diff --git a/.clang-format b/.clang-format index 609edd3da67..b43713fc922 100644 --- a/.clang-format +++ b/.clang-format @@ -33,6 +33,8 @@ BraceWrapping: # Keeps extern "C" blocks unindented. AfterExternBlock: false +InsertBraces: true + # Indent case labels. IndentCaseLabels: true diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 00000000000..9694e0f9a41 --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1 @@ +# Void parent level config to enable formatting. diff --git a/.github/workflows/sync_latest_angle.yml b/.github/workflows/sync_latest_angle.yml new file mode 100644 index 00000000000..6c50f310daf --- /dev/null +++ b/.github/workflows/sync_latest_angle.yml @@ -0,0 +1,23 @@ +name: Sync latest ANGLE +on: + workflow_dispatch: +jobs: + Sync_latest_ANGLE: + runs-on: macos-latest + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Configure Git user + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Sync latest ANGLE + run: | + git remote add upstream https://github.com/google/angle.git + git fetch upstream main + git merge upstream/main -m "Merge remote-tracking branch 'upstream/main' into metal-freeze" + git push diff --git a/.gitignore b/.gitignore index 329d6ca01d4..3139850f3ab 100644 --- a/.gitignore +++ b/.gitignore @@ -56,10 +56,9 @@ /third_party/gles1_conform /third_party/glmark2/src /third_party/glslang/src -/third_party/googletest +/third_party/googletest/src /third_party/ijar /third_party/jdk/current -/third_party/jdk/extras/java_8 /third_party/jinja2 /third_party/jsoncpp /third_party/kotlin_stdlib @@ -92,6 +91,7 @@ /third_party/r8/d8/cipd /third_party/r8/lib /third_party/rapidjson/src +/third_party/re2/src /third_party/requests/src /third_party/rust /third_party/rust-toolchain @@ -133,6 +133,7 @@ /tools/rust /tools/skia_goldctl /tools/valgrind +/tools/win angle.iml angle_debug.txt /build diff --git a/.gitmodules b/.gitmodules index 604a19565a9..8ad23f48237 100644 --- a/.gitmodules +++ b/.gitmodules @@ -53,7 +53,7 @@ [submodule "third_party/clspv/src"] path = third_party/clspv/src url = https://chromium.googlesource.com/external/github.com/google/clspv - gclient-condition = not build_with_chromium + gclient-condition = checkout_angle_cl_deps and not build_with_chromium [submodule "third_party/cpu_features/src"] path = third_party/cpu_features/src url = https://chromium.googlesource.com/external/github.com/google/cpu_features @@ -61,7 +61,7 @@ [submodule "third_party/dawn"] path = third_party/dawn url = https://dawn.googlesource.com/dawn - gclient-condition = not build_with_chromium + gclient-condition = checkout_angle_dawn_deps and not build_with_chromium [submodule "third_party/depot_tools"] path = third_party/depot_tools url = https://chromium.googlesource.com/chromium/tools/depot_tools @@ -81,9 +81,9 @@ [submodule "third_party/glmark2/src"] path = third_party/glmark2/src url = https://chromium.googlesource.com/external/github.com/glmark2/glmark2 -[submodule "third_party/googletest"] - path = third_party/googletest - url = https://chromium.googlesource.com/chromium/src/third_party/googletest +[submodule "third_party/googletest/src"] + path = third_party/googletest/src + url = https://chromium.googlesource.com/external/github.com/google/googletest gclient-condition = not build_with_chromium [submodule "third_party/ijar"] path = third_party/ijar @@ -104,7 +104,7 @@ [submodule "third_party/llvm/src"] path = third_party/llvm/src url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project - gclient-condition = not build_with_chromium + gclient-condition = checkout_angle_cl_deps and not build_with_chromium [submodule "third_party/jinja2"] path = third_party/jinja2 url = https://chromium.googlesource.com/chromium/src/third_party/jinja2 @@ -148,7 +148,7 @@ [submodule "third_party/OpenCL-CTS/src"] path = third_party/OpenCL-CTS/src url = https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenCL-CTS - gclient-condition = not build_with_chromium + gclient-condition = checkout_angle_cl_deps and not build_with_chromium [submodule "third_party/OpenCL-Docs/src"] path = third_party/OpenCL-Docs/src url = https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenCL-Docs @@ -156,7 +156,7 @@ [submodule "third_party/OpenCL-ICD-Loader/src"] path = third_party/OpenCL-ICD-Loader/src url = https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenCL-ICD-Loader - gclient-condition = not build_with_chromium + gclient-condition = checkout_angle_cl_deps and not build_with_chromium [submodule "third_party/OpenGL-Registry/src"] path = third_party/OpenGL-Registry/src url = https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenGL-Registry @@ -176,6 +176,10 @@ [submodule "third_party/rapidjson/src"] path = third_party/rapidjson/src url = https://chromium.googlesource.com/external/github.com/Tencent/rapidjson +[submodule "third_party/re2/src"] + path = third_party/re2/src + url = https://chromium.googlesource.com/external/github.com/google/re2 + gclient-condition = not build_with_chromium [submodule "third_party/requests/src"] path = third_party/requests/src url = https://chromium.googlesource.com/external/github.com/kennethreitz/requests @@ -291,3 +295,7 @@ path = tools/valgrind url = https://chromium.googlesource.com/chromium/src/tools/valgrind gclient-condition = not build_with_chromium +[submodule "tools/win"] + path = tools/win + url = https://chromium.googlesource.com/chromium/src/tools/win + gclient-condition = checkout_win and not build_with_chromium diff --git a/.gn b/.gn index a16b15b324d..cb77c2a94f6 100644 --- a/.gn +++ b/.gn @@ -37,21 +37,39 @@ exec_script_allowlist = angle_dotfile_settings.exec_script_allowlist + ] default_args = { - clang_use_chrome_plugins = false + clang_use_chrome_plugins = true build_angle_deqp_tests = true use_sysroot = true + # Turns on unsafe buffer warning suppressions during build. + clang_unsafe_buffers_paths = "//unsafe_buffers_paths.txt" + # Saves on importing extra dependencies and ANGLE doesn't use JS. enable_js_protobuf = false + # Needed only for std::atomic_ref for large Ts http://crbug.com/402171653 + use_llvm_libatomic = false + # Disable location tags in isolates. tests_have_location_tags = false # Use base level API level 29 support for AHardwareBuffer ANGLE tests. - android32_ndk_api_level = 29 - android64_ndk_api_level = 29 + android_ndk_api_level = 29 vma_vulkan_headers_dir = "//third_party/vulkan-headers/src" + + # Use Siso instead of Ninja. + use_siso = true + + # TODO(439777063): llvm and Dawn need to fix includes + use_clang_modules = false + + # Enable Rust usage + enable_rust = true + enable_rust_cxx = true + + # Angle must stay in C++20 for longer due to some downstream dependencies. + use_cxx23 = false } no_check_targets = [ "third_party/dawn/*" ] diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000000..fe31a04f581 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,20 @@ +# This file defines the Rust style for automatic reformatting. +# See also https://rust-lang.github.io/rustfmt +# +# ANGLE's rustfmt file mostly follows Chromium's, with the exception of line widths. + +# Rust language edition to be used by the parser. +edition = "2024" +# Version of the formatting rules to use. +style_edition = "2024" +# Line endings will be converted to \n. +newline_style = "Unix" +wrap_comments = true +comment_width = 100 +max_width = 100 +# The "Default" setting has a heuristic which splits lines too aggresively. +# We are willing to revisit this setting in future versions of rustfmt. +# Bugs: +# * https://github.com/rust-lang/rustfmt/issues/3119 +# * https://github.com/rust-lang/rustfmt/issues/3120 +use_small_heuristics = "Max" diff --git a/.vpython b/.vpython deleted file mode 100644 index d9dfb921bd9..00000000000 --- a/.vpython +++ /dev/null @@ -1,394 +0,0 @@ -# This is a vpython "spec" file. -# -# It describes patterns for python wheel dependencies of the python scripts in -# the chromium repo, particularly for dependencies that have compiled components -# (since pure-python dependencies can be easily vendored into third_party). -# -# When vpython is invoked, it finds this file and builds a python VirtualEnv, -# containing all of the dependencies described in this file, fetching them from -# CIPD (the "Chrome Infrastructure Package Deployer" service). Unlike `pip`, -# this never requires the end-user machine to have a working python extension -# compilation environment. All of these packages are built using: -# https://chromium.googlesource.com/infra/infra/+/main/infra/tools/dockerbuild/ -# -# All python scripts in the repo share this same spec, to avoid dependency -# fragmentation. -# -# If you have depot_tools installed in your $PATH, you can invoke python scripts -# in this repo by running them as you normally would run them, except -# substituting `vpython` instead of `python` on the command line, e.g.: -# vpython path/to/script.py some --arguments -# -# Read more about `vpython` and how to modify this file here: -# https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md -# -# For the definition of this spec, see: -# https://chromium.googlesource.com/infra/luci/luci-go/+/main/vpython/api/vpython/spec.proto - -python_version: "2.7" - -# Used by: -# build/chromeos/test_runner.py -wheel: < - name: "infra/python/wheels/jsonlines-py2_py3" - version: "version:1.2.0" -> -wheel: < - name: "infra/python/wheels/subprocess32/${vpython_platform}" - version: "version:3.5.0rc1" - # Only download for linux since we shouldn't be running CrOS tests on mac/win. - match_tag: < - abi: "cp27mu" - platform: "manylinux1_i686" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_x86_64" - > -> - -# Used by: -# build/chromeos/test_runner.py -# third_party/catapult -# -# This version must be compatible with the version range specified by -# //third_party/catapult/telemetry/telemetry/internal/util/external_modules.py -wheel: < - name: "infra/python/wheels/psutil/${vpython_platform}" - version: "version:5.2.2" -> - -# Used by: -# build/lacros/test_runner.py -wheel: < - name: "infra/python/wheels/parameterized-py2_py3" - version: "version:0.7.1" -> - -# Used by: -# third_party/catapult -# -# This version must be compatible with the version range specified by -# //third_party/catapult/telemetry/telemetry/internal/util/external_modules.py -# -# This version must also be compatible with the "numpy" version, as "cv2" -# depends on "numpy". In this case, OpenCV@2.4.13.2 has been built against -# numpy@1.11.3. -wheel: < - name: "infra/python/wheels/opencv_python/${vpython_platform}" - version: "version:2.4.13.2" - match_tag: < - platform: "win32" - > - match_tag: < - platform: "win_amd64" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_i686" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_x86_64" - > - match_tag: < - platform: "macosx_10_6_intel" - > -> - -# Used by: -# third_party/catapult -# -# This version must be compatible with the version range specified by -# //third_party/catapult/telemetry/telemetry/internal/util/external_modules.py -wheel: < - name: "infra/python/wheels/numpy/${vpython_platform}" - version: "version:1.11.3" -> - -# Used by: -# third_party/catapult -wheel: < - name: "infra/python/wheels/pypiwin32/${vpython_platform}" - version: "version:219" - match_tag: < - platform: "win32" - > - match_tag: < - platform: "win_amd64" - > -> - -# Used by: -# chrome/test/data/android/upload_download_utils_test.py -wheel: < - name: "infra/python/wheels/pyfakefs-py2_py3" - version: "version:3.7.2" -> - -# Used by: -# tools/perf/fetch_benchmark_deps.py -wheel: < - name: "infra/python/wheels/google_compute_engine-py2_py3" - version: "version:2.6.2" -> -wheel: < - name: "infra/python/wheels/boto-py2_py3" - version: "version:2.48.0" -> - -# Used by: -# testing/buildbot/generate_buildbot_json_coveragetest.py -wheel: < - name: "infra/python/wheels/coverage/${vpython_platform}" - version: "version:4.3.4" -> - -# Used by: -# build/android/pylib/local/emulator/avd.py -wheel: < - name: "infra/python/wheels/protobuf-py2_py3" - version: "version:3.6.1" -> -wheel: < - name: "infra/python/wheels/six-py2_py3" - version: "version:1.15.0" -> -wheel: < - name: "infra/python/wheels/pyftpdlib-py2_py3" - version: "version:0.7.0" -> -wheel: < - name: "infra/python/wheels/simplejson/${vpython_platform}" - version: "version:3.13.2" -> - -# Used by: -# tools/perf/core/results_dashboard.py -wheel: < - name: "infra/python/wheels/httplib2-py2_py3" - version: "version:0.10.3" -> - -# Used by: -# tools/perf/flakiness_cli -wheel: < - name: "infra/python/wheels/pandas/${vpython_platform}" - version: "version:0.23.4" - match_tag: < - platform: "win32" - > - match_tag: < - platform: "win_amd64" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_i686" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_x86_64" - > - match_tag: < - platform: "macosx_10_6_intel" - > -> -wheel: < - name: "infra/python/wheels/pytz-py2_py3" - version: "version:2018.4" -> -wheel: < - name: "infra/python/wheels/python-dateutil-py2_py3" - version: "version:2.7.3" -> - -# Used by: -# content/test/gpu/gpu_tests/color_profile_manager_mac.py -# Note: there's a version of this wheel for even older OS versions, -# but we don't need it for the GPU tests, and it looks like there are -# bugs in the not_match_tag implementation. -wheel: < - name: "infra/python/wheels/pyobjc/${vpython_platform}" - version: "version:4.1" - match_tag: < platform: "macosx_10_10_intel" > -> - -# Used by: -# third_party/catapult -wheel: < - name: "infra/python/wheels/six-py2_py3" - version: "version:1.15.0" -> -wheel: < - name: "infra/python/wheels/pbr-py2_py3" - version: "version:3.0.0" -> -wheel: < - name: "infra/python/wheels/funcsigs-py2_py3" - version: "version:1.0.2" -> -wheel: < - name: "infra/python/wheels/mock-py2_py3" - version: "version:2.0.0" -> - -# Used by: -# chrome/test/chromedriver/test/run_webdriver_tests.py - -wheel < - name: "infra/python/wheels/pytest-py2_py3" - version: "version:3.6.2" -> - -wheel < - name: "infra/python/wheels/attrs-py2_py3" - version: "version:17.4.0" -> - -wheel < - name: "infra/python/wheels/six-py2_py3" - version: "version:1.15.0" -> - -wheel < - name: "infra/python/wheels/more-itertools-py2_py3" - version: "version:4.1.0" -> - -wheel < - name: "infra/python/wheels/scandir/${vpython_platform}" - version: "version:1.7" -> - -wheel < - name: "infra/python/wheels/pluggy-py2_py3" - version: "version:0.7.1" -> - -wheel < - name: "infra/python/wheels/py-py2_py3" - version: "version:1.5.3" -> - -wheel < - name: "infra/python/wheels/funcsigs-py2_py3" - version: "version:1.0.2" -> -wheel: < - name: "infra/python/wheels/psutil/${vpython_platform}" - version: "version:5.2.2" -> - -# Used by: -# tools/infra -wheel: < - name: "infra/python/wheels/requests-py2_py3" - version: "version:2.13.0" -> -wheel: < - name: "infra/python/wheels/colorama-py2_py3" - version: "version:0.4.1" -> -wheel: < - name: "infra/python/wheels/mock-py2_py3" - version: "version:2.0.0" -> - -wheel: < - name: "infra/python/wheels/atomicwrites-py2_py3" - version: "version:1.3.0" -> - -wheel: < - name: "infra/python/wheels/pathlib2-py2_py3" - version: "version:2.3.3" -> - -# Used by Web Platform Tests (WPT) codebase in -# //third_party/blink/web_tests/external/wpt/tools/ -wheel: < - name: "infra/python/wheels/html5lib-py2_py3" - version: "version:1.0.1" -> -wheel: < - name: "infra/python/wheels/mozdebug-py2_py3" - version: "version:0.1.1" -> -wheel: < - name: "infra/python/wheels/mozinfo-py2_py3" - version: "version:1.1.0" -> -wheel: < - name: "infra/python/wheels/mozlog-py2_py3" - version: "version:5.0" -> -wheel: < - name: "infra/python/wheels/mozprocess-py2_py3" - version: "version:0.26" -> -wheel: < - name: "infra/python/wheels/urllib3-py2_py3" - version: "version:1.22" -> -wheel: < - name: "infra/python/wheels/blessings-py2_py3" - version: "version:1.7" -> -wheel: < - name: "infra/python/wheels/mozfile-py2_py3" - version: "version:2.0.0" -> -wheel: < - name: "infra/python/wheels/mozterm-py2_py3" - version: "version:1.0.0" -> -wheel: < - name: "infra/python/wheels/webencodings-py2_py3" - version: "version:0.5.1" -> -wheel: < - name: "infra/python/wheels/certifi-py2_py3" - version: "version:2018.11.29" -> -wheel: < - name: "infra/python/wheels/chardet-py2_py3" - version: "version:3.0.4" -> -wheel: < - name: "infra/python/wheels/idna-py2_py3" - version: "version:2.8" -> -wheel: < - name: "infra/python/wheels/pillow/${vpython_platform}" - version: "version:6.0.0" - match_tag: < - platform: "win32" - > - match_tag: < - platform: "win_amd64" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_i686" - > - match_tag: < - abi: "cp27mu" - platform: "manylinux1_x86_64" - > - match_tag: < - platform: "macosx_10_6_intel" - > -> - -# Used by: -# //third_party/blink/tools/blinkpy/web_tests/port/server_process.py -wheel: < - name: "infra/python/wheels/pywin32/${vpython_platform}" - version: "version:227" - match_tag: < - platform: "win32" - > - match_tag: < - platform: "win_amd64" - > -> diff --git a/.vpython3 b/.vpython3 index 7649355ce8c..bdb3aa2e950 100644 --- a/.vpython3 +++ b/.vpython3 @@ -22,7 +22,7 @@ # Read more about `vpython` and how to modify this file here: # https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md -python_version: "3.8" +python_version: "3.11" # Used by: # build/android/pylib/local/emulator/avd.py @@ -45,14 +45,14 @@ wheel: < # platform. wheel: < name: "infra/python/wheels/pytype/${vpython_platform}" - version: "version:2021.11.2" + version: "version:2024.9.13" match_tag: < platform: "manylinux1_x86_64" > > wheel: < name: "infra/python/wheels/importlab-py3" - version: "version:0.6.1" + version: "version:0.8.1" match_tag: < platform: "manylinux1_x86_64" > @@ -72,11 +72,8 @@ wheel: < > > wheel: < - name: "infra/python/wheels/libcst-py3" - version: "version:0.3.19" - match_tag: < - platform: "manylinux1_x86_64" - > + name: "infra/python/wheels/libcst/${vpython_platform}" + version: "version:1.1.0" > wheel: < name: "infra/python/wheels/pyyaml/${vpython_platform}" @@ -94,28 +91,18 @@ wheel: < > wheel: < name: "infra/python/wheels/typing-extensions-py3" - version: "version:4.0.1" - match_tag: < - platform: "manylinux1_x86_64" - > + version: "version:4.14.0" > wheel: < name: "infra/python/wheels/tabulate-py3" - version: "version:0.8.9" - match_tag: < - platform: "manylinux1_x86_64" - > -> -wheel: < - name: "infra/python/wheels/typed-ast/${vpython_platform}" - version: "version:1.5.3" + version: "version:0.9.0" match_tag: < platform: "manylinux1_x86_64" > > wheel: < name: "infra/python/wheels/ninja/${vpython_platform}" - version: "version:1.10.0.post2" + version: "version:1.10.2.4.chromium.1" match_tag: < platform: "manylinux1_x86_64" > @@ -123,9 +110,6 @@ wheel: < wheel: < name: "infra/python/wheels/mypy-extensions-py3" version: "version:0.4.3" - match_tag: < - platform: "manylinux1_x86_64" - > > # Common utilities. @@ -133,7 +117,7 @@ wheel: < # Chromium tests using Telemetry function properly. wheel: < name: "infra/python/wheels/numpy/${vpython_platform}" - version: "version:1.2x.supported.1" + version: "version:1.23.5.chromium.4" > wheel: < name: "infra/python/wheels/pexpect/${vpython_platform}" @@ -149,7 +133,7 @@ wheel: < > wheel: < name: "infra/python/wheels/pillow/${vpython_platform}" - version: "version:8.3.1" + version: "version:10.4.0" # There is currently no Linux arm/arm64 version in CIPD. not_match_tag < platform: "linux_aarch64" @@ -157,7 +141,7 @@ wheel: < > wheel: < name: "infra/python/wheels/opencv_python/${vpython_platform}" - version: "version:4.5.3.56.chromium.4" + version: "version:4.8.1.78.chromium.1" # There is currently no Linux arm/arm64 version in CIPD. not_match_tag < platform: "linux_aarch64" @@ -191,7 +175,7 @@ wheel: < > wheel: < name: "infra/python/wheels/python-dateutil-py2_py3" - version: "version:2.7.3" + version: "version:2.9.0" > # Used by WPT importer @@ -248,12 +232,12 @@ wheel: < # //third_party/blink/tools/wpt_upload.py wheel: < name: "infra/python/wheels/crcmod/${vpython_platform}" - version: "version:1.7.chromium.3" + version: "version:1.7.chromium.4" > wheel: < name: "infra/python/wheels/grpcio/${vpython_platform}" - version: "version:1.44.0" + version: "version:1.69.0" > wheel: < @@ -331,7 +315,7 @@ wheel: < > wheel: < name: "infra/python/wheels/aioquic/${vpython_platform}" - version: "version:0.9.15" + version: "version:1.2.0.chromium.1" > wheel: < name: "infra/python/wheels/pylsqpack/${vpython_platform}" @@ -339,11 +323,11 @@ wheel: < > wheel: < name: "infra/python/wheels/cryptography/${vpython_platform}" - version: "version:3.3.1.chromium.1" + version: "version:43.0.0" > wheel: < name: "infra/python/wheels/cffi/${vpython_platform}" - version: "version:1.14.5.chromium.7" + version: "version:1.15.1.chromium.2" > wheel: < name: "infra/python/wheels/pycparser-py2_py3" @@ -373,7 +357,7 @@ wheel: < wheel: < name: "infra/python/wheels/toml-py3" - version: "version:0.10.1" + version: "version:0.10.2" > wheel < @@ -430,14 +414,14 @@ wheel: < # testing/buildbot/generate_buildbot_json_coveragetest.py wheel: < name: "infra/python/wheels/coverage/${vpython_platform}" - version: "version:5.5.chromium.3" + version: "version:7.3.1" > # Used by: # //content/test/gpu wheel: < name: "infra/python/wheels/pathos/${vpython_platform}" - version: "version:0.2.7.chromium.5" + version: "version:0.3.0.chromium.2" not_match_tag < abi: "cp27mu" platform: "manylinux1_i686" @@ -465,14 +449,14 @@ wheel: < # //tools/infra/find_bad_builds.py wheel: < name: "infra/python/wheels/pytz-py2_py3" - version: "version:2018.4" + version: "version:2024.1" > # Used by: # //third_party/blink/tools/blinkpy/web_tests/port/server_process.py wheel: < name: "infra/python/wheels/pywin32/${vpython_platform}" - version: "version:300" + version: "version:308" match_tag: < platform: "win32" > @@ -485,7 +469,7 @@ wheel: < # //content/test/gpu/gpu_tests/color_profile_manager_mac.py wheel: < name: "infra/python/wheels/pyobjc/${vpython_platform}" - version: "version:7.3.chromium.1" + version: "version:10.0" match_tag: < platform: "macosx_10_10_intel" > @@ -505,7 +489,7 @@ wheel: < # tools/perf/flakiness_cli wheel: < name: "infra/python/wheels/pandas/${vpython_platform}" - version: "version:1.3.2.chromium.1" + version: "version:2.2.3.chromium.1" not_match_tag: < platform: "linux_aarch64" > @@ -528,3 +512,53 @@ wheel: < name: "infra/python/wheels/mako-py3" version: "version:1.2.3" > + +wheel: < + name: "infra/python/wheels/immutabledict-py3" + version: "version:4.1.0" +> + +wheel: < + name: "infra/python/wheels/jinja2-py3" + version: "version:3.1.2" +> + +wheel: < + name: "infra/python/wheels/msgspec/${vpython_platform}" + version: "version:0.18.6" +> + +wheel: < + name: "infra/python/wheels/pycnite-py3" + version: "version:2024.07.31" +> + +wheel: < + name: "infra/python/wheels/pydot-py2_py3" + version: "version:1.4.2" +> + +wheel: < + name: "infra/python/wheels/pyopenssl-py3" + version: "version:24.2.1" +> + +wheel: < + name: "infra/python/wheels/service-identity-py3" + version: "version:24.1.0" +> + +wheel: < + name: "infra/python/wheels/typing-inspect-py3" + version: "version:0.7.1" +> + +wheel: < + name: "infra/python/wheels/pyyaml/${vpython_platform}" + version: "version:5.4.1.chromium.1" +> + +wheel: < + name: "infra/python/wheels/tzdata-py2_py3" + version: "version:2023.4" +> diff --git a/AUTHORS b/AUTHORS index 37a9c07dff5..77a78af6d54 100644 --- a/AUTHORS +++ b/AUTHORS @@ -87,3 +87,5 @@ Tao Wang Phan Quang Minh Hongchen Yan Andrew Sumsion +Swapnadeep Som +Jérôme Lécuyer diff --git a/BUILD.gn b/BUILD.gn index 193801188af..b03776f9e5e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -36,7 +36,7 @@ declare_args() { angle_has_build # Enable using Vulkan to collect system info as a fallback. - angle_enable_vulkan_system_info = false + angle_enable_vulkan_system_info = is_chromeos # Link in system libGL, to work with apitrace. See doc/DebuggingTips.md. angle_link_glx = false @@ -125,8 +125,8 @@ if (angle_build_all) { } } -if (build_angle_end2end_tests_aosp) { - group("angle_end2end_tests_aosp") { +if (build_angle_end2end_tests_library) { + group("angle_end2end_tests_library") { testonly = true deps = [ "src/tests:angle_end2end_tests" ] } @@ -225,6 +225,11 @@ config("internal_config") { defines += [ "ANGLE_ENABLE_TRACE_EVENTS=1" ] } + # Enables platform trace events (PlatformMethods::addTraceEvent) e.g. AGI/perfetto on Android + if (angle_enable_platform_trace_events) { + defines += [ "ANGLE_ENABLE_PLATFORM_TRACE_EVENTS=1" ] + } + # Output `INFO`-level logs and up. if (angle_always_log_info) { defines += [ "ANGLE_ALWAYS_LOG_INFO" ] @@ -243,10 +248,6 @@ config("internal_config") { defines += [ "ANGLE_PLATFORM_CHROMEOS" ] } - if (is_ggp) { - defines += [ "__ggp__" ] - } - if (angle_use_vulkan_null_display) { defines += [ "ANGLE_USE_VULKAN_NULL_DISPLAY" ] } else if (angle_use_vulkan_display) { @@ -305,10 +306,14 @@ config("internal_config") { if (angle_enable_cl) { defines += [ "ANGLE_ENABLE_CL" ] } + + if (angle_trace_events_ignore_timestamp) { + defines += [ "ANGLE_TRACE_EVENTS_IGNORE_TIMESTAMP" ] + } } config("constructor_and_destructor_warnings") { - if (is_clang) { + if (is_clang && !angle_enable_global_mutex_load_time_allocate) { cflags = [ "-Wexit-time-destructors", "-Wglobal-constructors", @@ -316,6 +321,13 @@ config("constructor_and_destructor_warnings") { } } +config("no_thread_safety_warnings") { + if (is_clang) { + cflags_cc = [ "-Wno-thread-safety" ] + cflags_objcc = [ "-Wno-thread-safety" ] + } +} + config("extra_warnings") { cflags = [] @@ -410,6 +422,14 @@ config("angle_uwp_env") { } } +config("angle_translator_ir") { + defines = [ "ANGLE_IR=1" ] + include_dirs = [ + "$root_gen_dir/src", + "$root_gen_dir/third_party/angle/src", + ] +} + angle_source_set("cl_includes") { sources = cl_includes public_configs = [ ":external_config" ] @@ -574,12 +594,20 @@ angle_common_lib("angle_common_shader_state") { angle_source_set("angle_capture_common") { sources = [ + "src/common/frame_capture_binary_data.cpp", + "src/common/frame_capture_binary_data.h", "src/common/frame_capture_utils.cpp", "src/common/frame_capture_utils.h", "src/common/frame_capture_utils_autogen.cpp", "src/common/frame_capture_utils_autogen.h", ] - deps = [ ":angle_common" ] + + # Required for 32-bit platform large file I/O + defines = [ "_FILE_OFFSET_BITS=64" ] + deps = [ + ":angle_common", + ":angle_compression", + ] public_deps = [ ":angle_gl_enum_utils" ] } @@ -680,7 +708,7 @@ angle_static_library("angle_gpu_info_util") { if (angle_use_x11 && angle_has_build) { sources += libangle_gpu_info_util_x11_sources - deps += [ "src/third_party/libXNVCtrl:libXNVCtrl" ] + deps += [ "src/third_party/libXNVCtrl" ] defines += [ "GPU_INFO_USE_X11" ] libs += [ "X11", @@ -702,7 +730,6 @@ angle_static_library("angle_gpu_info_util") { if (is_apple) { frameworks = [ - "IOKit.framework", "CoreFoundation.framework", "CoreGraphics.framework", ] @@ -710,6 +737,7 @@ angle_static_library("angle_gpu_info_util") { frameworks += [ "OpenGL.framework" ] } if (is_mac || angle_enable_cgl) { + frameworks += [ "IOKit.framework" ] sources += libangle_gpu_info_util_mac_sources } if (is_ios && !angle_enable_cgl) { @@ -773,7 +801,7 @@ angle_static_library("translator") { defines += [ "ANGLE_ENABLE_VULKAN" ] } - if (angle_enable_metal) { + if (angle_enable_msl) { sources += angle_translator_lib_msl_sources defines += [ "ANGLE_ENABLE_METAL" ] } @@ -799,6 +827,12 @@ angle_static_library("translator") { "$angle_root/src/common/spirv:angle_spirv_headers", ] + if (angle_ir) { + deps += [ "$angle_root/src/compiler/translator/ir:translator_ir" ] + sources += angle_translator_lib_ir_sources + public_configs += [ ":angle_translator_ir" ] + } + if (_uses_spirv) { deps += [ "$angle_root/src/common/spirv:angle_spirv_base", @@ -868,35 +902,13 @@ action("angle_commit_id") { _commit_id_header = "$root_gen_dir/angle/angle_commit.h" script = "src/commit_id.py" outputs = [ _commit_id_header ] - + depfile = "${_commit_id_header}.d" visibility = [ ":angle_version" ] - # Add git as a dependency if it is available. - if (angle_enable_commit_id && - exec_script("src/commit_id.py", [ "check" ], "value") == 1) { - # commit id should depend on angle's HEAD revision - git_dirs = exec_script("src/commit_id.py", [ "get_git_dirs" ], "list lines") - inputs = [ git_dirs[0] + "/HEAD" ] - branch = read_file(git_dirs[0] + "/HEAD", "string") - result = string_split(branch) - if (result[0] == "ref:") { - _ref_file = result[1] - - # If git has packed the contents of .git/refs/heads/ in .git/packed-refs, - # unpack the head before depending on it. - exec_script("src/commit_id.py", - [ - "unpack", - _ref_file, - ], - "") - inputs += [ git_dirs[1] + "/" + _ref_file ] - } - } - args = [ "gen", rebase_path(_commit_id_header, root_build_dir), + rebase_path(depfile, root_build_dir), ] public_configs = [ ":angle_commit_id_config" ] @@ -1138,11 +1150,6 @@ angle_source_set("libANGLE_no_vulkan") { public_deps += [ "src/libANGLE/renderer/cl:angle_cl_backend" ] } - # Enable extra Chromium style warnings for libANGLE. - if (is_clang && angle_has_build && !is_nacl) { - suppressed_configs -= [ "//build/config/clang:find_bad_constructs" ] - } - if (is_apple) { sources += libangle_mac_sources } @@ -1154,6 +1161,9 @@ angle_source_set("libANGLE_no_vulkan") { if (is_debug) { defines += [ "ANGLE_GENERATE_SHADER_DEBUG_INFO" ] } + if (build_with_chromium) { + defines += [ "ANGLE_ALWAYS_REPORT_VALIDATION_ERRORS" ] + } configs += [ ":debug_annotations_config" ] public_configs += [ @@ -1174,6 +1184,7 @@ angle_source_set("angle_frame_capture_mock") { public_deps = [ ":libANGLE_headers" ] public_configs = [ ":angle_frame_capture_disabled" ] sources = [ + "src/common/frame_capture_binary_data.h", "src/common/frame_capture_utils.h", "src/common/frame_capture_utils_autogen.h", "src/common/gl_enum_utils_autogen.h", @@ -1408,7 +1419,8 @@ set_defaults("angle_libGLESv2") { template("angle_libGLESv2") { angle_shared_library(target_name) { - sources = invoker.sources + libglesv2_sources + sources = + invoker.sources + libglesv2_entry_point_sources + libglesv2_sources deps = invoker.deps + [ ":includes" ] defines = [ "LIBGLESV2_IMPLEMENTATION" ] @@ -1467,8 +1479,8 @@ if (angle_has_frame_capture) { } } -angle_static_library("libGLESv2_static") { - sources = libglesv2_sources +angle_static_library("libGLESv2_thin_static") { + sources = libglesv2_entry_point_sources if (angle_enable_cl) { sources += libglesv2_cl_sources } @@ -1479,6 +1491,11 @@ angle_static_library("libGLESv2_static") { public_deps = [ ":libANGLE" ] } +angle_static_library("libGLESv2_static") { + sources = libglesv2_sources + public_deps = [ ":libGLESv2_thin_static" ] +} + angle_shared_library("libGLESv1_CM") { sources = libglesv1_cm_sources output_name = "libGLESv1_CM${angle_libs_suffix}" @@ -1618,7 +1635,8 @@ angle_executable("angle_shader_translator") { } } -if (angle_standalone || build_with_chromium || build_angle_end2end_tests_aosp) { +if (angle_standalone || build_with_chromium || + build_angle_end2end_tests_library) { config("angle_feature_support_config") { include_dirs = [ "include", @@ -1735,10 +1753,14 @@ if (is_android && symbol_level != 0 && if ((angle_standalone || build_with_chromium) && is_android && current_toolchain == default_toolchain) { - apk_version_code = "0" - if (angle_enable_commit_id) { + if (build_with_chromium) { + import("//chrome/version.gni") + apk_version_code = chrome_version_code + } else if (angle_enable_commit_id) { apk_version_code = exec_script("src/commit_id.py", [ "position" ], "trim string") + } else { + apk_version_code = "0" } # Package ANGLE libraries for normal use on Android diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 95f1f6d4440..8e369f2c253 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -67,6 +67,7 @@ Apple Inc. Dean Jackson Kimmo Kinnunen Kyle Piddington + Roberto Rodriguez Autodesk, Inc. Ranger Harke @@ -125,6 +126,7 @@ Andrei Volykhin Jérôme Duval Till Rathmann Nick Shaforostov +Jérôme Lécuyer Microsoft Corporation Cooper Partin @@ -176,6 +178,7 @@ Samsung Electronics, Inc. Colin Peter Hyunchang Kim Hyunseok Ko + Hyunwoo Yu Igor Nazarov Jaedon Lee Jaewoo Kim @@ -208,6 +211,7 @@ Arm Ltd. Min Zhang Yuxiang Qian Shufen Ma + Xin Yuan Broadcom Inc. Gary Sweet diff --git a/DEPS b/DEPS index cc62f8047b1..60a6acf31d6 100644 --- a/DEPS +++ b/DEPS @@ -10,6 +10,8 @@ gclient_gn_args_file = 'build/config/gclient_args.gni' git_dependencies = "SYNC" gclient_gn_args = [ + 'checkout_angle_cl_deps', + 'checkout_angle_dawn_deps', 'checkout_angle_internal', 'checkout_angle_mesa', 'checkout_angle_restricted_traces', @@ -43,28 +45,16 @@ vars = { 'checkout_angle_mesa': False, # Version of Chromium our Chromium-based DEPS are mirrored from. - 'chromium_revision': '7a15ef98fa4643deb8be67b0d2d5594b19290ec2', + 'chromium_revision': 'e3a1e6f3ee5b4b9ec7f733b0f80e5e49cec1b812', # 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': '69ec1790cb7c1b72a758a3562aa4e511caaef780', + 'vk_gl_cts_revision': '9ef5ffd652cb39797f17321899d3d100bcf4ce08', # Current revision of googletest. - # Note: this dep cannot be auto-rolled b/c of nesting. - 'googletest_revision': '2d924d7a971e9667d76ad09727fb2402b4f8a1e3', - - # Current revision of Chrome's third_party googletest directory. This - # repository is mirrored as a separate repository, with separate git hashes - # that don't match the external googletest repository or Chrome. Mirrored - # patches will have a different git hash associated with them. - # To roll, first get the new hash for chromium_googletest_revision from the - # mirror of third_party/googletest located here: - # https://chromium.googlesource.com/chromium/src/third_party/googletest/ - # Then get the new hash for googletest_revision from the root Chrome DEPS - # file: https://source.chromium.org/chromium/chromium/src/+/main:DEPS - 'chromium_googletest_revision': '17bbed2084d3127bd7bcd27283f18d7a5861bea8', + 'googletest_revision': '4fe3307fb2d9f86d19777c7eb0e4809e9694dde7', # Current revision of jsoncpp. # Note: this dep cannot be auto-rolled b/c of nesting. @@ -88,21 +78,21 @@ 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': 'd5166861902b565df446e15181eba270fe168275', + 'catapult_revision': '145e14f52facfa0b5a34cca92b22dade15943a0c', # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:27.20250130.7.1', + 'fuchsia_version': 'version:30.20251218.4.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:b408832fea9036895f2767817491be5463ee6b22', + 'luci_go': 'git_revision:808a00437f24bb404c09608ad8bf3847a78de369', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. - 'android_sdk_build-tools_version': 'DxwAZ3hD551Neu6ycuW5CPnXFrdleRBd93oX1eB_m9YC', + 'android_sdk_build-tools_version': '-jLl4Ibk_WmgTsZaP-ueQwZDhBwkWf5BsQ4UNrkzXF0C', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_emulator_version # and whatever else without interference from each other. @@ -110,11 +100,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_platform-tools_version # and whatever else without interference from each other. - 'android_sdk_platform-tools_version': 'WihaseZR6cojZbkzIqwGhpTp92ztaGfqq8njBU8eTXYC', + 'android_sdk_platform-tools_version': 'qTD9QdBlBf3dyHsN1lJ0RH6AhHxR42Hmg2Ih-Vj4zIEC', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_platforms_version # and whatever else without interference from each other. - 'android_sdk_platforms_version': 'kIXA-9XuCfOESodXEdOBkW5f1ytrGWdbp3HFp1I8A_0C', + 'android_sdk_platforms_version': 'gxwLT70eR_ObwZJzKK8UIS-N549yAocNTmc0JHgO7gUC', # ninja CIPD package version. # https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja @@ -130,10 +120,10 @@ vars = { # reclient CIPD package 'reclient_package': 'infra/rbe/client/', # reclient CIPD package version - 'reclient_version': 're_client_version:0.175.0.98046de5-gomaip', + 'reclient_version': 're_client_version:0.185.0.db415f21-gomaip', # siso CIPD package version. - 'siso_version': 'git_revision:0b6159c39573013a79a47f8544200df07a6a74fc', + 'siso_version': 'git_revision:f78a1a934cf426488147ca8a4a17c29a010af8d5', # 'magic' text to tell depot_tools that git submodules should be accepted but # but parity with DEPS file is expected. @@ -147,7 +137,7 @@ vars = { # Make Dawn skip its standalone dependencies 'dawn_standalone': False, - 'dawn_revision': '1eca38fa52364bf66c0d288a0537a2813d72b39b', + 'dawn_revision': 'c1308bb3f17e9637f82be72f7ed0a75f3427dda4', # All of the restricted traces (large). 'checkout_angle_restricted_traces': 'checkout_angle_internal', @@ -158,6 +148,7 @@ vars = { 'checkout_angle_restricted_trace_20_minutes_till_dawn': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_2_3_4_player_mini_games': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_3d_pool_ball': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_ace_racer': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_afk_arena': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_age_of_origins_z': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_agent_a': 'checkout_angle_restricted_traces', @@ -169,12 +160,15 @@ vars = { 'checkout_angle_restricted_trace_animal_crossing': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_antistress': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_antutu_refinery': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_apex_girl': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_archero_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_arena_of_valor': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_arknights': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_asphalt_8': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_asphalt_9': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_asphalt_9_2024': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_avakin_life': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_avatar_world': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_aztec_ruins': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_aztec_ruins_high': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_badland': 'checkout_angle_restricted_traces', @@ -184,18 +178,25 @@ vars = { 'checkout_angle_restricted_trace_battle_of_polytopia': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_beach_buggy_racing': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_billiards_city': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_bingo_blitz': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_black_beacon': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_black_clover_m': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_black_desert_mobile': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_blade_and_soul_revolution': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_block_blast': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_block_craft_3d': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_blockman_go': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_blood_strike': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_botworld_adventure': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_brain_test_tricky_puzzles': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_brawl_stars': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_brawlhalla': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_bricks_breaker_quest': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_bridge_constructor_portal': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_brotato': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_bubble_shooter': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_bubble_shooter_and_friends': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_bubble_shooter_relaxing': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_bullet_echo': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_bus_simulator_indonesia': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_call_break_offline_card_game': 'checkout_angle_restricted_traces', @@ -205,26 +206,36 @@ vars = { 'checkout_angle_restricted_trace_car_chase': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_car_parking_multiplayer': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_car_race_3d': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_carrom_pool_disc_game': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_cash_frenzy_casino_slots': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_cashman_casino': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_castlevania_sotn': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_cat_runner': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_catalyst_black': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_chrono_trigger': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_clash_of_clans': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_clash_royale': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_cod_mobile': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_coin_master': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_color_block_combo_blast': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_command_and_conquer_rivals': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_cookie_run_kingdom': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_cookie_run_oven_break': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_critical_ops': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_csr2_drag_racing': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_cut_the_rope': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_dark_war_survival': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_darkness_rises': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_dc_dark_legion': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_dead_by_daylight': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_dead_cells': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_dead_trigger_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_diablo_immortal': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_dice_dreams': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_disney_mirrorverse': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_disney_solitaire': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_disney_tsum_tsum': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_domino_dreams': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_dont_starve': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_dota_underlords': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_downwell': 'checkout_angle_restricted_traces', @@ -245,6 +256,7 @@ vars = { 'checkout_angle_restricted_trace_fallout_shelter_online': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_family_island': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_farm_heroes_saga': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_fashion_show': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_fate_grand_order': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_fifa_mobile': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_final_fantasy': 'checkout_angle_restricted_traces', @@ -252,8 +264,10 @@ vars = { 'checkout_angle_restricted_trace_fire_emblem_heroes': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_fishdom': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_five_nights_at_freddys': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_football_league_2025': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_free_fire': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_free_fire_max': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_frost_and_flame': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_gacha_club': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_gacha_life': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_gangstar_vegas': 'checkout_angle_restricted_traces', @@ -263,38 +277,57 @@ vars = { 'checkout_angle_restricted_trace_goddess_of_victory_nikke': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_going_balls': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_google_maps': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_gossip_harbor': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_grand_mountain_adventure': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_grimvalor': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_gwent_witcher_card_game': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_happy_color': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_harry_potter_hogwarts_mystery': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_harry_potter_magic_awakened': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_hay_day': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_hearthstone': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_hero_wars': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_higgs_domino_island': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_hill_climb_racing': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_hole_io': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_homescapes': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_honkai_impact_3rd': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_honkai_star_rail': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_hungry_shark_evolution': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_hunter_assassin': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_i9_inferno_nine': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_identity_v': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_idle_heroes': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_indian_bikes_driving_3d': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_infinity_ops': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_injustice_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_into_the_dead_2': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_jackpot_party': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_jackpot_world': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_jetpack_joyride': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_junes_journey': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_kartrider_rush': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_kentucky_route_zero': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_kingshot': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_klondike_adventures': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_knives_out': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_lands_of_jail': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_last_shelter_survival': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_last_war_survival_game': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_last_z_survival_shooter': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_league_of_legends_wild_rift': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_lego_legacy': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_life_is_strange': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_lightning_link': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_lilys_garden': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_limbo': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_lineage_2m': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_lineage_m': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_loop_hero': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_lords_mobile': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_lost_light': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_lotsa_slots': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_love_and_deepspace': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_ludo_king': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_lumino_city': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_magic_rush_heroes': 'checkout_angle_restricted_traces', @@ -305,13 +338,20 @@ vars = { 'checkout_angle_restricted_trace_marvel_contest_of_champions': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_marvel_snap': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_marvel_strike_force': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_match_factory': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_match_masters': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_matching_story': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_merge_dragons': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_merge_mansion': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_messenger_lite': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_minecraft': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_minecraft_bedrock': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_minecraft_vibrant_visuals': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_minetest': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_mini_block_craft': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_mini_games_calm_and_relax': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_mini_world': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_mob_control': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_mobile_legends': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_modern_combat_5': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_monopoly_go': 'checkout_angle_restricted_traces', @@ -321,6 +361,9 @@ vars = { 'checkout_angle_restricted_trace_mortal_kombat': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_mu_origin_3': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_my_friend_pedro': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_my_talking_angela': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_my_talking_angela_2': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_my_talking_tom': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_my_talking_tom2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_my_talking_tom_friends': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_nba2k20_800': 'checkout_angle_restricted_traces', @@ -329,10 +372,14 @@ vars = { 'checkout_angle_restricted_trace_ni_no_kuni': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_nier_reincarnation': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_octopath_traveler': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_odin_valhalla_rising': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_off_the_road': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_offline_games': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_one_piece_treasure_cruise': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_one_punch_man': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_onmyoji': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_oxenfree': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_paper_io2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_passmark_complex': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_passmark_simple': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_passmark_unity': 'checkout_angle_restricted_traces', @@ -342,6 +389,7 @@ vars = { 'checkout_angle_restricted_trace_plants_vs_zombies_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_plants_vs_zombies_heroes': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_pokemon_go': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_pokemon_go_combat': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_pokemon_masters_ex': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_pokemon_unite': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_poppy_playtime': 'checkout_angle_restricted_traces', @@ -351,9 +399,13 @@ vars = { 'checkout_angle_restricted_trace_pubg_mobile_launch': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_pubg_mobile_lite': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_pubg_mobile_skydive': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_puzzle_and_dragons': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_puzzles_and_survival': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_qblock_wood_block_puzzle_game': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_race_master_3d': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_ragnarok_m_eternal_love': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_raid_shadow_legends': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_raising_a_goblin': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_real_commando_secret_mission': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_real_cricket_20': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_real_gangster_crime': 'checkout_angle_restricted_traces', @@ -366,12 +418,15 @@ vars = { 'checkout_angle_restricted_trace_rise_of_kingdoms': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_romancing_saga': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_rope_hero_vice_town': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_royal_kingdom': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_royal_match': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_rush_royale': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_saint_seiya_awakening': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_sakura_school_simulator': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_scary_teacher_3d': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_school_party_craft': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_scrabble_go': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_seaside_escape': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_shadow_fight_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_shadow_fight_3': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_shadowgun_legends': 'checkout_angle_restricted_traces', @@ -382,11 +437,16 @@ vars = { 'checkout_angle_restricted_trace_slay_the_spire': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_slingshot_test1': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_slingshot_test2': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_slotomania': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_snake_io': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_snake_lite': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_sniper_3d': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_soccer_superstar': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_solar_smash': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_sonic_forces': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_sonic_the_hedgehog': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_special_forces_group_2': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_spider_fighter_3': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_standoff_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_star_trek_fleet_command': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_star_wars_galaxy_of_heroes': 'checkout_angle_restricted_traces', @@ -400,10 +460,12 @@ vars = { 'checkout_angle_restricted_trace_subway_princess_runner': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_subway_surfers': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_summoners_war': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_super_bear_adventure': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_super_mario_run': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_supertuxkart': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_supreme_duelist': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_survivor_io': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_talking_tom_gold_run': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_talking_tom_hero_dash': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_temple_run_2': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_temple_run_300': 'checkout_angle_restricted_traces', @@ -415,22 +477,30 @@ vars = { 'checkout_angle_restricted_trace_the_witcher_monster_slayer': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_thief_puzzle': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_thimbleweed_park': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_tile_club': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_tmnt_shredders_revenge': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_toca_life_world': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_toon_blast': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_top_heroes_kingdom_saga': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_top_war': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_total_battle': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_tower_of_fantasy': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_township': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_traffic_rider': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_travel_town': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_trex_200': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_two_player_games': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_uber': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_umamusume_pretty_derby': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_vainglory': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_vita_mahjong': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_walking_dead_survivors': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_war_planet_online': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_warcraft_rumble': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_warhammer_40000_freeblade': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_wayward_souls': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_whatsapp': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_whiteout_survival': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_woodoku': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_words_crush': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_words_of_wonders': 'checkout_angle_restricted_traces', @@ -441,28 +511,36 @@ vars = { 'checkout_angle_restricted_trace_world_of_tanks_blitz': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_world_war_doh': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_worms_zone_io': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_wuthering_waves': 'checkout_angle_restricted_traces', + 'checkout_angle_restricted_trace_yalla_ludo': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_zenonia_4': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_zillow': 'checkout_angle_restricted_traces', 'checkout_angle_restricted_trace_zombie_smasher': 'checkout_angle_restricted_traces', # === ANGLE Restricted Trace Generated Var End === 'checkout_angle_perfetto': 'checkout_angle_restricted_traces', + + # Check out OpenCL related deps conditionally. This can be overridden with custom_vars. + 'checkout_angle_cl_deps': True, + + # Check out dawn related deps conditionally. This can be overridden with custom_vars. + 'checkout_angle_dawn_deps': True, } deps = { 'build': { - 'url': Var('chromium_git') + '/chromium/src/build.git@dc7b3561cdb982e8961e0f9930bb0bd532722625', + 'url': Var('chromium_git') + '/chromium/src/build.git@5ef0c4e7818b1c50ec4673d1981338ef14135dfa', 'condition': 'not build_with_chromium', }, 'buildtools': { - 'url': Var('chromium_git') + '/chromium/src/buildtools.git@6377d6649b0a2160ab8bb0b88d3cc64e3fd897cf', + 'url': Var('chromium_git') + '/chromium/src/buildtools.git@6a18683f555b4ac8b05ac8395c29c84483ac9588', 'condition': 'not build_with_chromium', }, 'third_party/clang-format/script': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/clang/tools/clang-format.git@37f6e68a107df43b7d7e044fd36a13cbae3413f2', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/clang/tools/clang-format.git@c2725e0622e1a86d55f14514f2177a39efea4a0e', 'condition': 'not build_with_chromium', }, @@ -470,22 +548,22 @@ deps = { 'packages': [ { 'package': 'gn/gn/linux-${{arch}}', - 'version': 'git_revision:ed1abc107815210dc66ec439542bee2f6cbabc00', + 'version': 'git_revision:103f8b437f5e791e0aef9d5c372521a5d675fabb', } ], 'dep_type': 'cipd', - 'condition': 'not build_with_chromium and host_os == "linux"', + 'condition': 'not build_with_chromium and checkout_linux', }, 'buildtools/mac': { 'packages': [ { 'package': 'gn/gn/mac-${{arch}}', - 'version': 'git_revision:ed1abc107815210dc66ec439542bee2f6cbabc00', + 'version': 'git_revision:103f8b437f5e791e0aef9d5c372521a5d675fabb', } ], 'dep_type': 'cipd', - 'condition': 'not build_with_chromium and host_os == "mac"', + 'condition': 'not build_with_chromium and checkout_mac', }, 'buildtools/reclient': { @@ -503,25 +581,25 @@ deps = { 'packages': [ { 'package': 'gn/gn/windows-amd64', - 'version': 'git_revision:ed1abc107815210dc66ec439542bee2f6cbabc00', + 'version': 'git_revision:103f8b437f5e791e0aef9d5c372521a5d675fabb', } ], 'dep_type': 'cipd', - 'condition': 'not build_with_chromium and host_os == "win"', + 'condition': 'not build_with_chromium and checkout_win', }, 'testing': { - 'url': '{chromium_git}/chromium/src/testing@8a57c900f440d8296314771517e8a02f26b93e17', + 'url': '{chromium_git}/chromium/src/testing@5c4e0257bbfadfdb0bb2d09d0f4a7e866aad1e2d', 'condition': 'not build_with_chromium', }, 'third_party/abseil-cpp': { - 'url': Var('chromium_git') + '/chromium/src/third_party/abseil-cpp@9d07d51c6ee92333a9f86acef20acadf9f5d9a89', + 'url': Var('chromium_git') + '/chromium/src/third_party/abseil-cpp@6d5ac0f7d3f0af5d13b78044fc31c793aa3549f8', 'condition': 'not build_with_chromium', }, 'third_party/android_build_tools': { - 'url': Var('chromium_git') + '/chromium/src/third_party/android_build_tools@3539c64cce01b0bad61eb21757d3f9822a242eef', + 'url': Var('chromium_git') + '/chromium/src/third_party/android_build_tools@6806b5008448cdb1d9f10d5fc9737774dfc65867', 'condition': 'checkout_android and not build_with_chromium', }, @@ -529,7 +607,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/aapt2', - 'version': '_lNsOL_GGlXLOIMGtrbMOqNd7TQHabaP1q8SlvUpFbMC', + 'version': 's6POXpUalcnuPehDsORiojCpgbNXT4LYq7DVUYgsfxEC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -562,7 +640,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/error_prone', - 'version': 'PW_AkPGAdnmLPk-dG161a_wYd9FRhQ9INn9f8HKj3fcC', + 'version': 'jum1S30anLAjV7GCe6k2X00_DFwQYvR-YF2iOvXN4GwC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -584,7 +662,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': 'jsEEMs5gHWH0oWH-A-WwE4Q4a5JnfgwwHYdaNd9UP9oC', + 'version': 'Ow8jpaRkHsJyhElyBOWWKBWl0KKNNuqbAE-cYWSPwQAC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -595,7 +673,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'no0RMx3qPOc-XlBlr8d_hUdnAYnHUeN6-qd2kXZO9e0C', + 'version': 'ITWXausfSUWr6lXywWULrkJidKFVjgOEGgVwcGV61LgC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -606,7 +684,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/nullaway', - 'version': '65WJkoinJEXvtu9xwdDNDb3QCbqBAl8FKDpgnXr3iiEC', + 'version': 'O_Zf07-x9h-o0nBYfdu032C5xXGXwCAD1lwZG1ZS9QEC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -614,7 +692,7 @@ deps = { }, 'third_party/android_deps': { - 'url': Var('chromium_git') + '/chromium/src/third_party/android_deps@e531e9499137b325a289bbd67b0e5c66d9ce3b5b', + 'url': Var('chromium_git') + '/chromium/src/third_party/android_deps@c2ef7a5a6647277a9c53c4b9e0c8403fe059723b', 'condition': 'checkout_android and not build_with_chromium', }, @@ -622,7 +700,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_toolchain/android_toolchain', - 'version': 'Idl-vYnWGnM8K3XJhM3h6zjYVDXlnljVz3FE00V9IM8C', + 'version': 'KXOia11cm9lVdUdPlbGLu8sCz6Y4ey_HV2s8_8qeqhgC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -630,19 +708,19 @@ deps = { }, 'third_party/android_platform': { - 'url': Var('chromium_git') + '/chromium/src/third_party/android_platform@e96dafd97e013cc44ee83d9d3d5d322a1356c6ca', + 'url': Var('chromium_git') + '/chromium/src/third_party/android_platform@e3919359f2387399042d31401817db4a02d756ec', 'condition': 'checkout_android and not build_with_chromium', }, 'third_party/android_sdk': { - 'url': Var('chromium_git') + '/chromium/src/third_party/android_sdk@16e8416791134998bf4e060ce9cbe7f94b66d432', + 'url': Var('chromium_git') + '/chromium/src/third_party/android_sdk@3af3898c67301201301f834693ff44326174ecea', 'condition': 'checkout_android and not build_with_chromium', }, 'third_party/android_sdk/public': { 'packages': [ { - 'package': 'chromium/third_party/android_sdk/public/build-tools/35.0.0', + 'package': 'chromium/third_party/android_sdk/public/build-tools/36.1.0', 'version': Var('android_sdk_build-tools_version'), }, { @@ -654,12 +732,12 @@ deps = { 'version': Var('android_sdk_platform-tools_version'), }, { - 'package': 'chromium/third_party/android_sdk/public/platforms/android-35', + 'package': 'chromium/third_party/android_sdk/public/platforms/android-36.1', 'version': Var('android_sdk_platforms_version'), }, { - 'package': 'chromium/third_party/android_sdk/public/cmdline-tools', - 'version': 'OCGHZKTdjXjIELVI6FMAgcDkfnd_1ybB0_MtljPtz-8C', + 'package': 'chromium/third_party/android_sdk/public/cmdline-tools/linux', + 'version': 'LZa8CWNVWS6UUQgQ7IJdFCqRV1Bmx2-alTNqEDJpJkcC', }, ], 'condition': 'checkout_android_native_support and not build_with_chromium', @@ -670,7 +748,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_system_sdk/public', - 'version': 'XzzECzCzGLrccJS1U-HdmM5VMh9BotgQ_mWhFQ464PwC', + 'version': 'EpgkrtsLblLuw0BrsWCF0h_njBzIZsBNDxQ5VtA4s2UC', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', @@ -678,7 +756,7 @@ deps = { }, 'third_party/astc-encoder/src': { - 'url': Var('chromium_git') + '/external/github.com/ARM-software/astc-encoder@573c475389bf51d16a5c3fc8348092e094e50e8f', + 'url': Var('chromium_git') + '/external/github.com/ARM-software/astc-encoder@2319d9c4d4af53a7fc7c52985e264ce6e8a02a9b', 'condition': 'not build_with_chromium', }, @@ -710,8 +788,8 @@ deps = { }, 'third_party/clspv/src': { - 'url': Var('chromium_git') + '/external/github.com/google/clspv@a173c052455434a422bcfe5c12ffe44d574fd6e1', - 'condition': 'not build_with_chromium', + 'url': Var('chromium_git') + '/external/github.com/google/clspv@8f35aa835ae973e1c802421ba5a873f5e967278c', + 'condition': 'checkout_angle_cl_deps and not build_with_chromium', }, 'third_party/cpu_features/src': { @@ -722,11 +800,11 @@ deps = { 'third_party/dawn': { 'url': Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'), - 'condition': 'not build_with_chromium' + 'condition': 'checkout_angle_dawn_deps and not build_with_chromium' }, 'third_party/depot_tools': { - 'url': Var('chromium_git') + '/chromium/tools/depot_tools.git@0cc30c3bafbabf75bc9c79bff5457741e742beb1', + 'url': Var('chromium_git') + '/chromium/tools/depot_tools.git@ec7d8f539cb439ce9ca7750ff0d8942e68325090', 'condition': 'not build_with_chromium', }, @@ -743,7 +821,7 @@ deps = { }, 'third_party/flatbuffers/src': { - 'url': Var('chromium_git') + '/external/github.com/google/flatbuffers.git@8db59321d9f02cdffa30126654059c7d02f70c32', + 'url': Var('chromium_git') + '/external/github.com/google/flatbuffers.git@a86afae9399bbe631d1ea0783f8816e780e236cc', 'condition': 'checkout_android and not build_with_chromium', }, @@ -766,16 +844,16 @@ deps = { # glmark2 is a GPL3-licensed OpenGL ES 2.0 benchmark. We use it for testing. 'third_party/glmark2/src': { - 'url': Var('chromium_git') + '/external/github.com/glmark2/glmark2@cb550a25c75a99ae0def91a02e16ae29d73e6d1e', + 'url': Var('chromium_git') + '/external/github.com/glmark2/glmark2@6edcf02205fd1e8979dc3f3964257a81959b80c8', }, - 'third_party/googletest': { - 'url': Var('chromium_git') + '/chromium/src/third_party/googletest' + '@' + Var('chromium_googletest_revision'), + 'third_party/googletest/src': { + 'url': Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + Var('googletest_revision'), 'condition': 'not build_with_chromium', }, 'third_party/ijar': { - 'url': Var('chromium_git') + '/chromium/src/third_party/ijar@4b6f53ee6268ff3b8ffe0279e334aa5110249b65', + 'url': Var('chromium_git') + '/chromium/src/third_party/ijar@94af60a05b33f9acb33477a8d969e48eb1c3029f', 'condition': 'checkout_android and not build_with_chromium', }, @@ -791,50 +869,39 @@ deps = { }, 'third_party/libdrm/src': { - 'url': Var('chromium_git') + '/chromiumos/third_party/libdrm.git@ad78bb591d02162d3b90890aa4d0a238b2a37cde', + 'url': Var('chromium_git') + '/chromiumos/third_party/libdrm.git@369990d9660a387f618d0eedc341eb285016243b', 'condition': 'checkout_angle_mesa or not build_with_chromium', }, # libjpeg_turbo is used by glmark2. 'third_party/libjpeg_turbo': { - 'url': Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git@927aabfcd26897abb9776ecf2a6c38ea5bb52ab6', + 'url': Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git@6bb85251a8382b5e07f635a981ac685cc5ab5053', 'condition': 'not build_with_chromium', }, 'third_party/libpng/src': { - 'url': Var('android_git') + '/platform/external/libpng@d2ece84bd73af1cd5fae5e7574f79b40e5de4fba', + 'url': Var('android_git') + '/platform/external/libpng@8cc222cd3e79fa5190f3aa039a03a4cbea6cfbe7', 'condition': 'not build_with_chromium', }, 'third_party/llvm/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project@d222fa4521531cc4ac14b8e157d231c108c003be', - 'condition': 'not build_with_chromium', - }, - - 'third_party/jdk': { - 'packages': [ - { - 'package': 'chromium/third_party/jdk', - 'version': 'tUJrCBvDNDE9jFvgkuOwX8tU6oCWT8CtI2_JxpGlTJIC', - }, - ], - 'condition': 'checkout_android and not build_with_chromium', - 'dep_type': 'cipd', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project@67790d3fb06b184b7be9c4d3e36ab01f0ac4198e', + 'condition': 'checkout_angle_cl_deps and not build_with_chromium', }, - 'third_party/jdk/extras': { + 'third_party/jdk/current': { 'packages': [ { - 'package': 'chromium/third_party/jdk/extras', - 'version': '-7m_pvgICYN60yQI3qmTj_8iKjtnT4NXicT0G_jJPqsC', + 'package': 'chromium/third_party/jdk/linux-amd64', + 'version': '2iiuF-nKDH3moTImx2op4WTRetbfhzKoZhH7Xo44zGsC', }, ], - 'condition': 'checkout_android and not build_with_chromium', + 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, 'third_party/jinja2': { - 'url': Var('chromium_git') + '/chromium/src/third_party/jinja2@5e1ee241ab04b38889f8d517f2da8b3df7cfbd9a', + 'url': Var('chromium_git') + '/chromium/src/third_party/jinja2@c3027d884967773057bf74b957e3fea87e5df4d7', 'condition': 'not build_with_chromium', }, @@ -844,27 +911,27 @@ deps = { }, 'third_party/libc++/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxx.git@2e25154d49c29fa9aa42c30ad4a027bd30123434', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxx.git@7ab65651aed6802d2599dcb7a73b1f82d5179d05', 'condition': 'not build_with_chromium', }, 'third_party/libc++abi/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxxabi.git@634228a732a1d9ae1a6d459556e8fc58707cf961', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxxabi.git@8f11bb1d4438d0239d0dfc1bd9456a9f31629dda', 'condition': 'not build_with_chromium', }, 'third_party/llvm-libc/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libc.git@6d0c8ee02e2fd44e69ac30e721e13be463035ee5', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libc.git@2a32a53cd558b813f154f6e2d290920556e7c9bc', 'condition': 'not build_with_chromium', }, 'third_party/libunwind/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libunwind.git@e55d8cf51c6db1fdd4bb56c158945ec59772c8ee', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libunwind.git@ba19d93d6d4f467fba11ff20fe2fc7c056f79345', 'condition': 'not build_with_chromium', }, 'third_party/markupsafe': { - 'url': Var('chromium_git') + '/chromium/src/third_party/markupsafe@9f8efc8637f847ab1ba984212598e6fb9cf1b3d4', + 'url': Var('chromium_git') + '/chromium/src/third_party/markupsafe@4256084ae14175d38a3ff7d739dca83ae49ccec6', 'condition': 'not build_with_chromium', }, @@ -881,7 +948,7 @@ deps = { }, 'third_party/nasm': { - 'url': Var('chromium_git') + '/chromium/deps/nasm.git@f477acb1049f5e043904b87b825c5915084a9a29', + 'url': Var('chromium_git') + '/chromium/deps/nasm.git@af5eeeb054bebadfbb79c7bcd100a95e2ad4525f', 'condition': 'not build_with_chromium', }, @@ -897,27 +964,27 @@ deps = { }, 'third_party/OpenCL-CTS/src': { - 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenCL-CTS@e0a31a03fc8f816d59fd8b3051ac6a61d3fa50c6', - 'condition': 'not build_with_chromium', + 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenCL-CTS@9fc0d23b4cfccd84be8927363a77107dc554de30', + 'condition': 'checkout_angle_cl_deps and not build_with_chromium', }, 'third_party/OpenCL-Docs/src': { - 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenCL-Docs@774114e8761920b976d538d47fad8178d05984ec', + 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenCL-Docs@5b4ca15f0e5a5be87b56b99f652f728e05cab587', 'condition': 'not build_with_chromium', }, 'third_party/OpenCL-ICD-Loader/src': { - 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenCL-ICD-Loader@9b5e3849b49a1448996c8b96ba086cd774d987db', - 'condition': 'not build_with_chromium', + 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenCL-ICD-Loader@ddf6c70230a79cdb8fcccfd3c775b09e6820f42e', + 'condition': 'checkout_angle_cl_deps and not build_with_chromium', }, 'third_party/OpenGL-Registry/src': { - 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenGL-Registry@5bae8738b23d06968e7c3a41308568120943ae77', + 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenGL-Registry@d38ff693f3e99ac5a61e3858de76c6c02976fa67', 'condition': 'not build_with_chromium', }, 'third_party/perfetto': { - 'url': Var('android_git') + '/platform/external/perfetto.git@d06bef7807a8b90de9bce77132e188f68459a714', + 'url': Var('android_git') + '/platform/external/perfetto.git@5c17fc6e089cecec6bd75073875f57c99dcd2f02', 'condition': 'not build_with_chromium and checkout_angle_perfetto', }, @@ -933,7 +1000,7 @@ deps = { }, 'third_party/protobuf': { - 'url': Var('chromium_git') + '/chromium/src/third_party/protobuf@d8e413be0cb7645a3545a6efea1aab03f9a58e52', + 'url': Var('chromium_git') + '/chromium/src/third_party/protobuf@ddf513ccaeed6b1316bc2029b10f4436ad297324', 'condition': 'not build_with_chromium', }, @@ -946,7 +1013,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': '8dKduCb-T1CXo1k__TsFWTWKwtx92qcCCIJ8zGP7QaAC', + 'version': 'y-gKj5TCCHcid39xiew3e8_-eZpgmCf83D9J_-extpQC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -960,7 +1027,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'ukddmPlorF_6XXPBcxDxCmK2PSAJlhu_MDUhZQCz1l8C', + 'version': 'a4fVqbIycCDqs1714SLRqxEdz6P-sH-z1QT_eeeF0PcC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -971,20 +1038,25 @@ deps = { 'url': Var('chromium_git') + '/external/github.com/Tencent/rapidjson@781a4e667d84aeedbeb8184b7b62425ea66ec59f', }, + 'third_party/re2/src': { + 'url': Var('chromium_git') + '/external/github.com/google/re2.git@972a15cedd008d846f1a39b2e88ce48d7f166cbd', + 'condition': 'not build_with_chromium', + }, + 'third_party/requests/src': { 'url': Var('chromium_git') + '/external/github.com/kennethreitz/requests.git@c7e0fc087ceeadb8b4c84a0953a422c474093d6d', 'condition': 'checkout_android and not build_with_chromium', }, 'third_party/rust': { - 'url': Var('chromium_git') + '/chromium/src/third_party/rust@588e69eab286e9f07b49d45ac9d483aac4c1c9cf', + 'url': Var('chromium_git') + '/chromium/src/third_party/rust@37133fcc2fb93e454471cec6501e6547c74108c0', 'condition': 'not build_with_chromium', }, 'third_party/siso/cipd': { 'packages': [ { - 'package': 'infra/build/siso/${{platform}}', + 'package': 'build/siso/${{platform}}', 'version': Var('siso_version'), } ], @@ -993,12 +1065,12 @@ deps = { }, 'third_party/six': { - 'url': Var('chromium_git') + '/chromium/src/third_party/six@580980eb7d380150995b82cd18e1254ab5eff77f', + 'url': Var('chromium_git') + '/chromium/src/third_party/six@98dedb5909b3e39848c6de5122772f5a89abe61a', 'condition': 'checkout_android and not build_with_chromium', }, 'third_party/SwiftShader': { - 'url': Var('swiftshader_git') + '/SwiftShader@720189cae8478484f51531a9eed9abc6d8635271', + 'url': Var('swiftshader_git') + '/SwiftShader@374652a342e0e8f5bc82df06e520ce6acb1c969d', 'condition': 'not build_with_chromium', }, @@ -1006,7 +1078,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/turbine', - 'version': 'qNNUfaj7w4cSHTjVawVaZpq0pABVec9LcFebN19wm4EC', + 'version': 'j49Y1F_PAMGZdDf53rGaEzVXdT6jXWDhEm7UMfGhjswC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -1018,17 +1090,17 @@ deps = { }, 'third_party/vulkan-deps': { - 'url': Var('chromium_git') + '/vulkan-deps@b62b2ca7025e54c25a16f678dd6ce39adfaccc73', + 'url': Var('chromium_git') + '/vulkan-deps@54fcc5faac160ea56b6205fa91a7bf94bea5528a', 'condition': 'not build_with_chromium', }, 'third_party/glslang/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/glslang@ef5207f9f8cce5097568efb15d3297d8b5d13014', + 'url': '{chromium_git}/external/github.com/KhronosGroup/glslang@f0bd0257c308b9a26562c1a30c4748a0219cc951', 'condition': 'not build_with_chromium', }, 'third_party/lunarg-vulkantools/src': { - 'url': '{chromium_git}/external/github.com/LunarG/VulkanTools@0ed717a810d28e7533d935a7c0017f6d267a8671', + 'url': '{chromium_git}/external/github.com/LunarG/VulkanTools@7e47ffa5e8647946a6ebc96f67cf974f6afaa8ba', 'condition': 'not build_with_chromium', }, @@ -1038,42 +1110,42 @@ deps = { }, 'third_party/spirv-headers/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@09913f088a1197aba4aefd300a876b2ebbaa3391', + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@04f10f650d514df88b76d25e83db360142c7b174', 'condition': 'not build_with_chromium', }, 'third_party/spirv-tools/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@dc1641d168304d3ef97bba23d5fc45c9bead45f5', + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@d3f9ef117aab877b23a266b1e7542549ea70b817', 'condition': 'not build_with_chromium', }, 'third_party/vulkan-headers/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@234c4b7370a8ea3239a214c9e871e4b17c89f4ab', + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@b5c8f996196ba4aa6d8f97e52b5d3b6e70f7e4e2', 'condition': 'not build_with_chromium', }, 'third_party/vulkan-loader/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@fde0f9718bd60b49cf8efc80d3fb7a093c309ac0', + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@32fcb949e253cbeb40cda7ea76122b492db579ae', 'condition': 'not build_with_chromium', }, 'third_party/vulkan-tools/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@a9f88a232a4cd6634e47f0f93c8fac5789387a7a', + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@48a4bcbdf619e57204783f8c1a04c76c160ddd5b', 'condition': 'not build_with_chromium', }, 'third_party/vulkan-utility-libraries/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@fe7a09b13899c5c77d956fa310286f7a7eb2c4ed', + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@a663eca87ba71294dd4b74ba9d3e64a72d725453', 'condition': 'not build_with_chromium', }, 'third_party/vulkan-validation-layers/src': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@266d5cd69a94c1262c44307f4c4209c97f5c6ec4', + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@2d34d32c82f7f0a308f09973f8874f69f56a66ae', 'condition': 'not build_with_chromium', }, 'third_party/vulkan_memory_allocator': { - 'url': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@56300b29fbfcc693ee6609ddad3fdd5b7a449a21', + 'url': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@cb0597213b0fcb999caa9ed08c2f88dc45eb7d50', 'condition': 'not build_with_chromium', }, @@ -1083,31 +1155,20 @@ deps = { }, 'third_party/zlib': { - 'url': Var('chromium_git') + '/chromium/src/third_party/zlib@5634698162b2182c350e4cb360a0f4dd7706afec', + 'url': Var('chromium_git') + '/chromium/src/third_party/zlib@980253c1cc835c893c57b5cfc10c5b942e10bc46', 'condition': 'not build_with_chromium', }, 'tools/android': { - 'url': Var('chromium_git') + '/chromium/src/tools/android@d5b1dd58bd5e7a0460e203909cb9fba5b3085a17', + 'url': Var('chromium_git') + '/chromium/src/tools/android@93a7974ca06a3e375df655bd7e86ec4845fae60c', 'condition': 'checkout_android and not build_with_chromium', }, 'tools/clang': { - 'url': Var('chromium_git') + '/chromium/src/tools/clang.git@1340d3ed8bae85ab0e8410c4439289dde1d3fea6', + 'url': Var('chromium_git') + '/chromium/src/tools/clang.git@8837640dd26df7735d6574781ec4e20fb0c1baab', 'condition': 'not build_with_chromium', }, - 'tools/clang/dsymutil': { - 'packages': [ - { - 'package': 'chromium/llvm-build-tools/dsymutil', - 'version': 'M56jPzDv1620Rnm__jTMYS62Zi8rxHVq7yw0qeBFEgkC', - } - ], - 'condition': 'checkout_mac and not build_with_chromium', - 'dep_type': 'cipd', - }, - 'tools/luci-go': { 'packages': [ { @@ -1128,27 +1189,27 @@ deps = { }, 'tools/mb': { - 'url': Var('chromium_git') + '/chromium/src/tools/mb@8e880be2d6e35587fd372f204b9d6d4aed0bc194', + 'url': Var('chromium_git') + '/chromium/src/tools/mb@1fc5adbbce8acd2a5fdccefde5af9865b982429d', 'condition': 'not build_with_chromium', }, 'tools/md_browser': { - 'url': Var('chromium_git') + '/chromium/src/tools/md_browser@6cc8e58a83412dc31de6fb7614fadb0b51748d4b', + 'url': Var('chromium_git') + '/chromium/src/tools/md_browser@b7cfebc8143108734248df4e855a1bff01173f77', 'condition': 'not build_with_chromium', }, 'tools/memory': { - 'url': Var('chromium_git') + '/chromium/src/tools/memory@8e9b58419b41fe0d9dfe2e870f3164f446a0d7ab', + 'url': Var('chromium_git') + '/chromium/src/tools/memory@e028ac649856478983fdca599522f242de568826', 'condition': 'not build_with_chromium', }, 'tools/perf': { - 'url': Var('chromium_git') + '/chromium/src/tools/perf@2ed187cab21cd990e4b58c381ac157382114bf57', + 'url': Var('chromium_git') + '/chromium/src/tools/perf@b70509b23814bdcb08547d72d3e8fe6cc7d5dbcc', 'condition': 'not build_with_chromium', }, 'tools/protoc_wrapper': { - 'url': Var('chromium_git') + '/chromium/src/tools/protoc_wrapper@dbcbea90c20ae1ece442d8ef64e61c7b10e2b013', + 'url': Var('chromium_git') + '/chromium/src/tools/protoc_wrapper@3438d4183bfc7c0d6850e8b970204cc8189f0323', 'condition': 'not build_with_chromium', }, @@ -1158,7 +1219,7 @@ deps = { }, 'tools/rust': { - 'url': Var('chromium_git') + '/chromium/src/tools/rust.git@05dbbfdcec4a7cc6c7cbf735d5a67d331a2f40da', + 'url': Var('chromium_git') + '/chromium/src/tools/rust.git@d2fadac996be252abe5077583a42970163e9f2e7', 'condition': 'not build_with_chromium', }, @@ -1166,7 +1227,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'Djmxg641BIFDuvtwbk4GxAWptW7AWRnqZ5hCffbpETcC', + 'version': 'yTR-Js4FbeTvqObewyJyRmr39wR04DHCNjjeLkgEfZEC', }, ], 'dep_type': 'cipd', @@ -1177,7 +1238,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'Rj9DcPKzbqhsLO2by6iMiqZvlUFzBcSsp42l8nyHD8MC', + 'version': 'Da5Ya6mYbLxKhrtipFoPIZ5OASVAOy4lxDi8n5OnhN0C', }, ], 'dep_type': 'cipd', @@ -1188,7 +1249,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'w4KjkADnVRHE8TgQXpDuP6qD3uivftyQ3ue-Ee-gqWQC', + 'version': '1EbFABRLnKXjSwrQyXiazV1dpZmsc6rNsPulULz1aYcC', }, ], 'dep_type': 'cipd', @@ -1199,7 +1260,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': '4aUb9UJChUHJebFHC5FjJ5d6Lf7cYuLSEJbco0uC3WEC', + 'version': 'R_blxv41vyVuvXG6g0-8OU0kt5eHXBJeZmXB0FJ5beYC', }, ], 'dep_type': 'cipd', @@ -1207,10 +1268,15 @@ deps = { }, 'tools/valgrind': { - 'url': Var('chromium_git') + '/chromium/src/tools/valgrind@aa44e7637ff74c6d4733ed5552afb44f3cfddb37', + 'url': Var('chromium_git') + '/chromium/src/tools/valgrind@da34b95fdbf2032df6cda5f3828c2ba421592644', 'condition': 'not build_with_chromium', }, + 'tools/win': { + 'url': Var('chromium_git') + '/chromium/src/tools/win@baacfc6d5986b07abe0503216b491e234b94ba79', + 'condition': 'checkout_win and not build_with_chromium', + }, + # === ANGLE Restricted Trace Generated Code Start === 'src/tests/restricted_traces/1945_air_force': { 'packages': [ @@ -1252,6 +1318,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_3d_pool_ball', }, + 'src/tests/restricted_traces/ace_racer': { + 'packages': [ + { + 'package': 'angle/traces/ace_racer', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_ace_racer', + }, 'src/tests/restricted_traces/afk_arena': { 'packages': [ { @@ -1362,6 +1438,26 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_antutu_refinery', }, + 'src/tests/restricted_traces/apex_girl': { + 'packages': [ + { + 'package': 'angle/traces/apex_girl', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_apex_girl', + }, + 'src/tests/restricted_traces/archero_2': { + 'packages': [ + { + 'package': 'angle/traces/archero_2', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_archero_2', + }, 'src/tests/restricted_traces/arena_of_valor': { 'packages': [ { @@ -1422,6 +1518,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_avakin_life', }, + 'src/tests/restricted_traces/avatar_world': { + 'packages': [ + { + 'package': 'angle/traces/avatar_world', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_avatar_world', + }, 'src/tests/restricted_traces/aztec_ruins': { 'packages': [ { @@ -1456,7 +1562,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/balatro', - 'version': 'version:1', + 'version': 'version:2', }, ], 'dep_type': 'cipd', @@ -1512,6 +1618,26 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_billiards_city', }, + 'src/tests/restricted_traces/bingo_blitz': { + 'packages': [ + { + 'package': 'angle/traces/bingo_blitz', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_bingo_blitz', + }, + 'src/tests/restricted_traces/black_beacon': { + 'packages': [ + { + 'package': 'angle/traces/black_beacon', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_black_beacon', + }, 'src/tests/restricted_traces/black_clover_m': { 'packages': [ { @@ -1552,6 +1678,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_block_blast', }, + 'src/tests/restricted_traces/block_craft_3d': { + 'packages': [ + { + 'package': 'angle/traces/block_craft_3d', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_block_craft_3d', + }, 'src/tests/restricted_traces/blockman_go': { 'packages': [ { @@ -1562,6 +1698,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_blockman_go', }, + 'src/tests/restricted_traces/blood_strike': { + 'packages': [ + { + 'package': 'angle/traces/blood_strike', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_blood_strike', + }, 'src/tests/restricted_traces/botworld_adventure': { 'packages': [ { @@ -1572,6 +1718,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_botworld_adventure', }, + 'src/tests/restricted_traces/brain_test_tricky_puzzles': { + 'packages': [ + { + 'package': 'angle/traces/brain_test_tricky_puzzles', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_brain_test_tricky_puzzles', + }, 'src/tests/restricted_traces/brawl_stars': { 'packages': [ { @@ -1612,6 +1768,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_bridge_constructor_portal', }, + 'src/tests/restricted_traces/brotato': { + 'packages': [ + { + 'package': 'angle/traces/brotato', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_brotato', + }, 'src/tests/restricted_traces/bubble_shooter': { 'packages': [ { @@ -1632,6 +1798,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_bubble_shooter_and_friends', }, + 'src/tests/restricted_traces/bubble_shooter_relaxing': { + 'packages': [ + { + 'package': 'angle/traces/bubble_shooter_relaxing', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_bubble_shooter_relaxing', + }, 'src/tests/restricted_traces/bullet_echo': { 'packages': [ { @@ -1722,6 +1898,36 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_car_race_3d', }, + 'src/tests/restricted_traces/carrom_pool_disc_game': { + 'packages': [ + { + 'package': 'angle/traces/carrom_pool_disc_game', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_carrom_pool_disc_game', + }, + 'src/tests/restricted_traces/cash_frenzy_casino_slots': { + 'packages': [ + { + 'package': 'angle/traces/cash_frenzy_casino_slots', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_cash_frenzy_casino_slots', + }, + 'src/tests/restricted_traces/cashman_casino': { + 'packages': [ + { + 'package': 'angle/traces/cashman_casino', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_cashman_casino', + }, 'src/tests/restricted_traces/castlevania_sotn': { 'packages': [ { @@ -1732,6 +1938,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_castlevania_sotn', }, + 'src/tests/restricted_traces/cat_runner': { + 'packages': [ + { + 'package': 'angle/traces/cat_runner', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_cat_runner', + }, 'src/tests/restricted_traces/catalyst_black': { 'packages': [ { @@ -1792,6 +2008,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_coin_master', }, + 'src/tests/restricted_traces/color_block_combo_blast': { + 'packages': [ + { + 'package': 'angle/traces/color_block_combo_blast', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_color_block_combo_blast', + }, 'src/tests/restricted_traces/command_and_conquer_rivals': { 'packages': [ { @@ -1806,7 +2032,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/cookie_run_kingdom', - 'version': 'version:5', + 'version': 'version:6', }, ], 'dep_type': 'cipd', @@ -1852,6 +2078,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_cut_the_rope', }, + 'src/tests/restricted_traces/dark_war_survival': { + 'packages': [ + { + 'package': 'angle/traces/dark_war_survival', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_dark_war_survival', + }, 'src/tests/restricted_traces/darkness_rises': { 'packages': [ { @@ -1862,6 +2098,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_darkness_rises', }, + 'src/tests/restricted_traces/dc_dark_legion': { + 'packages': [ + { + 'package': 'angle/traces/dc_dark_legion', + 'version': 'version:2', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_dc_dark_legion', + }, 'src/tests/restricted_traces/dead_by_daylight': { 'packages': [ { @@ -1902,6 +2148,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_diablo_immortal', }, + 'src/tests/restricted_traces/dice_dreams': { + 'packages': [ + { + 'package': 'angle/traces/dice_dreams', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_dice_dreams', + }, 'src/tests/restricted_traces/disney_mirrorverse': { 'packages': [ { @@ -1912,6 +2168,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_disney_mirrorverse', }, + 'src/tests/restricted_traces/disney_solitaire': { + 'packages': [ + { + 'package': 'angle/traces/disney_solitaire', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_disney_solitaire', + }, 'src/tests/restricted_traces/disney_tsum_tsum': { 'packages': [ { @@ -1922,6 +2188,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_disney_tsum_tsum', }, + 'src/tests/restricted_traces/domino_dreams': { + 'packages': [ + { + 'package': 'angle/traces/domino_dreams', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_domino_dreams', + }, 'src/tests/restricted_traces/dont_starve': { 'packages': [ { @@ -2122,6 +2398,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_farm_heroes_saga', }, + 'src/tests/restricted_traces/fashion_show': { + 'packages': [ + { + 'package': 'angle/traces/fashion_show', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_fashion_show', + }, 'src/tests/restricted_traces/fate_grand_order': { 'packages': [ { @@ -2146,7 +2432,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/final_fantasy', - 'version': 'version:5', + 'version': 'version:6', }, ], 'dep_type': 'cipd', @@ -2192,6 +2478,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_five_nights_at_freddys', }, + 'src/tests/restricted_traces/football_league_2025': { + 'packages': [ + { + 'package': 'angle/traces/football_league_2025', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_football_league_2025', + }, 'src/tests/restricted_traces/free_fire': { 'packages': [ { @@ -2212,6 +2508,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_free_fire_max', }, + 'src/tests/restricted_traces/frost_and_flame': { + 'packages': [ + { + 'package': 'angle/traces/frost_and_flame', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_frost_and_flame', + }, 'src/tests/restricted_traces/gacha_club': { 'packages': [ { @@ -2256,7 +2562,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/genshin_impact', - 'version': 'version:5', + 'version': 'version:6', }, ], 'dep_type': 'cipd', @@ -2302,6 +2608,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_google_maps', }, + 'src/tests/restricted_traces/gossip_harbor': { + 'packages': [ + { + 'package': 'angle/traces/gossip_harbor', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_gossip_harbor', + }, 'src/tests/restricted_traces/grand_mountain_adventure': { 'packages': [ { @@ -2352,6 +2668,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_harry_potter_hogwarts_mystery', }, + 'src/tests/restricted_traces/harry_potter_magic_awakened': { + 'packages': [ + { + 'package': 'angle/traces/harry_potter_magic_awakened', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_harry_potter_magic_awakened', + }, 'src/tests/restricted_traces/hay_day': { 'packages': [ { @@ -2372,6 +2698,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_hearthstone', }, + 'src/tests/restricted_traces/hero_wars': { + 'packages': [ + { + 'package': 'angle/traces/hero_wars', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_hero_wars', + }, 'src/tests/restricted_traces/higgs_domino_island': { 'packages': [ { @@ -2392,6 +2728,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_hill_climb_racing', }, + 'src/tests/restricted_traces/hole_io': { + 'packages': [ + { + 'package': 'angle/traces/hole_io', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_hole_io', + }, 'src/tests/restricted_traces/homescapes': { 'packages': [ { @@ -2402,6 +2748,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_homescapes', }, + 'src/tests/restricted_traces/honkai_impact_3rd': { + 'packages': [ + { + 'package': 'angle/traces/honkai_impact_3rd', + 'version': 'version:2', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_honkai_impact_3rd', + }, 'src/tests/restricted_traces/honkai_star_rail': { 'packages': [ { @@ -2422,46 +2778,96 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_hungry_shark_evolution', }, - 'src/tests/restricted_traces/idle_heroes': { + 'src/tests/restricted_traces/hunter_assassin': { 'packages': [ { - 'package': 'angle/traces/idle_heroes', - 'version': 'version:5', + 'package': 'angle/traces/hunter_assassin', + 'version': 'version:1', }, ], 'dep_type': 'cipd', - 'condition': 'checkout_angle_restricted_trace_idle_heroes', + 'condition': 'checkout_angle_restricted_trace_hunter_assassin', }, - 'src/tests/restricted_traces/infinity_ops': { + 'src/tests/restricted_traces/i9_inferno_nine': { 'packages': [ { - 'package': 'angle/traces/infinity_ops', + 'package': 'angle/traces/i9_inferno_nine', 'version': 'version:1', }, ], 'dep_type': 'cipd', - 'condition': 'checkout_angle_restricted_trace_infinity_ops', + 'condition': 'checkout_angle_restricted_trace_i9_inferno_nine', }, - 'src/tests/restricted_traces/injustice_2': { + 'src/tests/restricted_traces/identity_v': { 'packages': [ { - 'package': 'angle/traces/injustice_2', + 'package': 'angle/traces/identity_v', 'version': 'version:1', }, ], 'dep_type': 'cipd', - 'condition': 'checkout_angle_restricted_trace_injustice_2', + 'condition': 'checkout_angle_restricted_trace_identity_v', }, - 'src/tests/restricted_traces/into_the_dead_2': { + 'src/tests/restricted_traces/idle_heroes': { 'packages': [ { - 'package': 'angle/traces/into_the_dead_2', + 'package': 'angle/traces/idle_heroes', + 'version': 'version:5', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_idle_heroes', + }, + 'src/tests/restricted_traces/indian_bikes_driving_3d': { + 'packages': [ + { + 'package': 'angle/traces/indian_bikes_driving_3d', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_indian_bikes_driving_3d', + }, + 'src/tests/restricted_traces/infinity_ops': { + 'packages': [ + { + 'package': 'angle/traces/infinity_ops', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_infinity_ops', + }, + 'src/tests/restricted_traces/injustice_2': { + 'packages': [ + { + 'package': 'angle/traces/injustice_2', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_injustice_2', + }, + 'src/tests/restricted_traces/into_the_dead_2': { + 'packages': [ + { + 'package': 'angle/traces/into_the_dead_2', 'version': 'version:1', }, ], 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_into_the_dead_2', }, + 'src/tests/restricted_traces/jackpot_party': { + 'packages': [ + { + 'package': 'angle/traces/jackpot_party', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_jackpot_party', + }, 'src/tests/restricted_traces/jackpot_world': { 'packages': [ { @@ -2512,6 +2918,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_kentucky_route_zero', }, + 'src/tests/restricted_traces/kingshot': { + 'packages': [ + { + 'package': 'angle/traces/kingshot', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_kingshot', + }, 'src/tests/restricted_traces/klondike_adventures': { 'packages': [ { @@ -2522,6 +2938,26 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_klondike_adventures', }, + 'src/tests/restricted_traces/knives_out': { + 'packages': [ + { + 'package': 'angle/traces/knives_out', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_knives_out', + }, + 'src/tests/restricted_traces/lands_of_jail': { + 'packages': [ + { + 'package': 'angle/traces/lands_of_jail', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_lands_of_jail', + }, 'src/tests/restricted_traces/last_shelter_survival': { 'packages': [ { @@ -2532,6 +2968,26 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_last_shelter_survival', }, + 'src/tests/restricted_traces/last_war_survival_game': { + 'packages': [ + { + 'package': 'angle/traces/last_war_survival_game', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_last_war_survival_game', + }, + 'src/tests/restricted_traces/last_z_survival_shooter': { + 'packages': [ + { + 'package': 'angle/traces/last_z_survival_shooter', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_last_z_survival_shooter', + }, 'src/tests/restricted_traces/league_of_legends_wild_rift': { 'packages': [ { @@ -2562,6 +3018,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_life_is_strange', }, + 'src/tests/restricted_traces/lightning_link': { + 'packages': [ + { + 'package': 'angle/traces/lightning_link', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_lightning_link', + }, 'src/tests/restricted_traces/lilys_garden': { 'packages': [ { @@ -2582,6 +3048,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_limbo', }, + 'src/tests/restricted_traces/lineage_2m': { + 'packages': [ + { + 'package': 'angle/traces/lineage_2m', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_lineage_2m', + }, 'src/tests/restricted_traces/lineage_m': { 'packages': [ { @@ -2612,6 +3088,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_lords_mobile', }, + 'src/tests/restricted_traces/lost_light': { + 'packages': [ + { + 'package': 'angle/traces/lost_light', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_lost_light', + }, 'src/tests/restricted_traces/lotsa_slots': { 'packages': [ { @@ -2622,6 +3108,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_lotsa_slots', }, + 'src/tests/restricted_traces/love_and_deepspace': { + 'packages': [ + { + 'package': 'angle/traces/love_and_deepspace', + 'version': 'version:2', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_love_and_deepspace', + }, 'src/tests/restricted_traces/ludo_king': { 'packages': [ { @@ -2716,12 +3212,42 @@ deps = { 'packages': [ { 'package': 'angle/traces/marvel_strike_force', - 'version': 'version:1', + 'version': 'version:2', }, ], 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_marvel_strike_force', }, + 'src/tests/restricted_traces/match_factory': { + 'packages': [ + { + 'package': 'angle/traces/match_factory', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_match_factory', + }, + 'src/tests/restricted_traces/match_masters': { + 'packages': [ + { + 'package': 'angle/traces/match_masters', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_match_masters', + }, + 'src/tests/restricted_traces/matching_story': { + 'packages': [ + { + 'package': 'angle/traces/matching_story', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_matching_story', + }, 'src/tests/restricted_traces/merge_dragons': { 'packages': [ { @@ -2732,6 +3258,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_merge_dragons', }, + 'src/tests/restricted_traces/merge_mansion': { + 'packages': [ + { + 'package': 'angle/traces/merge_mansion', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_merge_mansion', + }, 'src/tests/restricted_traces/messenger_lite': { 'packages': [ { @@ -2762,6 +3298,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_minecraft_bedrock', }, + 'src/tests/restricted_traces/minecraft_vibrant_visuals': { + 'packages': [ + { + 'package': 'angle/traces/minecraft_vibrant_visuals', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_minecraft_vibrant_visuals', + }, 'src/tests/restricted_traces/minetest': { 'packages': [ { @@ -2782,6 +3328,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_mini_block_craft', }, + 'src/tests/restricted_traces/mini_games_calm_and_relax': { + 'packages': [ + { + 'package': 'angle/traces/mini_games_calm_and_relax', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_mini_games_calm_and_relax', + }, 'src/tests/restricted_traces/mini_world': { 'packages': [ { @@ -2792,6 +3348,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_mini_world', }, + 'src/tests/restricted_traces/mob_control': { + 'packages': [ + { + 'package': 'angle/traces/mob_control', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_mob_control', + }, 'src/tests/restricted_traces/mobile_legends': { 'packages': [ { @@ -2882,6 +3448,36 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_my_friend_pedro', }, + 'src/tests/restricted_traces/my_talking_angela': { + 'packages': [ + { + 'package': 'angle/traces/my_talking_angela', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_my_talking_angela', + }, + 'src/tests/restricted_traces/my_talking_angela_2': { + 'packages': [ + { + 'package': 'angle/traces/my_talking_angela_2', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_my_talking_angela_2', + }, + 'src/tests/restricted_traces/my_talking_tom': { + 'packages': [ + { + 'package': 'angle/traces/my_talking_tom', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_my_talking_tom', + }, 'src/tests/restricted_traces/my_talking_tom2': { 'packages': [ { @@ -2962,6 +3558,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_octopath_traveler', }, + 'src/tests/restricted_traces/odin_valhalla_rising': { + 'packages': [ + { + 'package': 'angle/traces/odin_valhalla_rising', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_odin_valhalla_rising', + }, 'src/tests/restricted_traces/off_the_road': { 'packages': [ { @@ -2972,6 +3578,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_off_the_road', }, + 'src/tests/restricted_traces/offline_games': { + 'packages': [ + { + 'package': 'angle/traces/offline_games', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_offline_games', + }, 'src/tests/restricted_traces/one_piece_treasure_cruise': { 'packages': [ { @@ -2992,6 +3608,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_one_punch_man', }, + 'src/tests/restricted_traces/onmyoji': { + 'packages': [ + { + 'package': 'angle/traces/onmyoji', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_onmyoji', + }, 'src/tests/restricted_traces/oxenfree': { 'packages': [ { @@ -3002,6 +3628,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_oxenfree', }, + 'src/tests/restricted_traces/paper_io2': { + 'packages': [ + { + 'package': 'angle/traces/paper_io2', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_paper_io2', + }, 'src/tests/restricted_traces/passmark_complex': { 'packages': [ { @@ -3092,6 +3728,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_pokemon_go', }, + 'src/tests/restricted_traces/pokemon_go_combat': { + 'packages': [ + { + 'package': 'angle/traces/pokemon_go_combat', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_pokemon_go_combat', + }, 'src/tests/restricted_traces/pokemon_masters_ex': { 'packages': [ { @@ -3106,7 +3752,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/pokemon_unite', - 'version': 'version:5', + 'version': 'version:6', }, ], 'dep_type': 'cipd', @@ -3182,6 +3828,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_pubg_mobile_skydive', }, + 'src/tests/restricted_traces/puzzle_and_dragons': { + 'packages': [ + { + 'package': 'angle/traces/puzzle_and_dragons', + 'version': 'version:2', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_puzzle_and_dragons', + }, 'src/tests/restricted_traces/puzzles_and_survival': { 'packages': [ { @@ -3192,6 +3848,26 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_puzzles_and_survival', }, + 'src/tests/restricted_traces/qblock_wood_block_puzzle_game': { + 'packages': [ + { + 'package': 'angle/traces/qblock_wood_block_puzzle_game', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_qblock_wood_block_puzzle_game', + }, + 'src/tests/restricted_traces/race_master_3d': { + 'packages': [ + { + 'package': 'angle/traces/race_master_3d', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_race_master_3d', + }, 'src/tests/restricted_traces/ragnarok_m_eternal_love': { 'packages': [ { @@ -3212,6 +3888,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_raid_shadow_legends', }, + 'src/tests/restricted_traces/raising_a_goblin': { + 'packages': [ + { + 'package': 'angle/traces/raising_a_goblin', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_raising_a_goblin', + }, 'src/tests/restricted_traces/real_commando_secret_mission': { 'packages': [ { @@ -3332,6 +4018,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_rope_hero_vice_town', }, + 'src/tests/restricted_traces/royal_kingdom': { + 'packages': [ + { + 'package': 'angle/traces/royal_kingdom', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_royal_kingdom', + }, 'src/tests/restricted_traces/royal_match': { 'packages': [ { @@ -3382,16 +4078,36 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_scary_teacher_3d', }, - 'src/tests/restricted_traces/scrabble_go': { + 'src/tests/restricted_traces/school_party_craft': { 'packages': [ { - 'package': 'angle/traces/scrabble_go', - 'version': 'version:5', + 'package': 'angle/traces/school_party_craft', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_school_party_craft', + }, + 'src/tests/restricted_traces/scrabble_go': { + 'packages': [ + { + 'package': 'angle/traces/scrabble_go', + 'version': 'version:5', }, ], 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_scrabble_go', }, + 'src/tests/restricted_traces/seaside_escape': { + 'packages': [ + { + 'package': 'angle/traces/seaside_escape', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_seaside_escape', + }, 'src/tests/restricted_traces/shadow_fight_2': { 'packages': [ { @@ -3416,7 +4132,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/shadowgun_legends', - 'version': 'version:1', + 'version': 'version:2', }, ], 'dep_type': 'cipd', @@ -3492,6 +4208,36 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_slingshot_test2', }, + 'src/tests/restricted_traces/slotomania': { + 'packages': [ + { + 'package': 'angle/traces/slotomania', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_slotomania', + }, + 'src/tests/restricted_traces/snake_io': { + 'packages': [ + { + 'package': 'angle/traces/snake_io', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_snake_io', + }, + 'src/tests/restricted_traces/snake_lite': { + 'packages': [ + { + 'package': 'angle/traces/snake_lite', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_snake_lite', + }, 'src/tests/restricted_traces/sniper_3d': { 'packages': [ { @@ -3502,11 +4248,21 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_sniper_3d', }, + 'src/tests/restricted_traces/soccer_superstar': { + 'packages': [ + { + 'package': 'angle/traces/soccer_superstar', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_soccer_superstar', + }, 'src/tests/restricted_traces/solar_smash': { 'packages': [ { 'package': 'angle/traces/solar_smash', - 'version': 'version:2', + 'version': 'version:3', }, ], 'dep_type': 'cipd', @@ -3542,6 +4298,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_special_forces_group_2', }, + 'src/tests/restricted_traces/spider_fighter_3': { + 'packages': [ + { + 'package': 'angle/traces/spider_fighter_3', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_spider_fighter_3', + }, 'src/tests/restricted_traces/standoff_2': { 'packages': [ { @@ -3596,7 +4362,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/state_of_survival', - 'version': 'version:1', + 'version': 'version:2', }, ], 'dep_type': 'cipd', @@ -3672,6 +4438,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_summoners_war', }, + 'src/tests/restricted_traces/super_bear_adventure': { + 'packages': [ + { + 'package': 'angle/traces/super_bear_adventure', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_super_bear_adventure', + }, 'src/tests/restricted_traces/super_mario_run': { 'packages': [ { @@ -3712,6 +4488,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_survivor_io', }, + 'src/tests/restricted_traces/talking_tom_gold_run': { + 'packages': [ + { + 'package': 'angle/traces/talking_tom_gold_run', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_talking_tom_gold_run', + }, 'src/tests/restricted_traces/talking_tom_hero_dash': { 'packages': [ { @@ -3822,6 +4608,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_thimbleweed_park', }, + 'src/tests/restricted_traces/tile_club': { + 'packages': [ + { + 'package': 'angle/traces/tile_club', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_tile_club', + }, 'src/tests/restricted_traces/tmnt_shredders_revenge': { 'packages': [ { @@ -3836,7 +4632,7 @@ deps = { 'packages': [ { 'package': 'angle/traces/toca_life_world', - 'version': 'version:2', + 'version': 'version:3', }, ], 'dep_type': 'cipd', @@ -3846,12 +4642,22 @@ deps = { 'packages': [ { 'package': 'angle/traces/toon_blast', - 'version': 'version:5', + 'version': 'version:6', }, ], 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_toon_blast', }, + 'src/tests/restricted_traces/top_heroes_kingdom_saga': { + 'packages': [ + { + 'package': 'angle/traces/top_heroes_kingdom_saga', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_top_heroes_kingdom_saga', + }, 'src/tests/restricted_traces/top_war': { 'packages': [ { @@ -3862,6 +4668,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_top_war', }, + 'src/tests/restricted_traces/total_battle': { + 'packages': [ + { + 'package': 'angle/traces/total_battle', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_total_battle', + }, 'src/tests/restricted_traces/tower_of_fantasy': { 'packages': [ { @@ -3892,6 +4708,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_traffic_rider', }, + 'src/tests/restricted_traces/travel_town': { + 'packages': [ + { + 'package': 'angle/traces/travel_town', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_travel_town', + }, 'src/tests/restricted_traces/trex_200': { 'packages': [ { @@ -3902,6 +4728,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_trex_200', }, + 'src/tests/restricted_traces/two_player_games': { + 'packages': [ + { + 'package': 'angle/traces/two_player_games', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_two_player_games', + }, 'src/tests/restricted_traces/uber': { 'packages': [ { @@ -3912,6 +4748,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_uber', }, + 'src/tests/restricted_traces/umamusume_pretty_derby': { + 'packages': [ + { + 'package': 'angle/traces/umamusume_pretty_derby', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_umamusume_pretty_derby', + }, 'src/tests/restricted_traces/vainglory': { 'packages': [ { @@ -3922,6 +4768,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_vainglory', }, + 'src/tests/restricted_traces/vita_mahjong': { + 'packages': [ + { + 'package': 'angle/traces/vita_mahjong', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_vita_mahjong', + }, 'src/tests/restricted_traces/walking_dead_survivors': { 'packages': [ { @@ -3982,6 +4838,16 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_whatsapp', }, + 'src/tests/restricted_traces/whiteout_survival': { + 'packages': [ + { + 'package': 'angle/traces/whiteout_survival', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_whiteout_survival', + }, 'src/tests/restricted_traces/woodoku': { 'packages': [ { @@ -4082,6 +4948,26 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_angle_restricted_trace_worms_zone_io', }, + 'src/tests/restricted_traces/wuthering_waves': { + 'packages': [ + { + 'package': 'angle/traces/wuthering_waves', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_wuthering_waves', + }, + 'src/tests/restricted_traces/yalla_ludo': { + 'packages': [ + { + 'package': 'angle/traces/yalla_ludo', + 'version': 'version:1', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_angle_restricted_trace_yalla_ludo', + }, 'src/tests/restricted_traces/zenonia_4': { 'packages': [ { @@ -4116,22 +5002,11 @@ deps = { # === ANDROID_DEPS Generated Code Start === # Generated by //third_party/android_deps/fetch_all.py - 'third_party/android_deps/cipd/libs/com_android_support_support_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_android_support_support_annotations', - 'version': 'version:2@28.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - 'third_party/android_deps/cipd/libs/com_android_tools_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_tools_common', - 'version': 'version:2@30.2.0-beta01.cr1', + 'version': 'version:2@30.2.0-beta01.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', @@ -4142,7 +5017,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api', - 'version': 'version:2@30.2.0-beta01.cr1', + 'version': 'version:2@30.2.0-beta01.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', @@ -4153,7 +5028,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_tools_sdk_common', - 'version': 'version:2@30.2.0-beta01.cr1', + 'version': 'version:2@30.2.0-beta01.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', @@ -4164,1199 +5039,208 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_apps_common_testing_accessibility_framework_accessibility_test_framework', - 'version': 'version:2@4.1.1.cr1', + 'version': 'version:2@4.0.0.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_datatransport_transport_api': { + 'third_party/android_deps/cipd/libs/com_googlecode_java_diff_utils_diffutils': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_datatransport_transport_api', - 'version': 'version:2@2.2.1.cr1', + 'package': 'chromium/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils', + 'version': 'version:2@1.3.0.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth': { + 'third_party/android_deps/cipd/libs/com_squareup_javapoet': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth', - 'version': 'version:2@21.1.1.cr1', + 'package': 'chromium/third_party/android_deps/libs/com_squareup_javapoet', + 'version': 'version:2@1.13.0.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth_api_phone': { + 'third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone', - 'version': 'version:2@18.0.2.cr1', + 'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy', + 'version': 'version:2@1.17.6.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth_base': { + 'third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy_agent': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base', - 'version': 'version:2@18.0.10.cr1', + 'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy_agent', + 'version': 'version:2@1.17.6.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth_blockstore': { + 'third_party/android_deps/cipd/libs/org_ccil_cowan_tagsoup_tagsoup': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth_blockstore', - 'version': 'version:2@16.4.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup', + 'version': 'version:2@1.2.1.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_base': { + 'third_party/android_deps/cipd/libs/org_checkerframework_checker_compat_qual': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_base', - 'version': 'version:2@18.5.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_compat_qual', + 'version': 'version:2@2.5.5.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_basement': { + 'third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_basement', - 'version': 'version:2@18.5.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime', + 'version': 'version:2@1.9.22.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_cast': { + 'third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_cast', - 'version': 'version:2@17.0.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime', + 'version': 'version:2@1.9.22.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_cast_framework': { + 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework', - 'version': 'version:2@17.0.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava', + 'version': 'version:2@1.8.1.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_clearcut': { + 'third_party/android_deps/cipd/libs/org_jsoup_jsoup': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut', - 'version': 'version:2@17.0.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_jsoup_jsoup', + 'version': 'version:2@1.15.1.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_cloud_messaging': { + 'third_party/android_deps/cipd/libs/org_mockito_mockito_android': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging', - 'version': 'version:2@16.0.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_android', + 'version': 'version:2@5.19.0.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_fido': { + 'third_party/android_deps/cipd/libs/org_mockito_mockito_core': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_fido', - 'version': 'version:2@21.1.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_core', + 'version': 'version:2@5.19.0.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_flags': { + 'third_party/android_deps/cipd/libs/org_mockito_mockito_subclass': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_flags', - 'version': 'version:2@17.0.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_subclass', + 'version': 'version:2@5.19.0.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_gcm': { + 'third_party/android_deps/cipd/libs/org_objenesis_objenesis': { 'packages': [ { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_gcm', - 'version': 'version:2@17.0.0.cr1', + 'package': 'chromium/third_party/android_deps/libs/org_objenesis_objenesis', + 'version': 'version:2@3.3.cr2', }, ], 'condition': 'checkout_android and not build_with_chromium and non_git_source', 'dep_type': 'cipd', }, - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_identity_credentials': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_identity_credentials', - 'version': 'version:2@16.0.0-alpha04.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, + # === ANDROID_DEPS Generated Code End === +} - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_iid': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_iid', - 'version': 'version:2@17.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', +hooks = [ + { + # Ensure that the DEPS'd "depot_tools" has its self-update capability + # disabled. + 'name': 'disable_depot_tools_selfupdate', + 'pattern': '.', + 'condition': 'not build_with_chromium', + 'action': [ + 'python3', + 'third_party/depot_tools/update_depot_tools_toggle.py', + '--disable', + ], }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_instantapps': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps', - 'version': 'version:2@18.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', + { + 'name': 'sysroot_x86', + 'pattern': '.', + 'condition': 'checkout_linux and ((checkout_x86 or checkout_x64) and not build_with_chromium)', + 'action': ['python3', 'build/linux/sysroot_scripts/install-sysroot.py', + '--arch=x86'], }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_location': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_location', - 'version': 'version:2@21.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', + { + 'name': 'sysroot_x64', + 'pattern': '.', + 'condition': 'checkout_linux and (checkout_x64 and not build_with_chromium)', + 'action': ['python3', 'build/linux/sysroot_scripts/install-sysroot.py', + '--arch=x64'], }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_phenotype': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype', - 'version': 'version:2@17.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_stats': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_stats', - 'version': 'version:2@17.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_tasks': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_tasks', - 'version': 'version:2@18.2.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_vision': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_vision', - 'version': 'version:2@20.1.3.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_gms_play_services_vision_common': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common', - 'version': 'version:2@19.1.3.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_libraries_identity_googleid_googleid': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_libraries_identity_googleid_googleid', - 'version': 'version:2@1.1.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_material_material': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_material_material', - 'version': 'version:2@1.13.0-alpha05.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_play_core_common': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_play_core_common', - 'version': 'version:2@2.0.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_android_play_feature_delivery': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_play_feature_delivery', - 'version': 'version:2@2.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_auto_service_auto_service_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations', - 'version': 'version:2@1.0-rc6.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_auto_value_auto_value_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations', - 'version': 'version:2@1.11.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_code_findbugs_jsr305': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_code_findbugs_jsr305', - 'version': 'version:2@3.0.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_code_gson_gson': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_code_gson_gson', - 'version': 'version:2@2.8.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_dagger_dagger': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_dagger_dagger', - 'version': 'version:2@2.52.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_errorprone_error_prone_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations', - 'version': 'version:2@2.30.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_annotations', - 'version': 'version:2@16.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_common': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_common', - 'version': 'version:2@19.5.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_components': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_components', - 'version': 'version:2@16.1.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_encoders': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_encoders', - 'version': 'version:2@16.1.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_encoders_json': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json', - 'version': 'version:2@17.1.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_iid': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_iid', - 'version': 'version:2@21.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_iid_interop': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop', - 'version': 'version:2@17.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_installations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_installations', - 'version': 'version:2@16.3.5.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_installations_interop': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop', - 'version': 'version:2@16.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_measurement_connector': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector', - 'version': 'version:2@18.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_firebase_firebase_messaging': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_messaging', - 'version': 'version:2@21.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_guava_failureaccess': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_guava_failureaccess', - 'version': 'version:2@1.0.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_guava_guava': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_guava_guava', - 'version': 'version:2@33.3.1-jre.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_guava_guava_android': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_guava_guava_android', - 'version': 'version:2@33.3.1-android.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_j2objc_j2objc_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations', - 'version': 'version:2@3.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_protobuf_protobuf_javalite': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite', - 'version': 'version:2@4.28.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_google_testparameterinjector_test_parameter_injector': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_testparameterinjector_test_parameter_injector', - 'version': 'version:2@1.18.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_googlecode_java_diff_utils_diffutils': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils', - 'version': 'version:2@1.3.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_squareup_javapoet': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_squareup_javapoet', - 'version': 'version:2@1.13.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_squareup_javawriter': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_squareup_javawriter', - 'version': 'version:2@2.1.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_squareup_moshi_moshi': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_squareup_moshi_moshi', - 'version': 'version:2@1.15.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_squareup_moshi_moshi_adapters': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_squareup_moshi_moshi_adapters', - 'version': 'version:2@1.15.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_squareup_okio_okio_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_squareup_okio_okio_jvm', - 'version': 'version:2@3.9.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/com_squareup_wire_wire_runtime_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_squareup_wire_wire_runtime_jvm', - 'version': 'version:2@5.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/jakarta_inject_jakarta_inject_api': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api', - 'version': 'version:2@2.0.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/javax_annotation_javax_annotation_api': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/javax_annotation_javax_annotation_api', - 'version': 'version:2@1.3.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/javax_annotation_jsr250_api': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/javax_annotation_jsr250_api', - 'version': 'version:2@1.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/javax_inject_javax_inject': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/javax_inject_javax_inject', - 'version': 'version:2@1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy', - 'version': 'version:2@1.14.12.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy_agent': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy_agent', - 'version': 'version:2@1.14.12.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_bouncycastle_bcprov_jdk18on': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_bouncycastle_bcprov_jdk18on', - 'version': 'version:2@1.78.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_ccil_cowan_tagsoup_tagsoup': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup', - 'version': 'version:2@1.2.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_checkerframework_checker_compat_qual': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_compat_qual', - 'version': 'version:2@2.5.5.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_checkerframework_checker_qual': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_qual', - 'version': 'version:2@3.43.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_checkerframework_checker_util': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_util', - 'version': 'version:2@3.25.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_codehaus_mojo_animal_sniffer_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations', - 'version': 'version:2@1.17.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_conscrypt_conscrypt_openjdk_uber': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_conscrypt_conscrypt_openjdk_uber', - 'version': 'version:2@2.5.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_hamcrest_hamcrest': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_hamcrest_hamcrest', - 'version': 'version:2@2.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime', - 'version': 'version:2@1.9.22.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime', - 'version': 'version:2@1.9.22.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_atomicfu_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm', - 'version': 'version:2@0.23.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android', - 'version': 'version:2@1.8.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm', - 'version': 'version:2@1.8.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava', - 'version': 'version:2@1.8.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm', - 'version': 'version:2@1.7.3.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_serialization_core_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_serialization_core_jvm', - 'version': 'version:2@1.7.2.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jsoup_jsoup': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jsoup_jsoup', - 'version': 'version:2@1.15.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_jspecify_jspecify': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jspecify_jspecify', - 'version': 'version:2@1.0.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_mockito_mockito_android': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_android', - 'version': 'version:2@5.11.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_mockito_mockito_core': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_core', - 'version': 'version:2@5.11.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_mockito_mockito_subclass': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_subclass', - 'version': 'version:2@5.11.0.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_objenesis_objenesis': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_objenesis_objenesis', - 'version': 'version:2@3.3.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_ow2_asm_asm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm', - 'version': 'version:2@9.7.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_ow2_asm_asm_analysis': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_analysis', - 'version': 'version:2@9.7.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_ow2_asm_asm_commons': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_commons', - 'version': 'version:2@9.7.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_ow2_asm_asm_tree': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_tree', - 'version': 'version:2@9.7.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_ow2_asm_asm_util': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_util', - 'version': 'version:2@9.7.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_annotations': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_annotations', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_junit': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_junit', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_nativeruntime': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_nativeruntime', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_nativeruntime_dist_compat': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_nativeruntime_dist_compat', - 'version': 'version:2@1.0.16.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_pluginapi': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_pluginapi', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_plugins_maven_dependency_resolver': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_resources': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_resources', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_robolectric': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_robolectric', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_sandbox': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_sandbox', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_shadowapi': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadowapi', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_shadows_framework': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadows_framework', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_utils': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_utils', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_robolectric_utils_reflector': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_robolectric_utils_reflector', - 'version': 'version:2@4.14.1.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - 'third_party/android_deps/cipd/libs/org_yaml_snakeyaml': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_yaml_snakeyaml', - 'version': 'version:2@2.3.cr1', - }, - ], - 'condition': 'checkout_android and not build_with_chromium and non_git_source', - 'dep_type': 'cipd', - }, - - # === ANDROID_DEPS Generated Code End === -} - -hooks = [ - { - # Ensure that the DEPS'd "depot_tools" has its self-update capability - # disabled. - 'name': 'disable_depot_tools_selfupdate', - 'pattern': '.', - 'condition': 'not build_with_chromium', - 'action': [ - 'python3', - 'third_party/depot_tools/update_depot_tools_toggle.py', - '--disable', - ], - }, - { - 'name': 'sysroot_x86', - 'pattern': '.', - 'condition': 'checkout_linux and ((checkout_x86 or checkout_x64) and not build_with_chromium)', - 'action': ['python3', 'build/linux/sysroot_scripts/install-sysroot.py', - '--arch=x86'], - }, - { - 'name': 'sysroot_x64', - 'pattern': '.', - 'condition': 'checkout_linux and (checkout_x64 and not build_with_chromium)', - 'action': ['python3', 'build/linux/sysroot_scripts/install-sysroot.py', - '--arch=x64'], - }, - { - # Case-insensitivity for the Win SDK. Must run before win_toolchain below. - 'name': 'ciopfs_linux', - 'pattern': '.', - 'condition': 'checkout_win and host_os == "linux" and not build_with_chromium', - 'action': [ 'python3', - 'third_party/depot_tools/download_from_google_storage.py', - '--no_resume', - '--no_auth', - '--bucket', 'chromium-browser-clang/ciopfs', - '-s', 'build/ciopfs.sha1', - ] + { + # Case-insensitivity for the Win SDK. Must run before win_toolchain below. + 'name': 'ciopfs_linux', + 'pattern': '.', + 'condition': 'checkout_win and host_os == "linux" and not build_with_chromium', + 'action': [ 'python3', + 'third_party/depot_tools/download_from_google_storage.py', + '--no_resume', + '--bucket', 'chromium-browser-clang/ciopfs', + '-s', 'build/ciopfs.sha1', + ] }, { # Update the Windows toolchain if necessary. Must run before 'clang' below. @@ -5380,6 +5264,13 @@ hooks = [ 'action': ['python3', 'tools/clang/scripts/update.py'], 'condition': 'not build_with_chromium', }, + { + # Pull down one additional llvm dependency + 'name': 'llvm_objdump', + 'pattern': '.', + 'action': ['python3', 'tools/clang/scripts/update.py', '--package', 'objdump'], + 'condition': 'not build_with_chromium', + }, { 'name': 'rust', @@ -5397,6 +5288,31 @@ hooks = [ '-o', 'build/util/LASTCHANGE'], }, + # Pull dsymutil binaries using checked-in hashes. + { + 'name': 'dsymutil_mac_arm64', + 'pattern': '.', + 'condition': 'host_os == "mac" and host_cpu == "arm64" and not build_with_chromium', + 'action': [ 'python3', + 'third_party/depot_tools/download_from_google_storage.py', + '--no_resume', + '--bucket', 'chromium-browser-clang', + '-s', 'tools/clang/dsymutil/bin/dsymutil.arm64.sha1', + '-o', 'tools/clang/dsymutil/bin/dsymutil', + ], + }, + { + 'name': 'dsymutil_mac_x64', + 'pattern': '.', + 'condition': 'host_os == "mac" and host_cpu == "x64" and not build_with_chromium', + 'action': [ 'python3', + 'third_party/depot_tools/download_from_google_storage.py', + '--no_resume', + '--bucket', 'chromium-browser-clang', + '-s', 'tools/clang/dsymutil/bin/dsymutil.x64.sha1', + '-o', 'tools/clang/dsymutil/bin/dsymutil', + ], + }, # Pull rc binaries using checked-in hashes. { 'name': 'rc_win', @@ -5405,7 +5321,6 @@ hooks = [ 'action': [ 'python3', 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', - '--no_auth', '--bucket', 'chromium-browser-clang/rc', '-s', 'build/toolchain/win/rc/win/rc.exe.sha1', ], @@ -5418,7 +5333,6 @@ hooks = [ 'action': [ 'python3', 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', - '--no_auth', '--bucket', 'chromium-browser-clang/rc', '-s', 'build/toolchain/win/rc/mac/rc.sha1', ], @@ -5430,7 +5344,6 @@ hooks = [ 'action': [ 'python3', 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', - '--no_auth', '--bucket', 'chromium-browser-clang/rc', '-s', 'build/toolchain/win/rc/linux64/rc.sha1', ] @@ -5445,7 +5358,6 @@ hooks = [ 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', '--platform=linux*', - '--no_auth', '--bucket', 'angle-glslang-validator', '-s', 'tools/glslang/glslang_validator.sha1', ], @@ -5460,7 +5372,6 @@ hooks = [ 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', '--platform=win32*', - '--no_auth', '--bucket', 'angle-glslang-validator', '-s', 'tools/glslang/glslang_validator.exe.sha1', ], @@ -5475,7 +5386,6 @@ hooks = [ 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', '--platform=linux*', - '--no_auth', '--bucket', 'angle-flex-bison', '-d', 'tools/flex-bison/linux/', ], @@ -5490,7 +5400,6 @@ hooks = [ 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', '--platform=darwin*', - '--no_auth', '--bucket', 'angle-flex-bison', '-d', 'tools/flex-bison/mac/', ], @@ -5505,7 +5414,6 @@ hooks = [ 'third_party/depot_tools/download_from_google_storage.py', '--no_resume', '--platform=win32*', - '--no_auth', '--bucket', 'angle-flex-bison', '-d', 'tools/flex-bison/windows/', ], @@ -5550,7 +5458,6 @@ hooks = [ recursedeps = [ 'buildtools', - 'third_party/googletest', 'third_party/jsoncpp', 'third_party/dawn', ] diff --git a/OWNERS b/OWNERS index 8c4daf6cd88..88f97037f09 100644 --- a/OWNERS +++ b/OWNERS @@ -36,7 +36,6 @@ per-file WATCHLISTS=* # Allow anyone to update gitlinks just like DEPS. per-file build=* per-file buildtools=* -per-file third_party/clang-format/script=* per-file testing=* per-file third_party/abseil-cpp=* per-file third_party/android_build_tools=* @@ -46,25 +45,29 @@ per-file third_party/android_sdk=* per-file third_party/astc-encoder/src=* per-file third_party/catapult=* per-file third_party/cherry=* +per-file third_party/clang-format/script=* +per-file third_party/clspv/src=* per-file third_party/colorama/src=* per-file third_party/cpu_features/src=* +per-file third_party/dawn=* per-file third_party/depot_tools=* -per-file third_party/dummy_chromium=* 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/googletest/src=* per-file third_party/ijar=* -per-file third_party/libdrm=* -per-file third_party/libjpeg_turbo=* -per-file third_party/libpng/src=* per-file third_party/jinja2=* per-file third_party/jsoncpp=* -per-file third_party/libc++/src=* per-file third_party/libc++abi/src=* +per-file third_party/libc++/src=* +per-file third_party/libdrm/src=* +per-file third_party/libjpeg_turbo=* +per-file third_party/libpng/src=* per-file third_party/libunwind/src=* +per-file third_party/llvm-libc/src=* +per-file third_party/llvm/src=* per-file third_party/lunarg-vulkantools/src=* per-file third_party/markupsafe=* per-file third_party/mesa/src=* @@ -74,9 +77,11 @@ per-file third_party/OpenCL-CTS/src=* per-file third_party/OpenCL-Docs/src=* per-file third_party/OpenCL-ICD-Loader/src=* per-file third_party/OpenGL-Registry/src=* +per-file third_party/perfetto=* per-file third_party/protobuf=* per-file third_party/Python-Markdown=* per-file third_party/rapidjson/src=* +per-file third_party/re2/src=* per-file third_party/requests/src=* per-file third_party/rust=* per-file third_party/six=* @@ -88,10 +93,10 @@ 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_memory_allocator=* 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=* per-file tools/android=* @@ -102,4 +107,6 @@ per-file tools/memory=* per-file tools/perf=* per-file tools/protoc_wrapper=* per-file tools/python=* +per-file tools/rust=* per-file tools/valgrind=* +per-file tools/win=* diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 95f1fce4fd0..203b99638d6 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -307,7 +307,8 @@ def _CheckExportValidity(input_api, output_api): use_shell = input_api.is_windows try: try: - subprocess.check_output(['gn', 'gen', outdir], shell=use_shell) + subprocess.check_output( + [sys.executable, 'third_party/depot_tools/gn.py', 'gen', outdir], shell=use_shell) except subprocess.CalledProcessError as e: return [ output_api.PresubmitError('Unable to run gn gen for export_targets.py: %s' % @@ -411,7 +412,17 @@ def test_files(f): if line.startswith('-'): continue - new_line_is_comment = line.startswith(' //') or line.startswith('+//') + # Note: we don't always get the context of the diff, so if a test already has a comment + # but is only renamed, the diff looks like: + # + # @@ + # -TEST_P(OLD, NAME) + # +TEST_P(NEW, NAME) + # + # Treat @@ as if it was a comment in that case, assuming the test already had a comment + # previously. + new_line_is_comment = ( + line.startswith(' //') or line.startswith('+//') or line.startswith('@@')) new_line_is_test_declaration = ( line.startswith('+TEST_P(') or line.startswith('+TEST(') or line.startswith('+TYPED_TEST(')) diff --git a/README.chromium b/README.chromium index 330b5e23fae..e786a2f4b92 100644 --- a/README.chromium +++ b/README.chromium @@ -2,6 +2,7 @@ Name: ANGLE URL: http://angleproject.org Version: N/A Revision: DEPS +Update Mechanism: Autoroll License: BSD-3-Clause License File: LICENSE Security Critical: yes @@ -12,4 +13,3 @@ The goal of ANGLE is to allow users of multiple operating systems to seamlessly run WebGL and other OpenGL ES content by translating OpenGL ES API calls to one of the hardware-supported APIs available for that platform. - diff --git a/README.md b/README.md index d29313db09c..eb070ff4991 100644 --- a/README.md +++ b/README.md @@ -12,28 +12,26 @@ Metal and MacOS, Chrome OS, and Fuchsia support. |----------------|:-------------:|:----------------:|:--------------:|:-------------:|:--------:|:-------------:| | OpenGL ES 2.0 | complete | complete | complete | complete | complete | complete | | OpenGL ES 3.0 | | complete | complete | complete | complete | complete | -| OpenGL ES 3.1 | | [incomplete][ES31OnD3D] | complete | complete | complete | | +| OpenGL ES 3.1 | | | complete | complete | complete | | | OpenGL ES 3.2 | | | in progress | in progress | complete | | Additionally, OpenGL ES 1.1 is implemented in the front-end using OpenGL ES 3.0 features. This version of the specification is thus supported on all platforms specified above that support OpenGL ES 3.0 with [known issues][ES1]. -[ES31OnD3D]: doc/ES31StatusOnD3D11.md [ES1]: doc/ES1Status.md ### Platform support via backing renderers -| | Direct3D 9 | Direct3D 11 | Desktop GL | GL ES | Vulkan | Metal | -|-------------:|:--------------:|:--------------:|:-------------:|:-----------:|:-----------:|:--------------------:| -| Windows | complete | complete | complete | complete | complete | | -| Linux | | | complete | | complete | | -| Mac OS X | | | complete | | | complete [1] | -| iOS | | | | | | complete [2] | -| Chrome OS | | | | complete | planned | | -| Android | | | | complete | complete | | -| GGP (Stadia) | | | | | complete | | -| Fuchsia | | | | | complete | | +| | Direct3D 9 | Direct3D 11 | Desktop GL | GL ES | Vulkan | Metal | WebGPU | +|-------------:|:--------------:|:--------------:|:-------------:|:-----------:|:-----------:|:--------------------:|:----------:| +| Windows | complete | complete | complete | complete | complete | | | +| Linux | | | complete | | complete | | | +| Mac OS X | | | complete | | | complete [1] | | +| iOS | | | | | | complete [2] | | +| Chrome OS | | | | complete | planned | | | +| Android | | | | complete | complete | | | +| Fuchsia | | | | | complete | | | [1] Metal is supported on macOS 10.14+ diff --git a/WATCHLISTS b/WATCHLISTS index f0e7d8a3a0e..f7e80956f66 100644 --- a/WATCHLISTS +++ b/WATCHLISTS @@ -10,6 +10,9 @@ { 'WATCHLIST_DEFINITIONS': { + 'angle-features': { + 'filepath': 'util/autogen/angle_features_autogen.h', + }, 'vulkan': { 'filepath': 'src/libANGLE/renderer/vulkan/', }, @@ -19,6 +22,10 @@ # Please keep alphabetical ############################################################################## 'WATCHLISTS': { + 'angle-features': [ + 'kaiyili+angleWatchAngleFeatures@google.com', + 'battlestar-gfx@google.com' + ], 'vulkan': ['cclao+angleWatchVk@google.com'], }, } diff --git a/build b/build index dc7b3561cdb..5ef0c4e7818 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit dc7b3561cdb982e8961e0f9930bb0bd532722625 +Subproject commit 5ef0c4e7818b1c50ec4673d1981338ef14135dfa diff --git a/build_overrides/angle.gni b/build_overrides/angle.gni index dcd98eb8f99..3bbc995b93a 100644 --- a/build_overrides/angle.gni +++ b/build_overrides/angle.gni @@ -21,3 +21,7 @@ angle_vulkan_memory_allocator_dir = "//third_party/vulkan_memory_allocator" angle_clspv_dir = "//third_party/clspv" angle_llvm_dir = "//third_party/llvm/src" angle_dawn_dir = "//third_party/dawn" + +# Embedder override for `-fsanitize=array-bounds` +# (see https://crbug.com/386992829) +angle_sanitize_array_bounds = false diff --git a/build_overrides/build.gni b/build_overrides/build.gni index a35323b5b5a..d7f893135dc 100644 --- a/build_overrides/build.gni +++ b/build_overrides/build.gni @@ -11,9 +11,6 @@ declare_args() { # If true, it assumes that //third_party/abseil-cpp is an available # dependency for googletest. gtest_enable_absl_printers = false - - # Set to default here so that it can be set via gn args - use_cxx17 = false } if (host_os == "mac" && use_system_xcode == "") { diff --git a/build_overrides/protobuf.gni b/build_overrides/protobuf.gni new file mode 100644 index 00000000000..8561ab799ee --- /dev/null +++ b/build_overrides/protobuf.gni @@ -0,0 +1,6 @@ +# Copyright 2025 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. + +# No overrides currently specified, because the defaults work fine for +# ANGLE diff --git a/build_overrides/vulkan_common.gni b/build_overrides/vulkan_common.gni index 61ccf73adda..ceb96a17fb6 100644 --- a/build_overrides/vulkan_common.gni +++ b/build_overrides/vulkan_common.gni @@ -10,4 +10,5 @@ vulkan_data_subdir = angle_data_dir vulkan_gen_subdir = "angle/vulkan" vulkan_use_x11 = angle_use_x11 +vulkan_no_xlib_headers = true vulkan_use_wayland = angle_use_wayland diff --git a/buildtools b/buildtools index 6377d6649b0..6a18683f555 160000 --- a/buildtools +++ b/buildtools @@ -1 +1 @@ -Subproject commit 6377d6649b0a2160ab8bb0b88d3cc64e3fd897cf +Subproject commit 6a18683f555b4ac8b05ac8395c29c84483ac9588 diff --git a/doc/BecomingCommitter.md b/doc/BecomingCommitter.md index 31ec0445f5f..e0663022355 100644 --- a/doc/BecomingCommitter.md +++ b/doc/BecomingCommitter.md @@ -36,6 +36,8 @@ In some cases the process could drag out slightly. Ping OWNERs and keep writing patches! Even in the rare cases where a nomination fails, the objection is usually something easy to address like “more patches” or “not enough people are familiar with this person’s work.” +Two-factor authentication with a security key is a requirement for adding your account as a committer. If you haven't done so already, you'll need to set up a security key on your account. For more information about this requirement see [Gerrit ReAuth](https://chromium.googlesource.com/chromium/src/+/main/docs/gerrit_reauth.md). + ## Maintaining committer status You don't really need to do much to maintain committer status: just keep being awesome and helping the ANGLE project! diff --git a/doc/CaptureAndReplay.md b/doc/CaptureAndReplay.md index 0da7335df8f..e8714f202f8 100644 --- a/doc/CaptureAndReplay.md +++ b/doc/CaptureAndReplay.md @@ -52,9 +52,9 @@ Some simple environment variables control frame capture: * Results in filenames like this: ``` foo.angledata.gz - foo_context1_001.cpp - foo_context1_002.cpp - foo_context1_003.cpp + foo_context1_0001.cpp + foo_context1_0002.cpp + foo_context1_0003.cpp foo_context1.cpp foo_context1.h foo.json @@ -63,6 +63,10 @@ Some simple environment variables control frame capture: ``` * `ANGLE_CAPTURE_SERIALIZE_STATE`: * Set to `1` to enable GL state serialization. Default is `0`. + * `ANGLE_CAPTURE_MAX_RESIDENT_BINARY_SIZE=`: + * Maximum binary data storage space in bytes. Must be a power of 2. Default is 2GB with a useful range of 512MB-4GB. + * `ANGLE_CAPTURE_BLOCK_SIZE=`: + * Block size for binary data, in bytes. Must be a power of 2. Default is 256MB, with a useful range of 32-512MB A good way to test out the capture is to use environment variables in conjunction with the sample template. For example: @@ -102,9 +106,9 @@ Place all the trace output files into it. For example, if the label was `deskto ``` src/tests/restricted_traces$ ls -1 desktop_test/ desktop_test.angledata.gz -desktop_test_context1_001.cpp -desktop_test_context1_002.cpp -desktop_test_context1_003.cpp +desktop_test_context1_0001.cpp +desktop_test_context1_0002.cpp +desktop_test_context1_0003.cpp desktop_test_context1.cpp desktop_test_context1.h desktop_test.json diff --git a/doc/DevSetup.md b/doc/DevSetup.md index 6114bb5de00..635fe1349d0 100644 --- a/doc/DevSetup.md +++ b/doc/DevSetup.md @@ -58,7 +58,10 @@ On Linux only, you need to install all the necessary dependencies before going f If building for Android (which requires Linux), switch to the [Android steps](https://chromium.googlesource.com/angle/angle.git/+/HEAD/doc/DevSetupAndroid.md) at this point. -After this completes successfully, you are ready to generate the ninja files: +### Building the code + +After the above completes successfully, you are ready to generate the ninja +files: ``` gn gen out/Debug ``` @@ -81,6 +84,10 @@ angle_assert_always_on = true/false (enables release asserts and runtime debug is_clang = false (NOT RECOMMENDED) (to use system default compiler instead of clang) ``` +When building with clang, we expect the build to run against a copy of clang +that includes the chrome clang plugin. To build against an ordinary copy of +clang lacking this plugin, set `clang_use_chrome_plugins = false`. + For a release build run `gn args out/Release` and set `is_debug = false`. Optionally set `angle_assert_always_on = true` for Release testing. diff --git a/doc/ES31StatusOnD3D11.md b/doc/ES31StatusOnD3D11.md deleted file mode 100644 index 2a8e1b8525e..00000000000 --- a/doc/ES31StatusOnD3D11.md +++ /dev/null @@ -1,31 +0,0 @@ -# ES31 Status on Direct3D 11 - -| New Features | Status | Limitations | -|:---------------------------------------------------|:-----------------------------|:------------| -| Arrays of arrays (shading language only) | Fully implemented | None | -| Compute shaders | Fully implemented | None | -| Explicit uniform location | Fully implemented | None | -| Framebuffers with no attachments | Fully implemented | None | -| Indirect draw commands | Fully implemented | None | -| Multisample formats for immutable textures | Fully implemented | None | -| Program interface queries | Fully implemented | None | -| Shader bitfield operations (shading language only) | Fully implemented | None | -| Shader layout binding (shading language only) | Fully implemented | None | -| Texture gather operations | Fully implemented | None | -| Vertex attribute binding | Fully implemented | None | -| Atomic counters | Implemented with limitations | Atomic counters in non-compute shaders are not implemented yet. | -| Shader image load/store operations | Implemented with limitations | See notes [1] [below](#notes-1) | -| Shader storage buffer objects | Implemented with limitations | See notes [2] [below](#notes-2) | -| Shader helper invocation (shading language only) | Hard to implement | The equivalent of gl_HelperInvocation is WaveIsHelperLane which requres SM6. | -| Separate shader objects | Unimplemented | It can be implemented with medium complexity. | -| Stencil texturing | Unimplemented | It can be implemented with medium complexity. Refer [here](https://stackoverflow.com/questions/34601325/directx11-read-stencil-bit-from-compute-shader). | - -### Notes [1] -* Images in non-compute shaders are not implemented yet. -* Multiple image variables are not allowed to be bound to the same image unit which refers to the same layer and level of a texture image. It means image aliasing is not supported. -* The same layer and level of a texture are not allowed to be bound to multiple image units. -* When a texture is bound to an image unit, the image unit format must exactly match the texture internal format. Similarly, the format layout qualifier for an image variable must exactly match the format of the image unit. Re-interpretation is not supported. See [here](http://anglebug.com/42261723). - -### Notes [2] -* Shader storage blocks in non-compute shaders are not implemented yet. -* Multiple shader storage blocks are not allowed to be bound to the same buffer. See [here](http://anglebug.com/42261718). diff --git a/doc/ExtensionSupport.md b/doc/ExtensionSupport.md index e85bc81fa20..e0d20cea71e 100644 --- a/doc/ExtensionSupport.md +++ b/doc/ExtensionSupport.md @@ -68,6 +68,7 @@ using data from registry_xml.py and gl.xml. | [GL_OES_draw_buffers_indexed](https://khronos.org/registry/OpenGL/extensions/OES/OES_draw_buffers_indexed.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_draw_elements_base_vertex](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_draw_elements_base_vertex.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_OES_draw_elements_base_vertex](https://khronos.org/registry/OpenGL/extensions/OES/OES_draw_elements_base_vertex.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| [GL_EXT_draw_instanced](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_draw_instanced.txt) | | | | | | | | | [GL_OES_EGL_image](https://khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_EGL_image_array](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_EGL_image_array.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_OES_EGL_image_external](https://khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -84,6 +85,9 @@ using data from registry_xml.py and gl.xml. | [GL_NV_fence](https://khronos.org/registry/OpenGL/extensions/NV/NV_fence.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_float_blend](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_float_blend.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | [GL_EXT_frag_depth](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_frag_depth.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| [GL_EXT_fragment_shading_rate](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_fragment_shading_rate.txt) | | | | | | | | +| [GL_EXT_fragment_shading_rate_attachment](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_fragment_shading_rate_attachment.txt) | | | | | | | | +| [GL_EXT_fragment_shading_rate_primitive](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_fragment_shading_rate_primitive.txt) | | | | | | | | | [GL_ANGLE_framebuffer_blit](https://khronos.org/registry/OpenGL/extensions/ANGLE/ANGLE_framebuffer_blit.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_NV_framebuffer_blit](https://khronos.org/registry/OpenGL/extensions/NV/NV_framebuffer_blit.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_MESA_framebuffer_flip_y](https://khronos.org/registry/OpenGL/extensions/MESA/MESA_framebuffer_flip_y.txt) | | | | | | | | @@ -99,12 +103,14 @@ using data from registry_xml.py and gl.xml. | [GL_EXT_map_buffer_range](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_map_buffer_range.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_memory_object](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_memory_object.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_memory_object_fd](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_external_objects_fd.txt) | | | ✔ | ✔ | | ✔ | ✔ | +| [GL_EXT_multi_draw_arrays](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_multi_draw_arrays.txt) | | | | | | | | | [GL_EXT_multi_draw_indirect](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_multi_draw_indirect.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_multisample_compatibility](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_multisample_compatibility.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_multisampled_render_to_texture](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_multisampled_render_to_texture.txt) | | | | | | | | | [GL_EXT_multisampled_render_to_texture2](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_multisampled_render_to_texture2.txt) | | | | | | | | | [GL_OVR_multiview](https://khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_OVR_multiview2](https://khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview2.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| [GL_OVR_multiview_multisampled_render_to_texture](https://khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview_multisampled_render_to_texture.txt) | | | | | | | | | [GL_KHR_no_error](https://khronos.org/registry/OpenGL/extensions/KHR/KHR_no_error.txt) | | | | | | | | | [GL_EXT_occlusion_query_boolean](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_occlusion_query_boolean.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_OES_packed_depth_stencil](https://khronos.org/registry/OpenGL/extensions/OES/OES_packed_depth_stencil.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -149,13 +155,13 @@ using data from registry_xml.py and gl.xml. | [GL_EXT_shader_non_constant_global_initializers](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_shader_non_constant_global_initializers.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_NV_shader_noperspective_interpolation](https://khronos.org/registry/OpenGL/extensions/NV/NV_shader_noperspective_interpolation.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_shader_texture_lod](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_shader_texture_lod.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| [GL_EXT_shader_texture_samples](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_shader_texture_samples.txt) | | | | | | | | | [GL_QCOM_shading_rate](https://khronos.org/registry/OpenGL/extensions/QCOM/QCOM_shading_rate.txt) | | | | | | | | | [GL_EXT_shadow_samplers](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_shadow_samplers.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_sRGB](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_sRGB.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_sRGB_write_control](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_sRGB_write_control.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_OES_standard_derivatives](https://khronos.org/registry/OpenGL/extensions/OES/OES_standard_derivatives.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_OES_surfaceless_context](https://khronos.org/registry/OpenGL/extensions/OES/OES_surfaceless_context.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| [GL_ARB_sync](https://khronos.org/registry/OpenGL/extensions/ARB/ARB_sync.txt) | | | | | | | | | [GL_EXT_tessellation_shader](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_tessellation_shader.txt) | ✔ | ✔ | ✔ | ✔ | | | ✔ | | [GL_OES_tessellation_shader](https://khronos.org/registry/OpenGL/extensions/OES/OES_tessellation_shader.txt) | | | | | | | | | [GL_OES_texture_3D](https://khronos.org/registry/OpenGL/extensions/OES/OES_texture_3D.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -201,6 +207,7 @@ using data from registry_xml.py and gl.xml. | [GL_EXT_texture_storage_compression](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_storage_compression.txt) | | | | | | | | | [GL_OES_texture_storage_multisample_2d_array](https://khronos.org/registry/OpenGL/extensions/OES/OES_texture_storage_multisample_2d_array.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_EXT_texture_type_2_10_10_10_REV](https://khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_type_2_10_10_10_REV.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| [GL_ARM_texture_unnormalized_coordinates](https://khronos.org/registry/OpenGL/extensions/ARM/ARM_texture_unnormalized_coordinates.txt) | | | | | | | | | [GL_ANGLE_texture_usage](https://khronos.org/registry/OpenGL/extensions/ANGLE/ANGLE_texture_usage.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | [GL_QCOM_tiled_rendering](https://khronos.org/registry/OpenGL/extensions/QCOM/QCOM_tiled_rendering.txt) | | | | | | | | | [GL_ANGLE_translated_shader_source](https://khronos.org/registry/OpenGL/extensions/ANGLE/ANGLE_translated_shader_source.txt) | | | | | | | | @@ -261,7 +268,6 @@ using data from registry_xml.py and gl.xml. | [GL_ANGLE_shader_pixel_local_storage](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/ANGLE_shader_pixel_local_storage.txt) | | | | | | | | | [GL_ANGLE_shader_pixel_local_storage_coherent](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/ANGLE_shader_pixel_local_storage.txt) | | | | | | | | | [GL_ANGLE_stencil_texturing](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/ANGLE_stencil_texturing.txt) | | | | | | | | -| [GL_CHROMIUM_sync_query](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/CHROMIUM_sync_query.txt) | | | | | | | | | [GL_ANGLE_texture_compression_dxt3](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/ANGLE_texture_compression_dxt3.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | | | | [GL_ANGLE_texture_compression_dxt5](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/ANGLE_texture_compression_dxt5.txt) | ✔ | ✔ | ✔ | ✔ | ✔ | | | | [GL_ANGLE_texture_external_update](https://chromium.googlesource.com/angle/angle/+/refs/heads/main/extensions/ANGLE_texture_external_update.txt) | | | | | | | | diff --git a/doc/Orientation.md b/doc/Orientation.md index fc34339ecbe..7325c838744 100644 --- a/doc/Orientation.md +++ b/doc/Orientation.md @@ -85,7 +85,7 @@ A basic guide to get up and running fixing bugs and performance issues in ANGLE. Right-click "Targets" and add `angle_perftests` as a Target Project. - Run `angle_perftests` with the flag `--gtest_filter=DrawCallPerfBenchmark.Run/d3d11_null` for - D3D11, `.../d3d9_null` for D3D9, `.../gl_null` for OpenGL and `.../vulkan_null` for Vulkan. + D3D11, `.../d3d9_null` for D3D9, and `.../vulkan_null` for Vulkan. - Make sure you close all open instances of Chrome, they use a lot of background CPU and GPU. In fact, close every process and application you can. diff --git a/dotfile_settings.gni b/dotfile_settings.gni index 91b2b34d6c3..d27fae199a7 100644 --- a/dotfile_settings.gni +++ b/dotfile_settings.gni @@ -7,8 +7,4 @@ angle_dotfile_settings = { exec_script_allowlist = [ get_path_info("BUILD.gn", "abspath") ] - - # TODO(crbug.com/389986807) - move other clients to `exec_script_allowlist` - # so that we don't need to keep supporting `exec_script_whitelist`. - exec_script_whitelist = exec_script_allowlist } diff --git a/extensions/ANGLE_rgbx_internal_format.txt b/extensions/ANGLE_rgbx_internal_format.txt index 4f77f27fbf2..8048d2787ec 100644 --- a/extensions/ANGLE_rgbx_internal_format.txt +++ b/extensions/ANGLE_rgbx_internal_format.txt @@ -48,6 +48,7 @@ Overview glTexSubImage* will accept the following format+type combinations: 1. format = GL_RGB, type = GL_UNSIGNED_BYTE + 2. format = GL_RGBA, type = GL_UNSIGNED_BYTE New Types diff --git a/extensions/ANGLE_shader_pixel_local_storage.txt b/extensions/ANGLE_shader_pixel_local_storage.txt index b447662688c..634d8418a2e 100644 --- a/extensions/ANGLE_shader_pixel_local_storage.txt +++ b/extensions/ANGLE_shader_pixel_local_storage.txt @@ -70,6 +70,8 @@ Dependencies This extension interacts with EXT_polygon_offset_clamp. + This extension interacts with EXT_texture_cube_map_array. + This extension interacts with KHR_blend_equation_advanced. This extension interacts with KHR_debug. @@ -82,8 +84,14 @@ Dependencies This extension interacts with OES_sample_variables. + This extension interacts with OES_texture_cube_map_array. + + This extension interacts with QCOM_tiled_rendering. + This extension interacts with OpenGL ES 3.1. + This extension interacts with OpenGL ES 3.2. + This extension interacts with GLSL ES 3.10. Overview @@ -137,6 +145,12 @@ Overview synchronously and in API primitive order. No barriers are required and render passes can emit overlapping fragments. + Because raster ordering may come at a performance cost on some + platforms, an application may opt out of coherent pixel local storage + by using the "noncoherent" layout qualifier on a plane-by-plane basis. + When using "noncoherent", the former restrictions and barrier + requirements apply. + Some implementations may support GL_ANGLE_shader_pixel_local_storage without supporting GL_ANGLE_shader_pixel_local_storage_coherent. @@ -192,43 +206,32 @@ New Tokens Accepted by the parameter of GetIntegerv(): MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE 0x96E0 - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE 0x96E1 - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE 0x96E2 - PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE 0x96E3 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE 0x96E1 + PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE 0x96E2 Accepted as array elements in the parameter of BeginPixelLocalStorageANGLE(): - LOAD_OP_ZERO_ANGLE 0x96E4 - LOAD_OP_CLEAR_ANGLE 0x96E5 - LOAD_OP_LOAD_ANGLE 0x96E6 + LOAD_OP_ZERO_ANGLE 0x96E3 + LOAD_OP_CLEAR_ANGLE 0x96E4 + LOAD_OP_LOAD_ANGLE 0x96E5 Accepted as array elements in the parameter of EndPixelLocalStorageANGLE(): - STORE_OP_STORE_ANGLE 0x96E7 - - Accepted by the parameter of - GetFramebufferPixelLocalStorageParameterivANGLE() and - GetFramebufferPixelLocalStorageParameterivRobustANGLE(): - - PIXEL_LOCAL_FORMAT_ANGLE 0x96E8 - PIXEL_LOCAL_TEXTURE_NAME_ANGLE 0x96E9 - PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE 0x96EA - PIXEL_LOCAL_TEXTURE_LAYER_ANGLE 0x96EB - - Accepted by the parameter of - GetFramebufferPixelLocalStorageParameterfvANGLE() and - GetFramebufferPixelLocalStorageParameterfvRobustANGLE(): - - PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE 0x96EC + STORE_OP_STORE_ANGLE 0x96E6 Accepted by the parameter of - GetFramebufferPixelLocalStorageParameterivANGLE() and - GetFramebufferPixelLocalStorageParameterivRobustANGLE(): + GetFramebufferPixelLocalStorageParameter{f,i}vANGLE() and + GetFramebufferPixelLocalStorageParameter{f,i}vRobustANGLE(): - PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE 0x96ED - PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE 0x96EE + PIXEL_LOCAL_FORMAT_ANGLE 0x96E7 + PIXEL_LOCAL_TEXTURE_NAME_ANGLE 0x96E8 + PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE 0x96E9 + PIXEL_LOCAL_TEXTURE_LAYER_ANGLE 0x96EA + PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE 0x96EB + PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE 0x96EC + PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE 0x96ED New GLSL Opaque Types @@ -280,6 +283,8 @@ Additions to the OpenGL ES Specification, Version 3.0.6 plane to 0. This is recommended over LOAD_OP_CLEAR_ANGLE, as it is more likely to be performant on all implementations. + This clear is executed regardless of + RASTERIZER_DISCARD state. LOAD_OP_CLEAR_ANGLE Clear the pixel local storage plane to its framebuffer's ith clear value of corresponding @@ -291,6 +296,8 @@ Additions to the OpenGL ES Specification, Version 3.0.6 of the clear value is too large to be represented in the plane's internalformat, it is clamped. + This clear is executed regardless of + RASTERIZER_DISCARD state. LOAD_OP_LOAD_ANGLE Load the contents of the bound texture image into pixel local storage. This Load Operation @@ -344,10 +351,10 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_OPERATION is generated if DITHER is enabled. - * INVALID_OPERATION is generated if RASTERIZER_DISCARD is enabled. - * INVALID_OPERATION is generated if TRANSFORM_FEEDBACK_ACTIVE is TRUE. + * INVALID_OPERATION is generated if QCOM_tiled_rendering is active. + * INVALID_OPERATION is generated if BLEND_DST_ALPHA, BLEND_DST_RGB, BLEND_SRC_ALPHA, or BLEND_SRC_RGB, for any draw buffer, is a blend function requiring the secondary color input, as specified in @@ -361,12 +368,6 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_VALUE is generated if < 1 or > MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. - * INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has - an image attached to any color attachment point on or after: - - COLOR_ATTACHMENT0 + - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE - * INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to any color attachment point on or after: @@ -400,12 +401,16 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_OPERATION is generated if the draw framebuffer has no attachments and no enabled, texture-backed pixel local storage planes. - * INVALID_OPERATION is generated if a single texture image is bound to + * INVALID_OPERATION is generated if, for any enabled backing texture, the + mipmap level bound to pixel local storage is outside the effective + base/max range of that texture. + + * INVALID_OPERATION is generated if a single texture slice is bound to more than one active pixel local storage plane. - * INVALID_OPERATION is generated if a single texture image is - simultaneously bound to a pixel local storage plane and attached to the - draw framebuffer. + * INVALID_OPERATION is generated if a single texture slice is + simultaneously bound to an active pixel local storage plane and attached + to an enabled drawbuffer. Errors generated by EndPixelLocalStorageANGLE(): @@ -432,150 +437,58 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is updated to equal . - * BLEND is disabled and COLOR_WRITEMASK is updated to {TRUE, TRUE, TRUE, - TRUE} for all draw buffers whose index is >= , where: - - = min( - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE, - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ) + * OpenGL ES 3.1, implementation-dependent: FRAMEBUFFER_DEFAULT_WIDTH and + FRAMEBUFFER_DEFAULT_HEIGHT may reflect the dimensions of the pixel local + storage planes, instead of their original values. This will last until + pixel local storage ends. Pixel local storage data will persist across all fragment invocations and across all draws issued until the application calls - EndPixelLocalStorageANGLE(), even if the application binds different shader - programs. In order to make this guarantee, the the OpenGL ES API only allows - a limited set of commands while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is - nonzero. All other commands generate INVALID_OPERATION. Valid commands while - pixel local storage is active are listed in Table X.3. - - ActiveTexture - BindBuffer - BindBufferBase - BindBufferRange - BindFramebuffer - BindSampler - BindTexture - BindVertexArray - BlendEquationSeparatei* - BlendEquationi* - BlendFuncSeparatei* - BlendFunci* - BufferData - BufferSubData - CheckFramebufferStatus - ClearBuffer* - ClipControlEXT - ColorMaski* - CullFace - DebugMessageCallback* - DebugMessageControl* - DebugMessageInsert* - Delete* - DepthFunc - DepthMask - DepthRangef - Disable - DisableVertexAttribArray - Disablei* - DispatchComputeIndirect - DrawArrays* - DrawBuffers - DrawElements* - DrawRangeElements* - Enable - EnableClientState - EnableVertexAttribArray - Enablei* - EndPixelLocalStorageANGLE - FlushMappedBufferRange - FramebufferMemorylessPixelLocalStorageANGLE - FramebufferParameter* - FramebufferPixelLocalStorageInterruptANGLE - FramebufferRenderbuffer - FramebufferTexture* - FrontFace - Gen* - Get* - Is* - MapBufferRange - ObjectLabel* - ObjectPtrLabel* - PixelLocalStorageBarrierANGLE - PolygonMode* - PolygonOffset* - PopDebugGroup* - ProvokingVertexANGLE - PushDebugGroup* - SamplerParameter* - Scissor - StencilFunc - StencilFuncSeparate - StencilMask - StencilMaskSeparate - StencilOp - StencilOpSeparate - TexParameter* - Uniform* - UnmapBuffer - UseProgram - ValidateProgram - VertexAttrib* - Viewport - - Table X.3: Valid commands while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE - is nonzero. - - Additional restrictions also go into effect while - PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero: + EndPixelLocalStorageANGLE(), or until a command is issued that implicitly + destroys the active render pass. - * Calls that modify the current draw framebuffer, or change the - DRAW_FRAMEBUFFER_BINDING, end pixel local storage implicitly with - of STORE_OP_STORE_ANGLE. + When a command destroys the active render pass, it is as if + EndPixelLocalStorageANGLE() had been called with + =PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE and of + STORE_OP_STORE_ANGLE. These commands are defined as: - e.g., BindFramebuffer, DrawBuffers, FramebufferTexture2D, - FramebufferTextureLayer, FramebufferRenderbuffer, - FramebufferParameteri, FramebufferTexturePixelLocalStorageANGLE, - FramebufferMemorylessPixelLocalStorageANGLE, etc. (When is - FRAMEBUFFER or DRAW_FRAMEBUFFER, or when the framebuffer object being - modified is the draw framebuffer whose pixel local storage is currently - active). + * Commands that modify the framebuffer in any way, or change any + framebuffer binding. - * INVALID_OPERATION is generated by Enable(), Disable() if is not - one of: BLEND, CULL_FACE, DEBUG_OUTPUT, DEBUG_OUTPUT_SYNCHRONOUS, - DEPTH_CLAMP_EXT, DEPTH_TEST, POLYGON_OFFSET_POINT_NV, - POLYGON_OFFSET_LINE_NV, POLYGON_OFFSET_LINE_ANGLE, POLYGON_OFFSET_FILL, - PRIMITIVE_RESTART_FIXED_INDEX, SCISSOR_TEST, SCISSOR_TEST_EXCLUSIVE_NV, - STENCIL_TEST, CLIP_DISTANCE[0..7]_EXT + e.g., BindFramebuffer, DeleteTextures/DeleteRenderbuffers (if + destroying an object attached to the draw framebuffer), DrawBuffers, + FramebufferTexture*, FramebufferRenderbuffer, FramebufferParameteri, + FramebufferMemorylessPixelLocalStorageANGLE, etc. - * Calls to ClearBuffer{f,i,ui}v() are ignored if is COLOR and any - of the following are true: + * Commands that transfer pixels in or out of the framebuffer. - >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE - >= - (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE) + e.g., ReadPixels, BlitFramebuffer, CopyTexImage2D, CopyTexSubImage*, + etc. - * Calls to EnableiOES(BLEND, ) and ColorMaskiOES(, ...) are ignored - if any of the following are true: + * Commands that invalidate tiled memory. - >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE - >= (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE) + e.g., DiscardFramebufferEXT, InvalidateFramebuffer, + InvalidateSubFramebuffer, etc. - * Calls to Enable(BLEND) and ColorMask() only update state on draw buffers - whose index is less than , where: + * BeginTransformFeedback + * StartTilingQCOM - = min( - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE, - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE); + In order to guarantee that pixel local storage contents remain valid, + additional restrictions go into effect while + PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero: - i.e., their behavior is overridden to the equivalence of: + * INVALID_OPERATION is generated by calls that would modify an active + pixel local storage backing texture. - for (int i = 0; i < ; ++i) - EnableiOES(BLEND, i) + e.g., TexSubImage*, TexParameter*, GenerateMipmap, + InvalidateTextureANGLE, etc. - for (int i = 0; i < ; ++i) - ColorMaskiOES(i, ...) + * INVALID_OPERATION is generated by Enable(), Disable() if is not + one of: BLEND, CULL_FACE, DEBUG_OUTPUT, DEBUG_OUTPUT_SYNCHRONOUS, + DEPTH_CLAMP_EXT, DEPTH_TEST, POLYGON_OFFSET_POINT_NV, + POLYGON_OFFSET_LINE_NV, POLYGON_OFFSET_LINE_ANGLE, POLYGON_OFFSET_FILL, + PRIMITIVE_RESTART_FIXED_INDEX, RASTERIZER_DISCARD, SCISSOR_TEST, + SCISSOR_TEST_EXCLUSIVE_NV, STENCIL_TEST, CLIP_DISTANCE[0..7]_EXT * INVALID_OPERATION is generated by Enablei*(), Disablei*() if is not one of: BLEND, SCISSOR_TEST, SCISSOR_TEST_EXCLUSIVE_NV @@ -588,9 +501,6 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_OPERATION is generated by BlendEquation*() if is one of the advanced blend equations defined in KHR_blend_equation_advanced. - * INVALID_OPERATION is generated if a draw is issued with a fragment - shader that accesses a texture bound to pixel local storage. - * INVALID_OPERATION is generated if a draw is issued with a fragment shader that has a pixel local uniform bound to an inactive pixel local storage plane. @@ -608,7 +518,15 @@ Additions to the OpenGL ES Specification, Version 3.0.6 shader that has a pixel local storage uniform whose format layout qualifier does not identically match the internalformat of its associated pixel local storage plane on the current draw framebuffer, as - enumerated in Table X.4. + enumerated in Table X.3. + + * INVALID_OPERATION is generated if a draw is issued while either of the + following two constraints are violated: + + (a) If the fragment shader declares index zero output, then attachment + zero must be present, and have a compatible numeric type. + + (b) If attachment zero is present, it must be enabled. Because of the "implementation-dependent" clause of the framebuffer completeness test, and because a pixel local storage implementation may add @@ -627,10 +545,10 @@ Additions to the OpenGL ES Specification, Version 3.0.6 Section 2.X.1 "Non-coherent Pixel Local Storage" - When GL_ANGLE_shader_pixel_local_storage_coherent is _not_ supported, and - pixel local storage is active, applications must also split their rendering - of pixel local storage into separate passes, none of which touch an - individual pixel more than once. The command: + When GL_ANGLE_shader_pixel_local_storage_coherent is _not_ supported, or + when accessing planes that use the "noncoherent" layout qualifier, + applications must split their rendering of pixel local storage into separate + passes, none of which touch an individual pixel more than once. The command: void PixelLocalStorageBarrierANGLE() @@ -695,6 +613,13 @@ Additions to the OpenGL ES Specification, Version 3.0.6 framebuffer entered an interrupted state. This command is ignored when the default framebuffer object name 0 is bound. + Modify Section 3.8.10.3 "Rendering Feedback Loops" + + (Modify the second bullet point) + + * The texture is attached to one of the attachment points or active pixel + local storage planes, A, of framebuffer object F + Modify Section 4.4.2 "Attaching Images to Framebuffer Objects" (Add a new paragraph to 4.4.2.3 "Attaching Renderbuffer Images to a @@ -737,7 +662,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * identifies the pixel local storage plane index. - * selects the data format, as enumerated in Table X.4. + * selects the data format, as enumerated in Table X.3. internalformat Clear Value Type Pixel Local Type format qualifier ----------------------------------------------------------------------- @@ -745,18 +670,16 @@ Additions to the OpenGL ES Specification, Version 3.0.6 RGBA8I INT ipixelLocalANGLE rgba8i RGBA8UI UNSIGNED_INT upixelLocalANGLE rgba8ui R32F FLOAT pixelLocalANGLE r32f + R32I INT ipixelLocalANGLE r32i R32UI UNSIGNED_INT upixelLocalANGLE r32ui - Table X.4: Supported pixel local storage internalformats, with the Clear + Table X.3: Supported pixel local storage internalformats, with the Clear Value Type used by BeginPixelLocalStorageANGLE(), and their required corresponding GLSL Pixel Local Type and format layout qualifier. Note that all pixel local storage formats consume exactly 4 bytes of storage. - Note that r32i is excluded from this table because it is not supported - by EXT_shader_pixel_local_storage. - Errors: * INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer @@ -773,7 +696,10 @@ Additions to the OpenGL ES Specification, Version 3.0.6 < 0 or >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. * INVALID_ENUM is generated if is not one of the - acceptable values in Table X.4, or NONE. + acceptable values in Table X.3, or NONE. + + * INVALID_OPERATION is generated if is not NONE and not + color-renderable. If is NONE, the pixel local storage plane at index is deinitialized and any internal storage is released. @@ -822,6 +748,12 @@ Additions to the OpenGL ES Specification, Version 3.0.6 - Zero if is a TEXTURE_2D - The array index to bind if is a TEXTURE_2D_ARRAY + - The cube map face index to bind if is a + TEXTURE_CUBE_MAP; indices zero to five correspond to the following + cube map faces: +X, -X, +Y, -Y, +Z, -Z + - The cube map array layer-face index to bind if is a + TEXTURE_CUBE_MAP_ARRAY_EXT, TEXTURE_CUBE_MAP_ARRAY_OES, or + TEXTURE_CUBE_MAP_ARRAY Errors: @@ -842,7 +774,9 @@ Additions to the OpenGL ES Specification, Version 3.0.6 existing immutable texture object, or zero. * INVALID_OPERATION is generated if is nonzero and not of - type TEXTURE_2D or TEXTURE_2D_ARRAY. + type TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP, + TEXTURE_CUBE_MAP_ARRAY_EXT, TEXTURE_CUBE_MAP_ARRAY_OES, or + TEXTURE_CUBE_MAP_ARRAY. * INVALID_VALUE is generated if is nonzero and < 0. @@ -857,7 +791,10 @@ Additions to the OpenGL ES Specification, Version 3.0.6 >= the immutable number of texture layers in . * INVALID_ENUM is generated if is nonzero and its - internalformat is not one of the acceptable values in Table X.4. + internalformat is not one of the acceptable values in Table X.3. + + * INVALID_OPERATION is generated if is nonzero and its + internalformat is not color-renderable. If is 0, and are ignored and the pixel local storage plane is deinitialized. @@ -881,7 +818,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 clear values: a 4-component vector of type FLOAT, INT, and UNSIGNED_INT. When the Load Operation LOAD_OP_CLEAR_ANGLE is executed, a pixel local storage plane is cleared to the value whose type corresponds to its - internalformat. (See Table X.4.) Clear values are set with the commands: + internalformat. (See Table X.3.) Clear values are set with the commands: void FramebufferPixelLocalClearValuefvANGLE(int plane, const float value[]) @@ -926,14 +863,10 @@ Additions to the OpenGL ES Specification, Version 3.0.6 void GetFramebufferPixelLocalStorageParameterfvANGLE(int plane, enum pname, - GLsizei bufSize, - GLsizei *length, GLfloat *params) void GetFramebufferPixelLocalStorageParameterivANGLE(int plane, enum pname, - GLsizei bufSize, - GLsizei *length, GLint *params) Parameters: @@ -949,7 +882,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 Description: * If is PIXEL_LOCAL_FORMAT_ANGLE, will contain the - internalformat of the plane from Table X.4, or NONE if the selected + internalformat of the plane from Table X.3, or NONE if the selected pixel local storage plane is in a deinitialized state. * If is PIXEL_LOCAL_TEXTURE_NAME_ANGLE, will contain the @@ -978,16 +911,10 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is bound to DRAW_FRAMEBUFFER. - * INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the - draw framebuffer is in an interrupted state. (See section 2.X.2 - "Interrupting Pixel Local Storage") - * INVALID_VALUE is generated if < 0 or >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. - * INVALID_ENUM is generated if is not in Table 6.Y, or if the - command issued is not the associated "Get Command" for in Table - 6.Y. + * INVALID_ENUM is generated if is not in Table 6.Y. * INVALID_VALUE is generated if is NULL. @@ -1031,18 +958,11 @@ Additions to the OpenGL ES Specification, Version 3.0.6 MAX_PIXEL_LOCAL_STORAGE- _PLANES_ANGLE Z+ GetIntegerv 4 4.4.2.X - MAX_COLOR_ATTACHMENTS_WITH- - _ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE Z+ GetIntegerv *0! 2.X - MAX_COMBINED_DRAW_BUFFERS_AND- _PIXEL_LOCAL_STORAGE_PLANES_ANGLE Z+ GetIntegerv 4 2.X Table 6.X: Impementation Dependent Pixel Local Storage Limits - Note that MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE may be - zero, in which case the application cannot render to any other color - attachments while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero. - Initial Get Value Type Get Command Value Sec. -------------------------------------------------------------------------- @@ -1081,16 +1001,16 @@ Interactions with the ANGLE_request_extension specification * OES_draw_buffers_indexed * EXT_draw_buffers_indexed - * EXT_color_buffer_float - * EXT_color_buffer_half_float + * EXT_shader_framebuffer_fetch_non_coherent * ANGLE_shader_pixel_local_storage_coherent * ANGLE_shader_pixel_local_storage Interactions with ANGLE_provoking_vertex, ANGLE_polygon_mode, EXT_blend_func_extended, EXT_clip_control, EXT_clip_cull_distance, EXT_depth_clamp, EXT_draw_buffers_indexed, EXT_polygon_offset_clamp, -KHR_blend_equation_advanced, KHR_debug, NV_polygon_mode, -NV_scissor_exclusive, OES_draw_buffers_indexed +EXT_texture_cube_map_array, KHR_blend_equation_advanced, KHR_debug, +NV_polygon_mode, NV_scissor_exclusive, OES_draw_buffers_indexed, +OES_texture_cube_map_array If any of these extensions is not supported, ignore the applicable references to the extension itself, and to BlendEquationSeparatei*, @@ -1100,7 +1020,8 @@ NV_scissor_exclusive, OES_draw_buffers_indexed ProvokingVertexANGLE, ObjectPtrLabel*, PopDebugGroup*, PushDebugGroup*, DEBUG_OUTPUT, DEBUG_OUTPUT_SYNCHRONOUS, SCISSOR_TEST_EXCLUSIVE_NV, CLIP_DISTANCE[0..7]_EXT, POLYGON_OFFSET_POINT_NV, POLYGON_OFFSET_LINE_NV, - POLYGON_OFFSET_LINE_ANGLE symbols. + POLYGON_OFFSET_LINE_ANGLE, TEXTURE_CUBE_MAP_ARRAY_EXT, + TEXTURE_CUBE_MAP_ARRAY_OES symbols. Interactions with OpenGL ES 3.1 @@ -1111,6 +1032,10 @@ Interactions with OpenGL ES 3.1 Add active pixel local storage planes to the list of resource types that count against MAX_COMBINED_SHADER_OUTPUT_RESOURCES. +Interactions with OpenGL ES 3.2 + + If OpenGL ES 3.2 is not supported, ignore all references to the + TEXTURE_CUBE_MAP_ARRAY symbol. Additions to the OpenGL ES Shading Language Specification, Version 3.00 @@ -1239,13 +1164,19 @@ Additions to the OpenGL ES Shading Language Specification, Version 3.00 layout-qualifier-id binding = + noncoherent - Accepable identifiers for are enumerated in Table X.4. + Acceptable identifiers for are enumerated in Table X.3. It is a compile-time error to declare a pixel local storage uniform that - does not specify both of these layout qualifiers, or to specify a format - layout qualifier on any type other than that format's corresponding "Pixel - Local Type", as enumerated in Table X.4. + does not specify both the binding and format layout qualifiers, or to + specify a format layout qualifier on any type other than that format's + corresponding "Pixel Local Type", as enumerated in Table X.3. + + If noncoherent is specified, any raster ordering guarantees are relaxed when + accessing the given plane, and the application is always responsible to + issue PixelLocalStorageBarrierANGLE() commands between overlapping + fragments. Modify Section 8 "Built-in Functions" @@ -1348,13 +1279,17 @@ Issues (4) Should we support binding cube map layers to pixel local storage? - RESOLVED: No. There is currently a 1:1 mapping on every implementation - from pixel local storage shaders to backend shaders, but binding a cube - map layer would require a texelFetch() implementation to behave - differently in the shader. We can always add cube map support in the - future, if the need arises. + RESOLVED: Yes. Cube map and cube map array layers use the same binding + semantics as 2D array layers. (5) Can we support transform feedback? RESOLVED: No. Transform feedback can lead to render pass breaks in the Vulkan backend. + + (6) Should feedback loops between sampled textures and pixel local storage + planes generate errors? + + RESOLVED: No. Follow the language for feedback loops between framebuffer + attachments and sampled textures. Rendering results are undefined. Layered + APIs such as WebGL make this case an error. diff --git a/extensions/ANGLE_translated_shader_source.txt b/extensions/ANGLE_translated_shader_source.txt index 69161156fc5..2f486e5b80b 100644 --- a/extensions/ANGLE_translated_shader_source.txt +++ b/extensions/ANGLE_translated_shader_source.txt @@ -72,10 +72,10 @@ Requests) Append in the end of the fourth paragraph of section 6.1.8 (Shader and Program Queries): - " If is TRANSLATED_SHADER_LENGTH_ANGLE, the length of the translated - source string, including a null terminator, is returned. If no source has - been defined, CompileShader has not been called, or the translation has - failed for , zero is returned." + " If is TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, the length of the + translated source string, including a null terminator, is returned. If no + source has been defined, CompileShader has not been called, or the + translation has failed for , zero is returned." Append after the last paragraph of section 6.1.8 (Shader and Program Queries): diff --git a/extensions/ANGLE_vulkan_image.txt b/extensions/ANGLE_vulkan_image.txt index a3417ea4a5a..11fbcd782c1 100644 --- a/extensions/ANGLE_vulkan_image.txt +++ b/extensions/ANGLE_vulkan_image.txt @@ -59,9 +59,11 @@ New Tokens Additions to Chapter 4 of the OpenGL 4.5 Specification (Event Model) The command + void AcquireTexturesANGLE(uint numTextures, const uint *textures, const GLenum *layouts); + will acquire ownership of textures. Since the texture layout state is managed internally by the GL, but may have been modified by an external API, the current layout of the textures must be specified to initialize internal @@ -71,10 +73,17 @@ Additions to Chapter 4 of the OpenGL 4.5 Specification (Event Model) perform appropriate transitions internally as necessary based on the specified current layout of the texture. + When ANGLE uses VK_KHR_unified_image_layouts, the Vulkan stage and access + masks for each texture continue to be derived from the layouts parameter + and used for synchronization purposes, but the actual Vulkan layout of the + images must be VK_IMAGE_LAYOUT_GENERAL. + The command + void ReleaseTexturesANGLE(uint numTextures, const uint *textures, GLenum *layouts); + will release ownership of textures. The current texture layouts will be returned, so an external API can perform appropriate transitions as necessary based on the returned current layout of the textures. diff --git a/extensions/CHROMIUM_copy_texture.txt b/extensions/CHROMIUM_copy_texture.txt index 03e17b9ab4a..28c2366929d 100644 --- a/extensions/CHROMIUM_copy_texture.txt +++ b/extensions/CHROMIUM_copy_texture.txt @@ -8,7 +8,7 @@ Name Strings Version - Last Modifed Date: March 24, 2017 + Last Modified Date: September 3, 2025 Dependencies @@ -17,6 +17,7 @@ Dependencies EXT_texture_format_BGRA8888 affects the definition of this extension. ARB_texture_rg affects the definition of this extension. CHROMIUM_ycbcr_422_image affects the definition of this extension. + ANGLE_yuv_internal_format affects the definition of this extension. Overview @@ -81,18 +82,27 @@ Additions to the OpenGL ES 2.0 Specification source format color components ---------------------------------------- - ALPHA (0, 0, 0, A) - RED (R, 0, 0, 1) - LUMINANCE (L, L, L, 1) - LUMINANCE_ALPHA (L, L, L, A) - RGB (R, G, B, 1) - RGB8 (R, G, B, 1) - RGBA (R, G, B, A) - RGBA8 (R, G, B, A) - BGRA_EXT (R, G, B, A) - BGRA8_EXT (R, G, B, A) - RGB_YCBCR_420V_CHROMIUM (R, G, B, 1) - RGB_YCBCR_422_CHROMIUM (R, G, B, 1) + ALPHA (0, 0, 0, A) + RED (R, 0, 0, 1) + LUMINANCE (L, L, L, 1) + LUMINANCE_ALPHA (L, L, L, A) + RGB (R, G, B, 1) + RGB8 (R, G, B, 1) + RGBA (R, G, B, A) + RGBA8 (R, G, B, A) + BGRA_EXT (R, G, B, A) + BGRA8_EXT (R, G, B, A) + RGB_YCBCR_420V_CHROMIUM (R, G, B, 1) + RGB_YCBCR_422_CHROMIUM (R, G, B, 1) + G8_B8R8_2PLANE_420_UNORM_ANGLE (R, G, B, 1) + G8_B8_R8_3PLANE_420_UNORM_ANGLE (R, G, B, 1) + G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE (R, G, B, 1) + G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE (R, G, B, 1) + G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE (R, G, B, 1) + G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE (R, G, B, 1) + G16_B16R16_2PLANE_420_UNORM_ANGLE (R, G, B, 1) + G16_B16_R16_3PLANE_420_UNORM_ANGLE (R, G, B, 1) + The format type of the destination texture is converted to that specified by . @@ -230,6 +240,15 @@ Additions to the OpenGL ES 2.0 Specification BGRA8_EXT RGB_YCBCR_420V_CHROMIUM RGB_YCBCR_422_CHROMIUM + G8_B8R8_2PLANE_420_UNORM_ANGLE + G8_B8_R8_3PLANE_420_UNORM_ANGLE + G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE + G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE + G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE + G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE + G16_B16R16_2PLANE_420_UNORM_ANGLE + G16_B16_R16_3PLANE_420_UNORM_ANGLE + Dependencies on ARB_texture_rg @@ -241,6 +260,18 @@ Dependencies on CHROMIUM_ycbcr_422_image If CHROMIUM_ycbcr_422_image is not supported: * delete any reference to the RGB_YCBCR_422_CHROMIUM format. +Dependencies on ANGLE_yuv_internal_format + + If ANGLE_yuv_internal_format is not supported: + * Delete references to the G8_B8R8_2PLANE_420_UNORM_ANGLE, + G8_B8_R8_3PLANE_420_UNORM_ANGLE, + G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE, + G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE, + G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE, + G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE, + G16_B16R16_2PLANE_420_UNORM_ANGLE, and + G16_B16_R16_3PLANE_420_UNORM_ANGLE formats. + Errors None. @@ -266,3 +297,4 @@ Revision History 18/1/2017 Supported source_level and dest_level. 19/1/2017 Added TEXTURE_CUBE_MAP as valid dest_id target. 24/3/2017 Clean up naming and move formats into tables. + 3/9/2025 Add source copy formats from ANGLE_yuv_internal_format diff --git a/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt b/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt index 4245d6ca732..0931f2fc095 100644 --- a/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt +++ b/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt @@ -9,6 +9,7 @@ Name Strings Contributors Geoff Lang + Shahbaz Youssefi Contacts @@ -54,6 +55,7 @@ New Tokens eglCreateContext: EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC + EGL_CONTEXT_HARDENED_ANGLE 0x34F8 Additions to the EGL 1.4 Specification @@ -65,6 +67,12 @@ Additions to the EGL 1.4 Specification WebGL specification. The default value of EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE is EGL_FALSE. + EGL_CONTEXT_HARDENED_ANGLE indicates whether additional hardening measures + should be applied, such as done by the shader translation. These hardening + measures are a subset of those enabled when + EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE is EGL_TRUE, and so it has no effect + in that case. + Errors None @@ -85,4 +93,5 @@ Revision History Rev. Date Author Changes ---- ------------- --------- ---------------------------------------- + 2 Jan 12, 2026 syoussefi Add hardened context creation flag 1 Sept 16, 2016 geofflang Initial version diff --git a/extensions/EGL_ANGLE_device_webgpu.txt b/extensions/EGL_ANGLE_device_webgpu.txt new file mode 100644 index 00000000000..ef8fcaf2d52 --- /dev/null +++ b/extensions/EGL_ANGLE_device_webgpu.txt @@ -0,0 +1,87 @@ +Name + + ANGLE_device_webgpu + +Name Strings + + EGL_ANGLE_device_webgpu + +Contributors + + Geoff Lang + +Contact + + Geoff Lang, Google (geofflang 'at' google 'dot' com) + +Status + + Draft + +Version + + Version 1, May 15, 2025 + +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 WebGPU device. + This extension defines a mapping from an EGL device to a WebGPU + 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 in eglQueryDeviceAttribEXT: + + EGL_WEBGPU_DEVICE_ANGLE 0x34F3 + EGL_WEBGPU_ADAPTER_ANGLE 0x34F4 + +Changes to section 3.2 (Devices) + + Replace the paragraph immediately following the prototype for + eglQueryDeviceAttribEXT: + + may be EGL_WEBGPU_DEVICE_ANGLE or EGL_WEBGPU_ADAPTER_ANGLE. + On success, EGL_TRUE is returned, and a valid WGPUDevice or WGPUAdapter + handle corresponding to the EGL device is returned in . wgpuAddRef is + called on the handle before returning and the client is responsible for + releasing this reference. This handle is compatible with WebGPU API functions. + If the EGL device is not currently associated with a WebGPU device and + is EGL_WEBGPU_DEVICE_ANGLE or EGL_WEBGPU_ADAPTER_ANGLE, EGL_BAD_ATTRIBUTE is + returned, and is left unchanged. + +Issues + + None + +Revision History + + Version 1, May 15, 2025 (Geoff Lang) + - Initial Draft + diff --git a/extensions/EGL_ANGLE_ggp_stream_descriptor.txt b/extensions/EGL_ANGLE_ggp_stream_descriptor.txt deleted file mode 100644 index 843d9b27bd7..00000000000 --- a/extensions/EGL_ANGLE_ggp_stream_descriptor.txt +++ /dev/null @@ -1,73 +0,0 @@ -Name - - ANGLE_ggp_stream_descriptor - -Name Strings - - EGL_ANGLE_ggp_stream_descriptor - -Contributors - - Jamie Madill - -Contacts - - Jamie Madill, Google Inc. (jmadill 'at' google.com) - -Status - - Draft - -Version - - Version 1, November 3, 2019 - -Number - - EGL Extension #?? - -Dependencies - - This extension is written against the wording of the EGL 1.5 - Specification. - -Overview - - This extension allows initializing an EGL Window surface backed by a - VkSurfaceKHR with a Google Games Platform GgpStreamDescriptor. - - It is based on the Vulkan extension VK_GGP_stream_descriptor_surface. - -New Types - - None - -New Procedures and Functions - - None - -New Tokens - - Accepted as an attribute name in the argument to - eglCreateSurfaceKHR: - - EGL_GGP_STREAM_DESCRIPTOR_ANGLE 0x348B - -Additions to the EGL 1.5 Specification - - Add the following to section 3.5.1 "Creating On-Screen Rendering Surfaces": - - EGL_GGP_STREAM_DESCRIPTOR_ANGLE indicates a GgpStreamDescriptor referring - to the GGP stream descriptor to associate with the surface. If - EGL_GGP_STREAM_DESCRIPTOR_ANGLE is not specified a default stream - descriptor will be used. - -Issues - - None yet. - -Revision History - - Rev. Date Author Changes - ---- ------------- --------- ---------------------------------------- - 1 Nov 3, 2019 jmadill Initial version diff --git a/extensions/EGL_ANGLE_metal_commands_scheduled_sync.txt b/extensions/EGL_ANGLE_metal_commands_scheduled_sync.txt new file mode 100644 index 00000000000..b39f433428a --- /dev/null +++ b/extensions/EGL_ANGLE_metal_commands_scheduled_sync.txt @@ -0,0 +1,108 @@ +Name + + ANGLE_metal_commands_scheduled_sync + +Name Strings + + EGL_ANGLE_metal_commands_scheduled_sync + +Contributors + + Sunny Sachanandani, Google + +Contacts + + Sunny Sachanandani, Google (sunnyps `at` google.com) + +Status + + Draft + +Version + + Version 1, 2025-10-09 + +Number + + EGL Extensions XXX + +Extension Type + + EGL display extension + +Dependencies + + This extension is written against the wording of the EGL 1.5 + Specification. + +Overview + + This extension enables the creation of EGL fence sync objects that are + signaled when any pending Metal commands are scheduled on the GPU. The EGL + fence sync objects have nearly identical semantics to those sync objects + defined by the EGL 1.5 Specification, except where noted. + + Creating the sync object flushes any pending work. These sync objects are + thread-safe and can be waited on from any thread with eglClientWaitSync + without a current context. Note that eglWaitSync is a no-op for these + sync objects since they only track CPU side scheduling of GPU commands. In + particular, specifying EGL_SYNC_FLUSH_COMMANDS_BIT has no effect either + since pending work is always flushed on creation of the sync object. + +New Types + + None. + +New Procedures and Functions + + None. + +New Tokens + + Accepted by the parameter of eglCreateSync, and returned + in when eglGetSyncAttrib is called with + EGL_SYNC_TYPE: + + EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE 0x34E0 + +Additions to the EGL Specification + + Add the following after the first paragraph of Section 3.8.1.1 (Creating + Fence Sync Objects), + + "If is EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, an EGL commands + scheduled sync object is created. No attributes may be specified in this + case. + + The default values for the EGL commands scheduled sync object attributes + are as follows: + + Attribute Name Initial Attribute Value(s) + -------------- -------------------------- + EGL_SYNC_TYPE EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE + EGL_SYNC_STATUS EGL_UNSIGNALED + EGL_SYNC_CONDITION EGL_SYNC_PRIOR_COMMANDS_COMPLETE + + Modify the list of eglCreateSync errors in Section 3.8.1.2 (Creating OpenCL + Event Sync Objects) + + "Errors + ------ + ..." + + Modify the second paragraph of Section 3.8.1.1 (Creating Fence Sync Objects), + + "When a fence sync object is created or when an EGL commands scheduled sync + object is created, eglCreateSync also inserts a fence command into the + command stream of the bound client API’s current context (i.e., the + context returned by eglGetCurrentContext), and associates it with the newly + created sync object." + +Issues + + None. + +Revision History + + Version 1, 2025-10-09 + - Initial draft diff --git a/extensions/EGL_ANGLE_platform_angle_webgpu.txt b/extensions/EGL_ANGLE_platform_angle_webgpu.txt index f452f53c29c..6d8db06a0f2 100644 --- a/extensions/EGL_ANGLE_platform_angle_webgpu.txt +++ b/extensions/EGL_ANGLE_platform_angle_webgpu.txt @@ -55,6 +55,14 @@ New Tokens EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE 0x34DF + Accepted as an attribute name in the argument of + eglGetPlatformDisplayEXT: + + EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE 0x3480 + EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE 0x34F7 + EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE 0x34F6 + + Additions to the EGL Specification None. @@ -65,6 +73,22 @@ New Behavior EGL_PLATFORM_ANGLE_TYPE_ANGLE should be EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE. + To configure the WebGPU function pointers used, use the attribute + EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE. The value of + EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE should be a pointer to + a DawnProcTable. If a proc table is not provided or the provided + proc table is NULL, an implementation specific one will be used. + + To use an existing WebGPU instance and device, use the attributes + EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE and + EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE. + EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE should be a WGPUInstance handle. + If an instance is not provided or is NULL, an implementation specific + one will be used. + EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE should be a WGPUDevice handle. + If a device is not provided or is NULL, an implementation specific + one will be used. + Issues None @@ -73,3 +97,9 @@ Revision History Version 1, 2024-01-22 (Liza Burakova) - Initial draft + Version 2, 2025-04-28 (Geoff Lang) + - Add EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE + Version 3, 2025-05-22 (Geoff Lang) + - Add EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE + Version 4, 2026-01-09 (Corentin Wallez) + - Add EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE diff --git a/extensions/EGL_ANGLE_swap_with_frame_token.txt b/extensions/EGL_ANGLE_swap_with_frame_token.txt deleted file mode 100644 index f58b7c75482..00000000000 --- a/extensions/EGL_ANGLE_swap_with_frame_token.txt +++ /dev/null @@ -1,83 +0,0 @@ -Name - - ANGLE_swap_with_frame_token - -Name Strings - - EGL_ANGLE_swap_with_frame_token - -Contributors - - Jamie Madill - -Contacts - - Jamie Madill, Google Inc. (jmadill 'at' google.com) - -Status - - Draft - -Version - - Version 1, November 3, 2019 - -Number - - EGL Extension #?? - -Dependencies - - This extension is written against the wording of the EGL 1.5 - Specification. - -Overview - - This extension allows an application that uses a Google Games - Platform surface to associate a Google Games Platform frame token - with an eglSwapBuffers operation. - - It is based on the Vulkan extension VK_GGP_frame_token. - -New Types - - This is a 64-bit unsigned type that represents a GGP frame token. - - typedef khronos_uint64_t EGLFrameTokenANGLE; - -New Procedures and Functions - - EGLBoolean eglSwapBuffersWithFrameTokenANGLE( - EGLDisplay dpy, - EGLSurface surface, - EGLFrameTokenANGLE frametoken); - -New Tokens - - None - -Additions to the EGL 1.5 Specification - - Add the following to section 3.10.1 "Posting to a Window": - - A Google Games Platform frame token can be specified when posting a color - buffer to a window by calling - - EGLBoolean eglSwapBuffersWithFrameTokenANGLE( - EGLDisplay dpy, - EGLSurface surface, - EGLFrameTokenANGLE frametoken); - - The behaviour of eglSwapBuffersWithFrameTokenANGLE is identical to that - of eglSwapBuffers except that the behaviour is undefined when - is not a valid GgpFrameToken. - -Issues - - None yet. - -Revision History - - Rev. Date Author Changes - ---- ------------- --------- ---------------------------------------- - 1 Nov 3, 2019 jmadill Initial version diff --git a/extensions/EGL_ANGLE_webgpu_texture_client_buffer.txt b/extensions/EGL_ANGLE_webgpu_texture_client_buffer.txt new file mode 100644 index 00000000000..7a049c4676f --- /dev/null +++ b/extensions/EGL_ANGLE_webgpu_texture_client_buffer.txt @@ -0,0 +1,140 @@ +Name + + ANGLE_webgpu_texture_client_buffer + +Name Strings + + EGL_ANGLE_webgpu_texture_client_buffer + +Contributors + + Geoff Lang + +Contacts + + Geoff Lang, Google Inc. (geofflang 'at' google.com) + +Status + + Draft + +Version + + Version 1, May 15, 2025 + +Number + + EGL Extension #?? + +Dependencies + + This extension is written against the wording of the EGL 1.2 + Specification. + + References the EGL_ANGLE_device_webgpu and EGL_KHR_image_base extensions. + +Overview + + This extension allows creating EGL surfaces and EGL images from D3D texture + objects. + +New Types + + None + +New Procedures and Functions + + None + +New Tokens + + Accepted by the parameter of eglCreateImageKHR and + parameter of eglCreatePbufferFromClientBuffer: + + EGL_WEBGPU_TEXTURE_ANGLE 0x34F5 + + Accepted in the parameter of eglCreateImageKHR and + eglCreatePbufferFromClientBuffer: + + EGL_TEXTURE_TYPE_ANGLE 0x345C + EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D + +Additions to Chapter 2 of the EGL 1.2 Specification (EGL Operation) + + Add to section 2.5.1 "EGLImage Specification" (as defined by the + EGL_KHR_image_base specification), in the description of + eglCreateImageKHR: + + "Values accepted for are listed in Table aaa, below. + + +----------------------------+-----------------------------------------+ + | | Notes | + +----------------------------+-----------------------------------------+ + | EGL_WEBGPU_TEXTURE_ANGLE | Used for WebGPU texture objects | + +----------------------------+-----------------------------------------+ + Table aaa. Legal values for eglCreateImageKHR parameter + + ... + + If is EGL_WEBGPU_TEXTURE_ANGLE, must be a valid display, + must be EGL_NO_CONTEXT, must be a pointer to a valid WGPUTexture + handle (cast into the type EGLClientBuffer), and attributes other than + EGL_TEXTURE_INTERNAL_FORMAT_ANGLE or EGL_TEXTURE_TYPE_ANGLE are ignored. + The width and height of the pbuffer are determined by the width and height of + . + + If EGL_TEXTURE_INTERNAL_FORMAT_ANGLE and EGL_TEXTURE_TYPE_ANGLE is specified, + they are used to interpret according to the provided internal format. + If EGL_TEXTURE_INTERNAL_FORMAT_ANGLE is a sized internal format, + EGL_TEXTURE_TYPE_ANGLE is not required. If either EGL_TEXTURE_INTERNAL_FORMAT_ANGLE + or EGL_TEXTURE_TYPE_ANGLE is provided and they are not a valid texture format + or the texture format is not a valid reinterpretation of the provided texture, + EGL_BAD_PARAMETER is generated. + + If the EGL_ANGLE_device_webgpu extension is present, the provided WGPUTexture + handle must have been created by the same WGPUDevice queried from the + display. It is undefined behaviour to import a WGPUTexture created on a + different WGPUDevice. + + The image may later be used as a GL_TEXTURE_2D or GL_TEXTURE_EXTERNAL_OES + target sibling based on the availability of GL_OES_EGL_image and/or + GL_OES_EGL_image_external extensions." + +Additions to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) + + Replace the last sentence of paragraph 1 of Section 3.5.3 with the + following text. + "Currently, the only client API resources which may be bound in this + fashion are OpenVG VGImage objects and Direct3D texture objects." + + Replace the last sentence of paragraph 2 ("To bind a client API...") of + Section 3.5.3 with the following text. + "When is EGL_OPENVG_IMAGE or EGL_WEBGPU_TEXTURE_ANGLE, the width and + height of the pbuffer are determined by the width and height of ." + + Replace the third paragraph of Section 3.5.3 with the following text. + " specifies the type of buffer to be bound. The only allowed values + of are EGL_OPENVG_IMAGE and EGL_WEBGPU_TEXTURE_ANGLE". + + Append the following text to the fourth paragraph of Section 3.5.3. + "When is EGL_WEBGPU_TEXTURE_ANGLE, must be + a valid D3D texture object, cast into the type EGLClientBuffer. If the + EGL_ANGLE_device_webgpu extension is present, the provided WGPUTexture handle + must have been created by the same WGPUDevice queried from the display. + It is undefined behaviour to import a WGPUTexture created on a + different WGPUDevice." + + Append to the end of Section 3.5.3. + "When a pbuffer is created with type EGL_WEBGPU_TEXTURE_ANGLE, the contents + of the associated WGPUTexture are undefined while the pbuffer is + the current read surface, draw surface or bound to a client texture." + +Issues + + None + +Revision History + + Version 1, May 15, 2025 (Geoff Lang) + - Initial Draft + diff --git a/gni/angle.gni b/gni/angle.gni index 4158fe8f285..a367e0cbd2a 100644 --- a/gni/angle.gni +++ b/gni/angle.gni @@ -3,10 +3,19 @@ # found in the LICENSE file. import("//build_overrides/angle.gni") +if (angle_has_build) { + import("//build/config/gclient_args.gni") +} -declare_args() { - is_ggp = false +if (!defined(checkout_angle_cl_deps)) { + checkout_angle_cl_deps = true +} + +if (!defined(checkout_angle_dawn_deps)) { + checkout_angle_dawn_deps = true +} +declare_args() { # Extract native libs in ANGLE apk. Useful for flamegraph generation. angle_extract_native_libs = false @@ -19,19 +28,28 @@ declare_args() { # Enables OpenCL support, off by default. angle_enable_cl = false + if (!checkout_angle_cl_deps) { + angle_enable_cl = false + } angle_restricted_traces = [] # Don't build dEQP by default. build_angle_deqp_tests = false - build_angle_end2end_tests_aosp = false + # Build the ANGLE end2end tests as a shared library. This shared library can (for example) be + # loaded by an Android APK to execute the end2end tests outside of the normal GTest framework. + build_angle_end2end_tests_library = false # List of traces for benchmark mode angle_standalone_benchmark_traces = [] # Benchmark mode golden default directory angle_standalone_benchmark_goldens_dir = "" + + # Whether the ANGLE translator should be built with IR instead + # THIS IS CURRENTLY EXPERIMENTAL. + angle_ir = false } declare_args() { @@ -69,11 +87,10 @@ if (angle_has_build) { } declare_args() { - angle_use_gbm = ozone_platform_gbm - angle_use_x11 = ozone_platform_x11 && !is_ggp && (is_linux || is_chromeos) - angle_use_wayland = - ozone_platform_wayland && !is_ggp && is_linux && !is_castos - angle_use_vulkan_display = (is_linux || is_chromeos) && !is_ggp + angle_use_gbm = ozone_platform_drm + angle_use_x11 = ozone_platform_x11 && (is_linux || is_chromeos) + angle_use_wayland = ozone_platform_wayland && is_linux && !is_castos + angle_use_vulkan_display = is_linux || is_chromeos } } else { declare_args() { @@ -83,10 +100,11 @@ if (angle_has_build) { is_lsan = false build_with_chromium = false dcheck_always_on = false - angle_use_x11 = (is_linux || is_chromeos) && !is_ggp - angle_use_wayland = is_linux && !is_ggp + angle_use_x11 = is_linux || is_chromeos + angle_use_wayland = is_linux + angle_use_gbm = false use_ozone = false - ozone_platform_gbm = false + ozone_platform_drm = false ozone_platform_wayland = false ozone_platform_headless = false use_fuzzing_engine = false @@ -95,7 +113,7 @@ if (angle_has_build) { } declare_args() { - angle_use_vulkan_display = (is_linux || is_chromeos) && !is_ggp + angle_use_vulkan_display = is_linux || is_chromeos } } @@ -116,7 +134,7 @@ declare_args() { if (current_cpu == "arm64" || current_cpu == "x64" || current_cpu == "mips64el" || current_cpu == "s390x" || current_cpu == "ppc64" || current_cpu == "loong64" || - current_cpu == "riscv64") { + current_cpu == "riscv64" || current_cpu == "arm64e") { angle_64bit_current_cpu = true } else if (current_cpu == "arm" || current_cpu == "x86" || current_cpu == "mipsel" || current_cpu == "s390" || @@ -143,9 +161,7 @@ declare_args() { if (!is_android) { ndk_api_level_at_least_26 = false } else { - ndk_api_level_at_least_26 = - (!angle_64bit_current_cpu && android32_ndk_api_level >= 26) || - (angle_64bit_current_cpu && android64_ndk_api_level >= 26) + ndk_api_level_at_least_26 = android_ndk_api_level >= 26 } # Vulkan loader is statically linked on Mac. http://anglebug.com/40096682 @@ -184,16 +200,16 @@ declare_args() { angle_enable_d3d9 = is_win && !angle_is_winuwp angle_enable_d3d11 = is_win angle_enable_gl = - (ozone_platform_gbm || ozone_platform_wayland || !is_linux || + (ozone_platform_drm || ozone_platform_wayland || !is_linux || ((angle_use_x11 && !is_chromeos) || angle_use_wayland || is_castos)) && - !is_fuchsia && !angle_is_winuwp && !is_ggp && !is_win_arm64 && !is_ios + !is_fuchsia && !angle_is_winuwp && !is_win_arm64 && !is_ios angle_enable_vulkan = angle_has_build && ((is_win && !angle_is_winuwp) || ((is_linux || is_chromeos) && (angle_use_x11 || angle_use_wayland || angle_use_vulkan_display)) || - is_android || is_fuchsia || is_ggp || is_mac) + is_android || is_fuchsia || is_mac) # When set to true, ANGLE will not use VK_KHR_surface and VK_KHR_swapchain # extensions. Content can be rendered only off-screen. @@ -203,7 +219,6 @@ declare_args() { angle_enable_null = !is_official_build angle_enable_gl_desktop_backend = !is_android && !is_ios - # http://anglebug.com/40096506 angle_enable_metal = is_apple # Enables the OpenCL pass-through back end @@ -215,7 +230,7 @@ declare_args() { angle_enable_wgpu = !is_official_build && !(is_android || is_fuchsia || angle_is_winuwp) && (!is_win || is_clang) && (!is_linux || angle_use_x11) && - defined(angle_dawn_dir) + defined(angle_dawn_dir) && checkout_angle_dawn_deps } declare_args() { @@ -224,6 +239,11 @@ declare_args() { } declare_args() { + # Test the system EGL. + # If "true", this disables testing any ANGLE libraries packaged with the + # end2end tests. Meaning, only either System EGL or ANGLE EGL libraries can + # be tested with the full suite, including all supported/enabled backends, but + # not both drivers at the same time. angle_test_enable_system_egl = false } @@ -246,16 +266,17 @@ if (!defined(checkout_angle_mesa)) { declare_args() { # Currently SwiftShader's Vulkan front-end doesn't build on Android. # Disabled by default on MSVC because of compiler warnings/errors. - angle_enable_swiftshader = - angle_enable_vulkan && !is_android && !is_ggp && is_clang + angle_enable_swiftshader = angle_enable_vulkan && !is_android && is_clang # Translator backend support: angle_enable_hlsl = angle_enable_d3d9 || angle_enable_d3d11 angle_enable_essl = angle_enable_gl || use_ozone angle_enable_glsl = angle_enable_gl || use_ozone + angle_enable_msl = angle_enable_metal angle_enable_trace = false angle_enable_trace_android_logcat = false angle_enable_trace_events = false + angle_enable_platform_trace_events = build_with_chromium angle_dump_pipeline_cache_graph = false angle_always_log_info = false @@ -308,6 +329,9 @@ declare_args() { angle_enable_overlay = angle_enable_vulkan && angle_debug_layers_enabled angle_build_mesa = false + + # Android platform's addTraceEvent ignores the timestamp and time() is a relatively heavy call. + angle_trace_events_ignore_timestamp = is_android && angle_standalone } declare_args() { @@ -333,6 +357,7 @@ if (!defined(angle_zlib_compression_utils_dir)) { angle_common_configs = [ angle_root + ":angle_asserts_config", angle_root + ":constructor_and_destructor_warnings", + angle_root + ":no_thread_safety_warnings", angle_root + ":extra_warnings", angle_root + ":internal_config", angle_root + ":angle_uwp_env", @@ -343,7 +368,7 @@ angle_remove_configs = [] if (angle_has_build) { angle_remove_configs += [ "//build/config/compiler:default_include_dirs" ] - if (is_clang && !is_nacl) { + if (is_clang) { angle_remove_configs += [ "//build/config/clang:find_bad_constructs" ] } @@ -352,6 +377,12 @@ if (angle_has_build) { angle_remove_configs += [ "//build/config/compiler:default_optimization" ] angle_common_configs += [ "//build/config/compiler:optimize_max" ] } + + # See https://crbug.com/386992829 + if (defined(angle_sanitize_array_bounds) && !angle_sanitize_array_bounds) { + angle_remove_configs += + [ "//build/config/compiler:sanitize_c_array_bounds" ] + } } set_defaults("angle_executable") { @@ -537,7 +568,8 @@ template("angle_static_library") { } } -if (angle_standalone || build_with_chromium || build_angle_end2end_tests_aosp) { +if (angle_standalone || build_with_chromium || + build_angle_end2end_tests_library) { template("angle_test") { test(target_name) { forward_variables_from(invoker, @@ -575,7 +607,7 @@ if (angle_standalone || build_with_chromium || build_angle_end2end_tests_aosp) { "//third_party/googletest:gtest", ] if (angle_has_rapidjson) { - public_deps += [ "$angle_root/third_party/rapidjson:rapidjson" ] + public_deps += [ "$angle_root/third_party/rapidjson" ] } data = invoker.data + [ @@ -614,8 +646,7 @@ if (angle_standalone || build_with_chromium || build_angle_end2end_tests_aosp) { } } - if ((is_linux && !is_chromeos) || - (build_with_chromium && is_chromeos_lacros && !is_chromeos_device)) { + if (is_linux && !is_chromeos) { use_xvfb = true } diff --git a/include/CL/cl.h b/include/CL/cl.h index afeeb4ee5e5..792e20cc8a1 100644 --- a/include/CL/cl.h +++ b/include/CL/cl.h @@ -112,9 +112,9 @@ typedef cl_uint cl_kernel_exec_info; typedef cl_bitfield cl_device_atomic_capabilities; typedef cl_bitfield cl_device_device_enqueue_capabilities; typedef cl_uint cl_khronos_vendor_id; -typedef cl_properties cl_mem_properties; -typedef cl_uint cl_version; +typedef cl_properties cl_mem_properties; #endif +typedef cl_uint cl_version; typedef struct _cl_image_format { cl_channel_order image_channel_order; @@ -914,8 +914,6 @@ typedef struct _cl_name_version { /* cl_khronos_vendor_id */ #define CL_KHRONOS_VENDOR_ID_CODEPLAY 0x10004 -#ifdef CL_VERSION_3_0 - /* cl_version */ #define CL_VERSION_MAJOR_BITS (10) #define CL_VERSION_MINOR_BITS (10) @@ -939,8 +937,6 @@ typedef struct _cl_name_version { (((minor) & CL_VERSION_MINOR_MASK) << CL_VERSION_PATCH_BITS) | \ ((patch) & CL_VERSION_PATCH_MASK)) -#endif - /********************************************************************************************************/ /* CL_NO_PROTOTYPES implies CL_NO_CORE_PROTOTYPES: */ diff --git a/include/CL/cl_d3d10.h b/include/CL/cl_d3d10.h index 8404644a471..6b56c775bf8 100644 --- a/include/CL/cl_d3d10.h +++ b/include/CL/cl_d3d10.h @@ -65,6 +65,9 @@ extern "C" { #define CL_KHR_D3D10_SHARING_EXTENSION_NAME \ "cl_khr_d3d10_sharing" + +#define CL_KHR_D3D10_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_uint cl_d3d10_device_source_khr; typedef cl_uint cl_d3d10_device_set_khr; @@ -228,6 +231,9 @@ clEnqueueReleaseD3D10ObjectsKHR( #define CL_INTEL_SHARING_FORMAT_QUERY_D3D10_EXTENSION_NAME \ "cl_intel_sharing_format_query_d3d10" + +#define CL_INTEL_SHARING_FORMAT_QUERY_D3D10_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* when cl_khr_d3d10_sharing is supported */ typedef cl_int CL_API_CALL diff --git a/include/CL/cl_d3d11.h b/include/CL/cl_d3d11.h index ade879509cf..384c8f428fc 100644 --- a/include/CL/cl_d3d11.h +++ b/include/CL/cl_d3d11.h @@ -65,6 +65,9 @@ extern "C" { #define CL_KHR_D3D11_SHARING_EXTENSION_NAME \ "cl_khr_d3d11_sharing" + +#define CL_KHR_D3D11_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_uint cl_d3d11_device_source_khr; typedef cl_uint cl_d3d11_device_set_khr; @@ -228,6 +231,9 @@ clEnqueueReleaseD3D11ObjectsKHR( #define CL_INTEL_SHARING_FORMAT_QUERY_D3D11_EXTENSION_NAME \ "cl_intel_sharing_format_query_d3d11" + +#define CL_INTEL_SHARING_FORMAT_QUERY_D3D11_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* when cl_khr_d3d11_sharing is supported */ typedef cl_int CL_API_CALL diff --git a/include/CL/cl_dx9_media_sharing.h b/include/CL/cl_dx9_media_sharing.h index c0df5c91989..b079379d0a7 100644 --- a/include/CL/cl_dx9_media_sharing.h +++ b/include/CL/cl_dx9_media_sharing.h @@ -67,6 +67,9 @@ extern "C" { #define CL_KHR_DX9_MEDIA_SHARING_EXTENSION_NAME \ "cl_khr_dx9_media_sharing" + +#define CL_KHR_DX9_MEDIA_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_uint cl_dx9_media_adapter_type_khr; typedef cl_uint cl_dx9_media_adapter_set_khr; @@ -209,6 +212,9 @@ clEnqueueReleaseDX9MediaSurfacesKHR( #define CL_INTEL_DX9_MEDIA_SHARING_EXTENSION_NAME \ "cl_intel_dx9_media_sharing" + +#define CL_INTEL_DX9_MEDIA_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_uint cl_dx9_device_source_intel; typedef cl_uint cl_dx9_device_set_intel; @@ -341,6 +347,9 @@ clEnqueueReleaseDX9ObjectsINTEL( #define CL_INTEL_SHARING_FORMAT_QUERY_DX9_EXTENSION_NAME \ "cl_intel_sharing_format_query_dx9" + +#define CL_INTEL_SHARING_FORMAT_QUERY_DX9_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* when cl_khr_dx9_media_sharing or cl_intel_dx9_media_sharing is supported */ typedef cl_int CL_API_CALL diff --git a/include/CL/cl_egl.h b/include/CL/cl_egl.h index 25cd5e0cb56..68aefec7619 100644 --- a/include/CL/cl_egl.h +++ b/include/CL/cl_egl.h @@ -51,6 +51,9 @@ extern "C" { #define CL_KHR_EGL_IMAGE_EXTENSION_NAME \ "cl_khr_egl_image" + +#define CL_KHR_EGL_IMAGE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* Command type for events created with clEnqueueAcquireEGLObjectsKHR */ #define CL_COMMAND_EGL_FENCE_SYNC_OBJECT_KHR 0x202F #define CL_COMMAND_ACQUIRE_EGL_OBJECTS_KHR 0x202D @@ -144,6 +147,9 @@ clEnqueueReleaseEGLObjectsKHR( #define CL_KHR_EGL_EVENT_EXTENSION_NAME \ "cl_khr_egl_event" + +#define CL_KHR_EGL_EVENT_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* CLeglDisplayKHR is an opaque handle to an EGLDisplay */ /* type CLeglDisplayKHR */ diff --git a/include/CL/cl_ext.h b/include/CL/cl_ext.h index d12cf0d52b8..ffefe075cb6 100644 --- a/include/CL/cl_ext.h +++ b/include/CL/cl_ext.h @@ -45,12 +45,17 @@ extern "C" { #endif /*************************************************************** -* cl_khr_command_buffer +* cl_khr_command_buffer (beta) ***************************************************************/ +#if defined(CL_ENABLE_BETA_EXTENSIONS) + #define cl_khr_command_buffer 1 #define CL_KHR_COMMAND_BUFFER_EXTENSION_NAME \ "cl_khr_command_buffer" + +#define CL_KHR_COMMAND_BUFFER_EXTENSION_VERSION CL_MAKE_VERSION(0, 9, 7) + typedef cl_bitfield cl_device_command_buffer_capabilities_khr; typedef struct _cl_command_buffer_khr* cl_command_buffer_khr; typedef cl_uint cl_sync_point_khr; @@ -58,18 +63,18 @@ typedef cl_uint cl_command_buffer_info_khr; typedef cl_uint cl_command_buffer_state_khr; typedef cl_properties cl_command_buffer_properties_khr; typedef cl_bitfield cl_command_buffer_flags_khr; -typedef cl_properties cl_ndrange_kernel_command_properties_khr; +typedef cl_properties cl_command_properties_khr; typedef struct _cl_mutable_command_khr* cl_mutable_command_khr; /* cl_device_info */ #define CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR 0x12A9 +#define CL_DEVICE_COMMAND_BUFFER_SUPPORTED_QUEUE_PROPERTIES_KHR 0x129A #define CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR 0x12AA /* cl_device_command_buffer_capabilities_khr - bitfield */ #define CL_COMMAND_BUFFER_CAPABILITY_KERNEL_PRINTF_KHR (1 << 0) #define CL_COMMAND_BUFFER_CAPABILITY_DEVICE_SIDE_ENQUEUE_KHR (1 << 1) #define CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR (1 << 2) -#define CL_COMMAND_BUFFER_CAPABILITY_OUT_OF_ORDER_KHR (1 << 3) /* cl_command_buffer_properties_khr */ #define CL_COMMAND_BUFFER_FLAGS_KHR 0x1293 @@ -146,6 +151,7 @@ typedef cl_int CL_API_CALL clCommandBarrierWithWaitListKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_uint num_sync_points_in_wait_list, const cl_sync_point_khr* sync_point_wait_list, cl_sync_point_khr* sync_point, @@ -158,6 +164,7 @@ typedef cl_int CL_API_CALL clCommandCopyBufferKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, @@ -175,6 +182,7 @@ typedef cl_int CL_API_CALL clCommandCopyBufferRectKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_buffer, cl_mem dst_buffer, const size_t* src_origin, @@ -196,6 +204,7 @@ typedef cl_int CL_API_CALL clCommandCopyBufferToImageKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -213,6 +222,7 @@ typedef cl_int CL_API_CALL clCommandCopyImageKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_image, cl_mem dst_image, const size_t* src_origin, @@ -230,6 +240,7 @@ typedef cl_int CL_API_CALL clCommandCopyImageToBufferKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_image, cl_mem dst_buffer, const size_t* src_origin, @@ -247,6 +258,7 @@ typedef cl_int CL_API_CALL clCommandFillBufferKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem buffer, const void* pattern, size_t pattern_size, @@ -264,6 +276,7 @@ typedef cl_int CL_API_CALL clCommandFillImageKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem image, const void* fill_color, const size_t* origin, @@ -280,7 +293,7 @@ typedef cl_int CL_API_CALL clCommandNDRangeKernelKHR_t( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, - const cl_ndrange_kernel_command_properties_khr* properties, + const cl_command_properties_khr* properties, cl_kernel kernel, cl_uint work_dim, const size_t* global_work_offset, @@ -294,37 +307,6 @@ clCommandNDRangeKernelKHR_t( typedef clCommandNDRangeKernelKHR_t * clCommandNDRangeKernelKHR_fn ; -typedef cl_int CL_API_CALL -clCommandSVMMemcpyKHR_t( - cl_command_buffer_khr command_buffer, - cl_command_queue command_queue, - void* dst_ptr, - const void* src_ptr, - size_t size, - cl_uint num_sync_points_in_wait_list, - const cl_sync_point_khr* sync_point_wait_list, - cl_sync_point_khr* sync_point, - cl_mutable_command_khr* mutable_handle); - -typedef clCommandSVMMemcpyKHR_t * -clCommandSVMMemcpyKHR_fn CL_API_SUFFIX__VERSION_2_0; - -typedef cl_int CL_API_CALL -clCommandSVMMemFillKHR_t( - cl_command_buffer_khr command_buffer, - cl_command_queue command_queue, - void* svm_ptr, - const void* pattern, - size_t pattern_size, - size_t size, - cl_uint num_sync_points_in_wait_list, - const cl_sync_point_khr* sync_point_wait_list, - cl_sync_point_khr* sync_point, - cl_mutable_command_khr* mutable_handle); - -typedef clCommandSVMMemFillKHR_t * -clCommandSVMMemFillKHR_fn CL_API_SUFFIX__VERSION_2_0; - typedef cl_int CL_API_CALL clGetCommandBufferInfoKHR_t( cl_command_buffer_khr command_buffer, @@ -370,6 +352,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandBarrierWithWaitListKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_uint num_sync_points_in_wait_list, const cl_sync_point_khr* sync_point_wait_list, cl_sync_point_khr* sync_point, @@ -379,6 +362,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandCopyBufferKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, @@ -393,6 +377,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandCopyBufferRectKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_buffer, cl_mem dst_buffer, const size_t* src_origin, @@ -411,6 +396,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandCopyBufferToImageKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -425,6 +411,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandCopyImageKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_image, cl_mem dst_image, const size_t* src_origin, @@ -439,6 +426,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandCopyImageToBufferKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem src_image, cl_mem dst_buffer, const size_t* src_origin, @@ -453,6 +441,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandFillBufferKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem buffer, const void* pattern, size_t pattern_size, @@ -467,6 +456,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandFillImageKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, cl_mem image, const void* fill_color, const size_t* origin, @@ -480,7 +470,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandNDRangeKernelKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, - const cl_ndrange_kernel_command_properties_khr* properties, + const cl_command_properties_khr* properties, cl_kernel kernel, cl_uint work_dim, const size_t* global_work_offset, @@ -491,10 +481,58 @@ clCommandNDRangeKernelKHR( cl_sync_point_khr* sync_point, cl_mutable_command_khr* mutable_handle) ; +extern CL_API_ENTRY cl_int CL_API_CALL +clGetCommandBufferInfoKHR( + cl_command_buffer_khr command_buffer, + cl_command_buffer_info_khr param_name, + size_t param_value_size, + void* param_value, + size_t* param_value_size_ret) ; + +#endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ + +/* From version 0.9.4 of the extension */ + +typedef cl_int CL_API_CALL +clCommandSVMMemcpyKHR_t( + cl_command_buffer_khr command_buffer, + cl_command_queue command_queue, + const cl_command_properties_khr* properties, + void* dst_ptr, + const void* src_ptr, + size_t size, + cl_uint num_sync_points_in_wait_list, + const cl_sync_point_khr* sync_point_wait_list, + cl_sync_point_khr* sync_point, + cl_mutable_command_khr* mutable_handle); + +typedef clCommandSVMMemcpyKHR_t * +clCommandSVMMemcpyKHR_fn CL_API_SUFFIX__VERSION_2_0; + +typedef cl_int CL_API_CALL +clCommandSVMMemFillKHR_t( + cl_command_buffer_khr command_buffer, + cl_command_queue command_queue, + const cl_command_properties_khr* properties, + void* svm_ptr, + const void* pattern, + size_t pattern_size, + size_t size, + cl_uint num_sync_points_in_wait_list, + const cl_sync_point_khr* sync_point_wait_list, + cl_sync_point_khr* sync_point, + cl_mutable_command_khr* mutable_handle); + +typedef clCommandSVMMemFillKHR_t * +clCommandSVMMemFillKHR_fn CL_API_SUFFIX__VERSION_2_0; + +#if !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) + extern CL_API_ENTRY cl_int CL_API_CALL clCommandSVMMemcpyKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, void* dst_ptr, const void* src_ptr, size_t size, @@ -507,6 +545,7 @@ extern CL_API_ENTRY cl_int CL_API_CALL clCommandSVMMemFillKHR( cl_command_buffer_khr command_buffer, cl_command_queue command_queue, + const cl_command_properties_khr* properties, void* svm_ptr, const void* pattern, size_t pattern_size, @@ -516,23 +555,22 @@ clCommandSVMMemFillKHR( cl_sync_point_khr* sync_point, cl_mutable_command_khr* mutable_handle) CL_API_SUFFIX__VERSION_2_0; -extern CL_API_ENTRY cl_int CL_API_CALL -clGetCommandBufferInfoKHR( - cl_command_buffer_khr command_buffer, - cl_command_buffer_info_khr param_name, - size_t param_value_size, - void* param_value, - size_t* param_value_size_ret) ; - #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ +#endif /* defined(CL_ENABLE_BETA_EXTENSIONS) */ + /*************************************************************** -* cl_khr_command_buffer_multi_device +* cl_khr_command_buffer_multi_device (beta) ***************************************************************/ +#if defined(CL_ENABLE_BETA_EXTENSIONS) + #define cl_khr_command_buffer_multi_device 1 #define CL_KHR_COMMAND_BUFFER_MULTI_DEVICE_EXTENSION_NAME \ "cl_khr_command_buffer_multi_device" + +#define CL_KHR_COMMAND_BUFFER_MULTI_DEVICE_EXTENSION_VERSION CL_MAKE_VERSION(0, 9, 2) + typedef cl_bitfield cl_platform_command_buffer_capabilities_khr; /* cl_platform_info */ @@ -583,14 +621,21 @@ clRemapCommandBufferKHR( #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ +#endif /* defined(CL_ENABLE_BETA_EXTENSIONS) */ + /*************************************************************** -* cl_khr_command_buffer_mutable_dispatch +* cl_khr_command_buffer_mutable_dispatch (beta) ***************************************************************/ +#if defined(CL_ENABLE_BETA_EXTENSIONS) + #define cl_khr_command_buffer_mutable_dispatch 1 #define CL_KHR_COMMAND_BUFFER_MUTABLE_DISPATCH_EXTENSION_NAME \ "cl_khr_command_buffer_mutable_dispatch" -typedef cl_uint cl_command_buffer_structure_type_khr; + +#define CL_KHR_COMMAND_BUFFER_MUTABLE_DISPATCH_EXTENSION_VERSION CL_MAKE_VERSION(0, 9, 3) + +typedef cl_uint cl_command_buffer_update_type_khr; typedef cl_bitfield cl_mutable_dispatch_fields_khr; typedef cl_uint cl_mutable_command_info_khr; typedef struct _cl_mutable_dispatch_arg_khr { @@ -604,8 +649,6 @@ typedef struct _cl_mutable_dispatch_exec_info_khr { const void* param_value; } cl_mutable_dispatch_exec_info_khr; typedef struct _cl_mutable_dispatch_config_khr { - cl_command_buffer_structure_type_khr type; - const void* next; cl_mutable_command_khr command; cl_uint num_args; cl_uint num_svm_args; @@ -618,12 +661,6 @@ typedef struct _cl_mutable_dispatch_config_khr { const size_t* global_work_size; const size_t* local_work_size; } cl_mutable_dispatch_config_khr; -typedef struct _cl_mutable_base_config_khr { - cl_command_buffer_structure_type_khr type; - const void* next; - cl_uint num_mutable_dispatch; - const cl_mutable_dispatch_config_khr* mutable_dispatch_list; -} cl_mutable_base_config_khr; typedef cl_bitfield cl_mutable_dispatch_asserts_khr; /* cl_command_buffer_flags_khr - bitfield */ @@ -635,7 +672,7 @@ typedef cl_bitfield cl_mutable_dispatch_asserts_khr; /* cl_device_info */ #define CL_DEVICE_MUTABLE_DISPATCH_CAPABILITIES_KHR 0x12B0 -/* cl_ndrange_kernel_command_properties_khr */ +/* cl_command_properties_khr */ #define CL_MUTABLE_DISPATCH_UPDATABLE_FIELDS_KHR 0x12B1 /* cl_mutable_dispatch_fields_khr - bitfield */ @@ -649,21 +686,20 @@ typedef cl_bitfield cl_mutable_dispatch_asserts_khr; #define CL_MUTABLE_COMMAND_COMMAND_QUEUE_KHR 0x12A0 #define CL_MUTABLE_COMMAND_COMMAND_BUFFER_KHR 0x12A1 #define CL_MUTABLE_COMMAND_COMMAND_TYPE_KHR 0x12AD -#define CL_MUTABLE_DISPATCH_PROPERTIES_ARRAY_KHR 0x12A2 +#define CL_MUTABLE_COMMAND_PROPERTIES_ARRAY_KHR 0x12A2 #define CL_MUTABLE_DISPATCH_KERNEL_KHR 0x12A3 #define CL_MUTABLE_DISPATCH_DIMENSIONS_KHR 0x12A4 #define CL_MUTABLE_DISPATCH_GLOBAL_WORK_OFFSET_KHR 0x12A5 #define CL_MUTABLE_DISPATCH_GLOBAL_WORK_SIZE_KHR 0x12A6 #define CL_MUTABLE_DISPATCH_LOCAL_WORK_SIZE_KHR 0x12A7 -/* cl_command_buffer_structure_type_khr */ -#define CL_STRUCTURE_TYPE_MUTABLE_BASE_CONFIG_KHR 0 -#define CL_STRUCTURE_TYPE_MUTABLE_DISPATCH_CONFIG_KHR 1 +/* cl_command_buffer_update_type_khr */ +#define CL_STRUCTURE_TYPE_MUTABLE_DISPATCH_CONFIG_KHR 0 /* cl_command_buffer_properties_khr */ #define CL_COMMAND_BUFFER_MUTABLE_DISPATCH_ASSERTS_KHR 0x12B7 -/* cl_ndrange_kernel_command_properties_khr */ +/* cl_command_properties_khr */ #define CL_MUTABLE_DISPATCH_ASSERTS_KHR 0x12B8 /* cl_mutable_dispatch_asserts_khr - bitfield */ @@ -673,7 +709,9 @@ typedef cl_bitfield cl_mutable_dispatch_asserts_khr; typedef cl_int CL_API_CALL clUpdateMutableCommandsKHR_t( cl_command_buffer_khr command_buffer, - const cl_mutable_base_config_khr* mutable_config); + cl_uint num_configs, + const cl_command_buffer_update_type_khr* config_types, + const void** configs); typedef clUpdateMutableCommandsKHR_t * clUpdateMutableCommandsKHR_fn ; @@ -694,7 +732,9 @@ clGetMutableCommandInfoKHR_fn ; extern CL_API_ENTRY cl_int CL_API_CALL clUpdateMutableCommandsKHR( cl_command_buffer_khr command_buffer, - const cl_mutable_base_config_khr* mutable_config) ; + cl_uint num_configs, + const cl_command_buffer_update_type_khr* config_types, + const void** configs) ; extern CL_API_ENTRY cl_int CL_API_CALL clGetMutableCommandInfoKHR( @@ -706,6 +746,8 @@ clGetMutableCommandInfoKHR( #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ +#endif /* defined(CL_ENABLE_BETA_EXTENSIONS) */ + /*************************************************************** * cl_khr_fp64 ***************************************************************/ @@ -713,6 +755,9 @@ clGetMutableCommandInfoKHR( #define CL_KHR_FP64_EXTENSION_NAME \ "cl_khr_fp64" + +#define CL_KHR_FP64_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + #if !defined(CL_VERSION_1_2) /* cl_device_info - defined in CL.h for OpenCL 1.2 and newer */ #define CL_DEVICE_DOUBLE_FP_CONFIG 0x1032 @@ -726,6 +771,9 @@ clGetMutableCommandInfoKHR( #define CL_KHR_FP16_EXTENSION_NAME \ "cl_khr_fp16" + +#define CL_KHR_FP16_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_device_info */ #define CL_DEVICE_HALF_FP_CONFIG 0x1033 @@ -737,6 +785,9 @@ clGetMutableCommandInfoKHR( "cl_APPLE_SetMemObjectDestructor" +#define CL_APPLE_SETMEMOBJECTDESTRUCTOR_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + + typedef cl_int CL_API_CALL clSetMemObjectDestructorAPPLE_t( cl_mem memobj, @@ -764,6 +815,9 @@ clSetMemObjectDestructorAPPLE( "cl_APPLE_ContextLoggingFunctions" +#define CL_APPLE_CONTEXTLOGGINGFUNCTIONS_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + + typedef void CL_API_CALL clLogMessagesToSystemLogAPPLE_t( const char* errstr, @@ -826,12 +880,22 @@ clLogMessagesToStderrAPPLE( #define CL_KHR_ICD_EXTENSION_NAME \ "cl_khr_icd" + +#define CL_KHR_ICD_EXTENSION_VERSION CL_MAKE_VERSION(2, 0, 0) + /* cl_platform_info */ #define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920 /* Error codes */ #define CL_PLATFORM_NOT_FOUND_KHR -1001 +/* ICD 2 tag value */ +#if INTPTR_MAX == INT32_MAX +#define CL_ICD2_TAG_KHR ((intptr_t)0x434C3331) +#else +#define CL_ICD2_TAG_KHR ((intptr_t)0x4F50454E434C3331) +#endif + typedef cl_int CL_API_CALL clIcdGetPlatformIDsKHR_t( @@ -842,6 +906,22 @@ clIcdGetPlatformIDsKHR_t( typedef clIcdGetPlatformIDsKHR_t * clIcdGetPlatformIDsKHR_fn ; +typedef void* CL_API_CALL +clIcdGetFunctionAddressForPlatformKHR_t( + cl_platform_id platform, + const char* func_name); + +typedef clIcdGetFunctionAddressForPlatformKHR_t * +clIcdGetFunctionAddressForPlatformKHR_fn ; + +typedef cl_int CL_API_CALL +clIcdSetPlatformDispatchDataKHR_t( + cl_platform_id platform, + void* dispatch_data); + +typedef clIcdSetPlatformDispatchDataKHR_t * +clIcdSetPlatformDispatchDataKHR_fn ; + #if !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) extern CL_API_ENTRY cl_int CL_API_CALL @@ -850,6 +930,16 @@ clIcdGetPlatformIDsKHR( cl_platform_id* platforms, cl_uint* num_platforms) ; +extern CL_API_ENTRY void* CL_API_CALL +clIcdGetFunctionAddressForPlatformKHR( + cl_platform_id platform, + const char* func_name) ; + +extern CL_API_ENTRY cl_int CL_API_CALL +clIcdSetPlatformDispatchDataKHR( + cl_platform_id platform, + void* dispatch_data) ; + #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ /*************************************************************** @@ -859,6 +949,9 @@ clIcdGetPlatformIDsKHR( #define CL_KHR_IL_PROGRAM_EXTENSION_NAME \ "cl_khr_il_program" + +#define CL_KHR_IL_PROGRAM_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_device_info */ #define CL_DEVICE_IL_VERSION_KHR 0x105B @@ -894,6 +987,9 @@ clCreateProgramWithILKHR( #define CL_KHR_IMAGE2D_FROM_BUFFER_EXTENSION_NAME \ "cl_khr_image2d_from_buffer" + +#define CL_KHR_IMAGE2D_FROM_BUFFER_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_device_info */ #define CL_DEVICE_IMAGE_PITCH_ALIGNMENT_KHR 0x104A #define CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT_KHR 0x104B @@ -905,6 +1001,9 @@ clCreateProgramWithILKHR( #define CL_KHR_INITIALIZE_MEMORY_EXTENSION_NAME \ "cl_khr_initialize_memory" + +#define CL_KHR_INITIALIZE_MEMORY_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_bitfield cl_context_memory_initialize_khr; /* cl_context_properties */ @@ -921,6 +1020,9 @@ typedef cl_bitfield cl_context_memory_initialize_khr; #define CL_KHR_TERMINATE_CONTEXT_EXTENSION_NAME \ "cl_khr_terminate_context" + +#define CL_KHR_TERMINATE_CONTEXT_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_bitfield cl_device_terminate_capability_khr; /* cl_device_info */ @@ -958,6 +1060,9 @@ clTerminateContextKHR( #define CL_KHR_SPIR_EXTENSION_NAME \ "cl_khr_spir" + +#define CL_KHR_SPIR_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_device_info */ #define CL_DEVICE_SPIR_VERSIONS 0x40E0 @@ -971,6 +1076,9 @@ clTerminateContextKHR( #define CL_KHR_CREATE_COMMAND_QUEUE_EXTENSION_NAME \ "cl_khr_create_command_queue" + +#define CL_KHR_CREATE_COMMAND_QUEUE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_properties cl_queue_properties_khr; @@ -1002,6 +1110,9 @@ clCreateCommandQueueWithPropertiesKHR( #define CL_NV_DEVICE_ATTRIBUTE_QUERY_EXTENSION_NAME \ "cl_nv_device_attribute_query" + +#define CL_NV_DEVICE_ATTRIBUTE_QUERY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000 #define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001 @@ -1018,6 +1129,9 @@ clCreateCommandQueueWithPropertiesKHR( #define CL_AMD_DEVICE_ATTRIBUTE_QUERY_EXTENSION_NAME \ "cl_amd_device_attribute_query" + +#define CL_AMD_DEVICE_ATTRIBUTE_QUERY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036 #define CL_DEVICE_TOPOLOGY_AMD 0x4037 @@ -1048,6 +1162,9 @@ clCreateCommandQueueWithPropertiesKHR( #define CL_ARM_PRINTF_EXTENSION_NAME \ "cl_arm_printf" + +#define CL_ARM_PRINTF_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_context_properties */ #define CL_PRINTF_CALLBACK_ARM 0x40B0 #define CL_PRINTF_BUFFERSIZE_ARM 0x40B1 @@ -1059,6 +1176,9 @@ clCreateCommandQueueWithPropertiesKHR( #define CL_EXT_DEVICE_FISSION_EXTENSION_NAME \ "cl_ext_device_fission" + +#define CL_EXT_DEVICE_FISSION_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_ulong cl_device_partition_property_ext; /* Error codes */ @@ -1145,6 +1265,9 @@ clCreateSubDevicesEXT( #define CL_EXT_MIGRATE_MEMOBJECT_EXTENSION_NAME \ "cl_ext_migrate_memobject" + +#define CL_EXT_MIGRATE_MEMOBJECT_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_bitfield cl_mem_migration_flags_ext; /* cl_mem_migration_flags_ext */ @@ -1188,6 +1311,9 @@ clEnqueueMigrateMemObjectEXT( #define CL_EXT_CXX_FOR_OPENCL_EXTENSION_NAME \ "cl_ext_cxx_for_opencl" + +#define CL_EXT_CXX_FOR_OPENCL_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_device_info */ #define CL_DEVICE_CXX_FOR_OPENCL_NUMERIC_VERSION_EXT 0x4230 @@ -1198,6 +1324,9 @@ clEnqueueMigrateMemObjectEXT( #define CL_QCOM_EXT_HOST_PTR_EXTENSION_NAME \ "cl_qcom_ext_host_ptr" + +#define CL_QCOM_EXT_HOST_PTR_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_uint cl_image_pitch_info_qcom; typedef struct _cl_mem_ext_host_ptr { cl_uint allocation_type; @@ -1258,6 +1387,9 @@ clGetDeviceImageInfoQCOM( #define CL_QCOM_EXT_HOST_PTR_IOCOHERENT_EXTENSION_NAME \ "cl_qcom_ext_host_ptr_iocoherent" + +#define CL_QCOM_EXT_HOST_PTR_IOCOHERENT_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_uint host_cache_policy */ #define CL_MEM_HOST_IOCOHERENT_QCOM 0x40A9 @@ -1268,6 +1400,9 @@ clGetDeviceImageInfoQCOM( #define CL_QCOM_ION_HOST_PTR_EXTENSION_NAME \ "cl_qcom_ion_host_ptr" + +#define CL_QCOM_ION_HOST_PTR_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* type cl_mem_ext_host_ptr */ typedef struct _cl_mem_ion_host_ptr { cl_mem_ext_host_ptr ext_host_ptr; @@ -1285,6 +1420,9 @@ typedef struct _cl_mem_ion_host_ptr { #define CL_QCOM_ANDROID_NATIVE_BUFFER_HOST_PTR_EXTENSION_NAME \ "cl_qcom_android_native_buffer_host_ptr" + +#define CL_QCOM_ANDROID_NATIVE_BUFFER_HOST_PTR_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* type cl_mem_ext_host_ptr */ typedef struct _cl_mem_android_native_buffer_host_ptr { cl_mem_ext_host_ptr ext_host_ptr; @@ -1301,6 +1439,9 @@ typedef struct _cl_mem_android_native_buffer_host_ptr { #define CL_IMG_YUV_IMAGE_EXTENSION_NAME \ "cl_img_yuv_image" + +#define CL_IMG_YUV_IMAGE_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_channel_order */ #define CL_NV21_IMG 0x40D0 #define CL_YV12_IMG 0x40D1 @@ -1312,6 +1453,9 @@ typedef struct _cl_mem_android_native_buffer_host_ptr { #define CL_IMG_CACHED_ALLOCATIONS_EXTENSION_NAME \ "cl_img_cached_allocations" + +#define CL_IMG_CACHED_ALLOCATIONS_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_mem_flags */ #define CL_MEM_USE_UNCACHED_CPU_MEMORY_IMG (1 << 26) #define CL_MEM_USE_CACHED_CPU_MEMORY_IMG (1 << 27) @@ -1323,6 +1467,9 @@ typedef struct _cl_mem_android_native_buffer_host_ptr { #define CL_IMG_USE_GRALLOC_PTR_EXTENSION_NAME \ "cl_img_use_gralloc_ptr" + +#define CL_IMG_USE_GRALLOC_PTR_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* Error codes */ #define CL_GRALLOC_RESOURCE_NOT_ACQUIRED_IMG 0x40D4 #define CL_INVALID_GRALLOC_OBJECT_IMG 0x40D5 @@ -1388,6 +1535,9 @@ clEnqueueReleaseGrallocObjectsIMG( #define CL_IMG_GENERATE_MIPMAP_EXTENSION_NAME \ "cl_img_generate_mipmap" + +#define CL_IMG_GENERATE_MIPMAP_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_uint cl_mipmap_filter_mode_img; /* cl_mipmap_filter_mode_img */ @@ -1436,11 +1586,22 @@ clEnqueueGenerateMipmapIMG( #define CL_IMG_MEM_PROPERTIES_EXTENSION_NAME \ "cl_img_mem_properties" + +#define CL_IMG_MEM_PROPERTIES_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_mem_properties */ #define CL_MEM_ALLOC_FLAGS_IMG 0x40D7 /* cl_mem_alloc_flags_img */ #define CL_MEM_ALLOC_RELAX_REQUIREMENTS_IMG (1 << 0) +#define CL_MEM_ALLOC_GPU_WRITE_COMBINE_IMG (1 << 1) +#define CL_MEM_ALLOC_GPU_CACHED_IMG (1 << 2) +#define CL_MEM_ALLOC_CPU_LOCAL_IMG (1 << 3) +#define CL_MEM_ALLOC_GPU_LOCAL_IMG (1 << 4) +#define CL_MEM_ALLOC_GPU_PRIVATE_IMG (1 << 5) + +/* cl_device_info */ +#define CL_DEVICE_MEMORY_CAPABILITIES_IMG 0x40D8 /*************************************************************** * cl_khr_subgroups @@ -1449,6 +1610,9 @@ clEnqueueGenerateMipmapIMG( #define CL_KHR_SUBGROUPS_EXTENSION_NAME \ "cl_khr_subgroups" + +#define CL_KHR_SUBGROUPS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + #if !defined(CL_VERSION_2_1) /* defined in CL.h for OpenCL 2.1 and newer */ typedef cl_uint cl_kernel_sub_group_info; @@ -1496,6 +1660,9 @@ clGetKernelSubGroupInfoKHR( #define CL_KHR_MIPMAP_IMAGE_EXTENSION_NAME \ "cl_khr_mipmap_image" + +#define CL_KHR_MIPMAP_IMAGE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_sampler_properties */ #define CL_SAMPLER_MIP_FILTER_MODE_KHR 0x1155 #define CL_SAMPLER_LOD_MIN_KHR 0x1156 @@ -1508,6 +1675,9 @@ clGetKernelSubGroupInfoKHR( #define CL_KHR_PRIORITY_HINTS_EXTENSION_NAME \ "cl_khr_priority_hints" + +#define CL_KHR_PRIORITY_HINTS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* To be used by clGetEventInfo */ typedef cl_uint cl_queue_priority_khr; @@ -1526,6 +1696,9 @@ typedef cl_uint cl_queue_priority_khr; #define CL_KHR_THROTTLE_HINTS_EXTENSION_NAME \ "cl_khr_throttle_hints" + +#define CL_KHR_THROTTLE_HINTS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* To be used by clGetEventInfo */ typedef cl_uint cl_queue_throttle_khr; @@ -1544,6 +1717,9 @@ typedef cl_uint cl_queue_throttle_khr; #define CL_KHR_SUBGROUP_NAMED_BARRIER_EXTENSION_NAME \ "cl_khr_subgroup_named_barrier" + +#define CL_KHR_SUBGROUP_NAMED_BARRIER_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_device_info */ #define CL_DEVICE_MAX_NAMED_BARRIER_COUNT_KHR 0x2035 @@ -1554,6 +1730,9 @@ typedef cl_uint cl_queue_throttle_khr; #define CL_KHR_EXTENDED_VERSIONING_EXTENSION_NAME \ "cl_khr_extended_versioning" + +#define CL_KHR_EXTENDED_VERSIONING_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + #define CL_VERSION_MAJOR_BITS_KHR 10 #define CL_VERSION_MINOR_BITS_KHR 10 #define CL_VERSION_PATCH_BITS_KHR 12 @@ -1597,6 +1776,9 @@ typedef struct _cl_name_version_khr { #define CL_KHR_DEVICE_UUID_EXTENSION_NAME \ "cl_khr_device_uuid" + +#define CL_KHR_DEVICE_UUID_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* Size Constants */ #define CL_UUID_SIZE_KHR 16 #define CL_LUID_SIZE_KHR 8 @@ -1615,6 +1797,9 @@ typedef struct _cl_name_version_khr { #define CL_KHR_PCI_BUS_INFO_EXTENSION_NAME \ "cl_khr_pci_bus_info" + +#define CL_KHR_PCI_BUS_INFO_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef struct _cl_device_pci_bus_info_khr { cl_uint pci_domain; cl_uint pci_bus; @@ -1633,6 +1818,9 @@ typedef struct _cl_device_pci_bus_info_khr { "cl_khr_suggested_local_work_size" +#define CL_KHR_SUGGESTED_LOCAL_WORK_SIZE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + + typedef cl_int CL_API_CALL clGetKernelSuggestedLocalWorkSizeKHR_t( cl_command_queue command_queue, @@ -1665,6 +1853,9 @@ clGetKernelSuggestedLocalWorkSizeKHR( #define CL_KHR_INTEGER_DOT_PRODUCT_EXTENSION_NAME \ "cl_khr_integer_dot_product" + +#define CL_KHR_INTEGER_DOT_PRODUCT_EXTENSION_VERSION CL_MAKE_VERSION(2, 0, 0) + typedef cl_bitfield cl_device_integer_dot_product_capabilities_khr; typedef struct _cl_device_integer_dot_product_acceleration_properties_khr { cl_bool signed_accelerated; @@ -1691,6 +1882,9 @@ typedef struct _cl_device_integer_dot_product_acceleration_properties_khr { #define CL_KHR_EXTERNAL_MEMORY_EXTENSION_NAME \ "cl_khr_external_memory" + +#define CL_KHR_EXTERNAL_MEMORY_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 1) + typedef cl_uint cl_external_memory_handle_type_khr; /* cl_platform_info */ @@ -1762,21 +1956,11 @@ clEnqueueReleaseExternalMemObjectsKHR( #define CL_KHR_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME \ "cl_khr_external_memory_dma_buf" -/* cl_external_memory_handle_type_khr */ -#define CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR 0x2067 -/*************************************************************** -* cl_khr_external_memory_dx -***************************************************************/ -#define cl_khr_external_memory_dx 1 -#define CL_KHR_EXTERNAL_MEMORY_DX_EXTENSION_NAME \ - "cl_khr_external_memory_dx" +#define CL_KHR_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) /* cl_external_memory_handle_type_khr */ -#define CL_EXTERNAL_MEMORY_HANDLE_D3D11_TEXTURE_KHR 0x2063 -#define CL_EXTERNAL_MEMORY_HANDLE_D3D11_TEXTURE_KMT_KHR 0x2064 -#define CL_EXTERNAL_MEMORY_HANDLE_D3D12_HEAP_KHR 0x2065 -#define CL_EXTERNAL_MEMORY_HANDLE_D3D12_RESOURCE_KHR 0x2066 +#define CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR 0x2067 /*************************************************************** * cl_khr_external_memory_opaque_fd @@ -1785,6 +1969,9 @@ clEnqueueReleaseExternalMemObjectsKHR( #define CL_KHR_EXTERNAL_MEMORY_OPAQUE_FD_EXTENSION_NAME \ "cl_khr_external_memory_opaque_fd" + +#define CL_KHR_EXTERNAL_MEMORY_OPAQUE_FD_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_external_memory_handle_type_khr */ #define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR 0x2060 @@ -1795,9 +1982,13 @@ clEnqueueReleaseExternalMemObjectsKHR( #define CL_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME \ "cl_khr_external_memory_win32" + +#define CL_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_VERSION CL_MAKE_VERSION(1, 1, 0) + /* cl_external_memory_handle_type_khr */ #define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR 0x2061 #define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR 0x2062 +#define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_NAME_KHR 0x2069 /*************************************************************** * cl_khr_external_semaphore @@ -1806,6 +1997,9 @@ clEnqueueReleaseExternalMemObjectsKHR( #define CL_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME \ "cl_khr_external_semaphore" + +#define CL_KHR_EXTERNAL_SEMAPHORE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 1) + typedef struct _cl_semaphore_khr * cl_semaphore_khr; typedef cl_uint cl_external_semaphore_handle_type_khr; @@ -1850,16 +2044,6 @@ clGetSemaphoreHandleForTypeKHR( #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ -/*************************************************************** -* cl_khr_external_semaphore_dx_fence -***************************************************************/ -#define cl_khr_external_semaphore_dx_fence 1 -#define CL_KHR_EXTERNAL_SEMAPHORE_DX_FENCE_EXTENSION_NAME \ - "cl_khr_external_semaphore_dx_fence" - -/* cl_external_semaphore_handle_type_khr */ -#define CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR 0x2059 - /*************************************************************** * cl_khr_external_semaphore_opaque_fd ***************************************************************/ @@ -1867,6 +2051,9 @@ clGetSemaphoreHandleForTypeKHR( #define CL_KHR_EXTERNAL_SEMAPHORE_OPAQUE_FD_EXTENSION_NAME \ "cl_khr_external_semaphore_opaque_fd" + +#define CL_KHR_EXTERNAL_SEMAPHORE_OPAQUE_FD_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_external_semaphore_handle_type_khr */ #define CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR 0x2055 @@ -1877,6 +2064,9 @@ clGetSemaphoreHandleForTypeKHR( #define CL_KHR_EXTERNAL_SEMAPHORE_SYNC_FD_EXTENSION_NAME \ "cl_khr_external_semaphore_sync_fd" + +#define CL_KHR_EXTERNAL_SEMAPHORE_SYNC_FD_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_properties cl_semaphore_reimport_properties_khr; /* cl_external_semaphore_handle_type_khr */ @@ -1903,15 +2093,23 @@ clReImportSemaphoreSyncFdKHR( #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ /*************************************************************** -* cl_khr_external_semaphore_win32 +* cl_khr_external_semaphore_win32 (beta) ***************************************************************/ +#if defined(CL_ENABLE_BETA_EXTENSIONS) + #define cl_khr_external_semaphore_win32 1 #define CL_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME \ "cl_khr_external_semaphore_win32" + +#define CL_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_VERSION CL_MAKE_VERSION(0, 9, 1) + /* cl_external_semaphore_handle_type_khr */ #define CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR 0x2056 #define CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR 0x2057 +#define CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_NAME_KHR 0x2068 + +#endif /* defined(CL_ENABLE_BETA_EXTENSIONS) */ /*************************************************************** * cl_khr_semaphore @@ -1920,6 +2118,9 @@ clReImportSemaphoreSyncFdKHR( #define CL_KHR_SEMAPHORE_EXTENSION_NAME \ "cl_khr_semaphore" + +#define CL_KHR_SEMAPHORE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* type cl_semaphore_khr */ typedef cl_properties cl_semaphore_properties_khr; typedef cl_uint cl_semaphore_info_khr; @@ -2067,6 +2268,9 @@ clRetainSemaphoreKHR( #define CL_ARM_IMPORT_MEMORY_EXTENSION_NAME \ "cl_arm_import_memory" + +#define CL_ARM_IMPORT_MEMORY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef intptr_t cl_import_properties_arm; /* cl_import_properties_arm */ @@ -2113,6 +2317,9 @@ clImportMemoryARM( #define CL_ARM_SHARED_VIRTUAL_MEMORY_EXTENSION_NAME \ "cl_arm_shared_virtual_memory" + +#define CL_ARM_SHARED_VIRTUAL_MEMORY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_bitfield cl_svm_mem_flags_arm; typedef cl_uint cl_kernel_exec_info_arm; typedef cl_bitfield cl_device_svm_capabilities_arm; @@ -2339,6 +2546,9 @@ clSetKernelExecInfoARM( #define CL_ARM_GET_CORE_ID_EXTENSION_NAME \ "cl_arm_get_core_id" + +#define CL_ARM_GET_CORE_ID_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_COMPUTE_UNITS_BITFIELD_ARM 0x40BF @@ -2351,6 +2561,9 @@ clSetKernelExecInfoARM( #define CL_ARM_JOB_SLOT_SELECTION_EXTENSION_NAME \ "cl_arm_job_slot_selection" + +#define CL_ARM_JOB_SLOT_SELECTION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_JOB_SLOTS_ARM 0x41E0 @@ -2364,6 +2577,9 @@ clSetKernelExecInfoARM( #define CL_ARM_SCHEDULING_CONTROLS_EXTENSION_NAME \ "cl_arm_scheduling_controls" + +#define CL_ARM_SCHEDULING_CONTROLS_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* Types */ typedef cl_bitfield cl_device_scheduling_controls_capabilities_arm; @@ -2403,6 +2619,9 @@ typedef cl_bitfield cl_device_scheduling_controls_capabilities_arm; #define CL_ARM_CONTROLLED_KERNEL_TERMINATION_EXTENSION_NAME \ "cl_arm_controlled_kernel_termination" + +#define CL_ARM_CONTROLLED_KERNEL_TERMINATION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* Types */ typedef cl_bitfield cl_device_controlled_termination_capabilities_arm; @@ -2433,6 +2652,9 @@ typedef cl_bitfield cl_device_controlled_termination_capabilities_arm; #define CL_ARM_PROTECTED_MEMORY_ALLOCATION_EXTENSION_NAME \ "cl_arm_protected_memory_allocation" + +#define CL_ARM_PROTECTED_MEMORY_ALLOCATION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + #define CL_MEM_PROTECTED_ALLOC_ARM ((cl_bitfield)1 << 36) /*************************************************************** @@ -2442,6 +2664,9 @@ typedef cl_bitfield cl_device_controlled_termination_capabilities_arm; #define CL_INTEL_EXEC_BY_LOCAL_THREAD_EXTENSION_NAME \ "cl_intel_exec_by_local_thread" + +#define CL_INTEL_EXEC_BY_LOCAL_THREAD_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_command_queue_properties - bitfield */ #define CL_QUEUE_THREAD_LOCAL_EXEC_ENABLE_INTEL ((cl_bitfield)1 << 31) @@ -2452,6 +2677,9 @@ typedef cl_bitfield cl_device_controlled_termination_capabilities_arm; #define CL_INTEL_DEVICE_ATTRIBUTE_QUERY_EXTENSION_NAME \ "cl_intel_device_attribute_query" + +#define CL_INTEL_DEVICE_ATTRIBUTE_QUERY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_bitfield cl_device_feature_capabilities_intel; /* cl_device_feature_capabilities_intel */ @@ -2474,6 +2702,9 @@ typedef cl_bitfield cl_device_feature_capabilities_intel; #define CL_INTEL_DEVICE_PARTITION_BY_NAMES_EXTENSION_NAME \ "cl_intel_device_partition_by_names" + +#define CL_INTEL_DEVICE_PARTITION_BY_NAMES_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + #define CL_DEVICE_PARTITION_BY_NAMES_INTEL 0x4052 #define CL_PARTITION_BY_NAMES_LIST_END_INTEL -1 @@ -2484,6 +2715,9 @@ typedef cl_bitfield cl_device_feature_capabilities_intel; #define CL_INTEL_ACCELERATOR_EXTENSION_NAME \ "cl_intel_accelerator" + +#define CL_INTEL_ACCELERATOR_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef struct _cl_accelerator_intel* cl_accelerator_intel; typedef cl_uint cl_accelerator_type_intel; typedef cl_uint cl_accelerator_info_intel; @@ -2572,6 +2806,9 @@ clReleaseAcceleratorINTEL( #define CL_INTEL_MOTION_ESTIMATION_EXTENSION_NAME \ "cl_intel_motion_estimation" + +#define CL_INTEL_MOTION_ESTIMATION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef struct _cl_motion_estimation_desc_intel { cl_uint mb_block_type; cl_uint subpixel_mode; @@ -2608,6 +2845,9 @@ typedef struct _cl_motion_estimation_desc_intel { #define CL_INTEL_ADVANCED_MOTION_ESTIMATION_EXTENSION_NAME \ "cl_intel_advanced_motion_estimation" + +#define CL_INTEL_ADVANCED_MOTION_ESTIMATION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_ME_VERSION_INTEL 0x407E @@ -2664,6 +2904,9 @@ typedef struct _cl_motion_estimation_desc_intel { #define CL_INTEL_SIMULTANEOUS_SHARING_EXTENSION_NAME \ "cl_intel_simultaneous_sharing" + +#define CL_INTEL_SIMULTANEOUS_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_SIMULTANEOUS_INTEROPS_INTEL 0x4104 #define CL_DEVICE_NUM_SIMULTANEOUS_INTEROPS_INTEL 0x4105 @@ -2675,6 +2918,9 @@ typedef struct _cl_motion_estimation_desc_intel { #define CL_INTEL_EGL_IMAGE_YUV_EXTENSION_NAME \ "cl_intel_egl_image_yuv" + +#define CL_INTEL_EGL_IMAGE_YUV_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_egl_image_properties_khr */ #define CL_EGL_YUV_PLANE_INTEL 0x4107 @@ -2685,6 +2931,9 @@ typedef struct _cl_motion_estimation_desc_intel { #define CL_INTEL_PACKED_YUV_EXTENSION_NAME \ "cl_intel_packed_yuv" + +#define CL_INTEL_PACKED_YUV_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_channel_order */ #define CL_YUYV_INTEL 0x4076 #define CL_UYVY_INTEL 0x4077 @@ -2698,6 +2947,9 @@ typedef struct _cl_motion_estimation_desc_intel { #define CL_INTEL_REQUIRED_SUBGROUP_SIZE_EXTENSION_NAME \ "cl_intel_required_subgroup_size" + +#define CL_INTEL_REQUIRED_SUBGROUP_SIZE_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_SUB_GROUP_SIZES_INTEL 0x4108 @@ -2714,10 +2966,15 @@ typedef struct _cl_motion_estimation_desc_intel { #define CL_INTEL_DRIVER_DIAGNOSTICS_EXTENSION_NAME \ "cl_intel_driver_diagnostics" -typedef cl_uint cl_diagnostics_verbose_level; + +#define CL_INTEL_DRIVER_DIAGNOSTICS_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + +typedef cl_bitfield cl_diagnostic_verbose_level_intel; /* cl_context_properties */ #define CL_CONTEXT_SHOW_DIAGNOSTICS_INTEL 0x4106 + +/* cl_diagnostic_verbose_level_intel */ #define CL_CONTEXT_DIAGNOSTICS_LEVEL_ALL_INTEL 0xff #define CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL (1 << 0) #define CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL (1 << 1) @@ -2730,6 +2987,9 @@ typedef cl_uint cl_diagnostics_verbose_level; #define CL_INTEL_PLANAR_YUV_EXTENSION_NAME \ "cl_intel_planar_yuv" + +#define CL_INTEL_PLANAR_YUV_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_channel_order */ #define CL_NV12_INTEL 0x410E @@ -2748,6 +3008,9 @@ typedef cl_uint cl_diagnostics_verbose_level; #define CL_INTEL_DEVICE_SIDE_AVC_MOTION_ESTIMATION_EXTENSION_NAME \ "cl_intel_device_side_avc_motion_estimation" + +#define CL_INTEL_DEVICE_SIDE_AVC_MOTION_ESTIMATION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_device_info */ #define CL_DEVICE_AVC_ME_VERSION_INTEL 0x410B #define CL_DEVICE_AVC_ME_SUPPORTS_TEXTURE_SAMPLER_USE_INTEL 0x410C @@ -2905,6 +3168,9 @@ typedef cl_uint cl_diagnostics_verbose_level; #define CL_INTEL_UNIFIED_SHARED_MEMORY_EXTENSION_NAME \ "cl_intel_unified_shared_memory" + +#define CL_INTEL_UNIFIED_SHARED_MEMORY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_bitfield cl_device_unified_shared_memory_capabilities_intel; typedef cl_properties cl_mem_properties_intel; typedef cl_bitfield cl_mem_alloc_flags_intel; @@ -3226,6 +3492,9 @@ clEnqueueMemsetINTEL( #define CL_INTEL_MEM_ALLOC_BUFFER_LOCATION_EXTENSION_NAME \ "cl_intel_mem_alloc_buffer_location" + +#define CL_INTEL_MEM_ALLOC_BUFFER_LOCATION_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_mem_properties_intel */ #define CL_MEM_ALLOC_BUFFER_LOCATION_INTEL 0x419E @@ -3239,6 +3508,9 @@ clEnqueueMemsetINTEL( #define CL_INTEL_CREATE_BUFFER_WITH_PROPERTIES_EXTENSION_NAME \ "cl_intel_create_buffer_with_properties" + +#define CL_INTEL_CREATE_BUFFER_WITH_PROPERTIES_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* type cl_mem_properties_intel */ @@ -3274,6 +3546,9 @@ clCreateBufferWithPropertiesINTEL( #define CL_INTEL_PROGRAM_SCOPE_HOST_PIPE_EXTENSION_NAME \ "cl_intel_program_scope_host_pipe" + +#define CL_INTEL_PROGRAM_SCOPE_HOST_PIPE_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* clGetEventInfo response when param_name is CL_EVENT_COMMAND_TYPE */ #define CL_COMMAND_READ_HOST_PIPE_INTEL 0x4214 #define CL_COMMAND_WRITE_HOST_PIPE_INTEL 0x4215 @@ -3348,6 +3623,9 @@ clEnqueueWriteHostPipeINTEL( #define CL_INTEL_MEM_CHANNEL_PROPERTY_EXTENSION_NAME \ "cl_intel_mem_channel_property" + +#define CL_INTEL_MEM_CHANNEL_PROPERTY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_mem_properties_intel */ #define CL_MEM_CHANNEL_INTEL 0x4213 @@ -3358,6 +3636,9 @@ clEnqueueWriteHostPipeINTEL( #define CL_INTEL_MEM_FORCE_HOST_MEMORY_EXTENSION_NAME \ "cl_intel_mem_force_host_memory" + +#define CL_INTEL_MEM_FORCE_HOST_MEMORY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_mem_flags */ #define CL_MEM_FORCE_HOST_MEMORY_INTEL (1 << 20) @@ -3368,6 +3649,9 @@ clEnqueueWriteHostPipeINTEL( #define CL_INTEL_COMMAND_QUEUE_FAMILIES_EXTENSION_NAME \ "cl_intel_command_queue_families" + +#define CL_INTEL_COMMAND_QUEUE_FAMILIES_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_bitfield cl_command_queue_capabilities_intel; #define CL_QUEUE_FAMILY_MAX_NAME_SIZE_INTEL 64 @@ -3412,6 +3696,9 @@ typedef struct _cl_queue_family_properties_intel { #define CL_INTEL_QUEUE_NO_SYNC_OPERATIONS_EXTENSION_NAME \ "cl_intel_queue_no_sync_operations" + +#define CL_INTEL_QUEUE_NO_SYNC_OPERATIONS_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_command_queue_properties */ #define CL_QUEUE_NO_SYNC_OPERATIONS_INTEL (1 << 29) @@ -3422,6 +3709,9 @@ typedef struct _cl_queue_family_properties_intel { #define CL_INTEL_SHARING_FORMAT_QUERY_EXTENSION_NAME \ "cl_intel_sharing_format_query" + +#define CL_INTEL_SHARING_FORMAT_QUERY_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /*************************************************************** * cl_ext_image_requirements_info ***************************************************************/ @@ -3431,6 +3721,9 @@ typedef struct _cl_queue_family_properties_intel { #define CL_EXT_IMAGE_REQUIREMENTS_INFO_EXTENSION_NAME \ "cl_ext_image_requirements_info" + +#define CL_EXT_IMAGE_REQUIREMENTS_INFO_EXTENSION_VERSION CL_MAKE_VERSION(0, 5, 0) + /* Types */ typedef cl_uint cl_image_requirements_info_ext; @@ -3487,6 +3780,9 @@ clGetImageRequirementsInfoEXT( #define CL_EXT_IMAGE_FROM_BUFFER_EXTENSION_NAME \ "cl_ext_image_from_buffer" + +#define CL_EXT_IMAGE_FROM_BUFFER_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_image_requirements_info_ext */ #define CL_IMAGE_REQUIREMENTS_SLICE_PITCH_ALIGNMENT_EXT 0x1291 @@ -3499,6 +3795,9 @@ clGetImageRequirementsInfoEXT( #define CL_LOADER_INFO_EXTENSION_NAME \ "cl_loader_info" + +#define CL_LOADER_INFO_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_uint cl_icdl_info; /* cl_icdl_info */ @@ -3536,6 +3835,9 @@ clGetICDLoaderInfoOCLICD( #define CL_KHR_DEPTH_IMAGES_EXTENSION_NAME \ "cl_khr_depth_images" + +#define CL_KHR_DEPTH_IMAGES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + #if !defined(CL_VERSION_2_0) /* cl_channel_order - defined in CL.h for OpenCL 2.0 and newer */ #define CL_DEPTH 0x10BD @@ -3549,6 +3851,9 @@ clGetICDLoaderInfoOCLICD( #define CL_EXT_FLOAT_ATOMICS_EXTENSION_NAME \ "cl_ext_float_atomics" + +#define CL_EXT_FLOAT_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_bitfield cl_device_fp_atomic_capabilities_ext; /* cl_device_fp_atomic_capabilities_ext */ @@ -3571,6 +3876,9 @@ typedef cl_bitfield cl_device_fp_atomic_capabilities_ext; #define CL_INTEL_CREATE_MEM_OBJECT_PROPERTIES_EXTENSION_NAME \ "cl_intel_create_mem_object_properties" + +#define CL_INTEL_CREATE_MEM_OBJECT_PROPERTIES_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* cl_mem_properties */ #define CL_MEM_LOCALLY_UNCACHED_RESOURCE_INTEL 0x4218 #define CL_MEM_DEVICE_ID_INTEL 0x4219 @@ -3583,6 +3891,9 @@ typedef cl_bitfield cl_device_fp_atomic_capabilities_ext; "cl_pocl_content_size" +#define CL_POCL_CONTENT_SIZE_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + + typedef cl_int CL_API_CALL clSetContentSizeBufferPoCL_t( cl_mem buffer, @@ -3607,10 +3918,453 @@ clSetContentSizeBufferPoCL( #define CL_EXT_IMAGE_RAW10_RAW12_EXTENSION_NAME \ "cl_ext_image_raw10_raw12" + +#define CL_EXT_IMAGE_RAW10_RAW12_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_channel_type */ #define CL_UNSIGNED_INT_RAW10_EXT 0x10E3 #define CL_UNSIGNED_INT_RAW12_EXT 0x10E4 +/*************************************************************** +* cl_khr_3d_image_writes +***************************************************************/ +#define cl_khr_3d_image_writes 1 +#define CL_KHR_3D_IMAGE_WRITES_EXTENSION_NAME \ + "cl_khr_3d_image_writes" + + +#define CL_KHR_3D_IMAGE_WRITES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_async_work_group_copy_fence +***************************************************************/ +#define cl_khr_async_work_group_copy_fence 1 +#define CL_KHR_ASYNC_WORK_GROUP_COPY_FENCE_EXTENSION_NAME \ + "cl_khr_async_work_group_copy_fence" + + +#define CL_KHR_ASYNC_WORK_GROUP_COPY_FENCE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_byte_addressable_store +***************************************************************/ +#define cl_khr_byte_addressable_store 1 +#define CL_KHR_BYTE_ADDRESSABLE_STORE_EXTENSION_NAME \ + "cl_khr_byte_addressable_store" + + +#define CL_KHR_BYTE_ADDRESSABLE_STORE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_device_enqueue_local_arg_types +***************************************************************/ +#define cl_khr_device_enqueue_local_arg_types 1 +#define CL_KHR_DEVICE_ENQUEUE_LOCAL_ARG_TYPES_EXTENSION_NAME \ + "cl_khr_device_enqueue_local_arg_types" + + +#define CL_KHR_DEVICE_ENQUEUE_LOCAL_ARG_TYPES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_expect_assume +***************************************************************/ +#define cl_khr_expect_assume 1 +#define CL_KHR_EXPECT_ASSUME_EXTENSION_NAME \ + "cl_khr_expect_assume" + + +#define CL_KHR_EXPECT_ASSUME_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_extended_async_copies +***************************************************************/ +#define cl_khr_extended_async_copies 1 +#define CL_KHR_EXTENDED_ASYNC_COPIES_EXTENSION_NAME \ + "cl_khr_extended_async_copies" + + +#define CL_KHR_EXTENDED_ASYNC_COPIES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_extended_bit_ops +***************************************************************/ +#define cl_khr_extended_bit_ops 1 +#define CL_KHR_EXTENDED_BIT_OPS_EXTENSION_NAME \ + "cl_khr_extended_bit_ops" + + +#define CL_KHR_EXTENDED_BIT_OPS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_global_int32_base_atomics +***************************************************************/ +#define cl_khr_global_int32_base_atomics 1 +#define CL_KHR_GLOBAL_INT32_BASE_ATOMICS_EXTENSION_NAME \ + "cl_khr_global_int32_base_atomics" + + +#define CL_KHR_GLOBAL_INT32_BASE_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_global_int32_extended_atomics +***************************************************************/ +#define cl_khr_global_int32_extended_atomics 1 +#define CL_KHR_GLOBAL_INT32_EXTENDED_ATOMICS_EXTENSION_NAME \ + "cl_khr_global_int32_extended_atomics" + + +#define CL_KHR_GLOBAL_INT32_EXTENDED_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_int64_base_atomics +***************************************************************/ +#define cl_khr_int64_base_atomics 1 +#define CL_KHR_INT64_BASE_ATOMICS_EXTENSION_NAME \ + "cl_khr_int64_base_atomics" + + +#define CL_KHR_INT64_BASE_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_int64_extended_atomics +***************************************************************/ +#define cl_khr_int64_extended_atomics 1 +#define CL_KHR_INT64_EXTENDED_ATOMICS_EXTENSION_NAME \ + "cl_khr_int64_extended_atomics" + + +#define CL_KHR_INT64_EXTENDED_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_kernel_clock (beta) +***************************************************************/ +#if defined(CL_ENABLE_BETA_EXTENSIONS) + +#define cl_khr_kernel_clock 1 +#define CL_KHR_KERNEL_CLOCK_EXTENSION_NAME \ + "cl_khr_kernel_clock" + + +#define CL_KHR_KERNEL_CLOCK_EXTENSION_VERSION CL_MAKE_VERSION(0, 9, 0) + +/* cl_device_info */ +#define CL_DEVICE_KERNEL_CLOCK_CAPABILITIES_KHR 0x1076 + +typedef cl_bitfield cl_device_kernel_clock_capabilities_khr; + +/* cl_device_kernel_clock_capabilities_khr */ +#define CL_DEVICE_KERNEL_CLOCK_SCOPE_DEVICE_KHR (1 << 0) +#define CL_DEVICE_KERNEL_CLOCK_SCOPE_WORK_GROUP_KHR (1 << 1) +#define CL_DEVICE_KERNEL_CLOCK_SCOPE_SUB_GROUP_KHR (1 << 2) + +#endif /* defined(CL_ENABLE_BETA_EXTENSIONS) */ + +/*************************************************************** +* cl_khr_local_int32_base_atomics +***************************************************************/ +#define cl_khr_local_int32_base_atomics 1 +#define CL_KHR_LOCAL_INT32_BASE_ATOMICS_EXTENSION_NAME \ + "cl_khr_local_int32_base_atomics" + + +#define CL_KHR_LOCAL_INT32_BASE_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_local_int32_extended_atomics +***************************************************************/ +#define cl_khr_local_int32_extended_atomics 1 +#define CL_KHR_LOCAL_INT32_EXTENDED_ATOMICS_EXTENSION_NAME \ + "cl_khr_local_int32_extended_atomics" + + +#define CL_KHR_LOCAL_INT32_EXTENDED_ATOMICS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_mipmap_image_writes +***************************************************************/ +#define cl_khr_mipmap_image_writes 1 +#define CL_KHR_MIPMAP_IMAGE_WRITES_EXTENSION_NAME \ + "cl_khr_mipmap_image_writes" + + +#define CL_KHR_MIPMAP_IMAGE_WRITES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_select_fprounding_mode +***************************************************************/ +#define cl_khr_select_fprounding_mode 1 +#define CL_KHR_SELECT_FPROUNDING_MODE_EXTENSION_NAME \ + "cl_khr_select_fprounding_mode" + + +#define CL_KHR_SELECT_FPROUNDING_MODE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_spirv_extended_debug_info +***************************************************************/ +#define cl_khr_spirv_extended_debug_info 1 +#define CL_KHR_SPIRV_EXTENDED_DEBUG_INFO_EXTENSION_NAME \ + "cl_khr_spirv_extended_debug_info" + + +#define CL_KHR_SPIRV_EXTENDED_DEBUG_INFO_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_spirv_linkonce_odr +***************************************************************/ +#define cl_khr_spirv_linkonce_odr 1 +#define CL_KHR_SPIRV_LINKONCE_ODR_EXTENSION_NAME \ + "cl_khr_spirv_linkonce_odr" + + +#define CL_KHR_SPIRV_LINKONCE_ODR_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_spirv_no_integer_wrap_decoration +***************************************************************/ +#define cl_khr_spirv_no_integer_wrap_decoration 1 +#define CL_KHR_SPIRV_NO_INTEGER_WRAP_DECORATION_EXTENSION_NAME \ + "cl_khr_spirv_no_integer_wrap_decoration" + + +#define CL_KHR_SPIRV_NO_INTEGER_WRAP_DECORATION_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_srgb_image_writes +***************************************************************/ +#define cl_khr_srgb_image_writes 1 +#define CL_KHR_SRGB_IMAGE_WRITES_EXTENSION_NAME \ + "cl_khr_srgb_image_writes" + + +#define CL_KHR_SRGB_IMAGE_WRITES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_ballot +***************************************************************/ +#define cl_khr_subgroup_ballot 1 +#define CL_KHR_SUBGROUP_BALLOT_EXTENSION_NAME \ + "cl_khr_subgroup_ballot" + + +#define CL_KHR_SUBGROUP_BALLOT_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_clustered_reduce +***************************************************************/ +#define cl_khr_subgroup_clustered_reduce 1 +#define CL_KHR_SUBGROUP_CLUSTERED_REDUCE_EXTENSION_NAME \ + "cl_khr_subgroup_clustered_reduce" + + +#define CL_KHR_SUBGROUP_CLUSTERED_REDUCE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_extended_types +***************************************************************/ +#define cl_khr_subgroup_extended_types 1 +#define CL_KHR_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME \ + "cl_khr_subgroup_extended_types" + + +#define CL_KHR_SUBGROUP_EXTENDED_TYPES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_non_uniform_arithmetic +***************************************************************/ +#define cl_khr_subgroup_non_uniform_arithmetic 1 +#define CL_KHR_SUBGROUP_NON_UNIFORM_ARITHMETIC_EXTENSION_NAME \ + "cl_khr_subgroup_non_uniform_arithmetic" + + +#define CL_KHR_SUBGROUP_NON_UNIFORM_ARITHMETIC_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_non_uniform_vote +***************************************************************/ +#define cl_khr_subgroup_non_uniform_vote 1 +#define CL_KHR_SUBGROUP_NON_UNIFORM_VOTE_EXTENSION_NAME \ + "cl_khr_subgroup_non_uniform_vote" + + +#define CL_KHR_SUBGROUP_NON_UNIFORM_VOTE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_rotate +***************************************************************/ +#define cl_khr_subgroup_rotate 1 +#define CL_KHR_SUBGROUP_ROTATE_EXTENSION_NAME \ + "cl_khr_subgroup_rotate" + + +#define CL_KHR_SUBGROUP_ROTATE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_shuffle +***************************************************************/ +#define cl_khr_subgroup_shuffle 1 +#define CL_KHR_SUBGROUP_SHUFFLE_EXTENSION_NAME \ + "cl_khr_subgroup_shuffle" + + +#define CL_KHR_SUBGROUP_SHUFFLE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_subgroup_shuffle_relative +***************************************************************/ +#define cl_khr_subgroup_shuffle_relative 1 +#define CL_KHR_SUBGROUP_SHUFFLE_RELATIVE_EXTENSION_NAME \ + "cl_khr_subgroup_shuffle_relative" + + +#define CL_KHR_SUBGROUP_SHUFFLE_RELATIVE_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_khr_work_group_uniform_arithmetic +***************************************************************/ +#define cl_khr_work_group_uniform_arithmetic 1 +#define CL_KHR_WORK_GROUP_UNIFORM_ARITHMETIC_EXTENSION_NAME \ + "cl_khr_work_group_uniform_arithmetic" + + +#define CL_KHR_WORK_GROUP_UNIFORM_ARITHMETIC_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/*************************************************************** +* cl_ext_buffer_device_address +***************************************************************/ +#define cl_ext_buffer_device_address 1 +#define CL_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME \ + "cl_ext_buffer_device_address" + + +#define CL_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 2) + +typedef cl_ulong cl_mem_device_address_ext; + + +typedef cl_int CL_API_CALL +clSetKernelArgDevicePointerEXT_t( + cl_kernel kernel, + cl_uint arg_index, + cl_mem_device_address_ext arg_value); + +typedef clSetKernelArgDevicePointerEXT_t * +clSetKernelArgDevicePointerEXT_fn CL_API_SUFFIX__VERSION_3_0; + +#if !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetKernelArgDevicePointerEXT( + cl_kernel kernel, + cl_uint arg_index, + cl_mem_device_address_ext arg_value) CL_API_SUFFIX__VERSION_3_0; + +#endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ + +/* cl_mem_properties */ +#define CL_MEM_DEVICE_PRIVATE_ADDRESS_EXT 0x5000 + +/* cl_mem_info */ +#define CL_MEM_DEVICE_ADDRESS_EXT 0x5001 + +/* cl_kernel_exec_info */ +#define CL_KERNEL_EXEC_INFO_DEVICE_PTRS_EXT 0x5002 + +/*************************************************************** +* cl_ext_image_unorm_int_2_101010 +***************************************************************/ +#define cl_ext_image_unorm_int_2_101010 1 +#define CL_EXT_IMAGE_UNORM_INT_2_101010_EXTENSION_NAME \ + "cl_ext_image_unorm_int_2_101010" + + +#define CL_EXT_IMAGE_UNORM_INT_2_101010_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/* cl_channel_type */ +#define CL_UNORM_INT_2_101010_EXT 0x10E5 + +/*************************************************************** +* cl_ext_immutable_memory_objects +***************************************************************/ +#define cl_ext_immutable_memory_objects 1 +#define CL_EXT_IMMUTABLE_MEMORY_OBJECTS_EXTENSION_NAME \ + "cl_ext_immutable_memory_objects" + + +#define CL_EXT_IMMUTABLE_MEMORY_OBJECTS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +/* cl_mem_flags */ +#define CL_MEM_IMMUTABLE_EXT (1 << 6) + +/*************************************************************** +* cl_img_cancel_command +***************************************************************/ +#define cl_img_cancel_command 1 +#define CL_IMG_CANCEL_COMMAND_EXTENSION_NAME \ + "cl_img_cancel_command" + + +#define CL_IMG_CANCEL_COMMAND_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + +/* Error codes */ +#define CL_CANCELLED_IMG -1126 + + +typedef cl_int CL_API_CALL +clCancelCommandsIMG_t( + const cl_event* event_list, + size_t num_events_in_list); + +typedef clCancelCommandsIMG_t * +clCancelCommandsIMG_fn ; + +#if !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) + +extern CL_API_ENTRY cl_int CL_API_CALL +clCancelCommandsIMG( + const cl_event* event_list, + size_t num_events_in_list) ; + +#endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ + +/*************************************************************** +* cl_qcom_perf_hint +***************************************************************/ +#define cl_qcom_perf_hint 1 +#define CL_QCOM_PERF_HINT_EXTENSION_NAME \ + "cl_qcom_perf_hint" + + +#define CL_QCOM_PERF_HINT_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 5) + +typedef cl_uint cl_perf_hint_qcom; + +/* cl_perf_hint_qcom */ +#define CL_PERF_HINT_HIGH_QCOM 0x40C3 +#define CL_PERF_HINT_NORMAL_QCOM 0x40C4 +#define CL_PERF_HINT_LOW_QCOM 0x40C5 + +/* cl_context_info */ +#define CL_CONTEXT_PERF_HINT_QCOM 0x40C2 + + +typedef cl_int CL_API_CALL +clSetPerfHintQCOM_t( + cl_context context, + cl_perf_hint_qcom perf_hint); + +typedef clSetPerfHintQCOM_t * +clSetPerfHintQCOM_fn ; + +#if !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetPerfHintQCOM( + cl_context context, + cl_perf_hint_qcom perf_hint) ; + +#endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ + #ifdef __cplusplus } #endif diff --git a/include/CL/cl_gl.h b/include/CL/cl_gl.h index f5b1e37bbe9..552560f71c4 100644 --- a/include/CL/cl_gl.h +++ b/include/CL/cl_gl.h @@ -51,6 +51,13 @@ extern "C" { #define CL_KHR_GL_SHARING_EXTENSION_NAME \ "cl_khr_gl_sharing" + +#define CL_KHR_GL_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + +typedef int cl_GLint; +typedef unsigned int cl_GLenum; +typedef unsigned int cl_GLuint; + typedef cl_uint cl_gl_context_info; /* Error codes */ @@ -313,6 +320,9 @@ clCreateFromGLTexture3D( #define CL_KHR_GL_EVENT_EXTENSION_NAME \ "cl_khr_gl_event" + +#define CL_KHR_GL_EVENT_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef struct __GLsync * cl_GLsync; /* cl_command_type */ @@ -345,6 +355,9 @@ clCreateEventFromGLsyncKHR( #define CL_KHR_GL_DEPTH_IMAGES_EXTENSION_NAME \ "cl_khr_gl_depth_images" + +#define CL_KHR_GL_DEPTH_IMAGES_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_channel_order */ #define CL_DEPTH_STENCIL 0x10BE @@ -358,6 +371,9 @@ clCreateEventFromGLsyncKHR( #define CL_KHR_GL_MSAA_SHARING_EXTENSION_NAME \ "cl_khr_gl_msaa_sharing" + +#define CL_KHR_GL_MSAA_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + /* cl_gl_texture_info */ #define CL_GL_NUM_SAMPLES 0x2012 @@ -368,6 +384,9 @@ clCreateEventFromGLsyncKHR( #define CL_INTEL_SHARING_FORMAT_QUERY_GL_EXTENSION_NAME \ "cl_intel_sharing_format_query_gl" + +#define CL_INTEL_SHARING_FORMAT_QUERY_GL_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* when cl_khr_gl_sharing is supported */ typedef cl_int CL_API_CALL diff --git a/include/CL/cl_layer.h b/include/CL/cl_layer.h index a43b89783db..245f7b53295 100644 --- a/include/CL/cl_layer.h +++ b/include/CL/cl_layer.h @@ -53,6 +53,9 @@ extern "C" { #define CL_LOADER_LAYERS_EXTENSION_NAME \ "cl_loader_layers" + +#define CL_LOADER_LAYERS_EXTENSION_VERSION CL_MAKE_VERSION(1, 0, 0) + typedef cl_uint cl_layer_info; typedef cl_uint cl_layer_api_version; diff --git a/include/CL/cl_platform.h b/include/CL/cl_platform.h index e7a0d6f4761..5f92d6faad4 100644 --- a/include/CL/cl_platform.h +++ b/include/CL/cl_platform.h @@ -77,7 +77,7 @@ extern "C" { #ifdef __GNUC__ #define CL_API_SUFFIX_DEPRECATED __attribute__((deprecated)) #define CL_API_PREFIX_DEPRECATED -#elif defined(_WIN32) +#elif defined(_MSC_VER) && !defined(__clang__) #define CL_API_SUFFIX_DEPRECATED #define CL_API_PREFIX_DEPRECATED __declspec(deprecated) #else @@ -361,11 +361,6 @@ typedef double cl_double; #include -/* Mirror types to GL types. Mirror types allow us to avoid deciding which 87s to load based on whether we are using GL or GLES here. */ -typedef unsigned int cl_GLuint; -typedef int cl_GLint; -typedef unsigned int cl_GLenum; - /* * Vector types * diff --git a/include/CL/cl_va_api_media_sharing_intel.h b/include/CL/cl_va_api_media_sharing_intel.h index 93f5d8bbcfd..9fb8863f24d 100644 --- a/include/CL/cl_va_api_media_sharing_intel.h +++ b/include/CL/cl_va_api_media_sharing_intel.h @@ -53,6 +53,9 @@ extern "C" { #define CL_INTEL_SHARING_FORMAT_QUERY_VA_API_EXTENSION_NAME \ "cl_intel_sharing_format_query_va_api" + +#define CL_INTEL_SHARING_FORMAT_QUERY_VA_API_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + /* when cl_intel_va_api_media_sharing is supported */ typedef cl_int CL_API_CALL @@ -89,6 +92,9 @@ clGetSupportedVA_APIMediaSurfaceFormatsINTEL( #define CL_INTEL_VA_API_MEDIA_SHARING_EXTENSION_NAME \ "cl_intel_va_api_media_sharing" + +#define CL_INTEL_VA_API_MEDIA_SHARING_EXTENSION_VERSION CL_MAKE_VERSION(0, 0, 0) + typedef cl_uint cl_va_api_device_source_intel; typedef cl_uint cl_va_api_device_set_intel; diff --git a/include/EGL/eglext_angle.h b/include/EGL/eglext_angle.h index c2f76a7aec7..9abe2ef6ba0 100644 --- a/include/EGL/eglext_angle.h +++ b/include/EGL/eglext_angle.h @@ -96,6 +96,9 @@ #ifndef EGL_ANGLE_platform_angle_webgpu #define EGL_ANGLE_platform_angle_webgpu 1 #define EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE 0x34DD +#define EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE 0x3468 +#define EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE 0x34F7 +#define EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE 0x34F6 #endif /* EGL_ANGLE_platform_angle_webgpu */ #ifndef EGL_ANGLE_platform_angle_vulkan @@ -183,6 +186,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLSt #ifndef EGL_ANGLE_create_context_webgl_compatibility #define EGL_ANGLE_create_context_webgl_compatibility 1 #define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC +#define EGL_CONTEXT_HARDENED_ANGLE 0x34F8 #endif /* EGL_ANGLE_create_context_webgl_compatibility */ #ifndef EGL_ANGLE_display_texture_share_group @@ -346,20 +350,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint #define EGL_CGL_PIXEL_FORMAT_ANGLE 0x3486 #endif -#ifndef EGL_ANGLE_ggp_stream_descriptor -#define EGL_ANGLE_ggp_stream_descriptor 1 -#define EGL_GGP_STREAM_DESCRIPTOR_ANGLE 0x348B -#endif /* EGL_ANGLE_ggp_stream_descriptor */ - -#ifndef EGL_ANGLE_swap_with_frame_token -#define EGL_ANGLE_swap_with_frame_token 1 -typedef khronos_uint64_t EGLFrameTokenANGLE; -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC)(EGLDisplay dpy, EGLSurface surface, EGLFrameTokenANGLE frametoken); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithFrameTokenANGLE(EGLDisplay dpy, EGLSurface surface, EGLFrameTokenANGLE frametoken); -#endif -#endif /* EGL_ANGLE_swap_with_frame_token */ - #ifndef EGL_ANGLE_prepare_swap_buffers #define EGL_ANGLE_prepare_swap_buffers 1 typedef EGLBoolean (EGLAPIENTRYP PFNEGLPREPARESWAPBUFFERSANGLEPROC)(EGLDisplay dpy, EGLSurface surface); @@ -444,6 +434,11 @@ EGLAPI void *EGLAPIENTRY eglCopyMetalSharedEventANGLE(EGLDisplay dpy, EGLSync sy #endif #endif /* EGL_ANGLE_metal_shared_event_sync */ +#ifndef EGL_ANGLE_metal_commands_scheduled_sync +#define EGL_ANGLE_metal_commands_scheduled_sync 1 +#define EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE 0x34E0 +#endif /* EGL_ANGLE_metal_commands_scheduled_sync */ + #ifndef EGL_ANGLE_global_fence_sync #define EGL_ANGLE_global_fence_sync 1 #define EGL_SYNC_GLOBAL_FENCE_ANGLE 0x34DE @@ -462,6 +457,24 @@ EGLAPI void EGLAPIENTRY eglSetValidationEnabledANGLE(EGLBoolean validationState) #define EGL_CONTEXT_MEMORY_USAGE_ANGLE 0x3462 #endif /* EGL_ANGLE_memory_usage_report */ +#ifndef EGL_ANGLE_device_webgpu +#define EGL_ANGLE_device_webgpu 1 +#define EGL_WEBGPU_DEVICE_ANGLE 0x34F3 +#define EGL_WEBGPU_ADAPTER_ANGLE 0x34F4 +#endif /* EGL_ANGLE_device_webgpu */ + +#ifndef ANGLE_webgpu_texture_client_buffer +#define ANGLE_webgpu_texture_client_buffer 1 +#define EGL_WEBGPU_TEXTURE_ANGLE 0x34F5 +#define EGL_TEXTURE_TYPE_ANGLE 0x345C +#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D +#endif /* ANGLE_webgpu_texture_client_buffer */ + +#ifndef EGL_ANGLE_create_context_passthrough_shaders +#define EGL_ANGLE_create_context_passthrough_shaders 1 +#define EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE 0x3463 +#endif /* EGL_ANGLE_create_context_passthrough_shaders */ + // clang-format on #endif // INCLUDE_EGL_EGLEXT_ANGLE_ diff --git a/include/GLES2/gl2ext.h b/include/GLES2/gl2ext.h index 25622b9968a..4e97ac6a9ea 100644 --- a/include/GLES2/gl2ext.h +++ b/include/GLES2/gl2ext.h @@ -6,7 +6,7 @@ extern "C" { #endif /* -** Copyright 2013-2020 The Khronos Group Inc. +** Copyright 2013-2025 The Khronos Group Inc. ** SPDX-License-Identifier: MIT ** ** This header is generated from the Khronos OpenGL / OpenGL ES XML @@ -19,7 +19,7 @@ extern "C" { #define GL_APIENTRYP GL_APIENTRY* #endif -/* Generated on date 20210107 */ +/* Generated on date 20251023 */ /* Generated C header for: * API: gles2 @@ -1052,6 +1052,21 @@ GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei #define GL_ARM_rgba8 1 #endif /* GL_ARM_rgba8 */ +#ifndef GL_ARM_shader_core_properties +#define GL_ARM_shader_core_properties 1 +#define GL_SHADER_CORE_COUNT_ARM 0x96F0 +#define GL_SHADER_CORE_ACTIVE_COUNT_ARM 0x96F1 +#define GL_SHADER_CORE_PRESENT_MASK_ARM 0x96F2 +#define GL_SHADER_CORE_MAX_WARP_COUNT_ARM 0x96F3 +#define GL_SHADER_CORE_PIXEL_RATE_ARM 0x96F4 +#define GL_SHADER_CORE_TEXEL_RATE_ARM 0x96F5 +#define GL_SHADER_CORE_FMA_RATE_ARM 0x96F6 +typedef void (GL_APIENTRYP PFNGLMAXACTIVESHADERCORESARMPROC) (GLuint count); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glMaxActiveShaderCoresARM (GLuint count); +#endif +#endif /* GL_ARM_shader_core_properties */ + #ifndef GL_ARM_shader_framebuffer_fetch #define GL_ARM_shader_framebuffer_fetch 1 #define GL_FETCH_PER_SAMPLE_ARM 0x8F65 @@ -1419,6 +1434,56 @@ GL_APICALL void GL_APIENTRY glNamedBufferStorageExternalEXT (GLuint buffer, GLin #define GL_EXT_float_blend 1 #endif /* GL_EXT_float_blend */ +#ifndef GL_EXT_fragment_shading_rate +#define GL_EXT_fragment_shading_rate 1 +#define GL_SHADING_RATE_1X1_PIXELS_EXT 0x96A6 +#define GL_SHADING_RATE_1X2_PIXELS_EXT 0x96A7 +#define GL_SHADING_RATE_2X1_PIXELS_EXT 0x96A8 +#define GL_SHADING_RATE_2X2_PIXELS_EXT 0x96A9 +#define GL_SHADING_RATE_1X4_PIXELS_EXT 0x96AA +#define GL_SHADING_RATE_4X1_PIXELS_EXT 0x96AB +#define GL_SHADING_RATE_4X2_PIXELS_EXT 0x96AC +#define GL_SHADING_RATE_2X4_PIXELS_EXT 0x96AD +#define GL_SHADING_RATE_4X4_PIXELS_EXT 0x96AE +#define GL_SHADING_RATE_EXT 0x96D0 +#define GL_SHADING_RATE_ATTACHMENT_EXT 0x96D1 +#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT 0x96D2 +#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT 0x96D3 +#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT 0x96D4 +#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT 0x96D5 +#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT 0x96D6 +#define GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT 0x96D7 +#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT 0x96D8 +#define GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT 0x96D9 +#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT 0x96DA +#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT 0x96DB +#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT 0x96DC +#define GL_FRAGMENT_SHADING_RATE_WITH_SHADER_DEPTH_STENCIL_WRITES_SUPPORTED_EXT 0x96DD +#define GL_FRAGMENT_SHADING_RATE_WITH_SAMPLE_MASK_SUPPORTED_EXT 0x96DE +#define GL_FRAGMENT_SHADING_RATE_ATTACHMENT_WITH_DEFAULT_FRAMEBUFFER_SUPPORTED_EXT 0x96DF +#define GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT 0x8F6F +typedef void (GL_APIENTRYP PFNGLGETFRAGMENTSHADINGRATESEXTPROC) (GLsizei samples, GLsizei maxCount, GLsizei *count, GLenum *shadingRates); +typedef void (GL_APIENTRYP PFNGLSHADINGRATEEXTPROC) (GLenum rate); +typedef void (GL_APIENTRYP PFNGLSHADINGRATECOMBINEROPSEXTPROC) (GLenum combinerOp0, GLenum combinerOp1); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERSHADINGRATEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint baseLayer, GLsizei numLayers, GLsizei texelWidth, GLsizei texelHeight); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetFragmentShadingRatesEXT (GLsizei samples, GLsizei maxCount, GLsizei *count, GLenum *shadingRates); +GL_APICALL void GL_APIENTRY glShadingRateEXT (GLenum rate); +GL_APICALL void GL_APIENTRY glShadingRateCombinerOpsEXT (GLenum combinerOp0, GLenum combinerOp1); +GL_APICALL void GL_APIENTRY glFramebufferShadingRateEXT (GLenum target, GLenum attachment, GLuint texture, GLint baseLayer, GLsizei numLayers, GLsizei texelWidth, GLsizei texelHeight); +#endif +#endif /* GL_EXT_fragment_shading_rate */ + +#ifndef GL_EXT_framebuffer_blit_layers +#define GL_EXT_framebuffer_blit_layers 1 +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERLAYERSEXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERLAYEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlitFramebufferLayersEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void GL_APIENTRY glBlitFramebufferLayerEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter); +#endif +#endif /* GL_EXT_framebuffer_blit_layers */ + #ifndef GL_EXT_geometry_point_size #define GL_EXT_geometry_point_size 1 #endif /* GL_EXT_geometry_point_size */ @@ -1572,6 +1637,86 @@ GL_APICALL void GL_APIENTRY glImportMemoryWin32NameEXT (GLuint memory, GLuint64 #endif #endif /* GL_EXT_memory_object_win32 */ +#ifndef GL_EXT_mesh_shader +#define GL_EXT_mesh_shader 1 +#define GL_MESH_SHADER_EXT 0x9559 +#define GL_TASK_SHADER_EXT 0x955A +#define GL_MAX_MESH_UNIFORM_BLOCKS_EXT 0x8E60 +#define GL_MAX_MESH_TEXTURE_IMAGE_UNITS_EXT 0x8E61 +#define GL_MAX_MESH_IMAGE_UNIFORMS_EXT 0x8E62 +#define GL_MAX_MESH_UNIFORM_COMPONENTS_EXT 0x8E63 +#define GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_EXT 0x8E64 +#define GL_MAX_MESH_ATOMIC_COUNTERS_EXT 0x8E65 +#define GL_MAX_MESH_SHADER_STORAGE_BLOCKS_EXT 0x8E66 +#define GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_EXT 0x8E67 +#define GL_MAX_TASK_UNIFORM_BLOCKS_EXT 0x8E68 +#define GL_MAX_TASK_TEXTURE_IMAGE_UNITS_EXT 0x8E69 +#define GL_MAX_TASK_IMAGE_UNIFORMS_EXT 0x8E6A +#define GL_MAX_TASK_UNIFORM_COMPONENTS_EXT 0x8E6B +#define GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_EXT 0x8E6C +#define GL_MAX_TASK_ATOMIC_COUNTERS_EXT 0x8E6D +#define GL_MAX_TASK_SHADER_STORAGE_BLOCKS_EXT 0x8E6E +#define GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_EXT 0x8E6F +#define GL_MAX_TASK_WORK_GROUP_TOTAL_COUNT_EXT 0x9740 +#define GL_MAX_MESH_WORK_GROUP_TOTAL_COUNT_EXT 0x9741 +#define GL_MAX_MESH_WORK_GROUP_INVOCATIONS_EXT 0x9757 +#define GL_MAX_TASK_WORK_GROUP_INVOCATIONS_EXT 0x9759 +#define GL_MAX_TASK_PAYLOAD_SIZE_EXT 0x9742 +#define GL_MAX_TASK_SHARED_MEMORY_SIZE_EXT 0x9743 +#define GL_MAX_MESH_SHARED_MEMORY_SIZE_EXT 0x9744 +#define GL_MAX_TASK_PAYLOAD_AND_SHARED_MEMORY_SIZE_EXT 0x9745 +#define GL_MAX_MESH_PAYLOAD_AND_SHARED_MEMORY_SIZE_EXT 0x9746 +#define GL_MAX_MESH_OUTPUT_MEMORY_SIZE_EXT 0x9747 +#define GL_MAX_MESH_PAYLOAD_AND_OUTPUT_MEMORY_SIZE_EXT 0x9748 +#define GL_MAX_MESH_OUTPUT_VERTICES_EXT 0x9538 +#define GL_MAX_MESH_OUTPUT_PRIMITIVES_EXT 0x9756 +#define GL_MAX_MESH_OUTPUT_COMPONENTS_EXT 0x9749 +#define GL_MAX_MESH_OUTPUT_LAYERS_EXT 0x974A +#define GL_MAX_MESH_MULTIVIEW_VIEW_COUNT_EXT 0x9557 +#define GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_EXT 0x92DF +#define GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_EXT 0x9543 +#define GL_MAX_PREFERRED_TASK_WORK_GROUP_INVOCATIONS_EXT 0x974B +#define GL_MAX_PREFERRED_MESH_WORK_GROUP_INVOCATIONS_EXT 0x974C +#define GL_MESH_PREFERS_LOCAL_INVOCATION_VERTEX_OUTPUT_EXT 0x974D +#define GL_MESH_PREFERS_LOCAL_INVOCATION_PRIMITIVE_OUTPUT_EXT 0x974E +#define GL_MESH_PREFERS_COMPACT_VERTEX_OUTPUT_EXT 0x974F +#define GL_MESH_PREFERS_COMPACT_PRIMITIVE_OUTPUT_EXT 0x9750 +#define GL_MAX_TASK_WORK_GROUP_COUNT_EXT 0x9751 +#define GL_MAX_MESH_WORK_GROUP_COUNT_EXT 0x9752 +#define GL_MAX_MESH_WORK_GROUP_SIZE_EXT 0x9758 +#define GL_MAX_TASK_WORK_GROUP_SIZE_EXT 0x975A +#define GL_MESH_WORK_GROUP_SIZE_EXT 0x953E +#define GL_TASK_WORK_GROUP_SIZE_EXT 0x953F +#define GL_MESH_VERTICES_OUT_EXT 0x9579 +#define GL_MESH_PRIMITIVES_OUT_EXT 0x957A +#define GL_MESH_OUTPUT_TYPE_EXT 0x957B +#define GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_EXT 0x959C +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_EXT 0x959D +#define GL_REFERENCED_BY_MESH_SHADER_EXT 0x95A0 +#define GL_REFERENCED_BY_TASK_SHADER_EXT 0x95A1 +#define GL_TASK_SHADER_INVOCATIONS_EXT 0x9753 +#define GL_MESH_SHADER_INVOCATIONS_EXT 0x9754 +#define GL_MESH_PRIMITIVES_GENERATED_EXT 0x9755 +#define GL_MESH_SHADER_BIT_EXT 0x00000040 +#define GL_TASK_SHADER_BIT_EXT 0x00000080 +#define GL_MESH_SUBROUTINE_EXT 0x957C +#define GL_TASK_SUBROUTINE_EXT 0x957D +#define GL_MESH_SUBROUTINE_UNIFORM_EXT 0x957E +#define GL_TASK_SUBROUTINE_UNIFORM_EXT 0x957F +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_EXT 0x959E +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_EXT 0x959F +typedef void (GL_APIENTRYP PFNGLDRAWMESHTASKSEXTPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (GL_APIENTRYP PFNGLDRAWMESHTASKSINDIRECTEXTPROC) (GLintptr indirect); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTEXTPROC) (GLintptr indirect, GLsizei drawcount, GLsizei stride); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTCOUNTEXTPROC) (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawMeshTasksEXT (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +GL_APICALL void GL_APIENTRY glDrawMeshTasksIndirectEXT (GLintptr indirect); +GL_APICALL void GL_APIENTRY glMultiDrawMeshTasksIndirectEXT (GLintptr indirect, GLsizei drawcount, GLsizei stride); +GL_APICALL void GL_APIENTRY glMultiDrawMeshTasksIndirectCountEXT (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#endif +#endif /* GL_EXT_mesh_shader */ + #ifndef GL_EXT_multi_draw_arrays #define GL_EXT_multi_draw_arrays 1 typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); @@ -1802,6 +1947,10 @@ GL_APICALL void GL_APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLe #endif #endif /* GL_EXT_semaphore_win32 */ +#ifndef GL_EXT_separate_depth_stencil +#define GL_EXT_separate_depth_stencil 1 +#endif /* GL_EXT_separate_depth_stencil */ + #ifndef GL_EXT_separate_shader_objects #define GL_EXT_separate_shader_objects 1 #define GL_ACTIVE_PROGRAM_EXT 0x8259 @@ -1812,7 +1961,7 @@ GL_APICALL void GL_APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLe #define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar *const*strings); typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); @@ -1857,7 +2006,7 @@ typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint progra #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); -GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); +GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar *const*strings); GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); @@ -1957,10 +2106,18 @@ GL_APICALL void GL_APIENTRY glClearPixelLocalStorageuiEXT (GLsizei offset, GLsiz #endif #endif /* GL_EXT_shader_pixel_local_storage2 */ +#ifndef GL_EXT_shader_samples_identical +#define GL_EXT_shader_samples_identical 1 +#endif /* GL_EXT_shader_samples_identical */ + #ifndef GL_EXT_shader_texture_lod #define GL_EXT_shader_texture_lod 1 #endif /* GL_EXT_shader_texture_lod */ +#ifndef GL_EXT_shader_texture_samples +#define GL_EXT_shader_texture_samples 1 +#endif /* GL_EXT_shader_texture_samples */ + #ifndef GL_EXT_shadow_samplers #define GL_EXT_shadow_samplers 1 #define GL_TEXTURE_COMPARE_MODE_EXT 0x884C @@ -2327,6 +2484,16 @@ GL_APICALL void GL_APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, c #define GL_GCCSO_SHADER_BINARY_FJ 0x9260 #endif /* GL_FJ_shader_binary_GCCSO */ +#ifndef GL_HUAWEI_program_binary +#define GL_HUAWEI_program_binary 1 +#define GL_HUAWEI_PROGRAM_BINARY 0x9771 +#endif /* GL_HUAWEI_program_binary */ + +#ifndef GL_HUAWEI_shader_binary +#define GL_HUAWEI_shader_binary 1 +#define GL_HUAWEI_SHADER_BINARY 0x9770 +#endif /* GL_HUAWEI_shader_binary */ + #ifndef GL_IMG_bindless_texture #define GL_IMG_bindless_texture 1 typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLEIMGPROC) (GLuint texture); @@ -2474,6 +2641,11 @@ GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint quer #endif #endif /* GL_INTEL_performance_query */ +#ifndef GL_MESA_bgra +#define GL_MESA_bgra 1 +#define GL_BGR_EXT 0x80E0 +#endif /* GL_MESA_bgra */ + #ifndef GL_MESA_framebuffer_flip_x #define GL_MESA_framebuffer_flip_x 1 #define GL_FRAMEBUFFER_FLIP_X_MESA 0x8BBC @@ -2500,10 +2672,42 @@ GL_APICALL void GL_APIENTRY glGetFramebufferParameterivMESA (GLenum target, GLen #define GL_PROGRAM_BINARY_FORMAT_MESA 0x875F #endif /* GL_MESA_program_binary_formats */ +#ifndef GL_MESA_sampler_objects +#define GL_MESA_sampler_objects 1 +#define GL_SAMPLER_BINDING 0x8919 +typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); +typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); +GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); +GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); +#endif +#endif /* GL_MESA_sampler_objects */ + #ifndef GL_MESA_shader_integer_functions #define GL_MESA_shader_integer_functions 1 #endif /* GL_MESA_shader_integer_functions */ +#ifndef GL_MESA_texture_const_bandwidth +#define GL_MESA_texture_const_bandwidth 1 +#define GL_CONST_BW_TILING_MESA 0x8BBE +#endif /* GL_MESA_texture_const_bandwidth */ + #ifndef GL_NVX_blend_equation_advanced_multi_draw_buffers #define GL_NVX_blend_equation_advanced_multi_draw_buffers 1 #endif /* GL_NVX_blend_equation_advanced_multi_draw_buffers */ @@ -3133,6 +3337,13 @@ GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei coun #endif #endif /* GL_NV_non_square_matrices */ +#ifndef GL_NV_pack_subimage +#define GL_NV_pack_subimage 1 +#define GL_PACK_ROW_LENGTH_NV 0x0D02 +#define GL_PACK_SKIP_ROWS_NV 0x0D03 +#define GL_PACK_SKIP_PIXELS_NV 0x0D04 +#endif /* GL_NV_pack_subimage */ + #ifndef GL_NV_path_rendering #define GL_NV_path_rendering 1 typedef double GLdouble; @@ -3341,7 +3552,7 @@ typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GL typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode); typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); +typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount); typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); @@ -3418,7 +3629,7 @@ GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fi GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode); GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); +GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount); GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); @@ -3630,6 +3841,14 @@ GL_APICALL void GL_APIENTRY glShadingRateSampleOrderCustomNV (GLenum rate, GLuin #define GL_NV_stereo_view_rendering 1 #endif /* GL_NV_stereo_view_rendering */ +#ifndef GL_NV_texture_barrier +#define GL_NV_texture_barrier 1 +typedef void (GL_APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTextureBarrierNV (void); +#endif +#endif /* GL_NV_texture_barrier */ + #ifndef GL_NV_texture_border_clamp #define GL_NV_texture_border_clamp 1 #define GL_TEXTURE_BORDER_COLOR_NV 0x1004 @@ -3726,8 +3945,10 @@ GL_APICALL void GL_APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, #define GL_MAX_VIEWS_OVR 0x9631 #define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633 typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +typedef void (GL_APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +GL_APICALL void GL_APIENTRY glNamedFramebufferTextureMultiviewOVR (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); #endif #endif /* GL_OVR_multiview */ @@ -3864,6 +4085,14 @@ GL_APICALL void GL_APIENTRY glTexEstimateMotionRegionsQCOM (GLuint ref, GLuint t #define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 #endif /* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_render_sRGB_R8_RG8 +#define GL_QCOM_render_sRGB_R8_RG8 1 +#endif /* GL_QCOM_render_sRGB_R8_RG8 */ + +#ifndef GL_QCOM_render_shared_exponent +#define GL_QCOM_render_shared_exponent 1 +#endif /* GL_QCOM_render_shared_exponent */ + #ifndef GL_QCOM_shader_framebuffer_fetch_noncoherent #define GL_QCOM_shader_framebuffer_fetch_noncoherent 1 #define GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM 0x96A2 @@ -3917,6 +4146,11 @@ GL_APICALL void GL_APIENTRY glTextureFoveationParametersQCOM (GLuint texture, GL #define GL_MAX_SHADER_SUBSAMPLED_IMAGE_UNITS_QCOM 0x8FA1 #endif /* GL_QCOM_texture_foveated_subsampled_layout */ +#ifndef GL_QCOM_texture_lod_bias +#define GL_QCOM_texture_lod_bias 1 +#define GL_TEXTURE_LOD_BIAS_QCOM 0x8C96 +#endif /* GL_QCOM_texture_lod_bias */ + #ifndef GL_QCOM_tiled_rendering #define GL_QCOM_tiled_rendering 1 #define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 @@ -3964,6 +4198,12 @@ GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); #define GL_WRITEONLY_RENDERING_QCOM 0x8823 #endif /* GL_QCOM_writeonly_rendering */ +#ifndef GL_QCOM_ycbcr_degamma +#define GL_QCOM_ycbcr_degamma 1 +#define GL_TEXTURE_Y_DEGAMMA_QCOM 0x9710 +#define GL_TEXTURE_CBCR_DEGAMMA_QCOM 0x9711 +#endif /* GL_QCOM_ycbcr_degamma */ + #ifndef GL_VIV_shader_binary #define GL_VIV_shader_binary 1 #define GL_SHADER_BINARY_VIV 0x8FC4 diff --git a/include/GLES2/gl2ext_angle.h b/include/GLES2/gl2ext_angle.h index e86dfd066c0..46b52b05a9f 100644 --- a/include/GLES2/gl2ext_angle.h +++ b/include/GLES2/gl2ext_angle.h @@ -238,11 +238,6 @@ GL_APICALL void GL_APIENTRY glCopySubTexture3DANGLE(GLuint sourceId, #endif #endif /* GL_ANGLE_copy_texture_3d */ -#ifndef GL_CHROMIUM_sync_query -#define GL_CHROMIUM_sync_query 1 -#define GL_COMMANDS_COMPLETED_CHROMIUM 0x84F7 -#endif /* GL_CHROMIUM_sync_query */ - #ifndef GL_EXT_texture_compression_s3tc_srgb #define GL_EXT_texture_compression_s3tc_srgb 1 #define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C @@ -332,6 +327,9 @@ typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVROBUSTANGLEPROC) (GLuint typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVROBUSTANGLEPROC)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VROBUSTANGLEPROC)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params); typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VROBUSTANGLEPROC)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params); +/* The following two are introduced by GL_ANGLE_shader_pixel_local_storage */ +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC) (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC) (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glGetBooleanvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data); GL_APICALL void GL_APIENTRY glGetBufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); @@ -397,6 +395,9 @@ GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivRobustANGLE (GLuint sampler GL_APICALL void GL_APIENTRY glGetQueryObjectivRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); GL_APICALL void GL_APIENTRY glGetQueryObjecti64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params); GL_APICALL void GL_APIENTRY glGetQueryObjectui64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params); +/* The following two are introduced by GL_ANGLE_shader_pixel_local_storage */ +GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterfvRobustANGLE (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivRobustANGLE (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); #endif #endif /* GL_ANGLE_robust_client_memory */ @@ -615,20 +616,19 @@ GL_APICALL void GL_APIENTRY glReleaseTexturesANGLE(GLuint numTexture, const GLui #ifndef GL_ANGLE_shader_pixel_local_storage #define GL_ANGLE_shader_pixel_local_storage 1 #define GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE 0x96E0 -#define GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE 0x96E1 -#define GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE 0x96E2 -#define GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE 0x96E3 -#define GL_LOAD_OP_ZERO_ANGLE 0x96E4 -#define GL_LOAD_OP_CLEAR_ANGLE 0x96E5 -#define GL_LOAD_OP_LOAD_ANGLE 0x96E6 -#define GL_STORE_OP_STORE_ANGLE 0x96E7 -#define GL_PIXEL_LOCAL_FORMAT_ANGLE 0x96E8 -#define GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE 0x96E9 -#define GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE 0x96EA -#define GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE 0x96EB -#define GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE 0x96EC -#define GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE 0x96ED -#define GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE 0x96EE +#define GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE 0x96E1 +#define GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE 0x96E2 +#define GL_LOAD_OP_ZERO_ANGLE 0x96E3 +#define GL_LOAD_OP_CLEAR_ANGLE 0x96E4 +#define GL_LOAD_OP_LOAD_ANGLE 0x96E5 +#define GL_STORE_OP_STORE_ANGLE 0x96E6 +#define GL_PIXEL_LOCAL_FORMAT_ANGLE 0x96E7 +#define GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE 0x96E8 +#define GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE 0x96E9 +#define GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE 0x96EA +#define GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE 0x96EB +#define GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE 0x96EC +#define GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE 0x96ED typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERMEMORYLESSPIXELLOCALSTORAGEANGLEPROC) (GLint plane, GLenum internalformat); typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREPIXELLOCALSTORAGEANGLEPROC) (GLint plane, GLuint backingtexture, GLint level, GLint layer); typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALCLEARVALUEFVANGLEPROC) (GLint plane, const GLfloat value[]); @@ -641,8 +641,6 @@ typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGEINTERRUPTANGLEPROC) typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGERESTOREANGLEPROC) (void); typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVANGLEPROC) (GLint plane, GLenum pname, GLfloat *params); typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVANGLEPROC) (GLint plane, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC) (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); -typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC) (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glFramebufferMemorylessPixelLocalStorageANGLE (GLint plane, GLenum internalformat); GL_APICALL void GL_APIENTRY glFramebufferTexturePixelLocalStorageANGLE (GLint plane, GLuint backingtexture, GLint level, GLint layer); @@ -656,8 +654,6 @@ GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageInterruptANGLE (void); GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageRestoreANGLE (void); GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterfvANGLE (GLint plane, GLenum pname, GLfloat *params); GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivANGLE (GLint plane, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterfvRobustANGLE (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivRobustANGLE (GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); #endif #endif /* GL_ANGLE_shader_pixel_local_storage */ diff --git a/include/GLSLANG/ShaderLang.h b/include/GLSLANG/ShaderLang.h index bbca8f4a980..cc43511bb0f 100644 --- a/include/GLSLANG/ShaderLang.h +++ b/include/GLSLANG/ShaderLang.h @@ -26,7 +26,7 @@ // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 371 +#define ANGLE_SH_VERSION 396 enum ShShaderSpec { @@ -37,7 +37,6 @@ enum ShShaderSpec SH_WEBGL2_SPEC, SH_GLES3_1_SPEC, - SH_WEBGL3_SPEC, SH_GLES3_2_SPEC, }; @@ -114,6 +113,7 @@ enum class ShPixelLocalStorageFormat : uint8_t RGBA8I, RGBA8UI, R32F, + R32I, R32UI, }; @@ -147,11 +147,6 @@ struct ShPixelLocalStorageOptions // ShPixelLocalStorageType::ImageLoadStore only: Can we use rgba8/rgba8i/rgba8ui image formats? // Or do we need to manually pack and unpack from r32i/r32ui? bool supportsNativeRGBA8ImageFormats = false; - - // anglebug.com/42266263 -- Metal [[raster_order_group()]] does not work for read_write textures - // on AMD when the render pass doesn't have a color attachment on slot 0. To work around this we - // attach one of the PLS textures to GL_COLOR_ATTACHMENT0, if there isn't one already. - bool renderPassNeedsAMDRasterOrderGroupsWorkaround = false; }; struct ShCompileOptions @@ -230,7 +225,8 @@ struct ShCompileOptions uint64_t unfoldShortCircuit : 1; // This flag initializes output variables to 0 at the beginning of main(). It is to avoid - // undefined behaviors. + // undefined behaviors. Additionally, it is intended as a workaround for drivers which get + // context lost if gl_FragColor is not written. uint64_t initOutputVariables : 1; // This flag scalarizes vec/ivec/bvec/mat constructor args. It is intended as a workaround for @@ -241,10 +237,6 @@ struct ShCompileOptions // drivers that do not handle struct scopes correctly, including all Mac drivers and Linux AMD. uint64_t regenerateStructNames : 1; - // This flag works around bugs in Mac drivers related to do-while by transforming them into an - // other construct. - uint64_t rewriteDoWhileLoops : 1; - // This flag works around a bug in the HLSL compiler optimizer that folds certain constant pow // expressions incorrectly. Only applies to the HLSL back-end. It works by expanding the integer // pow expressions into a series of multiplies. @@ -283,10 +275,6 @@ struct ShCompileOptions // active. The uniform block itself is also considered active. uint64_t useUnusedStandardSharedBlocks : 1; - // This flag works around a bug in unary minus operator on float numbers on Intel Mac OSX 10.11 - // drivers. It works by translating -float into 0.0 - float. - uint64_t rewriteFloatUnaryMinusOperator : 1; - // This flag works around a bug in evaluating atan(y, x) on some NVIDIA OpenGL drivers. It // works by using an expression to emulate this function. uint64_t emulateAtan2FloatFunction : 1; @@ -348,12 +336,9 @@ struct ShCompileOptions // read undefined values that could be coming from another webpage/application. uint64_t initSharedVariables : 1; - // Forces the value returned from an atomic operations to be always be resolved. This is - // targeted to workaround a bug in NVIDIA D3D driver where the return value from - // RWByteAddressBuffer.InterlockedAdd does not get resolved when used in the .yzw components of - // a RWByteAddressBuffer.Store operation. Only has an effect on HLSL translation. - // http://anglebug.com/42261924 - uint64_t forceAtomicValueResolution : 1; + // For MSL, non-const global variables cannot have an initializer, even if the initializer is + // constant. Initialization of these variables is deferred to the beginning of main. + uint64_t forceDeferNonConstGlobalInitializers : 1; // Rewrite gl_BaseVertex and gl_BaseInstance as uniform int uint64_t emulateGLBaseVertexBaseInstance : 1; @@ -394,10 +379,7 @@ struct ShCompileOptions // VK_EXT_depth_clip_control is supported, this code is not generated, saving a uniform look up. uint64_t addVulkanDepthCorrection : 1; - uint64_t forceShaderPrecisionHighpToMediump : 1; - - // Allow compiler to use specialization constant to do pre-rotation and y flip. - uint64_t useSpecializationConstant : 1; + uint64_t unused2 : 1; // Ask compiler to generate Vulkan transform feedback emulation support code. uint64_t addVulkanXfbEmulationSupportCode : 1; @@ -406,16 +388,15 @@ struct ShCompileOptions // VK_EXT_transform_feedback extension. uint64_t addVulkanXfbExtensionSupportCode : 1; - // This flag initializes fragment shader's output variables to zero at the beginning of the - // fragment shader's main(). It is intended as a workaround for drivers which get context lost - // if gl_FragColor is not written. - uint64_t initFragmentOutputVariables : 1; + // Reject shaders with variables that go above set limits; 2GB for uniform buffer objects, 64KB + // for private variables and 16MB for the total size of private variables. + uint64_t rejectWebglShadersWithLargeVariables : 1; // Always write explicit location layout qualifiers for fragment outputs. uint64_t explicitFragmentLocations : 1; - // Insert explicit casts for float/double/unsigned/signed int on macOS 10.15 with Intel driver - uint64_t addExplicitBoolCasts : 1; + // Dithering is emulated by injecting code in the fragment shader + uint64_t emulateDithering : 1; // Add round() after applying dither. This works around a Qualcomm quirk where values can get // ceil()ed instead. @@ -474,6 +455,24 @@ struct ShCompileOptions // Specify struct in one statement, declare instance in other. uint64_t separateCompoundStructDeclarations : 1; + // Whether to preserve denorm floats in the lexer or convert to zero + uint64_t preserveDenorms : 1; + + // Whether inactive shader variables from the output. + uint64_t removeInactiveVariables : 1; + + // Ensure all loops execute side-effects or terminate. + uint64_t ensureLoopForwardProgress : 1; + + // Do not preform any shader validation or perform any shader transformations. Shader state can + // still be reflected. + uint64_t skipAllValidationAndTransforms : 1; + + uint64_t transformFloatUniformTo16Bits : 1; + + // Whether the ANGLE IR should be used. Ineffective if ANGLE is built without IR support. + uint64_t useIR : 1; + ShCompileOptionsMetal metal; ShPixelLocalStorageOptions pls; }; @@ -501,6 +500,10 @@ struct ShBuiltInResources int MaxTextureImageUnits; int MaxFragmentUniformVectors; int MaxDrawBuffers; + int ShadingRateFlag2VerticalPixelsEXT; + int ShadingRateFlag4VerticalPixelsEXT; + int ShadingRateFlag2HorizontalPixelsEXT; + int ShadingRateFlag4HorizontalPixelsEXT; // Extensions. // Set to 1 to enable the extension, else 0. @@ -516,7 +519,6 @@ struct ShBuiltInResources int EXT_shader_texture_lod; int EXT_shader_framebuffer_fetch; int EXT_shader_framebuffer_fetch_non_coherent; - int NV_shader_framebuffer_fetch; int NV_shader_noperspective_interpolation; int ARM_shader_framebuffer_fetch; int ARM_shader_framebuffer_fetch_depth_stencil; @@ -524,6 +526,8 @@ struct ShBuiltInResources int OVR_multiview2; int EXT_multisampled_render_to_texture; int EXT_multisampled_render_to_texture2; + int EXT_fragment_shading_rate; + int EXT_fragment_shading_rate_primitive; int EXT_YUV_target; int EXT_geometry_shader; int OES_geometry_shader; @@ -537,7 +541,7 @@ struct ShBuiltInResources int ANGLE_shader_pixel_local_storage; int ANGLE_texture_multisample; int ANGLE_multi_draw; - // TODO(angleproject:3402) remove after chromium side removal to pass compilation + // TODO(http://anglebug.com/40096583) remove after chromium side removal to pass compilation int ANGLE_base_vertex_base_instance; int WEBGL_video_texture; int APPLE_clip_distance; @@ -568,10 +572,7 @@ struct ShBuiltInResources // function. This applies to Tegra K1 devices. int NV_draw_buffers; - // Set to 1 if highp precision is supported in the ESSL 1.00 version of the - // fragment language. Does not affect versions of the language where highp - // support is mandatory. - // Default is 0. + // Unused, highp support is always assumed. int FragmentPrecisionHigh; // GLSL ES 3.0 constants. @@ -595,6 +596,11 @@ struct ShBuiltInResources // Default is NULL. ShHashFunction64 HashFunction; + // User defined variables are prefixed with '_' and UserVariableNamePrefix. If UserVariableName + // is the null character, no prefixing is done and collisions between user variables and + // variables introduced during translation is possible. + char UserVariableNamePrefix; + // The maximum complexity an expression can be when limitExpressionComplexity is turned on. int MaxExpressionComplexity; @@ -694,7 +700,6 @@ struct ShBuiltInResources // EXT_geometry_shader constants int MaxGeometryUniformComponents; - int MaxGeometryUniformBlocks; int MaxGeometryInputComponents; int MaxGeometryOutputComponents; int MaxGeometryOutputVertices; @@ -702,7 +707,6 @@ struct ShBuiltInResources int MaxGeometryTextureImageUnits; int MaxGeometryAtomicCounterBuffers; int MaxGeometryAtomicCounters; - int MaxGeometryShaderStorageBlocks; int MaxGeometryShaderInvocations; int MaxGeometryImageUniforms; @@ -728,9 +732,6 @@ struct ShBuiltInResources int MaxTessEvaluationAtomicCounters; int MaxTessEvaluationAtomicCounterBuffers; - // Subpixel bits used in rasterization. - int SubPixelBits; - // APPLE_clip_distance / EXT_clip_cull_distance / ANGLE_clip_cull_distance constants int MaxClipDistances; int MaxCullDistances; @@ -738,7 +739,6 @@ struct ShBuiltInResources // ANGLE_shader_pixel_local_storage. int MaxPixelLocalStoragePlanes; - int MaxColorAttachmentsWithActivePixelLocalStorage; int MaxCombinedDrawBuffersAndPixelLocalStoragePlanes; }; @@ -894,17 +894,6 @@ uint32_t GetShaderSpecConstUsageBits(const ShHandle handle); bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector &variables); -// Gives the compiler-assigned register for a shader storage block. -// The method writes the value to the output variable "indexOut". -// Returns true if it found a valid shader storage block, false otherwise. -// Parameters: -// handle: Specifies the compiler -// shaderStorageBlockName: Specifies the shader storage block -// indexOut: output variable that stores the assigned register -bool GetShaderStorageBlockRegister(const ShHandle handle, - const std::string &shaderStorageBlockName, - unsigned int *indexOut); - // Gives the compiler-assigned register for a uniform block. // The method writes the value to the output variable "indexOut". // Returns true if it found a valid uniform block, false otherwise. @@ -962,13 +951,13 @@ uint32_t GetAdvancedBlendEquations(const ShHandle handle); // inline bool IsWebGLBasedSpec(ShShaderSpec spec) { - return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC); + return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC); } // Can't prefix with just _ because then we might introduce a double underscore, which is not safe // in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for // use by the underlying implementation). u is short for user-defined. -extern const char kUserDefinedNamePrefix[]; +extern const char kUserDefinedNamePrefix; enum class MetadataFlags { @@ -1003,19 +992,17 @@ namespace vk // Specialization constant ids enum class SpecializationConstantId : uint32_t { - SurfaceRotation = 0, - Dither = 1, + Dither = 0, - InvalidEnum = 2, + InvalidEnum = 1, EnumCount = InvalidEnum, }; enum class SpecConstUsage : uint32_t { - Rotation = 0, - Dither = 1, + Dither = 0, - InvalidEnum = 2, + InvalidEnum = 1, EnumCount = InvalidEnum, }; @@ -1140,6 +1127,15 @@ enum ReservedIds kIdDepthInputAttachment, kIdStencilInputAttachment, + // 16-bit storage extension + kIdFloat16, + kIdFloat16Vec2, + kIdFloat16Vec3, + kIdFloat16Vec4, + kIdFloat16Mat2, + kIdFloat16Mat3, + kIdFloat16Mat4, + kIdFirstUnreserved, }; } // namespace spirv diff --git a/include/GLSLANG/ShaderVars.h b/include/GLSLANG/ShaderVars.h index 40bf8732de7..7f0ed2c7e21 100644 --- a/include/GLSLANG/ShaderVars.h +++ b/include/GLSLANG/ShaderVars.h @@ -245,6 +245,8 @@ struct ShaderVariable // needs to know about, i.e. active variables, excluding non-zero array elements etc. uint32_t id; + bool isFloat16; + protected: bool isSameVariableAtLinkTime(const ShaderVariable &other, bool matchPrecision, diff --git a/include/export.h b/include/export.h index 6a8e30fd806..2b6aaa72f8d 100644 --- a/include/export.h +++ b/include/export.h @@ -18,12 +18,7 @@ # define ANGLE_EXPORT __declspec(dllimport) # endif # elif defined(__GNUC__) -# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) || \ - defined(LIBFEATURE_SUPPORT_IMPLEMENTATION) || defined(LIBCL_IMPLEMENTATION) -# define ANGLE_EXPORT __attribute__((visibility("default"))) -# else -# define ANGLE_EXPORT -# endif +# define ANGLE_EXPORT __attribute__((visibility("default"))) # else # define ANGLE_EXPORT # endif diff --git a/include/platform/Feature.h b/include/platform/Feature.h index e310de8f45f..e76194ef7a1 100644 --- a/include/platform/Feature.h +++ b/include/platform/Feature.h @@ -37,6 +37,7 @@ enum class FeatureCategory VulkanAppWorkarounds, MetalFeatures, MetalWorkarounds, + WebGPUWorkarounds, }; constexpr char kFeatureCategoryFrontendWorkarounds[] = "Frontend workarounds"; @@ -49,6 +50,7 @@ constexpr char kFeatureCategoryVulkanWorkarounds[] = "Vulkan workarounds"; constexpr char kFeatureCategoryVulkanFeatures[] = "Vulkan features"; constexpr char kFeatureCategoryMetalFeatures[] = "Metal features"; constexpr char kFeatureCategoryMetalWorkarounds[] = "Metal workarounds"; +constexpr char kFeatureCategoryWebGPUWorkarounds[] = "WebGPU workarounds"; constexpr char kFeatureCategoryUnknown[] = "Unknown"; inline const char *FeatureCategoryToString(const FeatureCategory &fc) @@ -95,6 +97,10 @@ inline const char *FeatureCategoryToString(const FeatureCategory &fc) return kFeatureCategoryMetalWorkarounds; break; + case FeatureCategory::WebGPUWorkarounds: + return kFeatureCategoryWebGPUWorkarounds; + break; + default: return kFeatureCategoryUnknown; break; @@ -171,7 +177,7 @@ struct FeatureSetBase public: void reset(); - void overrideFeatures(const std::vector &featureNames, bool enabled); + std::string overrideFeatures(const std::vector &featureNames, bool enabled); void populateFeatureList(FeatureList *features) const; const FeatureMap &getFeatures() const { return members; } diff --git a/include/platform/autogen/FeaturesGL_autogen.h b/include/platform/autogen/FeaturesGL_autogen.h index f3e8eae4d58..a6c97cab225 100644 --- a/include/platform/autogen/FeaturesGL_autogen.h +++ b/include/platform/autogen/FeaturesGL_autogen.h @@ -56,12 +56,6 @@ struct FeaturesGL : FeatureSetBase &members, }; - FeatureInfo doWhileGLSLCausesGPUHang = { - "doWhileGLSLCausesGPUHang", - FeatureCategory::OpenGLWorkarounds, - &members, - }; - FeatureInfo vertexIDDoesNotIncludeBaseVertex = { "vertexIDDoesNotIncludeBaseVertex", FeatureCategory::OpenGLWorkarounds, @@ -122,12 +116,6 @@ struct FeaturesGL : FeatureSetBase &members, }; - FeatureInfo emulateIsnanFloat = { - "emulateIsnanFloat", - FeatureCategory::OpenGLWorkarounds, - &members, - }; - FeatureInfo useUnusedBlocksWithStandardOrSharedLayout = { "useUnusedBlocksWithStandardOrSharedLayout", FeatureCategory::OpenGLWorkarounds, @@ -140,12 +128,6 @@ struct FeaturesGL : FeatureSetBase &members, }; - FeatureInfo rewriteFloatUnaryMinusOperator = { - "rewriteFloatUnaryMinusOperator", - FeatureCategory::OpenGLWorkarounds, - &members, - }; - FeatureInfo emulateAtan2Float = { "emulateAtan2Float", FeatureCategory::OpenGLWorkarounds, @@ -176,6 +158,12 @@ struct FeaturesGL : FeatureSetBase &members, }; + FeatureInfo forceMaxCombinedShaderOutputResources = { + "forceMaxCombinedShaderOutputResources", + FeatureCategory::OpenGLFeatures, + &members, + }; + FeatureInfo dontUseLoopsToInitializeVariables = { "dontUseLoopsToInitializeVariables", FeatureCategory::OpenGLWorkarounds, @@ -200,12 +188,6 @@ struct FeaturesGL : FeatureSetBase &members, }; - FeatureInfo disableBlendFuncExtended = { - "disableBlendFuncExtended", - FeatureCategory::OpenGLWorkarounds, - &members, - }; - FeatureInfo unsizedSRGBReadPixelsDoesntTransform = { "unsizedSRGBReadPixelsDoesntTransform", FeatureCategory::OpenGLWorkarounds, @@ -236,6 +218,12 @@ struct FeaturesGL : FeatureSetBase &members, }; + FeatureInfo disableMSAASampleCount1 = { + "disableMSAASampleCount1", + FeatureCategory::OpenGLWorkarounds, + &members, + }; + FeatureInfo allowClearForRobustResourceInit = { "allowClearForRobustResourceInit", FeatureCategory::OpenGLWorkarounds, @@ -254,12 +242,6 @@ struct FeaturesGL : FeatureSetBase &members, }; - FeatureInfo clearToZeroOrOneBroken = { - "clearToZeroOrOneBroken", - FeatureCategory::OpenGLWorkarounds, - &members, - }; - FeatureInfo limitMax3dArrayTextureSizeTo1024 = { "limitMax3dArrayTextureSizeTo1024", FeatureCategory::OpenGLWorkarounds, @@ -614,6 +596,12 @@ struct FeaturesGL : FeatureSetBase &members, }; + FeatureInfo emitMaxGlsl400ForTesting = { + "emitMaxGlsl400ForTesting", + FeatureCategory::OpenGLWorkarounds, + &members, + }; + FeatureInfo useIntermediateTextureForGenerateMipmap = { "useIntermediateTextureForGenerateMipmap", FeatureCategory::OpenGLWorkarounds, @@ -650,6 +638,24 @@ struct FeaturesGL : FeatureSetBase &members, }; + FeatureInfo resetSampleCoverageOnFBOChange = { + "resetSampleCoverageOnFBOChange", + FeatureCategory::OpenGLWorkarounds, + &members, + }; + + FeatureInfo disablePassthroughShaders = { + "disablePassthroughShaders", + FeatureCategory::OpenGLWorkarounds, + &members, + }; + + FeatureInfo disableClearTexImageForRobustInit = { + "disableClearTexImageForRobustInit", + FeatureCategory::OpenGLWorkarounds, + &members, + }; + }; inline FeaturesGL::FeaturesGL() = default; diff --git a/include/platform/autogen/FeaturesMtl_autogen.h b/include/platform/autogen/FeaturesMtl_autogen.h index 61c9f3ebed8..3efcc4506a4 100644 --- a/include/platform/autogen/FeaturesMtl_autogen.h +++ b/include/platform/autogen/FeaturesMtl_autogen.h @@ -140,18 +140,6 @@ struct FeaturesMtl : FeatureSetBase &members, }; - FeatureInfo intelExplicitBoolCastWorkaround = { - "intelExplicitBoolCastWorkaround", - FeatureCategory::MetalWorkarounds, - &members, - }; - - FeatureInfo intelDisableFastMath = { - "intelDisableFastMath", - FeatureCategory::MetalWorkarounds, - &members, - }; - FeatureInfo allowRenderpassWithoutAttachment = { "allowRenderpassWithoutAttachment", FeatureCategory::MetalFeatures, @@ -344,6 +332,12 @@ struct FeaturesMtl : FeatureSetBase &members, }; + FeatureInfo ensureLoopForwardProgress = { + "ensureLoopForwardProgress", + FeatureCategory::MetalFeatures, + &members, + }; + }; inline FeaturesMtl::FeaturesMtl() = default; diff --git a/include/platform/autogen/FeaturesVk_autogen.h b/include/platform/autogen/FeaturesVk_autogen.h index 3b9254101e0..303dac8e0db 100644 --- a/include/platform/autogen/FeaturesVk_autogen.h +++ b/include/platform/autogen/FeaturesVk_autogen.h @@ -26,6 +26,12 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo allowPipelineStatisticsForPrimitivesGeneratedQuery = { + "allowPipelineStatisticsForPrimitivesGeneratedQuery", + FeatureCategory::VulkanWorkarounds, + &members, + }; + FeatureInfo bresenhamLineRasterization = { "bresenhamLineRasterization", FeatureCategory::VulkanFeatures, @@ -98,12 +104,6 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo supportsGGPFrameToken = { - "supportsGGPFrameToken", - FeatureCategory::VulkanFeatures, - &members, - }; - FeatureInfo supportsExternalMemoryFd = { "supportsExternalMemoryFd", FeatureCategory::VulkanFeatures, @@ -170,6 +170,12 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo preferGlobalPipelineCache = { + "preferGlobalPipelineCache", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo supportsYUVSamplerConversion = { "supportsYUVSamplerConversion", FeatureCategory::VulkanFeatures, @@ -206,6 +212,12 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo usesSecondComponentForStencilBorderColor = { + "usesSecondComponentForStencilBorderColor", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo supportsMultiDrawIndirect = { "supportsMultiDrawIndirect", FeatureCategory::VulkanFeatures, @@ -236,26 +248,32 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo supportsDeviceFault = { + "supportsDeviceFault", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo supportsMultiview = { "supportsMultiview", FeatureCategory::VulkanFeatures, &members, }; - FeatureInfo forceD16TexFilter = { - "forceD16TexFilter", - FeatureCategory::VulkanWorkarounds, + FeatureInfo supportsMultiviewMultisampleRenderToTexture = { + "supportsMultiviewMultisampleRenderToTexture", + FeatureCategory::VulkanFeatures, &members, }; - FeatureInfo disableFlippingBlitWithCommand = { - "disableFlippingBlitWithCommand", + FeatureInfo forceD16TexFilter = { + "forceD16TexFilter", FeatureCategory::VulkanWorkarounds, &members, }; - FeatureInfo perFrameWindowSizeQuery = { - "perFrameWindowSizeQuery", + FeatureInfo avoidInvisibleWindowSwapchainRecreate = { + "avoidInvisibleWindowSwapchainRecreate", FeatureCategory::VulkanWorkarounds, &members, }; @@ -266,8 +284,14 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo supportsExternalMemoryDmaBufAndModifiers = { - "supportsExternalMemoryDmaBufAndModifiers", + FeatureInfo supportsExternalMemoryDmaBuf = { + "supportsExternalMemoryDmaBuf", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsImageDrmFormatModifier = { + "supportsImageDrmFormatModifier", FeatureCategory::VulkanFeatures, &members, }; @@ -308,12 +332,6 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo enablePreRotateSurfaces = { - "enablePreRotateSurfaces", - FeatureCategory::VulkanFeatures, - &members, - }; - FeatureInfo enablePrecisionQualifiers = { "enablePrecisionQualifiers", FeatureCategory::VulkanFeatures, @@ -428,8 +446,8 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo waitIdleBeforeSwapchainRecreation = { - "waitIdleBeforeSwapchainRecreation", + FeatureInfo destroyOldSwapchainInSharedPresentMode = { + "destroyOldSwapchainInSharedPresentMode", FeatureCategory::VulkanWorkarounds, &members, }; @@ -470,12 +488,6 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo compressVertexData = { - "compressVertexData", - FeatureCategory::VulkanWorkarounds, - &members, - }; - FeatureInfo preferDrawClearOverVkCmdClearAttachments = { "preferDrawClearOverVkCmdClearAttachments", FeatureCategory::VulkanWorkarounds, @@ -500,12 +512,6 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo preferDriverUniformOverSpecConst = { - "preferDriverUniformOverSpecConst", - FeatureCategory::VulkanFeatures, - &members, - }; - FeatureInfo exposeNonConformantExtensionsAndVersions = { "exposeNonConformantExtensionsAndVersions", FeatureCategory::VulkanWorkarounds, @@ -524,14 +530,14 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo forceFragmentShaderPrecisionHighpToMediump = { - "forceFragmentShaderPrecisionHighpToMediump", + FeatureInfo preferSubmitAtFBOBoundary = { + "preferSubmitAtFBOBoundary", FeatureCategory::VulkanWorkarounds, &members, }; - FeatureInfo preferSubmitAtFBOBoundary = { - "preferSubmitAtFBOBoundary", + FeatureInfo forceSubmitExceptionsAtFBOBoundary = { + "forceSubmitExceptionsAtFBOBoundary", FeatureCategory::VulkanWorkarounds, &members, }; @@ -728,6 +734,12 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo usePrimitiveTopologyDynamicState = { + "usePrimitiveTopologyDynamicState", + FeatureCategory::VulkanWorkarounds, + &members, + }; + FeatureInfo useDepthTestEnableDynamicState = { "useDepthTestEnableDynamicState", FeatureCategory::VulkanWorkarounds, @@ -794,6 +806,12 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo supportsPrimitiveFragmentShadingRate = { + "supportsPrimitiveFragmentShadingRate", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo supportsFoveatedRendering = { "supportsFoveatedRendering", FeatureCategory::VulkanFeatures, @@ -956,8 +974,8 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo hasEffectivePipelineCacheSerialization = { - "hasEffectivePipelineCacheSerialization", + FeatureInfo skipPipelineCacheSerialization = { + "skipPipelineCacheSerialization", FeatureCategory::VulkanFeatures, &members, }; @@ -968,14 +986,20 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo supportsPipelineProtectedAccess = { - "supportsPipelineProtectedAccess", - FeatureCategory::VulkanFeatures, + FeatureInfo syncPipelineCacheToBlobCacheEveryFrame = { + "syncPipelineCacheToBlobCacheEveryFrame", + FeatureCategory::VulkanWorkarounds, &members, }; - FeatureInfo supportsMixedReadWriteDepthStencilLayouts = { - "supportsMixedReadWriteDepthStencilLayouts", + FeatureInfo enableExtraSubmitFence = { + "enableExtraSubmitFence", + FeatureCategory::VulkanWorkarounds, + &members, + }; + + FeatureInfo supportsPipelineProtectedAccess = { + "supportsPipelineProtectedAccess", FeatureCategory::VulkanFeatures, &members, }; @@ -1028,8 +1052,14 @@ struct FeaturesVk : FeatureSetBase &members, }; - FeatureInfo asyncCommandBufferResetAndGarbageCleanup = { - "asyncCommandBufferResetAndGarbageCleanup", + FeatureInfo asyncGarbageCleanup = { + "asyncGarbageCleanup", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo asyncCommandBufferReset = { + "asyncCommandBufferReset", FeatureCategory::VulkanFeatures, &members, }; @@ -1106,6 +1136,18 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo forceHostImageCopyForLuma = { + "forceHostImageCopyForLuma", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo allowHostImageCopyAfterInitialUpload = { + "allowHostImageCopyAfterInitialUpload", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo enableParallelCompileAndLink = { "enableParallelCompileAndLink", FeatureCategory::VulkanFeatures, @@ -1238,6 +1280,18 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo isVertexSyncDeferred = { + "isVertexSyncDeferred", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo recycleVkEvent = { + "recycleVkEvent", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo supportsSynchronization2 = { "supportsSynchronization2", FeatureCategory::VulkanFeatures, @@ -1412,6 +1466,30 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo supportsAstcDecodeMode = { + "supportsAstcDecodeMode", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsAstcDecodeModeRgb9e5 = { + "supportsAstcDecodeModeRgb9e5", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsAstcHdr3dTextures = { + "supportsAstcHdr3dTextures", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsAstc3d = { + "supportsAstc3d", + FeatureCategory::VulkanFeatures, + &members, + }; + FeatureInfo supportsImageCompressionControlSwapchain = { "supportsImageCompressionControlSwapchain", FeatureCategory::VulkanFeatures, @@ -1442,6 +1520,132 @@ struct FeaturesVk : FeatureSetBase &members, }; + FeatureInfo supportsSwapchainMutableFormat = { + "supportsSwapchainMutableFormat", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsClipCullDistanceInGSAndTS = { + "supportsClipCullDistanceInGSAndTS", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsMaintenance9 = { + "supportsMaintenance9", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsShaderIntegerDotProduct = { + "supportsShaderIntegerDotProduct", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo convertLowpAndMediumpFloatUniformsTo16Bits = { + "convertLowpAndMediumpFloatUniformsTo16Bits", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsUnifiedImageLayouts = { + "supportsUnifiedImageLayouts", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsGlobalPriority = { + "supportsGlobalPriority", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsGlobalPriorityQuery = { + "supportsGlobalPriorityQuery", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsBufferDeviceAddress = { + "supportsBufferDeviceAddress", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo preferBGR565ToRGB565 = { + "preferBGR565ToRGB565", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo clSerializedExecution = { + "clSerializedExecution", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo externallySynchronizePipelineCacheAccess = { + "externallySynchronizePipelineCacheAccess", + FeatureCategory::VulkanWorkarounds, + &members, + }; + + FeatureInfo supportShaderPixelLocalStorageAngle = { + "supportShaderPixelLocalStorageAngle", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo debugClDumpCommandStream = { + "debugClDumpCommandStream", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsShaderAtomicInt64 = { + "supportsShaderAtomicInt64", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportsBindVertexBuffers2 = { + "supportsBindVertexBuffers2", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo forceSizePointerForBoundVertexBuffers = { + "forceSizePointerForBoundVertexBuffers", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo supportFragmentShadingRateExtExtensions = { + "supportFragmentShadingRateExtExtensions", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo dropDepthStencilClearOnInvalidate = { + "dropDepthStencilClearOnInvalidate", + FeatureCategory::VulkanWorkarounds, + &members, + }; + + FeatureInfo supportsTileMemoryHeap = { + "supportsTileMemoryHeap", + FeatureCategory::VulkanFeatures, + &members, + }; + + FeatureInfo simulateTileMemoryForTesting = { + "simulateTileMemoryForTesting", + FeatureCategory::VulkanFeatures, + &members, + }; + }; inline FeaturesVk::FeaturesVk() = default; diff --git a/include/platform/autogen/FeaturesWgpu_autogen.h b/include/platform/autogen/FeaturesWgpu_autogen.h new file mode 100644 index 00000000000..680b676deeb --- /dev/null +++ b/include/platform/autogen/FeaturesWgpu_autogen.h @@ -0,0 +1,36 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_features.py using data from wgpu_features.json. +// +// Copyright 2025 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. +// +// FeaturesWgpu_autogen.h: angle::Features and workarounds for the WebGPU backend. + +#ifndef ANGLE_PLATFORM_AUTOGEN_FEATURESWGPU_H_ +#define ANGLE_PLATFORM_AUTOGEN_FEATURESWGPU_H_ + +#include "platform/Feature.h" + +namespace angle +{ + +struct FeaturesWgpu : FeatureSetBase +{ + FeaturesWgpu(); + ~FeaturesWgpu(); + + FeatureInfo avoidWaitAny = { + "avoidWaitAny", + FeatureCategory::WebGPUWorkarounds, + &members, + }; + +}; + +inline FeaturesWgpu::FeaturesWgpu() = default; +inline FeaturesWgpu::~FeaturesWgpu() = default; + +} // namespace angle + +#endif // ANGLE_PLATFORM_AUTOGEN_FEATURESWGPU_H_ diff --git a/include/platform/autogen/FrontendFeatures_autogen.h b/include/platform/autogen/FrontendFeatures_autogen.h index 29f8f2d9fab..0f25e21f713 100644 --- a/include/platform/autogen/FrontendFeatures_autogen.h +++ b/include/platform/autogen/FrontendFeatures_autogen.h @@ -39,12 +39,6 @@ struct FrontendFeatures : FeatureSetBase &members, }; - FeatureInfo disableDrawBuffersIndexed = { - "disableDrawBuffersIndexed", - FeatureCategory::FrontendFeatures, - &members, - }; - FeatureInfo disableAnisotropicFiltering = { "disableAnisotropicFiltering", FeatureCategory::FrontendWorkarounds, @@ -105,6 +99,12 @@ struct FrontendFeatures : FeatureSetBase &members, }; + FeatureInfo useIr = { + "useIr", + FeatureCategory::FrontendFeatures, + &members, + }; + FeatureInfo cacheCompiledShader = { "cacheCompiledShader", FeatureCategory::FrontendFeatures, @@ -177,15 +177,33 @@ struct FrontendFeatures : FeatureSetBase &members, }; - FeatureInfo rejectWebglShadersWithUndefinedBehavior = { - "rejectWebglShadersWithUndefinedBehavior", + FeatureInfo alwaysEnableEmulatedMultidrawExtensions = { + "alwaysEnableEmulatedMultidrawExtensions", FeatureCategory::FrontendWorkarounds, &members, }; - FeatureInfo alwaysEnableEmulatedMultidrawExtensions = { - "alwaysEnableEmulatedMultidrawExtensions", - FeatureCategory::FrontendWorkarounds, + FeatureInfo forcePassthroughShaders = { + "forcePassthroughShaders", + FeatureCategory::FrontendFeatures, + &members, + }; + + FeatureInfo clipCullDistanceBrokenWithPassthroughShaders = { + "clipCullDistanceBrokenWithPassthroughShaders", + FeatureCategory::FrontendFeatures, + &members, + }; + + FeatureInfo noperspectiveInterpolationBrokenWithPassthroughShaders = { + "noperspectiveInterpolationBrokenWithPassthroughShaders", + FeatureCategory::FrontendFeatures, + &members, + }; + + FeatureInfo forceDebugContexts = { + "forceDebugContexts", + FeatureCategory::FrontendFeatures, &members, }; diff --git a/include/platform/frontend_features.json b/include/platform/frontend_features.json index 8bf2fcdb7c2..8c99f4753a6 100644 --- a/include/platform/frontend_features.json +++ b/include/platform/frontend_features.json @@ -30,14 +30,6 @@ ], "issue": "http://anglebug.com/42263580" }, - { - "name": "disable_draw_buffers_indexed", - "category": "Features", - "description": [ - "Disable support for OES_draw_buffers_indexed and EXT_draw_buffers_indexed" - ], - "issue": "http://anglebug.com/42266194" - }, { "name": "disable_anisotropic_filtering", "category": "Workarounds", @@ -114,6 +106,14 @@ ], "issue": "http://anglebug.com/40096838" }, + { + "name": "use_ir", + "category": "Features", + "description": [ + "Use the translator's IR instead of AST" + ], + "issue": "http://anglebug.com/349994211" + }, { "name": "cache_compiled_shader", "category": "Features", @@ -211,20 +211,44 @@ "issue": "https://issuetracker.google.com/349489248" }, { - "name": "reject_webgl_shaders_with_undefined_behavior", + "name": "always_enable_emulated_multidraw_extensions", "category": "Workarounds", "description": [ - "Attempts to detect undefined behavior when in WebGL mode and reject shaders if any detected." + "Enable multi-draw and base vertex base instance extensions for non-WebGL contexts if they are emulated." ], - "issue": "http://crbug.com/350528343" + "issue": "http://anglebug.com/355645824" }, { - "name": "always_enable_emulated_multidraw_extensions", - "category": "Workarounds", + "name": "force_passthrough_shaders", + "category": "Features", "description": [ - "Enable multi-draw and base vertex base instance extensions for non-WebGL contexts if they are emulated." + "Parse shaders for reflection but do not translate them." ], - "issue": "http://anglebug.com/355645824" + "issue": "https://anglebug.com/398857482" + }, + { + "name": "clip_cull_distance_broken_with_passthrough_shaders", + "category": "Features", + "description": [ + "GL_EXT_clip_cull_distance requires shader transformations to function at all on some drivers." + ], + "issue": "https://anglebug.com/398857482" + }, + { + "name": "noperspective_interpolation_broken_with_passthrough_shaders", + "category": "Features", + "description": [ + "GL_NV_shader_noperspective_interpolation requires shader transformations to function at all on some drivers." + ], + "issue": "https://anglebug.com/398857482" + }, + { + "name": "force_debug_contexts", + "category": "Features", + "description": [ + "Force every context into debug mode as if EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR was used." + ], + "issue": "https://anglebug.com/423956139" } ] } diff --git a/include/platform/gen_features.py b/include/platform/gen_features.py index 773f330e6be..d8cdd530354 100755 --- a/include/platform/gen_features.py +++ b/include/platform/gen_features.py @@ -20,6 +20,7 @@ 'gl_features.json': ('OpenGL', 'FeaturesGL'), 'mtl_features.json': ('Metal', 'FeaturesMtl'), 'vk_features.json': ('Vulkan', 'FeaturesVk'), + 'wgpu_features.json': ('WebGPU', 'FeaturesWgpu'), } feature_list_header_file = '../../util/autogen/angle_features_autogen.h' feature_list_source_file = '../../util/autogen/angle_features_autogen.cpp' diff --git a/include/platform/gl_features.json b/include/platform/gl_features.json index 03ad509d425..6c5abe533b1 100644 --- a/include/platform/gl_features.json +++ b/include/platform/gl_features.json @@ -49,14 +49,6 @@ "Issue clearing framebuffers with linear attachments when GL_FRAMEBUFFER_SRGB is enabled" ] }, - { - "name": "do_while_GLSL_causes_GPU_hang", - "category": "Workarounds", - "description": [ - "Some GLSL constructs involving do-while loops cause GPU hangs" - ], - "issue": "http://crbug.com/644669" - }, { "name": "vertex_ID_does_not_include_base_vertex", "category": "Workarounds", @@ -131,14 +123,6 @@ ], "issue": "http://anglebug.com/42260492" }, - { - "name": "emulate_isnan_float", - "category": "Workarounds", - "description": [ - "Using isnan() on highp float will get wrong answer" - ], - "issue": "http://crbug.com/650547" - }, { "name": "use_unused_blocks_with_standard_or_shared_layout", "category": "Workarounds", @@ -153,14 +137,6 @@ "Fix spec difference between GLSL 4.1 or lower and ESSL3" ] }, - { - "name": "rewrite_float_unary_minus_operator", - "category": "Workarounds", - "description": [ - "Using '-' will get wrong answer" - ], - "issue": "http://crbug.com/308366" - }, { "name": "emulate_atan_2_float", "category": "Workarounds", @@ -200,6 +176,14 @@ "The point size range reported from the API is inconsistent with the actual behavior" ] }, + { + "name": "force_max_combined_shader_output_resources", + "category": "Features", + "description": [ + "Force GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES to be the sum of GL_MAX_COMBINED_IMAGE_UNIFORMS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, and GL_MAX_COLOR_ATTACHMENTS" + ], + "issue": "" + }, { "name": "dont_use_loops_to_initialize_variables", "category": "Workarounds", @@ -230,14 +214,6 @@ "Apply a vendor-specific transformation to explicit cubemap derivatives" ] }, - { - "name": "disable_blend_func_extended", - "category": "Workarounds", - "description": [ - "ARB_blend_func_extended does not pass the tests" - ], - "issue": "http://anglebug.com/40644593" - }, { "name": "unsized_SRGB_read_pixels_doesnt_transform", "category": "Workarounds", @@ -281,6 +257,14 @@ ], "issue": "http://crbug.com/797243" }, + { + "name": "disable_MSAA_sample_count_1", + "category": "Workarounds", + "description": [ + "Do not expose multisample sample count 1 to avoid driver bugs" + ], + "issue": "http://anglebug.com/467164245" + }, { "name": "allow_clear_for_robust_resource_init", "category": "Workarounds", @@ -307,14 +291,6 @@ ], "issue": "https://crbug.com/705865" }, - { - "name": "clear_to_zero_or_one_broken", - "category": "Workarounds", - "description": [ - "Clears when the clear color is all zeros or ones do not work." - ], - "issue": "https://crbug.com/710443" - }, { "name": "limit_max_3d_array_texture_size_to_1024", "category": "Workarounds", @@ -794,6 +770,14 @@ ], "issue": "https://anglebug.com/41488638" }, + { + "name": "emit_max_glsl_400_for_testing", + "category": "Workarounds", + "description": [ + "Avoid GLSL versions above 4.0 for testing purposes." + ], + "issue": "https://anglebug.com/42267207" + }, { "name": "use_intermediate_texture_for_generate_mipmap", "category": "Workarounds", @@ -844,6 +828,30 @@ "Disable GL_KHR_blend_equation_advanced due to various driver issues." ], "issue": "https://anglebug.com/42267098" + }, + { + "name": "reset_sample_coverage_on_FBO_change", + "category": "Workarounds", + "description": [ + "Some Adreno drivers assume incorrect glSampleCoverage if new FBO is bound with different sample count" + ], + "issue": "https://crbug.com/408364831" + }, + { + "name": "disable_passthrough_shaders", + "category": "Workarounds", + "description": [ + "Some ES2 Mali drivers are unable to query enough information from a linked program to use passthrough shaders." + ], + "issue": "https://crbug.com/451796659" + }, + { + "name": "disable_clear_tex_image_for_robust_init", + "category": "Workarounds", + "description": [ + "IMG drivers are unable to handle glClearTexImage with various format combinations." + ], + "issue": "https://crbug.com/465918231" } ] } diff --git a/include/platform/mtl_features.json b/include/platform/mtl_features.json index e3b71dc8efb..386e3a83132 100644 --- a/include/platform/mtl_features.json +++ b/include/platform/mtl_features.json @@ -150,21 +150,6 @@ "Turn this on to allow transform feedback in Metal using a 2-pass VS for GLES3." ] }, - { - "name": "intel_explicit_bool_cast_workaround", - "category": "Workarounds", - "description": [ - "Insert explicit casts for float/double/unsigned/signed int on macOS 10.15 with Intel ", - "driver" - ] - }, - { - "name": "intel_disable_fast_math", - "category": "Workarounds", - "description": [ - "Disable fast math in atan and invariance cases when running below macOS 12.0" - ] - }, { "name": "allow_renderpass_without_attachment", "category": "Features", @@ -418,6 +403,14 @@ "having side effects and not optimized out." ], "issue": "http://crbug.com/1513738" + }, + { + "name": "ensure_loop_forward_progress", + "category": "Features", + "description": [ + "Inject statements into loop bodies when needed to ensure infinite loops are optimized out." + ], + "issue": "http://crbug.com/1513738" } ] } diff --git a/include/platform/vk_features.json b/include/platform/vk_features.json index abaddace1b9..baee2215170 100644 --- a/include/platform/vk_features.json +++ b/include/platform/vk_features.json @@ -15,6 +15,14 @@ ], "issue": "b/266235549" }, + { + "name": "allow_pipeline_statistics_for_primitives_generated_query", + "category": "Workarounds", + "description": [ + "On devices where primitivesGeneratedQuery vulkan feature is not available, allows pipelineStatisticsQuery vulkan feature to substitute primitivesGeneratedQuery if it generates the same results as primitivesGeneratedQuery" + ], + "issue:": "b/333987915" + }, { "name": "bresenham_line_rasterization", "category": "Features", @@ -103,13 +111,6 @@ "VkDevice supports the VK_ANDROID_external_memory_android_hardware_buffer extension" ] }, - { - "name": "supports_GGP_frame_token", - "category": "Features", - "description": [ - "VkDevice supports the VK_GGP_frame_token extension" - ] - }, { "name": "supports_external_memory_fd", "category": "Features", @@ -191,6 +192,14 @@ "VkDevice supports the VK_EXT_shader_stencil_export extension" ] }, + { + "name": "prefer_global_pipeline_cache", + "category": "Features", + "description": [ + "The renderer's pipeline cache will be used instead of the separate caches per program." + ], + "issue": "http://anglebug.com/411442610" + }, { "name": "supports_YUV_sampler_conversion", "category": "Features", @@ -238,6 +247,15 @@ ], "issue": "http://anglebug.com/42262239" }, + { + "name": "uses_second_component_for_stencil_border_color", + "category": "Features", + "description": [ + "Implementation utilizes second component of the INT custom border color ", + "for undefined format when sampling from a stencil texture." + ], + "issue": "http://issuetracker.google.com/390710636" + }, { "name": "supports_multi_draw_indirect", "category": "Features", @@ -279,6 +297,14 @@ ], "issue": "http://anglebug.com/42267057" }, + { + "name": "supports_device_fault", + "category": "Features", + "description": [ + "VkDevice supports the VK_EXT_device_fault extension" + ], + "issue": "http://issuetracker.google.com/399478440" + }, { "name": "supports_multiview", "category": "Features", @@ -288,29 +314,31 @@ "issue": "http://anglebug.com/42264577" }, { - "name": "force_D16_tex_filter", - "category": "Workarounds", + "name": "supports_multiview_multisample_render_to_texture", + "category": "Features", "description": [ - "VK_FORMAT_D16_UNORM does not support VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, ", - "which prevents OES_depth_texture from being supported." + "VkDevice supports the VK_KHR_multiview and VK_EXT_multisampled_render_to_single_sampled extension" ], - "issue": "http://anglebug.com/42262115" + "issue": "http://anglebug.com/42261787" }, { - "name": "disable_flipping_blit_with_command", + "name": "force_D16_tex_filter", "category": "Workarounds", "description": [ - "vkCmdBlitImage with flipped coordinates blits incorrectly." + "VK_FORMAT_D16_UNORM does not support VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, ", + "which prevents OES_depth_texture from being supported." ], - "issue": "http://anglebug.com/42262161" + "issue": "http://anglebug.com/42262115" }, { - "name": "per_frame_window_size_query", + "name": "avoid_invisible_window_swapchain_recreate", "category": "Workarounds", "description": [ - "Vulkan swapchain is not returning VK_ERROR_OUT_OF_DATE when window resizing" + "Do not recreate a swapchain when window is invisible even if its size is ", + "changed. This is a workaround for the bug when vkAcquireNextImageKHR constantly ", + "returns VK_ERROR_OUT_OF_DATE if recreate the swapchain while window is invisible." ], - "issue": "http://anglebug.com/40096601, http://anglebug.com/42262286, http://anglebug.com/42262287" + "issue": "http://anglebug.com/397848903" }, { "name": "pad_buffers_to_max_vertex_attrib_stride", @@ -326,10 +354,18 @@ "issue": "http://anglebug.com/42263049" }, { - "name": "supports_external_memory_dma_buf_and_modifiers", + "name": "supports_external_memory_dma_buf", "category": "Features", "description": [ - "VkDevice supports the VK_EXT_external_memory_dma_buf and VK_EXT_image_drm_format_modifier ", + "VkDevice supports the VK_EXT_external_memory_dma_buf", + "extensions" + ] + }, + { + "name": "supports_image_drm_format_modifier", + "category": "Features", + "description": [ + "VkDevice supports the VK_EXT_image_drm_format_modifier", "extensions" ], "issue": "http://anglebug.com/42264767" @@ -379,14 +415,6 @@ ], "issue": "http://anglebug.com/40096464" }, - { - "name": "enable_pre_rotate_surfaces", - "category": "Features", - "description": [ - "Enable Android pre-rotation for landscape applications" - ], - "issue": "http://anglebug.com/42262166" - }, { "name": "enable_precision_qualifiers", "category": "Features", @@ -546,13 +574,15 @@ "issue": "http://anglebug.com/40644747" }, { - "name": "wait_idle_before_swapchain_recreation", + "name": "destroy_old_swapchain_in_shared_present_mode", "category": "Workarounds", "description": [ - "Before passing an oldSwapchain to VkSwapchainCreateInfoKHR, wait for queue to be idle. ", - "Works around a bug on platforms which destroy oldSwapchain in vkCreateSwapchainKHR." + "Instead of passing an oldSwapchain to VkSwapchainCreateInfoKHR, wait for queue to ", + "be idle and destroy the swapchain immediately. Works around a bug on platforms ", + "which may return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR from vkCreateSwapchainKHR ", + "if use the oldSwapchain pointer." ], - "issue": "http://anglebug.com/42263629" + "issue": "http://anglebug.com/42262606" }, { "name": "force_texture_lod_offset_1", @@ -596,14 +626,6 @@ "Force nearest mip filtering when sampling." ] }, - { - "name": "compress_vertex_data", - "category": "Workarounds", - "description": [ - "Compress vertex data to smaller data types when ", - "possible. Using this feature makes ANGLE non-conformant." - ] - }, { "name": "prefer_draw_clear_over_vkCmdClearAttachments", "category": "Workarounds", @@ -637,14 +659,6 @@ ], "issue": "http://anglebug.com/42263477" }, - { - "name": "prefer_driver_uniform_over_spec_const", - "category": "Features", - "description": [ - "Prefer using driver uniforms instead of specialization constants." - ], - "issue": "http://anglebug.com/42265878" - }, { "name": "expose_non_conformant_extensions_and_versions", "category": "Workarounds", @@ -670,20 +684,20 @@ "issue": "http://anglebug.com/42264071" }, { - "name": "force_fragment_shader_precision_highp_to_mediump", + "name": "prefer_submit_at_FBO_boundary", "category": "Workarounds", "description": [ - "Forces highp precision in fragment shader to mediump." + "Submit commands to driver at each FBO boundary for performance improvements." ], - "issue": "https://issuetracker.google.com/184850002" + "issue": "https://issuetracker.google.com/187425444" }, { - "name": "prefer_submit_at_FBO_boundary", + "name": "force_submit_exceptions_at_FBO_boundary", "category": "Workarounds", "description": [ - "Submit commands to driver at each FBO boundary for performance improvements." + "Some commands force immediate submission at FBO boundary." ], - "issue": "https://issuetracker.google.com/187425444" + "issue": "https://issuetracker.google.com/422507974" }, { "name": "use_multiple_descriptors_for_external_formats", @@ -933,6 +947,14 @@ ], "issue": "http://anglebug.com/42264446" }, + { + "name": "use_primitive_topology_dynamic_state", + "category": "Workarounds", + "description": [ + "Use the Primitive Topology dynamic state from VK_EXT_extended_dynamic_state" + ], + "issue": "http://anglebug.com/42264446" + }, { "name": "use_depth_test_enable_dynamic_state", "category": "Workarounds", @@ -1021,6 +1043,14 @@ ], "issue": "http://anglebug.com/42265647" }, + { + "name": "supports_primitive_fragment_shading_rate", + "category": "Features", + "description": [ + "VkDevice supports primitiveFragmentShadingRate feature" + ], + "issue": "http://anglebug.com/397255625" + }, { "name": "supports_foveated_rendering", "category": "Features", @@ -1106,7 +1136,7 @@ "name": "supports_yuv_target", "category": "Features", "description": [ - "VkDevice supports VK_ANDROID_render_to_external_format and VK_EXT_ycbcr_attachment" + "VkDevice supports VK_ANDROID_external_format_resolve with nullColorAttachmentWithExternalFormatResolve" ] }, { @@ -1241,12 +1271,12 @@ "issue": "https://anglebug.com/42265839" }, { - "name": "has_effective_pipeline_cache_serialization", + "name": "skip_pipeline_cache_serialization", "category": "Features", "description": [ - "Whether the implementation serializes the Vulkan pipeline cache effectively. ", - "On some implementations, pipeline cache serialization returns no data, so there ", - "is no benefit to serializing it" + "Whether to serialize the Vulkan pipeline cache data. ", + "On some implementations, pipeline cache serialization returns no data", + "or very big data,so there is no benefit to serializing it." ], "issue": "https://anglebug.com/42265839" }, @@ -1259,20 +1289,29 @@ "issue": "http://anglebug.com/42263322" }, { - "name": "supports_pipeline_protected_access", - "category": "Features", + "name": "sync_pipeline_cache_to_blob_cache_every_frame", + "category": "Workarounds", "description": [ - "VkDevice supports the VK_EXT_pipeline_protected_access extension" + "Synchronize the Vulkan pipeline cache to the blob cache every frame", + "for testing purposes." ], - "issue": "https://anglebug.com/42266183" + "issue": "https://issuetracker.google.com/467732555" + }, + { + "name": "enable_extra_submit_fence", + "category": "Workarounds", + "description": [ + "Enable using a separate submit fence in the command batches." + ], + "issue": "https://issuetracker.google.com/384477641" }, { - "name": "supports_mixed_read_write_depth_stencil_layouts", + "name": "supports_pipeline_protected_access", "category": "Features", "description": [ - "VkDevice supports the mixed read and write depth/stencil layouts introduced by VK_KHR_maintenance2" + "VkDevice supports the VK_EXT_pipeline_protected_access extension" ], - "issue": "https://anglebug.com/42266364" + "issue": "https://anglebug.com/42266183" }, { "name": "supports_maintenance5", @@ -1338,13 +1377,21 @@ "issue": "https://issuetracker.google.com/253522366" }, { - "name": "async_command_buffer_reset_and_garbage_cleanup", + "name": "async_garbage_cleanup", "category": "Features", "description": [ - "Reset command buffer and cleanup garbage in async thread." + "cleanup garbage in async thread." ], "issue": "https://issuetracker.google.com/255411748" }, + { + "name": "async_command_buffer_reset", + "category": "Features", + "description": [ + "Reset command buffer in async thread." + ], + "issue": "https://issuetracker.google.com/378718508" + }, { "name": "use_reset_command_buffer_bit_for_secondary_pools", "category": "Workarounds", @@ -1438,6 +1485,23 @@ "perf query indicates only optimalDeviceAccess, but not identicalMemoryLayout" ] }, + { + "name": "force_host_image_copy_for_luma", + "category": "Features", + "description": [ + "When using VK_EXT_host_image_copy, use VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT for images created", + "for luminance/alpha textures" + ] + }, + { + "name": "allow_host_image_copy_after_initial_upload", + "category": "Features", + "description": [ + "When using VK_EXT_host_image_copy, do CPU copies also if data is uploaded to the texture after ", + "its initialization. This feature is best disabled for CPU-intensive workloads that do frequent ", + "uploads to the same texture." + ] + }, { "name": "enable_parallel_compile_and_link", "category": "Features", @@ -1617,6 +1681,22 @@ ], "issue": "https://issues.angleproject.org/360274928" }, + { + "name": "is_vertex_sync_deferred", + "category": "Features", + "description": [ + "Prefer VkEvent instead of VkCmdPipelineBarrier if vertex synchronization is deferred" + ], + "issue": "https://issues.angleproject.org/issues/414630743" + }, + { + "name": "recycle_vkEvent", + "category": "Features", + "description": [ + "Keep and recycle VkEvent instead of destroying when the last reference goes away" + ], + "issue": "https://issues.angleproject.org/409441956" + }, { "name": "supports_synchronization2", "category": "Features", @@ -1851,6 +1931,39 @@ ], "issue": "https://anglebug.com/379186304" }, + { + "name": "supports_astc_decode_mode", + "category": "Features", + "description": [ + "VkDevice supports VK_EXT_astc_decode_mode extension" + ], + "issue": "https://anglebug.com/419403188" + }, + { + "name": "supports_astc_decode_mode_rgb9e5", + "category": "Features", + "description": [ + "VkDevice supports VK_EXT_astc_decode_mode extension" + ], + "issue": "https://anglebug.com/419403188" + }, + { + "name": "supports_astc_hdr_3d_textures", + "category": "Features", + "description": [ + "Whether the device supports 3D textures with ASTC HDR compression" + ], + "issue": "https://anglebug.com/416095435" + }, + { + "name": "supports_astc_3d", + "category": "Features", + "description": [ + "VkDevice supports VK_EXT_texture_compression_astc_3d extension", + "Enable use of astc_3d" + ], + "issue": "https://anglebug.com/473593137" + }, { "name": "supports_image_compression_control_swapchain", "category": "Features", @@ -1888,6 +2001,174 @@ "description": [ "Enable the use of native builtin kernel in place of the libclc version" ] + }, + { + "name": "supports_swapchain_mutable_format", + "category": "Features", + "description": [ + "VkDevice supports VK_KHR_swapchain_mutable_format extension" + ], + "issue": "http://anglebug.com/386688871" + }, + { + "name": "supports_clip_cull_distance_in_GS_and_TS", + "category": "Features", + "description": [ + "Supports using clip/cull distance features in geometry and tessellation shaders" + ], + "issue": "http://anglebug.com/42264006" + }, + { + "name": "supports_maintenance9", + "category": "Features", + "description": [ + "VkDevice supports the VK_KHR_maintenance9 extension" + ], + "issue": "https://anglebug.com/429339330" + }, + { + "name": "supports_shader_integer_dot_product", + "category": "Features", + "description": [ + "VkDevice supports the VK_KHR_shader_integer_dot_product extension" + ] + }, + { + "name": "convert_lowp_and_mediump_float_uniforms_to_16_bits", + "category": "Features", + "description": [ + "transform lowp and mediump float uniforms into 16 bits" + ], + "issue": "http://anglebug.com/405795981" + }, + { + "name": "supports_unified_image_layouts", + "category": "Features", + "description": [ + "VkDevice supports VK_KHR_unified_image_layouts" + ], + "issue": "https://anglebug.com/422982681" + }, + { + "name": "supports_global_priority", + "category": "Features", + "description": [ + "VkDevice supports VK_EXT_global_priority" + ], + "issue": "https://anglebug.com/397474813" + }, + { + "name": "supports_global_priority_query", + "category": "Features", + "description": [ + "VkDevice supports VK_EXT_global_priority_query" + ], + "issue": "https://anglebug.com/397474813" + }, + { + "name": "supports_buffer_device_address", + "category": "Features", + "description": [ + "VkDevice supports the VK_KHR_buffer_device_address and uses ", + "physical storage buffers instead of storage buffers" + ] + }, + { + "name": "prefer_BGR565_to_RGB565", + "category": "Features", + "description": [ + "Use BGR565 instead of RGB565 for performance reasons" + ], + "issue": "https://issuetracker.google.com/409867243" + }, + { + "name": "cl_serialized_execution", + "category": "Features", + "description": [ + "Force each OpenCL enqueue command to submit and wait for fence." + ] + }, + { + "name": "externally_synchronize_pipeline_cache_access", + "category": "Workarounds", + "description": [ + "Externally synchronize all pipeline cache accesses" + ], + "issue": "https://anglebug.com/445240187" + }, + { + "name": "support_shader_pixel_local_storage_angle", + "category": "Features", + "description": [ + "Enable support for GL_ANGLE_shader_pixel_local_storage extension" + ], + "issue": "https://anglebug.com/40096838" + }, + { + "name": "debug_cl_dump_command_stream", + "category": "Features", + "description": [ + "Dump OpenCL-Vulkan CommandBuffer stream to stdout." + ] + }, + { + "name": "supports_shader_atomic_int64", + "category": "Features", + "description": [ + "VkDevice supports the VK_KHR_shader_atomic_int64 extension " + ] + }, + { + "name": "supports_bind_vertex_buffers_2", + "category": "Features", + "description": [ + "Using BindVertexBuffers2 is supported" + ], + "issue": "https://anglebug.com/474385503" + }, + { + "name": "force_size_pointer_for_bound_vertex_buffers", + "category": "Features", + "description": [ + "Make sure the pSizes pointer to BindVertexBuffers2 is provided" + ], + "issue": "https://anglebug.com/448047351" + }, + { + "name": "support_fragment_shading_rate_ext_extensions", + "category": "Features", + "description": [ + "Advertize support for these fragment shading rate extensions:", + "- GL_EXT_fragment_shading_rate", + "- GL_EXT_fragment_shading_rate_primitive", + "- GL_EXT_fragment_shading_rate_attachment" + ], + "issue": "https://anglebug.com/397255625" + }, + { + "name": "drop_depth_stencil_clear_on_invalidate", + "category": "Workarounds", + "description": [ + "There are old Unity titles that expect depth/stencil to be cleared for later re-use, ", + "so this we have to disable our optimization that drops the clears on invalidate." + ], + "issue": "https://issuetracker.google.com/462484277" + }, + { + "name": "supports_tile_memory_heap", + "category": "Features", + "description": [ + "VkDevice supports VK_QCOM_tile_memory_heap extension." + ], + "issue": "https://issuetracker.google.com/447633563" + }, + { + "name": "simulate_tile_memory_for_testing", + "category": "Features", + "description": [ + "Simulate VK_QCOM_tile_memory_heap for images on GPUs that do not support VK_QCOM_tile_memory_heap extension for testing purpose." + ], + "issue": "https://issuetracker.google.com/447633563" } ] } diff --git a/include/platform/wgpu_features.json b/include/platform/wgpu_features.json new file mode 100644 index 00000000000..9046b2b0232 --- /dev/null +++ b/include/platform/wgpu_features.json @@ -0,0 +1,18 @@ +{ + "description": [ + "Copyright 2025 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.", + "", + "wgpu_features.json: angle::Features and workarounds for the WebGPU backend." + ], + "features": [ + { + "name": "avoid_wait_any", + "category": "Workarounds", + "description": [ + "Avoid unnecessary calls to wpguInstanceWaitAny." + ] + } + ] +} diff --git a/include/vulkan/vulkan_fuchsia_ext.h b/include/vulkan/vulkan_fuchsia_ext.h index ecb28b0b6eb..9a9c63f8795 100644 --- a/include/vulkan/vulkan_fuchsia_ext.h +++ b/include/vulkan/vulkan_fuchsia_ext.h @@ -17,6 +17,16 @@ #include +/* vulkan.h includes when VK_USE_PLATFORM_XLIB_KHR is defined + * after https://github.com/KhronosGroup/Vulkan-Headers/pull/534. + * This defines some macros which break build, so undefine them here. + */ +#undef Always +#undef Bool +#undef None +#undef Status +#undef Success + // If this is not Fuchsia then define Fuchsia-specific types explicitly and include // vulkan_fuchsia.h to make it possible to compile the code on other platforms. // diff --git a/infra/ANGLEWrangling.md b/infra/ANGLEWrangling.md index 769b9cc193e..ca67c4ca0d9 100644 --- a/infra/ANGLEWrangling.md +++ b/infra/ANGLEWrangling.md @@ -1,201 +1,4 @@ # ANGLE Wrangling -As an ANGLE Sheriff. Your job is to: +Wrangling document has moved. See [ANGLE Wrangler](https://goto.google.com/angle-wrangler). - 1. Keep the [ANGLE Standalone][StandaloneCI] and [ANGLE/Chromium][ANGLEChromiumCI] waterfalls green. - 1. Ensure developers have reliable pre-commit testing via the - [ANGLE Standalone][StandaloneTry] and [ANGLE/Chromium][ANGLEChromiumTry] try waterfalls. - 1. Control and monitor the [ANGLE auto-rollers](#the-auto-rollers). - 1. Act as a point of contact for the Chromium Sheriff and other teams monitoring ANGLE regressions. - 1. **Note: currently not working!** Monitor and respond to ANGLE's [Perf alerts][PerfAlertGroup]. - -[StandaloneCI]: https://ci.chromium.org/p/angle/g/ci/console -[ANGLEChromiumCI]: https://ci.chromium.org/p/chromium/g/chromium.angle/console -[StandaloneTry]: https://ci.chromium.org/ui/p/angle/g/try/builders -[ANGLEChromiumTry]: https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders -[PerfAlertGroup]: https://groups.google.com/u/0/a/chromium.org/g/angle-perf-alerts - -If you're not an ANGLE team member, you can contact us on the public ANGLE project -[Google group](https://groups.google.com/forum/#!forum/angleproject). - -**Note**: Please review and if needed update the [wrangler schedule]. - -**Note**: If you need to suppress test failures (e.g. to keep an auto-roller unblocked), see -[Handling Test Failures](../doc/TestingAndProcesses.md). - -[wrangler schedule]: https://rotations.corp.google.com/rotation/5080504293392384 - -## Task: Monitor ANGLE CI and Try Testers - -Your first job is to keep the ANGLE builders green and unblocked. - -### Post-commit CI builders - -There are two consoles for ANGLE continuous integration builders: - - * Standalone ANGLE: https://ci.chromium.org/p/angle/g/ci/console - * Chromium + integrated ANGLE: https://ci.chromium.org/p/chromium/g/chromium.angle/console - -We recommend you track ANGLE build failures is via [Sheriff-o-matic][ANGLESoM]. -Bookmark the link and check it regularly during your shift. **Note**: -currently flaky failures show up as separate failure instances. - -[ANGLESoM]: https://sheriff-o-matic.appspot.com/angle - -We expect these waterfalls to be as "green" as possible. As a wrangler -please help clean out any failures by finding and reverting problematic CLs, -suppressing flaky tests that can't be fixed, or finding other solutions. We -aim to have zero failing builds, so follow the campsite rule and leave the -waterfall cleaner than when you started your shift. - -When you encounter red builds or flakiness, [file an ANGLE bug](http://anglebug.com/new) -and set the label: `Hotlist-Wrangler` ([search for existing bugs][WranglerBugs]). - -[WranglerBugs]: https://bugs.chromium.org/p/angleproject/issues/list?q=Hotlist%3DWrangler&can=2 - -See more detailed instructions on ANGLE testing by following [this link](README.md). - -### Pre-commit try builders - -In addition to the CI builders, we have a console for try jobs on the ANGLE CV (change verifier): - - * Standalone ANGLE: https://ci.chromium.org/ui/p/angle/g/try/builders - * Chromium + integrated ANGLE: https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders - -Failures are intended on this waterfall as developers test WIP changes. -You must act on any persistent flakiness or failure that causes developer drag -by filing bugs, reverting CLs, or taking other action as with the CI waterfall. - -If you find a failure that is unrelated to ANGLE, [file a Chromium bug](http://crbug.com/new). -Set the bug label `Hotlist-PixelWrangler`. Ensure you cc the current ANGLE and Chrome GPU -wranglers, which you can find by consulting -[build.chromium.org](https://ci.chromium.org/p/chromium/g/main/console). -For more information see [Filing Chromium Bug Reports](#filing-chromium-bug-reports) below. - -You can optionally follow [Chromium bugs in the `Internals>GPU>ANGLE` component][ChromiumANGLEBugs] -to be alerted to reports of ANGLE-related breakage in Chrome. - -[ChromiumANGLEBugs]: https://bugs.chromium.org/p/chromium/issues/list?q=component%3AInternals%3EGPU%3EANGLE&can=2 - -**NOTE: When all builds seem to be purple or otherwise broken:** - -This could be a major infrastructure outage. File a high-priority bug using -[g.co/bugatrooper](http://g.co/bugatrooper). - -### Filing Chromium Bug Reports - -The GPU Pixel Wrangler is responsible for *Chromium* bugs. Please file -Chromium issues with the Label `Hotlist-PixelWrangler` for bugs outside of -the ANGLE project. - -*IMPORTANT* info to include in Chromium bug reports: - - * Links to all first failing builds (e.g. first windows failure, first mac failure, etc). - * Related regression ranges. See below on how to determine the ANGLE regression range. - * Relevant error messages. - * Set the **Components** to one or more value, such as (start typing "Internals" and you'll see choices): - * `Internals>GPU` for general GPU bugs - * `Internals>GPU>Testing` for failures that look infrastructure-related - * `Internals>GPU>ANGLE` for ANGLE-related Chromium bugs - * `Internals>Skia` for Skia-specific bugs - * Cc relevant sheriffs or blame suspects, as well as yourself or the current ANGLE Wrangler. - * Set the `Hotlist-PixelWrangler` Label. - -### How to determine the ANGLE regression range on Chromium bots: - - 1. Open the first failing and last passing builds. - 1. For test failures: record `parent_got_angle_revision` in both builds. - 1. For compile failures record `got_angle_revision`. - 1. Create a regression link with this URL template: - `https://chromium.googlesource.com/angle/angle.git/+log/..` - -## Task: The Auto-Rollers - -The [ANGLE into Chrome auto-roller](https://autoroll.skia.org/r/angle-chromium-autoroll) automatically updates -Chrome with the latest ANGLE changes. - -The [ANGLE into Android auto-roller](https://autoroll.skia.org/r/angle-android-autoroll) updates Android with -the latest ANGLE changes. You must manually approve and land these rolls. The -recommendation is to pre-approve the roll and set "**Autosubmit**". - * The auto-roller abandons a presubmit-passed roll whenever a new ANGLE change - comes. During work hours, it's hard for Wrangler to approve and land in - time. - -We also use additional auto-rollers to roll third party libraries into ANGLE and Chromium: - - * [SwiftShader into ANGLE](https://autoroll.skia.org/r/swiftshader-angle-autoroll) - * [vulkan-deps into ANGLE](https://autoroll.skia.org/r/vulkan-deps-angle-autoroll) - * [VK-GL-CTS into ANGLE](https://autoroll.skia.org/r/vk-gl-cts-angle-autoroll) - * [Chromium into ANGLE](https://autoroll.skia.org/r/chromium-angle-autoroll) - * [SwiftShader into Chromium](https://autoroll.skia.org/r/swiftshader-chromium-autoroll) - -**Roller health**: You will be cc'ed on all rolls. Please check failed rolls - to verify there is no blocking breakage. - -For all rollers, you can trigger manual rolls using the dashboards to land -high-priority changes. For example: Chromium-side test expectation updates or -suppressions. When a roll fails, stop the roller, determine if the root cause -is a problem with ANGLE or with the upstream repo, and file an issue with an -appropriate next step. - -To monitor the rollers during your shift, you can: - 1. Open the [autoroll dashboard](https://autoroll.skia.org/) and put "angle" in `Filter`. The dashboard provides the status of ANGLE related rollers. Monitor their modes and numbers. - 1. Filter out the non-critical emails by a filter: “`from:(*-autoroll (Gerrit))`”. This improves the signal to noise ratio of your inbox, so the important emails, ex) "`The roll is failing consistently. Time to investigate.`", can stand out. - -The autoroller configurations live in the -[skia-autoroll-internal-config repository](https://skia.googlesource.com/skia-autoroll-internal-config.git/+/main/skia-public). -Feel free to maintain these configs yourself, or file a Skia [autoroll bug][SkiaAutorollBug] -for help as needed. - -[SkiaAutorollBug]: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug - -### Vulkan Dependencies auto-roller: Handling failures - -**Vulkan-deps consists of several related Vulkan dependencies**: Vulkan-Tools, -Vulkan-Loader, Vulkan-ValidationLayers, Vulkan-Headers and other related -repos. One common source of breaks is a Vulkan Headers update, which can take -a while to be integrated into other repos like the Vulkan Validation Layers. -No action on your part is needed for header updates. - -If a vulkan-deps AutoRoll CL triggers an failure in the `presubmit` bot, in -the "export targets" step, you can: - - 1. Add missing headers to the upstream `BUILD.gn` if possible. See this [example CL][GNHeaderExample]. - 1. Otherwise, add headers to `IGNORED_INCLUDES` in [`export_targets.py`][ExportTargetsPy]. See this -[example CL][ExportHeaderExample]. - -[GNHeaderExample]: https://github.com/KhronosGroup/Vulkan-Loader/pull/968 -[ExportTargetsPy]: ../scripts/export_targets.py -[ExportHeaderExample]: https://chromium-review.googlesource.com/c/angle/angle/+/3399044 - -If the roll fails for a reason other than a header update or presubmit, -determine the correct upstream repo and file an issue upstream. For simple -compilation failures, we usually submit fixes ourselves. For more info on -vulkan-deps see the [README][VulkanDepsREADME]. - -[VulkanDepsREADME]: https://chromium.googlesource.com/vulkan-deps/+/refs/heads/main/README.md - -### ANGLE into Chrome auto-roller: SwANGLE builders - -The ANGLE into Chromium roller has two SwiftShader + ANGLE (SwANGLE) builders: -[linux-swangle-try-x64](https://luci-milo.appspot.com/p/chromium/builders/try/linux-swangle-try-x64) -and -[win-swangle-try-x86](https://luci-milo.appspot.com/p/chromium/builders/try/win-swangle-try-x86). -However, failures on these bots may be due to SwiftShader changes. - -To handle failures on these bots: -1. If possible, suppress the failing tests in ANGLE, opening a bug to investigate later. -1. If you supsect an ANGLE CL caused a regression, - consider whether reverting it or suppressing the failures is a better course of action. -1. If you suspect a SwiftShader CL, and the breakage is too severe to suppress, - (a lot of tests fail in multiple suites), - consider reverting the responsible SwiftShader roll into Chromium - and open a SwiftShader [bug](http://go/swiftshaderbugs). SwiftShader rolls into Chromium - should fail afterwards, but if the bad roll manages to reland, - stop the [autoroller](https://autoroll.skia.org/r/swiftshader-chromium-autoroll) as well. - -## Task: Monitor and respond to ANGLE's perf alerts - -Any large regressions should be triaged with a new ANGLE bug linked to any suspected CLs that may -have caused performance to regress. If it's a known/expected regression, the bug can be closed as -such. The tests are very flaky right now, so a WontFix resolution is often appropriate. diff --git a/infra/README.md b/infra/README.md index f5b26c8e49c..21e66324114 100644 --- a/infra/README.md +++ b/infra/README.md @@ -3,94 +3,56 @@ ANGLE runs hundreds of thousands of tests on every change before it lands in the tree. We scale our pre-commit and post-commit testing to many machines using [Chromium Swarming][Swarming]. Our testing setup heavily leverages -existing work in Chromium. We also run compile-only -[Standalone Testing][Standalone] that does not depend on a Chromium checkout. - -Also see the documentation on [ANGLE Wrangling][Wrangling] for more info. +existing work in Chromium. We also run standalone testing +that does not depend on a Chromium checkout. ## Pre-Commit Testing -See the pre-commit try waterfall here: - -[`https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders`](https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders) +We have pre-commit testing on [Chromium][ANGLEChromiumTry] and [ANGLE][StandaloneTry] try waterfalls. We currently run pre-commit tests on: - * Windows 32-bit AMD and Windows 64-bit Intel and NVIDIA GPUs - * Linux 64-bit NVIDIA and Intel GPUs + * Windows 64-bit Intel and NVIDIA GPUs and SwiftShader on VMs + * Windows 32-bit on SwiftShader on VMs + * Linux 64-bit Intel and NVIDIA GPUs and SwiftShader on VMs * Mac NVIDIA, Intel and AMD GPUs - * Pixel 4 and Nexus 5X - * Fuchsia testing in a VM + * Pixel 2, Pixel 4 and Pixel 6 + * Fuchsia compile-only + * iOS simulator on demand Looking at an example build shows how tests are split up between machines. See for example: -[`https://ci.chromium.org/ui/p/angle/builders/ci/mac-rel/8123/overview`](https://ci.chromium.org/ui/p/angle/builders/ci/mac-rel/8123/overview) +[`https://ci.chromium.org/ui/p/angle/builders/ci/mac-test/8117/overview`](https://ci.chromium.org/ui/p/angle/builders/ci/mac-test/8117/overview) -This build ran 68 test steps across 3 GPU families. In some cases (e.g. +This build ran 67 test steps across 3 GPU families. In some cases (e.g. `angle_deqp_gles3_metal_tests`) the test is split up between multiple machines to -run faster (in this case 2 different machines at once). This build took 23 -minutes to complete 72 minutes of real automated testing. +run faster (in this case 2 different machines at once). This build took 10 +minutes to complete 50 minutes of real automated testing. For more details on running and working with our test sets see the docs in [Contributing Code][Contrib]. -[Swarming]: https://chromium-swarm.appspot.com/ -[Standalone]: #ANGLE-Standalone-Testing -[Contrib]: ../doc/ContributingCode.md#Testing -[Wrangling]: ANGLEWrangling.md - -## ANGLE Standalone Testing - -In addition to the ANGLE try bots using Chrome, and the GPU.FYI bots, ANGLE -has standalone testing on the Chrome infrastructure. Currently these tests are -compile-only. This page is for maintaining the configurations that don't use -Chromium. Also see the main instructions for [ANGLE Wrangling](ANGLEWrangling.md). - -It's the ANGLE team's responsibility for maintaining this testing -infrastructure. The bot configurations live in four different repos and six -branches. - -## Info Consoles - -Continuous builders for every ANGLE revision are found on the CI console: - -[https://ci.chromium.org/p/angle/g/ci/console](https://ci.chromium.org/p/angle/g/ci/console) - -Try jobs from pre-commit builds are found on the builders console: +## Post-Commit Testing -[https://ci.chromium.org/p/angle/g/try/builders](https://ci.chromium.org/p/angle/g/try/builders) +Similarly to pre-commit testing, there are also [Chromium][ANGLEChromiumCI] and [ANGLE][StandaloneCI] CI (Continuous Integration) waterfalls. +These run on the same configurations as pre-commit, plus additional configurations for which we only have limited HW, e.g. Samsung S22 phones. +They are useful for detecting flaky failures and for regression blamelists in case some failure does manage to slip through pre-commit testing. -## How to add a new build configuration +## Auto-Rollers - 1. [`bugs.chromium.org/p/chromium/issues/entry?template=Build+Infrastructure`](http://bugs.chromium.org/p/chromium/issues/entry?template=Build+Infrastructure): +Some ANGLE dependencies are rolled in via automatically created CLs by these auto-rollers: + * [SwiftShader](https://autoroll.skia.org/r/swiftshader-angle-autoroll) + * [vulkan-deps](https://autoroll.skia.org/r/vulkan-deps-angle-autoroll) + * [VK-GL-CTS](https://autoroll.skia.org/r/vk-gl-cts-angle-autoroll) + * [Chromium build dependencies](https://autoroll.skia.org/r/chromium-angle-autoroll) - * If adding a Mac bot, request new slaves by filing an infra issue. +Similarly, Chromium's copy of ANGLE is updated by the [ANGLE into Chromium auto-roller](https://autoroll.skia.org/r/angle-chromium-autoroll). +And there also exists a [SwiftShader into Chromium auto-roller](https://autoroll.skia.org/r/swiftshader-chromium-autoroll). - 1. [`chrome-internal.googlesource.com/infradata/config`](http://chrome-internal.googlesource.com/infradata/config): - - * Update **`configs/chromium-swarm/starlark/bots/angle.star`** with either Mac slaves requested in the previous step or increase the amount of Windows or Linux GCEs. - - 1. [`chromium.googlesource.com/chromium/tools/build`](https://chromium.googlesource.com/chromium/tools/build): - - * Update **`scripts/slave/recipes/angle.py`** with new the config. - * The recipe code requires 100% code coverage through mock bots, so add mock bot config to GenTests. - * Maybe run `./scripts/slave/recipes.py test train` to update checked-in golden files. This might no longer be necessary. - - 1. [`chromium.googlesource.com/angle/angle`](http://chromium.googlesource.com/angle/angle): - - * Update **`infra/config/global/cr-buildbucket.cfg`** to add the new builder (to ci and try), and set the new config option. - * Update **`infra/config/global/luci-milo.cfg`** to make the builders show up on the ci and try waterfalls. - * Update **`infra/config/global/luci-scheduler.cfg`** to make the builders trigger on new commits or try jobs respectively. - * Update **`infra/config/global/commit-queue.cfg`** to add the builder to the default CQ jobs (if desired). - -## Other Configuration - -There are other places where configuration for ANGLE infra lives. These are files that we shouldn't need to modify very often: - - 1. [`chrome-internal.googlesource.com/infradata/config`](http://chrome-internal.googlesource.com/infradata/config): - - * **`configs/luci-token-server/service_accounts.cfg`** (service account names) - * **`configs/chromium-swarm/pools.cfg`** (swarming pools) +[Swarming]: https://chromium-swarm.appspot.com/ +[Contrib]: ../doc/ContributingCode.md#Testing +[ANGLEChromiumCI]: https://ci.chromium.org/p/chromium/g/chromium.angle/console +[ANGLEChromiumTry]: https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders +[StandaloneCI]: https://ci.chromium.org/p/angle/g/ci/console +[StandaloneTry]: https://ci.chromium.org/ui/p/angle/g/try/builders - 1. [`chromium.googlesource.com/chromium/tools/depot_tools`](http://chromium.googlesource.com/chromium/tools/depot_tools): - * **`recipes/recipe_modules/gclient/config.py`** (gclient config) diff --git a/infra/config/PACKAGE.lock b/infra/config/PACKAGE.lock new file mode 100644 index 00000000000..3b4a7e0733a --- /dev/null +++ b/infra/config/PACKAGE.lock @@ -0,0 +1,24 @@ +{ + "lucicfg": "1.45.8", + "packages": [ + { + "name": "@angle-project", + "deps": [ + "@chromium-luci" + ], + "lucicfg": "1.45.8", + "entrypoints": [ + "main.star" + ] + }, + { + "name": "@chromium-luci", + "source": { + "repo": "https://chromium.googlesource.com/infra/chromium/+/refs/heads/main", + "revision": "d32eb6269c44595510753283e4288ea36b45f640", + "path": "starlark-libs/chromium-luci" + }, + "lucicfg": "1.45.0" + } + ] +} diff --git a/infra/config/PACKAGE.star b/infra/config/PACKAGE.star new file mode 100644 index 00000000000..35630fc3135 --- /dev/null +++ b/infra/config/PACKAGE.star @@ -0,0 +1,29 @@ +#!/usr/bin/env lucicfg +# +# Copyright 2025 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Package declaration for the Angle project.""" + +pkg.declare( + name = "@angle-project", + lucicfg = "1.45.8", +) + +pkg.options.lint_checks([ + "all", +]) + +pkg.entrypoint("main.star") + +pkg.depend( + name = "@chromium-luci", + source = pkg.source.googlesource( + host = "chromium", + repo = "infra/chromium", + ref = "refs/heads/main", + path = "starlark-libs/chromium-luci", + revision = "d32eb6269c44595510753283e4288ea36b45f640", + ), +) diff --git a/infra/config/angle_v2_ci.star b/infra/config/angle_v2_ci.star new file mode 100644 index 00000000000..0d8b8b0e75a --- /dev/null +++ b/infra/config/angle_v2_ci.star @@ -0,0 +1,102 @@ +# Copyright 2026 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""CI ANGLE builders using the angle_v2 recipe.""" + +load("@chromium-luci//builder_config.star", "builder_config") +load("@chromium-luci//builders.star", "os") +load("@chromium-luci//ci.star", "ci") +load("@chromium-luci//gardener_rotations.star", "gardener_rotations") +load("@chromium-luci//gn_args.star", "gn_args") +load("//constants.star", "default_experiments", "siso") + +ci.defaults.set( + executable = "recipe:angle_v2/angle_v2", + builder_group = "angle", + bucket = "ci", + pool = "luci.chromium.gpu.ci", + triggered_by = ["main-poller"], + build_numbers = True, + contact_team_email = "chrome-gpu-infra@google.com", + gardener_rotations = gardener_rotations.rotation("angle", None, None), + service_account = "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com", + shadow_service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", + siso_project = siso.project.DEFAULT_TRUSTED, + shadow_siso_project = siso.project.DEFAULT_UNTRUSTED, + siso_remote_jobs = siso.remote_jobs.DEFAULT, + thin_tester_cores = 2, + builderless = True, + experiments = default_experiments, + test_presentation = resultdb.test_presentation( + column_keys = ["v.gpu"], + grouping_keys = ["status", "v.test_suite"], + ), +) + +################################################################################ +# Parent Builders # +################################################################################ + +def angle_linux_parent_builder(**kwargs): + kwargs.setdefault("cores", 8) + kwargs.setdefault("os", os.LINUX_DEFAULT) + ci.builder(**kwargs) + +angle_linux_parent_builder( + name = "angle-linux-x64-builder-rel", + description_html = "Compiles release ANGLE test binaries for Linux/x64", + schedule = "triggered", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "angle_v2", + ), + chromium_config = builder_config.chromium_config( + config = "angle_v2_clang", + build_config = builder_config.build_config.RELEASE, + target_arch = builder_config.target_arch.INTEL, + target_bits = 64, + target_platform = builder_config.target_platform.LINUX, + ), + ), + gn_args = gn_args.config( + configs = [ + "capture", + "component", + "linux_clang", + "opencl", + "release_with_dchecks", + "x64", + ], + ), + # TODO(crbug.com/475260235): Move this to the main view once it is at + # parity with the older equivalent. + list_view = "exp", +) + +################################################################################ +# Child Testers # +################################################################################ + +ci.thin_tester( + name = "angle-linux-x64-sws-rel", + description_html = "Tests release ANGLE on Linux/x64 with SwiftShader", + parent = "angle-linux-x64-builder-rel", + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "angle_v2", + ), + chromium_config = builder_config.chromium_config( + config = "angle_v2_clang", + build_config = builder_config.build_config.RELEASE, + target_arch = builder_config.target_arch.INTEL, + target_bits = 64, + target_platform = builder_config.target_platform.LINUX, + ), + run_tests_serially = True, + ), + # TODO(crbug.com/475260235): Move this to the main view once it is at + # parity with the older equivalent. + list_view = "exp", +) diff --git a/infra/config/angle_v2_try.star b/infra/config/angle_v2_try.star new file mode 100644 index 00000000000..905ab0c8bb0 --- /dev/null +++ b/infra/config/angle_v2_try.star @@ -0,0 +1,97 @@ +# Copyright 2026 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Try ANGLE builders using the angle_v2 recipe.""" + +load("@chromium-luci//builders.star", "os") +load("@chromium-luci//try.star", "try_") +load("//constants.star", "default_experiments", "siso") + +try_.defaults.set( + executable = "recipe:angle_v2/angle_v2_trybot", + builder_group = "angle", + bucket = "try", + pool = "luci.chromium.gpu.try", + builderless = True, + build_numbers = True, + list_view = "try", + cq_group = "main", + contact_team_email = "chrome-gpu-infra@google.com", + service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", + siso_project = siso.project.DEFAULT_UNTRUSTED, + siso_remote_jobs = siso.remote_jobs.DEFAULT, + experiments = default_experiments, +) + +################################################################################ +# CQ Builders # +################################################################################ + +## Templates + +def apply_cq_builder_defaults(kwargs): + kwargs.setdefault("max_concurrent_builds", 4) + return kwargs + +def apply_linux_cq_builder_defaults(kwargs): + """Applies default builder settings for a Linux CQ builder. + + Args: + kwargs: The args being used for the builder as a dict. + + Returns: + |kwargs| with default values set for a Linux CQ builder. + """ + kwargs = apply_cq_builder_defaults(kwargs) + kwargs.setdefault("cores", 8) + kwargs.setdefault("os", os.LINUX_DEFAULT) + kwargs.setdefault("ssd", None) + return kwargs + +def angle_linux_functional_cq_tester(**kwargs): + kwargs = apply_linux_cq_builder_defaults(kwargs) + + # TODO(crbug.com/475260235): Actually add the try_.job() entry when we are + # ready to add chromium-luci builders to the CQ. + try_.builder(**kwargs) + +## Functional testers + +angle_linux_functional_cq_tester( + name = "angle-cq-linux-x64-rel", + description_html = "Tests release ANGLE on Linux/x64 on multiple hardware configs. Blocks CL submission.", + mirrors = [ + "ci/angle-linux-x64-builder-rel", + "ci/angle-linux-x64-sws-rel", + ], + gn_args = "ci/angle-linux-x64-builder-rel", +) + +################################################################################ +# Manual Trybots # +################################################################################ + +## Templates + +def angle_linux_manual_builder(*, name, **kwargs): + return try_.builder( + name = name, + max_concurrent_builds = 1, + cores = 8, + os = os.LINUX_DEFAULT, + ssd = None, + **kwargs + ) + +## Functional testers + +angle_linux_manual_builder( + name = "angle-try-linux-x64-sws-rel", + description_html = "Tests release ANGLE on Linux/x64 with SwiftShader. Manual only.", + mirrors = [ + "ci/angle-linux-x64-builder-rel", + "ci/angle-linux-x64-sws-rel", + ], + gn_args = "ci/angle-linux-x64-builder-rel", +) diff --git a/infra/config/constants.star b/infra/config/constants.star new file mode 100644 index 00000000000..4f031767bc3 --- /dev/null +++ b/infra/config/constants.star @@ -0,0 +1,24 @@ +# Copyright 2026 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Constants shared between multiple ANGLE Starlark files.""" + +# Copied from Chromium's lib/builders.star and trimmed. +siso = struct( + project = struct( + DEFAULT_TRUSTED = "rbe-chromium-trusted", + DEFAULT_UNTRUSTED = "rbe-chromium-untrusted", + ), + remote_jobs = struct( + DEFAULT = 250, + LOW_JOBS_FOR_CI = 80, + HIGH_JOBS_FOR_CI = 500, + LOW_JOBS_FOR_CQ = 150, + ), +) + +default_experiments = { + # Fail build when merge script fails. + "chromium_swarming.expose_merge_script_failures": 100, +} diff --git a/infra/config/generated/builders/ci/angle-linux-x64-builder-rel/gn-args.json b/infra/config/generated/builders/ci/angle-linux-x64-builder-rel/gn-args.json new file mode 100644 index 00000000000..42607e4f2f3 --- /dev/null +++ b/infra/config/generated/builders/ci/angle-linux-x64-builder-rel/gn-args.json @@ -0,0 +1,16 @@ +{ + "gn_args": { + "angle_enable_cl": true, + "angle_with_capture_by_default": true, + "dcheck_always_on": true, + "is_clang": true, + "is_component_build": true, + "is_debug": false, + "symbol_level": 1, + "target_cpu": "x64", + "target_os": "linux", + "use_reclient": false, + "use_remoteexec": true, + "use_siso": true + } +} \ No newline at end of file diff --git a/infra/config/generated/builders/gn_args_locations.json b/infra/config/generated/builders/gn_args_locations.json new file mode 100644 index 00000000000..bbfbeb59503 --- /dev/null +++ b/infra/config/generated/builders/gn_args_locations.json @@ -0,0 +1,7 @@ +{ + "angle": { + "angle-cq-linux-x64-rel": "try/angle-cq-linux-x64-rel/gn-args.json", + "angle-linux-x64-builder-rel": "ci/angle-linux-x64-builder-rel/gn-args.json", + "angle-try-linux-x64-sws-rel": "try/angle-try-linux-x64-sws-rel/gn-args.json" + } +} \ No newline at end of file diff --git a/infra/config/generated/builders/try/angle-cq-linux-x64-rel/gn-args.json b/infra/config/generated/builders/try/angle-cq-linux-x64-rel/gn-args.json new file mode 100644 index 00000000000..42607e4f2f3 --- /dev/null +++ b/infra/config/generated/builders/try/angle-cq-linux-x64-rel/gn-args.json @@ -0,0 +1,16 @@ +{ + "gn_args": { + "angle_enable_cl": true, + "angle_with_capture_by_default": true, + "dcheck_always_on": true, + "is_clang": true, + "is_component_build": true, + "is_debug": false, + "symbol_level": 1, + "target_cpu": "x64", + "target_os": "linux", + "use_reclient": false, + "use_remoteexec": true, + "use_siso": true + } +} \ No newline at end of file diff --git a/infra/config/generated/builders/try/angle-try-linux-x64-sws-rel/gn-args.json b/infra/config/generated/builders/try/angle-try-linux-x64-sws-rel/gn-args.json new file mode 100644 index 00000000000..42607e4f2f3 --- /dev/null +++ b/infra/config/generated/builders/try/angle-try-linux-x64-sws-rel/gn-args.json @@ -0,0 +1,16 @@ +{ + "gn_args": { + "angle_enable_cl": true, + "angle_with_capture_by_default": true, + "dcheck_always_on": true, + "is_clang": true, + "is_component_build": true, + "is_debug": false, + "symbol_level": 1, + "target_cpu": "x64", + "target_os": "linux", + "use_reclient": false, + "use_remoteexec": true, + "use_siso": true + } +} \ No newline at end of file diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg similarity index 92% rename from infra/config/generated/commit-queue.cfg rename to infra/config/generated/luci/commit-queue.cfg index 99474a303f4..52325f3439e 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg @@ -38,6 +38,16 @@ config_groups { builders { name: "angle/try/android-arm64-test" } + builders { + name: "angle/try/angle-cq-linux-x64-rel" + includable_only: true + disable_reuse_footers: "Include-Ci-Only-Tests" + } + builders { + name: "angle/try/angle-try-linux-x64-sws-rel" + includable_only: true + disable_reuse_footers: "Include-Ci-Only-Tests" + } builders { name: "angle/try/linux-asan-test" } @@ -89,6 +99,9 @@ config_groups { builders { name: "angle/try/linux-tsan-test" } + builders { + name: "angle/try/mac-arm64-test" + } builders { name: "angle/try/mac-dbg-compile" } @@ -199,3 +212,4 @@ config_groups { } } } +gerrit_listener_type: GERRIT_LISTENER_TYPE_PUBSUB diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg similarity index 57% rename from infra/config/generated/cr-buildbucket.cfg rename to infra/config/generated/luci/cr-buildbucket.cfg index 4220723fc48..c9fbcfbc672 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg @@ -6,13 +6,6 @@ buckets { name: "ci" - acls { - group: "all" - } - acls { - role: SCHEDULER - identity: "user:angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - } swarming { builders { name: "android-arm-compile" @@ -25,10 +18,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -58,10 +55,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -80,10 +73,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -113,10 +110,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -135,10 +128,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -168,10 +165,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -180,7 +173,7 @@ buckets { } } builders { - name: "android-arm64-exp-s22-test" + name: "android-arm64-exp-pixel10-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "os:Ubuntu" exe { @@ -190,10 +183,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -223,10 +220,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -235,7 +228,7 @@ buckets { } } builders { - name: "android-arm64-exp-test" + name: "android-arm64-exp-s24-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "os:Ubuntu" exe { @@ -245,10 +238,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -278,10 +275,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -290,7 +283,7 @@ buckets { } } builders { - name: "android-arm64-test" + name: "android-arm64-exp-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "os:Ubuntu" exe { @@ -300,10 +293,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -333,10 +330,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -345,7 +338,7 @@ buckets { } } builders { - name: "android-pixel4-perf" + name: "android-arm64-ir-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "os:Ubuntu" exe { @@ -355,10 +348,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -381,17 +378,13 @@ buckets { ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 18000 + execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -400,7 +393,7 @@ buckets { } } builders { - name: "android-pixel6-perf" + name: "android-arm64-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "os:Ubuntu" exe { @@ -410,10 +403,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -436,17 +433,13 @@ buckets { ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 18000 + execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -455,9 +448,8 @@ buckets { } } builders { - name: "linux-asan-test" + name: "android-pixel4-perf" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" @@ -466,10 +458,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -484,7 +480,7 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "linux",' + ' "platform": "android",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' @@ -492,17 +488,13 @@ buckets { ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 10800 + execution_timeout_secs: 18000 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -511,9 +503,8 @@ buckets { } } builders { - name: "linux-dbg-compile" + name: "android-pixel6-perf" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" @@ -522,10 +513,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -540,25 +535,21 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "linux",' + ' "platform": "android",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 10800 + execution_timeout_secs: 18000 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -567,10 +558,13 @@ buckets { } } builders { - name: "linux-exp-asan-test" + name: "angle-linux-x64-builder-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Ubuntu" + dimensions: "cores:8" + dimensions: "os:Ubuntu-22.04" + dimensions: "pool:luci.chromium.gpu.ci" + dimensions: "ssd:0" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -578,10 +572,100 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' + ' "$build/chromium_tests_builder_config": {' + ' "builder_config": {' + ' "additional_exclusions": [' + ' "infra/config/generated/builders/ci/angle-linux-x64-builder-rel/gn-args.json"' + ' ],' + ' "builder_db": {' + ' "entries": [' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "COMPILE_AND_TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' }' + ' }' + ' },' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' },' + ' "parent": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "run_tests_serially": true' + ' }' + ' }' + ' ]' + ' },' + ' "builder_ids": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' }' + ' ],' + ' "builder_ids_in_scope_for_testing": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' }' + ' ],' + ' "mirroring_builder_group_and_names": [' + ' {' + ' "builder": "angle-cq-linux-x64-rel",' + ' "group": "angle"' + ' },' + ' {' + ' "builder": "angle-try-linux-x64-sws-rel",' + ' "group": "angle"' + ' }' + ' ]' + ' }' + ' },' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "experiments": [],' ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "project": "rbe-chromium-trusted",' + ' "remote_jobs": 250' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -596,37 +680,100 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "linux",' - ' "recipe": "angle",' + ' "recipe": "angle_v2/angle_v2",' ' "sheriff_rotations": [' ' "angle"' - ' ],' - ' "test_mode": "compile_and_test",' - ' "toolchain": "clang"' + ' ]' '}' - execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "chromium_swarming.expose_merge_script_failures" + key: "chromium.use_per_builder_build_dir_name" value: 100 } experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { enable: true - } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://(chrome|content)/test:telemetry_gpu_integration_test[^/]*/.+)" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)|(ninja://[^/]*headless_shell_wpt/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + description_html: "Compiles release ANGLE test binaries for Linux/x64
This builder is mirrored by any of the following try builders:

Builder owner: chrome-gpu-infra@google.com" shadow_builder_adjustments { service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "experiments": [],' + ' "metrics_project": "chromium-reclient-metrics",' + ' "project": "rbe-chromium-untrusted",' + ' "remote_jobs": 250' + ' }' + '}' + } + contact_team_email: "chrome-gpu-infra@google.com" + custom_metric_definitions { + name: "/chrome/infra/browser/builds/cached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"true\"" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_retry_shard_count" + predicates: "has(build.output.properties.ran_tests_retry_shard)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_without_patch_count" + predicates: "has(build.output.properties.ran_tests_without_patch)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/uncached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"false\"" } } builders { - name: "linux-exp-test" + name: "angle-linux-x64-sws-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Ubuntu" + dimensions: "cores:2" + dimensions: "os:Ubuntu-22.04" + dimensions: "pool:luci.chromium.gpu.ci" + dimensions: "ssd:0" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -634,10 +781,78 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/chromium_tests_builder_config": {' + ' "builder_config": {' + ' "builder_db": {' + ' "entries": [' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "COMPILE_AND_TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' }' + ' }' + ' },' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' },' + ' "parent": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "run_tests_serially": true' + ' }' + ' }' + ' ]' + ' },' + ' "builder_ids": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' }' + ' ],' + ' "mirroring_builder_group_and_names": [' + ' {' + ' "builder": "angle-cq-linux-x64-rel",' + ' "group": "angle"' + ' },' + ' {' + ' "builder": "angle-try-linux-x64-sws-rel",' + ' "group": "angle"' + ' }' + ' ]' + ' }' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -652,34 +867,79 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "linux",' - ' "recipe": "angle",' + ' "recipe": "angle_v2/angle_v2",' ' "sheriff_rotations": [' ' "angle"' - ' ],' - ' "test_mode": "compile_and_test",' - ' "toolchain": "clang"' + ' ]' '}' - execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "chromium_swarming.expose_merge_script_failures" + key: "chromium.use_per_builder_build_dir_name" value: 100 } experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { enable: true - } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://(chrome|content)/test:telemetry_gpu_integration_test[^/]*/.+)" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)|(ninja://[^/]*headless_shell_wpt/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + description_html: "Tests release ANGLE on Linux/x64 with SwiftShader
This builder is mirrored by any of the following try builders:

Builder owner: chrome-gpu-infra@google.com" shadow_builder_adjustments { service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" } + contact_team_email: "chrome-gpu-infra@google.com" + custom_metric_definitions { + name: "/chrome/infra/browser/builds/cached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"true\"" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_retry_shard_count" + predicates: "has(build.output.properties.ran_tests_retry_shard)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_without_patch_count" + predicates: "has(build.output.properties.ran_tests_without_patch)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/uncached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"false\"" + } } builders { - name: "linux-exp-tsan-test" + name: "linux-asan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -690,10 +950,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -723,10 +987,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -735,7 +995,7 @@ buckets { } } builders { - name: "linux-intel-uhd630-perf" + name: "linux-dbg-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -746,10 +1006,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -769,20 +1033,16 @@ buckets { ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_and_test",' + ' "test_mode": "compile_only",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 18000 + execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -791,7 +1051,7 @@ buckets { } } builders { - name: "linux-nvidia-gtx1660-perf" + name: "linux-exp-asan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -802,10 +1062,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -828,17 +1092,13 @@ buckets { ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 18000 + execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -847,7 +1107,7 @@ buckets { } } builders { - name: "linux-test" + name: "linux-exp-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -858,10 +1118,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -891,10 +1155,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -903,7 +1163,7 @@ buckets { } } builders { - name: "linux-trace" + name: "linux-exp-tsan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -914,10 +1174,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -937,7 +1201,7 @@ buckets { ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "trace_tests",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 @@ -947,10 +1211,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -959,7 +1219,7 @@ buckets { } } builders { - name: "linux-tsan-test" + name: "linux-intel-uhd630-perf" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -970,10 +1230,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -996,17 +1260,13 @@ buckets { ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 10800 + execution_timeout_secs: 18000 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1015,9 +1275,10 @@ buckets { } } builders { - name: "mac-dbg-compile" + name: "linux-ir-test" swarming_host: "chromium-swarm.appspot.com" - dimensions: "os:Mac" + dimensions: "builderless:1" + dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1025,10 +1286,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1043,12 +1308,12 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "mac",' + ' "platform": "linux",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 @@ -1058,10 +1323,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1070,9 +1331,10 @@ buckets { } } builders { - name: "mac-exp-test" + name: "linux-nvidia-gtx1660-perf" swarming_host: "chromium-swarm.appspot.com" - dimensions: "os:Mac" + dimensions: "builderless:1" + dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1080,10 +1342,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1098,7 +1364,7 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "mac",' + ' "platform": "linux",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' @@ -1106,17 +1372,13 @@ buckets { ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' - execution_timeout_secs: 10800 + execution_timeout_secs: 18000 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1125,9 +1387,10 @@ buckets { } } builders { - name: "mac-test" + name: "linux-test" swarming_host: "chromium-swarm.appspot.com" - dimensions: "os:Mac" + dimensions: "builderless:1" + dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1135,10 +1398,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1153,7 +1420,7 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "mac",' + ' "platform": "linux",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' @@ -1168,10 +1435,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1180,10 +1443,10 @@ buckets { } } builders { - name: "win-asan-test" + name: "linux-trace" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1191,10 +1454,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1209,12 +1476,12 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "linux",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_and_test",' + ' "test_mode": "trace_tests",' ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 @@ -1224,10 +1491,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1236,10 +1499,10 @@ buckets { } } builders { - name: "win-dbg-compile" + name: "linux-tsan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1247,10 +1510,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1265,12 +1532,12 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "linux",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 @@ -1280,10 +1547,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1292,10 +1555,11 @@ buckets { } } builders { - name: "win-exp-test" + name: "mac-arm64-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.ci" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1303,10 +1567,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1321,7 +1589,7 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "mac",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' @@ -1336,10 +1604,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1348,10 +1612,11 @@ buckets { } } builders { - name: "win-msvc-compile" + name: "mac-dbg-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.ci" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1359,10 +1624,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1377,13 +1646,13 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "mac",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' ' "test_mode": "compile_only",' - ' "toolchain": "msvc"' + ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 build_numbers: YES @@ -1392,10 +1661,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1404,10 +1669,11 @@ buckets { } } builders { - name: "win-msvc-dbg-compile" + name: "mac-exp-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.ci" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1415,10 +1681,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1433,13 +1703,13 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "mac",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' - ' "toolchain": "msvc"' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 build_numbers: YES @@ -1448,10 +1718,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1460,10 +1726,11 @@ buckets { } } builders { - name: "win-msvc-x86-compile" + name: "mac-ir-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.ci" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1471,10 +1738,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1489,13 +1760,13 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "mac",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' - ' "toolchain": "msvc"' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 build_numbers: YES @@ -1504,10 +1775,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1516,10 +1783,11 @@ buckets { } } builders { - name: "win-msvc-x86-dbg-compile" + name: "mac-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Windows" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.ci" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -1527,10 +1795,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1545,13 +1817,13 @@ buckets { ' "gardener_rotations": [' ' "angle"' ' ],' - ' "platform": "win",' + ' "platform": "mac",' ' "recipe": "angle",' ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' - ' "toolchain": "msvc"' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 build_numbers: YES @@ -1560,10 +1832,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1572,7 +1840,7 @@ buckets { } } builders { - name: "win-test" + name: "win-asan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1583,10 +1851,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1616,10 +1888,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1628,7 +1896,7 @@ buckets { } } builders { - name: "win-trace" + name: "win-dbg-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1639,10 +1907,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1662,7 +1934,7 @@ buckets { ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "trace_tests",' + ' "test_mode": "compile_only",' ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 @@ -1672,10 +1944,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1684,7 +1952,7 @@ buckets { } } builders { - name: "win-x86-dbg-compile" + name: "win-exp-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1695,10 +1963,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1718,7 +1990,7 @@ buckets { ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_only",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' execution_timeout_secs: 10800 @@ -1728,10 +2000,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1740,7 +2008,7 @@ buckets { } } builders { - name: "win-x86-test" + name: "win-ir-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1751,10 +2019,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1784,10 +2056,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1796,7 +2064,7 @@ buckets { } } builders { - name: "win10-intel-uhd630-perf" + name: "win-msvc-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1807,10 +2075,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1830,20 +2102,16 @@ buckets { ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_and_test",' - ' "toolchain": "clang"' + ' "test_mode": "compile_only",' + ' "toolchain": "msvc"' '}' - execution_timeout_secs: 18000 + execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1852,7 +2120,7 @@ buckets { } } builders { - name: "win10-nvidia-gtx1660-perf" + name: "win-msvc-dbg-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1863,10 +2131,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1886,20 +2158,16 @@ buckets { ' "sheriff_rotations": [' ' "angle"' ' ],' - ' "test_mode": "compile_and_test",' - ' "toolchain": "clang"' + ' "test_mode": "compile_only",' + ' "toolchain": "msvc"' '}' - execution_timeout_secs: 18000 + execution_timeout_secs: 10800 build_numbers: YES service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1908,7 +2176,7 @@ buckets { } } builders { - name: "winuwp-compile" + name: "win-msvc-x86-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1919,10 +2187,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -1952,10 +2224,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -1964,7 +2232,7 @@ buckets { } } builders { - name: "winuwp-dbg-compile" + name: "win-msvc-x86-dbg-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Windows" @@ -1975,10 +2243,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-trusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2008,8 +2280,60 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + builders { + name: "win-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { @@ -2019,38 +2343,11 @@ buckets { service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" } } - } - shadow: "ci.shadow" -} -buckets { - name: "ci.shadow" - acls { - group: "all" - } - constraints { - pools: "luci.angle.ci" - service_accounts: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" - } - dynamic_builder_template {} -} -buckets { - name: "try" - acls { - group: "all" - } - acls { - role: SCHEDULER - group: "project-angle-tryjob-access" - } - acls { - role: SCHEDULER - group: "service-account-cq" - } - swarming { builders { - name: "android-arm-compile" + name: "win-trace" swarming_host: "chromium-swarm.appspot.com" - dimensions: "os:Ubuntu" + dimensions: "builderless:1" + dimensions: "os:Windows" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2058,10 +2355,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2073,29 +2374,92 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "android",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' ' "recipe": "angle",' - ' "test_mode": "compile_only",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "trace_tests",' ' "toolchain": "clang"' '}' + execution_timeout_secs: 10800 build_numbers: YES - service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "chromium_swarming.expose_merge_script_failures" value: 100 } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + builders { + name: "win-x86-dbg-compile" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_only",' + ' "toolchain": "clang"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { enable: true } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } } builders { - name: "android-arm-dbg-compile" + name: "win-x86-test" swarming_host: "chromium-swarm.appspot.com" - dimensions: "os:Ubuntu" + dimensions: "builderless:1" + dimensions: "os:Windows" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2103,10 +2467,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2118,29 +2486,803 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "android",' - ' "recipe": "angle",' - ' "test_mode": "compile_only",' - ' "toolchain": "clang"' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + builders { + name: "win10-intel-uhd630-perf" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + execution_timeout_secs: 18000 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + builders { + name: "win10-nvidia-gtx1660-perf" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + execution_timeout_secs: 18000 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + builders { + name: "winuwp-compile" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_only",' + ' "toolchain": "msvc"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + builders { + name: "winuwp-dbg-compile" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-trusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "gardener_rotations": [' + ' "angle"' + ' ],' + ' "platform": "win",' + ' "recipe": "angle",' + ' "sheriff_rotations": [' + ' "angle"' + ' ],' + ' "test_mode": "compile_only",' + ' "toolchain": "msvc"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + shadow_builder_adjustments { + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + } + } + shadow: "ci.shadow" +} +buckets { + name: "ci.shadow" + constraints { + pools: "luci.angle.ci" + pools: "luci.chromium.gpu.ci" + service_accounts: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + dynamic_builder_template {} +} +buckets { + name: "try" + swarming { + builders { + name: "android-arm-compile" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_only",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm-dbg-compile" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_only",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm64-dbg-compile" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_only",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm64-exp-pixel10-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm64-exp-s24-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm64-exp-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm64-ir-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "android-arm64-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "os:Ubuntu" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "android",' + ' "recipe": "angle",' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + resultdb { + enable: true + } + } + builders { + name: "angle-cq-linux-x64-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "os:Ubuntu-22.04" + dimensions: "pool:luci.chromium.gpu.try" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/chromium_tests_builder_config": {' + ' "builder_config": {' + ' "additional_exclusions": [' + ' "infra/config/generated/builders/try/angle-cq-linux-x64-rel/gn-args.json"' + ' ],' + ' "builder_db": {' + ' "entries": [' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "COMPILE_AND_TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' }' + ' }' + ' },' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' },' + ' "parent": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "run_tests_serially": true' + ' }' + ' }' + ' ]' + ' },' + ' "builder_ids": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' }' + ' ],' + ' "builder_ids_in_scope_for_testing": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' }' + ' ]' + ' }' + ' },' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "experiments": [],' + ' "metrics_project": "chromium-reclient-metrics",' + ' "project": "rbe-chromium-untrusted",' + ' "remote_jobs": 250' + ' },' + ' "builder_group": "angle",' + ' "recipe": "angle_v2/angle_v2_trybot"' '}' build_numbers: YES service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "chromium_swarming.expose_merge_script_failures" + key: "chromium.use_per_builder_build_dir_name" value: 100 } experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { enable: true - } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://(chrome|content)/test:telemetry_gpu_integration_test[^/]*/.+)" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)|(ninja://[^/]*headless_shell_wpt/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + description_html: "Tests release ANGLE on Linux/x64 on multiple hardware configs. Blocks CL submission.
This builder mirrors the following CI builders:

Builder owner: chrome-gpu-infra@google.com

NOTE: This builder only runs 4 max concurrent builds.

" + contact_team_email: "chrome-gpu-infra@google.com" + custom_metric_definitions { + name: "/chrome/infra/browser/builds/cached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"true\"" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_retry_shard_count" + predicates: "has(build.output.properties.ran_tests_retry_shard)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_without_patch_count" + predicates: "has(build.output.properties.ran_tests_without_patch)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/uncached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"false\"" + } + max_concurrent_builds: 4 } builders { - name: "android-arm64-dbg-compile" + name: "angle-try-linux-x64-sws-rel" swarming_host: "chromium-swarm.appspot.com" - dimensions: "os:Ubuntu" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "os:Ubuntu-22.04" + dimensions: "pool:luci.chromium.gpu.try" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2148,43 +3290,162 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' - ' },' - ' "$recipe_engine/resultdb/test_presentation": {' - ' "column_keys": [' - ' "v.gpu"' + ' "$build/chromium_tests_builder_config": {' + ' "builder_config": {' + ' "additional_exclusions": [' + ' "infra/config/generated/builders/try/angle-try-linux-x64-sws-rel/gn-args.json"' + ' ],' + ' "builder_db": {' + ' "entries": [' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "COMPILE_AND_TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' }' + ' }' + ' },' + ' {' + ' "builder_id": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' },' + ' "builder_spec": {' + ' "builder_group": "angle",' + ' "execution_mode": "TEST",' + ' "legacy_chromium_config": {' + ' "build_config": "Release",' + ' "config": "angle_v2_clang",' + ' "target_arch": "intel",' + ' "target_bits": 64,' + ' "target_platform": "linux"' + ' },' + ' "legacy_gclient_config": {' + ' "config": "angle_v2"' + ' },' + ' "parent": {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' },' + ' "run_tests_serially": true' + ' }' + ' }' + ' ]' + ' },' + ' "builder_ids": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-builder-rel",' + ' "project": "angle"' + ' }' + ' ],' + ' "builder_ids_in_scope_for_testing": [' + ' {' + ' "bucket": "ci",' + ' "builder": "angle-linux-x64-sws-rel",' + ' "project": "angle"' + ' }' + ' ]' + ' }' + ' },' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' ' ],' - ' "grouping_keys": [' - ' "status",' - ' "v.test_suite"' - ' ]' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "experiments": [],' + ' "metrics_project": "chromium-reclient-metrics",' + ' "project": "rbe-chromium-untrusted",' + ' "remote_jobs": 250' ' },' ' "builder_group": "angle",' - ' "platform": "android",' - ' "recipe": "angle",' - ' "test_mode": "compile_only",' - ' "toolchain": "clang"' + ' "recipe": "angle_v2/angle_v2_trybot"' '}' build_numbers: YES service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "chromium_swarming.expose_merge_script_failures" + key: "chromium.use_per_builder_build_dir_name" value: 100 } experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { enable: true - } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://(chrome|content)/test:telemetry_gpu_integration_test[^/]*/.+)" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)|(ninja://[^/]*headless_shell_wpt/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + description_html: "Tests release ANGLE on Linux/x64 with SwiftShader. Manual only.
This builder mirrors the following CI builders:

Builder owner: chrome-gpu-infra@google.com

NOTE: This builder only runs 1 max concurrent builds.

" + contact_team_email: "chrome-gpu-infra@google.com" + custom_metric_definitions { + name: "/chrome/infra/browser/builds/cached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"true\"" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_retry_shard_count" + predicates: "has(build.output.properties.ran_tests_retry_shard)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/ran_tests_without_patch_count" + predicates: "has(build.output.properties.ran_tests_without_patch)" + } + custom_metric_definitions { + name: "/chrome/infra/browser/builds/uncached_count" + predicates: "has(build.output.properties.is_cached)" + predicates: "string(build.output.properties.is_cached) == \"false\"" + } + max_concurrent_builds: 1 } builders { - name: "android-arm64-exp-s22-test" + name: "linux-asan-test" swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" @@ -2193,10 +3454,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2208,7 +3473,7 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "android",' + ' "platform": "linux",' ' "recipe": "angle",' ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' @@ -2219,17 +3484,14 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "android-arm64-exp-test" + name: "linux-dbg-compile" swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" @@ -2238,10 +3500,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2253,9 +3519,9 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "android",' + ' "platform": "linux",' ' "recipe": "angle",' - ' "test_mode": "compile_and_test",' + ' "test_mode": "compile_only",' ' "toolchain": "clang"' '}' build_numbers: YES @@ -2264,17 +3530,14 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "android-arm64-test" + name: "linux-exp-asan-test" swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" dimensions: "os:Ubuntu" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" @@ -2283,10 +3546,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2298,7 +3565,7 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "android",' + ' "platform": "linux",' ' "recipe": "angle",' ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' @@ -2309,16 +3576,12 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-asan-test" + name: "linux-exp-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -2329,10 +3592,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2355,16 +3622,12 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-dbg-compile" + name: "linux-exp-tsan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -2375,10 +3638,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2392,7 +3659,7 @@ buckets { ' "builder_group": "angle",' ' "platform": "linux",' ' "recipe": "angle",' - ' "test_mode": "compile_only",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' build_numbers: YES @@ -2401,16 +3668,12 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-exp-asan-test" + name: "linux-ir-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -2421,10 +3684,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2447,16 +3714,12 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-exp-test" + name: "linux-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -2467,10 +3730,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2493,16 +3760,12 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-exp-tsan-test" + name: "linux-trace" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -2513,10 +3776,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2530,7 +3797,7 @@ buckets { ' "builder_group": "angle",' ' "platform": "linux",' ' "recipe": "angle",' - ' "test_mode": "compile_and_test",' + ' "test_mode": "trace_tests",' ' "toolchain": "clang"' '}' build_numbers: YES @@ -2539,16 +3806,12 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-test" + name: "linux-tsan-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "os:Ubuntu" @@ -2559,10 +3822,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2585,19 +3852,16 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } } builders { - name: "linux-trace" + name: "mac-arm64-test" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Ubuntu" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.try" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2605,10 +3869,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2620,9 +3888,9 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "linux",' + ' "platform": "mac",' ' "recipe": "angle",' - ' "test_mode": "trace_tests",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' build_numbers: YES @@ -2631,19 +3899,18 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } + description_html: "

NOTE: This builder only runs 5 max concurrent builds.

" + max_concurrent_builds: 5 } builders { - name: "linux-tsan-test" + name: "mac-dbg-compile" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "os:Ubuntu" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.try" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2651,10 +3918,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2666,9 +3937,9 @@ buckets { ' ]' ' },' ' "builder_group": "angle",' - ' "platform": "linux",' + ' "platform": "mac",' ' "recipe": "angle",' - ' "test_mode": "compile_and_test",' + ' "test_mode": "compile_only",' ' "toolchain": "clang"' '}' build_numbers: YES @@ -2677,18 +3948,18 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } + description_html: "

NOTE: This builder only runs 5 max concurrent builds.

" + max_concurrent_builds: 5 } builders { - name: "mac-dbg-compile" + name: "mac-exp-test" swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.try" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2696,10 +3967,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2713,7 +3988,7 @@ buckets { ' "builder_group": "angle",' ' "platform": "mac",' ' "recipe": "angle",' - ' "test_mode": "compile_only",' + ' "test_mode": "compile_and_test",' ' "toolchain": "clang"' '}' build_numbers: YES @@ -2722,18 +3997,18 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } + description_html: "

NOTE: This builder only runs 1 max concurrent builds.

" + max_concurrent_builds: 1 } builders { - name: "mac-exp-test" + name: "mac-ir-test" swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.try" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2741,10 +4016,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2767,18 +4046,18 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } + description_html: "

NOTE: This builder only runs 1 max concurrent builds.

" + max_concurrent_builds: 1 } builders { name: "mac-test" swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" dimensions: "os:Mac" + dimensions: "pool:luci.chromium.gpu.try" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/main" @@ -2786,10 +4065,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2812,13 +4095,11 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } + description_html: "

NOTE: This builder only runs 5 max concurrent builds.

" + max_concurrent_builds: 5 } builders { name: "presubmit" @@ -2850,10 +4131,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -2870,10 +4147,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2896,10 +4177,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -2916,10 +4193,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2942,10 +4223,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -2962,10 +4239,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -2988,8 +4269,50 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } + resultdb { + enable: true + } + } + builders { + name: "win-ir-test" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Windows" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [' + ' "v.gpu"' + ' ],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "angle",' + ' "platform": "win",' + ' "recipe": "angle",' + ' "test_mode": "compile_and_test",' + ' "toolchain": "clang"' + '}' + build_numbers: YES + service_account: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { - key: "luci.recipes.use_python3" + key: "chromium_swarming.expose_merge_script_failures" value: 100 } resultdb { @@ -3008,10 +4331,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3034,10 +4361,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3054,10 +4377,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3080,10 +4407,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3100,10 +4423,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3126,10 +4453,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3146,10 +4469,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3172,10 +4499,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3192,10 +4515,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3218,10 +4545,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3238,10 +4561,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3264,10 +4591,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3284,10 +4607,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3310,10 +4637,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3330,10 +4653,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3356,10 +4683,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3376,10 +4699,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3402,10 +4729,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3422,10 +4745,14 @@ buckets { } properties: '{' - ' "$build/reclient": {' - ' "instance": "rbe-chromium-untrusted",' - ' "metrics_project": "chromium-reclient-metrics",' - ' "scandeps_server": true' + ' "$build/siso": {' + ' "configs": [' + ' "builder"' + ' ],' + ' "enable_cloud_monitoring": true,' + ' "enable_cloud_profiler": true,' + ' "enable_cloud_trace": true,' + ' "project": "rbe-chromium-untrusted"' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [' @@ -3448,10 +4775,6 @@ buckets { key: "chromium_swarming.expose_merge_script_failures" value: 100 } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } resultdb { enable: true } @@ -3461,11 +4784,9 @@ buckets { } buckets { name: "try.shadow" - acls { - group: "all" - } constraints { pools: "luci.angle.try" + pools: "luci.chromium.gpu.try" service_accounts: "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com" } dynamic_builder_template {} diff --git a/infra/config/generated/luci-logdog.cfg b/infra/config/generated/luci/luci-logdog.cfg similarity index 100% rename from infra/config/generated/luci-logdog.cfg rename to infra/config/generated/luci/luci-logdog.cfg diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg similarity index 83% rename from infra/config/generated/luci-milo.cfg rename to infra/config/generated/luci/luci-milo.cfg index e2c5176be90..4459b367337 100644 --- a/infra/config/generated/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg @@ -26,9 +26,14 @@ consoles { short_name: "dbg" } builders { - name: "buildbucket/luci.angle.ci/android-arm64-exp-s22-test" + name: "buildbucket/luci.angle.ci/android-arm64-exp-pixel10-test" category: "test|android|arm64" - short_name: "s22" + short_name: "p10" + } + builders { + name: "buildbucket/luci.angle.ci/android-arm64-exp-s24-test" + category: "test|android|arm64" + short_name: "s24" } builders { name: "buildbucket/luci.angle.ci/android-arm64-exp-test" @@ -45,11 +50,6 @@ consoles { category: "test|linux|x64" short_name: "asan" } - builders { - name: "buildbucket/luci.angle.ci/linux-exp-test" - category: "test|linux|x64" - short_name: "exp" - } builders { name: "buildbucket/luci.angle.ci/linux-tsan-test" category: "test|linux|x64" @@ -70,6 +70,11 @@ consoles { category: "compile|mac|x64" short_name: "dbg" } + builders { + name: "buildbucket/luci.angle.ci/mac-arm64-test" + category: "test|mac|arm64" + short_name: "rel" + } builders { name: "buildbucket/luci.angle.ci/mac-exp-test" category: "test|mac|x64" @@ -184,17 +189,47 @@ consoles { consoles { id: "exp" name: "ANGLE Experimental CI Builders" + builders { + name: "buildbucket/luci.angle.ci/angle-linux-x64-builder-rel" + } + builders { + name: "buildbucket/luci.angle.ci/angle-linux-x64-sws-rel" + } + builders { + name: "buildbucket/luci.angle.ci/android-arm64-ir-test" + } builders { name: "buildbucket/luci.angle.ci/linux-exp-asan-test" } + builders { + name: "buildbucket/luci.angle.ci/linux-exp-test" + } builders { name: "buildbucket/luci.angle.ci/linux-exp-tsan-test" } + builders { + name: "buildbucket/luci.angle.ci/linux-ir-test" + } + builders { + name: "buildbucket/luci.angle.ci/mac-ir-test" + } + builders { + name: "buildbucket/luci.angle.ci/win-ir-test" + } builder_view_only: true } consoles { id: "try" name: "ANGLE Try Builders" + builders { + name: "buildbucket/luci.angle.try/presubmit" + } + builders { + name: "buildbucket/luci.angle.try/angle-cq-linux-x64-rel" + } + builders { + name: "buildbucket/luci.angle.try/angle-try-linux-x64-sws-rel" + } builders { name: "buildbucket/luci.angle.try/android-arm-compile" } @@ -205,11 +240,17 @@ consoles { name: "buildbucket/luci.angle.try/android-arm64-dbg-compile" } builders { - name: "buildbucket/luci.angle.try/android-arm64-exp-s22-test" + name: "buildbucket/luci.angle.try/android-arm64-exp-pixel10-test" + } + builders { + name: "buildbucket/luci.angle.try/android-arm64-exp-s24-test" } builders { name: "buildbucket/luci.angle.try/android-arm64-exp-test" } + builders { + name: "buildbucket/luci.angle.try/android-arm64-ir-test" + } builders { name: "buildbucket/luci.angle.try/android-arm64-test" } @@ -231,15 +272,24 @@ consoles { builders { name: "buildbucket/luci.angle.try/linux-dbg-compile" } + builders { + name: "buildbucket/luci.angle.try/linux-ir-test" + } builders { name: "buildbucket/luci.angle.try/linux-test" } builders { name: "buildbucket/luci.angle.try/mac-dbg-compile" } + builders { + name: "buildbucket/luci.angle.try/mac-arm64-test" + } builders { name: "buildbucket/luci.angle.try/mac-exp-test" } + builders { + name: "buildbucket/luci.angle.try/mac-ir-test" + } builders { name: "buildbucket/luci.angle.try/mac-test" } @@ -264,6 +314,9 @@ consoles { builders { name: "buildbucket/luci.angle.try/win-msvc-x86-dbg-compile" } + builders { + name: "buildbucket/luci.angle.try/win-ir-test" + } builders { name: "buildbucket/luci.angle.try/win-test" } @@ -285,9 +338,6 @@ consoles { builders { name: "buildbucket/luci.angle.try/win-trace" } - builders { - name: "buildbucket/luci.angle.try/presubmit" - } builder_view_only: true } logo_url: "https://storage.googleapis.com/chrome-infra/OpenGL%20ES_RGB_June16.svg" diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg similarity index 82% rename from infra/config/generated/luci-scheduler.cfg rename to infra/config/generated/luci/luci-scheduler.cfg index 53e8ac8fa26..507ad2aa1e4 100644 --- a/infra/config/generated/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg @@ -7,7 +7,6 @@ job { id: "android-arm-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -21,7 +20,6 @@ job { job { id: "android-arm-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -35,7 +33,6 @@ job { job { id: "android-arm64-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -47,9 +44,8 @@ job { } } job { - id: "android-arm64-exp-s22-test" + id: "android-arm64-exp-pixel10-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -57,13 +53,25 @@ job { buildbucket { server: "cr-buildbucket.appspot.com" bucket: "ci" - builder: "android-arm64-exp-s22-test" + builder: "android-arm64-exp-pixel10-test" + } +} +job { + id: "android-arm64-exp-s24-test" + realm: "ci" + triggering_policy { + kind: LOGARITHMIC_BATCHING + log_base: 2 + } + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "android-arm64-exp-s24-test" } } job { id: "android-arm64-exp-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -74,10 +82,22 @@ job { builder: "android-arm64-exp-test" } } +job { + id: "android-arm64-ir-test" + realm: "ci" + triggering_policy { + kind: LOGARITHMIC_BATCHING + log_base: 2 + } + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "android-arm64-ir-test" + } +} job { id: "android-arm64-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -91,7 +111,6 @@ job { job { id: "android-pixel4-perf" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -105,7 +124,6 @@ job { job { id: "android-pixel6-perf" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -116,10 +134,28 @@ job { builder: "android-pixel6-perf" } } +job { + id: "angle-linux-x64-builder-rel" + realm: "ci" + schedule: "triggered" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "angle-linux-x64-builder-rel" + } +} +job { + id: "angle-linux-x64-sws-rel" + realm: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "angle-linux-x64-sws-rel" + } +} job { id: "linux-asan-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -133,7 +169,6 @@ job { job { id: "linux-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -147,7 +182,6 @@ job { job { id: "linux-exp-asan-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -161,7 +195,6 @@ job { job { id: "linux-exp-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -175,7 +208,6 @@ job { job { id: "linux-exp-tsan-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -189,7 +221,6 @@ job { job { id: "linux-intel-uhd630-perf" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -200,10 +231,22 @@ job { builder: "linux-intel-uhd630-perf" } } +job { + id: "linux-ir-test" + realm: "ci" + triggering_policy { + kind: LOGARITHMIC_BATCHING + log_base: 2 + } + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "linux-ir-test" + } +} job { id: "linux-nvidia-gtx1660-perf" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -217,7 +260,6 @@ job { job { id: "linux-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -231,7 +273,6 @@ job { job { id: "linux-trace" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -245,7 +286,6 @@ job { job { id: "linux-tsan-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -256,10 +296,22 @@ job { builder: "linux-tsan-test" } } +job { + id: "mac-arm64-test" + realm: "ci" + triggering_policy { + kind: LOGARITHMIC_BATCHING + log_base: 2 + } + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "mac-arm64-test" + } +} job { id: "mac-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -273,7 +325,6 @@ job { job { id: "mac-exp-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -284,10 +335,22 @@ job { builder: "mac-exp-test" } } +job { + id: "mac-ir-test" + realm: "ci" + triggering_policy { + kind: LOGARITHMIC_BATCHING + log_base: 2 + } + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "mac-ir-test" + } +} job { id: "mac-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -301,7 +364,6 @@ job { job { id: "win-asan-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -315,7 +377,6 @@ job { job { id: "win-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -329,7 +390,6 @@ job { job { id: "win-exp-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -340,10 +400,22 @@ job { builder: "win-exp-test" } } +job { + id: "win-ir-test" + realm: "ci" + triggering_policy { + kind: LOGARITHMIC_BATCHING + log_base: 2 + } + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "win-ir-test" + } +} job { id: "win-msvc-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -357,7 +429,6 @@ job { job { id: "win-msvc-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -371,7 +442,6 @@ job { job { id: "win-msvc-x86-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -385,7 +455,6 @@ job { job { id: "win-msvc-x86-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -399,7 +468,6 @@ job { job { id: "win-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -413,7 +481,6 @@ job { job { id: "win-trace" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -427,7 +494,6 @@ job { job { id: "win-x86-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -441,7 +507,6 @@ job { job { id: "win-x86-test" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -455,7 +520,6 @@ job { job { id: "win10-intel-uhd630-perf" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -469,7 +533,6 @@ job { job { id: "win10-nvidia-gtx1660-perf" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -483,7 +546,6 @@ job { job { id: "winuwp-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -497,7 +559,6 @@ job { job { id: "winuwp-dbg-compile" realm: "ci" - acl_sets: "ci" triggering_policy { kind: LOGARITHMIC_BATCHING log_base: 2 @@ -512,31 +573,37 @@ trigger { id: "main-poller" realm: "ci" schedule: "with 10s interval" - acl_sets: "ci" triggers: "android-arm-compile" triggers: "android-arm-dbg-compile" triggers: "android-arm64-dbg-compile" - triggers: "android-arm64-exp-s22-test" + triggers: "android-arm64-exp-pixel10-test" + triggers: "android-arm64-exp-s24-test" triggers: "android-arm64-exp-test" + triggers: "android-arm64-ir-test" triggers: "android-arm64-test" triggers: "android-pixel4-perf" triggers: "android-pixel6-perf" + triggers: "angle-linux-x64-builder-rel" triggers: "linux-asan-test" triggers: "linux-dbg-compile" triggers: "linux-exp-asan-test" triggers: "linux-exp-test" triggers: "linux-exp-tsan-test" triggers: "linux-intel-uhd630-perf" + triggers: "linux-ir-test" triggers: "linux-nvidia-gtx1660-perf" triggers: "linux-test" triggers: "linux-trace" triggers: "linux-tsan-test" + triggers: "mac-arm64-test" triggers: "mac-dbg-compile" triggers: "mac-exp-test" + triggers: "mac-ir-test" triggers: "mac-test" triggers: "win-asan-test" triggers: "win-dbg-compile" triggers: "win-exp-test" + triggers: "win-ir-test" triggers: "win-msvc-compile" triggers: "win-msvc-dbg-compile" triggers: "win-msvc-x86-compile" @@ -554,13 +621,3 @@ trigger { refs: "regexp:refs/heads/main" } } -acl_sets { - name: "ci" - acls { - role: OWNER - granted_to: "group:project-angle-admins" - } - acls { - granted_to: "group:all" - } -} diff --git a/infra/config/generated/project.cfg b/infra/config/generated/luci/project.cfg similarity index 56% rename from infra/config/generated/project.cfg rename to infra/config/generated/luci/project.cfg index 0b67a0bb640..7fd12742f84 100644 --- a/infra/config/generated/project.cfg +++ b/infra/config/generated/luci/project.cfg @@ -7,9 +7,13 @@ name: "angle" access: "group:all" lucicfg { - version: "1.43.16" - package_dir: ".." - config_dir: "generated" + version: "1.46.2" + package_name: "@angle-project" + package_dir: "../.." + config_dir: "generated/luci" entry_point: "main.star" experiments: "crbug.com/1182002" + experiments: "crbug.com/1347252" + experiments: "crbug.com/1496969" + experiments: "crbug.com/421431364" } diff --git a/infra/config/generated/realms.cfg b/infra/config/generated/luci/realms.cfg similarity index 93% rename from infra/config/generated/realms.cfg rename to infra/config/generated/luci/realms.cfg index bce70c49dbd..4d39dd016bb 100644 --- a/infra/config/generated/realms.cfg +++ b/infra/config/generated/luci/realms.cfg @@ -69,6 +69,16 @@ realms { role: "role/buildbucket.triggerer" principals: "user:angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" } + bindings { + role: "role/scheduler.triggerer" + principals: "user:angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + conditions { + restrict { + attribute: "scheduler.job.name" + values: "angle-linux-x64-sws-rel" + } + } + } } realms { name: "ci.shadow" diff --git a/infra/config/gn_args.star b/infra/config/gn_args.star new file mode 100644 index 00000000000..8809ea65f6c --- /dev/null +++ b/infra/config/gn_args.star @@ -0,0 +1,94 @@ +# Copyright 2026 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""ANGLE GN arg definitions.""" + +load("@chromium-luci//gn_args.star", "gn_args") + +gn_args.config( + name = "capture", + args = { + "angle_with_capture_by_default": True, + }, +) + +gn_args.config( + name = "clang", + args = { + "is_clang": True, + }, +) + +gn_args.config( + name = "component", + args = { + "is_component_build": True, + }, +) + +gn_args.config( + name = "linux", + args = { + "target_os": "linux", + }, +) + +gn_args.config( + name = "linux_clang", + configs = [ + "clang", + "linux", + "siso", + ], +) + +gn_args.config( + name = "minimal_symbols", + args = { + "symbol_level": 1, + }, +) + +gn_args.config( + name = "opencl", + args = { + "angle_enable_cl": True, + }, +) + +gn_args.config( + name = "release", + args = { + "is_debug": False, + }, + configs = [ + "minimal_symbols", + ], +) + +gn_args.config( + name = "release_with_dchecks", + args = { + "dcheck_always_on": True, + }, + configs = [ + "release", + ], +) + +gn_args.config( + name = "siso", + args = { + "use_reclient": False, + "use_remoteexec": True, + "use_siso": True, + }, +) + +gn_args.config( + name = "x64", + args = { + "target_cpu": "x64", + }, +) diff --git a/infra/config/legacy_builders.star b/infra/config/legacy_builders.star new file mode 100644 index 00000000000..fa9d0d3a700 --- /dev/null +++ b/infra/config/legacy_builders.star @@ -0,0 +1,404 @@ +# Copyright 2026 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Legacy builder definitions that were originally in main.star + +Moved due to them causing issues while working on anglebug.com/475260235. Any +builders that will be kept after that migration should be grouped and moved +into appropriately named files. +""" + +# Fail build when merge script fails. +build_experiments = {"chromium_swarming.expose_merge_script_failures": 100} + +# The category for an os: a more generic grouping than specific OS versions that +# can be used for computing defaults +os_category = struct( + ANDROID = "Android", + LINUX = "Linux", + MAC = "Mac", + WINDOWS = "Windows", +) + +def os_enum(dimension, category, console_name): + return struct(dimension = dimension, category = category, console_name = console_name) + +os = struct( + ANDROID = os_enum("Ubuntu", os_category.ANDROID, "android"), + LINUX = os_enum("Ubuntu", os_category.LINUX, "linux"), + MAC = os_enum("Mac", os_category.MAC, "mac"), + WINDOWS = os_enum("Windows", os_category.WINDOWS, "win"), +) + +# Recipes + +_DEFAULT_BUILDERLESS_OS_CATEGORIES = [os_category.LINUX, os_category.WINDOWS, os_category.MAC] +_CHROMIUM_POOL_OS_CATEGORIES = [os_category.MAC] + +def get_os_from_name(name): + """Returns os enum given the name. + + Args: + name: A name to check against. + + Returns: + An os enum given the name. + """ + if name.startswith("android"): + return os.ANDROID + if name.startswith("linux"): + return os.LINUX + if name.startswith("win"): + return os.WINDOWS + if name.startswith("mac"): + return os.MAC + return os.MAC + +def get_gpu_type_from_builder_name(name): + return name.split("-")[1] + +# Adds both the CI and Try standalone builders. +def angle_builder(name, cpu): + """Adds a CI and Try standalone builder. + + Args: + name: string representing name of the builder. + cpu: string representing CPU archiecture of builder. + """ + config_os = get_os_from_name(name) + dimensions = {} + dimensions["os"] = config_os.dimension + + if config_os.category in _DEFAULT_BUILDERLESS_OS_CATEGORIES: + dimensions["builderless"] = "1" + + ci_dimensions = {} + try_dimensions = {} + ci_dimensions.update(dimensions) + try_dimensions.update(dimensions) + + # TODO(crbug.com/375244064): Make the Chromium pools the default everywhere + # once all pool capacity is merged. + migrated_to_chromium_pool = config_os.category in _CHROMIUM_POOL_OS_CATEGORIES + if migrated_to_chromium_pool: + ci_dimensions["pool"] = "luci.chromium.gpu.ci" + try_dimensions["pool"] = "luci.chromium.gpu.try" + + is_asan = "-asan" in name + is_tsan = "-tsan" in name + is_debug = "-dbg" in name + is_exp = "-exp" in name + is_ir = "-ir" in name + is_perf = name.endswith("-perf") + is_pixel10 = "pixel10" in name + is_s24 = "s24" in name + is_trace = name.endswith("-trace") + is_uwp = "winuwp" in name + is_msvc = is_uwp or "-msvc" in name + + location_filters = None + + test_mode = "" + category = "" + if name.endswith("-compile"): + test_mode = "compile_only" + category = "compile" + elif name.endswith("-test"): + test_mode = "compile_and_test" + category = "test" + elif is_trace: + test_mode = "trace_tests" + category = "trace" + + # Trace tests are only run on CQ if files in the capture folders change. + location_filters = [ + cq.location_filter(path_regexp = "DEPS"), + cq.location_filter(path_regexp = "src/libANGLE/capture/.+"), + cq.location_filter(path_regexp = "src/tests/angle_end2end_tests_expectations.txt"), + cq.location_filter(path_regexp = "src/tests/capture.+"), + cq.location_filter(path_regexp = "src/tests/egl_tests/.+"), + cq.location_filter(path_regexp = "src/tests/gl_tests/.+"), + ] + elif is_perf: + test_mode = "compile_and_test" + category = "perf" + else: + print("Test mode unknown for %s" % name) + + if is_msvc: + toolchain = "msvc" + else: + toolchain = "clang" + + if is_uwp: + os_toolchain_name = "win-uwp" + elif is_msvc: + os_toolchain_name = "win-msvc" + else: + os_toolchain_name = config_os.console_name + + if is_perf: + short_name = get_gpu_type_from_builder_name(name) + elif is_asan: + short_name = "asan" + if is_exp: + short_name = "asan-exp" + elif is_tsan: + short_name = "tsan" + if is_exp: + short_name = "tsan-exp" + elif is_debug: + short_name = "dbg" + elif is_exp: + short_name = "exp" + if is_s24: + # This is a little clunky, but we'd like this to be cleanly "s24" rather than "s24-exp" + short_name = "s24" + elif is_pixel10: + short_name = "p10" + elif is_ir: + short_name = "ir" + else: + short_name = "rel" + + properties = { + "$build/siso": { + "configs": ["builder"], + "enable_cloud_monitoring": True, + "enable_cloud_profiler": True, + "enable_cloud_trace": True, + "project": "rbe-chromium-untrusted", + }, + "builder_group": "angle", + "platform": config_os.console_name, + "test_mode": test_mode, + "toolchain": toolchain, + } + + ci_properties = { + "$build/siso": { + "configs": ["builder"], + "enable_cloud_monitoring": True, + "enable_cloud_profiler": True, + "enable_cloud_trace": True, + "project": "rbe-chromium-trusted", + }, + "builder_group": "angle", + "platform": config_os.console_name, + "test_mode": test_mode, + "toolchain": toolchain, + } + + # TODO(343503161): Remove sheriff_rotations after SoM is updated. + ci_properties["gardener_rotations"] = ["angle"] + ci_properties["sheriff_rotations"] = ["angle"] + + if is_perf: + timeout_hours = 5 + else: + timeout_hours = 3 + + luci.builder( + name = name, + bucket = "ci", + triggered_by = ["main-poller"], + executable = "recipe:angle", + experiments = build_experiments, + service_account = "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com", + shadow_service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", + properties = ci_properties, + dimensions = ci_dimensions, + build_numbers = True, + resultdb_settings = resultdb.settings(enable = True), + test_presentation = resultdb.test_presentation( + column_keys = ["v.gpu"], + grouping_keys = ["status", "v.test_suite"], + ), + triggering_policy = scheduler.policy( + kind = scheduler.LOGARITHMIC_BATCHING_KIND, + log_base = 2, + ), + execution_timeout = timeout_hours * time.hour, + ) + + active_experimental_builders = [ + "android-arm64-exp-test", + "android-arm64-exp-pixel10-test", + "android-arm64-exp-s24-test", + "mac-exp-test", # temporarily used for AMD Radeon Pro 555X + "win-exp-test", # temporarily used for Intel UHD770 + ] + + if (not is_exp and not is_ir) or (name in active_experimental_builders): + luci.console_view_entry( + console_view = "ci", + builder = "ci/" + name, + category = category + "|" + os_toolchain_name + "|" + cpu, + short_name = short_name, + ) + else: + luci.list_view_entry( + list_view = "exp", + builder = "ci/" + name, + ) + + # Do not include perf tests in "try". + if not is_perf: + luci.list_view_entry( + list_view = "try", + builder = "try/" + name, + ) + + max_concurrent_builds = None + + # Don't add experimental bots to CQ. + # IR bots are also experimental currently. + add_to_cq = (not is_exp and not is_ir) + if migrated_to_chromium_pool: + if add_to_cq: + max_concurrent_builds = 5 + else: + max_concurrent_builds = 1 + + luci.builder( + name = name, + bucket = "try", + executable = "recipe:angle", + experiments = build_experiments, + service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", + properties = properties, + dimensions = try_dimensions, + build_numbers = True, + resultdb_settings = resultdb.settings(enable = True), + test_presentation = resultdb.test_presentation( + column_keys = ["v.gpu"], + grouping_keys = ["status", "v.test_suite"], + ), + max_concurrent_builds = max_concurrent_builds, + ) + + # Don't add experimental bots to CQ. + if add_to_cq: + luci.cq_tryjob_verifier( + cq_group = "main", + builder = "angle:try/" + name, + location_filters = location_filters, + ) + +luci.builder( + name = "presubmit", + bucket = "try", + executable = "recipe:run_presubmit", + experiments = build_experiments, + service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", + build_numbers = True, + dimensions = { + "os": os.LINUX.dimension, + }, + properties = { + "repo_name": "angle", + "runhooks": True, + }, + resultdb_settings = resultdb.settings(enable = True), + test_presentation = resultdb.test_presentation( + column_keys = ["v.gpu"], + grouping_keys = ["status", "v.test_suite"], + ), +) + +# name, clang, debug, cpu, uwp, trace_tests +angle_builder("android-arm-compile", cpu = "arm") +angle_builder("android-arm-dbg-compile", cpu = "arm") +angle_builder("android-arm64-dbg-compile", cpu = "arm64") +angle_builder("android-arm64-exp-pixel10-test", cpu = "arm64") +angle_builder("android-arm64-exp-s24-test", cpu = "arm64") +angle_builder("android-arm64-exp-test", cpu = "arm64") +angle_builder("android-arm64-ir-test", cpu = "arm64") +angle_builder("android-arm64-test", cpu = "arm64") +angle_builder("linux-asan-test", cpu = "x64") +angle_builder("linux-exp-asan-test", cpu = "x64") +angle_builder("linux-exp-test", cpu = "x64") +angle_builder("linux-exp-tsan-test", cpu = "x64") +angle_builder("linux-tsan-test", cpu = "x64") +angle_builder("linux-dbg-compile", cpu = "x64") +angle_builder("linux-ir-test", cpu = "x64") +angle_builder("linux-test", cpu = "x64") +angle_builder("mac-dbg-compile", cpu = "x64") +angle_builder("mac-arm64-test", cpu = "arm64") +angle_builder("mac-exp-test", cpu = "x64") +angle_builder("mac-ir-test", cpu = "x64") +angle_builder("mac-test", cpu = "x64") +angle_builder("win-asan-test", cpu = "x64") +angle_builder("win-dbg-compile", cpu = "x64") +angle_builder("win-exp-test", cpu = "x64") +angle_builder("win-msvc-compile", cpu = "x64") +angle_builder("win-msvc-dbg-compile", cpu = "x64") +angle_builder("win-msvc-x86-compile", cpu = "x86") +angle_builder("win-msvc-x86-dbg-compile", cpu = "x86") +angle_builder("win-ir-test", cpu = "x64") +angle_builder("win-test", cpu = "x64") +angle_builder("win-x86-dbg-compile", cpu = "x86") +angle_builder("win-x86-test", cpu = "x86") +angle_builder("winuwp-compile", cpu = "x64") +angle_builder("winuwp-dbg-compile", cpu = "x64") + +angle_builder("linux-trace", cpu = "x64") +angle_builder("win-trace", cpu = "x64") + +angle_builder("android-pixel4-perf", cpu = "arm64") +angle_builder("android-pixel6-perf", cpu = "arm64") +angle_builder("linux-intel-uhd630-perf", cpu = "x64") +angle_builder("linux-nvidia-gtx1660-perf", cpu = "x64") +angle_builder("win10-intel-uhd630-perf", cpu = "x64") +angle_builder("win10-nvidia-gtx1660-perf", cpu = "x64") + +# CQ + +luci.cq( + status_host = "chromium-cq-status.appspot.com", + submit_max_burst = 4, + submit_burst_delay = 480 * time.second, +) + +luci.cq_group( + name = "main", + watch = cq.refset( + "https://chromium.googlesource.com/angle/angle", + refs = [r"refs/heads/main"], + ), + acls = [ + acl.entry( + acl.CQ_COMMITTER, + groups = "project-angle-submit-access", + ), + acl.entry( + acl.CQ_DRY_RUNNER, + groups = "project-angle-tryjob-access", + ), + ], + verifiers = [ + luci.cq_tryjob_verifier( + builder = "angle:try/presubmit", + disable_reuse = True, + ), + luci.cq_tryjob_verifier( + builder = "chromium:try/android-angle-chromium-try", + ), + luci.cq_tryjob_verifier( + builder = "chromium:try/fuchsia-angle-try", + ), + luci.cq_tryjob_verifier( + builder = "chromium:try/linux-angle-chromium-try", + ), + luci.cq_tryjob_verifier( + builder = "chromium:try/mac-angle-chromium-try", + ), + luci.cq_tryjob_verifier( + builder = "chromium:try/win-angle-chromium-x64-try", + ), + luci.cq_tryjob_verifier( + builder = "chromium:try/win-angle-chromium-x86-try", + ), + ], +) diff --git a/infra/config/main.star b/infra/config/main.star index 2af250570e4..9269fd93886 100755 --- a/infra/config/main.star +++ b/infra/config/main.star @@ -6,25 +6,40 @@ # # main.star: lucicfg configuration for ANGLE's standalone builders. -lucicfg.check_version(min = "1.31.3", message = "Update depot_tools") +""" +main.star: lucicfg configuration for Angle's standalone builders. +""" + +load("@chromium-luci//builders.star", "os") +load("@chromium-luci//chromium_luci.star", "chromium_luci") # Use LUCI Scheduler BBv2 names and add Scheduler realms configs. lucicfg.enable_experiment("crbug.com/1182002") -# Fail build when merge script fails. -build_experiments = {"chromium_swarming.expose_merge_script_failures": 100} - lucicfg.config( - fail_on_warnings = True, - lint_checks = [ - "default", - "-module-docstring", - "-function-docstring", + config_dir = "generated", + tracked_files = [ + "builders/*/*/*", + "builders/*/*/*/*", + "builders/gn_args_locations.json", + "luci/commit-queue.cfg", + "luci/cr-buildbucket.cfg", + "luci/luci-logdog.cfg", + "luci/luci-milo.cfg", + "luci/luci-notify.cfg", + "luci/luci-scheduler.cfg", + "luci/project.cfg", + "luci/realms.cfg", + # TODO(crbug.com/475260235): Remove project.pyl once all builders are + # defined src-side. + "project.pyl", ], + fail_on_warnings = True, ) luci.project( name = "angle", + config_dir = "luci", buildbucket = "cr-buildbucket.appspot.com", logdog = "luci-logdog.appspot.com", milo = "luci-milo.appspot.com", @@ -79,6 +94,45 @@ luci.project( ], ) +chromium_luci.configure_project( + name = "angle", + is_main = True, + platforms = {}, +) + +chromium_luci.configure_builder_health_indicators( + unhealthy_period_days = 7, + pending_time_p50_min = 20, +) + +chromium_luci.configure_ci( + test_results_bq_dataset_name = "chromium", + resultdb_index_by_timestamp = True, +) + +chromium_luci.configure_try( + test_results_bq_dataset_name = "chromium", + resultdb_index_by_timestamp = True, +) + +chromium_luci.configure_builders( + os_dimension_overrides = { + os.LINUX_DEFAULT: os.LINUX_JAMMY, + os.MAC_DEFAULT: os.MAC_15, + os.WINDOWS_DEFAULT: os.WINDOWS_10, + }, +) + +chromium_luci.configure_per_builder_outputs( + root_dir = "builders", +) + +chromium_luci.configure_recipe_experiments( + # This can be removed once all builders use the chromium-luci wrappers for + # creating builders instead of directly calling luci.builder(). + require_builder_wrappers = False, +) + # Swarming permissions luci.realm(name = "pools/ci") luci.realm(name = "pools/try") @@ -116,264 +170,6 @@ luci.milo( luci.logdog(gs_bucket = "chromium-luci-logdog") -# The category for an os: a more generic grouping than specific OS versions that -# can be used for computing defaults -os_category = struct( - ANDROID = "Android", - LINUX = "Linux", - MAC = "Mac", - WINDOWS = "Windows", -) - -def os_enum(dimension, category, console_name): - return struct(dimension = dimension, category = category, console_name = console_name) - -os = struct( - ANDROID = os_enum("Ubuntu", os_category.ANDROID, "android"), - LINUX = os_enum("Ubuntu", os_category.LINUX, "linux"), - MAC = os_enum("Mac", os_category.MAC, "mac"), - WINDOWS = os_enum("Windows", os_category.WINDOWS, "win"), -) - -# Recipes - -_RECIPE_NAME_PREFIX = "recipe:" -_DEFAULT_BUILDERLESS_OS_CATEGORIES = [os_category.LINUX, os_category.WINDOWS] - -def _recipe_for_package(cipd_package): - def recipe(*, name, cipd_version = None, recipe = None, use_python3 = False): - # Force the caller to put the recipe prefix rather than adding it - # programatically to make the string greppable - if not name.startswith(_RECIPE_NAME_PREFIX): - fail("Recipe name {!r} does not start with {!r}" - .format(name, _RECIPE_NAME_PREFIX)) - if recipe == None: - recipe = name[len(_RECIPE_NAME_PREFIX):] - return luci.recipe( - name = name, - cipd_package = cipd_package, - cipd_version = cipd_version, - recipe = recipe, - use_bbagent = True, - use_python3 = use_python3, - ) - - return recipe - -build_recipe = _recipe_for_package( - "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build", -) - -build_recipe( - name = "recipe:angle", - use_python3 = True, -) - -build_recipe( - name = "recipe:run_presubmit", - use_python3 = True, -) - -def get_os_from_name(name): - if name.startswith("android"): - return os.ANDROID - if name.startswith("linux"): - return os.LINUX - if name.startswith("win"): - return os.WINDOWS - if name.startswith("mac"): - return os.MAC - return os.MAC - -def get_gpu_type_from_builder_name(name): - return name.split("-")[1] - -# Adds both the CI and Try standalone builders. -def angle_builder(name, cpu): - config_os = get_os_from_name(name) - dimensions = {} - dimensions["os"] = config_os.dimension - - if config_os.category in _DEFAULT_BUILDERLESS_OS_CATEGORIES: - dimensions["builderless"] = "1" - - is_asan = "-asan" in name - is_tsan = "-tsan" in name - is_debug = "-dbg" in name - is_exp = "-exp" in name - is_perf = name.endswith("-perf") - is_s22 = "s22" in name - is_trace = name.endswith("-trace") - is_uwp = "winuwp" in name - is_msvc = is_uwp or "-msvc" in name - - location_filters = None - - if name.endswith("-compile"): - test_mode = "compile_only" - category = "compile" - elif name.endswith("-test"): - test_mode = "compile_and_test" - category = "test" - elif is_trace: - test_mode = "trace_tests" - category = "trace" - - # Trace tests are only run on CQ if files in the capture folders change. - location_filters = [ - cq.location_filter(path_regexp = "DEPS"), - cq.location_filter(path_regexp = "src/libANGLE/capture/.+"), - cq.location_filter(path_regexp = "src/tests/angle_end2end_tests_expectations.txt"), - cq.location_filter(path_regexp = "src/tests/capture.+"), - cq.location_filter(path_regexp = "src/tests/egl_tests/.+"), - cq.location_filter(path_regexp = "src/tests/gl_tests/.+"), - ] - elif is_perf: - test_mode = "compile_and_test" - category = "perf" - else: - print("Test mode unknown for %s" % name) - - if is_msvc: - toolchain = "msvc" - else: - toolchain = "clang" - - if is_uwp: - os_toolchain_name = "win-uwp" - elif is_msvc: - os_toolchain_name = "win-msvc" - else: - os_toolchain_name = config_os.console_name - - if is_perf: - short_name = get_gpu_type_from_builder_name(name) - elif is_asan: - short_name = "asan" - if is_exp: - short_name = "asan-exp" - elif is_tsan: - short_name = "tsan" - if is_exp: - short_name = "tsan-exp" - elif is_debug: - short_name = "dbg" - elif is_exp: - short_name = "exp" - if is_s22: - # This is a little clunky, but we'd like this to be cleanly "s22" rather than "s22-exp" - short_name = "s22" - else: - short_name = "rel" - - properties = { - "builder_group": "angle", - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": True, - }, - "platform": config_os.console_name, - "toolchain": toolchain, - "test_mode": test_mode, - } - - ci_properties = { - "builder_group": "angle", - "$build/reclient": { - "instance": "rbe-chromium-trusted", - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": True, - }, - "platform": config_os.console_name, - "toolchain": toolchain, - "test_mode": test_mode, - } - - # TODO(343503161): Remove sheriff_rotations after SoM is updated. - ci_properties["gardener_rotations"] = ["angle"] - ci_properties["sheriff_rotations"] = ["angle"] - - if is_perf: - timeout_hours = 5 - else: - timeout_hours = 3 - - luci.builder( - name = name, - bucket = "ci", - triggered_by = ["main-poller"], - executable = "recipe:angle", - experiments = build_experiments, - service_account = "angle-ci-builder@chops-service-accounts.iam.gserviceaccount.com", - shadow_service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", - properties = ci_properties, - dimensions = dimensions, - build_numbers = True, - resultdb_settings = resultdb.settings(enable = True), - test_presentation = resultdb.test_presentation( - column_keys = ["v.gpu"], - grouping_keys = ["status", "v.test_suite"], - ), - triggering_policy = scheduler.policy( - kind = scheduler.LOGARITHMIC_BATCHING_KIND, - log_base = 2, - ), - execution_timeout = timeout_hours * time.hour, - ) - - active_experimental_builders = [ - "android-arm64-exp-test", - "android-arm64-exp-s22-test", - "linux-exp-test", - "mac-exp-test", - "win-exp-test", - ] - - if (not is_exp) or (name in active_experimental_builders): - luci.console_view_entry( - console_view = "ci", - builder = "ci/" + name, - category = category + "|" + os_toolchain_name + "|" + cpu, - short_name = short_name, - ) - else: - luci.list_view_entry( - list_view = "exp", - builder = "ci/" + name, - ) - - # Do not include perf tests in "try". - if not is_perf: - luci.list_view_entry( - list_view = "try", - builder = "try/" + name, - ) - - luci.builder( - name = name, - bucket = "try", - executable = "recipe:angle", - experiments = build_experiments, - service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", - properties = properties, - dimensions = dimensions, - build_numbers = True, - resultdb_settings = resultdb.settings(enable = True), - test_presentation = resultdb.test_presentation( - column_keys = ["v.gpu"], - grouping_keys = ["status", "v.test_suite"], - ), - ) - - # Don't add experimental bots to CQ. - if not is_exp: - luci.cq_tryjob_verifier( - cq_group = "main", - builder = "angle:try/" + name, - location_filters = location_filters, - ) - luci.bucket( name = "ci", acls = [ @@ -404,7 +200,7 @@ luci.bucket( name = "ci.shadow", shadows = "ci", constraints = luci.bucket_constraints( - pools = ["luci.angle.ci"], + pools = ["luci.angle.ci", "luci.chromium.gpu.ci"], ), bindings = [ luci.binding( @@ -439,7 +235,7 @@ luci.bucket( name = "try.shadow", shadows = "try", constraints = luci.bucket_constraints( - pools = ["luci.angle.try"], + pools = ["luci.angle.try", "luci.chromium.gpu.try"], service_accounts = [ "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", ], @@ -474,27 +270,6 @@ luci.bucket( dynamic = True, ) -luci.builder( - name = "presubmit", - bucket = "try", - executable = "recipe:run_presubmit", - experiments = build_experiments, - service_account = "angle-try-builder@chops-service-accounts.iam.gserviceaccount.com", - build_numbers = True, - dimensions = { - "os": os.LINUX.dimension, - }, - properties = { - "repo_name": "angle", - "runhooks": True, - }, - resultdb_settings = resultdb.settings(enable = True), - test_presentation = resultdb.test_presentation( - column_keys = ["v.gpu"], - grouping_keys = ["status", "v.test_suite"], - ), -) - luci.gitiles_poller( name = "main-poller", bucket = "ci", @@ -505,46 +280,6 @@ luci.gitiles_poller( schedule = "with 10s interval", ) -# name, clang, debug, cpu, uwp, trace_tests -angle_builder("android-arm-compile", cpu = "arm") -angle_builder("android-arm-dbg-compile", cpu = "arm") -angle_builder("android-arm64-dbg-compile", cpu = "arm64") -angle_builder("android-arm64-exp-s22-test", cpu = "arm64") -angle_builder("android-arm64-exp-test", cpu = "arm64") -angle_builder("android-arm64-test", cpu = "arm64") -angle_builder("linux-asan-test", cpu = "x64") -angle_builder("linux-exp-asan-test", cpu = "x64") -angle_builder("linux-exp-test", cpu = "x64") -angle_builder("linux-exp-tsan-test", cpu = "x64") -angle_builder("linux-tsan-test", cpu = "x64") -angle_builder("linux-dbg-compile", cpu = "x64") -angle_builder("linux-test", cpu = "x64") -angle_builder("mac-dbg-compile", cpu = "x64") -angle_builder("mac-exp-test", cpu = "x64") -angle_builder("mac-test", cpu = "x64") -angle_builder("win-asan-test", cpu = "x64") -angle_builder("win-dbg-compile", cpu = "x64") -angle_builder("win-exp-test", cpu = "x64") -angle_builder("win-msvc-compile", cpu = "x64") -angle_builder("win-msvc-dbg-compile", cpu = "x64") -angle_builder("win-msvc-x86-compile", cpu = "x86") -angle_builder("win-msvc-x86-dbg-compile", cpu = "x86") -angle_builder("win-test", cpu = "x64") -angle_builder("win-x86-dbg-compile", cpu = "x86") -angle_builder("win-x86-test", cpu = "x86") -angle_builder("winuwp-compile", cpu = "x64") -angle_builder("winuwp-dbg-compile", cpu = "x64") - -angle_builder("linux-trace", cpu = "x64") -angle_builder("win-trace", cpu = "x64") - -angle_builder("android-pixel4-perf", cpu = "arm64") -angle_builder("android-pixel6-perf", cpu = "arm64") -angle_builder("linux-intel-uhd630-perf", cpu = "x64") -angle_builder("linux-nvidia-gtx1660-perf", cpu = "x64") -angle_builder("win10-intel-uhd630-perf", cpu = "x64") -angle_builder("win10-nvidia-gtx1660-perf", cpu = "x64") - # Views luci.console_view( @@ -568,52 +303,11 @@ luci.list_view_entry( builder = "try/presubmit", ) -# CQ +# Run other non-builder setup. +exec("//gn_args.star") +exec("//recipes.star") -luci.cq( - status_host = "chromium-cq-status.appspot.com", - submit_max_burst = 4, - submit_burst_delay = 480 * time.second, -) - -luci.cq_group( - name = "main", - watch = cq.refset( - "https://chromium.googlesource.com/angle/angle", - refs = [r"refs/heads/main"], - ), - acls = [ - acl.entry( - acl.CQ_COMMITTER, - groups = "project-angle-submit-access", - ), - acl.entry( - acl.CQ_DRY_RUNNER, - groups = "project-angle-tryjob-access", - ), - ], - verifiers = [ - luci.cq_tryjob_verifier( - builder = "angle:try/presubmit", - disable_reuse = True, - ), - luci.cq_tryjob_verifier( - builder = "chromium:try/android-angle-chromium-try", - ), - luci.cq_tryjob_verifier( - builder = "chromium:try/fuchsia-angle-try", - ), - luci.cq_tryjob_verifier( - builder = "chromium:try/linux-angle-chromium-try", - ), - luci.cq_tryjob_verifier( - builder = "chromium:try/mac-angle-chromium-try", - ), - luci.cq_tryjob_verifier( - builder = "chromium:try/win-angle-chromium-x64-try", - ), - luci.cq_tryjob_verifier( - builder = "chromium:try/win-angle-chromium-x86-try", - ), - ], -) +# Handle any other builders defined in other files. +exec("//angle_v2_ci.star") +exec("//angle_v2_try.star") +exec("//legacy_builders.star") diff --git a/infra/config/recipes.star b/infra/config/recipes.star new file mode 100644 index 00000000000..e45996255d8 --- /dev/null +++ b/infra/config/recipes.star @@ -0,0 +1,96 @@ +# Copyright 2026 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Recipe definitions for recipes used by ANGLE builders.""" + +load("@chromium-luci//bootstrap.star", "register_recipe_bootstrappability") +load("@chromium-luci//recipe_experiments.star", "register_recipe_experiments") + +_RECIPE_NAME_PREFIX = "recipe:" + +def _recipe_for_package(cipd_package): + def recipe( + *, + name, + cipd_version = None, + recipe = None, + bootstrappable = False, + experiments = None): + """Declare a recipe for the given package. + + A wrapper around luci.recipe with a fixed cipd_package and some + chromium-specific functionality. See + https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/lucicfg/doc/README.md#luci.recipe + for more information. + + Args: + name: The name to use to refer to the executable in builder + definitions. Must start with "recipe:". See luci.recipe for more + information. + cipd_version: See luci.recipe. + recipe: See luci.recipe. + bootstrappable: Whether or not the recipe supports the chromium + bootstrapper. A recipe supports the bootstrapper if the following + conditions are met: + * chromium_bootstrap.update_gclient_config is called to update the + gclient config that is used for bot_update. This will be true if + calling chromium_checkout.ensure_checkout or + chromium_tests.prepare_checkout. + * If the recipe does analysis to reduce compilation/testing, it + skips analysis and performs a full build if + chromium_bootstrap.skip_analysis_reasons is non-empty. This will + be true if calling chromium_tests.determine_compilation_targets. + In addition to a True or False value, POLYMORPHIC can be + specified. This value will cause the builder's executable to be + changed to the bootstrapper in properties-optional, polymorphic + mode, which will by default not bootstrap any properties. On a + per-run basis the $bootstrap/properties property can be set to + bootstrap properties for different builders. + experiments: Experiments to apply to a builder using the recipe. If + the builder specifies an experiment, the experiment value from the + recipe will be ignored. + """ + + # Force the caller to put the recipe prefix rather than adding it + # programatically to make the string greppable + if not name.startswith(_RECIPE_NAME_PREFIX): + fail("Recipe name {!r} does not start with {!r}" + .format(name, _RECIPE_NAME_PREFIX)) + if recipe == None: + recipe = name[len(_RECIPE_NAME_PREFIX):] + ret = luci.recipe( + name = name, + cipd_package = cipd_package, + cipd_version = cipd_version, + recipe = recipe, + use_bbagent = True, + ) + + register_recipe_bootstrappability(name, bootstrappable) + + register_recipe_experiments(name, experiments or {}) + + return ret + + return recipe + +build_recipe = _recipe_for_package( + "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build", +) + +build_recipe( + name = "recipe:angle", +) + +build_recipe( + name = "recipe:angle_v2/angle_v2", +) + +build_recipe( + name = "recipe:angle_v2/angle_v2_trybot", +) + +build_recipe( + name = "recipe:run_presubmit", +) diff --git a/infra/specs/angle.json b/infra/specs/angle.json index 127d078c7be..b41ab80b87b 100644 --- a/infra/specs/angle.json +++ b/infra/specs/angle.json @@ -1,6 +1,7 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "android-arm64-exp-pixel10": {}, "android-arm64-exp-pixel6": { "gtest_tests": [ { @@ -12,6 +13,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -39,6 +41,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -66,6 +69,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles31_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -92,6 +96,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -118,6 +123,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -145,6 +151,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles3_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -171,6 +178,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -197,6 +205,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -227,6 +236,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -256,6 +266,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -285,6 +296,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", @@ -314,6 +326,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", @@ -344,6 +357,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", @@ -374,6 +388,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", @@ -403,6 +418,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -420,6 +436,36 @@ "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "AP1A.240405.002", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, { "args": [ "--use-angle=vulkan", @@ -429,6 +475,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -455,6 +502,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -481,6 +529,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -508,6 +557,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -533,6 +583,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", @@ -559,6 +610,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_capture_tests", "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", @@ -585,6 +637,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -610,24 +663,26 @@ } ] }, - "android-arm64-exp-s22": { + "android-arm64-exp-s24": { "gtest_tests": [ { "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -642,18 +697,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -668,18 +725,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles31_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -693,18 +752,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -718,18 +779,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -744,18 +807,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles3_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -769,18 +834,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -794,18 +861,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -823,18 +892,20 @@ "--surface-width=64", "--deqp-base-seed=1", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -851,18 +922,20 @@ "--surface-width=64", "--deqp-base-seed=1", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -879,18 +952,20 @@ "--surface-height=64", "--surface-width=64", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -907,18 +982,20 @@ "--surface-width=113", "--surface-height=47", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -936,18 +1013,20 @@ "--surface-height=64", "--deqp-gl-config-name=rgba8888d24s8", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -965,18 +1044,20 @@ "--surface-height=-1", "--deqp-gl-config-name=rgba8888d24s8", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -993,18 +1074,20 @@ "--surface-width=64", "--deqp-base-seed=1", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1017,19 +1100,51 @@ { "args": [ "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "AP3A.240905.015.A2", + "device_os_type": "user", + "device_type": "s5e9945", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1043,18 +1158,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1068,18 +1185,20 @@ "args": [ "--use-angle=vulkan", "-v", - "--shard-timeout=500" + "--shard-timeout=500", + "--do-not-store-tombstones" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1094,18 +1213,20 @@ "--gtest_filter=*Vulkan*:-*Vulkan_SwiftShader*", "--shard-timeout=300", "-v", - "--render-test-output-dir=${ISOLATED_OUTDIR}" + "--render-test-output-dir=${ISOLATED_OUTDIR}", + "--do-not-store-tombstones" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1118,18 +1239,20 @@ }, { "args": [ - "-v" + "-v", + "--do-not-store-tombstones" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1146,11 +1269,13 @@ "--test-machine-name", "${buildername}", "-v", - "--git-revision=${got_angle_revision}" + "--git-revision=${got_angle_revision}", + "--do-not-store-tombstones" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -1161,9 +1286,9 @@ "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "UP1A.231005.007", + "device_os": "AP3A.240905.015.A2", "device_os_type": "user", - "device_type": "s5e9925", + "device_type": "s5e9945", "os": "Android", "pool": "chromium.tests.gpu" }, @@ -1175,7 +1300,7 @@ } ] }, - "android-arm64-pixel4": { + "android-arm64-ir-pixel4": { "gtest_tests": [ { "args": [ @@ -1186,6 +1311,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_gles_tests", "swarming": { "containment_type": "AUTO", @@ -1211,6 +1337,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1237,6 +1364,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_gles_tests", "swarming": { "containment_type": "AUTO", @@ -1263,6 +1391,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1289,6 +1418,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles31_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1314,6 +1444,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1339,6 +1470,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1365,6 +1497,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles3_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1390,6 +1523,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_gles_tests", "swarming": { "containment_type": "AUTO", @@ -1416,6 +1550,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1441,6 +1576,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1470,6 +1606,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1498,6 +1635,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1526,6 +1664,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", @@ -1554,6 +1693,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", @@ -1583,6 +1723,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", @@ -1612,6 +1753,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", @@ -1640,6 +1782,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1656,6 +1799,35 @@ "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, { "args": [ "--use-angle=vulkan", @@ -1665,6 +1837,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1690,6 +1863,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1715,6 +1889,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1741,6 +1916,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -1769,6 +1945,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_gles1_conformance_tests", "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", @@ -1792,6 +1969,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", @@ -1817,6 +1995,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_capture_tests", "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", @@ -1844,6 +2023,7 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_perftests", "name": "angle_perftests", "swarming": { "containment_type": "AUTO", @@ -1870,6 +2050,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -1906,6 +2087,7 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", @@ -1936,6 +2118,7 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -1954,105 +2137,7 @@ } ] }, - "android-arm64-pixel4-perf": { - "isolated_scripts": [ - { - "args": [ - "--log=debug", - "--samples-per-test=3", - "--trials-per-sample=3", - "--show-test-stdout", - "--trial-time=10" - ], - "merge": { - "script": "//scripts/process_angle_perf_results.py" - }, - "name": "angle_perftests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "device_os": "RP1A.201105.002", - "device_os_type": "userdebug", - "device_type": "flame", - "os": "Android", - "pool": "chromium.tests.gpu", - "temp_band": "<30" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 30 - }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" - }, - { - "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-gl=native", - "--trace-tests", - "--trial-time=10" - ], - "merge": { - "script": "//scripts/process_angle_perf_results.py" - }, - "name": "angle_trace_perf_native_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "device_os": "RP1A.201105.002", - "device_os_type": "userdebug", - "device_type": "flame", - "os": "Android", - "pool": "chromium.tests.gpu", - "temp_band": "<30" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 30 - }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - }, - { - "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-angle=vulkan", - "--trace-tests", - "--trial-time=10" - ], - "merge": { - "script": "//scripts/process_angle_perf_results.py" - }, - "name": "angle_trace_perf_vulkan_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "device_os": "RP1A.201105.002", - "device_os_type": "userdebug", - "device_type": "flame", - "os": "Android", - "pool": "chromium.tests.gpu", - "temp_band": "<30" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 30 - }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, - "android-arm64-pixel6": { + "android-arm64-ir-pixel6": { "gtest_tests": [ { "args": [ @@ -2063,6 +2148,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2089,6 +2175,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2115,6 +2202,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles31_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2140,6 +2228,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2165,6 +2254,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2191,6 +2281,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests", "name": "angle_deqp_gles3_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2216,6 +2307,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2241,6 +2333,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2270,6 +2363,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2298,6 +2392,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2326,6 +2421,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", @@ -2354,6 +2450,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", @@ -2383,6 +2480,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", @@ -2412,6 +2510,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", @@ -2440,6 +2539,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2456,6 +2556,35 @@ "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, { "args": [ "--use-angle=vulkan", @@ -2465,6 +2594,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2490,6 +2620,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2515,6 +2646,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -2541,6 +2673,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -2565,6 +2698,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", @@ -2590,6 +2724,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_capture_tests", "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", @@ -2615,6 +2750,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -2639,151 +2775,110 @@ } ] }, - "android-arm64-pixel6-perf": { - "isolated_scripts": [ + "android-arm64-pixel4": { + "gtest_tests": [ { "args": [ - "--log=debug", - "--samples-per-test=3", - "--trials-per-sample=3", - "--show-test-stdout", - "--trial-time=10", - "--custom-throttling-temp=38" + "--use-angle=gles", + "-v", + "--shard-timeout=500" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gles_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "TP1A.220624.021", + "device_os": "RP1A.201105.002", "device_os_type": "userdebug", - "device_type": "oriole", + "device_type": "flame", "os": "Android", - "pool": "chromium.tests.gpu", - "temp_band": "<30" + "pool": "chromium.tests.gpu" }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 30 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-gl=native", - "--trace-tests", - "--trial-time=10", - "--custom-throttling-temp=38" + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "TP1A.220624.021", + "device_os": "RP1A.201105.002", "device_os_type": "userdebug", - "device_type": "oriole", + "device_type": "flame", "os": "Android", - "pool": "chromium.tests.gpu", - "temp_band": "<30" + "pool": "chromium.tests.gpu" }, - "hard_timeout": 7200, - "io_timeout": 300, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 30 + "shards": 4 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-angle=vulkan", - "--trace-tests", - "--trial-time=10", - "--custom-throttling-temp=38" + "--use-angle=gles", + "-v", + "--shard-timeout=500" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gles_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "device_os": "TP1A.220624.021", + "device_os": "RP1A.201105.002", "device_os_type": "userdebug", - "device_type": "oriole", + "device_type": "flame", "os": "Android", - "pool": "chromium.tests.gpu", - "temp_band": "<30" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 30 - }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, - "linux-amd": {}, - "linux-exp-intel": {}, - "linux-exp-nvidia": { - "gtest_tests": [ - { - "args": [ - "--use-angle=gl", - "--max-processes=1", - "--no-xvfb" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_egl_gl_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, - "test": "angle_deqp_egl_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--no-xvfb" + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, "test": "angle_deqp_gles2_tests", "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", @@ -2792,65 +2887,77 @@ { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests", + "name": "angle_deqp_gles31_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "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/", + "test": "angle_deqp_gles31_565_no_depth_no_stencil_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=webgpu", - "--no-xvfb" + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_webgpu_tests", + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "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/", + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--no-xvfb" + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_gl_tests", + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 20 }, "test": "angle_deqp_gles31_tests", "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", @@ -2859,249 +2966,312 @@ { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_multisample_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests", + "name": "angle_deqp_gles3_565_no_depth_no_stencil_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_multisample_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "test": "angle_deqp_gles3_565_no_depth_no_stencil_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=gles", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_rotate180_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gles_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 }, - "test": "angle_deqp_gles31_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_rotate270_tests", + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_rotate90_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 }, - "test": "angle_deqp_gles31_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--no-xvfb" + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_gl_tests", + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "--deqp-base-seed=1", + "--surface-height=64", + "--surface-width=64", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_multisample_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_multisample_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "--deqp-base-seed=2", + "--surface-width=113", + "--surface-height=47", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_vulkan_rotate180_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "--deqp-base-seed=3", + "--surface-width=-1", + "--surface-height=64", + "--deqp-gl-config-name=rgba8888d24s8", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_vulkan_rotate270_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "--deqp-base-seed=3", + "--surface-width=64", + "--surface-height=-1", + "--deqp-gl-config-name=rgba8888d24s8", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_vulkan_rotate90_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--no-xvfb" + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, { @@ -3110,186 +3280,4885 @@ "--surface-height=64", "--surface-width=64", "--deqp-base-seed=1", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles2_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles31_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--deqp-base-seed=1", - "--surface-height=64", - "--surface-width=64", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", + "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_deqp_khr_noctx_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=vulkan", - "--deqp-base-seed=2", - "--surface-width=113", - "--surface-height=47", - "--no-xvfb" + "-v", + "--shard-timeout=500" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", + "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_deqp_khr_single_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--deqp-base-seed=3", - "--surface-width=-1", - "--surface-height=64", - "--deqp-gl-config-name=rgba8888d24s8", - "--no-xvfb" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--shard-timeout=180", + "-v", + "--render-test-output-dir=${ISOLATED_OUTDIR}" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--deqp-base-seed=3", - "--surface-width=64", - "--surface-height=-1", - "--deqp-gl-config-name=rgba8888d24s8", - "--no-xvfb" + "--test-timeout=300", + "--batch-size=10", + "--gtest_filter=*Vulkan*", + "--shard-timeout=600", + "-v" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1", - "--no-xvfb" + "-v" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles3_vulkan_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", - "os": "Ubuntu-22.04", + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true - }, + } + ], + "isolated_scripts": [ { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--log=debug" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "-v", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "android-arm64-pixel4-perf": { + "isolated_scripts": [ + { + "args": [ + "--log=debug", + "--samples-per-test=3", + "--trials-per-sample=3", + "--show-test-stdout", + "--trial-time=10" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu", + "temp_band": "<30" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 30 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-gl=native", + "--trace-tests", + "--trial-time=10" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu", + "temp_band": "<30" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 30 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-angle=vulkan", + "--trace-tests", + "--trial-time=10" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "RP1A.201105.002", + "device_os_type": "userdebug", + "device_type": "flame", + "os": "Android", + "pool": "chromium.tests.gpu", + "temp_band": "<30" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 30 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "android-arm64-pixel6": { + "gtest_tests": [ + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests", + "name": "angle_deqp_gles31_565_no_depth_no_stencil_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_565_no_depth_no_stencil_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_565_no_depth_no_stencil_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests", + "name": "angle_deqp_gles3_565_no_depth_no_stencil_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_565_no_depth_no_stencil_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_565_no_depth_no_stencil_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=1", + "--surface-height=64", + "--surface-width=64", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=2", + "--surface-width=113", + "--surface-height=47", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=-1", + "--surface-height=64", + "--deqp-gl-config-name=rgba8888d24s8", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=64", + "--surface-height=-1", + "--deqp-gl-config-name=rgba8888d24s8", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", + "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "-v", + "--shard-timeout=500" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", + "name": "angle_deqp_khr_single_gles32_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_single_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=*Vulkan*:-*Vulkan_SwiftShader*", + "--shard-timeout=300", + "-v", + "--render-test-output-dir=${ISOLATED_OUTDIR}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "-v" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "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 + } + ], + "isolated_scripts": [ + { + "args": [ + "--log=debug" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "-v", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + } + ] + }, + "android-arm64-pixel6-perf": { + "isolated_scripts": [ + { + "args": [ + "--log=debug", + "--samples-per-test=3", + "--trials-per-sample=3", + "--show-test-stdout", + "--trial-time=10", + "--custom-throttling-temp=38" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu", + "temp_band": "<30" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 30 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-gl=native", + "--trace-tests", + "--trial-time=10", + "--custom-throttling-temp=38" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu", + "temp_band": "<30" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 30 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-angle=vulkan", + "--trace-tests", + "--trial-time=10", + "--custom-throttling-temp=38" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "device_os": "TP1A.220624.021", + "device_os_type": "userdebug", + "device_type": "oriole", + "os": "Android", + "pool": "chromium.tests.gpu", + "temp_band": "<30" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 30 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "angle-linux-x64-sws-rel": { + "gtest_tests": [ + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "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=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "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=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=*Vulkan_SwiftShader*" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=*Vulkan_SwiftShader*" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + } + ], + "isolated_scripts": [ + { + "args": [ + "--test-machine-name", + "${buildername}", + "--swiftshader", + "--key-frame-limit=10", + "--xvfb", + "--flaky-retries=2", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + } + ] + }, + "linux-amd": {}, + "linux-exp-intel": {}, + "linux-exp-nvidia": {}, + "linux-exp-swiftshader": {}, + "linux-exp-swiftshader-asan": {}, + "linux-exp-swiftshader-tsan": {}, + "linux-intel": { + "gtest_tests": [ + { + "args": [ + "--use-angle=gl", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "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": [ + "--gtest_filter=-*Vulkan_SwiftShader*", + "--max-processes=1", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--test-timeout=300", + "--batch-size=10", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "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 + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + } + ], + "isolated_scripts": [ + { + "args": [ + "--log=debug" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "linux-intel-perf": { + "isolated_scripts": [ + { + "args": [ + "--log=debug", + "--samples-per-test=3", + "--trials-per-sample=3", + "--show-test-stdout" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-angle=vulkan", + "--trace-tests" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "linux-ir-amd": {}, + "linux-ir-intel": { + "gtest_tests": [ + { + "args": [ + "--use-angle=gl", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "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": [ + "--gtest_filter=-*Vulkan_SwiftShader*", + "--max-processes=1", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--test-timeout=300", + "--batch-size=10", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "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 + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + } + ], + "isolated_scripts": [ + { + "args": [ + "--log=debug" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "8086:9bc5-23.2.1", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "linux-ir-nvidia": { + "gtest_tests": [ + { + "args": [ + "--use-angle=gl", + "--max-processes=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=gl", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=webgpu", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_vulkan_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_vulkan_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_vulkan_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=gl", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_vulkan_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_vulkan_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_vulkan_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=1", + "--surface-height=64", + "--surface-width=64", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=2", + "--surface-width=113", + "--surface-height=47", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=-1", + "--surface-height=64", + "--deqp-gl-config-name=rgba8888d24s8", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=64", + "--surface-height=-1", + "--deqp-gl-config-name=rgba8888d24s8", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", + "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", + "name": "angle_deqp_khr_single_gles32_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_single_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=-*Vulkan_SwiftShader*", + "--max-processes=4", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--test-timeout=300", + "--batch-size=10", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + } + ], + "isolated_scripts": [ + { + "args": [ + "--log=debug" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "linux-ir-swiftshader": { + "gtest_tests": [ + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "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=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "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=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=*Vulkan_SwiftShader*" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=*Vulkan_SwiftShader*" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + } + ], + "isolated_scripts": [ + { + "args": [ + "--test-machine-name", + "${buildername}", + "--swiftshader", + "--key-frame-limit=10", + "--xvfb", + "--flaky-retries=2", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + } + ] + }, + "linux-nvidia": { + "gtest_tests": [ + { + "args": [ + "--use-angle=gl", + "--max-processes=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=gl", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=webgpu", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_vulkan_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_vulkan_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_vulkan_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=gl", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_vulkan_rotate180_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_vulkan_rotate270_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_vulkan_rotate90_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=1", + "--surface-height=64", + "--surface-width=64", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=2", + "--surface-width=113", + "--surface-height=47", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=-1", + "--surface-height=64", + "--deqp-gl-config-name=rgba8888d24s8", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=64", + "--surface-height=-1", + "--deqp-gl-config-name=rgba8888d24s8", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", + "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_noctx_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan", + "--no-xvfb" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", + "name": "angle_deqp_khr_single_gles32_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_single_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gtest_filter=-*Vulkan_SwiftShader*", + "--max-processes=4", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--test-timeout=300", + "--batch-size=10", + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_api", + "name": "angle_oclcts_api", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_api", + "test_id_prefix": "ninja://src/tests:angle_oclcts_api/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_basic", + "name": "angle_oclcts_basic", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_basic", + "test_id_prefix": "ninja://src/tests:angle_oclcts_basic/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_bruteforce", + "name": "angle_oclcts_bruteforce", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_bruteforce", + "test_id_prefix": "ninja://src/tests:angle_oclcts_bruteforce/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_buffers", + "name": "angle_oclcts_buffers", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_buffers", + "test_id_prefix": "ninja://src/tests:angle_oclcts_buffers/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_cl_copy_images", + "name": "angle_oclcts_cl_copy_images", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_cl_copy_images", + "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_copy_images/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_cl_fill_images", + "name": "angle_oclcts_cl_fill_images", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_cl_fill_images", + "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_fill_images/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_cl_get_info", + "name": "angle_oclcts_cl_get_info", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_cl_get_info", + "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_get_info/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_compiler", + "name": "angle_oclcts_compiler", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_compiler", + "test_id_prefix": "ninja://src/tests:angle_oclcts_compiler/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_events", + "name": "angle_oclcts_events", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_events", + "test_id_prefix": "ninja://src/tests:angle_oclcts_events/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_multiples", + "name": "angle_oclcts_multiples", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_multiples", + "test_id_prefix": "ninja://src/tests:angle_oclcts_multiples/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_non_uniform_work_group", + "name": "angle_oclcts_non_uniform_work_group", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_non_uniform_work_group", + "test_id_prefix": "ninja://src/tests:angle_oclcts_non_uniform_work_group/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_oclcts_profiling", + "name": "angle_oclcts_profiling", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_oclcts_profiling", + "test_id_prefix": "ninja://src/tests:angle_oclcts_profiling/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "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 + }, + { + "args": [ + "--no-xvfb" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + } + ], + "isolated_scripts": [ + { + "args": [ + "--log=debug" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + }, + { + "args": [ + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" + ], + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "linux-nvidia-perf": { + "isolated_scripts": [ + { + "args": [ + "--log=debug", + "--samples-per-test=3", + "--trials-per-sample=3", + "--show-test-stdout" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", "swarming": { "containment_type": "AUTO", "dimensions": { @@ -3297,21 +8166,57 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 }, - "test": "angle_deqp_khr_noctx_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", - "use_isolated_scripts_api": true + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, + { + "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-gl=native", + "--trace-tests" + ], + "merge": { + "script": "//scripts/process_angle_perf_results.py" + }, + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "gpu": "10de:2184-535.183.01", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" }, { "args": [ + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", "--use-angle=vulkan", - "--no-xvfb" + "--trace-tests" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { @@ -3319,1107 +8224,1328 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "linux-swiftshader": { + "gtest_tests": [ + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_noctx_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_single_gles32_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_single_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--max-processes=4", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--test-timeout=300", - "--batch-size=10", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_gles1_conformance_tests", + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_rotate180_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_gles1_conformance_tests", - "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_api", + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_rotate270_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_api", - "test_id_prefix": "ninja://src/tests:angle_oclcts_api/", + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_basic", + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_rotate90_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_basic", - "test_id_prefix": "ninja://src/tests:angle_oclcts_basic/", + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_bruteforce", + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_bruteforce", - "test_id_prefix": "ninja://src/tests:angle_oclcts_bruteforce/", + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_buffers", + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_rotate180_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_buffers", - "test_id_prefix": "ninja://src/tests:angle_oclcts_buffers/", + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_cl_copy_images", + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_rotate270_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_cl_copy_images", - "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_copy_images/", + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_cl_fill_images", + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_rotate90_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=swiftshader" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, - "test": "angle_oclcts_cl_fill_images", - "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_fill_images/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_cl_get_info", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_cl_get_info", - "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_get_info/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_compiler", + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_compiler", - "test_id_prefix": "ninja://src/tests:angle_oclcts_compiler/", + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_events", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_events", - "test_id_prefix": "ninja://src/tests:angle_oclcts_events/", + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_multiples", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_multiples", - "test_id_prefix": "ninja://src/tests:angle_oclcts_multiples/", + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--gtest_filter=*Vulkan_SwiftShader*" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_non_uniform_work_group", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_non_uniform_work_group", - "test_id_prefix": "ninja://src/tests:angle_oclcts_non_uniform_work_group/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--gtest_filter=*Vulkan_SwiftShader*" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_profiling", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_profiling", - "test_id_prefix": "ninja://src/tests:angle_oclcts_profiling/", + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", "use_isolated_scripts_api": true - }, + } + ], + "isolated_scripts": [ { "args": [ - "--no-xvfb" + "--test-machine-name", + "${buildername}", + "--swiftshader", + "--key-frame-limit=10", + "--xvfb", + "--flaky-retries=2", + "--git-revision=${got_angle_revision}" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_unittests", + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 }, - "test": "angle_unittests", - "test_id_prefix": "ninja://src/tests:angle_unittests/", - "use_isolated_scripts_api": true - }, + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + } + ] + }, + "linux-swiftshader-asan": { + "gtest_tests": [ { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true - } - ], - "isolated_scripts": [ + }, { "args": [ - "--log=debug" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_capture_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, - "test": "angle_capture_tests", - "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout" + "--use-angle=swiftshader" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_rotate180_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--test-machine-name", - "${buildername}", - "--git-revision=${got_angle_revision}" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_restricted_trace_gold_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}", - "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" - ], + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_rotate270_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_restricted_trace_gold_tests", - "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-gl=native", - "--trace-tests" + "--use-angle=swiftshader" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_rotate90_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-angle=vulkan", - "--trace-tests" + "--use-angle=swiftshader" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-535.183.01", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 14 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, - "linux-exp-swiftshader": {}, - "linux-exp-swiftshader-asan": {}, - "linux-exp-swiftshader-tsan": {}, - "linux-intel": { - "gtest_tests": [ + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "use_isolated_scripts_api": true + }, { "args": [ - "--use-angle=gl", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_rotate180_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "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/", + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--max-processes=4", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_rotate270_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--test-timeout=300", - "--batch-size=10", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_gles1_conformance_tests", + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_rotate90_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_gles1_conformance_tests", - "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_unittests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 11 }, - "test": "angle_unittests", - "test_id_prefix": "ninja://src/tests:angle_unittests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true - } - ], - "isolated_scripts": [ + }, { "args": [ - "--log=debug" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_capture_tests", + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_capture_tests", - "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--test-machine-name", - "${buildername}", - "--git-revision=${got_angle_revision}" + "--use-angle=swiftshader" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_restricted_trace_gold_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}", - "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" - ], + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_restricted_trace_gold_tests", - "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-gl=native", - "--trace-tests" + "--gtest_filter=*Vulkan_SwiftShader*" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 6 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-angle=vulkan", - "--trace-tests" + "--gtest_filter=*Vulkan_SwiftShader*" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true } ] }, - "linux-intel-perf": { - "isolated_scripts": [ + "linux-swiftshader-tsan": { + "gtest_tests": [ { "args": [ - "--log=debug", - "--samples-per-test=3", - "--trials-per-sample=3", - "--show-test-stdout" + "--use-angle=swiftshader", + "--batch-timeout=600" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-gl=native", - "--trace-tests" + "--use-angle=swiftshader" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "hard_timeout": 7200, - "io_timeout": 300, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 4 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-angle=vulkan", - "--trace-tests" + "--use-angle=swiftshader" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "8086:9bc5-23.2.1", + "cpu": "x86-64", + "gpu": "none", "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "hard_timeout": 7200, - "io_timeout": 300, + "hard_timeout": 900, + "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 11 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, - "linux-nvidia": { - "gtest_tests": [ + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, { "args": [ - "--use-angle=gl", - "--max-processes=1", - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_egl_gl_tests", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "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/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_egl_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "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/", + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--no-xvfb" + "--use-angle=swiftshader", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "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/", + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=swiftshader" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles2_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, + "hard_timeout": 900, + "io_timeout": 900, "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/", + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=webgpu", - "--no-xvfb" + "--gtest_filter=*Vulkan_SwiftShader*" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles2_webgpu_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--no-xvfb" + "--gtest_filter=*Vulkan_SwiftShader*" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles31_gl_tests", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "gpu": "none", + "os": "Ubuntu-22.04", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "hard_timeout": 900, + "io_timeout": 900, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", "use_isolated_scripts_api": true - }, + } + ] + }, + "mac-amd": { + "gtest_tests": [ { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=gl", + "--max-processes=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_multisample_vulkan_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_multisample_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=metal" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_rotate180_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_rotate270_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_rotate90_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=webgpu", + "--flaky-retries=2" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ "--use-angle=gl", - "--no-xvfb" + "--flaky-retries=2" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -4431,942 +9557,1025 @@ }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_multisample_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles3_multisample_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_vulkan_rotate180_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, - "test": "angle_deqp_gles3_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=vulkan", - "--no-xvfb" - ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_vulkan_rotate270_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "x86-64", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true - }, + } + ] + }, + "mac-arm64-apple": { + "gtest_tests": [ { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=gl", + "--max-processes=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_vulkan_rotate90_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=metal" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_vulkan_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1", - "--no-xvfb" + "--use-angle=gl" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles2_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1", - "--no-xvfb" + "--use-angle=metal" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles31_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--deqp-base-seed=1", - "--surface-height=64", - "--surface-width=64", - "--no-xvfb" + "--use-angle=webgpu" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--deqp-base-seed=2", - "--surface-width=113", - "--surface-height=47", - "--no-xvfb" + "--use-angle=gl" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--deqp-base-seed=3", - "--surface-width=-1", - "--surface-height=64", - "--deqp-gl-config-name=rgba8888d24s8", - "--no-xvfb" + "--use-angle=metal" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--deqp-base-seed=3", - "--surface-width=64", - "--surface-height=-1", - "--deqp-gl-config-name=rgba8888d24s8", - "--no-xvfb" + "--use-angle=metal" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", + "--use-angle=gl", "--surface-height=64", "--surface-width=64", - "--deqp-base-seed=1", - "--no-xvfb" + "--deqp-base-seed=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles3_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=metal", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_noctx_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=gl", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_noctx_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=vulkan", - "--no-xvfb" + "--use-angle=metal", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_single_gles32_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_single_gles32_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--max-processes=4", - "--no-xvfb" + "--use-angle=gl" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--test-timeout=300", - "--batch-size=10", - "--no-xvfb" + "--use-angle=metal" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_gles1_conformance_tests", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_gles1_conformance_tests", - "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_api", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_oclcts_api", - "test_id_prefix": "ninja://src/tests:angle_oclcts_api/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--test-timeout=300", + "--batch-size=10" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_basic", + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_basic", - "test_id_prefix": "ninja://src/tests:angle_oclcts_basic/", + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--no-xvfb" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_bruteforce", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_bruteforce", - "test_id_prefix": "ninja://src/tests:angle_oclcts_bruteforce/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true }, { - "args": [ - "--no-xvfb" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_buffers", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "cpu": "arm64", + "display_attached": "1", + "gpu": "apple:m2", + "hidpi": "1", + "mac_model": "Mac14,7", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_buffers", - "test_id_prefix": "ninja://src/tests:angle_oclcts_buffers/", + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", "use_isolated_scripts_api": true - }, + } + ] + }, + "mac-exp-amd": {}, + "mac-exp-intel": { + "gtest_tests": [ { "args": [ - "--no-xvfb" + "--use-angle=gl", + "--max-processes=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_cl_copy_images", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_cl_copy_images", - "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_copy_images/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=metal" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_cl_fill_images", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_cl_fill_images", - "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_fill_images/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_cl_get_info", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_cl_get_info", - "test_id_prefix": "ninja://src/tests:angle_oclcts_cl_get_info/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_compiler", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_compiler", - "test_id_prefix": "ninja://src/tests:angle_oclcts_compiler/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=webgpu", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_events", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_oclcts_events", - "test_id_prefix": "ninja://src/tests:angle_oclcts_events/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_multiples", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_oclcts_multiples", - "test_id_prefix": "ninja://src/tests:angle_oclcts_multiples/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_oclcts_non_uniform_work_group", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_oclcts_non_uniform_work_group", - "test_id_prefix": "ninja://src/tests:angle_oclcts_non_uniform_work_group/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--no-xvfb" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_oclcts_profiling", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_oclcts_profiling", - "test_id_prefix": "ninja://src/tests:angle_oclcts_profiling/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--no-xvfb" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-15.5" }, "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-intel": { + "gtest_tests": [ { "args": [ - "--no-xvfb" + "--use-angle=gl", + "--max-processes=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true - } - ], - "isolated_scripts": [ + }, { "args": [ - "--log=debug" + "--use-angle=metal" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_capture_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_capture_tests", - "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--test-machine-name", - "${buildername}", - "--git-revision=${got_angle_revision}" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_restricted_trace_gold_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}", - "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" - ], + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_restricted_trace_gold_tests", - "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-gl=native", - "--trace-tests" + "--use-angle=webgpu", + "--flaky-retries=2" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-angle=vulkan", - "--trace-tests" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, - "linux-nvidia-perf": { - "isolated_scripts": [ + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true + }, { "args": [ - "--log=debug", - "--samples-per-test=3", - "--trials-per-sample=3", - "--show-test-stdout" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 7200, - "io_timeout": 300, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 2 }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-gl=native", - "--trace-tests" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 7200, - "io_timeout": 300, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 2 }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true }, { - "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-angle=vulkan", - "--trace-tests" - ], "merge": { - "script": "//scripts/process_angle_perf_results.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "gpu": "10de:2184-440.100", - "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", - "pool": "chromium.tests.gpu" + "cpu": "x86-64", + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", + "use_isolated_scripts_api": true } ] }, - "linux-swiftshader": { + "mac-ir-amd": { "gtest_tests": [ { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--max-processes=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_egl_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_deqp_egl_tests", @@ -5375,482 +10584,477 @@ }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "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/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_multisample_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_multisample_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_rotate180_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=webgpu", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_rotate270_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_rotate90_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles31_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 2 }, - "test": "angle_deqp_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_multisample_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles3_multisample_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=swiftshader" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_rotate180_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:7340", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true - }, + } + ] + }, + "mac-ir-intel": { + "gtest_tests": [ { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--max-processes=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_rotate270_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_rotate90_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles2_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" + "--use-angle=webgpu", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles31_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_gles3_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_khr_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_khr_noctx_gles2_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_khr_noctx_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "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*" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "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 }, { - "args": [ - "--gtest_filter=*Vulkan_SwiftShader*" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", - "pool": "chromium.tests.gpu" + "display_attached": "1", + "gpu": "8086:3e9b", + "os": "Mac-14.5" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true } - ], - "isolated_scripts": [ + ] + }, + "mac-x64-amd-555x-test": { + "gtest_tests": [ { "args": [ - "--test-machine-name", - "${buildername}", - "--swiftshader", - "--xvfb", - "--flaky-retries=2", - "--git-revision=${got_angle_revision}" + "--use-angle=gl", + "--max-processes=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_restricted_trace_gold_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}", - "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" - ], + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_restricted_trace_gold_tests", - "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" - } - ] - }, - "linux-swiftshader-asan": { - "gtest_tests": [ + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", + "use_isolated_scripts_api": true + }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_egl_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_deqp_egl_tests", @@ -5859,24 +11063,25 @@ }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 + "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/", @@ -5884,1043 +11089,1065 @@ }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_rotate180_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=webgpu", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_rotate270_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles31_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=gl", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_rotate90_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles31_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--use-angle=metal", + "--flaky-retries=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles31_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_metal_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 14 + "shards": 2 }, - "test": "angle_deqp_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--flaky-retries=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_rotate180_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles3_rotate180_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=swiftshader" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_rotate270_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "1002:67ef", + "hidpi": "1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate270_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true - }, + } + ] + }, + "win10-x64-exp-intel": { + "gtest_tests": [ { "args": [ - "--use-angle=swiftshader" + "--use-angle=d3d11", + "--max-processes=2" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_rotate90_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_d3d11_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_rotate90_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--max-processes=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 + "shards": 5 }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" + "--test-timeout=300", + "--batch-size=10" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles2_tests", + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles31_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles3_tests", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", "use_isolated_scripts_api": true - }, + } + ], + "isolated_scripts": [ { "args": [ - "--use-angle=swiftshader" + "--log=debug" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_noctx_gles2_tests", + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_noctx_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", - "use_isolated_scripts_api": true + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" }, { "args": [ - "--gtest_filter=*Vulkan_SwiftShader*" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 + "shards": 2 }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", - "use_isolated_scripts_api": true + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" }, { "args": [ - "--gtest_filter=*Vulkan_SwiftShader*" + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", - "use_isolated_scripts_api": true - } - ] - }, - "linux-swiftshader-tsan": { - "gtest_tests": [ + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, { "args": [ - "--use-angle=swiftshader", - "--batch-timeout=600" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_egl_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_egl_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", - "use_isolated_scripts_api": true + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" }, { "args": [ - "--use-angle=swiftshader" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles2_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:4680-31.0.101.5333", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 4 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true - }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "win10-x64-exp-nvidia": {}, + "win10-x64-intel": { + "gtest_tests": [ { "args": [ - "--use-angle=swiftshader" + "--use-angle=d3d11" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_d3d11_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" + "--gtest_filter=-*Vulkan_SwiftShader*", + "--max-processes=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles2_tests", + "module_name": "//src/tests:angle_end2end_tests", + "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 }, - "test": "angle_deqp_khr_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", "use_isolated_scripts_api": true - }, - { - "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" + }, + { + "args": [ + "--test-timeout=300", + "--batch-size=10" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles31_tests", + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=swiftshader", - "--surface-height=64", - "--surface-width=64", - "--deqp-base-seed=1" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_gles3_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=swiftshader" + "--max-processes=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_khr_noctx_gles2_tests", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_khr_noctx_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", "use_isolated_scripts_api": true - }, + } + ], + "isolated_scripts": [ { "args": [ - "--gtest_filter=*Vulkan_SwiftShader*" + "--log=debug" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", - "use_isolated_scripts_api": true + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" }, { "args": [ - "--gtest_filter=*Vulkan_SwiftShader*" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", - "gpu": "none", - "os": "Ubuntu-22.04", + "display_attached": "1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "hard_timeout": 900, - "io_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", - "use_isolated_scripts_api": true - } - ] - }, - "mac-amd": { - "gtest_tests": [ + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" + }, { "args": [ - "--use-angle=gl", - "--max-processes=1" + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}", + "--flaky-retries=1" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_egl_gl_tests", + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 5 }, - "test": "angle_deqp_egl_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", - "use_isolated_scripts_api": true + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" }, { "args": [ - "--use-angle=metal" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_egl_metal_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_egl_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", - "use_isolated_scripts_api": true + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true - }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "win10-x64-intel-perf": { + "isolated_scripts": [ { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--log=debug", + "--samples-per-test=3", + "--trials-per-sample=3", + "--show-test-stdout" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles2_metal_tests", + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" }, { "args": [ - "--use-angle=webgpu", - "--flaky-retries=2" + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-gl=native", + "--trace-tests" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles2_webgpu_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "hard_timeout": 7200, + "io_timeout": 300, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--log=debug", + "--show-test-stdout", + "--samples-per-test=3", + "--trials-per-sample=3", + "--use-angle=vulkan", + "--trace-tests" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles3_gl_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, + "hard_timeout": 7200, + "io_timeout": 300, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 10 }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", - "use_isolated_scripts_api": true - }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "win10-x64-ir-intel": { + "gtest_tests": [ { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--use-angle=d3d11" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_metal_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_d3d11_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ "--gtest_filter=-*Vulkan_SwiftShader*", - "--flaky-retries=2" + "--max-processes=1" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:7340", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 10 }, "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:7340", - "hidpi": "1", - "os": "Mac-14.4.1", - "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" + "--test-timeout=300", + "--batch-size=10" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_egl_gl_tests", + "module_name": "//src/tests:angle_gles1_conformance_tests", + "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "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/", + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", "use_isolated_scripts_api": true }, { - "args": [ - "--use-angle=metal" - ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_egl_metal_tests", + "module_name": "//src/tests:angle_unittests", + "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "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/", + "test": "angle_unittests", + "test_id_prefix": "ninja://src/tests:angle_unittests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--max-processes=1" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_white_box_tests", + "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "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/", + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", "use_isolated_scripts_api": true - }, + } + ], + "isolated_scripts": [ { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--log=debug" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles2_metal_tests", + "module_name": "//src/tests:angle_capture_tests", + "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "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 + "test": "angle_capture_tests", + "test_id_prefix": "ninja://src/tests:angle_capture_tests/" }, { "args": [ - "--use-angle=webgpu", - "--flaky-retries=2" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles2_webgpu_tests", + "module_name": "//src/tests:angle_perftests", + "name": "angle_perftests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true + "test": "angle_perftests", + "test_id_prefix": "ninja://src/tests:angle_perftests/" }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}", + "--flaky-retries=1" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "angle_deqp_gles3_gl_tests", + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}", + "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" + ], "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", - "use_isolated_scripts_api": true + "test": "angle_restricted_trace_gold_tests", + "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" }, { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-gl=native", + "--trace-tests" ], "merge": { - "script": "//scripts/angle_deqp_test_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_deqp_gles3_metal_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "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 + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--flaky-retries=2" + "--log=debug", + "--smoke-test-mode", + "--show-test-stdout", + "--use-angle=vulkan", + "--trace-tests" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "args": [ + "--smoke-test-mode" + ], + "script": "//scripts/process_angle_perf_results.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_trace_perf_tests", + "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "8086:9bc5-31.0.101.2127", + "os": "Windows-10", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 3 }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", - "use_isolated_scripts_api": true - }, + "test": "angle_trace_perf_tests", + "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + } + ] + }, + "win10-x64-ir-nvidia": { + "gtest_tests": [ { + "args": [ + "--use-angle=d3d11" + ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_unittests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_d3d11_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.4.1", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "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/", + "test": "angle_deqp_egl_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", "use_isolated_scripts_api": true - } - ] - }, - "mac-exp-intel": { - "gtest_tests": [ + }, { "args": [ "--use-angle=gl", @@ -6929,14 +12156,15 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, @@ -6946,21 +12174,23 @@ }, { "args": [ - "--use-angle=metal" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_egl_metal_tests", + "module_name": "//src/tests:angle_deqp_egl_tests", + "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "angle_deqp_egl_tests", "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", @@ -6968,20 +12198,20 @@ }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--use-angle=d3d11" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_d3d11_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, @@ -6991,20 +12221,20 @@ }, { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--use-angle=gl" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_metal_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, @@ -7014,20 +12244,20 @@ }, { "args": [ - "--use-angle=webgpu", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_webgpu_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, @@ -7037,651 +12267,632 @@ }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--use-angle=webgpu" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_gl_tests", + "module_name": "//src/tests:angle_deqp_gles2_tests", + "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "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" + "--use-angle=gl" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_metal_tests", + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "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/", + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", + "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "test": "angle_deqp_gles31_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_multisample_tests/", "use_isolated_scripts_api": true }, { + "args": [ + "--use-angle=vulkan" + ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_unittests", + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", + "name": "angle_deqp_gles31_vulkan_rotate180_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-15.0" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "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/", + "test": "angle_deqp_gles31_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate180_tests/", "use_isolated_scripts_api": true - } - ] - }, - "mac-exp-nvidia": {}, - "mac-intel": { - "gtest_tests": [ + }, { "args": [ - "--use-angle=gl", - "--max-processes=1" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_egl_gl_tests", + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", + "name": "angle_deqp_gles31_vulkan_rotate270_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "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/", + "test": "angle_deqp_gles31_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate270_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=metal" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_egl_metal_tests", + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", + "name": "angle_deqp_gles31_vulkan_rotate90_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "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/", + "test": "angle_deqp_gles31_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_rotate90_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_gl_tests", + "module_name": "//src/tests:angle_deqp_gles31_tests", + "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "test": "angle_deqp_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--use-angle=d3d11" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_metal_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_d3d11_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=webgpu", - "--flaky-retries=2" + "--use-angle=gl" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_webgpu_tests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=gl", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_gl_tests", + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", + "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", + "test": "angle_deqp_gles3_multisample_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_multisample_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--use-angle=metal", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles3_metal_tests", + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", + "name": "angle_deqp_gles3_vulkan_rotate180_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "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/", + "test": "angle_deqp_gles3_rotate180_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate180_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", + "name": "angle_deqp_gles3_vulkan_rotate270_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "8086:3e9b", - "os": "Mac-14.5" + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "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/", + "test": "angle_deqp_gles3_rotate270_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate270_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": "8086:3e9b", - "os": "Mac-14.5" - }, - "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-nvidia": { - "gtest_tests": [ { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--flaky-retries=2" + "--use-angle=vulkan" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", + "name": "angle_deqp_gles3_vulkan_rotate90_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-11.7.9", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "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/", + "test": "angle_deqp_gles3_rotate90_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_rotate90_tests/", "use_isolated_scripts_api": true }, { + "args": [ + "--use-angle=vulkan" + ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_unittests", + "module_name": "//src/tests:angle_deqp_gles3_tests", + "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { - "cpu": "x86-64", "display_attached": "1", - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-11.7.9", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, - "test": "angle_unittests", - "test_id_prefix": "ninja://src/tests:angle_unittests/", + "test": "angle_deqp_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", "use_isolated_scripts_api": true - } - ] - }, - "win10-x64-exp-intel": { - "gtest_tests": [ + }, { "args": [ - "--use-angle=d3d11", - "--max-processes=2" + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_d3d11_tests", + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", + "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "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/", + "test": "angle_deqp_khr_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles2_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--max-processes=2" + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_end2end_tests", + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", + "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", + "test": "angle_deqp_khr_gles31_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles31_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--test-timeout=300", - "--batch-size=10" + "--use-angle=vulkan", + "--deqp-base-seed=1", + "--surface-height=64", + "--surface-width=64" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_gles1_conformance_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_gles1_conformance_tests", - "test_id_prefix": "ninja://src/tests:angle_gles1_conformance_tests/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true }, { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=2", + "--surface-width=113", + "--surface-height=47" + ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_unittests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "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/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true }, { + "args": [ + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=-1", + "--surface-height=64", + "--deqp-gl-config-name=rgba8888d24s8" + ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_white_box_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_white_box_tests", - "test_id_prefix": "ninja://src/tests:angle_white_box_tests/", + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", "use_isolated_scripts_api": true - } - ], - "isolated_scripts": [ + }, { "args": [ - "--log=debug" + "--use-angle=vulkan", + "--deqp-base-seed=3", + "--surface-width=64", + "--surface-height=-1", + "--deqp-gl-config-name=rgba8888d24s8" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_capture_tests", + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", + "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_capture_tests", - "test_id_prefix": "ninja://src/tests:angle_capture_tests/" + "test": "angle_deqp_khr_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles32_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout" + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_perftests", + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", + "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" + "test": "angle_deqp_khr_gles3_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--test-machine-name", - "${buildername}", - "--git-revision=${got_angle_revision}" + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" ], "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_restricted_trace_gold_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}", - "--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}" - ], + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_restricted_trace_gold_tests", - "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" - }, - { - "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-gl=native", - "--trace-tests" + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--use-angle=vulkan" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_trace_perf_native_tests", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", + "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" + "test": "angle_deqp_khr_noctx_gles2_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles2_tests/", + "use_isolated_scripts_api": true }, { "args": [ - "--log=debug", - "--smoke-test-mode", - "--show-test-stdout", - "--use-angle=vulkan", - "--trace-tests" + "--use-angle=vulkan" ], "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//scripts/process_angle_perf_results.py" + "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_trace_perf_vulkan_tests", + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", + "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:4680-31.0.101.5333", - "os": "Windows-10-19045.3930", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, - "win10-x64-exp-nvidia": {}, - "win10-x64-intel": { - "gtest_tests": [ + "test": "angle_deqp_khr_noctx_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_noctx_gles32_tests/", + "use_isolated_scripts_api": true + }, { "args": [ - "--use-angle=d3d11" + "--use-angle=vulkan" ], "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, - "name": "angle_deqp_gles2_d3d11_tests", + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", + "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "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/", + "test": "angle_deqp_khr_single_gles32_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_single_gles32_tests/", "use_isolated_scripts_api": true }, { "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--max-processes=1" + "--gtest_filter=-*Vulkan_SwiftShader*" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 + "shards": 3 }, "test": "angle_end2end_tests", "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", @@ -7695,13 +12906,14 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_gles1_conformance_tests", "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -7714,13 +12926,14 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -7730,19 +12943,17 @@ "use_isolated_scripts_api": true }, { - "args": [ - "--max-processes=1" - ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_white_box_tests", "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -7760,13 +12971,14 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_capture_tests", "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -7786,13 +12998,14 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_perftests", "name": "angle_perftests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -7805,12 +13018,12 @@ "args": [ "--test-machine-name", "${buildername}", - "--git-revision=${got_angle_revision}", - "--flaky-retries=1" + "--git-revision=${got_angle_revision}" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -7822,11 +13035,12 @@ "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 }, "test": "angle_restricted_trace_gold_tests", "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" @@ -7845,13 +13059,14 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -7874,13 +13089,14 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", "dimensions": { "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -7891,95 +13107,6 @@ } ] }, - "win10-x64-intel-perf": { - "isolated_scripts": [ - { - "args": [ - "--log=debug", - "--samples-per-test=3", - "--trials-per-sample=3", - "--show-test-stdout" - ], - "merge": { - "script": "//scripts/process_angle_perf_results.py" - }, - "name": "angle_perftests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", - "pool": "chromium.tests.gpu" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 - }, - "test": "angle_perftests", - "test_id_prefix": "ninja://src/tests:angle_perftests/" - }, - { - "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-gl=native", - "--trace-tests" - ], - "merge": { - "script": "//scripts/process_angle_perf_results.py" - }, - "name": "angle_trace_perf_native_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", - "pool": "chromium.tests.gpu" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 - }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - }, - { - "args": [ - "--log=debug", - "--show-test-stdout", - "--samples-per-test=3", - "--trials-per-sample=3", - "--use-angle=vulkan", - "--trace-tests" - ], - "merge": { - "script": "//scripts/process_angle_perf_results.py" - }, - "name": "angle_trace_perf_vulkan_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "display_attached": "1", - "gpu": "8086:9bc5-31.0.101.2127", - "os": "Windows-10", - "pool": "chromium.tests.gpu" - }, - "hard_timeout": 7200, - "io_timeout": 300, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 - }, - "test": "angle_trace_perf_tests", - "test_id_prefix": "ninja://src/tests:angle_trace_perf_tests/" - } - ] - }, "win10-x64-nvidia": { "gtest_tests": [ { @@ -7989,6 +13116,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_d3d11_tests", "swarming": { "containment_type": "AUTO", @@ -8012,6 +13140,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_gl_tests", "swarming": { "containment_type": "AUTO", @@ -8034,6 +13163,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8057,6 +13187,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_d3d11_tests", "swarming": { "containment_type": "AUTO", @@ -8079,6 +13210,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_gl_tests", "swarming": { "containment_type": "AUTO", @@ -8101,6 +13233,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8123,6 +13256,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_webgpu_tests", "swarming": { "containment_type": "AUTO", @@ -8138,29 +13272,6 @@ "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", "use_isolated_scripts_api": true }, - { - "args": [ - "--use-angle=d3d11" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_gles31_d3d11_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "display_attached": "1", - "gpu": "10de:2184-31.0.15.4601", - "os": "Windows-10-19045", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 - }, - "test": "angle_deqp_gles31_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles31_tests/", - "use_isolated_scripts_api": true - }, { "args": [ "--use-angle=gl" @@ -8168,6 +13279,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_gl_tests", "swarming": { "containment_type": "AUTO", @@ -8191,6 +13303,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8213,6 +13326,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", "name": "angle_deqp_gles31_vulkan_rotate180_tests", "swarming": { "containment_type": "AUTO", @@ -8235,6 +13349,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", "name": "angle_deqp_gles31_vulkan_rotate270_tests", "swarming": { "containment_type": "AUTO", @@ -8257,6 +13372,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", "name": "angle_deqp_gles31_vulkan_rotate90_tests", "swarming": { "containment_type": "AUTO", @@ -8279,6 +13395,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8302,6 +13419,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_d3d11_tests", "swarming": { "containment_type": "AUTO", @@ -8325,6 +13443,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_gl_tests", "swarming": { "containment_type": "AUTO", @@ -8348,6 +13467,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8370,6 +13490,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", "name": "angle_deqp_gles3_vulkan_rotate180_tests", "swarming": { "containment_type": "AUTO", @@ -8393,6 +13514,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", "name": "angle_deqp_gles3_vulkan_rotate270_tests", "swarming": { "containment_type": "AUTO", @@ -8416,6 +13538,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", "name": "angle_deqp_gles3_vulkan_rotate90_tests", "swarming": { "containment_type": "AUTO", @@ -8439,6 +13562,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8465,6 +13589,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8490,6 +13615,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8515,6 +13641,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed1_width64_height64", "swarming": { "containment_type": "AUTO", @@ -8540,6 +13667,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed2_width113_height47", "swarming": { "containment_type": "AUTO", @@ -8566,6 +13694,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width-1_height64", "swarming": { "containment_type": "AUTO", @@ -8592,6 +13721,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles32_tests", "name": "angle_deqp_khr_gles32_vulkan_tests_seed3_width64_height-1", "swarming": { "containment_type": "AUTO", @@ -8617,6 +13747,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8632,6 +13763,32 @@ "test_id_prefix": "ninja://src/tests:angle_deqp_khr_gles3_tests/", "use_isolated_scripts_api": true }, + { + "args": [ + "--use-angle=vulkan", + "--surface-height=64", + "--surface-width=64", + "--deqp-base-seed=1" + ], + "merge": { + "script": "//scripts/angle_deqp_test_merge.py" + }, + "module_name": "//src/tests:angle_deqp_khr_glesext_tests", + "name": "angle_deqp_khr_glesext_vulkan_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "display_attached": "1", + "gpu": "10de:2184-31.0.15.4601", + "os": "Windows-10-19045", + "pool": "chromium.tests.gpu" + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_deqp_khr_glesext_tests", + "test_id_prefix": "ninja://src/tests:angle_deqp_khr_glesext_tests/", + "use_isolated_scripts_api": true + }, { "args": [ "--use-angle=vulkan" @@ -8639,6 +13796,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8661,6 +13819,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles32_tests", "name": "angle_deqp_khr_noctx_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8683,6 +13842,7 @@ "merge": { "script": "//scripts/angle_deqp_test_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_single_gles32_tests", "name": "angle_deqp_khr_single_gles32_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8705,6 +13865,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -8715,7 +13876,7 @@ "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 3 }, "test": "angle_end2end_tests", "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", @@ -8729,6 +13890,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_gles1_conformance_tests", "name": "angle_gles1_conformance_tests", "swarming": { "containment_type": "AUTO", @@ -8748,6 +13910,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_unittests", "name": "angle_unittests", "swarming": { "containment_type": "AUTO", @@ -8767,6 +13930,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_white_box_tests", "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", @@ -8791,6 +13955,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_capture_tests", "name": "angle_capture_tests", "swarming": { "containment_type": "AUTO", @@ -8817,6 +13982,7 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_perftests", "name": "angle_perftests", "swarming": { "containment_type": "AUTO", @@ -8841,6 +14007,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -8856,7 +14023,8 @@ "os": "Windows-10-19045", "pool": "chromium.tests.gpu" }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 }, "test": "angle_restricted_trace_gold_tests", "test_id_prefix": "ninja://src/tests/restricted_traces:angle_restricted_trace_gold_tests/" @@ -8875,6 +14043,7 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", @@ -8904,6 +14073,7 @@ ], "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -8933,6 +14103,7 @@ "merge": { "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_perftests", "name": "angle_perftests", "swarming": { "containment_type": "AUTO", @@ -8962,6 +14133,7 @@ "merge": { "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_native_tests", "swarming": { "containment_type": "AUTO", @@ -8991,6 +14163,7 @@ "merge": { "script": "//scripts/process_angle_perf_results.py" }, + "module_name": "//src/tests:angle_trace_perf_tests", "name": "angle_trace_perf_vulkan_tests", "swarming": { "containment_type": "AUTO", @@ -9019,6 +14192,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_tests", "swarming": { "containment_type": "AUTO", @@ -9043,6 +14217,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_tests", "swarming": { "containment_type": "AUTO", @@ -9067,6 +14242,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_tests", "swarming": { "containment_type": "AUTO", @@ -9091,6 +14267,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", "name": "angle_deqp_gles31_rotate180_tests", "swarming": { "containment_type": "AUTO", @@ -9115,6 +14292,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", "name": "angle_deqp_gles31_rotate270_tests", "swarming": { "containment_type": "AUTO", @@ -9139,6 +14317,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", "name": "angle_deqp_gles31_rotate90_tests", "swarming": { "containment_type": "AUTO", @@ -9163,6 +14342,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_tests", "swarming": { "containment_type": "AUTO", @@ -9188,6 +14368,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_tests", "swarming": { "containment_type": "AUTO", @@ -9212,6 +14393,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", "name": "angle_deqp_gles3_rotate180_tests", "swarming": { "containment_type": "AUTO", @@ -9236,6 +14418,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", "name": "angle_deqp_gles3_rotate270_tests", "swarming": { "containment_type": "AUTO", @@ -9260,6 +14443,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", "name": "angle_deqp_gles3_rotate90_tests", "swarming": { "containment_type": "AUTO", @@ -9284,6 +14468,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_tests", "swarming": { "containment_type": "AUTO", @@ -9312,6 +14497,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_tests", "swarming": { "containment_type": "AUTO", @@ -9339,6 +14525,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_tests", "swarming": { "containment_type": "AUTO", @@ -9366,6 +14553,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_tests", "swarming": { "containment_type": "AUTO", @@ -9390,6 +14578,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_tests", "swarming": { "containment_type": "AUTO", @@ -9414,6 +14603,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -9438,6 +14628,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_white_box_tests", "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", @@ -9462,11 +14653,13 @@ "--test-machine-name", "${buildername}", "--swiftshader", + "--key-frame-limit=10", "--git-revision=${got_angle_revision}" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests/restricted_traces:angle_restricted_trace_gold_tests", "name": "angle_restricted_trace_gold_tests", "precommit_args": [ "--gerrit-issue=${patch_issue}", @@ -9502,6 +14695,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -9514,7 +14708,7 @@ "hard_timeout": 900, "io_timeout": 900, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 14 }, "test": "angle_end2end_tests", "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", @@ -9527,6 +14721,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_white_box_tests", "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", @@ -9555,6 +14750,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_egl_tests", "name": "angle_deqp_egl_tests", "swarming": { "containment_type": "AUTO", @@ -9579,6 +14775,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles2_tests", "name": "angle_deqp_gles2_tests", "swarming": { "containment_type": "AUTO", @@ -9603,6 +14800,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_multisample_tests", "name": "angle_deqp_gles31_multisample_tests", "swarming": { "containment_type": "AUTO", @@ -9627,6 +14825,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate180_tests", "name": "angle_deqp_gles31_rotate180_tests", "swarming": { "containment_type": "AUTO", @@ -9651,6 +14850,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate270_tests", "name": "angle_deqp_gles31_rotate270_tests", "swarming": { "containment_type": "AUTO", @@ -9675,6 +14875,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_rotate90_tests", "name": "angle_deqp_gles31_rotate90_tests", "swarming": { "containment_type": "AUTO", @@ -9699,6 +14900,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles31_tests", "name": "angle_deqp_gles31_tests", "swarming": { "containment_type": "AUTO", @@ -9724,6 +14926,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_multisample_tests", "name": "angle_deqp_gles3_multisample_tests", "swarming": { "containment_type": "AUTO", @@ -9748,6 +14951,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate180_tests", "name": "angle_deqp_gles3_rotate180_tests", "swarming": { "containment_type": "AUTO", @@ -9772,6 +14976,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate270_tests", "name": "angle_deqp_gles3_rotate270_tests", "swarming": { "containment_type": "AUTO", @@ -9796,6 +15001,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_rotate90_tests", "name": "angle_deqp_gles3_rotate90_tests", "swarming": { "containment_type": "AUTO", @@ -9820,6 +15026,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_gles3_tests", "name": "angle_deqp_gles3_tests", "swarming": { "containment_type": "AUTO", @@ -9848,6 +15055,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles2_tests", "name": "angle_deqp_khr_gles2_tests", "swarming": { "containment_type": "AUTO", @@ -9875,6 +15083,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles31_tests", "name": "angle_deqp_khr_gles31_tests", "swarming": { "containment_type": "AUTO", @@ -9902,6 +15111,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_gles3_tests", "name": "angle_deqp_khr_gles3_tests", "swarming": { "containment_type": "AUTO", @@ -9926,6 +15136,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "name": "angle_deqp_khr_noctx_gles2_tests", "swarming": { "containment_type": "AUTO", @@ -9950,6 +15161,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_end2end_tests", "name": "angle_end2end_tests", "swarming": { "containment_type": "AUTO", @@ -9974,6 +15186,7 @@ "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, + "module_name": "//src/tests:angle_white_box_tests", "name": "angle_white_box_tests", "swarming": { "containment_type": "AUTO", diff --git a/infra/specs/angle_mb_config.pyl b/infra/specs/angle_mb_config.pyl index ae3b2f71b44..ca27daf86a9 100644 --- a/infra/specs/angle_mb_config.pyl +++ b/infra/specs/angle_mb_config.pyl @@ -14,39 +14,45 @@ # this dict to look up which config to use for a given bot. 'builder_groups': { 'angle': { - 'android-arm-compile': 'angle_reclient_android_arm_release_bot', - 'android-arm-dbg-compile': 'angle_reclient_android_arm_debug_bot', - 'android-arm64-dbg-compile': 'angle_reclient_android_arm64_debug_bot', - 'android-arm64-exp-s22-test': 'angle_reclient_android_arm64_release_bot', - 'android-arm64-exp-test': 'angle_reclient_android_arm64_release_bot', - 'android-arm64-test': 'angle_reclient_android_arm64_release_bot', - 'android-pixel4-perf': 'angle_reclient_android_perf_bot', - 'android-pixel6-perf': 'angle_reclient_android_perf_bot', + 'android-arm-compile': 'angle_remoteexec_android_arm_release_bot', + 'android-arm-dbg-compile': 'angle_remoteexec_android_arm_debug_bot', + 'android-arm64-dbg-compile': 'angle_remoteexec_android_arm64_debug_bot', + 'android-arm64-exp-pixel10-test': 'angle_remoteexec_android_arm64_release_bot', + 'android-arm64-exp-s24-test': 'angle_remoteexec_android_arm64_release_bot', + 'android-arm64-exp-test': 'angle_remoteexec_android_arm64_release_bot', + 'android-arm64-ir-test': 'angle_remoteexec_android_arm64_release_ir_bot', + 'android-arm64-test': 'angle_remoteexec_android_arm64_release_bot', + 'android-pixel4-perf': 'angle_remoteexec_android_perf_bot', + 'android-pixel6-perf': 'angle_remoteexec_android_perf_bot', 'linux-asan-test': 'angle_asan_lsan_ubsan_bot', - 'linux-dbg-compile': 'angle_reclient_debug_openclcts_bot', + 'linux-dbg-compile': 'angle_remoteexec_debug_openclcts_bot', 'linux-exp-asan-test': 'angle_asan_lsan_ubsan_bot', - 'linux-exp-test': 'angle_reclient_release_openclcts_bot', + 'linux-exp-test': 'angle_remoteexec_release_openclcts_bot', 'linux-exp-tsan-test': 'angle_tsan_bot', - 'linux-intel-uhd630-perf': 'angle_reclient_perf_bot', - 'linux-nvidia-gtx1660-perf': 'angle_reclient_perf_bot', - 'linux-test': 'angle_reclient_release_openclcts_bot', + 'linux-intel-uhd630-perf': 'angle_remoteexec_perf_bot', + 'linux-ir-test': 'angle_remoteexec_release_ir_bot', + 'linux-nvidia-gtx1660-perf': 'angle_remoteexec_perf_bot', + 'linux-test': 'angle_remoteexec_release_openclcts_bot', 'linux-tsan-test': 'angle_tsan_bot', 'linux-ubsan-test': 'angle_ubsan_bot', - 'mac-dbg-compile': 'angle_reclient_x64_debug_bot', - 'mac-exp-test': 'angle_reclient_x64_release_bot', - 'mac-test': 'angle_reclient_x64_release_bot', + 'mac-arm64-test': 'angle_remoteexec_arm64_release_bot', + 'mac-dbg-compile': 'angle_remoteexec_x64_debug_bot', + 'mac-exp-test': 'angle_remoteexec_x64_release_bot', + 'mac-ir-test': 'angle_remoteexec_x64_release_ir_bot', + 'mac-test': 'angle_remoteexec_x64_release_bot', 'win-asan-test': 'angle_asan_bot', - 'win-dbg-compile': 'angle_reclient_debug_bot', - 'win-exp-test': 'angle_reclient_release_bot', + 'win-dbg-compile': 'angle_remoteexec_debug_bot', + 'win-exp-test': 'angle_remoteexec_release_bot', + 'win-ir-test': 'angle_remoteexec_release_ir_bot', 'win-msvc-compile': 'angle_non_clang_release_bot', 'win-msvc-dbg-compile': 'angle_non_clang_debug_bot', 'win-msvc-x86-compile': 'angle_non_clang_x86_release_bot', 'win-msvc-x86-dbg-compile': 'angle_non_clang_x86_debug_bot', - 'win-test': 'angle_reclient_release_bot', - 'win-x86-dbg-compile': 'angle_reclient_x86_debug_bot', - 'win-x86-test': 'angle_reclient_x86_release_bot', - 'win10-intel-uhd630-perf': 'angle_reclient_perf_bot', - 'win10-nvidia-gtx1660-perf': 'angle_reclient_perf_bot', + 'win-test': 'angle_remoteexec_release_bot', + 'win-x86-dbg-compile': 'angle_remoteexec_x86_debug_bot', + 'win-x86-test': 'angle_remoteexec_x86_release_bot', + 'win10-intel-uhd630-perf': 'angle_remoteexec_perf_bot', + 'win10-nvidia-gtx1660-perf': 'angle_remoteexec_perf_bot', 'winuwp-compile': 'angle_winuwp_non_clang_release_bot', 'winuwp-dbg-compile': 'angle_winuwp_non_clang_debug_bot', }, @@ -58,28 +64,32 @@ # is not necessarily so (i.e., we might have mac, win, and linux # bots all using the 'release_bot' config). 'configs': { - 'angle_asan_bot': ['angle', 'opencl', 'reclient', 'asan', 'release'], - 'angle_asan_lsan_ubsan_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'asan', 'lsan', 'ubsan', 'release'], + 'angle_asan_bot': ['angle', 'opencl', 'remoteexec', 'asan', 'release'], + 'angle_asan_lsan_ubsan_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'asan', 'lsan', 'ubsan', 'release', 'smoke_traces'], 'angle_non_clang_debug_bot': ['angle', 'non_clang', 'debug'], 'angle_non_clang_release_bot': ['angle', 'non_clang', 'release'], - 'angle_non_clang_x86_debug_bot': ['angle', 'non_clang', 'x86', 'debug', 'cxx17'], + 'angle_non_clang_x86_debug_bot': ['angle', 'non_clang', 'x86', 'debug'], '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'], - 'angle_reclient_android_arm_release_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'android', 'arm', 'release'], - 'angle_reclient_android_perf_bot': ['angle', 'reclient', 'android', 'arm64', 'perf'], - 'angle_reclient_debug_bot': ['angle', 'opencl', 'reclient', 'debug'], - 'angle_reclient_debug_openclcts_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'debug'], - 'angle_reclient_perf_bot': ['angle', 'reclient', 'perf'], - 'angle_reclient_release_bot': ['angle', 'capture', 'opencl', 'reclient', 'release'], - 'angle_reclient_release_openclcts_bot': ['angle', 'capture', 'opencl', 'openclcts', 'reclient', 'release'], - 'angle_reclient_x64_debug_bot': ['angle', 'opencl', 'reclient', 'x64', 'debug'], - 'angle_reclient_x64_release_bot': ['angle', 'capture', 'opencl', 'reclient', 'x64', 'release'], - 'angle_reclient_x86_debug_bot': ['angle', 'opencl', 'reclient', 'x86', 'debug'], - 'angle_reclient_x86_release_bot': ['angle', 'opencl', 'reclient', 'x86', 'release'], - 'angle_tsan_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'tsan', 'release'], - 'angle_ubsan_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'ubsan', 'release'], + 'angle_remoteexec_android_arm64_debug_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'android', 'arm64', 'debug'], + 'angle_remoteexec_android_arm64_release_bot': ['angle', 'capture', 'opencl', 'openclcts', 'remoteexec', 'android', 'arm64', 'release'], + 'angle_remoteexec_android_arm64_release_ir_bot': ['angle', 'capture', 'ir', 'opencl', 'remoteexec', 'android', 'arm64', 'release'], + 'angle_remoteexec_android_arm_debug_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'android', 'arm', 'debug'], + 'angle_remoteexec_android_arm_release_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'android', 'arm', 'release'], + 'angle_remoteexec_android_perf_bot': ['angle', 'remoteexec', 'android', 'arm64', 'perf'], + 'angle_remoteexec_arm64_release_bot': ['angle', 'capture', 'remoteexec', 'arm64', 'release'], + 'angle_remoteexec_debug_bot': ['angle', 'opencl', 'remoteexec', 'debug'], + 'angle_remoteexec_debug_openclcts_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'debug'], + 'angle_remoteexec_perf_bot': ['angle', 'remoteexec', 'perf'], + 'angle_remoteexec_release_bot': ['angle', 'capture', 'opencl', 'remoteexec', 'release'], + 'angle_remoteexec_release_ir_bot': ['angle', 'capture', 'ir', 'opencl', 'remoteexec', 'release'], + 'angle_remoteexec_release_openclcts_bot': ['angle', 'capture', 'opencl', 'openclcts', 'remoteexec', 'release'], + 'angle_remoteexec_x64_debug_bot': ['angle', 'remoteexec', 'x64', 'debug'], + 'angle_remoteexec_x64_release_bot': ['angle', 'capture', 'remoteexec', 'x64', 'release'], + 'angle_remoteexec_x64_release_ir_bot': ['angle', 'capture', 'ir', 'remoteexec', 'x64', 'release'], + 'angle_remoteexec_x86_debug_bot': ['angle', 'opencl', 'remoteexec', 'x86', 'debug'], + 'angle_remoteexec_x86_release_bot': ['angle', 'opencl', 'remoteexec', 'x86', 'release'], + 'angle_tsan_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'tsan', 'release'], + 'angle_ubsan_bot': ['angle', 'opencl', 'openclcts', 'remoteexec', 'ubsan', 'release'], 'angle_winuwp_non_clang_debug_bot': ['angle', 'winuwp', 'non_clang', 'debug'], 'angle_winuwp_non_clang_release_bot': ['angle', 'winuwp', 'non_clang', 'release'], }, @@ -88,7 +98,7 @@ # mb should use. See //tools/mb/docs/user_guide.md for more information. 'mixins': { 'android': { - 'gn_args': 'target_os="android"', + 'gn_args': 'target_os="android" android_static_analysis = "on"', }, 'angle': { 'gn_args': 'is_component_build=true', @@ -105,13 +115,12 @@ 'capture': { 'gn_args': 'angle_with_capture_by_default=true', }, - 'cxx17': { - # Android does not fully support C++20 yet: b/330910097 - 'gn_args': 'use_cxx17=true', - }, 'debug': { 'gn_args': 'is_debug=true', }, + 'ir': { + 'gn_args': 'angle_ir=true', + }, 'lsan': { 'gn_args': 'is_lsan=true', }, @@ -127,12 +136,16 @@ 'perf': { 'gn_args': 'is_debug=false dcheck_always_on=false symbol_level=1', }, - 'reclient': { - 'gn_args': 'use_remoteexec=true', - }, 'release': { 'gn_args': 'is_debug=false dcheck_always_on=true symbol_level=1', }, + 'remoteexec': { + 'gn_args': 'use_remoteexec=true use_reclient=false use_siso=true', + }, + 'smoke_traces': { + # Reason for inclusion: antutu_refinery:benchmark asphalt_9_2024:custom aztec_ruins_high:benchmark balatro:custom basemark_gpu:benchmark batman_telltale:custom dead_cells:custom diablo_immortal:custom dota_underlords:custon genshin_impact:unity grand_mountain_adventure:custom honkai_star_rail:unity manhattan_31:benchmark minecraft_bedrock:custom, ni_no_kuni:unreal slingshot_test1:benchmark sonic_the_hedgehog:gles1 tessellation:benchmark tower_of_fantasy:unreal warcraft_rumble:unity + 'gn_args': 'angle_restricted_traces=["antutu_refinery", "asphalt_9_2024", "aztec_ruins_high", "balatro", "basemark_gpu", "batman_telltale", "dead_cells", "diablo_immortal", "dota_underlords", "genshin_impact", "grand_mountain_adventure", "honkai_star_rail", "manhattan_31", "minecraft_bedrock", "ni_no_kuni", "slingshot_test1", "sonic_the_hedgehog", "tessellation", "tower_of_fantasy", "warcraft_rumble"]' + }, 'tsan': { 'gn_args': 'is_tsan=true', }, diff --git a/infra/specs/generate_test_spec_json.py b/infra/specs/generate_test_spec_json.py index 984c3989438..23648d3561a 100755 --- a/infra/specs/generate_test_spec_json.py +++ b/infra/specs/generate_test_spec_json.py @@ -43,12 +43,15 @@ '--use-permissive-pixel-comparison=${use_permissive_angle_pixel_comparison}', ], }, - 'samsung_s22': { + 'no_tombstones': { + 'args': ['--do-not-store-tombstones',], + }, + 'samsung_s24': { 'swarming': { 'dimensions': { - 'device_os': 'UP1A.231005.007', + 'device_os': 'AP3A.240905.015.A2', 'device_os_type': 'user', - 'device_type': 's5e9925', + 'device_type': 's5e9945', 'os': 'Android' } } diff --git a/infra/specs/gn_isolate_map.pyl b/infra/specs/gn_isolate_map.pyl index a6ec39a09e0..54b07e3773b 100644 --- a/infra/specs/gn_isolate_map.pyl +++ b/infra/specs/gn_isolate_map.pyl @@ -127,6 +127,10 @@ "label": "//src/tests:angle_deqp_khr_gles32_tests", "type": "windowed_test_launcher", }, + "angle_deqp_khr_glesext_tests": { + "label": "//src/tests:angle_deqp_khr_glesext_tests", + "type": "windowed_test_launcher", + }, "angle_deqp_khr_noctx_gles2_tests": { "label": "//src/tests:angle_deqp_khr_noctx_gles2_tests", "type": "windowed_test_launcher", diff --git a/infra/specs/mixins.pyl b/infra/specs/mixins.pyl index 03fbe70934e..2491c8da7ce 100644 --- a/infra/specs/mixins.pyl +++ b/infra/specs/mixins.pyl @@ -22,6 +22,12 @@ 'swarming': { 'service_account': 'chromium-tester@chops-service-accounts.iam.gserviceaccount.com'}}, 'gpu-swarming-pool': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'pool': 'chromium.tests.gpu'}}}, + 'gpu_pixel_10_stable': { 'fail_if_unused': False, + 'swarming': { 'dimensions': { 'device_os': 'BD3A.250721.001', + 'device_os_type': 'userdebug', + 'device_type': 'frankel', + 'os': 'Android', + 'pool': 'chromium.tests.gpu'}}}, 'gpu_pixel_4_stable': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'device_os': 'RP1A.201105.002', 'device_os_type': 'userdebug', @@ -63,23 +69,38 @@ 'os': 'Ubuntu-22.04', 'pool': 'chromium.tests.gpu'}}}, 'linux_nvidia_gtx_1660_stable': { 'fail_if_unused': False, - 'swarming': { 'dimensions': { 'gpu': '10de:2184-440.100', - 'os': 'Ubuntu-18.04.5|Ubuntu-18.04.6', + 'swarming': { 'dimensions': { 'gpu': '10de:2184-535.183.01', + 'os': 'Ubuntu-22.04', 'pool': 'chromium.tests.gpu'}}}, + 'mac_arm64_apple_m2_retina_gpu_stable': { 'fail_if_unused': False, + 'swarming': { 'dimensions': { 'cpu': 'arm64', + 'display_attached': '1', + 'gpu': 'apple:m2', + 'hidpi': '1', + 'mac_model': 'Mac14,7', + 'os': 'Mac-14.4.1', + 'pool': 'chromium.tests.gpu'}}}, 'mac_mini_intel_gpu_experimental': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'cpu': 'x86-64', 'display_attached': '1', 'gpu': '8086:3e9b', - 'os': 'Mac-15.0'}}}, + 'os': 'Mac-15.5'}}}, 'mac_mini_intel_gpu_stable': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'cpu': 'x86-64', 'display_attached': '1', 'gpu': '8086:3e9b', 'os': 'Mac-14.5'}}}, + 'mac_retina_amd_555x_gpu_stable': { 'fail_if_unused': False, + 'swarming': { 'dimensions': { 'cpu': 'x86-64', + 'display_attached': '1', + 'gpu': '1002:67ef', + 'hidpi': '1', + 'os': 'Mac-14.4.1', + 'pool': 'chromium.tests.gpu'}}}, 'mac_retina_amd_gpu_experimental': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'cpu': 'x86-64', 'display_attached': '1', - 'gpu': '1002:67ef', + 'gpu': '1002:7340', 'hidpi': '1', 'os': 'Mac-14.4.1', 'pool': 'chromium.tests.gpu'}}}, @@ -90,25 +111,12 @@ 'hidpi': '1', 'os': 'Mac-14.4.1', 'pool': 'chromium.tests.gpu'}}}, - 'mac_retina_nvidia_gpu_experimental': { 'fail_if_unused': False, - 'swarming': { 'dimensions': { 'cpu': 'x86-64', - 'display_attached': '1', - 'gpu': '10de:0fe9', - 'hidpi': '1', - 'os': 'Mac-11.7.9', - 'pool': 'chromium.tests.gpu'}}}, - 'mac_retina_nvidia_gpu_stable': { 'fail_if_unused': False, - 'swarming': { 'dimensions': { 'cpu': 'x86-64', - 'display_attached': '1', - 'gpu': '10de:0fe9', - 'hidpi': '1', - 'os': 'Mac-11.7.9', - 'pool': 'chromium.tests.gpu'}}}, 'no_gpu': { 'fail_if_unused': False, 'swarming': {'dimensions': {'gpu': 'none'}}}, - 'samsung_s22': { 'swarming': { 'dimensions': { 'device_os': 'UP1A.231005.007', + 'no_tombstones': {'args': ['--do-not-store-tombstones']}, + 'samsung_s24': { 'swarming': { 'dimensions': { 'device_os': 'AP3A.240905.015.A2', 'device_os_type': 'user', - 'device_type': 's5e9925', + 'device_type': 's5e9945', 'os': 'Android'}}}, 'swarming_containment_auto': { 'fail_if_unused': False, 'swarming': {'containment_type': 'AUTO'}}, @@ -129,12 +137,12 @@ 'win10_intel_uhd_770_stable': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'display_attached': '1', 'gpu': '8086:4680-31.0.101.5333', - 'os': 'Windows-10-19045.3930', + 'os': 'Windows-10-19045', 'pool': 'chromium.tests.gpu'}}}, 'win10_nvidia_gtx_1660_experimental': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'display_attached': '1', - 'gpu': '10de:2184-31.0.15.4601', - 'os': 'Windows-10-19045', + 'gpu': '10de:2184-32.0.15.8180', + 'os': 'Windows-11-26100', 'pool': 'chromium.tests.gpu'}}}, 'win10_nvidia_gtx_1660_stable': { 'fail_if_unused': False, 'swarming': { 'dimensions': { 'display_attached': '1', diff --git a/infra/specs/test_suite_exceptions.pyl b/infra/specs/test_suite_exceptions.pyl index 4c0c1b0abd4..8e804d148b0 100644 --- a/infra/specs/test_suite_exceptions.pyl +++ b/infra/specs/test_suite_exceptions.pyl @@ -35,7 +35,7 @@ '--max-processes=2', ], 'swarming': { - 'shards': 3, + 'shards': 5, }, }, # anglebug.com/40644897 suspecting device lost caused by multiprocess @@ -44,7 +44,30 @@ '--max-processes=1', ], 'swarming': { - 'shards': 4, + 'shards': 10, + }, + }, + # anglebug.com/40644897 suspecting device lost caused by multiprocess + 'win10-x64-ir-intel': { + 'args': [ + '--max-processes=1', + ], + 'swarming': { + 'shards': 10, + }, + }, + }, + 'replacements': { + # anglebug.com/408276172 suspecting WebGPU backend flakiness caused by multiprocess + 'linux-intel': { + 'args': { + '--max-processes': '1', + }, + }, + # anglebug.com/408276172 suspecting WebGPU backend flakiness caused by multiprocess + 'linux-ir-intel': { + 'args': { + '--max-processes': '1', }, }, }, @@ -61,20 +84,31 @@ }, 'angle_restricted_trace_gold_tests': { 'modifications': { - # anglebug.com/42263955 flaky 4x8 pixel artifacts on Win Intel + 'win10-x64-exp-intel': { + 'swarming': { + 'shards': 4, + }, + }, 'win10-x64-intel': { + # anglebug.com/42263955 flaky 4x8 pixel artifacts on Win Intel 'args': [ '--flaky-retries=1', ], + 'swarming': { + 'shards': 5, + }, + }, + 'win10-x64-ir-intel': { + # anglebug.com/42263955 flaky 4x8 pixel artifacts on Win Intel + 'args': [ + '--flaky-retries=1', + ], + 'swarming': { + 'shards': 5, + }, }, }, }, - 'angle_trace_interpreter_tests': { - 'remove_from': [ - # TODO: Implement on Android. http://anglebug.com/42266248 - 'android-arm64-pixel4', - ], - }, 'angle_trace_perf_native_tests': { 'modifications': { 'android-arm64-pixel6-perf': { @@ -93,6 +127,21 @@ '--custom-throttling-temp=38', ], }, + 'win10-x64-exp-intel': { + 'swarming': { + 'shards': 4, + }, + }, + 'win10-x64-intel': { + 'swarming': { + 'shards': 3, + }, + }, + 'win10-x64-ir-intel': { + 'swarming': { + 'shards': 3, + }, + }, }, }, 'angle_white_box_tests': { @@ -103,6 +152,12 @@ '--max-processes=1', ], }, + # anglebug.com/40644897 suspecting device lost caused by multiprocess + 'win10-x64-ir-intel': { + 'args': [ + '--max-processes=1', + ], + }, }, }, } diff --git a/infra/specs/test_suites.pyl b/infra/specs/test_suites.pyl index fcca8efae37..5823261a07b 100644 --- a/infra/specs/test_suites.pyl +++ b/infra/specs/test_suites.pyl @@ -184,9 +184,6 @@ 'args': [ '--use-angle=metal', ], - 'linux_args': [ - '--no-xvfb', - ], 'merge': { 'script': '//scripts/angle_deqp_test_merge.py', }, @@ -289,6 +286,19 @@ }, 'angle_deqp_gles2_metal_gtests': { + 'angle_deqp_gles2_metal_tests': { + 'args': [ + '--use-angle=metal', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_gles2_tests', + 'use_isolated_scripts_api': True, + }, + }, + + 'angle_deqp_gles2_metal_with_retry_gtests': { 'angle_deqp_gles2_metal_tests': { 'args': [ '--use-angle=metal', @@ -384,22 +394,6 @@ }, }, - 'angle_deqp_gles31_d3d11_gtests': { - 'angle_deqp_gles31_d3d11_tests': { - 'args': [ - '--use-angle=d3d11', - ], - 'merge': { - 'script': '//scripts/angle_deqp_test_merge.py', - }, - 'swarming': { - 'shards': 2, - }, - 'test': 'angle_deqp_gles31_tests', - 'use_isolated_scripts_api': True, - }, - }, - 'angle_deqp_gles31_gl_gtests': { 'angle_deqp_gles31_gl_tests': { 'args': [ @@ -476,9 +470,6 @@ 'merge': { 'script': '//scripts/angle_deqp_test_merge.py', }, - 'swarming': { - 'shards': 1, - }, 'test': 'angle_deqp_gles31_rotate180_tests', 'use_isolated_scripts_api': True, }, @@ -495,9 +486,6 @@ 'merge': { 'script': '//scripts/angle_deqp_test_merge.py', }, - 'swarming': { - 'shards': 1, - }, 'test': 'angle_deqp_gles31_rotate270_tests', 'use_isolated_scripts_api': True, }, @@ -514,9 +502,6 @@ 'merge': { 'script': '//scripts/angle_deqp_test_merge.py', }, - 'swarming': { - 'shards': 1, - }, 'test': 'angle_deqp_gles31_rotate90_tests', 'use_isolated_scripts_api': True, }, @@ -619,6 +604,22 @@ }, 'angle_deqp_gles3_metal_gtests': { + 'angle_deqp_gles3_metal_tests': { + 'args': [ + '--use-angle=metal', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'swarming': { + 'shards': 2, + }, + 'test': 'angle_deqp_gles3_tests', + 'use_isolated_scripts_api': True, + }, + }, + + 'angle_deqp_gles3_metal_with_retry_gtests': { 'angle_deqp_gles3_metal_tests': { 'args': [ '--use-angle=metal', @@ -636,6 +637,19 @@ }, }, + 'angle_deqp_gles3_multisample_metal_gtests': { + 'angle_deqp_gles3_multisample_metal_tests': { + 'args': [ + '--use-angle=metal', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_gles3_multisample_tests', + 'use_isolated_scripts_api': True, + }, + }, + 'angle_deqp_gles3_multisample_vulkan_gtests': { 'angle_deqp_gles3_multisample_vulkan_tests': { 'args': [ @@ -739,6 +753,41 @@ }, }, + 'angle_deqp_khr_gles2_gl_gtests': { + 'angle_deqp_khr_gles2_gl_tests': { + 'args': [ + '--use-angle=gl', + '--surface-height=64', + '--surface-width=64', + '--deqp-base-seed=1', + ], + 'linux_args': [ + '--no-xvfb', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_gles2_tests', + 'use_isolated_scripts_api': True, + }, + }, + + 'angle_deqp_khr_gles2_metal_gtests': { + 'angle_deqp_khr_gles2_metal_tests': { + 'args': [ + '--use-angle=metal', + '--surface-height=64', + '--surface-width=64', + '--deqp-base-seed=1', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_gles2_tests', + 'use_isolated_scripts_api': True, + }, + }, + 'angle_deqp_khr_gles2_vulkan_gtests': { 'angle_deqp_khr_gles2_vulkan_tests': { 'args': [ @@ -870,6 +919,41 @@ }, }, + 'angle_deqp_khr_gles3_gl_gtests': { + 'angle_deqp_khr_gles3_gl_tests': { + 'args': [ + '--use-angle=gl', + '--surface-height=64', + '--surface-width=64', + '--deqp-base-seed=1', + ], + 'linux_args': [ + '--no-xvfb', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_gles3_tests', + 'use_isolated_scripts_api': True, + }, + }, + + 'angle_deqp_khr_gles3_metal_gtests': { + 'angle_deqp_khr_gles3_metal_tests': { + 'args': [ + '--use-angle=metal', + '--surface-height=64', + '--surface-width=64', + '--deqp-base-seed=1', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_gles3_tests', + 'use_isolated_scripts_api': True, + }, + }, + 'angle_deqp_khr_gles3_vulkan_gtests': { 'angle_deqp_khr_gles3_vulkan_tests': { 'args': [ @@ -893,6 +977,58 @@ }, }, + 'angle_deqp_khr_glesext_vulkan_gtests': { + 'angle_deqp_khr_glesext_vulkan_tests': { + 'args': [ + '--use-angle=vulkan', + '--surface-height=64', + '--surface-width=64', + '--deqp-base-seed=1', + ], + 'android_args': [ + '-v', + '--shard-timeout=500', + ], + 'linux_args': [ + '--no-xvfb', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_glesext_tests', + 'use_isolated_scripts_api': True, + }, + }, + + 'angle_deqp_khr_noctx_gles2_gl_gtests': { + 'angle_deqp_khr_noctx_gles2_gl_tests': { + 'args': [ + '--use-angle=gl', + ], + 'linux_args': [ + '--no-xvfb', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_noctx_gles2_tests', + 'use_isolated_scripts_api': True, + }, + }, + + 'angle_deqp_khr_noctx_gles2_metal_gtests': { + 'angle_deqp_khr_noctx_gles2_metal_tests': { + 'args': [ + '--use-angle=metal', + ], + 'merge': { + 'script': '//scripts/angle_deqp_test_merge.py', + }, + 'test': 'angle_deqp_khr_noctx_gles2_tests', + 'use_isolated_scripts_api': True, + }, + }, + 'angle_deqp_khr_noctx_gles2_vulkan_gtests': { 'angle_deqp_khr_noctx_gles2_vulkan_tests': { 'args': [ @@ -973,7 +1109,7 @@ '--no-xvfb', ], 'swarming': { - 'shards': 2, + 'shards': 3, }, 'use_isolated_scripts_api': True, }, @@ -1118,6 +1254,9 @@ 'mixins': [ 'angle_skia_gold_test', ], + 'swarming': { + 'shards': 3, + }, 'android_swarming': { 'shards': 6, }, @@ -1395,7 +1534,7 @@ '--use-angle=swiftshader', ], 'swarming': { - 'shards': 8, + 'shards': 11, }, 'use_isolated_scripts_api': True, }, @@ -1488,7 +1627,7 @@ ], 'use_isolated_scripts_api': True, 'swarming': { - 'shards': 10, + 'shards': 14, }, }, }, @@ -1499,6 +1638,7 @@ '--test-machine-name', '${buildername}', '--swiftshader', + '--key-frame-limit=10', ], 'linux_args': [ '--xvfb', @@ -1541,6 +1681,7 @@ 'angle_deqp_khr_gles31_vulkan_gtests', 'angle_deqp_khr_gles32_vulkan_gtests', 'angle_deqp_khr_gles3_vulkan_gtests', + 'angle_deqp_khr_glesext_vulkan_gtests', 'angle_deqp_khr_noctx_gles2_vulkan_gtests', 'angle_deqp_khr_noctx_gles32_vulkan_gtests', 'angle_deqp_khr_single_gles32_vulkan_gtests', @@ -1562,6 +1703,7 @@ 'angle_deqp_khr_gles31_vulkan_gtests', 'angle_deqp_khr_gles32_vulkan_gtests', 'angle_deqp_khr_gles3_vulkan_gtests', + 'angle_deqp_khr_glesext_vulkan_gtests', 'angle_deqp_khr_noctx_gles2_vulkan_gtests', 'angle_deqp_khr_noctx_gles32_vulkan_gtests', 'angle_deqp_khr_single_gles32_vulkan_gtests', @@ -1588,7 +1730,7 @@ 'angle_restricted_trace_gold_isolated_scripts', ], - 'isolated_scripts_group_s22': [ + 'isolated_scripts_group_s24': [ 'angle_restricted_trace_gold_isolated_scripts', ], @@ -1622,6 +1764,7 @@ 'angle_deqp_khr_gles31_vulkan_gtests', 'angle_deqp_khr_gles32_vulkan_gtests', 'angle_deqp_khr_gles3_vulkan_gtests', + 'angle_deqp_khr_glesext_vulkan_gtests', 'angle_deqp_khr_noctx_gles2_vulkan_gtests', 'angle_deqp_khr_noctx_gles32_vulkan_gtests', 'angle_deqp_khr_single_gles32_vulkan_gtests', @@ -1643,21 +1786,68 @@ 'angle_cl_profiling_gtests', ], + 'linux_nvidia_ir_gtests': [ + 'angle_deqp_egl_gl_gtests', + 'angle_deqp_egl_vulkan_gtests', + 'angle_deqp_gles2_gl_gtests', + 'angle_deqp_gles2_vulkan_gtests', + 'angle_deqp_gles2_webgpu_gtests', + 'angle_deqp_gles31_gl_gtests', + 'angle_deqp_gles31_multisample_vulkan_gtests', + 'angle_deqp_gles31_vulkan_gtests', + 'angle_deqp_gles31_vulkan_rotate180_gtests', + 'angle_deqp_gles31_vulkan_rotate270_gtests', + 'angle_deqp_gles31_vulkan_rotate90_gtests', + 'angle_deqp_gles3_gl_gtests', + 'angle_deqp_gles3_multisample_vulkan_gtests', + 'angle_deqp_gles3_vulkan_gtests', + 'angle_deqp_gles3_vulkan_rotate180_gtests', + 'angle_deqp_gles3_vulkan_rotate270_gtests', + 'angle_deqp_gles3_vulkan_rotate90_gtests', + 'angle_deqp_khr_gles2_vulkan_gtests', + 'angle_deqp_khr_gles31_vulkan_gtests', + 'angle_deqp_khr_gles32_vulkan_gtests', + 'angle_deqp_khr_gles3_vulkan_gtests', + 'angle_deqp_khr_glesext_vulkan_gtests', + 'angle_deqp_khr_noctx_gles2_vulkan_gtests', + 'angle_deqp_khr_noctx_gles32_vulkan_gtests', + 'angle_deqp_khr_single_gles32_vulkan_gtests', + 'angle_end2end_gtests', + 'angle_gles1_conformance_gtests', + 'angle_white_box_gtests', + ], + 'mac_amd_and_intel_gtests': [ 'angle_deqp_egl_gl_gtests', 'angle_deqp_egl_metal_gtests', 'angle_deqp_gles2_gl_with_retry_gtests', - 'angle_deqp_gles2_metal_gtests', + 'angle_deqp_gles2_metal_with_retry_gtests', 'angle_deqp_gles2_webgpu_with_retry_gtests', 'angle_deqp_gles3_gl_with_retry_gtests', - 'angle_deqp_gles3_metal_gtests', + 'angle_deqp_gles3_metal_with_retry_gtests', 'angle_end2end_with_retry_gtests', 'angle_unit_gtests', ], - 'mac_nvidia_gtests': [ + 'mac_apple_gtests': [ + 'angle_deqp_egl_gl_gtests', + 'angle_deqp_egl_metal_gtests', + 'angle_deqp_gles2_gl_gtests', + 'angle_deqp_gles2_metal_gtests', + 'angle_deqp_gles2_webgpu_gtests', + 'angle_deqp_khr_gles2_gl_gtests', + 'angle_deqp_khr_gles2_metal_gtests', + 'angle_deqp_khr_noctx_gles2_gl_gtests', + 'angle_deqp_khr_noctx_gles2_metal_gtests', + 'angle_deqp_gles3_gl_gtests', + 'angle_deqp_gles3_metal_gtests', + 'angle_deqp_gles3_multisample_metal_gtests', + 'angle_deqp_khr_gles3_gl_gtests', + 'angle_deqp_khr_gles3_metal_gtests', 'angle_end2end_with_retry_gtests', + 'angle_gles1_conformance_gtests', 'angle_unit_gtests', + 'angle_white_box_gtests', ], 'swangle_gtests': [ @@ -1733,7 +1923,6 @@ 'angle_deqp_gles2_gl_gtests', 'angle_deqp_gles2_vulkan_gtests', 'angle_deqp_gles2_webgpu_gtests', - 'angle_deqp_gles31_d3d11_gtests', 'angle_deqp_gles31_gl_gtests', 'angle_deqp_gles31_multisample_vulkan_gtests', 'angle_deqp_gles31_vulkan_gtests', @@ -1751,6 +1940,7 @@ 'angle_deqp_khr_gles31_vulkan_gtests', 'angle_deqp_khr_gles32_vulkan_gtests', 'angle_deqp_khr_gles3_vulkan_gtests', + 'angle_deqp_khr_glesext_vulkan_gtests', 'angle_deqp_khr_noctx_gles2_vulkan_gtests', 'angle_deqp_khr_noctx_gles32_vulkan_gtests', 'angle_deqp_khr_single_gles32_vulkan_gtests', diff --git a/infra/specs/trybot_analyze_config.json b/infra/specs/trybot_analyze_config.json index 0a7f70f0764..dbe42b216d6 100644 --- a/infra/specs/trybot_analyze_config.json +++ b/infra/specs/trybot_analyze_config.json @@ -1,7 +1,6 @@ { "angle": { "exclusions": [ - ".vpython", ".vpython3", "DEPS", "infra/specs/.*" diff --git a/infra/specs/waterfalls.pyl b/infra/specs/waterfalls.pyl index f43d366300f..e9d68c9627b 100644 --- a/infra/specs/waterfalls.pyl +++ b/infra/specs/waterfalls.pyl @@ -19,6 +19,14 @@ 'swarming_containment_auto', ], 'machines': { + 'android-arm64-exp-pixel10': { + 'os_type': 'android', + 'mixins': [ + 'gpu_pixel_10_stable', + ], + 'test_suites': { + }, + }, 'android-arm64-exp-pixel6': { # android-arm64-pixel6 below for android-arm64-test 'os_type': 'android', 'mixins': [ @@ -30,15 +38,37 @@ 'isolated_scripts': 'isolated_scripts_group_pixel6', }, }, - 'android-arm64-exp-s22': { + 'android-arm64-exp-s24': { 'os_type': 'android', 'mixins': [ 'gpu-swarming-pool', - 'samsung_s22', + 'samsung_s24', + # crbug.com/419062315 + 'no_tombstones', ], 'test_suites': { 'gtest_tests': 'android_vulkan_gtests', - 'isolated_scripts': 'isolated_scripts_group_s22', + 'isolated_scripts': 'isolated_scripts_group_s24', + }, + }, + 'android-arm64-ir-pixel4': { + 'os_type': 'android', + 'mixins': [ + 'gpu_pixel_4_stable', + ], + 'test_suites': { + 'gtest_tests': 'android_gtests', + 'isolated_scripts': 'isolated_scripts_group_common', + }, + }, + 'android-arm64-ir-pixel6': { + 'os_type': 'android', + 'mixins': [ + 'gpu_pixel_6_stable', + ], + 'test_suites': { + 'gtest_tests': 'android_vulkan_gtests', + 'isolated_scripts': 'isolated_scripts_group_pixel6', }, }, 'android-arm64-pixel4': { @@ -83,6 +113,20 @@ 'isolated_scripts': 'isolated_scripts_group_perf', }, }, + 'angle-linux-x64-sws-rel': { + 'os_type': 'linux', + 'mixins': [ + 'gpu-swarming-pool', + 'no_gpu', + 'linux-jammy', + 'timeout_15m', + 'x86-64', + ], + 'test_suites': { + 'gtest_tests': 'swangle_gtests', + 'isolated_scripts': 'swangle_restricted_trace_gold_isolated_scripts', + }, + }, 'linux-amd': { 'os_type': 'linux', 'mixins': [ @@ -105,8 +149,6 @@ 'linux_nvidia_gtx_1660_experimental', ], 'test_suites': { - 'gtest_tests': 'linux_nvidia_gtests', - 'isolated_scripts': 'isolated_scripts_group_common', }, }, 'linux-exp-swiftshader': { @@ -165,6 +207,48 @@ 'isolated_scripts': 'isolated_scripts_group_perf', }, }, + 'linux-ir-amd': { + 'os_type': 'linux', + 'mixins': [ + 'linux_amd_rx_5500_xt', + ], + 'test_suites': { + }, + }, + 'linux-ir-intel': { + 'os_type': 'linux', + 'mixins': [ + 'linux_intel_uhd_630_stable', + ], + 'test_suites': { + 'gtest_tests': 'linux_intel_gtests', + 'isolated_scripts': 'isolated_scripts_group_common', + }, + }, + 'linux-ir-nvidia': { + 'os_type': 'linux', + 'mixins': [ + 'linux_nvidia_gtx_1660_stable', + ], + 'test_suites': { + 'gtest_tests': 'linux_nvidia_ir_gtests', + 'isolated_scripts': 'isolated_scripts_group_common', + }, + }, + 'linux-ir-swiftshader': { + 'os_type': 'linux', + 'mixins': [ + 'gpu-swarming-pool', + 'no_gpu', + 'linux-jammy', + 'timeout_15m', + 'x86-64', + ], + 'test_suites': { + 'gtest_tests': 'swangle_gtests', + 'isolated_scripts': 'swangle_restricted_trace_gold_isolated_scripts', + }, + }, 'linux-nvidia': { 'os_type': 'linux', 'mixins': [ @@ -234,13 +318,21 @@ 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, + 'mac-arm64-apple': { + 'os_type': 'mac', + 'mixins': [ + 'mac_arm64_apple_m2_retina_gpu_stable', + ], + 'test_suites': { + 'gtest_tests': 'mac_apple_gtests', + }, + }, 'mac-exp-amd': { 'os_type': 'mac', 'mixins': [ 'mac_retina_amd_gpu_experimental', ], 'test_suites': { - 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, 'mac-exp-intel': { @@ -252,15 +344,25 @@ 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, - 'mac-exp-nvidia': { + 'mac-intel': { 'os_type': 'mac', 'mixins': [ - 'mac_retina_nvidia_gpu_experimental', + 'mac_mini_intel_gpu_stable', ], 'test_suites': { + 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, - 'mac-intel': { + 'mac-ir-amd': { + 'os_type': 'mac', + 'mixins': [ + 'mac_retina_amd_gpu_stable', + ], + 'test_suites': { + 'gtest_tests': 'mac_amd_and_intel_gtests', + }, + }, + 'mac-ir-intel': { 'os_type': 'mac', 'mixins': [ 'mac_mini_intel_gpu_stable', @@ -269,14 +371,13 @@ 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, - 'mac-nvidia': { + 'mac-x64-amd-555x-test': { 'os_type': 'mac', 'mixins': [ - 'mac_retina_nvidia_gpu_stable', + 'mac_retina_amd_555x_gpu_stable', ], 'test_suites': { - # Fewer tests enabled on this config because of limited capacity. - 'gtest_tests': 'mac_nvidia_gtests', + 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, 'win10-x64-exp-intel': { @@ -317,6 +418,26 @@ 'isolated_scripts': 'isolated_scripts_group_perf', }, }, + 'win10-x64-ir-intel': { + 'os_type': 'win', + 'mixins': [ + 'win10_intel_uhd_630_stable', + ], + 'test_suites': { + 'gtest_tests': 'win10_intel_gtests', + 'isolated_scripts': 'isolated_scripts_group_common', + }, + }, + 'win10-x64-ir-nvidia': { + 'os_type': 'win', + 'mixins': [ + 'win10_nvidia_gtx_1660_stable', + ], + 'test_suites': { + 'gtest_tests': 'win10_nvidia_gtests', + 'isolated_scripts': 'isolated_scripts_group_common', + }, + }, 'win10-x64-nvidia': { 'os_type': 'win', 'mixins': [ diff --git a/infra/whitespace.json b/infra/whitespace.json new file mode 100644 index 00000000000..3a1201a5017 --- /dev/null +++ b/infra/whitespace.json @@ -0,0 +1,3 @@ +[ + "Some whitespace to test the cherry-picker." +] diff --git a/samples/WindowTest/WindowTest.cpp b/samples/WindowTest/WindowTest.cpp index 45d7735a85d..97931821fb4 100644 --- a/samples/WindowTest/WindowTest.cpp +++ b/samples/WindowTest/WindowTest.cpp @@ -47,34 +47,34 @@ int main(int argc, char *argv[]) int newY = y; switch (event.Key.Code) { - case KEY_ESCAPE: + case angle::KeyType::ESCAPE: running = false; break; - case KEY_W: + case angle::KeyType::W: newWidth = std::max(0, width + (event.Key.Shift ? -20 : 20)); break; - case KEY_H: + case angle::KeyType::H: newHeight = std::max(0, height + (event.Key.Shift ? -20 : 20)); break; - case KEY_LEFT: + case angle::KeyType::LEFT: newX = x - 20; break; - case KEY_RIGHT: + case angle::KeyType::RIGHT: newX = x + 20; break; - case KEY_UP: + case angle::KeyType::UP: newY = y - 20; break; - case KEY_DOWN: + case angle::KeyType::DOWN: newY = y + 20; break; - case KEY_C: + case angle::KeyType::C: window->setMousePosition(width / 2, height / 2); break; - case KEY_T: + case angle::KeyType::T: window->signalTestEvent(); window->messageLoop(); if (window->didTestEventFire()) @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) std::cout << "Test event did not fire" << std::endl; } break; - case KEY_S: + case angle::KeyType::S: window->setVisible(false); window->messageLoop(); angle::Sleep(1000); diff --git a/samples/capture_replay/BUILD.gn b/samples/capture_replay/BUILD.gn index 64c8e04a751..ce0ef2f4a13 100644 --- a/samples/capture_replay/BUILD.gn +++ b/samples/capture_replay/BUILD.gn @@ -3,14 +3,7 @@ # found in the LICENSE file. import("../../gni/angle.gni") - -angle_trace_fixture("angle_capture_replay_sample_fixture") { - gl_header = "angle_trace_gl.h" - public_deps = [ - "$angle_root:libEGL", - "$angle_root/util:angle_util", - ] -} +import("../../src/tests/angle_traces.gni") angle_trace("capture_replay_sample_trace") { _trace = "angle_capture" @@ -21,5 +14,4 @@ angle_trace("capture_replay_sample_trace") { "$_trace.json", "$_trace.angledata.gz", ] - fixture = ":angle_capture_replay_sample_fixture" } diff --git a/samples/capture_replay/CaptureReplay.cpp b/samples/capture_replay/CaptureReplay.cpp index ae270b95cd2..362f7a65921 100644 --- a/samples/capture_replay/CaptureReplay.cpp +++ b/samples/capture_replay/CaptureReplay.cpp @@ -26,7 +26,7 @@ class CaptureReplaySample : public SampleApplication bool initialize() override { - mTraceLibrary.reset(new angle::TraceLibrary("capture_replay_sample_trace")); + mTraceLibrary.reset(new angle::TraceLibrary("capture_replay_sample_trace", mTraceInfo, "")); assert(mTraceLibrary->valid()); std::stringstream binaryPathStream; diff --git a/samples/capture_replay/angle_trace_gl.h b/samples/capture_replay/angle_trace_gl.h deleted file mode 100644 index 12795b7b2dd..00000000000 --- a/samples/capture_replay/angle_trace_gl.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// Copyright 2020 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. -// -// Sets up the GL bindings for capture_replay_sample - -#ifndef ANGLE_TRACE_GL_H_ -#define ANGLE_TRACE_GL_H_ - -#include "trace_fixture.h" -#include "util/util_gl.h" - -#endif // ANGLE_TRACE_GL_H_ diff --git a/samples/multiview/Multiview.cpp b/samples/multiview/Multiview.cpp index 02ab9180297..4a1c836e42a 100644 --- a/samples/multiview/Multiview.cpp +++ b/samples/multiview/Multiview.cpp @@ -68,7 +68,7 @@ class MultiviewSample : public SampleApplication // initialization. const char *allExtensions = reinterpret_cast(glGetString(GL_EXTENSIONS)); const std::string paddedExtensions = std::string(" ") + allExtensions + std::string(" "); - if ((paddedExtensions.find(std::string(" GL_OVR_multiview2 ")) == std::string::npos) && + if ((paddedExtensions.find(std::string(" GL_OVR_multiview2 ")) == std::string::npos) || (paddedExtensions.find(std::string(" GL_OVR_multiview ")) == std::string::npos)) { std::cout << "GL_OVR_multiview(2) is not available." << std::endl; diff --git a/samples/shader_translator/shader_translator.cpp b/samples/shader_translator/shader_translator.cpp index e977bb660e0..6ccfc7c984e 100644 --- a/samples/shader_translator/shader_translator.cpp +++ b/samples/shader_translator/shader_translator.cpp @@ -114,6 +114,9 @@ int main(int argc, char *argv[]) case 'u': printActiveVariables = true; break; + case 'r': + compileOptions.useIR = true; + break; case 's': if (argv[0][2] == '=') { @@ -141,22 +144,13 @@ int main(int argc, char *argv[]) } break; case 'w': - if (argv[0][4] == '3') - { - spec = SH_WEBGL3_SPEC; - } - else if (argv[0][4] == '2') + if (argv[0][4] == '2') { spec = SH_WEBGL2_SPEC; } - else if (argv[0][4] == 'n') - { - spec = SH_WEBGL_SPEC; - } else { - spec = SH_WEBGL_SPEC; - resources.FragmentPrecisionHigh = 1; + spec = SH_WEBGL_SPEC; } break; default: @@ -200,6 +194,10 @@ int main(int argc, char *argv[]) break; case 'm': output = SH_MSL_METAL_OUTPUT; + compileOptions.initializeUninitializedLocals = true; + compileOptions.forceDeferNonConstGlobalInitializers = true; + compileOptions.clampPointSize = true; + compileOptions.removeInactiveVariables = true; break; default: failCode = EFailUsage; @@ -244,7 +242,6 @@ int main(int argc, char *argv[]) case 'g': resources.EXT_frag_depth = 1; break; case 'l': resources.EXT_shader_texture_lod = 1; break; case 'f': resources.EXT_shader_framebuffer_fetch = 1; break; - case 'n': resources.NV_shader_framebuffer_fetch = 1; break; case 'a': resources.ARM_shader_framebuffer_fetch = 1; break; case 'm': resources.OVR_multiview2 = 1; @@ -254,6 +251,7 @@ int main(int argc, char *argv[]) break; case 'y': resources.EXT_YUV_target = 1; break; case 's': resources.OES_sample_variables = 1; break; + case 't': resources.EXT_fragment_shading_rate = 1; break; default: failCode = EFailUsage; } // clang-format on @@ -440,12 +438,12 @@ void usage() " -i : print intermediate tree\n" " -o : print translated code\n" " -u : print active attribs, uniforms, varyings and program outputs\n" + " -r : use the IR instead of AST\n" " -s=e2 : use GLES2 spec (this is by default)\n" " -s=e3 : use GLES3 spec\n" " -s=e31 : use GLES31 spec (in development)\n" " -s=e32 : use GLES32 spec (in development)\n" " -s=w : use WebGL 1.0 spec\n" - " -s=wn : use WebGL 1.0 spec with no highp support in fragment shaders\n" " -s=w2 : use WebGL 2.0 spec\n" " -b=e : output GLSL ES code (this is by default)\n" " -b=g : output GLSL code (compatibility profile)\n" @@ -454,7 +452,7 @@ void usage() " -b=v : output Vulkan SPIR-V code\n" " -b=h9 : output HLSL9 code\n" " -b=h11 : output HLSL11 code\n" - " -b=m : output MSL code (direct)\n" + " -b=m : output MSL code\n" " -x=i : enable GL_OES_EGL_image_external\n" " -x=d : enable GL_OES_EGL_standard_derivatives\n" " -x=r : enable ARB_texture_rectangle\n" @@ -463,11 +461,11 @@ void usage() " -x=g : enable EXT_frag_depth\n" " -x=l : enable EXT_shader_texture_lod\n" " -x=f : enable EXT_shader_framebuffer_fetch\n" - " -x=n : enable NV_shader_framebuffer_fetch\n" " -x=a : enable ARM_shader_framebuffer_fetch\n" " -x=m : enable OVR_multiview\n" " -x=y : enable YUV_target\n" - " -x=s : enable OES_sample_variables\n"); + " -x=s : enable OES_sample_variables\n" + " -x=t : enable EXT_fragment_shading_rate\n"); // clang-format on } diff --git a/scripts/angle_presubmit_utils_unittest.py b/scripts/angle_presubmit_utils_unittest.py index 5b30c2f6e87..0227ac41994 100755 --- a/scripts/angle_presubmit_utils_unittest.py +++ b/scripts/angle_presubmit_utils_unittest.py @@ -42,7 +42,7 @@ def test_correct_commit_message(self): b -Bug: angleproject:4662 +Bug: angleproject:42263262 Change-Id: I966c79d96175da9eee92ef6da20db50d488137b2 """ errors = self.run_check_commit_message_formatting(commit_msg) diff --git a/scripts/code_generation_hashes/ANGLE_format.json b/scripts/code_generation_hashes/ANGLE_format.json index 6d12fc3a226..50616083eca 100644 --- a/scripts/code_generation_hashes/ANGLE_format.json +++ b/scripts/code_generation_hashes/ANGLE_format.json @@ -1,14 +1,14 @@ { "src/libANGLE/renderer/FormatID_autogen.h": - "269e897fc2970ac9d438b2583fa6c4b4", + "2b5ac80521dc3ea477b9c748d48da95d", "src/libANGLE/renderer/Format_table_autogen.cpp": - "e57370a05f8b007f7d8e905c453bf389", + "21e0b0aa9ce772d528e7063ee94cede7", "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/angle_format_data.json": - "6adbfb39f9462db21c9f8632035ba4f6", + "f82d30f65cebd8c787ac0d29fa4c0221", "src/libANGLE/renderer/angle_format_map.json": - "135d70465df3e9b8535f15d3daee38ac", + "abad08e462a0839d1600d83f83bcad8b", "src/libANGLE/renderer/gen_angle_format_table.py": - "5dc62611df0c3498b12449185b7ccd6b" + "7e24f29bf1832274c06f6e74080ea363" } diff --git a/scripts/code_generation_hashes/ANGLE_load_functions_table.json b/scripts/code_generation_hashes/ANGLE_load_functions_table.json index 29b93cb5526..ec85f681d32 100644 --- a/scripts/code_generation_hashes/ANGLE_load_functions_table.json +++ b/scripts/code_generation_hashes/ANGLE_load_functions_table.json @@ -4,7 +4,7 @@ "src/libANGLE/renderer/gen_load_functions_table.py": "73e96775a0bd1a424f3f8585b1c5175f", "src/libANGLE/renderer/load_functions_data.json": - "ebabc981d90d247eeead445b4cf16920", + "b0768c4acab248a4bb842549c24ff003", "src/libANGLE/renderer/load_functions_table_autogen.cpp": - "cd276ead562319efba0a6c8e6ff2982f" + "fb42daa27b45b30a8699557ca367f571" } diff --git a/scripts/code_generation_hashes/ANGLE_shader_preprocessor.json b/scripts/code_generation_hashes/ANGLE_shader_preprocessor.json index 4bac11cb1b3..de0ca8f7798 100644 --- a/scripts/code_generation_hashes/ANGLE_shader_preprocessor.json +++ b/scripts/code_generation_hashes/ANGLE_shader_preprocessor.json @@ -4,13 +4,13 @@ "src/compiler/preprocessor/generate_parser.py": "9a4588fdf009298fe49c52b9252789c7", "src/compiler/preprocessor/preprocessor.l": - "31b4f8bc0bb8f713f5e4db8ae04925e2", + "dc2261e73ea92b35d68d69748c341319", "src/compiler/preprocessor/preprocessor.y": - "770be78579281bd332f2277dcd3be7d3", + "8e4f866302395b2e2e504d8f079a6631", "src/compiler/preprocessor/preprocessor_lex_autogen.cpp": - "39caf992f2baeb3de0198a216ac71951", + "c58edcc71ed87ab9613539a3acd5e194", "src/compiler/preprocessor/preprocessor_tab_autogen.cpp": - "3f39a629435b363bb4b9d24cecf2b13d", + "000f93c6b244dcae862efa319a737a7f", "tools/flex-bison/linux/bison.sha1": "dfc9209e0c76eddd9bed0601c6c189e5", "tools/flex-bison/linux/flex.sha1": diff --git a/scripts/code_generation_hashes/ANGLE_shader_translator.json b/scripts/code_generation_hashes/ANGLE_shader_translator.json index 9a9b1eaf78c..28eca37ab78 100644 --- a/scripts/code_generation_hashes/ANGLE_shader_translator.json +++ b/scripts/code_generation_hashes/ANGLE_shader_translator.json @@ -4,13 +4,13 @@ "src/compiler/translator/generate_parser.py": "ad919972a040d9b3b4aa5dc547fadc75", "src/compiler/translator/glslang.l": - "10643e0be402c2a893bed3c4c145c09a", + "acb74a06d21b8835358767235beb969a", "src/compiler/translator/glslang.y": - "53e0a7272e498302d2b08726397bddd3", + "c1e72fcb5ff3371f21e66092351059bd", "src/compiler/translator/glslang_lex_autogen.cpp": - "d5937e319642f70e625963617ac20ec7", + "47e19f00c1734935c48daffb011ff7f2", "src/compiler/translator/glslang_tab_autogen.cpp": - "e5f75ae62fef9ba4e284a67c46690dde", + "a678256fe6caaa595b5ab4e40453baa4", "src/compiler/translator/glslang_tab_autogen.h": "028bdaebf359aefbcdaafae466993ebe", "tools/flex-bison/linux/bison.sha1": diff --git a/scripts/code_generation_hashes/D3D11_format.json b/scripts/code_generation_hashes/D3D11_format.json index f4ec7054b0d..90fadc66329 100644 --- a/scripts/code_generation_hashes/D3D11_format.json +++ b/scripts/code_generation_hashes/D3D11_format.json @@ -4,9 +4,9 @@ "src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py": "70dcd2607cd481f450233c7c2b5c7ac0", "src/libANGLE/renderer/d3d/d3d11/texture_format_data.json": - "c33d9f61426be6ea8088f1348ee51f29", + "4538ef526c5a801d4a079a6166488899", "src/libANGLE/renderer/d3d/d3d11/texture_format_map.json": - "e936d9e4ececaeaebcd6e318c25776cb", + "60005ea7dd15a4e18e6156bc88e0a08e", "src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp": - "fa174e8ec537a19ee6d4e096964e5755" + "94f09f3702c5778f71f91cbde142912d" } diff --git a/scripts/code_generation_hashes/DXGI_format.json b/scripts/code_generation_hashes/DXGI_format.json index c71b9a573b4..648d43d8075 100644 --- a/scripts/code_generation_hashes/DXGI_format.json +++ b/scripts/code_generation_hashes/DXGI_format.json @@ -2,7 +2,7 @@ "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/angle_format_map.json": - "135d70465df3e9b8535f15d3daee38ac", + "abad08e462a0839d1600d83f83bcad8b", "src/libANGLE/renderer/dxgi_format_data.json": "3428e4761ccd05f960adffd6ccbd86c5", "src/libANGLE/renderer/dxgi_format_map_autogen.cpp": diff --git a/scripts/code_generation_hashes/DXGI_format_support.json b/scripts/code_generation_hashes/DXGI_format_support.json index 591fb7eaf57..722422b9ace 100644 --- a/scripts/code_generation_hashes/DXGI_format_support.json +++ b/scripts/code_generation_hashes/DXGI_format_support.json @@ -2,7 +2,7 @@ "src/libANGLE/renderer/dxgi_support_data.json": "861037ff2340dd52e713c7b7283609bd", "src/libANGLE/renderer/dxgi_support_table_autogen.cpp": - "220fadac8434f87259bc47c1473a309d", + "e0aa29cf32d8ba4e3c35186a0b064bb8", "src/libANGLE/renderer/gen_dxgi_support_tables.py": - "7f015104b9124627d3e962972284e507" + "0f29170ec8d8027a28b4335d5adf5e51" } diff --git a/scripts/code_generation_hashes/Extension_files.json b/scripts/code_generation_hashes/Extension_files.json index e1ea0a02ed0..cd3d1104011 100644 --- a/scripts/code_generation_hashes/Extension_files.json +++ b/scripts/code_generation_hashes/Extension_files.json @@ -1,8 +1,8 @@ { "doc/ExtensionSupport.md": - "9fedcc1a67af79d93c2da1105c9bada6", + "d2b01c702e39ac3612900dc9777d4676", "scripts/egl_angle_ext.xml": - "d9434b5d3dc4842f02bbb06f54fb7e02", + "676627eae49a3ccadeafc3adbd7dba8d", "scripts/extension_data/intel_630_linux.json": "3b86832de6a7095f4617e273cba6d45e", "scripts/extension_data/intel_630_win10.json": @@ -20,23 +20,23 @@ "scripts/extension_data/swiftshader_win10_gles1.json": "bea8e2106d62e1ea0e8938f150865a37", "scripts/gl_angle_ext.xml": - "ef111314bcf6e8c9cdc1a391080f1d80", + "da4ecccdd77635f1b0e9d4664f856706", "scripts/registry_xml.py": - "b4b40cf6f60ec0b2e8ef27dae59cfd91", + "b51290658fa62298178113925375d125", "src/libANGLE/gen_extensions.py": - "6ea1cb1733c4df98b527bbf2752e118b", + "dc4727460d1ece9f98a2ae47bf15ddb3", "src/libANGLE/gles_extensions_autogen.cpp": - "9004e1c1ac5eeacf9d75f5764f3fd067", + "8c4b8868adbb82eab4206af5f764703e", "src/libANGLE/gles_extensions_autogen.h": - "c9de395d8071f8f7548b55ed081bc224", + "0f54916907002fa66d5ac3a61429e1a6", "third_party/EGL-Registry/src/api/egl.xml": "2056d54ea07156f1988ca1366bdee21a", "third_party/OpenCL-Docs/src/xml/cl.xml": - "6d0bf09e20a8f8c3ae440d79eda08bf9", + "3c93f136de5049f4d9eca8240df1a025", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23", + "00c18abda09593ce770fd184bd8f6255", "third_party/OpenGL-Registry/src/xml/glx.xml": - "94f3eee4b076801d117804eb466714b7", + "649f24094c1938779ada7db2dc092d35", "third_party/OpenGL-Registry/src/xml/wgl.xml": - "eae784bf4d1b983a42af5671b140b7c4" + "da69debd6646f79119fcdaaf5969af2f" } 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 576c469331a..4080633a127 100644 --- a/scripts/code_generation_hashes/GL_CTS_(dEQP)_build_files.json +++ b/scripts/code_generation_hashes/GL_CTS_(dEQP)_build_files.json @@ -6,7 +6,7 @@ "src/tests/deqp_support/deqp_data_autogen.gni": "ee142f516fad1d6aa58ac8dc4b01ef32", "third_party/VK-GL-CTS/src/CMakeLists.txt": - "e1afa52c02a9940d9f97f0327514aecb", + "98cf61f26f931dd24bf3549804311265", "third_party/VK-GL-CTS/src/execserver/CMakeLists.txt": "38aa187592e6ef9a331fc1ea313fc68d", "third_party/VK-GL-CTS/src/executor/CMakeLists.txt": @@ -14,23 +14,23 @@ "third_party/VK-GL-CTS/src/external/amber/CMakeLists.txt": "8871068a2efa10bdce22d5a8588db7ab", "third_party/VK-GL-CTS/src/external/glslang/CMakeLists.txt": - "8fe044812319323f80490fae1afe384d", + "b0da94442d79f9cb782e4a6be74fa6a4", "third_party/VK-GL-CTS/src/external/jsoncpp/CMakeLists.txt": "80cd4f898f759cebdeaa46552fcedddb", "third_party/VK-GL-CTS/src/external/libpng/CMakeLists.txt": - "f0a31a5d1edcf912eea4668abf8c9c27", - "third_party/VK-GL-CTS/src/external/nvidia-video-samples/CMakeLists.txt": - "39ddc46154899c046b493f0b41108155", + "fb1d65fa30f92dc2368c8d952947e95e", "third_party/VK-GL-CTS/src/external/openglcts/CMakeLists.txt": "eb5ba40db4ae92a7ced48b16329afbb6", "third_party/VK-GL-CTS/src/external/openglcts/modules/CMakeLists.txt": "6b87a3cf65a8eb5506a87fa1049e752e", "third_party/VK-GL-CTS/src/external/openglcts/modules/common/CMakeLists.txt": - "836411fe1b612af9e3bef5ce01c1f251", + "397e09a957da589ffd561a4d30bcab6d", + "third_party/VK-GL-CTS/src/external/openglcts/modules/common/meshShader/CMakeLists.txt": + "04532172e252ad28f96de597586cf073", "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": - "1f1f826b0873c4f727f11f37e4d58960", + "6ea9e3f13f5f653627d793fd23a9b734", "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": @@ -46,27 +46,31 @@ "third_party/VK-GL-CTS/src/external/spirv-tools/CMakeLists.txt": "cca8b4b984c40afb9880d177d53623a1", "third_party/VK-GL-CTS/src/external/video_generator/CMakeLists.txt": - "72cbf91bf77673ed6af486ba371d186a", + "b1160ff12fbe868ec874a8510e94b537", "third_party/VK-GL-CTS/src/external/vulkan-validationlayers/CMakeLists.txt": - "0e910d92ced28115d4c7995daa81d464", + "53b56df74a8a4ac5ae1cedcbb1ff440f", "third_party/VK-GL-CTS/src/external/vulkan-video-samples/CMakeLists.txt": - "aa653441a7ad71ee278dccd76e66e8e2", + "55c84ac02cec3c779c0f13b4e258b249", "third_party/VK-GL-CTS/src/external/vulkancts/framework/vulkan/CMakeLists.txt": - "9673f963428d8ccba673da38c1e8d28f", + "0d72e65375aa0cd53bb0472e533f9499", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/CMakeLists.txt": - "578ee44956963be94f77c9a486236c70", + "7246051890748c5e644b13b4f4deaab0", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/amber/CMakeLists.txt": "51aed6000e6c76f2e4a5922e48841885", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/api/CMakeLists.txt": - "ac1044c23792172ff8457b4480beebb8", + "68ceee73a3815f955bdc709800ff0d2e", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/binding_model/CMakeLists.txt": - "bb50f14b3079e93ffd17ee15d513ad3b", + "ba186233f15df714529b476e82e08651", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/clipping/CMakeLists.txt": "2341f788b087bc78e89f66446fdad59b", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/compute/CMakeLists.txt": - "1a19805e1ecf7cea517d5ff5a8da4858", + "45c0c14e37959ad81c05c6e276a121e2", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/conditional_rendering/CMakeLists.txt": "933be687f555f0fe1dc061c270cc9aa6", + "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/cooperative_vector/CMakeLists.txt": + "7c0e5da40f80c2b1045cc16fc70b893c", + "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/data_graph/CMakeLists.txt": + "59ab713400bedf547332a2fd8fb887a4", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/descriptor_indexing/CMakeLists.txt": "86aa073130ad92896be00745532d9bc7", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/device_generated_commands/CMakeLists.txt": @@ -74,7 +78,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": - "447b6ea2e4299ca451a9c3ca7d56d3db", + "818867011729459b85e7d20dfa47c6e5", "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": @@ -86,13 +90,15 @@ "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/fragment_shading_rate/CMakeLists.txt": "70bd1230fad695239b2a5e9019737eaf", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/geometry/CMakeLists.txt": - "0d0cf6c5e43e63f73dbba0a511a50127", + "335903779295e9652fdfccde1f9a2078", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/image/CMakeLists.txt": - "7ed45010ceb8d734b023c3f0961d8432", + "a81aea82a145ab03d30574f8acca8387", + "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/image_processing/CMakeLists.txt": + "2a5340e24a562a513a4a4223b02c66c0", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/imageless_framebuffer/CMakeLists.txt": "62bd75a001d0e25016bcac31c1fbbfa8", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/memory/CMakeLists.txt": - "dd04b5a4b297ac37d6605124f998846a", + "4b5315a52a1669aa9bf075ca63c91fdb", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/memory_model/CMakeLists.txt": "e3000d0283ba5aa213921ef32c707b64", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/mesh_shader/CMakeLists.txt": @@ -102,63 +108,65 @@ "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/multiview/CMakeLists.txt": "e426e46a5ad0be2fbc7391bb6d9efc75", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt": - "d19bc9caa7d1b63a554ddf83e26cb17e", + "947a6a670de84e00984ad8a334f8e0f7", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/postmortem/CMakeLists.txt": "701b4a0c61cf94fa3cf44a6017496562", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/protected_memory/CMakeLists.txt": - "1738f389adb6a46eae4f560ccd3152a3", + "57966bb46c3156d090443753a38ee0ac", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/query_pool/CMakeLists.txt": - "1d99f4cebbacb0edb7dfd203fd8673b3", + "6fd3194185b50f25949aa0635cbebeeb", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/rasterization/CMakeLists.txt": "20691d4d355ac09d18b98f0c8e184842", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/ray_query/CMakeLists.txt": "e2e1ca16288794542a6da7d323bc2844", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/ray_tracing/CMakeLists.txt": - "a3fe4df3df9d1d8e72a61e0b1c46aafc", + "f12ad2a6e94d6d6e5d51d7c0db39019a", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/reconvergence/CMakeLists.txt": - "3abf06b8ce76c42dcf124976ab7babdc", + "c00ddc8833c41b98d0d70e2067f1c08b", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/renderpass/CMakeLists.txt": - "0c03fd5d6b8c50357f1b43c0d5316bcf", + "1f559bc7c9a4500b5bb756a24ea82ef6", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/robustness/CMakeLists.txt": "8c4ca66cc48131ed0d1380e13d44b6e7", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/sc/CMakeLists.txt": "59984e5eeb9a42789bd499b24b45fdc9", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/shader_object/CMakeLists.txt": - "c871efdd1959d74856c9794060052bdc", + "5992d8d787569663fcf4c780c19b0cdc", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/shaderexecutor/CMakeLists.txt": - "e1526d49f318a8a3151d582f5f3936f8", + "b454631bc58923238e5e3eedd4fe496c", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/shaderrender/CMakeLists.txt": "aed26ad8bba3ae469bde60b6fccc5d4e", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/sparse_resources/CMakeLists.txt": "965e2b61b0d71a751dedafc771f9a6b2", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt": - "ce6706cc64bf343e7cf5a89d2f08a7aa", + "7a72eb5791e8a9c488b65679e35572df", "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": "5da8e2fa227c4f18504e4b511e1390e7", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/synchronization/CMakeLists.txt": - "919208da9517f0897deb1c1c30c44eeb", + "5063053b90d085e7c49b248a7b52e6f1", + "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/tensor/CMakeLists.txt": + "e9b17dee83247c5dd83a3aebe8ac8b31", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/tessellation/CMakeLists.txt": - "bad6a711b7ad4c5eed405cc17f945fd9", + "ce33d79ab4c6522f0d25db75c7959089", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/texture/CMakeLists.txt": "12a01bae782a7fb371d76d4d943e680f", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/transform_feedback/CMakeLists.txt": - "62142047c88ec2d75708c32604941f98", + "9beae6ed8f1fbd14c7351184065a4a99", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/ubo/CMakeLists.txt": "b19406c9adcf4f085868da42a6910ee5", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/util/CMakeLists.txt": - "0ada8dd61fde51afc6c1313002489cc4", + "91d17e85771f10651a62d757da9e1bb1", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/video/CMakeLists.txt": - "1d57751c722ec6543bf8bf2f5594a632", + "16d70b88bf38e860c1ec9e2f95033c60", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/wsi/CMakeLists.txt": - "4b9b02f3fab98243826e777c3e71e340", + "e6619704db1d40d80aba3fa22e2587c3", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/ycbcr/CMakeLists.txt": - "74c13265acc58f025f8428179a668eaf", + "0ef63427b2fb168abd931ae5966f7200", "third_party/VK-GL-CTS/src/external/vulkancts/vkscpc/CMakeLists.txt": "b1e0a3495cabd10a8020bf0aa2635ee1", "third_party/VK-GL-CTS/src/external/vulkancts/vkscserver/CMakeLists.txt": - "9e662101f6be2a7029a0fbfda671eab9", + "8e3c3d8286a007fcad20f46031df5c76", "third_party/VK-GL-CTS/src/external/zlib/CMakeLists.txt": "30ffe3a360ab8870fe103084e9947e6d", "third_party/VK-GL-CTS/src/framework/CMakeLists.txt": @@ -190,7 +198,7 @@ "third_party/VK-GL-CTS/src/framework/opengl/wrapper/CMakeLists.txt": "31a7adfb6e907b53ef24bb6ea044b838", "third_party/VK-GL-CTS/src/framework/platform/CMakeLists.txt": - "e478854223edfe5bb698fa663a8141cb", + "2ef789461e96c0ec31c5cca0a3af9c14", "third_party/VK-GL-CTS/src/framework/qphelper/CMakeLists.txt": "4118a22199375e743dee74afda146f55", "third_party/VK-GL-CTS/src/framework/randomshaders/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 b8af653da33..17a948ec24a 100644 --- a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json +++ b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json @@ -1,44 +1,44 @@ { "scripts/egl_angle_ext.xml": - "d9434b5d3dc4842f02bbb06f54fb7e02", + "676627eae49a3ccadeafc3adbd7dba8d", "scripts/generate_loader.py": "93c78a8d11323fa311fed5118fbcf083", "scripts/gl_angle_ext.xml": - "ef111314bcf6e8c9cdc1a391080f1d80", + "da4ecccdd77635f1b0e9d4664f856706", "scripts/registry_xml.py": - "b4b40cf6f60ec0b2e8ef27dae59cfd91", + "b51290658fa62298178113925375d125", "src/libEGL/egl_loader_autogen.cpp": - "ab0ad32d623096b4a166c7bf5bf2561c", + "2aca2a57c51fc2b1c7e1da0a7ccf6107", "src/libEGL/egl_loader_autogen.h": - "a654f2dbdd5b1b343a478f8ecaf84fc5", + "bde0152d45cd681ab4e416a362a391d8", "third_party/EGL-Registry/src/api/egl.xml": "2056d54ea07156f1988ca1366bdee21a", "third_party/OpenCL-Docs/src/xml/cl.xml": - "6d0bf09e20a8f8c3ae440d79eda08bf9", + "3c93f136de5049f4d9eca8240df1a025", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23", + "00c18abda09593ce770fd184bd8f6255", "third_party/OpenGL-Registry/src/xml/glx.xml": - "94f3eee4b076801d117804eb466714b7", + "649f24094c1938779ada7db2dc092d35", "third_party/OpenGL-Registry/src/xml/wgl.xml": - "eae784bf4d1b983a42af5671b140b7c4", + "da69debd6646f79119fcdaaf5969af2f", "util/capture/trace_egl_loader_autogen.cpp": - "ea51900ee6b290c8a6ef1674ccc17224", + "a05c41eb1cc6e24c006cb3f462b694cf", "util/capture/trace_egl_loader_autogen.h": - "446416d576c66d5d9f0a709d27463879", + "9adc81af729078b16b36647f02401342", "util/capture/trace_gles_loader_autogen.cpp": - "a1f5589204c04a128bec7cc37c09e618", + "3876b50ba3bfd5eea4ee3dd798420eeb", "util/capture/trace_gles_loader_autogen.h": - "d6b1848250c6a21c592491cc2f365f58", + "5407015ec6041702781d42a03fe73c6b", "util/egl_loader_autogen.cpp": - "1a25333935b4ead43a58ccdbffc7f253", + "ae6abfc6c2c0a997ad59258dfc0339ce", "util/egl_loader_autogen.h": - "8ab5beca6edba8c395561bb0af452029", + "ea5f73048616a6fc80eaa7e93ef5f0ce", "util/gles_loader_autogen.cpp": - "21ba5e7139e81e9be425c5cacd0bb6b3", + "47b1b799443f34be7b48bffb54e95707", "util/gles_loader_autogen.h": - "01b1448da6ebd2bdd16e2bea5de9f273", + "4f9632d1df33e322a0f5c3c8bba4857a", "util/windows/wgl_loader_autogen.cpp": "373b062587eab8a163121255f54597dc", "util/windows/wgl_loader_autogen.h": - "788190d21890b3ded845acb5ccbfb7ad" + "0551e9c28a8d3902bcd5d6e5b1ed3c6f" } diff --git a/scripts/code_generation_hashes/GL_EGL_entry_points.json b/scripts/code_generation_hashes/GL_EGL_entry_points.json index d4d1718c4bf..f69fc8846bb 100644 --- a/scripts/code_generation_hashes/GL_EGL_entry_points.json +++ b/scripts/code_generation_hashes/GL_EGL_entry_points.json @@ -1,156 +1,160 @@ { "scripts/egl_angle_ext.xml": - "d9434b5d3dc4842f02bbb06f54fb7e02", + "676627eae49a3ccadeafc3adbd7dba8d", "scripts/entry_point_packed_egl_enums.json": "a72ae855c6b403912103b519139951a1", "scripts/entry_point_packed_gl_enums.json": - "57a3a729fd25032bc336f4b6a55bc238", + "cc42c7d7f13b0ba7966c84629f735299", "scripts/generate_entry_points.py": - "80a3624043df68434f5e1c84a0d1d921", + "59ec4bdb9cf0e4b4e23e73ac4aaf92ca", "scripts/gl_angle_ext.xml": - "ef111314bcf6e8c9cdc1a391080f1d80", + "da4ecccdd77635f1b0e9d4664f856706", "scripts/registry_xml.py": - "b4b40cf6f60ec0b2e8ef27dae59cfd91", + "b51290658fa62298178113925375d125", "src/common/entry_points_enum_autogen.cpp": - "755a7ec4d1ca69a84bf1695836fcd686", + "af2c99f1c7985989ba081c650a334931", "src/common/entry_points_enum_autogen.h": - "fbd372da9149983b866410f42f6bcd52", + "cb0ff7c85496371bd5f352575a0092f9", "src/common/frame_capture_utils_autogen.cpp": - "db55ec842aec79363576562452b45345", + "bb721e6effc5e61430f703bcf0253e4b", "src/common/frame_capture_utils_autogen.h": - "148cf5965be2aa1a3611e085a3d576eb", + "356c0711206b1ce487e833ecd6de6b8c", "src/libANGLE/Context_gles_1_0_autogen.h": "cb1cfe652972d301a5a98b4f233fcc4f", "src/libANGLE/Context_gles_2_0_autogen.h": - "bf03a51e6a27817e503bb822868d290e", + "63f297a21ff3d1ef014595d70e7f94ae", "src/libANGLE/Context_gles_3_0_autogen.h": - "d1697421290173be5ca0bc236fd479b4", + "6f7e3f65e013135786455ea33b197e07", "src/libANGLE/Context_gles_3_1_autogen.h": - "17b51301bb3edd475460e8e77ff21a1c", + "2b81a1dd0d3109090afc073417e0667c", "src/libANGLE/Context_gles_3_2_autogen.h": "cf9900e0067812fc6773e8ae4664da33", "src/libANGLE/Context_gles_ext_autogen.h": - "b2937a9e8393aeaa54b51fecfd029fd0", + "5ea5e2f858797e3400d4eb64ce10f5d2", "src/libANGLE/capture/capture_cl_autogen.cpp": - "fa6bf9530e2f1176decc6ceeaf7e3280", + "976ccf189abddcec11650a06d01679eb", "src/libANGLE/capture/capture_cl_autogen.h": - "b5a611a88b8f373d08c7ce29a4efdb64", + "ff5f05c3dd18774b3cf825b19c892b4e", "src/libANGLE/capture/capture_egl_autogen.cpp": - "8e026593627ed754e6268d6d6a7646eb", + "1b7c8ea9a5b7e19b4d9a44cdf366c306", "src/libANGLE/capture/capture_egl_autogen.h": - "ebf5190d63dc0b598bb93010279cae04", + "dddceb4900dd072f9bb9769c5996f71c", "src/libANGLE/capture/capture_gles_1_0_autogen.cpp": - "d203de86be595ac05578ef01b362380a", + "5f1d416dd6acdcc179a9d7c483b6713c", "src/libANGLE/capture/capture_gles_1_0_autogen.h": - "775d4c0d246b7674ab9e7c55b7f8183d", + "c491c1c8946a6468b59ac8bd5b9936c6", "src/libANGLE/capture/capture_gles_2_0_autogen.cpp": - "94f04888c6130a39539bcd7cef1244ff", + "d786d29fd1eee94f0017746ffe0af9f0", "src/libANGLE/capture/capture_gles_2_0_autogen.h": - "ad9709f556ceae4366dcff4435eab1ca", + "6c3bc3178fc40812046db9f4fe2d9ea6", "src/libANGLE/capture/capture_gles_3_0_autogen.cpp": - "6705cab4f78501fcbca133b169671037", + "93dc571c08e4e3f662175aea973abb3f", "src/libANGLE/capture/capture_gles_3_0_autogen.h": - "2363abe832f4f2cd4222194dc48cb53c", + "7ab8068b67babf2f724b58f7ac9e7d44", "src/libANGLE/capture/capture_gles_3_1_autogen.cpp": - "a266d12eab9874144d2c948755ee1b76", + "8a3c6f80cee730b0f45f21764697c8ec", "src/libANGLE/capture/capture_gles_3_1_autogen.h": - "7a437f522813a83b7b62a4dc5ffec73b", + "23487bac6dc9f9ffbf9eb599886c163c", "src/libANGLE/capture/capture_gles_3_2_autogen.cpp": - "7e6560b176108a579e281f727d75c410", + "6242d3fd743f910fabeb8756d593e048", "src/libANGLE/capture/capture_gles_3_2_autogen.h": - "5e956a19d9e3ba697fb05049c4be9936", + "2d0a452821504aac6c071f365282634d", "src/libANGLE/capture/capture_gles_ext_autogen.cpp": - "3b524b6fa03d9b959bbf4c2a06a91acd", + "acda0e8856686f6dd7462c0cdef63f55", "src/libANGLE/capture/capture_gles_ext_autogen.h": - "476b2dab23171b35b15f54c0108a2cd6", + "9aedc6498cec446617400afcacd0d63e", "src/libANGLE/context_private_call_autogen.h": - "faa8cc9fc573c8f138d6c057a50467be", + "82434f431a5851ec2168f8517329de82", "src/libANGLE/validationCL_autogen.h": - "0022d0cdb6a9e2ef4a59b71164f62333", + "d982f26ddeb70e0d4983625e9e83a1ef", "src/libANGLE/validationEGL_autogen.h": - "86c3a85276a68f897d06c1edb4d9c7a0", + "7723ac082391488cb95958e42db221ff", "src/libANGLE/validationES1_autogen.h": - "06762456388a02b9258d6262c1bf4a1b", + "66b46adeff0788563f81a89b4c620bd2", "src/libANGLE/validationES2_autogen.h": - "42a3c5a51ed936d5e47ab08ef2a17c9e", + "5bb6268a17bed5eedd8f8924ea1a85e1", "src/libANGLE/validationES31_autogen.h": - "1ed81afa47644b88a05e1e2bd72b3393", + "7de3988b7e07121b005c66eeaf966410", "src/libANGLE/validationES32_autogen.h": - "03fbf790c2db53d5b677747d40f5bbd6", + "67429f628946feab206d1ce9bdcf6fe9", "src/libANGLE/validationES3_autogen.h": - "29b3f384a582a4ffd45a898a481839fd", + "127ed661a38f20de9ba13fa989ce05d8", "src/libANGLE/validationESEXT_autogen.h": - "93bdf643bcc69034ace839c580f11c1a", + "662d53efaf8822310de32ac0b82a9fbf", "src/libEGL/libEGL_autogen.cpp": - "78c9ac6811d5806b4579e6b370e49b86", + "77d82db4a45c2f08108929ef7fe8b698", "src/libEGL/libEGL_autogen.def": - "4281c573e7f5d6da59e448ce5dab71e9", + "01f7efff224d3b48ba9ec640ee350277", + "src/libEGL/libEGL_vulkan_secondaries_autogen.def": + "145504627a80fc96b619ff99981c739e", "src/libGLESv2/cl_stubs_autogen.h": - "90de40afa78b7574558f8514f53dbab8", + "04f3af00f9dad04ab1cb3a85f0563b96", "src/libGLESv2/egl_context_lock_autogen.h": - "30f46f233c3b6ccc94e6240c9c16a3d1", + "8c2f68a26888ff37b5f312763a985b4f", "src/libGLESv2/egl_ext_stubs_autogen.h": - "406bda2d2f4938e3f68873a0943cde81", + "0f6d1f1a0232b02f78b98ad05e8fd1f1", "src/libGLESv2/egl_get_labeled_object_data.json": "2f4148b2ddf34e62670e32c5e6da4937", "src/libGLESv2/egl_stubs_autogen.h": "66ee6957861e78ae4090ef6dd735202a", "src/libGLESv2/entry_points_cl_autogen.cpp": - "68bc14dceb6620ef3502fe114419bb8e", + "2860e28d1c63eb07b16d7d91a5fe4cd8", "src/libGLESv2/entry_points_cl_autogen.h": - "dde2f94c3004874a7da995dae69da811", + "3c4c667a324923ee7049b86712edfedb", "src/libGLESv2/entry_points_egl_autogen.cpp": - "3f9ff6cfe5e1806349884a547c9bc936", + "a23b4dd0aa2568b0b89ff6f29085e562", "src/libGLESv2/entry_points_egl_autogen.h": "3bc7a8df9deadd7cfd615d0cfad0c6a8", "src/libGLESv2/entry_points_egl_ext_autogen.cpp": - "07796746978acbff836ac572dd2e32d4", + "bbb827f65e121629007ae9c9616db40a", "src/libGLESv2/entry_points_egl_ext_autogen.h": - "23ba1a691b535e73279103bf939637f7", + "7799eb7417ec584b9de7480f65f3203c", "src/libGLESv2/entry_points_gles_1_0_autogen.cpp": - "0a3aa3cab080699692a1290306dd54f2", + "2e7de9051c2db9fe853d24c0c4e98eb7", "src/libGLESv2/entry_points_gles_1_0_autogen.h": "1d3aef77845a416497070985a8e9cb31", "src/libGLESv2/entry_points_gles_2_0_autogen.cpp": - "505d868829b560e08a9742a3d1257d94", + "b73fa796d9d1a4fdb6aaf2d7d7d0042f", "src/libGLESv2/entry_points_gles_2_0_autogen.h": "691c60c2dfed9beca68aa1f32aa2c71b", "src/libGLESv2/entry_points_gles_3_0_autogen.cpp": - "6d64891e3ae131677c362c523122f324", + "3d9530b9507f7d1d93f22bf754be1c2c", "src/libGLESv2/entry_points_gles_3_0_autogen.h": "4ac2582759cdc6a30f78f83ab684d555", "src/libGLESv2/entry_points_gles_3_1_autogen.cpp": - "d8de40f06307d617b19b09eb9bf94fe9", + "0abae0743526ce647c686af83eccc84f", "src/libGLESv2/entry_points_gles_3_1_autogen.h": "a7327c330a91665fc31accbb78793b42", "src/libGLESv2/entry_points_gles_3_2_autogen.cpp": - "db95c356d32ec25fad5e63ee70461da3", + "2d3ed63d057ca62ddd0247d6519afe46", "src/libGLESv2/entry_points_gles_3_2_autogen.h": "647f932a299cdb4726b60bbba059f0d2", "src/libGLESv2/entry_points_gles_ext_autogen.cpp": - "5b3b239852b83eb2ff58dab3098211c8", + "7c70a664500fd35f901dec1442217ff1", "src/libGLESv2/entry_points_gles_ext_autogen.h": - "c684000f5cf5edf378e5fffc801a706d", + "236fe730d73c76156216cc5257adfc36", "src/libGLESv2/libGLESv2_autogen.cpp": - "6bc1ef24a4fc8770476f6521e4c66538", + "f805c210144d695ea49fb0c1214f2de8", "src/libGLESv2/libGLESv2_autogen.def": - "6debe0c86b1c9a502a255cf898c40037", + "ec8b6997e8592d3e9ab474e910e6ab84", "src/libGLESv2/libGLESv2_no_capture_autogen.def": - "f638ab0c2c7d089c54cdefacf430ee0f", + "1b210f319145d15cc40312a3d98eb51c", + "src/libGLESv2/libGLESv2_vulkan_secondaries_autogen.def": + "97f38ee2da8d9792d36838b86ac6dc3e", "src/libGLESv2/libGLESv2_with_capture_autogen.def": - "5e43c6ad11c2d5975305ffa4c544bb8d", + "2251d06d952966abba31744ff5b85c39", "src/libOpenCL/libOpenCL_autogen.cpp": - "10849978c910dc1af5dd4f0c815d1581", + "90d52cd2c41f90923309a3c05b2ba98d", "third_party/EGL-Registry/src/api/egl.xml": "2056d54ea07156f1988ca1366bdee21a", "third_party/OpenCL-Docs/src/xml/cl.xml": - "6d0bf09e20a8f8c3ae440d79eda08bf9", + "3c93f136de5049f4d9eca8240df1a025", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23", + "00c18abda09593ce770fd184bd8f6255", "third_party/OpenGL-Registry/src/xml/glx.xml": - "94f3eee4b076801d117804eb466714b7", + "649f24094c1938779ada7db2dc092d35", "third_party/OpenGL-Registry/src/xml/wgl.xml": - "eae784bf4d1b983a42af5671b140b7c4", + "da69debd6646f79119fcdaaf5969af2f", "util/capture/frame_capture_replay_autogen.cpp": - "09525c003676eb78bf7778cd4051a3bc" + "066677ed9ef272c2525aa210d365b8c9" } diff --git a/scripts/code_generation_hashes/GL_format_map.json b/scripts/code_generation_hashes/GL_format_map.json index 42189554dd9..eda4f5c861e 100644 --- a/scripts/code_generation_hashes/GL_format_map.json +++ b/scripts/code_generation_hashes/GL_format_map.json @@ -1,8 +1,8 @@ { "src/libANGLE/es3_format_type_combinations.json": - "91b6c6a3acbd7444639e5d15932d3e1c", + "a1b6346f897ae0a78c900a1a7bf095bc", "src/libANGLE/format_map_autogen.cpp": - "f0e7a624afaeeb8b3d87eea650795208", + "0af6c5aba2a2392d0cd96ef1b0ea3a00", "src/libANGLE/format_map_data.json": "4234d7b249edacad5105d4b049339125", "src/libANGLE/gen_format_map.py": 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 bbc9dcf9d45..7f47fb78bf8 100644 --- a/scripts/code_generation_hashes/GLenum_value_to_string_map.json +++ b/scripts/code_generation_hashes/GLenum_value_to_string_map.json @@ -1,14 +1,14 @@ { "scripts/gen_gl_enum_utils.py": - "3ec60ab12923f4825b57fe183f2152b2", + "12506d2a222614dc840212e20c192450", "scripts/gl_angle_ext.xml": - "ef111314bcf6e8c9cdc1a391080f1d80", + "da4ecccdd77635f1b0e9d4664f856706", "scripts/registry_xml.py": - "b4b40cf6f60ec0b2e8ef27dae59cfd91", + "b51290658fa62298178113925375d125", "src/common/gl_enum_utils_autogen.cpp": - "109224915eb4122569c2fc644e2228e1", + "aa875f38ef9dab5d108f526337cf4a45", "src/common/gl_enum_utils_autogen.h": - "51f421ef562d771b3cded2ad207d0fd9", + "58964ba04f5eb150a03742e62c16ad07", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23" + "00c18abda09593ce770fd184bd8f6255" } diff --git a/scripts/code_generation_hashes/Metal_default_shaders.json b/scripts/code_generation_hashes/Metal_default_shaders.json index a9a75cfde39..504c6e90c97 100644 --- a/scripts/code_generation_hashes/Metal_default_shaders.json +++ b/scripts/code_generation_hashes/Metal_default_shaders.json @@ -2,29 +2,29 @@ "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/angle_format_map.json": - "135d70465df3e9b8535f15d3daee38ac", + "abad08e462a0839d1600d83f83bcad8b", "src/libANGLE/renderer/gen_angle_format_table.py": - "5dc62611df0c3498b12449185b7ccd6b", + "7e24f29bf1832274c06f6e74080ea363", "src/libANGLE/renderer/metal/shaders/blit.metal": "9b3b7c24cd486c0987be24014f0ac427", "src/libANGLE/renderer/metal/shaders/clear.metal": "37ef05208eb5d12110a7d277a4bbcbe1", "src/libANGLE/renderer/metal/shaders/common.h": - "ff51dc3a133f17fd5de671bd82d62c05", + "a86aa849b1363664ba1a7d795fc54a93", "src/libANGLE/renderer/metal/shaders/constants.h": "dad1a869a1095be669b7da5651901d38", "src/libANGLE/renderer/metal/shaders/copy_buffer.metal": - "2cecb97b0c8f12aefb30a75db0d0fc84", + "ea327d8167919b501d66c9a3a9476c10", "src/libANGLE/renderer/metal/shaders/gen_indices.metal": - "b46a137083fb55a3dd2a392494dcf972", + "d640ca6e045c0c2b6d7598619178de3c", "src/libANGLE/renderer/metal/shaders/gen_mipmap.metal": "fab35deec42fd89ae7a11d2f87b6e0b4", "src/libANGLE/renderer/metal/shaders/gen_mtl_internal_shaders.py": "368cb14cf2005e682edc4d4afce8d7b9", "src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_autogen.metal": - "0f3fe1c9fcbbbf7879efe418a31baa94", + "9056c1be9b9afffe12fe0f0bb3f1fce4", "src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_src_autogen.h": - "4a9fa642936e4562194ad3407c4a152a", + "9aedbda4c5d3c6689f606f40c19e1fce", "src/libANGLE/renderer/metal/shaders/rewrite_indices.metal": "a29210b023ed3393e1342d94e338d449", "src/libANGLE/renderer/metal/shaders/visibility.metal": diff --git a/scripts/code_generation_hashes/Metal_format_table.json b/scripts/code_generation_hashes/Metal_format_table.json index 37c0d1eefbd..98e348fb9b8 100644 --- a/scripts/code_generation_hashes/Metal_format_table.json +++ b/scripts/code_generation_hashes/Metal_format_table.json @@ -2,7 +2,7 @@ "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/angle_format_map.json": - "135d70465df3e9b8535f15d3daee38ac", + "abad08e462a0839d1600d83f83bcad8b", "src/libANGLE/renderer/metal/gen_mtl_format_table.py": "2a8e60ae2d6e023dbac430183e3078f8", "src/libANGLE/renderer/metal/mtl_format_map.json": diff --git a/scripts/code_generation_hashes/OpenGL_dispatch_table.json b/scripts/code_generation_hashes/OpenGL_dispatch_table.json index f2ebe7ea033..a5431592247 100644 --- a/scripts/code_generation_hashes/OpenGL_dispatch_table.json +++ b/scripts/code_generation_hashes/OpenGL_dispatch_table.json @@ -2,17 +2,13 @@ "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp": - "44d6dfa7246df490e6004de61e6a8b6a", + "31c088a9f24d58dc3b440412ff1410b1", "src/libANGLE/renderer/gl/DispatchTableGL_autogen.h": - "14b4a321a5cac05dabe7c5675517ef99", + "c076045a5540e6832e725108bfb4169c", "src/libANGLE/renderer/gl/generate_gl_dispatch_table.py": - "4dbeb73a39a0f583c1c52dd25c5fc72f", + "fe318a1678227746748e4d6d5a13aa22", "src/libANGLE/renderer/gl/gl_bindings_data.json": - "440c50f681a956b63def45bf92d9843c", - "src/libANGLE/renderer/gl/null_functions.cpp": - "eb30cd0b6160462b7c28907996fcbde1", - "src/libANGLE/renderer/gl/null_functions.h": - "18d0ed6d25cfb40cea53edadb07d22fa", + "f1e0aff4b484fba636ecef3ba80d2513", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23" + "00c18abda09593ce770fd184bd8f6255" } diff --git a/scripts/code_generation_hashes/SPIR-V_helpers.json b/scripts/code_generation_hashes/SPIR-V_helpers.json index c687594c2f6..4129570d3e4 100644 --- a/scripts/code_generation_hashes/SPIR-V_helpers.json +++ b/scripts/code_generation_hashes/SPIR-V_helpers.json @@ -2,13 +2,13 @@ "src/common/spirv/gen_spirv_builder_and_parser.py": "1f1cb66a2d1668038c013462a4697ac9", "src/common/spirv/spirv_instruction_builder_autogen.cpp": - "32ffef5702224f13b91cb5515cafa70a", + "e6596bf8fec2f50c760d8f0498492b0e", "src/common/spirv/spirv_instruction_builder_autogen.h": - "99b52d72095b5fe4e1bf9bf633c7f3a5", + "4d321c7d60bad27ccd147df8ceba87a8", "src/common/spirv/spirv_instruction_parser_autogen.cpp": - "3dbadba5b7dce543dccd1a703fc29713", + "16f287dd58dc1a4e80d4d788583f5c2a", "src/common/spirv/spirv_instruction_parser_autogen.h": - "9b75df2b61cac8235b62e0b4deb60373", + "6fbf8a4b50e2dc8467df9a64c399589e", "third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json": - "d1a545ccd7ae4f610857abc91889c981" + "f73129dc6d2e742113957c51a9037b29" } diff --git a/scripts/code_generation_hashes/Static_builtins.json b/scripts/code_generation_hashes/Static_builtins.json index 082683fe7e9..2a8599ab121 100644 --- a/scripts/code_generation_hashes/Static_builtins.json +++ b/scripts/code_generation_hashes/Static_builtins.json @@ -1,20 +1,20 @@ { "src/compiler/translator/ImmutableString_autogen.cpp": - "aa5791d78395d37c360b37287fda4982", + "4b3fc9a8ddc87c73e5b1cd1c162c2b28", "src/compiler/translator/Operator_autogen.h": - "41096b767b263dd73172a0f0cbead070", + "5bf164c0e357df73ab727dd14346f05e", "src/compiler/translator/SymbolTable_autogen.cpp": - "4554202237bf3d04d3b80f04e38d6974", + "833ab97eddb14efd795c10a9f224b597", "src/compiler/translator/SymbolTable_autogen.h": - "36d32dd6e9e1111a1a04d3e64fddf8d0", + "e8ad6382d05f71593d12b9f3b18a3fe9", "src/compiler/translator/builtin_function_declarations.txt": - "3193f965fb5198fc7b0feb7ba12ef6f5", + "df755020e057b626d8a8412bb481bea8", "src/compiler/translator/builtin_variables.json": - "e1995c9828b7943e47dc2846c2d071c0", + "2eb97570952f7f077076ee53f28736b0", "src/compiler/translator/gen_builtin_symbols.py": - "c9d46e6222ed3595f46954ea48419b2c", + "dbb1761effeff6eaa6dd995ac5e98be0", "src/compiler/translator/tree_util/BuiltIn_autogen.h": - "427aed0586c4ac38de9bb63b9c263bed", + "32050cfc3fd6cdcc32e25ac83d8385d7", "src/tests/compiler_tests/ImmutableString_test_autogen.cpp": - "731f4a94c4b92e9cdf95085094fc3110" + "9aa15c6a129e0723fb9793cd0b9535eb" } diff --git a/scripts/code_generation_hashes/Vulkan_format.json b/scripts/code_generation_hashes/Vulkan_format.json index 617431df67f..b81d75ca657 100644 --- a/scripts/code_generation_hashes/Vulkan_format.json +++ b/scripts/code_generation_hashes/Vulkan_format.json @@ -2,11 +2,11 @@ "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/angle_format_map.json": - "135d70465df3e9b8535f15d3daee38ac", + "abad08e462a0839d1600d83f83bcad8b", "src/libANGLE/renderer/vulkan/gen_vk_format_table.py": - "b8aaea1be5641acf8247a5f7645291f1", + "ac08a2e90e9b332c3264d18fcf2fbeb8", "src/libANGLE/renderer/vulkan/vk_format_map.json": - "98ea3975e35609fde4fa75dd68f9f316", + "cef433c3606b754728b1642b091c51f6", "src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp": - "b439d4c90f75241e6912231a8e508057" + "762e7feb3dc45dd029bf72e291b3905e" } diff --git a/scripts/code_generation_hashes/Vulkan_internal_shader_programs.json b/scripts/code_generation_hashes/Vulkan_internal_shader_programs.json index d3ce654f53b..79566e3af9d 100644 --- a/scripts/code_generation_hashes/Vulkan_internal_shader_programs.json +++ b/scripts/code_generation_hashes/Vulkan_internal_shader_programs.json @@ -2,67 +2,63 @@ "src/libANGLE/renderer/vulkan/gen_vk_internal_shaders.py": "62278fc740a3deaf2bd07ef77422b1c4", "src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000000.inc": - "dcc2e34fb04417a2f4dc26ebab803380", + "41bc8c922642d232625d08d1a3cab00d", "src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000001.inc": - "8f25e71d8b99c65bc4161549bb4e5932", + "57fc8169da76bfa3409ffa40b7d128ee", "src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000002.inc": - "8dd51cfa420960d1e61ebcef4bee21eb", + "bbf15c080f7f20e667db95007b81699d", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000000.inc": - "b66bb253ca319fe94d8db5ab1da585bd", + "e8653ce9c0f6c84fd6f5ac18d482ba90", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000001.inc": - "f9e381841542d4bb52b9d0813724bafb", + "52daa380aa661a4c4dd47700d353a54e", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000002.inc": - "b173756b41d178a380a799a02d484d31", + "ee958e4676f6485e961b2466b79a1af7", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000003.inc": - "2a71eff7249f782b4912a8a2da5388bc", + "f4cc41cf4f66ad8d71244c333792110f", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000004.inc": - "1ff82465576bbbb5a8a67867adb3d993", + "a1a94d236bcec574e3f996f5413e3a2f", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000005.inc": - "27fd7e46c5a2a6efcc5047c27e68b1b4", + "9296a2700a05aabae411137075303160", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000006.inc": - "682a063ba4aa5e6b87478cb26f5f4f10", + "b8adfc930c7ad3942561c0e8fc5acfca", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000007.inc": - "3ac5410fcf9118790aa301a106aa6b67", + "e6394efdf73c562c1799b1082a175b0c", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000008.inc": - "e88e52908fbaec10ca48330a514f870b", + "811601c184de319ac8386255df8aa595", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000009.inc": - "3cde842f23fc9f2788be2a52cff8e17b", + "8c0d3a50e3f7fc2c3afe9e07d38811e4", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000A.inc": - "afb31d5c745fb3d9dbc5024dc429daa6", + "b598faa97c688df4bfe23519af2fd099", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000B.inc": - "b980a7e580145ad6ceb959baf3607ede", + "2bab3abfe8c12041f418ee1fc513bc6e", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000C.inc": - "e6fbd499f61b4bb0f8d411d5403bd7d2", + "0d81b243c55213a284d641e016c6753e", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000D.inc": - "2d498cef11b24c4188348a92369ea0ae", + "fdaf0901a9edc6f28aada61ee38f72b8", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000E.inc": - "02a156afa4fd305b96d865c0cef888a4", + "7e51f8d76479894b486a8c3b6833124c", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000F.inc": - "742497b15667a5f8c38da7095a6ddcbe", + "2d13a9e2dcd9030fe171dde207368f54", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000010.inc": - "2d7b945346b7fc2ab4fed0a45e75aeb9", + "5178d0a6e32bd8c7e3e18eeb4ebb5220", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000011.inc": - "219408b1e2f66d0e9dc4dbd6aa1dbb08", + "c97c201cb86f88d3b47f4bb6533b1d5a", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000012.inc": - "708a94f767154c2fcb0958e2a2348c4e", + "741e87d8fe7072b4a9f7e29c6bec9f3b", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000013.inc": - "6baebd5c12cc82c0018f9ea7e8c3e7c9", + "03e28f003e29a63d75c4b7764d145337", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000014.inc": - "dbdbfa7a87ec23f5401f97c6c864b946", + "467a39905b49ffcfe450914dad1fe960", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000015.inc": - "524df3a8ef94af7fc9d906399d6a9436", + "debd4e37bb142dff7c3128e73dd69ab6", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000016.inc": - "891dd92330251fbfadf6872f0066e3fc", + "29a2fc62be191367336ea401afa35e17", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000017.inc": - "6f1e10dcb19a12e5e86e98ceab2c6e45", + "19556f63b2e22c65120b6a7cde378ee2", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc": - "3b131ef841a7d119035aefc8487826bb", + "f0e825d5d33e9198899694f8c2d1035c", "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc": - "f60edde525e823378168c890873f4be7", - "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc": - "d770e8274bcbce8f6d03fd13ce27b9bc", - "src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc": - "de59d829ddb735d36238cc25e0022cd6", + "c418f8992217166fe20f31a51568aa49", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc": "82426086e0b5aea32d0f756a1f6e5342", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc": @@ -280,7 +276,7 @@ "src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.0000002A.inc": "426a6cabb4753b203b6ba60274fbb1b5", "src/libANGLE/renderer/vulkan/shaders/gen/ImageCopyFloat.frag.00000000.inc": - "7b8f9ea38024c54df7dafb58250cb172", + "32716fd0dc24ac20515521635f444ccf", "src/libANGLE/renderer/vulkan/shaders/gen/ImageCopyFloat.frag.00000001.inc": "b62b650bc28561e4036a99d91c36c960", "src/libANGLE/renderer/vulkan/shaders/gen/OverlayDraw.frag.00000000.inc": @@ -292,15 +288,15 @@ "src/libANGLE/renderer/vulkan/shaders/src/Blit3DSrc.frag.json": "c7c273b816e4551ea404666149d021bd", "src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.frag": - "5f5d59629ef2570096973c8a84ba7a21", + "f10d38023c6337126550761bf21236d1", "src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.frag.json": "353929c45304fe9c327b50a53c5f1918", "src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.inc": - "77073cb6a80a472c5a23165f6cb41847", + "a69bdc14a24393e42a5b9d9cc745df5c", "src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp": - "163151792f2ffed48258abd66a1bc10c", + "cd7482375ea91cf109898c4a259dd886", "src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp.json": - "8a3e9ff34eba0386edb98048547a272b", + "97cc55694332931c86f81fb78281b311", "src/libANGLE/renderer/vulkan/shaders/src/ConvertIndex.comp": "cab30c9098ecf1e2b00c7309b67cac1f", "src/libANGLE/renderer/vulkan/shaders/src/ConvertIndex.comp.json": @@ -348,7 +344,7 @@ "src/libANGLE/renderer/vulkan/shaders/src/ImageCopy.inc": "6c28a7ca97d0d9b1140eb73325248455", "src/libANGLE/renderer/vulkan/shaders/src/ImageCopyFloat.frag": - "f0f3fc1e9cd7f765e59f078490504a91", + "995bef2533de7b5f35f4f79d93629354", "src/libANGLE/renderer/vulkan/shaders/src/ImageCopyFloat.frag.json": "648ac936936acb9f2f8714c1de15a7ca", "src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.frag": @@ -358,9 +354,9 @@ "src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.vert": "5aa33152fce5b9261c4d427ad2babdd7", "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp": - "e9f13dec1bd2b0171deaa1de3516a626", + "fb89faf2d96bf866dd5bdfd905d9402a", "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h": - "b5fd3e48b63232c8faab1342701b257a", + "5302227e34a46e76a3340303e8650127", "tools/glslang/glslang_validator.exe.sha1": "17e862cc6f462fecbf50b24ed6544a27", "tools/glslang/glslang_validator.sha1": 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 002041e10cf..bcd9fe97b05 100644 --- a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json +++ b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json @@ -4,11 +4,11 @@ "src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py": "a9fd6f3ff2b584aff382364489146c76", "src/libANGLE/renderer/vulkan/vk_format_map.json": - "98ea3975e35609fde4fa75dd68f9f316", + "cef433c3606b754728b1642b091c51f6", "src/libANGLE/renderer/vulkan/vk_mandatory_format_support_data.json": "fa2bd54c1bb0ab2cf1d386061a4bc5c5", "src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp": - "96ac9e08704b7a086f7c8db5d213de2b", + "26e7ee4cead7fbccf06310ac1bb58caf", "third_party/vulkan-headers/src/registry/vk.xml": - "e728fb0d88625ddb6859d4ead0818fa2" + "71f5018aec430508e35f198302ca83a9" } diff --git a/scripts/code_generation_hashes/WebGPU_format.json b/scripts/code_generation_hashes/WebGPU_format.json index c276c4736e2..68bae1f7142 100644 --- a/scripts/code_generation_hashes/WebGPU_format.json +++ b/scripts/code_generation_hashes/WebGPU_format.json @@ -2,11 +2,11 @@ "src/libANGLE/renderer/angle_format.py": "45ffbde9a8edc7cec1c6c3afc5517b30", "src/libANGLE/renderer/angle_format_map.json": - "135d70465df3e9b8535f15d3daee38ac", + "abad08e462a0839d1600d83f83bcad8b", "src/libANGLE/renderer/wgpu/gen_wgpu_format_table.py": - "5ec5376c04a7c2cfce02a82fe87dc1d9", + "2bfcc8355154c904c9c3e2739402e39f", "src/libANGLE/renderer/wgpu/wgpu_format_map.json": - "76cdbf4bd3ee6e9651313c4754a9da71", + "e43710213b23e3a941cad9950ea9f747", "src/libANGLE/renderer/wgpu/wgpu_format_table_autogen.cpp": - "3c9cd317513908445b823924ee20f90a" + "b2be6626d1b74ebeea3fdc52ac6ac8bf" } diff --git a/scripts/code_generation_hashes/interpreter_utils.json b/scripts/code_generation_hashes/interpreter_utils.json index 6a95cb9aaaf..615e21fb4ea 100644 --- a/scripts/code_generation_hashes/interpreter_utils.json +++ b/scripts/code_generation_hashes/interpreter_utils.json @@ -1,24 +1,24 @@ { "scripts/egl_angle_ext.xml": - "d9434b5d3dc4842f02bbb06f54fb7e02", + "676627eae49a3ccadeafc3adbd7dba8d", "scripts/gen_interpreter_utils.py": - "c525953cf6fb2294d489e9c22cbabdb8", + "7c21cda140a45527c02ddd003ebe7914", "scripts/gl_angle_ext.xml": - "ef111314bcf6e8c9cdc1a391080f1d80", + "da4ecccdd77635f1b0e9d4664f856706", "scripts/registry_xml.py": - "b4b40cf6f60ec0b2e8ef27dae59cfd91", + "b51290658fa62298178113925375d125", "third_party/EGL-Registry/src/api/egl.xml": "2056d54ea07156f1988ca1366bdee21a", "third_party/OpenCL-Docs/src/xml/cl.xml": - "6d0bf09e20a8f8c3ae440d79eda08bf9", + "3c93f136de5049f4d9eca8240df1a025", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23", + "00c18abda09593ce770fd184bd8f6255", "third_party/OpenGL-Registry/src/xml/glx.xml": - "94f3eee4b076801d117804eb466714b7", + "649f24094c1938779ada7db2dc092d35", "third_party/OpenGL-Registry/src/xml/wgl.xml": - "eae784bf4d1b983a42af5671b140b7c4", + "da69debd6646f79119fcdaaf5969af2f", "util/capture/trace_fixture.h": - "4a0c7fde0a41217d377a49c2499b2e2a", + "a519a497caa153876f3a5441bbd3b1f8", "util/capture/trace_interpreter_autogen.cpp": - "0a35473ca38e4caf6a62eb0a0e75e146" + "60e35c72310288b38f961a1b2c8124b8" } diff --git a/scripts/code_generation_hashes/packed_enum.json b/scripts/code_generation_hashes/packed_enum.json index 4083652bc85..932e52c05ea 100644 --- a/scripts/code_generation_hashes/packed_enum.json +++ b/scripts/code_generation_hashes/packed_enum.json @@ -1,22 +1,22 @@ { "src/common/PackedCLEnums_autogen.cpp": - "883883aafe2cc350882ea789f52db67c", + "46081ff46665cb5468c9cfbeb5d65d9f", "src/common/PackedCLEnums_autogen.h": - "c2016e23792b0589789781f9180c1a56", + "8d7d40937dec0f7c3f2651c388c49bd0", "src/common/PackedEGLEnums_autogen.cpp": - "fa1a367e583643570cd058127ae67e33", + "8a3827607e85f0b359fe24931463937c", "src/common/PackedEGLEnums_autogen.h": - "7d87e160a0c8ea26cb0c835729f7b586", + "d3846e6832b350f84e8c7409339b76a6", "src/common/PackedGLEnums_autogen.cpp": - "02ed16de01a83b2d9c315d7e7ae387a4", + "b0618aa0bbe78cc43bfe7959c299000b", "src/common/PackedGLEnums_autogen.h": - "c437f3061e4cef21a16602f67dc46070", + "1297f5ac20b4a7de62deba06c7697df7", "src/common/gen_packed_gl_enums.py": "3334498103ee8b13fe721519dd8e0742", "src/common/packed_cl_enums.json": - "82f48aa039cbaf147b5e46be0ea8f153", + "34f1679258ca1a72e8686ad32f77245d", "src/common/packed_egl_enums.json": - "5797db941e95e418d69527eb4e4af900", + "871f5f84cdb8627813809de271d22a44", "src/common/packed_gl_enums.json": - "96c6d8a1b084a897f3145cbfdb7e3887" + "16d960e5e7af45e4ce2611d0f4d6ae5c" } diff --git a/scripts/code_generation_hashes/proc_table.json b/scripts/code_generation_hashes/proc_table.json index 9d3925023ff..b9881969434 100644 --- a/scripts/code_generation_hashes/proc_table.json +++ b/scripts/code_generation_hashes/proc_table.json @@ -1,26 +1,26 @@ { "scripts/egl_angle_ext.xml": - "d9434b5d3dc4842f02bbb06f54fb7e02", + "676627eae49a3ccadeafc3adbd7dba8d", "scripts/gen_proc_table.py": - "aaf46dc6c500b5aed34c2c51a5fe7b30", + "23ebf460dda78d2c21625e0d41d3cb97", "scripts/gl_angle_ext.xml": - "ef111314bcf6e8c9cdc1a391080f1d80", + "da4ecccdd77635f1b0e9d4664f856706", "scripts/registry_xml.py": - "b4b40cf6f60ec0b2e8ef27dae59cfd91", + "b51290658fa62298178113925375d125", "src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp": - "3c5d36837a2a48b462cd18f01399801e", + "15bb9a05ababbb1a2726df6e0d4a31b3", "src/libGLESv2/proc_table_cl_autogen.cpp": - "ed003b0f041aaaa35b67d3fe07e61f91", + "0fb2b75591e12301065ce19696222cb1", "src/libOpenCL/libOpenCL_autogen.map": "bc5f5cf48227149ed321258a16eff1d7", "third_party/EGL-Registry/src/api/egl.xml": "2056d54ea07156f1988ca1366bdee21a", "third_party/OpenCL-Docs/src/xml/cl.xml": - "6d0bf09e20a8f8c3ae440d79eda08bf9", + "3c93f136de5049f4d9eca8240df1a025", "third_party/OpenGL-Registry/src/xml/gl.xml": - "49f0afe5cac23951c74420e457b0cb23", + "00c18abda09593ce770fd184bd8f6255", "third_party/OpenGL-Registry/src/xml/glx.xml": - "94f3eee4b076801d117804eb466714b7", + "649f24094c1938779ada7db2dc092d35", "third_party/OpenGL-Registry/src/xml/wgl.xml": - "eae784bf4d1b983a42af5671b140b7c4" + "da69debd6646f79119fcdaaf5969af2f" } diff --git a/scripts/code_generation_hashes/restricted_traces.json b/scripts/code_generation_hashes/restricted_traces.json index dd00c2897c8..434d0918842 100644 --- a/scripts/code_generation_hashes/restricted_traces.json +++ b/scripts/code_generation_hashes/restricted_traces.json @@ -4,5 +4,5 @@ "src/tests/restricted_traces/gen_restricted_traces.py": "79978de70c2597f249241ed864562149", "src/tests/restricted_traces/restricted_traces.json": - "df250dc19c192eec4204e16b5ebe8ff9" + "cc71d87ae3366d33dd843978a5356184" } diff --git a/scripts/egl_angle_ext.xml b/scripts/egl_angle_ext.xml index f2530901e2a..5ff7f83dcd7 100644 --- a/scripts/egl_angle_ext.xml +++ b/scripts/egl_angle_ext.xml @@ -9,11 +9,6 @@ Includes data used to auto-generate ANGLE classes. - - - typedef khronos_uint64_t EGLFrameTokenANGLE; - - @@ -96,12 +91,6 @@ void eglReleaseExternalContextANGLE EGLDisplay dpy - - EGLBoolean eglSwapBuffersWithFrameTokenANGLE - EGLDisplay dpy - EGLSurface surface - EGLFrameTokenANGLE frametoken - void eglLockVulkanQueueANGLE EGLDisplay dpy @@ -221,11 +210,6 @@ - - - - - @@ -289,6 +273,7 @@ + @@ -362,11 +347,6 @@ - - - - - @@ -551,6 +531,11 @@ + + + + + @@ -628,7 +613,6 @@ - @@ -680,10 +664,14 @@ + + + + diff --git a/scripts/entry_point_packed_gl_enums.json b/scripts/entry_point_packed_gl_enums.json index b258660ba43..b6684ef79dc 100644 --- a/scripts/entry_point_packed_gl_enums.json +++ b/scripts/entry_point_packed_gl_enums.json @@ -458,6 +458,9 @@ "textarget": "TextureTarget", "texture": "TextureID" }, + "glFramebufferTextureMultisampleMultiview": { + "texture": "TextureID" + }, "glFramebufferTexture3D": { "textarget": "TextureTarget", "texture": "TextureID" @@ -1506,6 +1509,13 @@ "glShaderStorageBlockBinding": { "program": "ShaderProgramID" }, + "glShadingRate": { + "rate": "ShadingRate" + }, + "glShadingRateCombinerOps": { + "combinerOp0": "CombinerOp", + "combinerOp1": "CombinerOp" + }, "glSignalSemaphore": { "buffers": "const BufferID *", "semaphore": "SemaphoreID", diff --git a/scripts/export_targets.py b/scripts/export_targets.py index ad8d514c200..efce1d66e21 100755 --- a/scripts/export_targets.py +++ b/scripts/export_targets.py @@ -115,7 +115,7 @@ def recurse(key): print('Importing graph', file=sys.stderr) try: - p = run_checked('gn', 'desc', '--format=json', str(OUT_DIR), '*', stdout=subprocess.PIPE, + p = run_checked(sys.executable, 'third_party/depot_tools/gn.py', 'desc', '--format=json', str(OUT_DIR), '*', stdout=subprocess.PIPE, env=GN_ENV, shell=(True if sys.platform == 'win32' else False)) except subprocess.CalledProcessError: sys.stderr.buffer.write(b'"gn desc" failed. Is depot_tools in your PATH?\n') @@ -134,7 +134,8 @@ def recurse(key): def flattened_target(target_name: str, descs: dict, stop_at_lib: bool =True) -> dict: flattened = dict(descs[target_name]) - EXPECTED_TYPES = LIBRARY_TYPES + ('source_set', 'group', 'action') + EXPECTED_TYPES = LIBRARY_TYPES + ('source_set', 'group', 'action', 'action_foreach', + 'executable') def pre(k): dep = descs[k] @@ -187,6 +188,9 @@ def pre(k): b'compiler/translator/glsl/TranslatorESSL.h', b'compiler/translator/glsl/TranslatorGLSL.h', b'compiler/translator/hlsl/TranslatorHLSL.h', + b'compiler/translator/ir/src/builder.rs.h', + b'compiler/translator/ir/src/compile.rs.h', + b'compiler/translator/ir/src/output/legacy.rs.h', b'compiler/translator/msl/TranslatorMSL.h', b'compiler/translator/null/TranslatorNULL.h', b'compiler/translator/spirv/TranslatorSPIRV.h', @@ -212,11 +216,11 @@ def pre(k): b'libANGLE/renderer/vulkan/android/DisplayVkAndroid.h', b'libANGLE/renderer/vulkan/DisplayVk_api.h', b'libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h', - b'libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h', b'libANGLE/renderer/vulkan/mac/DisplayVkMac.h', b'libANGLE/renderer/vulkan/win32/DisplayVkWin32.h', b'libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h', b'libANGLE/renderer/vulkan/wayland/DisplayVkWayland.h', + b'libANGLE/renderer/wgpu/DisplayWgpu_api.h', b'loader_cmake_config.h', b'loader_linux.h', b'loader_windows.h', @@ -233,6 +237,7 @@ def pre(k): b'vulkan_ios.h', b'vulkan_macos.h', b'vulkan_metal.h', + b'vulkan_ohos.h', b'vulkan_sci.h', b'vulkan_vi.h', b'vulkan_wayland.h', @@ -244,11 +249,11 @@ def pre(k): # comments. Since the script doesn't skip comments they are # erroneously marked as valid includes b'rapidjson/...', - # Validation layers support building with robin hood hashing, but we are not enabling that - # See http://anglebug.com/42264327 - b'robin_hood.h', + # Conditionally included in http://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/9790 + b'parallel_hashmap/phmap.h', # Validation layers optionally use mimalloc b'mimalloc-new-delete.h', + b'mimalloc-stats.h', # From the Vulkan-Loader b'winres.h', # From a comment in vulkan-validation-layers/src/layers/vk_mem_alloc.h diff --git a/scripts/gen_gl_enum_utils.py b/scripts/gen_gl_enum_utils.py index e1ea73ad50a..d0d200def29 100755 --- a/scripts/gen_gl_enum_utils.py +++ b/scripts/gen_gl_enum_utils.py @@ -32,11 +32,6 @@ {{ {gles_enum_groups} }}; - -enum class BigGLEnum -{{ - {gl_enum_groups} -}}; }} // namespace gl # endif // COMMON_GL_ENUM_UTILS_AUTOGEN_H_ @@ -83,16 +78,6 @@ }} }} -const char *GLenumToString(BigGLEnum enumGroup, unsigned int value) -{{ - switch (enumGroup) - {{ - {gl_enums_value_to_string_table} - default: - return UnknownEnumToString(value); - }} -}} - namespace {{ using StringEnumEntry = std::pair; @@ -199,16 +184,12 @@ def main(header_output_path, source_output_path): # Compute a list of all GLES enums. gles_enums = set() - bigl_enums = set() for feature in xml.root.findall('feature'): for require in feature.findall('require'): assert 'api' not in require.attrib if 'gles' in feature.attrib['api']: for enum in require.findall('enum'): gles_enums.add(enum.attrib['name']) - if feature.attrib['api'] == 'gl': - for enum in require.findall('enum'): - bigl_enums.add(enum.attrib['name']) for extensions in xml.root.findall('extensions'): for extension in extensions.findall('extension'): @@ -219,19 +200,12 @@ def main(header_output_path, source_output_path): 'gles' in extension.attrib['supported']): for enum in require.findall('enum'): gles_enums.add(enum.attrib['name']) - if ('api' not in require.attrib or - feature.attrib['api'] == 'gl') and ('gl' in ext_apis): - for enum in require.findall('enum'): - bigl_enums.add(enum.attrib['name']) # Build a map from GLenum name to its value - gl_enum_groups = dict() gles_enum_groups = dict() # Add all enums to default groups - gl_default_enums = dict() gles_default_enums = dict() - gl_enum_groups[registry_xml.default_enum_group_name] = gl_default_enums gles_enum_groups[registry_xml.default_enum_group_name] = gles_default_enums enums_and_values = [] @@ -243,8 +217,6 @@ def main(header_output_path, source_output_path): if enum_name in gles_enums: gles_default_enums[enum_name] = enum_value - if enum_name in bigl_enums: - gl_default_enums[enum_name] = enum_value if 'group' in enum.attrib: for enum_group in enum.attrib['group'].split(','): @@ -254,24 +226,17 @@ def main(header_output_path, source_output_path): if enum_group not in gles_enum_groups: gles_enum_groups[enum_group] = dict() gles_enum_groups[enum_group][enum_name] = enum_value - if enum_name in bigl_enums: - if enum_group not in gl_enum_groups: - gl_enum_groups[enum_group] = dict() - gl_enum_groups[enum_group][enum_name] = enum_value for empty_group in empty_enum_groups: - assert not empty_group in gles_enum_groups or not empty_group in gl_enum_groups, 'Remove %s from the empty groups list, it has enums now.' % empty_group + assert empty_group not in gles_enum_groups, 'Remove %s from the empty groups list, it has enums now.' % empty_group if empty_group not in gles_enum_groups: gles_enum_groups[empty_group] = dict() - if empty_group not in gl_enum_groups: - gl_enum_groups[empty_group] = dict() # Write GLenum groups into the header file. header_content = template_gl_enums_header.format( script_name=os.path.basename(sys.argv[0]), data_source_name="gl.xml and gl_angle_ext.xml", - gles_enum_groups=',\n'.join(sorted(gles_enum_groups.keys())), - gl_enum_groups=',\n'.join(sorted(gl_enum_groups.keys()))) + gles_enum_groups=',\n'.join(sorted(gles_enum_groups.keys()))) header_output_path = registry_xml.script_relative(header_output_path) with open(header_output_path, 'w') as f: @@ -279,13 +244,11 @@ def main(header_output_path, source_output_path): # Write mapping to source file gles_enums_value_to_string_table = dump_value_to_string_mapping(gles_enum_groups, 'GLESEnum') - gl_enums_value_to_string_table = dump_value_to_string_mapping(gl_enum_groups, 'BigGLEnum') string_to_enum_table = dump_string_to_value_mapping(enums_and_values) source_content = template_gl_enums_source.format( script_name=os.path.basename(sys.argv[0]), data_source_name="gl.xml and gl_angle_ext.xml", gles_enums_value_to_string_table=gles_enums_value_to_string_table, - gl_enums_value_to_string_table=gl_enums_value_to_string_table, string_to_enum_table=string_to_enum_table, ) diff --git a/scripts/gen_interpreter_utils.py b/scripts/gen_interpreter_utils.py index bf12260a656..d929de1ee70 100644 --- a/scripts/gen_interpreter_utils.py +++ b/scripts/gen_interpreter_utils.py @@ -111,8 +111,15 @@ def GetFunctionsFromFixture(): for line in lines: line = re.sub('// .*\n', '', line.strip()) if line.startswith(pattern): - func_name = line[len(pattern):line.find('(')] - func_args = line.count(',') + 1 + func_name_end_index = line.find('(') + func_name = line[len(pattern):func_name_end_index] + args_start_index = func_name_end_index + 1 + args_end_index = line.find(')', args_start_index) + args_str = line[args_start_index:args_end_index].strip() + if args_str: + func_args = args_str.count(',') + 1 + else: + func_args = 0 funcs.append(func_name) arg_counts.add(func_args) f.close() diff --git a/scripts/gen_proc_table.py b/scripts/gen_proc_table.py index e16170356dd..30715c9c6bb 100644 --- a/scripts/gen_proc_table.py +++ b/scripts/gen_proc_table.py @@ -56,6 +56,11 @@ __eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname) {{ + if (procname == nullptr) + {{ + return nullptr; + }} + const ProcEntry *entry = std::lower_bound(std::begin(g_procTable), std::end(g_procTable), procname, CompareProc); diff --git a/scripts/generate_android_bp.py b/scripts/generate_android_bp.py index d22cea8341f..8dd5a76e216 100644 --- a/scripts/generate_android_bp.py +++ b/scripts/generate_android_bp.py @@ -84,7 +84,7 @@ def write_blueprint_key_value(output, name, value, indent=1): if isinstance(value, set) or isinstance(value, list): value = list(sorted(set(value))) if name == 'cflags': - fix_fortify_source_cflags(value) + fix_platform_default_defines(value) if isinstance(value, list): output.append(tabs(indent) + '%s: [' % name) @@ -440,6 +440,7 @@ def library_target_to_blueprint(target, build_info): if target in ROOT_TARGETS: bp['defaults'].append('angle_vendor_cc_defaults') bp['defaults'].append('angle_dma_buf_cc_defaults') + bp['afdo'] = True bps_for_abis[abi] = bp common_bp = merge_bps(bps_for_abis) @@ -458,6 +459,19 @@ def gn_action_args_to_blueprint_args(blueprint_inputs, blueprint_outputs, args): ('gen/', ''), ] + # some args have special prefix added in front of the file name, we need to + # take them out before transforming the file path, and then add them back: + # e.g. + # transform + # --extinst=,../../third_party/spirv-headers/src/include/spirv/unified1/extinst.debuginfo.grammar.json + # to + # --extinst=,$(location third_party/spirv-headers/src/include/spirv/unified1/extinst.debuginfo.grammar.json) + special_prefixs = [ + '--extinst=,', + '--extinst=SHDEBUG100_,', + '--extinst=CLDEBUG100_,', + ] + result_args = [] for arg in args: # Attempt to find if this arg is a path to one of the inputs. If it is, use the blueprint @@ -466,12 +480,23 @@ def gn_action_args_to_blueprint_args(blueprint_inputs, blueprint_outputs, args): remapped_path_arg = arg for (remap_source, remap_dest) in remap_folders: remapped_path_arg = remapped_path_arg.replace(remap_source, remap_dest) + special_prefix = '' + for special_item in special_prefixs: + if remapped_path_arg.startswith(special_item): + special_prefix = special_item + break + if special_prefix != '': + remapped_path_arg = remapped_path_arg[len(special_prefix):] if remapped_path_arg in blueprint_inputs or remapped_path_arg in blueprint_outputs: - result_args.append('$(location %s)' % remapped_path_arg) + remapped_path_arg = remapped_path_arg + result_args.append('%s$(location %s)' % (special_prefix, remapped_path_arg)) elif os.path.basename(remapped_path_arg) in blueprint_outputs: - result_args.append('$(location %s)' % os.path.basename(remapped_path_arg)) + remapped_path_arg = remapped_path_arg + result_args.append('%s$(location %s)' % + (special_prefix, os.path.basename(remapped_path_arg))) else: + remapped_path_arg = special_prefix + remapped_path_arg result_args.append(remapped_path_arg) return result_args @@ -495,6 +520,19 @@ def is_input_in_tool_files(tool_files, input): return input in tool_files +def separate_py_files_from_bp_srcs_entry(input_list): + bp_tools_list = [] # Initialize the new list for ".py" items + remaining_gn_input_list = [] # Initialize the list for the items that are not ".py" + + for item in input_list: + if item.endswith(".py"): + bp_tools_list.append(item) + else: + remaining_gn_input_list.append(item) + + return remaining_gn_input_list, bp_tools_list + + # special handling the {{response_file_name}} args in GN: # see https://gn.googlesource.com/gn/+/main/docs/reference.md#var_response_file_contents # in GN, if we use response_file_contents, the GN build system will automatically @@ -543,7 +581,15 @@ def action_target_to_blueprint(abi, target, build_info): if not is_input_in_tool_files(target_info['script'], input) ] - bp_srcs = gn_paths_to_blueprint_paths(gn_inputs) + # Take "*.py" out from gn_inputs, they need to be listed in tool_files entry + # in Android.bp. + gn_inputs_without_python_script = gn_inputs + extra_tool_files = [] + if 'script' in target_info: + gn_inputs_without_python_script, extra_tool_files = separate_py_files_from_bp_srcs_entry( + gn_inputs) + + bp_srcs = gn_paths_to_blueprint_paths(gn_inputs_without_python_script) bp['srcs'] = bp_srcs @@ -559,6 +605,17 @@ def action_target_to_blueprint(abi, target, build_info): bp['out'] = bp_outputs bp['tool_files'] = [gn_path_to_blueprint_path(target_info['script'])] + if 'script' in target_info: + # if there are more than 1 python script listed in "tool_files" entry in + # Android.bp action target, we need to specify which script we are + # invoking. + if len(extra_tool_files) > 0: + location = '$(location ' + target_info['script'].lstrip('/') + ')' + else: + location = '$(location)' + bp['tool_files'] += gn_paths_to_blueprint_paths(extra_tool_files) + else: + location = '$(location)' new_temporary_gn_response_file, updated_args = handle_gn_build_arg_response_file_name( target_info['args']) @@ -566,11 +623,11 @@ def action_target_to_blueprint(abi, target, build_info): if new_temporary_gn_response_file: # add the command 'echo $(in) > $(genDir)/gn_response_file' to # write $response_file_contents into the new_temporary_gn_response_file. - cmd = ['echo $(in) >', new_temporary_gn_response_file, '&&', '$(location)' + cmd = ['echo $(in) >', new_temporary_gn_response_file, '&&', location ] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, updated_args) else: - cmd = ['$(location)'] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, - target_info['args']) + cmd = [location] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, + target_info['args']) bp['cmd'] = ' '.join(cmd) @@ -736,20 +793,30 @@ def handle_angle_non_conformant_extensions_and_versions( bp['defaults'].append(non_conform_defaults) -def fix_fortify_source_cflags(cflags): - # search if there is any cflag starts with '-D_FORTIFY_SOURCE' - d_fortify_source_flag = [cflag for cflag in cflags if '-D_FORTIFY_SOURCE' in cflag] - # Insert -U_FORTIFY_SOURCE before the first -D_FORTIFY_SOURCE flag. - # In case a default mode for FORTIFY_SOURCE is predefined for a compiler, - # and the -D_FORTIFY_SOURCE mode we set is different from the default mode, - # the compiler will warn about "redefining FORTIFY_SOURCE macro". - # To fix this compiler warning, we unset the default mode with - # -U_FORTIFY_SOURCE before setting the desired FORTIFY_SOURCE mode in our - # cflags. - # reference: - # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++#tldr-what-compiler-options-should-i-use - if d_fortify_source_flag: - cflags.insert(cflags.index(d_fortify_source_flag[0]), '-U_FORTIFY_SOURCE') +def fix_platform_default_defines(cflags: list[str]) -> None: + """Avoids macro redefinition errors for flags specified by Android. + + Android may specify platform defaults for macros like `_FORTIFY_SOURCE` and + `_LIBCPP_HARDENING_MODE`. If both Android and Angle provide different values + for these (e.g., `-D_FORTIFY_SOURCE=3 -D_FORTIFY_SOURCE=2`), Clang will emit + errors about macro redefinitions. + + This inserts `-U${FLAG}` before Angle's definitions, to avoid those errors. + """ + flags_to_check = ( + '_FORTIFY_SOURCE', + '_LIBCPP_HARDENING_MODE', + ) + for flag in flags_to_check: + d_flag = f'-D{flag}' + + # It's _technically_ possible that we have multiple instances of these + # flags in a single command. If these flags _differ_ in value, they + # should already be a build error, so we only need to worry about adding + # the `-U` flag before the first. + flag_index = next((i for i, cflag in enumerate(cflags) if d_flag in cflag), None) + if flag_index is not None: + cflags.insert(flag_index, f'-U{flag}') def main(): @@ -782,8 +849,6 @@ def main(): { 'name': 'angle_common_library_cflags', - 'cpp_std': - 'gnu++17', # TODO(b/330910097): std::popcount missing from external/libcxx 'cflags': [ # Chrome and Android use different versions of Clang which support differnt warning options. # Ignore errors about unrecognized warning flags. @@ -844,14 +909,9 @@ def main(): 'src/third_party/libXNVCtrl/LICENSE', 'src/third_party/volk/LICENSE.md', 'third_party/abseil-cpp/LICENSE', - 'third_party/android_system_sdk/LICENSE', - 'third_party/bazel/LICENSE', - 'third_party/colorama/LICENSE', - 'third_party/proguard/LICENSE', - 'third_party/r8/LICENSE', - 'third_party/turbine/LICENSE', 'third_party/glslang/LICENSE', 'third_party/glslang/src/LICENSE.txt', + 'third_party/re2/LICENSE', 'third_party/spirv-headers/LICENSE', 'third_party/spirv-headers/src/LICENSE', 'third_party/spirv-tools/LICENSE', diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py index a666b538b92..fef954fe7be 100755 --- a/scripts/generate_entry_points.py +++ b/scripts/generate_entry_points.py @@ -44,6 +44,8 @@ 'drawArraysInstancedBaseInstanceANGLE', 'drawElementsInstancedBaseVertexBaseInstanceANGLE', 'logicOpANGLE', + 'shadingRateEXT', + 'shadingRateQCOM', ] # These are the entry points which potentially are used first by an application @@ -57,89 +59,26 @@ "clIcdGetPlatformIDsKHR": "true", } -# These are the only entry points that are allowed while pixel local storage is active. -PLS_ALLOW_LIST = { - "ActiveTexture", - "BindBuffer", - "BindBufferBase", - "BindBufferRange", - "BindFramebuffer", - "BindSampler", - "BindTexture", - "BindVertexArray", - "BlendEquation", - "BlendEquationSeparate", - "BlendFunc", - "BlendFuncSeparate", - "BufferData", - "BufferSubData", - "CheckFramebufferStatus", - "ClipControlEXT", - "ColorMask", - "CullFace", - "DepthFunc", - "DepthMask", - "DepthRangef", - "Disable", - "DisableVertexAttribArray", - "DispatchComputeIndirect", - "DrawBuffers", - "Enable", - "EnableClientState", - "EnableVertexAttribArray", - "EndPixelLocalStorageANGLE", - "FenceSync", - "FlushMappedBufferRange", - "FramebufferMemorylessPixelLocalStorageANGLE", - "FramebufferPixelLocalStorageInterruptANGLE", - "FramebufferRenderbuffer", - "FrontFace", - "MapBufferRange", - "PixelLocalStorageBarrierANGLE", - "ProvokingVertexANGLE", - "Scissor", - "StencilFunc", - "StencilFuncSeparate", - "StencilMask", - "StencilMaskSeparate", - "StencilOp", - "StencilOpSeparate", - "UnmapBuffer", - "UseProgram", - "ValidateProgram", - "Viewport", +# These entry points implicitly disable pixel local storage (if active) before running and before +# validation. +PLS_DISABLE_LIST = { + "glBeginTransformFeedback", + "glBindFramebuffer", + "glBlitFramebuffer", + "glCopyTexImage2D", + "glDiscardFramebufferEXT", + "glDrawBuffers", + "glFramebufferMemorylessPixelLocalStorageANGLE", + "glFramebufferRenderbuffer", + "glInvalidateFramebuffer", + "glInvalidateSubFramebuffer", + "glReadPixels", + "glStartTilingQCOM", } -PLS_ALLOW_WILDCARDS = [ - "BlendEquationSeparatei*", - "BlendEquationi*", - "BlendFuncSeparatei*", - "BlendFunci*", - "ClearBuffer*", - "ColorMaski*", - "DebugMessageCallback*", - "DebugMessageControl*", - "DebugMessageInsert*", - "Delete*", - "Disablei*", - "DrawArrays*", - "DrawElements*", - "DrawRangeElements*", - "Enablei*", - "FramebufferParameter*", - "FramebufferTexture*", - "Gen*", - "Get*", - "Is*", - "ObjectLabel*", - "ObjectPtrLabel*", - "PolygonMode*", - "PolygonOffset*", - "PopDebugGroup*", - "PushDebugGroup*", - "SamplerParameter*", - "TexParameter*", - "Uniform*", - "VertexAttrib*", +PLS_DISABLE_WILDCARDS = [ + "glCopyTexSubImage*", + "glFramebufferParameter*", + "glFramebufferTexture*", ] # These are the entry points which purely set state in the current context with @@ -162,12 +101,16 @@ 'glDepthRangef', 'glDisable', 'glDisablei', + 'glDisableVertexAttribArray', 'glEnable', 'glEnablei', + 'glEnableVertexAttribArray', 'glFrontFace', 'glHint', 'glIsEnabled', 'glIsEnabledi', + 'glIsVertexArray', + 'glIsVertexArrayOES', 'glLineWidth', 'glLogicOpANGLE', 'glMinSampleShading', @@ -182,7 +125,9 @@ 'glSampleCoverage', 'glSampleMaski', 'glScissor', - 'glShadingRate', + 'glShadingRateCombinerOps', + 'glShadingRateEXT', + 'glShadingRateQCOM', 'glStencilFunc', 'glStencilFuncSeparate', 'glStencilMask', @@ -210,6 +155,10 @@ 'glPushMatrix', 'glSampleCoveragex', 'glShadeModel', + 'glVertexAttribBinding', + 'glVertexAttribFormat', + 'glVertexAttribIFormat', + 'glVertexBindingDivisor', ] CONTEXT_PRIVATE_WILDCARDS = [ 'glBlendFunc*', @@ -218,6 +167,7 @@ 'glVertexAttribI[1-4]*', 'glVertexAttribP[1-4]*', 'glVertexAttribL[1-4]*', + 'glVertexAttribDivisor*', # GLES1 entry points 'glClipPlane[fx]', 'glGetClipPlane[fx]', @@ -241,6 +191,12 @@ 'glTranslate[fx]', ] +# These context private APIs needs to pass PrivateStateCache to validation function +VALIDATION_NEEDS_PRIVATE_STATE_CACHE_LIST = [ + 'glVertexAttribFormat', + 'glVertexAttribIFormat', +] + TEMPLATE_ENTRY_POINT_HEADER = """\ // GENERATED FILE - DO NOT EDIT. // Generated by {script_name} using data from {data_source_name}. @@ -361,13 +317,13 @@ {{ ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = {context_getter}; - {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params}); + {event_comment}ANGLE_UNSAFE_TODO(EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params})); if ({valid_context_check}) {{{packed_gl_enum_conversions} - {context_lock} - bool isCallValid = (context->skipValidation() || {validation_expression}); - if (isCallValid) + {context_lock}{implicit_pls_disable} + {validation_expression} + if (ANGLE_LIKELY(isCallValid)) {{ context->{name_lower_no_suffix}({internal_params}); }} @@ -386,12 +342,12 @@ {{ ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = {context_getter}; - {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params}); + {event_comment}ANGLE_UNSAFE_TODO(EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params})); if ({valid_context_check}) {{{packed_gl_enum_conversions} - bool isCallValid = (context->skipValidation() || {validation_expression}); - if (isCallValid) + {validation_expression} + if (ANGLE_LIKELY(isCallValid)) {{ ContextPrivate{name_no_suffix}({context_private_internal_params}); }} @@ -410,16 +366,17 @@ {{ ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = {context_getter}; - {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params}); + {event_comment}ANGLE_UNSAFE_TODO(EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params})); {return_type} returnValue; if ({valid_context_check}) {{{packed_gl_enum_conversions} - {context_lock} - bool isCallValid = (context->skipValidation() || {validation_expression}); - if (isCallValid) + {context_lock}{implicit_pls_disable} + {validation_expression} + if (ANGLE_LIKELY(isCallValid)) {{ returnValue = context->{name_lower_no_suffix}({internal_params}); + {mapbufferrange_return_modification} }} else {{ @@ -442,13 +399,13 @@ {{ ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = {context_getter}; - {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params}); + {event_comment}ANGLE_UNSAFE_TODO(EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params})); {return_type} returnValue; if ({valid_context_check}) {{{packed_gl_enum_conversions} - bool isCallValid = (context->skipValidation() || {validation_expression}); - if (isCallValid) + {validation_expression} + if (ANGLE_LIKELY(isCallValid)) {{ returnValue = ContextPrivate{name_no_suffix}({context_private_internal_params}); }} @@ -476,7 +433,7 @@ ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); {{ ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -507,7 +464,7 @@ Thread *thread = egl::GetCurrentThread(); ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -538,7 +495,7 @@ {return_type} returnValue; {{ {egl_lock} - EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -571,7 +528,7 @@ ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); {return_type} returnValue; - EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -596,7 +553,7 @@ TEMPLATE_CL_ENTRY_POINT_NO_RETURN = """\ void CL_API_CALL cl{name}({params}) {{ - CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -611,7 +568,7 @@ TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR = """\ cl_int CL_API_CALL cl{name}({params}) {{{initialization} - CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -627,7 +584,7 @@ TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET = """\ {return_type} CL_API_CALL cl{name}({params}) {{{initialization} - CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -649,7 +606,7 @@ TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER = """\ {return_type} CL_API_CALL cl{name}({params}) {{{initialization} - CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params}); + ANGLE_UNSAFE_TODO(CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params})); {packed_gl_enum_conversions} @@ -792,6 +749,7 @@ class Thread; {{ class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; {prototypes} @@ -981,19 +939,17 @@ class ErrorSet; TEMPLATE_PARAMETER_CAPTURE_GL_ENUM = """paramBuffer.addEnumParam("{name}", {api_enum}::{group}, ParamType::T{type}, {name});""" TEMPLATE_PARAMETER_CAPTURE_POINTER = """ + ParamCapture {name}Param("{name}", ParamType::T{type}); if (isCallValid) {{ - ParamCapture {name}Param("{name}", ParamType::T{type}); InitParamValue(ParamType::T{type}, {name}, &{name}Param.value); {capture_name}({params}, &{name}Param); - paramBuffer.addParam(std::move({name}Param)); }} else {{ - ParamCapture {name}Param("{name}", ParamType::T{type}); InitParamValue(ParamType::T{type}, static_cast<{cast_type}>(nullptr), &{name}Param.value); - paramBuffer.addParam(std::move({name}Param)); }} + paramBuffer.addParam(std::move({name}Param)); """ TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC = """void {name}({params});""" @@ -1098,7 +1054,6 @@ class ErrorSet; "EGLTimeKHR": UNSIGNED_LONG_LONG_FORMAT, "EGLImageKHR": POINTER_FORMAT, "EGLStreamKHR": POINTER_FORMAT, - "EGLFrameTokenANGLE": HEX_LONG_LONG_FORMAT, # CL-specific types "size_t": "%zu", "cl_char": "%hhd", @@ -1346,6 +1301,17 @@ class ErrorSet; // It can interfere with the debug events being set by the caller. // """ +TEMPLATE_MAPBUFFERRANGE_RETURN_MODIFICATION = """\ +#if ANGLE_CAPTURE_ENABLED + angle::FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared(); + if (returnValue != nullptr && frameCaptureShared->enabled()) + { + Buffer *buffer = context->getState().getTargetBuffer(targetPacked); + ASSERT(buffer); + returnValue = frameCaptureShared->maybeGetShadowMemoryPointer(buffer, length, access); + } +#endif""" + TEMPLATE_CAPTURE_PROTO = "angle::CallCapture Capture%s(%s);" TEMPLATE_VALIDATION_PROTO = "%s Validate%s(%s);" @@ -1680,9 +1646,9 @@ def is_aliasing_excepted(api, cmd_name): return api == apis.GLES and cmd_name in ALIASING_EXCEPTIONS -def is_allowed_with_active_pixel_local_storage(name): - return name in PLS_ALLOW_LIST or any( - [fnmatch.fnmatchcase(name, entry) for entry in PLS_ALLOW_WILDCARDS]) +def is_implicit_pls_disable_command(name): + return name in PLS_DISABLE_LIST or any( + [fnmatch.fnmatchcase(name, entry) for entry in PLS_DISABLE_WILDCARDS]) def is_context_private_state_command(api, name): @@ -1719,17 +1685,92 @@ def is_egl_entry_point_accessing_both_sync_and_non_sync_API_resources(cmd_name): return False -def get_validation_expression(api, cmd_name, entry_point_name, internal_params, is_gles1): +def is_cmd_map_buffer_range(cmd_name): + if cmd_name == "glMapBufferRange" or cmd_name == "glMapBufferRangeEXT": + return True + return False + +def validation_needs_private_state_cache(name): + return name in VALIDATION_NEEDS_PRIVATE_STATE_CACHE_LIST + +def get_validation_expression(api, cmd_name, entry_point_name, internal_params, sources): + if api != "GLES": + return "" + name = strip_api_prefix(cmd_name) - private_params = ["context->getPrivateState()", "context->getMutableErrorSetForValidation()"] - extra_params = private_params if is_context_private_state_command(api, - cmd_name) else ["context"] + private_params = ["context->getPrivateState()"] + if validation_needs_private_state_cache(cmd_name): + private_params += ["context->getPrivateStateCache()"] + private_params += ["context->getMutableErrorSetForValidation()"] + is_private = is_context_private_state_command(api, cmd_name) + extra_params = private_params if is_private else ["context"] expr = "Validate{name}({params})".format( name=name, params=", ".join(extra_params + [entry_point_name] + internal_params)) - if not is_gles1 and not is_allowed_with_active_pixel_local_storage(name): - expr = "(ValidatePixelLocalStorageInactive({extra_params}, {entry_point_name}) && {expr})".format( - extra_params=", ".join(private_params), entry_point_name=entry_point_name, expr=expr) - return expr + + def get_camel_case(name_with_underscores): + words = name_with_underscores.split('_') + words = [words[2]] + [(word[0].upper() + word[1:]) for word in words[3:]] + [words[1]] + return ''.join(words) + + condition = "" + error_suffix = sources[0].replace("_", "") + if sorted(sources) == ["1_0", "2_0"]: + # Entry points existing in all context versions + condition = "true" + elif sorted(sources) == ["1_0", "3_2"]: + # glGetPointerv is a special case: defined in ES 1.0 and ES 3.2 only + condition = "context->getClientVersion() < ES_2_0 || context->getClientVersion() >= ES_3_2" + error_suffix = "1Or32" + elif sources == ["1_0"]: + condition = "context->getClientVersion() < ES_2_0" + elif len(sources) == 1 and sources[0] in ["2_0", "3_0", "3_1", "3_2"]: + condition = "context->getClientVersion() >= ES_{}".format(sources[0]) + else: + assert (sources[0].startswith("GL_")) + exts = map(lambda x: "context->getExtensions().{}".format(get_camel_case(x)), sources) + condition = " || ".join(sorted(list(exts))) + error_suffix = "EXT" + + record_error = "else {{RecordVersionErrorES{}(context, {});}}".format( + error_suffix, entry_point_name) if condition != "true" else "" + + pre_validation = """#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif +""" + + # If a command holds a lock, assert that: + # * passed validation generates no errors + # * failed validation generates exactly one error + lock_assertion = "ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1));" + + # If a command does not hold a lock, assert that: + # * failed validation updates the error counter + # + # Since the error counter is global, it may be incremented from + # other threads thus this assertion is weaker than the one above. + lockless_assertion = "ASSERT(isCallValid || context->getPushedErrorCount() != errorCount);" + + has_lock = not is_context_private_state_command(api, cmd_name) + post_validation = """ +#if defined(ANGLE_ENABLE_ASSERTS) + {} +#endif""".format(lock_assertion if has_lock else lockless_assertion) + + return """bool isCallValid = context->skipValidation(); +if (!isCallValid) +{{ + if (ANGLE_LIKELY({support_condition})) + {{ + {pre_validation}isCallValid = {validation_expression};{post_validation} + }} + {record_error} +}}""".format( + support_condition=condition, + pre_validation=pre_validation, + validation_expression=expr, + post_validation=post_validation, + record_error=record_error) def entry_point_export(api): @@ -1897,6 +1938,7 @@ def is_context_lost_acceptable_cmd(cmd_name): "glGetError", "glGetSync", "glGetQueryObjecti", + "glGetQueryObjectui", "glGetProgramiv", "glGetGraphicsResetStatus", "glGetShaderiv", @@ -1916,15 +1958,15 @@ def get_context_getter_function(cmd_name): def get_valid_context_check(cmd_name): - return "context" + return "ANGLE_LIKELY(context != nullptr)" -def get_constext_lost_error_generator(cmd_name): +def get_constext_lost_error_generator(cmd_name, entry_point_name): # Don't generate context lost errors on commands that accept lost contexts if is_context_lost_acceptable_cmd(cmd_name): return "" - return "GenerateContextLostErrorOnCurrentGlobalContext();" + return "GenerateContextLostErrorOnCurrentGlobalContext({name});".format(name=entry_point_name) def strip_suffix_always(api, name): @@ -1998,7 +2040,7 @@ def get_def_template(api, cmd_name, return_type, has_errcode_ret): def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packed_enums, - packed_param_types, ep_to_object, is_gles1): + packed_param_types, ep_to_object, sources): packed_enums = get_packed_enums(api, cmd_packed_enums, cmd_name, packed_param_types, params) internal_params = [just_the_name_packed(param, packed_enums) for param in params] if internal_params and internal_params[-1] == "errcode_ret": @@ -2042,6 +2084,8 @@ def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packe return_type = proto[:-len(cmd_name)].strip() initialization = "InitBackEnds(%s);\n" % INIT_DICT[cmd_name] if cmd_name in INIT_DICT else "" event_comment = TEMPLATE_EVENT_COMMENT if cmd_name in NO_EVENT_MARKER_EXCEPTIONS_LIST else "" + mapbufferrange_return_modification = TEMPLATE_MAPBUFFERRANGE_RETURN_MODIFICATION if is_cmd_map_buffer_range( + cmd_name) else "" name_no_suffix = strip_suffix(api, cmd_name[2:]) name_lower_no_suffix = name_no_suffix[0:1].lower() + name_no_suffix[1:] entry_point_name = "angle::EntryPoint::GL" + strip_api_prefix(cmd_name) @@ -2082,7 +2126,7 @@ def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packe "egl_capture_params": ", ".join(["thread"] + internal_params), "validation_expression": - get_validation_expression(api, cmd_name, entry_point_name, internal_params, is_gles1), + get_validation_expression(api, cmd_name, entry_point_name, internal_params, sources), "format_params": ", ".join(format_params), "context_getter": @@ -2090,13 +2134,17 @@ def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packe "valid_context_check": get_valid_context_check(cmd_name), "constext_lost_error_generator": - get_constext_lost_error_generator(cmd_name), + get_constext_lost_error_generator(cmd_name, entry_point_name), "event_comment": event_comment, + "mapbufferrange_return_modification": + mapbufferrange_return_modification, "labeled_object": get_egl_entry_point_labeled_object(ep_to_object, cmd_name, params, packed_enums), "context_lock": get_context_lock(api, cmd_name), + "implicit_pls_disable": + get_implicit_pls_disable(cmd_name), "preamble": get_preamble(api, cmd_name, params), "epilog": @@ -2167,8 +2215,11 @@ def format_capture_method(api, command, cmd_name, proto, params, all_param_types api, cmd_name, ([context_param_typed, "bool isCallValid"] if api != apis.CL else ["bool isCallValid"]) + params, cmd_packed_gl_enums, packed_param_types) + params_with_type_param_header = get_internal_params( + api, cmd_name, ([context_param_typed] if api != apis.CL else []) + params, + cmd_packed_gl_enums, packed_param_types) params_just_name = ", ".join( - ([context_param_name, "isCallValid"] if api != apis.CL else ["isCallValid"]) + + ([context_param_name] if api != apis.CL else []) + [just_the_name_packed(param, packed_gl_enums) for param in params]) parameter_captures = [] @@ -2199,7 +2250,8 @@ def format_capture_method(api, command, cmd_name, proto, params, all_param_types cast_type=param_type) capture_pointer_func = TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC.format( - name=capture_name, params=params_with_type + ", angle::ParamCapture *paramCapture") + name=capture_name, + params=params_with_type_param_header + ", angle::ParamCapture *paramCapture") capture_pointer_funcs += [capture_pointer_func] elif capture_param_type in ('GLenum', 'GLbitfield'): gl_enum_group = find_gl_enum_group_in_command(command, param_name) @@ -2336,9 +2388,14 @@ def format_validation_proto(api, cmd_name, params, cmd_packed_gl_enums, packed_p else: return_type = "bool" if api in [apis.GL, apis.GLES]: - with_extra_params = ["const PrivateState &state", - "ErrorSet *errors"] if is_context_private_state_command( - api, cmd_name) else ["Context *context"] + with_extra_params = [] + if is_context_private_state_command(api, cmd_name): + with_extra_params += ["const PrivateState &state"] + if validation_needs_private_state_cache(cmd_name): + with_extra_params += ["const PrivateStateCache &privateStateCache"] + with_extra_params += ["ErrorSet *errors"] + else: + with_extra_params += ["Context *context"] with_extra_params += ["angle::EntryPoint entryPoint"] + params elif api == apis.EGL: with_extra_params = ["ValidationContext *val"] + params @@ -2397,8 +2454,7 @@ def __init__(self, cmd_packed_enums, export_template=TEMPLATE_GL_ENTRY_POINT_EXPORT, packed_param_types=[], - ep_to_object={}, - is_gles1=False): + ep_to_object={}): super().__init__(api, xml, commands) self.decls = [] @@ -2417,7 +2473,7 @@ def __init__(self, self.defs.append( format_entry_point_def(self.api, command_node, cmd_name, proto_text, param_text, cmd_packed_enums, packed_param_types, ep_to_object, - is_gles1)) + xml.sources_by_command[cmd_name])) self.export_defs.append( format_entry_point_export(cmd_name, proto_text, param_text, export_template)) @@ -2454,14 +2510,9 @@ class GLEntryPoints(ANGLEEntryPoints): all_param_types = set() - def __init__(self, api, xml, commands, is_gles1=False): - super().__init__( - api, - xml, - commands, - GLEntryPoints.all_param_types, - GLEntryPoints.get_packed_enums(), - is_gles1=is_gles1) + def __init__(self, api, xml, commands): + super().__init__(api, xml, commands, GLEntryPoints.all_param_types, + GLEntryPoints.get_packed_enums()) _packed_enums = None @@ -2566,6 +2617,8 @@ def get_decls(api, if is_context_private_state_command(api, cmd_name): continue + already_included.append(name_no_suffix) + param_text = ["".join(param.itertext()) for param in command.findall('param')] proto_text = "".join(proto.itertext()) decls.append( @@ -3089,23 +3142,19 @@ def format_replay_params(api, command_name, param_text_list, packed_enums, resou capture_type = get_capture_param_type_name(param_type) union_name = get_param_type_union_name(capture_type) param_access = 'captures[%d].value.%s' % (i, union_name) - # Workaround for https://github.com/KhronosGroup/OpenGL-Registry/issues/545 - if command_name == 'glCreateShaderProgramvEXT' and i == 2: - param_access = 'const_cast(%s)' % param_access - else: - cmd_no_suffix = strip_suffix(api, command_name) - if cmd_no_suffix in packed_enums and param_name in packed_enums[cmd_no_suffix]: - packed_type = remove_id_suffix(packed_enums[cmd_no_suffix][param_name]) - if packed_type == 'Sync': - param_access = 'gSyncMap2[captures[%d].value.GLuintVal]' % i - elif packed_type in resource_id_types: - param_access = 'g%sMap[%s]' % (packed_type, param_access) - elif packed_type == 'UniformLocation': - param_access = 'gUniformLocations[gCurrentProgram][%s]' % param_access - elif packed_type == 'egl::Image': - param_access = 'gEGLImageMap2[captures[%d].value.GLuintVal]' % i - elif packed_type == 'egl::Sync': - param_access = 'gEGLSyncMap[captures[%d].value.egl_SyncIDVal]' % i + cmd_no_suffix = strip_suffix(api, command_name) + if cmd_no_suffix in packed_enums and param_name in packed_enums[cmd_no_suffix]: + packed_type = remove_id_suffix(packed_enums[cmd_no_suffix][param_name]) + if packed_type == 'Sync': + param_access = 'gSyncMap2[captures[%d].value.GLuintVal]' % i + elif packed_type in resource_id_types: + param_access = 'g%sMap[%s]' % (packed_type, param_access) + elif packed_type == 'UniformLocation': + param_access = 'gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][%s]' % param_access + elif packed_type == 'egl::Image': + param_access = 'gEGLImageMap2[captures[%d].value.GLuintVal]' % i + elif packed_type == 'egl::Sync': + param_access = 'gEGLSyncMap[captures[%d].value.egl_SyncIDVal]' % i param_access_strs.append(param_access) return ', '.join(param_access_strs) @@ -3309,7 +3358,6 @@ def get_prepare_swap_buffers_call(api, cmd_name, params): if cmd_name not in [ "eglSwapBuffers", "eglSwapBuffersWithDamageKHR", - "eglSwapBuffersWithFrameTokenANGLE", "eglQuerySurface", "eglQuerySurface64KHR", ]: @@ -3327,13 +3375,24 @@ def get_prepare_swap_buffers_call(api, cmd_name, params): prepareCall = "ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(%s));" % (", ".join( [just_the_name(param) for param in passed_params])) - # For eglQuerySurface, the prepare call is only needed for EGL_BUFFER_AGE + # For eglQuerySurface, the prepare call is needed for EGL_BUFFER_AGE + # and EGL_SURFACE_COMPRESSION_EXT if cmd_name in ["eglQuerySurface", "eglQuerySurface64KHR"]: - prepareCall = "if (attribute == EGL_BUFFER_AGE_EXT) {" + prepareCall + "}" + prepareCall = "if (attribute == EGL_BUFFER_AGE_EXT || attribute == EGL_SURFACE_COMPRESSION_EXT) {" + prepareCall + "}" return prepareCall +def get_implicit_pls_disable(cmd_name): + if not is_implicit_pls_disable_command(cmd_name): + return "" + + return "if (context->getState().getPixelLocalStorageActivePlanes() != 0)" \ + "{" \ + "context->endPixelLocalStorageImplicit();" \ + "}" + + def get_preamble(api, cmd_name, params): preamble = "" preamble += get_prepare_swap_buffers_call(api, cmd_name, params) @@ -3351,9 +3410,8 @@ def get_unlocked_tail_call(api, cmd_name): # # - eglPrepareSwapBuffersANGLE -> Calls vkAcquireNextImageKHR in tail call # - # - eglSwapBuffers, eglSwapBuffersWithDamageKHR and - # eglSwapBuffersWithFrameTokenANGLE -> May throttle the CPU in tail call or - # calls native EGL function + # - eglSwapBuffers and eglSwapBuffersWithDamageKHR -> May throttle the CPU + # in tail call or calls native EGL function # # - eglClientWaitSyncKHR, eglClientWaitSync, glClientWaitSync, # glFinishFenceNV -> May wait on fence in tail call or call native EGL function @@ -3376,8 +3434,8 @@ def get_unlocked_tail_call(api, cmd_name): if (cmd_name in [ 'eglDestroySurface', 'eglMakeCurrent', 'eglReleaseThread', 'eglCreateWindowSurface', 'eglCreatePlatformWindowSurface', 'eglCreatePlatformWindowSurfaceEXT', - 'eglPrepareSwapBuffersANGLE', 'eglSwapBuffersWithFrameTokenANGLE', 'glFinishFenceNV', - 'glCompileShader', 'glLinkProgram', 'glShaderBinary', 'glFlush', 'glFinish' + 'eglPrepareSwapBuffersANGLE', 'glFinishFenceNV', 'glCompileShader', 'glLinkProgram', + 'glShaderBinary', 'glFlush', 'glFinish' ] or cmd_name.startswith('glTexImage2D') or cmd_name.startswith('glTexImage3D') or cmd_name.startswith('glTexSubImage2D') or cmd_name.startswith('glTexSubImage3D') or cmd_name.startswith('glCompressedTexImage2D') or @@ -3504,6 +3562,7 @@ def main(): '../src/libANGLE/validationESEXT_autogen.h', '../src/libEGL/libEGL_autogen.cpp', '../src/libEGL/libEGL_autogen.def', + '../src/libEGL/libEGL_vulkan_secondaries_autogen.def', '../src/libGLESv2/entry_points_cl_autogen.cpp', '../src/libGLESv2/entry_points_cl_autogen.h', '../src/libGLESv2/entry_points_egl_autogen.cpp', @@ -3526,6 +3585,7 @@ def main(): '../src/libGLESv2/libGLESv2_autogen.def', '../src/libGLESv2/libGLESv2_no_capture_autogen.def', '../src/libGLESv2/libGLESv2_with_capture_autogen.def', + '../src/libGLESv2/libGLESv2_vulkan_secondaries_autogen.def', '../src/libGLESv2/egl_context_lock_autogen.h', '../util/capture/frame_capture_replay_autogen.cpp', ] @@ -3560,6 +3620,14 @@ def main(): context_private_call_protos = [] context_private_call_functions = set() + # Build commands cache + for major_version, minor_version in registry_xml.GLES_VERSIONS: + version = "{}_{}".format(major_version, minor_version) + name_prefix = "GL_VERSION_ES_CM_" if major_version == 1 else "GL_ES_VERSION_" + feature_name = "{}{}".format(name_prefix, version) + xml.AddCommands(feature_name, version) + xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1']) + # First run through the main GLES entry points. Since ES2+ is the primary use # case, we go through those first and then add ES1-only APIs at the end. for major_version, minor_version in registry_xml.GLES_VERSIONS: @@ -3573,13 +3641,11 @@ def main(): comment = version.replace("_", ".") feature_name = "{}{}".format(name_prefix, version) - xml.AddCommands(feature_name, version) - version_commands = xml.commands[version] all_commands_no_suffix.extend(xml.commands[version]) all_commands_with_suffix.extend(xml.commands[version]) - eps = GLEntryPoints(apis.GLES, xml, version_commands, is_gles1=(major_version == 1)) + eps = GLEntryPoints(apis.GLES, xml, version_commands) eps.decls.insert(0, "extern \"C\" {") eps.decls.append("} // extern \"C\"") eps.defs.insert(0, "extern \"C\" {") @@ -3641,14 +3707,11 @@ def main(): for angle_ext in registry_xml.angle_extensions: glesdecls['exts']['ANGLE Extensions'][angle_ext] = [] - xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1']) - for extension_name, ext_cmd_names in sorted(xml.ext_data.items()): extension_commands.extend(xml.ext_data[extension_name]) # Detect and filter duplicate extensions. - is_gles1 = extension_name in registry_xml.gles1_extensions - eps = GLEntryPoints(apis.GLES, xml, ext_cmd_names, is_gles1=is_gles1) + eps = GLEntryPoints(apis.GLES, xml, ext_cmd_names) # Write the extension name as a comment before the first EP. comment = "\n// {}".format(extension_name) @@ -3695,7 +3758,6 @@ def main(): for name in extension_commands: all_commands_with_suffix.append(name) - all_commands_no_suffix.append(strip_suffix(apis.GLES, name)) # OpenCL clxml = registry_xml.RegistryXML('cl.xml') diff --git a/scripts/generate_stats.py b/scripts/generate_stats.py deleted file mode 100755 index c77bae4cda0..00000000000 --- a/scripts/generate_stats.py +++ /dev/null @@ -1,818 +0,0 @@ -#!/usr/bin/env vpython -# -# [VPYTHON:BEGIN] -# wheel: < -# name: "infra/python/wheels/google-auth-py2_py3" -# version: "version:1.2.1" -# > -# -# wheel: < -# name: "infra/python/wheels/pyasn1-py2_py3" -# version: "version:0.4.5" -# > -# -# wheel: < -# name: "infra/python/wheels/pyasn1_modules-py2_py3" -# version: "version:0.2.4" -# > -# -# wheel: < -# name: "infra/python/wheels/six" -# version: "version:1.10.0" -# > -# -# wheel: < -# name: "infra/python/wheels/cachetools-py2_py3" -# version: "version:2.0.1" -# > -# wheel: < -# name: "infra/python/wheels/rsa-py2_py3" -# version: "version:4.0" -# > -# -# wheel: < -# name: "infra/python/wheels/requests" -# version: "version:2.13.0" -# > -# -# wheel: < -# name: "infra/python/wheels/google-api-python-client-py2_py3" -# version: "version:1.6.2" -# > -# -# wheel: < -# name: "infra/python/wheels/httplib2-py2_py3" -# version: "version:0.12.1" -# > -# -# wheel: < -# name: "infra/python/wheels/oauth2client-py2_py3" -# version: "version:3.0.0" -# > -# -# wheel: < -# name: "infra/python/wheels/uritemplate-py2_py3" -# version: "version:3.0.0" -# > -# -# wheel: < -# name: "infra/python/wheels/google-auth-oauthlib-py2_py3" -# version: "version:0.3.0" -# > -# -# wheel: < -# name: "infra/python/wheels/requests-oauthlib-py2_py3" -# version: "version:1.2.0" -# > -# -# wheel: < -# name: "infra/python/wheels/oauthlib-py2_py3" -# version: "version:3.0.1" -# > -# -# wheel: < -# name: "infra/python/wheels/google-auth-httplib2-py2_py3" -# version: "version:0.0.3" -# > -# [VPYTHON:END] -# -# Copyright 2019 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. -# -# generate_deqp_stats.py: -# Checks output of deqp testers and generates stats using the GDocs API -# -# prerequirements: -# https://devsite.googleplex.com/sheets/api/quickstart/python -# Follow the quickstart guide. -# -# usage: generate_deqp_stats.py [-h] [--auth_path [AUTH_PATH]] [--spreadsheet [SPREADSHEET]] -# [--verbosity [VERBOSITY]] -# -# optional arguments: -# -h, --help show this help message and exit -# --auth_path [AUTH_PATH] -# path to directory containing authorization data (credentials.json and -# token.pickle). [default=/.auth] -# --spreadsheet [SPREADSHEET] -# ID of the spreadsheet to write stats to. [default -# ='1D6Yh7dAPP-aYLbX3HHQD8WubJV9XPuxvkKowmn2qhIw'] -# --verbosity [VERBOSITY] -# Verbosity of output. Valid options are [DEBUG, INFO, WARNING, ERROR]. -# [default=INFO] - -import argparse -import datetime -import logging -import os -import pickle -import re -import subprocess -import sys -import urllib -from google.auth.transport.requests import Request -from googleapiclient.discovery import build -from google_auth_oauthlib.flow import InstalledAppFlow - -#################### -# Global Constants # -#################### - -HOME_DIR = os.path.expanduser('~') -SCRIPT_DIR = sys.path[0] -ROOT_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, '..')) - -LOGGER = logging.getLogger('generate_stats') - -SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] - -BOT_NAMES = [ - 'mac-angle-amd', - 'mac-angle-intel', - 'win10-angle-x64-nvidia', - 'win10-angle-x64-intel', - 'win7-angle-x64-nvidia', - 'win7-angle-x86-amd', - 'Linux FYI dEQP Release (Intel HD 630)', - 'Linux FYI dEQP Release (NVIDIA)', - 'Android FYI dEQP Release (Nexus 5X)', - 'Android FYI 32 dEQP Vk Release (Pixel 2)', - 'Android FYI 64 dEQP Vk Release (Pixel 2)', -] -BOT_NAME_PREFIX = 'chromium/ci/' -BUILD_LINK_PREFIX = 'https://ci.chromium.org/p/chromium/builders/ci/' - -REQUIRED_COLUMNS = ['build_link', 'time', 'date', 'revision', 'angle_revision', 'duplicate'] -MAIN_RESULT_COLUMNS = ['Passed', 'Failed', 'Skipped', 'Not Supported', 'Exception', 'Crashed'] - -INFO_TAG = '*RESULT' - -WORKAROUND_FORMATTING_ERROR_STRING = "Still waiting for the following processes to finish:" - -###################### -# Build Info Parsing # -###################### - - -# Returns a struct with info about the latest successful build given a bot name. Info contains the -# build_name, time, date, angle_revision, and chrome revision. -# Uses: bb ls '' -n 1 -status success -p -def get_latest_success_build_info(bot_name): - bb = subprocess.Popen(['bb', 'ls', bot_name, '-n', '1', '-status', 'success', '-p'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - LOGGER.debug("Ran [bb ls '" + bot_name + "' -n 1 -status success -p]") - out, err = bb.communicate() - if err: - raise ValueError("Unexpected error from bb ls: '" + err + "'") - if not out: - raise ValueError("Unexpected empty result from bb ls of bot '" + bot_name + "'") - # Example output (line 1): - # ci.chromium.org/b/8915280275579996928 SUCCESS 'chromium/ci/Win10 FYI dEQP Release (NVIDIA)/26877' - # ... - if 'SUCCESS' not in out: - raise ValueError("Unexpected result from bb ls: '" + out + "'") - info = {} - for line in out.splitlines(): - # The first line holds the build name - if 'build_name' not in info: - info['build_name'] = line.strip().split("'")[1] - # Remove the bot name and prepend the build link - info['build_link'] = BUILD_LINK_PREFIX + urllib.quote( - info['build_name'].split(BOT_NAME_PREFIX)[1]) - if 'Created' in line: - # Example output of line with 'Created': - # ... - # Created today at 12:26:39, waited 2.056319s, started at 12:26:41, ran for 1h16m48.14963s, ended at 13:43:30 - # ... - info['time'] = re.findall(r'[0-9]{1,2}:[0-9]{2}:[0-9]{2}', line.split(',', 1)[0])[0] - # Format today's date in US format so Sheets can read it properly - info['date'] = datetime.datetime.now().strftime('%m/%d/%y') - if 'got_angle_revision' in line: - # Example output of line with angle revision: - # ... - # "parent_got_angle_revision": "8cbd321cafa92ffbf0495e6d0aeb9e1a97940fee", - # ... - info['angle_revision'] = filter(str.isalnum, line.split(':')[1]) - if '"revision"' in line: - # Example output of line with chromium revision: - # ... - # "revision": "3b68405a27f1f9590f83ae07757589dba862f141", - # ... - info['revision'] = filter(str.isalnum, line.split(':')[1]) - if 'build_name' not in info: - raise ValueError("Could not find build_name from bot '" + bot_name + "'") - return info - - -# Returns a list of step names that we're interested in given a build name. We are interested in -# step names starting with 'angle_'. May raise an exception. -# Uses: bb get '' -steps -def get_step_names(build_name): - bb = subprocess.Popen(['bb', 'get', build_name, '-steps'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - LOGGER.debug("Ran [bb get '" + build_name + "' -steps]") - out, err = bb.communicate() - if err: - raise ValueError("Unexpected error from bb get: '" + err + "'") - step_names = [] - # Example output (relevant lines to a single step): - # ... - # Step "angle_deqp_egl_vulkan_tests on (nvidia-quadro-p400-win10-stable) GPU on Windows on Windows-10" SUCCESS 4m12s Logs: "stdout", "chromium_swarming.summary", "Merge script log", "Flaky failure: dEQP.EGL/info_version (status CRASH,SUCCESS)", "step_metadata" - # Run on OS: 'Windows-10'
Max shard duration: 0:04:07.309848 (shard \#1)
Min shard duration: 0:02:26.402128 (shard \#0)
flaky failures [ignored]:
dEQP.EGL/info\_version
- # * [shard #0 isolated out](https://isolateserver.appspot.com/browse?namespace=default-gzip&hash=9a5999a59d332e55f54f495948d0c9f959e60ed2) - # * [shard #0 (128.3 sec)](https://chromium-swarm.appspot.com/user/task/446903ae365b8110) - # * [shard #1 isolated out](https://isolateserver.appspot.com/browse?namespace=default-gzip&hash=d71e1bdd91dee61b536b4057a9222e642bd3809f) - # * [shard #1 (229.3 sec)](https://chromium-swarm.appspot.com/user/task/446903b7b0d90210) - # * [shard #2 isolated out](https://isolateserver.appspot.com/browse?namespace=default-gzip&hash=ac9ba85b1cca77774061b87335c077980e1eef85) - # * [shard #2 (144.5 sec)](https://chromium-swarm.appspot.com/user/task/446903c18e15a010) - # * [shard #3 isolated out](https://isolateserver.appspot.com/browse?namespace=default-gzip&hash=976d586386864abecf53915fbac3e085f672e30f) - # * [shard #3 (138.4 sec)](https://chromium-swarm.appspot.com/user/task/446903cc8da0ad10) - # ... - for line in out.splitlines(): - if 'Step "angle_' not in line: - continue - step_names.append(line.split('"')[1]) - return step_names - - -# Performs some heuristic validation of the step_info struct returned from a single step log. -# Returns True if valid, False if invalid. May write to stderr -def validate_step_info(step_info, build_name, step_name): - print_name = "'" + build_name + "': '" + step_name + "'" - if not step_info: - LOGGER.warning('Step info empty for ' + print_name + '\n') - return False - - if 'Total' in step_info: - partial_sum_keys = MAIN_RESULT_COLUMNS - partial_sum_values = [int(step_info[key]) for key in partial_sum_keys if key in step_info] - computed_total = sum(partial_sum_values) - if step_info['Total'] != computed_total: - LOGGER.warning('Step info does not sum to total for ' + print_name + ' | Total: ' + - str(step_info['Total']) + ' - Computed total: ' + str(computed_total) + - '\n') - return True - - -# Returns a struct containing parsed info from a given step log. The info is parsed by looking for -# lines with the following format in stdout: -# '[TESTSTATS]: : '' -# May write to stderr -# Uses: bb log '' '' -def get_step_info(build_name, step_name): - bb = subprocess.Popen(['bb', 'log', build_name, step_name], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - LOGGER.debug("Ran [bb log '" + build_name + "' '" + step_name + "']") - out, err = bb.communicate() - if err: - LOGGER.warning("Unexpected error from bb log '" + build_name + "' '" + step_name + "': '" + - err + "'") - return None - step_info = {} - # Example output (relevant lines of stdout): - # ... - # *RESULT: Total: 155 - # *RESULT: Passed: 11 - # *RESULT: Failed: 0 - # *RESULT: Skipped: 12 - # *RESULT: Not Supported: 132 - # *RESULT: Exception: 0 - # *RESULT: Crashed: 0 - # *RESULT: Unexpected Passed: 12 - # ... - append_errors = [] - # Hacky workaround to fix issue where messages are dropped into the middle of lines by another - # process: - # eg. - # *RESULT: Still waiting for the following processes to finish: - # "c:\b\s\w\ir\out\Release\angle_deqp_gles3_tests.exe" --deqp-egl-display-type=angle-vulkan --gtest_flagfile="c:\b\s\w\itlcgdrz\scoped_dir7104_364984996\8ad93729-f679-406d-973b-06b9d1bf32de.tmp" --single-process-tests --test-launcher-batch-limit=400 --test-launcher-output="c:\b\s\w\itlcgdrz\7104_437216092\test_results.xml" --test-launcher-summary-output="c:\b\s\w\iosuk8ai\output.json" - # - # - # Removes the message and skips the line following it, and then appends the - # and back together - workaround_prev_line = "" - workaround_prev_line_count = 0 - for line in out.splitlines(): - # Skip lines if the workaround still has lines to skip - if workaround_prev_line_count > 0: - workaround_prev_line_count -= 1 - continue - # If there are no more lines to skip and there is a previous to append, - # append it and finish the workaround - elif workaround_prev_line != "": - line = workaround_prev_line + line - workaround_prev_line = "" - workaround_prev_line_count = 0 - LOGGER.debug("Formatting error workaround rebuilt line as: '" + line + "'\n") - - if INFO_TAG not in line: - continue - - # When the workaround string is detected, start the workaround with 1 line to skip and save - # the , but continue the loop until the workaround is finished - if WORKAROUND_FORMATTING_ERROR_STRING in line: - workaround_prev_line = line.split(WORKAROUND_FORMATTING_ERROR_STRING)[0] - workaround_prev_line_count = 1 - continue - - found_stat = True - line_columns = line.split(INFO_TAG, 1)[1].split(':') - if len(line_columns) is not 3: - LOGGER.warning("Line improperly formatted: '" + line + "'\n") - continue - key = line_columns[1].strip() - # If the value is clearly an int, sum it. Otherwise, concatenate it as a string - isInt = False - intVal = 0 - try: - intVal = int(line_columns[2]) - if intVal is not None: - isInt = True - except Exception as error: - isInt = False - - if isInt: - if key not in step_info: - step_info[key] = 0 - step_info[key] += intVal - else: - if key not in step_info: - step_info[key] = line_columns[2].strip() - else: - append_string = '\n' + line_columns[2].strip() - # Sheets has a limit of 50000 characters per cell, so make sure to stop appending - # below this limit - if len(step_info[key]) + len(append_string) < 50000: - step_info[key] += append_string - else: - if key not in append_errors: - append_errors.append(key) - LOGGER.warning("Too many characters in column '" + key + - "'. Output capped.") - return step_info - - -# Returns the info for each step run on a given bot_name. -def get_bot_info(bot_name): - info = get_latest_success_build_info(bot_name) - info['step_names'] = get_step_names(info['build_name']) - broken_step_names = [] - for step_name in info['step_names']: - LOGGER.info("Parsing step '" + step_name + "'...") - step_info = get_step_info(info['build_name'], step_name) - if validate_step_info(step_info, info['build_name'], step_name): - info[step_name] = step_info - else: - broken_step_names += step_name - for step_name in broken_step_names: - info['step_names'].remove(step_name) - return info - - -##################### -# Sheets Formatting # -##################### - - -# Get an individual spreadsheet based on the spreadsheet id. Returns the result of -# spreadsheets.get(), or throws an exception if the sheet could not open. -def get_spreadsheet(service, spreadsheet_id): - LOGGER.debug("Called [spreadsheets.get(spreadsheetId='" + spreadsheet_id + "')]") - request = service.get(spreadsheetId=spreadsheet_id) - spreadsheet = request.execute() - if not spreadsheet: - raise Exception("Did not open spreadsheet '" + spreadsheet_id + "'") - return spreadsheet - - -# Returns a nicely formatted string based on the bot_name and step_name -def format_sheet_name(bot_name, step_name): - # Some tokens should be ignored for readability in the name - unneccesary_tokens = ['FYI', 'Release', 'Vk', 'dEQP', '(', ')'] - for token in unneccesary_tokens: - bot_name = bot_name.replace(token, '') - bot_name = ' '.join(bot_name.strip().split()) # Remove extra spaces - step_name = re.findall(r'angle\w*', step_name)[0] # Separate test name - # Test names are formatted as 'angle_deqp___tests' - new_step_name = '' - # Put the frontend first - if '_egl_' in step_name: - step_name = step_name.replace('_egl_', '_') - new_step_name += ' EGL' - if '_gles2_' in step_name: - step_name = step_name.replace('_gles2_', '_') - new_step_name += ' GLES 2.0 ' - if '_gles3_' in step_name: - step_name = step_name.replace('_gles3_', '_') - new_step_name += ' GLES 3.0 ' - if '_gles31_' in step_name: - step_name = step_name.replace('_gles31_', '_') - new_step_name += ' GLES 3.1 ' - # Put the backend second - if '_d3d9_' in step_name: - step_name = step_name.replace('_d3d9_', '_') - new_step_name += ' D3D9 ' - if '_d3d11' in step_name: - step_name = step_name.replace('_d3d11_', '_') - new_step_name += ' D3D11 ' - if '_gl_' in step_name: - step_name = step_name.replace('_gl_', '_') - new_step_name += ' Desktop OpenGL ' - if '_gles_' in step_name: - step_name = step_name.replace('_gles_', '_') - new_step_name += ' OpenGLES ' - if '_vulkan_' in step_name: - step_name = step_name.replace('_vulkan_', '_') - new_step_name += ' Vulkan ' - # Add any remaining keywords from the step name into the formatted name (formatted nicely) - step_name = step_name.replace('angle_', '_') - step_name = step_name.replace('_deqp_', '_') - step_name = step_name.replace('_tests', '_') - step_name = step_name.replace('_', ' ').strip() - new_step_name += ' ' + step_name - new_step_name = ' '.join(new_step_name.strip().split()) # Remove extra spaces - return new_step_name + ' ' + bot_name - - -# Returns the full list of sheet names that should be populated based on the info struct -def get_sheet_names(info): - sheet_names = [] - for bot_name in info: - for step_name in info[bot_name]['step_names']: - sheet_name = format_sheet_name(bot_name, step_name) - sheet_names.append(sheet_name) - return sheet_names - - -# Returns True if the sheet is found in the spreadsheets object -def sheet_exists(spreadsheet, step_name): - for sheet in spreadsheet['sheets']: - if sheet['properties']['title'] == step_name: - return True - return False - - -# Validates the spreadsheets object against the list of sheet names which should appear. Returns a -# list of sheets that need creation. -def validate_sheets(spreadsheet, sheet_names): - create_sheets = [] - for sheet_name in sheet_names: - if not sheet_exists(spreadsheet, sheet_name): - create_sheets.append(sheet_name) - return create_sheets - - -# Performs a batch update with a given service, spreadsheet id, and list of -# updates to do. -def batch_update(service, spreadsheet_id, updates): - batch_update_request_body = { - 'requests': updates, - } - LOGGER.debug("Called [spreadsheets.batchUpdate(spreadsheetId='" + spreadsheet_id + "', body=" + - str(batch_update_request_body) + ')]') - request = service.batchUpdate(spreadsheetId=spreadsheet_id, body=batch_update_request_body) - request.execute() - - -# Creates sheets given a service and spreadsheed id based on a list of sheet names input -def create_sheets(service, spreadsheet_id, sheet_names): - updates = [{'addSheet': {'properties': {'title': sheet_name,}}} for sheet_name in sheet_names] - batch_update(service, spreadsheet_id, updates) - - -# Calls a values().batchGet() on the service to find the list of column names from each sheet in -# sheet_names. Returns a dictionary with one list per sheet_name. -def get_headers(service, spreadsheet_id, sheet_names): - header_ranges = [sheet_name + '!A1:Z' for sheet_name in sheet_names] - LOGGER.debug("Called [spreadsheets.values().batchGet(spreadsheetId='" + spreadsheet_id + - ', ranges=' + str(header_ranges) + "')]") - request = service.values().batchGet(spreadsheetId=spreadsheet_id, ranges=header_ranges) - response = request.execute() - headers = {} - for k, sheet_name in enumerate(sheet_names): - if 'values' in response['valueRanges'][k]: - # Headers are in the first row of values - headers[sheet_name] = response['valueRanges'][k]['values'][0] - else: - headers[sheet_name] = [] - return headers - - -# Calls values().batchUpdate() with supplied list of data to update on the -# service. -def batch_update_values(service, spreadsheet_id, data): - batch_update_values_request_body = { - 'valueInputOption': 'USER_ENTERED', # Helps with formatting of dates - 'data': data, - } - LOGGER.debug("Called [spreadsheets.values().batchUpdate(spreadsheetId='" + spreadsheet_id + - "', body=" + str(batch_update_values_request_body) + ')]') - request = service.values().batchUpdate( - spreadsheetId=spreadsheet_id, body=batch_update_values_request_body) - request.execute() - - -# Get the sheetId of a sheet based on its name -def get_sheet_id(spreadsheet, sheet_name): - for sheet in spreadsheet['sheets']: - if sheet['properties']['title'] == sheet_name: - return sheet['properties']['sheetId'] - return -1 - - -# Update the filters on sheets with a 'duplicate' column. Filter out any duplicate rows -def update_filters(service, spreadsheet_id, headers, info, spreadsheet): - updates = [] - for bot_name in info: - for step_name in info[bot_name]['step_names']: - sheet_name = format_sheet_name(bot_name, step_name) - duplicate_found = 'duplicate' in headers[sheet_name] - if duplicate_found: - sheet_id = get_sheet_id(spreadsheet, sheet_name) - if sheet_id > -1: - updates.append({ - "setBasicFilter": { - "filter": { - "range": { - "sheetId": sheet_id, - "startColumnIndex": 0, - "endColumnIndex": len(headers[sheet_name]) - }, - "sortSpecs": [{ - "dimensionIndex": headers[sheet_name].index('date'), - "sortOrder": "ASCENDING" - }], - "criteria": { - str(headers[sheet_name].index('duplicate')): { - "hiddenValues": - ["1"] # Hide rows when duplicate is 1 (true) - } - } - } - } - }) - if updates: - LOGGER.info('Updating sheet filters...') - batch_update(service, spreadsheet_id, updates) - -# Populates the headers with any missing/desired rows based on the info struct, and calls -# batch update to update the corresponding sheets if necessary. -def update_headers(service, spreadsheet_id, headers, info): - data = [] - sheet_names = [] - for bot_name in info: - for step_name in info[bot_name]['step_names']: - if not step_name in info[bot_name]: - LOGGER.error("Missing info for step name: '" + step_name + "'") - sheet_name = format_sheet_name(bot_name, step_name) - headers_stale = False - # Headers should always contain the following columns - for req in REQUIRED_COLUMNS: - if req not in headers[sheet_name]: - headers_stale = True - headers[sheet_name].append(req) - # Headers also must contain all the keys seen in this step - for key in info[bot_name][step_name].keys(): - if key not in headers[sheet_name]: - headers_stale = True - headers[sheet_name].append(key) - # Update the Gdoc headers if necessary - if headers_stale: - sheet_names.append(sheet_name) - header_range = sheet_name + '!A1:Z' - data.append({ - 'range': header_range, - 'majorDimension': 'ROWS', - 'values': [headers[sheet_name]] - }) - if data: - LOGGER.info('Updating sheet headers...') - batch_update_values(service, spreadsheet_id, data) - -# Calls values().append() to append a list of values to a given sheet. -def append_values(service, spreadsheet_id, sheet_name, values): - header_range = sheet_name + '!A1:Z' - insert_data_option = 'INSERT_ROWS' - value_input_option = 'USER_ENTERED' # Helps with formatting of dates - append_values_request_body = { - 'range': header_range, - 'majorDimension': 'ROWS', - 'values': [values], - } - LOGGER.debug("Called [spreadsheets.values().append(spreadsheetId='" + spreadsheet_id + - "', body=" + str(append_values_request_body) + ", range='" + header_range + - "', insertDataOption='" + insert_data_option + "', valueInputOption='" + - value_input_option + "')]") - request = service.values().append( - spreadsheetId=spreadsheet_id, - body=append_values_request_body, - range=header_range, - insertDataOption=insert_data_option, - valueInputOption=value_input_option) - request.execute() - - -# Formula to determine whether a row is a duplicate of the previous row based on checking the -# columns listed in filter_columns. -# Eg. -# date | pass | fail -# Jan 1 100 50 -# Jan 2 100 50 -# Jan 3 99 51 -# -# If we want to filter based on only the "pass" and "fail" columns, we generate the following -# formula in the 'duplicate' column: 'IF(B1=B0, IF(C1=C0,1,0) ,0); -# This formula is recursively generated for each column in filter_columns, using the column -# position as determined by headers. The formula uses a more generalized form with -# 'INDIRECT(ADDRESS(, ))'' instead of 'B1', where is Row() and Row()-1, and col is -# determined by the column's position in headers -def generate_duplicate_formula(headers, filter_columns): - # No more columns, put a 1 in the IF statement true branch - if len(filter_columns) == 0: - return '1' - # Next column is found, generate the formula for duplicate checking, and remove from the list - # for recursion - for i in range(len(headers)): - if headers[i] == filter_columns[0]: - col = str(i + 1) - formula = "IF(INDIRECT(ADDRESS(ROW(), " + col + "))=INDIRECT(ADDRESS(ROW() - 1, " + \ - col + "))," + generate_duplicate_formula(headers, filter_columns[1:]) + ",0)" - return formula - # Next column not found, remove from recursion but just return whatever the next one is - return generate_duplicate_formula(headers, filter_columns[1:]) - - -# Helper function to start the recursive call to generate_duplicate_formula -def generate_duplicate_formula_helper(headers): - filter_columns = MAIN_RESULT_COLUMNS - formula = generate_duplicate_formula(headers, filter_columns) - if (formula == "1"): - return "" - else: - # Final result needs to be prepended with = - return "=" + formula - -# Uses the list of headers and the info struct to come up with a list of values for each step -# from the latest builds. -def update_values(service, spreadsheet_id, headers, info): - data = [] - for bot_name in info: - for step_name in info[bot_name]['step_names']: - sheet_name = format_sheet_name(bot_name, step_name) - values = [] - # For each key in the list of headers, either add the corresponding value or add a blank - # value. It's necessary for the values to match the order of the headers - for key in headers[sheet_name]: - if key in info[bot_name] and key in REQUIRED_COLUMNS: - values.append(info[bot_name][key]) - elif key in info[bot_name][step_name]: - values.append(info[bot_name][step_name][key]) - elif key == "duplicate" and key in REQUIRED_COLUMNS: - values.append(generate_duplicate_formula_helper(headers[sheet_name])) - else: - values.append('') - LOGGER.info("Appending new rows to sheet '" + sheet_name + "'...") - try: - append_values(service, spreadsheet_id, sheet_name, values) - except Exception as error: - LOGGER.warning('%s\n' % str(error)) - - -# Updates the given spreadsheed_id with the info struct passed in. -def update_spreadsheet(service, spreadsheet_id, info): - LOGGER.info('Opening spreadsheet...') - spreadsheet = get_spreadsheet(service, spreadsheet_id) - LOGGER.info('Parsing sheet names...') - sheet_names = get_sheet_names(info) - new_sheets = validate_sheets(spreadsheet, sheet_names) - if new_sheets: - LOGGER.info('Creating new sheets...') - create_sheets(service, spreadsheet_id, new_sheets) - LOGGER.info('Parsing sheet headers...') - headers = get_headers(service, spreadsheet_id, sheet_names) - update_headers(service, spreadsheet_id, headers, info) - update_filters(service, spreadsheet_id, headers, info, spreadsheet) - update_values(service, spreadsheet_id, headers, info) - - -##################### -# Main/helpers # -##################### - - -# Loads or creates credentials and connects to the Sheets API. Returns a Spreadsheets object with -# an open connection. -def get_sheets_service(auth_path): - credentials_path = auth_path + '/credentials.json' - token_path = auth_path + '/token.pickle' - creds = None - if not os.path.exists(auth_path): - LOGGER.info("Creating auth dir '" + auth_path + "'") - os.makedirs(auth_path) - if not os.path.exists(credentials_path): - raise Exception('Missing credentials.json.\n' - 'Go to: https://developers.google.com/sheets/api/quickstart/python\n' - "Under Step 1, click 'ENABLE THE GOOGLE SHEETS API'\n" - "Click 'DOWNLOAD CLIENT CONFIGURATION'\n" - 'Save to your auth_path (' + auth_path + ') as credentials.json') - if os.path.exists(token_path): - with open(token_path, 'rb') as token: - creds = pickle.load(token) - LOGGER.info('Loaded credentials from ' + token_path) - if not creds or not creds.valid: - if creds and creds.expired and creds.refresh_token: - LOGGER.info('Refreshing credentials...') - creds.refresh(Request()) - else: - LOGGER.info('Could not find credentials. Requesting new credentials.') - flow = InstalledAppFlow.from_client_secrets_file(credentials_path, SCOPES) - creds = flow.run_local_server() - with open(token_path, 'wb') as token: - pickle.dump(creds, token) - service = build('sheets', 'v4', credentials=creds) - sheets = service.spreadsheets() - return sheets - - -# Parse the input to the script -def parse_args(): - parser = argparse.ArgumentParser(os.path.basename(sys.argv[0])) - parser.add_argument( - '--auth_path', - default=HOME_DIR + '/.auth', - nargs='?', - help='path to directory containing authorization data ' - '(credentials.json and token.pickle). ' - '[default=/.auth]') - parser.add_argument( - '--spreadsheet', - default='1uttk1z8lJ4ZsUY7wMdFauMzUxb048nh5l52zdrAznek', - nargs='?', - help='ID of the spreadsheet to write stats to. ' - "[default='1uttk1z8lJ4ZsUY7wMdFauMzUxb048nh5l52zdrAznek']") - parser.add_argument( - '--verbosity', - default='INFO', - nargs='?', - help='Verbosity of output. Valid options are ' - '[DEBUG, INFO, WARNING, ERROR]. ' - '[default=INFO]') - return parser.parse_args() - - -# Set up the logging with the right verbosity and output. -def initialize_logging(verbosity): - handler = logging.StreamHandler() - formatter = logging.Formatter(fmt='%(levelname)s: %(message)s') - handler.setFormatter(formatter) - LOGGER.addHandler(handler) - if 'DEBUG' in verbosity: - LOGGER.setLevel(level=logging.DEBUG) - elif 'INFO' in verbosity: - LOGGER.setLevel(level=logging.INFO) - elif 'WARNING' in verbosity: - LOGGER.setLevel(level=logging.WARNING) - elif 'ERROR' in verbosity: - LOGGER.setLevel(level=logging.ERROR) - else: - LOGGER.setLevel(level=logging.INFO) - - -def main(): - os.chdir(ROOT_DIR) - args = parse_args() - verbosity = args.verbosity.strip().upper() - initialize_logging(verbosity) - auth_path = args.auth_path.replace('\\', '/') - try: - service = get_sheets_service(auth_path) - except Exception as error: - LOGGER.error('%s\n' % str(error)) - exit(1) - - info = {} - LOGGER.info('Building info struct...') - for bot_name in BOT_NAMES: - LOGGER.info("Parsing bot '" + bot_name + "'...") - try: - info[bot_name] = get_bot_info(BOT_NAME_PREFIX + bot_name) - except Exception as error: - LOGGER.error('%s\n' % str(error)) - - LOGGER.info('Updating sheets...') - try: - update_spreadsheet(service, args.spreadsheet, info) - except Exception as error: - LOGGER.error('%s\n' % str(error)) - quit(1) - - LOGGER.info('Info was successfully parsed to sheet: https://docs.google.com/spreadsheets/d/' + - args.spreadsheet) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/scripts/gl_angle_ext.xml b/scripts/gl_angle_ext.xml index 44c6dea45fb..0389244dd92 100644 --- a/scripts/gl_angle_ext.xml +++ b/scripts/gl_angle_ext.xml @@ -1171,6 +1171,9 @@ + + + @@ -1340,7 +1343,6 @@ - @@ -1366,8 +1368,6 @@ - - @@ -1582,22 +1582,21 @@
- + - - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/scripts/process_angle_perf_results.py b/scripts/process_angle_perf_results.py index 47d8264cabd..4172adfd6e2 100755 --- a/scripts/process_angle_perf_results.py +++ b/scripts/process_angle_perf_results.py @@ -1,4 +1,4 @@ -#!/usr/bin/env vpython +#!/usr/bin/env vpython3 # # Copyright 2021 The ANGLE Project Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be diff --git a/scripts/registry_xml.py b/scripts/registry_xml.py index 3f2deac8b89..abe8900ee5c 100644 --- a/scripts/registry_xml.py +++ b/scripts/registry_xml.py @@ -41,7 +41,6 @@ # We document those extensions in gl_angle_ext.xml instead of the canonical gl.xml. angle_toggleable_extensions = [ - "GL_ANGLE_texture_rectangle", ] angle_requestable_extensions = [ @@ -74,12 +73,12 @@ "GL_ANGLE_texture_compression_dxt5", "GL_ANGLE_texture_external_update", "GL_ANGLE_texture_multisample", + "GL_ANGLE_texture_rectangle", "GL_ANGLE_vulkan_image", "GL_ANGLE_yuv_internal_format", "GL_CHROMIUM_color_buffer_float_rgb", "GL_CHROMIUM_color_buffer_float_rgba", "GL_CHROMIUM_lose_context", - "GL_CHROMIUM_sync_query", ] gles_requestable_extensions = [ @@ -88,10 +87,10 @@ "GL_ANGLE_pack_reverse_row_order", "GL_ANGLE_texture_usage", "GL_APPLE_clip_distance", - "GL_ARB_sync", "GL_ARM_rgba8", "GL_ARM_shader_framebuffer_fetch", "GL_ARM_shader_framebuffer_fetch_depth_stencil", + "GL_ARM_texture_unnormalized_coordinates", "GL_EXT_base_instance", "GL_EXT_blend_func_extended", "GL_EXT_blend_minmax", @@ -109,6 +108,7 @@ "GL_EXT_draw_buffers", "GL_EXT_draw_buffers_indexed", "GL_EXT_draw_elements_base_vertex", + "GL_EXT_draw_instanced", "GL_EXT_EGL_image_array", "GL_EXT_EGL_image_external_wrap_modes", "GL_EXT_EGL_image_storage", @@ -116,17 +116,22 @@ "GL_EXT_external_buffer", "GL_EXT_float_blend", "GL_EXT_frag_depth", + "GL_EXT_fragment_shading_rate", + "GL_EXT_fragment_shading_rate_attachment", + "GL_EXT_fragment_shading_rate_primitive", "GL_EXT_geometry_shader", "GL_EXT_gpu_shader5", "GL_EXT_instanced_arrays", "GL_EXT_map_buffer_range", "GL_EXT_memory_object", "GL_EXT_memory_object_fd", + "GL_EXT_multi_draw_arrays", "GL_EXT_multi_draw_indirect", "GL_EXT_multisampled_render_to_texture", "GL_EXT_multisampled_render_to_texture2", "GL_EXT_occlusion_query_boolean", "GL_EXT_polygon_offset_clamp", + "GL_EXT_primitive_bounding_box", "GL_EXT_protected_textures", "GL_EXT_pvrtc_sRGB", "GL_EXT_read_format_bgra", @@ -140,6 +145,7 @@ "GL_EXT_shader_io_blocks", "GL_EXT_shader_non_constant_global_initializers", "GL_EXT_shader_texture_lod", + "GL_EXT_shader_texture_samples", "GL_EXT_shadow_samplers", "GL_EXT_sRGB", "GL_EXT_tessellation_shader", @@ -170,6 +176,8 @@ "GL_EXT_YUV_target", "GL_IMG_texture_compression_pvrtc", "GL_IMG_texture_compression_pvrtc2", + "GL_KHR_blend_equation_advanced", + "GL_KHR_blend_equation_advanced_coherent", "GL_KHR_parallel_shader_compile", "GL_KHR_texture_compression_astc_hdr", "GL_KHR_texture_compression_astc_ldr", @@ -210,6 +218,7 @@ "GL_OES_get_program_binary", "GL_OES_gpu_shader5", "GL_OES_mapbuffer", + "GL_OES_primitive_bounding_box", "GL_OES_required_internalformat", "GL_OES_rgb8_rgba8", "GL_OES_sample_shading", @@ -236,6 +245,7 @@ "GL_OES_vertex_type_10_10_10_2", "GL_OVR_multiview", "GL_OVR_multiview2", + "GL_OVR_multiview_multisampled_render_to_texture", "GL_QCOM_framebuffer_foveated", "GL_QCOM_render_shared_exponent", "GL_QCOM_shading_rate", @@ -273,13 +283,10 @@ "GL_EXT_debug_marker", "GL_EXT_discard_framebuffer", "GL_EXT_multisample_compatibility", - "GL_EXT_primitive_bounding_box", "GL_EXT_robustness", "GL_EXT_sRGB_write_control", "GL_EXT_texture_format_sRGB_override", "GL_EXT_texture_sRGB_decode", - "GL_KHR_blend_equation_advanced", - "GL_KHR_blend_equation_advanced_coherent", "GL_KHR_debug", "GL_KHR_no_error", "GL_KHR_robust_buffer_access_behavior", @@ -291,7 +298,6 @@ "GL_OES_depth_texture", "GL_OES_EGL_sync", "GL_OES_packed_depth_stencil", - "GL_OES_primitive_bounding_box", "GL_OES_surfaceless_context", ] @@ -308,6 +314,27 @@ "GL_OES_texture_mirrored_repeat", ] +# Unsupported entry points that require explicit exclusion +# because XML registry does not contain enough information. +gles_skipped_commands = [ + # GL_EXT_EGL_image_storage + "glEGLImageTargetTextureStorageEXT", + # GL_EXT_external_buffer + "glNamedBufferStorageExternalEXT", + # GL_EXT_memory_object + "glTextureStorageMem2DEXT", + "glTextureStorageMem2DMultisampleEXT", + "glTextureStorageMem3DEXT", + "glTextureStorageMem3DMultisampleEXT", + "glNamedBufferStorageMemEXT", + # GL_EXT_texture_storage + "glTexStorage1DEXT", + "glTextureStorage1DEXT", + "glTextureStorage2DEXT", + "glTextureStorage3DEXT", + # GL_OVR_multiview + "glNamedFramebufferTextureMultiviewOVR", +] def check_sorted(name, l): unidiff = difflib.unified_diff(l, sorted(l, key=str.casefold), 'unsorted', 'sorted') @@ -346,7 +373,6 @@ def check_sorted(name, l): "EGL_ANGLE_display_texture_share_group", "EGL_ANGLE_external_context_and_surface", "EGL_ANGLE_feature_control", - "EGL_ANGLE_ggp_stream_descriptor", "EGL_ANGLE_memory_usage_report", "EGL_ANGLE_metal_create_context_ownership_identity", "EGL_ANGLE_metal_shared_event_sync", @@ -357,7 +383,6 @@ def check_sorted(name, l): "EGL_ANGLE_query_surface_pointer", "EGL_ANGLE_stream_producer_d3d_texture", "EGL_ANGLE_surface_d3d_texture_2d_share_handle", - "EGL_ANGLE_swap_with_frame_token", "EGL_ANGLE_sync_control_rate", "EGL_ANGLE_vulkan_image", "EGL_ANGLE_wait_until_work_scheduled", @@ -396,6 +421,7 @@ def check_sorted(name, l): "EGL_KHR_surfaceless_context", "EGL_KHR_swap_buffers_with_damage", "EGL_KHR_wait_sync", + "EGL_NV_context_priority_realtime", "EGL_NV_post_sub_buffer", "EGL_NV_stream_consumer_gltexture_yuv", ] @@ -403,6 +429,9 @@ def check_sorted(name, l): check_sorted('supported_egl_extensions', supported_egl_extensions) supported_cl_extensions = [ + # OpenCL 1.0 + "cl_arm_import_memory", + # Since OpenCL 1.1 "cl_khr_byte_addressable_store", "cl_khr_global_int32_base_atomics", @@ -415,12 +444,16 @@ def check_sorted(name, l): "cl_khr_depth_images", "cl_khr_image2d_from_buffer", + # OpenCL 3.0 + "cl_khr_external_memory", + # Optional "cl_khr_extended_versioning", "cl_khr_fp64", "cl_khr_icd", "cl_khr_int64_base_atomics", "cl_khr_int64_extended_atomics", + "cl_khr_priority_hints", ] # Strip these suffixes from Context entry point names. NV is excluded (for now). @@ -463,7 +496,7 @@ class apis: CL = 'CL' # For GLenum types -api_enums = {apis.GL: 'BigGLEnum', apis.GLES: 'GLESEnum'} +api_enums = {apis.GLES: 'GLESEnum'} default_enum_group_name = 'AllEnums' @@ -526,6 +559,7 @@ def __init__(self, xml_file, ext_file=None): self.all_commands = self.root.findall('commands/command') self.all_cmd_names = CommandNames() self.commands = {} + self.sources_by_command = {} def _AppendANGLEExts(self, ext_file): angle_ext_tree = etree.parse(script_relative(ext_file)) @@ -551,6 +585,10 @@ def AddCommands(self, feature_name, annotation): xpath = ".//feature[@name='%s']//command" % feature_name commands = [cmd.attrib['name'] for cmd in self.root.findall(xpath)] + # Reverse cache for all places a command may be defined in. + for cmd in commands: + self.sources_by_command.setdefault(cmd, []).append(annotation) + # Remove commands that have already been processed current_cmds = self.all_cmd_names.get_all_commands() commands = [cmd for cmd in commands if cmd not in current_cmds] @@ -561,7 +599,7 @@ def AddCommands(self, feature_name, annotation): def _ClassifySupport(self, extension): supported = extension.attrib['supported'] # Desktop GL extensions exposed in ANGLE GLES for Chrome. - if extension.attrib['name'] in ['GL_ARB_sync', 'GL_NV_robustness_video_memory_purge']: + if extension.attrib['name'] in ['GL_NV_robustness_video_memory_purge']: supported += "|gles2" if 'gles2' in supported: return 'gl2ext' @@ -604,18 +642,20 @@ def AddExtensionCommands(self, supported_extensions, apis): if 'api' in require.attrib and require.attrib['api'] not in apis: continue - # A special case for EXT_texture_storage - filter_out_comment = "Supported only if GL_EXT_direct_state_access is supported" - if 'comment' in require.attrib and require.attrib['comment'] == filter_out_comment: - continue - - extension_commands = require.findall('command') - ext_cmd_names += [command.attrib['name'] for command in extension_commands] + ext_cmd_names += [ + command.attrib['name'] + for command in require.findall('command') + if command.attrib['name'] not in gles_skipped_commands + ] self.ext_data[extension_name] = sorted(ext_cmd_names) for extension_name, ext_cmd_names in sorted(self.ext_data.items()): + # Reverse cache for all places a command may be defined in. + for cmd in ext_cmd_names: + self.sources_by_command.setdefault(cmd, []).append(extension_name) + # Detect and filter duplicate extensions. dupes = [] for ext_cmd in ext_cmd_names: diff --git a/scripts/roll_aosp.sh b/scripts/roll_aosp.sh index 5143daff138..88718d373df 100755 --- a/scripts/roll_aosp.sh +++ b/scripts/roll_aosp.sh @@ -47,8 +47,7 @@ function generate_Android_bp_file() { "target_cpu = \"$abi\"" # Target ndk API 26 to make sure ANGLE can use the Vulkan backend on Android - "android32_ndk_api_level = 26" - "android64_ndk_api_level = 26" + "android_ndk_api_level = 26" # Disable all backends except Vulkan "angle_enable_vulkan = true" @@ -75,13 +74,10 @@ function generate_Android_bp_file() { # Use system lib(std)c++, since the Chromium library breaks std::string "use_custom_libcxx = false" - # rapidJSON is used for ANGLE's frame capture (among other things), which is unnecessary for AOSP builds. - "angle_has_rapidjson = false" - - # TODO(b/279980674): re-enable end2end tests - "build_angle_end2end_tests_aosp = true" - "build_angle_trace_tests = false" + # Test the system EGL loader "angle_test_enable_system_egl = true" + "build_angle_end2end_tests_library = true" + "build_angle_trace_tests = false" ) if [[ "$1" == "--enableApiTrace" ]]; then @@ -165,6 +161,8 @@ copy_to_aosp_paths=( "build" "third_party/abseil-cpp" "third_party/glslang/src" + "third_party/re2/src" + "third_party/rapidjson/src" "third_party/spirv-headers/src" "third_party/spirv-tools/src" "third_party/vulkan-headers/src" @@ -176,12 +174,18 @@ copy_to_aosp_paths=( delete_after_codegen_paths=( "third_party/android_build_tools" "third_party/android_sdk" + "third_party/android_system_sdk" "third_party/android_toolchain" + "third_party/bazel" + "third_party/clspv/gn" + "third_party/colorama" "third_party/jdk/current" # subdirs only to keep third_party/jdk/BUILD.gn (not pulled by gclient as it comes from ANGLE repo) - "third_party/jdk/extras" "third_party/llvm-build" + "third_party/proguard" + "third_party/r8" "third_party/rust" "third_party/rust-toolchain" + "third_party/turbine" "third_party/zlib" # Replaced by Android's zlib # build/linux is hundreds of megs that aren't needed. diff --git a/scripts/roll_chromium_deps.py b/scripts/roll_chromium_deps.py index 3f073724e98..76462f215f3 100755 --- a/scripts/roll_chromium_deps.py +++ b/scripts/roll_chromium_deps.py @@ -61,9 +61,9 @@ def FindSrcDirPath(): 'third_party/depot_tools', 'third_party/flatbuffers/src', 'third_party/fuchsia-sdk/sdk', + 'third_party/googletest/src', 'third_party/ijar', - 'third_party/jdk', - 'third_party/jdk/extras', + 'third_party/jdk/current', 'third_party/jinja2', 'third_party/kotlin_stdlib', 'third_party/libc++/src', @@ -82,6 +82,7 @@ def FindSrcDirPath(): 'third_party/qemu-mac-x64', 'third_party/r8/cipd', 'third_party/r8/d8/cipd', + 'third_party/re2/src', 'third_party/requests/src', 'third_party/rust', 'third_party/siso/cipd', @@ -90,7 +91,6 @@ def FindSrcDirPath(): 'third_party/zlib', 'tools/android', 'tools/clang', - 'tools/clang/dsymutil', 'tools/luci-go', 'tools/mb', 'tools/md_browser', @@ -104,6 +104,7 @@ def FindSrcDirPath(): 'tools/skia_goldctl/mac_arm64', 'tools/skia_goldctl/win', 'tools/valgrind', + 'tools/win', ] ANGLE_URL = 'https://chromium.googlesource.com/angle/angle' diff --git a/scripts/run_code_generation.py b/scripts/run_code_generation.py index a4b8a9d37a9..2021c2eb38e 100755 --- a/scripts/run_code_generation.py +++ b/scripts/run_code_generation.py @@ -209,7 +209,7 @@ def main(): all_old_hashes = load_hashes() all_new_hashes = {} any_dirty = False - format_workaround = False + full_formats = [] parser = argparse.ArgumentParser(description='Generate ANGLE internal code.') parser.add_argument( @@ -248,8 +248,8 @@ def main(): all_old_hashes[fname] = {} if any_hash_dirty(name, filenames, new_hashes, all_old_hashes[fname]): any_dirty = True - if "preprocessor" in name: - format_workaround = True + full_formats += [fn for fn in filenames if '_tab_' in fn or '_lex_' in fn] + if not args.verify_only: print('Running ' + name + ' code generator') @@ -286,11 +286,13 @@ def main(): args += ['cl', 'format'] print('Calling git cl format') subprocess.check_call(args) - if format_workaround: + + if full_formats: # Some formattings fail, and thus we can never submit such a cl because # of vicious circle of needing clean formatting but formatting not generating # clean formatting. - print('Calling git cl format again') + print('Calling git cl format --full' % full_formats) + args += ['--full'] + full_formats subprocess.check_call(args) diff --git a/src/android_system_settings/res/layout/fragment.xml b/src/android_system_settings/res/layout/fragment.xml deleted file mode 100644 index c3305fc16f8..00000000000 --- a/src/android_system_settings/res/layout/fragment.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - diff --git a/src/android_system_settings/src/com/android/angle/AndroidManifest.xml b/src/android_system_settings/src/com/android/angle/AndroidManifest.xml index b01103ebcc0..92a4b374c1a 100644 --- a/src/android_system_settings/src/com/android/angle/AndroidManifest.xml +++ b/src/android_system_settings/src/com/android/angle/AndroidManifest.xml @@ -21,8 +21,8 @@ package="com.android.angle"> + android:minSdkVersion="35" + android:targetSdkVersion="35" /> @@ -38,7 +38,7 @@ diff --git a/src/android_system_settings/src/com/android/angle/MainActivity.java b/src/android_system_settings/src/com/android/angle/MainActivity.java index b0d22ddfc7a..7c7989f7b2e 100644 --- a/src/android_system_settings/src/com/android/angle/MainActivity.java +++ b/src/android_system_settings/src/com/android/angle/MainActivity.java @@ -15,12 +15,17 @@ */ package com.android.angle; -import android.app.Activity; import android.os.Bundle; +import android.view.ViewGroup.MarginLayoutParams; + +import androidx.core.view.WindowInsetsCompat; +import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.PreferenceFragmentCompat; + import com.android.angle.common.*; -public class MainActivity extends Activity +public class MainActivity extends AppCompatActivity { private final String TAG = this.getClass().getSimpleName(); @@ -28,6 +33,13 @@ public class MainActivity extends Activity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.fragment); + + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(android.R.id.content, new MainFragment()) + .commit(); + } } } + diff --git a/src/android_system_settings/src/com/android/angle/common/MainFragment.java b/src/android_system_settings/src/com/android/angle/common/MainFragment.java index 9e17eb2224c..b205b651428 100644 --- a/src/android_system_settings/src/com/android/angle/common/MainFragment.java +++ b/src/android_system_settings/src/com/android/angle/common/MainFragment.java @@ -20,23 +20,29 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.pm.ApplicationInfo; -import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.os.Build; import android.os.Bundle; -import android.os.Process; import android.util.Log; +import android.view.View; +import android.view.ViewGroup.MarginLayoutParams; + +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceFragment; +import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; import androidx.preference.SwitchPreference; +import com.android.angle.R; + +import java.lang.reflect.Method; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; @@ -44,17 +50,15 @@ import java.util.List; import java.util.Map; -import com.android.angle.R; - -public class MainFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener +public class MainFragment extends PreferenceFragmentCompat implements OnSharedPreferenceChangeListener { private final String TAG = this.getClass().getSimpleName(); private final boolean DEBUG = false; + private boolean mIsAngleSystemDriver; private SharedPreferences mSharedPreferences; private SwitchPreference mShowAngleInUseSwitchPref; - private List mApplicationListPreferences = new ArrayList<>(); private GlobalSettings mGlobalSettings; private Receiver mRefreshReceiver = new Receiver(); @@ -78,6 +82,8 @@ public void onCreate(Bundle savedInstanceState) mSharedPreferences = PreferenceManager.getDefaultSharedPreferences( getActivity().getApplicationContext()); + final String eglDriver = getSystemProperty("ro.hardware.egl", ""); + mIsAngleSystemDriver = eglDriver.equals("angle"); if (DEBUG) { Map preferences = PreferenceManager @@ -86,6 +92,7 @@ public void onCreate(Bundle savedInstanceState) { Log.d(TAG, key + ", " + preferences.get(key)); } + Log.d(TAG, "ro.hardware.egl = " + eglDriver); } mGlobalSettings = new GlobalSettings(getContext(), mSharedPreferences, mInstalledPackages); @@ -116,6 +123,20 @@ public void onPause() super.onPause(); } + @Override + public void onViewCreated(View view, Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + + ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); + MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams(); + mlp.topMargin = insets.top; + v.setLayoutParams(mlp); + return WindowInsetsCompat.CONSUMED; + }); + } + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { @@ -155,6 +176,17 @@ public boolean onPreferenceChange(Preference preference, Object newValue) }); } + private static String getSystemProperty(String key, String defaultValue) { + try { + Class systemProperties = Class.forName("android.os.SystemProperties"); + Method getMethod = systemProperties.getMethod("get", String.class, String.class); + return (String) getMethod.invoke(null, key, defaultValue); + } catch (Exception e) { + e.printStackTrace(); + return defaultValue; + } + } + private void createInstalledAppsListPreference() { final String selectDriverCategoryKey = @@ -162,12 +194,11 @@ private void createInstalledAppsListPreference() final PreferenceCategory preferenceCategory = (PreferenceCategory) findPreference(selectDriverCategoryKey); preferenceCategory.removeAll(); - mApplicationListPreferences.clear(); final Context context = preferenceCategory.getContext(); for (PackageInfo packageInfo : mInstalledPackages) { - ListPreference listPreference = new ListPreference(context); + final ListPreference listPreference = new ListPreference(context); initListPreference(packageInfo, listPreference); preferenceCategory.addPreference(listPreference); } @@ -229,14 +260,24 @@ private String getAppName(PackageInfo packageInfo) private void initListPreference(PackageInfo packageInfo, ListPreference listPreference) { - CharSequence[] drivers = getResources().getStringArray(R.array.driver_values); - listPreference.setEntries(drivers); - listPreference.setEntryValues(drivers); - final String packageName = packageInfo.packageName; listPreference.setKey(packageName); listPreference.setTitle(getAppName(packageInfo)); + if (mIsAngleSystemDriver) { + // if ANGLE is the system driver set by the ro property, then we disable the option and + // show all apps using ANGLE, because both "native" and "angle" options will ends up + // loading ANGLE, allowing users to choose "native" but still loads ANGLE will create + // more confusion. + listPreference.setEnabled(false); + listPreference.setSummary(GlobalSettings.DRIVER_SELECTION_ANGLE); + listPreference.setValue(GlobalSettings.DRIVER_SELECTION_ANGLE); + return; + } + + final CharSequence[] drivers = getResources().getStringArray(R.array.driver_values); + listPreference.setEntries(drivers); + listPreference.setEntryValues(drivers); final String driverSelectionValue = mSharedPreferences.getString(packageName, GlobalSettings.DRIVER_SELECTION_DEFAULT); listPreference.setDefaultValue(driverSelectionValue); @@ -259,7 +300,5 @@ public boolean onPreferenceChange(Preference preference, Object newValue) return true; } }); - - mApplicationListPreferences.add(listPreference); } } diff --git a/src/commit_id.py b/src/commit_id.py index 6fa4d2630e2..bb1e2ce746a 100755 --- a/src/commit_id.py +++ b/src/commit_id.py @@ -6,17 +6,14 @@ # Generate commit.h with git commit hash. # +import pathlib import subprocess as sp import sys import os usage = """\ -Usage: commit_id.py check - check if git is present - commit_id.py get_git_dirs - prints work-tree and common git directories - commit_id.py unpack - check if exists, and if not - create it based on .git/packed-refs - commit_id.py position - print commit position - commit_id.py gen - generate commit.h""" +Usage: commit_id.py position - print commit position + commit_id.py gen [depfile] - generate commit.h""" def grab_output(command, cwd): @@ -62,6 +59,51 @@ def unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path): fout.write(git_hash + '\n') +# Get the files that GN action target angle_commit_id depends on. +# If any of these files changed, the build system should rerun the commit_id.py +# script to regenerate the angle_commit.h +# Case 1: git config extensions.refStorage == file (or empty) +# Case 1.1: .git/HEAD contains the hash. +# Return .git/HEAD +# Case 1.2: .git/HEAD contains non-hash: e.g. refs/heads/ +# Return .git/HEAD +# Return .git/refs/heads/ +# Case 2: git config extensions.refStorage == reftable +# In this case, HEAD will just store refs/heads/.invalid. If any reference is +# updated, .git/reftable/table.list will be updated. +# Return .git/reftable/table.list +def get_git_inputs_and_maybe_unpack_ref(cwd): + # check git extensions.refStorage type + gitRefStorageType = grab_output('git config --get extensions.refStorage', cwd) + isRefTableStorage = gitRefStorageType and gitRefStorageType == "reftable" + git_dir = os.path.normpath(os.path.join(cwd, get_git_dir(cwd))) + head_file = os.path.join(git_dir, 'HEAD') + ret = [] + # commit id should depend on angle's HEAD revision only if + # extensions.refStorage = file. + # If extensions.refStorage = reftable, .git/HEAD will always contains + # "refs/heads/.invalid", and we can't rely on it as an indicator of whether + # to rerun this script. + if not isRefTableStorage: + ret.append(head_file) + git_common_dir = os.path.normpath(os.path.join(cwd, get_git_common_dir(cwd))) + result = pathlib.Path(head_file).read_text().split() + if result[0] == "ref:": + # if the extensions.refStorage is reftable, add .git/reftable/tables.list as an input to gn action target + if isRefTableStorage: + ret.append(os.path.join(git_common_dir, 'reftable', 'tables.list')) + else: + # if the extensions.refStorage is file, add loose ref file pointed by HEAD + ref_file = result[1] + ref_file_full_path = os.path.join(git_common_dir, ref_file) + + if not os.path.exists(ref_file_full_path): + packed_refs_full_path = os.path.join(git_common_dir, 'packed-refs') + unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path) + ret.append(os.path.join(git_common_dir, ref_file)) + return ret + + if len(sys.argv) < 2: sys.exit(usage) @@ -70,34 +112,10 @@ def unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path): # Set the root of ANGLE's repo as the working directory aosp_angle_path = os.path.join(os.path.dirname('.'), 'external', 'angle') aosp = os.path.exists(aosp_angle_path) -cwd = aosp_angle_path if aosp else os.path.join(os.path.dirname(os.path.realpath(__file__)), '..') +cwd = aosp_angle_path if aosp else os.path.join(os.path.dirname(os.path.abspath(__file__)), '..') git_dir_exists = does_git_dir_exist(cwd) -if operation == 'check': - if git_dir_exists: - print("1") - else: - print("0") - sys.exit(0) -elif operation == 'get_git_dirs': - print(get_git_dir(cwd)) - print(get_git_common_dir(cwd)) - sys.exit(0) -elif operation == 'unpack': - if len(sys.argv) < 3: - sys.exit(usage) - - ref_file = sys.argv[2] - git_common_dir = get_git_common_dir(cwd) - ref_file_full_path = os.path.join(cwd, git_common_dir, ref_file) - ref_file_exists = os.path.exists(ref_file_full_path) - - if not ref_file_exists: - packed_refs_full_path = os.path.join(cwd, git_common_dir, 'packed-refs') - unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path) - - sys.exit(0) -elif operation == 'position': +if operation == 'position': if git_dir_exists: print(get_commit_position(cwd)) else: @@ -108,6 +126,7 @@ def unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path): sys.exit(usage) output_file = sys.argv[2] +depfile = sys.argv[3] if len(sys.argv) == 4 else None commit_id_size = 12 commit_date = 'unknown date' commit_position = '0' @@ -126,12 +145,18 @@ def unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path): except: pass -hfile = open(output_file, 'w') +with open(output_file, 'w') as hfile: + hfile.write('#define ANGLE_COMMIT_HASH "%s"\n' % (commit_id or "unknown hash")) + hfile.write('#define ANGLE_COMMIT_HASH_SIZE %d\n' % commit_id_size) + hfile.write('#define ANGLE_COMMIT_DATE "%s"\n' % commit_date) + hfile.write('#define ANGLE_COMMIT_POSITION %s\n' % commit_position) -hfile.write('#define ANGLE_COMMIT_HASH "%s"\n' % (commit_id or "unknown hash")) -hfile.write('#define ANGLE_COMMIT_HASH_SIZE %d\n' % commit_id_size) -hfile.write('#define ANGLE_COMMIT_DATE "%s"\n' % commit_date) -hfile.write('#define ANGLE_COMMIT_POSITION %s\n' % commit_position) - - -hfile.close() +if depfile: + inputs = [] + if git_dir_exists: + inputs = get_git_inputs_and_maybe_unpack_ref(cwd) + with open(depfile, 'w') as f: + f.write(output_file) + f.write(': ') + f.write(' '.join(os.path.relpath(p) for p in inputs)) + f.write('\n') diff --git a/src/common/BinaryStream.h b/src/common/BinaryStream.h index cb81411cb73..6948b9bb399 100644 --- a/src/common/BinaryStream.h +++ b/src/common/BinaryStream.h @@ -10,13 +10,16 @@ #define COMMON_BINARYSTREAM_H_ #include + #include #include +#include #include #include "common/PackedEnums.h" #include "common/angleutils.h" -#include "common/mathutil.h" +#include "common/span.h" +#include "common/span_util.h" namespace gl { @@ -32,13 +35,7 @@ struct PromotedIntegerType class BinaryInputStream : angle::NonCopyable { public: - BinaryInputStream(const void *data, size_t length) - { - mError = false; - mOffset = 0; - mData = static_cast(data); - mLength = length; - } + BinaryInputStream(angle::Span data) : mData(data) {} // readInt will generate an error for bool types template @@ -47,7 +44,7 @@ class BinaryInputStream : angle::NonCopyable static_assert(!std::is_same()>(), "Use readBool"); using PromotedIntT = typename PromotedIntegerType::type; PromotedIntT value = 0; - read(&value); + read(angle::byte_span_from_ref(value)); ASSERT(angle::IsValueInRangeForNumericType(value)); return static_cast(value); } @@ -67,7 +64,7 @@ class BinaryInputStream : angle::NonCopyable if (size > 0) { param->resize(size); - readBytes(reinterpret_cast(param->data()), param->size() * sizeof(T)); + readBytes(angle::as_writable_byte_span(*param)); } } @@ -75,14 +72,14 @@ class BinaryInputStream : angle::NonCopyable void readPackedEnumMap(angle::PackedEnumMap *param) { static_assert(std::is_trivially_copyable(), "must be memcpy-able"); - readBytes(reinterpret_cast(param->data()), param->size() * sizeof(T)); + readBytes(angle::as_writable_byte_span(*param)); } template void readStruct(T *param) { static_assert(std::is_trivially_copyable(), "must be memcpy-able"); - readBytes(reinterpret_cast(param), sizeof(T)); + readBytes(angle::byte_span_from_ref(*param)); } template @@ -101,14 +98,13 @@ class BinaryInputStream : angle::NonCopyable bool readBool() { int value = 0; - read(&value); - return (value > 0); + read(angle::byte_span_from_ref(value)); + return value > 0; } void readBool(bool *outValue) { *outValue = readBool(); } - void readBytes(unsigned char outArray[], size_t count) { read(outArray, count); } - const unsigned char *getBytes(size_t count) { return read(nullptr, count); } + void readBytes(angle::Span outArray) { read(outArray); } std::string readString() { @@ -130,20 +126,20 @@ class BinaryInputStream : angle::NonCopyable angle::CheckedNumeric checkedOffset(mOffset); checkedOffset += length; - if (!checkedOffset.IsValid() || mOffset + length > mLength) + if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mData.size()) { mError = true; return; } - - v->assign(reinterpret_cast(mData) + mOffset, length); + auto char_span = angle::as_chars(mData).subspan(mOffset, length); + v->assign(char_span.data(), char_span.size()); mOffset = checkedOffset.ValueOrDie(); } float readFloat() { - float f; - read(&f, 1); + float f = 0.0f; + read(angle::byte_span_from_ref(f)); return f; } @@ -152,7 +148,7 @@ class BinaryInputStream : angle::NonCopyable angle::CheckedNumeric checkedOffset(mOffset); checkedOffset += length; - if (!checkedOffset.IsValid() || mOffset + length > mLength) + if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mData.size()) { mError = true; return; @@ -161,69 +157,42 @@ class BinaryInputStream : angle::NonCopyable mOffset = checkedOffset.ValueOrDie(); } - size_t offset() const { return mOffset; } - size_t remainingSize() const - { - ASSERT(mLength >= mOffset); - return mLength - mOffset; - } - bool error() const { return mError; } + bool endOfStream() const { return mOffset == mData.size(); } - bool endOfStream() const { return mOffset == mLength; } + // data() and size() methods allow implicit conversion to span. + const uint8_t *data() const { return mData.data(); } + size_t size() const { return mData.size(); } - const uint8_t *data() { return mData; } + angle::Span remainingSpan() const { return mData.subspan(mOffset); } private: - bool mError; - size_t mOffset; - const uint8_t *mData; - size_t mLength; - - template - const uint8_t *read(T *v, size_t num) + void read(angle::Span dstSpan) { - static_assert(std::is_fundamental::value, "T must be a fundamental type."); - - angle::CheckedNumeric checkedLength(num); - checkedLength *= sizeof(T); - if (!checkedLength.IsValid()) - { - mError = true; - return nullptr; - } - angle::CheckedNumeric checkedOffset(mOffset); - checkedOffset += checkedLength; + checkedOffset += dstSpan.size(); - if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength) + if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mData.size()) { mError = true; - return nullptr; + return; } - const uint8_t *srcBytes = mData + mOffset; - if (v != nullptr) - { - memcpy(v, srcBytes, checkedLength.ValueOrDie()); - } + angle::Span srcSpan = mData.subspan(mOffset, dstSpan.size()); + angle::SpanMemcpy(dstSpan, srcSpan); mOffset = checkedOffset.ValueOrDie(); - - return srcBytes; } - template - void read(T *v) - { - read(v, 1); - } + bool mError = false; + size_t mOffset = 0; + angle::Span mData; }; class BinaryOutputStream : angle::NonCopyable { public: - BinaryOutputStream(); - ~BinaryOutputStream(); + BinaryOutputStream() = default; + ~BinaryOutputStream() = default; // writeInt also handles bool types template @@ -234,7 +203,7 @@ class BinaryOutputStream : angle::NonCopyable using PromotedIntT = typename PromotedIntegerType::type; ASSERT(angle::IsValueInRangeForNumericType(param)); PromotedIntT intValue = static_cast(param); - write(&intValue, 1); + write(angle::byte_span_from_ref(intValue)); } // Specialized writeInt for values that can also be exactly -1. @@ -258,7 +227,7 @@ class BinaryOutputStream : angle::NonCopyable writeInt(param.size()); if (param.size() > 0) { - writeBytes(reinterpret_cast(param.data()), param.size() * sizeof(T)); + writeBytes(angle::as_byte_span(param)); } } @@ -266,7 +235,7 @@ class BinaryOutputStream : angle::NonCopyable void writePackedEnumMap(const angle::PackedEnumMap ¶m) { static_assert(std::is_trivially_copyable(), "must be memcpy-able"); - writeBytes(reinterpret_cast(param.data()), param.size() * sizeof(T)); + writeBytes(angle::as_byte_span(param)); } template @@ -275,7 +244,7 @@ class BinaryOutputStream : angle::NonCopyable static_assert(!std::is_pointer::value, "Must pass in a struct, not the pointer to struct"); static_assert(std::is_trivially_copyable(), "must be memcpy-able"); - writeBytes(reinterpret_cast(¶m), sizeof(T)); + writeBytes(angle::byte_span_from_ref(param)); } template @@ -285,51 +254,38 @@ class BinaryOutputStream : angle::NonCopyable writeInt(static_cast(param)); } - void writeString(const std::string &v) + void writeString(std::string_view v) { - writeInt(v.length()); - write(v.c_str(), v.length()); + writeInt(v.size()); + write(angle::as_byte_span(v)); } - void writeString(const char *v) - { - size_t len = strlen(v); - writeInt(len); - write(v, len); - } - - void writeBytes(const unsigned char *bytes, size_t count) { write(bytes, count); } + void writeBytes(angle::Span bytes) { write(bytes); } void writeBool(bool value) { - int intValue = value ? 1 : 0; - write(&intValue, 1); + const int intValue = value ? 1 : 0; + write(angle::byte_span_from_ref(intValue)); } - void writeFloat(float value) { write(&value, 1); } + void writeFloat(float value) { write(angle::byte_span_from_ref(value)); } - size_t length() const { return mData.size(); } + // data() and size() methods allow implicit conversion to span. + const uint8_t *data() const { return mData.data(); } + size_t size() const { return mData.size(); } - const void *data() const { return mData.size() ? &mData[0] : nullptr; } - - const std::vector &getData() const { return mData; } + // No further use of this stream allowed after data is taken. + std::vector takeData() { return std::move(mData); } private: - template - void write(const T *v, size_t num) + void write(angle::Span srcSpan) { - static_assert(std::is_fundamental::value, "T must be a fundamental type."); - const char *asBytes = reinterpret_cast(v); - mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T)); + mData.insert(mData.end(), srcSpan.begin(), srcSpan.end()); } std::vector mData; }; -inline BinaryOutputStream::BinaryOutputStream() {} - -inline BinaryOutputStream::~BinaryOutputStream() = default; - } // namespace gl #endif // COMMON_BINARYSTREAM_H_ diff --git a/src/common/BinaryStream_unittest.cpp b/src/common/BinaryStream_unittest.cpp index fcaaa3ee1af..bf1870c5d56 100644 --- a/src/common/BinaryStream_unittest.cpp +++ b/src/common/BinaryStream_unittest.cpp @@ -6,10 +6,19 @@ // BinaryStream_unittest.cpp: Unit tests of the binary stream classes. -#include - #include "common/BinaryStream.h" +#include + +#include +#include + +#include "common/PackedEnums.h" +#include "common/span.h" +#include "common/span_util.h" +#include "common/unsafe_buffers.h" +#include "gtest/gtest.h" + namespace angle { @@ -23,17 +32,18 @@ TEST(BinaryInputStream, Overflow) const size_t slopSize = 1024; std::vector data(dataSize + slopSize); - std::fill(data.begin(), data.begin() + dataSize, goodValue); - std::fill(data.begin() + dataSize, data.end(), badValue); - - std::vector outputData(dataSize); + angle::Span good_data = angle::Span(data).first(dataSize); + angle::Span bad_data = angle::Span(data).subspan(dataSize); + std::fill(good_data.begin(), good_data.end(), goodValue); + std::fill(bad_data.begin(), bad_data.end(), badValue); auto checkDataIsSafe = [=](uint8_t item) { return item == goodValue; }; { // One large read - gl::BinaryInputStream stream(data.data(), dataSize); - stream.readBytes(outputData.data(), dataSize); + std::vector outputData(dataSize); + gl::BinaryInputStream stream(good_data); + stream.readBytes(outputData); ASSERT_FALSE(stream.error()); ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe)); ASSERT_TRUE(stream.endOfStream()); @@ -41,10 +51,11 @@ TEST(BinaryInputStream, Overflow) { // Two half-sized reads - gl::BinaryInputStream stream(data.data(), dataSize); - stream.readBytes(outputData.data(), dataSize / 2); + std::vector outputData(dataSize); + gl::BinaryInputStream stream(good_data); + stream.readBytes(angle::Span(outputData).first(dataSize / 2)); ASSERT_FALSE(stream.error()); - stream.readBytes(outputData.data() + dataSize / 2, dataSize / 2); + stream.readBytes(angle::Span(outputData).subspan(dataSize / 2)); ASSERT_FALSE(stream.error()); ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe)); ASSERT_TRUE(stream.endOfStream()); @@ -52,22 +63,71 @@ TEST(BinaryInputStream, Overflow) { // One large read that is too big - gl::BinaryInputStream stream(data.data(), dataSize); - stream.readBytes(outputData.data(), dataSize + 1); + std::vector outputData(dataSize + 1); + gl::BinaryInputStream stream(good_data); + stream.readBytes(outputData); ASSERT_TRUE(stream.error()); } { // Two reads, one that overflows the offset - gl::BinaryInputStream stream(data.data(), dataSize); - stream.readBytes(outputData.data(), dataSize - 1); + std::vector outputData(dataSize - 1); + gl::BinaryInputStream stream(good_data); + stream.readBytes(outputData); ASSERT_FALSE(stream.error()); - stream.readBytes(outputData.data(), std::numeric_limits::max() - dataSize - 2); + // SAFETY: required for test, span is not legitimate. + ANGLE_UNSAFE_BUFFERS(stream.readBytes( + angle::Span(outputData.data(), std::numeric_limits::max() - dataSize - 2))); + ASSERT_TRUE(stream.error()); } } +// Test that readInt<> and writeInt<> match. +TEST(BinaryStream, Int) +{ + gl::BinaryOutputStream out; + out.writeInt(-100); + out.writeInt(-200); + out.writeInt(-300); + out.writeInt(-400); + out.writeInt(100); + out.writeInt(200); + out.writeInt(300); + out.writeInt(400); + out.writeInt(500); + + gl::BinaryInputStream in(out); + EXPECT_EQ(in.readInt(), -100); + EXPECT_EQ(in.readInt(), -200); + EXPECT_EQ(in.readInt(), -300); + EXPECT_EQ(in.readInt(), -400); + EXPECT_EQ(in.readInt(), 100u); + EXPECT_EQ(in.readInt(), 200u); + EXPECT_EQ(in.readInt(), 300u); + EXPECT_EQ(in.readInt(), 400u); + EXPECT_EQ(in.readInt(), 500u); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + +// Test that readBool and writeBool match. +TEST(BinaryStream, Bool) +{ + gl::BinaryOutputStream out; + out.writeBool(true); + out.writeBool(false); + + gl::BinaryInputStream in(out); + EXPECT_EQ(in.readBool(), true); + EXPECT_EQ(in.readBool(), false); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + // Test that readVector and writeVector match. -TEST(BinaryStream, IntVector) +TEST(BinaryStream, Vector) { std::vector writeData = {1, 2, 3, 4, 5}; std::vector readData; @@ -75,7 +135,7 @@ TEST(BinaryStream, IntVector) gl::BinaryOutputStream out; out.writeVector(writeData); - gl::BinaryInputStream in(out.data(), out.length()); + gl::BinaryInputStream in(out); in.readVector(&readData); ASSERT_EQ(writeData.size(), readData.size()); @@ -85,4 +145,150 @@ TEST(BinaryStream, IntVector) ASSERT_EQ(writeData[i], readData[i]); } } + +// Test that readString and writeString match. +TEST(BinaryStream, String) +{ + std::string empty; + std::string hello("hello"); + std::string nulls("\0\0\0", 3u); + EXPECT_EQ(3u, nulls.size()); + + gl::BinaryOutputStream out; + out.writeString(empty); + out.writeString(hello); + out.writeString(nulls); + out.writeString(empty); + out.writeString(empty); + out.writeString(hello); + + gl::BinaryInputStream in(out); + EXPECT_EQ(in.readString(), empty); + EXPECT_EQ(in.readString(), hello); + EXPECT_EQ(in.readString(), nulls); + EXPECT_EQ(in.readString(), empty); + EXPECT_EQ(in.readString(), empty); + EXPECT_EQ(in.readString(), hello); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + +// Test that readStruct and writeStruct match. +TEST(BinaryStream, Struct) +{ + struct Pod + { + int count; + char array[3]; + }; + + Pod pod1 = {123, {1, 2, 3}}; + gl::BinaryOutputStream out; + out.writeStruct(pod1); + + Pod pod2; + gl::BinaryInputStream in(out); + in.readStruct(&pod2); + EXPECT_TRUE(angle::byte_span_from_ref(pod1) == angle::byte_span_from_ref(pod2)); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + +// Test that readEnum and writeEnum match. +TEST(BinaryStream, Enum) +{ + enum class Color : uint8_t + { + kRed, + kGreen, + kBlue + }; + enum class Shorty : int16_t + { + kNeg = -1, + kMax = 32767 + }; + + gl::BinaryOutputStream out; + out.writeEnum(Color::kRed); + out.writeEnum(Shorty::kNeg); + out.writeEnum(Color::kGreen); + out.writeEnum(Shorty::kMax); + out.writeEnum(Color::kBlue); + + gl::BinaryInputStream in(out); + EXPECT_EQ(Color::kRed, in.readEnum()); + EXPECT_EQ(Shorty::kNeg, in.readEnum()); + EXPECT_EQ(Color::kGreen, in.readEnum()); + EXPECT_EQ(Shorty::kMax, in.readEnum()); + EXPECT_EQ(Color::kBlue, in.readEnum()); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + +// Test that readFloat and writeFloat match. +TEST(BinaryStream, Float) +{ + gl::BinaryOutputStream out; + out.writeFloat(123.456f); + out.writeFloat(-100.0f); + out.writeFloat(0.0f); + + gl::BinaryInputStream in(out); + EXPECT_EQ(123.456f, in.readFloat()); + EXPECT_EQ(-100.0f, in.readFloat()); + EXPECT_EQ(0.0f, in.readFloat()); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + +// Test that readPackedEnumMap and writePackedEnumMap match. +TEST(BinaryStream, PackedEnumMap) +{ + enum class Color : int16_t + { + kRed, + kGreen, + kBlue, + EnumCount = 3 + }; + + angle::PackedEnumMap map1; + map1[Color::kRed] = 1.0f; + map1[Color::kGreen] = 2.0f; + map1[Color::kBlue] = 3.0f; + + gl::BinaryOutputStream out; + out.writePackedEnumMap(map1); + + angle::PackedEnumMap map2; + gl::BinaryInputStream in(out); + in.readPackedEnumMap(&map2); + EXPECT_EQ(map2[Color::kRed], 1.0f); + EXPECT_EQ(map2[Color::kGreen], 2.0f); + EXPECT_EQ(map2[Color::kBlue], 3.0f); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + +// Test that skipping ahead works as expected. +TEST(BinaryStream, Skip) +{ + gl::BinaryOutputStream out; + out.writeFloat(123.456f); + out.writeFloat(-100.0f); + + gl::BinaryInputStream in(out); + in.skip(sizeof(float)); + EXPECT_EQ(-100.0f, in.readFloat()); + + EXPECT_FALSE(in.error()); + EXPECT_TRUE(in.endOfStream()); +} + } // namespace angle diff --git a/src/common/Color.h b/src/common/Color.h index 089c01d9378..964e3819f01 100644 --- a/src/common/Color.h +++ b/src/common/Color.h @@ -9,6 +9,10 @@ #ifndef COMMON_COLOR_H_ #define COMMON_COLOR_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include diff --git a/src/common/Color.inc b/src/common/Color.inc index 605cf025d62..2d80c813beb 100644 --- a/src/common/Color.inc +++ b/src/common/Color.inc @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +#pragma allow_unsafe_buffers +#endif + // Color.inc : Inline definitions of some functions from Color.h namespace angle diff --git a/src/common/CompiledShaderState.cpp b/src/common/CompiledShaderState.cpp index fdd8d89dab2..916de6d514f 100644 --- a/src/common/CompiledShaderState.cpp +++ b/src/common/CompiledShaderState.cpp @@ -8,9 +8,16 @@ // shader variables. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/CompiledShaderState.h" +#include + #include "common/BinaryStream.h" +#include "common/span.h" #include "common/utilities.h" namespace gl @@ -98,6 +105,7 @@ void WriteShaderVar(gl::BinaryOutputStream *stream, const sh::ShaderVariable &va stream->writeBool(var.texelFetchStaticUse); stream->writeInt(var.getFlattenedOffsetInParentArrays()); stream->writeInt(var.id); + stream->writeBool(var.isFloat16); } void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var) @@ -136,6 +144,7 @@ void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var) var->texelFetchStaticUse = stream->readBool(); var->setParentArrayIndex(stream->readInt()); var->id = stream->readInt(); + var->isFloat16 = stream->readBool(); } void WriteShInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block) @@ -180,9 +189,60 @@ void LoadShInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock *blo } } +std::string JoinShaderSources(GLsizei count, const char *const *string, const GLint *length) +{ + // Fast path for the most common case. + if (count == 1) + { + if (length == nullptr || length[0] < 0) + { + return std::string(string[0]); + } + else + { + return std::string(string[0], static_cast(length[0])); + } + } + + // Start with totalLength of 1 to reserve space for the null terminator + size_t totalLength = 1; + + // First pass, calculate the total length of the joined string + for (GLsizei i = 0; i < count; ++i) + { + if (length == nullptr || length[i] < 0) + { + totalLength += std::strlen(string[i]); + } + else + { + totalLength += static_cast(length[i]); + } + } + + // Second pass, allocate the string and concatenate each shader source + // fragment + std::string joinedString; + joinedString.reserve(totalLength); + for (GLsizei i = 0; i < count; ++i) + { + if (length == nullptr || length[i] < 0) + { + joinedString.append(string[i]); + } + else + { + joinedString.append(string[i], static_cast(length[i])); + } + } + + return joinedString; +} + CompiledShaderState::CompiledShaderState(gl::ShaderType type) : shaderType(type), shaderVersion(100), + translatedSource(std::make_shared()), numViews(-1), geometryShaderInputPrimitiveType(gl::PrimitiveMode::Triangles), geometryShaderOutputPrimitiveType(gl::PrimitiveMode::Triangles), @@ -199,16 +259,23 @@ CompiledShaderState::CompiledShaderState(gl::ShaderType type) CompiledShaderState::~CompiledShaderState() {} +void CompiledShaderState::buildPassthroughCompiledShaderState( + std::shared_ptr inputShaderSource) +{ + translatedSource = inputShaderSource; +} + void CompiledShaderState::buildCompiledShaderState(const ShHandle compilerHandle, - const bool isBinaryOutput) + ShShaderOutput outputType) { - if (isBinaryOutput) + switch (outputType) { - compiledBinary = sh::GetObjectBinaryBlob(compilerHandle); - } - else - { - translatedSource = sh::GetObjectCode(compilerHandle); + case SH_SPIRV_VULKAN_OUTPUT: + compiledBinary = sh::GetObjectBinaryBlob(compilerHandle); + break; + default: + translatedSource = std::make_shared(sh::GetObjectCode(compilerHandle)); + break; } // Gather the shader information @@ -387,8 +454,7 @@ void CompiledShaderState::serialize(gl::BinaryOutputStream &stream) const } stream.writeInt(advancedBlendEquations.bits()); stream.writeInt(pixelLocalStorageFormats.size()); - stream.writeBytes(reinterpret_cast(pixelLocalStorageFormats.data()), - pixelLocalStorageFormats.size()); + stream.writeBytes(angle::as_byte_span(pixelLocalStorageFormats)); break; } case gl::ShaderType::Geometry: @@ -406,11 +472,11 @@ void CompiledShaderState::serialize(gl::BinaryOutputStream &stream) const { unsigned char value = static_cast(geometryShaderInputPrimitiveType); - stream.writeBytes(&value, 1); + stream.writeBytes(angle::byte_span_from_ref(value)); } { unsigned char value = static_cast(geometryShaderOutputPrimitiveType); - stream.writeBytes(&value, 1); + stream.writeBytes(angle::byte_span_from_ref(value)); } { int value = static_cast(geometryShaderMaxVertices); @@ -467,7 +533,7 @@ void CompiledShaderState::serialize(gl::BinaryOutputStream &stream) const UNREACHABLE(); } - stream.writeString(translatedSource); + stream.writeString(*translatedSource); stream.writeVector(compiledBinary); } @@ -562,8 +628,7 @@ void CompiledShaderState::deserialize(gl::BinaryInputStream &stream) stream.readInt(&advancedBlendEquationBits); advancedBlendEquations = gl::BlendEquationBitSet(advancedBlendEquationBits); pixelLocalStorageFormats.resize(stream.readInt()); - stream.readBytes(reinterpret_cast(pixelLocalStorageFormats.data()), - pixelLocalStorageFormats.size()); + stream.readBytes(angle::as_writable_byte_span(pixelLocalStorageFormats)); break; } case gl::ShaderType::Geometry: @@ -583,13 +648,13 @@ void CompiledShaderState::deserialize(gl::BinaryInputStream &stream) { unsigned char value; - stream.readBytes(&value, 1); + stream.readBytes(angle::byte_span_from_ref(value)); geometryShaderInputPrimitiveType = static_cast(value); } { unsigned char value; - stream.readBytes(&value, 1); + stream.readBytes(angle::byte_span_from_ref(value)); geometryShaderOutputPrimitiveType = static_cast(value); } @@ -653,7 +718,11 @@ void CompiledShaderState::deserialize(gl::BinaryInputStream &stream) UNREACHABLE(); } - stream.readString(&translatedSource); + { + std::string src; + stream.readString(&src); + translatedSource = std::make_shared(std::move(src)); + } stream.readVector(&compiledBinary); } } // namespace gl diff --git a/src/common/CompiledShaderState.h b/src/common/CompiledShaderState.h index 641ba9e3c2f..aeda13f3cee 100644 --- a/src/common/CompiledShaderState.h +++ b/src/common/CompiledShaderState.h @@ -44,12 +44,16 @@ void LoadShInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock *blo bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y); +std::string JoinShaderSources(GLsizei count, const char *const *string, const GLint *length); + struct CompiledShaderState { CompiledShaderState(gl::ShaderType shaderType); ~CompiledShaderState(); - void buildCompiledShaderState(const ShHandle compilerHandle, const bool isBinaryOutput); + void buildCompiledShaderState(const ShHandle compilerHandle, + ShShaderOutput outputType); + void buildPassthroughCompiledShaderState(std::shared_ptr inputShaderSource); void serialize(gl::BinaryOutputStream &stream) const; void deserialize(gl::BinaryInputStream &stream); @@ -70,7 +74,7 @@ struct CompiledShaderState const gl::ShaderType shaderType; int shaderVersion; - std::string translatedSource; + std::shared_ptr translatedSource; sh::BinaryBlob compiledBinary; sh::WorkGroupSize localSize; diff --git a/src/common/FastVector.h b/src/common/FastVector.h index 197c3effa1d..9d613e0d17a 100644 --- a/src/common/FastVector.h +++ b/src/common/FastVector.h @@ -11,6 +11,10 @@ #ifndef COMMON_FASTVECTOR_H_ #define COMMON_FASTVECTOR_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "bitset_utils.h" #include "common/debug.h" diff --git a/src/common/FastVector_unittest.cpp b/src/common/FastVector_unittest.cpp index e551bf332d2..ba2aa6e9437 100644 --- a/src/common/FastVector_unittest.cpp +++ b/src/common/FastVector_unittest.cpp @@ -7,6 +7,10 @@ // Tests of the FastVector class // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/FastVector.h" diff --git a/src/common/FixedVector.h b/src/common/FixedVector.h index 52a1751d16a..ab97d2ec3bf 100644 --- a/src/common/FixedVector.h +++ b/src/common/FixedVector.h @@ -341,9 +341,9 @@ template void FixedVector::assign_from_initializer_list( std::initializer_list init) { - for (auto element : init) + for (const auto &element : init) { - mStorage[mSize] = std::move(element); + mStorage[mSize] = element; mSize++; } } @@ -355,4 +355,19 @@ bool FixedVector::full() const } } // namespace angle +namespace std +{ +template +typename angle::FixedVector::size_type erase_if(angle::FixedVector &c, + Predicate pred) +{ + const auto oldSize = c.size(); + auto it = std::remove_if(c.begin(), c.end(), pred); + const auto newSize = static_cast::size_type>( + std::distance(c.begin(), it)); + c.resize(newSize); + return oldSize - c.size(); +} +} // namespace std + #endif // COMMON_FIXEDVECTOR_H_ diff --git a/src/common/FixedVector_unittest.cpp b/src/common/FixedVector_unittest.cpp index 8a25857e799..9a9f257f203 100644 --- a/src/common/FixedVector_unittest.cpp +++ b/src/common/FixedVector_unittest.cpp @@ -150,4 +150,15 @@ TEST(FixedVector, Full) vec.push_back(1); EXPECT_TRUE(vec.full()); } + +// Test the `std::erase_if` overload. +TEST(FixedVector, StdEraseIf) +{ + FixedVector vec = {0, 1, 2, 3, 4}; + EXPECT_EQ(3u, std::erase_if(vec, [](int value) { return (value % 2) == 0; })); + EXPECT_EQ(2u, vec.size()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(3, vec[1]); +} + } // namespace angle diff --git a/src/common/Float16ToFloat32.py b/src/common/Float16ToFloat32.py index 592da65e75b..7ee794ecc42 100644 --- a/src/common/Float16ToFloat32.py +++ b/src/common/Float16ToFloat32.py @@ -15,12 +15,11 @@ def convertMantissa(i): return 0 elif i < 1024: m = i << 13 - e = 0 + e = 0x38800000 while not (m & 0x00800000): e -= 0x00800000 m = m << 1 m &= ~0x00800000 - e += 0x38800000 return m | e else: return 0x38000000 + ((i - 1024) << 13) @@ -48,7 +47,7 @@ def convertOffset(i): return 1024 -print """// +print("""// // Copyright 2012 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. @@ -56,29 +55,31 @@ def convertOffset(i): // This file is automatically generated. +#include "common/mathutil.h" + namespace gl { -""" +""") -print "const static unsigned g_mantissa[2048] = {" +print("const static unsigned g_mantissa[2048] = {") for i in range(0, 2048): - print " %#010x," % convertMantissa(i) -print "};\n" + print(" %#010x," % convertMantissa(i)) +print("};\n") -print "const static unsigned g_exponent[64] = {" +print("const static unsigned g_exponent[64] = {") for i in range(0, 64): - print " %#010x," % convertExponent(i) -print "};\n" + print(" %#010x," % convertExponent(i)) +print("};\n") -print "const static unsigned g_offset[64] = {" +print("const static unsigned g_offset[64] = {") for i in range(0, 64): - print " %#010x," % convertOffset(i) -print "};\n" + print(" %#010x," % convertOffset(i)) +print("};\n") -print """float float16ToFloat32(unsigned short h) +print("""float float16ToFloat32(unsigned short h) { unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; return bitCast(i32); } } -""" +""") diff --git a/src/common/MemoryBuffer.cpp b/src/common/MemoryBuffer.cpp index 98dce64c864..75d9d97b171 100644 --- a/src/common/MemoryBuffer.cpp +++ b/src/common/MemoryBuffer.cpp @@ -6,11 +6,14 @@ #include "common/MemoryBuffer.h" +#include +#include + #include -#include -#include +#include #include "common/debug.h" +#include "common/unsafe_buffers.h" namespace angle { @@ -23,12 +26,7 @@ MemoryBuffer::~MemoryBuffer() void MemoryBuffer::destroy() { - if (mData) - { - free(mData); - mData = nullptr; - } - + free(std::exchange(mData, nullptr)); mSize = 0; mCapacity = 0; #if defined(ANGLE_ENABLE_ASSERTS) @@ -39,15 +37,23 @@ void MemoryBuffer::destroy() bool MemoryBuffer::resize(size_t newSize) { - // If new size is within mCapacity, update mSize and early-return - if (newSize <= mCapacity) + if (!reserve(newSize)) + { + return false; + } + mSize = newSize; + return true; +} + +bool MemoryBuffer::reserve(size_t newCapacity) +{ + if (newCapacity <= mCapacity) { - mSize = newSize; + // Can already accommodate newCapacity, nothing to do. return true; } - // New size exceeds mCapacity, need to reallocate and copy over previous content. - uint8_t *newMemory = static_cast(malloc(sizeof(uint8_t) * newSize)); + uint8_t *newMemory = static_cast(malloc(newCapacity)); if (newMemory == nullptr) { return false; @@ -55,101 +61,41 @@ bool MemoryBuffer::resize(size_t newSize) // Book keeping #if defined(ANGLE_ENABLE_ASSERTS) - mTotalAllocatedBytes += newSize; + mTotalAllocatedBytes += newCapacity; #endif // ANGLE_ENABLE_ASSERTS - if (mData) + if (mSize > 0) { - if (mSize > 0) - { - // Copy the intersection of the old data and the new data - std::copy(mData, mData + mSize, newMemory); - + // Copy the intersection of the old data and the new data. + // SAFETY: Relies on correct size allocation above. + ANGLE_UNSAFE_BUFFERS(memcpy(newMemory, mData, mSize)); // Book keeping #if defined(ANGLE_ENABLE_ASSERTS) - mTotalCopiedBytes += mSize; + mTotalCopiedBytes += mSize; #endif // ANGLE_ENABLE_ASSERTS - } - free(mData); } - mData = newMemory; - mSize = newSize; - mCapacity = newSize; - + free(std::exchange(mData, newMemory)); + mCapacity = newCapacity; return true; } -bool MemoryBuffer::clearAndReserve(size_t newSize) +bool MemoryBuffer::clearAndReserve(size_t newCapacity) { clear(); - return reserve(newSize); -} - -bool MemoryBuffer::reserve(size_t newSize) -{ - if (newSize <= mCapacity) - { - // Can already accommodate newSize, nothing to do. - return true; - } - - // Cache original size - size_t originalSize = mSize; - - if (!resize(newSize)) - { - return false; - } - - // reserve(...) won't affect mSize, reset to original value. - mSize = originalSize; - - return true; -} - -bool MemoryBuffer::append(const MemoryBuffer &other) -{ - uint8_t *srcBuffer = other.mData; - const size_t srcBufferSize = other.mSize; - - // Handle the corner case where we are appending to self - if (this == &other) - { - if (!reserve(mSize * 2)) - { - return false; - } - srcBuffer = other.mData; - } - - return appendRaw(srcBuffer, srcBufferSize); -} - -bool MemoryBuffer::appendRaw(const uint8_t *buffer, const size_t bufferSize) -{ - ASSERT(buffer && bufferSize > 0); - - if (!reserve(mSize + bufferSize)) - { - return false; - } - - std::memcpy(mData + mSize, buffer, bufferSize); - mSize += bufferSize; - - return true; + return reserve(newCapacity); } void MemoryBuffer::fill(uint8_t datum) { if (!empty()) { - std::fill(mData, mData + mSize, datum); + // SAFETY: `mData` is always valid for `mSize`. + ANGLE_UNSAFE_BUFFERS(std::fill(mData, mData + mSize, datum)); } } -MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer() +MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) { *this = std::move(other); } @@ -244,7 +190,7 @@ void ScratchBuffer::tick() --mResetCounter; if (mResetCounter == 0) { - clear(); + destroy(); } } } @@ -252,10 +198,12 @@ void ScratchBuffer::tick() void ScratchBuffer::clear() { mResetCounter = mLifetime; - if (mScratchMemory.size() > 0) - { - mScratchMemory.clear(); - } + mScratchMemory.clear(); +} + +void ScratchBuffer::destroy() +{ + mScratchMemory.destroy(); } } // namespace angle diff --git a/src/common/MemoryBuffer.h b/src/common/MemoryBuffer.h index 117950bdaef..93842548851 100644 --- a/src/common/MemoryBuffer.h +++ b/src/common/MemoryBuffer.h @@ -7,16 +7,20 @@ #ifndef COMMON_MEMORYBUFFER_H_ #define COMMON_MEMORYBUFFER_H_ +#include +#include + #include "common/Optional.h" #include "common/angleutils.h" #include "common/debug.h" - -#include -#include +#include "common/span.h" +#include "common/unsafe_buffers.h" namespace angle { +// MemoryBuffers are used in place of std::vector when an uninitialized buffer +// as would be obtained via malloc is required. class MemoryBuffer final : NonCopyable { public: @@ -26,22 +30,20 @@ class MemoryBuffer final : NonCopyable MemoryBuffer(MemoryBuffer &&other); MemoryBuffer &operator=(MemoryBuffer &&other); - // Destroy underlying memory + // Free underlying memory. After this call, the MemoryBuffer has zero size + // but can be reused given a subsequent resize()/reserve(). void destroy(); - // Updates mSize to newSize. Updates mCapacity iff newSize > mCapacity + // Updates mSize to newSize. May cause a reallocation iff newSize > mCapacity. [[nodiscard]] bool resize(size_t newSize); - // Resets mSize to 0. Reserves memory and updates mCapacity iff newSize > mCapacity - [[nodiscard]] bool clearAndReserve(size_t newSize); + // Updates mCapacity iff newCapacity > mCapacity. May cause a reallocation if + // newCapacity > mCapacity. + [[nodiscard]] bool reserve(size_t newCapacity); - // Updates mCapacity iff newSize > mCapacity - [[nodiscard]] bool reserve(size_t newSize); - - // Appends content from "other" MemoryBuffer - [[nodiscard]] bool append(const MemoryBuffer &other); - // Appends content from "[buffer, buffer + bufferSize)" - [[nodiscard]] bool appendRaw(const uint8_t *buffer, const size_t bufferSize); + // Sets size to zero and updates mCapacity iff newCapacity > mCapacity. May cause + // a reallocation if newCapacity is greater than mCapacity prior to the clear. + [[nodiscard]] bool clearAndReserve(size_t newCapacity); // Sets size bound by capacity. void setSize(size_t size) @@ -51,7 +53,7 @@ class MemoryBuffer final : NonCopyable } void setSizeToCapacity() { setSize(mCapacity); } - // Invalidate current content + // Sets current size to 0, but retains buffer for future use. void clear() { (void)resize(0); } size_t size() const { return mSize; } @@ -65,15 +67,39 @@ class MemoryBuffer final : NonCopyable return mData; } + // Access entire buffer, although MemoryBuffer should be implicitly convertible to + // any span implementation because it has both data() and size() methods. + angle::Span span() + { + // SAFETY: `mData` is valid for `mSize` bytes. + return ANGLE_UNSAFE_BUFFERS(angle::Span(mData, mSize)); + } + angle::Span span() const + { + // SAFETY: `mData` is valid for `mSize` bytes. + return ANGLE_UNSAFE_BUFFERS(angle::Span(mData, mSize)); + } + + // Convenience methods for accessing portions of the buffer. + angle::Span first(size_t count) { return span().first(count); } + angle::Span last(size_t count) { return span().last(count); } + angle::Span subspan(size_t offset) { return span().subspan(offset); } + angle::Span subspan(size_t offset, size_t count) + { + return span().subspan(offset, count); + } + uint8_t &operator[](size_t pos) { ASSERT(mData && pos < mSize); - return mData[pos]; + // SAFETY: assert on previous line. + return ANGLE_UNSAFE_BUFFERS(mData[pos]); } const uint8_t &operator[](size_t pos) const { ASSERT(mData && pos < mSize); - return mData[pos]; + // SAFETY: assert on previous line. + return ANGLE_UNSAFE_BUFFERS(mData[pos]); } void fill(uint8_t datum); @@ -93,6 +119,9 @@ class MemoryBuffer final : NonCopyable ASSERT(totalCopiedBytes == mTotalCopiedBytes); #endif // ANGLE_ENABLE_ASSERTS } + // Validate data buffer is no longer present. Needed because data() may + // assert a non-null buffer. + void assertDataBufferFreed() const { ASSERT(mData == nullptr); } private: size_t mSize = 0; @@ -108,9 +137,9 @@ class ScratchBuffer final : NonCopyable { public: ScratchBuffer(); - // If we request a scratch buffer requesting a smaller size this many times, release and - // recreate the scratch buffer. This ensures we don't have a degenerate case where we are stuck - // hogging memory. + // If we request a scratch buffer requesting a smaller size this many times, release the + // scratch buffer. This ensures we don't have a degenerate case where we are stuck + // hogging memory. Zero means eternal lifetime. ScratchBuffer(uint32_t lifetime); ~ScratchBuffer(); @@ -123,11 +152,18 @@ class ScratchBuffer final : NonCopyable // Same as get, but ensures new values are initialized to a fixed constant. bool getInitialized(size_t requestedSize, MemoryBuffer **memoryBufferOut, uint8_t initValue); - // Ticks the release counter for the scratch buffer. Also done implicitly in get(). + // Ticks the release counter for the scratch buffer. Also done implicitly in get(). Memory + // will be returned to the system after tick expiration. void tick(); + // clear() the underlying MemoryBuffer, setting size to zero but retaining + // any allocated memory. void clear(); + // destroy() the underlying MemoryBuffer, setting size to zero and freeing + // any allocated memory. + void destroy(); + MemoryBuffer *getMemoryBuffer() { return &mScratchMemory; } private: diff --git a/src/common/MemoryBuffer_unittest.cpp b/src/common/MemoryBuffer_unittest.cpp index 6c82f1fb495..b9f01702068 100644 --- a/src/common/MemoryBuffer_unittest.cpp +++ b/src/common/MemoryBuffer_unittest.cpp @@ -8,7 +8,11 @@ #include "common/MemoryBuffer.h" -#include +#include + +#include "common/span.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" using namespace angle; @@ -16,7 +20,7 @@ namespace { // Test usage of MemoryBuffer with multiple resizes -TEST(MemoryBufferTest, MultipleResizes) +TEST(MemoryBuffer, MultipleResizes) { MemoryBuffer buffer; @@ -42,7 +46,7 @@ TEST(MemoryBufferTest, MultipleResizes) } // Test usage of MemoryBuffer with reserve and then multiple resizes -TEST(MemoryBufferTest, ReserveThenResize) +TEST(MemoryBuffer, ReserveThenResize) { MemoryBuffer buffer; @@ -70,76 +74,256 @@ TEST(MemoryBufferTest, ReserveThenResize) buffer.assertTotalCopiedBytes(100u); } -// Test usage of MemoryBuffer with clearAndReserve and then multiple resizes -TEST(MemoryBufferTest, ClearAndReserveThenResize) +// Test that clear() of a memory buffer retains the buffer. +TEST(MemoryBuffer, Clear) { MemoryBuffer buffer; + ASSERT_TRUE(buffer.resize(100)); + ASSERT_EQ(buffer.size(), 100u); + ASSERT_NE(buffer.data(), nullptr); + buffer.assertTotalAllocatedBytes(100u); + buffer.assertTotalCopiedBytes(0u); - ASSERT_TRUE(buffer.clearAndReserve(300)); - ASSERT_EQ(buffer.size(), 0u); + uint8_t *oldPtr = buffer.data(); + + buffer.clear(); + EXPECT_EQ(buffer.size(), 0u); + EXPECT_EQ(buffer.data(), oldPtr); + buffer.assertTotalAllocatedBytes(100u); + buffer.assertTotalCopiedBytes(0u); ASSERT_TRUE(buffer.resize(100)); ASSERT_EQ(buffer.size(), 100u); - buffer.assertTotalAllocatedBytes(300u); + EXPECT_EQ(buffer.data(), oldPtr); + buffer.assertTotalAllocatedBytes(100u); buffer.assertTotalCopiedBytes(0u); +} - ASSERT_TRUE(buffer.resize(300)); - ASSERT_EQ(buffer.size(), 300u); - buffer.assertTotalAllocatedBytes(300u); +// Test that destroy() of a memory buffer does not retain the buffer. +// Test destroying MemoryBuffer +TEST(MemoryBuffer, Destroy) +{ + MemoryBuffer buffer; + ASSERT_TRUE(buffer.resize(100)); + ASSERT_EQ(buffer.size(), 100u); + ASSERT_NE(buffer.data(), nullptr); + buffer.assertTotalAllocatedBytes(100u); + buffer.assertTotalCopiedBytes(0u); + + buffer.destroy(); + EXPECT_EQ(buffer.size(), 0u); + buffer.assertDataBufferFreed(); + buffer.assertTotalAllocatedBytes(0u); buffer.assertTotalCopiedBytes(0u); ASSERT_TRUE(buffer.resize(100)); ASSERT_EQ(buffer.size(), 100u); - buffer.assertTotalAllocatedBytes(300u); + ASSERT_NE(buffer.data(), nullptr); + buffer.assertTotalAllocatedBytes(100u); buffer.assertTotalCopiedBytes(0u); +} - ASSERT_TRUE(buffer.clearAndReserve(400)); +// Test usage of MemoryBuffer with clearAndReserve() and then multiple resizes. +TEST(MemoryBuffer, ClearAndReserve) +{ + MemoryBuffer buffer; + ASSERT_TRUE(buffer.resize(200)); + ASSERT_EQ(buffer.size(), 200u); + ASSERT_NE(buffer.data(), nullptr); + buffer.assertTotalAllocatedBytes(200u); + buffer.assertTotalCopiedBytes(0u); + + uint8_t *oldPtr = buffer.data(); + + ASSERT_TRUE(buffer.clearAndReserve(100)); ASSERT_EQ(buffer.size(), 0u); + EXPECT_EQ(buffer.data(), oldPtr); + buffer.assertTotalAllocatedBytes(200u); + buffer.assertTotalCopiedBytes(0u); - ASSERT_TRUE(buffer.resize(400)); - ASSERT_EQ(buffer.size(), 400u); - buffer.assertTotalAllocatedBytes(700u); + ASSERT_TRUE(buffer.resize(200)); + ASSERT_EQ(buffer.size(), 200u); + EXPECT_EQ(buffer.data(), oldPtr); + buffer.assertTotalAllocatedBytes(200u); buffer.assertTotalCopiedBytes(0u); + + ASSERT_TRUE(buffer.resize(300)); + ASSERT_EQ(buffer.size(), 300u); + EXPECT_NE(buffer.data(), oldPtr); + buffer.assertTotalAllocatedBytes(500u); + buffer.assertTotalCopiedBytes(200u); +} + +// Test that the span() method returns entire buffer. +TEST(MemoryBuffer, Span) +{ + MemoryBuffer buf; + { + Span s = buf.span(); + EXPECT_EQ(s.size(), 0u); + EXPECT_EQ(s.data(), nullptr); + } + ASSERT_TRUE(buf.resize(2u)); + { + Span s = buf.span(); + EXPECT_EQ(s.size(), 2u); + EXPECT_EQ(s.data(), buf.data()); + } +} + +// Test that the subspan() method returns correct portion of buffer. +TEST(MemoryBuffer, Subspan) +{ + MemoryBuffer buf; + { + Span s = buf.subspan(0); + EXPECT_EQ(s.size(), 0u); + EXPECT_EQ(s.data(), nullptr); + } + { + Span s = buf.subspan(0, 0); + EXPECT_EQ(s.size(), 0u); + EXPECT_EQ(s.data(), nullptr); + } + ASSERT_TRUE(buf.resize(4u)); + for (size_t i = 0; i < buf.size(); ++i) + { + buf[i] = i; + } + { + Span s = buf.subspan(0, 0); + EXPECT_EQ(s.size(), 0u); + } + { + Span s = buf.subspan(2, 0); + EXPECT_THAT(s.size(), 0u); + } + { + Span s = buf.subspan(0, 1); + EXPECT_THAT(s, testing::ElementsAre(0u)); + } + { + Span s = buf.subspan(1, 2); + EXPECT_THAT(s, testing::ElementsAre(1u, 2u)); + } + { + Span s = buf.subspan(3); + EXPECT_THAT(s, testing::ElementsAre(3u)); + } + { + Span s = buf.subspan(4); + EXPECT_THAT(s.size(), 0u); + } +} + +// Test that the first() method returns correct portion of buffer. +TEST(MemoryBuffer, First) +{ + MemoryBuffer buf; + { + Span s = buf.first(0); + EXPECT_EQ(s.size(), 0u); + EXPECT_EQ(s.data(), nullptr); + } + ASSERT_TRUE(buf.resize(4u)); + for (size_t i = 0; i < buf.size(); ++i) + { + buf[i] = i; + } + { + Span s = buf.first(0); + EXPECT_EQ(s.size(), 0u); + } + { + Span s = buf.first(2u); + EXPECT_THAT(s, testing::ElementsAre(0u, 1u)); + } +} + +// Test that the last() method returns correct portion of buffer. +TEST(MemoryBuffer, Last) +{ + MemoryBuffer buf; + { + Span s = buf.last(0); + EXPECT_EQ(s.size(), 0u); + EXPECT_EQ(s.data(), nullptr); + } + ASSERT_TRUE(buf.resize(4u)); + for (size_t i = 0; i < buf.size(); ++i) + { + buf[i] = i; + } + { + Span s = buf.last(0); + EXPECT_EQ(s.size(), 0u); + } + { + Span s = buf.last(2u); + EXPECT_THAT(s, testing::ElementsAre(2u, 3u)); + } +} + +// Test that filling a memory buffer writes the expected value. +TEST(MemoryBuffer, Fill) +{ + MemoryBuffer buf; + + // Test fill is a no-op on an empty buffer. + buf.fill(0x41); + EXPECT_TRUE(buf.empty()); + + ASSERT_TRUE(buf.resize(2)); + buf.fill(0x41); + EXPECT_EQ(0x41u, buf[0]); + EXPECT_EQ(0x41u, buf[1]); } -// Test appending and destroying MemoryBuffer -TEST(MemoryBufferTest, AppendAndDestroy) +// Demonstrate current behavior of ScratchBuffer lifetime mechanism +TEST(ScratchBuffer, Lifetime) { - MemoryBuffer bufferSrc; - MemoryBuffer bufferDst; - - ASSERT_TRUE(bufferSrc.clearAndReserve(100)); - ASSERT_EQ(bufferSrc.size(), 0u); - - ASSERT_TRUE(bufferSrc.resize(100)); - ASSERT_EQ(bufferSrc.size(), 100u); - bufferSrc.assertTotalAllocatedBytes(100u); - bufferSrc.assertTotalCopiedBytes(0u); - - ASSERT_TRUE(bufferDst.clearAndReserve(200)); - ASSERT_EQ(bufferDst.size(), 0u); - - ASSERT_TRUE(bufferDst.resize(100)); - ASSERT_EQ(bufferDst.size(), 100u); - ASSERT_TRUE(bufferDst.append(bufferSrc)); - ASSERT_EQ(bufferDst.size(), 200u); - bufferDst.assertTotalAllocatedBytes(200u); - bufferDst.assertTotalCopiedBytes(0u); - - ASSERT_TRUE(bufferDst.append(bufferSrc)); - ASSERT_EQ(bufferDst.size(), 300u); - bufferDst.assertTotalAllocatedBytes(500u); - bufferDst.assertTotalCopiedBytes(200u); - - ASSERT_TRUE(bufferDst.append(bufferDst)); - ASSERT_EQ(bufferDst.size(), 600u); - bufferDst.assertTotalAllocatedBytes(1100u); - bufferDst.assertTotalCopiedBytes(500u); - - bufferDst.destroy(); - ASSERT_EQ(bufferDst.size(), 0u); - bufferDst.assertTotalAllocatedBytes(0u); - bufferDst.assertTotalCopiedBytes(0u); + ScratchBuffer scratch(2); // Live for two ticks. + MemoryBuffer *out; + + ASSERT_TRUE(scratch.get(100u, &out)); + ASSERT_NE(out, nullptr); + ASSERT_NE(out->data(), nullptr); + + uint8_t *oldPtr = out->data(); + + scratch.tick(); + EXPECT_EQ(out->data(), oldPtr); + + scratch.tick(); + out->assertDataBufferFreed(); + + scratch.tick(); + out->assertDataBufferFreed(); +} + +// Test that an initial lifetime of zero means it never expires. +TEST(ScratchBuffer, EternalLifetime) +{ + ScratchBuffer scratch(0); + MemoryBuffer *out; + + ASSERT_TRUE(scratch.get(100u, &out)); + ASSERT_NE(out, nullptr); + ASSERT_NE(out->data(), nullptr); + + uint8_t *oldPtr = out->data(); + + scratch.tick(); + EXPECT_EQ(out->data(), oldPtr); + + scratch.tick(); + EXPECT_EQ(out->data(), oldPtr); + + scratch.tick(); + EXPECT_EQ(out->data(), oldPtr); + + scratch.tick(); + EXPECT_EQ(out->data(), oldPtr); } } // namespace diff --git a/src/common/PackedCLEnums_autogen.cpp b/src/common/PackedCLEnums_autogen.cpp index 1f1097e6fe1..ff2f9a823c3 100644 --- a/src/common/PackedCLEnums_autogen.cpp +++ b/src/common/PackedCLEnums_autogen.cpp @@ -443,6 +443,16 @@ DeviceInfo FromCLenum(CLenum from) return DeviceInfo::PipeSupport; case CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED: return DeviceInfo::LatestConformanceVersionPassed; + case CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR: + return DeviceInfo::IntegerDotProductCapabilities; + case CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR: + return DeviceInfo::IntegerDotProductAccelerationProperties8bit; + case CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR: + return DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked; + case CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR: + return DeviceInfo::ExternalMemoryImportHandleTypes; + case CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR: + return DeviceInfo::ExternalMemoryLinearImagesHandleTypes; default: return DeviceInfo::InvalidEnum; } @@ -670,6 +680,16 @@ CLenum ToCLenum(DeviceInfo from) return CL_DEVICE_PIPE_SUPPORT; case DeviceInfo::LatestConformanceVersionPassed: return CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED; + case DeviceInfo::IntegerDotProductCapabilities: + return CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR; + case DeviceInfo::IntegerDotProductAccelerationProperties8bit: + return CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR; + case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked: + return CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR; + case DeviceInfo::ExternalMemoryImportHandleTypes: + return CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR; + case DeviceInfo::ExternalMemoryLinearImagesHandleTypes: + return CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR; default: UNREACHABLE(); return 0; @@ -1007,6 +1027,21 @@ std::ostream &operator<<(std::ostream &os, DeviceInfo value) case DeviceInfo::LatestConformanceVersionPassed: os << "CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED"; break; + case DeviceInfo::IntegerDotProductCapabilities: + os << "CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR"; + break; + case DeviceInfo::IntegerDotProductAccelerationProperties8bit: + os << "CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR"; + break; + case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked: + os << "CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR"; + break; + case DeviceInfo::ExternalMemoryImportHandleTypes: + os << "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR"; + break; + case DeviceInfo::ExternalMemoryLinearImagesHandleTypes: + os << "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR"; + break; default: os << "GL_INVALID_ENUM"; break; @@ -1139,6 +1174,65 @@ std::ostream &operator<<(std::ostream &os, ExecutionStatus value) return os; } +template <> +ExternalMemoryHandle FromCLenum(CLenum from) +{ + switch (from) + { + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR: + return ExternalMemoryHandle::OpaqueFd; + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR: + return ExternalMemoryHandle::OpaqueWin32; + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR: + return ExternalMemoryHandle::OpaqueWin32Kmt; + case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR: + return ExternalMemoryHandle::DmaBuf; + default: + return ExternalMemoryHandle::InvalidEnum; + } +} + +CLenum ToCLenum(ExternalMemoryHandle from) +{ + switch (from) + { + case ExternalMemoryHandle::OpaqueFd: + return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR; + case ExternalMemoryHandle::OpaqueWin32: + return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR; + case ExternalMemoryHandle::OpaqueWin32Kmt: + return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR; + case ExternalMemoryHandle::DmaBuf: + return CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR; + default: + UNREACHABLE(); + return 0; + } +} + +std::ostream &operator<<(std::ostream &os, ExternalMemoryHandle value) +{ + switch (value) + { + case ExternalMemoryHandle::OpaqueFd: + os << "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR"; + break; + case ExternalMemoryHandle::OpaqueWin32: + os << "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR"; + break; + case ExternalMemoryHandle::OpaqueWin32Kmt: + os << "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR"; + break; + case ExternalMemoryHandle::DmaBuf: + os << "CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR"; + break; + default: + os << "GL_INVALID_ENUM"; + break; + } + return os; +} + template <> FilterMode FromCLenum(CLenum from) { @@ -1184,6 +1278,313 @@ std::ostream &operator<<(std::ostream &os, FilterMode value) return os; } +template <> +ImageChannelOrder FromCLenum(CLenum from) +{ + switch (from) + { + case CL_R: + return ImageChannelOrder::R; + case CL_A: + return ImageChannelOrder::A; + case CL_RG: + return ImageChannelOrder::RG; + case CL_RA: + return ImageChannelOrder::RA; + case CL_RGB: + return ImageChannelOrder::RGB; + case CL_RGBA: + return ImageChannelOrder::RGBA; + case CL_BGRA: + return ImageChannelOrder::BGRA; + case CL_ARGB: + return ImageChannelOrder::ARGB; + case CL_INTENSITY: + return ImageChannelOrder::Intensity; + case CL_LUMINANCE: + return ImageChannelOrder::Luminance; + case CL_Rx: + return ImageChannelOrder::Rx; + case CL_RGx: + return ImageChannelOrder::RGx; + case CL_RGBx: + return ImageChannelOrder::RGBx; + case CL_DEPTH: + return ImageChannelOrder::Depth; + case CL_sRGB: + return ImageChannelOrder::sRGB; + case CL_sRGBx: + return ImageChannelOrder::sRGBx; + case CL_sRGBA: + return ImageChannelOrder::sRGBA; + case CL_sBGRA: + return ImageChannelOrder::sBGRA; + case CL_ABGR: + return ImageChannelOrder::ABGR; + default: + return ImageChannelOrder::InvalidEnum; + } +} + +CLenum ToCLenum(ImageChannelOrder from) +{ + switch (from) + { + case ImageChannelOrder::R: + return CL_R; + case ImageChannelOrder::A: + return CL_A; + case ImageChannelOrder::RG: + return CL_RG; + case ImageChannelOrder::RA: + return CL_RA; + case ImageChannelOrder::RGB: + return CL_RGB; + case ImageChannelOrder::RGBA: + return CL_RGBA; + case ImageChannelOrder::BGRA: + return CL_BGRA; + case ImageChannelOrder::ARGB: + return CL_ARGB; + case ImageChannelOrder::Intensity: + return CL_INTENSITY; + case ImageChannelOrder::Luminance: + return CL_LUMINANCE; + case ImageChannelOrder::Rx: + return CL_Rx; + case ImageChannelOrder::RGx: + return CL_RGx; + case ImageChannelOrder::RGBx: + return CL_RGBx; + case ImageChannelOrder::Depth: + return CL_DEPTH; + case ImageChannelOrder::sRGB: + return CL_sRGB; + case ImageChannelOrder::sRGBx: + return CL_sRGBx; + case ImageChannelOrder::sRGBA: + return CL_sRGBA; + case ImageChannelOrder::sBGRA: + return CL_sBGRA; + case ImageChannelOrder::ABGR: + return CL_ABGR; + default: + UNREACHABLE(); + return 0; + } +} + +std::ostream &operator<<(std::ostream &os, ImageChannelOrder value) +{ + switch (value) + { + case ImageChannelOrder::R: + os << "CL_R"; + break; + case ImageChannelOrder::A: + os << "CL_A"; + break; + case ImageChannelOrder::RG: + os << "CL_RG"; + break; + case ImageChannelOrder::RA: + os << "CL_RA"; + break; + case ImageChannelOrder::RGB: + os << "CL_RGB"; + break; + case ImageChannelOrder::RGBA: + os << "CL_RGBA"; + break; + case ImageChannelOrder::BGRA: + os << "CL_BGRA"; + break; + case ImageChannelOrder::ARGB: + os << "CL_ARGB"; + break; + case ImageChannelOrder::Intensity: + os << "CL_INTENSITY"; + break; + case ImageChannelOrder::Luminance: + os << "CL_LUMINANCE"; + break; + case ImageChannelOrder::Rx: + os << "CL_Rx"; + break; + case ImageChannelOrder::RGx: + os << "CL_RGx"; + break; + case ImageChannelOrder::RGBx: + os << "CL_RGBx"; + break; + case ImageChannelOrder::Depth: + os << "CL_DEPTH"; + break; + case ImageChannelOrder::sRGB: + os << "CL_sRGB"; + break; + case ImageChannelOrder::sRGBx: + os << "CL_sRGBx"; + break; + case ImageChannelOrder::sRGBA: + os << "CL_sRGBA"; + break; + case ImageChannelOrder::sBGRA: + os << "CL_sBGRA"; + break; + case ImageChannelOrder::ABGR: + os << "CL_ABGR"; + break; + default: + os << "GL_INVALID_ENUM"; + break; + } + return os; +} + +template <> +ImageChannelType FromCLenum(CLenum from) +{ + switch (from) + { + case CL_SNORM_INT8: + return ImageChannelType::SnormInt8; + case CL_SNORM_INT16: + return ImageChannelType::SnormInt16; + case CL_UNORM_INT8: + return ImageChannelType::UnormInt8; + case CL_UNORM_INT16: + return ImageChannelType::UnormInt16; + case CL_UNORM_SHORT_565: + return ImageChannelType::UnormShort565; + case CL_UNORM_SHORT_555: + return ImageChannelType::UnormShort555; + case CL_UNORM_INT_101010: + return ImageChannelType::UnormInt101010; + case CL_SIGNED_INT8: + return ImageChannelType::SignedInt8; + case CL_SIGNED_INT16: + return ImageChannelType::SignedInt16; + case CL_SIGNED_INT32: + return ImageChannelType::SignedInt32; + case CL_UNSIGNED_INT8: + return ImageChannelType::UnsignedInt8; + case CL_UNSIGNED_INT16: + return ImageChannelType::UnsignedInt16; + case CL_UNSIGNED_INT32: + return ImageChannelType::UnsignedInt32; + case CL_HALF_FLOAT: + return ImageChannelType::HalfFloat; + case CL_FLOAT: + return ImageChannelType::Float; + case CL_UNORM_INT_101010_2: + return ImageChannelType::UnormInt101010_2; + default: + return ImageChannelType::InvalidEnum; + } +} + +CLenum ToCLenum(ImageChannelType from) +{ + switch (from) + { + case ImageChannelType::SnormInt8: + return CL_SNORM_INT8; + case ImageChannelType::SnormInt16: + return CL_SNORM_INT16; + case ImageChannelType::UnormInt8: + return CL_UNORM_INT8; + case ImageChannelType::UnormInt16: + return CL_UNORM_INT16; + case ImageChannelType::UnormShort565: + return CL_UNORM_SHORT_565; + case ImageChannelType::UnormShort555: + return CL_UNORM_SHORT_555; + case ImageChannelType::UnormInt101010: + return CL_UNORM_INT_101010; + case ImageChannelType::SignedInt8: + return CL_SIGNED_INT8; + case ImageChannelType::SignedInt16: + return CL_SIGNED_INT16; + case ImageChannelType::SignedInt32: + return CL_SIGNED_INT32; + case ImageChannelType::UnsignedInt8: + return CL_UNSIGNED_INT8; + case ImageChannelType::UnsignedInt16: + return CL_UNSIGNED_INT16; + case ImageChannelType::UnsignedInt32: + return CL_UNSIGNED_INT32; + case ImageChannelType::HalfFloat: + return CL_HALF_FLOAT; + case ImageChannelType::Float: + return CL_FLOAT; + case ImageChannelType::UnormInt101010_2: + return CL_UNORM_INT_101010_2; + default: + UNREACHABLE(); + return 0; + } +} + +std::ostream &operator<<(std::ostream &os, ImageChannelType value) +{ + switch (value) + { + case ImageChannelType::SnormInt8: + os << "CL_SNORM_INT8"; + break; + case ImageChannelType::SnormInt16: + os << "CL_SNORM_INT16"; + break; + case ImageChannelType::UnormInt8: + os << "CL_UNORM_INT8"; + break; + case ImageChannelType::UnormInt16: + os << "CL_UNORM_INT16"; + break; + case ImageChannelType::UnormShort565: + os << "CL_UNORM_SHORT_565"; + break; + case ImageChannelType::UnormShort555: + os << "CL_UNORM_SHORT_555"; + break; + case ImageChannelType::UnormInt101010: + os << "CL_UNORM_INT_101010"; + break; + case ImageChannelType::SignedInt8: + os << "CL_SIGNED_INT8"; + break; + case ImageChannelType::SignedInt16: + os << "CL_SIGNED_INT16"; + break; + case ImageChannelType::SignedInt32: + os << "CL_SIGNED_INT32"; + break; + case ImageChannelType::UnsignedInt8: + os << "CL_UNSIGNED_INT8"; + break; + case ImageChannelType::UnsignedInt16: + os << "CL_UNSIGNED_INT16"; + break; + case ImageChannelType::UnsignedInt32: + os << "CL_UNSIGNED_INT32"; + break; + case ImageChannelType::HalfFloat: + os << "CL_HALF_FLOAT"; + break; + case ImageChannelType::Float: + os << "CL_FLOAT"; + break; + case ImageChannelType::UnormInt101010_2: + os << "CL_UNORM_INT_101010_2"; + break; + default: + os << "GL_INVALID_ENUM"; + break; + } + return os; +} + template <> ImageInfo FromCLenum(CLenum from) { @@ -1810,6 +2211,51 @@ std::ostream &operator<<(std::ostream &os, MemObjectType value) return os; } +template <> +MemProperties FromCLenum(CLenum from) +{ + switch (from) + { + case CL_MEM_DEVICE_HANDLE_LIST_KHR: + return MemProperties::ExternalMemoryHandleListStart; + case CL_MEM_DEVICE_HANDLE_LIST_END_KHR: + return MemProperties::ExternalMemoryHandleListEnd; + default: + return MemProperties::InvalidEnum; + } +} + +CLenum ToCLenum(MemProperties from) +{ + switch (from) + { + case MemProperties::ExternalMemoryHandleListStart: + return CL_MEM_DEVICE_HANDLE_LIST_KHR; + case MemProperties::ExternalMemoryHandleListEnd: + return CL_MEM_DEVICE_HANDLE_LIST_END_KHR; + default: + UNREACHABLE(); + return 0; + } +} + +std::ostream &operator<<(std::ostream &os, MemProperties value) +{ + switch (value) + { + case MemProperties::ExternalMemoryHandleListStart: + os << "CL_MEM_DEVICE_HANDLE_LIST_KHR"; + break; + case MemProperties::ExternalMemoryHandleListEnd: + os << "CL_MEM_DEVICE_HANDLE_LIST_END_KHR"; + break; + default: + os << "GL_INVALID_ENUM"; + break; + } + return os; +} + template <> PipeInfo FromCLenum(CLenum from) { @@ -1885,6 +2331,8 @@ PlatformInfo FromCLenum(CLenum from) return PlatformInfo::ExtensionsWithVersion; case CL_PLATFORM_ICD_SUFFIX_KHR: return PlatformInfo::IcdSuffix; + case CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR: + return PlatformInfo::ExternalMemory; default: return PlatformInfo::InvalidEnum; } @@ -1912,6 +2360,8 @@ CLenum ToCLenum(PlatformInfo from) return CL_PLATFORM_EXTENSIONS_WITH_VERSION; case PlatformInfo::IcdSuffix: return CL_PLATFORM_ICD_SUFFIX_KHR; + case PlatformInfo::ExternalMemory: + return CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR; default: UNREACHABLE(); return 0; @@ -1949,6 +2399,9 @@ std::ostream &operator<<(std::ostream &os, PlatformInfo value) case PlatformInfo::IcdSuffix: os << "CL_PLATFORM_ICD_SUFFIX_KHR"; break; + case PlatformInfo::ExternalMemory: + os << "CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR"; + break; default: os << "GL_INVALID_ENUM"; break; diff --git a/src/common/PackedCLEnums_autogen.h b/src/common/PackedCLEnums_autogen.h index a5d1debf4e4..14f6cda770c 100644 --- a/src/common/PackedCLEnums_autogen.h +++ b/src/common/PackedCLEnums_autogen.h @@ -78,118 +78,123 @@ std::ostream &operator<<(std::ostream &os, ContextInfo value); enum class DeviceInfo : uint8_t { - Type = 0, - VendorID = 1, - MaxComputeUnits = 2, - MaxWorkItemDimensions = 3, - MaxWorkGroupSize = 4, - MaxWorkItemSizes = 5, - PreferredVectorWidthChar = 6, - PreferredVectorWidthShort = 7, - PreferredVectorWidthInt = 8, - PreferredVectorWidthLong = 9, - PreferredVectorWidthFloat = 10, - PreferredVectorWidthDouble = 11, - MaxClockFrequency = 12, - AddressBits = 13, - MaxReadImageArgs = 14, - MaxWriteImageArgs = 15, - MaxMemAllocSize = 16, - Image2D_MaxWidth = 17, - Image2D_MaxHeight = 18, - Image3D_MaxWidth = 19, - Image3D_MaxHeight = 20, - Image3D_MaxDepth = 21, - ImageSupport = 22, - MaxParameterSize = 23, - MaxSamplers = 24, - MemBaseAddrAlign = 25, - MinDataTypeAlignSize = 26, - SingleFpConfig = 27, - GlobalMemCacheType = 28, - GlobalMemCachelineSize = 29, - GlobalMemCacheSize = 30, - GlobalMemSize = 31, - MaxConstantBufferSize = 32, - MaxConstantArgs = 33, - LocalMemType = 34, - LocalMemSize = 35, - ErrorCorrectionSupport = 36, - ProfilingTimerResolution = 37, - EndianLittle = 38, - Available = 39, - CompilerAvailable = 40, - ExecutionCapabilities = 41, - QueueOnHostProperties = 42, - Name = 43, - Vendor = 44, - DriverVersion = 45, - Profile = 46, - Version = 47, - Extensions = 48, - Platform = 49, - DoubleFpConfig = 50, - HalfFpConfig = 51, - PreferredVectorWidthHalf = 52, - HostUnifiedMemory = 53, - NativeVectorWidthChar = 54, - NativeVectorWidthShort = 55, - NativeVectorWidthInt = 56, - NativeVectorWidthLong = 57, - NativeVectorWidthFloat = 58, - NativeVectorWidthDouble = 59, - NativeVectorWidthHalf = 60, - OpenCL_C_Version = 61, - LinkerAvailable = 62, - BuiltInKernels = 63, - ImageMaxBufferSize = 64, - ImageMaxArraySize = 65, - ParentDevice = 66, - PartitionMaxSubDevices = 67, - PartitionProperties = 68, - PartitionAffinityDomain = 69, - PartitionType = 70, - ReferenceCount = 71, - PreferredInteropUserSync = 72, - PrintfBufferSize = 73, - ImagePitchAlignment = 74, - ImageBaseAddressAlignment = 75, - MaxReadWriteImageArgs = 76, - MaxGlobalVariableSize = 77, - QueueOnDeviceProperties = 78, - QueueOnDevicePreferredSize = 79, - QueueOnDeviceMaxSize = 80, - MaxOnDeviceQueues = 81, - MaxOnDeviceEvents = 82, - SVM_Capabilities = 83, - GlobalVariablePreferredTotalSize = 84, - MaxPipeArgs = 85, - PipeMaxActiveReservations = 86, - PipeMaxPacketSize = 87, - PreferredPlatformAtomicAlignment = 88, - PreferredGlobalAtomicAlignment = 89, - PreferredLocalAtomicAlignment = 90, - IL_Version = 91, - MaxNumSubGroups = 92, - SubGroupIndependentForwardProgress = 93, - NumericVersion = 94, - ExtensionsWithVersion = 95, - ILsWithVersion = 96, - BuiltInKernelsWithVersion = 97, - AtomicMemoryCapabilities = 98, - AtomicFenceCapabilities = 99, - NonUniformWorkGroupSupport = 100, - OpenCL_C_AllVersions = 101, - PreferredWorkGroupSizeMultiple = 102, - WorkGroupCollectiveFunctionsSupport = 103, - GenericAddressSpaceSupport = 104, - OpenCL_C_Features = 105, - DeviceEnqueueCapabilities = 106, - PipeSupport = 107, - LatestConformanceVersionPassed = 108, - - InvalidEnum = 109, - EnumCount = 109, + Type = 0, + VendorID = 1, + MaxComputeUnits = 2, + MaxWorkItemDimensions = 3, + MaxWorkGroupSize = 4, + MaxWorkItemSizes = 5, + PreferredVectorWidthChar = 6, + PreferredVectorWidthShort = 7, + PreferredVectorWidthInt = 8, + PreferredVectorWidthLong = 9, + PreferredVectorWidthFloat = 10, + PreferredVectorWidthDouble = 11, + MaxClockFrequency = 12, + AddressBits = 13, + MaxReadImageArgs = 14, + MaxWriteImageArgs = 15, + MaxMemAllocSize = 16, + Image2D_MaxWidth = 17, + Image2D_MaxHeight = 18, + Image3D_MaxWidth = 19, + Image3D_MaxHeight = 20, + Image3D_MaxDepth = 21, + ImageSupport = 22, + MaxParameterSize = 23, + MaxSamplers = 24, + MemBaseAddrAlign = 25, + MinDataTypeAlignSize = 26, + SingleFpConfig = 27, + GlobalMemCacheType = 28, + GlobalMemCachelineSize = 29, + GlobalMemCacheSize = 30, + GlobalMemSize = 31, + MaxConstantBufferSize = 32, + MaxConstantArgs = 33, + LocalMemType = 34, + LocalMemSize = 35, + ErrorCorrectionSupport = 36, + ProfilingTimerResolution = 37, + EndianLittle = 38, + Available = 39, + CompilerAvailable = 40, + ExecutionCapabilities = 41, + QueueOnHostProperties = 42, + Name = 43, + Vendor = 44, + DriverVersion = 45, + Profile = 46, + Version = 47, + Extensions = 48, + Platform = 49, + DoubleFpConfig = 50, + HalfFpConfig = 51, + PreferredVectorWidthHalf = 52, + HostUnifiedMemory = 53, + NativeVectorWidthChar = 54, + NativeVectorWidthShort = 55, + NativeVectorWidthInt = 56, + NativeVectorWidthLong = 57, + NativeVectorWidthFloat = 58, + NativeVectorWidthDouble = 59, + NativeVectorWidthHalf = 60, + OpenCL_C_Version = 61, + LinkerAvailable = 62, + BuiltInKernels = 63, + ImageMaxBufferSize = 64, + ImageMaxArraySize = 65, + ParentDevice = 66, + PartitionMaxSubDevices = 67, + PartitionProperties = 68, + PartitionAffinityDomain = 69, + PartitionType = 70, + ReferenceCount = 71, + PreferredInteropUserSync = 72, + PrintfBufferSize = 73, + ImagePitchAlignment = 74, + ImageBaseAddressAlignment = 75, + MaxReadWriteImageArgs = 76, + MaxGlobalVariableSize = 77, + QueueOnDeviceProperties = 78, + QueueOnDevicePreferredSize = 79, + QueueOnDeviceMaxSize = 80, + MaxOnDeviceQueues = 81, + MaxOnDeviceEvents = 82, + SVM_Capabilities = 83, + GlobalVariablePreferredTotalSize = 84, + MaxPipeArgs = 85, + PipeMaxActiveReservations = 86, + PipeMaxPacketSize = 87, + PreferredPlatformAtomicAlignment = 88, + PreferredGlobalAtomicAlignment = 89, + PreferredLocalAtomicAlignment = 90, + IL_Version = 91, + MaxNumSubGroups = 92, + SubGroupIndependentForwardProgress = 93, + NumericVersion = 94, + ExtensionsWithVersion = 95, + ILsWithVersion = 96, + BuiltInKernelsWithVersion = 97, + AtomicMemoryCapabilities = 98, + AtomicFenceCapabilities = 99, + NonUniformWorkGroupSupport = 100, + OpenCL_C_AllVersions = 101, + PreferredWorkGroupSizeMultiple = 102, + WorkGroupCollectiveFunctionsSupport = 103, + GenericAddressSpaceSupport = 104, + OpenCL_C_Features = 105, + DeviceEnqueueCapabilities = 106, + PipeSupport = 107, + LatestConformanceVersionPassed = 108, + IntegerDotProductCapabilities = 109, + IntegerDotProductAccelerationProperties8bit = 110, + IntegerDotProductAccelerationProperties4x8bitPacked = 111, + ExternalMemoryImportHandleTypes = 112, + ExternalMemoryLinearImagesHandleTypes = 113, + + InvalidEnum = 114, + EnumCount = 114, }; template <> @@ -230,6 +235,22 @@ ExecutionStatus FromCLenum(CLenum from); CLenum ToCLenum(ExecutionStatus from); std::ostream &operator<<(std::ostream &os, ExecutionStatus value); +enum class ExternalMemoryHandle : uint8_t +{ + OpaqueFd = 0, + OpaqueWin32 = 1, + OpaqueWin32Kmt = 2, + DmaBuf = 3, + + InvalidEnum = 4, + EnumCount = 4, +}; + +template <> +ExternalMemoryHandle FromCLenum(CLenum from); +CLenum ToCLenum(ExternalMemoryHandle from); +std::ostream &operator<<(std::ostream &os, ExternalMemoryHandle value); + enum class FilterMode : uint8_t { Nearest = 0, @@ -244,6 +265,65 @@ FilterMode FromCLenum(CLenum from); CLenum ToCLenum(FilterMode from); std::ostream &operator<<(std::ostream &os, FilterMode value); +enum class ImageChannelOrder : uint8_t +{ + R = 0, + A = 1, + RG = 2, + RA = 3, + RGB = 4, + RGBA = 5, + BGRA = 6, + ARGB = 7, + Intensity = 8, + Luminance = 9, + Rx = 10, + RGx = 11, + RGBx = 12, + Depth = 13, + sRGB = 14, + sRGBx = 15, + sRGBA = 16, + sBGRA = 17, + ABGR = 18, + + InvalidEnum = 19, + EnumCount = 19, +}; + +template <> +ImageChannelOrder FromCLenum(CLenum from); +CLenum ToCLenum(ImageChannelOrder from); +std::ostream &operator<<(std::ostream &os, ImageChannelOrder value); + +enum class ImageChannelType : uint8_t +{ + SnormInt8 = 0, + SnormInt16 = 1, + UnormInt8 = 2, + UnormInt16 = 3, + UnormShort565 = 4, + UnormShort555 = 5, + UnormInt101010 = 6, + SignedInt8 = 7, + SignedInt16 = 8, + SignedInt32 = 9, + UnsignedInt8 = 10, + UnsignedInt16 = 11, + UnsignedInt32 = 12, + HalfFloat = 13, + Float = 14, + UnormInt101010_2 = 15, + + InvalidEnum = 16, + EnumCount = 16, +}; + +template <> +ImageChannelType FromCLenum(CLenum from); +CLenum ToCLenum(ImageChannelType from); +std::ostream &operator<<(std::ostream &os, ImageChannelType value); + enum class ImageInfo : uint8_t { Format = 0, @@ -394,6 +474,20 @@ MemObjectType FromCLenum(CLenum from); CLenum ToCLenum(MemObjectType from); std::ostream &operator<<(std::ostream &os, MemObjectType value); +enum class MemProperties : uint8_t +{ + ExternalMemoryHandleListStart = 0, + ExternalMemoryHandleListEnd = 1, + + InvalidEnum = 2, + EnumCount = 2, +}; + +template <> +MemProperties FromCLenum(CLenum from); +CLenum ToCLenum(MemProperties from); +std::ostream &operator<<(std::ostream &os, MemProperties value); + enum class PipeInfo : uint8_t { PacketSize = 0, @@ -420,9 +514,10 @@ enum class PlatformInfo : uint8_t NumericVersion = 6, ExtensionsWithVersion = 7, IcdSuffix = 8, + ExternalMemory = 9, - InvalidEnum = 9, - EnumCount = 9, + InvalidEnum = 10, + EnumCount = 10, }; template <> diff --git a/src/common/PackedEGLEnums_autogen.cpp b/src/common/PackedEGLEnums_autogen.cpp index 738254bd185..651f065f9eb 100644 --- a/src/common/PackedEGLEnums_autogen.cpp +++ b/src/common/PackedEGLEnums_autogen.cpp @@ -123,6 +123,8 @@ ContextPriority FromEGLenum(EGLenum from) return ContextPriority::Medium; case EGL_CONTEXT_PRIORITY_HIGH_IMG: return ContextPriority::High; + case EGL_CONTEXT_PRIORITY_REALTIME_NV: + return ContextPriority::Realtime; default: return ContextPriority::InvalidEnum; } @@ -138,6 +140,8 @@ EGLenum ToEGLenum(ContextPriority from) return EGL_CONTEXT_PRIORITY_MEDIUM_IMG; case ContextPriority::High: return EGL_CONTEXT_PRIORITY_HIGH_IMG; + case ContextPriority::Realtime: + return EGL_CONTEXT_PRIORITY_REALTIME_NV; default: UNREACHABLE(); return 0; @@ -157,6 +161,9 @@ std::ostream &operator<<(std::ostream &os, ContextPriority value) case ContextPriority::High: os << "EGL_CONTEXT_PRIORITY_HIGH_IMG"; break; + case ContextPriority::Realtime: + os << "EGL_CONTEXT_PRIORITY_REALTIME_NV"; + break; default: os << "GL_INVALID_ENUM"; break; diff --git a/src/common/PackedEGLEnums_autogen.h b/src/common/PackedEGLEnums_autogen.h index 7794e8509e1..748073f04a0 100644 --- a/src/common/PackedEGLEnums_autogen.h +++ b/src/common/PackedEGLEnums_autogen.h @@ -55,12 +55,13 @@ std::ostream &operator<<(std::ostream &os, CompositorTiming value); enum class ContextPriority : uint8_t { - Low = 0, - Medium = 1, - High = 2, + Low = 0, + Medium = 1, + High = 2, + Realtime = 3, - InvalidEnum = 3, - EnumCount = 3, + InvalidEnum = 4, + EnumCount = 4, }; template <> diff --git a/src/common/PackedEnums.h b/src/common/PackedEnums.h index 8070d101c5b..47e2bf7f675 100644 --- a/src/common/PackedEnums.h +++ b/src/common/PackedEnums.h @@ -9,6 +9,10 @@ #ifndef COMMON_PACKEDGLENUMS_H_ #define COMMON_PACKEDGLENUMS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/PackedEGLEnums_autogen.h" #include "common/PackedGLEnums_autogen.h" diff --git a/src/common/PackedGLEnums_autogen.cpp b/src/common/PackedGLEnums_autogen.cpp index 1e7d31ed40c..812bc4d225c 100644 --- a/src/common/PackedGLEnums_autogen.cpp +++ b/src/common/PackedGLEnums_autogen.cpp @@ -474,6 +474,79 @@ std::ostream &operator<<(std::ostream &os, ClipOrigin value) return os; } +template <> +CombinerOp FromGLenum(GLenum from) +{ + switch (from) + { + case GL_NONE: + return CombinerOp::Undefined; + case GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT: + return CombinerOp::Keep; + case GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT: + return CombinerOp::Replace; + case GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT: + return CombinerOp::Min; + case GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT: + return CombinerOp::Max; + case GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT: + return CombinerOp::Mul; + default: + return CombinerOp::InvalidEnum; + } +} + +GLenum ToGLenum(CombinerOp from) +{ + switch (from) + { + case CombinerOp::Undefined: + return GL_NONE; + case CombinerOp::Keep: + return GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT; + case CombinerOp::Replace: + return GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT; + case CombinerOp::Min: + return GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT; + case CombinerOp::Max: + return GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT; + case CombinerOp::Mul: + return GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT; + default: + UNREACHABLE(); + return 0; + } +} + +std::ostream &operator<<(std::ostream &os, CombinerOp value) +{ + switch (value) + { + case CombinerOp::Undefined: + os << "GL_NONE"; + break; + case CombinerOp::Keep: + os << "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT"; + break; + case CombinerOp::Replace: + os << "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT"; + break; + case CombinerOp::Min: + os << "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT"; + break; + case CombinerOp::Max: + os << "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT"; + break; + case CombinerOp::Mul: + os << "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT"; + break; + default: + os << "GL_INVALID_ENUM"; + break; + } + return os; +} + template <> CullFaceMode FromGLenum(GLenum from) { @@ -1456,8 +1529,6 @@ QueryType FromGLenum(GLenum from) return QueryType::AnySamples; case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: return QueryType::AnySamplesConservative; - case GL_COMMANDS_COMPLETED_CHROMIUM: - return QueryType::CommandsCompleted; case GL_PRIMITIVES_GENERATED_EXT: return QueryType::PrimitivesGenerated; case GL_TIME_ELAPSED_EXT: @@ -1479,8 +1550,6 @@ GLenum ToGLenum(QueryType from) return GL_ANY_SAMPLES_PASSED; case QueryType::AnySamplesConservative: return GL_ANY_SAMPLES_PASSED_CONSERVATIVE; - case QueryType::CommandsCompleted: - return GL_COMMANDS_COMPLETED_CHROMIUM; case QueryType::PrimitivesGenerated: return GL_PRIMITIVES_GENERATED_EXT; case QueryType::TimeElapsed: @@ -1505,9 +1574,6 @@ std::ostream &operator<<(std::ostream &os, QueryType value) case QueryType::AnySamplesConservative: os << "GL_ANY_SAMPLES_PASSED_CONSERVATIVE"; break; - case QueryType::CommandsCompleted: - os << "GL_COMMANDS_COMPLETED_CHROMIUM"; - break; case QueryType::PrimitivesGenerated: os << "GL_PRIMITIVES_GENERATED_EXT"; break; @@ -1652,17 +1718,23 @@ ShadingRate FromGLenum(GLenum from) { case GL_NONE: return ShadingRate::Undefined; - case GL_SHADING_RATE_1X1_PIXELS_QCOM: + case GL_SHADING_RATE_1X1_PIXELS_EXT: return ShadingRate::_1x1; - case GL_SHADING_RATE_1X2_PIXELS_QCOM: + case GL_SHADING_RATE_1X2_PIXELS_EXT: return ShadingRate::_1x2; - case GL_SHADING_RATE_2X1_PIXELS_QCOM: + case GL_SHADING_RATE_1X4_PIXELS_EXT: + return ShadingRate::_1x4; + case GL_SHADING_RATE_2X1_PIXELS_EXT: return ShadingRate::_2x1; - case GL_SHADING_RATE_2X2_PIXELS_QCOM: + case GL_SHADING_RATE_2X2_PIXELS_EXT: return ShadingRate::_2x2; - case GL_SHADING_RATE_4X2_PIXELS_QCOM: + case GL_SHADING_RATE_2X4_PIXELS_EXT: + return ShadingRate::_2x4; + case GL_SHADING_RATE_4X1_PIXELS_EXT: + return ShadingRate::_4x1; + case GL_SHADING_RATE_4X2_PIXELS_EXT: return ShadingRate::_4x2; - case GL_SHADING_RATE_4X4_PIXELS_QCOM: + case GL_SHADING_RATE_4X4_PIXELS_EXT: return ShadingRate::_4x4; default: return ShadingRate::InvalidEnum; @@ -1676,17 +1748,23 @@ GLenum ToGLenum(ShadingRate from) case ShadingRate::Undefined: return GL_NONE; case ShadingRate::_1x1: - return GL_SHADING_RATE_1X1_PIXELS_QCOM; + return GL_SHADING_RATE_1X1_PIXELS_EXT; case ShadingRate::_1x2: - return GL_SHADING_RATE_1X2_PIXELS_QCOM; + return GL_SHADING_RATE_1X2_PIXELS_EXT; + case ShadingRate::_1x4: + return GL_SHADING_RATE_1X4_PIXELS_EXT; case ShadingRate::_2x1: - return GL_SHADING_RATE_2X1_PIXELS_QCOM; + return GL_SHADING_RATE_2X1_PIXELS_EXT; case ShadingRate::_2x2: - return GL_SHADING_RATE_2X2_PIXELS_QCOM; + return GL_SHADING_RATE_2X2_PIXELS_EXT; + case ShadingRate::_2x4: + return GL_SHADING_RATE_2X4_PIXELS_EXT; + case ShadingRate::_4x1: + return GL_SHADING_RATE_4X1_PIXELS_EXT; case ShadingRate::_4x2: - return GL_SHADING_RATE_4X2_PIXELS_QCOM; + return GL_SHADING_RATE_4X2_PIXELS_EXT; case ShadingRate::_4x4: - return GL_SHADING_RATE_4X4_PIXELS_QCOM; + return GL_SHADING_RATE_4X4_PIXELS_EXT; default: UNREACHABLE(); return 0; @@ -1701,22 +1779,31 @@ std::ostream &operator<<(std::ostream &os, ShadingRate value) os << "GL_NONE"; break; case ShadingRate::_1x1: - os << "GL_SHADING_RATE_1X1_PIXELS_QCOM"; + os << "GL_SHADING_RATE_1X1_PIXELS_EXT"; break; case ShadingRate::_1x2: - os << "GL_SHADING_RATE_1X2_PIXELS_QCOM"; + os << "GL_SHADING_RATE_1X2_PIXELS_EXT"; + break; + case ShadingRate::_1x4: + os << "GL_SHADING_RATE_1X4_PIXELS_EXT"; break; case ShadingRate::_2x1: - os << "GL_SHADING_RATE_2X1_PIXELS_QCOM"; + os << "GL_SHADING_RATE_2X1_PIXELS_EXT"; break; case ShadingRate::_2x2: - os << "GL_SHADING_RATE_2X2_PIXELS_QCOM"; + os << "GL_SHADING_RATE_2X2_PIXELS_EXT"; + break; + case ShadingRate::_2x4: + os << "GL_SHADING_RATE_2X4_PIXELS_EXT"; + break; + case ShadingRate::_4x1: + os << "GL_SHADING_RATE_4X1_PIXELS_EXT"; break; case ShadingRate::_4x2: - os << "GL_SHADING_RATE_4X2_PIXELS_QCOM"; + os << "GL_SHADING_RATE_4X2_PIXELS_EXT"; break; case ShadingRate::_4x4: - os << "GL_SHADING_RATE_4X4_PIXELS_QCOM"; + os << "GL_SHADING_RATE_4X4_PIXELS_EXT"; break; default: os << "GL_INVALID_ENUM"; diff --git a/src/common/PackedGLEnums_autogen.h b/src/common/PackedGLEnums_autogen.h index 895760fb7fd..725618a9f69 100644 --- a/src/common/PackedGLEnums_autogen.h +++ b/src/common/PackedGLEnums_autogen.h @@ -134,6 +134,24 @@ ClipOrigin FromGLenum(GLenum from); GLenum ToGLenum(ClipOrigin from); std::ostream &operator<<(std::ostream &os, ClipOrigin value); +enum class CombinerOp : uint8_t +{ + Undefined = 0, + Keep = 1, + Replace = 2, + Min = 3, + Max = 4, + Mul = 5, + + InvalidEnum = 6, + EnumCount = 6, +}; + +template <> +CombinerOp FromGLenum(GLenum from); +GLenum ToGLenum(CombinerOp from); +std::ostream &operator<<(std::ostream &os, CombinerOp value); + enum class CullFaceMode : uint8_t { Back = 0, @@ -383,14 +401,13 @@ enum class QueryType : uint8_t { AnySamples = 0, AnySamplesConservative = 1, - CommandsCompleted = 2, - PrimitivesGenerated = 3, - TimeElapsed = 4, - Timestamp = 5, - TransformFeedbackPrimitivesWritten = 6, + PrimitivesGenerated = 2, + TimeElapsed = 3, + Timestamp = 4, + TransformFeedbackPrimitivesWritten = 5, - InvalidEnum = 7, - EnumCount = 7, + InvalidEnum = 6, + EnumCount = 6, }; template <> @@ -435,13 +452,16 @@ enum class ShadingRate : uint8_t Undefined = 0, _1x1 = 1, _1x2 = 2, - _2x1 = 3, - _2x2 = 4, - _4x2 = 5, - _4x4 = 6, + _1x4 = 3, + _2x1 = 4, + _2x2 = 5, + _2x4 = 6, + _4x1 = 7, + _4x2 = 8, + _4x4 = 9, - InvalidEnum = 7, - EnumCount = 7, + InvalidEnum = 10, + EnumCount = 10, }; template <> diff --git a/src/common/PoolAlloc.cpp b/src/common/PoolAlloc.cpp index 37567b67a24..a512771e918 100644 --- a/src/common/PoolAlloc.cpp +++ b/src/common/PoolAlloc.cpp @@ -7,14 +7,19 @@ // Implements the class methods for PoolAllocator and Allocation classes. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/PoolAlloc.h" #include #include #include +#include + +#include -#include "common/angleutils.h" -#include "common/debug.h" #include "common/mathutil.h" #include "common/platform.h" #include "common/tls.h" @@ -131,26 +136,13 @@ class PageHeader PageHeader(PageHeader *nextPage, size_t pageCount) : nextPage(nextPage), pageCount(pageCount) -# if defined(ANGLE_POOL_ALLOC_GUARD_BLOCKS) - , - lastAllocation(nullptr) -# endif - {} - - ~PageHeader() { -# if defined(ANGLE_POOL_ALLOC_GUARD_BLOCKS) - if (lastAllocation) - { - lastAllocation->checkAllocList(); - } -# endif } PageHeader *nextPage; size_t pageCount; # if defined(ANGLE_POOL_ALLOC_GUARD_BLOCKS) - Allocation *lastAllocation; + Allocation *lastAllocation = nullptr; # endif }; #endif @@ -170,14 +162,7 @@ PoolAllocator::PoolAllocator(int growthIncrement, int allocationAlignment) #endif mLocked(false) { - initialize(growthIncrement, allocationAlignment); -} - -void PoolAllocator::initialize(int pageSize, int alignment) -{ - mAlignment = alignment; #if !defined(ANGLE_DISABLE_POOL_ALLOC) - mPageSize = pageSize; mPageHeaderSkip = sizeof(PageHeader); // Alignment == 1 is a special fast-path where fastAllocate() is enabled @@ -209,41 +194,19 @@ void PoolAllocator::initialize(int pageSize, int alignment) // be obtained to allocate memory. // mCurrentPageOffset = mPageSize; - -#else // !defined(ANGLE_DISABLE_POOL_ALLOC) - mStack.push_back({}); #endif } PoolAllocator::~PoolAllocator() { + reset(); #if !defined(ANGLE_DISABLE_POOL_ALLOC) - while (mInUseList) - { - PageHeader *next = mInUseList->nextPage; - mInUseList->~PageHeader(); - delete[] reinterpret_cast(mInUseList); - mInUseList = next; - } - // We should not check the guard blocks - // here, because we did it already when the block was - // placed into the free list. - // while (mFreeList) { PageHeader *next = mFreeList->nextPage; delete[] reinterpret_cast(mFreeList); mFreeList = next; } -#else // !defined(ANGLE_DISABLE_POOL_ALLOC) - for (auto &allocs : mStack) - { - for (auto alloc : allocs) - { - free(alloc); - } - } - mStack.clear(); #endif } @@ -269,84 +232,48 @@ void Allocation::checkGuardBlock(unsigned char *blockMem, #endif } -void PoolAllocator::push() +void PoolAllocator::reset() { #if !defined(ANGLE_DISABLE_POOL_ALLOC) - AllocState state = {mCurrentPageOffset, mInUseList}; - - mStack.push_back(state); + mNumCalls = 0; + mTotalBytes = 0; - // - // Indicate there is no current page to allocate from. - // mCurrentPageOffset = mPageSize; -#else // !defined(ANGLE_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif -} - -// Do a mass-deallocation of all the individual allocations that have occurred since the last -// push(), or since the last pop(), or since the object's creation. -// -// Single-page allocations are saved for future use unless the release strategy is All. -void PoolAllocator::pop(ReleaseStrategy releaseStrategy) -{ - if (mStack.size() < 1) + PageHeader *page = std::exchange(mInUseList, nullptr); + while (page) { - return; - } - -#if !defined(ANGLE_DISABLE_POOL_ALLOC) - PageHeader *page = mStack.back().page; - mCurrentPageOffset = mStack.back().offset; + const size_t pageCount = page->pageCount; + PageHeader *nextInUse = page->nextPage; - while (mInUseList != page) - { - // Grab the pageCount before calling the destructor. While the destructor doesn't actually - // touch this variable, it's confusing MSAN. - const size_t pageCount = mInUseList->pageCount; - PageHeader *nextInUse = mInUseList->nextPage; - - // invoke destructor to free allocation list - mInUseList->~PageHeader(); +# if defined(ANGLE_POOL_ALLOC_GUARD_BLOCKS) + if (page->lastAllocation) + { + Allocation *allocations = std::exchange(page->lastAllocation, nullptr); + allocations->checkAllocList(); + } +# endif - if (pageCount > 1 || releaseStrategy == ReleaseStrategy::All) + if (pageCount > 1) { - delete[] reinterpret_cast(mInUseList); + delete[] reinterpret_cast(page); } else { # if defined(ANGLE_WITH_ASAN) // Clear any container annotations left over from when the memory // was last used. (crbug.com/1419798) - __asan_unpoison_memory_region(mInUseList, mPageSize); + __asan_unpoison_memory_region(page, mPageSize); # endif - mInUseList->nextPage = mFreeList; - mFreeList = mInUseList; + page->nextPage = mFreeList; + mFreeList = page; } - mInUseList = nextInUse; + page = nextInUse; } - - mStack.pop_back(); #else // !defined(ANGLE_DISABLE_POOL_ALLOC) - for (auto &alloc : mStack.back()) - { - free(alloc); - } - mStack.pop_back(); + mStack.clear(); #endif } -// -// Do a mass-deallocation of all the individual allocations -// that have occurred. -// -void PoolAllocator::popAll() -{ - while (mStack.size() > 0) - pop(); -} - void *PoolAllocator::allocate(size_t numBytes) { ASSERT(!mLocked); @@ -392,21 +319,19 @@ void *PoolAllocator::allocate(size_t numBytes) // Integer overflow is unexpected. ASSERT(numBytesToAlloc >= allocationSize); - PageHeader *memory = reinterpret_cast(::new char[numBytesToAlloc]); + uint8_t *memory = new (std::nothrow) uint8_t[numBytesToAlloc]; if (memory == nullptr) { return nullptr; } - - // Use placement-new to initialize header - new (memory) PageHeader(mInUseList, (numBytesToAlloc + mPageSize - 1) / mPageSize); - mInUseList = memory; + mInUseList = + new (memory) PageHeader(mInUseList, (numBytesToAlloc + mPageSize - 1) / mPageSize); // Make next allocation come from a new page mCurrentPageOffset = mPageSize; // Now that we actually have the pointer, make sure the data pointer will be aligned. - currentPagePtr = reinterpret_cast(memory) + mPageHeaderSkip; + currentPagePtr = reinterpret_cast(mInUseList) + mPageHeaderSkip; Allocation::AllocationSize(currentPagePtr, numBytes, mAlignment, &preAllocationPadding); return initializeAllocation(currentPagePtr + preAllocationPadding, numBytes); @@ -417,8 +342,8 @@ void *PoolAllocator::allocate(size_t numBytes) #else // !defined(ANGLE_DISABLE_POOL_ALLOC) - void *alloc = malloc(numBytes + mAlignment - 1); - mStack.back().push_back(alloc); + uint8_t *alloc = new (std::nothrow) uint8_t[numBytes + mAlignment - 1]; + mStack.emplace_back(std::unique_ptr(alloc)); intptr_t intAlloc = reinterpret_cast(alloc); intAlloc = rx::roundUpPow2(intAlloc, mAlignment); @@ -431,23 +356,22 @@ uint8_t *PoolAllocator::allocateNewPage(size_t numBytes) { // Need a simple page to allocate from. Pick a page from the free list, if any. Otherwise need // to make the allocation. - PageHeader *memory; if (mFreeList) { - memory = mFreeList; + PageHeader *page = mFreeList; mFreeList = mFreeList->nextPage; + page->nextPage = mInUseList; + mInUseList = page; } else { - memory = reinterpret_cast(::new char[mPageSize]); + uint8_t *memory = new (std::nothrow) uint8_t[mPageSize]; if (memory == nullptr) { return nullptr; } + mInUseList = new (memory) PageHeader(mInUseList, 1); } - // Use placement-new to initialize header - new (memory) PageHeader(mInUseList, 1); - mInUseList = memory; // Leave room for the page header. mCurrentPageOffset = mPageHeaderSkip; @@ -466,8 +390,8 @@ uint8_t *PoolAllocator::allocateNewPage(size_t numBytes) void *PoolAllocator::initializeAllocation(uint8_t *memory, size_t numBytes) { # if defined(ANGLE_POOL_ALLOC_GUARD_BLOCKS) - new (memory) Allocation(numBytes, memory, mInUseList->lastAllocation); - mInUseList->lastAllocation = reinterpret_cast(memory); + mInUseList->lastAllocation = + new (memory) Allocation(numBytes, memory, mInUseList->lastAllocation); # endif return Allocation::GetDataPointer(memory, mAlignment); diff --git a/src/common/PoolAlloc.h b/src/common/PoolAlloc.h index df8e2acb61c..dab10d9c23f 100644 --- a/src/common/PoolAlloc.h +++ b/src/common/PoolAlloc.h @@ -10,6 +10,10 @@ #ifndef COMMON_POOLALLOC_H_ #define COMMON_POOLALLOC_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #if !defined(NDEBUG) # define ANGLE_POOL_ALLOC_GUARD_BLOCKS // define to enable guard block checking #endif @@ -31,24 +35,22 @@ // new and delete methods. // -#include "angleutils.h" -#include "common/debug.h" +#include + +#include "common/angleutils.h" +#include "common/log_utils.h" + +#if defined(ANGLE_DISABLE_POOL_ALLOC) +# include +# include +#endif namespace angle { -class Allocation; class PageHeader; -// -// There are several stacks. One is to track the pushing and popping -// of the user, and not yet implemented. The others are simply a -// repositories of free pages or used pages. -// -// Page stacks are linked together with a simple header at the beginning -// of each allocation obtained from the underlying OS. Multi-page allocations -// are returned to the OS. Individual page allocations are kept for future -// re-use. -// +// Pages are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. // The "page size" used is not, nor must it match, the underlying OS // page size. But, having it be about that size or equal to a set of // pages is likely most optimal. @@ -56,11 +58,6 @@ class PageHeader; class PoolAllocator : angle::NonCopyable { public: - enum class ReleaseStrategy : uint8_t - { - OnlyMultiPage, - All, - }; static const int kDefaultAlignment = sizeof(void *); // @@ -68,35 +65,11 @@ class PoolAllocator : angle::NonCopyable // function can be used to make allocations with less overhead. // PoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = kDefaultAlignment); - - // - // Don't call the destructor just to free up the memory, call pop() - // ~PoolAllocator(); - // - // Initialize page size and alignment after construction - // - void initialize(int pageSize, int alignment); - - // - // Call push() to establish a new place to pop memory to. Does not - // have to be called to get things started. - // - void push(); - - // - // Call pop() to free all memory allocated since the last call to push(), - // or if no last call to push, frees all memory since first allocation. - // - void pop(ReleaseStrategy releaseStrategy = ReleaseStrategy::OnlyMultiPage); + // Marks all allocated memory as unused. The memory will be reused. + void reset(); - // - // Call popAll() to free all memory allocated. - // - void popAll(); - - // // Call allocate() to actually acquire memory. Returns 0 if no memory // available, otherwise a properly aligned pointer to 'numBytes' of memory. // @@ -130,8 +103,8 @@ class PoolAllocator : angle::NonCopyable } // There is no deallocate. The point of this class is that deallocation can be skipped by the - // user of it, as the model of use is to simultaneously deallocate everything at once by calling - // pop(), and to not have to solve memory leak problems. + // user of it, as the model of use is to simultaneously deallocate everything at once by + // destroying the instance or reset(). // Catch unwanted allocations. // TODO(jmadill): Remove this when we remove the global allocator. @@ -142,13 +115,6 @@ class PoolAllocator : angle::NonCopyable size_t mAlignment; // all returned allocations will be aligned at // this granularity, which will be a power of 2 #if !defined(ANGLE_DISABLE_POOL_ALLOC) - struct AllocState - { - size_t offset; - PageHeader *page; - }; - using AllocStack = std::vector; - // Slow path of allocation when we have to get a new page. uint8_t *allocateNewPage(size_t numBytes); // Track allocations if and only if we're using guard blocks @@ -164,19 +130,17 @@ class PoolAllocator : angle::NonCopyable // any) will align to pointer size by extension (since mAlignment is made aligned to at least // pointer size). size_t mCurrentPageOffset; - // List of popped memory + // List of unused memory. PageHeader *mFreeList; // List of all memory currently being used. The head of this list is where allocations are // currently being made from. PageHeader *mInUseList; - // Stack of where to allocate from, to partition pool - AllocStack mStack; int mNumCalls; // just an interesting statistic size_t mTotalBytes; // just an interesting statistic #else // !defined(ANGLE_DISABLE_POOL_ALLOC) - std::vector> mStack; + std::vector> mStack; #endif bool mLocked; diff --git a/src/common/PoolAlloc_unittest.cpp b/src/common/PoolAlloc_unittest.cpp index 6396f093133..118adbaa010 100644 --- a/src/common/PoolAlloc_unittest.cpp +++ b/src/common/PoolAlloc_unittest.cpp @@ -7,6 +7,10 @@ // Tests of the PoolAlloc class // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/PoolAlloc.h" @@ -26,14 +30,15 @@ TEST(PoolAllocatorTest, Interface) // Write to allocation to check later uint32_t *writePtr = static_cast(allocation); *writePtr = kTestValue; - // Test push and creating a new allocation - poolAllocator.push(); - allocation = poolAllocator.allocate(numBytes); - EXPECT_NE(nullptr, allocation); - // Make an allocation that spans multiple pages - allocation = poolAllocator.allocate(10 * 1024); - // pop previous two allocations - poolAllocator.pop(); + // Test other allocator creating a new allocation + { + PoolAllocator poolAllocator2; + allocation = poolAllocator2.allocate(numBytes); + EXPECT_NE(nullptr, allocation); + // Make an allocation that spans multiple pages + allocation = poolAllocator2.allocate(10 * 1024); + // Free previous two allocations. + } // Verify first allocation still has data EXPECT_EQ(kTestValue, *writePtr); // Make a bunch of allocations @@ -46,8 +51,6 @@ TEST(PoolAllocatorTest, Interface) // overwrite any other allocation we get error. memset(allocation, 0xb8, numBytes); } - // Free everything - poolAllocator.popAll(); } #if !defined(ANGLE_POOL_ALLOC_GUARD_BLOCKS) diff --git a/src/common/RingBufferAllocator.cpp b/src/common/RingBufferAllocator.cpp deleted file mode 100644 index 1d05626b6f0..00000000000 --- a/src/common/RingBufferAllocator.cpp +++ /dev/null @@ -1,311 +0,0 @@ -// -// Copyright 2022 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. -// -// RingBufferAllocator.cpp: -// Implements classes used for ring buffer allocators. -// - -#include "common/RingBufferAllocator.h" - -namespace angle -{ - -// RingBufferAllocator implementation. -RingBufferAllocator::RingBufferAllocator(RingBufferAllocator &&other) -{ - *this = std::move(other); -} - -RingBufferAllocator &RingBufferAllocator::operator=(RingBufferAllocator &&other) -{ - mOldBuffers = std::move(other.mOldBuffers); - mBuffer = std::move(other.mBuffer); - mDataBegin = other.mDataBegin; - mDataEnd = other.mDataEnd; - mFragmentEnd = other.mFragmentEnd; - mFragmentEndR = other.mFragmentEndR; - mFragmentReserve = other.mFragmentReserve; - - mMinCapacity = other.mMinCapacity; - mCurrentCapacity = other.mCurrentCapacity; - mAllocationMargin = other.mAllocationMargin; - mDecaySpeedFactor = other.mDecaySpeedFactor; - - ASSERT(other.mOldBuffers.size() == 0); - ASSERT(other.mBuffer.isEmpty()); - other.mBuffer.resetId(); - other.mDataBegin = nullptr; - other.mDataEnd = nullptr; - other.mFragmentEnd = nullptr; - other.mFragmentEndR = nullptr; - other.mFragmentReserve = 0; - - other.mMinCapacity = 0; - other.mCurrentCapacity = 0; - other.mAllocationMargin = 0; - other.mDecaySpeedFactor = 0; - - return *this; -} - -void RingBufferAllocator::reset() -{ - mListener = nullptr; - mFragmentReserve = 0; - mDecaySpeedFactor = kDefaultDecaySpeedFactor; - mMinCapacity = kMinRingBufferAllocationCapacity; - resize(mMinCapacity); - mOldBuffers.clear(); -} - -void RingBufferAllocator::setListener(RingBufferAllocateListener *listener) -{ - ASSERT(!mListener || !listener); - mListener = listener; -} - -void RingBufferAllocator::setDecaySpeedFactor(uint32_t decaySpeedFactor) -{ - ASSERT(valid()); - mDecaySpeedFactor = std::max(decaySpeedFactor, 1u); -} - -RingBufferAllocatorCheckPoint RingBufferAllocator::getReleaseCheckPoint() const -{ - ASSERT(valid()); - RingBufferAllocatorCheckPoint result; - result.mBufferId = mBuffer.getId(); - result.mReleasePtr = mDataEnd; - return result; -} - -void RingBufferAllocator::release(const RingBufferAllocatorCheckPoint &checkPoint) -{ - ASSERT(valid()); - ASSERT(checkPoint.valid()); - - if (mOldBuffers.size() > 0) - { - // mOldBuffers are sorted by id - int removeCount = 0; - for (uint32_t i = 0; - (i < mOldBuffers.size()) && (mOldBuffers[i].getId() < checkPoint.mBufferId); ++i) - { - ++removeCount; - } - mOldBuffers.erase(mOldBuffers.begin(), mOldBuffers.begin() + removeCount); - } - - if (checkPoint.mBufferId == mBuffer.getId()) - { - const uint32_t allocatedBefore = getNumAllocatedInBuffer(); - - release(checkPoint.mReleasePtr); - - if (allocatedBefore >= mAllocationMargin) - { - if ((mCurrentCapacity > mMinCapacity) && (allocatedBefore * 6 <= mCurrentCapacity)) - { - resize(std::max(allocatedBefore * 3, mMinCapacity)); - } - else - { - mAllocationMargin = mCurrentCapacity; - } - } - else - { - const uint64_t numReleased = (allocatedBefore - getNumAllocatedInBuffer()); - const uint64_t distanceToMargin = (mAllocationMargin - allocatedBefore); - mAllocationMargin -= - std::max(static_cast(numReleased * distanceToMargin / mAllocationMargin / - mDecaySpeedFactor), - 1u); - } - } -} - -void RingBufferAllocator::setFragmentReserve(uint32_t reserve) -{ - ASSERT(valid()); - mFragmentReserve = reserve; - mFragmentEndR = mBuffer.decClamped(mFragmentEnd, mFragmentReserve); -} - -uint8_t *RingBufferAllocator::allocateInNewFragment(uint32_t size) -{ - if (mListener) - { - mListener->onRingBufferFragmentEnd(); - } - - uint8_t *newFragmentBegin = nullptr; - if (mFragmentEnd != mDataBegin) - { - newFragmentBegin = mBuffer.data(); - uint8_t *const newFragmentEnd = mDataBegin; - uint8_t *const newFragmentEndR = mBuffer.decClamped(newFragmentEnd, mFragmentReserve); - - // It should wrap around only if it can allocate. - if (newFragmentEndR - newFragmentBegin >= static_cast(size)) - { - mDataEnd = newFragmentBegin; - mFragmentEnd = newFragmentEnd; - mFragmentEndR = newFragmentEndR; - - if (mListener) - { - mListener->onRingBufferNewFragment(); - } - - mDataEnd = newFragmentBegin + size; - return newFragmentBegin; - } - } - - resize(std::max(mCurrentCapacity + mCurrentCapacity / 2, size + mFragmentReserve)); - - if (mListener) - { - mListener->onRingBufferNewFragment(); - } - - ASSERT(mFragmentEndR - mDataEnd >= static_cast(size)); - newFragmentBegin = mDataEnd; - mDataEnd = newFragmentBegin + size; - return newFragmentBegin; -} - -void RingBufferAllocator::resize(uint32_t newCapacity) -{ - ASSERT(newCapacity >= mMinCapacity); - - if (mBuffer.getId() != 0) - { - mOldBuffers.emplace_back(std::move(mBuffer)); - } - - mCurrentCapacity = newCapacity; - mBuffer.incrementId(); - mBuffer.resize(mCurrentCapacity); - resetPointers(); - - mAllocationMargin = mCurrentCapacity; -} - -void RingBufferAllocator::release(uint8_t *releasePtr) -{ - if (releasePtr == mDataEnd) - { - // Ensures "mDataEnd == mBuffer.data()" with 0 allocations. - resetPointers(); - return; - } - - if (mDataBegin == mFragmentEnd) - { - ASSERT((releasePtr >= mBuffer.data() && releasePtr < mDataEnd) || - (releasePtr >= mDataBegin && releasePtr <= mBuffer.data() + mCurrentCapacity)); - if (releasePtr < mDataBegin) - { - mFragmentEnd = mBuffer.data() + mCurrentCapacity; - } - else - { - mFragmentEnd = releasePtr; - } - mFragmentEndR = mBuffer.decClamped(mFragmentEnd, mFragmentReserve); - } - else - { - ASSERT(releasePtr >= mDataBegin && releasePtr < mDataEnd); - } - mDataBegin = releasePtr; -} - -uint32_t RingBufferAllocator::getNumAllocatedInBuffer() const -{ - // 2 free fragments: [mBuffer.begin, mDataBegin) [mDataEnd, mBuffer.end); - // 1 used fragment: [DataBegin, DataEnd) - if (mFragmentEnd != mDataBegin) - { - ASSERT(mDataEnd >= mDataBegin); - return static_cast(mDataEnd - mDataBegin); - } - - // 1 free fragment: [mDataEnd, mDataBegin) - // 2 used fragments: [mBuffer.begin, mDataEnd) [mDataBegin, mBuffer.end) - ASSERT(mDataBegin >= mDataEnd); - return (mCurrentCapacity - static_cast(mDataBegin - mDataEnd)); -} - -void RingBufferAllocator::resetPointers() -{ - mDataBegin = mBuffer.data(); - mDataEnd = mDataBegin; - mFragmentEnd = mDataEnd + mCurrentCapacity; - mFragmentEndR = mBuffer.decClamped(mFragmentEnd, mFragmentReserve); -} - -// SharedRingBufferAllocator implementation. -SharedRingBufferAllocator::SharedRingBufferAllocator() -{ - mAllocator.reset(); -} - -SharedRingBufferAllocator::~SharedRingBufferAllocator() -{ -#if defined(ANGLE_ENABLE_ASSERTS) - ASSERT(!mSharedCP || mSharedCP->mRefCount == 1); -#endif - SafeDelete(mSharedCP); -} - -SharedRingBufferAllocatorCheckPoint *SharedRingBufferAllocator::acquireSharedCP() -{ - if (!mSharedCP) - { - mSharedCP = new SharedRingBufferAllocatorCheckPoint(); - } -#if defined(ANGLE_ENABLE_ASSERTS) - ASSERT(++mSharedCP->mRefCount > 1); - // Must always be 1 ref before -#endif - return mSharedCP; -} - -void SharedRingBufferAllocator::releaseToSharedCP() -{ - ASSERT(mSharedCP); - const RingBufferAllocatorCheckPoint releaseCP = mSharedCP->pop(); - if (releaseCP.valid()) - { - mAllocator.release(releaseCP); - } -} - -void SharedRingBufferAllocatorCheckPoint::releaseAndUpdate(RingBufferAllocatorCheckPoint *newValue) -{ - ASSERT(newValue && newValue->valid()); -#if defined(ANGLE_ENABLE_ASSERTS) - ASSERT(--mRefCount >= 1); - // Must always remain 1 ref -#endif - { - std::lock_guard lock(mMutex); - mValue = *newValue; - } - newValue->reset(); -} - -RingBufferAllocatorCheckPoint SharedRingBufferAllocatorCheckPoint::pop() -{ - std::lock_guard lock(mMutex); - RingBufferAllocatorCheckPoint value = mValue; - mValue.reset(); - return value; -} - -} // namespace angle diff --git a/src/common/RingBufferAllocator.h b/src/common/RingBufferAllocator.h deleted file mode 100644 index c717a1a9a1d..00000000000 --- a/src/common/RingBufferAllocator.h +++ /dev/null @@ -1,176 +0,0 @@ -// -// Copyright 2022 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. -// -// RingBufferAllocator.h: -// Classes used to implement ring buffer allocators. -// - -#ifndef COMMON_RING_BUFFER_ALLOCATOR_H_ -#define COMMON_RING_BUFFER_ALLOCATOR_H_ - -#include "angleutils.h" -#include "common/SimpleMutex.h" -#include "common/debug.h" - -#include - -namespace angle -{ - -static constexpr uint32_t kMinRingBufferAllocationCapacity = 1024; -static constexpr uint32_t kDefaultDecaySpeedFactor = 10; - -// Only called from RingBufferAllocator::allocate(). Other function may also change the fragment. -class RingBufferAllocateListener -{ - public: - virtual void onRingBufferNewFragment() = 0; - virtual void onRingBufferFragmentEnd() = 0; - - protected: - ~RingBufferAllocateListener() = default; -}; - -class RingBufferAllocatorCheckPoint final -{ - public: - void reset() { *this = {}; } - bool valid() const { return (mReleasePtr != nullptr); } - - private: - friend class RingBufferAllocator; - uint64_t mBufferId = 0; - uint8_t *mReleasePtr = nullptr; -}; - -class RingBufferAllocatorBuffer final -{ - public: - static constexpr uint32_t kBaseOffset = alignof(std::max_align_t); - - void resize(uint32_t size) { mStorage.resize(size + kBaseOffset); } - uint8_t *data() { return mStorage.data() + kBaseOffset; } - - uint8_t *decClamped(uint8_t *ptr, uint32_t offset) const - { - ASSERT(ptr >= mStorage.data() + kBaseOffset && ptr <= mStorage.data() + mStorage.size()); - return ptr - std::min(offset, static_cast(ptr - mStorage.data())); - } - - uint64_t getId() const { return mId; } - void resetId() { mId = 0; } - void incrementId() { ++mId; } - - bool isEmpty() const { return mStorage.empty(); } - - private: - uint64_t mId = 0; - std::vector mStorage; -}; - -class RingBufferAllocator final : angle::NonCopyable -{ - public: - RingBufferAllocator() = default; - RingBufferAllocator(RingBufferAllocator &&other); - RingBufferAllocator &operator=(RingBufferAllocator &&other); - - void reset(); - bool valid() const { return (getPointer() != nullptr); } - - void setListener(RingBufferAllocateListener *listener); - - void setDecaySpeedFactor(uint32_t decaySpeedFactor); - - void setFragmentReserve(uint32_t reserve); - - uint8_t *allocate(uint32_t size) - { - ASSERT(valid()); - if (ANGLE_LIKELY(mFragmentEndR - mDataEnd >= static_cast(size))) - { - uint8_t *const result = mDataEnd; - mDataEnd = result + size; - return result; - } - return allocateInNewFragment(size); - } - - uint8_t *getPointer() const { return mDataEnd; } - uint32_t getFragmentSize() const - { - ASSERT(mFragmentEnd >= mDataEnd); - return static_cast(mFragmentEnd - mDataEnd); - } - - RingBufferAllocatorCheckPoint getReleaseCheckPoint() const; - void release(const RingBufferAllocatorCheckPoint &checkPoint); - - private: - void release(uint8_t *releasePtr); - uint32_t getNumAllocatedInBuffer() const; - void resetPointers(); - - uint8_t *allocateInNewFragment(uint32_t size); - void resize(uint32_t newCapacity); - - RingBufferAllocateListener *mListener = nullptr; - - std::vector mOldBuffers; - RingBufferAllocatorBuffer mBuffer; - uint8_t *mDataBegin = nullptr; - uint8_t *mDataEnd = nullptr; - uint8_t *mFragmentEnd = nullptr; - uint8_t *mFragmentEndR = nullptr; - uint32_t mFragmentReserve = 0; - - uint32_t mMinCapacity = 0; - uint32_t mCurrentCapacity = 0; - uint32_t mAllocationMargin = 0; - - // 1 - fastest decay speed. - // 2 - 2x slower than fastest, and so on. - uint32_t mDecaySpeedFactor = 0; -}; - -class SharedRingBufferAllocatorCheckPoint final : angle::NonCopyable -{ - public: - void releaseAndUpdate(RingBufferAllocatorCheckPoint *newValue); - - private: - friend class SharedRingBufferAllocator; - RingBufferAllocatorCheckPoint pop(); - angle::SimpleMutex mMutex; - RingBufferAllocatorCheckPoint mValue; - -#if defined(ANGLE_ENABLE_ASSERTS) - std::atomic mRefCount{1}; -#endif -}; - -class SharedRingBufferAllocator final : angle::NonCopyable -{ - public: - SharedRingBufferAllocator(); - ~SharedRingBufferAllocator(); - - RingBufferAllocator &get() { return mAllocator; } - - // Once shared - always shared - bool isShared() const { return mSharedCP != nullptr; } - - // Once acquired must be released with releaseAndUpdate(). - SharedRingBufferAllocatorCheckPoint *acquireSharedCP(); - void releaseToSharedCP(); - - private: - RingBufferAllocator mAllocator; - SharedRingBufferAllocatorCheckPoint *mSharedCP = nullptr; -}; - -} // namespace angle - -#endif // COMMON_RING_BUFFER_ALLOCATOR_H_ diff --git a/src/common/WorkerThread.cpp b/src/common/WorkerThread.cpp index c613ed41279..1ff4766eed9 100644 --- a/src/common/WorkerThread.cpp +++ b/src/common/WorkerThread.cpp @@ -45,10 +45,17 @@ void AsyncWaitableEvent::markAsReady() mCondition.notify_all(); } +void AsyncWaitableEvent::markAsAborted() +{ + std::lock_guard lock(mMutex); + mAborted = true; + mCondition.notify_all(); +} + void AsyncWaitableEvent::wait() { std::unique_lock lock(mMutex); - mCondition.wait(lock, [this] { return mIsReady; }); + mCondition.wait(lock, [this] { return mIsReady || mAborted; }); } bool AsyncWaitableEvent::isReady() @@ -95,6 +102,8 @@ class AsyncWorkerPool final : public WorkerThreadPool bool isAsync() override; + size_t getEnqueuedTaskCount() override; + private: void createThreads(); @@ -115,13 +124,19 @@ class AsyncWorkerPool final : public WorkerThreadPool AsyncWorkerPool::AsyncWorkerPool(size_t numThreads) : mDesiredThreadCount(numThreads) { - ASSERT(numThreads != 0); + ASSERT(mDesiredThreadCount != 0); } AsyncWorkerPool::~AsyncWorkerPool() { { std::unique_lock lock(mMutex); + // Mark each task's AsyncWaitableEvent as aborted and drain the task queue + for (; !mTaskQueue.empty(); mTaskQueue.pop()) + { + auto task = mTaskQueue.front(); + task.first->markAsAborted(); + } mTerminated = true; } mCondVar.notify_all(); @@ -153,6 +168,7 @@ std::shared_ptr AsyncWorkerPool::postWorkerTask(const std::shared auto waitable = std::make_shared(); { std::lock_guard lock(mMutex); + ASSERT(!mTerminated); // Lazily create the threads on first task createThreads(); @@ -175,6 +191,7 @@ void AsyncWorkerPool::threadLoop() mCondVar.wait(lock, [this] { return !mTaskQueue.empty() || mTerminated; }); if (mTerminated) { + ASSERT(mTaskQueue.empty()); return; } task = mTaskQueue.front(); @@ -199,6 +216,12 @@ bool AsyncWorkerPool::isAsync() return true; } +size_t AsyncWorkerPool::getEnqueuedTaskCount() +{ + std::unique_lock lock(mMutex); + return mTaskQueue.size(); +} + #endif // ANGLE_STD_ASYNC_WORKERS #if ANGLE_DELEGATE_WORKERS @@ -277,29 +300,33 @@ bool DelegateWorkerPool::isAsync() #endif // static -std::shared_ptr WorkerThreadPool::Create(size_t numThreads, +std::shared_ptr WorkerThreadPool::Create(ThreadPoolType type, + size_t numThreads, PlatformMethods *platform) { - const bool multithreaded = numThreads != 1; + // A Synchronous pool must have a threadcount of 0 + ASSERT(type != ThreadPoolType::Synchronous || numThreads == 0); + std::shared_ptr pool(nullptr); #if ANGLE_DELEGATE_WORKERS + ASSERT(platform); const bool hasPostWorkerTaskImpl = platform->postWorkerTask != nullptr; - if (hasPostWorkerTaskImpl && multithreaded) + if (hasPostWorkerTaskImpl && type == ThreadPoolType::Asynchronous) { - pool = std::shared_ptr(new DelegateWorkerPool(platform)); + pool = std::make_shared(platform); } #endif #if ANGLE_STD_ASYNC_WORKERS - if (!pool && multithreaded) + if (!pool && type == ThreadPoolType::Asynchronous) { - pool = std::shared_ptr(new AsyncWorkerPool( - numThreads == 0 ? std::thread::hardware_concurrency() : numThreads)); + pool = std::make_shared( + numThreads == 0 ? std::thread::hardware_concurrency() : numThreads); } #endif if (!pool) { - return std::shared_ptr(new SingleThreadedWorkerPool()); + return std::make_shared(); } return pool; } diff --git a/src/common/WorkerThread.h b/src/common/WorkerThread.h index 31f7cb2f29d..609aeaffcfe 100644 --- a/src/common/WorkerThread.h +++ b/src/common/WorkerThread.h @@ -90,6 +90,7 @@ class AsyncWaitableEvent final : public WaitableEvent bool isReady() override; void markAsReady(); + void markAsAborted(); private: // To protect the concurrent accesses from both main thread and background @@ -97,9 +98,16 @@ class AsyncWaitableEvent final : public WaitableEvent std::mutex mMutex; bool mIsReady = false; + bool mAborted = false; std::condition_variable mCondition; }; +enum class ThreadPoolType +{ + Asynchronous = 0, + Synchronous = 1, +}; + // Request WorkerThreads from the WorkerThreadPool. Each pool can keep worker threads around so // we avoid the costly spin up and spin down time. class WorkerThreadPool : angle::NonCopyable @@ -108,13 +116,20 @@ class WorkerThreadPool : angle::NonCopyable WorkerThreadPool(); virtual ~WorkerThreadPool(); - // Creates a new thread pool. - // If numThreads is 0, the pool will choose the best number of threads to run. - // If numThreads is 1, the pool will be single-threaded. Tasks will run on the calling thread. - // Other numbers indicate how many threads the pool should spawn. - // Note that based on build options, this class may not actually run tasks in threads, or it may - // hook into the provided PlatformMethods::postWorkerTask, in which case numThreads is ignored. - static std::shared_ptr Create(size_t numThreads, PlatformMethods *platform); + // Creates a new thread pool + // + // If is Asynchronous, count of threads are spawned. If numThreads is 0, + // the pool chooses the count based on the number of concurrent threads supported by the + // platform. Note that based on build options, tasks may not actually run in an async thread. + // + // When angle_delegate_workers is enabled, like on Chromium, the pool hooks into the provided + // PlatformMethods::postWorkerTask and numThreads is ignored. + // + // If is Synchronous, the pool has no additional threads and tasks are executed + // inline on the calling thread. + static std::shared_ptr Create(ThreadPoolType type, + size_t numThreads, + PlatformMethods *platform); // Returns an event to wait on for the task to finish. If the pool fails to create the task, // returns null. This function is thread-safe. @@ -122,6 +137,8 @@ class WorkerThreadPool : angle::NonCopyable virtual bool isAsync() = 0; + virtual size_t getEnqueuedTaskCount() { return 0; } + private: }; diff --git a/src/common/WorkerThread_unittest.cpp b/src/common/WorkerThread_unittest.cpp index e6a8ec0be18..910c96484d6 100644 --- a/src/common/WorkerThread_unittest.cpp +++ b/src/common/WorkerThread_unittest.cpp @@ -28,8 +28,8 @@ TEST(WorkerPoolTest, SimpleTask) }; std::array, 2> pools = { - {WorkerThreadPool::Create(1, ANGLEPlatformCurrent()), - WorkerThreadPool::Create(0, ANGLEPlatformCurrent())}}; + {WorkerThreadPool::Create(ThreadPoolType::Synchronous, 0, ANGLEPlatformCurrent()), + WorkerThreadPool::Create(ThreadPoolType::Asynchronous, 0, ANGLEPlatformCurrent())}}; for (auto &pool : pools) { std::array, 4> tasks = { @@ -48,4 +48,78 @@ TEST(WorkerPoolTest, SimpleTask) } } +// Tests async worker pool application. +TEST(WorkerPoolTest, AsyncPoolTest) +{ + class TestTask : public Closure + { + public: + void operator()() override { fired = true; } + + bool fired = false; + }; + constexpr size_t kTaskCount = 4; + std::array, kTaskCount> tasks = { + {std::make_shared(), std::make_shared(), std::make_shared(), + std::make_shared()}}; + std::array, kTaskCount> waitables; + + { + std::shared_ptr pool = + WorkerThreadPool::Create(ThreadPoolType::Asynchronous, 2, ANGLEPlatformCurrent()); + + waitables = {{pool->postWorkerTask(tasks[0]), pool->postWorkerTask(tasks[1]), + pool->postWorkerTask(tasks[2]), pool->postWorkerTask(tasks[3])}}; + } + + WaitableEvent::WaitMany(&waitables); + + for (size_t taskIndex = 0; taskIndex < kTaskCount; taskIndex++) + { + EXPECT_TRUE(tasks[taskIndex]->fired || !waitables[taskIndex]->isReady()); + } +} + +// Tests async worker pool with a single thread. +TEST(WorkerPoolTest, AsyncPoolWithOneThreadTest) +{ + using CallbackFunc = std::function; + size_t callCount = 0; + CallbackFunc counter = [&callCount]() { callCount++; }; + + constexpr size_t kCallbackSteps = 1000; + class TestTask : public Closure + { + public: + TestTask(CallbackFunc callback) : mCallback(callback) { ASSERT(mCallback != nullptr); } + void operator()() override + { + for (size_t iter = 0; iter < kCallbackSteps; iter++) + { + mCallback(); + } + } + + private: + CallbackFunc mCallback; + }; + + std::shared_ptr pool = + WorkerThreadPool::Create(ThreadPoolType::Asynchronous, 1, ANGLEPlatformCurrent()); + + constexpr size_t kTaskCount = 4; + std::array, kTaskCount> tasks = { + {std::make_shared(counter), std::make_shared(counter), + std::make_shared(counter), std::make_shared(counter)}}; + + std::array, kTaskCount> waitables; + waitables = {{pool->postWorkerTask(tasks[0]), pool->postWorkerTask(tasks[1]), + pool->postWorkerTask(tasks[2]), pool->postWorkerTask(tasks[3])}}; + + WaitableEvent::WaitMany(&waitables); + + // Thread pool has 1 thread, all tasks should be serialized + EXPECT_EQ(callCount, kTaskCount * kCallbackSteps); +} + } // anonymous namespace diff --git a/src/common/android_util.h b/src/common/android_util.h index 9862578faad..d8161efa64f 100644 --- a/src/common/android_util.h +++ b/src/common/android_util.h @@ -112,6 +112,8 @@ enum { * * Corresponding formats: * Android: AHARDWAREBUFFER_FORMAT_BLOB + * Vulkan: N/A + * OpenGL ES: N/A */ ANGLE_AHB_FORMAT_BLOB = 0x21, @@ -171,22 +173,24 @@ enum { * * Corresponding formats: * Android: AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 + * Vulkan: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR + * OpenGL ES: N/A */ ANGLE_AHB_FORMAT_Y8Cb8Cr8_420 = 0x23, /** * Corresponding formats: * Android: AHARDWAREBUFFER_FORMAT_YV12 - * Vulkan: VK_FORMAT_S8_UINT - * OpenGL ES: GL_STENCIL_INDEX8 + * Vulkan: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM + * OpenGL ES: N/A */ ANGLE_AHB_FORMAT_YV12 = 0x32315659, /** * Corresponding formats: * Android: AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED - * Vulkan: VK_FORMAT_S8_UINT - * OpenGL ES: GL_STENCIL_INDEX8 + * Vulkan: N/A + * OpenGL ES: N/A */ ANGLE_AHB_FORMAT_IMPLEMENTATION_DEFINED = 0x22, diff --git a/src/common/angleutils.cpp b/src/common/angleutils.cpp index 4578a590c35..3f59548d153 100644 --- a/src/common/angleutils.cpp +++ b/src/common/angleutils.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "common/angleutils.h" #include "common/debug.h" @@ -17,71 +21,6 @@ namespace angle // dirtyPointer is a special value that will make the comparison with any valid pointer fail and // force the renderer to re-apply the state. const uintptr_t DirtyPointer = std::numeric_limits::max(); - -// AMD_performance_monitor helpers. - -PerfMonitorCounter::PerfMonitorCounter() = default; - -PerfMonitorCounter::~PerfMonitorCounter() = default; - -PerfMonitorCounterGroup::PerfMonitorCounterGroup() = default; - -PerfMonitorCounterGroup::~PerfMonitorCounterGroup() = default; - -uint32_t GetPerfMonitorCounterIndex(const PerfMonitorCounters &counters, const std::string &name) -{ - for (uint32_t counterIndex = 0; counterIndex < static_cast(counters.size()); - ++counterIndex) - { - if (counters[counterIndex].name == name) - { - return counterIndex; - } - } - - return std::numeric_limits::max(); -} - -uint32_t GetPerfMonitorCounterGroupIndex(const PerfMonitorCounterGroups &groups, - const std::string &name) -{ - for (uint32_t groupIndex = 0; groupIndex < static_cast(groups.size()); ++groupIndex) - { - if (groups[groupIndex].name == name) - { - return groupIndex; - } - } - - return std::numeric_limits::max(); -} - -const PerfMonitorCounter &GetPerfMonitorCounter(const PerfMonitorCounters &counters, - const std::string &name) -{ - return GetPerfMonitorCounter(const_cast(counters), name); -} - -PerfMonitorCounter &GetPerfMonitorCounter(PerfMonitorCounters &counters, const std::string &name) -{ - uint32_t counterIndex = GetPerfMonitorCounterIndex(counters, name); - ASSERT(counterIndex < static_cast(counters.size())); - return counters[counterIndex]; -} - -const PerfMonitorCounterGroup &GetPerfMonitorCounterGroup(const PerfMonitorCounterGroups &groups, - const std::string &name) -{ - return GetPerfMonitorCounterGroup(const_cast(groups), name); -} - -PerfMonitorCounterGroup &GetPerfMonitorCounterGroup(PerfMonitorCounterGroups &groups, - const std::string &name) -{ - uint32_t groupIndex = GetPerfMonitorCounterGroupIndex(groups, name); - ASSERT(groupIndex < static_cast(groups.size())); - return groups[groupIndex]; -} } // namespace angle std::string ArrayString(unsigned int i) @@ -127,3 +66,16 @@ size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector ASSERT(len >= 0); return static_cast(len); } + +const char *MakeStaticString(const std::string &str) +{ + // On the heap so that no destructor runs on application exit. + static std::set *strings = new std::set; + std::set::iterator it = strings->find(str); + if (it != strings->end()) + { + return it->c_str(); + } + + return strings->insert(str).first->c_str(); +} diff --git a/src/common/angleutils.h b/src/common/angleutils.h index 5af8f8edcae..7128843971d 100644 --- a/src/common/angleutils.h +++ b/src/common/angleutils.h @@ -29,6 +29,8 @@ #include #include +#include "common/unsafe_buffers.h" + namespace angle { @@ -37,11 +39,7 @@ using Microsoft::WRL::ComPtr; #endif // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) // Forward declaration. Implementation in system_utils.h -#if defined(ANGLE_PLATFORM_LINUX) || defined(ANGLE_PLATFORM_WINDOWS) -using ThreadId = uint64_t; -#else using ThreadId = std::thread::id; -#endif // A helper class to disallow copy and assignment operators class NonCopyable @@ -60,36 +58,34 @@ extern const uintptr_t DirtyPointer; // AMD_performance_monitor helpers. constexpr char kPerfMonitorExtensionName[] = "GL_AMD_performance_monitor"; -struct PerfMonitorCounter +struct PerfMonitorCounterInfo { - PerfMonitorCounter(); - ~PerfMonitorCounter(); + PerfMonitorCounterInfo() = default; + PerfMonitorCounterInfo(const char *name) : name(name) {} std::string name; +}; +struct PerfMonitorCounter +{ + PerfMonitorCounter() = default; + PerfMonitorCounter(uint64_t value) : value(value) {} + uint64_t value; }; -using PerfMonitorCounters = std::vector; +using PerfMonitorCountersInfo = std::vector; +using PerfMonitorCounters = std::vector; -struct PerfMonitorCounterGroup +struct PerfMonitorCounterGroupInfo { - PerfMonitorCounterGroup(); - ~PerfMonitorCounterGroup(); - std::string name; + PerfMonitorCountersInfo counters; +}; +struct PerfMonitorCounterGroup +{ PerfMonitorCounters counters; }; -using PerfMonitorCounterGroups = std::vector; - -uint32_t GetPerfMonitorCounterIndex(const PerfMonitorCounters &counters, const std::string &name); -const PerfMonitorCounter &GetPerfMonitorCounter(const PerfMonitorCounters &counters, - const std::string &name); -PerfMonitorCounter &GetPerfMonitorCounter(PerfMonitorCounters &counters, const std::string &name); -uint32_t GetPerfMonitorCounterGroupIndex(const PerfMonitorCounterGroups &groups, - const std::string &name); -const PerfMonitorCounterGroup &GetPerfMonitorCounterGroup(const PerfMonitorCounterGroups &groups, - const std::string &name); -PerfMonitorCounterGroup &GetPerfMonitorCounterGroup(PerfMonitorCounterGroups &groups, - const std::string &name); +using PerfMonitorCounterGroupsInfo = std::vector; +using PerfMonitorCounterGroups = std::vector; struct PerfMonitorTriplet { @@ -150,19 +146,25 @@ struct PerfMonitorTriplet FN(textureDescriptorSetCacheHits) \ FN(textureDescriptorSetCacheMisses) \ FN(textureDescriptorSetCacheTotalSize) \ + FN(uniformBuffersDescriptorSetCacheHits) \ + FN(uniformBuffersDescriptorSetCacheMisses) \ + FN(uniformBuffersDescriptorSetCacheTotalSize) \ FN(shaderResourcesDescriptorSetCacheHits) \ + FN(shaderResourcesDescriptorSetCacheMisses) \ + FN(shaderResourcesDescriptorSetCacheTotalSize) \ FN(deviceMemoryImageAllocationFallbacks) \ + FN(tileMemoryImages) \ + FN(fallbackFromTileMemory) \ FN(mutableTexturesUploaded) \ FN(fullImageClears) \ - FN(shaderResourcesDescriptorSetCacheMisses) \ - FN(shaderResourcesDescriptorSetCacheTotalSize) \ FN(buffersGhosted) \ FN(vertexArraySyncStateCalls) \ FN(allocateNewBufferBlockCalls) \ FN(bufferSuballocationCalls) \ FN(dynamicBufferAllocations) \ FN(framebufferCacheSize) \ - FN(pendingSubmissionGarbageObjects) + FN(pendingSubmissionGarbageObjects) \ + FN(graphicsDriverUniformsUpdated) #define ANGLE_DECLARE_PERF_COUNTER(COUNTER) uint64_t COUNTER; @@ -185,11 +187,7 @@ template class WrappedArray final : angle::NonCopyable { public: - template - constexpr WrappedArray(const T (&data)[N]) : mArray(&data[0]), mSize(N) - {} - - constexpr WrappedArray() : mArray(nullptr), mSize(0) {} + constexpr WrappedArray() = default; constexpr WrappedArray(const T *data, size_t size) : mArray(data), mSize(size) {} WrappedArray(WrappedArray &&other) : WrappedArray() @@ -198,14 +196,18 @@ class WrappedArray final : angle::NonCopyable std::swap(mSize, other.mSize); } + template + constexpr WrappedArray(const T (&data)[N]) : mArray(&data[0]), mSize(N) + {} + ~WrappedArray() {} constexpr const T *get() const { return mArray; } constexpr size_t size() const { return mSize; } private: - const T *mArray; - size_t mSize; + const T *mArray = nullptr; + size_t mSize = 0; }; template @@ -213,7 +215,8 @@ void SafeRelease(T (&resourceBlock)[N]) { for (unsigned int i = 0; i < N; i++) { - SafeRelease(resourceBlock[i]); + // SAFETY: size deduced by compiler from template. + SafeRelease(ANGLE_UNSAFE_BUFFERS(resourceBlock[i])); } } @@ -256,7 +259,8 @@ void SafeDeleteArray(T *&resource) template inline bool StructLessThan(const T &a, const T &b) { - return (memcmp(&a, &b, sizeof(T)) < 0); + // SAFETY: both `a` and `b` are the same compiler-deduced size. + return ANGLE_UNSAFE_BUFFERS(memcmp(&a, &b, sizeof(T)) < 0); } // Provide a less-than function for comparing structs @@ -264,13 +268,22 @@ inline bool StructLessThan(const T &a, const T &b) template inline bool StructEquals(const T &a, const T &b) { - return (memcmp(&a, &b, sizeof(T)) == 0); + // SAFETY: both `a` and `b` are the same compiler-deduced size. + return ANGLE_UNSAFE_BUFFERS(memcmp(&a, &b, sizeof(T)) == 0); } template inline void StructZero(T *obj) { - memset(obj, 0, sizeof(T)); + // SAFETY: compiler-deduced size. + ANGLE_UNSAFE_BUFFERS(memset(obj, 0, sizeof(T))); +} + +template +inline void StructCopy(T *dst, const T &src) +{ + // SAFETY: compiler-deduced size. + ANGLE_UNSAFE_BUFFERS(memcpy(dst, &src, sizeof(T))); } template @@ -280,18 +293,7 @@ inline bool IsMaskFlagSet(T mask, T flag) return (mask & flag) == flag; } -inline const char *MakeStaticString(const std::string &str) -{ - // On the heap so that no destructor runs on application exit. - static std::set *strings = new std::set; - std::set::iterator it = strings->find(str); - if (it != strings->end()) - { - return it->c_str(); - } - - return strings->insert(str).first->c_str(); -} +const char *MakeStaticString(const std::string &str); std::string ArrayString(unsigned int i); @@ -348,6 +350,8 @@ inline bool IsLittleEndian() // fake format for GL_ANGLE_rgbx_internal_format #define GL_RGBX8_SRGB_ANGLEX 0x6AFA +#define GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX 0x6AFD + // These are fake formats used to fit typeless D3D textures that can be bound to EGL pbuffers into // the format system (for extension EGL_ANGLE_d3d_texture_client_buffer): #define GL_RGBA8_TYPELESS_ANGLEX 0x6AC1 diff --git a/src/common/apple_platform_utils.mm b/src/common/apple_platform_utils.mm index edced2c0625..09abd085d19 100644 --- a/src/common/apple_platform_utils.mm +++ b/src/common/apple_platform_utils.mm @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "common/apple_platform_utils.h" #include "common/debug.h" @@ -121,13 +125,8 @@ bool IsMetalRendererAvailable() #if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST) bool GetMacosMachineModel(std::string *outMachineModel) { -# if TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 120000 - const mach_port_t mainPort = kIOMasterPortDefault; -# else - const mach_port_t mainPort = kIOMainPortDefault; -# endif - io_service_t platformExpert = - IOServiceGetMatchingService(mainPort, IOServiceMatching("IOPlatformExpertDevice")); + io_service_t platformExpert = IOServiceGetMatchingService( + kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice")); if (platformExpert == IO_OBJECT_NULL) { diff --git a/src/common/backtrace_utils.h b/src/common/backtrace_utils.h index cc0a483a98c..e7ac3f033c0 100644 --- a/src/common/backtrace_utils.h +++ b/src/common/backtrace_utils.h @@ -12,8 +12,10 @@ #include #include -#include "debug.h" -#include "hash_utils.h" + +#include "common/debug.h" +#include "common/hash_utils.h" +#include "common/span.h" namespace angle { @@ -59,7 +61,7 @@ class BacktraceInfo return mStackSymbols[index]; } - size_t hash() const { return ComputeGenericHash(*this); } + size_t hash() const { return ComputeGenericHash(angle::byte_span_from_ref(*this)); } // Used to add the stack addresses and their corresponding symbols to the object, when // angle_enable_unwind_backtrace_support is enabled on Android. diff --git a/src/common/backtrace_utils_android.cpp b/src/common/backtrace_utils_android.cpp index 7284d8e3ab0..d28797bd852 100644 --- a/src/common/backtrace_utils_android.cpp +++ b/src/common/backtrace_utils_android.cpp @@ -7,6 +7,10 @@ // Implements the functions related to the backtrace info class for Android platforms. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "backtrace_utils.h" #include diff --git a/src/common/base/README.chromium b/src/common/base/README.chromium index 19ab4cd9e52..2cf904ac4b0 100644 --- a/src/common/base/README.chromium +++ b/src/common/base/README.chromium @@ -1,13 +1,13 @@ Name: Chromium base:: helper Classes Short Name: base::numerics, base::MRUCachem, base::SHA1 -Version: +Version: N/A URL: https://chromium.googlesource.com/chromium/src/base/+/main -SOURCE CODE: Copy the Chromium folder manually into this folder and run git cl format. Date: 2017-05-24 -Revision: 28b5bbb227d331c01e6ff9b2f8729732135aadc7 (Chromium) +Revision: 28b5bbb227d331c01e6ff9b2f8729732135aadc7 +Update Mechanism: Static.HardFork (https://crbug.com/419410757) Security Critical: no Shipped: yes -License: Chromium +License: BSD-3-Clause License File: LICENSE in Chromium/src Description: @@ -15,9 +15,12 @@ base::numerics is a library for doing some simple safe math and conversions. base::MRUCache is a few collections of most-recently-used caching structures. base::SHA1 is a secure hashing algorithm. -To update the checkout, simply overwrite the folder with Chromium's latest, apply -the appropriate namespace, and make sure the paths are correct (anglebase/ instead of -base/), and update the header guards and macros. +To update the checkout: +1. Manually overwrite the folder with Chromium's copy +2. run `git cl format` +3. apply the appropriate namespace, and make sure the paths are correct (anglebase/ instead of +base/). +4. Update the header guards and macros. Modifications: diff --git a/src/common/base/anglebase/sha1.cc b/src/common/base/anglebase/sha1.cc index 3db432d66ff..e542f147be2 100644 --- a/src/common/base/anglebase/sha1.cc +++ b/src/common/base/anglebase/sha1.cc @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "anglebase/sha1.h" #include diff --git a/src/common/base/anglebase/trace_event/trace_event.h b/src/common/base/anglebase/trace_event/trace_event.h index 66d0a4012aa..92a2399dea3 100644 --- a/src/common/base/anglebase/trace_event/trace_event.h +++ b/src/common/base/anglebase/trace_event/trace_event.h @@ -141,6 +141,10 @@ #ifndef COMMON_TRACE_EVENT_H_ #define COMMON_TRACE_EVENT_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/event_tracer.h" diff --git a/src/common/bitset_utils.h b/src/common/bitset_utils.h index 7bebf40814d..b5038fa8d4f 100644 --- a/src/common/bitset_utils.h +++ b/src/common/bitset_utils.h @@ -166,7 +166,6 @@ class BitSetT final constexpr BitSetT &flip(); constexpr BitSetT &flip(ParamT pos); - constexpr unsigned long to_ulong() const { return static_cast(mBits); } constexpr BitsT bits() const { return mBits; } Iterator begin() const { return Iterator(*this); } @@ -574,8 +573,17 @@ class BitSetArray final updateIteratorBit(pos, true); } + void resetLaterBits(const BitSetArray &bits) + { + ASSERT(bits.first() > (mIndex * priv::kDefaultBitSetSize) + *mCurrentIterator); + prepareCopy(); + mParentCopy &= ~bits; + updateIteratorBits(bits); + } + void setLaterBits(const BitSetArray &bits) { + ASSERT(bits.first() > (mIndex * priv::kDefaultBitSetSize) + *mCurrentIterator); prepareCopy(); mParentCopy |= bits; updateIteratorBits(bits); @@ -650,15 +658,6 @@ class BitSetArray final constexpr static std::size_t size() { return N; } Iterator begin() const { return Iterator(*this, 0); } Iterator end() const { return Iterator(*this, kArraySize); } - constexpr unsigned long to_ulong() const - { - // TODO(anglebug.com/42264163): Handle serializing more than kDefaultBitSetSize - for (std::size_t index = 1; index < kArraySize; index++) - { - ASSERT(mBaseBitSetArray[index].none()); - } - return static_cast(mBaseBitSetArray[0].to_ulong()); - } // Assignment operators constexpr BitSetArray &operator&=(const BitSetArray &other); @@ -699,10 +698,28 @@ class BitSetArray final constexpr param_type last() const; constexpr value_type bits(size_t index) const; + constexpr static size_t ArraySize() { return kArraySize; } + + template + constexpr auto bits() const + -> std::enable_if_t + { + // This function should only exist when the default bitset size is 32 and N is not more + // than 64. When kDefaultBitSetSize is 32, BitSetArray is used for N > 32. This means N is + // in (32, 64], and kArraySize will be 2. + static_assert(kArraySize == 2); + uint64_t result = mBaseBitSetArray[1].bits(); + return (result << 32) | mBaseBitSetArray[0].bits(); + } // Produces a mask of ones up to the "x"th bit. constexpr static BitSetArray Mask(std::size_t x); + template = 0> + constexpr void initFromValue(uint64_t value); + template = 64), int> = 0> + constexpr void initFromValue(uint64_t value); + private: static constexpr std::size_t kDefaultBitSetSizeMinusOne = priv::kDefaultBitSetSize - 1; static constexpr std::size_t kShiftForDivision = @@ -730,25 +747,7 @@ template constexpr BitSetArray::BitSetArray(uint64_t value) { reset(); - - if (priv::kDefaultBitSetSize < 64) - { - size_t i = 0; - for (; i < kArraySize - 1; ++i) - { - value_type elemValue = - value & priv::BaseBitSetType::Mask(priv::kDefaultBitSetSize).bits(); - mBaseBitSetArray[i] = priv::BaseBitSetType(elemValue); - value >>= priv::kDefaultBitSetSize; - } - value_type elemValue = value & kLastElementMask; - mBaseBitSetArray[i] = priv::BaseBitSetType(elemValue); - } - else - { - value_type elemValue = value & priv::BaseBitSetType::Mask(priv::kDefaultBitSetSize).bits(); - mBaseBitSetArray[0] = priv::BaseBitSetType(elemValue); - } + initFromValue(value); } template @@ -1105,6 +1104,32 @@ constexpr BitSetArray BitSetArray::Mask(std::size_t x) return result; } + +template +template > +constexpr void BitSetArray::initFromValue(uint64_t value) +{ + static_assert(BitSetSize == 32, "Expected 32 bit size"); + size_t i = 0; + for (; i < kArraySize - 1; ++i) + { + value_type elemValue = value & priv::BaseBitSetType::Mask(BitSetSize).bits(); + mBaseBitSetArray[i] = priv::BaseBitSetType(elemValue); + value >>= BitSetSize; + } + value_type elemValue = value & kLastElementMask; + mBaseBitSetArray[i] = priv::BaseBitSetType(elemValue); +} + +template +template = 64), int>> +constexpr void BitSetArray::initFromValue(uint64_t value) +{ + static_assert(BitSetSize == 64, "Expected 64 bit size"); + value_type elemValue = value & priv::BaseBitSetType::Mask(BitSetSize).bits(); + mBaseBitSetArray[0] = priv::BaseBitSetType(elemValue); +} + } // namespace angle template diff --git a/src/common/debug.cpp b/src/common/debug.cpp index 706852242b5..2c7f18b509f 100644 --- a/src/common/debug.cpp +++ b/src/common/debug.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // debug.cpp: Debugging utilities. #include "common/debug.h" @@ -269,31 +273,28 @@ void Trace(LogSeverity severity, const char *message) #endif #if defined(ANGLE_PLATFORM_APPLE) - if (__builtin_available(macOS 10.12, iOS 10.0, *)) + os_log_type_t apple_log_type = OS_LOG_TYPE_DEFAULT; + switch (severity) { - os_log_type_t apple_log_type = OS_LOG_TYPE_DEFAULT; - switch (severity) - { - case LOG_INFO: - case LOG_EVENT: - apple_log_type = OS_LOG_TYPE_INFO; - break; - case LOG_WARN: - apple_log_type = OS_LOG_TYPE_DEFAULT; - break; - case LOG_ERR: - apple_log_type = OS_LOG_TYPE_ERROR; - break; - case LOG_FATAL: - // OS_LOG_TYPE_FAULT is too severe - grabs the entire process tree. - apple_log_type = OS_LOG_TYPE_ERROR; - break; - default: - UNREACHABLE(); - } - os_log_with_type(OS_LOG_DEFAULT, apple_log_type, "ANGLE: %s: %s\n", - LogSeverityName(severity), str.c_str()); + case LOG_INFO: + case LOG_EVENT: + apple_log_type = OS_LOG_TYPE_INFO; + break; + case LOG_WARN: + apple_log_type = OS_LOG_TYPE_DEFAULT; + break; + case LOG_ERR: + apple_log_type = OS_LOG_TYPE_ERROR; + break; + case LOG_FATAL: + // OS_LOG_TYPE_FAULT is too severe - grabs the entire process tree. + apple_log_type = OS_LOG_TYPE_ERROR; + break; + default: + UNREACHABLE(); } + os_log_with_type(OS_LOG_DEFAULT, apple_log_type, "ANGLE: %s: %s\n", + LogSeverityName(severity), str.c_str()); #else // Note: we use fprintf because includes static initializers. fprintf((severity >= LOG_WARN) ? stderr : stdout, "%s: %s\n", LogSeverityName(severity), diff --git a/src/common/entry_points_enum_autogen.cpp b/src/common/entry_points_enum_autogen.cpp index 7d3beb4fe34..c9a21c865c9 100644 --- a/src/common/entry_points_enum_autogen.cpp +++ b/src/common/entry_points_enum_autogen.cpp @@ -70,6 +70,8 @@ const char *GetEntryPointName(EntryPoint ep) return "clCreateSubDevices"; case EntryPoint::CLCreateUserEvent: return "clCreateUserEvent"; + case EntryPoint::CLEnqueueAcquireExternalMemObjectsKHR: + return "clEnqueueAcquireExternalMemObjectsKHR"; case EntryPoint::CLEnqueueBarrier: return "clEnqueueBarrier"; case EntryPoint::CLEnqueueBarrierWithWaitList: @@ -108,6 +110,8 @@ const char *GetEntryPointName(EntryPoint ep) return "clEnqueueReadBufferRect"; case EntryPoint::CLEnqueueReadImage: return "clEnqueueReadImage"; + case EntryPoint::CLEnqueueReleaseExternalMemObjectsKHR: + return "clEnqueueReleaseExternalMemObjectsKHR"; case EntryPoint::CLEnqueueSVMFree: return "clEnqueueSVMFree"; case EntryPoint::CLEnqueueSVMMap: @@ -182,8 +186,14 @@ const char *GetEntryPointName(EntryPoint ep) return "clGetSamplerInfo"; case EntryPoint::CLGetSupportedImageFormats: return "clGetSupportedImageFormats"; + case EntryPoint::CLIcdGetFunctionAddressForPlatformKHR: + return "clIcdGetFunctionAddressForPlatformKHR"; case EntryPoint::CLIcdGetPlatformIDsKHR: return "clIcdGetPlatformIDsKHR"; + case EntryPoint::CLIcdSetPlatformDispatchDataKHR: + return "clIcdSetPlatformDispatchDataKHR"; + case EntryPoint::CLImportMemoryARM: + return "clImportMemoryARM"; case EntryPoint::CLLinkProgram: return "clLinkProgram"; case EntryPoint::CLReleaseCommandQueue: @@ -460,8 +470,6 @@ const char *GetEntryPointName(EntryPoint ep) return "eglSwapBuffers"; case EntryPoint::EGLSwapBuffersWithDamageKHR: return "eglSwapBuffersWithDamageKHR"; - case EntryPoint::EGLSwapBuffersWithFrameTokenANGLE: - return "eglSwapBuffersWithFrameTokenANGLE"; case EntryPoint::EGLSwapInterval: return "eglSwapInterval"; case EntryPoint::EGLTerminate: @@ -882,8 +890,6 @@ const char *GetEntryPointName(EntryPoint ep) return "glEGLImageTargetTexStorageEXT"; case EntryPoint::GLEGLImageTargetTexture2DOES: return "glEGLImageTargetTexture2DOES"; - case EntryPoint::GLEGLImageTargetTextureStorageEXT: - return "glEGLImageTargetTextureStorageEXT"; case EntryPoint::GLEnable: return "glEnable"; case EntryPoint::GLEnableClientState: @@ -954,6 +960,8 @@ const char *GetEntryPointName(EntryPoint ep) return "glFramebufferRenderbuffer"; case EntryPoint::GLFramebufferRenderbufferOES: return "glFramebufferRenderbufferOES"; + case EntryPoint::GLFramebufferShadingRateEXT: + return "glFramebufferShadingRateEXT"; case EntryPoint::GLFramebufferTexture: return "glFramebufferTexture"; case EntryPoint::GLFramebufferTexture2D: @@ -968,6 +976,8 @@ const char *GetEntryPointName(EntryPoint ep) return "glFramebufferTextureEXT"; case EntryPoint::GLFramebufferTextureLayer: return "glFramebufferTextureLayer"; + case EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR: + return "glFramebufferTextureMultisampleMultiviewOVR"; case EntryPoint::GLFramebufferTextureMultiviewOVR: return "glFramebufferTextureMultiviewOVR"; case EntryPoint::GLFramebufferTextureOES: @@ -1080,6 +1090,8 @@ const char *GetEntryPointName(EntryPoint ep) return "glGetFragDataIndexEXT"; case EntryPoint::GLGetFragDataLocation: return "glGetFragDataLocation"; + case EntryPoint::GLGetFragmentShadingRatesEXT: + return "glGetFragmentShadingRatesEXT"; case EntryPoint::GLGetFramebufferAttachmentParameteriv: return "glGetFramebufferAttachmentParameteriv"; case EntryPoint::GLGetFramebufferAttachmentParameterivOES: @@ -1540,6 +1552,8 @@ const char *GetEntryPointName(EntryPoint ep) return "glMultMatrixx"; case EntryPoint::GLMultiDrawArraysANGLE: return "glMultiDrawArraysANGLE"; + case EntryPoint::GLMultiDrawArraysEXT: + return "glMultiDrawArraysEXT"; case EntryPoint::GLMultiDrawArraysIndirectEXT: return "glMultiDrawArraysIndirectEXT"; case EntryPoint::GLMultiDrawArraysInstancedANGLE: @@ -1550,6 +1564,8 @@ const char *GetEntryPointName(EntryPoint ep) return "glMultiDrawElementsANGLE"; case EntryPoint::GLMultiDrawElementsBaseVertexEXT: return "glMultiDrawElementsBaseVertexEXT"; + case EntryPoint::GLMultiDrawElementsEXT: + return "glMultiDrawElementsEXT"; case EntryPoint::GLMultiDrawElementsIndirectEXT: return "glMultiDrawElementsIndirectEXT"; case EntryPoint::GLMultiDrawElementsInstancedANGLE: @@ -1560,8 +1576,6 @@ const char *GetEntryPointName(EntryPoint ep) return "glMultiTexCoord4f"; case EntryPoint::GLMultiTexCoord4x: return "glMultiTexCoord4x"; - case EntryPoint::GLNamedBufferStorageExternalEXT: - return "glNamedBufferStorageExternalEXT"; case EntryPoint::GLNormal3f: return "glNormal3f"; case EntryPoint::GLNormal3x: @@ -1874,6 +1888,10 @@ const char *GetEntryPointName(EntryPoint ep) return "glShaderBinary"; case EntryPoint::GLShaderSource: return "glShaderSource"; + case EntryPoint::GLShadingRateCombinerOpsEXT: + return "glShadingRateCombinerOpsEXT"; + case EntryPoint::GLShadingRateEXT: + return "glShadingRateEXT"; case EntryPoint::GLShadingRateQCOM: return "glShadingRateQCOM"; case EntryPoint::GLSignalSemaphoreEXT: @@ -1976,8 +1994,6 @@ const char *GetEntryPointName(EntryPoint ep) return "glTexParameterx"; case EntryPoint::GLTexParameterxv: return "glTexParameterxv"; - case EntryPoint::GLTexStorage1DEXT: - return "glTexStorage1DEXT"; case EntryPoint::GLTexStorage2D: return "glTexStorage2D"; case EntryPoint::GLTexStorage2DEXT: diff --git a/src/common/entry_points_enum_autogen.h b/src/common/entry_points_enum_autogen.h index e09617166d0..a8144727fef 100644 --- a/src/common/entry_points_enum_autogen.h +++ b/src/common/entry_points_enum_autogen.h @@ -41,6 +41,7 @@ enum class EntryPoint CLCreateSubBuffer, CLCreateSubDevices, CLCreateUserEvent, + CLEnqueueAcquireExternalMemObjectsKHR, CLEnqueueBarrier, CLEnqueueBarrierWithWaitList, CLEnqueueCopyBuffer, @@ -60,6 +61,7 @@ enum class EntryPoint CLEnqueueReadBuffer, CLEnqueueReadBufferRect, CLEnqueueReadImage, + CLEnqueueReleaseExternalMemObjectsKHR, CLEnqueueSVMFree, CLEnqueueSVMMap, CLEnqueueSVMMemFill, @@ -97,7 +99,10 @@ enum class EntryPoint CLGetProgramInfo, CLGetSamplerInfo, CLGetSupportedImageFormats, + CLIcdGetFunctionAddressForPlatformKHR, CLIcdGetPlatformIDsKHR, + CLIcdSetPlatformDispatchDataKHR, + CLImportMemoryARM, CLLinkProgram, CLReleaseCommandQueue, CLReleaseContext, @@ -236,7 +241,6 @@ enum class EntryPoint EGLSurfaceAttrib, EGLSwapBuffers, EGLSwapBuffersWithDamageKHR, - EGLSwapBuffersWithFrameTokenANGLE, EGLSwapInterval, EGLTerminate, EGLUnlockSurfaceKHR, @@ -447,7 +451,6 @@ enum class EntryPoint GLEGLImageTargetRenderbufferStorageOES, GLEGLImageTargetTexStorageEXT, GLEGLImageTargetTexture2DOES, - GLEGLImageTargetTextureStorageEXT, GLEnable, GLEnableClientState, GLEnableVertexAttribArray, @@ -483,6 +486,7 @@ enum class EntryPoint GLFramebufferPixelLocalStorageRestoreANGLE, GLFramebufferRenderbuffer, GLFramebufferRenderbufferOES, + GLFramebufferShadingRateEXT, GLFramebufferTexture, GLFramebufferTexture2D, GLFramebufferTexture2DMultisampleEXT, @@ -490,6 +494,7 @@ enum class EntryPoint GLFramebufferTexture3DOES, GLFramebufferTextureEXT, GLFramebufferTextureLayer, + GLFramebufferTextureMultisampleMultiviewOVR, GLFramebufferTextureMultiviewOVR, GLFramebufferTextureOES, GLFramebufferTexturePixelLocalStorageANGLE, @@ -546,6 +551,7 @@ enum class EntryPoint GLGetFloatvRobustANGLE, GLGetFragDataIndexEXT, GLGetFragDataLocation, + GLGetFragmentShadingRatesEXT, GLGetFramebufferAttachmentParameteriv, GLGetFramebufferAttachmentParameterivOES, GLGetFramebufferAttachmentParameterivRobustANGLE, @@ -776,17 +782,18 @@ enum class EntryPoint GLMultMatrixf, GLMultMatrixx, GLMultiDrawArraysANGLE, + GLMultiDrawArraysEXT, GLMultiDrawArraysIndirectEXT, GLMultiDrawArraysInstancedANGLE, GLMultiDrawArraysInstancedBaseInstanceANGLE, GLMultiDrawElementsANGLE, GLMultiDrawElementsBaseVertexEXT, + GLMultiDrawElementsEXT, GLMultiDrawElementsIndirectEXT, GLMultiDrawElementsInstancedANGLE, GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, GLMultiTexCoord4f, GLMultiTexCoord4x, - GLNamedBufferStorageExternalEXT, GLNormal3f, GLNormal3x, GLNormalPointer, @@ -943,6 +950,8 @@ enum class EntryPoint GLShadeModel, GLShaderBinary, GLShaderSource, + GLShadingRateCombinerOpsEXT, + GLShadingRateEXT, GLShadingRateQCOM, GLSignalSemaphoreEXT, GLStartTilingQCOM, @@ -994,7 +1003,6 @@ enum class EntryPoint GLTexParameterivRobustANGLE, GLTexParameterx, GLTexParameterxv, - GLTexStorage1DEXT, GLTexStorage2D, GLTexStorage2DEXT, GLTexStorage2DMultisample, diff --git a/src/common/event_tracer.cpp b/src/common/event_tracer.cpp index 151cb2cd707..40a9d949014 100644 --- a/src/common/event_tracer.cpp +++ b/src/common/event_tracer.cpp @@ -37,7 +37,11 @@ angle::TraceEventHandle AddTraceEvent(PlatformMethods *platform, { ASSERT(platform); +#if defined(ANGLE_TRACE_EVENTS_IGNORE_TIMESTAMP) + double timestamp = 1.0; // Value doesn't matter, not used by the callback. +#else double timestamp = platform->monotonicallyIncreasingTime(platform); +#endif if (timestamp != 0) { diff --git a/src/common/frame_capture_binary_data.cpp b/src/common/frame_capture_binary_data.cpp new file mode 100644 index 00000000000..421858e19bc --- /dev/null +++ b/src/common/frame_capture_binary_data.cpp @@ -0,0 +1,643 @@ +// +// Copyright 2025 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. +// +// frame_capture_binary_data.cpp: +// Common code for the ANGLE trace replay large trace binary data definition. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#define USE_SYSTEM_ZLIB +#include "compression_utils_portable.h" + +#include "common/mathutil.h" +#include "frame_capture_binary_data.h" + +#include +#include + +namespace angle +{ + +// Return current size of all binary data +size_t FrameCaptureBinaryData::totalSize() const +{ + return ((mBlockCount - 1) * mDataBlockSize) + mCurrentBlockOffset; +} + +// Determine if any blocks have been saved to disk, i.e., if we have run out of resident +// blocks +bool FrameCaptureBinaryData::isSwapMode() const +{ + return (mStoredBlocks > 0); +} + +void FrameCaptureBinaryData::storeResidentBlocks() +{ + // Write out all resident binary data blocks by calling storeBlock on each, deleting + // front() from vector + if (!isSwapMode()) + { + while (mData.size() > 1) + { + storeBlock(); + mData.erase(mData.begin()); + } + } + + storeBlock(); +} + +void FrameCaptureBinaryData::updateGetDataCache(size_t blockId) +{ + const ReplayBlockDescription &desc = mReplayBlockDescriptions[blockId]; + + mCacheBlockId = blockId; + mCacheBlockBeginOffset = desc.beginDataOffset; + mCacheBlockEndOffset = desc.endDataOffset; + mCacheBlockBaseAddress = desc.residentAddress; + + // The location for the swap block differs for load and store. For store it will ultimately be + // zero as it's unnecessary to utilize the full BinaryDataSize. For load, it will end up + // as the last of the resident blocks. + if (blockId >= mMaxResidentBlockIndex) + { + mCurrentTransientLoadedBlockId = blockId; + } +} + +// Resident blocks will have a valid memory address at residentAddress +bool FrameCaptureBinaryData::isBlockResident(size_t blockId) const +{ + return (mReplayBlockDescriptions[blockId].residentAddress != nullptr); +} + +void FrameCaptureBinaryData::setBlockResident(size_t blockId, uint8_t *address) +{ + mReplayBlockDescriptions[blockId].residentAddress = address; +} + +void FrameCaptureBinaryData::setBlockNonResident(size_t blockId) +{ + mReplayBlockDescriptions[blockId].residentAddress = nullptr; +} + +void FrameCaptureBinaryData::setBlockSize(size_t blockSize) +{ + if (!gl::isPow2(blockSize)) + { + FATAL() << "Binary Data File Blocksize specified is not a power of 2: " << blockSize; + } + mDataBlockSize = blockSize; +} + +void FrameCaptureBinaryData::setBinaryDataSize(size_t binaryDataSize) +{ + if (!gl::isPow2(binaryDataSize)) + { + FATAL() << "Binary Data File Binary Data Size specified is not a power of 2: " + << binaryDataSize; + } + mMaxResidentBinarySize = binaryDataSize; +} + +std::vector &FrameCaptureBinaryData::prepareStoreBlock(size_t blockId) +{ + // Ensure mData has enough vectors up to and including the target index + if (!isSwapMode()) + { + mData.resize(mData.size() + 1); + } + + mBlockCount = blockId + 1; + + mData.back().resize(mDataBlockSize); + mCurrentBlockOffset = 0; + + return mData.back(); +} + +std::vector &FrameCaptureBinaryData::prepareLoadBlock(size_t blockId) +{ + size_t destBlockIndex = std::min(blockId, mMaxResidentBlockIndex); + + // Ensure mData has enough vectors up to the target index + if (destBlockIndex >= mData.size()) + { + mData.resize(destBlockIndex + 1); + } + + if (isSwapBlock(destBlockIndex)) + { + // If not the same block, mark previous block occupying swap slot as non-resident + if (blockId != mCurrentTransientLoadedBlockId) + { + // Since this is the swap block, we aren't actually freeing any memory. But we need + // a way to indicate whether a transient block is loaded. This way each logical + // block knows whether it is resident, and where. + setBlockNonResident(mCurrentTransientLoadedBlockId); + } + // Track which logical block is now in the swap slot + mCurrentTransientLoadedBlockId = blockId; + } + + mData.back().resize(mDataBlockSize); + mCurrentBlockOffset = 0; + + return mData.back(); +} + +// Write file index entries to the end of compressed binary data files +BinaryFileIndexInfo FrameCaptureBinaryData::appendFileIndex() +{ + BinaryFileIndexInfo indexInfo; + indexInfo.version = kLongTraceVersionId; + indexInfo.blockSize = mDataBlockSize; + indexInfo.blockCount = mBlockCount; + indexInfo.residentSize = mMaxResidentBinarySize; + indexInfo.indexOffset = 0; + + if (mIsBinaryDataCompressed) + { + size_t indexDataOffset = mFileStream->getPosition(); + // Copy index entries (index data trailer) to end of compressed data file + for (auto &entry : mFileIndex) + { + mFileStream->write(reinterpret_cast(&entry), sizeof(FileBlockInfo)); + } + indexInfo.indexOffset = indexDataOffset; + } + + // Return index information for saving in JSON file + return indexInfo; +} + +// Read in file index data from a compressed file and construct an access index +void FrameCaptureBinaryData::constructBlockDescIndex(size_t indexOffset) +{ + if (mIsBinaryDataCompressed) + { + // Move to the beginning of the index data in the compressed file + mFileStream->seek(indexOffset, kSeekBegin); + + // Populate the replay block description array + for (size_t i = 0; i < mBlockCount; i++) + { + // Read in block's information data + FileBlockInfo blockInfo; + mFileStream->read(reinterpret_cast(&blockInfo), sizeof(FileBlockInfo)); + + // Create and save a block description from the block information + ReplayBlockDescription blockDesc = {}; + blockDesc.fileOffset = blockInfo.fileOffset; + blockDesc.beginDataOffset = blockInfo.dataOffset; + blockDesc.endDataOffset = blockInfo.dataOffset + blockInfo.dataSize - 1; + blockDesc.dataSize = blockInfo.dataSize; + mReplayBlockDescriptions.push_back(blockDesc); + } + } + else + { + // Create block descriptions from fixed size calculations + mFileStream->seek(0, kSeekEnd); + size_t size = mFileStream->getPosition(); + mFileStream->seek(0, kSeekBegin); + + size_t remaining = size; + while (remaining > 0) + { + // The final block is typically smaller than mDataBlockSize + size_t dataSize = std::min(remaining, mDataBlockSize); + size_t offset = size - remaining; + + // Create and save a block description + ReplayBlockDescription blockDesc = {}; + blockDesc.fileOffset = offset; + blockDesc.beginDataOffset = offset; + blockDesc.endDataOffset = offset + dataSize - 1; + blockDesc.dataSize = dataSize; + mReplayBlockDescriptions.push_back(blockDesc); + remaining -= dataSize; + } + } +} + +size_t FrameCaptureBinaryData::append(const void *data, size_t size) +{ + if (mData.empty()) + { + prepareStoreBlock(0); + mBlockCount = 1; + } + + ASSERT(totalSize() % kBinaryAlignment == 0); + size_t startingOffset = totalSize(); + const size_t sizeToIncrease = rx::roundUpPow2(size, kBinaryAlignment); + + // If the requested data size will not fit into the current block, allocate + // a new block + if (mCurrentBlockOffset + sizeToIncrease > mDataBlockSize) + { + size_t newBlockId = (startingOffset + sizeToIncrease) / mDataBlockSize; + + if (!isSwapMode()) + { + if (newBlockId > mMaxResidentBlockIndex) + { + // All resident blocks are full, store them to disk + storeResidentBlocks(); + } + else + { + // Resident blocks available, no need to store to disk + } + } + else + { + // Resident blocks have been saved, write this block to disk + storeBlock(); + } + prepareStoreBlock(newBlockId); + startingOffset = totalSize(); + } + + memcpy(mData.back().data() + mCurrentBlockOffset, data, size); + mCurrentBlockOffset += sizeToIncrease; + return startingOffset; +} + +const uint8_t *FrameCaptureBinaryData::getData(size_t offset) +{ + // This is the fastpath for this function, misses should be negligible + if (offset >= mCacheBlockBeginOffset && offset < mCacheBlockEndOffset) + { + return (mCacheBlockBaseAddress + (offset - mCacheBlockBeginOffset)); + } + + // Calculate new block id for binary data to be loaded + size_t newBlockId = offset / mDataBlockSize; + // Swap block into memory if it is nonresident + if (!isBlockResident(newBlockId)) + { + loadBlock(newBlockId); + } + // Update the fastpath cache variables + updateGetDataCache(newBlockId); + + return (mCacheBlockBaseAddress + (offset - mCacheBlockBeginOffset)); +} + +void FrameCaptureBinaryData::clear() +{ + mCurrentBlockOffset = 0; + mFileIndex.clear(); + mReplayBlockDescriptions.clear(); + mData.clear(); +} + +// Helper class for compression/decompression operations +class ZLibHelper +{ + // See the following file for details on these variables and helpers: + // https://chromium.googlesource.com/chromium/src/+/master/third_party/zlib/google/compression_utils_portable.cc + static constexpr int kZlibMemoryLevel = 8; + static constexpr int kWindowBitsToGetGzipHeader = 16; + + public: + ZLibHelper(FrameCaptureBinaryData::Mode mode) : mMode(mode), mStream(), mInitialized(false) + { + int ret = 0; + mStream.zalloc = Z_NULL; + mStream.zfree = Z_NULL; + mStream.opaque = Z_NULL; + mStream.avail_in = 0; + mStream.next_in = Z_NULL; + + if (mMode == FrameCaptureBinaryData::Mode::Load) + { + ret = inflateInit2(&mStream, MAX_WBITS + kWindowBitsToGetGzipHeader); + } + else if (mMode == FrameCaptureBinaryData::Mode::Store) + { + ret = deflateInit2(&mStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, + MAX_WBITS + kWindowBitsToGetGzipHeader, kZlibMemoryLevel, + Z_DEFAULT_STRATEGY); + } + else + { + FATAL() << "Invalid Mode Enum in ZLibHelper"; + } + + if (ret != Z_OK) + { + FATAL() << "Zlib helper initialization failed: " << ret; + } + mInitialized = true; + } + + ~ZLibHelper() + { + if (mInitialized) + { + if (mMode == FrameCaptureBinaryData::Mode::Load) + { + inflateEnd(&mStream); + } + else if (mMode == FrameCaptureBinaryData::Mode::Store) + { + deflateEnd(&mStream); + } + else + { + FATAL() << "Invalid Mode Enum in ZLibHelper"; + } + } + } + + z_stream *getStream() { return &mStream; } + + ZLibHelper(const ZLibHelper &) = delete; + ZLibHelper &operator=(const ZLibHelper &) = delete; + ZLibHelper(ZLibHelper &&) = delete; + ZLibHelper &operator=(ZLibHelper &&) = delete; + + private: + FrameCaptureBinaryData::Mode mMode; + z_stream mStream; + bool mInitialized; +}; + +// Configure binary data output parameters and prepare file for writing +void FrameCaptureBinaryData::initializeBinaryDataStore(bool compression, + const std::string &outDir, + const std::string &fileName) +{ + std::string binaryDataFileName = outDir + fileName; + mStoredBlocks = 0; + mIsBinaryDataCompressed = compression; + + if ((mMaxResidentBinarySize / mDataBlockSize) <= 1) + { + FATAL() << "Error,insufficient resident memory specified or available"; + } + mMaxResidentBlockIndex = (mMaxResidentBinarySize / mDataBlockSize) - 1; + + mFileStream = new FileStream(binaryDataFileName, Mode::Store); +} + +// Optionally compress and then write a single data block to disk +void FrameCaptureBinaryData::storeBlock() +{ + std::vector &storeBlock = mData.front(); + + // The last block to be saved will be resized to fit used data + if (mCaptureComplete && mData.size() == 1) + { + storeBlock.resize(mCurrentBlockOffset); + } + + if (mIsBinaryDataCompressed) + { + // Use zlib library, based on example/doc here: https://zlib.net/zlib_how.html + ZLibHelper compressor(Mode::Store); + z_stream *zStream = compressor.getStream(); + + int deflateStatus = 0; + using ZlibBuffer = std::array; + std::unique_ptr compressBuffer(new ZlibBuffer()); + + FileBlockInfo fileIndexEntry; + fileIndexEntry.fileOffset = mFileStream->getPosition(); // CompressedFileOffset + fileIndexEntry.dataOffset = mStoredBlocks * mDataBlockSize; // UncompressedOffset + fileIndexEntry.dataSize = storeBlock.size(); // Size of block + // Save file index data + mFileIndex.push_back(fileIndexEntry); + + const unsigned char *uncompressedDataPtr = storeBlock.data(); + size_t remainingBytesToCompress = storeBlock.size(); + + while (remainingBytesToCompress > 0) + { + size_t bytesToCompress = + std::min(remainingBytesToCompress, static_cast(kZlibBufferSize)); + zStream->avail_in = static_cast(bytesToCompress); + zStream->next_in = const_cast(uncompressedDataPtr); + + do + { + zStream->avail_out = kZlibBufferSize; + zStream->next_out = compressBuffer->data(); + + int flushMode = Z_NO_FLUSH; + if (remainingBytesToCompress <= kZlibBufferSize) + { + flushMode = Z_FINISH; + } + deflateStatus = deflate(zStream, flushMode); + if (deflateStatus == Z_STREAM_ERROR) + { + FATAL() << "Error during deflate: Z_STREAM_ERROR"; + } + // This is the compressed data size about to be written + unsigned bytesCompressed = kZlibBufferSize - zStream->avail_out; + mFileStream->write(compressBuffer->data(), bytesCompressed); + } while (zStream->avail_out == 0); + + uncompressedDataPtr += bytesToCompress; + remainingBytesToCompress -= bytesToCompress; + } + } + else + { + mFileStream->write(storeBlock.data(), storeBlock.size()); + } + + mStoredBlocks++; +} + +BinaryFileIndexInfo FrameCaptureBinaryData::closeBinaryDataStore() +{ + mCaptureComplete = true; + storeResidentBlocks(); + + BinaryFileIndexInfo indexInfo; + indexInfo = appendFileIndex(); + clear(); + return indexInfo; +} + +// Sets up binary data loader with config data from the trace fixture +void FrameCaptureBinaryData::configureBinaryDataLoader(bool compression, + size_t blockCount, + size_t blockSize, + size_t residentSize, + size_t indexOffset, + const std::string &fileName) +{ + mIsBinaryDataCompressed = compression; + mFileName = fileName; + mMaxResidentBinarySize = residentSize; + mDataBlockSize = blockSize; + mBlockCount = blockCount; + mMaxResidentBlockIndex = (mMaxResidentBinarySize / mDataBlockSize) - 1; + mCurrentTransientLoadedBlockId = mMaxResidentBlockIndex; + mIndexOffset = indexOffset; +} + +// Setup binary data file access, init index and preload data blocks up to limit +void FrameCaptureBinaryData::initializeBinaryDataLoader() +{ + // Create file stream manager + mFileStream = new FileStream(mFileName.c_str(), Mode::Load); + + // Assemble binary data file/cache index + constructBlockDescIndex(mIndexOffset); + + // Preload binary data blocks up to limit + size_t blocksToPreload = + std::min(mReplayBlockDescriptions.size(), (mMaxResidentBlockIndex + 1)); + for (size_t i = 0; i < blocksToPreload; i++) + { + loadBlock(i); + } + + // Initialize getData cache + updateGetDataCache(0); +} + +// Load a single data block into memory +void FrameCaptureBinaryData::loadBlock(size_t blockId) +{ + std::vector &uncompressedDataBlock = prepareLoadBlock(blockId); + + // Move to start of this data block in the data file + mFileStream->seek(mReplayBlockDescriptions[blockId].fileOffset, kSeekBegin); + + if (mIsBinaryDataCompressed) + { + // Use zlib library, based on example/doc here: https://zlib.net/zlib_how.html + ZLibHelper decompressor(Mode::Load); + z_stream *zStream = decompressor.getStream(); + int inflateStatus = 0; + size_t bytesDecompressed = 0; + + using ZlibBuffer = std::array; + std::unique_ptr compressedDataBuffer(new ZlibBuffer()); + zStream->avail_out = static_cast(mDataBlockSize); + zStream->next_out = uncompressedDataBlock.data(); + + do + { + if (zStream->avail_in == 0) + { + zStream->avail_in = static_cast( + mFileStream->read(compressedDataBuffer->data(), kZlibBufferSize)); + zStream->next_in = compressedDataBuffer->data(); + } + + do + { + int availableOutputSpace = static_cast(mDataBlockSize - mCurrentBlockOffset); + zStream->avail_out = availableOutputSpace; + zStream->next_out = uncompressedDataBlock.data() + mCurrentBlockOffset; + inflateStatus = inflate(zStream, Z_NO_FLUSH); + ASSERT(inflateStatus != Z_STREAM_ERROR); + if (inflateStatus == Z_NEED_DICT || inflateStatus == Z_DATA_ERROR || + inflateStatus == Z_MEM_ERROR) + { + FATAL() << "Zlib inflate failed: " << inflateStatus; + } + bytesDecompressed = availableOutputSpace - zStream->avail_out; + mCurrentBlockOffset += bytesDecompressed; + } while (zStream->avail_out == 0 && mCurrentBlockOffset < mDataBlockSize); + } while (inflateStatus != Z_STREAM_END && mCurrentBlockOffset != mDataBlockSize); + } + else + { + mCurrentBlockOffset = mFileStream->read(uncompressedDataBlock.data(), mDataBlockSize); + } + + // Except for the last block this resize will be a no-op + uncompressedDataBlock.resize(mCurrentBlockOffset); + // Indicate that this block is now loaded + setBlockResident(blockId, uncompressedDataBlock.data()); +} + +void FrameCaptureBinaryData::closeBinaryDataLoader() +{ + clear(); +} + +int FileStreamSeek(FILE *stream, long long offset, int whence) +{ +#if defined(ANGLE_PLATFORM_WINDOWS) + return _fseeki64(stream, offset, whence); +#else + return fseeko(stream, static_cast(offset), whence); +#endif +} + +long long FileStreamTell(FILE *stream) +{ +#if defined(ANGLE_PLATFORM_WINDOWS) + return _ftelli64(stream); +#else + return ftello(stream); +#endif +} + +void FileStream::write(const uint8_t *data, size_t size) +{ + if (fwrite(data, 1, size, mFile) != size) + { + if (ferror(mFile)) + { + FATAL() << "Error writing " << size << " bytes to binary data file."; + } + } + if (fflush(mFile) != 0) + { + FATAL() << "Error flushing data to binary data file."; + } +} + +size_t FileStream::read(uint8_t *buffer, size_t size) +{ + size_t readBytes = fread(buffer, 1, size, mFile); + if (readBytes < size && ferror(mFile)) + { + FATAL() << "Error reading from binary data file."; + } + return readBytes; +} + +void FileStream::seek(long long offset, int whence) +{ + if (FileStreamSeek(mFile, offset, whence) != 0) + { + FATAL() << "Error seeking in binary data file with offset " << offset << " and whence " + << whence; + } +} + +size_t FileStream::getPosition() +{ + long long offset = FileStreamTell(mFile); + if (offset == -1) + { + FATAL() << "Error getting position in binary data file " << mFilePath; + } + angle::CheckedNumeric checkedOffset(offset); + size_t safeOffset = 0; + if (!checkedOffset.AssignIfValid(&safeOffset)) + { + FATAL() << "ANGLE file seek position offset out of range"; + } + + return safeOffset; +} +} // namespace angle diff --git a/src/common/frame_capture_binary_data.h b/src/common/frame_capture_binary_data.h new file mode 100644 index 00000000000..c624a2b393d --- /dev/null +++ b/src/common/frame_capture_binary_data.h @@ -0,0 +1,198 @@ +// +// Copyright 2025 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. +// +// frame_capture_binary_data.h: +// Common code for the ANGLE trace replay large trace binary data definition. +// + +#ifndef FRAME_CAPTURE_BINARY_DATA_H_ +#define FRAME_CAPTURE_BINARY_DATA_H_ + +#include "common/debug.h" + +#include +#include +#include + +namespace angle +{ + +constexpr size_t kDefaultBinaryDataSize = 0x80000000; +constexpr size_t kDefaultDataBlockSize = 256 * 1024 * 1024; +constexpr size_t kBinaryAlignment = 16; +// The zlib doc recommends buffer sizes on the order of 128K or 256K bytes +constexpr size_t kZlibBufferSize = 256 * 1024; +constexpr uint32_t kInvalidBlockId = 0xFFFFFFFF; +constexpr size_t kLongTraceVersionId = 1; + +// Index information ultimately saved in trace JSON file +struct BinaryFileIndexInfo +{ + size_t version; // Long file data description version number + size_t blockSize; // Size of binary data blocks in bytes + size_t blockCount; // Number of FileBlockInfo structures in file index trailer + size_t residentSize; // Max amount of device memory used for binary data storage + size_t indexOffset; // Offset in gzip file specifying start of file block descriptions + BinaryFileIndexInfo() : version(1), blockSize(0), blockCount(0), residentSize(0), indexOffset(0) + {} +}; + +class FileStream; + +class FrameCaptureBinaryData +{ + public: + enum class Mode + { + Load, + Store + }; + + // Describes a block's location in the binary data file + struct FileBlockInfo + { + size_t fileOffset; // Offset within the binary disk file + size_t dataOffset; // Starting offset in the logical flat data view + size_t dataSize; // Actual size of data in this block + + FileBlockInfo() : fileOffset(0), dataOffset(0), dataSize(0) {} + }; + + // Describes a block's state during replay + struct ReplayBlockDescription + { + size_t fileOffset; // Seek offset in binary data disk file + size_t beginDataOffset; // Beginning flat binary data offset + size_t endDataOffset; // Ending flat binary data offset (inclusive) + size_t dataSize; // Size of data in this block + uint8_t *residentAddress; // Memory address if resident, nullptr otherwise + }; + + std::vector> &data() { return mData; } + bool isSwapBlock(size_t blockId) { return blockId == mMaxResidentBlockIndex; } + size_t totalSize() const; + bool isSwapMode() const; + bool isBlockResident(size_t blockId) const; + void setBlockResident(size_t blockId, uint8_t *address); + void setBlockNonResident(size_t blockId); + void setBinaryDataSize(size_t binaryDataSize); + void setBlockSize(size_t blockSize); + + void storeResidentBlocks(); + // Format data for appending to compressed binary file + BinaryFileIndexInfo appendFileIndex(); + // Create binary memory block description index from binary file information + void constructBlockDescIndex(size_t indexOffset); + + size_t append(const void *data, size_t size); + void clear(); + const uint8_t *getData(size_t offset); + + void initializeBinaryDataStore(bool compression, + const std::string &outDir, + const std::string &fileName); + void storeBlock(); + BinaryFileIndexInfo closeBinaryDataStore(); + void configureBinaryDataLoader(bool compression, + size_t blockCount, + size_t blockSize, + size_t residentSize, + size_t indexOffset, + const std::string &fileName); + void initializeBinaryDataLoader(); + void loadBlock(size_t blockId); + void closeBinaryDataLoader(); + void updateGetDataCache(size_t blockId); + std::vector &prepareLoadBlock(size_t blockId); + std::vector &prepareStoreBlock(size_t blockId); + + private: + bool mIsBinaryDataCompressed; + std::string mFileName; + size_t mIndexOffset = 0; + + std::vector mFileIndex; + + uint32_t mStoredBlocks = 0; + size_t mCurrentTransientLoadedBlockId = kInvalidBlockId; + size_t mCurrentBlockOffset = 0; + size_t mMaxResidentBinarySize = kDefaultBinaryDataSize; + size_t mMaxResidentBlockIndex = (kDefaultBinaryDataSize / kDefaultDataBlockSize) - 1; + + // Binary data information + size_t mDataBlockSize = kDefaultDataBlockSize; + size_t mBlockCount = 0; + + // getData() fastpath cache information + size_t mCacheBlockId = kInvalidBlockId; + size_t mCacheBlockBeginOffset = 0; + size_t mCacheBlockEndOffset = 0; + uint8_t *mCacheBlockBaseAddress = nullptr; + + std::vector mReplayBlockDescriptions; + + // Chrome's allocator disallows creating one allocation that's bigger than 2GB, so the following + // is one large buffer that is split in multiple pieces in memory. + // Note: Make sure compression on write is disabled with a Chrome capture + // (ANGLE_CAPTURE_COMPRESSION=0), since that would require bundling all data in one big + // allocation. + std::vector> mData; + // Indicator that capture is complete and store can be finalized + bool mCaptureComplete = false; + + FileStream *mFileStream = nullptr; +}; + +constexpr int kSeekBegin = SEEK_SET; +constexpr int kSeekEnd = SEEK_END; + +class FileStream +{ + public: + explicit FileStream(const std::string &filePath, FrameCaptureBinaryData::Mode mode) + : mMode(mode), mFile(nullptr), mFilePath(filePath) + { + std::string openMode; + if (mMode == FrameCaptureBinaryData::Mode::Store) + { + openMode = "wb+"; + } + else if (mMode == FrameCaptureBinaryData::Mode::Load) + { + openMode = "rb"; + } + else + { + FATAL() << "Invalid Mode enum in FileStream helper"; + } + mFile = fopen(mFilePath.c_str(), openMode.c_str()); + + if (!mFile) + { + FATAL() << "Could not open binary data file " << mFilePath; + } + } + + ~FileStream() + { + if (mFile) + { + fclose(mFile); + mFile = nullptr; + } + } + + void write(const uint8_t *data, size_t size); + size_t read(uint8_t *buffer, size_t size); + void seek(long long offset, int whence); + size_t getPosition(); + + private: + FrameCaptureBinaryData::Mode mMode; + FILE *mFile; + std::string mFilePath; +}; +} // namespace angle +#endif // FRAME_CAPTURE_BINARY_DATA_H_ diff --git a/src/common/frame_capture_utils.cpp b/src/common/frame_capture_utils.cpp index c6a51afa8ba..d45c1ac69ea 100644 --- a/src/common/frame_capture_utils.cpp +++ b/src/common/frame_capture_utils.cpp @@ -7,6 +7,10 @@ // ANGLE Frame capture common classes. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/frame_capture_utils.h" namespace angle @@ -27,16 +31,13 @@ ParamCapture::ParamCapture(const char *nameIn, ParamType typeIn) : name(nameIn), type(typeIn), enumGroup(gl::GLESEnum::AllEnums), - bigGLEnum(gl::BigGLEnum::AllEnums), uniqueID(nextID++) {} ParamCapture::~ParamCapture() = default; ParamCapture::ParamCapture(ParamCapture &&other) - : type(ParamType::TGLenum), - enumGroup(gl::GLESEnum::AllEnums), - bigGLEnum(gl::BigGLEnum::AllEnums) + : type(ParamType::TGLenum), enumGroup(gl::GLESEnum::AllEnums) { *this = std::move(other); } @@ -47,7 +48,6 @@ ParamCapture &ParamCapture::operator=(ParamCapture &&other) std::swap(type, other.type); std::swap(value, other.value); std::swap(enumGroup, other.enumGroup); - std::swap(bigGLEnum, other.bigGLEnum); std::swap(data, other.data); std::swap(arrayClientPointerIndex, other.arrayClientPointerIndex); std::swap(readBufferSizeBytes, other.readBufferSizeBytes); @@ -196,7 +196,7 @@ void WriteParamValueReplay(std::ostream &os, os << "GL_FALSE"; break; default: - os << "0x" << std::hex << std::uppercase << GLint(value); + os << "0x" << std::hex << std::uppercase << GLint(value) << std::dec; } } @@ -466,7 +466,7 @@ void WriteParamValueReplay(std::ostream &os, } else { - os << "gCurrentProgram"; + os << "gCurrentProgramPerContext[gCurrentContext]"; } os << "][" << value.value << "]"; @@ -679,7 +679,7 @@ void WriteParamValueReplay(std::ostream &os, } else { - os << NULL; + os << "NULL"; } } diff --git a/src/common/frame_capture_utils.h b/src/common/frame_capture_utils.h index 821c8ce7803..d83b7c39021 100644 --- a/src/common/frame_capture_utils.h +++ b/src/common/frame_capture_utils.h @@ -73,7 +73,6 @@ struct ParamCapture : angle::NonCopyable ParamType type; ParamValue value; gl::GLESEnum enumGroup; // only used for param type GLenum, GLboolean and GLbitfield - gl::BigGLEnum bigGLEnum; // only used for param type GLenum, GLboolean and GLbitfield ParamData data; int dataNElements = 0; int arrayClientPointerIndex = -1; @@ -102,11 +101,6 @@ class ParamBuffer final : angle::NonCopyable gl::GLESEnum enumGroup, ParamType paramType, T paramValue); - template - void addEnumParam(const char *paramName, - gl::BigGLEnum enumGroup, - ParamType paramType, - T paramValue); template void addUnnamedParam(ParamType paramType, T paramValue); @@ -193,18 +187,6 @@ void ParamBuffer::addEnumParam(const char *paramName, mParamCaptures.emplace_back(std::move(capture)); } -template -void ParamBuffer::addEnumParam(const char *paramName, - gl::BigGLEnum enumGroup, - ParamType paramType, - T paramValue) -{ - ParamCapture capture(paramName, paramType); - InitParamValue(paramType, paramValue, &capture.value); - capture.bigGLEnum = enumGroup; - mParamCaptures.emplace_back(std::move(capture)); -} - template void ParamBuffer::addUnnamedParam(ParamType paramType, T paramValue) { diff --git a/src/common/frame_capture_utils_autogen.cpp b/src/common/frame_capture_utils_autogen.cpp index 0606442008b..af5cf356d9c 100644 --- a/src/common/frame_capture_utils_autogen.cpp +++ b/src/common/frame_capture_utils_autogen.cpp @@ -55,6 +55,9 @@ void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const Pa case ParamType::TClipOrigin: WriteParamValueReplay(os, call, param.value.ClipOriginVal); break; + case ParamType::TCombinerOp: + WriteParamValueReplay(os, call, param.value.CombinerOpVal); + break; case ParamType::TCompositorTiming: WriteParamValueReplay(os, call, param.value.CompositorTimingVal); @@ -109,10 +112,6 @@ void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const Pa case ParamType::TEGLDisplay: WriteParamValueReplay(os, call, param.value.EGLDisplayVal); break; - case ParamType::TEGLFrameTokenANGLE: - WriteParamValueReplay( - os, call, param.value.EGLFrameTokenANGLEVal); - break; case ParamType::TEGLGetBlobFuncANDROID: WriteParamValueReplay( os, call, param.value.EGLGetBlobFuncANDROIDVal); @@ -502,6 +501,9 @@ void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const Pa case ParamType::TShadingModel: WriteParamValueReplay(os, call, param.value.ShadingModelVal); break; + case ParamType::TShadingRate: + WriteParamValueReplay(os, call, param.value.ShadingRateVal); + break; case ParamType::TSurfaceID: WriteParamValueReplay(os, call, param.value.SurfaceIDVal); break; @@ -781,6 +783,10 @@ void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const Pa WriteParamValueReplay( os, call, param.value.cl_image_formatPointerVal); break; + case ParamType::Tcl_import_properties_armConstPointer: + WriteParamValueReplay( + os, call, param.value.cl_import_properties_armConstPointerVal); + break; case ParamType::Tcl_int: WriteParamValueReplay(os, call, param.value.cl_intVal); break; @@ -905,6 +911,8 @@ const char *ParamTypeToString(ParamType paramType) return "GLenum"; case ParamType::TClipOrigin: return "GLenum"; + case ParamType::TCombinerOp: + return "GLenum"; case ParamType::TCompositorTiming: return "GLenum"; case ParamType::TContextID: @@ -935,8 +943,6 @@ const char *ParamTypeToString(ParamType paramType) return "EGLDeviceEXT"; case ParamType::TEGLDisplay: return "EGLDisplay"; - case ParamType::TEGLFrameTokenANGLE: - return "EGLFrameTokenANGLE"; case ParamType::TEGLGetBlobFuncANDROID: return "EGLGetBlobFuncANDROID"; case ParamType::TEGLImage: @@ -1153,6 +1159,8 @@ const char *ParamTypeToString(ParamType paramType) return "GLenum"; case ParamType::TShadingModel: return "GLenum"; + case ParamType::TShadingRate: + return "GLenum"; case ParamType::TSurfaceID: return "GLuint"; case ParamType::TSyncID: @@ -1305,6 +1313,8 @@ const char *ParamTypeToString(ParamType paramType) return "const cl_image_format *"; case ParamType::Tcl_image_formatPointer: return "cl_image_format *"; + case ParamType::Tcl_import_properties_armConstPointer: + return "const cl_import_properties_arm *"; case ParamType::Tcl_int: return "cl_int"; case ParamType::Tcl_intPointer: diff --git a/src/common/frame_capture_utils_autogen.h b/src/common/frame_capture_utils_autogen.h index b9b01716139..7a68c69caa5 100644 --- a/src/common/frame_capture_utils_autogen.h +++ b/src/common/frame_capture_utils_autogen.h @@ -46,6 +46,7 @@ enum class ParamType TClientVertexArrayType, TClipDepthMode, TClipOrigin, + TCombinerOp, TCommandQueueInfo, TCommandQueueProperties, TCompositorTiming, @@ -66,7 +67,6 @@ enum class ParamType TEGLDEBUGPROCKHR, TEGLDeviceEXT, TEGLDisplay, - TEGLFrameTokenANGLE, TEGLGetBlobFuncANDROID, TEGLImage, TEGLImageKHR, @@ -195,6 +195,7 @@ enum class ParamType TShaderProgramIDPointer, TShaderType, TShadingModel, + TShadingRate, TSurfaceID, TSyncID, TTextureEnvParameter, @@ -236,6 +237,7 @@ enum class ParamType Tcl_image_descConstPointer, Tcl_image_formatConstPointer, Tcl_image_formatPointer, + Tcl_import_properties_armConstPointer, Tcl_int, Tcl_intPointer, Tcl_kernel, @@ -272,7 +274,7 @@ enum class ParamType TvoidPointerPointer, }; -constexpr uint32_t kParamTypeCount = 235; +constexpr uint32_t kParamTypeCount = 237; union ParamValue { @@ -288,6 +290,7 @@ union ParamValue gl::ClientVertexArrayType ClientVertexArrayTypeVal; gl::ClipDepthMode ClipDepthModeVal; gl::ClipOrigin ClipOriginVal; + gl::CombinerOp CombinerOpVal; egl::CompositorTiming CompositorTimingVal; gl::ContextID ContextIDVal; gl::CullFaceMode CullFaceModeVal; @@ -303,7 +306,6 @@ union ParamValue EGLDEBUGPROCKHR EGLDEBUGPROCKHRVal; EGLDeviceEXT EGLDeviceEXTVal; EGLDisplay EGLDisplayVal; - EGLFrameTokenANGLE EGLFrameTokenANGLEVal; EGLGetBlobFuncANDROID EGLGetBlobFuncANDROIDVal; EGLImage EGLImageVal; EGLImageKHR EGLImageKHRVal; @@ -412,6 +414,7 @@ union ParamValue gl::ShaderProgramID *ShaderProgramIDPointerVal; gl::ShaderType ShaderTypeVal; gl::ShadingModel ShadingModelVal; + gl::ShadingRate ShadingRateVal; egl::SurfaceID SurfaceIDVal; gl::SyncID SyncIDVal; gl::TextureEnvParameter TextureEnvParameterVal; @@ -492,6 +495,7 @@ union ParamValue const cl_image_desc *cl_image_descConstPointerVal; const cl_image_format *cl_image_formatConstPointerVal; cl_image_format *cl_image_formatPointerVal; + const cl_import_properties_arm *cl_import_properties_armConstPointerVal; cl_int cl_intVal; cl_int *cl_intPointerVal; cl_kernel cl_kernelVal; @@ -588,6 +592,12 @@ inline gl::ClipOrigin GetParamVal(const return value.ClipOriginVal; } +template <> +inline gl::CombinerOp GetParamVal(const ParamValue &value) +{ + return value.CombinerOpVal; +} + template <> inline egl::CompositorTiming GetParamVal( const ParamValue &value) @@ -685,13 +695,6 @@ inline EGLDisplay GetParamVal(const ParamVal return value.EGLDisplayVal; } -template <> -inline EGLFrameTokenANGLE GetParamVal( - const ParamValue &value) -{ - return value.EGLFrameTokenANGLEVal; -} - template <> inline EGLGetBlobFuncANDROID GetParamVal( const ParamValue &value) @@ -1398,6 +1401,13 @@ inline gl::ShadingModel GetParamVal( return value.ShadingModelVal; } +template <> +inline gl::ShadingRate GetParamVal( + const ParamValue &value) +{ + return value.ShadingRateVal; +} + template <> inline egl::SurfaceID GetParamVal(const ParamValue &value) { @@ -1931,6 +1941,14 @@ inline cl_image_format *GetParamVal +inline const cl_import_properties_arm * +GetParamVal( + const ParamValue &value) +{ + return value.cl_import_properties_armConstPointerVal; +} + template <> inline cl_int GetParamVal(const ParamValue &value) { @@ -2112,6 +2130,8 @@ T AccessParamValue(ParamType paramType, const ParamValue &value) return GetParamVal(value); case ParamType::TClipOrigin: return GetParamVal(value); + case ParamType::TCombinerOp: + return GetParamVal(value); case ParamType::TCommandQueueInfo: return GetParamVal(value); case ParamType::TCommandQueueProperties: @@ -2152,8 +2172,6 @@ T AccessParamValue(ParamType paramType, const ParamValue &value) return GetParamVal(value); case ParamType::TEGLDisplay: return GetParamVal(value); - case ParamType::TEGLFrameTokenANGLE: - return GetParamVal(value); case ParamType::TEGLGetBlobFuncANDROID: return GetParamVal(value); case ParamType::TEGLImage: @@ -2410,6 +2428,8 @@ T AccessParamValue(ParamType paramType, const ParamValue &value) return GetParamVal(value); case ParamType::TShadingModel: return GetParamVal(value); + case ParamType::TShadingRate: + return GetParamVal(value); case ParamType::TSurfaceID: return GetParamVal(value); case ParamType::TSyncID: @@ -2492,6 +2512,8 @@ T AccessParamValue(ParamType paramType, const ParamValue &value) return GetParamVal(value); case ParamType::Tcl_image_formatPointer: return GetParamVal(value); + case ParamType::Tcl_import_properties_armConstPointer: + return GetParamVal(value); case ParamType::Tcl_int: return GetParamVal(value); case ParamType::Tcl_intPointer: @@ -2631,6 +2653,12 @@ inline void SetParamVal(gl::ClipOrigin valueIn, ParamVal valueOut->ClipOriginVal = valueIn; } +template <> +inline void SetParamVal(gl::CombinerOp valueIn, ParamValue *valueOut) +{ + valueOut->CombinerOpVal = valueIn; +} + template <> inline void SetParamVal(egl::CompositorTiming valueIn, ParamValue *valueOut) @@ -2725,13 +2753,6 @@ inline void SetParamVal(EGLDisplay valueIn, ParamValue * valueOut->EGLDisplayVal = valueIn; } -template <> -inline void SetParamVal(EGLFrameTokenANGLE valueIn, - ParamValue *valueOut) -{ - valueOut->EGLFrameTokenANGLEVal = valueIn; -} - template <> inline void SetParamVal(EGLGetBlobFuncANDROID valueIn, ParamValue *valueOut) @@ -3424,6 +3445,12 @@ inline void SetParamVal(gl::ShadingModel valueIn, Para valueOut->ShadingModelVal = valueIn; } +template <> +inline void SetParamVal(gl::ShadingRate valueIn, ParamValue *valueOut) +{ + valueOut->ShadingRateVal = valueIn; +} + template <> inline void SetParamVal(egl::SurfaceID valueIn, ParamValue *valueOut) { @@ -3940,6 +3967,14 @@ inline void SetParamVal(cl_image_format *val valueOut->cl_image_formatPointerVal = valueIn; } +template <> +inline void SetParamVal( + const cl_import_properties_arm *valueIn, + ParamValue *valueOut) +{ + valueOut->cl_import_properties_armConstPointerVal = valueIn; +} + template <> inline void SetParamVal(cl_int valueIn, ParamValue *valueOut) { @@ -4132,6 +4167,9 @@ void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut) case ParamType::TClipOrigin: SetParamVal(valueIn, valueOut); break; + case ParamType::TCombinerOp: + SetParamVal(valueIn, valueOut); + break; case ParamType::TCommandQueueInfo: SetParamVal(valueIn, valueOut); break; @@ -4192,9 +4230,6 @@ void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut) case ParamType::TEGLDisplay: SetParamVal(valueIn, valueOut); break; - case ParamType::TEGLFrameTokenANGLE: - SetParamVal(valueIn, valueOut); - break; case ParamType::TEGLGetBlobFuncANDROID: SetParamVal(valueIn, valueOut); break; @@ -4579,6 +4614,9 @@ void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut) case ParamType::TShadingModel: SetParamVal(valueIn, valueOut); break; + case ParamType::TShadingRate: + SetParamVal(valueIn, valueOut); + break; case ParamType::TSurfaceID: SetParamVal(valueIn, valueOut); break; @@ -4702,6 +4740,9 @@ void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut) case ParamType::Tcl_image_formatPointer: SetParamVal(valueIn, valueOut); break; + case ParamType::Tcl_import_properties_armConstPointer: + SetParamVal(valueIn, valueOut); + break; case ParamType::Tcl_int: SetParamVal(valueIn, valueOut); break; diff --git a/src/common/gl_enum_utils.cpp b/src/common/gl_enum_utils.cpp index 59be8c8074e..3b0e45553ec 100644 --- a/src/common/gl_enum_utils.cpp +++ b/src/common/gl_enum_utils.cpp @@ -93,11 +93,6 @@ void OutputGLenumString(std::ostream &out, GLESEnum enumGroup, unsigned int valu return OutputGLenumStringImpl(out, enumGroup, value); } -void OutputGLenumString(std::ostream &out, BigGLEnum enumGroup, unsigned int value) -{ - return OutputGLenumStringImpl(out, enumGroup, value); -} - void OutputGLbitfieldString(std::ostream &out, GLESEnum enumGroup, unsigned int value) { out << GLbitfieldToString(enumGroup, value); @@ -113,11 +108,6 @@ std::string GLbitfieldToString(GLESEnum enumGroup, unsigned int value) return GLbitfieldToStringImpl(enumGroup, value); } -std::string GLbitfieldToString(BigGLEnum enumGroup, unsigned int value) -{ - return GLbitfieldToStringImpl(enumGroup, value); -} - const char *GLinternalFormatToString(unsigned int format) { return GLenumToString(gl::GLESEnum::InternalFormat, format); diff --git a/src/common/gl_enum_utils.h b/src/common/gl_enum_utils.h index b3ca8e2e899..611ab82adb9 100644 --- a/src/common/gl_enum_utils.h +++ b/src/common/gl_enum_utils.h @@ -18,11 +18,8 @@ namespace gl { const char *GLbooleanToString(unsigned int value); const char *GLenumToString(GLESEnum enumGroup, unsigned int value); -const char *GLenumToString(BigGLEnum enumGroup, unsigned int value); std::string GLbitfieldToString(GLESEnum enumGroup, unsigned int value); -std::string GLbitfieldToString(BigGLEnum enumGroup, unsigned int value); void OutputGLenumString(std::ostream &out, GLESEnum enumGroup, unsigned int value); -void OutputGLenumString(std::ostream &out, BigGLEnum enumGroup, unsigned int value); void OutputGLbitfieldString(std::ostream &out, GLESEnum enumGroup, unsigned int value); const char *GLinternalFormatToString(unsigned int format); unsigned int StringToGLenum(const char *str); diff --git a/src/common/gl_enum_utils_autogen.cpp b/src/common/gl_enum_utils_autogen.cpp index 416b30b2909..58bc6c4cbc3 100644 --- a/src/common/gl_enum_utils_autogen.cpp +++ b/src/common/gl_enum_utils_autogen.cpp @@ -2126,8 +2126,12 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM"; case 0x8F69: return "GL_TEXTURE_ASTC_DECODE_PRECISION_EXT"; + case 0x8F6A: + return "GL_TEXTURE_UNNORMALIZED_COORDINATES_ARM"; case 0x8F6E: return "GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT"; + case 0x8F6F: + return "GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT"; case 0x8F94: return "GL_R8_SNORM"; case 0x8F95: @@ -2783,17 +2787,23 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) case 0x96A5: return "GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM"; case 0x96A6: - return "GL_SHADING_RATE_1X1_PIXELS_QCOM"; + return "GL_SHADING_RATE_1X1_PIXELS_EXT"; case 0x96A7: - return "GL_SHADING_RATE_1X2_PIXELS_QCOM"; + return "GL_SHADING_RATE_1X2_PIXELS_EXT"; case 0x96A8: - return "GL_SHADING_RATE_2X1_PIXELS_QCOM"; + return "GL_SHADING_RATE_2X1_PIXELS_EXT"; case 0x96A9: - return "GL_SHADING_RATE_2X2_PIXELS_QCOM"; + return "GL_SHADING_RATE_2X2_PIXELS_EXT"; + case 0x96AA: + return "GL_SHADING_RATE_1X4_PIXELS_EXT"; + case 0x96AB: + return "GL_SHADING_RATE_4X1_PIXELS_EXT"; case 0x96AC: - return "GL_SHADING_RATE_4X2_PIXELS_QCOM"; + return "GL_SHADING_RATE_4X2_PIXELS_EXT"; + case 0x96AD: + return "GL_SHADING_RATE_2X4_PIXELS_EXT"; case 0x96AE: - return "GL_SHADING_RATE_4X4_PIXELS_QCOM"; + return "GL_SHADING_RATE_4X4_PIXELS_EXT"; case 0x96B0: return "GL_SERIALIZED_CONTEXT_STRING_ANGLE"; case 0x96B1: @@ -2850,35 +2860,67 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_SURFACE_COMPRESSION_FIXED_RATE_11BPC_EXT"; case 0x96CF: return "GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT"; + case 0x96D0: + return "GL_SHADING_RATE_EXT"; + case 0x96D1: + return "GL_SHADING_RATE_ATTACHMENT_EXT"; + case 0x96D2: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT"; + case 0x96D3: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT"; + case 0x96D4: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT"; + case 0x96D5: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT"; + case 0x96D6: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT"; + case 0x96D7: + return "GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT"; + case 0x96D8: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT"; + case 0x96D9: + return "GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT"; + case 0x96DA: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT"; + case 0x96DB: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT"; + case 0x96DC: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT"; + case 0x96DD: + return "GL_FRAGMENT_SHADING_RATE_WITH_SHADER_DEPTH_STENCIL_WRITES_SUPPORTED_" + "EXT"; + case 0x96DE: + return "GL_FRAGMENT_SHADING_RATE_WITH_SAMPLE_MASK_SUPPORTED_EXT"; + case 0x96DF: + return "GL_FRAGMENT_SHADING_RATE_ATTACHMENT_WITH_DEFAULT_FRAMEBUFFER_SUPPORTED_" + "EXT"; case 0x96E0: return "GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE"; case 0x96E1: - return "GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE"; - case 0x96E2: return "GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE"; - case 0x96E3: + case 0x96E2: return "GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE"; - case 0x96E4: + case 0x96E3: return "GL_LOAD_OP_ZERO_ANGLE"; - case 0x96E5: + case 0x96E4: return "GL_LOAD_OP_CLEAR_ANGLE"; - case 0x96E6: + case 0x96E5: return "GL_LOAD_OP_LOAD_ANGLE"; - case 0x96E7: + case 0x96E6: return "GL_STORE_OP_STORE_ANGLE"; - case 0x96E8: + case 0x96E7: return "GL_PIXEL_LOCAL_FORMAT_ANGLE"; - case 0x96E9: + case 0x96E8: return "GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE"; - case 0x96EA: + case 0x96E9: return "GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE"; - case 0x96EB: + case 0x96EA: return "GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE"; - case 0x96EC: + case 0x96EB: return "GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE"; - case 0x96ED: + case 0x96EC: return "GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE"; - case 0x96EE: + case 0x96ED: return "GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE"; case 0x9EA0: return "GL_RENDERABILITY_VALIDATION_ANGLE"; @@ -3645,10 +3687,16 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_BYTE"; case 0x1401: return "GL_UNSIGNED_BYTE"; + case 0x1402: + return "GL_SHORT"; case 0x1403: return "GL_UNSIGNED_SHORT"; + case 0x1404: + return "GL_INT"; case 0x1405: return "GL_UNSIGNED_INT"; + case 0x1406: + return "GL_FLOAT"; default: return UnknownEnumToString(value); } @@ -4523,6 +4571,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_DEPTH_ATTACHMENT"; case 0x8D20: return "GL_STENCIL_ATTACHMENT"; + case 0x96D1: + return "GL_SHADING_RATE_ATTACHMENT_EXT"; default: return UnknownEnumToString(value); } @@ -5171,6 +5221,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_FETCH_PER_SAMPLE_ARM"; case 0x8F66: return "GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM"; + case 0x8F6F: + return "GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT"; case 0x90D3: return "GL_SHADER_STORAGE_BUFFER_BINDING"; case 0x90D4: @@ -5257,6 +5309,28 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_DRIVER_UUID_EXT"; case 0x96A4: return "GL_SHADING_RATE_QCOM"; + case 0x96D0: + return "GL_SHADING_RATE_EXT"; + case 0x96D7: + return "GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT"; + case 0x96D8: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT"; + case 0x96D9: + return "GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT"; + case 0x96DA: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT"; + case 0x96DB: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT"; + case 0x96DC: + return "GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT"; + case 0x96DD: + return "GL_FRAGMENT_SHADING_RATE_WITH_SHADER_DEPTH_STENCIL_WRITES_SUPPORTED_" + "EXT"; + case 0x96DE: + return "GL_FRAGMENT_SHADING_RATE_WITH_SAMPLE_MASK_SUPPORTED_EXT"; + case 0x96DF: + return "GL_FRAGMENT_SHADING_RATE_ATTACHMENT_WITH_DEFAULT_FRAMEBUFFER_SUPPORTED_" + "EXT"; default: return UnknownEnumToString(value); } @@ -5315,6 +5389,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_NORMAL_MAP_OES"; case 0x8512: return "GL_REFLECTION_MAP_OES"; + case 0x8F6A: + return "GL_TEXTURE_UNNORMALIZED_COORDINATES_ARM"; case 0x96C0: return "GL_SURFACE_COMPRESSION_EXT"; default: @@ -5923,6 +5999,12 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) { switch (value) { + case 0x1200: + return "GL_AMBIENT"; + case 0x1201: + return "GL_DIFFUSE"; + case 0x1202: + return "GL_SPECULAR"; case 0x1203: return "GL_POSITION"; case 0x1204: @@ -6197,7 +6279,7 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) { switch (value) { - case 0x96EC: + case 0x96EB: return "GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE"; default: return UnknownEnumToString(value); @@ -6208,17 +6290,17 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) { switch (value) { - case 0x96E8: + case 0x96E7: return "GL_PIXEL_LOCAL_FORMAT_ANGLE"; - case 0x96E9: + case 0x96E8: return "GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE"; - case 0x96EA: + case 0x96E9: return "GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE"; - case 0x96EB: + case 0x96EA: return "GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE"; - case 0x96ED: + case 0x96EC: return "GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE"; - case 0x96EE: + case 0x96ED: return "GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE"; default: return UnknownEnumToString(value); @@ -6910,6 +6992,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_TEXTURE_MIN_LOD"; case 0x813B: return "GL_TEXTURE_MAX_LOD"; + case 0x8F6A: + return "GL_TEXTURE_UNNORMALIZED_COORDINATES_ARM"; default: return UnknownEnumToString(value); } @@ -6933,6 +7017,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_TEXTURE_COMPARE_MODE"; case 0x884D: return "GL_TEXTURE_COMPARE_FUNC"; + case 0x8F6A: + return "GL_TEXTURE_UNNORMALIZED_COORDINATES_ARM"; default: return UnknownEnumToString(value); } @@ -7021,6 +7107,52 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) } } + case GLESEnum::ShadingRate: + { + switch (value) + { + case 0x96A6: + return "GL_SHADING_RATE_1X1_PIXELS_EXT"; + case 0x96A7: + return "GL_SHADING_RATE_1X2_PIXELS_EXT"; + case 0x96A8: + return "GL_SHADING_RATE_2X1_PIXELS_EXT"; + case 0x96A9: + return "GL_SHADING_RATE_2X2_PIXELS_EXT"; + case 0x96AA: + return "GL_SHADING_RATE_1X4_PIXELS_EXT"; + case 0x96AB: + return "GL_SHADING_RATE_4X1_PIXELS_EXT"; + case 0x96AC: + return "GL_SHADING_RATE_4X2_PIXELS_EXT"; + case 0x96AD: + return "GL_SHADING_RATE_2X4_PIXELS_EXT"; + case 0x96AE: + return "GL_SHADING_RATE_4X4_PIXELS_EXT"; + default: + return UnknownEnumToString(value); + } + } + + case GLESEnum::ShadingRateCombinerOp: + { + switch (value) + { + case 0x96D2: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT"; + case 0x96D3: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT"; + case 0x96D4: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT"; + case 0x96D5: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT"; + case 0x96D6: + return "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT"; + default: + return UnknownEnumToString(value); + } + } + case GLESEnum::ShadingRateQCOM: { switch (value) @@ -7615,10 +7747,14 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_ADD"; case 0xBE2: return "GL_BLEND"; + case 0x1E01: + return "GL_REPLACE"; case 0x2100: return "GL_MODULATE"; case 0x2101: return "GL_DECAL"; + case 0x8570: + return "GL_COMBINE"; default: return UnknownEnumToString(value); } @@ -7628,6 +7764,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) { switch (value) { + case 0xD1C: + return "GL_ALPHA_SCALE"; case 0x2200: return "GL_TEXTURE_ENV_MODE"; case 0x2201: @@ -7814,6 +7952,8 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) return "GL_TEXTURE_SWIZZLE_B"; case 0x8E45: return "GL_TEXTURE_SWIZZLE_A"; + case 0x8F6A: + return "GL_TEXTURE_UNNORMALIZED_COORDINATES_ARM"; case 0x90EA: return "GL_DEPTH_STENCIL_TEXTURE_MODE"; case 0x9580: @@ -7962,8 +8102,6 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) { switch (value) { - case 0x2703: - return "GL_LINEAR_MIPMAP_LINEAR"; case 0x2901: return "GL_REPEAT"; case 0x812D: @@ -8391,33 +8529,6 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) } } - case GLESEnum::VertexBufferObjectUsage: - { - switch (value) - { - case 0x88E0: - return "GL_STREAM_DRAW"; - case 0x88E1: - return "GL_STREAM_READ"; - case 0x88E2: - return "GL_STREAM_COPY"; - case 0x88E4: - return "GL_STATIC_DRAW"; - case 0x88E5: - return "GL_STATIC_READ"; - case 0x88E6: - return "GL_STATIC_COPY"; - case 0x88E8: - return "GL_DYNAMIC_DRAW"; - case 0x88E9: - return "GL_DYNAMIC_READ"; - case 0x88EA: - return "GL_DYNAMIC_COPY"; - default: - return UnknownEnumToString(value); - } - } - case GLESEnum::VertexPointerType: { switch (value) @@ -8511,10632 +8622,6 @@ const char *GLenumToString(GLESEnum enumGroup, unsigned int value) } } -const char *GLenumToString(BigGLEnum enumGroup, unsigned int value) -{ - switch (enumGroup) - { - case BigGLEnum::AccumOp: - { - switch (value) - { - case 0x100: - return "GL_ACCUM"; - case 0x101: - return "GL_LOAD"; - case 0x102: - return "GL_RETURN"; - case 0x103: - return "GL_MULT"; - case 0x104: - return "GL_ADD"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::AllEnums: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x1: - return "GL_ONE"; - case 0x2: - return "GL_LINE_LOOP"; - case 0x3: - return "GL_LINE_STRIP"; - case 0x4: - return "GL_LINE_BIT"; - case 0x5: - return "GL_TRIANGLE_STRIP"; - case 0x6: - return "GL_TRIANGLE_FAN"; - case 0x7: - return "GL_QUADS"; - case 0x8: - return "GL_QUAD_STRIP"; - case 0x9: - return "GL_POLYGON"; - case 0xA: - return "GL_LINES_ADJACENCY"; - case 0xB: - return "GL_LINE_STRIP_ADJACENCY"; - case 0xC: - return "GL_TRIANGLES_ADJACENCY"; - case 0xD: - return "GL_TRIANGLE_STRIP_ADJACENCY"; - case 0xE: - return "GL_PATCHES"; - case 0x10: - return "GL_POLYGON_STIPPLE_BIT"; - case 0x16: - return "GL_UUID_SIZE_EXT"; - case 0x20: - return "GL_PIXEL_MODE_BIT"; - case 0x40: - return "GL_LIGHTING_BIT"; - case 0x80: - return "GL_FOG_BIT"; - case 0x100: - return "GL_ACCUM"; - case 0x101: - return "GL_LOAD"; - case 0x102: - return "GL_RETURN"; - case 0x103: - return "GL_MULT"; - case 0x104: - return "GL_ADD"; - case 0x200: - return "GL_NEVER"; - case 0x201: - return "GL_LESS"; - case 0x202: - return "GL_EQUAL"; - case 0x203: - return "GL_LEQUAL"; - case 0x204: - return "GL_GREATER"; - case 0x205: - return "GL_NOTEQUAL"; - case 0x206: - return "GL_GEQUAL"; - case 0x207: - return "GL_ALWAYS"; - case 0x300: - return "GL_SRC_COLOR"; - case 0x301: - return "GL_ONE_MINUS_SRC_COLOR"; - case 0x302: - return "GL_SRC_ALPHA"; - case 0x303: - return "GL_ONE_MINUS_SRC_ALPHA"; - case 0x304: - return "GL_DST_ALPHA"; - case 0x305: - return "GL_ONE_MINUS_DST_ALPHA"; - case 0x306: - return "GL_DST_COLOR"; - case 0x307: - return "GL_ONE_MINUS_DST_COLOR"; - case 0x308: - return "GL_SRC_ALPHA_SATURATE"; - case 0x400: - return "GL_FRONT_LEFT"; - case 0x401: - return "GL_FRONT_RIGHT"; - case 0x402: - return "GL_BACK_LEFT"; - case 0x403: - return "GL_BACK_RIGHT"; - case 0x404: - return "GL_FRONT"; - case 0x405: - return "GL_BACK"; - case 0x406: - return "GL_LEFT"; - case 0x407: - return "GL_RIGHT"; - case 0x408: - return "GL_FRONT_AND_BACK"; - case 0x409: - return "GL_AUX0"; - case 0x40A: - return "GL_AUX1"; - case 0x40B: - return "GL_AUX2"; - case 0x40C: - return "GL_AUX3"; - case 0x500: - return "GL_INVALID_ENUM"; - case 0x501: - return "GL_INVALID_VALUE"; - case 0x502: - return "GL_INVALID_OPERATION"; - case 0x503: - return "GL_STACK_OVERFLOW"; - case 0x504: - return "GL_STACK_UNDERFLOW"; - case 0x505: - return "GL_OUT_OF_MEMORY"; - case 0x506: - return "GL_INVALID_FRAMEBUFFER_OPERATION"; - case 0x507: - return "GL_CONTEXT_LOST"; - case 0x600: - return "GL_2D"; - case 0x601: - return "GL_3D"; - case 0x602: - return "GL_3D_COLOR"; - case 0x603: - return "GL_3D_COLOR_TEXTURE"; - case 0x604: - return "GL_4D_COLOR_TEXTURE"; - case 0x700: - return "GL_PASS_THROUGH_TOKEN"; - case 0x701: - return "GL_POINT_TOKEN"; - case 0x702: - return "GL_LINE_TOKEN"; - case 0x703: - return "GL_POLYGON_TOKEN"; - case 0x704: - return "GL_BITMAP_TOKEN"; - case 0x705: - return "GL_DRAW_PIXEL_TOKEN"; - case 0x706: - return "GL_COPY_PIXEL_TOKEN"; - case 0x707: - return "GL_LINE_RESET_TOKEN"; - case 0x800: - return "GL_EXP"; - case 0x801: - return "GL_EXP2"; - case 0x900: - return "GL_CW"; - case 0x901: - return "GL_CCW"; - case 0xA00: - return "GL_COEFF"; - case 0xA01: - return "GL_ORDER"; - case 0xA02: - return "GL_DOMAIN"; - case 0xB00: - return "GL_CURRENT_COLOR"; - case 0xB01: - return "GL_CURRENT_INDEX"; - case 0xB02: - return "GL_CURRENT_NORMAL"; - case 0xB03: - return "GL_CURRENT_TEXTURE_COORDS"; - case 0xB04: - return "GL_CURRENT_RASTER_COLOR"; - case 0xB05: - return "GL_CURRENT_RASTER_INDEX"; - case 0xB06: - return "GL_CURRENT_RASTER_TEXTURE_COORDS"; - case 0xB07: - return "GL_CURRENT_RASTER_POSITION"; - case 0xB08: - return "GL_CURRENT_RASTER_POSITION_VALID"; - case 0xB09: - return "GL_CURRENT_RASTER_DISTANCE"; - case 0xB10: - return "GL_POINT_SMOOTH"; - case 0xB11: - return "GL_POINT_SIZE"; - case 0xB12: - return "GL_POINT_SIZE_RANGE"; - case 0xB13: - return "GL_POINT_SIZE_GRANULARITY"; - case 0xB20: - return "GL_LINE_SMOOTH"; - case 0xB21: - return "GL_LINE_WIDTH"; - case 0xB22: - return "GL_LINE_WIDTH_RANGE"; - case 0xB23: - return "GL_LINE_WIDTH_GRANULARITY"; - case 0xB24: - return "GL_LINE_STIPPLE"; - case 0xB25: - return "GL_LINE_STIPPLE_PATTERN"; - case 0xB26: - return "GL_LINE_STIPPLE_REPEAT"; - case 0xB30: - return "GL_LIST_MODE"; - case 0xB31: - return "GL_MAX_LIST_NESTING"; - case 0xB32: - return "GL_LIST_BASE"; - case 0xB33: - return "GL_LIST_INDEX"; - case 0xB40: - return "GL_POLYGON_MODE"; - case 0xB41: - return "GL_POLYGON_SMOOTH"; - case 0xB42: - return "GL_POLYGON_STIPPLE"; - case 0xB43: - return "GL_EDGE_FLAG"; - case 0xB44: - return "GL_CULL_FACE"; - case 0xB45: - return "GL_CULL_FACE_MODE"; - case 0xB46: - return "GL_FRONT_FACE"; - case 0xB50: - return "GL_LIGHTING"; - case 0xB51: - return "GL_LIGHT_MODEL_LOCAL_VIEWER"; - case 0xB52: - return "GL_LIGHT_MODEL_TWO_SIDE"; - case 0xB53: - return "GL_LIGHT_MODEL_AMBIENT"; - case 0xB54: - return "GL_SHADE_MODEL"; - case 0xB55: - return "GL_COLOR_MATERIAL_FACE"; - case 0xB56: - return "GL_COLOR_MATERIAL_PARAMETER"; - case 0xB57: - return "GL_COLOR_MATERIAL"; - case 0xB60: - return "GL_FOG"; - case 0xB61: - return "GL_FOG_INDEX"; - case 0xB62: - return "GL_FOG_DENSITY"; - case 0xB63: - return "GL_FOG_START"; - case 0xB64: - return "GL_FOG_END"; - case 0xB65: - return "GL_FOG_MODE"; - case 0xB66: - return "GL_FOG_COLOR"; - case 0xB70: - return "GL_DEPTH_RANGE"; - case 0xB71: - return "GL_DEPTH_TEST"; - case 0xB72: - return "GL_DEPTH_WRITEMASK"; - case 0xB73: - return "GL_DEPTH_CLEAR_VALUE"; - case 0xB74: - return "GL_DEPTH_FUNC"; - case 0xB80: - return "GL_ACCUM_CLEAR_VALUE"; - case 0xB90: - return "GL_STENCIL_TEST"; - case 0xB91: - return "GL_STENCIL_CLEAR_VALUE"; - case 0xB92: - return "GL_STENCIL_FUNC"; - case 0xB93: - return "GL_STENCIL_VALUE_MASK"; - case 0xB94: - return "GL_STENCIL_FAIL"; - case 0xB95: - return "GL_STENCIL_PASS_DEPTH_FAIL"; - case 0xB96: - return "GL_STENCIL_PASS_DEPTH_PASS"; - case 0xB97: - return "GL_STENCIL_REF"; - case 0xB98: - return "GL_STENCIL_WRITEMASK"; - case 0xBA0: - return "GL_MATRIX_MODE"; - case 0xBA1: - return "GL_NORMALIZE"; - case 0xBA2: - return "GL_VIEWPORT"; - case 0xBA3: - return "GL_MODELVIEW_STACK_DEPTH"; - case 0xBA4: - return "GL_PROJECTION_STACK_DEPTH"; - case 0xBA5: - return "GL_TEXTURE_STACK_DEPTH"; - case 0xBA6: - return "GL_MODELVIEW_MATRIX"; - case 0xBA7: - return "GL_PROJECTION_MATRIX"; - case 0xBA8: - return "GL_TEXTURE_MATRIX"; - case 0xBB0: - return "GL_ATTRIB_STACK_DEPTH"; - case 0xBB1: - return "GL_CLIENT_ATTRIB_STACK_DEPTH"; - case 0xBC0: - return "GL_ALPHA_TEST"; - case 0xBC1: - return "GL_ALPHA_TEST_FUNC"; - case 0xBC2: - return "GL_ALPHA_TEST_REF"; - case 0xBD0: - return "GL_DITHER"; - case 0xBE0: - return "GL_BLEND_DST"; - case 0xBE1: - return "GL_BLEND_SRC"; - case 0xBE2: - return "GL_BLEND"; - case 0xBF0: - return "GL_LOGIC_OP_MODE"; - case 0xBF1: - return "GL_LOGIC_OP"; - case 0xBF2: - return "GL_COLOR_LOGIC_OP"; - case 0xC00: - return "GL_AUX_BUFFERS"; - case 0xC01: - return "GL_DRAW_BUFFER"; - case 0xC02: - return "GL_READ_BUFFER"; - case 0xC10: - return "GL_SCISSOR_BOX"; - case 0xC11: - return "GL_SCISSOR_TEST"; - case 0xC20: - return "GL_INDEX_CLEAR_VALUE"; - case 0xC21: - return "GL_INDEX_WRITEMASK"; - case 0xC22: - return "GL_COLOR_CLEAR_VALUE"; - case 0xC23: - return "GL_COLOR_WRITEMASK"; - case 0xC30: - return "GL_INDEX_MODE"; - case 0xC31: - return "GL_RGBA_MODE"; - case 0xC32: - return "GL_DOUBLEBUFFER"; - case 0xC33: - return "GL_STEREO"; - case 0xC40: - return "GL_RENDER_MODE"; - case 0xC50: - return "GL_PERSPECTIVE_CORRECTION_HINT"; - case 0xC51: - return "GL_POINT_SMOOTH_HINT"; - case 0xC52: - return "GL_LINE_SMOOTH_HINT"; - case 0xC53: - return "GL_POLYGON_SMOOTH_HINT"; - case 0xC54: - return "GL_FOG_HINT"; - case 0xC60: - return "GL_TEXTURE_GEN_S"; - case 0xC61: - return "GL_TEXTURE_GEN_T"; - case 0xC62: - return "GL_TEXTURE_GEN_R"; - case 0xC63: - return "GL_TEXTURE_GEN_Q"; - case 0xC70: - return "GL_PIXEL_MAP_I_TO_I"; - case 0xC71: - return "GL_PIXEL_MAP_S_TO_S"; - case 0xC72: - return "GL_PIXEL_MAP_I_TO_R"; - case 0xC73: - return "GL_PIXEL_MAP_I_TO_G"; - case 0xC74: - return "GL_PIXEL_MAP_I_TO_B"; - case 0xC75: - return "GL_PIXEL_MAP_I_TO_A"; - case 0xC76: - return "GL_PIXEL_MAP_R_TO_R"; - case 0xC77: - return "GL_PIXEL_MAP_G_TO_G"; - case 0xC78: - return "GL_PIXEL_MAP_B_TO_B"; - case 0xC79: - return "GL_PIXEL_MAP_A_TO_A"; - case 0xCB0: - return "GL_PIXEL_MAP_I_TO_I_SIZE"; - case 0xCB1: - return "GL_PIXEL_MAP_S_TO_S_SIZE"; - case 0xCB2: - return "GL_PIXEL_MAP_I_TO_R_SIZE"; - case 0xCB3: - return "GL_PIXEL_MAP_I_TO_G_SIZE"; - case 0xCB4: - return "GL_PIXEL_MAP_I_TO_B_SIZE"; - case 0xCB5: - return "GL_PIXEL_MAP_I_TO_A_SIZE"; - case 0xCB6: - return "GL_PIXEL_MAP_R_TO_R_SIZE"; - case 0xCB7: - return "GL_PIXEL_MAP_G_TO_G_SIZE"; - case 0xCB8: - return "GL_PIXEL_MAP_B_TO_B_SIZE"; - case 0xCB9: - return "GL_PIXEL_MAP_A_TO_A_SIZE"; - case 0xCF0: - return "GL_UNPACK_SWAP_BYTES"; - case 0xCF1: - return "GL_UNPACK_LSB_FIRST"; - case 0xCF2: - return "GL_UNPACK_ROW_LENGTH"; - case 0xCF3: - return "GL_UNPACK_SKIP_ROWS"; - case 0xCF4: - return "GL_UNPACK_SKIP_PIXELS"; - case 0xCF5: - return "GL_UNPACK_ALIGNMENT"; - case 0xD00: - return "GL_PACK_SWAP_BYTES"; - case 0xD01: - return "GL_PACK_LSB_FIRST"; - case 0xD02: - return "GL_PACK_ROW_LENGTH"; - case 0xD03: - return "GL_PACK_SKIP_ROWS"; - case 0xD04: - return "GL_PACK_SKIP_PIXELS"; - case 0xD05: - return "GL_PACK_ALIGNMENT"; - case 0xD10: - return "GL_MAP_COLOR"; - case 0xD11: - return "GL_MAP_STENCIL"; - case 0xD12: - return "GL_INDEX_SHIFT"; - case 0xD13: - return "GL_INDEX_OFFSET"; - case 0xD14: - return "GL_RED_SCALE"; - case 0xD15: - return "GL_RED_BIAS"; - case 0xD16: - return "GL_ZOOM_X"; - case 0xD17: - return "GL_ZOOM_Y"; - case 0xD18: - return "GL_GREEN_SCALE"; - case 0xD19: - return "GL_GREEN_BIAS"; - case 0xD1A: - return "GL_BLUE_SCALE"; - case 0xD1B: - return "GL_BLUE_BIAS"; - case 0xD1C: - return "GL_ALPHA_SCALE"; - case 0xD1D: - return "GL_ALPHA_BIAS"; - case 0xD1E: - return "GL_DEPTH_SCALE"; - case 0xD1F: - return "GL_DEPTH_BIAS"; - case 0xD30: - return "GL_MAX_EVAL_ORDER"; - case 0xD31: - return "GL_MAX_LIGHTS"; - case 0xD32: - return "GL_MAX_CLIP_PLANES"; - case 0xD33: - return "GL_MAX_TEXTURE_SIZE"; - case 0xD34: - return "GL_MAX_PIXEL_MAP_TABLE"; - case 0xD35: - return "GL_MAX_ATTRIB_STACK_DEPTH"; - case 0xD36: - return "GL_MAX_MODELVIEW_STACK_DEPTH"; - case 0xD37: - return "GL_MAX_NAME_STACK_DEPTH"; - case 0xD38: - return "GL_MAX_PROJECTION_STACK_DEPTH"; - case 0xD39: - return "GL_MAX_TEXTURE_STACK_DEPTH"; - case 0xD3A: - return "GL_MAX_VIEWPORT_DIMS"; - case 0xD3B: - return "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"; - case 0xD50: - return "GL_SUBPIXEL_BITS"; - case 0xD51: - return "GL_INDEX_BITS"; - case 0xD52: - return "GL_RED_BITS"; - case 0xD53: - return "GL_GREEN_BITS"; - case 0xD54: - return "GL_BLUE_BITS"; - case 0xD55: - return "GL_ALPHA_BITS"; - case 0xD56: - return "GL_DEPTH_BITS"; - case 0xD57: - return "GL_STENCIL_BITS"; - case 0xD58: - return "GL_ACCUM_RED_BITS"; - case 0xD59: - return "GL_ACCUM_GREEN_BITS"; - case 0xD5A: - return "GL_ACCUM_BLUE_BITS"; - case 0xD5B: - return "GL_ACCUM_ALPHA_BITS"; - case 0xD70: - return "GL_NAME_STACK_DEPTH"; - case 0xD80: - return "GL_AUTO_NORMAL"; - case 0xD90: - return "GL_MAP1_COLOR_4"; - case 0xD91: - return "GL_MAP1_INDEX"; - case 0xD92: - return "GL_MAP1_NORMAL"; - case 0xD93: - return "GL_MAP1_TEXTURE_COORD_1"; - case 0xD94: - return "GL_MAP1_TEXTURE_COORD_2"; - case 0xD95: - return "GL_MAP1_TEXTURE_COORD_3"; - case 0xD96: - return "GL_MAP1_TEXTURE_COORD_4"; - case 0xD97: - return "GL_MAP1_VERTEX_3"; - case 0xD98: - return "GL_MAP1_VERTEX_4"; - case 0xDB0: - return "GL_MAP2_COLOR_4"; - case 0xDB1: - return "GL_MAP2_INDEX"; - case 0xDB2: - return "GL_MAP2_NORMAL"; - case 0xDB3: - return "GL_MAP2_TEXTURE_COORD_1"; - case 0xDB4: - return "GL_MAP2_TEXTURE_COORD_2"; - case 0xDB5: - return "GL_MAP2_TEXTURE_COORD_3"; - case 0xDB6: - return "GL_MAP2_TEXTURE_COORD_4"; - case 0xDB7: - return "GL_MAP2_VERTEX_3"; - case 0xDB8: - return "GL_MAP2_VERTEX_4"; - case 0xDD0: - return "GL_MAP1_GRID_DOMAIN"; - case 0xDD1: - return "GL_MAP1_GRID_SEGMENTS"; - case 0xDD2: - return "GL_MAP2_GRID_DOMAIN"; - case 0xDD3: - return "GL_MAP2_GRID_SEGMENTS"; - case 0xDE0: - return "GL_TEXTURE_1D"; - case 0xDE1: - return "GL_TEXTURE_2D"; - case 0xDF0: - return "GL_FEEDBACK_BUFFER_POINTER"; - case 0xDF1: - return "GL_FEEDBACK_BUFFER_SIZE"; - case 0xDF2: - return "GL_FEEDBACK_BUFFER_TYPE"; - case 0xDF3: - return "GL_SELECTION_BUFFER_POINTER"; - case 0xDF4: - return "GL_SELECTION_BUFFER_SIZE"; - case 0x1000: - return "GL_TEXTURE_WIDTH"; - case 0x1001: - return "GL_TEXTURE_HEIGHT"; - case 0x1003: - return "GL_TEXTURE_COMPONENTS"; - case 0x1004: - return "GL_TEXTURE_BORDER_COLOR"; - case 0x1005: - return "GL_TEXTURE_BORDER"; - case 0x1006: - return "GL_TEXTURE_TARGET"; - case 0x1100: - return "GL_DONT_CARE"; - case 0x1101: - return "GL_FASTEST"; - case 0x1102: - return "GL_NICEST"; - case 0x1200: - return "GL_AMBIENT"; - case 0x1201: - return "GL_DIFFUSE"; - case 0x1202: - return "GL_SPECULAR"; - case 0x1203: - return "GL_POSITION"; - case 0x1204: - return "GL_SPOT_DIRECTION"; - case 0x1205: - return "GL_SPOT_EXPONENT"; - case 0x1206: - return "GL_SPOT_CUTOFF"; - case 0x1207: - return "GL_CONSTANT_ATTENUATION"; - case 0x1208: - return "GL_LINEAR_ATTENUATION"; - case 0x1209: - return "GL_QUADRATIC_ATTENUATION"; - case 0x1300: - return "GL_COMPILE"; - case 0x1301: - return "GL_COMPILE_AND_EXECUTE"; - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x1407: - return "GL_2_BYTES"; - case 0x1408: - return "GL_3_BYTES"; - case 0x1409: - return "GL_4_BYTES"; - case 0x140A: - return "GL_DOUBLE"; - case 0x140B: - return "GL_HALF_FLOAT"; - case 0x140C: - return "GL_FIXED"; - case 0x1500: - return "GL_CLEAR"; - case 0x1501: - return "GL_AND"; - case 0x1502: - return "GL_AND_REVERSE"; - case 0x1503: - return "GL_COPY"; - case 0x1504: - return "GL_AND_INVERTED"; - case 0x1505: - return "GL_NOOP"; - case 0x1506: - return "GL_XOR"; - case 0x1507: - return "GL_OR"; - case 0x1508: - return "GL_NOR"; - case 0x1509: - return "GL_EQUIV"; - case 0x150A: - return "GL_INVERT"; - case 0x150B: - return "GL_OR_REVERSE"; - case 0x150C: - return "GL_COPY_INVERTED"; - case 0x150D: - return "GL_OR_INVERTED"; - case 0x150E: - return "GL_NAND"; - case 0x150F: - return "GL_SET"; - case 0x1600: - return "GL_EMISSION"; - case 0x1601: - return "GL_SHININESS"; - case 0x1602: - return "GL_AMBIENT_AND_DIFFUSE"; - case 0x1603: - return "GL_COLOR_INDEXES"; - case 0x1700: - return "GL_MODELVIEW"; - case 0x1701: - return "GL_PROJECTION"; - case 0x1702: - return "GL_TEXTURE"; - case 0x1800: - return "GL_COLOR"; - case 0x1801: - return "GL_DEPTH"; - case 0x1802: - return "GL_STENCIL"; - case 0x1900: - return "GL_COLOR_INDEX"; - case 0x1901: - return "GL_STENCIL_INDEX"; - case 0x1902: - return "GL_DEPTH_COMPONENT"; - case 0x1903: - return "GL_RED"; - case 0x1904: - return "GL_GREEN"; - case 0x1905: - return "GL_BLUE"; - case 0x1906: - return "GL_ALPHA"; - case 0x1907: - return "GL_RGB"; - case 0x1908: - return "GL_RGBA"; - case 0x1909: - return "GL_LUMINANCE"; - case 0x190A: - return "GL_LUMINANCE_ALPHA"; - case 0x1A00: - return "GL_BITMAP"; - case 0x1B00: - return "GL_POINT"; - case 0x1B01: - return "GL_LINE"; - case 0x1B02: - return "GL_FILL"; - case 0x1C00: - return "GL_RENDER"; - case 0x1C01: - return "GL_FEEDBACK"; - case 0x1C02: - return "GL_SELECT"; - case 0x1D00: - return "GL_FLAT"; - case 0x1D01: - return "GL_SMOOTH"; - case 0x1E00: - return "GL_KEEP"; - case 0x1E01: - return "GL_REPLACE"; - case 0x1E02: - return "GL_INCR"; - case 0x1E03: - return "GL_DECR"; - case 0x1F00: - return "GL_VENDOR"; - case 0x1F01: - return "GL_RENDERER"; - case 0x1F02: - return "GL_VERSION"; - case 0x1F03: - return "GL_EXTENSIONS"; - case 0x2000: - return "GL_S"; - case 0x2001: - return "GL_T"; - case 0x2002: - return "GL_R"; - case 0x2003: - return "GL_Q"; - case 0x2100: - return "GL_MODULATE"; - case 0x2101: - return "GL_DECAL"; - case 0x2200: - return "GL_TEXTURE_ENV_MODE"; - case 0x2201: - return "GL_TEXTURE_ENV_COLOR"; - case 0x2300: - return "GL_TEXTURE_ENV"; - case 0x2400: - return "GL_EYE_LINEAR"; - case 0x2401: - return "GL_OBJECT_LINEAR"; - case 0x2402: - return "GL_SPHERE_MAP"; - case 0x2500: - return "GL_TEXTURE_GEN_MODE"; - case 0x2501: - return "GL_OBJECT_PLANE"; - case 0x2502: - return "GL_EYE_PLANE"; - case 0x2600: - return "GL_NEAREST"; - case 0x2601: - return "GL_LINEAR"; - case 0x2700: - return "GL_NEAREST_MIPMAP_NEAREST"; - case 0x2701: - return "GL_LINEAR_MIPMAP_NEAREST"; - case 0x2702: - return "GL_NEAREST_MIPMAP_LINEAR"; - case 0x2703: - return "GL_LINEAR_MIPMAP_LINEAR"; - case 0x2800: - return "GL_TEXTURE_MAG_FILTER"; - case 0x2801: - return "GL_TEXTURE_MIN_FILTER"; - case 0x2802: - return "GL_TEXTURE_WRAP_S"; - case 0x2803: - return "GL_TEXTURE_WRAP_T"; - case 0x2900: - return "GL_CLAMP"; - case 0x2901: - return "GL_REPEAT"; - case 0x2A00: - return "GL_POLYGON_OFFSET_UNITS"; - case 0x2A01: - return "GL_POLYGON_OFFSET_POINT"; - case 0x2A02: - return "GL_POLYGON_OFFSET_LINE"; - case 0x2A10: - return "GL_R3_G3_B2"; - case 0x2A20: - return "GL_V2F"; - case 0x2A21: - return "GL_V3F"; - case 0x2A22: - return "GL_C4UB_V2F"; - case 0x2A23: - return "GL_C4UB_V3F"; - case 0x2A24: - return "GL_C3F_V3F"; - case 0x2A25: - return "GL_N3F_V3F"; - case 0x2A26: - return "GL_C4F_N3F_V3F"; - case 0x2A27: - return "GL_T2F_V3F"; - case 0x2A28: - return "GL_T4F_V4F"; - case 0x2A29: - return "GL_T2F_C4UB_V3F"; - case 0x2A2A: - return "GL_T2F_C3F_V3F"; - case 0x2A2B: - return "GL_T2F_N3F_V3F"; - case 0x2A2C: - return "GL_T2F_C4F_N3F_V3F"; - case 0x2A2D: - return "GL_T4F_C4F_N3F_V4F"; - case 0x3000: - return "GL_CLIP_PLANE0"; - case 0x3001: - return "GL_CLIP_PLANE1"; - case 0x3002: - return "GL_CLIP_PLANE2"; - case 0x3003: - return "GL_CLIP_PLANE3"; - case 0x3004: - return "GL_CLIP_PLANE4"; - case 0x3005: - return "GL_CLIP_PLANE5"; - case 0x3006: - return "GL_CLIP_DISTANCE6"; - case 0x3007: - return "GL_CLIP_DISTANCE7"; - case 0x4000: - return "GL_LIGHT0"; - case 0x4001: - return "GL_LIGHT1"; - case 0x4002: - return "GL_LIGHT2"; - case 0x4003: - return "GL_LIGHT3"; - case 0x4004: - return "GL_LIGHT4"; - case 0x4005: - return "GL_LIGHT5"; - case 0x4006: - return "GL_LIGHT6"; - case 0x4007: - return "GL_LIGHT7"; - case 0x8000: - return "GL_HINT_BIT"; - case 0x8001: - return "GL_CONSTANT_COLOR"; - case 0x8002: - return "GL_ONE_MINUS_CONSTANT_COLOR"; - case 0x8003: - return "GL_CONSTANT_ALPHA"; - case 0x8004: - return "GL_ONE_MINUS_CONSTANT_ALPHA"; - case 0x8005: - return "GL_BLEND_COLOR"; - case 0x8006: - return "GL_FUNC_ADD"; - case 0x8007: - return "GL_MIN"; - case 0x8008: - return "GL_MAX"; - case 0x8009: - return "GL_BLEND_EQUATION"; - case 0x800A: - return "GL_FUNC_SUBTRACT"; - case 0x800B: - return "GL_FUNC_REVERSE_SUBTRACT"; - case 0x8010: - return "GL_CONVOLUTION_1D"; - case 0x8011: - return "GL_CONVOLUTION_2D"; - case 0x8012: - return "GL_SEPARABLE_2D"; - case 0x8024: - return "GL_HISTOGRAM"; - case 0x8025: - return "GL_PROXY_HISTOGRAM"; - case 0x802E: - return "GL_MINMAX"; - case 0x8032: - return "GL_UNSIGNED_BYTE_3_3_2"; - case 0x8033: - return "GL_UNSIGNED_SHORT_4_4_4_4"; - case 0x8034: - return "GL_UNSIGNED_SHORT_5_5_5_1"; - case 0x8035: - return "GL_UNSIGNED_INT_8_8_8_8"; - case 0x8036: - return "GL_UNSIGNED_INT_10_10_10_2"; - case 0x8037: - return "GL_POLYGON_OFFSET_FILL"; - case 0x8038: - return "GL_POLYGON_OFFSET_FACTOR"; - case 0x803A: - return "GL_RESCALE_NORMAL"; - case 0x803B: - return "GL_ALPHA4"; - case 0x803C: - return "GL_ALPHA8"; - case 0x803D: - return "GL_ALPHA12"; - case 0x803E: - return "GL_ALPHA16"; - case 0x803F: - return "GL_LUMINANCE4"; - case 0x8040: - return "GL_LUMINANCE8"; - case 0x8041: - return "GL_LUMINANCE12"; - case 0x8042: - return "GL_LUMINANCE16"; - case 0x8043: - return "GL_LUMINANCE4_ALPHA4"; - case 0x8044: - return "GL_LUMINANCE6_ALPHA2"; - case 0x8045: - return "GL_LUMINANCE8_ALPHA8"; - case 0x8046: - return "GL_LUMINANCE12_ALPHA4"; - case 0x8047: - return "GL_LUMINANCE12_ALPHA12"; - case 0x8048: - return "GL_LUMINANCE16_ALPHA16"; - case 0x8049: - return "GL_INTENSITY"; - case 0x804A: - return "GL_INTENSITY4"; - case 0x804B: - return "GL_INTENSITY8"; - case 0x804C: - return "GL_INTENSITY12"; - case 0x804D: - return "GL_INTENSITY16"; - case 0x804F: - return "GL_RGB4"; - case 0x8050: - return "GL_RGB5"; - case 0x8051: - return "GL_RGB8"; - case 0x8052: - return "GL_RGB10"; - case 0x8053: - return "GL_RGB12"; - case 0x8054: - return "GL_RGB16"; - case 0x8055: - return "GL_RGBA2"; - case 0x8056: - return "GL_RGBA4"; - case 0x8057: - return "GL_RGB5_A1"; - case 0x8058: - return "GL_RGBA8"; - case 0x8059: - return "GL_RGB10_A2"; - case 0x805A: - return "GL_RGBA12"; - case 0x805B: - return "GL_RGBA16"; - case 0x805C: - return "GL_TEXTURE_RED_SIZE"; - case 0x805D: - return "GL_TEXTURE_GREEN_SIZE"; - case 0x805E: - return "GL_TEXTURE_BLUE_SIZE"; - case 0x805F: - return "GL_TEXTURE_ALPHA_SIZE"; - case 0x8060: - return "GL_TEXTURE_LUMINANCE_SIZE"; - case 0x8061: - return "GL_TEXTURE_INTENSITY_SIZE"; - case 0x8063: - return "GL_PROXY_TEXTURE_1D"; - case 0x8064: - return "GL_PROXY_TEXTURE_2D"; - case 0x8066: - return "GL_TEXTURE_PRIORITY"; - case 0x8067: - return "GL_TEXTURE_RESIDENT"; - case 0x8068: - return "GL_TEXTURE_BINDING_1D"; - case 0x8069: - return "GL_TEXTURE_BINDING_2D"; - case 0x806A: - return "GL_TEXTURE_BINDING_3D"; - case 0x806B: - return "GL_PACK_SKIP_IMAGES"; - case 0x806C: - return "GL_PACK_IMAGE_HEIGHT"; - case 0x806D: - return "GL_UNPACK_SKIP_IMAGES"; - case 0x806E: - return "GL_UNPACK_IMAGE_HEIGHT"; - case 0x806F: - return "GL_TEXTURE_3D"; - case 0x8070: - return "GL_PROXY_TEXTURE_3D"; - case 0x8071: - return "GL_TEXTURE_DEPTH"; - case 0x8072: - return "GL_TEXTURE_WRAP_R"; - case 0x8073: - return "GL_MAX_3D_TEXTURE_SIZE"; - case 0x8074: - return "GL_VERTEX_ARRAY"; - case 0x8075: - return "GL_NORMAL_ARRAY"; - case 0x8076: - return "GL_COLOR_ARRAY"; - case 0x8077: - return "GL_INDEX_ARRAY"; - case 0x8078: - return "GL_TEXTURE_COORD_ARRAY"; - case 0x8079: - return "GL_EDGE_FLAG_ARRAY"; - case 0x807A: - return "GL_VERTEX_ARRAY_SIZE"; - case 0x807B: - return "GL_VERTEX_ARRAY_TYPE"; - case 0x807C: - return "GL_VERTEX_ARRAY_STRIDE"; - case 0x807E: - return "GL_NORMAL_ARRAY_TYPE"; - case 0x807F: - return "GL_NORMAL_ARRAY_STRIDE"; - case 0x8081: - return "GL_COLOR_ARRAY_SIZE"; - case 0x8082: - return "GL_COLOR_ARRAY_TYPE"; - case 0x8083: - return "GL_COLOR_ARRAY_STRIDE"; - case 0x8085: - return "GL_INDEX_ARRAY_TYPE"; - case 0x8086: - return "GL_INDEX_ARRAY_STRIDE"; - case 0x8088: - return "GL_TEXTURE_COORD_ARRAY_SIZE"; - case 0x8089: - return "GL_TEXTURE_COORD_ARRAY_TYPE"; - case 0x808A: - return "GL_TEXTURE_COORD_ARRAY_STRIDE"; - case 0x808C: - return "GL_EDGE_FLAG_ARRAY_STRIDE"; - case 0x808E: - return "GL_VERTEX_ARRAY_POINTER"; - case 0x808F: - return "GL_NORMAL_ARRAY_POINTER"; - case 0x8090: - return "GL_COLOR_ARRAY_POINTER"; - case 0x8091: - return "GL_INDEX_ARRAY_POINTER"; - case 0x8092: - return "GL_TEXTURE_COORD_ARRAY_POINTER"; - case 0x8093: - return "GL_EDGE_FLAG_ARRAY_POINTER"; - case 0x809D: - return "GL_MULTISAMPLE"; - case 0x809E: - return "GL_SAMPLE_ALPHA_TO_COVERAGE"; - case 0x809F: - return "GL_SAMPLE_ALPHA_TO_ONE"; - case 0x80A0: - return "GL_SAMPLE_COVERAGE"; - case 0x80A8: - return "GL_SAMPLE_BUFFERS"; - case 0x80A9: - return "GL_SAMPLES"; - case 0x80AA: - return "GL_SAMPLE_COVERAGE_VALUE"; - case 0x80AB: - return "GL_SAMPLE_COVERAGE_INVERT"; - case 0x80C8: - return "GL_BLEND_DST_RGB"; - case 0x80C9: - return "GL_BLEND_SRC_RGB"; - case 0x80CA: - return "GL_BLEND_DST_ALPHA"; - case 0x80CB: - return "GL_BLEND_SRC_ALPHA"; - case 0x80D0: - return "GL_COLOR_TABLE"; - case 0x80D1: - return "GL_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D2: - return "GL_POST_COLOR_MATRIX_COLOR_TABLE"; - case 0x80D3: - return "GL_PROXY_COLOR_TABLE"; - case 0x80D4: - return "GL_PROXY_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D5: - return "GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE"; - case 0x80E0: - return "GL_BGR"; - case 0x80E1: - return "GL_BGRA"; - case 0x80E8: - return "GL_MAX_ELEMENTS_VERTICES"; - case 0x80E9: - return "GL_MAX_ELEMENTS_INDICES"; - case 0x80EE: - return "GL_PARAMETER_BUFFER"; - case 0x80EF: - return "GL_PARAMETER_BUFFER_BINDING"; - case 0x8126: - return "GL_POINT_SIZE_MIN"; - case 0x8127: - return "GL_POINT_SIZE_MAX"; - case 0x8128: - return "GL_POINT_FADE_THRESHOLD_SIZE"; - case 0x8129: - return "GL_POINT_DISTANCE_ATTENUATION"; - case 0x812D: - return "GL_CLAMP_TO_BORDER"; - case 0x812F: - return "GL_CLAMP_TO_EDGE"; - case 0x813A: - return "GL_TEXTURE_MIN_LOD"; - case 0x813B: - return "GL_TEXTURE_MAX_LOD"; - case 0x813C: - return "GL_TEXTURE_BASE_LEVEL"; - case 0x813D: - return "GL_TEXTURE_MAX_LEVEL"; - case 0x8191: - return "GL_GENERATE_MIPMAP"; - case 0x8192: - return "GL_GENERATE_MIPMAP_HINT"; - case 0x81A5: - return "GL_DEPTH_COMPONENT16"; - case 0x81A6: - return "GL_DEPTH_COMPONENT24"; - case 0x81A7: - return "GL_DEPTH_COMPONENT32"; - case 0x81F8: - return "GL_LIGHT_MODEL_COLOR_CONTROL"; - case 0x81F9: - return "GL_SINGLE_COLOR"; - case 0x81FA: - return "GL_SEPARATE_SPECULAR_COLOR"; - case 0x8210: - return "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"; - case 0x8211: - return "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"; - case 0x8212: - return "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE"; - case 0x8213: - return "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE"; - case 0x8214: - return "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE"; - case 0x8215: - return "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE"; - case 0x8216: - return "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE"; - case 0x8217: - return "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE"; - case 0x8218: - return "GL_FRAMEBUFFER_DEFAULT"; - case 0x8219: - return "GL_FRAMEBUFFER_UNDEFINED"; - case 0x821A: - return "GL_DEPTH_STENCIL_ATTACHMENT"; - case 0x821B: - return "GL_MAJOR_VERSION"; - case 0x821C: - return "GL_MINOR_VERSION"; - case 0x821D: - return "GL_NUM_EXTENSIONS"; - case 0x821E: - return "GL_CONTEXT_FLAGS"; - case 0x821F: - return "GL_BUFFER_IMMUTABLE_STORAGE"; - case 0x8220: - return "GL_BUFFER_STORAGE_FLAGS"; - case 0x8221: - return "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"; - case 0x8222: - return "GL_INDEX"; - case 0x8225: - return "GL_COMPRESSED_RED"; - case 0x8226: - return "GL_COMPRESSED_RG"; - case 0x8227: - return "GL_RG"; - case 0x8228: - return "GL_RG_INTEGER"; - case 0x8229: - return "GL_R8"; - case 0x822A: - return "GL_R16"; - case 0x822B: - return "GL_RG8"; - case 0x822C: - return "GL_RG16"; - case 0x822D: - return "GL_R16F"; - case 0x822E: - return "GL_R32F"; - case 0x822F: - return "GL_RG16F"; - case 0x8230: - return "GL_RG32F"; - case 0x8231: - return "GL_R8I"; - case 0x8232: - return "GL_R8UI"; - case 0x8233: - return "GL_R16I"; - case 0x8234: - return "GL_R16UI"; - case 0x8235: - return "GL_R32I"; - case 0x8236: - return "GL_R32UI"; - case 0x8237: - return "GL_RG8I"; - case 0x8238: - return "GL_RG8UI"; - case 0x8239: - return "GL_RG16I"; - case 0x823A: - return "GL_RG16UI"; - case 0x823B: - return "GL_RG32I"; - case 0x823C: - return "GL_RG32UI"; - case 0x8242: - return "GL_DEBUG_OUTPUT_SYNCHRONOUS"; - case 0x8243: - return "GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"; - case 0x8244: - return "GL_DEBUG_CALLBACK_FUNCTION"; - case 0x8245: - return "GL_DEBUG_CALLBACK_USER_PARAM"; - case 0x8246: - return "GL_DEBUG_SOURCE_API"; - case 0x8247: - return "GL_DEBUG_SOURCE_WINDOW_SYSTEM"; - case 0x8248: - return "GL_DEBUG_SOURCE_SHADER_COMPILER"; - case 0x8249: - return "GL_DEBUG_SOURCE_THIRD_PARTY"; - case 0x824A: - return "GL_DEBUG_SOURCE_APPLICATION"; - case 0x824B: - return "GL_DEBUG_SOURCE_OTHER"; - case 0x824C: - return "GL_DEBUG_TYPE_ERROR"; - case 0x824D: - return "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"; - case 0x824E: - return "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"; - case 0x824F: - return "GL_DEBUG_TYPE_PORTABILITY"; - case 0x8250: - return "GL_DEBUG_TYPE_PERFORMANCE"; - case 0x8251: - return "GL_DEBUG_TYPE_OTHER"; - case 0x8252: - return "GL_LOSE_CONTEXT_ON_RESET"; - case 0x8253: - return "GL_GUILTY_CONTEXT_RESET"; - case 0x8254: - return "GL_INNOCENT_CONTEXT_RESET"; - case 0x8255: - return "GL_UNKNOWN_CONTEXT_RESET"; - case 0x8256: - return "GL_RESET_NOTIFICATION_STRATEGY"; - case 0x8257: - return "GL_PROGRAM_BINARY_RETRIEVABLE_HINT"; - case 0x8258: - return "GL_PROGRAM_SEPARABLE"; - case 0x8259: - return "GL_ACTIVE_PROGRAM"; - case 0x825A: - return "GL_PROGRAM_PIPELINE_BINDING"; - case 0x825B: - return "GL_MAX_VIEWPORTS"; - case 0x825C: - return "GL_VIEWPORT_SUBPIXEL_BITS"; - case 0x825D: - return "GL_VIEWPORT_BOUNDS_RANGE"; - case 0x825E: - return "GL_LAYER_PROVOKING_VERTEX"; - case 0x825F: - return "GL_VIEWPORT_INDEX_PROVOKING_VERTEX"; - case 0x8260: - return "GL_UNDEFINED_VERTEX"; - case 0x8261: - return "GL_NO_RESET_NOTIFICATION"; - case 0x8262: - return "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"; - case 0x8263: - return "GL_MAX_COMPUTE_UNIFORM_COMPONENTS"; - case 0x8264: - return "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"; - case 0x8265: - return "GL_MAX_COMPUTE_ATOMIC_COUNTERS"; - case 0x8266: - return "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"; - case 0x8267: - return "GL_COMPUTE_WORK_GROUP_SIZE"; - case 0x8268: - return "GL_DEBUG_TYPE_MARKER"; - case 0x8269: - return "GL_DEBUG_TYPE_PUSH_GROUP"; - case 0x826A: - return "GL_DEBUG_TYPE_POP_GROUP"; - case 0x826B: - return "GL_DEBUG_SEVERITY_NOTIFICATION"; - case 0x826C: - return "GL_MAX_DEBUG_GROUP_STACK_DEPTH"; - case 0x826D: - return "GL_DEBUG_GROUP_STACK_DEPTH"; - case 0x826E: - return "GL_MAX_UNIFORM_LOCATIONS"; - case 0x826F: - return "GL_INTERNALFORMAT_SUPPORTED"; - case 0x8270: - return "GL_INTERNALFORMAT_PREFERRED"; - case 0x8271: - return "GL_INTERNALFORMAT_RED_SIZE"; - case 0x8272: - return "GL_INTERNALFORMAT_GREEN_SIZE"; - case 0x8273: - return "GL_INTERNALFORMAT_BLUE_SIZE"; - case 0x8274: - return "GL_INTERNALFORMAT_ALPHA_SIZE"; - case 0x8275: - return "GL_INTERNALFORMAT_DEPTH_SIZE"; - case 0x8276: - return "GL_INTERNALFORMAT_STENCIL_SIZE"; - case 0x8277: - return "GL_INTERNALFORMAT_SHARED_SIZE"; - case 0x8278: - return "GL_INTERNALFORMAT_RED_TYPE"; - case 0x8279: - return "GL_INTERNALFORMAT_GREEN_TYPE"; - case 0x827A: - return "GL_INTERNALFORMAT_BLUE_TYPE"; - case 0x827B: - return "GL_INTERNALFORMAT_ALPHA_TYPE"; - case 0x827C: - return "GL_INTERNALFORMAT_DEPTH_TYPE"; - case 0x827D: - return "GL_INTERNALFORMAT_STENCIL_TYPE"; - case 0x827E: - return "GL_MAX_WIDTH"; - case 0x827F: - return "GL_MAX_HEIGHT"; - case 0x8280: - return "GL_MAX_DEPTH"; - case 0x8281: - return "GL_MAX_LAYERS"; - case 0x8282: - return "GL_MAX_COMBINED_DIMENSIONS"; - case 0x8283: - return "GL_COLOR_COMPONENTS"; - case 0x8284: - return "GL_DEPTH_COMPONENTS"; - case 0x8285: - return "GL_STENCIL_COMPONENTS"; - case 0x8286: - return "GL_COLOR_RENDERABLE"; - case 0x8287: - return "GL_DEPTH_RENDERABLE"; - case 0x8288: - return "GL_STENCIL_RENDERABLE"; - case 0x8289: - return "GL_FRAMEBUFFER_RENDERABLE"; - case 0x828A: - return "GL_FRAMEBUFFER_RENDERABLE_LAYERED"; - case 0x828B: - return "GL_FRAMEBUFFER_BLEND"; - case 0x828C: - return "GL_READ_PIXELS"; - case 0x828D: - return "GL_READ_PIXELS_FORMAT"; - case 0x828E: - return "GL_READ_PIXELS_TYPE"; - case 0x828F: - return "GL_TEXTURE_IMAGE_FORMAT"; - case 0x8290: - return "GL_TEXTURE_IMAGE_TYPE"; - case 0x8291: - return "GL_GET_TEXTURE_IMAGE_FORMAT"; - case 0x8292: - return "GL_GET_TEXTURE_IMAGE_TYPE"; - case 0x8293: - return "GL_MIPMAP"; - case 0x8294: - return "GL_MANUAL_GENERATE_MIPMAP"; - case 0x8295: - return "GL_AUTO_GENERATE_MIPMAP"; - case 0x8296: - return "GL_COLOR_ENCODING"; - case 0x8297: - return "GL_SRGB_READ"; - case 0x8298: - return "GL_SRGB_WRITE"; - case 0x829A: - return "GL_FILTER"; - case 0x829B: - return "GL_VERTEX_TEXTURE"; - case 0x829C: - return "GL_TESS_CONTROL_TEXTURE"; - case 0x829D: - return "GL_TESS_EVALUATION_TEXTURE"; - case 0x829E: - return "GL_GEOMETRY_TEXTURE"; - case 0x829F: - return "GL_FRAGMENT_TEXTURE"; - case 0x82A0: - return "GL_COMPUTE_TEXTURE"; - case 0x82A1: - return "GL_TEXTURE_SHADOW"; - case 0x82A2: - return "GL_TEXTURE_GATHER"; - case 0x82A3: - return "GL_TEXTURE_GATHER_SHADOW"; - case 0x82A4: - return "GL_SHADER_IMAGE_LOAD"; - case 0x82A5: - return "GL_SHADER_IMAGE_STORE"; - case 0x82A6: - return "GL_SHADER_IMAGE_ATOMIC"; - case 0x82A7: - return "GL_IMAGE_TEXEL_SIZE"; - case 0x82A8: - return "GL_IMAGE_COMPATIBILITY_CLASS"; - case 0x82A9: - return "GL_IMAGE_PIXEL_FORMAT"; - case 0x82AA: - return "GL_IMAGE_PIXEL_TYPE"; - case 0x82AC: - return "GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"; - case 0x82AD: - return "GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"; - case 0x82AE: - return "GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"; - case 0x82AF: - return "GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE"; - case 0x82B1: - return "GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"; - case 0x82B2: - return "GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"; - case 0x82B3: - return "GL_TEXTURE_COMPRESSED_BLOCK_SIZE"; - case 0x82B4: - return "GL_CLEAR_BUFFER"; - case 0x82B5: - return "GL_TEXTURE_VIEW"; - case 0x82B6: - return "GL_VIEW_COMPATIBILITY_CLASS"; - case 0x82B7: - return "GL_FULL_SUPPORT"; - case 0x82B8: - return "GL_CAVEAT_SUPPORT"; - case 0x82B9: - return "GL_IMAGE_CLASS_4_X_32"; - case 0x82BA: - return "GL_IMAGE_CLASS_2_X_32"; - case 0x82BB: - return "GL_IMAGE_CLASS_1_X_32"; - case 0x82BC: - return "GL_IMAGE_CLASS_4_X_16"; - case 0x82BD: - return "GL_IMAGE_CLASS_2_X_16"; - case 0x82BE: - return "GL_IMAGE_CLASS_1_X_16"; - case 0x82BF: - return "GL_IMAGE_CLASS_4_X_8"; - case 0x82C0: - return "GL_IMAGE_CLASS_2_X_8"; - case 0x82C1: - return "GL_IMAGE_CLASS_1_X_8"; - case 0x82C2: - return "GL_IMAGE_CLASS_11_11_10"; - case 0x82C3: - return "GL_IMAGE_CLASS_10_10_10_2"; - case 0x82C4: - return "GL_VIEW_CLASS_128_BITS"; - case 0x82C5: - return "GL_VIEW_CLASS_96_BITS"; - case 0x82C6: - return "GL_VIEW_CLASS_64_BITS"; - case 0x82C7: - return "GL_VIEW_CLASS_48_BITS"; - case 0x82C8: - return "GL_VIEW_CLASS_32_BITS"; - case 0x82C9: - return "GL_VIEW_CLASS_24_BITS"; - case 0x82CA: - return "GL_VIEW_CLASS_16_BITS"; - case 0x82CB: - return "GL_VIEW_CLASS_8_BITS"; - case 0x82CC: - return "GL_VIEW_CLASS_S3TC_DXT1_RGB"; - case 0x82CD: - return "GL_VIEW_CLASS_S3TC_DXT1_RGBA"; - case 0x82CE: - return "GL_VIEW_CLASS_S3TC_DXT3_RGBA"; - case 0x82CF: - return "GL_VIEW_CLASS_S3TC_DXT5_RGBA"; - case 0x82D0: - return "GL_VIEW_CLASS_RGTC1_RED"; - case 0x82D1: - return "GL_VIEW_CLASS_RGTC2_RG"; - case 0x82D2: - return "GL_VIEW_CLASS_BPTC_UNORM"; - case 0x82D3: - return "GL_VIEW_CLASS_BPTC_FLOAT"; - case 0x82D4: - return "GL_VERTEX_ATTRIB_BINDING"; - case 0x82D5: - return "GL_VERTEX_ATTRIB_RELATIVE_OFFSET"; - case 0x82D6: - return "GL_VERTEX_BINDING_DIVISOR"; - case 0x82D7: - return "GL_VERTEX_BINDING_OFFSET"; - case 0x82D8: - return "GL_VERTEX_BINDING_STRIDE"; - case 0x82D9: - return "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"; - case 0x82DA: - return "GL_MAX_VERTEX_ATTRIB_BINDINGS"; - case 0x82DB: - return "GL_TEXTURE_VIEW_MIN_LEVEL"; - case 0x82DC: - return "GL_TEXTURE_VIEW_NUM_LEVELS"; - case 0x82DD: - return "GL_TEXTURE_VIEW_MIN_LAYER"; - case 0x82DE: - return "GL_TEXTURE_VIEW_NUM_LAYERS"; - case 0x82DF: - return "GL_TEXTURE_IMMUTABLE_LEVELS"; - case 0x82E0: - return "GL_BUFFER"; - case 0x82E1: - return "GL_SHADER"; - case 0x82E2: - return "GL_PROGRAM"; - case 0x82E3: - return "GL_QUERY"; - case 0x82E4: - return "GL_PROGRAM_PIPELINE"; - case 0x82E5: - return "GL_MAX_VERTEX_ATTRIB_STRIDE"; - case 0x82E6: - return "GL_SAMPLER"; - case 0x82E7: - return "GL_DISPLAY_LIST"; - case 0x82E8: - return "GL_MAX_LABEL_LENGTH"; - case 0x82E9: - return "GL_NUM_SHADING_LANGUAGE_VERSIONS"; - case 0x82EA: - return "GL_QUERY_TARGET"; - case 0x82EC: - return "GL_TRANSFORM_FEEDBACK_OVERFLOW"; - case 0x82ED: - return "GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW"; - case 0x82EE: - return "GL_VERTICES_SUBMITTED"; - case 0x82EF: - return "GL_PRIMITIVES_SUBMITTED"; - case 0x82F0: - return "GL_VERTEX_SHADER_INVOCATIONS"; - case 0x82F1: - return "GL_TESS_CONTROL_SHADER_PATCHES"; - case 0x82F2: - return "GL_TESS_EVALUATION_SHADER_INVOCATIONS"; - case 0x82F3: - return "GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED"; - case 0x82F4: - return "GL_FRAGMENT_SHADER_INVOCATIONS"; - case 0x82F5: - return "GL_COMPUTE_SHADER_INVOCATIONS"; - case 0x82F6: - return "GL_CLIPPING_INPUT_PRIMITIVES"; - case 0x82F7: - return "GL_CLIPPING_OUTPUT_PRIMITIVES"; - case 0x82F9: - return "GL_MAX_CULL_DISTANCES"; - case 0x82FA: - return "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"; - case 0x82FB: - return "GL_CONTEXT_RELEASE_BEHAVIOR"; - case 0x82FC: - return "GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"; - case 0x8362: - return "GL_UNSIGNED_BYTE_2_3_3_REV"; - case 0x8363: - return "GL_UNSIGNED_SHORT_5_6_5"; - case 0x8364: - return "GL_UNSIGNED_SHORT_5_6_5_REV"; - case 0x8365: - return "GL_UNSIGNED_SHORT_4_4_4_4_REV"; - case 0x8366: - return "GL_UNSIGNED_SHORT_1_5_5_5_REV"; - case 0x8367: - return "GL_UNSIGNED_INT_8_8_8_8_REV"; - case 0x8368: - return "GL_UNSIGNED_INT_2_10_10_10_REV"; - case 0x8370: - return "GL_MIRRORED_REPEAT"; - case 0x83F0: - return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; - case 0x83F1: - return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; - case 0x83F2: - return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; - case 0x83F3: - return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; - case 0x8450: - return "GL_FOG_COORD_SRC"; - case 0x8451: - return "GL_FOG_COORD"; - case 0x8452: - return "GL_FRAGMENT_DEPTH"; - case 0x8453: - return "GL_CURRENT_FOG_COORD"; - case 0x8454: - return "GL_FOG_COORD_ARRAY_TYPE"; - case 0x8455: - return "GL_FOG_COORD_ARRAY_STRIDE"; - case 0x8456: - return "GL_FOG_COORD_ARRAY_POINTER"; - case 0x8457: - return "GL_FOG_COORD_ARRAY"; - case 0x8458: - return "GL_COLOR_SUM"; - case 0x8459: - return "GL_CURRENT_SECONDARY_COLOR"; - case 0x845A: - return "GL_SECONDARY_COLOR_ARRAY_SIZE"; - case 0x845B: - return "GL_SECONDARY_COLOR_ARRAY_TYPE"; - case 0x845C: - return "GL_SECONDARY_COLOR_ARRAY_STRIDE"; - case 0x845D: - return "GL_SECONDARY_COLOR_ARRAY_POINTER"; - case 0x845E: - return "GL_SECONDARY_COLOR_ARRAY"; - case 0x845F: - return "GL_CURRENT_RASTER_SECONDARY_COLOR"; - case 0x846D: - return "GL_ALIASED_POINT_SIZE_RANGE"; - case 0x846E: - return "GL_ALIASED_LINE_WIDTH_RANGE"; - case 0x84C0: - return "GL_TEXTURE0"; - case 0x84C1: - return "GL_TEXTURE1"; - case 0x84C2: - return "GL_TEXTURE2"; - case 0x84C3: - return "GL_TEXTURE3"; - case 0x84C4: - return "GL_TEXTURE4"; - case 0x84C5: - return "GL_TEXTURE5"; - case 0x84C6: - return "GL_TEXTURE6"; - case 0x84C7: - return "GL_TEXTURE7"; - case 0x84C8: - return "GL_TEXTURE8"; - case 0x84C9: - return "GL_TEXTURE9"; - case 0x84CA: - return "GL_TEXTURE10"; - case 0x84CB: - return "GL_TEXTURE11"; - case 0x84CC: - return "GL_TEXTURE12"; - case 0x84CD: - return "GL_TEXTURE13"; - case 0x84CE: - return "GL_TEXTURE14"; - case 0x84CF: - return "GL_TEXTURE15"; - case 0x84D0: - return "GL_TEXTURE16"; - case 0x84D1: - return "GL_TEXTURE17"; - case 0x84D2: - return "GL_TEXTURE18"; - case 0x84D3: - return "GL_TEXTURE19"; - case 0x84D4: - return "GL_TEXTURE20"; - case 0x84D5: - return "GL_TEXTURE21"; - case 0x84D6: - return "GL_TEXTURE22"; - case 0x84D7: - return "GL_TEXTURE23"; - case 0x84D8: - return "GL_TEXTURE24"; - case 0x84D9: - return "GL_TEXTURE25"; - case 0x84DA: - return "GL_TEXTURE26"; - case 0x84DB: - return "GL_TEXTURE27"; - case 0x84DC: - return "GL_TEXTURE28"; - case 0x84DD: - return "GL_TEXTURE29"; - case 0x84DE: - return "GL_TEXTURE30"; - case 0x84DF: - return "GL_TEXTURE31"; - case 0x84E0: - return "GL_ACTIVE_TEXTURE"; - case 0x84E1: - return "GL_CLIENT_ACTIVE_TEXTURE"; - case 0x84E2: - return "GL_MAX_TEXTURE_UNITS"; - case 0x84E3: - return "GL_TRANSPOSE_MODELVIEW_MATRIX"; - case 0x84E4: - return "GL_TRANSPOSE_PROJECTION_MATRIX"; - case 0x84E5: - return "GL_TRANSPOSE_TEXTURE_MATRIX"; - case 0x84E6: - return "GL_TRANSPOSE_COLOR_MATRIX"; - case 0x84E7: - return "GL_SUBTRACT"; - case 0x84E8: - return "GL_MAX_RENDERBUFFER_SIZE"; - case 0x84E9: - return "GL_COMPRESSED_ALPHA"; - case 0x84EA: - return "GL_COMPRESSED_LUMINANCE"; - case 0x84EB: - return "GL_COMPRESSED_LUMINANCE_ALPHA"; - case 0x84EC: - return "GL_COMPRESSED_INTENSITY"; - case 0x84ED: - return "GL_COMPRESSED_RGB"; - case 0x84EE: - return "GL_COMPRESSED_RGBA"; - case 0x84EF: - return "GL_TEXTURE_COMPRESSION_HINT"; - case 0x84F0: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER"; - case 0x84F1: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER"; - case 0x84F2: - return "GL_ALL_COMPLETED_NV"; - case 0x84F3: - return "GL_FENCE_STATUS_NV"; - case 0x84F4: - return "GL_FENCE_CONDITION_NV"; - case 0x84F5: - return "GL_TEXTURE_RECTANGLE"; - case 0x84F6: - return "GL_TEXTURE_BINDING_RECTANGLE"; - case 0x84F7: - return "GL_PROXY_TEXTURE_RECTANGLE"; - case 0x84F8: - return "GL_MAX_RECTANGLE_TEXTURE_SIZE"; - case 0x84F9: - return "GL_DEPTH_STENCIL"; - case 0x84FA: - return "GL_UNSIGNED_INT_24_8"; - case 0x84FD: - return "GL_MAX_TEXTURE_LOD_BIAS"; - case 0x84FE: - return "GL_TEXTURE_MAX_ANISOTROPY"; - case 0x84FF: - return "GL_MAX_TEXTURE_MAX_ANISOTROPY"; - case 0x8500: - return "GL_TEXTURE_FILTER_CONTROL"; - case 0x8501: - return "GL_TEXTURE_LOD_BIAS"; - case 0x8507: - return "GL_INCR_WRAP"; - case 0x8508: - return "GL_DECR_WRAP"; - case 0x8511: - return "GL_NORMAL_MAP"; - case 0x8512: - return "GL_REFLECTION_MAP"; - case 0x8513: - return "GL_TEXTURE_CUBE_MAP"; - case 0x8514: - return "GL_TEXTURE_BINDING_CUBE_MAP"; - case 0x8515: - return "GL_TEXTURE_CUBE_MAP_POSITIVE_X"; - case 0x8516: - return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"; - case 0x8517: - return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y"; - case 0x8518: - return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"; - case 0x8519: - return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z"; - case 0x851A: - return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"; - case 0x851B: - return "GL_PROXY_TEXTURE_CUBE_MAP"; - case 0x851C: - return "GL_MAX_CUBE_MAP_TEXTURE_SIZE"; - case 0x8570: - return "GL_COMBINE"; - case 0x8571: - return "GL_COMBINE_RGB"; - case 0x8572: - return "GL_COMBINE_ALPHA"; - case 0x8573: - return "GL_RGB_SCALE"; - case 0x8574: - return "GL_ADD_SIGNED"; - case 0x8575: - return "GL_INTERPOLATE"; - case 0x8576: - return "GL_CONSTANT"; - case 0x8577: - return "GL_PRIMARY_COLOR"; - case 0x8578: - return "GL_PREVIOUS"; - case 0x8580: - return "GL_SRC0_RGB"; - case 0x8581: - return "GL_SRC1_RGB"; - case 0x8582: - return "GL_SRC2_RGB"; - case 0x8588: - return "GL_SRC0_ALPHA"; - case 0x8589: - return "GL_SRC1_ALPHA"; - case 0x858A: - return "GL_SRC2_ALPHA"; - case 0x8590: - return "GL_OPERAND0_RGB"; - case 0x8591: - return "GL_OPERAND1_RGB"; - case 0x8592: - return "GL_OPERAND2_RGB"; - case 0x8598: - return "GL_OPERAND0_ALPHA"; - case 0x8599: - return "GL_OPERAND1_ALPHA"; - case 0x859A: - return "GL_OPERAND2_ALPHA"; - case 0x85B5: - return "GL_VERTEX_ARRAY_BINDING"; - case 0x8622: - return "GL_VERTEX_ATTRIB_ARRAY_ENABLED"; - case 0x8623: - return "GL_VERTEX_ATTRIB_ARRAY_SIZE"; - case 0x8624: - return "GL_VERTEX_ATTRIB_ARRAY_STRIDE"; - case 0x8625: - return "GL_VERTEX_ATTRIB_ARRAY_TYPE"; - case 0x8626: - return "GL_CURRENT_VERTEX_ATTRIB"; - case 0x8642: - return "GL_PROGRAM_POINT_SIZE"; - case 0x8643: - return "GL_VERTEX_PROGRAM_TWO_SIDE"; - case 0x8645: - return "GL_VERTEX_ATTRIB_ARRAY_POINTER"; - case 0x864F: - return "GL_DEPTH_CLAMP"; - case 0x86A0: - return "GL_TEXTURE_COMPRESSED_IMAGE_SIZE"; - case 0x86A1: - return "GL_TEXTURE_COMPRESSED"; - case 0x86A2: - return "GL_NUM_COMPRESSED_TEXTURE_FORMATS"; - case 0x86A3: - return "GL_COMPRESSED_TEXTURE_FORMATS"; - case 0x86AE: - return "GL_DOT3_RGB"; - case 0x86AF: - return "GL_DOT3_RGBA"; - case 0x8741: - return "GL_PROGRAM_BINARY_LENGTH"; - case 0x8743: - return "GL_MIRROR_CLAMP_TO_EDGE"; - case 0x874E: - return "GL_VERTEX_ATTRIB_ARRAY_LONG"; - case 0x8764: - return "GL_BUFFER_SIZE"; - case 0x8765: - return "GL_BUFFER_USAGE"; - case 0x87FE: - return "GL_NUM_PROGRAM_BINARY_FORMATS"; - case 0x87FF: - return "GL_PROGRAM_BINARY_FORMATS"; - case 0x8800: - return "GL_STENCIL_BACK_FUNC"; - case 0x8801: - return "GL_STENCIL_BACK_FAIL"; - case 0x8802: - return "GL_STENCIL_BACK_PASS_DEPTH_FAIL"; - case 0x8803: - return "GL_STENCIL_BACK_PASS_DEPTH_PASS"; - case 0x8814: - return "GL_RGBA32F"; - case 0x8815: - return "GL_RGB32F"; - case 0x8816: - return "GL_ALPHA32F_EXT"; - case 0x8818: - return "GL_LUMINANCE32F_EXT"; - case 0x8819: - return "GL_LUMINANCE_ALPHA32F_EXT"; - case 0x881A: - return "GL_RGBA16F"; - case 0x881B: - return "GL_RGB16F"; - case 0x881C: - return "GL_ALPHA16F_EXT"; - case 0x881E: - return "GL_LUMINANCE16F_EXT"; - case 0x881F: - return "GL_LUMINANCE_ALPHA16F_EXT"; - case 0x8824: - return "GL_MAX_DRAW_BUFFERS"; - case 0x8825: - return "GL_DRAW_BUFFER0"; - case 0x8826: - return "GL_DRAW_BUFFER1"; - case 0x8827: - return "GL_DRAW_BUFFER2"; - case 0x8828: - return "GL_DRAW_BUFFER3"; - case 0x8829: - return "GL_DRAW_BUFFER4"; - case 0x882A: - return "GL_DRAW_BUFFER5"; - case 0x882B: - return "GL_DRAW_BUFFER6"; - case 0x882C: - return "GL_DRAW_BUFFER7"; - case 0x882D: - return "GL_DRAW_BUFFER8"; - case 0x882E: - return "GL_DRAW_BUFFER9"; - case 0x882F: - return "GL_DRAW_BUFFER10"; - case 0x8830: - return "GL_DRAW_BUFFER11"; - case 0x8831: - return "GL_DRAW_BUFFER12"; - case 0x8832: - return "GL_DRAW_BUFFER13"; - case 0x8833: - return "GL_DRAW_BUFFER14"; - case 0x8834: - return "GL_DRAW_BUFFER15"; - case 0x883D: - return "GL_BLEND_EQUATION_ALPHA"; - case 0x884A: - return "GL_TEXTURE_DEPTH_SIZE"; - case 0x884B: - return "GL_DEPTH_TEXTURE_MODE"; - case 0x884C: - return "GL_TEXTURE_COMPARE_MODE"; - case 0x884D: - return "GL_TEXTURE_COMPARE_FUNC"; - case 0x884E: - return "GL_COMPARE_R_TO_TEXTURE"; - case 0x884F: - return "GL_TEXTURE_CUBE_MAP_SEAMLESS"; - case 0x8861: - return "GL_POINT_SPRITE"; - case 0x8862: - return "GL_COORD_REPLACE"; - case 0x8864: - return "GL_QUERY_COUNTER_BITS"; - case 0x8865: - return "GL_CURRENT_QUERY"; - case 0x8866: - return "GL_QUERY_RESULT"; - case 0x8867: - return "GL_QUERY_RESULT_AVAILABLE"; - case 0x8869: - return "GL_MAX_VERTEX_ATTRIBS"; - case 0x886A: - return "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"; - case 0x886C: - return "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"; - case 0x886D: - return "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"; - case 0x8871: - return "GL_MAX_TEXTURE_COORDS"; - case 0x8872: - return "GL_MAX_TEXTURE_IMAGE_UNITS"; - case 0x887F: - return "GL_GEOMETRY_SHADER_INVOCATIONS"; - case 0x8892: - return "GL_ARRAY_BUFFER"; - case 0x8893: - return "GL_ELEMENT_ARRAY_BUFFER"; - case 0x8894: - return "GL_ARRAY_BUFFER_BINDING"; - case 0x8895: - return "GL_ELEMENT_ARRAY_BUFFER_BINDING"; - case 0x8896: - return "GL_VERTEX_ARRAY_BUFFER_BINDING"; - case 0x8897: - return "GL_NORMAL_ARRAY_BUFFER_BINDING"; - case 0x8898: - return "GL_COLOR_ARRAY_BUFFER_BINDING"; - case 0x8899: - return "GL_INDEX_ARRAY_BUFFER_BINDING"; - case 0x889A: - return "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING"; - case 0x889B: - return "GL_EDGE_FLAG_ARRAY_BUFFER_BINDING"; - case 0x889C: - return "GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING"; - case 0x889D: - return "GL_FOG_COORD_ARRAY_BUFFER_BINDING"; - case 0x889E: - return "GL_WEIGHT_ARRAY_BUFFER_BINDING"; - case 0x889F: - return "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"; - case 0x88B8: - return "GL_READ_ONLY"; - case 0x88B9: - return "GL_WRITE_ONLY"; - case 0x88BA: - return "GL_READ_WRITE"; - case 0x88BB: - return "GL_BUFFER_ACCESS"; - case 0x88BC: - return "GL_BUFFER_MAPPED"; - case 0x88BD: - return "GL_BUFFER_MAP_POINTER"; - case 0x88BF: - return "GL_TIME_ELAPSED"; - case 0x88E0: - return "GL_STREAM_DRAW"; - case 0x88E1: - return "GL_STREAM_READ"; - case 0x88E2: - return "GL_STREAM_COPY"; - case 0x88E4: - return "GL_STATIC_DRAW"; - case 0x88E5: - return "GL_STATIC_READ"; - case 0x88E6: - return "GL_STATIC_COPY"; - case 0x88E8: - return "GL_DYNAMIC_DRAW"; - case 0x88E9: - return "GL_DYNAMIC_READ"; - case 0x88EA: - return "GL_DYNAMIC_COPY"; - case 0x88EB: - return "GL_PIXEL_PACK_BUFFER"; - case 0x88EC: - return "GL_PIXEL_UNPACK_BUFFER"; - case 0x88ED: - return "GL_PIXEL_PACK_BUFFER_BINDING"; - case 0x88EF: - return "GL_PIXEL_UNPACK_BUFFER_BINDING"; - case 0x88F0: - return "GL_DEPTH24_STENCIL8"; - case 0x88F1: - return "GL_TEXTURE_STENCIL_SIZE"; - case 0x88F9: - return "GL_SRC1_COLOR"; - case 0x88FA: - return "GL_ONE_MINUS_SRC1_COLOR"; - case 0x88FB: - return "GL_ONE_MINUS_SRC1_ALPHA"; - case 0x88FC: - return "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS"; - case 0x88FD: - return "GL_VERTEX_ATTRIB_ARRAY_INTEGER"; - case 0x88FE: - return "GL_VERTEX_ATTRIB_ARRAY_DIVISOR"; - case 0x88FF: - return "GL_MAX_ARRAY_TEXTURE_LAYERS"; - case 0x8904: - return "GL_MIN_PROGRAM_TEXEL_OFFSET"; - case 0x8905: - return "GL_MAX_PROGRAM_TEXEL_OFFSET"; - case 0x8914: - return "GL_SAMPLES_PASSED"; - case 0x8916: - return "GL_GEOMETRY_VERTICES_OUT"; - case 0x8917: - return "GL_GEOMETRY_INPUT_TYPE"; - case 0x8918: - return "GL_GEOMETRY_OUTPUT_TYPE"; - case 0x8919: - return "GL_SAMPLER_BINDING"; - case 0x891A: - return "GL_CLAMP_VERTEX_COLOR"; - case 0x891B: - return "GL_CLAMP_FRAGMENT_COLOR"; - case 0x891C: - return "GL_CLAMP_READ_COLOR"; - case 0x891D: - return "GL_FIXED_ONLY"; - case 0x8A11: - return "GL_UNIFORM_BUFFER"; - case 0x8A28: - return "GL_UNIFORM_BUFFER_BINDING"; - case 0x8A29: - return "GL_UNIFORM_BUFFER_START"; - case 0x8A2A: - return "GL_UNIFORM_BUFFER_SIZE"; - case 0x8A2B: - return "GL_MAX_VERTEX_UNIFORM_BLOCKS"; - case 0x8A2C: - return "GL_MAX_GEOMETRY_UNIFORM_BLOCKS"; - case 0x8A2D: - return "GL_MAX_FRAGMENT_UNIFORM_BLOCKS"; - case 0x8A2E: - return "GL_MAX_COMBINED_UNIFORM_BLOCKS"; - case 0x8A2F: - return "GL_MAX_UNIFORM_BUFFER_BINDINGS"; - case 0x8A30: - return "GL_MAX_UNIFORM_BLOCK_SIZE"; - case 0x8A31: - return "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"; - case 0x8A32: - return "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"; - case 0x8A33: - return "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"; - case 0x8A34: - return "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"; - case 0x8A35: - return "GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"; - case 0x8A36: - return "GL_ACTIVE_UNIFORM_BLOCKS"; - case 0x8A37: - return "GL_UNIFORM_TYPE"; - case 0x8A38: - return "GL_UNIFORM_SIZE"; - case 0x8A39: - return "GL_UNIFORM_NAME_LENGTH"; - case 0x8A3A: - return "GL_UNIFORM_BLOCK_INDEX"; - case 0x8A3B: - return "GL_UNIFORM_OFFSET"; - case 0x8A3C: - return "GL_UNIFORM_ARRAY_STRIDE"; - case 0x8A3D: - return "GL_UNIFORM_MATRIX_STRIDE"; - case 0x8A3E: - return "GL_UNIFORM_IS_ROW_MAJOR"; - case 0x8A3F: - return "GL_UNIFORM_BLOCK_BINDING"; - case 0x8A40: - return "GL_UNIFORM_BLOCK_DATA_SIZE"; - case 0x8A41: - return "GL_UNIFORM_BLOCK_NAME_LENGTH"; - case 0x8A42: - return "GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"; - case 0x8A43: - return "GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"; - case 0x8A44: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"; - case 0x8A45: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"; - case 0x8A46: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"; - case 0x8A48: - return "GL_TEXTURE_SRGB_DECODE_EXT"; - case 0x8A49: - return "GL_DECODE_EXT"; - case 0x8A4A: - return "GL_SKIP_DECODE_EXT"; - case 0x8A4F: - return "GL_PROGRAM_PIPELINE_OBJECT_EXT"; - case 0x8A52: - return "GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT"; - case 0x8B30: - return "GL_FRAGMENT_SHADER"; - case 0x8B31: - return "GL_VERTEX_SHADER"; - case 0x8B40: - return "GL_PROGRAM_OBJECT_EXT"; - case 0x8B48: - return "GL_SHADER_OBJECT_EXT"; - case 0x8B49: - return "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS"; - case 0x8B4A: - return "GL_MAX_VERTEX_UNIFORM_COMPONENTS"; - case 0x8B4B: - return "GL_MAX_VARYING_FLOATS"; - case 0x8B4C: - return "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"; - case 0x8B4D: - return "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"; - case 0x8B4F: - return "GL_SHADER_TYPE"; - case 0x8B50: - return "GL_FLOAT_VEC2"; - case 0x8B51: - return "GL_FLOAT_VEC3"; - case 0x8B52: - return "GL_FLOAT_VEC4"; - case 0x8B53: - return "GL_INT_VEC2"; - case 0x8B54: - return "GL_INT_VEC3"; - case 0x8B55: - return "GL_INT_VEC4"; - case 0x8B56: - return "GL_BOOL"; - case 0x8B57: - return "GL_BOOL_VEC2"; - case 0x8B58: - return "GL_BOOL_VEC3"; - case 0x8B59: - return "GL_BOOL_VEC4"; - case 0x8B5A: - return "GL_FLOAT_MAT2"; - case 0x8B5B: - return "GL_FLOAT_MAT3"; - case 0x8B5C: - return "GL_FLOAT_MAT4"; - case 0x8B5D: - return "GL_SAMPLER_1D"; - case 0x8B5E: - return "GL_SAMPLER_2D"; - case 0x8B5F: - return "GL_SAMPLER_3D"; - case 0x8B60: - return "GL_SAMPLER_CUBE"; - case 0x8B61: - return "GL_SAMPLER_1D_SHADOW"; - case 0x8B62: - return "GL_SAMPLER_2D_SHADOW"; - case 0x8B63: - return "GL_SAMPLER_2D_RECT"; - case 0x8B64: - return "GL_SAMPLER_2D_RECT_SHADOW"; - case 0x8B65: - return "GL_FLOAT_MAT2x3"; - case 0x8B66: - return "GL_FLOAT_MAT2x4"; - case 0x8B67: - return "GL_FLOAT_MAT3x2"; - case 0x8B68: - return "GL_FLOAT_MAT3x4"; - case 0x8B69: - return "GL_FLOAT_MAT4x2"; - case 0x8B6A: - return "GL_FLOAT_MAT4x3"; - case 0x8B80: - return "GL_DELETE_STATUS"; - case 0x8B81: - return "GL_COMPILE_STATUS"; - case 0x8B82: - return "GL_LINK_STATUS"; - case 0x8B83: - return "GL_VALIDATE_STATUS"; - case 0x8B84: - return "GL_INFO_LOG_LENGTH"; - case 0x8B85: - return "GL_ATTACHED_SHADERS"; - case 0x8B86: - return "GL_ACTIVE_UNIFORMS"; - case 0x8B87: - return "GL_ACTIVE_UNIFORM_MAX_LENGTH"; - case 0x8B88: - return "GL_SHADER_SOURCE_LENGTH"; - case 0x8B89: - return "GL_ACTIVE_ATTRIBUTES"; - case 0x8B8A: - return "GL_ACTIVE_ATTRIBUTE_MAX_LENGTH"; - case 0x8B8B: - return "GL_FRAGMENT_SHADER_DERIVATIVE_HINT"; - case 0x8B8C: - return "GL_SHADING_LANGUAGE_VERSION"; - case 0x8B8D: - return "GL_CURRENT_PROGRAM"; - case 0x8B90: - return "GL_PALETTE4_RGB8_OES"; - case 0x8B91: - return "GL_PALETTE4_RGBA8_OES"; - case 0x8B92: - return "GL_PALETTE4_R5_G6_B5_OES"; - case 0x8B93: - return "GL_PALETTE4_RGBA4_OES"; - case 0x8B94: - return "GL_PALETTE4_RGB5_A1_OES"; - case 0x8B95: - return "GL_PALETTE8_RGB8_OES"; - case 0x8B96: - return "GL_PALETTE8_RGBA8_OES"; - case 0x8B97: - return "GL_PALETTE8_R5_G6_B5_OES"; - case 0x8B98: - return "GL_PALETTE8_RGBA4_OES"; - case 0x8B99: - return "GL_PALETTE8_RGB5_A1_OES"; - case 0x8B9A: - return "GL_IMPLEMENTATION_COLOR_READ_TYPE"; - case 0x8B9B: - return "GL_IMPLEMENTATION_COLOR_READ_FORMAT"; - case 0x8BBB: - return "GL_FRAMEBUFFER_FLIP_Y_MESA"; - case 0x8BC0: - return "GL_COUNTER_TYPE_AMD"; - case 0x8BC1: - return "GL_COUNTER_RANGE_AMD"; - case 0x8BC2: - return "GL_UNSIGNED_INT64_AMD"; - case 0x8BC3: - return "GL_PERCENTAGE_AMD"; - case 0x8BC4: - return "GL_PERFMON_RESULT_AVAILABLE_AMD"; - case 0x8BC5: - return "GL_PERFMON_RESULT_SIZE_AMD"; - case 0x8BC6: - return "GL_PERFMON_RESULT_AMD"; - case 0x8C10: - return "GL_TEXTURE_RED_TYPE"; - case 0x8C11: - return "GL_TEXTURE_GREEN_TYPE"; - case 0x8C12: - return "GL_TEXTURE_BLUE_TYPE"; - case 0x8C13: - return "GL_TEXTURE_ALPHA_TYPE"; - case 0x8C14: - return "GL_TEXTURE_LUMINANCE_TYPE"; - case 0x8C15: - return "GL_TEXTURE_INTENSITY_TYPE"; - case 0x8C16: - return "GL_TEXTURE_DEPTH_TYPE"; - case 0x8C17: - return "GL_UNSIGNED_NORMALIZED"; - case 0x8C18: - return "GL_TEXTURE_1D_ARRAY"; - case 0x8C19: - return "GL_PROXY_TEXTURE_1D_ARRAY"; - case 0x8C1A: - return "GL_TEXTURE_2D_ARRAY"; - case 0x8C1B: - return "GL_PROXY_TEXTURE_2D_ARRAY"; - case 0x8C1C: - return "GL_TEXTURE_BINDING_1D_ARRAY"; - case 0x8C1D: - return "GL_TEXTURE_BINDING_2D_ARRAY"; - case 0x8C29: - return "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"; - case 0x8C2A: - return "GL_TEXTURE_BUFFER"; - case 0x8C2B: - return "GL_MAX_TEXTURE_BUFFER_SIZE"; - case 0x8C2C: - return "GL_TEXTURE_BINDING_BUFFER"; - case 0x8C2D: - return "GL_TEXTURE_BUFFER_DATA_STORE_BINDING"; - case 0x8C2F: - return "GL_ANY_SAMPLES_PASSED"; - case 0x8C36: - return "GL_SAMPLE_SHADING"; - case 0x8C37: - return "GL_MIN_SAMPLE_SHADING_VALUE"; - case 0x8C3A: - return "GL_R11F_G11F_B10F"; - case 0x8C3B: - return "GL_UNSIGNED_INT_10F_11F_11F_REV"; - case 0x8C3D: - return "GL_RGB9_E5"; - case 0x8C3E: - return "GL_UNSIGNED_INT_5_9_9_9_REV"; - case 0x8C3F: - return "GL_TEXTURE_SHARED_SIZE"; - case 0x8C40: - return "GL_SRGB"; - case 0x8C41: - return "GL_SRGB8"; - case 0x8C42: - return "GL_SRGB_ALPHA"; - case 0x8C43: - return "GL_SRGB8_ALPHA8"; - case 0x8C44: - return "GL_SLUMINANCE_ALPHA"; - case 0x8C45: - return "GL_SLUMINANCE8_ALPHA8"; - case 0x8C46: - return "GL_SLUMINANCE"; - case 0x8C47: - return "GL_SLUMINANCE8"; - case 0x8C48: - return "GL_COMPRESSED_SRGB"; - case 0x8C49: - return "GL_COMPRESSED_SRGB_ALPHA"; - case 0x8C4A: - return "GL_COMPRESSED_SLUMINANCE"; - case 0x8C4B: - return "GL_COMPRESSED_SLUMINANCE_ALPHA"; - case 0x8C76: - return "GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"; - case 0x8C7F: - return "GL_TRANSFORM_FEEDBACK_BUFFER_MODE"; - case 0x8C80: - return "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS"; - case 0x8C83: - return "GL_TRANSFORM_FEEDBACK_VARYINGS"; - case 0x8C84: - return "GL_TRANSFORM_FEEDBACK_BUFFER_START"; - case 0x8C85: - return "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"; - case 0x8C87: - return "GL_PRIMITIVES_GENERATED"; - case 0x8C88: - return "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"; - case 0x8C89: - return "GL_RASTERIZER_DISCARD"; - case 0x8C8A: - return "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS"; - case 0x8C8B: - return "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"; - case 0x8C8C: - return "GL_INTERLEAVED_ATTRIBS"; - case 0x8C8D: - return "GL_SEPARATE_ATTRIBS"; - case 0x8C8E: - return "GL_TRANSFORM_FEEDBACK_BUFFER"; - case 0x8C8F: - return "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"; - case 0x8CA0: - return "GL_POINT_SPRITE_COORD_ORIGIN"; - case 0x8CA1: - return "GL_LOWER_LEFT"; - case 0x8CA2: - return "GL_UPPER_LEFT"; - case 0x8CA3: - return "GL_STENCIL_BACK_REF"; - case 0x8CA4: - return "GL_STENCIL_BACK_VALUE_MASK"; - case 0x8CA5: - return "GL_STENCIL_BACK_WRITEMASK"; - case 0x8CA6: - return "GL_FRAMEBUFFER_BINDING"; - case 0x8CA7: - return "GL_RENDERBUFFER_BINDING"; - case 0x8CA8: - return "GL_READ_FRAMEBUFFER"; - case 0x8CA9: - return "GL_DRAW_FRAMEBUFFER"; - case 0x8CAA: - return "GL_READ_FRAMEBUFFER_BINDING"; - case 0x8CAB: - return "GL_RENDERBUFFER_SAMPLES"; - case 0x8CAC: - return "GL_DEPTH_COMPONENT32F"; - case 0x8CAD: - return "GL_DEPTH32F_STENCIL8"; - case 0x8CD0: - return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"; - case 0x8CD1: - return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"; - case 0x8CD2: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"; - case 0x8CD3: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"; - case 0x8CD4: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"; - case 0x8CD5: - return "GL_FRAMEBUFFER_COMPLETE"; - case 0x8CD6: - return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; - case 0x8CD7: - return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; - case 0x8CDB: - return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; - case 0x8CDC: - return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; - case 0x8CDD: - return "GL_FRAMEBUFFER_UNSUPPORTED"; - case 0x8CDF: - return "GL_MAX_COLOR_ATTACHMENTS"; - case 0x8CE0: - return "GL_COLOR_ATTACHMENT0"; - case 0x8CE1: - return "GL_COLOR_ATTACHMENT1"; - case 0x8CE2: - return "GL_COLOR_ATTACHMENT2"; - case 0x8CE3: - return "GL_COLOR_ATTACHMENT3"; - case 0x8CE4: - return "GL_COLOR_ATTACHMENT4"; - case 0x8CE5: - return "GL_COLOR_ATTACHMENT5"; - case 0x8CE6: - return "GL_COLOR_ATTACHMENT6"; - case 0x8CE7: - return "GL_COLOR_ATTACHMENT7"; - case 0x8CE8: - return "GL_COLOR_ATTACHMENT8"; - case 0x8CE9: - return "GL_COLOR_ATTACHMENT9"; - case 0x8CEA: - return "GL_COLOR_ATTACHMENT10"; - case 0x8CEB: - return "GL_COLOR_ATTACHMENT11"; - case 0x8CEC: - return "GL_COLOR_ATTACHMENT12"; - case 0x8CED: - return "GL_COLOR_ATTACHMENT13"; - case 0x8CEE: - return "GL_COLOR_ATTACHMENT14"; - case 0x8CEF: - return "GL_COLOR_ATTACHMENT15"; - case 0x8CF0: - return "GL_COLOR_ATTACHMENT16"; - case 0x8CF1: - return "GL_COLOR_ATTACHMENT17"; - case 0x8CF2: - return "GL_COLOR_ATTACHMENT18"; - case 0x8CF3: - return "GL_COLOR_ATTACHMENT19"; - case 0x8CF4: - return "GL_COLOR_ATTACHMENT20"; - case 0x8CF5: - return "GL_COLOR_ATTACHMENT21"; - case 0x8CF6: - return "GL_COLOR_ATTACHMENT22"; - case 0x8CF7: - return "GL_COLOR_ATTACHMENT23"; - case 0x8CF8: - return "GL_COLOR_ATTACHMENT24"; - case 0x8CF9: - return "GL_COLOR_ATTACHMENT25"; - case 0x8CFA: - return "GL_COLOR_ATTACHMENT26"; - case 0x8CFB: - return "GL_COLOR_ATTACHMENT27"; - case 0x8CFC: - return "GL_COLOR_ATTACHMENT28"; - case 0x8CFD: - return "GL_COLOR_ATTACHMENT29"; - case 0x8CFE: - return "GL_COLOR_ATTACHMENT30"; - case 0x8CFF: - return "GL_COLOR_ATTACHMENT31"; - case 0x8D00: - return "GL_DEPTH_ATTACHMENT"; - case 0x8D20: - return "GL_STENCIL_ATTACHMENT"; - case 0x8D40: - return "GL_FRAMEBUFFER"; - case 0x8D41: - return "GL_RENDERBUFFER"; - case 0x8D42: - return "GL_RENDERBUFFER_WIDTH"; - case 0x8D43: - return "GL_RENDERBUFFER_HEIGHT"; - case 0x8D44: - return "GL_RENDERBUFFER_INTERNAL_FORMAT"; - case 0x8D46: - return "GL_STENCIL_INDEX1"; - case 0x8D47: - return "GL_STENCIL_INDEX4"; - case 0x8D48: - return "GL_STENCIL_INDEX8"; - case 0x8D49: - return "GL_STENCIL_INDEX16"; - case 0x8D50: - return "GL_RENDERBUFFER_RED_SIZE"; - case 0x8D51: - return "GL_RENDERBUFFER_GREEN_SIZE"; - case 0x8D52: - return "GL_RENDERBUFFER_BLUE_SIZE"; - case 0x8D53: - return "GL_RENDERBUFFER_ALPHA_SIZE"; - case 0x8D54: - return "GL_RENDERBUFFER_DEPTH_SIZE"; - case 0x8D55: - return "GL_RENDERBUFFER_STENCIL_SIZE"; - case 0x8D56: - return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; - case 0x8D57: - return "GL_MAX_SAMPLES"; - case 0x8D62: - return "GL_RGB565"; - case 0x8D69: - return "GL_PRIMITIVE_RESTART_FIXED_INDEX"; - case 0x8D6A: - return "GL_ANY_SAMPLES_PASSED_CONSERVATIVE"; - case 0x8D6B: - return "GL_MAX_ELEMENT_INDEX"; - case 0x8D70: - return "GL_RGBA32UI"; - case 0x8D71: - return "GL_RGB32UI"; - case 0x8D76: - return "GL_RGBA16UI"; - case 0x8D77: - return "GL_RGB16UI"; - case 0x8D7C: - return "GL_RGBA8UI"; - case 0x8D7D: - return "GL_RGB8UI"; - case 0x8D82: - return "GL_RGBA32I"; - case 0x8D83: - return "GL_RGB32I"; - case 0x8D88: - return "GL_RGBA16I"; - case 0x8D89: - return "GL_RGB16I"; - case 0x8D8E: - return "GL_RGBA8I"; - case 0x8D8F: - return "GL_RGB8I"; - case 0x8D94: - return "GL_RED_INTEGER"; - case 0x8D95: - return "GL_GREEN_INTEGER"; - case 0x8D96: - return "GL_BLUE_INTEGER"; - case 0x8D97: - return "GL_ALPHA_INTEGER"; - case 0x8D98: - return "GL_RGB_INTEGER"; - case 0x8D99: - return "GL_RGBA_INTEGER"; - case 0x8D9A: - return "GL_BGR_INTEGER"; - case 0x8D9B: - return "GL_BGRA_INTEGER"; - case 0x8D9F: - return "GL_INT_2_10_10_10_REV"; - case 0x8DA7: - return "GL_FRAMEBUFFER_ATTACHMENT_LAYERED"; - case 0x8DA8: - return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; - case 0x8DAD: - return "GL_FLOAT_32_UNSIGNED_INT_24_8_REV"; - case 0x8DB9: - return "GL_FRAMEBUFFER_SRGB"; - case 0x8DBB: - return "GL_COMPRESSED_RED_RGTC1"; - case 0x8DBC: - return "GL_COMPRESSED_SIGNED_RED_RGTC1"; - case 0x8DBD: - return "GL_COMPRESSED_RG_RGTC2"; - case 0x8DBE: - return "GL_COMPRESSED_SIGNED_RG_RGTC2"; - case 0x8DC0: - return "GL_SAMPLER_1D_ARRAY"; - case 0x8DC1: - return "GL_SAMPLER_2D_ARRAY"; - case 0x8DC2: - return "GL_SAMPLER_BUFFER"; - case 0x8DC3: - return "GL_SAMPLER_1D_ARRAY_SHADOW"; - case 0x8DC4: - return "GL_SAMPLER_2D_ARRAY_SHADOW"; - case 0x8DC5: - return "GL_SAMPLER_CUBE_SHADOW"; - case 0x8DC6: - return "GL_UNSIGNED_INT_VEC2"; - case 0x8DC7: - return "GL_UNSIGNED_INT_VEC3"; - case 0x8DC8: - return "GL_UNSIGNED_INT_VEC4"; - case 0x8DC9: - return "GL_INT_SAMPLER_1D"; - case 0x8DCA: - return "GL_INT_SAMPLER_2D"; - case 0x8DCB: - return "GL_INT_SAMPLER_3D"; - case 0x8DCC: - return "GL_INT_SAMPLER_CUBE"; - case 0x8DCD: - return "GL_INT_SAMPLER_2D_RECT"; - case 0x8DCE: - return "GL_INT_SAMPLER_1D_ARRAY"; - case 0x8DCF: - return "GL_INT_SAMPLER_2D_ARRAY"; - case 0x8DD0: - return "GL_INT_SAMPLER_BUFFER"; - case 0x8DD1: - return "GL_UNSIGNED_INT_SAMPLER_1D"; - case 0x8DD2: - return "GL_UNSIGNED_INT_SAMPLER_2D"; - case 0x8DD3: - return "GL_UNSIGNED_INT_SAMPLER_3D"; - case 0x8DD4: - return "GL_UNSIGNED_INT_SAMPLER_CUBE"; - case 0x8DD5: - return "GL_UNSIGNED_INT_SAMPLER_2D_RECT"; - case 0x8DD6: - return "GL_UNSIGNED_INT_SAMPLER_1D_ARRAY"; - case 0x8DD7: - return "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY"; - case 0x8DD8: - return "GL_UNSIGNED_INT_SAMPLER_BUFFER"; - case 0x8DD9: - return "GL_GEOMETRY_SHADER"; - case 0x8DDF: - return "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"; - case 0x8DE0: - return "GL_MAX_GEOMETRY_OUTPUT_VERTICES"; - case 0x8DE1: - return "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"; - case 0x8DE5: - return "GL_ACTIVE_SUBROUTINES"; - case 0x8DE6: - return "GL_ACTIVE_SUBROUTINE_UNIFORMS"; - case 0x8DE7: - return "GL_MAX_SUBROUTINES"; - case 0x8DE8: - return "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS"; - case 0x8DF0: - return "GL_LOW_FLOAT"; - case 0x8DF1: - return "GL_MEDIUM_FLOAT"; - case 0x8DF2: - return "GL_HIGH_FLOAT"; - case 0x8DF3: - return "GL_LOW_INT"; - case 0x8DF4: - return "GL_MEDIUM_INT"; - case 0x8DF5: - return "GL_HIGH_INT"; - case 0x8DF8: - return "GL_SHADER_BINARY_FORMATS"; - case 0x8DF9: - return "GL_NUM_SHADER_BINARY_FORMATS"; - case 0x8DFA: - return "GL_SHADER_COMPILER"; - case 0x8DFB: - return "GL_MAX_VERTEX_UNIFORM_VECTORS"; - case 0x8DFC: - return "GL_MAX_VARYING_VECTORS"; - case 0x8DFD: - return "GL_MAX_FRAGMENT_UNIFORM_VECTORS"; - case 0x8E13: - return "GL_QUERY_WAIT"; - case 0x8E14: - return "GL_QUERY_NO_WAIT"; - case 0x8E15: - return "GL_QUERY_BY_REGION_WAIT"; - case 0x8E16: - return "GL_QUERY_BY_REGION_NO_WAIT"; - case 0x8E17: - return "GL_QUERY_WAIT_INVERTED"; - case 0x8E18: - return "GL_QUERY_NO_WAIT_INVERTED"; - case 0x8E19: - return "GL_QUERY_BY_REGION_WAIT_INVERTED"; - case 0x8E1A: - return "GL_QUERY_BY_REGION_NO_WAIT_INVERTED"; - case 0x8E1B: - return "GL_POLYGON_OFFSET_CLAMP"; - case 0x8E1E: - return "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"; - case 0x8E1F: - return "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"; - case 0x8E22: - return "GL_TRANSFORM_FEEDBACK"; - case 0x8E23: - return "GL_TRANSFORM_FEEDBACK_PAUSED"; - case 0x8E24: - return "GL_TRANSFORM_FEEDBACK_ACTIVE"; - case 0x8E25: - return "GL_TRANSFORM_FEEDBACK_BINDING"; - case 0x8E28: - return "GL_TIMESTAMP"; - case 0x8E42: - return "GL_TEXTURE_SWIZZLE_R"; - case 0x8E43: - return "GL_TEXTURE_SWIZZLE_G"; - case 0x8E44: - return "GL_TEXTURE_SWIZZLE_B"; - case 0x8E45: - return "GL_TEXTURE_SWIZZLE_A"; - case 0x8E46: - return "GL_TEXTURE_SWIZZLE_RGBA"; - case 0x8E47: - return "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"; - case 0x8E48: - return "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"; - case 0x8E49: - return "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"; - case 0x8E4A: - return "GL_NUM_COMPATIBLE_SUBROUTINES"; - case 0x8E4B: - return "GL_COMPATIBLE_SUBROUTINES"; - case 0x8E4C: - return "GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION"; - case 0x8E4D: - return "GL_FIRST_VERTEX_CONVENTION"; - case 0x8E4E: - return "GL_LAST_VERTEX_CONVENTION"; - case 0x8E4F: - return "GL_PROVOKING_VERTEX"; - case 0x8E50: - return "GL_SAMPLE_POSITION"; - case 0x8E51: - return "GL_SAMPLE_MASK"; - case 0x8E52: - return "GL_SAMPLE_MASK_VALUE"; - case 0x8E59: - return "GL_MAX_SAMPLE_MASK_WORDS"; - case 0x8E5A: - return "GL_MAX_GEOMETRY_SHADER_INVOCATIONS"; - case 0x8E5B: - return "GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"; - case 0x8E5C: - return "GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"; - case 0x8E5D: - return "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"; - case 0x8E5E: - return "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET"; - case 0x8E5F: - return "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"; - case 0x8E70: - return "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS"; - case 0x8E71: - return "GL_MAX_VERTEX_STREAMS"; - case 0x8E72: - return "GL_PATCH_VERTICES"; - case 0x8E73: - return "GL_PATCH_DEFAULT_INNER_LEVEL"; - case 0x8E74: - return "GL_PATCH_DEFAULT_OUTER_LEVEL"; - case 0x8E75: - return "GL_TESS_CONTROL_OUTPUT_VERTICES"; - case 0x8E76: - return "GL_TESS_GEN_MODE"; - case 0x8E77: - return "GL_TESS_GEN_SPACING"; - case 0x8E78: - return "GL_TESS_GEN_VERTEX_ORDER"; - case 0x8E79: - return "GL_TESS_GEN_POINT_MODE"; - case 0x8E7A: - return "GL_ISOLINES"; - case 0x8E7B: - return "GL_FRACTIONAL_ODD"; - case 0x8E7C: - return "GL_FRACTIONAL_EVEN"; - case 0x8E7D: - return "GL_MAX_PATCH_VERTICES"; - case 0x8E7E: - return "GL_MAX_TESS_GEN_LEVEL"; - case 0x8E7F: - return "GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"; - case 0x8E80: - return "GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"; - case 0x8E81: - return "GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"; - case 0x8E82: - return "GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"; - case 0x8E83: - return "GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"; - case 0x8E84: - return "GL_MAX_TESS_PATCH_COMPONENTS"; - case 0x8E85: - return "GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"; - case 0x8E86: - return "GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"; - case 0x8E87: - return "GL_TESS_EVALUATION_SHADER"; - case 0x8E88: - return "GL_TESS_CONTROL_SHADER"; - case 0x8E89: - return "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"; - case 0x8E8A: - return "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"; - case 0x8E8C: - return "GL_COMPRESSED_RGBA_BPTC_UNORM"; - case 0x8E8D: - return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"; - case 0x8E8E: - return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT"; - case 0x8E8F: - return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT"; - case 0x8F36: - return "GL_COPY_READ_BUFFER"; - case 0x8F37: - return "GL_COPY_WRITE_BUFFER"; - case 0x8F38: - return "GL_MAX_IMAGE_UNITS"; - case 0x8F39: - return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES"; - case 0x8F3A: - return "GL_IMAGE_BINDING_NAME"; - case 0x8F3B: - return "GL_IMAGE_BINDING_LEVEL"; - case 0x8F3C: - return "GL_IMAGE_BINDING_LAYERED"; - case 0x8F3D: - return "GL_IMAGE_BINDING_LAYER"; - case 0x8F3E: - return "GL_IMAGE_BINDING_ACCESS"; - case 0x8F3F: - return "GL_DRAW_INDIRECT_BUFFER"; - case 0x8F43: - return "GL_DRAW_INDIRECT_BUFFER_BINDING"; - case 0x8F46: - return "GL_DOUBLE_MAT2"; - case 0x8F47: - return "GL_DOUBLE_MAT3"; - case 0x8F48: - return "GL_DOUBLE_MAT4"; - case 0x8F49: - return "GL_DOUBLE_MAT2x3"; - case 0x8F4A: - return "GL_DOUBLE_MAT2x4"; - case 0x8F4B: - return "GL_DOUBLE_MAT3x2"; - case 0x8F4C: - return "GL_DOUBLE_MAT3x4"; - case 0x8F4D: - return "GL_DOUBLE_MAT4x2"; - case 0x8F4E: - return "GL_DOUBLE_MAT4x3"; - case 0x8F4F: - return "GL_VERTEX_BINDING_BUFFER"; - case 0x8F94: - return "GL_R8_SNORM"; - case 0x8F95: - return "GL_RG8_SNORM"; - case 0x8F96: - return "GL_RGB8_SNORM"; - case 0x8F97: - return "GL_RGBA8_SNORM"; - case 0x8F98: - return "GL_R16_SNORM"; - case 0x8F99: - return "GL_RG16_SNORM"; - case 0x8F9A: - return "GL_RGB16_SNORM"; - case 0x8F9B: - return "GL_RGBA16_SNORM"; - case 0x8F9C: - return "GL_SIGNED_NORMALIZED"; - case 0x8F9D: - return "GL_PRIMITIVE_RESTART"; - case 0x8F9E: - return "GL_PRIMITIVE_RESTART_INDEX"; - case 0x8FBD: - return "GL_SR8_EXT"; - case 0x8FBE: - return "GL_SRG8_EXT"; - case 0x8FFC: - return "GL_DOUBLE_VEC2"; - case 0x8FFD: - return "GL_DOUBLE_VEC3"; - case 0x8FFE: - return "GL_DOUBLE_VEC4"; - case 0x9009: - return "GL_TEXTURE_CUBE_MAP_ARRAY"; - case 0x900A: - return "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"; - case 0x900B: - return "GL_PROXY_TEXTURE_CUBE_MAP_ARRAY"; - case 0x900C: - return "GL_SAMPLER_CUBE_MAP_ARRAY"; - case 0x900D: - return "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"; - case 0x900E: - return "GL_INT_SAMPLER_CUBE_MAP_ARRAY"; - case 0x900F: - return "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"; - case 0x904C: - return "GL_IMAGE_1D"; - case 0x904D: - return "GL_IMAGE_2D"; - case 0x904E: - return "GL_IMAGE_3D"; - case 0x904F: - return "GL_IMAGE_2D_RECT"; - case 0x9050: - return "GL_IMAGE_CUBE"; - case 0x9051: - return "GL_IMAGE_BUFFER"; - case 0x9052: - return "GL_IMAGE_1D_ARRAY"; - case 0x9053: - return "GL_IMAGE_2D_ARRAY"; - case 0x9054: - return "GL_IMAGE_CUBE_MAP_ARRAY"; - case 0x9055: - return "GL_IMAGE_2D_MULTISAMPLE"; - case 0x9056: - return "GL_IMAGE_2D_MULTISAMPLE_ARRAY"; - case 0x9057: - return "GL_INT_IMAGE_1D"; - case 0x9058: - return "GL_INT_IMAGE_2D"; - case 0x9059: - return "GL_INT_IMAGE_3D"; - case 0x905A: - return "GL_INT_IMAGE_2D_RECT"; - case 0x905B: - return "GL_INT_IMAGE_CUBE"; - case 0x905C: - return "GL_INT_IMAGE_BUFFER"; - case 0x905D: - return "GL_INT_IMAGE_1D_ARRAY"; - case 0x905E: - return "GL_INT_IMAGE_2D_ARRAY"; - case 0x905F: - return "GL_INT_IMAGE_CUBE_MAP_ARRAY"; - case 0x9060: - return "GL_INT_IMAGE_2D_MULTISAMPLE"; - case 0x9061: - return "GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY"; - case 0x9062: - return "GL_UNSIGNED_INT_IMAGE_1D"; - case 0x9063: - return "GL_UNSIGNED_INT_IMAGE_2D"; - case 0x9064: - return "GL_UNSIGNED_INT_IMAGE_3D"; - case 0x9065: - return "GL_UNSIGNED_INT_IMAGE_2D_RECT"; - case 0x9066: - return "GL_UNSIGNED_INT_IMAGE_CUBE"; - case 0x9067: - return "GL_UNSIGNED_INT_IMAGE_BUFFER"; - case 0x9068: - return "GL_UNSIGNED_INT_IMAGE_1D_ARRAY"; - case 0x9069: - return "GL_UNSIGNED_INT_IMAGE_2D_ARRAY"; - case 0x906A: - return "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"; - case 0x906B: - return "GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE"; - case 0x906C: - return "GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY"; - case 0x906D: - return "GL_MAX_IMAGE_SAMPLES"; - case 0x906E: - return "GL_IMAGE_BINDING_FORMAT"; - case 0x906F: - return "GL_RGB10_A2UI"; - case 0x90BC: - return "GL_MIN_MAP_BUFFER_ALIGNMENT"; - case 0x90C7: - return "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"; - case 0x90C8: - return "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"; - case 0x90C9: - return "GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"; - case 0x90CA: - return "GL_MAX_VERTEX_IMAGE_UNIFORMS"; - case 0x90CB: - return "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"; - case 0x90CC: - return "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"; - case 0x90CD: - return "GL_MAX_GEOMETRY_IMAGE_UNIFORMS"; - case 0x90CE: - return "GL_MAX_FRAGMENT_IMAGE_UNIFORMS"; - case 0x90CF: - return "GL_MAX_COMBINED_IMAGE_UNIFORMS"; - case 0x90D2: - return "GL_SHADER_STORAGE_BUFFER"; - case 0x90D3: - return "GL_SHADER_STORAGE_BUFFER_BINDING"; - case 0x90D4: - return "GL_SHADER_STORAGE_BUFFER_START"; - case 0x90D5: - return "GL_SHADER_STORAGE_BUFFER_SIZE"; - case 0x90D6: - return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"; - case 0x90D7: - return "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"; - case 0x90D8: - return "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"; - case 0x90D9: - return "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"; - case 0x90DA: - return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"; - case 0x90DB: - return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"; - case 0x90DC: - return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"; - case 0x90DD: - return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"; - case 0x90DE: - return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE"; - case 0x90DF: - return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"; - case 0x90EA: - return "GL_DEPTH_STENCIL_TEXTURE_MODE"; - case 0x90EB: - return "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"; - case 0x90EC: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER"; - case 0x90ED: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"; - case 0x90EE: - return "GL_DISPATCH_INDIRECT_BUFFER"; - case 0x90EF: - return "GL_DISPATCH_INDIRECT_BUFFER_BINDING"; - case 0x9100: - return "GL_TEXTURE_2D_MULTISAMPLE"; - case 0x9101: - return "GL_PROXY_TEXTURE_2D_MULTISAMPLE"; - case 0x9102: - return "GL_TEXTURE_2D_MULTISAMPLE_ARRAY"; - case 0x9103: - return "GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY"; - case 0x9104: - return "GL_TEXTURE_BINDING_2D_MULTISAMPLE"; - case 0x9105: - return "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"; - case 0x9106: - return "GL_TEXTURE_SAMPLES"; - case 0x9107: - return "GL_TEXTURE_FIXED_SAMPLE_LOCATIONS"; - case 0x9108: - return "GL_SAMPLER_2D_MULTISAMPLE"; - case 0x9109: - return "GL_INT_SAMPLER_2D_MULTISAMPLE"; - case 0x910A: - return "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"; - case 0x910B: - return "GL_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910C: - return "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910D: - return "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910E: - return "GL_MAX_COLOR_TEXTURE_SAMPLES"; - case 0x910F: - return "GL_MAX_DEPTH_TEXTURE_SAMPLES"; - case 0x9110: - return "GL_MAX_INTEGER_SAMPLES"; - case 0x9111: - return "GL_MAX_SERVER_WAIT_TIMEOUT"; - case 0x9112: - return "GL_OBJECT_TYPE"; - case 0x9113: - return "GL_SYNC_CONDITION"; - case 0x9114: - return "GL_SYNC_STATUS"; - case 0x9115: - return "GL_SYNC_FLAGS"; - case 0x9116: - return "GL_SYNC_FENCE"; - case 0x9117: - return "GL_SYNC_GPU_COMMANDS_COMPLETE"; - case 0x9118: - return "GL_UNSIGNALED"; - case 0x9119: - return "GL_SIGNALED"; - case 0x911A: - return "GL_ALREADY_SIGNALED"; - case 0x911B: - return "GL_TIMEOUT_EXPIRED"; - case 0x911C: - return "GL_CONDITION_SATISFIED"; - case 0x911D: - return "GL_WAIT_FAILED"; - case 0x911F: - return "GL_BUFFER_ACCESS_FLAGS"; - case 0x9120: - return "GL_BUFFER_MAP_LENGTH"; - case 0x9121: - return "GL_BUFFER_MAP_OFFSET"; - case 0x9122: - return "GL_MAX_VERTEX_OUTPUT_COMPONENTS"; - case 0x9123: - return "GL_MAX_GEOMETRY_INPUT_COMPONENTS"; - case 0x9124: - return "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"; - case 0x9125: - return "GL_MAX_FRAGMENT_INPUT_COMPONENTS"; - case 0x9126: - return "GL_CONTEXT_PROFILE_MASK"; - case 0x9127: - return "GL_UNPACK_COMPRESSED_BLOCK_WIDTH"; - case 0x9128: - return "GL_UNPACK_COMPRESSED_BLOCK_HEIGHT"; - case 0x9129: - return "GL_UNPACK_COMPRESSED_BLOCK_DEPTH"; - case 0x912A: - return "GL_UNPACK_COMPRESSED_BLOCK_SIZE"; - case 0x912B: - return "GL_PACK_COMPRESSED_BLOCK_WIDTH"; - case 0x912C: - return "GL_PACK_COMPRESSED_BLOCK_HEIGHT"; - case 0x912D: - return "GL_PACK_COMPRESSED_BLOCK_DEPTH"; - case 0x912E: - return "GL_PACK_COMPRESSED_BLOCK_SIZE"; - case 0x912F: - return "GL_TEXTURE_IMMUTABLE_FORMAT"; - case 0x9143: - return "GL_MAX_DEBUG_MESSAGE_LENGTH"; - case 0x9144: - return "GL_MAX_DEBUG_LOGGED_MESSAGES"; - case 0x9145: - return "GL_DEBUG_LOGGED_MESSAGES"; - case 0x9146: - return "GL_DEBUG_SEVERITY_HIGH"; - case 0x9147: - return "GL_DEBUG_SEVERITY_MEDIUM"; - case 0x9148: - return "GL_DEBUG_SEVERITY_LOW"; - case 0x9151: - return "GL_BUFFER_OBJECT_EXT"; - case 0x9153: - return "GL_QUERY_OBJECT_EXT"; - case 0x9154: - return "GL_VERTEX_ARRAY_OBJECT_EXT"; - case 0x9192: - return "GL_QUERY_BUFFER"; - case 0x9193: - return "GL_QUERY_BUFFER_BINDING"; - case 0x9194: - return "GL_QUERY_RESULT_NO_WAIT"; - case 0x919D: - return "GL_TEXTURE_BUFFER_OFFSET"; - case 0x919E: - return "GL_TEXTURE_BUFFER_SIZE"; - case 0x919F: - return "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"; - case 0x91B0: - return "GL_MAX_SHADER_COMPILER_THREADS_KHR"; - case 0x91B1: - return "GL_COMPLETION_STATUS_KHR"; - case 0x91B9: - return "GL_COMPUTE_SHADER"; - case 0x91BB: - return "GL_MAX_COMPUTE_UNIFORM_BLOCKS"; - case 0x91BC: - return "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"; - case 0x91BD: - return "GL_MAX_COMPUTE_IMAGE_UNIFORMS"; - case 0x91BE: - return "GL_MAX_COMPUTE_WORK_GROUP_COUNT"; - case 0x91BF: - return "GL_MAX_COMPUTE_WORK_GROUP_SIZE"; - case 0x9270: - return "GL_COMPRESSED_R11_EAC"; - case 0x9271: - return "GL_COMPRESSED_SIGNED_R11_EAC"; - case 0x9272: - return "GL_COMPRESSED_RG11_EAC"; - case 0x9273: - return "GL_COMPRESSED_SIGNED_RG11_EAC"; - case 0x9274: - return "GL_COMPRESSED_RGB8_ETC2"; - case 0x9275: - return "GL_COMPRESSED_SRGB8_ETC2"; - case 0x9276: - return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"; - case 0x9277: - return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"; - case 0x9278: - return "GL_COMPRESSED_RGBA8_ETC2_EAC"; - case 0x9279: - return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"; - case 0x9285: - return "GL_BLEND_ADVANCED_COHERENT_KHR"; - case 0x9294: - return "GL_MULTIPLY_KHR"; - case 0x9295: - return "GL_SCREEN_KHR"; - case 0x9296: - return "GL_OVERLAY_KHR"; - case 0x9297: - return "GL_DARKEN_KHR"; - case 0x9298: - return "GL_LIGHTEN_KHR"; - case 0x9299: - return "GL_COLORDODGE_KHR"; - case 0x929A: - return "GL_COLORBURN_KHR"; - case 0x929B: - return "GL_HARDLIGHT_KHR"; - case 0x929C: - return "GL_SOFTLIGHT_KHR"; - case 0x929E: - return "GL_DIFFERENCE_KHR"; - case 0x92A0: - return "GL_EXCLUSION_KHR"; - case 0x92AD: - return "GL_HSL_HUE_KHR"; - case 0x92AE: - return "GL_HSL_SATURATION_KHR"; - case 0x92AF: - return "GL_HSL_COLOR_KHR"; - case 0x92B0: - return "GL_HSL_LUMINOSITY_KHR"; - case 0x92BB: - return "GL_PURGED_CONTEXT_RESET_NV"; - case 0x92C0: - return "GL_ATOMIC_COUNTER_BUFFER"; - case 0x92C1: - return "GL_ATOMIC_COUNTER_BUFFER_BINDING"; - case 0x92C2: - return "GL_ATOMIC_COUNTER_BUFFER_START"; - case 0x92C3: - return "GL_ATOMIC_COUNTER_BUFFER_SIZE"; - case 0x92C4: - return "GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE"; - case 0x92C5: - return "GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS"; - case 0x92C6: - return "GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES"; - case 0x92C7: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER"; - case 0x92C8: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER"; - case 0x92C9: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER"; - case 0x92CA: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER"; - case 0x92CB: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER"; - case 0x92CC: - return "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS"; - case 0x92CD: - return "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"; - case 0x92CE: - return "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"; - case 0x92CF: - return "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"; - case 0x92D0: - return "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"; - case 0x92D1: - return "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"; - case 0x92D2: - return "GL_MAX_VERTEX_ATOMIC_COUNTERS"; - case 0x92D3: - return "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"; - case 0x92D4: - return "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"; - case 0x92D5: - return "GL_MAX_GEOMETRY_ATOMIC_COUNTERS"; - case 0x92D6: - return "GL_MAX_FRAGMENT_ATOMIC_COUNTERS"; - case 0x92D7: - return "GL_MAX_COMBINED_ATOMIC_COUNTERS"; - case 0x92D8: - return "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"; - case 0x92D9: - return "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"; - case 0x92DA: - return "GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"; - case 0x92DB: - return "GL_UNSIGNED_INT_ATOMIC_COUNTER"; - case 0x92DC: - return "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"; - case 0x92E0: - return "GL_DEBUG_OUTPUT"; - case 0x92E1: - return "GL_UNIFORM"; - case 0x92E2: - return "GL_UNIFORM_BLOCK"; - case 0x92E3: - return "GL_PROGRAM_INPUT"; - case 0x92E4: - return "GL_PROGRAM_OUTPUT"; - case 0x92E5: - return "GL_BUFFER_VARIABLE"; - case 0x92E6: - return "GL_SHADER_STORAGE_BLOCK"; - case 0x92E7: - return "GL_IS_PER_PATCH"; - case 0x92E8: - return "GL_VERTEX_SUBROUTINE"; - case 0x92E9: - return "GL_TESS_CONTROL_SUBROUTINE"; - case 0x92EA: - return "GL_TESS_EVALUATION_SUBROUTINE"; - case 0x92EB: - return "GL_GEOMETRY_SUBROUTINE"; - case 0x92EC: - return "GL_FRAGMENT_SUBROUTINE"; - case 0x92ED: - return "GL_COMPUTE_SUBROUTINE"; - case 0x92EE: - return "GL_VERTEX_SUBROUTINE_UNIFORM"; - case 0x92EF: - return "GL_TESS_CONTROL_SUBROUTINE_UNIFORM"; - case 0x92F0: - return "GL_TESS_EVALUATION_SUBROUTINE_UNIFORM"; - case 0x92F1: - return "GL_GEOMETRY_SUBROUTINE_UNIFORM"; - case 0x92F2: - return "GL_FRAGMENT_SUBROUTINE_UNIFORM"; - case 0x92F3: - return "GL_COMPUTE_SUBROUTINE_UNIFORM"; - case 0x92F4: - return "GL_TRANSFORM_FEEDBACK_VARYING"; - case 0x92F5: - return "GL_ACTIVE_RESOURCES"; - case 0x92F6: - return "GL_MAX_NAME_LENGTH"; - case 0x92F7: - return "GL_MAX_NUM_ACTIVE_VARIABLES"; - case 0x92F8: - return "GL_MAX_NUM_COMPATIBLE_SUBROUTINES"; - case 0x92F9: - return "GL_NAME_LENGTH"; - case 0x92FA: - return "GL_TYPE"; - case 0x92FB: - return "GL_ARRAY_SIZE"; - case 0x92FC: - return "GL_OFFSET"; - case 0x92FD: - return "GL_BLOCK_INDEX"; - case 0x92FE: - return "GL_ARRAY_STRIDE"; - case 0x92FF: - return "GL_MATRIX_STRIDE"; - case 0x9300: - return "GL_IS_ROW_MAJOR"; - case 0x9301: - return "GL_ATOMIC_COUNTER_BUFFER_INDEX"; - case 0x9302: - return "GL_BUFFER_BINDING"; - case 0x9303: - return "GL_BUFFER_DATA_SIZE"; - case 0x9304: - return "GL_NUM_ACTIVE_VARIABLES"; - case 0x9305: - return "GL_ACTIVE_VARIABLES"; - case 0x9306: - return "GL_REFERENCED_BY_VERTEX_SHADER"; - case 0x9307: - return "GL_REFERENCED_BY_TESS_CONTROL_SHADER"; - case 0x9308: - return "GL_REFERENCED_BY_TESS_EVALUATION_SHADER"; - case 0x9309: - return "GL_REFERENCED_BY_GEOMETRY_SHADER"; - case 0x930A: - return "GL_REFERENCED_BY_FRAGMENT_SHADER"; - case 0x930B: - return "GL_REFERENCED_BY_COMPUTE_SHADER"; - case 0x930C: - return "GL_TOP_LEVEL_ARRAY_SIZE"; - case 0x930D: - return "GL_TOP_LEVEL_ARRAY_STRIDE"; - case 0x930E: - return "GL_LOCATION"; - case 0x930F: - return "GL_LOCATION_INDEX"; - case 0x9310: - return "GL_FRAMEBUFFER_DEFAULT_WIDTH"; - case 0x9311: - return "GL_FRAMEBUFFER_DEFAULT_HEIGHT"; - case 0x9312: - return "GL_FRAMEBUFFER_DEFAULT_LAYERS"; - case 0x9313: - return "GL_FRAMEBUFFER_DEFAULT_SAMPLES"; - case 0x9314: - return "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"; - case 0x9315: - return "GL_MAX_FRAMEBUFFER_WIDTH"; - case 0x9316: - return "GL_MAX_FRAMEBUFFER_HEIGHT"; - case 0x9317: - return "GL_MAX_FRAMEBUFFER_LAYERS"; - case 0x9318: - return "GL_MAX_FRAMEBUFFER_SAMPLES"; - case 0x934A: - return "GL_LOCATION_COMPONENT"; - case 0x934B: - return "GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"; - case 0x934C: - return "GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"; - case 0x935C: - return "GL_CLIP_ORIGIN"; - case 0x935D: - return "GL_CLIP_DEPTH_MODE"; - case 0x935E: - return "GL_NEGATIVE_ONE_TO_ONE"; - case 0x935F: - return "GL_ZERO_TO_ONE"; - case 0x9365: - return "GL_CLEAR_TEXTURE"; - case 0x9366: - return "GL_TEXTURE_REDUCTION_MODE_EXT"; - case 0x9367: - return "GL_WEIGHTED_AVERAGE_EXT"; - case 0x9380: - return "GL_NUM_SAMPLE_COUNTS"; - case 0x93A1: - return "GL_BGRA8_EXT"; - case 0x93AE: - return "GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE"; - case 0x93AF: - return "GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE"; - case 0x93B0: - return "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"; - case 0x93B1: - return "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"; - case 0x93B2: - return "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"; - case 0x93B3: - return "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"; - case 0x93B4: - return "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"; - case 0x93B5: - return "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"; - case 0x93B6: - return "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"; - case 0x93B7: - return "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"; - case 0x93B8: - return "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"; - case 0x93B9: - return "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"; - case 0x93BA: - return "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"; - case 0x93BB: - return "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"; - case 0x93BC: - return "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"; - case 0x93BD: - return "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"; - case 0x93D0: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"; - case 0x93D1: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"; - case 0x93D2: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"; - case 0x93D3: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"; - case 0x93D4: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"; - case 0x93D5: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"; - case 0x93D6: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"; - case 0x93D7: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"; - case 0x93D8: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"; - case 0x93D9: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"; - case 0x93DA: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"; - case 0x93DB: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"; - case 0x93DC: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"; - case 0x93DD: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"; - case 0x9530: - return "GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT"; - case 0x9531: - return "GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT"; - case 0x9551: - return "GL_SHADER_BINARY_FORMAT_SPIR_V"; - case 0x9552: - return "GL_SPIR_V_BINARY"; - case 0x9553: - return "GL_SPIR_V_EXTENSIONS"; - case 0x9554: - return "GL_NUM_SPIR_V_EXTENSIONS"; - case 0x9580: - return "GL_TEXTURE_TILING_EXT"; - case 0x9581: - return "GL_DEDICATED_MEMORY_OBJECT_EXT"; - case 0x9582: - return "GL_NUM_TILING_TYPES_EXT"; - case 0x9583: - return "GL_TILING_TYPES_EXT"; - case 0x9584: - return "GL_OPTIMAL_TILING_EXT"; - case 0x9585: - return "GL_LINEAR_TILING_EXT"; - case 0x9586: - return "GL_HANDLE_TYPE_OPAQUE_FD_EXT"; - case 0x958D: - return "GL_LAYOUT_GENERAL_EXT"; - case 0x958E: - return "GL_LAYOUT_COLOR_ATTACHMENT_EXT"; - case 0x958F: - return "GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT"; - case 0x9590: - return "GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT"; - case 0x9591: - return "GL_LAYOUT_SHADER_READ_ONLY_EXT"; - case 0x9592: - return "GL_LAYOUT_TRANSFER_SRC_EXT"; - case 0x9593: - return "GL_LAYOUT_TRANSFER_DST_EXT"; - case 0x9596: - return "GL_NUM_DEVICE_UUIDS_EXT"; - case 0x9597: - return "GL_DEVICE_UUID_EXT"; - case 0x9598: - return "GL_DRIVER_UUID_EXT"; - case 0x959B: - return "GL_PROTECTED_MEMORY_OBJECT_EXT"; - case 0x9630: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"; - case 0x9631: - return "GL_MAX_VIEWS_OVR"; - case 0x9632: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"; - case 0x9633: - return "GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR"; - case 0x10000: - return "GL_EVAL_BIT"; - case 0x20000: - return "GL_LIST_BIT"; - case 0x40000: - return "GL_TEXTURE_BIT"; - case 0x80000: - return "GL_SCISSOR_BIT"; - case 0x20000000: - return "GL_MULTISAMPLE_BIT"; - case 0xFFFFFFFF: - return "GL_INVALID_INDEX"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::AlphaFunction: - { - switch (value) - { - case 0x200: - return "GL_NEVER"; - case 0x201: - return "GL_LESS"; - case 0x202: - return "GL_EQUAL"; - case 0x203: - return "GL_LEQUAL"; - case 0x204: - return "GL_GREATER"; - case 0x205: - return "GL_NOTEQUAL"; - case 0x206: - return "GL_GEQUAL"; - case 0x207: - return "GL_ALWAYS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::AtomicCounterBufferPName: - { - switch (value) - { - case 0x90ED: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"; - case 0x92C1: - return "GL_ATOMIC_COUNTER_BUFFER_BINDING"; - case 0x92C4: - return "GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE"; - case 0x92C5: - return "GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS"; - case 0x92C6: - return "GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES"; - case 0x92C7: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER"; - case 0x92C8: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER"; - case 0x92C9: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER"; - case 0x92CA: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER"; - case 0x92CB: - return "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::AttribMask: - { - switch (value) - { - case 0x1: - return "GL_CURRENT_BIT"; - case 0x2: - return "GL_POINT_BIT"; - case 0x4: - return "GL_LINE_BIT"; - case 0x8: - return "GL_POLYGON_BIT"; - case 0x10: - return "GL_POLYGON_STIPPLE_BIT"; - case 0x20: - return "GL_PIXEL_MODE_BIT"; - case 0x40: - return "GL_LIGHTING_BIT"; - case 0x80: - return "GL_FOG_BIT"; - case 0x100: - return "GL_DEPTH_BUFFER_BIT"; - case 0x200: - return "GL_ACCUM_BUFFER_BIT"; - case 0x400: - return "GL_STENCIL_BUFFER_BIT"; - case 0x800: - return "GL_VIEWPORT_BIT"; - case 0x1000: - return "GL_TRANSFORM_BIT"; - case 0x2000: - return "GL_ENABLE_BIT"; - case 0x4000: - return "GL_COLOR_BUFFER_BIT"; - case 0x8000: - return "GL_HINT_BIT"; - case 0x10000: - return "GL_EVAL_BIT"; - case 0x20000: - return "GL_LIST_BIT"; - case 0x40000: - return "GL_TEXTURE_BIT"; - case 0x80000: - return "GL_SCISSOR_BIT"; - case 0x20000000: - return "GL_MULTISAMPLE_BIT"; - case 0xFFFFFFFF: - return "GL_ALL_ATTRIB_BITS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::AttributeType: - { - switch (value) - { - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - case 0x8B50: - return "GL_FLOAT_VEC2"; - case 0x8B51: - return "GL_FLOAT_VEC3"; - case 0x8B52: - return "GL_FLOAT_VEC4"; - case 0x8B53: - return "GL_INT_VEC2"; - case 0x8B54: - return "GL_INT_VEC3"; - case 0x8B55: - return "GL_INT_VEC4"; - case 0x8B56: - return "GL_BOOL"; - case 0x8B57: - return "GL_BOOL_VEC2"; - case 0x8B58: - return "GL_BOOL_VEC3"; - case 0x8B59: - return "GL_BOOL_VEC4"; - case 0x8B5A: - return "GL_FLOAT_MAT2"; - case 0x8B5B: - return "GL_FLOAT_MAT3"; - case 0x8B5C: - return "GL_FLOAT_MAT4"; - case 0x8B5D: - return "GL_SAMPLER_1D"; - case 0x8B5E: - return "GL_SAMPLER_2D"; - case 0x8B5F: - return "GL_SAMPLER_3D"; - case 0x8B60: - return "GL_SAMPLER_CUBE"; - case 0x8B61: - return "GL_SAMPLER_1D_SHADOW"; - case 0x8B62: - return "GL_SAMPLER_2D_SHADOW"; - case 0x8B63: - return "GL_SAMPLER_2D_RECT"; - case 0x8B64: - return "GL_SAMPLER_2D_RECT_SHADOW"; - case 0x8B65: - return "GL_FLOAT_MAT2x3"; - case 0x8B66: - return "GL_FLOAT_MAT2x4"; - case 0x8B67: - return "GL_FLOAT_MAT3x2"; - case 0x8B68: - return "GL_FLOAT_MAT3x4"; - case 0x8B69: - return "GL_FLOAT_MAT4x2"; - case 0x8B6A: - return "GL_FLOAT_MAT4x3"; - case 0x8DC2: - return "GL_SAMPLER_BUFFER"; - case 0x8DC3: - return "GL_SAMPLER_1D_ARRAY_SHADOW"; - case 0x8DC4: - return "GL_SAMPLER_2D_ARRAY_SHADOW"; - case 0x8DC5: - return "GL_SAMPLER_CUBE_SHADOW"; - case 0x8DC6: - return "GL_UNSIGNED_INT_VEC2"; - case 0x8DC7: - return "GL_UNSIGNED_INT_VEC3"; - case 0x8DC8: - return "GL_UNSIGNED_INT_VEC4"; - case 0x8DC9: - return "GL_INT_SAMPLER_1D"; - case 0x8DCA: - return "GL_INT_SAMPLER_2D"; - case 0x8DCB: - return "GL_INT_SAMPLER_3D"; - case 0x8DCC: - return "GL_INT_SAMPLER_CUBE"; - case 0x8DCD: - return "GL_INT_SAMPLER_2D_RECT"; - case 0x8DCE: - return "GL_INT_SAMPLER_1D_ARRAY"; - case 0x8DCF: - return "GL_INT_SAMPLER_2D_ARRAY"; - case 0x8DD0: - return "GL_INT_SAMPLER_BUFFER"; - case 0x8DD1: - return "GL_UNSIGNED_INT_SAMPLER_1D"; - case 0x8DD2: - return "GL_UNSIGNED_INT_SAMPLER_2D"; - case 0x8DD3: - return "GL_UNSIGNED_INT_SAMPLER_3D"; - case 0x8DD4: - return "GL_UNSIGNED_INT_SAMPLER_CUBE"; - case 0x8DD5: - return "GL_UNSIGNED_INT_SAMPLER_2D_RECT"; - case 0x8DD6: - return "GL_UNSIGNED_INT_SAMPLER_1D_ARRAY"; - case 0x8DD7: - return "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY"; - case 0x8DD8: - return "GL_UNSIGNED_INT_SAMPLER_BUFFER"; - case 0x8F46: - return "GL_DOUBLE_MAT2"; - case 0x8F47: - return "GL_DOUBLE_MAT3"; - case 0x8F48: - return "GL_DOUBLE_MAT4"; - case 0x8F49: - return "GL_DOUBLE_MAT2x3"; - case 0x8F4A: - return "GL_DOUBLE_MAT2x4"; - case 0x8F4B: - return "GL_DOUBLE_MAT3x2"; - case 0x8F4C: - return "GL_DOUBLE_MAT3x4"; - case 0x8F4D: - return "GL_DOUBLE_MAT4x2"; - case 0x8F4E: - return "GL_DOUBLE_MAT4x3"; - case 0x8FFC: - return "GL_DOUBLE_VEC2"; - case 0x8FFD: - return "GL_DOUBLE_VEC3"; - case 0x8FFE: - return "GL_DOUBLE_VEC4"; - case 0x900C: - return "GL_SAMPLER_CUBE_MAP_ARRAY"; - case 0x900D: - return "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"; - case 0x900E: - return "GL_INT_SAMPLER_CUBE_MAP_ARRAY"; - case 0x900F: - return "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"; - case 0x904C: - return "GL_IMAGE_1D"; - case 0x904D: - return "GL_IMAGE_2D"; - case 0x904E: - return "GL_IMAGE_3D"; - case 0x904F: - return "GL_IMAGE_2D_RECT"; - case 0x9050: - return "GL_IMAGE_CUBE"; - case 0x9051: - return "GL_IMAGE_BUFFER"; - case 0x9052: - return "GL_IMAGE_1D_ARRAY"; - case 0x9053: - return "GL_IMAGE_2D_ARRAY"; - case 0x9054: - return "GL_IMAGE_CUBE_MAP_ARRAY"; - case 0x9055: - return "GL_IMAGE_2D_MULTISAMPLE"; - case 0x9056: - return "GL_IMAGE_2D_MULTISAMPLE_ARRAY"; - case 0x9057: - return "GL_INT_IMAGE_1D"; - case 0x9058: - return "GL_INT_IMAGE_2D"; - case 0x9059: - return "GL_INT_IMAGE_3D"; - case 0x905A: - return "GL_INT_IMAGE_2D_RECT"; - case 0x905B: - return "GL_INT_IMAGE_CUBE"; - case 0x905C: - return "GL_INT_IMAGE_BUFFER"; - case 0x905D: - return "GL_INT_IMAGE_1D_ARRAY"; - case 0x905E: - return "GL_INT_IMAGE_2D_ARRAY"; - case 0x905F: - return "GL_INT_IMAGE_CUBE_MAP_ARRAY"; - case 0x9060: - return "GL_INT_IMAGE_2D_MULTISAMPLE"; - case 0x9061: - return "GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY"; - case 0x9062: - return "GL_UNSIGNED_INT_IMAGE_1D"; - case 0x9063: - return "GL_UNSIGNED_INT_IMAGE_2D"; - case 0x9064: - return "GL_UNSIGNED_INT_IMAGE_3D"; - case 0x9065: - return "GL_UNSIGNED_INT_IMAGE_2D_RECT"; - case 0x9066: - return "GL_UNSIGNED_INT_IMAGE_CUBE"; - case 0x9067: - return "GL_UNSIGNED_INT_IMAGE_BUFFER"; - case 0x9068: - return "GL_UNSIGNED_INT_IMAGE_1D_ARRAY"; - case 0x9069: - return "GL_UNSIGNED_INT_IMAGE_2D_ARRAY"; - case 0x906A: - return "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"; - case 0x906B: - return "GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE"; - case 0x906C: - return "GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY"; - case 0x9108: - return "GL_SAMPLER_2D_MULTISAMPLE"; - case 0x9109: - return "GL_INT_SAMPLER_2D_MULTISAMPLE"; - case 0x910A: - return "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"; - case 0x910B: - return "GL_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910C: - return "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910D: - return "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BindTransformFeedbackTarget: - { - switch (value) - { - case 0x8E22: - return "GL_TRANSFORM_FEEDBACK"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BinormalPointerTypeEXT: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BlendEquationModeEXT: - { - switch (value) - { - case 0x8006: - return "GL_FUNC_ADD"; - case 0x8007: - return "GL_MIN"; - case 0x8008: - return "GL_MAX"; - case 0x800A: - return "GL_FUNC_SUBTRACT"; - case 0x800B: - return "GL_FUNC_REVERSE_SUBTRACT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BlendingFactor: - { - switch (value) - { - case 0x0: - return "GL_ZERO"; - case 0x1: - return "GL_ONE"; - case 0x300: - return "GL_SRC_COLOR"; - case 0x301: - return "GL_ONE_MINUS_SRC_COLOR"; - case 0x302: - return "GL_SRC_ALPHA"; - case 0x303: - return "GL_ONE_MINUS_SRC_ALPHA"; - case 0x304: - return "GL_DST_ALPHA"; - case 0x305: - return "GL_ONE_MINUS_DST_ALPHA"; - case 0x306: - return "GL_DST_COLOR"; - case 0x307: - return "GL_ONE_MINUS_DST_COLOR"; - case 0x308: - return "GL_SRC_ALPHA_SATURATE"; - case 0x8001: - return "GL_CONSTANT_COLOR"; - case 0x8002: - return "GL_ONE_MINUS_CONSTANT_COLOR"; - case 0x8003: - return "GL_CONSTANT_ALPHA"; - case 0x8004: - return "GL_ONE_MINUS_CONSTANT_ALPHA"; - case 0x8589: - return "GL_SRC1_ALPHA"; - case 0x88F9: - return "GL_SRC1_COLOR"; - case 0x88FA: - return "GL_ONE_MINUS_SRC1_COLOR"; - case 0x88FB: - return "GL_ONE_MINUS_SRC1_ALPHA"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BlitFramebufferFilter: - { - switch (value) - { - case 0x2600: - return "GL_NEAREST"; - case 0x2601: - return "GL_LINEAR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::Boolean: - { - switch (value) - { - case 0x0: - return "GL_FALSE"; - case 0x1: - return "GL_TRUE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::Buffer: - { - switch (value) - { - case 0x1800: - return "GL_COLOR"; - case 0x1801: - return "GL_DEPTH"; - case 0x1802: - return "GL_STENCIL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferAccessARB: - { - switch (value) - { - case 0x88B8: - return "GL_READ_ONLY"; - case 0x88B9: - return "GL_WRITE_ONLY"; - case 0x88BA: - return "GL_READ_WRITE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferPNameARB: - { - switch (value) - { - case 0x821F: - return "GL_BUFFER_IMMUTABLE_STORAGE"; - case 0x8220: - return "GL_BUFFER_STORAGE_FLAGS"; - case 0x8764: - return "GL_BUFFER_SIZE"; - case 0x8765: - return "GL_BUFFER_USAGE"; - case 0x88BB: - return "GL_BUFFER_ACCESS"; - case 0x88BC: - return "GL_BUFFER_MAPPED"; - case 0x911F: - return "GL_BUFFER_ACCESS_FLAGS"; - case 0x9120: - return "GL_BUFFER_MAP_LENGTH"; - case 0x9121: - return "GL_BUFFER_MAP_OFFSET"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferPointerNameARB: - { - switch (value) - { - case 0x88BD: - return "GL_BUFFER_MAP_POINTER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferStorageMask: - { - switch (value) - { - case 0x1: - return "GL_MAP_READ_BIT"; - case 0x2: - return "GL_MAP_WRITE_BIT"; - case 0x40: - return "GL_MAP_PERSISTENT_BIT"; - case 0x80: - return "GL_MAP_COHERENT_BIT"; - case 0x100: - return "GL_DYNAMIC_STORAGE_BIT"; - case 0x200: - return "GL_CLIENT_STORAGE_BIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferStorageTarget: - { - switch (value) - { - case 0x8892: - return "GL_ARRAY_BUFFER"; - case 0x8893: - return "GL_ELEMENT_ARRAY_BUFFER"; - case 0x88EB: - return "GL_PIXEL_PACK_BUFFER"; - case 0x88EC: - return "GL_PIXEL_UNPACK_BUFFER"; - case 0x8A11: - return "GL_UNIFORM_BUFFER"; - case 0x8C2A: - return "GL_TEXTURE_BUFFER"; - case 0x8C8E: - return "GL_TRANSFORM_FEEDBACK_BUFFER"; - case 0x8F36: - return "GL_COPY_READ_BUFFER"; - case 0x8F37: - return "GL_COPY_WRITE_BUFFER"; - case 0x8F3F: - return "GL_DRAW_INDIRECT_BUFFER"; - case 0x90D2: - return "GL_SHADER_STORAGE_BUFFER"; - case 0x90EE: - return "GL_DISPATCH_INDIRECT_BUFFER"; - case 0x9192: - return "GL_QUERY_BUFFER"; - case 0x92C0: - return "GL_ATOMIC_COUNTER_BUFFER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferTargetARB: - { - switch (value) - { - case 0x80EE: - return "GL_PARAMETER_BUFFER"; - case 0x8892: - return "GL_ARRAY_BUFFER"; - case 0x8893: - return "GL_ELEMENT_ARRAY_BUFFER"; - case 0x88EB: - return "GL_PIXEL_PACK_BUFFER"; - case 0x88EC: - return "GL_PIXEL_UNPACK_BUFFER"; - case 0x8A11: - return "GL_UNIFORM_BUFFER"; - case 0x8C2A: - return "GL_TEXTURE_BUFFER"; - case 0x8C8E: - return "GL_TRANSFORM_FEEDBACK_BUFFER"; - case 0x8F36: - return "GL_COPY_READ_BUFFER"; - case 0x8F37: - return "GL_COPY_WRITE_BUFFER"; - case 0x8F3F: - return "GL_DRAW_INDIRECT_BUFFER"; - case 0x90D2: - return "GL_SHADER_STORAGE_BUFFER"; - case 0x90EE: - return "GL_DISPATCH_INDIRECT_BUFFER"; - case 0x9192: - return "GL_QUERY_BUFFER"; - case 0x92C0: - return "GL_ATOMIC_COUNTER_BUFFER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::BufferUsageARB: - { - switch (value) - { - case 0x88E0: - return "GL_STREAM_DRAW"; - case 0x88E1: - return "GL_STREAM_READ"; - case 0x88E2: - return "GL_STREAM_COPY"; - case 0x88E4: - return "GL_STATIC_DRAW"; - case 0x88E5: - return "GL_STATIC_READ"; - case 0x88E6: - return "GL_STATIC_COPY"; - case 0x88E8: - return "GL_DYNAMIC_DRAW"; - case 0x88E9: - return "GL_DYNAMIC_READ"; - case 0x88EA: - return "GL_DYNAMIC_COPY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClampColorModeARB: - { - switch (value) - { - case 0x0: - return "GL_FALSE"; - case 0x1: - return "GL_TRUE"; - case 0x891D: - return "GL_FIXED_ONLY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClampColorTargetARB: - { - switch (value) - { - case 0x891C: - return "GL_CLAMP_READ_COLOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClearBufferMask: - { - switch (value) - { - case 0x100: - return "GL_DEPTH_BUFFER_BIT"; - case 0x200: - return "GL_ACCUM_BUFFER_BIT"; - case 0x400: - return "GL_STENCIL_BUFFER_BIT"; - case 0x4000: - return "GL_COLOR_BUFFER_BIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClientAttribMask: - { - switch (value) - { - case 0x1: - return "GL_CLIENT_PIXEL_STORE_BIT"; - case 0x2: - return "GL_CLIENT_VERTEX_ARRAY_BIT"; - case 0xFFFFFFFF: - return "GL_CLIENT_ALL_ATTRIB_BITS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClipControlDepth: - { - switch (value) - { - case 0x935E: - return "GL_NEGATIVE_ONE_TO_ONE"; - case 0x935F: - return "GL_ZERO_TO_ONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClipControlOrigin: - { - switch (value) - { - case 0x8CA1: - return "GL_LOWER_LEFT"; - case 0x8CA2: - return "GL_UPPER_LEFT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ClipPlaneName: - { - switch (value) - { - case 0x3000: - return "GL_CLIP_PLANE0"; - case 0x3001: - return "GL_CLIP_PLANE1"; - case 0x3002: - return "GL_CLIP_PLANE2"; - case 0x3003: - return "GL_CLIP_PLANE3"; - case 0x3004: - return "GL_CLIP_PLANE4"; - case 0x3005: - return "GL_CLIP_PLANE5"; - case 0x3006: - return "GL_CLIP_DISTANCE6"; - case 0x3007: - return "GL_CLIP_DISTANCE7"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ColorBuffer: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x400: - return "GL_FRONT_LEFT"; - case 0x401: - return "GL_FRONT_RIGHT"; - case 0x402: - return "GL_BACK_LEFT"; - case 0x403: - return "GL_BACK_RIGHT"; - case 0x404: - return "GL_FRONT"; - case 0x405: - return "GL_BACK"; - case 0x406: - return "GL_LEFT"; - case 0x407: - return "GL_RIGHT"; - case 0x408: - return "GL_FRONT_AND_BACK"; - case 0x8CE0: - return "GL_COLOR_ATTACHMENT0"; - case 0x8CE1: - return "GL_COLOR_ATTACHMENT1"; - case 0x8CE2: - return "GL_COLOR_ATTACHMENT2"; - case 0x8CE3: - return "GL_COLOR_ATTACHMENT3"; - case 0x8CE4: - return "GL_COLOR_ATTACHMENT4"; - case 0x8CE5: - return "GL_COLOR_ATTACHMENT5"; - case 0x8CE6: - return "GL_COLOR_ATTACHMENT6"; - case 0x8CE7: - return "GL_COLOR_ATTACHMENT7"; - case 0x8CE8: - return "GL_COLOR_ATTACHMENT8"; - case 0x8CE9: - return "GL_COLOR_ATTACHMENT9"; - case 0x8CEA: - return "GL_COLOR_ATTACHMENT10"; - case 0x8CEB: - return "GL_COLOR_ATTACHMENT11"; - case 0x8CEC: - return "GL_COLOR_ATTACHMENT12"; - case 0x8CED: - return "GL_COLOR_ATTACHMENT13"; - case 0x8CEE: - return "GL_COLOR_ATTACHMENT14"; - case 0x8CEF: - return "GL_COLOR_ATTACHMENT15"; - case 0x8CF0: - return "GL_COLOR_ATTACHMENT16"; - case 0x8CF1: - return "GL_COLOR_ATTACHMENT17"; - case 0x8CF2: - return "GL_COLOR_ATTACHMENT18"; - case 0x8CF3: - return "GL_COLOR_ATTACHMENT19"; - case 0x8CF4: - return "GL_COLOR_ATTACHMENT20"; - case 0x8CF5: - return "GL_COLOR_ATTACHMENT21"; - case 0x8CF6: - return "GL_COLOR_ATTACHMENT22"; - case 0x8CF7: - return "GL_COLOR_ATTACHMENT23"; - case 0x8CF8: - return "GL_COLOR_ATTACHMENT24"; - case 0x8CF9: - return "GL_COLOR_ATTACHMENT25"; - case 0x8CFA: - return "GL_COLOR_ATTACHMENT26"; - case 0x8CFB: - return "GL_COLOR_ATTACHMENT27"; - case 0x8CFC: - return "GL_COLOR_ATTACHMENT28"; - case 0x8CFD: - return "GL_COLOR_ATTACHMENT29"; - case 0x8CFE: - return "GL_COLOR_ATTACHMENT30"; - case 0x8CFF: - return "GL_COLOR_ATTACHMENT31"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ColorMaterialParameter: - { - switch (value) - { - case 0x1200: - return "GL_AMBIENT"; - case 0x1201: - return "GL_DIFFUSE"; - case 0x1202: - return "GL_SPECULAR"; - case 0x1600: - return "GL_EMISSION"; - case 0x1602: - return "GL_AMBIENT_AND_DIFFUSE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ColorPointerType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ColorTableTarget: - { - switch (value) - { - case 0x80D0: - return "GL_COLOR_TABLE"; - case 0x80D1: - return "GL_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D2: - return "GL_POST_COLOR_MATRIX_COLOR_TABLE"; - case 0x80D3: - return "GL_PROXY_COLOR_TABLE"; - case 0x80D4: - return "GL_PROXY_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D5: - return "GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ColorTableTargetSGI: - { - switch (value) - { - case 0x80D0: - return "GL_COLOR_TABLE"; - case 0x80D1: - return "GL_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D2: - return "GL_POST_COLOR_MATRIX_COLOR_TABLE"; - case 0x80D3: - return "GL_PROXY_COLOR_TABLE"; - case 0x80D4: - return "GL_PROXY_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D5: - return "GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::CombinerBiasNV: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::CombinerComponentUsageNV: - { - switch (value) - { - case 0x1905: - return "GL_BLUE"; - case 0x1906: - return "GL_ALPHA"; - case 0x1907: - return "GL_RGB"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::CombinerPortionNV: - { - switch (value) - { - case 0x1906: - return "GL_ALPHA"; - case 0x1907: - return "GL_RGB"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::CombinerScaleNV: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ConditionalRenderMode: - { - switch (value) - { - case 0x8E13: - return "GL_QUERY_WAIT"; - case 0x8E14: - return "GL_QUERY_NO_WAIT"; - case 0x8E15: - return "GL_QUERY_BY_REGION_WAIT"; - case 0x8E16: - return "GL_QUERY_BY_REGION_NO_WAIT"; - case 0x8E17: - return "GL_QUERY_WAIT_INVERTED"; - case 0x8E18: - return "GL_QUERY_NO_WAIT_INVERTED"; - case 0x8E19: - return "GL_QUERY_BY_REGION_WAIT_INVERTED"; - case 0x8E1A: - return "GL_QUERY_BY_REGION_NO_WAIT_INVERTED"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ContainerType: - { - switch (value) - { - case 0x8B40: - return "GL_PROGRAM_OBJECT_EXT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ContextFlagMask: - { - switch (value) - { - case 0x1: - return "GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT"; - case 0x2: - return "GL_CONTEXT_FLAG_DEBUG_BIT"; - case 0x4: - return "GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"; - case 0x8: - return "GL_CONTEXT_FLAG_NO_ERROR_BIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ContextProfileMask: - { - switch (value) - { - case 0x1: - return "GL_CONTEXT_CORE_PROFILE_BIT"; - case 0x2: - return "GL_CONTEXT_COMPATIBILITY_PROFILE_BIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ConvolutionTarget: - { - switch (value) - { - case 0x8010: - return "GL_CONVOLUTION_1D"; - case 0x8011: - return "GL_CONVOLUTION_2D"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ConvolutionTargetEXT: - { - switch (value) - { - case 0x8010: - return "GL_CONVOLUTION_1D"; - case 0x8011: - return "GL_CONVOLUTION_2D"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::CopyBufferSubDataTarget: - { - switch (value) - { - case 0x8892: - return "GL_ARRAY_BUFFER"; - case 0x8893: - return "GL_ELEMENT_ARRAY_BUFFER"; - case 0x88EB: - return "GL_PIXEL_PACK_BUFFER"; - case 0x88EC: - return "GL_PIXEL_UNPACK_BUFFER"; - case 0x8A11: - return "GL_UNIFORM_BUFFER"; - case 0x8C2A: - return "GL_TEXTURE_BUFFER"; - case 0x8C8E: - return "GL_TRANSFORM_FEEDBACK_BUFFER"; - case 0x8F36: - return "GL_COPY_READ_BUFFER"; - case 0x8F37: - return "GL_COPY_WRITE_BUFFER"; - case 0x8F3F: - return "GL_DRAW_INDIRECT_BUFFER"; - case 0x90D2: - return "GL_SHADER_STORAGE_BUFFER"; - case 0x90EE: - return "GL_DISPATCH_INDIRECT_BUFFER"; - case 0x9192: - return "GL_QUERY_BUFFER"; - case 0x92C0: - return "GL_ATOMIC_COUNTER_BUFFER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::CopyImageSubDataTarget: - { - switch (value) - { - case 0xDE0: - return "GL_TEXTURE_1D"; - case 0xDE1: - return "GL_TEXTURE_2D"; - case 0x806F: - return "GL_TEXTURE_3D"; - case 0x84F5: - return "GL_TEXTURE_RECTANGLE"; - case 0x8513: - return "GL_TEXTURE_CUBE_MAP"; - case 0x8C18: - return "GL_TEXTURE_1D_ARRAY"; - case 0x8C1A: - return "GL_TEXTURE_2D_ARRAY"; - case 0x8D41: - return "GL_RENDERBUFFER"; - case 0x9009: - return "GL_TEXTURE_CUBE_MAP_ARRAY"; - case 0x9100: - return "GL_TEXTURE_2D_MULTISAMPLE"; - case 0x9102: - return "GL_TEXTURE_2D_MULTISAMPLE_ARRAY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DebugSeverity: - { - switch (value) - { - case 0x1100: - return "GL_DONT_CARE"; - case 0x826B: - return "GL_DEBUG_SEVERITY_NOTIFICATION"; - case 0x9146: - return "GL_DEBUG_SEVERITY_HIGH"; - case 0x9147: - return "GL_DEBUG_SEVERITY_MEDIUM"; - case 0x9148: - return "GL_DEBUG_SEVERITY_LOW"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DebugSource: - { - switch (value) - { - case 0x1100: - return "GL_DONT_CARE"; - case 0x8246: - return "GL_DEBUG_SOURCE_API"; - case 0x8247: - return "GL_DEBUG_SOURCE_WINDOW_SYSTEM"; - case 0x8248: - return "GL_DEBUG_SOURCE_SHADER_COMPILER"; - case 0x8249: - return "GL_DEBUG_SOURCE_THIRD_PARTY"; - case 0x824A: - return "GL_DEBUG_SOURCE_APPLICATION"; - case 0x824B: - return "GL_DEBUG_SOURCE_OTHER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DebugType: - { - switch (value) - { - case 0x1100: - return "GL_DONT_CARE"; - case 0x824C: - return "GL_DEBUG_TYPE_ERROR"; - case 0x824D: - return "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"; - case 0x824E: - return "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"; - case 0x824F: - return "GL_DEBUG_TYPE_PORTABILITY"; - case 0x8250: - return "GL_DEBUG_TYPE_PERFORMANCE"; - case 0x8251: - return "GL_DEBUG_TYPE_OTHER"; - case 0x8268: - return "GL_DEBUG_TYPE_MARKER"; - case 0x8269: - return "GL_DEBUG_TYPE_PUSH_GROUP"; - case 0x826A: - return "GL_DEBUG_TYPE_POP_GROUP"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DepthFunction: - { - switch (value) - { - case 0x200: - return "GL_NEVER"; - case 0x201: - return "GL_LESS"; - case 0x202: - return "GL_EQUAL"; - case 0x203: - return "GL_LEQUAL"; - case 0x204: - return "GL_GREATER"; - case 0x205: - return "GL_NOTEQUAL"; - case 0x206: - return "GL_GEQUAL"; - case 0x207: - return "GL_ALWAYS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DepthStencilTextureMode: - { - switch (value) - { - case 0x1901: - return "GL_STENCIL_INDEX"; - case 0x1902: - return "GL_DEPTH_COMPONENT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DrawBufferMode: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x400: - return "GL_FRONT_LEFT"; - case 0x401: - return "GL_FRONT_RIGHT"; - case 0x402: - return "GL_BACK_LEFT"; - case 0x403: - return "GL_BACK_RIGHT"; - case 0x404: - return "GL_FRONT"; - case 0x405: - return "GL_BACK"; - case 0x406: - return "GL_LEFT"; - case 0x407: - return "GL_RIGHT"; - case 0x408: - return "GL_FRONT_AND_BACK"; - case 0x409: - return "GL_AUX0"; - case 0x40A: - return "GL_AUX1"; - case 0x40B: - return "GL_AUX2"; - case 0x40C: - return "GL_AUX3"; - case 0x8CE0: - return "GL_COLOR_ATTACHMENT0"; - case 0x8CE1: - return "GL_COLOR_ATTACHMENT1"; - case 0x8CE2: - return "GL_COLOR_ATTACHMENT2"; - case 0x8CE3: - return "GL_COLOR_ATTACHMENT3"; - case 0x8CE4: - return "GL_COLOR_ATTACHMENT4"; - case 0x8CE5: - return "GL_COLOR_ATTACHMENT5"; - case 0x8CE6: - return "GL_COLOR_ATTACHMENT6"; - case 0x8CE7: - return "GL_COLOR_ATTACHMENT7"; - case 0x8CE8: - return "GL_COLOR_ATTACHMENT8"; - case 0x8CE9: - return "GL_COLOR_ATTACHMENT9"; - case 0x8CEA: - return "GL_COLOR_ATTACHMENT10"; - case 0x8CEB: - return "GL_COLOR_ATTACHMENT11"; - case 0x8CEC: - return "GL_COLOR_ATTACHMENT12"; - case 0x8CED: - return "GL_COLOR_ATTACHMENT13"; - case 0x8CEE: - return "GL_COLOR_ATTACHMENT14"; - case 0x8CEF: - return "GL_COLOR_ATTACHMENT15"; - case 0x8CF0: - return "GL_COLOR_ATTACHMENT16"; - case 0x8CF1: - return "GL_COLOR_ATTACHMENT17"; - case 0x8CF2: - return "GL_COLOR_ATTACHMENT18"; - case 0x8CF3: - return "GL_COLOR_ATTACHMENT19"; - case 0x8CF4: - return "GL_COLOR_ATTACHMENT20"; - case 0x8CF5: - return "GL_COLOR_ATTACHMENT21"; - case 0x8CF6: - return "GL_COLOR_ATTACHMENT22"; - case 0x8CF7: - return "GL_COLOR_ATTACHMENT23"; - case 0x8CF8: - return "GL_COLOR_ATTACHMENT24"; - case 0x8CF9: - return "GL_COLOR_ATTACHMENT25"; - case 0x8CFA: - return "GL_COLOR_ATTACHMENT26"; - case 0x8CFB: - return "GL_COLOR_ATTACHMENT27"; - case 0x8CFC: - return "GL_COLOR_ATTACHMENT28"; - case 0x8CFD: - return "GL_COLOR_ATTACHMENT29"; - case 0x8CFE: - return "GL_COLOR_ATTACHMENT30"; - case 0x8CFF: - return "GL_COLOR_ATTACHMENT31"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::DrawElementsType: - { - switch (value) - { - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ElementPointerTypeATI: - { - switch (value) - { - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::EnableCap: - { - switch (value) - { - case 0xB10: - return "GL_POINT_SMOOTH"; - case 0xB20: - return "GL_LINE_SMOOTH"; - case 0xB24: - return "GL_LINE_STIPPLE"; - case 0xB41: - return "GL_POLYGON_SMOOTH"; - case 0xB42: - return "GL_POLYGON_STIPPLE"; - case 0xB44: - return "GL_CULL_FACE"; - case 0xB50: - return "GL_LIGHTING"; - case 0xB57: - return "GL_COLOR_MATERIAL"; - case 0xB60: - return "GL_FOG"; - case 0xB71: - return "GL_DEPTH_TEST"; - case 0xB90: - return "GL_STENCIL_TEST"; - case 0xBA1: - return "GL_NORMALIZE"; - case 0xBC0: - return "GL_ALPHA_TEST"; - case 0xBD0: - return "GL_DITHER"; - case 0xBE2: - return "GL_BLEND"; - case 0xBF1: - return "GL_INDEX_LOGIC_OP"; - case 0xBF2: - return "GL_COLOR_LOGIC_OP"; - case 0xC11: - return "GL_SCISSOR_TEST"; - case 0xC60: - return "GL_TEXTURE_GEN_S"; - case 0xC61: - return "GL_TEXTURE_GEN_T"; - case 0xC62: - return "GL_TEXTURE_GEN_R"; - case 0xC63: - return "GL_TEXTURE_GEN_Q"; - case 0xD80: - return "GL_AUTO_NORMAL"; - case 0xD90: - return "GL_MAP1_COLOR_4"; - case 0xD91: - return "GL_MAP1_INDEX"; - case 0xD92: - return "GL_MAP1_NORMAL"; - case 0xD93: - return "GL_MAP1_TEXTURE_COORD_1"; - case 0xD94: - return "GL_MAP1_TEXTURE_COORD_2"; - case 0xD95: - return "GL_MAP1_TEXTURE_COORD_3"; - case 0xD96: - return "GL_MAP1_TEXTURE_COORD_4"; - case 0xD97: - return "GL_MAP1_VERTEX_3"; - case 0xD98: - return "GL_MAP1_VERTEX_4"; - case 0xDB0: - return "GL_MAP2_COLOR_4"; - case 0xDB1: - return "GL_MAP2_INDEX"; - case 0xDB2: - return "GL_MAP2_NORMAL"; - case 0xDB3: - return "GL_MAP2_TEXTURE_COORD_1"; - case 0xDB4: - return "GL_MAP2_TEXTURE_COORD_2"; - case 0xDB5: - return "GL_MAP2_TEXTURE_COORD_3"; - case 0xDB6: - return "GL_MAP2_TEXTURE_COORD_4"; - case 0xDB7: - return "GL_MAP2_VERTEX_3"; - case 0xDB8: - return "GL_MAP2_VERTEX_4"; - case 0xDE0: - return "GL_TEXTURE_1D"; - case 0xDE1: - return "GL_TEXTURE_2D"; - case 0x2A01: - return "GL_POLYGON_OFFSET_POINT"; - case 0x2A02: - return "GL_POLYGON_OFFSET_LINE"; - case 0x3000: - return "GL_CLIP_PLANE0"; - case 0x3001: - return "GL_CLIP_PLANE1"; - case 0x3002: - return "GL_CLIP_PLANE2"; - case 0x3003: - return "GL_CLIP_PLANE3"; - case 0x3004: - return "GL_CLIP_PLANE4"; - case 0x3005: - return "GL_CLIP_PLANE5"; - case 0x3006: - return "GL_CLIP_DISTANCE6"; - case 0x3007: - return "GL_CLIP_DISTANCE7"; - case 0x4000: - return "GL_LIGHT0"; - case 0x4001: - return "GL_LIGHT1"; - case 0x4002: - return "GL_LIGHT2"; - case 0x4003: - return "GL_LIGHT3"; - case 0x4004: - return "GL_LIGHT4"; - case 0x4005: - return "GL_LIGHT5"; - case 0x4006: - return "GL_LIGHT6"; - case 0x4007: - return "GL_LIGHT7"; - case 0x8037: - return "GL_POLYGON_OFFSET_FILL"; - case 0x8074: - return "GL_VERTEX_ARRAY"; - case 0x8075: - return "GL_NORMAL_ARRAY"; - case 0x8076: - return "GL_COLOR_ARRAY"; - case 0x8077: - return "GL_INDEX_ARRAY"; - case 0x8078: - return "GL_TEXTURE_COORD_ARRAY"; - case 0x8079: - return "GL_EDGE_FLAG_ARRAY"; - case 0x809D: - return "GL_MULTISAMPLE"; - case 0x809E: - return "GL_SAMPLE_ALPHA_TO_COVERAGE"; - case 0x809F: - return "GL_SAMPLE_ALPHA_TO_ONE"; - case 0x80A0: - return "GL_SAMPLE_COVERAGE"; - case 0x80D0: - return "GL_COLOR_TABLE"; - case 0x80D1: - return "GL_POST_CONVOLUTION_COLOR_TABLE"; - case 0x80D2: - return "GL_POST_COLOR_MATRIX_COLOR_TABLE"; - case 0x8242: - return "GL_DEBUG_OUTPUT_SYNCHRONOUS"; - case 0x84F5: - return "GL_TEXTURE_RECTANGLE"; - case 0x8513: - return "GL_TEXTURE_CUBE_MAP"; - case 0x8642: - return "GL_PROGRAM_POINT_SIZE"; - case 0x864F: - return "GL_DEPTH_CLAMP"; - case 0x884F: - return "GL_TEXTURE_CUBE_MAP_SEAMLESS"; - case 0x8C36: - return "GL_SAMPLE_SHADING"; - case 0x8C89: - return "GL_RASTERIZER_DISCARD"; - case 0x8D69: - return "GL_PRIMITIVE_RESTART_FIXED_INDEX"; - case 0x8DB9: - return "GL_FRAMEBUFFER_SRGB"; - case 0x8E51: - return "GL_SAMPLE_MASK"; - case 0x8F9D: - return "GL_PRIMITIVE_RESTART"; - case 0x92E0: - return "GL_DEBUG_OUTPUT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ErrorCode: - { - switch (value) - { - case 0x0: - return "GL_NO_ERROR"; - case 0x500: - return "GL_INVALID_ENUM"; - case 0x501: - return "GL_INVALID_VALUE"; - case 0x502: - return "GL_INVALID_OPERATION"; - case 0x503: - return "GL_STACK_OVERFLOW"; - case 0x504: - return "GL_STACK_UNDERFLOW"; - case 0x505: - return "GL_OUT_OF_MEMORY"; - case 0x506: - return "GL_INVALID_FRAMEBUFFER_OPERATION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ExternalHandleType: - { - switch (value) - { - case 0x9586: - return "GL_HANDLE_TYPE_OPAQUE_FD_EXT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FeedBackToken: - { - switch (value) - { - case 0x700: - return "GL_PASS_THROUGH_TOKEN"; - case 0x701: - return "GL_POINT_TOKEN"; - case 0x702: - return "GL_LINE_TOKEN"; - case 0x703: - return "GL_POLYGON_TOKEN"; - case 0x704: - return "GL_BITMAP_TOKEN"; - case 0x705: - return "GL_DRAW_PIXEL_TOKEN"; - case 0x706: - return "GL_COPY_PIXEL_TOKEN"; - case 0x707: - return "GL_LINE_RESET_TOKEN"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FeedbackType: - { - switch (value) - { - case 0x600: - return "GL_2D"; - case 0x601: - return "GL_3D"; - case 0x602: - return "GL_3D_COLOR"; - case 0x603: - return "GL_3D_COLOR_TEXTURE"; - case 0x604: - return "GL_4D_COLOR_TEXTURE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FenceConditionNV: - { - switch (value) - { - case 0x84F2: - return "GL_ALL_COMPLETED_NV"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FenceParameterNameNV: - { - switch (value) - { - case 0x84F3: - return "GL_FENCE_STATUS_NV"; - case 0x84F4: - return "GL_FENCE_CONDITION_NV"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogCoordSrc: - { - switch (value) - { - case 0x8451: - return "GL_FOG_COORD"; - case 0x8452: - return "GL_FRAGMENT_DEPTH"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogCoordinatePointerType: - { - switch (value) - { - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogMode: - { - switch (value) - { - case 0x800: - return "GL_EXP"; - case 0x801: - return "GL_EXP2"; - case 0x2601: - return "GL_LINEAR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogPName: - { - switch (value) - { - case 0xB61: - return "GL_FOG_INDEX"; - case 0xB62: - return "GL_FOG_DENSITY"; - case 0xB63: - return "GL_FOG_START"; - case 0xB64: - return "GL_FOG_END"; - case 0xB65: - return "GL_FOG_MODE"; - case 0x8450: - return "GL_FOG_COORD_SRC"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogParameter: - { - switch (value) - { - case 0xB61: - return "GL_FOG_INDEX"; - case 0xB62: - return "GL_FOG_DENSITY"; - case 0xB63: - return "GL_FOG_START"; - case 0xB64: - return "GL_FOG_END"; - case 0xB65: - return "GL_FOG_MODE"; - case 0xB66: - return "GL_FOG_COLOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogPointerTypeEXT: - { - switch (value) - { - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FogPointerTypeIBM: - { - switch (value) - { - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FragmentLightParameterSGIX: - { - switch (value) - { - case 0x1200: - return "GL_AMBIENT"; - case 0x1201: - return "GL_DIFFUSE"; - case 0x1202: - return "GL_SPECULAR"; - case 0x1203: - return "GL_POSITION"; - case 0x1204: - return "GL_SPOT_DIRECTION"; - case 0x1205: - return "GL_SPOT_EXPONENT"; - case 0x1206: - return "GL_SPOT_CUTOFF"; - case 0x1207: - return "GL_CONSTANT_ATTENUATION"; - case 0x1208: - return "GL_LINEAR_ATTENUATION"; - case 0x1209: - return "GL_QUADRATIC_ATTENUATION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FragmentShaderDestMaskATI: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FragmentShaderDestModMaskATI: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FragmentShaderGenericSourceATI: - { - switch (value) - { - case 0x0: - return "GL_ZERO"; - case 0x1: - return "GL_ONE"; - case 0x8577: - return "GL_PRIMARY_COLOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FragmentShaderTextureSourceATI: - { - switch (value) - { - case 0x84C0: - return "GL_TEXTURE0"; - case 0x84C1: - return "GL_TEXTURE1"; - case 0x84C2: - return "GL_TEXTURE2"; - case 0x84C3: - return "GL_TEXTURE3"; - case 0x84C4: - return "GL_TEXTURE4"; - case 0x84C5: - return "GL_TEXTURE5"; - case 0x84C6: - return "GL_TEXTURE6"; - case 0x84C7: - return "GL_TEXTURE7"; - case 0x84C8: - return "GL_TEXTURE8"; - case 0x84C9: - return "GL_TEXTURE9"; - case 0x84CA: - return "GL_TEXTURE10"; - case 0x84CB: - return "GL_TEXTURE11"; - case 0x84CC: - return "GL_TEXTURE12"; - case 0x84CD: - return "GL_TEXTURE13"; - case 0x84CE: - return "GL_TEXTURE14"; - case 0x84CF: - return "GL_TEXTURE15"; - case 0x84D0: - return "GL_TEXTURE16"; - case 0x84D1: - return "GL_TEXTURE17"; - case 0x84D2: - return "GL_TEXTURE18"; - case 0x84D3: - return "GL_TEXTURE19"; - case 0x84D4: - return "GL_TEXTURE20"; - case 0x84D5: - return "GL_TEXTURE21"; - case 0x84D6: - return "GL_TEXTURE22"; - case 0x84D7: - return "GL_TEXTURE23"; - case 0x84D8: - return "GL_TEXTURE24"; - case 0x84D9: - return "GL_TEXTURE25"; - case 0x84DA: - return "GL_TEXTURE26"; - case 0x84DB: - return "GL_TEXTURE27"; - case 0x84DC: - return "GL_TEXTURE28"; - case 0x84DD: - return "GL_TEXTURE29"; - case 0x84DE: - return "GL_TEXTURE30"; - case 0x84DF: - return "GL_TEXTURE31"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FragmentShaderValueRepATI: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x1903: - return "GL_RED"; - case 0x1904: - return "GL_GREEN"; - case 0x1905: - return "GL_BLUE"; - case 0x1906: - return "GL_ALPHA"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FramebufferAttachment: - { - switch (value) - { - case 0x821A: - return "GL_DEPTH_STENCIL_ATTACHMENT"; - case 0x8CE0: - return "GL_COLOR_ATTACHMENT0"; - case 0x8CE1: - return "GL_COLOR_ATTACHMENT1"; - case 0x8CE2: - return "GL_COLOR_ATTACHMENT2"; - case 0x8CE3: - return "GL_COLOR_ATTACHMENT3"; - case 0x8CE4: - return "GL_COLOR_ATTACHMENT4"; - case 0x8CE5: - return "GL_COLOR_ATTACHMENT5"; - case 0x8CE6: - return "GL_COLOR_ATTACHMENT6"; - case 0x8CE7: - return "GL_COLOR_ATTACHMENT7"; - case 0x8CE8: - return "GL_COLOR_ATTACHMENT8"; - case 0x8CE9: - return "GL_COLOR_ATTACHMENT9"; - case 0x8CEA: - return "GL_COLOR_ATTACHMENT10"; - case 0x8CEB: - return "GL_COLOR_ATTACHMENT11"; - case 0x8CEC: - return "GL_COLOR_ATTACHMENT12"; - case 0x8CED: - return "GL_COLOR_ATTACHMENT13"; - case 0x8CEE: - return "GL_COLOR_ATTACHMENT14"; - case 0x8CEF: - return "GL_COLOR_ATTACHMENT15"; - case 0x8CF0: - return "GL_COLOR_ATTACHMENT16"; - case 0x8CF1: - return "GL_COLOR_ATTACHMENT17"; - case 0x8CF2: - return "GL_COLOR_ATTACHMENT18"; - case 0x8CF3: - return "GL_COLOR_ATTACHMENT19"; - case 0x8CF4: - return "GL_COLOR_ATTACHMENT20"; - case 0x8CF5: - return "GL_COLOR_ATTACHMENT21"; - case 0x8CF6: - return "GL_COLOR_ATTACHMENT22"; - case 0x8CF7: - return "GL_COLOR_ATTACHMENT23"; - case 0x8CF8: - return "GL_COLOR_ATTACHMENT24"; - case 0x8CF9: - return "GL_COLOR_ATTACHMENT25"; - case 0x8CFA: - return "GL_COLOR_ATTACHMENT26"; - case 0x8CFB: - return "GL_COLOR_ATTACHMENT27"; - case 0x8CFC: - return "GL_COLOR_ATTACHMENT28"; - case 0x8CFD: - return "GL_COLOR_ATTACHMENT29"; - case 0x8CFE: - return "GL_COLOR_ATTACHMENT30"; - case 0x8CFF: - return "GL_COLOR_ATTACHMENT31"; - case 0x8D00: - return "GL_DEPTH_ATTACHMENT"; - case 0x8D20: - return "GL_STENCIL_ATTACHMENT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FramebufferAttachmentParameterName: - { - switch (value) - { - case 0x8210: - return "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"; - case 0x8211: - return "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"; - case 0x8212: - return "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE"; - case 0x8213: - return "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE"; - case 0x8214: - return "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE"; - case 0x8215: - return "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE"; - case 0x8216: - return "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE"; - case 0x8217: - return "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE"; - case 0x8CD0: - return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"; - case 0x8CD1: - return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"; - case 0x8CD2: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"; - case 0x8CD3: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"; - case 0x8CD4: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"; - case 0x8DA7: - return "GL_FRAMEBUFFER_ATTACHMENT_LAYERED"; - case 0x9630: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"; - case 0x9632: - return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FramebufferParameterName: - { - switch (value) - { - case 0x9310: - return "GL_FRAMEBUFFER_DEFAULT_WIDTH"; - case 0x9311: - return "GL_FRAMEBUFFER_DEFAULT_HEIGHT"; - case 0x9312: - return "GL_FRAMEBUFFER_DEFAULT_LAYERS"; - case 0x9313: - return "GL_FRAMEBUFFER_DEFAULT_SAMPLES"; - case 0x9314: - return "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FramebufferStatus: - { - switch (value) - { - case 0x8219: - return "GL_FRAMEBUFFER_UNDEFINED"; - case 0x8CD5: - return "GL_FRAMEBUFFER_COMPLETE"; - case 0x8CD6: - return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; - case 0x8CD7: - return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; - case 0x8CDB: - return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; - case 0x8CDC: - return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; - case 0x8CDD: - return "GL_FRAMEBUFFER_UNSUPPORTED"; - case 0x8D56: - return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; - case 0x8DA8: - return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FramebufferTarget: - { - switch (value) - { - case 0x8CA8: - return "GL_READ_FRAMEBUFFER"; - case 0x8CA9: - return "GL_DRAW_FRAMEBUFFER"; - case 0x8D40: - return "GL_FRAMEBUFFER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::FrontFaceDirection: - { - switch (value) - { - case 0x900: - return "GL_CW"; - case 0x901: - return "GL_CCW"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GetFramebufferParameter: - { - switch (value) - { - case 0xC32: - return "GL_DOUBLEBUFFER"; - case 0xC33: - return "GL_STEREO"; - case 0x80A8: - return "GL_SAMPLE_BUFFERS"; - case 0x80A9: - return "GL_SAMPLES"; - case 0x8B9A: - return "GL_IMPLEMENTATION_COLOR_READ_TYPE"; - case 0x8B9B: - return "GL_IMPLEMENTATION_COLOR_READ_FORMAT"; - case 0x9310: - return "GL_FRAMEBUFFER_DEFAULT_WIDTH"; - case 0x9311: - return "GL_FRAMEBUFFER_DEFAULT_HEIGHT"; - case 0x9312: - return "GL_FRAMEBUFFER_DEFAULT_LAYERS"; - case 0x9313: - return "GL_FRAMEBUFFER_DEFAULT_SAMPLES"; - case 0x9314: - return "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GetMapQuery: - { - switch (value) - { - case 0xA00: - return "GL_COEFF"; - case 0xA01: - return "GL_ORDER"; - case 0xA02: - return "GL_DOMAIN"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GetMultisamplePNameNV: - { - switch (value) - { - case 0x8E50: - return "GL_SAMPLE_POSITION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GetPName: - { - switch (value) - { - case 0xB00: - return "GL_CURRENT_COLOR"; - case 0xB01: - return "GL_CURRENT_INDEX"; - case 0xB02: - return "GL_CURRENT_NORMAL"; - case 0xB03: - return "GL_CURRENT_TEXTURE_COORDS"; - case 0xB04: - return "GL_CURRENT_RASTER_COLOR"; - case 0xB05: - return "GL_CURRENT_RASTER_INDEX"; - case 0xB06: - return "GL_CURRENT_RASTER_TEXTURE_COORDS"; - case 0xB07: - return "GL_CURRENT_RASTER_POSITION"; - case 0xB08: - return "GL_CURRENT_RASTER_POSITION_VALID"; - case 0xB09: - return "GL_CURRENT_RASTER_DISTANCE"; - case 0xB10: - return "GL_POINT_SMOOTH"; - case 0xB11: - return "GL_POINT_SIZE"; - case 0xB12: - return "GL_POINT_SIZE_RANGE"; - case 0xB13: - return "GL_POINT_SIZE_GRANULARITY"; - case 0xB20: - return "GL_LINE_SMOOTH"; - case 0xB21: - return "GL_LINE_WIDTH"; - case 0xB22: - return "GL_LINE_WIDTH_RANGE"; - case 0xB23: - return "GL_LINE_WIDTH_GRANULARITY"; - case 0xB24: - return "GL_LINE_STIPPLE"; - case 0xB25: - return "GL_LINE_STIPPLE_PATTERN"; - case 0xB26: - return "GL_LINE_STIPPLE_REPEAT"; - case 0xB30: - return "GL_LIST_MODE"; - case 0xB31: - return "GL_MAX_LIST_NESTING"; - case 0xB32: - return "GL_LIST_BASE"; - case 0xB33: - return "GL_LIST_INDEX"; - case 0xB40: - return "GL_POLYGON_MODE"; - case 0xB41: - return "GL_POLYGON_SMOOTH"; - case 0xB42: - return "GL_POLYGON_STIPPLE"; - case 0xB43: - return "GL_EDGE_FLAG"; - case 0xB44: - return "GL_CULL_FACE"; - case 0xB45: - return "GL_CULL_FACE_MODE"; - case 0xB46: - return "GL_FRONT_FACE"; - case 0xB50: - return "GL_LIGHTING"; - case 0xB51: - return "GL_LIGHT_MODEL_LOCAL_VIEWER"; - case 0xB52: - return "GL_LIGHT_MODEL_TWO_SIDE"; - case 0xB53: - return "GL_LIGHT_MODEL_AMBIENT"; - case 0xB54: - return "GL_SHADE_MODEL"; - case 0xB55: - return "GL_COLOR_MATERIAL_FACE"; - case 0xB56: - return "GL_COLOR_MATERIAL_PARAMETER"; - case 0xB57: - return "GL_COLOR_MATERIAL"; - case 0xB60: - return "GL_FOG"; - case 0xB61: - return "GL_FOG_INDEX"; - case 0xB62: - return "GL_FOG_DENSITY"; - case 0xB63: - return "GL_FOG_START"; - case 0xB64: - return "GL_FOG_END"; - case 0xB65: - return "GL_FOG_MODE"; - case 0xB66: - return "GL_FOG_COLOR"; - case 0xB70: - return "GL_DEPTH_RANGE"; - case 0xB71: - return "GL_DEPTH_TEST"; - case 0xB72: - return "GL_DEPTH_WRITEMASK"; - case 0xB73: - return "GL_DEPTH_CLEAR_VALUE"; - case 0xB74: - return "GL_DEPTH_FUNC"; - case 0xB80: - return "GL_ACCUM_CLEAR_VALUE"; - case 0xB90: - return "GL_STENCIL_TEST"; - case 0xB91: - return "GL_STENCIL_CLEAR_VALUE"; - case 0xB92: - return "GL_STENCIL_FUNC"; - case 0xB93: - return "GL_STENCIL_VALUE_MASK"; - case 0xB94: - return "GL_STENCIL_FAIL"; - case 0xB95: - return "GL_STENCIL_PASS_DEPTH_FAIL"; - case 0xB96: - return "GL_STENCIL_PASS_DEPTH_PASS"; - case 0xB97: - return "GL_STENCIL_REF"; - case 0xB98: - return "GL_STENCIL_WRITEMASK"; - case 0xBA0: - return "GL_MATRIX_MODE"; - case 0xBA1: - return "GL_NORMALIZE"; - case 0xBA2: - return "GL_VIEWPORT"; - case 0xBA3: - return "GL_MODELVIEW_STACK_DEPTH"; - case 0xBA4: - return "GL_PROJECTION_STACK_DEPTH"; - case 0xBA5: - return "GL_TEXTURE_STACK_DEPTH"; - case 0xBA6: - return "GL_MODELVIEW_MATRIX"; - case 0xBA7: - return "GL_PROJECTION_MATRIX"; - case 0xBA8: - return "GL_TEXTURE_MATRIX"; - case 0xBB0: - return "GL_ATTRIB_STACK_DEPTH"; - case 0xBB1: - return "GL_CLIENT_ATTRIB_STACK_DEPTH"; - case 0xBC0: - return "GL_ALPHA_TEST"; - case 0xBC1: - return "GL_ALPHA_TEST_FUNC"; - case 0xBC2: - return "GL_ALPHA_TEST_REF"; - case 0xBD0: - return "GL_DITHER"; - case 0xBE0: - return "GL_BLEND_DST"; - case 0xBE1: - return "GL_BLEND_SRC"; - case 0xBE2: - return "GL_BLEND"; - case 0xBF0: - return "GL_LOGIC_OP_MODE"; - case 0xBF1: - return "GL_LOGIC_OP"; - case 0xBF2: - return "GL_COLOR_LOGIC_OP"; - case 0xC00: - return "GL_AUX_BUFFERS"; - case 0xC01: - return "GL_DRAW_BUFFER"; - case 0xC02: - return "GL_READ_BUFFER"; - case 0xC10: - return "GL_SCISSOR_BOX"; - case 0xC11: - return "GL_SCISSOR_TEST"; - case 0xC20: - return "GL_INDEX_CLEAR_VALUE"; - case 0xC21: - return "GL_INDEX_WRITEMASK"; - case 0xC22: - return "GL_COLOR_CLEAR_VALUE"; - case 0xC23: - return "GL_COLOR_WRITEMASK"; - case 0xC30: - return "GL_INDEX_MODE"; - case 0xC31: - return "GL_RGBA_MODE"; - case 0xC32: - return "GL_DOUBLEBUFFER"; - case 0xC33: - return "GL_STEREO"; - case 0xC40: - return "GL_RENDER_MODE"; - case 0xC50: - return "GL_PERSPECTIVE_CORRECTION_HINT"; - case 0xC51: - return "GL_POINT_SMOOTH_HINT"; - case 0xC52: - return "GL_LINE_SMOOTH_HINT"; - case 0xC53: - return "GL_POLYGON_SMOOTH_HINT"; - case 0xC54: - return "GL_FOG_HINT"; - case 0xC60: - return "GL_TEXTURE_GEN_S"; - case 0xC61: - return "GL_TEXTURE_GEN_T"; - case 0xC62: - return "GL_TEXTURE_GEN_R"; - case 0xC63: - return "GL_TEXTURE_GEN_Q"; - case 0xCB0: - return "GL_PIXEL_MAP_I_TO_I_SIZE"; - case 0xCB1: - return "GL_PIXEL_MAP_S_TO_S_SIZE"; - case 0xCB2: - return "GL_PIXEL_MAP_I_TO_R_SIZE"; - case 0xCB3: - return "GL_PIXEL_MAP_I_TO_G_SIZE"; - case 0xCB4: - return "GL_PIXEL_MAP_I_TO_B_SIZE"; - case 0xCB5: - return "GL_PIXEL_MAP_I_TO_A_SIZE"; - case 0xCB6: - return "GL_PIXEL_MAP_R_TO_R_SIZE"; - case 0xCB7: - return "GL_PIXEL_MAP_G_TO_G_SIZE"; - case 0xCB8: - return "GL_PIXEL_MAP_B_TO_B_SIZE"; - case 0xCB9: - return "GL_PIXEL_MAP_A_TO_A_SIZE"; - case 0xCF0: - return "GL_UNPACK_SWAP_BYTES"; - case 0xCF1: - return "GL_UNPACK_LSB_FIRST"; - case 0xCF2: - return "GL_UNPACK_ROW_LENGTH"; - case 0xCF3: - return "GL_UNPACK_SKIP_ROWS"; - case 0xCF4: - return "GL_UNPACK_SKIP_PIXELS"; - case 0xCF5: - return "GL_UNPACK_ALIGNMENT"; - case 0xD00: - return "GL_PACK_SWAP_BYTES"; - case 0xD01: - return "GL_PACK_LSB_FIRST"; - case 0xD02: - return "GL_PACK_ROW_LENGTH"; - case 0xD03: - return "GL_PACK_SKIP_ROWS"; - case 0xD04: - return "GL_PACK_SKIP_PIXELS"; - case 0xD05: - return "GL_PACK_ALIGNMENT"; - case 0xD10: - return "GL_MAP_COLOR"; - case 0xD11: - return "GL_MAP_STENCIL"; - case 0xD12: - return "GL_INDEX_SHIFT"; - case 0xD13: - return "GL_INDEX_OFFSET"; - case 0xD14: - return "GL_RED_SCALE"; - case 0xD15: - return "GL_RED_BIAS"; - case 0xD16: - return "GL_ZOOM_X"; - case 0xD17: - return "GL_ZOOM_Y"; - case 0xD18: - return "GL_GREEN_SCALE"; - case 0xD19: - return "GL_GREEN_BIAS"; - case 0xD1A: - return "GL_BLUE_SCALE"; - case 0xD1B: - return "GL_BLUE_BIAS"; - case 0xD1C: - return "GL_ALPHA_SCALE"; - case 0xD1D: - return "GL_ALPHA_BIAS"; - case 0xD1E: - return "GL_DEPTH_SCALE"; - case 0xD1F: - return "GL_DEPTH_BIAS"; - case 0xD30: - return "GL_MAX_EVAL_ORDER"; - case 0xD31: - return "GL_MAX_LIGHTS"; - case 0xD32: - return "GL_MAX_CLIP_PLANES"; - case 0xD33: - return "GL_MAX_TEXTURE_SIZE"; - case 0xD34: - return "GL_MAX_PIXEL_MAP_TABLE"; - case 0xD35: - return "GL_MAX_ATTRIB_STACK_DEPTH"; - case 0xD36: - return "GL_MAX_MODELVIEW_STACK_DEPTH"; - case 0xD37: - return "GL_MAX_NAME_STACK_DEPTH"; - case 0xD38: - return "GL_MAX_PROJECTION_STACK_DEPTH"; - case 0xD39: - return "GL_MAX_TEXTURE_STACK_DEPTH"; - case 0xD3A: - return "GL_MAX_VIEWPORT_DIMS"; - case 0xD3B: - return "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"; - case 0xD50: - return "GL_SUBPIXEL_BITS"; - case 0xD51: - return "GL_INDEX_BITS"; - case 0xD52: - return "GL_RED_BITS"; - case 0xD53: - return "GL_GREEN_BITS"; - case 0xD54: - return "GL_BLUE_BITS"; - case 0xD55: - return "GL_ALPHA_BITS"; - case 0xD56: - return "GL_DEPTH_BITS"; - case 0xD57: - return "GL_STENCIL_BITS"; - case 0xD58: - return "GL_ACCUM_RED_BITS"; - case 0xD59: - return "GL_ACCUM_GREEN_BITS"; - case 0xD5A: - return "GL_ACCUM_BLUE_BITS"; - case 0xD5B: - return "GL_ACCUM_ALPHA_BITS"; - case 0xD70: - return "GL_NAME_STACK_DEPTH"; - case 0xD80: - return "GL_AUTO_NORMAL"; - case 0xD90: - return "GL_MAP1_COLOR_4"; - case 0xD91: - return "GL_MAP1_INDEX"; - case 0xD92: - return "GL_MAP1_NORMAL"; - case 0xD93: - return "GL_MAP1_TEXTURE_COORD_1"; - case 0xD94: - return "GL_MAP1_TEXTURE_COORD_2"; - case 0xD95: - return "GL_MAP1_TEXTURE_COORD_3"; - case 0xD96: - return "GL_MAP1_TEXTURE_COORD_4"; - case 0xD97: - return "GL_MAP1_VERTEX_3"; - case 0xD98: - return "GL_MAP1_VERTEX_4"; - case 0xDB0: - return "GL_MAP2_COLOR_4"; - case 0xDB1: - return "GL_MAP2_INDEX"; - case 0xDB2: - return "GL_MAP2_NORMAL"; - case 0xDB3: - return "GL_MAP2_TEXTURE_COORD_1"; - case 0xDB4: - return "GL_MAP2_TEXTURE_COORD_2"; - case 0xDB5: - return "GL_MAP2_TEXTURE_COORD_3"; - case 0xDB6: - return "GL_MAP2_TEXTURE_COORD_4"; - case 0xDB7: - return "GL_MAP2_VERTEX_3"; - case 0xDB8: - return "GL_MAP2_VERTEX_4"; - case 0xDD0: - return "GL_MAP1_GRID_DOMAIN"; - case 0xDD1: - return "GL_MAP1_GRID_SEGMENTS"; - case 0xDD2: - return "GL_MAP2_GRID_DOMAIN"; - case 0xDD3: - return "GL_MAP2_GRID_SEGMENTS"; - case 0xDE0: - return "GL_TEXTURE_1D"; - case 0xDE1: - return "GL_TEXTURE_2D"; - case 0xDF1: - return "GL_FEEDBACK_BUFFER_SIZE"; - case 0xDF2: - return "GL_FEEDBACK_BUFFER_TYPE"; - case 0xDF4: - return "GL_SELECTION_BUFFER_SIZE"; - case 0x2A00: - return "GL_POLYGON_OFFSET_UNITS"; - case 0x2A01: - return "GL_POLYGON_OFFSET_POINT"; - case 0x2A02: - return "GL_POLYGON_OFFSET_LINE"; - case 0x3000: - return "GL_CLIP_PLANE0"; - case 0x3001: - return "GL_CLIP_PLANE1"; - case 0x3002: - return "GL_CLIP_PLANE2"; - case 0x3003: - return "GL_CLIP_PLANE3"; - case 0x3004: - return "GL_CLIP_PLANE4"; - case 0x3005: - return "GL_CLIP_PLANE5"; - case 0x4000: - return "GL_LIGHT0"; - case 0x4001: - return "GL_LIGHT1"; - case 0x4002: - return "GL_LIGHT2"; - case 0x4003: - return "GL_LIGHT3"; - case 0x4004: - return "GL_LIGHT4"; - case 0x4005: - return "GL_LIGHT5"; - case 0x4006: - return "GL_LIGHT6"; - case 0x4007: - return "GL_LIGHT7"; - case 0x8005: - return "GL_BLEND_COLOR"; - case 0x8009: - return "GL_BLEND_EQUATION"; - case 0x8037: - return "GL_POLYGON_OFFSET_FILL"; - case 0x8038: - return "GL_POLYGON_OFFSET_FACTOR"; - case 0x8068: - return "GL_TEXTURE_BINDING_1D"; - case 0x8069: - return "GL_TEXTURE_BINDING_2D"; - case 0x806A: - return "GL_TEXTURE_BINDING_3D"; - case 0x806B: - return "GL_PACK_SKIP_IMAGES"; - case 0x806C: - return "GL_PACK_IMAGE_HEIGHT"; - case 0x806D: - return "GL_UNPACK_SKIP_IMAGES"; - case 0x806E: - return "GL_UNPACK_IMAGE_HEIGHT"; - case 0x8073: - return "GL_MAX_3D_TEXTURE_SIZE"; - case 0x8074: - return "GL_VERTEX_ARRAY"; - case 0x8075: - return "GL_NORMAL_ARRAY"; - case 0x8076: - return "GL_COLOR_ARRAY"; - case 0x8077: - return "GL_INDEX_ARRAY"; - case 0x8078: - return "GL_TEXTURE_COORD_ARRAY"; - case 0x8079: - return "GL_EDGE_FLAG_ARRAY"; - case 0x807A: - return "GL_VERTEX_ARRAY_SIZE"; - case 0x807B: - return "GL_VERTEX_ARRAY_TYPE"; - case 0x807C: - return "GL_VERTEX_ARRAY_STRIDE"; - case 0x807E: - return "GL_NORMAL_ARRAY_TYPE"; - case 0x807F: - return "GL_NORMAL_ARRAY_STRIDE"; - case 0x8081: - return "GL_COLOR_ARRAY_SIZE"; - case 0x8082: - return "GL_COLOR_ARRAY_TYPE"; - case 0x8083: - return "GL_COLOR_ARRAY_STRIDE"; - case 0x8085: - return "GL_INDEX_ARRAY_TYPE"; - case 0x8086: - return "GL_INDEX_ARRAY_STRIDE"; - case 0x8088: - return "GL_TEXTURE_COORD_ARRAY_SIZE"; - case 0x8089: - return "GL_TEXTURE_COORD_ARRAY_TYPE"; - case 0x808A: - return "GL_TEXTURE_COORD_ARRAY_STRIDE"; - case 0x808C: - return "GL_EDGE_FLAG_ARRAY_STRIDE"; - case 0x80A8: - return "GL_SAMPLE_BUFFERS"; - case 0x80A9: - return "GL_SAMPLES"; - case 0x80AA: - return "GL_SAMPLE_COVERAGE_VALUE"; - case 0x80AB: - return "GL_SAMPLE_COVERAGE_INVERT"; - case 0x80C8: - return "GL_BLEND_DST_RGB"; - case 0x80C9: - return "GL_BLEND_SRC_RGB"; - case 0x80CA: - return "GL_BLEND_DST_ALPHA"; - case 0x80CB: - return "GL_BLEND_SRC_ALPHA"; - case 0x80E8: - return "GL_MAX_ELEMENTS_VERTICES"; - case 0x80E9: - return "GL_MAX_ELEMENTS_INDICES"; - case 0x8126: - return "GL_POINT_SIZE_MIN"; - case 0x8127: - return "GL_POINT_SIZE_MAX"; - case 0x8128: - return "GL_POINT_FADE_THRESHOLD_SIZE"; - case 0x8129: - return "GL_POINT_DISTANCE_ATTENUATION"; - case 0x81F8: - return "GL_LIGHT_MODEL_COLOR_CONTROL"; - case 0x821B: - return "GL_MAJOR_VERSION"; - case 0x821C: - return "GL_MINOR_VERSION"; - case 0x821D: - return "GL_NUM_EXTENSIONS"; - case 0x821E: - return "GL_CONTEXT_FLAGS"; - case 0x825A: - return "GL_PROGRAM_PIPELINE_BINDING"; - case 0x825B: - return "GL_MAX_VIEWPORTS"; - case 0x825C: - return "GL_VIEWPORT_SUBPIXEL_BITS"; - case 0x825D: - return "GL_VIEWPORT_BOUNDS_RANGE"; - case 0x825E: - return "GL_LAYER_PROVOKING_VERTEX"; - case 0x825F: - return "GL_VIEWPORT_INDEX_PROVOKING_VERTEX"; - case 0x8263: - return "GL_MAX_COMPUTE_UNIFORM_COMPONENTS"; - case 0x8264: - return "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"; - case 0x8265: - return "GL_MAX_COMPUTE_ATOMIC_COUNTERS"; - case 0x8266: - return "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"; - case 0x826C: - return "GL_MAX_DEBUG_GROUP_STACK_DEPTH"; - case 0x826D: - return "GL_DEBUG_GROUP_STACK_DEPTH"; - case 0x826E: - return "GL_MAX_UNIFORM_LOCATIONS"; - case 0x82D6: - return "GL_VERTEX_BINDING_DIVISOR"; - case 0x82D7: - return "GL_VERTEX_BINDING_OFFSET"; - case 0x82D8: - return "GL_VERTEX_BINDING_STRIDE"; - case 0x82D9: - return "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"; - case 0x82DA: - return "GL_MAX_VERTEX_ATTRIB_BINDINGS"; - case 0x82E8: - return "GL_MAX_LABEL_LENGTH"; - case 0x846D: - return "GL_ALIASED_POINT_SIZE_RANGE"; - case 0x846E: - return "GL_ALIASED_LINE_WIDTH_RANGE"; - case 0x84E0: - return "GL_ACTIVE_TEXTURE"; - case 0x84E8: - return "GL_MAX_RENDERBUFFER_SIZE"; - case 0x84EF: - return "GL_TEXTURE_COMPRESSION_HINT"; - case 0x84F6: - return "GL_TEXTURE_BINDING_RECTANGLE"; - case 0x84F8: - return "GL_MAX_RECTANGLE_TEXTURE_SIZE"; - case 0x84FD: - return "GL_MAX_TEXTURE_LOD_BIAS"; - case 0x8514: - return "GL_TEXTURE_BINDING_CUBE_MAP"; - case 0x851C: - return "GL_MAX_CUBE_MAP_TEXTURE_SIZE"; - case 0x85B5: - return "GL_VERTEX_ARRAY_BINDING"; - case 0x8642: - return "GL_PROGRAM_POINT_SIZE"; - case 0x86A2: - return "GL_NUM_COMPRESSED_TEXTURE_FORMATS"; - case 0x86A3: - return "GL_COMPRESSED_TEXTURE_FORMATS"; - case 0x87FE: - return "GL_NUM_PROGRAM_BINARY_FORMATS"; - case 0x87FF: - return "GL_PROGRAM_BINARY_FORMATS"; - case 0x8800: - return "GL_STENCIL_BACK_FUNC"; - case 0x8801: - return "GL_STENCIL_BACK_FAIL"; - case 0x8802: - return "GL_STENCIL_BACK_PASS_DEPTH_FAIL"; - case 0x8803: - return "GL_STENCIL_BACK_PASS_DEPTH_PASS"; - case 0x8824: - return "GL_MAX_DRAW_BUFFERS"; - case 0x883D: - return "GL_BLEND_EQUATION_ALPHA"; - case 0x8869: - return "GL_MAX_VERTEX_ATTRIBS"; - case 0x8872: - return "GL_MAX_TEXTURE_IMAGE_UNITS"; - case 0x8894: - return "GL_ARRAY_BUFFER_BINDING"; - case 0x8895: - return "GL_ELEMENT_ARRAY_BUFFER_BINDING"; - case 0x88ED: - return "GL_PIXEL_PACK_BUFFER_BINDING"; - case 0x88EF: - return "GL_PIXEL_UNPACK_BUFFER_BINDING"; - case 0x88FC: - return "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS"; - case 0x88FF: - return "GL_MAX_ARRAY_TEXTURE_LAYERS"; - case 0x8904: - return "GL_MIN_PROGRAM_TEXEL_OFFSET"; - case 0x8905: - return "GL_MAX_PROGRAM_TEXEL_OFFSET"; - case 0x8919: - return "GL_SAMPLER_BINDING"; - case 0x8A28: - return "GL_UNIFORM_BUFFER_BINDING"; - case 0x8A29: - return "GL_UNIFORM_BUFFER_START"; - case 0x8A2A: - return "GL_UNIFORM_BUFFER_SIZE"; - case 0x8A2B: - return "GL_MAX_VERTEX_UNIFORM_BLOCKS"; - case 0x8A2C: - return "GL_MAX_GEOMETRY_UNIFORM_BLOCKS"; - case 0x8A2D: - return "GL_MAX_FRAGMENT_UNIFORM_BLOCKS"; - case 0x8A2E: - return "GL_MAX_COMBINED_UNIFORM_BLOCKS"; - case 0x8A2F: - return "GL_MAX_UNIFORM_BUFFER_BINDINGS"; - case 0x8A30: - return "GL_MAX_UNIFORM_BLOCK_SIZE"; - case 0x8A31: - return "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"; - case 0x8A32: - return "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"; - case 0x8A33: - return "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"; - case 0x8A34: - return "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"; - case 0x8B49: - return "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS"; - case 0x8B4A: - return "GL_MAX_VERTEX_UNIFORM_COMPONENTS"; - case 0x8B4B: - return "GL_MAX_VARYING_FLOATS"; - case 0x8B4C: - return "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"; - case 0x8B4D: - return "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"; - case 0x8B8B: - return "GL_FRAGMENT_SHADER_DERIVATIVE_HINT"; - case 0x8B8D: - return "GL_CURRENT_PROGRAM"; - case 0x8B9A: - return "GL_IMPLEMENTATION_COLOR_READ_TYPE"; - case 0x8B9B: - return "GL_IMPLEMENTATION_COLOR_READ_FORMAT"; - case 0x8C1C: - return "GL_TEXTURE_BINDING_1D_ARRAY"; - case 0x8C1D: - return "GL_TEXTURE_BINDING_2D_ARRAY"; - case 0x8C29: - return "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"; - case 0x8C2B: - return "GL_MAX_TEXTURE_BUFFER_SIZE"; - case 0x8C2C: - return "GL_TEXTURE_BINDING_BUFFER"; - case 0x8C84: - return "GL_TRANSFORM_FEEDBACK_BUFFER_START"; - case 0x8C85: - return "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"; - case 0x8C8F: - return "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"; - case 0x8CA3: - return "GL_STENCIL_BACK_REF"; - case 0x8CA4: - return "GL_STENCIL_BACK_VALUE_MASK"; - case 0x8CA5: - return "GL_STENCIL_BACK_WRITEMASK"; - case 0x8CA6: - return "GL_DRAW_FRAMEBUFFER_BINDING"; - case 0x8CA7: - return "GL_RENDERBUFFER_BINDING"; - case 0x8CAA: - return "GL_READ_FRAMEBUFFER_BINDING"; - case 0x8CDF: - return "GL_MAX_COLOR_ATTACHMENTS"; - case 0x8D6B: - return "GL_MAX_ELEMENT_INDEX"; - case 0x8DDF: - return "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"; - case 0x8DF8: - return "GL_SHADER_BINARY_FORMATS"; - case 0x8DF9: - return "GL_NUM_SHADER_BINARY_FORMATS"; - case 0x8DFA: - return "GL_SHADER_COMPILER"; - case 0x8DFB: - return "GL_MAX_VERTEX_UNIFORM_VECTORS"; - case 0x8DFC: - return "GL_MAX_VARYING_VECTORS"; - case 0x8DFD: - return "GL_MAX_FRAGMENT_UNIFORM_VECTORS"; - case 0x8E28: - return "GL_TIMESTAMP"; - case 0x8E4F: - return "GL_PROVOKING_VERTEX"; - case 0x8E59: - return "GL_MAX_SAMPLE_MASK_WORDS"; - case 0x8E89: - return "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"; - case 0x8E8A: - return "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"; - case 0x8F9E: - return "GL_PRIMITIVE_RESTART_INDEX"; - case 0x90BC: - return "GL_MIN_MAP_BUFFER_ALIGNMENT"; - case 0x90D3: - return "GL_SHADER_STORAGE_BUFFER_BINDING"; - case 0x90D4: - return "GL_SHADER_STORAGE_BUFFER_START"; - case 0x90D5: - return "GL_SHADER_STORAGE_BUFFER_SIZE"; - case 0x90D6: - return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"; - case 0x90D7: - return "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"; - case 0x90D8: - return "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"; - case 0x90D9: - return "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"; - case 0x90DA: - return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"; - case 0x90DB: - return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"; - case 0x90DC: - return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"; - case 0x90DD: - return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"; - case 0x90DF: - return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"; - case 0x90EB: - return "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"; - case 0x90EF: - return "GL_DISPATCH_INDIRECT_BUFFER_BINDING"; - case 0x9104: - return "GL_TEXTURE_BINDING_2D_MULTISAMPLE"; - case 0x9105: - return "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"; - case 0x910E: - return "GL_MAX_COLOR_TEXTURE_SAMPLES"; - case 0x910F: - return "GL_MAX_DEPTH_TEXTURE_SAMPLES"; - case 0x9110: - return "GL_MAX_INTEGER_SAMPLES"; - case 0x9111: - return "GL_MAX_SERVER_WAIT_TIMEOUT"; - case 0x9122: - return "GL_MAX_VERTEX_OUTPUT_COMPONENTS"; - case 0x9123: - return "GL_MAX_GEOMETRY_INPUT_COMPONENTS"; - case 0x9124: - return "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"; - case 0x9125: - return "GL_MAX_FRAGMENT_INPUT_COMPONENTS"; - case 0x9126: - return "GL_CONTEXT_PROFILE_MASK"; - case 0x919F: - return "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"; - case 0x91BB: - return "GL_MAX_COMPUTE_UNIFORM_BLOCKS"; - case 0x91BC: - return "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"; - case 0x91BE: - return "GL_MAX_COMPUTE_WORK_GROUP_COUNT"; - case 0x91BF: - return "GL_MAX_COMPUTE_WORK_GROUP_SIZE"; - case 0x92D2: - return "GL_MAX_VERTEX_ATOMIC_COUNTERS"; - case 0x92D3: - return "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"; - case 0x92D4: - return "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"; - case 0x92D5: - return "GL_MAX_GEOMETRY_ATOMIC_COUNTERS"; - case 0x92D6: - return "GL_MAX_FRAGMENT_ATOMIC_COUNTERS"; - case 0x92D7: - return "GL_MAX_COMBINED_ATOMIC_COUNTERS"; - case 0x9315: - return "GL_MAX_FRAMEBUFFER_WIDTH"; - case 0x9316: - return "GL_MAX_FRAMEBUFFER_HEIGHT"; - case 0x9317: - return "GL_MAX_FRAMEBUFFER_LAYERS"; - case 0x9318: - return "GL_MAX_FRAMEBUFFER_SAMPLES"; - case 0x9596: - return "GL_NUM_DEVICE_UUIDS_EXT"; - case 0x9597: - return "GL_DEVICE_UUID_EXT"; - case 0x9598: - return "GL_DRIVER_UUID_EXT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GetPointervPName: - { - switch (value) - { - case 0xDF0: - return "GL_FEEDBACK_BUFFER_POINTER"; - case 0xDF3: - return "GL_SELECTION_BUFFER_POINTER"; - case 0x808E: - return "GL_VERTEX_ARRAY_POINTER"; - case 0x808F: - return "GL_NORMAL_ARRAY_POINTER"; - case 0x8090: - return "GL_COLOR_ARRAY_POINTER"; - case 0x8091: - return "GL_INDEX_ARRAY_POINTER"; - case 0x8092: - return "GL_TEXTURE_COORD_ARRAY_POINTER"; - case 0x8093: - return "GL_EDGE_FLAG_ARRAY_POINTER"; - case 0x8244: - return "GL_DEBUG_CALLBACK_FUNCTION"; - case 0x8245: - return "GL_DEBUG_CALLBACK_USER_PARAM"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GetTextureParameter: - { - switch (value) - { - case 0x1000: - return "GL_TEXTURE_WIDTH"; - case 0x1001: - return "GL_TEXTURE_HEIGHT"; - case 0x1003: - return "GL_TEXTURE_COMPONENTS"; - case 0x1004: - return "GL_TEXTURE_BORDER_COLOR"; - case 0x1005: - return "GL_TEXTURE_BORDER"; - case 0x2800: - return "GL_TEXTURE_MAG_FILTER"; - case 0x2801: - return "GL_TEXTURE_MIN_FILTER"; - case 0x2802: - return "GL_TEXTURE_WRAP_S"; - case 0x2803: - return "GL_TEXTURE_WRAP_T"; - case 0x805C: - return "GL_TEXTURE_RED_SIZE"; - case 0x805D: - return "GL_TEXTURE_GREEN_SIZE"; - case 0x805E: - return "GL_TEXTURE_BLUE_SIZE"; - case 0x805F: - return "GL_TEXTURE_ALPHA_SIZE"; - case 0x8060: - return "GL_TEXTURE_LUMINANCE_SIZE"; - case 0x8061: - return "GL_TEXTURE_INTENSITY_SIZE"; - case 0x8066: - return "GL_TEXTURE_PRIORITY"; - case 0x8067: - return "GL_TEXTURE_RESIDENT"; - case 0x8511: - return "GL_NORMAL_MAP"; - case 0x8512: - return "GL_REFLECTION_MAP"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::GraphicsResetStatus: - { - switch (value) - { - case 0x0: - return "GL_NO_ERROR"; - case 0x8253: - return "GL_GUILTY_CONTEXT_RESET"; - case 0x8254: - return "GL_INNOCENT_CONTEXT_RESET"; - case 0x8255: - return "GL_UNKNOWN_CONTEXT_RESET"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::HintMode: - { - switch (value) - { - case 0x1100: - return "GL_DONT_CARE"; - case 0x1101: - return "GL_FASTEST"; - case 0x1102: - return "GL_NICEST"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::HintTarget: - { - switch (value) - { - case 0xC50: - return "GL_PERSPECTIVE_CORRECTION_HINT"; - case 0xC51: - return "GL_POINT_SMOOTH_HINT"; - case 0xC52: - return "GL_LINE_SMOOTH_HINT"; - case 0xC53: - return "GL_POLYGON_SMOOTH_HINT"; - case 0xC54: - return "GL_FOG_HINT"; - case 0x8192: - return "GL_GENERATE_MIPMAP_HINT"; - case 0x8257: - return "GL_PROGRAM_BINARY_RETRIEVABLE_HINT"; - case 0x84EF: - return "GL_TEXTURE_COMPRESSION_HINT"; - case 0x8B8B: - return "GL_FRAGMENT_SHADER_DERIVATIVE_HINT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::HistogramTarget: - { - switch (value) - { - case 0x8024: - return "GL_HISTOGRAM"; - case 0x8025: - return "GL_PROXY_HISTOGRAM"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::HistogramTargetEXT: - { - switch (value) - { - case 0x8024: - return "GL_HISTOGRAM"; - case 0x8025: - return "GL_PROXY_HISTOGRAM"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::IndexFunctionEXT: - { - switch (value) - { - case 0x200: - return "GL_NEVER"; - case 0x201: - return "GL_LESS"; - case 0x202: - return "GL_EQUAL"; - case 0x203: - return "GL_LEQUAL"; - case 0x204: - return "GL_GREATER"; - case 0x205: - return "GL_NOTEQUAL"; - case 0x206: - return "GL_GEQUAL"; - case 0x207: - return "GL_ALWAYS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::IndexMaterialParameterEXT: - { - switch (value) - { - case 0xD13: - return "GL_INDEX_OFFSET"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::IndexPointerType: - { - switch (value) - { - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::InterleavedArrayFormat: - { - switch (value) - { - case 0x2A20: - return "GL_V2F"; - case 0x2A21: - return "GL_V3F"; - case 0x2A22: - return "GL_C4UB_V2F"; - case 0x2A23: - return "GL_C4UB_V3F"; - case 0x2A24: - return "GL_C3F_V3F"; - case 0x2A25: - return "GL_N3F_V3F"; - case 0x2A26: - return "GL_C4F_N3F_V3F"; - case 0x2A27: - return "GL_T2F_V3F"; - case 0x2A28: - return "GL_T4F_V4F"; - case 0x2A29: - return "GL_T2F_C4UB_V3F"; - case 0x2A2A: - return "GL_T2F_C3F_V3F"; - case 0x2A2B: - return "GL_T2F_N3F_V3F"; - case 0x2A2C: - return "GL_T2F_C4F_N3F_V3F"; - case 0x2A2D: - return "GL_T4F_C4F_N3F_V4F"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::InternalFormat: - { - switch (value) - { - case 0x1901: - return "GL_STENCIL_INDEX"; - case 0x1902: - return "GL_DEPTH_COMPONENT"; - case 0x1903: - return "GL_RED"; - case 0x1907: - return "GL_RGB"; - case 0x1908: - return "GL_RGBA"; - case 0x2A10: - return "GL_R3_G3_B2"; - case 0x803B: - return "GL_ALPHA4"; - case 0x803C: - return "GL_ALPHA8"; - case 0x803D: - return "GL_ALPHA12"; - case 0x803E: - return "GL_ALPHA16"; - case 0x803F: - return "GL_LUMINANCE4"; - case 0x8040: - return "GL_LUMINANCE8"; - case 0x8041: - return "GL_LUMINANCE12"; - case 0x8042: - return "GL_LUMINANCE16"; - case 0x8043: - return "GL_LUMINANCE4_ALPHA4"; - case 0x8044: - return "GL_LUMINANCE6_ALPHA2"; - case 0x8045: - return "GL_LUMINANCE8_ALPHA8"; - case 0x8046: - return "GL_LUMINANCE12_ALPHA4"; - case 0x8047: - return "GL_LUMINANCE12_ALPHA12"; - case 0x8048: - return "GL_LUMINANCE16_ALPHA16"; - case 0x8049: - return "GL_INTENSITY"; - case 0x804A: - return "GL_INTENSITY4"; - case 0x804B: - return "GL_INTENSITY8"; - case 0x804C: - return "GL_INTENSITY12"; - case 0x804D: - return "GL_INTENSITY16"; - case 0x804F: - return "GL_RGB4"; - case 0x8050: - return "GL_RGB5"; - case 0x8051: - return "GL_RGB8"; - case 0x8052: - return "GL_RGB10"; - case 0x8053: - return "GL_RGB12"; - case 0x8054: - return "GL_RGB16"; - case 0x8055: - return "GL_RGBA2"; - case 0x8056: - return "GL_RGBA4"; - case 0x8057: - return "GL_RGB5_A1"; - case 0x8058: - return "GL_RGBA8"; - case 0x8059: - return "GL_RGB10_A2"; - case 0x805A: - return "GL_RGBA12"; - case 0x805B: - return "GL_RGBA16"; - case 0x81A5: - return "GL_DEPTH_COMPONENT16"; - case 0x81A6: - return "GL_DEPTH_COMPONENT24"; - case 0x81A7: - return "GL_DEPTH_COMPONENT32"; - case 0x8225: - return "GL_COMPRESSED_RED"; - case 0x8226: - return "GL_COMPRESSED_RG"; - case 0x8227: - return "GL_RG"; - case 0x8229: - return "GL_R8"; - case 0x822A: - return "GL_R16"; - case 0x822B: - return "GL_RG8"; - case 0x822C: - return "GL_RG16"; - case 0x822D: - return "GL_R16F"; - case 0x822E: - return "GL_R32F"; - case 0x822F: - return "GL_RG16F"; - case 0x8230: - return "GL_RG32F"; - case 0x8231: - return "GL_R8I"; - case 0x8232: - return "GL_R8UI"; - case 0x8233: - return "GL_R16I"; - case 0x8234: - return "GL_R16UI"; - case 0x8235: - return "GL_R32I"; - case 0x8236: - return "GL_R32UI"; - case 0x8237: - return "GL_RG8I"; - case 0x8238: - return "GL_RG8UI"; - case 0x8239: - return "GL_RG16I"; - case 0x823A: - return "GL_RG16UI"; - case 0x823B: - return "GL_RG32I"; - case 0x823C: - return "GL_RG32UI"; - case 0x83F0: - return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; - case 0x83F1: - return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; - case 0x83F2: - return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; - case 0x83F3: - return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; - case 0x84ED: - return "GL_COMPRESSED_RGB"; - case 0x84EE: - return "GL_COMPRESSED_RGBA"; - case 0x84F9: - return "GL_DEPTH_STENCIL"; - case 0x8814: - return "GL_RGBA32F"; - case 0x8815: - return "GL_RGB32F"; - case 0x881A: - return "GL_RGBA16F"; - case 0x881B: - return "GL_RGB16F"; - case 0x88F0: - return "GL_DEPTH24_STENCIL8"; - case 0x8C3A: - return "GL_R11F_G11F_B10F"; - case 0x8C3D: - return "GL_RGB9_E5"; - case 0x8C40: - return "GL_SRGB"; - case 0x8C41: - return "GL_SRGB8"; - case 0x8C42: - return "GL_SRGB_ALPHA"; - case 0x8C43: - return "GL_SRGB8_ALPHA8"; - case 0x8C48: - return "GL_COMPRESSED_SRGB"; - case 0x8C49: - return "GL_COMPRESSED_SRGB_ALPHA"; - case 0x8CAC: - return "GL_DEPTH_COMPONENT32F"; - case 0x8CAD: - return "GL_DEPTH32F_STENCIL8"; - case 0x8D46: - return "GL_STENCIL_INDEX1"; - case 0x8D47: - return "GL_STENCIL_INDEX4"; - case 0x8D48: - return "GL_STENCIL_INDEX8"; - case 0x8D49: - return "GL_STENCIL_INDEX16"; - case 0x8D62: - return "GL_RGB565"; - case 0x8D70: - return "GL_RGBA32UI"; - case 0x8D71: - return "GL_RGB32UI"; - case 0x8D76: - return "GL_RGBA16UI"; - case 0x8D77: - return "GL_RGB16UI"; - case 0x8D7C: - return "GL_RGBA8UI"; - case 0x8D7D: - return "GL_RGB8UI"; - case 0x8D82: - return "GL_RGBA32I"; - case 0x8D83: - return "GL_RGB32I"; - case 0x8D88: - return "GL_RGBA16I"; - case 0x8D89: - return "GL_RGB16I"; - case 0x8D8E: - return "GL_RGBA8I"; - case 0x8D8F: - return "GL_RGB8I"; - case 0x8DBB: - return "GL_COMPRESSED_RED_RGTC1"; - case 0x8DBC: - return "GL_COMPRESSED_SIGNED_RED_RGTC1"; - case 0x8DBD: - return "GL_COMPRESSED_RG_RGTC2"; - case 0x8DBE: - return "GL_COMPRESSED_SIGNED_RG_RGTC2"; - case 0x8E8C: - return "GL_COMPRESSED_RGBA_BPTC_UNORM"; - case 0x8E8D: - return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"; - case 0x8E8E: - return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT"; - case 0x8E8F: - return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT"; - case 0x8F94: - return "GL_R8_SNORM"; - case 0x8F95: - return "GL_RG8_SNORM"; - case 0x8F96: - return "GL_RGB8_SNORM"; - case 0x8F97: - return "GL_RGBA8_SNORM"; - case 0x8F98: - return "GL_R16_SNORM"; - case 0x8F99: - return "GL_RG16_SNORM"; - case 0x8F9A: - return "GL_RGB16_SNORM"; - case 0x8F9B: - return "GL_RGBA16_SNORM"; - case 0x8FBD: - return "GL_SR8_EXT"; - case 0x8FBE: - return "GL_SRG8_EXT"; - case 0x906F: - return "GL_RGB10_A2UI"; - case 0x9270: - return "GL_COMPRESSED_R11_EAC"; - case 0x9271: - return "GL_COMPRESSED_SIGNED_R11_EAC"; - case 0x9272: - return "GL_COMPRESSED_RG11_EAC"; - case 0x9273: - return "GL_COMPRESSED_SIGNED_RG11_EAC"; - case 0x9274: - return "GL_COMPRESSED_RGB8_ETC2"; - case 0x9275: - return "GL_COMPRESSED_SRGB8_ETC2"; - case 0x9276: - return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"; - case 0x9277: - return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"; - case 0x9278: - return "GL_COMPRESSED_RGBA8_ETC2_EAC"; - case 0x9279: - return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"; - case 0x93B0: - return "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"; - case 0x93B1: - return "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"; - case 0x93B2: - return "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"; - case 0x93B3: - return "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"; - case 0x93B4: - return "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"; - case 0x93B5: - return "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"; - case 0x93B6: - return "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"; - case 0x93B7: - return "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"; - case 0x93B8: - return "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"; - case 0x93B9: - return "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"; - case 0x93BA: - return "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"; - case 0x93BB: - return "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"; - case 0x93BC: - return "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"; - case 0x93BD: - return "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"; - case 0x93D0: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"; - case 0x93D1: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"; - case 0x93D2: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"; - case 0x93D3: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"; - case 0x93D4: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"; - case 0x93D5: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"; - case 0x93D6: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"; - case 0x93D7: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"; - case 0x93D8: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"; - case 0x93D9: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"; - case 0x93DA: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"; - case 0x93DB: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"; - case 0x93DC: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"; - case 0x93DD: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::InternalFormatPName: - { - switch (value) - { - case 0x80A9: - return "GL_SAMPLES"; - case 0x8191: - return "GL_GENERATE_MIPMAP"; - case 0x826F: - return "GL_INTERNALFORMAT_SUPPORTED"; - case 0x8270: - return "GL_INTERNALFORMAT_PREFERRED"; - case 0x8271: - return "GL_INTERNALFORMAT_RED_SIZE"; - case 0x8272: - return "GL_INTERNALFORMAT_GREEN_SIZE"; - case 0x8273: - return "GL_INTERNALFORMAT_BLUE_SIZE"; - case 0x8274: - return "GL_INTERNALFORMAT_ALPHA_SIZE"; - case 0x8275: - return "GL_INTERNALFORMAT_DEPTH_SIZE"; - case 0x8276: - return "GL_INTERNALFORMAT_STENCIL_SIZE"; - case 0x8277: - return "GL_INTERNALFORMAT_SHARED_SIZE"; - case 0x8278: - return "GL_INTERNALFORMAT_RED_TYPE"; - case 0x8279: - return "GL_INTERNALFORMAT_GREEN_TYPE"; - case 0x827A: - return "GL_INTERNALFORMAT_BLUE_TYPE"; - case 0x827B: - return "GL_INTERNALFORMAT_ALPHA_TYPE"; - case 0x827C: - return "GL_INTERNALFORMAT_DEPTH_TYPE"; - case 0x827D: - return "GL_INTERNALFORMAT_STENCIL_TYPE"; - case 0x827E: - return "GL_MAX_WIDTH"; - case 0x827F: - return "GL_MAX_HEIGHT"; - case 0x8280: - return "GL_MAX_DEPTH"; - case 0x8281: - return "GL_MAX_LAYERS"; - case 0x8283: - return "GL_COLOR_COMPONENTS"; - case 0x8286: - return "GL_COLOR_RENDERABLE"; - case 0x8287: - return "GL_DEPTH_RENDERABLE"; - case 0x8288: - return "GL_STENCIL_RENDERABLE"; - case 0x8289: - return "GL_FRAMEBUFFER_RENDERABLE"; - case 0x828A: - return "GL_FRAMEBUFFER_RENDERABLE_LAYERED"; - case 0x828B: - return "GL_FRAMEBUFFER_BLEND"; - case 0x828C: - return "GL_READ_PIXELS"; - case 0x828D: - return "GL_READ_PIXELS_FORMAT"; - case 0x828E: - return "GL_READ_PIXELS_TYPE"; - case 0x828F: - return "GL_TEXTURE_IMAGE_FORMAT"; - case 0x8290: - return "GL_TEXTURE_IMAGE_TYPE"; - case 0x8291: - return "GL_GET_TEXTURE_IMAGE_FORMAT"; - case 0x8292: - return "GL_GET_TEXTURE_IMAGE_TYPE"; - case 0x8293: - return "GL_MIPMAP"; - case 0x8295: - return "GL_AUTO_GENERATE_MIPMAP"; - case 0x8296: - return "GL_COLOR_ENCODING"; - case 0x8297: - return "GL_SRGB_READ"; - case 0x8298: - return "GL_SRGB_WRITE"; - case 0x829A: - return "GL_FILTER"; - case 0x829B: - return "GL_VERTEX_TEXTURE"; - case 0x829C: - return "GL_TESS_CONTROL_TEXTURE"; - case 0x829D: - return "GL_TESS_EVALUATION_TEXTURE"; - case 0x829E: - return "GL_GEOMETRY_TEXTURE"; - case 0x829F: - return "GL_FRAGMENT_TEXTURE"; - case 0x82A0: - return "GL_COMPUTE_TEXTURE"; - case 0x82A1: - return "GL_TEXTURE_SHADOW"; - case 0x82A2: - return "GL_TEXTURE_GATHER"; - case 0x82A3: - return "GL_TEXTURE_GATHER_SHADOW"; - case 0x82A4: - return "GL_SHADER_IMAGE_LOAD"; - case 0x82A5: - return "GL_SHADER_IMAGE_STORE"; - case 0x82A6: - return "GL_SHADER_IMAGE_ATOMIC"; - case 0x82A7: - return "GL_IMAGE_TEXEL_SIZE"; - case 0x82A8: - return "GL_IMAGE_COMPATIBILITY_CLASS"; - case 0x82A9: - return "GL_IMAGE_PIXEL_FORMAT"; - case 0x82AA: - return "GL_IMAGE_PIXEL_TYPE"; - case 0x82AC: - return "GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"; - case 0x82AD: - return "GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"; - case 0x82AE: - return "GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"; - case 0x82AF: - return "GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE"; - case 0x82B1: - return "GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"; - case 0x82B2: - return "GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"; - case 0x82B3: - return "GL_TEXTURE_COMPRESSED_BLOCK_SIZE"; - case 0x82B4: - return "GL_CLEAR_BUFFER"; - case 0x82B5: - return "GL_TEXTURE_VIEW"; - case 0x82B6: - return "GL_VIEW_COMPATIBILITY_CLASS"; - case 0x86A1: - return "GL_TEXTURE_COMPRESSED"; - case 0x90C7: - return "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"; - case 0x9365: - return "GL_CLEAR_TEXTURE"; - case 0x9380: - return "GL_NUM_SAMPLE_COUNTS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::InvalidateFramebufferAttachment: - { - switch (value) - { - case 0x1800: - return "GL_COLOR"; - case 0x1801: - return "GL_DEPTH"; - case 0x1802: - return "GL_STENCIL"; - case 0x821A: - return "GL_DEPTH_STENCIL_ATTACHMENT"; - case 0x8CE0: - return "GL_COLOR_ATTACHMENT0"; - case 0x8CE1: - return "GL_COLOR_ATTACHMENT1"; - case 0x8CE2: - return "GL_COLOR_ATTACHMENT2"; - case 0x8CE3: - return "GL_COLOR_ATTACHMENT3"; - case 0x8CE4: - return "GL_COLOR_ATTACHMENT4"; - case 0x8CE5: - return "GL_COLOR_ATTACHMENT5"; - case 0x8CE6: - return "GL_COLOR_ATTACHMENT6"; - case 0x8CE7: - return "GL_COLOR_ATTACHMENT7"; - case 0x8CE8: - return "GL_COLOR_ATTACHMENT8"; - case 0x8CE9: - return "GL_COLOR_ATTACHMENT9"; - case 0x8CEA: - return "GL_COLOR_ATTACHMENT10"; - case 0x8CEB: - return "GL_COLOR_ATTACHMENT11"; - case 0x8CEC: - return "GL_COLOR_ATTACHMENT12"; - case 0x8CED: - return "GL_COLOR_ATTACHMENT13"; - case 0x8CEE: - return "GL_COLOR_ATTACHMENT14"; - case 0x8CEF: - return "GL_COLOR_ATTACHMENT15"; - case 0x8CF0: - return "GL_COLOR_ATTACHMENT16"; - case 0x8CF1: - return "GL_COLOR_ATTACHMENT17"; - case 0x8CF2: - return "GL_COLOR_ATTACHMENT18"; - case 0x8CF3: - return "GL_COLOR_ATTACHMENT19"; - case 0x8CF4: - return "GL_COLOR_ATTACHMENT20"; - case 0x8CF5: - return "GL_COLOR_ATTACHMENT21"; - case 0x8CF6: - return "GL_COLOR_ATTACHMENT22"; - case 0x8CF7: - return "GL_COLOR_ATTACHMENT23"; - case 0x8CF8: - return "GL_COLOR_ATTACHMENT24"; - case 0x8CF9: - return "GL_COLOR_ATTACHMENT25"; - case 0x8CFA: - return "GL_COLOR_ATTACHMENT26"; - case 0x8CFB: - return "GL_COLOR_ATTACHMENT27"; - case 0x8CFC: - return "GL_COLOR_ATTACHMENT28"; - case 0x8CFD: - return "GL_COLOR_ATTACHMENT29"; - case 0x8CFE: - return "GL_COLOR_ATTACHMENT30"; - case 0x8CFF: - return "GL_COLOR_ATTACHMENT31"; - case 0x8D00: - return "GL_DEPTH_ATTACHMENT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LightEnvModeSGIX: - { - switch (value) - { - case 0x104: - return "GL_ADD"; - case 0x1E01: - return "GL_REPLACE"; - case 0x2100: - return "GL_MODULATE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LightModelColorControl: - { - switch (value) - { - case 0x81F9: - return "GL_SINGLE_COLOR"; - case 0x81FA: - return "GL_SEPARATE_SPECULAR_COLOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LightModelParameter: - { - switch (value) - { - case 0xB51: - return "GL_LIGHT_MODEL_LOCAL_VIEWER"; - case 0xB52: - return "GL_LIGHT_MODEL_TWO_SIDE"; - case 0xB53: - return "GL_LIGHT_MODEL_AMBIENT"; - case 0x81F8: - return "GL_LIGHT_MODEL_COLOR_CONTROL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LightName: - { - switch (value) - { - case 0x4000: - return "GL_LIGHT0"; - case 0x4001: - return "GL_LIGHT1"; - case 0x4002: - return "GL_LIGHT2"; - case 0x4003: - return "GL_LIGHT3"; - case 0x4004: - return "GL_LIGHT4"; - case 0x4005: - return "GL_LIGHT5"; - case 0x4006: - return "GL_LIGHT6"; - case 0x4007: - return "GL_LIGHT7"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LightParameter: - { - switch (value) - { - case 0x1203: - return "GL_POSITION"; - case 0x1204: - return "GL_SPOT_DIRECTION"; - case 0x1205: - return "GL_SPOT_EXPONENT"; - case 0x1206: - return "GL_SPOT_CUTOFF"; - case 0x1207: - return "GL_CONSTANT_ATTENUATION"; - case 0x1208: - return "GL_LINEAR_ATTENUATION"; - case 0x1209: - return "GL_QUADRATIC_ATTENUATION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LightTextureModeEXT: - { - switch (value) - { - case 0x8452: - return "GL_FRAGMENT_DEPTH"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ListMode: - { - switch (value) - { - case 0x1300: - return "GL_COMPILE"; - case 0x1301: - return "GL_COMPILE_AND_EXECUTE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ListNameType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x1407: - return "GL_2_BYTES"; - case 0x1408: - return "GL_3_BYTES"; - case 0x1409: - return "GL_4_BYTES"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::LogicOp: - { - switch (value) - { - case 0x1500: - return "GL_CLEAR"; - case 0x1501: - return "GL_AND"; - case 0x1502: - return "GL_AND_REVERSE"; - case 0x1503: - return "GL_COPY"; - case 0x1504: - return "GL_AND_INVERTED"; - case 0x1505: - return "GL_NOOP"; - case 0x1506: - return "GL_XOR"; - case 0x1507: - return "GL_OR"; - case 0x1508: - return "GL_NOR"; - case 0x1509: - return "GL_EQUIV"; - case 0x150A: - return "GL_INVERT"; - case 0x150B: - return "GL_OR_REVERSE"; - case 0x150C: - return "GL_COPY_INVERTED"; - case 0x150D: - return "GL_OR_INVERTED"; - case 0x150E: - return "GL_NAND"; - case 0x150F: - return "GL_SET"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MapBufferAccessMask: - { - switch (value) - { - case 0x1: - return "GL_MAP_READ_BIT"; - case 0x2: - return "GL_MAP_WRITE_BIT"; - case 0x4: - return "GL_MAP_INVALIDATE_RANGE_BIT"; - case 0x8: - return "GL_MAP_INVALIDATE_BUFFER_BIT"; - case 0x10: - return "GL_MAP_FLUSH_EXPLICIT_BIT"; - case 0x20: - return "GL_MAP_UNSYNCHRONIZED_BIT"; - case 0x40: - return "GL_MAP_PERSISTENT_BIT"; - case 0x80: - return "GL_MAP_COHERENT_BIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MapQuery: - { - switch (value) - { - case 0xA00: - return "GL_COEFF"; - case 0xA01: - return "GL_ORDER"; - case 0xA02: - return "GL_DOMAIN"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MapTarget: - { - switch (value) - { - case 0xD90: - return "GL_MAP1_COLOR_4"; - case 0xD91: - return "GL_MAP1_INDEX"; - case 0xD92: - return "GL_MAP1_NORMAL"; - case 0xD93: - return "GL_MAP1_TEXTURE_COORD_1"; - case 0xD94: - return "GL_MAP1_TEXTURE_COORD_2"; - case 0xD95: - return "GL_MAP1_TEXTURE_COORD_3"; - case 0xD96: - return "GL_MAP1_TEXTURE_COORD_4"; - case 0xD97: - return "GL_MAP1_VERTEX_3"; - case 0xD98: - return "GL_MAP1_VERTEX_4"; - case 0xDB0: - return "GL_MAP2_COLOR_4"; - case 0xDB1: - return "GL_MAP2_INDEX"; - case 0xDB2: - return "GL_MAP2_NORMAL"; - case 0xDB3: - return "GL_MAP2_TEXTURE_COORD_1"; - case 0xDB4: - return "GL_MAP2_TEXTURE_COORD_2"; - case 0xDB5: - return "GL_MAP2_TEXTURE_COORD_3"; - case 0xDB6: - return "GL_MAP2_TEXTURE_COORD_4"; - case 0xDB7: - return "GL_MAP2_VERTEX_3"; - case 0xDB8: - return "GL_MAP2_VERTEX_4"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MapTypeNV: - { - switch (value) - { - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MaterialParameter: - { - switch (value) - { - case 0x1200: - return "GL_AMBIENT"; - case 0x1201: - return "GL_DIFFUSE"; - case 0x1202: - return "GL_SPECULAR"; - case 0x1600: - return "GL_EMISSION"; - case 0x1601: - return "GL_SHININESS"; - case 0x1602: - return "GL_AMBIENT_AND_DIFFUSE"; - case 0x1603: - return "GL_COLOR_INDEXES"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MatrixIndexPointerTypeARB: - { - switch (value) - { - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MatrixMode: - { - switch (value) - { - case 0x1700: - return "GL_MODELVIEW"; - case 0x1701: - return "GL_PROJECTION"; - case 0x1702: - return "GL_TEXTURE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MemoryBarrierMask: - { - switch (value) - { - case 0x1: - return "GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT"; - case 0x2: - return "GL_ELEMENT_ARRAY_BARRIER_BIT"; - case 0x4: - return "GL_UNIFORM_BARRIER_BIT"; - case 0x8: - return "GL_TEXTURE_FETCH_BARRIER_BIT"; - case 0x20: - return "GL_SHADER_IMAGE_ACCESS_BARRIER_BIT"; - case 0x40: - return "GL_COMMAND_BARRIER_BIT"; - case 0x80: - return "GL_PIXEL_BUFFER_BARRIER_BIT"; - case 0x100: - return "GL_TEXTURE_UPDATE_BARRIER_BIT"; - case 0x200: - return "GL_BUFFER_UPDATE_BARRIER_BIT"; - case 0x400: - return "GL_FRAMEBUFFER_BARRIER_BIT"; - case 0x800: - return "GL_TRANSFORM_FEEDBACK_BARRIER_BIT"; - case 0x1000: - return "GL_ATOMIC_COUNTER_BARRIER_BIT"; - case 0x2000: - return "GL_SHADER_STORAGE_BARRIER_BIT"; - case 0x4000: - return "GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT"; - case 0x8000: - return "GL_QUERY_BUFFER_BARRIER_BIT"; - case 0xFFFFFFFF: - return "GL_ALL_BARRIER_BITS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MemoryObjectParameterName: - { - switch (value) - { - case 0x9581: - return "GL_DEDICATED_MEMORY_OBJECT_EXT"; - case 0x959B: - return "GL_PROTECTED_MEMORY_OBJECT_EXT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MeshMode1: - { - switch (value) - { - case 0x1B00: - return "GL_POINT"; - case 0x1B01: - return "GL_LINE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MeshMode2: - { - switch (value) - { - case 0x1B00: - return "GL_POINT"; - case 0x1B01: - return "GL_LINE"; - case 0x1B02: - return "GL_FILL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MinmaxTarget: - { - switch (value) - { - case 0x802E: - return "GL_MINMAX"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::MinmaxTargetEXT: - { - switch (value) - { - case 0x802E: - return "GL_MINMAX"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::NormalPointerType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ObjectIdentifier: - { - switch (value) - { - case 0x1702: - return "GL_TEXTURE"; - case 0x8074: - return "GL_VERTEX_ARRAY"; - case 0x82E0: - return "GL_BUFFER"; - case 0x82E1: - return "GL_SHADER"; - case 0x82E2: - return "GL_PROGRAM"; - case 0x82E3: - return "GL_QUERY"; - case 0x82E4: - return "GL_PROGRAM_PIPELINE"; - case 0x82E6: - return "GL_SAMPLER"; - case 0x8D40: - return "GL_FRAMEBUFFER"; - case 0x8D41: - return "GL_RENDERBUFFER"; - case 0x8E22: - return "GL_TRANSFORM_FEEDBACK"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PatchParameterName: - { - switch (value) - { - case 0x8E72: - return "GL_PATCH_VERTICES"; - case 0x8E73: - return "GL_PATCH_DEFAULT_INNER_LEVEL"; - case 0x8E74: - return "GL_PATCH_DEFAULT_OUTER_LEVEL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PathColor: - { - switch (value) - { - case 0x8577: - return "GL_PRIMARY_COLOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PathColorFormat: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x1906: - return "GL_ALPHA"; - case 0x1907: - return "GL_RGB"; - case 0x1908: - return "GL_RGBA"; - case 0x1909: - return "GL_LUMINANCE"; - case 0x190A: - return "GL_LUMINANCE_ALPHA"; - case 0x8049: - return "GL_INTENSITY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PathFillMode: - { - switch (value) - { - case 0x150A: - return "GL_INVERT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PathFontStyle: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PathGenMode: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x2400: - return "GL_EYE_LINEAR"; - case 0x2401: - return "GL_OBJECT_LINEAR"; - case 0x8576: - return "GL_CONSTANT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PathTransformType: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PipelineParameterName: - { - switch (value) - { - case 0x8259: - return "GL_ACTIVE_PROGRAM"; - case 0x8B30: - return "GL_FRAGMENT_SHADER"; - case 0x8B31: - return "GL_VERTEX_SHADER"; - case 0x8B84: - return "GL_INFO_LOG_LENGTH"; - case 0x8DD9: - return "GL_GEOMETRY_SHADER"; - case 0x8E87: - return "GL_TESS_EVALUATION_SHADER"; - case 0x8E88: - return "GL_TESS_CONTROL_SHADER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelCopyType: - { - switch (value) - { - case 0x1800: - return "GL_COLOR"; - case 0x1801: - return "GL_DEPTH"; - case 0x1802: - return "GL_STENCIL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelFormat: - { - switch (value) - { - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1900: - return "GL_COLOR_INDEX"; - case 0x1901: - return "GL_STENCIL_INDEX"; - case 0x1902: - return "GL_DEPTH_COMPONENT"; - case 0x1903: - return "GL_RED"; - case 0x1904: - return "GL_GREEN"; - case 0x1905: - return "GL_BLUE"; - case 0x1906: - return "GL_ALPHA"; - case 0x1907: - return "GL_RGB"; - case 0x1908: - return "GL_RGBA"; - case 0x1909: - return "GL_LUMINANCE"; - case 0x190A: - return "GL_LUMINANCE_ALPHA"; - case 0x80E0: - return "GL_BGR"; - case 0x80E1: - return "GL_BGRA"; - case 0x8227: - return "GL_RG"; - case 0x8228: - return "GL_RG_INTEGER"; - case 0x84F9: - return "GL_DEPTH_STENCIL"; - case 0x8D94: - return "GL_RED_INTEGER"; - case 0x8D95: - return "GL_GREEN_INTEGER"; - case 0x8D96: - return "GL_BLUE_INTEGER"; - case 0x8D98: - return "GL_RGB_INTEGER"; - case 0x8D99: - return "GL_RGBA_INTEGER"; - case 0x8D9A: - return "GL_BGR_INTEGER"; - case 0x8D9B: - return "GL_BGRA_INTEGER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelMap: - { - switch (value) - { - case 0xC70: - return "GL_PIXEL_MAP_I_TO_I"; - case 0xC71: - return "GL_PIXEL_MAP_S_TO_S"; - case 0xC72: - return "GL_PIXEL_MAP_I_TO_R"; - case 0xC73: - return "GL_PIXEL_MAP_I_TO_G"; - case 0xC74: - return "GL_PIXEL_MAP_I_TO_B"; - case 0xC75: - return "GL_PIXEL_MAP_I_TO_A"; - case 0xC76: - return "GL_PIXEL_MAP_R_TO_R"; - case 0xC77: - return "GL_PIXEL_MAP_G_TO_G"; - case 0xC78: - return "GL_PIXEL_MAP_B_TO_B"; - case 0xC79: - return "GL_PIXEL_MAP_A_TO_A"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelStoreParameter: - { - switch (value) - { - case 0xCF0: - return "GL_UNPACK_SWAP_BYTES"; - case 0xCF1: - return "GL_UNPACK_LSB_FIRST"; - case 0xCF2: - return "GL_UNPACK_ROW_LENGTH"; - case 0xCF3: - return "GL_UNPACK_SKIP_ROWS"; - case 0xCF4: - return "GL_UNPACK_SKIP_PIXELS"; - case 0xCF5: - return "GL_UNPACK_ALIGNMENT"; - case 0xD00: - return "GL_PACK_SWAP_BYTES"; - case 0xD01: - return "GL_PACK_LSB_FIRST"; - case 0xD02: - return "GL_PACK_ROW_LENGTH"; - case 0xD03: - return "GL_PACK_SKIP_ROWS"; - case 0xD04: - return "GL_PACK_SKIP_PIXELS"; - case 0xD05: - return "GL_PACK_ALIGNMENT"; - case 0x806B: - return "GL_PACK_SKIP_IMAGES"; - case 0x806C: - return "GL_PACK_IMAGE_HEIGHT"; - case 0x806D: - return "GL_UNPACK_SKIP_IMAGES"; - case 0x806E: - return "GL_UNPACK_IMAGE_HEIGHT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelTexGenModeSGIX: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x1906: - return "GL_ALPHA"; - case 0x1907: - return "GL_RGB"; - case 0x1908: - return "GL_RGBA"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelTransferParameter: - { - switch (value) - { - case 0xD10: - return "GL_MAP_COLOR"; - case 0xD11: - return "GL_MAP_STENCIL"; - case 0xD12: - return "GL_INDEX_SHIFT"; - case 0xD13: - return "GL_INDEX_OFFSET"; - case 0xD14: - return "GL_RED_SCALE"; - case 0xD15: - return "GL_RED_BIAS"; - case 0xD18: - return "GL_GREEN_SCALE"; - case 0xD19: - return "GL_GREEN_BIAS"; - case 0xD1A: - return "GL_BLUE_SCALE"; - case 0xD1B: - return "GL_BLUE_BIAS"; - case 0xD1C: - return "GL_ALPHA_SCALE"; - case 0xD1D: - return "GL_ALPHA_BIAS"; - case 0xD1E: - return "GL_DEPTH_SCALE"; - case 0xD1F: - return "GL_DEPTH_BIAS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PixelType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140B: - return "GL_HALF_FLOAT"; - case 0x1A00: - return "GL_BITMAP"; - case 0x8032: - return "GL_UNSIGNED_BYTE_3_3_2"; - case 0x8033: - return "GL_UNSIGNED_SHORT_4_4_4_4"; - case 0x8034: - return "GL_UNSIGNED_SHORT_5_5_5_1"; - case 0x8035: - return "GL_UNSIGNED_INT_8_8_8_8"; - case 0x8036: - return "GL_UNSIGNED_INT_10_10_10_2"; - case 0x8362: - return "GL_UNSIGNED_BYTE_2_3_3_REV"; - case 0x8363: - return "GL_UNSIGNED_SHORT_5_6_5"; - case 0x8364: - return "GL_UNSIGNED_SHORT_5_6_5_REV"; - case 0x8365: - return "GL_UNSIGNED_SHORT_4_4_4_4_REV"; - case 0x8366: - return "GL_UNSIGNED_SHORT_1_5_5_5_REV"; - case 0x8367: - return "GL_UNSIGNED_INT_8_8_8_8_REV"; - case 0x8368: - return "GL_UNSIGNED_INT_2_10_10_10_REV"; - case 0x84FA: - return "GL_UNSIGNED_INT_24_8"; - case 0x8C3B: - return "GL_UNSIGNED_INT_10F_11F_11F_REV"; - case 0x8C3E: - return "GL_UNSIGNED_INT_5_9_9_9_REV"; - case 0x8DAD: - return "GL_FLOAT_32_UNSIGNED_INT_24_8_REV"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PointParameterNameARB: - { - switch (value) - { - case 0x8126: - return "GL_POINT_SIZE_MIN"; - case 0x8127: - return "GL_POINT_SIZE_MAX"; - case 0x8128: - return "GL_POINT_FADE_THRESHOLD_SIZE"; - case 0x8129: - return "GL_POINT_DISTANCE_ATTENUATION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PolygonMode: - { - switch (value) - { - case 0x1B00: - return "GL_POINT"; - case 0x1B01: - return "GL_LINE"; - case 0x1B02: - return "GL_FILL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PrecisionType: - { - switch (value) - { - case 0x8DF0: - return "GL_LOW_FLOAT"; - case 0x8DF1: - return "GL_MEDIUM_FLOAT"; - case 0x8DF2: - return "GL_HIGH_FLOAT"; - case 0x8DF3: - return "GL_LOW_INT"; - case 0x8DF4: - return "GL_MEDIUM_INT"; - case 0x8DF5: - return "GL_HIGH_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::PrimitiveType: - { - switch (value) - { - case 0x0: - return "GL_POINTS"; - case 0x1: - return "GL_LINES"; - case 0x2: - return "GL_LINE_LOOP"; - case 0x3: - return "GL_LINE_STRIP"; - case 0x4: - return "GL_TRIANGLES"; - case 0x5: - return "GL_TRIANGLE_STRIP"; - case 0x6: - return "GL_TRIANGLE_FAN"; - case 0x7: - return "GL_QUADS"; - case 0x8: - return "GL_QUAD_STRIP"; - case 0x9: - return "GL_POLYGON"; - case 0xA: - return "GL_LINES_ADJACENCY"; - case 0xB: - return "GL_LINE_STRIP_ADJACENCY"; - case 0xC: - return "GL_TRIANGLES_ADJACENCY"; - case 0xD: - return "GL_TRIANGLE_STRIP_ADJACENCY"; - case 0xE: - return "GL_PATCHES"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ProgramInterface: - { - switch (value) - { - case 0x8C8E: - return "GL_TRANSFORM_FEEDBACK_BUFFER"; - case 0x92E1: - return "GL_UNIFORM"; - case 0x92E2: - return "GL_UNIFORM_BLOCK"; - case 0x92E3: - return "GL_PROGRAM_INPUT"; - case 0x92E4: - return "GL_PROGRAM_OUTPUT"; - case 0x92E5: - return "GL_BUFFER_VARIABLE"; - case 0x92E6: - return "GL_SHADER_STORAGE_BLOCK"; - case 0x92E8: - return "GL_VERTEX_SUBROUTINE"; - case 0x92E9: - return "GL_TESS_CONTROL_SUBROUTINE"; - case 0x92EA: - return "GL_TESS_EVALUATION_SUBROUTINE"; - case 0x92EB: - return "GL_GEOMETRY_SUBROUTINE"; - case 0x92EC: - return "GL_FRAGMENT_SUBROUTINE"; - case 0x92ED: - return "GL_COMPUTE_SUBROUTINE"; - case 0x92EE: - return "GL_VERTEX_SUBROUTINE_UNIFORM"; - case 0x92EF: - return "GL_TESS_CONTROL_SUBROUTINE_UNIFORM"; - case 0x92F0: - return "GL_TESS_EVALUATION_SUBROUTINE_UNIFORM"; - case 0x92F1: - return "GL_GEOMETRY_SUBROUTINE_UNIFORM"; - case 0x92F2: - return "GL_FRAGMENT_SUBROUTINE_UNIFORM"; - case 0x92F3: - return "GL_COMPUTE_SUBROUTINE_UNIFORM"; - case 0x92F4: - return "GL_TRANSFORM_FEEDBACK_VARYING"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ProgramInterfacePName: - { - switch (value) - { - case 0x92F5: - return "GL_ACTIVE_RESOURCES"; - case 0x92F6: - return "GL_MAX_NAME_LENGTH"; - case 0x92F7: - return "GL_MAX_NUM_ACTIVE_VARIABLES"; - case 0x92F8: - return "GL_MAX_NUM_COMPATIBLE_SUBROUTINES"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ProgramParameterPName: - { - switch (value) - { - case 0x8257: - return "GL_PROGRAM_BINARY_RETRIEVABLE_HINT"; - case 0x8258: - return "GL_PROGRAM_SEPARABLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ProgramPropertyARB: - { - switch (value) - { - case 0x8267: - return "GL_COMPUTE_WORK_GROUP_SIZE"; - case 0x8741: - return "GL_PROGRAM_BINARY_LENGTH"; - case 0x8916: - return "GL_GEOMETRY_VERTICES_OUT"; - case 0x8917: - return "GL_GEOMETRY_INPUT_TYPE"; - case 0x8918: - return "GL_GEOMETRY_OUTPUT_TYPE"; - case 0x8A35: - return "GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"; - case 0x8A36: - return "GL_ACTIVE_UNIFORM_BLOCKS"; - case 0x8B80: - return "GL_DELETE_STATUS"; - case 0x8B82: - return "GL_LINK_STATUS"; - case 0x8B83: - return "GL_VALIDATE_STATUS"; - case 0x8B84: - return "GL_INFO_LOG_LENGTH"; - case 0x8B85: - return "GL_ATTACHED_SHADERS"; - case 0x8B86: - return "GL_ACTIVE_UNIFORMS"; - case 0x8B87: - return "GL_ACTIVE_UNIFORM_MAX_LENGTH"; - case 0x8B89: - return "GL_ACTIVE_ATTRIBUTES"; - case 0x8B8A: - return "GL_ACTIVE_ATTRIBUTE_MAX_LENGTH"; - case 0x8C76: - return "GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"; - case 0x8C7F: - return "GL_TRANSFORM_FEEDBACK_BUFFER_MODE"; - case 0x8C83: - return "GL_TRANSFORM_FEEDBACK_VARYINGS"; - case 0x92D9: - return "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ProgramResourceProperty: - { - switch (value) - { - case 0x8E4A: - return "GL_NUM_COMPATIBLE_SUBROUTINES"; - case 0x8E4B: - return "GL_COMPATIBLE_SUBROUTINES"; - case 0x92E1: - return "GL_UNIFORM"; - case 0x92E7: - return "GL_IS_PER_PATCH"; - case 0x92F9: - return "GL_NAME_LENGTH"; - case 0x92FA: - return "GL_TYPE"; - case 0x92FB: - return "GL_ARRAY_SIZE"; - case 0x92FC: - return "GL_OFFSET"; - case 0x92FD: - return "GL_BLOCK_INDEX"; - case 0x92FE: - return "GL_ARRAY_STRIDE"; - case 0x92FF: - return "GL_MATRIX_STRIDE"; - case 0x9300: - return "GL_IS_ROW_MAJOR"; - case 0x9301: - return "GL_ATOMIC_COUNTER_BUFFER_INDEX"; - case 0x9302: - return "GL_BUFFER_BINDING"; - case 0x9303: - return "GL_BUFFER_DATA_SIZE"; - case 0x9304: - return "GL_NUM_ACTIVE_VARIABLES"; - case 0x9305: - return "GL_ACTIVE_VARIABLES"; - case 0x9306: - return "GL_REFERENCED_BY_VERTEX_SHADER"; - case 0x9307: - return "GL_REFERENCED_BY_TESS_CONTROL_SHADER"; - case 0x9308: - return "GL_REFERENCED_BY_TESS_EVALUATION_SHADER"; - case 0x9309: - return "GL_REFERENCED_BY_GEOMETRY_SHADER"; - case 0x930A: - return "GL_REFERENCED_BY_FRAGMENT_SHADER"; - case 0x930B: - return "GL_REFERENCED_BY_COMPUTE_SHADER"; - case 0x930C: - return "GL_TOP_LEVEL_ARRAY_SIZE"; - case 0x930D: - return "GL_TOP_LEVEL_ARRAY_STRIDE"; - case 0x930E: - return "GL_LOCATION"; - case 0x930F: - return "GL_LOCATION_INDEX"; - case 0x934A: - return "GL_LOCATION_COMPONENT"; - case 0x934B: - return "GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"; - case 0x934C: - return "GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ProgramStagePName: - { - switch (value) - { - case 0x8DE5: - return "GL_ACTIVE_SUBROUTINES"; - case 0x8DE6: - return "GL_ACTIVE_SUBROUTINE_UNIFORMS"; - case 0x8E47: - return "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"; - case 0x8E48: - return "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"; - case 0x8E49: - return "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::QueryCounterTarget: - { - switch (value) - { - case 0x8E28: - return "GL_TIMESTAMP"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::QueryObjectParameterName: - { - switch (value) - { - case 0x82EA: - return "GL_QUERY_TARGET"; - case 0x8866: - return "GL_QUERY_RESULT"; - case 0x8867: - return "GL_QUERY_RESULT_AVAILABLE"; - case 0x9194: - return "GL_QUERY_RESULT_NO_WAIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::QueryParameterName: - { - switch (value) - { - case 0x8864: - return "GL_QUERY_COUNTER_BITS"; - case 0x8865: - return "GL_CURRENT_QUERY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::QueryTarget: - { - switch (value) - { - case 0x82EC: - return "GL_TRANSFORM_FEEDBACK_OVERFLOW"; - case 0x82EE: - return "GL_VERTICES_SUBMITTED"; - case 0x82EF: - return "GL_PRIMITIVES_SUBMITTED"; - case 0x82F0: - return "GL_VERTEX_SHADER_INVOCATIONS"; - case 0x88BF: - return "GL_TIME_ELAPSED"; - case 0x8914: - return "GL_SAMPLES_PASSED"; - case 0x8C2F: - return "GL_ANY_SAMPLES_PASSED"; - case 0x8C87: - return "GL_PRIMITIVES_GENERATED"; - case 0x8C88: - return "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"; - case 0x8D6A: - return "GL_ANY_SAMPLES_PASSED_CONSERVATIVE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ReadBufferMode: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x400: - return "GL_FRONT_LEFT"; - case 0x401: - return "GL_FRONT_RIGHT"; - case 0x402: - return "GL_BACK_LEFT"; - case 0x403: - return "GL_BACK_RIGHT"; - case 0x404: - return "GL_FRONT"; - case 0x405: - return "GL_BACK"; - case 0x406: - return "GL_LEFT"; - case 0x407: - return "GL_RIGHT"; - case 0x409: - return "GL_AUX0"; - case 0x40A: - return "GL_AUX1"; - case 0x40B: - return "GL_AUX2"; - case 0x40C: - return "GL_AUX3"; - case 0x8CE0: - return "GL_COLOR_ATTACHMENT0"; - case 0x8CE1: - return "GL_COLOR_ATTACHMENT1"; - case 0x8CE2: - return "GL_COLOR_ATTACHMENT2"; - case 0x8CE3: - return "GL_COLOR_ATTACHMENT3"; - case 0x8CE4: - return "GL_COLOR_ATTACHMENT4"; - case 0x8CE5: - return "GL_COLOR_ATTACHMENT5"; - case 0x8CE6: - return "GL_COLOR_ATTACHMENT6"; - case 0x8CE7: - return "GL_COLOR_ATTACHMENT7"; - case 0x8CE8: - return "GL_COLOR_ATTACHMENT8"; - case 0x8CE9: - return "GL_COLOR_ATTACHMENT9"; - case 0x8CEA: - return "GL_COLOR_ATTACHMENT10"; - case 0x8CEB: - return "GL_COLOR_ATTACHMENT11"; - case 0x8CEC: - return "GL_COLOR_ATTACHMENT12"; - case 0x8CED: - return "GL_COLOR_ATTACHMENT13"; - case 0x8CEE: - return "GL_COLOR_ATTACHMENT14"; - case 0x8CEF: - return "GL_COLOR_ATTACHMENT15"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::RenderbufferParameterName: - { - switch (value) - { - case 0x8CAB: - return "GL_RENDERBUFFER_SAMPLES"; - case 0x8D42: - return "GL_RENDERBUFFER_WIDTH"; - case 0x8D43: - return "GL_RENDERBUFFER_HEIGHT"; - case 0x8D44: - return "GL_RENDERBUFFER_INTERNAL_FORMAT"; - case 0x8D50: - return "GL_RENDERBUFFER_RED_SIZE"; - case 0x8D51: - return "GL_RENDERBUFFER_GREEN_SIZE"; - case 0x8D52: - return "GL_RENDERBUFFER_BLUE_SIZE"; - case 0x8D53: - return "GL_RENDERBUFFER_ALPHA_SIZE"; - case 0x8D54: - return "GL_RENDERBUFFER_DEPTH_SIZE"; - case 0x8D55: - return "GL_RENDERBUFFER_STENCIL_SIZE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::RenderbufferTarget: - { - switch (value) - { - case 0x8D41: - return "GL_RENDERBUFFER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::RenderingMode: - { - switch (value) - { - case 0x1C00: - return "GL_RENDER"; - case 0x1C01: - return "GL_FEEDBACK"; - case 0x1C02: - return "GL_SELECT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ReplacementCodeTypeSUN: - { - switch (value) - { - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SamplerParameterF: - { - switch (value) - { - case 0x1004: - return "GL_TEXTURE_BORDER_COLOR"; - case 0x813A: - return "GL_TEXTURE_MIN_LOD"; - case 0x813B: - return "GL_TEXTURE_MAX_LOD"; - case 0x84FE: - return "GL_TEXTURE_MAX_ANISOTROPY"; - case 0x8501: - return "GL_TEXTURE_LOD_BIAS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SamplerParameterI: - { - switch (value) - { - case 0x2800: - return "GL_TEXTURE_MAG_FILTER"; - case 0x2801: - return "GL_TEXTURE_MIN_FILTER"; - case 0x2802: - return "GL_TEXTURE_WRAP_S"; - case 0x2803: - return "GL_TEXTURE_WRAP_T"; - case 0x8072: - return "GL_TEXTURE_WRAP_R"; - case 0x884C: - return "GL_TEXTURE_COMPARE_MODE"; - case 0x884D: - return "GL_TEXTURE_COMPARE_FUNC"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ScalarType: - { - switch (value) - { - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SecondaryColorPointerTypeIBM: - { - switch (value) - { - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SeparableTarget: - { - switch (value) - { - case 0x8012: - return "GL_SEPARABLE_2D"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SeparableTargetEXT: - { - switch (value) - { - case 0x8012: - return "GL_SEPARABLE_2D"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ShaderBinaryFormat: - { - switch (value) - { - case 0x9551: - return "GL_SHADER_BINARY_FORMAT_SPIR_V"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ShaderParameterName: - { - switch (value) - { - case 0x8B4F: - return "GL_SHADER_TYPE"; - case 0x8B80: - return "GL_DELETE_STATUS"; - case 0x8B81: - return "GL_COMPILE_STATUS"; - case 0x8B84: - return "GL_INFO_LOG_LENGTH"; - case 0x8B88: - return "GL_SHADER_SOURCE_LENGTH"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ShaderType: - { - switch (value) - { - case 0x8B30: - return "GL_FRAGMENT_SHADER"; - case 0x8B31: - return "GL_VERTEX_SHADER"; - case 0x8DD9: - return "GL_GEOMETRY_SHADER"; - case 0x8E87: - return "GL_TESS_EVALUATION_SHADER"; - case 0x8E88: - return "GL_TESS_CONTROL_SHADER"; - case 0x91B9: - return "GL_COMPUTE_SHADER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::ShadingModel: - { - switch (value) - { - case 0x1D00: - return "GL_FLAT"; - case 0x1D01: - return "GL_SMOOTH"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SizedInternalFormat: - { - switch (value) - { - case 0x2A10: - return "GL_R3_G3_B2"; - case 0x803B: - return "GL_ALPHA4"; - case 0x803C: - return "GL_ALPHA8"; - case 0x803D: - return "GL_ALPHA12"; - case 0x803E: - return "GL_ALPHA16"; - case 0x803F: - return "GL_LUMINANCE4"; - case 0x8040: - return "GL_LUMINANCE8"; - case 0x8041: - return "GL_LUMINANCE12"; - case 0x8042: - return "GL_LUMINANCE16"; - case 0x8043: - return "GL_LUMINANCE4_ALPHA4"; - case 0x8044: - return "GL_LUMINANCE6_ALPHA2"; - case 0x8045: - return "GL_LUMINANCE8_ALPHA8"; - case 0x8046: - return "GL_LUMINANCE12_ALPHA4"; - case 0x8047: - return "GL_LUMINANCE12_ALPHA12"; - case 0x8048: - return "GL_LUMINANCE16_ALPHA16"; - case 0x804A: - return "GL_INTENSITY4"; - case 0x804B: - return "GL_INTENSITY8"; - case 0x804C: - return "GL_INTENSITY12"; - case 0x804D: - return "GL_INTENSITY16"; - case 0x804F: - return "GL_RGB4"; - case 0x8050: - return "GL_RGB5"; - case 0x8051: - return "GL_RGB8"; - case 0x8052: - return "GL_RGB10"; - case 0x8053: - return "GL_RGB12"; - case 0x8054: - return "GL_RGB16"; - case 0x8055: - return "GL_RGBA2"; - case 0x8056: - return "GL_RGBA4"; - case 0x8057: - return "GL_RGB5_A1"; - case 0x8058: - return "GL_RGBA8"; - case 0x8059: - return "GL_RGB10_A2"; - case 0x805A: - return "GL_RGBA12"; - case 0x805B: - return "GL_RGBA16"; - case 0x81A5: - return "GL_DEPTH_COMPONENT16"; - case 0x81A6: - return "GL_DEPTH_COMPONENT24"; - case 0x81A7: - return "GL_DEPTH_COMPONENT32"; - case 0x8229: - return "GL_R8"; - case 0x822A: - return "GL_R16"; - case 0x822B: - return "GL_RG8"; - case 0x822C: - return "GL_RG16"; - case 0x822D: - return "GL_R16F"; - case 0x822E: - return "GL_R32F"; - case 0x822F: - return "GL_RG16F"; - case 0x8230: - return "GL_RG32F"; - case 0x8231: - return "GL_R8I"; - case 0x8232: - return "GL_R8UI"; - case 0x8233: - return "GL_R16I"; - case 0x8234: - return "GL_R16UI"; - case 0x8235: - return "GL_R32I"; - case 0x8236: - return "GL_R32UI"; - case 0x8237: - return "GL_RG8I"; - case 0x8238: - return "GL_RG8UI"; - case 0x8239: - return "GL_RG16I"; - case 0x823A: - return "GL_RG16UI"; - case 0x823B: - return "GL_RG32I"; - case 0x823C: - return "GL_RG32UI"; - case 0x83F0: - return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; - case 0x83F1: - return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; - case 0x83F2: - return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; - case 0x83F3: - return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; - case 0x8814: - return "GL_RGBA32F"; - case 0x8815: - return "GL_RGB32F"; - case 0x881A: - return "GL_RGBA16F"; - case 0x881B: - return "GL_RGB16F"; - case 0x88F0: - return "GL_DEPTH24_STENCIL8"; - case 0x8C3A: - return "GL_R11F_G11F_B10F"; - case 0x8C3D: - return "GL_RGB9_E5"; - case 0x8C41: - return "GL_SRGB8"; - case 0x8C43: - return "GL_SRGB8_ALPHA8"; - case 0x8CAC: - return "GL_DEPTH_COMPONENT32F"; - case 0x8CAD: - return "GL_DEPTH32F_STENCIL8"; - case 0x8D46: - return "GL_STENCIL_INDEX1"; - case 0x8D47: - return "GL_STENCIL_INDEX4"; - case 0x8D48: - return "GL_STENCIL_INDEX8"; - case 0x8D49: - return "GL_STENCIL_INDEX16"; - case 0x8D62: - return "GL_RGB565"; - case 0x8D70: - return "GL_RGBA32UI"; - case 0x8D71: - return "GL_RGB32UI"; - case 0x8D76: - return "GL_RGBA16UI"; - case 0x8D77: - return "GL_RGB16UI"; - case 0x8D7C: - return "GL_RGBA8UI"; - case 0x8D7D: - return "GL_RGB8UI"; - case 0x8D82: - return "GL_RGBA32I"; - case 0x8D83: - return "GL_RGB32I"; - case 0x8D88: - return "GL_RGBA16I"; - case 0x8D89: - return "GL_RGB16I"; - case 0x8D8E: - return "GL_RGBA8I"; - case 0x8D8F: - return "GL_RGB8I"; - case 0x8DBB: - return "GL_COMPRESSED_RED_RGTC1"; - case 0x8DBC: - return "GL_COMPRESSED_SIGNED_RED_RGTC1"; - case 0x8DBD: - return "GL_COMPRESSED_RG_RGTC2"; - case 0x8DBE: - return "GL_COMPRESSED_SIGNED_RG_RGTC2"; - case 0x8E8C: - return "GL_COMPRESSED_RGBA_BPTC_UNORM"; - case 0x8E8D: - return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"; - case 0x8E8E: - return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT"; - case 0x8E8F: - return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT"; - case 0x8F94: - return "GL_R8_SNORM"; - case 0x8F95: - return "GL_RG8_SNORM"; - case 0x8F96: - return "GL_RGB8_SNORM"; - case 0x8F97: - return "GL_RGBA8_SNORM"; - case 0x8F98: - return "GL_R16_SNORM"; - case 0x8F99: - return "GL_RG16_SNORM"; - case 0x8F9A: - return "GL_RGB16_SNORM"; - case 0x8F9B: - return "GL_RGBA16_SNORM"; - case 0x906F: - return "GL_RGB10_A2UI"; - case 0x9270: - return "GL_COMPRESSED_R11_EAC"; - case 0x9271: - return "GL_COMPRESSED_SIGNED_R11_EAC"; - case 0x9272: - return "GL_COMPRESSED_RG11_EAC"; - case 0x9273: - return "GL_COMPRESSED_SIGNED_RG11_EAC"; - case 0x9274: - return "GL_COMPRESSED_RGB8_ETC2"; - case 0x9275: - return "GL_COMPRESSED_SRGB8_ETC2"; - case 0x9276: - return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"; - case 0x9277: - return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"; - case 0x9278: - return "GL_COMPRESSED_RGBA8_ETC2_EAC"; - case 0x9279: - return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"; - case 0x93B0: - return "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"; - case 0x93B1: - return "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"; - case 0x93B2: - return "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"; - case 0x93B3: - return "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"; - case 0x93B4: - return "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"; - case 0x93B5: - return "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"; - case 0x93B6: - return "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"; - case 0x93B7: - return "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"; - case 0x93B8: - return "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"; - case 0x93B9: - return "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"; - case 0x93BA: - return "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"; - case 0x93BB: - return "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"; - case 0x93BC: - return "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"; - case 0x93BD: - return "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"; - case 0x93D0: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"; - case 0x93D1: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"; - case 0x93D2: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"; - case 0x93D3: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"; - case 0x93D4: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"; - case 0x93D5: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"; - case 0x93D6: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"; - case 0x93D7: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"; - case 0x93D8: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"; - case 0x93D9: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"; - case 0x93DA: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"; - case 0x93DB: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"; - case 0x93DC: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"; - case 0x93DD: - return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::StencilFunction: - { - switch (value) - { - case 0x200: - return "GL_NEVER"; - case 0x201: - return "GL_LESS"; - case 0x202: - return "GL_EQUAL"; - case 0x203: - return "GL_LEQUAL"; - case 0x204: - return "GL_GREATER"; - case 0x205: - return "GL_NOTEQUAL"; - case 0x206: - return "GL_GEQUAL"; - case 0x207: - return "GL_ALWAYS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::StencilOp: - { - switch (value) - { - case 0x0: - return "GL_ZERO"; - case 0x150A: - return "GL_INVERT"; - case 0x1E00: - return "GL_KEEP"; - case 0x1E01: - return "GL_REPLACE"; - case 0x1E02: - return "GL_INCR"; - case 0x1E03: - return "GL_DECR"; - case 0x8507: - return "GL_INCR_WRAP"; - case 0x8508: - return "GL_DECR_WRAP"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::StringName: - { - switch (value) - { - case 0x1F00: - return "GL_VENDOR"; - case 0x1F01: - return "GL_RENDERER"; - case 0x1F02: - return "GL_VERSION"; - case 0x1F03: - return "GL_EXTENSIONS"; - case 0x8B8C: - return "GL_SHADING_LANGUAGE_VERSION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SubroutineParameterName: - { - switch (value) - { - case 0x8A38: - return "GL_UNIFORM_SIZE"; - case 0x8A39: - return "GL_UNIFORM_NAME_LENGTH"; - case 0x8E4A: - return "GL_NUM_COMPATIBLE_SUBROUTINES"; - case 0x8E4B: - return "GL_COMPATIBLE_SUBROUTINES"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SyncBehaviorFlags: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SyncCondition: - { - switch (value) - { - case 0x9117: - return "GL_SYNC_GPU_COMMANDS_COMPLETE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SyncObjectMask: - { - switch (value) - { - case 0x1: - return "GL_SYNC_FLUSH_COMMANDS_BIT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SyncParameterName: - { - switch (value) - { - case 0x9112: - return "GL_OBJECT_TYPE"; - case 0x9113: - return "GL_SYNC_CONDITION"; - case 0x9114: - return "GL_SYNC_STATUS"; - case 0x9115: - return "GL_SYNC_FLAGS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::SyncStatus: - { - switch (value) - { - case 0x911A: - return "GL_ALREADY_SIGNALED"; - case 0x911B: - return "GL_TIMEOUT_EXPIRED"; - case 0x911C: - return "GL_CONDITION_SATISFIED"; - case 0x911D: - return "GL_WAIT_FAILED"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TangentPointerTypeEXT: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TexCoordPointerType: - { - switch (value) - { - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureCompareMode: - { - switch (value) - { - case 0x0: - return "GL_NONE"; - case 0x884E: - return "GL_COMPARE_R_TO_TEXTURE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureCoordName: - { - switch (value) - { - case 0x2000: - return "GL_S"; - case 0x2001: - return "GL_T"; - case 0x2002: - return "GL_R"; - case 0x2003: - return "GL_Q"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureEnvMode: - { - switch (value) - { - case 0x104: - return "GL_ADD"; - case 0xBE2: - return "GL_BLEND"; - case 0x2100: - return "GL_MODULATE"; - case 0x2101: - return "GL_DECAL"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureEnvParameter: - { - switch (value) - { - case 0x2200: - return "GL_TEXTURE_ENV_MODE"; - case 0x2201: - return "GL_TEXTURE_ENV_COLOR"; - case 0x8570: - return "GL_COMBINE"; - case 0x8571: - return "GL_COMBINE_RGB"; - case 0x8572: - return "GL_COMBINE_ALPHA"; - case 0x8573: - return "GL_RGB_SCALE"; - case 0x8574: - return "GL_ADD_SIGNED"; - case 0x8575: - return "GL_INTERPOLATE"; - case 0x8576: - return "GL_CONSTANT"; - case 0x8577: - return "GL_PRIMARY_COLOR"; - case 0x8578: - return "GL_PREVIOUS"; - case 0x8580: - return "GL_SRC0_RGB"; - case 0x8581: - return "GL_SRC1_RGB"; - case 0x8582: - return "GL_SRC2_RGB"; - case 0x8588: - return "GL_SRC0_ALPHA"; - case 0x8589: - return "GL_SRC1_ALPHA"; - case 0x858A: - return "GL_SRC2_ALPHA"; - case 0x8590: - return "GL_OPERAND0_RGB"; - case 0x8591: - return "GL_OPERAND1_RGB"; - case 0x8592: - return "GL_OPERAND2_RGB"; - case 0x8598: - return "GL_OPERAND0_ALPHA"; - case 0x8599: - return "GL_OPERAND1_ALPHA"; - case 0x859A: - return "GL_OPERAND2_ALPHA"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureEnvTarget: - { - switch (value) - { - case 0x2300: - return "GL_TEXTURE_ENV"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureGenMode: - { - switch (value) - { - case 0x2400: - return "GL_EYE_LINEAR"; - case 0x2401: - return "GL_OBJECT_LINEAR"; - case 0x2402: - return "GL_SPHERE_MAP"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureGenParameter: - { - switch (value) - { - case 0x2500: - return "GL_TEXTURE_GEN_MODE"; - case 0x2501: - return "GL_OBJECT_PLANE"; - case 0x2502: - return "GL_EYE_PLANE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureLayout: - { - switch (value) - { - case 0x9530: - return "GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT"; - case 0x9531: - return "GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT"; - case 0x958D: - return "GL_LAYOUT_GENERAL_EXT"; - case 0x958E: - return "GL_LAYOUT_COLOR_ATTACHMENT_EXT"; - case 0x958F: - return "GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT"; - case 0x9590: - return "GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT"; - case 0x9591: - return "GL_LAYOUT_SHADER_READ_ONLY_EXT"; - case 0x9592: - return "GL_LAYOUT_TRANSFER_SRC_EXT"; - case 0x9593: - return "GL_LAYOUT_TRANSFER_DST_EXT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureMagFilter: - { - switch (value) - { - case 0x2600: - return "GL_NEAREST"; - case 0x2601: - return "GL_LINEAR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureMinFilter: - { - switch (value) - { - case 0x2600: - return "GL_NEAREST"; - case 0x2601: - return "GL_LINEAR"; - case 0x2700: - return "GL_NEAREST_MIPMAP_NEAREST"; - case 0x2701: - return "GL_LINEAR_MIPMAP_NEAREST"; - case 0x2702: - return "GL_NEAREST_MIPMAP_LINEAR"; - case 0x2703: - return "GL_LINEAR_MIPMAP_LINEAR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureParameterName: - { - switch (value) - { - case 0x1000: - return "GL_TEXTURE_WIDTH"; - case 0x1001: - return "GL_TEXTURE_HEIGHT"; - case 0x1003: - return "GL_TEXTURE_COMPONENTS"; - case 0x1004: - return "GL_TEXTURE_BORDER_COLOR"; - case 0x1005: - return "GL_TEXTURE_BORDER"; - case 0x2800: - return "GL_TEXTURE_MAG_FILTER"; - case 0x2801: - return "GL_TEXTURE_MIN_FILTER"; - case 0x2802: - return "GL_TEXTURE_WRAP_S"; - case 0x2803: - return "GL_TEXTURE_WRAP_T"; - case 0x805C: - return "GL_TEXTURE_RED_SIZE"; - case 0x805D: - return "GL_TEXTURE_GREEN_SIZE"; - case 0x805E: - return "GL_TEXTURE_BLUE_SIZE"; - case 0x805F: - return "GL_TEXTURE_ALPHA_SIZE"; - case 0x8060: - return "GL_TEXTURE_LUMINANCE_SIZE"; - case 0x8061: - return "GL_TEXTURE_INTENSITY_SIZE"; - case 0x8066: - return "GL_TEXTURE_PRIORITY"; - case 0x8067: - return "GL_TEXTURE_RESIDENT"; - case 0x8072: - return "GL_TEXTURE_WRAP_R"; - case 0x813A: - return "GL_TEXTURE_MIN_LOD"; - case 0x813B: - return "GL_TEXTURE_MAX_LOD"; - case 0x813C: - return "GL_TEXTURE_BASE_LEVEL"; - case 0x813D: - return "GL_TEXTURE_MAX_LEVEL"; - case 0x8191: - return "GL_GENERATE_MIPMAP"; - case 0x84FE: - return "GL_TEXTURE_MAX_ANISOTROPY"; - case 0x8501: - return "GL_TEXTURE_LOD_BIAS"; - case 0x884C: - return "GL_TEXTURE_COMPARE_MODE"; - case 0x884D: - return "GL_TEXTURE_COMPARE_FUNC"; - case 0x8E42: - return "GL_TEXTURE_SWIZZLE_R"; - case 0x8E43: - return "GL_TEXTURE_SWIZZLE_G"; - case 0x8E44: - return "GL_TEXTURE_SWIZZLE_B"; - case 0x8E45: - return "GL_TEXTURE_SWIZZLE_A"; - case 0x8E46: - return "GL_TEXTURE_SWIZZLE_RGBA"; - case 0x90EA: - return "GL_DEPTH_STENCIL_TEXTURE_MODE"; - case 0x9580: - return "GL_TEXTURE_TILING_EXT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureSwizzle: - { - switch (value) - { - case 0x0: - return "GL_ZERO"; - case 0x1: - return "GL_ONE"; - case 0x1903: - return "GL_RED"; - case 0x1904: - return "GL_GREEN"; - case 0x1905: - return "GL_BLUE"; - case 0x1906: - return "GL_ALPHA"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureTarget: - { - switch (value) - { - case 0xDE0: - return "GL_TEXTURE_1D"; - case 0xDE1: - return "GL_TEXTURE_2D"; - case 0x8063: - return "GL_PROXY_TEXTURE_1D"; - case 0x8064: - return "GL_PROXY_TEXTURE_2D"; - case 0x806F: - return "GL_TEXTURE_3D"; - case 0x8070: - return "GL_PROXY_TEXTURE_3D"; - case 0x84F5: - return "GL_TEXTURE_RECTANGLE"; - case 0x84F7: - return "GL_PROXY_TEXTURE_RECTANGLE"; - case 0x8513: - return "GL_TEXTURE_CUBE_MAP"; - case 0x8515: - return "GL_TEXTURE_CUBE_MAP_POSITIVE_X"; - case 0x8516: - return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"; - case 0x8517: - return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y"; - case 0x8518: - return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"; - case 0x8519: - return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z"; - case 0x851A: - return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"; - case 0x851B: - return "GL_PROXY_TEXTURE_CUBE_MAP"; - case 0x8C18: - return "GL_TEXTURE_1D_ARRAY"; - case 0x8C19: - return "GL_PROXY_TEXTURE_1D_ARRAY"; - case 0x8C1A: - return "GL_TEXTURE_2D_ARRAY"; - case 0x8C1B: - return "GL_PROXY_TEXTURE_2D_ARRAY"; - case 0x8C2A: - return "GL_TEXTURE_BUFFER"; - case 0x8D41: - return "GL_RENDERBUFFER"; - case 0x9009: - return "GL_TEXTURE_CUBE_MAP_ARRAY"; - case 0x900B: - return "GL_PROXY_TEXTURE_CUBE_MAP_ARRAY"; - case 0x9100: - return "GL_TEXTURE_2D_MULTISAMPLE"; - case 0x9101: - return "GL_PROXY_TEXTURE_2D_MULTISAMPLE"; - case 0x9102: - return "GL_TEXTURE_2D_MULTISAMPLE_ARRAY"; - case 0x9103: - return "GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureUnit: - { - switch (value) - { - case 0x84C0: - return "GL_TEXTURE0"; - case 0x84C1: - return "GL_TEXTURE1"; - case 0x84C2: - return "GL_TEXTURE2"; - case 0x84C3: - return "GL_TEXTURE3"; - case 0x84C4: - return "GL_TEXTURE4"; - case 0x84C5: - return "GL_TEXTURE5"; - case 0x84C6: - return "GL_TEXTURE6"; - case 0x84C7: - return "GL_TEXTURE7"; - case 0x84C8: - return "GL_TEXTURE8"; - case 0x84C9: - return "GL_TEXTURE9"; - case 0x84CA: - return "GL_TEXTURE10"; - case 0x84CB: - return "GL_TEXTURE11"; - case 0x84CC: - return "GL_TEXTURE12"; - case 0x84CD: - return "GL_TEXTURE13"; - case 0x84CE: - return "GL_TEXTURE14"; - case 0x84CF: - return "GL_TEXTURE15"; - case 0x84D0: - return "GL_TEXTURE16"; - case 0x84D1: - return "GL_TEXTURE17"; - case 0x84D2: - return "GL_TEXTURE18"; - case 0x84D3: - return "GL_TEXTURE19"; - case 0x84D4: - return "GL_TEXTURE20"; - case 0x84D5: - return "GL_TEXTURE21"; - case 0x84D6: - return "GL_TEXTURE22"; - case 0x84D7: - return "GL_TEXTURE23"; - case 0x84D8: - return "GL_TEXTURE24"; - case 0x84D9: - return "GL_TEXTURE25"; - case 0x84DA: - return "GL_TEXTURE26"; - case 0x84DB: - return "GL_TEXTURE27"; - case 0x84DC: - return "GL_TEXTURE28"; - case 0x84DD: - return "GL_TEXTURE29"; - case 0x84DE: - return "GL_TEXTURE30"; - case 0x84DF: - return "GL_TEXTURE31"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TextureWrapMode: - { - switch (value) - { - case 0x2703: - return "GL_LINEAR_MIPMAP_LINEAR"; - case 0x2900: - return "GL_CLAMP"; - case 0x2901: - return "GL_REPEAT"; - case 0x812D: - return "GL_CLAMP_TO_BORDER"; - case 0x812F: - return "GL_CLAMP_TO_EDGE"; - case 0x8370: - return "GL_MIRRORED_REPEAT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TransformFeedbackBufferMode: - { - switch (value) - { - case 0x8C8C: - return "GL_INTERLEAVED_ATTRIBS"; - case 0x8C8D: - return "GL_SEPARATE_ATTRIBS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TransformFeedbackPName: - { - switch (value) - { - case 0x8C84: - return "GL_TRANSFORM_FEEDBACK_BUFFER_START"; - case 0x8C85: - return "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"; - case 0x8C8F: - return "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"; - case 0x8E23: - return "GL_TRANSFORM_FEEDBACK_PAUSED"; - case 0x8E24: - return "GL_TRANSFORM_FEEDBACK_ACTIVE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::TriangleFace: - { - switch (value) - { - case 0x404: - return "GL_FRONT"; - case 0x405: - return "GL_BACK"; - case 0x408: - return "GL_FRONT_AND_BACK"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::UniformBlockPName: - { - switch (value) - { - case 0x84F0: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER"; - case 0x84F1: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER"; - case 0x8A3F: - return "GL_UNIFORM_BLOCK_BINDING"; - case 0x8A40: - return "GL_UNIFORM_BLOCK_DATA_SIZE"; - case 0x8A41: - return "GL_UNIFORM_BLOCK_NAME_LENGTH"; - case 0x8A42: - return "GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"; - case 0x8A43: - return "GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"; - case 0x8A44: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"; - case 0x8A45: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"; - case 0x8A46: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"; - case 0x90EC: - return "GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::UniformPName: - { - switch (value) - { - case 0x8A37: - return "GL_UNIFORM_TYPE"; - case 0x8A38: - return "GL_UNIFORM_SIZE"; - case 0x8A39: - return "GL_UNIFORM_NAME_LENGTH"; - case 0x8A3A: - return "GL_UNIFORM_BLOCK_INDEX"; - case 0x8A3B: - return "GL_UNIFORM_OFFSET"; - case 0x8A3C: - return "GL_UNIFORM_ARRAY_STRIDE"; - case 0x8A3D: - return "GL_UNIFORM_MATRIX_STRIDE"; - case 0x8A3E: - return "GL_UNIFORM_IS_ROW_MAJOR"; - case 0x92DA: - return "GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::UniformType: - { - switch (value) - { - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - case 0x8B50: - return "GL_FLOAT_VEC2"; - case 0x8B51: - return "GL_FLOAT_VEC3"; - case 0x8B52: - return "GL_FLOAT_VEC4"; - case 0x8B53: - return "GL_INT_VEC2"; - case 0x8B54: - return "GL_INT_VEC3"; - case 0x8B55: - return "GL_INT_VEC4"; - case 0x8B56: - return "GL_BOOL"; - case 0x8B57: - return "GL_BOOL_VEC2"; - case 0x8B58: - return "GL_BOOL_VEC3"; - case 0x8B59: - return "GL_BOOL_VEC4"; - case 0x8B5A: - return "GL_FLOAT_MAT2"; - case 0x8B5B: - return "GL_FLOAT_MAT3"; - case 0x8B5C: - return "GL_FLOAT_MAT4"; - case 0x8B5D: - return "GL_SAMPLER_1D"; - case 0x8B5E: - return "GL_SAMPLER_2D"; - case 0x8B5F: - return "GL_SAMPLER_3D"; - case 0x8B60: - return "GL_SAMPLER_CUBE"; - case 0x8B61: - return "GL_SAMPLER_1D_SHADOW"; - case 0x8B62: - return "GL_SAMPLER_2D_SHADOW"; - case 0x8B63: - return "GL_SAMPLER_2D_RECT"; - case 0x8B64: - return "GL_SAMPLER_2D_RECT_SHADOW"; - case 0x8B65: - return "GL_FLOAT_MAT2x3"; - case 0x8B66: - return "GL_FLOAT_MAT2x4"; - case 0x8B67: - return "GL_FLOAT_MAT3x2"; - case 0x8B68: - return "GL_FLOAT_MAT3x4"; - case 0x8B69: - return "GL_FLOAT_MAT4x2"; - case 0x8B6A: - return "GL_FLOAT_MAT4x3"; - case 0x8DC0: - return "GL_SAMPLER_1D_ARRAY"; - case 0x8DC1: - return "GL_SAMPLER_2D_ARRAY"; - case 0x8DC2: - return "GL_SAMPLER_BUFFER"; - case 0x8DC3: - return "GL_SAMPLER_1D_ARRAY_SHADOW"; - case 0x8DC4: - return "GL_SAMPLER_2D_ARRAY_SHADOW"; - case 0x8DC5: - return "GL_SAMPLER_CUBE_SHADOW"; - case 0x8DC6: - return "GL_UNSIGNED_INT_VEC2"; - case 0x8DC7: - return "GL_UNSIGNED_INT_VEC3"; - case 0x8DC8: - return "GL_UNSIGNED_INT_VEC4"; - case 0x8DC9: - return "GL_INT_SAMPLER_1D"; - case 0x8DCA: - return "GL_INT_SAMPLER_2D"; - case 0x8DCB: - return "GL_INT_SAMPLER_3D"; - case 0x8DCC: - return "GL_INT_SAMPLER_CUBE"; - case 0x8DCD: - return "GL_INT_SAMPLER_2D_RECT"; - case 0x8DCE: - return "GL_INT_SAMPLER_1D_ARRAY"; - case 0x8DCF: - return "GL_INT_SAMPLER_2D_ARRAY"; - case 0x8DD0: - return "GL_INT_SAMPLER_BUFFER"; - case 0x8DD1: - return "GL_UNSIGNED_INT_SAMPLER_1D"; - case 0x8DD2: - return "GL_UNSIGNED_INT_SAMPLER_2D"; - case 0x8DD3: - return "GL_UNSIGNED_INT_SAMPLER_3D"; - case 0x8DD4: - return "GL_UNSIGNED_INT_SAMPLER_CUBE"; - case 0x8DD5: - return "GL_UNSIGNED_INT_SAMPLER_2D_RECT"; - case 0x8DD6: - return "GL_UNSIGNED_INT_SAMPLER_1D_ARRAY"; - case 0x8DD7: - return "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY"; - case 0x8DD8: - return "GL_UNSIGNED_INT_SAMPLER_BUFFER"; - case 0x8F46: - return "GL_DOUBLE_MAT2"; - case 0x8F47: - return "GL_DOUBLE_MAT3"; - case 0x8F48: - return "GL_DOUBLE_MAT4"; - case 0x8F49: - return "GL_DOUBLE_MAT2x3"; - case 0x8F4A: - return "GL_DOUBLE_MAT2x4"; - case 0x8F4B: - return "GL_DOUBLE_MAT3x2"; - case 0x8F4C: - return "GL_DOUBLE_MAT3x4"; - case 0x8F4D: - return "GL_DOUBLE_MAT4x2"; - case 0x8F4E: - return "GL_DOUBLE_MAT4x3"; - case 0x8FFC: - return "GL_DOUBLE_VEC2"; - case 0x8FFD: - return "GL_DOUBLE_VEC3"; - case 0x8FFE: - return "GL_DOUBLE_VEC4"; - case 0x900C: - return "GL_SAMPLER_CUBE_MAP_ARRAY"; - case 0x900D: - return "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"; - case 0x900E: - return "GL_INT_SAMPLER_CUBE_MAP_ARRAY"; - case 0x900F: - return "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"; - case 0x9108: - return "GL_SAMPLER_2D_MULTISAMPLE"; - case 0x9109: - return "GL_INT_SAMPLER_2D_MULTISAMPLE"; - case 0x910A: - return "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"; - case 0x910B: - return "GL_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910C: - return "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"; - case 0x910D: - return "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::UseProgramStageMask: - { - switch (value) - { - case 0x1: - return "GL_VERTEX_SHADER_BIT"; - case 0x2: - return "GL_FRAGMENT_SHADER_BIT"; - case 0x4: - return "GL_GEOMETRY_SHADER_BIT"; - case 0x8: - return "GL_TESS_CONTROL_SHADER_BIT"; - case 0x10: - return "GL_TESS_EVALUATION_SHADER_BIT"; - case 0x20: - return "GL_COMPUTE_SHADER_BIT"; - case 0xFFFFFFFF: - return "GL_ALL_SHADER_BITS"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexArrayPName: - { - switch (value) - { - case 0x82D5: - return "GL_VERTEX_ATTRIB_RELATIVE_OFFSET"; - case 0x8622: - return "GL_VERTEX_ATTRIB_ARRAY_ENABLED"; - case 0x8623: - return "GL_VERTEX_ATTRIB_ARRAY_SIZE"; - case 0x8624: - return "GL_VERTEX_ATTRIB_ARRAY_STRIDE"; - case 0x8625: - return "GL_VERTEX_ATTRIB_ARRAY_TYPE"; - case 0x874E: - return "GL_VERTEX_ATTRIB_ARRAY_LONG"; - case 0x886A: - return "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"; - case 0x88FD: - return "GL_VERTEX_ATTRIB_ARRAY_INTEGER"; - case 0x88FE: - return "GL_VERTEX_ATTRIB_ARRAY_DIVISOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribEnum: - { - switch (value) - { - case 0x8622: - return "GL_VERTEX_ATTRIB_ARRAY_ENABLED"; - case 0x8623: - return "GL_VERTEX_ATTRIB_ARRAY_SIZE"; - case 0x8624: - return "GL_VERTEX_ATTRIB_ARRAY_STRIDE"; - case 0x8625: - return "GL_VERTEX_ATTRIB_ARRAY_TYPE"; - case 0x8626: - return "GL_CURRENT_VERTEX_ATTRIB"; - case 0x886A: - return "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"; - case 0x889F: - return "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"; - case 0x88FD: - return "GL_VERTEX_ATTRIB_ARRAY_INTEGER"; - case 0x88FE: - return "GL_VERTEX_ATTRIB_ARRAY_DIVISOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribIType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribLType: - { - switch (value) - { - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribPointerPropertyARB: - { - switch (value) - { - case 0x8645: - return "GL_VERTEX_ATTRIB_ARRAY_POINTER"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribPointerType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - case 0x140B: - return "GL_HALF_FLOAT"; - case 0x140C: - return "GL_FIXED"; - case 0x8368: - return "GL_UNSIGNED_INT_2_10_10_10_REV"; - case 0x8C3B: - return "GL_UNSIGNED_INT_10F_11F_11F_REV"; - case 0x8D9F: - return "GL_INT_2_10_10_10_REV"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribPropertyARB: - { - switch (value) - { - case 0x82D4: - return "GL_VERTEX_ATTRIB_BINDING"; - case 0x82D5: - return "GL_VERTEX_ATTRIB_RELATIVE_OFFSET"; - case 0x8622: - return "GL_VERTEX_ATTRIB_ARRAY_ENABLED"; - case 0x8623: - return "GL_VERTEX_ATTRIB_ARRAY_SIZE"; - case 0x8624: - return "GL_VERTEX_ATTRIB_ARRAY_STRIDE"; - case 0x8625: - return "GL_VERTEX_ATTRIB_ARRAY_TYPE"; - case 0x8626: - return "GL_CURRENT_VERTEX_ATTRIB"; - case 0x874E: - return "GL_VERTEX_ATTRIB_ARRAY_LONG"; - case 0x886A: - return "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"; - case 0x889F: - return "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"; - case 0x88FD: - return "GL_VERTEX_ATTRIB_ARRAY_INTEGER"; - case 0x88FE: - return "GL_VERTEX_ATTRIB_ARRAY_DIVISOR"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexAttribType: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - case 0x140B: - return "GL_HALF_FLOAT"; - case 0x140C: - return "GL_FIXED"; - case 0x8368: - return "GL_UNSIGNED_INT_2_10_10_10_REV"; - case 0x8C3B: - return "GL_UNSIGNED_INT_10F_11F_11F_REV"; - case 0x8D9F: - return "GL_INT_2_10_10_10_REV"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexBufferObjectUsage: - { - switch (value) - { - case 0x88E0: - return "GL_STREAM_DRAW"; - case 0x88E1: - return "GL_STREAM_READ"; - case 0x88E2: - return "GL_STREAM_COPY"; - case 0x88E4: - return "GL_STATIC_DRAW"; - case 0x88E5: - return "GL_STATIC_READ"; - case 0x88E6: - return "GL_STATIC_COPY"; - case 0x88E8: - return "GL_DYNAMIC_DRAW"; - case 0x88E9: - return "GL_DYNAMIC_READ"; - case 0x88EA: - return "GL_DYNAMIC_COPY"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexPointerType: - { - switch (value) - { - case 0x1402: - return "GL_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexProvokingMode: - { - switch (value) - { - case 0x8E4D: - return "GL_FIRST_VERTEX_CONVENTION"; - case 0x8E4E: - return "GL_LAST_VERTEX_CONVENTION"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexShaderTextureUnitParameter: - { - switch (value) - { - case 0xB03: - return "GL_CURRENT_TEXTURE_COORDS"; - case 0xBA8: - return "GL_TEXTURE_MATRIX"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexShaderWriteMaskEXT: - { - switch (value) - { - case 0x0: - return "GL_FALSE"; - case 0x1: - return "GL_TRUE"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::VertexWeightPointerTypeEXT: - { - switch (value) - { - case 0x1406: - return "GL_FLOAT"; - default: - return UnknownEnumToString(value); - } - } - - case BigGLEnum::WeightPointerTypeARB: - { - switch (value) - { - case 0x1400: - return "GL_BYTE"; - case 0x1401: - return "GL_UNSIGNED_BYTE"; - case 0x1402: - return "GL_SHORT"; - case 0x1403: - return "GL_UNSIGNED_SHORT"; - case 0x1404: - return "GL_INT"; - case 0x1405: - return "GL_UNSIGNED_INT"; - case 0x1406: - return "GL_FLOAT"; - case 0x140A: - return "GL_DOUBLE"; - default: - return UnknownEnumToString(value); - } - } - - default: - return UnknownEnumToString(value); - } -} - namespace { using StringEnumEntry = std::pair; @@ -19321,7 +8806,9 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER", 0x90ED}, {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER", 0x92CB}, {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER", 0x92CA}, + {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_EXT", 0x959E}, {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV", 0x959E}, + {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_EXT", 0x959F}, {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV", 0x959F}, {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER", 0x92C8}, {"GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER", 0x92C9}, @@ -19994,6 +9481,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_CONSTANT_COLOR_EXT", 0x8001}, {"GL_CONSTANT_EXT", 0x8576}, {"GL_CONSTANT_NV", 0x8576}, + {"GL_CONST_BW_TILING_MESA", 0x8BBE}, {"GL_CONST_EYE_NV", 0x86E5}, {"GL_CONTEXT_COMPATIBILITY_PROFILE_BIT", 0x0002}, {"GL_CONTEXT_CORE_PROFILE_BIT", 0x0001}, @@ -20875,6 +10363,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT", 0x96D6}, {"GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT", 0x96D3}, {"GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT", 0x8F6F}, + {"GL_FRAGMENT_SHADING_RATE_PRIMITIVE_RATE_WITH_MULTI_VIEWPORT_SUPPORTED_EXT", 0x9780}, {"GL_FRAGMENT_SHADING_RATE_WITH_SAMPLE_MASK_SUPPORTED_EXT", 0x96DE}, {"GL_FRAGMENT_SHADING_RATE_WITH_SHADER_DEPTH_STENCIL_WRITES_SUPPORTED_EXT", 0x96DD}, {"GL_FRAGMENT_SUBROUTINE", 0x92EC}, @@ -21156,6 +10645,8 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_HSL_SATURATION", 0x92AE}, {"GL_HSL_SATURATION_KHR", 0x92AE}, {"GL_HSL_SATURATION_NV", 0x92AE}, + {"GL_HUAWEI_PROGRAM_BINARY", 0x9771}, + {"GL_HUAWEI_SHADER_BINARY", 0x9770}, {"GL_IDENTITY_NV", 0x862A}, {"GL_IGNORE_BORDER_HP", 0x8150}, {"GL_IMAGE_1D", 0x904C}, @@ -21524,9 +11015,9 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_LIST_MODE", 0x0B30}, {"GL_LIST_PRIORITY_SGIX", 0x8182}, {"GL_LOAD", 0x0101}, - {"GL_LOAD_OP_CLEAR_ANGLE", 0x96E5}, - {"GL_LOAD_OP_LOAD_ANGLE", 0x96E6}, - {"GL_LOAD_OP_ZERO_ANGLE", 0x96E4}, + {"GL_LOAD_OP_CLEAR_ANGLE", 0x96E4}, + {"GL_LOAD_OP_LOAD_ANGLE", 0x96E5}, + {"GL_LOAD_OP_ZERO_ANGLE", 0x96E3}, {"GL_LOCAL_CONSTANT_DATATYPE_EXT", 0x87ED}, {"GL_LOCAL_CONSTANT_EXT", 0x87C3}, {"GL_LOCAL_CONSTANT_VALUE_EXT", 0x87EC}, @@ -21792,6 +11283,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_ATTRIB_STACK_DEPTH", 0x0D35}, {"GL_MAX_BINDABLE_UNIFORM_SIZE_EXT", 0x8DED}, {"GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", 0x0D3B}, + {"GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL", 0x9247}, {"GL_MAX_CLIPMAP_DEPTH_SGIX", 0x8177}, {"GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX", 0x8178}, {"GL_MAX_CLIP_DISTANCES", 0x0D32}, @@ -21804,7 +11296,6 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_COLOR_ATTACHMENTS", 0x8CDF}, {"GL_MAX_COLOR_ATTACHMENTS_EXT", 0x8CDF}, {"GL_MAX_COLOR_ATTACHMENTS_NV", 0x8CDF}, - {"GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE", 0x96E1}, {"GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD", 0x91B3}, {"GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD", 0x91B4}, {"GL_MAX_COLOR_MATRIX_STACK_DEPTH", 0x80B3}, @@ -21818,7 +11309,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT", 0x82FA}, {"GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS", 0x8266}, {"GL_MAX_COMBINED_DIMENSIONS", 0x8282}, - {"GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE", 0x96E2}, + {"GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE", 0x96E1}, {"GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", 0x8A33}, {"GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS", 0x8A32}, {"GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT", 0x8A32}, @@ -21826,9 +11317,11 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_COMBINED_IMAGE_UNIFORMS", 0x90CF}, {"GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS", 0x8F39}, {"GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT", 0x8F39}, + {"GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_EXT", 0x8E67}, {"GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV", 0x8E67}, {"GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES", 0x8F39}, {"GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS", 0x90DC}, + {"GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_EXT", 0x8E6F}, {"GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV", 0x8E6F}, {"GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS", 0x8E1E}, {"GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT", 0x8E1E}, @@ -21987,19 +11480,39 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_LIST_NESTING", 0x0B31}, {"GL_MAX_MAP_TESSELLATION_NV", 0x86D6}, {"GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB", 0x8841}, + {"GL_MAX_MESH_ATOMIC_COUNTERS_EXT", 0x8E65}, {"GL_MAX_MESH_ATOMIC_COUNTERS_NV", 0x8E65}, + {"GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_EXT", 0x8E64}, {"GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV", 0x8E64}, + {"GL_MAX_MESH_IMAGE_UNIFORMS_EXT", 0x8E62}, {"GL_MAX_MESH_IMAGE_UNIFORMS_NV", 0x8E62}, + {"GL_MAX_MESH_MULTIVIEW_VIEW_COUNT_EXT", 0x9557}, + {"GL_MAX_MESH_OUTPUT_COMPONENTS_EXT", 0x9749}, + {"GL_MAX_MESH_OUTPUT_LAYERS_EXT", 0x974A}, + {"GL_MAX_MESH_OUTPUT_MEMORY_SIZE_EXT", 0x9747}, + {"GL_MAX_MESH_OUTPUT_PRIMITIVES_EXT", 0x9756}, {"GL_MAX_MESH_OUTPUT_PRIMITIVES_NV", 0x9539}, + {"GL_MAX_MESH_OUTPUT_VERTICES_EXT", 0x9538}, {"GL_MAX_MESH_OUTPUT_VERTICES_NV", 0x9538}, + {"GL_MAX_MESH_PAYLOAD_AND_OUTPUT_MEMORY_SIZE_EXT", 0x9748}, + {"GL_MAX_MESH_PAYLOAD_AND_SHARED_MEMORY_SIZE_EXT", 0x9746}, + {"GL_MAX_MESH_SHADER_STORAGE_BLOCKS_EXT", 0x8E66}, {"GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV", 0x8E66}, + {"GL_MAX_MESH_SHARED_MEMORY_SIZE_EXT", 0x9744}, + {"GL_MAX_MESH_TEXTURE_IMAGE_UNITS_EXT", 0x8E61}, {"GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV", 0x8E61}, {"GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV", 0x9536}, + {"GL_MAX_MESH_UNIFORM_BLOCKS_EXT", 0x8E60}, {"GL_MAX_MESH_UNIFORM_BLOCKS_NV", 0x8E60}, + {"GL_MAX_MESH_UNIFORM_COMPONENTS_EXT", 0x8E63}, {"GL_MAX_MESH_UNIFORM_COMPONENTS_NV", 0x8E63}, {"GL_MAX_MESH_VIEWS_NV", 0x9557}, + {"GL_MAX_MESH_WORK_GROUP_COUNT_EXT", 0x9752}, + {"GL_MAX_MESH_WORK_GROUP_INVOCATIONS_EXT", 0x9757}, {"GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV", 0x95A2}, + {"GL_MAX_MESH_WORK_GROUP_SIZE_EXT", 0x9758}, {"GL_MAX_MESH_WORK_GROUP_SIZE_NV", 0x953B}, + {"GL_MAX_MESH_WORK_GROUP_TOTAL_COUNT_EXT", 0x9741}, {"GL_MAX_MODELVIEW_STACK_DEPTH", 0x0D36}, {"GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV", 0x8E11}, {"GL_MAX_MULTIVIEW_BUFFERS_EXT", 0x90F2}, @@ -22021,6 +11534,8 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_PIXEL_MAP_TABLE", 0x0D34}, {"GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT", 0x8337}, {"GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI", 0x87F1}, + {"GL_MAX_PREFERRED_MESH_WORK_GROUP_INVOCATIONS_EXT", 0x974C}, + {"GL_MAX_PREFERRED_TASK_WORK_GROUP_INVOCATIONS_EXT", 0x974B}, {"GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB", 0x88B1}, {"GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB", 0x880B}, {"GL_MAX_PROGRAM_ATTRIBS_ARB", 0x88AD}, @@ -22108,17 +11623,31 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV", 0x9349}, {"GL_MAX_SUBROUTINES", 0x8DE7}, {"GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 0x8DE8}, + {"GL_MAX_TASK_ATOMIC_COUNTERS_EXT", 0x8E6D}, {"GL_MAX_TASK_ATOMIC_COUNTERS_NV", 0x8E6D}, + {"GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_EXT", 0x8E6C}, {"GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV", 0x8E6C}, + {"GL_MAX_TASK_IMAGE_UNIFORMS_EXT", 0x8E6A}, {"GL_MAX_TASK_IMAGE_UNIFORMS_NV", 0x8E6A}, {"GL_MAX_TASK_OUTPUT_COUNT_NV", 0x953A}, + {"GL_MAX_TASK_PAYLOAD_AND_SHARED_MEMORY_SIZE_EXT", 0x9745}, + {"GL_MAX_TASK_PAYLOAD_SIZE_EXT", 0x9742}, + {"GL_MAX_TASK_SHADER_STORAGE_BLOCKS_EXT", 0x8E6E}, {"GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV", 0x8E6E}, + {"GL_MAX_TASK_SHARED_MEMORY_SIZE_EXT", 0x9743}, + {"GL_MAX_TASK_TEXTURE_IMAGE_UNITS_EXT", 0x8E69}, {"GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV", 0x8E69}, {"GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV", 0x9537}, + {"GL_MAX_TASK_UNIFORM_BLOCKS_EXT", 0x8E68}, {"GL_MAX_TASK_UNIFORM_BLOCKS_NV", 0x8E68}, + {"GL_MAX_TASK_UNIFORM_COMPONENTS_EXT", 0x8E6B}, {"GL_MAX_TASK_UNIFORM_COMPONENTS_NV", 0x8E6B}, + {"GL_MAX_TASK_WORK_GROUP_COUNT_EXT", 0x9751}, + {"GL_MAX_TASK_WORK_GROUP_INVOCATIONS_EXT", 0x9759}, {"GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV", 0x95A3}, + {"GL_MAX_TASK_WORK_GROUP_SIZE_EXT", 0x975A}, {"GL_MAX_TASK_WORK_GROUP_SIZE_NV", 0x953C}, + {"GL_MAX_TASK_WORK_GROUP_TOTAL_COUNT_EXT", 0x9740}, {"GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS", 0x92D3}, {"GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT", 0x92D3}, {"GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES", 0x92D3}, @@ -22264,15 +11793,31 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_MEMORY_ATTACHABLE_NV", 0x95A8}, {"GL_MEMORY_ATTACHABLE_SIZE_NV", 0x95A7}, {"GL_MEMORY_SIZE_ANGLE", 0x93AD}, + {"GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_EXT", 0x9543}, {"GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV", 0x9543}, + {"GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_EXT", 0x92DF}, {"GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV", 0x92DF}, + {"GL_MESH_OUTPUT_TYPE_EXT", 0x957B}, {"GL_MESH_OUTPUT_TYPE_NV", 0x957B}, + {"GL_MESH_PREFERS_COMPACT_PRIMITIVE_OUTPUT_EXT", 0x9750}, + {"GL_MESH_PREFERS_COMPACT_VERTEX_OUTPUT_EXT", 0x974F}, + {"GL_MESH_PREFERS_LOCAL_INVOCATION_PRIMITIVE_OUTPUT_EXT", 0x974E}, + {"GL_MESH_PREFERS_LOCAL_INVOCATION_VERTEX_OUTPUT_EXT", 0x974D}, + {"GL_MESH_PRIMITIVES_GENERATED_EXT", 0x9755}, + {"GL_MESH_PRIMITIVES_OUT_EXT", 0x957A}, {"GL_MESH_PRIMITIVES_OUT_NV", 0x957A}, + {"GL_MESH_SHADER_BIT_EXT", 0x0040}, {"GL_MESH_SHADER_BIT_NV", 0x0040}, + {"GL_MESH_SHADER_EXT", 0x9559}, + {"GL_MESH_SHADER_INVOCATIONS_EXT", 0x9754}, {"GL_MESH_SHADER_NV", 0x9559}, + {"GL_MESH_SUBROUTINE_EXT", 0x957C}, {"GL_MESH_SUBROUTINE_NV", 0x957C}, + {"GL_MESH_SUBROUTINE_UNIFORM_EXT", 0x957E}, {"GL_MESH_SUBROUTINE_UNIFORM_NV", 0x957E}, + {"GL_MESH_VERTICES_OUT_EXT", 0x9579}, {"GL_MESH_VERTICES_OUT_NV", 0x9579}, + {"GL_MESH_WORK_GROUP_SIZE_EXT", 0x953E}, {"GL_MESH_WORK_GROUP_SIZE_NV", 0x953E}, {"GL_MIN", 0x8007}, {"GL_MINMAX", 0x802E}, @@ -22664,10 +12209,13 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_PACK_REVERSE_ROW_ORDER_ANGLE", 0x93A4}, {"GL_PACK_ROW_BYTES_APPLE", 0x8A15}, {"GL_PACK_ROW_LENGTH", 0x0D02}, + {"GL_PACK_ROW_LENGTH_NV", 0x0D02}, {"GL_PACK_SKIP_IMAGES", 0x806B}, {"GL_PACK_SKIP_IMAGES_EXT", 0x806B}, {"GL_PACK_SKIP_PIXELS", 0x0D04}, + {"GL_PACK_SKIP_PIXELS_NV", 0x0D04}, {"GL_PACK_SKIP_ROWS", 0x0D03}, + {"GL_PACK_SKIP_ROWS_NV", 0x0D03}, {"GL_PACK_SKIP_VOLUMES_SGIS", 0x8130}, {"GL_PACK_SUBSAMPLE_RATE_SGIX", 0x85A0}, {"GL_PACK_SWAP_BYTES", 0x0D00}, @@ -22792,14 +12340,14 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS", 0x8355}, {"GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS", 0x8354}, {"GL_PIXEL_GROUP_COLOR_SGIS", 0x8356}, - {"GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE", 0x96EC}, - {"GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE", 0x96ED}, - {"GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE", 0x96EE}, - {"GL_PIXEL_LOCAL_FORMAT_ANGLE", 0x96E8}, - {"GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE", 0x96E3}, - {"GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE", 0x96EB}, - {"GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE", 0x96EA}, - {"GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE", 0x96E9}, + {"GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE", 0x96EB}, + {"GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE", 0x96EC}, + {"GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE", 0x96ED}, + {"GL_PIXEL_LOCAL_FORMAT_ANGLE", 0x96E7}, + {"GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE", 0x96E2}, + {"GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE", 0x96EA}, + {"GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE", 0x96E9}, + {"GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE", 0x96E8}, {"GL_PIXEL_MAG_FILTER_EXT", 0x8331}, {"GL_PIXEL_MAP_A_TO_A", 0x0C79}, {"GL_PIXEL_MAP_A_TO_A_SIZE", 0x0CB9}, @@ -23111,6 +12659,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_PROXY_TEXTURE_RECTANGLE_NV", 0x84F7}, {"GL_PURGEABLE_APPLE", 0x8A1D}, {"GL_PURGED_CONTEXT_RESET_NV", 0x92BB}, + {"GL_PVRIC_SIGNATURE_MISMATCH_IMG", 0x8EA3}, {"GL_Q", 0x2003}, {"GL_QUADRATIC_ATTENUATION", 0x1209}, {"GL_QUADRATIC_CURVE_TO_NV", 0x000A}, @@ -23255,7 +12804,9 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_REFERENCED_BY_GEOMETRY_SHADER", 0x9309}, {"GL_REFERENCED_BY_GEOMETRY_SHADER_EXT", 0x9309}, {"GL_REFERENCED_BY_GEOMETRY_SHADER_OES", 0x9309}, + {"GL_REFERENCED_BY_MESH_SHADER_EXT", 0x95A0}, {"GL_REFERENCED_BY_MESH_SHADER_NV", 0x95A0}, + {"GL_REFERENCED_BY_TASK_SHADER_EXT", 0x95A1}, {"GL_REFERENCED_BY_TASK_SHADER_NV", 0x95A1}, {"GL_REFERENCED_BY_TESS_CONTROL_SHADER", 0x9307}, {"GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT", 0x9307}, @@ -23605,6 +13156,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_SAMPLER_KHR", 0x82E6}, {"GL_SAMPLER_OBJECT_AMD", 0x9155}, {"GL_SAMPLER_RENDERBUFFER_NV", 0x8E56}, + {"GL_SAMPLER_VIDEO_IMAGE_WEBGL", 0x9249}, {"GL_SAMPLES", 0x80A9}, {"GL_SAMPLES_3DFX", 0x86B4}, {"GL_SAMPLES_ARB", 0x80A9}, @@ -23722,6 +13274,13 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_SHADER_BINARY_VIV", 0x8FC4}, {"GL_SHADER_COMPILER", 0x8DFA}, {"GL_SHADER_CONSISTENT_NV", 0x86DD}, + {"GL_SHADER_CORE_ACTIVE_COUNT_ARM", 0x96F1}, + {"GL_SHADER_CORE_COUNT_ARM", 0x96F0}, + {"GL_SHADER_CORE_FMA_RATE_ARM", 0x96F6}, + {"GL_SHADER_CORE_MAX_WARP_COUNT_ARM", 0x96F3}, + {"GL_SHADER_CORE_PIXEL_RATE_ARM", 0x96F4}, + {"GL_SHADER_CORE_PRESENT_MASK_ARM", 0x96F2}, + {"GL_SHADER_CORE_TEXEL_RATE_ARM", 0x96F5}, {"GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV", 0x0010}, {"GL_SHADER_IMAGE_ACCESS_BARRIER_BIT", 0x0020}, {"GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT", 0x0020}, @@ -24015,7 +13574,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_STORAGE_CLIENT_APPLE", 0x85B4}, {"GL_STORAGE_PRIVATE_APPLE", 0x85BD}, {"GL_STORAGE_SHARED_APPLE", 0x85BF}, - {"GL_STORE_OP_STORE_ANGLE", 0x96E7}, + {"GL_STORE_OP_STORE_ANGLE", 0x96E6}, {"GL_STREAM_COPY", 0x88E2}, {"GL_STREAM_COPY_ARB", 0x88E2}, {"GL_STREAM_DRAW", 0x88E0}, @@ -24109,10 +13668,16 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_TANGENT_ARRAY_POINTER_EXT", 0x8442}, {"GL_TANGENT_ARRAY_STRIDE_EXT", 0x843F}, {"GL_TANGENT_ARRAY_TYPE_EXT", 0x843E}, + {"GL_TASK_SHADER_BIT_EXT", 0x0080}, {"GL_TASK_SHADER_BIT_NV", 0x0080}, + {"GL_TASK_SHADER_EXT", 0x955A}, + {"GL_TASK_SHADER_INVOCATIONS_EXT", 0x9753}, {"GL_TASK_SHADER_NV", 0x955A}, + {"GL_TASK_SUBROUTINE_EXT", 0x957D}, {"GL_TASK_SUBROUTINE_NV", 0x957D}, + {"GL_TASK_SUBROUTINE_UNIFORM_EXT", 0x957F}, {"GL_TASK_SUBROUTINE_UNIFORM_NV", 0x957F}, + {"GL_TASK_WORK_GROUP_SIZE_EXT", 0x953F}, {"GL_TASK_WORK_GROUP_SIZE_NV", 0x953F}, {"GL_TERMINATE_SEQUENCE_COMMAND_NV", 0x0000}, {"GL_TESSELLATION_FACTOR_AMD", 0x9005}, @@ -24322,6 +13887,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_TEXTURE_BUFFER_SIZE", 0x919E}, {"GL_TEXTURE_BUFFER_SIZE_EXT", 0x919E}, {"GL_TEXTURE_BUFFER_SIZE_OES", 0x919E}, + {"GL_TEXTURE_CBCR_DEGAMMA_QCOM", 0x9711}, {"GL_TEXTURE_CLIPMAP_CENTER_SGIX", 0x8171}, {"GL_TEXTURE_CLIPMAP_DEPTH_SGIX", 0x8176}, {"GL_TEXTURE_CLIPMAP_FRAME_SGIX", 0x8172}, @@ -24472,6 +14038,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_TEXTURE_LIGHT_EXT", 0x8350}, {"GL_TEXTURE_LOD_BIAS", 0x8501}, {"GL_TEXTURE_LOD_BIAS_EXT", 0x8501}, + {"GL_TEXTURE_LOD_BIAS_QCOM", 0x8C96}, {"GL_TEXTURE_LOD_BIAS_R_SGIX", 0x8190}, {"GL_TEXTURE_LOD_BIAS_S_SGIX", 0x818E}, {"GL_TEXTURE_LOD_BIAS_T_SGIX", 0x818F}, @@ -24559,6 +14126,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_TEXTURE_UPDATE_BARRIER_BIT", 0x0100}, {"GL_TEXTURE_UPDATE_BARRIER_BIT_EXT", 0x0100}, {"GL_TEXTURE_USAGE_ANGLE", 0x93A2}, + {"GL_TEXTURE_VIDEO_IMAGE_WEBGL", 0x9248}, {"GL_TEXTURE_VIEW", 0x82B5}, {"GL_TEXTURE_VIEW_MIN_LAYER", 0x82DD}, {"GL_TEXTURE_VIEW_MIN_LAYER_EXT", 0x82DD}, @@ -24580,6 +14148,7 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_TEXTURE_WRAP_R_OES", 0x8072}, {"GL_TEXTURE_WRAP_S", 0x2802}, {"GL_TEXTURE_WRAP_T", 0x2803}, + {"GL_TEXTURE_Y_DEGAMMA_QCOM", 0x9710}, {"GL_TEXT_FRAGMENT_SHADER_ATI", 0x8200}, {"GL_TILE_RASTER_ORDER_FIXED_MESA", 0x8BB8}, {"GL_TILE_RASTER_ORDER_INCREASING_X_MESA", 0x8BB9}, @@ -24711,7 +14280,9 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER", 0x90EC}, {"GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER", 0x8A46}, {"GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER", 0x8A45}, + {"GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_EXT", 0x959C}, {"GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV", 0x959C}, + {"GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_EXT", 0x959D}, {"GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV", 0x959D}, {"GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER", 0x84F0}, {"GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER", 0x84F1}, @@ -24736,6 +14307,8 @@ static StringEnumEntry g_stringEnumTable[] = { {"GL_UNKNOWN_CONTEXT_RESET_ARB", 0x8255}, {"GL_UNKNOWN_CONTEXT_RESET_EXT", 0x8255}, {"GL_UNKNOWN_CONTEXT_RESET_KHR", 0x8255}, + {"GL_UNMASKED_RENDERER_WEBGL", 0x9246}, + {"GL_UNMASKED_VENDOR_WEBGL", 0x9245}, {"GL_UNPACK_ALIGNMENT", 0x0CF5}, {"GL_UNPACK_CLIENT_STORAGE_APPLE", 0x85B2}, {"GL_UNPACK_CMYK_HINT_EXT", 0x800F}, diff --git a/src/common/gl_enum_utils_autogen.h b/src/common/gl_enum_utils_autogen.h index aa1a6561529..4df13034f8f 100644 --- a/src/common/gl_enum_utils_autogen.h +++ b/src/common/gl_enum_utils_autogen.h @@ -153,6 +153,8 @@ enum class GLESEnum ShaderParameterName, ShaderType, ShadingModel, + ShadingRate, + ShadingRateCombinerOp, ShadingRateQCOM, SizedInternalFormat, StencilFunction, @@ -195,225 +197,6 @@ enum class GLESEnum VertexAttribPointerType, VertexAttribPropertyARB, VertexAttribType, - VertexBufferObjectUsage, - VertexPointerType, - VertexProvokingMode, - VertexShaderTextureUnitParameter, - VertexShaderWriteMaskEXT, - VertexWeightPointerTypeEXT, - WeightPointerTypeARB -}; - -enum class BigGLEnum -{ - AccumOp, - AllEnums, - AlphaFunction, - AtomicCounterBufferPName, - AttribMask, - AttributeType, - BindTransformFeedbackTarget, - BinormalPointerTypeEXT, - BlendEquationModeEXT, - BlendingFactor, - BlitFramebufferFilter, - Boolean, - Buffer, - BufferAccessARB, - BufferPNameARB, - BufferPointerNameARB, - BufferStorageMask, - BufferStorageTarget, - BufferTargetARB, - BufferUsageARB, - ClampColorModeARB, - ClampColorTargetARB, - ClearBufferMask, - ClientAttribMask, - ClipControlDepth, - ClipControlOrigin, - ClipPlaneName, - ColorBuffer, - ColorMaterialParameter, - ColorPointerType, - ColorTableTarget, - ColorTableTargetSGI, - CombinerBiasNV, - CombinerComponentUsageNV, - CombinerPortionNV, - CombinerScaleNV, - ConditionalRenderMode, - ContainerType, - ContextFlagMask, - ContextProfileMask, - ConvolutionTarget, - ConvolutionTargetEXT, - CopyBufferSubDataTarget, - CopyImageSubDataTarget, - DebugSeverity, - DebugSource, - DebugType, - DepthFunction, - DepthStencilTextureMode, - DrawBufferMode, - DrawElementsType, - ElementPointerTypeATI, - EnableCap, - ErrorCode, - ExternalHandleType, - FeedBackToken, - FeedbackType, - FenceConditionNV, - FenceParameterNameNV, - FogCoordSrc, - FogCoordinatePointerType, - FogMode, - FogPName, - FogParameter, - FogPointerTypeEXT, - FogPointerTypeIBM, - FragmentLightParameterSGIX, - FragmentShaderDestMaskATI, - FragmentShaderDestModMaskATI, - FragmentShaderGenericSourceATI, - FragmentShaderTextureSourceATI, - FragmentShaderValueRepATI, - FramebufferAttachment, - FramebufferAttachmentParameterName, - FramebufferParameterName, - FramebufferStatus, - FramebufferTarget, - FrontFaceDirection, - GetFramebufferParameter, - GetMapQuery, - GetMultisamplePNameNV, - GetPName, - GetPointervPName, - GetTextureParameter, - GraphicsResetStatus, - HintMode, - HintTarget, - HistogramTarget, - HistogramTargetEXT, - IndexFunctionEXT, - IndexMaterialParameterEXT, - IndexPointerType, - InterleavedArrayFormat, - InternalFormat, - InternalFormatPName, - InvalidateFramebufferAttachment, - LightEnvModeSGIX, - LightModelColorControl, - LightModelParameter, - LightName, - LightParameter, - LightTextureModeEXT, - ListMode, - ListNameType, - LogicOp, - MapBufferAccessMask, - MapQuery, - MapTarget, - MapTypeNV, - MaterialParameter, - MatrixIndexPointerTypeARB, - MatrixMode, - MemoryBarrierMask, - MemoryObjectParameterName, - MeshMode1, - MeshMode2, - MinmaxTarget, - MinmaxTargetEXT, - NormalPointerType, - ObjectIdentifier, - PatchParameterName, - PathColor, - PathColorFormat, - PathFillMode, - PathFontStyle, - PathGenMode, - PathTransformType, - PipelineParameterName, - PixelCopyType, - PixelFormat, - PixelMap, - PixelStoreParameter, - PixelTexGenModeSGIX, - PixelTransferParameter, - PixelType, - PointParameterNameARB, - PolygonMode, - PrecisionType, - PrimitiveType, - ProgramInterface, - ProgramInterfacePName, - ProgramParameterPName, - ProgramPropertyARB, - ProgramResourceProperty, - ProgramStagePName, - QueryCounterTarget, - QueryObjectParameterName, - QueryParameterName, - QueryTarget, - ReadBufferMode, - RenderbufferParameterName, - RenderbufferTarget, - RenderingMode, - ReplacementCodeTypeSUN, - SamplerParameterF, - SamplerParameterI, - ScalarType, - SecondaryColorPointerTypeIBM, - SemaphoreParameterName, - SeparableTarget, - SeparableTargetEXT, - ShaderBinaryFormat, - ShaderParameterName, - ShaderType, - ShadingModel, - SizedInternalFormat, - StencilFunction, - StencilOp, - StringName, - SubroutineParameterName, - SyncBehaviorFlags, - SyncCondition, - SyncObjectMask, - SyncParameterName, - SyncStatus, - TangentPointerTypeEXT, - TexCoordPointerType, - TextureCompareMode, - TextureCoordName, - TextureEnvMode, - TextureEnvParameter, - TextureEnvTarget, - TextureGenMode, - TextureGenParameter, - TextureLayout, - TextureMagFilter, - TextureMinFilter, - TextureParameterName, - TextureSwizzle, - TextureTarget, - TextureUnit, - TextureWrapMode, - TransformFeedbackBufferMode, - TransformFeedbackPName, - TriangleFace, - UniformBlockPName, - UniformPName, - UniformType, - UseProgramStageMask, - VertexArrayPName, - VertexAttribEnum, - VertexAttribIType, - VertexAttribLType, - VertexAttribPointerPropertyARB, - VertexAttribPointerType, - VertexAttribPropertyARB, - VertexAttribType, - VertexBufferObjectUsage, VertexPointerType, VertexProvokingMode, VertexShaderTextureUnitParameter, diff --git a/src/common/hash_utils.h b/src/common/hash_utils.h index 766236540f9..f97b7fcd6b5 100644 --- a/src/common/hash_utils.h +++ b/src/common/hash_utils.h @@ -9,32 +9,26 @@ #define COMMON_HASHUTILS_H_ #include "common/debug.h" +#include "common/span.h" #include "xxhash.h" namespace angle { // Computes a hash of "key". Any data passed to this function must be multiples of // 4 bytes, since the PMurHash32 method can only operate increments of 4-byte words. -inline size_t ComputeGenericHash(const void *key, size_t keySize) +inline size_t ComputeGenericHash(angle::Span key) { constexpr unsigned int kSeed = 0xABCDEF98; // We can't support "odd" alignments. ComputeGenericHash requires aligned types - ASSERT(keySize % 4 == 0); + ASSERT(key.size() % 4 == 0); #if defined(ANGLE_IS_64_BIT_CPU) - return XXH64(key, keySize, kSeed); + return XXH64(key.data(), key.size(), kSeed); #else - return XXH32(key, keySize, kSeed); + return XXH32(key.data(), key.size(), kSeed); #endif // defined(ANGLE_IS_64_BIT_CPU) } -template -size_t ComputeGenericHash(const T &key) -{ - static_assert(sizeof(key) % 4 == 0, "ComputeGenericHash requires aligned types"); - return ComputeGenericHash(&key, sizeof(key)); -} - inline void HashCombine(size_t &seed) {} template diff --git a/src/common/hash_utils_unittest.cpp b/src/common/hash_utils_unittest.cpp index 490d2d472ea..06b5198cddc 100644 --- a/src/common/hash_utils_unittest.cpp +++ b/src/common/hash_utils_unittest.cpp @@ -8,6 +8,7 @@ #include #include "common/hash_utils.h" +#include "common/span.h" using namespace angle; @@ -23,8 +24,8 @@ TEST(HashUtilsTest, ComputeGenericHash) ASSERT_TRUE(a.size() % 4 == 0); ASSERT_TRUE(b.size() % 4 == 0); - size_t aHash = ComputeGenericHash(a.c_str(), a.size()); - size_t bHash = ComputeGenericHash(b.c_str(), b.size()); + size_t aHash = ComputeGenericHash(angle::as_byte_span(a)); + size_t bHash = ComputeGenericHash(angle::as_byte_span(b)); EXPECT_NE(aHash, bHash); } diff --git a/src/common/linux/dma_buf_utils.cpp b/src/common/linux/dma_buf_utils.cpp index a22232b1150..d9ea5fd94db 100644 --- a/src/common/linux/dma_buf_utils.cpp +++ b/src/common/linux/dma_buf_utils.cpp @@ -59,6 +59,32 @@ GLenum DrmFourCCFormatToGLInternalFormat(int fourccFormat, bool *isYUV) } } +uint32_t GLInternalFormatToDrmFourCCFormat(GLenum internalFormat) +{ + switch (internalFormat) + { + case GL_R8: + return DRM_FORMAT_R8; + case GL_RGB8: + return DRM_FORMAT_GR88; + case GL_RGB565: + return DRM_FORMAT_RGB565; + case GL_RGBA8: + return DRM_FORMAT_ABGR8888; + case GL_BGRA8_EXT: + return DRM_FORMAT_ARGB8888; + case GL_BGRX8_ANGLEX: + return DRM_FORMAT_XRGB8888; + case GL_RGBX8_ANGLE: + return DRM_FORMAT_XBGR8888; + case GL_RGB10_A2: + return DRM_FORMAT_ABGR2101010; + default: + WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0"; + return 0; + } +} + #if defined(ANGLE_ENABLE_VULKAN) std::vector VkFormatToDrmFourCCFormat(VkFormat format) { @@ -132,34 +158,4 @@ std::vector DrmFourCCFormatToVkFormats(int fourccFormat) #endif // ANGLE_ENABLE_VULKAN -#if defined(ANGLE_PLATFORM_LINUX) && defined(ANGLE_USES_GBM) -# include - -int GLInternalFormatToGbmFourCCFormat(GLenum internalFormat) -{ - switch (internalFormat) - { - case GL_R8: - return GBM_FORMAT_R8; - case GL_RGB8: - return GBM_FORMAT_GR88; - case GL_RGB565: - return GBM_FORMAT_RGB565; - case GL_RGBA8: - return GBM_FORMAT_ABGR8888; - case GL_BGRA8_EXT: - return GBM_FORMAT_ARGB8888; - case GL_BGRX8_ANGLEX: - return GBM_FORMAT_XRGB8888; - case GL_RGBX8_ANGLE: - return GBM_FORMAT_XBGR8888; - case GL_RGB10_A2: - return GBM_FORMAT_ABGR2101010; - default: - WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0"; - return 0; - } -} -#endif - } // namespace angle diff --git a/src/common/linux/dma_buf_utils.h b/src/common/linux/dma_buf_utils.h index adf26ebdff5..f2c4f2b852b 100644 --- a/src/common/linux/dma_buf_utils.h +++ b/src/common/linux/dma_buf_utils.h @@ -43,10 +43,7 @@ namespace angle { GLenum DrmFourCCFormatToGLInternalFormat(int format, bool *isYUV); - -#if defined(ANGLE_PLATFORM_LINUX) && defined(ANGLE_USES_GBM) -int GLInternalFormatToGbmFourCCFormat(GLenum internalFormat); -#endif +uint32_t GLInternalFormatToDrmFourCCFormat(GLenum internalFormat); #if defined(ANGLE_ENABLE_VULKAN) std::vector VkFormatToDrmFourCCFormat(VkFormat format); diff --git a/src/common/mathutil.cpp b/src/common/mathutil.cpp index 630348923b7..40a9aa0b59b 100644 --- a/src/common/mathutil.cpp +++ b/src/common/mathutil.cpp @@ -80,4 +80,17 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue = inputData->B * pow2_exp; } +std::ostream &operator<<(std::ostream &s, const IndexRange &a) +{ + if (a.isEmpty()) + { + s << "[]"; + } + else + { + s << "[" << a.start() << ", " << a.end() << "]"; + } + return s; +} + } // namespace gl diff --git a/src/common/mathutil.h b/src/common/mathutil.h index 45c00d8991d..0a67c2ca243 100644 --- a/src/common/mathutil.h +++ b/src/common/mathutil.h @@ -9,12 +9,17 @@ #ifndef COMMON_MATHUTIL_H_ #define COMMON_MATHUTIL_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include #include #include #include +#include #include @@ -41,7 +46,7 @@ inline constexpr bool isPow2(T x) } template -inline int log2(T x) +inline constexpr int log2(T x) { static_assert(std::is_integral::value, "log2 must be called on an integer type."); int r = 0; @@ -860,29 +865,45 @@ typedef Range RangeUI; static_assert(std::is_trivially_copyable(), "RangeUI should be trivial copyable so that we can memcpy"); +// Inclusive vertex index range [start(), end()]. struct IndexRange { struct Undefined {}; IndexRange(Undefined) {} - IndexRange() : IndexRange(0, 0, 0) {} - IndexRange(size_t start_, size_t end_, size_t vertexIndexCount_) - : start(start_), end(end_), vertexIndexCount(vertexIndexCount_) + IndexRange() = default; + IndexRange(uint32_t start_, uint32_t end_) : mStart(start_), mCount(end_ - start_ + 1) + { + ASSERT(start_ <= end_); + } + bool isEmpty() const { return mCount == 0; } + uint32_t start() const + { + ASSERT(!isEmpty()); + return mStart; + } + uint32_t end() const { - ASSERT(start <= end); + ASSERT(!isEmpty()); + return mStart + mCount - 1; } // Number of vertices in the range. - size_t vertexCount() const { return (end - start) + 1; } - - // Inclusive range of indices that are not primitive restart - size_t start; - size_t end; + uint32_t vertexCount() const { return mCount; } - // Number of non-primitive restart indices - size_t vertexIndexCount; + private: + uint32_t mStart{0}; + uint32_t mCount{0}; }; +inline bool operator==(const IndexRange &a, const IndexRange &b) +{ + return a.vertexCount() == b.vertexCount() && + ((a.vertexCount() == 0) || (a.start() == b.start())); +} + +std::ostream &operator<<(std::ostream &s, const IndexRange &a); + // Combine a floating-point value representing a mantissa (x) and an integer exponent (exp) into a // floating-point value. As in GLSL ldexp() built-in. inline float Ldexp(float x, int exp) @@ -1484,7 +1505,7 @@ template constexpr T roundUpPow2(const T value, const T alignment) { ASSERT(gl::isPow2(alignment)); - return (value + alignment - 1) & ~(alignment - 1); + return (value + (alignment - 1)) & ~(alignment - 1); } template @@ -1494,6 +1515,15 @@ constexpr T roundDownPow2(const T value, const T alignment) return value & ~(alignment - 1); } +template +angle::CheckedNumeric CheckedRoundUpPow2(const T value, const T alignment) +{ + ASSERT(gl::isPow2(alignment)); + angle::CheckedNumeric checkedValue(value); + angle::CheckedNumeric checkedAlignment(alignment); + return (checkedValue + checkedAlignment - 1) & ~(checkedAlignment - 1); +} + template angle::CheckedNumeric CheckedRoundUp(const T value, const T alignment) { diff --git a/src/common/mathutil_unittest.cpp b/src/common/mathutil_unittest.cpp index 33acdca6ec3..a66d881e15e 100644 --- a/src/common/mathutil_unittest.cpp +++ b/src/common/mathutil_unittest.cpp @@ -7,6 +7,10 @@ // Unit tests for the utils defined in mathutil.h // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "mathutil.h" #include @@ -249,6 +253,34 @@ TEST(MathUtilTest, CheckedRoundUpInvalid) ASSERT_FALSE(checkedLimit.IsValid()); } +// Test basic correctness of rx::CheckedRoundUpPow2 +TEST(MathUtilTest, CheckedRoundUpPow2) +{ + auto checkedValue = rx::CheckedRoundUpPow2(1u, 4u); + ASSERT_TRUE(checkedValue.IsValid()); + EXPECT_EQ(4u, checkedValue.ValueOrDie()); + + checkedValue = rx::CheckedRoundUpPow2(4u, 4u); + ASSERT_TRUE(checkedValue.IsValid()); + EXPECT_EQ(4u, checkedValue.ValueOrDie()); +} + +// Test that rounding up zero produces zero for rx::CheckedRoundUpPow2. +TEST(MathUtilTest, CheckedRoundUpPow2Zero) +{ + auto checkedValue = rx::CheckedRoundUpPow2(0u, 4u); + ASSERT_TRUE(checkedValue.IsValid()); + EXPECT_EQ(0u, checkedValue.ValueOrDie()); +} + +// Test out-of-bounds with rx::CheckedRoundUpPow2 +TEST(MathUtilTest, CheckedRoundUpPow2Invalid) +{ + auto limit = std::numeric_limits::max(); + auto checkedValue = rx::CheckedRoundUpPow2(limit, 4u); + ASSERT_FALSE(checkedValue.IsValid()); +} + // Test BitfieldReverse which reverses the order of the bits in an integer. TEST(MathUtilTest, BitfieldReverse) { diff --git a/src/common/matrix_utils.cpp b/src/common/matrix_utils.cpp index 3283be21f86..b8ab642aa85 100644 --- a/src/common/matrix_utils.cpp +++ b/src/common/matrix_utils.cpp @@ -6,6 +6,10 @@ // matrix_utils.cpp: Contains implementations for Mat4 methods. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/matrix_utils.h" namespace angle diff --git a/src/common/matrix_utils.h b/src/common/matrix_utils.h index 6f91b90f14f..6de3c83c37c 100644 --- a/src/common/matrix_utils.h +++ b/src/common/matrix_utils.h @@ -2,7 +2,7 @@ // 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. -// + // Matrix: // Utility class implementing various matrix operations. // Supports matrices with minimum 2 and maximum 4 number of rows/columns. @@ -14,11 +14,17 @@ #ifndef COMMON_MATRIX_UTILS_H_ #define COMMON_MATRIX_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include +#include #include #include "common/debug.h" #include "common/mathutil.h" +#include "common/span.h" #include "common/vector_utils.h" namespace @@ -84,26 +90,28 @@ template class Matrix { public: - Matrix(const std::vector &elements, const unsigned int numRows, const unsigned int numCols) - : mElements(elements), mRows(numRows), mCols(numCols) + Matrix(std::vector &&elements, const unsigned int numRows, const unsigned int numCols) + : mElements(std::move(elements)), mRows(numRows), mCols(numCols) { ASSERT(rows() >= 1 && rows() <= 4); ASSERT(columns() >= 1 && columns() <= 4); + ASSERT(mElements.size() >= rows() * columns()); } - Matrix(const std::vector &elements, const unsigned int size) - : mElements(elements), mRows(size), mCols(size) + Matrix(std::vector &&elements, const unsigned int size) + : mElements(std::move(elements)), mRows(size), mCols(size) { ASSERT(rows() >= 1 && rows() <= 4); ASSERT(columns() >= 1 && columns() <= 4); + ASSERT(mElements.size() >= rows() * columns()); } - Matrix(const T *elements, const unsigned int size) : mRows(size), mCols(size) + Matrix(angle::Span elements, const unsigned int size) + : mElements(elements.begin(), elements.end()), mRows(size), mCols(size) { ASSERT(rows() >= 1 && rows() <= 4); ASSERT(columns() >= 1 && columns() <= 4); - for (size_t i = 0; i < size * size; i++) - mElements.push_back(elements[i]); + ASSERT(mElements.size() >= rows() * columns()); } const T &operator()(const unsigned int rowIndex, const unsigned int columnIndex) const @@ -161,10 +169,10 @@ class Matrix { ASSERT(columns() == m.columns()); ASSERT(rows() == m.rows()); - return mElements == m.elements(); + return elements() == m.elements(); } - bool operator!=(const Matrix &m) const { return !(mElements == m.elements()); } + bool operator!=(const Matrix &m) const { return !(elements() == m.elements()); } bool nearlyEqual(T epsilon, const Matrix &m) const { @@ -186,10 +194,9 @@ class Matrix } unsigned int rows() const { return mRows; } - unsigned int columns() const { return mCols; } - std::vector elements() const { return mElements; } + angle::Span elements() const { return mElements; } T *data() { return mElements.data(); } const T *constData() const { return mElements.data(); } diff --git a/src/common/matrix_utils_unittest.cpp b/src/common/matrix_utils_unittest.cpp index ef0d7f6ef49..24798da0aa5 100644 --- a/src/common/matrix_utils_unittest.cpp +++ b/src/common/matrix_utils_unittest.cpp @@ -7,9 +7,14 @@ // Unit tests for the matrix utils. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "matrix_utils.h" -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" using namespace angle; @@ -95,7 +100,8 @@ TEST(MatrixUtilsTest, MatrixConstructorTest) Matrix m(std::vector(numElements, 1.0f), i, j); EXPECT_EQ(m.rows(), i); EXPECT_EQ(m.columns(), j); - EXPECT_EQ(m.elements(), std::vector(numElements, 1.0f)); + EXPECT_EQ(m.elements().size(), numElements); + EXPECT_THAT(m.elements(), testing::Each(testing::Eq(1.0f))); } } @@ -105,7 +111,8 @@ TEST(MatrixUtilsTest, MatrixConstructorTest) Matrix m(std::vector(numElements, 1.0f), i); EXPECT_EQ(m.size(), i); EXPECT_EQ(m.columns(), m.columns()); - EXPECT_EQ(m.elements(), std::vector(numElements, 1.0f)); + EXPECT_EQ(m.elements().size(), numElements); + EXPECT_THAT(m.elements(), testing::Each(testing::Eq(1.0f))); } } @@ -115,10 +122,10 @@ TEST(MatrixUtilsTest, MatrixCompMultTest) { unsigned int numElements = i * i; Matrix m1(std::vector(numElements, 2.0f), i); - Matrix actualResult = m1.compMult(m1); - std::vector actualResultElements = actualResult.elements(); - std::vector expectedResultElements(numElements, 4.0f); - EXPECT_EQ(expectedResultElements, actualResultElements); + Matrix actualResult = m1.compMult(m1); + angle::Span actualResultElements = actualResult.elements(); + EXPECT_EQ(actualResultElements.size(), numElements); + EXPECT_THAT(actualResultElements, testing::Each(testing::Eq(4.0f))); } } @@ -134,9 +141,9 @@ TEST(MatrixUtilsTest, MatrixOuterProductTest) Matrix actualResult = m1.outerProduct(m2); EXPECT_EQ(actualResult.rows(), i); EXPECT_EQ(actualResult.columns(), j); - std::vector actualResultElements = actualResult.elements(); - std::vector expectedResultElements(numElements, 4.0f); - EXPECT_EQ(expectedResultElements, actualResultElements); + angle::Span actualResultElements = actualResult.elements(); + EXPECT_EQ(actualResultElements.size(), numElements); + EXPECT_THAT(actualResultElements, testing::Each(testing::Eq(4.0f))); } } } @@ -177,12 +184,11 @@ TEST(MatrixUtilsTest, 2x2MatrixInverseTest) float inputElements[] = {2.0f, 5.0f, 3.0f, 7.0f}; unsigned int numElements = 4; std::vector input(inputElements, inputElements + numElements); - Matrix inputMatrix(input, 2); + Matrix inputMatrix(std::move(input), 2); float identityElements[] = {1.0f, 0.0f, 0.0f, 1.0f}; - std::vector identityMatrix(identityElements, identityElements + numElements); // A * inverse(A) = I, where I is identity matrix. Matrix result = inputMatrix * inputMatrix.inverse(); - EXPECT_EQ(identityMatrix, result.elements()); + EXPECT_THAT(result.elements(), testing::ElementsAreArray(identityElements)); } TEST(MatrixUtilsTest, 3x3MatrixInverseTest) @@ -190,35 +196,32 @@ TEST(MatrixUtilsTest, 3x3MatrixInverseTest) float inputElements[] = {11.0f, 23.0f, 37.0f, 13.0f, 29.0f, 41.0f, 19.0f, 31.0f, 43.0f}; unsigned int numElements = 9; std::vector input(inputElements, inputElements + numElements); - Matrix inputMatrix(input, 3); + Matrix inputMatrix(std::move(input), 3); float identityElements[] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - std::vector identityMatrix(identityElements, identityElements + numElements); // A * inverse(A) = I, where I is identity matrix. - Matrix result = inputMatrix * inputMatrix.inverse(); - std::vector resultElements = result.elements(); - const float floatFaultTolarance = 0.000001f; + Matrix result = inputMatrix * inputMatrix.inverse(); + angle::Span resultElements = result.elements(); + const float floatFaultTolarance = 0.000001f; for (size_t i = 0; i < numElements; i++) - EXPECT_NEAR(resultElements[i], identityMatrix[i], floatFaultTolarance); + EXPECT_NEAR(resultElements[i], identityElements[i], floatFaultTolarance); } TEST(MatrixUtilsTest, 4x4MatrixInverseTest) { + unsigned int numElements = 16; float inputElements[] = {29.0f, 43.0f, 61.0f, 79.0f, 31.0f, 47.0f, 67.0f, 83.0f, 37.0f, 53.0f, 71.0f, 89.0f, 41.0f, 59.0f, 73.0f, 97.0f}; - unsigned int numElements = 16; - std::vector input(inputElements, inputElements + numElements); - Matrix inputMatrix(input, 4); + Matrix inputMatrix(inputElements, 4); float identityElements[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; - std::vector identityMatrix(identityElements, identityElements + numElements); // A * inverse(A) = I, where I is identity matrix. - Matrix result = inputMatrix * inputMatrix.inverse(); - std::vector resultElements = result.elements(); - const float floatFaultTolarance = 0.00001f; + Matrix result = inputMatrix * inputMatrix.inverse(); + angle::Span resultElements = result.elements(); + const float floatFaultTolarance = 0.00001f; for (unsigned int i = 0; i < numElements; i++) - EXPECT_NEAR(resultElements[i], identityMatrix[i], floatFaultTolarance); + EXPECT_NEAR(resultElements[i], identityElements[i], floatFaultTolarance); } // Tests constructors for mat4; using raw float*, std::vector, diff --git a/src/common/packed_cl_enums.json b/src/common/packed_cl_enums.json index 9033e7575d4..d27a1ba72ba 100644 --- a/src/common/packed_cl_enums.json +++ b/src/common/packed_cl_enums.json @@ -8,7 +8,8 @@ "HostTimerResolution": "CL_PLATFORM_HOST_TIMER_RESOLUTION", "NumericVersion": "CL_PLATFORM_NUMERIC_VERSION", "ExtensionsWithVersion": "CL_PLATFORM_EXTENSIONS_WITH_VERSION", - "IcdSuffix": "CL_PLATFORM_ICD_SUFFIX_KHR" + "IcdSuffix": "CL_PLATFORM_ICD_SUFFIX_KHR", + "ExternalMemory": "CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR" }, "DeviceInfo": { "Type": "CL_DEVICE_TYPE", @@ -119,7 +120,12 @@ "OpenCL_C_Features": "CL_DEVICE_OPENCL_C_FEATURES", "DeviceEnqueueCapabilities": "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES", "PipeSupport": "CL_DEVICE_PIPE_SUPPORT", - "LatestConformanceVersionPassed": "CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED" + "LatestConformanceVersionPassed": "CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED", + "IntegerDotProductCapabilities": "CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR", + "IntegerDotProductAccelerationProperties8bit": "CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR", + "IntegerDotProductAccelerationProperties4x8bitPacked": "CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR", + "ExternalMemoryImportHandleTypes": "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR", + "ExternalMemoryLinearImagesHandleTypes": "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR" }, "ContextInfo": { "ReferenceCount": "CL_CONTEXT_REFERENCE_COUNT", @@ -165,6 +171,10 @@ "UsesSVM_Pointer": "CL_MEM_USES_SVM_POINTER", "Properties": "CL_MEM_PROPERTIES" }, + "MemProperties": { + "ExternalMemoryHandleListStart":"CL_MEM_DEVICE_HANDLE_LIST_KHR", + "ExternalMemoryHandleListEnd":"CL_MEM_DEVICE_HANDLE_LIST_END_KHR" + }, "ImageInfo": { "Format": "CL_IMAGE_FORMAT", "ElementSize": "CL_IMAGE_ELEMENT_SIZE", @@ -270,5 +280,50 @@ "CommandStart": "CL_PROFILING_COMMAND_START", "CommandEnd": "CL_PROFILING_COMMAND_END", "CommandComplete": "CL_PROFILING_COMMAND_COMPLETE" + }, + "ExternalMemoryHandle": { + "OpaqueFd": "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR", + "OpaqueWin32": "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR", + "OpaqueWin32Kmt": "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR", + "DmaBuf": "CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR" + }, + "ImageChannelOrder": { + "R": "CL_R", + "A": "CL_A", + "RG": "CL_RG", + "RA": "CL_RA", + "RGB": "CL_RGB", + "RGBA": "CL_RGBA", + "BGRA": "CL_BGRA", + "ARGB": "CL_ARGB", + "Intensity": "CL_INTENSITY", + "Luminance": "CL_LUMINANCE", + "Rx": "CL_Rx", + "RGx": "CL_RGx", + "RGBx": "CL_RGBx", + "Depth": "CL_DEPTH", + "sRGB": "CL_sRGB", + "sRGBx": "CL_sRGBx", + "sRGBA": "CL_sRGBA", + "sBGRA": "CL_sBGRA", + "ABGR": "CL_ABGR" + }, + "ImageChannelType": { + "SnormInt8": "CL_SNORM_INT8", + "SnormInt16": "CL_SNORM_INT16", + "UnormInt8": "CL_UNORM_INT8", + "UnormInt16": "CL_UNORM_INT16", + "UnormShort565": "CL_UNORM_SHORT_565", + "UnormShort555": "CL_UNORM_SHORT_555", + "UnormInt101010": "CL_UNORM_INT_101010", + "SignedInt8": "CL_SIGNED_INT8", + "SignedInt16": "CL_SIGNED_INT16", + "SignedInt32": "CL_SIGNED_INT32", + "UnsignedInt8": "CL_UNSIGNED_INT8", + "UnsignedInt16": "CL_UNSIGNED_INT16", + "UnsignedInt32": "CL_UNSIGNED_INT32", + "HalfFloat": "CL_HALF_FLOAT", + "Float": "CL_FLOAT", + "UnormInt101010_2": "CL_UNORM_INT_101010_2" } } diff --git a/src/common/packed_egl_enums.json b/src/common/packed_egl_enums.json index 24eebd036da..018779128bd 100644 --- a/src/common/packed_egl_enums.json +++ b/src/common/packed_egl_enums.json @@ -38,7 +38,8 @@ "ContextPriority": { "Low": "EGL_CONTEXT_PRIORITY_LOW_IMG", "Medium": "EGL_CONTEXT_PRIORITY_MEDIUM_IMG", - "High": "EGL_CONTEXT_PRIORITY_HIGH_IMG" + "High": "EGL_CONTEXT_PRIORITY_HIGH_IMG", + "Realtime": "EGL_CONTEXT_PRIORITY_REALTIME_NV" }, "ColorSpace": { "sRGB": "EGL_COLORSPACE_sRGB", diff --git a/src/common/packed_gl_enums.json b/src/common/packed_gl_enums.json index 3d4809b175b..08ba1a46413 100644 --- a/src/common/packed_gl_enums.json +++ b/src/common/packed_gl_enums.json @@ -111,7 +111,6 @@ { "AnySamples": "GL_ANY_SAMPLES_PASSED", "AnySamplesConservative": "GL_ANY_SAMPLES_PASSED_CONSERVATIVE", - "CommandsCompleted": "GL_COMMANDS_COMPLETED_CHROMIUM", "PrimitivesGenerated": "GL_PRIMITIVES_GENERATED_EXT", "TimeElapsed": "GL_TIME_ELAPSED_EXT", "Timestamp": "GL_TIMESTAMP_EXT", @@ -311,12 +310,24 @@ "ShadingRate": { "Undefined": "GL_NONE", - "_1x1": "GL_SHADING_RATE_1X1_PIXELS_QCOM", - "_1x2": "GL_SHADING_RATE_1X2_PIXELS_QCOM", - "_2x1": "GL_SHADING_RATE_2X1_PIXELS_QCOM", - "_2x2": "GL_SHADING_RATE_2X2_PIXELS_QCOM", - "_4x2": "GL_SHADING_RATE_4X2_PIXELS_QCOM", - "_4x4": "GL_SHADING_RATE_4X4_PIXELS_QCOM" + "_1x1": "GL_SHADING_RATE_1X1_PIXELS_EXT", + "_1x2": "GL_SHADING_RATE_1X2_PIXELS_EXT", + "_1x4": "GL_SHADING_RATE_1X4_PIXELS_EXT", + "_2x1": "GL_SHADING_RATE_2X1_PIXELS_EXT", + "_2x2": "GL_SHADING_RATE_2X2_PIXELS_EXT", + "_2x4": "GL_SHADING_RATE_2X4_PIXELS_EXT", + "_4x1": "GL_SHADING_RATE_4X1_PIXELS_EXT", + "_4x2": "GL_SHADING_RATE_4X2_PIXELS_EXT", + "_4x4": "GL_SHADING_RATE_4X4_PIXELS_EXT" + }, + "CombinerOp": + { + "Undefined": "GL_NONE", + "Keep" : "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT", + "Replace" : "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT", + "Min" : "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT", + "Max" : "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT", + "Mul" : "GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT" }, "TilingMode": { diff --git a/src/common/platform.h b/src/common/platform.h index 16eb8ddcd7a..48d6c5dfa79 100644 --- a/src/common/platform.h +++ b/src/common/platform.h @@ -20,9 +20,6 @@ #elif defined(ANDROID) && !defined(ANGLE_ANDROID_DMA_BUF) # define ANGLE_PLATFORM_ANDROID 1 # define ANGLE_PLATFORM_POSIX 1 -#elif defined(__ggp__) -# define ANGLE_PLATFORM_GGP 1 -# define ANGLE_PLATFORM_POSIX 1 #elif defined(__linux__) || defined(EMSCRIPTEN) # define ANGLE_PLATFORM_LINUX 1 # define ANGLE_PLATFORM_POSIX 1 @@ -114,8 +111,8 @@ // Macro for hinting that an expression is likely to be true/false. #if !defined(ANGLE_LIKELY) || !defined(ANGLE_UNLIKELY) # if defined(__GNUC__) || defined(__clang__) -# define ANGLE_LIKELY(x) __builtin_expect(!!(x), 1) -# define ANGLE_UNLIKELY(x) __builtin_expect(!!(x), 0) +# define ANGLE_LIKELY(x) __builtin_expect_with_probability(!!(x), 1, 0.9999) +# define ANGLE_UNLIKELY(x) __builtin_expect_with_probability(!!(x), 0, 0.9999) # else # define ANGLE_LIKELY(x) (x) # define ANGLE_UNLIKELY(x) (x) diff --git a/src/common/serializer/JsonSerializer.cpp b/src/common/serializer/JsonSerializer.cpp index 0028331d9b9..a62a2b8e488 100644 --- a/src/common/serializer/JsonSerializer.cpp +++ b/src/common/serializer/JsonSerializer.cpp @@ -7,6 +7,10 @@ // Note that for binary blob data only a checksum is stored so that // a lossless deserialization is not supported. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "JsonSerializer.h" #include "common/debug.h" @@ -46,18 +50,17 @@ void JsonSerializer::endGroup() addValue(name, std::move(group)); } -void JsonSerializer::addBlob(const std::string &name, const uint8_t *blob, size_t length) +void JsonSerializer::addBlob(const std::string &name, angle::Span blob) { - addBlobWithMax(name, blob, length, 16); + addBlobWithMax(name, blob, 16); } void JsonSerializer::addBlobWithMax(const std::string &name, - const uint8_t *blob, - size_t length, + angle::Span blob, size_t maxSerializedLength) { unsigned char hash[angle::base::kSHA1Length]; - angle::base::SHA1HashBytes(blob, length, hash); + angle::base::SHA1HashBytes(blob.data(), blob.size(), hash); std::ostringstream os; // Since we don't want to de-serialize the data we just store a checksum of the blob @@ -72,10 +75,11 @@ void JsonSerializer::addBlobWithMax(const std::string &name, hashName << name << "-hash"; addString(hashName.str(), os.str()); - std::vector data( - (length < maxSerializedLength) ? length : static_cast(maxSerializedLength)); - std::copy(blob, blob + data.size(), data.begin()); - + if (blob.size() > maxSerializedLength) + { + blob = blob.first(maxSerializedLength); + } + std::vector data(blob.begin(), blob.end()); std::ostringstream rawName; rawName << name << "-raw[0-" << data.size() - 1 << ']'; addVector(rawName.str(), data); @@ -83,7 +87,6 @@ void JsonSerializer::addBlobWithMax(const std::string &name, void JsonSerializer::addCString(const std::string &name, const char *value) { - rapidjson::Value tag(name.c_str(), mAllocator); rapidjson::Value val(value, mAllocator); addValue(name, std::move(val)); } diff --git a/src/common/serializer/JsonSerializer.h b/src/common/serializer/JsonSerializer.h index 7f8a908af3d..625ca9506e1 100644 --- a/src/common/serializer/JsonSerializer.h +++ b/src/common/serializer/JsonSerializer.h @@ -23,6 +23,8 @@ #include #include +#include "common/span.h" + namespace angle { @@ -53,17 +55,14 @@ class JsonSerializer : public angle::NonCopyable ~JsonSerializer(); void addCString(const std::string &name, const char *value); - void addString(const std::string &name, const std::string &value); - void addBlob(const std::string &name, const uint8_t *value, size_t length); + void addBlob(const std::string &name, angle::Span value); void addBlobWithMax(const std::string &name, - const uint8_t *value, - size_t length, + angle::Span value, size_t maxSerializedLength); void startGroup(const std::string &name); - void endGroup(); template @@ -92,7 +91,7 @@ class JsonSerializer : public angle::NonCopyable { if (!value.empty()) { - addBlob(name, reinterpret_cast(&value[0]), value.size() * sizeof(T)); + addBlob(name, angle::as_byte_span(value)); } else { diff --git a/src/common/serializer/JsonSerializer_unittest.cpp b/src/common/serializer/JsonSerializer_unittest.cpp index 50d67ed38ee..e004c0dda00 100644 --- a/src/common/serializer/JsonSerializer_unittest.cpp +++ b/src/common/serializer/JsonSerializer_unittest.cpp @@ -103,7 +103,7 @@ TEST_F(JsonSerializerTest, NamedStringValue) TEST_F(JsonSerializerTest, ByteArrayValue) { const uint8_t value[5] = {10, 0, 0xcc, 0xff, 0xaa}; - js.addBlob("test2", value, 5); + js.addBlob("test2", value); const std::string expect = R"({ diff --git a/src/common/span.h b/src/common/span.h index e17d7eb8a7e..51799021c84 100644 --- a/src/common/span.h +++ b/src/common/span.h @@ -1,112 +1,464 @@ -// -// Copyright 2025 The ANGLE Project Authors. All rights reserved. +// Copyright 2025 The ANGLE Project Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// -// Span.h: -// Basic implementation of C++20's span. -// + +// This is Chromium's base/containers/span.h, modified to support C++17 +// as part of the PDFium project, stubbed to be self-contained, and then +// modified to conform to ANGLE: +// -- fixed missing constexpr as exercised by test. +// -- added operator==(). #ifndef COMMON_SPAN_H_ #define COMMON_SPAN_H_ +#include +#include + +#include +#include +#include #include +#include -#include "common/log_utils.h" +#include "common/base/anglebase/logging.h" +#include "common/unsafe_buffers.h" namespace angle { -// Basic implementation of C++20's span. -// See the reference for std::span here: https://en.cppreference.com/w/cpp/container/span +constexpr size_t dynamic_extent = static_cast(-1); + +template +using DefaultSpanInternalPtr = T *; + +template > +class Span; + +namespace internal +{ + +template +struct IsSpanImpl : std::false_type +{}; + template +struct IsSpanImpl> : std::true_type +{}; + +template +using IsSpan = IsSpanImpl::type>; + +template +struct IsStdArrayImpl : std::false_type +{}; + +template +struct IsStdArrayImpl> : std::true_type +{}; + +template +using IsStdArray = IsStdArrayImpl::type>; + +template +using IsLegalSpanConversion = std::is_convertible; + +template +using ContainerHasConvertibleData = IsLegalSpanConversion< + typename std::remove_pointer().data())>::type, + T>; +template +using ContainerHasIntegralSize = std::is_integral().size())>; + +template +using EnableIfLegalSpanConversion = + typename std::enable_if::value>::type; + +// SFINAE check if Container can be converted to a Span. Note that the +// implementation details of this check differ slightly from the requirements in +// the working group proposal: in particular, the proposal also requires that +// the container conversion constructor participate in overload resolution only +// if two additional conditions are true: +// +// 1. Container implements operator[]. +// 2. Container::value_type matches remove_const_t. +// +// The requirements are relaxed slightly here: in particular, not requiring (2) +// means that an immutable Span can be easily constructed from a mutable +// container. +template +using EnableIfSpanCompatibleContainer = + typename std::enable_if::value && + !internal::IsStdArray::value && + ContainerHasConvertibleData::value && + ContainerHasIntegralSize::value>::type; + +template +using EnableIfConstSpanCompatibleContainer = + typename std::enable_if::value && !internal::IsSpan::value && + !internal::IsStdArray::value && + ContainerHasConvertibleData::value && + ContainerHasIntegralSize::value>::type; + +} // namespace internal + +// A Span is a value type that represents an array of elements of type T. Since +// it only consists of a pointer to memory with an associated size, it is very +// light-weight. It is cheap to construct, copy, move and use spans, so that +// users are encouraged to use it as a pass-by-value parameter. A Span does not +// own the underlying memory, so care must be taken to ensure that a Span does +// not outlive the backing store. +// +// Differences from the working group proposal +// ------------------------------------------- +// +// https://wg21.link/P0122 is the latest working group proposal, Chromium +// currently implements R6. +// +// Differences in constants and types: +// - Span has a capital "S". +// - Allows custom smart pointer types in internal representation, if desired. +// - no element_type type alias +// - no index_type type alias +// - no different_type type alias +// - no extent constant +// +// Differences from [span.cons]: +// - no constructor from a pointer range +// +// Differences from [span.sub]: +// - using size_t instead of ptrdiff_t for indexing +// +// Differences from [span.obs]: +// - using size_t instead of ptrdiff_t to represent size() +// +// Differences from [span.elem]: +// - no operator ()() +// - using size_t instead of ptrdiff_t for indexing +// +// Additions beyond the C++ standard draft +// - as_chars() function. +// - as_writable_chars() function. +// - as_byte_span() function. +// - as_writable_byte_span() function. +// - span_from_ref() function. +// - byte_span_from_ref() function. + +// [span], class template span +template class Span { public: - typedef size_t size_type; + using value_type = typename std::remove_cv::type; + using pointer = T *; + using reference = T &; + using iterator = T *; + using const_iterator = const T *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; - constexpr Span() = default; - constexpr Span(T *ptr, size_type size) : mData(ptr), mSize(size) {} + // [span.cons], span constructors, copy, assignment, and destructor + constexpr Span() noexcept = default; - template ::is_pool_allocated>> - constexpr Span(V &&vec) : mData(vec.data()), mSize(vec.size()) - {} + ANGLE_UNSAFE_BUFFER_USAGE constexpr Span(T *data, size_t size) noexcept + : data_(data), size_(size) + { + DCHECK(data_ || size_ == 0); + } - template ::is_pool_allocated>> - constexpr Span &operator=(V &&vec) + // TODO(dcheng): Implement construction from a |begin| and |end| pointer. + template + constexpr Span(T (&array)[N]) noexcept + // SAFETY: The type signature guarantees `array` contains `N` elements. + : ANGLE_UNSAFE_BUFFERS(Span(array, N)) { - mData = vec.data(); - mSize = vec.size(); - return *this; + static_assert(Extent == dynamic_extent || Extent == N); } - constexpr bool operator==(const Span &that) const + template + constexpr Span(std::array &array) noexcept + // SAFETY: The type signature guarantees `array` contains `N` elements. + : ANGLE_UNSAFE_BUFFERS(Span(array.data(), N)) + { + static_assert(Extent == dynamic_extent || Extent == N); + } + + template >> + constexpr Span(const std::array &array) noexcept + // SAFETY: The type signature guarantees `array` contains `N` elements. + : ANGLE_UNSAFE_BUFFERS(Span(array.data(), N)) + { + static_assert(Extent == dynamic_extent || Extent == N); + } + + // Conversion from a container that provides |T* data()| and |integral_type + // size()|. Note that |data()| may not return nullptr for some empty + // containers, which can lead to container overflow errors when probing + // raw ptrs. + template > + constexpr Span(Container &container) + // SAFETY: `size()` is the number of elements that can be safely accessed + // at `data()`. + : ANGLE_UNSAFE_BUFFERS(Span(container.data(), container.size())) + {} + + template > + constexpr Span(const Container &container) + // SAFETY: `size()` is exactly the number of elements in the initializer + // list, so accessing that many will be safe. + : ANGLE_UNSAFE_BUFFERS(Span(container.data(), container.size())) + {} + + constexpr Span(const Span &other) noexcept = default; + + // Conversions from spans of compatible types: this allows a Span to be + // seamlessly used as a Span, but not the other way around. + template > + constexpr Span(const Span &other) + // SAFETY: `size()` is the number of elements that can be safely accessed + // at `data()`. + : ANGLE_UNSAFE_BUFFERS(Span(other.data(), other.size())) { - if (mSize != that.mSize) - { - return false; - } + static_assert(Extent == dynamic_extent || Extent == M, + "Assigning to fixed span from incompatible span"); + } - if (mData == that.mData) - { - return true; - } + Span &operator=(const Span &other) noexcept = default; + Span &operator=(Span &&other) noexcept = default; - for (size_type index = 0; index < mSize; ++index) - { - if (mData[index] != that.mData[index]) - { - return false; - } - } + ~Span() noexcept = default; - return true; + template + bool operator==(const Span &other) const + { + return std::equal(begin(), end(), other.begin(), other.end()); + } + template + bool operator!=(const Span &other) const + { + return !std::equal(begin(), end(), other.begin(), other.end()); } - constexpr bool operator!=(const Span &that) const { return !(*this == that); } - constexpr T *data() const { return mData; } - constexpr size_type size() const { return mSize; } - constexpr bool empty() const { return mSize == 0; } + // [span.sub], span subviews + template + constexpr Span first() const + { + // TODO(tsepez): The following assert isn't yet good enough to replace + // the runtime check since we are still allowing unchecked conversions + // to arbitrary non-dynamic_extent spans. + static_assert(Extent == dynamic_extent || Count <= Extent); + CHECK(Count <= size_); + // SAFETY: CHECK() on line above. + return ANGLE_UNSAFE_BUFFERS(Span(data(), Count)); + } + constexpr Span first(size_t count) const + { + CHECK(count <= size_); + // SAFETY: CHECK() on line above. + return ANGLE_UNSAFE_BUFFERS(Span(static_cast(data_), count)); + } + + template + constexpr Span last() const + { + // TODO(tsepez): The following assert isn't yet good enough to replace + // the runtime check since we are still allowing unchecked conversions + // to arbitrary non-dynamic_extent spans. + static_assert(Extent == dynamic_extent || Count <= Extent); + CHECK(Count <= size_); + // SAFETY: CHECK() on line above. + return ANGLE_UNSAFE_BUFFERS(Span(data() + (size_ - Count), Count)); + } + constexpr Span last(size_t count) const + { + CHECK(count <= size_); + // SAFETY: CHECK() on line above. + return ANGLE_UNSAFE_BUFFERS(Span(static_cast(data_) + (size_ - count), count)); + } - constexpr T &operator[](size_type index) const { return mData[index]; } - constexpr T &front() const { return mData[0]; } - constexpr T &back() const { return mData[mSize - 1]; } + template + constexpr Span subspan() const + { + // TODO(tsepez): The following check isn't yet good enough to replace + // the runtime check since we are still allowing unchecked conversions + // to arbitrary non-dynamic_extent spans. + static_assert(Extent == dynamic_extent || Count == dynamic_extent || + Offset + Count <= Extent); + return subspan(Offset, Count); + } + constexpr Span subspan(size_t pos, size_t count = dynamic_extent) const + { + CHECK(pos <= size_); + CHECK(count == dynamic_extent || count <= size_ - pos); + // SAFETY: CHECK()s on lines above. + return ANGLE_UNSAFE_BUFFERS( + Span(static_cast(data_) + pos, count == dynamic_extent ? size_ - pos : count)); + } - constexpr T *begin() const { return mData; } - constexpr T *end() const { return mData + mSize; } + // [span.obs], span observers + constexpr size_t size() const noexcept { return size_; } + constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); } + constexpr bool empty() const noexcept { return size_ == 0; } - constexpr std::reverse_iterator rbegin() const + // [span.elem], span element access + T &operator[](size_t index) const noexcept { - return std::make_reverse_iterator(end()); + CHECK(index < size_); + return ANGLE_UNSAFE_BUFFERS(static_cast(data_)[index]); } - constexpr std::reverse_iterator rend() const + + constexpr T &front() const noexcept { - return std::make_reverse_iterator(begin()); + CHECK(!empty()); + return *data(); } - constexpr Span first(size_type count) const + constexpr T &back() const noexcept { - ASSERT(count <= mSize); - return count == 0 ? Span() : Span(mData, count); + CHECK(!empty()); + return ANGLE_UNSAFE_BUFFERS(*(data() + size() - 1)); } - constexpr Span last(size_type count) const + + constexpr T *data() const noexcept { return static_cast(data_); } + + // [span.iter], span iterator support + constexpr iterator begin() const noexcept { return static_cast(data_); } + constexpr iterator end() const noexcept { return ANGLE_UNSAFE_BUFFERS(begin() + size_); } + + constexpr const_iterator cbegin() const noexcept { return begin(); } + constexpr const_iterator cend() const noexcept { return end(); } + + constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } + + constexpr const_reverse_iterator crbegin() const noexcept { - ASSERT(count <= mSize); - return count == 0 ? Span() : Span(mData + mSize - count, count); + return const_reverse_iterator(cend()); } - constexpr Span subspan(size_type offset, size_type count) const + constexpr const_reverse_iterator crend() const noexcept { - ASSERT(offset + count <= mSize); - return count == 0 ? Span() : Span(mData + offset, count); + return const_reverse_iterator(cbegin()); } private: - T *mData = nullptr; - size_t mSize = 0; + InternalPtr data_ = nullptr; + size_t size_ = 0; }; +// Deduction guides. +template +Span(T (&)[N]) -> Span; + +template +Span(const T (&)[N]) -> Span; + +template +Span(std::array &) -> Span; + +template +Span(const std::array &) -> Span; + +template ().data())>>> +Span(Container &&) -> Span().data())>>; + +// [span.objectrep], views of object representation +template +Span as_bytes(Span s) noexcept +{ + // SAFETY: from size_bytes() method. + return ANGLE_UNSAFE_BUFFERS( + Span(reinterpret_cast(s.data()), s.size_bytes())); +} + +template ::value>::type> +Span as_writable_bytes(Span s) noexcept +{ + // SAFETY: from size_bytes() method. + return ANGLE_UNSAFE_BUFFERS( + Span(reinterpret_cast(s.data()), s.size_bytes())); +} + +template +Span as_chars(Span s) noexcept +{ + // SAFETY: from size_bytes() method. + return ANGLE_UNSAFE_BUFFERS( + Span(reinterpret_cast(s.data()), s.size_bytes())); +} + +template ::value>::type> +Span as_writable_chars(Span s) noexcept +{ + // SAFETY: from size_bytes() method. + return ANGLE_UNSAFE_BUFFERS(Span(reinterpret_cast(s.data()), s.size_bytes())); +} + +// `span_from_ref` converts a reference to T into a span of length 1. This is a +// non-std helper that is inspired by the `std::slice::from_ref()` function from +// Rust. +template +static constexpr Span span_from_ref(T &single_object) noexcept +{ + // SAFETY: single object passed by reference. + return ANGLE_UNSAFE_BUFFERS(Span(&single_object, 1u)); +} + +// `byte_span_from_ref` converts a reference to T into a span of uint8_t of +// length sizeof(T). This is a non-std helper that is a sugar for +// `as_writable_bytes(span_from_ref(x))`. +template +static constexpr Span byte_span_from_ref(const T &single_object) noexcept +{ + return as_bytes(span_from_ref(single_object)); +} +template +static constexpr Span byte_span_from_ref(T &single_object) noexcept +{ + return as_writable_bytes(span_from_ref(single_object)); +} + +// Convenience function for converting an object which is itself convertible +// to span into a span of bytes (i.e. span of const uint8_t). Typically used +// to convert std::string or string-objects holding chars, or std::vector +// or vector-like objects holding other scalar types, prior to passing them +// into an API that requires byte spans. +template +Span as_byte_span(const T &arg) +{ + return as_bytes(Span(arg)); +} +template +Span as_byte_span(T &&arg) +{ + return as_bytes(Span(arg)); +} + +// Convenience function for converting an object which is itself convertible +// to span into a span of mutable bytes (i.e. span of uint8_t). Typically used +// to convert std::string or string-objects holding chars, or std::vector +// or vector-like objects holding other scalar types, prior to passing them +// into an API that requires mutable byte spans. +template +constexpr Span as_writable_byte_span(T &&arg) +{ + return as_writable_bytes(Span(arg)); +} + } // namespace angle -#endif // COMMON_SPAN_ +#endif // COMMON_SPAN_H_ diff --git a/src/common/span_unittest.cpp b/src/common/span_unittest.cpp index 6c989dfe795..9d0d44f14fa 100644 --- a/src/common/span_unittest.cpp +++ b/src/common/span_unittest.cpp @@ -6,29 +6,47 @@ // span_unittests.cpp: Unit tests for the angle::Span class. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/span.h" #include -using namespace angle; +#include +#include +#include +#include +#include +namespace angle +{ namespace { -using Span = angle::Span; constexpr size_t kSpanDataSize = 16; -constexpr unsigned int kSpanData[kSpanDataSize] = {0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15}; +constexpr unsigned int kSpanData[kSpanDataSize] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15}; +constexpr std::array kSpanArr = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; + +class FakeRange +{ + public: + size_t size() const { return kSpanDataSize; } + const unsigned int *data() { return kSpanData; } +}; // Test that comparing spans work TEST(SpanTest, Comparison) { // Duplicate data to make sure comparison is being done on values (and not addresses). - constexpr unsigned int kSpanDataDup[kSpanDataSize] = {0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15}; + static constexpr unsigned int kSpanDataDup[kSpanDataSize] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15}; // Don't use ASSERT_EQ at first because the == is more hidden - ASSERT_TRUE(Span() == Span(kSpanData, 0)); + ASSERT_TRUE(Span() == Span(kSpanData, 0)); ASSERT_TRUE(Span(kSpanData + 3, 4) != Span(kSpanDataDup + 5, 4)); // Check ASSERT_EQ and ASSERT_NE work correctly @@ -72,24 +90,132 @@ TEST(SpanTest, Constructors) { // Default constructor { - Span sp; + Span sp; + static_assert(std::is_same_v>); ASSERT_TRUE(sp.size() == 0); ASSERT_TRUE(sp.empty()); } - // Constexpr construct from pointer + // Constexpr construct from pointer and size { constexpr Span sp(kSpanData, kSpanDataSize); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), kSpanData); + ASSERT_EQ(sp.size(), kSpanDataSize); + ASSERT_FALSE(sp.empty()); + } + + // Constexpr construct from fixed C-style array + { + constexpr Span sp(kSpanData); + static_assert(std::is_same_v>); ASSERT_EQ(sp.data(), kSpanData); ASSERT_EQ(sp.size(), kSpanDataSize); ASSERT_FALSE(sp.empty()); } + // Constexpr construct from constexpr std::array + { + constexpr Span sp(kSpanArr); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), kSpanArr.data()); + ASSERT_EQ(sp.size(), kSpanArr.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from const std::array. + { + const std::array kArr = {1, 2}; + Span sp(kArr); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), kArr.data()); + ASSERT_EQ(sp.size(), kArr.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from std::array. + { + std::array arr = {1, 2}; + Span sp(arr); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), arr.data()); + ASSERT_EQ(sp.size(), arr.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from std::array. + { + std::array arr = {1, 2}; + Span sp(arr); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), arr.data()); + ASSERT_EQ(sp.size(), arr.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from std::vector + { + std::vector vec({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}); + Span sp(vec); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), vec.data()); + ASSERT_EQ(sp.size(), vec.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from const std::vector + { + const std::vector vec({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}); + Span sp(vec); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), vec.data()); + ASSERT_EQ(sp.size(), vec.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from std::string + { + std::string str = "hooray"; + Span sp(str); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), str.data()); + ASSERT_EQ(sp.size(), str.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from const std::string + { + const std::string str = "hooray"; + Span sp(str); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), str.data()); + ASSERT_EQ(sp.size(), str.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construct from std::string_view + { + std::string_view view = "hooray"; + Span sp(view); + static_assert(std::is_same_v>); + ASSERT_EQ(sp.data(), view.data()); + ASSERT_EQ(sp.size(), view.size()); + ASSERT_FALSE(sp.empty()); + } + + // Construction from any class that provides data() and size(). + { + FakeRange range; + Span sp(range); + ASSERT_EQ(sp.data(), kSpanData); + ASSERT_EQ(sp.size(), kSpanDataSize); + } + // Copy constructor and copy assignment { - Span sp(kSpanData, kSpanDataSize); + Span sp(kSpanData); Span sp2(sp); - Span sp3; + Span sp3; ASSERT_EQ(sp, sp2); ASSERT_EQ(sp2.data(), kSpanData); @@ -98,7 +224,7 @@ TEST(SpanTest, Constructors) sp3 = sp; - ASSERT_EQ(sp, sp3); + ASSERT_EQ(sp3, sp); ASSERT_EQ(sp3.data(), kSpanData); ASSERT_EQ(sp3.size(), kSpanDataSize); ASSERT_FALSE(sp3.empty()); @@ -156,16 +282,37 @@ TEST(SpanTest, FirstAndLast) { constexpr Span sp(kSpanData, kSpanDataSize); constexpr size_t kSplitSize = kSpanDataSize / 4; - constexpr Span first = sp.first(kSplitSize); - constexpr Span last = sp.last(kSplitSize); + { + constexpr Span first = sp.first(kSplitSize); + constexpr Span last = sp.last(kSplitSize); + + static_assert( + std::is_same_v>); + ASSERT_EQ(first, Span(kSpanData, kSplitSize)); + ASSERT_EQ(first.data(), kSpanData); + ASSERT_EQ(first.size(), kSplitSize); + + static_assert( + std::is_same_v>); + ASSERT_EQ(last, Span(kSpanData + kSpanDataSize - kSplitSize, kSplitSize)); + ASSERT_EQ(last.data(), kSpanData + kSpanDataSize - kSplitSize); + ASSERT_EQ(last.size(), kSplitSize); + } - ASSERT_EQ(first, Span(kSpanData, kSplitSize)); - ASSERT_EQ(first.data(), kSpanData); - ASSERT_EQ(first.size(), kSplitSize); + { + constexpr Span first = sp.first(); + constexpr Span last = sp.last(); + + static_assert(std::is_same_v>); + ASSERT_EQ(first, Span(kSpanData, kSplitSize)); + ASSERT_EQ(first.data(), kSpanData); + ASSERT_EQ(first.size(), kSplitSize); - ASSERT_EQ(last, Span(kSpanData + kSpanDataSize - kSplitSize, kSplitSize)); - ASSERT_EQ(last.data(), kSpanData + kSpanDataSize - kSplitSize); - ASSERT_EQ(last.size(), kSplitSize); + static_assert(std::is_same_v>); + ASSERT_EQ(last, Span(kSpanData + kSpanDataSize - kSplitSize, kSplitSize)); + ASSERT_EQ(last.data(), kSpanData + kSpanDataSize - kSplitSize); + ASSERT_EQ(last.size(), kSplitSize); + } } // Test subspan @@ -174,11 +321,173 @@ TEST(SpanTest, Subspan) constexpr Span sp(kSpanData, kSpanDataSize); constexpr size_t kSplitOffset = kSpanDataSize / 4; constexpr size_t kSplitSize = kSpanDataSize / 2; - constexpr Span subspan = sp.subspan(kSplitOffset, kSplitSize); - ASSERT_EQ(subspan, Span(kSpanData + kSplitOffset, kSplitSize)); - ASSERT_EQ(subspan.data(), kSpanData + kSplitOffset); - ASSERT_EQ(subspan.size(), kSplitSize); + // Test one-arg subspan + { + constexpr Span subspan = sp.subspan(kSplitOffset); + static_assert( + std::is_same_v>); + ASSERT_EQ(subspan, Span(kSpanData + kSplitOffset, kSpanDataSize - kSplitOffset)); + ASSERT_EQ(subspan.data(), kSpanData + kSplitOffset); + ASSERT_EQ(subspan.size(), kSpanDataSize - kSplitOffset); + } + + // Test two-arg subspan + { + constexpr Span subspan = sp.subspan(kSplitOffset, kSplitSize); + static_assert( + std::is_same_v>); + ASSERT_EQ(subspan, Span(kSpanData + kSplitOffset, kSplitSize)); + ASSERT_EQ(subspan.data(), kSpanData + kSplitOffset); + ASSERT_EQ(subspan.size(), kSplitSize); + } + + // Templated one-arg subspan just sugar until C++20 fixed spans. + { + constexpr Span subspan = sp.subspan(); + static_assert( + std::is_same_v>); + ASSERT_EQ(subspan, Span(kSpanData + kSplitOffset, kSpanDataSize - kSplitOffset)); + ASSERT_EQ(subspan.data(), kSpanData + kSplitOffset); + ASSERT_EQ(subspan.size(), kSpanDataSize - kSplitOffset); + } + + // Templated two-arg subspan just sugar until C++20 fixed spans. + { + constexpr Span subspan = sp.subspan(); + static_assert( + std::is_same_v>); + ASSERT_EQ(subspan, Span(kSpanData + kSplitOffset, kSplitSize)); + ASSERT_EQ(subspan.data(), kSpanData + kSplitOffset); + ASSERT_EQ(subspan.size(), kSplitSize); + } +} + +// Test conversions from non-const to const spans. +TEST(SpanTest, ConstConversions) +{ + const unsigned int kStorage[kSpanDataSize] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15}; + unsigned int storage[kSpanDataSize] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + angle::Span readable_span(kStorage, kSpanDataSize); + angle::Span writable_span(storage, kSpanDataSize); + + static_assert( + std::is_same_v>); + + static_assert(std::is_same_v>); + + // Direct comparisons allowed. + EXPECT_TRUE(readable_span == writable_span); + EXPECT_FALSE(readable_span != writable_span); + + writable_span[0] = 1234; + EXPECT_FALSE(readable_span == writable_span); + + // Assignment allowed from non-const to const. + readable_span = writable_span; + EXPECT_TRUE(readable_span == writable_span); +} + +// Test conversions from fixed to dynamic spans. +TEST(SpanTest, FixedConversions) +{ + unsigned int storage[kSpanDataSize] = {}; + std::vector vec(kSpanDataSize, 42); + Span dynamic_span(vec); + Span static_span(storage); + + // Direct comparisons allowed. + EXPECT_NE(static_span, dynamic_span); + + // Assignment allowed from fixed to dynamic. + dynamic_span = static_span; + EXPECT_EQ(static_span, dynamic_span); + + // Other way around prohibited without fixed conversion. + dynamic_span[0] = 1234; + static_span = dynamic_span.first(); + EXPECT_EQ(static_span, dynamic_span); +} + +// Test non-member functions. +TEST(SpanTest, Helpers) +{ + // Test as_bytes. + { + constexpr int kArray[] = {2, 3, 5, 7, 11, 13}; + auto bytes_span = as_bytes(Span(kArray)); + EXPECT_EQ(reinterpret_cast(kArray), bytes_span.data()); + EXPECT_EQ(sizeof(kArray), bytes_span.size()); + EXPECT_EQ(bytes_span.size(), bytes_span.size_bytes()); + } + + // Test as_writble_bytes. + { + std::vector vec = {1, 1, 2, 3, 5, 8}; + Span mutable_span(vec); + auto writable_bytes_span = as_writable_bytes(mutable_span); + static_assert(std::is_same_v>); + EXPECT_EQ(reinterpret_cast(vec.data()), writable_bytes_span.data()); + EXPECT_EQ(sizeof(int) * vec.size(), writable_bytes_span.size()); + EXPECT_EQ(writable_bytes_span.size(), writable_bytes_span.size_bytes()); + } + + // Test as_chars. + { + constexpr int kArray[] = {2, 3, 5, 7, 11, 13}; + auto chars_span = as_chars(Span(kArray)); + EXPECT_EQ(reinterpret_cast(kArray), chars_span.data()); + EXPECT_EQ(sizeof(kArray), chars_span.size()); + EXPECT_EQ(chars_span.size(), chars_span.size_bytes()); + } + + // Test as writable chars. + { + std::vector vec = {1, 1, 2, 3, 5, 8}; + Span mutable_span(vec); + auto writable_chars_span = as_writable_chars(mutable_span); + static_assert(std::is_same_v>); + EXPECT_EQ(reinterpret_cast(vec.data()), writable_chars_span.data()); + EXPECT_EQ(sizeof(int) * vec.size(), writable_chars_span.size()); + EXPECT_EQ(writable_chars_span.size(), writable_chars_span.size_bytes()); + } + + // Test span_from_ref. + { + int x = 123; + auto s = span_from_ref(x); + EXPECT_EQ(&x, s.data()); + EXPECT_EQ(1u, s.size()); + EXPECT_EQ(sizeof(int), s.size_bytes()); + EXPECT_EQ(123, s[0]); + } + + // Test byte_span_from_ref. + { + int x = 123; + auto b = byte_span_from_ref(x); + EXPECT_EQ(reinterpret_cast(&x), b.data()); + EXPECT_EQ(sizeof(int), b.size()); + } + + // Test as_byte_span. + { + const std::vector kVec({2, 3, 5, 7, 11, 13}); + auto byte_span = as_byte_span(kVec); + static_assert(std::is_same_v>); + EXPECT_EQ(byte_span.data(), reinterpret_cast(kVec.data())); + EXPECT_EQ(byte_span.size(), kVec.size() * sizeof(int)); + } + + // Test as_writable_byte_span + { + int kMutArray[] = {2, 3, 5, 7}; + auto byte_span = as_writable_byte_span(kMutArray); + EXPECT_EQ(byte_span.data(), reinterpret_cast(kMutArray)); + EXPECT_EQ(byte_span.size(), sizeof(kMutArray)); + } } } // anonymous namespace +} // namespace angle diff --git a/src/common/span_util.h b/src/common/span_util.h new file mode 100644 index 00000000000..a0fc731b83b --- /dev/null +++ b/src/common/span_util.h @@ -0,0 +1,65 @@ +// Copyright 2025 The ANGLE Project Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMMON_SPAN_UTIL_H_ +#define COMMON_SPAN_UTIL_H_ + +#include +#include +#include + +#include "common/base/anglebase/logging.h" +#include "common/span.h" +#include "common/unsafe_buffers.h" + +namespace angle +{ + +// Bounds-checked byte-for-byte copies from spans into spans. +template +inline void SpanMemcpy(angle::Span dst, angle::Span src) +{ + static_assert(sizeof(T1) == sizeof(T2) && std::is_trivially_copyable_v && + std::is_trivially_copyable_v); + CHECK(dst.size() >= src.size()); + if (src.size()) + { + // SAFETY: static_assert() ensures `sizeof(T1)` equals `sizeof(T2)`, so + // comparing `size()` for equality ensures `size_bytes()` are equal, and + // `size_bytes()` accurately describes `data()`. + ANGLE_UNSAFE_BUFFERS(memcpy(dst.data(), src.data(), src.size_bytes())); + } +} + +// Bounds-checked byte-for-byte moves from spans into spans. +template +inline void SpanMemmove(angle::Span dst, angle::Span src) +{ + static_assert(sizeof(T1) == sizeof(T2) && std::is_trivially_copyable_v && + std::is_trivially_copyable_v); + CHECK(dst.size() >= src.size()); + if (src.size()) + { + // SAFETY: static_assert() ensures `sizeof(T1)` equals `sizeof(T2)`, so + // comparing `size()` for equality ensures `size_bytes()` are equal, and + // `size_bytes()` accurately describes `data()`. + ANGLE_UNSAFE_BUFFERS(memmove(dst.data(), src.data(), src.size_bytes())); + } +} + +// Bounds-checked memsets into spans. +template +inline void SpanMemset(angle::Span dst, uint8_t val) +{ + static_assert(std::is_trivially_copyable_v); + if (dst.size()) + { + // SAFETY: `dst.data()` is valid for `dst.size_bytes()` bytes. + ANGLE_UNSAFE_BUFFERS(memset(dst.data(), val, dst.size_bytes())); + } +} + +} // namespace angle + +#endif // COMMON_SPAN_UTIL_H_ diff --git a/src/common/span_util_unittest.cpp b/src/common/span_util_unittest.cpp new file mode 100644 index 00000000000..cdbe9c18d3a --- /dev/null +++ b/src/common/span_util_unittest.cpp @@ -0,0 +1,113 @@ +// Copyright 2025 The ANGLE Project Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "common/span_util.h" + +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace angle +{ +namespace +{ + +// Test that SpanMemcpy() can copy two same-size spans. +TEST(SpanMemcpy, FitsEntirely) +{ + std::vector src(4, 'A'); + std::vector dst(4, 'B'); + angle::SpanMemcpy(angle::Span(dst), angle::Span(src)); + EXPECT_EQ(dst[0], 'A'); + EXPECT_EQ(dst[1], 'A'); + EXPECT_EQ(dst[2], 'A'); + EXPECT_EQ(dst[3], 'A'); +} + +// Test that SpanMemcpy() can copy a smaller span into a larger one. +TEST(SpanMemcpy, FitsWithin) +{ + std::vector src(2, 'A'); + std::vector dst(4, 'B'); + // Also show that a const src argument is acceptable. + angle::SpanMemcpy(angle::Span(dst).subspan<1u>(), angle::Span(src)); + EXPECT_EQ(dst[0], 'B'); + EXPECT_EQ(dst[1], 'A'); + EXPECT_EQ(dst[2], 'A'); + EXPECT_EQ(dst[3], 'B'); +} + +// Test that SpanMemcpy() tolerates empty src arguments. +TEST(SpanMemcpy, EmptyCopyWithin) +{ + std::vector src; + std::vector dst(4, 'B'); + angle::SpanMemcpy(angle::Span(dst).subspan<1u>(), angle::Span(src)); + EXPECT_EQ(dst[0], 'B'); + EXPECT_EQ(dst[1], 'B'); + EXPECT_EQ(dst[2], 'B'); + EXPECT_EQ(dst[3], 'B'); +} + +// Test that SpanMemcpy() tolerates copies between two empty spans. +TEST(SpanMemcpy, EmptyCopyToEmpty) +{ + std::vector src; + std::vector dst; + angle::SpanMemcpy(angle::Span(dst), angle::Span(src)); +} + +// Test that SpanMemmove() actually moves characters. +TEST(SpanMemmove, FitsWithin) +{ + std::vector src(2, 'A'); + std::vector dst(4, 'B'); + // Also show that a const src argument is acceptable. + angle::SpanMemmove(angle::Span(dst).subspan<1u>(), angle::Span(src)); + EXPECT_EQ(dst[0], 'B'); + EXPECT_EQ(dst[1], 'A'); + EXPECT_EQ(dst[2], 'A'); + EXPECT_EQ(dst[3], 'B'); +} + +// Test that SpanMemmove() tolerates empty src arguments. +TEST(SpanMemmove, EmptyCopyWithin) +{ + std::vector src; + std::vector dst(4, 'B'); + angle::SpanMemmove(angle::Span(dst).subspan<1u>(), angle::Span(src)); + EXPECT_EQ(dst[0], 'B'); + EXPECT_EQ(dst[1], 'B'); + EXPECT_EQ(dst[2], 'B'); + EXPECT_EQ(dst[3], 'B'); +} + +// Test that SpanMemmove() tolerates copies between two empty spans. +TEST(SpanMemmove, EmptyCopyToEmpty) +{ + std::vector src; + std::vector dst; + angle::SpanMemmove(angle::Span(dst), angle::Span(src)); +} + +// Test that SpanMemset() tolerates setting into an empty span. +TEST(SpanMemset, AllowsEmpty) +{ + angle::Span empty; + angle::SpanMemset(empty, 0xff); +} + +// Test that SpanMemset() writes all the bytes of a larger type. +TEST(SpanMemset, WritesAll) +{ + std::vector dst(2); + angle::SpanMemset(angle::Span(dst), 0xff); + EXPECT_EQ(dst[0], 0xffffffff); + EXPECT_EQ(dst[1], 0xffffffff); +} + +} // namespace +} // namespace angle diff --git a/src/common/spirv/spirv_instruction_builder_autogen.cpp b/src/common/spirv/spirv_instruction_builder_autogen.cpp index 88f841985de..c11d4ce895b 100644 --- a/src/common/spirv/spirv_instruction_builder_autogen.cpp +++ b/src/common/spirv/spirv_instruction_builder_autogen.cpp @@ -3212,7 +3212,7 @@ void WriteGroupNonUniformBroadcast(Blob *blob, IdResult idResult2, IdScope execution, IdRef value, - IdRef id) + IdRef invocationId) { const size_t startSize = blob->size(); blob->push_back(0); @@ -3220,7 +3220,7 @@ void WriteGroupNonUniformBroadcast(Blob *blob, blob->push_back(idResult2); blob->push_back(execution); blob->push_back(value); - blob->push_back(id); + blob->push_back(invocationId); (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupNonUniformBroadcast); } void WriteGroupNonUniformBroadcastFirst(Blob *blob, @@ -3336,7 +3336,7 @@ void WriteGroupNonUniformShuffle(Blob *blob, IdResult idResult2, IdScope execution, IdRef value, - IdRef id) + IdRef invocationId) { const size_t startSize = blob->size(); blob->push_back(0); @@ -3344,7 +3344,7 @@ void WriteGroupNonUniformShuffle(Blob *blob, blob->push_back(idResult2); blob->push_back(execution); blob->push_back(value); - blob->push_back(id); + blob->push_back(invocationId); (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupNonUniformShuffle); } void WriteGroupNonUniformShuffleXor(Blob *blob, diff --git a/src/common/spirv/spirv_instruction_builder_autogen.h b/src/common/spirv/spirv_instruction_builder_autogen.h index be90c467440..4f39bde9ed3 100644 --- a/src/common/spirv/spirv_instruction_builder_autogen.h +++ b/src/common/spirv/spirv_instruction_builder_autogen.h @@ -929,7 +929,7 @@ void WriteGroupNonUniformBroadcast(Blob *blob, IdResult idResult2, IdScope execution, IdRef value, - IdRef id); + IdRef invocationId); void WriteGroupNonUniformBroadcastFirst(Blob *blob, IdResultType idResultType1, IdResult idResult2, @@ -972,7 +972,7 @@ void WriteGroupNonUniformShuffle(Blob *blob, IdResult idResult2, IdScope execution, IdRef value, - IdRef id); + IdRef invocationId); void WriteGroupNonUniformShuffleXor(Blob *blob, IdResultType idResultType1, IdResult idResult2, diff --git a/src/common/spirv/spirv_instruction_parser_autogen.cpp b/src/common/spirv/spirv_instruction_parser_autogen.cpp index 43553203a09..f60d5877213 100644 --- a/src/common/spirv/spirv_instruction_parser_autogen.cpp +++ b/src/common/spirv/spirv_instruction_parser_autogen.cpp @@ -3792,7 +3792,7 @@ void ParseGroupNonUniformBroadcast(const uint32_t *_instruction, IdResult *idResult2, IdScope *execution, IdRef *value, - IdRef *id) + IdRef *invocationId) { spv::Op _op; uint32_t _length; @@ -3803,7 +3803,7 @@ void ParseGroupNonUniformBroadcast(const uint32_t *_instruction, *idResult2 = IdResult(_instruction[_o++]); *execution = IdScope(_instruction[_o++]); *value = IdRef(_instruction[_o++]); - *id = IdRef(_instruction[_o++]); + *invocationId = IdRef(_instruction[_o++]); } void ParseGroupNonUniformBroadcastFirst(const uint32_t *_instruction, IdResultType *idResultType1, @@ -3926,7 +3926,7 @@ void ParseGroupNonUniformShuffle(const uint32_t *_instruction, IdResult *idResult2, IdScope *execution, IdRef *value, - IdRef *id) + IdRef *invocationId) { spv::Op _op; uint32_t _length; @@ -3937,7 +3937,7 @@ void ParseGroupNonUniformShuffle(const uint32_t *_instruction, *idResult2 = IdResult(_instruction[_o++]); *execution = IdScope(_instruction[_o++]); *value = IdRef(_instruction[_o++]); - *id = IdRef(_instruction[_o++]); + *invocationId = IdRef(_instruction[_o++]); } void ParseGroupNonUniformShuffleXor(const uint32_t *_instruction, IdResultType *idResultType1, diff --git a/src/common/spirv/spirv_instruction_parser_autogen.h b/src/common/spirv/spirv_instruction_parser_autogen.h index 76250714d90..5ed5fef556b 100644 --- a/src/common/spirv/spirv_instruction_parser_autogen.h +++ b/src/common/spirv/spirv_instruction_parser_autogen.h @@ -1049,7 +1049,7 @@ void ParseGroupNonUniformBroadcast(const uint32_t *_instruction, IdResult *idResult2, IdScope *execution, IdRef *value, - IdRef *id); + IdRef *invocationId); void ParseGroupNonUniformBroadcastFirst(const uint32_t *_instruction, IdResultType *idResultType1, IdResult *idResult2, @@ -1092,7 +1092,7 @@ void ParseGroupNonUniformShuffle(const uint32_t *_instruction, IdResult *idResult2, IdScope *execution, IdRef *value, - IdRef *id); + IdRef *invocationId); void ParseGroupNonUniformShuffleXor(const uint32_t *_instruction, IdResultType *idResultType1, IdResult *idResult2, diff --git a/src/common/string_utils.cpp b/src/common/string_utils.cpp index d8c9bb0fc4d..1501a8a4641 100644 --- a/src/common/string_utils.cpp +++ b/src/common/string_utils.cpp @@ -7,12 +7,17 @@ // String helper functions. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/string_utils.h" #include #include #include #include +#include #include #include @@ -136,8 +141,13 @@ std::string GetPrefix(const std::string &input, size_t offset, char delimiter) return input.substr(offset, match - offset); } -bool HexStringToUInt(const std::string &input, unsigned int *uintOut) +bool HexStringToUInt(const std::string_view &input, unsigned int *uintOut) { + if (input.empty() || uintOut == nullptr) + { + return false; + } + unsigned int offset = 0; if (input.size() >= 2 && input[0] == '0' && input[1] == 'x') @@ -151,9 +161,22 @@ bool HexStringToUInt(const std::string &input, unsigned int *uintOut) return false; } - std::stringstream inStream(input); - inStream >> std::hex >> *uintOut; - return !inStream.fail(); + std::string_view inputWithOffset = input.substr(offset); + const auto result = std::from_chars( + inputWithOffset.data(), inputWithOffset.data() + inputWithOffset.size(), *uintOut, 16); + if (result.ec != std::errc{}) + { + return false; + } + + // A successful conversion should consume the entire input string view. + // If result.ptr is not at the end, it means there were extra characters. + if (result.ptr != inputWithOffset.data() + inputWithOffset.size()) + { + return false; + } + + return true; } bool ReadFileToString(const std::string &path, std::string *stringOut) @@ -355,4 +378,19 @@ bool NamesMatchWithWildcard(const char *glob, const char *name) return false; } +std::vector HexStringToUintVector(const std::string_view &hexStr) +{ + std::vector bin; + bin.reserve(hexStr.length() / 2); + + for (size_t index = 0; index < hexStr.length(); index += 2) + { + unsigned int hexValue; + HexStringToUInt(hexStr.substr(index, 2), &hexValue); + bin.push_back(static_cast(hexValue)); + } + + return bin; +} + } // namespace angle diff --git a/src/common/string_utils.h b/src/common/string_utils.h index 7be7efe9835..b6c13d261a6 100644 --- a/src/common/string_utils.h +++ b/src/common/string_utils.h @@ -10,6 +10,7 @@ #ifndef LIBANGLE_STRING_UTILS_H_ #define LIBANGLE_STRING_UTILS_H_ +#include #include #include @@ -45,7 +46,7 @@ std::string TrimString(const std::string &input, const std::string &trimChars); std::string GetPrefix(const std::string &input, size_t offset, const char *delimiter); std::string GetPrefix(const std::string &input, size_t offset, char delimiter); -bool HexStringToUInt(const std::string &input, unsigned int *uintOut); +bool HexStringToUInt(const std::string_view &input, unsigned int *uintOut); bool ReadFileToString(const std::string &path, std::string *stringOut); @@ -120,6 +121,8 @@ std::vector GetCachedStringsFromEnvironmentVarOrAndroidProperty( // glob can have * as wildcard bool NamesMatchWithWildcard(const char *glob, const char *name); + +std::vector HexStringToUintVector(const std::string_view &hexStr); } // namespace angle #endif // LIBANGLE_STRING_UTILS_H_ diff --git a/src/common/system_utils.h b/src/common/system_utils.h index 3f54913cb98..882bf6eaa7c 100644 --- a/src/common/system_utils.h +++ b/src/common/system_utils.h @@ -42,6 +42,7 @@ bool IsDirectory(const char *filename); bool IsFullPath(std::string dirName); bool CreateDirectories(const std::string &path); void MakeForwardSlashThePathSeparator(std::string &path); +bool IsSameFileDescriptor(int fd1, int fd2); std::string GetRootDirectory(); std::string ConcatenatePath(std::string first, std::string second); @@ -233,19 +234,6 @@ std::wstring Widen(const std::string_view &utf8); std::string StripFilenameFromPath(const std::string &path); -#if defined(ANGLE_PLATFORM_LINUX) || defined(ANGLE_PLATFORM_WINDOWS) -// Use C++ thread_local which is about 2x faster than std::this_thread::get_id() -ANGLE_INLINE ThreadId GetCurrentThreadId() -{ - thread_local int tls; - return static_cast(reinterpret_cast(&tls)); -} -ANGLE_INLINE ThreadId InvalidThreadId() -{ - return -1; -} -#else -// Default. Fastest on Android (about the same as `pthread_self` and a bit faster then `gettid`). ANGLE_INLINE ThreadId GetCurrentThreadId() { return std::this_thread::get_id(); @@ -254,7 +242,6 @@ ANGLE_INLINE ThreadId InvalidThreadId() { return ThreadId(); } -#endif void SetCurrentThreadName(const char *name); } // namespace angle diff --git a/src/common/system_utils_apple.cpp b/src/common/system_utils_apple.cpp index 84b467c93b7..1a6b26ce406 100644 --- a/src/common/system_utils_apple.cpp +++ b/src/common/system_utils_apple.cpp @@ -6,6 +6,10 @@ // system_utils_apple.cpp: Implementation of OS-specific functions for Apple platforms +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "system_utils.h" #include diff --git a/src/common/system_utils_linux.cpp b/src/common/system_utils_linux.cpp index 7dd681d2c2f..97da0bee25c 100644 --- a/src/common/system_utils_linux.cpp +++ b/src/common/system_utils_linux.cpp @@ -6,6 +6,10 @@ // system_utils_linux.cpp: Implementation of OS-specific functions for Linux +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/debug.h" #include "system_utils.h" diff --git a/src/common/system_utils_posix.cpp b/src/common/system_utils_posix.cpp index 76c5c99f0fe..1caeb18a09c 100644 --- a/src/common/system_utils_posix.cpp +++ b/src/common/system_utils_posix.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + // system_utils_posix.cpp: Implementation of POSIX OS-specific functions. #include "common/debug.h" @@ -261,6 +265,23 @@ bool IsDebuggerAttached() return false; } +bool IsSameFileDescriptor(int fd1, int fd2) +{ + struct stat stat1, stat2; + if (fstat(fd1, &stat1) < 0) + { + return false; + } + if (fstat(fd2, &stat2) < 0) + { + return false; + } + // Comparing st_ino (the unique identifier within a filesystem) and + // st_dev (the identifier of the filesystem) uniquely identifies a + // file within a POSIX-conforming system + return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); +} + void BreakDebugger() { // This could have a fuller implementation. diff --git a/src/common/system_utils_unittest.cpp b/src/common/system_utils_unittest.cpp index dcadabedf21..ecce440b0ff 100644 --- a/src/common/system_utils_unittest.cpp +++ b/src/common/system_utils_unittest.cpp @@ -5,6 +5,10 @@ // system_utils_unittest.cpp: Unit tests for ANGLE's system utility functions +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/src/common/system_utils_win32.cpp b/src/common/system_utils_win32.cpp index 713c2214528..f7423cd9aee 100644 --- a/src/common/system_utils_win32.cpp +++ b/src/common/system_utils_win32.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // system_utils_win32.cpp: Implementation of OS-specific functions for Windows. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "common/FastVector.h" #include "system_utils.h" diff --git a/src/common/third_party/xxhash/README.chromium b/src/common/third_party/xxhash/README.chromium index 93a08866e4d..7fdc1569b29 100644 --- a/src/common/third_party/xxhash/README.chromium +++ b/src/common/third_party/xxhash/README.chromium @@ -2,6 +2,7 @@ Name: xxHash URL: https://github.com/Cyan4973/xxHash Revision: 0f2dd4a1cb103e3fc8c55c855b821eb24c6d82c3 Version: 0.8.2 +Update Mechanism: Manual License: BSD-2-Clause License File: LICENSE Security Critical: yes diff --git a/src/common/unsafe_buffers.h b/src/common/unsafe_buffers.h new file mode 100644 index 00000000000..342c4e4fbd6 --- /dev/null +++ b/src/common/unsafe_buffers.h @@ -0,0 +1,37 @@ +// +// Copyright 2025 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. +// + +// unsafe_buffers.h: exempts code from unsafe buffers warnings. Based upon +// https://source.chromium.org/chromium/chromium/src/+/main:base/compiler_specific.h + +#ifndef COMMON_UNSAFE_BUFFERS_H_ +#define COMMON_UNSAFE_BUFFERS_H_ + +#if defined(__clang__) && defined(__has_attribute) +# if __has_attribute(unsafe_buffer_usage) +# define ANGLE_UNSAFE_BUFFER_USAGE [[clang::unsafe_buffer_usage]] +# endif +#endif +#if !defined(ANGLE_UNSAFE_BUFFER_USAGE) +# define ANGLE_UNSAFE_BUFFER_USAGE +#endif + +// Formatting is off so that we can put each _Pragma on its own line. +// clang-format off +#if defined(UNSAFE_BUFFERS_BUILD) +# define ANGLE_UNSAFE_BUFFERS(...) \ + _Pragma("clang unsafe_buffer_usage begin") \ + __VA_ARGS__ \ + _Pragma("clang unsafe_buffer_usage end") +#else +# define ANGLE_UNSAFE_BUFFERS(...) __VA_ARGS__ +#endif +// clang-format on + +// Like ANGLE_UNSAFE_BUFFERS(), but indicates there is a TODO() task. +#define ANGLE_UNSAFE_TODO(...) ANGLE_UNSAFE_BUFFERS(__VA_ARGS__) + +#endif // COMMON_UNSAFE_BUFFERS_H_ diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp index 35085108ad1..d1dc4c68fb1 100644 --- a/src/common/utilities.cpp +++ b/src/common/utilities.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // utilities.cpp: Conversion functions and other utility routines. #include "common/utilities.h" @@ -27,68 +31,42 @@ namespace template gl::IndexRange ComputeTypedIndexRange(const IndexType *indices, size_t count, - bool primitiveRestartEnabled, - GLuint primitiveRestartIndex) + bool primitiveRestartEnabled) { - ASSERT(count > 0); - - IndexType minIndex = 0; - IndexType maxIndex = 0; - size_t nonPrimitiveRestartIndices = 0; + constexpr IndexType primitiveRestartIndex = std::numeric_limits::max(); + IndexType minIndex = primitiveRestartIndex; + IndexType maxIndex = 0; + bool hasVertices = false; if (primitiveRestartEnabled) { - // Find the first non-primitive restart index to initialize the min and max values - size_t i = 0; - for (; i < count; i++) + for (size_t i = 0; i < count; i++) { - if (indices[i] != primitiveRestartIndex) + IndexType index = indices[i]; + if (index == primitiveRestartIndex) { - minIndex = indices[i]; - maxIndex = indices[i]; - nonPrimitiveRestartIndices++; - break; - } - } - - // Loop over the rest of the indices - for (; i < count; i++) - { - if (indices[i] != primitiveRestartIndex) - { - if (minIndex > indices[i]) - { - minIndex = indices[i]; - } - if (maxIndex < indices[i]) - { - maxIndex = indices[i]; - } - nonPrimitiveRestartIndices++; + continue; } + hasVertices = true; + minIndex = std::min(minIndex, index); + maxIndex = std::max(maxIndex, index); } } else { - minIndex = indices[0]; - maxIndex = indices[0]; - nonPrimitiveRestartIndices = count; - - for (size_t i = 1; i < count; i++) + for (size_t i = 0; i < count; i++) { - if (minIndex > indices[i]) - { - minIndex = indices[i]; - } - if (maxIndex < indices[i]) - { - maxIndex = indices[i]; - } + IndexType index = indices[i]; + minIndex = std::min(minIndex, index); + maxIndex = std::max(maxIndex, index); } + hasVertices = count > 0; } - - return gl::IndexRange(static_cast(minIndex), static_cast(maxIndex), - nonPrimitiveRestartIndices); + if (!hasVertices) + { + return gl::IndexRange(); + } + return gl::IndexRange(minIndex, maxIndex); } } // anonymous namespace @@ -623,6 +601,33 @@ bool IsMatrixType(GLenum type) return VariableRowCount(type) > 1; } +bool IsFloatScalarAndVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return true; + default: + return false; + } +} + +bool IsFloatVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return true; + default: + return false; + } +} + GLenum TransposeMatrixType(GLenum type) { if (!IsMatrixType(type)) @@ -703,16 +708,13 @@ IndexRange ComputeIndexRange(DrawElementsType indexType, { case DrawElementsType::UnsignedByte: return ComputeTypedIndexRange(static_cast(indices), count, - primitiveRestartEnabled, - GetPrimitiveRestartIndex(indexType)); + primitiveRestartEnabled); case DrawElementsType::UnsignedShort: return ComputeTypedIndexRange(static_cast(indices), count, - primitiveRestartEnabled, - GetPrimitiveRestartIndex(indexType)); + primitiveRestartEnabled); case DrawElementsType::UnsignedInt: return ComputeTypedIndexRange(static_cast(indices), count, - primitiveRestartEnabled, - GetPrimitiveRestartIndex(indexType)); + primitiveRestartEnabled); default: UNREACHABLE(); return IndexRange(); @@ -908,12 +910,18 @@ std::string ParseResourceName(const std::string &name, std::vector { size_t open = name.find_last_of('[', baseNameLength - 1); size_t close = name.find_last_of(']', baseNameLength - 1); - hasIndex = (open != std::string::npos) && (close == baseNameLength - 1); + hasIndex = + (open != std::string::npos) && (close == baseNameLength - 1) && (close != open + 1); if (hasIndex) { baseNameLength = open; if (outSubscripts) { + if (!isdigit(name[open + 1])) + { + outSubscripts->push_back(GL_INVALID_INDEX); + break; + } int index = atoi(name.substr(open + 1).c_str()); if (index >= 0) { @@ -1296,6 +1304,7 @@ bool IsExternalImageTarget(EGLenum target) { case EGL_NATIVE_BUFFER_ANDROID: case EGL_D3D11_TEXTURE_ANGLE: + case EGL_WEBGPU_TEXTURE_ANGLE: case EGL_LINUX_DMA_BUF_EXT: case EGL_METAL_TEXTURE_ANGLE: case EGL_VULKAN_IMAGE_ANGLE: @@ -1470,7 +1479,7 @@ bool IsQueryEntryPoint(EntryPoint entryPoint) } } // namespace angle -void writeFile(const char *path, const void *content, size_t size) +void writeFile(const char *path, std::string_view content) { #if !defined(ANGLE_ENABLE_WINDOWS_UWP) FILE *file = fopen(path, "w"); @@ -1480,7 +1489,7 @@ void writeFile(const char *path, const void *content, size_t size) return; } - fwrite(content, sizeof(char), size, file); + fwrite(content.data(), sizeof(char), content.size(), file); fclose(file); #else UNREACHABLE(); diff --git a/src/common/utilities.h b/src/common/utilities.h index 531d689d650..c940e6a01a5 100644 --- a/src/common/utilities.h +++ b/src/common/utilities.h @@ -9,12 +9,17 @@ #ifndef COMMON_UTILITIES_H_ #define COMMON_UTILITIES_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include #include #include +#include #include #include "angle_gl.h" @@ -46,6 +51,8 @@ bool IsImage2DType(GLenum type); bool IsAtomicCounterType(GLenum type); bool IsOpaqueType(GLenum type); bool IsMatrixType(GLenum type); +bool IsFloatScalarAndVectorType(GLenum type); +bool IsFloatVectorType(GLenum type); GLenum TransposeMatrixType(GLenum type); int VariableRegisterCount(GLenum type); int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); @@ -384,7 +391,7 @@ void FillWithNullptr(T *array) } } // namespace angle -void writeFile(const char *path, const void *data, size_t size); +void writeFile(const char *path, std::string_view content); // Get the underlying type. Useful for indexing into arrays with enum values by avoiding the clutter // of the extraneous static_cast<>() calls. diff --git a/src/common/utilities_unittest.cpp b/src/common/utilities_unittest.cpp index 9598b683d54..119e4c52d75 100644 --- a/src/common/utilities_unittest.cpp +++ b/src/common/utilities_unittest.cpp @@ -5,6 +5,10 @@ // utilities_unittest.cpp: Unit tests for ANGLE's GL utility functions +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -35,12 +39,24 @@ TEST(ParseResourceName, NegativeArrayIndex) EXPECT_EQ(GL_INVALID_INDEX, indices.back()); } +// Parsing a letter array index should result in INVALID_INDEX. +TEST(ParseResourceName, LetterArrayIndex) +{ + std::vector indices; + EXPECT_EQ("foo", gl::ParseResourceName("foo[a]", &indices)); + ASSERT_EQ(1u, indices.size()); + EXPECT_EQ(GL_INVALID_INDEX, indices.back()); +} + // Parsing no array indices should result in an empty array. TEST(ParseResourceName, NoArrayIndex) { std::vector indices; EXPECT_EQ("foo", gl::ParseResourceName("foo", &indices)); EXPECT_TRUE(indices.empty()); + + EXPECT_EQ("foo[]", gl::ParseResourceName("foo[]", &indices)); + EXPECT_TRUE(indices.empty()); } // The ParseResourceName function should work when a nullptr is passed as the indices output vector. @@ -205,4 +221,41 @@ TEST(Utilities, ConstStrLen) EXPECT_EQ(3u, n2); } +// Tests gl::ComputeIndexRange(). +TEST(Utilities, IndexRanges) +{ + constexpr auto b = gl::DrawElementsType::UnsignedByte; + uint8_t vertices1[] = {1, 2, 3, 4, 0xff, 6, 5, 7, 10, 0xff, 0xff, 0xff, 9, 8, 0xff}; + EXPECT_EQ(ComputeIndexRange(b, vertices1, 0, true), gl::IndexRange()); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 0, false), gl::IndexRange()); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 1, true), gl::IndexRange(1, 1)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 1, false), gl::IndexRange(1, 1)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 2, true), gl::IndexRange(1, 2)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 2, false), gl::IndexRange(1, 2)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 4, true), gl::IndexRange(1, 4)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 4, false), gl::IndexRange(1, 4)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 5, true), gl::IndexRange(1, 4)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 5, false), gl::IndexRange(1, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 15, true), gl::IndexRange(1, 10)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 15, false), gl::IndexRange(1, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices1, 15, false), gl::IndexRange(1, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices1 + 9, 3, false), gl::IndexRange(255, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices1 + 9, 3, true), gl::IndexRange()); + EXPECT_EQ(ComputeIndexRange(b, vertices1 + 9, 4, false), gl::IndexRange(9, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices1 + 9, 4, true), gl::IndexRange(9, 9)); + EXPECT_EQ(ComputeIndexRange(b, vertices1 + 8, 4, false), gl::IndexRange(10, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices1 + 8, 4, true), gl::IndexRange(10, 10)); + uint8_t vertices2[] = { + 0xff, + 0xff, + 2, + }; + EXPECT_EQ(ComputeIndexRange(b, vertices2, 1, true), gl::IndexRange()); + EXPECT_EQ(ComputeIndexRange(b, vertices2, 1, false), gl::IndexRange(255, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices2, 2, true), gl::IndexRange()); + EXPECT_EQ(ComputeIndexRange(b, vertices2, 2, false), gl::IndexRange(255, 255)); + EXPECT_EQ(ComputeIndexRange(b, vertices2, 3, true), gl::IndexRange(2, 2)); + EXPECT_EQ(ComputeIndexRange(b, vertices2, 3, false), gl::IndexRange(2, 255)); +} + } // anonymous namespace diff --git a/src/common/vector_utils.h b/src/common/vector_utils.h index 053fae02397..13c41378d7e 100644 --- a/src/common/vector_utils.h +++ b/src/common/vector_utils.h @@ -8,6 +8,10 @@ #ifndef COMMON_VECTOR_UTILS_H_ #define COMMON_VECTOR_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include diff --git a/src/common/vector_utils_unittest.cpp b/src/common/vector_utils_unittest.cpp index 9c1184daf49..14441b5e32f 100644 --- a/src/common/vector_utils_unittest.cpp +++ b/src/common/vector_utils_unittest.cpp @@ -6,6 +6,10 @@ // vector_utils_unittests.cpp: Unit tests for the vector utils. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "vector_utils.h" #include diff --git a/src/common/vulkan/BUILD.gn b/src/common/vulkan/BUILD.gn index 7b4ddd3757d..87d2f5a682b 100644 --- a/src/common/vulkan/BUILD.gn +++ b/src/common/vulkan/BUILD.gn @@ -10,7 +10,7 @@ if (angle_use_wayland) { } declare_args() { - angle_use_custom_libvulkan = !is_android && !is_fuchsia && !is_ggp + angle_use_custom_libvulkan = !is_android && !is_fuchsia # On real CrOS devices, we should use the system Vulkan loader. On the # ChromeOS-for-Linux build, we should use the built libvulkan because the @@ -123,7 +123,7 @@ if (angle_enable_vulkan) { if (!angle_use_vulkan_null_display) { public_deps += [ "//third_party/fuchsia-sdk/sdk/pkg/vulkan_layers:VkLayer_image_pipe_swapchain" ] } - } else if (!is_android && !is_ggp) { + } else if (!is_android) { if (angle_shared_libvulkan) { data_deps = [ "$angle_vulkan_loader_dir:libvulkan" ] } else { diff --git a/src/common/vulkan/libvulkan_loader.cpp b/src/common/vulkan/libvulkan_loader.cpp index dafe092732c..f1b7e30d5b1 100644 --- a/src/common/vulkan/libvulkan_loader.cpp +++ b/src/common/vulkan/libvulkan_loader.cpp @@ -31,7 +31,7 @@ void *OpenLibVulkan() }; constexpr SearchType kSearchTypes[] = { -// On Android, Fuchsia and GGP we use the system libvulkan. +// On Android and Fuchsia we use the system libvulkan. #if defined(ANGLE_USE_CUSTOM_LIBVULKAN) SearchType::ModuleDir, #else diff --git a/src/common/vulkan/vk_headers.h b/src/common/vulkan/vk_headers.h index d43904a1e2b..e95c4c09a4c 100644 --- a/src/common/vulkan/vk_headers.h +++ b/src/common/vulkan/vk_headers.h @@ -16,6 +16,16 @@ # include #endif +/* vulkan.h includes when VK_USE_PLATFORM_XLIB_KHR is defined + * after https://github.com/KhronosGroup/Vulkan-Headers/pull/534. + * This defines some macros which break build, so undefine them here. + */ +#undef Always +#undef Bool +#undef None +#undef Status +#undef Success + #if !defined(ANGLE_SHARED_LIBVULKAN) namespace rx @@ -43,6 +53,9 @@ extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; // VK_EXT_external_memory_host extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; +// VK_EXT_device_fault +extern PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; + // VK_EXT_host_query_reset extern PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; @@ -62,6 +75,9 @@ extern PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; extern PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; extern PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; +// VK_KHR_maintenance5 +extern PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; + // VK_KHR_external_fence_capabilities extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; @@ -91,10 +107,6 @@ extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBuffe extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; # endif -# if defined(ANGLE_PLATFORM_GGP) -extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; -# endif // defined(ANGLE_PLATFORM_GGP) - // VK_KHR_shared_presentable_image extern PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR; @@ -148,6 +160,19 @@ extern PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAtta extern PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; extern PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; +// VK_KHR_external_memory_fd +extern PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; +extern PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; + +// VK_EXT_external_memory_host +extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; + +// VK_KHR_buffer_device_address +extern PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; + +// VK_QCOM_tile_memory_heap +extern PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; + } // namespace rx #endif // ANGLE_SHARED_LIBVULKAN diff --git a/src/common/vulkan/vulkan_icd.cpp b/src/common/vulkan/vulkan_icd.cpp index f27927d37ab..70f75bcf1e6 100644 --- a/src/common/vulkan/vulkan_icd.cpp +++ b/src/common/vulkan/vulkan_icd.cpp @@ -6,6 +6,10 @@ // vulkan_icd.cpp : Helper for creating vulkan instances & selecting physical device. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "common/vulkan/vulkan_icd.h" #include @@ -116,7 +120,7 @@ ScopedVkLoaderEnvironment::ScopedVkLoaderEnvironment(bool enableDebugLayers, vk: // Changing CWD and setting environment variables makes no sense on Android, // since this code is a part of Java application there. // Android Vulkan loader doesn't need this either. -#if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_GGP) +#if !defined(ANGLE_PLATFORM_ANDROID) if (icd == vk::ICD::Mock) { if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_MOCK_ICD_JSON).c_str())) diff --git a/src/compiler.gni b/src/compiler.gni index e5fb8be1d61..d96767c6e13 100644 --- a/src/compiler.gni +++ b/src/compiler.gni @@ -58,8 +58,6 @@ angle_translator_sources = [ "src/compiler/translator/InfoSink.h", "src/compiler/translator/Initialize.cpp", "src/compiler/translator/Initialize.h", - "src/compiler/translator/InitializeDll.cpp", - "src/compiler/translator/InitializeDll.h", "src/compiler/translator/InitializeGlobals.h", "src/compiler/translator/IntermNode.cpp", "src/compiler/translator/IntermNode.h", @@ -84,6 +82,8 @@ angle_translator_sources = [ "src/compiler/translator/Severity.h", "src/compiler/translator/ShaderLang.cpp", "src/compiler/translator/ShaderVars.cpp", + "src/compiler/translator/SizeClipCullDistance.cpp", + "src/compiler/translator/SizeClipCullDistance.h", "src/compiler/translator/StaticType.h", "src/compiler/translator/Symbol.cpp", "src/compiler/translator/Symbol.h", @@ -96,22 +96,8 @@ angle_translator_sources = [ "src/compiler/translator/Types.h", "src/compiler/translator/ValidateAST.cpp", "src/compiler/translator/ValidateAST.h", - "src/compiler/translator/ValidateBarrierFunctionCall.cpp", - "src/compiler/translator/ValidateBarrierFunctionCall.h", - "src/compiler/translator/ValidateClipCullDistance.cpp", - "src/compiler/translator/ValidateClipCullDistance.h", "src/compiler/translator/ValidateGlobalInitializer.cpp", "src/compiler/translator/ValidateGlobalInitializer.h", - "src/compiler/translator/ValidateLimitations.cpp", - "src/compiler/translator/ValidateLimitations.h", - "src/compiler/translator/ValidateMaxParameters.cpp", - "src/compiler/translator/ValidateMaxParameters.h", - "src/compiler/translator/ValidateOutputs.cpp", - "src/compiler/translator/ValidateOutputs.h", - "src/compiler/translator/ValidateSwitch.cpp", - "src/compiler/translator/ValidateSwitch.h", - "src/compiler/translator/ValidateTypeSizeLimitations.cpp", - "src/compiler/translator/ValidateTypeSizeLimitations.h", "src/compiler/translator/ValidateVaryingLocations.cpp", "src/compiler/translator/ValidateVaryingLocations.h", "src/compiler/translator/VariablePacker.cpp", @@ -125,6 +111,11 @@ angle_translator_sources = [ "src/compiler/translator/glslang_tab_autogen.cpp", "src/compiler/translator/glslang_tab_autogen.h", "src/compiler/translator/hlsl/TranslatorHLSL.h", + "src/compiler/translator/ir/src/builder.h", + "src/compiler/translator/ir/src/compile.h", + "src/compiler/translator/ir/src/output/ir_to_legacy.h", + "src/compiler/translator/ir/src/output/legacy.h", + "src/compiler/translator/ir/src/pool_alloc.h", "src/compiler/translator/length_limits.h", "src/compiler/translator/msl/DriverUniformMetal.h", "src/compiler/translator/msl/TranslatorMSL.h", @@ -148,8 +139,8 @@ angle_translator_sources = [ "src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h", "src/compiler/translator/tree_ops/FoldExpressions.cpp", "src/compiler/translator/tree_ops/FoldExpressions.h", - "src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp", - "src/compiler/translator/tree_ops/ForcePrecisionQualifier.h", + "src/compiler/translator/tree_ops/GatherDefaultUniforms.cpp", + "src/compiler/translator/tree_ops/GatherDefaultUniforms.h", "src/compiler/translator/tree_ops/InitializeVariables.cpp", "src/compiler/translator/tree_ops/InitializeVariables.h", "src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp", @@ -158,12 +149,12 @@ angle_translator_sources = [ "src/compiler/translator/tree_ops/PreTransformTextureCubeGradDerivatives.h", "src/compiler/translator/tree_ops/PruneEmptyCases.cpp", "src/compiler/translator/tree_ops/PruneEmptyCases.h", - "src/compiler/translator/tree_ops/PruneInfiniteLoops.cpp", - "src/compiler/translator/tree_ops/PruneInfiniteLoops.h", "src/compiler/translator/tree_ops/PruneNoOps.cpp", "src/compiler/translator/tree_ops/PruneNoOps.h", "src/compiler/translator/tree_ops/RecordConstantPrecision.cpp", "src/compiler/translator/tree_ops/RecordConstantPrecision.h", + "src/compiler/translator/tree_ops/ReduceInterfaceBlocks.cpp", + "src/compiler/translator/tree_ops/ReduceInterfaceBlocks.h", "src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp", "src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h", "src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.cpp", @@ -178,8 +169,6 @@ angle_translator_sources = [ "src/compiler/translator/tree_ops/RemoveUnreferencedVariables.h", "src/compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.cpp", "src/compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.h", - "src/compiler/translator/tree_ops/RescopeGlobalVariables.cpp", - "src/compiler/translator/tree_ops/RescopeGlobalVariables.h", "src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.cpp", "src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h", "src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp", @@ -192,6 +181,8 @@ angle_translator_sources = [ "src/compiler/translator/tree_ops/RewriteStructSamplers.h", "src/compiler/translator/tree_ops/RewriteTexelFetchOffset.cpp", "src/compiler/translator/tree_ops/RewriteTexelFetchOffset.h", + "src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp", + "src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h", "src/compiler/translator/tree_ops/SeparateDeclarations.cpp", "src/compiler/translator/tree_ops/SeparateDeclarations.h", "src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp", @@ -202,13 +193,11 @@ angle_translator_sources = [ "src/compiler/translator/tree_ops/SplitSequenceOperator.h", "src/compiler/translator/tree_ops/glsl/RegenerateStructNames.h", "src/compiler/translator/tree_ops/glsl/RewriteRepeatedAssignToSwizzled.h", - "src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h", "src/compiler/translator/tree_ops/glsl/UseInterfaceBlockFields.h", "src/compiler/translator/tree_ops/glsl/apple/AddAndTrueToLoopCondition.h", - "src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h", "src/compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.h", - "src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h", "src/compiler/translator/tree_ops/glsl/apple/UnfoldShortCircuitAST.h", + "src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.h", "src/compiler/translator/tree_util/BuiltIn.h", "src/compiler/translator/tree_util/BuiltIn_autogen.h", "src/compiler/translator/tree_util/DriverUniform.cpp", @@ -271,21 +260,16 @@ angle_translator_glsl_sources = [ "src/compiler/translator/glsl/VersionGLSL.cpp", "src/compiler/translator/tree_ops/glsl/RegenerateStructNames.cpp", "src/compiler/translator/tree_ops/glsl/RewriteRepeatedAssignToSwizzled.cpp", - "src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.cpp", "src/compiler/translator/tree_ops/glsl/UseInterfaceBlockFields.cpp", ] angle_translator_glsl_apple_sources = [ "src/compiler/translator/tree_ops/glsl/apple/AddAndTrueToLoopCondition.cpp", - "src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.cpp", "src/compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.cpp", - "src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.cpp", "src/compiler/translator/tree_ops/glsl/apple/UnfoldShortCircuitAST.cpp", ] angle_translator_hlsl_sources = [ "src/compiler/translator/hlsl/ASTMetadataHLSL.cpp", "src/compiler/translator/hlsl/ASTMetadataHLSL.h", - "src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.cpp", - "src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.h", "src/compiler/translator/hlsl/BuiltInFunctionEmulatorHLSL.cpp", "src/compiler/translator/hlsl/BuiltInFunctionEmulatorHLSL.h", "src/compiler/translator/hlsl/ImageFunctionHLSL.cpp", @@ -294,10 +278,6 @@ angle_translator_hlsl_sources = [ "src/compiler/translator/hlsl/OutputHLSL.h", "src/compiler/translator/hlsl/ResourcesHLSL.cpp", "src/compiler/translator/hlsl/ResourcesHLSL.h", - "src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.cpp", - "src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.h", - "src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.cpp", - "src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.h", "src/compiler/translator/hlsl/StructureHLSL.cpp", "src/compiler/translator/hlsl/StructureHLSL.h", "src/compiler/translator/hlsl/TextureFunctionHLSL.cpp", @@ -309,10 +289,6 @@ angle_translator_hlsl_sources = [ "src/compiler/translator/hlsl/emulated_builtin_functions_hlsl_autogen.cpp", "src/compiler/translator/tree_ops/hlsl/AddDefaultReturnStatements.cpp", "src/compiler/translator/tree_ops/hlsl/AddDefaultReturnStatements.h", - "src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.cpp", - "src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h", - "src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.cpp", - "src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.h", "src/compiler/translator/tree_ops/hlsl/ArrayReturnValueToOutParameter.cpp", "src/compiler/translator/tree_ops/hlsl/ArrayReturnValueToOutParameter.h", "src/compiler/translator/tree_ops/hlsl/BreakVariableAliasingInInnerLoops.cpp", @@ -323,12 +299,8 @@ angle_translator_hlsl_sources = [ "src/compiler/translator/tree_ops/hlsl/RecordUniformBlocksWithLargeArrayMember.h", "src/compiler/translator/tree_ops/hlsl/RemoveSwitchFallThrough.cpp", "src/compiler/translator/tree_ops/hlsl/RemoveSwitchFallThrough.h", - "src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.cpp", - "src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.h", "src/compiler/translator/tree_ops/hlsl/RewriteElseBlocks.cpp", "src/compiler/translator/tree_ops/hlsl/RewriteElseBlocks.h", - "src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.cpp", - "src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.h", "src/compiler/translator/tree_ops/hlsl/RewriteUnaryMinusOperatorInt.cpp", "src/compiler/translator/tree_ops/hlsl/RewriteUnaryMinusOperatorInt.h", "src/compiler/translator/tree_ops/hlsl/SeparateArrayConstructorStatements.cpp", @@ -370,6 +342,8 @@ angle_translator_lib_spirv_sources = [ "src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.h", "src/compiler/translator/tree_ops/spirv/RewriteR32fImages.cpp", "src/compiler/translator/tree_ops/spirv/RewriteR32fImages.h", + "src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.cpp", + "src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.h", ] angle_translator_essl_symbol_table_sources = [ @@ -418,6 +392,7 @@ angle_translator_lib_msl_sources = [ "src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.h", "src/compiler/translator/tree_ops/msl/ConvertUnsupportedConstructorsToFunctionCalls.cpp", "src/compiler/translator/tree_ops/msl/ConvertUnsupportedConstructorsToFunctionCalls.h", + "src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.cpp", "src/compiler/translator/tree_ops/msl/FixTypeConstructors.cpp", "src/compiler/translator/tree_ops/msl/FixTypeConstructors.h", "src/compiler/translator/tree_ops/msl/GuardFragDepthWrite.cpp", @@ -426,8 +401,8 @@ angle_translator_lib_msl_sources = [ "src/compiler/translator/tree_ops/msl/HoistConstants.h", "src/compiler/translator/tree_ops/msl/IntroduceVertexIndexID.cpp", "src/compiler/translator/tree_ops/msl/IntroduceVertexIndexID.h", - "src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.cpp", - "src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.h", + "src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.cpp", + "src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.h", "src/compiler/translator/tree_ops/msl/RewriteCaseDeclarations.cpp", "src/compiler/translator/tree_ops/msl/RewriteCaseDeclarations.h", "src/compiler/translator/tree_ops/msl/RewriteInterpolants.cpp", @@ -445,6 +420,14 @@ angle_translator_lib_msl_sources = [ ] angle_translator_lib_wgsl_sources = [ + "src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.cpp", + "src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.h", + "src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.cpp", + "src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.h", + "src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.cpp", + "src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.h", + "src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.cpp", + "src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h", "src/compiler/translator/wgsl/OutputUniformBlocks.cpp", "src/compiler/translator/wgsl/OutputUniformBlocks.h", "src/compiler/translator/wgsl/RewritePipelineVariables.cpp", @@ -452,6 +435,15 @@ angle_translator_lib_wgsl_sources = [ "src/compiler/translator/wgsl/TranslatorWGSL.cpp", "src/compiler/translator/wgsl/Utils.cpp", "src/compiler/translator/wgsl/Utils.h", + "src/compiler/translator/wgsl/WGSLProgramPrelude.cpp", + "src/compiler/translator/wgsl/WGSLProgramPrelude.h", +] + +angle_translator_lib_ir_sources = [ + "src/compiler/translator/ir/src/builder.cpp", + "src/compiler/translator/ir/src/compile.cpp", + "src/compiler/translator/ir/src/output/ir_to_legacy.cpp", + "src/compiler/translator/ir/src/pool_alloc.cpp", ] angle_preprocessor_sources = [ diff --git a/src/compiler/fuzz/translator_fuzzer.cpp b/src/compiler/fuzz/translator_fuzzer.cpp index 5ace655c9b7..eda0aceb37c 100644 --- a/src/compiler/fuzz/translator_fuzzer.cpp +++ b/src/compiler/fuzz/translator_fuzzer.cpp @@ -6,6 +6,10 @@ // translator_fuzzer.cpp: A libfuzzer fuzzer for the shader translator. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include @@ -83,7 +87,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } - if (spec != SH_GLES2_SPEC && type != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC && + if (spec != SH_GLES2_SPEC && spec != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC && spec != SH_WEBGL2_SPEC) { return 0; @@ -93,10 +97,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) bool hasUnsupportedOptions = false; - const bool hasMacGLSLOptions = options.rewriteFloatUnaryMinusOperator || - options.addAndTrueToLoopCondition || - options.rewriteDoWhileLoops || options.unfoldShortCircuit || - options.rewriteRowMajorMatrices; + const bool hasMacGLSLOptions = options.addAndTrueToLoopCondition || + options.unfoldShortCircuit || options.rewriteRowMajorMatrices; if (!IsOutputGLSL(shaderOutput) && !IsOutputESSL(shaderOutput)) { @@ -113,10 +115,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) hasUnsupportedOptions = hasUnsupportedOptions || hasMacGLSLOptions; #endif } + if (!IsOutputESSL(shaderOutput)) + { + hasUnsupportedOptions = hasUnsupportedOptions || options.skipAllValidationAndTransforms; + } if (!IsOutputSPIRV(shaderOutput)) { - hasUnsupportedOptions = hasUnsupportedOptions || options.useSpecializationConstant || - options.addVulkanXfbEmulationSupportCode || + hasUnsupportedOptions = hasUnsupportedOptions || options.addVulkanXfbEmulationSupportCode || options.roundOutputAfterDithering || options.addAdvancedBlendEquationsEmulation; } @@ -127,6 +132,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) options.allowTranslateUniformBlockToStructuredBuffer || options.rewriteIntegerUnaryMinusOperator; } + if (!IsOutputMSL(shaderOutput)) + { + hasUnsupportedOptions = hasUnsupportedOptions || options.ensureLoopForwardProgress; + } // If there are any options not supported with this output, don't attempt to run the translator. if (hasUnsupportedOptions) @@ -139,6 +148,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) static_cast(options.pls.fragmentSyncType) % static_cast(ShFragmentSynchronizationType::InvalidEnum)); + // Force enable options that are required by the output generators. + if (IsOutputSPIRV(shaderOutput)) + { + options.removeInactiveVariables = true; + } + if (IsOutputMSL(shaderOutput)) + { + options.removeInactiveVariables = true; + } + std::vector validOutputs; validOutputs.push_back(SH_ESSL_OUTPUT); validOutputs.push_back(SH_GLSL_COMPATIBILITY_OUTPUT); @@ -204,7 +223,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) resources.EXT_frag_depth = 1; resources.EXT_shader_texture_lod = 1; resources.EXT_shader_framebuffer_fetch = 1; - resources.NV_shader_framebuffer_fetch = 1; resources.ARM_shader_framebuffer_fetch = 1; resources.ARM_shader_framebuffer_fetch_depth_stencil = 1; resources.EXT_YUV_target = 1; @@ -228,9 +246,32 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) auto &translator = (*translators)[key]; + // Enable options that any security-sensitive application should enable, otherwise it's easy to + // trigger various inactionable errors. options.limitExpressionComplexity = true; + options.limitCallStackDepth = true; + options.rejectWebglShadersWithLargeVariables = true; + options.rejectWebglShadersWithUndefinedBehavior = true; const char *shaderStrings[] = {reinterpret_cast(data)}; - translator->compile(shaderStrings, 1, options); + + // Dump the string being passed to the compiler to ease debugging. + // The string is written char-by-char and unwanted characters are replaced with whitespace. + // This is because characters such as \r can hide the shader contents. + std::cerr << "\nCompile input with unprintable characters turned to whitespace:\n"; + for (const char *c = shaderStrings[0]; *c; ++c) + { + if (*c < ' ' && *c != '\n') + { + std::cerr << ' '; + } + else + { + std::cerr << *c; + } + } + std::cerr << "\nEnd of compile input.\n\n"; + + translator->compile(shaderStrings, options); return 0; } diff --git a/src/compiler/preprocessor/Input.cpp b/src/compiler/preprocessor/Input.cpp index 2ddb9467d24..0fd51002b6f 100644 --- a/src/compiler/preprocessor/Input.cpp +++ b/src/compiler/preprocessor/Input.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/preprocessor/Input.h" #include diff --git a/src/compiler/preprocessor/Input.h b/src/compiler/preprocessor/Input.h index 6f42a112d4e..ab9fd90a4b5 100644 --- a/src/compiler/preprocessor/Input.h +++ b/src/compiler/preprocessor/Input.h @@ -7,6 +7,10 @@ #ifndef COMPILER_PREPROCESSOR_INPUT_H_ #define COMPILER_PREPROCESSOR_INPUT_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include diff --git a/src/compiler/preprocessor/preprocessor.l b/src/compiler/preprocessor/preprocessor.l index cca479bd1b2..fac90fe4050 100644 --- a/src/compiler/preprocessor/preprocessor.l +++ b/src/compiler/preprocessor/preprocessor.l @@ -23,6 +23,9 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN scripts/run_code_generation.py // preprocessor.l: // Lexer for the OpenGL shading language preprocessor. +#ifdef UNSAFE_BUFFERS_BUILD +#pragma allow_unsafe_buffers +#endif } %{ diff --git a/src/compiler/preprocessor/preprocessor.y b/src/compiler/preprocessor/preprocessor.y index 500a76fcf11..8c0a94e4850 100644 --- a/src/compiler/preprocessor/preprocessor.y +++ b/src/compiler/preprocessor/preprocessor.y @@ -208,8 +208,7 @@ expression stream << $1 << " >> " << $3; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_UNDEFINED_SHIFT, - context->token->location, - text.c_str()); + context->token->location, text); *(context->valid) = false; } $$ = static_cast(0); @@ -233,8 +232,7 @@ expression stream << $1 << " << " << $3; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_UNDEFINED_SHIFT, - context->token->location, - text.c_str()); + context->token->location, text); *(context->valid) = false; } $$ = static_cast(0); @@ -261,8 +259,7 @@ expression stream << $1 << " % " << $3; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_DIVISION_BY_ZERO, - context->token->location, - text.c_str()); + context->token->location, text); *(context->valid) = false; } $$ = static_cast(0); @@ -287,8 +284,7 @@ expression stream << $1 << " / " << $3; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_DIVISION_BY_ZERO, - context->token->location, - text.c_str()); + context->token->location, text); *(context->valid) = false; } $$ = static_cast(0); diff --git a/src/compiler/preprocessor/preprocessor_lex_autogen.cpp b/src/compiler/preprocessor/preprocessor_lex_autogen.cpp index a9e066d0b8a..e7bfcd56792 100644 --- a/src/compiler/preprocessor/preprocessor_lex_autogen.cpp +++ b/src/compiler/preprocessor/preprocessor_lex_autogen.cpp @@ -9,6 +9,10 @@ // preprocessor.l: // Lexer for the OpenGL shading language preprocessor. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ @@ -1008,13 +1012,19 @@ YY_DECL #endif if (!yyg->yy_start) + { yyg->yy_start = 1; /* first start state */ + } if (!yyin) + { yyin = stdin; + } if (!yyout) + { yyout = stdout; + } if (!YY_CURRENT_BUFFER) { @@ -1055,7 +1065,9 @@ YY_DECL { yy_current_state = (int)yy_def[yy_current_state]; if (yy_current_state >= 95) + { yy_c = yy_meta[yy_c]; + } } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; @@ -1452,6 +1464,7 @@ YY_DECL } else + { switch (yy_get_next_buffer(yyscanner)) { case EOB_ACT_END_OF_FILE: @@ -1478,7 +1491,9 @@ YY_DECL else { if (!yyg->yy_did_buffer_switch_on_eof) + { YY_NEW_FILE; + } } break; } @@ -1502,14 +1517,15 @@ YY_DECL yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } + } break; } default: YY_FATAL_ERROR("fatal flex scanner internal error--no action found"); } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ + } /* end of scanning one token */ + } /* end of user's declarations */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer @@ -1528,7 +1544,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) int ret_val; if (yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1]) + { YY_FATAL_ERROR("fatal flex scanner internal error--end of buffer missed"); + } if (YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0) { /* Don't try to fill the buffer, so this is an EOF. */ @@ -1555,13 +1573,17 @@ static int yy_get_next_buffer(yyscan_t yyscanner) number_to_move = (int)(yyg->yy_c_buf_p - yyg->yytext_ptr - 1); for (i = 0; i < number_to_move; ++i) + { *(dest++) = *(source++); + } if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING) + { /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + } else { @@ -1580,20 +1602,28 @@ static int yy_get_next_buffer(yyscan_t yyscanner) int new_size = b->yy_buf_size * 2; if (new_size <= 0) + { b->yy_buf_size += b->yy_buf_size / 8; + } else + { b->yy_buf_size *= 2; + } b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *)b->yy_ch_buf, (yy_size_t)(b->yy_buf_size + 2), yyscanner); } else + { /* Can't grow it, we don't own it. */ b->yy_ch_buf = NULL; + } if (!b->yy_ch_buf) + { YY_FATAL_ERROR("fatal error - scanner input buffer overflow"); + } yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; @@ -1601,7 +1631,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) } if (num_to_read > YY_READ_BUF_SIZE) + { num_to_read = YY_READ_BUF_SIZE; + } /* Read in more data. */ yy_size_t ret = 0; @@ -1627,7 +1659,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) } else + { ret_val = EOB_ACT_CONTINUE_SCAN; + } if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { @@ -1636,7 +1670,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *)yyrealloc( (void *)YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t)new_size, yyscanner); if (!YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + { YY_FATAL_ERROR("out of dynamic memory in yy_get_next_buffer()"); + } /* "- 2" to take care of EOB's */ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int)(new_size - 2); } @@ -1672,7 +1708,9 @@ static yy_state_type yy_get_previous_state(yyscan_t yyscanner) { yy_current_state = (int)yy_def[yy_current_state]; if (yy_current_state >= 95) + { yy_c = yy_meta[yy_c]; + } } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } @@ -1702,7 +1740,9 @@ static yy_state_type yy_try_NUL_trans(yy_state_type yy_current_state, yyscan_t y { yy_current_state = (int)yy_def[yy_current_state]; if (yy_current_state >= 95) + { yy_c = yy_meta[yy_c]; + } } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 94); @@ -1735,8 +1775,10 @@ static int input(yyscan_t yyscanner) * valid NUL; if not, then we've hit the end of the buffer. */ if (yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]) + { /* This was really a NUL. */ *yyg->yy_c_buf_p = '\0'; + } else { /* need more input */ @@ -1764,10 +1806,14 @@ static int input(yyscan_t yyscanner) case EOB_ACT_END_OF_FILE: { if (yywrap(yyscanner)) + { return 0; + } if (!yyg->yy_did_buffer_switch_on_eof) + { YY_NEW_FILE; + } # ifdef __cplusplus return yyinput(yyscanner); # else @@ -1824,7 +1870,9 @@ void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) */ yyensure_buffer_stack(yyscanner); if (YY_CURRENT_BUFFER == new_buffer) + { return; + } if (YY_CURRENT_BUFFER) { @@ -1866,7 +1914,9 @@ YY_BUFFER_STATE yy_create_buffer(FILE *file, int size, yyscan_t yyscanner) b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state), yyscanner); if (!b) + { YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + } b->yy_buf_size = size; @@ -1875,7 +1925,9 @@ YY_BUFFER_STATE yy_create_buffer(FILE *file, int size, yyscan_t yyscanner) */ b->yy_ch_buf = (char *)yyalloc((yy_size_t)(b->yy_buf_size + 2), yyscanner); if (!b->yy_ch_buf) + { YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + } b->yy_is_our_buffer = 1; @@ -1893,13 +1945,19 @@ void yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!b) + { return; + } if (b == YY_CURRENT_BUFFER) /* Not sure if we should pop here. */ + { YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE)0; + } if (b->yy_is_our_buffer) + { yyfree((void *)b->yy_ch_buf, yyscanner); + } yyfree((void *)b, yyscanner); } @@ -1942,7 +2000,9 @@ void yy_flush_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!b) + { return; + } b->yy_n_chars = 0; @@ -1959,7 +2019,9 @@ void yy_flush_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) b->yy_buffer_status = YY_BUFFER_NEW; if (b == YY_CURRENT_BUFFER) + { yy_load_buffer_state(yyscanner); + } } /** Pushes the new state onto the stack. The new state becomes @@ -1972,7 +2034,9 @@ void yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (new_buffer == NULL) + { return; + } yyensure_buffer_stack(yyscanner); @@ -1987,7 +2051,9 @@ void yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) + { yyg->yy_buffer_stack_top++; + } YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ @@ -2003,12 +2069,16 @@ void yypop_buffer_state(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!YY_CURRENT_BUFFER) + { return; + } yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) + { --yyg->yy_buffer_stack_top; + } if (YY_CURRENT_BUFFER) { @@ -2036,7 +2106,9 @@ static void yyensure_buffer_stack(yyscan_t yyscanner) yyg->yy_buffer_stack = (struct yy_buffer_state **)yyalloc( num_to_alloc * sizeof(struct yy_buffer_state *), yyscanner); if (!yyg->yy_buffer_stack) + { YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + } memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state *)); @@ -2055,7 +2127,9 @@ static void yyensure_buffer_stack(yyscan_t yyscanner) yyg->yy_buffer_stack = (struct yy_buffer_state **)yyrealloc( yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state *), yyscanner); if (!yyg->yy_buffer_stack) + { YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + } /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, @@ -2076,12 +2150,16 @@ YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size, yyscan_t yyscanner) if (size < 2 || base[size - 2] != YY_END_OF_BUFFER_CHAR || base[size - 1] != YY_END_OF_BUFFER_CHAR) + { /* They forgot to leave room for the EOB's. */ return NULL; + } b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state), yyscanner); if (!b) + { YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()"); + } b->yy_buf_size = (int)(size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; @@ -2130,16 +2208,22 @@ YY_BUFFER_STATE yy_scan_bytes(const char *yybytes, int _yybytes_len, yyscan_t yy n = (yy_size_t)(_yybytes_len + 2); buf = (char *)yyalloc(n, yyscanner); if (!buf) + { YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()"); + } for (i = 0; i < _yybytes_len; ++i) + { buf[i] = yybytes[i]; + } buf[_yybytes_len] = buf[_yybytes_len + 1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf, n, yyscanner); if (!b) + { YY_FATAL_ERROR("bad buffer in yy_scan_bytes()"); + } /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -2196,7 +2280,9 @@ int yyget_lineno(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!YY_CURRENT_BUFFER) + { return 0; + } return yylineno; } @@ -2209,7 +2295,9 @@ int yyget_column(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!YY_CURRENT_BUFFER) + { return 0; + } return yycolumn; } @@ -2271,7 +2359,9 @@ void yyset_lineno(int _line_number, yyscan_t yyscanner) /* lineno is only valid if an input buffer exists. */ if (!YY_CURRENT_BUFFER) + { YY_FATAL_ERROR("yyset_lineno called with no buffer"); + } yylineno = _line_number; } @@ -2286,7 +2376,9 @@ void yyset_column(int _column_no, yyscan_t yyscanner) /* column is only valid if an input buffer exists. */ if (!YY_CURRENT_BUFFER) + { YY_FATAL_ERROR("yyset_column called with no buffer"); + } yycolumn = _column_no; } @@ -2487,7 +2579,9 @@ static void yy_flex_strncpy(char *s1, const char *s2, int n, yyscan_t yyscanner) int i; for (i = 0; i < n; ++i) + { s1[i] = s2[i]; + } } #endif @@ -2552,7 +2646,9 @@ Tokenizer::~Tokenizer() bool Tokenizer::init(size_t count, const char *const string[], const int length[]) { if ((count > 0) && (string == 0)) + { return false; + } mContext.input = Input(count, string, length); return initScanner(); @@ -2607,7 +2703,9 @@ void Tokenizer::lex(Token *token) bool Tokenizer::initScanner() { if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle)) + { return false; + } yyrestart(0, mHandle); return true; @@ -2616,7 +2714,9 @@ bool Tokenizer::initScanner() void Tokenizer::destroyScanner() { if (mHandle == nullptr) + { return; + } yylex_destroy(mHandle); mHandle = nullptr; diff --git a/src/compiler/preprocessor/preprocessor_tab_autogen.cpp b/src/compiler/preprocessor/preprocessor_tab_autogen.cpp index d03039602a4..cfb4bc1b2a0 100644 --- a/src/compiler/preprocessor/preprocessor_tab_autogen.cpp +++ b/src/compiler/preprocessor/preprocessor_tab_autogen.cpp @@ -604,8 +604,8 @@ static const yytype_int8 yytranslate[] = { #if PPDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = {0, 114, 114, 121, 122, 133, 133, 154, 154, 175, - 178, 181, 184, 187, 190, 193, 196, 199, 202, 227, - 249, 252, 255, 281, 308, 311, 314, 317, 329, 332}; + 178, 181, 184, 187, 190, 193, 196, 199, 202, 226, + 247, 250, 253, 278, 304, 307, 310, 313, 325, 328}; #endif /** Accessing symbol of state STATE. */ @@ -801,7 +801,9 @@ static void yy_symbol_value_print(FILE *yyo, YY_USE(yyoutput); YY_USE(context); if (!yyvaluep) + { return; + } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE(yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END @@ -910,7 +912,9 @@ static void yydestruct(const char *yymsg, YY_USE(yyvaluep); YY_USE(context); if (!yymsg) + { yymsg = "Deleting"; + } YY_SYMBOL_PRINT(yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN @@ -1024,22 +1028,30 @@ int yyparse(Context *context) # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) + { YYNOMEM; + } yystacksize *= 2; if (YYMAXDEPTH < yystacksize) + { yystacksize = YYMAXDEPTH; + } { yy_state_t *yyss1 = yyss; union yyalloc *yyptr = YY_CAST( union yyalloc *, YYSTACK_ALLOC(YY_CAST(YYSIZE_T, YYSTACK_BYTES(yystacksize)))); if (!yyptr) + { YYNOMEM; + } YYSTACK_RELOCATE(yyss_alloc, yyss); YYSTACK_RELOCATE(yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) + { YYSTACK_FREE(yyss1); + } } # endif @@ -1051,12 +1063,16 @@ int yyparse(Context *context) YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) + { YYABORT; + } } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ if (yystate == YYFINAL) + { YYACCEPT; + } goto yybackup; @@ -1070,7 +1086,9 @@ int yyparse(Context *context) /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default(yyn)) + { goto yydefault; + } /* Not known => get a lookahead token if don't already have one. */ @@ -1107,12 +1125,16 @@ int yyparse(Context *context) detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + { goto yydefault; + } yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error(yyn)) + { goto yyerrlab; + } yyn = -yyn; goto yyreduce; } @@ -1120,7 +1142,9 @@ int yyparse(Context *context) /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) + { yyerrstatus--; + } /* Shift the lookahead token. */ YY_SYMBOL_PRINT("Shifting", yytoken, &yylval, &yylloc); @@ -1139,7 +1163,9 @@ int yyparse(Context *context) yydefault: yyn = yydefact[yystate]; if (yyn == 0) + { goto yyerrlab; + } goto yyreduce; /*-----------------------------. @@ -1303,7 +1329,7 @@ int yyparse(Context *context) stream << yyvsp[-2] << " >> " << yyvsp[0]; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_UNDEFINED_SHIFT, - context->token->location, text.c_str()); + context->token->location, text); *(context->valid) = false; } yyval = static_cast(0); @@ -1330,7 +1356,7 @@ int yyparse(Context *context) stream << yyvsp[-2] << " << " << yyvsp[0]; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_UNDEFINED_SHIFT, - context->token->location, text.c_str()); + context->token->location, text); *(context->valid) = false; } yyval = static_cast(0); @@ -1366,7 +1392,7 @@ int yyparse(Context *context) stream << yyvsp[-2] << " % " << yyvsp[0]; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_DIVISION_BY_ZERO, - context->token->location, text.c_str()); + context->token->location, text); *(context->valid) = false; } yyval = static_cast(0); @@ -1394,7 +1420,7 @@ int yyparse(Context *context) stream << yyvsp[-2] << " / " << yyvsp[0]; std::string text = stream.str(); context->diagnostics->report(angle::pp::Diagnostics::PP_DIVISION_BY_ZERO, - context->token->location, text.c_str()); + context->token->location, text); *(context->valid) = false; } yyval = static_cast(0); @@ -1514,7 +1540,9 @@ int yyparse(Context *context) { /* Return failure if at end of input. */ if (yychar == PPEOF) + { YYABORT; + } } else { @@ -1534,7 +1562,9 @@ int yyparse(Context *context) /* Pacify compilers when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (0) + { YYERROR; + } ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered @@ -1562,13 +1592,17 @@ int yyparse(Context *context) { yyn = yytable[yyn]; if (0 < yyn) + { break; + } } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) + { YYABORT; + } yydestruct("Error: popping", YY_ACCESSING_SYMBOL(yystate), yyvsp, context); YYPOPSTACK(1); @@ -1630,7 +1664,9 @@ int yyparse(Context *context) } #ifndef yyoverflow if (yyss != yyssa) + { YYSTACK_FREE(yyss); + } #endif return yyresult; diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h index abb18546387..9267092cdf2 100644 --- a/src/compiler/translator/BaseTypes.h +++ b/src/compiler/translator/BaseTypes.h @@ -89,7 +89,6 @@ enum TBasicType EbtSamplerBuffer, EbtSamplerCubeArray, EbtSamplerCubeArrayShadow, - EbtSampler2DRectShadow, EbtISampler2DRect, EbtISamplerBuffer, EbtISamplerCubeArray, @@ -105,29 +104,20 @@ enum TBasicType EbtImage3D, EbtImage2DArray, EbtImageCube, - EbtImage2DMS, - EbtImage2DMSArray, EbtImageCubeArray, - EbtImageRect, EbtImageBuffer, EbtIImage2D, EbtIImage3D, EbtIImage2DArray, EbtIImageCube, - EbtIImage2DMS, - EbtIImage2DMSArray, EbtIImageCubeArray, - EbtIImageRect, EbtIImageBuffer, EbtGuardUIntImageBegin, EbtUImage2D = EbtGuardUIntImageBegin, EbtUImage3D, EbtUImage2DArray, EbtUImageCube, - EbtUImage2DMS, - EbtUImage2DMSArray, EbtUImageCubeArray, - EbtUImageRect, EbtUImageBuffer, EbtGuardUIntImageEnd = EbtUImageBuffer, EbtGuardImageEnd = EbtGuardUIntImageEnd, @@ -271,7 +261,6 @@ inline bool IsIntegerSampler(TBasicType type) case EbtSamplerBuffer: case EbtSamplerCubeArray: case EbtSamplerCubeArrayShadow: - case EbtSampler2DRectShadow: case EbtSamplerVideoWEBGL: return false; default: @@ -343,22 +332,6 @@ inline bool IsSamplerMS(TBasicType type) return IsSampler2DMS(type) || IsSampler2DMSArray(type); } -inline bool IsImageMS(TBasicType type) -{ - switch (type) - { - case EbtImage2DMS: - case EbtImage2DMSArray: - case EbtIImage2DMS: - case EbtIImage2DMSArray: - case EbtUImage2DMS: - case EbtUImage2DMSArray: - return true; - default: - return false; - } -} - inline bool IsFloatImage(TBasicType type) { switch (type) @@ -367,10 +340,7 @@ inline bool IsFloatImage(TBasicType type) case EbtImage3D: case EbtImage2DArray: case EbtImageCube: - case EbtImage2DMS: - case EbtImage2DMSArray: case EbtImageCubeArray: - case EbtImageRect: case EbtImageBuffer: return true; default: @@ -389,10 +359,7 @@ inline bool IsIntegerImage(TBasicType type) case EbtIImage3D: case EbtIImage2DArray: case EbtIImageCube: - case EbtIImage2DMS: - case EbtIImage2DMSArray: case EbtIImageCubeArray: - case EbtIImageRect: case EbtIImageBuffer: return true; default: @@ -411,10 +378,7 @@ inline bool IsUnsignedImage(TBasicType type) case EbtUImage3D: case EbtUImage2DArray: case EbtUImageCube: - case EbtUImage2DMS: - case EbtUImage2DMSArray: case EbtUImageCubeArray: - case EbtUImageRect: case EbtUImageBuffer: return true; default: @@ -436,7 +400,6 @@ inline bool IsSampler2D(TBasicType type) case EbtSampler2DRect: case EbtISampler2DRect: case EbtUSampler2DRect: - case EbtSampler2DRectShadow: case EbtSamplerExternalOES: case EbtSamplerExternal2DY2YEXT: case EbtSampler2DShadow: @@ -506,7 +469,6 @@ inline bool IsSamplerCube(TBasicType type) case EbtSamplerBuffer: case EbtSamplerCubeArray: case EbtSamplerCubeArrayShadow: - case EbtSampler2DRectShadow: case EbtISampler2DRect: case EbtISamplerBuffer: case EbtISamplerCubeArray: @@ -554,7 +516,6 @@ inline bool IsSampler3D(TBasicType type) case EbtSamplerBuffer: case EbtSamplerCubeArray: case EbtSamplerCubeArrayShadow: - case EbtSampler2DRectShadow: case EbtISampler2DRect: case EbtISamplerBuffer: case EbtISamplerCubeArray: @@ -604,7 +565,6 @@ inline bool IsSamplerArray(TBasicType type) case EbtISampler2DMS: case EbtUSampler2DMS: case EbtSamplerBuffer: - case EbtSampler2DRectShadow: case EbtISampler2DRect: case EbtISamplerBuffer: case EbtUSampler2DRect: @@ -618,6 +578,53 @@ inline bool IsSamplerArray(TBasicType type) return false; } +inline bool IsSampler2DArray(TBasicType type) +{ + switch (type) + { + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DMSArray: + case EbtISampler2DMSArray: + case EbtUSampler2DMSArray: + case EbtSampler2DArrayShadow: + return true; + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DRect: + case EbtISampler2DRect: + case EbtUSampler2DRect: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DShadow: + case EbtSampler2DMS: + case EbtISampler2DMS: + case EbtUSampler2DMS: + case EbtSamplerVideoWEBGL: + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCube: + case EbtSamplerCubeShadow: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + inline bool IsSamplerBuffer(TBasicType type) { switch (type) @@ -639,7 +646,6 @@ inline bool IsShadowSampler(TBasicType type) case EbtSamplerCubeShadow: case EbtSampler2DArrayShadow: case EbtSamplerCubeArrayShadow: - case EbtSampler2DRectShadow: return true; case EbtISampler2D: case EbtISampler3D: @@ -686,9 +692,6 @@ inline bool IsImage2D(TBasicType type) case EbtImage2D: case EbtIImage2D: case EbtUImage2D: - case EbtImage2DMS: - case EbtIImage2DMS: - case EbtUImage2DMS: return true; case EbtImage3D: case EbtIImage3D: @@ -699,15 +702,9 @@ inline bool IsImage2D(TBasicType type) case EbtImageCube: case EbtIImageCube: case EbtUImageCube: - case EbtImage2DMSArray: - case EbtIImage2DMSArray: - case EbtUImage2DMSArray: case EbtImageCubeArray: case EbtIImageCubeArray: case EbtUImageCubeArray: - case EbtImageRect: - case EbtIImageRect: - case EbtUImageRect: case EbtImageBuffer: case EbtIImageBuffer: case EbtUImageBuffer: @@ -736,18 +733,9 @@ inline bool IsImage3D(TBasicType type) case EbtImageCube: case EbtIImageCube: case EbtUImageCube: - case EbtImage2DMS: - case EbtIImage2DMS: - case EbtUImage2DMS: - case EbtImage2DMSArray: - case EbtIImage2DMSArray: - case EbtUImage2DMSArray: case EbtImageCubeArray: case EbtIImageCubeArray: case EbtUImageCubeArray: - case EbtImageRect: - case EbtIImageRect: - case EbtUImageRect: case EbtImageBuffer: case EbtIImageBuffer: case EbtUImageBuffer: @@ -766,9 +754,6 @@ inline bool IsImage2DArray(TBasicType type) case EbtImage2DArray: case EbtIImage2DArray: case EbtUImage2DArray: - case EbtImage2DMSArray: - case EbtIImage2DMSArray: - case EbtUImage2DMSArray: return true; case EbtImage2D: case EbtIImage2D: @@ -779,15 +764,9 @@ inline bool IsImage2DArray(TBasicType type) case EbtImageCube: case EbtIImageCube: case EbtUImageCube: - case EbtImage2DMS: - case EbtIImage2DMS: - case EbtUImage2DMS: case EbtImageCubeArray: case EbtIImageCubeArray: case EbtUImageCubeArray: - case EbtImageRect: - case EbtIImageRect: - case EbtUImageRect: case EbtImageBuffer: case EbtIImageBuffer: case EbtUImageBuffer: @@ -816,18 +795,9 @@ inline bool IsImageCube(TBasicType type) case EbtImage2DArray: case EbtIImage2DArray: case EbtUImage2DArray: - case EbtImage2DMS: - case EbtIImage2DMS: - case EbtUImage2DMS: - case EbtImage2DMSArray: - case EbtIImage2DMSArray: - case EbtUImage2DMSArray: case EbtImageCubeArray: case EbtIImageCubeArray: case EbtUImageCubeArray: - case EbtImageRect: - case EbtIImageRect: - case EbtUImageRect: case EbtImageBuffer: case EbtIImageBuffer: case EbtUImageBuffer: @@ -901,7 +871,11 @@ enum TQualifier EvqPosition, EvqPointSize, - EvqDrawID, // ANGLE_multi_draw + // ANGLE_base_vertex_base_instance_shader_builtin + EvqBaseVertex, + EvqBaseInstance, + // ANGLE_multi_draw + EvqDrawID, // built-ins read by fragment shader EvqFragCoord, @@ -929,6 +903,8 @@ enum TQualifier EvqLastFragDepth, EvqLastFragStencil, + EvqDepthRange, // gl_DepthRange + // GLSL ES 3.0 vertex output and fragment input // This section combines @@ -978,6 +954,10 @@ enum TQualifier EvqNoPerspectiveCentroidIn, EvqNoPerspectiveSampleIn, + // GL_EXT_fragment_shading_rate + EvqShadingRateEXT, + EvqPrimitiveShadingRateEXT, + // GLSL ES 3.0 extension OES_sample_variables EvqSampleID, EvqSamplePosition, @@ -1012,9 +992,6 @@ enum TQualifier EvqLayerOut, // gl_Layer (GS output) EvqLayerIn, // gl_Layer (FS input) - // GLSL ES 3.1 extension EXT_gpu_shader5 qualifiers - EvqPrecise, - // GLES ES 3.1 extension EXT_tessellation_shader qualifiers EvqPatchIn, EvqPatchOut, @@ -1338,7 +1315,7 @@ struct TLayoutQualifier // EXT_shader_framebuffer_fetch layout qualifiers. int inputAttachmentIndex; - bool noncoherent; + bool noncoherent; // Also used by ANGLE_shader_pixel_local_storage. // KHR_blend_equation_advanced layout qualifiers. AdvancedBlendEquations advancedBlendEquations; @@ -1479,8 +1456,10 @@ inline const char *getQualifierString(TQualifier q) case EvqParamConst: return "const"; case EvqInstanceID: return "InstanceID"; case EvqVertexID: return "VertexID"; - case EvqPosition: return "Position"; - case EvqPointSize: return "PointSize"; + case EvqPosition: return "out"; // Per EXT_separate_shader_objects + case EvqPointSize: return "out"; // Per EXT_separate_shader_objects + case EvqBaseVertex: return "BaseVertex"; + case EvqBaseInstance: return "BaseInstance"; case EvqDrawID: return "DrawID"; case EvqFragCoord: return "FragCoord"; case EvqFrontFacing: return "FrontFacing"; @@ -1498,6 +1477,7 @@ inline const char *getQualifierString(TQualifier q) case EvqLastFragData: return "LastFragData"; case EvqLastFragDepth: return "LastFragDepthARM"; case EvqLastFragStencil: return "LastFragStencilARM"; + case EvqDepthRange: return "DepthRange"; case EvqFragmentInOut: return "inout"; case EvqSmoothOut: return "smooth out"; case EvqCentroidOut: return "smooth centroid out"; @@ -1532,16 +1512,17 @@ inline const char *getQualifierString(TQualifier q) case EvqVolatile: return "volatile"; case EvqGeometryIn: return "in"; case EvqGeometryOut: return "out"; - case EvqPerVertexIn: return "gl_in"; + case EvqPerVertexIn: return "in"; case EvqPrimitiveIDIn: return "gl_PrimitiveIDIn"; case EvqInvocationID: return "gl_InvocationID"; case EvqPrimitiveID: return "gl_PrimitiveID"; - case EvqPrecise: return "precise"; case EvqClipDistance: return "ClipDistance"; case EvqCullDistance: return "CullDistance"; case EvqSample: return "sample"; case EvqSampleIn: return "sample in"; case EvqSampleOut: return "sample out"; + case EvqShadingRateEXT: return "ShadingRateEXT"; + case EvqPrimitiveShadingRateEXT: return "PrimitiveShadingRateEXT"; case EvqSampleID: return "SampleID"; case EvqSamplePosition: return "SamplePosition"; case EvqSampleMaskIn: return "SampleMaskIn"; diff --git a/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/compiler/translator/BuiltInFunctionEmulator.cpp index 34b43365cf1..18ad0b7ba7f 100644 --- a/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ b/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/BuiltInFunctionEmulator.h" #include "angle_gl.h" #include "compiler/translator/Symbol.h" diff --git a/src/compiler/translator/CallDAG.cpp b/src/compiler/translator/CallDAG.cpp index 5d47518eba0..6ad6543aad5 100644 --- a/src/compiler/translator/CallDAG.cpp +++ b/src/compiler/translator/CallDAG.cpp @@ -10,7 +10,6 @@ #include "compiler/translator/CallDAG.h" -#include "compiler/translator/Diagnostics.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/tree_util/IntermTraverse.h" @@ -22,14 +21,11 @@ namespace sh class CallDAG::CallDAGCreator : public TIntermTraverser { public: - CallDAGCreator(TDiagnostics *diagnostics) - : TIntermTraverser(true, false, false), - mDiagnostics(diagnostics), - mCurrentFunction(nullptr), - mCurrentIndex(0) + CallDAGCreator() + : TIntermTraverser(true, false, false), mCurrentFunction(nullptr), mCurrentIndex(0) {} - InitResult assignIndices() + void assignIndices() { int skipped = 0; for (auto &it : mFunctions) @@ -37,11 +33,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser // Skip unimplemented functions if (it.second.definitionNode) { - InitResult result = assignIndicesInternal(&it.second); - if (result != INITDAG_SUCCESS) - { - return result; - } + assignIndicesInternal(&it.second); } else { @@ -50,7 +42,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser } ASSERT(mFunctions.size() == mCurrentIndex + skipped); - return INITDAG_SUCCESS; } void fillDataStructures(std::vector *records, std::map *idToIndex) @@ -144,7 +135,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser } // Recursively assigns indices to a sub DAG - InitResult assignIndicesInternal(CreatorFunctionData *root) + void assignIndicesInternal(CreatorFunctionData *root) { // Iterative implementation of the index assignment algorithm. A recursive version // would be prettier but since the CallDAG creation runs before the limiting of the @@ -155,9 +146,12 @@ class CallDAG::CallDAGCreator : public TIntermTraverser if (root->indexAssigned) { - return INITDAG_SUCCESS; + return; } + // TODO(http://anglebug.com/349994211): The following description is no longer valid, since + // detection of recursion is no longer needed here. Future changes will remove this class. + // // If we didn't have to detect recursion, functionsToProcess could be a simple queue // in which we add the function being processed's callees. However in order to detect // recursion we need to know which functions we are currently visiting. For that reason @@ -169,10 +163,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser TVector functionsToProcess; functionsToProcess.push_back(root); - InitResult result = INITDAG_SUCCESS; - - std::stringstream errorStream = sh::InitializeStream(); - while (!functionsToProcess.empty()) { CreatorFunctionData *function = functionsToProcess.back(); @@ -189,9 +179,9 @@ class CallDAG::CallDAGCreator : public TIntermTraverser if (!function->definitionNode) { - errorStream << "Undefined function '" << function->name - << "()' used in the following call chain:"; - result = INITDAG_UNDEFINED; + // This function is undefined, but that's already checked and rejected by the + // parser. + ASSERT(false); break; } @@ -211,46 +201,14 @@ class CallDAG::CallDAGCreator : public TIntermTraverser // in the chain printed in the info log. if (callee->visiting) { - errorStream << "Recursive function call in the following call chain:"; - result = INITDAG_RECURSION; + // This is a recursion, but that's already checked and rejected by the parser. + ASSERT(false); break; } } - - if (result != INITDAG_SUCCESS) - { - break; - } } - - // The call chain is made of the function we were visiting when the error was detected. - if (result != INITDAG_SUCCESS) - { - bool first = true; - for (auto function : functionsToProcess) - { - if (function->visiting) - { - if (!first) - { - errorStream << " -> "; - } - errorStream << function->name << ")"; - first = false; - } - } - if (mDiagnostics) - { - std::string errorStr = errorStream.str(); - mDiagnostics->globalError(errorStr.c_str()); - } - } - - return result; } - TDiagnostics *mDiagnostics; - std::map mFunctions; CreatorFunctionData *mCurrentFunction; size_t mCurrentIndex; @@ -295,22 +253,17 @@ void CallDAG::clear() mFunctionIdToIndex.clear(); } -CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics) +void CallDAG::init(TIntermNode *root) { - CallDAGCreator creator(diagnostics); + CallDAGCreator creator; - // Creates the mapping of functions to callees + // Create the mapping of functions to callees root->traverse(&creator); - // Does the topological sort and detects recursions - InitResult result = creator.assignIndices(); - if (result != INITDAG_SUCCESS) - { - return result; - } + // Do the topological sort + creator.assignIndices(); creator.fillDataStructures(&mRecords, &mFunctionIdToIndex); - return INITDAG_SUCCESS; } } // namespace sh diff --git a/src/compiler/translator/CallDAG.h b/src/compiler/translator/CallDAG.h index 7e80f2e855d..93a7bc5b3ac 100644 --- a/src/compiler/translator/CallDAG.h +++ b/src/compiler/translator/CallDAG.h @@ -19,8 +19,7 @@ namespace sh { // The translator needs to analyze the the graph of the function calls -// to run checks and analyses; since in GLSL recursion is not allowed -// that graph is a DAG. +// to run checks and analyses. // This class is used to precompute that function call DAG so that it // can be reused by multiple analyses. // @@ -45,16 +44,7 @@ class CallDAG : angle::NonCopyable std::vector callees; }; - enum InitResult - { - INITDAG_SUCCESS, - INITDAG_RECURSION, - INITDAG_UNDEFINED, - }; - - // Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints - // the initialization error in diagnostics, if present. - InitResult init(TIntermNode *root, TDiagnostics *diagnostics); + void init(TIntermNode *root); // Returns InvalidIndex if the function wasn't found size_t findIndex(const TSymbolUniqueId &id) const; diff --git a/src/compiler/translator/CodeGen.cpp b/src/compiler/translator/CodeGen.cpp index 762393dcbce..a2c72949728 100644 --- a/src/compiler/translator/CodeGen.cpp +++ b/src/compiler/translator/CodeGen.cpp @@ -4,9 +4,7 @@ // found in the LICENSE file. // -#ifdef ANGLE_ENABLE_NULL -# include "compiler/translator/null/TranslatorNULL.h" -#endif // ANGLE_ENABLE_NULL +#include "compiler/translator/null/TranslatorNULL.h" #ifdef ANGLE_ENABLE_ESSL # include "compiler/translator/glsl/TranslatorESSL.h" @@ -44,12 +42,10 @@ namespace sh // TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) { -#ifdef ANGLE_ENABLE_NULL if (IsOutputNULL(output)) { return new TranslatorNULL(type, spec); } -#endif // ANGLE_ENABLE_NULL #ifdef ANGLE_ENABLE_ESSL if (IsOutputESSL(output)) diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp index fb93a9624e4..a438e5faf4a 100644 --- a/src/compiler/translator/CollectVariables.cpp +++ b/src/compiler/translator/CollectVariables.cpp @@ -5,6 +5,10 @@ // // CollectVariables.cpp: Collect lists of shader interface variables based on the AST. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/CollectVariables.h" #include "angle_gl.h" @@ -123,12 +127,14 @@ class CollectVariablesTraverser : public TIntermTraverser std::vector *sharedVariables, std::vector *uniformBlocks, std::vector *shaderStorageBlocks, + char userVariablePrefix, ShHashFunction64 hashFunction, TSymbolTable *symbolTable, GLenum shaderType, const TExtensionBehavior &extensionBehavior, const ShBuiltInResources &resources, - int tessControlShaderOutputVertices); + int tessControlShaderOutputVertices, + bool transformFloatUniformToFP16); bool visitGlobalQualifierDeclaration(Visit visit, TIntermGlobalQualifierDeclaration *node) override; @@ -143,16 +149,19 @@ class CollectVariablesTraverser : public TIntermTraverser bool staticUse, bool isShaderIOBlock, bool isPatch, + bool isUniform, ShaderVariable *variableOut) const; void setFieldProperties(const TType &type, const ImmutableString &name, bool staticUse, bool isShaderIOBlock, bool isPatch, + bool isUniform, SymbolType symbolType, ShaderVariable *variableOut) const; void setCommonVariableProperties(const TType &type, const TVariable &variable, + bool isUniform, ShaderVariable *variableOut) const; ShaderVariable recordAttribute(const TIntermSymbol &variable) const; @@ -204,6 +213,7 @@ class CollectVariablesTraverser : public TIntermTraverser bool mPositionAdded; bool mClipDistanceAdded; bool mCullDistanceAdded; + bool mPrimitiveShadingRateEXTAdded; // Fragment Shader builtins bool mPointCoordAdded; @@ -217,6 +227,7 @@ class CollectVariablesTraverser : public TIntermTraverser bool mFragDepthAdded; bool mSecondaryFragColorEXTAdded; bool mSecondaryFragDataEXTAdded; + bool mShadingRateEXTAdded; bool mSampleIDAdded; bool mSamplePositionAdded; bool mSampleMaskAdded; @@ -244,7 +255,9 @@ class CollectVariablesTraverser : public TIntermTraverser bool mBoundingBoxAdded; bool mTessCoordAdded; const int mTessControlShaderOutputVertices; + bool mTransformFloatUniformToFP16; + char mUserVariablePrefix; ShHashFunction64 mHashFunction; GLenum mShaderType; @@ -261,12 +274,14 @@ CollectVariablesTraverser::CollectVariablesTraverser( std::vector *sharedVariables, std::vector *uniformBlocks, std::vector *shaderStorageBlocks, + char userVariablePrefix, ShHashFunction64 hashFunction, TSymbolTable *symbolTable, GLenum shaderType, const TExtensionBehavior &extensionBehavior, const ShBuiltInResources &resources, - int tessControlShaderOutputVertices) + int tessControlShaderOutputVertices, + const bool transformFloatUniformToFP16) : TIntermTraverser(true, false, false, symbolTable), mAttribs(attribs), mOutputVariables(outputVariables), @@ -290,6 +305,7 @@ CollectVariablesTraverser::CollectVariablesTraverser( mPositionAdded(false), mClipDistanceAdded(false), mCullDistanceAdded(false), + mPrimitiveShadingRateEXTAdded(false), mPointCoordAdded(false), mFrontFacingAdded(false), mHelperInvocationAdded(false), @@ -301,6 +317,7 @@ CollectVariablesTraverser::CollectVariablesTraverser( mFragDepthAdded(false), mSecondaryFragColorEXTAdded(false), mSecondaryFragDataEXTAdded(false), + mShadingRateEXTAdded(false), mSampleIDAdded(false), mSamplePositionAdded(false), mSampleMaskAdded(false), @@ -318,6 +335,8 @@ CollectVariablesTraverser::CollectVariablesTraverser( mBoundingBoxAdded(false), mTessCoordAdded(false), mTessControlShaderOutputVertices(tessControlShaderOutputVertices), + mTransformFloatUniformToFP16(transformFloatUniformToFP16), + mUserVariablePrefix(userVariablePrefix), mHashFunction(hashFunction), mShaderType(shaderType), mExtensionBehavior(extensionBehavior), @@ -326,7 +345,7 @@ CollectVariablesTraverser::CollectVariablesTraverser( std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const { - return HashName(symbol, mHashFunction, nullptr).data(); + return HashName(symbol, mUserVariablePrefix, mHashFunction, nullptr).data(); } void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable, @@ -343,7 +362,7 @@ void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variab type.getQualifier() == EvqTessLevelOuter || type.getQualifier() == EvqBoundingBox; - setFieldOrVariableProperties(type, true, isShaderIOBlock, isPatch, info); + setFieldOrVariableProperties(type, true, isShaderIOBlock, isPatch, false, info); } void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable, @@ -448,72 +467,6 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) { UNREACHABLE(); } - else if (symbolName == "gl_DepthRange") - { - ASSERT(qualifier == EvqUniform); - - if (!mDepthRangeAdded) - { - ShaderVariable info; - const char kName[] = "gl_DepthRange"; - info.name = kName; - info.mappedName = kName; - info.type = GL_NONE; - info.precision = GL_NONE; - info.staticUse = true; - info.active = true; - - ShaderVariable nearInfo(GL_FLOAT); - const char kNearName[] = "near"; - nearInfo.name = kNearName; - nearInfo.mappedName = kNearName; - nearInfo.precision = GL_HIGH_FLOAT; - nearInfo.staticUse = true; - nearInfo.active = true; - - ShaderVariable farInfo(GL_FLOAT); - const char kFarName[] = "far"; - farInfo.name = kFarName; - farInfo.mappedName = kFarName; - farInfo.precision = GL_HIGH_FLOAT; - farInfo.staticUse = true; - farInfo.active = true; - - ShaderVariable diffInfo(GL_FLOAT); - const char kDiffName[] = "diff"; - diffInfo.name = kDiffName; - diffInfo.mappedName = kDiffName; - diffInfo.precision = GL_HIGH_FLOAT; - diffInfo.staticUse = true; - diffInfo.active = true; - - info.fields.push_back(nearInfo); - info.fields.push_back(farInfo); - info.fields.push_back(diffInfo); - - mUniforms->push_back(info); - mDepthRangeAdded = true; - } - } - else if (symbolName == "gl_NumSamples") - { - ASSERT(qualifier == EvqUniform); - - if (!mNumSamplesAdded) - { - ShaderVariable info; - const char kName[] = "gl_NumSamples"; - info.name = kName; - info.mappedName = kName; - info.type = GL_INT; - info.precision = GL_LOW_INT; - info.staticUse = true; - info.active = true; - - mUniforms->push_back(info); - mNumSamplesAdded = true; - } - } else { switch (qualifier) @@ -616,6 +569,50 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) case EvqSecondaryFragDataEXT: recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded); return; + case EvqDepthRange: + if (!mDepthRangeAdded) + { + ShaderVariable info; + const char kName[] = "gl_DepthRange"; + info.name = kName; + info.mappedName = kName; + info.type = GL_NONE; + info.precision = GL_NONE; + info.staticUse = true; + info.active = true; + + ShaderVariable nearInfo(GL_FLOAT); + const char kNearName[] = "near"; + nearInfo.name = kNearName; + nearInfo.mappedName = kNearName; + nearInfo.precision = GL_HIGH_FLOAT; + nearInfo.staticUse = true; + nearInfo.active = true; + + ShaderVariable farInfo(GL_FLOAT); + const char kFarName[] = "far"; + farInfo.name = kFarName; + farInfo.mappedName = kFarName; + farInfo.precision = GL_HIGH_FLOAT; + farInfo.staticUse = true; + farInfo.active = true; + + ShaderVariable diffInfo(GL_FLOAT); + const char kDiffName[] = "diff"; + diffInfo.name = kDiffName; + diffInfo.mappedName = kDiffName; + diffInfo.precision = GL_HIGH_FLOAT; + diffInfo.staticUse = true; + diffInfo.active = true; + + info.fields.push_back(nearInfo); + info.fields.push_back(farInfo); + info.fields.push_back(diffInfo); + + mUniforms->push_back(info); + mDepthRangeAdded = true; + } + break; case EvqInvocationID: recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings); break; @@ -670,6 +667,13 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) symbol->variable(), &mCullDistanceAdded, mShaderType == GL_FRAGMENT_SHADER ? mInputVaryings : mOutputVaryings); return; + case EvqPrimitiveShadingRateEXT: + recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveShadingRateEXTAdded, + mOutputVaryings); + return; + case EvqShadingRateEXT: + recordBuiltInVaryingUsed(symbol->variable(), &mShadingRateEXTAdded, mInputVaryings); + return; case EvqSampleID: recordBuiltInVaryingUsed(symbol->variable(), &mSampleIDAdded, mInputVaryings); return; @@ -682,6 +686,23 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) case EvqSampleMask: recordBuiltInFragmentOutputUsed(symbol->variable(), &mSampleMaskAdded); return; + case EvqNumSamples: + if (!mNumSamplesAdded) + { + ShaderVariable info; + const char kName[] = "gl_NumSamples"; + info.name = kName; + info.mappedName = kName; + info.type = GL_INT; + info.precision = GL_LOW_INT; + info.staticUse = true; + info.active = true; + + // Note: gl_NumSamples is considered a uniform + mUniforms->push_back(info); + mNumSamplesAdded = true; + } + break; case EvqPatchVerticesIn: recordBuiltInVaryingUsed(symbol->variable(), &mPatchVerticesInAdded, mInputVaryings); @@ -732,6 +753,7 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type, bool staticUse, bool isShaderIOBlock, bool isPatch, + const bool isUniform, ShaderVariable *variableOut) const { ASSERT(variableOut); @@ -761,7 +783,7 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type, // ShaderVariable objects. ShaderVariable fieldVariable; setFieldProperties(*field->type(), field->name(), staticUse, isShaderIOBlock, isPatch, - field->symbolType(), &fieldVariable); + isUniform, field->symbolType(), &fieldVariable); variableOut->fields.push_back(fieldVariable); } } @@ -773,15 +795,17 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type, { variableOut->structOrBlockName = interfaceBlock->name().data(); variableOut->mappedStructOrBlockName = - isPerVertex ? interfaceBlock->name().data() - : HashName(interfaceBlock->name(), mHashFunction, nullptr).data(); + isPerVertex + ? interfaceBlock->name().data() + : HashName(interfaceBlock->name(), mUserVariablePrefix, mHashFunction, nullptr) + .data(); } const TFieldList &fields = interfaceBlock->fields(); for (const TField *field : fields) { ShaderVariable fieldVariable; - setFieldProperties(*field->type(), field->name(), staticUse, true, isPatch, + setFieldProperties(*field->type(), field->name(), staticUse, true, isPatch, false, field->symbolType(), &fieldVariable); fieldVariable.isShaderIOBlock = true; variableOut->fields.push_back(fieldVariable); @@ -791,6 +815,11 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type, { variableOut->type = GLVariableType(type); variableOut->precision = GLVariablePrecision(type); + if (mTransformFloatUniformToFP16 && isUniform && type.getBasicType() == EbtFloat && + type.getPrecision() < EbpHigh) + { + variableOut->isFloat16 = true; + } } const angle::Span &arraySizes = type.getArraySizes(); @@ -826,19 +855,22 @@ void CollectVariablesTraverser::setFieldProperties(const TType &type, bool staticUse, bool isShaderIOBlock, bool isPatch, + const bool isUniform, SymbolType symbolType, ShaderVariable *variableOut) const { ASSERT(variableOut); - setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); + setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, isUniform, variableOut); variableOut->name.assign(name.data(), name.length()); - variableOut->mappedName = (symbolType == SymbolType::BuiltIn) - ? name.data() - : HashName(name, mHashFunction, nullptr).data(); + variableOut->mappedName = + (symbolType == SymbolType::BuiltIn) + ? name.data() + : HashName(name, mUserVariablePrefix, mHashFunction, nullptr).data(); } void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, const TVariable &variable, + const bool isUniform, ShaderVariable *variableOut) const { ASSERT(variableOut); @@ -849,7 +881,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, const bool isShaderIOBlock = type.getInterfaceBlock() != nullptr; const bool isPatch = type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut; - setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); + setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, isUniform, variableOut); const bool isNamed = variable.symbolType() != SymbolType::Empty; @@ -870,7 +902,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, variableOut->structOrBlockName.assign(interfaceBlock->name().data(), interfaceBlock->name().length()); variableOut->mappedStructOrBlockName = - HashName(interfaceBlock->name(), mHashFunction, nullptr).data(); + HashName(interfaceBlock->name(), mUserVariablePrefix, mHashFunction, nullptr).data(); variableOut->isShaderIOBlock = true; } } @@ -881,7 +913,7 @@ ShaderVariable CollectVariablesTraverser::recordAttribute(const TIntermSymbol &v ASSERT(!type.getStruct()); ShaderVariable attribute; - setCommonVariableProperties(type, variable.variable(), &attribute); + setCommonVariableProperties(type, variable.variable(), false, &attribute); attribute.location = type.getLayoutQualifier().location; return attribute; @@ -893,7 +925,7 @@ ShaderVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymb ASSERT(!type.getStruct()); ShaderVariable outputVariable; - setCommonVariableProperties(type, variable.variable(), &outputVariable); + setCommonVariableProperties(type, variable.variable(), false, &outputVariable); outputVariable.location = type.getLayoutQualifier().location; outputVariable.index = type.getLayoutQualifier().index; @@ -906,7 +938,7 @@ ShaderVariable CollectVariablesTraverser::recordVarying(const TIntermSymbol &var const TType &type = variable.getType(); ShaderVariable varying; - setCommonVariableProperties(type, variable.variable(), &varying); + setCommonVariableProperties(type, variable.variable(), false, &varying); varying.location = type.getLayoutQualifier().location; switch (type.getQualifier()) @@ -1059,8 +1091,8 @@ void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName, } ShaderVariable fieldVariable; - setFieldProperties(fieldType, field->name(), staticUse, false, false, field->symbolType(), - &fieldVariable); + setFieldProperties(fieldType, field->name(), staticUse, false, false, false, + field->symbolType(), &fieldVariable); fieldVariable.isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); interfaceBlock->fields.push_back(fieldVariable); @@ -1084,7 +1116,16 @@ void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName, ShaderVariable CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const { ShaderVariable uniform; - setCommonVariableProperties(variable.getType(), variable.variable(), &uniform); + // For mediump and lowp float uniforms, if mTransformFloatUniformToFP16 is true, we will change + // data type from 32-bit float to 16-bit float later in Spirv. Pass this information to + // the ShaderVariable so that the frontend are aware of the data type change and will transform + // the data type from 32-bit float to 16-bit float before writing the uniform data to memory. + if (mTransformFloatUniformToFP16 && (variable.getBasicType() == EbtFloat) && + variable.getPrecision() < EbpHigh) + { + uniform.isFloat16 = true; + } + setCommonVariableProperties(variable.getType(), variable.variable(), true, &uniform); uniform.binding = variable.getType().getLayoutQualifier().binding; uniform.imageUnitFormat = GetImageInternalFormatType(variable.getType().getLayoutQualifier().imageInternalFormat); @@ -1099,7 +1140,10 @@ ShaderVariable CollectVariablesTraverser::recordUniform(const TIntermSymbol &var bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node) { const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); + if (sequence.empty()) + { + return false; + } const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); TQualifier qualifier = typedNode.getQualifier(); @@ -1175,6 +1219,9 @@ bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node case EvqUniform: mUniforms->push_back(recordUniform(variable)); break; + case EvqPerVertexIn: + case EvqPerVertexOut: + break; default: if (IsVaryingIn(qualifier)) { @@ -1264,11 +1311,7 @@ bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode) } else if (qualifier != EvqPixelLocalEXT) { - - if (!namedBlock) - { - namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); - } + namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); ASSERT(namedBlock); ASSERT(namedBlock->staticUse); namedBlock->active = true; @@ -1303,17 +1346,20 @@ void CollectVariables(TIntermBlock *root, std::vector *sharedVariables, std::vector *uniformBlocks, std::vector *shaderStorageBlocks, + char userVariablePrefix, ShHashFunction64 hashFunction, TSymbolTable *symbolTable, GLenum shaderType, const TExtensionBehavior &extensionBehavior, const ShBuiltInResources &resources, - int tessControlShaderOutputVertices) + int tessControlShaderOutputVertices, + const bool transformFloatUniformToFP16) { - CollectVariablesTraverser collect( - attributes, outputVariables, uniforms, inputVaryings, outputVaryings, sharedVariables, - uniformBlocks, shaderStorageBlocks, hashFunction, symbolTable, shaderType, - extensionBehavior, resources, tessControlShaderOutputVertices); + CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings, + outputVaryings, sharedVariables, uniformBlocks, + shaderStorageBlocks, userVariablePrefix, hashFunction, + symbolTable, shaderType, extensionBehavior, resources, + tessControlShaderOutputVertices, transformFloatUniformToFP16); root->traverse(&collect); } diff --git a/src/compiler/translator/CollectVariables.h b/src/compiler/translator/CollectVariables.h index 6ea4b172a05..d6e70b1302d 100644 --- a/src/compiler/translator/CollectVariables.h +++ b/src/compiler/translator/CollectVariables.h @@ -27,12 +27,14 @@ void CollectVariables(TIntermBlock *root, std::vector *sharedVariables, std::vector *uniformBlocks, std::vector *shaderStorageBlocks, + char userVariablePrefix, ShHashFunction64 hashFunction, TSymbolTable *symbolTable, GLenum shaderType, const TExtensionBehavior &extensionBehavior, const ShBuiltInResources &resources, - int tessControlShaderOutputVertices); + int tessControlShaderOutputVertices, + bool transformFloatUniformToFP16); } // namespace sh #endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ diff --git a/src/compiler/translator/Common.h b/src/compiler/translator/Common.h index 871e9d9228d..893f2c7d7d0 100644 --- a/src/compiler/translator/Common.h +++ b/src/compiler/translator/Common.h @@ -7,6 +7,10 @@ #ifndef COMPILER_TRANSLATOR_COMMON_H_ #define COMPILER_TRANSLATOR_COMMON_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp index 5aa5a2ea043..69214f40c10 100644 --- a/src/compiler/translator/Compiler.cpp +++ b/src/compiler/translator/Compiler.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/Compiler.h" #include @@ -21,14 +25,9 @@ #include "compiler/translator/IsASTDepthBelowLimit.h" #include "compiler/translator/OutputTree.h" #include "compiler/translator/ParseContext.h" -#include "compiler/translator/ValidateBarrierFunctionCall.h" -#include "compiler/translator/ValidateClipCullDistance.h" -#include "compiler/translator/ValidateLimitations.h" -#include "compiler/translator/ValidateMaxParameters.h" -#include "compiler/translator/ValidateOutputs.h" -#include "compiler/translator/ValidateTypeSizeLimitations.h" -#include "compiler/translator/ValidateVaryingLocations.h" +#include "compiler/translator/SizeClipCullDistance.h" #include "compiler/translator/VariablePacker.h" +#include "compiler/translator/ir/src/compile.h" #include "compiler/translator/tree_ops/ClampFragDepth.h" #include "compiler/translator/tree_ops/ClampIndirectIndices.h" #include "compiler/translator/tree_ops/ClampPointSize.h" @@ -37,30 +36,26 @@ #include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h" #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" #include "compiler/translator/tree_ops/FoldExpressions.h" -#include "compiler/translator/tree_ops/ForcePrecisionQualifier.h" #include "compiler/translator/tree_ops/InitializeVariables.h" -#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" #include "compiler/translator/tree_ops/PruneEmptyCases.h" -#include "compiler/translator/tree_ops/PruneInfiniteLoops.h" #include "compiler/translator/tree_ops/PruneNoOps.h" #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h" #include "compiler/translator/tree_ops/RemoveDynamicIndexing.h" +#include "compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h" #include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h" #include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h" #include "compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.h" -#include "compiler/translator/tree_ops/RescopeGlobalVariables.h" #include "compiler/translator/tree_ops/RewritePixelLocalStorage.h" +#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/tree_ops/SeparateDeclarations.h" #include "compiler/translator/tree_ops/SimplifyLoopConditions.h" #include "compiler/translator/tree_ops/SplitSequenceOperator.h" #include "compiler/translator/tree_ops/glsl/RegenerateStructNames.h" #include "compiler/translator/tree_ops/glsl/RewriteRepeatedAssignToSwizzled.h" -#include "compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/tree_ops/glsl/UseInterfaceBlockFields.h" #include "compiler/translator/tree_ops/glsl/apple/AddAndTrueToLoopCondition.h" -#include "compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h" #include "compiler/translator/tree_ops/glsl/apple/UnfoldShortCircuitAST.h" -#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.h" #include "compiler/translator/tree_util/FindSymbolNode.h" #include "compiler/translator/tree_util/IntermNodePatternMatcher.h" #include "compiler/translator/tree_util/ReplaceShadowingVariables.h" @@ -172,7 +167,7 @@ void DumpFuzzerCase(char const *const *shaderStrings, memcpy(data, shaderStrings[i], length); data += length; } - auto hash = angle::ComputeGenericHash(contents.data(), contents.size()); + auto hash = angle::ComputeGenericHash(contents); std::ostringstream o = sh::InitializeStream(); o << ANGLE_FUZZER_CORPUS_OUTPUT_DIR << std::hex << std::setw(16) << std::setfill('0') << hash @@ -185,6 +180,128 @@ void DumpFuzzerCase(char const *const *shaderStrings, fclose(f); } #endif // defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) + +// Helper function to check if the TIntermNode is a struct specifier +bool IsCurrentNodeStructTypeDeclaration(TIntermNode *node) +{ + TIntermDeclaration *declarationNode = node->getAsDeclarationNode(); + if (declarationNode != nullptr) + { + TIntermTyped *typeNode = declarationNode->getSequence()->front()->getAsTyped(); + if (typeNode != nullptr && (typeNode->getType().getBasicType() == EbtStruct && + typeNode->getType().isStructSpecifier())) + { + return true; + } + } + return false; +} + +// Helper function to check if the TIntermNode is a uniform type declaration, and it is not a struct +// specifier +bool IsCurrentNodeUniformDeclaration(TIntermNode *node) +{ + TIntermDeclaration *declarationNode = node->getAsDeclarationNode(); + if (declarationNode != nullptr) + { + TIntermTyped *typeNode = declarationNode->getSequence()->front()->getAsTyped(); + if (typeNode != nullptr && typeNode->getType().getQualifier() == TQualifier::EvqUniform && + !IsCurrentNodeStructTypeDeclaration(node)) + { + return true; + } + } + return false; +} + +// Comparator function used for sorting shader uniforms +struct UniformSortComparator +{ + // returns true if the first < second, returns false otherwise + bool operator()(TIntermNode *first, TIntermNode *second) + { + const TType &firstType = first->getAsDeclarationNode() + ->getSequence() + ->front() + ->getAsSymbolNode() + ->variable() + .getType(); + const TType &secondType = second->getAsDeclarationNode() + ->getSequence() + ->front() + ->getAsSymbolNode() + ->variable() + .getType(); + // If both uniforms are structs, do not reorder them + if (firstType.getStruct() != nullptr && secondType.getStruct() != nullptr) + { + return false; + } + + // Next sort by precisions + // Group uniforms into high-precision and non-high-precision. A non-highp uniform is + // considered "smaller" than a highp uniform. + const TPrecision firstPrecision = firstType.getPrecision(); + const TPrecision secondPrecision = secondType.getPrecision(); + const bool firstIsHighP = (firstPrecision == TPrecision::EbpHigh); + const bool secondIsHighP = (secondPrecision == TPrecision::EbpHigh); + if (firstIsHighP != secondIsHighP) + { + return secondIsHighP; + } + // If both are highp, they are equivalent. Do not reorder them. + if (firstIsHighP) + { + return false; + } + // If we reach here, both uniforms are non-highp. We further sort them based on a list of + // criteria + ASSERT(firstType.getPrecision() != TPrecision::EbpHigh && + secondType.getPrecision() != TPrecision::EbpHigh); + // criteria 1: sort by whether the uniform is a struct. Non-structs is smaller. + if ((firstType.getStruct() == nullptr) != (secondType.getStruct() == nullptr)) + { + return firstType.getStruct() == nullptr; + } + // criteria 2: sort by arrayness. Non-array element is smaller. + if (firstType.isArray() != secondType.isArray()) + { + return !firstType.isArray(); + } + // criteria 3, non-matrix is smaller than matrix + if (firstType.isMatrix() != secondType.isMatrix()) + { + return !firstType.isMatrix(); + } + // if both are matrix, sort by matrix size + if (firstType.isMatrix() == secondType.isMatrix() && firstType.isMatrix()) + { + if (firstType.getCols() != secondType.getCols()) + { + return firstType.getCols() < secondType.getCols(); + } + else + { + return firstType.getRows() < secondType.getRows(); + } + } + // criteria 4, non-vector is smaller + if (firstType.isVector() != secondType.isVector()) + { + return !firstType.isVector(); + } + // if both are vectors, sort by vector size + if (firstType.isVector() == secondType.isVector() && firstType.isVector()) + { + return firstType.getNominalSize() < secondType.getNominalSize(); + } + + // If we can't determine which element is smaller based on previous criteria, consider first + // and second as equivalent. + return false; + } +}; + } // anonymous namespace bool IsGLSL130OrNewer(ShShaderOutput output) @@ -261,23 +378,6 @@ int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResource namespace { -class [[nodiscard]] TScopedPoolAllocator -{ - public: - TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator) - { - mAllocator->push(); - SetGlobalPoolAllocator(mAllocator); - } - ~TScopedPoolAllocator() - { - SetGlobalPoolAllocator(nullptr); - mAllocator->pop(angle::PoolAllocator::ReleaseStrategy::All); - } - - private: - angle::PoolAllocator *mAllocator; -}; class [[nodiscard]] TScopedSymbolTableLevel { @@ -308,7 +408,6 @@ int GetMaxShaderVersionForSpec(ShShaderSpec spec) case SH_WEBGL2_SPEC: return 300; case SH_GLES3_1_SPEC: - case SH_WEBGL3_SPEC: return 310; case SH_GLES3_2_SPEC: return 320; @@ -318,74 +417,27 @@ int GetMaxShaderVersionForSpec(ShShaderSpec spec) } } -bool ValidateFragColorAndFragData(GLenum shaderType, - int shaderVersion, - const TSymbolTable &symbolTable, - TDiagnostics *diagnostics) -{ - if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER) - { - return true; - } - - bool usesFragColor = false; - bool usesFragData = false; - // This validation is a bit stricter than the spec - it's only an error to write to - // both FragData and FragColor. But because it's better not to have reads from undefined - // variables, we always return an error if they are both referenced, rather than only if they - // are written. - if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) || - symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT())) - { - usesFragColor = true; - } - // Extension variables may not always be initialized (saves some time at symbol table init). - bool secondaryFragDataUsed = - symbolTable.gl_SecondaryFragDataEXT() != nullptr && - symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT()); - if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed) - { - usesFragData = true; - } - if (usesFragColor && usesFragData) - { - const char *errorMessage = "cannot use both gl_FragData and gl_FragColor"; - if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) || - secondaryFragDataUsed) - { - errorMessage = - "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)" - " and (gl_FragColor, gl_SecondaryFragColorEXT)"; - } - diagnostics->globalError(errorMessage); - return false; - } - return true; -} - } // namespace TShHandleBase::TShHandleBase() { - allocator.push(); SetGlobalPoolAllocator(&allocator); } TShHandleBase::~TShHandleBase() { SetGlobalPoolAllocator(nullptr); - allocator.popAll(); } TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : mVariablesCollected(false), - mGLPositionInitialized(false), - mShaderType(type), + : mShaderType(type), mShaderSpec(spec), mOutputType(output), mBuiltInFunctionEmulator(), mDiagnostics(mInfoSink.info), mSourcePath(nullptr), + mVariablesCollected(false), + mGLPositionInitialized(false), mComputeShaderLocalSizeDeclared(false), mComputeShaderLocalSize(1), mGeometryShaderMaxVertices(-1), @@ -405,12 +457,6 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) TCompiler::~TCompiler() {} -bool TCompiler::isHighPrecisionSupported() const -{ - return mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER || - mResources.FragmentPrecisionHigh == 1; -} - bool TCompiler::shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const { // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API, @@ -420,17 +466,6 @@ bool TCompiler::shouldRunLoopAndIndexingValidation(const ShCompileOptions &compi compileOptions.validateLoopIndexing; } -bool TCompiler::shouldLimitTypeSizes() const -{ - // Prevent unrealistically large variable sizes in shaders. This works around driver bugs - // around int-size limits (such as 2GB). The limits are generously large enough that no real - // shader should ever hit it. - // - // The size check does not take std430 into account, so this is limited to WebGL and shaders - // up to ES3. - return mShaderVersion <= 300; -} - bool TCompiler::Init(const ShBuiltInResources &resources) { SetGlobalPoolAllocator(&allocator); @@ -446,15 +481,13 @@ bool TCompiler::Init(const ShBuiltInResources &resources) return true; } -TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, +TIntermBlock *TCompiler::compileTreeForTesting(angle::Span shaderStrings, const ShCompileOptions &compileOptions) { - return compileTreeImpl(shaderStrings, numStrings, compileOptions); + return compileTreeImpl(shaderStrings, compileOptions); } -TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, +TIntermBlock *TCompiler::compileTreeImpl(angle::Span shaderStrings, const ShCompileOptions &compileOptions) { // Remember the compile options for helper functions such as validateAST. @@ -462,7 +495,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], clearResults(); - ASSERT(numStrings > 0); + ASSERT(!shaderStrings.empty()); ASSERT(GetGlobalPoolAllocator()); // Reset the extension behavior for each compilation unit. @@ -500,9 +533,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], } TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec, - compileOptions, &mDiagnostics, getResources(), getOutputType()); - - parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1); + compileOptions, &mDiagnostics, mResources, getOutputType()); // We preserve symbols at the built-in level from compile-to-compile. // Start pushing the user-defined symbols at global level. @@ -510,18 +541,17 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ASSERT(mSymbolTable.atGlobalLevel()); // Parse shader. - if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, - &parseContext) != 0) + if (PaParseStrings(shaderStrings.subspan(firstSource), nullptr, &parseContext) != 0) { return nullptr; } - if (!postParseChecks(parseContext)) + if (!parseContext.postParseChecks()) { return nullptr; } - setASTMetadata(parseContext); + setShaderMetadata(parseContext); if (!checkShaderVersion(&parseContext)) { @@ -529,9 +559,27 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], } TIntermBlock *root = parseContext.getTreeRoot(); - if (!checkAndSimplifyAST(root, parseContext, compileOptions)) +#ifdef ANGLE_IR + if (compileOptions.useIR) { - return nullptr; + ASSERT(root == nullptr); + ir::IR ir = parseContext.getIR(); + + // Create an AST out of the IR while the rest of the translator is still AST based. + root = ir::GenerateAST(std::move(ir), this, compileOptions).root; + } +#endif + ASSERT(root != nullptr); + if (compileOptions.skipAllValidationAndTransforms) + { + collectVariables(root); + } + else + { + if (!checkAndSimplifyAST(root, parseContext, compileOptions)) + { + return nullptr; + } } return root; @@ -602,7 +650,7 @@ bool TCompiler::checkShaderVersion(TParseContext *parseContext) return true; } -void TCompiler::setASTMetadata(const TParseContext &parseContext) +void TCompiler::setShaderMetadata(const TParseContext &parseContext) { mShaderVersion = parseContext.getShaderVersion(); @@ -633,7 +681,7 @@ void TCompiler::setASTMetadata(const TParseContext &parseContext) // rbegin(). mPixelLocalStorageFormats.resize(plsFormats.empty() ? 0 : plsFormats.rbegin()->first + 1, ShPixelLocalStorageFormat::NotPLS); - for (auto [binding, format] : parseContext.pixelLocalStorageFormats()) + for (auto [binding, format] : plsFormats) { mPixelLocalStorageFormats[binding] = format; } @@ -689,12 +737,11 @@ unsigned int TCompiler::getSharedMemorySize() const } bool TCompiler::getShaderBinary(const ShHandle compilerHandle, - const char *const shaderStrings[], - size_t numStrings, + angle::Span shaderStrings, const ShCompileOptions &compileOptions, ShaderBinaryBlob *const binaryOut) { - if (!compile(shaderStrings, numStrings, compileOptions)) + if (!compile(shaderStrings, compileOptions)) { return false; } @@ -702,30 +749,33 @@ bool TCompiler::getShaderBinary(const ShHandle compilerHandle, gl::BinaryOutputStream stream; gl::ShaderType shaderType = gl::FromGLenum(mShaderType); gl::CompiledShaderState state(shaderType); - state.buildCompiledShaderState(compilerHandle, IsOutputSPIRV(mOutputType)); + state.buildCompiledShaderState( + compilerHandle, + mOutputType); stream.writeBytes( - reinterpret_cast(angle::GetANGLEShaderProgramVersion()), - angle::GetANGLEShaderProgramVersionHashSize()); + // NOTE: version api could return a string view. + ANGLE_UNSAFE_TODO(angle::Span( + reinterpret_cast(angle::GetANGLEShaderProgramVersion()), + angle::GetANGLEShaderProgramVersionHashSize()))); stream.writeEnum(shaderType); stream.writeEnum(mOutputType); // Serialize the full source string for the shader. Ignore the source path if it is provided. std::string sourceString; size_t startingIndex = compileOptions.sourcePath ? 1 : 0; - for (size_t i = startingIndex; i < numStrings; ++i) + for (const char *str : shaderStrings.subspan(startingIndex)) { - sourceString.append(shaderStrings[i]); + sourceString.append(str); } stream.writeString(sourceString); - stream.writeBytes(reinterpret_cast(&compileOptions), sizeof(compileOptions)); - stream.writeBytes(reinterpret_cast(&mResources), sizeof(mResources)); + stream.writeBytes(angle::byte_span_from_ref(compileOptions)); + stream.writeBytes(angle::byte_span_from_ref(mResources)); state.serialize(stream); - ASSERT(binaryOut); - *binaryOut = std::move(stream.getData()); + *binaryOut = stream.takeData(); return true; } @@ -788,6 +838,12 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, { mValidateASTOptions = {}; +#if defined(ANGLE_IR) + const bool useIR = compileOptions.useIR; +#else + const bool useIR = false; +#endif + // Disallow expressions deemed too complex. // This needs to be checked before other functions that will traverse the AST // to prevent potential stack overflow crashes. @@ -796,188 +852,143 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, return false; } + // Some AST validation cannot be done until an AST pass is done. With IR, those passes (if + // needed) are done before AST is generated. + if (!useIR) + { + mValidateASTOptions.validateNoStatementsAfterBranch = false; + mValidateASTOptions.validateMultiDeclarations = false; + } + if (!validateAST(root)) { return false; } - // Turn |inout| variables that are never read from into |out| before collecting variables and - // before PLS uses them. - if (mShaderVersion >= 300 && - (IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_shader_framebuffer_fetch) || - IsExtensionEnabled(mExtensionBehavior, - TExtension::EXT_shader_framebuffer_fetch_non_coherent))) + const bool hasAnyClipCullDistance = + parseContext.isExtensionEnabled(TExtension::ANGLE_clip_cull_distance) || + parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance) || + parseContext.isExtensionEnabled(TExtension::APPLE_clip_distance); + if (hasAnyClipCullDistance) { - if (!RemoveUnusedFramebufferFetch(this, root, &mSymbolTable)) - { - return false; - } + mClipDistanceSize = static_cast(parseContext.getClipDistanceArraySize()); + mCullDistanceSize = static_cast(parseContext.getCullDistanceArraySize()); + mMetadataFlags[MetadataFlags::HasClipDistance] = parseContext.isClipDistanceUsed(); } - // For now, rewrite pixel local storage before collecting variables or any operations on images. - // - // TODO(anglebug.com/40096838): - // Should this actually run after collecting variables? - // Do we need more introspection? - // Do we want to hide rewritten shader image uniforms from glGetActiveUniform? - if (hasPixelLocalStorageUniforms()) + if (!useIR) { - ASSERT( - IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_shader_pixel_local_storage)); - if (!RewritePixelLocalStorage(this, root, getSymbolTable(), compileOptions, - getShaderVersion())) + // Turn |inout| variables that are never read from into |out| before collecting variables + // and before PLS uses them. + if (mShaderVersion >= 300 && + (IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_shader_framebuffer_fetch) || + IsExtensionEnabled(mExtensionBehavior, + TExtension::EXT_shader_framebuffer_fetch_non_coherent))) { - mDiagnostics.globalError("internal compiler error translating pixel local storage"); - return false; + if (!RemoveUnusedFramebufferFetch(this, root, &mSymbolTable)) + { + return false; + } } - } - if (shouldRunLoopAndIndexingValidation(compileOptions) && - !ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics)) - { - return false; - } + // Fold expressions that could not be folded before validation that was done as a part of + // parsing. + if (!FoldExpressions(this, root, &mDiagnostics)) + { + return false; + } + // Folding should only be able to generate warnings. + ASSERT(mDiagnostics.numErrors() == 0); - if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics)) - { - return false; - } + if (hasAnyClipCullDistance) + { + // gl_ClipDistance and gl_CullDistance built-in arrays have unique semantics. + // They are pre-declared as unsized and must be sized by the shader either + // redeclaring them or indexing them only with integral constant expressions. + // The translator treats them as having the maximum allowed size and this pass + // applies the actual sizes if needed. + if (mClipDistanceSize > 0 && !parseContext.isClipDistanceRedeclared() && + !SizeClipCullDistance(this, root, ImmutableString("gl_ClipDistance"), + mClipDistanceSize)) + { - // Fold expressions that could not be folded before validation that was done as a part of - // parsing. - if (!FoldExpressions(this, root, &mDiagnostics)) - { - return false; - } - // Folding should only be able to generate warnings. - ASSERT(mDiagnostics.numErrors() == 0); + return false; + } + if (mCullDistanceSize > 0 && !parseContext.isCullDistanceRedeclared() && + !SizeClipCullDistance(this, root, ImmutableString("gl_CullDistance"), + mCullDistanceSize)) + { + return false; + } + } - // gl_ClipDistance and gl_CullDistance built-in arrays have unique semantics. - // They are pre-declared as unsized and must be sized by the shader either - // redeclaring them or indexing them only with integral constant expressions. - // The translator treats them as having the maximum allowed size and this pass - // detects the actual sizes resizing the variables if needed. - if (parseContext.isExtensionEnabled(TExtension::ANGLE_clip_cull_distance) || - parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance) || - parseContext.isExtensionEnabled(TExtension::APPLE_clip_distance)) - { - bool isClipDistanceUsed = false; - if (!ValidateClipCullDistance(this, root, &mDiagnostics, - mResources.MaxCombinedClipAndCullDistances, - &mClipDistanceSize, &mCullDistanceSize, &isClipDistanceUsed)) + // We prune no-ops to work around driver bugs and to keep AST processing and output simple. + // The following kinds of no-ops are pruned: + // 1. Empty declarations "int;". + // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision + // for float, so float literal statements would end up with no precision which is + // invalid ESSL. + // 3. Any unreachable statement after a discard, return, break or continue. + // After this empty declarations are not allowed in the AST. + if (!PruneNoOps(this, root, &mSymbolTable)) { return false; } - mMetadataFlags[MetadataFlags::HasClipDistance] = isClipDistanceUsed; + mValidateASTOptions.validateNoStatementsAfterBranch = true; } - // Validate no barrier() after return before prunning it in |PruneNoOps()| below. - if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics)) - { - return false; - } - - // We prune no-ops to work around driver bugs and to keep AST processing and output simple. - // The following kinds of no-ops are pruned: - // 1. Empty declarations "int;". - // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision - // for float, so float literal statements would end up with no precision which is - // invalid ESSL. - // 3. Any unreachable statement after a discard, return, break or continue. - // After this empty declarations are not allowed in the AST. - if (!PruneNoOps(this, root, &mSymbolTable)) - { - return false; - } - mValidateASTOptions.validateNoStatementsAfterBranch = true; - - // We need to generate globals early if we have non constant initializers enabled - bool initializeLocalsAndGlobals = - compileOptions.initializeUninitializedLocals && !IsOutputHLSL(getOutputType()); + // We need to generate globals early if we have non constant initializers enabled. + bool initializeLocalsAndGlobals = compileOptions.initializeUninitializedLocals; bool canUseLoopsToInitialize = !compileOptions.dontUseLoopsToInitializeVariables; - bool highPrecisionSupported = isHighPrecisionSupported(); bool enableNonConstantInitializers = IsExtensionEnabled( mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers); - // forceDeferNonConstGlobalInitializers is needed for MSL - // to convert a non-const global. For example: - // - // int someGlobal = 123; - // - // to - // - // int someGlobal; - // void main() { - // someGlobal = 123; - // - // This is because MSL doesn't allow statically initialized non-const globals. - bool forceDeferNonConstGlobalInitializers = getOutputType() == SH_MSL_METAL_OUTPUT; - - if (enableNonConstantInitializers && - !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, - highPrecisionSupported, forceDeferNonConstGlobalInitializers, - &mSymbolTable)) - { - return false; - } - - // Create the function DAG and check there is no recursion - if (!initCallDag(root)) - { - return false; - } - if (compileOptions.limitCallStackDepth && !checkCallDepth()) + if (!useIR) { - return false; - } + if (enableNonConstantInitializers && + !DeferGlobalInitializers( + this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, + compileOptions.forceDeferNonConstGlobalInitializers, &mSymbolTable)) + { + return false; + } - // Checks which functions are used and if "main" exists - mFunctionMetadata.clear(); - mFunctionMetadata.resize(mCallDag.size()); - if (!tagUsedFunctions()) - { - return false; - } + // Create the function DAG. + initCallDag(root); - if (!pruneUnusedFunctions(root)) - { - return false; - } + // Checks which functions are used + mFunctionMetadata.clear(); + mFunctionMetadata.resize(mCallDag.size()); + tagUsedFunctions(); - if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion)) - { - if (!ReplaceShadowingVariables(this, root, &mSymbolTable)) + if (!pruneUnusedFunctions(root)) { return false; } - } - - if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType)) - { - return false; - } - - // anglebug.com/42265954: The ESSL spec has a bug with images as function arguments. The - // recommended workaround is to inline functions that accept image arguments. - if (mShaderVersion >= 310 && !MonomorphizeUnsupportedFunctions( - this, root, &mSymbolTable, - UnsupportedFunctionArgsBitSet{UnsupportedFunctionArgs::Image})) - { - return false; - } - if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER && - !ValidateOutputs(root, getExtensionBehavior(), mResources, hasPixelLocalStorageUniforms(), - IsWebGLBasedSpec(mShaderSpec), &mDiagnostics)) - { - return false; + if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion)) + { + if (!ReplaceShadowingVariables(this, root, &mSymbolTable)) + { + return false; + } + } } - // Clamping uniform array bounds needs to happen after validateLimitations pass. - if (compileOptions.clampIndirectArrayBounds) + // For now, rewrite pixel local storage before collecting variables or any operations on images. + // + // TODO(anglebug.com/40096838): + // Should this actually run after collecting variables? + // Do we need more introspection? + // Do we want to hide rewritten shader image uniforms from glGetActiveUniform? + if (hasPixelLocalStorageUniforms()) { - if (!ClampIndirectIndices(this, root, &mSymbolTable)) + ASSERT( + IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_shader_pixel_local_storage)); + if (!RewritePixelLocalStorage(this, root, getSymbolTable(), compileOptions, + getShaderVersion())) { + mDiagnostics.globalError("internal compiler error translating pixel local storage"); return false; } } @@ -994,37 +1005,42 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, } } - // This pass might emit short circuits so keep it before the short circuit unfolding - if (compileOptions.rewriteDoWhileLoops) + if (!useIR) { - if (!RewriteDoWhile(this, root, &mSymbolTable)) + if (compileOptions.addAndTrueToLoopCondition) { - return false; + if (!AddAndTrueToLoopCondition(this, root)) + { + return false; + } } - } - if (compileOptions.addAndTrueToLoopCondition) - { - if (!AddAndTrueToLoopCondition(this, root)) + if (compileOptions.unfoldShortCircuit) { - return false; + if (!UnfoldShortCircuitAST(this, root)) + { + return false; + } } - } - if (compileOptions.unfoldShortCircuit) - { - if (!UnfoldShortCircuitAST(this, root)) + if (compileOptions.regenerateStructNames) { - return false; + if (!RegenerateStructNames(this, root, &mSymbolTable)) + { + return false; + } } } - if (compileOptions.regenerateStructNames) + // https://crbug.com/437678149: + // On Mac, if ANGLE internal uniforms are not placed on the top of ANGLE_UserUniforms struct, + // the other user-defined uniforms are not intercepted correctly by the shader code. + // Sort user-defined uniforms first before adding ANGLE internal uniforms like + // angle_DrawID on top of them, so that the sort doesn't reorder the ANGLE internal uniforms + // and trigger the bug on Mac. + if (!sortUniforms(root)) { - if (!RegenerateStructNames(this, root, &mSymbolTable)) - { - return false; - } + return false; } if (mShaderType == GL_VERTEX_SHADER && @@ -1065,130 +1081,91 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, } } - if (compileOptions.simplifyLoopConditions) + // Needs to run before SimplifyLoopConditions to be able to detect |for| loops correctly. + if (compileOptions.ensureLoopForwardProgress) { - if (!SimplifyLoopConditions(this, root, &getSymbolTable())) + if (!EnsureLoopForwardProgress(this, root)) { return false; } } - else + + if (!useIR) { - // Split multi declarations and remove calls to array length(). - // Note that SimplifyLoopConditions needs to be run before any other AST transformations - // that may need to generate new statements from loop conditions or loop expressions. - if (!SimplifyLoopConditions(this, root, - IntermNodePatternMatcher::kMultiDeclaration | - IntermNodePatternMatcher::kArrayLengthMethod, - &getSymbolTable())) + if (compileOptions.simplifyLoopConditions) + { + if (!SimplifyLoopConditions(this, root, &getSymbolTable())) + { + return false; + } + } + else + { + // Split multi declarations and remove calls to array length(). + // Note that SimplifyLoopConditions needs to be run before any other AST transformations + // that may need to generate new statements from loop conditions or loop expressions. + if (!SimplifyLoopConditions(this, root, + IntermNodePatternMatcher::kMultiDeclaration | + IntermNodePatternMatcher::kArrayLengthMethod, + &getSymbolTable())) + { + return false; + } + } + + // Note that separate declarations need to be run before other AST transformations that + // generate new statements from expressions. + if (!SeparateDeclarations(*this, *root, mCompileOptions.separateCompoundStructDeclarations)) { return false; } } - // Note that separate declarations need to be run before other AST transformations that - // generate new statements from expressions. - if (!SeparateDeclarations(*this, *root, mCompileOptions.separateCompoundStructDeclarations)) - { - return false; - } + mValidateASTOptions.validateMultiDeclarations = true; - if (IsWebGLBasedSpec(mShaderSpec)) + if (!useIR) { - // Remove infinite loops, they are not supposed to exist in shaders. - bool anyInfiniteLoops = false; - if (!PruneInfiniteLoops(this, root, &mSymbolTable, &anyInfiniteLoops)) + if (!SplitSequenceOperator(this, root, IntermNodePatternMatcher::kArrayLengthMethod, + &getSymbolTable())) { return false; } - // If requested, reject shaders with infinite loops. If not requested, the same loops are - // removed from the shader as a fallback. - if (anyInfiniteLoops && mCompileOptions.rejectWebglShadersWithUndefinedBehavior) + if (!RemoveArrayLengthMethod(this, root)) { - mDiagnostics.globalError("Infinite loop detected in the shader"); return false; } - } - - if (compileOptions.rescopeGlobalVariables) - { - if (!RescopeGlobalVariables(*this, *root)) + // Fold the expressions again, because |RemoveArrayLengthMethod| can introduce new + // constants. + if (!FoldExpressions(this, root, &mDiagnostics)) { return false; } - } - - mValidateASTOptions.validateMultiDeclarations = true; - - if (!SplitSequenceOperator(this, root, IntermNodePatternMatcher::kArrayLengthMethod, - &getSymbolTable())) - { - return false; - } - - if (!RemoveArrayLengthMethod(this, root)) - { - return false; - } - // Fold the expressions again, because |RemoveArrayLengthMethod| can introduce new constants. - if (!FoldExpressions(this, root, &mDiagnostics)) - { - return false; - } - - if (!RemoveUnreferencedVariables(this, root, &mSymbolTable)) - { - return false; - } - - // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in - // drivers may not accept it. In this case we clean up the dead code from the end of switch - // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have - // left switch statements that only contained an empty declaration inside the final case in an - // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been - // run. - if (!PruneEmptyCases(this, root)) - { - return false; - } - - // Run after RemoveUnreferencedVariables, validate that the shader does not have excessively - // large variables. - if (shouldLimitTypeSizes() && !ValidateTypeSizeLimitations(root, &mSymbolTable, &mDiagnostics)) - { - return false; - } - // Built-in function emulation needs to happen after validateLimitations pass. - GetGlobalPoolAllocator()->lock(); - initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions); - GetGlobalPoolAllocator()->unlock(); - mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root); - - if (compileOptions.scalarizeVecAndMatConstructorArgs) - { - if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable)) + if (!RemoveUnreferencedVariables(this, root, &mSymbolTable)) { return false; } - } - if (compileOptions.forceShaderPrecisionHighpToMediump) - { - if (!ForceShaderPrecisionToMediump(root, &mSymbolTable, mShaderType)) + // In case the last case inside a switch statement is a certain type of no-op, GLSL + // compilers in drivers may not accept it. In this case we clean up the dead code from the + // end of switch statements. This is also required because PruneNoOps or + // RemoveUnreferencedVariables may have left switch statements that only contained an empty + // declaration inside the final case in an invalid state. Relies on that PruneNoOps and + // RemoveUnreferencedVariables have already been run. + if (!PruneEmptyCases(this, root)) { return false; } } - ASSERT(!mVariablesCollected); - CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings, - &mOutputVaryings, &mSharedVariables, &mUniformBlocks, &mShaderStorageBlocks, - mResources.HashFunction, &mSymbolTable, mShaderType, mExtensionBehavior, - mResources, mTessControlShaderOutputVertices); - collectInterfaceBlocks(); - mVariablesCollected = true; + GetGlobalPoolAllocator()->lock(); + initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions); + GetGlobalPoolAllocator()->unlock(); + mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root); + + collectVariables(root); + if (compileOptions.useUnusedStandardSharedBlocks) { if (!useAllMembersInUnusedStandardAndSharedBlocks(root)) @@ -1211,18 +1188,52 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, return false; } } - bool needInitializeOutputVariables = - compileOptions.initOutputVariables && mShaderType != GL_COMPUTE_SHADER; - needInitializeOutputVariables |= - compileOptions.initFragmentOutputVariables && mShaderType == GL_FRAGMENT_SHADER; - if (needInitializeOutputVariables) + + if (compileOptions.scalarizeVecAndMatConstructorArgs) { - if (!initializeOutputVariables(root)) + if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable)) { return false; } } + if (compileOptions.clampIndirectArrayBounds) + { + if (!ClampIndirectIndices(this, root, &mSymbolTable)) + { + return false; + } + } + + // Remove declarations of inactive shader interface variables so backends don't need to account + // for them. Note that currently, CollectVariables marks every field of an active uniform + // that's of struct type as active, i.e. no extracted sampler is inactive, so this can be done + // before extracting samplers from structs. + // + // For the MSL output, keep the inactive fragment outputs, but remove them otherwise. + if (compileOptions.removeInactiveVariables) + { + const bool removeFragmentOutputs = mOutputType != SH_MSL_METAL_OUTPUT; + + if (!RemoveInactiveInterfaceVariables( + this, root, &getSymbolTable(), getAttributes(), getInputVaryings(), + getOutputVariables(), getUniforms(), getInterfaceBlocks(), removeFragmentOutputs)) + { + return false; + } + } + + if (!useIR) + { + if (compileOptions.initOutputVariables) + { + if (!initializeOutputVariables(root)) + { + return false; + } + } + } + // Removing invariant declarations must be done after collecting variables. // Otherwise, built-in invariant declarations don't apply. if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions)) @@ -1233,32 +1244,33 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, } } - // gl_Position is always written in compatibility output mode. - // It may have been already initialized among other output variables, in that case we don't - // need to initialize it twice. - if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized && - (compileOptions.initGLPosition || mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT)) + if (!useIR) { - if (!initializeGLPosition(root)) + // gl_Position may have already been initialized among other output variables, in that case + // we don't need to initialize it twice. + if (!mGLPositionInitialized && compileOptions.initGLPosition) { - return false; + if (!initializeGLPosition(root)) + { + return false; + } + mGLPositionInitialized = true; } - mGLPositionInitialized = true; - } - // DeferGlobalInitializers needs to be run before other AST transformations that generate new - // statements from expressions. But it's fine to run DeferGlobalInitializers after the above - // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST - // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00. - // Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global - // initializers before we generate the DAG, since initializers may call functions which must not - // be optimized out - if (!enableNonConstantInitializers && - !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, - highPrecisionSupported, forceDeferNonConstGlobalInitializers, - &mSymbolTable)) - { - return false; + // DeferGlobalInitializers needs to be run before other AST transformations that generate + // new statements from expressions. But it's fine to run DeferGlobalInitializers after the + // above SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on + // the AST on ESSL >= 3.00, and the initializers that need to be deferred can only exist in + // ESSL < 3.00. Exception: if EXT_shader_non_constant_global_initializers is enabled, we + // must generate global initializers before we generate the DAG, since initializers may call + // functions which must not be optimized out + if (!enableNonConstantInitializers && + !DeferGlobalInitializers( + this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, + compileOptions.forceDeferNonConstGlobalInitializers, &mSymbolTable)) + { + return false; + } } if (initializeLocalsAndGlobals) @@ -1282,10 +1294,13 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, } } - if (!InitializeUninitializedLocals(this, root, getShaderVersion(), canUseLoopsToInitialize, - highPrecisionSupported, &getSymbolTable())) + if (!useIR) { - return false; + if (!InitializeUninitializedLocals(this, root, getShaderVersion(), + canUseLoopsToInitialize, &getSymbolTable())) + { + return false; + } } } @@ -1306,11 +1321,14 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, } } - if (compileOptions.rewriteRepeatedAssignToSwizzled) + if (!useIR) { - if (!sh::RewriteRepeatedAssignToSwizzled(this, root)) + if (compileOptions.rewriteRepeatedAssignToSwizzled) { - return false; + if (!sh::RewriteRepeatedAssignToSwizzled(this, root)) + { + return false; + } } } @@ -1325,52 +1343,53 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, return true; } -bool TCompiler::postParseChecks(const TParseContext &parseContext) +ShCompileOptions TCompiler::adjustOptions(const ShCompileOptions &compileOptionsIn) { - std::stringstream errorMessage; + ShCompileOptions compileOptions = compileOptionsIn; - if (parseContext.getTreeRoot() == nullptr) + // Apply key workarounds. + if (shouldFlattenPragmaStdglInvariantAll()) { - errorMessage << "Shader parsing failed (mTreeRoot == nullptr)"; + // This should be harmless to do in all cases, but for the moment, do it only conditionally. + compileOptions.flattenPragmaSTDGLInvariantAll = true; } - for (TType *type : parseContext.getDeferredArrayTypesToSize()) + // Disable options that are not applicable. + if (mShaderType == GL_COMPUTE_SHADER) { - errorMessage << "Unsized global array type: " << type->getBasicString(); + compileOptions.initOutputVariables = false; + } + if (mShaderType != GL_VERTEX_SHADER) + { + compileOptions.initGLPosition = false; } - if (!errorMessage.str().empty()) + // gl_Position should always be written in GLSL compatibility output mode. + if (mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT && mShaderType == GL_VERTEX_SHADER) { - mDiagnostics.globalError(errorMessage.str().c_str()); - return false; + compileOptions.initGLPosition = true; } - return true; + return compileOptions; } -bool TCompiler::compile(const char *const shaderStrings[], - size_t numStrings, +bool TCompiler::compile(angle::Span shaderStrings, const ShCompileOptions &compileOptionsIn) { #if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) - DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType, - compileOptionsIn); + DumpFuzzerCase(shaderStrings.data(), shaderStrings.size(), mShaderType, mShaderSpec, + mOutputType, compileOptionsIn); #endif // defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) - if (numStrings == 0) - return true; - - ShCompileOptions compileOptions = compileOptionsIn; - - // Apply key workarounds. - if (shouldFlattenPragmaStdglInvariantAll()) + if (shaderStrings.empty()) { - // This should be harmless to do in all cases, but for the moment, do it only conditionally. - compileOptions.flattenPragmaSTDGLInvariantAll = true; + return true; } - TScopedPoolAllocator scopedAlloc(&allocator); - TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); + const ShCompileOptions compileOptions = adjustOptions(compileOptionsIn); + + TScopedPoolAllocator scopedAlloc; + TIntermBlock *root = compileTreeImpl(shaderStrings, compileOptions); if (root) { @@ -1379,7 +1398,7 @@ bool TCompiler::compile(const char *const shaderStrings[], OutputTree(root, mInfoSink.info); } - if (compileOptions.objectCode) + if (compileOptions.objectCode && !compileOptions.skipAllValidationAndTransforms) { PerformanceDiagnostics perfDiagnostics(&mDiagnostics); if (!translate(root, compileOptions, &perfDiagnostics)) @@ -1458,13 +1477,16 @@ void TCompiler::setResourceString() << ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits << ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors << ":MaxDrawBuffers:" << mResources.MaxDrawBuffers + << ":ShadingRateFlag2VerticalPixelsEXT:" << mResources.ShadingRateFlag2VerticalPixelsEXT + << ":ShadingRateFlag2VerticalPixelsEXT:" << mResources.ShadingRateFlag2VerticalPixelsEXT + << ":ShadingRateFlag2HorizontalPixelsEXT:" << mResources.ShadingRateFlag2HorizontalPixelsEXT + << ":ShadingRateFlag4HorizontalPixelsEXT:" << mResources.ShadingRateFlag4HorizontalPixelsEXT << ":OES_standard_derivatives:" << mResources.OES_standard_derivatives << ":OES_EGL_image_external:" << mResources.OES_EGL_image_external << ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl3 << ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external << ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle << ":EXT_draw_buffers:" << mResources.EXT_draw_buffers - << ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh << ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity << ":MaxStatementDepth:" << mResources.MaxStatementDepth << ":MaxCallStackDepth:" << mResources.MaxCallStackDepth @@ -1478,7 +1500,6 @@ void TCompiler::setResourceString() << ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod << ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch << ":EXT_shader_framebuffer_fetch_non_coherent:" << mResources.EXT_shader_framebuffer_fetch_non_coherent - << ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch << ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch << ":ARM_shader_framebuffer_fetch_depth_stencil:" << mResources.ARM_shader_framebuffer_fetch_depth_stencil << ":OVR_multiview2:" << mResources.OVR_multiview2 @@ -1511,6 +1532,8 @@ void TCompiler::setResourceString() << ":OES_tessellation_shader:" << mResources.OES_tessellation_shader << ":OES_texture_buffer:" << mResources.OES_texture_buffer << ":EXT_texture_buffer:" << mResources.EXT_texture_buffer + << ":EXT_fragment_shading_rate:" << mResources.EXT_fragment_shading_rate + << ":EXT_fragment_shading_rate_primitive:" << mResources.EXT_fragment_shading_rate_primitive << ":OES_sample_variables:" << mResources.OES_sample_variables << ":EXT_clip_cull_distance:" << mResources.EXT_clip_cull_distance << ":ANGLE_clip_cull_distance:" << mResources.ANGLE_clip_cull_distance @@ -1542,7 +1565,6 @@ void TCompiler::setResourceString() << ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers << ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize << ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents - << ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks << ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents << ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents << ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices @@ -1550,7 +1572,6 @@ void TCompiler::setResourceString() << ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits << ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers << ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters - << ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks << ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations << ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms << ":MaxClipDistances" << mResources.MaxClipDistances @@ -1579,6 +1600,18 @@ void TCompiler::setResourceString() mBuiltInResourcesString = strstream.str(); } +void TCompiler::collectVariables(TIntermBlock *root) +{ + ASSERT(!mVariablesCollected); + CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings, + &mOutputVaryings, &mSharedVariables, &mUniformBlocks, &mShaderStorageBlocks, + mResources.UserVariableNamePrefix, mResources.HashFunction, &mSymbolTable, + mShaderType, mExtensionBehavior, mResources, mTessControlShaderOutputVertices, + mCompileOptions.transformFloatUniformTo16Bits); + collectInterfaceBlocks(); + mVariablesCollected = true; +} + void TCompiler::collectInterfaceBlocks() { ASSERT(mInterfaceBlocks.empty()); @@ -1635,95 +1668,24 @@ void TCompiler::clearResults() mSymbolTable.clearCompilationResults(); } -bool TCompiler::initCallDag(TIntermNode *root) +void TCompiler::initCallDag(TIntermNode *root) { mCallDag.clear(); - - switch (mCallDag.init(root, &mDiagnostics)) - { - case CallDAG::INITDAG_SUCCESS: - return true; - case CallDAG::INITDAG_RECURSION: - case CallDAG::INITDAG_UNDEFINED: - // Error message has already been written out. - ASSERT(mDiagnostics.numErrors() > 0); - return false; - } - - UNREACHABLE(); - return true; -} - -bool TCompiler::checkCallDepth() -{ - std::vector depths(mCallDag.size()); - - for (size_t i = 0; i < mCallDag.size(); i++) - { - int depth = 0; - const CallDAG::Record &record = mCallDag.getRecordFromIndex(i); - - for (int calleeIndex : record.callees) - { - depth = std::max(depth, depths[calleeIndex] + 1); - } - - depths[i] = depth; - - if (depth >= mResources.MaxCallStackDepth) - { - // Trace back the function chain to have a meaningful info log. - std::stringstream errorStream = sh::InitializeStream(); - errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth - << ") with the following call chain: " - << record.node->getFunction()->name(); - - int currentFunction = static_cast(i); - int currentDepth = depth; - - while (currentFunction != -1) - { - errorStream - << " -> " - << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name(); - - int nextFunction = -1; - for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees) - { - if (depths[calleeIndex] == currentDepth - 1) - { - currentDepth--; - nextFunction = calleeIndex; - } - } - - currentFunction = nextFunction; - } - - std::string errorStr = errorStream.str(); - mDiagnostics.globalError(errorStr.c_str()); - - return false; - } - } - - return true; + mCallDag.init(root); } -bool TCompiler::tagUsedFunctions() +void TCompiler::tagUsedFunctions() { - // Search from main, starting from the end of the DAG as it usually is the root. + // Search from main, starting from the end of the DAG as it's usually found at the end of the + // shader. for (size_t i = mCallDag.size(); i-- > 0;) { if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain()) { internalTagUsedFunction(i); - return true; + break; } } - - mDiagnostics.globalError("Missing main()"); - return false; } void TCompiler::internalTagUsedFunction(size_t index) @@ -1741,6 +1703,52 @@ void TCompiler::internalTagUsedFunction(size_t index) } } +bool TCompiler::sortUniforms(TIntermBlock *root) +{ + // First: Separate sequences into three chunks + TIntermSequence structTypeDeclarationSequence; + TIntermSequence uniformDeclarationSequence; + TIntermSequence remainingSequence; + + TIntermSequence *sequence = root->getSequence(); + size_t nodeIndex = 0; + while (nodeIndex < sequence->size()) + { + TIntermNode *node = sequence->at(nodeIndex); + if (IsCurrentNodeStructTypeDeclaration(node)) + { + structTypeDeclarationSequence.push_back(node); + } + else if (IsCurrentNodeUniformDeclaration(node)) + { + uniformDeclarationSequence.push_back(node); + } + else + { + remainingSequence.push_back(node); + } + ++nodeIndex; + } + + // Second: Sort uniforms based on their precisions and data types + std::stable_sort(uniformDeclarationSequence.begin(), uniformDeclarationSequence.end(), + UniformSortComparator()); + + // Third: merge three chunks + TIntermSequence reorderedSequence; + reorderedSequence.reserve(structTypeDeclarationSequence.size() + + uniformDeclarationSequence.size() + remainingSequence.size()); + std::move(structTypeDeclarationSequence.begin(), structTypeDeclarationSequence.end(), + std::back_inserter(reorderedSequence)); + std::move(uniformDeclarationSequence.begin(), uniformDeclarationSequence.end(), + std::back_inserter(reorderedSequence)); + std::move(remainingSequence.begin(), remainingSequence.end(), + std::back_inserter(reorderedSequence)); + + root->replaceAllChildren(std::move(reorderedSequence)); + return validateAST(root); +} + bool TCompiler::pruneUnusedFunctions(TIntermBlock *root) { TIntermSequence *sequence = root->getSequence(); @@ -1795,12 +1803,6 @@ bool TCompiler::limitExpressionComplexity(TIntermBlock *root) return false; } - if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters)) - { - mDiagnostics.globalError("Function has too many parameters."); - return false; - } - return true; } @@ -1812,7 +1814,7 @@ bool TCompiler::initializeGLPosition(TIntermBlock *root) if (!list.empty()) { return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, - mExtensionBehavior, false, false); + mExtensionBehavior, false); } return true; @@ -1836,6 +1838,32 @@ bool TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) bool TCompiler::initializeOutputVariables(TIntermBlock *root) { + // Place `main` at the end of the shader if not already. If a variable is declared after main, + // main cannot reference it. + { + const TIntermSequence *original = root->getSequence(); + TIntermSequence reordered; + TIntermNode *main = nullptr; + + for (TIntermNode *node : *original) + { + TIntermFunctionDefinition *function = node->getAsFunctionDefinition(); + if (function != nullptr && function->getFunction()->isMain()) + { + ASSERT(main == nullptr); + main = node; + } + else + { + reordered.push_back(node); + } + } + ASSERT(main != nullptr); + reordered.push_back(main); + + root->replaceAllChildren(std::move(reordered)); + } + InitVariableList list; for (TIntermNode *node : *root->getSequence()) @@ -1884,7 +1912,7 @@ bool TCompiler::initializeOutputVariables(TIntermBlock *root) } return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior, - false, false); + false); } const TExtensionBehavior &TCompiler::getExtensionBehavior() const diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h index 865c738a11d..c23d428a572 100644 --- a/src/compiler/translator/Compiler.h +++ b/src/compiler/translator/Compiler.h @@ -17,6 +17,7 @@ #include #include "common/PackedEnums.h" +#include "common/span.h" #include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/CallDAG.h" #include "compiler/translator/Diagnostics.h" @@ -100,12 +101,10 @@ class TCompiler : public TShHandleBase // compileTreeForTesting should be used only when tests require access to // the AST. Users of this function need to manually manage the global pool // allocator. Returns nullptr whenever there are compilation errors. - TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, + TIntermBlock *compileTreeForTesting(angle::Span shaderStrings, const ShCompileOptions &compileOptions); - bool compile(const char *const shaderStrings[], - size_t numStrings, + bool compile(angle::Span shaderStrings, const ShCompileOptions &compileOptions); // Get results of the last compilation. @@ -137,6 +136,7 @@ class TCompiler : public TShHandleBase } ShHashFunction64 getHashFunction() const { return mResources.HashFunction; } + char getUserVariableNamePrefix() const { return mResources.UserVariableNamePrefix; } NameMap &getNameMap() { return mNameMap; } TSymbolTable &getSymbolTable() { return mSymbolTable; } ShShaderSpec getShaderSpec() const { return mShaderSpec; } @@ -144,10 +144,7 @@ class TCompiler : public TShHandleBase const ShBuiltInResources &getBuiltInResources() const { return mResources; } const std::string &getBuiltInResourcesString() const { return mBuiltInResourcesString; } - bool isHighPrecisionSupported() const; - bool shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const; - bool shouldLimitTypeSizes() const; // Get the resources set by InitBuiltInSymbolTable const ShBuiltInResources &getResources() const; @@ -190,7 +187,7 @@ class TCompiler : public TShHandleBase AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; } bool hasPixelLocalStorageUniforms() const { return !mPixelLocalStorageFormats.empty(); } - const std::vector &GetPixelLocalStorageFormats() const + const std::vector &getPixelLocalStorageFormats() const { return mPixelLocalStorageFormats; } @@ -203,8 +200,7 @@ class TCompiler : public TShHandleBase // Generate a self-contained binary representation of the shader. bool getShaderBinary(const ShHandle compilerHandle, - const char *const shaderStrings[], - size_t numStrings, + angle::Span shaderStrings, const ShCompileOptions &compileOptions, ShaderBinaryBlob *const binaryOut); @@ -236,6 +232,9 @@ class TCompiler : public TShHandleBase return mShaderVersion == 100 && !IsWebGLBasedSpec(mShaderSpec); } + // Get built-in extensions with default behavior. + const TExtensionBehavior &getExtensionBehavior() const; + protected: // Add emulated functions to the built-in function emulator. virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, @@ -245,8 +244,6 @@ class TCompiler : public TShHandleBase [[nodiscard]] virtual bool translate(TIntermBlock *root, const ShCompileOptions &compileOptions, PerformanceDiagnostics *perfDiagnostics) = 0; - // Get built-in extensions with default behavior. - const TExtensionBehavior &getExtensionBehavior() const; const char *getSourcePath() const; // Relies on collectVariables having been called. bool isVaryingDefined(const char *varyingName); @@ -278,8 +275,6 @@ class TCompiler : public TShHandleBase bool initBuiltInSymbolTable(const ShBuiltInResources &resources); // Compute the string representation of the built-in resources void setResourceString(); - // Return false if the call depth is exceeded. - bool checkCallDepth(); // Insert statements to reference all members in unused uniform blocks with standard and shared // layout. This is to work around a Mac driver that treats unused standard/shared // uniform blocks as inactive. @@ -294,28 +289,26 @@ class TCompiler : public TShHandleBase [[nodiscard]] bool initializeGLPosition(TIntermBlock *root); // Return true if the maximum expression complexity is below the limit. bool limitExpressionComplexity(TIntermBlock *root); - // Creates the function call DAG for further analysis, returning false if there is a recursion - bool initCallDag(TIntermNode *root); - // Return false if "main" doesn't exist - bool tagUsedFunctions(); + // Creates the function call DAG for further analysis. + void initCallDag(TIntermNode *root); + void tagUsedFunctions(); void internalTagUsedFunction(size_t index); + void collectVariables(TIntermBlock *root); void collectInterfaceBlocks(); - bool mVariablesCollected; - - bool mGLPositionInitialized; + bool sortUniforms(TIntermBlock *root); // Removes unused function declarations and prototypes from the AST bool pruneUnusedFunctions(TIntermBlock *root); - TIntermBlock *compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, + ShCompileOptions adjustOptions(const ShCompileOptions &compileOptionsIn); + TIntermBlock *compileTreeImpl(angle::Span shaderStrings, const ShCompileOptions &compileOptions); // Fetches and stores shader metadata that is not stored within the AST itself, such as shader // version. - void setASTMetadata(const TParseContext &parseContext); + void setShaderMetadata(const TParseContext &parseContext); // Check if shader version meets the requirement. bool checkShaderVersion(TParseContext *parseContext); @@ -325,8 +318,6 @@ class TCompiler : public TShHandleBase const TParseContext &parseContext, const ShCompileOptions &compileOptions); - bool postParseChecks(const TParseContext &parseContext); - sh::GLenum mShaderType; ShShaderSpec mShaderSpec; ShShaderOutput mOutputType; @@ -351,6 +342,9 @@ class TCompiler : public TShHandleBase TDiagnostics mDiagnostics; const char *mSourcePath; // Path of source file or NULL + bool mVariablesCollected; + bool mGLPositionInitialized; + // Fragment shader early fragment tests bool mEarlyFragmentTestsSpecified; diff --git a/src/compiler/translator/Diagnostics.cpp b/src/compiler/translator/Diagnostics.cpp index 03066a319dd..90c505b5a55 100644 --- a/src/compiler/translator/Diagnostics.cpp +++ b/src/compiler/translator/Diagnostics.cpp @@ -10,16 +10,26 @@ #include "compiler/preprocessor/SourceLocation.h" #include "compiler/translator/Common.h" #include "compiler/translator/InfoSink.h" +#include "compiler/translator/ir/src/builder.h" namespace sh { TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink) - : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0) + : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0), mIRBuilder(nullptr) {} TDiagnostics::~TDiagnostics() {} +void TDiagnostics::onError() +{ + ++mNumErrors; + if (mIRBuilder != nullptr) + { + mIRBuilder->onError(); + } +} + void TDiagnostics::writeInfo(Severity severity, const angle::pp::SourceLocation &loc, const char *reason, @@ -28,7 +38,7 @@ void TDiagnostics::writeInfo(Severity severity, switch (severity) { case SH_ERROR: - ++mNumErrors; + onError(); break; case SH_WARNING: ++mNumWarnings; @@ -46,7 +56,7 @@ void TDiagnostics::writeInfo(Severity severity, void TDiagnostics::globalError(const char *message) { - ++mNumErrors; + onError(); mInfoSink.prefix(SH_ERROR); mInfoSink << message << "\n"; } diff --git a/src/compiler/translator/Diagnostics.h b/src/compiler/translator/Diagnostics.h index 8ed71b3d2b8..7eeda76c8cd 100644 --- a/src/compiler/translator/Diagnostics.h +++ b/src/compiler/translator/Diagnostics.h @@ -13,11 +13,15 @@ namespace sh { +namespace ir +{ +class Builder; +} class TInfoSinkBase; struct TSourceLoc; -class TDiagnostics : public angle::pp::Diagnostics, angle::NonCopyable +class TDiagnostics final : public angle::pp::Diagnostics, angle::NonCopyable { public: TDiagnostics(TInfoSinkBase &infoSink); @@ -36,7 +40,9 @@ class TDiagnostics : public angle::pp::Diagnostics, angle::NonCopyable void resetErrorCount(); - protected: + void setIRBuilder(ir::Builder *builder) { mIRBuilder = builder; } + + private: void writeInfo(Severity severity, const angle::pp::SourceLocation &loc, const char *reason, @@ -44,10 +50,14 @@ class TDiagnostics : public angle::pp::Diagnostics, angle::NonCopyable void print(ID id, const angle::pp::SourceLocation &loc, const std::string &text) override; - private: + void onError(); + TInfoSinkBase &mInfoSink; int mNumErrors; int mNumWarnings; + + // The IR builder needs to be notified on error to stop building the IR. + ir::Builder *mIRBuilder; }; // Diagnostics wrapper to use when the code is only allowed to generate warnings. diff --git a/src/compiler/translator/DirectiveHandler.cpp b/src/compiler/translator/DirectiveHandler.cpp index f4ad5f7ff9b..1f020baf73f 100644 --- a/src/compiler/translator/DirectiveHandler.cpp +++ b/src/compiler/translator/DirectiveHandler.cpp @@ -12,6 +12,7 @@ #include "common/debug.h" #include "compiler/translator/Common.h" #include "compiler/translator/Diagnostics.h" +#include "compiler/translator/ParseContext.h" namespace sh { @@ -36,11 +37,11 @@ static TBehavior getBehavior(const std::string &str) TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, TDiagnostics &diagnostics, - int &shaderVersion, + TParseContext &context, sh::GLenum shaderType) : mExtensionBehavior(extBehavior), mDiagnostics(diagnostics), - mShaderVersion(shaderVersion), + mContext(context), mShaderType(shaderType) {} @@ -63,7 +64,7 @@ void TDirectiveHandler::handlePragma(const angle::pp::SourceLocation &loc, if (name == kInvariant && value == kAll) { - if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) + if (mContext.getShaderVersion() == 300 && mShaderType == GL_FRAGMENT_SHADER) { // ESSL 3.00.4 section 4.6.1 mDiagnostics.error( @@ -151,7 +152,8 @@ void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc, } TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); - if (iter != mExtensionBehavior.end() && CheckExtensionVersion(iter->first, mShaderVersion)) + if (iter != mExtensionBehavior.end() && + CheckExtensionVersion(iter->first, mContext.getShaderVersion())) { iter->second = behaviorVal; // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled @@ -269,6 +271,19 @@ void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc, iter->second = behaviorVal; } } + // GL_EXT_fragment_shading_rate_primitive is implicitly enabled when + // GL_EXT_fragment_shading_rate are enabled. + else if (name == "GL_EXT_fragment_shading_rate") + { + constexpr char kFragmentShadingRatePrimitiveEXTName[] = + "GL_EXT_fragment_shading_rate_primitive"; + iter = + mExtensionBehavior.find(GetExtensionByName(kFragmentShadingRatePrimitiveEXTName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + } return; } @@ -295,7 +310,7 @@ void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, { if (version == 100 || version == 300 || version == 310 || version == 320) { - mShaderVersion = version; + mContext.onShaderVersionDeclared(version); // Add macros for supported extensions for (const auto &iter : mExtensionBehavior) diff --git a/src/compiler/translator/DirectiveHandler.h b/src/compiler/translator/DirectiveHandler.h index c416d5d42df..087bc436ea1 100644 --- a/src/compiler/translator/DirectiveHandler.h +++ b/src/compiler/translator/DirectiveHandler.h @@ -17,13 +17,14 @@ namespace sh { class TDiagnostics; +class TParseContext; class TDirectiveHandler : public angle::pp::DirectiveHandler, angle::NonCopyable { public: TDirectiveHandler(TExtensionBehavior &extBehavior, TDiagnostics &diagnostics, - int &shaderVersion, + TParseContext &context, sh::GLenum shaderType); ~TDirectiveHandler() override; @@ -50,7 +51,7 @@ class TDirectiveHandler : public angle::pp::DirectiveHandler, angle::NonCopyable TPragma mPragma; TExtensionBehavior &mExtensionBehavior; TDiagnostics &mDiagnostics; - int &mShaderVersion; + TParseContext &mContext; sh::GLenum mShaderType; }; diff --git a/src/compiler/translator/ExtensionBehavior.cpp b/src/compiler/translator/ExtensionBehavior.cpp index 8781c331b6e..92a84eee7a3 100644 --- a/src/compiler/translator/ExtensionBehavior.cpp +++ b/src/compiler/translator/ExtensionBehavior.cpp @@ -6,6 +6,10 @@ // ExtensionBehavior.cpp: Extension name enumeration and data structures for storing extension // behavior. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/ExtensionBehavior.h" #include "common/debug.h" @@ -17,6 +21,8 @@ // // Note that OES_EGL_image_external and OES_texture_3D are ESSL 100 only extensions, but one app has // been found that uses them on GLSL 310. http://issuetracker.google.com/285871779 +// Similarly, other applications have been found to use OES_EGL_image_external on GLSL 320. Refer to +// http://issuetracker.google.com/452565020 for details. // // Note that OES_texture_storage_multisample_2d_array officially requires ESSL 310 // but ANGLE is able to support it with ESSL 300 in most cases. @@ -36,6 +42,8 @@ OP(EXT_conservative_depth, 300, 320) \ OP(EXT_draw_buffers, 100, 100) \ OP(EXT_frag_depth, 100, 100) \ + OP(EXT_fragment_shading_rate, 310, 320) \ + OP(EXT_fragment_shading_rate_primitive, 310, 320) \ OP(EXT_geometry_shader, 310, 320) \ OP(OES_geometry_shader, 310, 320) \ OP(OES_shader_io_blocks, 310, 320) \ @@ -59,9 +67,8 @@ OP(EXT_YUV_target, 300, 320) \ OP(KHR_blend_equation_advanced, 100, 320) \ OP(NV_EGL_stream_consumer_external, 100, 320) \ - OP(NV_shader_framebuffer_fetch, 100, 100) \ OP(NV_shader_noperspective_interpolation, 300, 320) \ - OP(OES_EGL_image_external, 100, 310) \ + OP(OES_EGL_image_external, 100, 320) \ OP(OES_EGL_image_external_essl3, 300, 320) \ OP(OES_sample_variables, 300, 320) \ OP(OES_shader_multisample_interpolation, 300, 320) \ diff --git a/src/compiler/translator/ExtensionBehavior.h b/src/compiler/translator/ExtensionBehavior.h index b5c23f2c315..d01b45df503 100644 --- a/src/compiler/translator/ExtensionBehavior.h +++ b/src/compiler/translator/ExtensionBehavior.h @@ -36,6 +36,8 @@ enum class TExtension : uint8_t EXT_conservative_depth, EXT_draw_buffers, EXT_frag_depth, + EXT_fragment_shading_rate, + EXT_fragment_shading_rate_primitive, EXT_geometry_shader, EXT_gpu_shader5, EXT_primitive_bounding_box, @@ -55,7 +57,6 @@ enum class TExtension : uint8_t KHR_blend_equation_advanced, NV_EGL_stream_consumer_external, NV_fragment_shader_interlock, - NV_shader_framebuffer_fetch, NV_shader_noperspective_interpolation, OES_EGL_image_external, OES_EGL_image_external_essl3, diff --git a/src/compiler/translator/HashNames.cpp b/src/compiler/translator/HashNames.cpp index fc188ff582e..62b4f6d063f 100644 --- a/src/compiler/translator/HashNames.cpp +++ b/src/compiler/translator/HashNames.cpp @@ -55,23 +55,21 @@ void AddToNameMapIfNotMapped(const ImmutableString &name, } // anonymous namespace ImmutableString HashName(const ImmutableString &name, + char prefix, ShHashFunction64 hashFunction, NameMap *nameMap) { - const ImmutableString kUnhashedNamePrefix(kUserDefinedNamePrefix); - if (hashFunction == nullptr) { - if (name.length() + kUnhashedNamePrefix.length() > kESSLMaxIdentifierLength) + size_t kPrefixLength = 2; + if (!prefix || name.length() + kPrefixLength > kESSLMaxIdentifierLength) { // If the identifier length is already close to the limit, we can't prefix it. This is // not a problem since there are no builtins or ANGLE's internal variables that would // have as long names and could conflict. return name; } - ImmutableStringBuilder prefixedName(kUnhashedNamePrefix.length() + name.length()); - prefixedName << kUnhashedNamePrefix << name; - ImmutableString res = prefixedName; + ImmutableString res = BuildConcatenatedImmutableString('_', prefix, name); AddToNameMapIfNotMapped(name, res, nameMap); return res; } @@ -82,7 +80,10 @@ ImmutableString HashName(const ImmutableString &name, return hashedName; } -ImmutableString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap) +ImmutableString HashName(const TSymbol *symbol, + char prefix, + ShHashFunction64 hashFunction, + NameMap *nameMap) { if (symbol->symbolType() == SymbolType::Empty) { @@ -93,7 +94,7 @@ ImmutableString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, N { return symbol->name(); } - return HashName(symbol->name(), hashFunction, nameMap); + return HashName(symbol->name(), prefix, hashFunction, nameMap); } } // namespace sh diff --git a/src/compiler/translator/HashNames.h b/src/compiler/translator/HashNames.h index 37420951290..791fdf21abc 100644 --- a/src/compiler/translator/HashNames.h +++ b/src/compiler/translator/HashNames.h @@ -21,12 +21,16 @@ class ImmutableString; class TSymbol; ImmutableString HashName(const ImmutableString &name, + char prefix, ShHashFunction64 hashFunction, NameMap *nameMap); // Hash user-defined name for GLSL output, with special handling for internal names. // The nameMap parameter is optional and is used to cache hashed names if set. -ImmutableString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap); +ImmutableString HashName(const TSymbol *symbol, + char prefix, + ShHashFunction64 hashFunction, + NameMap *nameMap); } // namespace sh diff --git a/src/compiler/translator/ImmutableString.h b/src/compiler/translator/ImmutableString.h index b269fa3efaf..309a3ebad8c 100644 --- a/src/compiler/translator/ImmutableString.h +++ b/src/compiler/translator/ImmutableString.h @@ -10,6 +10,10 @@ #ifndef COMPILER_TRANSLATOR_IMMUTABLESTRING_H_ #define COMPILER_TRANSLATOR_IMMUTABLESTRING_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/string_utils.h" diff --git a/src/compiler/translator/ImmutableStringBuilder.cpp b/src/compiler/translator/ImmutableStringBuilder.cpp index 54616f0a383..5e9abd04f36 100644 --- a/src/compiler/translator/ImmutableStringBuilder.cpp +++ b/src/compiler/translator/ImmutableStringBuilder.cpp @@ -7,6 +7,10 @@ // the maximum length is known in advance. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/ImmutableStringBuilder.h" #include diff --git a/src/compiler/translator/ImmutableStringBuilder.h b/src/compiler/translator/ImmutableStringBuilder.h index 04764c41226..d6f7264c380 100644 --- a/src/compiler/translator/ImmutableStringBuilder.h +++ b/src/compiler/translator/ImmutableStringBuilder.h @@ -10,6 +10,10 @@ #ifndef COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ #define COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "compiler/translator/ImmutableString.h" diff --git a/src/compiler/translator/ImmutableString_autogen.cpp b/src/compiler/translator/ImmutableString_autogen.cpp index 1dc1d863d02..e16aa0d6054 100644 --- a/src/compiler/translator/ImmutableString_autogen.cpp +++ b/src/compiler/translator/ImmutableString_autogen.cpp @@ -29,220 +29,209 @@ std::ostream &operator<<(std::ostream &os, const ImmutableString &str) namespace { -constexpr int mangledkT1[] = {1010, 2612, 305, 1103, 602, 2540, 792, 1009, 550, 54, - 2937, 2671, 687, 157, 684, 1451, 375, 1283, 106, 2776, - 1544, 1773, 1844, 885, 2584, 2112, 387, 2575, 3152, 2290, - 1637, 1317, 1135, 1305, 2761, 1142, 354, 440, 3181, 93}; -constexpr int mangledkT2[] = {113, 1809, 1131, 1235, 2983, 2154, 83, 1560, 1911, 2522, - 3157, 2678, 37, 2136, 1636, 1893, 2950, 2085, 950, 1060, - 242, 2000, 678, 450, 2221, 2144, 891, 2916, 3009, 945, - 3020, 2446, 243, 2893, 2461, 2397, 759, 1880, 1958, 1451}; +constexpr int mangledkT1[] = {243, 1411, 674, 1682, 320, 3003, 2730, 1775, 2251, 2839, + 595, 1906, 1991, 2897, 28, 445, 1551, 407, 1678, 521, + 1582, 2176, 129, 680, 2437, 730, 1853, 2069, 185, 1985, + 1590, 1097, 2679, 2497, 2228, 2674, 2592, 2671, 2686, 166}; +constexpr int mangledkT2[] = {2703, 1866, 1948, 2198, 2747, 2641, 1286, 55, 1534, 94, + 337, 1013, 2156, 238, 2760, 1952, 2355, 2323, 1244, 2345, + 22, 2347, 888, 726, 1892, 782, 45, 2085, 1927, 3078, + 1859, 1384, 2519, 407, 696, 2356, 2752, 2952, 1833, 1987}; constexpr int mangledkG[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, - 0, 0, 1877, 0, 0, 0, 0, 1737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 804, 0, 0, 0, 0, 0, 0, 0, 0, 3048, 0, 0, 2068, 0, 0, - 912, 0, 0, 0, 3067, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 511, 0, 0, 0, 0, 2988, 0, 0, 433, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1836, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, + 241, 0, 0, 0, 1063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2309, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2056, 2788, 2630, 370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2338, 0, 0, 0, 0, 0, 0, 0, 0, 3145, 0, 0, 2874, 901, 0, 0, - 711, 0, 2522, 0, 0, 0, 2942, 0, 2497, 0, 0, 0, 3036, 0, 0, 0, - 0, 0, 0, 0, 543, 0, 0, 0, 0, 0, 0, 536, 102, 0, 0, 0, - 1566, 0, 0, 0, 0, 0, 0, 0, 0, 3174, 0, 0, 0, 0, 1070, 0, - 0, 1148, 0, 0, 0, 526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3161, 0, 0, 0, 0, 0, 0, 3244, 0, 0, 0, 0, 0, 0, 2775, 663, - 0, 0, 0, 0, 0, 0, 0, 0, 2929, 0, 0, 1239, 0, 644, 3210, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3080, 0, 0, 0, 0, - 892, 0, 1279, 201, 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, 539, - 0, 0, 0, 0, 785, 0, 0, 0, 2369, 1892, 3153, 2862, 0, 0, 0, 266, - 0, 600, 0, 2761, 0, 0, 0, 0, 0, 0, 659, 0, 0, 0, 0, 0, - 0, 0, 1004, 0, 286, 0, 0, 0, 0, 315, 1422, 0, 0, 987, 0, 0, - 0, 2031, 0, 0, 216, 2045, 883, 1282, 0, 0, 0, 0, 0, 0, 1396, 1339, - 1262, 0, 0, 0, 0, 0, 0, 953, 0, 0, 1345, 0, 0, 1148, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 223, 0, 293, 0, 0, 324, 0, 0, - 876, 409, 0, 0, 0, 0, 0, 0, 0, 0, 2641, 2620, 0, 0, 0, 430, - 0, 169, 0, 0, 794, 0, 962, 0, 0, 1700, 0, 472, 0, 0, 869, 2307, - 1170, 1421, 2170, 0, 0, 0, 0, 0, 190, 814, 0, 738, 0, 479, 0, 0, - 0, 0, 0, 0, 1444, 0, 1142, 937, 0, 1787, 695, 2333, 2835, 713, 0, 0, - 0, 0, 0, 0, 0, 2794, 0, 0, 2898, 0, 0, 0, 0, 2179, 0, 0, - 0, 0, 0, 0, 0, 1413, 0, 2318, 0, 0, 0, 269, 0, 2081, 834, 0, - 3102, 0, 3203, 0, 1836, 176, 0, 104, 0, 432, 0, 0, 0, 0, 0, 1103, - 0, 621, 2985, 0, 0, 0, 0, 0, 1276, 221, 361, 0, 0, 0, 0, 0, - 0, 3114, 0, 0, 0, 0, 0, 535, 0, 1012, 0, 0, 0, 1541, 0, 0, - 0, 0, 1385, 2736, 2860, 0, 686, 0, 3090, 1054, 0, 0, 0, 0, 1384, 2154, - 54, 1184, 0, 0, 0, 0, 277, 0, 0, 0, 0, 0, 990, 0, 795, 0, - 0, 1778, 1194, 0, 1288, 0, 738, 0, 0, 331, 0, 0, 0, 0, 0, 0, - 2762, 619, 0, 1451, 1907, 0, 0, 0, 0, 0, 529, 0, 0, 0, 0, 0, - 535, 430, 0, 3135, 0, 2699, 1905, 2267, 0, 0, 0, 0, 0, 0, 389, 1008, - 0, 0, 981, 0, 0, 0, 127, 0, 0, 0, 0, 1242, 0, 1133, 0, 0, - 0, 0, 0, 0, 1222, 304, 0, 3009, 2187, 0, 0, 0, 0, 0, 0, 428, - 1602, 0, 0, 0, 0, 0, 0, 3117, 0, 0, 0, 0, 0, 0, 3182, 3254, - 3234, 550, 452, 0, 0, 1196, 2355, 0, 0, 1149, 317, 578, 1922, 0, 0, 449, - 156, 1022, 0, 0, 3122, 525, 1254, 750, 0, 2871, 0, 0, 0, 0, 1904, 0, - 0, 0, 836, 0, 1166, 0, 0, 1381, 0, 513, 897, 934, 1156, 2707, 1746, 94, - 0, 1955, 387, 0, 0, 0, 3108, 663, 0, 0, 0, 0, 3205, 0, 0, 632, - 2022, 0, 2083, 0, 2881, 0, 1291, 0, 816, 0, 0, 2367, 469, 1036, 0, 1338, - 0, 627, 2694, 149, 0, 1276, 0, 1293, 678, 0, 0, 0, 0, 0, 1006, 2819, - 0, 0, 0, 1403, 650, 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, 809, - 1414, 0, 0, 0, 0, 1618, 0, 1547, 0, 477, 0, 972, 234, 742, 0, 0, - 0, 1911, 0, 435, 0, 1686, 0, 0, 0, 569, 0, 0, 902, 1519, 0, 0, - 0, 0, 2199, 34, 0, 0, 715, 0, 1538, 3189, 64, 0, 0, 0, 2884, 2374, - 0, 0, 1257, 0, 0, 1160, 3207, 0, 2324, 0, 0, 0, 973, 0, 0, 0, - 1271, 141, 811, 1103, 900, 1325, 0, 89, 0, 1444, 696, 0, 456, 0, 2545, 221, - 2292, 0, 417, 1028, 0, 212, 0, 0, 1570, 0, 3177, 1402, 0, 0, 380, 0, - 0, 0, 1111, 0, 0, 1120, 2149, 2682, 1223, 0, 460, 0, 837, 0, 0, 16, - 912, 0, 0, 881, 3195, 0, 0, 0, 2024, 0, 0, 747, 0, 0, 0, 489, - 1061, 81, 0, 0, 0, 685, 2224, 0, 284, 988, 0, 2755, 0, 0, 1180, 368, - 0, 0, 0, 0, 1824, 0, 2567, 0, 0, 0, 0, 1069, 0, 0, 0, 2649, - 1219, 0, 2723, 3155, 0, 893, 120, 2421, 443, 3025, 1547, 0, 0, 0, 32, 0, - 312, 3001, 1050, 126, 652, 0, 2032, 0, 68, 0, 1352, 1533, 0, 0, 1833, 1440, - 0, 0, 1011, 3257, 2282, 77, 0, 668, 0, 0, 2526, 0, 0, 0, 0, 679, - 760, 908, 0, 647, 775, 0, 0, 621, 0, 0, 0, 2904, 0, 0, 556, 0, - 384, 0, 0, 767, 199, 0, 1263, 421, 919, 0, 1286, 1216, 0, 0, 0, 0, - 0, 348, 0, 1027, 0, 0, 361, 1582, 0, 0, 0, 0, 0, 0, 0, 2984, - 0, 0, 0, 3169, 564, 896, 0, 0, 42, 2760, 825, 1085, 1123, 1581, 1162, 3138, - 686, 2240, 0, 0, 1970, 0, 1553, 0, 0, 0, 2230, 1089, 0, 0, 977, 0, - 0, 1972, 893, 0, 0, 274, 2017, 1453, 0, 1471, 0, 1571, 1475, 598, 0, 2781, - 2356, 379, 0, 1431, 2456, 0, 950, 0, 0, 225, 1743, 0, 0, 0, 0, 0, - 0, 1116, 0, 0, 1308, 0, 0, 0, 3009, 964, 0, 0, 0, 1677, 0, 0, - 702, 196, 0, 0, 3236, 1217, 239, 0, 2366, 1569, 0, 0, 0, 1409, 0, 0, - 0, 0, 0, 2918, 245, 0, 0, 1418, 0, 0, 0, 1096, 0, 0, 311, 0, - 0, 0, 0, 2120, 0, 2724, 0, 0, 1344, 961, 1937, 2772, 1672, 3058, 0, 0, - 796, 706, 0, 834, 293, 869, 736, 0, 0, 0, 1377, 0, 0, 892, 0, 3184, - 3055, 470, 0, 126, 199, 0, 853, 0, 366, 0, 0, 1883, 428, 2056, 0, 0, - 45, 0, 0, 0, 2581, 3023, 0, 261, 0, 2786, 875, 329, 0, 0, 0, 0, - 0, 0, 0, 0, 795, 0, 0, 904, 0, 438, 0, 0, 0, 2562, 0, 0, - 664, 0, 0, 0, 1228, 0, 1551, 0, 2882, 0, 0, 0, 76, 570, 0, 0, - 1411, 1803, 0, 0, 0, 419, 0, 97, 1559, 0, 2611, 301, 2935, 0, 0, 0, - 0, 0, 579, 0, 0, 0, 0, 0, 0, 1180, 0, 0, 1538, 0, 0, 1347, - 0, 2489, 0, 0, 1485, 665, 2251, 0, 0, 0, 0, 0, 342, 0, 1425, 0, - 1430, 3202, 0, 0, 1600, 0, 2731, 1913, 0, 0, 176, 0, 0, 0, 0, 0, - 580, 1048, 0, 0, 0, 0, 568, 92, 0, 712, 2565, 1157, 191, 2385, 0, 1513, - 415, 75, 0, 0, 0, 2968, 0, 0, 1273, 1010, 0, 1135, 0, 0, 2319, 220, - 0, 1976, 0, 0, 0, 920, 0, 297, 0, 0, 0, 0, 0, 2581, 558, 970, - 1123, 438, 239, 718, 0, 689, 0, 0, 3202, 0, 0, 0, 0, 0, 0, 693, - 0, 0, 776, 0, 1664, 394, 183, 0, 0, 2338, 2610, 0, 1427, 0, 2103, 0, - 0, 1866, 0, 0, 1983, 2865, 512, 0, 3246, 0, 1139, 874, 2977, 146, 0, 2909, - 0, 1975, 0, 2196, 3243, 2156, 0, 0, 0, 0, 0, 1709, 1230, 0, 985, 0, - 0, 525, 1827, 2166, 0, 419, 0, 0, 1363, 0, 2929, 0, 0, 397, 0, 1062, - 549, 0, 0, 0, 894, 2658, 3024, 2340, 94, 0, 2400, 0, 0, 0, 0, 2229, - 0, 337, 343, 0, 2145, 505, 0, 0, 1560, 819, 1024, 0, 0, 36, 2629, 0, - 0, 2170, 0, 747, 0, 0, 596, 107, 1459, 0, 0, 851, 0, 1948, 0, 690, - 0, 1443, 2040, 150, 0, 0, 2635, 727, 0, 2256, 0, 3268, 1665, 0, 0, 0, - 0, 325, 0, 0, 0, 2452, 2290, 2932, 1575, 1375, 663, 0, 1023, 0, 0, 0, - 162, 0, 0, 3257, 1985, 0, 0, 637, 2965, 3178, 327, 378, 0, 1134, 0, 0, - 637, 0, 152, 822, 2487, 1102, 465, 0, 0, 0, 0, 1156, 0, 0, 938, 0, - 2646, 1396, 0, 781, 2039, 0, 0, 0, 1273, 0, 754, 1572, 2646, 1231, 0, 1173, - 0, 0, 1514, 2142, 2792, 0, 0, 0, 509, 2271, 0, 575, 0, 0, 0, 915, - 0, 248, 0, 0, 1601, 2812, 0, 2756, 2557, 328, 0, 1150, 629, 0, 674, 0, - 0, 172, 0, 31, 0, 1849, 0, 0, 0, 0, 124, 28, 1341, 0, 2358, 2356, - 0, 0, 2375, 756, 2994, 856, 166, 0, 0, 0, 410, 0, 602, 0, 1718, 1354, - 0, 1396, 3244, 647, 3003, 129, 1970, 0, 54, 1129, 0, 0, 605, 0, 0, 312, - 3108, 0, 0, 2991, 0, 757, 0, 0, 2769, 570, 0, 0, 0, 0, 0, 2706, - 1106, 40, 0, 2627, 0, 0, 1319, 0, 2085, 294, 1461, 0, 0, 1197, 0, 0, - 0, 754, 0, 467, 3008, 0, 155, 0, 0, 1543, 532, 0, 0, 3268, 1995, 0, - 0, 0, 0, 0, 2792, 0, 0, 0, 0, 0, 0, 3078, 352, 0, 1280, 566, - 0, 215, 877, 1058, 0, 26, 940, 0, 0, 0, 1053, 0, 0, 2875, 0, 1434, - 0, 0, 0, 0, 0, 0, 865, 0, 2816, 825, 990, 2699, 0, 3264, 0, 674, - 638, 3253, 0, 0, 3012, 924, 749, 0, 314, 0, 2846, 3137, 0, 854, 2578, 0, - 79, 556, 588, 0, 0, 2214, 2711, 0, 0, 0, 0, 153, 0, 45, 2574, 3029, - 258, 67, 2908, 0, 0, 750, 0, 0, 0, 0, 0, 735, 1073, 0, 0, 1295, - 3048, 0, 0, 0, 0, 0, 1099, 835, 954, 0, 1386, 672, 0, 0, 0, 828, - 604, 0, 1449, 1182, 0, 186, 716, 249, 347, 1522, 0, 217, 0, 1316, 2637, 0, - 1141, 0, 461, 0, 0, 0, 0, 0, 770, 0, 697, 0, 0, 954, 0, 0, - 387, 0, 1615, 1369, 0, 109, 480, 1023, 513, 3237, 348, 2190, 0, 1544, 676, 3162, - 954, 0, 0, 2411, 2792, 0, 392, 1093, 504, 413, 0, 0, 0, 250, 0, 0, - 0, 610, 60, 0, 0, 1497, 3056, 3047, 0, 0, 98, 553, 1182, 2981, 0, 0, - 0, 1035, 1214, 0, 0, 1844, 0, 507, 0, 0, 0, 1060, 0, 0, 1106, 0, - 0, 307, 531, 0, 0, 248, 0, 0, 825, 0, 0, 1093, 0, 0, 1865, 0, - 599, 179, 654, 0, 177, 3060, 0, 0, 2612, 0, 2837, 0, 832, 1240, 3021, 909, - 1941, 2566, 821, 585, 0, 1864, 0, 1096, 1051, 0, 0, 0, 0, 0, 0, 399, - 2301, 0, 2950, 100, 0, 65, 1522, 0, 0, 29, 0, 1346, 0, 362, 0, 0, - 0, 0, 294, 2473, 3057, 950, 655, 0, 0, 2629, 0, 830, 3144, 0, 1197, 1829, - 0, 248, 2812, 737, 0, 0, 263, 2715, 0, 4, 0, 0, 0, 32, 0, 788, - 0, 0, 2007, 0, 0, 146, 24, 2474, 0, 0, 996, 2708, 0, 970, 0, 0, - 281, 292, 2977, 0, 2551, 2995, 2672, 555, 0, 0, 51, 1199, 804, 0, 1369, 2392, - 148, 0, 0, 0, 2683, 402, 848, 453, 620, 2851, 0, 1522, 0, 0, 1165, 0, - 0, 419, 437, 2421, 0, 829, 816, 1499, 178, 2043, 752, 791, 0, 0, 910, 0, - 0, 0, 3077, 0, 2513, 870, 828, 1352, 1504, 1359, 2838, 0, 1155, 1812, 3229, 0, - 0, 0, 2685, 0, 570, 842, 0, 0, 0, 0, 445, 317, 864, 0, 1370, 0, - 0, 0, 994, 0, 477, 1022, 1409, 1500, 0, 0, 3242, 16, 265, 0, 0, 3111, - 0, 496, 0, 2879, 3067, 0, 0, 2871, 1285, 574, 0, 480, 3091, 0, 0, 429, - 797, 830, 0, 0, 562, 0, 0, 854, 0, 0, 225, 150, 288, 0, 0, 0, - 1357, 0, 3097, 0, 522, 147, 280, 1679, 445, 173, 2762, 1111, 0, 0, 44, 526, - 1156, 723, 2212, 2525, 331, 499, 0, 2886, 532, 978, 2023, 1407, 1026, 207, 501, 0, - 268, 2669, 2833, 1139, 0, 1817, 247, 0, 911, 0, 43, 0, 0, 423, 729, 0, - 3128, 0, 1090, 1880, 1055, 1122, 2688, 0, 0, 0, 0, 1757, 1243, 1428, 2157, 818, - 133, 938, 0, 0, 0, 0, 2303, 294, 0, 796, 3188, 1475, 2957, 188, 0, 547, - 0, 1840, 0, 2686, 1476, 0, 905, 0, 58, 0, 170, 0, 2066, 261, 0, 914, - 0, 0, 0, 10, 1338, 849, 2677, 1455, 0, 0, 387, 0, 407, 0, 717, 883, - 144, 1315, 1380, 3071, 519, 541, 0, 71, 785, 0, 599, 0, 2360, 0, 918, 1104, - 119, 0, 0, 545, 663, 1505, 1911, 2228, 1278, 0, 0, 0, 0, 0, 1625, 0, - 218, 1962, 872, 517, 1233, 0, 2591, 0, 0, 1276, 0, 0, 0, 462, 0, 3187, - 0, 3221, 126, 0, 1050, 0, 0, 1349, 0, 3000, 310, 872, 3077, 1145, 0, 336, - 0, 1052, 0, 0, 0, 64, 509, 0, 704, 716, 2494, 0, 1002, 1563, 1477, 0, - 0, 0, 0, 1796, 1083, 0, 603, 707, 0, 0, 0, 1329, 2298, 858, 0, 0, - 1786, 705, 0, 0, 857, 2581, 0, 2385, 0, 0, 760, 850, 282, 0, 2523, 1262, - 1462, 0, 0, 638, 1562, 1265, 0, 1323, 462, 0, 1459, 0, 0, 553, 0, 654, - 0, 966, 359, 2944, 1132, 0, 1379, 0, 1446, 0, 0, 878, 3114, 0, 0, 0, - 1337, 571, 3153, 0, 0, 720, 0, 355, 1521, 2696, 2894, 0, 20, 164, 3240, 0, - 1260, 84, 2748, 1667, 0, 0, 0, 609, 213, 471, 2384, 3084, 3242, 0, 684, 1233, - 1256, 0, 0, 2112, 0, 0, 0, 753, 311, 0, 122, 1244, 2732, 1309, 0, 803, - 2392, 450, 0, 3046, 0, 326, 209, 1045, 1797, 0, 0, 3069, 0, 0, 0, 1510, - 1291, 0, 500, 0, 1689, 581, 0, 1546, 2777, 1086, 1010, 0, 2739, 1302, 0, 0, - 1094, 0, 0, 3137, 0, 0, 0, 1321, 399, 168, 3178, 523, 0, 1370, 0, 0, - 0, 0, 0, 1234, 0, 152, 0, 1775, 1990, 1101, 2572, 651, 2059, 0, 1478, 1125, - 2095, 1370, 0, 0, 3054, 0, 620, 0, 1261, 2879, 1841, 0, 1261, 2054, 0, 737, - 2206, 0, 1203, 0, 0, 2260, 2409, 0, 3165, 0, 0, 0, 0, 455, 459, 0, - 3084, 0, 2252, 985, 967, 416, 0, 3244, 0, 1491, 0, 715, 3246, 0, 0, 219, - 0, 2170, 0, 0, 3238, 832, 763, 134, 0, 425, 0, 0, 0, 19, 784, 3079, - 1309, 0, 1569, 0, 317, 101, 0, 0, 2243, 446, 814, 0, 844, 0, 0, 349, - 455, 0, 1196, 0, 394, 672, 0, 847, 0, 1969, 639, 0, 1114, 1669, 1676, 1986, - 3144, 3266, 2527, 899, 1854, 0, 834, 1658, 0, 2357, 0, 852, 748, 0, 0, 710, - 0, 0, 0, 0, 2383, 966, 0, 0, 0, 0, 2840, 1635, 982, 1828, 0, 714, - 332, 0, 0, 1549, 1343, 0, 3206, 0, 0, 2120, 2040, 0, 0, 0, 1958, 1006, - 421, 2902, 0, 0, 1878, 367, 0, 0, 140, 952, 0, 1554, 1400, 358, 634, 384, - 1599, 3137, 0, 2946, 119, 352, 2157, 3135, 548, 0, 0, 96, 509, 0, 1508, 321, - 2397, 1480, 0, 0, 400, 808, 718, 0, 2789, 0, 394, 0, 0, 0, 1349, 1365, - 30, 583, 34, 0, 458, 3033, 1668, 1055, 0, 2172, 1645, 0, 0, 1391, 3021, 0, - 0, 224, 2457, 1224, 3162, 2721, 0, 0, 0, 2689, 0, 0, 0, 0, 1687, 0, - 780, 0, 72, 938, 237, 483, 2283, 1562, 0, 2240, 2313, 1348, 2277, 1033, 0, 453, - 997, 0, 2987, 1150, 0, 0, 607, 0, 1091, 0, 227, 355, 2346, 0, 1129, 3131, - 3107, 0, 0, 0, 0, 883, 71, 712, 0, 3179, 1287, 0, 2769, 487, 1401, 0, - 444, 0, 0, 73, 0, 2428, 0, 502, 779, 0, 372, 866, 100, 2126, 0, 0, - 0, 0, 0, 1074, 1704, 2795, 312, 288, 553, 2048, 2421, 2542, 1088, 3039, 0, 0, - 0, 0, 0, 0, 1364, 666, 0, 2188, 0, 0, 0, 178, 163, 0, 0, 1372, - 371, 0, 1388, 2321, 1336, 0, 854, 609, 2593, 998, 1178, 0, 1437, 127, 0, 1200, - 1337, 0, 1649, 810, 887, 0, 3228, 341, 0, 210, 0, 0, 0, 1736, 0, 1048, - 406, 1458, 377, 0, 0, 0, 3080, 1069, 17, 319, 652, 0, 3215, 274, 0, 109, - 788, 839, 3257, 302, 0, 1413, 0, 0, 1257, 1443, 0, 0, 0, 0, 0, 786, - 2003, 709, 0, 3210, 110, 0, 0, 0, 0, 1303, 210, 1240, 1902, 0, 0, 0, - 0, 731, 2, 0, 0, 0, 3035, 236, 2083, 1237, 1507, 271, 0, 0, 337, 0, - 0, 493, 2067, 1933, 820, 50, 737, 0, 307, 0, 24, 287, 0, 1500, 0, 1273, - 0, 1051, 0, 355, 1828, 96, 0, 0, 1313, 1014, 578, 595, 7, 1154, 592, 0, - 0, 1194, 116, 1046, 0, 0, 0, 3207, 1424, 1190, 880, 0, 1004, 0, 0, 0, - 0, 0, 591, 0, 2843, 0, 1360, 0, 2418, 0, 0, 0, 0, 480, 0, 0, - 1011, 0, 3201, 1481, 0, 1949, 375, 482, 0, 0, 0, 0, 0, 0, 2635, 198, - 46, 808, 1008, 0, 1132, 0, 1030, 0, 3036, 0, 2712, 0, 0, 141, 0, 0, - 1038, 891, 0, 590, 1314, 0, 0, 529, 1824, 227, 471, 956, 1515, 1577, 0, 2643, - 2470, 1429, 1181, 1169, 524, 1569, 0, 139, 0, 2485, 0, 2863, 1532, 740, 0, 641, - 425, 592, 2225, 1267, 0, 0, 684, 289, 664, 0, 1784, 214, 1305, 0, 479, 0, - 2185, 0, 0, 0, 2851, 0, 788, 0, 3194, 131, 0, 615, 338, 1425, 1266, 357, - 1095, 367, 0, 0, 1939, 0, 0, 0, 1398, 1530, 2576, 2614, 1550, 0, 2147, 1239, - 2439, 0, 2336, 0, 1030, 0, 2825, 2191, 0, 1416, 595, 0, 308, 0, 269, 0, - 0, 0, 0, 927, 0, 733, 0, 1548, 0, 52, 1032, 402, 0, 2093, 0, 0, - 0, 480, 0, 251, 0, 0, 0, 0, 0, 0, 618, 2545, 61, 1375, 12, 216, - 1137, 781, 0, 858, 521, 0, 466, 0, 1417, 1104, 2748, 3202, 422, 131, 0, 0, - 1704, 417, 3265, 951, 38, 0, 315, 0, 0, 1019, 161, 0, 0, 0, 673, 821, - 869, 1087, 2351, 643, 0, 833, 533, 0, 0, 866, 677, 491, 951, 1533, 0, 1397, - 0, 0, 3208, 0, 0, 393, 2042, 0, 700, 650, 0, 853, 2051, 0, 3252, 1467, - 0, 0, 2338, 276, 0, 0, 0, 456, 1414, 156, 0, 0, 1500, 949, 673, 300, - 150, 105, 562, 0, 1403, 22, 911, 0, 0, 868, 0, 62, 0, 433, 736, 3076, - 0, 112, 0, 1539, 0, 390, 980, 0, 0, 1208, 980, 295, 0, 2710, 0, 2670, - 0, 0, 1135, 0, 518, 671, 3247, 0, 0, 0, 145, 455, 0, 0, 0, 0, - 1443, 928, 0, 0, 295}; + 619, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2602, 0, 0, 0, 1257, 459, + 2666, 381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1339, 0, 20, 0, 0, 0, 0, 0, 0, 532, 903, 668, 0, 0, + 0, 0, 2528, 0, 0, 0, 0, 0, 0, 0, 278, 2885, 0, 2906, 0, 0, + 0, 0, 1420, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 1975, 587, 0, + 0, 0, 0, 0, 0, 0, 859, 289, 0, 0, 2227, 0, 0, 0, 830, 0, + 0, 0, 0, 0, 690, 24, 1006, 0, 0, 1022, 0, 2531, 0, 0, 0, 0, + 0, 0, 0, 1021, 0, 0, 0, 0, 0, 3050, 0, 0, 0, 0, 0, 0, + 0, 0, 1311, 0, 2856, 0, 92, 0, 0, 0, 2759, 0, 0, 2071, 0, 1013, + 977, 0, 0, 0, 1019, 366, 0, 0, 270, 0, 2877, 0, 488, 0, 0, 2928, + 2907, 777, 0, 0, 0, 0, 0, 2951, 0, 358, 0, 0, 2665, 1329, 0, 0, + 0, 0, 0, 0, 0, 184, 2072, 0, 0, 0, 0, 0, 0, 0, 2953, 0, + 0, 0, 0, 0, 0, 0, 1293, 0, 0, 0, 443, 0, 0, 0, 0, 903, + 1420, 0, 0, 2843, 0, 1430, 0, 0, 2088, 0, 1148, 0, 1980, 2475, 0, 315, + 0, 0, 530, 0, 763, 0, 0, 0, 0, 761, 0, 0, 373, 0, 0, 0, + 0, 0, 0, 0, 0, 1429, 0, 398, 0, 0, 0, 0, 641, 159, 0, 0, + 0, 1108, 0, 0, 695, 0, 0, 2145, 0, 0, 2819, 391, 0, 0, 2000, 0, + 0, 788, 0, 2089, 0, 0, 0, 0, 2779, 0, 0, 187, 2562, 569, 271, 0, + 0, 2061, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1608, 0, 0, 0, + 0, 1368, 0, 0, 0, 2935, 0, 503, 0, 1189, 0, 0, 0, 1572, 216, 0, + 0, 0, 0, 0, 0, 525, 0, 0, 1084, 0, 590, 0, 0, 0, 964, 420, + 0, 0, 0, 0, 65, 0, 0, 937, 0, 0, 577, 145, 0, 0, 1285, 0, + 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 334, 0, 909, 0, 0, 2512, + 0, 420, 0, 0, 0, 0, 0, 0, 2456, 0, 0, 0, 0, 759, 961, 0, + 1283, 0, 668, 1067, 1159, 0, 2518, 1277, 0, 560, 2666, 0, 2661, 0, 260, 0, + 0, 0, 644, 0, 2454, 0, 997, 0, 0, 2160, 0, 0, 0, 2112, 2538, 1754, + 0, 972, 0, 0, 0, 7, 682, 0, 1042, 0, 87, 0, 0, 0, 0, 0, + 0, 0, 807, 1887, 0, 0, 0, 3015, 951, 2916, 977, 0, 0, 0, 2920, 2291, + 0, 0, 0, 0, 0, 2740, 0, 0, 0, 0, 135, 0, 0, 0, 0, 105, + 442, 2308, 346, 0, 0, 1020, 0, 405, 608, 172, 0, 1454, 1013, 0, 2811, 1143, + 1365, 0, 0, 0, 0, 0, 0, 1095, 0, 0, 0, 0, 0, 0, 1035, 0, + 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2678, 2044, 0, 0, 0, 1423, + 853, 0, 0, 117, 1429, 0, 0, 0, 0, 0, 0, 2590, 0, 0, 470, 0, + 613, 0, 2959, 1195, 0, 0, 1008, 299, 940, 0, 2522, 393, 2290, 0, 0, 0, + 0, 1153, 891, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 2926, + 0, 455, 0, 0, 0, 0, 863, 0, 688, 0, 0, 0, 0, 47, 0, 629, + 967, 1080, 0, 0, 1368, 0, 1379, 122, 254, 0, 0, 1176, 0, 0, 0, 0, + 0, 638, 0, 858, 0, 0, 107, 651, 631, 0, 0, 0, 1299, 0, 3010, 2543, + 42, 0, 2661, 0, 0, 31, 1339, 740, 2948, 0, 2930, 246, 1140, 0, 1309, 651, + 0, 1175, 930, 0, 0, 206, 537, 0, 0, 3080, 1178, 937, 0, 0, 0, 0, + 278, 0, 0, 0, 0, 0, 2216, 0, 516, 0, 0, 0, 749, 2675, 0, 0, + 1146, 0, 1408, 1094, 57, 0, 0, 36, 0, 312, 794, 2981, 0, 0, 0, 0, + 154, 828, 0, 171, 0, 0, 0, 271, 0, 0, 0, 0, 0, 0, 1655, 0, + 0, 0, 0, 0, 0, 777, 0, 0, 0, 0, 500, 624, 0, 0, 0, 21, + 1204, 223, 1181, 0, 1286, 1961, 0, 0, 0, 0, 844, 0, 2793, 2572, 1731, 1644, + 0, 0, 0, 647, 0, 0, 2899, 2168, 2784, 585, 0, 598, 0, 0, 0, 0, + 1072, 886, 0, 0, 0, 0, 1536, 0, 0, 0, 968, 0, 1655, 0, 732, 18, + 2967, 2413, 59, 0, 0, 0, 303, 0, 364, 215, 3082, 0, 727, 0, 2145, 1079, + 33, 994, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 908, 2387, 2405, 0, + 0, 1177, 431, 31, 0, 0, 243, 0, 0, 0, 0, 995, 0, 0, 0, 330, + 0, 538, 0, 0, 896, 0, 77, 0, 247, 402, 0, 225, 185, 0, 498, 316, + 0, 0, 529, 117, 580, 0, 0, 0, 0, 229, 0, 0, 1001, 0, 567, 0, + 0, 0, 0, 0, 0, 0, 2970, 934, 2921, 0, 1284, 0, 472, 1340, 2554, 0, + 0, 3074, 481, 0, 2311, 0, 0, 206, 2688, 2753, 2281, 812, 1379, 0, 0, 0, + 0, 2820, 0, 0, 0, 714, 0, 0, 300, 2591, 942, 0, 0, 0, 0, 0, + 0, 0, 47, 2289, 0, 2737, 485, 0, 3030, 0, 146, 0, 0, 1240, 0, 0, + 0, 0, 0, 2925, 0, 0, 0, 0, 0, 2233, 628, 0, 1115, 321, 0, 0, + 1746, 0, 1029, 2622, 0, 0, 0, 2256, 2545, 101, 0, 0, 362, 0, 654, 0, + 0, 1299, 0, 0, 0, 566, 0, 476, 0, 2532, 270, 466, 0, 0, 1103, 0, + 0, 2303, 0, 118, 69, 0, 2364, 0, 434, 0, 0, 2856, 0, 523, 264, 2387, + 2184, 2114, 0, 477, 0, 0, 0, 0, 686, 653, 392, 0, 0, 0, 717, 0, + 0, 1286, 1377, 0, 501, 2893, 0, 0, 0, 0, 1345, 0, 2126, 1277, 1228, 558, + 1319, 1310, 0, 675, 0, 0, 2046, 0, 0, 158, 582, 194, 0, 0, 2736, 1136, + 365, 2864, 0, 2931, 0, 0, 550, 247, 2133, 123, 0, 617, 0, 0, 859, 0, + 0, 0, 0, 1234, 0, 1358, 81, 2202, 871, 672, 0, 0, 836, 99, 1120, 0, + 205, 802, 139, 2317, 0, 0, 0, 0, 0, 337, 554, 1287, 0, 0, 0, 1431, + 0, 0, 0, 0, 0, 259, 0, 382, 0, 0, 2928, 3075, 568, 592, 0, 0, + 0, 309, 2212, 41, 2538, 0, 0, 0, 0, 67, 1510, 0, 0, 0, 371, 839, + 93, 2817, 0, 0, 0, 0, 1853, 0, 110, 0, 2912, 0, 0, 0, 589, 3039, + 0, 383, 1128, 849, 0, 0, 0, 1331, 2873, 1397, 0, 1450, 0, 0, 0, 0, + 10, 1316, 614, 0, 3092, 2300, 0, 0, 0, 0, 1028, 1021, 0, 0, 939, 2202, + 0, 1381, 2818, 2366, 2728, 0, 710, 1271, 0, 426, 0, 0, 1152, 0, 0, 0, + 0, 646, 0, 706, 865, 429, 1202, 0, 0, 0, 1383, 1586, 0, 474, 2135, 555, + 0, 2245, 991, 1124, 2777, 0, 280, 0, 1294, 0, 2979, 0, 0, 3082, 1604, 96, + 2939, 261, 1389, 0, 0, 0, 1239, 0, 0, 0, 0, 0, 0, 2130, 33, 0, + 338, 0, 1972, 320, 375, 88, 0, 498, 0, 872, 0, 0, 0, 2447, 0, 0, + 0, 0, 0, 928, 1032, 0, 0, 2787, 0, 815, 1012, 0, 0, 0, 0, 0, + 0, 97, 594, 0, 0, 0, 0, 0, 0, 573, 499, 462, 142, 511, 0, 0, + 0, 394, 855, 0, 0, 683, 0, 2814, 482, 1224, 2544, 0, 0, 735, 0, 0, + 623, 2316, 76, 2831, 0, 198, 1336, 0, 0, 0, 0, 0, 0, 2181, 0, 2366, + 0, 0, 674, 0, 0, 0, 0, 0, 656, 49, 0, 2150, 2685, 0, 363, 895, + 0, 0, 0, 182, 0, 0, 2974, 0, 2879, 533, 0, 0, 0, 0, 0, 0, + 722, 1158, 0, 0, 859, 0, 1274, 0, 0, 0, 0, 911, 1390, 1418, 2947, 0, + 2981, 0, 2163, 250, 3078, 0, 0, 0, 2952, 0, 0, 425, 2786, 0, 0, 0, + 0, 0, 0, 0, 880, 828, 741, 728, 2530, 112, 350, 1324, 0, 1134, 2894, 0, + 2945, 1497, 326, 0, 747, 147, 2952, 502, 0, 0, 0, 2721, 2322, 454, 0, 119, + 0, 0, 982, 1355, 0, 100, 0, 3028, 699, 0, 0, 0, 478, 1122, 0, 1191, + 0, 272, 0, 2442, 0, 0, 0, 0, 0, 432, 0, 0, 0, 1410, 0, 0, + 94, 0, 2611, 0, 2008, 1405, 0, 0, 2677, 0, 1243, 0, 0, 0, 0, 530, + 0, 2594, 787, 0, 2086, 1379, 0, 0, 0, 0, 0, 258, 1056, 739, 0, 799, + 411, 0, 0, 0, 0, 2188, 959, 48, 219, 976, 360, 1880, 0, 0, 0, 537, + 0, 40, 823, 2048, 0, 814, 701, 0, 0, 0, 1544, 1726, 0, 0, 2103, 2533, + 0, 2955, 2913, 435, 0, 1148, 1002, 2156, 0, 0, 0, 0, 11, 0, 457, 1207, + 0, 2177, 632, 0, 0, 45, 0, 1494, 0, 1815, 0, 0, 0, 0, 0, 492, + 0, 0, 1102, 2880, 0, 572, 77, 0, 0, 498, 0, 0, 0, 0, 379, 556, + 0, 0, 2392, 0, 0, 527, 0, 1905, 2202, 437, 2390, 2877, 0, 1312, 0, 292, + 363, 0, 634, 0, 2304, 0, 739, 0, 570, 0, 0, 2647, 912, 658, 0, 0, + 0, 0, 662, 935, 0, 5, 0, 1237, 0, 2222, 2986, 720, 0, 631, 0, 160, + 0, 74, 0, 817, 0, 600, 0, 0, 0, 1089, 12, 0, 1210, 2498, 0, 997, + 803, 0, 623, 0, 0, 2979, 716, 1060, 636, 2987, 0, 0, 0, 2733, 0, 3012, + 0, 0, 0, 41, 301, 0, 0, 246, 0, 0, 0, 2080, 313, 0, 0, 2937, + 0, 261, 0, 0, 0, 0, 0, 0, 0, 0, 822, 1505, 0, 1202, 0, 0, + 207, 1006, 0, 0, 0, 0, 1924, 0, 0, 662, 216, 0, 0, 0, 733, 0, + 0, 0, 0, 0, 419, 2223, 2755, 2554, 0, 692, 111, 65, 0, 0, 158, 2222, + 0, 0, 80, 1993, 0, 0, 640, 49, 2737, 192, 212, 1020, 0, 0, 0, 0, + 0, 0, 2400, 0, 1163, 0, 1236, 0, 1213, 0, 0, 0, 0, 63, 631, 0, + 0, 0, 0, 29, 1343, 2964, 1223, 709, 0, 0, 0, 396, 0, 0, 0, 2265, + 1151, 209, 0, 457, 746, 0, 999, 0, 250, 0, 0, 0, 0, 0, 210, 677, + 1781, 1542, 0, 0, 0, 758, 0, 0, 1166, 516, 0, 0, 0, 0, 284, 404, + 0, 371, 1486, 423, 2670, 0, 1494, 210, 2733, 0, 0, 2699, 0, 2766, 0, 77, + 526, 0, 0, 0, 0, 1038, 226, 2894, 1057, 1434, 0, 810, 0, 310, 462, 0, + 851, 0, 420, 1725, 894, 0, 0, 0, 0, 0, 0, 595, 267, 201, 0, 2398, + 858, 1181, 1624, 2881, 279, 3016, 281, 221, 0, 0, 302, 0, 0, 133, 97, 676, + 899, 0, 0, 1385, 0, 342, 233, 0, 0, 1240, 2865, 0, 0, 0, 0, 2349, + 0, 0, 269, 987, 1235, 2305, 0, 708, 1104, 0, 0, 2910, 0, 881, 108, 0, + 0, 1409, 776, 0, 1009, 0, 0, 0, 685, 1412, 0, 2399, 0, 682, 0, 0, + 749, 886, 0, 0, 820, 1466, 45, 0, 302, 474, 0, 0, 1438, 815, 348, 0, + 0, 0, 0, 0, 0, 1256, 1222, 887, 828, 274, 0, 612, 20, 0, 246, 2245, + 0, 0, 0, 1040, 2376, 1344, 0, 2643, 0, 0, 1189, 3097, 1394, 888, 1206, 1996, + 0, 313, 0, 0, 1405, 0, 0, 2643, 0, 832, 1315, 0, 154, 0, 2384, 1, + 941, 432, 83, 2988, 0, 0, 2448, 1181, 2407, 0, 3085, 0, 512, 190, 380, 817, + 0, 130, 35, 235, 0, 0, 0, 1313, 1414, 0, 58, 923, 0, 217, 1338, 391, + 0, 2173, 0, 915, 0, 0, 471, 0, 998, 0, 373, 38, 941, 386, 0, 2007, + 0, 741, 0, 0, 0, 0, 612, 891, 2959, 0, 2450, 0, 1169, 3019, 0, 69, + 0, 2864, 0, 2477, 6, 2987, 453, 580, 62, 891, 0, 417, 2669, 0, 519, 741, + 0, 1665, 2998, 0, 519, 0, 0, 16, 2454, 245, 0, 1558, 0, 0, 464, 0, + 1214, 0, 0, 123, 2219, 344, 0, 0, 30, 0, 151, 0, 0, 1201, 0, 1471, + 2747, 0, 481, 0, 34, 981, 2456, 2297, 1524, 0, 983, 942, 191, 0, 1193, 0, + 2238, 0, 1042, 0, 0, 215, 0, 0, 326, 0, 1776, 0, 1695, 37, 177, 0, + 2749, 0, 1338, 951, 141, 0, 1423, 890, 1107, 1025, 115, 350, 252, 0, 611, 382, + 834, 2829, 0, 0, 821, 1398, 0, 0, 2797, 0, 0, 1149, 2556, 0, 1337, 247, + 2303, 2554, 2139, 312, 522, 1218, 226, 1542, 0, 2971, 0, 0, 447, 0, 0, 2845, + 156, 0, 0, 0, 1955, 0, 81, 792, 0, 0, 0, 3038, 0, 591, 797, 0, + 827, 1133, 0, 111, 0, 531, 33, 293, 0, 0, 528, 0, 0, 0, 0, 175, + 389, 0, 0, 523, 0, 0, 0, 489, 0, 690, 0, 0, 315, 1307, 0, 2675, + 0, 2467, 126, 0, 0, 0, 0, 195, 2795, 206, 1131, 1026, 382, 1132, 947, 381, + 0, 0, 0, 0, 0, 2964, 0, 0, 940, 0, 2968, 1484, 0, 991, 984, 0, + 0, 0, 0, 162, 1276, 2750, 0, 659, 0, 1196, 0, 0, 1281, 2158, 356, 508, + 0, 0, 0, 0, 227, 0, 0, 1142, 80, 2020, 2349, 0, 0, 434, 0, 0, + 380, 0, 0, 490, 0, 1261, 925, 1119, 784, 409, 0, 179, 3032, 0, 0, 604, + 2809, 1233, 996, 0, 368, 448, 0, 897, 774, 664, 2435, 2545, 797, 0, 1513, 0, + 0, 326, 0, 0, 0, 0, 0, 2125, 486, 277, 2868, 134, 385, 768, 2992, 772, + 0, 0, 855, 2326, 2901, 0, 0, 0, 0, 2791, 0, 1908, 54, 0, 0, 0, + 0, 0, 0, 998, 2668, 658, 604, 0, 298, 97, 640, 820, 713, 314, 750, 1627, + 1408, 0, 0, 0, 1832, 2164, 461, 0, 1283, 1049, 0, 1737, 85, 602, 188, 0, + 2990, 2155, 2339, 113, 0, 150, 2510, 0, 0, 0, 2954, 1535, 0, 0, 1267, 613, + 0, 290, 573, 860, 2587, 3047, 0, 0, 757, 0, 2204, 0, 0, 328, 240, 524, + 0, 3030, 844, 1073, 333, 388, 0, 505, 0, 0, 303, 2477, 0, 0, 0, 594, + 0, 2895, 2307, 121, 0, 0, 0, 0, 2576, 349, 1819, 541, 765, 0, 777, 2619, + 814, 613, 2439, 0, 2341, 503, 334, 0, 0, 0, 2687, 576, 3093, 435, 0, 0, + 0, 558, 0, 521, 641, 0, 542, 2761, 2536, 0, 0, 708, 0, 0, 1741, 1209, + 0, 0, 0, 33, 801, 302, 0, 579, 0, 0, 1326, 0, 0, 0, 0, 0, + 1144, 925, 0, 0, 1180, 0, 2331, 2264, 0, 746, 0, 0, 0, 0, 1177, 618, + 0, 2485, 2190, 0, 2999, 0, 1272, 0, 986, 0, 607, 696, 1290, 0, 962, 1631, + 214, 2804, 496, 0, 0, 0, 750, 2741, 0, 1036, 0, 56, 0, 1262, 0, 1395, + 752, 1241, 1759, 838, 0, 0, 0, 1522, 837, 194, 0, 671, 652, 1798, 999, 0, + 571, 0, 73, 0, 697, 599, 1211, 811, 129, 1041, 0, 2502, 71, 0, 885, 0, + 2966, 0, 0, 1125, 333, 0, 668, 551, 0, 0, 33, 2076, 0, 874, 0, 0, + 0, 2832, 2023, 0, 0, 2575, 0, 550, 0, 2700, 403, 0, 798, 0, 1298, 0, + 1191, 0, 268, 553, 154, 0, 3032, 684, 0, 2407, 2821, 59, 0, 1065, 395, 0, + 1237, 0, 1313, 0, 255, 1454, 1238, 3034, 712, 823, 200, 0, 1027, 0, 0, 0, + 0, 1321, 0, 0, 875, 0, 0, 0, 390, 367, 2930, 408, 0, 0, 60, 1350, + 1133, 3012, 0, 0, 430, 0, 0, 2580, 1707, 2484, 131, 0, 1254, 0, 2883, 79, + 387, 1352, 0, 136, 884, 262, 0, 157, 2136, 2585, 0, 262, 99, 0, 0, 299, + 2592, 0, 0, 1101, 0, 0, 804, 542, 115, 0, 885, 3054, 0, 922, 0, 0, + 23, 0, 0, 0, 734, 1098, 1011, 577, 0, 0, 1361, 0, 0, 0, 0, 983, + 347, 910, 1003, 2912, 0, 1225, 557, 1376, 908, 0, 833, 0, 2106, 0, 517, 0, + 525, 716, 0, 580, 1024, 21, 1245, 0, 187, 317, 1589, 766, 0, 0, 10, 0, + 0, 747, 872, 116, 0, 0, 0, 1108, 0, 1027, 1020, 1014, 2922, 0, 0, 1487, + 115, 1447, 0, 0, 493, 0, 807, 582, 1082, 0, 0, 0, 407, 1874, 0, 1150, + 346, 1115, 0, 0, 432, 263, 0, 936, 0, 1832, 0, 0, 1886, 1263, 0, 0, + 0, 0, 2456, 922, 1387, 2827, 0, 2197, 0, 0, 0, 1294, 0, 0, 0, 2186, + 716, 42, 0, 0, 729, 323, 329, 2679, 0, 0, 1692, 2656, 0, 0, 454, 0, + 2182, 1074, 1362, 1255, 275, 273, 0, 0, 2313, 0, 0, 0, 0, 0, 0, 629, + 1402, 0, 0, 325, 1220, 0, 0, 0, 1404, 1415, 0, 0, 451, 320, 0, 77, + 0, 681, 0, 0, 0, 0, 3082, 0, 1890, 1062, 1104, 659, 103, 52, 957, 2324, + 0, 0, 358, 0, 0, 0, 251, 0, 130, 0, 0, 439, 0, 423, 0, 1737, + 0, 0, 0, 0, 688, 700, 728, 266, 1086, 473, 3059, 2562, 0, 0, 1359, 1159, + 230, 0, 0, 1008, 0, 663, 1242, 2653, 726, 0, 1610, 280, 0, 0, 1368, 995, + 376, 0, 770, 0, 983, 1155, 1301, 584, 786, 222, 0, 213, 0, 788, 0, 0, + 0, 2565, 835, 923, 944, 0, 0, 643, 1126, 0, 43, 0, 0, 603, 221, 0, + 0, 0, 880, 1972, 1161, 0, 0, 1200, 894, 0, 428, 1325, 1018, 0, 102, 385, + 2597, 1004, 637, 22, 1103, 1210, 0, 0, 1837, 1144, 2700, 1715, 0}; int MangledHashG(const char *key, const int *T) { @@ -251,7 +240,7 @@ int MangledHashG(const char *key, const int *T) for (int i = 0; key[i] != '\0'; i++) { sum += T[i] * key[i]; - sum %= 3269; + sum %= 3101; } return mangledkG[sum]; } @@ -261,31 +250,34 @@ int MangledPerfectHash(const char *key) if (strlen(key) > 40) return 0; - return (MangledHashG(key, mangledkT1) + MangledHashG(key, mangledkT2)) % 3269; + return (MangledHashG(key, mangledkT1) + MangledHashG(key, mangledkT2)) % 3101; } -constexpr int unmangledkT1[] = {185, 179, 43, 263, 143, 11, 69, 176, 125, 3, 223, - 196, 236, 59, 133, 183, 251, 270, 202, 193, 91, 207, - 17, 29, 81, 181, 160, 152, 51, 186, 88, 252}; -constexpr int unmangledkT2[] = {30, 35, 282, 170, 39, 137, 74, 279, 174, 219, 203, - 269, 2, 226, 58, 37, 171, 51, 273, 0, 210, 176, - 91, 234, 148, 247, 18, 234, 221, 137, 189, 99}; +constexpr int unmangledkT1[] = {28, 128, 1, 151, 144, 127, 90, 229, 212, 59, 3, + 94, 198, 281, 244, 119, 155, 315, 28, 217, 287, 281, + 241, 203, 130, 281, 49, 242, 34, 65, 171, 187}; +constexpr int unmangledkT2[] = {152, 112, 286, 48, 97, 327, 119, 261, 66, 87, 49, + 280, 100, 225, 100, 33, 68, 140, 149, 269, 138, 316, + 172, 193, 38, 302, 35, 211, 141, 204, 92, 157}; constexpr int unmangledkG[] = { - 0, 0, 155, 53, 0, 0, 0, 0, 0, 0, 0, 244, 0, 0, 43, 280, 0, 121, 268, - 0, 44, 0, 0, 117, 0, 0, 0, 144, 0, 54, 141, 246, 154, 74, 0, 97, 0, 137, - 88, 194, 0, 48, 79, 0, 0, 0, 0, 3, 0, 214, 0, 250, 41, 0, 101, 134, 0, - 0, 231, 278, 68, 237, 0, 0, 139, 0, 195, 121, 269, 0, 228, 0, 202, 236, 0, 0, - 166, 62, 0, 0, 176, 209, 66, 234, 0, 0, 207, 0, 0, 148, 118, 0, 82, 0, 268, - 159, 0, 240, 0, 0, 0, 150, 0, 165, 137, 0, 0, 38, 0, 140, 20, 190, 0, 0, - 139, 0, 6, 142, 68, 46, 0, 115, 134, 138, 0, 72, 22, 85, 267, 148, 50, 0, 271, - 30, 227, 25, 157, 111, 108, 172, 92, 213, 40, 213, 0, 165, 168, 0, 0, 151, 12, 259, - 0, 275, 260, 260, 193, 28, 190, 0, 60, 8, 29, 97, 277, 79, 0, 244, 103, 105, 234, - 13, 16, 33, 160, 99, 0, 31, 127, 0, 0, 192, 0, 208, 0, 118, 0, 112, 0, 227, - 159, 168, 0, 234, 0, 67, 128, 168, 267, 212, 254, 111, 237, 72, 0, 68, 159, 0, 0, - 0, 0, 0, 138, 209, 114, 0, 40, 0, 234, 0, 34, 20, 107, 94, 0, 199, 43, 50, - 0, 245, 218, 190, 192, 0, 0, 0, 176, 232, 80, 0, 73, 99, 37, 0, 0, 3, 0, - 0, 277, 0, 0, 81, 77, 0, 225, 0, 82, 50, 135, 184, 267, 235, 126, 178, 247, 176, - 130, 1, 225, 47, 279, 94, 0, 0, 0, 0, 0, 0, 175, 0, 13, 155, 0, 143}; + 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 59, 133, 0, 0, 34, 0, 0, 0, 0, + 94, 0, 0, 0, 237, 42, 0, 0, 0, 0, 307, 24, 0, 17, 17, 0, 238, 111, 0, + 0, 0, 116, 0, 150, 63, 0, 0, 0, 0, 0, 323, 81, 86, 297, 0, 0, 0, 0, + 0, 5, 37, 220, 0, 0, 73, 0, 0, 328, 40, 285, 301, 51, 39, 324, 175, 0, 173, + 116, 0, 88, 0, 23, 272, 0, 0, 109, 0, 30, 0, 0, 33, 59, 0, 108, 0, 20, + 273, 0, 0, 197, 0, 62, 0, 0, 0, 295, 0, 0, 117, 95, 0, 0, 254, 0, 295, + 0, 155, 137, 0, 107, 0, 50, 0, 0, 266, 0, 143, 0, 0, 272, 0, 154, 286, 122, + 129, 210, 179, 0, 63, 0, 0, 0, 20, 19, 0, 173, 0, 0, 55, 29, 115, 253, 0, + 0, 0, 228, 316, 0, 129, 0, 255, 0, 0, 53, 0, 26, 159, 103, 133, 46, 151, 0, + 79, 0, 0, 97, 0, 105, 1, 266, 0, 0, 0, 0, 0, 0, 72, 31, 0, 0, 0, + 67, 0, 15, 162, 115, 45, 109, 0, 166, 67, 64, 326, 11, 79, 0, 0, 0, 55, 64, + 0, 28, 0, 52, 0, 62, 0, 113, 4, 40, 0, 2, 156, 0, 0, 0, 164, 0, 123, + 19, 252, 198, 196, 0, 0, 305, 290, 80, 142, 56, 0, 0, 0, 87, 99, 0, 63, 42, + 0, 0, 32, 0, 73, 14, 0, 0, 128, 68, 0, 0, 13, 165, 0, 37, 177, 0, 0, + 259, 233, 320, 272, 0, 0, 114, 80, 157, 53, 0, 85, 0, 177, 0, 0, 60, 54, 0, + 117, 0, 0, 0, 318, 0, 0, 3, 65, 109, 96, 0, 0, 252, 85, 44, 0, 82, 0, + 112, 84, 30, 56, 96, 0, 91, 47, 120, 67, 0, 226, 0, 201, 23, 157, 57, 109, 0, + 67, 47, 89, 34, 0, 77, 232, 124}; int UnmangledHashG(const char *key, const int *T) { @@ -294,7 +286,7 @@ int UnmangledHashG(const char *key, const int *T) for (int i = 0; key[i] != '\0'; i++) { sum += T[i] * key[i]; - sum %= 284; + sum %= 331; } return unmangledkG[sum]; } @@ -304,7 +296,7 @@ int UnmangledPerfectHash(const char *key) if (strlen(key) > 32) return 0; - return (UnmangledHashG(key, unmangledkT1) + UnmangledHashG(key, unmangledkT2)) % 284; + return (UnmangledHashG(key, unmangledkT1) + UnmangledHashG(key, unmangledkT2)) % 331; } } // namespace diff --git a/src/compiler/translator/InfoSink.cpp b/src/compiler/translator/InfoSink.cpp index 09bd1173d1f..bf35c8a290e 100644 --- a/src/compiler/translator/InfoSink.cpp +++ b/src/compiler/translator/InfoSink.cpp @@ -106,16 +106,16 @@ TInfoSinkBase &TInfoSinkBase::operator<<(const TSymbol &symbol) { switch (symbol.symbolType()) { - case (SymbolType::BuiltIn): + case SymbolType::BuiltIn: *this << symbol.name(); break; - case (SymbolType::Empty): + case SymbolType::Empty: *this << "''"; break; - case (SymbolType::AngleInternal): + case SymbolType::AngleInternal: *this << '#' << symbol.name(); break; - case (SymbolType::UserDefined): + case SymbolType::UserDefined: *this << '\'' << symbol.name() << '\''; break; } @@ -123,13 +123,33 @@ TInfoSinkBase &TInfoSinkBase::operator<<(const TSymbol &symbol) return *this; } +TInfoSinkBase &TInfoSinkBase::operator<<(const TField &field) +{ + ASSERT(field.symbolType() != SymbolType::Empty); + switch (field.symbolType()) + { + case SymbolType::BuiltIn: + *this << field.name(); + break; + case SymbolType::AngleInternal: + *this << '#' << field.name(); + break; + case SymbolType::UserDefined: + *this << '\'' << field.name() << '\''; + break; + default: + UNREACHABLE(); + } + return *this; +} + void TInfoSinkBase::location(int file, int line) { TPersistStringStream stream = sh::InitializeStream(); if (line) stream << file << ":" << line; else - stream << file << ":? "; + stream << file << ":?"; stream << ": "; sink.append(stream.str()); diff --git a/src/compiler/translator/InfoSink.h b/src/compiler/translator/InfoSink.h index 8d3b1c0cf16..af8914a52e3 100644 --- a/src/compiler/translator/InfoSink.h +++ b/src/compiler/translator/InfoSink.h @@ -17,6 +17,7 @@ namespace sh { class ImmutableString; +class TField; class TSymbol; class TType; @@ -74,6 +75,7 @@ class TInfoSinkBase TInfoSinkBase &operator<<(const TType &type); TInfoSinkBase &operator<<(const TSymbol &symbol); + TInfoSinkBase &operator<<(const TField &symbol); // Make sure floats are written with correct precision. TInfoSinkBase &operator<<(float f) diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp index e68df131bb4..e7c35ccd151 100644 --- a/src/compiler/translator/Initialize.cpp +++ b/src/compiler/translator/Initialize.cpp @@ -49,6 +49,14 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi { extBehavior[TExtension::EXT_frag_depth] = EBhUndefined; } + if (resources.EXT_fragment_shading_rate) + { + extBehavior[TExtension::EXT_fragment_shading_rate] = EBhUndefined; + } + if (resources.EXT_fragment_shading_rate_primitive) + { + extBehavior[TExtension::EXT_fragment_shading_rate_primitive] = EBhUndefined; + } if (resources.EXT_primitive_bounding_box) { extBehavior[TExtension::EXT_primitive_bounding_box] = EBhUndefined; @@ -73,10 +81,6 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi { extBehavior[TExtension::EXT_shader_framebuffer_fetch_non_coherent] = EBhUndefined; } - if (resources.NV_shader_framebuffer_fetch) - { - extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined; - } if (resources.NV_shader_noperspective_interpolation) { extBehavior[TExtension::NV_shader_noperspective_interpolation] = EBhUndefined; diff --git a/src/compiler/translator/InitializeDll.cpp b/src/compiler/translator/InitializeDll.cpp deleted file mode 100644 index 99a0fea19bb..00000000000 --- a/src/compiler/translator/InitializeDll.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright 2002 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. -// - -#include "compiler/translator/InitializeDll.h" -#include "compiler/translator/InitializeGlobals.h" - -#include "common/platform.h" - -#include - -namespace sh -{ - -bool InitProcess() -{ - if (!InitializePoolIndex()) - { - assert(0 && "InitProcess(): Failed to initalize global pool"); - return false; - } - - return true; -} - -void DetachProcess() -{ - FreePoolIndex(); -} - -} // namespace sh diff --git a/src/compiler/translator/InitializeDll.h b/src/compiler/translator/InitializeDll.h deleted file mode 100644 index a75a13c2d9d..00000000000 --- a/src/compiler/translator/InitializeDll.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright 2002 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. -// -#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ -#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ - -namespace sh -{ -bool InitProcess(); -void DetachProcess(); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp index d835829f474..0ec1468e221 100644 --- a/src/compiler/translator/IntermNode.cpp +++ b/src/compiler/translator/IntermNode.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // // Build the intermediate representation. // @@ -113,22 +117,24 @@ angle::Matrix GetMatrix(const TConstantUnion *paramArray, const unsigned int cols) { std::vector elements; + elements.reserve(rows * cols); for (size_t i = 0; i < rows * cols; i++) elements.push_back(paramArray[i].getFConst()); // Transpose is used since the Matrix constructor expects arguments in row-major order, // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below // so that the created matrix will have the expected dimensions after the transpose. - return angle::Matrix(elements, cols, rows).transpose(); + return angle::Matrix(std::move(elements), cols, rows).transpose(); } angle::Matrix GetMatrix(const TConstantUnion *paramArray, const unsigned int size) { std::vector elements; + elements.reserve(size * size); for (size_t i = 0; i < size * size; i++) elements.push_back(paramArray[i].getFConst()); // Transpose is used since the Matrix constructor expects arguments in row-major order, // whereas the paramArray is in column-major order. - return angle::Matrix(elements, size).transpose(); + return angle::Matrix(std::move(elements), size).transpose(); } void SetUnionArrayFromMatrix(const angle::Matrix &m, TConstantUnion *resultArray) @@ -136,7 +142,7 @@ void SetUnionArrayFromMatrix(const angle::Matrix &m, TConstantUnion *resu // Transpose is used since the input Matrix is in row-major order, // whereas the actual result should be in column-major order. angle::Matrix result = m.transpose(); - std::vector resultElements = result.elements(); + angle::Span resultElements = result.elements(); for (size_t i = 0; i < resultElements.size(); i++) resultArray[i].setFConst(resultElements[i]); } @@ -452,6 +458,11 @@ TIntermBlock::TIntermBlock(std::initializer_list stmts) } } +TIntermBlock::TIntermBlock(TIntermSequence &&stmts) : mStatements(std::move(stmts)) +{ + mIsTreeRoot = false; +} + size_t TIntermBlock::getChildCount() const { return mStatements.size(); @@ -467,10 +478,9 @@ bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacem return replaceChildNodeInternal(original, replacement); } -void TIntermBlock::replaceAllChildren(const TIntermSequence &newStatements) +void TIntermBlock::replaceAllChildren(TIntermSequence &&newStatements) { - mStatements.clear(); - mStatements.insert(mStatements.begin(), newStatements.begin(), newStatements.end()); + mStatements = std::move(newStatements); } size_t TIntermFunctionPrototype::getChildCount() const @@ -1465,7 +1475,7 @@ void TIntermUnary::promote() TPrecision TIntermUnary::derivePrecision() const { // Unary operators generally derive their precision from their operand, except for a few - // built-ins where this is overriden. + // built-ins where this is overridden. switch (mOp) { case EOpArrayLength: @@ -1538,7 +1548,7 @@ void TIntermUnary::propagatePrecision(TPrecision precision) } } -TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets) +TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets) : TIntermExpression(TType(EbtFloat, EbpUndefined)), mOperand(operand), mSwizzleOffsets(swizzleOffsets), @@ -1740,8 +1750,8 @@ bool TIntermSwizzle::hasDuplicateOffsets() const { return true; } - int offsetCount[4] = {0u, 0u, 0u, 0u}; - for (const auto offset : mSwizzleOffsets) + uint32_t offsetCount[4] = {0u, 0u, 0u, 0u}; + for (const uint32_t offset : mSwizzleOffsets) { offsetCount[offset]++; if (offsetCount[offset] > 1) @@ -1757,7 +1767,7 @@ void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets; } -bool TIntermSwizzle::offsetsMatch(int offset) const +bool TIntermSwizzle::offsetsMatch(uint32_t offset) const { return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset; } @@ -1765,7 +1775,7 @@ bool TIntermSwizzle::offsetsMatch(int offset) const ImmutableString TIntermSwizzle::getOffsetsAsXYZW() const { ImmutableStringBuilder offsets(mSwizzleOffsets.size()); - for (const int offset : mSwizzleOffsets) + for (const uint32_t offset : mSwizzleOffsets) { switch (offset) { @@ -2135,11 +2145,11 @@ TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */) // We need to fold the two swizzles into one, so that repeated swizzling can't cause stack // overflow in ParseContext::checkCanBeLValue(). bool hadDuplicateOffsets = operandSwizzle->hasDuplicateOffsets(); - TVector foldedOffsets; - for (int offset : mSwizzleOffsets) + TVector foldedOffsets; + for (uint32_t offset : mSwizzleOffsets) { // Offset should already be validated. - ASSERT(static_cast(offset) < operandSwizzle->mSwizzleOffsets.size()); + ASSERT(offset < operandSwizzle->mSwizzleOffsets.size()); foldedOffsets.push_back(operandSwizzle->mSwizzleOffsets[offset]); } operandSwizzle->mSwizzleOffsets = foldedOffsets; @@ -2210,10 +2220,10 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) TIntermSwizzle *leftSwizzle = mLeft->getAsSwizzleNode(); if (leftSwizzle != nullptr) { - const TVector &swizzleOffsets = leftSwizzle->getSwizzleOffsets(); + const TVector &swizzleOffsets = leftSwizzle->getSwizzleOffsets(); ASSERT(index < swizzleOffsets.size()); - int remappedIndex = swizzleOffsets[index]; + uint32_t remappedIndex = swizzleOffsets[index]; return new TIntermSwizzle(leftSwizzle->getOperand(), {remappedIndex}); } @@ -4227,7 +4237,7 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg // TIntermPreprocessorDirective implementation. TIntermPreprocessorDirective::TIntermPreprocessorDirective(PreprocessorDirective directive, ImmutableString command) - : mDirective(directive), mCommand(std::move(command)) + : mDirective(directive), mCommand(command) {} TIntermPreprocessorDirective::TIntermPreprocessorDirective(const TIntermPreprocessorDirective &node) diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h index af4f952b024..1d858376a9d 100644 --- a/src/compiler/translator/IntermNode.h +++ b/src/compiler/translator/IntermNode.h @@ -16,6 +16,10 @@ #ifndef COMPILER_TRANSLATOR_INTERMNODE_H_ #define COMPILER_TRANSLATOR_INTERMNODE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLSLANG/ShaderLang.h" #include @@ -288,7 +292,7 @@ class TIntermSymbol : public TIntermTyped public: TIntermSymbol(const TVariable *variable); - TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); } + TIntermSymbol *deepCopy() const override { return new TIntermSymbol(*this); } bool hasConstantValue() const override; const TConstantUnion *getConstantValue() const override; @@ -449,7 +453,7 @@ class TIntermSwizzle : public TIntermExpression { public: // This constructor determines the type of the node based on the operand. - TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets); + TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets); TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); } @@ -466,17 +470,17 @@ class TIntermSwizzle : public TIntermExpression ImmutableString getOffsetsAsXYZW() const; void writeOffsetsAsXYZW(TInfoSinkBase *out) const; - const TVector &getSwizzleOffsets() { return mSwizzleOffsets; } + const TVector &getSwizzleOffsets() { return mSwizzleOffsets; } bool hasDuplicateOffsets() const; void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets); - bool offsetsMatch(int offset) const; + bool offsetsMatch(uint32_t offset) const; TIntermTyped *fold(TDiagnostics *diagnostics) override; protected: TIntermTyped *mOperand; - TVector mSwizzleOffsets; + TVector mSwizzleOffsets; bool mHasFoldedDuplicateOffsets; private: @@ -691,6 +695,7 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase public: TIntermBlock() : TIntermNode(), mIsTreeRoot(false) {} TIntermBlock(std::initializer_list stmts); + TIntermBlock(TIntermSequence &&stmts); ~TIntermBlock() override {} TIntermBlock *getAsBlock() override { return this; } @@ -700,7 +705,7 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase size_t getChildCount() const final; TIntermNode *getChildNode(size_t index) const final; bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - void replaceAllChildren(const TIntermSequence &newStatements); + void replaceAllChildren(TIntermSequence &&newStatements); // Only intended for initially building the block. void appendStatement(TIntermNode *statement); diff --git a/src/compiler/translator/IntermRebuild.h b/src/compiler/translator/IntermRebuild.h index 57768501a5f..3af388acc00 100644 --- a/src/compiler/translator/IntermRebuild.h +++ b/src/compiler/translator/IntermRebuild.h @@ -7,6 +7,10 @@ #ifndef COMPILER_TRANSLATOR_INTERMREBUILD_H_ #define COMPILER_TRANSLATOR_INTERMREBUILD_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/NodeType.h" #include "compiler/translator/tree_util/IntermTraverse.h" diff --git a/src/compiler/translator/Name.cpp b/src/compiler/translator/Name.cpp index 3a8a5f4185c..e32a54c58c3 100644 --- a/src/compiler/translator/Name.cpp +++ b/src/compiler/translator/Name.cpp @@ -82,7 +82,7 @@ void Name::emitImpl(T &out) const ASSERT(!mRawName.empty()); if (mRawName != "main") { - out << kUserDefinedNamePrefix << mRawName; + out << '_' << kUserDefinedNamePrefix << mRawName; } else { diff --git a/src/compiler/translator/OWNERS b/src/compiler/translator/OWNERS new file mode 100644 index 00000000000..e4fbac67436 --- /dev/null +++ b/src/compiler/translator/OWNERS @@ -0,0 +1,2 @@ +liza@chromium.org +mpdenton@chromium.org \ No newline at end of file diff --git a/src/compiler/translator/Operator_autogen.h b/src/compiler/translator/Operator_autogen.h index 1f2607b28ee..c3b4797d16b 100644 --- a/src/compiler/translator/Operator_autogen.h +++ b/src/compiler/translator/Operator_autogen.h @@ -307,8 +307,16 @@ enum TOperator : uint16_t EOpTextureProjOffsetBias, // Group TextureGather + + // Group TextureGatherNoComp EOpTextureGather, + // Group TextureGatherComp + EOpTextureGatherComp, + + // Group TextureGatherRef + EOpTextureGatherRef, + // Group TextureGatherOffset // Group TextureGatherOffsetNoComp @@ -317,6 +325,9 @@ enum TOperator : uint16_t // Group TextureGatherOffsetComp EOpTextureGatherOffsetComp, + // Group TextureGatherOffsetRef + EOpTextureGatherOffsetRef, + // Group TextureGatherOffsets // Group TextureGatherOffsetsNoComp @@ -325,6 +336,9 @@ enum TOperator : uint16_t // Group TextureGatherOffsetsComp EOpTextureGatherOffsetsComp, + // Group TextureGatherOffsetsRef + EOpTextureGatherOffsetsRef, + // Group TextureQueryLod EOpTextureQueryLOD, @@ -418,6 +432,7 @@ enum TOperator : uint16_t EOpInterpolateAtCenter, // Group MetalCommon + EOpLoopForwardProgress, EOpSaturate, }; @@ -446,6 +461,18 @@ static inline bool IsTextureOffsetBias(TOperator op) { return op >= EOpTextureOffsetBias && op <= EOpTextureProjOffsetBias; } +static inline bool IsTextureGatherNoComp(TOperator op) +{ + return op >= EOpTextureGather && op <= EOpTextureGather; +} +static inline bool IsTextureGatherComp(TOperator op) +{ + return op >= EOpTextureGatherComp && op <= EOpTextureGatherComp; +} +static inline bool IsTextureGatherRef(TOperator op) +{ + return op >= EOpTextureGatherRef && op <= EOpTextureGatherRef; +} static inline bool IsTextureGatherOffsetNoComp(TOperator op) { return op >= EOpTextureGatherOffset && op <= EOpTextureGatherOffset; @@ -454,9 +481,13 @@ static inline bool IsTextureGatherOffsetComp(TOperator op) { return op >= EOpTextureGatherOffsetComp && op <= EOpTextureGatherOffsetComp; } +static inline bool IsTextureGatherOffsetRef(TOperator op) +{ + return op >= EOpTextureGatherOffsetRef && op <= EOpTextureGatherOffsetRef; +} static inline bool IsTextureGatherOffset(TOperator op) { - return op >= EOpTextureGatherOffset && op <= EOpTextureGatherOffsetComp; + return op >= EOpTextureGatherOffset && op <= EOpTextureGatherOffsetRef; } static inline bool IsTextureGatherOffsetsNoComp(TOperator op) { @@ -466,13 +497,17 @@ static inline bool IsTextureGatherOffsetsComp(TOperator op) { return op >= EOpTextureGatherOffsetsComp && op <= EOpTextureGatherOffsetsComp; } +static inline bool IsTextureGatherOffsetsRef(TOperator op) +{ + return op >= EOpTextureGatherOffsetsRef && op <= EOpTextureGatherOffsetsRef; +} static inline bool IsTextureGatherOffsets(TOperator op) { - return op >= EOpTextureGatherOffsets && op <= EOpTextureGatherOffsetsComp; + return op >= EOpTextureGatherOffsets && op <= EOpTextureGatherOffsetsRef; } static inline bool IsTextureGather(TOperator op) { - return op >= EOpTextureGather && op <= EOpTextureGatherOffsetsComp; + return op >= EOpTextureGather && op <= EOpTextureGatherOffsetsRef; } static inline bool IsTexture(TOperator op) { diff --git a/src/compiler/translator/OutputTree.cpp b/src/compiler/translator/OutputTree.cpp index 48eebe57454..c3f071c7896 100644 --- a/src/compiler/translator/OutputTree.cpp +++ b/src/compiler/translator/OutputTree.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/SymbolTable.h" #include "compiler/translator/tree_util/IntermTraverse.h" @@ -90,6 +94,19 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node) OutputTreeText(mOut, node, getCurrentIndentDepth()); OutputVariable(mOut, node->variable()); mOut << "\n"; + + const TType &type = node->getType(); + if (type.getStruct() != nullptr && type.isStructSpecifier()) + { + const TFieldList &fields = type.getStruct()->fields(); + for (TField *field : fields) + { + OutputTreeText(mOut, node, getCurrentIndentDepth() + 1); + mOut << "member: "; + mOut << *field << " (" << *field->type() << ")"; + mOut << "\n"; + } + } } bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp index f8dc74d9793..2ad6df40b56 100644 --- a/src/compiler/translator/ParseContext.cpp +++ b/src/compiler/translator/ParseContext.cpp @@ -4,6 +4,19 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +// Note: During transition to IR, ParseContext.cpp builds the AST and IR at the same time, which is +// not efficient. The AST is used for validation purposes, but a stack that only contains the +// necessary information needed for validation is sufficient, so for example operations such as +// constant folding etc don't need to be performed. Such a stack could be very light, including IR +// ids that could then be used to query information out of the ir itself. +// +// This is best done when an AST-only build is no longer possible so that there wouldn't need to be +// a fallback to AST maintained at the same time. + #include "compiler/translator/ParseContext.h" #include @@ -13,10 +26,9 @@ #include "common/utilities.h" #include "compiler/preprocessor/SourceLocation.h" #include "compiler/translator/Declarator.h" -#include "compiler/translator/StaticType.h" #include "compiler/translator/ValidateGlobalInitializer.h" -#include "compiler/translator/ValidateSwitch.h" #include "compiler/translator/glslang.h" +#include "compiler/translator/tree_util/BuiltIn.h" #include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/util.h" @@ -31,9 +43,27 @@ namespace sh namespace { - const int kWebGLMaxStructNesting = 4; +// Arbitrarily enforce that all types declared with a size in bytes of over 2 GB will cause +// compilation failure. +// +// For local and global variables, the limit is much lower (64KB) as that much memory won't fit in +// the GPU registers anyway. +constexpr size_t kWebGLMaxVariableSizeInBytes = static_cast(2) * 1024 * 1024 * 1024; +constexpr size_t kWebGLMaxPrivateVariableSizeInBytes = static_cast(64) * 1024; +constexpr size_t kWebGLMaxTotalPrivateVariableSizeInBytes = static_cast(16) * 1024 * 1024; + +bool ShouldEnforceESSL100LoopAndIndexingLimitations(ShShaderSpec spec, + int shaderVersion, + const ShCompileOptions &compileOptions) +{ + // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API, + // validate loop and indexing as well (to verify that the shader only uses minimal functionality + // of ESSL 1.00 as in Appendix A of the spec). + return (IsWebGLBasedSpec(spec) && shaderVersion == 100) || compileOptions.validateLoopIndexing; +} + struct IsSamplerFunc { bool operator()(TBasicType type) { return IsSampler(type); } @@ -173,6 +203,7 @@ constexpr bool IsValidWithPixelLocalStorage(TLayoutImageInternalFormat internalF case EiifRGBA8I: case EiifRGBA8UI: case EiifR32F: + case EiifR32I: case EiifR32UI: return true; default: @@ -194,6 +225,8 @@ constexpr ShPixelLocalStorageFormat ImageFormatToPLSFormat(TLayoutImageInternalF return ShPixelLocalStorageFormat::RGBA8UI; case EiifR32F: return ShPixelLocalStorageFormat::R32F; + case EiifR32I: + return ShPixelLocalStorageFormat::R32I; case EiifR32UI: return ShPixelLocalStorageFormat::R32UI; } @@ -241,6 +274,161 @@ bool UsesDerivatives(TIntermAggregate *functionCall) return false; } } + +bool IsSamplerOrStructWithOnlySamplers(const TType *type) +{ + return IsSampler(type->getBasicType()) || type->isStructureContainingOnlySamplers(); +} + +void MarkClipCullFirstEncounter(const TSourceLoc &line, ClipCullDistanceInfo *info) +{ + if (info->firstEncounter.first_line < 0) + { + info->firstEncounter = line; + } +} + +void MarkClipCullRedeclaredSize(const TSourceLoc &line, + uint32_t arraySize, + ClipCullDistanceInfo *info) +{ + MarkClipCullFirstEncounter(line, info); + info->size = arraySize; +} + +void MarkClipCullArrayLengthMethodCall(const TSourceLoc &line, ClipCullDistanceInfo *info) +{ + MarkClipCullFirstEncounter(line, info); + info->hasArrayLengthMethodCall = true; +} + +void MarkClipCullIndex(const TSourceLoc &line, TIntermTyped *indexExpr, ClipCullDistanceInfo *info) +{ + MarkClipCullFirstEncounter(line, info); + const TConstantUnion *constIdx = indexExpr->getConstantValue(); + if (constIdx) + { + int idx = 0; + switch (constIdx->getType()) + { + case EbtInt: + idx = constIdx->getIConst(); + break; + case EbtUInt: + idx = constIdx->getUConst(); + break; + default: + // This can happen due to a compile error that is generated elsewhere. + break; + } + + info->maxIndex = std::max(info->maxIndex, idx); + } + else + { + info->hasNonConstIndex = true; + } +} + +void ValidateFragColorAndFragData(GLenum shaderType, + int shaderVersion, + const TSymbolTable &symbolTable, + TDiagnostics *diagnostics) +{ + if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER) + { + return; + } + + bool usesFragColor = false; + bool usesFragData = false; + // This validation is a bit stricter than the spec - it's only an error to write to + // both FragData and FragColor. But because it's better not to have reads from undefined + // variables, we always return an error if they are both referenced, rather than only if they + // are written. + if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) || + symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT())) + { + usesFragColor = true; + } + // Extension variables may not always be initialized (saves some time at symbol table init). + bool secondaryFragDataUsed = + symbolTable.gl_SecondaryFragDataEXT() != nullptr && + symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT()); + if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed) + { + usesFragData = true; + } + if (usesFragColor && usesFragData) + { + const char *errorMessage = "cannot use both gl_FragData and gl_FragColor"; + if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) || + secondaryFragDataUsed) + { + errorMessage = + "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)" + " and (gl_FragColor, gl_SecondaryFragColorEXT)"; + } + diagnostics->globalError(errorMessage); + } +} + +bool IsESSL100ConstantExpression(TIntermNode *node) +{ + return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst; +} + +// Calculate the size of a variable for validation purposes. If the variable is a UBO, add padding +// that makes the calculated size _at least_ as large as std140 requires. Given the limits are +// arbitrary and overly large, there is no need to be precise about this calculation as long as the +// calculated size is an overestimation of the real size (which could be, by a small amount). +angle::base::CheckedNumeric CalculateVariableSize(const TType *type, bool isStd140) +{ + constexpr size_t kVec4Size = sizeof(float) * 4; + + if (type->isArray()) + { + TType elementType = *type; + elementType.toArrayElementType(); + angle::base::CheckedNumeric elementSize = + CalculateVariableSize(&elementType, isStd140); + + return elementSize * type->getArraySizeProduct(); + } + + if (type->getBasicType() == EbtStruct) + { + const TStructure *structure = type->getStruct(); + angle::base::CheckedNumeric totalSize = 0; + for (const TField *field : structure->fields()) + { + const TType *fieldType = field->type(); + totalSize += CalculateVariableSize(fieldType, isStd140); + } + return totalSize; + } + + if (type->isMatrix()) + { + if (isStd140) + { + // Ignore row vs column major, and get the biggest size of the two possibilities as a + // possibly slight overestimation. Note that the size according to std140 is either + // rows times vec4 or cols times vec4 based on how the matrix is laid out. + return std::max(type->getRows(), type->getCols()) * kVec4Size; + } + else + { + return type->getRows() * type->getCols() * sizeof(float); + } + } + + // For vectors and scalars, return the size of a vec4 for std140. This is a slight + // overestimation. If this is the element of an array though, it's accurate (which is why it's + // a slight overestimation, e.g. the size of a large array of a scalar type is not + // overestimated). + return isStd140 ? kVec4Size : type->getNominalSize() * sizeof(float); +} } // namespace // This tracks each binding point's current default offset for inheritance of subsequent @@ -288,14 +476,12 @@ TParseContext::TParseContext(TSymbolTable &symt, mShaderType(type), mShaderSpec(spec), mCompileOptions(options), + mResources(resources), mShaderVersion(100), mTreeRoot(nullptr), - mLoopNestingLevel(0), mStructNestingLevel(0), - mSwitchNestingLevel(0), - mCurrentFunctionType(nullptr), + mCurrentFunction(nullptr), mFunctionReturnsValue(false), - mFragmentPrecisionHighOnESSL1(false), mEarlyFragmentTestsSpecified(false), mHasDiscard(false), mSampleQualifierSpecified(false), @@ -308,39 +494,25 @@ TParseContext::TParseContext(TSymbolTable &symt, mDefaultBufferMatrixPacking(EmpColumnMajor), mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), mDiagnostics(diagnostics), - mDirectiveHandler(ext, *mDiagnostics, mShaderVersion, mShaderType), + mDirectiveHandler(ext, *mDiagnostics, *this, mShaderType), mPreprocessor(mDiagnostics, &mDirectiveHandler, angle::pp::PreprocessorSettings(spec)), mScanner(nullptr), - mMaxExpressionComplexity(static_cast(options.limitExpressionComplexity - ? resources.MaxExpressionComplexity - : std::numeric_limits::max())), - mMaxStatementDepth(static_cast(resources.MaxStatementDepth)), - mMinProgramTexelOffset(resources.MinProgramTexelOffset), - mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), - mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset), - mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset), mComputeShaderLocalSizeDeclared(false), mComputeShaderLocalSize(-1), mNumViews(-1), - mMaxNumViews(resources.MaxViewsOVR), - mMaxImageUnits(resources.MaxImageUnits), - mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits), - mMaxUniformLocations(resources.MaxUniformLocations), - mMaxUniformBufferBindings(resources.MaxUniformBufferBindings), - mMaxVertexAttribs(resources.MaxVertexAttribs), - mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings), - mMaxAtomicCounterBufferSize(resources.MaxAtomicCounterBufferSize), - mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings), - mMaxPixelLocalStoragePlanes(resources.MaxPixelLocalStoragePlanes), mDeclaringFunction(false), + mDeclaringMain(false), + mMainFunction(nullptr), + mIsReturnVisitedInMain(false), + mValidateESSL100Limitations( + ShouldEnforceESSL100LoopAndIndexingLimitations(spec, mShaderVersion, options)), + mFragmentOutputIndex1Used(false), + mFragmentOutputFragDepthUsed(false), mGeometryShaderInputPrimitiveType(EptUndefined), mGeometryShaderOutputPrimitiveType(EptUndefined), mGeometryShaderInvocations(0), mGeometryShaderMaxVertices(-1), - mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations), - mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices), mGeometryInputArraySize(0), - mMaxPatchVertices(resources.MaxPatchVertices), mTessControlShaderOutputVertices(0), mTessEvaluationShaderInputPrimitiveType(EtetUndefined), mTessEvaluationShaderInputVertexSpacingType(EtetUndefined), @@ -349,10 +521,42 @@ TParseContext::TParseContext(TSymbolTable &symt, mHasAnyPreciseType(false), mAdvancedBlendEquations(0), mFunctionBodyNewScope(false), - mOutputType(outputType) -{} + mOutputType(outputType), + mIRBuilder(gl::FromGLenum(type), options) +{ + mDiagnostics->setIRBuilder(&mIRBuilder); + + // If not using the IR, don't build it by pretending there's been an error. + if (!mCompileOptions.useIR) + { + mIRBuilder.onError(); + } +} + +TParseContext::~TParseContext() +{ + mDiagnostics->setIRBuilder(nullptr); +} + +ir::IR TParseContext::getIR() +{ + // Set advanced blend if specified. This is not done during parse because multiple statements + // accumulate modes. + if (mAdvancedBlendEquations.any()) + { + mIRBuilder.setAdvancedBlendEquations(mAdvancedBlendEquations.bits()); + } + + return ir::Builder::destroy(std::move(mIRBuilder)); +} -TParseContext::~TParseContext() {} +void TParseContext::onShaderVersionDeclared(int version) +{ + mShaderVersion = version; + // Update cached decisions that depend on the shader version + mValidateESSL100Limitations = ShouldEnforceESSL100LoopAndIndexingLimitations( + mShaderSpec, mShaderVersion, mCompileOptions); +} bool TParseContext::anyMultiviewExtensionAvailable() { @@ -362,8 +566,8 @@ bool TParseContext::anyMultiviewExtensionAvailable() bool TParseContext::parseVectorFields(const TSourceLoc &line, const ImmutableString &compString, - int vecSize, - TVector *fieldOffsets) + uint32_t vecSize, + TVector *fieldOffsets) { ASSERT(fieldOffsets); size_t fieldCount = compString.length(); @@ -541,6 +745,15 @@ void TParseContext::outOfRangeError(bool isError, void TParseContext::setTreeRoot(TIntermBlock *treeRoot) { +#ifdef ANGLE_IR + // When the IR is used, make sure the temporary tree created during parse is not used by anyone. + // With IR, eventually this tree doesn't need to be created at all, a stack of node properties + // to verify / propagate is sufficient during parse for validation purposes. + if (mCompileOptions.useIR) + { + return; + } +#endif mTreeRoot = treeRoot; mTreeRoot->setIsTreeRoot(); } @@ -617,12 +830,12 @@ void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, } } -void TParseContext::markStaticReadIfSymbol(TIntermNode *node) +void TParseContext::markStaticUseIfSymbol(TIntermNode *node) { TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); if (swizzleNode) { - markStaticReadIfSymbol(swizzleNode->getOperand()); + markStaticUseIfSymbol(swizzleNode->getOperand()); return; } TIntermBinary *binaryNode = node->getAsBinaryNode(); @@ -634,7 +847,7 @@ void TParseContext::markStaticReadIfSymbol(TIntermNode *node) case EOpIndexIndirect: case EOpIndexDirectStruct: case EOpIndexDirectInterfaceBlock: - markStaticReadIfSymbol(binaryNode->getLeft()); + markStaticUseIfSymbol(binaryNode->getLeft()); return; default: return; @@ -643,7 +856,7 @@ void TParseContext::markStaticReadIfSymbol(TIntermNode *node) TIntermSymbol *symbolNode = node->getAsSymbolNode(); if (symbolNode) { - symbolTable.markStaticRead(symbolNode->variable()); + symbolTable.markStaticUse(symbolNode->variable()); } } @@ -771,6 +984,9 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn case EvqLayerIn: message = "can't modify gl_Layer in a fragment shader"; break; + case EvqShadingRateEXT: + message = "can't modify gl_ShadingRateEXT"; + break; case EvqSampleID: message = "can't modify gl_SampleID"; break; @@ -821,7 +1037,17 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn TIntermSymbol *symNode = node->getAsSymbolNode(); if (message.empty() && symNode != nullptr) { - symbolTable.markStaticWrite(symNode->variable()); + if (mValidateESSL100Limitations) + { + checkESSL100NoLoopSymbolAssign(symNode, line); + } + if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior) + { + // For simplicity, if a variable is written to, assume it's no longer always true. + mConstantTrueVariables.erase(symNode->variable().uniqueId()); + } + + symbolTable.markStaticUse(symNode->variable()); return true; } @@ -954,7 +1180,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, for (TIntermNode *arg : arguments) { - markStaticReadIfSymbol(arg); + markStaticUseIfSymbol(arg); const TIntermTyped *argTyped = arg->getAsTyped(); ASSERT(argTyped != nullptr); if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType())) @@ -1238,24 +1464,20 @@ unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TInter size = static_cast(signedSize); } - if (size == 0u) +#ifdef ANGLE_IR + if (mCompileOptions.useIR) { - error(line, "array size must be greater than zero", ""); - return 1u; + // Pop the array size from the IR too. IR's evaluation should be equal to the AST constant + // fold; when the AST goes away, the size as evaluated by IR is going to be used. + const uint32_t sizeAccordingToIr = mIRBuilder.popArraySize(); + ASSERT(mDiagnostics->numErrors() != 0 || size == sizeAccordingToIr); } +#endif - if (IsOutputHLSL(getOutputType())) + if (size == 0u) { - // The size of arrays is restricted here to prevent issues further down the - // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to - // 4096 registers so this should be reasonable even for aggressively optimizable code. - const unsigned int sizeLimit = 65536; - - if (size > sizeLimit) - { - error(line, "array size too large", ""); - return 1u; - } + error(line, "array size must be greater than zero", ""); + return 1u; } return size; @@ -1264,7 +1486,8 @@ unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TInter bool TParseContext::checkIsValidArrayDimension(const TSourceLoc &line, TVector *arraySizes) { - if (arraySizes->size() > mMaxExpressionComplexity) + if (mCompileOptions.limitExpressionComplexity && + arraySizes->size() > static_cast(mResources.MaxExpressionComplexity)) { error(line, "array has too many dimensions", ""); return false; @@ -1369,7 +1592,7 @@ bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &index void TParseContext::checkNestingLevel(const TSourceLoc &line) { - if (static_cast(mLoopNestingLevel + mSwitchNestingLevel) > mMaxStatementDepth) + if (mControlFlow.size() > static_cast(mResources.MaxStatementDepth)) { error(line, "statement is too deeply nested", ""); } @@ -1420,6 +1643,189 @@ void TParseContext::checkDeclarationIsValidArraySize(const TSourceLoc &line, } } +void TParseContext::checkVariableSize(const TSourceLoc &line, + const ImmutableString &identifier, + const TType *type) +{ + // Prevent unrealistically large variable sizes in shaders. This works around driver bugs + // around int-size limits (such as 2GB). The limits are generously large enough that no real + // shader should ever hit it. + // + // The size check does not take std430 into account as it is intended for WebGL shaders. For + // the same reason, other shader stages than vertex/fragment are ignored as defer-sized + // variables e.g. in geometry shaders are not handled. + // + // Additionally, if the shader has already failed compilation, do not validate the type sizes. + // For example, if previously an error is generated due to too-deep struct nesting the + // calculation here could overflow the stack if performed. + if (!mCompileOptions.rejectWebglShadersWithLargeVariables || numErrors() > 0 || + (mShaderType != GL_VERTEX_SHADER && mShaderType != GL_FRAGMENT_SHADER)) + { + return; + } + + // Note: the only allowed interface block in webgl shaders is UBOs in std140 mode, so the size + // is unconditionally calculated with std140 rules if the variable is an interface block. + // Uniform variables are treated the same way as UBOs, as they are often packed the same way + // later on. + const size_t variableSize = + CalculateVariableSize(type, type->isInterfaceBlock() || type->getQualifier() == EvqUniform) + .ValueOrDefault(std::numeric_limits::max()); + if (variableSize > kWebGLMaxVariableSizeInBytes) + { + error(line, "Size of declared variable exceeds implementation-defined limit", identifier); + return; + } + + switch (type->getQualifier()) + { + // List of all types that need to be limited (for example because they cause overflows + // in drivers, or create trouble for the SPIR-V gen as the number of an instruction's + // arguments cannot be more than 64KB (see OutputSPIRVTraverser::cast)). + + // Local/global variables + case EvqTemporary: + case EvqGlobal: + case EvqConst: + + // Function arguments + case EvqParamIn: + case EvqParamOut: + case EvqParamInOut: + case EvqParamConst: + + // Varyings + case EvqVaryingIn: + case EvqVaryingOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqNoPerspectiveOut: + case EvqCentroidOut: + case EvqSampleOut: + case EvqNoPerspectiveCentroidOut: + case EvqNoPerspectiveSampleOut: + case EvqSmoothIn: + case EvqFlatIn: + case EvqNoPerspectiveIn: + case EvqCentroidIn: + case EvqNoPerspectiveCentroidIn: + case EvqNoPerspectiveSampleIn: + case EvqVertexOut: + case EvqFragmentIn: + case EvqPerVertexIn: + case EvqPerVertexOut: + + if (variableSize > kWebGLMaxPrivateVariableSizeInBytes) + { + error(line, + "Size of declared private variable exceeds implementation-defined limit", + identifier); + return; + } + mTotalPrivateVariablesSize += variableSize; + break; + default: + break; + } +} + +void TParseContext::checkVaryingLocations(const TSourceLoc &line, const TVariable *variable) +{ + // This function only checks those varyings with explicit locations for the purposes of conflict + // detection. + const TType &type = variable->getType(); + if (type.getLayoutQualifier().location == -1) + { + return; + } + + const bool isVaryingIn = IsVaryingIn(type.getQualifier()); + const bool isVaryingOut = IsVaryingOut(type.getQualifier()); + if (!isVaryingIn && !isVaryingOut) + { + return; + } + + VariableAndField conflictingSymbol; + const TField *conflictingFieldInNewSymbol = nullptr; + + if (!ValidateVaryingLocation(variable, + isVaryingIn ? &mInputVaryingLocations : &mOutputVaryingLocations, + mShaderType, &conflictingSymbol, &conflictingFieldInNewSymbol)) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "'" << variable->name(); + if (conflictingFieldInNewSymbol != nullptr) + { + strstr << "." << conflictingFieldInNewSymbol->name(); + } + strstr << "' conflicting location with '" << conflictingSymbol.variable->name(); + if (conflictingSymbol.field) + { + strstr << "." << conflictingSymbol.field->name(); + } + strstr << "'"; + error(line, strstr.str().c_str(), variable->name()); + } +} + +void TParseContext::checkFragmentOutputLocations(const TSourceLoc &line, const TVariable *variable) +{ + const TType &type = variable->getType(); + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); + if (type.getQualifier() != EvqFragmentOut && type.getQualifier() != EvqFragmentInOut) + { + return; + } + + VariableAndLocation fragmentOutput; + fragmentOutput.line = line; + fragmentOutput.variable = variable; + + // Keep track of the variables for conflict check at the end. In particular, the limit check + // and error messages should use either |MAX_DRAW_BUFFERS| or |MAX_DUAL_SOURCE_DRAW_BUFFERS|, + // and that depends on whether |index=1| is used by any declaration. + if (layoutQualifier.location != -1) + { + mFragmentOutputsWithLocation.push_back(fragmentOutput); + if (layoutQualifier.index == 1) + { + mFragmentOutputIndex1Used = true; + } + } + else if (layoutQualifier.yuv == true) + { + mFragmentOutputsYuv.push_back(fragmentOutput); + } + else + { + mFragmentOutputsWithoutLocation.push_back(fragmentOutput); + } +} + +void TParseContext::checkVariableLocations(const TSourceLoc &line, const TVariable *variable) +{ + // Interface variables cannot be declared inside functions. + if (mCurrentFunction != nullptr || variable->symbolType() == SymbolType::Empty) + { + return; + } + + // In ESSL 310, the shader may assign explicit locations to varyings, which need to be checked + // for conflicts. + if (mShaderVersion >= 310) + { + checkVaryingLocations(line, variable); + } + + // In ESSL 300, the shader may assign explicit locations to fragment outputs, which need to be + // checked for conflicts. + if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER) + { + checkFragmentOutputLocations(line, variable); + } +} + // Do some simple checks that are shared between all variable declarations, // and update the symbol table. // @@ -1427,14 +1833,28 @@ void TParseContext::checkDeclarationIsValidArraySize(const TSourceLoc &line, // bool TParseContext::declareVariable(const TSourceLoc &line, const ImmutableString &identifier, - const TType *type, + const TType *declarationType, + GeomTessArray sized, TVariable **variable) { - ASSERT((*variable) == nullptr); + ASSERT(*variable == nullptr); + + // When gl_Position and gl_PointSize are redeclared per EXT_separate_shader_objects, make sure + // they have the right qualifier. + const TType *type = declarationType; + if (identifier == "gl_Position" || identifier == "gl_PointSize") + { + TType *fixedType = new TType(*type); + fixedType->setQualifier(identifier == "gl_Position" ? EvqPosition : EvqPointSize); + fixedType->setTypeId(type->typeId()); + type = fixedType; + } SymbolType symbolType = SymbolType::UserDefined; switch (type->getQualifier()) { + case EvqPosition: + case EvqPointSize: case EvqClipDistance: case EvqCullDistance: case EvqFragDepth: @@ -1443,12 +1863,20 @@ bool TParseContext::declareVariable(const TSourceLoc &line, case EvqLastFragDepth: case EvqLastFragStencil: symbolType = SymbolType::BuiltIn; + + if (mBuiltInQualified[type->getQualifier()]) + { + error( + line, + "built-ins cannot be redeclared after being qualified as invariant or precise", + identifier); + } break; default: break; } - (*variable) = new TVariable(&symbolTable, identifier, type, symbolType); + *variable = new TVariable(&symbolTable, identifier, type, symbolType); if (type->getQualifier() == EvqFragmentOut) { @@ -1468,7 +1896,8 @@ bool TParseContext::declareVariable(const TSourceLoc &line, if (!((identifier.beginsWith("gl_LastFragData") || type->getQualifier() == EvqFragmentInOut) && (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) || - isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent)))) + isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))) && + !(type->isPixelLocal() && isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))) { checkNoncoherentIsNotSpecified(line, type->getLayoutQualifier().noncoherent); } @@ -1540,6 +1969,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line, { needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions()); } + MarkClipCullRedeclaredSize(line, type->getOutermostArraySize(), &mClipDistanceInfo); } else { @@ -1570,6 +2000,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line, { needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions()); } + MarkClipCullRedeclaredSize(line, type->getOutermostArraySize(), &mCullDistanceInfo); } else { @@ -1587,7 +2018,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line, error(line, "gl_FragDepth can only be redeclared as float", identifier); return false; } - needsReservedCheck = false; + needsReservedCheck = (symbolType == SymbolType::UserDefined); } else if (isExtensionEnabled(TExtension::EXT_separate_shader_objects) && mShaderType == GL_VERTEX_SHADER) @@ -1638,9 +2069,51 @@ bool TParseContext::declareVariable(const TSourceLoc &line, if (!checkIsNonVoid(line, identifier, type->getBasicType())) return false; + checkVariableSize(line, identifier, type); + checkVariableLocations(line, *variable); + + // Declare the variable in IR + declareIRVariable(*variable, sized); + return true; } +void TParseContext::declareIRVariable(const TVariable *variable, GeomTessArray sized) +{ + // If the variable is yet to be sized, don't declare it yet. + if (sized == GeomTessArray::Deferred) + { + mDeferredArrayVariablesToSize.push_back(variable); + return; + } + + const TType &type = variable->getType(); + ASSERT(type.isTypeIdSet()); + + ir::VariableId variableId; + switch (type.getQualifier()) + { + case EvqTemporary: + case EvqGlobal: + case EvqConst: + case EvqParamIn: + case EvqParamOut: + case EvqParamInOut: + case EvqParamConst: + // Temporary variables + variableId = mIRBuilder.declareTempVariable(variable->name(), type.typeId(), type); + break; + default: + // Interface and built-in variables + variableId = mIRBuilder.declareInterfaceVariable( + variable->symbolType() == SymbolType::Empty ? kEmptyImmutableString + : variable->name(), + type.typeId(), type, ir::DeclarationSource::Shader); + break; + } + mVariableToId[variable] = VariableToIdInfo{variableId, VariableToIdInfo::kNoImplicitField}; +} + void TParseContext::parseParameterQualifier(const TSourceLoc &line, const TTypeQualifierBuilder &typeQualifierBuilder, TPublicType &type) @@ -1679,6 +2152,12 @@ void TParseContext::parseParameterQualifier(const TSourceLoc &line, } } +void TParseContext::addParameter(TFunction *function, TParameter *param) +{ + const TVariable *variable = param->createVariable(&symbolTable); + function->addParameter(variable); +} + template bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line, const std::array &extensions) @@ -2042,6 +2521,7 @@ void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType, getImageInternalFormatString(layoutQualifier.imageInternalFormat)); } break; + case EiifR32I: case EiifRGBA8I: if (publicType.getBasicType() != EbtIPixelLocalANGLE) { @@ -2059,7 +2539,6 @@ void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType, getImageInternalFormatString(layoutQualifier.imageInternalFormat)); } break; - case EiifR32I: case EiifRGBA8_SNORM: case EiifRGBA16F: case EiifRGBA32F: @@ -2260,7 +2739,7 @@ void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int arrayTotalElementCount) { // Expects arraySize to be 1 when setting binding for only a single variable. - if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits) + if (binding >= 0 && binding + arrayTotalElementCount > mResources.MaxImageUnits) { error(location, "image binding greater than gl_MaxImageUnits", "binding"); } @@ -2271,7 +2750,7 @@ void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location, int arrayTotalElementCount) { // Expects arraySize to be 1 when setting binding for only a single variable. - if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits) + if (binding >= 0 && binding + arrayTotalElementCount > mResources.MaxCombinedTextureImageUnits) { error(location, "sampler binding greater than maximum texture units", "binding"); } @@ -2285,7 +2764,7 @@ void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, int size = (arraySize == 0 ? 1 : arraySize); if (qualifier == EvqUniform) { - if (binding + size > mMaxUniformBufferBindings) + if (binding + size > mResources.MaxUniformBufferBindings) { error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS", "binding"); @@ -2293,7 +2772,7 @@ void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, } else if (qualifier == EvqBuffer) { - if (binding + size > mMaxShaderStorageBufferBindings) + if (binding + size > mResources.MaxShaderStorageBufferBindings) { error(location, "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS", @@ -2303,7 +2782,7 @@ void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, } void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding) { - if (binding >= mMaxAtomicCounterBindings) + if (binding >= mResources.MaxAtomicCounterBindings) { error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings", "binding"); @@ -2325,7 +2804,7 @@ void TParseContext::checkPixelLocalStorageBindingIsValid(const TSourceLoc &locat error(location, "pixel local storage requires a binding index", "layout qualifier"); } // TODO(anglebug.com/40096838): - else if (layoutQualifier.binding >= mMaxPixelLocalStoragePlanes) + else if (layoutQualifier.binding >= mResources.MaxPixelLocalStoragePlanes) { error(location, "pixel local storage binding out of range", "layout qualifier"); } @@ -2358,9 +2837,10 @@ void TParseContext::checkUniformLocationInRange(const TSourceLoc &location, int loc = layoutQualifier.location; if (loc >= 0) // Shader-specified location { - if (loc >= mMaxUniformLocations || objectLocationCount > mMaxUniformLocations || + if (loc >= mResources.MaxUniformLocations || + objectLocationCount > mResources.MaxUniformLocations || static_cast(loc) + static_cast(objectLocationCount) > - static_cast(mMaxUniformLocations)) + static_cast(mResources.MaxUniformLocations)) { error(location, "Uniform location out of range", "location"); } @@ -2374,9 +2854,10 @@ void TParseContext::checkAttributeLocationInRange(const TSourceLoc &location, int loc = layoutQualifier.location; if (loc >= 0) // Shader-specified location { - if (loc >= mMaxVertexAttribs || objectLocationCount > mMaxVertexAttribs || + if (loc >= mResources.MaxVertexAttribs || + objectLocationCount > mResources.MaxVertexAttribs || static_cast(loc) + static_cast(objectLocationCount) > - static_cast(mMaxVertexAttribs)) + static_cast(mResources.MaxVertexAttribs)) { error(location, "Attribute location out of range", "location"); } @@ -2427,8 +2908,8 @@ void TParseContext::checkNoncoherentIsNotSpecified(const TSourceLoc &location, b if (noncoherent != false) { error(location, - "invalid layout qualifier: only valid when used with 'gl_LastFragData' or the " - "variable decorated with 'inout' in a fragment shader", + "invalid layout qualifier: only valid when used with 'gl_LastFragData', the " + "variable decorated with 'inout' in a fragment shader, or pixel local storage", "noncoherent"); } } @@ -2459,7 +2940,7 @@ void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandid qual == EvqParamInOut || qual == EvqParamConst); if (argumentIsRead) { - markStaticReadIfSymbol(argument); + markStaticUseIfSymbol(argument); if (!IsImage(argument->getBasicType())) { if (argument->getMemoryQualifier().writeonly) @@ -2571,6 +3052,7 @@ TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *cons TIntermConstantUnion *node = new TIntermConstantUnion( constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst)); node->setLine(line); + pushConstant(constantUnion, node->getType()); return node; } @@ -2670,17 +3152,128 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, return variable; } -TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, - const ImmutableString &name, - const TSymbol *symbol) +ir::VariableId TParseContext::declareBuiltInOnFirstUse(const TVariable *variable) { - const TVariable *variable = getNamedVariable(location, name, symbol); + if (variable->symbolType() == SymbolType::BuiltIn && + mVariableToId.find(variable) == mVariableToId.end()) + { + const TType *variableType = &variable->getType(); - if (!variable) + // For and clip/cull distance, let the IR know that they are not actually sized yet. + if (variableType->getQualifier() == EvqClipDistance || + variableType->getQualifier() == EvqCullDistance) + { + TType *unsizedArrayType = new TType(*variableType); + unsizedArrayType->toArrayBaseType(); + unsizedArrayType->makeArray(0); + variableType = unsizedArrayType; + } + + // For gl_FragData, change the array size to 1 if MRT is not supported; only index 0 is + // valid for access. Note that gl_FragData usage itself is restricted to ESSL 100, so a + // version check is unnecessary. + if (variableType->getQualifier() == EvqFragData && + !isExtensionEnabled(TExtension::EXT_draw_buffers)) + { + TType *singleElementArrayType = new TType(*variableType); + singleElementArrayType->toArrayBaseType(); + singleElementArrayType->makeArray(1); + variableType = singleElementArrayType; + } + + const ir::TypeId typeId = getTypeId(*variableType); + const ir::VariableId id = mIRBuilder.declareInterfaceVariable( + variable->name(), typeId, *variableType, ir::DeclarationSource::Internal); + mVariableToId[variable] = VariableToIdInfo{id, VariableToIdInfo::kNoImplicitField}; + + switch (variableType->getQualifier()) + { + case EvqClipDistance: + mClipDistanceInfo.id = id; + break; + case EvqCullDistance: + mCullDistanceInfo.id = id; + break; + default: + break; + } + + return id; + } + + if (mDiagnostics->numErrors() > 0) { - TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - node->setLine(location); - return node; + return {}; + } + + return mVariableToId.at(variable).id; +} + +void TParseContext::declareFunction(const TFunction *function, FunctionDeclaration declaration) +{ + // If the function prototype hasn't been previously encountered, this is a new function that + // should be declared to the IR first. + if (mFunctionToId.find(function) == mFunctionToId.end()) + { + TVector params; + TVector paramDirections; + for (size_t i = 0; i < function->getParamCount(); ++i) + { + const TVariable *param = function->getParam(i); + const TType ¶mType = param->getType(); + + ir::VariableId paramId = mIRBuilder.declareFunctionParam( + param->name(), getTypeId(paramType), paramType, paramType.getQualifier()); + mVariableToId[param] = VariableToIdInfo{paramId, VariableToIdInfo::kNoImplicitField}; + + params.push_back(paramId); + paramDirections.push_back(paramType.getQualifier()); + } + + mFunctionToId[function] = + mIRBuilder.newFunction(function->name(), angle::Span(params.data(), params.size()), + angle::Span(paramDirections.data(), paramDirections.size()), + getTypeId(function->getReturnType()), function->getReturnType()); + } + else if (declaration == FunctionDeclaration::Definition) + { + TVector paramNames; + TVector paramIds(function->getParamCount()); + for (size_t i = 0; i < function->getParamCount(); ++i) + { + const TVariable *param = function->getParam(i); + paramNames.push_back(param->name()); + } + mIRBuilder.updateFunctionParamNames(mFunctionToId[function], + angle::Span(paramNames.data(), paramNames.size()), + angle::Span(paramIds.data(), paramIds.size())); + + // When a prototype is previously visited, `declareFunction` has already created the + // variables for the function parameters in the |if| above. When the function prototype is + // visited again during function definition, the real argument names are provided (so the + // variables should be renamed). New |TVariable|s are also created by the parser, which + // should map to the same IR ids. At this point, the old |TVariable|s are lost, so the IR + // returns the variable ids for the parameters. + for (size_t i = 0; i < function->getParamCount(); ++i) + { + const TVariable *param = function->getParam(i); + mVariableToId[param] = + VariableToIdInfo{paramIds[i], VariableToIdInfo::kNoImplicitField}; + } + } +} + +TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, + const ImmutableString &name, + const TSymbol *symbol) +{ + const TVariable *variable = getNamedVariable(location, name, symbol); + + if (!variable) + { + TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); + node->setLine(location); + return node; } const TType &variableType = variable->getType(); @@ -2713,7 +3306,8 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, (variableType.getQualifier() == EvqPerVertexIn)) { ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr); - node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize()); + variable = symbolTable.getGlInVariableWithArraySize(); + node = new TIntermSymbol(variable); } else { @@ -2733,6 +3327,34 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, } ASSERT(node != nullptr); node->setLine(location); + + // Push the variable or its equivalent constant. Note that when the variable is declared as + // `const`, the variable is pushed instead of the constant so its precision is retained. + if (variableType.getQualifier() == EvqConst && + mVariableToId.find(variable) != mVariableToId.end()) + { + pushVariable(variable); + } + else if (node->getAsConstantUnion()) + { + pushConstant(node->getAsConstantUnion()->getConstantValue(), variableType); + } + else if (variable->getConstPointer()) + { + pushConstant(variable->getConstPointer(), variableType); + } + else if (node->getAsSymbolNode()) + { + // For built-ins, declare them in the IR on first reference. + declareBuiltInOnFirstUse(variable); + pushVariable(variable); + + if (variableType.getQualifier() == EvqFragDepth) + { + mFragmentOutputFragDepthUsed = true; + } + } + return node; } @@ -2813,6 +3435,8 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, type->sizeUnsizedArrays(initializer->getType().getArraySizes()); } + type->setTypeId(getTypeId(*type)); + const TQualifier qualifier = type->getQualifier(); bool constError = false; @@ -2831,7 +3455,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, } TVariable *variable = nullptr; - if (!declareVariable(line, identifier, type, &variable)) + if (!declareVariable(line, identifier, type, GeomTessArray::Sized, &variable)) { return false; } @@ -2880,23 +3504,37 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, return false; } - if (qualifier == EvqConst) + const TConstantUnion *initializerConstArray = initializer->getConstantValue(); + if (initializerConstArray) { + if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior) + { + // If this is `bool variable = true`, track it. If it's ever used as l-value, it's + // removed from this list. At the end of parse, if a variable is in this list, it's set + // to true and never modified. + if (type->isScalarBool() && initializerConstArray->getBConst()) + { + mConstantTrueVariables.insert(variable->uniqueId()); + } + } + // Save the constant folded value to the variable if possible. - const TConstantUnion *constArray = initializer->getConstantValue(); - if (constArray) + if (qualifier == EvqConst) { - variable->shareConstPointer(constArray); + variable->shareConstPointer(initializerConstArray); if (initializer->getType().canReplaceWithConstantUnion()) { + mIRBuilder.initialize(mVariableToId.at(variable).id); ASSERT(*initNode == nullptr); return true; } } } + mIRBuilder.initialize(mVariableToId.at(variable).id); + *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer); - markStaticReadIfSymbol(initializer); + markStaticUseIfSymbol(initializer); (*initNode)->setLine(line); return true; } @@ -2928,165 +3566,666 @@ TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType, return nullptr; } -TIntermNode *TParseContext::addLoop(TLoopType type, - TIntermNode *init, - TIntermNode *cond, - TIntermTyped *expr, - TIntermNode *body, - const TSourceLoc &line) +void TParseContext::checkESSL100ForLoopInit(TIntermNode *init, const TSourceLoc &line) { - TIntermNode *node = nullptr; - TIntermTyped *typedCond = nullptr; - if (cond) + // The loop must be a `for` loop, and have the following form according to ESSL 100 spec, + // Appendix A: + // + // for (type symbol = initializer; symbol op constant; symbol += constant) + // + // Validate the init statement here. + if (init == nullptr) { - markStaticReadIfSymbol(cond); - typedCond = cond->getAsTyped(); + error(line, "Missing init declaration", "for"); + return; } - if (expr) + + // + // init-declaration has the form: + // type-specifier identifier = constant-expression + // + TIntermDeclaration *decl = init->getAsDeclarationNode(); + if (decl == nullptr) { - markStaticReadIfSymbol(expr); + error(line, "Invalid init declaration", "for"); + return; } - // In case the loop body was not parsed as a block and contains a statement that simply refers - // to a variable, we need to mark it as statically used. - if (body) + TIntermSequence *declSeq = decl->getSequence(); + if (declSeq->size() != 1) { - markStaticReadIfSymbol(body); + error(line, "Invalid init declaration", "for"); + return; } - if (cond == nullptr || typedCond) + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); + if (declInit == nullptr || declInit->getOp() != EOpInitialize) { - if (type == ELoopDoWhile && typedCond) - { - checkIsScalarBool(line, typedCond); - } - // In the case of other loops, it was checked before that the condition is a scalar boolean. - ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr || - (typedCond->getBasicType() == EbtBool && !typedCond->isArray() && - !typedCond->isVector())); - - node = new TIntermLoop(type, init, typedCond, expr, EnsureLoopBodyBlock(body)); - node->setLine(line); - return node; + error(line, "Invalid init declaration", "for"); + return; + } + TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); + if (symbol == nullptr) + { + error(line, "Invalid init declaration", "for"); + return; + } + // The loop index has type int or float. + TBasicType type = symbol->getBasicType(); + if ((type != EbtInt && type != EbtUInt && type != EbtFloat) || !symbol->isScalar()) + { + error(line, "Invalid type for loop index", getBasicString(type)); + return; + } + // The loop index is initialized with constant expression. + if (!IsESSL100ConstantExpression(declInit->getRight())) + { + error(line, "Loop index cannot be initialized with non-constant expression", + symbol->getName()); + return; } - ASSERT(type != ELoopDoWhile); - - TIntermDeclaration *declaration = cond->getAsDeclarationNode(); - ASSERT(declaration); - TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode(); - ASSERT(declarator->getLeft()->getAsSymbolNode()); - - // The condition is a declaration. In the AST representation we don't support declarations as - // loop conditions. Wrap the loop to a block that declares the condition variable and contains - // the loop. - TIntermBlock *block = new TIntermBlock(); + // Keep track of the loop symbol. The loop symbol is not allowed to be modified in the body. + ASSERT(mControlFlow.back().type == ControlFlowType::Loop); + mControlFlow.back().forLoopSymbol = symbol->uniqueId(); +} - TIntermDeclaration *declareCondition = new TIntermDeclaration(); - declareCondition->appendDeclarator(declarator->getLeft()->deepCopy()); - block->appendStatement(declareCondition); +void TParseContext::checkESSL100ForLoopCondition(TIntermNode *condition, const TSourceLoc &line) +{ + if (condition == nullptr) + { + error(line, "Missing condition", "for"); + return; + } - TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(), - declarator->getRight()->deepCopy()); - TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureLoopBodyBlock(body)); - block->appendStatement(loop); - loop->setLine(line); - block->setLine(line); - return block; + // condition has the form: + // loop_index relational_operator constant_expression + TIntermBinary *binOp = condition->getAsBinaryNode(); + if (binOp == nullptr) + { + error(line, "Invalid condition", "for"); + return; + } + // Loop index should be to the left of relational operator. + TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode(); + if (symbol == nullptr) + { + error(line, "Invalid condition", "for"); + return; + } + ASSERT(mControlFlow.back().type == ControlFlowType::Loop); + if (symbol->uniqueId() != mControlFlow.back().forLoopSymbol) + { + error(line, "Expected loop index", symbol->getName()); + return; + } + // Relational operator is one of: > >= < <= == or !=. + switch (binOp->getOp()) + { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + default: + error(line, "Invalid relational operator", GetOperatorString(binOp->getOp())); + return; + } + // Loop index must be compared with a constant. + if (!IsESSL100ConstantExpression(binOp->getRight())) + { + error(line, "Loop index cannot be compared with non-constant expression", + symbol->getName()); + return; + } } -TIntermNode *TParseContext::addIfElse(TIntermTyped *cond, - TIntermNodePair code, - const TSourceLoc &loc) +void TParseContext::checkESSL100ForLoopContinue(TIntermNode *statement, const TSourceLoc &line) { - bool isScalarBool = checkIsScalarBool(loc, cond); - // In case the conditional statements were not parsed as blocks and contain a statement that - // simply refers to a variable, we need to mark them as statically used. - if (code.node1) + if (statement == nullptr) { - markStaticReadIfSymbol(code.node1); + error(line, "Missing expression", "for"); + return; } - if (code.node2) + + // for expression has one of the following forms: + // + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // + // The last two forms are not specified in the spec, but we're assuming its an oversight. + TIntermUnary *unOp = statement->getAsUnaryNode(); + TIntermBinary *binOp = unOp ? nullptr : statement->getAsBinaryNode(); + + TOperator op = EOpNull; + const TFunction *opFunc = nullptr; + TIntermSymbol *symbol = nullptr; + if (unOp != nullptr) + { + op = unOp->getOp(); + opFunc = unOp->getFunction(); + symbol = unOp->getOperand()->getAsSymbolNode(); + } + else if (binOp != nullptr) { - markStaticReadIfSymbol(code.node2); + op = binOp->getOp(); + symbol = binOp->getLeft()->getAsSymbolNode(); } - // For compile time constant conditions, prune the code now. - if (isScalarBool && cond->getAsConstantUnion()) + // The operand must be loop index. + if (symbol == nullptr) { - if (cond->getAsConstantUnion()->getBConst(0) == true) - { - return EnsureBlock(code.node1); - } - else + error(line, "Invalid expression", "for"); + return; + } + ASSERT(mControlFlow.back().type == ControlFlowType::Loop); + if (symbol->uniqueId() != mControlFlow.back().forLoopSymbol) + { + error(line, "Expected loop index", symbol->getName()); + return; + } + + // The operator is one of: ++ -- += -=. + switch (op) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + ASSERT(unOp != nullptr && binOp == nullptr); + break; + case EOpAddAssign: + case EOpSubAssign: + ASSERT(unOp == nullptr && binOp != nullptr); + break; + default: + if (BuiltInGroup::IsBuiltIn(op)) + { + ASSERT(opFunc != nullptr); + error(line, "Invalid built-in call", opFunc->name().data()); + } + else + { + error(line, "Invalid operator", GetOperatorString(op)); + } + return; + } + + // Loop index must be incremented/decremented with a constant. + if (binOp != nullptr) + { + if (!IsESSL100ConstantExpression(binOp->getRight())) { - return EnsureBlock(code.node2); + error(line, "Loop index cannot be modified by non-constant expression", + symbol->getName()); + return; } } - TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2)); - markStaticReadIfSymbol(cond); - node->setLine(loc); - - return node; + // After the continue statement is visited, mark the for loop symbol as needing to stay + // constant. + mControlFlow.back().isForLoopSymbolConstant = true; } -void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) +bool TParseContext::isESSL100ConstantLoopSymbol(TIntermSymbol *symbol) { - checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision, - typeSpecifier->getBasicType()); + ASSERT(symbol != nullptr); + const TSymbolUniqueId symbolUniqueId = symbol->uniqueId(); - if (mShaderVersion < 300 && typeSpecifier->isArray()) + for (const ControlFlow &controlFlow : mControlFlow) { - error(typeSpecifier->getLine(), "not supported", "first-class array"); - typeSpecifier->clearArrayness(); + if (controlFlow.isForLoopSymbolConstant && symbolUniqueId == controlFlow.forLoopSymbol) + { + return true; + } } + return false; } -TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, - const TPublicType &typeSpecifier) +void TParseContext::checkESSL100NoLoopSymbolAssign(TIntermSymbol *symbol, const TSourceLoc &line) { - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - TPublicType returnType = typeSpecifier; - returnType.qualifier = typeQualifier.qualifier; - returnType.invariant = typeQualifier.invariant; - returnType.precise = typeQualifier.precise; - returnType.layoutQualifier = typeQualifier.layoutQualifier; - returnType.memoryQualifier = typeQualifier.memoryQualifier; - returnType.precision = typeSpecifier.precision; - - if (typeQualifier.precision != EbpUndefined) + if (isESSL100ConstantLoopSymbol(symbol)) { - returnType.precision = typeQualifier.precision; + error(line, "Loop index cannot be statically assigned to within the body of the loop", + symbol->getName()); } +} - checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision, - typeSpecifier.getBasicType()); - - checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, - typeSpecifier.getLine()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); - - checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(), - returnType.layoutQualifier.earlyFragmentTests); +void TParseContext::checkESSL100ConstantIndex(TIntermTyped *index, const TSourceLoc &line) +{ + // According to ESSL 100 spec, Appendix A: + // + // > constant-index-expressions are a superset of constant-expressions. + // > Constant-index-expressions can include loop indices as defined in GLSL ES 1.0 spec, + // > Appendix A, section 4. + // + // > The following are constant-index-expressions: + // > - Constant expressions + // > - Loop indices as defined in section 4 + // > - Expressions composed of both of the above + // + // To implement the above, all subnodes of index are visited: + // + // * If any are symbols, they must be a loop index. + // * Otherwise if they have no children, they must have a constant value. + // * No user function calls are allowed (every other forbidden function call ends up using a + // symbol, such as texture2D()) + // + // Since the expression complexity validation is not done yet (check against + // MaxExpressionComplexity), this operation is not done with recursion. + std::vector toInspect; + toInspect.push_back(index); - if (returnType.qualifier == EvqSampleIn || returnType.qualifier == EvqSampleOut || - returnType.qualifier == EvqNoPerspectiveSampleIn || - returnType.qualifier == EvqNoPerspectiveSampleOut) + while (!toInspect.empty()) { - mSampleQualifierSpecified = true; - } + TIntermTyped *node = toInspect.back(); + toInspect.pop_back(); - if (mShaderVersion < 300) - { - if (typeSpecifier.isArray()) + if (node->getAsAggregate() && node->getAsAggregate()->isFunctionCall()) { - error(typeSpecifier.getLine(), "not supported", "first-class array"); - returnType.clearArrayness(); + error(line, "Index expression cannot contain function calls", "[]"); + return; } - if (returnType.qualifier == EvqAttribute && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) + size_t childCount = node->getChildCount(); + if (childCount == 0) + { + // If a symbol is used that's not const or a loop index, this expression is not allowed. + TIntermSymbol *symbol = node->getAsSymbolNode(); + if (symbol != nullptr) + { + if (symbol->getQualifier() != EvqConst && !isESSL100ConstantLoopSymbol(symbol)) + { + error(line, "Index expression can only contain const or loop symbols", + symbol->getName().data()); + return; + } + } + else if (!node->hasConstantValue()) + { + error(line, "Index expression must be constant", "[]"); + return; + } + } + + for (size_t childIndex = 0; childIndex < childCount; ++childIndex) + { + toInspect.push_back(node->getChildNode(childIndex)->getAsTyped()); + } + } +} + +void TParseContext::popControlFlow() +{ + ASSERT(!mControlFlow.empty()); + const ControlFlow justEndedControlFlow = mControlFlow.back(); + mControlFlow.pop_back(); + + if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior) + { + // Carry information about whether break or return are present in the block to the parent + // block. + if (!mControlFlow.empty()) + { + mControlFlow.back().hasReturn = + mControlFlow.back().hasReturn || justEndedControlFlow.hasReturn; + // `break` in an if block or just a nested block also break out of the outer construct. + if (justEndedControlFlow.type == ControlFlowType::If || + justEndedControlFlow.type == ControlFlowType::NewScope) + { + mControlFlow.back().hasBreak = + mControlFlow.back().hasBreak || justEndedControlFlow.hasBreak; + } + } + + if (justEndedControlFlow.type != ControlFlowType::Loop || justEndedControlFlow.hasReturn || + justEndedControlFlow.hasBreak) + { + return; + } + + // If the loop has a constant-true condition without a break or return, it will loop + // forever. Give a parse error about it. + if (justEndedControlFlow.isLoopConditionConstantTrue) + { + error(justEndedControlFlow.loopLocation, "Infinite loop detected in the shader", ""); + return; + } + + // Otherwise, if the loop is based on a symbol that stays constant-true until the end of the + // shader, that's also an obvious infinite loop. + if (justEndedControlFlow.loopConditionConstantTrueSymbol != nullptr && + mConstantTrueVariables.find( + justEndedControlFlow.loopConditionConstantTrueSymbol->uniqueId()) != + mConstantTrueVariables.end()) + { + // But we can't know whether the variable will stay unchanged until the end of the + // shader, so the decision to produce a compile error is deferred. + VariableAndLocation loopVariable; + loopVariable.line = justEndedControlFlow.loopLocation; + loopVariable.variable = justEndedControlFlow.loopConditionConstantTrueSymbol; + + mPossiblyInfiniteLoops.push_back(loopVariable); + } + } +} + +void TParseContext::beginNestedScope() +{ + symbolTable.push(); + + ControlFlow flow = {}; + flow.type = ControlFlowType::NewScope; + mControlFlow.push_back(flow); +} + +void TParseContext::endNestedScope() +{ + symbolTable.pop(); + popControlFlow(); +} + +void TParseContext::beginLoop(TLoopType loopType, const TSourceLoc &line) +{ + ControlFlow flow = {}; + flow.type = ControlFlowType::Loop; + mControlFlow.push_back(flow); + + checkNestingLevel(line); + + // According to ESSL 100 spec, Appendix A, while and do-while don't need to be supported. + // WebGL forbids them, and so they must be rejected. + if (mValidateESSL100Limitations && loopType != ELoopFor) + { + error(line, "This type of loop is not allowed", loopType == ELoopWhile ? "while" : "do"); + } +} + +void TParseContext::onLoopConditionBegin(TIntermNode *init, const TSourceLoc &line) +{ + if (mValidateESSL100Limitations) + { + checkESSL100ForLoopInit(init, line); + } + + mIRBuilder.beginLoopCondition(); +} + +void TParseContext::onLoopConditionEnd(TIntermNode *condition, const TSourceLoc &line) +{ + if (mValidateESSL100Limitations) + { + checkESSL100ForLoopCondition(condition, line); + } + + if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior) + { + mControlFlow.back().loopLocation = line; + TIntermConstantUnion *constCondition = + condition ? condition->getAsConstantUnion() : nullptr; + TIntermSymbol *conditionSymbol = condition ? condition->getAsSymbolNode() : nullptr; + + const bool isConditionConstantTrue = + condition == nullptr || + (constCondition != nullptr && constCondition->getType().isScalarBool() && + constCondition->getBConst(0)); + + if (isConditionConstantTrue) + { + mControlFlow.back().isLoopConditionConstantTrue = true; + } + else if (conditionSymbol != nullptr && + mConstantTrueVariables.find(conditionSymbol->uniqueId()) != + mConstantTrueVariables.end()) + { + mControlFlow.back().loopConditionConstantTrueSymbol = &conditionSymbol->variable(); + } + } + + if (condition == nullptr) + { + // If a condition is not specified, assume it's true (possible with for(..;;..)). + mIRBuilder.pushConstantBool(true); + } + else if (condition->getAsDeclarationNode()) + { + // If a condition is a variable declaration (like while (bool cond = ...)), push the + // variable to the stack so it's loaded from. + TIntermDeclaration *declaration = condition->getAsDeclarationNode(); + TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode(); + ASSERT(declarator->getLeft()->getAsSymbolNode()); + pushVariable(&declarator->getLeft()->getAsSymbolNode()->variable()); + } + mIRBuilder.endLoopCondition(); +} + +void TParseContext::onLoopContinueEnd(TIntermNode *statement, const TSourceLoc &line) +{ + if (mValidateESSL100Limitations) + { + checkESSL100ForLoopContinue(statement, line); + } + + mIRBuilder.endLoopContinue(); + endStatementWithValue(statement); +} + +void TParseContext::onDoLoopBegin() +{ + mIRBuilder.beginDoLoop(); +} + +void TParseContext::onDoLoopConditionBegin() +{ + mIRBuilder.beginDoLoopCondition(); +} + +TIntermNode *TParseContext::addLoop(TLoopType type, + TIntermNode *init, + TIntermNode *cond, + TIntermTyped *expr, + TIntermNode *body, + const TSourceLoc &line) +{ + popControlFlow(); + + TIntermNode *node = nullptr; + TIntermTyped *typedCond = nullptr; + if (cond) + { + markStaticUseIfSymbol(cond); + typedCond = cond->getAsTyped(); + } + if (expr) + { + markStaticUseIfSymbol(expr); + } + + // In case the loop body was not parsed as a block and contains a statement that simply refers + // to a variable, we need to mark it as statically used. + if (body) + { + markStaticUseIfSymbol(body); + } + if (cond == nullptr || typedCond) + { + if (type == ELoopDoWhile && typedCond) + { + checkIsScalarBool(line, typedCond); + } + + if (type == ELoopDoWhile) + { + mIRBuilder.endDoLoop(); + } + else + { + mIRBuilder.endLoop(); + } + + // In the case of other loops, it was checked before that the condition is a scalar boolean. + ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr || + (typedCond->getBasicType() == EbtBool && !typedCond->isArray() && + !typedCond->isVector())); + + node = new TIntermLoop(type, init, typedCond, expr, EnsureLoopBodyBlock(body)); + node->setLine(line); + return node; + } + + ASSERT(type != ELoopDoWhile); + mIRBuilder.endLoop(); + + TIntermDeclaration *declaration = cond->getAsDeclarationNode(); + ASSERT(declaration); + TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode(); + ASSERT(declarator->getLeft()->getAsSymbolNode()); + + // The condition is a declaration. In the AST representation we don't support declarations as + // loop conditions. Wrap the loop to a block that declares the condition variable and contains + // the loop. + TIntermBlock *block = new TIntermBlock(); + + TIntermDeclaration *declareCondition = new TIntermDeclaration(); + declareCondition->appendDeclarator(declarator->getLeft()->deepCopy()); + block->appendStatement(declareCondition); + + TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(), + declarator->getRight()->deepCopy()); + TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureLoopBodyBlock(body)); + block->appendStatement(loop); + loop->setLine(line); + block->setLine(line); + return block; +} + +void TParseContext::onIfTrueBlockBegin(TIntermTyped *cond, const TSourceLoc &loc) +{ + ControlFlow flow = {}; + flow.type = ControlFlowType::If; + mControlFlow.push_back(flow); + + checkIsScalarBool(loc, cond); + mIRBuilder.beginIfTrueBlock(); +} + +void TParseContext::onIfTrueBlockEnd() +{ + mIRBuilder.endIfTrueBlock(); +} + +void TParseContext::onIfFalseBlockBegin() +{ + mIRBuilder.beginIfFalseBlock(); +} + +void TParseContext::onIfFalseBlockEnd() +{ + mIRBuilder.endIfFalseBlock(); +} + +TIntermNode *TParseContext::addIfElse(TIntermTyped *cond, + TIntermNodePair code, + const TSourceLoc &loc) +{ + popControlFlow(); + + bool isScalarBool = checkIsScalarBool(loc, cond); + // In case the conditional statements were not parsed as blocks and contain a statement that + // simply refers to a variable, we need to mark them as statically used. + if (code.node1) + { + markStaticUseIfSymbol(code.node1); + } + if (code.node2) + { + markStaticUseIfSymbol(code.node2); + } + + mIRBuilder.endIf(); + + // For compile time constant conditions, prune the code now. + if (isScalarBool && cond->getAsConstantUnion()) + { + if (cond->getAsConstantUnion()->getBConst(0) == true) + { + return EnsureBlock(code.node1); + } + else + { + return EnsureBlock(code.node2); + } + } + + TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2)); + markStaticUseIfSymbol(cond); + node->setLine(loc); + + return node; +} + +void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) +{ + checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision, + typeSpecifier->getBasicType()); + + if (mShaderVersion < 300 && typeSpecifier->isArray()) + { + error(typeSpecifier->getLine(), "not supported", "first-class array"); + typeSpecifier->clearArrayness(); + } +} + +TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, + const TPublicType &typeSpecifier) +{ + TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); + + TPublicType returnType = typeSpecifier; + returnType.qualifier = typeQualifier.qualifier; + returnType.invariant = typeQualifier.invariant; + returnType.precise = typeQualifier.precise; + returnType.layoutQualifier = typeQualifier.layoutQualifier; + returnType.memoryQualifier = typeQualifier.memoryQualifier; + returnType.precision = typeSpecifier.precision; + + if (typeQualifier.precision != EbpUndefined) + { + returnType.precision = typeQualifier.precision; + } + + checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision, + typeSpecifier.getBasicType()); + + checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, + typeSpecifier.getLine()); + + checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); + + checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(), + returnType.layoutQualifier.earlyFragmentTests); + + if (returnType.qualifier == EvqSampleIn || returnType.qualifier == EvqSampleOut || + returnType.qualifier == EvqNoPerspectiveSampleIn || + returnType.qualifier == EvqNoPerspectiveSampleOut) + { + mSampleQualifierSpecified = true; + } + + if (mShaderVersion < 300) + { + if (typeSpecifier.isArray()) + { + error(typeSpecifier.getLine(), "not supported", "first-class array"); + returnType.clearArrayness(); + } + + if (returnType.qualifier == EvqAttribute && + (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) { error(typeSpecifier.getLine(), "cannot be bool or int", getQualifierString(returnType.qualifier)); @@ -3287,7 +4426,7 @@ void TParseContext::checkAtomicCounterOffsetLimit(const TSourceLoc &location, co { TLayoutQualifier layoutQualifier = type.getLayoutQualifier(); - if (layoutQualifier.offset >= mMaxAtomicCounterBufferSize) + if (layoutQualifier.offset >= mResources.MaxAtomicCounterBufferSize) { error(location, "Offset must not exceed the maximum atomic counter buffer size", "atomic counter"); @@ -3305,9 +4444,43 @@ void TParseContext::checkAtomicCounterOffsetIsValid(bool forceAppend, void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, const ImmutableString &token, - TType *type) + TType *type, + GeomTessArray *sizedOut) { - if (IsGeometryShaderInput(mShaderType, type->getQualifier())) + if (type->getQualifier() == EvqPerVertexIn && mShaderType == GL_GEOMETRY_SHADER) + { + // This is a redeclaration of gl_in, which may be unsized. + if (!type->isArray()) + { + error(location, "gl_in must be an array", "gl_in"); + type->makeArray(0); + } + + // If the size is already determined, set the size / verify it: + if (mGeometryShaderInputPrimitiveType != EptUndefined) + { + ASSERT(mGeometryInputArraySize != 0); + if (type->getOutermostArraySize() > 0 && + type->getOutermostArraySize() != mGeometryInputArraySize) + { + error(location, "gl_in array size inconsistent with primitive", "gl_in"); + } + else if (type->getOutermostArraySize() == 0) + { + type->sizeOutermostUnsizedArray(mGeometryInputArraySize); + } + } + else + { + warning(location, + "Missing a valid input primitive declaration before declaring an unsized " + "gl_in array", + "Deferred"); + mDeferredArrayTypesToSize.push_back(type); + *sizedOut = GeomTessArray::Deferred; + } + } + else if (IsGeometryShaderInput(mShaderType, type->getQualifier())) { if (type->isArray() && type->getOutermostArraySize() == 0u) { @@ -3329,6 +4502,7 @@ void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &lo "array input", "Deferred"); mDeferredArrayTypesToSize.push_back(type); + *sizedOut = GeomTessArray::Deferred; } } else if (type->isArray()) @@ -3344,9 +4518,58 @@ void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &lo void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location, const ImmutableString &token, - TType *type) + TType *type, + GeomTessArray *sizedOut) { TQualifier qualifier = type->getQualifier(); + + if (qualifier == EvqPerVertexIn && type->isArray() && + (mShaderType == GL_TESS_CONTROL_SHADER || mShaderType == GL_TESS_EVALUATION_SHADER)) + { + // gl_in in both tessellation stages should be sized as gl_MaxPatchVertices + if (type->getOutermostArraySize() == 0) + { + ASSERT(mResources.MaxPatchVertices > 0); + type->sizeOutermostUnsizedArray(mResources.MaxPatchVertices); + } + else if (type->getOutermostArraySize() != + static_cast(mResources.MaxPatchVertices)) + { + error(location, + "If a size is specified for a tessellation control or evaluation gl_in " + "variable, it must match the maximum patch size (gl_MaxPatchVertices).", + token); + } + return; + } + if (qualifier == EvqPerVertexOut && type->isArray() && mShaderType == GL_TESS_CONTROL_SHADER) + { + if (type->getOutermostArraySize() == 0) + { + if (mTessControlShaderOutputVertices == 0) + { + error(location, + "Missing a valid vertices declaration before declaring an unsized " + "gl_out array", + "gl_out"); + } + else + { + type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices); + } + } + else if (type->getOutermostArraySize() != + static_cast(mTessControlShaderOutputVertices) && + mTessControlShaderOutputVertices != 0) + { + error(location, + "If a size is specified for a tessellation control gl_out " + "variable, it must match the the number of vertices in the output patch.", + token); + } + return; + } + if (!IsTessellationControlShaderOutput(mShaderType, qualifier) && !IsTessellationControlShaderInput(mShaderType, qualifier) && !IsTessellationEvaluationShaderInput(mShaderType, qualifier)) @@ -3378,8 +4601,8 @@ void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSource case EvqNoPerspectiveSampleIn: // Declaring an array size is optional. If no size is specified, it will be taken // from the implementation-dependent maximum patch size (gl_MaxPatchVertices). - ASSERT(mMaxPatchVertices > 0); - type->sizeOutermostUnsizedArray(mMaxPatchVertices); + ASSERT(mResources.MaxPatchVertices > 0); + type->sizeOutermostUnsizedArray(mResources.MaxPatchVertices); break; case EvqTessControlOut: case EvqTessEvaluationOut: @@ -3396,6 +4619,7 @@ void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSource if (mTessControlShaderOutputVertices == 0) { mDeferredArrayTypesToSize.push_back(type); + *sizedOut = GeomTessArray::Deferred; } else { @@ -3412,7 +4636,7 @@ void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSource if (IsTessellationControlShaderInput(mShaderType, qualifier) || IsTessellationEvaluationShaderInput(mShaderType, qualifier)) { - if (outermostSize != static_cast(mMaxPatchVertices)) + if (outermostSize != static_cast(mResources.MaxPatchVertices)) { error(location, "If a size is specified for a tessellation control or evaluation user-defined " @@ -3476,8 +4700,14 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration( } } - checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type); - checkTessellationShaderUnsizedArraysAndSetSize(identifierOrTypeLocation, identifier, type); + GeomTessArray sized = GeomTessArray::Sized; + checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type, &sized); + checkTessellationShaderUnsizedArraysAndSetSize(identifierOrTypeLocation, identifier, type, + &sized); + if (sized == GeomTessArray::Sized) + { + type->setTypeId(getTypeId(*type)); + } declarationQualifierErrorCheck(type->getQualifier(), publicType.layoutQualifier, identifierOrTypeLocation); @@ -3514,15 +4744,15 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration( checkAtomicCounterOffsetIsValid(false, identifierOrTypeLocation, type); } + adjustRedeclaredBuiltInType(identifierOrTypeLocation, identifier, type); + TVariable *variable = nullptr; - if (declareVariable(identifierOrTypeLocation, identifier, type, &variable)) + if (declareVariable(identifierOrTypeLocation, identifier, type, sized, &variable)) { symbol = new TIntermSymbol(variable); } } - adjustRedeclaredBuiltInType(identifierOrTypeLocation, identifier, type); - TIntermDeclaration *declaration = new TIntermDeclaration(); declaration->setLine(identifierOrTypeLocation); if (symbol) @@ -3554,8 +4784,9 @@ TIntermDeclaration *TParseContext::parseSingleArrayDeclaration( checkArrayOfArraysInOut(indexLocation, elementType, *arrayType); - checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType); - checkTessellationShaderUnsizedArraysAndSetSize(indexLocation, identifier, arrayType); + GeomTessArray sized = GeomTessArray::Sized; + checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType, &sized); + checkTessellationShaderUnsizedArraysAndSetSize(indexLocation, identifier, arrayType, &sized); checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType); checkDeclarationIsValidArraySize(identifierLocation, identifier, arrayType); @@ -3566,12 +4797,16 @@ TIntermDeclaration *TParseContext::parseSingleArrayDeclaration( } adjustRedeclaredBuiltInType(identifierLocation, identifier, arrayType); + if (sized == GeomTessArray::Sized) + { + arrayType->setTypeId(getTypeId(*arrayType)); + } TIntermDeclaration *declaration = new TIntermDeclaration(); declaration->setLine(identifierLocation); TVariable *variable = nullptr; - if (declareVariable(identifierLocation, identifier, arrayType, &variable)) + if (declareVariable(identifierLocation, identifier, arrayType, sized, &variable)) { TIntermSymbol *symbol = new TIntermSymbol(variable); symbol->setLine(identifierLocation); @@ -3711,6 +4946,18 @@ TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaratio TIntermSymbol *intermSymbol = new TIntermSymbol(variable); intermSymbol->setLine(identifierLoc); + mBuiltInQualified[type.getQualifier()] = true; + + const ir::VariableId id = declareBuiltInOnFirstUse(variable); + if (typeQualifier.invariant) + { + mIRBuilder.markVariableInvariant(id); + } + if (typeQualifier.precise) + { + mIRBuilder.markVariablePrecise(id); + } + return new TIntermGlobalQualifierDeclaration(intermSymbol, typeQualifier.precise, identifierLoc); } @@ -3732,8 +4979,9 @@ void TParseContext::parseDeclarator(TPublicType &publicType, TType *type = new TType(publicType); - checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type); - checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, type); + GeomTessArray sized = GeomTessArray::Sized; + checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type, &sized); + checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, type, &sized); checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type); checkDeclarationIsValidArraySize(identifierLocation, identifier, type); @@ -3744,9 +4992,13 @@ void TParseContext::parseDeclarator(TPublicType &publicType, } adjustRedeclaredBuiltInType(identifierLocation, identifier, type); + if (sized == GeomTessArray::Sized) + { + type->setTypeId(getTypeId(*type)); + } TVariable *variable = nullptr; - if (declareVariable(identifierLocation, identifier, type, &variable)) + if (declareVariable(identifierLocation, identifier, type, sized, &variable)) { TIntermSymbol *symbol = new TIntermSymbol(variable); symbol->setLine(identifierLocation); @@ -3776,8 +5028,10 @@ void TParseContext::parseArrayDeclarator(TPublicType &elementType, TType *arrayType = new TType(elementType); arrayType->makeArrays(arraySizes); - checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType); - checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, arrayType); + GeomTessArray sized = GeomTessArray::Sized; + checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType, &sized); + checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, arrayType, + &sized); checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType); checkDeclarationIsValidArraySize(identifierLocation, identifier, arrayType); @@ -3790,9 +5044,13 @@ void TParseContext::parseArrayDeclarator(TPublicType &elementType, } adjustRedeclaredBuiltInType(identifierLocation, identifier, arrayType); + if (sized == GeomTessArray::Sized) + { + arrayType->setTypeId(getTypeId(*arrayType)); + } TVariable *variable = nullptr; - if (declareVariable(identifierLocation, identifier, arrayType, &variable)) + if (declareVariable(identifierLocation, identifier, arrayType, sized, &variable)) { TIntermSymbol *symbol = new TIntermSymbol(variable); symbol->setLine(identifierLocation); @@ -3873,6 +5131,9 @@ TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location) // different type of node just for empty statements, that will be pruned from the AST anyway. TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium)); node->setLine(location); + // Because the node that is pushed has a value, appendStatement will expect to pop something + // from the stack. So push the same bogus value to the IR too. + mIRBuilder.pushConstantInt(0); return node; } @@ -3893,12 +5154,6 @@ void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision, const TPublicType &type, const TSourceLoc &loc) { - if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) && - !getFragmentPrecisionHigh()) - { - error(loc, "precision is not supported in fragment shader", "highp"); - } - if (!CanSetDefaultPrecisionOnType(type)) { error(loc, "illegal type argument for default precision qualifier", @@ -3934,7 +5189,7 @@ bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line) { - if (!symbolTable.setGlInArraySize(inputArraySize)) + if (!symbolTable.setGlInArraySize(inputArraySize, getShaderVersion())) { error(line, "Array size or input primitive declaration doesn't match the size of earlier sized " @@ -3969,9 +5224,15 @@ bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier if (mGeometryShaderInputPrimitiveType == EptUndefined) { mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType; - setGeometryShaderInputArraySize( - GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType), - typeQualifier.line); + const GLuint inputArraySize = + GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType); + + // Size any implicitly sized arrays that have already been declared. Done before + // verifying gl_in's array size, since that could also need to be sized. + sizeUnsizedArrayTypes(inputArraySize); + setGeometryShaderInputArraySize(inputArraySize, typeQualifier.line); + + mIRBuilder.setGsPrimitiveIn(mGeometryShaderInputPrimitiveType); } else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType) { @@ -3979,14 +5240,6 @@ bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier "layout"); return false; } - - // Size any implicitly sized arrays that have already been declared. - for (TType *type : mDeferredArrayTypesToSize) - { - type->sizeOutermostUnsizedArray( - symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize()); - } - mDeferredArrayTypesToSize.clear(); } // Set mGeometryInvocations if exists @@ -3995,6 +5248,7 @@ bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier if (mGeometryShaderInvocations == 0) { mGeometryShaderInvocations = layoutQualifier.invocations; + mIRBuilder.setGsInvocations(mGeometryShaderInvocations); } else if (mGeometryShaderInvocations != layoutQualifier.invocations) { @@ -4032,6 +5286,7 @@ bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifie if (mGeometryShaderOutputPrimitiveType == EptUndefined) { mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType; + mIRBuilder.setGsPrimitiveOut(mGeometryShaderOutputPrimitiveType); } else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType) { @@ -4047,6 +5302,7 @@ bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifie if (mGeometryShaderMaxVertices == -1) { mGeometryShaderMaxVertices = layoutQualifier.maxVertices; + mIRBuilder.setGsMaxVertices(mGeometryShaderMaxVertices); } else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices) { @@ -4075,13 +5331,10 @@ bool TParseContext::parseTessControlShaderOutputLayoutQualifier(const TTypeQuali if (mTessControlShaderOutputVertices == 0) { mTessControlShaderOutputVertices = layoutQualifier.vertices; + mIRBuilder.setTcsVertices(mTessControlShaderOutputVertices); // Size any implicitly sized arrays that have already been declared. - for (TType *type : mDeferredArrayTypesToSize) - { - type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices); - } - mDeferredArrayTypesToSize.clear(); + sizeUnsizedArrayTypes(mTessControlShaderOutputVertices); } else { @@ -4103,6 +5356,7 @@ bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier( if (mTessEvaluationShaderInputPrimitiveType == EtetUndefined) { mTessEvaluationShaderInputPrimitiveType = layoutQualifier.tesPrimitiveType; + mIRBuilder.setTesPrimitive(mTessEvaluationShaderInputPrimitiveType); } else { @@ -4115,6 +5369,7 @@ bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier( if (mTessEvaluationShaderInputVertexSpacingType == EtetUndefined) { mTessEvaluationShaderInputVertexSpacingType = layoutQualifier.tesVertexSpacingType; + mIRBuilder.setTesVertexSpacing(mTessEvaluationShaderInputVertexSpacingType); } else { @@ -4127,6 +5382,7 @@ bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier( if (mTessEvaluationShaderInputOrderingType == EtetUndefined) { mTessEvaluationShaderInputOrderingType = layoutQualifier.tesOrderingType; + mIRBuilder.setTesOrdering(mTessEvaluationShaderInputOrderingType); } else { @@ -4139,6 +5395,7 @@ bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier( if (mTessEvaluationShaderInputPointType == EtetUndefined) { mTessEvaluationShaderInputPointType = layoutQualifier.tesPointType; + mIRBuilder.setTesPointMode(mTessEvaluationShaderInputPointType); } else { @@ -4149,6 +5406,27 @@ bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier( return true; } +void TParseContext::sizeUnsizedArrayTypes(uint32_t arraySize) +{ + while (!mDeferredArrayTypesToSize.empty()) + { + TType *type = mDeferredArrayTypesToSize.back(); + + // Pop the type out of |mDeferredArrayTypesToSize| to satisfy an ASSERT in |getTypeId| that + // the type declaration is not deferred! + mDeferredArrayTypesToSize.pop_back(); + + type->sizeOutermostUnsizedArray(arraySize); + type->setTypeId(getTypeId(*type)); + } + + for (const TVariable *variable : mDeferredArrayVariablesToSize) + { + declareIRVariable(variable, GeomTessArray::Sized); + } + mDeferredArrayVariablesToSize.clear(); +} + void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) { TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); @@ -4290,7 +5568,7 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type return; } - if (layoutQualifier.numViews > mMaxNumViews) + if (layoutQualifier.numViews > mResources.MaxViewsOVR) { error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR", "layout"); @@ -4320,6 +5598,7 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type } mEarlyFragmentTestsSpecified = true; + mIRBuilder.setEarlyFragmentTests(mEarlyFragmentTestsSpecified); } else if (typeQualifier.qualifier == EvqFragmentOut) { @@ -4482,6 +5761,8 @@ TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration( error(location, "local function prototype declarations are not allowed", "function"); } + // Declare the function to the IR. It's body is not yet specified. + declareFunction(function, FunctionDeclaration::Prototype); return prototype; } @@ -4490,6 +5771,8 @@ TIntermFunctionDefinition *TParseContext::addFunctionDefinition( TIntermBlock *functionBody, const TSourceLoc &location) { + ASSERT(functionPrototype->getFunction() == mCurrentFunction); + // Undo push at end of parseFunctionDefinitionHeader() below for ESSL1.00 case if (mFunctionBodyNewScope) { @@ -4498,10 +5781,21 @@ TIntermFunctionDefinition *TParseContext::addFunctionDefinition( } // Check that non-void functions have at least one return statement. - if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue) + if (mCurrentFunction->getReturnType().getBasicType() != EbtVoid && !mFunctionReturnsValue) { - error(location, - "function does not return a value:", functionPrototype->getFunction()->name()); + error(location, "Function does not return a value", mCurrentFunction->name()); + } + if (mCompileOptions.limitExpressionComplexity && + mCurrentFunction->getParamCount() > + static_cast(mResources.MaxFunctionParameters)) + { + error(location, "Function has too many parameters", mCurrentFunction->name()); + } + + for (size_t paramIndex = 0; paramIndex < mCurrentFunction->getParamCount(); ++paramIndex) + { + const TVariable *param = mCurrentFunction->getParam(paramIndex); + checkVariableSize(functionPrototype->getLine(), param->name(), ¶m->getType()); } if (functionBody == nullptr) @@ -4513,6 +5807,14 @@ TIntermFunctionDefinition *TParseContext::addFunctionDefinition( new TIntermFunctionDefinition(functionPrototype, functionBody); functionNode->setLine(location); + if (mDeclaringMain) + { + mMainFunction = mCurrentFunction; + } + mCurrentFunction = nullptr; + + mIRBuilder.endFunction(); + symbolTable.pop(); return functionNode; } @@ -4531,11 +5833,13 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, } // Remember the return type for later checking for return statements. - mCurrentFunctionType = &(function->getReturnType()); + mCurrentFunction = function; mFunctionReturnsValue = false; + // The function is about to be defined + mDefinedFunctions.insert(function); *prototypeOut = createPrototypeNodeFromFunction(*function, location, true); - setLoopNestingLevel(0); + ASSERT(mControlFlow.empty()); // ESSL 1.00 spec allows for variable in function body to redefine parameter if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion)) @@ -4543,6 +5847,11 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, mFunctionBodyNewScope = true; symbolTable.push(); } + + // If the function prototype hasn't been previously encountered, this is a new function that + // should be declared to the IR first. + declareFunction(function, FunctionDeclaration::Definition); + mIRBuilder.beginFunction(mFunctionToId.at(function)); } TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function) @@ -4638,6 +5947,7 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF } mDeclaringMain = function->isMain(); + mIsReturnVisitedInMain = false; // // If this is a redeclaration, it could also be a definition, in which case, we want to use the @@ -4845,6 +6155,8 @@ TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSour return CreateZeroNode(type); } + mIRBuilder.construct(getTypeId(type), arguments.size()); + TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments); constructorNode->setLine(line); @@ -4926,10 +6238,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( // Both inputs and outputs of tessellation control shaders must be arrays. // For tessellation evaluation shaders, only inputs must necessarily be arrays. + // Inputs of geometry shaders must be arrays too. const bool isTCS = mShaderType == GL_TESS_CONTROL_SHADER; const bool isTESIn = mShaderType == GL_TESS_EVALUATION_SHADER && IsShaderIn(typeQualifier.qualifier); - if (arraySizes == nullptr && (isTCS || isTESIn)) + const bool isGSIn = + mShaderType == GL_GEOMETRY_SHADER && IsShaderIn(typeQualifier.qualifier); + if (arraySizes == nullptr && (isTCS || isTESIn || isGSIn)) { error(typeQualifier.line, "type must be an array", blockName); } @@ -5186,12 +6501,46 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7 fieldType->setMemoryQualifier(fieldMemoryQualifier); } + + // For per-vertex members, apply the appropriate built-in qualifiers to the members. + if (isGLPerVertex) + { + if (field->name() == "gl_Position") + { + fieldType->setQualifier(EvqPosition); + } + if (field->name() == "gl_PointSize") + { + fieldType->setQualifier(EvqPointSize); + } + if (field->name() == "gl_ClipDistance") + { + fieldType->setQualifier(EvqClipDistance); + } + if (field->name() == "gl_CullDistance") + { + fieldType->setQualifier(EvqCullDistance); + } + } } SymbolType instanceSymbolType = SymbolType::UserDefined; if (isGLPerVertex) { - instanceSymbolType = SymbolType::BuiltIn; + // Mark gl_PerVertex as built-in if usage is not erroneous. If it is, there will be failure + // elsewhere that validates gl_PerVertex cannot be used when not a built-in. + if (IsVaryingOut(typeQualifier.qualifier) && mShaderType != GL_FRAGMENT_SHADER && + mShaderType != GL_COMPUTE_SHADER) + { + instanceSymbolType = SymbolType::BuiltIn; + typeQualifier.qualifier = EvqPerVertexOut; + } + else if (IsVaryingIn(typeQualifier.qualifier) && mShaderType != GL_VERTEX_SHADER && + mShaderType != GL_FRAGMENT_SHADER && mShaderType != GL_COMPUTE_SHADER) + { + instanceSymbolType = SymbolType::BuiltIn; + typeQualifier.qualifier = EvqPerVertexIn; + } } TInterfaceBlock *interfaceBlock = new TInterfaceBlock(&symbolTable, blockName, fieldList, blockLayoutQualifier, instanceSymbolType); @@ -5200,26 +6549,79 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( error(nameLine, "redefinition of an interface block name", blockName); } + GeomTessArray sized = GeomTessArray::Sized; TType *interfaceBlockType = new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier); if (arraySizes) { interfaceBlockType->makeArrays(*arraySizes); - checkGeometryShaderInputAndSetArraySize(instanceLine, instanceName, interfaceBlockType); - checkTessellationShaderUnsizedArraysAndSetSize(instanceLine, instanceName, - interfaceBlockType); checkDeclarationIsValidArraySize(instanceLine, instanceName, interfaceBlockType); } + checkGeometryShaderInputAndSetArraySize(instanceLine, instanceName, interfaceBlockType, &sized); + checkTessellationShaderUnsizedArraysAndSetSize(instanceLine, instanceName, interfaceBlockType, + &sized); + + // If this is gl_PerVertex, make sure the instance name is as expected. + if (interfaceBlockType->getQualifier() == EvqPerVertexOut) + { + switch (mShaderType) + { + case GL_VERTEX_SHADER: + case GL_TESS_EVALUATION_SHADER_EXT: + case GL_GEOMETRY_SHADER_EXT: + if (!instanceName.empty()) + { + error(instanceLine, + "out gl_PerVertex instance name must be empty in this shader", + instanceName); + instanceSymbolType = SymbolType::UserDefined; + } + break; + case GL_TESS_CONTROL_SHADER_EXT: + if (instanceName != "gl_out") + { + error(instanceLine, + "out gl_PerVertex instance name must be gl_out in this shader", + instanceName); + instanceSymbolType = SymbolType::UserDefined; + } + break; + default: + UNREACHABLE(); + break; + } + } + else if (interfaceBlockType->getQualifier() == EvqPerVertexIn) + { + if (instanceName != "gl_in") + { + error(instanceLine, "in gl_PerVertex instance name must be gl_in", instanceName); + instanceSymbolType = SymbolType::UserDefined; + } + } + + if (sized == GeomTessArray::Sized) + { + interfaceBlockType->setTypeId(getTypeId(*interfaceBlockType)); + } // The instance variable gets created to refer to the interface block type from the AST // regardless of if there's an instance name. It's created as an empty symbol if there is no // instance name. TVariable *instanceVariable = new TVariable(&symbolTable, instanceName, interfaceBlockType, - instanceName.empty() ? SymbolType::Empty : SymbolType::UserDefined); + instanceName.empty() ? SymbolType::Empty : instanceSymbolType); + + checkVariableLocations(nameLine, instanceVariable); + declareIRVariable(instanceVariable, sized); if (instanceVariable->symbolType() == SymbolType::Empty) { + // Cannot have an array variable that is yet to be sized but which also has no name (because + // there is no way to specify arrayness with [] without a name). + ASSERT(sized == GeomTessArray::Sized); + const ir::VariableId instanceId = mVariableToId.at(instanceVariable).id; + // define symbols for the members of the interface block for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) { @@ -5237,7 +6639,8 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( { // These builtins can be redefined only when used within a redefined gl_PerVertex // block - if (interfaceBlock->name() != "gl_PerVertex") + if (interfaceBlockType->getQualifier() != EvqPerVertexIn && + interfaceBlockType->getQualifier() != EvqPerVertexOut) { error(field->line(), "redefinition in an invalid interface block", field->name()); @@ -5251,11 +6654,29 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( error(field->line(), "redefinition of an interface block member name", field->name()); } + + // Don't declare variables for fields of nameless interface blocks in the IR, just + // remember to implicitly index the instance variable when referenced. + mVariableToId[fieldVariable] = + VariableToIdInfo{instanceId, static_cast(memberIndex)}; } } else { - checkIsNotReserved(instanceLine, instanceName); + // gl_in and gl_out are allowed to be redeclared + bool isGlIn = + interfaceBlockType->getQualifier() == EvqPerVertexIn && instanceName == "gl_in"; + bool isGlOut = interfaceBlockType->getQualifier() == EvqPerVertexOut && + instanceName == "gl_out" && mShaderType == GL_TESS_CONTROL_SHADER_EXT; + + if (!isGlIn && !isGlOut) + { + checkIsNotReserved(instanceLine, instanceName); + } + else if (isGlIn) + { + symbolTable.onGlInVariableRedeclaration(instanceVariable); + } // add a symbol for this interface block if (!symbolTable.declare(instanceVariable)) @@ -5348,14 +6769,24 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); } - if (baseExpression->getQualifier() == EvqPerVertexIn) + switch (baseExpression->getQualifier()) { - if (mGeometryShaderInputPrimitiveType == EptUndefined && - mShaderType == GL_GEOMETRY_SHADER_EXT) - { - error(location, "missing input primitive declaration before indexing gl_in.", "["); - return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - } + case EvqPerVertexIn: + if (mGeometryShaderInputPrimitiveType == EptUndefined && + mShaderType == GL_GEOMETRY_SHADER_EXT) + { + error(location, "missing input primitive declaration before indexing gl_in.", "["); + return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); + } + break; + case EvqClipDistance: + MarkClipCullIndex(location, indexExpression, &mClipDistanceInfo); + break; + case EvqCullDistance: + MarkClipCullIndex(location, indexExpression, &mCullDistanceInfo); + break; + default: + break; } TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); @@ -5452,29 +6883,55 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, } } - if (indexConstantUnion) + int index = 0; + bool outOfRangeIndexIsError = false; + + // If the index is using the comma operator, descend to the right-most value, see if that's a + // constant. This is used for validating the index only, we can't constant fold the expression + // due to the left-hand-side of the comma. + TIntermTyped *commaRHS = indexExpression; + while (true) { - // If an out-of-range index is not qualified as constant, the behavior in the spec is - // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may - // constant fold expressions that are not constant expressions). The most compatible way to - // handle this case is to report a warning instead of an error and force the index to be in - // the correct range. - bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst; - int index = 0; - if (indexConstantUnion->getBasicType() == EbtInt) + TIntermConstantUnion *constant = commaRHS->getAsConstantUnion(); + if (constant) { - index = indexConstantUnion->getIConst(0); + // If an out-of-range index is not qualified as constant, the behavior in the spec is + // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may + // constant fold expressions that are not constant expressions). The most compatible way + // to handle this case is to report a warning instead of an error and force the index to + // be in the correct range. + outOfRangeIndexIsError = commaRHS->getQualifier() == EvqConst; + index = 0; + if (constant->getBasicType() == EbtInt) + { + index = constant->getIConst(0); + } + else if (constant->getBasicType() == EbtUInt) + { + index = static_cast(constant->getUConst(0)); + } + + if (index < 0) + { + outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", + "[]"); + } + break; } - else if (indexConstantUnion->getBasicType() == EbtUInt) + + TIntermBinary *asBinary = commaRHS->getAsBinaryNode(); + if (asBinary == nullptr || asBinary->getOp() != EOpComma) { - index = static_cast(indexConstantUnion->getUConst(0)); + break; } + commaRHS = asBinary->getRight(); + } + if (indexConstantUnion) + { int safeIndex = -1; - if (index < 0) { - outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]"); safeIndex = 0; } @@ -5533,11 +6990,36 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, TIntermBinary *node = new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression); node->setLine(location); + + if (baseExpression->isVector() && !baseExpression->isArray()) + { + const uint32_t irIndex = mIRBuilder.popArraySize(); +#ifdef ANGLE_IR + ASSERT(!mCompileOptions.useIR || mDiagnostics->numErrors() > 0 || + irIndex == static_cast(index)); +#endif + mIRBuilder.vectorComponent(irIndex); + } + else + { + mIRBuilder.index(); + } + return expressionOrFoldedResult(node); } } - markStaticReadIfSymbol(indexExpression); + // According to ESSL 100 spec, Appendix A, the index expression must be a + // constant-index-expression unless the operand is a uniform in a vertex shader. + if (mValidateESSL100Limitations && + !(mShaderType == GL_VERTEX_SHADER && baseExpression->getQualifier() == EvqUniform)) + { + checkESSL100ConstantIndex(indexExpression, location); + } + + mIRBuilder.index(); + + markStaticUseIfSymbol(indexExpression); TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression); node->setLine(location); // Indirect indexing can never be constant folded. @@ -5576,13 +7058,23 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre if (baseExpression->isVector()) { - TVector fieldOffsets; + TVector fieldOffsets; if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(), &fieldOffsets)) { fieldOffsets.resize(1); fieldOffsets[0] = 0; } + + if (fieldOffsets.size() == 1) + { + mIRBuilder.vectorComponent(fieldOffsets[0]); + } + else + { + mIRBuilder.vectorComponentMulti(angle::Span(fieldOffsets.data(), fieldOffsets.size())); + } + TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets); node->setLine(dotLocation); @@ -5610,6 +7102,8 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre } if (fieldFound) { + mIRBuilder.structField(i); + TIntermTyped *index = CreateIndexNode(i); index->setLine(fieldLocation); TIntermBinary *node = @@ -5646,6 +7140,8 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre } if (fieldFound) { + mIRBuilder.structField(i); + TIntermTyped *index = CreateIndexNode(i); index->setLine(fieldLocation); TIntermBinary *node = @@ -5785,7 +7281,10 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qual } else if (qualifierType == "r32i") { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } qualifier.imageInternalFormat = EiifR32I; } else if (qualifierType == "rgba32ui") @@ -5909,10 +7408,10 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qual if (qualifierType == "noncoherent") { if (checkCanUseOneOfExtensions( - qualifierTypeLine, - std::array{ - {TExtension::EXT_shader_framebuffer_fetch, - TExtension::EXT_shader_framebuffer_fetch_non_coherent}})) + qualifierTypeLine, std::array{ + {TExtension::EXT_shader_framebuffer_fetch, + TExtension::EXT_shader_framebuffer_fetch_non_coherent, + TExtension::ANGLE_shader_pixel_local_storage}})) { checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100); qualifier.noncoherent = true; @@ -6059,7 +7558,7 @@ void TParseContext::parseInvocations(int intValue, { // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because // it doesn't make sense to accept invocations <= 0. - if (intValue < 1 || intValue > mMaxGeometryShaderInvocations) + if (intValue < 1 || intValue > mResources.MaxGeometryShaderInvocations) { error(intValueLine, "out of range: invocations must be in the range of [1, " @@ -6079,7 +7578,7 @@ void TParseContext::parseMaxVertices(int intValue, { // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because // it doesn't make sense to accept max_vertices < 0. - if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices) + if (intValue < 0 || intValue > mResources.MaxGeometryOutputVertices) { error( intValueLine, @@ -6097,7 +7596,7 @@ void TParseContext::parseVertices(int intValue, const std::string &intValueString, int *vertices) { - if (intValue < 1 || intValue > mMaxPatchVertices) + if (intValue < 1 || intValue > mResources.MaxPatchVertices) { error(intValueLine, "out of range : vertices must be in the range of [1, gl_MaxPatchVertices]", @@ -6504,12 +8003,14 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif for (const TDeclarator *declarator : *declaratorList) { TType *type = new TType(typeSpecifier); + if (declarator->isArray()) { // Don't allow arrays of arrays in ESSL < 3.10. checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier); type->makeArrays(*declarator->arraySizes()); } + type->setTypeId(getTypeId(*type)); SymbolType symbolType = SymbolType::UserDefined; if (declarator->name() == "gl_Position" || declarator->name() == "gl_PointSize" || @@ -6541,18 +8042,18 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, } // To simplify pulling samplers out of structs, reorder the struct fields to put the samplers at - // the end. + // the end. Structures that *only* contain samplers are also put last. TFieldList *reorderedFields = new TFieldList; for (TField *field : *fieldList) { - if (!IsSampler(field->type()->getBasicType())) + if (!IsSamplerOrStructWithOnlySamplers(field->type())) { reorderedFields->push_back(field); } } for (TField *field : *fieldList) { - if (IsSampler(field->type()->getBasicType())) + if (IsSamplerOrStructWithOnlySamplers(field->type())) { reorderedFields->push_back(field); } @@ -6638,6 +8139,11 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier()); } + mSymbolToTypeId[structure] = mIRBuilder.getStructTypeId( + structure->symbolType() == SymbolType::Empty ? kEmptyImmutableString : structure->name(), + angle::Span(reorderedFields->data(), reorderedFields->size()), {}, + false, false, symbolTable.atGlobalLevel()); + TTypeSpecifierNonArray typeSpecifierNonArray; typeSpecifierNonArray.initializeStruct(structure, true, structLine); exitStructDeclaration(); @@ -6645,10 +8151,27 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, return typeSpecifierNonArray; } +void TParseContext::beginSwitch(const TSourceLoc &line, TIntermTyped *init) +{ + ControlFlow flow = {}; + flow.type = ControlFlowType::Switch; + flow.switchType = init->getBasicType(); + mControlFlow.push_back(flow); + + symbolTable.push(); + + checkNestingLevel(line); + + mIRBuilder.beginSwitch(); +} + TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermBlock *statementList, const TSourceLoc &loc) { + symbolTable.pop(); + popControlFlow(); + TBasicType switchType = init->getBasicType(); if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() || init->isVector()) @@ -6659,25 +8182,70 @@ TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, } ASSERT(statementList); - if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc)) + + // There have been some differences between versions of GLSL ES specs on whether this should + // be an error or not, but this was clarified as an error in GLSL ES versions newer than 3.00 + // too. + const size_t statementCount = statementList->getChildCount(); + if (statementCount > 0 && + statementList->getChildNode(statementCount - 1)->getAsCaseNode() != nullptr) { - ASSERT(mDiagnostics->numErrors() > 0); + error(loc, "no statement between the last case label and the end of the switch statement", + "switch"); return nullptr; } - markStaticReadIfSymbol(init); + mIRBuilder.endSwitch(); + + markStaticUseIfSymbol(init); TIntermSwitch *node = new TIntermSwitch(init, statementList); node->setLine(loc); return node; } -TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) +bool TParseContext::isNestedIn(ControlFlowType type) const { - if (mSwitchNestingLevel == 0) + // Used for validation, we need to know for example that a `continue` statement is nested + // within a loop, etc. Search backwards in the nested control flow info to find the closest + // control flow of given type. + for (auto iter = mControlFlow.rbegin(); iter != mControlFlow.rend(); ++iter) { - error(loc, "case labels need to be inside switch statements", "case"); - return nullptr; + if (iter->type == type) + { + return true; + } + } + return false; +} + +bool TParseContext::isDirectlyUnderSwitch() const +{ + return mControlFlow.size() > 0 && mControlFlow.back().type == ControlFlowType::Switch; +} + +bool TParseContext::checkCase(const TSourceLoc &line, int64_t caseValue, const char *caseOrDefault) +{ + if (!isDirectlyUnderSwitch()) + { + error(line, "case and default labels need to be inside switch statements", caseOrDefault); + return false; + } + for (int64_t existingCaseLabel : mControlFlow.back().caseLabels) + { + if (caseValue == existingCaseLabel) + { + error(line, "duplicate case label", caseOrDefault); + return false; + } } + + mControlFlow.back().caseLabels.push_back(caseValue); + + return true; +} + +TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) +{ if (condition == nullptr) { error(loc, "case label must have a condition", "case"); @@ -6687,6 +8255,7 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l condition->isMatrix() || condition->isArray() || condition->isVector()) { error(condition->getLine(), "case label must be a scalar integer", "case"); + return nullptr; } TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be @@ -6696,7 +8265,24 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l if (condition->getQualifier() != EvqConst || conditionConst == nullptr) { error(condition->getLine(), "case label must be constant", "case"); + return nullptr; + } + + const int64_t caseValue = condition->getBasicType() == EbtInt + ? static_cast(conditionConst->getIConst(0)) + : static_cast(conditionConst->getUConst(0)); + if (!checkCase(loc, caseValue, "case")) + { + return nullptr; + } + + if (condition->getBasicType() != mControlFlow.back().switchType) + { + error(loc, "case label type does not match switch init-expression type", "case"); } + + mIRBuilder.beginCase(); + TIntermCase *node = new TIntermCase(condition); node->setLine(loc); return node; @@ -6704,11 +8290,13 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) { - if (mSwitchNestingLevel == 0) + if (!checkCase(loc, ControlFlow::kDefaultCaseLabel, "default")) { - error(loc, "default labels need to be inside switch statements", "default"); return nullptr; } + + mIRBuilder.beginDefault(); + TIntermCase *node = new TIntermCase(nullptr); node->setLine(loc); return node; @@ -6766,7 +8354,9 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, return nullptr; } - markStaticReadIfSymbol(child); + mIRBuilder.builtIn(op, 1); + + markStaticUseIfSymbol(child); TIntermUnary *node = new TIntermUnary(op, child, func); node->setLine(loc); @@ -7019,6 +8609,11 @@ bool TParseContext::binaryOpCommonCheck(TOperator op, error(loc, "comparison operator only defined for scalars", GetOperatorString(op)); return false; } + if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool) + { + error(loc, "comparison operator not defined for booleans", GetOperatorString(op)); + return false; + } break; case EOpAdd: case EOpSub: @@ -7176,10 +8771,23 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, } } + switch (op) + { + case EOpLogicalAnd: + mIRBuilder.endShortCircuitAnd(); + break; + case EOpLogicalOr: + mIRBuilder.endShortCircuitOr(); + break; + default: + mIRBuilder.builtIn(op, 2); + break; + } + TIntermBinary *node = new TIntermBinary(op, left, right); ASSERT(op != EOpAssign); - markStaticReadIfSymbol(left); - markStaticReadIfSymbol(right); + markStaticUseIfSymbol(left); + markStaticUseIfSymbol(right); node->setLine(loc); return expressionOrFoldedResult(node); } @@ -7248,15 +8856,46 @@ TIntermTyped *TParseContext::addAssign(TOperator op, assignError(loc, "assign", left->getType(), right->getType()); return left; } + if (op != EOpAssign) { - markStaticReadIfSymbol(left); + markStaticUseIfSymbol(left); } - markStaticReadIfSymbol(right); + mIRBuilder.builtIn(op, 2); + + markStaticUseIfSymbol(right); node->setLine(loc); return node; } +void TParseContext::onShortCircuitAndBegin(TIntermTyped *left, const TSourceLoc &loc) +{ + if (!left->isScalar() || left->getBasicType() != EbtBool) + { + error(loc, "Left hand side of && must be a scalar bool", GetOperatorString(EOpLogicalAnd)); + } + mIRBuilder.beginShortCircuitAnd(); +} + +void TParseContext::onShortCircuitOrBegin(TIntermTyped *left, const TSourceLoc &loc) +{ + if (!left->isScalar() || left->getBasicType() != EbtBool) + { + error(loc, "Left hand side of || must be a scalar bool", GetOperatorString(EOpLogicalOr)); + } + mIRBuilder.beginShortCircuitOr(); +} + +void TParseContext::onCommaLeftHandSideParsed(TIntermTyped *left) +{ + if (left->getBasicType() != EbtVoid) + { + // The left-hand side's value is discarded, do so before the right-hand side is parsed (and + // pushed to the stack). + mIRBuilder.endStatementWithValue(); + } +} + TIntermTyped *TParseContext::addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc) @@ -7278,8 +8917,8 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left, } TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion); - markStaticReadIfSymbol(left); - markStaticReadIfSymbol(right); + markStaticUseIfSymbol(left); + markStaticUseIfSymbol(right); commaNode->setLine(loc); return expressionOrFoldedResult(commaNode); @@ -7290,26 +8929,38 @@ TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) switch (op) { case EOpContinue: - if (mLoopNestingLevel <= 0) + if (!isNestedIn(ControlFlowType::Loop)) { error(loc, "continue statement only allowed in loops", ""); } + mIRBuilder.branchContinue(); break; case EOpBreak: - if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0) + if (!isNestedIn(ControlFlowType::Loop) && !isNestedIn(ControlFlowType::Switch)) { error(loc, "break statement only allowed in loops and switch statements", ""); } + else + { + mControlFlow.back().hasBreak = true; + } + mIRBuilder.branchBreak(); break; case EOpReturn: - if (mCurrentFunctionType->getBasicType() != EbtVoid) + if (mCurrentFunction->getReturnType().getBasicType() != EbtVoid) { error(loc, "non-void function must return a value", "return"); } if (mDeclaringMain) { errorIfPLSDeclared(loc, PLSIllegalOperations::ReturnFromMain); + mIsReturnVisitedInMain = true; + } + if (!mControlFlow.empty()) + { + mControlFlow.back().hasReturn = true; } + mIRBuilder.branchReturn(); break; case EOpKill: if (mShaderType != GL_FRAGMENT_SHADER) @@ -7321,6 +8972,7 @@ TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) errorIfPLSDeclared(loc, PLSIllegalOperations::Discard); } mHasDiscard = true; + mIRBuilder.branchDiscard(); break; default: UNREACHABLE(); @@ -7335,17 +8987,22 @@ TIntermBranch *TParseContext::addBranch(TOperator op, { if (expression != nullptr) { - markStaticReadIfSymbol(expression); + markStaticUseIfSymbol(expression); ASSERT(op == EOpReturn); mFunctionReturnsValue = true; - if (mCurrentFunctionType->getBasicType() == EbtVoid) + if (mCurrentFunction->getReturnType().getBasicType() == EbtVoid) { error(loc, "void function cannot return a value", "return"); } - else if (*mCurrentFunctionType != expression->getType()) + else if (mCurrentFunction->getReturnType() != expression->getType()) { error(loc, "function return is not matching type:", "return"); } + if (!mControlFlow.empty()) + { + mControlFlow.back().hasReturn = true; + } + mIRBuilder.branchReturnValue(); } TIntermBranch *node = new TIntermBranch(op, expression); node->setLine(loc); @@ -7356,8 +9013,18 @@ void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement) { if (statement != nullptr) { - markStaticReadIfSymbol(statement); + // Validate that no statement is added before the first case label of a switch construct. + if (statement->getAsCaseNode() == nullptr && isDirectlyUnderSwitch() && + mControlFlow.back().caseLabels.empty()) + { + error(statement->getLine(), "statement before the first label", "switch"); + } + + markStaticUseIfSymbol(statement); block->appendStatement(statement); + + // Discard the value, if any. + endStatementWithValue(statement); } } @@ -7439,7 +9106,9 @@ void TParseContext::checkTextureOffset(TIntermAggregate *functionCall) TIntermSequence *arguments = functionCall->getSequence(); if (BuiltInGroup::IsTextureOffsetNoBias(op) || BuiltInGroup::IsTextureGatherOffsetNoComp(op) || - BuiltInGroup::IsTextureGatherOffsetsNoComp(op)) + BuiltInGroup::IsTextureGatherOffsetRef(op) || + BuiltInGroup::IsTextureGatherOffsetsNoComp(op) || + BuiltInGroup::IsTextureGatherOffsetsRef(op)) { offset = arguments->back(); } @@ -7461,10 +9130,12 @@ void TParseContext::checkTextureOffset(TIntermAggregate *functionCall) bool isTextureGatherOffsets = BuiltInGroup::IsTextureGatherOffsets(op); bool useTextureGatherOffsetConstraints = isTextureGatherOffset || isTextureGatherOffsets; - int minOffsetValue = - useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset : mMinProgramTexelOffset; - int maxOffsetValue = - useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset : mMaxProgramTexelOffset; + int minOffsetValue = useTextureGatherOffsetConstraints + ? mResources.MinProgramTextureGatherOffset + : mResources.MinProgramTexelOffset; + int maxOffsetValue = useTextureGatherOffsetConstraints + ? mResources.MaxProgramTextureGatherOffset + : mResources.MaxProgramTexelOffset; if (isTextureGatherOffsets) { @@ -7772,8 +9443,22 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc } else { + switch (thisNode->getQualifier()) + { + case EvqClipDistance: + MarkClipCullArrayLengthMethodCall(loc, &mClipDistanceInfo); + break; + case EvqCullDistance: + MarkClipCullArrayLengthMethodCall(loc, &mCullDistanceInfo); + break; + default: + break; + } + + mIRBuilder.arrayLength(); + TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr); - markStaticReadIfSymbol(thisNode); + markStaticUseIfSymbol(thisNode); node->setLine(loc); return node->fold(mDiagnostics); } @@ -7806,6 +9491,9 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCallImpl(TFunctionLookup * callNode->setLine(loc); checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode); functionCallRValueLValueErrorCheck(fnCandidate, callNode); + + mCallGraph[mCurrentFunction].insert(fnCandidate); + mIRBuilder.callFunction(mFunctionToId.at(fnCandidate)); return callNode; } @@ -7823,6 +9511,30 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCallImpl(TFunctionLookup * checkCanUseOneOfExtensions(loc, fnCandidate->extensions()); } + // From GLES 3.2: + // + // For tessellation control shaders, the barrier() function may only be placed inside + // the function main() of the shader and may not be called within any control flow. + // Barriers are also disallowed after a return statement in the function main(). + if (fnCandidate->getBuiltInOp() == EOpBarrierTCS) + { + if (mIsReturnVisitedInMain) + { + error(loc, + "barrier() may not be called at any point after a return statement in " + "the function main()", + "barrier"); + } + else if (!mDeclaringMain) + { + error(loc, "barrier() is only allowed inside the function main()", "barrier"); + } + else if (!mControlFlow.empty()) + { + error(loc, "barrier() is not allowed within any control flow", "barrier"); + } + } + // All function calls are mapped to a built-in operation. TOperator op = fnCandidate->getBuiltInOp(); if (BuiltInGroup::IsMath(op) && fnCandidate->getParamCount() == 1) @@ -7850,6 +9562,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCallImpl(TFunctionLookup * // Some built-in functions have out parameters too. functionCallRValueLValueErrorCheck(fnCandidate, callNode); + mIRBuilder.builtIn(op, fnCandidate->getParamCount()); + // See if we can constant fold a built-in. Note that this may be possible // even if it is not const-qualified. return callNode->fold(mDiagnostics); @@ -7874,6 +9588,19 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst)); } +void TParseContext::onTernaryConditionParsed(TIntermTyped *cond, const TSourceLoc &line) +{ + checkIsScalarBool(line, cond); + mIRBuilder.beginTernaryTrueExpression(); +} + +void TParseContext::onTernaryTrueExpressionParsed(TIntermTyped *trueExpression, + const TSourceLoc &line) +{ + mIRBuilder.endTernaryTrueExpression(trueExpression->getBasicType()); + mIRBuilder.beginTernaryFalseExpression(); +} + TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression, @@ -7892,13 +9619,13 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, error(loc, reasonStream.c_str(), "?:"); return falseExpression; } - if (IsOpaqueType(trueExpression->getBasicType())) + const TBasicType basicType = trueExpression->getBasicType(); + if (IsOpaqueType(basicType) || trueExpression->getType().isStructureContainingSamplers()) { // ESSL 1.00 section 4.1.7 // ESSL 3.00.6 section 4.1.7 - // Opaque/sampler types are not allowed in most types of expressions, including ternary. - // Note that structs containing opaque types don't need to be checked as structs are - // forbidden below. + // Opaque/sampler types are not allowed in the ternary operator, including structs with + // samplers in them. error(loc, "ternary operator is not allowed for opaque types", "?:"); return falseExpression; } @@ -7922,13 +9649,12 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, error(loc, "ternary operator is not allowed for arrays in ESSL 1.0 and webgl", "?:"); return falseExpression; } - if ((mShaderVersion < 300 || mShaderSpec == SH_WEBGL2_SPEC) && - trueExpression->getBasicType() == EbtStruct) + if ((mShaderVersion < 300 || mShaderSpec == SH_WEBGL2_SPEC) && basicType == EbtStruct) { error(loc, "ternary operator is not allowed for structures in ESSL 1.0 and webgl", "?:"); return falseExpression; } - if (trueExpression->getBasicType() == EbtInterfaceBlock) + if (basicType == EbtInterfaceBlock) { error(loc, "ternary operator is not allowed for interface blocks", "?:"); return falseExpression; @@ -7936,37 +9662,587 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, // WebGL2 section 5.26, the following results in an error: // "Ternary operator applied to void, arrays, or structs containing arrays" - if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid) + if (mShaderSpec == SH_WEBGL2_SPEC && basicType == EbtVoid) { error(loc, "ternary operator is not allowed for void", "?:"); return falseExpression; } + mIRBuilder.endTernaryFalseExpression(basicType); + mIRBuilder.endTernary(basicType); + TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression); - markStaticReadIfSymbol(cond); - markStaticReadIfSymbol(trueExpression); - markStaticReadIfSymbol(falseExpression); + markStaticUseIfSymbol(cond); + markStaticUseIfSymbol(trueExpression); + markStaticUseIfSymbol(falseExpression); node->setLine(loc); return expressionOrFoldedResult(node); } +ir::TypeId TParseContext::getTypeId(const TType &type) +{ + if (type.isTypeIdSet()) + { + return type.typeId(); + } + + // Normally, type ids are generated at the same time as types are, except for built-ins where + // the type is baked in. For now, calculate the type ID. + const TSymbol *block = nullptr; + const TFieldList *fields = nullptr; + ir::TypeId id; + if (type.getStruct()) + { + block = type.getStruct(); + fields = &type.getStruct()->fields(); + } + else if (type.getInterfaceBlock()) + { + block = type.getInterfaceBlock(); + fields = &type.getInterfaceBlock()->fields(); + } + + if (block) + { + if (mSymbolToTypeId.find(block) != mSymbolToTypeId.end()) + { + id = mSymbolToTypeId.at(block); + } + else + { + TVector fieldTypeIds; + for (const TField *field : *fields) + { + fieldTypeIds.push_back(getTypeId(*field->type())); + } + + // Same issue with built-ins where the type id is not baked in. So the type id of each + // field is also calculated here and passed in. + id = mIRBuilder.getStructTypeId( + block->symbolType() == SymbolType::Empty ? kEmptyImmutableString : block->name(), + angle::Span(fields->data(), fields->size()), + angle::Span(fieldTypeIds.data(), fieldTypeIds.size()), + block->isInterfaceBlock(), block->symbolType() == SymbolType::BuiltIn, true); + mSymbolToTypeId[block] = id; + } + } + else + { + id = mIRBuilder.getBasicTypeId(type.getBasicType(), type.getNominalSize(), + type.getSecondarySize()); + } + + if (type.isArray()) + { + // Make sure array types that are yet to be sized are not added to the IR yet. + ASSERT(std::find(mDeferredArrayTypesToSize.begin(), mDeferredArrayTypesToSize.end(), + &type) == mDeferredArrayTypesToSize.end()); + id = mIRBuilder.getArrayTypeId(id, type.getArraySizes()); + } + + return id; +} + +void TParseContext::pushVariable(const TVariable *variable) +{ + if (mDiagnostics->numErrors() > 0) + { + return; + } + + const VariableToIdInfo &info = mVariableToId.at(variable); + mIRBuilder.pushVariable(info.id); + if (info.implicitField != VariableToIdInfo::kNoImplicitField) + { + mIRBuilder.structField(info.implicitField); + } +} + +const TConstantUnion *TParseContext::pushConstant(const TConstantUnion *constant, const TType &type) +{ + const ir::TypeId typeId = getTypeId(type); + if (type.isArray()) + { + TType elementType(type); + elementType.toArrayElementType(); + + const size_t arraySize = type.getOutermostArraySize(); + for (size_t i = 0; i < arraySize; ++i) + { + constant = pushConstant(constant, elementType); + } + mIRBuilder.construct(typeId, arraySize); + } + else if (type.getBasicType() == EbtStruct) + { + const TStructure *structure = type.getStruct(); + + for (const TField *field : structure->fields()) + { + const TType *fieldType = field->type(); + constant = pushConstant(constant, *fieldType); + } + mIRBuilder.construct(typeId, structure->fields().size()); + } + else + { + size_t size = type.getObjectSize(); + for (size_t i = 0; i < size; ++i, ++constant) + { + switch (constant->getType()) + { + case EbtFloat: + mIRBuilder.pushConstantFloat(constant->getFConst()); + break; + case EbtInt: + mIRBuilder.pushConstantInt(constant->getIConst()); + break; + case EbtUInt: + mIRBuilder.pushConstantUint(constant->getUConst()); + break; + case EbtBool: + mIRBuilder.pushConstantBool(constant->getBConst()); + break; + case EbtYuvCscStandardEXT: + mIRBuilder.pushConstantYuvCscStandard(constant->getYuvCscStandardEXTConst()); + break; + default: + UNREACHABLE(); + } + } + if (size > 1) + { + mIRBuilder.construct(typeId, size); + } + } + + return constant; +} + +void TParseContext::endStatementWithValue(TIntermNode *statement) +{ + TIntermTyped *typed = statement ? statement->getAsTyped() : nullptr; + if (typed && typed->getBasicType() != EbtVoid) + { + mIRBuilder.endStatementWithValue(); + } +} + +void TParseContext::checkCallGraph() +{ + // Verify that the call graph does not contain a loop. + enum class VisitState + { + NotVisited, + Visiting, + Visited, + }; + struct Visit + { + // Note: Can't use default initializer because of msvc. + Visit() : state(VisitState::NotVisited) {} + VisitState state; + uint32_t callDepth = 0; + }; + TUnorderedMap visitState; + + TVector visitStack; + visitStack.reserve(mCallGraph.size()); + + // Visit all the functions; even if a function is unreachable, it must still result in a compile + // error. + for (auto iter : mCallGraph) + { + visitStack.push_back(iter.first); + + // Check the callees of this function too, if any is undefined, it's an error. + for (const TFunction *callee : iter.second) + { + if (mDefinedFunctions.find(callee) == mDefinedFunctions.end()) + { + std::stringstream errorStream = sh::InitializeStream(); + errorStream << "Function " << callee->name() << "() called by " + << iter.first->name() << "() is undefined"; + mDiagnostics->globalError(errorStream.str().c_str()); + } + } + } + + auto checkRecursion = [this, &visitState, &visitStack](const TFunction *function, + const TFunction *callee) -> bool { + if (visitState[callee].state == VisitState::Visiting) + { + std::stringstream errorStream = sh::InitializeStream(); + errorStream << "Recursive function call in the following call chain: " + << callee->name(); + if (callee != function) + { + for (auto caller = visitStack.rbegin(); caller != visitStack.rend(); ++caller) + { + if (visitState[*caller].state != VisitState::Visiting) + { + continue; + } + + errorStream << " <- " << (*caller)->name(); + if (*caller == callee) + { + break; + } + } + } + mDiagnostics->globalError(errorStream.str().c_str()); + visitState[callee].state = VisitState::Visited; + return false; + } + return true; + }; + + auto postVisitCheckCallDepth = [this, &visitState](const TFunction *function) -> bool { + if (!mCompileOptions.limitCallStackDepth) + { + return true; + } + + uint32_t callDepth = 0; + for (const TFunction *callee : mCallGraph[function]) + { + callDepth = std::max(callDepth, visitState[callee].callDepth); + } + // Add one depth for the call from this function to the callees. + ++callDepth; + + visitState[function].callDepth = callDepth; + + if (callDepth > static_cast(mResources.MaxCallStackDepth)) + { + std::stringstream errorStream = sh::InitializeStream(); + errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth + << ") in function: " << function->name(); + mDiagnostics->globalError(errorStream.str().c_str()); + return false; + } + + return true; + }; + + while (!visitStack.empty()) + { + const TFunction *function = visitStack.back(); + visitStack.pop_back(); + + Visit &visit = visitState[function]; + + // If node is already visited, ignore it as it's already checked. + if (visit.state == VisitState::Visited) + { + continue; + } + // If the node is done being visited, mark it so. + if (visit.state == VisitState::Visiting) + { + visit.state = VisitState::Visited; + if (!postVisitCheckCallDepth(function)) + { + break; + } + continue; + } + + // Add the callees to the stack. + visit.state = VisitState::Visiting; + visitStack.push_back(function); + + for (const TFunction *callee : mCallGraph[function]) + { + // If any is being visited, that's a recursion! + if (!checkRecursion(function, callee)) + { + break; + } + + visitStack.push_back(callee); + } + } +} + +void TParseContext::postParseValidateFragmentOutputLocations() +{ + TVector validOutputs(mFragmentOutputIndex1Used + ? mResources.MaxDualSourceDrawBuffers + : mResources.MaxDrawBuffers); + TVector validSecondaryOutputs(mResources.MaxDualSourceDrawBuffers); + + for (const VariableAndLocation &variable : mFragmentOutputsWithLocation) + { + const TType &type = variable.variable->getType(); + ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6. + const size_t elementCount = + static_cast(type.isArray() ? type.getOutermostArraySize() : 1u); + const size_t location = static_cast(type.getLayoutQualifier().location); + + ASSERT(type.getLayoutQualifier().location != -1); + + TVector *validOutputsToUse = &validOutputs; + TVector *otherOutputsToUse = &validSecondaryOutputs; + // The default index is 0, so we only assign the output to secondary outputs in case the + // index is explicitly set to 1. + if (type.getLayoutQualifier().index == 1) + { + validOutputsToUse = &validSecondaryOutputs; + otherOutputsToUse = &validOutputs; + } + + if (location + elementCount <= validOutputsToUse->size()) + { + for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++) + { + const size_t offsetLocation = location + elementIndex; + if ((*validOutputsToUse)[offsetLocation].variable != nullptr) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "conflicting output locations with previously defined output '" + << (*validOutputsToUse)[offsetLocation].variable->name() << "'"; + error(variable.line, strstr.str().c_str(), variable.variable->name()); + } + else + { + (*validOutputsToUse)[offsetLocation] = variable; + if (offsetLocation < otherOutputsToUse->size()) + { + VariableAndLocation other = (*otherOutputsToUse)[offsetLocation]; + if (other.variable != nullptr && + other.variable->getType().getBasicType() != type.getBasicType()) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "conflicting output types with previously defined output '" + << other.variable->name() << "' for location " << offsetLocation; + error(variable.line, strstr.str().c_str(), variable.variable->name()); + } + } + } + } + } + else if (elementCount > 0) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << (elementCount > 1 ? "output array locations would exceed " + : "output location must be < ") + << "MAX_" << (mFragmentOutputIndex1Used ? "DUAL_SOURCE_" : "") << "DRAW_BUFFERS"; + error(variable.line, strstr.str().c_str(), variable.variable->name()); + } + } + + // For outputs without a location, one may be provided with glBindFragDataLocationEXT or + // glBindFragDataLocationIndexedEXT, so we can't validate conflicts until link time. However, + // we _can_ validate that no single array is larger than MAX_DRAW_BUFFERS. + for (const VariableAndLocation &variable : mFragmentOutputsWithoutLocation) + { + const TType &type = variable.variable->getType(); + ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6. + const size_t elementCount = + static_cast(type.isArray() ? type.getOutermostArraySize() : 1u); + if (elementCount > validOutputs.size()) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "output array locations would exceed " + << "MAX_" << (mFragmentOutputIndex1Used ? "DUAL_SOURCE_" : "") << "DRAW_BUFFERS"; + error(variable.line, strstr.str().c_str(), variable.variable->name()); + } + } + + const bool isWebGL = IsWebGLBasedSpec(mShaderSpec); + if ((!mFragmentOutputsWithLocation.empty() && !mFragmentOutputsWithoutLocation.empty()) || + mFragmentOutputsWithoutLocation.size() > 1) + { + const char *unspecifiedLocationErrorMessage = nullptr; + if (!isExtensionEnabled(TExtension::EXT_blend_func_extended)) + { + unspecifiedLocationErrorMessage = + "when EXT_blend_func_extended extension is not enabled, must explicitly specify " + "all locations when using multiple fragment outputs"; + } + else if (!mPLSFormats.empty()) + { + unspecifiedLocationErrorMessage = + "must explicitly specify all locations when using multiple fragment outputs and " + "pixel local storage, even if EXT_blend_func_extended is enabled"; + } + else if (isWebGL) + { + unspecifiedLocationErrorMessage = + "must explicitly specify all locations when using multiple fragment outputs " + "in WebGL contexts, even if EXT_blend_func_extended is enabled"; + } + if (unspecifiedLocationErrorMessage != nullptr) + { + for (const VariableAndLocation &variable : mFragmentOutputsWithoutLocation) + { + error(variable.line, unspecifiedLocationErrorMessage, variable.variable->name()); + } + } + } + + if (!mFragmentOutputsYuv.empty() && + (mFragmentOutputsYuv.size() > 1 || mFragmentOutputFragDepthUsed || + !mFragmentOutputsWithLocation.empty() || !mFragmentOutputsWithoutLocation.empty())) + { + for (const VariableAndLocation &variable : mFragmentOutputsYuv) + { + error(variable.line, + "not allowed to specify yuv qualifier when using depth or multiple color " + "fragment outputs", + variable.variable->name()); + } + } +} + +bool TParseContext::postParseChecks() +{ +#ifndef ANGLE_IR + // If parse failed, we shouldn't reach here. + ASSERT(!mCompileOptions.useIR || mTreeRoot != nullptr); +#endif + + // If gl_Position is expected to be zero-initialized, make sure it's declared to the IR; it + // should still be done if gl_Position is statically not used by the shader. + if (mCompileOptions.initGLPosition) + { + const TSymbol *glPosition = + symbolTable.find(ImmutableString("gl_Position"), getShaderVersion()); + ASSERT(glPosition != nullptr && glPosition->isVariable()); + declareBuiltInOnFirstUse(static_cast(glPosition)); + } + + if (mMainFunction == nullptr) + { + error(kNoSourceLoc, "Missing main()", ""); + return false; + } + + for (TType *type : mDeferredArrayTypesToSize) + { + error(kNoSourceLoc, "Unsized global array type: ", type->getBasicString()); + } + + // Clip/cull distance validation now that the size can be determined. + if (mClipDistanceInfo.size == 0 && mClipDistanceInfo.hasNonConstIndex) + { + error(mClipDistanceInfo.firstEncounter, + "The gl_ClipDistance array must be sized by the shader either redeclaring it with a " + "size or indexing it only with constant integral expressions", + "gl_ClipDistance"); + } + + if (mCullDistanceInfo.size == 0 && mCullDistanceInfo.hasNonConstIndex) + { + error(mCullDistanceInfo.firstEncounter, + "The gl_CullDistance array must be sized by the shader either redeclaring it with a " + "size or indexing it only with constant integral expressions", + "gl_CullDistance"); + } + + const unsigned int usedClipDistances = getClipDistanceArraySize(); + const unsigned int usedCullDistances = getCullDistanceArraySize(); + const unsigned int combinedClipAndCullDistances = + usedClipDistances > 0 && usedCullDistances > 0 ? usedClipDistances + usedCullDistances : 0; + + // When cull distances are not supported, i.e., when GL_ANGLE_clip_cull_distance is + // exposed but GL_EXT_clip_cull_distance is not exposed, the combined limit is 0. + if (usedCullDistances > 0 && mResources.MaxCombinedClipAndCullDistances == 0) + { + error(mCullDistanceInfo.firstEncounter, "Cull distance functionality is not available", + "gl_CullDistance"); + } + + if (static_cast(combinedClipAndCullDistances) > mResources.MaxCombinedClipAndCullDistances) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " + "gl_MaxCombinedClipAndCullDistances (" + << combinedClipAndCullDistances << " > " + << mResources.MaxCombinedClipAndCullDistances << ")"; + error(mClipDistanceInfo.firstEncounter, strstr.str().c_str(), "gl_ClipDistance"); + } + + if (mClipDistanceInfo.hasArrayLengthMethodCall && usedClipDistances == 0) + { + error(mClipDistanceInfo.firstEncounter, + "The length() method cannot be called on gl_ClipDistance that is not " + "runtime sized and also has not yet been explicitly sized", + "gl_ClipDistance"); + } + if (mCullDistanceInfo.hasArrayLengthMethodCall && usedCullDistances == 0) + { + error(mCullDistanceInfo.firstEncounter, + "The length() method cannot be called on gl_CullDistance that is not " + "runtime sized and also has not yet been explicitly sized", + "gl_CullDistance"); + } + + if (ir::IsVariableIdValid(mClipDistanceInfo.id) && usedClipDistances > 0 && + !isClipDistanceRedeclared()) + { + mIRBuilder.onGlClipDistanceSized(mClipDistanceInfo.id, usedClipDistances); + } + if (ir::IsVariableIdValid(mCullDistanceInfo.id) && usedCullDistances > 0 && + !isCullDistanceRedeclared()) + { + mIRBuilder.onGlCullDistanceSized(mCullDistanceInfo.id, usedCullDistances); + } + + ValidateFragColorAndFragData(mShaderType, mShaderVersion, symbolTable, mDiagnostics); + postParseValidateFragmentOutputLocations(); + + if (mCompileOptions.rejectWebglShadersWithLargeVariables) + { + if (mTotalPrivateVariablesSize.ValueOrDefault(std::numeric_limits::max()) > + kWebGLMaxTotalPrivateVariableSizeInBytes) + { + error(TSourceLoc{}, + "Total size of declared private variables exceeds implementation-defined limit", + ""); + } + } + + if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior) + { + // For any possibly infinite loops, check if the loop variable remained unchanged and so the + // loop is in fact definitely an infinite loop. + for (VariableAndLocation loopVariable : mPossiblyInfiniteLoops) + { + if (mConstantTrueVariables.find(loopVariable.variable->uniqueId()) != + mConstantTrueVariables.end()) + { + error(loopVariable.line, "Infinite loop detected in the shader", + loopVariable.variable->name()); + } + } + } + + checkCallGraph(); + + return numErrors() == 0; +} + // // Parse an array of strings using yyparse. // // Returns 0 for success. // -int PaParseStrings(size_t count, - const char *const string[], +int PaParseStrings(angle::Span string, const int length[], TParseContext *context) { - if ((count == 0) || (string == nullptr)) + if (string.empty()) + { return 1; + } if (glslang_initialize(context)) return 1; - int error = glslang_scan(count, string, length, context); + int error = glslang_scan(string.size(), string.data(), length, context); if (!error) error = glslang_parse(context); diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h index bf70c848969..828eebbe033 100644 --- a/src/compiler/translator/ParseContext.h +++ b/src/compiler/translator/ParseContext.h @@ -6,6 +6,8 @@ #ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ #define COMPILER_TRANSLATOR_PARSECONTEXT_H_ +#include "common/hash_containers.h" +#include "common/span.h" #include "compiler/preprocessor/Preprocessor.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/Declarator.h" @@ -14,6 +16,7 @@ #include "compiler/translator/FunctionLookup.h" #include "compiler/translator/QualifierTypes.h" #include "compiler/translator/SymbolTable.h" +#include "compiler/translator/ValidateVaryingLocations.h" namespace sh { @@ -26,6 +29,40 @@ struct TMatrixFields int col; }; +struct ClipCullDistanceInfo +{ + // Whether the size is specified by redeclaring the built-in + uint32_t size = 0; + // What is the maximum constant index used with this built-in + int32_t maxIndex = -1; + // Whether any non-constant indices were used with this built-in + bool hasNonConstIndex = false; + // Whether .length() has been called on this built-in + bool hasArrayLengthMethodCall = false; + // A location to associate with post-parse errors + TSourceLoc firstEncounter = kNoSourceLoc; + // The IR id of this variable, only needed when !declared + ir::VariableId id = ir::kInvalidVariableId; +}; + +enum class GeomTessArray +{ + Sized, + Deferred, +}; + +enum class FunctionDeclaration +{ + Prototype, + Definition, +}; + +struct VariableAndLocation +{ + TSourceLoc line = {}; + const TVariable *variable = nullptr; +}; + // // The following are extra variables needed during parsing, grouped together so // they can be passed to the parser without needing a global. @@ -49,6 +86,7 @@ class TParseContext : angle::NonCopyable void *getScanner() const { return mScanner; } void setScanner(void *scanner) { mScanner = scanner; } int getShaderVersion() const { return mShaderVersion; } + void onShaderVersionDeclared(int version); sh::GLenum getShaderType() const { return mShaderType; } ShShaderSpec getShaderSpec() const { return mShaderSpec; } int numErrors() const { return mDiagnostics->numErrors(); } @@ -65,36 +103,13 @@ class TParseContext : angle::NonCopyable TIntermBlock *getTreeRoot() const { return mTreeRoot; } void setTreeRoot(TIntermBlock *treeRoot); - bool getFragmentPrecisionHigh() const - { - return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300; - } - void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh) - { - mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh; - } + ir::IR getIR(); bool usesDerivatives() const { return mUsesDerivatives; } bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; } bool hasDiscard() const { return mHasDiscard; } bool isSampleQualifierSpecified() const { return mSampleQualifierSpecified; } - void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; } - - void incrLoopNestingLevel(const TSourceLoc &line) - { - ++mLoopNestingLevel; - checkNestingLevel(line); - } - void decrLoopNestingLevel() { --mLoopNestingLevel; } - - void incrSwitchNestingLevel(const TSourceLoc &line) - { - ++mSwitchNestingLevel; - checkNestingLevel(line); - } - void decrSwitchNestingLevel() { --mSwitchNestingLevel; } - bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } sh::WorkGroupSize getComputeShaderLocalSize() const; @@ -125,8 +140,8 @@ class TParseContext : angle::NonCopyable // Look at a '.' field selector string and change it into offsets for a vector. bool parseVectorFields(const TSourceLoc &line, const ImmutableString &compString, - int vecSize, - TVector *fieldOffsets); + uint32_t vecSize, + TVector *fieldOffsets); void assignError(const TSourceLoc &line, const char *op, const TType &left, const TType &right); void unaryOpError(const TSourceLoc &line, const char *op, const TType &operand); @@ -242,6 +257,16 @@ class TParseContext : angle::NonCopyable const ImmutableString &identifier, TIntermTyped *initializer, const TSourceLoc &loc); + + void beginNestedScope(); + void endNestedScope(); + + void beginLoop(TLoopType loopType, const TSourceLoc &line); + void onLoopConditionBegin(TIntermNode *init, const TSourceLoc &line); + void onLoopConditionEnd(TIntermNode *condition, const TSourceLoc &line); + void onLoopContinueEnd(TIntermNode *statement, const TSourceLoc &line); + void onDoLoopBegin(); + void onDoLoopConditionBegin(); TIntermNode *addLoop(TLoopType type, TIntermNode *init, TIntermNode *cond, @@ -251,6 +276,10 @@ class TParseContext : angle::NonCopyable // For "if" test nodes. There are three children: a condition, a true path, and a false path. // The two paths are in TIntermNodePair code. + void onIfTrueBlockBegin(TIntermTyped *cond, const TSourceLoc &loc); + void onIfTrueBlockEnd(); + void onIfFalseBlockBegin(); + void onIfFalseBlockEnd(); TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc); void addFullySpecifiedType(TPublicType *typeSpecifier); @@ -348,6 +377,7 @@ class TParseContext : angle::NonCopyable void parseParameterQualifier(const TSourceLoc &line, const TTypeQualifierBuilder &typeQualifierBuilder, TPublicType &type); + void addParameter(TFunction *function, TParameter *param); TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, @@ -441,6 +471,7 @@ class TParseContext : angle::NonCopyable void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field); + void beginSwitch(const TSourceLoc &line, TIntermTyped *init); TIntermSwitch *addSwitch(TIntermTyped *init, TIntermBlock *statementList, const TSourceLoc &loc); @@ -461,7 +492,10 @@ class TParseContext : angle::NonCopyable TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); + void onShortCircuitAndBegin(TIntermTyped *left, const TSourceLoc &loc); + void onShortCircuitOrBegin(TIntermTyped *left, const TSourceLoc &loc); + void onCommaLeftHandSideParsed(TIntermTyped *left); TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); @@ -481,11 +515,28 @@ class TParseContext : angle::NonCopyable // has the arguments. TIntermTyped *addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc); + void onTernaryConditionParsed(TIntermTyped *cond, const TSourceLoc &line); + void onTernaryTrueExpressionParsed(TIntermTyped *trueExpression, const TSourceLoc &line); TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression, const TSourceLoc &line); + uint32_t getClipDistanceArraySize() const + { + return mClipDistanceInfo.size > 0 ? mClipDistanceInfo.size : mClipDistanceInfo.maxIndex + 1; + } + uint32_t getCullDistanceArraySize() const + { + return mCullDistanceInfo.size > 0 ? mCullDistanceInfo.size : mCullDistanceInfo.maxIndex + 1; + } + bool isClipDistanceRedeclared() const { return mClipDistanceInfo.size > 0; } + bool isCullDistanceRedeclared() const { return mCullDistanceInfo.size > 0; } + bool isClipDistanceUsed() const + { + return mClipDistanceInfo.maxIndex >= 0 || mClipDistanceInfo.hasNonConstIndex; + } + int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } int getGeometryShaderInvocations() const { @@ -517,19 +568,18 @@ class TParseContext : angle::NonCopyable return mTessEvaluationShaderInputPointType; } - const TVector &getDeferredArrayTypesToSize() const - { - return mDeferredArrayTypesToSize; - } - void markShaderHasPrecise() { mHasAnyPreciseType = true; } bool hasAnyPreciseType() const { return mHasAnyPreciseType; } AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; } ShShaderOutput getOutputType() const { return mOutputType; } - size_t getMaxExpressionComplexity() const { return mMaxExpressionComplexity; } - size_t getMaxStatementDepth() const { return mMaxStatementDepth; } + // Pop the side effect of a statement when it's discarded, like when ; is encountered. + void endStatementWithValue(TIntermNode *statement); + + bool postParseChecks(); + + const ShCompileOptions &getCompileOptions() const { return mCompileOptions; } // TODO(jmadill): make this private TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed @@ -546,7 +596,7 @@ class TParseContext : angle::NonCopyable // Note that there may be tests in AtomicCounter_test that will need to be updated as well. constexpr static size_t kAtomicCounterArrayStride = 4; - void markStaticReadIfSymbol(TIntermNode *node); + void markStaticUseIfSymbol(TIntermNode *node); // Returns a clamped index. If it prints out an error message, the token is "[]". int checkIndexLessThan(bool outOfRangeIndexIsError, @@ -558,9 +608,11 @@ class TParseContext : angle::NonCopyable bool declareVariable(const TSourceLoc &line, const ImmutableString &identifier, const TType *type, + GeomTessArray sized, TVariable **variable); void checkNestingLevel(const TSourceLoc &line); + bool checkCase(const TSourceLoc &line, int64_t caseValue, const char *caseOrDefault); void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, const ImmutableString &identifier, @@ -637,12 +689,14 @@ class TParseContext : angle::NonCopyable // Will set the size of the outermost array according to geometry shader input layout. void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, const ImmutableString &token, - TType *type); + TType *type, + GeomTessArray *sizedOut); // Similar, for tessellation shaders. void checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location, const ImmutableString &token, - TType *type); + TType *type, + GeomTessArray *sizedOut); // Will size any unsized array type so unsized arrays won't need to be taken into account // further along the line in parsing. @@ -679,6 +733,15 @@ class TParseContext : angle::NonCopyable const TSourceLoc &location, bool insertParametersToSymbolTable); + void checkESSL100ForLoopInit(TIntermNode *init, const TSourceLoc &line); + void checkESSL100ForLoopCondition(TIntermNode *condition, const TSourceLoc &line); + void checkESSL100ForLoopContinue(TIntermNode *statement, const TSourceLoc &line); + void checkESSL100NoLoopSymbolAssign(TIntermSymbol *symbol, const TSourceLoc &line); + void checkESSL100ConstantIndex(TIntermTyped *index, const TSourceLoc &line); + bool isESSL100ConstantLoopSymbol(TIntermSymbol *symbol); + + void checkCallGraph(); + void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration, const TSourceLoc &location); @@ -690,6 +753,49 @@ class TParseContext : angle::NonCopyable bool parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier); bool parseTessEvaluationShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier); + void checkVariableSize(const TSourceLoc &line, + const ImmutableString &identifier, + const TType *type); + void checkVaryingLocations(const TSourceLoc &line, const TVariable *variable); + void checkFragmentOutputLocations(const TSourceLoc &line, const TVariable *variable); + void checkVariableLocations(const TSourceLoc &line, const TVariable *variable); + void postParseValidateFragmentOutputLocations(); + + void sizeUnsizedArrayTypes(uint32_t arraySize); + + enum class ControlFlowType + { + // Control flow nested under `if`. + If, + // Control flow nested under `for`, `while` or `do { ... } while`. + Loop, + // Control flow nested under `switch`. + Switch, + // Not a divergent control flow, but nested under a new `{}` scope. + NewScope, + }; + bool isNestedIn(ControlFlowType type) const; + bool isDirectlyUnderSwitch() const; + void popControlFlow(); + + // Used to derive the IR type id of TType's that are statically allocated, which (currently) + // don't have an assigned type id. Once IR is the only path, static TTypes (used to bake the + // built-in variables and functions) can be simplified and the ID predefined and included with + // it. + ir::TypeId getTypeId(const TType &type); + // For built-ins, declare them in the IR on first use. + ir::VariableId declareBuiltInOnFirstUse(const TVariable *variable); + // Declare the variable to IR on declaration, or in the case of unsized geometry/tessellation + // arrays, whenever the size is determined. + void declareIRVariable(const TVariable *variable, GeomTessArray sized); + // Declare the function to the IR builder. If it's a definition and a prototype was previously + // seen, the parameter names are updated instead. + void declareFunction(const TFunction *function, FunctionDeclaration declaration); + // Push a variable to the IR builder. + void pushVariable(const TVariable *variable); + // Push a constant to the IR builder. + const TConstantUnion *pushConstant(const TConstantUnion *constant, const TType &type); + // Certain operations become illegal only iff the shader declares pixel local storage uniforms. enum class PLSIllegalOperations { @@ -740,16 +846,13 @@ class TParseContext : angle::NonCopyable sh::GLenum mShaderType; // vertex/fragment/geometry/etc shader ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES/WebGL/etc. ShCompileOptions mCompileOptions; // Options passed to TCompiler + const ShBuiltInResources &mResources; // Limits passed to TCompiler + int mShaderVersion; TIntermBlock *mTreeRoot; // root of parse tree being created - int mLoopNestingLevel; // 0 if outside all loops int mStructNestingLevel; // incremented while parsing a struct declaration - int mSwitchNestingLevel; // 0 if outside all switch statements - const TType - *mCurrentFunctionType; // the return type of the function that's currently being parsed - bool mFunctionReturnsValue; // true if a non-void function has a return - bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling - // ESSL1. + const TFunction *mCurrentFunction; // the function that's currently being parsed + bool mFunctionReturnsValue; // true if a non-void function has a return bool mEarlyFragmentTestsSpecified; // true if layout(early_fragment_tests) in; is specified. bool mHasDiscard; // true if |discard| is encountered in the shader. bool mSampleQualifierSpecified; // true if the |sample| qualifier is used @@ -769,35 +872,85 @@ class TParseContext : angle::NonCopyable TDirectiveHandler mDirectiveHandler; angle::pp::Preprocessor mPreprocessor; void *mScanner; - const size_t mMaxExpressionComplexity; - const size_t mMaxStatementDepth; - int mMinProgramTexelOffset; - int mMaxProgramTexelOffset; - int mMinProgramTextureGatherOffset; - int mMaxProgramTextureGatherOffset; + // Keep track of clip/cull distance redeclaration, accessed indices, etc so that gl_ClipDistance + // and gl_CullDistance can be validated and sized at the end of compilation. + ClipCullDistanceInfo mClipDistanceInfo; + ClipCullDistanceInfo mCullDistanceInfo; - // keep track of local group size declared in layout. It should be declared only once. + // Keep track of local group size declared in layout. It should be declared only once. bool mComputeShaderLocalSizeDeclared; sh::WorkGroupSize mComputeShaderLocalSize; - // keep track of number of views declared in layout. + // Keep track of number of views declared in layout. int mNumViews; - int mMaxNumViews; - int mMaxImageUnits; - int mMaxCombinedTextureImageUnits; - int mMaxUniformLocations; - int mMaxUniformBufferBindings; - int mMaxVertexAttribs; - int mMaxAtomicCounterBindings; - int mMaxAtomicCounterBufferSize; - int mMaxShaderStorageBufferBindings; - int mMaxPixelLocalStoragePlanes; - - // keeps track whether we are declaring / defining a function + + // Keeps track of whether any of the built-ins that can be redeclared (see + // IsRedeclarableBuiltIn()) has been marked as invariant/precise before the possible + // redeclaration. + // + // If redeclared after being marked as invariant/precise, a compile error is generated. + // The GLSL spec does not explicitly call this out as invalid, but it's not a useful sequence + // of statements (invariant/precise could have been directly specified on the redeclaration), + // and there are no known users. + TUnorderedMap mBuiltInQualified; + + // Keeps track whether we are declaring / defining a function bool mDeclaringFunction; - // keeps track whether we are declaring / defining the function main(). + // Keeps track whether we are declaring / defining the function main(). bool mDeclaringMain; + const TFunction *mMainFunction; + // Whether `return` has been observed in `main()`. Used to validate barrier() in tessellation + // control shaders which are not allowed after `return`. + bool mIsReturnVisitedInMain; + // Keeps track of the total size of shader-private variables, if validating that this size + // should not exceed a sensible threshold. + angle::base::CheckedNumeric mTotalPrivateVariablesSize; + + // Track state related to control flow, used for various validation: + // + // * That case is within switch, continue is within loop, and break is within loop or switch + // * That the shader statements don't get too nested (based on `MaxStatementDepth`) + // * In tessellation control shaders, barrier() cannot be called in divergent control flow. + // * ESSL 1.0 limits restricts the shape of `for` loops (see Appendix A) + // * ESSL 1.0 limits array indices to `constant-index-expressions` (see Appendix A) + // * Rejection of obvious infinite loops with WebGL. + struct ControlFlow + { + ControlFlowType type; + + // Used when validating ESSL 1.0 limitations for `for` loops. + TSymbolUniqueId forLoopSymbol = TSymbolUniqueId::kInvalid(); + bool isForLoopSymbolConstant = false; + + // Used to detect and reject infinite loops with WebGL. + TSourceLoc loopLocation = kNoSourceLoc; + bool isLoopConditionConstantTrue = false; + const TVariable *loopConditionConstantTrueSymbol = nullptr; + bool hasBreak = false; + bool hasReturn = false; + + // Used to detect and reject invalid `case` placements in a switch. + // int64_t is used to include both signed and unsigned case values (which are 32-bit). The + // default case uses a number outside the [INT_MIN, UINT_MAX] range. + TBasicType switchType = EbtInt; + static constexpr int64_t kDefaultCaseLabel = std::numeric_limits::max(); + TVector caseLabels; + }; + std::vector mControlFlow; + // Whether ESSL 1.0 limitations in Appendix A must be enforced. + bool mValidateESSL100Limitations; + // Whether the variable is initialized to true, and never modified. If this is used as a loop + // variable, where the loop doesn't have break or return, at the end of parse we can detect + // these loops as infinite loop. + TUnorderedSet mConstantTrueVariables; + TVector mPossiblyInfiniteLoops; + + // Track the static call graph. Static recursion is disallowed by GLSL. + TUnorderedMap> mCallGraph; + // Track functions that have been defined. At the end of parse, if any + // function is called that's not in this list, it's a compile error. + TUnorderedSet mDefinedFunctions; // Track the state of each atomic counter binding. std::map mAtomicCounterBindingStates; @@ -808,16 +961,24 @@ class TParseContext : angle::NonCopyable // Potential errors to generate immediately upon encountering a pixel local storage uniform. std::vector> mPLSPotentialErrors; + // Track the locations used by input and output varyings to detect conflicts. + LocationValidationMap mInputVaryingLocations; + LocationValidationMap mOutputVaryingLocations; + + // Track the locations used by fragment shader outputs to detect conflicts. + TVector mFragmentOutputsWithLocation; + TVector mFragmentOutputsWithoutLocation; + TVector mFragmentOutputsYuv; + bool mFragmentOutputIndex1Used; + bool mFragmentOutputFragDepthUsed; + // Track the geometry shader global parameters declared in layout. TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; int mGeometryShaderInvocations; int mGeometryShaderMaxVertices; - int mMaxGeometryShaderInvocations; - int mMaxGeometryShaderMaxVertices; unsigned int mGeometryInputArraySize; - int mMaxPatchVertices; int mTessControlShaderOutputVertices; TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType; TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType; @@ -826,6 +987,9 @@ class TParseContext : angle::NonCopyable // List of array declarations without an explicit size that have come before layout(vertices=N). // Once the vertex count is specified, these arrays are sized. TVector mDeferredArrayTypesToSize; + // For the IR, the variables themselves are declared late instead of having to go through a + // retype. + TVector mDeferredArrayVariablesToSize; // Whether the |precise| keyword has been seen in the shader. bool mHasAnyPreciseType; @@ -835,10 +999,26 @@ class TParseContext : angle::NonCopyable bool mFunctionBodyNewScope; ShShaderOutput mOutputType; + + ir::Builder mIRBuilder; + // Support for creating the IR while the translator still has the option to not go through the + // IR path. Once AST generation during parse is removed, TParseContext can instead keep track + // of IDs directly, instead of TSymbol derivatives, together with an array-based mapping to + // validation info including type and variable data. + struct VariableToIdInfo + { + ir::VariableId id; + // For nameless interface blocks, the shader directly references the fields. The IR instead + // selects a field from the block variable, which is found in |id|. + static constexpr uint32_t kNoImplicitField = 0xFFFF'FFFF; + uint32_t implicitField = kNoImplicitField; + }; + angle::HashMap mSymbolToTypeId; + angle::HashMap mVariableToId; + angle::HashMap mFunctionToId; }; -int PaParseStrings(size_t count, - const char *const string[], +int PaParseStrings(angle::Span string, const int length[], TParseContext *context); diff --git a/src/compiler/translator/PoolAlloc.cpp b/src/compiler/translator/PoolAlloc.cpp index 9f9bebcc64f..ea762403fdb 100644 --- a/src/compiler/translator/PoolAlloc.cpp +++ b/src/compiler/translator/PoolAlloc.cpp @@ -27,6 +27,11 @@ void FreePoolIndex() PoolIndex = TLS_INVALID_INDEX; } +bool IsGlobalPoolAllocatorInitialized() +{ + return PoolIndex != TLS_INVALID_INDEX; +} + angle::PoolAllocator *GetGlobalPoolAllocator() { ASSERT(PoolIndex != TLS_INVALID_INDEX); diff --git a/src/compiler/translator/PoolAlloc.h b/src/compiler/translator/PoolAlloc.h index 98f549b179e..942dd5e141a 100644 --- a/src/compiler/translator/PoolAlloc.h +++ b/src/compiler/translator/PoolAlloc.h @@ -28,6 +28,17 @@ // extern angle::PoolAllocator *GetGlobalPoolAllocator(); extern void SetGlobalPoolAllocator(angle::PoolAllocator *poolAllocator); +extern bool IsGlobalPoolAllocatorInitialized(); + +class [[nodiscard]] TScopedPoolAllocator +{ + public: + TScopedPoolAllocator() { SetGlobalPoolAllocator(&mAllocator); } + ~TScopedPoolAllocator() { SetGlobalPoolAllocator(nullptr); } + + private: + angle::PoolAllocator mAllocator; +}; // // This STL compatible allocator is intended to be used as the allocator diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp index 17ec83b397d..a5bfbbce700 100644 --- a/src/compiler/translator/ShaderLang.cpp +++ b/src/compiler/translator/ShaderLang.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + // // Implement the top-level of interface to the compiler, // as defined in ShaderLang.h @@ -12,8 +16,10 @@ #include "GLSLANG/ShaderLang.h" #include "common/PackedEnums.h" +#include "common/span.h" +#include "common/unsafe_buffers.h" #include "compiler/translator/Compiler.h" -#include "compiler/translator/InitializeDll.h" +#include "compiler/translator/InitializeGlobals.h" #include "compiler/translator/length_limits.h" #ifdef ANGLE_ENABLE_HLSL # include "compiler/translator/hlsl/TranslatorHLSL.h" @@ -21,6 +27,10 @@ #include "angle_gl.h" #include "compiler/translator/VariablePacker.h" +#ifdef ANGLE_IR +# include "compiler/translator/ir/src/compile.h" +#endif + namespace sh { @@ -143,7 +153,10 @@ bool Initialize() { if (!isInitialized) { - isInitialized = InitProcess(); + isInitialized = InitializePoolIndex(); +#ifdef ANGLE_IR + ir::ffi::initialize_global_pool_index_workaround(); +#endif } return isInitialized; } @@ -155,7 +168,10 @@ bool Finalize() { if (isInitialized) { - DetachProcess(); + FreePoolIndex(); +#ifdef ANGLE_IR + ir::ffi::free_global_pool_index_workaround(); +#endif isInitialized = false; } return true; @@ -170,14 +186,18 @@ void InitBuiltInResources(ShBuiltInResources *resources) memset(resources, 0, sizeof(*resources)); // Constants. - resources->MaxVertexAttribs = 8; - resources->MaxVertexUniformVectors = 128; - resources->MaxVaryingVectors = 8; - resources->MaxVertexTextureImageUnits = 0; - resources->MaxCombinedTextureImageUnits = 8; - resources->MaxTextureImageUnits = 8; - resources->MaxFragmentUniformVectors = 16; - resources->MaxDrawBuffers = 1; + resources->MaxVertexAttribs = 8; + resources->MaxVertexUniformVectors = 128; + resources->MaxVaryingVectors = 8; + resources->MaxVertexTextureImageUnits = 0; + resources->MaxCombinedTextureImageUnits = 8; + resources->MaxTextureImageUnits = 8; + resources->MaxFragmentUniformVectors = 16; + resources->MaxDrawBuffers = 1; + resources->ShadingRateFlag2VerticalPixelsEXT = 1; + resources->ShadingRateFlag4VerticalPixelsEXT = 2; + resources->ShadingRateFlag2HorizontalPixelsEXT = 4; + resources->ShadingRateFlag4HorizontalPixelsEXT = 8; // Extensions. resources->OES_standard_derivatives = 0; @@ -192,7 +212,6 @@ void InitBuiltInResources(ShBuiltInResources *resources) resources->EXT_shader_texture_lod = 0; resources->EXT_shader_framebuffer_fetch = 0; resources->EXT_shader_framebuffer_fetch_non_coherent = 0; - resources->NV_shader_framebuffer_fetch = 0; resources->ARM_shader_framebuffer_fetch = 0; resources->ARM_shader_framebuffer_fetch_depth_stencil = 0; resources->OVR_multiview = 0; @@ -227,6 +246,8 @@ void InitBuiltInResources(ShBuiltInResources *resources) resources->OES_tessellation_shader = 0; resources->OES_texture_buffer = 0; resources->EXT_texture_buffer = 0; + resources->EXT_fragment_shading_rate = 0; + resources->EXT_fragment_shading_rate_primitive = 0; resources->OES_sample_variables = 0; resources->EXT_clip_cull_distance = 0; resources->ANGLE_clip_cull_distance = 0; @@ -236,9 +257,6 @@ void InitBuiltInResources(ShBuiltInResources *resources) resources->MaxCullDistances = 8; resources->MaxCombinedClipAndCullDistances = 8; - // Disable highp precision in fragment shader by default. - resources->FragmentPrecisionHigh = 0; - // GLSL ES 3.0 constants. resources->MaxVertexOutputVectors = 16; resources->MaxFragmentInputVectors = 15; @@ -253,6 +271,8 @@ void InitBuiltInResources(ShBuiltInResources *resources) // Disable name hashing by default. resources->HashFunction = nullptr; + resources->UserVariableNamePrefix = kUserDefinedNamePrefix; + resources->MaxExpressionComplexity = 256; resources->MaxStatementDepth = 256; resources->MaxCallStackDepth = 256; @@ -303,7 +323,6 @@ void InitBuiltInResources(ShBuiltInResources *resources) resources->MaxShaderStorageBufferBindings = 4; resources->MaxGeometryUniformComponents = 1024; - resources->MaxGeometryUniformBlocks = 12; resources->MaxGeometryInputComponents = 64; resources->MaxGeometryOutputComponents = 64; resources->MaxGeometryOutputVertices = 256; @@ -311,7 +330,6 @@ void InitBuiltInResources(ShBuiltInResources *resources) resources->MaxGeometryTextureImageUnits = 16; resources->MaxGeometryAtomicCounterBuffers = 0; resources->MaxGeometryAtomicCounters = 0; - resources->MaxGeometryShaderStorageBlocks = 0; resources->MaxGeometryShaderInvocations = 32; resources->MaxGeometryImageUniforms = 0; @@ -336,8 +354,6 @@ void InitBuiltInResources(ShBuiltInResources *resources) resources->MaxTessEvaluationAtomicCounters = 0; resources->MaxTessEvaluationAtomicCounterBuffers = 0; - resources->SubPixelBits = 8; - resources->MaxSamples = 4; } @@ -411,7 +427,9 @@ bool Compile(const ShHandle handle, TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); - return compiler->compile(shaderStrings, numStrings, compileOptions); + // SAFETY: required from caller across this exposed API. + return compiler->compile(ANGLE_UNSAFE_BUFFERS(angle::Span(shaderStrings, numStrings)), + compileOptions); } void ClearResults(const ShHandle handle) @@ -480,7 +498,10 @@ bool GetShaderBinary(const ShHandle handle, TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); - return compiler->getShaderBinary(handle, shaderStrings, numStrings, compileOptions, binaryOut); + // SAFETY: required from caller across this exposed API. + return compiler->getShaderBinary(handle, + ANGLE_UNSAFE_BUFFERS(angle::Span(shaderStrings, numStrings)), + compileOptions, binaryOut); } const std::map *GetNameHashingMap(const ShHandle handle) @@ -615,7 +636,7 @@ const std::vector *GetPixelLocalStorageFormats(const TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); - return &compiler->GetPixelLocalStorageFormats(); + return &compiler->getPixelLocalStorageFormats(); } uint32_t GetShaderSpecConstUsageBits(const ShHandle handle) @@ -633,28 +654,6 @@ bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vectorhasShaderStorageBlock(shaderStorageBlockName)) - { - return false; - } - - *indexOut = translator->getShaderStorageBlockRegister(shaderStorageBlockName); - return true; -#else - return false; -#endif // ANGLE_ENABLE_HLSL -} - bool GetUniformBlockRegister(const ShHandle handle, const std::string &uniformBlockName, unsigned int *indexOut) @@ -906,7 +905,7 @@ uint32_t GetAdvancedBlendEquations(const ShHandle handle) // Can't prefix with just _ because then we might introduce a double underscore, which is not safe // in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for // use by the underlying implementation). u is short for user-defined. -const char kUserDefinedNamePrefix[] = "_u"; +const char kUserDefinedNamePrefix = 'u'; const char *BlockLayoutTypeToString(BlockLayoutType type) { diff --git a/src/compiler/translator/ShaderVars.cpp b/src/compiler/translator/ShaderVars.cpp index 5b8139c8cc5..830898838f2 100644 --- a/src/compiler/translator/ShaderVars.cpp +++ b/src/compiler/translator/ShaderVars.cpp @@ -7,6 +7,10 @@ // Methods for GL variable types (varyings, uniforms, etc) // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/debug.h" @@ -56,6 +60,7 @@ ShaderVariable::ShaderVariable(GLenum typeIn) isPatch(false), texelFetchStaticUse(false), id(0), + isFloat16(false), flattenedOffsetInParentArrays(-1) {} @@ -96,6 +101,7 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other) isPatch(other.isPatch), texelFetchStaticUse(other.texelFetchStaticUse), id(other.id), + isFloat16(other.isFloat16), flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays) {} @@ -130,6 +136,7 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) isPatch = other.isPatch; texelFetchStaticUse = other.texelFetchStaticUse; id = other.id; + isFloat16 = other.isFloat16; return *this; } @@ -148,7 +155,7 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const interpolation != other.interpolation || isInvariant != other.isInvariant || isShaderIOBlock != other.isShaderIOBlock || isPatch != other.isPatch || texelFetchStaticUse != other.texelFetchStaticUse || - isFragmentInOut != other.isFragmentInOut) + isFragmentInOut != other.isFragmentInOut || isFloat16 != other.isFloat16) { return false; } diff --git a/src/compiler/translator/SizeClipCullDistance.cpp b/src/compiler/translator/SizeClipCullDistance.cpp new file mode 100644 index 00000000000..792be8f3862 --- /dev/null +++ b/src/compiler/translator/SizeClipCullDistance.cpp @@ -0,0 +1,44 @@ +// +// Copyright 2025 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. +// + +#include "SizeClipCullDistance.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/util.h" + +namespace sh +{ +bool SizeClipCullDistance(TCompiler *compiler, + TIntermBlock *root, + const ImmutableString &name, + uint8_t size) +{ + const TVariable *var = static_cast( + compiler->getSymbolTable().findBuiltIn(name, compiler->getShaderVersion())); + ASSERT(var != nullptr); + + if (size != var->getType().getOutermostArraySize()) + { + TType *resizedType = new TType(var->getType()); + resizedType->setArraySize(0, size); + TVariable *resizedVar = + new TVariable(&compiler->getSymbolTable(), name, resizedType, SymbolType::BuiltIn); + if (!ReplaceVariable(compiler, root, var, resizedVar)) + { + return false; + } + var = resizedVar; + } + + TIntermDeclaration *globalDecl = new TIntermDeclaration(); + globalDecl->appendDeclarator(new TIntermSymbol(var)); + root->insertStatement(0, globalDecl); + + return compiler->validateAST(root); +} +} // namespace sh diff --git a/src/compiler/translator/SizeClipCullDistance.h b/src/compiler/translator/SizeClipCullDistance.h new file mode 100644 index 00000000000..b4cb4670311 --- /dev/null +++ b/src/compiler/translator/SizeClipCullDistance.h @@ -0,0 +1,28 @@ +// +// Copyright 2025 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. +// +// The SizeClipCullDistance function redeclares gl_ClipDistance and gl_CullDistance when implicitly +// sized. +// + +#ifndef COMPILER_TRANSLATOR_SIZECLIPCULLDISTANCE_H_ +#define COMPILER_TRANSLATOR_SIZECLIPCULLDISTANCE_H_ + +#include "GLSLANG/ShaderVars.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TIntermBlock; + +bool SizeClipCullDistance(TCompiler *compiler, + TIntermBlock *root, + const ImmutableString &name, + uint8_t size); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SIZECLIPCULLDISTANCE_H_ diff --git a/src/compiler/translator/StaticType.h b/src/compiler/translator/StaticType.h index 4c5807e0972..d0cf5ea3550 100644 --- a/src/compiler/translator/StaticType.h +++ b/src/compiler/translator/StaticType.h @@ -10,6 +10,10 @@ #ifndef COMPILER_TRANSLATOR_STATIC_TYPE_H_ #define COMPILER_TRANSLATOR_STATIC_TYPE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/Types.h" namespace sh diff --git a/src/compiler/translator/Symbol.cpp b/src/compiler/translator/Symbol.cpp index dddf7707150..9c885385120 100644 --- a/src/compiler/translator/Symbol.cpp +++ b/src/compiler/translator/Symbol.cpp @@ -6,6 +6,10 @@ // Symbol.cpp: Symbols representing variables, functions, structures and interface blocks. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #if defined(_MSC_VER) # pragma warning(disable : 4718) #endif @@ -163,7 +167,8 @@ TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extension), TFieldListCollection(fields), mBlockStorage(layoutQualifier.blockStorage), - mBinding(layoutQualifier.binding) + mBinding(layoutQualifier.binding), + mIsDefaultUniformBlock(false) { ASSERT(name != nullptr); } @@ -177,7 +182,8 @@ TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extensions), TFieldListCollection(fields), mBlockStorage(layoutQualifier.blockStorage), - mBinding(layoutQualifier.binding) + mBinding(layoutQualifier.binding), + mIsDefaultUniformBlock(false) { ASSERT(name != nullptr); } diff --git a/src/compiler/translator/Symbol.h b/src/compiler/translator/Symbol.h index b07b92c26cf..f7e12c51c40 100644 --- a/src/compiler/translator/Symbol.h +++ b/src/compiler/translator/Symbol.h @@ -9,6 +9,10 @@ #ifndef COMPILER_TRANSLATOR_SYMBOL_H_ #define COMPILER_TRANSLATOR_SYMBOL_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/angleutils.h" #include "compiler/translator/ExtensionBehavior.h" #include "compiler/translator/ImmutableString.h" @@ -47,6 +51,10 @@ class TSymbol : angle::NonCopyable // Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty). ImmutableString getMangledName() const; + // Return whether this will generate a temporary name in `name()`. Not to be confused with + // SymbolType::Empty, which shouldn't call `name()`. + bool isNameless() const { return mSymbolType == SymbolType::AngleInternal && mName.empty(); } + bool isFunction() const { return mSymbolClass == SymbolClass::Function; } bool isVariable() const { return mSymbolClass == SymbolClass::Variable; } bool isStruct() const { return mSymbolClass == SymbolClass::Struct; } @@ -232,6 +240,12 @@ class TInterfaceBlock : public TSymbol, public TFieldListCollection TLayoutBlockStorage blockStorage() const { return mBlockStorage; } int blockBinding() const { return mBinding; } + bool isDefaultUniformBlock() const { return mIsDefaultUniformBlock; } + void setDefaultUniformBlock() { mIsDefaultUniformBlock = true; } + + // For IR->AST translation only + void setBlockStorage(TLayoutBlockStorage blockStorage) { mBlockStorage = blockStorage; } + void setBlockBinding(int binding) { mBinding = binding; } private: friend class TSymbolTable; @@ -263,6 +277,7 @@ class TInterfaceBlock : public TSymbol, public TFieldListCollection TLayoutBlockStorage mBlockStorage; int mBinding; + bool mIsDefaultUniformBlock; // Note that we only record matrix packing on a per-field granularity. }; diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp index e1daf91e09f..c280656e954 100644 --- a/src/compiler/translator/SymbolTable.cpp +++ b/src/compiler/translator/SymbolTable.cpp @@ -7,6 +7,10 @@ // the header file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #if defined(_MSC_VER) # pragma warning(disable : 4718) #endif @@ -65,6 +69,10 @@ class TSymbolTable::TSymbolTableLevel bool insert(TSymbol *symbol); +#ifdef ANGLE_IR + void redeclare(TSymbol *symbol); +#endif + // Insert a function using its unmangled name as the key. void insertUnmangled(TFunction *function); @@ -87,6 +95,14 @@ bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol) return result.second; } +#ifdef ANGLE_IR +void TSymbolTable::TSymbolTableLevel::redeclare(TSymbol *symbol) +{ + // returning true means symbol was added to the table + level.insert_or_assign(symbol->getMangledName(), symbol); +} +#endif + void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function) { level.insert(tLevelPair(function->name(), function)); @@ -163,22 +179,60 @@ const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFu return firstDeclaration; } -bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize) +bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize, int shaderVersion) { if (mGlInVariableWithArraySize) { return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize; } - const TInterfaceBlock *glPerVertex = static_cast(m_gl_PerVertex); - TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); - glInType->makeArray(inputArraySize); + // Note: gl_in may be redeclared by the shader. + const TSymbol *glPerVertexVar = find(ImmutableString("gl_in"), shaderVersion); + ASSERT(glPerVertexVar); + + TType *glInType = new TType(static_cast(glPerVertexVar)->getType()); + glInType->sizeOutermostUnsizedArray(inputArraySize); mGlInVariableWithArraySize = - new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn, + new TVariable(this, glPerVertexVar->name(), glInType, glPerVertexVar->symbolType(), TExtension::EXT_geometry_shader); return true; } -TVariable *TSymbolTable::getGlInVariableWithArraySize() const +void TSymbolTable::onGlInVariableRedeclaration(const TVariable *redeclaredGlIn) +{ + // There are 4 possibilities: + // + // 1. input primitive layout is set, then gl_in is encountered (not declared) + // 2. input primitive layout is set, then gl_in is redeclared + // 3. gl_in is redeclared with a size, then input primitive layout is set + // 4. gl_in is redeclared without a size, then input primitive layout is set + // + // In case 1, setGlInArraySize declares mGlInVariableWithArraySize, but this function is not + // called. + // + // In case 2, setGlInArraySize declares mGlInVariableWithArraySize, but we need to replace it + // with the shader-declared gl_in (redeclaredGlIn). The array size of + // mGlInVariableWithArraySize and redeclaredGlIn should match (validated before the call). + // + // In case 3, this function is called when mGlInVariableWithArraySize is nullptr. We set that + // to redeclaredGlIn. Later when the input primitive is encountered, setGlInArraySize verifies + // that the size matches the expectation. + // + // In case 4, similarly this function is called when mGlInVariableWithArraySize is nullptr. + // That is again set to redeclaredGlIn. The parser needs to ensure this unsized array is sized + // before calling setGlInArraySize which verifies the array sizes match. + // + // In all cases, basically mGlInVariableWithArraySize should be set to the redeclared variable. + + // If mGlInVariableWithArraySize is set when gl_in is redeclared, it's because gl_in was + // sized before the redeclaration. In that case, make sure the redeclared variable is also + // sized. + ASSERT(mGlInVariableWithArraySize == nullptr || + mGlInVariableWithArraySize->getType().getOutermostArraySize() == + redeclaredGlIn->getType().getOutermostArraySize()); + mGlInVariableWithArraySize = redeclaredGlIn; +} + +const TVariable *TSymbolTable::getGlInVariableWithArraySize() const { return mGlInVariableWithArraySize; } @@ -204,16 +258,10 @@ TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const return &iter->second; } -void TSymbolTable::markStaticWrite(const TVariable &variable) +void TSymbolTable::markStaticUse(const TVariable &variable) { - auto metadata = getOrCreateVariableMetadata(variable); - metadata->staticWrite = true; -} - -void TSymbolTable::markStaticRead(const TVariable &variable) -{ - auto metadata = getOrCreateVariableMetadata(variable); - metadata->staticRead = true; + auto metadata = getOrCreateVariableMetadata(variable); + metadata->staticUse = true; } bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const @@ -221,7 +269,7 @@ bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const ASSERT(!variable.getConstPointer()); int id = variable.uniqueId().get(); auto iter = mVariableMetadata.find(id); - return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite); + return iter != mVariableMetadata.end() && iter->second.staticUse; } void TSymbolTable::addInvariantVarying(const TVariable &variable) @@ -293,13 +341,26 @@ bool TSymbolTable::declare(TSymbol *symbol) { ASSERT(!mTable.empty()); // The following built-ins may be redeclared by the shader: gl_ClipDistance, gl_CullDistance, - // gl_LastFragData, gl_LastFragColorARM, gl_LastFragDepthARM and gl_LastFragStencilARM. + // gl_PerVertex, gl_in (EXT_geometry_shader), gl_Position, gl_PointSize + // (EXT_separate_shader_objects), gl_LastFragData, gl_LastFragColorARM, gl_LastFragDepthARM and + // gl_LastFragStencilARM. ASSERT(symbol->symbolType() == SymbolType::UserDefined || (symbol->symbolType() == SymbolType::BuiltIn && IsRedeclarableBuiltIn(symbol->name()))); ASSERT(!symbol->isFunction()); return mTable.back()->insert(symbol); } +#ifdef ANGLE_IR +void TSymbolTable::redeclare(TSymbol *symbol) +{ + ASSERT(!mTable.empty()); + ASSERT(symbol->symbolType() == SymbolType::UserDefined || + (symbol->symbolType() == SymbolType::BuiltIn && IsRedeclarableBuiltIn(symbol->name()))); + ASSERT(!symbol->isFunction()); + mTable.back()->redeclare(symbol); +} +#endif + bool TSymbolTable::declareInternal(TSymbol *symbol) { ASSERT(!mTable.empty()); @@ -427,9 +488,7 @@ void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType) setDefaultPrecision(samplerType, EbpLow); } -TSymbolTable::VariableMetadata::VariableMetadata() - : staticRead(false), staticWrite(false), invariant(false) -{} +TSymbolTable::VariableMetadata::VariableMetadata() : staticUse(false), invariant(false) {} const TSymbol *SymbolRule::get(ShShaderSpec shaderSpec, int shaderVersion, diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h index a6ad49cc923..a196c3bd062 100644 --- a/src/compiler/translator/SymbolTable.h +++ b/src/compiler/translator/SymbolTable.h @@ -215,6 +215,12 @@ class TSymbolTable : angle::NonCopyable, TSymbolTableBase // successful, and false if the declaration failed due to redefinition. bool declare(TSymbol *symbol); +#ifdef ANGLE_IR + // Going from IR back to AST, the symbols get redeclared. Make sure the symbol table is + // updated. + void redeclare(TSymbol *symbol); +#endif + // Only used to declare internal variables. bool declareInternal(TSymbol *symbol); @@ -228,14 +234,14 @@ class TSymbolTable : angle::NonCopyable, TSymbolTableBase bool *wasDefinedOut) const; // Return false if the gl_in array size has already been initialized with a mismatching value. - bool setGlInArraySize(unsigned int inputArraySize); - TVariable *getGlInVariableWithArraySize() const; + bool setGlInArraySize(unsigned int inputArraySize, int shaderVersion); + void onGlInVariableRedeclaration(const TVariable *redeclaredGlIn); + const TVariable *getGlInVariableWithArraySize() const; const TVariable *gl_FragData() const; const TVariable *gl_SecondaryFragDataEXT() const; - void markStaticRead(const TVariable &variable); - void markStaticWrite(const TVariable &variable); + void markStaticUse(const TVariable &variable); // Note: Should not call this for constant variables. bool isStaticallyUsed(const TVariable &variable) const; @@ -288,8 +294,7 @@ class TSymbolTable : angle::NonCopyable, TSymbolTableBase struct VariableMetadata { VariableMetadata(); - bool staticRead; - bool staticWrite; + bool staticUse; bool invariant; }; @@ -327,7 +332,7 @@ class TSymbolTable : angle::NonCopyable, TSymbolTableBase // Store gl_in variable with its array size once the array size can be determined. The array // size can also be checked against latter input primitive type declaration. - TVariable *mGlInVariableWithArraySize; + const TVariable *mGlInVariableWithArraySize; friend struct SymbolIdChecker; }; diff --git a/src/compiler/translator/SymbolTable_autogen.cpp b/src/compiler/translator/SymbolTable_autogen.cpp index 3782fdd07d5..75ab4742b09 100644 --- a/src/compiler/translator/SymbolTable_autogen.cpp +++ b/src/compiler/translator/SymbolTable_autogen.cpp @@ -25,7 +25,7 @@ using TableBase = TSymbolTableBase; struct SymbolIdChecker { - static_assert(TSymbolTable::kFirstUserDefinedSymbolId > 2339); + static_assert(TSymbolTable::kFirstUserDefinedSymbolId > 2015); }; namespace BuiltInName @@ -40,8 +40,6 @@ constexpr const ImmutableString abs("abs"); constexpr const ImmutableString acos("acos"); constexpr const ImmutableString acosh("acosh"); constexpr const ImmutableString all("all"); -constexpr const ImmutableString angle_BaseInstance("angle_BaseInstance"); -constexpr const ImmutableString angle_BaseVertex("angle_BaseVertex"); constexpr const ImmutableString any("any"); constexpr const ImmutableString asin("asin"); constexpr const ImmutableString asinh("asinh"); @@ -122,7 +120,6 @@ constexpr const ImmutableString gl_HelperInvocation("gl_HelperInvocation"); constexpr const ImmutableString gl_InstanceID("gl_InstanceID"); constexpr const ImmutableString gl_InstanceIndex("gl_InstanceIndex"); constexpr const ImmutableString gl_InvocationID("gl_InvocationID"); -constexpr const ImmutableString gl_LastFragColor("gl_LastFragColor"); constexpr const ImmutableString gl_LastFragColorARM("gl_LastFragColorARM"); constexpr const ImmutableString gl_LastFragData("gl_LastFragData"); constexpr const ImmutableString gl_LastFragDepthARM("gl_LastFragDepthARM"); @@ -224,12 +221,22 @@ constexpr const ImmutableString gl_PointSize("gl_PointSize"); constexpr const ImmutableString gl_Position("gl_Position"); constexpr const ImmutableString gl_PrimitiveID("gl_PrimitiveID"); constexpr const ImmutableString gl_PrimitiveIDIn("gl_PrimitiveIDIn"); +constexpr const ImmutableString gl_PrimitiveShadingRateEXT("gl_PrimitiveShadingRateEXT"); constexpr const ImmutableString gl_SampleID("gl_SampleID"); constexpr const ImmutableString gl_SampleMask("gl_SampleMask"); constexpr const ImmutableString gl_SampleMaskIn("gl_SampleMaskIn"); constexpr const ImmutableString gl_SamplePosition("gl_SamplePosition"); constexpr const ImmutableString gl_SecondaryFragColorEXT("gl_SecondaryFragColorEXT"); constexpr const ImmutableString gl_SecondaryFragDataEXT("gl_SecondaryFragDataEXT"); +constexpr const ImmutableString gl_ShadingRateEXT("gl_ShadingRateEXT"); +constexpr const ImmutableString gl_ShadingRateFlag2HorizontalPixelsEXT( + "gl_ShadingRateFlag2HorizontalPixelsEXT"); +constexpr const ImmutableString gl_ShadingRateFlag2VerticalPixelsEXT( + "gl_ShadingRateFlag2VerticalPixelsEXT"); +constexpr const ImmutableString gl_ShadingRateFlag4HorizontalPixelsEXT( + "gl_ShadingRateFlag4HorizontalPixelsEXT"); +constexpr const ImmutableString gl_ShadingRateFlag4VerticalPixelsEXT( + "gl_ShadingRateFlag4VerticalPixelsEXT"); constexpr const ImmutableString gl_TessCoord("gl_TessCoord"); constexpr const ImmutableString gl_TessLevelInner("gl_TessLevelInner"); constexpr const ImmutableString gl_TessLevelOuter("gl_TessLevelOuter"); @@ -284,6 +291,7 @@ constexpr const ImmutableString lessThan("lessThan"); constexpr const ImmutableString lessThanEqual("lessThanEqual"); constexpr const ImmutableString log("log"); constexpr const ImmutableString log2("log2"); +constexpr const ImmutableString loopForwardProgress("loopForwardProgress"); constexpr const ImmutableString matrixCompMult("matrixCompMult"); constexpr const ImmutableString max("max"); constexpr const ImmutableString memoryBarrier("memoryBarrier"); @@ -396,30 +404,18 @@ namespace BuiltInVariable constexpr const unsigned int kArraySize4[1] = {4}; -constexpr const TVariable kangle_BaseInstance( - BuiltInId::angle_BaseInstance, - BuiltInName::angle_BaseInstance, - SymbolType::BuiltIn, - std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, - StaticType::Get()); -constexpr const TVariable kangle_BaseVertex( - BuiltInId::angle_BaseVertex, - BuiltInName::angle_BaseVertex, - SymbolType::BuiltIn, - std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, - StaticType::Get()); constexpr const TVariable kgl_BaseInstance( BuiltInId::gl_BaseInstance, BuiltInName::gl_BaseInstance, SymbolType::BuiltIn, std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, - StaticType::Get()); + StaticType::Get()); constexpr const TVariable kgl_BaseVertex( BuiltInId::gl_BaseVertex, BuiltInName::gl_BaseVertex, SymbolType::BuiltIn, std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, - StaticType::Get()); + StaticType::Get()); constexpr const TVariable kgl_DrawID(BuiltInId::gl_DrawID, BuiltInName::gl_DrawID, SymbolType::BuiltIn, @@ -446,6 +442,12 @@ constexpr const TVariable kgl_FragDepth(BuiltInId::gl_FragDepth, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); +constexpr const TVariable kgl_FragDepthEXT( + BuiltInId::gl_FragDepthEXT, + BuiltInName::gl_FragDepthEXT, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_frag_depth}}, + StaticType::Get()); constexpr const TVariable kgl_FrontFacing( BuiltInId::gl_FrontFacing, BuiltInName::gl_FrontFacing, @@ -500,12 +502,6 @@ constexpr const TVariable kgl_InvocationIDTCSES3_2( SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kgl_LastFragColor( - BuiltInId::gl_LastFragColor, - BuiltInName::gl_LastFragColor, - SymbolType::BuiltIn, - std::array{{TExtension::NV_shader_framebuffer_fetch}}, - StaticType::Get()); constexpr const TVariable kgl_LastFragColorARM( BuiltInId::gl_LastFragColorARM, BuiltInName::gl_LastFragColorARM, @@ -568,12 +564,13 @@ constexpr const TVariable kgl_NumSamples(BuiltInId::gl_NumSamples, SymbolType::BuiltIn, std::array{ {TExtension::OES_sample_variables}}, - StaticType::Get()); -constexpr const TVariable kgl_NumSamplesES3_2(BuiltInId::gl_NumSamplesES3_2, - BuiltInName::gl_NumSamples, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); + StaticType::Get()); +constexpr const TVariable kgl_NumSamplesES3_2( + BuiltInId::gl_NumSamplesES3_2, + BuiltInName::gl_NumSamples, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); constexpr const TVariable kgl_NumWorkGroups( BuiltInId::gl_NumWorkGroups, BuiltInName::gl_NumWorkGroups, @@ -628,6 +625,31 @@ constexpr const TVariable kgl_Position(BuiltInId::gl_Position, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); +constexpr const TVariable kgl_PositionGS( + BuiltInId::gl_PositionGS, + BuiltInName::gl_Position, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PositionGSES3_2( + BuiltInId::gl_PositionGSES3_2, + BuiltInName::gl_Position, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PositionTES(BuiltInId::gl_PositionTES, + BuiltInName::gl_Position, + SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_tessellation_shader, + TExtension::OES_tessellation_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PositionTESES3_2( + BuiltInId::gl_PositionTESES3_2, + BuiltInName::gl_Position, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); constexpr const TVariable kgl_PrimitiveID( BuiltInId::gl_PrimitiveID, BuiltInName::gl_PrimitiveID, @@ -690,6 +712,18 @@ constexpr const TVariable kgl_PrimitiveIDTESES3_2( SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); +constexpr const TVariable kgl_PrimitiveShadingRateEXT( + BuiltInId::gl_PrimitiveShadingRateEXT, + BuiltInName::gl_PrimitiveShadingRateEXT, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_fragment_shading_rate_primitive}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveShadingRateEXTGS( + BuiltInId::gl_PrimitiveShadingRateEXTGS, + BuiltInName::gl_PrimitiveShadingRateEXT, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_fragment_shading_rate_primitive}}, + StaticType::Get()); constexpr const TVariable kgl_SampleID(BuiltInId::gl_SampleID, BuiltInName::gl_SampleID, SymbolType::BuiltIn, @@ -719,6 +753,12 @@ constexpr const TVariable kgl_SecondaryFragColorEXT( SymbolType::BuiltIn, std::array{{TExtension::EXT_blend_func_extended}}, StaticType::Get()); +constexpr const TVariable kgl_ShadingRateEXT( + BuiltInId::gl_ShadingRateEXT, + BuiltInName::gl_ShadingRateEXT, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_fragment_shading_rate}}, + StaticType::Get()); constexpr const TVariable kgl_TessCoord(BuiltInId::gl_TessCoord, BuiltInName::gl_TessCoord, SymbolType::BuiltIn, @@ -933,210 +973,162 @@ constexpr const TVariable kpt00h( SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00k( - BuiltInId::pt00k, +constexpr const TVariable kpt00j( + BuiltInId::pt00j, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00l( - BuiltInId::pt00l, +constexpr const TVariable kpt00k( + BuiltInId::pt00k, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00n( - BuiltInId::pt00n, +constexpr const TVariable kpt00m( + BuiltInId::pt00m, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00o( - BuiltInId::pt00o, +constexpr const TVariable kpt00n( + BuiltInId::pt00n, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00p( - BuiltInId::pt00p, +constexpr const TVariable kpt00o( + BuiltInId::pt00o, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00q(BuiltInId::pt00q, +constexpr const TVariable kpt00p(BuiltInId::pt00p, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00r(BuiltInId::pt00r, +constexpr const TVariable kpt00q(BuiltInId::pt00q, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00s(BuiltInId::pt00s, +constexpr const TVariable kpt00r(BuiltInId::pt00r, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00t(BuiltInId::pt00t, +constexpr const TVariable kpt00s(BuiltInId::pt00s, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00u(BuiltInId::pt00u, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt00v( - BuiltInId::pt00v, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt00w( - BuiltInId::pt00w, +constexpr const TVariable kpt00t( + BuiltInId::pt00t, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00x(BuiltInId::pt00x, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt00y(BuiltInId::pt00y, +constexpr const TVariable kpt00u(BuiltInId::pt00u, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt00z(BuiltInId::pt00z, +constexpr const TVariable kpt00v(BuiltInId::pt00v, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01A(BuiltInId::pt01A, +constexpr const TVariable kpt00w(BuiltInId::pt00w, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01B( - BuiltInId::pt01B, +constexpr const TVariable kpt00x( + BuiltInId::pt00x, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01C(BuiltInId::pt01C, +constexpr const TVariable kpt00y(BuiltInId::pt00y, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01D(BuiltInId::pt01D, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt01E( - BuiltInId::pt01E, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt01F( - BuiltInId::pt01F, +constexpr const TVariable kpt00z( + BuiltInId::pt00z, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01G(BuiltInId::pt01G, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt01H(BuiltInId::pt01H, +constexpr const TVariable kpt01A(BuiltInId::pt01A, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01I(BuiltInId::pt01I, +constexpr const TVariable kpt01B(BuiltInId::pt01B, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01J(BuiltInId::pt01J, +constexpr const TVariable kpt01C(BuiltInId::pt01C, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01K( - BuiltInId::pt01K, +constexpr const TVariable kpt01D( + BuiltInId::pt01D, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01L(BuiltInId::pt01L, +constexpr const TVariable kpt01E(BuiltInId::pt01E, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01M(BuiltInId::pt01M, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt01N( - BuiltInId::pt01N, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt01O( - BuiltInId::pt01O, +constexpr const TVariable kpt01F( + BuiltInId::pt01F, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01P(BuiltInId::pt01P, - BuiltInName::_empty, - SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, - StaticType::Get()); -constexpr const TVariable kpt01Q(BuiltInId::pt01Q, +constexpr const TVariable kpt01G(BuiltInId::pt01G, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01R( - BuiltInId::pt01R, +constexpr const TVariable kpt01H( + BuiltInId::pt01H, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01S( - BuiltInId::pt01S, +constexpr const TVariable kpt01I( + BuiltInId::pt01I, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01T( - BuiltInId::pt01T, +constexpr const TVariable kpt01J( + BuiltInId::pt01J, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01U(BuiltInId::pt01U, +constexpr const TVariable kpt01K(BuiltInId::pt01K, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01V( - BuiltInId::pt01V, +constexpr const TVariable kpt01L( + BuiltInId::pt01L, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -constexpr const TVariable kpt01W( - BuiltInId::pt01W, +constexpr const TVariable kpt01M( + BuiltInId::pt01M, BuiltInName::_empty, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, @@ -1323,16 +1315,6 @@ constexpr const TVariable kpt_o_30D(BuiltInId::pt_o_30D, std::array{{TExtension::UNDEFINED}}, StaticType::Get()); -const TVariable *angle_BaseInstance() -{ - return &kangle_BaseInstance; -} - -const TVariable *angle_BaseVertex() -{ - return &kangle_BaseVertex; -} - const TVariable *gl_BaseInstance() { return &kgl_BaseInstance; @@ -1368,6 +1350,11 @@ const TVariable *gl_FragDepth() return &kgl_FragDepth; } +const TVariable *gl_FragDepthEXT() +{ + return &kgl_FragDepthEXT; +} + const TVariable *gl_FrontFacing() { return &kgl_FrontFacing; @@ -1413,11 +1400,6 @@ const TVariable *gl_InvocationIDTCSES3_2() return &kgl_InvocationIDTCSES3_2; } -const TVariable *gl_LastFragColor() -{ - return &kgl_LastFragColor; -} - const TVariable *gl_LastFragColorARM() { return &kgl_LastFragColorARM; @@ -1523,6 +1505,26 @@ const TVariable *gl_Position() return &kgl_Position; } +const TVariable *gl_PositionGS() +{ + return &kgl_PositionGS; +} + +const TVariable *gl_PositionGSES3_2() +{ + return &kgl_PositionGSES3_2; +} + +const TVariable *gl_PositionTES() +{ + return &kgl_PositionTES; +} + +const TVariable *gl_PositionTESES3_2() +{ + return &kgl_PositionTESES3_2; +} + const TVariable *gl_PrimitiveID() { return &kgl_PrimitiveID; @@ -1573,6 +1575,16 @@ const TVariable *gl_PrimitiveIDTESES3_2() return &kgl_PrimitiveIDTESES3_2; } +const TVariable *gl_PrimitiveShadingRateEXT() +{ + return &kgl_PrimitiveShadingRateEXT; +} + +const TVariable *gl_PrimitiveShadingRateEXTGS() +{ + return &kgl_PrimitiveShadingRateEXTGS; +} + const TVariable *gl_SampleID() { return &kgl_SampleID; @@ -1598,6 +1610,11 @@ const TVariable *gl_SecondaryFragColorEXT() return &kgl_SecondaryFragColorEXT; } +const TVariable *gl_ShadingRateEXT() +{ + return &kgl_ShadingRateEXT; +} + const TVariable *gl_TessCoord() { return &kgl_TessCoord; @@ -1973,32 +1990,40 @@ constexpr const TVariable *p00h00C[2] = {&BuiltInVariable::kpt00h, &BuiltI constexpr const TVariable *p00h20B[2] = {&BuiltInVariable::kpt00h, &BuiltInVariable::kpt20B}; constexpr const TVariable *p00h30B00B00B[4] = {&BuiltInVariable::kpt00h, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00j00C[2] = {&BuiltInVariable::kpt00j, &BuiltInVariable::kpt00C}; constexpr const TVariable *p00k00C[2] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00l00C[2] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00l20B[2] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt20B}; -constexpr const TVariable *p00l30B00B[3] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt30B, +constexpr const TVariable *p00k20B[2] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00k30B00B[3] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00l30B00C[3] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt30B, +constexpr const TVariable *p00k30B00C[3] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00l30B20B20B[4] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt30B, +constexpr const TVariable *p00k30B20B20B[4] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00m00C[2] = {&BuiltInVariable::kpt00m, &BuiltInVariable::kpt00C}; constexpr const TVariable *p00n00C[2] = {&BuiltInVariable::kpt00n, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00o00C[2] = {&BuiltInVariable::kpt00o, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00o20B[2] = {&BuiltInVariable::kpt00o, &BuiltInVariable::kpt20B}; -constexpr const TVariable *p00o30B00B[3] = {&BuiltInVariable::kpt00o, &BuiltInVariable::kpt30B, +constexpr const TVariable *p00n20B[2] = {&BuiltInVariable::kpt00n, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00n30B00B[3] = {&BuiltInVariable::kpt00n, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00o30B00C[3] = {&BuiltInVariable::kpt00o, &BuiltInVariable::kpt30B, +constexpr const TVariable *p00n30B00C[3] = {&BuiltInVariable::kpt00n, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00o30B20B20B[4] = {&BuiltInVariable::kpt00o, &BuiltInVariable::kpt30B, +constexpr const TVariable *p00n30B20B20B[4] = {&BuiltInVariable::kpt00n, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; -constexpr const TVariable *p00p10B[2] = {&BuiltInVariable::kpt00p, &BuiltInVariable::kpt10B}; -constexpr const TVariable *p00q10C00B[3] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00o10B[2] = {&BuiltInVariable::kpt00o, &BuiltInVariable::kpt10B}; +constexpr const TVariable *p00p10C00B[3] = {&BuiltInVariable::kpt00p, &BuiltInVariable::kpt10C, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00p10C00C00C[4] = {&BuiltInVariable::kpt00p, &BuiltInVariable::kpt10C, + &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; +constexpr const TVariable *p00p10C00D00D[4] = {&BuiltInVariable::kpt00p, &BuiltInVariable::kpt10C, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00p10C30B[3] = {&BuiltInVariable::kpt00p, &BuiltInVariable::kpt10C, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p00q20C00B[3] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00q10C00C00C[4] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00q20C00C00C[4] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00q10C00D00D[4] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00q20C00D00D[4] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00q10C30B[3] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00q20C30B[3] = {&BuiltInVariable::kpt00q, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30B}; constexpr const TVariable *p00r20C00B[3] = {&BuiltInVariable::kpt00r, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; @@ -2024,190 +2049,116 @@ constexpr const TVariable *p00t20C00D00D[4] = {&BuiltInVariable::kpt00t, &BuiltI &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; constexpr const TVariable *p00t20C30B[3] = {&BuiltInVariable::kpt00t, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30B}; -constexpr const TVariable *p00u10C00C00B[4] = {&BuiltInVariable::kpt00u, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00u10C00C00C00C[5] = { - &BuiltInVariable::kpt00u, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00u10C00C00D00D[5] = { - &BuiltInVariable::kpt00u, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00v20C00C00B[4] = {&BuiltInVariable::kpt00v, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00v20C00C00C00C[5] = { - &BuiltInVariable::kpt00v, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00v20C00C00D00D[5] = { - &BuiltInVariable::kpt00v, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00w20C00B[3] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00w20C00C00C[4] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00w20C00D00D[4] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00w20C30B[3] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt30B}; -constexpr const TVariable *p00x10C00B[3] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00x10C00C00C[4] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00x10C00D00D[4] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00y00C00B[3] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt00C, +constexpr const TVariable *p00u00C00B[3] = {&BuiltInVariable::kpt00u, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00y00C00C00C[4] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt00C, +constexpr const TVariable *p00u00C00C00C[4] = {&BuiltInVariable::kpt00u, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00y00C00D00D[4] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt00C, +constexpr const TVariable *p00u00C00D00D[4] = {&BuiltInVariable::kpt00u, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00y00C30B[3] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt00C, +constexpr const TVariable *p00u00C30B[3] = {&BuiltInVariable::kpt00u, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt30B}; -constexpr const TVariable *p00z10C00B[3] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00v10C00B[3] = {&BuiltInVariable::kpt00v, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p00z10C00C00C[4] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00v10C00C00C[4] = {&BuiltInVariable::kpt00v, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p00z10C00D00D[4] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00v10C00D00D[4] = {&BuiltInVariable::kpt00v, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p00z10C30C[3] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10C, +constexpr const TVariable *p00v10C30C[3] = {&BuiltInVariable::kpt00v, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01A20C00B[3] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00w20C00B[3] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01A20C00C00C[4] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00w20C00C00C[4] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01A20C00D00D[4] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00w20C00D00D[4] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01A20C30C[3] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00w20C30C[3] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01B20C00B[3] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00x20C00B[3] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01B20C00C00C[4] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00x20C00C00C[4] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01B20C00D00D[4] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00x20C00D00D[4] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01B20C30C[3] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00x20C30C[3] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01C20C00B[3] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00y20C00B[3] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01C20C00C00C[4] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00y20C00C00C[4] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01C20C00D00D[4] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00y20C00D00D[4] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01C20C30C[3] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00y20C30C[3] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01D10C00C00B[4] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01D10C00C00C00C[5] = { - &BuiltInVariable::kpt01D, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01D10C00C00D00D[5] = { - &BuiltInVariable::kpt01D, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01E20C00C00B[4] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01E20C00C00C00C[5] = { - &BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01E20C00C00D00D[5] = { - &BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01F20C00B[3] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00z20C00B[3] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01F20C00C00C[4] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00z20C00C00C[4] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01F20C00D00D[4] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00z20C00D00D[4] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01F20C30C[3] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, +constexpr const TVariable *p00z20C30C[3] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01G10C00B[3] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01G10C00C00C[4] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01G10C00D00D[4] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01H00C00B[3] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01A00C00B[3] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01H00C00C00C[4] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01A00C00C00C[4] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01H00C00D00D[4] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01A00C00D00D[4] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01H00C30C[3] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01A00C30C[3] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01I10C00B[3] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10C, +constexpr const TVariable *p01B10C00B[3] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01I10C00C00C[4] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10C, +constexpr const TVariable *p01B10C00C00C[4] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01I10C00D00D[4] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10C, +constexpr const TVariable *p01B10C00D00D[4] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01I10C30D[3] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10C, +constexpr const TVariable *p01B10C30D[3] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01J20C00B[3] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01C20C00B[3] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01J20C00C00C[4] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01C20C00C00C[4] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01J20C00D00D[4] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01C20C00D00D[4] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01J20C30D[3] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01C20C30D[3] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01K20C00B[3] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01D20C00B[3] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01K20C00C00C[4] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01D20C00C00C[4] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01K20C00D00D[4] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01D20C00D00D[4] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01K20C30D[3] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01D20C30D[3] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01L20C00B[3] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01E20C00B[3] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01L20C00C00C[4] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01E20C00C00C[4] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01L20C00D00D[4] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01E20C00D00D[4] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01L20C30D[3] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01E20C30D[3] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01M10C00C00B[4] = {&BuiltInVariable::kpt01M, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01M10C00C00C00C[5] = { - &BuiltInVariable::kpt01M, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01M10C00C00D00D[5] = { - &BuiltInVariable::kpt01M, &BuiltInVariable::kpt10C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01N20C00C00B[4] = {&BuiltInVariable::kpt01N, &BuiltInVariable::kpt20C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01N20C00C00C00C[5] = { - &BuiltInVariable::kpt01N, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01N20C00C00D00D[5] = { - &BuiltInVariable::kpt01N, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01O20C00B[3] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01F20C00B[3] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01O20C00C00C[4] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01F20C00C00C[4] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01O20C00D00D[4] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01F20C00D00D[4] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01O20C30D[3] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt20C, +constexpr const TVariable *p01F20C30D[3] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt20C, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01P10C00B[3] = {&BuiltInVariable::kpt01P, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01P10C00C00C[4] = {&BuiltInVariable::kpt01P, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01P10C00D00D[4] = {&BuiltInVariable::kpt01P, &BuiltInVariable::kpt10C, - &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01Q00C00B[3] = {&BuiltInVariable::kpt01Q, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01G00C00B[3] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00B}; -constexpr const TVariable *p01Q00C00C00C[4] = {&BuiltInVariable::kpt01Q, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01G00C00C00C[4] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00C}; -constexpr const TVariable *p01Q00C00D00D[4] = {&BuiltInVariable::kpt01Q, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01G00C00D00D[4] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; -constexpr const TVariable *p01Q00C30D[3] = {&BuiltInVariable::kpt01Q, &BuiltInVariable::kpt00C, +constexpr const TVariable *p01G00C30D[3] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt00C, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01R30B[2] = {&BuiltInVariable::kpt01R, &BuiltInVariable::kpt30B}; -constexpr const TVariable *p01S30C[2] = {&BuiltInVariable::kpt01S, &BuiltInVariable::kpt30C}; -constexpr const TVariable *p01T30D[2] = {&BuiltInVariable::kpt01T, &BuiltInVariable::kpt30D}; -constexpr const TVariable *p01U[1] = {&BuiltInVariable::kpt01U}; -constexpr const TVariable *p01V[1] = {&BuiltInVariable::kpt01V}; -constexpr const TVariable *p01W[1] = {&BuiltInVariable::kpt01W}; +constexpr const TVariable *p01H30B[2] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01I30C[2] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt30C}; +constexpr const TVariable *p01J30D[2] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01K[1] = {&BuiltInVariable::kpt01K}; +constexpr const TVariable *p01L[1] = {&BuiltInVariable::kpt01L}; +constexpr const TVariable *p01M[1] = {&BuiltInVariable::kpt01M}; constexpr const TVariable *p10B00B00B[3] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B}; constexpr const TVariable *p10B00C[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt00C}; @@ -6536,11 +6487,11 @@ constexpr const TFunction textureCubeGradEXT_00J20B20B20B( StaticType::Get(), EOpTextureCubeGradEXT, true); -constexpr const TFunction textureVideoWEBGL_00p10B( +constexpr const TFunction textureVideoWEBGL_00o10B( BuiltInId::textureVideoWEBGL_SamplerVideoWEBGL1_Float2, BuiltInName::textureVideoWEBGL, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00p10B, + BuiltInParameters::p00o10B, 2, StaticType::Get(), EOpTextureVideoWEBGL, @@ -6817,18 +6768,18 @@ constexpr const TFunction texture_00g30B(BuiltInId::texture_SamplerCubeArray1_Fl StaticType::Get(), EOpTexture, true); -constexpr const TFunction texture_00l30B(BuiltInId::texture_ISamplerCubeArray1_Float4, +constexpr const TFunction texture_00k30B(BuiltInId::texture_ISamplerCubeArray1_Float4, BuiltInName::texture, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l30B00B, + BuiltInParameters::p00k30B00B, 2, StaticType::Get(), EOpTexture, true); -constexpr const TFunction texture_00o30B(BuiltInId::texture_USamplerCubeArray1_Float4, +constexpr const TFunction texture_00n30B(BuiltInId::texture_USamplerCubeArray1_Float4, BuiltInName::texture, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o30B00B, + BuiltInParameters::p00n30B00B, 2, StaticType::Get(), EOpTexture, @@ -6852,22 +6803,22 @@ constexpr const TFunction textureExt_00g30B( StaticType::Get(), EOpTexture, true); -constexpr const TFunction textureExt_00l30B( +constexpr const TFunction textureExt_00k30B( BuiltInId::textureExt_ISamplerCubeArray1_Float4, BuiltInName::textureExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l30B00B, + BuiltInParameters::p00k30B00B, 2, StaticType::Get(), EOpTexture, true); -constexpr const TFunction textureExt_00o30B( +constexpr const TFunction textureExt_00n30B( BuiltInId::textureExt_USamplerCubeArray1_Float4, BuiltInName::textureExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o30B00B, + BuiltInParameters::p00n30B00B, 2, StaticType::Get(), EOpTexture, @@ -6908,10 +6859,10 @@ constexpr const TFunction texture_00N10B(BuiltInId::texture_Sampler2DRect1_Float StaticType::Get(), EOpTexture, true); -constexpr const TFunction texture_00p10B(BuiltInId::texture_SamplerVideoWEBGL1_Float2, +constexpr const TFunction texture_00o10B(BuiltInId::texture_SamplerVideoWEBGL1_Float2, BuiltInName::texture, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00p10B, + BuiltInParameters::p00o10B, 2, StaticType::Get(), EOpTexture, @@ -7213,20 +7164,20 @@ constexpr const TFunction textureLod_00g30B00B( StaticType::Get(), EOpTextureLod, true); -constexpr const TFunction textureLod_00l30B00B( +constexpr const TFunction textureLod_00k30B00B( BuiltInId::textureLod_ISamplerCubeArray1_Float4_Float1, BuiltInName::textureLod, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l30B00B, + BuiltInParameters::p00k30B00B, 3, StaticType::Get(), EOpTextureLod, true); -constexpr const TFunction textureLod_00o30B00B( +constexpr const TFunction textureLod_00n30B00B( BuiltInId::textureLod_USamplerCubeArray1_Float4_Float1, BuiltInName::textureLod, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o30B00B, + BuiltInParameters::p00n30B00B, 3, StaticType::Get(), EOpTextureLod, @@ -7241,22 +7192,22 @@ constexpr const TFunction textureLodExt_00g30B00B( StaticType::Get(), EOpTextureLod, true); -constexpr const TFunction textureLodExt_00l30B00B( +constexpr const TFunction textureLodExt_00k30B00B( BuiltInId::textureLodExt_ISamplerCubeArray1_Float4_Float1, BuiltInName::textureLodExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l30B00B, + BuiltInParameters::p00k30B00B, 3, StaticType::Get(), EOpTextureLod, true); -constexpr const TFunction textureLodExt_00o30B00B( +constexpr const TFunction textureLodExt_00n30B00B( BuiltInId::textureLodExt_USamplerCubeArray1_Float4_Float1, BuiltInName::textureLodExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o30B00B, + BuiltInParameters::p00n30B00B, 3, StaticType::Get(), EOpTextureLod, @@ -7405,20 +7356,20 @@ constexpr const TFunction textureSize_00g00C( StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSize_00l00C( +constexpr const TFunction textureSize_00k00C( BuiltInId::textureSize_ISamplerCubeArray1_Int1, BuiltInName::textureSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l00C, + BuiltInParameters::p00k00C, 2, StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSize_00o00C( +constexpr const TFunction textureSize_00n00C( BuiltInId::textureSize_USamplerCubeArray1_Int1, BuiltInName::textureSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o00C, + BuiltInParameters::p00n00C, 2, StaticType::Get(), EOpTextureSize, @@ -7442,22 +7393,22 @@ constexpr const TFunction textureSizeExt_00g00C( StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSizeExt_00l00C( +constexpr const TFunction textureSizeExt_00k00C( BuiltInId::textureSizeExt_ISamplerCubeArray1_Int1, BuiltInName::textureSizeExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l00C, + BuiltInParameters::p00k00C, 2, StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSizeExt_00o00C( +constexpr const TFunction textureSizeExt_00n00C( BuiltInId::textureSizeExt_USamplerCubeArray1_Int1, BuiltInName::textureSizeExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o00C, + BuiltInParameters::p00n00C, 2, StaticType::Get(), EOpTextureSize, @@ -7480,18 +7431,18 @@ constexpr const TFunction textureSize_00f(BuiltInId::textureSize_SamplerBuffer1, StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSize_00k(BuiltInId::textureSize_ISamplerBuffer1, +constexpr const TFunction textureSize_00j(BuiltInId::textureSize_ISamplerBuffer1, BuiltInName::textureSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00k00C, + BuiltInParameters::p00j00C, 1, StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSize_00n(BuiltInId::textureSize_USamplerBuffer1, +constexpr const TFunction textureSize_00m(BuiltInId::textureSize_USamplerBuffer1, BuiltInName::textureSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00n00C, + BuiltInParameters::p00m00C, 1, StaticType::Get(), EOpTextureSize, @@ -7505,20 +7456,20 @@ constexpr const TFunction textureSizeExt_00f( StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSizeExt_00k( +constexpr const TFunction textureSizeExt_00j( BuiltInId::textureSizeExt_ISamplerBuffer1, BuiltInName::textureSizeExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00k00C, + BuiltInParameters::p00j00C, 1, StaticType::Get(), EOpTextureSize, true); -constexpr const TFunction textureSizeExt_00n( +constexpr const TFunction textureSizeExt_00m( BuiltInId::textureSizeExt_USamplerBuffer1, BuiltInName::textureSizeExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00n00C, + BuiltInParameters::p00m00C, 1, StaticType::Get(), EOpTextureSize, @@ -7823,20 +7774,20 @@ constexpr const TFunction texelFetch_00f00C( StaticType::Get(), EOpTexelFetch, true); -constexpr const TFunction texelFetch_00k00C( +constexpr const TFunction texelFetch_00j00C( BuiltInId::texelFetch_ISamplerBuffer1_Int1, BuiltInName::texelFetch, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00k00C, + BuiltInParameters::p00j00C, 2, StaticType::Get(), EOpTexelFetch, true); -constexpr const TFunction texelFetch_00n00C( +constexpr const TFunction texelFetch_00m00C( BuiltInId::texelFetch_USamplerBuffer1_Int1, BuiltInName::texelFetch, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00n00C, + BuiltInParameters::p00m00C, 2, StaticType::Get(), EOpTexelFetch, @@ -7850,20 +7801,20 @@ constexpr const TFunction texelFetchExt_00f00C( StaticType::Get(), EOpTexelFetch, true); -constexpr const TFunction texelFetchExt_00k00C( +constexpr const TFunction texelFetchExt_00j00C( BuiltInId::texelFetchExt_ISamplerBuffer1_Int1, BuiltInName::texelFetchExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00k00C, + BuiltInParameters::p00j00C, 2, StaticType::Get(), EOpTexelFetch, true); -constexpr const TFunction texelFetchExt_00n00C( +constexpr const TFunction texelFetchExt_00m00C( BuiltInId::texelFetchExt_USamplerBuffer1_Int1, BuiltInName::texelFetchExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00n00C, + BuiltInParameters::p00m00C, 2, StaticType::Get(), EOpTexelFetch, @@ -8138,20 +8089,20 @@ constexpr const TFunction textureGrad_00g30B20B20B( StaticType::Get(), EOpTextureGrad, true); -constexpr const TFunction textureGrad_00l30B20B20B( +constexpr const TFunction textureGrad_00k30B20B20B( BuiltInId::textureGrad_ISamplerCubeArray1_Float4_Float3_Float3, BuiltInName::textureGrad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l30B20B20B, + BuiltInParameters::p00k30B20B20B, 4, StaticType::Get(), EOpTextureGrad, true); -constexpr const TFunction textureGrad_00o30B20B20B( +constexpr const TFunction textureGrad_00n30B20B20B( BuiltInId::textureGrad_USamplerCubeArray1_Float4_Float3_Float3, BuiltInName::textureGrad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o30B20B20B, + BuiltInParameters::p00n30B20B20B, 4, StaticType::Get(), EOpTextureGrad, @@ -8166,22 +8117,22 @@ constexpr const TFunction textureGradExt_00g30B20B20B( StaticType::Get(), EOpTextureGrad, true); -constexpr const TFunction textureGradExt_00l30B20B20B( +constexpr const TFunction textureGradExt_00k30B20B20B( BuiltInId::textureGradExt_ISamplerCubeArray1_Float4_Float3_Float3, BuiltInName::textureGradExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l30B20B20B, + BuiltInParameters::p00k30B20B20B, 4, StaticType::Get(), EOpTextureGrad, true); -constexpr const TFunction textureGradExt_00o30B20B20B( +constexpr const TFunction textureGradExt_00n30B20B20B( BuiltInId::textureGradExt_USamplerCubeArray1_Float4_Float3_Float3, BuiltInName::textureGradExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o30B20B20B, + BuiltInParameters::p00n30B20B20B, 4, StaticType::Get(), EOpTextureGrad, @@ -8510,20 +8461,20 @@ constexpr const TFunction texture_00g30B00B( StaticType::Get(), EOpTextureBias, true); -constexpr const TFunction texture_00l30B00B( +constexpr const TFunction texture_00k30B00B( BuiltInId::texture_ISamplerCubeArray1_Float4_Float1, BuiltInName::texture, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l30B00B, + BuiltInParameters::p00k30B00B, 3, StaticType::Get(), EOpTextureBias, true); -constexpr const TFunction texture_00o30B00B( +constexpr const TFunction texture_00n30B00B( BuiltInId::texture_USamplerCubeArray1_Float4_Float1, BuiltInName::texture, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o30B00B, + BuiltInParameters::p00n30B00B, 3, StaticType::Get(), EOpTextureBias, @@ -8538,22 +8489,22 @@ constexpr const TFunction textureExt_00g30B00B( StaticType::Get(), EOpTextureBias, true); -constexpr const TFunction textureExt_00l30B00B( +constexpr const TFunction textureExt_00k30B00B( BuiltInId::textureExt_ISamplerCubeArray1_Float4_Float1, BuiltInName::textureExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l30B00B, + BuiltInParameters::p00k30B00B, 3, StaticType::Get(), EOpTextureBias, true); -constexpr const TFunction textureExt_00o30B00B( +constexpr const TFunction textureExt_00n30B00B( BuiltInId::textureExt_USamplerCubeArray1_Float4_Float1, BuiltInName::textureExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o30B00B, + BuiltInParameters::p00n30B00B, 3, StaticType::Get(), EOpTextureBias, @@ -9485,33 +9436,6 @@ constexpr const TFunction textureGather_00W10B( StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00H10B00C( - BuiltInId::textureGather_Sampler2D1_Float2_Int1, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00H10B00C, - 3, - StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00Q10B00C( - BuiltInId::textureGather_ISampler2D1_Float2_Int1, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00Q10B00C, - 3, - StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00W10B00C( - BuiltInId::textureGather_USampler2D1_Float2_Int1, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00W10B00C, - 3, - StaticType::Get(), - EOpTextureGather, - true); constexpr const TFunction textureGather_00K20B( BuiltInId::textureGather_Sampler2DArray1_Float3, BuiltInName::textureGather, @@ -9539,33 +9463,6 @@ constexpr const TFunction textureGather_00Z20B( StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00K20B00C( - BuiltInId::textureGather_Sampler2DArray1_Float3_Int1, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00K20B00C, - 3, - StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00T20B00C( - BuiltInId::textureGather_ISampler2DArray1_Float3_Int1, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00T20B00C, - 3, - StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00Z20B00C( - BuiltInId::textureGather_USampler2DArray1_Float3_Int1, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00Z20B00C, - 3, - StaticType::Get(), - EOpTextureGather, - true); constexpr const TFunction textureGather_00J20B( BuiltInId::textureGather_SamplerCube1_Float3, BuiltInName::textureGather, @@ -9593,125 +9490,170 @@ constexpr const TFunction textureGather_00Y20B( StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00J20B00C( - BuiltInId::textureGather_SamplerCube1_Float3_Int1, +constexpr const TFunction textureGather_00g30B( + BuiltInId::textureGather_SamplerCubeArray1_Float4, BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00J20B00C, - 3, + BuiltInParameters::p00g30B00B, + 2, StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00S20B00C( - BuiltInId::textureGather_ISamplerCube1_Float3_Int1, +constexpr const TFunction textureGather_00k30B( + BuiltInId::textureGather_ISamplerCubeArray1_Float4, BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00S20B00C, - 3, + BuiltInParameters::p00k30B00B, + 2, StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00Y20B00C( - BuiltInId::textureGather_USamplerCube1_Float3_Int1, +constexpr const TFunction textureGather_00n30B( + BuiltInId::textureGather_USamplerCubeArray1_Float4, BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00Y20B00C, - 3, + BuiltInParameters::p00n30B00B, + 2, StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00g30B( - BuiltInId::textureGather_SamplerCubeArray1_Float4, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, +constexpr const TFunction textureGatherExt_00g30B( + BuiltInId::textureGatherExt_SamplerCubeArray1_Float4, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, BuiltInParameters::p00g30B00B, 2, StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00l30B( - BuiltInId::textureGather_ISamplerCubeArray1_Float4, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l30B00B, +constexpr const TFunction textureGatherExt_00k30B( + BuiltInId::textureGatherExt_ISamplerCubeArray1_Float4, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B00B, 2, StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00o30B( - BuiltInId::textureGather_USamplerCubeArray1_Float4, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o30B00B, +constexpr const TFunction textureGatherExt_00n30B( + BuiltInId::textureGatherExt_USamplerCubeArray1_Float4, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00n30B00B, 2, StaticType::Get(), EOpTextureGather, true); -constexpr const TFunction textureGather_00g30B00C( - BuiltInId::textureGather_SamplerCubeArray1_Float4_Int1, - BuiltInName::textureGather, +constexpr const TFunction textureGather_00H10B00C( + BuiltInId::textureGather_Sampler2D1_Float2_Int1, + BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00g30B00C, + BuiltInParameters::p00H10B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGather_00l30B00C( - BuiltInId::textureGather_ISamplerCubeArray1_Float4_Int1, +constexpr const TFunction textureGather_00Q10B00C( + BuiltInId::textureGather_ISampler2D1_Float2_Int1, BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00l30B00C, + BuiltInParameters::p00Q10B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGather_00o30B00C( - BuiltInId::textureGather_USamplerCubeArray1_Float4_Int1, +constexpr const TFunction textureGather_00W10B00C( + BuiltInId::textureGather_USampler2D1_Float2_Int1, BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00o30B00C, + BuiltInParameters::p00W10B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGather_00h30B00B( - BuiltInId::textureGather_SamplerCubeArrayShadow1_Float4_Float1, +constexpr const TFunction textureGather_00K20B00C( + BuiltInId::textureGather_Sampler2DArray1_Float3_Int1, BuiltInName::textureGather, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00h30B00B00B, + BuiltInParameters::p00K20B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGatherExt_00g30B( - BuiltInId::textureGatherExt_SamplerCubeArray1_Float4, - BuiltInName::textureGatherExt, - std::array{ - {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00g30B00B, - 2, +constexpr const TFunction textureGather_00T20B00C( + BuiltInId::textureGather_ISampler2DArray1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B00C, + 3, + StaticType::Get(), + EOpTextureGatherComp, + true); +constexpr const TFunction textureGather_00Z20B00C( + BuiltInId::textureGather_USampler2DArray1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B00C, + 3, + StaticType::Get(), + EOpTextureGatherComp, + true); +constexpr const TFunction textureGather_00J20B00C( + BuiltInId::textureGather_SamplerCube1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B00C, + 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGatherExt_00l30B( - BuiltInId::textureGatherExt_ISamplerCubeArray1_Float4, - BuiltInName::textureGatherExt, - std::array{ - {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l30B00B, - 2, +constexpr const TFunction textureGather_00S20B00C( + BuiltInId::textureGather_ISamplerCube1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B00C, + 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGatherExt_00o30B( - BuiltInId::textureGatherExt_USamplerCubeArray1_Float4, - BuiltInName::textureGatherExt, - std::array{ - {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o30B00B, - 2, +constexpr const TFunction textureGather_00Y20B00C( + BuiltInId::textureGather_USamplerCube1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B00C, + 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, + true); +constexpr const TFunction textureGather_00g30B00C( + BuiltInId::textureGather_SamplerCubeArray1_Float4_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00g30B00C, + 3, + StaticType::Get(), + EOpTextureGatherComp, + true); +constexpr const TFunction textureGather_00k30B00C( + BuiltInId::textureGather_ISamplerCubeArray1_Float4_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B00C, + 3, + StaticType::Get(), + EOpTextureGatherComp, + true); +constexpr const TFunction textureGather_00n30B00C( + BuiltInId::textureGather_USamplerCubeArray1_Float4_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00n30B00C, + 3, + StaticType::Get(), + EOpTextureGatherComp, true); constexpr const TFunction textureGatherExt_00g30B00C( BuiltInId::textureGatherExt_SamplerCubeArray1_Float4_Int1, @@ -9721,27 +9663,36 @@ constexpr const TFunction textureGatherExt_00g30B00C( BuiltInParameters::p00g30B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGatherExt_00l30B00C( +constexpr const TFunction textureGatherExt_00k30B00C( BuiltInId::textureGatherExt_ISamplerCubeArray1_Float4_Int1, BuiltInName::textureGatherExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00l30B00C, + BuiltInParameters::p00k30B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, true); -constexpr const TFunction textureGatherExt_00o30B00C( +constexpr const TFunction textureGatherExt_00n30B00C( BuiltInId::textureGatherExt_USamplerCubeArray1_Float4_Int1, BuiltInName::textureGatherExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00o30B00C, + BuiltInParameters::p00n30B00C, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherComp, + true); +constexpr const TFunction textureGather_00h30B00B( + BuiltInId::textureGather_SamplerCubeArrayShadow1_Float4_Float1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00h30B00B00B, + 3, + StaticType::Get(), + EOpTextureGatherRef, true); constexpr const TFunction textureGatherExt_00h30B00B( BuiltInId::textureGatherExt_SamplerCubeArrayShadow1_Float4_Float1, @@ -9751,16 +9702,7 @@ constexpr const TFunction textureGatherExt_00h30B00B( BuiltInParameters::p00h30B00B00B, 3, StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00c10B( - BuiltInId::textureGather_Sampler2DShadow1_Float2, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00c10B00B10Cx4, - 2, - StaticType::Get(), - EOpTextureGather, + EOpTextureGatherRef, true); constexpr const TFunction textureGather_00c10B00B( BuiltInId::textureGather_Sampler2DShadow1_Float2_Float1, @@ -9769,16 +9711,7 @@ constexpr const TFunction textureGather_00c10B00B( BuiltInParameters::p00c10B00B10Cx4, 3, StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00e20B( - BuiltInId::textureGather_Sampler2DArrayShadow1_Float3, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00e20B00B10Cx4, - 2, - StaticType::Get(), - EOpTextureGather, + EOpTextureGatherRef, true); constexpr const TFunction textureGather_00e20B00B( BuiltInId::textureGather_Sampler2DArrayShadow1_Float3_Float1, @@ -9787,16 +9720,7 @@ constexpr const TFunction textureGather_00e20B00B( BuiltInParameters::p00e20B00B10Cx4, 3, StaticType::Get(), - EOpTextureGather, - true); -constexpr const TFunction textureGather_00d20B( - BuiltInId::textureGather_SamplerCubeShadow1_Float3, - BuiltInName::textureGather, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00d20B00B, - 2, - StaticType::Get(), - EOpTextureGather, + EOpTextureGatherRef, true); constexpr const TFunction textureGather_00d20B00B( BuiltInId::textureGather_SamplerCubeShadow1_Float3_Float1, @@ -9805,7 +9729,7 @@ constexpr const TFunction textureGather_00d20B00B( BuiltInParameters::p00d20B00B, 3, StaticType::Get(), - EOpTextureGather, + EOpTextureGatherRef, true); constexpr const TFunction textureGatherOffset_00H10B10C( BuiltInId::textureGatherOffset_Sampler2D1_Float2_Int2, @@ -9861,24 +9785,6 @@ constexpr const TFunction textureGatherOffset_00Z20B10C( StaticType::Get(), EOpTextureGatherOffset, true); -constexpr const TFunction textureGatherOffset_00c10B00B10C( - BuiltInId::textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2, - BuiltInName::textureGatherOffset, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00c10B00B10Cx4, - 4, - StaticType::Get(), - EOpTextureGatherOffset, - true); -constexpr const TFunction textureGatherOffset_00e20B00B10C( - BuiltInId::textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2, - BuiltInName::textureGatherOffset, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00e20B00B10Cx4, - 4, - StaticType::Get(), - EOpTextureGatherOffset, - true); constexpr const TFunction textureGatherOffset_00H10B10C00C( BuiltInId::textureGatherOffset_Sampler2D1_Float2_Int2_Int1, BuiltInName::textureGatherOffset, @@ -9933,6 +9839,24 @@ constexpr const TFunction textureGatherOffset_00Z20B10C00C( StaticType::Get(), EOpTextureGatherOffsetComp, true); +constexpr const TFunction textureGatherOffset_00c10B00B10C( + BuiltInId::textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00c10B00B10Cx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsetRef, + true); +constexpr const TFunction textureGatherOffset_00e20B00B10C( + BuiltInId::textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e20B00B10Cx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsetRef, + true); constexpr const TFunction textureGatherOffsets_00H10B10Cx4( BuiltInId::textureGatherOffsets_Sampler2D1_Float2_4xInt2, BuiltInName::textureGatherOffsets, @@ -9987,24 +9911,6 @@ constexpr const TFunction textureGatherOffsets_00Z20B10Cx4( StaticType::Get(), EOpTextureGatherOffsets, true); -constexpr const TFunction textureGatherOffsets_00c10B00B10Cx4( - BuiltInId::textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2, - BuiltInName::textureGatherOffsets, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00c10B00B10Cx4, - 4, - StaticType::Get(), - EOpTextureGatherOffsets, - true); -constexpr const TFunction textureGatherOffsets_00e20B00B10Cx4( - BuiltInId::textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2, - BuiltInName::textureGatherOffsets, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00e20B00B10Cx4, - 4, - StaticType::Get(), - EOpTextureGatherOffsets, - true); constexpr const TFunction textureGatherOffsetsExt_00H10B10Cx4( BuiltInId::textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2, BuiltInName::textureGatherOffsetsExt, @@ -10059,24 +9965,6 @@ constexpr const TFunction textureGatherOffsetsExt_00Z20B10Cx4( StaticType::Get(), EOpTextureGatherOffsets, true); -constexpr const TFunction textureGatherOffsetsExt_00c10B00B10Cx4( - BuiltInId::textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2, - BuiltInName::textureGatherOffsetsExt, - std::array{{TExtension::EXT_gpu_shader5, TExtension::OES_gpu_shader5}}, - BuiltInParameters::p00c10B00B10Cx4, - 4, - StaticType::Get(), - EOpTextureGatherOffsets, - true); -constexpr const TFunction textureGatherOffsetsExt_00e20B00B10Cx4( - BuiltInId::textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2, - BuiltInName::textureGatherOffsetsExt, - std::array{{TExtension::EXT_gpu_shader5, TExtension::OES_gpu_shader5}}, - BuiltInParameters::p00e20B00B10Cx4, - 4, - StaticType::Get(), - EOpTextureGatherOffsets, - true); constexpr const TFunction textureGatherOffsets_00H10B10Cx400C( BuiltInId::textureGatherOffsets_Sampler2D1_Float2_4xInt2_Int1, BuiltInName::textureGatherOffsets, @@ -10185,6 +10073,42 @@ constexpr const TFunction textureGatherOffsetsExt_00Z20B10Cx400C( StaticType::Get(), EOpTextureGatherOffsetsComp, true); +constexpr const TFunction textureGatherOffsets_00c10B00B10Cx4( + BuiltInId::textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00c10B00B10Cx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsRef, + true); +constexpr const TFunction textureGatherOffsets_00e20B00B10Cx4( + BuiltInId::textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e20B00B10Cx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsRef, + true); +constexpr const TFunction textureGatherOffsetsExt_00c10B00B10Cx4( + BuiltInId::textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5, TExtension::OES_gpu_shader5}}, + BuiltInParameters::p00c10B00B10Cx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsRef, + true); +constexpr const TFunction textureGatherOffsetsExt_00e20B00B10Cx4( + BuiltInId::textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5, TExtension::OES_gpu_shader5}}, + BuiltInParameters::p00e20B00B10Cx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsRef, + true); constexpr const TFunction textureQueryLOD_00H10B( BuiltInId::textureQueryLOD_Sampler2D1_Float2, BuiltInName::textureQueryLOD, @@ -10329,20 +10253,20 @@ constexpr const TFunction textureQueryLOD_00g20B( StaticType::Get(), EOpTextureQueryLOD, true); -constexpr const TFunction textureQueryLOD_00l20B( +constexpr const TFunction textureQueryLOD_00k20B( BuiltInId::textureQueryLOD_ISamplerCubeArray1_Float3, BuiltInName::textureQueryLOD, std::array{{TExtension::EXT_texture_query_lod}}, - BuiltInParameters::p00l20B, + BuiltInParameters::p00k20B, 2, StaticType::Get(), EOpTextureQueryLOD, true); -constexpr const TFunction textureQueryLOD_00o20B( +constexpr const TFunction textureQueryLOD_00n20B( BuiltInId::textureQueryLOD_USamplerCubeArray1_Float3, BuiltInName::textureQueryLOD, std::array{{TExtension::EXT_texture_query_lod}}, - BuiltInParameters::p00o20B, + BuiltInParameters::p00n20B, 2, StaticType::Get(), EOpTextureQueryLOD, @@ -10958,8951 +10882,6197 @@ constexpr const TFunction atomicCompSwap_00C00C00C( StaticType::Get(), EOpAtomicCompSwap, false); -constexpr const TFunction imageSize_00q(BuiltInId::imageSize_Image2D1, +constexpr const TFunction imageSize_00p(BuiltInId::imageSize_Image2D1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00B, + BuiltInParameters::p00p10C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_00z(BuiltInId::imageSize_IImage2D1, +constexpr const TFunction imageSize_00v(BuiltInId::imageSize_IImage2D1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00B, + BuiltInParameters::p00v10C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01I(BuiltInId::imageSize_UImage2D1, +constexpr const TFunction imageSize_01B(BuiltInId::imageSize_UImage2D1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00B, + BuiltInParameters::p01B10C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_00r(BuiltInId::imageSize_Image3D1, +constexpr const TFunction imageSize_00q(BuiltInId::imageSize_Image3D1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00B, + BuiltInParameters::p00q20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01A(BuiltInId::imageSize_IImage3D1, +constexpr const TFunction imageSize_00w(BuiltInId::imageSize_IImage3D1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00B, + BuiltInParameters::p00w20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01J(BuiltInId::imageSize_UImage3D1, +constexpr const TFunction imageSize_01C(BuiltInId::imageSize_UImage3D1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00B, + BuiltInParameters::p01C20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_00s(BuiltInId::imageSize_Image2DArray1, +constexpr const TFunction imageSize_00r(BuiltInId::imageSize_Image2DArray1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00B, + BuiltInParameters::p00r20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01B(BuiltInId::imageSize_IImage2DArray1, +constexpr const TFunction imageSize_00x(BuiltInId::imageSize_IImage2DArray1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00B, + BuiltInParameters::p00x20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01K(BuiltInId::imageSize_UImage2DArray1, +constexpr const TFunction imageSize_01D(BuiltInId::imageSize_UImage2DArray1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00B, + BuiltInParameters::p01D20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_00t(BuiltInId::imageSize_ImageCube1, +constexpr const TFunction imageSize_00s(BuiltInId::imageSize_ImageCube1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00B, + BuiltInParameters::p00s20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01C(BuiltInId::imageSize_IImageCube1, +constexpr const TFunction imageSize_00y(BuiltInId::imageSize_IImageCube1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00B, + BuiltInParameters::p00y20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01L(BuiltInId::imageSize_UImageCube1, +constexpr const TFunction imageSize_01E(BuiltInId::imageSize_UImageCube1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00B, + BuiltInParameters::p01E20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_00w(BuiltInId::imageSize_ImageCubeArray1, +constexpr const TFunction imageSize_00t(BuiltInId::imageSize_ImageCubeArray1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00B, + BuiltInParameters::p00t20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01F(BuiltInId::imageSize_IImageCubeArray1, +constexpr const TFunction imageSize_00z(BuiltInId::imageSize_IImageCubeArray1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00B, + BuiltInParameters::p00z20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01O(BuiltInId::imageSize_UImageCubeArray1, +constexpr const TFunction imageSize_01F(BuiltInId::imageSize_UImageCubeArray1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00B, + BuiltInParameters::p01F20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSizeExt_00w(BuiltInId::imageSizeExt_ImageCubeArray1, +constexpr const TFunction imageSizeExt_00t(BuiltInId::imageSizeExt_ImageCubeArray1, BuiltInName::imageSizeExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00w20C00B, + BuiltInParameters::p00t20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSizeExt_01F(BuiltInId::imageSizeExt_IImageCubeArray1, +constexpr const TFunction imageSizeExt_00z(BuiltInId::imageSizeExt_IImageCubeArray1, BuiltInName::imageSizeExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p01F20C00B, + BuiltInParameters::p00z20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSizeExt_01O(BuiltInId::imageSizeExt_UImageCubeArray1, +constexpr const TFunction imageSizeExt_01F(BuiltInId::imageSizeExt_UImageCubeArray1, BuiltInName::imageSizeExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p01O20C00B, + BuiltInParameters::p01F20C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_00y(BuiltInId::imageSize_ImageBuffer1, +constexpr const TFunction imageSize_00u(BuiltInId::imageSize_ImageBuffer1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00B, + BuiltInParameters::p00u00C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01H(BuiltInId::imageSize_IImageBuffer1, +constexpr const TFunction imageSize_01A(BuiltInId::imageSize_IImageBuffer1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00B, + BuiltInParameters::p01A00C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSize_01Q(BuiltInId::imageSize_UImageBuffer1, +constexpr const TFunction imageSize_01G(BuiltInId::imageSize_UImageBuffer1, BuiltInName::imageSize, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00B, + BuiltInParameters::p01G00C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSizeExt_00y( +constexpr const TFunction imageSizeExt_00u( BuiltInId::imageSizeExt_ImageBuffer1, BuiltInName::imageSizeExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00y00C00B, + BuiltInParameters::p00u00C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSizeExt_01H( +constexpr const TFunction imageSizeExt_01A( BuiltInId::imageSizeExt_IImageBuffer1, BuiltInName::imageSizeExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p01H00C00B, + BuiltInParameters::p01A00C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageSizeExt_01Q( +constexpr const TFunction imageSizeExt_01G( BuiltInId::imageSizeExt_UImageBuffer1, BuiltInName::imageSizeExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p01Q00C00B, + BuiltInParameters::p01G00C00B, 1, StaticType::Get(), EOpImageSize, true); -constexpr const TFunction imageStore_00q10C30B( +constexpr const TFunction imageStore_00p10C30B( BuiltInId::imageStore_Image2D1_Int2_Float4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C30B, + BuiltInParameters::p00p10C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_00z10C30C( +constexpr const TFunction imageStore_00v10C30C( BuiltInId::imageStore_IImage2D1_Int2_Int4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C30C, + BuiltInParameters::p00v10C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01I10C30D( +constexpr const TFunction imageStore_01B10C30D( BuiltInId::imageStore_UImage2D1_Int2_UInt4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C30D, + BuiltInParameters::p01B10C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_00r20C30B( +constexpr const TFunction imageStore_00q20C30B( BuiltInId::imageStore_Image3D1_Int3_Float4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C30B, + BuiltInParameters::p00q20C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01A20C30C( +constexpr const TFunction imageStore_00w20C30C( BuiltInId::imageStore_IImage3D1_Int3_Int4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C30C, + BuiltInParameters::p00w20C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01J20C30D( +constexpr const TFunction imageStore_01C20C30D( BuiltInId::imageStore_UImage3D1_Int3_UInt4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C30D, + BuiltInParameters::p01C20C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_00s20C30B( +constexpr const TFunction imageStore_00r20C30B( BuiltInId::imageStore_Image2DArray1_Int3_Float4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C30B, + BuiltInParameters::p00r20C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01B20C30C( +constexpr const TFunction imageStore_00x20C30C( BuiltInId::imageStore_IImage2DArray1_Int3_Int4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C30C, + BuiltInParameters::p00x20C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01K20C30D( +constexpr const TFunction imageStore_01D20C30D( BuiltInId::imageStore_UImage2DArray1_Int3_UInt4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C30D, + BuiltInParameters::p01D20C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_00t20C30B( +constexpr const TFunction imageStore_00s20C30B( BuiltInId::imageStore_ImageCube1_Int3_Float4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C30B, + BuiltInParameters::p00s20C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01C20C30C( +constexpr const TFunction imageStore_00y20C30C( BuiltInId::imageStore_IImageCube1_Int3_Int4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C30C, + BuiltInParameters::p00y20C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01L20C30D( +constexpr const TFunction imageStore_01E20C30D( BuiltInId::imageStore_UImageCube1_Int3_UInt4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C30D, + BuiltInParameters::p01E20C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_00w20C30B( +constexpr const TFunction imageStore_00t20C30B( BuiltInId::imageStore_ImageCubeArray1_Int3_Float4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C30B, + BuiltInParameters::p00t20C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01F20C30C( +constexpr const TFunction imageStore_00z20C30C( BuiltInId::imageStore_IImageCubeArray1_Int3_Int4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C30C, + BuiltInParameters::p00z20C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01O20C30D( +constexpr const TFunction imageStore_01F20C30D( BuiltInId::imageStore_UImageCubeArray1_Int3_UInt4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C30D, + BuiltInParameters::p01F20C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStoreExt_00w20C30B( +constexpr const TFunction imageStoreExt_00t20C30B( BuiltInId::imageStoreExt_ImageCubeArray1_Int3_Float4, BuiltInName::imageStoreExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00w20C30B, + BuiltInParameters::p00t20C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStoreExt_01F20C30C( +constexpr const TFunction imageStoreExt_00z20C30C( BuiltInId::imageStoreExt_IImageCubeArray1_Int3_Int4, BuiltInName::imageStoreExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p01F20C30C, + BuiltInParameters::p00z20C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStoreExt_01O20C30D( +constexpr const TFunction imageStoreExt_01F20C30D( BuiltInId::imageStoreExt_UImageCubeArray1_Int3_UInt4, BuiltInName::imageStoreExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p01O20C30D, + BuiltInParameters::p01F20C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_00y00C30B( +constexpr const TFunction imageStore_00u00C30B( BuiltInId::imageStore_ImageBuffer1_Int1_Float4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C30B, + BuiltInParameters::p00u00C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01H00C30C( +constexpr const TFunction imageStore_01A00C30C( BuiltInId::imageStore_IImageBuffer1_Int1_Int4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C30C, + BuiltInParameters::p01A00C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStore_01Q00C30D( +constexpr const TFunction imageStore_01G00C30D( BuiltInId::imageStore_UImageBuffer1_Int1_UInt4, BuiltInName::imageStore, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C30D, + BuiltInParameters::p01G00C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStoreExt_00y00C30B( +constexpr const TFunction imageStoreExt_00u00C30B( BuiltInId::imageStoreExt_ImageBuffer1_Int1_Float4, BuiltInName::imageStoreExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00y00C30B, + BuiltInParameters::p00u00C30B, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStoreExt_01H00C30C( +constexpr const TFunction imageStoreExt_01A00C30C( BuiltInId::imageStoreExt_IImageBuffer1_Int1_Int4, BuiltInName::imageStoreExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p01H00C30C, + BuiltInParameters::p01A00C30C, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageStoreExt_01Q00C30D( +constexpr const TFunction imageStoreExt_01G00C30D( BuiltInId::imageStoreExt_UImageBuffer1_Int1_UInt4, BuiltInName::imageStoreExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p01Q00C30D, + BuiltInParameters::p01G00C30D, 3, StaticType::Get(), EOpImageStore, false); -constexpr const TFunction imageLoad_00q10C( +constexpr const TFunction imageLoad_00p10C( BuiltInId::imageLoad_Image2D1_Int2, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00B, + BuiltInParameters::p00p10C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_00z10C(BuiltInId::imageLoad_IImage2D1_Int2, +constexpr const TFunction imageLoad_00v10C(BuiltInId::imageLoad_IImage2D1_Int2, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00B, + BuiltInParameters::p00v10C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01I10C( +constexpr const TFunction imageLoad_01B10C( BuiltInId::imageLoad_UImage2D1_Int2, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00B, + BuiltInParameters::p01B10C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_00r20C( +constexpr const TFunction imageLoad_00q20C( BuiltInId::imageLoad_Image3D1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00B, + BuiltInParameters::p00q20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01A20C(BuiltInId::imageLoad_IImage3D1_Int3, +constexpr const TFunction imageLoad_00w20C(BuiltInId::imageLoad_IImage3D1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00B, + BuiltInParameters::p00w20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01J20C( +constexpr const TFunction imageLoad_01C20C( BuiltInId::imageLoad_UImage3D1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00B, + BuiltInParameters::p01C20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_00s20C( +constexpr const TFunction imageLoad_00r20C( BuiltInId::imageLoad_Image2DArray1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00B, + BuiltInParameters::p00r20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01B20C(BuiltInId::imageLoad_IImage2DArray1_Int3, +constexpr const TFunction imageLoad_00x20C(BuiltInId::imageLoad_IImage2DArray1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00B, + BuiltInParameters::p00x20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01K20C( +constexpr const TFunction imageLoad_01D20C( BuiltInId::imageLoad_UImage2DArray1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00B, + BuiltInParameters::p01D20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_00t20C( +constexpr const TFunction imageLoad_00s20C( BuiltInId::imageLoad_ImageCube1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00B, + BuiltInParameters::p00s20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01C20C(BuiltInId::imageLoad_IImageCube1_Int3, +constexpr const TFunction imageLoad_00y20C(BuiltInId::imageLoad_IImageCube1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00B, + BuiltInParameters::p00y20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01L20C( +constexpr const TFunction imageLoad_01E20C( BuiltInId::imageLoad_UImageCube1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00B, + BuiltInParameters::p01E20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_00w20C( +constexpr const TFunction imageLoad_00t20C( BuiltInId::imageLoad_ImageCubeArray1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00B, + BuiltInParameters::p00t20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01F20C(BuiltInId::imageLoad_IImageCubeArray1_Int3, +constexpr const TFunction imageLoad_00z20C(BuiltInId::imageLoad_IImageCubeArray1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00B, + BuiltInParameters::p00z20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01O20C( +constexpr const TFunction imageLoad_01F20C( BuiltInId::imageLoad_UImageCubeArray1_Int3, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00B, + BuiltInParameters::p01F20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoadExt_00w20C( +constexpr const TFunction imageLoadExt_00t20C( BuiltInId::imageLoadExt_ImageCubeArray1_Int3, BuiltInName::imageLoadExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p00w20C00B, + BuiltInParameters::p00t20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoadExt_01F20C( +constexpr const TFunction imageLoadExt_00z20C( BuiltInId::imageLoadExt_IImageCubeArray1_Int3, BuiltInName::imageLoadExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p01F20C00B, + BuiltInParameters::p00z20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoadExt_01O20C( +constexpr const TFunction imageLoadExt_01F20C( BuiltInId::imageLoadExt_UImageCubeArray1_Int3, BuiltInName::imageLoadExt, std::array{ {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, - BuiltInParameters::p01O20C00B, + BuiltInParameters::p01F20C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_00y00C( +constexpr const TFunction imageLoad_00u00C( BuiltInId::imageLoad_ImageBuffer1_Int1, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00B, + BuiltInParameters::p00u00C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01H00C(BuiltInId::imageLoad_IImageBuffer1_Int1, +constexpr const TFunction imageLoad_01A00C(BuiltInId::imageLoad_IImageBuffer1_Int1, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00B, + BuiltInParameters::p01A00C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoad_01Q00C( +constexpr const TFunction imageLoad_01G00C( BuiltInId::imageLoad_UImageBuffer1_Int1, BuiltInName::imageLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00B, + BuiltInParameters::p01G00C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoadExt_00y00C( +constexpr const TFunction imageLoadExt_00u00C( BuiltInId::imageLoadExt_ImageBuffer1_Int1, BuiltInName::imageLoadExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p00y00C00B, + BuiltInParameters::p00u00C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoadExt_01H00C( +constexpr const TFunction imageLoadExt_01A00C( BuiltInId::imageLoadExt_IImageBuffer1_Int1, BuiltInName::imageLoadExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p01H00C00B, + BuiltInParameters::p01A00C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageLoadExt_01Q00C( +constexpr const TFunction imageLoadExt_01G00C( BuiltInId::imageLoadExt_UImageBuffer1_Int1, BuiltInName::imageLoadExt, std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, - BuiltInParameters::p01Q00C00B, + BuiltInParameters::p01G00C00B, 2, StaticType::Get(), EOpImageLoad, true); -constexpr const TFunction imageAtomicAdd_00q10C00D( +constexpr const TFunction imageAtomicAdd_00p10C00D( BuiltInId::imageAtomicAdd_Image2D1_Int2_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00z10C00D( +constexpr const TFunction imageAtomicAdd_00v10C00D( BuiltInId::imageAtomicAdd_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01I10C00D( +constexpr const TFunction imageAtomicAdd_01B10C00D( BuiltInId::imageAtomicAdd_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00r20C00D( +constexpr const TFunction imageAtomicAdd_00q20C00D( BuiltInId::imageAtomicAdd_Image3D1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01A20C00D( +constexpr const TFunction imageAtomicAdd_00w20C00D( BuiltInId::imageAtomicAdd_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01J20C00D( +constexpr const TFunction imageAtomicAdd_01C20C00D( BuiltInId::imageAtomicAdd_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00t20C00D( +constexpr const TFunction imageAtomicAdd_00s20C00D( BuiltInId::imageAtomicAdd_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01C20C00D( +constexpr const TFunction imageAtomicAdd_00y20C00D( BuiltInId::imageAtomicAdd_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01L20C00D( +constexpr const TFunction imageAtomicAdd_01E20C00D( BuiltInId::imageAtomicAdd_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00y00C00D( +constexpr const TFunction imageAtomicAdd_00u00C00D( BuiltInId::imageAtomicAdd_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01H00C00D( +constexpr const TFunction imageAtomicAdd_01A00C00D( BuiltInId::imageAtomicAdd_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01Q00C00D( +constexpr const TFunction imageAtomicAdd_01G00C00D( BuiltInId::imageAtomicAdd_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00s20C00D( +constexpr const TFunction imageAtomicAdd_00r20C00D( BuiltInId::imageAtomicAdd_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01B20C00D( +constexpr const TFunction imageAtomicAdd_00x20C00D( BuiltInId::imageAtomicAdd_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01K20C00D( +constexpr const TFunction imageAtomicAdd_01D20C00D( BuiltInId::imageAtomicAdd_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00w20C00D( +constexpr const TFunction imageAtomicAdd_00t20C00D( BuiltInId::imageAtomicAdd_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01F20C00D( +constexpr const TFunction imageAtomicAdd_00z20C00D( BuiltInId::imageAtomicAdd_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01O20C00D( +constexpr const TFunction imageAtomicAdd_01F20C00D( BuiltInId::imageAtomicAdd_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_00x10C00D( - BuiltInId::imageAtomicAdd_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01G10C00D( - BuiltInId::imageAtomicAdd_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01P10C00D( - BuiltInId::imageAtomicAdd_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00u10C00C00D( - BuiltInId::imageAtomicAdd_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01D10C00C00D( - BuiltInId::imageAtomicAdd_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01M10C00C00D( - BuiltInId::imageAtomicAdd_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_00v20C00C00D( - BuiltInId::imageAtomicAdd_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01E20C00C00D( - BuiltInId::imageAtomicAdd_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01N20C00C00D( - BuiltInId::imageAtomicAdd_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_00q10C00C( +constexpr const TFunction imageAtomicAdd_00p10C00C( BuiltInId::imageAtomicAdd_Image2D1_Int2_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00z10C00C( +constexpr const TFunction imageAtomicAdd_00v10C00C( BuiltInId::imageAtomicAdd_IImage2D1_Int2_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01I10C00C( +constexpr const TFunction imageAtomicAdd_01B10C00C( BuiltInId::imageAtomicAdd_UImage2D1_Int2_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00r20C00C( +constexpr const TFunction imageAtomicAdd_00q20C00C( BuiltInId::imageAtomicAdd_Image3D1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01A20C00C( +constexpr const TFunction imageAtomicAdd_00w20C00C( BuiltInId::imageAtomicAdd_IImage3D1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01J20C00C( +constexpr const TFunction imageAtomicAdd_01C20C00C( BuiltInId::imageAtomicAdd_UImage3D1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00t20C00C( +constexpr const TFunction imageAtomicAdd_00s20C00C( BuiltInId::imageAtomicAdd_ImageCube1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01C20C00C( +constexpr const TFunction imageAtomicAdd_00y20C00C( BuiltInId::imageAtomicAdd_IImageCube1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01L20C00C( +constexpr const TFunction imageAtomicAdd_01E20C00C( BuiltInId::imageAtomicAdd_UImageCube1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00y00C00C( +constexpr const TFunction imageAtomicAdd_00u00C00C( BuiltInId::imageAtomicAdd_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01H00C00C( +constexpr const TFunction imageAtomicAdd_01A00C00C( BuiltInId::imageAtomicAdd_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01Q00C00C( +constexpr const TFunction imageAtomicAdd_01G00C00C( BuiltInId::imageAtomicAdd_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00s20C00C( +constexpr const TFunction imageAtomicAdd_00r20C00C( BuiltInId::imageAtomicAdd_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01B20C00C( +constexpr const TFunction imageAtomicAdd_00x20C00C( BuiltInId::imageAtomicAdd_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01K20C00C( +constexpr const TFunction imageAtomicAdd_01D20C00C( BuiltInId::imageAtomicAdd_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00w20C00C( +constexpr const TFunction imageAtomicAdd_00t20C00C( BuiltInId::imageAtomicAdd_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01F20C00C( +constexpr const TFunction imageAtomicAdd_00z20C00C( BuiltInId::imageAtomicAdd_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_01O20C00C( +constexpr const TFunction imageAtomicAdd_01F20C00C( BuiltInId::imageAtomicAdd_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAdd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_00x10C00C( - BuiltInId::imageAtomicAdd_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01G10C00C( - BuiltInId::imageAtomicAdd_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01P10C00C( - BuiltInId::imageAtomicAdd_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAdd_00u10C00C00C( - BuiltInId::imageAtomicAdd_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01D10C00C00C( - BuiltInId::imageAtomicAdd_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01M10C00C00C( - BuiltInId::imageAtomicAdd_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_00v20C00C00C( - BuiltInId::imageAtomicAdd_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01E20C00C00C( - BuiltInId::imageAtomicAdd_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAdd_01N20C00C00C( - BuiltInId::imageAtomicAdd_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAdd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicMin_00q10C00D( +constexpr const TFunction imageAtomicMin_00p10C00D( BuiltInId::imageAtomicMin_Image2D1_Int2_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00z10C00D( +constexpr const TFunction imageAtomicMin_00v10C00D( BuiltInId::imageAtomicMin_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01I10C00D( +constexpr const TFunction imageAtomicMin_01B10C00D( BuiltInId::imageAtomicMin_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00r20C00D( +constexpr const TFunction imageAtomicMin_00q20C00D( BuiltInId::imageAtomicMin_Image3D1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01A20C00D( +constexpr const TFunction imageAtomicMin_00w20C00D( BuiltInId::imageAtomicMin_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01J20C00D( +constexpr const TFunction imageAtomicMin_01C20C00D( BuiltInId::imageAtomicMin_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00t20C00D( +constexpr const TFunction imageAtomicMin_00s20C00D( BuiltInId::imageAtomicMin_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01C20C00D( +constexpr const TFunction imageAtomicMin_00y20C00D( BuiltInId::imageAtomicMin_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01L20C00D( +constexpr const TFunction imageAtomicMin_01E20C00D( BuiltInId::imageAtomicMin_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00y00C00D( +constexpr const TFunction imageAtomicMin_00u00C00D( BuiltInId::imageAtomicMin_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01H00C00D( +constexpr const TFunction imageAtomicMin_01A00C00D( BuiltInId::imageAtomicMin_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01Q00C00D( +constexpr const TFunction imageAtomicMin_01G00C00D( BuiltInId::imageAtomicMin_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00s20C00D( +constexpr const TFunction imageAtomicMin_00r20C00D( BuiltInId::imageAtomicMin_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01B20C00D( +constexpr const TFunction imageAtomicMin_00x20C00D( BuiltInId::imageAtomicMin_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01K20C00D( +constexpr const TFunction imageAtomicMin_01D20C00D( BuiltInId::imageAtomicMin_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00w20C00D( +constexpr const TFunction imageAtomicMin_00t20C00D( BuiltInId::imageAtomicMin_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01F20C00D( +constexpr const TFunction imageAtomicMin_00z20C00D( BuiltInId::imageAtomicMin_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01O20C00D( +constexpr const TFunction imageAtomicMin_01F20C00D( BuiltInId::imageAtomicMin_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00x10C00D( - BuiltInId::imageAtomicMin_ImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicMin_00p10C00C( + BuiltInId::imageAtomicMin_Image2D1_Int2_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, + BuiltInParameters::p00p10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01G10C00D( - BuiltInId::imageAtomicMin_IImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicMin_00v10C00C( + BuiltInId::imageAtomicMin_IImage2D1_Int2_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, + BuiltInParameters::p00v10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01P10C00D( - BuiltInId::imageAtomicMin_UImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicMin_01B10C00C( + BuiltInId::imageAtomicMin_UImage2D1_Int2_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01B10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00u10C00C00D( - BuiltInId::imageAtomicMin_Image2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicMin_00q20C00C( + BuiltInId::imageAtomicMin_Image3D1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00q20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01D10C00C00D( - BuiltInId::imageAtomicMin_IImage2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicMin_00w20C00C( + BuiltInId::imageAtomicMin_IImage3D1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00w20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01M10C00C00D( - BuiltInId::imageAtomicMin_UImage2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicMin_01C20C00C( + BuiltInId::imageAtomicMin_UImage3D1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p01C20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00v20C00C00D( - BuiltInId::imageAtomicMin_Image2DMSArray1_Int3_Int1_UInt1, +constexpr const TFunction imageAtomicMin_00s20C00C( + BuiltInId::imageAtomicMin_ImageCube1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00s20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01E20C00C00D( - BuiltInId::imageAtomicMin_IImage2DMSArray1_Int3_Int1_UInt1, +constexpr const TFunction imageAtomicMin_00y20C00C( + BuiltInId::imageAtomicMin_IImageCube1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00y20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01N20C00C00D( - BuiltInId::imageAtomicMin_UImage2DMSArray1_Int3_Int1_UInt1, +constexpr const TFunction imageAtomicMin_01E20C00C( + BuiltInId::imageAtomicMin_UImageCube1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p01E20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00q10C00C( - BuiltInId::imageAtomicMin_Image2D1_Int2_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_00z10C00C( - BuiltInId::imageAtomicMin_IImage2D1_Int2_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01I10C00C( - BuiltInId::imageAtomicMin_UImage2D1_Int2_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_00r20C00C( - BuiltInId::imageAtomicMin_Image3D1_Int3_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01A20C00C( - BuiltInId::imageAtomicMin_IImage3D1_Int3_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01J20C00C( - BuiltInId::imageAtomicMin_UImage3D1_Int3_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_00t20C00C( - BuiltInId::imageAtomicMin_ImageCube1_Int3_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01C20C00C( - BuiltInId::imageAtomicMin_IImageCube1_Int3_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01L20C00C( - BuiltInId::imageAtomicMin_UImageCube1_Int3_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_00y00C00C( +constexpr const TFunction imageAtomicMin_00u00C00C( BuiltInId::imageAtomicMin_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01H00C00C( +constexpr const TFunction imageAtomicMin_01A00C00C( BuiltInId::imageAtomicMin_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01Q00C00C( +constexpr const TFunction imageAtomicMin_01G00C00C( BuiltInId::imageAtomicMin_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00s20C00C( +constexpr const TFunction imageAtomicMin_00r20C00C( BuiltInId::imageAtomicMin_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01B20C00C( +constexpr const TFunction imageAtomicMin_00x20C00C( BuiltInId::imageAtomicMin_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01K20C00C( +constexpr const TFunction imageAtomicMin_01D20C00C( BuiltInId::imageAtomicMin_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00w20C00C( +constexpr const TFunction imageAtomicMin_00t20C00C( BuiltInId::imageAtomicMin_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01F20C00C( +constexpr const TFunction imageAtomicMin_00z20C00C( BuiltInId::imageAtomicMin_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_01O20C00C( +constexpr const TFunction imageAtomicMin_01F20C00C( BuiltInId::imageAtomicMin_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMin, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_00x10C00C( - BuiltInId::imageAtomicMin_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01G10C00C( - BuiltInId::imageAtomicMin_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01P10C00C( - BuiltInId::imageAtomicMin_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMin_00u10C00C00C( - BuiltInId::imageAtomicMin_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01D10C00C00C( - BuiltInId::imageAtomicMin_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01M10C00C00C( - BuiltInId::imageAtomicMin_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_00v20C00C00C( - BuiltInId::imageAtomicMin_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01E20C00C00C( - BuiltInId::imageAtomicMin_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMin_01N20C00C00C( - BuiltInId::imageAtomicMin_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMin, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMax_00q10C00D( +constexpr const TFunction imageAtomicMax_00p10C00D( BuiltInId::imageAtomicMax_Image2D1_Int2_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00z10C00D( +constexpr const TFunction imageAtomicMax_00v10C00D( BuiltInId::imageAtomicMax_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01I10C00D( +constexpr const TFunction imageAtomicMax_01B10C00D( BuiltInId::imageAtomicMax_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00r20C00D( +constexpr const TFunction imageAtomicMax_00q20C00D( BuiltInId::imageAtomicMax_Image3D1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01A20C00D( +constexpr const TFunction imageAtomicMax_00w20C00D( BuiltInId::imageAtomicMax_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01J20C00D( +constexpr const TFunction imageAtomicMax_01C20C00D( BuiltInId::imageAtomicMax_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00t20C00D( +constexpr const TFunction imageAtomicMax_00s20C00D( BuiltInId::imageAtomicMax_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01C20C00D( +constexpr const TFunction imageAtomicMax_00y20C00D( BuiltInId::imageAtomicMax_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01L20C00D( +constexpr const TFunction imageAtomicMax_01E20C00D( BuiltInId::imageAtomicMax_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00y00C00D( +constexpr const TFunction imageAtomicMax_00u00C00D( BuiltInId::imageAtomicMax_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01H00C00D( +constexpr const TFunction imageAtomicMax_01A00C00D( BuiltInId::imageAtomicMax_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01Q00C00D( +constexpr const TFunction imageAtomicMax_01G00C00D( BuiltInId::imageAtomicMax_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00s20C00D( +constexpr const TFunction imageAtomicMax_00r20C00D( BuiltInId::imageAtomicMax_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01B20C00D( +constexpr const TFunction imageAtomicMax_00x20C00D( BuiltInId::imageAtomicMax_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01K20C00D( +constexpr const TFunction imageAtomicMax_01D20C00D( BuiltInId::imageAtomicMax_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00w20C00D( +constexpr const TFunction imageAtomicMax_00t20C00D( BuiltInId::imageAtomicMax_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01F20C00D( +constexpr const TFunction imageAtomicMax_00z20C00D( BuiltInId::imageAtomicMax_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01O20C00D( +constexpr const TFunction imageAtomicMax_01F20C00D( BuiltInId::imageAtomicMax_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_00x10C00D( - BuiltInId::imageAtomicMax_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01G10C00D( - BuiltInId::imageAtomicMax_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01P10C00D( - BuiltInId::imageAtomicMax_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00u10C00C00D( - BuiltInId::imageAtomicMax_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01D10C00C00D( - BuiltInId::imageAtomicMax_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01M10C00C00D( - BuiltInId::imageAtomicMax_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_00v20C00C00D( - BuiltInId::imageAtomicMax_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01E20C00C00D( - BuiltInId::imageAtomicMax_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01N20C00C00D( - BuiltInId::imageAtomicMax_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_00q10C00C( +constexpr const TFunction imageAtomicMax_00p10C00C( BuiltInId::imageAtomicMax_Image2D1_Int2_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00z10C00C( +constexpr const TFunction imageAtomicMax_00v10C00C( BuiltInId::imageAtomicMax_IImage2D1_Int2_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01I10C00C( +constexpr const TFunction imageAtomicMax_01B10C00C( BuiltInId::imageAtomicMax_UImage2D1_Int2_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00r20C00C( +constexpr const TFunction imageAtomicMax_00q20C00C( BuiltInId::imageAtomicMax_Image3D1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01A20C00C( +constexpr const TFunction imageAtomicMax_00w20C00C( BuiltInId::imageAtomicMax_IImage3D1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01J20C00C( +constexpr const TFunction imageAtomicMax_01C20C00C( BuiltInId::imageAtomicMax_UImage3D1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00t20C00C( +constexpr const TFunction imageAtomicMax_00s20C00C( BuiltInId::imageAtomicMax_ImageCube1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01C20C00C( +constexpr const TFunction imageAtomicMax_00y20C00C( BuiltInId::imageAtomicMax_IImageCube1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01L20C00C( +constexpr const TFunction imageAtomicMax_01E20C00C( BuiltInId::imageAtomicMax_UImageCube1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00y00C00C( +constexpr const TFunction imageAtomicMax_00u00C00C( BuiltInId::imageAtomicMax_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01H00C00C( +constexpr const TFunction imageAtomicMax_01A00C00C( BuiltInId::imageAtomicMax_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01Q00C00C( +constexpr const TFunction imageAtomicMax_01G00C00C( BuiltInId::imageAtomicMax_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00s20C00C( +constexpr const TFunction imageAtomicMax_00r20C00C( BuiltInId::imageAtomicMax_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01B20C00C( +constexpr const TFunction imageAtomicMax_00x20C00C( BuiltInId::imageAtomicMax_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01K20C00C( +constexpr const TFunction imageAtomicMax_01D20C00C( BuiltInId::imageAtomicMax_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00w20C00C( +constexpr const TFunction imageAtomicMax_00t20C00C( BuiltInId::imageAtomicMax_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01F20C00C( +constexpr const TFunction imageAtomicMax_00z20C00C( BuiltInId::imageAtomicMax_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_01O20C00C( +constexpr const TFunction imageAtomicMax_01F20C00C( BuiltInId::imageAtomicMax_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMax, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMax_00x10C00C( - BuiltInId::imageAtomicMax_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicMax, +constexpr const TFunction imageAtomicAnd_00p10C00D( + BuiltInId::imageAtomicAnd_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, + BuiltInParameters::p00p10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicMax, + StaticType::Get(), + EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicMax_01G10C00C( - BuiltInId::imageAtomicMax_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicMax, +constexpr const TFunction imageAtomicAnd_00v10C00D( + BuiltInId::imageAtomicAnd_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, + BuiltInParameters::p00v10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicMax, + StaticType::Get(), + EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicMax_01P10C00C( - BuiltInId::imageAtomicMax_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicMax, +constexpr const TFunction imageAtomicAnd_01B10C00D( + BuiltInId::imageAtomicAnd_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_00u10C00C00C( - BuiltInId::imageAtomicMax_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01D10C00C00C( - BuiltInId::imageAtomicMax_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01M10C00C00C( - BuiltInId::imageAtomicMax_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_00v20C00C00C( - BuiltInId::imageAtomicMax_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01E20C00C00C( - BuiltInId::imageAtomicMax_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMax_01N20C00C00C( - BuiltInId::imageAtomicMax_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMax, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicAnd_00q10C00D( - BuiltInId::imageAtomicAnd_Image2D1_Int2_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_00z10C00D( - BuiltInId::imageAtomicAnd_IImage2D1_Int2_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01I10C00D( - BuiltInId::imageAtomicAnd_UImage2D1_Int2_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00r20C00D( +constexpr const TFunction imageAtomicAnd_00q20C00D( BuiltInId::imageAtomicAnd_Image3D1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01A20C00D( +constexpr const TFunction imageAtomicAnd_00w20C00D( BuiltInId::imageAtomicAnd_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01J20C00D( +constexpr const TFunction imageAtomicAnd_01C20C00D( BuiltInId::imageAtomicAnd_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00t20C00D( +constexpr const TFunction imageAtomicAnd_00s20C00D( BuiltInId::imageAtomicAnd_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01C20C00D( +constexpr const TFunction imageAtomicAnd_00y20C00D( BuiltInId::imageAtomicAnd_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01L20C00D( +constexpr const TFunction imageAtomicAnd_01E20C00D( BuiltInId::imageAtomicAnd_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00y00C00D( +constexpr const TFunction imageAtomicAnd_00u00C00D( BuiltInId::imageAtomicAnd_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01H00C00D( +constexpr const TFunction imageAtomicAnd_01A00C00D( BuiltInId::imageAtomicAnd_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01Q00C00D( +constexpr const TFunction imageAtomicAnd_01G00C00D( BuiltInId::imageAtomicAnd_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00s20C00D( +constexpr const TFunction imageAtomicAnd_00r20C00D( BuiltInId::imageAtomicAnd_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01B20C00D( +constexpr const TFunction imageAtomicAnd_00x20C00D( BuiltInId::imageAtomicAnd_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01K20C00D( +constexpr const TFunction imageAtomicAnd_01D20C00D( BuiltInId::imageAtomicAnd_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00w20C00D( +constexpr const TFunction imageAtomicAnd_00t20C00D( BuiltInId::imageAtomicAnd_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01F20C00D( +constexpr const TFunction imageAtomicAnd_00z20C00D( BuiltInId::imageAtomicAnd_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01O20C00D( +constexpr const TFunction imageAtomicAnd_01F20C00D( BuiltInId::imageAtomicAnd_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_00x10C00D( - BuiltInId::imageAtomicAnd_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01G10C00D( - BuiltInId::imageAtomicAnd_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01P10C00D( - BuiltInId::imageAtomicAnd_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00u10C00C00D( - BuiltInId::imageAtomicAnd_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01D10C00C00D( - BuiltInId::imageAtomicAnd_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01M10C00C00D( - BuiltInId::imageAtomicAnd_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_00v20C00C00D( - BuiltInId::imageAtomicAnd_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01E20C00C00D( - BuiltInId::imageAtomicAnd_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01N20C00C00D( - BuiltInId::imageAtomicAnd_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_00q10C00C( +constexpr const TFunction imageAtomicAnd_00p10C00C( BuiltInId::imageAtomicAnd_Image2D1_Int2_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00z10C00C( +constexpr const TFunction imageAtomicAnd_00v10C00C( BuiltInId::imageAtomicAnd_IImage2D1_Int2_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01I10C00C( +constexpr const TFunction imageAtomicAnd_01B10C00C( BuiltInId::imageAtomicAnd_UImage2D1_Int2_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00r20C00C( +constexpr const TFunction imageAtomicAnd_00q20C00C( BuiltInId::imageAtomicAnd_Image3D1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01A20C00C( +constexpr const TFunction imageAtomicAnd_00w20C00C( BuiltInId::imageAtomicAnd_IImage3D1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01J20C00C( +constexpr const TFunction imageAtomicAnd_01C20C00C( BuiltInId::imageAtomicAnd_UImage3D1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00t20C00C( +constexpr const TFunction imageAtomicAnd_00s20C00C( BuiltInId::imageAtomicAnd_ImageCube1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01C20C00C( +constexpr const TFunction imageAtomicAnd_00y20C00C( BuiltInId::imageAtomicAnd_IImageCube1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01L20C00C( +constexpr const TFunction imageAtomicAnd_01E20C00C( BuiltInId::imageAtomicAnd_UImageCube1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00y00C00C( +constexpr const TFunction imageAtomicAnd_00u00C00C( BuiltInId::imageAtomicAnd_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01H00C00C( +constexpr const TFunction imageAtomicAnd_01A00C00C( BuiltInId::imageAtomicAnd_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01Q00C00C( +constexpr const TFunction imageAtomicAnd_01G00C00C( BuiltInId::imageAtomicAnd_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00s20C00C( +constexpr const TFunction imageAtomicAnd_00r20C00C( BuiltInId::imageAtomicAnd_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01B20C00C( +constexpr const TFunction imageAtomicAnd_00x20C00C( BuiltInId::imageAtomicAnd_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01K20C00C( +constexpr const TFunction imageAtomicAnd_01D20C00C( BuiltInId::imageAtomicAnd_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00w20C00C( +constexpr const TFunction imageAtomicAnd_00t20C00C( BuiltInId::imageAtomicAnd_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01F20C00C( +constexpr const TFunction imageAtomicAnd_00z20C00C( BuiltInId::imageAtomicAnd_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_01O20C00C( +constexpr const TFunction imageAtomicAnd_01F20C00C( BuiltInId::imageAtomicAnd_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAnd, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_00x10C00C( - BuiltInId::imageAtomicAnd_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01G10C00C( - BuiltInId::imageAtomicAnd_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01P10C00C( - BuiltInId::imageAtomicAnd_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAnd_00u10C00C00C( - BuiltInId::imageAtomicAnd_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01D10C00C00C( - BuiltInId::imageAtomicAnd_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01M10C00C00C( - BuiltInId::imageAtomicAnd_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_00v20C00C00C( - BuiltInId::imageAtomicAnd_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01E20C00C00C( - BuiltInId::imageAtomicAnd_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAnd_01N20C00C00C( - BuiltInId::imageAtomicAnd_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAnd, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicOr_00q10C00D( +constexpr const TFunction imageAtomicOr_00p10C00D( BuiltInId::imageAtomicOr_Image2D1_Int2_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00z10C00D( +constexpr const TFunction imageAtomicOr_00v10C00D( BuiltInId::imageAtomicOr_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01I10C00D( +constexpr const TFunction imageAtomicOr_01B10C00D( BuiltInId::imageAtomicOr_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00r20C00D( +constexpr const TFunction imageAtomicOr_00q20C00D( BuiltInId::imageAtomicOr_Image3D1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01A20C00D( +constexpr const TFunction imageAtomicOr_00w20C00D( BuiltInId::imageAtomicOr_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01J20C00D( +constexpr const TFunction imageAtomicOr_01C20C00D( BuiltInId::imageAtomicOr_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00t20C00D( +constexpr const TFunction imageAtomicOr_00s20C00D( BuiltInId::imageAtomicOr_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01C20C00D( +constexpr const TFunction imageAtomicOr_00y20C00D( BuiltInId::imageAtomicOr_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01L20C00D( +constexpr const TFunction imageAtomicOr_01E20C00D( BuiltInId::imageAtomicOr_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00y00C00D( +constexpr const TFunction imageAtomicOr_00u00C00D( BuiltInId::imageAtomicOr_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01H00C00D( +constexpr const TFunction imageAtomicOr_01A00C00D( BuiltInId::imageAtomicOr_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01Q00C00D( +constexpr const TFunction imageAtomicOr_01G00C00D( BuiltInId::imageAtomicOr_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00s20C00D( +constexpr const TFunction imageAtomicOr_00r20C00D( BuiltInId::imageAtomicOr_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01B20C00D( +constexpr const TFunction imageAtomicOr_00x20C00D( BuiltInId::imageAtomicOr_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01K20C00D( +constexpr const TFunction imageAtomicOr_01D20C00D( BuiltInId::imageAtomicOr_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00w20C00D( +constexpr const TFunction imageAtomicOr_00t20C00D( BuiltInId::imageAtomicOr_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01F20C00D( +constexpr const TFunction imageAtomicOr_00z20C00D( BuiltInId::imageAtomicOr_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01O20C00D( +constexpr const TFunction imageAtomicOr_01F20C00D( BuiltInId::imageAtomicOr_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00x10C00D( - BuiltInId::imageAtomicOr_ImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicOr_00p10C00C( + BuiltInId::imageAtomicOr_Image2D1_Int2_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, + BuiltInParameters::p00p10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01G10C00D( - BuiltInId::imageAtomicOr_IImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicOr_00v10C00C( + BuiltInId::imageAtomicOr_IImage2D1_Int2_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, + BuiltInParameters::p00v10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01P10C00D( - BuiltInId::imageAtomicOr_UImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicOr_01B10C00C( + BuiltInId::imageAtomicOr_UImage2D1_Int2_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01B10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00u10C00C00D( - BuiltInId::imageAtomicOr_Image2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicOr_00q20C00C( + BuiltInId::imageAtomicOr_Image3D1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00q20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01D10C00C00D( - BuiltInId::imageAtomicOr_IImage2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicOr_00w20C00C( + BuiltInId::imageAtomicOr_IImage3D1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00w20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01M10C00C00D( - BuiltInId::imageAtomicOr_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_00v20C00C00D( - BuiltInId::imageAtomicOr_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01E20C00C00D( - BuiltInId::imageAtomicOr_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01N20C00C00D( - BuiltInId::imageAtomicOr_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_00q10C00C( - BuiltInId::imageAtomicOr_Image2D1_Int2_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_00z10C00C( - BuiltInId::imageAtomicOr_IImage2D1_Int2_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01I10C00C( - BuiltInId::imageAtomicOr_UImage2D1_Int2_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_00r20C00C( - BuiltInId::imageAtomicOr_Image3D1_Int3_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01A20C00C( - BuiltInId::imageAtomicOr_IImage3D1_Int3_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01J20C00C( +constexpr const TFunction imageAtomicOr_01C20C00C( BuiltInId::imageAtomicOr_UImage3D1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00t20C00C( +constexpr const TFunction imageAtomicOr_00s20C00C( BuiltInId::imageAtomicOr_ImageCube1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01C20C00C( +constexpr const TFunction imageAtomicOr_00y20C00C( BuiltInId::imageAtomicOr_IImageCube1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01L20C00C( +constexpr const TFunction imageAtomicOr_01E20C00C( BuiltInId::imageAtomicOr_UImageCube1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00y00C00C( +constexpr const TFunction imageAtomicOr_00u00C00C( BuiltInId::imageAtomicOr_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01H00C00C( +constexpr const TFunction imageAtomicOr_01A00C00C( BuiltInId::imageAtomicOr_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01Q00C00C( +constexpr const TFunction imageAtomicOr_01G00C00C( BuiltInId::imageAtomicOr_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00s20C00C( +constexpr const TFunction imageAtomicOr_00r20C00C( BuiltInId::imageAtomicOr_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01B20C00C( +constexpr const TFunction imageAtomicOr_00x20C00C( BuiltInId::imageAtomicOr_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01K20C00C( +constexpr const TFunction imageAtomicOr_01D20C00C( BuiltInId::imageAtomicOr_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00w20C00C( +constexpr const TFunction imageAtomicOr_00t20C00C( BuiltInId::imageAtomicOr_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01F20C00C( +constexpr const TFunction imageAtomicOr_00z20C00C( BuiltInId::imageAtomicOr_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_01O20C00C( +constexpr const TFunction imageAtomicOr_01F20C00C( BuiltInId::imageAtomicOr_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicOr, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_00x10C00C( - BuiltInId::imageAtomicOr_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01G10C00C( - BuiltInId::imageAtomicOr_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01P10C00C( - BuiltInId::imageAtomicOr_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOr_00u10C00C00C( - BuiltInId::imageAtomicOr_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01D10C00C00C( - BuiltInId::imageAtomicOr_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01M10C00C00C( - BuiltInId::imageAtomicOr_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_00v20C00C00C( - BuiltInId::imageAtomicOr_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01E20C00C00C( - BuiltInId::imageAtomicOr_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOr_01N20C00C00C( - BuiltInId::imageAtomicOr_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicOr, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicXor_00q10C00D( +constexpr const TFunction imageAtomicXor_00p10C00D( BuiltInId::imageAtomicXor_Image2D1_Int2_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00z10C00D( +constexpr const TFunction imageAtomicXor_00v10C00D( BuiltInId::imageAtomicXor_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01I10C00D( +constexpr const TFunction imageAtomicXor_01B10C00D( BuiltInId::imageAtomicXor_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00r20C00D( +constexpr const TFunction imageAtomicXor_00q20C00D( BuiltInId::imageAtomicXor_Image3D1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01A20C00D( +constexpr const TFunction imageAtomicXor_00w20C00D( BuiltInId::imageAtomicXor_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01J20C00D( +constexpr const TFunction imageAtomicXor_01C20C00D( BuiltInId::imageAtomicXor_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00t20C00D( +constexpr const TFunction imageAtomicXor_00s20C00D( BuiltInId::imageAtomicXor_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01C20C00D( +constexpr const TFunction imageAtomicXor_00y20C00D( BuiltInId::imageAtomicXor_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01L20C00D( +constexpr const TFunction imageAtomicXor_01E20C00D( BuiltInId::imageAtomicXor_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00y00C00D( +constexpr const TFunction imageAtomicXor_00u00C00D( BuiltInId::imageAtomicXor_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01H00C00D( +constexpr const TFunction imageAtomicXor_01A00C00D( BuiltInId::imageAtomicXor_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01Q00C00D( +constexpr const TFunction imageAtomicXor_01G00C00D( BuiltInId::imageAtomicXor_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00s20C00D( +constexpr const TFunction imageAtomicXor_00r20C00D( BuiltInId::imageAtomicXor_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01B20C00D( +constexpr const TFunction imageAtomicXor_00x20C00D( BuiltInId::imageAtomicXor_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01K20C00D( +constexpr const TFunction imageAtomicXor_01D20C00D( BuiltInId::imageAtomicXor_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00w20C00D( +constexpr const TFunction imageAtomicXor_00t20C00D( BuiltInId::imageAtomicXor_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01F20C00D( +constexpr const TFunction imageAtomicXor_00z20C00D( BuiltInId::imageAtomicXor_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01O20C00D( +constexpr const TFunction imageAtomicXor_01F20C00D( BuiltInId::imageAtomicXor_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_00x10C00D( - BuiltInId::imageAtomicXor_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01G10C00D( - BuiltInId::imageAtomicXor_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01P10C00D( - BuiltInId::imageAtomicXor_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00u10C00C00D( - BuiltInId::imageAtomicXor_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01D10C00C00D( - BuiltInId::imageAtomicXor_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01M10C00C00D( - BuiltInId::imageAtomicXor_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_00v20C00C00D( - BuiltInId::imageAtomicXor_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01E20C00C00D( - BuiltInId::imageAtomicXor_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01N20C00C00D( - BuiltInId::imageAtomicXor_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_00q10C00C( +constexpr const TFunction imageAtomicXor_00p10C00C( BuiltInId::imageAtomicXor_Image2D1_Int2_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00z10C00C( +constexpr const TFunction imageAtomicXor_00v10C00C( BuiltInId::imageAtomicXor_IImage2D1_Int2_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01I10C00C( +constexpr const TFunction imageAtomicXor_01B10C00C( BuiltInId::imageAtomicXor_UImage2D1_Int2_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00r20C00C( +constexpr const TFunction imageAtomicXor_00q20C00C( BuiltInId::imageAtomicXor_Image3D1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01A20C00C( +constexpr const TFunction imageAtomicXor_00w20C00C( BuiltInId::imageAtomicXor_IImage3D1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01J20C00C( +constexpr const TFunction imageAtomicXor_01C20C00C( BuiltInId::imageAtomicXor_UImage3D1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00t20C00C( +constexpr const TFunction imageAtomicXor_00s20C00C( BuiltInId::imageAtomicXor_ImageCube1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01C20C00C( +constexpr const TFunction imageAtomicXor_00y20C00C( BuiltInId::imageAtomicXor_IImageCube1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01L20C00C( +constexpr const TFunction imageAtomicXor_01E20C00C( BuiltInId::imageAtomicXor_UImageCube1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00y00C00C( +constexpr const TFunction imageAtomicXor_00u00C00C( BuiltInId::imageAtomicXor_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01H00C00C( +constexpr const TFunction imageAtomicXor_01A00C00C( BuiltInId::imageAtomicXor_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01Q00C00C( +constexpr const TFunction imageAtomicXor_01G00C00C( BuiltInId::imageAtomicXor_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00s20C00C( +constexpr const TFunction imageAtomicXor_00r20C00C( BuiltInId::imageAtomicXor_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01B20C00C( +constexpr const TFunction imageAtomicXor_00x20C00C( BuiltInId::imageAtomicXor_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01K20C00C( +constexpr const TFunction imageAtomicXor_01D20C00C( BuiltInId::imageAtomicXor_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00w20C00C( +constexpr const TFunction imageAtomicXor_00t20C00C( BuiltInId::imageAtomicXor_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01F20C00C( +constexpr const TFunction imageAtomicXor_00z20C00C( BuiltInId::imageAtomicXor_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_01O20C00C( +constexpr const TFunction imageAtomicXor_01F20C00C( BuiltInId::imageAtomicXor_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicXor, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXor_00x10C00C( - BuiltInId::imageAtomicXor_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicXor, +constexpr const TFunction imageAtomicExchange_00p10C00D( + BuiltInId::imageAtomicExchange_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, + BuiltInParameters::p00p10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicXor, + StaticType::Get(), + EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicXor_01G10C00C( - BuiltInId::imageAtomicXor_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicXor, +constexpr const TFunction imageAtomicExchange_00v10C00D( + BuiltInId::imageAtomicExchange_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, + BuiltInParameters::p00v10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicXor, + StaticType::Get(), + EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicXor_01P10C00C( - BuiltInId::imageAtomicXor_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicXor, +constexpr const TFunction imageAtomicExchange_01B10C00D( + BuiltInId::imageAtomicExchange_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_00u10C00C00C( - BuiltInId::imageAtomicXor_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01D10C00C00C( - BuiltInId::imageAtomicXor_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01M10C00C00C( - BuiltInId::imageAtomicXor_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_00v20C00C00C( - BuiltInId::imageAtomicXor_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01E20C00C00C( - BuiltInId::imageAtomicXor_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXor_01N20C00C00C( - BuiltInId::imageAtomicXor_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicXor, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicExchange_00q10C00D( - BuiltInId::imageAtomicExchange_Image2D1_Int2_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00z10C00D( - BuiltInId::imageAtomicExchange_IImage2D1_Int2_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01I10C00D( - BuiltInId::imageAtomicExchange_UImage2D1_Int2_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00r20C00D( +constexpr const TFunction imageAtomicExchange_00q20C00D( BuiltInId::imageAtomicExchange_Image3D1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01A20C00D( +constexpr const TFunction imageAtomicExchange_00w20C00D( BuiltInId::imageAtomicExchange_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01J20C00D( +constexpr const TFunction imageAtomicExchange_01C20C00D( BuiltInId::imageAtomicExchange_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00t20C00D( +constexpr const TFunction imageAtomicExchange_00s20C00D( BuiltInId::imageAtomicExchange_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01C20C00D( +constexpr const TFunction imageAtomicExchange_00y20C00D( BuiltInId::imageAtomicExchange_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01L20C00D( +constexpr const TFunction imageAtomicExchange_01E20C00D( BuiltInId::imageAtomicExchange_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00y00C00D( +constexpr const TFunction imageAtomicExchange_00u00C00D( BuiltInId::imageAtomicExchange_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01H00C00D( +constexpr const TFunction imageAtomicExchange_01A00C00D( BuiltInId::imageAtomicExchange_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01Q00C00D( +constexpr const TFunction imageAtomicExchange_01G00C00D( BuiltInId::imageAtomicExchange_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00s20C00D( +constexpr const TFunction imageAtomicExchange_00r20C00D( BuiltInId::imageAtomicExchange_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01B20C00D( +constexpr const TFunction imageAtomicExchange_00x20C00D( BuiltInId::imageAtomicExchange_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01K20C00D( +constexpr const TFunction imageAtomicExchange_01D20C00D( BuiltInId::imageAtomicExchange_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00w20C00D( +constexpr const TFunction imageAtomicExchange_00t20C00D( BuiltInId::imageAtomicExchange_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01F20C00D( +constexpr const TFunction imageAtomicExchange_00z20C00D( BuiltInId::imageAtomicExchange_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01O20C00D( +constexpr const TFunction imageAtomicExchange_01F20C00D( BuiltInId::imageAtomicExchange_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00x10C00D( - BuiltInId::imageAtomicExchange_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01G10C00D( - BuiltInId::imageAtomicExchange_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01P10C00D( - BuiltInId::imageAtomicExchange_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00u10C00C00D( - BuiltInId::imageAtomicExchange_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01D10C00C00D( - BuiltInId::imageAtomicExchange_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01M10C00C00D( - BuiltInId::imageAtomicExchange_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00v20C00C00D( - BuiltInId::imageAtomicExchange_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01E20C00C00D( - BuiltInId::imageAtomicExchange_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01N20C00C00D( - BuiltInId::imageAtomicExchange_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00q10C00C( +constexpr const TFunction imageAtomicExchange_00p10C00C( BuiltInId::imageAtomicExchange_Image2D1_Int2_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00z10C00C( +constexpr const TFunction imageAtomicExchange_00v10C00C( BuiltInId::imageAtomicExchange_IImage2D1_Int2_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01I10C00C( +constexpr const TFunction imageAtomicExchange_01B10C00C( BuiltInId::imageAtomicExchange_UImage2D1_Int2_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00r20C00C( +constexpr const TFunction imageAtomicExchange_00q20C00C( BuiltInId::imageAtomicExchange_Image3D1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01A20C00C( +constexpr const TFunction imageAtomicExchange_00w20C00C( BuiltInId::imageAtomicExchange_IImage3D1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01J20C00C( +constexpr const TFunction imageAtomicExchange_01C20C00C( BuiltInId::imageAtomicExchange_UImage3D1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00t20C00C( +constexpr const TFunction imageAtomicExchange_00s20C00C( BuiltInId::imageAtomicExchange_ImageCube1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01C20C00C( +constexpr const TFunction imageAtomicExchange_00y20C00C( BuiltInId::imageAtomicExchange_IImageCube1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01L20C00C( +constexpr const TFunction imageAtomicExchange_01E20C00C( BuiltInId::imageAtomicExchange_UImageCube1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00y00C00C( +constexpr const TFunction imageAtomicExchange_00u00C00C( BuiltInId::imageAtomicExchange_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01H00C00C( +constexpr const TFunction imageAtomicExchange_01A00C00C( BuiltInId::imageAtomicExchange_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01Q00C00C( +constexpr const TFunction imageAtomicExchange_01G00C00C( BuiltInId::imageAtomicExchange_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00s20C00C( +constexpr const TFunction imageAtomicExchange_00r20C00C( BuiltInId::imageAtomicExchange_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01B20C00C( +constexpr const TFunction imageAtomicExchange_00x20C00C( BuiltInId::imageAtomicExchange_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01K20C00C( +constexpr const TFunction imageAtomicExchange_01D20C00C( BuiltInId::imageAtomicExchange_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00w20C00C( +constexpr const TFunction imageAtomicExchange_00t20C00C( BuiltInId::imageAtomicExchange_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01F20C00C( +constexpr const TFunction imageAtomicExchange_00z20C00C( BuiltInId::imageAtomicExchange_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01O20C00C( +constexpr const TFunction imageAtomicExchange_01F20C00C( BuiltInId::imageAtomicExchange_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00x10C00C( - BuiltInId::imageAtomicExchange_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01G10C00C( - BuiltInId::imageAtomicExchange_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01P10C00C( - BuiltInId::imageAtomicExchange_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00u10C00C00C( - BuiltInId::imageAtomicExchange_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01D10C00C00C( - BuiltInId::imageAtomicExchange_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01M10C00C00C( - BuiltInId::imageAtomicExchange_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00v20C00C00C( - BuiltInId::imageAtomicExchange_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01E20C00C00C( - BuiltInId::imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01N20C00C00C( - BuiltInId::imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00q10C00B( +constexpr const TFunction imageAtomicExchange_00p10C00B( BuiltInId::imageAtomicExchange_Image2D1_Int2_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00B, + BuiltInParameters::p00p10C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00z10C00B( +constexpr const TFunction imageAtomicExchange_00v10C00B( BuiltInId::imageAtomicExchange_IImage2D1_Int2_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00B, + BuiltInParameters::p00v10C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01I10C00B( +constexpr const TFunction imageAtomicExchange_01B10C00B( BuiltInId::imageAtomicExchange_UImage2D1_Int2_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00B, + BuiltInParameters::p01B10C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00r20C00B( +constexpr const TFunction imageAtomicExchange_00q20C00B( BuiltInId::imageAtomicExchange_Image3D1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00B, + BuiltInParameters::p00q20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01A20C00B( +constexpr const TFunction imageAtomicExchange_00w20C00B( BuiltInId::imageAtomicExchange_IImage3D1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00B, + BuiltInParameters::p00w20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01J20C00B( +constexpr const TFunction imageAtomicExchange_01C20C00B( BuiltInId::imageAtomicExchange_UImage3D1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00B, + BuiltInParameters::p01C20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00t20C00B( +constexpr const TFunction imageAtomicExchange_00s20C00B( BuiltInId::imageAtomicExchange_ImageCube1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00B, + BuiltInParameters::p00s20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01C20C00B( +constexpr const TFunction imageAtomicExchange_00y20C00B( BuiltInId::imageAtomicExchange_IImageCube1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00B, + BuiltInParameters::p00y20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01L20C00B( +constexpr const TFunction imageAtomicExchange_01E20C00B( BuiltInId::imageAtomicExchange_UImageCube1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00B, + BuiltInParameters::p01E20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00y00C00B( +constexpr const TFunction imageAtomicExchange_00u00C00B( BuiltInId::imageAtomicExchange_ImageBuffer1_Int1_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00B, + BuiltInParameters::p00u00C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01H00C00B( +constexpr const TFunction imageAtomicExchange_01A00C00B( BuiltInId::imageAtomicExchange_IImageBuffer1_Int1_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00B, + BuiltInParameters::p01A00C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01Q00C00B( +constexpr const TFunction imageAtomicExchange_01G00C00B( BuiltInId::imageAtomicExchange_UImageBuffer1_Int1_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00B, + BuiltInParameters::p01G00C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00s20C00B( +constexpr const TFunction imageAtomicExchange_00r20C00B( BuiltInId::imageAtomicExchange_Image2DArray1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00B, + BuiltInParameters::p00r20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01B20C00B( +constexpr const TFunction imageAtomicExchange_00x20C00B( BuiltInId::imageAtomicExchange_IImage2DArray1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00B, + BuiltInParameters::p00x20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01K20C00B( +constexpr const TFunction imageAtomicExchange_01D20C00B( BuiltInId::imageAtomicExchange_UImage2DArray1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00B, + BuiltInParameters::p01D20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00w20C00B( +constexpr const TFunction imageAtomicExchange_00t20C00B( BuiltInId::imageAtomicExchange_ImageCubeArray1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00B, + BuiltInParameters::p00t20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01F20C00B( +constexpr const TFunction imageAtomicExchange_00z20C00B( BuiltInId::imageAtomicExchange_IImageCubeArray1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00B, + BuiltInParameters::p00z20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_01O20C00B( +constexpr const TFunction imageAtomicExchange_01F20C00B( BuiltInId::imageAtomicExchange_UImageCubeArray1_Int3_Float1, BuiltInName::imageAtomicExchange, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00B, + BuiltInParameters::p01F20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchange_00x10C00B( - BuiltInId::imageAtomicExchange_ImageRect1_Int2_Float1, - BuiltInName::imageAtomicExchange, +constexpr const TFunction imageAtomicCompSwap_00p10C00D00D( + BuiltInId::imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00B, - 3, - StaticType::Get(), - EOpImageAtomicExchange, + BuiltInParameters::p00p10C00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicExchange_01G10C00B( - BuiltInId::imageAtomicExchange_IImageRect1_Int2_Float1, - BuiltInName::imageAtomicExchange, +constexpr const TFunction imageAtomicCompSwap_00v10C00D00D( + BuiltInId::imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00B, - 3, - StaticType::Get(), - EOpImageAtomicExchange, + BuiltInParameters::p00v10C00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicExchange_01P10C00B( - BuiltInId::imageAtomicExchange_UImageRect1_Int2_Float1, - BuiltInName::imageAtomicExchange, +constexpr const TFunction imageAtomicCompSwap_01B10C00D00D( + BuiltInId::imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00B, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00u10C00C00B( - BuiltInId::imageAtomicExchange_Image2DMS1_Int2_Int1_Float1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01D10C00C00B( - BuiltInId::imageAtomicExchange_IImage2DMS1_Int2_Int1_Float1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01M10C00C00B( - BuiltInId::imageAtomicExchange_UImage2DMS1_Int2_Int1_Float1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_00v20C00C00B( - BuiltInId::imageAtomicExchange_Image2DMSArray1_Int3_Int1_Float1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01E20C00C00B( - BuiltInId::imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Float1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchange_01N20C00C00B( - BuiltInId::imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Float1, - BuiltInName::imageAtomicExchange, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicCompSwap_00q10C00D00D( - BuiltInId::imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_00z10C00D00D( - BuiltInId::imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01I10C00D00D( - BuiltInId::imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00r20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00q20C00D00D( BuiltInId::imageAtomicCompSwap_Image3D1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01A20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00w20C00D00D( BuiltInId::imageAtomicCompSwap_IImage3D1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01J20C00D00D( +constexpr const TFunction imageAtomicCompSwap_01C20C00D00D( BuiltInId::imageAtomicCompSwap_UImage3D1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00t20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00s20C00D00D( BuiltInId::imageAtomicCompSwap_ImageCube1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01C20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00y20C00D00D( BuiltInId::imageAtomicCompSwap_IImageCube1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01L20C00D00D( +constexpr const TFunction imageAtomicCompSwap_01E20C00D00D( BuiltInId::imageAtomicCompSwap_UImageCube1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00y00C00D00D( +constexpr const TFunction imageAtomicCompSwap_00u00C00D00D( BuiltInId::imageAtomicCompSwap_ImageBuffer1_Int1_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01H00C00D00D( +constexpr const TFunction imageAtomicCompSwap_01A00C00D00D( BuiltInId::imageAtomicCompSwap_IImageBuffer1_Int1_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01Q00C00D00D( +constexpr const TFunction imageAtomicCompSwap_01G00C00D00D( BuiltInId::imageAtomicCompSwap_UImageBuffer1_Int1_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00s20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00r20C00D00D( BuiltInId::imageAtomicCompSwap_Image2DArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01B20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00x20C00D00D( BuiltInId::imageAtomicCompSwap_IImage2DArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01K20C00D00D( +constexpr const TFunction imageAtomicCompSwap_01D20C00D00D( BuiltInId::imageAtomicCompSwap_UImage2DArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00w20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00t20C00D00D( BuiltInId::imageAtomicCompSwap_ImageCubeArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01F20C00D00D( +constexpr const TFunction imageAtomicCompSwap_00z20C00D00D( BuiltInId::imageAtomicCompSwap_IImageCubeArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01O20C00D00D( +constexpr const TFunction imageAtomicCompSwap_01F20C00D00D( BuiltInId::imageAtomicCompSwap_UImageCubeArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_00x10C00D00D( - BuiltInId::imageAtomicCompSwap_ImageRect1_Int2_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01G10C00D00D( - BuiltInId::imageAtomicCompSwap_IImageRect1_Int2_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01P10C00D00D( - BuiltInId::imageAtomicCompSwap_UImageRect1_Int2_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00u10C00C00D00D( - BuiltInId::imageAtomicCompSwap_Image2DMS1_Int2_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01D10C00C00D00D( - BuiltInId::imageAtomicCompSwap_IImage2DMS1_Int2_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01M10C00C00D00D( - BuiltInId::imageAtomicCompSwap_UImage2DMS1_Int2_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_00v20C00C00D00D( - BuiltInId::imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01E20C00C00D00D( - BuiltInId::imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01N20C00C00D00D( - BuiltInId::imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_00q10C00C00C( +constexpr const TFunction imageAtomicCompSwap_00p10C00C00C( BuiltInId::imageAtomicCompSwap_Image2D1_Int2_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00z10C00C00C( +constexpr const TFunction imageAtomicCompSwap_00v10C00C00C( BuiltInId::imageAtomicCompSwap_IImage2D1_Int2_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01I10C00C00C( +constexpr const TFunction imageAtomicCompSwap_01B10C00C00C( BuiltInId::imageAtomicCompSwap_UImage2D1_Int2_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00r20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00q20C00C00C( BuiltInId::imageAtomicCompSwap_Image3D1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01A20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00w20C00C00C( BuiltInId::imageAtomicCompSwap_IImage3D1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01J20C00C00C( +constexpr const TFunction imageAtomicCompSwap_01C20C00C00C( BuiltInId::imageAtomicCompSwap_UImage3D1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00t20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00s20C00C00C( BuiltInId::imageAtomicCompSwap_ImageCube1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01C20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00y20C00C00C( BuiltInId::imageAtomicCompSwap_IImageCube1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01L20C00C00C( +constexpr const TFunction imageAtomicCompSwap_01E20C00C00C( BuiltInId::imageAtomicCompSwap_UImageCube1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00y00C00C00C( +constexpr const TFunction imageAtomicCompSwap_00u00C00C00C( BuiltInId::imageAtomicCompSwap_ImageBuffer1_Int1_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01H00C00C00C( +constexpr const TFunction imageAtomicCompSwap_01A00C00C00C( BuiltInId::imageAtomicCompSwap_IImageBuffer1_Int1_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01Q00C00C00C( +constexpr const TFunction imageAtomicCompSwap_01G00C00C00C( BuiltInId::imageAtomicCompSwap_UImageBuffer1_Int1_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00s20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00r20C00C00C( BuiltInId::imageAtomicCompSwap_Image2DArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01B20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00x20C00C00C( BuiltInId::imageAtomicCompSwap_IImage2DArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01K20C00C00C( +constexpr const TFunction imageAtomicCompSwap_01D20C00C00C( BuiltInId::imageAtomicCompSwap_UImage2DArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00w20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00t20C00C00C( BuiltInId::imageAtomicCompSwap_ImageCubeArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01F20C00C00C( +constexpr const TFunction imageAtomicCompSwap_00z20C00C00C( BuiltInId::imageAtomicCompSwap_IImageCubeArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_01O20C00C00C( +constexpr const TFunction imageAtomicCompSwap_01F20C00C00C( BuiltInId::imageAtomicCompSwap_UImageCubeArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwap, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01O20C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_00x10C00C00C( - BuiltInId::imageAtomicCompSwap_ImageRect1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00x10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01G10C00C00C( - BuiltInId::imageAtomicCompSwap_IImageRect1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01G10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01P10C00C00C( - BuiltInId::imageAtomicCompSwap_UImageRect1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwap_00u10C00C00C00C( - BuiltInId::imageAtomicCompSwap_Image2DMS1_Int2_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00u10C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01D10C00C00C00C( - BuiltInId::imageAtomicCompSwap_IImage2DMS1_Int2_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01D10C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01M10C00C00C00C( - BuiltInId::imageAtomicCompSwap_UImage2DMS1_Int2_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01M10C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_00v20C00C00C00C( - BuiltInId::imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p00v20C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01E20C00C00C00C( - BuiltInId::imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01E20C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwap_01N20C00C00C00C( - BuiltInId::imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwap, - std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01N20C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicAddExt_00q10C00D( +constexpr const TFunction imageAtomicAddExt_00p10C00D( BuiltInId::imageAtomicAddExt_Image2D1_Int2_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00z10C00D( +constexpr const TFunction imageAtomicAddExt_00v10C00D( BuiltInId::imageAtomicAddExt_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01I10C00D( +constexpr const TFunction imageAtomicAddExt_01B10C00D( BuiltInId::imageAtomicAddExt_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00r20C00D( +constexpr const TFunction imageAtomicAddExt_00q20C00D( BuiltInId::imageAtomicAddExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01A20C00D( +constexpr const TFunction imageAtomicAddExt_00w20C00D( BuiltInId::imageAtomicAddExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01J20C00D( +constexpr const TFunction imageAtomicAddExt_01C20C00D( BuiltInId::imageAtomicAddExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00t20C00D( +constexpr const TFunction imageAtomicAddExt_00s20C00D( BuiltInId::imageAtomicAddExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01C20C00D( +constexpr const TFunction imageAtomicAddExt_00y20C00D( BuiltInId::imageAtomicAddExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01L20C00D( +constexpr const TFunction imageAtomicAddExt_01E20C00D( BuiltInId::imageAtomicAddExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00y00C00D( +constexpr const TFunction imageAtomicAddExt_00u00C00D( BuiltInId::imageAtomicAddExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01H00C00D( +constexpr const TFunction imageAtomicAddExt_01A00C00D( BuiltInId::imageAtomicAddExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01Q00C00D( +constexpr const TFunction imageAtomicAddExt_01G00C00D( BuiltInId::imageAtomicAddExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00s20C00D( +constexpr const TFunction imageAtomicAddExt_00r20C00D( BuiltInId::imageAtomicAddExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01B20C00D( +constexpr const TFunction imageAtomicAddExt_00x20C00D( BuiltInId::imageAtomicAddExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01K20C00D( +constexpr const TFunction imageAtomicAddExt_01D20C00D( BuiltInId::imageAtomicAddExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00w20C00D( +constexpr const TFunction imageAtomicAddExt_00t20C00D( BuiltInId::imageAtomicAddExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01F20C00D( +constexpr const TFunction imageAtomicAddExt_00z20C00D( BuiltInId::imageAtomicAddExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01O20C00D( +constexpr const TFunction imageAtomicAddExt_01F20C00D( BuiltInId::imageAtomicAddExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00x10C00D( - BuiltInId::imageAtomicAddExt_ImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicAddExt_00p10C00C( + BuiltInId::imageAtomicAddExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, + BuiltInParameters::p00p10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01G10C00D( - BuiltInId::imageAtomicAddExt_IImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicAddExt_00v10C00C( + BuiltInId::imageAtomicAddExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, + BuiltInParameters::p00v10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01P10C00D( - BuiltInId::imageAtomicAddExt_UImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicAddExt_01B10C00C( + BuiltInId::imageAtomicAddExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01B10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00u10C00C00D( - BuiltInId::imageAtomicAddExt_Image2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicAddExt_00q20C00C( + BuiltInId::imageAtomicAddExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00q20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01D10C00C00D( - BuiltInId::imageAtomicAddExt_IImage2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicAddExt_00w20C00C( + BuiltInId::imageAtomicAddExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01M10C00C00D( - BuiltInId::imageAtomicAddExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_00v20C00C00D( - BuiltInId::imageAtomicAddExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01E20C00C00D( - BuiltInId::imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01N20C00C00D( - BuiltInId::imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_00q10C00C( - BuiltInId::imageAtomicAddExt_Image2D1_Int2_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_00z10C00C( - BuiltInId::imageAtomicAddExt_IImage2D1_Int2_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01I10C00C( - BuiltInId::imageAtomicAddExt_UImage2D1_Int2_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_00r20C00C( - BuiltInId::imageAtomicAddExt_Image3D1_Int3_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01A20C00C( - BuiltInId::imageAtomicAddExt_IImage3D1_Int3_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01J20C00C( +constexpr const TFunction imageAtomicAddExt_01C20C00C( BuiltInId::imageAtomicAddExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00t20C00C( +constexpr const TFunction imageAtomicAddExt_00s20C00C( BuiltInId::imageAtomicAddExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01C20C00C( +constexpr const TFunction imageAtomicAddExt_00y20C00C( BuiltInId::imageAtomicAddExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01L20C00C( +constexpr const TFunction imageAtomicAddExt_01E20C00C( BuiltInId::imageAtomicAddExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00y00C00C( +constexpr const TFunction imageAtomicAddExt_00u00C00C( BuiltInId::imageAtomicAddExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01H00C00C( +constexpr const TFunction imageAtomicAddExt_01A00C00C( BuiltInId::imageAtomicAddExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01Q00C00C( +constexpr const TFunction imageAtomicAddExt_01G00C00C( BuiltInId::imageAtomicAddExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00s20C00C( +constexpr const TFunction imageAtomicAddExt_00r20C00C( BuiltInId::imageAtomicAddExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01B20C00C( +constexpr const TFunction imageAtomicAddExt_00x20C00C( BuiltInId::imageAtomicAddExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01K20C00C( +constexpr const TFunction imageAtomicAddExt_01D20C00C( BuiltInId::imageAtomicAddExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00w20C00C( +constexpr const TFunction imageAtomicAddExt_00t20C00C( BuiltInId::imageAtomicAddExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01F20C00C( +constexpr const TFunction imageAtomicAddExt_00z20C00C( BuiltInId::imageAtomicAddExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_01O20C00C( +constexpr const TFunction imageAtomicAddExt_01F20C00C( BuiltInId::imageAtomicAddExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAddExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_00x10C00C( - BuiltInId::imageAtomicAddExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01G10C00C( - BuiltInId::imageAtomicAddExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01P10C00C( - BuiltInId::imageAtomicAddExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicAdd, false); -constexpr const TFunction imageAtomicAddExt_00u10C00C00C( - BuiltInId::imageAtomicAddExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01D10C00C00C( - BuiltInId::imageAtomicAddExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01M10C00C00C( - BuiltInId::imageAtomicAddExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_00v20C00C00C( - BuiltInId::imageAtomicAddExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01E20C00C00C( - BuiltInId::imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicAddExt_01N20C00C00C( - BuiltInId::imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAddExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAdd, - false); -constexpr const TFunction imageAtomicMinExt_00q10C00D( +constexpr const TFunction imageAtomicMinExt_00p10C00D( BuiltInId::imageAtomicMinExt_Image2D1_Int2_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00z10C00D( +constexpr const TFunction imageAtomicMinExt_00v10C00D( BuiltInId::imageAtomicMinExt_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01I10C00D( +constexpr const TFunction imageAtomicMinExt_01B10C00D( BuiltInId::imageAtomicMinExt_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00r20C00D( +constexpr const TFunction imageAtomicMinExt_00q20C00D( BuiltInId::imageAtomicMinExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01A20C00D( +constexpr const TFunction imageAtomicMinExt_00w20C00D( BuiltInId::imageAtomicMinExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01J20C00D( +constexpr const TFunction imageAtomicMinExt_01C20C00D( BuiltInId::imageAtomicMinExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00t20C00D( +constexpr const TFunction imageAtomicMinExt_00s20C00D( BuiltInId::imageAtomicMinExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01C20C00D( +constexpr const TFunction imageAtomicMinExt_00y20C00D( BuiltInId::imageAtomicMinExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01L20C00D( +constexpr const TFunction imageAtomicMinExt_01E20C00D( BuiltInId::imageAtomicMinExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00y00C00D( +constexpr const TFunction imageAtomicMinExt_00u00C00D( BuiltInId::imageAtomicMinExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01H00C00D( +constexpr const TFunction imageAtomicMinExt_01A00C00D( BuiltInId::imageAtomicMinExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01Q00C00D( +constexpr const TFunction imageAtomicMinExt_01G00C00D( BuiltInId::imageAtomicMinExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00s20C00D( +constexpr const TFunction imageAtomicMinExt_00r20C00D( BuiltInId::imageAtomicMinExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01B20C00D( +constexpr const TFunction imageAtomicMinExt_00x20C00D( BuiltInId::imageAtomicMinExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01K20C00D( +constexpr const TFunction imageAtomicMinExt_01D20C00D( BuiltInId::imageAtomicMinExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00w20C00D( +constexpr const TFunction imageAtomicMinExt_00t20C00D( BuiltInId::imageAtomicMinExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01F20C00D( +constexpr const TFunction imageAtomicMinExt_00z20C00D( BuiltInId::imageAtomicMinExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01O20C00D( +constexpr const TFunction imageAtomicMinExt_01F20C00D( BuiltInId::imageAtomicMinExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_00x10C00D( - BuiltInId::imageAtomicMinExt_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01G10C00D( - BuiltInId::imageAtomicMinExt_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01P10C00D( - BuiltInId::imageAtomicMinExt_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00u10C00C00D( - BuiltInId::imageAtomicMinExt_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01D10C00C00D( - BuiltInId::imageAtomicMinExt_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01M10C00C00D( - BuiltInId::imageAtomicMinExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_00v20C00C00D( - BuiltInId::imageAtomicMinExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01E20C00C00D( - BuiltInId::imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01N20C00C00D( - BuiltInId::imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_00q10C00C( +constexpr const TFunction imageAtomicMinExt_00p10C00C( BuiltInId::imageAtomicMinExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00z10C00C( +constexpr const TFunction imageAtomicMinExt_00v10C00C( BuiltInId::imageAtomicMinExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01I10C00C( +constexpr const TFunction imageAtomicMinExt_01B10C00C( BuiltInId::imageAtomicMinExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00r20C00C( +constexpr const TFunction imageAtomicMinExt_00q20C00C( BuiltInId::imageAtomicMinExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01A20C00C( +constexpr const TFunction imageAtomicMinExt_00w20C00C( BuiltInId::imageAtomicMinExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01J20C00C( +constexpr const TFunction imageAtomicMinExt_01C20C00C( BuiltInId::imageAtomicMinExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00t20C00C( +constexpr const TFunction imageAtomicMinExt_00s20C00C( BuiltInId::imageAtomicMinExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01C20C00C( +constexpr const TFunction imageAtomicMinExt_00y20C00C( BuiltInId::imageAtomicMinExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01L20C00C( +constexpr const TFunction imageAtomicMinExt_01E20C00C( BuiltInId::imageAtomicMinExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00y00C00C( +constexpr const TFunction imageAtomicMinExt_00u00C00C( BuiltInId::imageAtomicMinExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01H00C00C( +constexpr const TFunction imageAtomicMinExt_01A00C00C( BuiltInId::imageAtomicMinExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01Q00C00C( +constexpr const TFunction imageAtomicMinExt_01G00C00C( BuiltInId::imageAtomicMinExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00s20C00C( +constexpr const TFunction imageAtomicMinExt_00r20C00C( BuiltInId::imageAtomicMinExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01B20C00C( +constexpr const TFunction imageAtomicMinExt_00x20C00C( BuiltInId::imageAtomicMinExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01K20C00C( +constexpr const TFunction imageAtomicMinExt_01D20C00C( BuiltInId::imageAtomicMinExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00w20C00C( +constexpr const TFunction imageAtomicMinExt_00t20C00C( BuiltInId::imageAtomicMinExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01F20C00C( +constexpr const TFunction imageAtomicMinExt_00z20C00C( BuiltInId::imageAtomicMinExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_01O20C00C( +constexpr const TFunction imageAtomicMinExt_01F20C00C( BuiltInId::imageAtomicMinExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMinExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicMin, false); -constexpr const TFunction imageAtomicMinExt_00x10C00C( - BuiltInId::imageAtomicMinExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicMinExt, +constexpr const TFunction imageAtomicMaxExt_00p10C00D( + BuiltInId::imageAtomicMaxExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, + BuiltInParameters::p00p10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicMin, + StaticType::Get(), + EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMinExt_01G10C00C( - BuiltInId::imageAtomicMinExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicMinExt, +constexpr const TFunction imageAtomicMaxExt_00v10C00D( + BuiltInId::imageAtomicMaxExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, + BuiltInParameters::p00v10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicMin, + StaticType::Get(), + EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMinExt_01P10C00C( - BuiltInId::imageAtomicMinExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicMinExt, +constexpr const TFunction imageAtomicMaxExt_01B10C00D( + BuiltInId::imageAtomicMaxExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01B10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicMin, + StaticType::Get(), + EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMinExt_00u10C00C00C( - BuiltInId::imageAtomicMinExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01D10C00C00C( - BuiltInId::imageAtomicMinExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01M10C00C00C( - BuiltInId::imageAtomicMinExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_00v20C00C00C( - BuiltInId::imageAtomicMinExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01E20C00C00C( - BuiltInId::imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMinExt_01N20C00C00C( - BuiltInId::imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMinExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMin, - false); -constexpr const TFunction imageAtomicMaxExt_00q10C00D( - BuiltInId::imageAtomicMaxExt_Image2D1_Int2_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00z10C00D( - BuiltInId::imageAtomicMaxExt_IImage2D1_Int2_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01I10C00D( - BuiltInId::imageAtomicMaxExt_UImage2D1_Int2_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00r20C00D( +constexpr const TFunction imageAtomicMaxExt_00q20C00D( BuiltInId::imageAtomicMaxExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01A20C00D( +constexpr const TFunction imageAtomicMaxExt_00w20C00D( BuiltInId::imageAtomicMaxExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01J20C00D( +constexpr const TFunction imageAtomicMaxExt_01C20C00D( BuiltInId::imageAtomicMaxExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00t20C00D( +constexpr const TFunction imageAtomicMaxExt_00s20C00D( BuiltInId::imageAtomicMaxExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01C20C00D( +constexpr const TFunction imageAtomicMaxExt_00y20C00D( BuiltInId::imageAtomicMaxExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01L20C00D( +constexpr const TFunction imageAtomicMaxExt_01E20C00D( BuiltInId::imageAtomicMaxExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00y00C00D( +constexpr const TFunction imageAtomicMaxExt_00u00C00D( BuiltInId::imageAtomicMaxExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01H00C00D( +constexpr const TFunction imageAtomicMaxExt_01A00C00D( BuiltInId::imageAtomicMaxExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01Q00C00D( +constexpr const TFunction imageAtomicMaxExt_01G00C00D( BuiltInId::imageAtomicMaxExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00s20C00D( +constexpr const TFunction imageAtomicMaxExt_00r20C00D( BuiltInId::imageAtomicMaxExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01B20C00D( +constexpr const TFunction imageAtomicMaxExt_00x20C00D( BuiltInId::imageAtomicMaxExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01K20C00D( +constexpr const TFunction imageAtomicMaxExt_01D20C00D( BuiltInId::imageAtomicMaxExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00w20C00D( +constexpr const TFunction imageAtomicMaxExt_00t20C00D( BuiltInId::imageAtomicMaxExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01F20C00D( +constexpr const TFunction imageAtomicMaxExt_00z20C00D( BuiltInId::imageAtomicMaxExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01O20C00D( +constexpr const TFunction imageAtomicMaxExt_01F20C00D( BuiltInId::imageAtomicMaxExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00x10C00D( - BuiltInId::imageAtomicMaxExt_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01G10C00D( - BuiltInId::imageAtomicMaxExt_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01P10C00D( - BuiltInId::imageAtomicMaxExt_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00u10C00C00D( - BuiltInId::imageAtomicMaxExt_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01D10C00C00D( - BuiltInId::imageAtomicMaxExt_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01M10C00C00D( - BuiltInId::imageAtomicMaxExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00v20C00C00D( - BuiltInId::imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01E20C00C00D( - BuiltInId::imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01N20C00C00D( - BuiltInId::imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00q10C00C( +constexpr const TFunction imageAtomicMaxExt_00p10C00C( BuiltInId::imageAtomicMaxExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00z10C00C( +constexpr const TFunction imageAtomicMaxExt_00v10C00C( BuiltInId::imageAtomicMaxExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01I10C00C( +constexpr const TFunction imageAtomicMaxExt_01B10C00C( BuiltInId::imageAtomicMaxExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00r20C00C( +constexpr const TFunction imageAtomicMaxExt_00q20C00C( BuiltInId::imageAtomicMaxExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01A20C00C( +constexpr const TFunction imageAtomicMaxExt_00w20C00C( BuiltInId::imageAtomicMaxExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01J20C00C( +constexpr const TFunction imageAtomicMaxExt_01C20C00C( BuiltInId::imageAtomicMaxExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00t20C00C( +constexpr const TFunction imageAtomicMaxExt_00s20C00C( BuiltInId::imageAtomicMaxExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01C20C00C( +constexpr const TFunction imageAtomicMaxExt_00y20C00C( BuiltInId::imageAtomicMaxExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01L20C00C( +constexpr const TFunction imageAtomicMaxExt_01E20C00C( BuiltInId::imageAtomicMaxExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00y00C00C( +constexpr const TFunction imageAtomicMaxExt_00u00C00C( BuiltInId::imageAtomicMaxExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01H00C00C( +constexpr const TFunction imageAtomicMaxExt_01A00C00C( BuiltInId::imageAtomicMaxExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01Q00C00C( +constexpr const TFunction imageAtomicMaxExt_01G00C00C( BuiltInId::imageAtomicMaxExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00s20C00C( +constexpr const TFunction imageAtomicMaxExt_00r20C00C( BuiltInId::imageAtomicMaxExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01B20C00C( +constexpr const TFunction imageAtomicMaxExt_00x20C00C( BuiltInId::imageAtomicMaxExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01K20C00C( +constexpr const TFunction imageAtomicMaxExt_01D20C00C( BuiltInId::imageAtomicMaxExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00w20C00C( +constexpr const TFunction imageAtomicMaxExt_00t20C00C( BuiltInId::imageAtomicMaxExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01F20C00C( +constexpr const TFunction imageAtomicMaxExt_00z20C00C( BuiltInId::imageAtomicMaxExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_01O20C00C( +constexpr const TFunction imageAtomicMaxExt_01F20C00C( BuiltInId::imageAtomicMaxExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicMaxExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00x10C00C( - BuiltInId::imageAtomicMaxExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01G10C00C( - BuiltInId::imageAtomicMaxExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01P10C00C( - BuiltInId::imageAtomicMaxExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicMax, false); -constexpr const TFunction imageAtomicMaxExt_00u10C00C00C( - BuiltInId::imageAtomicMaxExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01D10C00C00C( - BuiltInId::imageAtomicMaxExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01M10C00C00C( - BuiltInId::imageAtomicMaxExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_00v20C00C00C( - BuiltInId::imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01E20C00C00C( - BuiltInId::imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicMaxExt_01N20C00C00C( - BuiltInId::imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicMaxExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicMax, - false); -constexpr const TFunction imageAtomicAndExt_00q10C00D( +constexpr const TFunction imageAtomicAndExt_00p10C00D( BuiltInId::imageAtomicAndExt_Image2D1_Int2_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00z10C00D( +constexpr const TFunction imageAtomicAndExt_00v10C00D( BuiltInId::imageAtomicAndExt_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01I10C00D( +constexpr const TFunction imageAtomicAndExt_01B10C00D( BuiltInId::imageAtomicAndExt_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00r20C00D( +constexpr const TFunction imageAtomicAndExt_00q20C00D( BuiltInId::imageAtomicAndExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01A20C00D( +constexpr const TFunction imageAtomicAndExt_00w20C00D( BuiltInId::imageAtomicAndExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01J20C00D( +constexpr const TFunction imageAtomicAndExt_01C20C00D( BuiltInId::imageAtomicAndExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00t20C00D( +constexpr const TFunction imageAtomicAndExt_00s20C00D( BuiltInId::imageAtomicAndExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01C20C00D( +constexpr const TFunction imageAtomicAndExt_00y20C00D( BuiltInId::imageAtomicAndExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01L20C00D( +constexpr const TFunction imageAtomicAndExt_01E20C00D( BuiltInId::imageAtomicAndExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00y00C00D( +constexpr const TFunction imageAtomicAndExt_00u00C00D( BuiltInId::imageAtomicAndExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01H00C00D( +constexpr const TFunction imageAtomicAndExt_01A00C00D( BuiltInId::imageAtomicAndExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01Q00C00D( +constexpr const TFunction imageAtomicAndExt_01G00C00D( BuiltInId::imageAtomicAndExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00s20C00D( +constexpr const TFunction imageAtomicAndExt_00r20C00D( BuiltInId::imageAtomicAndExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01B20C00D( +constexpr const TFunction imageAtomicAndExt_00x20C00D( BuiltInId::imageAtomicAndExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01K20C00D( +constexpr const TFunction imageAtomicAndExt_01D20C00D( BuiltInId::imageAtomicAndExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00w20C00D( +constexpr const TFunction imageAtomicAndExt_00t20C00D( BuiltInId::imageAtomicAndExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01F20C00D( +constexpr const TFunction imageAtomicAndExt_00z20C00D( BuiltInId::imageAtomicAndExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01O20C00D( +constexpr const TFunction imageAtomicAndExt_01F20C00D( BuiltInId::imageAtomicAndExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00x10C00D( - BuiltInId::imageAtomicAndExt_ImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicAndExt_00p10C00C( + BuiltInId::imageAtomicAndExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, + BuiltInParameters::p00p10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01G10C00D( - BuiltInId::imageAtomicAndExt_IImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicAndExt_00v10C00C( + BuiltInId::imageAtomicAndExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, + BuiltInParameters::p00v10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01P10C00D( - BuiltInId::imageAtomicAndExt_UImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicAndExt_01B10C00C( + BuiltInId::imageAtomicAndExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01B10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00u10C00C00D( - BuiltInId::imageAtomicAndExt_Image2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicAndExt_00q20C00C( + BuiltInId::imageAtomicAndExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00q20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01D10C00C00D( - BuiltInId::imageAtomicAndExt_IImage2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicAndExt_00w20C00C( + BuiltInId::imageAtomicAndExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01M10C00C00D( - BuiltInId::imageAtomicAndExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_00v20C00C00D( - BuiltInId::imageAtomicAndExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01E20C00C00D( - BuiltInId::imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01N20C00C00D( - BuiltInId::imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_00q10C00C( - BuiltInId::imageAtomicAndExt_Image2D1_Int2_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_00z10C00C( - BuiltInId::imageAtomicAndExt_IImage2D1_Int2_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01I10C00C( - BuiltInId::imageAtomicAndExt_UImage2D1_Int2_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_00r20C00C( - BuiltInId::imageAtomicAndExt_Image3D1_Int3_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01A20C00C( - BuiltInId::imageAtomicAndExt_IImage3D1_Int3_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01J20C00C( +constexpr const TFunction imageAtomicAndExt_01C20C00C( BuiltInId::imageAtomicAndExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00t20C00C( +constexpr const TFunction imageAtomicAndExt_00s20C00C( BuiltInId::imageAtomicAndExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01C20C00C( +constexpr const TFunction imageAtomicAndExt_00y20C00C( BuiltInId::imageAtomicAndExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01L20C00C( +constexpr const TFunction imageAtomicAndExt_01E20C00C( BuiltInId::imageAtomicAndExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00y00C00C( +constexpr const TFunction imageAtomicAndExt_00u00C00C( BuiltInId::imageAtomicAndExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01H00C00C( +constexpr const TFunction imageAtomicAndExt_01A00C00C( BuiltInId::imageAtomicAndExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01Q00C00C( +constexpr const TFunction imageAtomicAndExt_01G00C00C( BuiltInId::imageAtomicAndExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00s20C00C( +constexpr const TFunction imageAtomicAndExt_00r20C00C( BuiltInId::imageAtomicAndExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01B20C00C( +constexpr const TFunction imageAtomicAndExt_00x20C00C( BuiltInId::imageAtomicAndExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01K20C00C( +constexpr const TFunction imageAtomicAndExt_01D20C00C( BuiltInId::imageAtomicAndExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00w20C00C( +constexpr const TFunction imageAtomicAndExt_00t20C00C( BuiltInId::imageAtomicAndExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01F20C00C( +constexpr const TFunction imageAtomicAndExt_00z20C00C( BuiltInId::imageAtomicAndExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_01O20C00C( +constexpr const TFunction imageAtomicAndExt_01F20C00C( BuiltInId::imageAtomicAndExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicAndExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_00x10C00C( - BuiltInId::imageAtomicAndExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01G10C00C( - BuiltInId::imageAtomicAndExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01P10C00C( - BuiltInId::imageAtomicAndExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicAnd, false); -constexpr const TFunction imageAtomicAndExt_00u10C00C00C( - BuiltInId::imageAtomicAndExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01D10C00C00C( - BuiltInId::imageAtomicAndExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01M10C00C00C( - BuiltInId::imageAtomicAndExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_00v20C00C00C( - BuiltInId::imageAtomicAndExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01E20C00C00C( - BuiltInId::imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicAndExt_01N20C00C00C( - BuiltInId::imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicAndExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicAnd, - false); -constexpr const TFunction imageAtomicOrExt_00q10C00D( +constexpr const TFunction imageAtomicOrExt_00p10C00D( BuiltInId::imageAtomicOrExt_Image2D1_Int2_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00z10C00D( +constexpr const TFunction imageAtomicOrExt_00v10C00D( BuiltInId::imageAtomicOrExt_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01I10C00D( +constexpr const TFunction imageAtomicOrExt_01B10C00D( BuiltInId::imageAtomicOrExt_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00r20C00D( +constexpr const TFunction imageAtomicOrExt_00q20C00D( BuiltInId::imageAtomicOrExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01A20C00D( +constexpr const TFunction imageAtomicOrExt_00w20C00D( BuiltInId::imageAtomicOrExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01J20C00D( +constexpr const TFunction imageAtomicOrExt_01C20C00D( BuiltInId::imageAtomicOrExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00t20C00D( +constexpr const TFunction imageAtomicOrExt_00s20C00D( BuiltInId::imageAtomicOrExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01C20C00D( +constexpr const TFunction imageAtomicOrExt_00y20C00D( BuiltInId::imageAtomicOrExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01L20C00D( +constexpr const TFunction imageAtomicOrExt_01E20C00D( BuiltInId::imageAtomicOrExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00y00C00D( +constexpr const TFunction imageAtomicOrExt_00u00C00D( BuiltInId::imageAtomicOrExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01H00C00D( +constexpr const TFunction imageAtomicOrExt_01A00C00D( BuiltInId::imageAtomicOrExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01Q00C00D( +constexpr const TFunction imageAtomicOrExt_01G00C00D( BuiltInId::imageAtomicOrExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00s20C00D( +constexpr const TFunction imageAtomicOrExt_00r20C00D( BuiltInId::imageAtomicOrExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01B20C00D( +constexpr const TFunction imageAtomicOrExt_00x20C00D( BuiltInId::imageAtomicOrExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01K20C00D( +constexpr const TFunction imageAtomicOrExt_01D20C00D( BuiltInId::imageAtomicOrExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00w20C00D( +constexpr const TFunction imageAtomicOrExt_00t20C00D( BuiltInId::imageAtomicOrExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01F20C00D( +constexpr const TFunction imageAtomicOrExt_00z20C00D( BuiltInId::imageAtomicOrExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01O20C00D( +constexpr const TFunction imageAtomicOrExt_01F20C00D( BuiltInId::imageAtomicOrExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_00x10C00D( - BuiltInId::imageAtomicOrExt_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01G10C00D( - BuiltInId::imageAtomicOrExt_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01P10C00D( - BuiltInId::imageAtomicOrExt_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00u10C00C00D( - BuiltInId::imageAtomicOrExt_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01D10C00C00D( - BuiltInId::imageAtomicOrExt_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01M10C00C00D( - BuiltInId::imageAtomicOrExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_00v20C00C00D( - BuiltInId::imageAtomicOrExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01E20C00C00D( - BuiltInId::imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01N20C00C00D( - BuiltInId::imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_00q10C00C( +constexpr const TFunction imageAtomicOrExt_00p10C00C( BuiltInId::imageAtomicOrExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00z10C00C( +constexpr const TFunction imageAtomicOrExt_00v10C00C( BuiltInId::imageAtomicOrExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01I10C00C( +constexpr const TFunction imageAtomicOrExt_01B10C00C( BuiltInId::imageAtomicOrExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00r20C00C( +constexpr const TFunction imageAtomicOrExt_00q20C00C( BuiltInId::imageAtomicOrExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01A20C00C( +constexpr const TFunction imageAtomicOrExt_00w20C00C( BuiltInId::imageAtomicOrExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01J20C00C( +constexpr const TFunction imageAtomicOrExt_01C20C00C( BuiltInId::imageAtomicOrExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00t20C00C( +constexpr const TFunction imageAtomicOrExt_00s20C00C( BuiltInId::imageAtomicOrExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01C20C00C( +constexpr const TFunction imageAtomicOrExt_00y20C00C( BuiltInId::imageAtomicOrExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01L20C00C( +constexpr const TFunction imageAtomicOrExt_01E20C00C( BuiltInId::imageAtomicOrExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00y00C00C( +constexpr const TFunction imageAtomicOrExt_00u00C00C( BuiltInId::imageAtomicOrExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01H00C00C( +constexpr const TFunction imageAtomicOrExt_01A00C00C( BuiltInId::imageAtomicOrExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01Q00C00C( +constexpr const TFunction imageAtomicOrExt_01G00C00C( BuiltInId::imageAtomicOrExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00s20C00C( +constexpr const TFunction imageAtomicOrExt_00r20C00C( BuiltInId::imageAtomicOrExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01B20C00C( +constexpr const TFunction imageAtomicOrExt_00x20C00C( BuiltInId::imageAtomicOrExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01K20C00C( +constexpr const TFunction imageAtomicOrExt_01D20C00C( BuiltInId::imageAtomicOrExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00w20C00C( +constexpr const TFunction imageAtomicOrExt_00t20C00C( BuiltInId::imageAtomicOrExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01F20C00C( +constexpr const TFunction imageAtomicOrExt_00z20C00C( BuiltInId::imageAtomicOrExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_01O20C00C( +constexpr const TFunction imageAtomicOrExt_01F20C00C( BuiltInId::imageAtomicOrExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicOrExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicOr, false); -constexpr const TFunction imageAtomicOrExt_00x10C00C( - BuiltInId::imageAtomicOrExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicOrExt, +constexpr const TFunction imageAtomicXorExt_00p10C00D( + BuiltInId::imageAtomicXorExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, + BuiltInParameters::p00p10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicOr, + StaticType::Get(), + EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicOrExt_01G10C00C( - BuiltInId::imageAtomicOrExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicOrExt, +constexpr const TFunction imageAtomicXorExt_00v10C00D( + BuiltInId::imageAtomicXorExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, + BuiltInParameters::p00v10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicOr, + StaticType::Get(), + EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicOrExt_01P10C00C( - BuiltInId::imageAtomicOrExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicOrExt, +constexpr const TFunction imageAtomicXorExt_01B10C00D( + BuiltInId::imageAtomicXorExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01B10C00D00D, 3, - StaticType::Get(), - EOpImageAtomicOr, + StaticType::Get(), + EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicOrExt_00u10C00C00C( - BuiltInId::imageAtomicOrExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01D10C00C00C( - BuiltInId::imageAtomicOrExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01M10C00C00C( - BuiltInId::imageAtomicOrExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_00v20C00C00C( - BuiltInId::imageAtomicOrExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01E20C00C00C( - BuiltInId::imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicOrExt_01N20C00C00C( - BuiltInId::imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicOrExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicOr, - false); -constexpr const TFunction imageAtomicXorExt_00q10C00D( - BuiltInId::imageAtomicXorExt_Image2D1_Int2_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00z10C00D( - BuiltInId::imageAtomicXorExt_IImage2D1_Int2_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01I10C00D( - BuiltInId::imageAtomicXorExt_UImage2D1_Int2_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00r20C00D( +constexpr const TFunction imageAtomicXorExt_00q20C00D( BuiltInId::imageAtomicXorExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01A20C00D( +constexpr const TFunction imageAtomicXorExt_00w20C00D( BuiltInId::imageAtomicXorExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01J20C00D( +constexpr const TFunction imageAtomicXorExt_01C20C00D( BuiltInId::imageAtomicXorExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00t20C00D( +constexpr const TFunction imageAtomicXorExt_00s20C00D( BuiltInId::imageAtomicXorExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01C20C00D( +constexpr const TFunction imageAtomicXorExt_00y20C00D( BuiltInId::imageAtomicXorExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01L20C00D( +constexpr const TFunction imageAtomicXorExt_01E20C00D( BuiltInId::imageAtomicXorExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00y00C00D( +constexpr const TFunction imageAtomicXorExt_00u00C00D( BuiltInId::imageAtomicXorExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01H00C00D( +constexpr const TFunction imageAtomicXorExt_01A00C00D( BuiltInId::imageAtomicXorExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01Q00C00D( +constexpr const TFunction imageAtomicXorExt_01G00C00D( BuiltInId::imageAtomicXorExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00s20C00D( +constexpr const TFunction imageAtomicXorExt_00r20C00D( BuiltInId::imageAtomicXorExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01B20C00D( +constexpr const TFunction imageAtomicXorExt_00x20C00D( BuiltInId::imageAtomicXorExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01K20C00D( +constexpr const TFunction imageAtomicXorExt_01D20C00D( BuiltInId::imageAtomicXorExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00w20C00D( +constexpr const TFunction imageAtomicXorExt_00t20C00D( BuiltInId::imageAtomicXorExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01F20C00D( +constexpr const TFunction imageAtomicXorExt_00z20C00D( BuiltInId::imageAtomicXorExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01O20C00D( +constexpr const TFunction imageAtomicXorExt_01F20C00D( BuiltInId::imageAtomicXorExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00x10C00D( - BuiltInId::imageAtomicXorExt_ImageRect1_Int2_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01G10C00D( - BuiltInId::imageAtomicXorExt_IImageRect1_Int2_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01P10C00D( - BuiltInId::imageAtomicXorExt_UImageRect1_Int2_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00u10C00C00D( - BuiltInId::imageAtomicXorExt_Image2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01D10C00C00D( - BuiltInId::imageAtomicXorExt_IImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01M10C00C00D( - BuiltInId::imageAtomicXorExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00v20C00C00D( - BuiltInId::imageAtomicXorExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01E20C00C00D( - BuiltInId::imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01N20C00C00D( - BuiltInId::imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00q10C00C( +constexpr const TFunction imageAtomicXorExt_00p10C00C( BuiltInId::imageAtomicXorExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, + BuiltInParameters::p00p10C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00z10C00C( +constexpr const TFunction imageAtomicXorExt_00v10C00C( BuiltInId::imageAtomicXorExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, + BuiltInParameters::p00v10C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01I10C00C( +constexpr const TFunction imageAtomicXorExt_01B10C00C( BuiltInId::imageAtomicXorExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, + BuiltInParameters::p01B10C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00r20C00C( +constexpr const TFunction imageAtomicXorExt_00q20C00C( BuiltInId::imageAtomicXorExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, + BuiltInParameters::p00q20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01A20C00C( +constexpr const TFunction imageAtomicXorExt_00w20C00C( BuiltInId::imageAtomicXorExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01J20C00C( +constexpr const TFunction imageAtomicXorExt_01C20C00C( BuiltInId::imageAtomicXorExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00t20C00C( +constexpr const TFunction imageAtomicXorExt_00s20C00C( BuiltInId::imageAtomicXorExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01C20C00C( +constexpr const TFunction imageAtomicXorExt_00y20C00C( BuiltInId::imageAtomicXorExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01L20C00C( +constexpr const TFunction imageAtomicXorExt_01E20C00C( BuiltInId::imageAtomicXorExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00y00C00C( +constexpr const TFunction imageAtomicXorExt_00u00C00C( BuiltInId::imageAtomicXorExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01H00C00C( +constexpr const TFunction imageAtomicXorExt_01A00C00C( BuiltInId::imageAtomicXorExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01Q00C00C( +constexpr const TFunction imageAtomicXorExt_01G00C00C( BuiltInId::imageAtomicXorExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00s20C00C( +constexpr const TFunction imageAtomicXorExt_00r20C00C( BuiltInId::imageAtomicXorExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01B20C00C( +constexpr const TFunction imageAtomicXorExt_00x20C00C( BuiltInId::imageAtomicXorExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01K20C00C( +constexpr const TFunction imageAtomicXorExt_01D20C00C( BuiltInId::imageAtomicXorExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00w20C00C( +constexpr const TFunction imageAtomicXorExt_00t20C00C( BuiltInId::imageAtomicXorExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01F20C00C( +constexpr const TFunction imageAtomicXorExt_00z20C00C( BuiltInId::imageAtomicXorExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_01O20C00C( +constexpr const TFunction imageAtomicXorExt_01F20C00C( BuiltInId::imageAtomicXorExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicXorExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00x10C00C( - BuiltInId::imageAtomicXorExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01G10C00C( - BuiltInId::imageAtomicXorExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01P10C00C( - BuiltInId::imageAtomicXorExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicXor, false); -constexpr const TFunction imageAtomicXorExt_00u10C00C00C( - BuiltInId::imageAtomicXorExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01D10C00C00C( - BuiltInId::imageAtomicXorExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01M10C00C00C( - BuiltInId::imageAtomicXorExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_00v20C00C00C( - BuiltInId::imageAtomicXorExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01E20C00C00C( - BuiltInId::imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicXorExt_01N20C00C00C( - BuiltInId::imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicXorExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicXor, - false); -constexpr const TFunction imageAtomicExchangeExt_00q10C00D( +constexpr const TFunction imageAtomicExchangeExt_00p10C00D( BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00z10C00D( +constexpr const TFunction imageAtomicExchangeExt_00v10C00D( BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01I10C00D( +constexpr const TFunction imageAtomicExchangeExt_01B10C00D( BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00r20C00D( +constexpr const TFunction imageAtomicExchangeExt_00q20C00D( BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01A20C00D( +constexpr const TFunction imageAtomicExchangeExt_00w20C00D( BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01J20C00D( +constexpr const TFunction imageAtomicExchangeExt_01C20C00D( BuiltInId::imageAtomicExchangeExt_UImage3D1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00t20C00D( +constexpr const TFunction imageAtomicExchangeExt_00s20C00D( BuiltInId::imageAtomicExchangeExt_ImageCube1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01C20C00D( +constexpr const TFunction imageAtomicExchangeExt_00y20C00D( BuiltInId::imageAtomicExchangeExt_IImageCube1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01L20C00D( +constexpr const TFunction imageAtomicExchangeExt_01E20C00D( BuiltInId::imageAtomicExchangeExt_UImageCube1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00y00C00D( +constexpr const TFunction imageAtomicExchangeExt_00u00C00D( BuiltInId::imageAtomicExchangeExt_ImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01H00C00D( +constexpr const TFunction imageAtomicExchangeExt_01A00C00D( BuiltInId::imageAtomicExchangeExt_IImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01Q00C00D( +constexpr const TFunction imageAtomicExchangeExt_01G00C00D( BuiltInId::imageAtomicExchangeExt_UImageBuffer1_Int1_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00s20C00D( +constexpr const TFunction imageAtomicExchangeExt_00r20C00D( BuiltInId::imageAtomicExchangeExt_Image2DArray1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01B20C00D( +constexpr const TFunction imageAtomicExchangeExt_00x20C00D( BuiltInId::imageAtomicExchangeExt_IImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01K20C00D( +constexpr const TFunction imageAtomicExchangeExt_01D20C00D( BuiltInId::imageAtomicExchangeExt_UImage2DArray1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00w20C00D( +constexpr const TFunction imageAtomicExchangeExt_00t20C00D( BuiltInId::imageAtomicExchangeExt_ImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01F20C00D( +constexpr const TFunction imageAtomicExchangeExt_00z20C00D( BuiltInId::imageAtomicExchangeExt_IImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01O20C00D( +constexpr const TFunction imageAtomicExchangeExt_01F20C00D( BuiltInId::imageAtomicExchangeExt_UImageCubeArray1_Int3_UInt1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, + BuiltInParameters::p01F20C00D00D, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00x10C00D( - BuiltInId::imageAtomicExchangeExt_ImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicExchangeExt_00p10C00C( + BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, + BuiltInParameters::p00p10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01G10C00D( - BuiltInId::imageAtomicExchangeExt_IImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicExchangeExt_00v10C00C( + BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, + BuiltInParameters::p00v10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01P10C00D( - BuiltInId::imageAtomicExchangeExt_UImageRect1_Int2_UInt1, +constexpr const TFunction imageAtomicExchangeExt_01B10C00C( + BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01B10C00C00C, 3, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00u10C00C00D( - BuiltInId::imageAtomicExchangeExt_Image2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicExchangeExt_00q20C00C( + BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 4, - StaticType::Get(), + BuiltInParameters::p00q20C00C00C, + 3, + StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01D10C00C00D( - BuiltInId::imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_UInt1, +constexpr const TFunction imageAtomicExchangeExt_00w20C00C( + BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01M10C00C00D( - BuiltInId::imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_UInt1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00v20C00C00D( - BuiltInId::imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01E20C00C00D( - BuiltInId::imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01N20C00C00D( - BuiltInId::imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_UInt1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00q10C00C( - BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00z10C00C( - BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01I10C00C( - BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00r20C00C( - BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01A20C00C( - BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, + BuiltInParameters::p00w20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01J20C00C( +constexpr const TFunction imageAtomicExchangeExt_01C20C00C( BuiltInId::imageAtomicExchangeExt_UImage3D1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00t20C00C( +constexpr const TFunction imageAtomicExchangeExt_00s20C00C( BuiltInId::imageAtomicExchangeExt_ImageCube1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01C20C00C( +constexpr const TFunction imageAtomicExchangeExt_00y20C00C( BuiltInId::imageAtomicExchangeExt_IImageCube1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01L20C00C( +constexpr const TFunction imageAtomicExchangeExt_01E20C00C( BuiltInId::imageAtomicExchangeExt_UImageCube1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00y00C00C( +constexpr const TFunction imageAtomicExchangeExt_00u00C00C( BuiltInId::imageAtomicExchangeExt_ImageBuffer1_Int1_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01H00C00C( +constexpr const TFunction imageAtomicExchangeExt_01A00C00C( BuiltInId::imageAtomicExchangeExt_IImageBuffer1_Int1_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01Q00C00C( +constexpr const TFunction imageAtomicExchangeExt_01G00C00C( BuiltInId::imageAtomicExchangeExt_UImageBuffer1_Int1_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00s20C00C( +constexpr const TFunction imageAtomicExchangeExt_00r20C00C( BuiltInId::imageAtomicExchangeExt_Image2DArray1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01B20C00C( +constexpr const TFunction imageAtomicExchangeExt_00x20C00C( BuiltInId::imageAtomicExchangeExt_IImage2DArray1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01K20C00C( +constexpr const TFunction imageAtomicExchangeExt_01D20C00C( BuiltInId::imageAtomicExchangeExt_UImage2DArray1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00w20C00C( +constexpr const TFunction imageAtomicExchangeExt_00t20C00C( BuiltInId::imageAtomicExchangeExt_ImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01F20C00C( +constexpr const TFunction imageAtomicExchangeExt_00z20C00C( BuiltInId::imageAtomicExchangeExt_IImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01O20C00C( +constexpr const TFunction imageAtomicExchangeExt_01F20C00C( BuiltInId::imageAtomicExchangeExt_UImageCubeArray1_Int3_Int1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00x10C00C( - BuiltInId::imageAtomicExchangeExt_ImageRect1_Int2_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01G10C00C( - BuiltInId::imageAtomicExchangeExt_IImageRect1_Int2_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01P10C00C( - BuiltInId::imageAtomicExchangeExt_UImageRect1_Int2_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00u10C00C00C( - BuiltInId::imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01D10C00C00C( - BuiltInId::imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01M10C00C00C( - BuiltInId::imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00v20C00C00C( - BuiltInId::imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01E20C00C00C( - BuiltInId::imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01N20C00C00C( - BuiltInId::imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Int1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00q10C00B( +constexpr const TFunction imageAtomicExchangeExt_00p10C00B( BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00B, + BuiltInParameters::p00p10C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00z10C00B( +constexpr const TFunction imageAtomicExchangeExt_00v10C00B( BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00B, + BuiltInParameters::p00v10C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01I10C00B( +constexpr const TFunction imageAtomicExchangeExt_01B10C00B( BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00B, + BuiltInParameters::p01B10C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00r20C00B( +constexpr const TFunction imageAtomicExchangeExt_00q20C00B( BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00B, + BuiltInParameters::p00q20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01A20C00B( +constexpr const TFunction imageAtomicExchangeExt_00w20C00B( BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00B, + BuiltInParameters::p00w20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01J20C00B( +constexpr const TFunction imageAtomicExchangeExt_01C20C00B( BuiltInId::imageAtomicExchangeExt_UImage3D1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00B, + BuiltInParameters::p01C20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00t20C00B( +constexpr const TFunction imageAtomicExchangeExt_00s20C00B( BuiltInId::imageAtomicExchangeExt_ImageCube1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00B, + BuiltInParameters::p00s20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01C20C00B( +constexpr const TFunction imageAtomicExchangeExt_00y20C00B( BuiltInId::imageAtomicExchangeExt_IImageCube1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00B, + BuiltInParameters::p00y20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01L20C00B( +constexpr const TFunction imageAtomicExchangeExt_01E20C00B( BuiltInId::imageAtomicExchangeExt_UImageCube1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00B, + BuiltInParameters::p01E20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00y00C00B( +constexpr const TFunction imageAtomicExchangeExt_00u00C00B( BuiltInId::imageAtomicExchangeExt_ImageBuffer1_Int1_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00B, + BuiltInParameters::p00u00C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01H00C00B( +constexpr const TFunction imageAtomicExchangeExt_01A00C00B( BuiltInId::imageAtomicExchangeExt_IImageBuffer1_Int1_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00B, + BuiltInParameters::p01A00C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01Q00C00B( +constexpr const TFunction imageAtomicExchangeExt_01G00C00B( BuiltInId::imageAtomicExchangeExt_UImageBuffer1_Int1_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00B, + BuiltInParameters::p01G00C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00s20C00B( +constexpr const TFunction imageAtomicExchangeExt_00r20C00B( BuiltInId::imageAtomicExchangeExt_Image2DArray1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00B, + BuiltInParameters::p00r20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01B20C00B( +constexpr const TFunction imageAtomicExchangeExt_00x20C00B( BuiltInId::imageAtomicExchangeExt_IImage2DArray1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00B, + BuiltInParameters::p00x20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01K20C00B( +constexpr const TFunction imageAtomicExchangeExt_01D20C00B( BuiltInId::imageAtomicExchangeExt_UImage2DArray1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00B, + BuiltInParameters::p01D20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00w20C00B( +constexpr const TFunction imageAtomicExchangeExt_00t20C00B( BuiltInId::imageAtomicExchangeExt_ImageCubeArray1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00B, + BuiltInParameters::p00t20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01F20C00B( +constexpr const TFunction imageAtomicExchangeExt_00z20C00B( BuiltInId::imageAtomicExchangeExt_IImageCubeArray1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00B, + BuiltInParameters::p00z20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_01O20C00B( +constexpr const TFunction imageAtomicExchangeExt_01F20C00B( BuiltInId::imageAtomicExchangeExt_UImageCubeArray1_Int3_Float1, BuiltInName::imageAtomicExchangeExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00B, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00x10C00B( - BuiltInId::imageAtomicExchangeExt_ImageRect1_Int2_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00B, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01G10C00B( - BuiltInId::imageAtomicExchangeExt_IImageRect1_Int2_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00B, - 3, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01P10C00B( - BuiltInId::imageAtomicExchangeExt_UImageRect1_Int2_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00B, + BuiltInParameters::p01F20C00B, 3, StaticType::Get(), EOpImageAtomicExchange, false); -constexpr const TFunction imageAtomicExchangeExt_00u10C00C00B( - BuiltInId::imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01D10C00C00B( - BuiltInId::imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01M10C00C00B( - BuiltInId::imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_00v20C00C00B( - BuiltInId::imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01E20C00C00B( - BuiltInId::imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicExchangeExt_01N20C00C00B( - BuiltInId::imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Float1, - BuiltInName::imageAtomicExchangeExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00B, - 4, - StaticType::Get(), - EOpImageAtomicExchange, - false); -constexpr const TFunction imageAtomicCompSwapExt_00q10C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00p10C00D00D( BuiltInId::imageAtomicCompSwapExt_Image2D1_Int2_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00D00D, + BuiltInParameters::p00p10C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00z10C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00v10C00D00D( BuiltInId::imageAtomicCompSwapExt_IImage2D1_Int2_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00D00D, + BuiltInParameters::p00v10C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01I10C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01B10C00D00D( BuiltInId::imageAtomicCompSwapExt_UImage2D1_Int2_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00D00D, + BuiltInParameters::p01B10C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00r20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00q20C00D00D( BuiltInId::imageAtomicCompSwapExt_Image3D1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00D00D, + BuiltInParameters::p00q20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01A20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00w20C00D00D( BuiltInId::imageAtomicCompSwapExt_IImage3D1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00D00D, + BuiltInParameters::p00w20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01J20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01C20C00D00D( BuiltInId::imageAtomicCompSwapExt_UImage3D1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00D00D, + BuiltInParameters::p01C20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00t20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00s20C00D00D( BuiltInId::imageAtomicCompSwapExt_ImageCube1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00D00D, + BuiltInParameters::p00s20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01C20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00y20C00D00D( BuiltInId::imageAtomicCompSwapExt_IImageCube1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00D00D, + BuiltInParameters::p00y20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01L20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01E20C00D00D( BuiltInId::imageAtomicCompSwapExt_UImageCube1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00D00D, + BuiltInParameters::p01E20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00y00C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00u00C00D00D( BuiltInId::imageAtomicCompSwapExt_ImageBuffer1_Int1_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00D00D, + BuiltInParameters::p00u00C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01H00C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01A00C00D00D( BuiltInId::imageAtomicCompSwapExt_IImageBuffer1_Int1_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00D00D, + BuiltInParameters::p01A00C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01Q00C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01G00C00D00D( BuiltInId::imageAtomicCompSwapExt_UImageBuffer1_Int1_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00D00D, + BuiltInParameters::p01G00C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00s20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00r20C00D00D( BuiltInId::imageAtomicCompSwapExt_Image2DArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00D00D, + BuiltInParameters::p00r20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01B20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00x20C00D00D( BuiltInId::imageAtomicCompSwapExt_IImage2DArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00D00D, + BuiltInParameters::p00x20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01K20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01D20C00D00D( BuiltInId::imageAtomicCompSwapExt_UImage2DArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00D00D, + BuiltInParameters::p01D20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00w20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00t20C00D00D( BuiltInId::imageAtomicCompSwapExt_ImageCubeArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00D00D, + BuiltInParameters::p00t20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01F20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_00z20C00D00D( BuiltInId::imageAtomicCompSwapExt_IImageCubeArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00D00D, + BuiltInParameters::p00z20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01O20C00D00D( +constexpr const TFunction imageAtomicCompSwapExt_01F20C00D00D( BuiltInId::imageAtomicCompSwapExt_UImageCubeArray1_Int3_UInt1_UInt1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00D00D, + BuiltInParameters::p01F20C00D00D, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00x10C00D00D( - BuiltInId::imageAtomicCompSwapExt_ImageRect1_Int2_UInt1_UInt1, +constexpr const TFunction imageAtomicCompSwapExt_00p10C00C00C( + BuiltInId::imageAtomicCompSwapExt_Image2D1_Int2_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00D00D, + BuiltInParameters::p00p10C00C00C, 4, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01G10C00D00D( - BuiltInId::imageAtomicCompSwapExt_IImageRect1_Int2_UInt1_UInt1, +constexpr const TFunction imageAtomicCompSwapExt_00v10C00C00C( + BuiltInId::imageAtomicCompSwapExt_IImage2D1_Int2_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00D00D, + BuiltInParameters::p00v10C00C00C, 4, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01P10C00D00D( - BuiltInId::imageAtomicCompSwapExt_UImageRect1_Int2_UInt1_UInt1, +constexpr const TFunction imageAtomicCompSwapExt_01B10C00C00C( + BuiltInId::imageAtomicCompSwapExt_UImage2D1_Int2_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00D00D, + BuiltInParameters::p01B10C00C00C, 4, - StaticType::Get(), + StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00u10C00C00D00D( - BuiltInId::imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_UInt1_UInt1, +constexpr const TFunction imageAtomicCompSwapExt_00q20C00C00C( + BuiltInId::imageAtomicCompSwapExt_Image3D1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00D00D, - 5, - StaticType::Get(), + BuiltInParameters::p00q20C00C00C, + 4, + StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01D10C00C00D00D( - BuiltInId::imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_UInt1_UInt1, +constexpr const TFunction imageAtomicCompSwapExt_00w20C00C00C( + BuiltInId::imageAtomicCompSwapExt_IImage3D1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00D00D, - 5, - StaticType::Get(), + BuiltInParameters::p00w20C00C00C, + 4, + StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01M10C00C00D00D( - BuiltInId::imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_00v20C00C00D00D( - BuiltInId::imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01E20C00C00D00D( - BuiltInId::imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01N20C00C00D00D( - BuiltInId::imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_UInt1_UInt1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00D00D, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_00q10C00C00C( - BuiltInId::imageAtomicCompSwapExt_Image2D1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00q10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_00z10C00C00C( - BuiltInId::imageAtomicCompSwapExt_IImage2D1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00z10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01I10C00C00C( - BuiltInId::imageAtomicCompSwapExt_UImage2D1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01I10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_00r20C00C00C( - BuiltInId::imageAtomicCompSwapExt_Image3D1_Int3_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00r20C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01A20C00C00C( - BuiltInId::imageAtomicCompSwapExt_IImage3D1_Int3_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01A20C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01J20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_01C20C00C00C( BuiltInId::imageAtomicCompSwapExt_UImage3D1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01J20C00C00C, + BuiltInParameters::p01C20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00t20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00s20C00C00C( BuiltInId::imageAtomicCompSwapExt_ImageCube1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00t20C00C00C, + BuiltInParameters::p00s20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01C20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00y20C00C00C( BuiltInId::imageAtomicCompSwapExt_IImageCube1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01C20C00C00C, + BuiltInParameters::p00y20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01L20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_01E20C00C00C( BuiltInId::imageAtomicCompSwapExt_UImageCube1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01L20C00C00C, + BuiltInParameters::p01E20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00y00C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00u00C00C00C( BuiltInId::imageAtomicCompSwapExt_ImageBuffer1_Int1_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00y00C00C00C, + BuiltInParameters::p00u00C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01H00C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_01A00C00C00C( BuiltInId::imageAtomicCompSwapExt_IImageBuffer1_Int1_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01H00C00C00C, + BuiltInParameters::p01A00C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01Q00C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_01G00C00C00C( BuiltInId::imageAtomicCompSwapExt_UImageBuffer1_Int1_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01Q00C00C00C, + BuiltInParameters::p01G00C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00s20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00r20C00C00C( BuiltInId::imageAtomicCompSwapExt_Image2DArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00s20C00C00C, + BuiltInParameters::p00r20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01B20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00x20C00C00C( BuiltInId::imageAtomicCompSwapExt_IImage2DArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01B20C00C00C, + BuiltInParameters::p00x20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01K20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_01D20C00C00C( BuiltInId::imageAtomicCompSwapExt_UImage2DArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01K20C00C00C, + BuiltInParameters::p01D20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00w20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00t20C00C00C( BuiltInId::imageAtomicCompSwapExt_ImageCubeArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00w20C00C00C, + BuiltInParameters::p00t20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01F20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_00z20C00C00C( BuiltInId::imageAtomicCompSwapExt_IImageCubeArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01F20C00C00C, + BuiltInParameters::p00z20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_01O20C00C00C( +constexpr const TFunction imageAtomicCompSwapExt_01F20C00C00C( BuiltInId::imageAtomicCompSwapExt_UImageCubeArray1_Int3_Int1_Int1, BuiltInName::imageAtomicCompSwapExt, std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01O20C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_00x10C00C00C( - BuiltInId::imageAtomicCompSwapExt_ImageRect1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00x10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01G10C00C00C( - BuiltInId::imageAtomicCompSwapExt_IImageRect1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01G10C00C00C, - 4, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01P10C00C00C( - BuiltInId::imageAtomicCompSwapExt_UImageRect1_Int2_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01P10C00C00C, + BuiltInParameters::p01F20C00C00C, 4, StaticType::Get(), EOpImageAtomicCompSwap, false); -constexpr const TFunction imageAtomicCompSwapExt_00u10C00C00C00C( - BuiltInId::imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00u10C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01D10C00C00C00C( - BuiltInId::imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01D10C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01M10C00C00C00C( - BuiltInId::imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01M10C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_00v20C00C00C00C( - BuiltInId::imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p00v20C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01E20C00C00C00C( - BuiltInId::imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01E20C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction imageAtomicCompSwapExt_01N20C00C00C00C( - BuiltInId::imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_Int1_Int1, - BuiltInName::imageAtomicCompSwapExt, - std::array{{TExtension::OES_shader_image_atomic}}, - BuiltInParameters::p01N20C00C00C00C, - 5, - StaticType::Get(), - EOpImageAtomicCompSwap, - false); -constexpr const TFunction pixelLocalLoadANGLE_01R( +constexpr const TFunction pixelLocalLoadANGLE_01H( BuiltInId::pixelLocalLoadANGLE_PixelLocalANGLE1, BuiltInName::pixelLocalLoadANGLE, std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, - BuiltInParameters::p01R30B, + BuiltInParameters::p01H30B, 1, StaticType::Get(), EOpPixelLocalLoadANGLE, true); -constexpr const TFunction pixelLocalLoadANGLE_01S( +constexpr const TFunction pixelLocalLoadANGLE_01I( BuiltInId::pixelLocalLoadANGLE_IPixelLocalANGLE1, BuiltInName::pixelLocalLoadANGLE, std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, - BuiltInParameters::p01S30C, + BuiltInParameters::p01I30C, 1, StaticType::Get(), EOpPixelLocalLoadANGLE, true); -constexpr const TFunction pixelLocalLoadANGLE_01T( +constexpr const TFunction pixelLocalLoadANGLE_01J( BuiltInId::pixelLocalLoadANGLE_UPixelLocalANGLE1, BuiltInName::pixelLocalLoadANGLE, std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, - BuiltInParameters::p01T30D, + BuiltInParameters::p01J30D, 1, StaticType::Get(), EOpPixelLocalLoadANGLE, true); -constexpr const TFunction pixelLocalStoreANGLE_01R30B( +constexpr const TFunction pixelLocalStoreANGLE_01H30B( BuiltInId::pixelLocalStoreANGLE_PixelLocalANGLE1_Float4, BuiltInName::pixelLocalStoreANGLE, std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, - BuiltInParameters::p01R30B, + BuiltInParameters::p01H30B, 2, StaticType::Get(), EOpPixelLocalStoreANGLE, false); -constexpr const TFunction pixelLocalStoreANGLE_01S30C( +constexpr const TFunction pixelLocalStoreANGLE_01I30C( BuiltInId::pixelLocalStoreANGLE_IPixelLocalANGLE1_Int4, BuiltInName::pixelLocalStoreANGLE, std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, - BuiltInParameters::p01S30C, + BuiltInParameters::p01I30C, 2, StaticType::Get(), EOpPixelLocalStoreANGLE, false); -constexpr const TFunction pixelLocalStoreANGLE_01T30D( +constexpr const TFunction pixelLocalStoreANGLE_01J30D( BuiltInId::pixelLocalStoreANGLE_UPixelLocalANGLE1_UInt4, BuiltInName::pixelLocalStoreANGLE, std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, - BuiltInParameters::p01T30D, + BuiltInParameters::p01J30D, 2, StaticType::Get(), EOpPixelLocalStoreANGLE, @@ -20068,27 +17238,27 @@ constexpr const TFunction EndPrimitiveES3_2_( StaticType::Get(), EOpEndPrimitive, false); -constexpr const TFunction subpassLoad_01U( +constexpr const TFunction subpassLoad_01K( BuiltInId::subpassLoad_SubpassInput1, BuiltInName::subpassLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01U, + BuiltInParameters::p01K, 1, StaticType::Get(), EOpSubpassLoad, true); -constexpr const TFunction subpassLoad_01V(BuiltInId::subpassLoad_ISubpassInput1, +constexpr const TFunction subpassLoad_01L(BuiltInId::subpassLoad_ISubpassInput1, BuiltInName::subpassLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01V, + BuiltInParameters::p01L, 1, StaticType::Get(), EOpSubpassLoad, true); -constexpr const TFunction subpassLoad_01W(BuiltInId::subpassLoad_USubpassInput1, +constexpr const TFunction subpassLoad_01M(BuiltInId::subpassLoad_USubpassInput1, BuiltInName::subpassLoad, std::array{{TExtension::UNDEFINED}}, - BuiltInParameters::p01W, + BuiltInParameters::p01M, 1, StaticType::Get(), EOpSubpassLoad, @@ -20146,6 +17316,15 @@ constexpr const TFunction interpolateAtCenter_30B( StaticType::Get(), EOpInterpolateAtCenter, true); +constexpr const TFunction loopForwardProgress_( + BuiltInId::loopForwardProgress, + BuiltInName::loopForwardProgress, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpLoopForwardProgress, + false); constexpr const TFunction saturate_00B(BuiltInId::saturate_Float1, BuiltInName::saturate, std::array{{TExtension::UNDEFINED}}, @@ -20700,7 +17879,7 @@ constexpr SymbolRule kRules[] = { &texture2DProjGradEXT_00H30B10B10B), Rule::Get<100, Shader::ALL, EXT_INDEX(EXT_shader_texture_lod)>( &textureCubeGradEXT_00J20B20B20B), - Rule::Get<100, Shader::ALL, 0>(&textureVideoWEBGL_00p10B), + Rule::Get<100, Shader::ALL, 0>(&textureVideoWEBGL_00o10B), Rule::Get<100, Shader::FRAGMENT, 0>(&texture2D_00H10B00B), Rule::Get<100, Shader::FRAGMENT, 0>(&texture2DProj_00H20B00B), Rule::Get<100, Shader::FRAGMENT, 0>(&texture2DProj_00H30B00B), @@ -20738,19 +17917,19 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::ALL, 0>(&texture_00g30B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00g30B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00g30B), - Rule::Get<320, Shader::ALL, 0>(&texture_00l30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00l30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00l30B), - Rule::Get<320, Shader::ALL, 0>(&texture_00o30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00o30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00o30B), + Rule::Get<320, Shader::ALL, 0>(&texture_00k30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00k30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00k30B), + Rule::Get<320, Shader::ALL, 0>(&texture_00n30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00n30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00n30B), Rule::Get<320, Shader::ALL, 0>(&texture_00h30B00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00h30B00B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00h30B00B), Rule::Get<300, Shader::ALL, EXT_INDEX(OES_EGL_image_external_essl3)>(&texture_00L10B), Rule::Get<300, Shader::ALL, EXT_INDEX(EXT_YUV_target)>(&texture_00M10B), Rule::Get<300, Shader::ALL, EXT_INDEX(ARB_texture_rectangle)>(&texture_00N10B), - Rule::Get<300, Shader::ALL, 0>(&texture_00p10B), + Rule::Get<300, Shader::ALL, 0>(&texture_00o10B), Rule::Get<300, Shader::ALL, 0>(&textureProj_00H20B), Rule::Get<300, Shader::ALL, 0>(&textureProj_00Q20B), Rule::Get<300, Shader::ALL, 0>(&textureProj_00W20B), @@ -20786,12 +17965,12 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::ALL, 0>(&textureLod_00g30B00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureLodExt_00g30B00B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureLodExt_00g30B00B), - Rule::Get<320, Shader::ALL, 0>(&textureLod_00l30B00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureLodExt_00l30B00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureLodExt_00l30B00B), - Rule::Get<320, Shader::ALL, 0>(&textureLod_00o30B00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureLodExt_00o30B00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureLodExt_00o30B00B), + Rule::Get<320, Shader::ALL, 0>(&textureLod_00k30B00B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureLodExt_00k30B00B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureLodExt_00k30B00B), + Rule::Get<320, Shader::ALL, 0>(&textureLod_00n30B00B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureLodExt_00n30B00B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureLodExt_00n30B00B), Rule::Get<300, Shader::ALL, 0>(&textureSize_00H00C), Rule::Get<300, Shader::ALL, 0>(&textureSize_00Q00C), Rule::Get<300, Shader::ALL, 0>(&textureSize_00W00C), @@ -20810,24 +17989,24 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::ALL, 0>(&textureSize_00g00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureSizeExt_00g00C), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureSizeExt_00g00C), - Rule::Get<320, Shader::ALL, 0>(&textureSize_00l00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureSizeExt_00l00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureSizeExt_00l00C), - Rule::Get<320, Shader::ALL, 0>(&textureSize_00o00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureSizeExt_00o00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureSizeExt_00o00C), + Rule::Get<320, Shader::ALL, 0>(&textureSize_00k00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureSizeExt_00k00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureSizeExt_00k00C), + Rule::Get<320, Shader::ALL, 0>(&textureSize_00n00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureSizeExt_00n00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureSizeExt_00n00C), Rule::Get<320, Shader::ALL, 0>(&textureSize_00h00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureSizeExt_00h00C), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureSizeExt_00h00C), Rule::Get<320, Shader::ALL, 0>(&textureSize_00f), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&textureSizeExt_00f), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&textureSizeExt_00f), - Rule::Get<320, Shader::ALL, 0>(&textureSize_00k), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&textureSizeExt_00k), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&textureSizeExt_00k), - Rule::Get<320, Shader::ALL, 0>(&textureSize_00n), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&textureSizeExt_00n), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&textureSizeExt_00n), + Rule::Get<320, Shader::ALL, 0>(&textureSize_00j), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&textureSizeExt_00j), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&textureSizeExt_00j), + Rule::Get<320, Shader::ALL, 0>(&textureSize_00m), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&textureSizeExt_00m), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&textureSizeExt_00m), Rule::Get<310, Shader::ALL, 0>(&textureSize_00O), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_texture_multisample)>(&textureSizeExt_00O), Rule::Get<310, Shader::ALL, 0>(&textureSize_00U), @@ -20867,12 +18046,12 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::ALL, 0>(&texelFetch_00f00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&texelFetchExt_00f00C), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&texelFetchExt_00f00C), - Rule::Get<320, Shader::ALL, 0>(&texelFetch_00k00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&texelFetchExt_00k00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&texelFetchExt_00k00C), - Rule::Get<320, Shader::ALL, 0>(&texelFetch_00n00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&texelFetchExt_00n00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&texelFetchExt_00n00C), + Rule::Get<320, Shader::ALL, 0>(&texelFetch_00j00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&texelFetchExt_00j00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&texelFetchExt_00j00C), + Rule::Get<320, Shader::ALL, 0>(&texelFetch_00m00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&texelFetchExt_00m00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&texelFetchExt_00m00C), Rule::Get<310, Shader::ALL, 0>(&texelFetch_00O10C00C), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_texture_multisample)>(&texelFetchExt_00O10C00C), Rule::Get<310, Shader::ALL, 0>(&texelFetch_00U10C00C), @@ -20910,16 +18089,16 @@ constexpr SymbolRule kRules[] = { &textureGradExt_00g30B20B20B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>( &textureGradExt_00g30B20B20B), - Rule::Get<320, Shader::ALL, 0>(&textureGrad_00l30B20B20B), + Rule::Get<320, Shader::ALL, 0>(&textureGrad_00k30B20B20B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>( - &textureGradExt_00l30B20B20B), + &textureGradExt_00k30B20B20B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>( - &textureGradExt_00l30B20B20B), - Rule::Get<320, Shader::ALL, 0>(&textureGrad_00o30B20B20B), + &textureGradExt_00k30B20B20B), + Rule::Get<320, Shader::ALL, 0>(&textureGrad_00n30B20B20B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>( - &textureGradExt_00o30B20B20B), + &textureGradExt_00n30B20B20B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>( - &textureGradExt_00o30B20B20B), + &textureGradExt_00n30B20B20B), Rule::Get<300, Shader::ALL, 0>(&textureProjGrad_00H20B10B10B), Rule::Get<300, Shader::ALL, 0>(&textureProjGrad_00Q20B10B10B), Rule::Get<300, Shader::ALL, 0>(&textureProjGrad_00W20B10B10B), @@ -20958,12 +18137,12 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::FRAGMENT, 0>(&texture_00g30B00B), Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00g30B00B), Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00g30B00B), - Rule::Get<320, Shader::FRAGMENT, 0>(&texture_00l30B00B), - Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00l30B00B), - Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00l30B00B), - Rule::Get<320, Shader::FRAGMENT, 0>(&texture_00o30B00B), - Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00o30B00B), - Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00o30B00B), + Rule::Get<320, Shader::FRAGMENT, 0>(&texture_00k30B00B), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00k30B00B), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00k30B00B), + Rule::Get<320, Shader::FRAGMENT, 0>(&texture_00n30B00B), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(OES_texture_cube_map_array)>(&textureExt_00n30B00B), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_cube_map_array)>(&textureExt_00n30B00B), Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_shadow_lod)>(&texture_00h30B00B00B), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(OES_EGL_image_external_essl3)>(&texture_00L10B00B), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(OES_EGL_image_external_essl3)>( @@ -21070,47 +18249,44 @@ constexpr SymbolRule kRules[] = { Rule::Get<310, Shader::ALL, 0>(&textureGather_00H10B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00Q10B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00W10B), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00H10B00C), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00Q10B00C), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00W10B00C), Rule::Get<310, Shader::ALL, 0>(&textureGather_00K20B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00T20B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00Z20B), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00K20B00C), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00T20B00C), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00Z20B00C), Rule::Get<310, Shader::ALL, 0>(&textureGather_00J20B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00S20B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00Y20B), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00J20B00C), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00S20B00C), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00Y20B00C), Rule::Get<320, Shader::ALL, 0>(&textureGather_00g30B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00g30B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00g30B), - Rule::Get<320, Shader::ALL, 0>(&textureGather_00l30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00l30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00l30B), - Rule::Get<320, Shader::ALL, 0>(&textureGather_00o30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00o30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00o30B), + Rule::Get<320, Shader::ALL, 0>(&textureGather_00k30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00k30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00k30B), + Rule::Get<320, Shader::ALL, 0>(&textureGather_00n30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00n30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00n30B), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00H10B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00Q10B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00W10B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00K20B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00T20B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00Z20B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00J20B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00S20B00C), + Rule::Get<310, Shader::ALL, 0>(&textureGather_00Y20B00C), Rule::Get<320, Shader::ALL, 0>(&textureGather_00g30B00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00g30B00C), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00g30B00C), - Rule::Get<320, Shader::ALL, 0>(&textureGather_00l30B00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00l30B00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00l30B00C), - Rule::Get<320, Shader::ALL, 0>(&textureGather_00o30B00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00o30B00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00o30B00C), + Rule::Get<320, Shader::ALL, 0>(&textureGather_00k30B00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00k30B00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00k30B00C), + Rule::Get<320, Shader::ALL, 0>(&textureGather_00n30B00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00n30B00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00n30B00C), Rule::Get<320, Shader::ALL, 0>(&textureGather_00h30B00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&textureGatherExt_00h30B00B), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&textureGatherExt_00h30B00B), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00c10B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00c10B00B), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00e20B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00e20B00B), - Rule::Get<310, Shader::ALL, 0>(&textureGather_00d20B), Rule::Get<310, Shader::ALL, 0>(&textureGather_00d20B00B), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00H10B10C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00Q10B10C), @@ -21118,14 +18294,14 @@ constexpr SymbolRule kRules[] = { Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00K20B10C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00T20B10C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00Z20B10C), - Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00c10B00B10C), - Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00e20B00B10C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00H10B10C00C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00Q10B10C00C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00W10B10C00C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00K20B10C00C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00T20B10C00C), Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00Z20B10C00C), + Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00c10B00B10C), + Rule::Get<310, Shader::ALL, 0>(&textureGatherOffset_00e20B00B10C), Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00H10B10Cx4), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>(&textureGatherOffsetsExt_00H10B10Cx4), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>(&textureGatherOffsetsExt_00H10B10Cx4), @@ -21144,16 +18320,6 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00Z20B10Cx4), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>(&textureGatherOffsetsExt_00Z20B10Cx4), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>(&textureGatherOffsetsExt_00Z20B10Cx4), - Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00c10B00B10Cx4), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>( - &textureGatherOffsetsExt_00c10B00B10Cx4), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>( - &textureGatherOffsetsExt_00c10B00B10Cx4), - Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00e20B00B10Cx4), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>( - &textureGatherOffsetsExt_00e20B00B10Cx4), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>( - &textureGatherOffsetsExt_00e20B00B10Cx4), Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00H10B10Cx400C), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>( &textureGatherOffsetsExt_00H10B10Cx400C), @@ -21184,6 +18350,16 @@ constexpr SymbolRule kRules[] = { &textureGatherOffsetsExt_00Z20B10Cx400C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>( &textureGatherOffsetsExt_00Z20B10Cx400C), + Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00c10B00B10Cx4), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>( + &textureGatherOffsetsExt_00c10B00B10Cx4), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>( + &textureGatherOffsetsExt_00c10B00B10Cx4), + Rule::Get<320, Shader::ALL, 0>(&textureGatherOffsets_00e20B00B10Cx4), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_gpu_shader5)>( + &textureGatherOffsetsExt_00e20B00B10Cx4), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_gpu_shader5)>( + &textureGatherOffsetsExt_00e20B00B10Cx4), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00H10B), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00Q10B), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00W10B), @@ -21200,8 +18376,8 @@ constexpr SymbolRule kRules[] = { Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00d20B), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00e10B), Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00g20B), - Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00l20B), - Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00o20B), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00k20B), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00n20B), Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_texture_query_lod)>(&textureQueryLOD_00h20B), Rule::Get<300, Shader::ALL, EXT_INDEX(EXT_YUV_target)>(&rgb_2_yuv_20B00G), Rule::Get<300, Shader::ALL, EXT_INDEX(EXT_YUV_target)>(&yuv_2_rgb_20B00G), @@ -21284,1221 +18460,810 @@ constexpr SymbolRule kRules[] = { Rule::Get<310, Shader::ALL, 0>(&atomicExchange_00C00C), Rule::Get<310, Shader::ALL, 0>(&atomicCompSwap_00D00D00D), Rule::Get<310, Shader::ALL, 0>(&atomicCompSwap_00C00C00C), + Rule::Get<310, Shader::ALL, 0>(&imageSize_00p), + Rule::Get<310, Shader::ALL, 0>(&imageSize_00v), + Rule::Get<310, Shader::ALL, 0>(&imageSize_01B), Rule::Get<310, Shader::ALL, 0>(&imageSize_00q), - Rule::Get<310, Shader::ALL, 0>(&imageSize_00z), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01I), + Rule::Get<310, Shader::ALL, 0>(&imageSize_00w), + Rule::Get<310, Shader::ALL, 0>(&imageSize_01C), Rule::Get<310, Shader::ALL, 0>(&imageSize_00r), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01A), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01J), + Rule::Get<310, Shader::ALL, 0>(&imageSize_00x), + Rule::Get<310, Shader::ALL, 0>(&imageSize_01D), Rule::Get<310, Shader::ALL, 0>(&imageSize_00s), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01B), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01K), - Rule::Get<310, Shader::ALL, 0>(&imageSize_00t), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01C), - Rule::Get<310, Shader::ALL, 0>(&imageSize_01L), - Rule::Get<320, Shader::ALL, 0>(&imageSize_00w), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageSizeExt_00w), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageSizeExt_00w), + Rule::Get<310, Shader::ALL, 0>(&imageSize_00y), + Rule::Get<310, Shader::ALL, 0>(&imageSize_01E), + Rule::Get<320, Shader::ALL, 0>(&imageSize_00t), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageSizeExt_00t), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageSizeExt_00t), + Rule::Get<320, Shader::ALL, 0>(&imageSize_00z), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageSizeExt_00z), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageSizeExt_00z), Rule::Get<320, Shader::ALL, 0>(&imageSize_01F), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageSizeExt_01F), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageSizeExt_01F), - Rule::Get<320, Shader::ALL, 0>(&imageSize_01O), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageSizeExt_01O), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageSizeExt_01O), - Rule::Get<320, Shader::ALL, 0>(&imageSize_00y), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageSizeExt_00y), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageSizeExt_00y), - Rule::Get<320, Shader::ALL, 0>(&imageSize_01H), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageSizeExt_01H), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageSizeExt_01H), - Rule::Get<320, Shader::ALL, 0>(&imageSize_01Q), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageSizeExt_01Q), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageSizeExt_01Q), - Rule::Get<310, Shader::ALL, 0>(&imageStore_00q10C30B), - Rule::Get<310, Shader::ALL, 0>(&imageStore_00z10C30C), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01I10C30D), + Rule::Get<320, Shader::ALL, 0>(&imageSize_00u), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageSizeExt_00u), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageSizeExt_00u), + Rule::Get<320, Shader::ALL, 0>(&imageSize_01A), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageSizeExt_01A), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageSizeExt_01A), + Rule::Get<320, Shader::ALL, 0>(&imageSize_01G), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageSizeExt_01G), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageSizeExt_01G), + Rule::Get<310, Shader::ALL, 0>(&imageStore_00p10C30B), + Rule::Get<310, Shader::ALL, 0>(&imageStore_00v10C30C), + Rule::Get<310, Shader::ALL, 0>(&imageStore_01B10C30D), + Rule::Get<310, Shader::ALL, 0>(&imageStore_00q20C30B), + Rule::Get<310, Shader::ALL, 0>(&imageStore_00w20C30C), + Rule::Get<310, Shader::ALL, 0>(&imageStore_01C20C30D), Rule::Get<310, Shader::ALL, 0>(&imageStore_00r20C30B), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01A20C30C), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01J20C30D), + Rule::Get<310, Shader::ALL, 0>(&imageStore_00x20C30C), + Rule::Get<310, Shader::ALL, 0>(&imageStore_01D20C30D), Rule::Get<310, Shader::ALL, 0>(&imageStore_00s20C30B), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01B20C30C), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01K20C30D), - Rule::Get<310, Shader::ALL, 0>(&imageStore_00t20C30B), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01C20C30C), - Rule::Get<310, Shader::ALL, 0>(&imageStore_01L20C30D), - Rule::Get<320, Shader::ALL, 0>(&imageStore_00w20C30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageStoreExt_00w20C30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageStoreExt_00w20C30B), - Rule::Get<320, Shader::ALL, 0>(&imageStore_01F20C30C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageStoreExt_01F20C30C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageStoreExt_01F20C30C), - Rule::Get<320, Shader::ALL, 0>(&imageStore_01O20C30D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageStoreExt_01O20C30D), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageStoreExt_01O20C30D), - Rule::Get<320, Shader::ALL, 0>(&imageStore_00y00C30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageStoreExt_00y00C30B), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageStoreExt_00y00C30B), - Rule::Get<320, Shader::ALL, 0>(&imageStore_01H00C30C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageStoreExt_01H00C30C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageStoreExt_01H00C30C), - Rule::Get<320, Shader::ALL, 0>(&imageStore_01Q00C30D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageStoreExt_01Q00C30D), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageStoreExt_01Q00C30D), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_00q10C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_00z10C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01I10C), + Rule::Get<310, Shader::ALL, 0>(&imageStore_00y20C30C), + Rule::Get<310, Shader::ALL, 0>(&imageStore_01E20C30D), + Rule::Get<320, Shader::ALL, 0>(&imageStore_00t20C30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageStoreExt_00t20C30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageStoreExt_00t20C30B), + Rule::Get<320, Shader::ALL, 0>(&imageStore_00z20C30C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageStoreExt_00z20C30C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageStoreExt_00z20C30C), + Rule::Get<320, Shader::ALL, 0>(&imageStore_01F20C30D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageStoreExt_01F20C30D), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageStoreExt_01F20C30D), + Rule::Get<320, Shader::ALL, 0>(&imageStore_00u00C30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageStoreExt_00u00C30B), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageStoreExt_00u00C30B), + Rule::Get<320, Shader::ALL, 0>(&imageStore_01A00C30C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageStoreExt_01A00C30C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageStoreExt_01A00C30C), + Rule::Get<320, Shader::ALL, 0>(&imageStore_01G00C30D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageStoreExt_01G00C30D), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageStoreExt_01G00C30D), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_00p10C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_00v10C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_01B10C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_00q20C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_00w20C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_01C20C), Rule::Get<310, Shader::ALL, 0>(&imageLoad_00r20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01A20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01J20C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_00x20C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_01D20C), Rule::Get<310, Shader::ALL, 0>(&imageLoad_00s20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01B20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01K20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_00t20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01C20C), - Rule::Get<310, Shader::ALL, 0>(&imageLoad_01L20C), - Rule::Get<320, Shader::ALL, 0>(&imageLoad_00w20C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageLoadExt_00w20C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageLoadExt_00w20C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_00y20C), + Rule::Get<310, Shader::ALL, 0>(&imageLoad_01E20C), + Rule::Get<320, Shader::ALL, 0>(&imageLoad_00t20C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageLoadExt_00t20C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageLoadExt_00t20C), + Rule::Get<320, Shader::ALL, 0>(&imageLoad_00z20C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageLoadExt_00z20C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageLoadExt_00z20C), Rule::Get<320, Shader::ALL, 0>(&imageLoad_01F20C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageLoadExt_01F20C), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageLoadExt_01F20C), - Rule::Get<320, Shader::ALL, 0>(&imageLoad_01O20C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_cube_map_array)>(&imageLoadExt_01O20C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_cube_map_array)>(&imageLoadExt_01O20C), - Rule::Get<320, Shader::ALL, 0>(&imageLoad_00y00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageLoadExt_00y00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageLoadExt_00y00C), - Rule::Get<320, Shader::ALL, 0>(&imageLoad_01H00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageLoadExt_01H00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageLoadExt_01H00C), - Rule::Get<320, Shader::ALL, 0>(&imageLoad_01Q00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageLoadExt_01Q00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageLoadExt_01Q00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00q10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00z10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00t20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageLoad_00u00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageLoadExt_00u00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageLoadExt_00u00C), + Rule::Get<320, Shader::ALL, 0>(&imageLoad_01A00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageLoadExt_01A00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageLoadExt_01A00C), + Rule::Get<320, Shader::ALL, 0>(&imageLoad_01G00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_texture_buffer)>(&imageLoadExt_01G00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_texture_buffer)>(&imageLoadExt_01G00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00p10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00v10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01B10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00q20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00w20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01B20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00w20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00y20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01E20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00u00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01A00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01G00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00r20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00x20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01D20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00t20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00z20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00z20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01O20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00x10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01G10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01P10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00u10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01D10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01M10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00v20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01E20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01N20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00q10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00z10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01I10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00r20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00t20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00p10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00v10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01B10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00q20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00w20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00w20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00y20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01E20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00u00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01A00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01G00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00r20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00x20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01D20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00t20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00z20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00z20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01P10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAddExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00u10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01D10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01M10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_00v20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01E20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAdd_01N20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAddExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00q10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00z10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00t20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00p10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00v10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01B10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00q20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00w20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01B20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00w20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00y20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01E20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00u00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01A00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01G00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00r20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00x20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01D20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00t20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00z20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00z20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01O20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00x10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01G10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01P10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00u10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01D10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01M10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00v20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01E20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01N20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00q10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00z10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01I10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00r20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00t20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00p10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00v10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01B10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00q20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00w20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00w20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00y20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01E20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00u00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01A00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01G00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00r20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00x20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01D20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00t20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00z20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00z20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01P10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMinExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00u10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01D10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01M10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_00v20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01E20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMin_01N20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMinExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00q10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00z10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00t20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00p10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00v10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01B10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00q20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00w20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01B20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00w20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00y20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01E20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00u00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01A00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01G00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00r20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00x20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01D20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00t20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00z20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00z20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01O20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00x10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01G10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01P10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00u10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01D10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01M10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00v20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01E20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01N20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00q10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00z10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01I10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00r20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00t20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00p10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00v10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01B10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00q20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00w20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00w20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00y20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01E20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00u00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01A00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01G00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00r20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00x20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01D20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00t20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00z20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00z20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01P10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicMaxExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00u10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01D10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01M10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_00v20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01E20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicMax_01N20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicMaxExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00q10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00z10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00t20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00p10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00v10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01B10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00q20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00w20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01B20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00w20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00y20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01E20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00u00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01A00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01G00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00r20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00x20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01D20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00t20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00z20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00z20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01O20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00x10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01G10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01P10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00u10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01D10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01M10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00v20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01E20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01N20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00q10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00z10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01I10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00r20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00t20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00p10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00v10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01B10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00q20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00w20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00w20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00y20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01E20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00u00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01A00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01G00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00r20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00x20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01D20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00t20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00z20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00z20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01P10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicAndExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00u10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01D10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01M10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_00v20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01E20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicAnd_01N20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicAndExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00q10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00z10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00t20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00p10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00v10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01B10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00q20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00w20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01B20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00w20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00y20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01E20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00u00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01A00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01G00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00r20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00x20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01D20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00t20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00z20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00z20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01O20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00x10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01G10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01P10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00u10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01D10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01M10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00v20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01E20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01N20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00q10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00z10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01I10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00r20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00t20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00p10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00v10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01B10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00q20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00w20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00w20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00y20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01E20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00u00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01A00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01G00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00r20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00x20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01D20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00t20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00z20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00z20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01P10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00u10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01D10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01M10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_00v20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01E20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicOr_01N20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicOrExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00q10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00z10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00t20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00p10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00v10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01B10C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00q20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00w20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01B20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00w20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00y20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01E20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00u00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01A00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01G00C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00r20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00x20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01D20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00t20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00z20C00D), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00z20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01O20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00x10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01G10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01P10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00u10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01D10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01M10C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00v20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01E20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01N20C00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00q10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00z10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01I10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00r20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00t20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00p10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00v10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01B10C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00q20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00w20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00w20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00y20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01E20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00u00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01A00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01G00C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00r20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00x20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01D20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00t20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00z20C00C), + Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00z20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01P10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>(&imageAtomicXorExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00u10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01D10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01M10C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_00v20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01E20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00p10C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicXor_01N20C00C00C), + &imageAtomicExchangeExt_00p10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00v10C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicXorExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00q10C00D), + &imageAtomicExchangeExt_00v10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01B10C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00q10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00z10C00D), + &imageAtomicExchangeExt_01B10C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00q20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00z10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01I10C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01I10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00r20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00r20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01A20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01A20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01J20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01J20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00t20C00D), + &imageAtomicExchangeExt_00q20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00w20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00t20C00D), + &imageAtomicExchangeExt_00w20C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01C20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicExchangeExt_01C20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01L20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01L20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00y00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00y00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01H00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01H00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01Q00C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01Q00C00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00s20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicExchangeExt_00s20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01B20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00y20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01B20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01K20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01K20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00w20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00w20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01F20C00D), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01F20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01O20C00D), + &imageAtomicExchangeExt_00y20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01E20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01O20C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00x10C00D), + &imageAtomicExchangeExt_01E20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00u00C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00x10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01G10C00D), + &imageAtomicExchangeExt_00u00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01A00C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01G10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01P10C00D), + &imageAtomicExchangeExt_01A00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01G00C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01P10C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00u10C00C00D), + &imageAtomicExchangeExt_01G00C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00r20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00u10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01D10C00C00D), + &imageAtomicExchangeExt_00r20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00x20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01D10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01M10C00C00D), + &imageAtomicExchangeExt_00x20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01D20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01M10C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00v20C00C00D), + &imageAtomicExchangeExt_01D20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00t20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00v20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01E20C00C00D), + &imageAtomicExchangeExt_00t20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00z20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01E20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01N20C00C00D), + &imageAtomicExchangeExt_00z20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01F20C00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01N20C00C00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00q10C00C), + &imageAtomicExchangeExt_01F20C00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00p10C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00q10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00z10C00C), + &imageAtomicExchangeExt_00p10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00v10C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00z10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01I10C00C), + &imageAtomicExchangeExt_00v10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01B10C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01I10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00r20C00C), + &imageAtomicExchangeExt_01B10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00q20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00r20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01A20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01A20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01J20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01J20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00t20C00C), + &imageAtomicExchangeExt_00q20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00w20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00t20C00C), + &imageAtomicExchangeExt_00w20C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01C20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicExchangeExt_01C20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01L20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01L20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00y00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00y00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01H00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01H00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01Q00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01Q00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00s20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicExchangeExt_00s20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01B20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01B20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01K20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01K20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00w20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00w20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01F20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01F20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01O20C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01O20C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00x10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00x10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01G10C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01G10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01P10C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00y20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01P10C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00u10C00C00C), + &imageAtomicExchangeExt_00y20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01E20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00u10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01D10C00C00C), + &imageAtomicExchangeExt_01E20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00u00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01D10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01M10C00C00C), + &imageAtomicExchangeExt_00u00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01A00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01M10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00v20C00C00C), + &imageAtomicExchangeExt_01A00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01G00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00v20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01E20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01E20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01N20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01N20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00q10C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00q10C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00z10C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00z10C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01I10C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01I10C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00r20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00r20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01A20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01A20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01J20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01J20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00t20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00t20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01C20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01C20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01L20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01L20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00y00C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00y00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01H00C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01H00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01Q00C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01Q00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00s20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00s20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01B20C00B), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01B20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01K20C00B), + &imageAtomicExchangeExt_01G00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00r20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01K20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00w20C00B), + &imageAtomicExchangeExt_00r20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00x20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00w20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01F20C00B), + &imageAtomicExchangeExt_00x20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01D20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01F20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01O20C00B), + &imageAtomicExchangeExt_01D20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00t20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01O20C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00x10C00B), + &imageAtomicExchangeExt_00t20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00z20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00x10C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01G10C00B), + &imageAtomicExchangeExt_00z20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01F20C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01G10C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01P10C00B), + &imageAtomicExchangeExt_01F20C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00p10C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01P10C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00u10C00C00B), + &imageAtomicExchangeExt_00p10C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00v10C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00u10C00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01D10C00C00B), + &imageAtomicExchangeExt_00v10C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01B10C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01D10C00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01M10C00C00B), + &imageAtomicExchangeExt_01B10C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00q20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01M10C00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00v20C00C00B), + &imageAtomicExchangeExt_00q20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00w20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_00v20C00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01E20C00C00B), + &imageAtomicExchangeExt_00w20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01C20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01E20C00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01N20C00C00B), + &imageAtomicExchangeExt_01C20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00s20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicExchangeExt_01N20C00C00B), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00q10C00D00D), + &imageAtomicExchangeExt_00s20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00y20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00q10C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00z10C00D00D), + &imageAtomicExchangeExt_00y20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01E20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00z10C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01I10C00D00D), + &imageAtomicExchangeExt_01E20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00u00C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01I10C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00r20C00D00D), + &imageAtomicExchangeExt_00u00C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01A00C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00r20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01A20C00D00D), + &imageAtomicExchangeExt_01A00C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01G00C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01A20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01J20C00D00D), + &imageAtomicExchangeExt_01G00C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00r20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01J20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00t20C00D00D), + &imageAtomicExchangeExt_00r20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00x20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00t20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01C20C00D00D), + &imageAtomicExchangeExt_00x20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01D20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01C20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01L20C00D00D), + &imageAtomicExchangeExt_01D20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00t20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01L20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00y00C00D00D), + &imageAtomicExchangeExt_00t20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_00z20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00y00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01H00C00D00D), + &imageAtomicExchangeExt_00z20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicExchange_01F20C00B), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01H00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01Q00C00D00D), + &imageAtomicExchangeExt_01F20C00B), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00p10C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01Q00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00s20C00D00D), + &imageAtomicCompSwapExt_00p10C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00v10C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00s20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01B20C00D00D), + &imageAtomicCompSwapExt_00v10C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01B10C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01B20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01K20C00D00D), + &imageAtomicCompSwapExt_01B10C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00q20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01K20C00D00D), + &imageAtomicCompSwapExt_00q20C00D00D), Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00w20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicCompSwapExt_00w20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01F20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01C20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01F20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01O20C00D00D), + &imageAtomicCompSwapExt_01C20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00s20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01O20C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00x10C00D00D), + &imageAtomicCompSwapExt_00s20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00y20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00x10C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01G10C00D00D), + &imageAtomicCompSwapExt_00y20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01E20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01G10C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01P10C00D00D), + &imageAtomicCompSwapExt_01E20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00u00C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01P10C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00u10C00C00D00D), + &imageAtomicCompSwapExt_00u00C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01A00C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00u10C00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01D10C00C00D00D), + &imageAtomicCompSwapExt_01A00C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01G00C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01D10C00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01M10C00C00D00D), + &imageAtomicCompSwapExt_01G00C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00r20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01M10C00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00v20C00C00D00D), + &imageAtomicCompSwapExt_00r20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00x20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00v20C00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01E20C00C00D00D), + &imageAtomicCompSwapExt_00x20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01D20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01E20C00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01N20C00C00D00D), + &imageAtomicCompSwapExt_01D20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00t20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01N20C00C00D00D), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00q10C00C00C), + &imageAtomicCompSwapExt_00t20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00z20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00q10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00z10C00C00C), + &imageAtomicCompSwapExt_00z20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01F20C00D00D), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00z10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01I10C00C00C), + &imageAtomicCompSwapExt_01F20C00D00D), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00p10C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01I10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00r20C00C00C), + &imageAtomicCompSwapExt_00p10C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00v10C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00r20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01A20C00C00C), + &imageAtomicCompSwapExt_00v10C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01B10C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01A20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01J20C00C00C), + &imageAtomicCompSwapExt_01B10C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00q20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01J20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00t20C00C00C), + &imageAtomicCompSwapExt_00q20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00w20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00t20C00C00C), + &imageAtomicCompSwapExt_00w20C00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01C20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicCompSwapExt_01C20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01L20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01L20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00y00C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00y00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01H00C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01H00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01Q00C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01Q00C00C00C), Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00s20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( &imageAtomicCompSwapExt_00s20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01B20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01B20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01K20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00y20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01K20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00w20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00w20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01F20C00C00C), + &imageAtomicCompSwapExt_00y20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01E20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01F20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01O20C00C00C), - Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01O20C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00x10C00C00C), + &imageAtomicCompSwapExt_01E20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00u00C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00x10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01G10C00C00C), + &imageAtomicCompSwapExt_00u00C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01A00C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01G10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01P10C00C00C), + &imageAtomicCompSwapExt_01A00C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01G00C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01P10C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00u10C00C00C00C), + &imageAtomicCompSwapExt_01G00C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00r20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00u10C00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01D10C00C00C00C), + &imageAtomicCompSwapExt_00r20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00x20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01D10C00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01M10C00C00C00C), + &imageAtomicCompSwapExt_00x20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01D20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01M10C00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00v20C00C00C00C), + &imageAtomicCompSwapExt_01D20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00t20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_00v20C00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01E20C00C00C00C), + &imageAtomicCompSwapExt_00t20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_00z20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01E20C00C00C00C), - Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01N20C00C00C00C), + &imageAtomicCompSwapExt_00z20C00C00C), + Rule::Get<320, Shader::ALL, 0>(&imageAtomicCompSwap_01F20C00C00C), Rule::Get<310, Shader::ALL, EXT_INDEX(OES_shader_image_atomic)>( - &imageAtomicCompSwapExt_01N20C00C00C00C), + &imageAtomicCompSwapExt_01F20C00C00C), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_shader_pixel_local_storage)>( - &pixelLocalLoadANGLE_01R), + &pixelLocalLoadANGLE_01H), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_shader_pixel_local_storage)>( - &pixelLocalLoadANGLE_01S), + &pixelLocalLoadANGLE_01I), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_shader_pixel_local_storage)>( - &pixelLocalLoadANGLE_01T), + &pixelLocalLoadANGLE_01J), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_shader_pixel_local_storage)>( - &pixelLocalStoreANGLE_01R30B), + &pixelLocalStoreANGLE_01H30B), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_shader_pixel_local_storage)>( - &pixelLocalStoreANGLE_01S30C), + &pixelLocalStoreANGLE_01I30C), Rule::Get<300, Shader::ALL, EXT_INDEX(ANGLE_shader_pixel_local_storage)>( - &pixelLocalStoreANGLE_01T30D), + &pixelLocalStoreANGLE_01J30D), Rule::Get(&beginInvocationInterlockNV_), Rule::Get(&endInvocationInterlockNV_), Rule::Get(&beginFragmentShaderOrderingINTEL_), @@ -22520,15 +19285,16 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::GEOMETRY, 0>(&EndPrimitiveES3_2_), Rule::Get<310, Shader::GEOMETRY, EXT_INDEX(EXT_geometry_shader)>(&EndPrimitive_), Rule::Get<310, Shader::GEOMETRY, EXT_INDEX(OES_geometry_shader)>(&EndPrimitive_), - Rule::Get(&subpassLoad_01U), - Rule::Get(&subpassLoad_01V), - Rule::Get(&subpassLoad_01W), + Rule::Get(&subpassLoad_01K), + Rule::Get(&subpassLoad_01L), + Rule::Get(&subpassLoad_01M), Rule::Get(&numSamples_), Rule::Get(&samplePosition_00D), Rule::Get(&interpolateAtCenter_00B), Rule::Get(&interpolateAtCenter_10B), Rule::Get(&interpolateAtCenter_20B), Rule::Get(&interpolateAtCenter_30B), + Rule::Get(&loopForwardProgress_), Rule::Get(&saturate_00B), Rule::Get(&saturate_10B), Rule::Get(&saturate_20B), @@ -22571,6 +19337,10 @@ constexpr SymbolRule kRules[] = { Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_MaxFragmentAtomicCounterBuffers), Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_MaxCombinedAtomicCounterBuffers), Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_MaxAtomicCounterBufferSize), + Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_ShadingRateFlag2VerticalPixelsEXT), + Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_ShadingRateFlag4VerticalPixelsEXT), + Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_ShadingRateFlag2HorizontalPixelsEXT), + Rule::Get<310, Shader::ALL, 0>(&TableBase::m_gl_ShadingRateFlag4HorizontalPixelsEXT), Rule::Get<320, Shader::ALL, 0>(&TableBase::m_gl_MaxGeometryInputComponentsES3_2), Rule::Get<310, Shader::ALL, EXT_INDEX(EXT_geometry_shader)>( &TableBase::m_gl_MaxGeometryInputComponents), @@ -22734,15 +19504,11 @@ constexpr SymbolRule kRules[] = { &BuiltInVariable::kgl_SecondaryFragColorEXT), Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(EXT_blend_func_extended)>( &TableBase::m_gl_SecondaryFragDataEXT), - Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(EXT_frag_depth)>(&TableBase::m_gl_FragDepthEXT), + Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(EXT_frag_depth)>(&BuiltInVariable::kgl_FragDepthEXT), Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(EXT_shader_framebuffer_fetch)>( &TableBase::m_gl_LastFragData), Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(EXT_shader_framebuffer_fetch_non_coherent)>( &TableBase::m_gl_LastFragData), - Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(NV_shader_framebuffer_fetch)>( - &TableBase::m_gl_LastFragDataNV), - Rule::Get<100, Shader::FRAGMENT, EXT_INDEX(NV_shader_framebuffer_fetch)>( - &BuiltInVariable::kgl_LastFragColor), Rule::Get<0, Shader::FRAGMENT, EXT_INDEX(ARM_shader_framebuffer_fetch)>( &BuiltInVariable::kgl_LastFragColorARM), Rule::Get<0, Shader::FRAGMENT, EXT_INDEX(ARM_shader_framebuffer_fetch_depth_stencil)>( @@ -22778,6 +19544,8 @@ constexpr SymbolRule kRules[] = { &BuiltInVariable::kgl_LayerGS), Rule::Get<310, Shader::GEOMETRY_EXT, EXT_INDEX(OES_geometry_shader)>( &BuiltInVariable::kgl_LayerGS), + Rule::Get<310, Shader::FRAGMENT, EXT_INDEX(EXT_fragment_shading_rate)>( + &BuiltInVariable::kgl_ShadingRateEXT), Rule::Get<320, Shader::FRAGMENT, 0>(&BuiltInVariable::kgl_SampleIDES3_2), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(OES_sample_variables)>( &BuiltInVariable::kgl_SampleID), @@ -22790,21 +19558,16 @@ constexpr SymbolRule kRules[] = { Rule::Get<320, Shader::FRAGMENT, 0>(&TableBase::m_gl_SampleMaskES3_2), Rule::Get<300, Shader::FRAGMENT, EXT_INDEX(OES_sample_variables)>(&TableBase::m_gl_SampleMask), Rule::Get<0, Shader::VERTEX, 0>(&BuiltInVariable::kgl_Position), - Rule::Get<320, Shader::GEOMETRY_EXT, 0>(&TableBase::m_gl_PositionGSES3_2), - Rule::Get<320, Shader::TESS_CONTROL_EXT, 0>(&TableBase::m_gl_PositionTCSES3_2), - Rule::Get<320, Shader::TESS_EVALUATION_EXT, 0>(&TableBase::m_gl_PositionTESES3_2), + Rule::Get<320, Shader::GEOMETRY_EXT, 0>(&BuiltInVariable::kgl_PositionGSES3_2), + Rule::Get<320, Shader::TESS_EVALUATION_EXT, 0>(&BuiltInVariable::kgl_PositionTESES3_2), Rule::Get<310, Shader::GEOMETRY_EXT, EXT_INDEX(EXT_geometry_shader)>( - &TableBase::m_gl_PositionGS), + &BuiltInVariable::kgl_PositionGS), Rule::Get<310, Shader::GEOMETRY_EXT, EXT_INDEX(OES_geometry_shader)>( - &TableBase::m_gl_PositionGS), - Rule::Get<310, Shader::TESS_CONTROL_EXT, EXT_INDEX(EXT_tessellation_shader)>( - &TableBase::m_gl_PositionTCS), - Rule::Get<310, Shader::TESS_CONTROL_EXT, EXT_INDEX(OES_tessellation_shader)>( - &TableBase::m_gl_PositionTCS), + &BuiltInVariable::kgl_PositionGS), Rule::Get<310, Shader::TESS_EVALUATION_EXT, EXT_INDEX(EXT_tessellation_shader)>( - &TableBase::m_gl_PositionTES), + &BuiltInVariable::kgl_PositionTES), Rule::Get<310, Shader::TESS_EVALUATION_EXT, EXT_INDEX(OES_tessellation_shader)>( - &TableBase::m_gl_PositionTES), + &BuiltInVariable::kgl_PositionTES), Rule::Get<100, Shader::VERTEX, 0>(&BuiltInVariable::kgl_PointSize), Rule::Get<300, Shader::VERTEX, 0>(&BuiltInVariable::kgl_PointSize300), Rule::Get<300, Shader::VERTEX, 0>(&BuiltInVariable::kgl_InstanceID), @@ -22816,16 +19579,16 @@ constexpr SymbolRule kRules[] = { &BuiltInVariable::kgl_BaseVertex), Rule::Get<300, Shader::VERTEX, EXT_INDEX(ANGLE_base_vertex_base_instance_shader_builtin)>( &BuiltInVariable::kgl_BaseInstance), - Rule::Get<0, Shader::VERTEX, EXT_INDEX(ANGLE_base_vertex_base_instance_shader_builtin)>( - &BuiltInVariable::kangle_BaseVertex), - Rule::Get<0, Shader::VERTEX, EXT_INDEX(ANGLE_base_vertex_base_instance_shader_builtin)>( - &BuiltInVariable::kangle_BaseInstance), Rule::Get<0, Shader::VERTEX, EXT_INDEX(APPLE_clip_distance)>( &TableBase::m_gl_ClipDistanceAPPLE), Rule::Get<300, Shader::NOT_COMPUTE, EXT_INDEX(EXT_clip_cull_distance)>( &TableBase::m_gl_ClipDistance), Rule::Get<300, Shader::NOT_COMPUTE, EXT_INDEX(ANGLE_clip_cull_distance)>( &TableBase::m_gl_ClipDistance), + Rule::Get<310, Shader::VERTEX, EXT_INDEX(EXT_fragment_shading_rate_primitive)>( + &BuiltInVariable::kgl_PrimitiveShadingRateEXT), + Rule::Get<310, Shader::GEOMETRY_EXT, EXT_INDEX(EXT_fragment_shading_rate_primitive)>( + &BuiltInVariable::kgl_PrimitiveShadingRateEXTGS), Rule::Get<310, Shader::COMPUTE, 0>(&BuiltInVariable::kgl_NumWorkGroups), Rule::Get<310, Shader::COMPUTE, 0>(&BuiltInVariable::kgl_WorkGroupSize), Rule::Get<310, Shader::COMPUTE, 0>(&BuiltInVariable::kgl_WorkGroupID), @@ -22906,15 +19669,10 @@ constexpr SymbolRule kRules[] = { Rule::Get<310, Shader::TESS_EVALUATION_EXT, EXT_INDEX(OES_tessellation_shader)>( &TableBase::m_gl_TessLevelInnerTES), Rule::Get<320, Shader::TESS_CONTROL_EXT, 0>(&TableBase::m_gl_outTCSES3_2), - Rule::Get<320, Shader::TESS_EVALUATION_EXT, 0>(&TableBase::m_gl_outTESES3_2), Rule::Get<310, Shader::TESS_CONTROL_EXT, EXT_INDEX(EXT_tessellation_shader)>( &TableBase::m_gl_outTCS), Rule::Get<310, Shader::TESS_CONTROL_EXT, EXT_INDEX(OES_tessellation_shader)>( &TableBase::m_gl_outTCS), - Rule::Get<310, Shader::TESS_EVALUATION_EXT, EXT_INDEX(EXT_tessellation_shader)>( - &TableBase::m_gl_outTES), - Rule::Get<310, Shader::TESS_EVALUATION_EXT, EXT_INDEX(OES_tessellation_shader)>( - &TableBase::m_gl_outTES), Rule::Get<320, Shader::TESS_CONTROL_EXT, 0>(&TableBase::m_gl_BoundingBoxTCSES3_2), Rule::Get<320, Shader::TESS_CONTROL_EXT, EXT_INDEX(EXT_tessellation_shader)>( &TableBase::m_gl_BoundingBoxTCS), @@ -23436,7 +20194,7 @@ constexpr const char *kMangledNames[] = {"radians(00B", "texture2DProjGradEXT(00H20B10B10B", "texture2DProjGradEXT(00H30B10B10B", "textureCubeGradEXT(00J20B20B20B", - "textureVideoWEBGL(00p10B", + "textureVideoWEBGL(00o10B", "texture2D(00H10B00B", "texture2DProj(00H20B00B", "texture2DProj(00H30B00B", @@ -23469,13 +20227,13 @@ constexpr const char *kMangledNames[] = {"radians(00B", "texture(00d30B", "texture(00e30B", "texture(00g30B", - "texture(00l30B", - "texture(00o30B", + "texture(00k30B", + "texture(00n30B", "texture(00h30B00B", "texture(00L10B", "texture(00M10B", "texture(00N10B", - "texture(00p10B", + "texture(00o10B", "textureProj(00H20B", "textureProj(00Q20B", "textureProj(00W20B", @@ -23509,8 +20267,8 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureLod(00e30B00B", "textureLod(00h30B00B00B", "textureLod(00g30B00B", - "textureLod(00l30B00B", - "textureLod(00o30B00B", + "textureLod(00k30B00B", + "textureLod(00n30B00B", "textureSize(00H00C", "textureSize(00Q00C", "textureSize(00W00C", @@ -23527,12 +20285,12 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureSize(00d00C", "textureSize(00e00C", "textureSize(00g00C", - "textureSize(00l00C", - "textureSize(00o00C", + "textureSize(00k00C", + "textureSize(00n00C", "textureSize(00h00C", "textureSize(00f", - "textureSize(00k", - "textureSize(00n", + "textureSize(00j", + "textureSize(00m", "textureSize(00O", "textureSize(00U", "textureSize(00a", @@ -23561,8 +20319,8 @@ constexpr const char *kMangledNames[] = {"radians(00B", "texelFetch(00T20C00C", "texelFetch(00Z20C00C", "texelFetch(00f00C", - "texelFetch(00k00C", - "texelFetch(00n00C", + "texelFetch(00j00C", + "texelFetch(00m00C", "texelFetch(00O10C00C", "texelFetch(00U10C00C", "texelFetch(00a10C00C", @@ -23587,8 +20345,8 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureGrad(00Z20B10B10B", "textureGrad(00e30B10B10B", "textureGrad(00g30B20B20B", - "textureGrad(00l30B20B20B", - "textureGrad(00o30B20B20B", + "textureGrad(00k30B20B20B", + "textureGrad(00n30B20B20B", "textureProjGrad(00H20B10B10B", "textureProjGrad(00Q20B10B10B", "textureProjGrad(00W20B10B10B", @@ -23625,8 +20383,8 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureProj(00c30B00B", "texture(00e30B00B", "texture(00g30B00B", - "texture(00l30B00B", - "texture(00o30B00B", + "texture(00k30B00B", + "texture(00n30B00B", "texture(00h30B00B00B", "texture(00L10B00B", "textureProj(00L20B00B", @@ -23730,33 +20488,30 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureGather(00H10B", "textureGather(00Q10B", "textureGather(00W10B", - "textureGather(00H10B00C", - "textureGather(00Q10B00C", - "textureGather(00W10B00C", "textureGather(00K20B", "textureGather(00T20B", "textureGather(00Z20B", - "textureGather(00K20B00C", - "textureGather(00T20B00C", - "textureGather(00Z20B00C", "textureGather(00J20B", "textureGather(00S20B", "textureGather(00Y20B", + "textureGather(00g30B", + "textureGather(00k30B", + "textureGather(00n30B", + "textureGather(00H10B00C", + "textureGather(00Q10B00C", + "textureGather(00W10B00C", + "textureGather(00K20B00C", + "textureGather(00T20B00C", + "textureGather(00Z20B00C", "textureGather(00J20B00C", "textureGather(00S20B00C", "textureGather(00Y20B00C", - "textureGather(00g30B", - "textureGather(00l30B", - "textureGather(00o30B", "textureGather(00g30B00C", - "textureGather(00l30B00C", - "textureGather(00o30B00C", + "textureGather(00k30B00C", + "textureGather(00n30B00C", "textureGather(00h30B00B", - "textureGather(00c10B", "textureGather(00c10B00B", - "textureGather(00e20B", "textureGather(00e20B00B", - "textureGather(00d20B", "textureGather(00d20B00B", "textureGatherOffset(00H10B10C", "textureGatherOffset(00Q10B10C", @@ -23764,28 +20519,28 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureGatherOffset(00K20B10C", "textureGatherOffset(00T20B10C", "textureGatherOffset(00Z20B10C", - "textureGatherOffset(00c10B00B10C", - "textureGatherOffset(00e20B00B10C", "textureGatherOffset(00H10B10C00C", "textureGatherOffset(00Q10B10C00C", "textureGatherOffset(00W10B10C00C", "textureGatherOffset(00K20B10C00C", "textureGatherOffset(00T20B10C00C", "textureGatherOffset(00Z20B10C00C", + "textureGatherOffset(00c10B00B10C", + "textureGatherOffset(00e20B00B10C", "textureGatherOffsets(00H10B10Cx4", "textureGatherOffsets(00Q10B10Cx4", "textureGatherOffsets(00W10B10Cx4", "textureGatherOffsets(00K20B10Cx4", "textureGatherOffsets(00T20B10Cx4", "textureGatherOffsets(00Z20B10Cx4", - "textureGatherOffsets(00c10B00B10Cx4", - "textureGatherOffsets(00e20B00B10Cx4", "textureGatherOffsets(00H10B10Cx400C", "textureGatherOffsets(00Q10B10Cx400C", "textureGatherOffsets(00W10B10Cx400C", "textureGatherOffsets(00K20B10Cx400C", "textureGatherOffsets(00T20B10Cx400C", "textureGatherOffsets(00Z20B10Cx400C", + "textureGatherOffsets(00c10B00B10Cx4", + "textureGatherOffsets(00e20B00B10Cx4", "textureQueryLOD(00H10B", "textureQueryLOD(00Q10B", "textureQueryLOD(00W10B", @@ -23802,8 +20557,8 @@ constexpr const char *kMangledNames[] = {"radians(00B", "textureQueryLOD(00d20B", "textureQueryLOD(00e10B", "textureQueryLOD(00g20B", - "textureQueryLOD(00l20B", - "textureQueryLOD(00o20B", + "textureQueryLOD(00k20B", + "textureQueryLOD(00n20B", "textureQueryLOD(00h20B", "rgb_2_yuv(20B00G", "yuv_2_rgb(20B00G", @@ -23850,525 +20605,372 @@ constexpr const char *kMangledNames[] = {"radians(00B", "atomicExchange(00C00C", "atomicCompSwap(00D00D00D", "atomicCompSwap(00C00C00C", + "imageSize(00p", + "imageSize(00v", + "imageSize(01B", "imageSize(00q", - "imageSize(00z", - "imageSize(01I", + "imageSize(00w", + "imageSize(01C", "imageSize(00r", - "imageSize(01A", - "imageSize(01J", + "imageSize(00x", + "imageSize(01D", "imageSize(00s", - "imageSize(01B", - "imageSize(01K", + "imageSize(00y", + "imageSize(01E", "imageSize(00t", - "imageSize(01C", - "imageSize(01L", - "imageSize(00w", + "imageSize(00z", "imageSize(01F", - "imageSize(01O", - "imageSize(00y", - "imageSize(01H", - "imageSize(01Q", - "imageStore(00q10C30B", - "imageStore(00z10C30C", - "imageStore(01I10C30D", + "imageSize(00u", + "imageSize(01A", + "imageSize(01G", + "imageStore(00p10C30B", + "imageStore(00v10C30C", + "imageStore(01B10C30D", + "imageStore(00q20C30B", + "imageStore(00w20C30C", + "imageStore(01C20C30D", "imageStore(00r20C30B", - "imageStore(01A20C30C", - "imageStore(01J20C30D", + "imageStore(00x20C30C", + "imageStore(01D20C30D", "imageStore(00s20C30B", - "imageStore(01B20C30C", - "imageStore(01K20C30D", + "imageStore(00y20C30C", + "imageStore(01E20C30D", "imageStore(00t20C30B", - "imageStore(01C20C30C", - "imageStore(01L20C30D", - "imageStore(00w20C30B", - "imageStore(01F20C30C", - "imageStore(01O20C30D", - "imageStore(00y00C30B", - "imageStore(01H00C30C", - "imageStore(01Q00C30D", - "imageLoad(00q10C", - "imageLoad(00z10C", - "imageLoad(01I10C", + "imageStore(00z20C30C", + "imageStore(01F20C30D", + "imageStore(00u00C30B", + "imageStore(01A00C30C", + "imageStore(01G00C30D", + "imageLoad(00p10C", + "imageLoad(00v10C", + "imageLoad(01B10C", + "imageLoad(00q20C", + "imageLoad(00w20C", + "imageLoad(01C20C", "imageLoad(00r20C", - "imageLoad(01A20C", - "imageLoad(01J20C", + "imageLoad(00x20C", + "imageLoad(01D20C", "imageLoad(00s20C", - "imageLoad(01B20C", - "imageLoad(01K20C", + "imageLoad(00y20C", + "imageLoad(01E20C", "imageLoad(00t20C", - "imageLoad(01C20C", - "imageLoad(01L20C", - "imageLoad(00w20C", + "imageLoad(00z20C", "imageLoad(01F20C", - "imageLoad(01O20C", - "imageLoad(00y00C", - "imageLoad(01H00C", - "imageLoad(01Q00C", - "imageAtomicAdd(00q10C00D", - "imageAtomicAdd(00z10C00D", - "imageAtomicAdd(01I10C00D", - "imageAtomicAdd(00r20C00D", - "imageAtomicAdd(01A20C00D", - "imageAtomicAdd(01J20C00D", - "imageAtomicAdd(00t20C00D", + "imageLoad(00u00C", + "imageLoad(01A00C", + "imageLoad(01G00C", + "imageAtomicAdd(00p10C00D", + "imageAtomicAdd(00v10C00D", + "imageAtomicAdd(01B10C00D", + "imageAtomicAdd(00q20C00D", + "imageAtomicAdd(00w20C00D", "imageAtomicAdd(01C20C00D", - "imageAtomicAdd(01L20C00D", - "imageAtomicAdd(00y00C00D", - "imageAtomicAdd(01H00C00D", - "imageAtomicAdd(01Q00C00D", "imageAtomicAdd(00s20C00D", - "imageAtomicAdd(01B20C00D", - "imageAtomicAdd(01K20C00D", - "imageAtomicAdd(00w20C00D", + "imageAtomicAdd(00y20C00D", + "imageAtomicAdd(01E20C00D", + "imageAtomicAdd(00u00C00D", + "imageAtomicAdd(01A00C00D", + "imageAtomicAdd(01G00C00D", + "imageAtomicAdd(00r20C00D", + "imageAtomicAdd(00x20C00D", + "imageAtomicAdd(01D20C00D", + "imageAtomicAdd(00t20C00D", + "imageAtomicAdd(00z20C00D", "imageAtomicAdd(01F20C00D", - "imageAtomicAdd(01O20C00D", - "imageAtomicAdd(00x10C00D", - "imageAtomicAdd(01G10C00D", - "imageAtomicAdd(01P10C00D", - "imageAtomicAdd(00u10C00C00D", - "imageAtomicAdd(01D10C00C00D", - "imageAtomicAdd(01M10C00C00D", - "imageAtomicAdd(00v20C00C00D", - "imageAtomicAdd(01E20C00C00D", - "imageAtomicAdd(01N20C00C00D", - "imageAtomicAdd(00q10C00C", - "imageAtomicAdd(00z10C00C", - "imageAtomicAdd(01I10C00C", - "imageAtomicAdd(00r20C00C", - "imageAtomicAdd(01A20C00C", - "imageAtomicAdd(01J20C00C", - "imageAtomicAdd(00t20C00C", + "imageAtomicAdd(00p10C00C", + "imageAtomicAdd(00v10C00C", + "imageAtomicAdd(01B10C00C", + "imageAtomicAdd(00q20C00C", + "imageAtomicAdd(00w20C00C", "imageAtomicAdd(01C20C00C", - "imageAtomicAdd(01L20C00C", - "imageAtomicAdd(00y00C00C", - "imageAtomicAdd(01H00C00C", - "imageAtomicAdd(01Q00C00C", "imageAtomicAdd(00s20C00C", - "imageAtomicAdd(01B20C00C", - "imageAtomicAdd(01K20C00C", - "imageAtomicAdd(00w20C00C", + "imageAtomicAdd(00y20C00C", + "imageAtomicAdd(01E20C00C", + "imageAtomicAdd(00u00C00C", + "imageAtomicAdd(01A00C00C", + "imageAtomicAdd(01G00C00C", + "imageAtomicAdd(00r20C00C", + "imageAtomicAdd(00x20C00C", + "imageAtomicAdd(01D20C00C", + "imageAtomicAdd(00t20C00C", + "imageAtomicAdd(00z20C00C", "imageAtomicAdd(01F20C00C", - "imageAtomicAdd(01O20C00C", - "imageAtomicAdd(00x10C00C", - "imageAtomicAdd(01G10C00C", - "imageAtomicAdd(01P10C00C", - "imageAtomicAdd(00u10C00C00C", - "imageAtomicAdd(01D10C00C00C", - "imageAtomicAdd(01M10C00C00C", - "imageAtomicAdd(00v20C00C00C", - "imageAtomicAdd(01E20C00C00C", - "imageAtomicAdd(01N20C00C00C", - "imageAtomicMin(00q10C00D", - "imageAtomicMin(00z10C00D", - "imageAtomicMin(01I10C00D", - "imageAtomicMin(00r20C00D", - "imageAtomicMin(01A20C00D", - "imageAtomicMin(01J20C00D", - "imageAtomicMin(00t20C00D", + "imageAtomicMin(00p10C00D", + "imageAtomicMin(00v10C00D", + "imageAtomicMin(01B10C00D", + "imageAtomicMin(00q20C00D", + "imageAtomicMin(00w20C00D", "imageAtomicMin(01C20C00D", - "imageAtomicMin(01L20C00D", - "imageAtomicMin(00y00C00D", - "imageAtomicMin(01H00C00D", - "imageAtomicMin(01Q00C00D", "imageAtomicMin(00s20C00D", - "imageAtomicMin(01B20C00D", - "imageAtomicMin(01K20C00D", - "imageAtomicMin(00w20C00D", + "imageAtomicMin(00y20C00D", + "imageAtomicMin(01E20C00D", + "imageAtomicMin(00u00C00D", + "imageAtomicMin(01A00C00D", + "imageAtomicMin(01G00C00D", + "imageAtomicMin(00r20C00D", + "imageAtomicMin(00x20C00D", + "imageAtomicMin(01D20C00D", + "imageAtomicMin(00t20C00D", + "imageAtomicMin(00z20C00D", "imageAtomicMin(01F20C00D", - "imageAtomicMin(01O20C00D", - "imageAtomicMin(00x10C00D", - "imageAtomicMin(01G10C00D", - "imageAtomicMin(01P10C00D", - "imageAtomicMin(00u10C00C00D", - "imageAtomicMin(01D10C00C00D", - "imageAtomicMin(01M10C00C00D", - "imageAtomicMin(00v20C00C00D", - "imageAtomicMin(01E20C00C00D", - "imageAtomicMin(01N20C00C00D", - "imageAtomicMin(00q10C00C", - "imageAtomicMin(00z10C00C", - "imageAtomicMin(01I10C00C", - "imageAtomicMin(00r20C00C", - "imageAtomicMin(01A20C00C", - "imageAtomicMin(01J20C00C", - "imageAtomicMin(00t20C00C", + "imageAtomicMin(00p10C00C", + "imageAtomicMin(00v10C00C", + "imageAtomicMin(01B10C00C", + "imageAtomicMin(00q20C00C", + "imageAtomicMin(00w20C00C", "imageAtomicMin(01C20C00C", - "imageAtomicMin(01L20C00C", - "imageAtomicMin(00y00C00C", - "imageAtomicMin(01H00C00C", - "imageAtomicMin(01Q00C00C", "imageAtomicMin(00s20C00C", - "imageAtomicMin(01B20C00C", - "imageAtomicMin(01K20C00C", - "imageAtomicMin(00w20C00C", + "imageAtomicMin(00y20C00C", + "imageAtomicMin(01E20C00C", + "imageAtomicMin(00u00C00C", + "imageAtomicMin(01A00C00C", + "imageAtomicMin(01G00C00C", + "imageAtomicMin(00r20C00C", + "imageAtomicMin(00x20C00C", + "imageAtomicMin(01D20C00C", + "imageAtomicMin(00t20C00C", + "imageAtomicMin(00z20C00C", "imageAtomicMin(01F20C00C", - "imageAtomicMin(01O20C00C", - "imageAtomicMin(00x10C00C", - "imageAtomicMin(01G10C00C", - "imageAtomicMin(01P10C00C", - "imageAtomicMin(00u10C00C00C", - "imageAtomicMin(01D10C00C00C", - "imageAtomicMin(01M10C00C00C", - "imageAtomicMin(00v20C00C00C", - "imageAtomicMin(01E20C00C00C", - "imageAtomicMin(01N20C00C00C", - "imageAtomicMax(00q10C00D", - "imageAtomicMax(00z10C00D", - "imageAtomicMax(01I10C00D", - "imageAtomicMax(00r20C00D", - "imageAtomicMax(01A20C00D", - "imageAtomicMax(01J20C00D", - "imageAtomicMax(00t20C00D", + "imageAtomicMax(00p10C00D", + "imageAtomicMax(00v10C00D", + "imageAtomicMax(01B10C00D", + "imageAtomicMax(00q20C00D", + "imageAtomicMax(00w20C00D", "imageAtomicMax(01C20C00D", - "imageAtomicMax(01L20C00D", - "imageAtomicMax(00y00C00D", - "imageAtomicMax(01H00C00D", - "imageAtomicMax(01Q00C00D", "imageAtomicMax(00s20C00D", - "imageAtomicMax(01B20C00D", - "imageAtomicMax(01K20C00D", - "imageAtomicMax(00w20C00D", + "imageAtomicMax(00y20C00D", + "imageAtomicMax(01E20C00D", + "imageAtomicMax(00u00C00D", + "imageAtomicMax(01A00C00D", + "imageAtomicMax(01G00C00D", + "imageAtomicMax(00r20C00D", + "imageAtomicMax(00x20C00D", + "imageAtomicMax(01D20C00D", + "imageAtomicMax(00t20C00D", + "imageAtomicMax(00z20C00D", "imageAtomicMax(01F20C00D", - "imageAtomicMax(01O20C00D", - "imageAtomicMax(00x10C00D", - "imageAtomicMax(01G10C00D", - "imageAtomicMax(01P10C00D", - "imageAtomicMax(00u10C00C00D", - "imageAtomicMax(01D10C00C00D", - "imageAtomicMax(01M10C00C00D", - "imageAtomicMax(00v20C00C00D", - "imageAtomicMax(01E20C00C00D", - "imageAtomicMax(01N20C00C00D", - "imageAtomicMax(00q10C00C", - "imageAtomicMax(00z10C00C", - "imageAtomicMax(01I10C00C", - "imageAtomicMax(00r20C00C", - "imageAtomicMax(01A20C00C", - "imageAtomicMax(01J20C00C", - "imageAtomicMax(00t20C00C", + "imageAtomicMax(00p10C00C", + "imageAtomicMax(00v10C00C", + "imageAtomicMax(01B10C00C", + "imageAtomicMax(00q20C00C", + "imageAtomicMax(00w20C00C", "imageAtomicMax(01C20C00C", - "imageAtomicMax(01L20C00C", - "imageAtomicMax(00y00C00C", - "imageAtomicMax(01H00C00C", - "imageAtomicMax(01Q00C00C", "imageAtomicMax(00s20C00C", - "imageAtomicMax(01B20C00C", - "imageAtomicMax(01K20C00C", - "imageAtomicMax(00w20C00C", + "imageAtomicMax(00y20C00C", + "imageAtomicMax(01E20C00C", + "imageAtomicMax(00u00C00C", + "imageAtomicMax(01A00C00C", + "imageAtomicMax(01G00C00C", + "imageAtomicMax(00r20C00C", + "imageAtomicMax(00x20C00C", + "imageAtomicMax(01D20C00C", + "imageAtomicMax(00t20C00C", + "imageAtomicMax(00z20C00C", "imageAtomicMax(01F20C00C", - "imageAtomicMax(01O20C00C", - "imageAtomicMax(00x10C00C", - "imageAtomicMax(01G10C00C", - "imageAtomicMax(01P10C00C", - "imageAtomicMax(00u10C00C00C", - "imageAtomicMax(01D10C00C00C", - "imageAtomicMax(01M10C00C00C", - "imageAtomicMax(00v20C00C00C", - "imageAtomicMax(01E20C00C00C", - "imageAtomicMax(01N20C00C00C", - "imageAtomicAnd(00q10C00D", - "imageAtomicAnd(00z10C00D", - "imageAtomicAnd(01I10C00D", - "imageAtomicAnd(00r20C00D", - "imageAtomicAnd(01A20C00D", - "imageAtomicAnd(01J20C00D", - "imageAtomicAnd(00t20C00D", + "imageAtomicAnd(00p10C00D", + "imageAtomicAnd(00v10C00D", + "imageAtomicAnd(01B10C00D", + "imageAtomicAnd(00q20C00D", + "imageAtomicAnd(00w20C00D", "imageAtomicAnd(01C20C00D", - "imageAtomicAnd(01L20C00D", - "imageAtomicAnd(00y00C00D", - "imageAtomicAnd(01H00C00D", - "imageAtomicAnd(01Q00C00D", "imageAtomicAnd(00s20C00D", - "imageAtomicAnd(01B20C00D", - "imageAtomicAnd(01K20C00D", - "imageAtomicAnd(00w20C00D", + "imageAtomicAnd(00y20C00D", + "imageAtomicAnd(01E20C00D", + "imageAtomicAnd(00u00C00D", + "imageAtomicAnd(01A00C00D", + "imageAtomicAnd(01G00C00D", + "imageAtomicAnd(00r20C00D", + "imageAtomicAnd(00x20C00D", + "imageAtomicAnd(01D20C00D", + "imageAtomicAnd(00t20C00D", + "imageAtomicAnd(00z20C00D", "imageAtomicAnd(01F20C00D", - "imageAtomicAnd(01O20C00D", - "imageAtomicAnd(00x10C00D", - "imageAtomicAnd(01G10C00D", - "imageAtomicAnd(01P10C00D", - "imageAtomicAnd(00u10C00C00D", - "imageAtomicAnd(01D10C00C00D", - "imageAtomicAnd(01M10C00C00D", - "imageAtomicAnd(00v20C00C00D", - "imageAtomicAnd(01E20C00C00D", - "imageAtomicAnd(01N20C00C00D", - "imageAtomicAnd(00q10C00C", - "imageAtomicAnd(00z10C00C", - "imageAtomicAnd(01I10C00C", - "imageAtomicAnd(00r20C00C", - "imageAtomicAnd(01A20C00C", - "imageAtomicAnd(01J20C00C", - "imageAtomicAnd(00t20C00C", + "imageAtomicAnd(00p10C00C", + "imageAtomicAnd(00v10C00C", + "imageAtomicAnd(01B10C00C", + "imageAtomicAnd(00q20C00C", + "imageAtomicAnd(00w20C00C", "imageAtomicAnd(01C20C00C", - "imageAtomicAnd(01L20C00C", - "imageAtomicAnd(00y00C00C", - "imageAtomicAnd(01H00C00C", - "imageAtomicAnd(01Q00C00C", "imageAtomicAnd(00s20C00C", - "imageAtomicAnd(01B20C00C", - "imageAtomicAnd(01K20C00C", - "imageAtomicAnd(00w20C00C", + "imageAtomicAnd(00y20C00C", + "imageAtomicAnd(01E20C00C", + "imageAtomicAnd(00u00C00C", + "imageAtomicAnd(01A00C00C", + "imageAtomicAnd(01G00C00C", + "imageAtomicAnd(00r20C00C", + "imageAtomicAnd(00x20C00C", + "imageAtomicAnd(01D20C00C", + "imageAtomicAnd(00t20C00C", + "imageAtomicAnd(00z20C00C", "imageAtomicAnd(01F20C00C", - "imageAtomicAnd(01O20C00C", - "imageAtomicAnd(00x10C00C", - "imageAtomicAnd(01G10C00C", - "imageAtomicAnd(01P10C00C", - "imageAtomicAnd(00u10C00C00C", - "imageAtomicAnd(01D10C00C00C", - "imageAtomicAnd(01M10C00C00C", - "imageAtomicAnd(00v20C00C00C", - "imageAtomicAnd(01E20C00C00C", - "imageAtomicAnd(01N20C00C00C", - "imageAtomicOr(00q10C00D", - "imageAtomicOr(00z10C00D", - "imageAtomicOr(01I10C00D", - "imageAtomicOr(00r20C00D", - "imageAtomicOr(01A20C00D", - "imageAtomicOr(01J20C00D", - "imageAtomicOr(00t20C00D", + "imageAtomicOr(00p10C00D", + "imageAtomicOr(00v10C00D", + "imageAtomicOr(01B10C00D", + "imageAtomicOr(00q20C00D", + "imageAtomicOr(00w20C00D", "imageAtomicOr(01C20C00D", - "imageAtomicOr(01L20C00D", - "imageAtomicOr(00y00C00D", - "imageAtomicOr(01H00C00D", - "imageAtomicOr(01Q00C00D", "imageAtomicOr(00s20C00D", - "imageAtomicOr(01B20C00D", - "imageAtomicOr(01K20C00D", - "imageAtomicOr(00w20C00D", + "imageAtomicOr(00y20C00D", + "imageAtomicOr(01E20C00D", + "imageAtomicOr(00u00C00D", + "imageAtomicOr(01A00C00D", + "imageAtomicOr(01G00C00D", + "imageAtomicOr(00r20C00D", + "imageAtomicOr(00x20C00D", + "imageAtomicOr(01D20C00D", + "imageAtomicOr(00t20C00D", + "imageAtomicOr(00z20C00D", "imageAtomicOr(01F20C00D", - "imageAtomicOr(01O20C00D", - "imageAtomicOr(00x10C00D", - "imageAtomicOr(01G10C00D", - "imageAtomicOr(01P10C00D", - "imageAtomicOr(00u10C00C00D", - "imageAtomicOr(01D10C00C00D", - "imageAtomicOr(01M10C00C00D", - "imageAtomicOr(00v20C00C00D", - "imageAtomicOr(01E20C00C00D", - "imageAtomicOr(01N20C00C00D", - "imageAtomicOr(00q10C00C", - "imageAtomicOr(00z10C00C", - "imageAtomicOr(01I10C00C", - "imageAtomicOr(00r20C00C", - "imageAtomicOr(01A20C00C", - "imageAtomicOr(01J20C00C", - "imageAtomicOr(00t20C00C", + "imageAtomicOr(00p10C00C", + "imageAtomicOr(00v10C00C", + "imageAtomicOr(01B10C00C", + "imageAtomicOr(00q20C00C", + "imageAtomicOr(00w20C00C", "imageAtomicOr(01C20C00C", - "imageAtomicOr(01L20C00C", - "imageAtomicOr(00y00C00C", - "imageAtomicOr(01H00C00C", - "imageAtomicOr(01Q00C00C", "imageAtomicOr(00s20C00C", - "imageAtomicOr(01B20C00C", - "imageAtomicOr(01K20C00C", - "imageAtomicOr(00w20C00C", + "imageAtomicOr(00y20C00C", + "imageAtomicOr(01E20C00C", + "imageAtomicOr(00u00C00C", + "imageAtomicOr(01A00C00C", + "imageAtomicOr(01G00C00C", + "imageAtomicOr(00r20C00C", + "imageAtomicOr(00x20C00C", + "imageAtomicOr(01D20C00C", + "imageAtomicOr(00t20C00C", + "imageAtomicOr(00z20C00C", "imageAtomicOr(01F20C00C", - "imageAtomicOr(01O20C00C", - "imageAtomicOr(00x10C00C", - "imageAtomicOr(01G10C00C", - "imageAtomicOr(01P10C00C", - "imageAtomicOr(00u10C00C00C", - "imageAtomicOr(01D10C00C00C", - "imageAtomicOr(01M10C00C00C", - "imageAtomicOr(00v20C00C00C", - "imageAtomicOr(01E20C00C00C", - "imageAtomicOr(01N20C00C00C", - "imageAtomicXor(00q10C00D", - "imageAtomicXor(00z10C00D", - "imageAtomicXor(01I10C00D", - "imageAtomicXor(00r20C00D", - "imageAtomicXor(01A20C00D", - "imageAtomicXor(01J20C00D", - "imageAtomicXor(00t20C00D", + "imageAtomicXor(00p10C00D", + "imageAtomicXor(00v10C00D", + "imageAtomicXor(01B10C00D", + "imageAtomicXor(00q20C00D", + "imageAtomicXor(00w20C00D", "imageAtomicXor(01C20C00D", - "imageAtomicXor(01L20C00D", - "imageAtomicXor(00y00C00D", - "imageAtomicXor(01H00C00D", - "imageAtomicXor(01Q00C00D", "imageAtomicXor(00s20C00D", - "imageAtomicXor(01B20C00D", - "imageAtomicXor(01K20C00D", - "imageAtomicXor(00w20C00D", + "imageAtomicXor(00y20C00D", + "imageAtomicXor(01E20C00D", + "imageAtomicXor(00u00C00D", + "imageAtomicXor(01A00C00D", + "imageAtomicXor(01G00C00D", + "imageAtomicXor(00r20C00D", + "imageAtomicXor(00x20C00D", + "imageAtomicXor(01D20C00D", + "imageAtomicXor(00t20C00D", + "imageAtomicXor(00z20C00D", "imageAtomicXor(01F20C00D", - "imageAtomicXor(01O20C00D", - "imageAtomicXor(00x10C00D", - "imageAtomicXor(01G10C00D", - "imageAtomicXor(01P10C00D", - "imageAtomicXor(00u10C00C00D", - "imageAtomicXor(01D10C00C00D", - "imageAtomicXor(01M10C00C00D", - "imageAtomicXor(00v20C00C00D", - "imageAtomicXor(01E20C00C00D", - "imageAtomicXor(01N20C00C00D", - "imageAtomicXor(00q10C00C", - "imageAtomicXor(00z10C00C", - "imageAtomicXor(01I10C00C", - "imageAtomicXor(00r20C00C", - "imageAtomicXor(01A20C00C", - "imageAtomicXor(01J20C00C", - "imageAtomicXor(00t20C00C", + "imageAtomicXor(00p10C00C", + "imageAtomicXor(00v10C00C", + "imageAtomicXor(01B10C00C", + "imageAtomicXor(00q20C00C", + "imageAtomicXor(00w20C00C", "imageAtomicXor(01C20C00C", - "imageAtomicXor(01L20C00C", - "imageAtomicXor(00y00C00C", - "imageAtomicXor(01H00C00C", - "imageAtomicXor(01Q00C00C", "imageAtomicXor(00s20C00C", - "imageAtomicXor(01B20C00C", - "imageAtomicXor(01K20C00C", - "imageAtomicXor(00w20C00C", + "imageAtomicXor(00y20C00C", + "imageAtomicXor(01E20C00C", + "imageAtomicXor(00u00C00C", + "imageAtomicXor(01A00C00C", + "imageAtomicXor(01G00C00C", + "imageAtomicXor(00r20C00C", + "imageAtomicXor(00x20C00C", + "imageAtomicXor(01D20C00C", + "imageAtomicXor(00t20C00C", + "imageAtomicXor(00z20C00C", "imageAtomicXor(01F20C00C", - "imageAtomicXor(01O20C00C", - "imageAtomicXor(00x10C00C", - "imageAtomicXor(01G10C00C", - "imageAtomicXor(01P10C00C", - "imageAtomicXor(00u10C00C00C", - "imageAtomicXor(01D10C00C00C", - "imageAtomicXor(01M10C00C00C", - "imageAtomicXor(00v20C00C00C", - "imageAtomicXor(01E20C00C00C", - "imageAtomicXor(01N20C00C00C", - "imageAtomicExchange(00q10C00D", - "imageAtomicExchange(00z10C00D", - "imageAtomicExchange(01I10C00D", - "imageAtomicExchange(00r20C00D", - "imageAtomicExchange(01A20C00D", - "imageAtomicExchange(01J20C00D", - "imageAtomicExchange(00t20C00D", + "imageAtomicExchange(00p10C00D", + "imageAtomicExchange(00v10C00D", + "imageAtomicExchange(01B10C00D", + "imageAtomicExchange(00q20C00D", + "imageAtomicExchange(00w20C00D", "imageAtomicExchange(01C20C00D", - "imageAtomicExchange(01L20C00D", - "imageAtomicExchange(00y00C00D", - "imageAtomicExchange(01H00C00D", - "imageAtomicExchange(01Q00C00D", "imageAtomicExchange(00s20C00D", - "imageAtomicExchange(01B20C00D", - "imageAtomicExchange(01K20C00D", - "imageAtomicExchange(00w20C00D", + "imageAtomicExchange(00y20C00D", + "imageAtomicExchange(01E20C00D", + "imageAtomicExchange(00u00C00D", + "imageAtomicExchange(01A00C00D", + "imageAtomicExchange(01G00C00D", + "imageAtomicExchange(00r20C00D", + "imageAtomicExchange(00x20C00D", + "imageAtomicExchange(01D20C00D", + "imageAtomicExchange(00t20C00D", + "imageAtomicExchange(00z20C00D", "imageAtomicExchange(01F20C00D", - "imageAtomicExchange(01O20C00D", - "imageAtomicExchange(00x10C00D", - "imageAtomicExchange(01G10C00D", - "imageAtomicExchange(01P10C00D", - "imageAtomicExchange(00u10C00C00D", - "imageAtomicExchange(01D10C00C00D", - "imageAtomicExchange(01M10C00C00D", - "imageAtomicExchange(00v20C00C00D", - "imageAtomicExchange(01E20C00C00D", - "imageAtomicExchange(01N20C00C00D", - "imageAtomicExchange(00q10C00C", - "imageAtomicExchange(00z10C00C", - "imageAtomicExchange(01I10C00C", - "imageAtomicExchange(00r20C00C", - "imageAtomicExchange(01A20C00C", - "imageAtomicExchange(01J20C00C", - "imageAtomicExchange(00t20C00C", + "imageAtomicExchange(00p10C00C", + "imageAtomicExchange(00v10C00C", + "imageAtomicExchange(01B10C00C", + "imageAtomicExchange(00q20C00C", + "imageAtomicExchange(00w20C00C", "imageAtomicExchange(01C20C00C", - "imageAtomicExchange(01L20C00C", - "imageAtomicExchange(00y00C00C", - "imageAtomicExchange(01H00C00C", - "imageAtomicExchange(01Q00C00C", "imageAtomicExchange(00s20C00C", - "imageAtomicExchange(01B20C00C", - "imageAtomicExchange(01K20C00C", - "imageAtomicExchange(00w20C00C", + "imageAtomicExchange(00y20C00C", + "imageAtomicExchange(01E20C00C", + "imageAtomicExchange(00u00C00C", + "imageAtomicExchange(01A00C00C", + "imageAtomicExchange(01G00C00C", + "imageAtomicExchange(00r20C00C", + "imageAtomicExchange(00x20C00C", + "imageAtomicExchange(01D20C00C", + "imageAtomicExchange(00t20C00C", + "imageAtomicExchange(00z20C00C", "imageAtomicExchange(01F20C00C", - "imageAtomicExchange(01O20C00C", - "imageAtomicExchange(00x10C00C", - "imageAtomicExchange(01G10C00C", - "imageAtomicExchange(01P10C00C", - "imageAtomicExchange(00u10C00C00C", - "imageAtomicExchange(01D10C00C00C", - "imageAtomicExchange(01M10C00C00C", - "imageAtomicExchange(00v20C00C00C", - "imageAtomicExchange(01E20C00C00C", - "imageAtomicExchange(01N20C00C00C", - "imageAtomicExchange(00q10C00B", - "imageAtomicExchange(00z10C00B", - "imageAtomicExchange(01I10C00B", - "imageAtomicExchange(00r20C00B", - "imageAtomicExchange(01A20C00B", - "imageAtomicExchange(01J20C00B", - "imageAtomicExchange(00t20C00B", + "imageAtomicExchange(00p10C00B", + "imageAtomicExchange(00v10C00B", + "imageAtomicExchange(01B10C00B", + "imageAtomicExchange(00q20C00B", + "imageAtomicExchange(00w20C00B", "imageAtomicExchange(01C20C00B", - "imageAtomicExchange(01L20C00B", - "imageAtomicExchange(00y00C00B", - "imageAtomicExchange(01H00C00B", - "imageAtomicExchange(01Q00C00B", "imageAtomicExchange(00s20C00B", - "imageAtomicExchange(01B20C00B", - "imageAtomicExchange(01K20C00B", - "imageAtomicExchange(00w20C00B", + "imageAtomicExchange(00y20C00B", + "imageAtomicExchange(01E20C00B", + "imageAtomicExchange(00u00C00B", + "imageAtomicExchange(01A00C00B", + "imageAtomicExchange(01G00C00B", + "imageAtomicExchange(00r20C00B", + "imageAtomicExchange(00x20C00B", + "imageAtomicExchange(01D20C00B", + "imageAtomicExchange(00t20C00B", + "imageAtomicExchange(00z20C00B", "imageAtomicExchange(01F20C00B", - "imageAtomicExchange(01O20C00B", - "imageAtomicExchange(00x10C00B", - "imageAtomicExchange(01G10C00B", - "imageAtomicExchange(01P10C00B", - "imageAtomicExchange(00u10C00C00B", - "imageAtomicExchange(01D10C00C00B", - "imageAtomicExchange(01M10C00C00B", - "imageAtomicExchange(00v20C00C00B", - "imageAtomicExchange(01E20C00C00B", - "imageAtomicExchange(01N20C00C00B", - "imageAtomicCompSwap(00q10C00D00D", - "imageAtomicCompSwap(00z10C00D00D", - "imageAtomicCompSwap(01I10C00D00D", - "imageAtomicCompSwap(00r20C00D00D", - "imageAtomicCompSwap(01A20C00D00D", - "imageAtomicCompSwap(01J20C00D00D", - "imageAtomicCompSwap(00t20C00D00D", + "imageAtomicCompSwap(00p10C00D00D", + "imageAtomicCompSwap(00v10C00D00D", + "imageAtomicCompSwap(01B10C00D00D", + "imageAtomicCompSwap(00q20C00D00D", + "imageAtomicCompSwap(00w20C00D00D", "imageAtomicCompSwap(01C20C00D00D", - "imageAtomicCompSwap(01L20C00D00D", - "imageAtomicCompSwap(00y00C00D00D", - "imageAtomicCompSwap(01H00C00D00D", - "imageAtomicCompSwap(01Q00C00D00D", "imageAtomicCompSwap(00s20C00D00D", - "imageAtomicCompSwap(01B20C00D00D", - "imageAtomicCompSwap(01K20C00D00D", - "imageAtomicCompSwap(00w20C00D00D", + "imageAtomicCompSwap(00y20C00D00D", + "imageAtomicCompSwap(01E20C00D00D", + "imageAtomicCompSwap(00u00C00D00D", + "imageAtomicCompSwap(01A00C00D00D", + "imageAtomicCompSwap(01G00C00D00D", + "imageAtomicCompSwap(00r20C00D00D", + "imageAtomicCompSwap(00x20C00D00D", + "imageAtomicCompSwap(01D20C00D00D", + "imageAtomicCompSwap(00t20C00D00D", + "imageAtomicCompSwap(00z20C00D00D", "imageAtomicCompSwap(01F20C00D00D", - "imageAtomicCompSwap(01O20C00D00D", - "imageAtomicCompSwap(00x10C00D00D", - "imageAtomicCompSwap(01G10C00D00D", - "imageAtomicCompSwap(01P10C00D00D", - "imageAtomicCompSwap(00u10C00C00D00D", - "imageAtomicCompSwap(01D10C00C00D00D", - "imageAtomicCompSwap(01M10C00C00D00D", - "imageAtomicCompSwap(00v20C00C00D00D", - "imageAtomicCompSwap(01E20C00C00D00D", - "imageAtomicCompSwap(01N20C00C00D00D", - "imageAtomicCompSwap(00q10C00C00C", - "imageAtomicCompSwap(00z10C00C00C", - "imageAtomicCompSwap(01I10C00C00C", - "imageAtomicCompSwap(00r20C00C00C", - "imageAtomicCompSwap(01A20C00C00C", - "imageAtomicCompSwap(01J20C00C00C", - "imageAtomicCompSwap(00t20C00C00C", + "imageAtomicCompSwap(00p10C00C00C", + "imageAtomicCompSwap(00v10C00C00C", + "imageAtomicCompSwap(01B10C00C00C", + "imageAtomicCompSwap(00q20C00C00C", + "imageAtomicCompSwap(00w20C00C00C", "imageAtomicCompSwap(01C20C00C00C", - "imageAtomicCompSwap(01L20C00C00C", - "imageAtomicCompSwap(00y00C00C00C", - "imageAtomicCompSwap(01H00C00C00C", - "imageAtomicCompSwap(01Q00C00C00C", "imageAtomicCompSwap(00s20C00C00C", - "imageAtomicCompSwap(01B20C00C00C", - "imageAtomicCompSwap(01K20C00C00C", - "imageAtomicCompSwap(00w20C00C00C", + "imageAtomicCompSwap(00y20C00C00C", + "imageAtomicCompSwap(01E20C00C00C", + "imageAtomicCompSwap(00u00C00C00C", + "imageAtomicCompSwap(01A00C00C00C", + "imageAtomicCompSwap(01G00C00C00C", + "imageAtomicCompSwap(00r20C00C00C", + "imageAtomicCompSwap(00x20C00C00C", + "imageAtomicCompSwap(01D20C00C00C", + "imageAtomicCompSwap(00t20C00C00C", + "imageAtomicCompSwap(00z20C00C00C", "imageAtomicCompSwap(01F20C00C00C", - "imageAtomicCompSwap(01O20C00C00C", - "imageAtomicCompSwap(00x10C00C00C", - "imageAtomicCompSwap(01G10C00C00C", - "imageAtomicCompSwap(01P10C00C00C", - "imageAtomicCompSwap(00u10C00C00C00C", - "imageAtomicCompSwap(01D10C00C00C00C", - "imageAtomicCompSwap(01M10C00C00C00C", - "imageAtomicCompSwap(00v20C00C00C00C", - "imageAtomicCompSwap(01E20C00C00C00C", - "imageAtomicCompSwap(01N20C00C00C00C", - "pixelLocalLoadANGLE(01R", - "pixelLocalLoadANGLE(01S", - "pixelLocalLoadANGLE(01T", - "pixelLocalStoreANGLE(01R30B", - "pixelLocalStoreANGLE(01S30C", - "pixelLocalStoreANGLE(01T30D", + "pixelLocalLoadANGLE(01H", + "pixelLocalLoadANGLE(01I", + "pixelLocalLoadANGLE(01J", + "pixelLocalStoreANGLE(01H30B", + "pixelLocalStoreANGLE(01I30C", + "pixelLocalStoreANGLE(01J30D", "beginInvocationInterlockNV(", "endInvocationInterlockNV(", "beginFragmentShaderOrderingINTEL(", @@ -24383,15 +20985,16 @@ constexpr const char *kMangledNames[] = {"radians(00B", "groupMemoryBarrier(", "EmitVertex(", "EndPrimitive(", - "subpassLoad(01U", - "subpassLoad(01V", - "subpassLoad(01W", + "subpassLoad(01K", + "subpassLoad(01L", + "subpassLoad(01M", "numSamples(", "samplePosition(00D", "interpolateAtCenter(00B", "interpolateAtCenter(10B", "interpolateAtCenter(20B", "interpolateAtCenter(30B", + "loopForwardProgress(", "saturate(00B", "saturate(10B", "saturate(20B", @@ -24432,6 +21035,10 @@ constexpr const char *kMangledNames[] = {"radians(00B", "gl_MaxFragmentAtomicCounterBuffers", "gl_MaxCombinedAtomicCounterBuffers", "gl_MaxAtomicCounterBufferSize", + "gl_ShadingRateFlag2VerticalPixelsEXT", + "gl_ShadingRateFlag4VerticalPixelsEXT", + "gl_ShadingRateFlag2HorizontalPixelsEXT", + "gl_ShadingRateFlag4HorizontalPixelsEXT", "gl_MaxGeometryInputComponents", "gl_MaxGeometryOutputComponents", "gl_MaxGeometryImageUniforms", @@ -24474,12 +21081,12 @@ constexpr const char *kMangledNames[] = {"radians(00B", "gl_SecondaryFragDataEXT", "gl_FragDepthEXT", "gl_LastFragData", - "gl_LastFragColor", "gl_LastFragColorARM", "gl_LastFragDepthARM", "gl_LastFragStencilARM", "gl_PrimitiveID", "gl_Layer", + "gl_ShadingRateEXT", "gl_SampleID", "gl_SamplePosition", "gl_SampleMaskIn", @@ -24493,9 +21100,8 @@ constexpr const char *kMangledNames[] = {"radians(00B", "gl_DrawID", "gl_BaseVertex", "gl_BaseInstance", - "angle_BaseVertex", - "angle_BaseInstance", "gl_ClipDistance", + "gl_PrimitiveShadingRateEXT", "gl_NumWorkGroups", "gl_WorkGroupSize", "gl_WorkGroupID", @@ -25017,7 +21623,7 @@ constexpr uint16_t kMangledOffsets[] = { 506, // texture2DProjGradEXT_00H20B10B10B 507, // texture2DProjGradEXT_00H30B10B10B 508, // textureCubeGradEXT_00J20B20B20B - 509, // textureVideoWEBGL_00p10B + 509, // textureVideoWEBGL_00o10B 510, // texture2D_00H10B00B 511, // texture2DProj_00H20B00B 512, // texture2DProj_00H30B00B @@ -25050,13 +21656,13 @@ constexpr uint16_t kMangledOffsets[] = { 539, // texture_00d30B 540, // texture_00e30B 541, // texture_00g30B - 544, // texture_00l30B - 547, // texture_00o30B + 544, // texture_00k30B + 547, // texture_00n30B 550, // texture_00h30B00B 553, // texture_00L10B 554, // texture_00M10B 555, // texture_00N10B - 556, // texture_00p10B + 556, // texture_00o10B 557, // textureProj_00H20B 558, // textureProj_00Q20B 559, // textureProj_00W20B @@ -25090,8 +21696,8 @@ constexpr uint16_t kMangledOffsets[] = { 587, // textureLod_00e30B00B 588, // textureLod_00h30B00B00B 589, // textureLod_00g30B00B - 592, // textureLod_00l30B00B - 595, // textureLod_00o30B00B + 592, // textureLod_00k30B00B + 595, // textureLod_00n30B00B 598, // textureSize_00H00C 599, // textureSize_00Q00C 600, // textureSize_00W00C @@ -25108,12 +21714,12 @@ constexpr uint16_t kMangledOffsets[] = { 611, // textureSize_00d00C 612, // textureSize_00e00C 613, // textureSize_00g00C - 616, // textureSize_00l00C - 619, // textureSize_00o00C + 616, // textureSize_00k00C + 619, // textureSize_00n00C 622, // textureSize_00h00C 625, // textureSize_00f - 628, // textureSize_00k - 631, // textureSize_00n + 628, // textureSize_00j + 631, // textureSize_00m 634, // textureSize_00O 636, // textureSize_00U 638, // textureSize_00a @@ -25142,8 +21748,8 @@ constexpr uint16_t kMangledOffsets[] = { 665, // texelFetch_00T20C00C 666, // texelFetch_00Z20C00C 667, // texelFetch_00f00C - 670, // texelFetch_00k00C - 673, // texelFetch_00n00C + 670, // texelFetch_00j00C + 673, // texelFetch_00m00C 676, // texelFetch_00O10C00C 678, // texelFetch_00U10C00C 680, // texelFetch_00a10C00C @@ -25168,8 +21774,8 @@ constexpr uint16_t kMangledOffsets[] = { 703, // textureGrad_00Z20B10B10B 704, // textureGrad_00e30B10B10B 705, // textureGrad_00g30B20B20B - 708, // textureGrad_00l30B20B20B - 711, // textureGrad_00o30B20B20B + 708, // textureGrad_00k30B20B20B + 711, // textureGrad_00n30B20B20B 714, // textureProjGrad_00H20B10B10B 715, // textureProjGrad_00Q20B10B10B 716, // textureProjGrad_00W20B10B10B @@ -25206,8 +21812,8 @@ constexpr uint16_t kMangledOffsets[] = { 747, // textureProj_00c30B00B 748, // texture_00e30B00B 749, // texture_00g30B00B - 752, // texture_00l30B00B - 755, // texture_00o30B00B + 752, // texture_00k30B00B + 755, // texture_00n30B00B 758, // texture_00h30B00B00B 759, // texture_00L10B00B 760, // textureProj_00L20B00B @@ -25311,792 +21917,640 @@ constexpr uint16_t kMangledOffsets[] = { 858, // textureGather_00H10B 859, // textureGather_00Q10B 860, // textureGather_00W10B - 861, // textureGather_00H10B00C - 862, // textureGather_00Q10B00C - 863, // textureGather_00W10B00C - 864, // textureGather_00K20B - 865, // textureGather_00T20B - 866, // textureGather_00Z20B - 867, // textureGather_00K20B00C - 868, // textureGather_00T20B00C - 869, // textureGather_00Z20B00C - 870, // textureGather_00J20B - 871, // textureGather_00S20B - 872, // textureGather_00Y20B - 873, // textureGather_00J20B00C - 874, // textureGather_00S20B00C - 875, // textureGather_00Y20B00C - 876, // textureGather_00g30B - 879, // textureGather_00l30B - 882, // textureGather_00o30B + 861, // textureGather_00K20B + 862, // textureGather_00T20B + 863, // textureGather_00Z20B + 864, // textureGather_00J20B + 865, // textureGather_00S20B + 866, // textureGather_00Y20B + 867, // textureGather_00g30B + 870, // textureGather_00k30B + 873, // textureGather_00n30B + 876, // textureGather_00H10B00C + 877, // textureGather_00Q10B00C + 878, // textureGather_00W10B00C + 879, // textureGather_00K20B00C + 880, // textureGather_00T20B00C + 881, // textureGather_00Z20B00C + 882, // textureGather_00J20B00C + 883, // textureGather_00S20B00C + 884, // textureGather_00Y20B00C 885, // textureGather_00g30B00C - 888, // textureGather_00l30B00C - 891, // textureGather_00o30B00C + 888, // textureGather_00k30B00C + 891, // textureGather_00n30B00C 894, // textureGather_00h30B00B - 897, // textureGather_00c10B - 898, // textureGather_00c10B00B - 899, // textureGather_00e20B - 900, // textureGather_00e20B00B - 901, // textureGather_00d20B - 902, // textureGather_00d20B00B - 903, // textureGatherOffset_00H10B10C - 904, // textureGatherOffset_00Q10B10C - 905, // textureGatherOffset_00W10B10C - 906, // textureGatherOffset_00K20B10C - 907, // textureGatherOffset_00T20B10C - 908, // textureGatherOffset_00Z20B10C - 909, // textureGatherOffset_00c10B00B10C - 910, // textureGatherOffset_00e20B00B10C - 911, // textureGatherOffset_00H10B10C00C - 912, // textureGatherOffset_00Q10B10C00C - 913, // textureGatherOffset_00W10B10C00C - 914, // textureGatherOffset_00K20B10C00C - 915, // textureGatherOffset_00T20B10C00C - 916, // textureGatherOffset_00Z20B10C00C - 917, // textureGatherOffsets_00H10B10Cx4 - 920, // textureGatherOffsets_00Q10B10Cx4 - 923, // textureGatherOffsets_00W10B10Cx4 - 926, // textureGatherOffsets_00K20B10Cx4 - 929, // textureGatherOffsets_00T20B10Cx4 - 932, // textureGatherOffsets_00Z20B10Cx4 - 935, // textureGatherOffsets_00c10B00B10Cx4 - 938, // textureGatherOffsets_00e20B00B10Cx4 - 941, // textureGatherOffsets_00H10B10Cx400C - 944, // textureGatherOffsets_00Q10B10Cx400C - 947, // textureGatherOffsets_00W10B10Cx400C - 950, // textureGatherOffsets_00K20B10Cx400C - 953, // textureGatherOffsets_00T20B10Cx400C - 956, // textureGatherOffsets_00Z20B10Cx400C - 959, // textureQueryLOD_00H10B - 960, // textureQueryLOD_00Q10B - 961, // textureQueryLOD_00W10B - 962, // textureQueryLOD_00I20B - 963, // textureQueryLOD_00R20B - 964, // textureQueryLOD_00X20B - 965, // textureQueryLOD_00J20B - 966, // textureQueryLOD_00S20B - 967, // textureQueryLOD_00Y20B - 968, // textureQueryLOD_00K10B - 969, // textureQueryLOD_00T10B - 970, // textureQueryLOD_00Z10B - 971, // textureQueryLOD_00c10B - 972, // textureQueryLOD_00d20B - 973, // textureQueryLOD_00e10B - 974, // textureQueryLOD_00g20B - 975, // textureQueryLOD_00l20B - 976, // textureQueryLOD_00o20B - 977, // textureQueryLOD_00h20B - 978, // rgb_2_yuv_20B00G - 979, // yuv_2_rgb_20B00G - 980, // dFdx_00B - 982, // dFdx_10B - 984, // dFdx_20B - 986, // dFdx_30B - 988, // dFdy_00B - 990, // dFdy_10B - 992, // dFdy_20B - 994, // dFdy_30B - 996, // fwidth_00B - 998, // fwidth_10B - 1000, // fwidth_20B - 1002, // fwidth_30B - 1004, // interpolateAtCentroid_00B - 1006, // interpolateAtCentroid_10B - 1008, // interpolateAtCentroid_20B - 1010, // interpolateAtCentroid_30B - 1012, // interpolateAtSample_00B00C - 1014, // interpolateAtSample_10B00C - 1016, // interpolateAtSample_20B00C - 1018, // interpolateAtSample_30B00C - 1020, // interpolateAtOffset_00B10B - 1022, // interpolateAtOffset_10B10B - 1024, // interpolateAtOffset_20B10B - 1026, // interpolateAtOffset_30B10B - 1028, // atomicCounter_00F - 1029, // atomicCounterIncrement_00F - 1030, // atomicCounterDecrement_00F - 1031, // atomicAdd_00D00D - 1032, // atomicAdd_00C00C - 1033, // atomicMin_00D00D - 1034, // atomicMin_00C00C - 1035, // atomicMax_00D00D - 1036, // atomicMax_00C00C - 1037, // atomicAnd_00D00D - 1038, // atomicAnd_00C00C - 1039, // atomicOr_00D00D - 1040, // atomicOr_00C00C - 1041, // atomicXor_00D00D - 1042, // atomicXor_00C00C - 1043, // atomicExchange_00D00D - 1044, // atomicExchange_00C00C - 1045, // atomicCompSwap_00D00D00D - 1046, // atomicCompSwap_00C00C00C + 897, // textureGather_00c10B00B + 898, // textureGather_00e20B00B + 899, // textureGather_00d20B00B + 900, // textureGatherOffset_00H10B10C + 901, // textureGatherOffset_00Q10B10C + 902, // textureGatherOffset_00W10B10C + 903, // textureGatherOffset_00K20B10C + 904, // textureGatherOffset_00T20B10C + 905, // textureGatherOffset_00Z20B10C + 906, // textureGatherOffset_00H10B10C00C + 907, // textureGatherOffset_00Q10B10C00C + 908, // textureGatherOffset_00W10B10C00C + 909, // textureGatherOffset_00K20B10C00C + 910, // textureGatherOffset_00T20B10C00C + 911, // textureGatherOffset_00Z20B10C00C + 912, // textureGatherOffset_00c10B00B10C + 913, // textureGatherOffset_00e20B00B10C + 914, // textureGatherOffsets_00H10B10Cx4 + 917, // textureGatherOffsets_00Q10B10Cx4 + 920, // textureGatherOffsets_00W10B10Cx4 + 923, // textureGatherOffsets_00K20B10Cx4 + 926, // textureGatherOffsets_00T20B10Cx4 + 929, // textureGatherOffsets_00Z20B10Cx4 + 932, // textureGatherOffsets_00H10B10Cx400C + 935, // textureGatherOffsets_00Q10B10Cx400C + 938, // textureGatherOffsets_00W10B10Cx400C + 941, // textureGatherOffsets_00K20B10Cx400C + 944, // textureGatherOffsets_00T20B10Cx400C + 947, // textureGatherOffsets_00Z20B10Cx400C + 950, // textureGatherOffsets_00c10B00B10Cx4 + 953, // textureGatherOffsets_00e20B00B10Cx4 + 956, // textureQueryLOD_00H10B + 957, // textureQueryLOD_00Q10B + 958, // textureQueryLOD_00W10B + 959, // textureQueryLOD_00I20B + 960, // textureQueryLOD_00R20B + 961, // textureQueryLOD_00X20B + 962, // textureQueryLOD_00J20B + 963, // textureQueryLOD_00S20B + 964, // textureQueryLOD_00Y20B + 965, // textureQueryLOD_00K10B + 966, // textureQueryLOD_00T10B + 967, // textureQueryLOD_00Z10B + 968, // textureQueryLOD_00c10B + 969, // textureQueryLOD_00d20B + 970, // textureQueryLOD_00e10B + 971, // textureQueryLOD_00g20B + 972, // textureQueryLOD_00k20B + 973, // textureQueryLOD_00n20B + 974, // textureQueryLOD_00h20B + 975, // rgb_2_yuv_20B00G + 976, // yuv_2_rgb_20B00G + 977, // dFdx_00B + 979, // dFdx_10B + 981, // dFdx_20B + 983, // dFdx_30B + 985, // dFdy_00B + 987, // dFdy_10B + 989, // dFdy_20B + 991, // dFdy_30B + 993, // fwidth_00B + 995, // fwidth_10B + 997, // fwidth_20B + 999, // fwidth_30B + 1001, // interpolateAtCentroid_00B + 1003, // interpolateAtCentroid_10B + 1005, // interpolateAtCentroid_20B + 1007, // interpolateAtCentroid_30B + 1009, // interpolateAtSample_00B00C + 1011, // interpolateAtSample_10B00C + 1013, // interpolateAtSample_20B00C + 1015, // interpolateAtSample_30B00C + 1017, // interpolateAtOffset_00B10B + 1019, // interpolateAtOffset_10B10B + 1021, // interpolateAtOffset_20B10B + 1023, // interpolateAtOffset_30B10B + 1025, // atomicCounter_00F + 1026, // atomicCounterIncrement_00F + 1027, // atomicCounterDecrement_00F + 1028, // atomicAdd_00D00D + 1029, // atomicAdd_00C00C + 1030, // atomicMin_00D00D + 1031, // atomicMin_00C00C + 1032, // atomicMax_00D00D + 1033, // atomicMax_00C00C + 1034, // atomicAnd_00D00D + 1035, // atomicAnd_00C00C + 1036, // atomicOr_00D00D + 1037, // atomicOr_00C00C + 1038, // atomicXor_00D00D + 1039, // atomicXor_00C00C + 1040, // atomicExchange_00D00D + 1041, // atomicExchange_00C00C + 1042, // atomicCompSwap_00D00D00D + 1043, // atomicCompSwap_00C00C00C + 1044, // imageSize_00p + 1045, // imageSize_00v + 1046, // imageSize_01B 1047, // imageSize_00q - 1048, // imageSize_00z - 1049, // imageSize_01I + 1048, // imageSize_00w + 1049, // imageSize_01C 1050, // imageSize_00r - 1051, // imageSize_01A - 1052, // imageSize_01J + 1051, // imageSize_00x + 1052, // imageSize_01D 1053, // imageSize_00s - 1054, // imageSize_01B - 1055, // imageSize_01K + 1054, // imageSize_00y + 1055, // imageSize_01E 1056, // imageSize_00t - 1057, // imageSize_01C - 1058, // imageSize_01L - 1059, // imageSize_00w + 1059, // imageSize_00z 1062, // imageSize_01F - 1065, // imageSize_01O - 1068, // imageSize_00y - 1071, // imageSize_01H - 1074, // imageSize_01Q - 1077, // imageStore_00q10C30B - 1078, // imageStore_00z10C30C - 1079, // imageStore_01I10C30D + 1065, // imageSize_00u + 1068, // imageSize_01A + 1071, // imageSize_01G + 1074, // imageStore_00p10C30B + 1075, // imageStore_00v10C30C + 1076, // imageStore_01B10C30D + 1077, // imageStore_00q20C30B + 1078, // imageStore_00w20C30C + 1079, // imageStore_01C20C30D 1080, // imageStore_00r20C30B - 1081, // imageStore_01A20C30C - 1082, // imageStore_01J20C30D + 1081, // imageStore_00x20C30C + 1082, // imageStore_01D20C30D 1083, // imageStore_00s20C30B - 1084, // imageStore_01B20C30C - 1085, // imageStore_01K20C30D + 1084, // imageStore_00y20C30C + 1085, // imageStore_01E20C30D 1086, // imageStore_00t20C30B - 1087, // imageStore_01C20C30C - 1088, // imageStore_01L20C30D - 1089, // imageStore_00w20C30B - 1092, // imageStore_01F20C30C - 1095, // imageStore_01O20C30D - 1098, // imageStore_00y00C30B - 1101, // imageStore_01H00C30C - 1104, // imageStore_01Q00C30D - 1107, // imageLoad_00q10C - 1108, // imageLoad_00z10C - 1109, // imageLoad_01I10C + 1089, // imageStore_00z20C30C + 1092, // imageStore_01F20C30D + 1095, // imageStore_00u00C30B + 1098, // imageStore_01A00C30C + 1101, // imageStore_01G00C30D + 1104, // imageLoad_00p10C + 1105, // imageLoad_00v10C + 1106, // imageLoad_01B10C + 1107, // imageLoad_00q20C + 1108, // imageLoad_00w20C + 1109, // imageLoad_01C20C 1110, // imageLoad_00r20C - 1111, // imageLoad_01A20C - 1112, // imageLoad_01J20C + 1111, // imageLoad_00x20C + 1112, // imageLoad_01D20C 1113, // imageLoad_00s20C - 1114, // imageLoad_01B20C - 1115, // imageLoad_01K20C + 1114, // imageLoad_00y20C + 1115, // imageLoad_01E20C 1116, // imageLoad_00t20C - 1117, // imageLoad_01C20C - 1118, // imageLoad_01L20C - 1119, // imageLoad_00w20C + 1119, // imageLoad_00z20C 1122, // imageLoad_01F20C - 1125, // imageLoad_01O20C - 1128, // imageLoad_00y00C - 1131, // imageLoad_01H00C - 1134, // imageLoad_01Q00C - 1137, // imageAtomicAdd_00q10C00D - 1139, // imageAtomicAdd_00z10C00D - 1141, // imageAtomicAdd_01I10C00D - 1143, // imageAtomicAdd_00r20C00D - 1145, // imageAtomicAdd_01A20C00D - 1147, // imageAtomicAdd_01J20C00D - 1149, // imageAtomicAdd_00t20C00D - 1151, // imageAtomicAdd_01C20C00D - 1153, // imageAtomicAdd_01L20C00D - 1155, // imageAtomicAdd_00y00C00D - 1157, // imageAtomicAdd_01H00C00D - 1159, // imageAtomicAdd_01Q00C00D - 1161, // imageAtomicAdd_00s20C00D - 1163, // imageAtomicAdd_01B20C00D - 1165, // imageAtomicAdd_01K20C00D - 1167, // imageAtomicAdd_00w20C00D - 1169, // imageAtomicAdd_01F20C00D - 1171, // imageAtomicAdd_01O20C00D - 1173, // imageAtomicAdd_00x10C00D - 1175, // imageAtomicAdd_01G10C00D - 1177, // imageAtomicAdd_01P10C00D - 1179, // imageAtomicAdd_00u10C00C00D - 1181, // imageAtomicAdd_01D10C00C00D - 1183, // imageAtomicAdd_01M10C00C00D - 1185, // imageAtomicAdd_00v20C00C00D - 1187, // imageAtomicAdd_01E20C00C00D - 1189, // imageAtomicAdd_01N20C00C00D - 1191, // imageAtomicAdd_00q10C00C - 1193, // imageAtomicAdd_00z10C00C - 1195, // imageAtomicAdd_01I10C00C - 1197, // imageAtomicAdd_00r20C00C - 1199, // imageAtomicAdd_01A20C00C - 1201, // imageAtomicAdd_01J20C00C - 1203, // imageAtomicAdd_00t20C00C - 1205, // imageAtomicAdd_01C20C00C - 1207, // imageAtomicAdd_01L20C00C - 1209, // imageAtomicAdd_00y00C00C - 1211, // imageAtomicAdd_01H00C00C - 1213, // imageAtomicAdd_01Q00C00C - 1215, // imageAtomicAdd_00s20C00C - 1217, // imageAtomicAdd_01B20C00C - 1219, // imageAtomicAdd_01K20C00C - 1221, // imageAtomicAdd_00w20C00C - 1223, // imageAtomicAdd_01F20C00C - 1225, // imageAtomicAdd_01O20C00C - 1227, // imageAtomicAdd_00x10C00C - 1229, // imageAtomicAdd_01G10C00C - 1231, // imageAtomicAdd_01P10C00C - 1233, // imageAtomicAdd_00u10C00C00C - 1235, // imageAtomicAdd_01D10C00C00C - 1237, // imageAtomicAdd_01M10C00C00C - 1239, // imageAtomicAdd_00v20C00C00C - 1241, // imageAtomicAdd_01E20C00C00C - 1243, // imageAtomicAdd_01N20C00C00C - 1245, // imageAtomicMin_00q10C00D - 1247, // imageAtomicMin_00z10C00D - 1249, // imageAtomicMin_01I10C00D - 1251, // imageAtomicMin_00r20C00D - 1253, // imageAtomicMin_01A20C00D - 1255, // imageAtomicMin_01J20C00D - 1257, // imageAtomicMin_00t20C00D - 1259, // imageAtomicMin_01C20C00D - 1261, // imageAtomicMin_01L20C00D - 1263, // imageAtomicMin_00y00C00D - 1265, // imageAtomicMin_01H00C00D - 1267, // imageAtomicMin_01Q00C00D - 1269, // imageAtomicMin_00s20C00D - 1271, // imageAtomicMin_01B20C00D - 1273, // imageAtomicMin_01K20C00D - 1275, // imageAtomicMin_00w20C00D - 1277, // imageAtomicMin_01F20C00D - 1279, // imageAtomicMin_01O20C00D - 1281, // imageAtomicMin_00x10C00D - 1283, // imageAtomicMin_01G10C00D - 1285, // imageAtomicMin_01P10C00D - 1287, // imageAtomicMin_00u10C00C00D - 1289, // imageAtomicMin_01D10C00C00D - 1291, // imageAtomicMin_01M10C00C00D - 1293, // imageAtomicMin_00v20C00C00D - 1295, // imageAtomicMin_01E20C00C00D - 1297, // imageAtomicMin_01N20C00C00D - 1299, // imageAtomicMin_00q10C00C - 1301, // imageAtomicMin_00z10C00C - 1303, // imageAtomicMin_01I10C00C - 1305, // imageAtomicMin_00r20C00C - 1307, // imageAtomicMin_01A20C00C - 1309, // imageAtomicMin_01J20C00C - 1311, // imageAtomicMin_00t20C00C - 1313, // imageAtomicMin_01C20C00C - 1315, // imageAtomicMin_01L20C00C - 1317, // imageAtomicMin_00y00C00C - 1319, // imageAtomicMin_01H00C00C - 1321, // imageAtomicMin_01Q00C00C - 1323, // imageAtomicMin_00s20C00C - 1325, // imageAtomicMin_01B20C00C - 1327, // imageAtomicMin_01K20C00C - 1329, // imageAtomicMin_00w20C00C - 1331, // imageAtomicMin_01F20C00C - 1333, // imageAtomicMin_01O20C00C - 1335, // imageAtomicMin_00x10C00C - 1337, // imageAtomicMin_01G10C00C - 1339, // imageAtomicMin_01P10C00C - 1341, // imageAtomicMin_00u10C00C00C - 1343, // imageAtomicMin_01D10C00C00C - 1345, // imageAtomicMin_01M10C00C00C - 1347, // imageAtomicMin_00v20C00C00C - 1349, // imageAtomicMin_01E20C00C00C - 1351, // imageAtomicMin_01N20C00C00C - 1353, // imageAtomicMax_00q10C00D - 1355, // imageAtomicMax_00z10C00D - 1357, // imageAtomicMax_01I10C00D - 1359, // imageAtomicMax_00r20C00D - 1361, // imageAtomicMax_01A20C00D - 1363, // imageAtomicMax_01J20C00D - 1365, // imageAtomicMax_00t20C00D - 1367, // imageAtomicMax_01C20C00D - 1369, // imageAtomicMax_01L20C00D - 1371, // imageAtomicMax_00y00C00D - 1373, // imageAtomicMax_01H00C00D - 1375, // imageAtomicMax_01Q00C00D - 1377, // imageAtomicMax_00s20C00D - 1379, // imageAtomicMax_01B20C00D - 1381, // imageAtomicMax_01K20C00D - 1383, // imageAtomicMax_00w20C00D - 1385, // imageAtomicMax_01F20C00D - 1387, // imageAtomicMax_01O20C00D - 1389, // imageAtomicMax_00x10C00D - 1391, // imageAtomicMax_01G10C00D - 1393, // imageAtomicMax_01P10C00D - 1395, // imageAtomicMax_00u10C00C00D - 1397, // imageAtomicMax_01D10C00C00D - 1399, // imageAtomicMax_01M10C00C00D - 1401, // imageAtomicMax_00v20C00C00D - 1403, // imageAtomicMax_01E20C00C00D - 1405, // imageAtomicMax_01N20C00C00D - 1407, // imageAtomicMax_00q10C00C - 1409, // imageAtomicMax_00z10C00C - 1411, // imageAtomicMax_01I10C00C - 1413, // imageAtomicMax_00r20C00C - 1415, // imageAtomicMax_01A20C00C - 1417, // imageAtomicMax_01J20C00C - 1419, // imageAtomicMax_00t20C00C - 1421, // imageAtomicMax_01C20C00C - 1423, // imageAtomicMax_01L20C00C - 1425, // imageAtomicMax_00y00C00C - 1427, // imageAtomicMax_01H00C00C - 1429, // imageAtomicMax_01Q00C00C - 1431, // imageAtomicMax_00s20C00C - 1433, // imageAtomicMax_01B20C00C - 1435, // imageAtomicMax_01K20C00C - 1437, // imageAtomicMax_00w20C00C - 1439, // imageAtomicMax_01F20C00C - 1441, // imageAtomicMax_01O20C00C - 1443, // imageAtomicMax_00x10C00C - 1445, // imageAtomicMax_01G10C00C - 1447, // imageAtomicMax_01P10C00C - 1449, // imageAtomicMax_00u10C00C00C - 1451, // imageAtomicMax_01D10C00C00C - 1453, // imageAtomicMax_01M10C00C00C - 1455, // imageAtomicMax_00v20C00C00C - 1457, // imageAtomicMax_01E20C00C00C - 1459, // imageAtomicMax_01N20C00C00C - 1461, // imageAtomicAnd_00q10C00D - 1463, // imageAtomicAnd_00z10C00D - 1465, // imageAtomicAnd_01I10C00D - 1467, // imageAtomicAnd_00r20C00D - 1469, // imageAtomicAnd_01A20C00D - 1471, // imageAtomicAnd_01J20C00D - 1473, // imageAtomicAnd_00t20C00D - 1475, // imageAtomicAnd_01C20C00D - 1477, // imageAtomicAnd_01L20C00D - 1479, // imageAtomicAnd_00y00C00D - 1481, // imageAtomicAnd_01H00C00D - 1483, // imageAtomicAnd_01Q00C00D - 1485, // imageAtomicAnd_00s20C00D - 1487, // imageAtomicAnd_01B20C00D - 1489, // imageAtomicAnd_01K20C00D - 1491, // imageAtomicAnd_00w20C00D - 1493, // imageAtomicAnd_01F20C00D - 1495, // imageAtomicAnd_01O20C00D - 1497, // imageAtomicAnd_00x10C00D - 1499, // imageAtomicAnd_01G10C00D - 1501, // imageAtomicAnd_01P10C00D - 1503, // imageAtomicAnd_00u10C00C00D - 1505, // imageAtomicAnd_01D10C00C00D - 1507, // imageAtomicAnd_01M10C00C00D - 1509, // imageAtomicAnd_00v20C00C00D - 1511, // imageAtomicAnd_01E20C00C00D - 1513, // imageAtomicAnd_01N20C00C00D - 1515, // imageAtomicAnd_00q10C00C - 1517, // imageAtomicAnd_00z10C00C - 1519, // imageAtomicAnd_01I10C00C - 1521, // imageAtomicAnd_00r20C00C - 1523, // imageAtomicAnd_01A20C00C - 1525, // imageAtomicAnd_01J20C00C - 1527, // imageAtomicAnd_00t20C00C - 1529, // imageAtomicAnd_01C20C00C - 1531, // imageAtomicAnd_01L20C00C - 1533, // imageAtomicAnd_00y00C00C - 1535, // imageAtomicAnd_01H00C00C - 1537, // imageAtomicAnd_01Q00C00C - 1539, // imageAtomicAnd_00s20C00C - 1541, // imageAtomicAnd_01B20C00C - 1543, // imageAtomicAnd_01K20C00C - 1545, // imageAtomicAnd_00w20C00C - 1547, // imageAtomicAnd_01F20C00C - 1549, // imageAtomicAnd_01O20C00C - 1551, // imageAtomicAnd_00x10C00C - 1553, // imageAtomicAnd_01G10C00C - 1555, // imageAtomicAnd_01P10C00C - 1557, // imageAtomicAnd_00u10C00C00C - 1559, // imageAtomicAnd_01D10C00C00C - 1561, // imageAtomicAnd_01M10C00C00C - 1563, // imageAtomicAnd_00v20C00C00C - 1565, // imageAtomicAnd_01E20C00C00C - 1567, // imageAtomicAnd_01N20C00C00C - 1569, // imageAtomicOr_00q10C00D - 1571, // imageAtomicOr_00z10C00D - 1573, // imageAtomicOr_01I10C00D - 1575, // imageAtomicOr_00r20C00D - 1577, // imageAtomicOr_01A20C00D - 1579, // imageAtomicOr_01J20C00D - 1581, // imageAtomicOr_00t20C00D - 1583, // imageAtomicOr_01C20C00D - 1585, // imageAtomicOr_01L20C00D - 1587, // imageAtomicOr_00y00C00D - 1589, // imageAtomicOr_01H00C00D - 1591, // imageAtomicOr_01Q00C00D - 1593, // imageAtomicOr_00s20C00D - 1595, // imageAtomicOr_01B20C00D - 1597, // imageAtomicOr_01K20C00D - 1599, // imageAtomicOr_00w20C00D - 1601, // imageAtomicOr_01F20C00D - 1603, // imageAtomicOr_01O20C00D - 1605, // imageAtomicOr_00x10C00D - 1607, // imageAtomicOr_01G10C00D - 1609, // imageAtomicOr_01P10C00D - 1611, // imageAtomicOr_00u10C00C00D - 1613, // imageAtomicOr_01D10C00C00D - 1615, // imageAtomicOr_01M10C00C00D - 1617, // imageAtomicOr_00v20C00C00D - 1619, // imageAtomicOr_01E20C00C00D - 1621, // imageAtomicOr_01N20C00C00D - 1623, // imageAtomicOr_00q10C00C - 1625, // imageAtomicOr_00z10C00C - 1627, // imageAtomicOr_01I10C00C - 1629, // imageAtomicOr_00r20C00C - 1631, // imageAtomicOr_01A20C00C - 1633, // imageAtomicOr_01J20C00C - 1635, // imageAtomicOr_00t20C00C - 1637, // imageAtomicOr_01C20C00C - 1639, // imageAtomicOr_01L20C00C - 1641, // imageAtomicOr_00y00C00C - 1643, // imageAtomicOr_01H00C00C - 1645, // imageAtomicOr_01Q00C00C - 1647, // imageAtomicOr_00s20C00C - 1649, // imageAtomicOr_01B20C00C - 1651, // imageAtomicOr_01K20C00C - 1653, // imageAtomicOr_00w20C00C - 1655, // imageAtomicOr_01F20C00C - 1657, // imageAtomicOr_01O20C00C - 1659, // imageAtomicOr_00x10C00C - 1661, // imageAtomicOr_01G10C00C - 1663, // imageAtomicOr_01P10C00C - 1665, // imageAtomicOr_00u10C00C00C - 1667, // imageAtomicOr_01D10C00C00C - 1669, // imageAtomicOr_01M10C00C00C - 1671, // imageAtomicOr_00v20C00C00C - 1673, // imageAtomicOr_01E20C00C00C - 1675, // imageAtomicOr_01N20C00C00C - 1677, // imageAtomicXor_00q10C00D - 1679, // imageAtomicXor_00z10C00D - 1681, // imageAtomicXor_01I10C00D - 1683, // imageAtomicXor_00r20C00D - 1685, // imageAtomicXor_01A20C00D - 1687, // imageAtomicXor_01J20C00D - 1689, // imageAtomicXor_00t20C00D - 1691, // imageAtomicXor_01C20C00D - 1693, // imageAtomicXor_01L20C00D - 1695, // imageAtomicXor_00y00C00D - 1697, // imageAtomicXor_01H00C00D - 1699, // imageAtomicXor_01Q00C00D - 1701, // imageAtomicXor_00s20C00D - 1703, // imageAtomicXor_01B20C00D - 1705, // imageAtomicXor_01K20C00D - 1707, // imageAtomicXor_00w20C00D - 1709, // imageAtomicXor_01F20C00D - 1711, // imageAtomicXor_01O20C00D - 1713, // imageAtomicXor_00x10C00D - 1715, // imageAtomicXor_01G10C00D - 1717, // imageAtomicXor_01P10C00D - 1719, // imageAtomicXor_00u10C00C00D - 1721, // imageAtomicXor_01D10C00C00D - 1723, // imageAtomicXor_01M10C00C00D - 1725, // imageAtomicXor_00v20C00C00D - 1727, // imageAtomicXor_01E20C00C00D - 1729, // imageAtomicXor_01N20C00C00D - 1731, // imageAtomicXor_00q10C00C - 1733, // imageAtomicXor_00z10C00C - 1735, // imageAtomicXor_01I10C00C - 1737, // imageAtomicXor_00r20C00C - 1739, // imageAtomicXor_01A20C00C - 1741, // imageAtomicXor_01J20C00C - 1743, // imageAtomicXor_00t20C00C - 1745, // imageAtomicXor_01C20C00C - 1747, // imageAtomicXor_01L20C00C - 1749, // imageAtomicXor_00y00C00C - 1751, // imageAtomicXor_01H00C00C - 1753, // imageAtomicXor_01Q00C00C - 1755, // imageAtomicXor_00s20C00C - 1757, // imageAtomicXor_01B20C00C - 1759, // imageAtomicXor_01K20C00C - 1761, // imageAtomicXor_00w20C00C - 1763, // imageAtomicXor_01F20C00C - 1765, // imageAtomicXor_01O20C00C - 1767, // imageAtomicXor_00x10C00C - 1769, // imageAtomicXor_01G10C00C - 1771, // imageAtomicXor_01P10C00C - 1773, // imageAtomicXor_00u10C00C00C - 1775, // imageAtomicXor_01D10C00C00C - 1777, // imageAtomicXor_01M10C00C00C - 1779, // imageAtomicXor_00v20C00C00C - 1781, // imageAtomicXor_01E20C00C00C - 1783, // imageAtomicXor_01N20C00C00C - 1785, // imageAtomicExchange_00q10C00D - 1787, // imageAtomicExchange_00z10C00D - 1789, // imageAtomicExchange_01I10C00D - 1791, // imageAtomicExchange_00r20C00D - 1793, // imageAtomicExchange_01A20C00D - 1795, // imageAtomicExchange_01J20C00D - 1797, // imageAtomicExchange_00t20C00D - 1799, // imageAtomicExchange_01C20C00D - 1801, // imageAtomicExchange_01L20C00D - 1803, // imageAtomicExchange_00y00C00D - 1805, // imageAtomicExchange_01H00C00D - 1807, // imageAtomicExchange_01Q00C00D - 1809, // imageAtomicExchange_00s20C00D - 1811, // imageAtomicExchange_01B20C00D - 1813, // imageAtomicExchange_01K20C00D - 1815, // imageAtomicExchange_00w20C00D - 1817, // imageAtomicExchange_01F20C00D - 1819, // imageAtomicExchange_01O20C00D - 1821, // imageAtomicExchange_00x10C00D - 1823, // imageAtomicExchange_01G10C00D - 1825, // imageAtomicExchange_01P10C00D - 1827, // imageAtomicExchange_00u10C00C00D - 1829, // imageAtomicExchange_01D10C00C00D - 1831, // imageAtomicExchange_01M10C00C00D - 1833, // imageAtomicExchange_00v20C00C00D - 1835, // imageAtomicExchange_01E20C00C00D - 1837, // imageAtomicExchange_01N20C00C00D - 1839, // imageAtomicExchange_00q10C00C - 1841, // imageAtomicExchange_00z10C00C - 1843, // imageAtomicExchange_01I10C00C - 1845, // imageAtomicExchange_00r20C00C - 1847, // imageAtomicExchange_01A20C00C - 1849, // imageAtomicExchange_01J20C00C - 1851, // imageAtomicExchange_00t20C00C - 1853, // imageAtomicExchange_01C20C00C - 1855, // imageAtomicExchange_01L20C00C - 1857, // imageAtomicExchange_00y00C00C - 1859, // imageAtomicExchange_01H00C00C - 1861, // imageAtomicExchange_01Q00C00C - 1863, // imageAtomicExchange_00s20C00C - 1865, // imageAtomicExchange_01B20C00C - 1867, // imageAtomicExchange_01K20C00C - 1869, // imageAtomicExchange_00w20C00C - 1871, // imageAtomicExchange_01F20C00C - 1873, // imageAtomicExchange_01O20C00C - 1875, // imageAtomicExchange_00x10C00C - 1877, // imageAtomicExchange_01G10C00C - 1879, // imageAtomicExchange_01P10C00C - 1881, // imageAtomicExchange_00u10C00C00C - 1883, // imageAtomicExchange_01D10C00C00C - 1885, // imageAtomicExchange_01M10C00C00C - 1887, // imageAtomicExchange_00v20C00C00C - 1889, // imageAtomicExchange_01E20C00C00C - 1891, // imageAtomicExchange_01N20C00C00C - 1893, // imageAtomicExchange_00q10C00B - 1895, // imageAtomicExchange_00z10C00B - 1897, // imageAtomicExchange_01I10C00B - 1899, // imageAtomicExchange_00r20C00B - 1901, // imageAtomicExchange_01A20C00B - 1903, // imageAtomicExchange_01J20C00B - 1905, // imageAtomicExchange_00t20C00B - 1907, // imageAtomicExchange_01C20C00B - 1909, // imageAtomicExchange_01L20C00B - 1911, // imageAtomicExchange_00y00C00B - 1913, // imageAtomicExchange_01H00C00B - 1915, // imageAtomicExchange_01Q00C00B - 1917, // imageAtomicExchange_00s20C00B - 1919, // imageAtomicExchange_01B20C00B - 1921, // imageAtomicExchange_01K20C00B - 1923, // imageAtomicExchange_00w20C00B - 1925, // imageAtomicExchange_01F20C00B - 1927, // imageAtomicExchange_01O20C00B - 1929, // imageAtomicExchange_00x10C00B - 1931, // imageAtomicExchange_01G10C00B - 1933, // imageAtomicExchange_01P10C00B - 1935, // imageAtomicExchange_00u10C00C00B - 1937, // imageAtomicExchange_01D10C00C00B - 1939, // imageAtomicExchange_01M10C00C00B - 1941, // imageAtomicExchange_00v20C00C00B - 1943, // imageAtomicExchange_01E20C00C00B - 1945, // imageAtomicExchange_01N20C00C00B - 1947, // imageAtomicCompSwap_00q10C00D00D - 1949, // imageAtomicCompSwap_00z10C00D00D - 1951, // imageAtomicCompSwap_01I10C00D00D - 1953, // imageAtomicCompSwap_00r20C00D00D - 1955, // imageAtomicCompSwap_01A20C00D00D - 1957, // imageAtomicCompSwap_01J20C00D00D - 1959, // imageAtomicCompSwap_00t20C00D00D - 1961, // imageAtomicCompSwap_01C20C00D00D - 1963, // imageAtomicCompSwap_01L20C00D00D - 1965, // imageAtomicCompSwap_00y00C00D00D - 1967, // imageAtomicCompSwap_01H00C00D00D - 1969, // imageAtomicCompSwap_01Q00C00D00D - 1971, // imageAtomicCompSwap_00s20C00D00D - 1973, // imageAtomicCompSwap_01B20C00D00D - 1975, // imageAtomicCompSwap_01K20C00D00D - 1977, // imageAtomicCompSwap_00w20C00D00D - 1979, // imageAtomicCompSwap_01F20C00D00D - 1981, // imageAtomicCompSwap_01O20C00D00D - 1983, // imageAtomicCompSwap_00x10C00D00D - 1985, // imageAtomicCompSwap_01G10C00D00D - 1987, // imageAtomicCompSwap_01P10C00D00D - 1989, // imageAtomicCompSwap_00u10C00C00D00D - 1991, // imageAtomicCompSwap_01D10C00C00D00D - 1993, // imageAtomicCompSwap_01M10C00C00D00D - 1995, // imageAtomicCompSwap_00v20C00C00D00D - 1997, // imageAtomicCompSwap_01E20C00C00D00D - 1999, // imageAtomicCompSwap_01N20C00C00D00D - 2001, // imageAtomicCompSwap_00q10C00C00C - 2003, // imageAtomicCompSwap_00z10C00C00C - 2005, // imageAtomicCompSwap_01I10C00C00C - 2007, // imageAtomicCompSwap_00r20C00C00C - 2009, // imageAtomicCompSwap_01A20C00C00C - 2011, // imageAtomicCompSwap_01J20C00C00C - 2013, // imageAtomicCompSwap_00t20C00C00C - 2015, // imageAtomicCompSwap_01C20C00C00C - 2017, // imageAtomicCompSwap_01L20C00C00C - 2019, // imageAtomicCompSwap_00y00C00C00C - 2021, // imageAtomicCompSwap_01H00C00C00C - 2023, // imageAtomicCompSwap_01Q00C00C00C - 2025, // imageAtomicCompSwap_00s20C00C00C - 2027, // imageAtomicCompSwap_01B20C00C00C - 2029, // imageAtomicCompSwap_01K20C00C00C - 2031, // imageAtomicCompSwap_00w20C00C00C - 2033, // imageAtomicCompSwap_01F20C00C00C - 2035, // imageAtomicCompSwap_01O20C00C00C - 2037, // imageAtomicCompSwap_00x10C00C00C - 2039, // imageAtomicCompSwap_01G10C00C00C - 2041, // imageAtomicCompSwap_01P10C00C00C - 2043, // imageAtomicCompSwap_00u10C00C00C00C - 2045, // imageAtomicCompSwap_01D10C00C00C00C - 2047, // imageAtomicCompSwap_01M10C00C00C00C - 2049, // imageAtomicCompSwap_00v20C00C00C00C - 2051, // imageAtomicCompSwap_01E20C00C00C00C - 2053, // imageAtomicCompSwap_01N20C00C00C00C - 2055, // pixelLocalLoadANGLE_01R - 2056, // pixelLocalLoadANGLE_01S - 2057, // pixelLocalLoadANGLE_01T - 2058, // pixelLocalStoreANGLE_01R30B - 2059, // pixelLocalStoreANGLE_01S30C - 2060, // pixelLocalStoreANGLE_01T30D - 2061, // beginInvocationInterlockNV_ - 2062, // endInvocationInterlockNV_ - 2063, // beginFragmentShaderOrderingINTEL_ - 2064, // beginInvocationInterlockARB_ - 2065, // endInvocationInterlockARB_ - 2066, // memoryBarrier_ - 2067, // memoryBarrierAtomicCounter_ - 2068, // memoryBarrierBuffer_ - 2069, // memoryBarrierImage_ - 2070, // barrier_ - 2074, // memoryBarrierShared_ - 2075, // groupMemoryBarrier_ - 2076, // EmitVertex_ - 2079, // EndPrimitive_ - 2082, // subpassLoad_01U - 2083, // subpassLoad_01V - 2084, // subpassLoad_01W - 2085, // numSamples_ - 2086, // samplePosition_00D - 2087, // interpolateAtCenter_00B - 2088, // interpolateAtCenter_10B - 2089, // interpolateAtCenter_20B - 2090, // interpolateAtCenter_30B - 2091, // saturate_00B - 2092, // saturate_10B - 2093, // saturate_20B - 2094, // saturate_30B - 2095, // gl_DepthRangeParameters - 2096, // gl_DepthRange - 2097, // gl_NumSamples - 2099, // gl_MaxVertexAttribs - 2100, // gl_MaxVertexUniformVectors - 2101, // gl_MaxVertexTextureImageUnits - 2102, // gl_MaxCombinedTextureImageUnits - 2103, // gl_MaxTextureImageUnits - 2104, // gl_MaxFragmentUniformVectors - 2105, // gl_MaxVaryingVectors - 2106, // gl_MaxDrawBuffers - 2107, // gl_MaxDualSourceDrawBuffersEXT - 2108, // gl_MaxVertexOutputVectors - 2109, // gl_MaxFragmentInputVectors - 2110, // gl_MinProgramTexelOffset - 2111, // gl_MaxProgramTexelOffset - 2112, // gl_MaxImageUnits - 2113, // gl_MaxVertexImageUniforms - 2114, // gl_MaxFragmentImageUniforms - 2115, // gl_MaxComputeImageUniforms - 2116, // gl_MaxCombinedImageUniforms - 2117, // gl_MaxCombinedShaderOutputResources - 2118, // gl_MaxComputeWorkGroupCount - 2119, // gl_MaxComputeWorkGroupSize - 2120, // gl_MaxComputeUniformComponents - 2121, // gl_MaxComputeTextureImageUnits - 2122, // gl_MaxComputeAtomicCounters - 2123, // gl_MaxComputeAtomicCounterBuffers - 2124, // gl_MaxVertexAtomicCounters - 2125, // gl_MaxFragmentAtomicCounters - 2126, // gl_MaxCombinedAtomicCounters - 2127, // gl_MaxAtomicCounterBindings - 2128, // gl_MaxVertexAtomicCounterBuffers - 2129, // gl_MaxFragmentAtomicCounterBuffers - 2130, // gl_MaxCombinedAtomicCounterBuffers - 2131, // gl_MaxAtomicCounterBufferSize - 2132, // gl_MaxGeometryInputComponents - 2135, // gl_MaxGeometryOutputComponents - 2138, // gl_MaxGeometryImageUniforms - 2141, // gl_MaxGeometryTextureImageUnits - 2144, // gl_MaxGeometryOutputVertices - 2147, // gl_MaxGeometryTotalOutputComponents - 2150, // gl_MaxGeometryUniformComponents - 2153, // gl_MaxGeometryAtomicCounters - 2156, // gl_MaxGeometryAtomicCounterBuffers - 2159, // gl_MaxTessControlInputComponents - 2162, // gl_MaxTessControlOutputComponents - 2165, // gl_MaxTessControlTextureImageUnits - 2168, // gl_MaxTessControlUniformComponents - 2171, // gl_MaxTessControlTotalOutputComponents - 2174, // gl_MaxTessControlImageUniforms - 2177, // gl_MaxTessControlAtomicCounters - 2180, // gl_MaxTessControlAtomicCounterBuffers - 2183, // gl_MaxTessPatchComponents - 2186, // gl_MaxPatchVertices - 2189, // gl_MaxTessGenLevel - 2192, // gl_MaxTessEvaluationInputComponents - 2195, // gl_MaxTessEvaluationOutputComponents - 2198, // gl_MaxTessEvaluationTextureImageUnits - 2201, // gl_MaxTessEvaluationUniformComponents - 2204, // gl_MaxTessEvaluationImageUniforms - 2207, // gl_MaxTessEvaluationAtomicCounters - 2210, // gl_MaxTessEvaluationAtomicCounterBuffers - 2213, // gl_MaxSamples - 2215, // gl_MaxClipDistances - 2218, // gl_MaxCullDistances - 2220, // gl_MaxCombinedClipAndCullDistances - 2222, // gl_FragCoord - 2224, // gl_FrontFacing - 2225, // gl_PointCoord - 2226, // gl_FragColor - 2227, // gl_FragData - 2228, // gl_FragDepth - 2229, // gl_HelperInvocation - 2230, // gl_SecondaryFragColorEXT - 2231, // gl_SecondaryFragDataEXT - 2232, // gl_FragDepthEXT - 2233, // gl_LastFragData - 2236, // gl_LastFragColor - 2237, // gl_LastFragColorARM - 2238, // gl_LastFragDepthARM - 2239, // gl_LastFragStencilARM - 2240, // gl_PrimitiveID - 2252, // gl_Layer - 2259, // gl_SampleID - 2261, // gl_SamplePosition - 2263, // gl_SampleMaskIn - 2265, // gl_SampleMask - 2267, // gl_Position - 2277, // gl_PointSize - 2279, // gl_InstanceID - 2280, // gl_InstanceIndex - 2281, // gl_VertexID - 2282, // gl_VertexIndex - 2283, // gl_DrawID - 2284, // gl_BaseVertex - 2285, // gl_BaseInstance - 2286, // angle_BaseVertex - 2287, // angle_BaseInstance - 2288, // gl_ClipDistance - 2291, // gl_NumWorkGroups - 2292, // gl_WorkGroupSize - 2293, // gl_WorkGroupID - 2294, // gl_LocalInvocationID - 2295, // gl_GlobalInvocationID - 2296, // gl_LocalInvocationIndex - 2297, // gl_PrimitiveIDIn - 2300, // gl_InvocationID - 2306, // gl_PerVertex - 2315, // gl_in - 2324, // gl_PatchVerticesIn - 2330, // gl_TessLevelOuter - 2336, // gl_TessLevelInner - 2342, // gl_out - 2348, // gl_BoundingBox - 2351, // gl_BoundingBoxEXT - 2354, // gl_BoundingBoxOES - 2357, // gl_TessCoord - 2358, // gl_ViewID_OVR - 2359, // gl_CullDistance + 1125, // imageLoad_00u00C + 1128, // imageLoad_01A00C + 1131, // imageLoad_01G00C + 1134, // imageAtomicAdd_00p10C00D + 1136, // imageAtomicAdd_00v10C00D + 1138, // imageAtomicAdd_01B10C00D + 1140, // imageAtomicAdd_00q20C00D + 1142, // imageAtomicAdd_00w20C00D + 1144, // imageAtomicAdd_01C20C00D + 1146, // imageAtomicAdd_00s20C00D + 1148, // imageAtomicAdd_00y20C00D + 1150, // imageAtomicAdd_01E20C00D + 1152, // imageAtomicAdd_00u00C00D + 1154, // imageAtomicAdd_01A00C00D + 1156, // imageAtomicAdd_01G00C00D + 1158, // imageAtomicAdd_00r20C00D + 1160, // imageAtomicAdd_00x20C00D + 1162, // imageAtomicAdd_01D20C00D + 1164, // imageAtomicAdd_00t20C00D + 1166, // imageAtomicAdd_00z20C00D + 1168, // imageAtomicAdd_01F20C00D + 1170, // imageAtomicAdd_00p10C00C + 1172, // imageAtomicAdd_00v10C00C + 1174, // imageAtomicAdd_01B10C00C + 1176, // imageAtomicAdd_00q20C00C + 1178, // imageAtomicAdd_00w20C00C + 1180, // imageAtomicAdd_01C20C00C + 1182, // imageAtomicAdd_00s20C00C + 1184, // imageAtomicAdd_00y20C00C + 1186, // imageAtomicAdd_01E20C00C + 1188, // imageAtomicAdd_00u00C00C + 1190, // imageAtomicAdd_01A00C00C + 1192, // imageAtomicAdd_01G00C00C + 1194, // imageAtomicAdd_00r20C00C + 1196, // imageAtomicAdd_00x20C00C + 1198, // imageAtomicAdd_01D20C00C + 1200, // imageAtomicAdd_00t20C00C + 1202, // imageAtomicAdd_00z20C00C + 1204, // imageAtomicAdd_01F20C00C + 1206, // imageAtomicMin_00p10C00D + 1208, // imageAtomicMin_00v10C00D + 1210, // imageAtomicMin_01B10C00D + 1212, // imageAtomicMin_00q20C00D + 1214, // imageAtomicMin_00w20C00D + 1216, // imageAtomicMin_01C20C00D + 1218, // imageAtomicMin_00s20C00D + 1220, // imageAtomicMin_00y20C00D + 1222, // imageAtomicMin_01E20C00D + 1224, // imageAtomicMin_00u00C00D + 1226, // imageAtomicMin_01A00C00D + 1228, // imageAtomicMin_01G00C00D + 1230, // imageAtomicMin_00r20C00D + 1232, // imageAtomicMin_00x20C00D + 1234, // imageAtomicMin_01D20C00D + 1236, // imageAtomicMin_00t20C00D + 1238, // imageAtomicMin_00z20C00D + 1240, // imageAtomicMin_01F20C00D + 1242, // imageAtomicMin_00p10C00C + 1244, // imageAtomicMin_00v10C00C + 1246, // imageAtomicMin_01B10C00C + 1248, // imageAtomicMin_00q20C00C + 1250, // imageAtomicMin_00w20C00C + 1252, // imageAtomicMin_01C20C00C + 1254, // imageAtomicMin_00s20C00C + 1256, // imageAtomicMin_00y20C00C + 1258, // imageAtomicMin_01E20C00C + 1260, // imageAtomicMin_00u00C00C + 1262, // imageAtomicMin_01A00C00C + 1264, // imageAtomicMin_01G00C00C + 1266, // imageAtomicMin_00r20C00C + 1268, // imageAtomicMin_00x20C00C + 1270, // imageAtomicMin_01D20C00C + 1272, // imageAtomicMin_00t20C00C + 1274, // imageAtomicMin_00z20C00C + 1276, // imageAtomicMin_01F20C00C + 1278, // imageAtomicMax_00p10C00D + 1280, // imageAtomicMax_00v10C00D + 1282, // imageAtomicMax_01B10C00D + 1284, // imageAtomicMax_00q20C00D + 1286, // imageAtomicMax_00w20C00D + 1288, // imageAtomicMax_01C20C00D + 1290, // imageAtomicMax_00s20C00D + 1292, // imageAtomicMax_00y20C00D + 1294, // imageAtomicMax_01E20C00D + 1296, // imageAtomicMax_00u00C00D + 1298, // imageAtomicMax_01A00C00D + 1300, // imageAtomicMax_01G00C00D + 1302, // imageAtomicMax_00r20C00D + 1304, // imageAtomicMax_00x20C00D + 1306, // imageAtomicMax_01D20C00D + 1308, // imageAtomicMax_00t20C00D + 1310, // imageAtomicMax_00z20C00D + 1312, // imageAtomicMax_01F20C00D + 1314, // imageAtomicMax_00p10C00C + 1316, // imageAtomicMax_00v10C00C + 1318, // imageAtomicMax_01B10C00C + 1320, // imageAtomicMax_00q20C00C + 1322, // imageAtomicMax_00w20C00C + 1324, // imageAtomicMax_01C20C00C + 1326, // imageAtomicMax_00s20C00C + 1328, // imageAtomicMax_00y20C00C + 1330, // imageAtomicMax_01E20C00C + 1332, // imageAtomicMax_00u00C00C + 1334, // imageAtomicMax_01A00C00C + 1336, // imageAtomicMax_01G00C00C + 1338, // imageAtomicMax_00r20C00C + 1340, // imageAtomicMax_00x20C00C + 1342, // imageAtomicMax_01D20C00C + 1344, // imageAtomicMax_00t20C00C + 1346, // imageAtomicMax_00z20C00C + 1348, // imageAtomicMax_01F20C00C + 1350, // imageAtomicAnd_00p10C00D + 1352, // imageAtomicAnd_00v10C00D + 1354, // imageAtomicAnd_01B10C00D + 1356, // imageAtomicAnd_00q20C00D + 1358, // imageAtomicAnd_00w20C00D + 1360, // imageAtomicAnd_01C20C00D + 1362, // imageAtomicAnd_00s20C00D + 1364, // imageAtomicAnd_00y20C00D + 1366, // imageAtomicAnd_01E20C00D + 1368, // imageAtomicAnd_00u00C00D + 1370, // imageAtomicAnd_01A00C00D + 1372, // imageAtomicAnd_01G00C00D + 1374, // imageAtomicAnd_00r20C00D + 1376, // imageAtomicAnd_00x20C00D + 1378, // imageAtomicAnd_01D20C00D + 1380, // imageAtomicAnd_00t20C00D + 1382, // imageAtomicAnd_00z20C00D + 1384, // imageAtomicAnd_01F20C00D + 1386, // imageAtomicAnd_00p10C00C + 1388, // imageAtomicAnd_00v10C00C + 1390, // imageAtomicAnd_01B10C00C + 1392, // imageAtomicAnd_00q20C00C + 1394, // imageAtomicAnd_00w20C00C + 1396, // imageAtomicAnd_01C20C00C + 1398, // imageAtomicAnd_00s20C00C + 1400, // imageAtomicAnd_00y20C00C + 1402, // imageAtomicAnd_01E20C00C + 1404, // imageAtomicAnd_00u00C00C + 1406, // imageAtomicAnd_01A00C00C + 1408, // imageAtomicAnd_01G00C00C + 1410, // imageAtomicAnd_00r20C00C + 1412, // imageAtomicAnd_00x20C00C + 1414, // imageAtomicAnd_01D20C00C + 1416, // imageAtomicAnd_00t20C00C + 1418, // imageAtomicAnd_00z20C00C + 1420, // imageAtomicAnd_01F20C00C + 1422, // imageAtomicOr_00p10C00D + 1424, // imageAtomicOr_00v10C00D + 1426, // imageAtomicOr_01B10C00D + 1428, // imageAtomicOr_00q20C00D + 1430, // imageAtomicOr_00w20C00D + 1432, // imageAtomicOr_01C20C00D + 1434, // imageAtomicOr_00s20C00D + 1436, // imageAtomicOr_00y20C00D + 1438, // imageAtomicOr_01E20C00D + 1440, // imageAtomicOr_00u00C00D + 1442, // imageAtomicOr_01A00C00D + 1444, // imageAtomicOr_01G00C00D + 1446, // imageAtomicOr_00r20C00D + 1448, // imageAtomicOr_00x20C00D + 1450, // imageAtomicOr_01D20C00D + 1452, // imageAtomicOr_00t20C00D + 1454, // imageAtomicOr_00z20C00D + 1456, // imageAtomicOr_01F20C00D + 1458, // imageAtomicOr_00p10C00C + 1460, // imageAtomicOr_00v10C00C + 1462, // imageAtomicOr_01B10C00C + 1464, // imageAtomicOr_00q20C00C + 1466, // imageAtomicOr_00w20C00C + 1468, // imageAtomicOr_01C20C00C + 1470, // imageAtomicOr_00s20C00C + 1472, // imageAtomicOr_00y20C00C + 1474, // imageAtomicOr_01E20C00C + 1476, // imageAtomicOr_00u00C00C + 1478, // imageAtomicOr_01A00C00C + 1480, // imageAtomicOr_01G00C00C + 1482, // imageAtomicOr_00r20C00C + 1484, // imageAtomicOr_00x20C00C + 1486, // imageAtomicOr_01D20C00C + 1488, // imageAtomicOr_00t20C00C + 1490, // imageAtomicOr_00z20C00C + 1492, // imageAtomicOr_01F20C00C + 1494, // imageAtomicXor_00p10C00D + 1496, // imageAtomicXor_00v10C00D + 1498, // imageAtomicXor_01B10C00D + 1500, // imageAtomicXor_00q20C00D + 1502, // imageAtomicXor_00w20C00D + 1504, // imageAtomicXor_01C20C00D + 1506, // imageAtomicXor_00s20C00D + 1508, // imageAtomicXor_00y20C00D + 1510, // imageAtomicXor_01E20C00D + 1512, // imageAtomicXor_00u00C00D + 1514, // imageAtomicXor_01A00C00D + 1516, // imageAtomicXor_01G00C00D + 1518, // imageAtomicXor_00r20C00D + 1520, // imageAtomicXor_00x20C00D + 1522, // imageAtomicXor_01D20C00D + 1524, // imageAtomicXor_00t20C00D + 1526, // imageAtomicXor_00z20C00D + 1528, // imageAtomicXor_01F20C00D + 1530, // imageAtomicXor_00p10C00C + 1532, // imageAtomicXor_00v10C00C + 1534, // imageAtomicXor_01B10C00C + 1536, // imageAtomicXor_00q20C00C + 1538, // imageAtomicXor_00w20C00C + 1540, // imageAtomicXor_01C20C00C + 1542, // imageAtomicXor_00s20C00C + 1544, // imageAtomicXor_00y20C00C + 1546, // imageAtomicXor_01E20C00C + 1548, // imageAtomicXor_00u00C00C + 1550, // imageAtomicXor_01A00C00C + 1552, // imageAtomicXor_01G00C00C + 1554, // imageAtomicXor_00r20C00C + 1556, // imageAtomicXor_00x20C00C + 1558, // imageAtomicXor_01D20C00C + 1560, // imageAtomicXor_00t20C00C + 1562, // imageAtomicXor_00z20C00C + 1564, // imageAtomicXor_01F20C00C + 1566, // imageAtomicExchange_00p10C00D + 1568, // imageAtomicExchange_00v10C00D + 1570, // imageAtomicExchange_01B10C00D + 1572, // imageAtomicExchange_00q20C00D + 1574, // imageAtomicExchange_00w20C00D + 1576, // imageAtomicExchange_01C20C00D + 1578, // imageAtomicExchange_00s20C00D + 1580, // imageAtomicExchange_00y20C00D + 1582, // imageAtomicExchange_01E20C00D + 1584, // imageAtomicExchange_00u00C00D + 1586, // imageAtomicExchange_01A00C00D + 1588, // imageAtomicExchange_01G00C00D + 1590, // imageAtomicExchange_00r20C00D + 1592, // imageAtomicExchange_00x20C00D + 1594, // imageAtomicExchange_01D20C00D + 1596, // imageAtomicExchange_00t20C00D + 1598, // imageAtomicExchange_00z20C00D + 1600, // imageAtomicExchange_01F20C00D + 1602, // imageAtomicExchange_00p10C00C + 1604, // imageAtomicExchange_00v10C00C + 1606, // imageAtomicExchange_01B10C00C + 1608, // imageAtomicExchange_00q20C00C + 1610, // imageAtomicExchange_00w20C00C + 1612, // imageAtomicExchange_01C20C00C + 1614, // imageAtomicExchange_00s20C00C + 1616, // imageAtomicExchange_00y20C00C + 1618, // imageAtomicExchange_01E20C00C + 1620, // imageAtomicExchange_00u00C00C + 1622, // imageAtomicExchange_01A00C00C + 1624, // imageAtomicExchange_01G00C00C + 1626, // imageAtomicExchange_00r20C00C + 1628, // imageAtomicExchange_00x20C00C + 1630, // imageAtomicExchange_01D20C00C + 1632, // imageAtomicExchange_00t20C00C + 1634, // imageAtomicExchange_00z20C00C + 1636, // imageAtomicExchange_01F20C00C + 1638, // imageAtomicExchange_00p10C00B + 1640, // imageAtomicExchange_00v10C00B + 1642, // imageAtomicExchange_01B10C00B + 1644, // imageAtomicExchange_00q20C00B + 1646, // imageAtomicExchange_00w20C00B + 1648, // imageAtomicExchange_01C20C00B + 1650, // imageAtomicExchange_00s20C00B + 1652, // imageAtomicExchange_00y20C00B + 1654, // imageAtomicExchange_01E20C00B + 1656, // imageAtomicExchange_00u00C00B + 1658, // imageAtomicExchange_01A00C00B + 1660, // imageAtomicExchange_01G00C00B + 1662, // imageAtomicExchange_00r20C00B + 1664, // imageAtomicExchange_00x20C00B + 1666, // imageAtomicExchange_01D20C00B + 1668, // imageAtomicExchange_00t20C00B + 1670, // imageAtomicExchange_00z20C00B + 1672, // imageAtomicExchange_01F20C00B + 1674, // imageAtomicCompSwap_00p10C00D00D + 1676, // imageAtomicCompSwap_00v10C00D00D + 1678, // imageAtomicCompSwap_01B10C00D00D + 1680, // imageAtomicCompSwap_00q20C00D00D + 1682, // imageAtomicCompSwap_00w20C00D00D + 1684, // imageAtomicCompSwap_01C20C00D00D + 1686, // imageAtomicCompSwap_00s20C00D00D + 1688, // imageAtomicCompSwap_00y20C00D00D + 1690, // imageAtomicCompSwap_01E20C00D00D + 1692, // imageAtomicCompSwap_00u00C00D00D + 1694, // imageAtomicCompSwap_01A00C00D00D + 1696, // imageAtomicCompSwap_01G00C00D00D + 1698, // imageAtomicCompSwap_00r20C00D00D + 1700, // imageAtomicCompSwap_00x20C00D00D + 1702, // imageAtomicCompSwap_01D20C00D00D + 1704, // imageAtomicCompSwap_00t20C00D00D + 1706, // imageAtomicCompSwap_00z20C00D00D + 1708, // imageAtomicCompSwap_01F20C00D00D + 1710, // imageAtomicCompSwap_00p10C00C00C + 1712, // imageAtomicCompSwap_00v10C00C00C + 1714, // imageAtomicCompSwap_01B10C00C00C + 1716, // imageAtomicCompSwap_00q20C00C00C + 1718, // imageAtomicCompSwap_00w20C00C00C + 1720, // imageAtomicCompSwap_01C20C00C00C + 1722, // imageAtomicCompSwap_00s20C00C00C + 1724, // imageAtomicCompSwap_00y20C00C00C + 1726, // imageAtomicCompSwap_01E20C00C00C + 1728, // imageAtomicCompSwap_00u00C00C00C + 1730, // imageAtomicCompSwap_01A00C00C00C + 1732, // imageAtomicCompSwap_01G00C00C00C + 1734, // imageAtomicCompSwap_00r20C00C00C + 1736, // imageAtomicCompSwap_00x20C00C00C + 1738, // imageAtomicCompSwap_01D20C00C00C + 1740, // imageAtomicCompSwap_00t20C00C00C + 1742, // imageAtomicCompSwap_00z20C00C00C + 1744, // imageAtomicCompSwap_01F20C00C00C + 1746, // pixelLocalLoadANGLE_01H + 1747, // pixelLocalLoadANGLE_01I + 1748, // pixelLocalLoadANGLE_01J + 1749, // pixelLocalStoreANGLE_01H30B + 1750, // pixelLocalStoreANGLE_01I30C + 1751, // pixelLocalStoreANGLE_01J30D + 1752, // beginInvocationInterlockNV_ + 1753, // endInvocationInterlockNV_ + 1754, // beginFragmentShaderOrderingINTEL_ + 1755, // beginInvocationInterlockARB_ + 1756, // endInvocationInterlockARB_ + 1757, // memoryBarrier_ + 1758, // memoryBarrierAtomicCounter_ + 1759, // memoryBarrierBuffer_ + 1760, // memoryBarrierImage_ + 1761, // barrier_ + 1765, // memoryBarrierShared_ + 1766, // groupMemoryBarrier_ + 1767, // EmitVertex_ + 1770, // EndPrimitive_ + 1773, // subpassLoad_01K + 1774, // subpassLoad_01L + 1775, // subpassLoad_01M + 1776, // numSamples_ + 1777, // samplePosition_00D + 1778, // interpolateAtCenter_00B + 1779, // interpolateAtCenter_10B + 1780, // interpolateAtCenter_20B + 1781, // interpolateAtCenter_30B + 1782, // loopForwardProgress_ + 1783, // saturate_00B + 1784, // saturate_10B + 1785, // saturate_20B + 1786, // saturate_30B + 1787, // gl_DepthRangeParameters + 1788, // gl_DepthRange + 1789, // gl_NumSamples + 1791, // gl_MaxVertexAttribs + 1792, // gl_MaxVertexUniformVectors + 1793, // gl_MaxVertexTextureImageUnits + 1794, // gl_MaxCombinedTextureImageUnits + 1795, // gl_MaxTextureImageUnits + 1796, // gl_MaxFragmentUniformVectors + 1797, // gl_MaxVaryingVectors + 1798, // gl_MaxDrawBuffers + 1799, // gl_MaxDualSourceDrawBuffersEXT + 1800, // gl_MaxVertexOutputVectors + 1801, // gl_MaxFragmentInputVectors + 1802, // gl_MinProgramTexelOffset + 1803, // gl_MaxProgramTexelOffset + 1804, // gl_MaxImageUnits + 1805, // gl_MaxVertexImageUniforms + 1806, // gl_MaxFragmentImageUniforms + 1807, // gl_MaxComputeImageUniforms + 1808, // gl_MaxCombinedImageUniforms + 1809, // gl_MaxCombinedShaderOutputResources + 1810, // gl_MaxComputeWorkGroupCount + 1811, // gl_MaxComputeWorkGroupSize + 1812, // gl_MaxComputeUniformComponents + 1813, // gl_MaxComputeTextureImageUnits + 1814, // gl_MaxComputeAtomicCounters + 1815, // gl_MaxComputeAtomicCounterBuffers + 1816, // gl_MaxVertexAtomicCounters + 1817, // gl_MaxFragmentAtomicCounters + 1818, // gl_MaxCombinedAtomicCounters + 1819, // gl_MaxAtomicCounterBindings + 1820, // gl_MaxVertexAtomicCounterBuffers + 1821, // gl_MaxFragmentAtomicCounterBuffers + 1822, // gl_MaxCombinedAtomicCounterBuffers + 1823, // gl_MaxAtomicCounterBufferSize + 1824, // gl_ShadingRateFlag2VerticalPixelsEXT + 1825, // gl_ShadingRateFlag4VerticalPixelsEXT + 1826, // gl_ShadingRateFlag2HorizontalPixelsEXT + 1827, // gl_ShadingRateFlag4HorizontalPixelsEXT + 1828, // gl_MaxGeometryInputComponents + 1831, // gl_MaxGeometryOutputComponents + 1834, // gl_MaxGeometryImageUniforms + 1837, // gl_MaxGeometryTextureImageUnits + 1840, // gl_MaxGeometryOutputVertices + 1843, // gl_MaxGeometryTotalOutputComponents + 1846, // gl_MaxGeometryUniformComponents + 1849, // gl_MaxGeometryAtomicCounters + 1852, // gl_MaxGeometryAtomicCounterBuffers + 1855, // gl_MaxTessControlInputComponents + 1858, // gl_MaxTessControlOutputComponents + 1861, // gl_MaxTessControlTextureImageUnits + 1864, // gl_MaxTessControlUniformComponents + 1867, // gl_MaxTessControlTotalOutputComponents + 1870, // gl_MaxTessControlImageUniforms + 1873, // gl_MaxTessControlAtomicCounters + 1876, // gl_MaxTessControlAtomicCounterBuffers + 1879, // gl_MaxTessPatchComponents + 1882, // gl_MaxPatchVertices + 1885, // gl_MaxTessGenLevel + 1888, // gl_MaxTessEvaluationInputComponents + 1891, // gl_MaxTessEvaluationOutputComponents + 1894, // gl_MaxTessEvaluationTextureImageUnits + 1897, // gl_MaxTessEvaluationUniformComponents + 1900, // gl_MaxTessEvaluationImageUniforms + 1903, // gl_MaxTessEvaluationAtomicCounters + 1906, // gl_MaxTessEvaluationAtomicCounterBuffers + 1909, // gl_MaxSamples + 1911, // gl_MaxClipDistances + 1914, // gl_MaxCullDistances + 1916, // gl_MaxCombinedClipAndCullDistances + 1918, // gl_FragCoord + 1920, // gl_FrontFacing + 1921, // gl_PointCoord + 1922, // gl_FragColor + 1923, // gl_FragData + 1924, // gl_FragDepth + 1925, // gl_HelperInvocation + 1926, // gl_SecondaryFragColorEXT + 1927, // gl_SecondaryFragDataEXT + 1928, // gl_FragDepthEXT + 1929, // gl_LastFragData + 1931, // gl_LastFragColorARM + 1932, // gl_LastFragDepthARM + 1933, // gl_LastFragStencilARM + 1934, // gl_PrimitiveID + 1946, // gl_Layer + 1953, // gl_ShadingRateEXT + 1954, // gl_SampleID + 1956, // gl_SamplePosition + 1958, // gl_SampleMaskIn + 1960, // gl_SampleMask + 1962, // gl_Position + 1969, // gl_PointSize + 1971, // gl_InstanceID + 1972, // gl_InstanceIndex + 1973, // gl_VertexID + 1974, // gl_VertexIndex + 1975, // gl_DrawID + 1976, // gl_BaseVertex + 1977, // gl_BaseInstance + 1978, // gl_ClipDistance + 1981, // gl_PrimitiveShadingRateEXT + 1983, // gl_NumWorkGroups + 1984, // gl_WorkGroupSize + 1985, // gl_WorkGroupID + 1986, // gl_LocalInvocationID + 1987, // gl_GlobalInvocationID + 1988, // gl_LocalInvocationIndex + 1989, // gl_PrimitiveIDIn + 1992, // gl_InvocationID + 1998, // gl_PerVertex + 2007, // gl_in + 2016, // gl_PatchVerticesIn + 2022, // gl_TessLevelOuter + 2028, // gl_TessLevelInner + 2034, // gl_out + 2037, // gl_BoundingBox + 2040, // gl_BoundingBoxEXT + 2043, // gl_BoundingBoxOES + 2046, // gl_TessCoord + 2047, // gl_ViewID_OVR + 2048, // gl_CullDistance }; using Ext = TExtension; @@ -26317,6 +22771,8 @@ constexpr UnmangledEntry unmangled[] = { Shader::FRAGMENT}, {"interpolateAtCenter", std::array{{Ext::UNDEFINED}}, kESSLInternalBackendBuiltIns, Shader::FRAGMENT}, + {"loopForwardProgress", std::array{{Ext::UNDEFINED}}, + kESSLInternalBackendBuiltIns, Shader::ALL}, {"saturate", std::array{{Ext::UNDEFINED}}, kESSLInternalBackendBuiltIns, Shader::ALL}}; @@ -26342,7 +22798,7 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, std::array{{TExtension::UNDEFINED}}, fields_gl_DepthRangeParameters); m_gl_DepthRangeParameters = gl_DepthRangeParameters; TType *type_gl_DepthRange = new TType(gl_DepthRangeParameters, false); - type_gl_DepthRange->setQualifier(EvqUniform); + type_gl_DepthRange->setQualifier(EvqDepthRange); type_gl_DepthRange->realize(); m_gl_DepthRange = new TVariable(BuiltInId::gl_DepthRange, BuiltInName::gl_DepthRange, SymbolType::BuiltIn, @@ -26658,6 +23114,50 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, unionArray[0].setIConst(resources.MaxAtomicCounterBufferSize); static_cast(m_gl_MaxAtomicCounterBufferSize)->shareConstPointer(unionArray); } + m_gl_ShadingRateFlag2VerticalPixelsEXT = + new TVariable(BuiltInId::gl_ShadingRateFlag2VerticalPixelsEXT, + BuiltInName::gl_ShadingRateFlag2VerticalPixelsEXT, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.ShadingRateFlag2VerticalPixelsEXT); + static_cast(m_gl_ShadingRateFlag2VerticalPixelsEXT) + ->shareConstPointer(unionArray); + } + m_gl_ShadingRateFlag4VerticalPixelsEXT = + new TVariable(BuiltInId::gl_ShadingRateFlag4VerticalPixelsEXT, + BuiltInName::gl_ShadingRateFlag4VerticalPixelsEXT, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.ShadingRateFlag4VerticalPixelsEXT); + static_cast(m_gl_ShadingRateFlag4VerticalPixelsEXT) + ->shareConstPointer(unionArray); + } + m_gl_ShadingRateFlag2HorizontalPixelsEXT = + new TVariable(BuiltInId::gl_ShadingRateFlag2HorizontalPixelsEXT, + BuiltInName::gl_ShadingRateFlag2HorizontalPixelsEXT, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.ShadingRateFlag2HorizontalPixelsEXT); + static_cast(m_gl_ShadingRateFlag2HorizontalPixelsEXT) + ->shareConstPointer(unionArray); + } + m_gl_ShadingRateFlag4HorizontalPixelsEXT = + new TVariable(BuiltInId::gl_ShadingRateFlag4HorizontalPixelsEXT, + BuiltInName::gl_ShadingRateFlag4HorizontalPixelsEXT, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.ShadingRateFlag4HorizontalPixelsEXT); + static_cast(m_gl_ShadingRateFlag4HorizontalPixelsEXT) + ->shareConstPointer(unionArray); + } m_gl_MaxGeometryInputComponents = new TVariable(BuiltInId::gl_MaxGeometryInputComponents, BuiltInName::gl_MaxGeometryInputComponents, SymbolType::BuiltIn, @@ -27311,7 +23811,7 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, ->shareConstPointer(unionArray); } TType *type_gl_FragData = new TType(EbtFloat, EbpMedium, EvqFragData, 4); - if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC) + if (spec != SH_WEBGL2_SPEC) { type_gl_FragData->makeArray(resources.MaxDrawBuffers); } @@ -27331,12 +23831,6 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, BuiltInId::gl_SecondaryFragDataEXT, BuiltInName::gl_SecondaryFragDataEXT, SymbolType::BuiltIn, std::array{{TExtension::EXT_blend_func_extended}}, type_gl_SecondaryFragDataEXT); - TType *type_gl_FragDepthEXT = - new TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1); - type_gl_FragDepthEXT->realize(); - m_gl_FragDepthEXT = new TVariable( - BuiltInId::gl_FragDepthEXT, BuiltInName::gl_FragDepthEXT, SymbolType::BuiltIn, - std::array{{TExtension::EXT_frag_depth}}, type_gl_FragDepthEXT); TType *type_gl_LastFragData = new TType(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); type_gl_LastFragData->makeArray(resources.MaxDrawBuffers); type_gl_LastFragData->realize(); @@ -27345,13 +23839,6 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, std::array{{TExtension::EXT_shader_framebuffer_fetch, TExtension::EXT_shader_framebuffer_fetch_non_coherent}}, type_gl_LastFragData); - TType *type_gl_LastFragDataNV = new TType(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); - type_gl_LastFragDataNV->makeArray(resources.MaxDrawBuffers); - type_gl_LastFragDataNV->realize(); - m_gl_LastFragDataNV = new TVariable( - BuiltInId::gl_LastFragDataNV, BuiltInName::gl_LastFragData, SymbolType::BuiltIn, - std::array{{TExtension::NV_shader_framebuffer_fetch}}, - type_gl_LastFragDataNV); TType *type_gl_SampleMaskIn = new TType(EbtInt, EbpHigh, EvqSampleMaskIn, 1); type_gl_SampleMaskIn->makeArray((resources.MaxSamples + 31) / 32); type_gl_SampleMaskIn->realize(); @@ -27413,36 +23900,6 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, m_gl_inES3_2 = new TVariable(BuiltInId::gl_inES3_2, BuiltInName::gl_in, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, type_gl_inES3_2); - TFieldList *fields_gl_PerVertexOutBlock = new TFieldList(); - fields_gl_PerVertexOutBlock->push_back( - new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, - zeroSourceLoc, SymbolType::BuiltIn)); - TInterfaceBlock *gl_PerVertexOutBlock = - new TInterfaceBlock(BuiltInId::gl_PerVertexOutBlock, BuiltInName::gl_PerVertex, - std::array{ - {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, - fields_gl_PerVertexOutBlock); - TFieldList *fields_gl_PerVertexOutBlockES3_2 = new TFieldList(); - fields_gl_PerVertexOutBlockES3_2->push_back( - new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, - zeroSourceLoc, SymbolType::BuiltIn)); - TInterfaceBlock *gl_PerVertexOutBlockES3_2 = new TInterfaceBlock( - BuiltInId::gl_PerVertexOutBlockES3_2, BuiltInName::gl_PerVertex, - std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexOutBlockES3_2); - TType *type_gl_PositionGS = new TType(EbtFloat, EbpHigh, EvqPosition, 4); - type_gl_PositionGS->setInterfaceBlock(gl_PerVertexOutBlock); - type_gl_PositionGS->realize(); - m_gl_PositionGS = - new TVariable(BuiltInId::gl_PositionGS, BuiltInName::gl_Position, SymbolType::BuiltIn, - std::array{ - {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, - type_gl_PositionGS); - TType *type_gl_PositionGSES3_2 = new TType(EbtFloat, EbpHigh, EvqPosition, 4); - type_gl_PositionGSES3_2->setInterfaceBlock(gl_PerVertexOutBlockES3_2); - type_gl_PositionGSES3_2->realize(); - m_gl_PositionGSES3_2 = - new TVariable(BuiltInId::gl_PositionGSES3_2, BuiltInName::gl_Position, SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, type_gl_PositionGSES3_2); TType *type_gl_TessLevelOuterTCS = new TType(EbtFloat, EbpHigh, EvqTessLevelOuter, 1); type_gl_TessLevelOuterTCS->makeArray(4u); type_gl_TessLevelOuterTCS->realize(); @@ -27530,36 +23987,6 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, m_gl_BoundingBoxTCSES3_2 = new TVariable( BuiltInId::gl_BoundingBoxTCSES3_2, BuiltInName::gl_BoundingBox, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, type_gl_BoundingBoxTCSES3_2); - TFieldList *fields_gl_PerVertexOutTcsBlock = new TFieldList(); - fields_gl_PerVertexOutTcsBlock->push_back( - new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, - zeroSourceLoc, SymbolType::BuiltIn)); - TInterfaceBlock *gl_PerVertexOutTcsBlock = - new TInterfaceBlock(BuiltInId::gl_PerVertexOutTcsBlock, BuiltInName::gl_PerVertex, - std::array{{TExtension::EXT_tessellation_shader, - TExtension::OES_tessellation_shader}}, - fields_gl_PerVertexOutTcsBlock); - TFieldList *fields_gl_PerVertexOutTcsBlockES3_2 = new TFieldList(); - fields_gl_PerVertexOutTcsBlockES3_2->push_back( - new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, - zeroSourceLoc, SymbolType::BuiltIn)); - TInterfaceBlock *gl_PerVertexOutTcsBlockES3_2 = new TInterfaceBlock( - BuiltInId::gl_PerVertexOutTcsBlockES3_2, BuiltInName::gl_PerVertex, - std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexOutTcsBlockES3_2); - TType *type_gl_PositionTCS = new TType(EbtFloat, EbpHigh, EvqPosition, 4); - type_gl_PositionTCS->setInterfaceBlock(gl_PerVertexOutTcsBlock); - type_gl_PositionTCS->realize(); - m_gl_PositionTCS = - new TVariable(BuiltInId::gl_PositionTCS, BuiltInName::gl_Position, SymbolType::BuiltIn, - std::array{{TExtension::EXT_tessellation_shader, - TExtension::OES_tessellation_shader}}, - type_gl_PositionTCS); - TType *type_gl_PositionTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqPosition, 4); - type_gl_PositionTCSES3_2->setInterfaceBlock(gl_PerVertexOutTcsBlockES3_2); - type_gl_PositionTCSES3_2->realize(); - m_gl_PositionTCSES3_2 = new TVariable( - BuiltInId::gl_PositionTCSES3_2, BuiltInName::gl_Position, SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, type_gl_PositionTCSES3_2); TType *type_gl_BoundingBoxEXTTCS = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); type_gl_BoundingBoxEXTTCS->makeArray(2u); type_gl_BoundingBoxEXTTCS->realize(); @@ -27647,50 +24074,6 @@ void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, m_gl_inTESES3_2 = new TVariable(BuiltInId::gl_inTESES3_2, BuiltInName::gl_in, SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, type_gl_inTESES3_2); - TType *type_gl_outTES = new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); - type_gl_outTES->makeArray(resources.MaxPatchVertices); - type_gl_outTES->realize(); - m_gl_outTES = new TVariable(BuiltInId::gl_outTES, BuiltInName::gl_out, SymbolType::BuiltIn, - std::array{{TExtension::EXT_tessellation_shader, - TExtension::OES_tessellation_shader}}, - type_gl_outTES); - TType *type_gl_outTESES3_2 = - new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); - type_gl_outTESES3_2->makeArray(resources.MaxPatchVertices); - type_gl_outTESES3_2->realize(); - m_gl_outTESES3_2 = - new TVariable(BuiltInId::gl_outTESES3_2, BuiltInName::gl_out, SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, type_gl_outTESES3_2); - TFieldList *fields_gl_PerVertexOutTesBlock = new TFieldList(); - fields_gl_PerVertexOutTesBlock->push_back( - new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, - zeroSourceLoc, SymbolType::BuiltIn)); - TInterfaceBlock *gl_PerVertexOutTesBlock = - new TInterfaceBlock(BuiltInId::gl_PerVertexOutTesBlock, BuiltInName::gl_PerVertex, - std::array{{TExtension::EXT_tessellation_shader, - TExtension::OES_tessellation_shader}}, - fields_gl_PerVertexOutTesBlock); - TFieldList *fields_gl_PerVertexOutTesBlockES3_2 = new TFieldList(); - fields_gl_PerVertexOutTesBlockES3_2->push_back( - new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, - zeroSourceLoc, SymbolType::BuiltIn)); - TInterfaceBlock *gl_PerVertexOutTesBlockES3_2 = new TInterfaceBlock( - BuiltInId::gl_PerVertexOutTesBlockES3_2, BuiltInName::gl_PerVertex, - std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexOutTesBlockES3_2); - TType *type_gl_PositionTES = new TType(EbtFloat, EbpHigh, EvqPosition, 4); - type_gl_PositionTES->setInterfaceBlock(gl_PerVertexOutTesBlock); - type_gl_PositionTES->realize(); - m_gl_PositionTES = - new TVariable(BuiltInId::gl_PositionTES, BuiltInName::gl_Position, SymbolType::BuiltIn, - std::array{{TExtension::EXT_tessellation_shader, - TExtension::OES_tessellation_shader}}, - type_gl_PositionTES); - TType *type_gl_PositionTESES3_2 = new TType(EbtFloat, EbpHigh, EvqPosition, 4); - type_gl_PositionTESES3_2->setInterfaceBlock(gl_PerVertexOutTesBlockES3_2); - type_gl_PositionTESES3_2->realize(); - m_gl_PositionTESES3_2 = new TVariable( - BuiltInId::gl_PositionTESES3_2, BuiltInName::gl_Position, SymbolType::BuiltIn, - std::array{{TExtension::UNDEFINED}}, type_gl_PositionTESES3_2); TType *type_gl_ClipDistance = new TType(EbtFloat, EbpHigh, EvqClipDistance, 1); type_gl_ClipDistance->makeArray(resources.MaxClipDistances); type_gl_ClipDistance->realize(); @@ -27713,7 +24096,7 @@ namespace { uint16_t GetNextRuleIndex(uint32_t nameHash) { - if (nameHash == 1578 - 1) + if (nameHash == 1426 - 1) return ArraySize(BuiltInArray::kRules); return BuiltInArray::kMangledOffsets[nameHash + 1]; } @@ -27725,7 +24108,7 @@ const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name, int shader return nullptr; uint32_t nameHash = name.mangledNameHash(); - if (nameHash >= 1578) + if (nameHash >= 1426) return nullptr; const char *actualName = BuiltInArray::kMangledNames[nameHash]; @@ -27747,7 +24130,7 @@ bool TSymbolTable::isUnmangledBuiltInName(const ImmutableString &name, return false; uint32_t nameHash = name.unmangledNameHash(); - if (nameHash >= 179) + if (nameHash >= 180) return false; return BuiltInArray::unmangled[nameHash].matches(name, mShaderSpec, shaderVersion, mShaderType, diff --git a/src/compiler/translator/SymbolTable_autogen.h b/src/compiler/translator/SymbolTable_autogen.h index dba53c09052..6705263f271 100644 --- a/src/compiler/translator/SymbolTable_autogen.h +++ b/src/compiler/translator/SymbolTable_autogen.h @@ -54,6 +54,10 @@ class TSymbolTableBase TSymbol *m_gl_MaxFragmentAtomicCounterBuffers = nullptr; TSymbol *m_gl_MaxCombinedAtomicCounterBuffers = nullptr; TSymbol *m_gl_MaxAtomicCounterBufferSize = nullptr; + TSymbol *m_gl_ShadingRateFlag2VerticalPixelsEXT = nullptr; + TSymbol *m_gl_ShadingRateFlag4VerticalPixelsEXT = nullptr; + TSymbol *m_gl_ShadingRateFlag2HorizontalPixelsEXT = nullptr; + TSymbol *m_gl_ShadingRateFlag4HorizontalPixelsEXT = nullptr; TSymbol *m_gl_MaxGeometryInputComponents = nullptr; TSymbol *m_gl_MaxGeometryInputComponentsES3_2 = nullptr; TSymbol *m_gl_MaxGeometryOutputComponents = nullptr; @@ -116,9 +120,7 @@ class TSymbolTableBase TSymbol *m_gl_MaxCombinedClipAndCullDistances = nullptr; TSymbol *m_gl_FragData = nullptr; TSymbol *m_gl_SecondaryFragDataEXT = nullptr; - TSymbol *m_gl_FragDepthEXT = nullptr; TSymbol *m_gl_LastFragData = nullptr; - TSymbol *m_gl_LastFragDataNV = nullptr; TSymbol *m_gl_SampleMaskIn = nullptr; TSymbol *m_gl_SampleMaskInES3_2 = nullptr; TSymbol *m_gl_SampleMask = nullptr; @@ -128,8 +130,6 @@ class TSymbolTableBase TSymbol *m_gl_PerVertexES3_2 = nullptr; TSymbol *m_gl_in = nullptr; TSymbol *m_gl_inES3_2 = nullptr; - TSymbol *m_gl_PositionGS = nullptr; - TSymbol *m_gl_PositionGSES3_2 = nullptr; TSymbol *m_gl_TessLevelOuterTCS = nullptr; TSymbol *m_gl_TessLevelOuterTCSES3_2 = nullptr; TSymbol *m_gl_TessLevelInnerTCS = nullptr; @@ -142,8 +142,6 @@ class TSymbolTableBase TSymbol *m_gl_outTCSES3_2 = nullptr; TSymbol *m_gl_BoundingBoxTCS = nullptr; TSymbol *m_gl_BoundingBoxTCSES3_2 = nullptr; - TSymbol *m_gl_PositionTCS = nullptr; - TSymbol *m_gl_PositionTCSES3_2 = nullptr; TSymbol *m_gl_BoundingBoxEXTTCS = nullptr; TSymbol *m_gl_BoundingBoxEXTTCSES3_2 = nullptr; TSymbol *m_gl_BoundingBoxOESTCS = nullptr; @@ -156,10 +154,6 @@ class TSymbolTableBase TSymbol *m_gl_PerVertexTESES3_2 = nullptr; TSymbol *m_gl_inTES = nullptr; TSymbol *m_gl_inTESES3_2 = nullptr; - TSymbol *m_gl_outTES = nullptr; - TSymbol *m_gl_outTESES3_2 = nullptr; - TSymbol *m_gl_PositionTES = nullptr; - TSymbol *m_gl_PositionTESES3_2 = nullptr; TSymbol *m_gl_ClipDistance = nullptr; TSymbol *m_gl_CullDistance = nullptr; }; diff --git a/src/compiler/translator/SymbolUniqueId.cpp b/src/compiler/translator/SymbolUniqueId.cpp index 94278a00425..7347128672e 100644 --- a/src/compiler/translator/SymbolUniqueId.cpp +++ b/src/compiler/translator/SymbolUniqueId.cpp @@ -17,16 +17,4 @@ TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->n TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.uniqueId().get()) {} -TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default; - -bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const -{ - return mId == other.mId; -} - -bool TSymbolUniqueId::operator!=(const TSymbolUniqueId &other) const -{ - return !(*this == other); -} - } // namespace sh diff --git a/src/compiler/translator/SymbolUniqueId.h b/src/compiler/translator/SymbolUniqueId.h index 6f8ecef1ed2..f803b459498 100644 --- a/src/compiler/translator/SymbolUniqueId.h +++ b/src/compiler/translator/SymbolUniqueId.h @@ -22,12 +22,15 @@ class TSymbolUniqueId POOL_ALLOCATOR_NEW_DELETE explicit TSymbolUniqueId(const TSymbol &symbol); constexpr TSymbolUniqueId(const TSymbolUniqueId &) = default; - TSymbolUniqueId &operator=(const TSymbolUniqueId &); - bool operator==(const TSymbolUniqueId &) const; - bool operator!=(const TSymbolUniqueId &) const; + TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default; + bool operator==(const TSymbolUniqueId &other) const { return mId == other.mId; } + bool operator!=(const TSymbolUniqueId &other) const { return !(*this == other); } + bool operator<(const TSymbolUniqueId &other) const { return get() < other.get(); } constexpr int get() const { return mId; } + static constexpr TSymbolUniqueId kInvalid() { return TSymbolUniqueId(-1); } + private: friend class TSymbolTable; explicit TSymbolUniqueId(TSymbolTable *symbolTable); @@ -56,4 +59,13 @@ enum class SymbolClass : uint8_t } // namespace sh +namespace std +{ +template <> +struct hash +{ + size_t operator()(const sh::TSymbolUniqueId &key) const { return key.get(); } +}; +} // namespace std + #endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp index 58c799eccdf..c0882da9b13 100644 --- a/src/compiler/translator/Types.cpp +++ b/src/compiler/translator/Types.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #if defined(_MSC_VER) # pragma warning(disable : 4718) #endif @@ -391,11 +395,6 @@ int TType::getDeepestStructNesting() const return mStructure ? mStructure->deepestNesting() : 0; } -bool TType::isNamelessStruct() const -{ - return mStructure && mStructure->symbolType() == SymbolType::Empty; -} - bool TType::isStructureContainingArrays() const { return mStructure ? mStructure->containsArrays() : false; @@ -416,6 +415,11 @@ bool TType::isStructureContainingSamplers() const return mStructure ? mStructure->containsSamplers() : false; } +bool TType::isStructureContainingOnlySamplers() const +{ + return mStructure ? mStructure->containsOnlySamplers() : false; +} + bool TType::isInterfaceBlockContainingType(TBasicType t) const { return isInterfaceBlock() ? mInterfaceBlock->containsType(t) : false; @@ -839,6 +843,20 @@ bool TFieldListCollection::containsSamplers() const return false; } +bool TFieldListCollection::containsOnlySamplers() const +{ + for (const auto *field : *mFields) + { + const TType *fieldType = field->type(); + if (!IsSampler(fieldType->getBasicType()) && + !fieldType->isStructureContainingOnlySamplers()) + { + return false; + } + } + return true; +} + TString TFieldListCollection::buildMangledFieldList() const { TString mangledName; diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h index c312bcbb095..105d99c4692 100644 --- a/src/compiler/translator/Types.h +++ b/src/compiler/translator/Types.h @@ -15,6 +15,7 @@ #include "compiler/translator/Common.h" #include "compiler/translator/ImmutableString.h" #include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/ir/src/builder.h" namespace sh { @@ -64,6 +65,7 @@ class TFieldListCollection : angle::NonCopyable bool containsMatrices() const; bool containsType(TBasicType t) const; bool containsSamplers() const; + bool containsOnlySamplers() const; size_t objectSize() const; // How many locations the field list consumes as a uniform. @@ -170,11 +172,11 @@ class TType bool isInterpolant() const { return interpolant; } void setInterpolant(bool i) { interpolant = i; } - TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } + const TMemoryQualifier &getMemoryQualifier() const { return memoryQualifier; } void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } - TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } - void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } + const TLayoutQualifier &getLayoutQualifier() const { return layoutQualifier; } + void setLayoutQualifier(const TLayoutQualifier &lq) { layoutQualifier = lq; } uint8_t getNominalSize() const { return primarySize; } uint8_t getSecondarySize() const { return secondarySize; } @@ -252,6 +254,7 @@ class TType { return primarySize == 1 && secondarySize == 1 && !mStructure && isArray(); } + bool isScalarBool() const { return isScalar() && type == EbtBool; } bool isScalarFloat() const { return isScalar() && type == EbtFloat; } bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } @@ -331,12 +334,11 @@ class TType // deepest field (nesting2.field1.position). int getDeepestStructNesting() const; - bool isNamelessStruct() const; - bool isStructureContainingArrays() const; bool isStructureContainingMatrices() const; bool isStructureContainingType(TBasicType t) const; bool isStructureContainingSamplers() const; + bool isStructureContainingOnlySamplers() const; bool isInterfaceBlockContainingType(TBasicType t) const; bool isStructSpecifier() const { return mIsStructSpecifier; } @@ -364,6 +366,10 @@ class TType bool isImage() const { return IsImage(type); } bool isPixelLocal() const { return IsPixelLocal(type); } + void setTypeId(ir::TypeId typeId) { mTypeId = typeId; } + ir::TypeId typeId() const { return mTypeId; } + bool isTypeIdSet() const { return ir::IsTypeIdValid(mTypeId); } + private: constexpr void invalidateMangledName() { mMangledName = nullptr; } const char *buildMangledName() const; @@ -409,6 +415,8 @@ class TType size_t mInterfaceBlockFieldIndex; mutable const char *mMangledName; + + ir::TypeId mTypeId = ir::kInvalidTypeId; }; // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the @@ -461,7 +469,7 @@ struct TTypeSpecifierNonArray bool isVector() const { return primarySize > 1 && secondarySize == 1; } }; -// Type represeting parsed type specifire on a struct or variable declaration or +// Type representing parsed type specifier on a struct or variable declaration or // parameter declaration. // Note: must be trivially constructible. struct TPublicType diff --git a/src/compiler/translator/ValidateAST.cpp b/src/compiler/translator/ValidateAST.cpp index fcd0d7eff73..b94b549164f 100644 --- a/src/compiler/translator/ValidateAST.cpp +++ b/src/compiler/translator/ValidateAST.cpp @@ -89,7 +89,7 @@ class ValidateAST : public TIntermTraverser // For validateVariableReferences: std::vector> mDeclaredVariables; std::set mNamelessInterfaceBlocks; - std::map mReferencedBuiltIns; + std::map mReferencedBuiltIns; bool mVariableReferencesFailed = false; // For validateOps: @@ -623,11 +623,11 @@ void ValidateAST::visitBuiltInVariable(TIntermSymbol *node) auto iter = mReferencedBuiltIns.find(name); if (iter == mReferencedBuiltIns.end()) { - mReferencedBuiltIns[name] = variable; + mReferencedBuiltIns.emplace(name, variable->uniqueId()); return; } - if (variable != iter->second) + if (variable->uniqueId() != iter->second) { mDiagnostics->error( node->getLine(), @@ -644,10 +644,13 @@ void ValidateAST::visitBuiltInVariable(TIntermSymbol *node) if ((name == "gl_ClipDistance" && qualifier != EvqClipDistance) || (name == "gl_CullDistance" && qualifier != EvqCullDistance) || (name == "gl_FragDepth" && qualifier != EvqFragDepth) || + (name == "gl_FragDepthEXT" && qualifier != EvqFragDepth) || (name == "gl_LastFragData" && qualifier != EvqLastFragData) || (name == "gl_LastFragColorARM" && qualifier != EvqLastFragColor) || (name == "gl_LastFragDepthARM" && qualifier != EvqLastFragDepth) || - (name == "gl_LastFragStencilARM" && qualifier != EvqLastFragStencil)) + (name == "gl_LastFragStencilARM" && qualifier != EvqLastFragStencil) || + (name == "gl_DepthRange" && qualifier != EvqDepthRange) || + (name == "gl_NumSamples" && qualifier != EvqNumSamples)) { mDiagnostics->error( node->getLine(), @@ -777,7 +780,8 @@ void ValidateAST::visitSymbol(TIntermSymbol *node) visitVariableNeedingDeclaration(node); } } - if (variable->symbolType() == SymbolType::Empty) + if (variable->symbolType() == SymbolType::Empty && + variable->getType().getInterfaceBlock() == nullptr) { if (!isInDeclaration()) { diff --git a/src/compiler/translator/ValidateAST.h b/src/compiler/translator/ValidateAST.h index c14ebc57e60..ee10006be0c 100644 --- a/src/compiler/translator/ValidateAST.h +++ b/src/compiler/translator/ValidateAST.h @@ -93,10 +93,10 @@ struct ValidateASTOptions // - Case expressions have the same type as the switch selector bool validateExpressionTypes = true; // If SeparateDeclarations has been run, check for the absence of multi declarations as well. - bool validateMultiDeclarations = false; + bool validateMultiDeclarations = true; // If PruneNoOps has been run, check that no statements are ever added after branches in the // same block. Those statements would be dead code. - bool validateNoStatementsAfterBranch = false; + bool validateNoStatementsAfterBranch = true; // Check that swizzle is not applied to swizzle. Swizzles of swizzles are folded in // TIntermSwizzle::fold. bool validateNoSwizzleOfSwizzle = true; diff --git a/src/compiler/translator/ValidateBarrierFunctionCall.cpp b/src/compiler/translator/ValidateBarrierFunctionCall.cpp deleted file mode 100644 index 46527fc3901..00000000000 --- a/src/compiler/translator/ValidateBarrierFunctionCall.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// Copyright 2020 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. -// -// ValidateBarrierFunctionCalls: -// Runs compilation checks related to the "barrier built-in function. - -#include "compiler/translator/ValidateBarrierFunctionCall.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ -namespace -{ -class Traverser : public TIntermTraverser -{ - public: - Traverser(TDiagnostics *diagnostics) - : TIntermTraverser(true, false, true), mDiagnostics(diagnostics) - {} - - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override - { - if (!node->getFunction()->isMain()) - { - return false; - } - - mInMain = visit == PreVisit; - return true; - } - - bool visitBranch(Visit visit, TIntermBranch *branch) override - { - if (branch->getFlowOp() == EOpReturn) - { - mSeenReturn = true; - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (node->getOp() != EOpBarrierTCS) - { - return true; - } - - if (mSeenReturn) - { - mDiagnostics->error(node->getLine(), - "barrier() may not be called at any point after a return statement " - "in the function main().", - "barrier"); - mValid = false; - return false; - } - - // TODO(anglebug.com/42264094): Determine if we should check loops as well. - if (mBranchCount > 0) - { - mDiagnostics->error( - node->getLine(), - "barrier() may not be called in potentially divergent flow control.", "barrier"); - mValid = false; - return false; - } - - return true; - } - - bool visitIfElse(Visit visit, TIntermIfElse *node) override - { - mBranchCount += ((visit == PreVisit) ? 1 : -1); - return true; - } - - bool valid() const { return mValid; } - - private: - TDiagnostics *mDiagnostics = nullptr; - bool mInMain = false; - bool mSeenReturn = false; - bool mValid = true; - uint32_t mBranchCount = 0; -}; -} // anonymous namespace - -bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics) -{ - Traverser traverser(diagnostics); - root->traverse(&traverser); - return traverser.valid(); -} -} // namespace sh diff --git a/src/compiler/translator/ValidateBarrierFunctionCall.h b/src/compiler/translator/ValidateBarrierFunctionCall.h deleted file mode 100644 index 6b91eb456a5..00000000000 --- a/src/compiler/translator/ValidateBarrierFunctionCall.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright 2020 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. -// -// ValidateBarrierFunctionCalls: -// Runs compilation checks related to the "barrier built-in function. - -#ifndef COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_ -#define COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_ - -#include "common/angleutils.h" - -namespace sh -{ -class TDiagnostics; -class TIntermBlock; - -[[nodiscard]] bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_ diff --git a/src/compiler/translator/ValidateClipCullDistance.cpp b/src/compiler/translator/ValidateClipCullDistance.cpp deleted file mode 100644 index 963fe2ecf0f..00000000000 --- a/src/compiler/translator/ValidateClipCullDistance.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// -// Copyright 2020 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. -// -// The ValidateClipCullDistance function: -// * gathers clip/cull distance usages -// * checks if the sum of array sizes for gl_ClipDistance and -// gl_CullDistance exceeds gl_MaxCombinedClipAndCullDistances -// * checks if length() operator is used correctly -// * adds an explicit clip/cull distance declaration -// - -#include "ValidateClipCullDistance.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/tree_util/ReplaceVariable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); -} - -class ValidateClipCullDistanceTraverser : public TIntermTraverser -{ - public: - ValidateClipCullDistanceTraverser(); - void validate(TDiagnostics *diagnostics, - const unsigned int maxCombinedClipAndCullDistances, - uint8_t *clipDistanceSizeOut, - uint8_t *cullDistanceSizeOut, - bool *clipDistanceRedeclaredOut, - bool *cullDistanceRedeclaredOut, - bool *clipDistanceUsedOut); - - private: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - - uint8_t mClipDistanceSize; - uint8_t mCullDistanceSize; - - int8_t mMaxClipDistanceIndex; - int8_t mMaxCullDistanceIndex; - - bool mHasNonConstClipDistanceIndex; - bool mHasNonConstCullDistanceIndex; - - const TIntermSymbol *mClipDistance; - const TIntermSymbol *mCullDistance; -}; - -ValidateClipCullDistanceTraverser::ValidateClipCullDistanceTraverser() - : TIntermTraverser(true, false, false), - mClipDistanceSize(0), - mCullDistanceSize(0), - mMaxClipDistanceIndex(-1), - mMaxCullDistanceIndex(-1), - mHasNonConstClipDistanceIndex(false), - mHasNonConstCullDistanceIndex(false), - mClipDistance(nullptr), - mCullDistance(nullptr) -{} - -bool ValidateClipCullDistanceTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - - if (sequence.size() != 1) - { - return true; - } - - const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); - if (symbol == nullptr) - { - return true; - } - - if (symbol->getName() == "gl_ClipDistance") - { - mClipDistanceSize = static_cast(symbol->getOutermostArraySize()); - mClipDistance = symbol; - } - else if (symbol->getName() == "gl_CullDistance") - { - mCullDistanceSize = static_cast(symbol->getOutermostArraySize()); - mCullDistance = symbol; - } - - return true; -} - -bool ValidateClipCullDistanceTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - TOperator op = node->getOp(); - if (op != EOpIndexDirect && op != EOpIndexIndirect) - { - return true; - } - - TIntermSymbol *left = node->getLeft()->getAsSymbolNode(); - if (!left) - { - return true; - } - - ImmutableString varName(left->getName()); - if (varName != "gl_ClipDistance" && varName != "gl_CullDistance") - { - return true; - } - - const TConstantUnion *constIdx = node->getRight()->getConstantValue(); - if (constIdx) - { - int idx = 0; - switch (constIdx->getType()) - { - case EbtInt: - idx = constIdx->getIConst(); - break; - case EbtUInt: - idx = constIdx->getUConst(); - break; - default: - UNREACHABLE(); - break; - } - - if (varName == "gl_ClipDistance") - { - if (idx > mMaxClipDistanceIndex) - { - mMaxClipDistanceIndex = static_cast(idx); - if (!mClipDistance) - { - mClipDistance = left; - } - } - } - else - { - ASSERT(varName == "gl_CullDistance"); - if (idx > mMaxCullDistanceIndex) - { - mMaxCullDistanceIndex = static_cast(idx); - if (!mCullDistance) - { - mCullDistance = left; - } - } - } - } - else - { - if (varName == "gl_ClipDistance") - { - mHasNonConstClipDistanceIndex = true; - if (!mClipDistance) - { - mClipDistance = left; - } - } - else - { - ASSERT(varName == "gl_CullDistance"); - mHasNonConstCullDistanceIndex = true; - if (!mCullDistance) - { - mCullDistance = left; - } - } - } - - return true; -} - -void ValidateClipCullDistanceTraverser::validate(TDiagnostics *diagnostics, - const unsigned int maxCombinedClipAndCullDistances, - uint8_t *clipDistanceSizeOut, - uint8_t *cullDistanceSizeOut, - bool *clipDistanceRedeclaredOut, - bool *cullDistanceRedeclaredOut, - bool *clipDistanceUsedOut) -{ - ASSERT(diagnostics); - - if (mClipDistanceSize == 0 && mHasNonConstClipDistanceIndex) - { - error(*mClipDistance, - "The array must be sized by the shader either redeclaring it with a size or " - "indexing it only with constant integral expressions", - diagnostics); - } - - if (mCullDistanceSize == 0 && mHasNonConstCullDistanceIndex) - { - error(*mCullDistance, - "The array must be sized by the shader either redeclaring it with a size or " - "indexing it only with constant integral expressions", - diagnostics); - } - - unsigned int enabledClipDistances = - (mClipDistanceSize > 0 ? mClipDistanceSize - : (mClipDistance ? mMaxClipDistanceIndex + 1 : 0)); - unsigned int enabledCullDistances = - (mCullDistanceSize > 0 ? mCullDistanceSize - : (mCullDistance ? mMaxCullDistanceIndex + 1 : 0)); - unsigned int combinedClipAndCullDistances = - (enabledClipDistances > 0 && enabledCullDistances > 0 - ? enabledClipDistances + enabledCullDistances - : 0); - - // When cull distances are not supported, i.e., when GL_ANGLE_clip_cull_distance is - // exposed but GL_EXT_clip_cull_distance is not exposed, the combined limit is 0. - if (enabledCullDistances > 0 && maxCombinedClipAndCullDistances == 0) - { - error(*mCullDistance, "Cull distance functionality is not available", diagnostics); - } - - if (combinedClipAndCullDistances > maxCombinedClipAndCullDistances) - { - const TIntermSymbol *greaterSymbol = - (enabledClipDistances >= enabledCullDistances ? mClipDistance : mCullDistance); - - std::stringstream strstr = sh::InitializeStream(); - strstr << "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " - "gl_MaxCombinedClipAndCullDistances (" - << combinedClipAndCullDistances << " > " << maxCombinedClipAndCullDistances << ")"; - error(*greaterSymbol, strstr.str().c_str(), diagnostics); - } - - // Update the compiler state - *clipDistanceSizeOut = mClipDistanceSize ? mClipDistanceSize : (mMaxClipDistanceIndex + 1); - *cullDistanceSizeOut = mCullDistanceSize ? mCullDistanceSize : (mMaxCullDistanceIndex + 1); - *clipDistanceRedeclaredOut = mClipDistanceSize != 0; - *cullDistanceRedeclaredOut = mCullDistanceSize != 0; - *clipDistanceUsedOut = (mMaxClipDistanceIndex != -1) || mHasNonConstClipDistanceIndex; -} - -class ValidateClipCullDistanceLengthTraverser : public TIntermTraverser -{ - public: - ValidateClipCullDistanceLengthTraverser(TDiagnostics *diagnostics, - uint8_t clipDistanceSized, - uint8_t cullDistanceSized); - - private: - bool visitUnary(Visit visit, TIntermUnary *node) override; - - TDiagnostics *mDiagnostics; - const bool mClipDistanceSized; - const bool mCullDistanceSized; -}; - -ValidateClipCullDistanceLengthTraverser::ValidateClipCullDistanceLengthTraverser( - TDiagnostics *diagnostics, - uint8_t clipDistanceSize, - uint8_t cullDistanceSize) - : TIntermTraverser(true, false, false), - mDiagnostics(diagnostics), - mClipDistanceSized(clipDistanceSize > 0), - mCullDistanceSized(cullDistanceSize > 0) -{} - -bool ValidateClipCullDistanceLengthTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (node->getOp() == EOpArrayLength) - { - TIntermTyped *operand = node->getOperand(); - if ((operand->getQualifier() == EvqClipDistance && !mClipDistanceSized) || - (operand->getQualifier() == EvqCullDistance && !mCullDistanceSized)) - { - error(*operand->getAsSymbolNode(), - "The length() method cannot be called on an array that is not " - "runtime sized and also has not yet been explicitly sized", - mDiagnostics); - } - } - return true; -} - -bool ReplaceAndDeclareVariable(TCompiler *compiler, - TIntermBlock *root, - const ImmutableString &name, - unsigned int size) -{ - const TVariable *var = static_cast( - compiler->getSymbolTable().findBuiltIn(name, compiler->getShaderVersion())); - ASSERT(var != nullptr); - - if (size != var->getType().getOutermostArraySize()) - { - TType *resizedType = new TType(var->getType()); - resizedType->setArraySize(0, size); - TVariable *resizedVar = - new TVariable(&compiler->getSymbolTable(), name, resizedType, SymbolType::BuiltIn); - if (!ReplaceVariable(compiler, root, var, resizedVar)) - { - return false; - } - var = resizedVar; - } - - TIntermDeclaration *globalDecl = new TIntermDeclaration(); - globalDecl->appendDeclarator(new TIntermSymbol(var)); - root->insertStatement(0, globalDecl); - - return true; -} - -} // anonymous namespace - -bool ValidateClipCullDistance(TCompiler *compiler, - TIntermBlock *root, - TDiagnostics *diagnostics, - const unsigned int maxCombinedClipAndCullDistances, - uint8_t *clipDistanceSizeOut, - uint8_t *cullDistanceSizeOut, - bool *clipDistanceUsedOut) -{ - ValidateClipCullDistanceTraverser varyingValidator; - root->traverse(&varyingValidator); - int numErrorsBefore = diagnostics->numErrors(); - bool clipDistanceRedeclared; - bool cullDistanceRedeclared; - varyingValidator.validate(diagnostics, maxCombinedClipAndCullDistances, clipDistanceSizeOut, - cullDistanceSizeOut, &clipDistanceRedeclared, &cullDistanceRedeclared, - clipDistanceUsedOut); - - ValidateClipCullDistanceLengthTraverser lengthValidator(diagnostics, *clipDistanceSizeOut, - *cullDistanceSizeOut); - root->traverse(&lengthValidator); - if (diagnostics->numErrors() != numErrorsBefore) - { - return false; - } - - // If the clip/cull distance variables are not explicitly redeclared in the incoming shader, - // redeclare them to ensure that various pruning passes will not cause inconsistent AST state. - if (*clipDistanceSizeOut > 0 && !clipDistanceRedeclared && - !ReplaceAndDeclareVariable(compiler, root, ImmutableString("gl_ClipDistance"), - *clipDistanceSizeOut)) - { - - return false; - } - if (*cullDistanceSizeOut > 0 && !cullDistanceRedeclared && - !ReplaceAndDeclareVariable(compiler, root, ImmutableString("gl_CullDistance"), - *cullDistanceSizeOut)) - { - return false; - } - - return true; -} - -} // namespace sh diff --git a/src/compiler/translator/ValidateClipCullDistance.h b/src/compiler/translator/ValidateClipCullDistance.h deleted file mode 100644 index 86a70395cd7..00000000000 --- a/src/compiler/translator/ValidateClipCullDistance.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2020 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. -// -// The ValidateClipCullDistance function checks if the sum of array sizes for gl_ClipDistance and -// gl_CullDistance exceeds gl_MaxCombinedClipAndCullDistances -// - -#ifndef COMPILER_TRANSLATOR_VALIDATECLIPCULLDISTANCE_H_ -#define COMPILER_TRANSLATOR_VALIDATECLIPCULLDISTANCE_H_ - -#include "GLSLANG/ShaderVars.h" -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TIntermBlock; -class TDiagnostics; - -bool ValidateClipCullDistance(TCompiler *compiler, - TIntermBlock *root, - TDiagnostics *diagnostics, - const unsigned int maxCombinedClipAndCullDistances, - uint8_t *clipDistanceSizeOut, - uint8_t *cullDistanceSizeOut, - bool *clipDistanceUsedOut); - -} // namespace sh - -#endif diff --git a/src/compiler/translator/ValidateLimitations.cpp b/src/compiler/translator/ValidateLimitations.cpp deleted file mode 100644 index 866736bd2ab..00000000000 --- a/src/compiler/translator/ValidateLimitations.cpp +++ /dev/null @@ -1,448 +0,0 @@ -// -// Copyright 2002 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. -// - -#include "compiler/translator/ValidateLimitations.h" - -#include "angle_gl.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/ParseContext.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -int GetLoopSymbolId(TIntermLoop *loop) -{ - // Here we assume all the operations are valid, because the loop node is - // already validated before this call. - TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence(); - TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); - TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); - - return symbol->uniqueId().get(); -} - -// Traverses a node to check if it represents a constant index expression. -// Definition: -// constant-index-expressions are a superset of constant-expressions. -// Constant-index-expressions can include loop indices as defined in -// GLSL ES 1.0 spec, Appendix A, section 4. -// The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above -class ValidateConstIndexExpr : public TIntermTraverser -{ - public: - ValidateConstIndexExpr(const std::vector &loopSymbols) - : TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols) - {} - - // Returns true if the parsed node represents a constant index expression. - bool isValid() const { return mValid; } - - void visitSymbol(TIntermSymbol *symbol) override - { - // Only constants and loop indices are allowed in a - // constant index expression. - if (mValid) - { - bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), - symbol->uniqueId().get()) != mLoopSymbolIds.end(); - mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol; - } - } - - private: - bool mValid; - const std::vector mLoopSymbolIds; -}; - -// Traverses intermediate tree to ensure that the shader does not exceed the -// minimum functionality mandated in GLSL 1.0 spec, Appendix A. -class ValidateLimitationsTraverser : public TLValueTrackingTraverser -{ - public: - ValidateLimitationsTraverser(sh::GLenum shaderType, - TSymbolTable *symbolTable, - TDiagnostics *diagnostics); - - void visitSymbol(TIntermSymbol *node) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitLoop(Visit, TIntermLoop *) override; - - private: - void error(TSourceLoc loc, const char *reason, const char *token); - void error(TSourceLoc loc, const char *reason, const ImmutableString &token); - - bool isLoopIndex(TIntermSymbol *symbol); - bool validateLoopType(TIntermLoop *node); - - bool validateForLoopHeader(TIntermLoop *node); - // If valid, return the index symbol id; Otherwise, return -1. - int validateForLoopInit(TIntermLoop *node); - bool validateForLoopCond(TIntermLoop *node, int indexSymbolId); - bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId); - - // Returns true if indexing does not exceed the minimum functionality - // mandated in GLSL 1.0 spec, Appendix A, Section 5. - bool isConstExpr(TIntermNode *node); - bool isConstIndexExpr(TIntermNode *node); - bool validateIndexing(TIntermBinary *node); - - sh::GLenum mShaderType; - TDiagnostics *mDiagnostics; - std::vector mLoopSymbolIds; -}; - -ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType, - TSymbolTable *symbolTable, - TDiagnostics *diagnostics) - : TLValueTrackingTraverser(true, false, false, symbolTable), - mShaderType(shaderType), - mDiagnostics(diagnostics) -{ - ASSERT(diagnostics); -} - -void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node) -{ - if (isLoopIndex(node) && isLValueRequiredHere()) - { - error(node->getLine(), - "Loop index cannot be statically assigned to within the body of the loop", - node->getName()); - } -} - -bool ValidateLimitationsTraverser::visitBinary(Visit, TIntermBinary *node) -{ - // Check indexing. - switch (node->getOp()) - { - case EOpIndexDirect: - case EOpIndexIndirect: - validateIndexing(node); - break; - default: - break; - } - return true; -} - -bool ValidateLimitationsTraverser::visitLoop(Visit, TIntermLoop *node) -{ - if (!validateLoopType(node)) - return false; - - if (!validateForLoopHeader(node)) - return false; - - mLoopSymbolIds.push_back(GetLoopSymbolId(node)); - node->getBody()->traverse(this); - mLoopSymbolIds.pop_back(); - - // The loop is fully processed - no need to visit children. - return false; -} - -void ValidateLimitationsTraverser::error(TSourceLoc loc, const char *reason, const char *token) -{ - mDiagnostics->error(loc, reason, token); -} - -void ValidateLimitationsTraverser::error(TSourceLoc loc, - const char *reason, - const ImmutableString &token) -{ - error(loc, reason, token.data()); -} - -bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol) -{ - return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->uniqueId().get()) != - mLoopSymbolIds.end(); -} - -bool ValidateLimitationsTraverser::validateLoopType(TIntermLoop *node) -{ - TLoopType type = node->getType(); - if (type == ELoopFor) - return true; - - // Reject while and do-while loops. - error(node->getLine(), "This type of loop is not allowed", type == ELoopWhile ? "while" : "do"); - return false; -} - -bool ValidateLimitationsTraverser::validateForLoopHeader(TIntermLoop *node) -{ - ASSERT(node->getType() == ELoopFor); - - // - // The for statement has the form: - // for ( init-declaration ; condition ; expression ) statement - // - int indexSymbolId = validateForLoopInit(node); - if (indexSymbolId < 0) - return false; - if (!validateForLoopCond(node, indexSymbolId)) - return false; - if (!validateForLoopExpr(node, indexSymbolId)) - return false; - - return true; -} - -int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node) -{ - TIntermNode *init = node->getInit(); - if (init == nullptr) - { - error(node->getLine(), "Missing init declaration", "for"); - return -1; - } - - // - // init-declaration has the form: - // type-specifier identifier = constant-expression - // - TIntermDeclaration *decl = init->getAsDeclarationNode(); - if (decl == nullptr) - { - error(init->getLine(), "Invalid init declaration", "for"); - return -1; - } - // To keep things simple do not allow declaration list. - TIntermSequence *declSeq = decl->getSequence(); - if (declSeq->size() != 1) - { - error(decl->getLine(), "Invalid init declaration", "for"); - return -1; - } - TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); - if ((declInit == nullptr) || (declInit->getOp() != EOpInitialize)) - { - error(decl->getLine(), "Invalid init declaration", "for"); - return -1; - } - TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == nullptr) - { - error(declInit->getLine(), "Invalid init declaration", "for"); - return -1; - } - // The loop index has type int or float. - TBasicType type = symbol->getBasicType(); - if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat)) - { - error(symbol->getLine(), "Invalid type for loop index", getBasicString(type)); - return -1; - } - // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) - { - error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression", - symbol->getName()); - return -1; - } - - return symbol->uniqueId().get(); -} - -bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int indexSymbolId) -{ - TIntermNode *cond = node->getCondition(); - if (cond == nullptr) - { - error(node->getLine(), "Missing condition", "for"); - return false; - } - // - // condition has the form: - // loop_index relational_operator constant_expression - // - TIntermBinary *binOp = cond->getAsBinaryNode(); - if (binOp == nullptr) - { - error(node->getLine(), "Invalid condition", "for"); - return false; - } - // Loop index should be to the left of relational operator. - TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == nullptr) - { - error(binOp->getLine(), "Invalid condition", "for"); - return false; - } - if (symbol->uniqueId().get() != indexSymbolId) - { - error(symbol->getLine(), "Expected loop index", symbol->getName()); - return false; - } - // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) - { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - default: - error(binOp->getLine(), "Invalid relational operator", - GetOperatorString(binOp->getOp())); - break; - } - // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) - { - error(binOp->getLine(), "Loop index cannot be compared with non-constant expression", - symbol->getName()); - return false; - } - - return true; -} - -bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int indexSymbolId) -{ - TIntermNode *expr = node->getExpression(); - if (expr == nullptr) - { - error(node->getLine(), "Missing expression", "for"); - return false; - } - - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary *unOp = expr->getAsUnaryNode(); - TIntermBinary *binOp = unOp ? nullptr : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - const TFunction *opFunc = nullptr; - TIntermSymbol *symbol = nullptr; - if (unOp != nullptr) - { - op = unOp->getOp(); - opFunc = unOp->getFunction(); - symbol = unOp->getOperand()->getAsSymbolNode(); - } - else if (binOp != nullptr) - { - op = binOp->getOp(); - symbol = binOp->getLeft()->getAsSymbolNode(); - } - - // The operand must be loop index. - if (symbol == nullptr) - { - error(expr->getLine(), "Invalid expression", "for"); - return false; - } - if (symbol->uniqueId().get() != indexSymbolId) - { - error(symbol->getLine(), "Expected loop index", symbol->getName()); - return false; - } - - // The operator is one of: ++ -- += -=. - switch (op) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != nullptr) && (binOp == nullptr)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == nullptr) && (binOp != nullptr)); - break; - default: - if (BuiltInGroup::IsBuiltIn(op)) - { - ASSERT(opFunc != nullptr); - error(expr->getLine(), "Invalid built-in call", opFunc->name().data()); - } - else - { - error(expr->getLine(), "Invalid operator", GetOperatorString(op)); - } - return false; - } - - // Loop index must be incremented/decremented with a constant. - if (binOp != nullptr) - { - if (!isConstExpr(binOp->getRight())) - { - error(binOp->getLine(), "Loop index cannot be modified by non-constant expression", - symbol->getName()); - return false; - } - } - - return true; -} - -bool ValidateLimitationsTraverser::isConstExpr(TIntermNode *node) -{ - ASSERT(node != nullptr); - return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst; -} - -bool ValidateLimitationsTraverser::isConstIndexExpr(TIntermNode *node) -{ - ASSERT(node != nullptr); - - ValidateConstIndexExpr validate(mLoopSymbolIds); - node->traverse(&validate); - return validate.isValid(); -} - -bool ValidateLimitationsTraverser::validateIndexing(TIntermBinary *node) -{ - ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect)); - - bool valid = true; - TIntermTyped *index = node->getRight(); - // The index expession must be a constant-index-expression unless - // the operand is a uniform in a vertex shader. - TIntermTyped *operand = node->getLeft(); - bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); - if (!skip && !isConstIndexExpr(index)) - { - error(index->getLine(), "Index expression must be constant", "[]"); - valid = false; - } - return valid; -} - -} // namespace - -bool ValidateLimitations(TIntermNode *root, - GLenum shaderType, - TSymbolTable *symbolTable, - TDiagnostics *diagnostics) -{ - ValidateLimitationsTraverser validate(shaderType, symbolTable, diagnostics); - root->traverse(&validate); - return diagnostics->numErrors() == 0; -} - -} // namespace sh diff --git a/src/compiler/translator/ValidateLimitations.h b/src/compiler/translator/ValidateLimitations.h deleted file mode 100644 index 00f26b53f57..00000000000 --- a/src/compiler/translator/ValidateLimitations.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2010 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. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ -#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -class TDiagnostics; - -// Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES -// 1.00 spec Appendix A. -bool ValidateLimitations(TIntermNode *root, - GLenum shaderType, - TSymbolTable *symbolTable, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/src/compiler/translator/ValidateMaxParameters.cpp b/src/compiler/translator/ValidateMaxParameters.cpp deleted file mode 100644 index b3f53e27fa4..00000000000 --- a/src/compiler/translator/ValidateMaxParameters.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright 2016 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. -// -// ValidateMaxParameters checks if function definitions have more than a set number of parameters. - -#include "compiler/translator/ValidateMaxParameters.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/Symbol.h" - -namespace sh -{ - -bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters) -{ - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); - if (definition != nullptr && - definition->getFunctionPrototype()->getFunction()->getParamCount() > maxParameters) - { - return false; - } - } - return true; -} - -} // namespace sh diff --git a/src/compiler/translator/ValidateMaxParameters.h b/src/compiler/translator/ValidateMaxParameters.h deleted file mode 100644 index 73cdb992d36..00000000000 --- a/src/compiler/translator/ValidateMaxParameters.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright 2016 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. -// -// ValidateMaxParameters checks if function definitions have more than a set number of parameters. - -#ifndef COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ -#define COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ - -namespace sh -{ - -class TIntermBlock; - -// Return true if valid. -bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ diff --git a/src/compiler/translator/ValidateOutputs.cpp b/src/compiler/translator/ValidateOutputs.cpp deleted file mode 100644 index 927783db73f..00000000000 --- a/src/compiler/translator/ValidateOutputs.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// -// Copyright 2013 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. -// -// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, -// out-of-range locations, that locations are specified when using multiple outputs, and YUV output -// validity. - -#include "compiler/translator/ValidateOutputs.h" - -#include - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/ParseContext.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); -} - -class ValidateOutputsTraverser : public TIntermTraverser -{ - public: - ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, - const ShBuiltInResources &resources, - bool usesPixelLocalStorage, - bool isWebGL); - - void validate(TDiagnostics *diagnostics) const; - - void visitSymbol(TIntermSymbol *) override; - - private: - int mMaxDrawBuffers; - int mMaxDualSourceDrawBuffers; - bool mEnablesBlendFuncExtended; - bool mUsesIndex1; - bool mUsesPixelLocalStorage; - bool mIsWebGL; - bool mUsesFragDepth; - - typedef std::vector OutputVector; - OutputVector mOutputs; - OutputVector mUnspecifiedLocationOutputs; - OutputVector mYuvOutputs; - std::set mVisitedSymbols; // Visited symbol ids. -}; - -ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, - const ShBuiltInResources &resources, - bool usesPixelLocalStorage, - bool isWebGL) - : TIntermTraverser(true, false, false), - mMaxDrawBuffers(resources.MaxDrawBuffers), - mMaxDualSourceDrawBuffers(resources.MaxDualSourceDrawBuffers), - mEnablesBlendFuncExtended( - IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)), - mUsesIndex1(false), - mUsesPixelLocalStorage(usesPixelLocalStorage), - mIsWebGL(isWebGL), - mUsesFragDepth(false) -{} - -void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol) -{ - if (symbol->variable().symbolType() == SymbolType::Empty) - return; - - if (mVisitedSymbols.count(symbol->uniqueId().get()) == 1) - return; - - mVisitedSymbols.insert(symbol->uniqueId().get()); - - TQualifier qualifier = symbol->getQualifier(); - if (qualifier == EvqFragmentOut) - { - const TLayoutQualifier &layoutQualifier = symbol->getType().getLayoutQualifier(); - if (layoutQualifier.location != -1) - { - mOutputs.push_back(symbol); - if (layoutQualifier.index == 1) - { - mUsesIndex1 = true; - } - } - else if (layoutQualifier.yuv == true) - { - mYuvOutputs.push_back(symbol); - } - else - { - mUnspecifiedLocationOutputs.push_back(symbol); - } - } - else if (qualifier == EvqFragDepth) - { - mUsesFragDepth = true; - } -} - -void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const -{ - ASSERT(diagnostics); - OutputVector validOutputs(mUsesIndex1 ? mMaxDualSourceDrawBuffers : mMaxDrawBuffers, nullptr); - OutputVector validSecondaryOutputs(mMaxDualSourceDrawBuffers, nullptr); - - for (const auto &symbol : mOutputs) - { - const TType &type = symbol->getType(); - ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6. - const size_t elementCount = - static_cast(type.isArray() ? type.getOutermostArraySize() : 1u); - const size_t location = static_cast(type.getLayoutQualifier().location); - - ASSERT(type.getLayoutQualifier().location != -1); - - OutputVector *validOutputsToUse = &validOutputs; - OutputVector *otherOutputsToUse = &validSecondaryOutputs; - // The default index is 0, so we only assign the output to secondary outputs in case the - // index is explicitly set to 1. - if (type.getLayoutQualifier().index == 1) - { - validOutputsToUse = &validSecondaryOutputs; - otherOutputsToUse = &validOutputs; - } - - if (location + elementCount <= validOutputsToUse->size()) - { - for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++) - { - const size_t offsetLocation = location + elementIndex; - if ((*validOutputsToUse)[offsetLocation]) - { - std::stringstream strstr = sh::InitializeStream(); - strstr << "conflicting output locations with previously defined output '" - << (*validOutputsToUse)[offsetLocation]->getName() << "'"; - error(*symbol, strstr.str().c_str(), diagnostics); - } - else - { - (*validOutputsToUse)[offsetLocation] = symbol; - if (offsetLocation < otherOutputsToUse->size()) - { - TIntermSymbol *otherSymbol = (*otherOutputsToUse)[offsetLocation]; - if (otherSymbol && otherSymbol->getType().getBasicType() != - symbol->getType().getBasicType()) - { - std::stringstream strstr = sh::InitializeStream(); - strstr << "conflicting output types with previously defined output " - << "'" << (*otherOutputsToUse)[offsetLocation]->getName() << "'" - << " for location " << offsetLocation; - error(*symbol, strstr.str().c_str(), diagnostics); - } - } - } - } - } - else - { - if (elementCount > 0) - { - std::stringstream strstr = sh::InitializeStream(); - strstr << (elementCount > 1 ? "output array locations would exceed " - : "output location must be < ") - << "MAX_" << (mUsesIndex1 ? "DUAL_SOURCE_" : "") << "DRAW_BUFFERS"; - error(*symbol, strstr.str().c_str(), diagnostics); - } - } - } - - if ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) || - mUnspecifiedLocationOutputs.size() > 1) - { - const char *unspecifiedLocationErrorMessage = nullptr; - if (!mEnablesBlendFuncExtended) - { - unspecifiedLocationErrorMessage = - "must explicitly specify all locations when using multiple fragment outputs"; - } - else if (mUsesPixelLocalStorage) - { - unspecifiedLocationErrorMessage = - "must explicitly specify all locations when using multiple fragment outputs and " - "pixel local storage, even if EXT_blend_func_extended is enabled"; - } - else if (mIsWebGL) - { - unspecifiedLocationErrorMessage = - "must explicitly specify all locations when using multiple fragment outputs " - "in WebGL contexts, even if EXT_blend_func_extended is enabled"; - } - if (unspecifiedLocationErrorMessage != nullptr) - { - for (const auto &symbol : mUnspecifiedLocationOutputs) - { - error(*symbol, unspecifiedLocationErrorMessage, diagnostics); - } - } - } - - if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() || - !mUnspecifiedLocationOutputs.empty())) - { - for (const auto &symbol : mYuvOutputs) - { - error(*symbol, - "not allowed to specify yuv qualifier when using depth or multiple color " - "fragment outputs", - diagnostics); - } - } -} - -} // anonymous namespace - -bool ValidateOutputs(TIntermBlock *root, - const TExtensionBehavior &extBehavior, - const ShBuiltInResources &resources, - bool usesPixelLocalStorage, - bool isWebGL, - TDiagnostics *diagnostics) -{ - ValidateOutputsTraverser validateOutputs(extBehavior, resources, usesPixelLocalStorage, - isWebGL); - root->traverse(&validateOutputs); - int numErrorsBefore = diagnostics->numErrors(); - validateOutputs.validate(diagnostics); - return (diagnostics->numErrors() == numErrorsBefore); -} - -} // namespace sh diff --git a/src/compiler/translator/ValidateOutputs.h b/src/compiler/translator/ValidateOutputs.h deleted file mode 100644 index 2d502985c2a..00000000000 --- a/src/compiler/translator/ValidateOutputs.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2013 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. -// -// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, -// out-of-range locations, that locations are specified when using multiple outputs, and YUV output -// validity. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ -#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ - -#include - -#include "compiler/translator/ExtensionBehavior.h" - -namespace sh -{ - -class TCompiler; -class TIntermBlock; -class TDiagnostics; - -// Returns true if the shader has no conflicting or otherwise erroneous fragment outputs. -bool ValidateOutputs(TIntermBlock *root, - const TExtensionBehavior &extBehavior, - const ShBuiltInResources &resources, - bool usesPixelLocalStorage, - bool isWebGL, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/src/compiler/translator/ValidateSwitch.cpp b/src/compiler/translator/ValidateSwitch.cpp deleted file mode 100644 index 8a9e7b22a1d..00000000000 --- a/src/compiler/translator/ValidateSwitch.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// Copyright 2002 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. -// - -#include "compiler/translator/ValidateSwitch.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -const int kMaxAllowedTraversalDepth = 256; - -class ValidateSwitch : public TIntermTraverser -{ - public: - static bool validate(TBasicType switchType, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc); - - void visitSymbol(TIntermSymbol *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitDeclaration(Visit, TIntermDeclaration *) override; - bool visitBlock(Visit visit, TIntermBlock *) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitUnary(Visit, TIntermUnary *) override; - bool visitTernary(Visit, TIntermTernary *) override; - bool visitSwizzle(Visit, TIntermSwizzle *) override; - bool visitIfElse(Visit visit, TIntermIfElse *) override; - bool visitSwitch(Visit, TIntermSwitch *) override; - bool visitCase(Visit, TIntermCase *node) override; - bool visitAggregate(Visit, TIntermAggregate *) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit, TIntermBranch *) override; - - private: - ValidateSwitch(TBasicType switchType, TDiagnostics *context); - - bool validateInternal(const TSourceLoc &loc); - - TBasicType mSwitchType; - TDiagnostics *mDiagnostics; - bool mCaseTypeMismatch; - bool mFirstCaseFound; - bool mStatementBeforeCase; - bool mLastStatementWasCase; - int mControlFlowDepth; - bool mCaseInsideControlFlow; - int mDefaultCount; - std::set mCasesSigned; - std::set mCasesUnsigned; - bool mDuplicateCases; -}; - -bool ValidateSwitch::validate(TBasicType switchType, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - ValidateSwitch validate(switchType, diagnostics); - ASSERT(statementList); - statementList->traverse(&validate); - return validate.validateInternal(loc); -} - -ValidateSwitch::ValidateSwitch(TBasicType switchType, TDiagnostics *diagnostics) - : TIntermTraverser(true, false, true, nullptr), - mSwitchType(switchType), - mDiagnostics(diagnostics), - mCaseTypeMismatch(false), - mFirstCaseFound(false), - mStatementBeforeCase(false), - mLastStatementWasCase(false), - mControlFlowDepth(0), - mCaseInsideControlFlow(false), - mDefaultCount(0), - mDuplicateCases(false) -{ - setMaxAllowedDepth(kMaxAllowedTraversalDepth); -} - -void ValidateSwitch::visitSymbol(TIntermSymbol *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) -{ - // Conditions of case labels are not traversed, so this is some other constant - // Could be just a statement like "0;" - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBlock(Visit visit, TIntermBlock *) -{ - if (getParentNode() != nullptr) - { - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - } - return true; -} - -bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitTernary(Visit, TIntermTernary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwizzle(Visit, TIntermSwizzle *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - // Don't go into nested switch statements - return false; -} - -bool ValidateSwitch::visitCase(Visit, TIntermCase *node) -{ - const char *nodeStr = node->hasCondition() ? "case" : "default"; - if (mControlFlowDepth > 0) - { - mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr); - mCaseInsideControlFlow = true; - } - mFirstCaseFound = true; - mLastStatementWasCase = true; - if (!node->hasCondition()) - { - ++mDefaultCount; - if (mDefaultCount > 1) - { - mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr); - } - } - else - { - TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); - if (condition == nullptr) - { - // This can happen in error cases. - return false; - } - TBasicType conditionType = condition->getBasicType(); - if (conditionType != mSwitchType) - { - mDiagnostics->error(condition->getLine(), - "case label type does not match switch init-expression type", - nodeStr); - mCaseTypeMismatch = true; - } - - if (conditionType == EbtInt) - { - int iConst = condition->getIConst(0); - if (mCasesSigned.find(iConst) != mCasesSigned.end()) - { - mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesSigned.insert(iConst); - } - } - else if (conditionType == EbtUInt) - { - unsigned int uConst = condition->getUConst(0); - if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) - { - mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesUnsigned.insert(uConst); - } - } - // Other types are possible only in error cases, where the error has already been generated - // when parsing the case statement. - } - // Don't traverse the condition of the case statement - return false; -} - -bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) -{ - if (getParentNode() != nullptr) - { - // This is not the statementList node, but some other node. - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - } - return true; -} - -bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::validateInternal(const TSourceLoc &loc) -{ - if (mStatementBeforeCase) - { - mDiagnostics->error(loc, "statement before the first label", "switch"); - } - if (mLastStatementWasCase) - { - // There have been some differences between versions of GLSL ES specs on whether this should - // be an error or not, but as of early 2018 the latest discussion is that this is an error - // also on GLSL ES versions newer than 3.00. - mDiagnostics->error( - loc, "no statement between the last label and the end of the switch statement", - "switch"); - } - if (getMaxDepth() >= kMaxAllowedTraversalDepth) - { - mDiagnostics->error(loc, "too complex expressions inside a switch statement", "switch"); - } - return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && - !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases && - getMaxDepth() < kMaxAllowedTraversalDepth; -} - -} // anonymous namespace - -bool ValidateSwitchStatementList(TBasicType switchType, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - return ValidateSwitch::validate(switchType, diagnostics, statementList, loc); -} - -} // namespace sh diff --git a/src/compiler/translator/ValidateSwitch.h b/src/compiler/translator/ValidateSwitch.h deleted file mode 100644 index 828faac98a2..00000000000 --- a/src/compiler/translator/ValidateSwitch.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright 2002 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. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_ -#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" - -namespace sh -{ -class TDiagnostics; -class TIntermBlock; - -// Check for errors and output error messages on the context. -// Returns true if there are no errors. -bool ValidateSwitchStatementList(TBasicType switchType, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/src/compiler/translator/ValidateTypeSizeLimitations.cpp b/src/compiler/translator/ValidateTypeSizeLimitations.cpp deleted file mode 100644 index 01acbfe4e06..00000000000 --- a/src/compiler/translator/ValidateTypeSizeLimitations.cpp +++ /dev/null @@ -1,350 +0,0 @@ -// -// Copyright 2021 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. -// - -#include "compiler/translator/ValidateTypeSizeLimitations.h" - -#include "angle_gl.h" -#include "common/mathutil.h" -#include "common/span.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/Symbol.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/blocklayout.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -// Arbitrarily enforce that all types declared with a size in bytes of over 2 GB will cause -// compilation failure. -// -// For local and global variables, the limit is much lower (64KB) as that much memory won't fit in -// the GPU registers anyway. -constexpr size_t kMaxVariableSizeInBytes = static_cast(2) * 1024 * 1024 * 1024; -constexpr size_t kMaxPrivateVariableSizeInBytes = static_cast(64) * 1024; -constexpr size_t kMaxTotalPrivateVariableSizeInBytes = static_cast(16) * 1024 * 1024; - -// Traverses intermediate tree to ensure that the shader does not -// exceed certain implementation-defined limits on the sizes of types. -// Some code was copied from the CollectVariables pass. -class ValidateTypeSizeLimitationsTraverser : public TIntermTraverser -{ - public: - ValidateTypeSizeLimitationsTraverser(TSymbolTable *symbolTable, TDiagnostics *diagnostics) - : TIntermTraverser(true, false, false, symbolTable), - mDiagnostics(diagnostics), - mTotalPrivateVariablesSize(0) - { - ASSERT(diagnostics); - } - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - const TIntermSequence &sequence = *(node->getSequence()); - - for (TIntermNode *variableNode : sequence) - { - // See CollectVariablesTraverser::visitDeclaration for a - // deeper analysis of the AST structures that might be - // encountered. - TIntermSymbol *asSymbol = variableNode->getAsSymbolNode(); - TIntermBinary *asBinary = variableNode->getAsBinaryNode(); - - if (asBinary != nullptr) - { - ASSERT(asBinary->getOp() == EOpInitialize); - asSymbol = asBinary->getLeft()->getAsSymbolNode(); - } - - ASSERT(asSymbol); - - const TVariable &variable = asSymbol->variable(); - if (variable.symbolType() == SymbolType::AngleInternal) - { - // Ignore internal variables. - continue; - } - - if (!validateVariableSize(variable, asSymbol->getLine())) - { - return false; - } - } - - return true; - } - - void visitFunctionPrototype(TIntermFunctionPrototype *node) override - { - const TFunction *function = node->getFunction(); - const size_t paramCount = function->getParamCount(); - - for (size_t paramIndex = 0; paramIndex < paramCount; ++paramIndex) - { - validateVariableSize(*function->getParam(paramIndex), node->getLine()); - } - } - - bool validateVariableSize(const TVariable &variable, const TSourceLoc &location) - { - const TType &variableType = variable.getType(); - - // Create a ShaderVariable from which to compute - // (conservative) sizing information. - ShaderVariable shaderVar; - setCommonVariableProperties(variableType, variable, &shaderVar); - - size_t variableSize; - { - // Compute the std140 layout of this variable, assuming - // it's a member of a block (which it might not be). - Std140BlockEncoder layoutEncoder; - BlockEncoderVisitor visitor("", "", &layoutEncoder); - // Since the size limit's arbitrary, it doesn't matter - // whether the row-major layout is correctly determined. - constexpr bool isRowMajorLayout = false; - - // For efficiency, don't actually iterate over all array elements, as only the size - // calculation matters. Instead, for arrays, the size is reduced to 2 (so array-ness - // and padding is taken into account), and the total size is derived from the array - // size. - const uint32_t arraySizeProduct = - shaderVar.isArray() ? shaderVar.getArraySizeProduct() : 1; - if (arraySizeProduct > 1) - { - shaderVar.arraySizes.resize(1); - shaderVar.arraySizes[0] = 2; - } - - TraverseShaderVariable(shaderVar, isRowMajorLayout, &visitor); - variableSize = layoutEncoder.getCurrentOffset(); - - if (arraySizeProduct > 1) - { - // Calculate the actual size of the variable. - ASSERT(variableSize % 2 == 0); - variableSize = variableSize / 2 * arraySizeProduct; - } - } - - if (variableSize > kMaxVariableSizeInBytes) - { - error(location, "Size of declared variable exceeds implementation-defined limit", - variable.name()); - return false; - } - - // Skip over struct declarations. As long as they are not used (or if they are used later - // in a less-restricted context (such as a UBO or SSBO)), they can be larger than - // kMaxPrivateVariableSizeInBytes. - if (variable.symbolType() == SymbolType::Empty && variableType.isStructSpecifier()) - { - return true; - } - - switch (variableType.getQualifier()) - { - // List of all types that need to be limited (for example because they cause overflows - // in drivers, or create trouble for the SPIR-V gen as the number of an instruction's - // arguments cannot be more than 64KB (see OutputSPIRVTraverser::cast)). - - // Local/global variables - case EvqTemporary: - case EvqGlobal: - case EvqConst: - - // Function arguments - case EvqParamIn: - case EvqParamOut: - case EvqParamInOut: - case EvqParamConst: - - // Varyings - case EvqVaryingIn: - case EvqVaryingOut: - case EvqSmoothOut: - case EvqFlatOut: - case EvqNoPerspectiveOut: - case EvqCentroidOut: - case EvqSampleOut: - case EvqNoPerspectiveCentroidOut: - case EvqNoPerspectiveSampleOut: - case EvqSmoothIn: - case EvqFlatIn: - case EvqNoPerspectiveIn: - case EvqCentroidIn: - case EvqNoPerspectiveCentroidIn: - case EvqNoPerspectiveSampleIn: - case EvqVertexOut: - case EvqFragmentIn: - case EvqGeometryIn: - case EvqGeometryOut: - case EvqPerVertexIn: - case EvqPerVertexOut: - case EvqPatchIn: - case EvqPatchOut: - case EvqTessControlIn: - case EvqTessControlOut: - case EvqTessEvaluationIn: - case EvqTessEvaluationOut: - - if (variableSize > kMaxPrivateVariableSizeInBytes) - { - error(location, - "Size of declared private variable exceeds implementation-defined limit", - variable.name()); - return false; - } - mTotalPrivateVariablesSize += variableSize; - break; - default: - break; - } - - return true; - } - - void validateTotalPrivateVariableSize() - { - if (mTotalPrivateVariablesSize.ValueOrDefault(std::numeric_limits::max()) > - kMaxTotalPrivateVariableSizeInBytes) - { - mDiagnostics->error( - TSourceLoc{}, - "Total size of declared private variables exceeds implementation-defined limit", - ""); - } - } - - private: - void error(TSourceLoc loc, const char *reason, const ImmutableString &token) - { - mDiagnostics->error(loc, reason, token.data()); - } - - void setFieldOrVariableProperties(const TType &type, - bool staticUse, - bool isShaderIOBlock, - bool isPatch, - ShaderVariable *variableOut) const - { - ASSERT(variableOut); - - variableOut->staticUse = staticUse; - variableOut->isShaderIOBlock = isShaderIOBlock; - variableOut->isPatch = isPatch; - - const TStructure *structure = type.getStruct(); - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - if (structure) - { - // Structures use a NONE type that isn't exposed outside ANGLE. - variableOut->type = GL_NONE; - if (structure->symbolType() != SymbolType::Empty) - { - variableOut->structOrBlockName = structure->name().data(); - } - - const TFieldList &fields = structure->fields(); - - for (const TField *field : fields) - { - // Regardless of the variable type (uniform, in/out etc.) its fields are always - // plain ShaderVariable objects. - ShaderVariable fieldVariable; - setFieldProperties(*field->type(), field->name(), staticUse, isShaderIOBlock, - isPatch, &fieldVariable); - variableOut->fields.push_back(fieldVariable); - } - } - else if (interfaceBlock && isShaderIOBlock) - { - variableOut->type = GL_NONE; - if (interfaceBlock->symbolType() != SymbolType::Empty) - { - variableOut->structOrBlockName = interfaceBlock->name().data(); - } - const TFieldList &fields = interfaceBlock->fields(); - for (const TField *field : fields) - { - ShaderVariable fieldVariable; - setFieldProperties(*field->type(), field->name(), staticUse, true, isPatch, - &fieldVariable); - fieldVariable.isShaderIOBlock = true; - variableOut->fields.push_back(fieldVariable); - } - } - else - { - variableOut->type = GLVariableType(type); - variableOut->precision = GLVariablePrecision(type); - } - - const angle::Span &arraySizes = type.getArraySizes(); - if (!arraySizes.empty()) - { - variableOut->arraySizes.assign(arraySizes.begin(), arraySizes.end()); - // WebGL does not support tessellation shaders; removed - // code specific to that shader type. - } - } - - void setFieldProperties(const TType &type, - const ImmutableString &name, - bool staticUse, - bool isShaderIOBlock, - bool isPatch, - ShaderVariable *variableOut) const - { - ASSERT(variableOut); - setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); - variableOut->name.assign(name.data(), name.length()); - } - - void setCommonVariableProperties(const TType &type, - const TVariable &variable, - ShaderVariable *variableOut) const - { - ASSERT(variableOut); - - // Shortcut some processing that's unnecessary for this analysis. - const bool staticUse = true; - const bool isShaderIOBlock = type.getInterfaceBlock() != nullptr; - const bool isPatch = false; - - setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); - - const bool isNamed = variable.symbolType() != SymbolType::Empty; - - if (isNamed) - { - variableOut->name.assign(variable.name().data(), variable.name().length()); - } - } - - TDiagnostics *mDiagnostics; - std::vector mLoopSymbolIds; - - angle::base::CheckedNumeric mTotalPrivateVariablesSize; -}; - -} // namespace - -bool ValidateTypeSizeLimitations(TIntermNode *root, - TSymbolTable *symbolTable, - TDiagnostics *diagnostics) -{ - ValidateTypeSizeLimitationsTraverser validate(symbolTable, diagnostics); - root->traverse(&validate); - validate.validateTotalPrivateVariableSize(); - return diagnostics->numErrors() == 0; -} - -} // namespace sh diff --git a/src/compiler/translator/ValidateTypeSizeLimitations.h b/src/compiler/translator/ValidateTypeSizeLimitations.h deleted file mode 100644 index defa39876db..00000000000 --- a/src/compiler/translator/ValidateTypeSizeLimitations.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2021 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. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATETYPESIZELIMITATIONS_H_ -#define COMPILER_TRANSLATOR_VALIDATETYPESIZELIMITATIONS_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -class TDiagnostics; - -// Returns true if the given shader does not violate certain -// implementation-defined limits on the size of variables' types. -bool ValidateTypeSizeLimitations(TIntermNode *root, - TSymbolTable *symbolTable, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATETYPESIZELIMITATIONS_H_ diff --git a/src/compiler/translator/ValidateVaryingLocations.cpp b/src/compiler/translator/ValidateVaryingLocations.cpp index 3c2eeeb5bc7..5547f2a6686 100644 --- a/src/compiler/translator/ValidateVaryingLocations.cpp +++ b/src/compiler/translator/ValidateVaryingLocations.cpp @@ -20,11 +20,6 @@ namespace sh namespace { -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); -} - int GetStructLocationCount(const TStructure *structure); int GetFieldLocationCount(const TField *field) @@ -131,19 +126,13 @@ bool ShouldIgnoreVaryingArraySize(TQualifier qualifier, GLenum shaderType) } } -struct SymbolAndField -{ - const TIntermSymbol *symbol; - const TField *field; -}; -using LocationMap = std::map; - -void MarkVaryingLocations(TDiagnostics *diagnostics, - const TIntermSymbol *varying, +bool MarkVaryingLocations(const TVariable *variable, const TField *field, int location, int elementCount, - LocationMap *locationMap) + LocationValidationMap *locationMap, + VariableAndField *conflictingSymbolOut, + const TField **conflictingFieldInNewSymbolOut) { for (int elementIndex = 0; elementIndex < elementCount; ++elementIndex) { @@ -151,218 +140,137 @@ void MarkVaryingLocations(TDiagnostics *diagnostics, auto conflict = locationMap->find(offsetLocation); if (conflict != locationMap->end()) { - std::stringstream strstr = sh::InitializeStream(); - strstr << "'" << varying->getName(); - if (field) - { - strstr << "." << field->name(); - } - strstr << "' conflicting location with '" << conflict->second.symbol->getName(); - if (conflict->second.field) - { - strstr << "." << conflict->second.field->name(); - } - strstr << "'"; - error(*varying, strstr.str().c_str(), diagnostics); + *conflictingSymbolOut = conflict->second; + *conflictingFieldInNewSymbolOut = field; + return false; } else { - (*locationMap)[offsetLocation] = {varying, field}; + (*locationMap)[offsetLocation] = {variable, field}; } } + + return true; } -using VaryingVector = std::vector; +} // anonymous namespace -void ValidateShaderInterfaceAndAssignLocations(TDiagnostics *diagnostics, - const VaryingVector &varyingVector, - GLenum shaderType) +unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType) { - // Location conflicts can only happen when there are two or more varyings in varyingVector. - if (varyingVector.size() <= 1) + const TQualifier qualifier = varyingType.getQualifier(); + const bool ignoreVaryingArraySize = ShouldIgnoreVaryingArraySize(qualifier, shaderType); + + if (varyingType.isInterfaceBlock()) { - return; + return GetInterfaceBlockLocationCount(varyingType, ignoreVaryingArraySize); } - LocationMap locationMap; - for (const TIntermSymbol *varying : varyingVector) + return GetLocationCount(varyingType, ignoreVaryingArraySize); +} + +bool ValidateVaryingLocation(const TVariable *newVariable, + LocationValidationMap *locationMap, + GLenum shaderType, + VariableAndField *conflictingSymbolOut, + const TField **conflictingFieldInNewSymbolOut) +{ + const TType &type = newVariable->getType(); + const int location = type.getLayoutQualifier().location; + ASSERT(location >= 0); + + bool ignoreVaryingArraySize = ShouldIgnoreVaryingArraySize(type.getQualifier(), shaderType); + + // A varying is either: + // + // - A vector or matrix, which can take a number of contiguous locations + // - A struct, which also takes a number of contiguous locations + // - An interface block. + // + // Interface blocks can assign arbitrary locations to their fields, for example: + // + // layout(location = 4) in block { + // vec4 a; // gets location 4 + // vec4 b; // gets location 5 + // layout(location = 7) vec4 c; // gets location 7 + // vec4 d; // gets location 8 + // layout (location = 1) vec4 e; // gets location 1 + // vec4 f; // gets location 2 + // }; + // + // The following code therefore takes two paths. For non-interface-block types, the number + // of locations for the varying is calculated (elementCount), and all locations in + // [location, location + elementCount) are marked as occupied. + // + // For interface blocks, a similar algorithm is implemented except each field is + // individually marked with the location either advancing automatically or taking its value + // from the field's layout qualifier. + + if (type.isInterfaceBlock()) { - const TType &varyingType = varying->getType(); - const int location = varyingType.getLayoutQualifier().location; - ASSERT(location >= 0); - - bool ignoreVaryingArraySize = - ShouldIgnoreVaryingArraySize(varying->getQualifier(), shaderType); - - // A varying is either: - // - // - A vector or matrix, which can take a number of contiguous locations - // - A struct, which also takes a number of contiguous locations - // - An interface block. - // - // Interface blocks can assign arbitrary locations to their fields, for example: - // - // layout(location = 4) in block { - // vec4 a; // gets location 4 - // vec4 b; // gets location 5 - // layout(location = 7) vec4 c; // gets location 7 - // vec4 d; // gets location 8 - // layout (location = 1) vec4 e; // gets location 1 - // vec4 f; // gets location 2 - // }; - // - // The following code therefore takes two paths. For non-interface-block types, the number - // of locations for the varying is calculated (elementCount), and all locations in - // [location, location + elementCount) are marked as occupied. - // - // For interface blocks, a similar algorithm is implemented except each field is - // individually marked with the location either advancing automatically or taking its value - // from the field's layout qualifier. - - if (varyingType.isInterfaceBlock()) - { - int currentLocation = location; - bool anyFieldWithLocation = false; + const int startLocation = location; + int currentLocation = location; + bool anyFieldWithLocation = false; - for (const TField *field : varyingType.getInterfaceBlock()->fields()) + for (const TField *field : type.getInterfaceBlock()->fields()) + { + const int fieldLocation = field->type()->getLayoutQualifier().location; + if (fieldLocation >= 0) { - const int fieldLocation = field->type()->getLayoutQualifier().location; - if (fieldLocation >= 0) - { - currentLocation = fieldLocation; - anyFieldWithLocation = true; - } - - const int fieldLocationCount = GetFieldLocationCount(field); - MarkVaryingLocations(diagnostics, varying, field, currentLocation, - fieldLocationCount, &locationMap); - - currentLocation += fieldLocationCount; + currentLocation = fieldLocation; + anyFieldWithLocation = true; } - // Array interface blocks can't have location qualifiers on fields. - ASSERT(ignoreVaryingArraySize || !anyFieldWithLocation || !varyingType.isArray()); - - if (!ignoreVaryingArraySize && varyingType.isArray()) + const int fieldLocationCount = GetFieldLocationCount(field); + if (!MarkVaryingLocations(newVariable, field, currentLocation, fieldLocationCount, + locationMap, conflictingSymbolOut, + conflictingFieldInNewSymbolOut)) { - // This is only reached if the varying is an array of interface blocks, with only a - // layout qualifier on the block itself, for example: - // - // layout(location = 4) in block { - // vec4 a; - // vec4 b; - // vec4 c; - // vec4 d; - // } instance[N]; - // - // The locations for instance[0] are already marked by the above code, so we need to - // further mark locations occupied by instances [1, N). |currentLocation| is - // already just past the end of instance[0], which is the beginning of instance[1]. - // - int remainingLocations = currentLocation * (varyingType.getArraySizeProduct() - 1); - MarkVaryingLocations(diagnostics, varying, nullptr, currentLocation, - remainingLocations, &locationMap); + return false; } - } - else - { - const int elementCount = GetLocationCount(varying->getType(), ignoreVaryingArraySize); - MarkVaryingLocations(diagnostics, varying, nullptr, location, elementCount, - &locationMap); - } - } -} - -class ValidateVaryingLocationsTraverser : public TIntermTraverser -{ - public: - ValidateVaryingLocationsTraverser(GLenum shaderType); - void validate(TDiagnostics *diagnostics); - - private: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - - VaryingVector mInputVaryingsWithLocation; - VaryingVector mOutputVaryingsWithLocation; - GLenum mShaderType; -}; - -ValidateVaryingLocationsTraverser::ValidateVaryingLocationsTraverser(GLenum shaderType) - : TIntermTraverser(true, false, false), mShaderType(shaderType) -{} - -bool ValidateVaryingLocationsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); - const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); - if (symbol == nullptr) - { - return false; - } + currentLocation += fieldLocationCount; + } - if (symbol->variable().symbolType() == SymbolType::Empty) - { - return false; - } + // Array interface blocks can't have location qualifiers on fields. + ASSERT(ignoreVaryingArraySize || !anyFieldWithLocation || !type.isArray()); - // Collect varyings that have explicit 'location' qualifiers. - const TQualifier qualifier = symbol->getQualifier(); - if (symbol->getType().getLayoutQualifier().location != -1) - { - if (IsVaryingIn(qualifier)) - { - mInputVaryingsWithLocation.push_back(symbol); - } - else if (IsVaryingOut(qualifier)) + if (!ignoreVaryingArraySize && type.isArray()) { - mOutputVaryingsWithLocation.push_back(symbol); + // This is only reached if the varying is an array of interface blocks, with only a + // layout qualifier on the block itself, for example: + // + // layout(location = 4) in block { + // vec4 a; + // vec4 b; + // vec4 c; + // vec4 d; + // } instance[N]; + // + // The locations for instance[0] are already marked by the above code, so we need to + // further mark locations occupied by instances [1, N). |currentLocation| is + // already just past the end of instance[0], which is the beginning of instance[1]. + // + int remainingLocations = + (currentLocation - startLocation) * (type.getArraySizeProduct() - 1); + if (!MarkVaryingLocations(newVariable, nullptr, currentLocation, remainingLocations, + locationMap, conflictingSymbolOut, + conflictingFieldInNewSymbolOut)) + { + return false; + } } } - - return false; -} - -bool ValidateVaryingLocationsTraverser::visitFunctionDefinition(Visit visit, - TIntermFunctionDefinition *node) -{ - // We stop traversing function definitions because varyings cannot be defined in a function. - return false; -} - -void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics) -{ - ASSERT(diagnostics); - - ValidateShaderInterfaceAndAssignLocations(diagnostics, mInputVaryingsWithLocation, mShaderType); - ValidateShaderInterfaceAndAssignLocations(diagnostics, mOutputVaryingsWithLocation, - mShaderType); -} - -} // anonymous namespace - -unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType) -{ - const TQualifier qualifier = varyingType.getQualifier(); - const bool ignoreVaryingArraySize = ShouldIgnoreVaryingArraySize(qualifier, shaderType); - - if (varyingType.isInterfaceBlock()) + else { - return GetInterfaceBlockLocationCount(varyingType, ignoreVaryingArraySize); + const int elementCount = GetLocationCount(type, ignoreVaryingArraySize); + if (!MarkVaryingLocations(newVariable, nullptr, location, elementCount, locationMap, + conflictingSymbolOut, conflictingFieldInNewSymbolOut)) + { + return false; + } } - return GetLocationCount(varyingType, ignoreVaryingArraySize); -} - -bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType) -{ - ValidateVaryingLocationsTraverser varyingValidator(shaderType); - root->traverse(&varyingValidator); - int numErrorsBefore = diagnostics->numErrors(); - varyingValidator.validate(diagnostics); - return (diagnostics->numErrors() == numErrorsBefore); + return true; } } // namespace sh diff --git a/src/compiler/translator/ValidateVaryingLocations.h b/src/compiler/translator/ValidateVaryingLocations.h index 5ce43c91c4b..0c8904bf1f7 100644 --- a/src/compiler/translator/ValidateVaryingLocations.h +++ b/src/compiler/translator/ValidateVaryingLocations.h @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// The ValidateVaryingLocations function checks if there exists location conflicts on shader +// The ValidateVaryingLocation function checks if there exists location conflicts on shader // varyings. // @@ -11,17 +11,32 @@ #define COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ #include "GLSLANG/ShaderVars.h" +#include "compiler/translator/Common.h" namespace sh { -class TIntermBlock; -class TIntermSymbol; -class TDiagnostics; +class TVariable; +class TField; class TType; +struct VariableAndField +{ + const TVariable *variable = nullptr; + const TField *field = nullptr; +}; +using LocationValidationMap = TUnorderedMap; + unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType); -bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType); +// Add locations used by |newVariable| to the location map. If a conflict is detected, |false| is +// returned, and |conflictingSymbolOut| will return what is the conflicting symbol. If +// |newVariable| is a struct or interface block, the conflicting field is returned in +// |conflictingFieldInNewSymbolOut|. +bool ValidateVaryingLocation(const TVariable *newVariable, + LocationValidationMap *locationMap, + GLenum shaderType, + VariableAndField *conflictingSymbolOut, + const TField **conflictingFieldInNewSymbolOut); } // namespace sh diff --git a/src/compiler/translator/blocklayout.cpp b/src/compiler/translator/blocklayout.cpp index 4b9fb9e6b74..5f873eaf194 100644 --- a/src/compiler/translator/blocklayout.cpp +++ b/src/compiler/translator/blocklayout.cpp @@ -190,20 +190,22 @@ class BaseAlignmentVisitor : public ShaderVariableVisitor BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) {} BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix) { int arrayStride; int matrixStride; - getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride); + getBlockLayoutInfo(type, bytesPerComponent, arraySizes, isRowMajorMatrix, &arrayStride, + &matrixStride); const BlockMemberInfo memberInfo(type, static_cast(mCurrentOffset * kBytesPerComponent), static_cast(arrayStride * kBytesPerComponent), static_cast(matrixStride * kBytesPerComponent), gl::ArraySizeProduct(arraySizes), isRowMajorMatrix); - advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); + advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); return memberInfo; } @@ -281,6 +283,7 @@ void BlockLayoutEncoder::align(size_t baseAlignment) // StubBlockEncoder implementation. void StubBlockEncoder::getBlockLayoutInfo(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, @@ -290,6 +293,207 @@ void StubBlockEncoder::getBlockLayoutInfo(GLenum type, *matrixStrideOut = 0; } +// PackedSPIRVBlockEncoder implementation. +PackedSPIRVBlockEncoder::PackedSPIRVBlockEncoder() {} + +BlockMemberInfo PackedSPIRVBlockEncoder::encodeType(GLenum type, + const size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix) +{ + // Similar to BlockLayoutEncoder::encodeType(), except mCurrentOffset tracks offset in number + // of byte, instead of number of 4-byte. + int arrayStride; + int matrixStride; + + getBlockLayoutInfo(type, bytesPerComponent, arraySizes, isRowMajorMatrix, &arrayStride, + &matrixStride); + + const BlockMemberInfo memberInfo(type, static_cast(mCurrentOffset), arrayStride, + matrixStride, gl::ArraySizeProduct(arraySizes), + isRowMajorMatrix); + + advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; +} + +BlockMemberInfo PackedSPIRVBlockEncoder::encodeArrayOfPreEncodedStructs( + size_t size, + const std::vector &arraySizes) +{ + // Similar to BlockLayoutEncoder::encodeArrayOfPreEncodedStructs, except mCurrentOffset tracks + // offset in number of byte, instead of number of 4-byte. + const unsigned int innerArraySizeProduct = gl::InnerArraySizeProduct(arraySizes); + const unsigned int outermostArraySize = gl::OutermostArraySize(arraySizes); + + // The size of struct is expected to be already aligned appropriately. + const size_t arrayStride = size * innerArraySizeProduct; + GLenum type = GL_INVALID_ENUM; + const BlockMemberInfo memberInfo(type, static_cast(mCurrentOffset), + static_cast(arrayStride), -1, + gl::ArraySizeProduct(arraySizes), false); + + angle::base::CheckedNumeric checkedOffset(arrayStride); + checkedOffset *= outermostArraySize; + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + + return memberInfo; +} + +size_t PackedSPIRVBlockEncoder::getCurrentOffset() const +{ + // Similar to BlockLayoutEncoder::getCurrentOffset(), except mCurrentOffset tracks offset in + // number of byte, instead of number of 4-byte. + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + return checkedOffset.ValueOrDefault(std::numeric_limits::max()); +} + +void PackedSPIRVBlockEncoder::enterAggregateType(const ShaderVariable &structVar) +{ + // Similar to Std140BlockEncoder::enterAggregateType(), except mCurrentOffset tracks offset in + // number of byte, instead of number of 4-byte. + align(getBaseAlignment(structVar)); +} + +void PackedSPIRVBlockEncoder::exitAggregateType(const ShaderVariable &structVar) +{ + // Similar to Std140BlockEncoder::exitAggregateType(), except mCurrentOffset tracks offset in + // number of byte, instead of number of 4-byte. + align(getBaseAlignment(structVar)); +} + +void PackedSPIRVBlockEncoder::getBlockLayoutInfo(GLenum type, + const size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) +{ + // Right now we only pass kBytesPer16BitComponent for 16-bit float and vectors: half, half2, + // half3, half4. For all other data types, we pass kBytesPerComponent. + ASSERT(bytesPerComponent == kBytesPer16BitComponent || bytesPerComponent == kBytesPerComponent); + size_t baseAlignment = 0; + int matrixStride = 0; + int arrayStride = 0; + + if (gl::IsMatrixType(type)) + { + baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix); + matrixStride = static_cast(getTypeBaseAlignment(type, isRowMajorMatrix)); + + if (!arraySizes.empty()) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = + static_cast(getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters); + } + } + else if (!arraySizes.empty()) + { + baseAlignment = static_cast(getTypeBaseAlignment(type, false)); + arrayStride = static_cast(getTypeBaseAlignment(type, false)); + } + else + { + if (bytesPerComponent == kBytesPer16BitComponent) + { + ASSERT(gl::IsFloatScalarAndVectorType(type)); + baseAlignment = bytesPerComponent; + } + else + { + ASSERT(bytesPerComponent == kBytesPerComponent); + const size_t numComponents = static_cast(gl::VariableComponentCount(type)); + baseAlignment = ComponentAlignment(numComponents) * bytesPerComponent; + } + } + + align(baseAlignment); + + if (bytesPerComponent == kBytesPer16BitComponent && gl::IsFloatVectorType(type)) + { + if (isVectorStraddle(type)) + { + adjustAlignmentForStraddleVector(); + } + } + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void PackedSPIRVBlockEncoder::advanceOffset(GLenum type, + const size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) +{ + // Similar to Std140BlockEncoder::advanceOffset(), except mCurrentOffset tracks offset in + // number of byte, instead of number of 4-byte. + if (!arraySizes.empty()) + { + angle::base::CheckedNumeric checkedOffset(arrayStride); + checkedOffset *= gl::ArraySizeProduct(arraySizes); + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + } + else if (gl::IsMatrixType(type)) + { + angle::base::CheckedNumeric checkedOffset(matrixStride); + checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix); + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + } + else + { + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset += (gl::VariableComponentCount(type) * bytesPerComponent); + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + } +} + +size_t PackedSPIRVBlockEncoder::getBaseAlignment(const ShaderVariable &variable) const +{ + // Similar to Std140BlockEncoder::getBaseAlignment(), except it returns the number of byte + // count, instead of number of 4-byte count. + return kComponentsPerRegister * kBytesPerComponent; +} + +size_t PackedSPIRVBlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const +{ + // Similar to Std140BlockEncoder::getTypeBaseAlignment(), except it returns the number of byte + // count, instead of number of 4-byte count. + return kComponentsPerRegister * kBytesPerComponent; +} + +// Check if the memory occupied by data crosses 16-byte boundary: +// startMemory / 16 != (startMemory + dataSize) / 16 ? crosses boundary : does not cross boundary +bool PackedSPIRVBlockEncoder::isVectorStraddle(GLenum type) +{ + angle::base::CheckedNumeric checked16ByteOffset(mCurrentOffset); + checked16ByteOffset /= 16; + const size_t vectorSize = + kBytesPer16BitComponent * static_cast(gl::VariableComponentCount(type)); + angle::base::CheckedNumeric checkedOffsetWithVector(mCurrentOffset); + checkedOffsetWithVector += vectorSize; + checkedOffsetWithVector /= 16; + if (checked16ByteOffset.ValueOrDefault(std::numeric_limits::max()) != + checkedOffsetWithVector.ValueOrDefault(std::numeric_limits::max())) + { + return true; + } + return false; +} + +void PackedSPIRVBlockEncoder::adjustAlignmentForStraddleVector() +{ + // align the mCurrentOffset to the next 16 byte + align(16u); +} + // Std140BlockEncoder implementation. Std140BlockEncoder::Std140BlockEncoder() {} @@ -304,6 +508,7 @@ void Std140BlockEncoder::exitAggregateType(const ShaderVariable &structVar) } void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, @@ -346,6 +551,7 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, } void Std140BlockEncoder::advanceOffset(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, @@ -633,7 +839,10 @@ void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable, innermostArraySize.push_back(variable.getNestedArraySize(0)); } BlockMemberInfo variableInfo = - mEncoder->encodeType(variable.type, innermostArraySize, isRowMajor); + mEncoder->encodeType(variable.type, + variable.isFloat16 ? BlockLayoutEncoder::kBytesPer16BitComponent + : BlockLayoutEncoder::kBytesPerComponent, + innermostArraySize, isRowMajor); if (!mIsTopLevelArrayStrideReady) { ASSERT(mTopLevelArrayStride); diff --git a/src/compiler/translator/blocklayout.h b/src/compiler/translator/blocklayout.h index eb3e397add4..95d85b50387 100644 --- a/src/compiler/translator/blocklayout.h +++ b/src/compiler/translator/blocklayout.h @@ -119,6 +119,7 @@ class BlockLayoutEncoder virtual ~BlockLayoutEncoder() {} virtual BlockMemberInfo encodeType(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix); // Advance the offset based on struct size and array dimensions. Size can be calculated with @@ -138,6 +139,8 @@ class BlockLayoutEncoder static constexpr size_t kBytesPerComponent = 4u; static constexpr unsigned int kComponentsPerRegister = 4u; + static constexpr size_t kBytesPer16BitComponent = 2u; + static size_t GetBlockRegister(const BlockMemberInfo &info); static size_t GetBlockRegisterElement(const BlockMemberInfo &info); @@ -145,11 +148,13 @@ class BlockLayoutEncoder void align(size_t baseAlignment); virtual void getBlockLayoutInfo(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; virtual void advanceOffset(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, @@ -169,12 +174,14 @@ class StubBlockEncoder : public BlockLayoutEncoder protected: void getBlockLayoutInfo(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override; void advanceOffset(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, @@ -182,6 +189,51 @@ class StubBlockEncoder : public BlockLayoutEncoder {} }; +// The unit of mCurrentOffset in PackedSPIRVBlockEncoder is byte, instead of 4-byte as used by +// Std140BlockEncoder. The data type that the PackedSPIRVBlockEncoder processes can be half float, +// which is 2 bytes, and the VK_KHR_relaxed_block_layout allows 2 byte alignment, therefore changing +// mCurrentOffset unit from 4-byte to byte to allow more fine-grained offsets. +class PackedSPIRVBlockEncoder : public BlockLayoutEncoder +{ + public: + PackedSPIRVBlockEncoder(); + + BlockMemberInfo encodeType(GLenum type, + size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix) override; + + BlockMemberInfo encodeArrayOfPreEncodedStructs( + size_t size, + const std::vector &arraySizes) override; + + size_t getCurrentOffset() const override; + + void enterAggregateType(const ShaderVariable &structVar) override; + void exitAggregateType(const ShaderVariable &structVar) override; + + protected: + void getBlockLayoutInfo(GLenum type, + size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) override; + void advanceOffset(GLenum type, + size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) override; + + virtual size_t getBaseAlignment(const ShaderVariable &variable) const; + virtual size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const; + + private: + bool isVectorStraddle(GLenum type); + void adjustAlignmentForStraddleVector(); +}; + // Block layout according to the std140 block layout // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification @@ -195,11 +247,13 @@ class Std140BlockEncoder : public BlockLayoutEncoder protected: void getBlockLayoutInfo(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override; void advanceOffset(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, diff --git a/src/compiler/translator/builtin_function_declarations.txt b/src/compiler/translator/builtin_function_declarations.txt index ec6fdd1e421..4708a4e5174 100644 --- a/src/compiler/translator/builtin_function_declarations.txt +++ b/src/compiler/translator/builtin_function_declarations.txt @@ -302,7 +302,7 @@ GROUP BEGIN Texture {"queryFunction": true} vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2); vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3); DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "extension": "WEBGL_video_texture"} - vec4 textureVideoWEBGL(samplerVideoWEBGL, vec2); + vec4 textureVideoWEBGL(samplerVideoWEBGL, vec2); // Variants with bias are limited to fragment shaders GROUP BEGIN Bias {"shader_type": "FRAGMENT", "opSuffix": "Bias"} @@ -557,65 +557,80 @@ GROUP BEGIN Texture {"queryFunction": true} GROUP END OffsetBias GROUP BEGIN Gather {"queryFunction": true} - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} - gvec4 textureGather(gsampler2D, vec2); - gvec4 textureGather(gsampler2D, vec2, int); - gvec4 textureGather(gsampler2DArray, vec3); - gvec4 textureGather(gsampler2DArray, vec3, int); - gvec4 textureGather(gsamplerCube, vec3); - gvec4 textureGather(gsamplerCube, vec3, int); - DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} - gvec4 textureGather(gsamplerCubeArray, vec4); - gvec4 textureGather(gsamplerCubeArray, vec4, int); - vec4 textureGather(samplerCubeArrayShadow, vec4, float); - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"} - gvec4 textureGather(gsamplerCubeArray, vec4); - gvec4 textureGather(gsamplerCubeArray, vec4, int); - vec4 textureGather(samplerCubeArrayShadow, vec4, float); - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} - vec4 textureGather(sampler2DShadow, vec2); - vec4 textureGather(sampler2DShadow, vec2, float); - vec4 textureGather(sampler2DArrayShadow, vec3); - vec4 textureGather(sampler2DArrayShadow, vec3, float); - vec4 textureGather(samplerCubeShadow, vec3); - vec4 textureGather(samplerCubeShadow, vec3, float); - - GROUP BEGIN Offset {"queryFunction": true} - GROUP BEGIN NoComp {"queryFunction": true} - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} - gvec4 textureGatherOffset(gsampler2D, vec2, ivec2); - gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2); - vec4 textureGatherOffset(sampler2DShadow, vec2, float, ivec2); - vec4 textureGatherOffset(sampler2DArrayShadow, vec3, float, ivec2); - GROUP END NoComp - GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"} - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} - gvec4 textureGatherOffset(gsampler2D, vec2, ivec2, int); - gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2, int); - GROUP END Comp - GROUP END Offset - GROUP BEGIN Offsets {"queryFunction": true} - GROUP BEGIN NoComp {"queryFunction": true} - DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} - gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]); - gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]); - vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]); - vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]); - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "EXT_gpu_shader5, OES_gpu_shader5", "suffix": "Ext"} - gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]); - gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]); - vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]); - vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]); - GROUP END NoComp - GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"} - DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} - gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int); - gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int); - DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "EXT_gpu_shader5, OES_gpu_shader5", "suffix": "Ext"} - gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int); - gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int); - GROUP END Comp - GROUP END Offsets + GROUP BEGIN NoComp {"queryFunction": true} + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} + gvec4 textureGather(gsampler2D, vec2); + gvec4 textureGather(gsampler2DArray, vec3); + gvec4 textureGather(gsamplerCube, vec3); + DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} + gvec4 textureGather(gsamplerCubeArray, vec4); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"} + gvec4 textureGather(gsamplerCubeArray, vec4); + GROUP END NoComp + GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"} + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} + gvec4 textureGather(gsampler2D, vec2, int); + gvec4 textureGather(gsampler2DArray, vec3, int); + gvec4 textureGather(gsamplerCube, vec3, int); + DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} + gvec4 textureGather(gsamplerCubeArray, vec4, int); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"} + gvec4 textureGather(gsamplerCubeArray, vec4, int); + GROUP END Comp + GROUP BEGIN Ref {"queryFunction": true, "opSuffix": "Ref"} + DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} + vec4 textureGather(samplerCubeArrayShadow, vec4, float); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"} + vec4 textureGather(samplerCubeArrayShadow, vec4, float); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} + vec4 textureGather(sampler2DShadow, vec2, float); + vec4 textureGather(sampler2DArrayShadow, vec3, float); + vec4 textureGather(samplerCubeShadow, vec3, float); + GROUP END Ref + + GROUP BEGIN Offset {"queryFunction": true} + GROUP BEGIN NoComp {"queryFunction": true} + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} + gvec4 textureGatherOffset(gsampler2D, vec2, ivec2); + gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2); + GROUP END NoComp + GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"} + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} + gvec4 textureGatherOffset(gsampler2D, vec2, ivec2, int); + gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2, int); + GROUP END Comp + GROUP BEGIN Ref {"queryFunction": true, "opSuffix": "Ref"} + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS"} + vec4 textureGatherOffset(sampler2DShadow, vec2, float, ivec2); + vec4 textureGatherOffset(sampler2DArrayShadow, vec3, float, ivec2); + GROUP END Ref + GROUP END Offset + GROUP BEGIN Offsets {"queryFunction": true} + GROUP BEGIN NoComp {"queryFunction": true} + DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} + gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]); + gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "EXT_gpu_shader5, OES_gpu_shader5", "suffix": "Ext"} + gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]); + gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]); + GROUP END NoComp + GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"} + DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} + gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int); + gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "EXT_gpu_shader5, OES_gpu_shader5", "suffix": "Ext"} + gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int); + gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int); + GROUP END Comp + GROUP BEGIN Ref {"queryFunction": true, "opSuffix": "Ref"} + DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS"} + vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]); + vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]); + DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "essl_extension": "EXT_gpu_shader5, OES_gpu_shader5", "suffix": "Ext"} + vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]); + vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]); + GROUP END Ref + GROUP END Offsets GROUP END Gather GROUP BEGIN QueryLod {"shader_type": "FRAGMENT"} @@ -860,6 +875,8 @@ GROUP END MetalFragmentSample // MSL common functions GROUP BEGIN MetalCommon + DEFAULT METADATA {"essl_level": "ESSL_INTERNAL_BACKEND_BUILTINS", "hasSideEffects": true} + void loopForwardProgress(); DEFAULT METADATA {"essl_level": "ESSL_INTERNAL_BACKEND_BUILTINS"} genType saturate(genType); GROUP END MetalCommon diff --git a/src/compiler/translator/builtin_variables.json b/src/compiler/translator/builtin_variables.json index 3cf753ee1b0..0bf581843b5 100644 --- a/src/compiler/translator/builtin_variables.json +++ b/src/compiler/translator/builtin_variables.json @@ -60,7 +60,7 @@ }, "gl_DepthRange":{ "essl_level":"COMMON_BUILTINS", - "initDynamicType":"TType *{type_name} = new TType(gl_DepthRangeParameters, false); {type_name}->setQualifier(EvqUniform);" + "initDynamicType":"TType *{type_name} = new TType(gl_DepthRangeParameters, false); {type_name}->setQualifier(EvqDepthRange);" } }, "subgroups":{ @@ -73,7 +73,7 @@ "type":{ "basic":"Int", "precision":"Low", - "qualifier":"Uniform" + "qualifier":"NumSamples" } } } @@ -382,6 +382,42 @@ "qualifier":"Const" }, "value":"resources" + }, + "gl_ShadingRateFlag2VerticalPixelsEXT":{ + "essl_level":"ESSL3_1_BUILTINS", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"Const" + }, + "value":"resources" + }, + "gl_ShadingRateFlag4VerticalPixelsEXT":{ + "essl_level":"ESSL3_1_BUILTINS", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"Const" + }, + "value":"resources" + }, + "gl_ShadingRateFlag2HorizontalPixelsEXT":{ + "essl_level":"ESSL3_1_BUILTINS", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"Const" + }, + "value":"resources" + }, + "gl_ShadingRateFlag4HorizontalPixelsEXT":{ + "essl_level":"ESSL3_1_BUILTINS", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"Const" + }, + "value":"resources" } }, "subgroups":{ @@ -795,7 +831,7 @@ }, "gl_FragData":{ "essl_level":"ESSL1_BUILTINS", - "initDynamicType":"TType *{type_name} = new TType(EbtFloat, EbpMedium, EvqFragData, 4); if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC) {{ {type_name}->makeArray(resources.MaxDrawBuffers); }} else {{ {type_name}->makeArray(1u); }}" + "initDynamicType":"TType *{type_name} = new TType(EbtFloat, EbpMedium, EvqFragData, 4); if (spec != SH_WEBGL2_SPEC) {{ {type_name}->makeArray(resources.MaxDrawBuffers); }} else {{ {type_name}->makeArray(1u); }}" }, "gl_FragDepth":{ "essl_level":"ESSL3_BUILTINS", @@ -852,7 +888,11 @@ "gl_FragDepthEXT":{ "essl_level":"ESSL1_BUILTINS", "essl_extension":"EXT_frag_depth", - "initDynamicType":"TType *{type_name} = new TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1);" + "type": { + "basic":"Float", + "precision":"High", + "qualifier":"FragDepth" + } } } }, @@ -865,26 +905,6 @@ } } }, - "NVShaderFramebufferFetch":{ - "variables":{ - "gl_LastFragColor":{ - "essl_level":"ESSL1_BUILTINS", - "essl_extension":"NV_shader_framebuffer_fetch", - "type":{ - "basic":"Float", - "precision":"Medium", - "qualifier":"LastFragColor", - "primarySize":4 - } - }, - "gl_LastFragData":{ - "essl_level":"ESSL1_BUILTINS", - "suffix":"NV", - "essl_extension":"NV_shader_framebuffer_fetch", - "initDynamicType":"TType *{type_name} = new TType(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); {type_name}->makeArray(resources.MaxDrawBuffers);" - } - } - }, "ARMShaderFramebufferFetch":{ "variables":{ "gl_LastFragColorARM":{ @@ -946,6 +966,19 @@ } } }, + "EXTFragmentShadingRate":{ + "variables":{ + "gl_ShadingRateEXT":{ + "essl_level":"ESSL3_1_BUILTINS", + "essl_extension":"EXT_fragment_shading_rate", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"ShadingRateEXT" + } + } + } + }, "OESSampleVariables":{ "variables":{ "gl_SampleID":{ @@ -1091,7 +1124,7 @@ "type":{ "basic":"Int", "precision":"High", - "qualifier":"Uniform" + "qualifier":"BaseVertex" } }, "gl_BaseInstance":{ @@ -1100,25 +1133,7 @@ "type":{ "basic":"Int", "precision":"High", - "qualifier":"Uniform" - } - }, - "angle_BaseVertex":{ - "essl_level":"COMMON_BUILTINS", - "essl_extension":"ANGLE_base_vertex_base_instance_shader_builtin", - "type":{ - "basic":"Int", - "precision":"High", - "qualifier":"Uniform" - } - }, - "angle_BaseInstance":{ - "essl_level":"COMMON_BUILTINS", - "essl_extension":"ANGLE_base_vertex_base_instance_shader_builtin", - "type":{ - "basic":"Int", - "precision":"High", - "qualifier":"Uniform" + "qualifier":"BaseInstance" } } } @@ -1134,6 +1149,19 @@ "suffix": "APPLE" } } + }, + "EXTFragmentShadingRatePrimitive":{ + "variables":{ + "gl_PrimitiveShadingRateEXT":{ + "essl_level":"ESSL3_1_BUILTINS", + "essl_extension":"EXT_fragment_shading_rate_primitive", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"PrimitiveShadingRateEXT" + } + } + } } } }, @@ -1198,6 +1226,18 @@ "GeometryShader":{ "shader_type": "GEOMETRY_EXT", "variables":{ + "gl_Position":{ + "suffix":"GS", + "essl_level":"ESSL3_1_BUILTINS", + "essl_extension":"EXT_geometry_shader, OES_geometry_shader", + "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", + "type":{ + "basic":"Float", + "precision":"High", + "qualifier":"Position", + "primarySize":4 + } + }, "gl_PrimitiveIDIn":{ "essl_level":"ESSL3_1_BUILTINS", "essl_extension":"EXT_geometry_shader, OES_geometry_shader", @@ -1260,34 +1300,15 @@ "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", "initDynamicType":"TType *{type_name} = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); {type_name}->makeArray(0u);", "comment":"The array size of gl_in is undefined until we get a valid input primitive declaration." - } - }, - "subgroups":{ - "Out":{ - "variables":{ - "gl_PerVertex":{ - "suffix":"OutBlock", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_geometry_shader, OES_geometry_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "private":true, - "class":"TInterfaceBlock", - "fields":{ - "gl_Position":{ - "basic":"Float", - "precision":"High", - "qualifier":"Position", - "primarySize":4 - } - } - }, - "gl_Position":{ - "suffix":"GS", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_geometry_shader, OES_geometry_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "initDynamicType":"TType *{type_name} = new TType(EbtFloat, EbpHigh, EvqPosition, 4); {type_name}->setInterfaceBlock(gl_PerVertexOutBlock{ext_or_core_suffix});" - } + }, + "gl_PrimitiveShadingRateEXT":{ + "suffix":"GS", + "essl_level":"ESSL3_1_BUILTINS", + "essl_extension":"EXT_fragment_shading_rate_primitive", + "type":{ + "basic":"Int", + "precision":"Medium", + "qualifier":"PrimitiveShadingRateEXT" } } } @@ -1380,33 +1401,6 @@ } }, "subgroups":{ - "Out":{ - "variables":{ - "gl_PerVertex":{ - "suffix":"OutTcsBlock", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "private":true, - "class":"TInterfaceBlock", - "fields":{ - "gl_Position":{ - "basic":"Float", - "precision":"High", - "qualifier":"Position", - "primarySize":4 - } - } - }, - "gl_Position":{ - "suffix":"TCS", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "initDynamicType":"TType *{type_name} = new TType(EbtFloat, EbpHigh, EvqPosition, 4); {type_name}->setInterfaceBlock(gl_PerVertexOutTcsBlock{ext_or_core_suffix});" - } - } - }, "EXTPrimitiveBoundingBox":{ "variables":{ "gl_BoundingBoxEXT":{ @@ -1434,6 +1428,18 @@ "TessellationEvaluationShader":{ "shader_type": "TESS_EVALUATION_EXT", "variables":{ + "gl_Position":{ + "suffix":"TES", + "essl_level":"ESSL3_1_BUILTINS", + "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", + "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", + "type":{ + "basic":"Float", + "precision":"High", + "qualifier":"Position", + "primarySize":4 + } + }, "gl_PatchVerticesIn":{ "suffix":"TES", "essl_level":"ESSL3_1_BUILTINS", @@ -1500,42 +1506,6 @@ "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", "initDynamicType":"TType *{type_name} = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); {type_name}->makeArray(resources.MaxPatchVertices);" - }, - "gl_out":{ - "suffix":"TES", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "initDynamicType":"TType *{type_name} = new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); {type_name}->makeArray(resources.MaxPatchVertices);" - } - }, - "subgroups":{ - "Out":{ - "variables":{ - "gl_PerVertex":{ - "suffix":"OutTesBlock", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "private":true, - "class":"TInterfaceBlock", - "fields":{ - "gl_Position":{ - "basic":"Float", - "precision":"High", - "qualifier":"Position", - "primarySize":4 - } - } - }, - "gl_Position":{ - "suffix":"TES", - "essl_level":"ESSL3_1_BUILTINS", - "essl_extension":"EXT_tessellation_shader, OES_tessellation_shader", - "essl_extension_becomes_core_in":"ESSL3_2_BUILTINS", - "initDynamicType":"TType *{type_name} = new TType(EbtFloat, EbpHigh, EvqPosition, 4); {type_name}->setInterfaceBlock(gl_PerVertexOutTesBlock{ext_or_core_suffix});" - } - } } } }, diff --git a/src/compiler/translator/gen_builtin_symbols.py b/src/compiler/translator/gen_builtin_symbols.py index cda458a1038..a737da720e8 100755 --- a/src/compiler/translator/gen_builtin_symbols.py +++ b/src/compiler/translator/gen_builtin_symbols.py @@ -590,7 +590,6 @@ class TSymbolTableBase 'SamplerBuffer', 'SamplerCubeArray', 'SamplerCubeArrayShadow', - 'Sampler2DRectShadow', 'ISampler2DRect', 'ISamplerBuffer', 'ISamplerCubeArray', @@ -602,28 +601,19 @@ class TSymbolTableBase 'Image3D', 'Image2DArray', 'ImageCube', - 'Image2DMS', - 'Image2DMSArray', 'ImageCubeArray', - 'ImageRect', 'ImageBuffer', 'IImage2D', 'IImage3D', 'IImage2DArray', 'IImageCube', - 'IImage2DMS', - 'IImage2DMSArray', 'IImageCubeArray', - 'IImageRect', 'IImageBuffer', 'UImage2D', 'UImage3D', 'UImage2DArray', 'UImageCube', - 'UImage2DMS', - 'UImage2DMSArray', 'UImageCubeArray', - 'UImageRect', 'UImageBuffer', 'PixelLocalANGLE', 'IPixelLocalANGLE', @@ -1434,13 +1424,12 @@ def gen_function_variants(function_props): function_variants.append(function_props) return function_variants - # If we have image_params then we're generating variants for 33 separate functions, + # If we have image_params then we're generating variants for multiple separate functions, # each for a different type of image variable if 'image_params' in gen_type: variants = [['gimage2D', 'ivec2'], ['gimage3D', 'ivec3'], ['gimageCube', 'ivec3'], ['gimageBuffer', 'int'], ['gimage2DArray', 'ivec3'], - ['gimageCubeArray', 'ivec3'], ['gimageRect', 'ivec2'], - ['gimage2DMS', 'ivec2', 'int'], ['gimage2DMSArray', 'ivec3', 'int']] + ['gimageCubeArray', 'ivec3']] for variant in variants: image_variant_parameters = [] for param in parameters: diff --git a/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.cpp b/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.cpp index 8835dc311f5..a35456bf560 100644 --- a/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.cpp +++ b/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.cpp @@ -23,52 +23,6 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e } } -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - // isnan() is supported since GLSL 1.3. - if (targetGLSLVersion < GLSL_VERSION_130) - return; - - // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. - emu->addEmulatedFunction( - BuiltInId::isnan_Float1, - "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); - emu->addEmulatedFunction( - BuiltInId::isnan_Float2, - "bvec2 isnan_emu(vec2 x)\n" - "{\n" - " bvec2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - BuiltInId::isnan_Float3, - "bvec3 isnan_emu(vec3 x)\n" - "{\n" - " bvec3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - BuiltInId::isnan_Float4, - "bvec4 isnan_emu(vec4 x)\n" - "{\n" - " bvec4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); -} - void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) { emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1, diff --git a/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.h b/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.h index 59dfa1559b8..bd0f3498d0a 100644 --- a/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.h +++ b/src/compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.h @@ -20,11 +20,6 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e sh::GLenum shaderType); // -// This works around isnan() bug in Intel Mac drivers -// -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); -// // This works around atan(y, x) bug in NVIDIA drivers. // void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu); diff --git a/src/compiler/translator/glsl/OutputESSL.cpp b/src/compiler/translator/glsl/OutputESSL.cpp index 41bf2665cdc..e7f64ad503a 100644 --- a/src/compiler/translator/glsl/OutputESSL.cpp +++ b/src/compiler/translator/glsl/OutputESSL.cpp @@ -20,11 +20,6 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision) if (precision == EbpUndefined) return false; - if (precision == EbpHigh && !isHighPrecisionSupported()) - { - precision = EbpMedium; - } - TInfoSinkBase &out = objSink(); out << getPrecisionString(precision); return true; @@ -44,8 +39,11 @@ ImmutableString TOutputESSL::translateTextureFunction(const ImmutableString &nam } else { - // Default translating textureVideoWEBGL to texture2D. - return ImmutableString("texture2D"); + // For ESSL 300+ (ES 3.0+), use "texture" instead of "texture2D" to match the + // translation of samplerVideoWEBGL to sampler2D and the ESSL version's texture + // function naming. ESSL 100 (ES 2.0) still uses texture2D. + return (getShaderVersion() >= 300) ? ImmutableString("texture") + : ImmutableString("texture2D"); } } diff --git a/src/compiler/translator/glsl/OutputGLSL.cpp b/src/compiler/translator/glsl/OutputGLSL.cpp index 01e6b6acaed..3da333a5b7d 100644 --- a/src/compiler/translator/glsl/OutputGLSL.cpp +++ b/src/compiler/translator/glsl/OutputGLSL.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/glsl/OutputGLSL.h" #include "compiler/translator/Compiler.h" @@ -75,8 +79,10 @@ ImmutableString TOutputGLSL::translateTextureFunction(const ImmutableString &nam } else { - // Default translating textureVideoWEBGL to texture2D. - return ImmutableString("texture2D"); + // For GLSL 130+, use "texture" instead of "texture2D" to match the translation + // of samplerVideoWEBGL to sampler2D and the GLSL version's texture function naming. + return sh::IsGLSL130OrNewer(getShaderOutput()) ? ImmutableString("texture") + : ImmutableString("texture2D"); } } diff --git a/src/compiler/translator/glsl/OutputGLSLBase.cpp b/src/compiler/translator/glsl/OutputGLSLBase.cpp index 3f005cf1417..437a7763897 100644 --- a/src/compiler/translator/glsl/OutputGLSLBase.cpp +++ b/src/compiler/translator/glsl/OutputGLSLBase.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/glsl/OutputGLSLBase.h" #include "angle_gl.h" @@ -87,12 +91,13 @@ TOutputGLSLBase::TOutputGLSLBase(TCompiler *compiler, : TIntermTraverser(true, true, true, &compiler->getSymbolTable()), mObjSink(objSink), mDeclaringVariable(false), + mSkippedDeclaringAnonymousStruct(false), mHashFunction(compiler->getHashFunction()), + mUserVariablePrefix(compiler->getUserVariableNamePrefix()), mNameMap(compiler->getNameMap()), mShaderType(compiler->getShaderType()), mShaderVersion(compiler->getShaderVersion()), mOutput(compiler->getOutputType()), - mHighPrecisionSupported(compiler->isHighPrecisionSupported()), // If pixel local storage introduces new fragment outputs, we are now required to specify a // location for _all_ fragment outputs, including previously valid outputs that had an // implicit location of zero. @@ -460,8 +465,30 @@ void TOutputGLSLBase::writeVariableType(const TType &type, out << getMemoryQualifiers(type); } - // Declare the struct. - if (type.isStructSpecifier()) + // Declare the struct. If this is an anonymous struct that's separated from its declaration, + // don't declare it independently, but put it together back with the variable that declared it. + // That would look like for example: + // + // out struct + // { + // ... + // } variable; + const bool isStruct = type.getStruct() != nullptr; + const bool isAnonymousStruct = isStruct && type.getStruct()->isNameless(); + const bool isAnonymousStructDeclaration = + isAnonymousStruct && symbol->symbolType() == SymbolType::Empty; + const bool isNamedStructDeclaration = type.isStructSpecifier() && !isAnonymousStruct; + ASSERT(!isAnonymousStructDeclaration || type.isStructSpecifier()); + // Declare struct if: + // + // * It's named (regardless of standalone or part of variable declaration) + // * It's anonymous, but this is the variable declaration. Generate the struct as part of the + // variable declaration, and don't give it a name. + const bool shouldDeclareStruct = + isStruct && + (isNamedStructDeclaration || (isAnonymousStruct && !isAnonymousStructDeclaration)); + mSkippedDeclaringAnonymousStruct = isAnonymousStructDeclaration; + if (shouldDeclareStruct) { const TStructure *structure = type.getStruct(); @@ -471,7 +498,7 @@ void TOutputGLSLBase::writeVariableType(const TType &type, { declareInterfaceBlock(type); } - else + else if (!isAnonymousStructDeclaration) { if (writeVariablePrecision(type.getPrecision())) out << " "; @@ -689,7 +716,12 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpIndexDirectInterfaceBlock: if (visit == InVisit) { - out << "."; + if (node->getLeft()->getAsSymbolNode() == nullptr || + node->getLeft()->getAsSymbolNode()->variable().symbolType() != + SymbolType::Empty) + { + out << "."; + } const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); @@ -901,8 +933,11 @@ bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node) curNode->traverse(this); - if (isSingleStatement(curNode)) + if (isSingleStatement(curNode) && !mSkippedDeclaringAnonymousStruct) + { out << ";\n"; + } + mSkippedDeclaringAnonymousStruct = false; } // Scope the blocks except when at the global scope. @@ -1156,12 +1191,12 @@ ImmutableString TOutputGLSLBase::getTypeName(const TType &type) return ImmutableString("sampler2D"); } - return GetTypeName(type, mHashFunction, &mNameMap); + return GetTypeName(type, mUserVariablePrefix, mHashFunction, &mNameMap); } ImmutableString TOutputGLSLBase::hashName(const TSymbol *symbol) { - return HashName(symbol, mHashFunction, &mNameMap); + return HashName(symbol, mUserVariablePrefix, mHashFunction, &mNameMap); } ImmutableString TOutputGLSLBase::hashFieldName(const TField *field) @@ -1169,7 +1204,7 @@ ImmutableString TOutputGLSLBase::hashFieldName(const TField *field) ASSERT(field->symbolType() != SymbolType::Empty); if (field->symbolType() == SymbolType::UserDefined) { - return HashName(field->name(), mHashFunction, &mNameMap); + return HashName(field->name(), mUserVariablePrefix, mHashFunction, &mNameMap); } return field->name(); @@ -1193,7 +1228,9 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure) out << "struct "; - if (structure->symbolType() != SymbolType::Empty) + // Keep nameless structs nameless, because they may need to match with another shader + // stage (for example if used to declare a varying). + if (structure->symbolType() != SymbolType::Empty && !structure->isNameless()) { out << hashName(structure) << " "; } diff --git a/src/compiler/translator/glsl/OutputGLSLBase.h b/src/compiler/translator/glsl/OutputGLSLBase.h index ffeb51dcd27..ebaaa5c87de 100644 --- a/src/compiler/translator/glsl/OutputGLSLBase.h +++ b/src/compiler/translator/glsl/OutputGLSLBase.h @@ -90,7 +90,7 @@ class TOutputGLSLBase : public TIntermTraverser const char *mapQualifierToString(TQualifier qualifier); sh::GLenum getShaderType() const { return mShaderType; } - bool isHighPrecisionSupported() const { return mHighPrecisionSupported; } + int getShaderVersion() const { return mShaderVersion; } const char *getIndentPrefix(int extraIndentDepth = 0); bool needsToWriteLayoutQualifier(const TType &type); @@ -105,17 +105,17 @@ class TOutputGLSLBase : public TIntermTraverser TInfoSinkBase &mObjSink; bool mDeclaringVariable; + bool mSkippedDeclaringAnonymousStruct; // name hashing. ShHashFunction64 mHashFunction; + char mUserVariablePrefix; NameMap &mNameMap; sh::GLenum mShaderType; const int mShaderVersion; ShShaderOutput mOutput; - bool mHighPrecisionSupported; - // Emit "layout(locaton = 0)" for fragment outputs whose location is unspecified. This is for // transformations like pixel local storage, where new outputs are introduced to the shader, and // previously valid fragment outputs with an implicit location of 0 are now required to specify diff --git a/src/compiler/translator/glsl/TranslatorESSL.cpp b/src/compiler/translator/glsl/TranslatorESSL.cpp index 0742e526ba9..40cde54ab14 100644 --- a/src/compiler/translator/glsl/TranslatorESSL.cpp +++ b/src/compiler/translator/glsl/TranslatorESSL.cpp @@ -12,6 +12,7 @@ #include "compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.h" #include "compiler/translator/glsl/OutputESSL.h" #include "compiler/translator/tree_ops/DeclarePerVertexBlocks.h" +#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" #include "compiler/translator/tree_ops/RecordConstantPrecision.h" #include "compiler/translator/tree_util/FindSymbolNode.h" #include "compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h" @@ -110,6 +111,15 @@ bool TranslatorESSL::translate(TIntermBlock *root, return false; } + // anglebug.com/42265954: The ESSL spec has a bug with images as function arguments. The + // recommended workaround is to inline functions that accept image arguments. + if (shaderVer >= 310 && !MonomorphizeUnsupportedFunctions( + this, root, &getSymbolTable(), + UnsupportedFunctionArgsBitSet{UnsupportedFunctionArgs::Image})) + { + return false; + } + // Write emulated built-in functions if needed. if (!getBuiltInFunctionEmulator().isOutputEmpty()) { @@ -239,13 +249,7 @@ void TranslatorESSL::writeExtensionBehavior(const ShCompileOptions &compileOptio { const bool isMultiview = (iter->first == TExtension::OVR_multiview) || (iter->first == TExtension::OVR_multiview2); - if (getResources().NV_shader_framebuffer_fetch && - iter->first == TExtension::EXT_shader_framebuffer_fetch) - { - sink << "#extension GL_NV_shader_framebuffer_fetch : " - << GetBehaviorString(iter->second) << "\n"; - } - else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers) + if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers) { sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second) << "\n"; diff --git a/src/compiler/translator/glsl/TranslatorGLSL.cpp b/src/compiler/translator/glsl/TranslatorGLSL.cpp index 01dd4bf8074..d9ad9cbc7da 100644 --- a/src/compiler/translator/glsl/TranslatorGLSL.cpp +++ b/src/compiler/translator/glsl/TranslatorGLSL.cpp @@ -11,10 +11,10 @@ #include "compiler/translator/glsl/ExtensionGLSL.h" #include "compiler/translator/glsl/OutputGLSL.h" #include "compiler/translator/glsl/VersionGLSL.h" +#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" #include "compiler/translator/tree_ops/PreTransformTextureCubeGradDerivatives.h" #include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h" #include "compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.h" -#include "compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h" namespace sh { @@ -31,11 +31,6 @@ void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); } - if (compileOptions.emulateIsnanFloatFunction) - { - InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion()); - } - if (compileOptions.emulateAtan2FloatFunction) { InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); @@ -104,17 +99,19 @@ bool TranslatorGLSL::translate(TIntermBlock *root, } } - if (compileOptions.rewriteTexelFetchOffsetToTexelFetch) + // anglebug.com/42265954: The ESSL spec has a bug with images as function arguments. The + // recommended workaround is to inline functions that accept image arguments. + if (getShaderVersion() >= 310 && + !MonomorphizeUnsupportedFunctions( + this, root, &getSymbolTable(), + UnsupportedFunctionArgsBitSet{UnsupportedFunctionArgs::Image})) { - if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion())) - { - return false; - } + return false; } - if (compileOptions.rewriteFloatUnaryMinusOperator) + if (compileOptions.rewriteTexelFetchOffsetToTexelFetch) { - if (!sh::RewriteUnaryMinusOperatorFloat(this, root)) + if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion())) { return false; } diff --git a/src/compiler/translator/glslang.l b/src/compiler/translator/glslang.l index 02df51f347b..efc341f799f 100644 --- a/src/compiler/translator/glslang.l +++ b/src/compiler/translator/glslang.l @@ -115,7 +115,7 @@ static int ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2(TParseContext *c static int WEBGL_video_texture_extension(TParseContext *context, int token); static int uint_constant(TParseContext *context); static int int_constant(TParseContext *context); -static int float_constant(yyscan_t yyscanner); +static int float_constant(TParseContext* context, yyscan_t yyscanner); static int floatsuffix_check(TParseContext* context); static int yuvcscstandardext_constant(TParseContext *context); %} @@ -405,9 +405,9 @@ O [0-7] 0{O}+[uU] { return uint_constant(context); } {D}+[uU] { return uint_constant(context); } -{D}+{E} { return float_constant(yyscanner); } -{D}+"."{D}*({E})? { return float_constant(yyscanner); } -"."{D}+({E})? { return float_constant(yyscanner); } +{D}+{E} { return float_constant(context, yyscanner); } +{D}+"."{D}*({E})? { return float_constant(context, yyscanner); } +"."{D}+({E})? { return float_constant(context, yyscanner); } {D}+{E}[fF] { return floatsuffix_check(context); } {D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); } @@ -863,7 +863,7 @@ int floatsuffix_check(TParseContext* context) std::string text = yytext; text.resize(text.size() - 1); - if (!strtof_clamp(text, &(yylval->lex.f))) + if (!strtof_clamp(text, &(yylval->lex.f), context->getCompileOptions().preserveDenorms)) yyextra->warning(*yylloc, "Float overflow", yytext); return(FLOATCONSTANT); @@ -888,10 +888,10 @@ int int_constant(TParseContext *context) { return INTCONSTANT; } -int float_constant(yyscan_t yyscanner) { +int float_constant(TParseContext* context, yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - if (!strtof_clamp(yytext, &(yylval->lex.f))) + if (!strtof_clamp(yytext, &(yylval->lex.f), context->getCompileOptions().preserveDenorms)) yyextra->warning(*yylloc, "Float overflow", yytext); return FLOATCONSTANT; } @@ -943,9 +943,7 @@ int glslang_scan(size_t count, const char* const string[], const int length[], if (!preprocessor->init(count, string, length)) return 1; - if (context->getFragmentPrecisionHigh()) - preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - + preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); return 0; diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y index b8c7adcd254..d75ed93781e 100644 --- a/src/compiler/translator/glslang.y +++ b/src/compiler/translator/glslang.y @@ -513,8 +513,10 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2); + | logical_and_expression AND_OP { + context->onShortCircuitAndBegin($1, @2); + } inclusive_or_expression { + $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $4, @2); } ; @@ -527,15 +529,21 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } - | logical_or_expression OR_OP logical_xor_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2); + | logical_or_expression OR_OP { + context->onShortCircuitOrBegin($1, @2); + } logical_xor_expression { + $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $4, @2); } ; conditional_expression : logical_or_expression { $$ = $1; } - | logical_or_expression QUESTION expression COLON assignment_expression { - $$ = context->addTernarySelection($1, $3, $5, @2); + | logical_or_expression QUESTION { + context->onTernaryConditionParsed($1, @2); + } expression COLON { + context->onTernaryTrueExpressionParsed($4, @2); + } assignment_expression { + $$ = context->addTernarySelection($1, $4, $7, @2); } ; @@ -582,8 +590,10 @@ expression : assignment_expression { $$ = $1; } - | expression COMMA assignment_expression { - $$ = context->addComma($1, $3, @2); + | expression COMMA { + context->onCommaLeftHandSideParsed($1); + } assignment_expression { + $$ = context->addComma($1, $4, @2); } ; @@ -657,7 +667,7 @@ function_header_with_parameters $$ = $1; if ($2.type.getBasicType() != EbtVoid) { - $1->addParameter($2.createVariable(&context->symbolTable)); + context->addParameter($1, &$2); } else { @@ -682,7 +692,7 @@ function_header_with_parameters // (void, non_void) parameters. context->error(@2, "cannot be a parameter type except for '(void)'", "void"); } - $1->addParameter($3.createVariable(&context->symbolTable)); + context->addParameter($1, &$3); } } ; @@ -1537,7 +1547,7 @@ compound_statement_with_scope $$ = new TIntermBlock(); $$->setLine(@$); } - | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { + | LEFT_BRACE { context->beginNestedScope(); } statement_list { context->endNestedScope(); } RIGHT_BRACE { $3->setLine(@$); $$ = $3; } @@ -1545,12 +1555,19 @@ compound_statement_with_scope statement_no_new_scope : compound_statement_no_new_scope { $$ = $1; } - | simple_statement { $$ = $1; } + | simple_statement { + context->endStatementWithValue($1); + $$ = $1; + } ; statement_with_scope - : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; } - | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; } + : { context->beginNestedScope(); } compound_statement_no_new_scope { context->endNestedScope(); $$ = $2; } + | { context->beginNestedScope(); } simple_statement { + context->endStatementWithValue($2); + context->endNestedScope(); + $$ = $2; + } ; compound_statement_no_new_scope @@ -1585,17 +1602,24 @@ expression_statement ; selection_statement - : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - $$ = context->addIfElse($3, $5, @1); + : IF LEFT_PAREN expression RIGHT_PAREN { + context->onIfTrueBlockBegin($3, @1); + } selection_rest_statement { + $$ = context->addIfElse($3, $6, @1); } ; selection_rest_statement - : statement_with_scope ELSE statement_with_scope { + : statement_with_scope ELSE { + context->onIfTrueBlockEnd(); + context->onIfFalseBlockBegin(); + } statement_with_scope { + context->onIfFalseBlockEnd(); $$.node1 = $1; - $$.node2 = $3; + $$.node2 = $4; } | statement_with_scope { + context->onIfTrueBlockEnd(); $$.node1 = $1; $$.node2 = nullptr; } @@ -1604,9 +1628,8 @@ selection_rest_statement // Note that we've diverged from the spec grammar here a bit for the sake of simplicity. // We're reusing compound_statement_with_scope instead of having separate rules for switch. switch_statement - : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(@1); } compound_statement_with_scope { + : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->beginSwitch(@1, $3); } compound_statement_no_new_scope { $$ = context->addSwitch($3, $6, @1); - context->decrSwitchNestingLevel(); } ; @@ -1630,24 +1653,34 @@ condition ; iteration_statement - : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(@1); } condition RIGHT_PAREN statement_no_new_scope { + : WHILE LEFT_PAREN { + context->symbolTable.push(); context->beginLoop(ELoopWhile, @1); + context->onLoopConditionBegin(nullptr, @1); + } condition { + context->onLoopConditionEnd($4, @4); + } RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->addLoop(ELoopWhile, 0, $4, 0, $6, @1); - context->decrLoopNestingLevel(); - } - | DO { context->incrLoopNestingLevel(@1); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); - context->decrLoopNestingLevel(); - } - | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(@1); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { + $$ = context->addLoop(ELoopWhile, 0, $4, 0, $7, @1); + } + | DO { + context->beginLoop(ELoopDoWhile, @1); + context->onDoLoopBegin(); + } statement_with_scope WHILE LEFT_PAREN { + context->onDoLoopConditionBegin(); + } expression RIGHT_PAREN SEMICOLON { + $$ = context->addLoop(ELoopDoWhile, 0, $7, 0, $3, @4); + } + | FOR LEFT_PAREN { context->symbolTable.push(); context->beginLoop(ELoopFor, @1); } for_init_statement { + context->onLoopConditionBegin($4, @4); + } for_rest_statement RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->addLoop(ELoopFor, $4, $5.node1, reinterpret_cast($5.node2), $7, @1); - context->decrLoopNestingLevel(); + $$ = context->addLoop(ELoopFor, $4, $6.node1, reinterpret_cast($6.node2), $8, @1); } ; for_init_statement : expression_statement { + context->endStatementWithValue($1); $$ = $1; } | declaration_statement { @@ -1666,12 +1699,17 @@ conditionopt for_rest_statement : conditionopt SEMICOLON { + context->onLoopConditionEnd($1, @1); + context->onLoopContinueEnd(nullptr, @1); $$.node1 = $1; $$.node2 = 0; } - | conditionopt SEMICOLON expression { + | conditionopt SEMICOLON { + context->onLoopConditionEnd($1, @1); + } expression { + context->onLoopContinueEnd($4, @4); $$.node1 = $1; - $$.node2 = $3; + $$.node2 = $4; } ; diff --git a/src/compiler/translator/glslang_lex_autogen.cpp b/src/compiler/translator/glslang_lex_autogen.cpp index 607c76438aa..6668b80f033 100644 --- a/src/compiler/translator/glslang_lex_autogen.cpp +++ b/src/compiler/translator/glslang_lex_autogen.cpp @@ -978,7 +978,7 @@ static int ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2(TParseContext *c static int WEBGL_video_texture_extension(TParseContext *context, int token); static int uint_constant(TParseContext *context); static int int_constant(TParseContext *context); -static int float_constant(yyscan_t yyscanner); +static int float_constant(TParseContext *context, yyscan_t yyscanner); static int floatsuffix_check(TParseContext *context); static int yuvcscstandardext_constant(TParseContext *context); @@ -1236,13 +1236,19 @@ YY_DECL #endif if (!yyg->yy_start) + { yyg->yy_start = 1; /* first start state */ + } if (!yyin) + { yyin = stdin; + } if (!yyout) + { yyout = stdout; + } if (!YY_CURRENT_BUFFER) { @@ -1283,7 +1289,9 @@ YY_DECL { yy_current_state = (int)yy_def[yy_current_state]; if (yy_current_state >= 982) + { yy_c = yy_meta[yy_c]; + } } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; @@ -1300,13 +1308,17 @@ YY_DECL { int yyl; for (yyl = 0; yyl < yyleng; ++yyl) + { if (yytext[yyl] == '\n') + { do { yylineno++; yycolumn = 0; } while (0); + } + } } do_action: /* This label is used only to access EOF actions. */ @@ -2314,19 +2326,19 @@ YY_DECL case 203: YY_RULE_SETUP { - return float_constant(yyscanner); + return float_constant(context, yyscanner); } YY_BREAK case 204: YY_RULE_SETUP { - return float_constant(yyscanner); + return float_constant(context, yyscanner); } YY_BREAK case 205: YY_RULE_SETUP { - return float_constant(yyscanner); + return float_constant(context, yyscanner); } YY_BREAK case 206: @@ -2728,6 +2740,7 @@ YY_DECL } else + { switch (yy_get_next_buffer(yyscanner)) { case EOB_ACT_END_OF_FILE: @@ -2754,7 +2767,9 @@ YY_DECL else { if (!yyg->yy_did_buffer_switch_on_eof) + { YY_NEW_FILE; + } } break; } @@ -2778,15 +2793,16 @@ YY_DECL yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } + } break; } default: YY_FATAL_ERROR("fatal flex scanner internal error--no action found"); } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of yylex */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -2804,7 +2820,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) int ret_val; if (yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1]) + { YY_FATAL_ERROR("fatal flex scanner internal error--end of buffer missed"); + } if (YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0) { /* Don't try to fill the buffer, so this is an EOF. */ @@ -2831,13 +2849,17 @@ static int yy_get_next_buffer(yyscan_t yyscanner) number_to_move = (int)(yyg->yy_c_buf_p - yyg->yytext_ptr - 1); for (i = 0; i < number_to_move; ++i) + { *(dest++) = *(source++); + } if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING) + { /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + } else { @@ -2856,20 +2878,28 @@ static int yy_get_next_buffer(yyscan_t yyscanner) int new_size = b->yy_buf_size * 2; if (new_size <= 0) + { b->yy_buf_size += b->yy_buf_size / 8; + } else + { b->yy_buf_size *= 2; + } b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *)b->yy_ch_buf, (yy_size_t)(b->yy_buf_size + 2), yyscanner); } else + { /* Can't grow it, we don't own it. */ b->yy_ch_buf = NULL; + } if (!b->yy_ch_buf) + { YY_FATAL_ERROR("fatal error - scanner input buffer overflow"); + } yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; @@ -2877,7 +2907,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) } if (num_to_read > YY_READ_BUF_SIZE) + { num_to_read = YY_READ_BUF_SIZE; + } /* Read in more data. */ yy_size_t ret = 0; @@ -2900,10 +2932,12 @@ static int yy_get_next_buffer(yyscan_t yyscanner) ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } - } + } else + { ret_val = EOB_ACT_CONTINUE_SCAN; + } if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { @@ -2912,7 +2946,9 @@ static int yy_get_next_buffer(yyscan_t yyscanner) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *)yyrealloc( (void *)YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t)new_size, yyscanner); if (!YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + { YY_FATAL_ERROR("out of dynamic memory in yy_get_next_buffer()"); + } /* "- 2" to take care of EOB's */ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int)(new_size - 2); } @@ -2948,7 +2984,9 @@ static yy_state_type yy_get_previous_state(yyscan_t yyscanner) { yy_current_state = (int)yy_def[yy_current_state]; if (yy_current_state >= 982) + { yy_c = yy_meta[yy_c]; + } } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } @@ -2978,7 +3016,9 @@ static yy_state_type yy_try_NUL_trans(yy_state_type yy_current_state, yyscan_t y { yy_current_state = (int)yy_def[yy_current_state]; if (yy_current_state >= 982) + { yy_c = yy_meta[yy_c]; + } } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 981); @@ -3011,8 +3051,10 @@ static int input(yyscan_t yyscanner) * valid NUL; if not, then we've hit the end of the buffer. */ if (yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]) + { /* This was really a NUL. */ *yyg->yy_c_buf_p = '\0'; + } else { /* need more input */ @@ -3040,10 +3082,14 @@ static int input(yyscan_t yyscanner) case EOB_ACT_END_OF_FILE: { if (yywrap(yyscanner)) + { return 0; + } if (!yyg->yy_did_buffer_switch_on_eof) + { YY_NEW_FILE; + } # ifdef __cplusplus return yyinput(yyscanner); # else @@ -3063,12 +3109,14 @@ static int input(yyscan_t yyscanner) yyg->yy_hold_char = *++yyg->yy_c_buf_p; if (c == '\n') + { do { yylineno++; yycolumn = 0; } while (0); + } return c; } @@ -3108,7 +3156,9 @@ void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) */ yyensure_buffer_stack(yyscanner); if (YY_CURRENT_BUFFER == new_buffer) + { return; + } if (YY_CURRENT_BUFFER) { @@ -3150,7 +3200,9 @@ YY_BUFFER_STATE yy_create_buffer(FILE *file, int size, yyscan_t yyscanner) b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state), yyscanner); if (!b) + { YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + } b->yy_buf_size = size; @@ -3159,7 +3211,9 @@ YY_BUFFER_STATE yy_create_buffer(FILE *file, int size, yyscan_t yyscanner) */ b->yy_ch_buf = (char *)yyalloc((yy_size_t)(b->yy_buf_size + 2), yyscanner); if (!b->yy_ch_buf) + { YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + } b->yy_is_our_buffer = 1; @@ -3177,13 +3231,19 @@ void yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!b) + { return; + } if (b == YY_CURRENT_BUFFER) /* Not sure if we should pop here. */ + { YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE)0; + } if (b->yy_is_our_buffer) + { yyfree((void *)b->yy_ch_buf, yyscanner); + } yyfree((void *)b, yyscanner); } @@ -3226,7 +3286,9 @@ void yy_flush_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!b) + { return; + } b->yy_n_chars = 0; @@ -3243,7 +3305,9 @@ void yy_flush_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) b->yy_buffer_status = YY_BUFFER_NEW; if (b == YY_CURRENT_BUFFER) + { yy_load_buffer_state(yyscanner); + } } /** Pushes the new state onto the stack. The new state becomes @@ -3256,7 +3320,9 @@ void yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (new_buffer == NULL) + { return; + } yyensure_buffer_stack(yyscanner); @@ -3271,7 +3337,9 @@ void yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) + { yyg->yy_buffer_stack_top++; + } YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ @@ -3287,12 +3355,16 @@ void yypop_buffer_state(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!YY_CURRENT_BUFFER) + { return; + } yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) + { --yyg->yy_buffer_stack_top; + } if (YY_CURRENT_BUFFER) { @@ -3320,7 +3392,9 @@ static void yyensure_buffer_stack(yyscan_t yyscanner) yyg->yy_buffer_stack = (struct yy_buffer_state **)yyalloc( num_to_alloc * sizeof(struct yy_buffer_state *), yyscanner); if (!yyg->yy_buffer_stack) + { YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + } memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state *)); @@ -3339,7 +3413,9 @@ static void yyensure_buffer_stack(yyscan_t yyscanner) yyg->yy_buffer_stack = (struct yy_buffer_state **)yyrealloc( yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state *), yyscanner); if (!yyg->yy_buffer_stack) + { YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + } /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, @@ -3360,12 +3436,16 @@ YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size, yyscan_t yyscanner) if (size < 2 || base[size - 2] != YY_END_OF_BUFFER_CHAR || base[size - 1] != YY_END_OF_BUFFER_CHAR) + { /* They forgot to leave room for the EOB's. */ return NULL; + } b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state), yyscanner); if (!b) + { YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()"); + } b->yy_buf_size = (int)(size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; @@ -3414,16 +3494,22 @@ YY_BUFFER_STATE yy_scan_bytes(const char *yybytes, int _yybytes_len, yyscan_t yy n = (yy_size_t)(_yybytes_len + 2); buf = (char *)yyalloc(n, yyscanner); if (!buf) + { YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()"); + } for (i = 0; i < _yybytes_len; ++i) + { buf[i] = yybytes[i]; + } buf[_yybytes_len] = buf[_yybytes_len + 1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf, n, yyscanner); if (!b) + { YY_FATAL_ERROR("bad buffer in yy_scan_bytes()"); + } /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -3480,7 +3566,9 @@ int yyget_lineno(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!YY_CURRENT_BUFFER) + { return 0; + } return yylineno; } @@ -3493,7 +3581,9 @@ int yyget_column(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; if (!YY_CURRENT_BUFFER) + { return 0; + } return yycolumn; } @@ -3555,7 +3645,9 @@ void yyset_lineno(int _line_number, yyscan_t yyscanner) /* lineno is only valid if an input buffer exists. */ if (!YY_CURRENT_BUFFER) + { YY_FATAL_ERROR("yyset_lineno called with no buffer"); + } yylineno = _line_number; } @@ -3570,7 +3662,9 @@ void yyset_column(int _column_no, yyscan_t yyscanner) /* column is only valid if an input buffer exists. */ if (!YY_CURRENT_BUFFER) + { YY_FATAL_ERROR("yyset_column called with no buffer"); + } yycolumn = _column_no; } @@ -3771,7 +3865,9 @@ static void yy_flex_strncpy(char *s1, const char *s2, int n, yyscan_t yyscanner) int i; for (i = 0; i < n; ++i) + { s1[i] = s2[i]; + } } #endif @@ -3823,14 +3919,20 @@ yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner) yyget_extra(yyscanner)->getPreprocessor().lex(&token); yy_size_t len = token.type == angle::pp::Token::LAST ? 0 : token.text.size(); if (len < max_size) + { memcpy(buf, token.text.c_str(), len); + } yyset_column(token.location.file, yyscanner); yyset_lineno(token.location.line, yyscanner); if (len >= max_size) + { YY_FATAL_ERROR("Input buffer overflow"); + } else if (len > 0) + { buf[len++] = ' '; + } return len; } @@ -4217,7 +4319,9 @@ int uint_constant(TParseContext *context) } if (!atoi_clamp(yytext, &(yylval->lex.u))) + { yyextra->error(*yylloc, "Integer overflow", yytext); + } return UINTCONSTANT; } @@ -4234,8 +4338,10 @@ int floatsuffix_check(TParseContext *context) std::string text = yytext; text.resize(text.size() - 1); - if (!strtof_clamp(text, &(yylval->lex.f))) + if (!strtof_clamp(text, &(yylval->lex.f), context->getCompileOptions().preserveDenorms)) + { yyextra->warning(*yylloc, "Float overflow", yytext); + } return (FLOATCONSTANT); } @@ -4253,20 +4359,26 @@ int int_constant(TParseContext *context) if (!atoi_clamp(yytext, &u)) { if (context->getShaderVersion() >= 300) + { yyextra->error(*yylloc, "Integer overflow", yytext); + } else + { yyextra->warning(*yylloc, "Integer overflow", yytext); + } } yylval->lex.i = static_cast(u); return INTCONSTANT; } -int float_constant(yyscan_t yyscanner) +int float_constant(TParseContext *context, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; - if (!strtof_clamp(yytext, &(yylval->lex.f))) + if (!strtof_clamp(yytext, &(yylval->lex.f), context->getCompileOptions().preserveDenorms)) + { yyextra->warning(*yylloc, "Float overflow", yytext); + } return FLOATCONSTANT; } @@ -4292,7 +4404,9 @@ int glslang_initialize(TParseContext *context) { yyscan_t scanner = NULL; if (yylex_init_extra(context, &scanner)) + { return 1; + } context->setScanner(scanner); return 0; @@ -4302,7 +4416,9 @@ int glslang_finalize(TParseContext *context) { yyscan_t scanner = context->getScanner(); if (scanner == NULL) + { return 0; + } context->setScanner(NULL); yylex_destroy(scanner); @@ -4323,11 +4439,11 @@ int glslang_scan(size_t count, angle::pp::Preprocessor *preprocessor = &context->getPreprocessor(); if (!preprocessor->init(count, string, length)) + { return 1; + } - if (context->getFragmentPrecisionHigh()) - preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - + preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); return 0; diff --git a/src/compiler/translator/glslang_tab_autogen.cpp b/src/compiler/translator/glslang_tab_autogen.cpp index 67bf1134ef0..39c7613e355 100644 --- a/src/compiler/translator/glslang_tab_autogen.cpp +++ b/src/compiler/translator/glslang_tab_autogen.cpp @@ -338,78 +338,89 @@ enum yysymbol_kind_t YYSYMBOL_exclusive_or_expression = 206, /* exclusive_or_expression */ YYSYMBOL_inclusive_or_expression = 207, /* inclusive_or_expression */ YYSYMBOL_logical_and_expression = 208, /* logical_and_expression */ - YYSYMBOL_logical_xor_expression = 209, /* logical_xor_expression */ - YYSYMBOL_logical_or_expression = 210, /* logical_or_expression */ - YYSYMBOL_conditional_expression = 211, /* conditional_expression */ - YYSYMBOL_assignment_expression = 212, /* assignment_expression */ - YYSYMBOL_assignment_operator = 213, /* assignment_operator */ - YYSYMBOL_expression = 214, /* expression */ - YYSYMBOL_constant_expression = 215, /* constant_expression */ - YYSYMBOL_enter_struct = 216, /* enter_struct */ - YYSYMBOL_declaration = 217, /* declaration */ - YYSYMBOL_function_prototype = 218, /* function_prototype */ - YYSYMBOL_function_declarator = 219, /* function_declarator */ - YYSYMBOL_function_header_with_parameters = 220, /* function_header_with_parameters */ - YYSYMBOL_function_header = 221, /* function_header */ - YYSYMBOL_parameter_declarator = 222, /* parameter_declarator */ - YYSYMBOL_parameter_declaration = 223, /* parameter_declaration */ - YYSYMBOL_parameter_type_specifier = 224, /* parameter_type_specifier */ - YYSYMBOL_init_declarator_list = 225, /* init_declarator_list */ - YYSYMBOL_single_declaration = 226, /* single_declaration */ - YYSYMBOL_fully_specified_type = 227, /* fully_specified_type */ - YYSYMBOL_interpolation_qualifier = 228, /* interpolation_qualifier */ - YYSYMBOL_type_qualifier = 229, /* type_qualifier */ - YYSYMBOL_invariant_qualifier = 230, /* invariant_qualifier */ - YYSYMBOL_precise_qualifier = 231, /* precise_qualifier */ - YYSYMBOL_single_type_qualifier = 232, /* single_type_qualifier */ - YYSYMBOL_storage_qualifier = 233, /* storage_qualifier */ - YYSYMBOL_type_specifier = 234, /* type_specifier */ - YYSYMBOL_precision_qualifier = 235, /* precision_qualifier */ - YYSYMBOL_layout_qualifier = 236, /* layout_qualifier */ - YYSYMBOL_layout_qualifier_id_list = 237, /* layout_qualifier_id_list */ - YYSYMBOL_layout_qualifier_id = 238, /* layout_qualifier_id */ - YYSYMBOL_type_specifier_no_prec = 239, /* type_specifier_no_prec */ - YYSYMBOL_array_specifier = 240, /* array_specifier */ - YYSYMBOL_type_specifier_nonarray = 241, /* type_specifier_nonarray */ - YYSYMBOL_struct_specifier = 242, /* struct_specifier */ - YYSYMBOL_243_1 = 243, /* $@1 */ - YYSYMBOL_244_2 = 244, /* $@2 */ - YYSYMBOL_struct_declaration_list = 245, /* struct_declaration_list */ - YYSYMBOL_struct_declaration = 246, /* struct_declaration */ - YYSYMBOL_struct_declarator_list = 247, /* struct_declarator_list */ - YYSYMBOL_struct_declarator = 248, /* struct_declarator */ - YYSYMBOL_initializer = 249, /* initializer */ - YYSYMBOL_declaration_statement = 250, /* declaration_statement */ - YYSYMBOL_statement = 251, /* statement */ - YYSYMBOL_simple_statement = 252, /* simple_statement */ - YYSYMBOL_compound_statement_with_scope = 253, /* compound_statement_with_scope */ - YYSYMBOL_254_3 = 254, /* $@3 */ - YYSYMBOL_255_4 = 255, /* $@4 */ - YYSYMBOL_statement_no_new_scope = 256, /* statement_no_new_scope */ - YYSYMBOL_statement_with_scope = 257, /* statement_with_scope */ - YYSYMBOL_258_5 = 258, /* $@5 */ - YYSYMBOL_259_6 = 259, /* $@6 */ - YYSYMBOL_compound_statement_no_new_scope = 260, /* compound_statement_no_new_scope */ - YYSYMBOL_statement_list = 261, /* statement_list */ - YYSYMBOL_expression_statement = 262, /* expression_statement */ - YYSYMBOL_selection_statement = 263, /* selection_statement */ - YYSYMBOL_selection_rest_statement = 264, /* selection_rest_statement */ - YYSYMBOL_switch_statement = 265, /* switch_statement */ - YYSYMBOL_266_7 = 266, /* $@7 */ - YYSYMBOL_case_label = 267, /* case_label */ - YYSYMBOL_condition = 268, /* condition */ - YYSYMBOL_iteration_statement = 269, /* iteration_statement */ - YYSYMBOL_270_8 = 270, /* $@8 */ - YYSYMBOL_271_9 = 271, /* $@9 */ - YYSYMBOL_272_10 = 272, /* $@10 */ - YYSYMBOL_for_init_statement = 273, /* for_init_statement */ - YYSYMBOL_conditionopt = 274, /* conditionopt */ - YYSYMBOL_for_rest_statement = 275, /* for_rest_statement */ - YYSYMBOL_jump_statement = 276, /* jump_statement */ - YYSYMBOL_translation_unit = 277, /* translation_unit */ - YYSYMBOL_external_declaration = 278, /* external_declaration */ - YYSYMBOL_function_definition = 279, /* function_definition */ - YYSYMBOL_280_11 = 280 /* $@11 */ + YYSYMBOL_209_1 = 209, /* $@1 */ + YYSYMBOL_logical_xor_expression = 210, /* logical_xor_expression */ + YYSYMBOL_logical_or_expression = 211, /* logical_or_expression */ + YYSYMBOL_212_2 = 212, /* $@2 */ + YYSYMBOL_conditional_expression = 213, /* conditional_expression */ + YYSYMBOL_214_3 = 214, /* $@3 */ + YYSYMBOL_215_4 = 215, /* $@4 */ + YYSYMBOL_assignment_expression = 216, /* assignment_expression */ + YYSYMBOL_assignment_operator = 217, /* assignment_operator */ + YYSYMBOL_expression = 218, /* expression */ + YYSYMBOL_219_5 = 219, /* $@5 */ + YYSYMBOL_constant_expression = 220, /* constant_expression */ + YYSYMBOL_enter_struct = 221, /* enter_struct */ + YYSYMBOL_declaration = 222, /* declaration */ + YYSYMBOL_function_prototype = 223, /* function_prototype */ + YYSYMBOL_function_declarator = 224, /* function_declarator */ + YYSYMBOL_function_header_with_parameters = 225, /* function_header_with_parameters */ + YYSYMBOL_function_header = 226, /* function_header */ + YYSYMBOL_parameter_declarator = 227, /* parameter_declarator */ + YYSYMBOL_parameter_declaration = 228, /* parameter_declaration */ + YYSYMBOL_parameter_type_specifier = 229, /* parameter_type_specifier */ + YYSYMBOL_init_declarator_list = 230, /* init_declarator_list */ + YYSYMBOL_single_declaration = 231, /* single_declaration */ + YYSYMBOL_fully_specified_type = 232, /* fully_specified_type */ + YYSYMBOL_interpolation_qualifier = 233, /* interpolation_qualifier */ + YYSYMBOL_type_qualifier = 234, /* type_qualifier */ + YYSYMBOL_invariant_qualifier = 235, /* invariant_qualifier */ + YYSYMBOL_precise_qualifier = 236, /* precise_qualifier */ + YYSYMBOL_single_type_qualifier = 237, /* single_type_qualifier */ + YYSYMBOL_storage_qualifier = 238, /* storage_qualifier */ + YYSYMBOL_type_specifier = 239, /* type_specifier */ + YYSYMBOL_precision_qualifier = 240, /* precision_qualifier */ + YYSYMBOL_layout_qualifier = 241, /* layout_qualifier */ + YYSYMBOL_layout_qualifier_id_list = 242, /* layout_qualifier_id_list */ + YYSYMBOL_layout_qualifier_id = 243, /* layout_qualifier_id */ + YYSYMBOL_type_specifier_no_prec = 244, /* type_specifier_no_prec */ + YYSYMBOL_array_specifier = 245, /* array_specifier */ + YYSYMBOL_type_specifier_nonarray = 246, /* type_specifier_nonarray */ + YYSYMBOL_struct_specifier = 247, /* struct_specifier */ + YYSYMBOL_248_6 = 248, /* $@6 */ + YYSYMBOL_249_7 = 249, /* $@7 */ + YYSYMBOL_struct_declaration_list = 250, /* struct_declaration_list */ + YYSYMBOL_struct_declaration = 251, /* struct_declaration */ + YYSYMBOL_struct_declarator_list = 252, /* struct_declarator_list */ + YYSYMBOL_struct_declarator = 253, /* struct_declarator */ + YYSYMBOL_initializer = 254, /* initializer */ + YYSYMBOL_declaration_statement = 255, /* declaration_statement */ + YYSYMBOL_statement = 256, /* statement */ + YYSYMBOL_simple_statement = 257, /* simple_statement */ + YYSYMBOL_compound_statement_with_scope = 258, /* compound_statement_with_scope */ + YYSYMBOL_259_8 = 259, /* $@8 */ + YYSYMBOL_260_9 = 260, /* $@9 */ + YYSYMBOL_statement_no_new_scope = 261, /* statement_no_new_scope */ + YYSYMBOL_statement_with_scope = 262, /* statement_with_scope */ + YYSYMBOL_263_10 = 263, /* $@10 */ + YYSYMBOL_264_11 = 264, /* $@11 */ + YYSYMBOL_compound_statement_no_new_scope = 265, /* compound_statement_no_new_scope */ + YYSYMBOL_statement_list = 266, /* statement_list */ + YYSYMBOL_expression_statement = 267, /* expression_statement */ + YYSYMBOL_selection_statement = 268, /* selection_statement */ + YYSYMBOL_269_12 = 269, /* $@12 */ + YYSYMBOL_selection_rest_statement = 270, /* selection_rest_statement */ + YYSYMBOL_271_13 = 271, /* $@13 */ + YYSYMBOL_switch_statement = 272, /* switch_statement */ + YYSYMBOL_273_14 = 273, /* $@14 */ + YYSYMBOL_case_label = 274, /* case_label */ + YYSYMBOL_condition = 275, /* condition */ + YYSYMBOL_iteration_statement = 276, /* iteration_statement */ + YYSYMBOL_277_15 = 277, /* $@15 */ + YYSYMBOL_278_16 = 278, /* $@16 */ + YYSYMBOL_279_17 = 279, /* $@17 */ + YYSYMBOL_280_18 = 280, /* $@18 */ + YYSYMBOL_281_19 = 281, /* $@19 */ + YYSYMBOL_282_20 = 282, /* $@20 */ + YYSYMBOL_for_init_statement = 283, /* for_init_statement */ + YYSYMBOL_conditionopt = 284, /* conditionopt */ + YYSYMBOL_for_rest_statement = 285, /* for_rest_statement */ + YYSYMBOL_286_21 = 286, /* $@21 */ + YYSYMBOL_jump_statement = 287, /* jump_statement */ + YYSYMBOL_translation_unit = 288, /* translation_unit */ + YYSYMBOL_external_declaration = 289, /* external_declaration */ + YYSYMBOL_function_definition = 290, /* function_definition */ + YYSYMBOL_291_22 = 291 /* $@22 */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -793,16 +804,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 167 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 3566 +#define YYLAST 3577 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 185 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 96 +#define YYNNTS 107 /* YYNRULES -- Number of rules. */ -#define YYNRULES 329 +#define YYNRULES 340 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 453 +#define YYNSTATES 464 /* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 439 @@ -848,23 +859,24 @@ static const yytype_int16 yyrline[] = { 320, 323, 329, 336, 342, 345, 353, 356, 362, 365, 371, 375, 382, 390, 393, 396, 402, 405, 408, 411, 418, 419, 420, 421, 429, 430, 433, 436, 443, 444, 447, 453, 454, 458, 465, 466, 469, 472, 475, 481, 482, 485, 491, 492, 499, 500, 507, 508, - 515, 516, 522, 523, 529, 530, 536, 537, 543, 544, 550, 551, 552, 553, 557, 558, - 559, 563, 567, 571, 575, 582, 585, 591, 598, 605, 608, 611, 615, 619, 623, 627, - 631, 638, 645, 648, 655, 668, 691, 701, 704, 710, 714, 718, 722, 729, 735, 738, - 742, 746, 751, 758, 762, 766, 770, 775, 782, 786, 792, 795, 798, 808, 812, 819, - 825, 831, 835, 839, 842, 845, 849, 857, 862, 866, 869, 872, 875, 878, 882, 892, - 895, 899, 902, 905, 908, 911, 914, 918, 925, 932, 935, 938, 944, 951, 954, 960, - 963, 966, 969, 975, 978, 985, 990, 997, 1005, 1019, 1022, 1025, 1028, 1031, 1034, 1038, - 1042, 1046, 1050, 1054, 1058, 1062, 1066, 1070, 1074, 1078, 1082, 1086, 1090, 1094, 1098, 1102, - 1106, 1110, 1114, 1118, 1125, 1128, 1131, 1134, 1137, 1140, 1143, 1151, 1159, 1169, 1172, 1175, - 1178, 1181, 1184, 1187, 1195, 1203, 1213, 1216, 1219, 1222, 1225, 1228, 1231, 1239, 1247, 1257, - 1260, 1263, 1266, 1274, 1282, 1289, 1299, 1306, 1313, 1316, 1319, 1322, 1325, 1328, 1331, 1334, - 1337, 1340, 1343, 1346, 1349, 1357, 1365, 1373, 1381, 1389, 1397, 1407, 1417, 1427, 1430, 1437, - 1444, 1451, 1454, 1464, 1464, 1467, 1467, 1473, 1476, 1482, 1485, 1492, 1496, 1502, 1505, 1511, - 1515, 1519, 1520, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1536, 1540, 1540, 1540, 1547, 1548, - 1552, 1552, 1553, 1553, 1558, 1562, 1569, 1573, 1580, 1581, 1588, 1594, 1598, 1607, 1607, 1614, - 1617, 1623, 1627, 1633, 1633, 1638, 1638, 1642, 1642, 1650, 1653, 1659, 1662, 1668, 1672, 1679, - 1682, 1685, 1688, 1691, 1699, 1705, 1711, 1714, 1720, 1720}; + 515, 516, 516, 524, 525, 531, 532, 532, 540, 541, 543, 541, 551, 552, 558, 559, + 560, 561, 565, 566, 567, 571, 575, 579, 583, 590, 593, 593, 601, 608, 615, 618, + 621, 625, 629, 633, 637, 641, 648, 655, 658, 665, 678, 701, 711, 714, 720, 724, + 728, 732, 739, 745, 748, 752, 756, 761, 768, 772, 776, 780, 785, 792, 796, 802, + 805, 808, 818, 822, 829, 835, 841, 845, 849, 852, 855, 859, 867, 872, 876, 879, + 882, 885, 888, 892, 902, 905, 909, 912, 915, 918, 921, 924, 928, 935, 942, 945, + 948, 954, 961, 964, 970, 973, 976, 979, 985, 988, 995, 1000, 1007, 1015, 1029, 1032, + 1035, 1038, 1041, 1044, 1048, 1052, 1056, 1060, 1064, 1068, 1072, 1076, 1080, 1084, 1088, 1092, + 1096, 1100, 1104, 1108, 1112, 1116, 1120, 1124, 1128, 1135, 1138, 1141, 1144, 1147, 1150, 1153, + 1161, 1169, 1179, 1182, 1185, 1188, 1191, 1194, 1197, 1205, 1213, 1223, 1226, 1229, 1232, 1235, + 1238, 1241, 1249, 1257, 1267, 1270, 1273, 1276, 1284, 1292, 1299, 1309, 1316, 1323, 1326, 1329, + 1332, 1335, 1338, 1341, 1344, 1347, 1350, 1353, 1356, 1359, 1367, 1375, 1383, 1391, 1399, 1407, + 1417, 1427, 1437, 1440, 1447, 1454, 1461, 1464, 1474, 1474, 1477, 1477, 1483, 1486, 1492, 1495, + 1502, 1506, 1512, 1515, 1521, 1525, 1529, 1530, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1546, + 1550, 1550, 1550, 1557, 1558, 1565, 1565, 1566, 1566, 1575, 1579, 1586, 1590, 1597, 1598, 1605, + 1605, 1613, 1613, 1621, 1631, 1631, 1637, 1640, 1646, 1650, 1656, 1659, 1656, 1665, 1668, 1665, + 1673, 1673, 1673, 1682, 1686, 1692, 1695, 1701, 1707, 1707, 1717, 1720, 1723, 1726, 1729, 1737, + 1743, 1749, 1752, 1758, 1758}; #endif /** Accessing symbol of state STATE. */ @@ -1086,12 +1098,17 @@ static const char *const yytname[] = {"\"end of file\"", "exclusive_or_expression", "inclusive_or_expression", "logical_and_expression", + "$@1", "logical_xor_expression", "logical_or_expression", + "$@2", "conditional_expression", + "$@3", + "$@4", "assignment_expression", "assignment_operator", "expression", + "$@5", "constant_expression", "enter_struct", "declaration", @@ -1120,8 +1137,8 @@ static const char *const yytname[] = {"\"end of file\"", "array_specifier", "type_specifier_nonarray", "struct_specifier", - "$@1", - "$@2", + "$@6", + "$@7", "struct_declaration_list", "struct_declaration", "struct_declarator_list", @@ -1131,33 +1148,39 @@ static const char *const yytname[] = {"\"end of file\"", "statement", "simple_statement", "compound_statement_with_scope", - "$@3", - "$@4", + "$@8", + "$@9", "statement_no_new_scope", "statement_with_scope", - "$@5", - "$@6", + "$@10", + "$@11", "compound_statement_no_new_scope", "statement_list", "expression_statement", "selection_statement", + "$@12", "selection_rest_statement", + "$@13", "switch_statement", - "$@7", + "$@14", "case_label", "condition", "iteration_statement", - "$@8", - "$@9", - "$@10", + "$@15", + "$@16", + "$@17", + "$@18", + "$@19", + "$@20", "for_init_statement", "conditionopt", "for_rest_statement", + "$@21", "jump_statement", "translation_unit", "external_declaration", "function_definition", - "$@11", + "$@22", YY_NULLPTR}; static const char *yysymbol_name(yysymbol_kind_t yysymbol) @@ -1166,312 +1189,352 @@ static const char *yysymbol_name(yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-397) +#define YYPACT_NINF (-413) #define yypact_value_is_default(Yyn) ((Yyn) == YYPACT_NINF) -#define YYTABLE_NINF (-289) +#define YYTABLE_NINF (-328) #define yytable_value_is_error(Yyn) 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { - 3052, -397, -397, -397, -397, -397, 105, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -397, -94, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, - -397, -397, -397, -132, -397, -397, -397, -81, -41, -49, 3184, -90, -397, -86, -397, 1609, - -397, -397, -397, -397, -397, -397, -397, -397, -39, -397, 2920, -397, -397, 3432, -397, -397, - -397, -31, -47, -397, -26, -397, 3184, -397, -397, -397, 3184, 3, 3, -397, -35, -135, - -114, -397, 3184, -397, -397, 1734, -10, -397, -397, -6, 3184, -397, -397, -9, -93, -397, - 438, -397, -397, -397, -397, -39, -97, -397, 2193, -87, -397, -397, 3184, 3, 2497, -397, - -397, 7, -397, -397, -397, -397, -397, 2193, 2193, 2193, -397, -397, -397, -397, -397, -397, - -397, -78, -397, -397, -397, 12, -69, 2344, 8, -397, 2193, -33, -96, -116, -124, 5, - -12, -7, -4, 31, 30, -123, -397, 17, -397, 1888, -397, 2638, 3184, 19, -397, -47, - 13, 14, -397, 22, 25, 16, 2042, 28, 2193, 32, 44, 37, -397, -397, 40, -397, - -397, -80, -397, -81, 45, -397, -397, -397, -397, 611, -397, -397, -397, -397, -397, -397, - -10, 2193, -83, -397, -397, 2193, 3, -39, -76, -397, -111, -397, -397, -397, -62, -397, - -397, 2193, 3308, -397, -397, 2193, 46, -397, -397, -397, 2193, 2193, 2193, 2193, 2193, 2193, - 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, -397, -397, - 47, -397, 2779, -397, -397, -397, -397, -397, 48, -397, 2193, -397, -397, -48, 2193, 43, - -397, -397, -397, 784, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, 2193, - 2193, -397, -397, -397, -397, 2193, -397, -43, -10, 3, -397, -122, -397, -397, 51, 41, - -397, 55, -397, -397, -397, -397, -397, -33, -33, -96, -96, -116, -116, -116, -116, -124, - -124, 5, -12, -7, -4, 31, 30, -11, -397, -397, 150, -26, 1130, 1303, -60, -397, - -59, -397, 1456, 784, -397, -397, -397, -397, -397, -397, -109, -397, 2193, 57, -397, -397, - -397, -397, 1456, 48, -397, 41, 3, 3184, 58, 56, -397, -397, 2193, -397, 50, 61, - 206, -397, 60, 59, 957, -397, -55, 2193, 957, 48, -397, 2193, -397, -397, -397, 63, - 41, -397, -397, -397, -397}; + 3063, -413, -413, -413, -413, -413, 125, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -106, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, + -413, -413, -413, -107, -413, -413, -413, -68, -121, -104, 3195, -119, -413, -26, -413, 1620, + -413, -413, -413, -413, -413, -413, -413, -413, -71, -413, 2931, -413, -413, 3443, -413, -413, + -413, -40, -49, -413, -32, -413, 3195, -413, -413, -413, 3195, 12, 12, -413, -24, -134, + -127, -413, 3195, -413, -413, 1745, -23, -413, -413, -29, 3195, -413, -413, -17, -81, -413, + 449, -413, -413, -413, -413, -71, -103, -413, 2204, -94, -413, -413, 3195, 12, 2508, -413, + -413, -12, -413, -413, -413, -413, -413, 2204, 2204, 2204, -413, -413, -413, -413, -413, -413, + -413, -65, -413, -413, -413, 7, -80, 2355, 18, -413, 2204, -21, -39, 19, -122, 17, + -22, 1, 3, 34, 35, -129, -413, 22, -413, 1899, -413, 2649, 3195, 29, -413, -49, + 16, 20, -413, 28, 31, 23, 2053, 32, 2204, 26, 36, 33, -413, -413, 101, -413, + -413, -105, -413, -68, 37, -413, -413, -413, -413, 622, -413, -413, -413, -413, -413, -413, + -23, 2204, -84, -413, -413, 2204, 12, -71, -48, -413, -115, -413, -413, -413, -79, -413, + -413, 2204, 3319, -413, -413, 2204, 38, -413, -413, -413, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, -413, 2204, -413, -413, -413, -413, + 39, -413, 2790, -413, -413, -413, -413, -413, 41, -413, 2204, -413, -413, -47, 2204, 55, + -413, -413, -413, 795, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, -413, 2204, + -413, -413, -413, -413, -413, 2204, -413, -42, -23, 12, -413, -137, -413, -413, 40, 58, + -413, 66, -413, -413, -413, -413, -413, -21, -21, -39, -39, 19, 19, 19, 19, -122, + -122, 17, -22, 1, 2204, 34, 2204, 2204, -413, -413, 134, -32, 1141, 1314, -72, -413, + -69, -413, 1467, 795, -413, 2204, -413, -413, -413, -413, -128, -413, 3, 35, -1, 69, + -413, -413, -413, -413, -413, -413, -413, 58, 12, 3195, -413, 65, -413, -413, -413, -413, + 1467, 41, -32, 62, 71, -413, 2204, 2204, -413, 63, 76, 221, -413, -413, 2204, 968, + -413, -62, 78, 968, -413, -413, -413, -413, -413, 70, 2204, -413, 41, -413, 58, -413}; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_int16 yydefact[] = { - 0, 127, 128, 153, 154, 155, 0, 135, 137, 173, 170, 171, 172, 177, 178, 179, 180, 181, 182, - 174, 175, 176, 183, 184, 185, 186, 187, 188, 138, 139, 140, 143, 144, 136, 189, 190, 191, 192, - 193, 194, 151, 141, 123, 122, 124, 142, 145, 146, 147, 148, 149, 150, 0, 169, 196, 198, 229, - 231, 199, 205, 206, 207, 208, 214, 215, 216, 217, 200, 209, 218, 201, 210, 219, 197, 223, 224, - 225, 228, 202, 226, 211, 220, 203, 227, 212, 221, 204, 213, 222, 230, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 246, 248, 245, 247, 249, 250, 251, 252, 253, 254, 255, - 256, 0, 195, 258, 327, 328, 0, 99, 98, 0, 110, 115, 132, 0, 133, 134, 125, 129, 120, - 131, 130, 152, 163, 257, 0, 324, 326, 0, 2, 3, 261, 0, 0, 89, 0, 97, 0, 106, - 100, 108, 0, 109, 0, 90, 2, 116, 0, 95, 0, 126, 121, 0, 164, 1, 325, 0, 0, - 259, 162, 159, 0, 157, 0, 329, 101, 105, 107, 103, 111, 102, 0, 117, 88, 96, 0, 0, - 0, 263, 10, 4, 8, 6, 7, 9, 31, 0, 0, 0, 165, 38, 37, 39, 36, 5, 12, - 32, 14, 19, 20, 0, 0, 25, 0, 40, 0, 44, 47, 50, 55, 58, 60, 62, 64, 66, - 68, 70, 87, 0, 29, 0, 91, 0, 0, 0, 156, 0, 0, 0, 309, 0, 0, 0, 0, - 0, 0, 0, 0, 283, 292, 296, 40, 72, 85, 0, 272, 0, 152, 275, 294, 274, 273, 0, - 276, 277, 278, 279, 280, 281, 104, 0, 112, 271, 119, 0, 0, 269, 0, 267, 0, 264, 33, - 34, 0, 16, 17, 0, 0, 23, 22, 0, 169, 26, 28, 35, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 167, 0, 262, 0, - 160, 161, 158, 320, 319, 290, 311, 0, 323, 321, 0, 0, 0, 304, 307, 282, 0, 75, 76, - 78, 77, 80, 81, 82, 83, 84, 79, 74, 0, 0, 297, 293, 295, 114, 0, 118, 0, 270, - 0, 265, 0, 92, 11, 0, 18, 30, 15, 21, 27, 41, 42, 43, 46, 45, 48, 49, 53, - 54, 51, 52, 56, 57, 59, 61, 63, 65, 67, 69, 0, 168, 260, 0, 0, 0, 0, 0, - 322, 0, 303, 0, 284, 73, 86, 113, 266, 268, 93, 0, 13, 0, 0, 289, 291, 314, 313, - 316, 290, 301, 305, 0, 0, 0, 0, 94, 71, 0, 315, 0, 0, 300, 298, 0, 0, 0, - 285, 0, 317, 0, 290, 302, 0, 287, 308, 286, 0, 318, 312, 299, 306, 310}; + 0, 132, 133, 158, 159, 160, 0, 140, 142, 178, 175, 176, 177, 182, 183, 184, 185, 186, 187, + 179, 180, 181, 188, 189, 190, 191, 192, 193, 143, 144, 145, 148, 149, 141, 194, 195, 196, 197, + 198, 199, 156, 146, 128, 127, 129, 147, 150, 151, 152, 153, 154, 155, 0, 174, 201, 203, 234, + 236, 204, 210, 211, 212, 213, 219, 220, 221, 222, 205, 214, 223, 206, 215, 224, 202, 228, 229, + 230, 233, 207, 231, 216, 225, 208, 232, 217, 226, 209, 218, 227, 235, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 251, 253, 250, 252, 254, 255, 256, 257, 258, 259, 260, + 261, 0, 200, 263, 338, 339, 0, 104, 103, 0, 115, 120, 137, 0, 138, 139, 130, 134, 125, + 136, 135, 157, 168, 262, 0, 335, 337, 0, 2, 3, 266, 0, 0, 94, 0, 102, 0, 111, + 105, 113, 0, 114, 0, 95, 2, 121, 0, 100, 0, 131, 126, 0, 169, 1, 336, 0, 0, + 264, 167, 164, 0, 162, 0, 340, 106, 110, 112, 108, 116, 107, 0, 122, 93, 101, 0, 0, + 0, 268, 10, 4, 8, 6, 7, 9, 31, 0, 0, 0, 170, 38, 37, 39, 36, 5, 12, + 32, 14, 19, 20, 0, 0, 25, 0, 40, 0, 44, 47, 50, 55, 58, 60, 62, 64, 67, + 69, 72, 92, 0, 29, 0, 96, 0, 0, 0, 161, 0, 0, 0, 317, 0, 0, 0, 0, + 0, 0, 0, 0, 288, 297, 301, 40, 76, 89, 0, 277, 0, 157, 280, 299, 279, 278, 0, + 281, 282, 283, 284, 285, 286, 109, 0, 117, 276, 124, 0, 0, 274, 0, 272, 0, 269, 33, + 34, 0, 16, 17, 0, 0, 23, 22, 0, 174, 26, 28, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 70, 73, 171, 172, 0, 267, 0, + 165, 166, 163, 331, 330, 295, 320, 0, 334, 332, 0, 0, 0, 311, 314, 287, 0, 79, 80, + 82, 81, 84, 85, 86, 87, 88, 83, 78, 0, 90, 302, 298, 300, 119, 0, 123, 0, 275, + 0, 270, 0, 97, 11, 0, 18, 30, 15, 21, 27, 41, 42, 43, 46, 45, 48, 49, 53, + 54, 51, 52, 56, 57, 59, 61, 63, 0, 68, 0, 0, 173, 265, 0, 0, 0, 0, 0, + 333, 0, 310, 0, 289, 77, 0, 118, 271, 273, 98, 0, 13, 66, 71, 0, 0, 294, 296, + 324, 323, 321, 303, 308, 312, 0, 0, 315, 0, 91, 99, 74, 318, 326, 295, 0, 0, 0, + 290, 0, 0, 325, 0, 0, 307, 304, 309, 0, 0, 75, 0, 328, 0, 305, 313, 292, 316, + 291, 0, 0, 322, 295, 319, 329, 306}; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -397, -51, -397, -397, -397, -397, -397, -397, -64, -397, -397, -397, -397, 42, -397, -142, - -140, -175, -143, -84, -75, -85, -82, -77, -73, -397, -151, -179, -397, -188, -202, -397, - 9, 10, -397, -397, -397, 77, 89, 90, -397, -397, -375, -397, -118, -397, -397, -121, - -397, -120, 239, -397, -397, 15, 0, -144, -397, -397, -397, -397, -152, -182, -32, -113, - -261, -150, -254, -377, -185, -397, -397, -187, -396, -397, -397, -145, -72, -141, -397, -397, - -397, -397, -397, -166, -397, -397, -397, -397, -397, -397, -397, -397, -397, 117, -397, -397}; + -413, -51, -413, -413, -413, -413, -413, -413, -45, -413, -413, -413, -413, -90, -413, -130, + -126, -194, -136, -64, -70, -67, -140, -66, -413, -147, -413, -413, -153, -413, -413, -176, + -413, -195, -413, -208, -413, 9, 13, -413, -413, -413, 97, 114, 112, -413, -413, -370, + -413, -120, -413, -413, -123, -413, -117, 261, -413, -413, 30, 0, -135, -413, -413, -413, + -413, -151, -174, -10, -89, -266, -124, -251, -379, -413, -413, -413, -177, -412, -413, -413, + -145, -63, -118, -413, -413, -413, -413, -413, -413, -413, -157, -413, -413, -413, -413, -413, + -413, -413, -413, -413, -413, -413, -413, -413, 139, -413, -413}; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - 0, 279, 207, 208, 209, 366, 210, 211, 212, 213, 214, 215, 216, 254, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 255, 256, 351, 257, 231, 162, - 258, 259, 120, 121, 122, 151, 152, 153, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 174, 175, 232, 166, 136, 137, 236, 170, 190, 191, 280, 281, - 276, 261, 262, 263, 264, 339, 425, 445, 394, 395, 396, 446, 265, 266, 267, 433, - 268, 434, 269, 424, 270, 402, 328, 397, 418, 430, 431, 271, 138, 139, 140, 148}; + 0, 279, 207, 208, 209, 366, 210, 211, 212, 213, 214, 215, 216, 254, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 388, 228, 229, 390, 255, 391, 438, 256, 351, 257, 405, 231, + 162, 258, 259, 120, 121, 122, 151, 152, 153, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 174, 175, 232, 166, 136, 137, 236, 170, 190, 191, 280, 281, 276, 261, 262, + 263, 264, 339, 427, 455, 394, 395, 396, 456, 265, 266, 267, 433, 444, 460, 268, 434, 269, + 426, 270, 402, 436, 328, 439, 397, 432, 420, 441, 442, 458, 271, 138, 139, 140, 148}; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 135, 145, 155, 177, 154, 275, 163, 164, 283, 118, 119, 355, 356, 286, 230, 185, 358, 172, 235, - 415, 305, 306, 363, 432, 303, 304, 316, 422, 165, 146, 155, 320, 154, 163, 155, 184, 295, 272, - 274, 142, 143, 165, 189, 422, 188, 450, 335, 158, 143, 409, 189, 186, 188, 283, 233, 307, 308, - 187, 333, 444, 364, 317, 426, 444, 287, 288, 165, 163, 278, 238, 189, 144, 188, 273, 159, 239, - 233, 301, 156, 302, 233, 157, 230, 277, 322, 289, 173, 357, 352, 290, 147, 353, 361, 292, 275, - 362, 406, 230, 275, 293, 365, 367, 419, 420, 181, 182, 352, 447, 352, 352, 3, 4, 5, 352, - 371, 189, 189, 188, 188, 150, 352, 149, 135, 399, 165, 361, 183, 135, 407, 391, 379, 380, 381, - 382, 171, 360, 142, 143, 135, 176, 283, 169, 398, 298, 299, 300, 400, 118, 119, 355, 135, 309, - 310, 233, 135, 323, 324, 352, 412, 375, 376, 237, 135, 377, 378, 234, 383, 384, -30, 296, 135, - 311, 404, 405, 291, 312, 260, 313, 275, 314, 315, 318, 451, 329, 326, 327, 330, 331, 135, 334, - 135, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 336, 189, 338, 188, 337, -29, 217, -24, - 352, 350, 392, 401, -288, 421, 411, -31, 413, 428, 410, 436, 439, 437, 440, 441, 251, 370, 385, - 387, 443, 421, 179, 388, 427, 452, 135, 135, 386, 389, 178, 438, 284, 285, 390, 180, 141, 359, - 416, 408, 442, 414, 448, 429, 449, 325, 168, 417, 0, 0, 0, 297, 0, 0, 0, 275, 260, - 0, 403, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 423, - 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 423, 0, 163, 164, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 372, 373, - 374, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 435, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 260, 0, - 0, 0, 0, 260, 260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 260, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, - 0, 0, 0, 260, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, - 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, 252, 0, 0, 0, - 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, - 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, 354, 0, - 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, - 0, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, - 0, 176, 0, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 250, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, - 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, - 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, - 5, 201, 7, 8, 9, 10, 11, 12, 0, 0, 0, 253, 203, 204, 205, 206, 0, 0, 0, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, - 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 201, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 203, 204, 205, 206, 0, 0, - 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 160, 117, 0, 9, 10, 11, - 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 161, 34, 35, 36, 37, 38, - 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 202, 9, - 10, 11, 12, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 0, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, - 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, - 319, 9, 10, 11, 12, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 0, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, - 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, - 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, - 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, - 9, 10, 11, 12, 0, 0, 0, 0, 0, 332, 203, 204, 205, 206, 0, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, - 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 9, - 10, 11, 12, 0, 0, 0, 0, 0, 0, 203, 204, 205, 206, 0, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, - 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 294, 0, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 201, 7, 8, - 9, 10, 11, 12, 0, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 282, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, - 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 321, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 0, 0, 117, 0, 0, 0, 0, 0, 0, 167, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 393, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 1, 2, 3, 4, 5, - 0, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 9, 10, 11, 12, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, - 116, 0, 368, 117, 9, 10, 11, 12, 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, - 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 0, 0, 117}; + 135, 145, 154, 177, 163, 155, 286, 356, 275, 118, 164, 358, 230, 119, 355, 172, 283, 417, 363, + 235, 316, 443, 305, 306, 185, 320, 165, 142, 143, 165, 154, 163, 424, 155, 409, 233, 184, 155, + 186, 295, 335, 149, 188, 429, 187, 189, 272, 274, 463, 156, 188, 333, 157, 189, 146, 317, 364, + 307, 308, 144, 165, 283, 424, 352, 150, 163, 353, 273, 454, 233, 188, 278, 454, 189, 159, 217, + 277, 287, 288, 233, 230, 238, 292, 365, 173, 322, 357, 239, 293, 352, 421, 406, 165, 422, 367, + 230, 352, 275, 289, 352, 457, 275, 290, 147, 181, 182, 352, 158, 143, 284, 285, 379, 380, 381, + 382, 188, 188, 371, 189, 189, 361, 352, 135, 362, 399, 171, 361, 135, 297, 407, 3, 4, 5, + 176, 301, 398, 302, 183, 135, 400, 233, 169, 234, 217, 360, 142, 143, 118, 283, -30, 135, 119, + 355, 237, 135, 298, 299, 300, 217, 303, 304, 311, 135, 309, 310, 323, 324, 352, 430, 291, 135, + 375, 376, 383, 384, 404, 260, 377, 378, 296, 453, 275, 314, 312, 313, 315, 318, 326, 135, 329, + 135, 327, 330, 334, 331, 336, 414, 337, -29, 338, -24, 415, 188, 392, 411, 189, -293, 423, 372, + 373, 374, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 401, 217, 352, -31, + 410, 428, 431, 437, 446, 447, 450, 135, 135, 423, 451, 452, -327, 461, 386, 413, 449, 370, 387, + 385, 412, 389, 416, 179, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 448, 462, 178, 260, + 180, 141, 359, 325, 275, 350, 408, 418, 459, 440, 403, 168, 0, 419, 0, 0, 425, 0, 0, + 0, 0, 0, 0, 445, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 217, 0, 163, 0, + 0, 0, 0, 0, 164, 0, 0, 0, 425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 435, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 260, 0, + 0, 0, 0, 260, 260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 260, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 0, 0, 0, 260, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, + 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 201, 0, 0, 0, 251, 252, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, + 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, + 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 0, 0, 0, 251, 354, 0, 0, 0, 0, 253, 203, 204, 205, 206, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, + 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, + 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, 0, 0, 0, 0, 0, 253, 203, 204, + 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, 0, 243, + 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, + 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 176, 0, 0, 0, 0, 0, 253, + 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, + 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 201, 7, 8, 9, 10, 11, 12, + 0, 0, 0, 253, 203, 204, 205, 206, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 201, 7, 8, 9, 10, 11, + 12, 0, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 0, 160, 117, 0, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 0, 0, 0, 0, 0, 161, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, + 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 201, 0, 0, 202, 9, 10, 11, 12, 0, 0, 0, 203, 204, + 205, 206, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 192, 193, + 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 319, 9, 10, 11, 12, 0, 0, 0, + 203, 204, 205, 206, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, + 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 9, 10, 11, 12, 0, 0, 0, 0, + 0, 332, 203, 204, 205, 206, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 192, + 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 9, 10, 11, 12, 0, 0, 0, 0, 0, + 0, 203, 204, 205, 206, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 52, 294, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 192, 193, + 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 2, 3, 4, 5, 201, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, + 203, 204, 205, 206, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, + 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 7, 8, + 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 321, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 0, + 0, 0, 0, 0, 0, 167, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 393, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 0, 0, 117, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 0, 0, 117, 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, 12, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 0, 0, 117, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, + 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 0, 368, 117, 9, 10, 11, 12, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 0, 116, 0, 0, 117}; static const yytype_int16 yycheck[] = { - 0, 52, 122, 148, 122, 184, 127, 127, 190, 0, 0, 265, 273, 201, 165, 159, 277, 64, 170, - 396, 144, 145, 133, 419, 140, 141, 149, 402, 163, 161, 150, 233, 150, 154, 154, 170, 215, 181, - 182, 133, 134, 163, 162, 418, 162, 441, 248, 133, 134, 171, 170, 165, 170, 235, 163, 179, 180, - 171, 246, 436, 171, 184, 171, 440, 142, 143, 163, 188, 188, 162, 190, 165, 190, 170, 125, 168, - 163, 173, 168, 175, 163, 171, 233, 170, 236, 163, 133, 170, 168, 167, 171, 171, 168, 162, 273, - 171, 357, 248, 277, 168, 162, 289, 162, 162, 155, 156, 168, 162, 168, 168, 5, 6, 7, 168, - 293, 235, 236, 235, 236, 168, 168, 162, 122, 171, 163, 168, 161, 127, 171, 317, 305, 306, 307, - 308, 165, 279, 133, 134, 138, 165, 322, 141, 330, 176, 177, 178, 334, 138, 138, 403, 150, 146, - 147, 163, 154, 136, 137, 168, 169, 301, 302, 170, 162, 303, 304, 171, 309, 310, 161, 161, 170, - 183, 351, 352, 162, 182, 176, 181, 357, 148, 150, 164, 443, 161, 171, 171, 161, 171, 188, 161, - 190, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 169, 322, 166, 322, 161, 161, 165, 162, - 168, 170, 164, 169, 165, 402, 164, 161, 67, 161, 363, 162, 171, 166, 162, 18, 165, 290, 311, - 313, 170, 418, 154, 314, 412, 171, 235, 236, 312, 315, 150, 428, 199, 200, 316, 154, 6, 278, - 397, 361, 434, 395, 439, 418, 440, 239, 138, 397, -1, -1, -1, 218, -1, -1, -1, 443, 265, - -1, 339, -1, -1, -1, -1, -1, -1, -1, 233, -1, -1, -1, -1, -1, -1, -1, -1, 402, - -1, -1, -1, -1, -1, 248, -1, -1, -1, -1, -1, -1, -1, -1, -1, 418, -1, 423, 423, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 322, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 339, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 422, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 52, 122, 148, 127, 122, 201, 273, 184, 0, 127, 277, 165, 0, 265, 64, 190, 396, 133, + 170, 149, 433, 144, 145, 159, 233, 163, 133, 134, 163, 150, 154, 402, 150, 171, 163, 170, 154, + 165, 215, 248, 162, 162, 171, 171, 162, 181, 182, 460, 168, 170, 246, 171, 170, 161, 184, 171, + 179, 180, 165, 163, 235, 432, 168, 168, 188, 171, 170, 447, 163, 190, 188, 451, 190, 125, 165, + 170, 142, 143, 163, 233, 162, 162, 162, 133, 236, 170, 168, 168, 168, 162, 357, 163, 162, 289, + 248, 168, 273, 163, 168, 162, 277, 167, 171, 155, 156, 168, 133, 134, 199, 200, 305, 306, 307, + 308, 235, 236, 293, 235, 236, 168, 168, 122, 171, 171, 165, 168, 127, 218, 171, 5, 6, 7, + 165, 173, 330, 175, 161, 138, 334, 163, 141, 171, 233, 279, 133, 134, 138, 322, 161, 150, 138, + 403, 170, 154, 176, 177, 178, 248, 140, 141, 183, 162, 146, 147, 136, 137, 168, 169, 162, 170, + 301, 302, 309, 310, 351, 176, 303, 304, 161, 446, 357, 148, 182, 181, 150, 164, 171, 188, 161, + 190, 171, 161, 161, 171, 169, 391, 161, 161, 166, 162, 67, 322, 164, 164, 322, 165, 402, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 169, 315, 168, 161, + 363, 405, 161, 166, 170, 162, 171, 235, 236, 432, 162, 18, 162, 171, 312, 390, 439, 290, 313, + 311, 388, 315, 395, 154, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 438, 458, 150, 265, + 154, 6, 278, 239, 446, 170, 361, 397, 451, 432, 339, 138, -1, 397, -1, -1, 402, -1, -1, + -1, -1, -1, -1, 434, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, 390, -1, 425, -1, + -1, -1, -1, -1, 425, -1, -1, -1, 432, -1, -1, -1, -1, -1, -1, -1, -1, -1, 322, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 339, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 424, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 396, 397, -1, -1, -1, -1, 402, 403, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 418, -1, -1, -1, -1, 423, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 436, - -1, -1, -1, 440, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + -1, -1, -1, -1, -1, -1, -1, 425, -1, -1, -1, -1, -1, -1, 432, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 447, -1, -1, -1, 451, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 161, -1, -1, -1, 165, 166, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 161, -1, -1, -1, 165, 166, -1, -1, -1, -1, 171, 172, 173, 174, 175, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, -1, -1, -1, -1, -1, 171, 172, 173, + 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, -1, -1, -1, -1, -1, 171, + 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, @@ -1479,108 +1542,79 @@ static const yytype_int16 yycheck[] = { 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, 166, -1, -1, -1, - -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, 166, -1, - -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, 161, 9, 10, 11, 12, 13, 14, + -1, -1, -1, 171, 172, 173, 174, 175, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, 161, 9, 10, 11, 12, 13, + 14, -1, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, - -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, - -1, 165, -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, - 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, - -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, - 7, 161, 9, 10, 11, 12, 13, 14, -1, -1, -1, 171, 172, 173, 174, 175, -1, -1, -1, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - 6, 7, 161, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, 172, 173, 174, 175, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, 133, 134, -1, 11, 12, 13, - 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, 171, 47, 48, 49, 50, 51, - 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, 164, 11, - 12, 13, 14, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, -1, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, - 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, - 164, 11, 12, 13, 14, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, -1, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, - 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, - 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, - 11, 12, 13, 14, -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, -1, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, - 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, 11, - 12, 13, 14, -1, -1, -1, -1, -1, -1, 172, 173, 174, 175, -1, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, - 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, 161, 9, 10, - 11, 12, 13, 14, -1, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, 26, 27, 28, 29, + 128, 129, 130, 131, -1, 133, 134, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + -1, -1, -1, -1, -1, 171, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, + 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 161, -1, -1, 164, 11, 12, 13, 14, -1, -1, -1, 172, 173, + 174, 175, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, 132, 133, + 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, 164, 11, 12, 13, 14, -1, -1, -1, + 172, 173, 174, 175, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, + 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, 11, 12, 13, 14, -1, -1, -1, -1, + -1, 171, 172, 173, 174, 175, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, 132, + 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, 11, 12, 13, 14, -1, -1, -1, -1, -1, + -1, 172, 173, 174, 175, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, 132, 133, + 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3, 4, 5, 6, 7, 161, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, + 172, 173, 174, 175, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, + -1, 134, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, -1, 9, 10, + 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 166, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, @@ -1594,48 +1628,41 @@ static const yytype_int16 yycheck[] = { 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, + -1, -1, -1, -1, -1, 0, -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 166, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, -1, -1, 0, -1, -1, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 166, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 128, 129, 130, 131, -1, -1, 134, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, -1, -1, 134, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, 14, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, -1, -1, 134, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, + -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 3, 4, 5, 6, 7, - -1, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 11, 12, 13, 14, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, - 131, -1, 133, 134, 11, 12, 13, 14, 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, - -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, -1, -1, 134}; + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, -1, 133, 134, 11, 12, 13, 14, + 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, -1, 131, -1, -1, 134}; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of state STATE-NUM. */ @@ -1646,59 +1673,60 @@ static const yytype_int16 yystos[] = { 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 134, 217, 218, 219, 220, 221, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 239, 241, 242, 277, 278, 279, 235, 133, 134, 165, 186, 161, 171, 280, 162, 168, 222, - 223, 224, 229, 234, 168, 171, 133, 186, 133, 171, 216, 232, 234, 163, 240, 0, 278, 239, 244, - 165, 64, 133, 237, 238, 165, 260, 223, 222, 224, 186, 186, 161, 170, 240, 165, 171, 229, 234, - 245, 246, 132, 133, 135, 136, 137, 138, 139, 142, 143, 161, 164, 172, 173, 174, 175, 187, 188, + 129, 130, 131, 134, 222, 223, 224, 225, 226, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 244, 246, 247, 288, 289, 290, 240, 133, 134, 165, 186, 161, 171, 291, 162, 168, 227, + 228, 229, 234, 239, 168, 171, 133, 186, 133, 171, 221, 237, 239, 163, 245, 0, 289, 244, 249, + 165, 64, 133, 242, 243, 165, 265, 228, 227, 229, 186, 186, 161, 170, 245, 165, 171, 234, 239, + 250, 251, 132, 133, 135, 136, 137, 138, 139, 142, 143, 161, 164, 172, 173, 174, 175, 187, 188, 189, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 215, 239, 163, 171, 245, 243, 170, 162, 168, 15, 16, 17, 19, 20, 21, 22, - 23, 24, 25, 67, 165, 166, 171, 198, 211, 212, 214, 217, 218, 239, 250, 251, 252, 253, 261, - 262, 263, 265, 267, 269, 276, 240, 170, 240, 212, 249, 170, 234, 186, 247, 248, 166, 246, 198, - 198, 214, 142, 143, 163, 167, 162, 162, 168, 66, 212, 161, 198, 176, 177, 178, 173, 175, 140, - 141, 144, 145, 179, 180, 146, 147, 183, 182, 181, 148, 150, 149, 184, 164, 164, 215, 166, 245, - 136, 137, 238, 171, 171, 271, 161, 161, 171, 171, 214, 161, 215, 169, 161, 166, 254, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, 170, 213, 168, 171, 166, 251, 249, 170, 249, 247, 240, - 168, 171, 133, 171, 162, 190, 214, 133, 139, 193, 212, 198, 198, 198, 200, 200, 201, 201, 202, - 202, 202, 202, 203, 203, 204, 205, 206, 207, 208, 209, 214, 164, 166, 257, 258, 259, 272, 214, - 171, 214, 169, 270, 261, 212, 212, 249, 171, 248, 171, 240, 164, 169, 67, 260, 252, 250, 262, - 273, 162, 162, 214, 227, 229, 268, 255, 171, 212, 161, 268, 274, 275, 257, 264, 266, 186, 162, - 166, 214, 171, 162, 18, 253, 170, 252, 256, 260, 162, 214, 256, 257, 249, 171}; + 210, 211, 213, 220, 244, 163, 171, 250, 248, 170, 162, 168, 15, 16, 17, 19, 20, 21, 22, + 23, 24, 25, 67, 165, 166, 171, 198, 213, 216, 218, 222, 223, 244, 255, 256, 257, 258, 266, + 267, 268, 272, 274, 276, 287, 245, 170, 245, 216, 254, 170, 239, 186, 252, 253, 166, 251, 198, + 198, 218, 142, 143, 163, 167, 162, 162, 168, 66, 216, 161, 198, 176, 177, 178, 173, 175, 140, + 141, 144, 145, 179, 180, 146, 147, 183, 182, 181, 148, 150, 149, 184, 164, 164, 220, 166, 250, + 136, 137, 243, 171, 171, 279, 161, 161, 171, 171, 218, 161, 220, 169, 161, 166, 259, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 170, 217, 168, 171, 166, 256, 254, 170, 254, 252, 245, + 168, 171, 133, 171, 162, 190, 218, 133, 139, 193, 216, 198, 198, 198, 200, 200, 201, 201, 202, + 202, 202, 202, 203, 203, 204, 205, 206, 209, 208, 212, 214, 164, 166, 262, 263, 264, 281, 218, + 171, 218, 169, 277, 266, 216, 219, 254, 171, 253, 171, 245, 164, 207, 210, 218, 67, 265, 257, + 255, 267, 283, 162, 162, 218, 232, 234, 275, 260, 216, 171, 169, 161, 282, 269, 273, 186, 278, + 166, 215, 280, 275, 284, 285, 262, 270, 265, 170, 162, 216, 218, 171, 162, 18, 254, 257, 261, + 265, 162, 286, 261, 271, 171, 218, 262}; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int16 yyr1[] = { 0, 185, 186, 186, 187, 188, 188, 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, 189, 190, 191, 192, 192, 193, 193, 194, 194, 195, 195, 196, 197, 197, 197, 198, 198, 198, 198, 199, 199, 199, 199, 200, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, 203, 204, 204, - 204, 205, 205, 206, 206, 207, 207, 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, 213, 214, 214, 215, 216, 217, 217, 217, 217, 217, 217, - 217, 217, 218, 219, 219, 220, 220, 221, 222, 222, 223, 223, 223, 223, 224, 225, 225, 225, 225, - 225, 226, 226, 226, 226, 226, 227, 227, 228, 228, 228, 229, 229, 230, 231, 232, 232, 232, 232, - 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 234, 235, 235, 235, 236, 237, 237, 238, 238, 238, 238, 239, 239, 240, 240, 240, 240, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 243, 242, 244, 242, 245, 245, 246, - 246, 247, 247, 248, 248, 249, 250, 251, 251, 252, 252, 252, 252, 252, 252, 252, 253, 254, 255, - 253, 256, 256, 258, 257, 259, 257, 260, 260, 261, 261, 262, 262, 263, 264, 264, 266, 265, 267, - 267, 268, 268, 270, 269, 271, 269, 272, 269, 273, 273, 274, 274, 275, 275, 276, 276, 276, 276, - 276, 277, 277, 278, 278, 280, 279}; + 204, 205, 205, 206, 206, 207, 207, 208, 209, 208, 210, 210, 211, 212, 211, 213, 214, 215, 213, + 216, 216, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 218, 219, 218, 220, 221, 222, + 222, 222, 222, 222, 222, 222, 222, 223, 224, 224, 225, 225, 226, 227, 227, 228, 228, 228, 228, + 229, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 232, 232, 233, 233, 233, 234, 234, 235, + 236, 237, 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 239, 240, 240, 240, 241, 242, 242, 243, 243, 243, 243, 244, 244, 245, + 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 248, 247, + 249, 247, 250, 250, 251, 251, 252, 252, 253, 253, 254, 255, 256, 256, 257, 257, 257, 257, 257, + 257, 257, 258, 259, 260, 258, 261, 261, 263, 262, 264, 262, 265, 265, 266, 266, 267, 267, 269, + 268, 271, 270, 270, 273, 272, 274, 274, 275, 275, 277, 278, 276, 279, 280, 276, 281, 282, 276, + 283, 283, 284, 284, 285, 286, 285, 287, 287, 287, 287, 287, 288, 288, 289, 289, 291, 290}; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { - 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, 3, 2, 2, 1, 1, 1, 3, 2, 2, 2, 1, 2, 3, 2, 1, - 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 2, - 2, 4, 5, 6, 7, 2, 3, 2, 1, 1, 2, 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, 3, 4, 6, 5, 1, 2, 3, 5, 4, - 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 4, 1, 3, 1, 3, 3, 1, 1, 2, 2, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 0, 5, 1, 2, 3, 4, 1, 3, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, 1, 2, 1, 2, 5, 3, - 1, 0, 6, 3, 2, 1, 4, 0, 6, 0, 8, 0, 7, 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, 2, 1, 1, 0, 3}; + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, 3, 2, 2, 1, 1, 1, 3, 2, 2, 2, 1, 2, 3, 2, 1, 1, + 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, + 1, 3, 1, 0, 4, 1, 3, 1, 0, 4, 1, 0, 0, 7, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 1, + 2, 2, 2, 4, 5, 6, 7, 2, 3, 2, 1, 1, 2, 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, 3, 4, 6, 5, 1, 2, 3, 5, + 4, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 4, 1, 3, 1, 3, 3, 1, 1, 2, 2, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 0, 5, 1, 2, 3, 4, 1, 3, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, 1, 2, 1, 2, 0, 6, 0, 4, 1, 0, 6, + 3, 2, 1, 4, 0, 0, 7, 0, 0, 9, 0, 0, 8, 1, 1, 1, 0, 2, 0, 4, 2, 2, 2, 3, 2, 1, 2, 1, 1, 0, 3}; enum { @@ -1800,7 +1828,9 @@ static int yy_location_print_(FILE *yyo, YYLTYPE const *const yylocp) { res += YYFPRINTF(yyo, "%d", yylocp->first_line); if (0 <= yylocp->first_column) + { res += YYFPRINTF(yyo, ".%d", yylocp->first_column); + } } if (0 <= yylocp->last_line) { @@ -1808,10 +1838,14 @@ static int yy_location_print_(FILE *yyo, YYLTYPE const *const yylocp) { res += YYFPRINTF(yyo, "-%d", yylocp->last_line); if (0 <= end_col) + { res += YYFPRINTF(yyo, ".%d", end_col); + } } else if (0 <= end_col && yylocp->first_column < end_col) + { res += YYFPRINTF(yyo, "-%d", end_col); + } } return res; } @@ -1860,7 +1894,9 @@ static void yy_symbol_value_print(FILE *yyo, YY_USE(context); YY_USE(scanner); if (!yyvaluep) + { return; + } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE(yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END @@ -1983,7 +2019,9 @@ static void yydestruct(const char *yymsg, YY_USE(context); YY_USE(scanner); if (!yymsg) + { yymsg = "Deleting"; + } YY_SYMBOL_PRINT(yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN @@ -2117,23 +2155,31 @@ int yyparse(TParseContext *context, void *scanner) # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) + { YYNOMEM; + } yystacksize *= 2; if (YYMAXDEPTH < yystacksize) + { yystacksize = YYMAXDEPTH; + } { yy_state_t *yyss1 = yyss; union yyalloc *yyptr = YY_CAST( union yyalloc *, YYSTACK_ALLOC(YY_CAST(YYSIZE_T, YYSTACK_BYTES(yystacksize)))); if (!yyptr) + { YYNOMEM; + } YYSTACK_RELOCATE(yyss_alloc, yyss); YYSTACK_RELOCATE(yyvs_alloc, yyvs); YYSTACK_RELOCATE(yyls_alloc, yyls); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) + { YYSTACK_FREE(yyss1); + } } # endif @@ -2146,12 +2192,16 @@ int yyparse(TParseContext *context, void *scanner) YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) + { YYABORT; + } } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ if (yystate == YYFINAL) + { YYACCEPT; + } goto yybackup; @@ -2165,7 +2215,9 @@ int yyparse(TParseContext *context, void *scanner) /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default(yyn)) + { goto yydefault; + } /* Not known => get a lookahead token if don't already have one. */ @@ -2203,12 +2255,16 @@ int yyparse(TParseContext *context, void *scanner) detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + { goto yydefault; + } yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error(yyn)) + { goto yyerrlab; + } yyn = -yyn; goto yyreduce; } @@ -2216,7 +2272,9 @@ int yyparse(TParseContext *context, void *scanner) /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) + { yyerrstatus--; + } /* Shift the lookahead token. */ YY_SYMBOL_PRINT("Shifting", yytoken, &yylval, &yylloc); @@ -2236,7 +2294,9 @@ int yyparse(TParseContext *context, void *scanner) yydefault: yyn = yydefact[yystate]; if (yyn == 0) + { goto yyerrlab; + } goto yyreduce; /*-----------------------------. @@ -2706,21 +2766,28 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 65: /* logical_and_expression: logical_and_expression AND_OP inclusive_or_expression */ + case 65: /* $@1: %empty */ + { + context->onShortCircuitAndBegin((yyvsp[-1].interm.intermTypedNode), (yylsp[0])); + } + break; + + case 66: /* logical_and_expression: logical_and_expression AND_OP $@1 + inclusive_or_expression */ { (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( - EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), - (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + EOpLogicalAnd, (yyvsp[-3].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-2])); } break; - case 66: /* logical_xor_expression: logical_and_expression */ + case 67: /* logical_xor_expression: logical_and_expression */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 67: /* logical_xor_expression: logical_xor_expression XOR_OP logical_and_expression */ + case 68: /* logical_xor_expression: logical_xor_expression XOR_OP logical_and_expression */ { (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), @@ -2728,42 +2795,60 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 68: /* logical_or_expression: logical_xor_expression */ + case 69: /* logical_or_expression: logical_xor_expression */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 69: /* logical_or_expression: logical_or_expression OR_OP logical_xor_expression */ + case 70: /* $@2: %empty */ + { + context->onShortCircuitOrBegin((yyvsp[-1].interm.intermTypedNode), (yylsp[0])); + } + break; + + case 71: /* logical_or_expression: logical_or_expression OR_OP $@2 logical_xor_expression */ { (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( - EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), - (yylsp[-1])); + EOpLogicalOr, (yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), + (yylsp[-2])); } break; - case 70: /* conditional_expression: logical_or_expression */ + case 72: /* conditional_expression: logical_or_expression */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 71: /* conditional_expression: logical_or_expression QUESTION expression COLON + case 73: /* $@3: %empty */ + { + context->onTernaryConditionParsed((yyvsp[-1].interm.intermTypedNode), (yylsp[0])); + } + break; + + case 74: /* $@4: %empty */ + { + context->onTernaryTrueExpressionParsed((yyvsp[-1].interm.intermTypedNode), (yylsp[-3])); + } + break; + + case 75: /* conditional_expression: logical_or_expression QUESTION $@3 expression COLON $@4 assignment_expression */ { (yyval.interm.intermTypedNode) = context->addTernarySelection( - (yyvsp[-4].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), - (yyvsp[0].interm.intermTypedNode), (yylsp[-3])); + (yyvsp[-6].interm.intermTypedNode), (yyvsp[-3].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-5])); } break; - case 72: /* assignment_expression: conditional_expression */ + case 76: /* assignment_expression: conditional_expression */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 73: /* assignment_expression: unary_expression assignment_operator + case 77: /* assignment_expression: unary_expression assignment_operator assignment_expression */ { (yyval.interm.intermTypedNode) = @@ -2772,119 +2857,125 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 74: /* assignment_operator: EQUAL */ + case 78: /* assignment_operator: EQUAL */ { (yyval.interm.op) = EOpAssign; } break; - case 75: /* assignment_operator: MUL_ASSIGN */ + case 79: /* assignment_operator: MUL_ASSIGN */ { (yyval.interm.op) = EOpMulAssign; } break; - case 76: /* assignment_operator: DIV_ASSIGN */ + case 80: /* assignment_operator: DIV_ASSIGN */ { (yyval.interm.op) = EOpDivAssign; } break; - case 77: /* assignment_operator: MOD_ASSIGN */ + case 81: /* assignment_operator: MOD_ASSIGN */ { ES3_OR_NEWER("%=", (yyloc), "integer modulus operator"); (yyval.interm.op) = EOpIModAssign; } break; - case 78: /* assignment_operator: ADD_ASSIGN */ + case 82: /* assignment_operator: ADD_ASSIGN */ { (yyval.interm.op) = EOpAddAssign; } break; - case 79: /* assignment_operator: SUB_ASSIGN */ + case 83: /* assignment_operator: SUB_ASSIGN */ { (yyval.interm.op) = EOpSubAssign; } break; - case 80: /* assignment_operator: LEFT_ASSIGN */ + case 84: /* assignment_operator: LEFT_ASSIGN */ { ES3_OR_NEWER("<<=", (yyloc), "bit-wise operator"); (yyval.interm.op) = EOpBitShiftLeftAssign; } break; - case 81: /* assignment_operator: RIGHT_ASSIGN */ + case 85: /* assignment_operator: RIGHT_ASSIGN */ { ES3_OR_NEWER(">>=", (yyloc), "bit-wise operator"); (yyval.interm.op) = EOpBitShiftRightAssign; } break; - case 82: /* assignment_operator: AND_ASSIGN */ + case 86: /* assignment_operator: AND_ASSIGN */ { ES3_OR_NEWER("&=", (yyloc), "bit-wise operator"); (yyval.interm.op) = EOpBitwiseAndAssign; } break; - case 83: /* assignment_operator: XOR_ASSIGN */ + case 87: /* assignment_operator: XOR_ASSIGN */ { ES3_OR_NEWER("^=", (yyloc), "bit-wise operator"); (yyval.interm.op) = EOpBitwiseXorAssign; } break; - case 84: /* assignment_operator: OR_ASSIGN */ + case 88: /* assignment_operator: OR_ASSIGN */ { ES3_OR_NEWER("|=", (yyloc), "bit-wise operator"); (yyval.interm.op) = EOpBitwiseOrAssign; } break; - case 85: /* expression: assignment_expression */ + case 89: /* expression: assignment_expression */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 86: /* expression: expression COMMA assignment_expression */ + case 90: /* $@5: %empty */ + { + context->onCommaLeftHandSideParsed((yyvsp[-1].interm.intermTypedNode)); + } + break; + + case 91: /* expression: expression COMMA $@5 assignment_expression */ { (yyval.interm.intermTypedNode) = context->addComma( - (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + (yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-2])); } break; - case 87: /* constant_expression: conditional_expression */ + case 92: /* constant_expression: conditional_expression */ { context->checkIsConst((yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 88: /* enter_struct: IDENTIFIER LEFT_BRACE */ + case 93: /* enter_struct: IDENTIFIER LEFT_BRACE */ { context->enterStructDeclaration((yylsp[-1]), ImmutableString((yyvsp[-1].lex).string)); (yyval.lex) = (yyvsp[-1].lex); } break; - case 89: /* declaration: function_prototype SEMICOLON */ + case 94: /* declaration: function_prototype SEMICOLON */ { (yyval.interm.intermNode) = context->addFunctionPrototypeDeclaration( *((yyvsp[-1].interm).function), (yylsp[-1])); } break; - case 90: /* declaration: init_declarator_list SEMICOLON */ + case 95: /* declaration: init_declarator_list SEMICOLON */ { (yyval.interm.intermNode) = (yyvsp[-1].interm).intermDeclaration; } break; - case 91: /* declaration: PRECISION precision_qualifier type_specifier_no_prec SEMICOLON */ + case 96: /* declaration: PRECISION precision_qualifier type_specifier_no_prec SEMICOLON */ { context->parseDefaultPrecisionQualifier((yyvsp[-2].interm.precision), (yyvsp[-1].interm.type), (yylsp[-3])); @@ -2892,7 +2983,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 92: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE + case 97: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON */ { ES3_OR_NEWER(ImmutableString((yyvsp[-3].lex).string), (yylsp[-4]), "interface blocks"); @@ -2903,7 +2994,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 93: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE + case 98: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON */ { ES3_OR_NEWER(ImmutableString((yyvsp[-4].lex).string), (yylsp[-5]), "interface blocks"); @@ -2914,7 +3005,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 94: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE + case 99: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON */ { ES3_OR_NEWER(ImmutableString((yyvsp[-5].lex).string), (yylsp[-6]), "interface blocks"); @@ -2926,14 +3017,14 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 95: /* declaration: type_qualifier SEMICOLON */ + case 100: /* declaration: type_qualifier SEMICOLON */ { context->parseGlobalLayoutQualifier(*(yyvsp[-1].interm.typeQualifierBuilder)); (yyval.interm.intermNode) = nullptr; } break; - case 96: /* declaration: type_qualifier IDENTIFIER SEMICOLON */ + case 101: /* declaration: type_qualifier IDENTIFIER SEMICOLON */ { (yyval.interm.intermNode) = context->parseGlobalQualifierDeclaration( *(yyvsp[-2].interm.typeQualifierBuilder), (yylsp[-1]), @@ -2941,7 +3032,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 97: /* function_prototype: function_declarator RIGHT_PAREN */ + case 102: /* function_prototype: function_declarator RIGHT_PAREN */ { (yyval.interm).function = context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function)); @@ -2949,26 +3040,25 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 98: /* function_declarator: function_header */ + case 103: /* function_declarator: function_header */ { (yyval.interm.function) = (yyvsp[0].interm.function); } break; - case 99: /* function_declarator: function_header_with_parameters */ + case 104: /* function_declarator: function_header_with_parameters */ { (yyval.interm.function) = (yyvsp[0].interm.function); } break; - case 100: /* function_header_with_parameters: function_header parameter_declaration */ + case 105: /* function_header_with_parameters: function_header parameter_declaration */ { // Add the parameter (yyval.interm.function) = (yyvsp[-1].interm.function); if ((yyvsp[0].interm.param).type.getBasicType() != EbtVoid) { - (yyvsp[-1].interm.function) - ->addParameter((yyvsp[0].interm.param).createVariable(&context->symbolTable)); + context->addParameter((yyvsp[-1].interm.function), &(yyvsp[0].interm.param)); } else { @@ -2979,7 +3069,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 101: /* function_header_with_parameters: function_header_with_parameters COMMA + case 106: /* function_header_with_parameters: function_header_with_parameters COMMA parameter_declaration */ { (yyval.interm.function) = (yyvsp[-2].interm.function); @@ -3000,13 +3090,12 @@ int yyparse(TParseContext *context, void *scanner) context->error((yylsp[-1]), "cannot be a parameter type except for '(void)'", "void"); } - (yyvsp[-2].interm.function) - ->addParameter((yyvsp[0].interm.param).createVariable(&context->symbolTable)); + context->addParameter((yyvsp[-2].interm.function), &(yyvsp[0].interm.param)); } } break; - case 102: /* function_header: fully_specified_type IDENTIFIER LEFT_PAREN */ + case 107: /* function_header: fully_specified_type IDENTIFIER LEFT_PAREN */ { (yyval.interm.function) = context->parseFunctionHeader( (yyvsp[-2].interm.type), ImmutableString((yyvsp[-1].lex).string), (yylsp[-1])); @@ -3016,14 +3105,14 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 103: /* parameter_declarator: type_specifier identifier */ + case 108: /* parameter_declarator: type_specifier identifier */ { (yyval.interm.param) = context->parseParameterDeclarator( (yyvsp[-1].interm.type), ImmutableString((yyvsp[0].lex).string), (yylsp[0])); } break; - case 104: /* parameter_declarator: type_specifier identifier array_specifier */ + case 109: /* parameter_declarator: type_specifier identifier array_specifier */ { (yyval.interm.param) = context->parseParameterArrayDeclarator( (yyvsp[-2].interm.type), ImmutableString((yyvsp[-1].lex).string), (yylsp[-1]), @@ -3031,7 +3120,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 105: /* parameter_declaration: type_qualifier parameter_declarator */ + case 110: /* parameter_declaration: type_qualifier parameter_declarator */ { (yyval.interm.param) = (yyvsp[0].interm.param); context->parseParameterQualifier((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), @@ -3039,14 +3128,14 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 106: /* parameter_declaration: parameter_declarator */ + case 111: /* parameter_declaration: parameter_declarator */ { (yyval.interm.param) = (yyvsp[0].interm.param); (yyval.interm.param).type.setQualifier(EvqParamIn); } break; - case 107: /* parameter_declaration: type_qualifier parameter_type_specifier */ + case 112: /* parameter_declaration: type_qualifier parameter_type_specifier */ { (yyval.interm.param) = context->parseParameterDeclarator( (yyvsp[0].interm.type), kEmptyImmutableString, (yylsp[0])); @@ -3055,7 +3144,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 108: /* parameter_declaration: parameter_type_specifier */ + case 113: /* parameter_declaration: parameter_type_specifier */ { (yyval.interm.param) = context->parseParameterDeclarator( (yyvsp[0].interm.type), kEmptyImmutableString, (yylsp[0])); @@ -3063,19 +3152,19 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 109: /* parameter_type_specifier: type_specifier */ + case 114: /* parameter_type_specifier: type_specifier */ { (yyval.interm.type) = (yyvsp[0].interm.type); } break; - case 110: /* init_declarator_list: single_declaration */ + case 115: /* init_declarator_list: single_declaration */ { (yyval.interm) = (yyvsp[0].interm); } break; - case 111: /* init_declarator_list: init_declarator_list COMMA identifier */ + case 116: /* init_declarator_list: init_declarator_list COMMA identifier */ { (yyval.interm) = (yyvsp[-2].interm); context->parseDeclarator((yyval.interm).type, (yylsp[0]), @@ -3084,7 +3173,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 112: /* init_declarator_list: init_declarator_list COMMA identifier array_specifier */ + case 117: /* init_declarator_list: init_declarator_list COMMA identifier array_specifier */ { (yyval.interm) = (yyvsp[-3].interm); context->parseArrayDeclarator( @@ -3093,7 +3182,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 113: /* init_declarator_list: init_declarator_list COMMA identifier array_specifier + case 118: /* init_declarator_list: init_declarator_list COMMA identifier array_specifier EQUAL initializer */ { ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)"); @@ -3105,7 +3194,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 114: /* init_declarator_list: init_declarator_list COMMA identifier EQUAL initializer + case 119: /* init_declarator_list: init_declarator_list COMMA identifier EQUAL initializer */ { (yyval.interm) = (yyvsp[-4].interm); @@ -3115,7 +3204,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 115: /* single_declaration: fully_specified_type */ + case 120: /* single_declaration: fully_specified_type */ { (yyval.interm).type = (yyvsp[0].interm.type); (yyval.interm).intermDeclaration = context->parseSingleDeclaration( @@ -3123,7 +3212,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 116: /* single_declaration: fully_specified_type identifier */ + case 121: /* single_declaration: fully_specified_type identifier */ { (yyval.interm).type = (yyvsp[-1].interm.type); (yyval.interm).intermDeclaration = context->parseSingleDeclaration( @@ -3131,7 +3220,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 117: /* single_declaration: fully_specified_type identifier array_specifier */ + case 122: /* single_declaration: fully_specified_type identifier array_specifier */ { (yyval.interm).type = (yyvsp[-2].interm.type); (yyval.interm).intermDeclaration = context->parseSingleArrayDeclaration( @@ -3140,7 +3229,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 118: /* single_declaration: fully_specified_type identifier array_specifier EQUAL + case 123: /* single_declaration: fully_specified_type identifier array_specifier EQUAL initializer */ { ES3_OR_NEWER("[]", (yylsp[-2]), "first-class arrays (array initializer)"); @@ -3152,7 +3241,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 119: /* single_declaration: fully_specified_type identifier EQUAL initializer */ + case 124: /* single_declaration: fully_specified_type identifier EQUAL initializer */ { (yyval.interm).type = (yyvsp[-3].interm.type); (yyval.interm).intermDeclaration = context->parseSingleInitDeclaration( @@ -3161,33 +3250,33 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 120: /* fully_specified_type: type_specifier */ + case 125: /* fully_specified_type: type_specifier */ { context->addFullySpecifiedType(&(yyvsp[0].interm.type)); (yyval.interm.type) = (yyvsp[0].interm.type); } break; - case 121: /* fully_specified_type: type_qualifier type_specifier */ + case 126: /* fully_specified_type: type_qualifier type_specifier */ { (yyval.interm.type) = context->addFullySpecifiedType( *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.type)); } break; - case 122: /* interpolation_qualifier: SMOOTH */ + case 127: /* interpolation_qualifier: SMOOTH */ { (yyval.interm.qualifier) = EvqSmooth; } break; - case 123: /* interpolation_qualifier: FLAT */ + case 128: /* interpolation_qualifier: FLAT */ { (yyval.interm.qualifier) = EvqFlat; } break; - case 124: /* interpolation_qualifier: NOPERSPECTIVE */ + case 129: /* interpolation_qualifier: NOPERSPECTIVE */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::NV_shader_noperspective_interpolation)) @@ -3198,7 +3287,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 125: /* type_qualifier: single_type_qualifier */ + case 130: /* type_qualifier: single_type_qualifier */ { (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0])); (yyval.interm.typeQualifierBuilder) @@ -3206,7 +3295,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 126: /* type_qualifier: type_qualifier single_type_qualifier */ + case 131: /* type_qualifier: type_qualifier single_type_qualifier */ { (yyval.interm.typeQualifierBuilder) = (yyvsp[-1].interm.typeQualifierBuilder); (yyval.interm.typeQualifierBuilder) @@ -3214,26 +3303,26 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 127: /* invariant_qualifier: INVARIANT */ + case 132: /* invariant_qualifier: INVARIANT */ { // empty } break; - case 128: /* precise_qualifier: PRECISE */ + case 133: /* precise_qualifier: PRECISE */ { context->markShaderHasPrecise(); } break; - case 129: /* single_type_qualifier: storage_qualifier */ + case 134: /* single_type_qualifier: storage_qualifier */ { context->checkLocalVariableConstStorageQualifier(*(yyvsp[0].interm.qualifierWrapper)); (yyval.interm.qualifierWrapper) = (yyvsp[0].interm.qualifierWrapper); } break; - case 130: /* single_type_qualifier: layout_qualifier */ + case 135: /* single_type_qualifier: layout_qualifier */ { context->checkIsAtGlobalLevel((yylsp[0]), "layout"); (yyval.interm.qualifierWrapper) = @@ -3241,34 +3330,34 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 131: /* single_type_qualifier: precision_qualifier */ + case 136: /* single_type_qualifier: precision_qualifier */ { (yyval.interm.qualifierWrapper) = new TPrecisionQualifierWrapper((yyvsp[0].interm.precision), (yylsp[0])); } break; - case 132: /* single_type_qualifier: interpolation_qualifier */ + case 137: /* single_type_qualifier: interpolation_qualifier */ { (yyval.interm.qualifierWrapper) = new TInterpolationQualifierWrapper((yyvsp[0].interm.qualifier), (yylsp[0])); } break; - case 133: /* single_type_qualifier: invariant_qualifier */ + case 138: /* single_type_qualifier: invariant_qualifier */ { context->checkIsAtGlobalLevel((yylsp[0]), "invariant"); (yyval.interm.qualifierWrapper) = new TInvariantQualifierWrapper((yylsp[0])); } break; - case 134: /* single_type_qualifier: precise_qualifier */ + case 139: /* single_type_qualifier: precise_qualifier */ { (yyval.interm.qualifierWrapper) = new TPreciseQualifierWrapper((yylsp[0])); } break; - case 135: /* storage_qualifier: ATTRIBUTE */ + case 140: /* storage_qualifier: ATTRIBUTE */ { VERTEX_ONLY("attribute", (yylsp[0])); ES2_ONLY("attribute", (yylsp[0])); @@ -3277,45 +3366,45 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 136: /* storage_qualifier: VARYING */ + case 141: /* storage_qualifier: VARYING */ { ES2_ONLY("varying", (yylsp[0])); (yyval.interm.qualifierWrapper) = context->parseVaryingQualifier((yylsp[0])); } break; - case 137: /* storage_qualifier: CONST_QUAL */ + case 142: /* storage_qualifier: CONST_QUAL */ { (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqConst, (yylsp[0])); } break; - case 138: /* storage_qualifier: IN_QUAL */ + case 143: /* storage_qualifier: IN_QUAL */ { (yyval.interm.qualifierWrapper) = context->parseInQualifier((yylsp[0])); } break; - case 139: /* storage_qualifier: OUT_QUAL */ + case 144: /* storage_qualifier: OUT_QUAL */ { (yyval.interm.qualifierWrapper) = context->parseOutQualifier((yylsp[0])); } break; - case 140: /* storage_qualifier: INOUT_QUAL */ + case 145: /* storage_qualifier: INOUT_QUAL */ { (yyval.interm.qualifierWrapper) = context->parseInOutQualifier((yylsp[0])); } break; - case 141: /* storage_qualifier: CENTROID */ + case 146: /* storage_qualifier: CENTROID */ { ES3_OR_NEWER("centroid", (yylsp[0]), "storage qualifier"); (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqCentroid, (yylsp[0])); } break; - case 142: /* storage_qualifier: PATCH */ + case 147: /* storage_qualifier: PATCH */ { constexpr std::array extensions{ {TExtension::OES_tessellation_shader, TExtension::EXT_tessellation_shader}}; @@ -3328,14 +3417,14 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 143: /* storage_qualifier: UNIFORM */ + case 148: /* storage_qualifier: UNIFORM */ { (yyval.interm.qualifierWrapper) = context->parseGlobalStorageQualifier(EvqUniform, (yylsp[0])); } break; - case 144: /* storage_qualifier: BUFFER */ + case 149: /* storage_qualifier: BUFFER */ { ES3_1_OR_NEWER("buffer", (yylsp[0]), "storage qualifier"); (yyval.interm.qualifierWrapper) = @@ -3343,37 +3432,37 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 145: /* storage_qualifier: READONLY */ + case 150: /* storage_qualifier: READONLY */ { (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqReadOnly, (yylsp[0])); } break; - case 146: /* storage_qualifier: WRITEONLY */ + case 151: /* storage_qualifier: WRITEONLY */ { (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqWriteOnly, (yylsp[0])); } break; - case 147: /* storage_qualifier: COHERENT */ + case 152: /* storage_qualifier: COHERENT */ { (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqCoherent, (yylsp[0])); } break; - case 148: /* storage_qualifier: RESTRICT */ + case 153: /* storage_qualifier: RESTRICT */ { (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqRestrict, (yylsp[0])); } break; - case 149: /* storage_qualifier: VOLATILE */ + case 154: /* storage_qualifier: VOLATILE */ { (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqVolatile, (yylsp[0])); } break; - case 150: /* storage_qualifier: SHARED */ + case 155: /* storage_qualifier: SHARED */ { COMPUTE_ONLY("shared", (yylsp[0])); (yyval.interm.qualifierWrapper) = @@ -3381,14 +3470,14 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 151: /* storage_qualifier: SAMPLE */ + case 156: /* storage_qualifier: SAMPLE */ { ES3_OR_NEWER("sample", (yylsp[0]), "storage qualifier"); (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqSample, (yylsp[0])); } break; - case 152: /* type_specifier: type_specifier_no_prec */ + case 157: /* type_specifier: type_specifier_no_prec */ { (yyval.interm.type) = (yyvsp[0].interm.type); (yyval.interm.type).precision = @@ -3396,73 +3485,73 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 153: /* precision_qualifier: HIGH_PRECISION */ + case 158: /* precision_qualifier: HIGH_PRECISION */ { (yyval.interm.precision) = EbpHigh; } break; - case 154: /* precision_qualifier: MEDIUM_PRECISION */ + case 159: /* precision_qualifier: MEDIUM_PRECISION */ { (yyval.interm.precision) = EbpMedium; } break; - case 155: /* precision_qualifier: LOW_PRECISION */ + case 160: /* precision_qualifier: LOW_PRECISION */ { (yyval.interm.precision) = EbpLow; } break; - case 156: /* layout_qualifier: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN */ + case 161: /* layout_qualifier: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN */ { context->checkCanUseLayoutQualifier((yylsp[-3])); (yyval.interm.layoutQualifier) = (yyvsp[-1].interm.layoutQualifier); } break; - case 157: /* layout_qualifier_id_list: layout_qualifier_id */ + case 162: /* layout_qualifier_id_list: layout_qualifier_id */ { (yyval.interm.layoutQualifier) = (yyvsp[0].interm.layoutQualifier); } break; - case 158: /* layout_qualifier_id_list: layout_qualifier_id_list COMMA layout_qualifier_id */ + case 163: /* layout_qualifier_id_list: layout_qualifier_id_list COMMA layout_qualifier_id */ { (yyval.interm.layoutQualifier) = context->joinLayoutQualifiers( (yyvsp[-2].interm.layoutQualifier), (yyvsp[0].interm.layoutQualifier), (yylsp[0])); } break; - case 159: /* layout_qualifier_id: IDENTIFIER */ + case 164: /* layout_qualifier_id: IDENTIFIER */ { (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(ImmutableString((yyvsp[0].lex).string), (yylsp[0])); } break; - case 160: /* layout_qualifier_id: IDENTIFIER EQUAL INTCONSTANT */ + case 165: /* layout_qualifier_id: IDENTIFIER EQUAL INTCONSTANT */ { (yyval.interm.layoutQualifier) = context->parseLayoutQualifier( ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0])); } break; - case 161: /* layout_qualifier_id: IDENTIFIER EQUAL UINTCONSTANT */ + case 166: /* layout_qualifier_id: IDENTIFIER EQUAL UINTCONSTANT */ { (yyval.interm.layoutQualifier) = context->parseLayoutQualifier( ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0])); } break; - case 162: /* layout_qualifier_id: SHARED */ + case 167: /* layout_qualifier_id: SHARED */ { (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(ImmutableString("shared"), (yylsp[0])); } break; - case 163: /* type_specifier_no_prec: type_specifier_nonarray */ + case 168: /* type_specifier_no_prec: type_specifier_nonarray */ { (yyval.interm.type) .initialize((yyvsp[0].interm.typeSpecifierNonArray), @@ -3470,7 +3559,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 164: /* type_specifier_no_prec: type_specifier_nonarray array_specifier */ + case 169: /* type_specifier_no_prec: type_specifier_nonarray array_specifier */ { (yyval.interm.type) .initialize((yyvsp[-1].interm.typeSpecifierNonArray), @@ -3479,7 +3568,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 165: /* array_specifier: LEFT_BRACKET RIGHT_BRACKET */ + case 170: /* array_specifier: LEFT_BRACKET RIGHT_BRACKET */ { ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array"); (yyval.interm.arraySizes) = new TVector(); @@ -3487,7 +3576,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 166: /* array_specifier: LEFT_BRACKET constant_expression RIGHT_BRACKET */ + case 171: /* array_specifier: LEFT_BRACKET constant_expression RIGHT_BRACKET */ { (yyval.interm.arraySizes) = new TVector(); unsigned int size = @@ -3499,7 +3588,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 167: /* array_specifier: array_specifier LEFT_BRACKET RIGHT_BRACKET */ + case 172: /* array_specifier: array_specifier LEFT_BRACKET RIGHT_BRACKET */ { ES3_1_OR_NEWER("[]", (yylsp[-1]), "arrays of arrays"); (yyval.interm.arraySizes) = (yyvsp[-2].interm.arraySizes); @@ -3511,7 +3600,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 168: /* array_specifier: array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET + case 173: /* array_specifier: array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET */ { ES3_1_OR_NEWER("[]", (yylsp[-2]), "arrays of arrays"); @@ -3529,184 +3618,184 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 169: /* type_specifier_nonarray: VOID_TYPE */ + case 174: /* type_specifier_nonarray: VOID_TYPE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtVoid, (yylsp[0])); } break; - case 170: /* type_specifier_nonarray: FLOAT_TYPE */ + case 175: /* type_specifier_nonarray: FLOAT_TYPE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); } break; - case 171: /* type_specifier_nonarray: INT_TYPE */ + case 176: /* type_specifier_nonarray: INT_TYPE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); } break; - case 172: /* type_specifier_nonarray: UINT_TYPE */ + case 177: /* type_specifier_nonarray: UINT_TYPE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); } break; - case 173: /* type_specifier_nonarray: BOOL_TYPE */ + case 178: /* type_specifier_nonarray: BOOL_TYPE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); } break; - case 174: /* type_specifier_nonarray: VEC2 */ + case 179: /* type_specifier_nonarray: VEC2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(2); } break; - case 175: /* type_specifier_nonarray: VEC3 */ + case 180: /* type_specifier_nonarray: VEC3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(3); } break; - case 176: /* type_specifier_nonarray: VEC4 */ + case 181: /* type_specifier_nonarray: VEC4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(4); } break; - case 177: /* type_specifier_nonarray: BVEC2 */ + case 182: /* type_specifier_nonarray: BVEC2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(2); } break; - case 178: /* type_specifier_nonarray: BVEC3 */ + case 183: /* type_specifier_nonarray: BVEC3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(3); } break; - case 179: /* type_specifier_nonarray: BVEC4 */ + case 184: /* type_specifier_nonarray: BVEC4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(4); } break; - case 180: /* type_specifier_nonarray: IVEC2 */ + case 185: /* type_specifier_nonarray: IVEC2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(2); } break; - case 181: /* type_specifier_nonarray: IVEC3 */ + case 186: /* type_specifier_nonarray: IVEC3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(3); } break; - case 182: /* type_specifier_nonarray: IVEC4 */ + case 187: /* type_specifier_nonarray: IVEC4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(4); } break; - case 183: /* type_specifier_nonarray: UVEC2 */ + case 188: /* type_specifier_nonarray: UVEC2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(2); } break; - case 184: /* type_specifier_nonarray: UVEC3 */ + case 189: /* type_specifier_nonarray: UVEC3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(3); } break; - case 185: /* type_specifier_nonarray: UVEC4 */ + case 190: /* type_specifier_nonarray: UVEC4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setAggregate(4); } break; - case 186: /* type_specifier_nonarray: MATRIX2 */ + case 191: /* type_specifier_nonarray: MATRIX2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2); } break; - case 187: /* type_specifier_nonarray: MATRIX3 */ + case 192: /* type_specifier_nonarray: MATRIX3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3); } break; - case 188: /* type_specifier_nonarray: MATRIX4 */ + case 193: /* type_specifier_nonarray: MATRIX4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4); } break; - case 189: /* type_specifier_nonarray: MATRIX2x3 */ + case 194: /* type_specifier_nonarray: MATRIX2x3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3); } break; - case 190: /* type_specifier_nonarray: MATRIX3x2 */ + case 195: /* type_specifier_nonarray: MATRIX3x2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2); } break; - case 191: /* type_specifier_nonarray: MATRIX2x4 */ + case 196: /* type_specifier_nonarray: MATRIX2x4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4); } break; - case 192: /* type_specifier_nonarray: MATRIX4x2 */ + case 197: /* type_specifier_nonarray: MATRIX4x2 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2); } break; - case 193: /* type_specifier_nonarray: MATRIX3x4 */ + case 198: /* type_specifier_nonarray: MATRIX3x4 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4); } break; - case 194: /* type_specifier_nonarray: MATRIX4x3 */ + case 199: /* type_specifier_nonarray: MATRIX4x3 */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3); } break; - case 195: /* type_specifier_nonarray: YUVCSCSTANDARDEXT */ + case 200: /* type_specifier_nonarray: YUVCSCSTANDARDEXT */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target)) { @@ -3716,43 +3805,43 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 196: /* type_specifier_nonarray: SAMPLER2D */ + case 201: /* type_specifier_nonarray: SAMPLER2D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2D, (yylsp[0])); } break; - case 197: /* type_specifier_nonarray: SAMPLER3D */ + case 202: /* type_specifier_nonarray: SAMPLER3D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler3D, (yylsp[0])); } break; - case 198: /* type_specifier_nonarray: SAMPLERCUBE */ + case 203: /* type_specifier_nonarray: SAMPLERCUBE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCube, (yylsp[0])); } break; - case 199: /* type_specifier_nonarray: SAMPLER2DARRAY */ + case 204: /* type_specifier_nonarray: SAMPLER2DARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArray, (yylsp[0])); } break; - case 200: /* type_specifier_nonarray: SAMPLER2DMS */ + case 205: /* type_specifier_nonarray: SAMPLER2DMS */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMS, (yylsp[0])); } break; - case 201: /* type_specifier_nonarray: SAMPLER2DMSARRAY */ + case 206: /* type_specifier_nonarray: SAMPLER2DMSARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMSArray, (yylsp[0])); } break; - case 202: /* type_specifier_nonarray: SAMPLERCUBEARRAYOES */ + case 207: /* type_specifier_nonarray: SAMPLERCUBEARRAYOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -3763,7 +3852,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 203: /* type_specifier_nonarray: SAMPLERCUBEARRAYEXT */ + case 208: /* type_specifier_nonarray: SAMPLERCUBEARRAYEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -3774,7 +3863,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 204: /* type_specifier_nonarray: SAMPLERBUFFER */ + case 209: /* type_specifier_nonarray: SAMPLERBUFFER */ { constexpr std::array extensions{ {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; @@ -3787,43 +3876,43 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 205: /* type_specifier_nonarray: ISAMPLER2D */ + case 210: /* type_specifier_nonarray: ISAMPLER2D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2D, (yylsp[0])); } break; - case 206: /* type_specifier_nonarray: ISAMPLER3D */ + case 211: /* type_specifier_nonarray: ISAMPLER3D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler3D, (yylsp[0])); } break; - case 207: /* type_specifier_nonarray: ISAMPLERCUBE */ + case 212: /* type_specifier_nonarray: ISAMPLERCUBE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCube, (yylsp[0])); } break; - case 208: /* type_specifier_nonarray: ISAMPLER2DARRAY */ + case 213: /* type_specifier_nonarray: ISAMPLER2DARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DArray, (yylsp[0])); } break; - case 209: /* type_specifier_nonarray: ISAMPLER2DMS */ + case 214: /* type_specifier_nonarray: ISAMPLER2DMS */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMS, (yylsp[0])); } break; - case 210: /* type_specifier_nonarray: ISAMPLER2DMSARRAY */ + case 215: /* type_specifier_nonarray: ISAMPLER2DMSARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMSArray, (yylsp[0])); } break; - case 211: /* type_specifier_nonarray: ISAMPLERCUBEARRAYOES */ + case 216: /* type_specifier_nonarray: ISAMPLERCUBEARRAYOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -3834,7 +3923,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 212: /* type_specifier_nonarray: ISAMPLERCUBEARRAYEXT */ + case 217: /* type_specifier_nonarray: ISAMPLERCUBEARRAYEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -3845,7 +3934,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 213: /* type_specifier_nonarray: ISAMPLERBUFFER */ + case 218: /* type_specifier_nonarray: ISAMPLERBUFFER */ { constexpr std::array extensions{ {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; @@ -3858,43 +3947,43 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 214: /* type_specifier_nonarray: USAMPLER2D */ + case 219: /* type_specifier_nonarray: USAMPLER2D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2D, (yylsp[0])); } break; - case 215: /* type_specifier_nonarray: USAMPLER3D */ + case 220: /* type_specifier_nonarray: USAMPLER3D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler3D, (yylsp[0])); } break; - case 216: /* type_specifier_nonarray: USAMPLERCUBE */ + case 221: /* type_specifier_nonarray: USAMPLERCUBE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCube, (yylsp[0])); } break; - case 217: /* type_specifier_nonarray: USAMPLER2DARRAY */ + case 222: /* type_specifier_nonarray: USAMPLER2DARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DArray, (yylsp[0])); } break; - case 218: /* type_specifier_nonarray: USAMPLER2DMS */ + case 223: /* type_specifier_nonarray: USAMPLER2DMS */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMS, (yylsp[0])); } break; - case 219: /* type_specifier_nonarray: USAMPLER2DMSARRAY */ + case 224: /* type_specifier_nonarray: USAMPLER2DMSARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMSArray, (yylsp[0])); } break; - case 220: /* type_specifier_nonarray: USAMPLERCUBEARRAYOES */ + case 225: /* type_specifier_nonarray: USAMPLERCUBEARRAYOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -3905,7 +3994,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 221: /* type_specifier_nonarray: USAMPLERCUBEARRAYEXT */ + case 226: /* type_specifier_nonarray: USAMPLERCUBEARRAYEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -3916,7 +4005,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 222: /* type_specifier_nonarray: USAMPLERBUFFER */ + case 227: /* type_specifier_nonarray: USAMPLERBUFFER */ { constexpr std::array extensions{ {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; @@ -3929,25 +4018,25 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 223: /* type_specifier_nonarray: SAMPLER2DSHADOW */ + case 228: /* type_specifier_nonarray: SAMPLER2DSHADOW */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DShadow, (yylsp[0])); } break; - case 224: /* type_specifier_nonarray: SAMPLERCUBESHADOW */ + case 229: /* type_specifier_nonarray: SAMPLERCUBESHADOW */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeShadow, (yylsp[0])); } break; - case 225: /* type_specifier_nonarray: SAMPLER2DARRAYSHADOW */ + case 230: /* type_specifier_nonarray: SAMPLER2DARRAYSHADOW */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArrayShadow, (yylsp[0])); } break; - case 226: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOWOES */ + case 231: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOWOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -3958,7 +4047,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 227: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOWEXT */ + case 232: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOWEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -3969,7 +4058,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 228: /* type_specifier_nonarray: SAMPLERVIDEOWEBGL */ + case 233: /* type_specifier_nonarray: SAMPLERVIDEOWEBGL */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::WEBGL_video_texture)) { @@ -3979,7 +4068,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 229: /* type_specifier_nonarray: SAMPLER_EXTERNAL_OES */ + case 234: /* type_specifier_nonarray: SAMPLER_EXTERNAL_OES */ { constexpr std::array extensions{ {TExtension::NV_EGL_stream_consumer_external, @@ -3992,7 +4081,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 230: /* type_specifier_nonarray: SAMPLEREXTERNAL2DY2YEXT */ + case 235: /* type_specifier_nonarray: SAMPLEREXTERNAL2DY2YEXT */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target)) { @@ -4002,7 +4091,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 231: /* type_specifier_nonarray: SAMPLER2DRECT */ + case 236: /* type_specifier_nonarray: SAMPLER2DRECT */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::ARB_texture_rectangle)) { @@ -4012,79 +4101,79 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 232: /* type_specifier_nonarray: IMAGE2D */ + case 237: /* type_specifier_nonarray: IMAGE2D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0])); } break; - case 233: /* type_specifier_nonarray: IIMAGE2D */ + case 238: /* type_specifier_nonarray: IIMAGE2D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0])); } break; - case 234: /* type_specifier_nonarray: UIMAGE2D */ + case 239: /* type_specifier_nonarray: UIMAGE2D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0])); } break; - case 235: /* type_specifier_nonarray: IMAGE3D */ + case 240: /* type_specifier_nonarray: IMAGE3D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0])); } break; - case 236: /* type_specifier_nonarray: IIMAGE3D */ + case 241: /* type_specifier_nonarray: IIMAGE3D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0])); } break; - case 237: /* type_specifier_nonarray: UIMAGE3D */ + case 242: /* type_specifier_nonarray: UIMAGE3D */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0])); } break; - case 238: /* type_specifier_nonarray: IMAGE2DARRAY */ + case 243: /* type_specifier_nonarray: IMAGE2DARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0])); } break; - case 239: /* type_specifier_nonarray: IIMAGE2DARRAY */ + case 244: /* type_specifier_nonarray: IIMAGE2DARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0])); } break; - case 240: /* type_specifier_nonarray: UIMAGE2DARRAY */ + case 245: /* type_specifier_nonarray: UIMAGE2DARRAY */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0])); } break; - case 241: /* type_specifier_nonarray: IMAGECUBE */ + case 246: /* type_specifier_nonarray: IMAGECUBE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0])); } break; - case 242: /* type_specifier_nonarray: IIMAGECUBE */ + case 247: /* type_specifier_nonarray: IIMAGECUBE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0])); } break; - case 243: /* type_specifier_nonarray: UIMAGECUBE */ + case 248: /* type_specifier_nonarray: UIMAGECUBE */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0])); } break; - case 244: /* type_specifier_nonarray: IMAGECUBEARRAYOES */ + case 249: /* type_specifier_nonarray: IMAGECUBEARRAYOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -4095,7 +4184,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 245: /* type_specifier_nonarray: IMAGECUBEARRAYEXT */ + case 250: /* type_specifier_nonarray: IMAGECUBEARRAYEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -4106,7 +4195,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 246: /* type_specifier_nonarray: IIMAGECUBEARRAYOES */ + case 251: /* type_specifier_nonarray: IIMAGECUBEARRAYOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -4117,7 +4206,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 247: /* type_specifier_nonarray: IIMAGECUBEARRAYEXT */ + case 252: /* type_specifier_nonarray: IIMAGECUBEARRAYEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -4128,7 +4217,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 248: /* type_specifier_nonarray: UIMAGECUBEARRAYOES */ + case 253: /* type_specifier_nonarray: UIMAGECUBEARRAYOES */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) @@ -4139,7 +4228,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 249: /* type_specifier_nonarray: UIMAGECUBEARRAYEXT */ + case 254: /* type_specifier_nonarray: UIMAGECUBEARRAYEXT */ { if (context->getShaderVersion() < 320 && !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) @@ -4150,7 +4239,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 250: /* type_specifier_nonarray: IMAGEBUFFER */ + case 255: /* type_specifier_nonarray: IMAGEBUFFER */ { constexpr std::array extensions{ {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; @@ -4163,7 +4252,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 251: /* type_specifier_nonarray: IIMAGEBUFFER */ + case 256: /* type_specifier_nonarray: IIMAGEBUFFER */ { constexpr std::array extensions{ {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; @@ -4176,7 +4265,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 252: /* type_specifier_nonarray: UIMAGEBUFFER */ + case 257: /* type_specifier_nonarray: UIMAGEBUFFER */ { constexpr std::array extensions{ {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; @@ -4189,13 +4278,13 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 253: /* type_specifier_nonarray: ATOMICUINT */ + case 258: /* type_specifier_nonarray: ATOMICUINT */ { (yyval.interm.typeSpecifierNonArray).initialize(EbtAtomicCounter, (yylsp[0])); } break; - case 254: /* type_specifier_nonarray: PIXELLOCALANGLE */ + case 259: /* type_specifier_nonarray: PIXELLOCALANGLE */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::ANGLE_shader_pixel_local_storage)) @@ -4206,7 +4295,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 255: /* type_specifier_nonarray: IPIXELLOCALANGLE */ + case 260: /* type_specifier_nonarray: IPIXELLOCALANGLE */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::ANGLE_shader_pixel_local_storage)) @@ -4217,7 +4306,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 256: /* type_specifier_nonarray: UPIXELLOCALANGLE */ + case 261: /* type_specifier_nonarray: UPIXELLOCALANGLE */ { if (!context->checkCanUseExtension((yylsp[0]), TExtension::ANGLE_shader_pixel_local_storage)) @@ -4228,13 +4317,13 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 257: /* type_specifier_nonarray: struct_specifier */ + case 262: /* type_specifier_nonarray: struct_specifier */ { (yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray); } break; - case 258: /* type_specifier_nonarray: TYPE_NAME */ + case 263: /* type_specifier_nonarray: TYPE_NAME */ { // This is for user defined type names. The lexical phase looked up the type. const TStructure *structure = static_cast((yyvsp[0].lex).symbol); @@ -4245,13 +4334,13 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 259: /* $@1: %empty */ + case 264: /* $@6: %empty */ { context->enterStructDeclaration((yylsp[-1]), ImmutableString((yyvsp[-1].lex).string)); } break; - case 260: /* struct_specifier: STRUCT identifier LEFT_BRACE $@1 struct_declaration_list + case 265: /* struct_specifier: STRUCT identifier LEFT_BRACE $@6 struct_declaration_list RIGHT_BRACE */ { (yyval.interm.typeSpecifierNonArray) = context->addStructure( @@ -4260,41 +4349,41 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 261: /* $@2: %empty */ + case 266: /* $@7: %empty */ { context->enterStructDeclaration((yylsp[0]), kEmptyImmutableString); } break; - case 262: /* struct_specifier: STRUCT LEFT_BRACE $@2 struct_declaration_list RIGHT_BRACE */ + case 267: /* struct_specifier: STRUCT LEFT_BRACE $@7 struct_declaration_list RIGHT_BRACE */ { (yyval.interm.typeSpecifierNonArray) = context->addStructure( (yylsp[-4]), (yyloc), kEmptyImmutableString, (yyvsp[-1].interm.fieldList)); } break; - case 263: /* struct_declaration_list: struct_declaration */ + case 268: /* struct_declaration_list: struct_declaration */ { (yyval.interm.fieldList) = context->addStructFieldList((yyvsp[0].interm.fieldList), (yylsp[0])); } break; - case 264: /* struct_declaration_list: struct_declaration_list struct_declaration */ + case 269: /* struct_declaration_list: struct_declaration_list struct_declaration */ { (yyval.interm.fieldList) = context->combineStructFieldLists( (yyvsp[-1].interm.fieldList), (yyvsp[0].interm.fieldList), (yylsp[0])); } break; - case 265: /* struct_declaration: type_specifier struct_declarator_list SEMICOLON */ + case 270: /* struct_declaration: type_specifier struct_declarator_list SEMICOLON */ { (yyval.interm.fieldList) = context->addStructDeclaratorList( (yyvsp[-2].interm.type), (yyvsp[-1].interm.declaratorList)); } break; - case 266: /* struct_declaration: type_qualifier type_specifier struct_declarator_list + case 271: /* struct_declaration: type_qualifier type_specifier struct_declarator_list SEMICOLON */ { // ES3 Only, but errors should be handled elsewhere @@ -4304,255 +4393,272 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 267: /* struct_declarator_list: struct_declarator */ + case 272: /* struct_declarator_list: struct_declarator */ { (yyval.interm.declaratorList) = new TDeclaratorList(); (yyval.interm.declaratorList)->push_back((yyvsp[0].interm.declarator)); } break; - case 268: /* struct_declarator_list: struct_declarator_list COMMA struct_declarator */ + case 273: /* struct_declarator_list: struct_declarator_list COMMA struct_declarator */ { (yyval.interm.declaratorList)->push_back((yyvsp[0].interm.declarator)); } break; - case 269: /* struct_declarator: identifier */ + case 274: /* struct_declarator: identifier */ { (yyval.interm.declarator) = context->parseStructDeclarator(ImmutableString((yyvsp[0].lex).string), (yylsp[0])); } break; - case 270: /* struct_declarator: identifier array_specifier */ + case 275: /* struct_declarator: identifier array_specifier */ { (yyval.interm.declarator) = context->parseStructArrayDeclarator( ImmutableString((yyvsp[-1].lex).string), (yylsp[-1]), (yyvsp[0].interm.arraySizes)); } break; - case 271: /* initializer: assignment_expression */ + case 276: /* initializer: assignment_expression */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 272: /* declaration_statement: declaration */ + case 277: /* declaration_statement: declaration */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 273: /* statement: compound_statement_with_scope */ + case 278: /* statement: compound_statement_with_scope */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); } break; - case 274: /* statement: simple_statement */ + case 279: /* statement: simple_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 275: /* simple_statement: declaration_statement */ + case 280: /* simple_statement: declaration_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 276: /* simple_statement: expression_statement */ + case 281: /* simple_statement: expression_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 277: /* simple_statement: selection_statement */ + case 282: /* simple_statement: selection_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 278: /* simple_statement: switch_statement */ + case 283: /* simple_statement: switch_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermSwitch); } break; - case 279: /* simple_statement: case_label */ + case 284: /* simple_statement: case_label */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermCase); } break; - case 280: /* simple_statement: iteration_statement */ + case 285: /* simple_statement: iteration_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 281: /* simple_statement: jump_statement */ + case 286: /* simple_statement: jump_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 282: /* compound_statement_with_scope: LEFT_BRACE RIGHT_BRACE */ + case 287: /* compound_statement_with_scope: LEFT_BRACE RIGHT_BRACE */ { (yyval.interm.intermBlock) = new TIntermBlock(); (yyval.interm.intermBlock)->setLine((yyloc)); } break; - case 283: /* $@3: %empty */ + case 288: /* $@8: %empty */ { - context->symbolTable.push(); + context->beginNestedScope(); } break; - case 284: /* $@4: %empty */ + case 289: /* $@9: %empty */ { - context->symbolTable.pop(); + context->endNestedScope(); } break; - case 285: /* compound_statement_with_scope: LEFT_BRACE $@3 statement_list $@4 RIGHT_BRACE */ + case 290: /* compound_statement_with_scope: LEFT_BRACE $@8 statement_list $@9 RIGHT_BRACE */ { (yyvsp[-2].interm.intermBlock)->setLine((yyloc)); (yyval.interm.intermBlock) = (yyvsp[-2].interm.intermBlock); } break; - case 286: /* statement_no_new_scope: compound_statement_no_new_scope */ + case 291: /* statement_no_new_scope: compound_statement_no_new_scope */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); } break; - case 287: /* statement_no_new_scope: simple_statement */ + case 292: /* statement_no_new_scope: simple_statement */ { + context->endStatementWithValue((yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 288: /* $@5: %empty */ + case 293: /* $@10: %empty */ { - context->symbolTable.push(); + context->beginNestedScope(); } break; - case 289: /* statement_with_scope: $@5 compound_statement_no_new_scope */ + case 294: /* statement_with_scope: $@10 compound_statement_no_new_scope */ { - context->symbolTable.pop(); + context->endNestedScope(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); } break; - case 290: /* $@6: %empty */ + case 295: /* $@11: %empty */ { - context->symbolTable.push(); + context->beginNestedScope(); } break; - case 291: /* statement_with_scope: $@6 simple_statement */ + case 296: /* statement_with_scope: $@11 simple_statement */ { - context->symbolTable.pop(); + context->endStatementWithValue((yyvsp[0].interm.intermNode)); + context->endNestedScope(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 292: /* compound_statement_no_new_scope: LEFT_BRACE RIGHT_BRACE */ + case 297: /* compound_statement_no_new_scope: LEFT_BRACE RIGHT_BRACE */ { (yyval.interm.intermBlock) = new TIntermBlock(); (yyval.interm.intermBlock)->setLine((yyloc)); } break; - case 293: /* compound_statement_no_new_scope: LEFT_BRACE statement_list RIGHT_BRACE */ + case 298: /* compound_statement_no_new_scope: LEFT_BRACE statement_list RIGHT_BRACE */ { (yyvsp[-1].interm.intermBlock)->setLine((yyloc)); (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); } break; - case 294: /* statement_list: statement */ + case 299: /* statement_list: statement */ { (yyval.interm.intermBlock) = new TIntermBlock(); context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode)); } break; - case 295: /* statement_list: statement_list statement */ + case 300: /* statement_list: statement_list statement */ { (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode)); } break; - case 296: /* expression_statement: SEMICOLON */ + case 301: /* expression_statement: SEMICOLON */ { (yyval.interm.intermNode) = context->addEmptyStatement((yyloc)); } break; - case 297: /* expression_statement: expression SEMICOLON */ + case 302: /* expression_statement: expression SEMICOLON */ { context->checkIsValidExpressionStatement((yyloc), (yyvsp[-1].interm.intermTypedNode)); (yyval.interm.intermNode) = (yyvsp[-1].interm.intermTypedNode); } break; - case 298: /* selection_statement: IF LEFT_PAREN expression RIGHT_PAREN + case 303: /* $@12: %empty */ + { + context->onIfTrueBlockBegin((yyvsp[-1].interm.intermTypedNode), (yylsp[-3])); + } + break; + + case 304: /* selection_statement: IF LEFT_PAREN expression RIGHT_PAREN $@12 selection_rest_statement */ { - (yyval.interm.intermNode) = context->addIfElse((yyvsp[-2].interm.intermTypedNode), - (yyvsp[0].interm.nodePair), (yylsp[-4])); + (yyval.interm.intermNode) = context->addIfElse((yyvsp[-3].interm.intermTypedNode), + (yyvsp[0].interm.nodePair), (yylsp[-5])); + } + break; + + case 305: /* $@13: %empty */ + { + context->onIfTrueBlockEnd(); + context->onIfFalseBlockBegin(); } break; - case 299: /* selection_rest_statement: statement_with_scope ELSE statement_with_scope */ + case 306: /* selection_rest_statement: statement_with_scope ELSE $@13 statement_with_scope + */ { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); + context->onIfFalseBlockEnd(); + (yyval.interm.nodePair).node1 = (yyvsp[-3].interm.intermNode); (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); } break; - case 300: /* selection_rest_statement: statement_with_scope */ + case 307: /* selection_rest_statement: statement_with_scope */ { + context->onIfTrueBlockEnd(); (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); (yyval.interm.nodePair).node2 = nullptr; } break; - case 301: /* $@7: %empty */ + case 308: /* $@14: %empty */ { - context->incrSwitchNestingLevel((yylsp[-3])); + context->beginSwitch((yylsp[-3]), (yyvsp[-1].interm.intermTypedNode)); } break; - case 302: /* switch_statement: SWITCH LEFT_PAREN expression RIGHT_PAREN $@7 - compound_statement_with_scope */ + case 309: /* switch_statement: SWITCH LEFT_PAREN expression RIGHT_PAREN $@14 + compound_statement_no_new_scope */ { (yyval.interm.intermSwitch) = context->addSwitch( (yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermBlock), (yylsp[-5])); - context->decrSwitchNestingLevel(); } break; - case 303: /* case_label: CASE constant_expression COLON */ + case 310: /* case_label: CASE constant_expression COLON */ { (yyval.interm.intermCase) = context->addCase((yyvsp[-1].interm.intermTypedNode), (yylsp[-2])); } break; - case 304: /* case_label: DEFAULT COLON */ + case 311: /* case_label: DEFAULT COLON */ { (yyval.interm.intermCase) = context->addDefault((yylsp[-1])); } break; - case 305: /* condition: expression */ + case 312: /* condition: expression */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermTypedNode); context->checkIsScalarBool((yyvsp[0].interm.intermTypedNode)->getLine(), @@ -4560,7 +4666,7 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 306: /* condition: fully_specified_type identifier EQUAL initializer */ + case 313: /* condition: fully_specified_type identifier EQUAL initializer */ { (yyval.interm.intermNode) = context->addConditionInitializer( (yyvsp[-3].interm.type), ImmutableString((yyvsp[-2].lex).string), @@ -4568,129 +4674,156 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 307: /* $@8: %empty */ + case 314: /* $@15: %empty */ { context->symbolTable.push(); - context->incrLoopNestingLevel((yylsp[-1])); + context->beginLoop(ELoopWhile, (yylsp[-1])); + context->onLoopConditionBegin(nullptr, (yylsp[-1])); + } + break; + + case 315: /* $@16: %empty */ + { + context->onLoopConditionEnd((yyvsp[0].interm.intermNode), (yylsp[0])); } break; - case 308: /* iteration_statement: WHILE LEFT_PAREN $@8 condition RIGHT_PAREN + case 316: /* iteration_statement: WHILE LEFT_PAREN $@15 condition $@16 RIGHT_PAREN statement_no_new_scope */ { context->symbolTable.pop(); (yyval.interm.intermNode) = - context->addLoop(ELoopWhile, 0, (yyvsp[-2].interm.intermNode), 0, - (yyvsp[0].interm.intermNode), (yylsp[-5])); - context->decrLoopNestingLevel(); + context->addLoop(ELoopWhile, 0, (yyvsp[-3].interm.intermNode), 0, + (yyvsp[0].interm.intermNode), (yylsp[-6])); + } + break; + + case 317: /* $@17: %empty */ + { + context->beginLoop(ELoopDoWhile, (yylsp[0])); + context->onDoLoopBegin(); } break; - case 309: /* $@9: %empty */ + case 318: /* $@18: %empty */ { - context->incrLoopNestingLevel((yylsp[0])); + context->onDoLoopConditionBegin(); } break; - case 310: /* iteration_statement: DO $@9 statement_with_scope WHILE LEFT_PAREN expression - RIGHT_PAREN SEMICOLON */ + case 319: /* iteration_statement: DO $@17 statement_with_scope WHILE LEFT_PAREN $@18 + expression RIGHT_PAREN SEMICOLON */ { (yyval.interm.intermNode) = context->addLoop(ELoopDoWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, - (yyvsp[-5].interm.intermNode), (yylsp[-4])); - context->decrLoopNestingLevel(); + (yyvsp[-6].interm.intermNode), (yylsp[-5])); } break; - case 311: /* $@10: %empty */ + case 320: /* $@19: %empty */ { context->symbolTable.push(); - context->incrLoopNestingLevel((yylsp[-1])); + context->beginLoop(ELoopFor, (yylsp[-1])); + } + break; + + case 321: /* $@20: %empty */ + { + context->onLoopConditionBegin((yyvsp[0].interm.intermNode), (yylsp[0])); } break; - case 312: /* iteration_statement: FOR LEFT_PAREN $@10 for_init_statement for_rest_statement - RIGHT_PAREN statement_no_new_scope */ + case 322: /* iteration_statement: FOR LEFT_PAREN $@19 for_init_statement $@20 + for_rest_statement RIGHT_PAREN statement_no_new_scope */ { context->symbolTable.pop(); (yyval.interm.intermNode) = context->addLoop( - ELoopFor, (yyvsp[-3].interm.intermNode), (yyvsp[-2].interm.nodePair).node1, + ELoopFor, (yyvsp[-4].interm.intermNode), (yyvsp[-2].interm.nodePair).node1, reinterpret_cast((yyvsp[-2].interm.nodePair).node2), - (yyvsp[0].interm.intermNode), (yylsp[-6])); - context->decrLoopNestingLevel(); + (yyvsp[0].interm.intermNode), (yylsp[-7])); } break; - case 313: /* for_init_statement: expression_statement */ + case 323: /* for_init_statement: expression_statement */ { + context->endStatementWithValue((yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 314: /* for_init_statement: declaration_statement */ + case 324: /* for_init_statement: declaration_statement */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 315: /* conditionopt: condition */ + case 325: /* conditionopt: condition */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 316: /* conditionopt: %empty */ + case 326: /* conditionopt: %empty */ { (yyval.interm.intermNode) = nullptr; } break; - case 317: /* for_rest_statement: conditionopt SEMICOLON */ + case 327: /* for_rest_statement: conditionopt SEMICOLON */ { + context->onLoopConditionEnd((yyvsp[-1].interm.intermNode), (yylsp[-1])); + context->onLoopContinueEnd(nullptr, (yylsp[-1])); (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermNode); (yyval.interm.nodePair).node2 = 0; } break; - case 318: /* for_rest_statement: conditionopt SEMICOLON expression */ + case 328: /* $@21: %empty */ + { + context->onLoopConditionEnd((yyvsp[-1].interm.intermNode), (yylsp[-1])); + } + break; + + case 329: /* for_rest_statement: conditionopt SEMICOLON $@21 expression */ { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); + context->onLoopContinueEnd((yyvsp[0].interm.intermTypedNode), (yylsp[0])); + (yyval.interm.nodePair).node1 = (yyvsp[-3].interm.intermNode); (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); } break; - case 319: /* jump_statement: CONTINUE SEMICOLON */ + case 330: /* jump_statement: CONTINUE SEMICOLON */ { (yyval.interm.intermNode) = context->addBranch(EOpContinue, (yylsp[-1])); } break; - case 320: /* jump_statement: BREAK SEMICOLON */ + case 331: /* jump_statement: BREAK SEMICOLON */ { (yyval.interm.intermNode) = context->addBranch(EOpBreak, (yylsp[-1])); } break; - case 321: /* jump_statement: RETURN SEMICOLON */ + case 332: /* jump_statement: RETURN SEMICOLON */ { (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yylsp[-1])); } break; - case 322: /* jump_statement: RETURN expression SEMICOLON */ + case 333: /* jump_statement: RETURN expression SEMICOLON */ { (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yyvsp[-1].interm.intermTypedNode), (yylsp[-2])); } break; - case 323: /* jump_statement: DISCARD SEMICOLON */ + case 334: /* jump_statement: DISCARD SEMICOLON */ { (yyval.interm.intermNode) = context->addBranch(EOpKill, (yylsp[-1])); } break; - case 324: /* translation_unit: external_declaration */ + case 335: /* translation_unit: external_declaration */ { (yyval.interm.intermBlock) = new TIntermBlock(); (yyval.interm.intermBlock)->setLine((yyloc)); @@ -4699,32 +4832,32 @@ int yyparse(TParseContext *context, void *scanner) } break; - case 325: /* translation_unit: translation_unit external_declaration */ + case 336: /* translation_unit: translation_unit external_declaration */ { (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); } break; - case 326: /* external_declaration: function_definition */ + case 337: /* external_declaration: function_definition */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 327: /* external_declaration: declaration */ + case 338: /* external_declaration: declaration */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 328: /* $@11: %empty */ + case 339: /* $@22: %empty */ { context->parseFunctionDefinitionHeader((yylsp[0]), (yyvsp[0].interm).function, &((yyvsp[0].interm).intermFunctionPrototype)); } break; - case 329: /* function_definition: function_prototype $@11 compound_statement_no_new_scope */ + case 340: /* function_definition: function_prototype $@22 compound_statement_no_new_scope */ { (yyval.interm.intermNode) = context->addFunctionDefinition((yyvsp[-2].interm).intermFunctionPrototype, @@ -4790,7 +4923,9 @@ int yyparse(TParseContext *context, void *scanner) { /* Return failure if at end of input. */ if (yychar == YYEOF) + { YYABORT; + } } else { @@ -4810,7 +4945,9 @@ int yyparse(TParseContext *context, void *scanner) /* Pacify compilers when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (0) + { YYERROR; + } ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered @@ -4838,13 +4975,17 @@ int yyparse(TParseContext *context, void *scanner) { yyn = yytable[yyn]; if (0 < yyn) + { break; + } } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) + { YYABORT; + } yyerror_range[1] = *yylsp; yydestruct("Error: popping", YY_ACCESSING_SYMBOL(yystate), yyvsp, yylsp, context, scanner); @@ -4912,7 +5053,9 @@ int yyparse(TParseContext *context, void *scanner) } #ifndef yyoverflow if (yyss != yyssa) + { YYSTACK_FREE(yyss); + } #endif return yyresult; diff --git a/src/compiler/translator/hlsl/ASTMetadataHLSL.cpp b/src/compiler/translator/hlsl/ASTMetadataHLSL.cpp index 73a6fb07dc8..c0e75599fbf 100644 --- a/src/compiler/translator/hlsl/ASTMetadataHLSL.cpp +++ b/src/compiler/translator/hlsl/ASTMetadataHLSL.cpp @@ -47,8 +47,6 @@ class PullGradient : public TIntermTraverser mGradientBuiltinFunctions.insert(ImmutableString("textureProj")); mGradientBuiltinFunctions.insert(ImmutableString("textureOffset")); mGradientBuiltinFunctions.insert(ImmutableString("textureProjOffset")); - - // ESSL 310 doesn't add builtin gradient functions } void traverse(TIntermFunctionDefinition *node) @@ -114,8 +112,12 @@ class PullGradient : public TIntermTraverser } else if (BuiltInGroup::IsBuiltIn(node->getOp()) && !BuiltInGroup::IsMath(node->getOp())) { + // Texture sample functions that operate on shadow samplers bottom out in the HLSL + // SampleCmp function which does not have an LOD parameter. These functions need + // gradients. if (mGradientBuiltinFunctions.find(node->getFunction()->name()) != - mGradientBuiltinFunctions.end()) + mGradientBuiltinFunctions.end() || + isShadowSamplerTextureCall(node)) { onGradient(); } @@ -126,6 +128,23 @@ class PullGradient : public TIntermTraverser } private: + bool isShadowSamplerTextureCall(TIntermAggregate *node) const + { + if (!node->getFunction()) + { + return false; + } + + if (node->getFunction()->name() != "textureLod") + { + return false; + } + + TIntermSequence *arguments = node->getSequence(); + TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); + return IsShadowSampler(samplerType); + } + MetadataList *mMetadataList; ASTMetadataHLSL *mMetadata; size_t mIndex; diff --git a/src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.cpp b/src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.cpp deleted file mode 100644 index 5c57cd229d5..00000000000 --- a/src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright 2018 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. -// -// AtomicCounterFunctionHLSL: Class for writing implementation of atomic counter functions into HLSL -// output. -// - -#include "compiler/translator/hlsl/AtomicCounterFunctionHLSL.h" - -#include "compiler/translator/Common.h" -#include "compiler/translator/ImmutableStringBuilder.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -namespace -{ -constexpr ImmutableString kAtomicCounter("atomicCounter"); -constexpr ImmutableString kAtomicCounterIncrement("atomicCounterIncrement"); -constexpr ImmutableString kAtomicCounterDecrement("atomicCounterDecrement"); -constexpr ImmutableString kAtomicCounterBaseName("_acbase_"); -} // namespace - -AtomicCounterFunctionHLSL::AtomicCounterFunctionHLSL(bool forceResolution) - : mForceResolution(forceResolution) -{} - -ImmutableString AtomicCounterFunctionHLSL::useAtomicCounterFunction(const ImmutableString &name) -{ - // The largest string that will be create created is "_acbase_increment" or "_acbase_decrement" - ImmutableStringBuilder hlslFunctionNameSB(kAtomicCounterBaseName.length() + - strlen("increment")); - hlslFunctionNameSB << kAtomicCounterBaseName; - - AtomicCounterFunction atomicMethod; - if (kAtomicCounter == name) - { - atomicMethod = AtomicCounterFunction::LOAD; - hlslFunctionNameSB << "load"; - } - else if (kAtomicCounterIncrement == name) - { - atomicMethod = AtomicCounterFunction::INCREMENT; - hlslFunctionNameSB << "increment"; - } - else if (kAtomicCounterDecrement == name) - { - atomicMethod = AtomicCounterFunction::DECREMENT; - hlslFunctionNameSB << "decrement"; - } - else - { - atomicMethod = AtomicCounterFunction::INVALID; - UNREACHABLE(); - } - - ImmutableString hlslFunctionName(hlslFunctionNameSB); - mAtomicCounterFunctions[hlslFunctionName] = atomicMethod; - - return hlslFunctionName; -} - -void AtomicCounterFunctionHLSL::atomicCounterFunctionHeader(TInfoSinkBase &out) -{ - for (auto &atomicFunction : mAtomicCounterFunctions) - { - out << "uint " << atomicFunction.first - << "(in RWByteAddressBuffer counter, int address)\n" - "{\n" - " uint ret;\n"; - - switch (atomicFunction.second) - { - case AtomicCounterFunction::INCREMENT: - out << " counter.InterlockedAdd(address, 1u, ret);\n"; - break; - case AtomicCounterFunction::DECREMENT: - out << " counter.InterlockedAdd(address, 0u - 1u, ret);\n" - " ret -= 1u;\n"; // atomicCounterDecrement is a post-decrement op - break; - case AtomicCounterFunction::LOAD: - out << " ret = counter.Load(address);\n"; - break; - default: - UNREACHABLE(); - break; - } - - if (mForceResolution && atomicFunction.second != AtomicCounterFunction::LOAD) - { - out << " if (ret == 0) {\n" - " ret = 0 - ret;\n" - " }\n"; - } - - out << " return ret;\n" - "}\n\n"; - } -} - -ImmutableString getAtomicCounterNameForBinding(int binding) -{ - std::stringstream counterName = sh::InitializeStream(); - counterName << kAtomicCounterBaseName << binding; - return ImmutableString(counterName.str()); -} - -} // namespace sh diff --git a/src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.h b/src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.h deleted file mode 100644 index 41438145889..00000000000 --- a/src/compiler/translator/hlsl/AtomicCounterFunctionHLSL.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright 2018 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. -// -// AtomicCounterFunctionHLSL: Class for writing implementation of atomic counter functions into HLSL -// output. -// - -#ifndef COMPILER_TRANSLATOR_HLSL_ATOMICCOUNTERFUNCTIONHLSL_H_ -#define COMPILER_TRANSLATOR_HLSL_ATOMICCOUNTERFUNCTIONHLSL_H_ - -#include - -#include "compiler/translator/Common.h" -#include "compiler/translator/ImmutableString.h" - -namespace sh -{ - -class TInfoSinkBase; -struct TLayoutQualifier; - -class AtomicCounterFunctionHLSL final : angle::NonCopyable -{ - public: - AtomicCounterFunctionHLSL(bool forceResolution); - - ImmutableString useAtomicCounterFunction(const ImmutableString &name); - - void atomicCounterFunctionHeader(TInfoSinkBase &out); - - private: - enum class AtomicCounterFunction - { - LOAD, - INCREMENT, - DECREMENT, - INVALID - }; - - std::map mAtomicCounterFunctions; - bool mForceResolution; -}; - -ImmutableString getAtomicCounterNameForBinding(int binding); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_HLSL_ATOMICCOUNTERFUNCTIONHLSL_H_ diff --git a/src/compiler/translator/hlsl/ImageFunctionHLSL.cpp b/src/compiler/translator/hlsl/ImageFunctionHLSL.cpp index f473dd85e50..f62813241e0 100644 --- a/src/compiler/translator/hlsl/ImageFunctionHLSL.cpp +++ b/src/compiler/translator/hlsl/ImageFunctionHLSL.cpp @@ -6,6 +6,10 @@ // ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "compiler/translator/hlsl/ImageFunctionHLSL.h" #include "compiler/translator/ImmutableStringBuilder.h" #include "compiler/translator/hlsl/UtilsHLSL.h" @@ -71,11 +75,6 @@ void ImageFunctionHLSL::OutputImageFunctionArgumentList( case EbtUImage2DArray: out << ", int3 p"; break; - case EbtUImageBuffer: - case EbtIImageBuffer: - case EbtImageBuffer: - out << ", int p"; - break; default: UNREACHABLE(); @@ -89,21 +88,18 @@ void ImageFunctionHLSL::OutputImageFunctionArgumentList( case EbtImage3D: case EbtImageCube: case EbtImage2DArray: - case EbtImageBuffer: out << ", float4 data"; break; case EbtIImage2D: case EbtIImage3D: case EbtIImageCube: case EbtIImage2DArray: - case EbtIImageBuffer: out << ", int4 data"; break; case EbtUImage2D: case EbtUImage3D: case EbtUImageCube: case EbtUImage2DArray: - case EbtUImageBuffer: out << ", uint4 data"; break; default: @@ -131,11 +127,6 @@ void ImageFunctionHLSL::OutputImageSizeFunctionBody( out << " uint width; uint height;\n" << " " << imageReference << ".GetDimensions(width, height);\n"; } - else if (IsImageBuffer(imageFunction.image)) - { - out << " uint width;\n" - << " " << imageReference << ".GetDimensions(width);\n"; - } else UNREACHABLE(); @@ -168,10 +159,6 @@ void ImageFunctionHLSL::OutputImageLoadFunctionBody( { out << " return " << imageReference << "[uint2(p.x, p.y)];\n"; } - else if (IsImageBuffer(imageFunction.image)) - { - out << " return " << imageReference << "[uint(p.x)];\n"; - } else UNREACHABLE(); } @@ -183,8 +170,7 @@ void ImageFunctionHLSL::OutputImageStoreFunctionBody( const ImmutableString &imageReference) { if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image) || - IsImageBuffer(imageFunction.image)) + IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image)) { out << " " << imageReference << "[p] = data;\n"; } @@ -278,10 +264,6 @@ const char *ImageFunctionHLSL::ImageFunction::getReturnType() const case EbtIImage2DArray: case EbtUImage2DArray: return "int3"; - case EbtImageBuffer: - case EbtIImageBuffer: - case EbtUImageBuffer: - return "int"; default: UNREACHABLE(); } @@ -290,19 +272,16 @@ const char *ImageFunctionHLSL::ImageFunction::getReturnType() const { switch (image) { - case EbtImageBuffer: case EbtImage2D: case EbtImage3D: case EbtImageCube: case EbtImage2DArray: return "float4"; - case EbtIImageBuffer: case EbtIImage2D: case EbtIImage3D: case EbtIImageCube: case EbtIImage2DArray: return "int4"; - case EbtUImageBuffer: case EbtUImage2D: case EbtUImage3D: case EbtUImageCube: diff --git a/src/compiler/translator/hlsl/OutputHLSL.cpp b/src/compiler/translator/hlsl/OutputHLSL.cpp index 53856566ad2..973ceae6c2e 100644 --- a/src/compiler/translator/hlsl/OutputHLSL.cpp +++ b/src/compiler/translator/hlsl/OutputHLSL.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/hlsl/OutputHLSL.h" #include @@ -17,7 +21,6 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/StaticType.h" #include "compiler/translator/blocklayout.h" -#include "compiler/translator/hlsl/AtomicCounterFunctionHLSL.h" #include "compiler/translator/hlsl/BuiltInFunctionEmulatorHLSL.h" #include "compiler/translator/hlsl/ImageFunctionHLSL.h" #include "compiler/translator/hlsl/ResourcesHLSL.h" @@ -60,7 +63,7 @@ bool IsDeclarationWrittenOut(TIntermDeclaration *node) ASSERT(sequence->size() == 1); ASSERT(variable); return (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal || - variable->getQualifier() == EvqConst || variable->getQualifier() == EvqShared); + variable->getQualifier() == EvqConst); } bool IsInStd140UniformBlock(TIntermTyped *node) @@ -114,49 +117,6 @@ const TInterfaceBlock *GetInterfaceBlockOfUniformBlockNearestIndexOperator(TInte return nullptr; } -const char *GetHLSLAtomicFunctionStringAndLeftParenthesis(TOperator op) -{ - switch (op) - { - case EOpAtomicAdd: - return "InterlockedAdd("; - case EOpAtomicMin: - return "InterlockedMin("; - case EOpAtomicMax: - return "InterlockedMax("; - case EOpAtomicAnd: - return "InterlockedAnd("; - case EOpAtomicOr: - return "InterlockedOr("; - case EOpAtomicXor: - return "InterlockedXor("; - case EOpAtomicExchange: - return "InterlockedExchange("; - case EOpAtomicCompSwap: - return "InterlockedCompareExchange("; - default: - UNREACHABLE(); - return ""; - } -} - -bool IsAtomicFunctionForSharedVariableDirectAssign(const TIntermBinary &node) -{ - TIntermAggregate *aggregateNode = node.getRight()->getAsAggregate(); - if (aggregateNode == nullptr) - { - return false; - } - - if (node.getOp() == EOpAssign && BuiltInGroup::IsAtomicMemory(aggregateNode->getOp())) - { - return !IsInShaderStorageBlock((*aggregateNode->getSequence())[0]->getAsTyped()) && - !IsInShaderStorageBlock(node.getLeft()); - } - - return false; -} - const char *kZeros = "_ANGLE_ZEROS_"; constexpr int kZeroCount = 256; std::string DefineZeroArray() @@ -315,11 +275,9 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, int maxDualSourceDrawBuffers, const std::vector &uniforms, const ShCompileOptions &compileOptions, - sh::WorkGroupSize workGroupSize, TSymbolTable *symbolTable, PerformanceDiagnostics *perfDiagnostics, const std::map &uniformBlockOptimizedMap, - const std::vector &shaderStorageBlocks, uint8_t clipDistanceSize, uint8_t cullDistanceSize, bool isEarlyFragmentTestsSpecified) @@ -337,7 +295,6 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, mNumRenderTargets(numRenderTargets), mMaxDualSourceDrawBuffers(maxDualSourceDrawBuffers), mCurrentFunctionMetadata(nullptr), - mWorkGroupSize(workGroupSize), mPerfDiagnostics(perfDiagnostics), mClipDistanceSize(clipDistanceSize), mCullDistanceSize(cullDistanceSize), @@ -350,7 +307,6 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, mUsesFragCoord = false; mUsesPointCoord = false; mUsesFrontFacing = false; - mUsesHelperInvocation = false; mUsesPointSize = false; mUsesInstanceID = false; mHasMultiviewExtensionEnabled = @@ -364,11 +320,6 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, mUsesSampleMaskIn = false; mUsesSampleMask = false; mUsesNumSamples = false; - mUsesNumWorkGroups = false; - mUsesWorkGroupID = false; - mUsesLocalInvocationID = false; - mUsesGlobalInvocationID = false; - mUsesLocalInvocationIndex = false; mUsesXor = false; mUsesDiscardRewriting = false; mUsesNestedBreak = false; @@ -389,8 +340,6 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, mStructureHLSL = new StructureHLSL; mTextureFunctionHLSL = new TextureFunctionHLSL; mImageFunctionHLSL = new ImageFunctionHLSL; - mAtomicCounterFunctionHLSL = - new AtomicCounterFunctionHLSL(compileOptions.forceAtomicValueResolution); unsigned int firstUniformRegister = compileOptions.skipD3DConstantRegisterZero ? 1u : 0u; mResourcesHLSL = new ResourcesHLSL(mStructureHLSL, outputType, uniforms, firstUniformRegister); @@ -413,18 +362,14 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, // Reserve registers for the default uniform block and driver constants mResourcesHLSL->reserveUniformBlockRegisters(2); - - mSSBOOutputHLSL = new ShaderStorageBlockOutputHLSL(this, mResourcesHLSL, shaderStorageBlocks); } OutputHLSL::~OutputHLSL() { - SafeDelete(mSSBOOutputHLSL); SafeDelete(mStructureHLSL); SafeDelete(mResourcesHLSL); SafeDelete(mTextureFunctionHLSL); SafeDelete(mImageFunctionHLSL); - SafeDelete(mAtomicCounterFunctionHLSL); for (auto &eqFunction : mStructEqualityFunctions) { SafeDelete(eqFunction); @@ -448,8 +393,7 @@ void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) builtInFunctionEmulator.markBuiltInFunctionsForEmulation(treeRoot); // Now that we are done changing the AST, do the analyses need for HLSL generation - CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr); - ASSERT(success == CallDAG::INITDAG_SUCCESS); + mCallDag.init(treeRoot); mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag); const std::vector std140Structs = FlagStd140Structs(treeRoot); @@ -476,11 +420,6 @@ void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) builtInFunctionEmulator.cleanup(); } -const std::map &OutputHLSL::getShaderStorageBlockRegisterMap() const -{ - return mResourcesHLSL->getShaderStorageBlockRegisterMap(); -} - const std::map &OutputHLSL::getUniformBlockRegisterMap() const { return mResourcesHLSL->getUniformBlockRegisterMap(); @@ -687,7 +626,6 @@ void OutputHLSL::header(TInfoSinkBase &out, mResourcesHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable); out << mResourcesHLSL->uniformBlocksHeader(mReferencedUniformBlocks, mUniformBlockOptimizedMap); - mSSBOOutputHLSL->writeShaderStorageBlocksHeader(mShaderType, out); if (!mEqualityFunctions.empty()) { @@ -745,11 +683,6 @@ void OutputHLSL::header(TInfoSinkBase &out, "#define FLATTEN\n" "#endif\n"; - // array stride for atomic counter buffers is always 4 per original extension - // ARB_shader_atomic_counters and discussion on - // https://github.com/KhronosGroup/OpenGL-API/issues/5 - out << "\n#define ATOMIC_COUNTER_ARRAY_STRIDE 4\n\n"; - if (mUseZeroArray) { out << DefineZeroArray() << "\n"; @@ -864,11 +797,6 @@ void OutputHLSL::header(TInfoSinkBase &out, out << "static bool gl_FrontFacing = false;\n"; } - if (mUsesHelperInvocation) - { - out << "static bool gl_HelperInvocation = false;\n"; - } - out << "\n"; if (mUsesDepthRange) @@ -913,11 +841,8 @@ void OutputHLSL::header(TInfoSinkBase &out, if (mOutputType == SH_HLSL_4_1_OUTPUT) { out << " uint dx_Misc : packoffset(c2.w);\n"; - unsigned int registerIndex = 4; + const unsigned int registerIndex = 4; mResourcesHLSL->samplerMetadataUniforms(out, registerIndex); - // Sampler metadata struct must be two 4-vec, 32 bytes. - registerIndex += mResourcesHLSL->getSamplerCount() * 2; - mResourcesHLSL->imageMetadataUniforms(out, registerIndex); } out << "};\n"; @@ -1129,68 +1054,6 @@ void OutputHLSL::header(TInfoSinkBase &out, out << kImage2DFunctionString << "\n"; } } - else // Compute shader - { - ASSERT(mShaderType == GL_COMPUTE_SHADER); - - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - if (mUsesNumWorkGroups) - { - out << " uint3 gl_NumWorkGroups : packoffset(c0);\n"; - } - ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT); - unsigned int registerIndex = 1; - mResourcesHLSL->samplerMetadataUniforms(out, registerIndex); - // Sampler metadata struct must be two 4-vec, 32 bytes. - registerIndex += mResourcesHLSL->getSamplerCount() * 2; - mResourcesHLSL->imageMetadataUniforms(out, registerIndex); - out << "};\n"; - - out << kImage2DFunctionString << "\n"; - - std::ostringstream systemValueDeclaration = sh::InitializeStream(); - std::ostringstream glBuiltinInitialization = sh::InitializeStream(); - - systemValueDeclaration << "\nstruct CS_INPUT\n{\n"; - glBuiltinInitialization << "\nvoid initGLBuiltins(CS_INPUT input)\n" << "{\n"; - - if (mUsesWorkGroupID) - { - out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n"; - systemValueDeclaration << " uint3 dx_WorkGroupID : " << "SV_GroupID;\n"; - glBuiltinInitialization << " gl_WorkGroupID = input.dx_WorkGroupID;\n"; - } - - if (mUsesLocalInvocationID) - { - out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n"; - systemValueDeclaration << " uint3 dx_LocalInvocationID : " << "SV_GroupThreadID;\n"; - glBuiltinInitialization << " gl_LocalInvocationID = input.dx_LocalInvocationID;\n"; - } - - if (mUsesGlobalInvocationID) - { - out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n"; - systemValueDeclaration << " uint3 dx_GlobalInvocationID : " - << "SV_DispatchThreadID;\n"; - glBuiltinInitialization << " gl_GlobalInvocationID = input.dx_GlobalInvocationID;\n"; - } - - if (mUsesLocalInvocationIndex) - { - out << "static uint gl_LocalInvocationIndex = uint(0);\n"; - systemValueDeclaration << " uint dx_LocalInvocationIndex : " << "SV_GroupIndex;\n"; - glBuiltinInitialization - << " gl_LocalInvocationIndex = input.dx_LocalInvocationIndex;\n"; - } - - systemValueDeclaration << "};\n\n"; - glBuiltinInitialization << "};\n\n"; - - out << systemValueDeclaration.str(); - out << glBuiltinInitialization.str(); - } if (!mappedStructs.empty()) { @@ -1203,7 +1066,6 @@ void OutputHLSL::header(TInfoSinkBase &out, bool getDimensionsIgnoresBaseLevel = mCompileOptions.HLSLGetDimensionsIgnoresBaseLevel; mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel); mImageFunctionHLSL->imageFunctionHeader(out); - mAtomicCounterFunctionHLSL->atomicCounterFunctionHeader(out); if (mUsesFragCoord) { @@ -1220,11 +1082,6 @@ void OutputHLSL::header(TInfoSinkBase &out, out << "#define GL_USES_FRONT_FACING\n"; } - if (mUsesHelperInvocation) - { - out << "#define GL_USES_HELPER_INVOCATION\n"; - } - if (mUsesPointSize) { out << "#define GL_USES_POINT_SIZE\n"; @@ -1329,21 +1186,6 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesNumSamples = true; out << name; } - else if (IsAtomicCounter(variable.getType().getBasicType())) - { - const TType &variableType = variable.getType(); - if (variableType.getQualifier() == EvqUniform) - { - TLayoutQualifier layout = variableType.getLayoutQualifier(); - mReferencedUniforms[uniqueId.get()] = &variable; - out << getAtomicCounterNameForBinding(layout.binding) << ", " << layout.offset; - } - else - { - TString varName = DecorateVariableIfNeeded(variable); - out << varName << ", " << varName << "_offset"; - } - } else { const TType &variableType = variable.getType(); @@ -1442,11 +1284,6 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesFrontFacing = true; out << name; } - else if (qualifier == EvqHelperInvocation) - { - mUsesHelperInvocation = true; - out << name; - } else if (qualifier == EvqPointSize) { mUsesPointSize = true; @@ -1488,31 +1325,6 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesSampleMask = true; out << name; } - else if (qualifier == EvqNumWorkGroups) - { - mUsesNumWorkGroups = true; - out << name; - } - else if (qualifier == EvqWorkGroupID) - { - mUsesWorkGroupID = true; - out << name; - } - else if (qualifier == EvqLocalInvocationID) - { - mUsesLocalInvocationID = true; - out << name; - } - else if (qualifier == EvqGlobalInvocationID) - { - mUsesGlobalInvocationID = true; - out << name; - } - else if (qualifier == EvqLocalInvocationIndex) - { - mUsesLocalInvocationIndex = true; - out << name; - } else { out << DecorateVariableIfNeeded(variable); @@ -1648,49 +1460,6 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) // function call is assigned. ASSERT(rightAgg == nullptr); } - // Assignment expressions with atomic functions should be transformed into atomic - // function calls in HLSL. - // e.g. original_value = atomicAdd(dest, value) should be translated into - // InterlockedAdd(dest, value, original_value); - else if (IsAtomicFunctionForSharedVariableDirectAssign(*node)) - { - TIntermAggregate *atomicFunctionNode = node->getRight()->getAsAggregate(); - TOperator atomicFunctionOp = atomicFunctionNode->getOp(); - out << GetHLSLAtomicFunctionStringAndLeftParenthesis(atomicFunctionOp); - TIntermSequence *argumentSeq = atomicFunctionNode->getSequence(); - ASSERT(argumentSeq->size() >= 2u); - for (auto &argument : *argumentSeq) - { - argument->traverse(this); - out << ", "; - } - node->getLeft()->traverse(this); - out << ")"; - return false; - } - else if (IsInShaderStorageBlock(node->getLeft())) - { - mSSBOOutputHLSL->outputStoreFunctionCallPrefix(node->getLeft()); - out << ", "; - if (IsInShaderStorageBlock(node->getRight())) - { - mSSBOOutputHLSL->outputLoadFunctionCall(node->getRight()); - } - else - { - node->getRight()->traverse(this); - } - - out << ")"; - return false; - } - else if (IsInShaderStorageBlock(node->getRight())) - { - node->getLeft()->traverse(this); - out << " = "; - mSSBOOutputHLSL->outputLoadFunctionCall(node->getRight()); - return false; - } outputAssign(visit, node->getType(), out); break; @@ -1722,11 +1491,6 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) else if (visit == InVisit) { out << " = "; - if (IsInShaderStorageBlock(node->getRight())) - { - mSSBOOutputHLSL->outputLoadFunctionCall(node->getRight()); - return false; - } } break; case EOpAddAssign: @@ -1825,10 +1589,6 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) // separator to access the sampler variable that has been moved out of the struct. outputTriplet(out, visit, "", "_", ""); } - else if (IsAtomicCounter(leftType.getBasicType())) - { - outputTriplet(out, visit, "", " + (", ") * ATOMIC_COUNTER_ARRAY_STRIDE"); - } else { outputTriplet(out, visit, "", "[", "]"); @@ -1859,12 +1619,6 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) // We do not currently support indirect references to interface blocks ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock); - const TType &leftType = node->getLeft()->getType(); - if (IsAtomicCounter(leftType.getBasicType())) - { - outputTriplet(out, visit, "", " + (", ") * ATOMIC_COUNTER_ARRAY_STRIDE"); - } - else { outputTriplet(out, visit, "", "[", "]"); if (visit == PostVisit) @@ -1928,7 +1682,6 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) break; case EOpIndexDirectInterfaceBlock: { - ASSERT(!IsInShaderStorageBlock(node->getLeft())); bool structInStd140UniformBlock = node->getBasicType() == EbtStruct && IsInStd140UniformBlock(node->getLeft()) && needStructMapping(node); @@ -2229,13 +1982,6 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) // tested in GLSLTest and results are consistent with GL. outputTriplet(out, visit, "firstbithigh(", "", ")"); break; - case EOpArrayLength: - { - TIntermTyped *operand = node->getOperand(); - ASSERT(IsInShaderStorageBlock(operand)); - mSSBOOutputHLSL->outputLengthFunctionCall(operand); - return false; - } default: UNREACHABLE(); } @@ -2290,14 +2036,7 @@ bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node) out << "{\n"; if (isMainBlock) { - if (mShaderType == GL_COMPUTE_SHADER) - { - out << "initGLBuiltins(input);\n"; - } - else - { - out << "@@ MAIN PROLOGUE @@\n"; - } + out << "@@ MAIN PROLOGUE @@\n"; } } @@ -2382,11 +2121,6 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition } out << "PS_OUTPUT main(@@ PIXEL MAIN PARAMETERS @@)"; break; - case GL_COMPUTE_SHADER: - out << "[numthreads(" << mWorkGroupSize[0] << ", " << mWorkGroupSize[1] << ", " - << mWorkGroupSize[2] << ")]\n"; - out << "void main(CS_INPUT input)"; - break; default: UNREACHABLE(); break; @@ -2457,11 +2191,7 @@ bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node) declarator->getAsSymbolNode()->variable().symbolType() != SymbolType::Empty) // Variable declaration { - if (declarator->getQualifier() == EvqShared) - { - out << "groupshared "; - } - else if (!mInsideFunction) + if (!mInsideFunction) { out << "static "; } @@ -2474,14 +2204,7 @@ bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node) { symbol->traverse(this); out << ArrayString(symbol->getType()); - // Temporarily disable shadred memory initialization. It is very slow for D3D11 - // drivers to compile a compute shader if we add code to initialize a - // groupshared array variable with a large array size. And maybe produce - // incorrect result. See http://anglebug.com/40644676. - if (declarator->getQualifier() != EvqShared) - { - out << " = " + zeroInitializer(symbol->getType()); - } + out << " = " + zeroInitializer(symbol->getType()); } else { @@ -2595,13 +2318,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) type.getMemoryQualifier().readonly); out << imageFunctionName << "("; } - else if (node->getFunction()->isAtomicCounterFunction()) - { - const ImmutableString &name = node->getFunction()->name(); - ImmutableString atomicFunctionName = - mAtomicCounterFunctionHLSL->useAtomicCounterFunction(name); - out << atomicFunctionName << "("; - } else { const ImmutableString &name = node->getFunction()->name(); @@ -2832,87 +2548,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } break; } - case EOpBarrier: - // barrier() is translated to GroupMemoryBarrierWithGroupSync(), which is the - // cheapest *WithGroupSync() function, without any functionality loss, but - // with the potential for severe performance loss. - outputTriplet(out, visit, "GroupMemoryBarrierWithGroupSync(", "", ")"); - break; - case EOpMemoryBarrierShared: - outputTriplet(out, visit, "GroupMemoryBarrier(", "", ")"); - break; - case EOpMemoryBarrierAtomicCounter: - case EOpMemoryBarrierBuffer: case EOpMemoryBarrierImage: outputTriplet(out, visit, "DeviceMemoryBarrier(", "", ")"); break; - case EOpGroupMemoryBarrier: - case EOpMemoryBarrier: - outputTriplet(out, visit, "AllMemoryBarrier(", "", ")"); - break; - - // Single atomic function calls without return value. - // e.g. atomicAdd(dest, value) should be translated into InterlockedAdd(dest, value). - case EOpAtomicAdd: - case EOpAtomicMin: - case EOpAtomicMax: - case EOpAtomicAnd: - case EOpAtomicOr: - case EOpAtomicXor: - // The parameter 'original_value' of InterlockedExchange(dest, value, original_value) - // and InterlockedCompareExchange(dest, compare_value, value, original_value) is not - // optional. - // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/interlockedexchange - // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/interlockedcompareexchange - // So all the call of atomicExchange(dest, value) and atomicCompSwap(dest, - // compare_value, value) should all be modified into the form of "int temp; temp = - // atomicExchange(dest, value);" and "int temp; temp = atomicCompSwap(dest, - // compare_value, value);" in the intermediate tree before traversing outputHLSL. - case EOpAtomicExchange: - case EOpAtomicCompSwap: - { - ASSERT(node->getChildCount() > 1); - TIntermTyped *memNode = (*node->getSequence())[0]->getAsTyped(); - if (IsInShaderStorageBlock(memNode)) - { - // Atomic memory functions for SSBO. - // "_ssbo_atomicXXX_TYPE(RWByteAddressBuffer buffer, uint loc" is written to |out|. - mSSBOOutputHLSL->outputAtomicMemoryFunctionCallPrefix(memNode, node->getOp()); - // Write the rest argument list to |out|. - for (size_t i = 1; i < node->getChildCount(); i++) - { - out << ", "; - TIntermTyped *argument = (*node->getSequence())[i]->getAsTyped(); - if (IsInShaderStorageBlock(argument)) - { - mSSBOOutputHLSL->outputLoadFunctionCall(argument); - } - else - { - argument->traverse(this); - } - } - - out << ")"; - return false; - } - else - { - // Atomic memory functions for shared variable. - if (node->getOp() != EOpAtomicExchange && node->getOp() != EOpAtomicCompSwap) - { - outputTriplet(out, visit, - GetHLSLAtomicFunctionStringAndLeftParenthesis(node->getOp()), ",", - ")"); - } - else - { - UNREACHABLE(); - } - } - - break; - } } return true; @@ -3145,11 +2783,6 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) { ASSERT(!mInsideMain); out << "return "; - if (IsInShaderStorageBlock(node->getExpression())) - { - mSSBOOutputHLSL->outputLoadFunctionCall(node->getExpression()); - return false; - } } else { @@ -3445,18 +3078,8 @@ void OutputHLSL::writeParameter(const TVariable *param, TInfoSinkBase &out) } } - // If the parameter is an atomic counter, we need to add an extra parameter to keep track of the - // buffer offset. - if (IsAtomicCounter(type.getBasicType())) - { - out << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr << ", int " - << nameStr << "_offset"; - } - else - { - out << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr - << ArrayString(type); - } + out << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr + << ArrayString(type); // If the structure parameter contains samplers, they need to be passed into the function as // separate parameters. HLSL doesn't natively support samplers in structs. diff --git a/src/compiler/translator/hlsl/OutputHLSL.h b/src/compiler/translator/hlsl/OutputHLSL.h index cf7be71c1d7..5e56601575e 100644 --- a/src/compiler/translator/hlsl/OutputHLSL.h +++ b/src/compiler/translator/hlsl/OutputHLSL.h @@ -16,14 +16,12 @@ #include "compiler/translator/FlagStd140Structs.h" #include "compiler/translator/ImmutableString.h" #include "compiler/translator/hlsl/ASTMetadataHLSL.h" -#include "compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.h" #include "compiler/translator/tree_util/IntermTraverse.h" class BuiltInFunctionEmulator; namespace sh { -class AtomicCounterFunctionHLSL; class ImageFunctionHLSL; class ResourcesHLSL; class StructureHLSL; @@ -32,7 +30,17 @@ class TSymbolTable; class TVariable; class UnfoldShortCircuit; +struct TReferencedBlock : angle::NonCopyable +{ + POOL_ALLOCATOR_NEW_DELETE + TReferencedBlock(const TInterfaceBlock *block, const TVariable *instanceVariable); + const TInterfaceBlock *block; + const TVariable *instanceVariable; // May be nullptr if the block is not instanced. +}; + +// Maps from uniqueId to a variable. using ReferencedVariables = std::map; +using ReferencedInterfaceBlocks = std::map; class OutputHLSL : public TIntermTraverser { @@ -47,11 +55,9 @@ class OutputHLSL : public TIntermTraverser int maxDualSourceDrawBuffers, const std::vector &uniforms, const ShCompileOptions &compileOptions, - sh::WorkGroupSize workGroupSize, TSymbolTable *symbolTable, PerformanceDiagnostics *perfDiagnostics, const std::map &uniformBlockOptimizedMap, - const std::vector &shaderStorageBlocks, uint8_t clipDistanceSize, uint8_t cullDistanceSize, bool isEarlyFragmentTestsSpecified); @@ -60,7 +66,6 @@ class OutputHLSL : public TIntermTraverser void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); - const std::map &getShaderStorageBlockRegisterMap() const; const std::map &getUniformBlockRegisterMap() const; const std::map &getUniformBlockUseStructuredBufferMap() const; const std::map &getUniformRegisterMap() const; @@ -75,8 +80,6 @@ class OutputHLSL : public TIntermTraverser } protected: - friend class ShaderStorageBlockOutputHLSL; - TString zeroInitializer(const TType &type) const; void writeReferencedAttributes(TInfoSinkBase &out) const; @@ -194,7 +197,6 @@ class OutputHLSL : public TIntermTraverser ResourcesHLSL *mResourcesHLSL; TextureFunctionHLSL *mTextureFunctionHLSL; ImageFunctionHLSL *mImageFunctionHLSL; - AtomicCounterFunctionHLSL *mAtomicCounterFunctionHLSL; // Parameters determining what goes in the header output bool mUsesFragColor; @@ -203,7 +205,6 @@ class OutputHLSL : public TIntermTraverser bool mUsesFragCoord; bool mUsesPointCoord; bool mUsesFrontFacing; - bool mUsesHelperInvocation; bool mUsesPointSize; bool mUsesInstanceID; bool mHasMultiviewExtensionEnabled; @@ -215,11 +216,6 @@ class OutputHLSL : public TIntermTraverser bool mUsesSampleMaskIn; bool mUsesSampleMask; bool mUsesNumSamples; - bool mUsesNumWorkGroups; - bool mUsesWorkGroupID; - bool mUsesLocalInvocationID; - bool mUsesGlobalInvocationID; - bool mUsesLocalInvocationIndex; bool mUsesXor; bool mUsesDiscardRewriting; bool mUsesNestedBreak; @@ -285,8 +281,6 @@ class OutputHLSL : public TIntermTraverser }; std::vector mFlatEvaluateFunctions; - sh::WorkGroupSize mWorkGroupSize; - PerformanceDiagnostics *mPerfDiagnostics; private: @@ -297,7 +291,6 @@ class OutputHLSL : public TIntermTraverser // assignment. bool needStructMapping(TIntermTyped *node); - ShaderStorageBlockOutputHLSL *mSSBOOutputHLSL; uint8_t mClipDistanceSize; uint8_t mCullDistanceSize; bool mIsEarlyFragmentTestsSpecified; diff --git a/src/compiler/translator/hlsl/ResourcesHLSL.cpp b/src/compiler/translator/hlsl/ResourcesHLSL.cpp index c872566b9ab..abf6172e76e 100644 --- a/src/compiler/translator/hlsl/ResourcesHLSL.cpp +++ b/src/compiler/translator/hlsl/ResourcesHLSL.cpp @@ -11,7 +11,6 @@ #include "common/utilities.h" #include "compiler/translator/ImmutableStringBuilder.h" -#include "compiler/translator/hlsl/AtomicCounterFunctionHLSL.h" #include "compiler/translator/hlsl/StructureHLSL.h" #include "compiler/translator/hlsl/UtilsHLSL.h" #include "compiler/translator/hlsl/blocklayoutHLSL.h" @@ -464,15 +463,6 @@ void ResourcesHLSL::outputUniform(TInfoSinkBase &out, out << ArrayString(type) << " : " << registerString << ";\n"; } -void ResourcesHLSL::outputAtomicCounterBuffer(TInfoSinkBase &out, - const int binding, - const unsigned int registerIndex) -{ - // Atomic counter memory access is not incoherent - out << "uniform globallycoherent RWByteAddressBuffer " - << getAtomicCounterNameForBinding(binding) << " : register(u" << registerIndex << ");\n"; -} - void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, ShShaderOutput outputType, const ReferencedVariables &referencedUniforms, @@ -490,7 +480,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, TVector> groupedReadonlyImageUniforms(HLSL_TEXTURE_MAX + 1); TVector> groupedImageUniforms(HLSL_RWTEXTURE_MAX + 1); - TUnorderedMap assignedAtomicCounterBindings; unsigned int reservedReadonlyImageRegisterCount = 0, reservedImageRegisterCount = 0; for (auto &uniformIt : referencedUniforms) { @@ -532,24 +521,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, groupedImageUniforms[group].push_back(&variable); } } - else if (outputType == SH_HLSL_4_1_OUTPUT && IsAtomicCounter(type.getBasicType())) - { - TLayoutQualifier layout = type.getLayoutQualifier(); - int binding = layout.binding; - unsigned int registerIndex; - if (assignedAtomicCounterBindings.find(binding) == assignedAtomicCounterBindings.end()) - { - registerIndex = mUAVRegister++; - assignedAtomicCounterBindings[binding] = registerIndex; - outputAtomicCounterBuffer(out, binding, registerIndex); - } - else - { - registerIndex = assignedAtomicCounterBindings[binding]; - } - const ShaderVariable *uniform = findUniformByName(variable.name()); - mUniformRegisterMap[uniform->name] = registerIndex; - } else { if (type.isStructureContainingSamplers()) @@ -589,8 +560,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, if (outputType == SH_HLSL_4_1_OUTPUT) { unsigned int groupTextureRegisterIndex = 0; - // Atomic counters and RW texture share the same resources. Therefore, RW texture need to - // start counting after the last atomic counter. unsigned int groupRWTextureRegisterIndex = mUAVRegister; // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case. ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D); @@ -614,11 +583,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, &groupTextureRegisterIndex); } mReadonlyImageCount = groupTextureRegisterIndex - mReadonlyImage2DRegisterIndex; - if (mReadonlyImageCount) - { - out << "static const uint readonlyImageIndexStart = " << mReadonlyImage2DRegisterIndex - << ";\n"; - } // Reserve u type register for writable image2D variables. mImage2DRegisterIndex = mUAVRegister; @@ -632,10 +596,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, &groupRWTextureRegisterIndex); } mImageCount = groupRWTextureRegisterIndex - mImage2DRegisterIndex; - if (mImageCount) - { - out << "static const uint imageIndexStart = " << mImage2DRegisterIndex << ";\n"; - } } } @@ -656,31 +616,6 @@ void ResourcesHLSL::samplerMetadataUniforms(TInfoSinkBase &out, unsigned int reg } } -void ResourcesHLSL::imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex) -{ - if (mReadonlyImageCount > 0 || mImageCount > 0) - { - out << " struct ImageMetadata\n" - " {\n" - " int layer;\n" - " uint level;\n" - " int2 padding;\n" - " };\n"; - - if (mReadonlyImageCount > 0) - { - out << " ImageMetadata readonlyImageMetadata[" << mReadonlyImageCount - << "] : packoffset(c" << regIndex << ");\n"; - } - - if (mImageCount > 0) - { - out << " ImageMetadata imageMetadata[" << mImageCount << "] : packoffset(c" - << regIndex + mReadonlyImageCount << ");\n"; - } - } -} - TString ResourcesHLSL::uniformBlocksHeader( const ReferencedInterfaceBlocks &referencedInterfaceBlocks, const std::map &uniformBlockOptimizedMap) @@ -748,58 +683,6 @@ TString ResourcesHLSL::uniformBlocksHeader( return (interfaceBlocks.empty() ? "" : ("// Uniform Blocks\n\n" + interfaceBlocks)); } -void ResourcesHLSL::allocateShaderStorageBlockRegisters( - const ReferencedInterfaceBlocks &referencedInterfaceBlocks) -{ - for (const auto &interfaceBlockReference : referencedInterfaceBlocks) - { - const TInterfaceBlock &interfaceBlock = *interfaceBlockReference.second->block; - const TVariable *instanceVariable = interfaceBlockReference.second->instanceVariable; - - mShaderStorageBlockRegisterMap[interfaceBlock.name().data()] = mUAVRegister; - - if (instanceVariable != nullptr && instanceVariable->getType().isArray()) - { - mUAVRegister += instanceVariable->getType().getOutermostArraySize(); - } - else - { - mUAVRegister += 1u; - } - } -} - -TString ResourcesHLSL::shaderStorageBlocksHeader( - const ReferencedInterfaceBlocks &referencedInterfaceBlocks) -{ - TString interfaceBlocks; - - for (const auto &interfaceBlockReference : referencedInterfaceBlocks) - { - const TInterfaceBlock &interfaceBlock = *interfaceBlockReference.second->block; - const TVariable *instanceVariable = interfaceBlockReference.second->instanceVariable; - - unsigned int activeRegister = mShaderStorageBlockRegisterMap[interfaceBlock.name().data()]; - - if (instanceVariable != nullptr && instanceVariable->getType().isArray()) - { - unsigned int instanceArraySize = instanceVariable->getType().getOutermostArraySize(); - for (unsigned int arrayIndex = 0; arrayIndex < instanceArraySize; arrayIndex++) - { - interfaceBlocks += shaderStorageBlockString( - interfaceBlock, instanceVariable, activeRegister + arrayIndex, arrayIndex); - } - } - else - { - interfaceBlocks += shaderStorageBlockString(interfaceBlock, instanceVariable, - activeRegister, GL_INVALID_INDEX); - } - } - - return interfaceBlocks; -} - TString ResourcesHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock, const TVariable *instanceVariable, unsigned int registerIndex, @@ -879,26 +762,6 @@ TString ResourcesHLSL::uniformBlockWithOneLargeArrayMemberString( return hlsl; } -TString ResourcesHLSL::shaderStorageBlockString(const TInterfaceBlock &interfaceBlock, - const TVariable *instanceVariable, - unsigned int registerIndex, - unsigned int arrayIndex) -{ - TString hlsl; - if (instanceVariable != nullptr) - { - hlsl += "RWByteAddressBuffer " + - InterfaceBlockInstanceString(instanceVariable->name(), arrayIndex) + - ": register(u" + str(registerIndex) + ");\n"; - } - else - { - hlsl += "RWByteAddressBuffer " + Decorate(interfaceBlock.name()) + ": register(u" + - str(registerIndex) + ");\n"; - } - return hlsl; -} - TString ResourcesHLSL::InterfaceBlockInstanceString(const ImmutableString &instanceName, unsigned int arrayIndex) { diff --git a/src/compiler/translator/hlsl/ResourcesHLSL.h b/src/compiler/translator/hlsl/ResourcesHLSL.h index 5028f9895c1..e95d1b16710 100644 --- a/src/compiler/translator/hlsl/ResourcesHLSL.h +++ b/src/compiler/translator/hlsl/ResourcesHLSL.h @@ -37,23 +37,14 @@ class ResourcesHLSL : angle::NonCopyable // Must be called after uniformsHeader void samplerMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex); unsigned int getSamplerCount() const { return mSamplerCount; } - void imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex); TString uniformBlocksHeader( const ReferencedInterfaceBlocks &referencedInterfaceBlocks, const std::map &uniformBlockOptimizedMap); - void allocateShaderStorageBlockRegisters( - const ReferencedInterfaceBlocks &referencedInterfaceBlocks); - TString shaderStorageBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks); // Used for direct index references static TString InterfaceBlockInstanceString(const ImmutableString &instanceName, unsigned int arrayIndex); - const std::map &getShaderStorageBlockRegisterMap() const - { - return mShaderStorageBlockRegisterMap; - } - const std::map &getUniformBlockRegisterMap() const { return mUniformBlockRegisterMap; @@ -83,10 +74,6 @@ class ResourcesHLSL : angle::NonCopyable unsigned int registerIndex, unsigned int arrayIndex); - TString shaderStorageBlockString(const TInterfaceBlock &interfaceBlock, - const TVariable *instanceVariable, - unsigned int registerIndex, - unsigned int arrayIndex); TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); TString uniformBlockStructString(const TInterfaceBlock &interfaceBlock); @@ -96,9 +83,6 @@ class ResourcesHLSL : angle::NonCopyable const TType &type, const TVariable &variable, const unsigned int registerIndex); - void outputAtomicCounterBuffer(TInfoSinkBase &out, - const int binding, - const unsigned int registerIndex); // Returns the uniform's register index unsigned int assignUniformRegister(const TType &type, @@ -140,7 +124,6 @@ class ResourcesHLSL : angle::NonCopyable const std::vector &mUniforms; std::map mUniformBlockRegisterMap; - std::map mShaderStorageBlockRegisterMap; std::map mUniformRegisterMap; std::map mUniformBlockUseStructuredBufferMap; unsigned int mReadonlyImage2DRegisterIndex = 0; diff --git a/src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.cpp b/src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.cpp deleted file mode 100644 index 1ff02b0feb7..00000000000 --- a/src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.cpp +++ /dev/null @@ -1,441 +0,0 @@ -// -// Copyright 2018 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. -// -// ShaderStorageBlockFunctionHLSL: Wrapper functions for RWByteAddressBuffer Load/Store functions. -// - -#include "compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.h" - -#include "common/utilities.h" -#include "compiler/translator/blocklayout.h" -#include "compiler/translator/hlsl/UtilsHLSL.h" -#include "compiler/translator/hlsl/blocklayoutHLSL.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -// static -void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody( - TInfoSinkBase &out, - const ShaderStorageBlockFunction &ssboFunction) -{ - const char *convertString; - switch (ssboFunction.type.getBasicType()) - { - case EbtFloat: - convertString = "asfloat("; - break; - case EbtInt: - convertString = "asint("; - break; - case EbtUInt: - convertString = "asuint("; - break; - case EbtBool: - convertString = "asint("; - break; - default: - UNREACHABLE(); - return; - } - - size_t bytesPerComponent = - gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type))); - out << " " << ssboFunction.typeString << " result"; - if (ssboFunction.type.isScalar()) - { - size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent; - out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n "; - } - else if (ssboFunction.type.isVector()) - { - if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle) - { - size_t componentStride = bytesPerComponent; - if (ssboFunction.rowMajor) - { - componentStride = ssboFunction.matrixStride; - } - - out << " = {"; - for (const int offset : ssboFunction.swizzleOffsets) - { - size_t offsetInBytes = offset * componentStride; - out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),"; - } - out << "};\n"; - } - else - { - out << " = " << convertString << "buffer.Load" - << static_cast(ssboFunction.type.getNominalSize()) << "(loc));\n"; - } - } - else if (ssboFunction.type.isMatrix()) - { - if (ssboFunction.rowMajor) - { - out << ";"; - out << " float" << static_cast(ssboFunction.type.getRows()) << "x" - << static_cast(ssboFunction.type.getCols()) << " tmp_ = {"; - for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++) - { - out << "asfloat(buffer.Load" << static_cast(ssboFunction.type.getCols()) - << "(loc + " << rowIndex * ssboFunction.matrixStride << ")), "; - } - out << "};\n"; - out << " result = transpose(tmp_);\n"; - } - else - { - out << " = {"; - for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++) - { - out << "asfloat(buffer.Load" << static_cast(ssboFunction.type.getRows()) - << "(loc + " << columnIndex * ssboFunction.matrixStride << ")), "; - } - out << "};\n"; - } - } - else - { - // TODO(jiajia.qin@intel.com): Process all possible return types. - // http://anglebug.com/40644618 - out << ";\n"; - } - - out << " return result;\n"; - return; -} - -// static -void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody( - TInfoSinkBase &out, - const ShaderStorageBlockFunction &ssboFunction) -{ - size_t bytesPerComponent = - gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type))); - if (ssboFunction.type.isScalar()) - { - size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent; - if (ssboFunction.type.getBasicType() == EbtBool) - { - out << " buffer.Store(loc + " << offset << ", uint(value));\n"; - } - else - { - out << " buffer.Store(loc + " << offset << ", asuint(value));\n"; - } - } - else if (ssboFunction.type.isVector()) - { - out << " uint" << static_cast(ssboFunction.type.getNominalSize()) - << " _value;\n"; - if (ssboFunction.type.getBasicType() == EbtBool) - { - out << " _value = uint" << static_cast(ssboFunction.type.getNominalSize()) - << "(value);\n"; - } - else - { - out << " _value = asuint(value);\n"; - } - - if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle) - { - size_t componentStride = bytesPerComponent; - if (ssboFunction.rowMajor) - { - componentStride = ssboFunction.matrixStride; - } - const TVector &swizzleOffsets = ssboFunction.swizzleOffsets; - for (int index = 0; index < static_cast(swizzleOffsets.size()); index++) - { - size_t offsetInBytes = swizzleOffsets[index] * componentStride; - out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n"; - } - } - else - { - out << " buffer.Store" << static_cast(ssboFunction.type.getNominalSize()) - << "(loc, _value);\n"; - } - } - else if (ssboFunction.type.isMatrix()) - { - if (ssboFunction.rowMajor) - { - out << " float" << static_cast(ssboFunction.type.getRows()) << "x" - << static_cast(ssboFunction.type.getCols()) - << " tmp_ = transpose(value);\n"; - for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++) - { - out << " buffer.Store" << static_cast(ssboFunction.type.getCols()) - << "(loc + " << rowIndex * ssboFunction.matrixStride << ", asuint(tmp_[" - << static_cast(rowIndex) << "]));\n"; - } - } - else - { - for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++) - { - out << " buffer.Store" << static_cast(ssboFunction.type.getRows()) - << "(loc + " << columnIndex * ssboFunction.matrixStride << ", asuint(value[" - << static_cast(columnIndex) << "]));\n"; - } - } - } - else - { - // TODO(jiajia.qin@intel.com): Process all possible return types. - // http://anglebug.com/40644618 - } -} - -// static -void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out, - int unsizedArrayStride) -{ - out << " uint dim = 0;\n"; - out << " buffer.GetDimensions(dim);\n"; - out << " return int((dim - loc)/uint(" << unsizedArrayStride << "));\n"; -} - -// static -void ShaderStorageBlockFunctionHLSL::OutputSSBOAtomicMemoryFunctionBody( - TInfoSinkBase &out, - const ShaderStorageBlockFunction &ssboFunction) -{ - out << " " << ssboFunction.typeString << " original_value;\n"; - switch (ssboFunction.method) - { - case SSBOMethod::ATOMIC_ADD: - out << " buffer.InterlockedAdd(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_MIN: - out << " buffer.InterlockedMin(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_MAX: - out << " buffer.InterlockedMax(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_AND: - out << " buffer.InterlockedAnd(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_OR: - out << " buffer.InterlockedOr(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_XOR: - out << " buffer.InterlockedXor(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_EXCHANGE: - out << " buffer.InterlockedExchange(loc, value, original_value);\n"; - break; - case SSBOMethod::ATOMIC_COMPSWAP: - out << " buffer.InterlockedCompareExchange(loc, compare_value, value, " - "original_value);\n"; - break; - default: - UNREACHABLE(); - } - out << " return original_value;\n"; -} - -bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<( - const ShaderStorageBlockFunction &rhs) const -{ - return functionName < rhs.functionName; -} - -TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction( - const TType &type, - SSBOMethod method, - TLayoutBlockStorage storage, - bool rowMajor, - int matrixStride, - int unsizedArrayStride, - TIntermSwizzle *swizzleNode) -{ - ShaderStorageBlockFunction ssboFunction; - ssboFunction.typeString = TypeString(type); - ssboFunction.method = method; - switch (method) - { - case SSBOMethod::LOAD: - ssboFunction.functionName = "_Load_"; - break; - case SSBOMethod::STORE: - ssboFunction.functionName = "_Store_"; - break; - case SSBOMethod::LENGTH: - ssboFunction.unsizedArrayStride = unsizedArrayStride; - ssboFunction.functionName = "_Length_" + str(unsizedArrayStride); - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_ADD: - ssboFunction.functionName = "_ssbo_atomicAdd_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_MIN: - ssboFunction.functionName = "_ssbo_atomicMin_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_MAX: - ssboFunction.functionName = "_ssbo_atomicMax_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_AND: - ssboFunction.functionName = "_ssbo_atomicAnd_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_OR: - ssboFunction.functionName = "_ssbo_atomicOr_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_XOR: - ssboFunction.functionName = "_ssbo_atomicXor_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_EXCHANGE: - ssboFunction.functionName = "_ssbo_atomicExchange_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - case SSBOMethod::ATOMIC_COMPSWAP: - ssboFunction.functionName = "_ssbo_atomicCompSwap_" + ssboFunction.typeString; - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; - default: - UNREACHABLE(); - } - - ssboFunction.functionName += ssboFunction.typeString; - ssboFunction.type = type; - if (swizzleNode != nullptr) - { - ssboFunction.swizzleOffsets = swizzleNode->getSwizzleOffsets(); - ssboFunction.isDefaultSwizzle = false; - } - else - { - if (ssboFunction.type.getNominalSize() > 1) - { - for (uint8_t index = 0; index < ssboFunction.type.getNominalSize(); index++) - { - ssboFunction.swizzleOffsets.push_back(index); - } - } - else - { - ssboFunction.swizzleOffsets.push_back(0); - } - - ssboFunction.isDefaultSwizzle = true; - } - ssboFunction.rowMajor = rowMajor; - ssboFunction.matrixStride = matrixStride; - ssboFunction.functionName += "_" + TString(getBlockStorageString(storage)); - - if (rowMajor) - { - ssboFunction.functionName += "_rm_"; - } - else - { - ssboFunction.functionName += "_cm_"; - } - - for (const int offset : ssboFunction.swizzleOffsets) - { - switch (offset) - { - case 0: - ssboFunction.functionName += "x"; - break; - case 1: - ssboFunction.functionName += "y"; - break; - case 2: - ssboFunction.functionName += "z"; - break; - case 3: - ssboFunction.functionName += "w"; - break; - default: - UNREACHABLE(); - } - } - - mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); - return ssboFunction.functionName; -} - -void ShaderStorageBlockFunctionHLSL::shaderStorageBlockFunctionHeader(TInfoSinkBase &out) -{ - for (const ShaderStorageBlockFunction &ssboFunction : mRegisteredShaderStorageBlockFunctions) - { - switch (ssboFunction.method) - { - case SSBOMethod::LOAD: - { - // Function header - out << ssboFunction.typeString << " " << ssboFunction.functionName - << "(RWByteAddressBuffer buffer, uint loc)\n"; - out << "{\n"; - OutputSSBOLoadFunctionBody(out, ssboFunction); - break; - } - case SSBOMethod::STORE: - { - // Function header - out << "void " << ssboFunction.functionName - << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString - << " value)\n"; - out << "{\n"; - OutputSSBOStoreFunctionBody(out, ssboFunction); - break; - } - case SSBOMethod::LENGTH: - { - out << "int " << ssboFunction.functionName - << "(RWByteAddressBuffer buffer, uint loc)\n"; - out << "{\n"; - OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride); - break; - } - case SSBOMethod::ATOMIC_ADD: - case SSBOMethod::ATOMIC_MIN: - case SSBOMethod::ATOMIC_MAX: - case SSBOMethod::ATOMIC_AND: - case SSBOMethod::ATOMIC_OR: - case SSBOMethod::ATOMIC_XOR: - case SSBOMethod::ATOMIC_EXCHANGE: - { - out << ssboFunction.typeString << " " << ssboFunction.functionName - << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString - << " value)\n"; - out << "{\n"; - - OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction); - break; - } - case SSBOMethod::ATOMIC_COMPSWAP: - { - out << ssboFunction.typeString << " " << ssboFunction.functionName - << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString - << " compare_value, " << ssboFunction.typeString << " value)\n"; - out << "{\n"; - OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction); - break; - } - default: - UNREACHABLE(); - } - - out << "}\n" - "\n"; - } -} - -} // namespace sh diff --git a/src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.h b/src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.h deleted file mode 100644 index 89e3ead08fd..00000000000 --- a/src/compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright 2018 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. -// -// ShaderStorageBlockOutputHLSL: A traverser to translate a ssbo_access_chain to an offset of -// RWByteAddressBuffer. -// //EOpIndexDirectInterfaceBlock -// ssbo_variable := -// | the name of the SSBO -// | the name of a variable in an SSBO backed interface block - -// // EOpIndexInDirect -// // EOpIndexDirect -// ssbo_array_indexing := ssbo_access_chain[expr_no_ssbo] - -// // EOpIndexDirectStruct -// ssbo_structure_access := ssbo_access_chain.identifier - -// ssbo_access_chain := -// | ssbo_variable -// | ssbo_array_indexing -// | ssbo_structure_access -// - -#ifndef COMPILER_TRANSLATOR_HLSL_SHADERSTORAGEBLOCKFUNCTIONHLSL_H_ -#define COMPILER_TRANSLATOR_HLSL_SHADERSTORAGEBLOCKFUNCTIONHLSL_H_ - -#include - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/Types.h" - -namespace sh -{ - -class TIntermSwizzle; -enum class SSBOMethod -{ - LOAD, - STORE, - LENGTH, - ATOMIC_ADD, - ATOMIC_MIN, - ATOMIC_MAX, - ATOMIC_AND, - ATOMIC_OR, - ATOMIC_XOR, - ATOMIC_EXCHANGE, - ATOMIC_COMPSWAP -}; - -class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable -{ - public: - TString registerShaderStorageBlockFunction(const TType &type, - SSBOMethod method, - TLayoutBlockStorage storage, - bool rowMajor, - int matrixStride, - int unsizedArrayStride, - TIntermSwizzle *node); - - void shaderStorageBlockFunctionHeader(TInfoSinkBase &out); - - private: - struct ShaderStorageBlockFunction - { - bool operator<(const ShaderStorageBlockFunction &rhs) const; - TString functionName; - TString typeString; - SSBOMethod method; - TType type; - bool rowMajor; - int matrixStride; - int unsizedArrayStride; - TVector swizzleOffsets; - bool isDefaultSwizzle; - }; - - static void OutputSSBOLoadFunctionBody(TInfoSinkBase &out, - const ShaderStorageBlockFunction &ssboFunction); - static void OutputSSBOStoreFunctionBody(TInfoSinkBase &out, - const ShaderStorageBlockFunction &ssboFunction); - static void OutputSSBOLengthFunctionBody(TInfoSinkBase &out, int unsizedArrayStride); - static void OutputSSBOAtomicMemoryFunctionBody(TInfoSinkBase &out, - const ShaderStorageBlockFunction &ssboFunction); - using ShaderStorageBlockFunctionSet = std::set; - ShaderStorageBlockFunctionSet mRegisteredShaderStorageBlockFunctions; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_HLSL_SHADERSTORAGEBLOCKFUNCTIONHLSL_H_ diff --git a/src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.cpp b/src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.cpp deleted file mode 100644 index b3ce5dbc850..00000000000 --- a/src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.cpp +++ /dev/null @@ -1,668 +0,0 @@ -// -// Copyright 2018 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. -// -// ShaderStorageBlockOutputHLSL: A traverser to translate a ssbo_access_chain to an offset of -// RWByteAddressBuffer. -// //EOpIndexDirectInterfaceBlock -// ssbo_variable := -// | the name of the SSBO -// | the name of a variable in an SSBO backed interface block - -// // EOpIndexInDirect -// // EOpIndexDirect -// ssbo_array_indexing := ssbo_access_chain[expr_no_ssbo] - -// // EOpIndexDirectStruct -// ssbo_structure_access := ssbo_access_chain.identifier - -// ssbo_access_chain := -// | ssbo_variable -// | ssbo_array_indexing -// | ssbo_structure_access -// - -#include "compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.h" - -#include "common/span.h" -#include "compiler/translator/hlsl/ResourcesHLSL.h" -#include "compiler/translator/hlsl/blocklayoutHLSL.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -constexpr const char kShaderStorageDeclarationString[] = - "// @@ SHADER STORAGE DECLARATION STRING @@"; - -void GetBlockLayoutInfo(TIntermTyped *node, - bool rowMajorAlreadyAssigned, - TLayoutBlockStorage *storage, - bool *rowMajor) -{ - TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); - if (swizzleNode) - { - return GetBlockLayoutInfo(swizzleNode->getOperand(), rowMajorAlreadyAssigned, storage, - rowMajor); - } - - TIntermBinary *binaryNode = node->getAsBinaryNode(); - if (binaryNode) - { - switch (binaryNode->getOp()) - { - case EOpIndexDirectInterfaceBlock: - { - // The column_major/row_major qualifier of a field member overrides the interface - // block's row_major/column_major. So we can assign rowMajor here and don't need to - // assign it again. But we still need to call recursively to get the storage's - // value. - const TType &type = node->getType(); - *rowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor; - return GetBlockLayoutInfo(binaryNode->getLeft(), true, storage, rowMajor); - } - case EOpIndexIndirect: - case EOpIndexDirect: - case EOpIndexDirectStruct: - return GetBlockLayoutInfo(binaryNode->getLeft(), rowMajorAlreadyAssigned, storage, - rowMajor); - default: - UNREACHABLE(); - return; - } - } - - const TType &type = node->getType(); - ASSERT(type.getQualifier() == EvqBuffer); - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - ASSERT(interfaceBlock); - *storage = interfaceBlock->blockStorage(); - // If the block doesn't have an instance name, rowMajorAlreadyAssigned will be false. In - // this situation, we still need to set rowMajor's value. - if (!rowMajorAlreadyAssigned) - { - *rowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor; - } -} - -// It's possible that the current type has lost the original layout information. So we should pass -// the right layout information to GetBlockMemberInfoByType. -const BlockMemberInfo GetBlockMemberInfoByType(const TType &type, - TLayoutBlockStorage storage, - bool rowMajor) -{ - sh::Std140BlockEncoder std140Encoder; - sh::Std430BlockEncoder std430Encoder; - sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false); - sh::BlockLayoutEncoder *encoder = nullptr; - - if (storage == EbsStd140) - { - encoder = &std140Encoder; - } - else if (storage == EbsStd430) - { - encoder = &std430Encoder; - } - else - { - encoder = &hlslEncoder; - } - - std::vector arraySizes; - const angle::Span &typeArraySizes = type.getArraySizes(); - if (!typeArraySizes.empty()) - { - arraySizes.assign(typeArraySizes.begin(), typeArraySizes.end()); - } - return encoder->encodeType(GLVariableType(type), arraySizes, rowMajor); -} - -const TField *GetFieldMemberInShaderStorageBlock(const TInterfaceBlock *interfaceBlock, - const ImmutableString &variableName) -{ - for (const TField *field : interfaceBlock->fields()) - { - if (field->name() == variableName) - { - return field; - } - } - return nullptr; -} - -const InterfaceBlock *FindInterfaceBlock(const TInterfaceBlock *needle, - const std::vector &haystack) -{ - for (const InterfaceBlock &block : haystack) - { - if (strcmp(block.name.c_str(), needle->name().data()) == 0) - { - ASSERT(block.fields.size() == needle->fields().size()); - return █ - } - } - - UNREACHABLE(); - return nullptr; -} - -std::string StripArrayIndices(const std::string &nameIn) -{ - std::string name = nameIn; - size_t pos = name.find('['); - while (pos != std::string::npos) - { - size_t closePos = name.find(']', pos); - ASSERT(closePos != std::string::npos); - name.erase(pos, closePos - pos + 1); - pos = name.find('[', pos); - } - ASSERT(name.find(']') == std::string::npos); - return name; -} - -// Does not include any array indices. -void MapVariableToField(const ShaderVariable &variable, - const TField *field, - std::string currentName, - ShaderVarToFieldMap *shaderVarToFieldMap) -{ - ASSERT((field->type()->getStruct() == nullptr) == variable.fields.empty()); - (*shaderVarToFieldMap)[currentName] = field; - - if (!variable.fields.empty()) - { - const TStructure *subStruct = field->type()->getStruct(); - ASSERT(variable.fields.size() == subStruct->fields().size()); - - for (size_t index = 0; index < variable.fields.size(); ++index) - { - const TField *subField = subStruct->fields()[index]; - const ShaderVariable &subVariable = variable.fields[index]; - std::string subName = currentName + "." + subVariable.name; - MapVariableToField(subVariable, subField, subName, shaderVarToFieldMap); - } - } -} - -class BlockInfoVisitor final : public BlockEncoderVisitor -{ - public: - BlockInfoVisitor(const std::string &prefix, - TLayoutBlockStorage storage, - const ShaderVarToFieldMap &shaderVarToFieldMap, - BlockMemberInfoMap *blockInfoOut) - : BlockEncoderVisitor(prefix, "", getEncoder(storage)), - mShaderVarToFieldMap(shaderVarToFieldMap), - mBlockInfoOut(blockInfoOut), - mHLSLEncoder(HLSLBlockEncoder::ENCODE_PACKED, false), - mStorage(storage) - {} - - BlockLayoutEncoder *getEncoder(TLayoutBlockStorage storage) - { - switch (storage) - { - case EbsStd140: - return &mStd140Encoder; - case EbsStd430: - return &mStd430Encoder; - default: - return &mHLSLEncoder; - } - } - - void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override - { - BlockEncoderVisitor::enterStructAccess(structVar, isRowMajor); - - std::string variableName = StripArrayIndices(collapseNameStack()); - - // Remove the trailing "." - variableName.pop_back(); - - BlockInfoVisitor childVisitor(variableName, mStorage, mShaderVarToFieldMap, mBlockInfoOut); - childVisitor.getEncoder(mStorage)->enterAggregateType(structVar); - TraverseShaderVariables(structVar.fields, isRowMajor, &childVisitor); - childVisitor.getEncoder(mStorage)->exitAggregateType(structVar); - - int offset = static_cast(getEncoder(mStorage)->getCurrentOffset()); - int arrayStride = static_cast(childVisitor.getEncoder(mStorage)->getCurrentOffset()); - - auto iter = mShaderVarToFieldMap.find(variableName); - if (iter == mShaderVarToFieldMap.end()) - return; - - const TField *structField = iter->second; - if (mBlockInfoOut->count(structField) == 0) - { - mBlockInfoOut->emplace(structField, BlockMemberInfo(offset, arrayStride, -1, false)); - } - } - - void encodeVariable(const ShaderVariable &variable, - const BlockMemberInfo &variableInfo, - const std::string &name, - const std::string &mappedName) override - { - auto iter = mShaderVarToFieldMap.find(StripArrayIndices(name)); - if (iter == mShaderVarToFieldMap.end()) - return; - - const TField *field = iter->second; - if (mBlockInfoOut->count(field) == 0) - { - mBlockInfoOut->emplace(field, variableInfo); - } - } - - private: - const ShaderVarToFieldMap &mShaderVarToFieldMap; - BlockMemberInfoMap *mBlockInfoOut; - Std140BlockEncoder mStd140Encoder; - Std430BlockEncoder mStd430Encoder; - HLSLBlockEncoder mHLSLEncoder; - TLayoutBlockStorage mStorage; -}; - -void GetShaderStorageBlockMembersInfo(const TInterfaceBlock *interfaceBlock, - const std::vector &shaderStorageBlocks, - BlockMemberInfoMap *blockInfoOut) -{ - // Find the sh::InterfaceBlock. - const InterfaceBlock *block = FindInterfaceBlock(interfaceBlock, shaderStorageBlocks); - ASSERT(block); - - // Map ShaderVariable to TField. - ShaderVarToFieldMap shaderVarToFieldMap; - for (size_t index = 0; index < block->fields.size(); ++index) - { - const TField *field = interfaceBlock->fields()[index]; - const ShaderVariable &variable = block->fields[index]; - MapVariableToField(variable, field, variable.name, &shaderVarToFieldMap); - } - - BlockInfoVisitor visitor("", interfaceBlock->blockStorage(), shaderVarToFieldMap, blockInfoOut); - TraverseShaderVariables(block->fields, false, &visitor); -} - -TIntermTyped *Mul(TIntermTyped *left, TIntermTyped *right) -{ - return left && right ? new TIntermBinary(EOpMul, left, right) : nullptr; -} - -TIntermTyped *Add(TIntermTyped *left, TIntermTyped *right) -{ - return left ? right ? new TIntermBinary(EOpAdd, left, right) : left : right; -} - -} // anonymous namespace - -ShaderStorageBlockOutputHLSL::ShaderStorageBlockOutputHLSL( - OutputHLSL *outputHLSL, - ResourcesHLSL *resourcesHLSL, - const std::vector &shaderStorageBlocks) - : mOutputHLSL(outputHLSL), - mResourcesHLSL(resourcesHLSL), - mShaderStorageBlocks(shaderStorageBlocks) -{ - mSSBOFunctionHLSL = new ShaderStorageBlockFunctionHLSL; -} - -ShaderStorageBlockOutputHLSL::~ShaderStorageBlockOutputHLSL() -{ - SafeDelete(mSSBOFunctionHLSL); -} - -void ShaderStorageBlockOutputHLSL::outputStoreFunctionCallPrefix(TIntermTyped *node) -{ - traverseSSBOAccess(node, SSBOMethod::STORE); -} - -void ShaderStorageBlockOutputHLSL::outputLoadFunctionCall(TIntermTyped *node) -{ - traverseSSBOAccess(node, SSBOMethod::LOAD); - mOutputHLSL->getInfoSink() << ")"; -} - -void ShaderStorageBlockOutputHLSL::outputLengthFunctionCall(TIntermTyped *node) -{ - traverseSSBOAccess(node, SSBOMethod::LENGTH); - mOutputHLSL->getInfoSink() << ")"; -} - -void ShaderStorageBlockOutputHLSL::outputAtomicMemoryFunctionCallPrefix(TIntermTyped *node, - TOperator op) -{ - switch (op) - { - case EOpAtomicAdd: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_ADD); - break; - case EOpAtomicMin: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_MIN); - break; - case EOpAtomicMax: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_MAX); - break; - case EOpAtomicAnd: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_AND); - break; - case EOpAtomicOr: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_OR); - break; - case EOpAtomicXor: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_XOR); - break; - case EOpAtomicExchange: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_EXCHANGE); - break; - case EOpAtomicCompSwap: - traverseSSBOAccess(node, SSBOMethod::ATOMIC_COMPSWAP); - break; - default: - UNREACHABLE(); - break; - } -} - -// Note that we must calculate the matrix stride here instead of ShaderStorageBlockFunctionHLSL. -// It's because that if the current node's type is a vector which comes from a matrix, we will -// lose the matrix type info once we enter ShaderStorageBlockFunctionHLSL. -int ShaderStorageBlockOutputHLSL::getMatrixStride(TIntermTyped *node, - TLayoutBlockStorage storage, - bool rowMajor, - bool *isRowMajorMatrix) const -{ - if (node->getType().isMatrix()) - { - *isRowMajorMatrix = rowMajor; - return GetBlockMemberInfoByType(node->getType(), storage, rowMajor).matrixStride; - } - - if (node->getType().isVector()) - { - TIntermBinary *binaryNode = node->getAsBinaryNode(); - if (binaryNode) - { - return getMatrixStride(binaryNode->getLeft(), storage, rowMajor, isRowMajorMatrix); - } - else - { - TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); - if (swizzleNode) - { - return getMatrixStride(swizzleNode->getOperand(), storage, rowMajor, - isRowMajorMatrix); - } - } - } - return 0; -} - -void ShaderStorageBlockOutputHLSL::collectShaderStorageBlocks(TIntermTyped *node) -{ - TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); - if (swizzleNode) - { - return collectShaderStorageBlocks(swizzleNode->getOperand()); - } - - TIntermBinary *binaryNode = node->getAsBinaryNode(); - if (binaryNode) - { - switch (binaryNode->getOp()) - { - case EOpIndexDirectInterfaceBlock: - case EOpIndexIndirect: - case EOpIndexDirect: - case EOpIndexDirectStruct: - return collectShaderStorageBlocks(binaryNode->getLeft()); - default: - UNREACHABLE(); - return; - } - } - - const TIntermSymbol *symbolNode = node->getAsSymbolNode(); - const TType &type = symbolNode->getType(); - ASSERT(type.getQualifier() == EvqBuffer); - const TVariable &variable = symbolNode->variable(); - - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - ASSERT(interfaceBlock); - if (mReferencedShaderStorageBlocks.count(interfaceBlock->uniqueId().get()) == 0) - { - const TVariable *instanceVariable = nullptr; - if (type.isInterfaceBlock()) - { - instanceVariable = &variable; - } - mReferencedShaderStorageBlocks[interfaceBlock->uniqueId().get()] = - new TReferencedBlock(interfaceBlock, instanceVariable); - GetShaderStorageBlockMembersInfo(interfaceBlock, mShaderStorageBlocks, - &mBlockMemberInfoMap); - } -} - -void ShaderStorageBlockOutputHLSL::traverseSSBOAccess(TIntermTyped *node, SSBOMethod method) -{ - // TODO: Merge collectShaderStorageBlocks and GetBlockLayoutInfo to simplify the code. - collectShaderStorageBlocks(node); - - // Note that we don't have correct BlockMemberInfo from mBlockMemberInfoMap at the current - // point. But we must use those information to generate the right function name. So here we have - // to calculate them again. - TLayoutBlockStorage storage; - bool rowMajor; - GetBlockLayoutInfo(node, false, &storage, &rowMajor); - int unsizedArrayStride = 0; - if (node->getType().isUnsizedArray()) - { - // The unsized array member must be the last member of a shader storage block. - TIntermBinary *binaryNode = node->getAsBinaryNode(); - if (binaryNode) - { - const TInterfaceBlock *interfaceBlock = - binaryNode->getLeft()->getType().getInterfaceBlock(); - ASSERT(interfaceBlock); - const TIntermConstantUnion *index = binaryNode->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - auto fieldInfoIter = mBlockMemberInfoMap.find(field); - ASSERT(fieldInfoIter != mBlockMemberInfoMap.end()); - unsizedArrayStride = fieldInfoIter->second.arrayStride; - } - else - { - const TIntermSymbol *symbolNode = node->getAsSymbolNode(); - const TVariable &variable = symbolNode->variable(); - const TInterfaceBlock *interfaceBlock = symbolNode->getType().getInterfaceBlock(); - ASSERT(interfaceBlock); - const TField *field = - GetFieldMemberInShaderStorageBlock(interfaceBlock, variable.name()); - auto fieldInfoIter = mBlockMemberInfoMap.find(field); - ASSERT(fieldInfoIter != mBlockMemberInfoMap.end()); - unsizedArrayStride = fieldInfoIter->second.arrayStride; - } - } - bool isRowMajorMatrix = false; - int matrixStride = getMatrixStride(node, storage, rowMajor, &isRowMajorMatrix); - - const TString &functionName = mSSBOFunctionHLSL->registerShaderStorageBlockFunction( - node->getType(), method, storage, isRowMajorMatrix, matrixStride, unsizedArrayStride, - node->getAsSwizzleNode()); - TInfoSinkBase &out = mOutputHLSL->getInfoSink(); - out << functionName; - out << "("; - BlockMemberInfo blockMemberInfo; - TIntermNode *loc = traverseNode(out, node, &blockMemberInfo); - out << ", "; - loc->traverse(mOutputHLSL); -} - -void ShaderStorageBlockOutputHLSL::writeShaderStorageBlocksHeader(GLenum shaderType, - TInfoSinkBase &out) const -{ - if (mReferencedShaderStorageBlocks.empty()) - { - return; - } - - mResourcesHLSL->allocateShaderStorageBlockRegisters(mReferencedShaderStorageBlocks); - out << "// Shader Storage Blocks\n\n"; - if (shaderType == GL_COMPUTE_SHADER) - { - out << mResourcesHLSL->shaderStorageBlocksHeader(mReferencedShaderStorageBlocks); - } - else - { - out << kShaderStorageDeclarationString << "\n"; - } - mSSBOFunctionHLSL->shaderStorageBlockFunctionHeader(out); -} - -TIntermTyped *ShaderStorageBlockOutputHLSL::traverseNode(TInfoSinkBase &out, - TIntermTyped *node, - BlockMemberInfo *blockMemberInfo) -{ - if (TIntermSymbol *symbolNode = node->getAsSymbolNode()) - { - const TVariable &variable = symbolNode->variable(); - const TType &type = variable.getType(); - if (type.isInterfaceBlock()) - { - out << DecorateVariableIfNeeded(variable); - } - else - { - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - out << Decorate(interfaceBlock->name()); - const TField *field = - GetFieldMemberInShaderStorageBlock(interfaceBlock, variable.name()); - return createFieldOffset(field, blockMemberInfo); - } - } - else if (TIntermSwizzle *swizzleNode = node->getAsSwizzleNode()) - { - return traverseNode(out, swizzleNode->getOperand(), blockMemberInfo); - } - else if (TIntermBinary *binaryNode = node->getAsBinaryNode()) - { - switch (binaryNode->getOp()) - { - case EOpIndexDirect: - { - const TType &leftType = binaryNode->getLeft()->getType(); - if (leftType.isInterfaceBlock()) - { - ASSERT(leftType.getQualifier() == EvqBuffer); - TIntermSymbol *instanceArraySymbol = binaryNode->getLeft()->getAsSymbolNode(); - - const int arrayIndex = - binaryNode->getRight()->getAsConstantUnion()->getIConst(0); - out << mResourcesHLSL->InterfaceBlockInstanceString( - instanceArraySymbol->getName(), arrayIndex); - } - else - { - return writeEOpIndexDirectOrIndirectOutput(out, binaryNode, blockMemberInfo); - } - break; - } - case EOpIndexIndirect: - { - // We do not currently support indirect references to interface blocks - ASSERT(binaryNode->getLeft()->getBasicType() != EbtInterfaceBlock); - return writeEOpIndexDirectOrIndirectOutput(out, binaryNode, blockMemberInfo); - } - case EOpIndexDirectStruct: - { - // We do not currently support direct references to interface blocks - ASSERT(binaryNode->getLeft()->getBasicType() != EbtInterfaceBlock); - TIntermTyped *left = traverseNode(out, binaryNode->getLeft(), blockMemberInfo); - const TStructure *structure = binaryNode->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = binaryNode->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - return Add(createFieldOffset(field, blockMemberInfo), left); - } - case EOpIndexDirectInterfaceBlock: - { - ASSERT(IsInShaderStorageBlock(binaryNode->getLeft())); - traverseNode(out, binaryNode->getLeft(), blockMemberInfo); - const TInterfaceBlock *interfaceBlock = - binaryNode->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = binaryNode->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - return createFieldOffset(field, blockMemberInfo); - } - default: - return nullptr; - } - } - return nullptr; -} - -TIntermTyped *ShaderStorageBlockOutputHLSL::writeEOpIndexDirectOrIndirectOutput( - TInfoSinkBase &out, - TIntermBinary *node, - BlockMemberInfo *blockMemberInfo) -{ - ASSERT(IsInShaderStorageBlock(node->getLeft())); - TIntermTyped *left = traverseNode(out, node->getLeft(), blockMemberInfo); - TIntermTyped *right = node->getRight()->deepCopy(); - const TType &type = node->getLeft()->getType(); - TLayoutBlockStorage storage; - bool rowMajor; - GetBlockLayoutInfo(node, false, &storage, &rowMajor); - - if (type.isArray()) - { - const angle::Span &arraySizes = type.getArraySizes(); - for (unsigned int i = 0; i < arraySizes.size() - 1; i++) - { - right = Mul(CreateUIntNode(arraySizes[i]), right); - } - right = Mul(CreateUIntNode(blockMemberInfo->arrayStride), right); - } - else if (type.isMatrix()) - { - if (rowMajor) - { - right = Mul(CreateUIntNode(BlockLayoutEncoder::kBytesPerComponent), right); - } - else - { - right = Mul(CreateUIntNode(blockMemberInfo->matrixStride), right); - } - } - else if (type.isVector()) - { - if (blockMemberInfo->isRowMajorMatrix) - { - right = Mul(CreateUIntNode(blockMemberInfo->matrixStride), right); - } - else - { - right = Mul(CreateUIntNode(BlockLayoutEncoder::kBytesPerComponent), right); - } - } - return Add(left, right); -} - -TIntermTyped *ShaderStorageBlockOutputHLSL::createFieldOffset(const TField *field, - BlockMemberInfo *blockMemberInfo) -{ - auto fieldInfoIter = mBlockMemberInfoMap.find(field); - ASSERT(fieldInfoIter != mBlockMemberInfoMap.end()); - *blockMemberInfo = fieldInfoIter->second; - return CreateUIntNode(blockMemberInfo->offset); -} - -} // namespace sh diff --git a/src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.h b/src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.h deleted file mode 100644 index 1549296426e..00000000000 --- a/src/compiler/translator/hlsl/ShaderStorageBlockOutputHLSL.h +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright 2018 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. -// -// ShaderStorageBlockOutputHLSL: A traverser to translate a buffer variable of shader storage block -// to an offset of RWByteAddressBuffer. -// - -#ifndef COMPILER_TRANSLATOR_HLSL_SHADERSTORAGEBLOCKOUTPUTHLSL_H_ -#define COMPILER_TRANSLATOR_HLSL_SHADERSTORAGEBLOCKOUTPUTHLSL_H_ - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/blocklayout.h" -#include "compiler/translator/hlsl/ShaderStorageBlockFunctionHLSL.h" - -namespace sh -{ -class ResourcesHLSL; -class OutputHLSL; -class TSymbolTable; - -struct TReferencedBlock : angle::NonCopyable -{ - POOL_ALLOCATOR_NEW_DELETE - TReferencedBlock(const TInterfaceBlock *block, const TVariable *instanceVariable); - const TInterfaceBlock *block; - const TVariable *instanceVariable; // May be nullptr if the block is not instanced. -}; - -// Maps from uniqueId to a variable. -using ReferencedInterfaceBlocks = std::map; - -// Used to save shader storage block field member information. -using BlockMemberInfoMap = std::map; - -using ShaderVarToFieldMap = std::map; - -class ShaderStorageBlockOutputHLSL -{ - public: - ShaderStorageBlockOutputHLSL(OutputHLSL *outputHLSL, - ResourcesHLSL *resourcesHLSL, - const std::vector &shaderStorageBlocks); - - ~ShaderStorageBlockOutputHLSL(); - - // This writes part of the function call to store a value to a SSBO to the output stream. After - // calling this, ", )" should be written to the output stream to complete the - // function call. - void outputStoreFunctionCallPrefix(TIntermTyped *node); - // This writes the function call to load a SSBO value to the output stream. - void outputLoadFunctionCall(TIntermTyped *node); - // This writes the function call to get the lengh of unsized array member of SSBO. - void outputLengthFunctionCall(TIntermTyped *node); - // Writes the atomic memory function calls for SSBO. - void outputAtomicMemoryFunctionCallPrefix(TIntermTyped *node, TOperator op); - - void writeShaderStorageBlocksHeader(GLenum shaderType, TInfoSinkBase &out) const; - - private: - void traverseSSBOAccess(TIntermTyped *node, SSBOMethod method); - TIntermTyped *traverseNode(TInfoSinkBase &out, - TIntermTyped *node, - BlockMemberInfo *blockMemberInfo); - int getMatrixStride(TIntermTyped *node, - TLayoutBlockStorage storage, - bool rowMajor, - bool *isRowMajor) const; - TIntermTyped *writeEOpIndexDirectOrIndirectOutput(TInfoSinkBase &out, - TIntermBinary *node, - BlockMemberInfo *blockMemberInfo); - // Common part in dot operations. - TIntermTyped *createFieldOffset(const TField *field, BlockMemberInfo *blockMemberInfo); - void collectShaderStorageBlocks(TIntermTyped *node); - OutputHLSL *mOutputHLSL; - ShaderStorageBlockFunctionHLSL *mSSBOFunctionHLSL; - ResourcesHLSL *mResourcesHLSL; - ReferencedInterfaceBlocks mReferencedShaderStorageBlocks; - - BlockMemberInfoMap mBlockMemberInfoMap; - const std::vector &mShaderStorageBlocks; -}; -} // namespace sh - -#endif // COMPILER_TRANSLATOR_HLSL_SHADERSTORAGEBLOCKOUTPUTHLSL_H_ diff --git a/src/compiler/translator/hlsl/TextureFunctionHLSL.cpp b/src/compiler/translator/hlsl/TextureFunctionHLSL.cpp index 22121b28bda..f704344cc79 100644 --- a/src/compiler/translator/hlsl/TextureFunctionHLSL.cpp +++ b/src/compiler/translator/hlsl/TextureFunctionHLSL.cpp @@ -9,6 +9,10 @@ // behavior. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/hlsl/TextureFunctionHLSL.h" #include "compiler/translator/ImmutableStringBuilder.h" @@ -1534,7 +1538,7 @@ ImmutableString TextureFunctionHLSL::useTextureFunction(const ImmutableString &n bool bias = (argumentCount > mandatoryArgumentCount); // Bias argument is optional - if (lod0 || shaderType == GL_VERTEX_SHADER || shaderType == GL_COMPUTE_SHADER) + if (lod0 || shaderType == GL_VERTEX_SHADER) { if (bias) { diff --git a/src/compiler/translator/hlsl/TranslatorHLSL.cpp b/src/compiler/translator/hlsl/TranslatorHLSL.cpp index e2ae665fb17..9a061cce41c 100644 --- a/src/compiler/translator/hlsl/TranslatorHLSL.cpp +++ b/src/compiler/translator/hlsl/TranslatorHLSL.cpp @@ -12,15 +12,11 @@ #include "compiler/translator/tree_ops/SimplifyLoopConditions.h" #include "compiler/translator/tree_ops/SplitSequenceOperator.h" #include "compiler/translator/tree_ops/hlsl/AddDefaultReturnStatements.h" -#include "compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h" -#include "compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.h" #include "compiler/translator/tree_ops/hlsl/ArrayReturnValueToOutParameter.h" #include "compiler/translator/tree_ops/hlsl/BreakVariableAliasingInInnerLoops.h" #include "compiler/translator/tree_ops/hlsl/ExpandIntegerPowExpressions.h" #include "compiler/translator/tree_ops/hlsl/RecordUniformBlocksWithLargeArrayMember.h" -#include "compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.h" #include "compiler/translator/tree_ops/hlsl/RewriteElseBlocks.h" -#include "compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.h" #include "compiler/translator/tree_ops/hlsl/RewriteUnaryMinusOperatorInt.h" #include "compiler/translator/tree_ops/hlsl/SeparateArrayConstructorStatements.h" #include "compiler/translator/tree_ops/hlsl/SeparateArrayInitialization.h" @@ -49,7 +45,7 @@ bool TranslatorHLSL::translate(TIntermBlock *root, // the return value of the function is not propagated to its return expressions. Additionally, // an expression such as // - // cond ? gl_NumWorkGroups.x : gl_NumWorkGroups.y + // cond ? gl_.x : gl_.y // // does not have a precision as the built-in does not specify a precision. // @@ -100,24 +96,6 @@ bool TranslatorHLSL::translate(TIntermBlock *root, return false; } - if (getShaderVersion() >= 310) - { - // Do element-by-element assignments of arrays in SSBOs. This allows the D3D backend to use - // RWByteAddressBuffer.Load() and .Store(), which only operate on values up to 16 bytes in - // size. Note that this must be done before SeparateExpressionsReturningArrays. - if (!sh::AggregateAssignArraysInSSBOs(this, root, &getSymbolTable())) - { - return false; - } - // Do field-by-field assignment of structs in SSBOs. This allows the D3D backend to use - // RWByteAddressBuffer.Load() and .Store(), which only operate on values up to 16 bytes in - // size. - if (!sh::AggregateAssignStructsInSSBOs(this, root, &getSymbolTable())) - { - return false; - } - } - if (!SeparateExpressionsReturningArrays(this, root, &getSymbolTable())) { return false; @@ -198,21 +176,6 @@ bool TranslatorHLSL::translate(TIntermBlock *root, } } - if (getShaderVersion() >= 310) - { - // Due to ssbo also can be used as the argument of atomic memory functions, we should put - // RewriteExpressionsWithShaderStorageBlock before RewriteAtomicFunctionExpressions. - if (!sh::RewriteExpressionsWithShaderStorageBlock(this, root, &getSymbolTable())) - { - return false; - } - if (!sh::RewriteAtomicFunctionExpressions(this, root, &getSymbolTable(), - getShaderVersion())) - { - return false; - } - } - mUniformBlockOptimizedMap.clear(); mSlowCompilingUniformBlockSet.clear(); // In order to get the exact maximum of slots are available for shader resources, which would @@ -230,13 +193,11 @@ bool TranslatorHLSL::translate(TIntermBlock *root, sh::OutputHLSL outputHLSL( getShaderType(), getShaderSpec(), getShaderVersion(), getExtensionBehavior(), getSourcePath(), getOutputType(), numRenderTargets, maxDualSourceDrawBuffers, getUniforms(), - compileOptions, getComputeShaderLocalSize(), &getSymbolTable(), perfDiagnostics, - mUniformBlockOptimizedMap, mShaderStorageBlocks, getClipDistanceArraySize(), - getCullDistanceArraySize(), isEarlyFragmentTestsSpecified()); + compileOptions, &getSymbolTable(), perfDiagnostics, mUniformBlockOptimizedMap, + getClipDistanceArraySize(), getCullDistanceArraySize(), isEarlyFragmentTestsSpecified()); outputHLSL.output(root, getInfoSink().obj); - mShaderStorageBlockRegisterMap = outputHLSL.getShaderStorageBlockRegisterMap(); mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap(); mUniformBlockUseStructuredBufferMap = outputHLSL.getUniformBlockUseStructuredBufferMap(); mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); @@ -253,18 +214,6 @@ bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll() return false; } -bool TranslatorHLSL::hasShaderStorageBlock(const std::string &uniformBlockName) const -{ - return (mShaderStorageBlockRegisterMap.count(uniformBlockName) > 0); -} - -unsigned int TranslatorHLSL::getShaderStorageBlockRegister( - const std::string &shaderStorageBlockName) const -{ - ASSERT(hasShaderStorageBlock(shaderStorageBlockName)); - return mShaderStorageBlockRegisterMap.find(shaderStorageBlockName)->second; -} - bool TranslatorHLSL::hasUniformBlock(const std::string &uniformBlockName) const { return (mUniformBlockRegisterMap.count(uniformBlockName) > 0); diff --git a/src/compiler/translator/hlsl/TranslatorHLSL.h b/src/compiler/translator/hlsl/TranslatorHLSL.h index 8e53eb231b1..69dfc4ac2fe 100644 --- a/src/compiler/translator/hlsl/TranslatorHLSL.h +++ b/src/compiler/translator/hlsl/TranslatorHLSL.h @@ -18,9 +18,6 @@ class TranslatorHLSL : public TCompiler TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); TranslatorHLSL *getAsTranslatorHLSL() override { return this; } - bool hasShaderStorageBlock(const std::string &interfaceBlockName) const; - unsigned int getShaderStorageBlockRegister(const std::string &interfaceBlockName) const; - bool hasUniformBlock(const std::string &interfaceBlockName) const; unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const; bool shouldUniformBlockUseStructuredBuffer(const std::string &uniformBlockName) const; @@ -37,7 +34,6 @@ class TranslatorHLSL : public TCompiler PerformanceDiagnostics *perfDiagnostics) override; bool shouldFlattenPragmaStdglInvariantAll() override; - std::map mShaderStorageBlockRegisterMap; std::map mUniformBlockRegisterMap; std::map mUniformBlockUseStructuredBufferMap; std::map mUniformRegisterMap; diff --git a/src/compiler/translator/hlsl/UtilsHLSL.cpp b/src/compiler/translator/hlsl/UtilsHLSL.cpp index bf0e365e000..53912e57eb1 100644 --- a/src/compiler/translator/hlsl/UtilsHLSL.cpp +++ b/src/compiler/translator/hlsl/UtilsHLSL.cpp @@ -282,51 +282,6 @@ HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat return HLSL_TEXTURE_UNKNOWN; } } - case EbtImageBuffer: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_BUFFER; - case EiifRGBA8: - return HLSL_TEXTURE_BUFFER_UNORM; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_BUFFER_SNORM; - default: - UNREACHABLE(); - return HLSL_TEXTURE_UNKNOWN; - } - } - case EbtUImageBuffer: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_BUFFER_UINT4; - default: - UNREACHABLE(); - return HLSL_TEXTURE_UNKNOWN; - } - } - case EbtIImageBuffer: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_BUFFER_INT4; - default: - UNREACHABLE(); - return HLSL_TEXTURE_UNKNOWN; - } - } default: UNREACHABLE(); return HLSL_TEXTURE_UNKNOWN; @@ -702,51 +657,6 @@ HLSLRWTextureGroup RWTextureGroup(const TBasicType type, } break; } - case EbtImageBuffer: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_BUFFER_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_BUFFER_UNORM; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_BUFFER_SNORM; - default: - UNREACHABLE(); - } - break; - } - case EbtIImageBuffer: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_BUFFER_INT4; - default: - UNREACHABLE(); - } - break; - } - case EbtUImageBuffer: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_BUFFER_UINT4; - default: - UNREACHABLE(); - } - break; - } default: UNREACHABLE(); } @@ -787,16 +697,6 @@ const char *RWTextureString(const HLSLRWTextureGroup RWTextureGroup) return "RWTexture2DArray"; case HLSL_RWTEXTURE_3D_INT4: return "RWTexture3D"; - case HLSL_RWTEXTURE_BUFFER_FLOAT4: - return "RWBuffer"; - case HLSL_RWTEXTURE_BUFFER_UNORM: - return "RWBuffer"; - case HLSL_RWTEXTURE_BUFFER_SNORM: - return "RWBuffer"; - case HLSL_RWTEXTURE_BUFFER_UINT4: - return "RWBuffer"; - case HLSL_RWTEXTURE_BUFFER_INT4: - return "RWBuffer"; default: UNREACHABLE(); } @@ -843,16 +743,6 @@ const char *RWTextureGroupSuffix(const HLSLRWTextureGroup type) return "RW2DArray_int4_"; case HLSL_RWTEXTURE_3D_INT4: return "RW3D_int4_"; - case HLSL_RWTEXTURE_BUFFER_FLOAT4: - return "RWBuffer_float4_"; - case HLSL_RWTEXTURE_BUFFER_UNORM: - return "RWBuffer_unorm_float4_"; - case HLSL_RWTEXTURE_BUFFER_SNORM: - return "RWBuffer_snorm_float4_"; - case HLSL_RWTEXTURE_BUFFER_UINT4: - return "RWBuffer_uint4_"; - case HLSL_RWTEXTURE_BUFFER_INT4: - return "RWBuffer_int4_"; default: UNREACHABLE(); } @@ -1079,9 +969,6 @@ TString TypeString(const TType &type) return "sampler2D"; case EbtSamplerVideoWEBGL: return "sampler2D"; - case EbtAtomicCounter: - // Multiple atomic_uints will be implemented as a single RWByteAddressBuffer - return "RWByteAddressBuffer"; default: break; } diff --git a/src/compiler/translator/hlsl/blocklayoutHLSL.cpp b/src/compiler/translator/hlsl/blocklayoutHLSL.cpp index dd2eb507c18..41905e89773 100644 --- a/src/compiler/translator/hlsl/blocklayoutHLSL.cpp +++ b/src/compiler/translator/hlsl/blocklayoutHLSL.cpp @@ -27,6 +27,7 @@ void HLSLBlockEncoder::enterAggregateType(const ShaderVariable &structVar) void HLSLBlockEncoder::exitAggregateType(const ShaderVariable &structVar) {} void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, @@ -76,6 +77,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, } void HLSLBlockEncoder::advanceOffset(GLenum typeIn, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, @@ -150,7 +152,8 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * else { // We operate only on varyings and uniforms, which do not have matrix layout qualifiers - encoder->encodeType(variable.type, variable.arraySizes, false); + encoder->encodeType(variable.type, BlockLayoutEncoder::kBytesPerComponent, + variable.arraySizes, false); } } diff --git a/src/compiler/translator/hlsl/blocklayoutHLSL.h b/src/compiler/translator/hlsl/blocklayoutHLSL.h index a6b4799cd2f..c9ddf832e24 100644 --- a/src/compiler/translator/hlsl/blocklayoutHLSL.h +++ b/src/compiler/translator/hlsl/blocklayoutHLSL.h @@ -45,11 +45,13 @@ class HLSLBlockEncoder : public BlockLayoutEncoder protected: void getBlockLayoutInfo(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override; void advanceOffset(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, diff --git a/src/compiler/translator/ir/.gitignore b/src/compiler/translator/ir/.gitignore new file mode 100644 index 00000000000..2f7896d1d13 --- /dev/null +++ b/src/compiler/translator/ir/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/src/compiler/translator/ir/BUILD.gn b/src/compiler/translator/ir/BUILD.gn new file mode 100644 index 00000000000..396924fe306 --- /dev/null +++ b/src/compiler/translator/ir/BUILD.gn @@ -0,0 +1,57 @@ +# 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. + +import("../../../../gni/angle.gni") +if (angle_has_build) { + import("//build/rust/rust_static_library.gni") +} + +angle_translator_ir_sources = [ + "src/ast.rs", + "src/builder.rs", + "src/compile.rs", + "src/debug.rs", + "src/instruction.rs", + "src/ir.rs", + "src/lib.rs", + "src/output.rs", + "src/output/glsl.rs", + "src/output/legacy.rs", + "src/transform.rs", + "src/transform/astify.rs", + "src/transform/dealias.rs", + "src/transform/initialize_uninitialized_variables.rs", + "src/transform/propagate_precision.rs", + "src/transform/prune_unused_variables.rs", + "src/transform/remove_unused_framebuffer_fetch.rs", + "src/traverser.rs", + "src/util.rs", + "src/validator.rs", +] + +if (angle_ir) { + config("gen_src_include") { + include_dirs = [ + "$root_gen_dir/src", + "$root_gen_dir/third_party/angle/src", + ] + } + + rust_static_library("translator_ir") { + # Need unsafe because of FFI + allow_unsafe = true + + sources = angle_translator_ir_sources + cxx_bindings = [ + "src/builder.rs", + "src/compile.rs", + "src/output/legacy.rs", + ] + + configs += [ + "$angle_root:internal_config", + ":gen_src_include", + ] + } +} diff --git a/src/compiler/translator/ir/doc/README.md b/src/compiler/translator/ir/doc/README.md new file mode 100644 index 00000000000..935c1f712ec --- /dev/null +++ b/src/compiler/translator/ir/doc/README.md @@ -0,0 +1,848 @@ +# ANGLE IR + +## Background + +The ANGLE translator was originally based on an old fork of glslang. +While it has diverged significantly from that project, the core AST (Abstract Syntax Tree) design of +glslang has remained in the ANGLE translator. +In time, ANGLE has accumulated numerous AST transformations, which have gotten more complex over +time as more and more corner case bugs were discovered by users, security researchers and fuzzers. +The ANGLE IR was created to step away from this situation by providing a more easily malleable +intermediate representation of the input GLSL. + +Currently, the ANGLE IR is experimental, and conditional to a build option (`angle_ir=true`). +It is created during parse, but is soon turned back into AST for the existing transformations to +use, although a dozen transformations are immediately made obsolete. +Over time, we intend to port the rest of the compilation steps to use the IR directly, leading to +generating the output directly from the IR. +Simultaneously, once the IR is no longer optional, the parse step can also be simplified not to +create an AST (which it currently does for validation purposes). + +## Overview + +The ANGLE IR is written in Rust and can be found in [src/compiler/translator/ir/src/](../src): + +* [ir.rs](../src/ir.rs): The data structure of the IR can be found in this file, such as the various +  ids, type information, variable information, opcodes, control flow blocks, the IR metadata and +  finally the IR itself. +* [debug.rs](../src/debug.rs): Provides debug utils, mainly to dump the IR in a readable format. +* [validator.rs](../src/validator.rs): Provides internal validation. +* [instruction.rs](../src/instruction.rs): Provides helpers to create an instruction, including +  deriving precision from operands, constant folding etc. +* [builder.rs](../src/builder.rs): Used during parse to create the IR. +* [traverser.rs](../src/traverser.rs): Provides utilities to visit or transform the IR. +* [transform/](../src/transform/): The set of transformations that can be applied to the IR can be +  found here. +* [output/](../src/output/): Output generators are placed here. +* [ast.rs](../src/ast.rs): Helper to generate an AST out of the IR.  This is currently used to +  actually generate the legacy AST, but can also be used to generate GLSL, WGSL, etc that are +  text-based outputs with similar restrictions as GLSL. +* [compile.rs](../src/compile.rs): Orchestrator of the compilation process, deciding which +  transformations to apply and what output to generate. + +## IR Basics + +The IR includes the following entities, all of which are referenced by ids: + +* Types (`enum Type`): Referenced by `TypeId`, a type can be: + * `Type::Scalar`: A single `BasicType`, such as `float`, `int`, `yuvCscStandardEXT`, + `atomic_uint` + * `Type::Vector`: A vector of scalars + * `Type::Matrix`: A set of vectors (each, one column of the matrix) + * `Type::Array`: An array of other types + * `Type::UnsizedArray`: An unsized array of other types, such as allowed at the end of a storage + block. + * `Type::Struct`: A collection of other types. + Both `struct` and interface blocks are considered structs. + * `Type::Image`: An image. + This type includes information such as the basic type of the image (float, int, uint), whether + it's sampled (e.g. `texture2D` vs `image2D`), dimensionality (e.g. `texture2D` vs `texture3D`) + etc. + * `Type::Pointer`: A pointer to another type. + Pointers are references to memory locations, and they are used to load and store values. + +* Constants (`struct Constant`): Referenced by `ConstantId`, a constant pairs a `TypeId` with a + value `ConstantValue`. + The constant value is either a scalar if the type is a scalar, or a composite + (`ConstantValue::Composite`) which is simply a collection of other constants that make up the + value based on the type. + Constants do not have an intrinsic precision, but may inherit one in the specific instruction they + are used at based on neighboring operands according to GLSL rules. + +* Variables (`struct Variable`): Referenced by `VariableId`, a variable includes the following + information: + * Name (`struct Name`): The variable name is a string paired with the name's source: A shader + interface variable, an internal variable or a temporary. + The name source is used to generate exact or mangled names based on whether the backend + references it or not. + * Type (`TypeId`) + * Precision (`enum Precision`): Corresponding to GLSL's `highp`, `mediump`, etc + * Decorations (a set of `enum Decoration`): A set of additional properties of the variable, + originating from various qualifiers and layout qualifiers in GLSL + * Whether the variable is a built-in and which (`enum BuiltIn`) + * Whether the variable has an initializer, which must always be a constant (`ConstantId`) + +* Functions (`struct Function`): Referenced by `FunctionId`, a function includes the following + information: + * Name (`struct Name`) + * Parameters (a set of `struct FunctionParam`): Each `FunctionParam` consists of a variable + (`VariableId`) and the direction of the variable (`in`, `out`, `inout`). + * Return type, precision and decorations + +* Registers: Every intermediate value in the IR is called a register, referenced by `RegisterId`. + Registers are typically the result of operations. + They are never "void", i.e. they contain some value. + +For simplicity, some common ids are predefined: + +* Types, e.g. `TYPE_ID_VOID`, `TYPE_ID_FLOAT`, `TYPE_ID_VEC4`, `TYPE_ID_MAT3x2`, etc +* Constants, e.g. `CONSTANT_ID_FALSE`, `CONSTANT_ID_FLOAT_ONE`, `CONSTANT_ID_YUV_CSC_ITU601`, etc + +The IR itself is split in two structs, the IR metadata (`struct IRMeta`) and the actual +control-flow blocks and instructions. +This was necessarily to satisfy Rust's borrow checker during build and transformations of IR as the +instructions and blocks mutate at the same time as the metadata. + +The IR metadata includes global properties such as whether `early_fragment_tests` was specified, the +geometry shader max vertices, which variables are global, which function is `main()`, etc as well as: + +* The list of types, constants, variables and functions, each indexed by their corresponding id. +* The list of instructions that produce values, indexed by `RegisterId` + +The `IRMeta` struct provides helper functionality to create types from other types, create basic +constants or composite constants from other constants, declare variables, create instructions and +declare functions. + +The control-flow part of the IR consists of a set of entry point blocks (`struct Block`) per +function. +See below for details on control flow. + +## IR Operations + +The actual instructions in the IR are instances of `enum OpCode`. +This enum includes all sorts of instructions, each an opcode and its parameters if any. + +The opcode parameters are typically of type `TypedId`. +Rarely, a parameter may be a `ConstantId` or directly `u32`. +A `TypedId` bundles the `TypeId` and `Id` of the operand and its associated precision (mainly +because of constants, which don't have a precision out of context of the instruction). +`enum Id` is simply an enum that can either reference a `RegisterId`, `ConstantId` or `VariableId`. + +The opcodes in `OpCode` are: + +* Control flow ops, such as `OpCode::Return` (GLSL's `return`), `OpCode::Loop` (GLSL's `for` and + `while`), etc +* Indexing operations, such as `OpCode::ExtractVectorComponent` (GLSL's `value.x`), + `OpCode::AccessStructField` (GLSL's `pointer.field`), etc +* Constructors, such as `OpCode::ConstructMatrixFromScalar` (GLSL's `mat2x3(f)`), + `OpCode::ConstructVectorFromMultiple` (GLSL's `vec4(a, b, c)`). +* `OpCode::Load` and `OpCode::Store` to access memory +* `OpCode::Call` to call functions +* `OpCode::Unary`, `OpCode::Binary` and `OpCode::BuiltIn`, which themselves include an + `enum UnaryOpCode`, `enum BinaryOpCode` and `enum BuiltInOpCode` that indicate the specific op. + Unary and binary ops can be GLSL ops (like `+`) or built-ins (like `round()`) and produce values. + Built-in ops contain miscellaneous GLSL built-ins that either do not produce values (like + `barrier()` or have more than 2 parameters (like `faceforward`). +* `OpCode::Texture` encapsulates the _many_ GLSL texture built-ins. + This op consists of the `sampler` and `coord` parameters which are always present, plus + `enum TextureOpCode` which covers all the variations such as whether it's `texture*Proj`, + `texture*Lod`, `texture*Grad`, `texture*Gather`, etc, each with their own additional parameters. + +There is additionally `OpCode::Alias` which is used by transformations to make local changes +without having to propagate a register ID change over the whole IR. + +## IR Control Flow + +The instructions of a function are grouped in control-flow blocks (`struct Block`). +A block is simply: + +* A set of variables the block declares +* Possibly a merge input (see below) +* A set of instructions in this block +* Sub-blocks (see below) + +Within a block, there are no control-flow operations; either all or none of the block is executed. +A block is _always_ terminated with a control-flow operation, so for example there is always a +`return` instruction at the end of a function or a `continue` at the end of a loop body. + +Non-diverging control-flow operations (`OpCode::Discard`, `OpCode::Return`, `OpCode::Break`, +`OpCode::Continue`, `OpCode::Passthrough`, `OpCode::LoopIf` and `OpCode::Merge`) exit the block and +jump to a predetermined location, defined by a previous block. +There are no sub-blocks when a block is terminated by these operations. + +Some operations however diverge the control flow. +They always include a "merge" sub-block, which is where control flow reconverges after the +sub-blocks terminate. + +* `OpCode::If`: Based on the condition, either the true or false sub-block is executed. +* `OpCode::Loop`: The condition sub-block is executed, and if its terminating `OpCode::LoopIf` + evaluates to true, the body sub-block is executed. + * If a sub-block terminates with `OpCode::Continue`, control flow jumps back to the continue + block. + * If a sub-block terminates with `OpCode::Break`, control flow jumps to the merge sub-block. +* `OpCode::DoLoop`: Same as `OpCode::Loop`, except the body sub-block is executed first. +* `OpCode::Switch`: Based on the switch expression, one of the case sub-blocks is executed. + * If a case sub-block terminates with `OpCode::Passthrough`, control flow jumps to the next case + in the switch operation's list of case sub-blocks. + * If a case sub-block terminates with `OpCode::Break`, control flow jumps to the merge sub-block. +* `OpCode::NextBlock`: This is a special control flow instruction that doesn't actually diverge + control flow but chains blocks. + It's useful for transformations that might remove control-flow, such as constant folding an `if`, + or that might stitch blocks, for example to prepend a block to the beginning of the shader. + Control flow in this case unconditionally jumps to the merge sub-block. + +The merge sub-block may optionally include a "merge input". +This is the new preferred replacement for SSA's "phi" operator. +A merge block's input is a register whose value is determined by the blocks that merge into it (via +`OpCode::Merge`). +Merge inputs are present to avoid excessive use of temporary variables when generating SPIR-V, which +uses SPIR-V's `OpPhi` instruction for ternary operators and short-circuits. +The ANGLE IR's use of merge inputs is currently limited to a single input for simplicity, enough to +cover the SPIR-V generator's use-case, and is used in the same scenarios. + +The following is an example of control flow using `OpCode::If` with a merge input, corresponding to +`v3 = v1 ? v2 : c1` (where `vi` are variables and `c1` is a constant): + +``` ++-------------------+ +| r1 = Load v1 | +| If r1 | ++-------------------+ + | | | + | | -- true block --> +-------------------+ + | | | r2 = Load v2 | + | | | Merge r2 |.. + | | +-------------------+ . + | | . + | -- false block --> +-------------------+ . + | | Merge c1 |. . + | +-------------------+ . . + | . . + | merge block . . + V . . ++-------------------+ <... merge target ....... +| Input: r3 | +| Store v3 r3 | ++-------------------+ +``` + +The following is an example of control flow using `OpCode::Loop` with a continue block, +corresponding to `for (int v1 = c1; v1 < c2; ++v1) {...}`: + +``` ++-------------------+ +| Declare v1 = c1 | +| Loop | ++-------------------+ + | | | | continue target + | | | -- condition --> +---------------------+ <... + | | | | r1 = Load v1 | . + | | | | r2 = LessThan r1 c2 | . + | | | | LoopIf r2 |.. . + | | | +---------------------+ . . + | | | . . + | | --- body ---> +-------------------+ . . + | | | ... | . . + | | | Continue |..... . . + | | +-------------------+ . . . + | | . . . + | | body continue target . . . + | -- continue --> +--------------------+ <.. . . + | | PrefixIncrement v1 | . . + | | Continue | . . + | +--------------------+........... + | . + | merge block . + V . ++-------------------+ <... merge target .......... +| ... | ++-------------------+ +``` + +## Debug Output + +The IR can be dumped to `stdout` by calling `debug::dump(&ir);`. +This section explains the output from this utility for the following simple GLSL shader: + +``` +#version 310 es +precision mediump float; + +// Miscellaneous metadata: +layout(early_fragment_tests) in; + +// A global interface variable: +out vec4 color; + +void main() +{ + // A local variable with initializer: + vec2 result = vec2(0, 0); + + // A loop with a continue block + for (int i = 0; i < 10; ++i) + { + // Swizzle, constructor and built-in: + result.yx += vec2(i, exp(float(i))); + } + + // Ternary operator: + color = result.x > result.y ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +} +``` + +The following IR is generated from the above shader: + +``` +Fragment Shader +[Early fragment tests] + +Types: + t0: void + t1: float + t2: int + t3: uint + t4: bool + t5: atomic_uint + t6: yuvCscStandardEXT + t7: Vector of t1[2] + t8: Vector of t1[3] + t9: Vector of t1[4] + t10: Vector of t2[2] + t11: Vector of t2[3] + t12: Vector of t2[4] + t13: Vector of t3[2] + t14: Vector of t3[3] + t15: Vector of t3[4] + t16: Vector of t4[2] + t17: Vector of t4[3] + t18: Vector of t4[4] + t19: Matrix of t7[2] + t20: Matrix of t8[2] + t21: Matrix of t9[2] + t22: Matrix of t7[3] + t23: Matrix of t8[3] + t24: Matrix of t9[3] + t25: Matrix of t7[4] + t26: Matrix of t8[4] + t27: Matrix of t9[4] + t28: Pointer to t9 + t29: Pointer to t7 + t30: Pointer to t2 + t31: Pointer to t1 + +Constants: + c0 (t4): false + c1 (t4): true + c2 (t1): 0.0 + c3 (t1): 1.0 + c4 (t2): 0 + c5 (t2): 1 + c6 (t3): 0 + c7 (t3): 1 + c8 (t6): itu_601 + c9 (t6): itu_601_full_range + c10 (t6): itu_709 + c11 (t7): composite(c2, c2) + c12 (t2): 10 + c13 (t9): composite(c2, c3, c2, c3) + c14 (t9): composite(c3, c2, c2, c3) + +Variables: + v0 (t28): '_ucolor' [mediump, output] + v1 (t29): 'tresult_1'=c11 [mediump] + v2 (t30): 'ti_2'=c4 [mediump] + +Globals: v0 + +Functions: + + f0: 'main'() -> t0 + + __________________ + Entry To Function: + Declare: v1, v2 + Loop + | + +-> _______________ + | Loop Condition: + | r0 (t2) = Load v2 [mediump] + | r1 (t4) = LessThan r0 c12[mediump] + | LoopIf r1 + | + +-> __________ + | Loop Body: + | r3 (t29) = AccessVectorComponentMulti v1 (1, 0) [mediump] + | r4 (t2) = Load v2 [mediump] + | r5 (t1) = ConstructScalarFromScalar r4 [mediump] + | r6 (t1) = Exp r5 [mediump] + | r7 (t2) = Load v2 [mediump] + | r8 (t7) = ConstructVectorFromMultiple (r7, r6) [mediump] + | r9 (t7) = Load r3 [mediump] + | r10 (t7) = Add r9 r8 [mediump] + | Store r3 r10 + | Continue + | + +-> ____________________ + | Loop Continue Block: + | r2 (t2) = PrefixIncrement v2 [mediump] + | Continue + | + V___________ + Merge Block: + r11 (t31) = AccessVectorComponent v1 0 [mediump] + r12 (t31) = AccessVectorComponent v1 1 [mediump] + r13 (t1) = Load r12 [mediump] + r14 (t1) = Load r11 [mediump] + r15 (t4) = GreaterThan r14 r13 + If r15 + | + +-> ______________ + | If True Block: + | Merge c13[mediump] + | + +-> _______________ + | If False Block: + | Merge c14[mediump] + | + V___________ + Merge Block: + Input: r16 (t9) [mediump] + Store v0 r16 + Return +``` + +The above IR is explained piecemeal below: + +First, the shader type and metadata are specified: + +``` +Fragment Shader +[Early fragment tests] +``` + +The list of types follows, with scalar, vector and matrix types predefined and always present. +The types are identified by `tN`, with `N` being the `TypeId` value. + +``` +Types: + t0: void + t1: float + t2: int + ... + t4: bool + ... + t7: Vector of t1[2] <--- corresponding to GLSL's vec2 + ... + t9: Vector of t1[4] <--- corresponding to GLSL's vec4 + ... + ... + t28: Pointer to t9 + t29: Pointer to t7 + t30: Pointer to t2 + t31: Pointer to t1 +``` + +The constants are output next, identified by `cN`, with `N` being the `ConstantId` value. +The type of the constant is specified in parenthesis. + +``` +Constants: + ... + c2 (t1): 0.0 + c3 (t1): 1.0 + c4 (t2): 0 + c5 (t2): 1 + ... + c11 (t7): composite(c2, c2) + c12 (t2): 10 + c13 (t9): composite(c2, c3, c2, c3) + c14 (t9): composite(c3, c2, c2, c3) +``` + +The list of all variables (regardless) of scope follow, identified by `vN`, with `N` being the +`VariableId` value. +Similar to constants, the type of the variable is specified in parentheses. +The name of the variable is specified in quotations; currently, temporary variable names are +prefixed with `t` and suffixed by `_N` to disambiguate them, interface variables are prefixed with +`_u` per the legacy AST's convention, and built-ins and internal names are output as-is. +If the variable has an initializer, it's output as `=cM`. +The precision and other decorations of the variable are output as a list in brackets. + +``` +Variables: + v0 (t28): '_ucolor' [mediump, output] + v1 (t29): 'tresult_1'=c11 [mediump] + v2 (t30): 'ti_2'=c4 [mediump] +``` + +The list of variables in the global scope are provided before the functions are output. + +``` +Globals: v0 +``` + +The functions are output next, identified by `fN`, with `N` being the `FunctionId` value, each +starting with the function prototype: + +``` +Functions: + + f0: 'main'() -> t0 +``` + +In the above, the function `'main'` takes no argument and its return type is `t0` (i.e. `void`). + +The entry block of the function is the first block to be written. +In this example, this block defines two variables `v1` and `v2` (`result` and `i` respectively). +The sole instruction in this block is the `Loop` instruction, which corresponds to the beginning of +the `for` loop in the shader. +The `for` loop's init expression would go in this block, which in this case is only the declaration +of variable `v2` with a constant initializer. + +``` + __________________ + Entry To Function: + Declare: v1, v2 + Loop +``` + +This block has four sub-blocks: + +``` + | + +-> _______________ + | Loop Condition: + ... + | LoopIf r1 + | + +-> __________ + | Loop Body: + ... + | Continue + | + +-> ____________________ + | Loop Continue Block: + ... + | Continue + | + V___________ + Merge Block: + ... +``` + +The "Loop Condition" block executes before entering the loop body; the `LoopIf` terminating this +block decides if the body should be entered, or control flow should move to the "Merge Block". + +The "Loop Body" is the contents of the loop body, as expected. +The "Continue" instruction, when executed, moves control flow to the "Loop Continue Block", if any, +or the "Loop Condition" block otherwise. + +The "Loop Continue Block" corresponds to the `for` loop's continue expression and always terminates +with `Continue`, moving control flow back to the "Loop Condition". + +The loop condition makes a decision based on a boolean value: + +``` + +-> _______________ + | Loop Condition: + | r0 (t2) = Load v2 [mediump] + | r1 (t4) = LessThan r0 c12[mediump] + | LoopIf r1 +``` + +In the above, the value of `v2` is loaded in register 0. +Registers are identified by `rN`, with `N` being the `RegisterId` value. +The type of the result is specified in parentheses. +The precision of this operation is specified in brackets on the right. + +Then, `r0` is compared with the constant `c12`. +Constants do not intrinsically have a precision, but are assigned a precision in the context of the +instruction based on GLSL rules, in this case `c12` is assigned a `mediump` precision specified in +brackets next to the constant. +The result of this operation is stored in `r1`. + +Finally, the decision to execute the loop body or break out of the loop is made based on `r1`. + +The loop body executes a number of instructions: + +The pointer `v1` is swizzled with `.yx`; `r3` holds this pointer: + +``` + +-> __________ + | Loop Body: + | r3 (t29) = AccessVectorComponentMulti v1 (1, 0) [mediump] +``` + +The value of `v2` is loaded (which is of type `t2` (`int`)) and cast to `t1` (`float`) with a +constructor of scalar from scalar: + +``` + | r4 (t2) = Load v2 [mediump] + | r5 (t1) = ConstructScalarFromScalar r4 [mediump] +``` + +The `exp()` built-in is applied to the result: + +``` + | r6 (t1) = Exp r5 [mediump] +``` + +The value of `v2` is loaded again (unnecessarily, as no optimization passes have run) for the first +argument of the constructor `vec2(i, exp(float(i)))` with the second argument calculated above in +`r6` already: + +``` + | r7 (t2) = Load v2 [mediump] + | r8 (t7) = ConstructVectorFromMultiple (r7, r6) [mediump] +``` + +Finally, the add-assign operator is implemented as a load from the swizzled pointer, add and store +back to the same pointer: + +``` + | r9 (t7) = Load r3 [mediump] + | r10 (t7) = Add r9 r8 [mediump] + | Store r3 r10 +``` + +As described previously, the body terminates with a `Continue` instruction: + +``` + | Continue +``` + +The loop continue block increments `i` and continues the loop: + +``` + +-> ____________________ + | Loop Continue Block: + | r2 (t2) = PrefixIncrement v2 [mediump] + | Continue +``` + +Once the loop terminates, control flow is converged to the merge block. +The merge block continues the shader to evaluate the ternary operator. +The IR does not include a ternary operator, and implements this operation with an `if`/`else`. + +First, the components of `v1` are compared: + +``` + | + V___________ + Merge Block: + r11 (t31) = AccessVectorComponent v1 0 [mediump] + r12 (t31) = AccessVectorComponent v1 1 [mediump] + r13 (t1) = Load r12 [mediump] + r14 (t1) = Load r11 [mediump] + r15 (t4) = GreaterThan r14 r13 +``` + +This block is terminated with an `if` based on the previously calculated condition: + +``` + If r15 +``` + +This block has three sub-blocks: + +``` + | + +-> ______________ + | If True Block: + ... + | + +-> _______________ + | If False Block: + ... + | + V___________ + Merge Block: + Input: r16 (t9) [mediump] + ... +``` + +Importantly, the merge block includes a merge input, specified after `Input:` as a register (`r16`) +with its type and precision specified as usual in parentheses in brackets respectively. + +The true and false blocks in this example are simple, they each assign a constant value to the merge +input: + +``` + +-> ______________ + | If True Block: + | Merge c13[mediump] + | + +-> _______________ + | If False Block: + | Merge c14[mediump] +``` + +When the merge block of this `if` construct is executed, the merge input will contain either `c13` +or `c14` based on the path that executed before merging into this block. +This is equivalent to SSA's "phi" instruction with similar semantics, but is much easier to reason +about; think of the merge block's input register as a nameless temporary variable, with `Merge id` +storing into this variable and the merge block loading from it. + +Finally, the merge block assigns the ternary operator's result (found in the merge input `r16`) to +the output variable `color`: + +``` + | + V___________ + Merge Block: + Input: r16 (t9) [mediump] + Store v0 r16 +``` + +This final block of the function ends with a `Return` statement: + + +``` + Return +``` + +## Visitors + +A read-only pass on the IR (a "visit") is useful to gather information, such as shader reflection +information, or to generate an output from it, such as the translated shader or the debug dump. + +From a high level, visiting the IR is very simple: + +``` +* For each function + * Visit the entry block (including its instructions) + * Recursively visit the subblocks +``` + +There are helpers provided for this traversal, but it could just as easily be done free-form if the +helper is too restrictive. +These helpers can be found in the `traverser::visitor` module: + +* `traverser::visitor::for_each_function` runs a callback for each function itself, then another + callback for each of its blocks, and then a post-visit callback for the function. + The callback is passed a `BlockKind` that describes what it refers to (like an `if`'s true block, + a loop's continue block, etc). + The block callback returns a value to control which sub-blocks to visit next: + * `VISIT_SUB_BLOCKS`: continue to visit all sub-blocks + * `SKIP_TO_MERGE_BLOCK`: in GLSL terms, skip nested blocks and continue in the same scope. + For example, an `if`'s true and false blocks are skipped, and traversal continues to the + instruction after the `if` blocks. + * `STOP`: stop the traversal + +* `traverser::visitor::visit` is used by `for_each_function`, taking the same block callback, and + can be used to traverse a specific block instead of the whole IR. + +* `traverser::visitor::visit_block_instructions` takes a few callbacks to visit the instructions + within the block: + * A callback to visit the block itself, returning a generic `BlockResult` type + * A callback to visit each non-branch instruction, taking the `BlockResult` + * A callback to visit the terminating branch instruction, taking the `BlockResult` of the current + block, but also the `BlockResult` of the sub-blocks. + This means that the branch instruction is not visited until all (non-merge) sub-blocks are + visited first. + * If there is a merge block, this function repeats the above until the chain of merge blocks are + all visited. + The list of `BlockResult`s from this merge chain is passed to one final callback to aggregate + the results into a different `BlockResult` which is returned from this function. + +For examples of visitor traversals, see `debug.rs` which dumps the IR and `duplicate_block()` in +`util.rs` which makes a copy of a block (while replacing variables and creating new register ids). + +## Transformations + +The instructions in the IR are found in a graph (DAG) of blocks, with every block containing a +vector of non-branch instructions, ending with a branch instruction. +As such, it is not onerous to write free-form transformations, as might be necessary for complex +transformations such as dead-code elimination, by creating blocks and stitching them together, +adding instructions anywhere in the vector, or in-place modify the instructions as necessary. + +For common transformations, a set of utilities are provided. + +### Generating Instructions + +There are macros to create an instruction. +`instruction::make!()` creates an instruction, which is either void or has a new register as its +result. +For example: + +``` +let negate_operand = instruction::make!(negate, ir_meta, operand); +let add_operands = instruction::make!(add, ir_meta, lhs, rhs); +``` + +Transformations will frequently need to make localized changes, which ideally wouldn't perturb the +rest of the IR. +To support this, it's possible to: + +* Reassign an instruction to a new register with `IRMeta::assign_new_register_to_instruction()` +* Make an instruction whose result is the old register id with `instruction::make_with_result_id!()` + +With the above, it's possible for example to transform: + +``` +id = SomeOpCode ... +``` + +to: + +``` +new_id = SomeOpCode ... +// transformations on new_id, ending with: +id = ... +``` + +And the rest of the IR would continue to use register `id` as usual, and does not need to be +modified to use some new register id. + +### Transformation During Traversal + +The following helpers are very high level, and simply iterate over the functions and blocks, issuing +a callback: + +* `traverser::transformer::for_each_function` takes a few callbacks to transform the function: + * A callback to visit the function itself in preparation for the transformation + * A callback to transform the blocks, given the function's entry block + +* `traverser::transformer::for_each_block` takes callbacks to apply to blocks as it traverses them. + Each block is visited once before and once after the sub-blocks. + Both callbacks may modify the block as desired and return a reference to the block from where + traversal may continue. + In practice, there are two common choices: + * If the callback returns a reference to the original block, all the sub-blocks will get traversed + * If the callback has already processed the sub-blocks (including e.g. because it generated new + ones itself), it can return a reference to a merge block (in the chain of merge blocks) for + traversal to continue. + For example, if the callback splits a block to add an `if` in the middle, it may return the + merge block so that the true and false blocks of the if are skipped and not traversed. + +Another set of helpers take a callback that transforms an instruction, and returns a vector of +`Transform` operations to be applied by the helper in order: + +* If an empty vector is returned, the instruction is taken as is. + Otherwise, the instruction is _removed_ and replaced with the transformation. +* `Transform::Keep` indicates that the original instruction must be kept as-is. +* `Transform::Remove` indicates that the original instruction should be dropped. + This is normally not needed, since the original instruction is always dropped when there is a + transformation, but is useful if the only transformation is to drop the instruction. +* `Transform::Add` takes an instruction and adds it to the current block +* `Transform::AddBlock` takes a block and adds its instructions to the current block. + This is useful if the transformation adds a block that has sub-blocks, in which case the current + block is split, and the rest of the instructions are placed at the end of the merge chain of the + given block. +* `Transform::DeclareVariable` takes a variable id (where the variable is already declared in the IR + by the callback) and adds it to the list of variables to be declared by this block. + +Since these `Transform`s do not provide facilities to directly manipulate the branch instruction, +the callback is not allowed to transform the terminating branch instruction. +However, it is possible to prepend instructions to it by using `Transform::Keep` at the end of the +list of transforms. + +These helpers are: + +* `traverser::transformer::for_each_instruction`, takes such a callback and runs it for every + instruction of every function. +* `traverser::transformer::transform_block`, takes such a callback and runs it for every instruction + the given block and its sub-blocks. + +See the transformations under `transform/` for examples. diff --git a/src/compiler/translator/ir/src/ast.rs b/src/compiler/translator/ir/src/ast.rs new file mode 100644 index 00000000000..066dc2d07f7 --- /dev/null +++ b/src/compiler/translator/ir/src/ast.rs @@ -0,0 +1,587 @@ +// 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. +// +// A helper to turn the IR into a GLSL AST. For the GLSL generator, this is used to generate the +// shader itself. While the translator is not yet fully converted to use the IR, this is used to +// drop back to the legacy AST. + +use crate::ir::*; +use crate::*; + +pub trait Target { + type BlockResult; + + fn begin(&mut self); + fn end(&mut self) -> Self::BlockResult; + + // Upfront, create objects that would later represent types, constants, variables and + // functions. Later, the generator references these objects by ID and the implementation + // can look these objects up based on that. + fn new_type(&mut self, ir_meta: &IRMeta, id: TypeId, type_info: &Type); + fn new_constant(&mut self, ir_meta: &IRMeta, id: ConstantId, constant: &Constant); + fn new_variable(&mut self, ir_meta: &IRMeta, id: VariableId, variable: &Variable); + fn new_function(&mut self, ir_meta: &IRMeta, id: FunctionId, function: &Function); + + // Set up everything that needs to be set up in the global scope. That includes global + // variables, geometry/tessellation info, etc. + fn global_scope(&mut self, ir_meta: &IRMeta); + + fn begin_block(&mut self, ir_meta: &IRMeta, variables: &[VariableId]) -> Self::BlockResult; + fn merge_blocks(&mut self, blocks: Vec) -> Self::BlockResult; + + // Instructions + fn swizzle_single( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + id: TypedId, + index: u32, + ); + fn swizzle_multi( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + id: TypedId, + indices: &[u32], + ); + fn index( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + id: TypedId, + index: TypedId, + ); + fn select_field( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + id: TypedId, + index: u32, + field: &Field, + ); + fn construct_single( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + type_id: TypeId, + id: TypedId, + ); + fn construct_multi( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + type_id: TypeId, + ids: &[TypedId], + ); + fn load(&mut self, block: &mut Self::BlockResult, result: RegisterId, pointer: TypedId); + fn store(&mut self, block: &mut Self::BlockResult, pointer: TypedId, value: TypedId); + fn call( + &mut self, + block: &mut Self::BlockResult, + result: Option, + function_id: FunctionId, + params: &[TypedId], + ); + fn unary( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + unary_op: UnaryOpCode, + id: TypedId, + ); + fn binary( + &mut self, + block: &mut Self::BlockResult, + result: RegisterId, + binary_op: BinaryOpCode, + lhs: TypedId, + rhs: TypedId, + ); + fn built_in( + &mut self, + block: &mut Self::BlockResult, + result: Option, + built_in_op: BuiltInOpCode, + args: &[TypedId], + ); + fn texture( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + offset: Option, + ); + fn texture_compare( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + ); + fn texture_lod( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + lod: TypedId, + offset: Option, + ); + fn texture_compare_lod( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + lod: TypedId, + ); + fn texture_bias( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + bias: TypedId, + offset: Option, + ); + fn texture_compare_bias( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + bias: TypedId, + ); + fn texture_grad( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + dx: TypedId, + dy: TypedId, + offset: Option, + ); + fn texture_gather( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + offset: Option, + ); + fn texture_gather_component( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + component: TypedId, + offset: Option, + ); + fn texture_gather_ref( + &mut self, + ir_meta: &IRMeta, + block: &mut Self::BlockResult, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + refz: TypedId, + offset: Option, + ); + + // Control flow + fn branch_discard(&mut self, block: &mut Self::BlockResult); + fn branch_return(&mut self, block: &mut Self::BlockResult, value: Option); + fn branch_break(&mut self, block: &mut Self::BlockResult); + fn branch_continue(&mut self, block: &mut Self::BlockResult); + fn branch_if( + &mut self, + block: &mut Self::BlockResult, + condition: TypedId, + true_block: Option, + false_block: Option, + ); + fn branch_loop( + &mut self, + block: &mut Self::BlockResult, + loop_condition_block: Option, + body_block: Option, + ); + fn branch_do_loop( + &mut self, + block: &mut Self::BlockResult, + body_block: Option, + ); + fn branch_loop_if(&mut self, block: &mut Self::BlockResult, condition: TypedId); + fn branch_switch( + &mut self, + block: &mut Self::BlockResult, + value: TypedId, + case_ids: &[Option], + case_blocks: Vec, + ); + + // Take the current AST and place it as the body of the given function. + fn end_function(&mut self, block: Self::BlockResult, id: FunctionId); +} + +pub struct Generator { + ir: IR, +} + +impl Generator { + pub fn new(ir: IR) -> Generator { + Generator { ir } + } + + // Note: call transform::dealias::run() beforehand, as well as transform::astify::run(). + pub fn generate(&mut self, target: &mut T) -> T::BlockResult { + // Declare the types, variables and functions up-front so they can be referred to by ids + // when generating the AST itself. + self.create_types(target); + self.create_constants(target); + self.create_variables(target); + self.create_functions(target); + + self.generate_ast(target) + } + + fn create_types(&self, target: &mut T) { + self.ir.meta.all_types().iter().enumerate().for_each(|(id, type_info)| { + if !type_info.is_dead_code_eliminated() { + target.new_type(&self.ir.meta, TypeId { id: id as u32 }, type_info) + } + }); + } + + fn create_constants(&self, target: &mut T) { + self.ir.meta.all_constants().iter().enumerate().for_each(|(id, constant)| { + if !constant.is_dead_code_eliminated { + target.new_constant(&self.ir.meta, ConstantId { id: id as u32 }, constant) + } + }); + } + + fn create_variables(&self, target: &mut T) { + self.ir.meta.all_variables().iter().enumerate().for_each(|(id, variable)| { + if !variable.is_dead_code_eliminated { + let variable_id = VariableId { id: id as u32 }; + debug_assert!(!self.ir.meta.variable_needs_zero_initialization(variable_id)); + target.new_variable(&self.ir.meta, variable_id, variable) + } + }); + } + + fn create_functions(&self, target: &mut T) { + self.ir.meta.all_functions().iter().enumerate().for_each(|(id, function)| { + if self.ir.function_entries[id].is_some() { + target.new_function(&self.ir.meta, FunctionId { id: id as u32 }, function) + } + }); + } + + fn generate_ast(&self, target: &mut T) -> T::BlockResult { + target.begin(); + + // Prepare the global scope + target.global_scope(&self.ir.meta); + + // Visit the functions in DAG-sorted order, so that forward declarations are + // unnecessary. + let function_decl_order = + util::calculate_function_decl_order(&self.ir.meta, &self.ir.function_entries); + + for function_id in function_decl_order { + let entry = &self.ir.function_entries[function_id.id as usize].as_ref().unwrap(); + + let result_body = self.generate_block(entry, target); + target.end_function(result_body, function_id); + } + + target.end() + } + + fn generate_block(&self, block: &Block, target: &mut T) -> T::BlockResult { + traverser::visitor::visit_block_instructions( + &mut (self, target), + block, + &|(generator, target), block: &Block| { + // transform::astify::run() should have gotten rid of merge block inputs. + debug_assert!(block.input.is_none()); + target.begin_block(&generator.ir.meta, &block.variables) + }, + &|(generator, target), block_result, instructions| { + generator.generate_instructions(block_result, instructions, *target); + }, + &|(generator, target), + block_result, + branch_opcode, + loop_condition_block_result, + block1_result, + block2_result, + case_block_results| { + generator.generate_branch_instruction( + block_result, + branch_opcode, + loop_condition_block_result, + block1_result, + block2_result, + case_block_results, + *target, + ); + }, + &|(_, target), block_result_chain| target.merge_blocks(block_result_chain), + ) + } + + fn generate_instructions( + &self, + block_result: &mut T::BlockResult, + instructions: &[BlockInstruction], + target: &mut T, + ) { + // Generate nodes for all instructions except the terminating branch instruction. + instructions.iter().for_each(|instruction| { + let (op, result) = instruction.get_op_and_result(&self.ir.meta); + match op { + &OpCode::ExtractVectorComponent(id, index) + | &OpCode::AccessVectorComponent(id, index) => { + target.swizzle_single(block_result, result.unwrap().id, id, index) + } + &OpCode::ExtractVectorComponentMulti(id, ref indices) + | &OpCode::AccessVectorComponentMulti(id, ref indices) => { + target.swizzle_multi(block_result, result.unwrap().id, id, indices) + } + &OpCode::ExtractVectorComponentDynamic(id, index) + | &OpCode::AccessVectorComponentDynamic(id, index) + | &OpCode::ExtractMatrixColumn(id, index) + | &OpCode::AccessMatrixColumn(id, index) + | &OpCode::ExtractArrayElement(id, index) + | &OpCode::AccessArrayElement(id, index) => { + target.index(block_result, result.unwrap().id, id, index) + } + &OpCode::ExtractStructField(id, index) => target.select_field( + block_result, + result.unwrap().id, + id, + index, + self.ir.meta.get_type(id.type_id).get_struct_field(index), + ), + &OpCode::AccessStructField(id, index) => { + let struct_type_id = + self.ir.meta.get_type(id.type_id).get_element_type_id().unwrap(); + target.select_field( + block_result, + result.unwrap().id, + id, + index, + self.ir.meta.get_type(struct_type_id).get_struct_field(index), + ) + } + + &OpCode::ConstructScalarFromScalar(id) + | &OpCode::ConstructVectorFromScalar(id) + | &OpCode::ConstructMatrixFromScalar(id) + | &OpCode::ConstructMatrixFromMatrix(id) => { + let result = result.unwrap(); + target.construct_single(block_result, result.id, result.type_id, id); + } + &OpCode::ConstructVectorFromMultiple(ref ids) + | &OpCode::ConstructMatrixFromMultiple(ref ids) + | &OpCode::ConstructStruct(ref ids) + | &OpCode::ConstructArray(ref ids) => { + let result = result.unwrap(); + target.construct_multi(block_result, result.id, result.type_id, ids) + } + + &OpCode::Load(pointer) => target.load(block_result, result.unwrap().id, pointer), + &OpCode::Store(pointer, value) => { + debug_assert!(result.is_none()); + target.store(block_result, pointer, value); + } + + &OpCode::Call(function_id, ref params) => { + target.call(block_result, result.map(|id| id.id), function_id, params) + } + + &OpCode::Unary(unary_op, id) => { + target.unary(block_result, result.unwrap().id, unary_op, id) + } + &OpCode::Binary(binary_op, lhs, rhs) => { + target.binary(block_result, result.unwrap().id, binary_op, lhs, rhs) + } + &OpCode::BuiltIn(built_in_op, ref params) => { + target.built_in(block_result, result.map(|id| id.id), built_in_op, params) + } + &OpCode::Texture(TextureOpCode::Implicit { is_proj, offset }, sampler, coord) => { + target.texture( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + is_proj, + offset, + ) + } + &OpCode::Texture(TextureOpCode::Compare { compare }, sampler, coord) => target + .texture_compare( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + compare, + ), + &OpCode::Texture(TextureOpCode::Lod { is_proj, lod, offset }, sampler, coord) => { + target.texture_lod( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + is_proj, + lod, + offset, + ) + } + &OpCode::Texture(TextureOpCode::CompareLod { compare, lod }, sampler, coord) => { + target.texture_compare_lod( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + compare, + lod, + ) + } + &OpCode::Texture(TextureOpCode::Bias { is_proj, bias, offset }, sampler, coord) => { + target.texture_bias( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + is_proj, + bias, + offset, + ) + } + &OpCode::Texture(TextureOpCode::CompareBias { compare, bias }, sampler, coord) => { + target.texture_compare_bias( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + compare, + bias, + ) + } + &OpCode::Texture( + TextureOpCode::Grad { is_proj, dx, dy, offset }, + sampler, + coord, + ) => target.texture_grad( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + is_proj, + dx, + dy, + offset, + ), + &OpCode::Texture(TextureOpCode::Gather { offset }, sampler, coord) => target + .texture_gather( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + offset, + ), + &OpCode::Texture( + TextureOpCode::GatherComponent { component, offset }, + sampler, + coord, + ) => target.texture_gather_component( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + component, + offset, + ), + &OpCode::Texture(TextureOpCode::GatherRef { refz, offset }, sampler, coord) => { + target.texture_gather_ref( + &self.ir.meta, + block_result, + result.unwrap().id, + sampler, + coord, + refz, + offset, + ) + } + _ => panic!("Internal error: unexpected op when generating AST"), + } + }); + } + + fn generate_branch_instruction( + &self, + block_result: &mut T::BlockResult, + op: &OpCode, + loop_condition_block_result: Option, + block1_result: Option, + block2_result: Option, + case_block_results: Vec, + target: &mut T, + ) { + match op { + &OpCode::Discard => target.branch_discard(block_result), + &OpCode::Return(id) => target.branch_return(block_result, id), + &OpCode::Break => target.branch_break(block_result), + &OpCode::Continue => target.branch_continue(block_result), + &OpCode::If(id) => target.branch_if(block_result, id, block1_result, block2_result), + &OpCode::Loop => { + target.branch_loop(block_result, loop_condition_block_result, block1_result) + } + &OpCode::DoLoop => target.branch_do_loop(block_result, block1_result), + &OpCode::LoopIf(id) => target.branch_loop_if(block_result, id), + &OpCode::Switch(id, ref case_ids) => { + target.branch_switch(block_result, id, case_ids, case_block_results) + } + // Passthrough, NextBlock and Merge translate to nothing in GLSL + &OpCode::Passthrough | &OpCode::NextBlock | &OpCode::Merge(None) => (), + // Merge with a value should have been eliminated by astify. + &OpCode::Merge(Some(_)) => panic!( + "Internal error: unexpected merge instruction with value when generating AST" + ), + _ => panic!("Internal error: unexpected branch op when generating AST"), + } + } +} diff --git a/src/compiler/translator/ir/src/builder.cpp b/src/compiler/translator/ir/src/builder.cpp new file mode 100644 index 00000000000..2ce37ab3587 --- /dev/null +++ b/src/compiler/translator/ir/src/builder.cpp @@ -0,0 +1,1384 @@ +// +// 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. +// + +#include "compiler/translator/ir/src/builder.h" + +#include "compiler/translator/ConstantUnion.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/Types.h" + +namespace sh +{ +namespace ir +{ +namespace +{ +template typename Span> +rust::Slice Slice(const Span &span) +{ + return rust::Slice(const_cast(span.data()), span.size()); +} + +template typename Span> +rust::Slice SliceCast(const Span &span) +{ + return rust::Slice(reinterpret_cast(span.data()), span.size()); +} + +template typename Span> +rust::Slice SliceMut(const Span &span) +{ + return rust::Slice(span.data(), span.size()); +} + +rust::Str Str(const ImmutableString &str) +{ + return rust::Str(str.data(), str.length()); +} + +ffi::BuildOptions MakeBuildOptions(const ShCompileOptions &options) +{ + return ffi::BuildOptions{ + .initialize_uninitialized_variables = options.initializeUninitializedLocals, + .initializer_allowed_on_non_const_global_variables = + !options.forceDeferNonConstGlobalInitializers, + .initialize_output_variables = options.initOutputVariables, + }; +} + +ffi::ASTLayoutQualifier MakeASTLayoutQualifier(const TLayoutQualifier &qualifier) +{ + return ffi::ASTLayoutQualifier{ + qualifier.location, + static_cast(qualifier.matrixPacking), + static_cast(qualifier.blockStorage), + qualifier.binding, + qualifier.offset, + static_cast(qualifier.depth), + static_cast(qualifier.imageInternalFormat), + qualifier.numViews, + qualifier.yuv, + qualifier.index, + qualifier.noncoherent, + }; +} + +ffi::ASTMemoryQualifier MakeASTMemoryQualifier(const TMemoryQualifier &qualifier) +{ + return ffi::ASTMemoryQualifier{ + qualifier.readonly, qualifier.writeonly, qualifier.coherent, + qualifier.restrictQualifier, qualifier.volatileQualifier, + }; +} + +ffi::ASTType MakeASTType(const TType &type, TypeId typeId) +{ + ASSERT(!type.isTypeIdSet() || type.typeId().id == typeId.id); + ASSERT(typeId.id != kInvalidTypeId.id); + + return ffi::ASTType{ + typeId, + static_cast(type.getQualifier()), + static_cast(type.getPrecision()), + MakeASTLayoutQualifier(type.getLayoutQualifier()), + MakeASTMemoryQualifier(type.getMemoryQualifier()), + type.isInvariant(), + type.isPrecise(), + type.isInterpolant(), + }; +} +} // anonymous namespace + +Builder::Builder(gl::ShaderType shaderType, const ShCompileOptions &options) + : // C++ and Rust enums are identically defined. + mBuilder( + ffi::builder_new(static_cast(shaderType), MakeBuildOptions(options))) + +{} + +// static +IR Builder::destroy(Builder &&builder) +{ + if (builder.mHasError) + { + // Discard everything if the shader failed to build. + return ffi::builder_fail(std::move(builder.mBuilder)); + } + + return ffi::builder_finish(std::move(builder.mBuilder)); +} + +TypeId Builder::getBasicTypeId(TBasicType basicType, uint32_t primarySize, uint32_t secondarySize) +{ + return mBuilder->get_basic_type_id(static_cast(basicType), primarySize, + secondarySize); +} + +TypeId Builder::getStructTypeId(const ImmutableString &name, + const angle::Span &fields, + const angle::Span &fieldTypeIds, + bool isInterfaceBlock, + bool isBuiltIn, + bool isAtGlobalScope) +{ + if (mHasError) + { + return {}; + } + + TVector astFields; + + for (size_t i = 0; i < fields.size(); ++i) + { + const TField *field = fields[i]; + astFields.emplace_back(ffi::ASTField{ + Str(field->name()), + MakeASTType(*field->type(), + fieldTypeIds.empty() ? field->type()->typeId() : fieldTypeIds[i]), + }); + } + + ffi::ASTStruct astStruct = { + Str(name), Slice(astFields), isInterfaceBlock, isBuiltIn, isAtGlobalScope, + }; + + return mBuilder->get_struct_type_id(astStruct); +} + +TypeId Builder::getArrayTypeId(TypeId elementTypeId, + const angle::Span &arraySizes) +{ + if (mHasError) + { + return {}; + } + + return mBuilder->get_array_type_id(elementTypeId, Slice(arraySizes)); +} + +void Builder::setEarlyFragmentTests(bool value) +{ + mBuilder->set_early_fragment_tests(value); +} + +void Builder::setAdvancedBlendEquations(uint32_t value) +{ + mBuilder->set_advanced_blend_equations(value); +} + +void Builder::setTcsVertices(uint32_t value) +{ + mBuilder->set_tcs_vertices(value); +} + +void Builder::setTesPrimitive(TLayoutTessEvaluationType value) +{ + mBuilder->set_tes_primitive(static_cast(value)); +} + +void Builder::setTesVertexSpacing(TLayoutTessEvaluationType value) +{ + mBuilder->set_tes_vertex_spacing(static_cast(value)); +} + +void Builder::setTesOrdering(TLayoutTessEvaluationType value) +{ + mBuilder->set_tes_ordering(static_cast(value)); +} + +void Builder::setTesPointMode(TLayoutTessEvaluationType value) +{ + mBuilder->set_tes_point_mode(static_cast(value)); +} + +void Builder::setGsPrimitiveIn(TLayoutPrimitiveType value) +{ + mBuilder->set_gs_primitive_in(static_cast(value)); +} + +void Builder::setGsPrimitiveOut(TLayoutPrimitiveType value) +{ + mBuilder->set_gs_primitive_out(static_cast(value)); +} + +void Builder::setGsInvocations(uint32_t value) +{ + mBuilder->set_gs_invocations(value); +} + +void Builder::setGsMaxVertices(uint32_t value) +{ + mBuilder->set_gs_max_vertices(value); +} + +VariableId Builder::declareInterfaceVariable(const ImmutableString &name, + TypeId typeId, + const TType &type, + DeclarationSource source) +{ + if (mHasError) + { + return {}; + } + + return mBuilder->declare_interface_variable(Str(name), MakeASTType(type, typeId), + source == DeclarationSource::Internal); +} + +VariableId Builder::declareTempVariable(const ImmutableString &name, + TypeId typeId, + const TType &type) +{ + if (mHasError) + { + return {}; + } + + return mBuilder->declare_temp_variable(Str(name), MakeASTType(type, typeId)); +} + +void Builder::markVariableInvariant(VariableId id) +{ + if (!mHasError) + { + mBuilder->mark_variable_invariant(id); + } +} + +void Builder::markVariablePrecise(VariableId id) +{ + if (!mHasError) + { + mBuilder->mark_variable_precise(id); + } +} + +void Builder::initialize(VariableId id) +{ + if (!mHasError) + { + mBuilder->initialize(id); + } +} + +FunctionId Builder::newFunction(const ImmutableString &name, + const angle::Span ¶ms, + const angle::Span ¶mDirections, + TypeId returnTypeId, + const TType &returnType) +{ + if (mHasError) + { + return {}; + } + + return mBuilder->new_function(Str(name), Slice(params), + SliceCast(paramDirections), returnTypeId, + MakeASTType(returnType, returnTypeId)); +} + +void Builder::updateFunctionParamNames(FunctionId id, + const angle::Span ¶mNames, + const angle::Span ¶mIdsOut) +{ + if (mHasError) + { + return; + } + + std::vector paramNameStrs; + paramNameStrs.reserve(paramNames.size()); + + for (const ImmutableString ¶m : paramNames) + { + paramNameStrs.push_back(Str(param)); + } + + mBuilder->update_function_param_names(id, Slice(paramNameStrs), SliceMut(paramIdsOut)); +} +VariableId Builder::declareFunctionParam(const ImmutableString &name, + TypeId typeId, + const TType &type, + TQualifier direction) +{ + if (mHasError) + { + return {}; + } + + return mBuilder->declare_function_param(Str(name), typeId, MakeASTType(type, typeId), + static_cast(direction)); +} + +void Builder::beginFunction(FunctionId id) +{ + if (!mHasError) + { + mBuilder->begin_function(id); + } +} + +void Builder::endFunction() +{ + if (!mHasError) + { + mBuilder->end_function(); + } +} + +void Builder::beginIfTrueBlock() +{ + if (!mHasError) + { + mBuilder->begin_if_true_block(); + } +} + +void Builder::endIfTrueBlock() +{ + if (!mHasError) + { + mBuilder->end_if_true_block(); + } +} + +void Builder::beginIfFalseBlock() +{ + if (!mHasError) + { + mBuilder->begin_if_false_block(); + } +} + +void Builder::endIfFalseBlock() +{ + if (!mHasError) + { + mBuilder->end_if_false_block(); + } +} + +void Builder::endIf() +{ + if (!mHasError) + { + mBuilder->end_if(); + } +} + +void Builder::beginTernaryTrueExpression() +{ + if (!mHasError) + { + mBuilder->begin_ternary_true_expression(); + } +} + +void Builder::endTernaryTrueExpression(TBasicType basicType) +{ + if (!mHasError) + { + mBuilder->end_ternary_true_expression(basicType == EbtVoid); + } +} + +void Builder::beginTernaryFalseExpression() +{ + if (!mHasError) + { + mBuilder->begin_ternary_false_expression(); + } +} + +void Builder::endTernaryFalseExpression(TBasicType basicType) +{ + if (!mHasError) + { + mBuilder->end_ternary_false_expression(basicType == EbtVoid); + } +} + +void Builder::endTernary(TBasicType basicType) +{ + if (!mHasError) + { + mBuilder->end_ternary(basicType == EbtVoid); + } +} + +void Builder::beginShortCircuitOr() +{ + if (!mHasError) + { + mBuilder->begin_short_circuit_or(); + } +} + +void Builder::endShortCircuitOr() +{ + if (!mHasError) + { + mBuilder->end_short_circuit_or(); + } +} + +void Builder::beginShortCircuitAnd() +{ + if (!mHasError) + { + mBuilder->begin_short_circuit_and(); + } +} + +void Builder::endShortCircuitAnd() +{ + if (!mHasError) + { + mBuilder->end_short_circuit_and(); + } +} + +void Builder::beginLoopCondition() +{ + if (!mHasError) + { + mBuilder->begin_loop_condition(); + } +} + +void Builder::endLoopCondition() +{ + if (!mHasError) + { + mBuilder->end_loop_condition(); + } +} + +void Builder::endLoopContinue() +{ + if (!mHasError) + { + mBuilder->end_loop_continue(); + } +} + +void Builder::endLoop() +{ + if (!mHasError) + { + mBuilder->end_loop(); + } +} + +void Builder::beginDoLoop() +{ + if (!mHasError) + { + mBuilder->begin_do_loop(); + } +} + +void Builder::beginDoLoopCondition() +{ + if (!mHasError) + { + mBuilder->begin_do_loop_condition(); + } +} + +void Builder::endDoLoop() +{ + if (!mHasError) + { + mBuilder->end_do_loop(); + } +} + +void Builder::beginSwitch() +{ + if (!mHasError) + { + mBuilder->begin_switch(); + } +} + +void Builder::beginCase() +{ + if (!mHasError) + { + mBuilder->begin_case(); + } +} + +void Builder::beginDefault() +{ + if (!mHasError) + { + mBuilder->begin_default(); + } +} + +void Builder::endSwitch() +{ + if (!mHasError) + { + mBuilder->end_switch(); + } +} + +void Builder::branchDiscard() +{ + if (!mHasError) + { + mBuilder->branch_discard(); + } +} + +void Builder::branchReturn() +{ + if (!mHasError) + { + mBuilder->branch_return(); + } +} + +void Builder::branchReturnValue() +{ + if (!mHasError) + { + mBuilder->branch_return_value(); + } +} + +void Builder::branchBreak() +{ + if (!mHasError) + { + mBuilder->branch_break(); + } +} + +void Builder::branchContinue() +{ + if (!mHasError) + { + mBuilder->branch_continue(); + } +} + +uint32_t Builder::popArraySize() +{ + if (!mHasError) + { + return mBuilder->pop_array_size(); + } + return 0xEE; +} + +void Builder::endStatementWithValue() +{ + if (!mHasError) + { + mBuilder->end_statement_with_value(); + } +} + +void Builder::pushConstantFloat(float value) +{ + if (!mHasError) + { + mBuilder->push_constant_float(value); + } +} + +void Builder::pushConstantInt(int32_t value) +{ + if (!mHasError) + { + mBuilder->push_constant_int(value); + } +} + +void Builder::pushConstantUint(uint32_t value) +{ + if (!mHasError) + { + mBuilder->push_constant_uint(value); + } +} + +void Builder::pushConstantBool(bool value) +{ + if (!mHasError) + { + mBuilder->push_constant_bool(value); + } +} + +void Builder::pushConstantYuvCscStandard(TYuvCscStandardEXT value) +{ + if (!mHasError) + { + mBuilder->push_constant_yuv_csc_standard(static_cast(value)); + } +} + +void Builder::pushVariable(VariableId id) +{ + if (!mHasError) + { + mBuilder->push_variable(id); + } +} + +void Builder::callFunction(FunctionId id) +{ + if (!mHasError) + { + mBuilder->call_function(id); + } +} + +void Builder::vectorComponent(uint32_t component) +{ + if (!mHasError) + { + mBuilder->vector_component(component); + } +} + +void Builder::vectorComponentMulti(const angle::Span &components) +{ + if (!mHasError) + { + mBuilder->vector_component_multi(Slice(components)); + } +} + +void Builder::index() +{ + if (!mHasError) + { + mBuilder->index(); + } +} + +void Builder::structField(uint32_t fieldIndex) +{ + if (!mHasError) + { + mBuilder->struct_field(fieldIndex); + } +} + +void Builder::construct(TypeId typeId, size_t argCount) +{ + if (!mHasError) + { + mBuilder->construct(typeId, argCount); + } +} + +void Builder::onGlClipDistanceSized(VariableId id, uint32_t length) +{ + if (!mHasError) + { + mBuilder->on_gl_clip_distance_sized(id, length); + } +} + +void Builder::onGlCullDistanceSized(VariableId id, uint32_t length) +{ + if (!mHasError) + { + mBuilder->on_gl_cull_distance_sized(id, length); + } +} + +void Builder::arrayLength() +{ + if (!mHasError) + { + mBuilder->array_length(); + } +} + +void Builder::builtIn(TOperator op, size_t argCount) +{ + if (mHasError) + { + return; + } + switch (op) + { + case EOpNegative: + mBuilder->negate(); + return; + case EOpPositive: + // Nothing, this is a no-op. + return; + case EOpPostIncrement: + mBuilder->postfix_increment(); + return; + case EOpPostDecrement: + mBuilder->postfix_decrement(); + return; + case EOpPreIncrement: + mBuilder->prefix_increment(); + return; + case EOpPreDecrement: + mBuilder->prefix_decrement(); + return; + case EOpAssign: + mBuilder->store(); + return; + case EOpAdd: + mBuilder->add(); + return; + case EOpAddAssign: + mBuilder->add_assign(); + return; + case EOpSub: + mBuilder->sub(); + return; + case EOpSubAssign: + mBuilder->sub_assign(); + return; + case EOpMul: + mBuilder->mul(); + return; + case EOpMulAssign: + mBuilder->mul_assign(); + return; + case EOpVectorTimesScalar: + mBuilder->vector_times_scalar(); + return; + case EOpVectorTimesScalarAssign: + mBuilder->vector_times_scalar_assign(); + return; + case EOpMatrixTimesScalar: + mBuilder->matrix_times_scalar(); + return; + case EOpMatrixTimesScalarAssign: + mBuilder->matrix_times_scalar_assign(); + return; + case EOpVectorTimesMatrix: + mBuilder->vector_times_matrix(); + return; + case EOpVectorTimesMatrixAssign: + mBuilder->vector_times_matrix_assign(); + return; + case EOpMatrixTimesVector: + mBuilder->matrix_times_vector(); + return; + case EOpMatrixTimesMatrix: + mBuilder->matrix_times_matrix(); + return; + case EOpMatrixTimesMatrixAssign: + mBuilder->matrix_times_matrix_assign(); + return; + case EOpDiv: + mBuilder->div(); + return; + case EOpDivAssign: + mBuilder->div_assign(); + return; + case EOpIMod: + mBuilder->imod(); + return; + case EOpIModAssign: + mBuilder->imod_assign(); + return; + case EOpLogicalNot: + mBuilder->logical_not(); + return; + case EOpLogicalXor: + mBuilder->logical_xor(); + return; + case EOpEqual: + mBuilder->equal(); + return; + case EOpNotEqual: + mBuilder->not_equal(); + return; + case EOpLessThan: + mBuilder->less_than(); + return; + case EOpGreaterThan: + mBuilder->greater_than(); + return; + case EOpLessThanEqual: + mBuilder->less_than_equal(); + return; + case EOpGreaterThanEqual: + mBuilder->greater_than_equal(); + return; + case EOpBitwiseNot: + mBuilder->bitwise_not(); + return; + case EOpBitShiftLeft: + mBuilder->bit_shift_left(); + return; + case EOpBitShiftLeftAssign: + mBuilder->bit_shift_left_assign(); + return; + case EOpBitShiftRight: + mBuilder->bit_shift_right(); + return; + case EOpBitShiftRightAssign: + mBuilder->bit_shift_right_assign(); + return; + case EOpBitwiseOr: + mBuilder->bitwise_or(); + return; + case EOpBitwiseOrAssign: + mBuilder->bitwise_or_assign(); + return; + case EOpBitwiseXor: + mBuilder->bitwise_xor(); + return; + case EOpBitwiseXorAssign: + mBuilder->bitwise_xor_assign(); + return; + case EOpBitwiseAnd: + mBuilder->bitwise_and(); + return; + case EOpBitwiseAndAssign: + mBuilder->bitwise_and_assign(); + return; + case EOpRadians: + mBuilder->built_in_radians(); + return; + case EOpDegrees: + mBuilder->built_in_degrees(); + return; + case EOpSin: + mBuilder->built_in_sin(); + return; + case EOpCos: + mBuilder->built_in_cos(); + return; + case EOpTan: + mBuilder->built_in_tan(); + return; + case EOpAsin: + mBuilder->built_in_asin(); + return; + case EOpAcos: + mBuilder->built_in_acos(); + return; + case EOpAtan: + if (argCount == 2) + { + mBuilder->built_in_atan_binary(); + } + else + { + mBuilder->built_in_atan(); + } + return; + case EOpSinh: + mBuilder->built_in_sinh(); + return; + case EOpCosh: + mBuilder->built_in_cosh(); + return; + case EOpTanh: + mBuilder->built_in_tanh(); + return; + case EOpAsinh: + mBuilder->built_in_asinh(); + return; + case EOpAcosh: + mBuilder->built_in_acosh(); + return; + case EOpAtanh: + mBuilder->built_in_atanh(); + return; + case EOpPow: + mBuilder->built_in_pow(); + return; + case EOpExp: + mBuilder->built_in_exp(); + return; + case EOpLog: + mBuilder->built_in_log(); + return; + case EOpExp2: + mBuilder->built_in_exp2(); + return; + case EOpLog2: + mBuilder->built_in_log2(); + return; + case EOpSqrt: + mBuilder->built_in_sqrt(); + return; + case EOpInversesqrt: + mBuilder->built_in_inversesqrt(); + return; + case EOpAbs: + mBuilder->built_in_abs(); + return; + case EOpSign: + mBuilder->built_in_sign(); + return; + case EOpFloor: + mBuilder->built_in_floor(); + return; + case EOpTrunc: + mBuilder->built_in_trunc(); + return; + case EOpRound: + mBuilder->built_in_round(); + return; + case EOpRoundEven: + mBuilder->built_in_roundeven(); + return; + case EOpCeil: + mBuilder->built_in_ceil(); + return; + case EOpFract: + mBuilder->built_in_fract(); + return; + case EOpMod: + mBuilder->built_in_mod(); + return; + case EOpMin: + mBuilder->built_in_min(); + return; + case EOpMax: + mBuilder->built_in_max(); + return; + case EOpClamp: + mBuilder->built_in_clamp(); + return; + case EOpMix: + mBuilder->built_in_mix(); + return; + case EOpStep: + mBuilder->built_in_step(); + return; + case EOpSmoothstep: + mBuilder->built_in_smoothstep(); + return; + case EOpModf: + mBuilder->built_in_modf(); + return; + case EOpIsnan: + mBuilder->built_in_isnan(); + return; + case EOpIsinf: + mBuilder->built_in_isinf(); + return; + case EOpFloatBitsToInt: + mBuilder->built_in_floatbitstoint(); + return; + case EOpFloatBitsToUint: + mBuilder->built_in_floatbitstouint(); + return; + case EOpIntBitsToFloat: + mBuilder->built_in_intbitstofloat(); + return; + case EOpUintBitsToFloat: + mBuilder->built_in_uintbitstofloat(); + return; + case EOpFma: + mBuilder->built_in_fma(); + return; + case EOpFrexp: + mBuilder->built_in_frexp(); + return; + case EOpLdexp: + mBuilder->built_in_ldexp(); + return; + case EOpPackSnorm2x16: + mBuilder->built_in_packsnorm2x16(); + return; + case EOpPackHalf2x16: + mBuilder->built_in_packhalf2x16(); + return; + case EOpUnpackSnorm2x16: + mBuilder->built_in_unpacksnorm2x16(); + return; + case EOpUnpackHalf2x16: + mBuilder->built_in_unpackhalf2x16(); + return; + case EOpPackUnorm2x16: + mBuilder->built_in_packunorm2x16(); + return; + case EOpUnpackUnorm2x16: + mBuilder->built_in_unpackunorm2x16(); + return; + case EOpPackUnorm4x8: + mBuilder->built_in_packunorm4x8(); + return; + case EOpPackSnorm4x8: + mBuilder->built_in_packsnorm4x8(); + return; + case EOpUnpackUnorm4x8: + mBuilder->built_in_unpackunorm4x8(); + return; + case EOpUnpackSnorm4x8: + mBuilder->built_in_unpacksnorm4x8(); + return; + case EOpLength: + mBuilder->built_in_length(); + return; + case EOpDistance: + mBuilder->built_in_distance(); + return; + case EOpDot: + mBuilder->built_in_dot(); + return; + case EOpCross: + mBuilder->built_in_cross(); + return; + case EOpNormalize: + mBuilder->built_in_normalize(); + return; + case EOpFaceforward: + mBuilder->built_in_faceforward(); + return; + case EOpReflect: + mBuilder->built_in_reflect(); + return; + case EOpRefract: + mBuilder->built_in_refract(); + return; + case EOpMatrixCompMult: + mBuilder->built_in_matrixcompmult(); + return; + case EOpOuterProduct: + mBuilder->built_in_outerproduct(); + return; + case EOpTranspose: + mBuilder->built_in_transpose(); + return; + case EOpDeterminant: + mBuilder->built_in_determinant(); + return; + case EOpInverse: + mBuilder->built_in_inverse(); + return; + case EOpLessThanComponentWise: + mBuilder->built_in_lessthan(); + return; + case EOpLessThanEqualComponentWise: + mBuilder->built_in_lessthanequal(); + return; + case EOpGreaterThanComponentWise: + mBuilder->built_in_greaterthan(); + return; + case EOpGreaterThanEqualComponentWise: + mBuilder->built_in_greaterthanequal(); + return; + case EOpEqualComponentWise: + mBuilder->built_in_equal(); + return; + case EOpNotEqualComponentWise: + mBuilder->built_in_notequal(); + return; + case EOpAny: + mBuilder->built_in_any(); + return; + case EOpAll: + mBuilder->built_in_all(); + return; + case EOpNotComponentWise: + mBuilder->built_in_not(); + return; + case EOpBitfieldExtract: + mBuilder->built_in_bitfieldextract(); + return; + case EOpBitfieldInsert: + mBuilder->built_in_bitfieldinsert(); + return; + case EOpBitfieldReverse: + mBuilder->built_in_bitfieldreverse(); + return; + case EOpBitCount: + mBuilder->built_in_bitcount(); + return; + case EOpFindLSB: + mBuilder->built_in_findlsb(); + return; + case EOpFindMSB: + mBuilder->built_in_findmsb(); + return; + case EOpUaddCarry: + mBuilder->built_in_uaddcarry(); + return; + case EOpUsubBorrow: + mBuilder->built_in_usubborrow(); + return; + case EOpUmulExtended: + mBuilder->built_in_umulextended(); + return; + case EOpImulExtended: + mBuilder->built_in_imulextended(); + return; + case EOpTextureSize: + { + // textureSize() takes the sampler and possibly lod. + const bool withLod = argCount > 1; + mBuilder->built_in_texturesize(withLod); + return; + } + case EOpTextureQueryLOD: + mBuilder->built_in_texturequerylod(); + return; + case EOpTexelFetch: + { + // texelFetch() takes the sampler, coordinates and either the lod or sample index, + // except for samplerBuffers. + const bool withLodOrSample = argCount > 2; + mBuilder->built_in_texelfetch(withLodOrSample); + return; + } + case EOpTexelFetchOffset: + mBuilder->built_in_texelfetchoffset(); + return; + case EOpRgb_2_yuv: + mBuilder->built_in_rgb_2_yuv(); + return; + case EOpYuv_2_rgb: + mBuilder->built_in_yuv_2_rgb(); + return; + case EOpDFdx: + mBuilder->built_in_dfdx(); + return; + case EOpDFdy: + mBuilder->built_in_dfdy(); + return; + case EOpFwidth: + mBuilder->built_in_fwidth(); + return; + case EOpInterpolateAtCentroid: + mBuilder->built_in_interpolateatcentroid(); + return; + case EOpInterpolateAtSample: + mBuilder->built_in_interpolateatsample(); + return; + case EOpInterpolateAtOffset: + mBuilder->built_in_interpolateatoffset(); + return; + case EOpAtomicCounter: + mBuilder->built_in_atomiccounter(); + return; + case EOpAtomicCounterIncrement: + mBuilder->built_in_atomiccounterincrement(); + return; + case EOpAtomicCounterDecrement: + mBuilder->built_in_atomiccounterdecrement(); + return; + case EOpAtomicAdd: + mBuilder->built_in_atomicadd(); + return; + case EOpAtomicMin: + mBuilder->built_in_atomicmin(); + return; + case EOpAtomicMax: + mBuilder->built_in_atomicmax(); + return; + case EOpAtomicAnd: + mBuilder->built_in_atomicand(); + return; + case EOpAtomicOr: + mBuilder->built_in_atomicor(); + return; + case EOpAtomicXor: + mBuilder->built_in_atomicxor(); + return; + case EOpAtomicExchange: + mBuilder->built_in_atomicexchange(); + return; + case EOpAtomicCompSwap: + mBuilder->built_in_atomiccompswap(); + return; + case EOpImageSize: + mBuilder->built_in_imagesize(); + return; + case EOpImageStore: + mBuilder->built_in_imagestore(); + return; + case EOpImageLoad: + mBuilder->built_in_imageload(); + return; + case EOpImageAtomicAdd: + mBuilder->built_in_imageatomicadd(); + return; + case EOpImageAtomicMin: + mBuilder->built_in_imageatomicmin(); + return; + case EOpImageAtomicMax: + mBuilder->built_in_imageatomicmax(); + return; + case EOpImageAtomicAnd: + mBuilder->built_in_imageatomicand(); + return; + case EOpImageAtomicOr: + mBuilder->built_in_imageatomicor(); + return; + case EOpImageAtomicXor: + mBuilder->built_in_imageatomicxor(); + return; + case EOpImageAtomicExchange: + mBuilder->built_in_imageatomicexchange(); + return; + case EOpImageAtomicCompSwap: + mBuilder->built_in_imageatomiccompswap(); + return; + case EOpPixelLocalLoadANGLE: + mBuilder->built_in_pixellocalloadangle(); + return; + case EOpPixelLocalStoreANGLE: + mBuilder->built_in_pixellocalstoreangle(); + return; + case EOpMemoryBarrier: + mBuilder->built_in_memorybarrier(); + return; + case EOpMemoryBarrierAtomicCounter: + mBuilder->built_in_memorybarrieratomiccounter(); + return; + case EOpMemoryBarrierBuffer: + mBuilder->built_in_memorybarrierbuffer(); + return; + case EOpMemoryBarrierImage: + mBuilder->built_in_memorybarrierimage(); + return; + case EOpBarrier: + case EOpBarrierTCS: + mBuilder->built_in_barrier(); + return; + case EOpMemoryBarrierShared: + mBuilder->built_in_memorybarriershared(); + return; + case EOpGroupMemoryBarrier: + mBuilder->built_in_groupmemorybarrier(); + return; + case EOpEmitVertex: + mBuilder->built_in_emitvertex(); + return; + case EOpEndPrimitive: + mBuilder->built_in_endprimitive(); + return; + case EOpTexture: + case EOpTexture2D: + case EOpShadow2DEXT: + case EOpTexture2DRect: + case EOpTexture3D: + case EOpTextureCube: + case EOpTextureVideoWEBGL: + { + // texture() takes the sampler, coordinates and possibly a compare parameter. + // Note that the variant with a bias parameter is given a different Op. + const bool withCompare = argCount > 2; + mBuilder->built_in_texture(withCompare); + return; + } + case EOpTextureProj: + case EOpShadow2DProjEXT: + case EOpTexture2DProj: + case EOpTexture2DRectProj: + case EOpTexture3DProj: + mBuilder->built_in_textureproj(); + return; + case EOpTextureLod: + case EOpTexture2DLodEXTFS: + case EOpTexture2DLodVS: + case EOpTexture3DLod: + case EOpTextureCubeLodEXTFS: + case EOpTextureCubeLodVS: + { + // textureLod() takes the sampler, coordinates and lod. The EXT_texture_shadow_lod + // extension introduces a variant that possibly takes a compare parameter. + const bool withCompare = argCount > 3; + mBuilder->built_in_texturelod(withCompare); + return; + } + case EOpTextureProjLod: + case EOpTexture2DProjLodEXTFS: + case EOpTexture2DProjLodVS: + case EOpTexture3DProjLod: + mBuilder->built_in_textureprojlod(); + return; + case EOpTextureBias: + case EOpTexture2DBias: + case EOpTexture3DBias: + case EOpTextureCubeBias: + { + // The bias-variant of texture() takes the sampler, coordinates and the bias parameter. + // The EXT_texture_shadow_lod extension introduces a variant that possibly takes a + // compare parameter. + const bool withCompare = argCount > 3; + mBuilder->built_in_texturebias(withCompare); + return; + } + case EOpTextureProjBias: + case EOpTexture2DProjBias: + case EOpTexture3DProjBias: + mBuilder->built_in_textureprojbias(); + return; + case EOpTextureOffset: + mBuilder->built_in_textureoffset(); + return; + case EOpTextureProjOffset: + mBuilder->built_in_textureprojoffset(); + return; + case EOpTextureLodOffset: + mBuilder->built_in_texturelodoffset(); + return; + case EOpTextureProjLodOffset: + mBuilder->built_in_textureprojlodoffset(); + return; + case EOpTextureOffsetBias: + mBuilder->built_in_textureoffsetbias(); + return; + case EOpTextureProjOffsetBias: + mBuilder->built_in_textureprojoffsetbias(); + return; + case EOpTextureGrad: + case EOpTexture2DGradEXT: + case EOpTextureCubeGradEXT: + mBuilder->built_in_texturegrad(); + return; + case EOpTextureProjGrad: + case EOpTexture2DProjGradEXT: + mBuilder->built_in_textureprojgrad(); + return; + case EOpTextureGradOffset: + mBuilder->built_in_texturegradoffset(); + return; + case EOpTextureProjGradOffset: + mBuilder->built_in_textureprojgradoffset(); + return; + case EOpTextureGather: + mBuilder->built_in_texturegather(); + return; + case EOpTextureGatherComp: + mBuilder->built_in_texturegathercomp(); + return; + case EOpTextureGatherRef: + mBuilder->built_in_texturegatherref(); + return; + case EOpTextureGatherOffset: + case EOpTextureGatherOffsets: + mBuilder->built_in_texturegatheroffset(); + return; + case EOpTextureGatherOffsetComp: + case EOpTextureGatherOffsetsComp: + mBuilder->built_in_texturegatheroffsetcomp(); + return; + case EOpTextureGatherOffsetRef: + case EOpTextureGatherOffsetsRef: + mBuilder->built_in_texturegatheroffsetref(); + return; + default: + UNREACHABLE(); + } +} +} // namespace ir +} // namespace sh diff --git a/src/compiler/translator/ir/src/builder.h b/src/compiler/translator/ir/src/builder.h new file mode 100644 index 00000000000..393db386237 --- /dev/null +++ b/src/compiler/translator/ir/src/builder.h @@ -0,0 +1,351 @@ +// +// 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. +// +// Bridge to IR builder in Rust. If ANGLE_IR is disabled, all functions are no-op; otherwise it +// converts between AST-based enums and types to IR's types. Once migration to IR is complete, +// ANGLE could directly use the IR types to avoid most of this sort of conversion. +// + +#ifndef COMPILER_TRANSLATOR_IR_SRC_BUILDER_H_ +#define COMPILER_TRANSLATOR_IR_SRC_BUILDER_H_ + +#include + +#include "common/PackedEnums.h" +#include "common/span.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Operator_autogen.h" + +#ifdef ANGLE_IR +# include "compiler/translator/ir/src/builder.rs.h" +#endif + +namespace sh +{ +class TField; +class TSymbol; + +class TType; + +class TConstantUnion; + +namespace ir +{ +enum class DeclarationSource +{ + // The variable be declared to IR is an internal built-in variable + Internal, + // The variable be declared to IR is declared by the shader, including when a built-in is + // redeclared. + Shader, +}; + +#ifdef ANGLE_IR +using IR = rust::Box; +using TypeId = ffi::TypeId; +using ConstantId = ffi::ConstantId; +using VariableId = ffi::VariableId; +using FunctionId = ffi::FunctionId; + +static constexpr TypeId kInvalidTypeId = TypeId{0xFFFF'FFFF}; +inline bool IsTypeIdValid(TypeId id) +{ + return id.id != kInvalidTypeId.id; +} + +static constexpr VariableId kInvalidVariableId = VariableId{0xFFFF'FFFF}; +inline bool IsVariableIdValid(VariableId id) +{ + return id.id != kInvalidVariableId.id; +} + +class Builder +{ + public: + Builder(gl::ShaderType shaderType, const ShCompileOptions &options); + static IR destroy(Builder &&builder); + + void onError() { mHasError = true; } + + TypeId getBasicTypeId(TBasicType basicType, uint32_t primarySize, uint32_t secondarySize); + TypeId getStructTypeId(const ImmutableString &name, + const angle::Span &fields, + const angle::Span &fieldTypeIds, + bool isInterfaceBlock, + bool isBuiltIn, + bool isAtGlobalScope); + TypeId getArrayTypeId(TypeId elementTypeId, const angle::Span &arraySizes); + + void setEarlyFragmentTests(bool value); + void setAdvancedBlendEquations(uint32_t value); + void setTcsVertices(uint32_t value); + void setTesPrimitive(TLayoutTessEvaluationType value); + void setTesVertexSpacing(TLayoutTessEvaluationType value); + void setTesOrdering(TLayoutTessEvaluationType value); + void setTesPointMode(TLayoutTessEvaluationType value); + void setGsPrimitiveIn(TLayoutPrimitiveType value); + void setGsPrimitiveOut(TLayoutPrimitiveType value); + void setGsInvocations(uint32_t value); + void setGsMaxVertices(uint32_t value); + TypeId sizeUnsizedArrayType(TypeId typeId, uint32_t arraySize); + + VariableId declareInterfaceVariable(const ImmutableString &name, + TypeId typeId, + const TType &type, + DeclarationSource source); + VariableId declareTempVariable(const ImmutableString &name, TypeId typeId, const TType &type); + void markVariableInvariant(VariableId id); + void markVariablePrecise(VariableId id); + void initialize(VariableId id); + + FunctionId newFunction(const ImmutableString &name, + const angle::Span ¶ms, + const angle::Span ¶mDirections, + TypeId returnTypeId, + const TType &returnType); + void updateFunctionParamNames(FunctionId id, + const angle::Span ¶mNames, + const angle::Span ¶mIdsOut); + VariableId declareFunctionParam(const ImmutableString &name, + TypeId typeId, + const TType &type, + TQualifier direction); + void beginFunction(FunctionId id); + void endFunction(); + + void beginIfTrueBlock(); + void endIfTrueBlock(); + void beginIfFalseBlock(); + void endIfFalseBlock(); + void endIf(); + + void beginTernaryTrueExpression(); + void endTernaryTrueExpression(TBasicType basicType); + void beginTernaryFalseExpression(); + void endTernaryFalseExpression(TBasicType basicType); + void endTernary(TBasicType basicType); + + void beginShortCircuitOr(); + void endShortCircuitOr(); + void beginShortCircuitAnd(); + void endShortCircuitAnd(); + + void beginLoopCondition(); + void endLoopCondition(); + void endLoopContinue(); + void endLoop(); + void beginDoLoop(); + void beginDoLoopCondition(); + void endDoLoop(); + + void beginSwitch(); + void beginCase(); + void beginDefault(); + void endSwitch(); + + void branchDiscard(); + void branchReturn(); + void branchReturnValue(); + void branchBreak(); + void branchContinue(); + + uint32_t popArraySize(); + void endStatementWithValue(); + void pushConstantFloat(float value); + void pushConstantInt(int32_t value); + void pushConstantUint(uint32_t value); + void pushConstantBool(bool value); + void pushConstantYuvCscStandard(TYuvCscStandardEXT value); + void pushVariable(VariableId id); + void callFunction(FunctionId id); + void vectorComponent(uint32_t component); + void vectorComponentMulti(const angle::Span &components); + void index(); + void structField(uint32_t fieldIndex); + void construct(TypeId typeId, size_t argCount); + void onGlClipDistanceSized(VariableId id, uint32_t length); + void onGlCullDistanceSized(VariableId id, uint32_t length); + void arrayLength(); + + // Everything else that has a TOperator. + void builtIn(TOperator op, size_t argCount); + + private: + rust::Box mBuilder; + // If the shader fails validation, stop generating the IR to avoid crashing on unexpected input. + // This is the simpler alternative to replacing existing elements with fake ones that would have + // passed validation. + bool mHasError = false; +}; + +#else // ANGLE_IR +using IR = void *; +using TypeId = uint8_t; +using ConstantId = uint8_t; +using VariableId = uint8_t; +using FunctionId = uint8_t; + +static constexpr TypeId kInvalidTypeId = 0; +inline bool IsTypeIdValid(TypeId id) +{ + return true; +} + +static constexpr VariableId kInvalidVariableId = 0; +inline bool IsVariableIdValid(VariableId id) +{ + return true; +} + +class Builder +{ + public: + Builder(gl::ShaderType shaderType, const ShCompileOptions &options) {} + static IR destroy(Builder &&builder) { return nullptr; } + + void onError() {} + + TypeId getBasicTypeId(TBasicType basicType, uint32_t primarySize, uint32_t secondarySize) + { + return 0; + } + TypeId getStructTypeId(const ImmutableString &name, + const angle::Span &fields, + const angle::Span &fieldTypeIds, + bool isInterfaceBlock, + bool isBuiltIn, + bool isAtGlobalScope) + { + return 0; + } + TypeId getArrayTypeId(TypeId elementTypeId, const angle::Span &arraySizes) + { + return 0; + } + + void setEarlyFragmentTests(bool value) {} + void setAdvancedBlendEquations(uint32_t value) {} + void setTcsVertices(uint32_t value) {} + void setTesPrimitive(TLayoutTessEvaluationType value) {} + void setTesVertexSpacing(TLayoutTessEvaluationType value) {} + void setTesOrdering(TLayoutTessEvaluationType value) {} + void setTesPointMode(TLayoutTessEvaluationType value) {} + void setGsPrimitiveIn(TLayoutPrimitiveType value) {} + void setGsPrimitiveOut(TLayoutPrimitiveType value) {} + void setGsInvocations(uint32_t value) {} + void setGsMaxVertices(uint32_t value) {} + TypeId sizeUnsizedArrayType(TypeId typeId, uint32_t arraySize) { return typeId; } + + VariableId declareInterfaceVariable(const ImmutableString &name, + TypeId typeId, + const TType &type, + DeclarationSource source) + { + return 0; + } + VariableId declareTempVariable(const ImmutableString &name, TypeId typeId, const TType &type) + { + return 0; + } + void markVariableInvariant(VariableId id) {} + void markVariablePrecise(VariableId id) {} + void initialize(VariableId id) {} + + FunctionId newFunction(const ImmutableString &name, + const angle::Span ¶ms, + const angle::Span ¶mDirections, + TypeId returnTypeId, + const TType &returnType) + { + return 0; + } + void updateFunctionParamNames(FunctionId id, + const angle::Span ¶mNames, + const angle::Span ¶mIdsOut) + {} + VariableId declareFunctionParam(const ImmutableString &name, + TypeId typeId, + const TType &type, + TQualifier direction) + { + return 0; + } + void beginFunction(FunctionId id) {} + void endFunction() {} + + void beginIfTrueBlock() {} + void endIfTrueBlock() {} + void beginIfFalseBlock() {} + void endIfFalseBlock() {} + void endIf() {} + + void beginTernaryTrueExpression() {} + void endTernaryTrueExpression(TBasicType) {} + void beginTernaryFalseExpression() {} + void endTernaryFalseExpression(TBasicType) {} + void endTernary(TBasicType) {} + + void beginShortCircuitOr() {} + void endShortCircuitOr() {} + void beginShortCircuitAnd() {} + void endShortCircuitAnd() {} + + void beginLoopCondition() {} + void endLoopCondition() {} + void endLoopContinue() {} + void endLoop() {} + void beginDoLoop() {} + void beginDoLoopCondition() {} + void endDoLoop() {} + + void beginSwitch() {} + void beginCase() {} + void beginDefault() {} + void endSwitch() {} + + void branchDiscard() {} + void branchReturn() {} + void branchReturnValue() {} + void branchBreak() {} + void branchContinue() {} + + uint32_t popArraySize() { return 0; } + void endStatementWithValue() {} + void pushConstantFloat(float value) {} + void pushConstantInt(int32_t value) {} + void pushConstantUint(uint32_t value) {} + void pushConstantBool(bool value) {} + void pushConstantYuvCscStandard(TYuvCscStandardEXT value) {} + void pushVariable(VariableId id) {} + void callFunction(FunctionId id) {} + void vectorComponent(uint32_t component) {} + void vectorComponentMulti(const angle::Span &components) {} + void index() {} + void structField(uint32_t fieldIndex) {} + void construct(TypeId typeId, size_t argCount) {} + void onGlClipDistanceSized(VariableId id, uint32_t length) {} + void onGlCullDistanceSized(VariableId id, uint32_t length) {} + void arrayLength() {} + void builtIn(TOperator op, size_t argCount) {} +}; +#endif // ANGLE_IR +} // namespace ir +} // namespace sh + +#ifdef ANGLE_IR +inline bool operator==(sh::ir::TypeId one, sh::ir::TypeId other) +{ + return one.id == other.id; +} + +inline bool operator!=(sh::ir::TypeId one, sh::ir::TypeId other) +{ + return !(one == other); +} +#endif + +#endif // COMPILER_TRANSLATOR_IR_SRC_BUILDER_H_ diff --git a/src/compiler/translator/ir/src/builder.rs b/src/compiler/translator/ir/src/builder.rs new file mode 100644 index 00000000000..1636b11cbd1 --- /dev/null +++ b/src/compiler/translator/ir/src/builder.rs @@ -0,0 +1,5499 @@ +// 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. +// +// The IR builder connects to ParseContext.cpp, turning the parse output to an IR. It is not meant +// to be used by transformations, as they can generate IR more efficiently. + +use crate::ir::*; +use crate::*; + +// Used when building the IR from GLSL, holds an intermediate block to be filled with instructions. +#[cfg_attr(debug_assertions, derive(Debug))] +struct IntermediateBlock { + block: Block, + is_merge_block: bool, + // Once the block is terminated with return, break, continue or discard, any new instructions + // that are encountered are dead code. Those instructions are processed as usual, but don't + // result in any changes to the block. + new_instructions_are_dead_code: bool, +} + +impl IntermediateBlock { + fn new() -> IntermediateBlock { + IntermediateBlock { + block: Block::new(), + is_merge_block: false, + new_instructions_are_dead_code: false, + } + } + + // Used with debug_assert!, ensures that the block does not have any leftovers. + fn is_reset(&self) -> bool { + self.block.variables.is_empty() + && self.block.instructions.is_empty() + && self.block.merge_block.is_none() + && self.block.block1.is_none() + && self.block.block2.is_none() + && self.block.case_blocks.is_empty() + && self.block.input.is_none() + && !self.is_merge_block + && !self.new_instructions_are_dead_code + } + + fn reset(&mut self) { + self.block.input = None; + self.is_merge_block = false; + self.new_instructions_are_dead_code = false; + + debug_assert!(self.is_reset()); + } + + fn split_merge_block(&mut self) -> Option { + if let Some(merge_block) = self.block.merge_block.take() { + Some(IntermediateBlock { + block: *merge_block, + is_merge_block: true, + new_instructions_are_dead_code: self.new_instructions_are_dead_code, + }) + } else { + None + } + } +} + +// Helper to construct the CFG of a function. +#[cfg_attr(debug_assertions, derive(Debug))] +struct CFGBuilder { + // The current block that is being built. Once the block is complete it will be pushed to the + // `interm_blocks` stack if necessary + // + // Note that `current_block` is logically the top of `interm_block` stack, but is created + // separately to avoid lots of `panic!`s as otherwise Rust doesn't know there is always at + // least one element on the stack. + current_block: IntermediateBlock, + // The blocks of the CFG that is being built. Once a function is complete, this stack + // should be empty. + interm_blocks: Vec, +} + +impl CFGBuilder { + fn new() -> CFGBuilder { + CFGBuilder { current_block: IntermediateBlock::new(), interm_blocks: Vec::new() } + } + + fn clear(&mut self) { + let _ = std::mem::replace(&mut self.current_block, IntermediateBlock::new()); + self.interm_blocks.clear(); + } + + fn is_empty(&self) -> bool { + self.current_block.is_reset() && self.interm_blocks.is_empty() + } + + // When a new GLSL block is encountered that affects the control flow (body of a function, true + // or false block of an if, etc), `current_block` starts off as a non-merge block. + // + // If the GLSL block finishes without divergence, `current_block` remains as non-merged. If + // the GLSL block diverges, `current_block` is pushed onto stack and a new non-merge + // `current_block` is created. Once merged (for example end of `if`) a new merge + // `current_block` is created. This may happen multiple times, resulting in a set of nodes on + // the stack and one node as `current_block`. + // + // Note again that `current_block` is logically the top element of the stack. Once the GLSL + // block finishes, the stack (including `current_block`) is traversed until a non-merge block + // is found; the blocks that are popped in the process are chained via their `merge_block`. + // The non-merge block itself is then placed where appropriate, (such as Function::entry, + // Block::block1 of top of stack, etc) + // + // For `for` and `while` loops, before the condition is processed, `current_block` is pushed to + // the stack and a new non-merge block is created (because it needs to be executed multiple + // times), which will contain the condition only. For `for` loops if there is a continue + // expression, similarly `current_block` is pushed to the stack and a new non-merge block is + // created. Once the loop is finished, not only is the body popped but also the continue and + // condition blocks. + // + // For `do-while` loops, the only difference is that the condition block is placed on top of + // the body block instead of under. + + fn take_block(block: &mut IntermediateBlock) -> IntermediateBlock { + std::mem::replace(block, IntermediateBlock::new()) + } + + // Push a new non-merge block on the stack + fn push_block(&mut self) { + debug_assert!(self.current_block.block.is_terminated()); + self.interm_blocks.push(Self::take_block(&mut self.current_block)); + self.current_block.reset(); + } + + // Extract a chain of merge blocks until a non-merge block is reached. The blocks are linked + // together by their `merge_block`. + fn pop_block(&mut self) -> Block { + debug_assert!(self.current_block.block.is_terminated()); + let mut result = Self::take_block(&mut self.current_block); + + while result.is_merge_block { + let mut parent_block = self.interm_blocks.pop().unwrap(); + parent_block.block.set_merge_block(result.block); + result = parent_block; + } + + result.block + } + + // Restore a block as the current block, possible during constant folding. The builder assumes + // intermediate blocks are not yet merged into chains (if needed), but pop_block would do just + // that. When restoring the block as the current block, undo that chaining of blocks to keep + // the builder logic simpler. + fn restore_block_as_current(&mut self, mut block: IntermediateBlock) { + debug_assert!(self.current_block.is_reset()); + + while let Some(merge_block) = block.split_merge_block() { + self.interm_blocks.push(block); + block = merge_block; + } + self.current_block = block; + } + + fn are_new_instructions_dead_code_in_current_block(&self) -> bool { + self.current_block.new_instructions_are_dead_code + } + + fn are_new_instructions_dead_code_in_parent_block(&self) -> bool { + self.interm_blocks.last().unwrap().new_instructions_are_dead_code + } + + fn add_variable_declaration(&mut self, variable_id: VariableId) { + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.add_variable_declaration(variable_id); + } + } + + // Add an instruction to the current block. This may be a break, continue, return or discard, + // in which case the block terminates early. If another instruction is added after the block + // is terminated, it is dropped as dead-code. + fn add_void_instruction(&mut self, op: OpCode) { + if !self.current_block.new_instructions_are_dead_code { + if matches!(op, OpCode::Discard | OpCode::Return(_) | OpCode::Break | OpCode::Continue) + { + self.current_block.new_instructions_are_dead_code = true; + } + + self.current_block.block.add_void_instruction(op); + } + } + fn add_typed_instruction(&mut self, id: RegisterId) { + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.add_register_instruction(id); + } + } + + fn begin_if_true_block(&mut self, condition: TypedId) { + // The current block should terminate with a jump based on the condition. It is pushed to + // the stack. + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.terminate(OpCode::If(condition)); + } + self.push_block(); + } + + fn end_if_body_block_common( + &mut self, + merge_param: Option, + set_block: &SetBlock, + ) where + SetBlock: Fn(&mut Block, Block), + { + if !self.current_block.block.is_terminated() { + self.current_block.block.terminate(OpCode::Merge(merge_param)); + } else { + debug_assert!(!matches!( + self.current_block.block.get_terminating_op(), + OpCode::NextBlock + )); + } + let true_or_false_block = self.pop_block(); + if !self.are_new_instructions_dead_code_in_parent_block() { + set_block(&mut self.interm_blocks.last_mut().unwrap().block, true_or_false_block); + } + } + + fn end_if_true_block(&mut self, merge_param: Option) { + // Take the block and set it as the true block of the previously pushed if header block. + self.end_if_body_block_common(merge_param, &|if_block, true_block| { + if_block.set_if_true_block(true_block) + }); + } + + fn begin_if_false_block(&mut self) { + // The true block of the block is already processed, so there is nothing in the + // `current_block`, and it's ready to record the instructions of the false block already. + debug_assert!(self.current_block.is_reset()); + } + + fn end_if_false_block(&mut self, merge_param: Option) { + // Take the block and set it as the false block of the previously pushed if header block. + self.end_if_body_block_common(merge_param, &|if_block, false_block| { + if_block.set_if_false_block(false_block) + }); + } + + // Return whether an already terminated if block is empty with no operations; that is it has a + // single instruction and it is a Merge instruction with no parameter. If there are any + // variable declarations but no instructions, the variable declarations can safely be dropped. + // + // Note: we could potentially follow the chain of NextBlocks to such a block if all the + // intermediate blocks are also empty, if such a chain is ever generated. + fn is_no_op_merge_block(block: &Option>) -> bool { + block + .as_ref() + .map(|block| { + block.instructions.len() == 1 + && matches!(block.get_terminating_op(), OpCode::Merge(None)) + }) + .unwrap_or(true) + } + + fn end_if(&mut self, input: Option) -> Option { + // The true and else blocks have been processed. The header of the if is already at the + // top of the stack. Prepare a merge block to continue what comes after the if. + // + // If the entire `if` was dead-code eliminated however, restore the previous (already + // terminated) block + if self.are_new_instructions_dead_code_in_parent_block() { + self.current_block = self.interm_blocks.pop().unwrap(); + return None; + } + + debug_assert!(self.current_block.is_reset()); + + // If the condition of the if is a constant, it can be constant-folded. + let mut if_block = self.interm_blocks.pop().unwrap(); + let if_condition = if_block.block.get_terminating_op().get_if_condition().id.get_constant(); + + match if_condition { + Some(condition) => { + // Remove the if instruction from the block and revive it as the current block. + if_block.block.unterminate(); + self.restore_block_as_current(if_block); + + let true_block = self.current_block.block.block1.take(); + let false_block = self.current_block.block.block2.take(); + + // Append the true or false block based on condition. At the same time, + // replace the `input` id with the parameter of the block that is replacing the + // if. + self.const_fold_if_with_block(if condition == CONSTANT_ID_TRUE { + true_block + } else { + false_block + }) + } + None => { + // Not a constant, see if both the true and false blocks are empty. + let true_block_empty = Self::is_no_op_merge_block(&if_block.block.block1); + let false_block_empty = Self::is_no_op_merge_block(&if_block.block.block2); + + if true_block_empty && false_block_empty { + // If both blocks are empty, eliminate the if entirely. + if_block.block.unterminate(); + self.restore_block_as_current(if_block); + self.current_block.block.block1.take(); + self.current_block.block.block2.take(); + None + } else { + // Need to keep the if block as-is, push it back and make the current block a + // merge block. + self.interm_blocks.push(if_block); + self.current_block.is_merge_block = true; + self.current_block.block.input = input.map(|id| id.as_register_id()); + None + } + } + } + } + + fn const_fold_if_with_block(&mut self, block: Option>) -> Option { + match block { + Some(block) => { + // Make the current block jump to this block. + self.current_block.block.terminate(OpCode::NextBlock); + self.push_block(); + + self.restore_block_as_current(IntermediateBlock { + block: *block, + is_merge_block: true, + new_instructions_are_dead_code: self + .are_new_instructions_dead_code_in_parent_block(), + }); + + // If there was a merge parameter, replace the merge input with this id directly. + let last_block = self.current_block.block.get_merge_chain_last_block_mut(); + let terminating_op = last_block.get_terminating_op(); + if matches!(terminating_op, OpCode::Merge(..)) { + let merge_param = terminating_op.get_merge_parameter(); + last_block.unterminate(); + merge_param + } else { + // If the terminating op is not a merge, the rest of this block is going to be + // dead code. + self.current_block.new_instructions_are_dead_code = true; + None + } + } + None => { + // The if should be entirely eliminated, as there is nothing to replace it with. + // For example, `if (false) { only_true_block(); }`. + // + // The if header (code leading to the if) is already set as `current_block` and + // unterminated, so there is nothing to do. + None + } + } + } + + fn begin_loop_condition(&mut self) { + // Loops have a condition to evaluate every time, so a new block is created for that. + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.terminate(OpCode::Loop); + } + self.push_block(); + } + + fn end_loop_condition_common(&mut self, condition: TypedId) { + // There cannot be control flow in the condition expression, so this block must always be + // alive. + debug_assert!(!self.current_block.new_instructions_are_dead_code); + self.current_block.block.terminate(OpCode::LoopIf(condition)); + let mut condition_block = self.pop_block(); + + if !self.are_new_instructions_dead_code_in_parent_block() { + // GLSL supports such a construct: + // + // while (bool var = ...) { use(var); } + // + // To support this, pull the variable declaration to the parent scope so it's not + // declared only in the condition block. + let loop_block = &mut self.interm_blocks.last_mut().unwrap().block; + loop_block.variables.append(&mut std::mem::take(&mut condition_block.variables)); + loop_block.set_loop_condition_block(condition_block); + } + } + + fn end_loop_condition(&mut self, condition: TypedId) { + self.end_loop_condition_common(condition); + + // Body of the loop is recorded in the current (empty) block. + debug_assert!(self.current_block.is_reset()); + } + + fn end_loop_continue(&mut self) { + // There cannot be control flow in the continue expression, so this block must always be + // alive. + debug_assert!(!self.current_block.new_instructions_are_dead_code); + self.current_block.block.terminate(OpCode::Continue); + + let continue_block = self.pop_block(); + + if !self.are_new_instructions_dead_code_in_parent_block() { + self.interm_blocks.last_mut().unwrap().block.set_loop_continue_block(continue_block); + } + } + + fn end_loop(&mut self) { + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.terminate(OpCode::Continue); + } + + // Retrieve and set the body block of the loop. The header of the loop is already at the + // top of the stack. Prepare a merge block to continue what comes after the loop. + // + // If the entire loop was dead-code eliminated however, restore the previous (already + // terminated) block. + let body_block = self.pop_block(); + + if self.are_new_instructions_dead_code_in_parent_block() { + self.current_block = self.interm_blocks.pop().unwrap(); + return; + } + + debug_assert!(self.current_block.is_reset()); + + // If the condition of the loop is a constant false, it can be constant-folded. + let mut loop_block = self.interm_blocks.pop().unwrap(); + let loop_condition = loop_block + .block + .loop_condition + .as_ref() + .unwrap() + .get_merge_chain_terminating_op() + .get_loop_condition() + .id + .get_constant(); + + match loop_condition { + Some(condition) if condition == CONSTANT_ID_FALSE => { + // Remove the loop instruction from the block and revive it as the current block. + loop_block.block.unterminate(); + self.restore_block_as_current(loop_block); + + // Remove the condition block. + self.current_block.block.loop_condition.take(); + + // Remove the continue block that might have been added, if any. + debug_assert!(self.current_block.block.block1.is_none()); + self.current_block.block.block2.take(); + } + _ => { + // Not a constant false, push the loop block back and make the current block a + // merge block. + loop_block.block.set_loop_body_block(body_block); + + self.interm_blocks.push(loop_block); + self.current_block.is_merge_block = true; + } + } + } + + fn begin_do_loop(&mut self) { + // Insert a new block for the body of the do-loop. + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.terminate(OpCode::DoLoop); + } + self.push_block(); + } + + fn begin_do_loop_condition(&mut self) { + // Retrieve and set the body block of the do-loop. The header of the do-loop is already at + // the top of the stack. + if !self.current_block.block.is_terminated() { + self.current_block.block.terminate(OpCode::Continue); + } + let body_block = self.pop_block(); + + if !self.are_new_instructions_dead_code_in_parent_block() { + self.interm_blocks.last_mut().unwrap().block.set_loop_body_block(body_block); + } + + // Loops have a condition to evaluate every time, which is recorded in the current (empty) + // block. + debug_assert!(self.current_block.is_reset()); + } + + fn end_do_loop(&mut self, condition: TypedId) { + self.end_loop_condition_common(condition); + + // Prepare a merge block to continue what comes after the do-loop. If the entire do-loop + // was dead-code eliminated however, restore the previous (already terminated) block. + if self.are_new_instructions_dead_code_in_parent_block() { + self.current_block = self.interm_blocks.pop().unwrap(); + return; + } + + // Make the current block a merge block. + debug_assert!(self.current_block.is_reset()); + self.current_block.is_merge_block = true; + } + + fn begin_switch(&mut self, value: TypedId) { + // Insert a new block for the first case. + if !self.current_block.new_instructions_are_dead_code { + self.current_block.block.terminate(OpCode::Switch(value, Vec::new())); + } + self.push_block(); + } + + fn is_empty_switch_block(block: &Block) -> bool { + if let OpCode::Switch(_, cases) = block.get_terminating_op() { + cases.is_empty() + } else { + false + } + } + + fn end_previous_case(&mut self) { + if !self.are_new_instructions_dead_code_in_parent_block() { + // If this was the very first `case` in the switch, there is no previous case to end. + let is_first_block = + Self::is_empty_switch_block(&self.interm_blocks.last().unwrap().block); + + if !is_first_block { + // If the block is terminated, nothing to do, just add it to the list of switch's + // case blocks. If it isn't terminated, terminate it with a `Passthrough` first. + // + if !self.current_block.block.is_terminated() { + self.current_block.block.terminate(OpCode::Passthrough); + } + + let mut case_block = self.pop_block(); + if !self.are_new_instructions_dead_code_in_parent_block() { + // GLSL supports declaring a variable in one case and using it in another: + // + // switch (..) { + // case 0: + // int i = 0; + // default: + // output = i; + // } + // + // To support this, pull the variable declaration to the parent scope so it's + // not declared only in one case block. + let switch_block = &mut self.interm_blocks.last_mut().unwrap().block; + switch_block.variables.append(&mut std::mem::take(&mut case_block.variables)); + switch_block.add_switch_case_block(case_block); + } + } + } + } + + fn begin_case_impl(&mut self, value: Option) { + // Add the value to the switch's case blocks. + if !self.are_new_instructions_dead_code_in_parent_block() { + // But first, terminate the previous case, if any and not already. + self.end_previous_case(); + + self.interm_blocks + .last_mut() + .unwrap() + .block + .get_terminating_op_mut() + .add_switch_case(value); + } + } + + fn begin_case(&mut self, value: TypedId) { + self.begin_case_impl(value.id.get_constant()); + } + + fn begin_default(&mut self) { + self.begin_case_impl(None); + } + + // Check if the switch in the block at the top the stack has a matching case (e.g. if it uses a + // constant expression) and what the matching block is (if any). + fn switch_has_matching_case(switch_block: &mut Block) -> (bool, Option) { + let (switch_expr, switch_cases) = + switch_block.get_terminating_op().get_switch_expression_and_cases(); + + // If there are no cases, the switch is a no-op + if switch_cases.is_empty() { + return (false, None); + } + + // If the expression is constant, but no matching cases (or default) exists, the switch is + // a no-op. + if let Some(switch_expr) = switch_expr.id.get_constant() { + // First check if there's an exact match + let any_exact = switch_cases + .iter() + .position(|case| case.map(|case_id| case_id == switch_expr).unwrap_or(false)); + if any_exact.is_some() { + return (true, any_exact); + } + // Otherwise, check if there's a `default`: + let any_default = switch_cases.iter().position(|case| case.is_none()); + return (any_default.is_some(), any_default); + } + + // Expression is not a constant, assume the switch is not no-op. + (true, None) + } + + fn end_switch(&mut self) { + // Terminate the last case, if not already. + self.end_previous_case(); + + // The case blocks have already been processed. The header of the switch is already at the + // top of the stack. Prepare a merge block to continue what comes after the switch. + // + // If the entire `switch` was dead-code eliminated however, restore the previous (already + // terminated) block + if self.are_new_instructions_dead_code_in_parent_block() { + self.current_block = self.interm_blocks.pop().unwrap(); + return; + } + + debug_assert!(self.current_block.is_reset()); + + let mut switch_block = self.interm_blocks.pop().unwrap(); + + // If the last block didn't explicitly `break`, it is terminated with `Passthrough`. Fix + // that up to become `Break`. + if let Some(last_case_block) = switch_block.block.case_blocks.last_mut() { + let last_case_block = last_case_block.get_merge_chain_last_block_mut(); + if matches!(last_case_block.get_terminating_op(), OpCode::Passthrough) { + last_case_block.unterminate(); + last_case_block.terminate(OpCode::Break); + } + } + + // There are a couple of possibilities to constant fold the switch: + // + // - The switch has no cases: In this case, it can simply be removed. + // - The switch has a constant expression, but none of the cases match it: In this case, the + // switch can be removed as well. + // - The switch has a constant expression with a matching case: In this case, the + // non-matching cases (that also cannot be fallen-through) can be removed. Note that + // sometimes the entire switch can be replaced with the matching blocks, but it can get + // tricky with break and continue in it. + + let (has_matching_case, matching_block_index) = + Self::switch_has_matching_case(&mut switch_block.block); + if !has_matching_case { + // Remove the switch instruction from the block and revive it as the current block. + switch_block.block.case_blocks.clear(); + switch_block.block.unterminate(); + self.restore_block_as_current(switch_block); + } else { + // If the switch expression is constant, remove the case blocks that cannot be executed + if let Some(matching_block_index) = matching_block_index { + let case_blocks = std::mem::take(&mut switch_block.block.case_blocks); + + // Starting from the matching block, take blocks while their terminator is + // `Passthrough` and then the final block with a different terminator. Note that + // take_while stops _after_ the first element that doesn't match the predicate, + // i.e. that element is lost. Because of that, the first element after + // `Passthrough` is also matched. + let mut iter = case_blocks.into_iter().skip(matching_block_index); + let mut matching_case_block = iter.next().unwrap(); + let mut fallthrough_chain_last_block = + matching_case_block.get_merge_chain_last_block_mut(); + + for fallthrough_block in iter { + // If the previous block was fallthrough, chain this block to it. Otherwise + // this block and all after it are unreachable. + if !matches!( + fallthrough_chain_last_block.get_terminating_op(), + &OpCode::Passthrough + ) { + break; + } + + fallthrough_chain_last_block.unterminate(); + fallthrough_chain_last_block.terminate(OpCode::NextBlock); + fallthrough_chain_last_block.set_merge_block(fallthrough_block); + fallthrough_chain_last_block = + fallthrough_chain_last_block.get_merge_chain_last_block_mut(); + } + + let (switch_expression, switch_cases) = + switch_block.block.get_terminating_op().get_switch_expression_and_cases(); + let matching_case = switch_cases[matching_block_index]; + // Replace the switch with one that has only one target, that is the matching case. + switch_block.block.unterminate(); + switch_block + .block + .terminate(OpCode::Switch(switch_expression, vec![matching_case])); + switch_block.block.case_blocks = vec![matching_case_block]; + } + + // The switch has to remain (whether constant or not), push it back and make the + // current block a merge block. + self.interm_blocks.push(switch_block); + self.current_block.is_merge_block = true; + } + } +} + +// A helper to build the IR from scratch. The helper is invoked while parsing the shader, and +// its main purpose is to maintain in-progress items until completed, and adapt the incoming GLSL +// syntax to the IR. +pub struct Builder { + // The IR being built + ir: IR, + + // Flags controlling the IR generation + options: Options, + + // The current function that is being built (if any). + current_function: Option, + + // The CFG of the current function being built, if any. + current_function_cfg: CFGBuilder, + + // The CFG of the initialization code of global variables. + // + // Global variables can either be initialized with constants or non-constant expressions. If + // initialized with a constant, the Variable::initializer can be used, but that's impossible + // with non-constant initializers; there may be complex code (with multiple instructions) to + // execute before that can happen. To support that, when code is encountered in the global + // scope, it is generated in `global_initializers_cfg` and when it's assigned to a variable, + // a Store op is added to the top block of the cfg. + // + // At the end of parsing, this is prepended to the CFG of main(). + global_initializers_cfg: CFGBuilder, + + // Stack of intermediate values. As the parser observes expressions, it pushes them on the + // stack. When these intermediate expressions are combined in an operation, the corresponding + // operation is popped off the stack. The exact number of ids to pop depends on the + // instruction. + // + // This stack should be empty after every statement in a GLSL block is completely processed. + // It should also be empty at the end of every Block. + interm_ids: Vec, + + // gl_ClipDistance and gl_CullDistance may be sized after `.length()` is called on them. To + // support this, a global variable is created to hold that yet-to-be-determined constant. When + // the size of gl_ClipDistance and gl_CullDistance is determined, that variable is initialized + // with it. + gl_clip_distance_length_var_id: Option, + gl_cull_distance_length_var_id: Option, +} + +impl Builder { + pub fn new(shader_type: ShaderType, options: Options) -> Builder { + Builder { + ir: IR::new(shader_type), + options, + current_function: None, + current_function_cfg: CFGBuilder::new(), + global_initializers_cfg: CFGBuilder::new(), + interm_ids: Vec::new(), + gl_clip_distance_length_var_id: None, + gl_cull_distance_length_var_id: None, + } + } + + // Called at the end of the shader to finalize it. Notably, this moves the cached global + // initialization code to the beginning of `main()`. + pub fn finish(&mut self) { + debug_assert!(self.ir.meta.get_main_function_id().is_some()); + + if !self.global_initializers_cfg.is_empty() { + self.global_initializers_cfg.current_block.block.terminate(OpCode::NextBlock); + let global_init_block = self.global_initializers_cfg.pop_block(); + self.ir.prepend_to_main(global_init_block); + } + + // Instantly dead-code-eliminate unreachable functions. + let function_decl_order = + util::calculate_function_decl_order(&self.ir.meta, &self.ir.function_entries); + let function_count = self.ir.function_entries.len(); + // Take all entry blocks out ... + let mut function_entries = std::mem::take(&mut self.ir.function_entries); + self.ir.function_entries.resize_with(function_count, || None); + // ... and only place back the ones that are reachable from `main` (i.e. are in the DAG). + for function_id in function_decl_order { + let id = function_id.id as usize; + self.ir.function_entries[id] = function_entries[id].take(); + } + + // `main()` is always reachable from `main()`! + debug_assert!( + self.ir.function_entries[self.ir.meta.get_main_function_id().unwrap().id as usize] + .is_some() + ); + } + + // Called at the end of the shader after it has failed validation. At this point, the IR is no + // longer going to be used and is likely in a half-baked state, discard everything. + pub fn fail(&mut self) { + self.current_function_cfg.clear(); + self.global_initializers_cfg.clear(); + self.interm_ids.clear(); + let shader_type = self.ir.meta.get_shader_type(); + let _ = std::mem::replace(&mut self.ir, IR::new(shader_type)); + } + + // Get a reference to the IR for direct access, such as for doing type look up etc, avoiding + // the need for a set of forwarding functions. + pub fn ir(&mut self) -> &mut IR { + &mut self.ir + } + pub fn take_ir(&mut self) -> IR { + std::mem::replace(&mut self.ir, IR::new(ShaderType::Vertex)) + } + + fn variable_is_private_and_can_be_initialized( + &self, + type_id: TypeId, + decorations: &Decorations, + built_in: Option, + ) -> bool { + let type_info = self.ir.meta.get_type(type_id); + debug_assert!(!type_info.is_pointer()); + + // Some variables cannot be initialized, like uniforms, inputs, etc. + !(type_info.is_image() + || type_info.is_unsized_array() + || built_in.is_some() + || decorations.has(Decoration::Input) + || decorations.has(Decoration::Output) + || decorations.has(Decoration::InputOutput) + || decorations.has(Decoration::Uniform) + || decorations.has(Decoration::Buffer) + || decorations.has(Decoration::Shared)) + } + + fn built_in_is_output(&self, built_in: BuiltIn) -> bool { + // gl_PrimitiveID is an output in geometry shaders, but input in tessellation and fragment + // shaders. gl_Layer is an output in geometry shaders, but input in vertex shaders (for + // multiview). + // + // gl_ClipDistance and gl_CullDistance are inputs in fragment shader, output otherwise. + // + // gl_TessLevelOuter and gl_TessLevelInner are outputs in tessellation control shaders, but + // input in tessellation evaluation shaders. + match built_in { + BuiltIn::FragColor + | BuiltIn::FragData + | BuiltIn::FragDepth + | BuiltIn::SecondaryFragColorEXT + | BuiltIn::SecondaryFragDataEXT + | BuiltIn::SampleMask + | BuiltIn::Position + | BuiltIn::PointSize + | BuiltIn::PrimitiveShadingRateEXT + | BuiltIn::BoundingBoxOES + | BuiltIn::PerVertexOut => true, + BuiltIn::PrimitiveID | BuiltIn::LayerOut => { + self.ir.meta.get_shader_type() == ShaderType::Geometry + } + BuiltIn::ClipDistance | BuiltIn::CullDistance => { + self.ir.meta.get_shader_type() != ShaderType::Fragment + } + BuiltIn::TessLevelOuter | BuiltIn::TessLevelInner => { + self.ir.meta.get_shader_type() == ShaderType::TessellationControl + } + _ => false, + } + } + + fn variable_is_output(&self, decorations: &Decorations, built_in: Option) -> bool { + decorations.has(Decoration::Output) + || built_in.is_some_and(|built_in| self.built_in_is_output(built_in)) + } + + // Internal helper to declare a new variable. + fn declare_variable( + &mut self, + name: Name, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + built_in: Option, + scope: VariableScope, + ) -> VariableId { + // The declared variable may be uninitialized. If the build flags indicate the need, + // the variable is marked such that it is zero-initialized before output generation. Note + // that function parameters are handled in declare_function_param. + let needs_zero_initialization = scope != VariableScope::FunctionParam + && ((self.options.initialize_uninitialized_variables + && self.variable_is_private_and_can_be_initialized( + type_id, + &decorations, + built_in, + )) + || (self.options.initialize_output_variables + && self.variable_is_output(&decorations, built_in)) + || (self.options.initialize_gl_position + && matches!(built_in, Some(BuiltIn::Position)))); + + let variable_id = self.ir.meta.declare_variable( + name, + type_id, + precision, + decorations, + built_in, + None, + scope, + ); + + // Add the variable to the list of local variables in this scope, if not global. Function + // parameters are part of the `Function` and so don't need to be explicitly marked as + // needing declaration. + if scope == VariableScope::Local { + self.current_function_cfg.add_variable_declaration(variable_id); + } + + if needs_zero_initialization { + self.ir.meta.require_variable_zero_initialization(variable_id); + } + + variable_id + } + + // Declare a built-in variable. Must have never been declared before. + pub fn declare_built_in_variable( + &mut self, + built_in: BuiltIn, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + ) -> VariableId { + // Note: the name of the built-in is not derived. For text-based generators, the name can + // be derived from the built-in enum, and the string is unnecessary. For SPIR-V, the name + // is unused. + // + // Built-ins are always globally declared. + self.declare_variable( + Name::new_exact(""), + type_id, + precision, + decorations, + Some(built_in), + VariableScope::Global, + ) + } + + // Declare an interface variable. Interface variables are special in that their name must be + // preserved in a predictable form for text-based generators. + pub fn declare_interface_variable( + &mut self, + name: &'static str, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + ) -> VariableId { + self.declare_variable( + Name::new_interface(name), + type_id, + precision, + decorations, + None, + VariableScope::Global, + ) + } + + // Declare a temporary variable. The name of this variable is kept as closely to the original + // as possible, but without any guarantees. + pub fn declare_temp_variable( + &mut self, + name: &'static str, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + ) -> VariableId { + let scope = if self.current_function.is_none() { + VariableScope::Global + } else { + VariableScope::Local + }; + + self.declare_variable(Name::new_temp(name), type_id, precision, decorations, None, scope) + } + + // Declare a const temporary variable. The name of this variable is ultimately unused. + pub fn declare_const_variable(&mut self, type_id: TypeId, precision: Precision) -> VariableId { + self.ir.meta.declare_const_variable(Name::new_temp(""), type_id, precision) + } + + // In GLSL, it's possible to mark a variable as invariant or precise in a separate line, + // especially useful for built-ins that are otherwise not necessarily declared explicitly. + // The following allow these declarations to add invariant and precise decorations. + fn mark_variable_invariant(&mut self, variable_id: VariableId) { + self.ir.meta.get_variable_mut(variable_id).decorations.add_invariant(); + } + fn mark_variable_precise(&mut self, variable_id: VariableId) { + self.ir.meta.get_variable_mut(variable_id).decorations.add_precise(); + } + + // When a function prototype is encountered, the following functions are called: + // + // return_type function (...) @new_function; + // + // If that is followed by the function definition, then the following functions are called: + // + // return_type function (type param, ...) @new_function/@update_function_param_names + // @begin_function + // { + // ... + // } + // @end_function + // + // Note that if the prototype is previously seen, `new_function` is not called again on + // definition because the function id is already known. Instead, `update_function_param_names` + // is called so the parameter names reflect that of the definition. + + pub fn new_function( + &mut self, + name: &'static str, + params: Vec, + return_type_id: TypeId, + return_precision: Precision, + return_decorations: Decorations, + ) -> FunctionId { + let function = + Function::new(name, params, return_type_id, return_precision, return_decorations); + let is_main = name == "main"; + + let id = self.ir.add_function(function); + + // If this is the main() function, remember its id. + if is_main { + self.ir.meta.set_main_function_id(id); + } + + id + } + pub fn update_function_param_names( + &mut self, + id: FunctionId, + param_names: &[&'static str], + ) -> Vec { + let function = self.ir.meta.get_function_mut(id); + let params = function.params.iter().map(|param| param.variable_id).collect::>(); + + debug_assert!(params.len() == param_names.len()); + + params.iter().zip(param_names.iter()).for_each(|(¶m, name)| { + self.ir.meta.get_variable_mut(param).name = Name::new_temp(name) + }); + + params + } + + // Start a new function to build. + pub fn begin_function(&mut self, id: FunctionId) { + debug_assert!(self.current_function_cfg.is_empty()); + self.current_function = Some(id); + } + + // Declare a parameter for the function that is being defined. Called for each parameters + // before calling `begin_function`. This is not done while parsing the prototype because if it + // isn't followed by a definition, there is no need to assign variable ids to them. + pub fn declare_function_param( + &mut self, + name: &'static str, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + direction: FunctionParamDirection, + ) -> VariableId { + let variable_id = self.declare_variable( + Name::new_temp(name), + type_id, + precision, + decorations, + None, + VariableScope::FunctionParam, + ); + + if self.options.initialize_uninitialized_variables + && direction == FunctionParamDirection::Output + { + self.ir.meta.require_variable_zero_initialization(variable_id); + } + + variable_id + } + + // Once the entire function body is visited, `end_function` puts the graph in the function. + pub fn end_function(&mut self) { + // End with a `return` in case not explicitly added. + if !self.scope().are_new_instructions_dead_code_in_current_block() { + let return_type_id = + self.ir.meta.get_function(self.current_function.unwrap()).return_type_id; + if return_type_id == TYPE_ID_VOID { + self.branch_return(); + } else { + // In GLSL, it's possible to miss the return statement from a function that returns + // a value. Generate a zero node. + let null_value = self.ir.meta.get_constant_null(return_type_id); + self.push_constant(null_value, return_type_id); + self.branch_return_value(); + } + } + + self.ir.set_function_entry( + self.current_function.unwrap(), + self.current_function_cfg.pop_block(), + ); + debug_assert!(self.current_function_cfg.is_empty()); + self.current_function = None; + + debug_assert!(self.interm_ids.is_empty()); + } + + // Many instructions are generated either as part of a function or the initialization code for + // global variables. The following function should be used so that the generated code is + // placed in the appropriate scope (function or global). + fn scope(&mut self) -> &mut CFGBuilder { + match self.current_function { + Some(_) => &mut self.current_function_cfg, + None => &mut self.global_initializers_cfg, + } + } + + // Used internally, loads an id from the top of the id stack. If that is a pointer, its value + // is loaded before returning. + fn load(&mut self) -> TypedId { + let to_load = self.interm_ids.pop().unwrap(); + + let result = instruction::load(&mut self.ir.meta, to_load); + self.add_instruction(result); + + // Actually return the loaded result instead of leaving it on the stack. + self.interm_ids.pop().unwrap() + } + + // Store the value at the top of the id stack into the pointer under it. + pub fn store(&mut self) { + let value = self.load(); + // The `a = b` expression is itself a value, and we use `a` to load that value back if + // used, so the pointer is kept on the stack. Note that the precision of a and b may be + // different, and if the result of a = b is used, the precision of a is the correct one + // (already on the stack!). + let pointer = *self.interm_ids.last().unwrap(); + + let result = instruction::store(&mut self.ir.meta, pointer, value); + self.add_instruction(result); + } + + // Use the value at the top of the id stack as the initializer for the given variable. If the + // initializer is a constant, it will be set in `Variable::initializer`. Otherwise similarly + // to `store()`, the non-constant expression is stored with `OpCode::Store` to be deferred to + // the beginning of `main()`. + pub fn initialize(&mut self, id: VariableId) { + let value = self.load(); + + // For some generators, non-const global variables cannot have an initializer. + let initializer_allowed = self.options.initializer_allowed_on_non_const_global_variables + || self.current_function.is_some() + || self.ir.meta.get_variable(id).is_const; + + if let Id::Constant(constant_id) = value.id + && initializer_allowed + { + self.ir.meta.set_variable_initializer(id, constant_id); + } else { + self.ir.meta.on_variable_initialized(id); + let id = TypedId::from_variable_id(&self.ir.meta, id); + self.scope().add_void_instruction(OpCode::Store(id, value)); + } + } + + // Flow control helpers. + + // For `if` support, the following functions are called at the specified points: + // + // if (condition) { + // @begin_if_true_block + // ... + // @end_if_true_block + // } else { + // @begin_if_false_block + // ... + // @end_if_false_block + // } + // @end_if + // + // In `begin_if_true_block`, the result of the `condition` is found at the top of the id stack. + pub fn begin_if_true_block(&mut self) { + // The condition must be at the top of the stack. + let condition = self.load(); + self.scope().begin_if_true_block(condition); + } + pub fn end_if_true_block(&mut self) { + self.scope().end_if_true_block(None); + } + pub fn begin_if_false_block(&mut self) { + self.scope().begin_if_false_block(); + } + pub fn end_if_false_block(&mut self) { + self.scope().end_if_false_block(None); + } + pub fn end_if(&mut self) { + self.scope().end_if(None); + } + + // Support for ?: is similar to if/else: + // + // (condition ? + // @begin_ternary_true_expression + // ... + // @end_ternary_true_expression : + // @begin_ternary_false_expression + // ... + // @end_ternary_false_expression) @end_ternary + // + // In `begin_if_true_expression`, the result of the `condition` is found at the top of the id + // stack. In `end_if_true_expression`, the merge parameter is found at the top of the id + // stack. In `end_if_false_expression`, the merge parameter is found at the top of the id + // stack. + // + // In the end, the result id is found in the input of the merge block of the if/else used to + // implement it. + // + // If the expressions are `void`, then end_ternary_true_expression_void, + // end_ternary_false_expression_void, and end_ternary_void are called. + pub fn begin_ternary_true_expression(&mut self) { + self.begin_if_true_block(); + } + pub fn end_ternary_true_expression(&mut self) { + let true_value = self.load(); + self.scope().end_if_true_block(Some(true_value)); + + // The result of the merge will have the same type as either of the true or false values. + // Push a new id with this type on the stack so that `end_ternary` would use it to declare + // the input of the merge block. + let new_id = + self.ir.meta.new_register(OpCode::MergeInput, true_value.type_id, true_value.precision); + self.interm_ids.push(TypedId::from_register_id(new_id)); + } + pub fn end_ternary_true_expression_void(&mut self) { + self.end_if_true_block(); + } + pub fn begin_ternary_false_expression(&mut self) { + self.begin_if_false_block(); + } + pub fn end_ternary_false_expression(&mut self) { + let false_value = self.load(); + self.scope().end_if_false_block(Some(false_value)); + + // Adjust the precision of the result which was inherited from the true value. + let result = &mut self.interm_ids.last_mut().unwrap(); + result.precision = + instruction::precision::higher_precision(result.precision, false_value.precision); + self.ir.meta.get_instruction_mut(result.id.get_register()).result.precision = + result.precision; + } + pub fn end_ternary_false_expression_void(&mut self) { + self.end_if_false_block(); + } + pub fn end_ternary(&mut self) { + let merge_input = self.interm_ids.pop().unwrap(); + let constant_folded_merge_input = self.scope().end_if(Some(merge_input)); + let result = constant_folded_merge_input.unwrap_or(merge_input); + self.interm_ids.push(TypedId::new(result.id, merge_input.type_id, merge_input.precision)); + } + pub fn end_ternary_void(&mut self) { + self.end_if(); + } + + // Short circuit support is implemented over ?: and uses the same mechanism: + // + // a || b == a ? true : b + // a && b == a ? b : false + // + // The following functions are called as specified below: + // + // a @begin_short_circuit_or || b @end_short_circuit_or + // a @begin_short_circuit_and && b @end_short_circuit_and + // + // In `begin_short_circuit_or/and`, the result of `a` is found at the of the id stack. + // In `end_short_circuit_or/and`, the result of `b` is found at the of the id stack. + pub fn begin_short_circuit_or(&mut self) { + self.begin_ternary_true_expression(); + self.push_constant_bool(true); + self.end_ternary_true_expression(); + self.begin_ternary_false_expression(); + } + pub fn end_short_circuit_or(&mut self) { + self.end_ternary_false_expression(); + self.end_ternary() + } + pub fn begin_short_circuit_and(&mut self) { + self.begin_ternary_true_expression(); + } + pub fn end_short_circuit_and(&mut self) { + self.end_ternary_true_expression(); + self.begin_ternary_false_expression(); + self.push_constant_bool(false); + self.end_ternary_false_expression(); + self.end_ternary() + } + + // For `while` and `for` support, the following functions are called at the specified points: + // + // while (@begin_loop_condition condition @end_loop_condition) { + // ... + // } + // @end_loop + // + // for (init; + // @begin_loop_condition condition @end_loop_condition; + // continue @end_loop_continue) { + // ... + // } + // @end_loop + // + // In `end_loop_condition`, the result of the `condition` is found at the top of the id stack. + pub fn begin_loop_condition(&mut self) { + self.scope().begin_loop_condition(); + } + pub fn end_loop_condition(&mut self) { + let condition = self.load(); + self.scope().end_loop_condition(condition); + } + pub fn end_loop_continue(&mut self) { + self.scope().end_loop_continue(); + } + pub fn end_loop(&mut self) { + self.scope().end_loop(); + } + + // For `do-while` support, the following functions are called at the specified points: + // + // do { @begin_do_loop + // ... + // @begin_do_loop_condition + // } while(condition); + // @end_do_loop + // + // In `end_do_loop`, the result of the `condition` is found at the top of the id stack. + pub fn begin_do_loop(&mut self) { + self.scope().begin_do_loop(); + } + pub fn begin_do_loop_condition(&mut self) { + self.scope().begin_do_loop_condition(); + } + pub fn end_do_loop(&mut self) { + let condition = self.load(); + self.scope().end_do_loop(condition); + } + + // For `switch` support, the following functions are called at the specified points: + // + // switch (value @begin_switch) { + // case N @begin_case: + // ... + // default @begin_default: + // ... + // ... + // } + // @end_switch + // + // In `begin_switch`, the result of the `value` is found at the top of the id stack. + // + // In `begin_case`, the value `N` is found at the top of the id stack. + // + // In `begin_case` or `end_switch`, if the previous case block is not already terminated, it + // will terminate with `Passthrough` to the next block. + pub fn begin_switch(&mut self) { + let value = self.load(); + self.scope().begin_switch(value); + } + pub fn begin_case(&mut self) { + let value = self.load(); + self.scope().begin_case(value); + } + pub fn begin_default(&mut self) { + self.scope().begin_default(); + } + pub fn end_switch(&mut self) { + self.scope().end_switch(); + } + + pub fn branch_discard(&mut self) { + self.add_instruction(instruction::branch_discard()); + } + pub fn branch_return(&mut self) { + self.add_instruction(instruction::branch_return(None)); + } + pub fn branch_return_value(&mut self) { + let value = self.load(); + self.add_instruction(instruction::branch_return(Some(value))); + } + pub fn branch_break(&mut self) { + self.add_instruction(instruction::branch_break()); + } + pub fn branch_continue(&mut self) { + self.add_instruction(instruction::branch_continue()); + } + + // Called when a constant expression used as an array size is evaluated. The result is found + // on the stack, but is not used by an instruction; it's returned to the parser instead. + pub fn pop_array_size(&mut self) -> u32 { + let size_id = self.interm_ids.pop().unwrap().id.get_constant().unwrap(); + // Use get_index() because the expression may either be int or uint, both of which are + // acceptable; get_index() returns a u32 for either case. + self.ir.meta.get_constant(size_id).value.get_index() + } + + // Called when a statement in a block is finished, but only if the statement has a value (i.e. + // leaves an id on the stack). + // + // statement; @end_statement_with_value + // + // or + // + // expression, @end_statement_with_value expression2 + // + pub fn end_statement_with_value(&mut self) { + // There _must_ be a value on the stack, unwrap() will assert that. + self.interm_ids.pop().unwrap(); + } + + fn push_id(&mut self, id: Id, type_id: TypeId, precision: Precision) { + self.interm_ids.push(TypedId::new(id, type_id, precision)); + } + + // Called when constant scalar values are visited. + fn push_constant(&mut self, id: ConstantId, type_id: TypeId) { + self.push_id(Id::new_constant(id), type_id, Precision::NotApplicable); + } + pub fn push_constant_float(&mut self, value: f32) { + let id = self.ir.meta.get_constant_float(value); + self.push_constant(id, TYPE_ID_FLOAT); + } + pub fn push_constant_int(&mut self, value: i32) { + let id = self.ir.meta.get_constant_int(value); + self.push_constant(id, TYPE_ID_INT); + } + pub fn push_constant_uint(&mut self, value: u32) { + let id = self.ir.meta.get_constant_uint(value); + self.push_constant(id, TYPE_ID_UINT); + } + pub fn push_constant_bool(&mut self, value: bool) { + let id = self.ir.meta.get_constant_bool(value); + self.push_constant(id, TYPE_ID_BOOL); + } + pub fn push_constant_yuv_csc_standard(&mut self, value: YuvCscStandard) { + let id = self.ir.meta.get_constant_yuv_csc_standard(value); + self.push_constant(id, TYPE_ID_YUV_CSC_STANDARD); + } + + // Called when a variable is visited. + pub fn push_variable(&mut self, id: VariableId) { + let variable = self.ir.meta.get_variable(id); + let type_id = variable.type_id; + let precision = variable.precision; + + debug_assert!(self.ir.meta.get_type(type_id).is_pointer()); + + // If the variable is a constant, replace it with its constant value but with the + // variable's precision. While constants are not associated with a precision, const + // variables are. As a result, the resulting TypedId when this value is load()ed will be a + // constant but with a precision, which affects the precision of other intermediate ops. + if variable.is_const { + debug_assert!(variable.initializer.is_some()); + debug_assert!( + self.ir.meta.get_type(type_id).get_element_type_id().unwrap() + == self.ir.meta.get_constant(variable.initializer.unwrap()).type_id + ); + + let constant_id = variable.initializer.unwrap(); + let pointee_type_id = self.ir.meta.get_constant(constant_id).type_id; + self.push_id(Id::new_constant(constant_id), pointee_type_id, precision) + } else { + // Mark the variable as statically used during parse. This _has_ to be done during + // parse because static use in dead code is still considered static use by GLSL. + self.ir.meta.get_variable_mut(id).is_static_use = true; + self.push_id(Id::new_variable(id), type_id, precision) + } + } + + // Depending on whether the instruction::* function returned a Constant, Void or Register, + // either add a void or typed instruction (if necessary) and push a value to the stack (if + // necessary). + fn add_instruction(&mut self, result: instruction::Result) { + match result { + instruction::Result::Constant(id) => { + self.interm_ids.push(TypedId::from_typed_constant_id(id)) + } + instruction::Result::Void(op) => self.scope().add_void_instruction(op), + instruction::Result::Register(id) => { + self.scope().add_typed_instruction(id.id); + self.interm_ids.push(TypedId::from_register_id(id)) + } + instruction::Result::NoOp(id) => self.interm_ids.push(id), + }; + } + + // Helper to get N arguments off the stack in the right order. + fn get_args(n: usize, mut load: Load) -> Vec + where + Load: FnMut() -> T, + { + let mut args: Vec<_> = (0..n).map(|_| load()).collect(); + args.reverse(); + args + } + + // Called when a user-defined function is called + pub fn call_function(&mut self, id: FunctionId) { + let arg_count = self.ir.meta.get_function(id).params.len(); + + // Collect the call arguments. + // + // Note: The function parameters are not load()ed because they may be `out` or `inout`, + // i.e. they could be pointers. + let args = Self::get_args(arg_count, || self.interm_ids.pop().unwrap()); + let result = instruction::call(&mut self.ir.meta, id, args); + self.add_instruction(result); + } + + // A generic helper to make an assignment operator with an op (like +=). The rhs operand of + // the binary operator is found at the top of the stack, and the lhs operand is found under it. + fn assign_and_op(&mut self, op: Op) + where + Op: FnOnce(&mut Self), + { + // X op= Y is calculated as X = X op Y. This is implemented by `Temp = X op Y`, followed + // by `X = Temp`. As a preparation, duplicate lhs on the stack so existing functions can + // be used. + let rhs = self.interm_ids.pop().unwrap(); + let lhs = *self.interm_ids.last().unwrap(); + self.interm_ids.push(lhs); + self.interm_ids.push(rhs); + + // Create the op instruction followed by a store to lhs. + op(self); + self.store(); + } + + // Called when a component of a vector is taken, like `vector.y`. + // + // The vector being indexed is expected to be found at the top of the stack. + pub fn vector_component(&mut self, component: u32) { + let vector = self.interm_ids.pop().unwrap(); + let result = instruction::vector_component(&mut self.ir.meta, vector, component); + self.add_instruction(result); + } + + // Called when multiple components of a vector are taken, like `vector.yxy`. + // + // The vector being indexed is expected to be found at the top of the stack. + pub fn vector_component_multi(&mut self, components: Vec) { + let vector = self.interm_ids.pop().unwrap(); + + let result = instruction::vector_component_multi(&mut self.ir.meta, vector, components); + self.add_instruction(result); + } + + // Called when an array-like index is taken: + // + // - vector[expr] + // - matrix[expr] + // - array[expr] + // + // The index is expected to be found at the top of the stack, followed by the expression being + // indexed. + pub fn index(&mut self) { + let index = self.load(); + let indexed = self.interm_ids.pop().unwrap(); + + let result = instruction::index(&mut self.ir.meta, indexed, index); + self.add_instruction(result); + } + + // Called when a field of a struct is selected, like `block.field`. + // + // The struct whose field is being selected is expected to be found at the top of the stack. + pub fn struct_field(&mut self, field_index: u32) { + let struct_id = self.interm_ids.pop().unwrap(); + + let result = instruction::struct_field(&mut self.ir.meta, struct_id, field_index); + self.add_instruction(result); + } + + fn trim_constructor_args_to_component_count( + &mut self, + args: Vec, + count: u32, + ) -> Vec { + // To simplify this, do a first pass where matrix arguments are split by column. This lets + // the following code simply deal with scalars and vectors. + let mut matrix_expanded_args = Vec::new(); + for id in args { + let type_info = self.ir.meta.get_type(id.type_id); + + if let &Type::Matrix(_, column_count) = type_info { + for row in 0..column_count { + self.interm_ids.push(id); + self.interm_ids.push(TypedId::from_constant_id( + self.ir.meta.get_constant_uint(row), + TYPE_ID_UINT, + )); + self.index(); + matrix_expanded_args.push(self.load()); + } + } else { + matrix_expanded_args.push(id); + } + } + + let mut result = Vec::new(); + let mut total = 0; + + for id in matrix_expanded_args { + let type_info = self.ir.meta.get_type(id.type_id); + + if let &Type::Scalar(..) = type_info { + // Scalar values add a single component, take them directly. + result.push(id); + total += 1; + } else if let &Type::Vector(_, vec_size) = type_info { + // If the vector is entirely consumed, take it directly. Otherwise only take + // enough components to fulfill the given `count`. + let needed_components = count - total; + if needed_components >= vec_size { + result.push(id); + total += vec_size; + } else { + self.interm_ids.push(id); + if needed_components == 1 { + self.vector_component(0); + } else { + self.vector_component_multi((0..needed_components).collect()); + } + result.push(self.load()); + total = count; + } + } + + debug_assert!(total <= count); + if total >= count { + break; + } + } + + result + } + + // Trim extra arguments passed to a constructor. This is only possible with a vector and + // matrix constructor. + // + // Constructing a matrix from another matrix is special, the input matrix may have more or + // fewer components. So matNxM(m) is not trimmed by this function. + // + // Additionally, array and struct constructors require an exact match of arguments, so no + // stripping is done. + fn trim_constructor_args(&mut self, type_id: TypeId, args: Vec) -> Vec { + let type_info = self.ir.meta.get_type(type_id); + + match type_info { + // Nothing to do for arrays and structs + Type::Array(..) | Type::Struct(..) => { + return args; + } + // Early out for matrix-from-matrix constructors. + Type::Matrix(..) if args.len() == 1 => { + return args; + } + _ => (), + } + + let total_components = type_info.get_total_component_count(&self.ir.meta); + self.trim_constructor_args_to_component_count(args, total_components) + } + + // Called when a constructor is used, like `vec(a, b, c)`. Constructors take many + // forms, including having more parameters than needed. This function corrects that by taking + // the appropriate number of parameters. The following are examples of each form: + // + // - float(f), vecN(vN), matNxM(mNxM): Replaced with just f, vN and mNxM respectively + // - float(v): Replaced with float(v.x) + // - float(m): Replaced with m[0][0] + // - vecN(f) + // - vecN(v1.zy, v2.xzy): If number of components exceeds N, extra components are stripped, such + // as vecN(v1.zy, v2.x) + // - vecN(m) + // - matNxM(f) + // - matNxM(m) + // - matNxM(v1.zy, v2.x, ...): Similarly to constructing a vector, extra components are + // stripped. + // - array(elem0, elem1, ...) + // - Struct(field0, field1, ...) + // + // The arguments of the constructor are found on the stack in reverse order. + pub fn construct(&mut self, type_id: TypeId, arg_count: usize) { + // Collect the constructor arguments. + let args = Self::get_args(arg_count, || self.load()); + + // In the case of ConstructVectorFromMultiple and ConstructMatrixFromMultiple, there may be + // more components in the parameters than the constructor needs. In this step, these + // components are removed. Other constructor kinds are unaffected. + // + // Note: this can affect the precision of the result if the stripped args would have + // increased the end precision. This is such a niche case that we're ignoring it for + // simplicity. + let args = self.trim_constructor_args(type_id, args); + + let result = instruction::construct(&mut self.ir.meta, type_id, args); + self.add_instruction(result); + } + + fn declare_clip_cull_distance_array_length_variable( + &mut self, + existing_id: Option, + name: &'static str, + ) -> VariableId { + existing_id.unwrap_or_else(|| { + let name = Name::new_temp(name); + self.declare_variable( + name, + TYPE_ID_INT, + Precision::Low, + Decorations::new_none(), + None, + VariableScope::Global, + ) + }) + } + + fn on_gl_clip_cull_distance_sized( + &mut self, + id: VariableId, + length: u32, + length_variable: Option, + ) { + let type_id = self.ir.meta.get_variable(id).type_id; + let type_info = self.ir.meta.get_type(type_id); + debug_assert!(type_info.is_pointer()); + + let type_id = type_info.get_element_type_id().unwrap(); + let type_info = self.ir.meta.get_type(type_id); + debug_assert!(type_info.is_unsized_array()); + + let element_type_id = type_info.get_element_type_id().unwrap(); + let sized_type_id = self.ir.meta.get_array_type_id(element_type_id, length); + let sized_type_id = self.ir.meta.get_pointer_type_id(sized_type_id); + + // Update the type of the variable. + self.ir.meta.get_variable_mut(id).type_id = sized_type_id; + + if let Some(length_variable_id) = length_variable { + let length = self.ir.meta.get_constant_int(length as i32); + self.ir.meta.set_variable_initializer(length_variable_id, length); + } + } + + // Called when the size of gl_ClipDistance is determined. It updates the type of the + // gl_ClipDistance variable and initializes the temp variable used to hold its length (if any). + pub fn on_gl_clip_distance_sized(&mut self, id: VariableId, length: u32) { + self.on_gl_clip_cull_distance_sized(id, length, self.gl_clip_distance_length_var_id); + } + pub fn on_gl_cull_distance_sized(&mut self, id: VariableId, length: u32) { + self.on_gl_clip_cull_distance_sized(id, length, self.gl_cull_distance_length_var_id); + } + + // Called when the length() method is visited. + pub fn array_length(&mut self) { + let operand = self.interm_ids.pop().unwrap(); + let type_info = self.ir.meta.get_type(operand.type_id); + + // Support for gl_ClipDistance and gl_CullDistance, who may be sized later. + let (is_clip_distance, is_cull_distance) = if let Id::Variable(variable_id) = operand.id { + let built_in = self.ir.meta.get_variable(variable_id).built_in; + (built_in == Some(BuiltIn::ClipDistance), built_in == Some(BuiltIn::CullDistance)) + } else { + (false, false) + }; + + match *type_info { + Type::Pointer(type_id) => { + let array_type_info = self.ir.meta.get_type(type_id); + if let &Type::Array(_, size) = array_type_info { + // The length is a constant, so push that on the stack. + self.push_constant_int(size as i32); + } else if is_clip_distance || is_cull_distance { + // If gl_ClipDistance and gl_CullDistance are not yet sized, use a global + // variable for their size. When they are sized, the global variable is + // initialized with the length. + let length_var = if is_clip_distance { + let new_var = self.declare_clip_cull_distance_array_length_variable( + self.gl_clip_distance_length_var_id, + "clip_distance_length", + ); + self.gl_clip_distance_length_var_id = Some(new_var); + new_var + } else { + let new_var = self.declare_clip_cull_distance_array_length_variable( + self.gl_cull_distance_length_var_id, + "cull_distance_length", + ); + self.gl_cull_distance_length_var_id = Some(new_var); + new_var + }; + + // Load from the (currently uninitialized) variable. The newly added + // variable is initialized with the real length when determined. + self.push_variable(length_var); + let length = self.load(); + self.interm_ids.push(length); + } else { + // The array is unsized, so this should be a runtime instruction. + let result = instruction::array_length(&mut self.ir.meta, operand); + self.add_instruction(result); + } + } + Type::Array(_, size) => { + self.push_constant_int(size as i32); + } + _ => panic!("Internal error: length() called on non-array"), + } + } + + // A generic helper to make a unary operator. The operand of the unary operator is found at + // the top of the stack. + fn unary_instruction_from_stack(&mut self, inst: MakeInst) + where + MakeInst: FnOnce(&mut IRMeta, TypedId) -> instruction::Result, + { + // Load the operand. + let operand = self.load(); + + let result = inst(&mut self.ir.meta, operand); + self.add_instruction(result); + } + fn unary_instruction_from_stack_with_pointer(&mut self, inst: MakeInst) + where + MakeInst: FnOnce(&mut IRMeta, TypedId) -> instruction::Result, + { + // The operand is expected to be a pointer. + let operand = self.interm_ids.pop().unwrap(); + + let result = inst(&mut self.ir.meta, operand); + self.add_instruction(result); + } + + // A generic helper to make a binary operator. The rhs operand of the binary operator is found + // at the top of the stack, and the lhs operand is found under it. + fn binary_instruction_from_stack(&mut self, inst: MakeInst) + where + MakeInst: FnOnce(&mut IRMeta, TypedId, TypedId) -> instruction::Result, + { + // Load the operands. + let rhs = self.load(); + let lhs = self.load(); + + let result = inst(&mut self.ir.meta, lhs, rhs); + self.add_instruction(result); + } + + // Arithmetic operations. + pub fn negate(&mut self) { + self.unary_instruction_from_stack(instruction::negate); + } + pub fn postfix_increment(&mut self) { + self.unary_instruction_from_stack_with_pointer(instruction::postfix_increment); + } + pub fn postfix_decrement(&mut self) { + self.unary_instruction_from_stack_with_pointer(instruction::postfix_decrement); + } + pub fn prefix_increment(&mut self) { + self.unary_instruction_from_stack_with_pointer(instruction::prefix_increment); + } + pub fn prefix_decrement(&mut self) { + self.unary_instruction_from_stack_with_pointer(instruction::prefix_decrement); + } + pub fn add(&mut self) { + self.binary_instruction_from_stack(instruction::add); + } + pub fn add_assign(&mut self) { + self.assign_and_op(Self::add); + } + pub fn sub(&mut self) { + self.binary_instruction_from_stack(instruction::sub); + } + pub fn sub_assign(&mut self) { + self.assign_and_op(Self::sub); + } + pub fn mul(&mut self) { + self.binary_instruction_from_stack(instruction::mul); + } + pub fn mul_assign(&mut self) { + self.assign_and_op(Self::mul); + } + pub fn vector_times_scalar(&mut self) { + self.binary_instruction_from_stack(instruction::vector_times_scalar); + } + pub fn vector_times_scalar_assign(&mut self) { + self.assign_and_op(Self::vector_times_scalar); + } + pub fn matrix_times_scalar(&mut self) { + self.binary_instruction_from_stack(instruction::matrix_times_scalar); + } + pub fn matrix_times_scalar_assign(&mut self) { + self.assign_and_op(Self::matrix_times_scalar); + } + pub fn vector_times_matrix(&mut self) { + self.binary_instruction_from_stack(instruction::vector_times_matrix); + } + pub fn vector_times_matrix_assign(&mut self) { + self.assign_and_op(Self::vector_times_matrix); + } + pub fn matrix_times_vector(&mut self) { + self.binary_instruction_from_stack(instruction::matrix_times_vector); + } + pub fn matrix_times_matrix(&mut self) { + self.binary_instruction_from_stack(instruction::matrix_times_matrix); + } + pub fn matrix_times_matrix_assign(&mut self) { + self.assign_and_op(Self::matrix_times_matrix); + } + pub fn div(&mut self) { + self.binary_instruction_from_stack(instruction::div); + } + pub fn div_assign(&mut self) { + self.assign_and_op(Self::div); + } + pub fn imod(&mut self) { + self.binary_instruction_from_stack(instruction::imod); + } + pub fn imod_assign(&mut self) { + self.assign_and_op(Self::imod); + } + + // Logical operations. + pub fn logical_not(&mut self) { + self.unary_instruction_from_stack(instruction::logical_not); + } + pub fn logical_xor(&mut self) { + self.binary_instruction_from_stack(instruction::logical_xor); + } + + // Comparisons. + pub fn equal(&mut self) { + self.binary_instruction_from_stack(instruction::equal); + } + pub fn not_equal(&mut self) { + self.binary_instruction_from_stack(instruction::not_equal); + } + pub fn less_than(&mut self) { + self.binary_instruction_from_stack(instruction::less_than); + } + pub fn greater_than(&mut self) { + self.binary_instruction_from_stack(instruction::greater_than); + } + pub fn less_than_equal(&mut self) { + self.binary_instruction_from_stack(instruction::less_than_equal); + } + pub fn greater_than_equal(&mut self) { + self.binary_instruction_from_stack(instruction::greater_than_equal); + } + + // Bit operations. + pub fn bitwise_not(&mut self) { + self.unary_instruction_from_stack(instruction::bitwise_not); + } + pub fn bit_shift_left(&mut self) { + self.binary_instruction_from_stack(instruction::bit_shift_left); + } + pub fn bit_shift_left_assign(&mut self) { + self.assign_and_op(Self::bit_shift_left); + } + pub fn bit_shift_right(&mut self) { + self.binary_instruction_from_stack(instruction::bit_shift_right); + } + pub fn bit_shift_right_assign(&mut self) { + self.assign_and_op(Self::bit_shift_right); + } + pub fn bitwise_or(&mut self) { + self.binary_instruction_from_stack(instruction::bitwise_or); + } + pub fn bitwise_or_assign(&mut self) { + self.assign_and_op(Self::bitwise_or); + } + pub fn bitwise_xor(&mut self) { + self.binary_instruction_from_stack(instruction::bitwise_xor); + } + pub fn bitwise_xor_assign(&mut self) { + self.assign_and_op(Self::bitwise_xor); + } + pub fn bitwise_and(&mut self) { + self.binary_instruction_from_stack(instruction::bitwise_and); + } + pub fn bitwise_and_assign(&mut self) { + self.assign_and_op(Self::bitwise_and); + } + + // Generic helpers to make a built-in operator. The operands are found in reverse order in + // the stack. + fn built_in_unary_instruction_from_stack(&mut self, built_in_op: UnaryOpCode) { + self.unary_instruction_from_stack(|ir_meta, operand| { + instruction::built_in_unary(ir_meta, built_in_op, operand) + }); + } + fn built_in_unary_instruction_from_stack_with_pointer(&mut self, built_in_op: UnaryOpCode) { + self.unary_instruction_from_stack_with_pointer(|ir_meta, operand| { + instruction::built_in_unary(ir_meta, built_in_op, operand) + }); + } + fn built_in_binary_instruction_from_stack_with_pointer_lhs( + &mut self, + built_in_op: BinaryOpCode, + ) { + // Load the operands. + let rhs = self.load(); + let lhs = self.interm_ids.pop().unwrap(); + + let result = instruction::built_in_binary(&mut self.ir.meta, built_in_op, lhs, rhs); + self.add_instruction(result); + } + fn built_in_binary_instruction_from_stack_with_pointer_rhs( + &mut self, + built_in_op: BinaryOpCode, + ) { + // Load the operands. + let rhs = self.interm_ids.pop().unwrap(); + let lhs = self.load(); + + let result = instruction::built_in_binary(&mut self.ir.meta, built_in_op, lhs, rhs); + self.add_instruction(result); + } + fn built_in_binary_instruction_from_stack(&mut self, built_in_op: BinaryOpCode) { + self.binary_instruction_from_stack(|ir_meta, lhs, rhs| { + instruction::built_in_binary(ir_meta, built_in_op, lhs, rhs) + }); + } + fn built_in_instruction_from_stack_with_pointer_args( + &mut self, + built_in_op: BuiltInOpCode, + first_pointer_arg_count: usize, + load_arg_count: usize, + last_pointer_arg_count: usize, + ) { + // Load the operands. Note that pointer arguments are always either the first or last + // arguments in GLSL built-ins. + let mut args = + (0..last_pointer_arg_count).map(|_| self.interm_ids.pop().unwrap()).collect::>(); + args.extend((0..load_arg_count).map(|_| self.load())); + args.extend((0..first_pointer_arg_count).map(|_| self.interm_ids.pop().unwrap())); + args.reverse(); + + let result = instruction::built_in(&mut self.ir.meta, built_in_op, args); + self.add_instruction(result); + } + fn built_in_instruction_from_stack(&mut self, built_in_op: BuiltInOpCode, arg_count: usize) { + self.built_in_instruction_from_stack_with_pointer_args(built_in_op, 0, arg_count, 0); + } + + // Built-in operations + pub fn built_in_radians(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Radians); + } + pub fn built_in_degrees(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Degrees); + } + pub fn built_in_sin(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Sin); + } + pub fn built_in_cos(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Cos); + } + pub fn built_in_tan(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Tan); + } + pub fn built_in_asin(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Asin); + } + pub fn built_in_acos(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Acos); + } + pub fn built_in_atan(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Atan); + } + pub fn built_in_sinh(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Sinh); + } + pub fn built_in_cosh(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Cosh); + } + pub fn built_in_tanh(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Tanh); + } + pub fn built_in_asinh(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Asinh); + } + pub fn built_in_acosh(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Acosh); + } + pub fn built_in_atanh(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Atanh); + } + pub fn built_in_atan_binary(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Atan); + } + pub fn built_in_pow(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Pow); + } + pub fn built_in_exp(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Exp); + } + pub fn built_in_log(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Log); + } + pub fn built_in_exp2(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Exp2); + } + pub fn built_in_log2(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Log2); + } + pub fn built_in_sqrt(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Sqrt); + } + pub fn built_in_inversesqrt(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Inversesqrt); + } + pub fn built_in_abs(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Abs); + } + pub fn built_in_sign(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Sign); + } + pub fn built_in_floor(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Floor); + } + pub fn built_in_trunc(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Trunc); + } + pub fn built_in_round(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Round); + } + pub fn built_in_roundeven(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::RoundEven); + } + pub fn built_in_ceil(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Ceil); + } + pub fn built_in_fract(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Fract); + } + pub fn built_in_mod(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Mod); + } + pub fn built_in_min(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Min); + } + pub fn built_in_max(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Max); + } + pub fn built_in_clamp(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Clamp, 3); + } + pub fn built_in_mix(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Mix, 3); + } + pub fn built_in_step(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Step); + } + pub fn built_in_smoothstep(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Smoothstep, 3); + } + pub fn built_in_modf(&mut self) { + // modf() takes two parameters, the second of which is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_rhs(BinaryOpCode::Modf); + } + pub fn built_in_isnan(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Isnan); + } + pub fn built_in_isinf(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Isinf); + } + pub fn built_in_floatbitstoint(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::FloatBitsToInt); + } + pub fn built_in_floatbitstouint(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::FloatBitsToUint); + } + pub fn built_in_intbitstofloat(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::IntBitsToFloat); + } + pub fn built_in_uintbitstofloat(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::UintBitsToFloat); + } + pub fn built_in_fma(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Fma, 3); + } + pub fn built_in_frexp(&mut self) { + // frexp() takes two parameters, the second of which is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_rhs(BinaryOpCode::Frexp); + } + pub fn built_in_ldexp(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Ldexp); + } + pub fn built_in_packsnorm2x16(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::PackSnorm2x16); + } + pub fn built_in_packhalf2x16(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::PackHalf2x16); + } + pub fn built_in_unpacksnorm2x16(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::UnpackSnorm2x16); + } + pub fn built_in_unpackhalf2x16(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::UnpackHalf2x16); + } + pub fn built_in_packunorm2x16(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::PackUnorm2x16); + } + pub fn built_in_unpackunorm2x16(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::UnpackUnorm2x16); + } + pub fn built_in_packunorm4x8(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::PackUnorm4x8); + } + pub fn built_in_packsnorm4x8(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::PackSnorm4x8); + } + pub fn built_in_unpackunorm4x8(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::UnpackUnorm4x8); + } + pub fn built_in_unpacksnorm4x8(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::UnpackSnorm4x8); + } + pub fn built_in_length(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Length); + } + pub fn built_in_distance(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Distance); + } + pub fn built_in_dot(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Dot); + } + pub fn built_in_cross(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Cross); + } + pub fn built_in_normalize(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Normalize); + } + pub fn built_in_faceforward(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Faceforward, 3); + } + pub fn built_in_reflect(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::Reflect); + } + pub fn built_in_refract(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Refract, 3); + } + pub fn built_in_matrixcompmult(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::MatrixCompMult); + } + pub fn built_in_outerproduct(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::OuterProduct); + } + pub fn built_in_transpose(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Transpose); + } + pub fn built_in_determinant(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Determinant); + } + pub fn built_in_inverse(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Inverse); + } + pub fn built_in_lessthan(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::LessThanVec); + } + pub fn built_in_lessthanequal(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::LessThanEqualVec); + } + pub fn built_in_greaterthan(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::GreaterThanVec); + } + pub fn built_in_greaterthanequal(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::GreaterThanEqualVec); + } + pub fn built_in_equal(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::EqualVec); + } + pub fn built_in_notequal(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::NotEqualVec); + } + pub fn built_in_any(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Any); + } + pub fn built_in_all(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::All); + } + pub fn built_in_not(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Not); + } + pub fn built_in_bitfieldextract(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::BitfieldExtract, 3); + } + pub fn built_in_bitfieldinsert(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::BitfieldInsert, 4); + } + pub fn built_in_bitfieldreverse(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::BitfieldReverse); + } + pub fn built_in_bitcount(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::BitCount); + } + pub fn built_in_findlsb(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::FindLSB); + } + pub fn built_in_findmsb(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::FindMSB); + } + pub fn built_in_uaddcarry(&mut self) { + // uaddCarry() takes three parameters, the last of which is a pointer. + self.built_in_instruction_from_stack_with_pointer_args(BuiltInOpCode::UaddCarry, 0, 2, 1); + } + pub fn built_in_usubborrow(&mut self) { + // usubBurrow() takes three parameters, the last of which is a pointer. + self.built_in_instruction_from_stack_with_pointer_args(BuiltInOpCode::UsubBorrow, 0, 2, 1); + } + pub fn built_in_umulextended(&mut self) { + // umulExtended() takes four parameters, the last two of which are pointers. + self.built_in_instruction_from_stack_with_pointer_args( + BuiltInOpCode::UmulExtended, + 0, + 2, + 2, + ); + } + pub fn built_in_imulextended(&mut self) { + // imulExtended() takes four parameters, the last two of which are pointers. + self.built_in_instruction_from_stack_with_pointer_args( + BuiltInOpCode::ImulExtended, + 0, + 2, + 2, + ); + } + pub fn built_in_texturesize(&mut self, with_lod: bool) { + self.built_in_instruction_from_stack( + BuiltInOpCode::TextureSize, + if with_lod { 2 } else { 1 }, + ); + } + pub fn built_in_texturequerylod(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::TextureQueryLod, 2); + } + pub fn built_in_texelfetch(&mut self, with_lod_or_sample: bool) { + self.built_in_instruction_from_stack( + BuiltInOpCode::TexelFetch, + if with_lod_or_sample { 3 } else { 2 }, + ); + } + pub fn built_in_texelfetchoffset(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::TexelFetchOffset, 4); + } + pub fn built_in_rgb_2_yuv(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Rgb2Yuv, 2); + } + pub fn built_in_yuv_2_rgb(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Yuv2Rgb, 2); + } + pub fn built_in_dfdx(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::DFdx); + } + pub fn built_in_dfdy(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::DFdy); + } + pub fn built_in_fwidth(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::Fwidth); + } + pub fn built_in_interpolateatcentroid(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::InterpolateAtCentroid); + } + pub fn built_in_interpolateatsample(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::InterpolateAtSample); + } + pub fn built_in_interpolateatoffset(&mut self) { + self.built_in_binary_instruction_from_stack(BinaryOpCode::InterpolateAtOffset); + } + pub fn built_in_atomiccounter(&mut self) { + self.built_in_unary_instruction_from_stack_with_pointer(UnaryOpCode::AtomicCounter); + } + pub fn built_in_atomiccounterincrement(&mut self) { + self.built_in_unary_instruction_from_stack_with_pointer( + UnaryOpCode::AtomicCounterIncrement, + ); + } + pub fn built_in_atomiccounterdecrement(&mut self) { + self.built_in_unary_instruction_from_stack_with_pointer( + UnaryOpCode::AtomicCounterDecrement, + ); + } + pub fn built_in_atomicadd(&mut self) { + // atomicAdd's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicAdd); + } + pub fn built_in_atomicmin(&mut self) { + // atomicMin's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicMin); + } + pub fn built_in_atomicmax(&mut self) { + // atomicMax's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicMax); + } + pub fn built_in_atomicand(&mut self) { + // atomicAnd's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicAnd); + } + pub fn built_in_atomicor(&mut self) { + // atomicOr's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicOr); + } + pub fn built_in_atomicxor(&mut self) { + // atomicXor's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicXor); + } + pub fn built_in_atomicexchange(&mut self) { + // atomicExchange's first argument is a pointer. + self.built_in_binary_instruction_from_stack_with_pointer_lhs(BinaryOpCode::AtomicExchange); + } + pub fn built_in_atomiccompswap(&mut self) { + // atomicCompSwap's first argument is a pointer. + self.built_in_instruction_from_stack_with_pointer_args( + BuiltInOpCode::AtomicCompSwap, + 1, + 2, + 0, + ); + } + pub fn built_in_imagesize(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::ImageSize); + } + pub fn built_in_imagestore(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageStore, 3); + } + pub fn built_in_imageload(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageLoad, 2); + } + pub fn built_in_imageatomicadd(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicAdd, 3); + } + pub fn built_in_imageatomicmin(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicMin, 3); + } + pub fn built_in_imageatomicmax(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicMax, 3); + } + pub fn built_in_imageatomicand(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicAnd, 3); + } + pub fn built_in_imageatomicor(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicOr, 3); + } + pub fn built_in_imageatomicxor(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicXor, 3); + } + pub fn built_in_imageatomicexchange(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicExchange, 3); + } + pub fn built_in_imageatomiccompswap(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::ImageAtomicCompSwap, 4); + } + pub fn built_in_pixellocalloadangle(&mut self) { + self.built_in_unary_instruction_from_stack(UnaryOpCode::PixelLocalLoadANGLE); + } + pub fn built_in_pixellocalstoreangle(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::PixelLocalStoreANGLE, 2); + } + pub fn built_in_memorybarrier(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::MemoryBarrier, 0); + } + pub fn built_in_memorybarrieratomiccounter(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::MemoryBarrierAtomicCounter, 0); + } + pub fn built_in_memorybarrierbuffer(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::MemoryBarrierBuffer, 0); + } + pub fn built_in_memorybarrierimage(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::MemoryBarrierImage, 0); + } + pub fn built_in_barrier(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::Barrier, 0); + } + pub fn built_in_memorybarriershared(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::MemoryBarrierShared, 0); + } + pub fn built_in_groupmemorybarrier(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::GroupMemoryBarrier, 0); + } + pub fn built_in_emitvertex(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::EmitVertex, 0); + } + pub fn built_in_endprimitive(&mut self) { + self.built_in_instruction_from_stack(BuiltInOpCode::EndPrimitive, 0); + } + + // A generic helper to make a texture* built-in operator. The coord operand of the texture + // built-in is found at the top of the stack, and the sampler operand is found under it. + // Any other operand is expected to be already popped, and passed in with `texture_op`. + fn built_in_texture_instruction_from_stack(&mut self, texture_op: TextureOpCode) { + // Load the operands. + let coord = self.load(); + let sampler = self.load(); + + let result = instruction::built_in_texture(&mut self.ir.meta, texture_op, sampler, coord); + self.add_instruction(result); + } + + // Built-in texture* operations + pub fn built_in_texture(&mut self, with_compare: bool) { + let texture_op = if with_compare { + let compare = self.load(); + TextureOpCode::Compare { compare } + } else { + TextureOpCode::Implicit { is_proj: false, offset: None } + }; + self.built_in_texture_instruction_from_stack(texture_op); + } + pub fn built_in_textureproj(&mut self) { + self.built_in_texture_instruction_from_stack(TextureOpCode::Implicit { + is_proj: true, + offset: None, + }); + } + pub fn built_in_texturelod(&mut self, with_compare: bool) { + let lod = self.load(); + let texture_op = if with_compare { + let compare = self.load(); + TextureOpCode::CompareLod { compare, lod } + } else { + TextureOpCode::Lod { is_proj: false, lod, offset: None } + }; + self.built_in_texture_instruction_from_stack(texture_op); + } + pub fn built_in_textureprojlod(&mut self) { + let lod = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Lod { + is_proj: true, + lod, + offset: None, + }); + } + pub fn built_in_texturebias(&mut self, with_compare: bool) { + let bias = self.load(); + let texture_op = if with_compare { + let compare = self.load(); + TextureOpCode::CompareBias { compare, bias } + } else { + TextureOpCode::Bias { is_proj: false, bias, offset: None } + }; + + self.built_in_texture_instruction_from_stack(texture_op); + } + pub fn built_in_textureprojbias(&mut self) { + let bias = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Bias { + is_proj: true, + bias, + offset: None, + }); + } + pub fn built_in_textureoffset(&mut self) { + let offset = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Implicit { + is_proj: false, + offset: Some(offset), + }); + } + pub fn built_in_textureprojoffset(&mut self) { + let offset = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Implicit { + is_proj: true, + offset: Some(offset), + }); + } + pub fn built_in_texturelodoffset(&mut self) { + let offset = self.load(); + let lod = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Lod { + is_proj: false, + lod, + offset: Some(offset), + }); + } + pub fn built_in_textureprojlodoffset(&mut self) { + let offset = self.load(); + let lod = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Lod { + is_proj: true, + lod, + offset: Some(offset), + }); + } + pub fn built_in_textureoffsetbias(&mut self) { + let bias = self.load(); + let offset = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Bias { + is_proj: false, + bias, + offset: Some(offset), + }); + } + pub fn built_in_textureprojoffsetbias(&mut self) { + let bias = self.load(); + let offset = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Bias { + is_proj: true, + bias, + offset: Some(offset), + }); + } + pub fn built_in_texturegrad(&mut self) { + let dy = self.load(); + let dx = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Grad { + is_proj: false, + dx, + dy, + offset: None, + }); + } + pub fn built_in_textureprojgrad(&mut self) { + let dy = self.load(); + let dx = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Grad { + is_proj: true, + dx, + dy, + offset: None, + }); + } + pub fn built_in_texturegradoffset(&mut self) { + let offset = self.load(); + let dy = self.load(); + let dx = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Grad { + is_proj: false, + dx, + dy, + offset: Some(offset), + }); + } + pub fn built_in_textureprojgradoffset(&mut self) { + let offset = self.load(); + let dy = self.load(); + let dx = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Grad { + is_proj: true, + dx, + dy, + offset: Some(offset), + }); + } + pub fn built_in_texturegather(&mut self) { + self.built_in_texture_instruction_from_stack(TextureOpCode::Gather { offset: None }); + } + pub fn built_in_texturegathercomp(&mut self) { + let component = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::GatherComponent { + component, + offset: None, + }); + } + pub fn built_in_texturegatherref(&mut self) { + let refz = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::GatherRef { + refz, + offset: None, + }); + } + pub fn built_in_texturegatheroffset(&mut self) { + let offset = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::Gather { + offset: Some(offset), + }); + } + pub fn built_in_texturegatheroffsetcomp(&mut self) { + let component = self.load(); + let offset = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::GatherComponent { + component, + offset: Some(offset), + }); + } + pub fn built_in_texturegatheroffsetref(&mut self) { + let offset = self.load(); + let refz = self.load(); + self.built_in_texture_instruction_from_stack(TextureOpCode::GatherRef { + refz, + offset: Some(offset), + }); + } +} + +#[cxx::bridge(namespace = "sh::ir::ffi")] +pub mod ffi { + // Flags controlling the way the IR is built, applying transformations during IR generation. + struct BuildOptions { + // Whether uninitialized local and global variables should be zero-initialized. + initialize_uninitialized_variables: bool, + // Whether non-const global variables are allowed to have an initializer. + initializer_allowed_on_non_const_global_variables: bool, + // Whether output variables should be zero-initialized. + initialize_output_variables: bool, + // Whether gl_Position should be zero-initialized. + initialize_gl_position: bool, + } + + // The following enums and types must be identical to what's found in BaseTypes.h. This + // duplication is not ideal, but necessary during the transition to IR. Once the translator + // switches over to IR completely, it can directly use the types exported from here (or better + // yet, switch to more IR friendly types) and remove them from BaseTypes.h. + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTPrecision { + Undefined, + Low, + Medium, + High, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTBasicType { + Void, + Float, + Int, + UInt, + Bool, + AtomicCounter, + YuvCscStandardEXT, + Sampler2D, + Sampler3D, + SamplerCube, + Sampler2DArray, + SamplerExternalOES, + SamplerExternal2DY2YEXT, + Sampler2DRect, + Sampler2DMS, + Sampler2DMSArray, + ISampler2D, + ISampler3D, + ISamplerCube, + ISampler2DArray, + ISampler2DMS, + ISampler2DMSArray, + USampler2D, + USampler3D, + USamplerCube, + USampler2DArray, + USampler2DMS, + USampler2DMSArray, + Sampler2DShadow, + SamplerCubeShadow, + Sampler2DArrayShadow, + SamplerBuffer, + SamplerCubeArray, + SamplerCubeArrayShadow, + ISampler2DRect, + ISamplerBuffer, + ISamplerCubeArray, + USampler2DRect, + USamplerBuffer, + USamplerCubeArray, + SamplerVideoWEBGL, + Image2D, + Image3D, + Image2DArray, + ImageCube, + ImageCubeArray, + ImageBuffer, + IImage2D, + IImage3D, + IImage2DArray, + IImageCube, + IImageCubeArray, + IImageBuffer, + UImage2D, + UImage3D, + UImage2DArray, + UImageCube, + UImageCubeArray, + UImageBuffer, + PixelLocalANGLE, + IPixelLocalANGLE, + UPixelLocalANGLE, + SubpassInput, + ISubpassInput, + USubpassInput, + Struct, + InterfaceBlock, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTQualifier { + Temporary, + Global, + Const, + Attribute, + VaryingIn, + VaryingOut, + Uniform, + Buffer, + Patch, + VertexIn, + FragmentOut, + VertexOut, + FragmentIn, + FragmentInOut, + ParamIn, + ParamOut, + ParamInOut, + ParamConst, + InstanceID, + VertexID, + Position, + PointSize, + BaseVertex, + BaseInstance, + DrawID, + FragCoord, + FrontFacing, + PointCoord, + HelperInvocation, + FragColor, + FragData, + FragDepth, + SecondaryFragColorEXT, + SecondaryFragDataEXT, + ViewIDOVR, + ClipDistance, + CullDistance, + LastFragColor, + LastFragData, + LastFragDepth, + LastFragStencil, + DepthRange, + Smooth, + Flat, + NoPerspective, + Centroid, + Sample, + NoPerspectiveCentroid, + NoPerspectiveSample, + SmoothOut, + FlatOut, + NoPerspectiveOut, + CentroidOut, + SampleOut, + NoPerspectiveCentroidOut, + NoPerspectiveSampleOut, + SmoothIn, + FlatIn, + NoPerspectiveIn, + CentroidIn, + SampleIn, + NoPerspectiveCentroidIn, + NoPerspectiveSampleIn, + ShadingRateEXT, + PrimitiveShadingRateEXT, + SampleID, + SamplePosition, + SampleMaskIn, + SampleMask, + NumSamples, + Shared, + ComputeIn, + NumWorkGroups, + WorkGroupSize, + WorkGroupID, + LocalInvocationID, + GlobalInvocationID, + LocalInvocationIndex, + ReadOnly, + WriteOnly, + Coherent, + Restrict, + Volatile, + GeometryIn, + GeometryOut, + PerVertexIn, + PrimitiveIDIn, + InvocationID, + PrimitiveID, + LayerOut, + LayerIn, + PatchIn, + PatchOut, + TessControlIn, + TessControlOut, + PerVertexOut, + PatchVerticesIn, + TessLevelOuter, + TessLevelInner, + BoundingBox, + TessEvaluationIn, + TessEvaluationOut, + TessCoord, + SpecConst, + PixelLocalEXT, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTLayoutImageInternalFormat { + Unspecified, + RGBA32F, + RGBA16F, + R32F, + RGBA32UI, + RGBA16UI, + RGBA8UI, + R32UI, + RGBA32I, + RGBA16I, + RGBA8I, + R32I, + RGBA8, + RGBA8SNORM, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTLayoutMatrixPacking { + Unspecified, + RowMajor, + ColumnMajor, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTLayoutBlockStorage { + Unspecified, + Shared, + Packed, + Std140, + Std430, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTLayoutDepth { + Unspecified, + Any, + Greater, + Less, + Unchanged, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTYuvCscStandardEXT { + Undefined, + Itu601, + Itu601FullRange, + Itu709, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTLayoutPrimitiveType { + Undefined, + Points, + Lines, + LinesAdjacency, + Triangles, + TrianglesAdjacency, + LineStrip, + TriangleStrip, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTLayoutTessEvaluationType { + Undefined, + Triangles, + Quads, + Isolines, + EqualSpacing, + FractionalEvenSpacing, + FractionalOddSpacing, + Cw, + Ccw, + PointMode, + } + + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTShaderType { + Vertex, + TessControl, + TessEvaluation, + Geometry, + Fragment, + Compute, + } + + // The AST structs don't have to be identical to TLayoutQualifier/etc, it's too risky to assume + // identical layout so the fields are copied from TLayoutQualifier/etc instead. + struct ASTLayoutQualifier { + location: i32, + matrix_packing: ASTLayoutMatrixPacking, + block_storage: ASTLayoutBlockStorage, + binding: i32, + offset: i32, + depth: ASTLayoutDepth, + image_internal_format: ASTLayoutImageInternalFormat, + num_views: i32, + yuv: bool, + index: i32, + noncoherent: bool, + + // The following fields are only needed while output/legacy.rs is needed, as they may be + // set in the IR and need to translate back to AST, but can never be set when parsing GLSL. + push_constant: bool, + input_attachment_index: i32, + raster_ordered: bool, + } + + struct ASTMemoryQualifier { + readonly: bool, + writeonly: bool, + coherent: bool, + restrict_qualifier: bool, + volatile_qualifier: bool, + } + + struct ASTType { + type_id: TypeId, + qualifier: ASTQualifier, + precision: ASTPrecision, + layout_qualifier: ASTLayoutQualifier, + memory_qualifier: ASTMemoryQualifier, + invariant: bool, + precise: bool, + interpolant: bool, + } + + struct ASTField { + name: &'static str, + ast_type: ASTType, + } + + struct ASTStruct<'a> { + name: &'static str, + fields: &'a [ASTField], + is_interface_block: bool, + is_internal: bool, + is_at_global_scope: bool, + } + + // IR ids that the parser would have to know about. + #[derive(Copy, Clone)] + struct TypeId { + id: u32, + } + #[derive(Copy, Clone)] + struct FunctionId { + id: u32, + } + #[derive(Copy, Clone)] + struct VariableId { + id: u32, + } + #[derive(Copy, Clone)] + struct ConstantId { + id: u32, + } + + extern "Rust" { + type BuilderWrapper; + #[derive(ExternType)] + type IR; + + fn builder_new(shader_type: ASTShaderType, options: BuildOptions) -> Box; + fn builder_finish(mut builder: Box) -> Box; + fn builder_fail(mut builder: Box) -> Box; + + // Helpers to get a TypeId out of a TType. + fn get_basic_type_id( + self: &mut BuilderWrapper, + basic_type: ASTBasicType, + primary_size: u32, + secondary_size: u32, + ) -> TypeId; + fn get_struct_type_id(self: &mut BuilderWrapper, struct_info: &ASTStruct) -> TypeId; + fn get_array_type_id( + self: &mut BuilderWrapper, + element_type_id: TypeId, + array_sizes: &[u32], + ) -> TypeId; + + // Helpers to set global metadata. + fn set_early_fragment_tests(self: &mut BuilderWrapper, value: bool); + fn set_advanced_blend_equations(self: &mut BuilderWrapper, value: u32); + fn set_tcs_vertices(self: &mut BuilderWrapper, value: u32); + fn set_tes_primitive(self: &mut BuilderWrapper, value: ASTLayoutTessEvaluationType); + fn set_tes_vertex_spacing(self: &mut BuilderWrapper, value: ASTLayoutTessEvaluationType); + fn set_tes_ordering(self: &mut BuilderWrapper, value: ASTLayoutTessEvaluationType); + fn set_tes_point_mode(self: &mut BuilderWrapper, value: ASTLayoutTessEvaluationType); + fn set_gs_primitive_in(self: &mut BuilderWrapper, value: ASTLayoutPrimitiveType); + fn set_gs_primitive_out(self: &mut BuilderWrapper, value: ASTLayoutPrimitiveType); + fn set_gs_invocations(self: &mut BuilderWrapper, value: u32); + fn set_gs_max_vertices(self: &mut BuilderWrapper, value: u32); + + fn declare_interface_variable( + self: &mut BuilderWrapper, + name: &'static str, + ast_type: &ASTType, + is_declaration_internal: bool, + ) -> VariableId; + fn declare_temp_variable( + self: &mut BuilderWrapper, + name: &'static str, + ast_type: &ASTType, + ) -> VariableId; + fn mark_variable_invariant(self: &mut BuilderWrapper, variable_id: VariableId); + fn mark_variable_precise(self: &mut BuilderWrapper, variable_id: VariableId); + fn new_function( + self: &mut BuilderWrapper, + name: &'static str, + params: &[VariableId], + param_directions: &[ASTQualifier], + return_type_id: TypeId, + return_ast_type: &ASTType, + ) -> FunctionId; + fn update_function_param_names( + self: &mut BuilderWrapper, + id: FunctionId, + param_names: &[&'static str], + param_ids: &mut [VariableId], + ); + fn declare_function_param( + self: &mut BuilderWrapper, + name: &'static str, + type_id: TypeId, + ast_type: &ASTType, + direction: ASTQualifier, + ) -> VariableId; + fn begin_function(self: &mut BuilderWrapper, id: FunctionId); + fn end_function(self: &mut BuilderWrapper); + fn store(self: &mut BuilderWrapper); + fn initialize(self: &mut BuilderWrapper, id: VariableId); + fn begin_if_true_block(self: &mut BuilderWrapper); + fn end_if_true_block(self: &mut BuilderWrapper); + fn begin_if_false_block(self: &mut BuilderWrapper); + fn end_if_false_block(self: &mut BuilderWrapper); + fn end_if(self: &mut BuilderWrapper); + fn begin_ternary_true_expression(self: &mut BuilderWrapper); + fn end_ternary_true_expression(self: &mut BuilderWrapper, is_void: bool); + fn begin_ternary_false_expression(self: &mut BuilderWrapper); + fn end_ternary_false_expression(self: &mut BuilderWrapper, is_void: bool); + fn end_ternary(self: &mut BuilderWrapper, is_void: bool); + fn begin_short_circuit_or(self: &mut BuilderWrapper); + fn end_short_circuit_or(self: &mut BuilderWrapper); + fn begin_short_circuit_and(self: &mut BuilderWrapper); + fn end_short_circuit_and(self: &mut BuilderWrapper); + fn begin_loop_condition(self: &mut BuilderWrapper); + fn end_loop_condition(self: &mut BuilderWrapper); + fn end_loop_continue(self: &mut BuilderWrapper); + fn end_loop(self: &mut BuilderWrapper); + fn begin_do_loop(self: &mut BuilderWrapper); + fn begin_do_loop_condition(self: &mut BuilderWrapper); + fn end_do_loop(self: &mut BuilderWrapper); + fn begin_switch(self: &mut BuilderWrapper); + fn begin_case(self: &mut BuilderWrapper); + fn begin_default(self: &mut BuilderWrapper); + fn end_switch(self: &mut BuilderWrapper); + fn branch_discard(self: &mut BuilderWrapper); + fn branch_return(self: &mut BuilderWrapper); + fn branch_return_value(self: &mut BuilderWrapper); + fn branch_break(self: &mut BuilderWrapper); + fn branch_continue(self: &mut BuilderWrapper); + fn pop_array_size(self: &mut BuilderWrapper) -> u32; + fn end_statement_with_value(self: &mut BuilderWrapper); + fn push_constant_float(self: &mut BuilderWrapper, value: f32); + fn push_constant_int(self: &mut BuilderWrapper, value: i32); + fn push_constant_uint(self: &mut BuilderWrapper, value: u32); + fn push_constant_bool(self: &mut BuilderWrapper, value: bool); + fn push_constant_yuv_csc_standard(self: &mut BuilderWrapper, value: ASTYuvCscStandardEXT); + fn push_variable(self: &mut BuilderWrapper, id: VariableId); + fn call_function(self: &mut BuilderWrapper, id: FunctionId); + fn vector_component(self: &mut BuilderWrapper, component: u32); + fn vector_component_multi(self: &mut BuilderWrapper, components: &[u32]); + fn index(self: &mut BuilderWrapper); + fn struct_field(self: &mut BuilderWrapper, field_index: u32); + fn construct(self: &mut BuilderWrapper, type_id: TypeId, arg_count: usize); + fn on_gl_clip_distance_sized(self: &mut BuilderWrapper, id: VariableId, length: u32); + fn on_gl_cull_distance_sized(self: &mut BuilderWrapper, id: VariableId, length: u32); + fn array_length(self: &mut BuilderWrapper); + fn negate(self: &mut BuilderWrapper); + fn postfix_increment(self: &mut BuilderWrapper); + fn postfix_decrement(self: &mut BuilderWrapper); + fn prefix_increment(self: &mut BuilderWrapper); + fn prefix_decrement(self: &mut BuilderWrapper); + fn add(self: &mut BuilderWrapper); + fn add_assign(self: &mut BuilderWrapper); + fn sub(self: &mut BuilderWrapper); + fn sub_assign(self: &mut BuilderWrapper); + fn mul(self: &mut BuilderWrapper); + fn mul_assign(self: &mut BuilderWrapper); + fn vector_times_scalar(self: &mut BuilderWrapper); + fn vector_times_scalar_assign(self: &mut BuilderWrapper); + fn matrix_times_scalar(self: &mut BuilderWrapper); + fn matrix_times_scalar_assign(self: &mut BuilderWrapper); + fn vector_times_matrix(self: &mut BuilderWrapper); + fn vector_times_matrix_assign(self: &mut BuilderWrapper); + fn matrix_times_vector(self: &mut BuilderWrapper); + fn matrix_times_matrix(self: &mut BuilderWrapper); + fn matrix_times_matrix_assign(self: &mut BuilderWrapper); + fn div(self: &mut BuilderWrapper); + fn div_assign(self: &mut BuilderWrapper); + fn imod(self: &mut BuilderWrapper); + fn imod_assign(self: &mut BuilderWrapper); + fn logical_not(self: &mut BuilderWrapper); + fn logical_xor(self: &mut BuilderWrapper); + fn equal(self: &mut BuilderWrapper); + fn not_equal(self: &mut BuilderWrapper); + fn less_than(self: &mut BuilderWrapper); + fn greater_than(self: &mut BuilderWrapper); + fn less_than_equal(self: &mut BuilderWrapper); + fn greater_than_equal(self: &mut BuilderWrapper); + fn bitwise_not(self: &mut BuilderWrapper); + fn bit_shift_left(self: &mut BuilderWrapper); + fn bit_shift_left_assign(self: &mut BuilderWrapper); + fn bit_shift_right(self: &mut BuilderWrapper); + fn bit_shift_right_assign(self: &mut BuilderWrapper); + fn bitwise_or(self: &mut BuilderWrapper); + fn bitwise_or_assign(self: &mut BuilderWrapper); + fn bitwise_xor(self: &mut BuilderWrapper); + fn bitwise_xor_assign(self: &mut BuilderWrapper); + fn bitwise_and(self: &mut BuilderWrapper); + fn bitwise_and_assign(self: &mut BuilderWrapper); + fn built_in_radians(self: &mut BuilderWrapper); + fn built_in_degrees(self: &mut BuilderWrapper); + fn built_in_sin(self: &mut BuilderWrapper); + fn built_in_cos(self: &mut BuilderWrapper); + fn built_in_tan(self: &mut BuilderWrapper); + fn built_in_asin(self: &mut BuilderWrapper); + fn built_in_acos(self: &mut BuilderWrapper); + fn built_in_atan(self: &mut BuilderWrapper); + fn built_in_sinh(self: &mut BuilderWrapper); + fn built_in_cosh(self: &mut BuilderWrapper); + fn built_in_tanh(self: &mut BuilderWrapper); + fn built_in_asinh(self: &mut BuilderWrapper); + fn built_in_acosh(self: &mut BuilderWrapper); + fn built_in_atanh(self: &mut BuilderWrapper); + fn built_in_atan_binary(self: &mut BuilderWrapper); + fn built_in_pow(self: &mut BuilderWrapper); + fn built_in_exp(self: &mut BuilderWrapper); + fn built_in_log(self: &mut BuilderWrapper); + fn built_in_exp2(self: &mut BuilderWrapper); + fn built_in_log2(self: &mut BuilderWrapper); + fn built_in_sqrt(self: &mut BuilderWrapper); + fn built_in_inversesqrt(self: &mut BuilderWrapper); + fn built_in_abs(self: &mut BuilderWrapper); + fn built_in_sign(self: &mut BuilderWrapper); + fn built_in_floor(self: &mut BuilderWrapper); + fn built_in_trunc(self: &mut BuilderWrapper); + fn built_in_round(self: &mut BuilderWrapper); + fn built_in_roundeven(self: &mut BuilderWrapper); + fn built_in_ceil(self: &mut BuilderWrapper); + fn built_in_fract(self: &mut BuilderWrapper); + fn built_in_mod(self: &mut BuilderWrapper); + fn built_in_min(self: &mut BuilderWrapper); + fn built_in_max(self: &mut BuilderWrapper); + fn built_in_clamp(self: &mut BuilderWrapper); + fn built_in_mix(self: &mut BuilderWrapper); + fn built_in_step(self: &mut BuilderWrapper); + fn built_in_smoothstep(self: &mut BuilderWrapper); + fn built_in_modf(self: &mut BuilderWrapper); + fn built_in_isnan(self: &mut BuilderWrapper); + fn built_in_isinf(self: &mut BuilderWrapper); + fn built_in_floatbitstoint(self: &mut BuilderWrapper); + fn built_in_floatbitstouint(self: &mut BuilderWrapper); + fn built_in_intbitstofloat(self: &mut BuilderWrapper); + fn built_in_uintbitstofloat(self: &mut BuilderWrapper); + fn built_in_fma(self: &mut BuilderWrapper); + fn built_in_frexp(self: &mut BuilderWrapper); + fn built_in_ldexp(self: &mut BuilderWrapper); + fn built_in_packsnorm2x16(self: &mut BuilderWrapper); + fn built_in_packhalf2x16(self: &mut BuilderWrapper); + fn built_in_unpacksnorm2x16(self: &mut BuilderWrapper); + fn built_in_unpackhalf2x16(self: &mut BuilderWrapper); + fn built_in_packunorm2x16(self: &mut BuilderWrapper); + fn built_in_unpackunorm2x16(self: &mut BuilderWrapper); + fn built_in_packunorm4x8(self: &mut BuilderWrapper); + fn built_in_packsnorm4x8(self: &mut BuilderWrapper); + fn built_in_unpackunorm4x8(self: &mut BuilderWrapper); + fn built_in_unpacksnorm4x8(self: &mut BuilderWrapper); + fn built_in_length(self: &mut BuilderWrapper); + fn built_in_distance(self: &mut BuilderWrapper); + fn built_in_dot(self: &mut BuilderWrapper); + fn built_in_cross(self: &mut BuilderWrapper); + fn built_in_normalize(self: &mut BuilderWrapper); + fn built_in_faceforward(self: &mut BuilderWrapper); + fn built_in_reflect(self: &mut BuilderWrapper); + fn built_in_refract(self: &mut BuilderWrapper); + fn built_in_matrixcompmult(self: &mut BuilderWrapper); + fn built_in_outerproduct(self: &mut BuilderWrapper); + fn built_in_transpose(self: &mut BuilderWrapper); + fn built_in_determinant(self: &mut BuilderWrapper); + fn built_in_inverse(self: &mut BuilderWrapper); + fn built_in_lessthan(self: &mut BuilderWrapper); + fn built_in_lessthanequal(self: &mut BuilderWrapper); + fn built_in_greaterthan(self: &mut BuilderWrapper); + fn built_in_greaterthanequal(self: &mut BuilderWrapper); + fn built_in_equal(self: &mut BuilderWrapper); + fn built_in_notequal(self: &mut BuilderWrapper); + fn built_in_any(self: &mut BuilderWrapper); + fn built_in_all(self: &mut BuilderWrapper); + fn built_in_not(self: &mut BuilderWrapper); + fn built_in_bitfieldextract(self: &mut BuilderWrapper); + fn built_in_bitfieldinsert(self: &mut BuilderWrapper); + fn built_in_bitfieldreverse(self: &mut BuilderWrapper); + fn built_in_bitcount(self: &mut BuilderWrapper); + fn built_in_findlsb(self: &mut BuilderWrapper); + fn built_in_findmsb(self: &mut BuilderWrapper); + fn built_in_uaddcarry(self: &mut BuilderWrapper); + fn built_in_usubborrow(self: &mut BuilderWrapper); + fn built_in_umulextended(self: &mut BuilderWrapper); + fn built_in_imulextended(self: &mut BuilderWrapper); + fn built_in_texturesize(self: &mut BuilderWrapper, with_lod: bool); + fn built_in_texturequerylod(self: &mut BuilderWrapper); + fn built_in_texelfetch(self: &mut BuilderWrapper, with_lod_or_sample: bool); + fn built_in_texelfetchoffset(self: &mut BuilderWrapper); + fn built_in_rgb_2_yuv(self: &mut BuilderWrapper); + fn built_in_yuv_2_rgb(self: &mut BuilderWrapper); + fn built_in_dfdx(self: &mut BuilderWrapper); + fn built_in_dfdy(self: &mut BuilderWrapper); + fn built_in_fwidth(self: &mut BuilderWrapper); + fn built_in_interpolateatcentroid(self: &mut BuilderWrapper); + fn built_in_interpolateatsample(self: &mut BuilderWrapper); + fn built_in_interpolateatoffset(self: &mut BuilderWrapper); + fn built_in_atomiccounter(self: &mut BuilderWrapper); + fn built_in_atomiccounterincrement(self: &mut BuilderWrapper); + fn built_in_atomiccounterdecrement(self: &mut BuilderWrapper); + fn built_in_atomicadd(self: &mut BuilderWrapper); + fn built_in_atomicmin(self: &mut BuilderWrapper); + fn built_in_atomicmax(self: &mut BuilderWrapper); + fn built_in_atomicand(self: &mut BuilderWrapper); + fn built_in_atomicor(self: &mut BuilderWrapper); + fn built_in_atomicxor(self: &mut BuilderWrapper); + fn built_in_atomicexchange(self: &mut BuilderWrapper); + fn built_in_atomiccompswap(self: &mut BuilderWrapper); + fn built_in_imagesize(self: &mut BuilderWrapper); + fn built_in_imagestore(self: &mut BuilderWrapper); + fn built_in_imageload(self: &mut BuilderWrapper); + fn built_in_imageatomicadd(self: &mut BuilderWrapper); + fn built_in_imageatomicmin(self: &mut BuilderWrapper); + fn built_in_imageatomicmax(self: &mut BuilderWrapper); + fn built_in_imageatomicand(self: &mut BuilderWrapper); + fn built_in_imageatomicor(self: &mut BuilderWrapper); + fn built_in_imageatomicxor(self: &mut BuilderWrapper); + fn built_in_imageatomicexchange(self: &mut BuilderWrapper); + fn built_in_imageatomiccompswap(self: &mut BuilderWrapper); + fn built_in_pixellocalloadangle(self: &mut BuilderWrapper); + fn built_in_pixellocalstoreangle(self: &mut BuilderWrapper); + fn built_in_memorybarrier(self: &mut BuilderWrapper); + fn built_in_memorybarrieratomiccounter(self: &mut BuilderWrapper); + fn built_in_memorybarrierbuffer(self: &mut BuilderWrapper); + fn built_in_memorybarrierimage(self: &mut BuilderWrapper); + fn built_in_barrier(self: &mut BuilderWrapper); + fn built_in_memorybarriershared(self: &mut BuilderWrapper); + fn built_in_groupmemorybarrier(self: &mut BuilderWrapper); + fn built_in_emitvertex(self: &mut BuilderWrapper); + fn built_in_endprimitive(self: &mut BuilderWrapper); + fn built_in_texture(self: &mut BuilderWrapper, with_compare: bool); + fn built_in_textureproj(self: &mut BuilderWrapper); + fn built_in_texturelod(self: &mut BuilderWrapper, with_compare: bool); + fn built_in_textureprojlod(self: &mut BuilderWrapper); + fn built_in_texturebias(self: &mut BuilderWrapper, with_compare: bool); + fn built_in_textureprojbias(self: &mut BuilderWrapper); + fn built_in_textureoffset(self: &mut BuilderWrapper); + fn built_in_textureprojoffset(self: &mut BuilderWrapper); + fn built_in_texturelodoffset(self: &mut BuilderWrapper); + fn built_in_textureprojlodoffset(self: &mut BuilderWrapper); + fn built_in_textureoffsetbias(self: &mut BuilderWrapper); + fn built_in_textureprojoffsetbias(self: &mut BuilderWrapper); + fn built_in_texturegrad(self: &mut BuilderWrapper); + fn built_in_textureprojgrad(self: &mut BuilderWrapper); + fn built_in_texturegradoffset(self: &mut BuilderWrapper); + fn built_in_textureprojgradoffset(self: &mut BuilderWrapper); + fn built_in_texturegather(self: &mut BuilderWrapper); + fn built_in_texturegathercomp(self: &mut BuilderWrapper); + fn built_in_texturegatherref(self: &mut BuilderWrapper); + fn built_in_texturegatheroffset(self: &mut BuilderWrapper); + fn built_in_texturegatheroffsetcomp(self: &mut BuilderWrapper); + fn built_in_texturegatheroffsetref(self: &mut BuilderWrapper); + } +} + +pub use ffi::BuildOptions as Options; + +impl From for ffi::TypeId { + fn from(id: TypeId) -> Self { + ffi::TypeId { id: id.id } + } +} + +impl From for TypeId { + fn from(id: ffi::TypeId) -> Self { + TypeId { id: id.id } + } +} + +impl From for ffi::ConstantId { + fn from(id: ConstantId) -> Self { + ffi::ConstantId { id: id.id } + } +} + +impl From for ConstantId { + fn from(id: ffi::ConstantId) -> Self { + ConstantId { id: id.id } + } +} + +impl From for ffi::VariableId { + fn from(id: VariableId) -> Self { + ffi::VariableId { id: id.id } + } +} + +impl From for VariableId { + fn from(id: ffi::VariableId) -> Self { + VariableId { id: id.id } + } +} + +impl From for ffi::FunctionId { + fn from(id: FunctionId) -> Self { + ffi::FunctionId { id: id.id } + } +} + +impl From for FunctionId { + fn from(id: ffi::FunctionId) -> Self { + FunctionId { id: id.id } + } +} + +impl From for Precision { + fn from(precision: ffi::ASTPrecision) -> Self { + match precision { + ffi::ASTPrecision::Low => Precision::Low, + ffi::ASTPrecision::Medium => Precision::Medium, + ffi::ASTPrecision::High => Precision::High, + _ => Precision::NotApplicable, + } + } +} + +impl From for YuvCscStandard { + fn from(value: ffi::ASTYuvCscStandardEXT) -> Self { + match value { + ffi::ASTYuvCscStandardEXT::Itu601 => YuvCscStandard::Itu601, + ffi::ASTYuvCscStandardEXT::Itu601FullRange => YuvCscStandard::Itu601FullRange, + ffi::ASTYuvCscStandardEXT::Itu709 => YuvCscStandard::Itu709, + _ => panic!("Internal error: Impossible yuv csc standard value"), + } + } +} + +impl From for TessellationPrimitive { + fn from(value: ffi::ASTLayoutTessEvaluationType) -> Self { + match value { + ffi::ASTLayoutTessEvaluationType::Undefined => TessellationPrimitive::Undefined, + ffi::ASTLayoutTessEvaluationType::Triangles => TessellationPrimitive::Triangles, + ffi::ASTLayoutTessEvaluationType::Quads => TessellationPrimitive::Quads, + ffi::ASTLayoutTessEvaluationType::Isolines => TessellationPrimitive::Isolines, + _ => panic!("Internal error: Unexpected tessellation evaluation layout"), + } + } +} + +impl From for TessellationSpacing { + fn from(value: ffi::ASTLayoutTessEvaluationType) -> Self { + match value { + ffi::ASTLayoutTessEvaluationType::Undefined => TessellationSpacing::Undefined, + ffi::ASTLayoutTessEvaluationType::EqualSpacing => TessellationSpacing::EqualSpacing, + ffi::ASTLayoutTessEvaluationType::FractionalEvenSpacing => { + TessellationSpacing::FractionalEvenSpacing + } + ffi::ASTLayoutTessEvaluationType::FractionalOddSpacing => { + TessellationSpacing::FractionalOddSpacing + } + _ => panic!("Internal error: Unexpected tessellation evaluation layout"), + } + } +} + +impl From for TessellationOrdering { + fn from(value: ffi::ASTLayoutTessEvaluationType) -> Self { + match value { + ffi::ASTLayoutTessEvaluationType::Undefined => TessellationOrdering::Undefined, + ffi::ASTLayoutTessEvaluationType::Cw => TessellationOrdering::Cw, + ffi::ASTLayoutTessEvaluationType::Ccw => TessellationOrdering::Ccw, + _ => panic!("Internal error: Unexpected tessellation evaluation layout"), + } + } +} + +impl From for GeometryPrimitive { + fn from(value: ffi::ASTLayoutPrimitiveType) -> Self { + match value { + ffi::ASTLayoutPrimitiveType::Undefined => GeometryPrimitive::Undefined, + ffi::ASTLayoutPrimitiveType::Points => GeometryPrimitive::Points, + ffi::ASTLayoutPrimitiveType::Lines => GeometryPrimitive::Lines, + ffi::ASTLayoutPrimitiveType::LinesAdjacency => GeometryPrimitive::LinesAdjacency, + ffi::ASTLayoutPrimitiveType::Triangles => GeometryPrimitive::Triangles, + ffi::ASTLayoutPrimitiveType::TrianglesAdjacency => { + GeometryPrimitive::TrianglesAdjacency + } + ffi::ASTLayoutPrimitiveType::LineStrip => GeometryPrimitive::LineStrip, + ffi::ASTLayoutPrimitiveType::TriangleStrip => GeometryPrimitive::TriangleStrip, + _ => panic!("Internal error: Unexpected geometry primitive layout"), + } + } +} + +fn builder_new(shader_type: ffi::ASTShaderType, options: ffi::BuildOptions) -> Box { + let shader_type = match shader_type { + ffi::ASTShaderType::Vertex => ShaderType::Vertex, + ffi::ASTShaderType::TessControl => ShaderType::TessellationControl, + ffi::ASTShaderType::TessEvaluation => ShaderType::TessellationEvaluation, + ffi::ASTShaderType::Geometry => ShaderType::Geometry, + ffi::ASTShaderType::Fragment => ShaderType::Fragment, + ffi::ASTShaderType::Compute => ShaderType::Compute, + _ => panic!("Internal error: Impossible shader type enum value"), + }; + Box::new(BuilderWrapper { builder: Builder::new(shader_type, options) }) +} + +fn builder_finish(mut builder: Box) -> Box { + builder.builder.finish(); + + // Propagate precision to constant + let mut ir = builder.builder.take_ir(); + transform::propagate_precision::run(&mut ir); + + Box::new(ir) +} + +fn builder_fail(mut builder: Box) -> Box { + builder.builder.fail(); + Box::new(builder.builder.take_ir()) +} + +struct BuilderWrapper { + builder: Builder, +} + +impl BuilderWrapper { + fn apply_primary_secondary_dimensions( + builder: &mut Builder, + base_type_id: TypeId, + primary_size: u32, + secondary_size: u32, + ) -> TypeId { + if secondary_size > 1 { + debug_assert!(base_type_id == TYPE_ID_FLOAT); + builder.ir().meta.get_matrix_type_id(primary_size, secondary_size) + } else if primary_size > 1 { + builder.ir().meta.get_vector_type_id_from_element_id(base_type_id, primary_size) + } else { + base_type_id + } + } + + fn get_basic_type_id( + &mut self, + basic_type: ffi::ASTBasicType, + primary_size: u32, + secondary_size: u32, + ) -> ffi::TypeId { + let ir_base_type = match basic_type { + ffi::ASTBasicType::Void => TYPE_ID_VOID, + ffi::ASTBasicType::Float => TYPE_ID_FLOAT, + ffi::ASTBasicType::Int => TYPE_ID_INT, + ffi::ASTBasicType::UInt => TYPE_ID_UINT, + ffi::ASTBasicType::Bool => TYPE_ID_BOOL, + ffi::ASTBasicType::AtomicCounter => TYPE_ID_ATOMIC_COUNTER, + ffi::ASTBasicType::YuvCscStandardEXT => TYPE_ID_YUV_CSC_STANDARD, + _ => { + debug_assert!(primary_size <= 1 && secondary_size <= 1); + + let image_basic_type = if matches!( + basic_type, + ffi::ASTBasicType::Sampler2D + | ffi::ASTBasicType::Sampler3D + | ffi::ASTBasicType::SamplerCube + | ffi::ASTBasicType::Sampler2DArray + | ffi::ASTBasicType::SamplerExternalOES + | ffi::ASTBasicType::SamplerExternal2DY2YEXT + | ffi::ASTBasicType::Sampler2DRect + | ffi::ASTBasicType::Sampler2DMS + | ffi::ASTBasicType::Sampler2DMSArray + | ffi::ASTBasicType::Sampler2DShadow + | ffi::ASTBasicType::SamplerCubeShadow + | ffi::ASTBasicType::Sampler2DArrayShadow + | ffi::ASTBasicType::SamplerBuffer + | ffi::ASTBasicType::SamplerCubeArray + | ffi::ASTBasicType::SamplerCubeArrayShadow + | ffi::ASTBasicType::SamplerVideoWEBGL + | ffi::ASTBasicType::Image2D + | ffi::ASTBasicType::Image3D + | ffi::ASTBasicType::Image2DArray + | ffi::ASTBasicType::ImageCube + | ffi::ASTBasicType::ImageCubeArray + | ffi::ASTBasicType::ImageBuffer + | ffi::ASTBasicType::PixelLocalANGLE + | ffi::ASTBasicType::SubpassInput + ) { + ImageBasicType::Float + } else if matches!( + basic_type, + ffi::ASTBasicType::ISampler2D + | ffi::ASTBasicType::ISampler3D + | ffi::ASTBasicType::ISamplerCube + | ffi::ASTBasicType::ISampler2DArray + | ffi::ASTBasicType::ISampler2DMS + | ffi::ASTBasicType::ISampler2DMSArray + | ffi::ASTBasicType::ISampler2DRect + | ffi::ASTBasicType::ISamplerBuffer + | ffi::ASTBasicType::ISamplerCubeArray + | ffi::ASTBasicType::IImage2D + | ffi::ASTBasicType::IImage3D + | ffi::ASTBasicType::IImage2DArray + | ffi::ASTBasicType::IImageCube + | ffi::ASTBasicType::IImageCubeArray + | ffi::ASTBasicType::IImageBuffer + | ffi::ASTBasicType::IPixelLocalANGLE + | ffi::ASTBasicType::ISubpassInput + ) { + ImageBasicType::Int + } else { + debug_assert!(matches!( + basic_type, + ffi::ASTBasicType::USampler2D + | ffi::ASTBasicType::USampler3D + | ffi::ASTBasicType::USamplerCube + | ffi::ASTBasicType::USampler2DArray + | ffi::ASTBasicType::USampler2DMS + | ffi::ASTBasicType::USampler2DMSArray + | ffi::ASTBasicType::USampler2DRect + | ffi::ASTBasicType::USamplerBuffer + | ffi::ASTBasicType::USamplerCubeArray + | ffi::ASTBasicType::UImage2D + | ffi::ASTBasicType::UImage3D + | ffi::ASTBasicType::UImage2DArray + | ffi::ASTBasicType::UImageCube + | ffi::ASTBasicType::UImageCubeArray + | ffi::ASTBasicType::UImageBuffer + | ffi::ASTBasicType::UPixelLocalANGLE + | ffi::ASTBasicType::USubpassInput + )); + ImageBasicType::Uint + }; + + let dimension = if matches!( + basic_type, + ffi::ASTBasicType::Sampler2D + | ffi::ASTBasicType::Sampler2DArray + | ffi::ASTBasicType::Sampler2DMS + | ffi::ASTBasicType::Sampler2DMSArray + | ffi::ASTBasicType::Sampler2DShadow + | ffi::ASTBasicType::Sampler2DArrayShadow + | ffi::ASTBasicType::ISampler2D + | ffi::ASTBasicType::ISampler2DArray + | ffi::ASTBasicType::ISampler2DMS + | ffi::ASTBasicType::ISampler2DMSArray + | ffi::ASTBasicType::USampler2D + | ffi::ASTBasicType::USampler2DArray + | ffi::ASTBasicType::USampler2DMS + | ffi::ASTBasicType::USampler2DMSArray + | ffi::ASTBasicType::Image2D + | ffi::ASTBasicType::Image2DArray + | ffi::ASTBasicType::IImage2D + | ffi::ASTBasicType::IImage2DArray + | ffi::ASTBasicType::UImage2D + | ffi::ASTBasicType::UImage2DArray + ) { + ImageDimension::D2 + } else if matches!( + basic_type, + ffi::ASTBasicType::Sampler3D + | ffi::ASTBasicType::ISampler3D + | ffi::ASTBasicType::USampler3D + | ffi::ASTBasicType::Image3D + | ffi::ASTBasicType::IImage3D + | ffi::ASTBasicType::UImage3D + ) { + ImageDimension::D3 + } else if matches!( + basic_type, + ffi::ASTBasicType::SamplerCube + | ffi::ASTBasicType::SamplerCubeShadow + | ffi::ASTBasicType::SamplerCubeArray + | ffi::ASTBasicType::SamplerCubeArrayShadow + | ffi::ASTBasicType::ISamplerCube + | ffi::ASTBasicType::ISamplerCubeArray + | ffi::ASTBasicType::USamplerCube + | ffi::ASTBasicType::USamplerCubeArray + | ffi::ASTBasicType::ImageCube + | ffi::ASTBasicType::ImageCubeArray + | ffi::ASTBasicType::IImageCube + | ffi::ASTBasicType::IImageCubeArray + | ffi::ASTBasicType::UImageCube + | ffi::ASTBasicType::UImageCubeArray + ) { + ImageDimension::Cube + } else if matches!(basic_type, ffi::ASTBasicType::SamplerExternalOES) { + ImageDimension::External + } else if matches!(basic_type, ffi::ASTBasicType::SamplerExternal2DY2YEXT) { + ImageDimension::ExternalY2Y + } else if matches!( + basic_type, + ffi::ASTBasicType::Sampler2DRect + | ffi::ASTBasicType::ISampler2DRect + | ffi::ASTBasicType::USampler2DRect + ) { + ImageDimension::Rect + } else if matches!( + basic_type, + ffi::ASTBasicType::SamplerBuffer + | ffi::ASTBasicType::ISamplerBuffer + | ffi::ASTBasicType::USamplerBuffer + | ffi::ASTBasicType::ImageBuffer + | ffi::ASTBasicType::IImageBuffer + | ffi::ASTBasicType::UImageBuffer + ) { + ImageDimension::Buffer + } else if matches!(basic_type, ffi::ASTBasicType::SamplerVideoWEBGL) { + ImageDimension::Video + } else if matches!( + basic_type, + ffi::ASTBasicType::PixelLocalANGLE + | ffi::ASTBasicType::IPixelLocalANGLE + | ffi::ASTBasicType::UPixelLocalANGLE + ) { + ImageDimension::PixelLocal + } else { + debug_assert!(matches!( + basic_type, + ffi::ASTBasicType::SubpassInput + | ffi::ASTBasicType::ISubpassInput + | ffi::ASTBasicType::USubpassInput + )); + ImageDimension::Subpass + }; + + let is_sampled = matches!( + basic_type, + ffi::ASTBasicType::Sampler2D + | ffi::ASTBasicType::Sampler3D + | ffi::ASTBasicType::SamplerCube + | ffi::ASTBasicType::Sampler2DArray + | ffi::ASTBasicType::SamplerExternalOES + | ffi::ASTBasicType::SamplerExternal2DY2YEXT + | ffi::ASTBasicType::Sampler2DRect + | ffi::ASTBasicType::Sampler2DMS + | ffi::ASTBasicType::Sampler2DMSArray + | ffi::ASTBasicType::Sampler2DShadow + | ffi::ASTBasicType::SamplerCubeShadow + | ffi::ASTBasicType::Sampler2DArrayShadow + | ffi::ASTBasicType::SamplerBuffer + | ffi::ASTBasicType::SamplerCubeArray + | ffi::ASTBasicType::SamplerCubeArrayShadow + | ffi::ASTBasicType::SamplerVideoWEBGL + | ffi::ASTBasicType::ISampler2D + | ffi::ASTBasicType::ISampler3D + | ffi::ASTBasicType::ISamplerCube + | ffi::ASTBasicType::ISampler2DArray + | ffi::ASTBasicType::ISampler2DMS + | ffi::ASTBasicType::ISampler2DMSArray + | ffi::ASTBasicType::ISampler2DRect + | ffi::ASTBasicType::ISamplerBuffer + | ffi::ASTBasicType::ISamplerCubeArray + | ffi::ASTBasicType::USampler2D + | ffi::ASTBasicType::USampler3D + | ffi::ASTBasicType::USamplerCube + | ffi::ASTBasicType::USampler2DArray + | ffi::ASTBasicType::USampler2DMS + | ffi::ASTBasicType::USampler2DMSArray + | ffi::ASTBasicType::USampler2DRect + | ffi::ASTBasicType::USamplerBuffer + | ffi::ASTBasicType::USamplerCubeArray + ); + + let is_array = matches!( + basic_type, + ffi::ASTBasicType::Sampler2DArray + | ffi::ASTBasicType::Sampler2DMSArray + | ffi::ASTBasicType::Sampler2DArrayShadow + | ffi::ASTBasicType::SamplerCubeArray + | ffi::ASTBasicType::SamplerCubeArrayShadow + | ffi::ASTBasicType::Image2DArray + | ffi::ASTBasicType::ImageCubeArray + | ffi::ASTBasicType::ISampler2DArray + | ffi::ASTBasicType::ISampler2DMSArray + | ffi::ASTBasicType::ISamplerCubeArray + | ffi::ASTBasicType::IImage2DArray + | ffi::ASTBasicType::IImageCubeArray + | ffi::ASTBasicType::USampler2DArray + | ffi::ASTBasicType::USampler2DMSArray + | ffi::ASTBasicType::USamplerCubeArray + | ffi::ASTBasicType::UImage2DArray + | ffi::ASTBasicType::UImageCubeArray + ); + + let is_ms = matches!( + basic_type, + ffi::ASTBasicType::Sampler2DMS + | ffi::ASTBasicType::Sampler2DMSArray + | ffi::ASTBasicType::ISampler2DMS + | ffi::ASTBasicType::ISampler2DMSArray + | ffi::ASTBasicType::USampler2DMS + | ffi::ASTBasicType::USampler2DMSArray + ); + + let is_shadow = matches!( + basic_type, + ffi::ASTBasicType::Sampler2DShadow + | ffi::ASTBasicType::SamplerCubeShadow + | ffi::ASTBasicType::Sampler2DArrayShadow + | ffi::ASTBasicType::SamplerCubeArrayShadow + ); + + self.builder.ir().meta.get_image_type_id( + image_basic_type, + ImageType { dimension, is_sampled, is_array, is_ms, is_shadow }, + ) + } + }; + + Self::apply_primary_secondary_dimensions( + &mut self.builder, + ir_base_type, + primary_size, + secondary_size, + ) + .into() + } + + fn ast_type_built_in(ast_type: &ffi::ASTType) -> Option { + match ast_type.qualifier { + ffi::ASTQualifier::InstanceID => Some(BuiltIn::InstanceID), + ffi::ASTQualifier::VertexID => Some(BuiltIn::VertexID), + ffi::ASTQualifier::Position => Some(BuiltIn::Position), + ffi::ASTQualifier::PointSize => Some(BuiltIn::PointSize), + ffi::ASTQualifier::BaseVertex => Some(BuiltIn::BaseVertex), + ffi::ASTQualifier::BaseInstance => Some(BuiltIn::BaseInstance), + ffi::ASTQualifier::DrawID => Some(BuiltIn::DrawID), + ffi::ASTQualifier::FragCoord => Some(BuiltIn::FragCoord), + ffi::ASTQualifier::FrontFacing => Some(BuiltIn::FrontFacing), + ffi::ASTQualifier::PointCoord => Some(BuiltIn::PointCoord), + ffi::ASTQualifier::HelperInvocation => Some(BuiltIn::HelperInvocation), + ffi::ASTQualifier::FragColor => Some(BuiltIn::FragColor), + ffi::ASTQualifier::FragData => Some(BuiltIn::FragData), + ffi::ASTQualifier::FragDepth => Some(BuiltIn::FragDepth), + ffi::ASTQualifier::SecondaryFragColorEXT => Some(BuiltIn::SecondaryFragColorEXT), + ffi::ASTQualifier::SecondaryFragDataEXT => Some(BuiltIn::SecondaryFragDataEXT), + ffi::ASTQualifier::ViewIDOVR => Some(BuiltIn::ViewIDOVR), + ffi::ASTQualifier::ClipDistance => Some(BuiltIn::ClipDistance), + ffi::ASTQualifier::CullDistance => Some(BuiltIn::CullDistance), + ffi::ASTQualifier::LastFragColor => Some(BuiltIn::LastFragColor), + ffi::ASTQualifier::LastFragData => Some(BuiltIn::LastFragData), + ffi::ASTQualifier::LastFragDepth => Some(BuiltIn::LastFragDepthARM), + ffi::ASTQualifier::LastFragStencil => Some(BuiltIn::LastFragStencilARM), + ffi::ASTQualifier::DepthRange => Some(BuiltIn::DepthRange), + ffi::ASTQualifier::ShadingRateEXT => Some(BuiltIn::ShadingRateEXT), + ffi::ASTQualifier::PrimitiveShadingRateEXT => Some(BuiltIn::PrimitiveShadingRateEXT), + ffi::ASTQualifier::SampleID => Some(BuiltIn::SampleID), + ffi::ASTQualifier::SamplePosition => Some(BuiltIn::SamplePosition), + ffi::ASTQualifier::SampleMaskIn => Some(BuiltIn::SampleMaskIn), + ffi::ASTQualifier::SampleMask => Some(BuiltIn::SampleMask), + ffi::ASTQualifier::NumSamples => Some(BuiltIn::NumSamples), + ffi::ASTQualifier::NumWorkGroups => Some(BuiltIn::NumWorkGroups), + ffi::ASTQualifier::WorkGroupSize => Some(BuiltIn::WorkGroupSize), + ffi::ASTQualifier::WorkGroupID => Some(BuiltIn::WorkGroupID), + ffi::ASTQualifier::LocalInvocationID => Some(BuiltIn::LocalInvocationID), + ffi::ASTQualifier::GlobalInvocationID => Some(BuiltIn::GlobalInvocationID), + ffi::ASTQualifier::LocalInvocationIndex => Some(BuiltIn::LocalInvocationIndex), + ffi::ASTQualifier::PerVertexIn => Some(BuiltIn::PerVertexIn), + ffi::ASTQualifier::PerVertexOut => Some(BuiltIn::PerVertexOut), + ffi::ASTQualifier::PrimitiveIDIn => Some(BuiltIn::PrimitiveIDIn), + ffi::ASTQualifier::InvocationID => Some(BuiltIn::InvocationID), + ffi::ASTQualifier::PrimitiveID => Some(BuiltIn::PrimitiveID), + ffi::ASTQualifier::LayerOut => Some(BuiltIn::LayerOut), + ffi::ASTQualifier::LayerIn => Some(BuiltIn::LayerIn), + ffi::ASTQualifier::PatchVerticesIn => Some(BuiltIn::PatchVerticesIn), + ffi::ASTQualifier::TessLevelOuter => Some(BuiltIn::TessLevelOuter), + ffi::ASTQualifier::TessLevelInner => Some(BuiltIn::TessLevelInner), + ffi::ASTQualifier::TessCoord => Some(BuiltIn::TessCoord), + ffi::ASTQualifier::BoundingBox => Some(BuiltIn::BoundingBoxOES), + ffi::ASTQualifier::PixelLocalEXT => Some(BuiltIn::PixelLocalEXT), + _ => None, + } + } + + fn ast_type_decorations(ast_type: &ffi::ASTType) -> Decorations { + let mut decorations = Decorations::new(match ast_type.qualifier { + ffi::ASTQualifier::Temporary + | ffi::ASTQualifier::Global + | ffi::ASTQualifier::Const + | ffi::ASTQualifier::InstanceID + | ffi::ASTQualifier::VertexID + | ffi::ASTQualifier::Position + | ffi::ASTQualifier::PointSize + | ffi::ASTQualifier::BaseVertex + | ffi::ASTQualifier::BaseInstance + | ffi::ASTQualifier::DrawID + | ffi::ASTQualifier::FragCoord + | ffi::ASTQualifier::FrontFacing + | ffi::ASTQualifier::PointCoord + | ffi::ASTQualifier::HelperInvocation + | ffi::ASTQualifier::FragColor + | ffi::ASTQualifier::FragData + | ffi::ASTQualifier::FragDepth + | ffi::ASTQualifier::SecondaryFragColorEXT + | ffi::ASTQualifier::SecondaryFragDataEXT + | ffi::ASTQualifier::ViewIDOVR + | ffi::ASTQualifier::ClipDistance + | ffi::ASTQualifier::CullDistance + | ffi::ASTQualifier::LastFragColor + | ffi::ASTQualifier::LastFragData + | ffi::ASTQualifier::LastFragDepth + | ffi::ASTQualifier::LastFragStencil + | ffi::ASTQualifier::DepthRange + | ffi::ASTQualifier::ShadingRateEXT + | ffi::ASTQualifier::PrimitiveShadingRateEXT + | ffi::ASTQualifier::SampleID + | ffi::ASTQualifier::SamplePosition + | ffi::ASTQualifier::SampleMaskIn + | ffi::ASTQualifier::SampleMask + | ffi::ASTQualifier::NumSamples + | ffi::ASTQualifier::NumWorkGroups + | ffi::ASTQualifier::WorkGroupSize + | ffi::ASTQualifier::WorkGroupID + | ffi::ASTQualifier::LocalInvocationID + | ffi::ASTQualifier::GlobalInvocationID + | ffi::ASTQualifier::LocalInvocationIndex + | ffi::ASTQualifier::PerVertexIn + | ffi::ASTQualifier::PrimitiveIDIn + | ffi::ASTQualifier::InvocationID + | ffi::ASTQualifier::PrimitiveID + | ffi::ASTQualifier::LayerOut + | ffi::ASTQualifier::LayerIn + | ffi::ASTQualifier::PerVertexOut + | ffi::ASTQualifier::PatchVerticesIn + | ffi::ASTQualifier::TessLevelOuter + | ffi::ASTQualifier::TessLevelInner + | ffi::ASTQualifier::TessCoord + | ffi::ASTQualifier::BoundingBox => vec![], + + // Parameter directions are separately tracked, the Input/Output decorations are not + // used for function parameters. + ffi::ASTQualifier::ParamIn + | ffi::ASTQualifier::ParamOut + | ffi::ASTQualifier::ParamInOut + | ffi::ASTQualifier::ParamConst => vec![], + + ffi::ASTQualifier::Attribute + | ffi::ASTQualifier::VaryingIn + | ffi::ASTQualifier::VertexIn + | ffi::ASTQualifier::FragmentIn + | ffi::ASTQualifier::GeometryIn + | ffi::ASTQualifier::TessControlIn + | ffi::ASTQualifier::TessEvaluationIn => vec![Decoration::Input], + + ffi::ASTQualifier::VaryingOut + | ffi::ASTQualifier::FragmentOut + | ffi::ASTQualifier::VertexOut + | ffi::ASTQualifier::GeometryOut + | ffi::ASTQualifier::TessControlOut + | ffi::ASTQualifier::TessEvaluationOut => vec![Decoration::Output], + + ffi::ASTQualifier::FragmentInOut => vec![Decoration::InputOutput], + + ffi::ASTQualifier::Uniform => vec![Decoration::Uniform], + ffi::ASTQualifier::Buffer => vec![Decoration::Buffer], + ffi::ASTQualifier::Shared => vec![Decoration::Shared], + + ffi::ASTQualifier::Smooth => vec![Decoration::Smooth], + ffi::ASTQualifier::Flat => vec![Decoration::Flat], + ffi::ASTQualifier::NoPerspective => vec![Decoration::NoPerspective], + ffi::ASTQualifier::Centroid => vec![Decoration::Centroid], + ffi::ASTQualifier::Sample => vec![Decoration::Sample], + ffi::ASTQualifier::NoPerspectiveCentroid => { + vec![Decoration::NoPerspective, Decoration::Centroid] + } + ffi::ASTQualifier::NoPerspectiveSample => { + vec![Decoration::NoPerspective, Decoration::Sample] + } + ffi::ASTQualifier::Patch => vec![Decoration::Patch], + + ffi::ASTQualifier::SmoothOut => vec![Decoration::Output, Decoration::Smooth], + ffi::ASTQualifier::FlatOut => vec![Decoration::Output, Decoration::Flat], + ffi::ASTQualifier::NoPerspectiveOut => { + vec![Decoration::Output, Decoration::NoPerspective] + } + ffi::ASTQualifier::CentroidOut => vec![Decoration::Output, Decoration::Centroid], + ffi::ASTQualifier::SampleOut => vec![Decoration::Output, Decoration::Sample], + ffi::ASTQualifier::NoPerspectiveCentroidOut => { + vec![Decoration::Output, Decoration::NoPerspective, Decoration::Centroid] + } + ffi::ASTQualifier::NoPerspectiveSampleOut => { + vec![Decoration::Output, Decoration::NoPerspective, Decoration::Sample] + } + ffi::ASTQualifier::PatchOut => vec![Decoration::Output, Decoration::Patch], + + ffi::ASTQualifier::SmoothIn => vec![Decoration::Input, Decoration::Smooth], + ffi::ASTQualifier::FlatIn => vec![Decoration::Input, Decoration::Flat], + ffi::ASTQualifier::NoPerspectiveIn => { + vec![Decoration::Input, Decoration::NoPerspective] + } + ffi::ASTQualifier::CentroidIn => vec![Decoration::Input, Decoration::Centroid], + ffi::ASTQualifier::SampleIn => vec![Decoration::Input, Decoration::Sample], + ffi::ASTQualifier::NoPerspectiveCentroidIn => { + vec![Decoration::Input, Decoration::NoPerspective, Decoration::Centroid] + } + ffi::ASTQualifier::NoPerspectiveSampleIn => { + vec![Decoration::Input, Decoration::NoPerspective, Decoration::Sample] + } + ffi::ASTQualifier::PatchIn => vec![Decoration::Input, Decoration::Patch], + + ffi::ASTQualifier::PixelLocalEXT => unimplemented!(), + _ => panic!("Internal error: Unexpected qualifier"), + }); + + if ast_type.invariant { + decorations.decorations.push(Decoration::Invariant); + } + if ast_type.precise { + decorations.decorations.push(Decoration::Precise); + } + if ast_type.interpolant { + decorations.decorations.push(Decoration::Interpolant); + } + + if ast_type.memory_qualifier.readonly { + decorations.decorations.push(Decoration::ReadOnly); + } + if ast_type.memory_qualifier.writeonly { + decorations.decorations.push(Decoration::WriteOnly); + } + if ast_type.memory_qualifier.coherent { + decorations.decorations.push(Decoration::Coherent); + } + if ast_type.memory_qualifier.restrict_qualifier { + decorations.decorations.push(Decoration::Restrict); + } + if ast_type.memory_qualifier.volatile_qualifier { + decorations.decorations.push(Decoration::Volatile); + } + + if ast_type.layout_qualifier.location >= 0 { + decorations + .decorations + .push(Decoration::Location(ast_type.layout_qualifier.location as u32)); + } + if ast_type.layout_qualifier.index >= 0 { + decorations.decorations.push(Decoration::Index(ast_type.layout_qualifier.index as u32)); + } + if ast_type.layout_qualifier.binding >= 0 { + decorations + .decorations + .push(Decoration::Binding(ast_type.layout_qualifier.binding as u32)); + } + if ast_type.layout_qualifier.offset >= 0 { + decorations + .decorations + .push(Decoration::Offset(ast_type.layout_qualifier.offset as u32)); + } + if ast_type.layout_qualifier.num_views >= 0 { + decorations + .decorations + .push(Decoration::NumViews(ast_type.layout_qualifier.num_views as u32)); + } + if ast_type.layout_qualifier.yuv { + decorations.decorations.push(Decoration::Yuv); + } + if ast_type.layout_qualifier.noncoherent { + decorations.decorations.push(Decoration::NonCoherent); + } + + match ast_type.layout_qualifier.matrix_packing { + ffi::ASTLayoutMatrixPacking::RowMajor => { + decorations.decorations.push(Decoration::MatrixPacking(MatrixPacking::RowMajor)) + } + ffi::ASTLayoutMatrixPacking::ColumnMajor => { + decorations.decorations.push(Decoration::MatrixPacking(MatrixPacking::ColumnMajor)) + } + ffi::ASTLayoutMatrixPacking::Unspecified => (), + _ => panic!("Internal error: Unexpected matrix packing enum value"), + }; + + match ast_type.layout_qualifier.block_storage { + ffi::ASTLayoutBlockStorage::Shared => { + decorations.decorations.push(Decoration::Block(BlockStorage::Shared)) + } + ffi::ASTLayoutBlockStorage::Packed => { + decorations.decorations.push(Decoration::Block(BlockStorage::Packed)) + } + ffi::ASTLayoutBlockStorage::Std140 => { + decorations.decorations.push(Decoration::Block(BlockStorage::Std140)) + } + ffi::ASTLayoutBlockStorage::Std430 => { + decorations.decorations.push(Decoration::Block(BlockStorage::Std430)) + } + ffi::ASTLayoutBlockStorage::Unspecified => (), + _ => panic!("Internal error: Unexpected block storage enum value"), + }; + + match ast_type.layout_qualifier.depth { + ffi::ASTLayoutDepth::Any => decorations.decorations.push(Decoration::Depth(Depth::Any)), + ffi::ASTLayoutDepth::Greater => { + decorations.decorations.push(Decoration::Depth(Depth::Greater)) + } + ffi::ASTLayoutDepth::Less => { + decorations.decorations.push(Decoration::Depth(Depth::Less)) + } + ffi::ASTLayoutDepth::Unchanged => { + decorations.decorations.push(Decoration::Depth(Depth::Unchanged)) + } + ffi::ASTLayoutDepth::Unspecified => (), + _ => panic!("Internal error: Unexpected depth enum value"), + }; + + match ast_type.layout_qualifier.image_internal_format { + ffi::ASTLayoutImageInternalFormat::RGBA32F => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA32F)), + ffi::ASTLayoutImageInternalFormat::RGBA16F => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA16F)), + ffi::ASTLayoutImageInternalFormat::R32F => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::R32F)), + ffi::ASTLayoutImageInternalFormat::RGBA32UI => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA32UI)), + ffi::ASTLayoutImageInternalFormat::RGBA16UI => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA16UI)), + ffi::ASTLayoutImageInternalFormat::RGBA8UI => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA8UI)), + ffi::ASTLayoutImageInternalFormat::R32UI => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::R32UI)), + ffi::ASTLayoutImageInternalFormat::RGBA32I => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA32I)), + ffi::ASTLayoutImageInternalFormat::RGBA16I => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA16I)), + ffi::ASTLayoutImageInternalFormat::RGBA8I => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA8I)), + ffi::ASTLayoutImageInternalFormat::R32I => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::R32I)), + ffi::ASTLayoutImageInternalFormat::RGBA8 => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA8)), + ffi::ASTLayoutImageInternalFormat::RGBA8SNORM => decorations + .decorations + .push(Decoration::ImageInternalFormat(ImageInternalFormat::RGBA8SNORM)), + ffi::ASTLayoutImageInternalFormat::Unspecified => (), + _ => panic!("Internal error: Unexpected image internal format enum value"), + }; + + decorations + } + + fn get_struct_type_id(&mut self, struct_info: &ffi::ASTStruct) -> ffi::TypeId { + let fields = struct_info + .fields + .iter() + .map(|field| { + Field::new( + if struct_info.is_internal { + Name::new_exact(field.name) + } else { + Name::new_temp(field.name) + }, + field.ast_type.type_id.into(), + field.ast_type.precision.into(), + Self::ast_type_decorations(&field.ast_type), + ) + }) + .collect::>(); + + let (name, specialization) = if struct_info.is_interface_block { + ( + if struct_info.is_internal { + Name::new_exact(struct_info.name) + } else { + Name::new_interface(struct_info.name) + }, + StructSpecialization::InterfaceBlock, + ) + } else { + ( + if struct_info.is_internal { + Name::new_exact(struct_info.name) + } else if struct_info.is_at_global_scope { + Name::new_interface(struct_info.name) + } else { + Name::new_temp(struct_info.name) + }, + StructSpecialization::Struct, + ) + }; + + self.builder.ir().meta.get_struct_type_id(name, fields, specialization).into() + } + + fn get_array_type_id( + &mut self, + element_type_id: ffi::TypeId, + array_sizes: &[u32], + ) -> ffi::TypeId { + array_sizes + .iter() + .fold(element_type_id.into(), |element_type_id, &array_size| { + if array_size == 0 { + self.builder.ir().meta.get_unsized_array_type_id(element_type_id) + } else { + self.builder.ir().meta.get_array_type_id(element_type_id, array_size) + } + }) + .into() + } + + fn set_early_fragment_tests(&mut self, value: bool) { + self.builder.ir().meta.set_early_fragment_tests(value); + } + + fn set_advanced_blend_equations(&mut self, value: u32) { + // Identical to gl::BlendEquationType, only including advanced blend equations. + const BLEND_MULTIPLY: u32 = 1 << 6; + const BLEND_SCREEN: u32 = 1 << 7; + const BLEND_OVERLAY: u32 = 1 << 8; + const BLEND_DARKEN: u32 = 1 << 9; + const BLEND_LIGHTEN: u32 = 1 << 10; + const BLEND_COLORDODGE: u32 = 1 << 11; + const BLEND_COLORBURN: u32 = 1 << 12; + const BLEND_HARDLIGHT: u32 = 1 << 13; + const BLEND_SOFTLIGHT: u32 = 1 << 14; + const BLEND_DIFFERENCE: u32 = 1 << 16; + const BLEND_EXCLUSION: u32 = 1 << 18; + const BLEND_HSL_HUE: u32 = 1 << 19; + const BLEND_HSL_SATURATION: u32 = 1 << 20; + const BLEND_HSL_COLOR: u32 = 1 << 21; + const BLEND_HSL_LUMINOSITY: u32 = 1 << 22; + + let mut equations = AdvancedBlendEquations::new(); + + if value & BLEND_MULTIPLY != 0 { + equations.multiply = true; + } + if value & BLEND_SCREEN != 0 { + equations.screen = true; + } + if value & BLEND_OVERLAY != 0 { + equations.overlay = true; + } + if value & BLEND_DARKEN != 0 { + equations.darken = true; + } + if value & BLEND_LIGHTEN != 0 { + equations.lighten = true; + } + if value & BLEND_COLORDODGE != 0 { + equations.colordodge = true; + } + if value & BLEND_COLORBURN != 0 { + equations.colorburn = true; + } + if value & BLEND_HARDLIGHT != 0 { + equations.hardlight = true; + } + if value & BLEND_SOFTLIGHT != 0 { + equations.softlight = true; + } + if value & BLEND_DIFFERENCE != 0 { + equations.difference = true; + } + if value & BLEND_EXCLUSION != 0 { + equations.exclusion = true; + } + if value & BLEND_HSL_HUE != 0 { + equations.hsl_hue = true; + } + if value & BLEND_HSL_SATURATION != 0 { + equations.hsl_saturation = true; + } + if value & BLEND_HSL_COLOR != 0 { + equations.hsl_color = true; + } + if value & BLEND_HSL_LUMINOSITY != 0 { + equations.hsl_luminosity = true; + } + + self.builder.ir().meta.add_advanced_blend_equations(equations); + } + + fn set_tcs_vertices(&mut self, value: u32) { + self.builder.ir().meta.set_tcs_vertices(value); + } + + fn set_tes_primitive(&mut self, value: ffi::ASTLayoutTessEvaluationType) { + self.builder.ir().meta.set_tes_primitive(value.into()); + } + + fn set_tes_vertex_spacing(&mut self, value: ffi::ASTLayoutTessEvaluationType) { + self.builder.ir().meta.set_tes_vertex_spacing(value.into()); + } + + fn set_tes_ordering(&mut self, value: ffi::ASTLayoutTessEvaluationType) { + self.builder.ir().meta.set_tes_ordering(value.into()); + } + + fn set_tes_point_mode(&mut self, value: ffi::ASTLayoutTessEvaluationType) { + self.builder + .ir() + .meta + .set_tes_point_mode(value == ffi::ASTLayoutTessEvaluationType::PointMode); + } + + fn set_gs_primitive_in(&mut self, value: ffi::ASTLayoutPrimitiveType) { + self.builder.ir().meta.set_gs_primitive_in(value.into()); + } + + fn set_gs_primitive_out(&mut self, value: ffi::ASTLayoutPrimitiveType) { + self.builder.ir().meta.set_gs_primitive_out(value.into()); + } + + fn set_gs_invocations(&mut self, value: u32) { + self.builder.ir().meta.set_gs_invocations(value); + } + + fn set_gs_max_vertices(&mut self, value: u32) { + self.builder.ir().meta.set_gs_max_vertices(value); + } + + // `is_declaration_internal` is used to know if a built-in is redeclared or not, which matters + // for some backends when generating output. + fn declare_interface_variable( + &mut self, + name: &'static str, + ast_type: &ffi::ASTType, + is_declaration_internal: bool, + ) -> ffi::VariableId { + if let Some(built_in) = Self::ast_type_built_in(ast_type) { + let variable_id = self.builder.declare_built_in_variable( + built_in, + ast_type.type_id.into(), + ast_type.precision.into(), + Self::ast_type_decorations(ast_type), + ); + + if !is_declaration_internal { + match ast_type.qualifier { + ffi::ASTQualifier::PerVertexIn => { + self.builder.ir().meta.on_per_vertex_in_redeclaration() + } + ffi::ASTQualifier::PerVertexOut => { + self.builder.ir().meta.on_per_vertex_out_redeclaration() + } + _ => {} + }; + } + + variable_id + } else { + debug_assert!(!is_declaration_internal); + self.builder.declare_interface_variable( + name, + ast_type.type_id.into(), + ast_type.precision.into(), + Self::ast_type_decorations(ast_type), + ) + } + .into() + } + + fn declare_temp_variable( + &mut self, + name: &'static str, + ast_type: &ffi::ASTType, + ) -> ffi::VariableId { + if ast_type.qualifier == ffi::ASTQualifier::Const { + self.builder.declare_const_variable(ast_type.type_id.into(), ast_type.precision.into()) + } else { + self.builder.declare_temp_variable( + name, + ast_type.type_id.into(), + ast_type.precision.into(), + Self::ast_type_decorations(ast_type), + ) + } + .into() + } + + fn mark_variable_invariant(&mut self, variable_id: ffi::VariableId) { + self.builder.mark_variable_invariant(variable_id.into()); + } + + fn mark_variable_precise(&mut self, variable_id: ffi::VariableId) { + self.builder.mark_variable_precise(variable_id.into()); + } + + fn function_param_direction(qualifier: ffi::ASTQualifier) -> FunctionParamDirection { + match qualifier { + ffi::ASTQualifier::ParamIn | ffi::ASTQualifier::ParamConst => { + FunctionParamDirection::Input + } + ffi::ASTQualifier::ParamOut => FunctionParamDirection::Output, + ffi::ASTQualifier::ParamInOut => FunctionParamDirection::InputOutput, + _ => panic!("Internal error: Unexpected qualifier on function parameter"), + } + } + + fn new_function( + &mut self, + name: &'static str, + params: &[ffi::VariableId], + param_directions: &[ffi::ASTQualifier], + return_type_id: ffi::TypeId, + return_ast_type: &ffi::ASTType, + ) -> ffi::FunctionId { + let params = params + .iter() + .map(|&id| id.into()) + .zip( + param_directions.iter().map(|&qualifier| Self::function_param_direction(qualifier)), + ) + .map(|(id, dir)| FunctionParam::new(id, dir)) + .collect(); + self.builder + .new_function( + name, + params, + return_type_id.into(), + return_ast_type.precision.into(), + Self::ast_type_decorations(return_ast_type), + ) + .into() + } + + fn update_function_param_names( + self: &mut BuilderWrapper, + id: ffi::FunctionId, + param_names: &[&'static str], + param_ids: &mut [ffi::VariableId], + ) { + let ids = self.builder.update_function_param_names(id.into(), param_names); + debug_assert!(ids.len() == param_ids.len()); + + ids.iter().zip(param_ids.iter_mut()).for_each(|(id, out)| *out = (*id).into()); + } + + fn declare_function_param( + &mut self, + name: &'static str, + type_id: ffi::TypeId, + ast_type: &ffi::ASTType, + direction: ffi::ASTQualifier, + ) -> ffi::VariableId { + self.builder + .declare_function_param( + name, + type_id.into(), + ast_type.precision.into(), + Self::ast_type_decorations(ast_type), + Self::function_param_direction(direction), + ) + .into() + } + + fn begin_function(&mut self, id: ffi::FunctionId) { + self.builder.begin_function(id.into()); + } + + fn end_function(&mut self) { + self.builder.end_function(); + } + + fn store(&mut self) { + self.builder.store(); + } + + fn initialize(&mut self, id: ffi::VariableId) { + self.builder.initialize(id.into()); + } + + fn begin_if_true_block(&mut self) { + self.builder.begin_if_true_block(); + } + + fn end_if_true_block(&mut self) { + self.builder.end_if_true_block(); + } + + fn begin_if_false_block(&mut self) { + self.builder.begin_if_false_block(); + } + + fn end_if_false_block(&mut self) { + self.builder.end_if_false_block(); + } + + fn end_if(&mut self) { + self.builder.end_if(); + } + + fn begin_ternary_true_expression(&mut self) { + self.builder.begin_ternary_true_expression(); + } + + fn end_ternary_true_expression(&mut self, is_void: bool) { + if is_void { + self.builder.end_ternary_true_expression_void(); + } else { + self.builder.end_ternary_true_expression(); + } + } + + fn begin_ternary_false_expression(&mut self) { + self.builder.begin_ternary_false_expression(); + } + + fn end_ternary_false_expression(&mut self, is_void: bool) { + if is_void { + self.builder.end_ternary_false_expression_void(); + } else { + self.builder.end_ternary_false_expression(); + } + } + + fn end_ternary(&mut self, is_void: bool) { + if is_void { + self.builder.end_ternary_void(); + } else { + self.builder.end_ternary(); + } + } + + fn begin_short_circuit_or(&mut self) { + self.builder.begin_short_circuit_or(); + } + + fn end_short_circuit_or(&mut self) { + self.builder.end_short_circuit_or(); + } + + fn begin_short_circuit_and(&mut self) { + self.builder.begin_short_circuit_and(); + } + + fn end_short_circuit_and(&mut self) { + self.builder.end_short_circuit_and(); + } + + fn begin_loop_condition(&mut self) { + self.builder.begin_loop_condition(); + } + + fn end_loop_condition(&mut self) { + self.builder.end_loop_condition(); + } + + fn end_loop_continue(&mut self) { + self.builder.end_loop_continue(); + } + + fn end_loop(&mut self) { + self.builder.end_loop(); + } + + fn begin_do_loop(&mut self) { + self.builder.begin_do_loop(); + } + + fn begin_do_loop_condition(&mut self) { + self.builder.begin_do_loop_condition(); + } + + fn end_do_loop(&mut self) { + self.builder.end_do_loop(); + } + + fn begin_switch(&mut self) { + self.builder.begin_switch(); + } + + fn begin_case(&mut self) { + self.builder.begin_case(); + } + + fn begin_default(&mut self) { + self.builder.begin_default(); + } + + fn end_switch(&mut self) { + self.builder.end_switch(); + } + + fn branch_discard(&mut self) { + self.builder.branch_discard(); + } + + fn branch_return(&mut self) { + self.builder.branch_return(); + } + + fn branch_return_value(&mut self) { + self.builder.branch_return_value(); + } + + fn branch_break(&mut self) { + self.builder.branch_break(); + } + + fn branch_continue(&mut self) { + self.builder.branch_continue(); + } + + fn pop_array_size(&mut self) -> u32 { + self.builder.pop_array_size() + } + + fn end_statement_with_value(&mut self) { + self.builder.end_statement_with_value(); + } + + fn push_constant_float(&mut self, value: f32) { + self.builder.push_constant_float(value); + } + + fn push_constant_int(&mut self, value: i32) { + self.builder.push_constant_int(value); + } + + fn push_constant_uint(&mut self, value: u32) { + self.builder.push_constant_uint(value); + } + + fn push_constant_bool(&mut self, value: bool) { + self.builder.push_constant_bool(value); + } + + fn push_constant_yuv_csc_standard(&mut self, value: ffi::ASTYuvCscStandardEXT) { + self.builder.push_constant_yuv_csc_standard(value.into()); + } + + fn push_variable(&mut self, id: ffi::VariableId) { + self.builder.push_variable(id.into()); + } + + fn call_function(&mut self, id: ffi::FunctionId) { + self.builder.call_function(id.into()); + } + + fn vector_component(&mut self, component: u32) { + self.builder.vector_component(component); + } + + fn vector_component_multi(&mut self, components: &[u32]) { + self.builder.vector_component_multi(components.to_vec()); + } + + fn index(&mut self) { + self.builder.index(); + } + + fn struct_field(&mut self, field_index: u32) { + self.builder.struct_field(field_index); + } + + fn construct(&mut self, type_id: ffi::TypeId, arg_count: usize) { + self.builder.construct(type_id.into(), arg_count); + } + + fn on_gl_clip_distance_sized(&mut self, id: ffi::VariableId, length: u32) { + self.builder.on_gl_clip_distance_sized(id.into(), length); + } + + fn on_gl_cull_distance_sized(&mut self, id: ffi::VariableId, length: u32) { + self.builder.on_gl_cull_distance_sized(id.into(), length); + } + + fn array_length(&mut self) { + self.builder.array_length(); + } + + fn negate(&mut self) { + self.builder.negate(); + } + + fn postfix_increment(&mut self) { + self.builder.postfix_increment(); + } + + fn postfix_decrement(&mut self) { + self.builder.postfix_decrement(); + } + + fn prefix_increment(&mut self) { + self.builder.prefix_increment(); + } + + fn prefix_decrement(&mut self) { + self.builder.prefix_decrement(); + } + + fn add(&mut self) { + self.builder.add(); + } + + fn add_assign(&mut self) { + self.builder.add_assign(); + } + + fn sub(&mut self) { + self.builder.sub(); + } + + fn sub_assign(&mut self) { + self.builder.sub_assign(); + } + + fn mul(&mut self) { + self.builder.mul(); + } + + fn mul_assign(&mut self) { + self.builder.mul_assign(); + } + + fn vector_times_scalar(&mut self) { + self.builder.vector_times_scalar(); + } + + fn vector_times_scalar_assign(&mut self) { + self.builder.vector_times_scalar_assign(); + } + + fn matrix_times_scalar(&mut self) { + self.builder.matrix_times_scalar(); + } + + fn matrix_times_scalar_assign(&mut self) { + self.builder.matrix_times_scalar_assign(); + } + + fn vector_times_matrix(&mut self) { + self.builder.vector_times_matrix(); + } + + fn vector_times_matrix_assign(&mut self) { + self.builder.vector_times_matrix_assign(); + } + + fn matrix_times_vector(&mut self) { + self.builder.matrix_times_vector(); + } + + fn matrix_times_matrix(&mut self) { + self.builder.matrix_times_matrix(); + } + + fn matrix_times_matrix_assign(&mut self) { + self.builder.matrix_times_matrix_assign(); + } + + fn div(&mut self) { + self.builder.div(); + } + + fn div_assign(&mut self) { + self.builder.div_assign(); + } + + fn imod(&mut self) { + self.builder.imod(); + } + + fn imod_assign(&mut self) { + self.builder.imod_assign(); + } + + fn logical_not(&mut self) { + self.builder.logical_not(); + } + + fn logical_xor(&mut self) { + self.builder.logical_xor(); + } + + fn equal(&mut self) { + self.builder.equal(); + } + + fn not_equal(&mut self) { + self.builder.not_equal(); + } + + fn less_than(&mut self) { + self.builder.less_than(); + } + + fn greater_than(&mut self) { + self.builder.greater_than(); + } + + fn less_than_equal(&mut self) { + self.builder.less_than_equal(); + } + + fn greater_than_equal(&mut self) { + self.builder.greater_than_equal(); + } + + fn bitwise_not(&mut self) { + self.builder.bitwise_not(); + } + + fn bit_shift_left(&mut self) { + self.builder.bit_shift_left(); + } + + fn bit_shift_left_assign(&mut self) { + self.builder.bit_shift_left_assign(); + } + + fn bit_shift_right(&mut self) { + self.builder.bit_shift_right(); + } + + fn bit_shift_right_assign(&mut self) { + self.builder.bit_shift_right_assign(); + } + + fn bitwise_or(&mut self) { + self.builder.bitwise_or(); + } + + fn bitwise_or_assign(&mut self) { + self.builder.bitwise_or_assign(); + } + + fn bitwise_xor(&mut self) { + self.builder.bitwise_xor(); + } + + fn bitwise_xor_assign(&mut self) { + self.builder.bitwise_xor_assign(); + } + + fn bitwise_and(&mut self) { + self.builder.bitwise_and(); + } + + fn bitwise_and_assign(&mut self) { + self.builder.bitwise_and_assign(); + } + + fn built_in_radians(&mut self) { + self.builder.built_in_radians(); + } + + fn built_in_degrees(&mut self) { + self.builder.built_in_degrees(); + } + + fn built_in_sin(&mut self) { + self.builder.built_in_sin(); + } + + fn built_in_cos(&mut self) { + self.builder.built_in_cos(); + } + + fn built_in_tan(&mut self) { + self.builder.built_in_tan(); + } + + fn built_in_asin(&mut self) { + self.builder.built_in_asin(); + } + + fn built_in_acos(&mut self) { + self.builder.built_in_acos(); + } + + fn built_in_atan(&mut self) { + self.builder.built_in_atan(); + } + + fn built_in_sinh(&mut self) { + self.builder.built_in_sinh(); + } + + fn built_in_cosh(&mut self) { + self.builder.built_in_cosh(); + } + + fn built_in_tanh(&mut self) { + self.builder.built_in_tanh(); + } + + fn built_in_asinh(&mut self) { + self.builder.built_in_asinh(); + } + + fn built_in_acosh(&mut self) { + self.builder.built_in_acosh(); + } + + fn built_in_atanh(&mut self) { + self.builder.built_in_atanh(); + } + + fn built_in_atan_binary(&mut self) { + self.builder.built_in_atan_binary(); + } + + fn built_in_pow(&mut self) { + self.builder.built_in_pow(); + } + + fn built_in_exp(&mut self) { + self.builder.built_in_exp(); + } + + fn built_in_log(&mut self) { + self.builder.built_in_log(); + } + + fn built_in_exp2(&mut self) { + self.builder.built_in_exp2(); + } + + fn built_in_log2(&mut self) { + self.builder.built_in_log2(); + } + + fn built_in_sqrt(&mut self) { + self.builder.built_in_sqrt(); + } + + fn built_in_inversesqrt(&mut self) { + self.builder.built_in_inversesqrt(); + } + + fn built_in_abs(&mut self) { + self.builder.built_in_abs(); + } + + fn built_in_sign(&mut self) { + self.builder.built_in_sign(); + } + + fn built_in_floor(&mut self) { + self.builder.built_in_floor(); + } + + fn built_in_trunc(&mut self) { + self.builder.built_in_trunc(); + } + + fn built_in_round(&mut self) { + self.builder.built_in_round(); + } + + fn built_in_roundeven(&mut self) { + self.builder.built_in_roundeven(); + } + + fn built_in_ceil(&mut self) { + self.builder.built_in_ceil(); + } + + fn built_in_fract(&mut self) { + self.builder.built_in_fract(); + } + + fn built_in_mod(&mut self) { + self.builder.built_in_mod(); + } + + fn built_in_min(&mut self) { + self.builder.built_in_min(); + } + + fn built_in_max(&mut self) { + self.builder.built_in_max(); + } + + fn built_in_clamp(&mut self) { + self.builder.built_in_clamp(); + } + + fn built_in_mix(&mut self) { + self.builder.built_in_mix(); + } + + fn built_in_step(&mut self) { + self.builder.built_in_step(); + } + + fn built_in_smoothstep(&mut self) { + self.builder.built_in_smoothstep(); + } + + fn built_in_modf(&mut self) { + self.builder.built_in_modf(); + } + + fn built_in_isnan(&mut self) { + self.builder.built_in_isnan(); + } + + fn built_in_isinf(&mut self) { + self.builder.built_in_isinf(); + } + + fn built_in_floatbitstoint(&mut self) { + self.builder.built_in_floatbitstoint(); + } + + fn built_in_floatbitstouint(&mut self) { + self.builder.built_in_floatbitstouint(); + } + + fn built_in_intbitstofloat(&mut self) { + self.builder.built_in_intbitstofloat(); + } + + fn built_in_uintbitstofloat(&mut self) { + self.builder.built_in_uintbitstofloat(); + } + + fn built_in_fma(&mut self) { + self.builder.built_in_fma(); + } + + fn built_in_frexp(&mut self) { + self.builder.built_in_frexp(); + } + + fn built_in_ldexp(&mut self) { + self.builder.built_in_ldexp(); + } + + fn built_in_packsnorm2x16(&mut self) { + self.builder.built_in_packsnorm2x16(); + } + + fn built_in_packhalf2x16(&mut self) { + self.builder.built_in_packhalf2x16(); + } + + fn built_in_unpacksnorm2x16(&mut self) { + self.builder.built_in_unpacksnorm2x16(); + } + + fn built_in_unpackhalf2x16(&mut self) { + self.builder.built_in_unpackhalf2x16(); + } + + fn built_in_packunorm2x16(&mut self) { + self.builder.built_in_packunorm2x16(); + } + + fn built_in_unpackunorm2x16(&mut self) { + self.builder.built_in_unpackunorm2x16(); + } + + fn built_in_packunorm4x8(&mut self) { + self.builder.built_in_packunorm4x8(); + } + + fn built_in_packsnorm4x8(&mut self) { + self.builder.built_in_packsnorm4x8(); + } + + fn built_in_unpackunorm4x8(&mut self) { + self.builder.built_in_unpackunorm4x8(); + } + + fn built_in_unpacksnorm4x8(&mut self) { + self.builder.built_in_unpacksnorm4x8(); + } + + fn built_in_length(&mut self) { + self.builder.built_in_length(); + } + + fn built_in_distance(&mut self) { + self.builder.built_in_distance(); + } + + fn built_in_dot(&mut self) { + self.builder.built_in_dot(); + } + + fn built_in_cross(&mut self) { + self.builder.built_in_cross(); + } + + fn built_in_normalize(&mut self) { + self.builder.built_in_normalize(); + } + + fn built_in_faceforward(&mut self) { + self.builder.built_in_faceforward(); + } + + fn built_in_reflect(&mut self) { + self.builder.built_in_reflect(); + } + + fn built_in_refract(&mut self) { + self.builder.built_in_refract(); + } + + fn built_in_matrixcompmult(&mut self) { + self.builder.built_in_matrixcompmult(); + } + + fn built_in_outerproduct(&mut self) { + self.builder.built_in_outerproduct(); + } + + fn built_in_transpose(&mut self) { + self.builder.built_in_transpose(); + } + + fn built_in_determinant(&mut self) { + self.builder.built_in_determinant(); + } + + fn built_in_inverse(&mut self) { + self.builder.built_in_inverse(); + } + + fn built_in_lessthan(&mut self) { + self.builder.built_in_lessthan(); + } + + fn built_in_lessthanequal(&mut self) { + self.builder.built_in_lessthanequal(); + } + + fn built_in_greaterthan(&mut self) { + self.builder.built_in_greaterthan(); + } + + fn built_in_greaterthanequal(&mut self) { + self.builder.built_in_greaterthanequal(); + } + + fn built_in_equal(&mut self) { + self.builder.built_in_equal(); + } + + fn built_in_notequal(&mut self) { + self.builder.built_in_notequal(); + } + + fn built_in_any(&mut self) { + self.builder.built_in_any(); + } + + fn built_in_all(&mut self) { + self.builder.built_in_all(); + } + + fn built_in_not(&mut self) { + self.builder.built_in_not(); + } + + fn built_in_bitfieldextract(&mut self) { + self.builder.built_in_bitfieldextract(); + } + + fn built_in_bitfieldinsert(&mut self) { + self.builder.built_in_bitfieldinsert(); + } + + fn built_in_bitfieldreverse(&mut self) { + self.builder.built_in_bitfieldreverse(); + } + + fn built_in_bitcount(&mut self) { + self.builder.built_in_bitcount(); + } + + fn built_in_findlsb(&mut self) { + self.builder.built_in_findlsb(); + } + + fn built_in_findmsb(&mut self) { + self.builder.built_in_findmsb(); + } + + fn built_in_uaddcarry(&mut self) { + self.builder.built_in_uaddcarry(); + } + + fn built_in_usubborrow(&mut self) { + self.builder.built_in_usubborrow(); + } + + fn built_in_umulextended(&mut self) { + self.builder.built_in_umulextended(); + } + + fn built_in_imulextended(&mut self) { + self.builder.built_in_imulextended(); + } + + fn built_in_texturesize(&mut self, with_lod: bool) { + self.builder.built_in_texturesize(with_lod); + } + + fn built_in_texturequerylod(&mut self) { + self.builder.built_in_texturequerylod(); + } + + fn built_in_texelfetch(&mut self, with_lod_or_sample: bool) { + self.builder.built_in_texelfetch(with_lod_or_sample); + } + + fn built_in_texelfetchoffset(&mut self) { + self.builder.built_in_texelfetchoffset(); + } + + fn built_in_rgb_2_yuv(&mut self) { + self.builder.built_in_rgb_2_yuv(); + } + + fn built_in_yuv_2_rgb(&mut self) { + self.builder.built_in_yuv_2_rgb(); + } + + fn built_in_dfdx(&mut self) { + self.builder.built_in_dfdx(); + } + + fn built_in_dfdy(&mut self) { + self.builder.built_in_dfdy(); + } + + fn built_in_fwidth(&mut self) { + self.builder.built_in_fwidth(); + } + + fn built_in_interpolateatcentroid(&mut self) { + self.builder.built_in_interpolateatcentroid(); + } + + fn built_in_interpolateatsample(&mut self) { + self.builder.built_in_interpolateatsample(); + } + + fn built_in_interpolateatoffset(&mut self) { + self.builder.built_in_interpolateatoffset(); + } + + fn built_in_atomiccounter(&mut self) { + self.builder.built_in_atomiccounter(); + } + + fn built_in_atomiccounterincrement(&mut self) { + self.builder.built_in_atomiccounterincrement(); + } + + fn built_in_atomiccounterdecrement(&mut self) { + self.builder.built_in_atomiccounterdecrement(); + } + + fn built_in_atomicadd(&mut self) { + self.builder.built_in_atomicadd(); + } + + fn built_in_atomicmin(&mut self) { + self.builder.built_in_atomicmin(); + } + + fn built_in_atomicmax(&mut self) { + self.builder.built_in_atomicmax(); + } + + fn built_in_atomicand(&mut self) { + self.builder.built_in_atomicand(); + } + + fn built_in_atomicor(&mut self) { + self.builder.built_in_atomicor(); + } + + fn built_in_atomicxor(&mut self) { + self.builder.built_in_atomicxor(); + } + + fn built_in_atomicexchange(&mut self) { + self.builder.built_in_atomicexchange(); + } + + fn built_in_atomiccompswap(&mut self) { + self.builder.built_in_atomiccompswap(); + } + + fn built_in_imagesize(&mut self) { + self.builder.built_in_imagesize(); + } + + fn built_in_imagestore(&mut self) { + self.builder.built_in_imagestore(); + } + + fn built_in_imageload(&mut self) { + self.builder.built_in_imageload(); + } + + fn built_in_imageatomicadd(&mut self) { + self.builder.built_in_imageatomicadd(); + } + + fn built_in_imageatomicmin(&mut self) { + self.builder.built_in_imageatomicmin(); + } + + fn built_in_imageatomicmax(&mut self) { + self.builder.built_in_imageatomicmax(); + } + + fn built_in_imageatomicand(&mut self) { + self.builder.built_in_imageatomicand(); + } + + fn built_in_imageatomicor(&mut self) { + self.builder.built_in_imageatomicor(); + } + + fn built_in_imageatomicxor(&mut self) { + self.builder.built_in_imageatomicxor(); + } + + fn built_in_imageatomicexchange(&mut self) { + self.builder.built_in_imageatomicexchange(); + } + + fn built_in_imageatomiccompswap(&mut self) { + self.builder.built_in_imageatomiccompswap(); + } + + fn built_in_pixellocalloadangle(&mut self) { + self.builder.built_in_pixellocalloadangle(); + } + + fn built_in_pixellocalstoreangle(&mut self) { + self.builder.built_in_pixellocalstoreangle(); + } + + fn built_in_memorybarrier(&mut self) { + self.builder.built_in_memorybarrier(); + } + + fn built_in_memorybarrieratomiccounter(&mut self) { + self.builder.built_in_memorybarrieratomiccounter(); + } + + fn built_in_memorybarrierbuffer(&mut self) { + self.builder.built_in_memorybarrierbuffer(); + } + + fn built_in_memorybarrierimage(&mut self) { + self.builder.built_in_memorybarrierimage(); + } + + fn built_in_barrier(&mut self) { + self.builder.built_in_barrier(); + } + + fn built_in_memorybarriershared(&mut self) { + self.builder.built_in_memorybarriershared(); + } + + fn built_in_groupmemorybarrier(&mut self) { + self.builder.built_in_groupmemorybarrier(); + } + + fn built_in_emitvertex(&mut self) { + self.builder.built_in_emitvertex(); + } + + fn built_in_endprimitive(&mut self) { + self.builder.built_in_endprimitive(); + } + + // Built-in texture* operations + fn built_in_texture(&mut self, with_compare: bool) { + self.builder.built_in_texture(with_compare); + } + + fn built_in_textureproj(&mut self) { + self.builder.built_in_textureproj(); + } + + fn built_in_texturelod(&mut self, with_compare: bool) { + self.builder.built_in_texturelod(with_compare); + } + + fn built_in_textureprojlod(&mut self) { + self.builder.built_in_textureprojlod(); + } + + fn built_in_texturebias(&mut self, with_compare: bool) { + self.builder.built_in_texturebias(with_compare); + } + + fn built_in_textureprojbias(&mut self) { + self.builder.built_in_textureprojbias(); + } + + fn built_in_textureoffset(&mut self) { + self.builder.built_in_textureoffset(); + } + + fn built_in_textureprojoffset(&mut self) { + self.builder.built_in_textureprojoffset(); + } + + fn built_in_texturelodoffset(&mut self) { + self.builder.built_in_texturelodoffset(); + } + + fn built_in_textureprojlodoffset(&mut self) { + self.builder.built_in_textureprojlodoffset(); + } + + fn built_in_textureoffsetbias(&mut self) { + self.builder.built_in_textureoffsetbias(); + } + + fn built_in_textureprojoffsetbias(&mut self) { + self.builder.built_in_textureprojoffsetbias(); + } + + fn built_in_texturegrad(&mut self) { + self.builder.built_in_texturegrad(); + } + + fn built_in_textureprojgrad(&mut self) { + self.builder.built_in_textureprojgrad(); + } + + fn built_in_texturegradoffset(&mut self) { + self.builder.built_in_texturegradoffset(); + } + + fn built_in_textureprojgradoffset(&mut self) { + self.builder.built_in_textureprojgradoffset(); + } + + fn built_in_texturegather(&mut self) { + self.builder.built_in_texturegather(); + } + + fn built_in_texturegathercomp(&mut self) { + self.builder.built_in_texturegathercomp(); + } + + fn built_in_texturegatherref(&mut self) { + self.builder.built_in_texturegatherref(); + } + + fn built_in_texturegatheroffset(&mut self) { + self.builder.built_in_texturegatheroffset(); + } + + fn built_in_texturegatheroffsetcomp(&mut self) { + self.builder.built_in_texturegatheroffsetcomp(); + } + + fn built_in_texturegatheroffsetref(&mut self) { + self.builder.built_in_texturegatheroffsetref(); + } +} diff --git a/src/compiler/translator/ir/src/compile.cpp b/src/compiler/translator/ir/src/compile.cpp new file mode 100644 index 00000000000..033930d1dd3 --- /dev/null +++ b/src/compiler/translator/ir/src/compile.cpp @@ -0,0 +1,148 @@ +// +// Copyright 2025 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. +// + +#include "compiler/translator/ir/src/compile.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/PoolAlloc.h" + +namespace sh +{ +namespace ir +{ +namespace +{ +void SetEnabledExtensions(const TExtensionBehavior &behavior, ffi::ExtensionsEnabled *extensions) +{ + extensions->ANDROID_extension_pack_es31a = + IsExtensionEnabled(behavior, TExtension::ANDROID_extension_pack_es31a); + extensions->ANGLE_base_vertex_base_instance_shader_builtin = + IsExtensionEnabled(behavior, TExtension::ANGLE_base_vertex_base_instance_shader_builtin); + extensions->ANGLE_clip_cull_distance = + IsExtensionEnabled(behavior, TExtension::ANGLE_clip_cull_distance); + extensions->ANGLE_multi_draw = IsExtensionEnabled(behavior, TExtension::ANGLE_multi_draw); + extensions->ANGLE_shader_pixel_local_storage = + IsExtensionEnabled(behavior, TExtension::ANGLE_shader_pixel_local_storage); + extensions->ANGLE_texture_multisample = + IsExtensionEnabled(behavior, TExtension::ANGLE_texture_multisample); + extensions->APPLE_clip_distance = IsExtensionEnabled(behavior, TExtension::APPLE_clip_distance); + extensions->ARB_fragment_shader_interlock = + IsExtensionEnabled(behavior, TExtension::ARB_fragment_shader_interlock); + extensions->ARB_texture_rectangle = + IsExtensionEnabled(behavior, TExtension::ARB_texture_rectangle); + extensions->ARM_shader_framebuffer_fetch = + IsExtensionEnabled(behavior, TExtension::ARM_shader_framebuffer_fetch); + extensions->ARM_shader_framebuffer_fetch_depth_stencil = + IsExtensionEnabled(behavior, TExtension::ARM_shader_framebuffer_fetch_depth_stencil); + extensions->EXT_YUV_target = IsExtensionEnabled(behavior, TExtension::EXT_YUV_target); + extensions->EXT_blend_func_extended = + IsExtensionEnabled(behavior, TExtension::EXT_blend_func_extended); + extensions->EXT_clip_cull_distance = + IsExtensionEnabled(behavior, TExtension::EXT_clip_cull_distance); + extensions->EXT_conservative_depth = + IsExtensionEnabled(behavior, TExtension::EXT_conservative_depth); + extensions->EXT_draw_buffers = IsExtensionEnabled(behavior, TExtension::EXT_draw_buffers); + extensions->EXT_frag_depth = IsExtensionEnabled(behavior, TExtension::EXT_frag_depth); + extensions->EXT_fragment_shading_rate = + IsExtensionEnabled(behavior, TExtension::EXT_fragment_shading_rate); + extensions->EXT_fragment_shading_rate_primitive = + IsExtensionEnabled(behavior, TExtension::EXT_fragment_shading_rate_primitive); + extensions->EXT_geometry_shader = IsExtensionEnabled(behavior, TExtension::EXT_geometry_shader); + extensions->EXT_gpu_shader5 = IsExtensionEnabled(behavior, TExtension::EXT_gpu_shader5); + extensions->EXT_primitive_bounding_box = + IsExtensionEnabled(behavior, TExtension::EXT_primitive_bounding_box); + extensions->EXT_separate_shader_objects = + IsExtensionEnabled(behavior, TExtension::EXT_separate_shader_objects); + extensions->EXT_shader_framebuffer_fetch = + IsExtensionEnabled(behavior, TExtension::EXT_shader_framebuffer_fetch); + extensions->EXT_shader_framebuffer_fetch_non_coherent = + IsExtensionEnabled(behavior, TExtension::EXT_shader_framebuffer_fetch_non_coherent); + extensions->EXT_shader_io_blocks = + IsExtensionEnabled(behavior, TExtension::EXT_shader_io_blocks); + extensions->EXT_shader_non_constant_global_initializers = + IsExtensionEnabled(behavior, TExtension::EXT_shader_non_constant_global_initializers); + extensions->EXT_shader_texture_lod = + IsExtensionEnabled(behavior, TExtension::EXT_shader_texture_lod); + extensions->EXT_shadow_samplers = IsExtensionEnabled(behavior, TExtension::EXT_shadow_samplers); + extensions->EXT_tessellation_shader = + IsExtensionEnabled(behavior, TExtension::EXT_tessellation_shader); + extensions->EXT_texture_buffer = IsExtensionEnabled(behavior, TExtension::EXT_texture_buffer); + extensions->EXT_texture_cube_map_array = + IsExtensionEnabled(behavior, TExtension::EXT_texture_cube_map_array); + extensions->EXT_texture_query_lod = + IsExtensionEnabled(behavior, TExtension::EXT_texture_query_lod); + extensions->EXT_texture_shadow_lod = + IsExtensionEnabled(behavior, TExtension::EXT_texture_shadow_lod); + extensions->INTEL_fragment_shader_ordering = + IsExtensionEnabled(behavior, TExtension::INTEL_fragment_shader_ordering); + extensions->KHR_blend_equation_advanced = + IsExtensionEnabled(behavior, TExtension::KHR_blend_equation_advanced); + extensions->NV_EGL_stream_consumer_external = + IsExtensionEnabled(behavior, TExtension::NV_EGL_stream_consumer_external); + extensions->NV_fragment_shader_interlock = + IsExtensionEnabled(behavior, TExtension::NV_fragment_shader_interlock); + extensions->NV_shader_noperspective_interpolation = + IsExtensionEnabled(behavior, TExtension::NV_shader_noperspective_interpolation); + extensions->OES_EGL_image_external = + IsExtensionEnabled(behavior, TExtension::OES_EGL_image_external); + extensions->OES_EGL_image_external_essl3 = + IsExtensionEnabled(behavior, TExtension::OES_EGL_image_external_essl3); + extensions->OES_geometry_shader = IsExtensionEnabled(behavior, TExtension::OES_geometry_shader); + extensions->OES_gpu_shader5 = IsExtensionEnabled(behavior, TExtension::OES_gpu_shader5); + extensions->OES_primitive_bounding_box = + IsExtensionEnabled(behavior, TExtension::OES_primitive_bounding_box); + extensions->OES_sample_variables = + IsExtensionEnabled(behavior, TExtension::OES_sample_variables); + extensions->OES_shader_image_atomic = + IsExtensionEnabled(behavior, TExtension::OES_shader_image_atomic); + extensions->OES_shader_io_blocks = + IsExtensionEnabled(behavior, TExtension::OES_shader_io_blocks); + extensions->OES_shader_multisample_interpolation = + IsExtensionEnabled(behavior, TExtension::OES_shader_multisample_interpolation); + extensions->OES_standard_derivatives = + IsExtensionEnabled(behavior, TExtension::OES_standard_derivatives); + extensions->OES_tessellation_shader = + IsExtensionEnabled(behavior, TExtension::OES_tessellation_shader); + extensions->OES_texture_3D = IsExtensionEnabled(behavior, TExtension::OES_texture_3D); + extensions->OES_texture_buffer = IsExtensionEnabled(behavior, TExtension::OES_texture_buffer); + extensions->OES_texture_cube_map_array = + IsExtensionEnabled(behavior, TExtension::OES_texture_cube_map_array); + extensions->OES_texture_storage_multisample_2d_array = + IsExtensionEnabled(behavior, TExtension::OES_texture_storage_multisample_2d_array); + extensions->OVR_multiview = IsExtensionEnabled(behavior, TExtension::OVR_multiview); + extensions->OVR_multiview2 = IsExtensionEnabled(behavior, TExtension::OVR_multiview2); + extensions->WEBGL_video_texture = IsExtensionEnabled(behavior, TExtension::WEBGL_video_texture); +} + +void SetOptions(TCompiler *compiler, const ShCompileOptions &options, ffi::CompileOptions *opt) +{ + opt->shader_version = compiler->getShaderVersion(); + opt->is_es1 = compiler->getShaderVersion() == 100; + + opt->initialize_uninitialized_variables = options.initializeUninitializedLocals || + options.initOutputVariables || options.initGLPosition; + opt->loops_allowed_when_initializing_variables = !options.dontUseLoopsToInitializeVariables; + opt->initializer_allowed_on_non_constant_global_variables = + !options.forceDeferNonConstGlobalInitializers; +} +} // namespace + +Output GenerateAST(IR ir, TCompiler *compiler, const ShCompileOptions &options) +{ + ffi::CompileOptions opt; + SetOptions(compiler, options, &opt); + SetEnabledExtensions(compiler->getExtensionBehavior(), &opt.extensions); + + ffi::Output output = ffi::generate_ast(std::move(ir), compiler, GetGlobalPoolAllocator(), opt); + + Output out; + out.root = output.ast; + out.TODOvariables = {}; + + return out; +} +} // namespace ir +} // namespace sh diff --git a/src/compiler/translator/ir/src/compile.h b/src/compiler/translator/ir/src/compile.h new file mode 100644 index 00000000000..9387ec0f1a8 --- /dev/null +++ b/src/compiler/translator/ir/src/compile.h @@ -0,0 +1,50 @@ +// +// Copyright 2025 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. +// +// Bridge to IR operations and code generation in Rust. +// + +#ifndef COMPILER_TRANSLATOR_IR_SRC_COMPILE_H_ +#define COMPILER_TRANSLATOR_IR_SRC_COMPILE_H_ + +#include + +#ifdef ANGLE_IR +# include "compiler/translator/ir/src/compile.rs.h" +#endif + +namespace sh +{ +class TType; +class TVariable; +class TIntermNode; +class TIntermTyped; +class TIntermBlock; +class TCompiler; + +namespace ir +{ +struct Output +{ + TIntermBlock *root = nullptr; + std::vector TODOvariables; +}; + +#ifdef ANGLE_IR +using IR = rust::Box; + +Output GenerateAST(IR ir, TCompiler *compiler, const ShCompileOptions &options); +#else +using IR = void *; + +Output GenerateAST(IR ir, TCompiler *compiler, const ShCompileOptions &options) +{ + return {}; +} +#endif +} // namespace ir +} // namespace sh + +#endif // COMPILER_TRANSLATOR_IR_SRC_COMPILE_H_ diff --git a/src/compiler/translator/ir/src/compile.rs b/src/compiler/translator/ir/src/compile.rs new file mode 100644 index 00000000000..f2fc8d707be --- /dev/null +++ b/src/compiler/translator/ir/src/compile.rs @@ -0,0 +1,211 @@ +// Copyright 2025 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. +// +// The compile process, including IR transformations and output generation. + +use crate::ir::*; +use crate::*; + +#[cxx::bridge(namespace = "sh::ir::ffi")] +mod ffi { + // TODO(http://anglebug.com/349994211): equivalent enums to the options in ShaderLang.h, eventually all options need to be + // passed to IR: add them as the translator is converted to IR. + + // TODO(http://anglebug.com/349994211): equivalent to ShBuiltInResources, or at least the parts that the compiler really uses: + // add as needed. + + // List of enabled extensions + struct ExtensionsEnabled { + ANDROID_extension_pack_es31a: bool, + ANGLE_base_vertex_base_instance_shader_builtin: bool, + ANGLE_clip_cull_distance: bool, + ANGLE_multi_draw: bool, + ANGLE_shader_pixel_local_storage: bool, + ANGLE_texture_multisample: bool, + APPLE_clip_distance: bool, + ARB_fragment_shader_interlock: bool, + ARB_texture_rectangle: bool, + ARM_shader_framebuffer_fetch: bool, + ARM_shader_framebuffer_fetch_depth_stencil: bool, + EXT_YUV_target: bool, + EXT_blend_func_extended: bool, + EXT_clip_cull_distance: bool, + EXT_conservative_depth: bool, + EXT_draw_buffers: bool, + EXT_frag_depth: bool, + EXT_fragment_shading_rate: bool, + EXT_fragment_shading_rate_primitive: bool, + EXT_geometry_shader: bool, + EXT_gpu_shader5: bool, + EXT_primitive_bounding_box: bool, + EXT_separate_shader_objects: bool, + EXT_shader_framebuffer_fetch: bool, + EXT_shader_framebuffer_fetch_non_coherent: bool, + EXT_shader_io_blocks: bool, + EXT_shader_non_constant_global_initializers: bool, + EXT_shader_texture_lod: bool, + EXT_shadow_samplers: bool, + EXT_tessellation_shader: bool, + EXT_texture_buffer: bool, + EXT_texture_cube_map_array: bool, + EXT_texture_query_lod: bool, + EXT_texture_shadow_lod: bool, + INTEL_fragment_shader_ordering: bool, + KHR_blend_equation_advanced: bool, + NV_EGL_stream_consumer_external: bool, + NV_fragment_shader_interlock: bool, + NV_shader_noperspective_interpolation: bool, + OES_EGL_image_external: bool, + OES_EGL_image_external_essl3: bool, + OES_geometry_shader: bool, + OES_gpu_shader5: bool, + OES_primitive_bounding_box: bool, + OES_sample_variables: bool, + OES_shader_image_atomic: bool, + OES_shader_io_blocks: bool, + OES_shader_multisample_interpolation: bool, + OES_standard_derivatives: bool, + OES_tessellation_shader: bool, + OES_texture_3D: bool, + OES_texture_buffer: bool, + OES_texture_cube_map_array: bool, + OES_texture_storage_multisample_2d_array: bool, + OVR_multiview: bool, + OVR_multiview2: bool, + WEBGL_video_texture: bool, + } + + struct CompileOptions { + // Input shader and device properties: + + // The version of the input version + shader_version: i32, + // Extensions that were enabled, mostly useful for the GLSL/ESSL output to replicate them. + extensions: ExtensionsEnabled, + // TODO(http://anglebug.com/349994211): equivalent to ShBuiltInResources + + // Flags controlling the output: + + // Whether this is an ES1 shader. This is used while the output is AST. Eventually, an + // enum equivalent to ShShaderOutput should be used to instead indicate what the _output_ + // version is, not the input. + is_es1: bool, + + // Whether uninitialized local and global variables should be zero-initialized. + initialize_uninitialized_variables: bool, + // Whether loops can be used when zero-initializing variables. + loops_allowed_when_initializing_variables: bool, + // Whether non-const variables in global scope can have an initializer + initializer_allowed_on_non_constant_global_variables: bool, + // TODO(http://anglebug.com/349994211): equivalent to ShCompileOptions flags + } + + // TODO(http://anglebug.com/349994211): Equivalent to sh::ShaderVariable, to be done after + // CollectVariables is implemented in the IR. + struct ShaderVariable { + todo: i32, + } + + struct Output { + // Note: For now, generate always results in an AST. Eventually either text or binary + // should be returned. + ast: *mut TIntermBlock, + // TODO(http://anglebug.com/349994211): Reflection data collected by the IR (equivalent to + // what CollectVariables produces). + variables: Vec, + } + + extern "C++" { + include!("compiler/translator/ir/src/output/legacy.h"); + + #[namespace = "sh"] + type TCompiler = crate::output::legacy::ffi::TCompiler; + + #[namespace = "sh"] + type TIntermBlock = crate::output::legacy::ffi::TIntermBlock; + + // Work around an issue similar to http://crbug.com/418073233 where the translator is + // statically linked to both libGLESv2.so and angle_end2end_tests, and crossing the + // C++->Rust boundary somehow jumps between the two copies, messing up global variables. + #[namespace = "angle"] + type PoolAllocator; + + include!("compiler/translator/ir/src/builder.rs.h"); + type IR = crate::ir::IR; + + include!("compiler/translator/ir/src/pool_alloc.h"); + unsafe fn initialize_global_pool_index(); + unsafe fn free_global_pool_index(); + unsafe fn set_global_pool_allocator(allocator: *mut PoolAllocator); + } + extern "Rust" { + unsafe fn generate_ast( + mut ir: Box, + compiler: *mut TCompiler, + allocator: *mut PoolAllocator, + options: &CompileOptions, + ) -> Output; + + fn initialize_global_pool_index_workaround(); + fn free_global_pool_index_workaround(); + } +} + +pub use ffi::CompileOptions as Options; + +unsafe fn generate_ast( + mut ir: Box, + compiler: *mut ffi::TCompiler, + allocator: *mut ffi::PoolAllocator, + options: &Options, +) -> ffi::Output { + unsafe { ffi::set_global_pool_allocator(allocator) }; + + // Apply transforms shared by multiple generators: + common_transforms(&mut ir, options); + + // Passes required before AST can be generated: + transform::dealias::run(&mut ir); + transform::astify::run(&mut ir); + + let mut ast_gen = output::legacy::Generator::new(compiler, options); + let mut generator = ast::Generator::new(*ir); + let ast = generator.generate(&mut ast_gen); + + ffi::Output { ast, variables: vec![] } +} + +fn common_transforms(ir: &mut IR, options: &Options) { + // Turn |inout| variables that are never read from into |out| before collecting variables and + // before PLS uses them. + if ir.meta.get_shader_type() == ShaderType::Fragment + && options.shader_version >= 300 + && (options.extensions.EXT_shader_framebuffer_fetch + || options.extensions.EXT_shader_framebuffer_fetch_non_coherent) + { + transform::remove_unused_framebuffer_fetch::run(ir); + } + + // Basic dead-code-elimination to avoid outputting variables, constants and types that are not + // used by the shader. + transform::prune_unused_variables::run(ir); + + // Run after unused variables are removed, initialize local and output variables if necessary. + if options.initialize_uninitialized_variables { + let transform_options = transform::initialize_uninitialized_variables::Options { + loops_allowed_when_initializing_variables: options + .loops_allowed_when_initializing_variables, + initializer_allowed_on_non_constant_global_variables: options + .initializer_allowed_on_non_constant_global_variables, + }; + transform::initialize_uninitialized_variables::run(ir, &transform_options); + } +} + +fn initialize_global_pool_index_workaround() { + unsafe { ffi::initialize_global_pool_index() }; +} +fn free_global_pool_index_workaround() { + unsafe { ffi::free_global_pool_index() }; +} diff --git a/src/compiler/translator/ir/src/debug.rs b/src/compiler/translator/ir/src/debug.rs new file mode 100644 index 00000000000..4b1285569e2 --- /dev/null +++ b/src/compiler/translator/ir/src/debug.rs @@ -0,0 +1,1138 @@ +// 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. +// +// Debug utilities. Notable, the IR can be dumped for inspection. + +use crate::ir::*; +use crate::*; + +fn register_id_str(id: RegisterId) -> String { + format!("r{}", id.id) +} + +fn constant_id_str(id: ConstantId) -> String { + format!("c{}", id.id) +} + +fn variable_id_str(id: VariableId) -> String { + format!("v{}", id.id) +} + +fn function_id_str(id: FunctionId) -> String { + format!("f{}", id.id) +} + +fn type_id_str(id: TypeId) -> String { + format!("t{}", id.id) +} + +fn precision_str(precision: Precision) -> &'static str { + match precision { + Precision::NotApplicable => "", + Precision::Low => "lowp", + Precision::Medium => "mediump", + Precision::High => "highp", + } +} + +fn id_str(id: TypedId) -> String { + match id.id { + Id::Register(rid) => register_id_str(rid), + Id::Constant(cid) => { + // Constants normally do not have an associated precision, but if a constant replaces a + // `const` variable, its use as an operand of an instruction would be associated with a + // precision. In that case, output the precision too. + let constant_str = constant_id_str(cid); + match id.precision { + Precision::NotApplicable => constant_str, + _ => format!("{constant_str}[{}]", precision_str(id.precision)), + } + } + Id::Variable(vid) => variable_id_str(vid), + } +} + +fn id_list_str(ids: &[TypedId]) -> String { + ids.iter().map(|&id| id_str(id)).collect::>().join(", ") +} + +fn index_list_str(ids: &[u32]) -> String { + ids.iter().map(|index| index.to_string()).collect::>().join(", ") +} + +fn shader_type_str(shader_type: ShaderType) -> String { + (match shader_type { + ShaderType::Vertex => "Vertex Shader", + ShaderType::TessellationControl => "Tessellation Control Shader", + ShaderType::TessellationEvaluation => "Tessellation Evaluation Shader", + ShaderType::Geometry => "Geometry Shader", + ShaderType::Fragment => "Fragment Shader", + ShaderType::Compute => "Compute Shader", + }) + .to_string() +} + +fn early_fragment_tests_str(early_fragment_tests: bool) -> String { + (if early_fragment_tests { "[Early fragment tests]" } else { "" }).to_string() +} + +fn blend_equation_advanced_str(equations: &AdvancedBlendEquations) -> String { + if equations.all() { + return "[Advanced Blend Equations: All]".to_string(); + } + + let mut equations_list = Vec::new(); + if equations.multiply { + equations_list.push("Multiply"); + } + if equations.screen { + equations_list.push("Screen"); + } + if equations.overlay { + equations_list.push("Overlay"); + } + if equations.darken { + equations_list.push("Darken"); + } + if equations.lighten { + equations_list.push("Lighten"); + } + if equations.colordodge { + equations_list.push("Color Dodge"); + } + if equations.colorburn { + equations_list.push("Color Burn"); + } + if equations.hardlight { + equations_list.push("Hard Light"); + } + if equations.softlight { + equations_list.push("Soft Light"); + } + if equations.difference { + equations_list.push("Difference"); + } + if equations.exclusion { + equations_list.push("Exclusion"); + } + if equations.hsl_hue { + equations_list.push("HSL Hue"); + } + if equations.hsl_saturation { + equations_list.push("HSL Saturation"); + } + if equations.hsl_color { + equations_list.push("HSL Color"); + } + if equations.hsl_luminosity { + equations_list.push("HSL Luminosity"); + } + + if equations_list.is_empty() { + return String::new(); + } + + let indent = " ".to_string(); + let delim = format!(",\n{indent}"); + format!("[Advanced Blend Equations:\n{indent}{}]", equations_list.join(&delim)) +} + +fn tcs_vertices_str(vertices: u32) -> String { + format!("[Vertices: {vertices}]") +} + +fn tes_primitive_str(primitive: TessellationPrimitive) -> String { + format!( + "[Primitive: {}]", + match primitive { + TessellationPrimitive::Undefined => "Undefined", + TessellationPrimitive::Triangles => "Triangles", + TessellationPrimitive::Quads => "Quads", + TessellationPrimitive::Isolines => "Isolines", + } + ) +} + +fn tes_vertex_spacing_str(vertex_spacing: TessellationSpacing) -> String { + format!( + "[Vertex Spacing: {}]", + match vertex_spacing { + TessellationSpacing::Undefined => "Undefined", + TessellationSpacing::EqualSpacing => "Equal", + TessellationSpacing::FractionalEvenSpacing => "Fractional Even", + TessellationSpacing::FractionalOddSpacing => "Fractional Odd", + } + ) +} + +fn tes_ordering_str(ordering: TessellationOrdering) -> String { + format!( + "[Ordering: {}]", + match ordering { + TessellationOrdering::Undefined => "Undefined", + TessellationOrdering::Cw => "CW", + TessellationOrdering::Ccw => "CCW", + } + ) +} + +fn tes_point_mode_str(point_mode: bool) -> String { + (if point_mode { "[Point Mode]" } else { "" }).to_string() +} + +fn gs_primitive_str(primitive: GeometryPrimitive, direction: &str) -> String { + format!( + "[Primitive {}: {}]", + direction, + match primitive { + GeometryPrimitive::Undefined => "Undefined", + GeometryPrimitive::Points => "Points", + GeometryPrimitive::Lines => "Lines", + GeometryPrimitive::LinesAdjacency => "Lines Adjacency", + GeometryPrimitive::Triangles => "Triangles", + GeometryPrimitive::TrianglesAdjacency => "Triangles Adjacency", + GeometryPrimitive::LineStrip => "Line Strip", + GeometryPrimitive::TriangleStrip => "Triangle Strip", + } + ) +} + +fn gs_invocations_str(invocations: u32) -> String { + format!("[Invocations: {invocations}]") +} + +fn gs_max_vertices_str(max_vertices: u32) -> String { + format!("[Max Vertices: {max_vertices}]") +} + +fn basic_type_str(basic: BasicType) -> String { + (match basic { + BasicType::Void => "void", + BasicType::Float => "float", + BasicType::Int => "int", + BasicType::Uint => "uint", + BasicType::Bool => "bool", + BasicType::AtomicCounter => "atomic_uint", + BasicType::YuvCscStandard => "yuvCscStandardEXT", + }) + .to_string() +} + +fn image_type_str(basic_type: ImageBasicType, image_type: ImageType) -> String { + let prefix = match basic_type { + ImageBasicType::Float => "", + ImageBasicType::Int => "i", + ImageBasicType::Uint => "u", + }; + let mut base_name = if image_type.is_sampled { "sampler" } else { "image" }; + let suffix = match image_type.dimension { + ImageDimension::D2 => "2D", + ImageDimension::D3 => "3D", + ImageDimension::Cube => "Cube", + ImageDimension::Rect => "Rect", + ImageDimension::Buffer => "Buffer", + ImageDimension::External => "ExternalOES", + ImageDimension::ExternalY2Y => "External2DY2YEXT", + ImageDimension::Video => "VideoWEBGL", + ImageDimension::PixelLocal => { + base_name = "pixelLocalANGLE"; + "" + } + ImageDimension::Subpass => { + base_name = "subpassInput"; + "" + } + }; + let multisample_suffix = if image_type.is_ms { "MS" } else { "" }; + let array_suffix = if image_type.is_array { "Array" } else { "" }; + let shadow_suffix = if image_type.is_shadow { "Shadow" } else { "" }; + format!("{prefix}{base_name}{suffix}{multisample_suffix}{array_suffix}{shadow_suffix}") +} + +fn name_str(name: &Name, temp_prefix: &'static str, id: u32) -> String { + // Some names are expected to be output exactly, and are known to be unique. Others will + // be disambiguated with an `_N` suffix if they clash with any other name in text outputs. + format!( + "'{}{}{}'", + match name.source { + NameSource::ShaderInterface => USER_SYMBOL_PREFIX, + NameSource::Temporary => temp_prefix, + _ => "", + }, + name.name, + if name.source == NameSource::Temporary { format!("_{id}") } else { "".to_string() } + ) +} + +fn block_storage_str(storage: BlockStorage) -> String { + (match storage { + BlockStorage::Shared => "shared", + BlockStorage::Packed => "packed", + BlockStorage::Std140 => "std140", + BlockStorage::Std430 => "std430", + }) + .to_string() +} + +fn matrix_packing_str(packing: MatrixPacking) -> String { + (match packing { + MatrixPacking::ColumnMajor => "column_major", + MatrixPacking::RowMajor => "row_major", + }) + .to_string() +} + +fn depth_str(depth: Depth) -> String { + (match depth { + Depth::Any => "depth_any", + Depth::Greater => "depth_greater", + Depth::Less => "depth_less", + Depth::Unchanged => "depth_unchanged", + }) + .to_string() +} + +fn image_internal_format_str(format: ImageInternalFormat) -> String { + (match format { + ImageInternalFormat::RGBA32F => "rgba32f", + ImageInternalFormat::RGBA16F => "rgba16f", + ImageInternalFormat::R32F => "r32f", + ImageInternalFormat::RGBA32UI => "rgba32ui", + ImageInternalFormat::RGBA16UI => "rgba16ui", + ImageInternalFormat::RGBA8UI => "rgba8ui", + ImageInternalFormat::R32UI => "r32ui", + ImageInternalFormat::RGBA32I => "rgba32i", + ImageInternalFormat::RGBA16I => "rgba16i", + ImageInternalFormat::RGBA8I => "rgba8i", + ImageInternalFormat::R32I => "r32i", + ImageInternalFormat::RGBA8 => "rgba8", + ImageInternalFormat::RGBA8SNORM => "rgba8snorm", + }) + .to_string() +} + +fn decoration_str(decoration: Decoration) -> String { + match decoration { + Decoration::Invariant => "invariant".to_string(), + Decoration::Precise => "precise".to_string(), + Decoration::Interpolant => "interpolant".to_string(), + Decoration::Smooth => "smooth".to_string(), + Decoration::Flat => "flat".to_string(), + Decoration::NoPerspective => "noperspective".to_string(), + Decoration::Centroid => "centroid".to_string(), + Decoration::Sample => "sample".to_string(), + Decoration::Patch => "patch".to_string(), + Decoration::Shared => "shared(memory)".to_string(), + Decoration::ReadOnly => "readonly".to_string(), + Decoration::WriteOnly => "writeonly".to_string(), + Decoration::Coherent => "coherent".to_string(), + Decoration::Restrict => "restrict".to_string(), + Decoration::Volatile => "volatile".to_string(), + Decoration::Uniform => "uniform".to_string(), + Decoration::Buffer => "buffer".to_string(), + Decoration::PushConstant => "push_constant".to_string(), + Decoration::NonCoherent => "noncoherent".to_string(), + Decoration::Yuv => "yuv".to_string(), + Decoration::Input => "input".to_string(), + Decoration::Output => "output".to_string(), + Decoration::InputOutput => "input/output".to_string(), + Decoration::Location(n) => format!("location={n}"), + Decoration::Index(n) => format!("index={n}"), + Decoration::InputAttachmentIndex(n) => format!("input_attachment_index={n}"), + Decoration::SpecConst(n) => format!("constant_id={n}"), + Decoration::Block(storage) => block_storage_str(storage), + Decoration::Binding(n) => format!("binding={n}"), + Decoration::Offset(n) => format!("offset={n}"), + Decoration::MatrixPacking(packing) => matrix_packing_str(packing), + Decoration::Depth(depth) => depth_str(depth), + Decoration::ImageInternalFormat(format) => image_internal_format_str(format), + Decoration::NumViews(n) => format!("num_views={n}"), + Decoration::RasterOrdered => "raster_ordered(D3D)".to_string(), + } +} + +fn decoration_list(precision: Precision, decorations: &Decorations) -> String { + let mut result = Vec::new(); + match precision { + Precision::NotApplicable => {} + _ => result.push(precision_str(precision).to_string()), + }; + + decorations.decorations.iter().for_each(|&decoration| { + result.push(decoration_str(decoration)); + }); + + result.join(", ") +} + +fn append_decorations(result: &mut String, precision: Precision, decorations: &Decorations) { + let decorations = decoration_list(precision, decorations); + if !decorations.is_empty() { + *result = format!("{result} [{decorations}]"); + } +} + +fn field_str(field: &Field, index: usize) -> String { + let mut result = format!( + "{}: {}", + name_str(&field.name, TEMP_STRUCT_FIELD_PREFIX, index as u32), + type_id_str(field.type_id) + ); + append_decorations(&mut result, field.precision, &field.decorations); + result +} + +fn yuv_csc_standard_str(yuv_csc: YuvCscStandard) -> String { + (match yuv_csc { + YuvCscStandard::Itu601 => "itu_601", + YuvCscStandard::Itu601FullRange => "itu_601_full_range", + YuvCscStandard::Itu709 => "itu_709", + }) + .to_string() +} + +fn built_in_str(built_in: BuiltIn) -> String { + (match built_in { + BuiltIn::InstanceID => "InstanceID", + BuiltIn::VertexID => "VertexID", + BuiltIn::Position => "Position", + BuiltIn::PointSize => "PointSize", + BuiltIn::BaseVertex => "BaseVertex", + BuiltIn::BaseInstance => "BaseInstance", + BuiltIn::DrawID => "DrawID", + BuiltIn::FragCoord => "FragCoord", + BuiltIn::FrontFacing => "FrontFacing", + BuiltIn::PointCoord => "PointCoord", + BuiltIn::HelperInvocation => "HelperInvocation", + BuiltIn::FragColor => "FragColor", + BuiltIn::FragData => "FragData", + BuiltIn::FragDepth => "FragDepth", + BuiltIn::SecondaryFragColorEXT => "SecondaryFragColorEXT", + BuiltIn::SecondaryFragDataEXT => "SecondaryFragDataEXT", + BuiltIn::DepthRange => "DepthRange", + BuiltIn::ViewIDOVR => "ViewIDOVR", + BuiltIn::ClipDistance => "ClipDistance", + BuiltIn::CullDistance => "CullDistance", + BuiltIn::LastFragColor => "LastFragColor", + BuiltIn::LastFragData => "LastFragData", + BuiltIn::LastFragDepthARM => "LastFragDepthARM", + BuiltIn::LastFragStencilARM => "LastFragStencilARM", + BuiltIn::ShadingRateEXT => "ShadingRateEXT", + BuiltIn::PrimitiveShadingRateEXT => "PrimitiveShadingRateEXT", + BuiltIn::SampleID => "SampleID", + BuiltIn::SamplePosition => "SamplePosition", + BuiltIn::SampleMaskIn => "SampleMaskIn", + BuiltIn::SampleMask => "SampleMask", + BuiltIn::NumSamples => "NumSamples", + BuiltIn::NumWorkGroups => "NumWorkGroups", + BuiltIn::WorkGroupSize => "WorkGroupSize", + BuiltIn::WorkGroupID => "WorkGroupID", + BuiltIn::LocalInvocationID => "LocalInvocationID", + BuiltIn::GlobalInvocationID => "GlobalInvocationID", + BuiltIn::LocalInvocationIndex => "LocalInvocationIndex", + BuiltIn::PerVertexIn => "PerVertexIn", + BuiltIn::PerVertexOut => "PerVertexOut", + BuiltIn::PrimitiveIDIn => "PrimitiveIDIn", + BuiltIn::InvocationID => "InvocationID", + BuiltIn::PrimitiveID => "PrimitiveID", + BuiltIn::LayerOut => "Layer(GS)", + BuiltIn::LayerIn => "Layer(FS)", + BuiltIn::PatchVerticesIn => "PatchVerticesIn", + BuiltIn::TessLevelOuter => "TessLevelOuter", + BuiltIn::TessLevelInner => "TessLevelInner", + BuiltIn::TessCoord => "TessCoord", + BuiltIn::BoundingBoxOES => "BoundingBoxOES", + BuiltIn::PixelLocalEXT => "PixelLocalEXT", + }) + .to_string() +} + +fn function_param_direction_str(direction: FunctionParamDirection) -> String { + (match direction { + FunctionParamDirection::Input => "in", + FunctionParamDirection::Output => "out", + FunctionParamDirection::InputOutput => "inout", + }) + .to_string() +} + +fn function_prototype_str(id: FunctionId, function: &Function) -> String { + let name = name_str(&function.name, TEMP_FUNCTION_PREFIX, id.id); + + let mut return_type = type_id_str(function.return_type_id); + append_decorations(&mut return_type, function.return_precision, &function.return_decorations); + + let params = function + .params + .iter() + .map(|param| { + format!( + "{} {}", + function_param_direction_str(param.direction), + variable_id_str(param.variable_id) + ) + }) + .collect::>() + .join(", "); + + format!("{}: {name}({params}) -> {return_type}", function_id_str(id)) +} + +fn block_kind_str(kind: traverser::BlockKind) -> String { + match kind { + traverser::BlockKind::Entry => "Entry To Function:".to_string(), + traverser::BlockKind::True => "If True Block:".to_string(), + traverser::BlockKind::False => "If False Block:".to_string(), + traverser::BlockKind::LoopCondition => "Loop Condition:".to_string(), + traverser::BlockKind::LoopBody => "Loop Body:".to_string(), + traverser::BlockKind::Continue => "Loop Continue Block:".to_string(), + traverser::BlockKind::Case(case) => case + .map(|constant_id| format!("Case {}:", constant_id_str(constant_id))) + .unwrap_or("Default Case:".to_string()), + traverser::BlockKind::Merge => "Merge Block:".to_string(), + } +} + +fn unary_opcode_str(op: UnaryOpCode) -> &'static str { + match op { + UnaryOpCode::ArrayLength => "ArrayLength", + UnaryOpCode::Negate => "Negate", + UnaryOpCode::PostfixIncrement => "PostfixIncrement", + UnaryOpCode::PostfixDecrement => "PostfixDecrement", + UnaryOpCode::PrefixIncrement => "PrefixIncrement", + UnaryOpCode::PrefixDecrement => "PrefixDecrement", + UnaryOpCode::LogicalNot => "LogicalNot", + UnaryOpCode::BitwiseNot => "BitwiseNot", + UnaryOpCode::Radians => "Radians", + UnaryOpCode::Degrees => "Degrees", + UnaryOpCode::Sin => "Sin", + UnaryOpCode::Cos => "Cos", + UnaryOpCode::Tan => "Tan", + UnaryOpCode::Asin => "Asin", + UnaryOpCode::Acos => "Acos", + UnaryOpCode::Atan => "Atan", + UnaryOpCode::Sinh => "Sinh", + UnaryOpCode::Cosh => "Cosh", + UnaryOpCode::Tanh => "Tanh", + UnaryOpCode::Asinh => "Asinh", + UnaryOpCode::Acosh => "Acosh", + UnaryOpCode::Atanh => "Atanh", + UnaryOpCode::Exp => "Exp", + UnaryOpCode::Log => "Log", + UnaryOpCode::Exp2 => "Exp2", + UnaryOpCode::Log2 => "Log2", + UnaryOpCode::Sqrt => "Sqrt", + UnaryOpCode::Inversesqrt => "Inversesqrt", + UnaryOpCode::Abs => "Abs", + UnaryOpCode::Sign => "Sign", + UnaryOpCode::Floor => "Floor", + UnaryOpCode::Trunc => "Trunc", + UnaryOpCode::Round => "Round", + UnaryOpCode::RoundEven => "RoundEven", + UnaryOpCode::Ceil => "Ceil", + UnaryOpCode::Fract => "Fract", + UnaryOpCode::Isnan => "Isnan", + UnaryOpCode::Isinf => "Isinf", + UnaryOpCode::FloatBitsToInt => "FloatBitsToInt", + UnaryOpCode::FloatBitsToUint => "FloatBitsToUint", + UnaryOpCode::IntBitsToFloat => "IntBitsToFloat", + UnaryOpCode::UintBitsToFloat => "UintBitsToFloat", + UnaryOpCode::PackSnorm2x16 => "PackSnorm2x16", + UnaryOpCode::PackHalf2x16 => "PackHalf2x16", + UnaryOpCode::UnpackSnorm2x16 => "UnpackSnorm2x16", + UnaryOpCode::UnpackHalf2x16 => "UnpackHalf2x16", + UnaryOpCode::PackUnorm2x16 => "PackUnorm2x16", + UnaryOpCode::UnpackUnorm2x16 => "UnpackUnorm2x16", + UnaryOpCode::PackUnorm4x8 => "PackUnorm4x8", + UnaryOpCode::PackSnorm4x8 => "PackSnorm4x8", + UnaryOpCode::UnpackUnorm4x8 => "UnpackUnorm4x8", + UnaryOpCode::UnpackSnorm4x8 => "UnpackSnorm4x8", + UnaryOpCode::Length => "Length", + UnaryOpCode::Normalize => "Normalize", + UnaryOpCode::Transpose => "Transpose", + UnaryOpCode::Determinant => "Determinant", + UnaryOpCode::Inverse => "Inverse", + UnaryOpCode::Any => "Any", + UnaryOpCode::All => "All", + UnaryOpCode::Not => "Not", + UnaryOpCode::BitfieldReverse => "BitfieldReverse", + UnaryOpCode::BitCount => "BitCount", + UnaryOpCode::FindLSB => "FindLSB", + UnaryOpCode::FindMSB => "FindMSB", + UnaryOpCode::DFdx => "DFdx", + UnaryOpCode::DFdy => "DFdy", + UnaryOpCode::Fwidth => "Fwidth", + UnaryOpCode::InterpolateAtCentroid => "InterpolateAtCentroid", + UnaryOpCode::AtomicCounter => "AtomicCounter", + UnaryOpCode::AtomicCounterIncrement => "AtomicCounterIncrement", + UnaryOpCode::AtomicCounterDecrement => "AtomicCounterDecrement", + UnaryOpCode::ImageSize => "ImageSize", + UnaryOpCode::PixelLocalLoadANGLE => "PixelLocalLoadANGLE", + } +} + +fn binary_opcode_str(op: BinaryOpCode) -> &'static str { + match op { + BinaryOpCode::Add => "Add", + BinaryOpCode::Sub => "Sub", + BinaryOpCode::Mul => "Mul", + BinaryOpCode::VectorTimesScalar => "VectorTimesScalar", + BinaryOpCode::MatrixTimesScalar => "MatrixTimesScalar", + BinaryOpCode::VectorTimesMatrix => "VectorTimesMatrix", + BinaryOpCode::MatrixTimesVector => "MatrixTimesVector", + BinaryOpCode::MatrixTimesMatrix => "MatrixTimesMatrix", + BinaryOpCode::Div => "Div", + BinaryOpCode::IMod => "IMod", + BinaryOpCode::LogicalXor => "LogicalXor", + BinaryOpCode::Equal => "Equal", + BinaryOpCode::NotEqual => "NotEqual", + BinaryOpCode::LessThan => "LessThan", + BinaryOpCode::GreaterThan => "GreaterThan", + BinaryOpCode::LessThanEqual => "LessThanEqual", + BinaryOpCode::GreaterThanEqual => "GreaterThanEqual", + BinaryOpCode::BitShiftLeft => "BitShiftLeft", + BinaryOpCode::BitShiftRight => "BitShiftRight", + BinaryOpCode::BitwiseOr => "BitwiseOr", + BinaryOpCode::BitwiseXor => "BitwiseXor", + BinaryOpCode::BitwiseAnd => "BitwiseAnd", + BinaryOpCode::Atan => "Atan[binary]", + BinaryOpCode::Pow => "Pow", + BinaryOpCode::Mod => "Mod", + BinaryOpCode::Min => "Min", + BinaryOpCode::Max => "Max", + BinaryOpCode::Step => "Step", + BinaryOpCode::Modf => "Modf", + BinaryOpCode::Frexp => "Frexp", + BinaryOpCode::Ldexp => "Ldexp", + BinaryOpCode::Distance => "Distance", + BinaryOpCode::Dot => "Dot", + BinaryOpCode::Cross => "Cross", + BinaryOpCode::Reflect => "Reflect", + BinaryOpCode::MatrixCompMult => "MatrixCompMult", + BinaryOpCode::OuterProduct => "OuterProduct", + BinaryOpCode::LessThanVec => "LessThan[built-in]", + BinaryOpCode::LessThanEqualVec => "LessThanEqual[built-in]", + BinaryOpCode::GreaterThanVec => "GreaterThan[built-in]", + BinaryOpCode::GreaterThanEqualVec => "GreaterThanEqual[built-in]", + BinaryOpCode::EqualVec => "Equal[built-in]", + BinaryOpCode::NotEqualVec => "NotEqual[built-in]", + BinaryOpCode::InterpolateAtSample => "InterpolateAtSample", + BinaryOpCode::InterpolateAtOffset => "InterpolateAtOffset", + BinaryOpCode::AtomicAdd => "AtomicAdd", + BinaryOpCode::AtomicMin => "AtomicMin", + BinaryOpCode::AtomicMax => "AtomicMax", + BinaryOpCode::AtomicAnd => "AtomicAnd", + BinaryOpCode::AtomicOr => "AtomicOr", + BinaryOpCode::AtomicXor => "AtomicXor", + BinaryOpCode::AtomicExchange => "AtomicExchange", + } +} + +fn built_in_opcode_str(op: BuiltInOpCode) -> &'static str { + match op { + BuiltInOpCode::Clamp => "Clamp", + BuiltInOpCode::Mix => "Mix", + BuiltInOpCode::Smoothstep => "Smoothstep", + BuiltInOpCode::Fma => "Fma", + BuiltInOpCode::Faceforward => "Faceforward", + BuiltInOpCode::Refract => "Refract", + BuiltInOpCode::BitfieldExtract => "BitfieldExtract", + BuiltInOpCode::BitfieldInsert => "BitfieldInsert", + BuiltInOpCode::UaddCarry => "UaddCarry", + BuiltInOpCode::UsubBorrow => "UsubBorrow", + BuiltInOpCode::UmulExtended => "UmulExtended", + BuiltInOpCode::ImulExtended => "ImulExtended", + BuiltInOpCode::TextureSize => "TextureSize", + BuiltInOpCode::TextureQueryLod => "TextureQueryLod", + BuiltInOpCode::TexelFetch => "TexelFetch", + BuiltInOpCode::TexelFetchOffset => "TexelFetchOffset", + BuiltInOpCode::Rgb2Yuv => "Rgb2Yuv", + BuiltInOpCode::Yuv2Rgb => "Yuv2Rgb", + BuiltInOpCode::AtomicCompSwap => "AtomicCompSwap", + BuiltInOpCode::ImageStore => "ImageStore", + BuiltInOpCode::ImageLoad => "ImageLoad", + BuiltInOpCode::ImageAtomicAdd => "ImageAtomicAdd", + BuiltInOpCode::ImageAtomicMin => "ImageAtomicMin", + BuiltInOpCode::ImageAtomicMax => "ImageAtomicMax", + BuiltInOpCode::ImageAtomicAnd => "ImageAtomicAnd", + BuiltInOpCode::ImageAtomicOr => "ImageAtomicOr", + BuiltInOpCode::ImageAtomicXor => "ImageAtomicXor", + BuiltInOpCode::ImageAtomicExchange => "ImageAtomicExchange", + BuiltInOpCode::ImageAtomicCompSwap => "ImageAtomicCompSwap", + BuiltInOpCode::PixelLocalStoreANGLE => "PixelLocalStoreANGLE", + BuiltInOpCode::MemoryBarrier => "MemoryBarrier", + BuiltInOpCode::MemoryBarrierAtomicCounter => "MemoryBarrierAtomicCounter", + BuiltInOpCode::MemoryBarrierBuffer => "MemoryBarrierBuffer", + BuiltInOpCode::MemoryBarrierImage => "MemoryBarrierImage", + BuiltInOpCode::Barrier => "Barrier", + BuiltInOpCode::MemoryBarrierShared => "MemoryBarrierShared", + BuiltInOpCode::GroupMemoryBarrier => "GroupMemoryBarrier", + BuiltInOpCode::EmitVertex => "EmitVertex", + BuiltInOpCode::EndPrimitive => "EndPrimitive", + BuiltInOpCode::SubpassLoad => "SubpassLoad", + BuiltInOpCode::BeginInvocationInterlockNV => "BeginInvocationInterlockNV", + BuiltInOpCode::EndInvocationInterlockNV => "EndInvocationInterlockNV", + BuiltInOpCode::BeginFragmentShaderOrderingINTEL => "BeginFragmentShaderOrderingINTEL", + BuiltInOpCode::BeginInvocationInterlockARB => "BeginInvocationInterlockARB", + BuiltInOpCode::EndInvocationInterlockARB => "EndInvocationInterlockARB", + BuiltInOpCode::NumSamples => "NumSamples", + BuiltInOpCode::SamplePosition => "SamplePosition", + BuiltInOpCode::InterpolateAtCenter => "InterpolateAtCenter", + BuiltInOpCode::Saturate => "Saturate", + BuiltInOpCode::LoopForwardProgress => "LoopForwardProgress", + } +} + +fn texture_opcode_str(op: &TextureOpCode) -> (&'static str, String) { + match *op { + TextureOpCode::Implicit { is_proj, offset } => ( + "", + format!( + "is_proj:{}{}", + is_proj, + offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string()) + ), + ), + TextureOpCode::Compare { compare } => ("Compare", format!("compare:{}", id_str(compare))), + TextureOpCode::Lod { is_proj, lod, offset } => ( + "Lod", + format!( + "is_proj:{} lod:{}{}", + is_proj, + id_str(lod), + offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string()) + ), + ), + TextureOpCode::CompareLod { compare, lod } => { + ("CompareLod", format!("compare:{} lod:{}", id_str(compare), id_str(lod))) + } + TextureOpCode::Bias { is_proj, bias, offset } => ( + "Bias", + format!( + "is_proj:{} bias:{}{}", + is_proj, + id_str(bias), + offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string()) + ), + ), + TextureOpCode::CompareBias { compare, bias } => { + ("CompareBias", format!("compare:{} bias:{}", id_str(compare), id_str(bias))) + } + TextureOpCode::Grad { is_proj, dx, dy, offset } => ( + "Grad", + format!( + "is_proj:{} dx:{} dy:{}{}", + is_proj, + id_str(dx), + id_str(dy), + offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string()) + ), + ), + TextureOpCode::Gather { offset } => { + ("Gather", offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string())) + } + TextureOpCode::GatherComponent { component, offset } => ( + "GatherComponent", + format!( + "component:{}{}", + id_str(component), + offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string()) + ), + ), + TextureOpCode::GatherRef { refz, offset } => ( + "GatherRef", + format!( + "refz:{}{}", + id_str(refz), + offset.map(|id| format!(" offset:{}", id_str(id))).unwrap_or("".to_string()) + ), + ), + } +} + +fn opcode_str(op: &OpCode) -> String { + match *op { + OpCode::MergeInput => { + panic!("Internal error: No block instruction should use MergeInput") + } + OpCode::Call(id, ref params) => { + format!("Call {} With ({})", function_id_str(id), id_list_str(params)) + } + OpCode::Discard => "Discard".to_string(), + OpCode::Return(id) => { + format!("Return{}", id.map(|id| format!(" {}", id_str(id))).unwrap_or("".to_string())) + } + OpCode::Break => "Break".to_string(), + OpCode::Continue => "Continue".to_string(), + OpCode::Passthrough => "Passthrough".to_string(), + OpCode::NextBlock => "NextBlock".to_string(), + OpCode::Merge(id) => { + format!("Merge{}", id.map(|id| format!(" {}", id_str(id))).unwrap_or("".to_string())) + } + OpCode::If(id) => format!("If {}", id_str(id)), + OpCode::Loop => "Loop".to_string(), + OpCode::DoLoop => "DoLoop".to_string(), + OpCode::LoopIf(id) => format!("LoopIf {}", id_str(id)), + OpCode::Switch(id, _) => format!("Switch {}", id_str(id)), + OpCode::ExtractVectorComponent(id, index) => { + format!("ExtractVectorComponent {} {index}", id_str(id)) + } + OpCode::ExtractVectorComponentMulti(id, ref indices) => { + format!("ExtractVectorComponentMulti {} ({})", id_str(id), index_list_str(indices)) + } + OpCode::ExtractVectorComponentDynamic(id, index) => { + format!("ExtractVectorComponentDynamic {} {}", id_str(id), id_str(index)) + } + OpCode::ExtractMatrixColumn(id, index) => { + format!("ExtractMatrixColumn {} {}", id_str(id), id_str(index)) + } + OpCode::ExtractStructField(id, index) => { + format!("ExtractStructField {} {index}", id_str(id)) + } + OpCode::ExtractArrayElement(id, index) => { + format!("ExtractArrayElement {} {}", id_str(id), id_str(index)) + } + OpCode::ConstructScalarFromScalar(id) => { + format!("ConstructScalarFromScalar {}", id_str(id)) + } + OpCode::ConstructVectorFromScalar(id) => { + format!("ConstructVectorFromScalar {}", id_str(id)) + } + OpCode::ConstructMatrixFromScalar(id) => { + format!("ConstructMatrixFromScalar {}", id_str(id)) + } + OpCode::ConstructMatrixFromMatrix(id) => { + format!("ConstructMatrixFromMatrix {}", id_str(id)) + } + OpCode::ConstructVectorFromMultiple(ref ids) => { + format!("ConstructVectorFromMultiple ({})", id_list_str(ids)) + } + OpCode::ConstructMatrixFromMultiple(ref ids) => { + format!("ConstructMatrixFromMultiple ({})", id_list_str(ids)) + } + OpCode::ConstructStruct(ref ids) => { + format!("ConstructStruct ({})", id_list_str(ids)) + } + OpCode::ConstructArray(ref ids) => { + format!("ConstructArray ({})", id_list_str(ids)) + } + OpCode::AccessVectorComponent(id, index) => { + format!("AccessVectorComponent {} {index}", id_str(id)) + } + OpCode::AccessVectorComponentMulti(id, ref indices) => { + format!("AccessVectorComponentMulti {} ({})", id_str(id), index_list_str(indices)) + } + OpCode::AccessVectorComponentDynamic(id, index) => { + format!("AccessVectorComponentDynamic {} {}", id_str(id), id_str(index)) + } + OpCode::AccessMatrixColumn(id, index) => { + format!("AccessMatrixColumn {} {}", id_str(id), id_str(index)) + } + OpCode::AccessStructField(id, index) => { + format!("AccessStructField {} {index}", id_str(id)) + } + OpCode::AccessArrayElement(id, index) => { + format!("AccessArrayElement {} {}", id_str(id), id_str(index)) + } + OpCode::Load(id) => format!("Load {}", id_str(id)), + OpCode::Store(target, value) => { + format!("Store {} {}", id_str(target), id_str(value)) + } + OpCode::Alias(id) => format!("Alias {}", id_str(id)), + OpCode::Unary(unary_op, id) => { + format!("{} {}", unary_opcode_str(unary_op), id_str(id)) + } + OpCode::Binary(binary_op, lhs, rhs) => { + format!("{} {} {}", binary_opcode_str(binary_op), id_str(lhs), id_str(rhs)) + } + OpCode::BuiltIn(built_in_op, ref ids) => { + format!("{} ({})", built_in_opcode_str(built_in_op), id_list_str(ids)) + } + OpCode::Texture(ref texture_op, sampler, coord) => { + let (variant, params) = texture_opcode_str(texture_op); + format!( + "Texture{} sampler:{} coord:{} {}", + variant, + id_str(sampler), + id_str(coord), + params + ) + } + } +} + +// Helper to append to the string on a new line, unless the appended string is empty. +fn append_on_new_line(result: &mut String, new: String, indent: usize) { + if new.is_empty() { + return; + } + + result.push('\n'); + + // The first two levels of indent are " ", before the function blocks are output. + result.push_str(&" ".repeat(std::cmp::min(indent, 2))); + + // To annotate control flow, "| " is added per block indent. + if indent > 2 { + result.push_str(&"| ".repeat(indent - 2)); + } + + result.push_str(&new); +} + +fn dump_shader_properties(ir_meta: &IRMeta, result: &mut String) { + match ir_meta.get_shader_type() { + ShaderType::Fragment => { + append_on_new_line( + result, + early_fragment_tests_str(ir_meta.get_early_fragment_tests()), + 0, + ); + append_on_new_line( + result, + blend_equation_advanced_str(ir_meta.get_advanced_blend_equations()), + 0, + ); + } + ShaderType::TessellationControl => { + append_on_new_line(result, tcs_vertices_str(ir_meta.get_tcs_vertices()), 0); + } + ShaderType::TessellationEvaluation => { + append_on_new_line(result, tes_primitive_str(ir_meta.get_tes_primitive()), 0); + append_on_new_line(result, tes_vertex_spacing_str(ir_meta.get_tes_vertex_spacing()), 0); + append_on_new_line(result, tes_ordering_str(ir_meta.get_tes_ordering()), 0); + append_on_new_line(result, tes_point_mode_str(ir_meta.get_tes_point_mode()), 0); + } + ShaderType::Geometry => { + append_on_new_line(result, gs_primitive_str(ir_meta.get_gs_primitive_in(), "In"), 0); + append_on_new_line(result, gs_primitive_str(ir_meta.get_gs_primitive_out(), "Out"), 0); + append_on_new_line(result, gs_invocations_str(ir_meta.get_gs_invocations()), 0); + append_on_new_line(result, gs_max_vertices_str(ir_meta.get_gs_max_vertices()), 0); + } + _ => {} + }; +} + +fn dump_types(ir_meta: &IRMeta, result: &mut String) { + result.push_str("\n\nTypes:"); + ir_meta.all_types().iter().enumerate().for_each(|(id, t)| { + let formatted = format!( + "t{id}: {}", + match t { + &Type::Scalar(basic_type) => basic_type_str(basic_type), + &Type::Vector(type_id, count) => + format!("Vector of {}[{count}]", type_id_str(type_id)), + &Type::Matrix(type_id, count) => + format!("Matrix of {}[{count}]", type_id_str(type_id)), + &Type::Array(type_id, count) => + format!("Array of {}[{count}]", type_id_str(type_id)), + &Type::UnsizedArray(type_id) => + format!("Unsized Array of {}", type_id_str(type_id)), + &Type::Image(basic_type, image_type) => image_type_str(basic_type, image_type), + Type::Struct(name, _, specialization) => format!( + "{} {}:", + match specialization { + StructSpecialization::Struct => "Struct", + StructSpecialization::InterfaceBlock => "Interface Block", + }, + name_str(name, TEMP_STRUCT_PREFIX, id as u32) + ), + &Type::Pointer(type_id) => format!("Pointer to {}", type_id_str(type_id)), + Type::DeadCodeEliminated => { + return; + } + } + ); + append_on_new_line(result, formatted, 1); + if let Type::Struct(_, fields, _) = t { + fields + .iter() + .enumerate() + .for_each(|(index, field)| append_on_new_line(result, field_str(field, index), 2)); + } + }); +} + +fn dump_constants(ir_meta: &IRMeta, result: &mut String) { + result.push_str("\n\nConstants:"); + ir_meta.all_constants().iter().enumerate().for_each(|(id, c)| { + if c.is_dead_code_eliminated { + return; + } + let formatted = format!( + "c{id} ({}): {}", + type_id_str(c.type_id), + match &c.value { + &ConstantValue::Float(f) => format!("{f:?}"), + &ConstantValue::Int(i) => i.to_string(), + &ConstantValue::Uint(u) => u.to_string(), + &ConstantValue::Bool(b) => b.to_string(), + &ConstantValue::YuvCsc(yuv_csc) => yuv_csc_standard_str(yuv_csc), + ConstantValue::Composite(elements) => format!( + "composite({})", + elements + .iter() + .map(|&element| constant_id_str(element)) + .collect::>() + .join(", ") + ), + } + ); + append_on_new_line(result, formatted, 1); + }); +} + +fn dump_variables(ir_meta: &IRMeta, result: &mut String) { + result.push_str("\n\nVariables:"); + ir_meta.all_variables().iter().enumerate().for_each(|(id, v)| { + if v.is_dead_code_eliminated { + return; + } + let name = name_str(&v.name, TEMP_VARIABLE_PREFIX, id as u32); + let initializer = v + .initializer + .map(|constant_id| format!("={}", constant_id_str(constant_id))) + .or(ir_meta + .variable_needs_zero_initialization(VariableId { id: id as u32 }) + .then_some("=TO_BE_ZERO_INIT".to_string())) + .unwrap_or("".to_string()); + let built_in = v + .built_in + .map(|built_in| format!(" <{}>", built_in_str(built_in))) + .unwrap_or("".to_string()); + + let mut formatted = + format!("v{id} ({}): {}{}{}", type_id_str(v.type_id), name, initializer, built_in); + append_decorations(&mut formatted, v.precision, &v.decorations); + + append_on_new_line(result, formatted, 1); + }); + + write!( + result, + "\n\nGlobals: {}", + ir_meta + .all_global_variables() + .iter() + .map(|&id| variable_id_str(id)) + .collect::>() + .join(", ") + ) + .unwrap(); +} + +fn dump_instruction( + result: &mut String, + ir_meta: &IRMeta, + instruction: &BlockInstruction, + indent: usize, +) { + let (result_id, op, decorations) = match instruction { + &BlockInstruction::Register(id) => { + let instruction = ir_meta.get_instruction(id); + debug_assert!(id.id == instruction.result.id.id); + let type_id = format!("({})", type_id_str(instruction.result.type_id)); + ( + format!("{} {:>6} = ", register_id_str(id), type_id), + opcode_str(&instruction.op), + decoration_list(instruction.result.precision, &Decorations::new_none()), + ) + } + BlockInstruction::Void(op) => ("".to_string(), opcode_str(op), "".to_string()), + }; + + let mut formatted = format!("{result_id:15}{op}"); + + if !decorations.is_empty() { + formatted = format!("{formatted:60} [{decorations}]"); + } + + append_on_new_line(result, formatted, indent); +} + +fn dump_block( + result: &mut String, + ir_meta: &IRMeta, + kind: traverser::BlockKind, + block: &Block, + indent: usize, +) { + // Start every block with a new line to separate them more easily. + let block_kind = block_kind_str(kind); + let block_header = "_".repeat(block_kind.len()); + let is_merge_block = matches!(kind, traverser::BlockKind::Merge); + if is_merge_block { + append_on_new_line(result, "|".to_string(), indent); + append_on_new_line( + result, + "V".to_string() + &block_header[..block_header.len() - 1], + indent, + ); + } else if indent > 2 { + append_on_new_line(result, "|".to_string(), indent - 1); + append_on_new_line(result, "+-> ".to_string() + &block_header, indent - 1); + } else { + result.push('\n'); + append_on_new_line(result, block_header, indent); + } + append_on_new_line(result, block_kind, indent); + + block.input.inspect(|input| { + debug_assert!(matches!(ir_meta.get_instruction(input.id).op, OpCode::MergeInput)); + debug_assert!(ir_meta.get_instruction(input.id).result.type_id == input.type_id); + debug_assert!(ir_meta.get_instruction(input.id).result.precision == input.precision); + + let mut formatted = + format!("Input: {} ({})", register_id_str(input.id), type_id_str(input.type_id)); + append_decorations(&mut formatted, input.precision, &Decorations::new_none()); + append_on_new_line(result, formatted, indent); + }); + + if !block.variables.is_empty() { + let declarations = format!( + "Declare: {}", + block.variables.iter().map(|&id| variable_id_str(id)).collect::>().join(", ") + ); + append_on_new_line(result, declarations, indent); + } + + for instruction in &block.instructions { + dump_instruction(result, ir_meta, instruction, indent); + } +} + +fn dump_functions(ir_meta: &IRMeta, function_entries: &[Option], result: &mut String) { + result.push_str("\n\nFunctions:"); + + traverser::visitor::for_each_function( + result, + function_entries, + |result, id| { + result.push('\n'); + append_on_new_line(result, function_prototype_str(id, ir_meta.get_function(id)), 1); + }, + |result, block, kind, indent| { + dump_block(result, ir_meta, kind, block, indent + 2); + traverser::visitor::VISIT_SUB_BLOCKS + }, + |_, _| {}, + ); +} + +// Dump the IR for debug purposes. +pub fn dump(ir: &IR) { + // TODO: verify that the following removes the binary for dump_types etc, otherwise they + // all need to have this cfg. + //#[cfg(debug_assertions)] + { + let mut result = shader_type_str(ir.meta.get_shader_type()); + dump_shader_properties(&ir.meta, &mut result); + dump_types(&ir.meta, &mut result); + dump_constants(&ir.meta, &mut result); + dump_variables(&ir.meta, &mut result); + dump_functions(&ir.meta, &ir.function_entries, &mut result); + + println!("{result}"); + } +} diff --git a/src/compiler/translator/ir/src/instruction.rs b/src/compiler/translator/ir/src/instruction.rs new file mode 100644 index 00000000000..d0b0e3bcd5d --- /dev/null +++ b/src/compiler/translator/ir/src/instruction.rs @@ -0,0 +1,5218 @@ +// 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. +// +// Helper functions to create instructions given parameters. The result type and precision is +// automatically deduced, and const-folding is done if possible. + +use crate::ir::*; +use crate::*; + +// Helper functions that perform constant folding per instruction +mod const_fold { + use crate::ir::*; + + fn apply_unary_componentwise( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32) -> f32 + Copy, + IntOp: Fn(i32) -> i32 + Copy, + UintOp: Fn(u32) -> u32 + Copy, + BoolOp: Fn(bool) -> bool + Copy, + { + let constant = ir_meta.get_constant(constant_id); + debug_assert!(constant.type_id == result_type_id); + + match &constant.value { + &ConstantValue::Float(f) => ir_meta.get_constant_float(float_op(f)), + &ConstantValue::Int(i) => ir_meta.get_constant_int(int_op(i)), + &ConstantValue::Uint(u) => ir_meta.get_constant_uint(uint_op(u)), + &ConstantValue::Bool(b) => ir_meta.get_constant_bool(bool_op(b)), + ConstantValue::YuvCsc(_) => { + panic!("Internal error: Ops not allowed on YUV CSC constants") + } + ConstantValue::Composite(components) => { + let type_id = constant.type_id; + let element_type_id = ir_meta.get_type(type_id).get_element_type_id().unwrap(); + + let mapped = components + .clone() + .iter() + .map(|&component_id| { + apply_unary_componentwise( + ir_meta, + component_id, + element_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, mapped) + } + } + } + + fn apply_binary_to_scalars( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32, f32) -> f32 + Copy, + IntOp: Fn(i32, i32) -> i32 + Copy, + UintOp: Fn(u32, u32) -> u32 + Copy, + BoolOp: Fn(bool, bool) -> bool + Copy, + { + let lhs = ir_meta.get_constant(lhs_constant_id); + let rhs = ir_meta.get_constant(rhs_constant_id); + + match (&lhs.value, &rhs.value) { + (&ConstantValue::Float(f1), &ConstantValue::Float(f2)) => { + ir_meta.get_constant_float(float_op(f1, f2)) + } + (&ConstantValue::Int(i1), &ConstantValue::Int(i2)) => { + ir_meta.get_constant_int(int_op(i1, i2)) + } + (&ConstantValue::Uint(u1), &ConstantValue::Uint(u2)) => { + ir_meta.get_constant_uint(uint_op(u1, u2)) + } + (&ConstantValue::Bool(b1), &ConstantValue::Bool(b2)) => { + ir_meta.get_constant_bool(bool_op(b1, b2)) + } + (&ConstantValue::YuvCsc(_), &ConstantValue::YuvCsc(_)) => { + panic!("Internal error: Ops not allowed on YUV CSC constants") + } + _ => panic!("Internal error: Expected scalars when constant folding a binary op"), + } + } + + fn apply_binary_componentwise_scalar_rhs( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32, f32) -> f32 + Copy, + IntOp: Fn(i32, i32) -> i32 + Copy, + UintOp: Fn(u32, u32) -> u32 + Copy, + BoolOp: Fn(bool, bool) -> bool + Copy, + { + let lhs = ir_meta.get_constant(lhs_constant_id); + + if let ConstantValue::Composite(lhs_components) = &lhs.value { + let result_element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap_or(result_type_id); + + let components = lhs_components + .clone() + .iter() + .map(|&lhs_component_id| { + apply_binary_componentwise_scalar_rhs( + ir_meta, + lhs_component_id, + rhs_constant_id, + result_element_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, components) + } else { + apply_binary_to_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } + } + + fn apply_binary_componentwise_scalar_lhs( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32, f32) -> f32 + Copy, + IntOp: Fn(i32, i32) -> i32 + Copy, + UintOp: Fn(u32, u32) -> u32 + Copy, + BoolOp: Fn(bool, bool) -> bool + Copy, + { + let rhs = ir_meta.get_constant(rhs_constant_id); + + if let ConstantValue::Composite(rhs_components) = &rhs.value { + let result_element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap_or(result_type_id); + + let components = rhs_components + .clone() + .iter() + .map(|&rhs_component_id| { + apply_binary_componentwise_scalar_lhs( + ir_meta, + lhs_constant_id, + rhs_component_id, + result_element_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, components) + } else { + apply_binary_to_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } + } + + fn apply_binary_componentwise_non_scalar( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32, f32) -> f32 + Copy, + IntOp: Fn(i32, i32) -> i32 + Copy, + UintOp: Fn(u32, u32) -> u32 + Copy, + BoolOp: Fn(bool, bool) -> bool + Copy, + { + let lhs = ir_meta.get_constant(lhs_constant_id); + let rhs = ir_meta.get_constant(rhs_constant_id); + + if let ( + ConstantValue::Composite(lhs_components), + ConstantValue::Composite(rhs_components), + ) = (&lhs.value, &rhs.value) + { + let result_element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap_or(result_type_id); + + let components = lhs_components + .clone() + .iter() + .zip(rhs_components.clone().iter()) + .map(|(&lhs_component_id, &rhs_component_id)| { + apply_binary_componentwise_non_scalar( + ir_meta, + lhs_component_id, + rhs_component_id, + result_element_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, components) + } else { + apply_binary_to_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } + } + + fn apply_binary_componentwise( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32, f32) -> f32 + Copy, + IntOp: Fn(i32, i32) -> i32 + Copy, + UintOp: Fn(u32, u32) -> u32 + Copy, + BoolOp: Fn(bool, bool) -> bool + Copy, + { + let is_lhs_scalar = !ir_meta.get_constant(lhs_constant_id).value.is_composite(); + let is_rhs_scalar = !ir_meta.get_constant(rhs_constant_id).value.is_composite(); + + if is_rhs_scalar { + apply_binary_componentwise_scalar_rhs( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } else if is_lhs_scalar { + apply_binary_componentwise_scalar_lhs( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } else { + apply_binary_componentwise_non_scalar( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } + } + + pub fn composite_element( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + index: u32, + _result_type_id: TypeId, + ) -> ConstantId { + ir_meta.get_constant(constant_id).value.get_composite_elements()[index as usize] + } + + pub fn vector_component_multi( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + fields: &[u32], + result_type_id: TypeId, + ) -> ConstantId { + let composite_elements = ir_meta.get_constant(constant_id).value.get_composite_elements(); + let new_elements = fields.iter().map(|&field| composite_elements[field as usize]).collect(); + ir_meta.get_constant_composite(result_type_id, new_elements) + } + + pub fn index( + ir_meta: &mut IRMeta, + indexed_constant_id: ConstantId, + index_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let index = ir_meta.get_constant(index_constant_id).value.get_index(); + composite_element(ir_meta, indexed_constant_id, index, result_type_id) + } + + // Taking a list of constants, flattens them so every element is a basic type. For example, + // [v.xy, m2x3, ...] becomes [v.x, v.y, m[0][0], m[0][1], ...] + fn flatten_constructor_args( + ir_meta: &IRMeta, + args: std::iter::Peekable, + ) -> Vec + where + I: Iterator, + { + let mut result = Vec::new(); + + for arg in args { + let constant = ir_meta.get_constant(arg); + + if let ConstantValue::Composite(ids) = &constant.value { + let flattened = flatten_constructor_args(ir_meta, ids.iter().copied().peekable()); + result.extend(flattened); + } else { + result.push(arg); + } + } + + result + } + + // Taking a list of all-scalar constants, casts the values to the given basic_type. + fn cast_constructor_args( + ir_meta: &mut IRMeta, + args: Vec, + basic_type: BasicType, + ) -> Vec { + args.iter() + .map(|&arg| { + let constant = ir_meta.get_constant(arg); + if let ConstantValue::Float(f) = constant.value { + match basic_type { + BasicType::Int => ir_meta.get_constant_int(f as i32), + // Note: ESSL 3.00.6 section 5.4.1. It is undefined to convert a negative + // floating-point value to an uint + BasicType::Uint => ir_meta.get_constant_uint(if f < 0.0 { + f as i32 as u32 + } else { + f as u32 + }), + BasicType::Bool => ir_meta.get_constant_bool(f != 0.0), + _ => arg, + } + } else if let ConstantValue::Int(i) = constant.value { + match basic_type { + BasicType::Float => ir_meta.get_constant_float(i as f32), + BasicType::Uint => ir_meta.get_constant_uint(i as u32), + BasicType::Bool => ir_meta.get_constant_bool(i != 0), + _ => arg, + } + } else if let ConstantValue::Uint(u) = constant.value { + match basic_type { + BasicType::Float => ir_meta.get_constant_float(u as f32), + BasicType::Int => ir_meta.get_constant_int(u as i32), + BasicType::Bool => ir_meta.get_constant_bool(u != 0), + _ => arg, + } + } else if let ConstantValue::Bool(b) = constant.value { + match basic_type { + BasicType::Float => ir_meta.get_constant_float(b.into()), + BasicType::Int => ir_meta.get_constant_int(b as i32), + BasicType::Uint => ir_meta.get_constant_uint(b as u32), + _ => arg, + } + } else { + // This function is called on scalars, so `Composite` is impossible. + // Additionally, GLSL forbids type conversion to and from + // yuvCscStandardEXT. + arg + } + }) + .collect() + } + + // Construct a vector from a scalar by replicating it. + fn construct_vector_from_scalar( + ir_meta: &mut IRMeta, + arg: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let type_info = ir_meta.get_type(result_type_id); + let vec_size = type_info.get_vector_size().unwrap(); + let args = vec![arg; vec_size as usize]; + ir_meta.get_constant_composite(result_type_id, args) + } + + // Construct a matrix from a scalar by setting the diagonal elements with that scalar while + // everywhere else is filled with zeros. + fn construct_matrix_from_scalar( + ir_meta: &mut IRMeta, + arg: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let type_info = ir_meta.get_type(result_type_id); + let &Type::Matrix(vector_type_id, column_count) = type_info else { unreachable!() }; + let &Type::Vector(_, row_count) = ir_meta.get_type(vector_type_id) else { unreachable!() }; + + // Create columns where every component is 0 except the one at index = column_index. + let columns = (0..column_count) + .map(|column| { + let column_components = (0..row_count) + .map(|row| if row == column { arg } else { CONSTANT_ID_FLOAT_ZERO }) + .collect(); + ir_meta.get_constant_composite(vector_type_id, column_components) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, columns) + } + + // Construct a matrix from a matrix by starting with the identity matrix and overwriting it with + // components from the argument. + fn construct_matrix_from_matrix( + ir_meta: &mut IRMeta, + arg: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let type_info = ir_meta.get_type(result_type_id); + let &Type::Matrix(vector_type_id, column_count) = type_info else { unreachable!() }; + let &Type::Vector(_, row_count) = ir_meta.get_type(vector_type_id) else { unreachable!() }; + + let input = ir_meta.get_constant(arg); + let input_columns = input.value.get_composite_elements(); + let input_column_components: Vec<_> = input_columns + .iter() + .map(|&column_id| ir_meta.get_constant(column_id).value.get_composite_elements()) + .collect(); + let input_column_count = input_columns.len() as u32; + let input_row_count = input_column_components[0].len() as u32; + + // Create columns where every component is taken from the input matrix, except if it's out + // of bounds. In that case, the component is 1 on the diagonal and 0 elsewhere. + let columns: Vec<_> = (0..column_count) + .map(|column| { + (0..row_count) + .map(|row| { + if column < input_column_count && row < input_row_count { + input_column_components[column as usize][row as usize] + } else if row == column { + CONSTANT_ID_FLOAT_ONE + } else { + CONSTANT_ID_FLOAT_ZERO + } + }) + .collect() + }) + .collect(); + + let columns = columns + .into_iter() + .map(|column_components| { + ir_meta.get_constant_composite(vector_type_id, column_components) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, columns) + } + + // Construct a vector from multiple components. + fn construct_vector_from_many( + ir_meta: &mut IRMeta, + args: Vec, + result_type_id: TypeId, + ) -> ConstantId { + ir_meta.get_constant_composite(result_type_id, args) + } + + // Construct a matrix from multiple components. + fn construct_matrix_from_many( + ir_meta: &mut IRMeta, + args: Vec, + result_type_id: TypeId, + ) -> ConstantId { + let type_info = ir_meta.get_type(result_type_id); + let &Type::Matrix(vector_type_id, column_count) = type_info else { unreachable!() }; + let &Type::Vector(_, row_count) = ir_meta.get_type(vector_type_id) else { unreachable!() }; + + let columns = (0..column_count) + .map(|column| { + let start = (column * row_count) as usize; + let end = start + row_count as usize; + ir_meta.get_constant_composite(vector_type_id, args[start..end].to_vec()) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, columns) + } + + pub fn construct( + ir_meta: &mut IRMeta, + args: &mut impl Iterator, + result_type_id: TypeId, + ) -> ConstantId { + let type_info = ir_meta.get_type(result_type_id); + + // For arrays and struct, simply make the constant out of the arguments. + if type_info.is_struct() || type_info.is_array() { + return ir_meta.get_constant_composite(result_type_id, args.collect()); + } + + let is_vector = type_info.is_vector(); + let is_matrix = type_info.is_matrix(); + let mut args = args.peekable(); + let first_arg = *args.peek().unwrap(); + let is_first_arg_matrix = + ir_meta.get_type(ir_meta.get_constant(first_arg).type_id).is_matrix(); + + if is_matrix && is_first_arg_matrix { + // Matrix-from-matrix construction is special with the way a sub-region of the argument + // is picked out, so flatten_constructor_args` cannot be used. + construct_matrix_from_matrix(ir_meta, first_arg, result_type_id) + } else { + // For scalars, vectors and matrices, first flatten the components for simplicity. + let args = flatten_constructor_args(ir_meta, args); + + // Then cast the basic type to the type of the result, if needed. + let basic_type = + ir_meta.get_type(ir_meta.get_scalar_type(result_type_id)).get_scalar_basic_type(); + let args = cast_constructor_args(ir_meta, args, basic_type); + + if is_vector && args.len() == 1 { + construct_vector_from_scalar(ir_meta, args[0], result_type_id) + } else if is_matrix && args.len() == 1 { + construct_matrix_from_scalar(ir_meta, args[0], result_type_id) + } else if is_vector { + construct_vector_from_many(ir_meta, args, result_type_id) + } else if is_matrix { + construct_matrix_from_many(ir_meta, args, result_type_id) + } else { + // The type cast is enough to satisfy scalar constructors. + args[0] + } + } + } + + pub fn negate( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_unary_componentwise( + ir_meta, + constant_id, + result_type_id, + |f| -f, + |i| i.wrapping_neg(), + |u| u.wrapping_neg(), + |_| panic!("Internal error: Cannot negate a bool"), + ) + } + pub fn add( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 + f2, + |i1, i2| i1.wrapping_add(i2), + |u1, u2| u1.wrapping_add(u2), + |_, _| panic!("Internal error: Cannot add bools"), + ) + } + pub fn sub( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 - f2, + |i1, i2| i1.wrapping_sub(i2), + |u1, u2| u1.wrapping_sub(u2), + |_, _| panic!("Internal error: Cannot subtract bools"), + ) + } + pub fn mul( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 * f2, + |i1, i2| i1.wrapping_mul(i2), + |u1, u2| u1.wrapping_mul(u2), + |_, _| panic!("Internal error: Cannot multiply bools"), + ) + } + pub fn div( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 / f2, + |i1, i2| i1.checked_div(i2).unwrap_or(i32::MAX), + |u1, u2| u1.checked_div(u2).unwrap_or(u32::MAX), + |_, _| panic!("Internal error: Cannot divide bools"), + ) + } + pub fn imod( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |_, _| panic!("Internal error: Cannot use % to calculate remainder of floats"), + // ESSL 3.00.6 section 5.9: Results of modulus are undefined when either one of the + // operands is negative. + |i1, i2| if i1 < 0 || i2 < 0 { 0 } else { i1.checked_rem(i2).unwrap_or(0) }, + |u1, u2| u1.checked_rem(u2).unwrap_or(0), + |_, _| panic!("Internal error: Cannot use % on bools"), + ) + } + pub fn dot(ir_meta: &IRMeta, lhs_constant_id: ConstantId, rhs_constant_id: ConstantId) -> f32 { + let lhs = ir_meta.get_constant(lhs_constant_id); + let rhs = ir_meta.get_constant(rhs_constant_id); + + if !lhs.value.is_composite() { + return lhs.value.get_float() * rhs.value.get_float(); + } + + let lhs_components = lhs.value.get_composite_elements(); + let rhs_components = rhs.value.get_composite_elements(); + + lhs_components + .iter() + .zip(rhs_components.iter()) + .map(|(&lhs_component_id, &rhs_component_id)| { + ir_meta.get_constant(lhs_component_id).value.get_float() + * ir_meta.get_constant(rhs_component_id).value.get_float() + }) + .sum() + } + pub fn transpose( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let constant = ir_meta.get_constant(constant_id); + let columns = constant.value.get_composite_elements(); + let column_count = columns.len(); + let row_count = ir_meta.get_type(result_type_id).get_matrix_size().unwrap(); + + let mut transposed_data = vec![Vec::new(); row_count as usize]; + + // Create new columns out of rows of the matrix. + columns.iter().for_each(|&column_id| { + let column = ir_meta.get_constant(column_id).value.get_composite_elements(); + debug_assert!(column.len() == row_count as usize); + column.iter().enumerate().for_each(|(row_index, &component)| { + transposed_data[row_index].push(component); + }); + }); + + // Create constants for these columns. + let transposed_column_type_id = + ir_meta.get_vector_type_id(BasicType::Float, column_count as u32); + let transposed_column_ids = transposed_data + .into_iter() + .map(|data| ir_meta.get_constant_composite(transposed_column_type_id, data)) + .collect(); + + // Finally, assemble the matrix itself. + ir_meta.get_constant_composite(result_type_id, transposed_column_ids) + } + pub fn vector_times_matrix( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let rhs = ir_meta.get_constant(rhs_constant_id); + let rhs_columns = rhs.value.get_composite_elements(); + + let result_column_ids = rhs_columns + .clone() + .iter() + .map(|&column_id| ir_meta.get_constant_float(dot(ir_meta, lhs_constant_id, column_id))) + .collect(); + ir_meta.get_constant_composite(result_type_id, result_column_ids) + } + pub fn matrix_times_vector( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let lhs = ir_meta.get_constant(lhs_constant_id); + let matrix_type = ir_meta.get_type(lhs.type_id); + let column_count = matrix_type.get_matrix_size().unwrap(); + let row_count = ir_meta.get_type(result_type_id).get_vector_size().unwrap(); + + // Transpose the matrix first, so `vector_times_matrix` can be reused. + let transposed_type_id = ir_meta.get_matrix_type_id(row_count, column_count); + let transposed = transpose(ir_meta, lhs_constant_id, transposed_type_id); + vector_times_matrix(ir_meta, rhs_constant_id, transposed, result_type_id) + } + pub fn matrix_times_matrix( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let lhs = ir_meta.get_constant(lhs_constant_id); + let rhs = ir_meta.get_constant(rhs_constant_id); + let lhs_type = ir_meta.get_type(lhs.type_id); + let result_type = ir_meta.get_type(result_type_id); + + let lhs_columns = lhs.value.get_composite_elements(); + let rhs_columns = rhs.value.get_composite_elements().clone(); + + let result_column_type_id = result_type.get_element_type_id().unwrap(); + + // Say LHS has C1 columns of R1 components, and RHS has C2 columns of R2 components. For + // matrix times matrix to work, C1 == R2 must hold. The result will have C2 columns of R1 + // components. + let rhs_column_count = rhs_columns.len(); + let common_component_count = lhs_columns.len(); + let lhs_row_count = ir_meta.get_type(result_column_type_id).get_vector_size().unwrap(); + + debug_assert!( + ir_meta.get_type(lhs_type.get_element_type_id().unwrap()).get_vector_size().unwrap() + == lhs_row_count + ); + debug_assert!(result_type.get_matrix_size().unwrap() == rhs_column_count as u32); + + // The result at column c, row r, is the dot product of row r in lhs and column c in rhs. + // Equivalently, it's the dot product of column r in transposed lhs and column c in rhs. + // The lhs is thus transposed so the `dot` helper can be used. + let lhs_transposed_type_id = + ir_meta.get_matrix_type_id(lhs_row_count, common_component_count as u32); + let lhs_transposed_id = transpose(ir_meta, lhs_constant_id, lhs_transposed_type_id); + + let lhs = ir_meta.get_constant(lhs_transposed_id); + let lhs_columns = lhs.value.get_composite_elements().clone(); + + let result_columns_ids = rhs_columns + .iter() + .map(|&rhs_column_id| { + let result_column_ids = lhs_columns + .iter() + .map(|&lhs_column_id| { + ir_meta.get_constant_float(dot(ir_meta, lhs_column_id, rhs_column_id)) + }) + .collect(); + ir_meta.get_constant_composite(result_column_type_id, result_column_ids) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, result_columns_ids) + } + pub fn logical_not( + _ir_meta: &mut IRMeta, + constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + debug_assert!(constant_id == CONSTANT_ID_TRUE || constant_id == CONSTANT_ID_FALSE); + if constant_id == CONSTANT_ID_FALSE { CONSTANT_ID_TRUE } else { CONSTANT_ID_FALSE } + } + pub fn logical_xor( + _ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + debug_assert!(lhs_constant_id == CONSTANT_ID_TRUE || lhs_constant_id == CONSTANT_ID_FALSE); + debug_assert!(rhs_constant_id == CONSTANT_ID_TRUE || rhs_constant_id == CONSTANT_ID_FALSE); + + if lhs_constant_id == rhs_constant_id { CONSTANT_ID_FALSE } else { CONSTANT_ID_TRUE } + } + pub fn equal( + _ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + // Note: because the IR ensures constants are unique, no need for a recursive equality + // check of the components. + if lhs_constant_id == rhs_constant_id { CONSTANT_ID_TRUE } else { CONSTANT_ID_FALSE } + } + pub fn not_equal( + _ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + if lhs_constant_id == rhs_constant_id { CONSTANT_ID_FALSE } else { CONSTANT_ID_TRUE } + } + fn compare_scalars( + ir_meta: &IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + float_compare: FloatCompare, + int_compare: IntCompare, + uint_compare: UintCompare, + ) -> ConstantId + where + FloatCompare: FnOnce(f32, f32) -> bool, + IntCompare: FnOnce(i32, i32) -> bool, + UintCompare: FnOnce(u32, u32) -> bool, + { + let lhs_constant = ir_meta.get_constant(lhs_constant_id); + let rhs_constant = ir_meta.get_constant(rhs_constant_id); + + let result = match (&lhs_constant.value, &rhs_constant.value) { + (&ConstantValue::Float(lhs_f), &ConstantValue::Float(rhs_f)) => { + float_compare(lhs_f, rhs_f) + } + (&ConstantValue::Int(lhs_i), &ConstantValue::Int(rhs_i)) => int_compare(lhs_i, rhs_i), + (&ConstantValue::Uint(lhs_u), &ConstantValue::Uint(rhs_u)) => { + uint_compare(lhs_u, rhs_u) + } + _ => false, + }; + + if result { CONSTANT_ID_TRUE } else { CONSTANT_ID_FALSE } + } + pub fn less_than( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + compare_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + |f1, f2| f1 < f2, + |i1, i2| i1 < i2, + |u1, u2| u1 < u2, + ) + } + pub fn greater_than( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + compare_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + |f1, f2| f1 > f2, + |i1, i2| i1 > i2, + |u1, u2| u1 > u2, + ) + } + pub fn less_than_equal( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + compare_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + |f1, f2| f1 <= f2, + |i1, i2| i1 <= i2, + |u1, u2| u1 <= u2, + ) + } + pub fn greater_than_equal( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + compare_scalars( + ir_meta, + lhs_constant_id, + rhs_constant_id, + |f1, f2| f1 >= f2, + |i1, i2| i1 >= i2, + |u1, u2| u1 >= u2, + ) + } + pub fn bitwise_not( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_unary_componentwise( + ir_meta, + constant_id, + result_type_id, + |_| panic!("Internal error: Cannot bitwise-not a float"), + |i| !i, + |u| !u, + |_| panic!("Internal error: Cannot bitwise-not a bool"), + ) + } + pub fn bit_shift_left( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + // GLSL allows the operands of shift to differ in signedness. Cast the rhs to the type of + // lhs before calling the helper. This can be conveniently done with `construct`, which + // may turn a scalar rhs into a vector. This is ok because the operation is component-wise + // anyway. + let lhs_type_id = ir_meta.get_constant(lhs_constant_id).type_id; + let rhs_constant_id = + construct(ir_meta, &mut std::iter::once(rhs_constant_id), lhs_type_id); + + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |_, _| panic!("Internal error: Cannot use << on floats"), + |i1, i2| i1.checked_shl(i2 as u32).unwrap_or(0), + |u1, u2| u1.checked_shl(u2).unwrap_or(0), + |_, _| panic!("Internal error: Cannot use << on bools"), + ) + } + pub fn bit_shift_right( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + // See bit_shift_left + let lhs_type_id = ir_meta.get_constant(lhs_constant_id).type_id; + let rhs_constant_id = + construct(ir_meta, &mut std::iter::once(rhs_constant_id), lhs_type_id); + + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |_, _| panic!("Internal error: Cannot use >> on floats"), + |i1, i2| i1.checked_shr(i2 as u32).unwrap_or(0), + |u1, u2| u1.checked_shr(u2).unwrap_or(0), + |_, _| panic!("Internal error: Cannot use >> on bools"), + ) + } + pub fn bitwise_or( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |_, _| panic!("Internal error: Cannot use | on floats"), + |i1, i2| i1 | i2, + |u1, u2| u1 | u2, + |_, _| panic!("Internal error: Cannot use | on bools"), + ) + } + pub fn bitwise_xor( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |_, _| panic!("Internal error: Cannot use ^ on floats"), + |i1, i2| i1 ^ i2, + |u1, u2| u1 ^ u2, + |_, _| panic!("Internal error: Cannot use ^ on bools"), + ) + } + pub fn bitwise_and( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |_, _| panic!("Internal error: Cannot use & on floats"), + |i1, i2| i1 & i2, + |u1, u2| u1 & u2, + |_, _| panic!("Internal error: Cannot use & on bools"), + ) + } + // Helpers to fold unary built-ins that do not apply the operation component-wise or don't + // match the common patterns. + fn bitcast_helper( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + op: Op, + ) -> ConstantId + where + Op: Fn(&mut IRMeta, &ConstantValue) -> ConstantId + Copy, + { + let constant = ir_meta.get_constant(constant_id); + let element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap_or(result_type_id); + + if let ConstantValue::Composite(components) = &constant.value { + let mapped = components + .clone() + .iter() + .map(|&component_id| bitcast_helper(ir_meta, component_id, element_type_id, op)) + .collect(); + ir_meta.get_constant_composite(result_type_id, mapped) + } else { + op(ir_meta, &constant.value.clone()) + } + } + fn built_in_floatbitstoint( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| { + ir_meta.get_constant_int(value.get_float().to_bits() as i32) + }) + } + fn built_in_floatbitstouint( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| { + ir_meta.get_constant_uint(value.get_float().to_bits()) + }) + } + fn built_in_intbitstofloat( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| { + ir_meta.get_constant_float(f32::from_bits(value.get_int() as u32)) + }) + } + fn built_in_uintbitstofloat( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| { + ir_meta.get_constant_float(f32::from_bits(value.get_uint())) + }) + } + fn built_in_bitcount( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| match *value { + ConstantValue::Int(i) => ir_meta.get_constant_int(i.count_ones() as i32), + ConstantValue::Uint(u) => ir_meta.get_constant_int(u.count_ones() as i32), + _ => { + panic!("Internal error: The bitCount() built-in only applies to [u]int types"); + } + }) + } + fn built_in_findlsb( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| match *value { + ConstantValue::Int(i) => { + ir_meta.get_constant_int(if i == 0 { -1 } else { i.trailing_zeros() as i32 }) + } + ConstantValue::Uint(u) => { + ir_meta.get_constant_int(if u == 0 { -1 } else { u.trailing_zeros() as i32 }) + } + _ => { + panic!("Internal error: The findLSB() built-in only applies to [u]int types"); + } + }) + } + fn built_in_findmsb( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + bitcast_helper(ir_meta, constant_id, result_type_id, |ir_meta, value| { + match *value { + ConstantValue::Int(i) => { + // Note: For negative numbers, look for zero instead of one in value. Using + // complement handles the intValue == -1 special case, where the return value + // needs to be -1. + println!("Got {i}"); + let i = if i < 0 { !i } else { i }; + println!("Maybe complement: {i}"); + ir_meta.get_constant_int(if i == 0 { + -1 + } else { + 31 - i.leading_zeros() as i32 + }) + } + ConstantValue::Uint(u) => ir_meta.get_constant_int(if u == 0 { + -1 + } else { + 31 - u.leading_zeros() as i32 + }), + _ => { + panic!("Internal error: The findMSB() built-in only applies to [u]int types"); + } + } + }) + } + fn built_in_any( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let constant = ir_meta.get_constant(constant_id); + debug_assert!(result_type_id == TYPE_ID_BOOL); + + let any = constant.value.get_composite_elements().contains(&CONSTANT_ID_TRUE); + ir_meta.get_constant_bool(any) + } + fn built_in_all( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let constant = ir_meta.get_constant(constant_id); + debug_assert!(result_type_id == TYPE_ID_BOOL); + + let all = constant + .value + .get_composite_elements() + .iter() + .all(|&component_id| component_id == CONSTANT_ID_TRUE); + ir_meta.get_constant_bool(all) + } + fn get_vector_length(ir_meta: &IRMeta, constant: &Constant) -> f32 { + let sum: f32 = constant + .value + .get_composite_elements() + .iter() + .map(|&component_id| { + let component = ir_meta.get_constant(component_id).value.get_float(); + component * component + }) + .sum(); + sum.sqrt() + } + fn built_in_length( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + debug_assert!(result_type_id == TYPE_ID_FLOAT); + + let constant = ir_meta.get_constant(constant_id); + if !constant.value.is_composite() { + return constant_id; + } + + let length = get_vector_length(ir_meta, constant); + ir_meta.get_constant_float(length) + } + fn built_in_normalize( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let constant = ir_meta.get_constant(constant_id); + debug_assert!(result_type_id == constant.type_id); + + if !constant.value.is_composite() { + return CONSTANT_ID_FLOAT_ONE; + } + + let length = get_vector_length(ir_meta, constant); + + let mapped = constant + .value + .get_composite_elements() + .clone() + .iter() + .map(|&component_id| { + let component = ir_meta.get_constant(component_id).value.get_float() / length; + ir_meta.get_constant_float(component) + }) + .collect(); + + ir_meta.get_constant_composite(result_type_id, mapped) + } + fn built_in_transpose( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + transpose(ir_meta, constant_id, result_type_id) + } + fn determinant_2x2(m: &[&[f32]; 2]) -> f32 { + m[0][0] * m[1][1] - m[0][1] * m[1][0] + } + fn determinant_3x3(m: &[&[f32]; 3]) -> f32 { + let sub0 = [&m[1][1..], &m[2][1..]]; + let sub1 = [&m[0][1..], &m[2][1..]]; + let sub2 = [&m[0][1..], &m[1][1..]]; + + m[0][0] * determinant_2x2(&sub0) - m[1][0] * determinant_2x2(&sub1) + + m[2][0] * determinant_2x2(&sub2) + } + fn determinant_4x4(m: &[&[f32]; 4]) -> f32 { + let sub0 = [&m[1][1..], &m[2][1..], &m[3][1..]]; + let sub1 = [&m[0][1..], &m[2][1..], &m[3][1..]]; + let sub2 = [&m[0][1..], &m[1][1..], &m[3][1..]]; + let sub3 = [&m[0][1..], &m[1][1..], &m[2][1..]]; + + m[0][0] * determinant_3x3(&sub0) - m[1][0] * determinant_3x3(&sub1) + + m[2][0] * determinant_3x3(&sub2) + - m[3][0] * determinant_3x3(&sub3) + } + fn get_matrix_values(ir_meta: &IRMeta, constant_id: ConstantId) -> ([[f32; 4]; 4], usize) { + let columns = ir_meta.get_constant(constant_id).value.get_composite_elements(); + let mut column_values = [[0.; 4]; 4]; + let column_count = columns.len(); + + // Gather all constant values in the matrix first to simplify processing. + columns.iter().enumerate().for_each(|(column_index, &column_id)| { + let column = ir_meta.get_constant(column_id).value.get_composite_elements(); + // Note: only needed on square matrices in GLSL. + debug_assert!(column.len() == column_count); + column.iter().enumerate().for_each(|(row_index, &component)| { + column_values[column_index][row_index] = + ir_meta.get_constant(component).value.get_float(); + }); + }); + + (column_values, column_count) + } + fn determinant_helper(m: &[[f32; 4]; 4], size: usize) -> f32 { + let m2x2: [&[f32]; 2] = [&m[0], &m[1]]; + let m3x3: [&[f32]; 3] = [&m[0], &m[1], &m[2]]; + let m4x4: [&[f32]; 4] = [&m[0], &m[1], &m[2], &m[3]]; + match size { + 2 => determinant_2x2(&m2x2), + 3 => determinant_3x3(&m3x3), + 4 => determinant_4x4(&m4x4), + _ => panic!( + "Internal error: Invalid matrix dimensions when calculating determinant/inverse" + ), + } + } + fn determinant(ir_meta: &IRMeta, constant_id: ConstantId) -> f32 { + let (m, size) = get_matrix_values(ir_meta, constant_id); + determinant_helper(&m, size) + } + fn built_in_determinant( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + _result_type_id: TypeId, + ) -> ConstantId { + let determinant = determinant(ir_meta, constant_id); + ir_meta.get_constant_float(determinant) + } + fn built_in_inverse( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let (m, size) = get_matrix_values(ir_meta, constant_id); + let determinant = determinant_helper(&m, size); + let determinant_reciprocal = if determinant == 0. { 0. } else { determinant.recip() }; + + // The inverse of A is the transpose of the cofactor matrix times the reciprocal of the + // determinant of A. In the following, the cofactor matrix is calculated and + // simultaneously transposed. + let mut coft = [[0.; 4]; 4]; + let vec_type_id = match size { + 2 => { + coft[0][0] = m[1][1]; + coft[1][0] = -m[1][0]; + coft[0][1] = -m[0][1]; + coft[1][1] = m[0][0]; + TYPE_ID_VEC2 + } + 3 => { + coft[0][0] = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + coft[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); + coft[2][0] = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + coft[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]); + coft[1][1] = m[0][0] * m[2][2] - m[2][0] * m[0][2]; + coft[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]); + coft[0][2] = m[0][1] * m[1][2] - m[1][1] * m[0][2]; + coft[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]); + coft[2][2] = m[0][0] * m[1][1] - m[1][0] * m[0][1]; + TYPE_ID_VEC3 + } + 4 => { + coft[0][0] = m[1][1] * m[2][2] * m[3][3] + + m[2][1] * m[3][2] * m[1][3] + + m[3][1] * m[1][2] * m[2][3] + - m[1][1] * m[3][2] * m[2][3] + - m[2][1] * m[1][2] * m[3][3] + - m[3][1] * m[2][2] * m[1][3]; + coft[1][0] = -(m[1][0] * m[2][2] * m[3][3] + + m[2][0] * m[3][2] * m[1][3] + + m[3][0] * m[1][2] * m[2][3] + - m[1][0] * m[3][2] * m[2][3] + - m[2][0] * m[1][2] * m[3][3] + - m[3][0] * m[2][2] * m[1][3]); + coft[2][0] = m[1][0] * m[2][1] * m[3][3] + + m[2][0] * m[3][1] * m[1][3] + + m[3][0] * m[1][1] * m[2][3] + - m[1][0] * m[3][1] * m[2][3] + - m[2][0] * m[1][1] * m[3][3] + - m[3][0] * m[2][1] * m[1][3]; + coft[3][0] = -(m[1][0] * m[2][1] * m[3][2] + + m[2][0] * m[3][1] * m[1][2] + + m[3][0] * m[1][1] * m[2][2] + - m[1][0] * m[3][1] * m[2][2] + - m[2][0] * m[1][1] * m[3][2] + - m[3][0] * m[2][1] * m[1][2]); + coft[0][1] = -(m[0][1] * m[2][2] * m[3][3] + + m[2][1] * m[3][2] * m[0][3] + + m[3][1] * m[0][2] * m[2][3] + - m[0][1] * m[3][2] * m[2][3] + - m[2][1] * m[0][2] * m[3][3] + - m[3][1] * m[2][2] * m[0][3]); + coft[1][1] = m[0][0] * m[2][2] * m[3][3] + + m[2][0] * m[3][2] * m[0][3] + + m[3][0] * m[0][2] * m[2][3] + - m[0][0] * m[3][2] * m[2][3] + - m[2][0] * m[0][2] * m[3][3] + - m[3][0] * m[2][2] * m[0][3]; + coft[2][1] = -(m[0][0] * m[2][1] * m[3][3] + + m[2][0] * m[3][1] * m[0][3] + + m[3][0] * m[0][1] * m[2][3] + - m[0][0] * m[3][1] * m[2][3] + - m[2][0] * m[0][1] * m[3][3] + - m[3][0] * m[2][1] * m[0][3]); + coft[3][1] = m[0][0] * m[2][1] * m[3][2] + + m[2][0] * m[3][1] * m[0][2] + + m[3][0] * m[0][1] * m[2][2] + - m[0][0] * m[3][1] * m[2][2] + - m[2][0] * m[0][1] * m[3][2] + - m[3][0] * m[2][1] * m[0][2]; + coft[0][2] = m[0][1] * m[1][2] * m[3][3] + + m[1][1] * m[3][2] * m[0][3] + + m[3][1] * m[0][2] * m[1][3] + - m[0][1] * m[3][2] * m[1][3] + - m[1][1] * m[0][2] * m[3][3] + - m[3][1] * m[1][2] * m[0][3]; + coft[1][2] = -(m[0][0] * m[1][2] * m[3][3] + + m[1][0] * m[3][2] * m[0][3] + + m[3][0] * m[0][2] * m[1][3] + - m[0][0] * m[3][2] * m[1][3] + - m[1][0] * m[0][2] * m[3][3] + - m[3][0] * m[1][2] * m[0][3]); + coft[2][2] = m[0][0] * m[1][1] * m[3][3] + + m[1][0] * m[3][1] * m[0][3] + + m[3][0] * m[0][1] * m[1][3] + - m[0][0] * m[3][1] * m[1][3] + - m[1][0] * m[0][1] * m[3][3] + - m[3][0] * m[1][1] * m[0][3]; + coft[3][2] = -(m[0][0] * m[1][1] * m[3][2] + + m[1][0] * m[3][1] * m[0][2] + + m[3][0] * m[0][1] * m[1][2] + - m[0][0] * m[3][1] * m[1][2] + - m[1][0] * m[0][1] * m[3][2] + - m[3][0] * m[1][1] * m[0][2]); + coft[0][3] = -(m[0][1] * m[1][2] * m[2][3] + + m[1][1] * m[2][2] * m[0][3] + + m[2][1] * m[0][2] * m[1][3] + - m[0][1] * m[2][2] * m[1][3] + - m[1][1] * m[0][2] * m[2][3] + - m[2][1] * m[1][2] * m[0][3]); + coft[1][3] = m[0][0] * m[1][2] * m[2][3] + + m[1][0] * m[2][2] * m[0][3] + + m[2][0] * m[0][2] * m[1][3] + - m[0][0] * m[2][2] * m[1][3] + - m[1][0] * m[0][2] * m[2][3] + - m[2][0] * m[1][2] * m[0][3]; + coft[2][3] = -(m[0][0] * m[1][1] * m[2][3] + + m[1][0] * m[2][1] * m[0][3] + + m[2][0] * m[0][1] * m[1][3] + - m[0][0] * m[2][1] * m[1][3] + - m[1][0] * m[0][1] * m[2][3] + - m[2][0] * m[1][1] * m[0][3]); + coft[3][3] = m[0][0] * m[1][1] * m[2][2] + + m[1][0] * m[2][1] * m[0][2] + + m[2][0] * m[0][1] * m[1][2] + - m[0][0] * m[2][1] * m[1][2] + - m[1][0] * m[0][1] * m[2][2] + - m[2][0] * m[1][1] * m[0][2]; + TYPE_ID_VEC4 + } + _ => panic!("Internal error: Invalid matrix dimensions when calculating inverse"), + }; + + let columns = (0..size) + .map(|column_index| { + let column = (0..size) + .map(|row_index| { + ir_meta.get_constant_float( + coft[column_index][row_index] * determinant_reciprocal, + ) + }) + .collect(); + ir_meta.get_constant_composite(vec_type_id, column) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, columns) + } + fn float_isx_helper( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + ) -> ConstantId + where + FloatOp: Fn(f32) -> bool + Copy, + { + let constant = ir_meta.get_constant(constant_id); + let type_id = constant.type_id; + let element_type_id = ir_meta.get_type(type_id).get_element_type_id().unwrap_or(type_id); + + match &constant.value { + &ConstantValue::Float(f) => ir_meta.get_constant_bool(float_op(f)), + ConstantValue::Int(_) + | ConstantValue::Uint(_) + | ConstantValue::Bool(_) + | ConstantValue::YuvCsc(_) => { + panic!("Internal error: is not allowed on constants other than float") + } + ConstantValue::Composite(components) => { + let mapped = components + .clone() + .iter() + .map(|&component_id| { + float_isx_helper(ir_meta, component_id, element_type_id, float_op) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, mapped) + } + } + } + fn built_in_isnan( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + float_isx_helper(ir_meta, constant_id, result_type_id, |f| f.is_nan()) + } + fn built_in_isinf( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + float_isx_helper(ir_meta, constant_id, result_type_id, |f| f.is_infinite()) + } + fn pack2x16_helper( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + pack: Pack, + ) -> ConstantId + where + Pack: Fn(f32) -> u16 + Copy, + { + debug_assert!(result_type_id == TYPE_ID_UINT); + + // Expect a vec2, produce a uint. First float is written to the least significant bits. + let fs = ir_meta.get_constant(constant_id).value.get_composite_elements(); + let f1 = ir_meta.get_constant(fs[0]).value.get_float(); + let f2 = ir_meta.get_constant(fs[1]).value.get_float(); + + let result = pack(f1) as u32 | (pack(f2) as u32) << 16; + ir_meta.get_constant_uint(result) + } + fn unpack2x16_helper( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + unpack: Unpack, + ) -> ConstantId + where + Unpack: Fn(u16) -> f32 + Copy, + { + debug_assert!(result_type_id == TYPE_ID_VEC2); + + // Expect a uint, produce a vec2. First float is taken from the least significant bits. + let packed = ir_meta.get_constant(constant_id).value.get_uint(); + let f1 = unpack((packed & 0xFFFF) as u16); + let f2 = unpack((packed >> 16) as u16); + + let unpacked = vec![ir_meta.get_constant_float(f1), ir_meta.get_constant_float(f2)]; + ir_meta.get_constant_composite(result_type_id, unpacked) + } + fn pack4x8_helper( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + pack: Pack, + ) -> ConstantId + where + Pack: Fn(f32) -> u8 + Copy, + { + debug_assert!(result_type_id == TYPE_ID_UINT); + + // Expect a vec4, produce a uint. First float is written to the least significant bits. + let fs = ir_meta.get_constant(constant_id).value.get_composite_elements(); + let f1 = ir_meta.get_constant(fs[0]).value.get_float(); + let f2 = ir_meta.get_constant(fs[1]).value.get_float(); + let f3 = ir_meta.get_constant(fs[2]).value.get_float(); + let f4 = ir_meta.get_constant(fs[3]).value.get_float(); + + let result = pack(f1) as u32 + | (pack(f2) as u32) << 8 + | (pack(f3) as u32) << 16 + | (pack(f4) as u32) << 24; + ir_meta.get_constant_uint(result) + } + fn unpack4x8_helper( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + unpack: Unpack, + ) -> ConstantId + where + Unpack: Fn(u8) -> f32 + Copy, + { + debug_assert!(result_type_id == TYPE_ID_VEC4); + + // Expect a uint, produce a vec4. First float is taken from the least significant bits. + let packed = ir_meta.get_constant(constant_id).value.get_uint(); + let f1 = unpack((packed & 0xFF) as u8); + let f2 = unpack((packed >> 8 & 0xFF) as u8); + let f3 = unpack((packed >> 16 & 0xFF) as u8); + let f4 = unpack((packed >> 24 & 0xFF) as u8); + + let unpacked = vec![ + ir_meta.get_constant_float(f1), + ir_meta.get_constant_float(f2), + ir_meta.get_constant_float(f3), + ir_meta.get_constant_float(f4), + ]; + ir_meta.get_constant_composite(result_type_id, unpacked) + } + fn f32_to_snorm16(v: f32) -> i16 { + (v.clamp(-1., 1.) * 32767.).round() as i16 + } + fn built_in_packsnorm2x16( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + pack2x16_helper(ir_meta, constant_id, result_type_id, |f| f32_to_snorm16(f) as u16) + } + fn snorm16_to_f32(v: i16) -> f32 { + (v as f32 / 32767.).clamp(-1., 1.) + } + fn built_in_unpacksnorm2x16( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + unpack2x16_helper(ir_meta, constant_id, result_type_id, |u| snorm16_to_f32(u as i16)) + } + fn f32_to_unorm16(v: f32) -> u16 { + (v.clamp(0., 1.) * 65535.).round() as u16 + } + fn built_in_packunorm2x16( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + pack2x16_helper(ir_meta, constant_id, result_type_id, f32_to_unorm16) + } + fn unorm16_to_f32(v: u16) -> f32 { + v as f32 / 65535. + } + fn built_in_unpackunorm2x16( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + unpack2x16_helper(ir_meta, constant_id, result_type_id, unorm16_to_f32) + } + fn f32_to_f16(v: f32) -> u16 { + let v = v.to_bits(); + let sign = (v & 0x80000000) >> 16; + let abs = v & 0x7FFFFFFF; + + if abs > 0x7F800000 { + // NaN + 0x7FFF + } else if abs > 0x47FFEFFF { + // Infinity + (sign | 0x7C00) as u16 + } else if abs < 0x38800000 { + // Denormal + let mantissa = (abs & 0x007FFFFF) | 0x00800000; + let e = 113 - (abs >> 23); + + let abs = if e < 24 { mantissa >> e } else { 0 }; + + (sign | (abs + 0x00000FFF + (abs >> 13 & 1)) >> 13) as u16 + } else { + (sign | (abs + 0xC8000000 + 0x00000FFF + (abs >> 13 & 1)) >> 13) as u16 + } + } + fn built_in_packhalf2x16( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + pack2x16_helper(ir_meta, constant_id, result_type_id, f32_to_f16) + } + fn f16_to_f32(v: u16) -> f32 { + // Based on http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + // See also Float16ToFloat32.py, this is non-baked copy of that generator. + let offset = v >> 10; + let offset = if offset == 0 || offset == 32 { 0 } else { 1024 }; + let offset = offset + (v & 0x3FF); + + let mantissa = if offset == 0 { + 0 + } else if offset < 1024 { + let mut m = (offset as u32) << 13; + let mut e = 0x38800000; + while (m & 0x00800000) == 0 { + e -= 0x00800000; + m <<= 1; + } + m &= !0x00800000; + m | e + } else { + 0x38000000 + ((offset as u32 - 1024) << 13) + }; + + let exponent = v >> 10; + let exponent = if exponent == 0 { + 0 + } else if exponent < 31 { + (exponent as u32) << 23 + } else if exponent == 31 { + 0x47800000 + } else if exponent == 32 { + 0x80000000 + } else if exponent < 63 { + 0x80000000 + ((exponent as u32 - 32) << 23) + } else { + 0xC7800000 + }; + + f32::from_bits(mantissa + exponent) + } + fn built_in_unpackhalf2x16( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + unpack2x16_helper(ir_meta, constant_id, result_type_id, f16_to_f32) + } + fn f32_to_snorm8(v: f32) -> i8 { + (v.clamp(-1., 1.) * 127.).round() as i8 + } + fn built_in_packsnorm4x8( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + pack4x8_helper(ir_meta, constant_id, result_type_id, |f| f32_to_snorm8(f) as u8) + } + fn snorm8_to_f32(v: i8) -> f32 { + (v as f32 / 127.).clamp(-1., 1.) + } + fn built_in_unpacksnorm4x8( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + unpack4x8_helper(ir_meta, constant_id, result_type_id, |u| snorm8_to_f32(u as i8)) + } + fn f32_to_unorm8(v: f32) -> u8 { + (v.clamp(0., 1.) * 255.).round() as u8 + } + fn built_in_packunorm4x8( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + pack4x8_helper(ir_meta, constant_id, result_type_id, f32_to_unorm8) + } + fn unorm8_to_f32(v: u8) -> f32 { + v as f32 / 255. + } + fn built_in_unpackunorm4x8( + ir_meta: &mut IRMeta, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + unpack4x8_helper(ir_meta, constant_id, result_type_id, unorm8_to_f32) + } + pub fn built_in_unary( + ir_meta: &mut IRMeta, + op: UnaryOpCode, + constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let float_op = match op { + UnaryOpCode::Radians => |f: f32| f.to_radians(), + UnaryOpCode::Degrees => |f: f32| f.to_degrees(), + UnaryOpCode::Sin => |f: f32| f.sin(), + UnaryOpCode::Cos => |f: f32| f.cos(), + UnaryOpCode::Tan => |f: f32| f.tan(), + // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0. + UnaryOpCode::Asin => |f: f32| if f.abs() > 1. { 0. } else { f.asin() }, + // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0. + UnaryOpCode::Acos => |f: f32| if f.abs() > 1. { 0. } else { f.acos() }, + UnaryOpCode::Atan => |f: f32| f.atan(), + UnaryOpCode::Sinh => |f: f32| f.sinh(), + UnaryOpCode::Cosh => |f: f32| f.cosh(), + UnaryOpCode::Tanh => |f: f32| f.tanh(), + UnaryOpCode::Asinh => |f: f32| f.asinh(), + // For acosh(x), results are undefined if |x| < 1, we are choosing to set result to 0. + UnaryOpCode::Acosh => |f: f32| if f.abs() < 1. { 0. } else { f.acosh() }, + // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0. + UnaryOpCode::Atanh => |f: f32| if f.abs() >= 1. { 0. } else { f.atanh() }, + UnaryOpCode::Exp => |f: f32| f.exp(), + // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. + UnaryOpCode::Log => |f: f32| if f <= 0. { 0. } else { f.ln() }, + UnaryOpCode::Exp2 => |f: f32| f.exp2(), + // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. + UnaryOpCode::Log2 => |f: f32| f.log2(), + // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. + UnaryOpCode::Sqrt => |f: f32| if f < 0. { 0. } else { f.sqrt() }, + // For inversesqrt(x), results are undefined if x <= 0, we are choosing to set result + // to 0. + UnaryOpCode::Inversesqrt => |f: f32| if f <= 0. { 0. } else { f.sqrt().recip() }, + UnaryOpCode::Abs => |f: f32| f.abs(), + UnaryOpCode::Sign => |f: f32| { + if f > 0. { + 1. + } else if f < 0. { + -1. + } else { + 0. + } + }, + UnaryOpCode::Floor => |f: f32| f.floor(), + UnaryOpCode::Trunc => |f: f32| f.trunc(), + UnaryOpCode::Round => |f: f32| f.round(), + UnaryOpCode::RoundEven => |f: f32| f.round_ties_even(), + UnaryOpCode::Ceil => |f: f32| f.ceil(), + UnaryOpCode::Fract => |f: f32| f.fract(), + UnaryOpCode::Isnan => { + return built_in_isnan(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Isinf => { + return built_in_isinf(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::FloatBitsToInt => { + return built_in_floatbitstoint(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::FloatBitsToUint => { + return built_in_floatbitstouint(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::IntBitsToFloat => { + return built_in_intbitstofloat(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::UintBitsToFloat => { + return built_in_uintbitstofloat(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::PackSnorm2x16 => { + return built_in_packsnorm2x16(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::PackHalf2x16 => { + return built_in_packhalf2x16(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::UnpackSnorm2x16 => { + return built_in_unpacksnorm2x16(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::UnpackHalf2x16 => { + return built_in_unpackhalf2x16(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::PackUnorm2x16 => { + return built_in_packunorm2x16(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::UnpackUnorm2x16 => { + return built_in_unpackunorm2x16(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::PackUnorm4x8 => { + return built_in_packunorm4x8(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::PackSnorm4x8 => { + return built_in_packsnorm4x8(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::UnpackUnorm4x8 => { + return built_in_unpackunorm4x8(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::UnpackSnorm4x8 => { + return built_in_unpacksnorm4x8(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Length => { + return built_in_length(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Normalize => { + return built_in_normalize(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Transpose => { + return built_in_transpose(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Determinant => { + return built_in_determinant(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Inverse => { + return built_in_inverse(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::Any => { + return built_in_any(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::All => { + return built_in_all(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::BitCount => { + return built_in_bitcount(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::FindLSB => { + return built_in_findlsb(ir_meta, constant_id, result_type_id); + } + UnaryOpCode::FindMSB => { + return built_in_findmsb(ir_meta, constant_id, result_type_id); + } + // For dFdx, dFdy and fwidth, note that derivates of constants is 0 + UnaryOpCode::DFdx => |_f: f32| 0., + UnaryOpCode::DFdy => |_f: f32| 0., + UnaryOpCode::Fwidth => |_f: f32| 0., + UnaryOpCode::InterpolateAtCentroid => return constant_id, + UnaryOpCode::AtomicCounter + | UnaryOpCode::AtomicCounterIncrement + | UnaryOpCode::AtomicCounterDecrement + | UnaryOpCode::ImageSize + | UnaryOpCode::PixelLocalLoadANGLE => { + panic!("Internal error: Unexpected built-ins to constant-fold") + } + _ => |_| panic!("Internal error: Invalid built-in operation on float"), + }; + + let int_op = match op { + UnaryOpCode::Abs => |i: i32| i.abs(), + UnaryOpCode::Sign => |i: i32| { + if i > 0 { + 1 + } else if i < 0 { + -1 + } else { + 0 + } + }, + UnaryOpCode::BitfieldReverse => |i: i32| i.reverse_bits(), + _ => |_| panic!("Internal error: Invalid built-in operation on int"), + }; + + let uint_op = match op { + UnaryOpCode::BitfieldReverse => |u: u32| u.reverse_bits(), + _ => |_| panic!("Internal error: Invalid built-in operation on uint"), + }; + + let bool_op = match op { + UnaryOpCode::Not => |b: bool| !b, + _ => |_| panic!("Internal error: Invalid built-in operation on uint"), + }; + + apply_unary_componentwise( + ir_meta, + constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } + + fn built_in_distance( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + debug_assert!(result_type_id == TYPE_ID_FLOAT); + + let lhs = ir_meta.get_constant(lhs_constant_id); + let rhs = ir_meta.get_constant(rhs_constant_id); + + if !lhs.value.is_composite() { + return ir_meta + .get_constant_float((lhs.value.get_float() - rhs.value.get_float()).abs()); + } + + let lhs = lhs.value.get_composite_elements(); + let rhs = rhs.value.get_composite_elements(); + + let sum: f32 = lhs + .iter() + .zip(rhs.iter()) + .map(|(&lhs_component_id, &rhs_component_id)| { + let lhs_component = ir_meta.get_constant(lhs_component_id).value.get_float(); + let rhs_component = ir_meta.get_constant(rhs_component_id).value.get_float(); + let diff = rhs_component - lhs_component; + diff * diff + }) + .sum(); + ir_meta.get_constant_float(sum.sqrt()) + } + fn built_in_dot( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + debug_assert!(result_type_id == TYPE_ID_FLOAT); + ir_meta.get_constant_float(dot(ir_meta, lhs_constant_id, rhs_constant_id)) + } + fn built_in_cross( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + debug_assert!(result_type_id == TYPE_ID_VEC3); + + let lhs = ir_meta.get_constant(lhs_constant_id).value.get_composite_elements(); + let rhs = ir_meta.get_constant(rhs_constant_id).value.get_composite_elements(); + + let x2 = ir_meta.get_constant(lhs[2]).value.get_float(); + let x1 = ir_meta.get_constant(lhs[1]).value.get_float(); + let x0 = ir_meta.get_constant(lhs[0]).value.get_float(); + let y2 = ir_meta.get_constant(rhs[2]).value.get_float(); + let y1 = ir_meta.get_constant(rhs[1]).value.get_float(); + let y0 = ir_meta.get_constant(rhs[0]).value.get_float(); + + let components = vec![ + ir_meta.get_constant_float(x1 * y2 - y1 * x2), + ir_meta.get_constant_float(x2 * y0 - y2 * x0), + ir_meta.get_constant_float(x0 * y1 - y0 * x1), + ]; + ir_meta.get_constant_composite(result_type_id, components) + } + fn built_in_reflect( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + // For the incident vector I and surface orientation N, returns the reflection + // direction: + // I - 2 * dot(N, I) * N. + let n_dot_i = dot(ir_meta, rhs_constant_id, lhs_constant_id); + + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |i, n| i - 2. * n_dot_i * n, + |_, _| panic!("Internal error: The reflect() built-in only applies to float types"), + |_, _| panic!("Internal error: The reflect() built-in only applies to float types"), + |_, _| panic!("Internal error: The reflect() built-in only applies to float types"), + ) + } + fn built_in_outerproduct( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let lhs_type_id = ir_meta.get_constant(lhs_constant_id).type_id; + let rhs = ir_meta.get_constant(rhs_constant_id).value.get_composite_elements().clone(); + let column_count = rhs.len(); + + let columns = (0..column_count) + .map(|column| mul(ir_meta, lhs_constant_id, rhs[column], lhs_type_id)) + .collect(); + ir_meta.get_constant_composite(result_type_id, columns) + } + fn compare_helper( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + float_op: FloatOp, + int_op: IntOp, + uint_op: UintOp, + bool_op: BoolOp, + ) -> ConstantId + where + FloatOp: Fn(f32, f32) -> bool + Copy, + IntOp: Fn(i32, i32) -> bool + Copy, + UintOp: Fn(u32, u32) -> bool + Copy, + BoolOp: Fn(bool, bool) -> bool + Copy, + { + let lhs_constant = ir_meta.get_constant(lhs_constant_id); + let rhs_constant = ir_meta.get_constant(rhs_constant_id); + + if let ( + ConstantValue::Composite(lhs_components), + ConstantValue::Composite(rhs_components), + ) = (&lhs_constant.value, &rhs_constant.value) + { + let mapped = lhs_components + .clone() + .iter() + .zip(rhs_components.clone().iter()) + .map(|(&lhs_component_id, &rhs_component_id)| { + let lhs = ir_meta.get_constant(lhs_component_id).value.clone(); + let rhs = ir_meta.get_constant(rhs_component_id).value.clone(); + + match lhs { + ConstantValue::Float(lhs) => ir_meta.get_constant_bool(float_op(lhs, rhs.get_float())), + ConstantValue::Int(lhs) => ir_meta.get_constant_bool(int_op(lhs, rhs.get_int())), + ConstantValue::Uint(lhs) => ir_meta.get_constant_bool(uint_op(lhs, rhs.get_uint())), + ConstantValue::Bool(lhs) => ir_meta.get_constant_bool(bool_op(lhs, rhs.get_bool())), + _ => { panic!("Internal error: Comparison built-ins only valid on float, [u]int and bool values"); } + } + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, mapped) + } else { + panic!("Internal error: Comparison built-ins only valid on vector types"); + } + } + fn built_in_lessthan( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + compare_helper( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 < f2, + |i1, i2| i1 < i2, + |u1, u2| u1 < u2, + |_, _| panic!("Internal error: lessThan() does not accept bool vectors"), + ) + } + fn built_in_lessthanequal( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + compare_helper( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 <= f2, + |i1, i2| i1 <= i2, + |u1, u2| u1 <= u2, + |_, _| panic!("Internal error: lessThanEqual() does not accept bool vectors"), + ) + } + fn built_in_greaterthan( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + compare_helper( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 > f2, + |i1, i2| i1 > i2, + |u1, u2| u1 > u2, + |_, _| panic!("Internal error: greaterThan() does not accept bool vectors"), + ) + } + fn built_in_greaterthanequal( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + compare_helper( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 >= f2, + |i1, i2| i1 >= i2, + |u1, u2| u1 >= u2, + |_, _| panic!("Internal error: greaterThanEqual() does not accept bool vectors"), + ) + } + fn built_in_equal( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + compare_helper( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 == f2, + |i1, i2| i1 == i2, + |u1, u2| u1 == u2, + |b1, b2| b1 == b2, + ) + } + fn built_in_notequal( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + compare_helper( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + |f1, f2| f1 != f2, + |i1, i2| i1 != i2, + |u1, u2| u1 != u2, + |b1, b2| b1 != b2, + ) + } + fn ldexp_helper(ir_meta: &mut IRMeta, x: f32, exp: i32) -> ConstantId { + let result = if (-126..=128).contains(&exp) { x * 2.0_f32.powi(exp) } else { 0.0 }; + ir_meta.get_constant_float(result) + } + fn built_in_ldexp( + ir_meta: &mut IRMeta, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + let lhs_constant = ir_meta.get_constant(lhs_constant_id); + let rhs_constant = ir_meta.get_constant(rhs_constant_id); + + if let ( + ConstantValue::Composite(lhs_components), + ConstantValue::Composite(rhs_components), + ) = (&lhs_constant.value, &rhs_constant.value) + { + let mapped = lhs_components + .clone() + .iter() + .zip(rhs_components.clone().iter()) + .map(|(&lhs_component_id, &rhs_component_id)| { + let lhs = ir_meta.get_constant(lhs_component_id).value.clone(); + let rhs = ir_meta.get_constant(rhs_component_id).value.clone(); + ldexp_helper(ir_meta, lhs.get_float(), rhs.get_int()) + }) + .collect(); + ir_meta.get_constant_composite(result_type_id, mapped) + } else { + ldexp_helper(ir_meta, lhs_constant.value.get_float(), rhs_constant.value.get_int()) + } + } + pub fn built_in_binary( + ir_meta: &mut IRMeta, + op: BinaryOpCode, + lhs_constant_id: ConstantId, + rhs_constant_id: ConstantId, + result_type_id: TypeId, + ) -> ConstantId { + if op == BinaryOpCode::Ldexp { + return built_in_ldexp(ir_meta, lhs_constant_id, rhs_constant_id, result_type_id); + } + + let float_op = match op { + BinaryOpCode::Atan => |y: f32, x: f32| y.atan2(x), + // For pow(x, y), results are undefined if x < 0 or if x = 0 and y <= 0. + BinaryOpCode::Pow => { + |x: f32, y: f32| if x < 0. || (x == 0. && y <= 0.) { 0. } else { x.powf(y) } + } + BinaryOpCode::Mod => |f1: f32, f2: f32| f1 - f2 * (f1 / f2).floor(), + BinaryOpCode::Min => |f1: f32, f2: f32| f1.min(f2), + BinaryOpCode::Max => |f1: f32, f2: f32| f1.max(f2), + BinaryOpCode::Step => |edge: f32, x: f32| if x < edge { 0. } else { 1. }, + BinaryOpCode::Distance => { + return built_in_distance( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::Dot => { + return built_in_dot(ir_meta, lhs_constant_id, rhs_constant_id, result_type_id); + } + BinaryOpCode::Cross => { + return built_in_cross(ir_meta, lhs_constant_id, rhs_constant_id, result_type_id); + } + BinaryOpCode::Reflect => { + return built_in_reflect(ir_meta, lhs_constant_id, rhs_constant_id, result_type_id); + } + BinaryOpCode::MatrixCompMult => |f1: f32, f2: f32| f1 * f2, + BinaryOpCode::OuterProduct => { + return built_in_outerproduct( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::LessThanVec => { + return built_in_lessthan( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::LessThanEqualVec => { + return built_in_lessthanequal( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::GreaterThanVec => { + return built_in_greaterthan( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::GreaterThanEqualVec => { + return built_in_greaterthanequal( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::EqualVec => { + return built_in_equal(ir_meta, lhs_constant_id, rhs_constant_id, result_type_id); + } + BinaryOpCode::NotEqualVec => { + return built_in_notequal( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + ); + } + BinaryOpCode::InterpolateAtSample | BinaryOpCode::InterpolateAtOffset => { + return lhs_constant_id; + } + BinaryOpCode::Modf + | BinaryOpCode::Frexp + | BinaryOpCode::Ldexp + | BinaryOpCode::AtomicAdd + | BinaryOpCode::AtomicMin + | BinaryOpCode::AtomicMax + | BinaryOpCode::AtomicAnd + | BinaryOpCode::AtomicOr + | BinaryOpCode::AtomicXor + | BinaryOpCode::AtomicExchange => { + panic!("Internal error: Unexpected built-ins to constant-fold") + } + _ => panic!("Internal error: Invalid built-in operation on float"), + }; + + let int_op = match op { + BinaryOpCode::Min => |i1: i32, i2: i32| i1.min(i2), + BinaryOpCode::Max => |i1: i32, i2: i32| i1.max(i2), + _ => |_, _| panic!("Internal error: Invalid built-in operation on int"), + }; + + let uint_op = match op { + BinaryOpCode::Min => |u1: u32, u2: u32| u1.min(u2), + BinaryOpCode::Max => |u1: u32, u2: u32| u1.max(u2), + _ => |_, _| panic!("Internal error: Invalid built-in operation on uint"), + }; + + let bool_op = |_, _| panic!("Internal error: Invalid built-in operation on uint"); + + apply_binary_componentwise( + ir_meta, + lhs_constant_id, + rhs_constant_id, + result_type_id, + float_op, + int_op, + uint_op, + bool_op, + ) + } + + fn built_in_clamp_with_scalar_limits( + ir_meta: &mut IRMeta, + x_constant_id: ConstantId, + min_constant: &ConstantValue, + max_constant: &ConstantValue, + result_type_id: TypeId, + ) -> ConstantId { + apply_unary_componentwise( + ir_meta, + x_constant_id, + result_type_id, + |f| { + let min = min_constant.get_float(); + let max = max_constant.get_float(); + if min > max { 0. } else { f.clamp(min, max) } + }, + |i| { + let min = min_constant.get_int(); + let max = max_constant.get_int(); + if min > max { 0 } else { i.clamp(min, max) } + }, + |u| { + let min = min_constant.get_uint(); + let max = max_constant.get_uint(); + if min > max { 0 } else { u.clamp(min, max) } + }, + |_| panic!("Internal error: The clamp() built-in does not apply to bool types"), + ) + } + pub fn built_in_clamp( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // clamp(x, min, max) either accepts scalars for min, max or a vector of matching size with + // x. + let max_constant = ir_meta.get_constant(operands[2]); + let min_constant = ir_meta.get_constant(operands[1]); + let x_constant = ir_meta.get_constant(operands[0]); + + if let ( + ConstantValue::Composite(x_components), + ConstantValue::Composite(min_components), + ConstantValue::Composite(max_components), + ) = (&x_constant.value, &min_constant.value, &max_constant.value) + { + let result_element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap(); + + let components = x_components + .clone() + .iter() + .zip(min_components.clone().iter()) + .zip(max_components.clone().iter()) + .map(|((&x_component_id, &min_component_id), &max_component_id)| { + let min = ir_meta.get_constant(min_component_id).value.clone(); + let max = ir_meta.get_constant(max_component_id).value.clone(); + + built_in_clamp_with_scalar_limits( + ir_meta, + x_component_id, + &min, + &max, + result_element_type_id, + ) + }) + .collect(); + + ir_meta.get_constant_composite(result_type_id, components) + } else { + built_in_clamp_with_scalar_limits( + ir_meta, + operands[0], + &min_constant.value.clone(), + &max_constant.value.clone(), + result_type_id, + ) + } + } + + fn built_in_mix_with_scalar_factor( + ir_meta: &mut IRMeta, + x_constant_id: ConstantId, + y_constant_id: ConstantId, + a_constant: &ConstantValue, + result_type_id: TypeId, + ) -> ConstantId { + if let &ConstantValue::Bool(a) = a_constant { + if a { y_constant_id } else { x_constant_id } + } else { + apply_binary_componentwise( + ir_meta, + x_constant_id, + y_constant_id, + result_type_id, + |f1, f2| { + let a = a_constant.get_float(); + f1 * (1. - a) + f2 * a + }, + |_, _| panic!("Internal error: The mix() built-in only applies to float types"), + |_, _| panic!("Internal error: The mix() built-in only applies to float types"), + |_, _| panic!("Internal error: The mix() built-in only applies to float types"), + ) + } + } + pub fn built_in_mix( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // mix(x, y, a) either accepts scalar for a, or a vector of matching size with x and y. + // The type of a could possibly be bool instead of float (but not if x and y are vectors + // and a is a scalar). + let a_constant = ir_meta.get_constant(operands[2]); + let y_constant = ir_meta.get_constant(operands[1]); + let x_constant = ir_meta.get_constant(operands[0]); + + if let ( + ConstantValue::Composite(x_components), + ConstantValue::Composite(y_components), + ConstantValue::Composite(a_components), + ) = (&x_constant.value, &y_constant.value, &a_constant.value) + { + let result_element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap(); + + let components = x_components + .clone() + .iter() + .zip(y_components.clone().iter()) + .zip(a_components.clone().iter()) + .map(|((&x_component_id, &y_component_id), &a_component_id)| { + let a = ir_meta.get_constant(a_component_id).value.clone(); + + built_in_mix_with_scalar_factor( + ir_meta, + x_component_id, + y_component_id, + &a, + result_element_type_id, + ) + }) + .collect(); + + ir_meta.get_constant_composite(result_type_id, components) + } else { + built_in_mix_with_scalar_factor( + ir_meta, + operands[0], + operands[1], + &a_constant.value.clone(), + result_type_id, + ) + } + } + fn built_in_smoothstep_with_scalar_edges( + ir_meta: &mut IRMeta, + x_constant_id: ConstantId, + edge0_constant: &ConstantValue, + edge1_constant: &ConstantValue, + result_type_id: TypeId, + ) -> ConstantId { + let edge0 = edge0_constant.get_float(); + let edge1 = edge1_constant.get_float(); + + apply_unary_componentwise( + ir_meta, + x_constant_id, + result_type_id, + |f| { + if edge0 >= edge1 { + 0. + } else { + // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth + // Hermite interpolation between 0 and 1 when edge0 < x < edge1. + let t = ((f - edge0) / (edge1 - edge0)).clamp(0., 1.); + t * t * (3. - 2. * t) + } + }, + |_| panic!("Internal error: The smoothstep() built-in only applies to float types"), + |_| panic!("Internal error: The smoothstep() built-in only applies to float types"), + |_| panic!("Internal error: The smoothstep() built-in only applies to float types"), + ) + } + pub fn built_in_smoothstep( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // smoothstep(edge0, edge1, x) either accepts scalar for edge0 and edge1, or a vector of + // matching size with x. + let x_constant = ir_meta.get_constant(operands[2]); + let edge1_constant = ir_meta.get_constant(operands[1]); + let edge0_constant = ir_meta.get_constant(operands[0]); + + if let ( + ConstantValue::Composite(edge0_components), + ConstantValue::Composite(edge1_components), + ConstantValue::Composite(x_components), + ) = (&edge0_constant.value, &edge1_constant.value, &x_constant.value) + { + let result_element_type_id = + ir_meta.get_type(result_type_id).get_element_type_id().unwrap(); + + let components = edge0_components + .clone() + .iter() + .zip(edge1_components.clone().iter()) + .zip(x_components.clone().iter()) + .map(|((&edge0_component_id, &edge1_component_id), &x_component_id)| { + let edge0 = ir_meta.get_constant(edge0_component_id).value.clone(); + let edge1 = ir_meta.get_constant(edge1_component_id).value.clone(); + + built_in_smoothstep_with_scalar_edges( + ir_meta, + x_component_id, + &edge0, + &edge1, + result_element_type_id, + ) + }) + .collect(); + + ir_meta.get_constant_composite(result_type_id, components) + } else { + built_in_smoothstep_with_scalar_edges( + ir_meta, + operands[2], + &edge0_constant.value.clone(), + &edge1_constant.value.clone(), + result_type_id, + ) + } + } + pub fn built_in_fma( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // fma(a, b, c) accepts scalar or vectors of float. + let c_constant = ir_meta.get_constant(operands[2]); + let b_constant = ir_meta.get_constant(operands[1]); + let a_constant = ir_meta.get_constant(operands[0]); + + if let ( + ConstantValue::Composite(a_components), + ConstantValue::Composite(b_components), + ConstantValue::Composite(c_components), + ) = (&a_constant.value, &b_constant.value, &c_constant.value) + { + let components = a_components + .clone() + .iter() + .zip(b_components.clone().iter()) + .zip(c_components.clone().iter()) + .map(|((&a_component_id, &b_component_id), &c_component_id)| { + let a = ir_meta.get_constant(a_component_id).value.get_float(); + let b = ir_meta.get_constant(b_component_id).value.get_float(); + let c = ir_meta.get_constant(c_component_id).value.get_float(); + + ir_meta.get_constant_float(a * b + c) + }) + .collect(); + + ir_meta.get_constant_composite(result_type_id, components) + } else { + let a = a_constant.value.get_float(); + let b = b_constant.value.get_float(); + let c = c_constant.value.get_float(); + + ir_meta.get_constant_float(a * b + c) + } + } + pub fn built_in_faceforward( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // faceforward(N, I, Nref) accepts scalar or vectors of float. + let nref_constant_id = operands[2]; + let i_constant_id = operands[1]; + let n_constant_id = operands[0]; + + // If dot(Nref, I) < 0 return N, otherwise return -N. + let nref_dot_i = dot(ir_meta, nref_constant_id, i_constant_id); + if nref_dot_i < 0. { n_constant_id } else { negate(ir_meta, n_constant_id, result_type_id) } + } + pub fn built_in_refract( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // refract(I, N, eta) accepts matching scalars or vectors of float for I and N, and float + // for eta. + let eta = ir_meta.get_constant(operands[2]).value.get_float(); + let n_constant_id = operands[1]; + let i_constant_id = operands[0]; + + // For the incident vector I and surface normal N, and the ratio of indices of + // refraction eta, return the refraction vector, R. + // + // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) + // if (k < 0.0) + // return genType(0.0) + // else + // return eta * I - (eta * dot(N, I) + sqrt(k)) * N + let n_dot_i = dot(ir_meta, n_constant_id, i_constant_id); + let k = 1. - eta * eta * (1. - n_dot_i * n_dot_i); + let sqrt_k = k.sqrt(); + apply_binary_componentwise( + ir_meta, + i_constant_id, + n_constant_id, + result_type_id, + |i, n| { + if k < 0. { 0. } else { eta * i - (eta * n_dot_i + sqrt_k) * n } + }, + |_, _| panic!("Internal error: The refract() built-in only applies to float types"), + |_, _| panic!("Internal error: The refract() built-in only applies to float types"), + |_, _| panic!("Internal error: The refract() built-in only applies to float types"), + ) + } + fn built_in_bitfieldextract_unsigned_scalar(value: u32, offset: i32, bits: i32) -> u32 { + // If bits is zero, the result will be zero. The result will be undefined if offset or bits + // is negative, or if the sum of offset and bits is greater than the number of bits used to + // store the operand. + if offset < 0 || bits <= 0 || offset + bits > 32 { + 0 + } else { + let value = value >> offset; + let mask = if bits == 32 { u32::MAX } else { (1 << bits) - 1 }; + value & mask + } + } + fn built_in_bitfieldextract_signed_scalar(value: i32, offset: i32, bits: i32) -> i32 { + // For unsigned data types, the most significant bits of the result will be set to zero. + // For signed data types, the most significant bits will be set to the value of bit offset + // + base - 1 (i.e., it is sign extended to the width of the return type). + let unsigned = built_in_bitfieldextract_unsigned_scalar(value as u32, offset, bits); + let sign_extended = if bits >= 32 || bits <= 0 { + unsigned + } else { + let sign_bit_set = (unsigned >> (bits - 1)) & 1 != 0; + if sign_bit_set { unsigned | ((1 << (32 - bits)) - 1) << bits } else { unsigned } + }; + sign_extended as i32 + } + pub fn built_in_bitfieldextract( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // bitfieldExtract(value, offset, bits) accepts a scalar or vector integer for value, and a + // scalar signed integer for offset and bits. + let bits = ir_meta.get_constant(operands[2]).value.get_int(); + let offset = ir_meta.get_constant(operands[1]).value.get_int(); + let value_constant_id = operands[0]; + + apply_unary_componentwise( + ir_meta, + value_constant_id, + result_type_id, + |_| { + panic!( + "Internal error: The bitfieldExtract() built-in only applies to [u]int types" + ) + }, + |i| built_in_bitfieldextract_signed_scalar(i, offset, bits), + |u| built_in_bitfieldextract_unsigned_scalar(u, offset, bits), + |_| { + panic!( + "Internal error: The bitfieldExtract() built-in only applies to [u]int types" + ) + }, + ) + } + fn built_in_bitfieldinsert_unsigned_scalar( + base: u32, + insert: u32, + offset: i32, + bits: i32, + ) -> u32 { + // If bits is zero, the result will simply be the original value of base. The result will + // be undefined if offset or bits is negative, or if the sum of offset and bits is greater + // than the number of bits used to store the operand. + if bits == 0 { + base + } else if offset < 0 || bits < 0 || offset + bits > 32 { + 0 + } else if bits == 32 { + // Per the above check, offset must be 0 + insert + } else { + // The result will have bits [offset, offset + bits - 1] taken from bits [0, bits - 1] + // of insert, and all other bits taken directly from the corresponding bits of base. + let mask = (1 << bits) - 1; + base & !(mask << offset) | (insert & mask) << offset + } + } + pub fn built_in_bitfieldinsert( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + // bitfieldInsert(base, insert, offset, bits) accepts matching integer scalars or vectors + // for base and insert, and a scalar signed integer for offset and bits. + let bits = ir_meta.get_constant(operands[3]).value.get_int(); + let offset = ir_meta.get_constant(operands[2]).value.get_int(); + let insert_constant_id = operands[1]; + let base_constant_id = operands[0]; + + apply_binary_componentwise( + ir_meta, + base_constant_id, + insert_constant_id, + result_type_id, + |_, _| { + panic!("Internal error: The bitfieldInsert() built-in only applies to [u]int types") + }, + |base, insert| { + built_in_bitfieldinsert_unsigned_scalar(base as u32, insert as u32, offset, bits) + as i32 + }, + |base, insert| built_in_bitfieldinsert_unsigned_scalar(base, insert, offset, bits), + |_, _| { + panic!("Internal error: The bitfieldInsert() built-in only applies to [u]int types") + }, + ) + } + fn built_in_rgb_yuv_transform(r: f32, g: f32, b: f32, m: &[f32; 12]) -> [f32; 3] { + [ + r * m[0] + g * m[3] + b * m[6] + m[9], + r * m[1] + g * m[4] + b * m[7] + m[10], + r * m[2] + g * m[5] + b * m[8] + m[11], + ] + } + pub fn built_in_rgb_yuv_helper( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + itu601: &[f32; 12], + itu601_full_range: &[f32; 12], + itu709: &[f32; 12], + result_type_id: TypeId, + ) -> ConstantId { + // rgb_2_yuv(color, conv_standard) takes a vec3 for color and yuvCscStandardEXT for + // conv_standard. It uses a mat4x3 per the given standard that is multiplied by vec4(color, + // 1). yuv_2_rgb(color, conv_standard) operates similarly, using the inverse matrix. + let standard = ir_meta.get_constant(operands[1]).value.get_yuv_csc(); + let color = ir_meta.get_constant(operands[0]).value.get_composite_elements(); + + let b = ir_meta.get_constant(color[2]).value.get_float(); + let g = ir_meta.get_constant(color[1]).value.get_float(); + let r = ir_meta.get_constant(color[0]).value.get_float(); + + // See details where these constants come from in EmulateYUVBuiltIns.cpp. + // TODO(http://anglebug.com/349994211): update the above comment once that transformation + // is done in the IR. + let conversion_matrix = match standard { + YuvCscStandard::Itu601 => itu601, + YuvCscStandard::Itu601FullRange => itu601_full_range, + YuvCscStandard::Itu709 => itu709, + }; + + let components = built_in_rgb_yuv_transform(r, g, b, conversion_matrix) + .iter() + .map(|&f| ir_meta.get_constant_float(f)) + .collect(); + ir_meta.get_constant_composite(result_type_id, components) + } + pub fn built_in_rgb_2_yuv( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + let itu601 = [ + 0.256782, -0.148219, 0.439220, 0.504143, -0.291001, -0.367798, 0.097898, 0.439220, + -0.071422, 0.062745, 0.501961, 0.501961, + ]; + + let itu601_full_range = [ + 0.298993, -0.168732, 0.500005, 0.587016, -0.331273, -0.418699, 0.113991, 0.500005, + -0.081306, 0.000000, 0.501961, 0.501961, + ]; + + let itu709 = [ + 0.182580, -0.100641, 0.439219, 0.614243, -0.338579, -0.398950, 0.062000, 0.439219, + -0.040269, 0.062745, 0.501961, 0.501961, + ]; + + built_in_rgb_yuv_helper( + ir_meta, + operands, + &itu601, + &itu601_full_range, + &itu709, + result_type_id, + ) + } + pub fn built_in_yuv_2_rgb( + ir_meta: &mut IRMeta, + operands: &[ConstantId], + result_type_id: TypeId, + ) -> ConstantId { + let itu601 = [ + 1.164384, 1.164384, 1.164384, 0.0, -0.391721, 2.017232, 1.596027, -0.812926, 0.0, + -0.874202, 0.531626, -1.085631, + ]; + + let itu601_full_range = [ + 1.000000, 1.000000, 1.000000, 0.000000, -0.344100, 1.772, 1.402, -0.714100, 0.000000, + -0.703749, 0.531175, -0.889475, + ]; + + let itu709 = [ + 1.164384, 1.164384, 1.164384, 0.000000, -0.213221, 2.112402, 1.792741, -0.532882, + 0.000000, -0.972945, 0.301455, -1.133402, + ]; + + built_in_rgb_yuv_helper( + ir_meta, + operands, + &itu601, + &itu601_full_range, + &itu709, + result_type_id, + ) + } + pub fn built_in( + ir_meta: &mut IRMeta, + op: BuiltInOpCode, + operands: Vec, + result_type_id: TypeId, + ) -> ConstantId { + let fold = match op { + BuiltInOpCode::Clamp => built_in_clamp, + BuiltInOpCode::Mix => built_in_mix, + BuiltInOpCode::Smoothstep => built_in_smoothstep, + BuiltInOpCode::Fma => built_in_fma, + BuiltInOpCode::Faceforward => built_in_faceforward, + BuiltInOpCode::Refract => built_in_refract, + BuiltInOpCode::BitfieldExtract => built_in_bitfieldextract, + BuiltInOpCode::BitfieldInsert => built_in_bitfieldinsert, + BuiltInOpCode::Rgb2Yuv => built_in_rgb_2_yuv, + BuiltInOpCode::Yuv2Rgb => built_in_yuv_2_rgb, + BuiltInOpCode::UaddCarry + | BuiltInOpCode::UsubBorrow + | BuiltInOpCode::UmulExtended + | BuiltInOpCode::ImulExtended + | BuiltInOpCode::TextureSize + | BuiltInOpCode::TextureQueryLod + | BuiltInOpCode::TexelFetch + | BuiltInOpCode::TexelFetchOffset + | BuiltInOpCode::AtomicCompSwap + | BuiltInOpCode::ImageStore + | BuiltInOpCode::ImageLoad + | BuiltInOpCode::ImageAtomicAdd + | BuiltInOpCode::ImageAtomicMin + | BuiltInOpCode::ImageAtomicMax + | BuiltInOpCode::ImageAtomicAnd + | BuiltInOpCode::ImageAtomicOr + | BuiltInOpCode::ImageAtomicXor + | BuiltInOpCode::ImageAtomicExchange + | BuiltInOpCode::ImageAtomicCompSwap + | BuiltInOpCode::PixelLocalStoreANGLE + | BuiltInOpCode::MemoryBarrier + | BuiltInOpCode::MemoryBarrierAtomicCounter + | BuiltInOpCode::MemoryBarrierBuffer + | BuiltInOpCode::MemoryBarrierImage + | BuiltInOpCode::Barrier + | BuiltInOpCode::MemoryBarrierShared + | BuiltInOpCode::GroupMemoryBarrier + | BuiltInOpCode::EmitVertex + | BuiltInOpCode::EndPrimitive + | BuiltInOpCode::SubpassLoad + | BuiltInOpCode::BeginInvocationInterlockNV + | BuiltInOpCode::EndInvocationInterlockNV + | BuiltInOpCode::BeginFragmentShaderOrderingINTEL + | BuiltInOpCode::BeginInvocationInterlockARB + | BuiltInOpCode::EndInvocationInterlockARB + | BuiltInOpCode::NumSamples + | BuiltInOpCode::SamplePosition + | BuiltInOpCode::InterpolateAtCenter + | BuiltInOpCode::LoopForwardProgress + | BuiltInOpCode::Saturate => { + panic!("Internal error: Unexpected built-ins to constant-fold") + } + }; + + fold(ir_meta, &operands, result_type_id) + } +} + +// Helper functions that derive the result type of an operation. +mod promote { + use crate::ir::*; + + // A helper to get the type id of an element being indexed. The difference with + // `Type::get_element_type_id` is that if the type is a `Pointer`, the result is also a + // pointer. + // + // Additionally, to support swizzles, the element is optionally vectorized. + fn get_indexed_type_id( + ir_meta: &mut IRMeta, + type_id: TypeId, + vector_size: Option, + ) -> TypeId { + let type_info = ir_meta.get_type(type_id); + let is_pointer = type_info.is_pointer(); + let mut element_type_id = type_info.get_element_type_id().unwrap(); + + if is_pointer { + element_type_id = ir_meta.get_type(element_type_id).get_element_type_id().unwrap(); + } + + vector_size.inspect(|&size| { + element_type_id = ir_meta.get_vector_type_id_from_element_id(element_type_id, size) + }); + + if is_pointer { + element_type_id = ir_meta.get_pointer_type_id(element_type_id); + } + + element_type_id + } + // Used by some binary operations between scalars and vectors, returns the vector type. + fn promote_scalar_if_necessary(ir_meta: &mut IRMeta, type1: TypeId, type2: TypeId) -> TypeId { + if ir_meta.get_type(type1).is_scalar() { type2 } else { type1 } + } + // Used by increment/decrement operations which take a pointer by produce a register. + fn dereference(ir_meta: &IRMeta, pointer_type: TypeId) -> TypeId { + ir_meta.get_type(pointer_type).get_element_type_id().unwrap() + } + + // The type of `vector.x` derived from the type of `vector`, used for AccessVectorComponent and + // ExtractVectorComponent. + pub fn vector_component(ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + get_indexed_type_id(ir_meta, operand_type, None) + } + + // The type of `vector.xy` derived from the type of `vector`, used for + // AccessVectorComponentMulti and ExtractVectorComponentMulti. + pub fn vector_component_multi( + ir_meta: &mut IRMeta, + operand_type: TypeId, + vector_size: u32, + ) -> TypeId { + get_indexed_type_id(ir_meta, operand_type, Some(vector_size)) + } + + // The type of `a[i]` derived from the type of `a`, used for AccessVectorComponentDynamic, + // AccessMatrixColumn, AccessArrayElement, ExtractVectorComponentDynamic, ExtractMatrixColumn, + // and ExtractArrayElement. + pub fn index(ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + get_indexed_type_id(ir_meta, operand_type, None) + } + + // The type of `strct.field` derived from the type of `strct` and the selected field, used for + // AccessStructField and ExtractStructField, + pub fn struct_field(ir_meta: &mut IRMeta, type_id: TypeId, field: u32) -> TypeId { + let mut type_info = ir_meta.get_type(type_id); + let is_pointer = type_info.is_pointer(); + if is_pointer { + type_info = ir_meta.get_type(type_info.get_element_type_id().unwrap()); + } + + let mut field_type_id = type_info.get_struct_field(field).type_id; + + if is_pointer { + field_type_id = ir_meta.get_pointer_type_id(field_type_id); + } + + field_type_id + } + + // The result type of Negate and BitwiseNot is the same as their operand. + pub fn negate(_ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + operand_type + } + pub fn bitwise_not(_ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + operand_type + } + // The result type of post/prefix increment/decrement is the same as their operand, except it + // is dereferenced. + pub fn postfix_increment(ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + dereference(ir_meta, operand_type) + } + pub fn postfix_decrement(ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + dereference(ir_meta, operand_type) + } + pub fn prefix_increment(ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + dereference(ir_meta, operand_type) + } + pub fn prefix_decrement(ir_meta: &mut IRMeta, operand_type: TypeId) -> TypeId { + dereference(ir_meta, operand_type) + } + + // Add, Sub, Mul, Div, IMod, BitwiseOr, BitwiseAnd, and BitwiseXor implicitly promote a scalar + // operand to vector if they other operand is a vector. + pub fn add(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn sub(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn mul(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn div(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn imod(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn bitwise_or(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn bitwise_and(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + pub fn bitwise_xor(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + promote_scalar_if_necessary(ir_meta, lhs_type, rhs_type) + } + + // VectorTimesScalar and MatrixTimesScalar apply the scalar to each component, and the result + // is identical to the vector/matrix itself. + pub fn vector_times_scalar( + _ir_meta: &mut IRMeta, + lhs_type: TypeId, + _rhs_type: TypeId, + ) -> TypeId { + lhs_type + } + pub fn matrix_times_scalar( + _ir_meta: &mut IRMeta, + lhs_type: TypeId, + _rhs_type: TypeId, + ) -> TypeId { + lhs_type + } + + // For VectorTimesMatrix, the result type is a vector of the matrix's row count. + pub fn vector_times_matrix( + ir_meta: &mut IRMeta, + _lhs_type: TypeId, + rhs_type: TypeId, + ) -> TypeId { + let size = ir_meta.get_type(rhs_type).get_matrix_size().unwrap(); + ir_meta.get_vector_type_id(BasicType::Float, size) + } + // For MatrixTimesVector, the result type is a vector of the matrix's column count. + pub fn matrix_times_vector( + ir_meta: &mut IRMeta, + lhs_type: TypeId, + _rhs_type: TypeId, + ) -> TypeId { + ir_meta.get_type(lhs_type).get_element_type_id().unwrap() + } + // For MatrixTimesMatrix, the result type is a matrix with rhs's column count of lhs's column + // type. + pub fn matrix_times_matrix(ir_meta: &mut IRMeta, lhs_type: TypeId, rhs_type: TypeId) -> TypeId { + let result_column_type_id = ir_meta.get_type(lhs_type).get_element_type_id().unwrap(); + let result_row_count = ir_meta.get_type(result_column_type_id).get_vector_size().unwrap(); + let result_column_count = ir_meta.get_type(rhs_type).get_matrix_size().unwrap(); + ir_meta.get_matrix_type_id(result_column_count, result_row_count) + } + + // BitShiftLeft and BitShiftRight produce a result with the same type as the value being + // shifted. + pub fn bit_shift_left(_ir_meta: &mut IRMeta, lhs_type: TypeId, _rhs_type: TypeId) -> TypeId { + lhs_type + } + pub fn bit_shift_right(_ir_meta: &mut IRMeta, lhs_type: TypeId, _rhs_type: TypeId) -> TypeId { + lhs_type + } + + // Used to create a scalar or vector based on vector parameters + fn change_base_type( + ir_meta: &mut IRMeta, + original_type_id: TypeId, + new_basic_type: BasicType, + ) -> TypeId { + let vec_size = ir_meta.get_type(original_type_id).get_vector_size(); + match vec_size { + Some(n) => ir_meta.get_vector_type_id(new_basic_type, n), + None => ir_meta.get_basic_type_id(new_basic_type), + } + } + // Used to swap row and column size of a matrix + fn get_transposed_type(ir_meta: &mut IRMeta, mat_type_id: TypeId) -> TypeId { + let mat_type = ir_meta.get_type(mat_type_id); + let column_count = mat_type.get_matrix_size().unwrap(); + let column_type_id = mat_type.get_element_type_id().unwrap(); + let row_count = ir_meta.get_type(column_type_id).get_vector_size().unwrap(); + + ir_meta.get_matrix_type_id(row_count, column_count) + } + // Used to create a type based on the number of dimensions in an image. Both imageSize and + // textureSize return int or ivecN, so a base type of Int is unconditionally used. + fn get_image_size_type(ir_meta: &mut IRMeta, image_type_id: TypeId) -> TypeId { + let image_type = ir_meta.get_type(image_type_id); + let (_, image_type) = image_type.get_image_type(); + let is_array = image_type.is_array; + let dimensions = match image_type.dimension { + ImageDimension::D2 + | ImageDimension::Cube + | ImageDimension::Rect + | ImageDimension::External + | ImageDimension::ExternalY2Y + | ImageDimension::Video + | ImageDimension::PixelLocal + | ImageDimension::Subpass => { + if is_array { + 3 + } else { + 2 + } + } + ImageDimension::D3 => 3, + ImageDimension::Buffer => 1, + }; + + if dimensions == 1 { + TYPE_ID_INT + } else { + ir_meta.get_vector_type_id(BasicType::Int, dimensions) + } + } + // Used to create the gvec4 type that results from reading from an image (with imageLoad, + // texture*, pixelLocalLoadANGLE). + fn get_image_read_type(ir_meta: &mut IRMeta, image_type_id: TypeId) -> TypeId { + let image_basic_type = ir_meta.get_type(image_type_id).get_image_type().0; + match image_basic_type { + ImageBasicType::Float => TYPE_ID_VEC4, + ImageBasicType::Int => TYPE_ID_IVEC4, + ImageBasicType::Uint => TYPE_ID_UVEC4, + } + } + pub fn built_in_unary(ir_meta: &mut IRMeta, op: UnaryOpCode, operand_type: TypeId) -> TypeId { + match op { + UnaryOpCode::Radians + | UnaryOpCode::Degrees + | UnaryOpCode::Sin + | UnaryOpCode::Cos + | UnaryOpCode::Tan + | UnaryOpCode::Asin + | UnaryOpCode::Acos + | UnaryOpCode::Atan + | UnaryOpCode::Sinh + | UnaryOpCode::Cosh + | UnaryOpCode::Tanh + | UnaryOpCode::Asinh + | UnaryOpCode::Acosh + | UnaryOpCode::Atanh + | UnaryOpCode::Exp + | UnaryOpCode::Log + | UnaryOpCode::Exp2 + | UnaryOpCode::Log2 + | UnaryOpCode::Sqrt + | UnaryOpCode::Inversesqrt + | UnaryOpCode::Abs + | UnaryOpCode::Sign + | UnaryOpCode::Floor + | UnaryOpCode::Trunc + | UnaryOpCode::Round + | UnaryOpCode::RoundEven + | UnaryOpCode::Ceil + | UnaryOpCode::Fract + | UnaryOpCode::Normalize + | UnaryOpCode::Inverse + | UnaryOpCode::Not + | UnaryOpCode::BitfieldReverse + | UnaryOpCode::DFdx + | UnaryOpCode::DFdy + | UnaryOpCode::Fwidth + | UnaryOpCode::InterpolateAtCentroid => operand_type, + UnaryOpCode::FloatBitsToInt => change_base_type(ir_meta, operand_type, BasicType::Int), + UnaryOpCode::FloatBitsToUint => { + change_base_type(ir_meta, operand_type, BasicType::Uint) + } + UnaryOpCode::IntBitsToFloat | UnaryOpCode::UintBitsToFloat => { + change_base_type(ir_meta, operand_type, BasicType::Float) + } + UnaryOpCode::PackUnorm2x16 + | UnaryOpCode::PackSnorm2x16 + | UnaryOpCode::PackHalf2x16 + | UnaryOpCode::PackUnorm4x8 + | UnaryOpCode::PackSnorm4x8 => TYPE_ID_UINT, + UnaryOpCode::UnpackSnorm2x16 + | UnaryOpCode::UnpackHalf2x16 + | UnaryOpCode::UnpackUnorm2x16 => TYPE_ID_VEC2, + UnaryOpCode::UnpackUnorm4x8 | UnaryOpCode::UnpackSnorm4x8 => TYPE_ID_VEC4, + UnaryOpCode::Length | UnaryOpCode::Determinant => TYPE_ID_FLOAT, + UnaryOpCode::Transpose => get_transposed_type(ir_meta, operand_type), + UnaryOpCode::Isnan | UnaryOpCode::Isinf | UnaryOpCode::Any | UnaryOpCode::All => { + TYPE_ID_BOOL + } + UnaryOpCode::BitCount | UnaryOpCode::FindLSB | UnaryOpCode::FindMSB => { + change_base_type(ir_meta, operand_type, BasicType::Int) + } + UnaryOpCode::AtomicCounter + | UnaryOpCode::AtomicCounterIncrement + | UnaryOpCode::AtomicCounterDecrement => TYPE_ID_UINT, + UnaryOpCode::ImageSize => get_image_size_type(ir_meta, operand_type), + UnaryOpCode::PixelLocalLoadANGLE => get_image_read_type(ir_meta, operand_type), + _ => panic!("Internal error: Unexpected unary op is not a built-in"), + } + } + + // Used to get the matrix type that's the result of outerProduct(). + // For outerProduct(vecM, vecN) the result is matNxM. + fn get_outerproduct_type( + ir_meta: &mut IRMeta, + lhs_type_id: TypeId, + rhs_type_id: TypeId, + ) -> TypeId { + let column_count = ir_meta.get_type(rhs_type_id).get_vector_size().unwrap(); + let row_count = ir_meta.get_type(lhs_type_id).get_vector_size().unwrap(); + + ir_meta.get_matrix_type_id(column_count, row_count) + } + pub fn built_in_binary( + ir_meta: &mut IRMeta, + op: BinaryOpCode, + lhs_type: TypeId, + rhs_type: TypeId, + ) -> TypeId { + match op { + BinaryOpCode::Atan + | BinaryOpCode::Pow + | BinaryOpCode::Mod + | BinaryOpCode::Min + | BinaryOpCode::Max + | BinaryOpCode::Modf + | BinaryOpCode::Frexp + | BinaryOpCode::Ldexp + | BinaryOpCode::Cross + | BinaryOpCode::Reflect + | BinaryOpCode::MatrixCompMult + | BinaryOpCode::InterpolateAtSample + | BinaryOpCode::InterpolateAtOffset => lhs_type, + BinaryOpCode::Step + | BinaryOpCode::AtomicAdd + | BinaryOpCode::AtomicMin + | BinaryOpCode::AtomicMax + | BinaryOpCode::AtomicAnd + | BinaryOpCode::AtomicOr + | BinaryOpCode::AtomicXor + | BinaryOpCode::AtomicExchange => rhs_type, + BinaryOpCode::Distance | BinaryOpCode::Dot => TYPE_ID_FLOAT, + BinaryOpCode::OuterProduct => get_outerproduct_type(ir_meta, lhs_type, rhs_type), + BinaryOpCode::LessThanVec + | BinaryOpCode::LessThanEqualVec + | BinaryOpCode::GreaterThanVec + | BinaryOpCode::GreaterThanEqualVec + | BinaryOpCode::EqualVec + | BinaryOpCode::NotEqualVec => change_base_type(ir_meta, lhs_type, BasicType::Bool), + _ => panic!("Internal error: Unexpected binary op is not a built-in"), + } + } + + pub fn built_in( + ir_meta: &mut IRMeta, + op: BuiltInOpCode, + operand_types: &mut impl Iterator, + ) -> TypeId { + match op { + BuiltInOpCode::Clamp + | BuiltInOpCode::Mix + | BuiltInOpCode::Fma + | BuiltInOpCode::Faceforward + | BuiltInOpCode::Refract + | BuiltInOpCode::BitfieldExtract + | BuiltInOpCode::BitfieldInsert + | BuiltInOpCode::UaddCarry + | BuiltInOpCode::UsubBorrow + | BuiltInOpCode::InterpolateAtCenter + | BuiltInOpCode::Saturate => operand_types.next().unwrap(), + BuiltInOpCode::Smoothstep + | BuiltInOpCode::AtomicCompSwap + | BuiltInOpCode::ImageAtomicAdd + | BuiltInOpCode::ImageAtomicMin + | BuiltInOpCode::ImageAtomicMax + | BuiltInOpCode::ImageAtomicAnd + | BuiltInOpCode::ImageAtomicOr + | BuiltInOpCode::ImageAtomicXor + | BuiltInOpCode::ImageAtomicExchange + | BuiltInOpCode::ImageAtomicCompSwap => operand_types.last().unwrap(), + BuiltInOpCode::UmulExtended + | BuiltInOpCode::ImulExtended + | BuiltInOpCode::ImageStore + | BuiltInOpCode::PixelLocalStoreANGLE + | BuiltInOpCode::MemoryBarrier + | BuiltInOpCode::MemoryBarrierAtomicCounter + | BuiltInOpCode::MemoryBarrierBuffer + | BuiltInOpCode::MemoryBarrierImage + | BuiltInOpCode::Barrier + | BuiltInOpCode::MemoryBarrierShared + | BuiltInOpCode::GroupMemoryBarrier + | BuiltInOpCode::EmitVertex + | BuiltInOpCode::EndPrimitive + | BuiltInOpCode::BeginInvocationInterlockNV + | BuiltInOpCode::EndInvocationInterlockNV + | BuiltInOpCode::BeginFragmentShaderOrderingINTEL + | BuiltInOpCode::BeginInvocationInterlockARB + | BuiltInOpCode::EndInvocationInterlockARB + | BuiltInOpCode::LoopForwardProgress => TYPE_ID_VOID, + BuiltInOpCode::TextureSize => { + get_image_size_type(ir_meta, operand_types.next().unwrap()) + } + BuiltInOpCode::TextureQueryLod => TYPE_ID_VEC2, + BuiltInOpCode::TexelFetch + | BuiltInOpCode::TexelFetchOffset + | BuiltInOpCode::ImageLoad + | BuiltInOpCode::SubpassLoad => { + get_image_read_type(ir_meta, operand_types.next().unwrap()) + } + BuiltInOpCode::Rgb2Yuv | BuiltInOpCode::Yuv2Rgb => TYPE_ID_VEC3, + BuiltInOpCode::NumSamples => TYPE_ID_UINT, + BuiltInOpCode::SamplePosition => TYPE_ID_VEC2, + } + } + + pub fn built_in_texture(ir_meta: &mut IRMeta, op: &TextureOpCode, sampler: TypeId) -> TypeId { + // The result of sampling from a texture is always gvec4, except for shadow samplers, in + // which case it's vec4 for textureGather* and float otherwise. + if matches!(op, TextureOpCode::GatherRef { .. }) { + // textureGather* with shadow samplers always takes a refZ parameter. + TYPE_ID_VEC4 + } else { + let image_type = ir_meta.get_type(sampler).get_image_type().1; + if image_type.is_shadow { TYPE_ID_FLOAT } else { get_image_read_type(ir_meta, sampler) } + } + } +} + +// Helper functions that derive the precision of an operation. +pub mod precision { + use crate::ir::*; + use crate::*; + + // Taking some precision and comparing it with another: + // + // * Upgrade to highp is either no-op or an upgrade, so it can unconditionally be done. + // * Upgrade to mediump is only necessary if the original precision was lowp. + // * Upgrade to lowp is never necessary. + // + // If either precision is NotApplicable, use the other one. This can happen with constants as + // they don't have a precision. + pub fn higher_precision(one: Precision, other: Precision) -> Precision { + match one { + Precision::High => Precision::High, + Precision::Medium if other == Precision::Low => Precision::Medium, + _ => { + // The other's precision is at least as high as this one, unless it doesn't have a + // precision at all. + if other == Precision::NotApplicable { one } else { other } + } + } + } + + // Take a set of precisions and return the highest per `higher_precision`. + fn highest_precision(precisions: &mut impl Iterator) -> Precision { + precisions.reduce(higher_precision).unwrap() + } + + // Constructor precision is derived from its parameters, except for structs. + pub fn construct( + ir_meta: &IRMeta, + type_id: TypeId, + args: &mut impl Iterator, + ) -> Precision { + if !util::is_precision_applicable_to_type(ir_meta, type_id) { + Precision::NotApplicable + } else { + args.fold(Precision::NotApplicable, |accumulator, precision| { + higher_precision(accumulator, precision) + }) + } + } + + // Array length is usually a constant and therefore has no precision. If it is called on an + // unsized array at the end of an SSBO, it's highp. + pub fn array_length() -> Precision { + // Note: ANGLE has always treated length() as highp, but the spec does not seem to mandate + // that. Rather, it seems the precision is unspecified and must be derived from + // neighboring operations, although it is unclear whether the following is specifically + // referencing written as such because length() typically returns a constant or not. + // + // > The precision is determined using the same rules as for other cases where there is no + // > intrinsic precision. + Precision::High + } + + // The result of Negate, post/prefix increment/decrement and BitwiseNot has the same precision + // as the operand. + pub fn negate(operand: Precision) -> Precision { + operand + } + pub fn bitwise_not(operand: Precision) -> Precision { + operand + } + pub fn postfix_increment(operand: Precision) -> Precision { + operand + } + pub fn postfix_decrement(operand: Precision) -> Precision { + operand + } + pub fn prefix_increment(operand: Precision) -> Precision { + operand + } + pub fn prefix_decrement(operand: Precision) -> Precision { + operand + } + + // The result of most binary operations is the higher of the operands. + pub fn add(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn sub(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn mul(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn div(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn imod(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn vector_times_scalar(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn matrix_times_scalar(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn vector_times_matrix(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn matrix_times_vector(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn matrix_times_matrix(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn bitwise_or(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn bitwise_xor(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + pub fn bitwise_and(lhs: Precision, rhs: Precision) -> Precision { + higher_precision(lhs, rhs) + } + + // Shift operations have the same precision in the result as the value being shifted. + pub fn bit_shift_left(lhs: Precision, _rhs: Precision) -> Precision { + lhs + } + pub fn bit_shift_right(lhs: Precision, _rhs: Precision) -> Precision { + lhs + } + + // Operations that produce bool have no precision. + pub fn logical_not(_operand: Precision) -> Precision { + Precision::NotApplicable + } + pub fn logical_xor(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + pub fn equal(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + pub fn not_equal(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + pub fn less_than(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + pub fn greater_than(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + pub fn less_than_equal(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + pub fn greater_than_equal(_lhs: Precision, _rhs: Precision) -> Precision { + Precision::NotApplicable + } + + pub fn built_in_unary(op: UnaryOpCode, operand: Precision) -> Precision { + match op { + UnaryOpCode::FloatBitsToInt + | UnaryOpCode::FloatBitsToUint + | UnaryOpCode::IntBitsToFloat + | UnaryOpCode::UintBitsToFloat + | UnaryOpCode::PackUnorm2x16 + | UnaryOpCode::PackSnorm2x16 + | UnaryOpCode::PackHalf2x16 + | UnaryOpCode::PackUnorm4x8 + | UnaryOpCode::PackSnorm4x8 + | UnaryOpCode::UnpackSnorm2x16 + | UnaryOpCode::UnpackUnorm2x16 + | UnaryOpCode::BitfieldReverse + | UnaryOpCode::AtomicCounter + | UnaryOpCode::AtomicCounterIncrement + | UnaryOpCode::AtomicCounterDecrement + | UnaryOpCode::ImageSize => Precision::High, + + UnaryOpCode::UnpackHalf2x16 + | UnaryOpCode::UnpackUnorm4x8 + | UnaryOpCode::UnpackSnorm4x8 => Precision::Medium, + + UnaryOpCode::BitCount | UnaryOpCode::FindLSB | UnaryOpCode::FindMSB => Precision::Low, + + UnaryOpCode::Isnan + | UnaryOpCode::Isinf + | UnaryOpCode::Any + | UnaryOpCode::All + | UnaryOpCode::Not => Precision::NotApplicable, + + UnaryOpCode::Radians + | UnaryOpCode::Degrees + | UnaryOpCode::Sin + | UnaryOpCode::Cos + | UnaryOpCode::Tan + | UnaryOpCode::Asin + | UnaryOpCode::Acos + | UnaryOpCode::Atan + | UnaryOpCode::Sinh + | UnaryOpCode::Cosh + | UnaryOpCode::Tanh + | UnaryOpCode::Asinh + | UnaryOpCode::Acosh + | UnaryOpCode::Atanh + | UnaryOpCode::Exp + | UnaryOpCode::Log + | UnaryOpCode::Exp2 + | UnaryOpCode::Log2 + | UnaryOpCode::Sqrt + | UnaryOpCode::Inversesqrt + | UnaryOpCode::Abs + | UnaryOpCode::Sign + | UnaryOpCode::Floor + | UnaryOpCode::Trunc + | UnaryOpCode::Round + | UnaryOpCode::RoundEven + | UnaryOpCode::Ceil + | UnaryOpCode::Fract + | UnaryOpCode::Length + | UnaryOpCode::Normalize + | UnaryOpCode::Transpose + | UnaryOpCode::Determinant + | UnaryOpCode::Inverse + | UnaryOpCode::DFdx + | UnaryOpCode::DFdy + | UnaryOpCode::Fwidth + | UnaryOpCode::InterpolateAtCentroid + | UnaryOpCode::PixelLocalLoadANGLE => operand, + _ => panic!("Internal error: Unexpected unary op is not a built-in"), + } + } + + pub fn built_in_binary(op: BinaryOpCode, lhs: Precision, rhs: Precision) -> Precision { + match op { + BinaryOpCode::Frexp + | BinaryOpCode::Ldexp + | BinaryOpCode::AtomicAdd + | BinaryOpCode::AtomicMin + | BinaryOpCode::AtomicMax + | BinaryOpCode::AtomicAnd + | BinaryOpCode::AtomicOr + | BinaryOpCode::AtomicXor + | BinaryOpCode::AtomicExchange => Precision::High, + + BinaryOpCode::InterpolateAtSample | BinaryOpCode::InterpolateAtOffset => lhs, + + BinaryOpCode::LessThanVec + | BinaryOpCode::LessThanEqualVec + | BinaryOpCode::GreaterThanVec + | BinaryOpCode::GreaterThanEqualVec + | BinaryOpCode::EqualVec + | BinaryOpCode::NotEqualVec => Precision::NotApplicable, + + BinaryOpCode::Atan + | BinaryOpCode::Pow + | BinaryOpCode::Mod + | BinaryOpCode::Min + | BinaryOpCode::Max + | BinaryOpCode::Step + | BinaryOpCode::Modf + | BinaryOpCode::Distance + | BinaryOpCode::Dot + | BinaryOpCode::Cross + | BinaryOpCode::Reflect + | BinaryOpCode::MatrixCompMult + | BinaryOpCode::OuterProduct => higher_precision(lhs, rhs), + _ => panic!("Internal error: Unexpected binary op is not a built-in"), + } + } + + pub fn built_in( + op: BuiltInOpCode, + operands: &mut impl Iterator, + ) -> Precision { + match op { + BuiltInOpCode::TextureSize + | BuiltInOpCode::UaddCarry + | BuiltInOpCode::UsubBorrow + | BuiltInOpCode::AtomicCompSwap + | BuiltInOpCode::ImageAtomicAdd + | BuiltInOpCode::ImageAtomicMin + | BuiltInOpCode::ImageAtomicMax + | BuiltInOpCode::ImageAtomicAnd + | BuiltInOpCode::ImageAtomicOr + | BuiltInOpCode::ImageAtomicXor + | BuiltInOpCode::ImageAtomicExchange + | BuiltInOpCode::ImageAtomicCompSwap + | BuiltInOpCode::NumSamples + | BuiltInOpCode::SamplePosition => Precision::High, + + BuiltInOpCode::BitfieldExtract + | BuiltInOpCode::BitfieldInsert + | BuiltInOpCode::InterpolateAtCenter + | BuiltInOpCode::TextureQueryLod + | BuiltInOpCode::TexelFetch + | BuiltInOpCode::TexelFetchOffset + | BuiltInOpCode::ImageLoad + | BuiltInOpCode::SubpassLoad => operands.next().unwrap(), + + BuiltInOpCode::Clamp + | BuiltInOpCode::Mix + | BuiltInOpCode::Smoothstep + | BuiltInOpCode::Fma + | BuiltInOpCode::Faceforward + | BuiltInOpCode::Refract + | BuiltInOpCode::Rgb2Yuv + | BuiltInOpCode::Yuv2Rgb + | BuiltInOpCode::Saturate => highest_precision(operands), + + BuiltInOpCode::UmulExtended + | BuiltInOpCode::ImulExtended + | BuiltInOpCode::ImageStore + | BuiltInOpCode::PixelLocalStoreANGLE + | BuiltInOpCode::MemoryBarrier + | BuiltInOpCode::MemoryBarrierAtomicCounter + | BuiltInOpCode::MemoryBarrierBuffer + | BuiltInOpCode::MemoryBarrierImage + | BuiltInOpCode::Barrier + | BuiltInOpCode::MemoryBarrierShared + | BuiltInOpCode::GroupMemoryBarrier + | BuiltInOpCode::EmitVertex + | BuiltInOpCode::EndPrimitive + | BuiltInOpCode::BeginInvocationInterlockNV + | BuiltInOpCode::EndInvocationInterlockNV + | BuiltInOpCode::BeginFragmentShaderOrderingINTEL + | BuiltInOpCode::BeginInvocationInterlockARB + | BuiltInOpCode::EndInvocationInterlockARB + | BuiltInOpCode::LoopForwardProgress => { + panic!("Internal error: invalid to derive precision of void built-in") + } + } + } + + pub fn built_in_texture(_op: &TextureOpCode, sampler: Precision) -> Precision { + // Result of texture sampling always has the same precision as the sampler. + sampler + } + + // A helper that does the opposite of the above; it takes an instruction, and looks at the + // operands that don't already have a precision (but should such as constants, or registers + // derived from constants). In the case of constants, the precision is immediately fixed. For + // registers, they are added to a list so the caller can continue processing them. + pub fn propagate_to_id( + id: &mut TypedId, + precision: Precision, + to_propagate: &mut Vec<(RegisterId, Precision)>, + ) { + if id.precision == Precision::NotApplicable && precision != Precision::NotApplicable { + match id.id { + Id::Register(register_id) => { + id.precision = precision; + to_propagate.push((register_id, precision)); + } + Id::Constant(_) => id.precision = precision, + Id::Variable(_) => { + panic!("Internal error: Unexpected need to propagate precision to a variable") + } + } + } + } + pub fn propagate_to_ids( + ids: &mut std::slice::IterMut<'_, TypedId>, + precision: Precision, + to_propagate: &mut Vec<(RegisterId, Precision)>, + ) { + ids.for_each(|id| { + propagate_to_id(id, precision, to_propagate); + }); + } + pub fn propagate( + instruction: &mut Instruction, + function_arg_precisions: &std::collections::HashMap>, + struct_member_precisions: &std::collections::HashMap>, + to_propagate: &mut Vec<(RegisterId, Precision)>, + ) { + let precision = instruction.result.precision; + + let propagate_by_matching_precision = + |ids: &mut std::slice::IterMut<'_, TypedId>, + to_match: &[Precision], + to_propagate: &mut Vec<(RegisterId, Precision)>| { + ids.zip(to_match.iter()).for_each(|(id, &expect)| { + propagate_to_id(id, expect, to_propagate); + }); + }; + + match instruction.op { + OpCode::ExtractVectorComponentDynamic(ref mut indexed, ref mut index) + | OpCode::ExtractMatrixColumn(ref mut indexed, ref mut index) + | OpCode::ExtractArrayElement(ref mut indexed, ref mut index) => { + propagate_to_id(indexed, precision, to_propagate); + // For constant indices, always apply highp + propagate_to_id(index, Precision::High, to_propagate); + } + // Pointers cannot have been derived from constants (and be without precision). + OpCode::AccessVectorComponentDynamic(_, ref mut index) + | OpCode::AccessMatrixColumn(_, ref mut index) + | OpCode::AccessArrayElement(_, ref mut index) => { + // For constant indices, always apply highp + propagate_to_id(index, Precision::High, to_propagate); + } + OpCode::ExtractVectorComponent(ref mut indexed, _) + | OpCode::ExtractVectorComponentMulti(ref mut indexed, _) + | OpCode::ExtractStructField(ref mut indexed, _) => { + propagate_to_id(indexed, precision, to_propagate); + } + // For constructors, propagate precision to arguments. + OpCode::ConstructScalarFromScalar(ref mut arg) + | OpCode::ConstructVectorFromScalar(ref mut arg) + | OpCode::ConstructMatrixFromScalar(ref mut arg) + | OpCode::ConstructMatrixFromMatrix(ref mut arg) => { + propagate_to_id(arg, precision, to_propagate); + } + OpCode::ConstructVectorFromMultiple(ref mut args) + | OpCode::ConstructMatrixFromMultiple(ref mut args) + | OpCode::ConstructArray(ref mut args) => { + propagate_to_ids(&mut args.iter_mut(), precision, to_propagate); + } + // For function calls, propagate precision of each parameter to its corresponding + // argument. + OpCode::Call(function_id, ref mut args) => { + propagate_by_matching_precision( + &mut args.iter_mut(), + &function_arg_precisions[&function_id], + to_propagate, + ); + } + // For struct constructors, propagate precision of each member to its corresponding + // argument. + OpCode::ConstructStruct(ref mut args) => { + propagate_by_matching_precision( + &mut args.iter_mut(), + &struct_member_precisions[&instruction.result.type_id], + to_propagate, + ); + } + OpCode::Alias(ref mut alias_id) => { + propagate_to_id(alias_id, precision, to_propagate); + } + // Pointers cannot have been derived from constants (and be without precision). + OpCode::AccessVectorComponent(..) + | OpCode::AccessVectorComponentMulti(..) + | OpCode::AccessStructField(..) + | OpCode::Load(..) => {} + + OpCode::Unary(op, ref mut operand) => { + match op { + UnaryOpCode::ArrayLength => { + // Precision of result does not affect the operand in any way. For now, + // don't assign any precision to the argument; it may not be applicable to + // it, e.g. if it's a bool array. + }, + // Precision of result does not affect the operand in any way, assume highp as + // otherwise the constant cannot take precision from anywhere else: + UnaryOpCode::PackSnorm2x16 | + UnaryOpCode::PackHalf2x16 | + UnaryOpCode::PackUnorm2x16 | + UnaryOpCode::PackUnorm4x8 | + UnaryOpCode::PackSnorm4x8 | + UnaryOpCode::BitCount | + UnaryOpCode::FindMSB | + UnaryOpCode::FindLSB | + UnaryOpCode::Isnan | + UnaryOpCode::Isinf | + // Arguments of these built-ins are always highp + UnaryOpCode::FloatBitsToInt | + UnaryOpCode::FloatBitsToUint | + UnaryOpCode::IntBitsToFloat | + UnaryOpCode::UintBitsToFloat | + UnaryOpCode::UnpackSnorm2x16 | + UnaryOpCode::UnpackHalf2x16 | + UnaryOpCode::UnpackUnorm2x16 | + UnaryOpCode::UnpackUnorm4x8 | + UnaryOpCode::UnpackSnorm4x8 | + UnaryOpCode::BitfieldReverse => { + propagate_to_id(operand, Precision::High, to_propagate); + }, + _ => { + propagate_to_id(operand, precision, to_propagate); + } + }; + } + OpCode::Binary(op, ref mut lhs, ref mut rhs) => { + match op { + BinaryOpCode::Add + | BinaryOpCode::Sub + | BinaryOpCode::Mul + | BinaryOpCode::VectorTimesScalar + | BinaryOpCode::MatrixTimesScalar + | BinaryOpCode::VectorTimesMatrix + | BinaryOpCode::MatrixTimesVector + | BinaryOpCode::MatrixTimesMatrix + | BinaryOpCode::Div + | BinaryOpCode::IMod + | BinaryOpCode::BitShiftLeft + | BinaryOpCode::BitShiftRight + | BinaryOpCode::BitwiseOr + | BinaryOpCode::BitwiseXor + | BinaryOpCode::BitwiseAnd + | BinaryOpCode::Atan + | BinaryOpCode::Pow + | BinaryOpCode::Mod + | BinaryOpCode::Min + | BinaryOpCode::Max + | BinaryOpCode::Step + | BinaryOpCode::Modf + | BinaryOpCode::Distance + | BinaryOpCode::Dot + | BinaryOpCode::Cross + | BinaryOpCode::Reflect + | BinaryOpCode::MatrixCompMult + | BinaryOpCode::OuterProduct + | BinaryOpCode::InterpolateAtOffset => { + propagate_to_id(lhs, precision, to_propagate); + propagate_to_id(rhs, precision, to_propagate); + } + BinaryOpCode::LogicalXor => { + // Parameters are boolean, so there are no precisions. + } + BinaryOpCode::Frexp | BinaryOpCode::Ldexp => { + // Arguments of frexp and ldexp are always highp. + propagate_to_id(lhs, Precision::High, to_propagate); + propagate_to_id(rhs, Precision::High, to_propagate); + } + BinaryOpCode::Equal + | BinaryOpCode::NotEqual + | BinaryOpCode::LessThan + | BinaryOpCode::GreaterThan + | BinaryOpCode::LessThanEqual + | BinaryOpCode::GreaterThanEqual + | BinaryOpCode::LessThanVec + | BinaryOpCode::LessThanEqualVec + | BinaryOpCode::GreaterThanVec + | BinaryOpCode::GreaterThanEqualVec + | BinaryOpCode::EqualVec + | BinaryOpCode::NotEqualVec => { + // Apply precision from one operand to the other, as the result does not + // have a precision. If neither has a precision, precision cannot be + // derived, AST generation will assume highp. + if lhs.precision != Precision::NotApplicable { + propagate_to_id(rhs, lhs.precision, to_propagate); + } else { + propagate_to_id(lhs, rhs.precision, to_propagate); + } + } + + BinaryOpCode::InterpolateAtSample => { + // Precision is only applicable to the lhs. Assume highp for the sample + // parameter, which otherwise cannot get a precision from anywhere. + propagate_to_id(lhs, precision, to_propagate); + propagate_to_id(rhs, Precision::High, to_propagate); + } + + BinaryOpCode::AtomicAdd + | BinaryOpCode::AtomicMin + | BinaryOpCode::AtomicMax + | BinaryOpCode::AtomicAnd + | BinaryOpCode::AtomicOr + | BinaryOpCode::AtomicXor + | BinaryOpCode::AtomicExchange => { + // Atomics always apply to 32-bit values. The first argument is a pointer + // (so cannot be derived from constants), so only the second argument may + // need a precision. + propagate_to_id(rhs, precision, to_propagate); + } + }; + } + OpCode::BuiltIn(op, ref mut params) => { + match op { + BuiltInOpCode::Clamp | + BuiltInOpCode::Mix | + BuiltInOpCode::Smoothstep | + BuiltInOpCode::Fma | + BuiltInOpCode::Faceforward | + BuiltInOpCode::Refract | + BuiltInOpCode::BitfieldExtract | + BuiltInOpCode::BitfieldInsert | + BuiltInOpCode::TextureQueryLod | + BuiltInOpCode::TexelFetch | + BuiltInOpCode::TexelFetchOffset | + BuiltInOpCode::Rgb2Yuv | + BuiltInOpCode::Yuv2Rgb | + BuiltInOpCode::AtomicCompSwap | + BuiltInOpCode::ImageLoad | + BuiltInOpCode::ImageAtomicAdd | + BuiltInOpCode::ImageAtomicMin | + BuiltInOpCode::ImageAtomicMax | + BuiltInOpCode::ImageAtomicAnd | + BuiltInOpCode::ImageAtomicOr | + BuiltInOpCode::ImageAtomicXor | + BuiltInOpCode::ImageAtomicExchange | + BuiltInOpCode::ImageAtomicCompSwap | + BuiltInOpCode::SamplePosition | + BuiltInOpCode::InterpolateAtCenter | + BuiltInOpCode::Saturate => { + propagate_to_ids(&mut params.iter_mut(), precision, to_propagate); + }, + BuiltInOpCode::TextureSize => { + // Return precision is highp. Assume highp for the lod parameter. + propagate_to_id(params.last_mut().unwrap(), Precision::High, to_propagate); + }, + BuiltInOpCode::UaddCarry | + BuiltInOpCode::UsubBorrow => { + // The parameters are highp,highp,lowp + propagate_to_id(&mut params[0], Precision::High, to_propagate); + propagate_to_id(&mut params[1], Precision::High, to_propagate); + propagate_to_id(&mut params[2], Precision::Low, to_propagate); + }, + BuiltInOpCode::UmulExtended | + BuiltInOpCode::ImulExtended => { + // The parameters are highp,highp,pointer,pointer + propagate_to_id(&mut params[0], Precision::High, to_propagate); + propagate_to_id(&mut params[1], Precision::High, to_propagate); + }, + // No arguments, so no precision to propagate. + BuiltInOpCode::NumSamples | + // The parameter is a pointer, so cannot be derived from constants. + BuiltInOpCode::SubpassLoad => { + }, + // Void instructions are handled by the caller. + BuiltInOpCode::ImageStore | + BuiltInOpCode::MemoryBarrier | + BuiltInOpCode::MemoryBarrierAtomicCounter | + BuiltInOpCode::MemoryBarrierBuffer | + BuiltInOpCode::MemoryBarrierImage | + BuiltInOpCode::Barrier | + BuiltInOpCode::MemoryBarrierShared | + BuiltInOpCode::GroupMemoryBarrier | + BuiltInOpCode::EmitVertex | + BuiltInOpCode::EndPrimitive | + BuiltInOpCode::BeginInvocationInterlockNV | + BuiltInOpCode::EndInvocationInterlockNV | + BuiltInOpCode::BeginFragmentShaderOrderingINTEL | + BuiltInOpCode::BeginInvocationInterlockARB | + BuiltInOpCode::EndInvocationInterlockARB | + BuiltInOpCode::PixelLocalStoreANGLE | + BuiltInOpCode::LoopForwardProgress => { + panic!("Internal error: Unexpected void instruction when propagating precision to constants"); + } + }; + } + OpCode::Texture(ref mut texture_op, _sampler, ref mut coord) => { + // Apply precision to coord. Note that sampler is a pointer and cannot be derived + // from constants. + propagate_to_id(coord, precision, to_propagate); + match texture_op { + TextureOpCode::Implicit { offset, .. } + | TextureOpCode::Lod { offset, .. } + | TextureOpCode::Bias { offset, .. } + | TextureOpCode::Grad { offset, .. } + | TextureOpCode::Gather { offset } + | TextureOpCode::GatherComponent { offset, .. } + | TextureOpCode::GatherRef { offset, .. } => { + offset + .iter_mut() + .for_each(|offset| propagate_to_id(offset, precision, to_propagate)); + } + _ => {} + }; + match texture_op { + TextureOpCode::Implicit { .. } => {} + TextureOpCode::Compare { compare } => { + propagate_to_id(compare, precision, to_propagate); + } + TextureOpCode::Lod { lod, .. } => { + propagate_to_id(lod, precision, to_propagate); + } + TextureOpCode::CompareLod { compare, lod } => { + propagate_to_id(compare, precision, to_propagate); + propagate_to_id(lod, precision, to_propagate); + } + TextureOpCode::Bias { bias, .. } => { + propagate_to_id(bias, precision, to_propagate); + } + TextureOpCode::CompareBias { compare, bias } => { + propagate_to_id(compare, precision, to_propagate); + propagate_to_id(bias, precision, to_propagate); + } + TextureOpCode::Grad { dx, dy, .. } => { + propagate_to_id(dx, precision, to_propagate); + propagate_to_id(dy, precision, to_propagate); + } + TextureOpCode::Gather { .. } => {} + TextureOpCode::GatherComponent { component, .. } => { + propagate_to_id(component, precision, to_propagate); + } + TextureOpCode::GatherRef { refz, .. } => { + propagate_to_id(refz, precision, to_propagate); + } + }; + } + OpCode::MergeInput => { + // Handled specially by the caller. + } + // Void instructions are handled by the caller. + OpCode::Discard + | OpCode::Return(_) + | OpCode::Break + | OpCode::Continue + | OpCode::Passthrough + | OpCode::NextBlock + | OpCode::Merge(_) + | OpCode::If(_) + | OpCode::Loop + | OpCode::DoLoop + | OpCode::LoopIf(_) + | OpCode::Switch(..) + | OpCode::Store(..) => panic!( + "Internal error: Unexpected void instruction when propagating precision to constants" + ), + } + } +} + +// The result of creating an instruction. It's either a constant (if constant-folded), a void +// instruction or a register id referencing the instruction in IRMeta::instructions. Sometimes +// an instruction can detect that it's a no-op too. +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Result { + Constant(TypedConstantId), + Void(OpCode), + Register(TypedRegisterId), + NoOp(TypedId), +} + +impl Result { + pub fn get_result_id(&self) -> TypedId { + match *self { + instruction::Result::Constant(id) => TypedId::from_typed_constant_id(id), + instruction::Result::Register(id) => TypedId::from_register_id(id), + instruction::Result::NoOp(id) => id, + _ => panic!("Internal error: Expected instruction with value"), + } + } + + // Use to make sure the result of the instruction is not a new register, but rather an + // existing one. During transformations, an instruction producing register N may need to + // be replaced with other instructions. Making sure the end result has the same id + // obviates the need to transform the IR further to replace the result id with a new one. + pub fn override_result_id(&mut self, ir_meta: &mut IRMeta, id: TypedRegisterId) { + match self { + Result::Register(replace_by) => { + ir_meta.replace_instruction(id.id, replace_by.id); + *replace_by = id; + } + Result::Constant(constant_id) => { + // Create an alias for this constant. + let mut alias = + instruction::alias(ir_meta, TypedId::from_typed_constant_id(*constant_id)); + alias.override_result_id(ir_meta, id); + *self = alias; + } + Result::NoOp(replace_by) => { + // Create an alias for this id. + let mut alias = instruction::alias(ir_meta, *replace_by); + alias.override_result_id(ir_meta, id); + *self = alias; + } + _ => panic!("Internal error: Expected typed instruction when replacing result id"), + } + } +} + +// Helper macros to create an instruction, returning a Result. For example: +// +// instruction::make!(negate, ir_meta, operand) +// instruction::make!(add, ir_meta, lhs, rhs) +macro_rules! make { + ($func:ident, $ir_meta:expr, $($params:expr),*) => { + instruction::$func($ir_meta, $($params),*) + } + } +pub(crate) use make; +// Similar to make!(), but with a specific result id. +// +// instruction::make_with_result_id!(negate, ir_meta, result_id, operand) +macro_rules! make_with_result_id { + ($func:ident, $ir_meta:expr, $result:expr, $($params:expr),*) => { + { + let mut inst = instruction::$func($ir_meta, $($params),*); + inst.override_result_id($ir_meta, $result); + inst + } + } + } +pub(crate) use make_with_result_id; + +fn make_constant(constant_id: ConstantId, type_id: TypeId, precision: Precision) -> Result { + Result::Constant(TypedConstantId::new(constant_id, type_id, precision)) +} + +fn make_register( + ir_meta: &mut IRMeta, + op: OpCode, + type_id: TypeId, + precision: Precision, +) -> Result { + Result::Register(ir_meta.new_register(op, type_id, precision)) +} + +// A generic helper to make a unary operator. +fn unary_op( + ir_meta: &mut IRMeta, + operand: TypedId, + promote: Promote, + derive_precision: DerivePrecision, + op: UnaryOp, + const_fold: ConstFold, +) -> Result +where + Promote: FnOnce(&mut IRMeta, TypeId) -> TypeId, + DerivePrecision: FnOnce(Precision) -> Precision, + UnaryOp: FnOnce(&mut IRMeta, TypedId, TypeId) -> OpCode, + ConstFold: FnOnce(&mut IRMeta, ConstantId, TypeId) -> ConstantId, +{ + let result_type_id = promote(ir_meta, operand.type_id); + let precision = derive_precision(operand.precision); + + // If the operand is constant, constant fold the operation + if let Id::Constant(constant_id) = operand.id { + let folded = const_fold(ir_meta, constant_id, result_type_id); + make_constant(folded, result_type_id, precision) + } else { + // Otherwise make an instruction + let op = op(ir_meta, operand, result_type_id); + make_register(ir_meta, op, result_type_id, precision) + } +} + +// A generic helper to make a binary operator. +fn binary_op( + ir_meta: &mut IRMeta, + lhs: TypedId, + rhs: TypedId, + promote: Promote, + derive_precision: DerivePrecision, + op: BinaryOp, + const_fold: ConstFold, +) -> Result +where + Promote: FnOnce(&mut IRMeta, TypeId, TypeId) -> TypeId, + DerivePrecision: FnOnce(Precision, Precision) -> Precision, + BinaryOp: FnOnce(&mut IRMeta, TypedId, TypedId) -> OpCode, + ConstFold: FnOnce(&mut IRMeta, ConstantId, ConstantId, TypeId) -> ConstantId, +{ + let result_type_id = promote(ir_meta, lhs.type_id, rhs.type_id); + let precision = derive_precision(lhs.precision, rhs.precision); + + // If both operands are constant, constant fold the operation + if let (Id::Constant(lhs_constant_id), Id::Constant(rhs_constant_id)) = (lhs.id, rhs.id) { + let folded = const_fold(ir_meta, lhs_constant_id, rhs_constant_id, result_type_id); + make_constant(folded, result_type_id, precision) + } else { + // Otherwise make an instruction + let op = op(ir_meta, lhs, rhs); + make_register(ir_meta, op, result_type_id, precision) + } +} + +// Call a user-defined function. +pub fn call(ir_meta: &mut IRMeta, id: FunctionId, args: Vec) -> Result { + let call = OpCode::Call(id, args); + + let function = ir_meta.get_function(id); + let return_type_id = function.return_type_id; + let return_precision = function.return_precision; + + // The result depends on whether the function returns void or a value. + // If the function is not void, push a new id for its result. + if return_type_id != TYPE_ID_VOID { + make_register(ir_meta, call, return_type_id, return_precision) + } else { + Result::Void(call) + } +} + +// Block terminating instructions. +pub fn branch_discard() -> Result { + Result::Void(OpCode::Discard) +} +pub fn branch_return(value: Option) -> Result { + Result::Void(OpCode::Return(value)) +} +pub fn branch_break() -> Result { + Result::Void(OpCode::Break) +} +pub fn branch_continue() -> Result { + Result::Void(OpCode::Continue) +} +pub fn branch_passthrough() -> Result { + Result::Void(OpCode::Passthrough) +} +pub fn branch_next_block() -> Result { + Result::Void(OpCode::NextBlock) +} +pub fn branch_merge(id: Option) -> Result { + Result::Void(OpCode::Merge(id)) +} + +fn load_from_pointer(ir_meta: &mut IRMeta, to_load: TypedId, pointee_type_id: TypeId) -> Result { + make_register(ir_meta, OpCode::Load(to_load), pointee_type_id, to_load.precision) +} + +// Load a value from a pointer and return it. +pub fn load(ir_meta: &mut IRMeta, to_load: TypedId) -> Result { + let type_info = ir_meta.get_type(to_load.type_id); + + match type_info { + &Type::Pointer(pointee_type_id) => load_from_pointer(ir_meta, to_load, pointee_type_id), + _ => Result::NoOp(to_load), + } +} + +// Store a value into a pointer. +pub fn store(_ir_meta: &mut IRMeta, pointer: TypedId, value: TypedId) -> Result { + Result::Void(OpCode::Store(pointer, value)) +} + +pub fn alias(ir_meta: &mut IRMeta, id: TypedId) -> Result { + make_register(ir_meta, OpCode::Alias(id), id.type_id, id.precision) +} + +fn same_precision_as_operand(precision: Precision) -> Precision { + precision +} + +fn same_precision_as_lhs(lhs: Precision, _rhs: Precision) -> Precision { + lhs +} + +// Take a component of a vector, like `vector.y`. +pub fn vector_component(ir_meta: &mut IRMeta, vector: TypedId, component: u32) -> Result { + // To avoid constant index on swizzles, like var.xyz[1], check if the value being indexed + // is a swizzle, in which case the swizzle components can be folded and the swizzle + // applied to the original vector. + // + // Note that this logic is not valid if the original swizzle was on a pointer and the + // latter is on a loaded value, because the pointer's pointee value may have changed in + // between. + let mut vector = vector; + let mut component = component; + + if let Id::Register(register_id) = vector.id { + let instruction = ir_meta.get_instruction(register_id); + match &instruction.op { + &OpCode::ExtractVectorComponentMulti(original_vector, ref original_components) + | &OpCode::AccessVectorComponentMulti(original_vector, ref original_components) => { + vector = original_vector; + component = original_components[component as usize]; + } + _ => (), + } + } + + unary_op( + ir_meta, + vector, + promote::vector_component, + same_precision_as_operand, + |ir_meta, operand, result_type_id| { + let is_pointer = ir_meta.get_type(result_type_id).is_pointer(); + if is_pointer { + OpCode::AccessVectorComponent(operand, component) + } else { + OpCode::ExtractVectorComponent(operand, component) + } + }, + |ir_meta, constant_id, result_type_id| { + const_fold::composite_element(ir_meta, constant_id, component, result_type_id) + }, + ) +} + +fn merge_swizzle_components(components: &[u32], to_apply: &[u32]) -> Vec { + to_apply.iter().map(|&index| components[index as usize]).collect() +} + +// Take multiple components of a vector, like `vector.yxy`. +pub fn vector_component_multi( + ir_meta: &mut IRMeta, + vector: TypedId, + components: Vec, +) -> Result { + // If the swizzle selects every element in order, optimize that out. + { + let mut type_info = ir_meta.get_type(vector.type_id); + if type_info.is_pointer() { + type_info = ir_meta.get_type(type_info.get_element_type_id().unwrap()); + } + let vec_size = type_info.get_vector_size().unwrap() as usize; + let identity = [0, 1, 2, 3]; + if components[..] == identity[0..vec_size] { + return Result::NoOp(vector); + } + } + + // To avoid swizzles of swizzles, like var.xyz.xz, check if the value being swizzled is + // itself a swizzle, in which case the swizzle components can be folded and the swizzle + // applied to the original vector. + // + // Note that this logic is not valid if the original swizzle was on a pointer and the + // latter is on a loaded value, because the pointer's pointee value may have changed in + // between. + let mut vector = vector; + let mut components = components; + + if let Id::Register(register_id) = vector.id { + let instruction = ir_meta.get_instruction(register_id); + match &instruction.op { + &OpCode::ExtractVectorComponentMulti(original_vector, ref original_components) + | &OpCode::AccessVectorComponentMulti(original_vector, ref original_components) => { + vector = original_vector; + components = merge_swizzle_components(original_components, &components); + } + _ => (), + } + } + + let components_clone = components.clone(); + unary_op( + ir_meta, + vector, + |ir_meta, operand_type| { + promote::vector_component_multi(ir_meta, operand_type, components.len() as u32) + }, + same_precision_as_operand, + |ir_meta, operand, result_type_id| { + let is_pointer = ir_meta.get_type(result_type_id).is_pointer(); + if is_pointer { + OpCode::AccessVectorComponentMulti(operand, components_clone) + } else { + OpCode::ExtractVectorComponentMulti(operand, components_clone) + } + }, + |ir_meta, constant_id, result_type_id| { + const_fold::vector_component_multi(ir_meta, constant_id, &components, result_type_id) + }, + ) +} + +// Equivalent of operator []. +pub fn index(ir_meta: &mut IRMeta, indexed: TypedId, index: TypedId) -> Result { + // Note: constant index on a vector should use vector_component() instead. + debug_assert!(!(ir_meta.get_type(indexed.type_id).is_vector() && index.id.is_constant())); + + binary_op( + ir_meta, + indexed, + index, + |ir_meta, indexed_type, _| promote::index(ir_meta, indexed_type), + same_precision_as_lhs, + |ir_meta, indexed, index| { + let mut referenced_indexed_type = ir_meta.get_type(indexed.type_id); + let is_pointer = referenced_indexed_type.is_pointer(); + + if is_pointer { + referenced_indexed_type = + ir_meta.get_type(referenced_indexed_type.get_element_type_id().unwrap()); + } + + match referenced_indexed_type { + Type::Vector(..) => { + if is_pointer { + OpCode::AccessVectorComponentDynamic(indexed, index) + } else { + OpCode::ExtractVectorComponentDynamic(indexed, index) + } + } + Type::Matrix(..) => { + if is_pointer { + OpCode::AccessMatrixColumn(indexed, index) + } else { + OpCode::ExtractMatrixColumn(indexed, index) + } + } + _ => { + if is_pointer { + OpCode::AccessArrayElement(indexed, index) + } else { + OpCode::ExtractArrayElement(indexed, index) + } + } + } + }, + const_fold::index, + ) +} + +// Select a field of a struct, like `block.field`. +pub fn struct_field(ir_meta: &mut IRMeta, struct_id: TypedId, field_index: u32) -> Result { + // Use the precision of the field itself on the result + let mut struct_type_info = ir_meta.get_type(struct_id.type_id); + if struct_type_info.is_pointer() { + struct_type_info = ir_meta.get_type(struct_type_info.get_element_type_id().unwrap()); + } + let field_precision = struct_type_info.get_struct_field(field_index).precision; + + unary_op( + ir_meta, + struct_id, + |ir_meta, operand_type| promote::struct_field(ir_meta, operand_type, field_index), + |_| field_precision, + |ir_meta, operand, result_type_id| { + let is_pointer = ir_meta.get_type(result_type_id).is_pointer(); + + if is_pointer { + OpCode::AccessStructField(operand, field_index) + } else { + OpCode::ExtractStructField(operand, field_index) + } + }, + |ir_meta, constant_id, result_type_id| { + const_fold::composite_element(ir_meta, constant_id, field_index, result_type_id) + }, + ) +} + +fn verify_construct_arg_component_count( + ir_meta: &mut IRMeta, + type_id: TypeId, + args: &[TypedId], +) -> bool { + let type_info = ir_meta.get_type(type_id); + match type_info { + // Structs and arrays always require an exact number of elements. + Type::Array(..) | Type::Struct(..) => { + return true; + } + // Matrix-from-matrix constructors are allowed to have mismatching component count. + Type::Matrix(..) if args.len() == 1 => { + return true; + } + _ => (), + } + + let expected_total_components = type_info.get_total_component_count(ir_meta); + + let args_total_components: u32 = args + .iter() + .map(|id| { + let type_info = ir_meta.get_type(id.type_id); + type_info.get_total_component_count(ir_meta) + }) + .sum(); + + // Vec and matrix constructors either take a scalar, or the caller should have ensured the + // number of arguments in args matches the constructed type. + args_total_components == 1 || args_total_components == expected_total_components +} + +// Construct a value of a type from the given arguments. +pub fn construct(ir_meta: &mut IRMeta, type_id: TypeId, args: Vec) -> Result { + // Note: For vector and matrix constructors with multiple components, it is expected that + // the total components in `args` matches the components needed for type_id. + debug_assert!(verify_construct_arg_component_count(ir_meta, type_id, &args)); + + // Constructor precision is derived from its parameters, except for structs. + let promoted_precision = + precision::construct(ir_meta, type_id, &mut args.iter().map(|id| id.precision)); + + // If the type of the first argument is the same as the result, the rest of the arguments + // will be stripped (if any) and the cast is a no-op. In that case, push args[0] back to + // the stack and early out. + // + // Note: Per the GLSL spec, the constructor precision is derived from its arguments, + // meaning that `vecN(vN, vM)` where vN is mediump and vM is highp should have highp + // results, so replacing that with `vN` with the same precision is not entirely correct. + // For maximum correctness, the `Alias` op can be used to change the precision and give + // this a new id, but this is such a niche case that we're ignoring it for simplicity. + if args[0].type_id == type_id { + return Result::NoOp(args[0]); + } + + let all_constants = args.iter().all(|id| id.id.is_constant()); + if all_constants { + let folded = const_fold::construct( + ir_meta, + &mut args.iter().map(|id| id.id.get_constant().unwrap()), + type_id, + ); + make_constant(folded, type_id, promoted_precision) + } else { + let type_info = ir_meta.get_type(type_id); + let arg0_type_info = ir_meta.get_type(args[0].type_id); + + // Decide the opcode + let op = match type_info { + Type::Scalar(..) => OpCode::ConstructScalarFromScalar(args[0]), + Type::Vector(..) => { + if args.len() == 1 && arg0_type_info.is_scalar() { + OpCode::ConstructVectorFromScalar(args[0]) + } else { + OpCode::ConstructVectorFromMultiple(args) + } + } + Type::Matrix(..) => { + if args.len() == 1 && arg0_type_info.is_scalar() { + OpCode::ConstructMatrixFromScalar(args[0]) + } else if args.len() == 1 && arg0_type_info.is_matrix() { + OpCode::ConstructMatrixFromMatrix(args[0]) + } else { + OpCode::ConstructMatrixFromMultiple(args) + } + } + Type::Struct(..) => OpCode::ConstructStruct(args), + Type::Array(..) => OpCode::ConstructArray(args), + _ => panic!("Internal error: Type cannot be constructed"), + }; + + make_register(ir_meta, op, type_id, promoted_precision) + } +} + +// Get the array length of an unsized array. +pub fn array_length(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + // This should only be called for unsized arrays, otherwise the size is already known to + // the caller. + let type_info = ir_meta.get_type(operand.type_id); + debug_assert!(type_info.is_pointer()); + let pointee_type_id = type_info.get_element_type_id().unwrap(); + + let type_info = ir_meta.get_type(pointee_type_id); + debug_assert!(type_info.is_unsized_array()); + + make_register( + ir_meta, + OpCode::Unary(UnaryOpCode::ArrayLength, operand), + TYPE_ID_INT, + precision::array_length(), + ) +} + +// Evaluate -operand +// +// Result type: Same as operand's +// Result precision: Same as operand's +pub fn negate(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + promote::negate, + precision::negate, + |_, operand, _| OpCode::Unary(UnaryOpCode::Negate, operand), + const_fold::negate, + ) +} + +// Evaluate operand++ +// +// Result type: Same as operand's +// Result precision: Same as operand's +pub fn postfix_increment(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + promote::postfix_increment, + precision::postfix_increment, + |_, operand, _| OpCode::Unary(UnaryOpCode::PostfixIncrement, operand), + |_, _, _| panic!("Internal error: Operand of ++ cannot be a constant"), + ) +} + +// Evaluate operand-- +// +// Result type: Same as operand's +// Result precision: Same as operand's +pub fn postfix_decrement(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + promote::postfix_decrement, + precision::postfix_decrement, + |_, operand, _| OpCode::Unary(UnaryOpCode::PostfixDecrement, operand), + |_, _, _| panic!("Internal error: Operand of -- cannot be a constant"), + ) +} + +// Evaluate ++operand +// +// Result type: Same as operand's +// Result precision: Same as operand's +pub fn prefix_increment(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + promote::prefix_increment, + precision::prefix_increment, + |_, operand, _| OpCode::Unary(UnaryOpCode::PrefixIncrement, operand), + |_, _, _| panic!("Internal error: Operand of ++ cannot be a constant"), + ) +} + +// Evaluate --operand +// +// Result type: Same as operand's +// Result precision: Same as operand's +pub fn prefix_decrement(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + promote::prefix_decrement, + precision::prefix_decrement, + |_, operand, _| OpCode::Unary(UnaryOpCode::PrefixDecrement, operand), + |_, _, _| panic!("Internal error: Operand of -- cannot be a constant"), + ) +} + +// Evaluate operand1+operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector/matrix, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn add(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::add, + precision::add, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::Add, lhs, rhs), + const_fold::add, + ) +} + +// Evaluate operand1-operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector/matrix, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn sub(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::sub, + precision::sub, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::Sub, lhs, rhs), + const_fold::sub, + ) +} + +// Evaluate operand1*operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector/matrix, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn mul(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::mul, + precision::mul, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::Mul, lhs, rhs), + const_fold::mul, + ) +} + +// Evaluate operand1*operand2 +// +// Result type: Same as operand1. +// Result precision: Higher of the two operands. +pub fn vector_times_scalar(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + // Make sure the vector is operand1 + let (vector, scalar) = + if ir_meta.get_type(lhs.type_id).is_scalar() { (rhs, lhs) } else { (lhs, rhs) }; + + binary_op( + ir_meta, + vector, + scalar, + promote::vector_times_scalar, + precision::vector_times_scalar, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::VectorTimesScalar, lhs, rhs), + const_fold::mul, + ) +} + +// Evaluate operand1*operand2 +// +// Result type: Same as operand1. +// Result precision: Higher of the two operands. +pub fn matrix_times_scalar(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + // Make sure the matrix is operand1 + let (matrix, scalar) = + if ir_meta.get_type(lhs.type_id).is_scalar() { (rhs, lhs) } else { (lhs, rhs) }; + + binary_op( + ir_meta, + matrix, + scalar, + promote::matrix_times_scalar, + precision::matrix_times_scalar, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::MatrixTimesScalar, lhs, rhs), + const_fold::mul, + ) +} + +// Evaluate operand1*operand2 +// +// Result type: Vector of operand2's row count. +// Result precision: Higher of the two operands. +pub fn vector_times_matrix(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::vector_times_matrix, + precision::vector_times_matrix, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::VectorTimesMatrix, lhs, rhs), + const_fold::vector_times_matrix, + ) +} + +// Evaluate operand1*operand2 +// +// Result type: operand1's column type. +// Result precision: Higher of the two operands. +pub fn matrix_times_vector(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::matrix_times_vector, + precision::matrix_times_vector, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::MatrixTimesVector, lhs, rhs), + const_fold::matrix_times_vector, + ) +} + +// Evaluate operand1*operand2 +// +// Result type: matrix with operand2's column count of operand1's column type. +// Result precision: Higher of the two operands. +pub fn matrix_times_matrix(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::matrix_times_matrix, + precision::matrix_times_matrix, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::MatrixTimesMatrix, lhs, rhs), + const_fold::matrix_times_matrix, + ) +} + +// Evaluate operand1/operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector/matrix, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn div(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::div, + precision::div, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::Div, lhs, rhs), + const_fold::div, + ) +} + +// Evaluate operand1%operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn imod(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::imod, + precision::imod, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::IMod, lhs, rhs), + const_fold::imod, + ) +} + +// Evaluate !operand +// +// Result type: Same as operand (bool) +// Result precision: Not applicable +pub fn logical_not(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + // If ! is applied to an instruction that already has a !, use the original instead. + if let Id::Register(register_id) = operand.id { + let operand_instruction = ir_meta.get_instruction(register_id); + if let OpCode::Unary(UnaryOpCode::LogicalNot, original) = operand_instruction.op { + return Result::NoOp(original); + } + } + + unary_op( + ir_meta, + operand, + |_, _| TYPE_ID_BOOL, + precision::logical_not, + |_, operand, _| OpCode::Unary(UnaryOpCode::LogicalNot, operand), + const_fold::logical_not, + ) +} + +// Evaluate operand1^^operand2 +// +// Result type: Same as operand1 and operand2 (bool) +// Result precision: Not applicable +pub fn logical_xor(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::logical_xor, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::LogicalXor, lhs, rhs), + const_fold::logical_xor, + ) +} + +// Evaluate operand1==operand2 +// +// Result type: bool +// Result precision: Not applicable +pub fn equal(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::equal, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::Equal, lhs, rhs), + const_fold::equal, + ) +} + +// Evaluate operand1!=operand2 +// +// Result type: bool +// Result precision: Not applicable +pub fn not_equal(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::not_equal, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::NotEqual, lhs, rhs), + const_fold::not_equal, + ) +} + +// Evaluate operand1 Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::less_than, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::LessThan, lhs, rhs), + const_fold::less_than, + ) +} + +// Evaluate operand1>operand2 +// +// Result type: bool +// Result precision: Not applicable +pub fn greater_than(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::greater_than, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::GreaterThan, lhs, rhs), + const_fold::greater_than, + ) +} + +// Evaluate operand1<=operand2 +// +// Result type: bool +// Result precision: Not applicable +pub fn less_than_equal(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::less_than_equal, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::LessThanEqual, lhs, rhs), + const_fold::less_than_equal, + ) +} + +// Evaluate operand1>=operand2 +// +// Result type: bool +// Result precision: Not applicable +pub fn greater_than_equal(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + |_, _, _| TYPE_ID_BOOL, + precision::greater_than_equal, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::GreaterThanEqual, lhs, rhs), + const_fold::greater_than_equal, + ) +} + +// Evaluate ~operand +// +// Result type: Same as operand +// Result precision: Same as operand +pub fn bitwise_not(ir_meta: &mut IRMeta, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + promote::bitwise_not, + precision::bitwise_not, + |_, operand, _| OpCode::Unary(UnaryOpCode::BitwiseNot, operand), + const_fold::bitwise_not, + ) +} + +// Evaluate operand1< Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::bit_shift_left, + precision::bit_shift_left, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::BitShiftLeft, lhs, rhs), + const_fold::bit_shift_left, + ) +} + +// Evaluate operand1>>operand2 +// +// Result type: Same as operand1 +// Result precision: Same as operand1 +pub fn bit_shift_right(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::bit_shift_right, + precision::bit_shift_right, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::BitShiftRight, lhs, rhs), + const_fold::bit_shift_right, + ) +} + +// Evaluate operand1|operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn bitwise_or(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::bitwise_or, + precision::bitwise_or, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::BitwiseOr, lhs, rhs), + const_fold::bitwise_or, + ) +} + +// Evaluate operand1^operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn bitwise_xor(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::bitwise_xor, + precision::bitwise_xor, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::BitwiseXor, lhs, rhs), + const_fold::bitwise_xor, + ) +} + +// Evaluate operand1&operand2 +// +// Result type: Same as operand1, unless it's a scalar and operand2 is a vector, +// in which case same as operand2. +// Result precision: Higher of the two operands. +pub fn bitwise_and(ir_meta: &mut IRMeta, lhs: TypedId, rhs: TypedId) -> Result { + binary_op( + ir_meta, + lhs, + rhs, + promote::bitwise_and, + precision::bitwise_and, + |_, lhs, rhs| OpCode::Binary(BinaryOpCode::BitwiseAnd, lhs, rhs), + const_fold::bitwise_and, + ) +} + +// Evaluate built_in(operand) +// +// Result type: Typically same as operand's but with exceptions. See the GLSL ES spec. +// Result precision: Typically same as operand's but with exceptions. See the GLSL ES spec. +pub fn built_in_unary(ir_meta: &mut IRMeta, op: UnaryOpCode, operand: TypedId) -> Result { + unary_op( + ir_meta, + operand, + |ir_meta, operand_type| promote::built_in_unary(ir_meta, op, operand_type), + |operand_precision| precision::built_in_unary(op, operand_precision), + |_, operand, _| OpCode::Unary(op, operand), + |ir_meta, constant_id, result_type_id| { + const_fold::built_in_unary(ir_meta, op, constant_id, result_type_id) + }, + ) +} + +// Evaluate built_in(operand1, operand2) +// +// Result type: Depends on the built-in. See the GLSL ES spec. +// Result precision: Typically the higher of operand1's and operand2's but with exceptions. See the +// GLSL ES spec. +pub fn built_in_binary( + ir_meta: &mut IRMeta, + op: BinaryOpCode, + operand1: TypedId, + operand2: TypedId, +) -> Result { + binary_op( + ir_meta, + operand1, + operand2, + |ir_meta, operand1_type, operand2_type| { + promote::built_in_binary(ir_meta, op, operand1_type, operand2_type) + }, + |operand1_precision, operand2_precision| { + precision::built_in_binary(op, operand1_precision, operand2_precision) + }, + |_, operand1, operand2| OpCode::Binary(op, operand1, operand2), + |ir_meta, constant1_id, constant2_id, result_type_id| { + const_fold::built_in_binary(ir_meta, op, constant1_id, constant2_id, result_type_id) + }, + ) +} + +// Evaluate built_in(operands...) +// +// Result type: Depends on the built-in. See the GLSL ES spec. +// Result precision: Typically the higher of operand1's and operand2's but with exceptions. See the +// GLSL ES spec. +pub fn built_in(ir_meta: &mut IRMeta, op: BuiltInOpCode, operands: Vec) -> Result { + let result_type_id = promote::built_in(ir_meta, op, &mut operands.iter().map(|id| id.type_id)); + let precision = (result_type_id != TYPE_ID_VOID) + .then(|| precision::built_in(op, &mut operands.iter().map(|id| id.precision))); + + // If all operands are constant, constant fold the operation + if op.may_const_fold() && operands.iter().all(|id| id.id.is_constant()) { + // Note: No built-in that returns `void` can possibly take all-constant arguments. + debug_assert!(result_type_id != TYPE_ID_VOID); + + let constants = operands.iter().map(|id| id.id.get_constant().unwrap()).collect(); + let folded = const_fold::built_in(ir_meta, op, constants, result_type_id); + make_constant(folded, result_type_id, precision.unwrap()) + } else { + // Otherwise make an instruction + let op = OpCode::BuiltIn(op, operands); + + if result_type_id != TYPE_ID_VOID { + make_register(ir_meta, op, result_type_id, precision.unwrap()) + } else { + // If there is no result, make a void instruction + Result::Void(op) + } + } +} + +// Evaluate texture*(operands...) +// +// Result type: Typically vec4 with the same basic type as the sampler, or float if "compare". See +// the GLSL ES spec. Result precision: Same as the sampler operand. See the GLSL ES spec. +pub fn built_in_texture( + ir_meta: &mut IRMeta, + op: TextureOpCode, + sampler: TypedId, + coord: TypedId, +) -> Result { + let result_type_id = promote::built_in_texture(ir_meta, &op, sampler.type_id); + + // Constant folding is impossible, as the sampler cannot be a constant. + debug_assert!(sampler.id.get_constant().is_none()); + + // Make an instruction + let precision = precision::built_in_texture(&op, sampler.precision); + let op = OpCode::Texture(op, sampler, coord); + make_register(ir_meta, op, result_type_id, precision) +} diff --git a/src/compiler/translator/ir/src/ir.rs b/src/compiler/translator/ir/src/ir.rs new file mode 100644 index 00000000000..0867ebb0253 --- /dev/null +++ b/src/compiler/translator/ir/src/ir.rs @@ -0,0 +1,2901 @@ +// 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. +// +// The IR itself, consisting of a number of enums and structs. + +use super::instruction; +use std::collections::{HashMap, HashSet}; + +// Strong types for ids that refer to constants, registers, variables, types etc. They are used to +// look information up in different tables. In all cases, 0 means no applicable ID. +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct RegisterId { + pub id: u32, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct ConstantId { + pub id: u32, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct VariableId { + pub id: u32, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct FunctionId { + pub id: u32, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct TypeId { + pub id: u32, +} + +// Fixed enums for faster type lookup +// Note: if more types are added here or the values are changed, adjust MAX_PREDEFINED_TYPE_ID. +// TODO(http://anglebug.com/349994211): In the future, we can duplicate the reserved ids in an +// enum, so that static types, autogen'ed symbols etc already know their (type) ids. +pub const TYPE_ID_VOID: TypeId = TypeId { id: 0 }; +pub const TYPE_ID_FLOAT: TypeId = TypeId { id: 1 }; +pub const TYPE_ID_INT: TypeId = TypeId { id: 2 }; +pub const TYPE_ID_UINT: TypeId = TypeId { id: 3 }; +pub const TYPE_ID_BOOL: TypeId = TypeId { id: 4 }; +pub const TYPE_ID_ATOMIC_COUNTER: TypeId = TypeId { id: 5 }; +pub const TYPE_ID_YUV_CSC_STANDARD: TypeId = TypeId { id: 6 }; +// Note: vector type ids must be consecutive +pub const TYPE_ID_VEC2: TypeId = TypeId { id: 7 }; +pub const TYPE_ID_VEC3: TypeId = TypeId { id: 8 }; +pub const TYPE_ID_VEC4: TypeId = TypeId { id: 9 }; +pub const TYPE_ID_IVEC2: TypeId = TypeId { id: 10 }; +pub const TYPE_ID_IVEC3: TypeId = TypeId { id: 11 }; +pub const TYPE_ID_IVEC4: TypeId = TypeId { id: 12 }; +pub const TYPE_ID_UVEC2: TypeId = TypeId { id: 13 }; +pub const TYPE_ID_UVEC3: TypeId = TypeId { id: 14 }; +pub const TYPE_ID_UVEC4: TypeId = TypeId { id: 15 }; +pub const TYPE_ID_BVEC2: TypeId = TypeId { id: 16 }; +pub const TYPE_ID_BVEC3: TypeId = TypeId { id: 17 }; +pub const TYPE_ID_BVEC4: TypeId = TypeId { id: 18 }; +// Note: matrix type ids must be consecutive in rows, then columns +pub const TYPE_ID_MAT2: TypeId = TypeId { id: 19 }; +pub const TYPE_ID_MAT2X3: TypeId = TypeId { id: 20 }; +pub const TYPE_ID_MAT2X4: TypeId = TypeId { id: 21 }; +pub const TYPE_ID_MAT3X2: TypeId = TypeId { id: 22 }; +pub const TYPE_ID_MAT3: TypeId = TypeId { id: 23 }; +pub const TYPE_ID_MAT3X4: TypeId = TypeId { id: 24 }; +pub const TYPE_ID_MAT4X2: TypeId = TypeId { id: 25 }; +pub const TYPE_ID_MAT4X3: TypeId = TypeId { id: 26 }; +pub const TYPE_ID_MAT4: TypeId = TypeId { id: 27 }; +const MAX_PREDEFINED_TYPE_ID: u32 = TYPE_ID_MAT4.id; + +// Fixed enums for bool constants to avoid tracking whether they are defined or not, plus other +// constants for convenience. +// Note: if more constants are added here or the values are changed, adjust +// MAX_PREDEFINED_CONSTANT_ID. +pub const CONSTANT_ID_FALSE: ConstantId = ConstantId { id: 0 }; +pub const CONSTANT_ID_TRUE: ConstantId = ConstantId { id: 1 }; +pub const CONSTANT_ID_FLOAT_ZERO: ConstantId = ConstantId { id: 2 }; +pub const CONSTANT_ID_FLOAT_ONE: ConstantId = ConstantId { id: 3 }; +pub const CONSTANT_ID_INT_ZERO: ConstantId = ConstantId { id: 4 }; +pub const CONSTANT_ID_INT_ONE: ConstantId = ConstantId { id: 5 }; +pub const CONSTANT_ID_UINT_ZERO: ConstantId = ConstantId { id: 6 }; +pub const CONSTANT_ID_UINT_ONE: ConstantId = ConstantId { id: 7 }; +pub const CONSTANT_ID_YUV_CSC_ITU601: ConstantId = ConstantId { id: 8 }; +pub const CONSTANT_ID_YUV_CSC_ITU601_FULL_RANGE: ConstantId = ConstantId { id: 9 }; +pub const CONSTANT_ID_YUV_CSC_ITU709: ConstantId = ConstantId { id: 10 }; +const MAX_PREDEFINED_CONSTANT_ID: u32 = CONSTANT_ID_YUV_CSC_ITU709.id; + +// Prefixes used for symbols. +pub const USER_SYMBOL_PREFIX: &str = "_u"; +pub const TEMP_VARIABLE_PREFIX: &str = "t"; +pub const TEMP_FUNCTION_PREFIX: &str = "f"; +pub const TEMP_STRUCT_PREFIX: &str = "s"; +pub const TEMP_STRUCT_FIELD_PREFIX: &str = "m"; +// Make sure ANGLE symbols start with this to avoid collision with the user symbol prefixes above. +pub const ANGLE_SYMBOL_PREFIX: &str = "ANGLE"; + +// An ID that can be referred to by an operand of an instruction. +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Id { + Register(RegisterId), + Constant(ConstantId), + Variable(VariableId), +} + +impl Id { + pub fn new_register(id: RegisterId) -> Id { + Id::Register(id) + } + pub fn new_constant(id: ConstantId) -> Id { + Id::Constant(id) + } + pub fn new_variable(id: VariableId) -> Id { + Id::Variable(id) + } + + pub fn is_register(&self) -> bool { + matches!(self, Id::Register(_)) + } + pub fn is_constant(&self) -> bool { + matches!(self, Id::Constant(_)) + } + pub fn is_variable(&self) -> bool { + matches!(self, Id::Variable(_)) + } + + pub fn get_register(&self) -> RegisterId { + match self { + &Id::Register(id) => id, + _ => { + panic!("Internal error: unexpected non-register id"); + } + } + } + + pub fn get_constant(&self) -> Option { + match self { + &Id::Constant(id) => Some(id), + _ => None, + } + } +} + +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct TypedId { + pub id: Id, + pub type_id: TypeId, + pub precision: Precision, +} + +impl TypedId { + pub fn new(id: Id, type_id: TypeId, precision: Precision) -> TypedId { + TypedId { id, type_id, precision } + } + + pub fn from_constant_id(id: ConstantId, type_id: TypeId) -> TypedId { + TypedId { id: Id::new_constant(id), type_id, precision: Precision::NotApplicable } + } + pub fn from_typed_constant_id(constant_id: TypedConstantId) -> TypedId { + TypedId { + id: Id::new_constant(constant_id.id), + type_id: constant_id.type_id, + precision: constant_id.precision, + } + } + + pub fn from_register_id(register_id: TypedRegisterId) -> TypedId { + TypedId { + id: Id::new_register(register_id.id), + type_id: register_id.type_id, + precision: register_id.precision, + } + } + + pub fn as_register_id(&self) -> TypedRegisterId { + TypedRegisterId { + id: self.id.get_register(), + type_id: self.type_id, + precision: self.precision, + } + } + + pub fn from_bool_variable_id(id: VariableId) -> TypedId { + Self::new(Id::new_variable(id), TYPE_ID_BOOL, Precision::NotApplicable) + } + + pub fn from_variable_id(ir_meta: &IRMeta, id: VariableId) -> TypedId { + let variable = ir_meta.get_variable(id); + Self::new(Id::new_variable(id), variable.type_id, variable.precision) + } + + // Replace id with whatever it is aliasing (if any). The precision is retained, and the type + // should match the alias already. + pub fn dealias(&mut self, alias_map: &HashMap) { + if let Id::Register(register_id) = self.id { + alias_map.get(®ister_id).inspect(|&mapped| { + self.id = *mapped; + }); + } + } +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum UnaryOpCode { + // Get the array length of a pointer. The result is an `int` per GLSL. + // %result = ArrayLength %ptr + ArrayLength, + + // Calculate -operand. + // %result = Negate %operand + Negate, + + // Calculate !operand. + // %result = LogicalNot %operand + LogicalNot, + + // Calculate ~operand + // %result = BitwiseNot %operand + BitwiseNot, + + // Calculate ++operand, --operand, operand++ and operand--. The operand must be a pointer. + // %result = PrefixIncrement %operand + // %result = PrefixDecrement %operand + // %result = PostfixIncrement %operand + // %result = PostfixDecrement %operand + PrefixIncrement, + PrefixDecrement, + PostfixIncrement, + PostfixDecrement, + + // Unary built-ins with the same name in GLSL + Radians, + Degrees, + Sin, + Cos, + Tan, + Asin, + Acos, + Atan, + Sinh, + Cosh, + Tanh, + Asinh, + Acosh, + Atanh, + Exp, + Log, + Exp2, + Log2, + Sqrt, + Inversesqrt, + Abs, + Sign, + Floor, + Trunc, + Round, + RoundEven, + Ceil, + Fract, + Isnan, + Isinf, + FloatBitsToInt, + FloatBitsToUint, + IntBitsToFloat, + UintBitsToFloat, + PackSnorm2x16, + PackHalf2x16, + UnpackSnorm2x16, + UnpackHalf2x16, + PackUnorm2x16, + UnpackUnorm2x16, + PackUnorm4x8, + PackSnorm4x8, + UnpackUnorm4x8, + UnpackSnorm4x8, + Length, + Normalize, + Transpose, + Determinant, + Inverse, + Any, + All, + Not, + BitfieldReverse, + BitCount, + FindLSB, + FindMSB, + DFdx, + DFdy, + Fwidth, + InterpolateAtCentroid, + AtomicCounter, // The parameter is a pointer + AtomicCounterIncrement, // The parameter is a pointer + AtomicCounterDecrement, // The parameter is a pointer + ImageSize, + PixelLocalLoadANGLE, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BinaryOpCode { + // Calculate operand1 + operand2. + // %result = Add %operand1 %operand2 + Add, + // Calculate operand1 - operand2. + // %result = Sub %operand1 %operand2 + Sub, + // Calculate operand1 * operand2. + // %result = Mul %operand1 %operand2 + Mul, + // Calculate operand1 * operand2, where operand1 is a float vector and operand2 is a scalar. + // %result = VectorTimesScalar %operand1 %operand2 + VectorTimesScalar, + // Calculate operand1 * operand2, where operand1 is a matrix and operand2 is a scalar. + // %result = MatrixTimesScalar %operand1 %operand2 + MatrixTimesScalar, + // Calculate operand1 * operand2, where operand1 is a vector and operand2 is a matrix. + // %result = VectorTimesMatrix %operand1 %operand2 + VectorTimesMatrix, + // Calculate operand1 * operand2, where operand1 is a matrix and operand2 is a vector. + // %result = MatrixTimesVector %operand1 %operand2 + MatrixTimesVector, + // Calculate operand1 * operand2, where operand1 is a matrix and operand2 is a matrix. + // %result = MatrixTimesMatrix %operand1 %operand2 + MatrixTimesMatrix, + + // Calculate operand1 / operand2. + // %result = Div %operand1 %operand2 + Div, + // Calculate operand1 % operand2. + // %result = IMod %operand1 %operand2 + IMod, + + // Calculate operand1 ^^ operand2. + // %result = LogicalXor %operand1 %operand2 + LogicalXor, + + // Calculate operand1 == operand2. + // %result = Equal %operand1 %operand2 + Equal, + // Calculate operand1 != operand2. + // %result = NotEqual %operand1 %operand2 + NotEqual, + // Calculate operand1 < operand2. + // %result = LessThan %operand1 %operand2 + LessThan, + // Calculate operand1 > operand2. + // %result = GreaterThan %operand1 %operand2 + GreaterThan, + // Calculate operand1 <= operand2. + // %result = LessThanEqual %operand1 %operand2 + LessThanEqual, + // Calculate operand1 >= operand2. + // %result = GreaterThanEqual %operand1 %operand2 + GreaterThanEqual, + + // Calculate operand1 << operand2. + // %result = BitShiftLeft %operand1 %operand2 + BitShiftLeft, + // Calculate operand1 >> operand2. + // %result = BitShiftRight %operand1 %operand2 + BitShiftRight, + // Calculate operand1 | operand2. + // %result = BitwiseOr %operand1 %operand2 + BitwiseOr, + // Calculate operand1 ^ operand2. + // %result = BitwiseXor %operand1 %operand2 + BitwiseXor, + // Calculate operand1 & operand2. + // %result = BitwiseAnd %operand1 %operand2 + BitwiseAnd, + + // Binary built-ins with the same name in GLSL + Atan, + Pow, + Mod, + Min, + Max, + Step, + Modf, // Second parameter is a pointer + Frexp, // Second paarameter is a pointer + Ldexp, + Distance, + Dot, + Cross, + Reflect, + MatrixCompMult, + OuterProduct, + LessThanVec, + LessThanEqualVec, + GreaterThanVec, + GreaterThanEqualVec, + EqualVec, + NotEqualVec, + InterpolateAtSample, + InterpolateAtOffset, + AtomicAdd, // First parameter is a pointer + AtomicMin, // First parameter is a pointer + AtomicMax, // First parameter is a pointer + AtomicAnd, // First parameter is a pointer + AtomicOr, // First parameter is a pointer + AtomicXor, // First parameter is a pointer + AtomicExchange, // First parameter is a pointer +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BuiltInOpCode { + // GLSL built-ins with the same name. Most built-ins with one or two parameters are found in + // UnaryOpCode and BinaryOpCode, but the ones with any other number of parameters are placed + // here, as well as a few that don't really fit a "unary" or "binary" built-in. Texture + // sampling built-ins are specially handled in `OpCode`. + Clamp, + Mix, + Smoothstep, + Fma, + Faceforward, + Refract, + BitfieldExtract, + BitfieldInsert, + UaddCarry, // The third parameter is a pointer + UsubBorrow, // The third parameter is a pointer + UmulExtended, // The third and fourth parameters are pointers + ImulExtended, // The third and fourth parameters are pointers + TextureSize, + TextureQueryLod, + TexelFetch, + TexelFetchOffset, + Rgb2Yuv, + Yuv2Rgb, + AtomicCompSwap, + ImageStore, + ImageLoad, + ImageAtomicAdd, + ImageAtomicMin, + ImageAtomicMax, + ImageAtomicAnd, + ImageAtomicOr, + ImageAtomicXor, + ImageAtomicExchange, + ImageAtomicCompSwap, + PixelLocalStoreANGLE, + MemoryBarrier, + MemoryBarrierAtomicCounter, + MemoryBarrierBuffer, + MemoryBarrierImage, + // Note: barrier() semantics in CS and TCS are different. + Barrier, + MemoryBarrierShared, + GroupMemoryBarrier, + EmitVertex, + EndPrimitive, + + // Vulkan GLSL built-in + SubpassLoad, + + // Desktop GLSL built-ins + BeginInvocationInterlockNV, + EndInvocationInterlockNV, + BeginFragmentShaderOrderingINTEL, + BeginInvocationInterlockARB, + EndInvocationInterlockARB, + + // MSL built-in + NumSamples, + SamplePosition, + InterpolateAtCenter, + LoopForwardProgress, + Saturate, + // TODO(http://anglebug.com/349994211): We could add one op for each internal function call + // (EOpCallInternalRawFunction). Won't be needed for SPIR-V, but maybe for others. Ideally, + // they should all be converted to something that can be represented in the IR instead, but + // basically they could be added here as some form of built-in. +} + +impl BuiltInOpCode { + // Normally, a built-in with all-constant parameters can be constant folded. That is true for + // all opcodes in UnaryOpCode and BinaryOpCode, but BuiltInOpCode has a few exceptions, such as + // barriers (no arguments) or SamplePosition (an MSL built-in). + pub fn may_const_fold(&self) -> bool { + match self { + BuiltInOpCode::Clamp + | BuiltInOpCode::Mix + | BuiltInOpCode::Smoothstep + | BuiltInOpCode::Fma + | BuiltInOpCode::Faceforward + | BuiltInOpCode::Refract + | BuiltInOpCode::BitfieldExtract + | BuiltInOpCode::BitfieldInsert + | BuiltInOpCode::Rgb2Yuv + | BuiltInOpCode::Yuv2Rgb => true, + BuiltInOpCode::UaddCarry + | BuiltInOpCode::UsubBorrow + | BuiltInOpCode::UmulExtended + | BuiltInOpCode::ImulExtended + | BuiltInOpCode::TextureSize + | BuiltInOpCode::TextureQueryLod + | BuiltInOpCode::TexelFetch + | BuiltInOpCode::TexelFetchOffset + | BuiltInOpCode::AtomicCompSwap + | BuiltInOpCode::ImageStore + | BuiltInOpCode::ImageLoad + | BuiltInOpCode::ImageAtomicAdd + | BuiltInOpCode::ImageAtomicMin + | BuiltInOpCode::ImageAtomicMax + | BuiltInOpCode::ImageAtomicAnd + | BuiltInOpCode::ImageAtomicOr + | BuiltInOpCode::ImageAtomicXor + | BuiltInOpCode::ImageAtomicExchange + | BuiltInOpCode::ImageAtomicCompSwap + | BuiltInOpCode::PixelLocalStoreANGLE + | BuiltInOpCode::MemoryBarrier + | BuiltInOpCode::MemoryBarrierAtomicCounter + | BuiltInOpCode::MemoryBarrierBuffer + | BuiltInOpCode::MemoryBarrierImage + | BuiltInOpCode::Barrier + | BuiltInOpCode::MemoryBarrierShared + | BuiltInOpCode::GroupMemoryBarrier + | BuiltInOpCode::EmitVertex + | BuiltInOpCode::EndPrimitive + | BuiltInOpCode::SubpassLoad + | BuiltInOpCode::BeginInvocationInterlockNV + | BuiltInOpCode::EndInvocationInterlockNV + | BuiltInOpCode::BeginFragmentShaderOrderingINTEL + | BuiltInOpCode::BeginInvocationInterlockARB + | BuiltInOpCode::EndInvocationInterlockARB + | BuiltInOpCode::NumSamples + | BuiltInOpCode::SamplePosition + | BuiltInOpCode::InterpolateAtCenter + | BuiltInOpCode::LoopForwardProgress + | BuiltInOpCode::Saturate => false, + } + } +} + +// `texture*()` built-ins have many variants. To reduce chances of mistakes, the variants are +// specifically spelled out with named arguments. +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum TextureOpCode { + Implicit { is_proj: bool, offset: Option }, + Compare { compare: TypedId }, + Lod { is_proj: bool, lod: TypedId, offset: Option }, + CompareLod { compare: TypedId, lod: TypedId }, + Bias { is_proj: bool, bias: TypedId, offset: Option }, + CompareBias { compare: TypedId, bias: TypedId }, + Grad { is_proj: bool, dx: TypedId, dy: TypedId, offset: Option }, + Gather { offset: Option }, + GatherComponent { component: TypedId, offset: Option }, + GatherRef { refz: TypedId, offset: Option }, +} + +// The opcode of an instruction together with its possible operands. The `result`, if applicable, +// is always specified in the `Instruction` struct. +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum OpCode { + // A special op to indicate that a register is an input to a merge block. Not to be used + // directly in blocks, this instruction is a marker for the global list of instructions in + // `IRMeta::instructions`. + MergeInput, + + // Discard the fragment (fragment shader only). + // Discard + Discard, + // Return from the function, optionally with one value. + // Return [%value] + Return(Option), + // Break from a loop or switch. + // Break + Break, + // Continue a loop. + // Continue + Continue, + // Passthrough from one case label to the next. + // Passthrough + Passthrough, + // Jump to next block, effectively concatenating it with the current block. + // NextBlock + NextBlock, + // Jump to merge block, optionally with one value. + // Merge [%value] + Merge(Option), + // Jump to a branch of if/else. + // If %condition + If(TypedId), + // Marking the beginning of a loop, jumps to the block that evaluates the condition of the + // loop (which should terminate in a `LoopIf`). If the condition block's `LoopIf` condition + // is true, that block jumps to the body of loop or the merge block otherwise. For and + // while loops can be distinguished by the presence of a "continue" block in Block. The + // body of the loop itself must terminate with `Continue` (if not otherwise terminated + // with `Break`, `Return` etc). The continue block itself, if any, should also terminate + // with `Continue`, though that's immaterial (as there cannot be any other terminator). + // Loop + Loop, + // Similarly to `Loop`, marks the beginning of a do-loop. Unlike `Loop`, the initial jump is + // to the body of the do-while loop. The body and condition blocks are similar to `Loop`. + // DoLoop + DoLoop, + // Jump to beginning of the body of the loop if the condition is true. + // LoopIf %condition + LoopIf(TypedId), + // Switch based on a condition and jump to any number of blocks based on matching values. The + // None value indicates the default block. + // Switch %condition %case_values... + Switch(TypedId, Vec>), + + // Extract a component of a vector into a scalar. + // %result = ExtractVectorComponent %vector %index + ExtractVectorComponent(TypedId, u32), + // Extract multiple components of a vector into another vector. + // %result = ExtractVectorComponentMulti %vector %indices... + ExtractVectorComponentMulti(TypedId, Vec), + // Extract a component of a vector dynamically. + // %result = ExtractVectorComponentDynamic %vector %index + ExtractVectorComponentDynamic(TypedId, TypedId), + // Extract a column of a matrix into a vector. + // %result = ExtractMatrixColumn %matrix %column + ExtractMatrixColumn(TypedId, TypedId), + // Extract a field of a struct. + // %result = ExtractStructField %struct %field_index + ExtractStructField(TypedId, u32), + // Extract an element of an array. + // %result = ExtractArrayElement %array %element_index + ExtractArrayElement(TypedId, TypedId), + + // Given a vector pointer, create an access to a scalar component. + // %result = AccessVectorComponent %vector_ptr %index + AccessVectorComponent(TypedId, u32), + // Access multiple components of a vector into another vector. + // %result = AccessVectorComponentMulti %vector_ptr %indices... + AccessVectorComponentMulti(TypedId, Vec), + // Access a component of a vector dynamically. + // %result = AccessVectorComponentDynamic %vector_ptr %index + AccessVectorComponentDynamic(TypedId, TypedId), + // Access a column of a matrix into a vector. + // %result = AccessMatrixColumn %matrix_ptr %column + AccessMatrixColumn(TypedId, TypedId), + // Access a field of a struct. + // %result = AccessStructField %struct_ptr %field_index + AccessStructField(TypedId, u32), + // Access an element of an array. + // %result = AccessArrayElement %array_ptr %element_index + AccessArrayElement(TypedId, TypedId), + + // Given a scalar, construct a scalar with a different type (effectively a cast). + // %result = ConstructScalarFromScalar %value + ConstructScalarFromScalar(TypedId), + // Given a scalar, construct a vector by replicating it. The basic type is cast if + // necesseray. %result = ConstructVectorFromScalar %value + ConstructVectorFromScalar(TypedId), + // Given a scalar, construct a matrix where every element is 0 except on the diagonal, which + // is the given scalar. The basic type is cast if necessary. + // %result = ConstructMatrixFromScalar %value + ConstructMatrixFromScalar(TypedId), + // Given a matrix of size AxB, construct a matrix of size NxM as such: + // + // * Take C to be the minimum of A and N + // * Take R to be ghe minimum of B and M + // * The resulting matrix is the identity matrix of size NxM with the CxR submatrix of the + // input matrix superimposed. + // + // In effect, this means that if the result matrix is smaller than the input matrix, the + // result is a submatrix of the input. If it is larger, it is padded with 1s on the + // diagonal and 0s elsewhere. + // %result = ConstructMatrixFromMatrix %value + ConstructMatrixFromMatrix(TypedId), + // Given multiple values, construct a vector/matrix by piecing together components from these + // values. The total number of components in the values must match the number of components + // in the resulting vector. The basic type is cast if necesseray. + // %result = ConstructVectorFromMultiple %values... + // %result = ConstructMatrixFromMultiple %values... + ConstructVectorFromMultiple(Vec), + ConstructMatrixFromMultiple(Vec), + // Given values for each field of a struct, construct a value of that struct type. + // %result = ConstructStruct %fields... + ConstructStruct(Vec), + // Given values for each element of an array, construct a value of that array type. + // %result = ConstructArray %fields... + ConstructArray(Vec), + + // Load from a pointer. + // %result = Load %ptr + Load(TypedId), + // Assign to a pointer. + // Store %ptr %value + Store(TypedId, TypedId), + // Create a register alias for another id. Produced by transformations, makes it possible to + // make an existing register id use a different value (such as a constant, or another + // pre-existing register id). + // Alias %new %old + Alias(TypedId), + + // Call a function, optionally returning a result. + // [%result =] Call %function %operands... + Call(FunctionId, Vec), + + // Common arithmetic, logical and bitwise operations as well as most built-ins are bundled + // under the following. This makes it easier to inspect the ids of an instruction by reducing + // the need for numerous `match` arms. + // + // Lots of GLSL built-ins with one or two parameters are also found in these opcodes. + Unary(UnaryOpCode, TypedId), + Binary(BinaryOpCode, TypedId, TypedId), + + // GLSL built-ins that aren't a unary or binary operation. `texture*` built-ins are also + // separately specified. + BuiltIn(BuiltInOpCode, Vec), + + // Texture sampling built-ins have a number of variants. They are represented by the exact + // parameters they take in the IR. + // + // %result = Texture[Variant] %sampler %coord [%args...] + Texture(TextureOpCode, TypedId, TypedId), +} + +impl OpCode { + pub fn is_branch(&self) -> bool { + matches!( + *self, + OpCode::Discard + | OpCode::Return(_) + | OpCode::Break + | OpCode::Continue + | OpCode::Passthrough + | OpCode::NextBlock + | OpCode::Merge(_) + | OpCode::If(_) + | OpCode::Loop + | OpCode::DoLoop + | OpCode::LoopIf(_) + | OpCode::Switch(_, _) + ) + } + + pub fn get_if_condition(&self) -> TypedId { + match self { + &OpCode::If(id) => id, + _ => panic!("Internal error: Expected if"), + } + } + pub fn get_loop_condition(&self) -> TypedId { + match self { + &OpCode::LoopIf(id) => id, + _ => panic!("Internal error: Expected loop condition"), + } + } + pub fn get_merge_parameter(&self) -> Option { + match self { + &OpCode::Merge(id) => id, + _ => panic!("Internal error: Expected merge"), + } + } + pub fn get_switch_expression_and_cases(&self) -> (TypedId, &Vec>) { + match self { + OpCode::Switch(id, cases) => (*id, cases), + _ => panic!("Internal error: Expected switch"), + } + } + pub fn add_switch_case(&mut self, value: Option) { + match self { + OpCode::Switch(_, values) => values.push(value), + _ => panic!("Internal error: Expected switch"), + }; + } +} + +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct TypedConstantId { + pub id: ConstantId, + pub type_id: TypeId, + // Note that while constants don't have a precision, there may be one assigned to them in the + // intermediate ops due to load from `const` variables. + pub precision: Precision, +} + +impl TypedConstantId { + pub fn new(id: ConstantId, type_id: TypeId, precision: Precision) -> TypedConstantId { + TypedConstantId { id, type_id, precision } + } +} + +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct TypedRegisterId { + pub id: RegisterId, + pub type_id: TypeId, + pub precision: Precision, +} + +impl TypedRegisterId { + pub fn new(id: RegisterId, type_id: TypeId, precision: Precision) -> TypedRegisterId { + TypedRegisterId { id, type_id, precision } + } +} + +// Representation of an IR instruction. For example: +// +// %result = Operation %operand1 ... +// +// Most instructions have a result, but some don't (notably Store, void function calls and +// control-flow instructions). The instructions that don't have a result are directly stored in +// the blocks, but for convenience during visits and transformations, the instructions that have a +// result are indirectly referenced by the blocks, referenced by their result ID. +// +// The `Instruction` type associates a result ID with the instruction (that is otherwise just the +// `OpCode`). +// +// Associated with each result ID is a set of information, such as its type and precision. +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Instruction { + // The instruction opcode itself. + pub op: OpCode, + // The `result` of the operation. This is always a temporary (register) value. + pub result: TypedRegisterId, +} + +impl Instruction { + pub fn new(op: OpCode, result: TypedRegisterId) -> Instruction { + Instruction { op, result } + } +} + +// The entities in a block of the IR. They are either directly the opcodes themselves (if they +// don't have a result), or an indirect reference to `IRMeta::instructions` by the ID of the result +// they produce. +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BlockInstruction { + Void(OpCode), + Register(RegisterId), +} + +impl BlockInstruction { + pub fn new_void(op: OpCode) -> BlockInstruction { + BlockInstruction::Void(op) + } + + pub fn new_control_flow(op: OpCode) -> BlockInstruction { + BlockInstruction::Void(op) + } + + pub fn new_typed(id: RegisterId) -> BlockInstruction { + BlockInstruction::Register(id) + } + + pub fn is_branch(&self) -> bool { + match self { + BlockInstruction::Void(op) => op.is_branch(), + _ => false, + } + } + + // Convenience function to get the OpCode of the instruction no matter if Void or Register. + // The result (if available) is simultaneously returned. + pub fn get_op_and_result<'block, 'ir: 'block>( + &'block self, + ir: &'ir IRMeta, + ) -> (&'block OpCode, Option) { + match self { + BlockInstruction::Void(op) => (op, None), + &BlockInstruction::Register(id) => { + let instruction = ir.get_instruction(id); + (&instruction.op, Some(instruction.result)) + } + } + } +} + +// Representation of a block of instructions. There are no branch instructions inside a block, and +// every block ends with a branch instruction (if, for, return, etc). +// +// Every block may have an input +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Block { + // Some compilers do a bad job of register allocation, so the ANGLE IR supports scoping + // variables to blocks. This information is solely used during code generation for the purpose + // of declaring variables in the right scope. + pub variables: Vec, + + // The merge blocks may have an input, which is a more modern way of keeping the IR in SSA + // form compared with Phi instructions (and is easier to generate text with). ANGLE's IR uses + // variables (like SPIR-V) and only ever really uses one parameter with merge inputs, so it's + // not truly in SSA form. This could be avoided with temp variables, but having this support + // makes it easier to translate ?: or short-circuiting && or ||. ANGLE never produces blocks + // with more than one input. If SSA form is needed, it's sufficient to turn this into a vector + // so all temporary variables can be eliminated. + pub input: Option, + + // The instructions inside the block, the last one is always a branch instruction. + pub instructions: Vec, + + // The IR has the following branch instructions: + // + // - Discard: Terminates the current invocation of the fragment shader. + // - Return: Returns execution to the caller of this function, or terminates the shader if in + // `main()`. + // - Break: Break out of a loop or a switch case. + // * Branch is done to the `merge_block` of the innermost loop or switch block. + // - Continue: Continue to the beginning of the loop. + // * If the loop has a continue block, branch is done to `block2` of the innermost loop + // block. + // * If this is the continue block itself, or if there is no continue block in a loop, branch + // is done to the parent of the innermost loop block. That will always be the block that + // evaluates the loop condition. + // * If this is part of a do-loop, branch is done to the innermost do block. + // - Passthrough: Pass through from one switch case to another. + // * If this is `case_blocks[i]` in the innermost switch block, branch to `case_blocks[i+1]` + // of that block. + // - NextBlock: Continue to the next block of execution. This is useful to represent blocks + // that are split for various reasons; for example the condition block of a for loop that is + // separated from the instructions before it. + // * Branch is done to the `merge_block` of this block. + // - Merge: Branch to the merge block of the innermost control flow structure (if, loop, etc). + // - If: Based on condition: + // * Branch to `block1` if the condition is true. + // * Branch to `block2` if the condition is false. + // - Loop: + // * Branch to `loop_condition` first, which terminates in a `LoopIf`. + // * Branch to `block1` if the condition is true. + // * Branch to `merge_block` if the condition is false. + // * If there is a continue block, it is found in `block2`. + // - DoLoop: Identical to `Loop`, except branches to `block1` instead of `loop_condition`. + // - Switch: Given case values in `case_blocks`, where `None` denotes the `default` case, based + // on given expression: + // * Branch to `merge_block` if no matching cases and no default case exists. + // * Branch to `case_blocks[i]` if no matching cases and case expression `i` is `None`. + // * Branch to `case_blocks[i]` if case expression `i` is equal to the switch expression. + pub merge_block: Option>, + // `loop_condition` is the block that evaluates the loop condition. + pub loop_condition: Option>, + // `block1` is used for true block of `if` and body of loops. + pub block1: Option>, + // `block2` is used for false block of `if` and continue block of `for`. + pub block2: Option>, + // `case_blocks` contain the case blocks of `switch`. + pub case_blocks: Vec, +} + +impl Block { + pub fn new() -> Block { + Block { + variables: Vec::new(), + input: None, + instructions: Vec::with_capacity(8), + merge_block: None, + loop_condition: None, + block1: None, + block2: None, + case_blocks: Vec::new(), + } + } + + // Helpers used to create a function, one block at a time. Moves the intermediary block into a + // child block. + pub fn set_merge_block(&mut self, block: Block) { + debug_assert!(self.merge_block.is_none()); + self.merge_block = Some(Box::new(block)); + } + + pub fn set_sub_block1(&mut self, block: Block) { + debug_assert!(self.block1.is_none()); + self.block1 = Some(Box::new(block)); + } + + pub fn set_sub_block2(&mut self, block: Block) { + debug_assert!(self.block2.is_none()); + self.block2 = Some(Box::new(block)); + } + + pub fn set_if_true_block(&mut self, block: Block) { + self.set_sub_block1(block); + } + + pub fn set_if_false_block(&mut self, block: Block) { + self.set_sub_block2(block); + } + + pub fn set_loop_condition_block(&mut self, block: Block) { + debug_assert!(self.loop_condition.is_none()); + self.loop_condition = Some(Box::new(block)); + } + + pub fn set_loop_body_block(&mut self, block: Block) { + self.set_sub_block1(block); + } + + pub fn set_loop_continue_block(&mut self, block: Block) { + self.set_sub_block2(block); + } + + pub fn set_switch_case_blocks(&mut self, blocks: Vec) { + debug_assert!(self.case_blocks.is_empty()); + self.case_blocks = blocks; + } + + pub fn add_switch_case_block(&mut self, block: Block) { + self.case_blocks.push(block); + } + + pub fn set_sub_blocks( + &mut self, + loop_condition_block: Option, + block1: Option, + block2: Option, + case_blocks: Vec, + ) { + if let Some(block) = loop_condition_block { + self.set_loop_condition_block(block); + } + if let Some(block) = block1 { + self.set_sub_block1(block); + } + if let Some(block) = block2 { + self.set_sub_block2(block); + } + self.set_switch_case_blocks(case_blocks); + } + + // Takes a chain of blocks, and sets them as the merge chain of the current block. If the + // current block has a merge block of its own, it is set as the merge block of the given + // chain. Effectively, this inserts the given block right after this one. + // + // It returns the end of the _input_ merge chain after it is chained to the current block, + // letting the caller continue to the rest of the original merge chain (which can be found in + // the `merge_block` of the return value). + pub fn insert_into_merge_chain(&mut self, block: Block) -> &mut Block { + let original_merge_block = self.merge_block.take(); + self.set_merge_block(block); + + let result = self.get_merge_chain_last_block_mut(); + result.merge_block = original_merge_block; + result + } + + pub fn add_variable_declaration(&mut self, variable_id: VariableId) { + self.variables.push(variable_id); + } + + pub fn add_void_instruction(&mut self, op: OpCode) { + debug_assert!(!self.is_terminated()); + self.instructions.push(BlockInstruction::new_void(op)); + } + pub fn add_register_instruction(&mut self, id: RegisterId) { + debug_assert!(!self.is_terminated()); + self.instructions.push(BlockInstruction::new_typed(id)); + } + pub fn add_typed_instruction(&mut self, inst: instruction::Result) -> TypedId { + // Helper to add typed instruction created with the `instruction` helpers. Returns the id + // of the result, for use in future instructions. + match inst { + instruction::Result::Register(id) => { + self.instructions.push(BlockInstruction::new_typed(id.id)); + TypedId::from_register_id(id) + } + instruction::Result::Constant(id) => TypedId::from_typed_constant_id(id), + instruction::Result::NoOp(id) => id, + instruction::Result::Void(_) => panic!("Internal error: Expected typed instruction"), + } + } + pub fn add_instruction(&mut self, inst: instruction::Result) { + // Helper to add instruction created with the `instruction` helpers. + match inst { + instruction::Result::Void(op) => self.instructions.push(BlockInstruction::new_void(op)), + _ => { + self.add_typed_instruction(inst); + } + } + } + pub fn prepend_instruction(&mut self, inst: instruction::Result) { + // Special case of prepending an instruction to the list of instructions. Used in rare + // occasions, in particular to replace the merge block input with a variable load + // instruction for AST-ification. + self.add_instruction(inst); + self.instructions.rotate_right(1); + } + + pub fn prepend_code(&mut self, mut block: Block) { + // Prepend the code in `block` to the code in `self`. There may be other blocks that + // reference `self`, so this operation simply makes `self` the merge block of `block`, then + // swaps the contents of `self` and `block` to make existing references effectively point + // to the new code being prepended. + std::mem::swap(self, &mut block); + // If there's a merge input, it should remain in place. + std::mem::swap(&mut self.input, &mut block.input); + + let last_block = self.get_merge_chain_last_block_mut(); + last_block.terminate(OpCode::NextBlock); + // Note: after the above swap, `block` now contains what was previously in `self`. + last_block.set_merge_block(block); + } + + // Whether the block is already terminated. This is used for assertions, but also ensures that + // dead code after return/break/continue/etc is dropped automatically. + pub fn is_terminated(&self) -> bool { + self.instructions + .last() + .map(|instruction| match instruction { + BlockInstruction::Void(op) => op.is_branch(), + _ => false, + }) + .unwrap_or(false) + } + + pub fn terminate(&mut self, op: OpCode) { + self.add_void_instruction(op); + } + pub fn unterminate(&mut self) { + debug_assert!(self.is_terminated()); + self.instructions.pop(); + } + + // Return the branch op found at the end of this block. + pub fn get_terminating_op(&self) -> &OpCode { + match self.instructions.last().unwrap() { + BlockInstruction::Void(op) => op, + _ => panic!("Internal error: Expected terminated block"), + } + } + pub fn get_terminating_op_mut(&mut self) -> &mut OpCode { + match self.instructions.last_mut().unwrap() { + BlockInstruction::Void(op) => op, + _ => panic!("Internal error: Expected terminated block"), + } + } + + pub fn get_merge_chain_last_block(&self) -> &Block { + let mut last_block = self; + while let Some(ref merge_block) = last_block.merge_block { + last_block = merge_block; + } + last_block + } + + pub fn get_merge_chain_last_block_mut(&mut self) -> &mut Block { + let mut last_block = self; + while let Some(ref mut merge_block) = last_block.merge_block { + last_block = merge_block; + } + last_block + } + + // Return the branch op found at the end of the merge chain of this block. Useful for sub + // blocks of another block, for example to retrieve the terminating op of the loop condition. + pub fn get_merge_chain_terminating_op(&self) -> &OpCode { + self.get_merge_chain_last_block().get_terminating_op() + } + + // Run a closure on the sub blocks, excluding the merge block. + pub fn for_each_sub_block(&self, state: &mut State, visit: &Visit) + where + Visit: Fn(&mut State, &Self), + { + self.loop_condition.as_ref().inspect(|sub_block| visit(state, sub_block)); + self.block1.as_ref().inspect(|sub_block| visit(state, sub_block)); + self.block2.as_ref().inspect(|sub_block| visit(state, sub_block)); + self.case_blocks.iter().for_each(|sub_block| visit(state, sub_block)); + } + pub fn for_each_sub_block_mut( + &mut self, + state: &mut State, + transform: &Transform, + ) where + Transform: Fn(&mut State, &mut Self), + { + self.loop_condition.as_mut().map(|sub_block| transform(state, sub_block)); + self.block1.as_mut().map(|sub_block| transform(state, sub_block)); + self.block2.as_mut().map(|sub_block| transform(state, sub_block)); + self.case_blocks.iter_mut().for_each(|sub_block| transform(state, sub_block)); + } +} + +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum YuvCscStandard { + Itu601, + Itu601FullRange, + Itu709, +} + +// A constant is either a single value (float, int, uint or bool) or is a composite of other +// constant values. The type of the composite is specified in `Constant::type_id`. +#[derive(Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum ConstantValue { + Float(f32), + Int(i32), + Uint(u32), + Bool(bool), + YuvCsc(YuvCscStandard), + Composite(Vec), +} + +impl ConstantValue { + pub fn get_float(&self) -> f32 { + match *self { + ConstantValue::Float(f) => f, + _ => panic!("Internal error: Expected a float constant"), + } + } + + pub fn get_int(&self) -> i32 { + match *self { + ConstantValue::Int(i) => i, + _ => panic!("Internal error: Expected an int constant"), + } + } + + pub fn get_uint(&self) -> u32 { + match *self { + ConstantValue::Uint(u) => u, + _ => panic!("Internal error: Expected an unsigned int constant"), + } + } + + pub fn get_bool(&self) -> bool { + match *self { + ConstantValue::Bool(b) => b, + _ => panic!("Internal error: Expected a bool constant"), + } + } + + pub fn get_yuv_csc(&self) -> YuvCscStandard { + match *self { + ConstantValue::YuvCsc(s) => s, + _ => panic!("Internal error: Expected a yuvCscStandardEXT constant"), + } + } + + pub fn get_index(&self) -> u32 { + match *self { + ConstantValue::Int(i) => i as u32, + ConstantValue::Uint(u) => u, + _ => panic!("Internal error: Expected an index constant"), + } + } + + pub fn is_composite(&self) -> bool { + matches!(self, ConstantValue::Composite(_)) + } + + pub fn get_composite_elements(&self) -> &Vec { + match self { + ConstantValue::Composite(ids) => ids, + _ => panic!("Internal error: Attempt to query elements of a non-composite type"), + } + } +} + +// A constant value. Constant values are of a given type, and can composite accordingly. +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Constant { + pub type_id: TypeId, + pub value: ConstantValue, + pub is_dead_code_eliminated: bool, +} + +impl Constant { + pub fn new_bool(value: bool) -> Constant { + Constant { + type_id: TYPE_ID_BOOL, + value: ConstantValue::Bool(value), + is_dead_code_eliminated: false, + } + } + pub fn new_int(value: i32) -> Constant { + Constant { + type_id: TYPE_ID_INT, + value: ConstantValue::Int(value), + is_dead_code_eliminated: false, + } + } + pub fn new_uint(value: u32) -> Constant { + Constant { + type_id: TYPE_ID_UINT, + value: ConstantValue::Uint(value), + is_dead_code_eliminated: false, + } + } + pub fn new_float(value: f32) -> Constant { + Constant { + type_id: TYPE_ID_FLOAT, + value: ConstantValue::Float(value), + is_dead_code_eliminated: false, + } + } + pub fn new_yuv_csc(value: YuvCscStandard) -> Constant { + Constant { + type_id: TYPE_ID_YUV_CSC_STANDARD, + value: ConstantValue::YuvCsc(value), + is_dead_code_eliminated: false, + } + } + pub fn new_composite(type_id: TypeId, params: Vec) -> Constant { + Constant { + type_id, + value: ConstantValue::Composite(params), + is_dead_code_eliminated: false, + } + } +} + +// Where a name came from. This affects how it is output. +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum NameSource { + // A name in the shader itself, which corresponds to an interface variable (input, output, + // etc). The backend may rely on this name to be output with a certain prefix. + ShaderInterface, + // A name that must be output exactly, because: + // + // - It's an ANGLE-internal name, which should not collide with a shader name. + // - It's `main`. + Internal, + // A name that can freely be changed because it's internal to the shader. The output + // generator may try its best to retain it as-is, but without guarantees. + Temporary, +} + +// A name associated with a variable, struct, struct field etc. +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Name { + // This is a slice into the shader source, a static name, or otherwise an empty string. Either + // way (including when it's received as a string from FFI), it lives for the duration of the + // compilation, and so is considered 'static. + // TODO(http://anglebug.com/349994211): use [u8], BStr or std::ffi:CStr instead of str, Rust + // should never really access this, and having Unicode in the mix will either cause trouble or + // add binary size for no good reason. + pub name: &'static str, + // Whether the name has any significance other than being debug info. For example, it may be a + // name that needs to be output exactly in text because the backend/driver looks for it. + pub source: NameSource, +} + +impl Name { + // Create a temp name, it is not important if the name is exactly preserved in the output (for + // example, it's a temporary helper variable etc). Duplicate names are allowed, and will be + // made distinguishable if generating text. Temp names are optional, and might as well be "". + pub fn new_temp(name: &'static str) -> Name { + Name { name, source: NameSource::Temporary } + } + // A name that must be preserved in some predictable form in the output. This is useful for + // backends that reference this name directly, such as with OpenGL. + pub fn new_interface(name: &'static str) -> Name { + Name { name, source: NameSource::ShaderInterface } + } + // A name that must be preserved exactly in the output, for example `main`, or ANGLE internal + // interface variables. + pub fn new_exact(name: &'static str) -> Name { + Name { name, source: NameSource::Internal } + } +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum VariableScope { + Global, + Local, + FunctionParam, +} + +// Information surrounding a variable. +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Variable { + pub name: Name, + pub type_id: TypeId, + pub precision: Precision, + pub decorations: Decorations, + pub built_in: Option, + pub initializer: Option, + pub scope: VariableScope, + // Reflection info + pub is_const: bool, + pub is_static_use: bool, + pub is_dead_code_eliminated: bool, +} + +impl Variable { + pub fn new( + name: Name, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + built_in: Option, + initializer: Option, + scope: VariableScope, + ) -> Variable { + Variable { + name, + type_id, + precision, + decorations, + built_in, + initializer, + scope, + is_const: false, + is_static_use: false, + is_dead_code_eliminated: false, + } + } + + // Const variables are only created during parse. They are replaced by constants and never + // referenced, and only serve the purpose of holding the assigned precision to the constant. + // That precision affects the precision of operations they are involved in. + pub fn new_const(name: Name, type_id: TypeId, precision: Precision) -> Variable { + Variable { + name, + type_id, + precision, + decorations: Decorations::new_none(), + built_in: None, + initializer: None, + scope: VariableScope::Global, + is_const: true, + is_static_use: false, + is_dead_code_eliminated: false, + } + } +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BuiltIn { + // The BuiltIn enum value X corresponds to gl_X in GLSL. + InstanceID, + VertexID, + Position, + PointSize, + BaseVertex, + BaseInstance, + DrawID, + FragCoord, + FrontFacing, + PointCoord, + HelperInvocation, + FragColor, + FragData, + FragDepth, + SecondaryFragColorEXT, + SecondaryFragDataEXT, + DepthRange, + ViewIDOVR, + ClipDistance, + CullDistance, + LastFragColor, + LastFragData, + LastFragDepthARM, + LastFragStencilARM, + ShadingRateEXT, + PrimitiveShadingRateEXT, + SampleID, + SamplePosition, + SampleMaskIn, + SampleMask, + NumSamples, + NumWorkGroups, + WorkGroupSize, + WorkGroupID, + LocalInvocationID, + GlobalInvocationID, + LocalInvocationIndex, + PerVertexIn, + PerVertexOut, + PrimitiveIDIn, + InvocationID, + PrimitiveID, + // gl_Layer as GS output + LayerOut, + // gl_Layer as FS input + LayerIn, + PatchVerticesIn, + TessLevelOuter, + TessLevelInner, + TessCoord, + BoundingBoxOES, + PixelLocalEXT, +} + +// Whether a function parameter is `in`, `out` or `inout`. +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum FunctionParamDirection { + Input, + Output, + InputOutput, +} + +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct FunctionParam { + pub variable_id: VariableId, + pub direction: FunctionParamDirection, +} + +impl FunctionParam { + pub fn new(variable_id: VariableId, direction: FunctionParamDirection) -> FunctionParam { + FunctionParam { variable_id, direction } + } +} + +// A function is defined by its name, parameters, return type and a graph of blocks. The blocks +// are specified separately in `IR`. +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Function { + pub name: Name, + pub params: Vec, + pub return_type_id: TypeId, + pub return_precision: Precision, + pub return_decorations: Decorations, +} + +impl Function { + pub fn new( + name: &'static str, + params: Vec, + return_type_id: TypeId, + return_precision: Precision, + return_decorations: Decorations, + ) -> Function { + Function { + // Keep the exact name for main() only + name: if name == "main" { Name::new_exact(name) } else { Name::new_temp(name) }, + params, + return_type_id, + return_precision, + return_decorations, + } + } +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum ShaderType { + Vertex, + TessellationControl, + TessellationEvaluation, + Geometry, + Fragment, + Compute, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Precision { + NotApplicable, + Low, + Medium, + High, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BlockStorage { + Shared, + Packed, + Std140, + Std430, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum MatrixPacking { + ColumnMajor, + RowMajor, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Depth { + Any, + Greater, + Less, + Unchanged, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum ImageInternalFormat { + RGBA32F, + RGBA16F, + R32F, + RGBA32UI, + RGBA16UI, + RGBA8UI, + R32UI, + RGBA32I, + RGBA16I, + RGBA8I, + R32I, + RGBA8, + RGBA8SNORM, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum GeometryPrimitive { + Undefined, + Points, + Lines, + LinesAdjacency, + Triangles, + TrianglesAdjacency, + LineStrip, + TriangleStrip, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum TessellationPrimitive { + Undefined, + Triangles, + Quads, + Isolines, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum TessellationSpacing { + Undefined, + EqualSpacing, + FractionalEvenSpacing, + FractionalOddSpacing, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum TessellationOrdering { + Undefined, + Cw, + Ccw, +} + +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Decoration { + // Corresponding to GLSL qualifiers with the same name + Invariant, + Precise, + Interpolant, + Smooth, + Flat, + NoPerspective, + Centroid, + Sample, + Patch, + Shared, + ReadOnly, + WriteOnly, + Coherent, + Restrict, + Volatile, + Uniform, + Buffer, + PushConstant, + NonCoherent, + Yuv, + // TODO(http://anglebug.com/349994211): handle __pixel_localEXT, likely in combination with + // Input/Output/InputOutput + // Indicates that a variable (excluding built-ins) is an input to the shader + Input, + // Indicates that a variable (excluding built-ins) is an output of the shader + Output, + // Indicates that a variable (excluding built-ins) is both an input to and output of the + // shader, used in EXT_shader_framebuffer_fetch. + InputOutput, + // The location qualifier of an input or output + Location(u32), + // The index qualifier per EXT_blend_func_extended + Index(u32), + // The input attachment qualifier for EXT_shader_framebuffer_fetch support + InputAttachmentIndex(u32), + // Specialization constant index + SpecConst(u32), + // The storage of UBO and SSBO blocks. + Block(BlockStorage), + // The binding qualifier + Binding(u32), + // The offset qualifier + Offset(u32), + // The matrix packing of a block or struct field + MatrixPacking(MatrixPacking), + // The depth qualifier + Depth(Depth), + // Internal format declared on storage images + ImageInternalFormat(ImageInternalFormat), + // Number of views in OVR_multiview + NumViews(u32), + // Used internally to implement ANGLE_pixel_local_storage, indicates a D3D 11.3 Rasterizer + // Order Views (ROV) + RasterOrdered, +} + +// A set of decorations that only affect variables. They are placed in a vector that's expected to +// always be very short. +#[derive(Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Decorations { + pub decorations: Vec, +} + +impl Decorations { + pub fn new_none() -> Decorations { + Decorations { decorations: Vec::new() } + } + pub fn new(decorations: Vec) -> Decorations { + Decorations { decorations } + } + pub fn add_invariant(&mut self) { + if !self.has(Decoration::Invariant) { + self.decorations.push(Decoration::Invariant); + } + } + pub fn add_precise(&mut self) { + if !self.has(Decoration::Precise) { + self.decorations.push(Decoration::Precise); + } + } + + pub fn has(&self, query: Decoration) -> bool { + self.decorations.contains(&query) + } +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BasicType { + Void, + Float, + Int, + Uint, + Bool, + AtomicCounter, + // To support EXT_YUV_target + YuvCscStandard, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum ImageBasicType { + Float, + Int, + Uint, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum ImageDimension { + // Note: D2 is 2D, but works around identifier starting with number + D2, + D3, + Cube, + Rect, + Buffer, + // For OES_EGL_image_external + External, + // For GL_EXT_YUV_target + ExternalY2Y, + // For WebGL_video_texture + Video, + // For ANGLE_shader_pixel_local_storage + PixelLocal, + // For subpass inputs + Subpass, +} + +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct ImageType { + pub dimension: ImageDimension, + pub is_sampled: bool, + pub is_array: bool, + pub is_ms: bool, + pub is_shadow: bool, +} + +// A field of a struct or interface block. +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct Field { + pub name: Name, + pub type_id: TypeId, + pub precision: Precision, + pub decorations: Decorations, +} + +impl Field { + pub fn new( + name: Name, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + ) -> Field { + Field { name, type_id, precision, decorations } + } +} + +#[derive(PartialEq, Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum StructSpecialization { + Struct, + InterfaceBlock, +} + +// The type of an expression. Types can be recursive, for example a vector, matrix or array of +// another type. +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Type { + // Representing Void, Float, Int, Uint, Bool, YuvCscStandard and AtomicCounter + Scalar(BasicType), + // Representing FloatImage, IntImage and UintImage + Image(ImageBasicType, ImageType), + // Representing Struct, may represent an interface block as well. + Struct(Name, Vec, StructSpecialization), + // A vector of other Scalar types + Vector(TypeId, u32), + // A matrix of other Vector types (which are columns) + Matrix(TypeId, u32), + // An array of other types + Array(TypeId, u32), + UnsizedArray(TypeId), + // A pointer to a type, includes variables, access chains etc + Pointer(TypeId), + // An eliminated type that doesn't need to be declared in the output. + DeadCodeEliminated, +} + +impl Type { + pub fn new_void() -> Type { + Type::Scalar(BasicType::Void) + } + pub fn new_scalar(basic_type: BasicType) -> Type { + Type::Scalar(basic_type) + } + pub fn new_image(basic_type: ImageBasicType, image_type: ImageType) -> Type { + Type::Image(basic_type, image_type) + } + pub fn new_struct( + name: Name, + fields: Vec, + specialization: StructSpecialization, + ) -> Type { + Type::Struct(name, fields, specialization) + } + pub fn new_vector(type_id: TypeId, count: u32) -> Type { + Type::Vector(type_id, count) + } + pub fn new_matrix(type_id: TypeId, count: u32) -> Type { + Type::Matrix(type_id, count) + } + pub fn new_array(type_id: TypeId, count: u32) -> Type { + Type::Array(type_id, count) + } + pub fn new_unsized_array(type_id: TypeId) -> Type { + Type::UnsizedArray(type_id) + } + pub fn new_pointer(type_id: TypeId) -> Type { + Type::Pointer(type_id) + } + + pub fn is_scalar(&self) -> bool { + matches!(self, Type::Scalar(_)) + } + + pub fn is_vector(&self) -> bool { + matches!(self, Type::Vector(..)) + } + + pub fn is_matrix(&self) -> bool { + matches!(self, Type::Matrix(..)) + } + + pub fn is_image(&self) -> bool { + matches!(self, Type::Image(..)) + } + + pub fn is_array(&self) -> bool { + matches!(self, Type::Array(..)) + } + + pub fn is_unsized_array(&self) -> bool { + matches!(self, Type::UnsizedArray(_)) + } + + pub fn is_struct(&self) -> bool { + matches!(self, Type::Struct(..)) + } + + pub fn is_pointer(&self) -> bool { + matches!(self, Type::Pointer(_)) + } + + pub fn is_dead_code_eliminated(&self) -> bool { + matches!(self, Type::DeadCodeEliminated) + } + + pub fn get_scalar_basic_type(&self) -> BasicType { + match self { + &Type::Scalar(basic_type) => basic_type, + _ => panic!("Internal error: Expected scalar type"), + } + } + + pub fn get_vector_size(&self) -> Option { + match self { + &Type::Vector(_, count) => Some(count), + _ => None, + } + } + + pub fn get_matrix_size(&self) -> Option { + match self { + &Type::Matrix(_, count) => Some(count), + _ => None, + } + } + + pub fn get_element_type_id(&self) -> Option { + match *self { + Type::Vector(element_id, _) => Some(element_id), + Type::Matrix(element_id, _) => Some(element_id), + Type::Array(element_id, _) => Some(element_id), + Type::UnsizedArray(element_id) => Some(element_id), + Type::Pointer(element_id) => Some(element_id), + _ => None, + } + } + + pub fn get_struct_field(&self, field: u32) -> &Field { + match self { + Type::Struct(_, fields, _) => &fields[field as usize], + _ => panic!("Internal error: Expected struct type"), + } + } + + pub fn get_image_type(&self) -> (ImageBasicType, &ImageType) { + match self { + Type::Image(basic_type, image_type) => (*basic_type, image_type), + _ => panic!("Internal error: Expected image type"), + } + } + + pub fn get_total_component_count(&self, ir_meta: &IRMeta) -> u32 { + let mut total_components = 1; + + if let &Type::Matrix(vector_type_id, count) = self { + let vector_type_info = ir_meta.get_type(vector_type_id); + total_components = count * vector_type_info.get_vector_size().unwrap(); + } else if let &Type::Vector(_, count) = self { + total_components = count; + } + + total_components + } +} + +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct AdvancedBlendEquations { + pub multiply: bool, + pub screen: bool, + pub overlay: bool, + pub darken: bool, + pub lighten: bool, + pub colordodge: bool, + pub colorburn: bool, + pub hardlight: bool, + pub softlight: bool, + pub difference: bool, + pub exclusion: bool, + pub hsl_hue: bool, + pub hsl_saturation: bool, + pub hsl_color: bool, + pub hsl_luminosity: bool, +} + +impl AdvancedBlendEquations { + pub fn new() -> AdvancedBlendEquations { + AdvancedBlendEquations { + multiply: false, + screen: false, + overlay: false, + darken: false, + lighten: false, + colordodge: false, + colorburn: false, + hardlight: false, + softlight: false, + difference: false, + exclusion: false, + hsl_hue: false, + hsl_saturation: false, + hsl_color: false, + hsl_luminosity: false, + } + } + + pub fn set_all(&mut self) { + self.multiply = true; + self.screen = true; + self.overlay = true; + self.darken = true; + self.lighten = true; + self.colordodge = true; + self.colorburn = true; + self.hardlight = true; + self.softlight = true; + self.difference = true; + self.exclusion = true; + self.hsl_hue = true; + self.hsl_saturation = true; + self.hsl_color = true; + self.hsl_luminosity = true; + } + + pub fn add(&mut self, equations: Self) { + self.multiply |= equations.multiply; + self.screen |= equations.screen; + self.overlay |= equations.overlay; + self.darken |= equations.darken; + self.lighten |= equations.lighten; + self.colordodge |= equations.colordodge; + self.colorburn |= equations.colorburn; + self.hardlight |= equations.hardlight; + self.softlight |= equations.softlight; + self.difference |= equations.difference; + self.exclusion |= equations.exclusion; + self.hsl_hue |= equations.hsl_hue; + self.hsl_saturation |= equations.hsl_saturation; + self.hsl_color |= equations.hsl_color; + self.hsl_luminosity |= equations.hsl_luminosity; + } + + pub fn all(&self) -> bool { + self.multiply + && self.screen + && self.overlay + && self.darken + && self.lighten + && self.colordodge + && self.colorburn + && self.hardlight + && self.softlight + && self.difference + && self.exclusion + && self.hsl_hue + && self.hsl_saturation + && self.hsl_color + && self.hsl_luminosity + } +} + +// The entire IR. At a high level, the IR is: +// +// - A set of types +// - A set of constants +// - A set of variables +// - A set of Functions +// +// Each of the above is implemented as a map of the respective ID to data. Additionally, the IR +// carries other global data, such as shader type, enabled advanced blend equations, geometry or +// tessellation parameters etc. +// +// Transformations traverse functions and mutate them. The rest of the IR may be accessed and +// modified during these transformations too. Since the many layers of helper functions and +// closures makes it hard for Rust to verify things, everything in the IR except the function +// blocks are split into an `IRMeta` struct (allowing both the `.functions` and `.meta` to be +// borrowed as &mut). +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct IRMeta { + types: Vec, + constants: Vec, + variables: Vec, + functions: Vec, + + // List of instructions indexed by register ID. Stored in a global array, this allows + // easy look up of instructions that calculate an id, such as the parameter of another + // instruction. + instructions: Vec, + + // List of global variables. + global_variables: Vec, + + // Id of main(). + main_function_id: Option, + + // Maps to look up the id of existing types. This ensures that the type ids are unique and + // there are no duplicate types. + image_type_map: HashMap<(ImageBasicType, ImageType), TypeId>, + array_type_map: HashMap<(TypeId, u32), TypeId>, + pointer_type_map: HashMap, + + // Maps to look up the id of existing constants to avoid duplicates even though they are + // harmless. Note that float constants are hashed by their bit pattern as integers because + // Rust does not implement Eq and Hash for f32. + float_constant_map: HashMap, + int_constant_map: HashMap, + uint_constant_map: HashMap, + composite_constant_map: HashMap<(TypeId, Vec), ConstantId>, + + // Data that globally affects the shader: + shader_type: ShaderType, + + // Affecting fragment shaders: + early_fragment_tests: bool, + advanced_blend_equations: AdvancedBlendEquations, + + // Affecting tessellation control shaders: + tcs_vertices: u32, + + // Affecting tessellation evaluation shaders: + tes_primitive: TessellationPrimitive, + tes_vertex_spacing: TessellationSpacing, + tes_ordering: TessellationOrdering, + tes_point_mode: bool, + + // Affecting geometry shaders: + gs_primitive_in: GeometryPrimitive, + gs_primitive_out: GeometryPrimitive, + gs_invocations: u32, + gs_max_vertices: u32, + + // Affecting pre-fragment shaders, whether gl_PerVertex is redeclared by the shader or not + // matters; with GLSL output, we cannot unconditionally declare gl_PerVertex in geometry shader + // for example without also doing that in the vertex shader, because then there'd be an + // interface mismatch. + per_vertex_in_is_redeclared: bool, + per_vertex_out_is_redeclared: bool, + // TODO(http://anglebug.com/349994211): invariant and others that can be globally set, do they + // need to be tracked here? + + // Set of variables that are required to be zero-initialized before output generation. This + // set is determined during parse, but zero-initialization needs to be done late in + // compilation. + variables_pending_zero_initialization: HashSet, +} + +impl IRMeta { + pub fn new(shader_type: ShaderType) -> IRMeta { + let mut types = vec![ + // Corresponding to TYPE_ID_VOID + Type::new_void(), + // Corresponding to TYPE_ID_FLOAT + Type::new_scalar(BasicType::Float), + // Corresponding to TYPE_ID_INT + Type::new_scalar(BasicType::Int), + // Corresponding to TYPE_ID_UINT + Type::new_scalar(BasicType::Uint), + // Corresponding to TYPE_ID_BOOL + Type::new_scalar(BasicType::Bool), + // Corresponding to TYPE_ID_ATOMIC_COUNTER + Type::new_scalar(BasicType::AtomicCounter), + // Corresponding to TYPE_ID_YUV_CSC_STANDARD + Type::new_scalar(BasicType::YuvCscStandard), + // Corresponding to TYPE_ID_VEC2 + Type::new_vector(TYPE_ID_FLOAT, 2), + // Corresponding to TYPE_ID_VEC3 + Type::new_vector(TYPE_ID_FLOAT, 3), + // Corresponding to TYPE_ID_VEC4 + Type::new_vector(TYPE_ID_FLOAT, 4), + // Corresponding to TYPE_ID_IVEC2 + Type::new_vector(TYPE_ID_INT, 2), + // Corresponding to TYPE_ID_IVEC3 + Type::new_vector(TYPE_ID_INT, 3), + // Corresponding to TYPE_ID_IVEC4 + Type::new_vector(TYPE_ID_INT, 4), + // Corresponding to TYPE_ID_UVEC2 + Type::new_vector(TYPE_ID_UINT, 2), + // Corresponding to TYPE_ID_UVEC3 + Type::new_vector(TYPE_ID_UINT, 3), + // Corresponding to TYPE_ID_UVEC4 + Type::new_vector(TYPE_ID_UINT, 4), + // Corresponding to TYPE_ID_BVEC2 + Type::new_vector(TYPE_ID_BOOL, 2), + // Corresponding to TYPE_ID_BVEC3 + Type::new_vector(TYPE_ID_BOOL, 3), + // Corresponding to TYPE_ID_BVEC4 + Type::new_vector(TYPE_ID_BOOL, 4), + // Corresponding to TYPE_ID_MAT2 + Type::new_matrix(TYPE_ID_VEC2, 2), + // Corresponding to TYPE_ID_MAT2X3 + Type::new_matrix(TYPE_ID_VEC3, 2), + // Corresponding to TYPE_ID_MAT2X4 + Type::new_matrix(TYPE_ID_VEC4, 2), + // Corresponding to TYPE_ID_MAT3X2 + Type::new_matrix(TYPE_ID_VEC2, 3), + // Corresponding to TYPE_ID_MAT3 + Type::new_matrix(TYPE_ID_VEC3, 3), + // Corresponding to TYPE_ID_MAT3X4 + Type::new_matrix(TYPE_ID_VEC4, 3), + // Corresponding to TYPE_ID_MAT4X2 + Type::new_matrix(TYPE_ID_VEC2, 4), + // Corresponding to TYPE_ID_MAT4X3 + Type::new_matrix(TYPE_ID_VEC3, 4), + // Corresponding to TYPE_ID_MAT4 + Type::new_matrix(TYPE_ID_VEC4, 4), + ]; + + let mut constants = vec![ + // Corresponding to CONSTANT_ID_FALSE + Constant::new_bool(false), + // Corresponding to CONSTANT_ID_TRUE + Constant::new_bool(true), + // Corresponding to CONSTANT_ID_FLOAT_ZERO + Constant::new_float(0.0), + // Corresponding to CONSTANT_ID_FLOAT_ONE + Constant::new_float(1.0), + // Corresponding to CONSTANT_ID_INT_ZERO + Constant::new_int(0), + // Corresponding to CONSTANT_ID_INT_ONE + Constant::new_int(1), + // Corresponding to CONSTANT_ID_UINT_ZERO + Constant::new_uint(0), + // Corresponding to CONSTANT_ID_UINT_ONE + Constant::new_uint(1), + // Corresponding to CONSTANT_ID_YUV_CSC_ITU601 + Constant::new_yuv_csc(YuvCscStandard::Itu601), + // Corresponding to CONSTANT_ID_YUV_CSC_ITU601_FULL_RANGE + Constant::new_yuv_csc(YuvCscStandard::Itu601FullRange), + // Corresponding to CONSTANT_ID_YUV_CSC_ITU709 + Constant::new_yuv_csc(YuvCscStandard::Itu709), + ]; + + let mut variables = Vec::new(); + let mut functions = Vec::new(); + let mut instructions = Vec::new(); + + // Reserve sensible counts upfront. + // Fr types, typically there may be a few structs and blocks and some samplers. + types.reserve(20); + // For constants, there can be many of them. + constants.reserve(200); + // For variables, there can be many temporary ones. + variables.reserve(200); + // For functions, there are typically no more than a handful. + functions.reserve(20); + // For instructions (corresponding to register ids), hundreds in a shader are common. + instructions.reserve(200); + + // Add the predefined constants to the respective maps so they aren't recreated. + let float_constant_map = HashMap::from([ + (0.0_f32.to_bits(), CONSTANT_ID_FLOAT_ZERO), + (1.0_f32.to_bits(), CONSTANT_ID_FLOAT_ONE), + ]); + let int_constant_map = HashMap::from([(0, CONSTANT_ID_INT_ZERO), (1, CONSTANT_ID_INT_ONE)]); + let uint_constant_map = + HashMap::from([(0, CONSTANT_ID_UINT_ZERO), (1, CONSTANT_ID_UINT_ONE)]); + + IRMeta { + types, + constants, + variables, + functions, + instructions, + global_variables: Vec::new(), + main_function_id: None, + image_type_map: HashMap::new(), + array_type_map: HashMap::new(), + pointer_type_map: HashMap::new(), + float_constant_map, + int_constant_map, + uint_constant_map, + composite_constant_map: HashMap::new(), + shader_type, + early_fragment_tests: false, + advanced_blend_equations: AdvancedBlendEquations::new(), + tcs_vertices: 0, + tes_primitive: TessellationPrimitive::Undefined, + tes_vertex_spacing: TessellationSpacing::Undefined, + tes_ordering: TessellationOrdering::Undefined, + tes_point_mode: false, + gs_primitive_in: GeometryPrimitive::Undefined, + gs_primitive_out: GeometryPrimitive::Undefined, + gs_invocations: 0, + gs_max_vertices: 0, + per_vertex_in_is_redeclared: false, + per_vertex_out_is_redeclared: false, + variables_pending_zero_initialization: HashSet::new(), + } + } + + pub fn all_types(&self) -> &Vec { + &self.types + } + pub fn all_constants(&self) -> &Vec { + &self.constants + } + pub fn all_variables(&self) -> &Vec { + &self.variables + } + pub fn all_functions(&self) -> &Vec { + &self.functions + } + pub fn all_functions_mut(&mut self) -> &mut Vec { + &mut self.functions + } + pub fn all_global_variables(&self) -> &Vec { + &self.global_variables + } + pub fn prune_global_variables(&mut self, keep: Keep) + where + Keep: Fn(VariableId) -> bool, + { + self.global_variables.retain(|&variable_id| keep(variable_id)); + } + + pub fn get_main_function_id(&self) -> Option { + self.main_function_id + } + pub fn set_main_function_id(&mut self, main_id: FunctionId) { + debug_assert!(self.main_function_id.is_none()); + self.main_function_id = Some(main_id); + } + + pub fn get_shader_type(&self) -> ShaderType { + self.shader_type + } + pub fn get_early_fragment_tests(&self) -> bool { + self.early_fragment_tests + } + pub fn get_advanced_blend_equations(&self) -> &AdvancedBlendEquations { + &self.advanced_blend_equations + } + pub fn get_tcs_vertices(&self) -> u32 { + self.tcs_vertices + } + pub fn get_tes_primitive(&self) -> TessellationPrimitive { + self.tes_primitive + } + pub fn get_tes_vertex_spacing(&self) -> TessellationSpacing { + self.tes_vertex_spacing + } + pub fn get_tes_ordering(&self) -> TessellationOrdering { + self.tes_ordering + } + pub fn get_tes_point_mode(&self) -> bool { + self.tes_point_mode + } + pub fn get_gs_primitive_in(&self) -> GeometryPrimitive { + self.gs_primitive_in + } + pub fn get_gs_primitive_out(&self) -> GeometryPrimitive { + self.gs_primitive_out + } + pub fn get_gs_invocations(&self) -> u32 { + self.gs_invocations + } + pub fn get_gs_max_vertices(&self) -> u32 { + self.gs_max_vertices + } + pub fn is_per_vertex_in_redeclared(&self) -> bool { + self.per_vertex_in_is_redeclared + } + pub fn is_per_vertex_out_redeclared(&self) -> bool { + self.per_vertex_out_is_redeclared + } + + pub fn set_early_fragment_tests(&mut self, value: bool) { + self.early_fragment_tests = value; + } + pub fn add_advanced_blend_equations(&mut self, equations: AdvancedBlendEquations) { + self.advanced_blend_equations.add(equations); + } + pub fn set_tcs_vertices(&mut self, value: u32) { + self.tcs_vertices = value + } + pub fn set_tes_primitive(&mut self, value: TessellationPrimitive) { + self.tes_primitive = value; + } + pub fn set_tes_vertex_spacing(&mut self, value: TessellationSpacing) { + self.tes_vertex_spacing = value; + } + pub fn set_tes_ordering(&mut self, value: TessellationOrdering) { + self.tes_ordering = value; + } + pub fn set_tes_point_mode(&mut self, value: bool) { + self.tes_point_mode = value; + } + pub fn set_gs_primitive_in(&mut self, value: GeometryPrimitive) { + self.gs_primitive_in = value; + } + pub fn set_gs_primitive_out(&mut self, value: GeometryPrimitive) { + self.gs_primitive_out = value; + } + pub fn set_gs_invocations(&mut self, value: u32) { + self.gs_invocations = value; + } + pub fn set_gs_max_vertices(&mut self, value: u32) { + self.gs_max_vertices = value; + } + pub fn on_per_vertex_in_redeclaration(&mut self) { + self.per_vertex_in_is_redeclared = true; + } + pub fn on_per_vertex_out_redeclaration(&mut self) { + self.per_vertex_out_is_redeclared = true; + } + + fn add_item_and_get_id(items: &mut Vec, new_item: T) -> u32 { + let item_id = items.len() as u32; + items.push(new_item); + item_id + } + + fn add_type_and_get_id(types: &mut Vec, type_desc: Type) -> TypeId { + TypeId { id: Self::add_item_and_get_id(types, type_desc) } + } + + pub fn add_constant_and_get_id( + constants: &mut Vec, + constant: Constant, + ) -> ConstantId { + ConstantId { id: Self::add_item_and_get_id(constants, constant) } + } + + // Returns a predefined type id, see TYPE_ID_* constants. + pub fn get_basic_type_id(&self, basic_type: BasicType) -> TypeId { + match basic_type { + BasicType::Void => TYPE_ID_VOID, + BasicType::Float => TYPE_ID_FLOAT, + BasicType::Int => TYPE_ID_INT, + BasicType::Uint => TYPE_ID_UINT, + BasicType::Bool => TYPE_ID_BOOL, + BasicType::AtomicCounter => TYPE_ID_ATOMIC_COUNTER, + BasicType::YuvCscStandard => TYPE_ID_YUV_CSC_STANDARD, + } + } + + // Returns a predefined type id for vectors, see TYPE_ID_* constants. + pub fn get_vector_type_id(&self, basic_type: BasicType, vector_size: u32) -> TypeId { + debug_assert!((2..=4).contains(&vector_size)); + + let offset = vector_size - 2; + + match basic_type { + BasicType::Float => TypeId { id: TYPE_ID_VEC2.id + offset }, + BasicType::Int => TypeId { id: TYPE_ID_IVEC2.id + offset }, + BasicType::Uint => TypeId { id: TYPE_ID_UVEC2.id + offset }, + BasicType::Bool => TypeId { id: TYPE_ID_BVEC2.id + offset }, + _ => panic!("Internal error: Not a vector-able type"), + } + } + + // Returns a vectors type id based on the given element. + pub fn get_vector_type_id_from_element_id( + &self, + element_type_id: TypeId, + vector_size: u32, + ) -> TypeId { + match element_type_id { + TYPE_ID_FLOAT => self.get_vector_type_id(BasicType::Float, vector_size), + TYPE_ID_INT => self.get_vector_type_id(BasicType::Int, vector_size), + TYPE_ID_UINT => self.get_vector_type_id(BasicType::Uint, vector_size), + TYPE_ID_BOOL => self.get_vector_type_id(BasicType::Bool, vector_size), + _ => panic!("Internal error: Not a vector-able type"), + } + } + + // Returns a predefined type id for matrices, see TYPE_ID_* constants. + pub fn get_matrix_type_id(&self, column_count: u32, row_count: u32) -> TypeId { + debug_assert!((2..=4).contains(&column_count)); + debug_assert!((2..=4).contains(&row_count)); + + let offset = (column_count - 2) * 3 + (row_count - 2); + TypeId { id: TYPE_ID_MAT2.id + offset } + } + + // TODO(http://anglebug.com/349994211): get_image_type_id, get_array_type_id, + // get_unsized_array_type_id, and get_constant_* are very similar. Maybe they can be + // templatized + some lambdas + pub fn get_image_type_id( + &mut self, + basic_type: ImageBasicType, + image_type: ImageType, + ) -> TypeId { + // Look up the image type; if one doesn't exist, create it. + *self.image_type_map.entry((basic_type, image_type)).or_insert_with(|| { + Self::add_type_and_get_id(&mut self.types, Type::new_image(basic_type, image_type)) + }) + } + + pub fn get_struct_type_id( + &mut self, + name: Name, + fields: Vec, + specialization: StructSpecialization, + ) -> TypeId { + // Note: this should only make new types, not used as a way to look up a struct, that ID + // should already be known. + Self::add_type_and_get_id(&mut self.types, Type::new_struct(name, fields, specialization)) + } + + pub fn get_unsized_array_type_id(&mut self, element_type_id: TypeId) -> TypeId { + // Look up the array type; if one doesn't exist, create it. Size of 0 is used in the key + // when the array is unsized. + *self.array_type_map.entry((element_type_id, 0)).or_insert_with(|| { + Self::add_type_and_get_id(&mut self.types, Type::new_unsized_array(element_type_id)) + }) + } + + pub fn get_array_type_id(&mut self, element_type_id: TypeId, array_size: u32) -> TypeId { + // Look up the array type; if one doesn't exist, create it. + *self.array_type_map.entry((element_type_id, array_size)).or_insert_with(|| { + Self::add_type_and_get_id(&mut self.types, Type::new_array(element_type_id, array_size)) + }) + } + + pub fn get_pointer_type_id(&mut self, pointee_type_id: TypeId) -> TypeId { + // Look up the pointer type; if one doesn't exist, create it. + *self.pointer_type_map.entry(pointee_type_id).or_insert_with(|| { + Self::add_type_and_get_id(&mut self.types, Type::new_pointer(pointee_type_id)) + }) + } + + pub fn get_constant_float(&mut self, value: f32) -> ConstantId { + // Look up the float constant; if one doesn't exist, create it. + *self.float_constant_map.entry(value.to_bits()).or_insert_with(|| { + Self::add_constant_and_get_id(&mut self.constants, Constant::new_float(value)) + }) + } + + pub fn get_constant_int(&mut self, value: i32) -> ConstantId { + // Look up the int constant; if one doesn't exist, create it. + *self.int_constant_map.entry(value).or_insert_with(|| { + Self::add_constant_and_get_id(&mut self.constants, Constant::new_int(value)) + }) + } + + pub fn get_constant_uint(&mut self, value: u32) -> ConstantId { + // Look up the int constant; if one doesn't exist, create it. + *self.uint_constant_map.entry(value).or_insert_with(|| { + Self::add_constant_and_get_id(&mut self.constants, Constant::new_uint(value)) + }) + } + + pub fn get_constant_yuv_csc_standard(&mut self, value: YuvCscStandard) -> ConstantId { + match value { + YuvCscStandard::Itu601 => CONSTANT_ID_YUV_CSC_ITU601, + YuvCscStandard::Itu601FullRange => CONSTANT_ID_YUV_CSC_ITU601_FULL_RANGE, + YuvCscStandard::Itu709 => CONSTANT_ID_YUV_CSC_ITU709, + } + } + + pub fn get_constant_bool(&mut self, value: bool) -> ConstantId { + // Bool constants are predefined + if value { CONSTANT_ID_TRUE } else { CONSTANT_ID_FALSE } + } + + pub fn get_constant_composite( + &mut self, + type_id: TypeId, + components: Vec, + ) -> ConstantId { + // Look up the composite constant; if one doesn't exist, create it. + *self.composite_constant_map.entry((type_id, components.clone())).or_insert_with(|| { + Self::add_constant_and_get_id( + &mut self.constants, + Constant::new_composite(type_id, components), + ) + }) + } + + pub fn dead_code_eliminate_variable(&mut self, id: VariableId) { + // The variable is expected to already be removed from the IR, and this is just marking it + // as eliminated. + self.variables[id.id as usize].is_dead_code_eliminated = true; + } + pub fn dead_code_eliminate_constant(&mut self, id: ConstantId) { + // Don't dead-code-eliminate predefined constants, they may be referenced by future + // transformations. + if id.id <= MAX_PREDEFINED_CONSTANT_ID { + return; + } + + // Mark the constant as dead-code-eliminated. + let constant = &mut self.constants[id.id as usize]; + constant.is_dead_code_eliminated = true; + + // Remove the constant from the constant map, so this id is never returned in future + // lookups. + match constant.value { + ConstantValue::Float(f) => { + self.float_constant_map.remove(&f.to_bits()); + } + ConstantValue::Int(i) => { + self.int_constant_map.remove(&i); + } + ConstantValue::Uint(u) => { + self.uint_constant_map.remove(&u); + } + ConstantValue::Bool(_) | ConstantValue::YuvCsc(_) => { + // Nothing to do, all possible values are predefined. + } + ConstantValue::Composite(ref components) => { + self.composite_constant_map.remove(&(constant.type_id, components.clone())); + } + }; + } + pub fn dead_code_eliminate_type(&mut self, id: TypeId) { + // Don't dead-code-eliminate predefined types, they may be referenced by future + // transformations. + if id.id <= MAX_PREDEFINED_TYPE_ID { + return; + } + + let type_info = &mut self.types[id.id as usize]; + + // Remove the type from the type map, so this id is never returned in future lookups. + match *type_info { + Type::Image(basic_type, image_type) => { + self.image_type_map.remove(&(basic_type, image_type)); + } + Type::Array(element_type_id, count) => { + self.array_type_map.remove(&(element_type_id, count)); + } + Type::UnsizedArray(element_type_id) => { + self.array_type_map.remove(&(element_type_id, 0)); + } + Type::Pointer(pointee_type_id) => { + self.pointer_type_map.remove(&pointee_type_id); + } + _ => {} + } + + // Mark the type as dead-code-eliminated. + *type_info = Type::DeadCodeEliminated; + } + + // Generate the "null" value of a given type. That is 0 for numeric types, false for boolean, + // etc. + pub fn get_constant_scalar_null(&mut self, basic_type: BasicType) -> ConstantId { + match basic_type { + BasicType::Void => panic!("Internal error: Cannot create a null value of type void"), + BasicType::AtomicCounter => { + panic!("Internal error: Cannot create a null value of type atomicCounter") + } + BasicType::Float => CONSTANT_ID_FLOAT_ZERO, + BasicType::Int => CONSTANT_ID_INT_ZERO, + BasicType::Uint => CONSTANT_ID_UINT_ZERO, + BasicType::Bool => CONSTANT_ID_FALSE, + BasicType::YuvCscStandard => CONSTANT_ID_YUV_CSC_ITU601, + } + } + pub fn get_constant_null(&mut self, type_id: TypeId) -> ConstantId { + match self.get_type(type_id) { + &Type::Scalar(basic_type) => self.get_constant_scalar_null(basic_type), + &Type::Vector(component_type_id, count) + | &Type::Matrix(component_type_id, count) + | &Type::Array(component_type_id, count) => { + let null_component = self.get_constant_null(component_type_id); + self.get_constant_composite( + type_id, + std::iter::repeat_n(null_component, count as usize).collect(), + ) + } + Type::Struct(_, fields, StructSpecialization::Struct) => { + let fields = fields.iter().map(|field| field.type_id).collect::>(); + let components = fields + .iter() + .map(|&field_type_id| self.get_constant_null(field_type_id)) + .collect(); + self.get_constant_composite(type_id, components) + } + Type::Struct(..) => { + panic!("Internal error: Cannot create a null value of interface block type") + } + Type::UnsizedArray(_) => { + panic!("Internal error: Cannot create a null value of unsized array type") + } + Type::Pointer(_) => { + panic!("Internal error: Cannot create a null value of pointer type") + } + Type::Image(..) => panic!("Internal error: Cannot create a null value of image type"), + Type::DeadCodeEliminated => { + panic!("Internal error: Cannot create a null value of dead-code-eliminated type") + } + } + } + + pub fn add_variable(&mut self, variable: Variable) -> VariableId { + VariableId { id: Self::add_item_and_get_id(&mut self.variables, variable) } + } + pub fn declare_variable( + &mut self, + name: Name, + type_id: TypeId, + precision: Precision, + decorations: Decorations, + built_in: Option, + initializer: Option, + scope: VariableScope, + ) -> VariableId { + // Automatically turn the type into a pointer + debug_assert!(!self.get_type(type_id).is_pointer()); + let type_id = self.get_pointer_type_id(type_id); + let var = + Variable::new(name, type_id, precision, decorations, built_in, initializer, scope); + let variable_id = self.add_variable(var); + + if scope == VariableScope::Global { + self.global_variables.push(variable_id); + } + + variable_id + } + // Used only by builder.rs. Transformations should not create const variables, but instead + // just use constants. + pub fn declare_const_variable( + &mut self, + name: Name, + type_id: TypeId, + precision: Precision, + ) -> VariableId { + // Automatically turn the type into a pointer + debug_assert!(!self.get_type(type_id).is_pointer()); + let type_id = self.get_pointer_type_id(type_id); + let var = Variable::new_const(name, type_id, precision); + // No need to add the variable to any scope, because they are always replaced by their + // constant value in the IR. + self.add_variable(var) + } + + // Used only by builder.rs. Transformations should set the initializer at the same time as + // declaring the variable with `declare_variable`. + pub fn set_variable_initializer(&mut self, id: VariableId, constant_id: ConstantId) { + debug_assert!(self.variables[id.id as usize].initializer.is_none()); + self.variables[id.id as usize].initializer = Some(constant_id); + self.on_variable_initialized(id); + } + pub fn on_variable_initialized(&mut self, id: VariableId) { + // Now that the initializer is visited (during parse), the variable won't need + // zero-initialization. + self.variables_pending_zero_initialization.remove(&id); + } + pub fn require_variable_zero_initialization(&mut self, id: VariableId) { + debug_assert!(!self.variable_needs_zero_initialization(id)); + self.variables_pending_zero_initialization.insert(id); + } + pub fn variable_needs_zero_initialization(&self, id: VariableId) -> bool { + self.variables_pending_zero_initialization.contains(&id) + } + pub fn on_variable_zero_initialization_done(&mut self, id: VariableId) { + debug_assert!(self.variable_needs_zero_initialization(id)); + self.variables_pending_zero_initialization.remove(&id); + } + + pub fn add_function(&mut self, function: Function) -> FunctionId { + FunctionId { id: IRMeta::add_item_and_get_id(&mut self.functions, function) } + } + + pub fn get_type(&self, type_id: TypeId) -> &Type { + // TODO(http://anglebug.com/349994211): this may be in a hot loop, do unsafe lookup + + // debug_assert when outside Chrome? Same with other getters. Need to measure if it + // impacts performance. + &self.types[type_id.id as usize] + } + pub fn get_type_mut(&mut self, type_id: TypeId) -> &mut Type { + &mut self.types[type_id.id as usize] + } + pub fn get_constant(&self, constant_id: ConstantId) -> &Constant { + &self.constants[constant_id.id as usize] + } + pub fn get_constant_mut(&mut self, constant_id: ConstantId) -> &mut Constant { + &mut self.constants[constant_id.id as usize] + } + pub fn get_variable(&self, variable_id: VariableId) -> &Variable { + &self.variables[variable_id.id as usize] + } + pub fn get_variable_mut(&mut self, variable_id: VariableId) -> &mut Variable { + &mut self.variables[variable_id.id as usize] + } + pub fn get_function(&self, function_id: FunctionId) -> &Function { + &self.functions[function_id.id as usize] + } + pub fn get_function_mut(&mut self, function_id: FunctionId) -> &mut Function { + &mut self.functions[function_id.id as usize] + } + pub fn get_instruction(&self, register_id: RegisterId) -> &Instruction { + &self.instructions[register_id.id as usize] + } + pub fn get_instruction_mut(&mut self, register_id: RegisterId) -> &mut Instruction { + &mut self.instructions[register_id.id as usize] + } + pub fn get_aliased_id(&self, register_id: RegisterId) -> TypedId { + // Follow `Alias`es of the instruction to get to the origin of the id. + // Useful when analyzing / transforming the IR. + let instruction = &self.instructions[register_id.id as usize]; + if let OpCode::Alias(alias_id) = instruction.op { + match alias_id.id { + Id::Register(alias_id) => self.get_aliased_id(alias_id), + _ => alias_id, + } + } else { + TypedId::from_register_id(instruction.result) + } + } + pub fn replace_instruction(&mut self, to_replace: RegisterId, replace_by: RegisterId) { + // Takes an instruction with ID `replace_by` and makes the instruction `to_replace` contain + // that instead. This is used by transformations to change an instruction without + // affecting its result ID, and therefore no need to replicate an ID change throughout the + // IR. + self.instructions.swap(to_replace.id as usize, replace_by.id as usize); + // Make sure the replacing instruction has the id of the one being replaced. The other is + // not worth correcting as it is a dead ID. + self.instructions[to_replace.id as usize].result.id = to_replace; + + // The `replace_by` ID should no longer be used, it refers to an instruction that is + // technically thrown away. If possible, actually throw it away. + if replace_by.id as usize + 1 == self.instructions.len() { + self.instructions.pop(); + } + } + pub fn assign_new_register_to_instruction(&mut self, to_replace: RegisterId) -> RegisterId { + // Used to change the ID of an instruction with a new one. This is used by transformations + // to make the instruction produce a new ID, let that be post-processed and eventually + // have another instruction produce the original ID (using `replace_instruction` above). + // In this way, the rest of the IR does not need to be modified to take the transformations + // into account. + let new_id = RegisterId { id: self.instructions.len() as u32 }; + + // Take the instruction out and place a bogus instruction in its place. + let mut instruction = std::mem::replace( + &mut self.instructions[to_replace.id as usize], + Instruction::new( + OpCode::NextBlock, + TypedRegisterId::new(to_replace, TYPE_ID_VOID, Precision::NotApplicable), + ), + ); + + // Change the result of the instruction and place it in the instruction list. + instruction.result.id = new_id; + self.instructions.push(instruction); + new_id + } + + pub fn new_register( + &mut self, + op: OpCode, + type_id: TypeId, + precision: Precision, + ) -> TypedRegisterId { + let new_id = RegisterId { id: self.instructions.len() as u32 }; + let typed_id = TypedRegisterId::new(new_id, type_id, precision); + self.instructions.push(Instruction::new(op, typed_id)); + typed_id + } + + // Given a matrix, vector or scalar type id, retrieves the scalar type of their components. + pub fn get_scalar_type(&self, type_id: TypeId) -> TypeId { + let type_info = self.get_type(type_id); + let element_type_id = type_info.get_element_type_id().unwrap_or(type_id); + let element_type_info = self.get_type(element_type_id); + element_type_info.get_element_type_id().unwrap_or(element_type_id) + } +} + +#[cfg_attr(debug_assertions, derive(Debug))] +pub struct IR { + pub meta: IRMeta, + // The first block of the function for each function id. This is the root of the block graph. + // If this block doesn't exist, the function has been dead-code-eliminated. + // + // This is separate from IRMeta so that can be mutated while the function blocks are traversed. + pub function_entries: Vec>, +} + +impl IR { + pub fn new(shader_type: ShaderType) -> IR { + IR { meta: IRMeta::new(shader_type), function_entries: Vec::with_capacity(20) } + } + + pub fn add_function(&mut self, function: Function) -> FunctionId { + let new_id = self.meta.add_function(function); + debug_assert!(new_id.id as usize == self.function_entries.len()); + self.function_entries.push(None); + new_id + } + + pub fn set_function_entry(&mut self, id: FunctionId, entry: Block) { + debug_assert!(self.function_entries[id.id as usize].is_none()); + self.function_entries[id.id as usize] = Some(entry); + } + + pub fn prepend_to_main(&mut self, mut new_entry: Block) { + let main_function_id = self.meta.get_main_function_id().unwrap(); + let main_entry = &mut self.function_entries[main_function_id.id as usize]; + let main_entry_block = main_entry.take().unwrap(); + + // Terminate the last block of `new_entry` with a `NextBlock`, and set its merge block to + // the current main block. + let last_block = new_entry.get_merge_chain_last_block_mut(); + debug_assert!(matches!(last_block.get_terminating_op(), OpCode::NextBlock)); + last_block.set_merge_block(main_entry_block); + + *main_entry = Some(new_entry); + } +} diff --git a/src/compiler/translator/ir/src/lib.rs b/src/compiler/translator/ir/src/lib.rs new file mode 100644 index 00000000000..0706c6b9f26 --- /dev/null +++ b/src/compiler/translator/ir/src/lib.rs @@ -0,0 +1,29 @@ +// 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. +// + +// For now, disable unused warnings. +#![allow(dead_code)] +// Disable some clippy warnings that are not necessarily useful: +// Not ideal that some functions take many params, but artificially wrapping them in a struct is +// not helpful. +#![allow(clippy::too_many_arguments)] +// `some_option.as_mut().map()` is used to mirror `some_option.as_ref().inspect()` in some places +// to provide mutable equivalent of immutable operations. The suggestion to use `if let` for the +// mutable case breaks the symmetry. +#![allow(clippy::option_map_unit_fn)] + +mod ast; +mod builder; +mod compile; +mod debug; +mod instruction; +mod ir; +mod output; +mod transform; +mod traverser; +mod util; +mod validator; +use std::collections::{HashMap, HashSet}; +use std::fmt::Write; diff --git a/src/compiler/translator/ir/src/output.rs b/src/compiler/translator/ir/src/output.rs new file mode 100644 index 00000000000..d16e8c9db2f --- /dev/null +++ b/src/compiler/translator/ir/src/output.rs @@ -0,0 +1,6 @@ +// 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. + +pub mod glsl; +pub mod legacy; diff --git a/src/compiler/translator/ir/src/output/glsl.rs b/src/compiler/translator/ir/src/output/glsl.rs new file mode 100644 index 00000000000..2fb00088a47 --- /dev/null +++ b/src/compiler/translator/ir/src/output/glsl.rs @@ -0,0 +1,1489 @@ +// 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. +// +// Output GLSL from the IR. +// +// TODO(http://anglebug.com/349994211): This is more of a debug placeholder. It does generate GLSL +// nearly correctly, but does not add #version and #extension, neither does it account for ESSL 100 +// vs 300 differences, and it prints the result to stdout. It was implemented as a way to +// prototype AST generation, but is kept because ultimately GLSL generation can enhance and use +// this. It will also serve as basis for WGSL, MSL, and HLSL generation. +// + +use crate::ir::*; +use crate::*; + +#[cfg_attr(debug_assertions, derive(Debug))] +struct GlslType { + // Text to declare the type, such as "S { ... }". Note that Type::Struct represents both + // structs and interface blocks, so the `struct`, `uniform`, `buffer` etc is not part of + // the declaration text. The type can have a pre and post text such as for + // `type name[len]`. + declaration_text_pre: String, + declaration_text_post: String, + // Text to use the type elsewhere, such as "S". + use_text_pre: String, + use_text_post: String, +} +#[cfg_attr(debug_assertions, derive(Debug))] +struct GlslConstant { + text: String, + type_id: TypeId, +} +#[cfg_attr(debug_assertions, derive(Debug))] +struct GlslVariable { + declaration_text: String, + name: String, + type_id: TypeId, + skip_declaration: bool, +} +#[cfg_attr(debug_assertions, derive(Debug))] +struct GlslFunction { + declaration_text: String, + name: String, + return_type_id: TypeId, +} + +pub struct Generator { + types: HashMap, + constants: HashMap, + variables: HashMap, + functions: HashMap, + + preamble: String, + type_declarations: String, + global_variables: String, + function_declarations: String, + + expressions: HashMap, + // TODO(http://anglebug.com/349994211): needs output GLSL version, for example to know whether + // it should output texture() or texture2D() etc. + // TODO(http://anglebug.com/349994211): needs a list of extensions that are enabled / should be + // enabled. +} + +impl Generator { + pub fn new() -> Generator { + Generator { + types: HashMap::new(), + constants: HashMap::new(), + variables: HashMap::new(), + functions: HashMap::new(), + preamble: String::new(), + type_declarations: String::new(), + global_variables: String::new(), + function_declarations: String::new(), + expressions: HashMap::new(), + } + } + + fn basic_type_str(id: TypeId) -> String { + (match id { + TYPE_ID_VOID => "void", + TYPE_ID_FLOAT => "float", + TYPE_ID_INT => "int", + TYPE_ID_UINT => "uint", + TYPE_ID_BOOL => "bool", + TYPE_ID_ATOMIC_COUNTER => "atomic_uint", + TYPE_ID_YUV_CSC_STANDARD => "yuvCscStandardEXT", + TYPE_ID_VEC2 => "vec2", + TYPE_ID_VEC3 => "vec3", + TYPE_ID_VEC4 => "vec4", + TYPE_ID_IVEC2 => "ivec2", + TYPE_ID_IVEC3 => "ivec3", + TYPE_ID_IVEC4 => "ivec4", + TYPE_ID_UVEC2 => "uvec2", + TYPE_ID_UVEC3 => "uvec3", + TYPE_ID_UVEC4 => "uvec4", + TYPE_ID_BVEC2 => "bvec2", + TYPE_ID_BVEC3 => "bvec3", + TYPE_ID_BVEC4 => "bvec4", + TYPE_ID_MAT2 => "mat2", + TYPE_ID_MAT2X3 => "mat2x3", + TYPE_ID_MAT2X4 => "mat2x4", + TYPE_ID_MAT3X2 => "mat3x2", + TYPE_ID_MAT3 => "mat3", + TYPE_ID_MAT3X4 => "mat3x4", + TYPE_ID_MAT4X2 => "mat4x2", + TYPE_ID_MAT4X3 => "mat4x3", + TYPE_ID_MAT4 => "mat4", + _ => panic!("Internal error: Invalid basic type"), + }) + .to_string() + } + + fn image_type_str(basic_type: ImageBasicType, image_type: ImageType) -> String { + let prefix = match basic_type { + ImageBasicType::Float => "", + ImageBasicType::Int => "i", + ImageBasicType::Uint => "u", + }; + let mut base_name = if image_type.is_sampled { "sampler" } else { "image" }; + let suffix = match image_type.dimension { + ImageDimension::D2 => "2D", + ImageDimension::D3 => "3D", + ImageDimension::Cube => "Cube", + ImageDimension::Rect => "Rect", + ImageDimension::Buffer => "Buffer", + ImageDimension::External => "ExternalOES", + ImageDimension::ExternalY2Y => "External2DY2YEXT", + ImageDimension::Video => "VideoWEBGL", + ImageDimension::PixelLocal => { + base_name = "pixelLocalANGLE"; + "" + } + ImageDimension::Subpass => { + base_name = "subpassInput"; + "" + } + }; + let multisample_suffix = if image_type.is_ms { "MS" } else { "" }; + let array_suffix = if image_type.is_array { "Array" } else { "" }; + let shadow_suffix = if image_type.is_shadow { "Shadow" } else { "" }; + format!("{prefix}{base_name}{suffix}{multisample_suffix}{array_suffix}{shadow_suffix}") + } + + fn block_storage_str(storage: BlockStorage) -> String { + (match storage { + BlockStorage::Shared => "shared", + BlockStorage::Packed => "packed", + BlockStorage::Std140 => "std140", + BlockStorage::Std430 => "std430", + }) + .to_string() + } + + fn matrix_packing_str(packing: MatrixPacking) -> String { + (match packing { + MatrixPacking::ColumnMajor => "column_major", + MatrixPacking::RowMajor => "row_major", + }) + .to_string() + } + + fn depth_str(depth: Depth) -> String { + (match depth { + Depth::Any => "depth_any", + Depth::Greater => "depth_greater", + Depth::Less => "depth_less", + Depth::Unchanged => "depth_unchanged", + }) + .to_string() + } + + fn image_internal_format_str(format: ImageInternalFormat) -> String { + (match format { + ImageInternalFormat::RGBA32F => "rgba32f", + ImageInternalFormat::RGBA16F => "rgba16f", + ImageInternalFormat::R32F => "r32f", + ImageInternalFormat::RGBA32UI => "rgba32ui", + ImageInternalFormat::RGBA16UI => "rgba16ui", + ImageInternalFormat::RGBA8UI => "rgba8ui", + ImageInternalFormat::R32UI => "r32ui", + ImageInternalFormat::RGBA32I => "rgba32i", + ImageInternalFormat::RGBA16I => "rgba16i", + ImageInternalFormat::RGBA8I => "rgba8i", + ImageInternalFormat::R32I => "r32i", + ImageInternalFormat::RGBA8 => "rgba8", + ImageInternalFormat::RGBA8SNORM => "rgba8snorm", + }) + .to_string() + } + + fn add_qualifier_str( + decoration: Decoration, + qualifiers: &mut Vec, + layout_qualifiers: &mut Vec, + ) { + match decoration { + Decoration::Invariant => qualifiers.push("invariant".to_string()), + Decoration::Precise => qualifiers.push("precise".to_string()), + Decoration::Interpolant => qualifiers.push("interpolant".to_string()), + Decoration::Smooth => qualifiers.push("smooth".to_string()), + Decoration::Flat => qualifiers.push("flat".to_string()), + Decoration::NoPerspective => qualifiers.push("noperspective".to_string()), + Decoration::Centroid => qualifiers.push("centroid".to_string()), + Decoration::Sample => qualifiers.push("sample".to_string()), + Decoration::Patch => qualifiers.push("patch".to_string()), + Decoration::Shared => qualifiers.push("shared".to_string()), + Decoration::ReadOnly => qualifiers.push("readonly".to_string()), + Decoration::WriteOnly => qualifiers.push("writeonly".to_string()), + Decoration::Coherent => qualifiers.push("coherent".to_string()), + Decoration::Restrict => qualifiers.push("restrict".to_string()), + Decoration::Volatile => qualifiers.push("volatile".to_string()), + Decoration::Uniform => qualifiers.push("uniform".to_string()), + Decoration::Buffer => qualifiers.push("buffer".to_string()), + Decoration::PushConstant => layout_qualifiers.push("push_constant".to_string()), + Decoration::NonCoherent => qualifiers.push("noncoherent".to_string()), + Decoration::Yuv => layout_qualifiers.push("yuv".to_string()), + Decoration::Input => qualifiers.push("in".to_string()), + Decoration::Output => qualifiers.push("out".to_string()), + Decoration::InputOutput => qualifiers.push("inout".to_string()), + Decoration::Location(n) => layout_qualifiers.push(format!("location={n}")), + Decoration::Index(n) => layout_qualifiers.push(format!("index={n}")), + Decoration::InputAttachmentIndex(n) => { + layout_qualifiers.push(format!("input_attachment_index={n}")) + } + Decoration::SpecConst(n) => layout_qualifiers.push(format!("constant_id={n}")), + Decoration::Block(storage) => layout_qualifiers.push(Self::block_storage_str(storage)), + Decoration::Binding(n) => layout_qualifiers.push(format!("binding={n}")), + Decoration::Offset(n) => layout_qualifiers.push(format!("offset={n}")), + Decoration::MatrixPacking(packing) => { + layout_qualifiers.push(Self::matrix_packing_str(packing)) + } + Decoration::Depth(depth) => layout_qualifiers.push(Self::depth_str(depth)), + Decoration::ImageInternalFormat(format) => { + layout_qualifiers.push(Self::image_internal_format_str(format)) + } + Decoration::NumViews(n) => layout_qualifiers.push(format!("num_views={n}")), + Decoration::RasterOrdered => layout_qualifiers.push("d3d_raster_ordered".to_string()), + } + } + + fn qualifiers_str(precision: Precision, decorations: &Decorations) -> String { + let mut qualifiers = vec![]; + let mut layout_qualifiers = vec![]; + + decorations.decorations.iter().for_each(|&decoration| { + Self::add_qualifier_str(decoration, &mut qualifiers, &mut layout_qualifiers); + }); + + let mut result = String::new(); + if !layout_qualifiers.is_empty() { + write!( + result, + "layout({}) ", + layout_qualifiers.into_iter().collect::>().join(", ") + ) + .unwrap(); + } + if !qualifiers.is_empty() { + result.push_str(&qualifiers.into_iter().collect::>().join(" ")); + result.push(' '); + } + match precision { + Precision::NotApplicable => (), + Precision::Low => result.push_str("lowp "), + Precision::Medium => result.push_str("mediump "), + Precision::High => result.push_str("highp "), + }; + result + } + + fn built_in_str(built_in: BuiltIn, shader_type: ShaderType) -> String { + (match built_in { + BuiltIn::InstanceID => "gl_InstanceID", + BuiltIn::VertexID => "gl_VertexID", + BuiltIn::Position => "gl_Position", + BuiltIn::PointSize => "gl_PointSize", + BuiltIn::BaseVertex => "gl_BaseVertex", + BuiltIn::BaseInstance => "gl_BaseInstance", + BuiltIn::DrawID => "gl_DrawID", + BuiltIn::FragCoord => "gl_FragCoord", + BuiltIn::FrontFacing => "gl_FrontFacing", + BuiltIn::PointCoord => "gl_PointCoord", + BuiltIn::HelperInvocation => "gl_HelperInvocation", + BuiltIn::FragColor => "gl_FragColor", + BuiltIn::FragData => "gl_FragData", + BuiltIn::FragDepth => "gl_FragDepth", + BuiltIn::SecondaryFragColorEXT => "gl_SecondaryFragColorEXT", + BuiltIn::SecondaryFragDataEXT => "gl_SecondaryFragDataEXT", + BuiltIn::DepthRange => "gl_DepthRange", + BuiltIn::ViewIDOVR => "gl_ViewID_OVR", + BuiltIn::ClipDistance => "gl_ClipDistance", + BuiltIn::CullDistance => "gl_CullDistance", + BuiltIn::LastFragColor => "gl_LastFragColorARM", + BuiltIn::LastFragData => "gl_LastFragData", + BuiltIn::LastFragDepthARM => "gl_LastFragDepthARM", + BuiltIn::LastFragStencilARM => "gl_LastFragStencilARM", + BuiltIn::ShadingRateEXT => "gl_ShadingRateEXT", + BuiltIn::PrimitiveShadingRateEXT => "gl_PrimitiveShadingRateEXT", + BuiltIn::SampleID => "gl_SampleID", + BuiltIn::SamplePosition => "gl_SamplePosition", + BuiltIn::SampleMaskIn => "gl_SampleMaskIn", + BuiltIn::SampleMask => "gl_SampleMask", + BuiltIn::NumSamples => "gl_NumSamples", + BuiltIn::NumWorkGroups => "gl_NumWorkGroups", + BuiltIn::WorkGroupSize => "gl_WorkGroupSize", + BuiltIn::WorkGroupID => "gl_WorkGroupID", + BuiltIn::LocalInvocationID => "gl_LocalInvocationID", + BuiltIn::GlobalInvocationID => "gl_GlobalInvocationID", + BuiltIn::LocalInvocationIndex => "gl_LocalInvocationIndex", + BuiltIn::PerVertexIn => "gl_in", + BuiltIn::PerVertexOut => { + if shader_type == ShaderType::Geometry { + "" + } else { + "gl_out" + } + } + BuiltIn::PrimitiveIDIn => "gl_PrimitiveIDIn", + BuiltIn::InvocationID => "gl_InvocationID", + BuiltIn::PrimitiveID => "gl_PrimitiveID", + BuiltIn::LayerOut => "gl_Layer", + BuiltIn::LayerIn => "gl_Layer", + BuiltIn::PatchVerticesIn => "gl_PatchVerticesIn", + BuiltIn::TessLevelOuter => "gl_TessLevelOuter", + BuiltIn::TessLevelInner => "gl_TessLevelInner", + BuiltIn::TessCoord => "gl_TessCoord", + BuiltIn::BoundingBoxOES => "gl_BoundingBoxOES", + BuiltIn::PixelLocalEXT => "gl_PixelLocalEXT", + }) + .to_string() + } + + fn name_str(name: &Name, temp_prefix: &'static str, id: u32) -> String { + format!( + "{}{}{}", + match name.source { + // Make sure unnamed interface blocks remain unnamed. + NameSource::ShaderInterface => + if !name.name.is_empty() { + USER_SYMBOL_PREFIX + } else { + "" + }, + NameSource::Temporary => temp_prefix, + _ => "", + }, + name.name, + if name.source == NameSource::Temporary { format!("_{id}") } else { "".to_string() } + ) + } + + fn variable_declaration_str( + &self, + ir_meta: &IRMeta, + name: &Name, + type_id: TypeId, + precision: Precision, + decorations: &Decorations, + built_in: Option, + initializer: Option, + temp_prefix: &'static str, + id: u32, + ) -> (String, String) { + let type_info = &self.types[&type_id]; + let qualifiers = Self::qualifiers_str(precision, decorations); + let var_name = if let Some(built_in) = built_in { + Self::built_in_str(built_in, ir_meta.get_shader_type()) + } else { + Self::name_str(name, temp_prefix, id) + }; + + let mut declaration_text = format!( + "{qualifiers}{} {var_name}{}", + &type_info.use_text_pre, &type_info.use_text_post + ); + + if let Some(constant_id) = initializer { + write!(declaration_text, " = {}", self.get_constant_expression(constant_id)).unwrap(); + } + + (declaration_text, var_name) + } + + fn yuv_csc_standard_str(yuv_csc: YuvCscStandard) -> String { + (match yuv_csc { + YuvCscStandard::Itu601 => "itu_601", + YuvCscStandard::Itu601FullRange => "itu_601_full_range", + YuvCscStandard::Itu709 => "itu_709", + }) + .to_string() + } + + fn function_param_direction_str(direction: FunctionParamDirection) -> String { + (match direction { + FunctionParamDirection::Input => "in", + FunctionParamDirection::Output => "out", + FunctionParamDirection::InputOutput => "inout", + }) + .to_string() + } + + fn blend_equation_advanced_str(equations: &AdvancedBlendEquations) -> String { + if equations.all() { + return "layout(blend_support_all_equations) out;\n".to_string(); + } + + let mut equations_list = Vec::new(); + if equations.multiply { + equations_list.push("blend_support_multiply"); + } + if equations.screen { + equations_list.push("blend_support_screen"); + } + if equations.overlay { + equations_list.push("blend_support_overlay"); + } + if equations.darken { + equations_list.push("blend_support_darken"); + } + if equations.lighten { + equations_list.push("blend_support_lighten"); + } + if equations.colordodge { + equations_list.push("blend_support_colordodge"); + } + if equations.colorburn { + equations_list.push("blend_support_colorburn"); + } + if equations.hardlight { + equations_list.push("blend_support_hardlight"); + } + if equations.softlight { + equations_list.push("blend_support_softlight"); + } + if equations.difference { + equations_list.push("blend_support_difference"); + } + if equations.exclusion { + equations_list.push("blend_support_exclusion"); + } + if equations.hsl_hue { + equations_list.push("blend_support_hsl_hue"); + } + if equations.hsl_saturation { + equations_list.push("blend_support_hsl_saturation"); + } + if equations.hsl_color { + equations_list.push("blend_support_hsl_color"); + } + if equations.hsl_luminosity { + equations_list.push("blend_support_hsl_luminosity"); + } + + if equations_list.is_empty() { + return String::new(); + } + + format!("layout({}) out;\n", equations_list.join(", ")) + } + + fn tes_qualifiers_str( + primitive: TessellationPrimitive, + vertex_spacing: TessellationSpacing, + ordering: TessellationOrdering, + point_mode: bool, + ) -> String { + let mut qualifiers = Vec::new(); + + match primitive { + TessellationPrimitive::Undefined => (), + TessellationPrimitive::Triangles => qualifiers.push("triangles"), + TessellationPrimitive::Quads => qualifiers.push("quads"), + TessellationPrimitive::Isolines => qualifiers.push("isolines"), + } + match vertex_spacing { + TessellationSpacing::Undefined => (), + TessellationSpacing::EqualSpacing => qualifiers.push("equal"), + TessellationSpacing::FractionalEvenSpacing => { + qualifiers.push("fractional_even_spacing") + } + TessellationSpacing::FractionalOddSpacing => qualifiers.push("fractional_odd_spacing"), + } + match ordering { + TessellationOrdering::Undefined => (), + TessellationOrdering::Cw => qualifiers.push("cw"), + TessellationOrdering::Ccw => qualifiers.push("ccw"), + } + if point_mode { + qualifiers.push("point_mode"); + } + + format!("layout({}) in;\n", qualifiers.join(", ")) + } + + fn add_gs_primitive_str(qualifiers: &mut Vec, primitive: GeometryPrimitive) { + match primitive { + GeometryPrimitive::Undefined => (), + GeometryPrimitive::Points => qualifiers.push("points".to_string()), + GeometryPrimitive::Lines => qualifiers.push("lines".to_string()), + GeometryPrimitive::LinesAdjacency => qualifiers.push("lines_adjacency".to_string()), + GeometryPrimitive::Triangles => qualifiers.push("triangles".to_string()), + GeometryPrimitive::TrianglesAdjacency => { + qualifiers.push("triangles_adjacency".to_string()) + } + GeometryPrimitive::LineStrip => qualifiers.push("line_strip".to_string()), + GeometryPrimitive::TriangleStrip => qualifiers.push("triangle_strip".to_string()), + } + } + + fn gs_qualifiers_in_str(primitive: GeometryPrimitive, invocations: u32) -> String { + let mut qualifiers = Vec::new(); + Self::add_gs_primitive_str(&mut qualifiers, primitive); + if invocations > 0 { + qualifiers.push(format!("invocations = {invocations}")); + } + + format!("layout({}) in;\n", qualifiers.join(", ")) + } + + fn gs_qualifiers_out_str(primitive: GeometryPrimitive, max_vertices: u32) -> String { + let mut qualifiers = Vec::new(); + Self::add_gs_primitive_str(&mut qualifiers, primitive); + qualifiers.push(format!("max_vertices = {max_vertices}")); + + format!("layout({}) out;\n", qualifiers.join(", ")) + } + + fn declare_variables( + glsl_variables: &HashMap, + block: &mut String, + variables: &[VariableId], + ) { + variables.iter().for_each(|id| { + let glsl_variable = &glsl_variables[id]; + if !glsl_variable.skip_declaration { + writeln!(block, "{};", glsl_variable.declaration_text).unwrap(); + } + }); + } + + fn get_swizzle(index: u32) -> &'static str { + match index { + 0 => "x", + 1 => "y", + 2 => "z", + 3 => "w", + _ => panic!("Internal error: Unexpected swizzle index"), + } + } + + fn get_swizzle_multi(indices: &[u32]) -> String { + indices.iter().map(|&index| Self::get_swizzle(index)).collect::>().join("") + } + + fn get_constant_expression(&self, id: ConstantId) -> &String { + &self.constants[&id].text + } + + fn get_expression(&self, id: TypedId) -> &String { + match &id.id { + Id::Register(id) => &self.expressions[id], + Id::Constant(id) => &self.constants[id].text, + Id::Variable(id) => &self.variables[id].name, + } + } + fn get_expressions<'a>(&self, ids: &mut impl Iterator) -> String { + ids.map(|&id| self.get_expression(id)).fold(String::new(), |mut acc, id| { + if !acc.is_empty() { + acc.push_str(", "); + } + acc.push_str(id); + acc + }) + } + + fn indent_block(block: String, times: usize) -> String { + if block.is_empty() { + return "".to_string(); + } + + debug_assert!(block.ends_with('\n')); + // Only 1 and 2 are given, avoid excessive string overhead and handle the two cases. + let indent = if times == 1 { " " } else { " " }; + let replace_with = if times == 1 { "\n " } else { "\n " }; + let mut result = block.replace("\n", replace_with); + // The result is missing indentation from the beginning, and has two extra spaces in + // the end. + result.truncate(result.len() - indent.len()); + result.insert_str(0, indent); + result + } + + fn texture_common( + &mut self, + _ir_meta: &IRMeta, + built_in: &'static str, + result: RegisterId, + sampler: TypedId, + args: &[TypedId], + ) { + // TODO(http://anglebug.com/349994211): when targeting ES100, there is a suffix based on + // the sampler type. + + let sampler = self.get_expression(sampler); + + let expr = format!("{built_in}({sampler}, {})", self.get_expressions(&mut args.iter())); + self.expressions.insert(result, expr); + } +} + +impl ast::Target for Generator { + type BlockResult = String; + + fn begin(&mut self) {} + fn end(&mut self) -> String { + // TODO(http://anglebug.com/349994211): add #version and #extension lines when ANGLE uses + // the IR all the way through to + // codegen. + println!("{}", self.function_declarations); + // TODO(http://anglebug.com/349994211): return the resulting string instead + "".to_string() + } + + fn new_type(&mut self, ir_meta: &IRMeta, id: TypeId, type_info: &Type) { + let (declaration_text_pre, declaration_text_post, use_text_pre, use_text_post) = + match type_info { + Type::Scalar(..) | Type::Vector(..) | Type::Matrix(..) => { + (Self::basic_type_str(id), "".to_string(), None, None) + } + &Type::Array(type_id, count) => { + let base_type = &self.types[&type_id]; + ( + base_type.declaration_text_pre.clone(), + format!("{}[{count}]", &base_type.declaration_text_post), + Some(base_type.use_text_pre.clone()), + Some(format!("{}[{count}]", &base_type.use_text_post)), + ) + } + &Type::UnsizedArray(type_id) => { + let base_type = &self.types[&type_id]; + ( + base_type.declaration_text_pre.clone(), + format!("{}[]", &base_type.declaration_text_post), + Some(base_type.use_text_pre.clone()), + Some(format!("{}[]", &base_type.use_text_post)), + ) + } + &Type::Image(basic_type, image_type) => { + (Self::image_type_str(basic_type, image_type), "".to_string(), None, None) + } + Type::Struct(name, fields, specialization) => { + let name = Self::name_str(name, TEMP_STRUCT_PREFIX, id.id); + let declaration_text = format!( + "{} {{\n{}}}", + &name, + fields + .iter() + .enumerate() + .map(|(index, field)| format!( + " {};\n", + self.variable_declaration_str( + ir_meta, + &field.name, + field.type_id, + field.precision, + &field.decorations, + None, + None, + TEMP_STRUCT_FIELD_PREFIX, + index as u32 + ) + .0 + )) + .collect::>() + .join("") + ); + + // Declare the struct for future use. + if *specialization == StructSpecialization::Struct { + writeln!(self.type_declarations, "struct {};", &declaration_text).unwrap(); + } + + ( + declaration_text, + "".to_string(), + if *specialization == StructSpecialization::InterfaceBlock { + None + } else { + Some(name) + }, + None, + ) + } + Type::Pointer(pointee_type_id) => { + let pointee_type = &self.types[pointee_type_id]; + ( + pointee_type.declaration_text_pre.clone(), + pointee_type.declaration_text_post.clone(), + Some(pointee_type.use_text_pre.clone()), + Some(pointee_type.use_text_post.clone()), + ) + } + Type::DeadCodeEliminated => { + return; + } + }; + + let glsl_type = GlslType { + use_text_pre: use_text_pre.unwrap_or(declaration_text_pre.clone()), + use_text_post: use_text_post.unwrap_or(declaration_text_post.clone()), + declaration_text_pre, + declaration_text_post, + }; + + self.types.insert(id, glsl_type); + } + + fn new_constant(&mut self, _ir_meta: &IRMeta, id: ConstantId, constant: &Constant) { + let type_info = &self.types[&constant.type_id]; + let constant_text = match &constant.value { + &ConstantValue::Float(f) => format!("{f:?}"), + &ConstantValue::Int(i) => i.to_string(), + &ConstantValue::Uint(u) => format!("{u}u"), + &ConstantValue::Bool(b) => b.to_string(), + &ConstantValue::YuvCsc(yuv_csc) => Self::yuv_csc_standard_str(yuv_csc), + ConstantValue::Composite(elements) => format!( + "{}{}({})", + &type_info.use_text_pre, + &type_info.use_text_post, + elements + .iter() + .map(|element| self.constants[element].text.clone()) + .collect::>() + .join(", ") + ), + }; + + let glsl_constant = GlslConstant { text: constant_text, type_id: constant.type_id }; + + self.constants.insert(id, glsl_constant); + } + + fn new_variable(&mut self, ir_meta: &IRMeta, id: VariableId, variable: &Variable) { + let (declaration_text, name) = self.variable_declaration_str( + ir_meta, + &variable.name, + variable.type_id, + variable.precision, + &variable.decorations, + variable.built_in, + variable.initializer, + TEMP_VARIABLE_PREFIX, + id.id, + ); + + let skip_declaration = match variable.built_in { + Some(BuiltIn::PerVertexIn) => !ir_meta.is_per_vertex_in_redeclared(), + Some(BuiltIn::PerVertexOut) => !ir_meta.is_per_vertex_out_redeclared(), + Some(BuiltIn::FragDepth) + | Some(BuiltIn::LastFragData) + | Some(BuiltIn::LastFragColor) + | Some(BuiltIn::LastFragDepthARM) + | Some(BuiltIn::LastFragStencilARM) + | Some(BuiltIn::ClipDistance) + | Some(BuiltIn::CullDistance) => false, + Some(_) => true, + _ => false, + }; + + let glsl_variable = + GlslVariable { declaration_text, name, type_id: variable.type_id, skip_declaration }; + + self.variables.insert(id, glsl_variable); + + // TODO(http://anglebug.com/349994211): Add `invariant gl_Position;` and other globally + // qualified expressions where needed. + } + + fn new_function(&mut self, _ir_meta: &IRMeta, id: FunctionId, function: &Function) { + let qualifiers = + Self::qualifiers_str(function.return_precision, &function.return_decorations); + let return_type = &self.types[&function.return_type_id]; + let name = Self::name_str(&function.name, TEMP_FUNCTION_PREFIX, id.id); + + let declaration_text = format!( + "{qualifiers}{}{} {}({})", + &return_type.use_text_pre, + &return_type.use_text_post, + &name, + function + .params + .iter() + .map(|param| { + format!( + "{} {}", + Self::function_param_direction_str(param.direction), + &self.variables[¶m.variable_id].declaration_text + ) + }) + .collect::>() + .join(", ") + ); + + let glsl_function = + GlslFunction { declaration_text, name, return_type_id: function.return_type_id }; + + self.functions.insert(id, glsl_function); + } + + fn global_scope(&mut self, ir_meta: &IRMeta) { + match ir_meta.get_shader_type() { + ShaderType::Fragment => { + if ir_meta.get_early_fragment_tests() { + self.preamble.push_str("layout(early_fragment_tests) in;\n"); + } + self.preamble += + &Self::blend_equation_advanced_str(ir_meta.get_advanced_blend_equations()); + } + ShaderType::TessellationControl => { + writeln!(self.preamble, "layout(vertices = {}) out;", ir_meta.get_tcs_vertices()) + .unwrap(); + } + ShaderType::TessellationEvaluation => { + self.preamble += &Self::tes_qualifiers_str( + ir_meta.get_tes_primitive(), + ir_meta.get_tes_vertex_spacing(), + ir_meta.get_tes_ordering(), + ir_meta.get_tes_point_mode(), + ); + } + ShaderType::Geometry => { + self.preamble += &Self::gs_qualifiers_in_str( + ir_meta.get_gs_primitive_in(), + ir_meta.get_gs_invocations(), + ); + self.preamble += &Self::gs_qualifiers_out_str( + ir_meta.get_gs_primitive_out(), + ir_meta.get_gs_max_vertices(), + ); + } + _ => (), + }; + + Self::declare_variables( + &self.variables, + &mut self.global_variables, + ir_meta.all_global_variables(), + ); + + println!("{}", self.preamble); + println!("{}", self.type_declarations); + println!("{}", self.global_variables); + } + + fn begin_block(&mut self, _ir_meta: &IRMeta, variables: &[VariableId]) -> String { + let mut block = String::new(); + Self::declare_variables(&self.variables, &mut block, variables); + block + } + + fn merge_blocks(&mut self, blocks: Vec) -> String { + blocks.join("") + } + + fn swizzle_single( + &mut self, + _block_result: &mut String, + result: RegisterId, + id: TypedId, + index: u32, + ) { + let expr = format!("{}.{}", self.get_expression(id), Self::get_swizzle(index)); + self.expressions.insert(result, expr); + } + + fn swizzle_multi( + &mut self, + _block_result: &mut String, + result: RegisterId, + id: TypedId, + indices: &[u32], + ) { + let expr = format!("{}.{}", self.get_expression(id), Self::get_swizzle_multi(indices)); + self.expressions.insert(result, expr); + } + + fn index( + &mut self, + _block_result: &mut String, + result: RegisterId, + id: TypedId, + index: TypedId, + ) { + let expr = format!("{}[{}]", self.get_expression(id), self.get_expression(index)); + self.expressions.insert(result, expr); + } + + fn select_field( + &mut self, + _block_result: &mut String, + result: RegisterId, + id: TypedId, + index: u32, + field: &Field, + ) { + let lhs = self.get_expression(id); + let field_name = Self::name_str(&field.name, TEMP_STRUCT_FIELD_PREFIX, index); + // Note: if selecting the field of a nameless interface block, just use the field. + let expr = if lhs.is_empty() { field_name } else { format!("{}.{}", lhs, field_name) }; + self.expressions.insert(result, expr); + } + + fn construct_single( + &mut self, + _block_result: &mut String, + result: RegisterId, + type_id: TypeId, + id: TypedId, + ) { + let type_info = &self.types[&type_id]; + let expr = format!( + "{}{}({})", + type_info.use_text_pre, + type_info.use_text_post, + self.get_expression(id) + ); + self.expressions.insert(result, expr); + } + + fn construct_multi( + &mut self, + _block_result: &mut String, + result: RegisterId, + type_id: TypeId, + ids: &[TypedId], + ) { + let type_info = &self.types[&type_id]; + let expr = format!( + "{}{}({})", + type_info.use_text_pre, + type_info.use_text_post, + ids.iter().map(|&id| self.get_expression(id).clone()).collect::>().join(", ") + ); + self.expressions.insert(result, expr); + } + + fn load(&mut self, _block_result: &mut String, result: RegisterId, pointer: TypedId) { + let expr = self.get_expression(pointer).clone(); + self.expressions.insert(result, expr); + } + + fn store(&mut self, block_result: &mut String, pointer: TypedId, value: TypedId) { + let statement = + format!("{} = ({});\n", self.get_expression(pointer), self.get_expression(value)); + block_result.push_str(&statement); + } + + fn call( + &mut self, + block_result: &mut String, + result: Option, + function_id: FunctionId, + params: &[TypedId], + ) { + let statement = format!( + "{}({})", + self.functions[&function_id].name, + params.iter().map(|&id| self.get_expression(id).clone()).collect::>().join(", ") + ); + match result { + Some(result) => { + self.expressions.insert(result, statement); + } + None => { + writeln!(block_result, "{statement};").unwrap(); + } + }; + } + + fn unary( + &mut self, + _block_result: &mut String, + result: RegisterId, + unary_op: UnaryOpCode, + id: TypedId, + ) { + let id = self.get_expression(id); + let expr = match unary_op { + UnaryOpCode::ArrayLength => format!("({id}).length()"), + UnaryOpCode::Negate => format!("-({id})"), + UnaryOpCode::PostfixIncrement => format!("({id})++"), + UnaryOpCode::PostfixDecrement => format!("({id})--"), + UnaryOpCode::PrefixIncrement => format!("++({id})"), + UnaryOpCode::PrefixDecrement => format!("--({id})"), + UnaryOpCode::LogicalNot => format!("!({id})"), + UnaryOpCode::BitwiseNot => format!("~({id})"), + UnaryOpCode::Radians => format!("radians({id})"), + UnaryOpCode::Degrees => format!("degrees({id})"), + UnaryOpCode::Sin => format!("sin({id})"), + UnaryOpCode::Cos => format!("cos({id})"), + UnaryOpCode::Tan => format!("tan({id})"), + UnaryOpCode::Asin => format!("asin({id})"), + UnaryOpCode::Acos => format!("acos({id})"), + UnaryOpCode::Atan => format!("atan({id})"), + UnaryOpCode::Sinh => format!("sinh({id})"), + UnaryOpCode::Cosh => format!("cosh({id})"), + UnaryOpCode::Tanh => format!("tanh({id})"), + UnaryOpCode::Asinh => format!("asinh({id})"), + UnaryOpCode::Acosh => format!("acosh({id})"), + UnaryOpCode::Atanh => format!("atanh({id})"), + UnaryOpCode::Exp => format!("exp({id})"), + UnaryOpCode::Log => format!("log({id})"), + UnaryOpCode::Exp2 => format!("exp2({id})"), + UnaryOpCode::Log2 => format!("log2({id})"), + UnaryOpCode::Sqrt => format!("sqrt({id})"), + UnaryOpCode::Inversesqrt => format!("unversesqrt({id})"), + UnaryOpCode::Abs => format!("abs({id})"), + UnaryOpCode::Sign => format!("sign({id})"), + UnaryOpCode::Floor => format!("floor({id})"), + UnaryOpCode::Trunc => format!("trunc({id})"), + UnaryOpCode::Round => format!("round({id})"), + UnaryOpCode::RoundEven => format!("roundEven({id})"), + UnaryOpCode::Ceil => format!("ceil({id})"), + UnaryOpCode::Fract => format!("fract({id})"), + UnaryOpCode::Isnan => format!("isnan({id})"), + UnaryOpCode::Isinf => format!("isinf({id})"), + UnaryOpCode::FloatBitsToInt => format!("floatBitsToInt({id})"), + UnaryOpCode::FloatBitsToUint => format!("FloatBitsToUint({id})"), + UnaryOpCode::IntBitsToFloat => format!("intBitsToFloat({id})"), + UnaryOpCode::UintBitsToFloat => format!("UintBitsToFloat({id})"), + UnaryOpCode::PackSnorm2x16 => format!("packSnorm2x16({id})"), + UnaryOpCode::PackHalf2x16 => format!("packHalf2x16({id})"), + UnaryOpCode::UnpackSnorm2x16 => format!("unpackSnorm2x16({id})"), + UnaryOpCode::UnpackHalf2x16 => format!("unpackHalf2x16({id})"), + UnaryOpCode::PackUnorm2x16 => format!("packUnorm2x16({id})"), + UnaryOpCode::UnpackUnorm2x16 => format!("unpackUnorm2x16({id})"), + UnaryOpCode::PackUnorm4x8 => format!("packUnorm4x8({id})"), + UnaryOpCode::PackSnorm4x8 => format!("packSnorm4x8({id})"), + UnaryOpCode::UnpackUnorm4x8 => format!("unpackUnorm4x8({id})"), + UnaryOpCode::UnpackSnorm4x8 => format!("unpackSnorm4x8({id})"), + UnaryOpCode::Length => format!("length({id})"), + UnaryOpCode::Normalize => format!("normalize({id})"), + UnaryOpCode::Transpose => format!("transpose({id})"), + UnaryOpCode::Determinant => format!("determinant({id})"), + UnaryOpCode::Inverse => format!("inverse({id})"), + UnaryOpCode::Any => format!("any({id})"), + UnaryOpCode::All => format!("all({id})"), + UnaryOpCode::Not => format!("not({id})"), + UnaryOpCode::BitfieldReverse => format!("bitfieldReverse({id})"), + UnaryOpCode::BitCount => format!("bitCount({id})"), + UnaryOpCode::FindLSB => format!("findLSB({id})"), + UnaryOpCode::FindMSB => format!("findMSB({id})"), + UnaryOpCode::DFdx => format!("dFdx({id})"), + UnaryOpCode::DFdy => format!("dFdy({id})"), + UnaryOpCode::Fwidth => format!("fwidth({id})"), + UnaryOpCode::InterpolateAtCentroid => format!("interpolateAtCentroid({id})"), + UnaryOpCode::AtomicCounter => format!("atomicCounter({id})"), + UnaryOpCode::AtomicCounterIncrement => format!("atomicCounterIncrement({id})"), + UnaryOpCode::AtomicCounterDecrement => format!("atomicCounterDecrement({id})"), + UnaryOpCode::ImageSize => format!("imageSize({id})"), + UnaryOpCode::PixelLocalLoadANGLE => { + panic!("Internal error: Unexpected non-GLSL opcode for GLSL generator") + } + }; + self.expressions.insert(result, expr); + } + + fn binary( + &mut self, + _block_result: &mut String, + result: RegisterId, + binary_op: BinaryOpCode, + lhs: TypedId, + rhs: TypedId, + ) { + let lhs = self.get_expression(lhs); + let rhs = self.get_expression(rhs); + let (call, op) = match binary_op { + BinaryOpCode::Add => (false, "+"), + BinaryOpCode::Sub => (false, "-"), + BinaryOpCode::Mul => (false, "*"), + BinaryOpCode::VectorTimesScalar => (false, "*"), + BinaryOpCode::MatrixTimesScalar => (false, "*"), + BinaryOpCode::VectorTimesMatrix => (false, "*"), + BinaryOpCode::MatrixTimesVector => (false, "*"), + BinaryOpCode::MatrixTimesMatrix => (false, "*"), + BinaryOpCode::Div => (false, "/"), + BinaryOpCode::IMod => (false, "%"), + BinaryOpCode::LogicalXor => (false, "^^"), + BinaryOpCode::Equal => (false, "=="), + BinaryOpCode::NotEqual => (false, "!="), + BinaryOpCode::LessThan => (false, "<"), + BinaryOpCode::GreaterThan => (false, ">"), + BinaryOpCode::LessThanEqual => (false, "<="), + BinaryOpCode::GreaterThanEqual => (false, ">="), + BinaryOpCode::BitShiftLeft => (false, "<<"), + BinaryOpCode::BitShiftRight => (false, ">>"), + BinaryOpCode::BitwiseOr => (false, "|"), + BinaryOpCode::BitwiseXor => (false, "^"), + BinaryOpCode::BitwiseAnd => (false, "&"), + BinaryOpCode::Atan => (true, "atan"), + BinaryOpCode::Pow => (true, "pow"), + BinaryOpCode::Mod => (true, "mod"), + BinaryOpCode::Min => (true, "min"), + BinaryOpCode::Max => (true, "max"), + BinaryOpCode::Step => (true, "step"), + BinaryOpCode::Modf => (true, "modf"), + BinaryOpCode::Frexp => (true, "frexp"), + BinaryOpCode::Ldexp => (true, "ldexp"), + BinaryOpCode::Distance => (true, "distance"), + BinaryOpCode::Dot => (true, "dot"), + BinaryOpCode::Cross => (true, "cross"), + BinaryOpCode::Reflect => (true, "reflect"), + BinaryOpCode::MatrixCompMult => (true, "matrixCompMult"), + BinaryOpCode::OuterProduct => (true, "outerProduct"), + BinaryOpCode::LessThanVec => (true, "lessThan"), + BinaryOpCode::LessThanEqualVec => (true, "lessThanEqual"), + BinaryOpCode::GreaterThanVec => (true, "greaterThan"), + BinaryOpCode::GreaterThanEqualVec => (true, "greaterThanEqual"), + BinaryOpCode::EqualVec => (true, "equal"), + BinaryOpCode::NotEqualVec => (true, "notEqual"), + BinaryOpCode::InterpolateAtSample => (true, "interpolateAtSample"), + BinaryOpCode::InterpolateAtOffset => (true, "interpolateAtOffset"), + BinaryOpCode::AtomicAdd => (true, "atomicAdd"), + BinaryOpCode::AtomicMin => (true, "atomicMin"), + BinaryOpCode::AtomicMax => (true, "atomicMax"), + BinaryOpCode::AtomicAnd => (true, "atomicAnd"), + BinaryOpCode::AtomicOr => (true, "atomicOr"), + BinaryOpCode::AtomicXor => (true, "atomicXor"), + BinaryOpCode::AtomicExchange => (true, "atomicExchange"), + }; + let expr = + if call { format!("{op}({lhs}, {rhs})") } else { format!("({lhs}) {op} ({rhs})") }; + self.expressions.insert(result, expr); + } + + fn built_in( + &mut self, + block_result: &mut String, + result: Option, + built_in_op: BuiltInOpCode, + args: &[TypedId], + ) { + let built_in = match built_in_op { + BuiltInOpCode::Clamp => "clamp", + BuiltInOpCode::Mix => "mix", + BuiltInOpCode::Smoothstep => "smoothstep", + BuiltInOpCode::Fma => "fma", + BuiltInOpCode::Faceforward => "faceforward", + BuiltInOpCode::Refract => "refract", + BuiltInOpCode::BitfieldExtract => "bitfieldExtract", + BuiltInOpCode::BitfieldInsert => "bitfieldInsert", + BuiltInOpCode::UaddCarry => "uaddCarry", + BuiltInOpCode::UsubBorrow => "usubBorrow", + BuiltInOpCode::UmulExtended => "umulExtended", + BuiltInOpCode::ImulExtended => "imulExtended", + BuiltInOpCode::TextureSize => "textureSize", + BuiltInOpCode::TextureQueryLod => "textureQueryLod", + BuiltInOpCode::TexelFetch => "texelFetch", + BuiltInOpCode::TexelFetchOffset => "texelFetchOffset", + BuiltInOpCode::Rgb2Yuv => "rgb_2_yuv", + BuiltInOpCode::Yuv2Rgb => "yuv_2_rgb", + BuiltInOpCode::AtomicCompSwap => "atomicCompSwap", + BuiltInOpCode::ImageStore => "imageStore", + BuiltInOpCode::ImageLoad => "imageLoad", + BuiltInOpCode::ImageAtomicAdd => "imageAtomicAdd", + BuiltInOpCode::ImageAtomicMin => "imageAtomicMin", + BuiltInOpCode::ImageAtomicMax => "imageAtomicMax", + BuiltInOpCode::ImageAtomicAnd => "imageAtomicAnd", + BuiltInOpCode::ImageAtomicOr => "imageAtomicOr", + BuiltInOpCode::ImageAtomicXor => "imageAtomicXor", + BuiltInOpCode::ImageAtomicExchange => "imageAtomicExchange", + BuiltInOpCode::ImageAtomicCompSwap => "imageAtomicCompSwap", + BuiltInOpCode::MemoryBarrier => "memoryBarrier", + BuiltInOpCode::MemoryBarrierAtomicCounter => "memoryBarrierAtomicCounter", + BuiltInOpCode::MemoryBarrierBuffer => "memoryBarrierBuffer", + BuiltInOpCode::MemoryBarrierImage => "memoryBarrierImage", + BuiltInOpCode::Barrier => "barrier", + BuiltInOpCode::MemoryBarrierShared => "memoryBarrierShared", + BuiltInOpCode::GroupMemoryBarrier => "groupMemoryBarrier", + BuiltInOpCode::EmitVertex => "EmitVertex", + BuiltInOpCode::EndPrimitive => "EndPrimitive", + BuiltInOpCode::BeginInvocationInterlockNV => "beginInvocationInterlockNV", + BuiltInOpCode::EndInvocationInterlockNV => "endInvocationInterlockNV", + BuiltInOpCode::BeginFragmentShaderOrderingINTEL => "beginFragmentShaderOrderingINTEL", + BuiltInOpCode::BeginInvocationInterlockARB => "beginInvocationInterlockARB", + BuiltInOpCode::EndInvocationInterlockARB => "endInvocationInterlockARB", + BuiltInOpCode::PixelLocalStoreANGLE + | BuiltInOpCode::SubpassLoad + | BuiltInOpCode::NumSamples + | BuiltInOpCode::SamplePosition + | BuiltInOpCode::InterpolateAtCenter + | BuiltInOpCode::LoopForwardProgress + | BuiltInOpCode::Saturate => { + panic!("Internal error: Unexpected non-GLSL opcode for GLSL generator") + } + }; + let expr = format!("{built_in}({})", self.get_expressions(&mut args.iter())); + if let Some(result) = result { + self.expressions.insert(result, expr); + } else { + writeln!(block_result, "{expr};").unwrap(); + } + } + + fn texture( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if is_proj { "textureProjOffset" } else { "textureOffset" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, offset]); + } else { + let built_in = if is_proj { "textureProj" } else { "texture" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord]); + } + } + + fn texture_compare( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + ) { + self.texture_common(ir_meta, "texture", result, sampler, &[coord, compare]); + } + + fn texture_lod( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + lod: TypedId, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if is_proj { "textureProjLodOffset" } else { "textureLodOffset" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, lod, offset]); + } else { + let built_in = if is_proj { "textureProjLod" } else { "textureLod" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, lod]); + } + } + + fn texture_compare_lod( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + lod: TypedId, + ) { + self.texture_common(ir_meta, "textureLod", result, sampler, &[coord, compare, lod]); + } + + fn texture_bias( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + bias: TypedId, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if is_proj { "textureProjOffset" } else { "textureOffset" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, offset, bias]); + } else { + let built_in = if is_proj { "textureProj" } else { "texture" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, bias]); + } + } + + fn texture_compare_bias( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + bias: TypedId, + ) { + self.texture_common(ir_meta, "texture", result, sampler, &[coord, compare, bias]); + } + + fn texture_grad( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + dx: TypedId, + dy: TypedId, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if is_proj { "textureProjGradOffset" } else { "textureGradOffset" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, dx, dy, offset]); + } else { + let built_in = if is_proj { "textureProjGrad" } else { "textureGrad" }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, dx, dy]); + } + } + + fn texture_gather( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if ir_meta.get_type(offset.type_id).is_array() { + "textureGatherOffsets" + } else { + "textureGatherOffset" + }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, offset]); + } else { + self.texture_common(ir_meta, "textureGather", result, sampler, &[coord]); + } + } + + fn texture_gather_component( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + component: TypedId, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if ir_meta.get_type(offset.type_id).is_array() { + "textureGatherOffsets" + } else { + "textureGatherOffset" + }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, offset, component]); + } else { + self.texture_common(ir_meta, "textureGather", result, sampler, &[coord, component]); + } + } + + fn texture_gather_ref( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut String, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + refz: TypedId, + offset: Option, + ) { + if let Some(offset) = offset { + let built_in = if ir_meta.get_type(offset.type_id).is_array() { + "textureGatherOffsets" + } else { + "textureGatherOffset" + }; + self.texture_common(ir_meta, built_in, result, sampler, &[coord, refz, offset]); + } else { + self.texture_common(ir_meta, "textureGather", result, sampler, &[coord, refz]); + } + } + + fn branch_discard(&mut self, block: &mut String) { + block.push_str("discard;\n"); + } + fn branch_return(&mut self, block: &mut String, value: Option) { + if let Some(id) = value { + writeln!(block, "return {};", self.get_expression(id)).unwrap(); + } else { + block.push_str("return;\n"); + } + } + fn branch_break(&mut self, block: &mut String) { + block.push_str("break;\n"); + } + fn branch_continue(&mut self, block: &mut String) { + block.push_str("continue;\n"); + } + fn branch_if( + &mut self, + block: &mut String, + condition: TypedId, + true_block: Option, + false_block: Option, + ) { + // The true block should always be present. + writeln!( + block, + "if ({}) {{\n{}}}", + self.get_expression(condition), + Self::indent_block(true_block.unwrap(), 1) + ) + .unwrap(); + if let Some(false_block) = false_block { + writeln!(block, "else {{\n{}}}", Self::indent_block(false_block, 1)).unwrap(); + } + } + fn branch_loop( + &mut self, + block: &mut String, + loop_condition_block: Option, + body_block: Option, + ) { + // The condition and body blocks should always be present. + writeln!( + block, + "for (;;) {{\n{}\n{}}}", + Self::indent_block(loop_condition_block.unwrap(), 1), + Self::indent_block(body_block.unwrap(), 1) + ) + .unwrap(); + } + fn branch_do_loop(&mut self, block: &mut String, body_block: Option) { + // The condition and body blocks should always be present. The difference between + // DoLoop and Loop is effectively that the condition block is evaluated after the body + // instead of before. + writeln!(block, "for (;;) {{\n{}}}", Self::indent_block(body_block.unwrap(), 1)).unwrap(); + } + fn branch_loop_if(&mut self, block: &mut String, condition: TypedId) { + // The condition block of a loop ends in `if (!condition) break;` + writeln!(block, "if (!({}))\n break;", self.get_expression(condition)).unwrap(); + } + fn branch_switch( + &mut self, + block: &mut String, + value: TypedId, + case_ids: &[Option], + case_blocks: Vec, + ) { + writeln!(block, "switch ({}) {{", self.get_expression(value)).unwrap(); + case_blocks.into_iter().zip(case_ids).for_each(|(case, &case_id)| { + let case_line = if let Some(case_id) = case_id { + format!(" case {}:\n", self.get_constant_expression(case_id)) + } else { + " default:\n".to_string() + }; + + let case_body = if case.is_empty() { + "".to_string() + } else { + format!(" {{\n{} }}\n", Self::indent_block(case, 2)) + }; + + block.push_str(&case_line); + block.push_str(&case_body); + }); + block.push_str("}\n"); + } + + // Take the current AST and place it as the body of the given function. + fn end_function(&mut self, block_result: String, id: FunctionId) { + writeln!( + self.function_declarations, + "{} {{\n{}}}", + self.functions[&id].declaration_text, + Self::indent_block(block_result, 1), + ) + .unwrap(); + } +} diff --git a/src/compiler/translator/ir/src/output/ir_to_legacy.cpp b/src/compiler/translator/ir/src/output/ir_to_legacy.cpp new file mode 100644 index 00000000000..3a689872e2c --- /dev/null +++ b/src/compiler/translator/ir/src/output/ir_to_legacy.cpp @@ -0,0 +1,1675 @@ +// +// Copyright 2025 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. +// + +#include "compiler/translator/ir/src/output/ir_to_legacy.h" + +#include "compiler/translator/ir/src/output/legacy.rs.h" + +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/util.h" + +#include + +namespace sh +{ +namespace ir +{ +namespace ffi +{ + +namespace +{ +ImmutableString Str(rust::Str str) +{ + ImmutableStringBuilder builder(str.length()); + builder << ImmutableString(str.data(), str.length()); + return builder; +} + +ImmutableString Str(const SymbolName &name) +{ + constexpr uint32_t kNoId = 0xFFFF'FFFF; + const bool appendId = name.id != kNoId; + ImmutableStringBuilder builder(name.name.length() + (appendId ? 1 + 11 : 0)); + builder << ImmutableString(name.name.data(), name.name.length()); + if (appendId) + { + builder << '_'; + builder << name.id; + } + return builder; +} + +TType *Type(const TType *baseType, const ASTType &astType) +{ + TType *completeType = new TType(*baseType); + + TLayoutQualifier layoutQualifier = completeType->getLayoutQualifier(); + const ASTLayoutQualifier &astLayoutQualifier = astType.layout_qualifier; + layoutQualifier.location = astLayoutQualifier.location; + layoutQualifier.locationsSpecified = layoutQualifier.location >= 0; + layoutQualifier.matrixPacking = + static_cast(astLayoutQualifier.matrix_packing); + layoutQualifier.blockStorage = + static_cast(astLayoutQualifier.block_storage); + layoutQualifier.binding = astLayoutQualifier.binding; + layoutQualifier.offset = astLayoutQualifier.offset; + layoutQualifier.pushConstant = astLayoutQualifier.push_constant; + layoutQualifier.depth = static_cast(astLayoutQualifier.depth); + layoutQualifier.imageInternalFormat = + static_cast(astLayoutQualifier.image_internal_format); + layoutQualifier.numViews = astLayoutQualifier.num_views; + layoutQualifier.yuv = astLayoutQualifier.yuv; + layoutQualifier.index = astLayoutQualifier.index; + layoutQualifier.inputAttachmentIndex = astLayoutQualifier.input_attachment_index; + layoutQualifier.noncoherent = astLayoutQualifier.noncoherent; + layoutQualifier.rasterOrdered = astLayoutQualifier.raster_ordered; + + TMemoryQualifier memoryQualifier = completeType->getMemoryQualifier(); + const ASTMemoryQualifier &astMemoryQualifier = astType.memory_qualifier; + memoryQualifier.readonly = astMemoryQualifier.readonly; + memoryQualifier.writeonly = astMemoryQualifier.writeonly; + memoryQualifier.coherent = astMemoryQualifier.coherent; + memoryQualifier.restrictQualifier = astMemoryQualifier.restrict_qualifier; + memoryQualifier.volatileQualifier = astMemoryQualifier.volatile_qualifier; + + completeType->setQualifier(static_cast(astType.qualifier)); + completeType->setPrecision(static_cast(astType.precision)); + completeType->setInvariant(astType.invariant); + completeType->setPrecise(astType.precise); + completeType->setInterpolant(astType.interpolant); + completeType->setLayoutQualifier(layoutQualifier); + completeType->setMemoryQualifier(memoryQualifier); + + return completeType; +} + +TIntermTyped *Expr(const Expression &expr) +{ + return expr.needs_copy ? expr.node->deepCopy() : expr.node; +} + +TIntermSequence Exprs(rust::Slice exprs) +{ + TIntermSequence seq; + for (const Expression &expr : exprs) + { + seq.push_back(Expr(expr)); + } + return seq; +} + +TIntermTyped *UnaryBuiltIn(TCompiler *compiler, const char *name, const Expression &operand) +{ + TIntermTyped *operandNode = Expr(operand); + return CreateBuiltInUnaryFunctionCallNode(name, operandNode, compiler->getSymbolTable(), + compiler->getShaderVersion()); +} + +TIntermTyped *BinaryBuiltIn(TCompiler *compiler, + const char *name, + const Expression &lhs, + const Expression &rhs) +{ + TIntermTyped *lhsNode = Expr(lhs); + TIntermTyped *rhsNode = Expr(rhs); + return CreateBuiltInFunctionCallNode(name, {lhsNode, rhsNode}, compiler->getSymbolTable(), + compiler->getShaderVersion()); +} + +TIntermTyped *BuiltIn(TCompiler *compiler, const char *name, rust::Slice args) +{ + TIntermSequence argsNodes = Exprs(args); + return CreateBuiltInFunctionCallNode(name, &argsNodes, compiler->getSymbolTable(), + compiler->getShaderVersion()); +} +} // namespace + +TType *make_basic_type(ASTBasicType basicType) +{ + return new TType(static_cast(basicType)); +} + +TType *make_vector_type(const TType *scalarType, uint32_t count) +{ + return new TType(scalarType->getBasicType(), EbpHigh, EvqTemporary, count); +} + +TType *make_matrix_type(const TType *vectorType, uint32_t count) +{ + return new TType(vectorType->getBasicType(), EbpHigh, EvqTemporary, count, + vectorType->getNominalSize()); +} + +TType *make_array_type(const TType *elementType, uint32_t count) +{ + TType *arrayType = new TType(*elementType); + arrayType->makeArray(count); + return arrayType; +} + +TType *make_unsized_array_type(const TType *elementType) +{ + return make_array_type(elementType, 0); +} + +TType *make_struct_type(TCompiler *compiler, + const SymbolName &name, + rust::Slice fields, + bool isInterfaceBlock) +{ + const SymbolType structSymbolType = static_cast(name.symbol_type); + // The field symbol types usually inherit from the struct itself. Except when the symbol type + // is empty (nameless struct), the fields are still user-defined. + const SymbolType fieldSymbolType = Str(name) == "" ? SymbolType::UserDefined : structSymbolType; + + TFieldList *fieldList = new TFieldList(); + fieldList->reserve(fields.size()); + for (const ASTFieldInfo &fieldInfo : fields) + { + TType *fieldType = Type(fieldInfo.base_type, fieldInfo.ast_type); + if (fieldSymbolType == SymbolType::BuiltIn) + { + if (fieldInfo.name == "gl_Position") + { + fieldType->setQualifier(EvqPosition); + } + if (fieldInfo.name == "gl_PointSize") + { + fieldType->setQualifier(EvqPointSize); + } + if (fieldInfo.name == "gl_ClipDistance") + { + fieldType->setQualifier(EvqClipDistance); + } + if (fieldInfo.name == "gl_CullDistance") + { + fieldType->setQualifier(EvqCullDistance); + } + } + + fieldList->push_back( + new TField(fieldType, Str(fieldInfo.name), TSourceLoc(), fieldSymbolType)); + } + + if (isInterfaceBlock) + { + // Note: Information expected in TLayoutQualifier is set when the interface block type is + // used to declare a variable, where the decorations are. + TInterfaceBlock *interfaceBlock = + new TInterfaceBlock(&compiler->getSymbolTable(), Str(name), fieldList, + TLayoutQualifier{}, structSymbolType); + compiler->getSymbolTable().redeclare(interfaceBlock); + // Same with qualifier and layoutQualifier. + return new TType(interfaceBlock, EvqTemporary, TLayoutQualifier{}); + } + else + { + TStructure *structure = + new TStructure(&compiler->getSymbolTable(), Str(name), fieldList, structSymbolType); + return new TType(structure, false); + } +} + +TIntermNode *declare_struct(TCompiler *compiler, const TType *structType) +{ + TType *structSpecifierType = new TType(structType->getStruct(), true); + structSpecifierType->setQualifier(EvqGlobal); + + TVariable *structVariable = new TVariable(&compiler->getSymbolTable(), kEmptyImmutableString, + structSpecifierType, SymbolType::Empty); + TIntermSymbol *structDeclarator = new TIntermSymbol(structVariable); + TIntermDeclaration *structDeclaration = new TIntermDeclaration; + structDeclaration->appendDeclarator(structDeclarator); + + return structDeclaration; +} + +TIntermTyped *make_float_constant(float f) +{ + return CreateFloatNode(f, EbpUndefined); +} + +TIntermTyped *make_int_constant(int32_t i) +{ + return CreateIndexNode(i); +} + +TIntermTyped *make_uint_constant(uint32_t u) +{ + return CreateUIntNode(u); +} + +TIntermTyped *make_bool_constant(bool b) +{ + return CreateBoolNode(b); +} + +TIntermTyped *make_yuv_csc_constant(ASTYuvCscStandardEXT yuvCsc) +{ + return CreateYuvCscNode(static_cast(yuvCsc)); +} + +TIntermTyped *make_composite_constant(rust::Slice elements, + const TType *constantType) +{ + TInfoSinkBase unusedSink; + TDiagnostics unused(unusedSink); + + TType constantTypeQualified = TType(*constantType); + constantTypeQualified.setQualifier(EvqConst); + + TIntermSequence args(elements.begin(), elements.end()); + return TIntermAggregate::CreateConstructor(constantTypeQualified, &args)->fold(&unused); +} + +TIntermTyped *make_constant_variable(TCompiler *compiler, + const TType *constantType, + TIntermTyped *value) +{ + ASSERT(value->hasConstantValue()); + + TType *constantTypeQualified = new TType(*constantType); + constantTypeQualified->setQualifier(EvqConst); + + // If the IR was unable to assign a precision to the constant, it means it was not used in any + // context that needed a precision, for example `(variable ? const1 : const2) < const3` + if (IsPrecisionApplicableToType(constantType->getBasicType()) && + constantType->getPrecision() == EbpUndefined) + { + constantTypeQualified->setPrecision(EbpHigh); + } + + TVariable *variable = new TVariable(&compiler->getSymbolTable(), kEmptyImmutableString, + constantTypeQualified, SymbolType::AngleInternal); + + const TConstantUnion *constArray = value->getConstantValue(); + if (constArray) + { + variable->shareConstPointer(constArray); + } + + return new TIntermSymbol(variable); +} + +TIntermTyped *make_variable(TCompiler *compiler, + const SymbolName &name, + const TType *baseType, + const ASTType &astType, + bool isRedeclaredBuiltIn, + bool isStaticUse) +{ + SymbolType symbolType = static_cast(name.symbol_type); + const TVariable *variable = nullptr; + + if (symbolType == SymbolType::BuiltIn && !isRedeclaredBuiltIn) + { + variable = static_cast( + compiler->getSymbolTable().findBuiltIn(Str(name.name), compiler->getShaderVersion())); + ASSERT(variable != nullptr); + } + else + { + // If the variable is an interface block, AST specifies some variable information in + // TInterfaceBlock too. Adjust the TInterfaceBlock right now, overriding const-ness knowing + // that the interface block is paired with a single variable anyway. + TType *varType = Type(baseType, astType); + if (varType->isInterfaceBlock()) + { + TInterfaceBlock *block = const_cast(varType->getInterfaceBlock()); + block->setBlockStorage(varType->getLayoutQualifier().blockStorage); + block->setBlockBinding(varType->getLayoutQualifier().binding); + } + + TVariable *newVariable = + new TVariable(&compiler->getSymbolTable(), Str(name), varType, symbolType); + + if (symbolType != SymbolType::Empty && + (varType->isInterfaceBlock() || IsShaderIn(varType->getQualifier()) || + IsShaderOut(varType->getQualifier()))) + { + compiler->getSymbolTable().redeclare(newVariable); + } + variable = newVariable; + } + if (isStaticUse) + { + compiler->getSymbolTable().markStaticUse(*variable); + } + return new TIntermSymbol(variable); +} + +TIntermTyped *make_nameless_block_field_variable(TCompiler *compiler, + TIntermTyped *variable, + uint32_t fieldIndex, + const SymbolName &name, + const TType *baseType, + const ASTType &astType) +{ + SymbolType symbolType = static_cast(name.symbol_type); + const TInterfaceBlock *interfaceBlock = variable->getType().getInterfaceBlock(); + + // If the variable is an interface block, AST specifies some variable information in + // TInterfaceBlock too. Adjust the TInterfaceBlock right now, overriding const-ness knowing + // that the interface block is paired with a single variable anyway. + TType *fieldType = Type(baseType, astType); + fieldType->setInterfaceBlockField(interfaceBlock, fieldIndex); + fieldType->setQualifier(variable->getType().getQualifier()); + + TVariable *field_variable = + new TVariable(&compiler->getSymbolTable(), Str(name), fieldType, symbolType); + compiler->getSymbolTable().redeclare(field_variable); + return new TIntermSymbol(field_variable); +} + +TIntermNode *declare_variable(TIntermTyped *variable) +{ + TIntermDeclaration *declaration = new TIntermDeclaration; + declaration->appendDeclarator(variable->getAsSymbolNode()); + return declaration; +} + +TIntermNode *declare_variable_with_initializer(TIntermTyped *variable, TIntermTyped *value) +{ + ASSERT(value->hasConstantValue()); + + TIntermDeclaration *declaration = new TIntermDeclaration; + TIntermBinary *init = + new TIntermBinary(EOpInitialize, variable->getAsSymbolNode(), value->deepCopy()); + declaration->appendDeclarator(init); + return declaration; +} + +TIntermNode *globally_qualify_built_in_invariant(TIntermTyped *variable) +{ + return new TIntermGlobalQualifierDeclaration(variable->getAsSymbolNode()->deepCopy(), false, + TSourceLoc()); +} + +TIntermNode *globally_qualify_built_in_precise(TIntermTyped *variable) +{ + return new TIntermGlobalQualifierDeclaration(variable->getAsSymbolNode()->deepCopy(), true, + TSourceLoc()); +} + +TFunction *make_function(TCompiler *compiler, + const SymbolName &name, + const TType *returnType, + const ASTType &returnAstType, + rust::Slice params, + rust::Slice paramDirections) +{ + TFunction *function = new TFunction(&compiler->getSymbolTable(), Str(name), + static_cast(name.symbol_type), + Type(returnType, returnAstType), false); + + ASSERT(params.size() == paramDirections.size()); + for (size_t paramIndex = 0; paramIndex < params.size(); ++paramIndex) + { + const TVariable *param = ¶ms[paramIndex]->getAsSymbolNode()->variable(); + + // Update the qualifier of function param variables to the correct EvqParamIn/Out/InOut, + // ignoring const-ness since each param is given its own TType. + const TQualifier qualifier = static_cast(paramDirections[paramIndex]); + const_cast(param->getType()).setQualifier(qualifier); + + function->addParameter(param); + } + + return function; +} + +TIntermNode *declare_function(const TFunction *function, TIntermBlock *body) +{ + return new TIntermFunctionDefinition(new TIntermFunctionPrototype(function), body); +} + +TIntermBlock *make_interm_block() +{ + return new TIntermBlock; +} + +void append_instructions_to_block(TIntermBlock *block, rust::Slice nodes) +{ + block->getSequence()->insert(block->getSequence()->end(), nodes.begin(), nodes.end()); +} + +void append_blocks_to_block(TIntermBlock *block, rust::Slice blocksToAppend) +{ + for (const TIntermBlock *toAppend : blocksToAppend) + { + block->getSequence()->insert(block->getSequence()->end(), toAppend->getSequence()->begin(), + toAppend->getSequence()->end()); + } +} + +TIntermTyped *swizzle(const Expression &operand, rust::Slice indices) +{ + TVector indicesVec(indices.begin(), indices.end()); + return new TIntermSwizzle(Expr(operand), indicesVec); +} + +TIntermTyped *index(const Expression &operand, const Expression &index) +{ + TIntermTyped *operandNode = Expr(operand); + TIntermTyped *indexNode = Expr(index); + TIntermConstantUnion *indexNodeAsConst = indexNode->getAsConstantUnion(); + const TOperator op = indexNodeAsConst != nullptr ? EOpIndexDirect : EOpIndexIndirect; + + // The AST expects indices to be signed integers for some reason. + if (op == EOpIndexDirect && indexNodeAsConst->getConstantValue()->getType() == EbtUInt) + { + indexNode = CreateIndexNode(indexNodeAsConst->getConstantValue()->getUConst()); + } + + return new TIntermBinary(op, operandNode, indexNode); +} + +TIntermTyped *select_field(const Expression &operand, uint32_t fieldIndex) +{ + TIntermTyped *operandNode = Expr(operand); + const TOperator op = operandNode->getType().isInterfaceBlock() ? EOpIndexDirectInterfaceBlock + : EOpIndexDirectStruct; + + return new TIntermBinary(op, operandNode, CreateIndexNode(fieldIndex)); +} + +TIntermTyped *construct(const TType *type, rust::Slice operands) +{ + TIntermSequence operandsSequence = Exprs(operands); + return TIntermAggregate::CreateConstructor(*type, &operandsSequence); +} + +TIntermNode *store(const Expression &pointer, const Expression &value) +{ + return new TIntermBinary(EOpAssign, Expr(pointer), Expr(value)); +} + +TIntermTyped *call(const TFunction *function, rust::Slice args) +{ + TIntermSequence argsSequence = Exprs(args); + return TIntermAggregate::CreateFunctionCall(*function, &argsSequence); +} + +TIntermNode *call_void(const TFunction *function, rust::Slice args) +{ + return call(function, args); +} + +TIntermTyped *array_length(const Expression &operand) +{ + return new TIntermUnary(EOpArrayLength, Expr(operand), nullptr); +} + +TIntermTyped *negate(const Expression &operand) +{ + return new TIntermUnary(EOpNegative, Expr(operand), nullptr); +} + +TIntermTyped *postfix_increment(const Expression &operand) +{ + return new TIntermUnary(EOpPostIncrement, Expr(operand), nullptr); +} + +TIntermTyped *postfix_decrement(const Expression &operand) +{ + return new TIntermUnary(EOpPostDecrement, Expr(operand), nullptr); +} + +TIntermTyped *prefix_increment(const Expression &operand) +{ + return new TIntermUnary(EOpPreIncrement, Expr(operand), nullptr); +} + +TIntermTyped *prefix_decrement(const Expression &operand) +{ + return new TIntermUnary(EOpPreDecrement, Expr(operand), nullptr); +} + +TIntermTyped *logical_not(const Expression &operand) +{ + return new TIntermUnary(EOpLogicalNot, Expr(operand), nullptr); +} + +TIntermTyped *bitwise_not(const Expression &operand) +{ + return new TIntermUnary(EOpBitwiseNot, Expr(operand), nullptr); +} + +TIntermTyped *built_in_radians(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "radians", operand); +} + +TIntermTyped *built_in_degrees(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "degrees", operand); +} + +TIntermTyped *built_in_sin(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "sin", operand); +} + +TIntermTyped *built_in_cos(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "cos", operand); +} + +TIntermTyped *built_in_tan(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "tan", operand); +} + +TIntermTyped *built_in_asin(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "asin", operand); +} + +TIntermTyped *built_in_acos(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "acos", operand); +} + +TIntermTyped *built_in_atan(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "atan", operand); +} + +TIntermTyped *built_in_sinh(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "sinh", operand); +} + +TIntermTyped *built_in_cosh(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "cosh", operand); +} + +TIntermTyped *built_in_tanh(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "tanh", operand); +} + +TIntermTyped *built_in_asinh(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "asinh", operand); +} + +TIntermTyped *built_in_acosh(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "acosh", operand); +} + +TIntermTyped *built_in_atanh(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "atanh", operand); +} + +TIntermTyped *built_in_exp(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "exp", operand); +} + +TIntermTyped *built_in_log(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "log", operand); +} + +TIntermTyped *built_in_exp2(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "exp2", operand); +} + +TIntermTyped *built_in_log2(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "log2", operand); +} + +TIntermTyped *built_in_sqrt(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "sqrt", operand); +} + +TIntermTyped *built_in_inversesqrt(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "inversesqrt", operand); +} + +TIntermTyped *built_in_abs(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "abs", operand); +} + +TIntermTyped *built_in_sign(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "sign", operand); +} + +TIntermTyped *built_in_floor(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "floor", operand); +} + +TIntermTyped *built_in_trunc(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "trunc", operand); +} + +TIntermTyped *built_in_round(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "round", operand); +} + +TIntermTyped *built_in_roundeven(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "roundEven", operand); +} + +TIntermTyped *built_in_ceil(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "ceil", operand); +} + +TIntermTyped *built_in_fract(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "fract", operand); +} + +TIntermTyped *built_in_isnan(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "isnan", operand); +} + +TIntermTyped *built_in_isinf(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "isinf", operand); +} + +TIntermTyped *built_in_floatbitstoint(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "floatBitsToInt", operand); +} + +TIntermTyped *built_in_floatbitstouint(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "floatBitsToUint", operand); +} + +TIntermTyped *built_in_intbitstofloat(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "intBitsToFloat", operand); +} + +TIntermTyped *built_in_uintbitstofloat(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "uintBitsToFloat", operand); +} + +TIntermTyped *built_in_packsnorm2x16(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "packSnorm2x16", operand); +} + +TIntermTyped *built_in_packhalf2x16(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "packHalf2x16", operand); +} + +TIntermTyped *built_in_unpacksnorm2x16(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "unpackSnorm2x16", operand); +} + +TIntermTyped *built_in_unpackhalf2x16(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "unpackHalf2x16", operand); +} + +TIntermTyped *built_in_packunorm2x16(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "packUnorm2x16", operand); +} + +TIntermTyped *built_in_unpackunorm2x16(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "unpackUnorm2x16", operand); +} + +TIntermTyped *built_in_packunorm4x8(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "packUnorm4x8", operand); +} + +TIntermTyped *built_in_packsnorm4x8(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "packSnorm4x8", operand); +} + +TIntermTyped *built_in_unpackunorm4x8(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "unpackUnorm4x8", operand); +} + +TIntermTyped *built_in_unpacksnorm4x8(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "unpackSnorm4x8", operand); +} + +TIntermTyped *built_in_length(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "length", operand); +} + +TIntermTyped *built_in_normalize(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "normalize", operand); +} + +TIntermTyped *built_in_transpose(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "transpose", operand); +} + +TIntermTyped *built_in_determinant(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "determinant", operand); +} + +TIntermTyped *built_in_inverse(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "inverse", operand); +} + +TIntermTyped *built_in_any(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "any", operand); +} + +TIntermTyped *built_in_all(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "all", operand); +} + +TIntermTyped *built_in_not(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "not", operand); +} + +TIntermTyped *built_in_bitfieldreverse(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "bitfieldReverse", operand); +} + +TIntermTyped *built_in_bitcount(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "bitCount", operand); +} + +TIntermTyped *built_in_findlsb(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "findLSB", operand); +} + +TIntermTyped *built_in_findmsb(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "findMSB", operand); +} + +TIntermTyped *built_in_dfdx(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "dFdx", operand); +} + +TIntermTyped *built_in_dfdy(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "dFdy", operand); +} + +TIntermTyped *built_in_fwidth(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "fwidth", operand); +} + +TIntermTyped *built_in_interpolateatcentroid(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "interpolateAtCentroid", operand); +} + +TIntermTyped *built_in_atomiccounter(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "atomicCounter", operand); +} + +TIntermTyped *built_in_atomiccounterincrement(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "atomicCounterIncrement", operand); +} + +TIntermTyped *built_in_atomiccounterdecrement(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "atomicCounterDecrement", operand); +} + +TIntermTyped *built_in_imagesize(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "imageSize", operand); +} + +TIntermTyped *built_in_pixellocalload(TCompiler *compiler, const Expression &operand) +{ + return UnaryBuiltIn(compiler, "pixelLocalLoadANGLE", operand); +} + +TIntermTyped *add(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpAdd, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *sub(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpSub, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *mul(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpMul, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *vector_times_scalar(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpVectorTimesScalar, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *matrix_times_scalar(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpMatrixTimesScalar, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *vector_times_matrix(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpVectorTimesMatrix, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *matrix_times_vector(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpMatrixTimesVector, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *matrix_times_matrix(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpMatrixTimesMatrix, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *div(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpDiv, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *imod(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpIMod, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *logical_xor(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpLogicalXor, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *equal(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpEqual, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *not_equal(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpNotEqual, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *less_than(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpLessThan, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *greater_than(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpGreaterThan, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *less_than_equal(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpLessThanEqual, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *greater_than_equal(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpGreaterThanEqual, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *bit_shift_left(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpBitShiftLeft, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *bit_shift_right(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpBitShiftRight, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *bitwise_or(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpBitwiseOr, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *bitwise_xor(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpBitwiseXor, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *bitwise_and(const Expression &lhs, const Expression &rhs) +{ + return new TIntermBinary(EOpBitwiseAnd, Expr(lhs), Expr(rhs)); +} + +TIntermTyped *built_in_atan_binary(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atan", lhs, rhs); +} + +TIntermTyped *built_in_pow(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "pow", lhs, rhs); +} + +TIntermTyped *built_in_mod(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "mod", lhs, rhs); +} + +TIntermTyped *built_in_min(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "min", lhs, rhs); +} + +TIntermTyped *built_in_max(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "max", lhs, rhs); +} + +TIntermTyped *built_in_step(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "step", lhs, rhs); +} + +TIntermTyped *built_in_modf(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "modf", lhs, rhs); +} + +TIntermTyped *built_in_frexp(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "frexp", lhs, rhs); +} + +TIntermTyped *built_in_ldexp(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "ldexp", lhs, rhs); +} + +TIntermTyped *built_in_distance(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "distance", lhs, rhs); +} + +TIntermTyped *built_in_dot(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "dot", lhs, rhs); +} + +TIntermTyped *built_in_cross(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "cross", lhs, rhs); +} + +TIntermTyped *built_in_reflect(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "reflect", lhs, rhs); +} + +TIntermTyped *built_in_matrixcompmult(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "matrixCompMult", lhs, rhs); +} + +TIntermTyped *built_in_outerproduct(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "outerProduct", lhs, rhs); +} + +TIntermTyped *built_in_lessthanvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "lessThan", lhs, rhs); +} + +TIntermTyped *built_in_lessthanequalvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "lessThanEqual", lhs, rhs); +} + +TIntermTyped *built_in_greaterthanvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "greaterThan", lhs, rhs); +} + +TIntermTyped *built_in_greaterthanequalvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "greaterThanEqual", lhs, rhs); +} + +TIntermTyped *built_in_equalvec(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "equal", lhs, rhs); +} + +TIntermTyped *built_in_notequalvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "notEqual", lhs, rhs); +} + +TIntermTyped *built_in_interpolateatsample(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "interpolateAtSample", lhs, rhs); +} + +TIntermTyped *built_in_interpolateatoffset(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "interpolateAtOffset", lhs, rhs); +} + +TIntermTyped *built_in_atomicadd(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicAdd", lhs, rhs); +} + +TIntermTyped *built_in_atomicmin(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicMin", lhs, rhs); +} + +TIntermTyped *built_in_atomicmax(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicMax", lhs, rhs); +} + +TIntermTyped *built_in_atomicand(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicAnd", lhs, rhs); +} + +TIntermTyped *built_in_atomicor(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicOr", lhs, rhs); +} + +TIntermTyped *built_in_atomicxor(TCompiler *compiler, const Expression &lhs, const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicXor", lhs, rhs); +} + +TIntermTyped *built_in_atomicexchange(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs) +{ + return BinaryBuiltIn(compiler, "atomicExchange", lhs, rhs); +} + +TIntermTyped *built_in_clamp(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "clamp", args); +} + +TIntermTyped *built_in_mix(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "mix", args); +} + +TIntermTyped *built_in_smoothstep(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "smoothstep", args); +} + +TIntermTyped *built_in_fma(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "fma", args); +} + +TIntermTyped *built_in_faceforward(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "faceforward", args); +} + +TIntermTyped *built_in_refract(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "refract", args); +} + +TIntermTyped *built_in_bitfieldextract(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "bitfieldExtract", args); +} + +TIntermTyped *built_in_bitfieldinsert(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "bitfieldInsert", args); +} + +TIntermTyped *built_in_uaddcarry(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "uaddCarry", args); +} + +TIntermTyped *built_in_usubborrow(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "usubBorrow", args); +} + +TIntermNode *built_in_umulextended(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "umulExtended", args); +} + +TIntermNode *built_in_imulextended(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imulExtended", args); +} + +TIntermTyped *built_in_texturesize(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "textureSize", args); +} + +TIntermTyped *built_in_texturequerylod(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "textureQueryLOD", args); +} + +TIntermTyped *built_in_texelfetch(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "texelFetch", args); +} + +TIntermTyped *built_in_texelfetchoffset(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "texelFetchOffset", args); +} + +TIntermTyped *built_in_rgb_2_yuv(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "rgb_2_yuv", args); +} + +TIntermTyped *built_in_yuv_2_rgb(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "yuv_2_rgb", args); +} + +TIntermTyped *built_in_atomiccompswap(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "atomicCompSwap", args); +} + +TIntermNode *built_in_imagestore(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageStore", args); +} + +TIntermTyped *built_in_imageload(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageLoad", args); +} + +TIntermTyped *built_in_imageatomicadd(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicAdd", args); +} + +TIntermTyped *built_in_imageatomicmin(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicMin", args); +} + +TIntermTyped *built_in_imageatomicmax(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicMax", args); +} + +TIntermTyped *built_in_imageatomicand(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicAnd", args); +} + +TIntermTyped *built_in_imageatomicor(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicOr", args); +} + +TIntermTyped *built_in_imageatomicxor(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicXor", args); +} + +TIntermTyped *built_in_imageatomicexchange(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicExchange", args); +} + +TIntermTyped *built_in_imageatomiccompswap(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "imageAtomicCompSwap", args); +} + +TIntermNode *built_in_pixellocalstore(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "pixelLocalStoreANGLE", args); +} + +TIntermNode *built_in_memorybarrier(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "memoryBarrier", args); +} + +TIntermNode *built_in_memorybarrieratomiccounter(TCompiler *compiler, + rust::Slice args) +{ + return BuiltIn(compiler, "memoryBarrierAtomicCounter", args); +} + +TIntermNode *built_in_memorybarrierbuffer(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "memoryBarrierBuffer", args); +} + +TIntermNode *built_in_memorybarrierimage(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "memoryBarrierImage", args); +} + +TIntermNode *built_in_barrier(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "barrier", args); +} + +TIntermNode *built_in_memorybarriershared(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "memoryBarrierShared", args); +} + +TIntermNode *built_in_groupmemorybarrier(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "groupMemoryBarrier", args); +} + +TIntermNode *built_in_emitvertex(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "EmitVertex", args); +} + +TIntermNode *built_in_endprimitive(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "EndPrimitive", args); +} + +TIntermTyped *built_in_subpassload(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "subpassLoad", args); +} + +TIntermNode *built_in_begininvocationinterlocknv(TCompiler *compiler, + rust::Slice args) +{ + return BuiltIn(compiler, "beginInvocationInterlockNV", args); +} + +TIntermNode *built_in_endinvocationinterlocknv(TCompiler *compiler, + rust::Slice args) +{ + return BuiltIn(compiler, "endInvocationInterlockNV", args); +} + +TIntermNode *built_in_beginfragmentshaderorderingintel(TCompiler *compiler, + rust::Slice args) +{ + return BuiltIn(compiler, "beginFragmentShaderOrderingINTEL", args); +} + +TIntermNode *built_in_begininvocationinterlockarb(TCompiler *compiler, + rust::Slice args) +{ + return BuiltIn(compiler, "beginInvocationInterlockARB", args); +} + +TIntermNode *built_in_endinvocationinterlockarb(TCompiler *compiler, + rust::Slice args) +{ + return BuiltIn(compiler, "endInvocationInterlockARB", args); +} + +TIntermTyped *built_in_numsamples(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "numSamples", args); +} + +TIntermTyped *built_in_sampleposition(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "samplePosition", args); +} + +TIntermTyped *built_in_interpolateatcenter(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "interpolateAtCenter", args); +} + +TIntermNode *built_in_loopforwardprogress(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "loopForwardProgress", args); +} + +TIntermTyped *built_in_saturate(TCompiler *compiler, rust::Slice args) +{ + return BuiltIn(compiler, "saturate", args); +} + +TIntermTyped *built_in_texture(TCompiler *compiler, + rust::Slice args, + ASTBasicType samplerType, + bool isProj) +{ + const char *builtIn = isProj ? "textureProj" : "texture"; + if (compiler->getShaderVersion() == 100) + { + switch (static_cast(samplerType)) + { + case EbtSampler2D: + case EbtSamplerExternalOES: + builtIn = isProj ? "texture2DProj" : "texture2D"; + break; + case EbtSampler3D: + builtIn = isProj ? "texture3DProj" : "texture3D"; + break; + case EbtSamplerCube: + ASSERT(!isProj); + builtIn = "textureCube"; + break; + case EbtSampler2DRect: + builtIn = isProj ? "texture2DRectProj" : "texture2DRect"; + break; + case EbtSampler2DShadow: + builtIn = isProj ? "shadow2DProjEXT" : "shadow2DEXT"; + break; + case EbtSamplerVideoWEBGL: + ASSERT(!isProj); + builtIn = "textureVideoWEBGL"; + break; + default: + ASSERT(false); + } + } + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_textureoffset(TCompiler *compiler, + rust::Slice args, + bool isProj) +{ + const char *builtIn = isProj ? "textureProjOffset" : "textureOffset"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texture_with_compare(TCompiler *compiler, rust::Slice args) +{ + const char *builtIn = "texture"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturelod(TCompiler *compiler, + rust::Slice args, + ASTBasicType samplerType, + bool isProj) +{ + const char *builtIn = isProj ? "textureProjLod" : "textureLod"; + if (compiler->getShaderVersion() == 100) + { + switch (static_cast(samplerType)) + { + case EbtSampler2D: + if (compiler->getShaderType() == GL_FRAGMENT_SHADER) + { + builtIn = isProj ? "texture2DProjLodEXT" : "texture2DLodEXT"; + } + else + { + builtIn = isProj ? "texture2DProjLod" : "texture2DLod"; + } + break; + case EbtSampler3D: + builtIn = isProj ? "texture3DProjLod" : "texture3DLod"; + break; + case EbtSamplerCube: + ASSERT(!isProj); + if (compiler->getShaderType() == GL_FRAGMENT_SHADER) + { + builtIn = "textureCubeLodEXT"; + } + else + { + builtIn = "textureCubeLod"; + } + break; + default: + ASSERT(false); + } + } + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturelodoffset(TCompiler *compiler, + rust::Slice args, + bool isProj) +{ + const char *builtIn = isProj ? "textureProjLodOffset" : "textureLodOffset"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturelod_with_compare(TCompiler *compiler, + rust::Slice args) +{ + const char *builtIn = "textureLod"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturegrad(TCompiler *compiler, + rust::Slice args, + ASTBasicType samplerType, + bool isProj) +{ + const char *builtIn = isProj ? "textureProjGrad" : "textureGrad"; + if (compiler->getShaderVersion() == 100) + { + switch (static_cast(samplerType)) + { + case EbtSampler2D: + builtIn = isProj ? "texture2DProjGradEXT" : "texture2DGradEXT"; + break; + case EbtSamplerCube: + ASSERT(!isProj); + builtIn = "textureCubeGradEXT"; + break; + default: + ASSERT(false); + } + } + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturegradoffset(TCompiler *compiler, + rust::Slice args, + bool isProj) +{ + const char *builtIn = isProj ? "textureProjGradOffset" : "textureGradOffset"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturegather(TCompiler *compiler, rust::Slice args) +{ + const char *builtIn = "textureGather"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +TIntermTyped *built_in_texturegatheroffset(TCompiler *compiler, + rust::Slice args, + bool isOffsetArray) +{ + const char *builtIn = isOffsetArray ? "textureGatherOffsets" : "textureGatherOffset"; + ASSERT(compiler->getShaderVersion() >= 300); + return BuiltIn(compiler, builtIn, args); +} + +void branch_discard(TIntermBlock *block) +{ + block->appendStatement(new TIntermBranch(EOpKill, nullptr)); +} + +void branch_return_value(TIntermBlock *block, const Expression &value) +{ + block->appendStatement(new TIntermBranch(EOpReturn, Expr(value))); +} + +void branch_return(TIntermBlock *block) +{ + block->appendStatement(new TIntermBranch(EOpReturn, nullptr)); +} + +void branch_break(TIntermBlock *block) +{ + block->appendStatement(new TIntermBranch(EOpBreak, nullptr)); +} + +void branch_continue(TIntermBlock *block) +{ + block->appendStatement(new TIntermBranch(EOpContinue, nullptr)); +} + +void branch_if(TIntermBlock *block, const Expression &condition, TIntermBlock *trueBlock) +{ + branch_if_else(block, condition, trueBlock, nullptr); +} + +void branch_if_else(TIntermBlock *block, + const Expression &condition, + TIntermBlock *trueBlock, + TIntermBlock *falseBlock) +{ + block->appendStatement(new TIntermIfElse(Expr(condition), trueBlock, falseBlock)); +} + +void branch_loop(TIntermBlock *block, TIntermBlock *loopConditionBlock, TIntermBlock *bodyBlock) +{ + TIntermBlock *loopBody = new TIntermBlock; + loopBody->appendStatement(loopConditionBlock); + loopBody->appendStatement(bodyBlock); + + block->appendStatement(new TIntermLoop(ELoopFor, nullptr, nullptr, nullptr, loopBody)); +} + +void branch_do_loop(TIntermBlock *block, TIntermBlock *bodyBlock) +{ + block->appendStatement(new TIntermLoop(ELoopFor, nullptr, nullptr, nullptr, bodyBlock)); +} + +void branch_loop_if(TIntermBlock *block, const Expression &condition) +{ + TIntermTyped *notCondition = new TIntermUnary(EOpLogicalNot, Expr(condition), nullptr); + + TIntermBlock *breakBlock = new TIntermBlock; + breakBlock->appendStatement(new TIntermBranch(EOpBreak, nullptr)); + + block->appendStatement(new TIntermIfElse(notCondition, breakBlock, nullptr)); +} + +void branch_switch(TIntermBlock *block, + const Expression &value, + rust::Slice caseLabels, + rust::Slice caseBlocks) +{ + ASSERT(caseLabels.size() == caseBlocks.size()); + + TIntermBlock *switchBody = new TIntermBlock; + for (size_t caseIndex = 0; caseIndex < caseLabels.size(); ++caseIndex) + { + TIntermBlock *caseBlock = caseBlocks[caseIndex]; + TIntermTyped *label = caseLabels[caseIndex]; + if (label != nullptr) + { + ASSERT(label->getAsConstantUnion()); + label = label->deepCopy(); + } + + switchBody->appendStatement(new TIntermCase(label)); + switchBody->appendStatement(caseBlock); + } + + block->appendStatement(new TIntermSwitch(Expr(value), switchBody)); +} + +TIntermBlock *finalize(TCompiler *compiler, + rust::Slice typeDeclarations, + rust::Slice globalVariables, + rust::Slice functionDeclarations) +{ + TIntermBlock *root = new TIntermBlock; + root->setIsTreeRoot(); + + append_instructions_to_block(root, typeDeclarations); + append_instructions_to_block(root, globalVariables); + append_instructions_to_block(root, functionDeclarations); + + return root; +} + +} // namespace ffi +} // namespace ir +} // namespace sh diff --git a/src/compiler/translator/ir/src/output/ir_to_legacy.h b/src/compiler/translator/ir/src/output/ir_to_legacy.h new file mode 100644 index 00000000000..f57a252cb77 --- /dev/null +++ b/src/compiler/translator/ir/src/output/ir_to_legacy.h @@ -0,0 +1,360 @@ +// +// Copyright 2025 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. +// +// Bridge from IR in Rust. Forward declares callbacks from IR to generate a legacy AST. +// + +#ifndef COMPILER_TRANSLATOR_IR_SRC_IR_TO_LEGACY_H_ +#define COMPILER_TRANSLATOR_IR_SRC_IR_TO_LEGACY_H_ + +#include + +// There are complex dependencies that can be mostly solved by forward declaring the ffi types, +// except rust::Slice that needs to actually be included. builder.rs.h includes this type and is +// outside this complex dependency, so that's used here. +#include "compiler/translator/ir/src/builder.rs.h" + +namespace sh +{ +class TCompiler; +class TType; +class TFunction; +class TVariable; +class TIntermNode; +class TIntermTyped; +class TIntermBlock; + +namespace ir +{ +namespace ffi +{ +struct SymbolName; +struct ASTFieldInfo; +struct Expression; + +TType *make_basic_type(ASTBasicType basicType); +TType *make_vector_type(const TType *scalarType, uint32_t count); +TType *make_matrix_type(const TType *vectorType, uint32_t count); +TType *make_array_type(const TType *elementType, uint32_t count); +TType *make_unsized_array_type(const TType *elementType); +TType *make_struct_type(TCompiler *compiler, + const SymbolName &name, + rust::Slice fields, + bool isInterfaceBlock); +TIntermNode *declare_struct(TCompiler *compiler, const TType *structType); + +TIntermTyped *make_float_constant(float f); +TIntermTyped *make_int_constant(int32_t i); +TIntermTyped *make_uint_constant(uint32_t u); +TIntermTyped *make_bool_constant(bool b); +TIntermTyped *make_yuv_csc_constant(ASTYuvCscStandardEXT yuvCsc); +TIntermTyped *make_composite_constant(rust::Slice elements, + const TType *constantType); +TIntermTyped *make_constant_variable(TCompiler *compiler, + const TType *constantType, + TIntermTyped *value); + +TIntermTyped *make_variable(TCompiler *compiler, + const SymbolName &name, + const TType *baseType, + const ASTType &astType, + bool isRedeclaredBuiltIn, + bool isStaticUse); +TIntermTyped *make_nameless_block_field_variable(TCompiler *compiler, + TIntermTyped *variable, + uint32_t fieldIndex, + const SymbolName &name, + const TType *baseType, + const ASTType &astType); +TIntermNode *declare_variable(TIntermTyped *variable); +TIntermNode *declare_variable_with_initializer(TIntermTyped *variable, TIntermTyped *value); +TIntermNode *globally_qualify_built_in_invariant(TIntermTyped *variable); +TIntermNode *globally_qualify_built_in_precise(TIntermTyped *variable); + +TFunction *make_function(TCompiler *compiler, + const SymbolName &name, + const TType *returnType, + const ASTType &returnAstType, + rust::Slice params, + rust::Slice paramDirections); +TIntermNode *declare_function(const TFunction *function, TIntermBlock *body); + +TIntermBlock *make_interm_block(); +void append_instructions_to_block(TIntermBlock *block, rust::Slice nodes); +void append_blocks_to_block(TIntermBlock *block, rust::Slice blocksToAppend); + +TIntermTyped *swizzle(const Expression &operand, rust::Slice indices); +TIntermTyped *index(const Expression &operand, const Expression &index); +TIntermTyped *select_field(const Expression &operand, uint32_t fieldIndex); +TIntermTyped *construct(const TType *type, rust::Slice operands); +TIntermNode *store(const Expression &pointer, const Expression &value); +TIntermTyped *call(const TFunction *function, rust::Slice args); +TIntermNode *call_void(const TFunction *function, rust::Slice args); + +TIntermTyped *array_length(const Expression &operand); +TIntermTyped *negate(const Expression &operand); +TIntermTyped *postfix_increment(const Expression &operand); +TIntermTyped *postfix_decrement(const Expression &operand); +TIntermTyped *prefix_increment(const Expression &operand); +TIntermTyped *prefix_decrement(const Expression &operand); +TIntermTyped *logical_not(const Expression &operand); +TIntermTyped *bitwise_not(const Expression &operand); +TIntermTyped *built_in_radians(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_degrees(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_sin(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_cos(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_tan(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_asin(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_acos(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_atan(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_sinh(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_cosh(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_tanh(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_asinh(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_acosh(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_atanh(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_exp(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_log(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_exp2(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_log2(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_sqrt(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_inversesqrt(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_abs(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_sign(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_floor(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_trunc(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_round(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_roundeven(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_ceil(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_fract(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_isnan(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_isinf(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_floatbitstoint(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_floatbitstouint(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_intbitstofloat(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_uintbitstofloat(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_packsnorm2x16(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_packhalf2x16(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_unpacksnorm2x16(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_unpackhalf2x16(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_packunorm2x16(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_unpackunorm2x16(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_packunorm4x8(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_packsnorm4x8(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_unpackunorm4x8(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_unpacksnorm4x8(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_length(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_normalize(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_transpose(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_determinant(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_inverse(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_any(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_all(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_not(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_bitfieldreverse(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_bitcount(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_findlsb(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_findmsb(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_dfdx(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_dfdy(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_fwidth(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_interpolateatcentroid(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_atomiccounter(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_atomiccounterincrement(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_atomiccounterdecrement(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_imagesize(TCompiler *compiler, const Expression &operand); +TIntermTyped *built_in_pixellocalload(TCompiler *compiler, const Expression &operand); + +TIntermTyped *add(const Expression &lhs, const Expression &rhs); +TIntermTyped *sub(const Expression &lhs, const Expression &rhs); +TIntermTyped *mul(const Expression &lhs, const Expression &rhs); +TIntermTyped *vector_times_scalar(const Expression &lhs, const Expression &rhs); +TIntermTyped *matrix_times_scalar(const Expression &lhs, const Expression &rhs); +TIntermTyped *vector_times_matrix(const Expression &lhs, const Expression &rhs); +TIntermTyped *matrix_times_vector(const Expression &lhs, const Expression &rhs); +TIntermTyped *matrix_times_matrix(const Expression &lhs, const Expression &rhs); +TIntermTyped *div(const Expression &lhs, const Expression &rhs); +TIntermTyped *imod(const Expression &lhs, const Expression &rhs); +TIntermTyped *logical_xor(const Expression &lhs, const Expression &rhs); +TIntermTyped *equal(const Expression &lhs, const Expression &rhs); +TIntermTyped *not_equal(const Expression &lhs, const Expression &rhs); +TIntermTyped *less_than(const Expression &lhs, const Expression &rhs); +TIntermTyped *greater_than(const Expression &lhs, const Expression &rhs); +TIntermTyped *less_than_equal(const Expression &lhs, const Expression &rhs); +TIntermTyped *greater_than_equal(const Expression &lhs, const Expression &rhs); +TIntermTyped *bit_shift_left(const Expression &lhs, const Expression &rhs); +TIntermTyped *bit_shift_right(const Expression &lhs, const Expression &rhs); +TIntermTyped *bitwise_or(const Expression &lhs, const Expression &rhs); +TIntermTyped *bitwise_xor(const Expression &lhs, const Expression &rhs); +TIntermTyped *bitwise_and(const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atan_binary(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_pow(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_mod(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_min(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_max(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_step(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_modf(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_frexp(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_ldexp(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_distance(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_dot(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_cross(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_reflect(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_matrixcompmult(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_outerproduct(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_lessthanvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_lessthanequalvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_greaterthanvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_greaterthanequalvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_equalvec(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_notequalvec(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_interpolateatsample(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_interpolateatoffset(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); +TIntermTyped *built_in_atomicadd(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atomicmin(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atomicmax(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atomicand(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atomicor(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atomicxor(TCompiler *compiler, const Expression &lhs, const Expression &rhs); +TIntermTyped *built_in_atomicexchange(TCompiler *compiler, + const Expression &lhs, + const Expression &rhs); + +TIntermTyped *built_in_clamp(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_mix(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_smoothstep(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_fma(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_faceforward(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_refract(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_bitfieldextract(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_bitfieldinsert(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_uaddcarry(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_usubborrow(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_umulextended(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_imulextended(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_texturesize(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_texturequerylod(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_texelfetch(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_texelfetchoffset(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_rgb_2_yuv(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_yuv_2_rgb(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_atomiccompswap(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_imagestore(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageload(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicadd(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicmin(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicmax(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicand(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicor(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicxor(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomicexchange(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_imageatomiccompswap(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_pixellocalstore(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_memorybarrier(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_memorybarrieratomiccounter(TCompiler *compiler, + rust::Slice args); +TIntermNode *built_in_memorybarrierbuffer(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_memorybarrierimage(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_barrier(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_memorybarriershared(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_groupmemorybarrier(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_emitvertex(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_endprimitive(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_subpassload(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_begininvocationinterlocknv(TCompiler *compiler, + rust::Slice args); +TIntermNode *built_in_endinvocationinterlocknv(TCompiler *compiler, + rust::Slice args); +TIntermNode *built_in_beginfragmentshaderorderingintel(TCompiler *compiler, + rust::Slice args); +TIntermNode *built_in_begininvocationinterlockarb(TCompiler *compiler, + rust::Slice args); +TIntermNode *built_in_endinvocationinterlockarb(TCompiler *compiler, + rust::Slice args); +TIntermTyped *built_in_numsamples(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_sampleposition(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_interpolateatcenter(TCompiler *compiler, rust::Slice args); +TIntermNode *built_in_loopforwardprogress(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_saturate(TCompiler *compiler, rust::Slice args); + +TIntermTyped *built_in_texture(TCompiler *compiler, + rust::Slice args, + ASTBasicType samplerType, + bool isProj); +TIntermTyped *built_in_textureoffset(TCompiler *compiler, + rust::Slice args, + bool isProj); +TIntermTyped *built_in_texture_with_compare(TCompiler *compiler, + rust::Slice args); +TIntermTyped *built_in_texturelod(TCompiler *compiler, + rust::Slice args, + ASTBasicType samplerType, + bool isProj); +TIntermTyped *built_in_texturelodoffset(TCompiler *compiler, + rust::Slice args, + bool isProj); +TIntermTyped *built_in_texturelod_with_compare(TCompiler *compiler, + rust::Slice args); +TIntermTyped *built_in_texturegrad(TCompiler *compiler, + rust::Slice args, + ASTBasicType samplerType, + bool isProj); +TIntermTyped *built_in_texturegradoffset(TCompiler *compiler, + rust::Slice args, + bool isProj); +TIntermTyped *built_in_texturegather(TCompiler *compiler, rust::Slice args); +TIntermTyped *built_in_texturegatheroffset(TCompiler *compiler, + rust::Slice args, + bool isOffsetArray); + +void branch_discard(TIntermBlock *block); +void branch_return_value(TIntermBlock *block, const Expression &value); +void branch_return(TIntermBlock *block); +void branch_break(TIntermBlock *block); +void branch_continue(TIntermBlock *block); + +void branch_if(TIntermBlock *block, const Expression &condition, TIntermBlock *trueBlock); +void branch_if_else(TIntermBlock *block, + const Expression &condition, + TIntermBlock *trueBlock, + TIntermBlock *falseBlock); +void branch_loop(TIntermBlock *block, TIntermBlock *loopConditionBlock, TIntermBlock *bodyBlock); +void branch_do_loop(TIntermBlock *block, TIntermBlock *bodyBlock); +void branch_loop_if(TIntermBlock *block, const Expression &condition); +void branch_switch(TIntermBlock *block, + const Expression &value, + rust::Slice caseLabels, + rust::Slice caseBlocks); + +TIntermBlock *finalize(TCompiler *compiler, + rust::Slice typeDeclarations, + rust::Slice globalVariables, + rust::Slice functionDeclarations); + +} // namespace ffi +} // namespace ir +} // namespace sh + +#endif // COMPILER_TRANSLATOR_IR_SRC_IR_TO_LEGACY_H_ diff --git a/src/compiler/translator/ir/src/output/legacy.h b/src/compiler/translator/ir/src/output/legacy.h new file mode 100644 index 00000000000..50b17d0909a --- /dev/null +++ b/src/compiler/translator/ir/src/output/legacy.h @@ -0,0 +1,27 @@ +// +// Copyright 2025 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. +// +// Bridge from IR in Rust. Forward declares legacy AST types. +// + +#ifndef COMPILER_TRANSLATOR_IR_SRC_LEGACY_H_ +#define COMPILER_TRANSLATOR_IR_SRC_LEGACY_H_ + +namespace sh +{ +class TType; +class TFunction; +class TIntermNode; +class TIntermTyped; +class TIntermBlock; +class TCompiler; +} // namespace sh + +namespace angle +{ +class PoolAllocator; +} + +#endif // COMPILER_TRANSLATOR_IR_SRC_LEGACY_H_ diff --git a/src/compiler/translator/ir/src/output/legacy.rs b/src/compiler/translator/ir/src/output/legacy.rs new file mode 100644 index 00000000000..650f210d619 --- /dev/null +++ b/src/compiler/translator/ir/src/output/legacy.rs @@ -0,0 +1,2992 @@ +// Copyright 2025 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. +// +// Output legacy AST from the IR. This generator will no longer be needed once the translator is +// entirely converted to IR. + +use crate::ir::*; +use crate::*; + +const SYMBOL_NAME_NO_ID: u32 = 0xFFFFFFFF; + +#[cxx::bridge(namespace = "sh::ir::ffi")] +pub mod ffi { + #[derive(Copy, Clone)] + #[repr(u32)] + enum ASTSymbolType { + BuiltIn, + UserDefined, + AngleInternal, + Empty, + } + + unsafe extern "C++" { + include!("compiler/translator/ir/src/builder.rs.h"); + + // Forward the legacy AST types from builder since it already defines the same types. + type ASTPrecision = crate::builder::ffi::ASTPrecision; + type ASTBasicType = crate::builder::ffi::ASTBasicType; + type ASTQualifier = crate::builder::ffi::ASTQualifier; + type ASTLayoutImageInternalFormat = crate::builder::ffi::ASTLayoutImageInternalFormat; + type ASTLayoutMatrixPacking = crate::builder::ffi::ASTLayoutMatrixPacking; + type ASTLayoutBlockStorage = crate::builder::ffi::ASTLayoutBlockStorage; + type ASTLayoutDepth = crate::builder::ffi::ASTLayoutDepth; + type ASTYuvCscStandardEXT = crate::builder::ffi::ASTYuvCscStandardEXT; + type ASTLayoutQualifier = crate::builder::ffi::ASTLayoutQualifier; + type ASTMemoryQualifier = crate::builder::ffi::ASTMemoryQualifier; + type ASTType = crate::builder::ffi::ASTType; + + #[namespace = "sh"] + type TCompiler; + #[namespace = "sh"] + type TType; + #[namespace = "sh"] + type TFunction; + #[namespace = "sh"] + type TIntermNode; + #[namespace = "sh"] + type TIntermTyped; + #[namespace = "sh"] + type TIntermBlock; + } + + struct ASTFieldInfo { + name: &'static str, + base_type: *const TType, + ast_type: ASTType, + } + + struct SymbolName { + name: &'static str, + symbol_type: ASTSymbolType, + // In some cases, the IR may generate variables with the same name, such as in + // duplicate_block(). The ID is appended to temporary names to ensure no duplication. + // When ID is SYMBOL_NAME_NO_ID, the ID should not be appended. + id: u32, + } + + struct Expression { + node: *mut TIntermTyped, + needs_copy: bool, + } + + unsafe extern "C++" { + include!("compiler/translator/ir/src/output/ir_to_legacy.h"); + + // SAFETY: The following functions produce an AST in C++ and use pool-allocated objects of + // TType, TInterm* etc. They take `*mut` pointers mirroring the existing legacy C++ AST + // code. + unsafe fn make_basic_type(basic_type: ASTBasicType) -> *mut TType; + unsafe fn make_vector_type(scalar_type: *const TType, count: u32) -> *mut TType; + unsafe fn make_matrix_type(vector_type: *const TType, count: u32) -> *mut TType; + unsafe fn make_array_type(element_type: *const TType, count: u32) -> *mut TType; + unsafe fn make_unsized_array_type(element_type: *const TType) -> *mut TType; + unsafe fn make_struct_type( + compiler: *mut TCompiler, + name: &SymbolName, + fields: &[ASTFieldInfo], + is_interface_block: bool, + ) -> *mut TType; + unsafe fn declare_struct( + compiler: *mut TCompiler, + struct_type: *const TType, + ) -> *mut TIntermNode; + + unsafe fn make_float_constant(f: f32) -> *mut TIntermTyped; + unsafe fn make_int_constant(i: i32) -> *mut TIntermTyped; + unsafe fn make_uint_constant(u: u32) -> *mut TIntermTyped; + unsafe fn make_bool_constant(b: bool) -> *mut TIntermTyped; + unsafe fn make_yuv_csc_constant(yuv_csc: ASTYuvCscStandardEXT) -> *mut TIntermTyped; + unsafe fn make_composite_constant( + elements: &[*mut TIntermTyped], + constant_type: *const TType, + ) -> *mut TIntermTyped; + unsafe fn make_constant_variable( + compiler: *mut TCompiler, + constant_type: *const TType, + value: *mut TIntermTyped, + ) -> *mut TIntermTyped; + + unsafe fn make_variable( + compiler: *mut TCompiler, + name: &SymbolName, + base_type: *const TType, + ast_type: &ASTType, + is_redeclared_built_in: bool, + is_static_use: bool, + ) -> *mut TIntermTyped; + unsafe fn make_nameless_block_field_variable( + compiler: *mut TCompiler, + variable: *mut TIntermTyped, + field_index: u32, + name: &SymbolName, + base_type: *const TType, + ast_type: &ASTType, + ) -> *mut TIntermTyped; + unsafe fn declare_variable(variable: *mut TIntermTyped) -> *mut TIntermNode; + unsafe fn declare_variable_with_initializer( + variable: *mut TIntermTyped, + value: *mut TIntermTyped, + ) -> *mut TIntermNode; + unsafe fn globally_qualify_built_in_invariant( + variable: *mut TIntermTyped, + ) -> *mut TIntermNode; + unsafe fn globally_qualify_built_in_precise( + variable: *mut TIntermTyped, + ) -> *mut TIntermNode; + + unsafe fn make_function( + compiler: *mut TCompiler, + name: &SymbolName, + return_type: *const TType, + return_ast_type: &ASTType, + params: &[*mut TIntermTyped], + param_directions: &[ASTQualifier], + ) -> *mut TFunction; + unsafe fn declare_function( + function: *const TFunction, + body: *mut TIntermBlock, + ) -> *mut TIntermNode; + + unsafe fn make_interm_block() -> *mut TIntermBlock; + unsafe fn append_instructions_to_block( + block: *mut TIntermBlock, + nodes: &[*mut TIntermNode], + ); + unsafe fn append_blocks_to_block( + block: *mut TIntermBlock, + blocks_to_append: &[*mut TIntermBlock], + ); + + // TODO(http://anglebug.com/349994211): the AST automatically derives the type of the + // intermediate node. However, the IR may apply transformations that use Precision::High + // in the middle of low precision operations, so the precision of intermediate nodes must + // be overridden to what they were originally expected to be; i.e. all the following need + // to take a precision parameter to override in the node they create. + // + // This may not be a problem as ultimately the output will be generated by the IR itself + // and this file will go away. + + unsafe fn swizzle(operand: &Expression, indices: &[u32]) -> *mut TIntermTyped; + unsafe fn index(operand: &Expression, index: &Expression) -> *mut TIntermTyped; + unsafe fn select_field(operand: &Expression, field_index: u32) -> *mut TIntermTyped; + unsafe fn construct( + construct_type: *const TType, + operands: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn store(pointer: &Expression, value: &Expression) -> *mut TIntermNode; + unsafe fn call(function: *const TFunction, args: &[Expression]) -> *mut TIntermTyped; + unsafe fn call_void(function: *const TFunction, args: &[Expression]) -> *mut TIntermNode; + + unsafe fn array_length(operand: &Expression) -> *mut TIntermTyped; + unsafe fn negate(operand: &Expression) -> *mut TIntermTyped; + unsafe fn postfix_increment(operand: &Expression) -> *mut TIntermTyped; + unsafe fn postfix_decrement(operand: &Expression) -> *mut TIntermTyped; + unsafe fn prefix_increment(operand: &Expression) -> *mut TIntermTyped; + unsafe fn prefix_decrement(operand: &Expression) -> *mut TIntermTyped; + unsafe fn logical_not(operand: &Expression) -> *mut TIntermTyped; + unsafe fn bitwise_not(operand: &Expression) -> *mut TIntermTyped; + unsafe fn built_in_radians( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_degrees( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_sin(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_cos(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_tan(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_asin( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_acos( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atan( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_sinh( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_cosh( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_tanh( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_asinh( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_acosh( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atanh( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_exp(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_log(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_exp2( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_log2( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_sqrt( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_inversesqrt( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_abs(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_sign( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_floor( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_trunc( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_round( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_roundeven( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_ceil( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_fract( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_isnan( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_isinf( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_floatbitstoint( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_floatbitstouint( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_intbitstofloat( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_uintbitstofloat( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_packsnorm2x16( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_packhalf2x16( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_unpacksnorm2x16( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_unpackhalf2x16( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_packunorm2x16( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_unpackunorm2x16( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_packunorm4x8( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_packsnorm4x8( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_unpackunorm4x8( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_unpacksnorm4x8( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_length( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_normalize( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_transpose( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_determinant( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_inverse( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_any(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_all(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_not(compiler: *mut TCompiler, operand: &Expression) + -> *mut TIntermTyped; + unsafe fn built_in_bitfieldreverse( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_bitcount( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_findlsb( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_findmsb( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_dfdx( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_dfdy( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_fwidth( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_interpolateatcentroid( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomiccounter( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomiccounterincrement( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomiccounterdecrement( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_imagesize( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_pixellocalload( + compiler: *mut TCompiler, + operand: &Expression, + ) -> *mut TIntermTyped; + + unsafe fn add(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn sub(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn mul(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn vector_times_scalar(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn matrix_times_scalar(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn vector_times_matrix(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn matrix_times_vector(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn matrix_times_matrix(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn div(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn imod(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn logical_xor(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn equal(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn not_equal(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn less_than(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn greater_than(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn less_than_equal(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn greater_than_equal(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn bit_shift_left(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn bit_shift_right(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn bitwise_or(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn bitwise_xor(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn bitwise_and(lhs: &Expression, rhs: &Expression) -> *mut TIntermTyped; + unsafe fn built_in_atan_binary( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_pow( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_mod( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_min( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_max( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_step( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_modf( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_frexp( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_ldexp( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_distance( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_dot( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_cross( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_reflect( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_matrixcompmult( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_outerproduct( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_lessthanvec( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_lessthanequalvec( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_greaterthanvec( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_greaterthanequalvec( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_equalvec( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_notequalvec( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_interpolateatsample( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_interpolateatoffset( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicadd( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicmin( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicmax( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicand( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicor( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicxor( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + unsafe fn built_in_atomicexchange( + compiler: *mut TCompiler, + lhs: &Expression, + rhs: &Expression, + ) -> *mut TIntermTyped; + + unsafe fn built_in_clamp( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_mix(compiler: *mut TCompiler, args: &[Expression]) -> *mut TIntermTyped; + unsafe fn built_in_smoothstep( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_fma(compiler: *mut TCompiler, args: &[Expression]) -> *mut TIntermTyped; + unsafe fn built_in_faceforward( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_refract( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_bitfieldextract( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_bitfieldinsert( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_uaddcarry( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_usubborrow( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_umulextended( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_imulextended( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_texturesize( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_texturequerylod( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_texelfetch( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_texelfetchoffset( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_rgb_2_yuv( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_yuv_2_rgb( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_atomiccompswap( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imagestore( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_imageload( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicadd( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicmin( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicmax( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicand( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicor( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicxor( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomicexchange( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_imageatomiccompswap( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_pixellocalstore( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_memorybarrier( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_memorybarrieratomiccounter( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_memorybarrierbuffer( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_memorybarrierimage( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_barrier( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_memorybarriershared( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_groupmemorybarrier( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_emitvertex( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_endprimitive( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_subpassload( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_begininvocationinterlocknv( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_endinvocationinterlocknv( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_beginfragmentshaderorderingintel( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_begininvocationinterlockarb( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_endinvocationinterlockarb( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_numsamples( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_sampleposition( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_interpolateatcenter( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_loopforwardprogress( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermNode; + unsafe fn built_in_saturate( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + + unsafe fn built_in_texture( + compiler: *mut TCompiler, + args: &[Expression], + sampler_type: ASTBasicType, + is_proj: bool, + ) -> *mut TIntermTyped; + unsafe fn built_in_textureoffset( + compiler: *mut TCompiler, + args: &[Expression], + is_proj: bool, + ) -> *mut TIntermTyped; + unsafe fn built_in_texture_with_compare( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_texturelod( + compiler: *mut TCompiler, + args: &[Expression], + sampler_type: ASTBasicType, + is_proj: bool, + ) -> *mut TIntermTyped; + unsafe fn built_in_texturelodoffset( + compiler: *mut TCompiler, + args: &[Expression], + is_proj: bool, + ) -> *mut TIntermTyped; + unsafe fn built_in_texturelod_with_compare( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_texturegrad( + compiler: *mut TCompiler, + args: &[Expression], + sampler_type: ASTBasicType, + is_proj: bool, + ) -> *mut TIntermTyped; + unsafe fn built_in_texturegradoffset( + compiler: *mut TCompiler, + args: &[Expression], + is_proj: bool, + ) -> *mut TIntermTyped; + unsafe fn built_in_texturegather( + compiler: *mut TCompiler, + args: &[Expression], + ) -> *mut TIntermTyped; + unsafe fn built_in_texturegatheroffset( + compiler: *mut TCompiler, + args: &[Expression], + is_offset_array: bool, + ) -> *mut TIntermTyped; + + unsafe fn branch_discard(block: *mut TIntermBlock); + unsafe fn branch_return(block: *mut TIntermBlock); + unsafe fn branch_return_value(block: *mut TIntermBlock, value: &Expression); + unsafe fn branch_break(block: *mut TIntermBlock); + unsafe fn branch_continue(block: *mut TIntermBlock); + + unsafe fn branch_if( + block: *mut TIntermBlock, + condition: &Expression, + true_block: *mut TIntermBlock, + ); + unsafe fn branch_if_else( + block: *mut TIntermBlock, + condition: &Expression, + true_block: *mut TIntermBlock, + false_block: *mut TIntermBlock, + ); + unsafe fn branch_loop( + block: *mut TIntermBlock, + loop_condition_block: *mut TIntermBlock, + body_block: *mut TIntermBlock, + ); + unsafe fn branch_do_loop(block: *mut TIntermBlock, body_block: *mut TIntermBlock); + unsafe fn branch_loop_if(block: *mut TIntermBlock, condition: &Expression); + unsafe fn branch_switch( + block: *mut TIntermBlock, + value: &Expression, + case_labels: &[*mut TIntermTyped], + case_blocks: &[*mut TIntermBlock], + ); + + unsafe fn finalize( + legacy_compiler: *mut TCompiler, + type_declarations: &[*mut TIntermNode], + global_variables: &[*mut TIntermNode], + function_declarations: &[*mut TIntermNode], + ) -> *mut TIntermBlock; + } +} + +use ffi::TCompiler; +use ffi::TFunction; +use ffi::TIntermBlock; +use ffi::TIntermNode; +use ffi::TIntermTyped; +use ffi::TType; + +impl From for ffi::ASTPrecision { + fn from(precision: Precision) -> Self { + match precision { + Precision::Low => ffi::ASTPrecision::Low, + Precision::Medium => ffi::ASTPrecision::Medium, + Precision::High => ffi::ASTPrecision::High, + _ => ffi::ASTPrecision::Undefined, + } + } +} + +impl From for ffi::ASTYuvCscStandardEXT { + fn from(value: YuvCscStandard) -> Self { + match value { + YuvCscStandard::Itu601 => ffi::ASTYuvCscStandardEXT::Itu601, + YuvCscStandard::Itu601FullRange => ffi::ASTYuvCscStandardEXT::Itu601FullRange, + YuvCscStandard::Itu709 => ffi::ASTYuvCscStandardEXT::Itu709, + } + } +} + +impl From for ffi::ASTLayoutBlockStorage { + fn from(value: BlockStorage) -> Self { + match value { + BlockStorage::Shared => ffi::ASTLayoutBlockStorage::Shared, + BlockStorage::Packed => ffi::ASTLayoutBlockStorage::Packed, + BlockStorage::Std140 => ffi::ASTLayoutBlockStorage::Std140, + BlockStorage::Std430 => ffi::ASTLayoutBlockStorage::Std430, + } + } +} + +impl From for ffi::ASTLayoutMatrixPacking { + fn from(value: MatrixPacking) -> Self { + match value { + MatrixPacking::RowMajor => ffi::ASTLayoutMatrixPacking::RowMajor, + MatrixPacking::ColumnMajor => ffi::ASTLayoutMatrixPacking::ColumnMajor, + } + } +} + +impl From for ffi::ASTLayoutDepth { + fn from(value: Depth) -> Self { + match value { + Depth::Any => ffi::ASTLayoutDepth::Any, + Depth::Greater => ffi::ASTLayoutDepth::Greater, + Depth::Less => ffi::ASTLayoutDepth::Less, + Depth::Unchanged => ffi::ASTLayoutDepth::Unchanged, + } + } +} + +impl From for ffi::ASTLayoutImageInternalFormat { + fn from(value: ImageInternalFormat) -> Self { + match value { + ImageInternalFormat::RGBA32F => ffi::ASTLayoutImageInternalFormat::RGBA32F, + ImageInternalFormat::RGBA16F => ffi::ASTLayoutImageInternalFormat::RGBA16F, + ImageInternalFormat::R32F => ffi::ASTLayoutImageInternalFormat::R32F, + ImageInternalFormat::RGBA32UI => ffi::ASTLayoutImageInternalFormat::RGBA32UI, + ImageInternalFormat::RGBA16UI => ffi::ASTLayoutImageInternalFormat::RGBA16UI, + ImageInternalFormat::RGBA8UI => ffi::ASTLayoutImageInternalFormat::RGBA8UI, + ImageInternalFormat::R32UI => ffi::ASTLayoutImageInternalFormat::R32UI, + ImageInternalFormat::RGBA32I => ffi::ASTLayoutImageInternalFormat::RGBA32I, + ImageInternalFormat::RGBA16I => ffi::ASTLayoutImageInternalFormat::RGBA16I, + ImageInternalFormat::RGBA8I => ffi::ASTLayoutImageInternalFormat::RGBA8I, + ImageInternalFormat::R32I => ffi::ASTLayoutImageInternalFormat::R32I, + ImageInternalFormat::RGBA8 => ffi::ASTLayoutImageInternalFormat::RGBA8, + ImageInternalFormat::RGBA8SNORM => ffi::ASTLayoutImageInternalFormat::RGBA8SNORM, + } + } +} + +pub struct Generator<'options> { + // The IR types are mapped to a base TType; which are augmented with layout qualifiers etc when + // variables / functions are declared. + types: HashMap, + // Small constants are stored in TIntermConstantUnion. Larger constants are stored in a global + // variable (in global_variables, with a TIntermSymbol stashed here). Fields of nameless + // interface blocks are stored by their interface block id and field index. + constants: HashMap, + variables: HashMap, + nameless_block_field_variables: HashMap<(VariableId, u32), *mut TIntermTyped>, + functions: HashMap, + + // Global nodes like layout(early_fragment_tests). + preamble: Vec<*mut TIntermNode>, + // Struct type declarations + type_declarations: Vec<*mut TIntermNode>, + // List of global variables declarations. + global_variables: Vec<*mut TIntermNode>, + // The functions (TIntermFunctionDeclaration) in call DAG order + function_declarations: Vec<*mut TIntermNode>, + + // Every register is a typed value, mapped to a TIntermTyped. Later when the register is used, + // the corresponding node is used as child of a new node. The first use of the node can + // directly use the pointer, but consecutive uses need to deepCopy() the node. Unconditional + // deepCopy() is simpler, but can lead to lots of unnecessary copies. `needs_deep_copy` tracks + // this. + expressions: HashMap, + needs_deep_copy: HashSet, + + // Used by legacy code to declare types and variables. + legacy_compiler: *mut TCompiler, + // Derived from the GLSL version, used to decide which built-in to use, e.g. texture2D() vs + // texture() and other ES1 vs ES3 differences. + options: &'options compile::Options, +} + +impl<'options> Generator<'options> { + pub fn new( + legacy_compiler: *mut TCompiler, + options: &'options compile::Options, + ) -> Generator<'options> { + Generator { + types: HashMap::new(), + constants: HashMap::new(), + variables: HashMap::new(), + nameless_block_field_variables: HashMap::new(), + functions: HashMap::new(), + preamble: Vec::new(), + type_declarations: Vec::new(), + global_variables: Vec::new(), + function_declarations: Vec::new(), + expressions: HashMap::new(), + needs_deep_copy: HashSet::new(), + legacy_compiler, + options, + } + } + + fn legacy_symbol_type(name: &Name) -> ffi::ASTSymbolType { + debug_assert!(!name.name.starts_with("gl_")); + match name.source { + NameSource::ShaderInterface => { + if name.name.is_empty() { + ffi::ASTSymbolType::Empty + } else { + ffi::ASTSymbolType::UserDefined + } + } + NameSource::Internal => { + if name.name == "main" { + // `main` is considered a user-defined name in the AST, special as it's handled. + ffi::ASTSymbolType::UserDefined + } else { + ffi::ASTSymbolType::AngleInternal + } + } + NameSource::Temporary => { + if name.name.is_empty() { + ffi::ASTSymbolType::AngleInternal + } else { + ffi::ASTSymbolType::UserDefined + } + } + } + } + + fn legacy_struct_symbol_type(name: &Name) -> ffi::ASTSymbolType { + // For structs, the rules are a little different compared with other symbols: + // + // * Structs at global scope are marked as ShaderInterface, but their symbol type is + // AngleInternal instead of Empty. + // * gl_DepthRangeParameters needs to be handled and given a BuiltIn symbol type. + match name.source { + NameSource::ShaderInterface | NameSource::Temporary => { + if name.name.is_empty() { + ffi::ASTSymbolType::AngleInternal + } else { + ffi::ASTSymbolType::UserDefined + } + } + NameSource::Internal => { + if name.name.starts_with("gl_") { + ffi::ASTSymbolType::BuiltIn + } else { + ffi::ASTSymbolType::AngleInternal + } + } + } + } + + fn id_to_append(name: &Name, id: u32) -> u32 { + if name.source == NameSource::Temporary && !name.name.is_empty() { + id + } else { + SYMBOL_NAME_NO_ID + } + } + + fn legacy_param_direction(direction: FunctionParamDirection) -> ffi::ASTQualifier { + match direction { + FunctionParamDirection::Input => ffi::ASTQualifier::ParamIn, + FunctionParamDirection::Output => ffi::ASTQualifier::ParamOut, + FunctionParamDirection::InputOutput => ffi::ASTQualifier::ParamInOut, + } + } + + fn legacy_blend_equation_advanced(equations: &AdvancedBlendEquations) -> u32 { + // Identical to gl::BlendEquationType, only including advanced blend equations. + const BLEND_MULTIPLY: u32 = 1 << 6; + const BLEND_SCREEN: u32 = 1 << 7; + const BLEND_OVERLAY: u32 = 1 << 8; + const BLEND_DARKEN: u32 = 1 << 9; + const BLEND_LIGHTEN: u32 = 1 << 10; + const BLEND_COLORDODGE: u32 = 1 << 11; + const BLEND_COLORBURN: u32 = 1 << 12; + const BLEND_HARDLIGHT: u32 = 1 << 13; + const BLEND_SOFTLIGHT: u32 = 1 << 14; + const BLEND_DIFFERENCE: u32 = 1 << 16; + const BLEND_EXCLUSION: u32 = 1 << 18; + const BLEND_HSL_HUE: u32 = 1 << 19; + const BLEND_HSL_SATURATION: u32 = 1 << 20; + const BLEND_HSL_COLOR: u32 = 1 << 21; + const BLEND_HSL_LUMINOSITY: u32 = 1 << 22; + + let mut value = 0; + + if equations.multiply { + value |= BLEND_MULTIPLY; + } + if equations.screen { + value |= BLEND_SCREEN; + } + if equations.overlay { + value |= BLEND_OVERLAY; + } + if equations.darken { + value |= BLEND_DARKEN; + } + if equations.lighten { + value |= BLEND_LIGHTEN; + } + if equations.colordodge { + value |= BLEND_COLORDODGE; + } + if equations.colorburn { + value |= BLEND_COLORBURN; + } + if equations.hardlight { + value |= BLEND_HARDLIGHT; + } + if equations.softlight { + value |= BLEND_SOFTLIGHT; + } + if equations.difference { + value |= BLEND_DIFFERENCE; + } + if equations.exclusion { + value |= BLEND_EXCLUSION; + } + if equations.hsl_hue { + value |= BLEND_HSL_HUE; + } + if equations.hsl_saturation { + value |= BLEND_HSL_SATURATION; + } + if equations.hsl_color { + value |= BLEND_HSL_COLOR; + } + if equations.hsl_luminosity { + value |= BLEND_HSL_LUMINOSITY; + } + + value + } + + fn legacy_basic_type(basic_type: BasicType) -> ffi::ASTBasicType { + match basic_type { + BasicType::Void => ffi::ASTBasicType::Void, + BasicType::Float => ffi::ASTBasicType::Float, + BasicType::Int => ffi::ASTBasicType::Int, + BasicType::Uint => ffi::ASTBasicType::UInt, + BasicType::Bool => ffi::ASTBasicType::Bool, + BasicType::AtomicCounter => ffi::ASTBasicType::AtomicCounter, + BasicType::YuvCscStandard => ffi::ASTBasicType::YuvCscStandardEXT, + } + } + + fn legacy_image_basic_type( + image_basic_type: ImageBasicType, + image_type: &ImageType, + ) -> ffi::ASTBasicType { + match image_type.dimension { + ImageDimension::D2 => match image_basic_type { + ImageBasicType::Float => { + if image_type.is_sampled { + if image_type.is_shadow { + if image_type.is_array { + ffi::ASTBasicType::Sampler2DArrayShadow + } else { + ffi::ASTBasicType::Sampler2DShadow + } + } else { + match (image_type.is_ms, image_type.is_array) { + (false, false) => ffi::ASTBasicType::Sampler2D, + (false, true) => ffi::ASTBasicType::Sampler2DArray, + (true, false) => ffi::ASTBasicType::Sampler2DMS, + (true, true) => ffi::ASTBasicType::Sampler2DMSArray, + } + } + } else { + // Multisampled storage images are a desktop GLSL feature + debug_assert!(!image_type.is_ms); + if image_type.is_array { + ffi::ASTBasicType::Image2DArray + } else { + ffi::ASTBasicType::Image2D + } + } + } + ImageBasicType::Int => { + if image_type.is_sampled { + match (image_type.is_ms, image_type.is_array) { + (false, false) => ffi::ASTBasicType::ISampler2D, + (false, true) => ffi::ASTBasicType::ISampler2DArray, + (true, false) => ffi::ASTBasicType::ISampler2DMS, + (true, true) => ffi::ASTBasicType::ISampler2DMSArray, + } + } else { + debug_assert!(!image_type.is_ms); + if image_type.is_array { + ffi::ASTBasicType::IImage2DArray + } else { + ffi::ASTBasicType::IImage2D + } + } + } + ImageBasicType::Uint => { + if image_type.is_sampled { + match (image_type.is_ms, image_type.is_array) { + (false, false) => ffi::ASTBasicType::USampler2D, + (false, true) => ffi::ASTBasicType::USampler2DArray, + (true, false) => ffi::ASTBasicType::USampler2DMS, + (true, true) => ffi::ASTBasicType::USampler2DMSArray, + } + } else if image_type.is_array { + ffi::ASTBasicType::UImage2DArray + } else { + ffi::ASTBasicType::UImage2D + } + } + }, + ImageDimension::D3 => match image_basic_type { + ImageBasicType::Float => { + if image_type.is_sampled { + ffi::ASTBasicType::Sampler3D + } else { + ffi::ASTBasicType::Image3D + } + } + ImageBasicType::Int => { + if image_type.is_sampled { + ffi::ASTBasicType::ISampler3D + } else { + ffi::ASTBasicType::IImage3D + } + } + ImageBasicType::Uint => { + if image_type.is_sampled { + ffi::ASTBasicType::USampler3D + } else { + ffi::ASTBasicType::UImage3D + } + } + }, + ImageDimension::Cube => match image_basic_type { + ImageBasicType::Float => { + if image_type.is_sampled { + if image_type.is_shadow { + if image_type.is_array { + ffi::ASTBasicType::SamplerCubeArrayShadow + } else { + ffi::ASTBasicType::SamplerCubeShadow + } + } else if image_type.is_array { + ffi::ASTBasicType::SamplerCubeArray + } else { + ffi::ASTBasicType::SamplerCube + } + } else if image_type.is_array { + ffi::ASTBasicType::ImageCubeArray + } else { + ffi::ASTBasicType::ImageCube + } + } + ImageBasicType::Int => { + if image_type.is_sampled { + if image_type.is_array { + ffi::ASTBasicType::ISamplerCubeArray + } else { + ffi::ASTBasicType::ISamplerCube + } + } else if image_type.is_array { + ffi::ASTBasicType::IImageCubeArray + } else { + ffi::ASTBasicType::IImageCube + } + } + ImageBasicType::Uint => { + if image_type.is_sampled { + if image_type.is_array { + ffi::ASTBasicType::USamplerCubeArray + } else { + ffi::ASTBasicType::USamplerCube + } + } else if image_type.is_array { + ffi::ASTBasicType::UImageCubeArray + } else { + ffi::ASTBasicType::UImageCube + } + } + }, + ImageDimension::Rect => match image_basic_type { + ImageBasicType::Float => { + // Rect storage images are a desktop GLSL feature + debug_assert!(image_type.is_sampled); + ffi::ASTBasicType::Sampler2DRect + } + ImageBasicType::Int => { + debug_assert!(image_type.is_sampled); + ffi::ASTBasicType::ISampler2DRect + } + ImageBasicType::Uint => { + debug_assert!(image_type.is_sampled); + ffi::ASTBasicType::USampler2DRect + } + }, + ImageDimension::Buffer => match image_basic_type { + ImageBasicType::Float => { + if image_type.is_sampled { + ffi::ASTBasicType::SamplerBuffer + } else { + ffi::ASTBasicType::ImageBuffer + } + } + ImageBasicType::Int => { + if image_type.is_sampled { + ffi::ASTBasicType::ISamplerBuffer + } else { + ffi::ASTBasicType::IImageBuffer + } + } + ImageBasicType::Uint => { + if image_type.is_sampled { + ffi::ASTBasicType::USamplerBuffer + } else { + ffi::ASTBasicType::UImageBuffer + } + } + }, + ImageDimension::External => ffi::ASTBasicType::SamplerExternalOES, + ImageDimension::ExternalY2Y => ffi::ASTBasicType::SamplerExternal2DY2YEXT, + ImageDimension::Video => ffi::ASTBasicType::SamplerVideoWEBGL, + ImageDimension::PixelLocal => match image_basic_type { + ImageBasicType::Float => ffi::ASTBasicType::PixelLocalANGLE, + ImageBasicType::Int => ffi::ASTBasicType::IPixelLocalANGLE, + ImageBasicType::Uint => ffi::ASTBasicType::UPixelLocalANGLE, + }, + ImageDimension::Subpass => match image_basic_type { + ImageBasicType::Float => ffi::ASTBasicType::SubpassInput, + ImageBasicType::Int => ffi::ASTBasicType::ISubpassInput, + ImageBasicType::Uint => ffi::ASTBasicType::USubpassInput, + }, + } + } + + fn get_qualifier( + shader_type: ShaderType, + is_es1: bool, + decorations: &Decorations, + built_in: Option, + is_global: bool, + ) -> ffi::ASTQualifier { + if let Some(built_in) = built_in { + match built_in { + BuiltIn::InstanceID => ffi::ASTQualifier::InstanceID, + BuiltIn::VertexID => ffi::ASTQualifier::VertexID, + BuiltIn::Position => ffi::ASTQualifier::Position, + BuiltIn::PointSize => ffi::ASTQualifier::PointSize, + BuiltIn::BaseVertex => ffi::ASTQualifier::BaseVertex, + BuiltIn::BaseInstance => ffi::ASTQualifier::BaseInstance, + BuiltIn::DrawID => ffi::ASTQualifier::DrawID, + BuiltIn::FragCoord => ffi::ASTQualifier::FragCoord, + BuiltIn::FrontFacing => ffi::ASTQualifier::FrontFacing, + BuiltIn::PointCoord => ffi::ASTQualifier::PointCoord, + BuiltIn::HelperInvocation => ffi::ASTQualifier::HelperInvocation, + BuiltIn::FragColor => ffi::ASTQualifier::FragColor, + BuiltIn::FragData => ffi::ASTQualifier::FragData, + BuiltIn::FragDepth => ffi::ASTQualifier::FragDepth, + BuiltIn::SecondaryFragColorEXT => ffi::ASTQualifier::SecondaryFragColorEXT, + BuiltIn::SecondaryFragDataEXT => ffi::ASTQualifier::SecondaryFragDataEXT, + BuiltIn::DepthRange => ffi::ASTQualifier::DepthRange, + BuiltIn::ViewIDOVR => ffi::ASTQualifier::ViewIDOVR, + BuiltIn::ClipDistance => ffi::ASTQualifier::ClipDistance, + BuiltIn::CullDistance => ffi::ASTQualifier::CullDistance, + BuiltIn::LastFragColor => ffi::ASTQualifier::LastFragColor, + BuiltIn::LastFragData => ffi::ASTQualifier::LastFragData, + BuiltIn::LastFragDepthARM => ffi::ASTQualifier::LastFragDepth, + BuiltIn::LastFragStencilARM => ffi::ASTQualifier::LastFragStencil, + BuiltIn::ShadingRateEXT => ffi::ASTQualifier::ShadingRateEXT, + BuiltIn::PrimitiveShadingRateEXT => ffi::ASTQualifier::PrimitiveShadingRateEXT, + BuiltIn::SampleID => ffi::ASTQualifier::SampleID, + BuiltIn::SamplePosition => ffi::ASTQualifier::SamplePosition, + BuiltIn::SampleMaskIn => ffi::ASTQualifier::SampleMaskIn, + BuiltIn::SampleMask => ffi::ASTQualifier::SampleMask, + BuiltIn::NumSamples => ffi::ASTQualifier::NumSamples, + BuiltIn::NumWorkGroups => ffi::ASTQualifier::NumWorkGroups, + BuiltIn::WorkGroupSize => ffi::ASTQualifier::WorkGroupSize, + BuiltIn::WorkGroupID => ffi::ASTQualifier::WorkGroupID, + BuiltIn::LocalInvocationID => ffi::ASTQualifier::LocalInvocationID, + BuiltIn::GlobalInvocationID => ffi::ASTQualifier::GlobalInvocationID, + BuiltIn::LocalInvocationIndex => ffi::ASTQualifier::LocalInvocationIndex, + BuiltIn::PerVertexIn => ffi::ASTQualifier::PerVertexIn, + BuiltIn::PerVertexOut => ffi::ASTQualifier::PerVertexOut, + BuiltIn::PrimitiveIDIn => ffi::ASTQualifier::PrimitiveIDIn, + BuiltIn::InvocationID => ffi::ASTQualifier::InvocationID, + BuiltIn::PrimitiveID => ffi::ASTQualifier::PrimitiveID, + BuiltIn::LayerOut => ffi::ASTQualifier::LayerOut, + BuiltIn::LayerIn => ffi::ASTQualifier::LayerIn, + BuiltIn::PatchVerticesIn => ffi::ASTQualifier::PatchVerticesIn, + BuiltIn::TessLevelOuter => ffi::ASTQualifier::TessLevelOuter, + BuiltIn::TessLevelInner => ffi::ASTQualifier::TessLevelInner, + BuiltIn::TessCoord => ffi::ASTQualifier::TessCoord, + BuiltIn::BoundingBoxOES => ffi::ASTQualifier::BoundingBox, + BuiltIn::PixelLocalEXT => ffi::ASTQualifier::PixelLocalEXT, + } + } else if decorations + .decorations + .iter() + .any(|&decoration| matches!(decoration, Decoration::SpecConst(_))) + { + ffi::ASTQualifier::SpecConst + } else { + let is_input = decorations.has(Decoration::Input); + let is_output = decorations.has(Decoration::Output); + let is_inout = decorations.has(Decoration::InputOutput); + let is_uniform = decorations.has(Decoration::Uniform); + let is_buffer = decorations.has(Decoration::Buffer); + let is_shared = decorations.has(Decoration::Shared); + let is_smooth = decorations.has(Decoration::Smooth); + let is_flat = decorations.has(Decoration::Flat); + let is_noperspective = decorations.has(Decoration::NoPerspective); + let is_centroid = decorations.has(Decoration::Centroid); + let is_sample = decorations.has(Decoration::Sample); + let is_patch = decorations.has(Decoration::Patch); + + if is_uniform { + ffi::ASTQualifier::Uniform + } else if is_buffer { + ffi::ASTQualifier::Buffer + } else if is_shared { + ffi::ASTQualifier::Shared + } else if is_input { + if is_smooth { + ffi::ASTQualifier::SmoothIn + } else if is_flat { + ffi::ASTQualifier::FlatIn + } else if is_noperspective { + if is_centroid { + ffi::ASTQualifier::NoPerspectiveCentroidIn + } else if is_sample { + ffi::ASTQualifier::NoPerspectiveSampleIn + } else { + ffi::ASTQualifier::NoPerspectiveIn + } + } else if is_centroid { + ffi::ASTQualifier::CentroidIn + } else if is_sample { + ffi::ASTQualifier::SampleIn + } else if is_patch { + ffi::ASTQualifier::PatchIn + } else if is_es1 { + if shader_type == ShaderType::Vertex { + ffi::ASTQualifier::Attribute + } else { + ffi::ASTQualifier::VaryingIn + } + } else { + match shader_type { + ShaderType::Vertex => ffi::ASTQualifier::VertexIn, + ShaderType::TessellationControl => ffi::ASTQualifier::TessControlIn, + ShaderType::TessellationEvaluation => ffi::ASTQualifier::TessEvaluationIn, + ShaderType::Geometry => ffi::ASTQualifier::GeometryIn, + ShaderType::Fragment => ffi::ASTQualifier::FragmentIn, + ShaderType::Compute => { + panic!("Internal error: Unexpected Input decoration in compute shader") + } + } + } + } else if is_output { + if is_smooth { + ffi::ASTQualifier::SmoothOut + } else if is_flat { + ffi::ASTQualifier::FlatOut + } else if is_noperspective { + if is_centroid { + ffi::ASTQualifier::NoPerspectiveCentroidOut + } else if is_sample { + ffi::ASTQualifier::NoPerspectiveSampleOut + } else { + ffi::ASTQualifier::NoPerspectiveOut + } + } else if is_centroid { + ffi::ASTQualifier::CentroidOut + } else if is_sample { + ffi::ASTQualifier::SampleOut + } else if is_patch { + ffi::ASTQualifier::PatchOut + } else if is_es1 && shader_type != ShaderType::Fragment { + ffi::ASTQualifier::VaryingOut + } else { + match shader_type { + ShaderType::Vertex => ffi::ASTQualifier::VertexOut, + ShaderType::TessellationControl => ffi::ASTQualifier::TessControlOut, + ShaderType::TessellationEvaluation => ffi::ASTQualifier::TessEvaluationOut, + ShaderType::Geometry => ffi::ASTQualifier::GeometryOut, + ShaderType::Fragment => ffi::ASTQualifier::FragmentOut, + ShaderType::Compute => { + panic!("Internal error: Unexpected Output decoration in compute shader") + } + } + } + } else if is_inout { + ffi::ASTQualifier::FragmentInOut + } else if is_global { + // AST marks fields as EvqGlobal if not otherwise qualified. If qualified, these + // must be members of I/O blocks, and they are not qualified as in or out + // explicitly. + if is_smooth { + ffi::ASTQualifier::Smooth + } else if is_flat { + ffi::ASTQualifier::Flat + } else if is_noperspective { + if is_centroid { + ffi::ASTQualifier::NoPerspectiveCentroid + } else if is_sample { + ffi::ASTQualifier::NoPerspectiveSample + } else { + ffi::ASTQualifier::NoPerspective + } + } else if is_centroid { + ffi::ASTQualifier::Centroid + } else if is_sample { + ffi::ASTQualifier::Sample + } else if is_patch { + ffi::ASTQualifier::Patch + } else { + ffi::ASTQualifier::Global + } + } else { + ffi::ASTQualifier::Temporary + } + } + } + + fn get_layout_qualifier(decorations: &Decorations) -> ffi::ASTLayoutQualifier { + let mut layout_qualifier = ffi::ASTLayoutQualifier { + location: -1, + matrix_packing: ffi::ASTLayoutMatrixPacking::Unspecified, + block_storage: ffi::ASTLayoutBlockStorage::Unspecified, + binding: -1, + offset: -1, + depth: ffi::ASTLayoutDepth::Unspecified, + image_internal_format: ffi::ASTLayoutImageInternalFormat::Unspecified, + num_views: -1, + yuv: false, + index: -1, + noncoherent: false, + push_constant: false, + input_attachment_index: -1, + raster_ordered: false, + }; + + for &decoration in &decorations.decorations { + match decoration { + Decoration::PushConstant => layout_qualifier.push_constant = true, + Decoration::NonCoherent => layout_qualifier.noncoherent = true, + Decoration::Yuv => layout_qualifier.yuv = true, + Decoration::Location(location) => layout_qualifier.location = location as i32, + Decoration::Index(index) => layout_qualifier.index = index as i32, + Decoration::InputAttachmentIndex(index) => { + layout_qualifier.input_attachment_index = index as i32 + } + Decoration::SpecConst(location) => layout_qualifier.location = location as i32, + Decoration::Block(storage) => layout_qualifier.block_storage = storage.into(), + Decoration::Binding(binding) => layout_qualifier.binding = binding as i32, + Decoration::Offset(offset) => layout_qualifier.offset = offset as i32, + Decoration::MatrixPacking(packing) => { + layout_qualifier.matrix_packing = packing.into() + } + Decoration::Depth(depth) => layout_qualifier.depth = depth.into(), + Decoration::ImageInternalFormat(format) => { + layout_qualifier.image_internal_format = format.into() + } + Decoration::NumViews(num_views) => layout_qualifier.num_views = num_views as i32, + Decoration::RasterOrdered => layout_qualifier.raster_ordered = true, + _ => (), + }; + } + + layout_qualifier + } + + fn get_memory_qualifier(decorations: &Decorations) -> ffi::ASTMemoryQualifier { + let readonly = decorations.has(Decoration::ReadOnly); + let writeonly = decorations.has(Decoration::WriteOnly); + let coherent = decorations.has(Decoration::Coherent); + let restrict_qualifier = decorations.has(Decoration::Restrict); + let volatile_qualifier = decorations.has(Decoration::Volatile); + + ffi::ASTMemoryQualifier { + readonly, + writeonly, + coherent, + restrict_qualifier, + volatile_qualifier, + } + } + + fn get_ast_type( + shader_type: ShaderType, + is_es1: bool, + precision: Precision, + decorations: &Decorations, + built_in: Option, + is_global: bool, + ) -> ffi::ASTType { + let invariant = decorations.has(Decoration::Invariant); + let precise = decorations.has(Decoration::Precise); + let interpolant = decorations.has(Decoration::Interpolant); + + ffi::ASTType { + // Note: TypeId is unused after going back to AST. + type_id: TYPE_ID_VOID.into(), + qualifier: Self::get_qualifier(shader_type, is_es1, decorations, built_in, is_global), + precision: precision.into(), + layout_qualifier: Self::get_layout_qualifier(decorations), + memory_qualifier: Self::get_memory_qualifier(decorations), + invariant, + precise, + interpolant, + } + } + + fn built_in_str(built_in: BuiltIn, shader_type: ShaderType, is_es1: bool) -> &'static str { + match built_in { + BuiltIn::InstanceID => "gl_InstanceID", + BuiltIn::VertexID => "gl_VertexID", + BuiltIn::Position => "gl_Position", + BuiltIn::PointSize => "gl_PointSize", + BuiltIn::BaseVertex => "gl_BaseVertex", + BuiltIn::BaseInstance => "gl_BaseInstance", + BuiltIn::DrawID => "gl_DrawID", + BuiltIn::FragCoord => "gl_FragCoord", + BuiltIn::FrontFacing => "gl_FrontFacing", + BuiltIn::PointCoord => "gl_PointCoord", + BuiltIn::HelperInvocation => "gl_HelperInvocation", + BuiltIn::FragColor => "gl_FragColor", + BuiltIn::FragData => "gl_FragData", + BuiltIn::FragDepth => { + if is_es1 { + "gl_FragDepthEXT" + } else { + "gl_FragDepth" + } + } + BuiltIn::SecondaryFragColorEXT => "gl_SecondaryFragColorEXT", + BuiltIn::SecondaryFragDataEXT => "gl_SecondaryFragDataEXT", + BuiltIn::DepthRange => "gl_DepthRange", + BuiltIn::ViewIDOVR => "gl_ViewID_OVR", + BuiltIn::ClipDistance => "gl_ClipDistance", + BuiltIn::CullDistance => "gl_CullDistance", + BuiltIn::LastFragColor => "gl_LastFragColorARM", + BuiltIn::LastFragData => "gl_LastFragData", + BuiltIn::LastFragDepthARM => "gl_LastFragDepthARM", + BuiltIn::LastFragStencilARM => "gl_LastFragStencilARM", + BuiltIn::ShadingRateEXT => "gl_ShadingRateEXT", + BuiltIn::PrimitiveShadingRateEXT => "gl_PrimitiveShadingRateEXT", + BuiltIn::SampleID => "gl_SampleID", + BuiltIn::SamplePosition => "gl_SamplePosition", + BuiltIn::SampleMaskIn => "gl_SampleMaskIn", + BuiltIn::SampleMask => "gl_SampleMask", + BuiltIn::NumSamples => "gl_NumSamples", + BuiltIn::NumWorkGroups => "gl_NumWorkGroups", + BuiltIn::WorkGroupSize => "gl_WorkGroupSize", + BuiltIn::WorkGroupID => "gl_WorkGroupID", + BuiltIn::LocalInvocationID => "gl_LocalInvocationID", + BuiltIn::GlobalInvocationID => "gl_GlobalInvocationID", + BuiltIn::LocalInvocationIndex => "gl_LocalInvocationIndex", + BuiltIn::PerVertexIn => "gl_in", + BuiltIn::PerVertexOut => { + if shader_type == ShaderType::TessellationControl { + "gl_out" + } else { + "" + } + } + BuiltIn::PrimitiveIDIn => "gl_PrimitiveIDIn", + BuiltIn::InvocationID => "gl_InvocationID", + BuiltIn::PrimitiveID => "gl_PrimitiveID", + BuiltIn::LayerOut => "gl_Layer", + BuiltIn::LayerIn => "gl_Layer", + BuiltIn::PatchVerticesIn => "gl_PatchVerticesIn", + BuiltIn::TessLevelOuter => "gl_TessLevelOuter", + BuiltIn::TessLevelInner => "gl_TessLevelInner", + BuiltIn::TessCoord => "gl_TessCoord", + BuiltIn::BoundingBoxOES => "gl_BoundingBoxOES", + BuiltIn::PixelLocalEXT => "gl_PixelLocalEXT", + } + } + + fn declare_variable( + &self, + variable: *mut TIntermTyped, + initializer: Option, + ) -> *mut TIntermNode { + if let Some(constant_id) = initializer { + let initializer = self.constants[&constant_id]; + unsafe { ffi::declare_variable_with_initializer(variable, initializer) } + } else { + unsafe { ffi::declare_variable(variable) } + } + } + + fn get_expression(&mut self, id: TypedId) -> ffi::Expression { + match id.id { + Id::Register(id) => { + // The first time an expression is used, don't duplicate it. If it's ever used more + // than once, duplicate it then. + let needs_copy = !self.needs_deep_copy.insert(id); + ffi::Expression { node: self.expressions[&id], needs_copy } + } + Id::Constant(id) => ffi::Expression { node: self.constants[&id], needs_copy: true }, + Id::Variable(id) => ffi::Expression { node: self.variables[&id], needs_copy: true }, + } + } + + fn get_sampler_type(ir_meta: &IRMeta, sampler: TypedId) -> ffi::ASTBasicType { + let (basic_type, image_type) = ir_meta.get_type(sampler.type_id).get_image_type(); + Self::legacy_image_basic_type(basic_type, image_type) + } +} + +impl ast::Target for Generator<'_> { + type BlockResult = *mut TIntermBlock; + + fn begin(&mut self) {} + fn end(&mut self) -> *mut TIntermBlock { + unsafe { + ffi::finalize( + self.legacy_compiler, + &self.type_declarations, + &self.global_variables, + &self.function_declarations, + ) + } + } + + fn new_type(&mut self, ir_meta: &IRMeta, id: TypeId, type_info: &Type) { + let legacy_type = match type_info { + &Type::Scalar(basic_type) => unsafe { + ffi::make_basic_type(Self::legacy_basic_type(basic_type)) + }, + &Type::Vector(type_id, count) => unsafe { + ffi::make_vector_type(self.types[&type_id], count) + }, + &Type::Matrix(type_id, count) => unsafe { + ffi::make_matrix_type(self.types[&type_id], count) + }, + &Type::Array(type_id, count) => unsafe { + ffi::make_array_type(self.types[&type_id], count) + }, + &Type::UnsizedArray(type_id) => unsafe { + ffi::make_unsized_array_type(self.types[&type_id]) + }, + &Type::Image(basic_type, ref image_type) => unsafe { + ffi::make_basic_type(Self::legacy_image_basic_type(basic_type, image_type)) + }, + Type::Struct(name, fields, specialization) => { + let is_interface_block = *specialization == StructSpecialization::InterfaceBlock; + let fields = fields + .iter() + .map(|field| ffi::ASTFieldInfo { + name: field.name.name, + base_type: self.types[&field.type_id], + ast_type: Self::get_ast_type( + ir_meta.get_shader_type(), + self.options.is_es1, + field.precision, + &field.decorations, + None, + // AST marks fields as EvqGlobal + true, + ), + }) + .collect::>(); + + let symbol_type = Self::legacy_struct_symbol_type(name); + let legacy_type = unsafe { + ffi::make_struct_type( + self.legacy_compiler, + &ffi::SymbolName { + name: name.name, + symbol_type, + id: Self::id_to_append(name, id.id), + }, + &fields, + is_interface_block, + ) + }; + if !is_interface_block && symbol_type != ffi::ASTSymbolType::BuiltIn { + self.type_declarations + .push(unsafe { ffi::declare_struct(self.legacy_compiler, legacy_type) }); + } + + legacy_type + } + &Type::Pointer(pointee_type_id) => self.types[&pointee_type_id], + Type::DeadCodeEliminated => { + return; + } + }; + + self.types.insert(id, legacy_type); + } + + fn new_constant(&mut self, ir_meta: &IRMeta, id: ConstantId, constant: &Constant) { + let constant = match &constant.value { + &ConstantValue::Float(f) => unsafe { ffi::make_float_constant(f) }, + &ConstantValue::Int(i) => unsafe { ffi::make_int_constant(i) }, + &ConstantValue::Uint(u) => unsafe { ffi::make_uint_constant(u) }, + &ConstantValue::Bool(b) => unsafe { ffi::make_bool_constant(b) }, + &ConstantValue::YuvCsc(yuv_csc) => unsafe { + ffi::make_yuv_csc_constant(yuv_csc.into()) + }, + ConstantValue::Composite(elements) => { + let constant_type = self.types[&constant.type_id]; + let type_info = ir_meta.get_type(constant.type_id); + let value = unsafe { + ffi::make_composite_constant( + &elements.iter().map(|element| self.constants[element]).collect::>(), + constant_type, + ) + }; + + // With the AST, small constants are kept as TIntermConstantUnion, while + // the rest are stored in temp variables to avoid excessive repetition: + // + // - All arrays use temp variables + // - Otherwise, non-structs use inline constants + // - Structures with arrays use temp variables + // - Otherwise only structs with 16 bytes or less are inlined. + // + // For simplicity, small struct constants are also placed in variables (which is + // not a common scenario). + if type_info.is_array() || type_info.is_struct() { + let variable = unsafe { + ffi::make_constant_variable(self.legacy_compiler, constant_type, value) + }; + let declaration = + unsafe { ffi::declare_variable_with_initializer(variable, value) }; + + self.global_variables.push(declaration); + variable + } else { + value + } + } + }; + + self.constants.insert(id, constant); + } + + fn new_variable(&mut self, ir_meta: &IRMeta, id: VariableId, variable: &Variable) { + let var_type = self.types[&variable.type_id]; + let is_global = variable.scope == VariableScope::Global; + let ast_type = Self::get_ast_type( + ir_meta.get_shader_type(), + self.options.is_es1, + variable.precision, + &variable.decorations, + variable.built_in, + is_global, + ); + + let (var_name, symbol_type, field_symbol_type) = if let Some(built_in) = variable.built_in { + let var_name = + Self::built_in_str(built_in, ir_meta.get_shader_type(), self.options.is_es1); + ( + var_name, + if var_name.is_empty() { + // gl_PerVertex can have an empty instance name when it's the output of + // geometry shader. + ffi::ASTSymbolType::Empty + } else { + ffi::ASTSymbolType::BuiltIn + }, + Some(ffi::ASTSymbolType::BuiltIn), + ) + } else { + (variable.name.name, Self::legacy_symbol_type(&variable.name), None) + }; + + let is_redeclared_built_in = match variable.built_in { + Some(BuiltIn::PerVertexIn) => ir_meta.is_per_vertex_in_redeclared(), + Some(BuiltIn::PerVertexOut) => ir_meta.is_per_vertex_out_redeclared(), + // Always redeclare gl_FragDepth if possible even if the shader didn't. + Some(BuiltIn::FragDepth) => self.options.extensions.EXT_conservative_depth, + // Always redeclare gl_Clip/CullDistance even if the shader didn't. + Some(BuiltIn::ClipDistance) | Some(BuiltIn::CullDistance) => true, + _ => false, + }; + + let legacy_variable = unsafe { + ffi::make_variable( + self.legacy_compiler, + &ffi::SymbolName { + name: var_name, + symbol_type, + id: Self::id_to_append(&variable.name, id.id), + }, + var_type, + &ast_type, + is_redeclared_built_in, + variable.is_static_use, + ) + }; + + self.variables.insert(id, legacy_variable); + + // Most built-ins may not be redeclared, but may still be modified via global statements + // like `invariant gl_Position;`. Take those into account here. + if !is_redeclared_built_in && variable.built_in.is_some() { + if ast_type.invariant { + self.global_variables + .push(unsafe { ffi::globally_qualify_built_in_invariant(legacy_variable) }); + } + if ast_type.precise { + self.global_variables + .push(unsafe { ffi::globally_qualify_built_in_precise(legacy_variable) }); + } + } + + // The AST expects to have a dedicated variable for each field of an unnamed interface + // block. In theory, the IR should be able to still generate (unnamed).field and let the + // AST side handle things correctly, but currently there are too many places that assume to + // be able to find or reference nodes based on field alone. + debug_assert!(ir_meta.get_type(variable.type_id).is_pointer()); + if let Type::Struct(_, fields, StructSpecialization::InterfaceBlock) = + ir_meta.get_type(ir_meta.get_type(variable.type_id).get_element_type_id().unwrap()) + && symbol_type == ffi::ASTSymbolType::Empty + { + for (index, field) in fields.iter().enumerate() { + let field_name = field.name.name; + let field_symbol_type = + field_symbol_type.unwrap_or_else(|| Self::legacy_symbol_type(&field.name)); + + let field_type = self.types[&field.type_id]; + let field_ast_type = Self::get_ast_type( + ir_meta.get_shader_type(), + self.options.is_es1, + field.precision, + &field.decorations, + None, + true, + ); + + let legacy_field_variable = unsafe { + ffi::make_nameless_block_field_variable( + self.legacy_compiler, + legacy_variable, + index as u32, + &ffi::SymbolName { + name: field_name, + symbol_type: field_symbol_type, + id: SYMBOL_NAME_NO_ID, + }, + field_type, + &field_ast_type, + ) + }; + + self.nameless_block_field_variables + .insert((id, index as u32), legacy_field_variable); + } + } + } + + fn new_function(&mut self, ir_meta: &IRMeta, id: FunctionId, function: &Function) { + let params = function + .params + .iter() + .map(|param| self.variables[¶m.variable_id]) + .collect::>(); + let param_directions = function + .params + .iter() + .map(|param| Self::legacy_param_direction(param.direction)) + .collect::>(); + + let return_type = self.types[&function.return_type_id]; + let return_ast_type = Self::get_ast_type( + ir_meta.get_shader_type(), + self.options.is_es1, + function.return_precision, + &function.return_decorations, + None, + false, + ); + let symbol_type = Self::legacy_symbol_type(&function.name); + + let legacy_function = unsafe { + ffi::make_function( + self.legacy_compiler, + &ffi::SymbolName { + name: function.name.name, + symbol_type, + id: Self::id_to_append(&function.name, id.id), + }, + return_type, + &return_ast_type, + ¶ms, + ¶m_directions, + ) + }; + self.functions.insert(id, legacy_function); + } + + fn global_scope(&mut self, ir_meta: &IRMeta) { + // The global properties such as early_fragment_tests, blend_equation_advanced, TCS, TES + // and GS parameters are already parsed and stashed in TCompiler. The IR currently does not + // modify them, so there is no need to pass them back to it. + + // Declare global variables. Local variables are declared in the block they are + // encountered. + ir_meta.all_global_variables().iter().for_each(|&id| { + let variable = ir_meta.get_variable(id); + debug_assert!(variable.scope == VariableScope::Global); + + // Most built-ins cannot be redeclared, don't add a declaration for them in the AST. + // gl_FragDepth can be redeclared, but not gl_FragDepthEXT. + let skip_declaration = match variable.built_in { + Some(BuiltIn::PerVertexIn) => !ir_meta.is_per_vertex_in_redeclared(), + Some(BuiltIn::PerVertexOut) => !ir_meta.is_per_vertex_out_redeclared(), + Some(BuiltIn::FragDepth) => !self.options.extensions.EXT_conservative_depth, + Some(BuiltIn::LastFragData) + | Some(BuiltIn::LastFragColor) + | Some(BuiltIn::LastFragDepthARM) + | Some(BuiltIn::LastFragStencilARM) + | Some(BuiltIn::ClipDistance) + | Some(BuiltIn::CullDistance) => false, + Some(_) => true, + _ => false, + }; + + if !skip_declaration { + let declaration = self.declare_variable(self.variables[&id], variable.initializer); + self.global_variables.push(declaration); + } + }); + } + + fn begin_block(&mut self, ir_meta: &IRMeta, variables: &[VariableId]) -> *mut TIntermBlock { + let block = unsafe { ffi::make_interm_block() }; + variables.iter().for_each(|&id| { + let variable = ir_meta.get_variable(id); + let declaration = self.declare_variable(self.variables[&id], variable.initializer); + unsafe { ffi::append_instructions_to_block(block, &[declaration]) }; + }); + block + } + + fn merge_blocks(&mut self, blocks: Vec<*mut TIntermBlock>) -> *mut TIntermBlock { + debug_assert!(!blocks.is_empty()); + unsafe { ffi::append_blocks_to_block(blocks[0], &blocks[1..]) }; + blocks[0] + } + + fn swizzle_single( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + id: TypedId, + index: u32, + ) { + let expr = unsafe { ffi::swizzle(&self.get_expression(id), &[index]) }; + self.expressions.insert(result, expr); + } + + fn swizzle_multi( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + id: TypedId, + indices: &[u32], + ) { + let expr = unsafe { ffi::swizzle(&self.get_expression(id), indices) }; + self.expressions.insert(result, expr); + } + + fn index( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + id: TypedId, + index: TypedId, + ) { + let expr = unsafe { ffi::index(&self.get_expression(id), &self.get_expression(index)) }; + self.expressions.insert(result, expr); + } + + fn select_field( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + id: TypedId, + index: u32, + _field: &Field, + ) { + // When selecting a field of a nameless interface block, the AST expects to see references + // to the field variables directly. + if let Id::Variable(var_id) = id.id + && let Some(&field_variable) = self.nameless_block_field_variables.get(&(var_id, index)) + { + self.expressions.insert(result, field_variable); + self.needs_deep_copy.insert(result); + return; + } + let expr = unsafe { ffi::select_field(&self.get_expression(id), index) }; + self.expressions.insert(result, expr); + } + + fn construct_single( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + type_id: TypeId, + id: TypedId, + ) { + let expr = unsafe { ffi::construct(self.types[&type_id], &[self.get_expression(id)]) }; + self.expressions.insert(result, expr); + } + + fn construct_multi( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + type_id: TypeId, + ids: &[TypedId], + ) { + let expr = unsafe { + ffi::construct( + self.types[&type_id], + &ids.iter().map(|&id| self.get_expression(id)).collect::>(), + ) + }; + self.expressions.insert(result, expr); + } + + fn load( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + pointer: TypedId, + ) { + // Nothing to do, AST does not distinguish pointers from values, so load is implicitly + // done. Just associate the id of the loaded value to the pointer expression. + let expr = self.get_expression(pointer); + self.expressions.insert(result, expr.node); + + // Because two ids reference the same node, make sure the duplicate one always requires a + // copy. + self.needs_deep_copy.insert(result); + } + + fn store(&mut self, block_result: &mut *mut TIntermBlock, pointer: TypedId, value: TypedId) { + let assignment = + unsafe { ffi::store(&self.get_expression(pointer), &self.get_expression(value)) }; + unsafe { ffi::append_instructions_to_block(*block_result, &[assignment]) }; + } + + fn call( + &mut self, + block_result: &mut *mut TIntermBlock, + result: Option, + function_id: FunctionId, + params: &[TypedId], + ) { + let params = params.iter().map(|&id| self.get_expression(id)).collect::>(); + let function = self.functions[&function_id]; + match result { + Some(result) => { + let expr = unsafe { ffi::call(function, ¶ms) }; + self.expressions.insert(result, expr); + } + None => { + let statement = unsafe { ffi::call_void(function, ¶ms) }; + unsafe { ffi::append_instructions_to_block(*block_result, &[statement]) }; + } + }; + } + + fn unary( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + unary_op: UnaryOpCode, + id: TypedId, + ) { + let operand = self.get_expression(id); + let expr = unsafe { + match unary_op { + UnaryOpCode::ArrayLength => ffi::array_length(&operand), + UnaryOpCode::Negate => ffi::negate(&operand), + UnaryOpCode::PostfixIncrement => ffi::postfix_increment(&operand), + UnaryOpCode::PostfixDecrement => ffi::postfix_decrement(&operand), + UnaryOpCode::PrefixIncrement => ffi::prefix_increment(&operand), + UnaryOpCode::PrefixDecrement => ffi::prefix_decrement(&operand), + UnaryOpCode::LogicalNot => ffi::logical_not(&operand), + UnaryOpCode::BitwiseNot => ffi::bitwise_not(&operand), + UnaryOpCode::Radians => ffi::built_in_radians(self.legacy_compiler, &operand), + UnaryOpCode::Degrees => ffi::built_in_degrees(self.legacy_compiler, &operand), + UnaryOpCode::Sin => ffi::built_in_sin(self.legacy_compiler, &operand), + UnaryOpCode::Cos => ffi::built_in_cos(self.legacy_compiler, &operand), + UnaryOpCode::Tan => ffi::built_in_tan(self.legacy_compiler, &operand), + UnaryOpCode::Asin => ffi::built_in_asin(self.legacy_compiler, &operand), + UnaryOpCode::Acos => ffi::built_in_acos(self.legacy_compiler, &operand), + UnaryOpCode::Atan => ffi::built_in_atan(self.legacy_compiler, &operand), + UnaryOpCode::Sinh => ffi::built_in_sinh(self.legacy_compiler, &operand), + UnaryOpCode::Cosh => ffi::built_in_cosh(self.legacy_compiler, &operand), + UnaryOpCode::Tanh => ffi::built_in_tanh(self.legacy_compiler, &operand), + UnaryOpCode::Asinh => ffi::built_in_asinh(self.legacy_compiler, &operand), + UnaryOpCode::Acosh => ffi::built_in_acosh(self.legacy_compiler, &operand), + UnaryOpCode::Atanh => ffi::built_in_atanh(self.legacy_compiler, &operand), + UnaryOpCode::Exp => ffi::built_in_exp(self.legacy_compiler, &operand), + UnaryOpCode::Log => ffi::built_in_log(self.legacy_compiler, &operand), + UnaryOpCode::Exp2 => ffi::built_in_exp2(self.legacy_compiler, &operand), + UnaryOpCode::Log2 => ffi::built_in_log2(self.legacy_compiler, &operand), + UnaryOpCode::Sqrt => ffi::built_in_sqrt(self.legacy_compiler, &operand), + UnaryOpCode::Inversesqrt => { + ffi::built_in_inversesqrt(self.legacy_compiler, &operand) + } + UnaryOpCode::Abs => ffi::built_in_abs(self.legacy_compiler, &operand), + UnaryOpCode::Sign => ffi::built_in_sign(self.legacy_compiler, &operand), + UnaryOpCode::Floor => ffi::built_in_floor(self.legacy_compiler, &operand), + UnaryOpCode::Trunc => ffi::built_in_trunc(self.legacy_compiler, &operand), + UnaryOpCode::Round => ffi::built_in_round(self.legacy_compiler, &operand), + UnaryOpCode::RoundEven => ffi::built_in_roundeven(self.legacy_compiler, &operand), + UnaryOpCode::Ceil => ffi::built_in_ceil(self.legacy_compiler, &operand), + UnaryOpCode::Fract => ffi::built_in_fract(self.legacy_compiler, &operand), + UnaryOpCode::Isnan => ffi::built_in_isnan(self.legacy_compiler, &operand), + UnaryOpCode::Isinf => ffi::built_in_isinf(self.legacy_compiler, &operand), + UnaryOpCode::FloatBitsToInt => { + ffi::built_in_floatbitstoint(self.legacy_compiler, &operand) + } + UnaryOpCode::FloatBitsToUint => { + ffi::built_in_floatbitstouint(self.legacy_compiler, &operand) + } + UnaryOpCode::IntBitsToFloat => { + ffi::built_in_intbitstofloat(self.legacy_compiler, &operand) + } + UnaryOpCode::UintBitsToFloat => { + ffi::built_in_uintbitstofloat(self.legacy_compiler, &operand) + } + UnaryOpCode::PackSnorm2x16 => { + ffi::built_in_packsnorm2x16(self.legacy_compiler, &operand) + } + UnaryOpCode::PackHalf2x16 => { + ffi::built_in_packhalf2x16(self.legacy_compiler, &operand) + } + UnaryOpCode::UnpackSnorm2x16 => { + ffi::built_in_unpacksnorm2x16(self.legacy_compiler, &operand) + } + UnaryOpCode::UnpackHalf2x16 => { + ffi::built_in_unpackhalf2x16(self.legacy_compiler, &operand) + } + UnaryOpCode::PackUnorm2x16 => { + ffi::built_in_packunorm2x16(self.legacy_compiler, &operand) + } + UnaryOpCode::UnpackUnorm2x16 => { + ffi::built_in_unpackunorm2x16(self.legacy_compiler, &operand) + } + UnaryOpCode::PackUnorm4x8 => { + ffi::built_in_packunorm4x8(self.legacy_compiler, &operand) + } + UnaryOpCode::PackSnorm4x8 => { + ffi::built_in_packsnorm4x8(self.legacy_compiler, &operand) + } + UnaryOpCode::UnpackUnorm4x8 => { + ffi::built_in_unpackunorm4x8(self.legacy_compiler, &operand) + } + UnaryOpCode::UnpackSnorm4x8 => { + ffi::built_in_unpacksnorm4x8(self.legacy_compiler, &operand) + } + UnaryOpCode::Length => ffi::built_in_length(self.legacy_compiler, &operand), + UnaryOpCode::Normalize => ffi::built_in_normalize(self.legacy_compiler, &operand), + UnaryOpCode::Transpose => ffi::built_in_transpose(self.legacy_compiler, &operand), + UnaryOpCode::Determinant => { + ffi::built_in_determinant(self.legacy_compiler, &operand) + } + UnaryOpCode::Inverse => ffi::built_in_inverse(self.legacy_compiler, &operand), + UnaryOpCode::Any => ffi::built_in_any(self.legacy_compiler, &operand), + UnaryOpCode::All => ffi::built_in_all(self.legacy_compiler, &operand), + UnaryOpCode::Not => ffi::built_in_not(self.legacy_compiler, &operand), + UnaryOpCode::BitfieldReverse => { + ffi::built_in_bitfieldreverse(self.legacy_compiler, &operand) + } + UnaryOpCode::BitCount => ffi::built_in_bitcount(self.legacy_compiler, &operand), + UnaryOpCode::FindLSB => ffi::built_in_findlsb(self.legacy_compiler, &operand), + UnaryOpCode::FindMSB => ffi::built_in_findmsb(self.legacy_compiler, &operand), + UnaryOpCode::DFdx => ffi::built_in_dfdx(self.legacy_compiler, &operand), + UnaryOpCode::DFdy => ffi::built_in_dfdy(self.legacy_compiler, &operand), + UnaryOpCode::Fwidth => ffi::built_in_fwidth(self.legacy_compiler, &operand), + UnaryOpCode::InterpolateAtCentroid => { + ffi::built_in_interpolateatcentroid(self.legacy_compiler, &operand) + } + UnaryOpCode::AtomicCounter => { + ffi::built_in_atomiccounter(self.legacy_compiler, &operand) + } + UnaryOpCode::AtomicCounterIncrement => { + ffi::built_in_atomiccounterincrement(self.legacy_compiler, &operand) + } + UnaryOpCode::AtomicCounterDecrement => { + ffi::built_in_atomiccounterdecrement(self.legacy_compiler, &operand) + } + UnaryOpCode::ImageSize => ffi::built_in_imagesize(self.legacy_compiler, &operand), + UnaryOpCode::PixelLocalLoadANGLE => { + ffi::built_in_pixellocalload(self.legacy_compiler, &operand) + } + } + }; + self.expressions.insert(result, expr); + } + + fn binary( + &mut self, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + binary_op: BinaryOpCode, + lhs: TypedId, + rhs: TypedId, + ) { + let lhs = self.get_expression(lhs); + let rhs = self.get_expression(rhs); + let expr = unsafe { + match binary_op { + BinaryOpCode::Add => ffi::add(&lhs, &rhs), + BinaryOpCode::Sub => ffi::sub(&lhs, &rhs), + BinaryOpCode::Mul => ffi::mul(&lhs, &rhs), + BinaryOpCode::VectorTimesScalar => ffi::vector_times_scalar(&lhs, &rhs), + BinaryOpCode::MatrixTimesScalar => ffi::matrix_times_scalar(&lhs, &rhs), + BinaryOpCode::VectorTimesMatrix => ffi::vector_times_matrix(&lhs, &rhs), + BinaryOpCode::MatrixTimesVector => ffi::matrix_times_vector(&lhs, &rhs), + BinaryOpCode::MatrixTimesMatrix => ffi::matrix_times_matrix(&lhs, &rhs), + BinaryOpCode::Div => ffi::div(&lhs, &rhs), + BinaryOpCode::IMod => ffi::imod(&lhs, &rhs), + BinaryOpCode::LogicalXor => ffi::logical_xor(&lhs, &rhs), + BinaryOpCode::Equal => ffi::equal(&lhs, &rhs), + BinaryOpCode::NotEqual => ffi::not_equal(&lhs, &rhs), + BinaryOpCode::LessThan => ffi::less_than(&lhs, &rhs), + BinaryOpCode::GreaterThan => ffi::greater_than(&lhs, &rhs), + BinaryOpCode::LessThanEqual => ffi::less_than_equal(&lhs, &rhs), + BinaryOpCode::GreaterThanEqual => ffi::greater_than_equal(&lhs, &rhs), + BinaryOpCode::BitShiftLeft => ffi::bit_shift_left(&lhs, &rhs), + BinaryOpCode::BitShiftRight => ffi::bit_shift_right(&lhs, &rhs), + BinaryOpCode::BitwiseOr => ffi::bitwise_or(&lhs, &rhs), + BinaryOpCode::BitwiseXor => ffi::bitwise_xor(&lhs, &rhs), + BinaryOpCode::BitwiseAnd => ffi::bitwise_and(&lhs, &rhs), + BinaryOpCode::Atan => ffi::built_in_atan_binary(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Pow => ffi::built_in_pow(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Mod => ffi::built_in_mod(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Min => ffi::built_in_min(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Max => ffi::built_in_max(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Step => ffi::built_in_step(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Modf => ffi::built_in_modf(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Frexp => ffi::built_in_frexp(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Ldexp => ffi::built_in_ldexp(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Distance => ffi::built_in_distance(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Dot => ffi::built_in_dot(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Cross => ffi::built_in_cross(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::Reflect => ffi::built_in_reflect(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::MatrixCompMult => { + ffi::built_in_matrixcompmult(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::OuterProduct => { + ffi::built_in_outerproduct(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::LessThanVec => { + ffi::built_in_lessthanvec(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::LessThanEqualVec => { + ffi::built_in_lessthanequalvec(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::GreaterThanVec => { + ffi::built_in_greaterthanvec(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::GreaterThanEqualVec => { + ffi::built_in_greaterthanequalvec(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::EqualVec => ffi::built_in_equalvec(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::NotEqualVec => { + ffi::built_in_notequalvec(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::InterpolateAtSample => { + ffi::built_in_interpolateatsample(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::InterpolateAtOffset => { + ffi::built_in_interpolateatoffset(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::AtomicAdd => { + ffi::built_in_atomicadd(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::AtomicMin => { + ffi::built_in_atomicmin(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::AtomicMax => { + ffi::built_in_atomicmax(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::AtomicAnd => { + ffi::built_in_atomicand(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::AtomicOr => ffi::built_in_atomicor(self.legacy_compiler, &lhs, &rhs), + BinaryOpCode::AtomicXor => { + ffi::built_in_atomicxor(self.legacy_compiler, &lhs, &rhs) + } + BinaryOpCode::AtomicExchange => { + ffi::built_in_atomicexchange(self.legacy_compiler, &lhs, &rhs) + } + } + }; + self.expressions.insert(result, expr); + } + + fn built_in( + &mut self, + block_result: &mut *mut TIntermBlock, + result: Option, + built_in_op: BuiltInOpCode, + args: &[TypedId], + ) { + let args = args.iter().map(|&arg| self.get_expression(arg)).collect::>(); + let (expr, statement) = unsafe { + match built_in_op { + BuiltInOpCode::Clamp => { + (Some(ffi::built_in_clamp(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::Mix => (Some(ffi::built_in_mix(self.legacy_compiler, &args)), None), + BuiltInOpCode::Smoothstep => { + (Some(ffi::built_in_smoothstep(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::Fma => (Some(ffi::built_in_fma(self.legacy_compiler, &args)), None), + BuiltInOpCode::Faceforward => { + (Some(ffi::built_in_faceforward(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::Refract => { + (Some(ffi::built_in_refract(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::BitfieldExtract => { + (Some(ffi::built_in_bitfieldextract(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::BitfieldInsert => { + (Some(ffi::built_in_bitfieldinsert(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::UaddCarry => { + (Some(ffi::built_in_uaddcarry(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::UsubBorrow => { + (Some(ffi::built_in_usubborrow(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::UmulExtended => { + (None, Some(ffi::built_in_umulextended(self.legacy_compiler, &args))) + } + BuiltInOpCode::ImulExtended => { + (None, Some(ffi::built_in_imulextended(self.legacy_compiler, &args))) + } + BuiltInOpCode::TextureSize => { + (Some(ffi::built_in_texturesize(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::TextureQueryLod => { + (Some(ffi::built_in_texturequerylod(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::TexelFetch => { + (Some(ffi::built_in_texelfetch(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::TexelFetchOffset => { + (Some(ffi::built_in_texelfetchoffset(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::Rgb2Yuv => { + (Some(ffi::built_in_rgb_2_yuv(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::Yuv2Rgb => { + (Some(ffi::built_in_yuv_2_rgb(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::AtomicCompSwap => { + (Some(ffi::built_in_atomiccompswap(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageStore => { + (None, Some(ffi::built_in_imagestore(self.legacy_compiler, &args))) + } + BuiltInOpCode::ImageLoad => { + (Some(ffi::built_in_imageload(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicAdd => { + (Some(ffi::built_in_imageatomicadd(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicMin => { + (Some(ffi::built_in_imageatomicmin(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicMax => { + (Some(ffi::built_in_imageatomicmax(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicAnd => { + (Some(ffi::built_in_imageatomicand(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicOr => { + (Some(ffi::built_in_imageatomicor(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicXor => { + (Some(ffi::built_in_imageatomicxor(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicExchange => { + (Some(ffi::built_in_imageatomicexchange(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::ImageAtomicCompSwap => { + (Some(ffi::built_in_imageatomiccompswap(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::PixelLocalStoreANGLE => { + (None, Some(ffi::built_in_pixellocalstore(self.legacy_compiler, &args))) + } + BuiltInOpCode::MemoryBarrier => { + (None, Some(ffi::built_in_memorybarrier(self.legacy_compiler, &args))) + } + BuiltInOpCode::MemoryBarrierAtomicCounter => ( + None, + Some(ffi::built_in_memorybarrieratomiccounter(self.legacy_compiler, &args)), + ), + BuiltInOpCode::MemoryBarrierBuffer => { + (None, Some(ffi::built_in_memorybarrierbuffer(self.legacy_compiler, &args))) + } + BuiltInOpCode::MemoryBarrierImage => { + (None, Some(ffi::built_in_memorybarrierimage(self.legacy_compiler, &args))) + } + BuiltInOpCode::Barrier => { + (None, Some(ffi::built_in_barrier(self.legacy_compiler, &args))) + } + BuiltInOpCode::MemoryBarrierShared => { + (None, Some(ffi::built_in_memorybarriershared(self.legacy_compiler, &args))) + } + BuiltInOpCode::GroupMemoryBarrier => { + (None, Some(ffi::built_in_groupmemorybarrier(self.legacy_compiler, &args))) + } + BuiltInOpCode::EmitVertex => { + (None, Some(ffi::built_in_emitvertex(self.legacy_compiler, &args))) + } + BuiltInOpCode::EndPrimitive => { + (None, Some(ffi::built_in_endprimitive(self.legacy_compiler, &args))) + } + BuiltInOpCode::SubpassLoad => { + (Some(ffi::built_in_subpassload(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::BeginInvocationInterlockNV => ( + None, + Some(ffi::built_in_begininvocationinterlocknv(self.legacy_compiler, &args)), + ), + BuiltInOpCode::EndInvocationInterlockNV => ( + None, + Some(ffi::built_in_endinvocationinterlocknv(self.legacy_compiler, &args)), + ), + BuiltInOpCode::BeginFragmentShaderOrderingINTEL => ( + None, + Some(ffi::built_in_beginfragmentshaderorderingintel( + self.legacy_compiler, + &args, + )), + ), + BuiltInOpCode::BeginInvocationInterlockARB => ( + None, + Some(ffi::built_in_begininvocationinterlockarb(self.legacy_compiler, &args)), + ), + BuiltInOpCode::EndInvocationInterlockARB => ( + None, + Some(ffi::built_in_endinvocationinterlockarb(self.legacy_compiler, &args)), + ), + BuiltInOpCode::NumSamples => { + (Some(ffi::built_in_numsamples(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::SamplePosition => { + (Some(ffi::built_in_sampleposition(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::InterpolateAtCenter => { + (Some(ffi::built_in_interpolateatcenter(self.legacy_compiler, &args)), None) + } + BuiltInOpCode::LoopForwardProgress => { + (None, Some(ffi::built_in_loopforwardprogress(self.legacy_compiler, &args))) + } + BuiltInOpCode::Saturate => { + (Some(ffi::built_in_saturate(self.legacy_compiler, &args)), None) + } + } + }; + if let Some(result) = result { + self.expressions.insert(result, expr.unwrap()); + } else { + unsafe { ffi::append_instructions_to_block(*block_result, &[statement.unwrap()]) }; + } + } + + fn texture( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + offset: Option, + ) { + let sampler_type = Self::get_sampler_type(ir_meta, sampler); + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + + let expr = if let Some(offset) = offset { + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_textureoffset( + self.legacy_compiler, + &[sampler, coord, offset], + is_proj, + ) + } + } else { + unsafe { + ffi::built_in_texture( + self.legacy_compiler, + &[sampler, coord], + sampler_type, + is_proj, + ) + } + }; + self.expressions.insert(result, expr); + } + + fn texture_compare( + &mut self, + _ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + ) { + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let compare = self.get_expression(compare); + + let expr = unsafe { + ffi::built_in_texture_with_compare(self.legacy_compiler, &[sampler, coord, compare]) + }; + self.expressions.insert(result, expr); + } + + fn texture_lod( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + lod: TypedId, + offset: Option, + ) { + let sampler_type = Self::get_sampler_type(ir_meta, sampler); + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let lod = self.get_expression(lod); + + let expr = if let Some(offset) = offset { + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_texturelodoffset( + self.legacy_compiler, + &[sampler, coord, lod, offset], + is_proj, + ) + } + } else { + unsafe { + ffi::built_in_texturelod( + self.legacy_compiler, + &[sampler, coord, lod], + sampler_type, + is_proj, + ) + } + }; + self.expressions.insert(result, expr); + } + + fn texture_compare_lod( + &mut self, + _ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + lod: TypedId, + ) { + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let compare = self.get_expression(compare); + let lod = self.get_expression(lod); + + let expr = unsafe { + ffi::built_in_texturelod_with_compare( + self.legacy_compiler, + &[sampler, coord, compare, lod], + ) + }; + self.expressions.insert(result, expr); + } + + fn texture_bias( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + bias: TypedId, + offset: Option, + ) { + let sampler_type = Self::get_sampler_type(ir_meta, sampler); + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let bias = self.get_expression(bias); + + let expr = if let Some(offset) = offset { + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_textureoffset( + self.legacy_compiler, + &[sampler, coord, offset, bias], + is_proj, + ) + } + } else { + unsafe { + ffi::built_in_texture( + self.legacy_compiler, + &[sampler, coord, bias], + sampler_type, + is_proj, + ) + } + }; + self.expressions.insert(result, expr); + } + + fn texture_compare_bias( + &mut self, + _ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + compare: TypedId, + bias: TypedId, + ) { + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let compare = self.get_expression(compare); + let bias = self.get_expression(bias); + + let expr = unsafe { + ffi::built_in_texture_with_compare( + self.legacy_compiler, + &[sampler, coord, compare, bias], + ) + }; + self.expressions.insert(result, expr); + } + + fn texture_grad( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + is_proj: bool, + dx: TypedId, + dy: TypedId, + offset: Option, + ) { + let sampler_type = Self::get_sampler_type(ir_meta, sampler); + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let dx = self.get_expression(dx); + let dy = self.get_expression(dy); + + let expr = if let Some(offset) = offset { + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_texturegradoffset( + self.legacy_compiler, + &[sampler, coord, dx, dy, offset], + is_proj, + ) + } + } else { + unsafe { + ffi::built_in_texturegrad( + self.legacy_compiler, + &[sampler, coord, dx, dy], + sampler_type, + is_proj, + ) + } + }; + self.expressions.insert(result, expr); + } + + fn texture_gather( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + offset: Option, + ) { + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + + let expr = if let Some(offset) = offset { + let is_offset_array = ir_meta.get_type(offset.type_id).is_array(); + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_texturegatheroffset( + self.legacy_compiler, + &[sampler, coord, offset], + is_offset_array, + ) + } + } else { + unsafe { ffi::built_in_texturegather(self.legacy_compiler, &[sampler, coord]) } + }; + self.expressions.insert(result, expr); + } + + fn texture_gather_component( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + component: TypedId, + offset: Option, + ) { + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let component = self.get_expression(component); + + let expr = if let Some(offset) = offset { + let is_offset_array = ir_meta.get_type(offset.type_id).is_array(); + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_texturegatheroffset( + self.legacy_compiler, + &[sampler, coord, offset, component], + is_offset_array, + ) + } + } else { + unsafe { + ffi::built_in_texturegather(self.legacy_compiler, &[sampler, coord, component]) + } + }; + self.expressions.insert(result, expr); + } + + fn texture_gather_ref( + &mut self, + ir_meta: &IRMeta, + _block_result: &mut *mut TIntermBlock, + result: RegisterId, + sampler: TypedId, + coord: TypedId, + refz: TypedId, + offset: Option, + ) { + let sampler = self.get_expression(sampler); + let coord = self.get_expression(coord); + let refz = self.get_expression(refz); + + let expr = if let Some(offset) = offset { + let is_offset_array = ir_meta.get_type(offset.type_id).is_array(); + let offset = self.get_expression(offset); + unsafe { + ffi::built_in_texturegatheroffset( + self.legacy_compiler, + &[sampler, coord, refz, offset], + is_offset_array, + ) + } + } else { + unsafe { ffi::built_in_texturegather(self.legacy_compiler, &[sampler, coord, refz]) } + }; + self.expressions.insert(result, expr); + } + + fn branch_discard(&mut self, block: &mut *mut TIntermBlock) { + unsafe { ffi::branch_discard(*block) }; + } + fn branch_return(&mut self, block: &mut *mut TIntermBlock, value: Option) { + if let Some(id) = value { + unsafe { ffi::branch_return_value(*block, &self.get_expression(id)) }; + } else { + unsafe { ffi::branch_return(*block) }; + } + } + fn branch_break(&mut self, block: &mut *mut TIntermBlock) { + unsafe { ffi::branch_break(*block) }; + } + fn branch_continue(&mut self, block: &mut *mut TIntermBlock) { + unsafe { ffi::branch_continue(*block) }; + } + fn branch_if( + &mut self, + block: &mut *mut TIntermBlock, + condition: TypedId, + true_block: Option<*mut TIntermBlock>, + false_block: Option<*mut TIntermBlock>, + ) { + // The true block should always be present. + let true_block = true_block.unwrap(); + let condition = self.get_expression(condition); + if let Some(false_block) = false_block { + unsafe { ffi::branch_if_else(*block, &condition, true_block, false_block) }; + } else { + unsafe { ffi::branch_if(*block, &condition, true_block) }; + } + } + fn branch_loop( + &mut self, + block: &mut *mut TIntermBlock, + loop_condition_block: Option<*mut TIntermBlock>, + body_block: Option<*mut TIntermBlock>, + ) { + // The condition and body blocks should always be present. + unsafe { ffi::branch_loop(*block, loop_condition_block.unwrap(), body_block.unwrap()) }; + } + fn branch_do_loop( + &mut self, + block: &mut *mut TIntermBlock, + body_block: Option<*mut TIntermBlock>, + ) { + // The condition and body blocks should always be present. The difference between + // DoLoop and Loop is effectively that the condition block is evaluated after the body + // instead of before. + unsafe { ffi::branch_do_loop(*block, body_block.unwrap()) }; + } + fn branch_loop_if(&mut self, block: &mut *mut TIntermBlock, condition: TypedId) { + // The condition block of a loop ends in `if (!condition) break;` + unsafe { ffi::branch_loop_if(*block, &self.get_expression(condition)) }; + } + fn branch_switch( + &mut self, + block: &mut *mut TIntermBlock, + value: TypedId, + case_ids: &[Option], + case_blocks: Vec<*mut TIntermBlock>, + ) { + let value = self.get_expression(value); + let case_labels = case_ids + .iter() + .map(|id| id.map(|id| self.constants[&id]).unwrap_or(std::ptr::null_mut())) + .collect::>(); + + unsafe { ffi::branch_switch(*block, &value, &case_labels, &case_blocks) }; + } + + // Take the current AST and place it as the body of the given function. + fn end_function(&mut self, block_result: *mut TIntermBlock, id: FunctionId) { + let declaration = unsafe { ffi::declare_function(self.functions[&id], block_result) }; + self.function_declarations.push(declaration); + } +} diff --git a/src/compiler/translator/ir/src/pool_alloc.cpp b/src/compiler/translator/ir/src/pool_alloc.cpp new file mode 100644 index 00000000000..c518dd681d7 --- /dev/null +++ b/src/compiler/translator/ir/src/pool_alloc.cpp @@ -0,0 +1,45 @@ +// +// Copyright 2025 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. +// + +#include "compiler/translator/ir/src/pool_alloc.h" + +#include "compiler/translator/ir/src/compile.rs.h" + +#include "compiler/translator/InitializeGlobals.h" +#include "compiler/translator/PoolAlloc.h" + +#include + +namespace sh +{ +namespace ir +{ +namespace ffi +{ +void initialize_global_pool_index() +{ + // If going through Rust and back has landed us in a different copy of the translator, also + // initialize the TLS in this copy. + if (!IsGlobalPoolAllocatorInitialized()) + { + InitializePoolIndex(); + } +} +void free_global_pool_index() +{ + if (IsGlobalPoolAllocatorInitialized()) + { + FreePoolIndex(); + } +} + +void set_global_pool_allocator(angle::PoolAllocator *allocator) +{ + SetGlobalPoolAllocator(allocator); +} +} // namespace ffi +} // namespace ir +} // namespace sh diff --git a/src/compiler/translator/ir/src/pool_alloc.h b/src/compiler/translator/ir/src/pool_alloc.h new file mode 100644 index 00000000000..7077648b972 --- /dev/null +++ b/src/compiler/translator/ir/src/pool_alloc.h @@ -0,0 +1,30 @@ +// +// Copyright 2025 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. +// +// Bridge from IR in Rust. Forward declares callbacks from IR to generate a legacy AST. +// + +#ifndef COMPILER_TRANSLATOR_IR_SRC_POOL_ALLOC_H_ +#define COMPILER_TRANSLATOR_IR_SRC_POOL_ALLOC_H_ + +namespace angle +{ +class PoolAllocator; +} + +namespace sh +{ +namespace ir +{ +namespace ffi +{ +void initialize_global_pool_index(); +void free_global_pool_index(); +void set_global_pool_allocator(angle::PoolAllocator *allocator); +} // namespace ffi +} // namespace ir +} // namespace sh + +#endif // COMPILER_TRANSLATOR_IR_SRC_POOL_ALLOC_H_ diff --git a/src/compiler/translator/ir/src/transform.rs b/src/compiler/translator/ir/src/transform.rs new file mode 100644 index 00000000000..6e56e2e7af9 --- /dev/null +++ b/src/compiler/translator/ir/src/transform.rs @@ -0,0 +1,9 @@ +// 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. +pub mod astify; +pub mod dealias; +pub mod initialize_uninitialized_variables; +pub mod propagate_precision; +pub mod prune_unused_variables; +pub mod remove_unused_framebuffer_fetch; diff --git a/src/compiler/translator/ir/src/transform/astify.rs b/src/compiler/translator/ir/src/transform/astify.rs new file mode 100644 index 00000000000..4ebd58e6b34 --- /dev/null +++ b/src/compiler/translator/ir/src/transform/astify.rs @@ -0,0 +1,1167 @@ +// 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. +// +// Prepare the IR for turning into AST (be it ANGLE's legacy AST, or actual GLSL/etc text): +// +// - Remove merge block inputs and replace them with temp variables. +// - Use temporary variables for ops that have side effect but whose results are used multiple +// times. +// - Use temporary variables for swizzles applied to swizzles. This is normally folded, except if +// the first swizzle is applied to a pointer, it's loaded, and then another swizzle is applied to +// the loaded value. +// - Use temporary variables for constants whose precision is higher than the other operands in the +// instruction so that the constant's precision is not lost. +// - TODO(http://anglebug.com/349994211): Use temporary variables for ops whose result precision +// does not match what would have automatically been derived for it... it's a rather niche +// optimization, as precision mismatch can happen only by IR transformations. Current AST doesn't +// do this (so GLSL output would have incorrect precisions for example), although intermediate +// nodes' precisions are retained during transformation so SPIR-V output is correct. Without this +// change, SPIR-V output from AST after IR is incorrect until SPIR-V is directly generated from +// IR. +// - Replicate the continue block before every `continue`, if any. +// - Replicate the do-loop condition block before every `continue`, if any, but with it ending with +// `if (!condition) break;`. To support `continue` inside `switch`, a bool variable is created +// for those that include a `continue` statement, which is set to true before the `break` that's +// generated during this replication. After the switch, an `if (propagate_break) break;` is +// added. +use crate::ir::*; +use crate::*; + +#[cfg_attr(debug_assertions, derive(Debug))] +struct RegisterInfo { + // How many times the register is read from. + read_count: u32, + // Whether the calculation that led to this ID has side effect. If the ID is read from + // multiple times, it cannot be replicated in AST if it has side effects. + has_side_effect: bool, + // Whether the calculation that led to this ID is complex. If the ID is read from + // multiple times, it is inefficient in AST to replicate it. + is_complex: bool, + // Whether the register must be marked as having a side effect if ever accessed. See + // `preprocess_block_registers`'s comment on OpCode::Load. + mark_side_effect_if_read: bool, +} + +impl RegisterInfo { + fn new() -> RegisterInfo { + RegisterInfo { + read_count: 0, + has_side_effect: false, + is_complex: false, + mark_side_effect_if_read: false, + } + } +} + +#[cfg_attr(debug_assertions, derive(Debug))] +struct BreakInfo { + // Whether this is a switch block + is_switch: bool, + // What is the variable to propagate `break`s. + propagate_break_var: Option, +} + +impl BreakInfo { + fn new_loop() -> BreakInfo { + BreakInfo { is_switch: false, propagate_break_var: None } + } + + fn new_switch() -> BreakInfo { + BreakInfo { is_switch: true, propagate_break_var: None } + } +} + +#[cfg_attr(debug_assertions, derive(Debug))] +struct State<'a> { + ir_meta: &'a mut IRMeta, + // Used to know when temporary variables are needed + register_info: HashMap, + // List of registers without side effect that are not necessarily cached in a temp variable, + // see comment in `preprocess_block_registers` for details. + uncached_registers: Vec, + // Used to replicate the continue block of for loops before each `continue` + // instruction. `continue_stack` includes the continue block of constructs that + // interact with a `continue` instruction (Loop and DoLoop). + continue_stack: Vec>, + // Used to replicate the condition block of do-loops before each `continue` + // instruction. + // + // `break_stack` tracks constructs that interact with a `break` instruction (Loop, + // DoLoop and Switch). It contains whether the construct is a Switch block, and if so + // whether it needs a variable for an indirect break and what that variable is. + // + // `condition_stack` includes the condition block of DoLoop, or None for Loops. The + // condition block is changed to include `if (!condition) break` followed by + // `NextBlock`, instead of `LoopIf`. + break_stack: Vec, + condition_stack: Vec>, +} + +pub fn run(ir: &mut IR) { + let mut state = State { + ir_meta: &mut ir.meta, + register_info: HashMap::new(), + uncached_registers: Vec::new(), + continue_stack: Vec::new(), + break_stack: Vec::new(), + condition_stack: Vec::new(), + }; + + // Pre-process the registers to determine when temporary variables are needed. + preprocess_registers(&mut state, &ir.function_entries); + + // First, create temporary variables for the result of instructions that have side + // effects and yet are read from multiple times. + traverser::transformer::for_each_instruction( + &mut state, + &mut ir.function_entries, + &|state, instruction| transform_instruction(state, instruction), + ); + + // Then create variables for merge block inputs as that is not representable in the + // AST. No need to try and be smart with them, such as producing ?:, && or ||. + traverser::transformer::for_each_function( + &mut state, + &mut ir.function_entries, + &|state, _, entry| { + traverser::transformer::for_each_block( + state, + entry, + &|state, block| replace_merge_input_with_variable(state, block), + &|_, block| block, + ); + }, + ); + + // Finally, duplicate the continue block, if any, before each `continue` branch, because + // it may be too complicated to be placed inside a `for ()` expression. Afterwards, + // the IR no longer has continue blocks. + // + // At the same time, duplicate the condition block of do-loops before each `continue` + // branch. + traverser::transformer::for_each_function( + &mut state, + &mut ir.function_entries, + &|state, _, entry| { + traverser::transformer::for_each_block( + state, + entry, + &|state, block| transform_continue_instructions_pre_visit(state, block), + &|state, block| transform_continue_instructions_post_visit(state, block), + ); + }, + ); +} + +fn get_op_read_ids(opcode: &OpCode) -> Vec { + match opcode { + OpCode::MergeInput + | OpCode::Discard + | OpCode::Break + | OpCode::Continue + | OpCode::Passthrough + | OpCode::NextBlock + | OpCode::Loop + | OpCode::DoLoop + | OpCode::Return(None) + | OpCode::Merge(None) => vec![], + OpCode::Call(_, params) + | OpCode::ConstructVectorFromMultiple(params) + | OpCode::ConstructMatrixFromMultiple(params) + | OpCode::ConstructStruct(params) + | OpCode::ConstructArray(params) + | OpCode::BuiltIn(_, params) => params.clone(), + &OpCode::Return(Some(id)) + | &OpCode::Merge(Some(id)) + | &OpCode::If(id) + | &OpCode::LoopIf(id) + | &OpCode::Switch(id, _) + | &OpCode::ExtractVectorComponent(id, _) + | &OpCode::ExtractVectorComponentMulti(id, _) + | &OpCode::ExtractStructField(id, _) + | &OpCode::ConstructScalarFromScalar(id) + | &OpCode::ConstructVectorFromScalar(id) + | &OpCode::ConstructMatrixFromScalar(id) + | &OpCode::ConstructMatrixFromMatrix(id) + | &OpCode::AccessVectorComponent(id, _) + | &OpCode::AccessVectorComponentMulti(id, _) + | &OpCode::AccessStructField(id, _) + | &OpCode::Load(id) + | &OpCode::Unary(_, id) => vec![id], + &OpCode::ExtractVectorComponentDynamic(lhs, rhs) + | &OpCode::ExtractMatrixColumn(lhs, rhs) + | &OpCode::ExtractArrayElement(lhs, rhs) + | &OpCode::AccessVectorComponentDynamic(lhs, rhs) + | &OpCode::AccessMatrixColumn(lhs, rhs) + | &OpCode::AccessArrayElement(lhs, rhs) + | &OpCode::Store(lhs, rhs) + | &OpCode::Binary(_, lhs, rhs) => vec![lhs, rhs], + &OpCode::Texture(ref texture_op, sampler, coord) => { + let mut read_ids = Vec::with_capacity(4); + read_ids.push(sampler); + read_ids.push(coord); + match texture_op { + &TextureOpCode::Implicit { is_proj: _, offset } + | &TextureOpCode::Gather { offset } => { + offset.inspect(|&id| read_ids.push(id)); + } + &TextureOpCode::Compare { compare } => { + read_ids.push(compare); + } + &TextureOpCode::Lod { is_proj: _, lod, offset } => { + read_ids.push(lod); + offset.inspect(|&id| read_ids.push(id)); + } + &TextureOpCode::CompareLod { compare, lod } => { + read_ids.push(compare); + read_ids.push(lod); + } + &TextureOpCode::Bias { is_proj: _, bias, offset } => { + read_ids.push(bias); + offset.inspect(|&id| read_ids.push(id)); + } + &TextureOpCode::CompareBias { compare, bias } => { + read_ids.push(compare); + read_ids.push(bias); + } + &TextureOpCode::Grad { is_proj: _, dx, dy, offset } => { + read_ids.push(dx); + read_ids.push(dy); + offset.inspect(|&id| read_ids.push(id)); + } + &TextureOpCode::GatherComponent { component, offset } => { + read_ids.push(component); + offset.inspect(|&id| read_ids.push(id)); + } + &TextureOpCode::GatherRef { refz, offset } => { + read_ids.push(refz); + offset.inspect(|&id| read_ids.push(id)); + } + }; + read_ids + } + &OpCode::Alias(_) => { + panic!("Internal error: Aliases must have been resolved before text generation") + } + } +} + +// Return whether Loads and other expressions without side effect can stay deferred after this op +// or not. Additionally, it returns whether the op only reads from its arguments or not; if it +// only reads from the arguments, then the expressions don't need to be cached before the op +// itself. +fn can_reorder_expressions_after_op(opcode: &OpCode) -> (bool, bool) { + match opcode { + OpCode::Store(..) => (false, true), + OpCode::Call(..) + | OpCode::Unary(UnaryOpCode::PrefixIncrement, _) + | OpCode::Unary(UnaryOpCode::PrefixDecrement, _) + | OpCode::Unary(UnaryOpCode::PostfixIncrement, _) + | OpCode::Unary(UnaryOpCode::PostfixDecrement, _) + | OpCode::Unary(UnaryOpCode::AtomicCounterIncrement, _) + | OpCode::Unary(UnaryOpCode::AtomicCounterDecrement, _) + | OpCode::Binary(BinaryOpCode::Modf, _, _) + | OpCode::Binary(BinaryOpCode::Frexp, _, _) + | OpCode::Binary(BinaryOpCode::AtomicAdd, _, _) + | OpCode::Binary(BinaryOpCode::AtomicMin, _, _) + | OpCode::Binary(BinaryOpCode::AtomicMax, _, _) + | OpCode::Binary(BinaryOpCode::AtomicAnd, _, _) + | OpCode::Binary(BinaryOpCode::AtomicOr, _, _) + | OpCode::Binary(BinaryOpCode::AtomicXor, _, _) + | OpCode::Binary(BinaryOpCode::AtomicExchange, _, _) + | OpCode::BuiltIn(BuiltInOpCode::UaddCarry, _) + | OpCode::BuiltIn(BuiltInOpCode::UsubBorrow, _) + | OpCode::BuiltIn(BuiltInOpCode::UmulExtended, _) + | OpCode::BuiltIn(BuiltInOpCode::ImulExtended, _) + | OpCode::BuiltIn(BuiltInOpCode::AtomicCompSwap, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageStore, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicAdd, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicMin, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicMax, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicAnd, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicOr, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicXor, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicExchange, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicCompSwap, _) + | OpCode::BuiltIn(BuiltInOpCode::PixelLocalStoreANGLE, _) => { + // Functions may mutate global variables. They may also mutate out and inout + // variables. For simplicity, we don't try to track exactly what they mutate, and + // assume any load that has been deferred might be mutated by the call (and so, cannot + // be deferred). + // Similarly, for built-ins that modify memory, we don't track what exactly they might + // have modified. + (false, false) + } + OpCode::BuiltIn(BuiltInOpCode::BeginInvocationInterlockNV, _) + | OpCode::BuiltIn(BuiltInOpCode::EndInvocationInterlockNV, _) + | OpCode::BuiltIn(BuiltInOpCode::BeginFragmentShaderOrderingINTEL, _) + | OpCode::BuiltIn(BuiltInOpCode::BeginInvocationInterlockARB, _) + | OpCode::BuiltIn(BuiltInOpCode::EndInvocationInterlockARB, _) => { + // Reads should not be deferred to after the interlock operation (especially _end_ of + // the interlock). + (false, false) + } + _ => (true, false), + } +} + +fn clear_uncached_registers( + uncached_registers: &mut Vec, + register_info: &mut HashMap, +) { + uncached_registers.iter().for_each(|id| { + register_info.get_mut(id).unwrap().mark_side_effect_if_read = true; + }); + uncached_registers.clear(); +} + +fn preprocess_block_registers(state: &mut State, block: &Block) { + // Add an unassuming entry for the merge input, if any. + if let Some(input) = block.input { + state.register_info.entry(input.id).or_insert(RegisterInfo::new()); + } + + for instruction in &block.instructions { + let (opcode, result) = instruction.get_op_and_result(state.ir_meta); + + // If any loads are deferred, make sure they are not done after instructions that might + // have mutated their memory. This is done by marking them to be cached if ever read + // again; if never read after this point, it was fine to let them be read on use before + // this point. + let (can_reorder_expressions, op_only_reads_from_args) = + can_reorder_expressions_after_op(opcode); + if !can_reorder_expressions && !op_only_reads_from_args { + clear_uncached_registers(&mut state.uncached_registers, &mut state.register_info); + } + + // Mark every potentially-register Id in the arguments of the opcode as being + // accessed. + for id in get_op_read_ids(opcode) { + if let Id::Register(id) = id.id { + let read_register_info = state.register_info.get_mut(&id).unwrap(); + read_register_info.read_count += 1; + + if read_register_info.mark_side_effect_if_read { + read_register_info.has_side_effect = true; + } + } + } + + if !can_reorder_expressions && op_only_reads_from_args { + clear_uncached_registers(&mut state.uncached_registers, &mut state.register_info); + } + + // If the instruction has a side-effect, mark its resulting ID as having side + // effect. Similarly, if it is complex, mark it as such. + if let Some(result_id) = result { + // Add an unassuming entry for the result. + let result_info = + state.register_info.entry(result_id.id).or_insert(RegisterInfo::new()); + + match opcode { + OpCode::Call(..) + | OpCode::Unary(UnaryOpCode::PrefixIncrement, _) + | OpCode::Unary(UnaryOpCode::PrefixDecrement, _) + | OpCode::Unary(UnaryOpCode::PostfixIncrement, _) + | OpCode::Unary(UnaryOpCode::PostfixDecrement, _) + | OpCode::Unary(UnaryOpCode::AtomicCounter, _) + | OpCode::Unary(UnaryOpCode::AtomicCounterIncrement, _) + | OpCode::Unary(UnaryOpCode::AtomicCounterDecrement, _) + | OpCode::Unary(UnaryOpCode::PixelLocalLoadANGLE, _) + | OpCode::Binary(BinaryOpCode::Modf, _, _) + | OpCode::Binary(BinaryOpCode::Frexp, _, _) + | OpCode::Binary(BinaryOpCode::AtomicAdd, _, _) + | OpCode::Binary(BinaryOpCode::AtomicMin, _, _) + | OpCode::Binary(BinaryOpCode::AtomicMax, _, _) + | OpCode::Binary(BinaryOpCode::AtomicAnd, _, _) + | OpCode::Binary(BinaryOpCode::AtomicOr, _, _) + | OpCode::Binary(BinaryOpCode::AtomicXor, _, _) + | OpCode::Binary(BinaryOpCode::AtomicExchange, _, _) + | OpCode::BuiltIn(BuiltInOpCode::UaddCarry, _) + | OpCode::BuiltIn(BuiltInOpCode::UsubBorrow, _) + | OpCode::BuiltIn(BuiltInOpCode::UmulExtended, _) + | OpCode::BuiltIn(BuiltInOpCode::ImulExtended, _) + | OpCode::BuiltIn(BuiltInOpCode::AtomicCompSwap, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageLoad, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicAdd, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicMin, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicMax, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicAnd, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicOr, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicXor, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicExchange, _) + | OpCode::BuiltIn(BuiltInOpCode::ImageAtomicCompSwap, _) => { + // TODO(http://anglebug.com/349994211): for now, assume every function call has + // a side effect. This can be optimized with a prepass going over functions + // and checking if they have side effect. AST assumes user functions have side + // effects, and mostly uses isKnownNotToHaveSideEffects for built-ins, which + // are separately checked here. Some internal transformations mark a function + // as no-side effect, but no real benefit comes from that IMO. This is + // probably fine as-is. + // + // TODO(http://anglebug.com/349994211): move the above logic (of which ops have + // side effect) to a query in OpCode or IRMeta. Later, when DCE is performed + // the same information is needed. + result_info.has_side_effect = true; + result_info.is_complex = true; + } + OpCode::AccessVectorComponent(..) + | OpCode::AccessVectorComponentMulti(..) + | OpCode::AccessVectorComponentDynamic(..) + | OpCode::AccessMatrixColumn(..) + | OpCode::AccessStructField(..) + | OpCode::AccessArrayElement(..) + | OpCode::ExtractVectorComponentDynamic(..) + | OpCode::ExtractMatrixColumn(..) + | OpCode::ExtractStructField(..) + | OpCode::ExtractArrayElement(..) + | OpCode::Load(..) => { + // Consider Access* instructions not complex and not having side effect, it's + // impossible to cache the result in the AST. + // Most Extract* instructions also don't need to be cached in a variable. + // For load, we would ideally not want to cache the result in a variable only + // to have to load from it on every use again. + } + OpCode::ExtractVectorComponent(vector_id, _) + | OpCode::ExtractVectorComponentMulti(vector_id, _) => { + // Shading languages typically don't expect swizzle applied to swizzle, so + // check to see if the value being swizzled was itself loaded from a swizzled + // pointer, in which case mark the load operation as "complex" with "multiple + // reads" so it gets cached in a temporary. + let load_id = vector_id.id.get_register(); + if let OpCode::Load(pointer_id) = state.ir_meta.get_instruction(load_id).op + && let Id::Register(pointer_id) = pointer_id.id + && matches!( + state.ir_meta.get_instruction(pointer_id).op, + OpCode::AccessVectorComponentMulti(..) + ) + { + let load_register_info = state.register_info.get_mut(&load_id).unwrap(); + // The ExtractVectorComponent* instruction has already counted as + // one read, so one more is enough. + load_register_info.read_count += 1; + debug_assert!(load_register_info.read_count > 1); + load_register_info.is_complex = true; + } + } + _ => { + // For everything else, consider the result complex so the logic is not + // duplicated. This can cover everything from a+b to texture calls + // etc. + result_info.is_complex = true; + } + }; + + // When a register does not have a side effect, it refers to a temporary expression + // that is yet to be used. For example, take `a + b`. To produce smaller more + // readable shader, the result of this temporary is not immediately cached in a + // temp variable, it may never need to be cached, for example if `a + b` is going to be + // stored in a variable right away and this register is never referenced afterwards. + // + // However, these expressions cannot stay uncached forever. Take the following example: + // + // r1 = Load global_variable + // r2 = Add r1 ... + // Call function_that_changes_global_variable + // Store local_variable r2 + // + // In the above scenario, if the load from `r1` is deferred until the expression + // corresponding to `r2` is used (in assignment to `local_variable`), the AST would + // look like this: + // + // function_that_changes_global_variable(); + // local_variable = global_variable + ...; + // + // This is incorrect because `r1` contained the value of `global_variable` _before_ the + // function call, not after. Instead, the following would be correct: + // + // temp_variable = global_variable + ...; + // function_that_changes_global_variable(); + // local_variable = temp_variable; + // + // To produce nicer AST, these side-effect-less results are not considered complex / + // with side effect initially. If the results are read from right away, the AST can + // reference the expression directly. + // + // However, if any instruction can modify a variable (i.e. Store, some + // built-ins, function calls), the result of the expression needs to be cached in a + // temporary variable if it's ever accessed afterwards. + // + // To implement this, the register is marked as being deferred here in a list, and + // later if a mutating instruction is encountered, all these registers are marked as + // needing to be cached if read from again. For simplicity, we don't track exactly + // which variables may be modified by the mutating instruction. + if !state.register_info.get(&result_id.id).unwrap().has_side_effect { + let result_type = state.ir_meta.get_type(result_id.type_id); + let can_be_cached = !matches!( + result_type, + Type::Scalar(BasicType::AtomicCounter) + | Type::Image(..) + | Type::UnsizedArray(_) + | Type::Pointer(_) + ); + if can_be_cached { + state.uncached_registers.push(result_id.id); + } + } + } + } +} + +fn preprocess_registers(state: &mut State, function_entries: &[Option]) { + traverser::visitor::for_each_function( + state, + function_entries, + |_, _| {}, + |state, block, _, _| { + preprocess_block_registers(state, block); + traverser::visitor::VISIT_SUB_BLOCKS + }, + |_, _| {}, + ); +} + +fn has_constants_with_higher_precision(operands: &[TypedId]) -> Option { + // Check if the highest precision of the constant operands is higher than the highest precision + // of the non-constant operands. In that case, any constant that has a precision higher than + // the non-constant operands must be placed in a temporary variable. + let (highest_constant_precision, highest_non_constant_precision) = operands.iter().fold( + (Precision::NotApplicable, Precision::NotApplicable), + |(constant_precision, non_constant_precision), operand| { + if operand.id.is_constant() { + ( + instruction::precision::higher_precision(constant_precision, operand.precision), + non_constant_precision, + ) + } else { + ( + constant_precision, + instruction::precision::higher_precision( + non_constant_precision, + operand.precision, + ), + ) + } + }, + ); + let highest_precision = instruction::precision::higher_precision( + highest_constant_precision, + highest_non_constant_precision, + ); + + if highest_constant_precision != Precision::NotApplicable + && highest_non_constant_precision != highest_precision + { + Some(highest_non_constant_precision) + } else { + None + } +} + +fn declare_temp_variable_if_high_precision_constant( + state: &mut State, + id: TypedId, + other_operands_precision: Precision, + transforms: &mut Vec, +) -> TypedId { + if let Id::Constant(constant_id) = id.id + && instruction::precision::higher_precision(id.precision, other_operands_precision) + != other_operands_precision + { + let variable_id = state.ir_meta.declare_variable( + Name::new_temp(""), + id.type_id, + id.precision, + Decorations::new_none(), + None, + Some(constant_id), + VariableScope::Local, + ); + transforms.push(traverser::Transform::DeclareVariable(variable_id)); + TypedId::from_variable_id(state.ir_meta, variable_id) + } else { + id + } +} + +fn declare_temp_variable_if_high_precision_constant_vec( + state: &mut State, + non_constant_precision: Precision, + params: Vec, + transforms: &mut Vec, +) -> Vec { + params + .iter() + .map(|&id| { + declare_temp_variable_if_high_precision_constant( + state, + id, + non_constant_precision, + transforms, + ) + }) + .collect() +} + +fn declare_temp_variable_for_constant_operands( + state: &mut State, + id: RegisterId, + transforms: &mut Vec, +) { + // If a constant is used in the instruction whose precision is higher than the other operands, + // a temporary variable is created to hold its value so that its precision can be retained. + // For example, if the input shader has the following: + // + // const high float a = 1.0; + // mediump float b = 2.0; + // ... = a + b; + // + // Then `a + b` is calculated as highp. The IR translates this to: + // + // Constant c1 (float) = 1.0 + // Variable v1 (float) = 2.0 [mediump] + // %result[highp] = Add c1[highp] v1 + // + // Note that the constant precision is specified in the instruction, and not the constant + // itself. If naively translated to the AST, this will generate the following GLSL: + // + // mediump float b = 2.0; + // ... = 1.0 + b; + // + // Which evaluates at mediump precision because the precision of `1.0` is derived as mediump + // (from its neighboring operand `b`). In this case, we'd need to create a temporary variable + // for `1.0`. + let instruction = state.ir_meta.get_instruction(id); + let result = instruction.result; + if result.precision == Precision::NotApplicable { + return; + } + + // Note: Only instructions with multiple operands need to be inspected, and only if the + // precision of the result could depend on the constant. This excludes for example + // `OpCode::ConstructMatrixFromMatrix` (single operand, it would have been constant folded), or + // `OpCode::Texture` (precision is derived from the sampler argument, the constant precision is + // irrelevant). Some `OpCode::Binary` and `OpCode::BuiltIn` instructions also derive their + // precision from a specific argument, but we won't be too picky here. + // + // Note: `if let` expressions below are manually implementing `map()`, but that's on purpose. + // Using `map()` leads to borrow checker errors due to the closure borrowing `state` and + // `params` at the same time. With the `if`, the borrow checker is able to accept the + // implementation due to `params.clone()`. + #[allow(clippy::manual_map)] + let new_op = match &instruction.op { + OpCode::ConstructVectorFromMultiple(params) => { + if let Some(non_constant_precision) = has_constants_with_higher_precision(params) { + Some(OpCode::ConstructVectorFromMultiple( + declare_temp_variable_if_high_precision_constant_vec( + state, + non_constant_precision, + params.clone(), + transforms, + ), + )) + } else { + None + } + } + OpCode::ConstructMatrixFromMultiple(params) => { + if let Some(non_constant_precision) = has_constants_with_higher_precision(params) { + Some(OpCode::ConstructMatrixFromMultiple( + declare_temp_variable_if_high_precision_constant_vec( + state, + non_constant_precision, + params.clone(), + transforms, + ), + )) + } else { + None + } + } + OpCode::ConstructArray(params) => { + if let Some(non_constant_precision) = has_constants_with_higher_precision(params) { + Some(OpCode::ConstructArray(declare_temp_variable_if_high_precision_constant_vec( + state, + non_constant_precision, + params.clone(), + transforms, + ))) + } else { + None + } + } + OpCode::BuiltIn(built_in_op, params) => { + if let Some(non_constant_precision) = has_constants_with_higher_precision(params) { + Some(OpCode::BuiltIn( + *built_in_op, + declare_temp_variable_if_high_precision_constant_vec( + state, + non_constant_precision, + params.clone(), + transforms, + ), + )) + } else { + None + } + } + &OpCode::Binary(binary_op, lhs, rhs) => { + if let Some(non_constant_precision) = has_constants_with_higher_precision(&[lhs, rhs]) { + let lhs = declare_temp_variable_if_high_precision_constant( + state, + lhs, + non_constant_precision, + transforms, + ); + let rhs = declare_temp_variable_if_high_precision_constant( + state, + rhs, + non_constant_precision, + transforms, + ); + Some(OpCode::Binary(binary_op, lhs, rhs)) + } else { + None + } + } + _ => None, + }; + + if let Some(new_op) = new_op { + let new_id = state.ir_meta.new_register(new_op, result.type_id, result.precision); + state.ir_meta.replace_instruction(id, new_id.id); + } +} + +fn transform_instruction( + state: &mut State, + instruction: &BlockInstruction, +) -> Vec { + // If the instruction is: + // + // - a register + // - with side effect or it's complex + // - read multiple times + // + // Then a temporary variable must be created to hold the result. For the sake of + // simplicity, any register with a side effect is placed in a temporary, because + // otherwise it's hard to tell when generating the AST if that statement should be + // placed directly in the block, or whether it's used in another expression that will + // eventually turn into a statement in the *same* block. + // + // TODO(http://anglebug.com/349994211): if the result of the expression with side effect is + // never used, for example in a common `i++`, then a variable can be eliminated if + // `has_side_effect` is `&& read_count > 0` in the `if` below, but then the read count + // information needs to be provided to `ast::Generator` so that expressions with side effect + // but also read_count == 0 could be placed in the block they are executed and their value + // discarded. + if let &BlockInstruction::Register(id) = instruction { + let info = &state.register_info[&id]; + let cache_in_variable_if_necessary = info.has_side_effect || info.is_complex; + let read_multiple_times = info.read_count > 1; + + if cache_in_variable_if_necessary && read_multiple_times || info.has_side_effect { + let instruction = state.ir_meta.get_instruction(id); + let id = instruction.result; + + // Assume the instruction is: + // + // %id = ... + // + // This is replaced with: + // + // %new_id = ... + // Store %new_variable %new_id + // %id = Load %new_variable + let variable_id = state.ir_meta.declare_variable( + Name::new_temp(""), + id.type_id, + id.precision, + Decorations::new_none(), + None, + None, + VariableScope::Local, + ); + let mut transforms = vec![traverser::Transform::DeclareVariable(variable_id)]; + + let new_register_id = state.ir_meta.assign_new_register_to_instruction(id.id); + declare_temp_variable_for_constant_operands(state, new_register_id, &mut transforms); + + // %new_id = ... + transforms + .push(traverser::Transform::Add(BlockInstruction::new_typed(new_register_id))); + + let variable_id = TypedId::from_variable_id(state.ir_meta, variable_id); + let new_register_id = + TypedId::new(Id::new_register(new_register_id), id.type_id, id.precision); + + // Store %new_variable %new_id + traverser::add_void_instruction( + &mut transforms, + instruction::make!(store, state.ir_meta, variable_id, new_register_id), + ); + // %id = Load %new_variable + traverser::add_typed_instruction( + &mut transforms, + instruction::make_with_result_id!(load, state.ir_meta, id, variable_id), + ); + + transforms + } else { + let mut transforms = vec![]; + declare_temp_variable_for_constant_operands(state, id, &mut transforms); + if !transforms.is_empty() { + // If the instruction is rewritten (i.e. variables are added), + // `declare_temp_variable_for_constant_operands` makes it use the same result id + // (as `id.id`), so just keep that in the list of instructions. + transforms.push(traverser::Transform::Keep); + } + transforms + } + } else { + vec![] + } +} + +fn replace_merge_input_with_variable<'block>( + state: &mut State, + block: &'block mut Block, +) -> &'block mut Block { + // Look at the merge block, if there is an input, it is removed and a variable is added + // to the current block instead. + if let Some(merge_block) = &mut block.merge_block + && let Some(input) = merge_block.input + { + let variable_id = state.ir_meta.declare_variable( + Name::new_temp(""), + input.type_id, + input.precision, + Decorations::new_none(), + None, + None, + VariableScope::Local, + ); + + // Add variable to the list of variables to be declared in this block. + block.variables.push(variable_id); + + // Adjust the merge block as well as blocks that can `Merge`. + let variable_id = TypedId::from_variable_id(state.ir_meta, variable_id); + replace_merge_input_with_variable_in_sub_blocks( + state, + merge_block, + &mut block.block1, + &mut block.block2, + input, + variable_id, + ); + } + + block +} + +fn replace_merge_input_with_variable_in_sub_blocks( + state: &mut State, + merge_block: &mut Box, + block1: &mut Option>, + block2: &mut Option>, + input_id: TypedRegisterId, + variable_id: TypedId, +) { + // Remove the merge block input and replace it with: + // + // %input_id = Load %variable_id + merge_block.prepend_instruction(instruction::make_with_result_id!( + load, + state.ir_meta, + input_id, + variable_id + )); + merge_block.input = None; + + // Remove the Merge(%value) from the end of each sub-block, and replace it with: + // + // Store %variable_id %value + // Merge + replace_merge_terminator_with_variable_store(state, block1, variable_id); + replace_merge_terminator_with_variable_store(state, block2, variable_id); +} + +fn replace_merge_terminator_with_variable_store( + state: &mut State, + block: &mut Option>, + variable_id: TypedId, +) { + if let Some(block) = block { + let block = block.get_merge_chain_last_block_mut(); + let merge_id = block.get_terminating_op().get_merge_parameter().unwrap(); + block.unterminate(); + + // Store %variable_id %value + block.add_instruction(instruction::make!(store, state.ir_meta, variable_id, merge_id)); + // Merge + block.terminate(OpCode::Merge(None)); + } +} + +fn transform_continue_instructions_pre_visit<'block>( + state: &mut State, + block: &'block mut Block, +) -> &'block mut Block { + // Transformation 1: + // + // When a loop is encountered that has a continue block, that block is removed and + // instead replicated before every `Continue` branch in the sub-blocks (that correspond + // to this loop, and not a nested loop). This is implemented by visiting the blocks + // in the following way: + // + // - When a block terminating with `Loop` or `DoLoop` is visited, check if there is a continue + // block. If so, remove it and push to `continue_stack`. Otherwise push a None to + // `continue_stack`. Loop and DoLoop are the only constructs that can be the target of a + // `continue` instruction, and the above enables matching continue blocks to their + // corresponding loops. + // - When a block terminating with `Continue` is visited, replicate the block at the top of the + // stack, if any, and place it after this block. Note that the continue block already + // terminates with `Continue`, and it is sufficient to change the terminating branch of this + // block to `NextBlock` and setting the replicated continue block as the merge block. + // - After the `Loop` and `DoLoop` blocks are visited, pop the corresponding entry from + // `continue_stack`. + + // Transformation 2: + // + // When a do-loop is encountered, the condition block is removed, its `LoopIf + // %condition` is changed to `if (!condition) break;`, and is replicated before every + // `Continue` branch in the sub-blocks (that correspond to this loop). This is + // implemented as follows: + // + // - When a block terminating with `Loop`, `DoLoop` or `Switch` is visited, add an entry to + // `break_stack` to know which construct a nested `Break` would affect. + // - When a block terminating with `Loop` is visited, add `None` to `condition_stack` just to + // indicate that `continue` applies to `Loop`, and not a `DoLoop`. + // - When a block terminating with `DoLoop` is visited, take the condition block and place it in + // `condition_stack`. + // - When a block terminating with `Continue` is visited and there is a block at the top of the + // `condition_stack` : + // - Inspect the top elements of `break_stack`, and add a variable (if not already) to all + // that are of `switch` type. + // - Replicate the condition block, and place it after this block. The condition block is + // transformed such that instead of `LoopIf %condition`, it terminates with an `if + // (!condition) { /* set all relevant switch vars to true */ break; }` followed by a + // `Continue` branch. + // - Change the terminating branch of this block to `NextBlock` and set the replicated + // condition block as the merge block. + // - After the `Switch` block is visited, check if a new variable was added while visiting the + // sub-blocks. If so, add an `if (propagate_break) break;` in a block after the switch. + // - After the `Loop`, `DoLoop` and `Switch` blocks are visited, pop the corresponding entries + // from `break_stack` and `condition_stack`. + // + // Note that the conditions for the two transformations are mutually exclusive (one + // affects `for` loops, i.e. `Loop`, and the other do-whiles, i.e. `DoLoop`), which is + // why they can be easily implemented in one pass. + let mut current_block = block; + + let op = current_block.get_terminating_op(); + match op { + OpCode::Loop => transform_continue_pre_visit_loop(state, current_block), + OpCode::DoLoop => transform_continue_pre_visit_do_loop(state, current_block), + OpCode::Switch(..) => transform_continue_pre_visit_switch(state, current_block), + OpCode::Continue => { + current_block = transform_continue_visit_continue(state, current_block); + } + _ => (), + }; + current_block +} + +fn transform_continue_pre_visit_loop(state: &mut State, block: &mut Block) { + // Transformation 1: Take the loop continue block and push in `continue_stack`. + let continue_block = block.block2.take().map(|block| *block); + state.continue_stack.push(continue_block); + + // Transformation 2: Add an entry to `break_stack` + state.break_stack.push(BreakInfo::new_loop()); + // Transformation 2: Add an entry to `condition_stack` + state.condition_stack.push(None); +} + +fn transform_continue_pre_visit_do_loop(state: &mut State, block: &mut Block) { + // Transformation 1: Add an entry to `continue_stack` + debug_assert!(block.block2.is_none()); + state.continue_stack.push(None); + + // Transformation 2: Add an entry to `break_stack` + state.break_stack.push(BreakInfo::new_loop()); + // Transformation 2: Take the do-loop condition block and push in `condition_stack`. + let condition_block = block.loop_condition.take().map(|block| *block); + state.condition_stack.push(condition_block); +} + +fn transform_continue_pre_visit_switch(state: &mut State, _block: &mut Block) { + // Transformation 2: Add an entry to `break_stack` + state.break_stack.push(BreakInfo::new_switch()); +} + +fn transform_continue_visit_continue<'block>( + state: &mut State, + block: &'block mut Block, +) -> &'block mut Block { + let continue_block = state.continue_stack.last().unwrap().as_ref(); + let condition_block = state.condition_stack.last().unwrap().as_ref(); + + let block_to_append = if let Some(continue_block) = continue_block { + // Transformation 1: If there is a continue block at the top of the stack, the + // `continue` corresponds to a GLSL `for` loop. Replicate that before the + // `Continue` instruction. + util::duplicate_block(state.ir_meta, &mut HashMap::new(), continue_block) + } else if let Some(condition_block) = condition_block { + // Transformation 2: If there is a condition block at the top of the stack, the + // `continue` corresponds to a GLSL `do-while` loop. Add helper variables to + // enclosing switches, if any, replicate the condition block and transform it to be + // placed before this particular `continue`. + let mut duplicate = + util::duplicate_block(state.ir_meta, &mut HashMap::new(), condition_block); + + let variables_to_set = transform_continue_add_variable_to_enclosing_switch_blocks(state); + transform_continue_adjust_condition_block(state, &mut duplicate, variables_to_set); + + duplicate + } else { + return block; + }; + + block.unterminate(); + block.terminate(OpCode::NextBlock); + block.set_merge_block(block_to_append); + block.get_merge_chain_last_block_mut() +} + +fn transform_continue_add_variable_to_enclosing_switch_blocks( + state: &mut State, +) -> Vec { + let mut variables_to_set = Vec::new(); + + // For each enclosing `switch` block for this `continue` instruction, add a + // `propagate_break` variable to be used to jump out of the switch blocks and continue + // the loop. + for scope in state.break_stack.iter_mut().rev() { + if !scope.is_switch { + break; + } + + let variable_id = match scope.propagate_break_var { + Some(variable_id) => variable_id, + None => { + let variable_id = state.ir_meta.declare_variable( + Name::new_temp("propagate_break"), + TYPE_ID_BOOL, + Precision::NotApplicable, + Decorations::new_none(), + None, + Some(CONSTANT_ID_FALSE), + VariableScope::Local, + ); + scope.propagate_break_var = Some(variable_id); + variable_id + } + }; + variables_to_set.push(variable_id); + } + + variables_to_set +} + +fn transform_continue_adjust_condition_block( + state: &mut State, + block: &mut Block, + variables_to_set: Vec, +) { + let block = block.get_merge_chain_last_block_mut(); + + // Since this is the condition block of a do-while loop, it must terminate with a + // `LoopIf`. Take the condition out of it. + let condition = block.get_terminating_op().get_loop_condition(); + block.unterminate(); + + // Create another block that only contains the `Continue` branch, and set it as the + // merge block of the original block. + let mut continue_block = Block::new(); + continue_block.terminate(OpCode::Continue); + block.set_merge_block(continue_block); + + // Create a block that sets the given variables all to true, and ends in `Break`. + let mut break_block = Block::new(); + let constant_true = TypedId::from_constant_id(CONSTANT_ID_TRUE, TYPE_ID_BOOL); + for variable_id in variables_to_set { + let variable_id = TypedId::from_bool_variable_id(variable_id); + break_block.add_void_instruction(OpCode::Store(variable_id, constant_true)); + } + break_block.terminate(OpCode::Break); + + // Terminate the current block with an `If` of the logical not of the condition, where + // the true block is `break_block`. + let not_instruction = instruction::make!(logical_not, state.ir_meta, condition); + let not_condition = block.add_typed_instruction(not_instruction); + block.terminate(OpCode::If(not_condition)); + block.set_if_true_block(break_block); +} + +fn transform_continue_instructions_post_visit<'block>( + state: &mut State, + block: &'block mut Block, +) -> &'block mut Block { + let mut current_block = block; + + let op = current_block.get_terminating_op(); + match op { + OpCode::Loop | OpCode::DoLoop => transform_continue_post_visit_loop(state, current_block), + OpCode::Switch(..) => { + current_block = transform_continue_post_visit_switch(state, current_block); + } + _ => (), + }; + current_block +} + +fn transform_continue_post_visit_loop(state: &mut State, _block: &mut Block) { + // Pop the corresponding entries from the stacks + state.continue_stack.pop(); + state.break_stack.pop(); + state.condition_stack.pop(); +} + +fn transform_continue_post_visit_switch<'block>( + state: &mut State, + block: &'block mut Block, +) -> &'block mut Block { + // Pop from `break_stack` only. + let break_info = state.break_stack.pop().unwrap(); + + // Check if a new variable was supposed to be added to the block. If so, declare it, + // and add an `if (propagate_break) break;` to the block. + if let Some(variable_id) = break_info.propagate_break_var { + block.variables.push(variable_id); + + // A block that only has `Break`. + let mut break_block = Block::new(); + break_block.terminate(OpCode::Break); + + // A block that contains: + // + // %value = Load %variable + // If %value + let mut propagate_break_block = Block::new(); + let load_instruction = + instruction::make!(load, state.ir_meta, TypedId::from_bool_variable_id(variable_id)); + let load_value = propagate_break_block.add_typed_instruction(load_instruction); + propagate_break_block.terminate(OpCode::If(load_value)); + propagate_break_block.set_if_true_block(break_block); + + // Insert the new block after the one containing `Switch` (i.e. `block`) in the + // merge chain. This function's return value ensures that the newly added block is + // not revisited. + block.insert_into_merge_chain(propagate_break_block) + } else { + block + } +} diff --git a/src/compiler/translator/ir/src/transform/dealias.rs b/src/compiler/translator/ir/src/transform/dealias.rs new file mode 100644 index 00000000000..b5a05393354 --- /dev/null +++ b/src/compiler/translator/ir/src/transform/dealias.rs @@ -0,0 +1,149 @@ +// 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. +// +// Remove Alias instructions from the IR. Instructions in the form `%new = Alias %original` +// are removed and `%original.id` is made to replace every instance of `%new.id`. The types +// are identical and untouched, and the precision of `%new` is retained. +use crate::ir::*; +use crate::*; + +struct State<'a> { + ir_meta: &'a mut IRMeta, + alias_map: HashMap, +} + +pub fn run(ir: &mut IR) { + let mut state = State { ir_meta: &mut ir.meta, alias_map: HashMap::new() }; + + traverser::transformer::for_each_function( + &mut state, + &mut ir.function_entries, + &|state, _, entry| { + traverser::transformer::for_each_block( + state, + entry, + &|state, block| dealias_registers(state, block), + &|_, block| block, + ) + }, + ); +} + +fn dealias_registers<'block>(state: &mut State, block: &'block mut Block) -> &'block mut Block { + let instructions = std::mem::take(&mut block.instructions); + let mut transformed = Vec::with_capacity(instructions.len()); + + for mut instruction in instructions.into_iter() { + let (opcode, result) = match &mut instruction { + BlockInstruction::Void(op) => (op, None), + &mut BlockInstruction::Register(id) => { + (&mut state.ir_meta.get_instruction_mut(id).op, Some(id)) + } + }; + + match opcode { + OpCode::MergeInput + | OpCode::Discard + | OpCode::Break + | OpCode::Continue + | OpCode::Passthrough + | OpCode::NextBlock + | OpCode::Loop + | OpCode::DoLoop + | OpCode::Return(None) + | OpCode::Merge(None) => (), + OpCode::Call(_, params) + | OpCode::ConstructVectorFromMultiple(params) + | OpCode::ConstructMatrixFromMultiple(params) + | OpCode::ConstructStruct(params) + | OpCode::ConstructArray(params) + | OpCode::BuiltIn(_, params) => { + for param in params { + param.dealias(&state.alias_map); + } + } + OpCode::Return(Some(id)) + | OpCode::Merge(Some(id)) + | OpCode::If(id) + | OpCode::LoopIf(id) + | OpCode::Switch(id, _) + | OpCode::ExtractVectorComponent(id, _) + | OpCode::ExtractVectorComponentMulti(id, _) + | OpCode::ExtractStructField(id, _) + | OpCode::ConstructScalarFromScalar(id) + | OpCode::ConstructVectorFromScalar(id) + | OpCode::ConstructMatrixFromScalar(id) + | OpCode::ConstructMatrixFromMatrix(id) + | OpCode::AccessVectorComponent(id, _) + | OpCode::AccessVectorComponentMulti(id, _) + | OpCode::AccessStructField(id, _) + | OpCode::Load(id) + | OpCode::Unary(_, id) => id.dealias(&state.alias_map), + OpCode::ExtractVectorComponentDynamic(lhs, rhs) + | OpCode::ExtractMatrixColumn(lhs, rhs) + | OpCode::ExtractArrayElement(lhs, rhs) + | OpCode::AccessVectorComponentDynamic(lhs, rhs) + | OpCode::AccessMatrixColumn(lhs, rhs) + | OpCode::AccessArrayElement(lhs, rhs) + | OpCode::Store(lhs, rhs) + | OpCode::Binary(_, lhs, rhs) => { + lhs.dealias(&state.alias_map); + rhs.dealias(&state.alias_map); + } + OpCode::Texture(texture_op, sampler, coord) => { + sampler.dealias(&state.alias_map); + coord.dealias(&state.alias_map); + match texture_op { + TextureOpCode::Implicit { is_proj: _, offset } + | TextureOpCode::Gather { offset } => { + offset.as_mut().map(|id| id.dealias(&state.alias_map)); + } + TextureOpCode::Compare { compare } => { + compare.dealias(&state.alias_map); + } + TextureOpCode::Lod { is_proj: _, lod, offset } => { + lod.dealias(&state.alias_map); + offset.as_mut().map(|id| id.dealias(&state.alias_map)); + } + TextureOpCode::CompareLod { compare, lod } => { + compare.dealias(&state.alias_map); + lod.dealias(&state.alias_map); + } + TextureOpCode::Bias { is_proj: _, bias, offset } => { + bias.dealias(&state.alias_map); + offset.as_mut().map(|id| id.dealias(&state.alias_map)); + } + TextureOpCode::CompareBias { compare, bias } => { + compare.dealias(&state.alias_map); + bias.dealias(&state.alias_map); + } + TextureOpCode::Grad { is_proj: _, dx, dy, offset } => { + dx.dealias(&state.alias_map); + dy.dealias(&state.alias_map); + offset.as_mut().map(|id| id.dealias(&state.alias_map)); + } + TextureOpCode::GatherComponent { component, offset } => { + component.dealias(&state.alias_map); + offset.as_mut().map(|id| id.dealias(&state.alias_map)); + } + TextureOpCode::GatherRef { refz, offset } => { + refz.dealias(&state.alias_map); + offset.as_mut().map(|id| id.dealias(&state.alias_map)); + } + } + } + OpCode::Alias(_) => { + let register_id = result.unwrap(); + state.alias_map.insert(register_id, state.ir_meta.get_aliased_id(register_id).id); + continue; + } + }; + + transformed.push(instruction); + } + + block.instructions = transformed; + + block +} diff --git a/src/compiler/translator/ir/src/transform/initialize_uninitialized_variables.rs b/src/compiler/translator/ir/src/transform/initialize_uninitialized_variables.rs new file mode 100644 index 00000000000..aaedd6c74df --- /dev/null +++ b/src/compiler/translator/ir/src/transform/initialize_uninitialized_variables.rs @@ -0,0 +1,328 @@ +// Copyright 2025 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. +// +// Initialize uninitialized variables based on a set of flags: +// +// - If required, all local, global and function parameter variables that were not initialized +// during parse are zero-initialized. +// - If required, all shader output variables, or just fragment shader output variables are +// zero-initialized. +// - If required, gl_Position is zero-initialized +// +// Either way, zero initialization may either be done via an initializer or assignment +// instructions. If the variable being initialized via instructions is a global variable, it is +// initialized at the beginning of main, otherwise it is initialized at the beginning of the block +// that defines it. Based on flags, a loop may or may not be used to initialize an array. +use crate::ir::*; +use crate::*; + +pub struct Options { + pub loops_allowed_when_initializing_variables: bool, + pub initializer_allowed_on_non_constant_global_variables: bool, +} + +struct State<'a> { + ir_meta: &'a mut IRMeta, +} + +pub fn run(ir: &mut IR, options: &Options) { + let mut state = State { ir_meta: &mut ir.meta }; + + traverser::transformer::for_each_function( + &mut state, + &mut ir.function_entries, + &|state, function_id, entry| { + // Initialize function parameters that need initialization. + { + let function = state.ir_meta.get_function(function_id); + let to_initialize = function + .params + .iter() + .filter_map(|param| { + state + .ir_meta + .variable_needs_zero_initialization(param.variable_id) + .then_some(param.variable_id) + }) + .collect::>(); + make_init_block(state.ir_meta, to_initialize, entry, options); + } + + traverser::transformer::for_each_block( + state, + entry, + &|state, block| { + let to_initialize = block + .variables + .iter() + .filter(|&variable_id| { + state.ir_meta.variable_needs_zero_initialization(*variable_id) + }) + .copied() + .collect::>(); + make_init_block(state.ir_meta, to_initialize, block, options); + block + }, + &|_, block| block, + ) + }, + ); + + // Do the same for global variables + { + let to_initialize = state + .ir_meta + .all_global_variables() + .iter() + .filter(|&variable_id| state.ir_meta.variable_needs_zero_initialization(*variable_id)) + .copied() + .collect::>(); + let main_id = state.ir_meta.get_main_function_id().unwrap(); + let main_entry = ir.function_entries[main_id.id as usize].as_mut().unwrap(); + make_init_block(state.ir_meta, to_initialize, main_entry, options); + } +} + +fn is_initializer_allowed( + ir_meta: &IRMeta, + id: VariableId, + decorations: &Decorations, + built_in: Option, + options: &Options, +) -> bool { + // If the initializer value is a constant, it can be set as the initializer. However, that + // is disallowed in the following case: + // + // * initializer_allowed_on_non_constant_global_variables is false + // * It's the global scope + // * The variable is not `const`. + // + // Additionally, function parameters cannot have an initializer, neither can built-ins and + // interface variables. + let variable = ir_meta.get_variable(id); + variable.scope != VariableScope::FunctionParam + && built_in.is_none() + && decorations.decorations.is_empty() + && (variable.scope == VariableScope::Local + || options.initializer_allowed_on_non_constant_global_variables + || variable.is_const) +} + +fn initialize_with_zeros<'block>( + ir_meta: &mut IRMeta, + mut block: &'block mut Block, + id: TypedId, + allow_loops: bool, +) -> &'block mut Block { + let type_info = ir_meta.get_type(id.type_id); + debug_assert!(type_info.is_pointer()); + let type_id = type_info.get_element_type_id().unwrap(); + let type_info = ir_meta.get_type(type_id); + + match *type_info { + Type::Struct(_, ref fields, _) => { + // For structs, initialize field by field. + for index in 0..fields.len() { + // selected_field = AccessStructField id index + let selected_field = block.add_typed_instruction(instruction::struct_field( + ir_meta, + id, + index as u32, + )); + // Recursively set the field to zeros. + block = initialize_with_zeros(ir_meta, block, selected_field, allow_loops); + } + } + Type::Array(element_id, count) => { + // For arrays, initialize element by element, either with a loop or unrolled. + let element_type_info = ir_meta.get_type(element_id); + let is_small_array = count <= 1 + || (!element_type_info.is_struct() && !element_type_info.is_array() && count <= 3); + let use_loop = allow_loops && !is_small_array; + if use_loop { + // Note: `uint` would be a better loop index type, but ESSL 100 doesn't support + // that. + let count_constant = + TypedId::from_constant_id(ir_meta.get_constant_int(count as i32), TYPE_ID_INT); + + // Loop variable, int index = 0: + let loop_index_id = ir_meta.declare_variable( + Name::new_temp(""), + TYPE_ID_INT, + Precision::High, + Decorations::new_none(), + None, + Some(CONSTANT_ID_INT_ZERO), + VariableScope::Local, + ); + block.add_variable_declaration(loop_index_id); + let loop_index_id = TypedId::from_variable_id(ir_meta, loop_index_id); + + // Add the loop condition, index < count: + { + let mut condition_block = Block::new(); + // loaded_index = Load loop_index_id + let loaded_index = condition_block + .add_typed_instruction(instruction::load(ir_meta, loop_index_id)); + // compare_with_count = LessThan loop_index_id count + let compare_with_count = condition_block.add_typed_instruction( + instruction::less_than(ir_meta, loaded_index, count_constant), + ); + condition_block.terminate(OpCode::LoopIf(compare_with_count)); + block.set_loop_condition_block(condition_block); + } + + // Add the loop continue block, ++index: + { + let mut continue_block = Block::new(); + continue_block.add_typed_instruction(instruction::prefix_increment( + ir_meta, + loop_index_id, + )); + + continue_block.terminate(OpCode::Continue); + block.set_loop_continue_block(continue_block); + } + + // Add the loop body, recursively initialize id[index] + { + let mut body_block = Block::new(); + // loaded_index = Load loop_index_id + let loaded_index = + body_block.add_typed_instruction(instruction::load(ir_meta, loop_index_id)); + // selected_element = AccessArrayElement id index + let selected_element = body_block.add_typed_instruction(instruction::index( + ir_meta, + id, + loaded_index, + )); + // Recursively set the element to zeros. + let body_last_block = initialize_with_zeros( + ir_meta, + &mut body_block, + selected_element, + allow_loops, + ); + + body_last_block.terminate(OpCode::Continue); + block.set_loop_body_block(body_block); + } + + let next_block = Block::new(); + block.terminate(OpCode::Loop); + block.set_merge_block(next_block); + block = block.get_merge_chain_last_block_mut(); + } else { + // Note that it is important to have the array init in the right order to + // workaround a driver bug per http://crbug.com/40514481. + for index in 0..count { + let index_constant = TypedId::from_constant_id( + ir_meta.get_constant_int(index as i32), + TYPE_ID_INT, + ); + // selected_element = AccessArrayElement id index + let selected_element = block.add_typed_instruction(instruction::index( + ir_meta, + id, + index_constant, + )); + // Recursively set the element to zeros. + block = initialize_with_zeros(ir_meta, block, selected_element, allow_loops); + } + } + } + _ => { + // For scalars, vectors and matrices, use a zero constant which is not very big. + let null_value = TypedId::from_constant_id(ir_meta.get_constant_null(type_id), type_id); + block.add_void_instruction(OpCode::Store(id, null_value)); + } + } + + block +} + +fn make_init_block( + ir_meta: &mut IRMeta, + to_initialize: Vec, + target_block: &mut Block, + options: &Options, +) { + if to_initialize.is_empty() { + return; + } + + // Create a block to initialize the variables + let mut init_block = Block::new(); + let mut current_block = &mut init_block; + let mut any_code_generated = false; + + for &id in to_initialize.iter() { + let variable = ir_meta.get_variable(id); + debug_assert!(variable.initializer.is_none()); + + let type_info = ir_meta.get_type(variable.type_id); + debug_assert!(type_info.is_pointer()); + let type_id = type_info.get_element_type_id().unwrap(); + let type_info = ir_meta.get_type(type_id); + + debug_assert!( + !type_info.is_image() + && !type_info.is_unsized_array() + && !variable.decorations.has(Decoration::Input) + && !variable.decorations.has(Decoration::InputOutput) + && !variable.decorations.has(Decoration::Uniform) + && !variable.decorations.has(Decoration::Buffer) + && !variable.decorations.has(Decoration::Shared) + ); + + // If using an initializer is allowed and the type is simple, create a zero initializer and + // set it as the initializer for the variable. + let is_initializer_allowed = + is_initializer_allowed(ir_meta, id, &variable.decorations, variable.built_in, options); + let is_fragment_output_array = matches!(variable.built_in, Some(BuiltIn::FragData)) + || (ir_meta.get_shader_type() == ShaderType::Fragment + && variable.decorations.has(Decoration::Output)); + + // TODO(http://anglebug.com/349994211): Eventually it's best for SPIR-V if + // initialize_with_value is always used because it can use OpConstantNull as the + // initializer. This can be done when SPIR-V generation is done from IR, at which point + // it's likely best not to initialize variables here so a possibly giant constant is not + // generated in the IR only to be replaced by OpConstantNull, and zero-init variables + // directly while generating SPIR-V. + if is_initializer_allowed + && (type_info.is_scalar() || type_info.is_vector() || type_info.is_matrix()) + { + let null_value = ir_meta.get_constant_null(type_id); + ir_meta.set_variable_initializer(id, null_value); + } else { + let variable = TypedId::from_variable_id(ir_meta, id); + // For gl_FragData, the array elements are assigned one by one to keep the AST + // compatible with ESSL 1.00 which doesn't have array assignment. + current_block = initialize_with_zeros( + ir_meta, + current_block, + variable, + options.loops_allowed_when_initializing_variables && !is_fragment_output_array, + ); + ir_meta.on_variable_zero_initialization_done(id); + any_code_generated = true; + } + } + + // Make sure the init block is prepended to the block that is expected to initialize the + // variables. + if any_code_generated { + // Because the init_block may reference variables that are declared in target_block, the + // declaration of those variables need to be moved to init_block. This is only needed when + // initialization function-local variables. + let (mut to_move, to_keep): (Vec<_>, Vec<_>) = target_block + .variables + .iter() + .partition(|variable_id| to_initialize.contains(variable_id)); + target_block.variables = to_keep; + init_block.variables.append(&mut to_move); + + target_block.prepend_code(init_block); + } +} diff --git a/src/compiler/translator/ir/src/transform/propagate_precision.rs b/src/compiler/translator/ir/src/transform/propagate_precision.rs new file mode 100644 index 00000000000..aaaecc4f1f1 --- /dev/null +++ b/src/compiler/translator/ir/src/transform/propagate_precision.rs @@ -0,0 +1,217 @@ +// Copyright 2025 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. +// +// Walk over the IR and propagate precision to constants and constant-derived registers which don't +// get a precision assigned to them during parse. +use crate::ir::*; +use crate::*; + +struct State<'a> { + ir_meta: &'a mut IRMeta, + current_function_return_precision: Precision, + // Used to propagate newly-assigned register precisions to their instructions. + updated_precisions: HashMap, + // Used to propagate precision to function call arguments + function_arg_precisions: HashMap>, + // Used to propagate precision to struct constructor arguments + struct_member_precisions: HashMap>, +} + +pub fn run(ir: &mut IR) { + let mut state = State { + ir_meta: &mut ir.meta, + current_function_return_precision: Precision::NotApplicable, + updated_precisions: HashMap::new(), + function_arg_precisions: HashMap::new(), + struct_member_precisions: HashMap::new(), + }; + + // Prepare a map of functions to the precision of their arguments. + traverser::visitor::for_each_function( + &mut state, + &ir.function_entries, + |state, function_id| { + let argument_precision = state + .ir_meta + .get_function(function_id) + .params + .iter() + .map(|param| state.ir_meta.get_variable(param.variable_id).precision) + .collect(); + state.function_arg_precisions.insert(function_id, argument_precision); + }, + |_, _, _, _| traverser::visitor::STOP, + |_, _| {}, + ); + + // Prepare a map of structs to the precision of their members. + state.ir_meta.all_types().iter().enumerate().for_each(|(index, type_info)| { + if let Type::Struct(_, fields, _) = type_info { + let member_precision = fields.iter().map(|field| field.precision).collect(); + state.struct_member_precisions.insert(TypeId { id: index as u32 }, member_precision); + } + }); + + traverser::transformer::for_each_function( + &mut state, + &mut ir.function_entries, + &|state, function_id, entry| { + state.current_function_return_precision = + state.ir_meta.get_function(function_id).return_precision; + propagate_precision_in_block(state, entry, Precision::NotApplicable); + }, + ); +} + +fn propagate_precision_in_block( + state: &mut State, + block: &mut Block, + merge_block_input_precision: Precision, +) { + // Propagate precision in the current block first + + // Propagate precision in the merge block before the sub-blocks of this block. This is so that + // if the merge input of the merge block gets a precision, we can propagate it to the Merge() + // instructions of the sub-blocks without having to revisit them twice. + + if let Some(merge_block) = block.merge_block.as_mut() { + propagate_precision_in_block(state, merge_block, merge_block_input_precision); + } + + propagate_precision_in_instructions(state, block, merge_block_input_precision); + + // Because the merge blocks are visited already, we know what the merge block input precision + // is going to be (if updated). + let this_block_merge_input_precision = block + .merge_block + .as_ref() + .map(|merge_block| { + merge_block.input.map(|id| id.precision).unwrap_or(Precision::NotApplicable) + }) + .unwrap_or(Precision::NotApplicable); + + block.for_each_sub_block_mut(state, &|state, sub_block| { + propagate_precision_in_block(state, sub_block, this_block_merge_input_precision) + }); + + // At the end, if the merge input has gotten a precision, update it. + if let Some(id) = block.input.as_mut() { + if let Some(&precision) = state.updated_precisions.get(&id.id) { + // See comment above, it's unexpected for this register to have been used + // multiple times if it didn't have a precision (and so was derived from + // non-variable constants). + debug_assert!(id.precision == Precision::NotApplicable); + id.precision = precision; + } else if id.precision == Precision::NotApplicable + && util::is_precision_applicable_to_type(state.ir_meta, id.type_id) + { + // If precision is applicable but could not be derived above, then it's impossible to + // derive a precision for the merge input. Just assign highp to it. + // For example, in: + // + // (u ? constant0 : constant1) < constant2 + // + // The result is a boolean, the condition is boolean, and all arguments are constant. + // The merge input for the ternary expression will not get a precision in that case + // with the logic above. + let instruction = state.ir_meta.get_instruction_mut(id.id); + instruction.result.precision = Precision::High; + id.precision = Precision::High; + } + } +} + +fn propagate_precision_in_instructions( + state: &mut State, + block: &mut Block, + merge_block_input_precision: Precision, +) { + for instruction in block.instructions.iter_mut() { + // To propagate precision, there are two steps. First, the precision of the operands need + // to be determined; this is typically the same as the result precision, but some built-ins + // impose specific precision requirements on their arguments. Next, the precision is + // propagated to those operands that don't already have one (which is only the case for + // constants, merge inputs that have only received constants, and any op that only uses + // those as operands). + let mut new_ids_to_update = vec![]; + match instruction { + BlockInstruction::Register(id) => { + let instruction = state.ir_meta.get_instruction_mut(*id); + instruction::precision::propagate( + instruction, + &state.function_arg_precisions, + &state.struct_member_precisions, + &mut new_ids_to_update, + ); + } + BlockInstruction::Void(OpCode::Merge(Some(id))) => { + instruction::precision::propagate_to_id( + id, + merge_block_input_precision, + &mut new_ids_to_update, + ); + } + BlockInstruction::Void(OpCode::Return(Some(id))) => { + instruction::precision::propagate_to_id( + id, + state.current_function_return_precision, + &mut new_ids_to_update, + ); + } + BlockInstruction::Void(OpCode::Store(pointer, value)) => { + instruction::precision::propagate_to_id( + value, + pointer.precision, + &mut new_ids_to_update, + ); + } + BlockInstruction::Void(OpCode::BuiltIn( + BuiltInOpCode::PixelLocalStoreANGLE, + params, + )) => { + let precision = params[0].precision; + instruction::precision::propagate_to_id( + &mut params[1], + precision, + &mut new_ids_to_update, + ); + } + BlockInstruction::Void(OpCode::BuiltIn(BuiltInOpCode::ImageStore, params)) => { + let precision = params[0].precision; + instruction::precision::propagate_to_ids( + &mut params.iter_mut(), + precision, + &mut new_ids_to_update, + ); + } + _ => {} + }; + + while let Some((id, precision)) = new_ids_to_update.pop() { + let type_id = state.ir_meta.get_instruction(id).result.type_id; + if !util::is_precision_applicable_to_type(state.ir_meta, type_id) { + continue; + } + + state.updated_precisions.insert(id, precision); + + let instruction = state.ir_meta.get_instruction_mut(id); + // Note: It should never be possible to assign precision to the same register twice + // during parse, because the registers that don't have a precision but should are + // derived purely from constants (not const variables) and so cannot have been used + // multiple times in different expressions. + // + // Post-parse transformations should not leave precision undefined. + debug_assert!(instruction.result.precision == Precision::NotApplicable); + instruction.result.precision = precision; + // Propagate precision to the operands if needed + instruction::precision::propagate( + instruction, + &state.function_arg_precisions, + &state.struct_member_precisions, + &mut new_ids_to_update, + ); + } + } +} diff --git a/src/compiler/translator/ir/src/transform/prune_unused_variables.rs b/src/compiler/translator/ir/src/transform/prune_unused_variables.rs new file mode 100644 index 00000000000..1a9e310d171 --- /dev/null +++ b/src/compiler/translator/ir/src/transform/prune_unused_variables.rs @@ -0,0 +1,306 @@ +// Copyright 2025 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. +// +// Remove unreferenced variables from the IR. During traversal, additionally unreferenced +// constants and types are tracked and marked as dead-code-eliminated. +// +// Eventually this transformation should be replaced with a more comprehensive +// dead-code-elimination algorithm. +use crate::ir::*; +use crate::*; + +#[cfg_attr(debug_assertions, derive(Debug))] +struct Referenced { + pub variables: Vec, + pub constants: Vec, + pub types: Vec, +} + +struct State<'a> { + ir_meta: &'a mut IRMeta, + referenced: Referenced, +} + +pub fn run(ir: &mut IR) { + let referenced_variables = vec![false; ir.meta.all_variables().len()]; + let referenced_constants = vec![false; ir.meta.all_constants().len()]; + let referenced_types = vec![false; ir.meta.all_types().len()]; + + let mut state = State { + ir_meta: &mut ir.meta, + referenced: Referenced { + variables: referenced_variables, + constants: referenced_constants, + types: referenced_types, + }, + }; + + // Don't prune interface variables, as reflection info is not yet gathered. + // TODO(http://anglebug.com/349994211): Once reflection info is collected before this step, + // removing the following loop would let inactive variables be pruned. + for &variable_id in state.ir_meta.all_global_variables() { + let variable = state.ir_meta.get_variable(variable_id); + if !variable.decorations.decorations.is_empty() || variable.built_in.is_some() { + state.referenced.variables[variable_id.id as usize] = true; + } + } + + // Visit all instructions and mark types, constants and variables that are visited. + traverser::visitor::for_each_function( + &mut state, + &ir.function_entries, + |state, function_id| { + state + .ir_meta + .get_function(function_id) + .params + .iter() + .for_each(|param| state.referenced.variables[param.variable_id.id as usize] = true); + }, + |state, block, _, _| { + visit_block(state, block); + traverser::visitor::VISIT_SUB_BLOCKS + }, + |_, _| {}, + ); + + // Remove unreferenced variables from blocks. + traverser::transformer::for_each_function( + &mut state, + &mut ir.function_entries, + &|state, _, entry| { + traverser::transformer::for_each_block( + state, + entry, + &|state, block| { + // Prune local variables to exclude unreferenced variables. + block + .variables + .retain(|variable_id| state.referenced.variables[variable_id.id as usize]); + block + }, + &|_, block| block, + ) + }, + ); + // Prune unreferenced global variables too. + state + .ir_meta + .prune_global_variables(|variable_id| state.referenced.variables[variable_id.id as usize]); + + // Mark constants and types that are used outside instructions as referenced. + mark_referenced_variable_types_and_initializers(state.ir_meta, &mut state.referenced); + mark_referenced_constant_components(state.ir_meta, &mut state.referenced.constants); + mark_referenced_type_components(state.ir_meta, &mut state.referenced.types); + + // Mark the variables, types and constants that are no longer referenced as + // dead-code-eliminated. + state.referenced.variables.iter().enumerate().for_each(|(id, is_referenced)| { + if !is_referenced { + state.ir_meta.dead_code_eliminate_variable(VariableId { id: id as u32 }); + } + }); + state.referenced.constants.iter().enumerate().for_each(|(id, is_referenced)| { + if !is_referenced { + state.ir_meta.dead_code_eliminate_constant(ConstantId { id: id as u32 }); + } + }); + state.referenced.types.iter().enumerate().for_each(|(id, is_referenced)| { + if !is_referenced { + state.ir_meta.dead_code_eliminate_type(TypeId { id: id as u32 }); + } + }); +} + +fn record_reference(referenced: &mut Referenced, id: TypedId) { + referenced.types[id.type_id.id as usize] = true; + match id.id { + Id::Register(_) => {} + Id::Constant(constant_id) => { + referenced.constants[constant_id.id as usize] = true; + } + Id::Variable(variable_id) => { + referenced.variables[variable_id.id as usize] = true; + } + } +} + +fn visit_block(state: &mut State, block: &Block) { + for instruction in block.instructions.iter() { + let (opcode, result) = instruction.get_op_and_result(state.ir_meta); + if let Some(id) = result { + state.referenced.types[id.type_id.id as usize] = true; + } + + match opcode { + OpCode::MergeInput + | OpCode::Discard + | OpCode::Break + | OpCode::Continue + | OpCode::Passthrough + | OpCode::NextBlock + | OpCode::Loop + | OpCode::DoLoop + | OpCode::Return(None) + | OpCode::Merge(None) => (), + OpCode::Call(_, params) + | OpCode::ConstructVectorFromMultiple(params) + | OpCode::ConstructMatrixFromMultiple(params) + | OpCode::ConstructStruct(params) + | OpCode::ConstructArray(params) + | OpCode::BuiltIn(_, params) => { + for param in params { + record_reference(&mut state.referenced, *param); + } + } + OpCode::Return(Some(id)) + | OpCode::Merge(Some(id)) + | OpCode::If(id) + | OpCode::LoopIf(id) + | OpCode::ExtractVectorComponent(id, _) + | OpCode::ExtractVectorComponentMulti(id, _) + | OpCode::ExtractStructField(id, _) + | OpCode::ConstructScalarFromScalar(id) + | OpCode::ConstructVectorFromScalar(id) + | OpCode::ConstructMatrixFromScalar(id) + | OpCode::ConstructMatrixFromMatrix(id) + | OpCode::AccessVectorComponent(id, _) + | OpCode::AccessVectorComponentMulti(id, _) + | OpCode::AccessStructField(id, _) + | OpCode::Load(id) + | OpCode::Unary(_, id) + | OpCode::Alias(id) => record_reference(&mut state.referenced, *id), + OpCode::Switch(id, cases) => { + record_reference(&mut state.referenced, *id); + for case in cases { + case.map(|id| { + state.referenced.constants[id.id as usize] = true; + }); + } + } + OpCode::ExtractVectorComponentDynamic(lhs, rhs) + | OpCode::ExtractMatrixColumn(lhs, rhs) + | OpCode::ExtractArrayElement(lhs, rhs) + | OpCode::AccessVectorComponentDynamic(lhs, rhs) + | OpCode::AccessMatrixColumn(lhs, rhs) + | OpCode::AccessArrayElement(lhs, rhs) + | OpCode::Store(lhs, rhs) + | OpCode::Binary(_, lhs, rhs) => { + record_reference(&mut state.referenced, *lhs); + record_reference(&mut state.referenced, *rhs); + } + OpCode::Texture(texture_op, sampler, coord) => { + record_reference(&mut state.referenced, *sampler); + record_reference(&mut state.referenced, *coord); + match texture_op { + TextureOpCode::Implicit { is_proj: _, offset } + | TextureOpCode::Gather { offset } => { + offset.map(|id| record_reference(&mut state.referenced, id)); + } + TextureOpCode::Compare { compare } => { + record_reference(&mut state.referenced, *compare); + } + TextureOpCode::Lod { is_proj: _, lod, offset } => { + record_reference(&mut state.referenced, *lod); + offset.map(|id| record_reference(&mut state.referenced, id)); + } + TextureOpCode::CompareLod { compare, lod } => { + record_reference(&mut state.referenced, *compare); + record_reference(&mut state.referenced, *lod); + } + TextureOpCode::Bias { is_proj: _, bias, offset } => { + record_reference(&mut state.referenced, *bias); + offset.map(|id| record_reference(&mut state.referenced, id)); + } + TextureOpCode::CompareBias { compare, bias } => { + record_reference(&mut state.referenced, *compare); + record_reference(&mut state.referenced, *bias); + } + TextureOpCode::Grad { is_proj: _, dx, dy, offset } => { + record_reference(&mut state.referenced, *dx); + record_reference(&mut state.referenced, *dy); + offset.map(|id| record_reference(&mut state.referenced, id)); + } + TextureOpCode::GatherComponent { component, offset } => { + record_reference(&mut state.referenced, *component); + offset.map(|id| record_reference(&mut state.referenced, id)); + } + TextureOpCode::GatherRef { refz, offset } => { + record_reference(&mut state.referenced, *refz); + offset.map(|id| record_reference(&mut state.referenced, id)); + } + } + } + }; + } +} + +// For variables that are live, mark their type and initializer as live too. +fn mark_referenced_variable_types_and_initializers(ir_meta: &IRMeta, referenced: &mut Referenced) { + referenced.variables.iter().enumerate().for_each(|(id, is_referenced)| { + if *is_referenced { + let variable = ir_meta.get_variable(VariableId { id: id as u32 }); + referenced.types[variable.type_id.id as usize] = true; + variable.initializer.map(|id| referenced.constants[id.id as usize] = true); + } + }); +} + +fn mark_referenced(id: u32, referenced: &mut [bool], to_process: &mut Vec) { + let id = id as usize; + if !referenced[id] { + referenced[id] = true; + to_process.push(id); + } +} + +// For constants that are live, mark their constituting components as live too. +fn mark_referenced_constant_components(ir_meta: &IRMeta, referenced: &mut [bool]) { + let mut to_process = referenced + .iter() + .enumerate() + .filter_map(|(id, is_referenced)| if *is_referenced { Some(id) } else { None }) + .collect::>(); + + while let Some(id) = to_process.pop() { + let constant = ir_meta.get_constant(ConstantId { id: id as u32 }); + if constant.value.is_composite() { + let components = constant.value.get_composite_elements(); + for component_id in components { + mark_referenced(component_id.id, referenced, &mut to_process); + } + } + } +} + +// For types that are live, mark their subtypes as live too. We don't prune basic types (float, +// uvec4, etc), only structs have any reason to be dead-code-eliminated so that we don't need to +// unnecessarily declare them. +fn mark_referenced_type_components(ir_meta: &IRMeta, referenced: &mut [bool]) { + let mut to_process = referenced + .iter() + .enumerate() + .filter_map(|(id, is_referenced)| if *is_referenced { Some(id) } else { None }) + .collect::>(); + + while let Some(id) = to_process.pop() { + let type_info = ir_meta.get_type(TypeId { id: id as u32 }); + match type_info { + Type::Scalar(_) | Type::Vector(..) | Type::Matrix(..) | Type::Image(..) => (), + Type::Struct(_, fields, _) => { + for field in fields { + mark_referenced(field.type_id.id, referenced, &mut to_process); + } + } + Type::Array(element_id, _) + | Type::UnsizedArray(element_id) + | Type::Pointer(element_id) => { + mark_referenced(element_id.id, referenced, &mut to_process); + } + Type::DeadCodeEliminated => { + panic!("Internal error: A dead-code-eliminated type cannot be referenced"); + } + } + } +} diff --git a/src/compiler/translator/ir/src/transform/remove_unused_framebuffer_fetch.rs b/src/compiler/translator/ir/src/transform/remove_unused_framebuffer_fetch.rs new file mode 100644 index 00000000000..a8dd0cbc65d --- /dev/null +++ b/src/compiler/translator/ir/src/transform/remove_unused_framebuffer_fetch.rs @@ -0,0 +1,254 @@ +// Copyright 2025 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. +// +// Turn `inout` variables that are never read from into |out| before collecting variables and +// before PLS uses them. +// +// An `inout` variable must remain as `inout` under the following conditions: +// +// - If not all channels are written to (and the unwritten channels should be preserved) +// - If the shader reads from the variable before fully overwriting it +// - If the shader has `discard` +// +// Detecting the above conditions perfectly can be very tricky. To simplify this transformation +// and detect the most common cases, the following assumptions are made: +// +// - Any writes other than directly under `main()`'s body (not nested) do not count, because they +// may be conditionally done. +// - Any reads anywhere will make the variable stay as `inout`. +// +use crate::ir::*; +use crate::*; + +struct State<'a> { + ir_meta: &'a mut IRMeta, + // Whether a read operation has been performed on the variable + is_read: Vec, + // Which channels of the variable have been written to in main() + written_channels: Vec, + is_in_main: bool, + shader_has_discard: bool, +} + +pub fn run(ir: &mut IR) { + let is_read = vec![false; ir.meta.all_variables().len()]; + let written_channels = vec![0u8; ir.meta.all_variables().len()]; + + let mut state = State { + ir_meta: &mut ir.meta, + is_read, + written_channels, + is_in_main: false, + shader_has_discard: false, + }; + + traverser::visitor::for_each_function( + &mut state, + &ir.function_entries, + |state, function_id| { + state.is_in_main = + state.ir_meta.get_main_function_id().map(|id| id == function_id).unwrap(); + }, + |state, block, _, depth| { + visit_block(state, block, depth); + traverser::visitor::VISIT_SUB_BLOCKS + }, + |_, _| {}, + ); + + // Turn `inout` fragment outputs to `out` if they are never read from and completely + // overwritten. + if !state.shader_has_discard { + for variable_id in state.ir_meta.all_global_variables().clone() { + // Must not be read from + if state.is_read[variable_id.id as usize] { + continue; + } + + // Must be an `inout` variable + let variable = state.ir_meta.get_variable(variable_id); + if !variable.decorations.has(Decoration::InputOutput) { + continue; + } + + // Must have written to all channels + let type_info = state.ir_meta.get_type(variable.type_id); + debug_assert!(type_info.is_pointer()); + let type_info = state.ir_meta.get_type(type_info.get_element_type_id().unwrap()); + let all_channels = if type_info.is_scalar() { + 1u8 + } else if let Some(vector_size) = type_info.get_vector_size() { + ((1 << vector_size) - 1) as u8 + } else { + continue; + }; + if state.written_channels[variable_id.id as usize] & all_channels == all_channels { + // Turn `inout` into `out` + for decoration in + state.ir_meta.get_variable_mut(variable_id).decorations.decorations.iter_mut() + { + if *decoration == Decoration::InputOutput { + *decoration = Decoration::Output; + break; + } + } + } + } + } +} + +fn read_pointer(ir_meta: &IRMeta, is_read: &mut [bool], pointer: TypedId) { + let mut pointer = pointer; + while let Id::Register(register_id) = pointer.id { + match ir_meta.get_instruction(register_id).op { + OpCode::Alias(id) + | OpCode::AccessVectorComponent(id, _) + | OpCode::AccessVectorComponentMulti(id, _) + | OpCode::AccessVectorComponentDynamic(id, _) + | OpCode::AccessMatrixColumn(id, _) + | OpCode::AccessStructField(id, _) + | OpCode::AccessArrayElement(id, _) => { + pointer = id; + } + _ => { + panic!("Internal error: Unexpected value-producing instruction"); + } + } + } + + // Mark the whole variable as read for simplicity. + if let Id::Variable(variable_id) = pointer.id { + is_read[variable_id.id as usize] = true; + } else { + panic!("Internal error: Unexpected constant where a pointer is expected"); + } +} + +fn write_pointer( + ir_meta: &IRMeta, + written_channels: &mut [u8], + pointer: TypedId, + depth: usize, + is_in_main: bool, +) { + let mut pointer = pointer; + + // Don't count writes that may never execute. + if depth > 0 || !is_in_main { + return; + } + + let mut channels = 0u8; + while let Id::Register(register_id) = pointer.id { + match ir_meta.get_instruction(register_id).op { + OpCode::Alias(id) => { + pointer = id; + } + OpCode::AccessVectorComponent(id, index) => { + pointer = id; + // Swizzle of swizzle is never generated due to folding. + debug_assert!(channels == 0); + channels |= (1 << index) as u8; + } + OpCode::AccessVectorComponentMulti(id, ref indices) => { + pointer = id; + // Swizzle of swizzle is never generated due to folding. + debug_assert!(channels == 0); + for index in indices { + channels |= (1 << index) as u8; + } + } + OpCode::AccessVectorComponentDynamic(..) + | OpCode::AccessMatrixColumn(..) + | OpCode::AccessStructField(..) + | OpCode::AccessArrayElement(..) => { + // `inout` variables cannot be structs or matrices. For simplicity, we also ignore + // arrays and keep them as `inout`. When the vector component is not a constant, + // we can't track which channels are written to. In all the above cases, assume + // the output is not written to. + return; + } + _ => { + panic!("Internal error: Unexpected value-producing instruction"); + } + } + } + + // Mark the channels that have been written to. + if let Id::Variable(variable_id) = pointer.id { + // If channels is zero, it means that swizzle was not used, so the whole variable + // is being written to. + written_channels[variable_id.id as usize] |= if channels == 0 { 0xFu8 } else { channels }; + } else { + panic!("Internal error: Unexpected constant where a pointer is expected"); + } +} + +fn visit_block(state: &mut State, block: &Block, depth: usize) { + for instruction in block.instructions.iter() { + let (opcode, _) = instruction.get_op_and_result(state.ir_meta); + + match opcode { + OpCode::Discard => { + state.shader_has_discard = true; + }, + // Read accesses + &OpCode::Load(pointer) | + &OpCode::Unary(UnaryOpCode::PrefixIncrement, pointer) | + &OpCode::Unary(UnaryOpCode::PrefixDecrement, pointer) | + &OpCode::Unary(UnaryOpCode::PostfixIncrement, pointer) | + &OpCode::Unary(UnaryOpCode::PostfixDecrement, pointer) | + // While the atomic*() functions don't make sense for color outputs, there's nothing + // preventing a shader from using them. + &OpCode::Binary(BinaryOpCode::AtomicAdd, pointer, _) | + &OpCode::Binary(BinaryOpCode::AtomicMin, pointer, _) | + &OpCode::Binary(BinaryOpCode::AtomicMax, pointer, _) | + &OpCode::Binary(BinaryOpCode::AtomicAnd, pointer, _) | + &OpCode::Binary(BinaryOpCode::AtomicOr, pointer, _) | + &OpCode::Binary(BinaryOpCode::AtomicXor, pointer, _) | + &OpCode::Binary(BinaryOpCode::AtomicExchange, pointer, _) => { + read_pointer(state.ir_meta, &mut state.is_read, pointer); + } + + // Write accesses + &OpCode::Store(pointer, _) | + &OpCode::Binary(BinaryOpCode::Modf, _, pointer) | + &OpCode::Binary(BinaryOpCode::Frexp, _, pointer) => { + write_pointer(state.ir_meta, &mut state.written_channels, pointer, depth, state.is_in_main); + }, + OpCode::BuiltIn(BuiltInOpCode::UaddCarry, args) | + OpCode::BuiltIn(BuiltInOpCode::UsubBorrow, args) => { + write_pointer(state.ir_meta, &mut state.written_channels, args[2], depth, state.is_in_main); + } + OpCode::BuiltIn(BuiltInOpCode::UmulExtended, args) | + OpCode::BuiltIn(BuiltInOpCode::ImulExtended, args) => { + write_pointer(state.ir_meta, &mut state.written_channels, args[3], depth, state.is_in_main); + write_pointer(state.ir_meta, &mut state.written_channels, args[2], depth, state.is_in_main); + }, + + // Calls could read or write from variables depending on the parameter direction. + &OpCode::Call(function_id, ref args) => { + let param_directions = state.ir_meta.get_function(function_id).params.iter().map(|param| param.direction); + args.iter().zip(param_directions).for_each(|(&arg, direction)| { + // `out` and `inout` parameters are always pointers. Treat `inout` parameters + // as being read. + match direction { + FunctionParamDirection::Input => { + if state.ir_meta.get_type(arg.type_id).is_pointer() { + read_pointer(state.ir_meta, &mut state.is_read, arg); + } + }, + FunctionParamDirection::InputOutput => { + read_pointer(state.ir_meta, &mut state.is_read, arg); + }, + FunctionParamDirection::Output => { + write_pointer(state.ir_meta, &mut state.written_channels, arg, depth, state.is_in_main); + }, + }; + }); + }, + _ => {}, + }; + } +} diff --git a/src/compiler/translator/ir/src/traverser.rs b/src/compiler/translator/ir/src/traverser.rs new file mode 100644 index 00000000000..74003ff6395 --- /dev/null +++ b/src/compiler/translator/ir/src/traverser.rs @@ -0,0 +1,579 @@ +// 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. +// +// Traverser utilities for the IR. Fundamentally, there are two types of traversers: +// +// - A visitor does a read-only traversal of the IR. +// - A transformer may mutate the IR at the instruction or block granularity. The +// instruction::make! and instruction::make_with_result_id! macros can be used to generate new +// instructions during transformations. To avoid excessive modifications to the IR, when +// transforming an instruction that produces a given id, use instruction::make_with_result_id! on +// the final instruction to produce the same id, leaving the rest of the IR intact. + +use crate::ir::*; +use crate::*; + +#[derive(Copy, Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum BlockKind { + // Entry to the function + Entry, + // The true and false blocks of an if + True, + False, + // The condition of a loop + LoopCondition, + // The body of a (do-)loop + LoopBody, + // The continue block of a loop + Continue, + // The case block of a switch, and the associated constant with the case (if any). + Case(Option), + // Merge block of a divergent control flow. + Merge, +} + +pub mod visitor { + use super::*; + + #[derive(PartialEq, Copy, Clone)] + #[cfg_attr(debug_assertions, derive(Debug))] + pub enum VisitAfter { + SubBlocks, + MergeBlock, + Nothing, + } + + pub const VISIT_SUB_BLOCKS: VisitAfter = VisitAfter::SubBlocks; + pub const SKIP_TO_MERGE_BLOCK: VisitAfter = VisitAfter::MergeBlock; + pub const STOP: VisitAfter = VisitAfter::Nothing; + + pub fn for_each_function( + state: &mut State, + function_entries: &[Option], + pre_visit: PreVisit, + block_visit: BlockVisit, + post_visit: PostVisit, + ) where + PreVisit: Fn(&mut State, FunctionId), + BlockVisit: Fn(&mut State, &Block, BlockKind, usize) -> VisitAfter, + PostVisit: Fn(&mut State, FunctionId), + { + for (id, entry) in function_entries.iter().enumerate() { + if entry.is_none() { + // Skip over functions that have been dead-code eliminated. + continue; + } + let func_id = FunctionId { id: id as u32 }; + pre_visit(state, func_id); + visit(state, entry.as_ref().unwrap(), BlockKind::Entry, &block_visit, 0); + // TODO(http://anglebug.com/349994211): post visit useful for functions? + post_visit(state, func_id); + } + } + + fn block1_kind(parent_op: &OpCode) -> BlockKind { + match parent_op { + OpCode::If(_) => BlockKind::True, + _ => BlockKind::LoopBody, + } + } + fn block2_kind(parent_op: &OpCode) -> BlockKind { + match parent_op { + OpCode::If(_) => BlockKind::False, + _ => BlockKind::Continue, + } + } + + pub fn visit( + state: &mut State, + block: &Block, + kind: BlockKind, + block_visit: &BlockVisit, + depth: usize, + ) where + BlockVisit: Fn(&mut State, &Block, BlockKind, usize) -> VisitAfter, + { + let visit_after = block_visit(state, block, kind, depth); + + let visit_sub_blocks = visit_after == VISIT_SUB_BLOCKS; + let visit_merge_block = visit_after != STOP; + let parent_op = block.get_terminating_op(); + let sub_block_depth = depth + 1; + + if visit_sub_blocks { + block.loop_condition.as_ref().inspect(|block| { + visit(state, block, BlockKind::LoopCondition, block_visit, sub_block_depth) + }); + block.block1.as_ref().inspect(|block| { + visit(state, block, block1_kind(parent_op), block_visit, sub_block_depth) + }); + block.block2.as_ref().inspect(|block| { + visit(state, block, block2_kind(parent_op), block_visit, sub_block_depth) + }); + if let OpCode::Switch(_, case_ids) = parent_op { + block.case_blocks.iter().zip(case_ids).for_each(|(case, &case_id)| { + visit(state, case, BlockKind::Case(case_id), block_visit, sub_block_depth) + }); + } + } + + if visit_merge_block { + block + .merge_block + .as_ref() + .inspect(|merge| visit(state, merge, BlockKind::Merge, block_visit, depth)); + } + } + + // A helper to visit the instructions (but also variables and inputs) of a block in a way + // that is convenient for replicating what the block includes, such as when generating + // code. + // + // This helper is used when something is generated out of the visited blocks. To + // facilitate that, `block_visit` returns a BlockResult representing the result of the + // visit to each block. These results are automatically aggregated when sub-blocks are + // visited so that the caller doesn't have to do gymnastics to do the same. + // + // `block_visit` is used to look ahead in the block if needed, such as the variable list, + // the input of the merge block etc, as well as mark the beginning of a new block. Some + // object representing the result of a visit to this block is returned. + // `non_branch_instructions_visit` is called on all instructions of the block except the + // branch instruction, before recursing into the sub-blocks. The block's result object is + // passed in. + // `branch_instructions_visit` is called after the sub-blocks are visited and is only used + // to visit the block's terminating branch instruction. This instruction takes the result + // objects for the sub-blocks to operate on. + // `merge_result_block_chain` is called after all the blocks in a merge-chain are visited to + // aggregate them as necessary. The aggregated result is returned. + pub fn visit_block_instructions< + State, + BlockResult, + BlockVisit, + NonBranchInstructionsVisit, + BranchInstructionVisit, + MergeResultBlockChain, + >( + state: &mut State, + block: &Block, + block_visit: &BlockVisit, + non_branch_instructions_visit: &NonBranchInstructionsVisit, + branch_instruction_visit: &BranchInstructionVisit, + merge_result_block_chain: &MergeResultBlockChain, + ) -> BlockResult + where + BlockVisit: Fn(&mut State, &Block) -> BlockResult, + NonBranchInstructionsVisit: Fn(&mut State, &mut BlockResult, &[BlockInstruction]), + BranchInstructionVisit: Fn( + &mut State, + &mut BlockResult, + &OpCode, + Option, + Option, + Option, + Vec, + ), + MergeResultBlockChain: Fn(&mut State, Vec) -> BlockResult, + { + let mut cur_block = block; + let mut result_block_chain = Vec::new(); + loop { + let mut this_block_result = block_visit(state, cur_block); + + // Visit the instructions first, except the branch instruction. Any id that is + // defined in this block may be used by the sub-blocks, so it must be visited + // beforehand. + non_branch_instructions_visit( + state, + &mut this_block_result, + &cur_block.instructions[..cur_block.instructions.len() - 1], + ); + + // Generate instructions for the sub-blocks before processing the branch instruction. + let loop_condition_block_result = cur_block.loop_condition.as_ref().map(|block| { + visit_block_instructions( + state, + block, + block_visit, + non_branch_instructions_visit, + branch_instruction_visit, + merge_result_block_chain, + ) + }); + let block1_result = cur_block.block1.as_ref().map(|block| { + visit_block_instructions( + state, + block, + block_visit, + non_branch_instructions_visit, + branch_instruction_visit, + merge_result_block_chain, + ) + }); + let block2_result = cur_block.block2.as_ref().map(|block| { + visit_block_instructions( + state, + block, + block_visit, + non_branch_instructions_visit, + branch_instruction_visit, + merge_result_block_chain, + ) + }); + let case_block_results = cur_block + .case_blocks + .iter() + .map(|block| { + visit_block_instructions( + state, + block, + block_visit, + non_branch_instructions_visit, + branch_instruction_visit, + merge_result_block_chain, + ) + }) + .collect::>(); + + // Finally, visit the branch instruction after visiting the sub-blocks. + branch_instruction_visit( + state, + &mut this_block_result, + cur_block.get_terminating_op(), + loop_condition_block_result, + block1_result, + block2_result, + case_block_results, + ); + result_block_chain.push(this_block_result); + + // Continue visiting the merge blocks. They are logical continuations of the + // parent block. + if let Some(merge_block) = cur_block.merge_block.as_ref() { + cur_block = merge_block; + } else { + break; + } + } + + merge_result_block_chain(state, result_block_chain) + } +} + +// How to transform an instruction after visiting it. +#[cfg_attr(debug_assertions, derive(Debug))] +pub enum Transform { + // Keep the instruction unchanged. Only use this in combination with the other transforms; + // if `Keep` is the only transform, return an empty vector from the transformation callback + // instead. + Keep, + // Remove the instruction. Normally not needed, except if the only transformation is to + // remove the instruction. Otherwise, not specifying `Keep` automatically results in the + // instruction being removed. + Remove, + // Add a new instruction. + Add(BlockInstruction), + // Add a new block. The instructions of the new block are appended to the current block, + // and the branch targets of the current block are set to the new block's. The following + // instructions are placed at the end of the merge chain. + AddBlock(Block), + // Declare a variable at the top of the block. The variable itself should be added to the + // IR's list of variables already. + DeclareVariable(VariableId), + // TODO(http://anglebug.com/349994211): one that removes variables? Best if transformations + // change variables instead of deleting and adding new ones. Ideally, removing variables + // shouldn't be necessary. +} + +// Convenience function to process an instruction::Result::Void and append it to the list of +// Transforms. +pub fn add_void_instruction(transforms: &mut Vec, inst: instruction::Result) { + match inst { + instruction::Result::Void(op) => { + transforms.push(Transform::Add(BlockInstruction::new_void(op))) + } + _ => panic!("Internal error: Expected instruction with no value"), + }; +} + +// Convenience function to process a typed instruction::Result and append it to the list of +// Transforms. Returns a TypedId representing the result. +pub fn add_typed_instruction( + transforms: &mut Vec, + inst: instruction::Result, +) -> TypedId { + if let instruction::Result::Register(id) = inst { + transforms.push(Transform::Add(BlockInstruction::new_typed(id.id))); + } + + inst.get_result_id() +} + +// Variant of the above that create a single instruction, removing some boilerplate. +pub fn single_void_instruction(inst: instruction::Result) -> Vec { + let mut transforms = vec![]; + add_void_instruction(&mut transforms, inst); + transforms +} +pub fn single_typed_instruction(inst: instruction::Result) -> Vec { + let mut transforms = vec![]; + add_typed_instruction(&mut transforms, inst); + transforms +} + +pub mod transformer { + use super::*; + + pub fn for_each_function( + state: &mut State, + function_entries: &mut [Option], + tree_transform: &TreeTransform, + ) where + TreeTransform: Fn(&mut State, FunctionId, &mut Block), + { + for (id, entry) in function_entries.iter_mut().enumerate() { + if entry.is_none() { + // Skip over functions that have been dead-code eliminated. + continue; + } + + // Let the transformer freely transform the function blocks as it sees fit. + let func_id = FunctionId { id: id as u32 }; + tree_transform(state, func_id, entry.as_mut().unwrap()); + } + } + + // Run a function for each block of the tree, starting from a root node. The function + // receives the block to transform, which it is free to transform in any way. It returns a + // block for which the sub-blocks should be visited. The block is visited once before the + // sub-blocks are visited and once after. + // + // If a transformation turns one block into a tree of blocks, it may choose to make the + // traversal skip over the new blocks by returning the merge block of the tree. Otherwise, + // it may choose to return the original block so the new blocks are revisited. + pub fn for_each_block( + state: &mut State, + block: &mut Block, + block_transform_pre: &BlockTransformPre, + block_transform_post: &BlockTransformPost, + ) where + for<'block> BlockTransformPre: Fn(&mut State, &'block mut Block) -> &'block mut Block, + for<'block> BlockTransformPost: Fn(&mut State, &'block mut Block) -> &'block mut Block, + { + let mut cur_block = block; + + loop { + // Visit the block. It may be transformed to another (or a tree of blocks). The + // branch targets may have changed after this. + cur_block = block_transform_pre(state, cur_block); + + // Visit the sub-blocks after transforming the root block. + cur_block.for_each_sub_block_mut(state, &|state, sub_block| { + for_each_block(state, sub_block, block_transform_pre, block_transform_post) + }); + + // Visit the block again after visiting the sub-blocks. It may be transformed further. + cur_block = block_transform_post(state, cur_block); + + // If there is a merge block, continue down the chain. + if let Some(merge_block) = cur_block.merge_block.as_mut() { + cur_block = merge_block; + } else { + break; + } + } + } + + pub fn for_each_instruction( + state: &mut State, + function_entries: &mut [Option], + inst_transform: &InstTransform, + ) where + InstTransform: Fn(&mut State, &BlockInstruction) -> Vec, + { + for_each_function(state, function_entries, &|state, _, entry| { + for_each_block( + state, + entry, + &|state, block| transform_block(state, block, inst_transform), + &|_, block| block, + ) + }); + } + + // Used for common transformations, where typically instructions are added or changed + // (including adding complex control flow), but the original control flow of the shader is + // not changed. Some transformations may need the latter, such as dead-code elimintation, + // but such transformations are likely better off directly manipulating the IR as the + // following helper may be too limiting. + // + // To make sure mistakes are not made, the branch instruction in the block is not allowed + // to be transformed for this reason. + // TODO(http://anglebug.com/349994211): If `Transform` is sufficiently expanded (for example to + // manipulate `block1`, `block2`, `input` etc), this might just work for complex transforms + // like DCE too, but we'll see if ever needed. + // + // The transformation function is given an instruction, and it is expected to return a set + // of transformations to be applied to it. If an empty vector is returned, the instruction + // is kept as is; the empty vector is used because this will be the most common result. + pub fn transform_block<'block, State, InstTransform>( + state: &mut State, + block: &'block mut Block, + inst_transform: &InstTransform, + ) -> &'block mut Block + where + InstTransform: Fn(&mut State, &BlockInstruction) -> Vec, + { + for (i, instruction) in block.instructions.iter().enumerate() { + let result = inst_transform(state, instruction); + if !result.is_empty() { + // Transforming branches is not yet supported, but it is allowed to return + // [..., Keep], i.e. it is valid to prepend to the branch instruction. + debug_assert!( + !instruction.is_branch() || matches!(result.last().unwrap(), Transform::Keep) + ); + // Don't return [Keep], just return []. + debug_assert!(!(result.len() == 1 && matches!(result[0], Transform::Keep))); + + // If any changes are to be made, use a helper to recreate the block. This + // would move the instructions so far visited as untransformed, and starts + // applying modifications going forward. + return transform_block_from(state, block, inst_transform, i, result); + } + } + + // If the loop is not broken out of, nothing has changed and the block is not transformed. + block + } + + // Transform the block starting with the first instruction that was definitely transformed. + // + // Once the transformation is finished, the block may have turned into a tree of blocks; + // the last block in the merge chain is returned. + // + // - The input to the original block becomes the input to the root block of the tree. + // - The variables declared in the original block are also declared in the root block. + // - The branch targets of the original block (based on the original branch instruction, which + // is not transformable) are set in the last block in the merge chain. + fn transform_block_from<'block, State, InstTransform>( + state: &mut State, + block: &'block mut Block, + inst_transform: &InstTransform, + intact_count: usize, + first_transform_result: Vec, + ) -> &'block mut Block + where + InstTransform: Fn(&mut State, &BlockInstruction) -> Vec, + { + let mut new_block = Block::new(); + let mut instructions = std::mem::take(&mut block.instructions); + + // Inherit the block input and variables in the new block. + new_block.input = block.input; + new_block.variables = std::mem::take(&mut block.variables); + // Keep the branch targets in a temp block for now. If the transformation results in a + // tree of blocks, these branch targets are set to the tail of the merge chain. + let mut branch_targets = Block::new(); + inherit_branch_targets(&mut branch_targets, block); + + // Take the first `intact_count` instructions as-is. + let to_transform = instructions.split_off(intact_count); + new_block.instructions = instructions; + + let mut to_transform = to_transform.into_iter(); + + { + // The first of the non-intact instructions is already transformed, so apply the + // transformation to it right away. + let mut cur_block = apply_transforms( + &mut new_block, + to_transform.next().unwrap(), + first_transform_result, + ); + + // Apply the transformation to the rest of the instructions. + for instruction in to_transform { + let result = inst_transform(state, &instruction); + cur_block = apply_transforms(cur_block, instruction, result); + } + } + + // Overwrite the old block and return the the tail of the merge chain. + *block = new_block; + let cur_block = block.get_merge_chain_last_block_mut(); + inherit_branch_targets(cur_block, &mut branch_targets); + + cur_block + } + + fn inherit_branch_targets(new_block: &mut Block, old_block: &mut Block) { + debug_assert!(new_block.merge_block.is_none()); + debug_assert!(new_block.loop_condition.is_none()); + debug_assert!(new_block.block1.is_none()); + debug_assert!(new_block.block2.is_none()); + debug_assert!(new_block.case_blocks.is_empty()); + + new_block.merge_block = old_block.merge_block.take(); + new_block.loop_condition = old_block.loop_condition.take(); + new_block.block1 = old_block.block1.take(); + new_block.block2 = old_block.block2.take(); + new_block.case_blocks = std::mem::take(&mut old_block.case_blocks); + } + + // After visiting an instruction, apply the transformations that are requested by the + // callback. + fn apply_transforms( + new_block: &mut Block, + instruction: BlockInstruction, + transform_result: Vec, + ) -> &mut Block { + // An empty transformation result means the instruction should be kept as-is. + if transform_result.is_empty() { + new_block.instructions.push(instruction); + return new_block; + } + + let mut cur_block = new_block; + let mut instruction = instruction; + + for transform in transform_result { + match transform { + Transform::Keep => { + // There should only be one `Keep`, but to satisfy Rust, make sure + // `instruction` stays valid. If `Keep` is encountered again, the branch + // instruction built below will cause panics later (because it's a branch + // in the middle of the block). + cur_block.instructions.push(std::mem::replace( + &mut instruction, + BlockInstruction::new_control_flow(OpCode::NextBlock), + )); + } + Transform::Remove => { + // Nothing to do. Just ignoring the instruction will do. + } + Transform::Add(inst) => { + debug_assert!(!inst.is_branch()); + cur_block.instructions.push(inst); + } + Transform::DeclareVariable(variable_id) => { + cur_block.variables.push(variable_id); + } + Transform::AddBlock(mut block) => { + debug_assert!(block.input.is_none()); + + // Append the instructions/variables of the new block to this block, then + // set the branch targets to the `block`'s. Future transformations + // continue in the merge block of the added block (if any). + cur_block.instructions.extend(std::mem::take(&mut block.instructions)); + cur_block.variables.extend(std::mem::take(&mut block.variables)); + inherit_branch_targets(cur_block, &mut block); + + cur_block = cur_block.get_merge_chain_last_block_mut(); + } + } + } + + cur_block + } +} diff --git a/src/compiler/translator/ir/src/util.rs b/src/compiler/translator/ir/src/util.rs new file mode 100644 index 00000000000..21bcb484591 --- /dev/null +++ b/src/compiler/translator/ir/src/util.rs @@ -0,0 +1,413 @@ +// 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. +// +// Miscellaneous utility functions + +use crate::ir::*; +use crate::*; + +// Calculates the DAG order of the functions. If the functions are declared in this order, +// there is no need for forward declarations. Returns an empty vector if there is recursion. +pub fn calculate_function_decl_order( + ir_meta: &IRMeta, + function_entries: &[Option], +) -> Vec { + // Build the function call graph first. + let mut call_graph = vec![HashSet::new(); function_entries.len()]; + + traverser::visitor::for_each_function( + &mut (FunctionId { id: 0 }, &mut call_graph), + function_entries, + |(current_function, _), id| { + *current_function = id; + }, + |(current_function, call_graph), block, _, _| { + for instruction in &block.instructions { + let (opcode, _) = instruction.get_op_and_result(ir_meta); + if let &OpCode::Call(callee, _) = opcode { + call_graph[current_function.id as usize].insert(callee); + } + } + + traverser::visitor::VISIT_SUB_BLOCKS + }, + |_, _| {}, + ); + + #[derive(Copy, Clone, PartialEq)] + #[cfg_attr(debug_assertions, derive(Debug))] + enum VisitState { + NotVisited, + Visiting, + Visited, + } + #[derive(Copy, Clone, PartialEq)] + #[cfg_attr(debug_assertions, derive(Debug))] + enum VisitOrder { + Pre, + Post, + } + + // Call DFS from main(), calculating the topological sort and whether there are any cycles + // in one go. + let mut decl_order = Vec::new(); + let mut visit_state = vec![VisitState::NotVisited; function_entries.len()]; + let mut visit_stack = vec![(ir_meta.get_main_function_id().unwrap(), VisitOrder::Pre)]; + + while let Some((function_id, visit)) = visit_stack.pop() { + let state = &mut visit_state[function_id.id as usize]; + + match visit { + VisitOrder::Pre => { + match *state { + // If this node is already visited, move on, we have reached it from another + // call path. + VisitState::Visited => { + continue; + } + // If this node is being visited and we cycle back to it, there's a loop! + // This was already validated by the parser, so this would be an internal + // error. + VisitState::Visiting => { + panic!("Internal error: recursion detected"); + } + VisitState::NotVisited => { + // Schedule this node to be visited again after the callees. + *state = VisitState::Visiting; + visit_stack.push((function_id, VisitOrder::Post)); + // Visit the callees. + call_graph[function_id.id as usize].iter().for_each(|id| { + visit_stack.push((*id, VisitOrder::Pre)); + }); + } + } + } + VisitOrder::Post => { + // Once all callees are visited, this function can be declared. + debug_assert!(*state == VisitState::Visiting); + *state = VisitState::Visited; + decl_order.push(function_id); + } + }; + } + + decl_order +} + +struct DuplicateBlockContext<'a, 'b, 'c> { + ir_meta: &'a mut IRMeta, + variable_map: &'b mut HashMap, + register_map: &'c mut HashMap, +} + +// Duplicate a block (including its sub-blocks) with new temp ids. This is useful for example +// to monomorphize functions. +pub fn duplicate_block( + ir_meta: &mut IRMeta, + variable_map: &mut HashMap, + block: &Block, +) -> Block { + let mut register_map = HashMap::new(); + + let mut context = + DuplicateBlockContext { ir_meta, variable_map, register_map: &mut register_map }; + + traverser::visitor::visit_block_instructions( + &mut context, + block, + &|context, block| new_block_to_duplicate(context, &block.variables, block.input), + &|context, block_result, instructions| { + duplicate_instructions(context, block_result, instructions) + }, + &|context, + block_result, + branch_opcode, + loop_condition_block_result, + block1_result, + block2_result, + case_block_results| { + duplicate_branch_instruction( + context, + block_result, + branch_opcode, + loop_condition_block_result, + block1_result, + block2_result, + case_block_results, + ) + }, + &|_, block_result_chain| merge_duplicated_block_chain(block_result_chain), + ) +} + +fn new_block_to_duplicate( + context: &mut DuplicateBlockContext, + block_variables: &[VariableId], + block_input: Option, +) -> Block { + let mut new_block = Block::new(); + new_block.variables = block_variables + .iter() + .map(|&variable_id| { + let variable = context.ir_meta.get_variable(variable_id); + + // Note that variables inside blocks should always be Temporary, not Internal or + // ShaderInterface. As such, it's ok to reuse the same name, they will be + // disambiguated during codegen if necessary. + debug_assert!(variable.name.source == NameSource::Temporary); + + let replacement = Variable::new( + variable.name, + variable.type_id, + variable.precision, + variable.decorations.clone(), + variable.built_in, + variable.initializer, + variable.scope, + ); + let replacement = context.ir_meta.add_variable(replacement); + + context.variable_map.insert(variable_id, Id::new_variable(replacement)); + replacement + }) + .collect(); + + new_block.input = block_input.map(|input| { + let replacement = + context.ir_meta.new_register(OpCode::MergeInput, input.type_id, input.precision); + + context.register_map.insert(input.id, replacement.id); + replacement + }); + + new_block +} + +macro_rules! mapped_id { + ($context:ident, $id:ident) => {{ + let mapped = match $id.id { + Id::Register(r) => Id::new_register(*$context.register_map.get(&r).unwrap_or(&r)), + Id::Variable(v) => *$context.variable_map.get(&v).unwrap_or(&$id.id), + Id::Constant(_) => $id.id, + }; + + TypedId::new(mapped, $id.type_id, $id.precision) + }}; +} + +macro_rules! mapped_ids { + ($context:ident, $ids:ident) => { + $ids.iter().map(|&id| mapped_id!($context, id)).collect() + }; +} + +fn duplicate_instructions( + context: &mut DuplicateBlockContext, + block: &mut Block, + instructions: &[BlockInstruction], +) { + instructions.iter().for_each(|instruction| { + let (op, result) = instruction.get_op_and_result(context.ir_meta); + let duplicate_op = match op { + &OpCode::ExtractVectorComponent(id, index) => { + OpCode::ExtractVectorComponent(mapped_id!(context, id), index) + } + &OpCode::AccessVectorComponent(id, index) => { + OpCode::AccessVectorComponent(mapped_id!(context, id), index) + } + &OpCode::ExtractVectorComponentMulti(id, ref indices) => { + OpCode::ExtractVectorComponentMulti(mapped_id!(context, id), indices.clone()) + } + &OpCode::AccessVectorComponentMulti(id, ref indices) => { + OpCode::AccessVectorComponentMulti(mapped_id!(context, id), indices.clone()) + } + &OpCode::ExtractVectorComponentDynamic(id, index) => { + OpCode::ExtractVectorComponentDynamic( + mapped_id!(context, id), + mapped_id!(context, index), + ) + } + &OpCode::AccessVectorComponentDynamic(id, index) => { + OpCode::AccessVectorComponentDynamic( + mapped_id!(context, id), + mapped_id!(context, index), + ) + } + &OpCode::ExtractMatrixColumn(id, index) => { + OpCode::ExtractMatrixColumn(mapped_id!(context, id), mapped_id!(context, index)) + } + &OpCode::AccessMatrixColumn(id, index) => { + OpCode::AccessMatrixColumn(mapped_id!(context, id), mapped_id!(context, index)) + } + &OpCode::ExtractArrayElement(id, index) => { + OpCode::ExtractArrayElement(mapped_id!(context, id), mapped_id!(context, index)) + } + &OpCode::AccessArrayElement(id, index) => { + OpCode::AccessArrayElement(mapped_id!(context, id), mapped_id!(context, index)) + } + &OpCode::ExtractStructField(id, index) => { + OpCode::ExtractStructField(mapped_id!(context, id), index) + } + &OpCode::AccessStructField(id, index) => { + OpCode::AccessStructField(mapped_id!(context, id), index) + } + &OpCode::ConstructScalarFromScalar(id) => { + OpCode::ConstructScalarFromScalar(mapped_id!(context, id)) + } + &OpCode::ConstructVectorFromScalar(id) => { + OpCode::ConstructVectorFromScalar(mapped_id!(context, id)) + } + &OpCode::ConstructMatrixFromScalar(id) => { + OpCode::ConstructMatrixFromScalar(mapped_id!(context, id)) + } + &OpCode::ConstructMatrixFromMatrix(id) => { + OpCode::ConstructMatrixFromMatrix(mapped_id!(context, id)) + } + OpCode::ConstructVectorFromMultiple(ids) => { + OpCode::ConstructVectorFromMultiple(mapped_ids!(context, ids)) + } + OpCode::ConstructMatrixFromMultiple(ids) => { + OpCode::ConstructMatrixFromMultiple(mapped_ids!(context, ids)) + } + OpCode::ConstructStruct(ids) => OpCode::ConstructStruct(mapped_ids!(context, ids)), + OpCode::ConstructArray(ids) => OpCode::ConstructArray(mapped_ids!(context, ids)), + &OpCode::Load(pointer) => OpCode::Load(mapped_id!(context, pointer)), + &OpCode::Store(pointer, value) => { + OpCode::Store(mapped_id!(context, pointer), mapped_id!(context, value)) + } + &OpCode::Call(function_id, ref params) => { + OpCode::Call(function_id, mapped_ids!(context, params)) + } + &OpCode::Unary(unary_op, id) => OpCode::Unary(unary_op, mapped_id!(context, id)), + &OpCode::Binary(binary_op, lhs, rhs) => { + OpCode::Binary(binary_op, mapped_id!(context, lhs), mapped_id!(context, rhs)) + } + &OpCode::BuiltIn(built_in_op, ref ids) => { + OpCode::BuiltIn(built_in_op, mapped_ids!(context, ids)) + } + &OpCode::Texture(ref texture_op, sampler, coord) => { + let texture_op = match *texture_op { + TextureOpCode::Implicit { is_proj, offset } => TextureOpCode::Implicit { + is_proj, + offset: offset.map(|id| mapped_id!(context, id)), + }, + TextureOpCode::Compare { compare } => { + TextureOpCode::Compare { compare: mapped_id!(context, compare) } + } + TextureOpCode::Lod { is_proj, lod, offset } => TextureOpCode::Lod { + is_proj, + lod: mapped_id!(context, lod), + offset: offset.map(|id| mapped_id!(context, id)), + }, + TextureOpCode::CompareLod { compare, lod } => TextureOpCode::CompareLod { + compare: mapped_id!(context, compare), + lod: mapped_id!(context, lod), + }, + TextureOpCode::Bias { is_proj, bias, offset } => TextureOpCode::Bias { + is_proj, + bias: mapped_id!(context, bias), + offset: offset.map(|id| mapped_id!(context, id)), + }, + TextureOpCode::CompareBias { compare, bias } => TextureOpCode::CompareBias { + compare: mapped_id!(context, compare), + bias: mapped_id!(context, bias), + }, + TextureOpCode::Grad { is_proj, dx, dy, offset } => TextureOpCode::Grad { + is_proj, + dx: mapped_id!(context, dx), + dy: mapped_id!(context, dy), + offset: offset.map(|id| mapped_id!(context, id)), + }, + TextureOpCode::Gather { offset } => { + TextureOpCode::Gather { offset: offset.map(|id| mapped_id!(context, id)) } + } + TextureOpCode::GatherComponent { component, offset } => { + TextureOpCode::GatherComponent { + component: mapped_id!(context, component), + offset: offset.map(|id| mapped_id!(context, id)), + } + } + TextureOpCode::GatherRef { refz, offset } => TextureOpCode::GatherRef { + refz: mapped_id!(context, refz), + offset: offset.map(|id| mapped_id!(context, id)), + }, + }; + OpCode::Texture( + texture_op, + mapped_id!(context, sampler), + mapped_id!(context, coord), + ) + } + _ => panic!("Internal error: unexpected op when duplicating block"), + }; + match result { + Some(original_id) => { + let new_id = context.ir_meta.new_register( + duplicate_op, + original_id.type_id, + original_id.precision, + ); + context.register_map.insert(original_id.id, new_id.id); + block.add_register_instruction(new_id.id); + } + None => { + block.add_void_instruction(duplicate_op); + } + }; + }); +} + +fn duplicate_branch_instruction( + context: &mut DuplicateBlockContext, + block: &mut Block, + op: &OpCode, + loop_condition_block_result: Option, + block1_result: Option, + block2_result: Option, + case_block_results: Vec, +) { + block.set_sub_blocks( + loop_condition_block_result, + block1_result, + block2_result, + case_block_results, + ); + + match *op { + OpCode::Discard => block.terminate(OpCode::Discard), + OpCode::Return(id) => block.terminate(OpCode::Return(id.map(|id| mapped_id!(context, id)))), + OpCode::Break => block.terminate(OpCode::Break), + OpCode::Continue => block.terminate(OpCode::Continue), + OpCode::Passthrough => block.terminate(OpCode::Passthrough), + OpCode::NextBlock => block.terminate(OpCode::NextBlock), + OpCode::Merge(id) => block.terminate(OpCode::Merge(id.map(|id| mapped_id!(context, id)))), + OpCode::If(id) => block.terminate(OpCode::If(mapped_id!(context, id))), + OpCode::Loop => block.terminate(OpCode::Loop), + OpCode::DoLoop => block.terminate(OpCode::DoLoop), + OpCode::LoopIf(id) => block.terminate(OpCode::LoopIf(mapped_id!(context, id))), + OpCode::Switch(id, ref case_ids) => { + block.terminate(OpCode::Switch(mapped_id!(context, id), case_ids.clone())) + } + _ => panic!("Internal error: unexpected branch op when duplicating block"), + } +} + +fn merge_duplicated_block_chain(mut block_chain: Vec) -> Block { + let mut current_block = block_chain.pop().unwrap(); + + while let Some(mut parent_block) = block_chain.pop() { + parent_block.set_merge_block(current_block); + current_block = parent_block; + } + + current_block +} + +pub fn is_precision_applicable_to_type(ir_meta: &IRMeta, type_id: TypeId) -> bool { + let mut base_type_id = type_id; + while let Some(id) = ir_meta.get_type(base_type_id).get_element_type_id() { + base_type_id = id; + } + matches!(base_type_id, TYPE_ID_FLOAT | TYPE_ID_INT | TYPE_ID_UINT) +} diff --git a/src/compiler/translator/ir/src/validator.rs b/src/compiler/translator/ir/src/validator.rs new file mode 100644 index 00000000000..315be54fe1b --- /dev/null +++ b/src/compiler/translator/ir/src/validator.rs @@ -0,0 +1,65 @@ +// 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. +// +// A helper to validate the rules of IR. This is useful particularly to be run after +// transformations, to ensure they generate valid IR. +// +// TODO(http://anglebug.com/349994211): to validate: +// +// - Every ID must be present in the respective map. +// - Every variable must be defined somewhere, either in global block or in a block. +// - Every accessed variable must be declared in an accessible block. +// - Branches must have the appropriate targets set (merge, trueblock for if, etc). +// - No branches inside a block, every block ends in branch. (i.e. no dead code) +// - For merge blocks that have an input, the branch instruction of blocks that jump to it have an +// output. +// - No identical types with different IDs. +// - If there's a cached "has side effect", that it's correct. +// - Validate that ImageType fields are valid in combination with ImageDimension +// - No operations should have entirely constant arguments, that should be folded (and +// transformations shouldn't retintroduce it) +// - Catch misuse of built-in names. +// - Precision is not applied to types that don't are not applicable. It _is_ applied to types +// that are applicable (including uniforms and samplers for example). Needs to work to make +// sure precision is always assigned. +// - Case values are always ConstantId (int/uint only too?) +// - Variables are Pointers +// - Pointers only valid in the right arg of load/store/access/call +// - Loop blocks ends in the appropriate instructions. +// - Do blocks end in DoLoop (unless already terminated by something else, like Return) +// - If condition is a bool. +// - Maximum one default case for Switch instructions. +// - No pointer->pointer type. +// - Interface variables with NameSource::Internal are unique. +// - NameSource::Internal names don't start with the user and temporary name prefixes (_u, t and f +// respectively). +// - Interface variables with NameSource::ShaderInterface are unique. +// - NameSource::ShaderInterface and NameSource::Internal are never found inside body +// - blocks, those should always be Temporary. +// - No identity swizzles. +// - Type matches? +// - Block inputs have MergeInput opcode, nothing else has that opcode. +// - Block inputs are not pointers. AST-ifier does not handle that. +// - Whatever else is in the AST validation currently. +// - Validate built-ins that accept an out or inout parameter, that the corresponding parameter is +// passed a Pointer at the call site. For that matter, do the same for user function calls too. +// - Check for invalid texture* combinations, like non-shadow samplers with TextureCompare ops, or +// is_proj is false for cubemaps. +// - Check that function parameter variables don't have an initializer. +// - Check that returned values from functions match the type of the function's return value. +// - Validate that if there's a merge variable in an if block, both true and false blocks exist +// and they both end in a Merge with an ID. (Technically, we should be able to also support one +// block being merge and the other discard/return/break/continue, but no such code can be +// generated right now). +use crate::ir::*; +struct Validator {} + +impl Validator { + fn new() -> Validator { + Validator {} + } + fn validate(&mut self, _ir: &IR) -> bool { + true + } +} diff --git a/src/compiler/translator/msl/AstHelpers.cpp b/src/compiler/translator/msl/AstHelpers.cpp index 9533d49c527..a2ad182a1b2 100644 --- a/src/compiler/translator/msl/AstHelpers.cpp +++ b/src/compiler/translator/msl/AstHelpers.cpp @@ -15,30 +15,6 @@ using namespace sh; //////////////////////////////////////////////////////////////////////////////// -const TVariable &sh::CreateStructTypeVariable(TSymbolTable &symbolTable, - const TStructure &structure) -{ - TType *type = new TType(&structure, true); - TVariable *var = new TVariable(&symbolTable, ImmutableString(""), type, SymbolType::Empty); - return *var; -} - -const TVariable &sh::CreateInstanceVariable(TSymbolTable &symbolTable, - const TStructure &structure, - const Name &name, - TQualifier qualifier, - const angle::Span *arraySizes) -{ - TType *type = new TType(&structure, false); - type->setQualifier(qualifier); - if (arraySizes) - { - type->makeArrays(*arraySizes); - } - TVariable *var = new TVariable(&symbolTable, name.rawName(), type, name.symbolType()); - return *var; -} - static void AcquireFunctionExtras(TFunction &dest, const TFunction &src) { if (src.isDefined()) @@ -196,44 +172,6 @@ void sh::SetArg(TIntermAggregate &call, size_t index, TIntermTyped &arg) (*call.getSequence())[index] = &arg; } -TIntermBinary &sh::AccessField(const TVariable &structInstanceVar, const Name &name) -{ - return AccessField(*new TIntermSymbol(&structInstanceVar), name); -} - -TIntermBinary &sh::AccessField(TIntermTyped &object, const Name &name) -{ - const TStructure *structure = object.getType().getStruct(); - ASSERT(structure); - const TFieldList &fieldList = structure->fields(); - for (int i = 0; i < static_cast(fieldList.size()); ++i) - { - TField *current = fieldList[i]; - if (Name(*current) == name) - { - return AccessFieldByIndex(object, i); - } - } - UNREACHABLE(); - return AccessFieldByIndex(object, -1); -} - -TIntermBinary &sh::AccessFieldByIndex(TIntermTyped &object, int index) -{ -#if defined(ANGLE_ENABLE_ASSERTS) - const TType &type = object.getType(); - ASSERT(!type.isArray()); - const TStructure *structure = type.getStruct(); - ASSERT(structure); - ASSERT(0 <= index); - ASSERT(static_cast(index) < structure->fields().size()); -#endif - - return *new TIntermBinary( - TOperator::EOpIndexDirectStruct, &object, - new TIntermConstantUnion(new TConstantUnion(index), *new TType(TBasicType::EbtInt))); -} - TIntermBinary &sh::AccessIndex(TIntermTyped &indexableNode, int index) { #if defined(ANGLE_ENABLE_ASSERTS) @@ -266,7 +204,7 @@ TIntermTyped &sh::SubVector(TIntermTyped &vectorNode, int begin, int end) { return vectorNode; } - TVector offsets(static_cast(end - begin)); + TVector offsets(static_cast(end - begin)); std::iota(offsets.begin(), offsets.end(), begin); TIntermSwizzle *swizzle = new TIntermSwizzle(vectorNode.deepCopy(), offsets); return *swizzle->fold(nullptr); // Swizzles must always be folded to prevent double swizzles. @@ -393,9 +331,7 @@ bool sh::HasArrayField(const TStructure &structure) return false; } -TIntermTyped &sh::CoerceSimple(TBasicType toBasicType, - TIntermTyped &fromNode, - bool needsExplicitBoolCast) +TIntermTyped &sh::CoerceSimple(TBasicType toBasicType, TIntermTyped &fromNode) { const TType &fromType = fromNode.getType(); @@ -407,33 +343,6 @@ TIntermTyped &sh::CoerceSimple(TBasicType toBasicType, if (toBasicType != fromBasicType) { - if (toBasicType == TBasicType::EbtBool && fromNode.isVector() && needsExplicitBoolCast) - { - switch (fromBasicType) - { - case TBasicType::EbtFloat: - case TBasicType::EbtInt: - case TBasicType::EbtUInt: - { - TIntermSequence *argsSequence = new TIntermSequence(); - for (uint8_t i = 0; i < fromType.getNominalSize(); i++) - { - TIntermTyped &fromTypeSwizzle = SubVector(fromNode, i, i + 1); - TIntermAggregate *boolConstructor = TIntermAggregate::CreateConstructor( - *new TType(toBasicType, 1, 1), new TIntermSequence{&fromTypeSwizzle}); - argsSequence->push_back(boolConstructor); - } - return *TIntermAggregate::CreateConstructor( - *new TType(toBasicType, fromType.getNominalSize(), - fromType.getSecondarySize()), - argsSequence); - } - - default: - break; // No explicit conversion needed - } - } - return *TIntermAggregate::CreateConstructor( *new TType(toBasicType, fromType.getNominalSize(), fromType.getSecondarySize()), new TIntermSequence{&fromNode}); @@ -441,9 +350,7 @@ TIntermTyped &sh::CoerceSimple(TBasicType toBasicType, return fromNode; } -TIntermTyped &sh::CoerceSimple(const TType &toType, - TIntermTyped &fromNode, - bool needsExplicitBoolCast) +TIntermTyped &sh::CoerceSimple(const TType &toType, TIntermTyped &fromNode) { const TType &fromType = fromNode.getType(); @@ -459,33 +366,6 @@ TIntermTyped &sh::CoerceSimple(const TType &toType, if (toBasicType != fromBasicType) { - if (toBasicType == TBasicType::EbtBool && fromNode.isVector() && needsExplicitBoolCast) - { - switch (fromBasicType) - { - case TBasicType::EbtFloat: - case TBasicType::EbtInt: - case TBasicType::EbtUInt: - { - TIntermSequence *argsSequence = new TIntermSequence(); - for (uint8_t i = 0; i < fromType.getNominalSize(); i++) - { - TIntermTyped &fromTypeSwizzle = SubVector(fromNode, i, i + 1); - TIntermAggregate *boolConstructor = TIntermAggregate::CreateConstructor( - *new TType(toBasicType, 1, 1), new TIntermSequence{&fromTypeSwizzle}); - argsSequence->push_back(boolConstructor); - } - return *TIntermAggregate::CreateConstructor( - *new TType(toBasicType, fromType.getNominalSize(), - fromType.getSecondarySize()), - new TIntermSequence{*argsSequence}); - } - - default: - break; // No explicit conversion needed - } - } - return *TIntermAggregate::CreateConstructor(toType, new TIntermSequence{&fromNode}); } return fromNode; diff --git a/src/compiler/translator/msl/AstHelpers.h b/src/compiler/translator/msl/AstHelpers.h index 4006cce9579..905004fd12e 100644 --- a/src/compiler/translator/msl/AstHelpers.h +++ b/src/compiler/translator/msl/AstHelpers.h @@ -19,17 +19,6 @@ namespace sh { -// Creates a variable for a struct type. -const TVariable &CreateStructTypeVariable(TSymbolTable &symbolTable, const TStructure &structure); - -// Creates a variable for a struct instance. -const TVariable &CreateInstanceVariable( - TSymbolTable &symbolTable, - const TStructure &structure, - const Name &name, - TQualifier qualifier = TQualifier::EvqTemporary, - const angle::Span *arraySizes = nullptr); - // The input sequence should be discarded from AST after this is called. TIntermSequence &CloneSequenceAndPrepend(const TIntermSequence &seq, TIntermNode &node); @@ -74,18 +63,6 @@ TIntermTyped &GetArg(const TIntermAggregate &call, size_t index); // Sets the argument of a function call at the given index. void SetArg(TIntermAggregate &call, size_t index, TIntermTyped &arg); -// Accesses a field for the given node with the given field name. -// The node must be a struct instance. -TIntermBinary &AccessField(const TVariable &structInstanceVar, const Name &field); - -// Accesses a field for the given node with the given field name. -// The node must be a struct instance. -TIntermBinary &AccessField(TIntermTyped &object, const Name &field); - -// Accesses a field for the given node by its field index. -// The node must be a struct instance. -TIntermBinary &AccessFieldByIndex(TIntermTyped &object, int index); - // Accesses an element by index for the given node. // The node must be an array, vector, or matrix. TIntermBinary &AccessIndex(TIntermTyped &indexableNode, int index); @@ -139,14 +116,12 @@ bool HasArrayField(const TStructure &structure); // Coerces `fromNode` to `toType` by a constructor call of `toType` if their types differ. // Vector and matrix dimensions are retained. // Array types are not allowed. -TIntermTyped &CoerceSimple(TBasicType toBasicType, - TIntermTyped &fromNode, - bool needsExplicitBoolCast); +TIntermTyped &CoerceSimple(TBasicType toBasicType, TIntermTyped &fromNode); // Coerces `fromNode` to `toType` by a constructor call of `toType` if their types differ. // Vector and matrix dimensions must coincide between to and from. // Array types are not allowed. -TIntermTyped &CoerceSimple(const TType &toType, TIntermTyped &fromNode, bool needsExplicitBoolCast); +TIntermTyped &CoerceSimple(const TType &toType, TIntermTyped &fromNode); TIntermTyped &AsType(SymbolEnv &symbolEnv, const TType &toType, TIntermTyped &fromNode); diff --git a/src/compiler/translator/msl/DebugSink.h b/src/compiler/translator/msl/DebugSink.h index 872add77142..e1ac16eca62 100644 --- a/src/compiler/translator/msl/DebugSink.h +++ b/src/compiler/translator/msl/DebugSink.h @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "compiler/translator/InfoSink.h" diff --git a/src/compiler/translator/msl/EmitMetal.cpp b/src/compiler/translator/msl/EmitMetal.cpp index adef17611b2..0cdc1bae0a1 100644 --- a/src/compiler/translator/msl/EmitMetal.cpp +++ b/src/compiler/translator/msl/EmitMetal.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -523,12 +527,14 @@ static const char *GetOperatorString(TOperator op, return "metal::rint"; case TOperator::EOpClamp: return "metal::clamp"; // TODO fast vs precise namespace + case TOperator::EOpLoopForwardProgress: + return "ANGLE_loopForwardProgress"; case TOperator::EOpSaturate: return "metal::saturate"; // TODO fast vs precise namespace case TOperator::EOpMix: - if (!argType1->isScalar() && argType2 && argType2->getBasicType() == EbtBool) + if (argType2 && argType2->getBasicType() == EbtBool) { - return "ANGLE_mix_bool"; + return "metal::select"; } return "metal::mix"; case TOperator::EOpStep: diff --git a/src/compiler/translator/msl/IdGen.cpp b/src/compiler/translator/msl/IdGen.cpp index 0924d774706..d9dd895c964 100644 --- a/src/compiler/translator/msl/IdGen.cpp +++ b/src/compiler/translator/msl/IdGen.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include diff --git a/src/compiler/translator/msl/Layout.cpp b/src/compiler/translator/msl/Layout.cpp index d16b7fa1706..94216914d59 100644 --- a/src/compiler/translator/msl/Layout.cpp +++ b/src/compiler/translator/msl/Layout.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include diff --git a/src/compiler/translator/msl/ModifyStruct.cpp b/src/compiler/translator/msl/ModifyStruct.cpp index 12e849681fa..366ed366185 100644 --- a/src/compiler/translator/msl/ModifyStruct.cpp +++ b/src/compiler/translator/msl/ModifyStruct.cpp @@ -16,6 +16,7 @@ #include "compiler/translator/msl/AstHelpers.h" #include "compiler/translator/msl/ModifyStruct.h" #include "compiler/translator/msl/TranslatorMSL.h" +#include "compiler/translator/tree_util/IntermNode_util.h" using namespace sh; diff --git a/src/compiler/translator/msl/Pipeline.cpp b/src/compiler/translator/msl/Pipeline.cpp index 00318da8f12..4fa250ae0a0 100644 --- a/src/compiler/translator/msl/Pipeline.cpp +++ b/src/compiler/translator/msl/Pipeline.cpp @@ -112,7 +112,7 @@ bool Pipeline::uses(const TVariable &var) const case TQualifier::EvqSampleMaskIn: case TQualifier::EvqSampleMask: return var.symbolType() == SymbolType::BuiltIn; - case TQualifier::EvqUniform: + case TQualifier::EvqNumSamples: return var.name() == "gl_NumSamples"; default: return false; diff --git a/src/compiler/translator/msl/ProgramPrelude.cpp b/src/compiler/translator/msl/ProgramPrelude.cpp index c8fdeafe2dc..652acfbd3a1 100644 --- a/src/compiler/translator/msl/ProgramPrelude.cpp +++ b/src/compiler/translator/msl/ProgramPrelude.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "compiler/translator/InfoSink.h" @@ -113,7 +117,6 @@ class ProgramPrelude : public TIntermTraverser void degrees(); void radians(); void mod(); - void mixBool(); void postIncrementMatrix(); void preIncrementMatrix(); void postDecrementMatrix(); @@ -127,8 +130,6 @@ class ProgramPrelude : public TIntermTraverser void addScalarMatrix(); void subMatrixScalar(); void subScalarMatrix(); - void divMatrixScalar(); - void divMatrixScalarAssign(); void divScalarMatrix(); void componentWiseDivide(); void componentWiseDivideAssign(); @@ -279,6 +280,7 @@ class ProgramPrelude : public TIntermTraverser void interpolateAtCentroid(); void interpolateAtSample(); void interpolateAtOffset(); + void loopForwardProgress(); private: TInfoSinkBase &mOut; @@ -433,15 +435,6 @@ ANGLE_ALWAYS_INLINE X ANGLE_mod(X x, Y y) } )") -PROGRAM_PRELUDE_DECLARE(mixBool, - R"( -template -ANGLE_ALWAYS_INLINE metal::vec ANGLE_mix_bool(metal::vec a, metal::vec b, metal::vec c) -{ - return metal::mix(a, b, static_cast>(c)); -} -)") - PROGRAM_PRELUDE_DECLARE(pack_half_2x16, R"( ANGLE_ALWAYS_INLINE uint32_t ANGLE_pack_half_2x16(float2 v) @@ -600,32 +593,6 @@ ANGLE_ALWAYS_INLINE metal::matrix operator-(T x, metal::matrix -ANGLE_ALWAYS_INLINE thread metal::matrix &operator/=(thread metal::matrix &m, T x) -{ - for (size_t col = 0; col < Cols; ++col) - { - m[col] /= x; - } - return m; -} -)") - -PROGRAM_PRELUDE_DECLARE(divMatrixScalar, - R"( -#if __METAL_VERSION__ <= 220 -template -ANGLE_ALWAYS_INLINE metal::matrix operator/(metal::matrix m, T x) -{ - m /= x; - return m; -} -#endif -)", - divMatrixScalarAssign()) - PROGRAM_PRELUDE_DECLARE(divScalarMatrix, R"( template @@ -2796,6 +2763,14 @@ template ANGLE_ALWAYS_INLINE T ANGLE_interpolateAtOffset(T value, float2) { return value; } )") +PROGRAM_PRELUDE_DECLARE(loopForwardProgress, + R"( +ANGLE_ALWAYS_INLINE void ANGLE_loopForwardProgress() +{ + volatile bool p = true; +} +)") + //////////////////////////////////////////////////////////////////////////////// // Returned Name is valid for as long as `buffer` is still alive. @@ -3430,14 +3405,7 @@ void ProgramPrelude::visitOperator(TOperator op, case TOperator::EOpMax: case TOperator::EOpStep: case TOperator::EOpSmoothstep: - break; case TOperator::EOpMix: - if (argType2->getBasicType() == TBasicType::EbtBool) - { - mixBool(); - } - break; - case TOperator::EOpAll: case TOperator::EOpAny: case TOperator::EOpIsnan: @@ -3486,34 +3454,23 @@ void ProgramPrelude::visitOperator(TOperator op, break; case TOperator::EOpDiv: - if (argType0->isMatrix()) + if (argType1->isMatrix()) { - if (argType1->isMatrix()) + if (argType0->isMatrix()) { componentWiseDivide(); } - else if (argType1->isScalar()) + else if (argType0->isScalar()) { - divMatrixScalar(); + divScalarMatrix(); } } - if (argType0->isScalar() && argType1->isMatrix()) - { - divScalarMatrix(); - } break; case TOperator::EOpDivAssign: - if (argType0->isMatrix()) + if (argType0->isMatrix() && argType1->isMatrix()) { - if (argType1->isMatrix()) - { - componentWiseDivideAssign(); - } - else if (argType1->isScalar()) - { - divMatrixScalarAssign(); - } + componentWiseDivideAssign(); } break; @@ -3690,6 +3647,10 @@ void ProgramPrelude::visitOperator(TOperator op, ASSERT(!func); break; + case TOperator::EOpLoopForwardProgress: + loopForwardProgress(); + break; + case TOperator::EOpCallFunctionInAST: case TOperator::EOpCallInternalRawFunction: default: diff --git a/src/compiler/translator/msl/RewritePipelines.cpp b/src/compiler/translator/msl/RewritePipelines.cpp index c2c72248738..d45be1a2f4d 100644 --- a/src/compiler/translator/msl/RewritePipelines.cpp +++ b/src/compiler/translator/msl/RewritePipelines.cpp @@ -20,6 +20,7 @@ #include "compiler/translator/tree_ops/PruneNoOps.h" #include "compiler/translator/tree_util/DriverUniform.h" #include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/util.h" diff --git a/src/compiler/translator/msl/SymbolEnv.cpp b/src/compiler/translator/msl/SymbolEnv.cpp index 41ea04c93b6..c98f27f5fff 100644 --- a/src/compiler/translator/msl/SymbolEnv.cpp +++ b/src/compiler/translator/msl/SymbolEnv.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -518,7 +522,6 @@ static TBasicType GetTextureBasicType(TBasicType basicType) case EbtSamplerBuffer: case EbtSamplerCubeArray: case EbtSamplerCubeArrayShadow: - case EbtSampler2DRectShadow: return TBasicType::EbtFloat; case EbtISampler2D: @@ -637,7 +640,6 @@ Name sh::GetTextureTypeName(TBasicType samplerType) break; // Shadow - case EbtSampler2DRectShadow: case EbtSampler2DShadow: HANDLE_TEXTURE_NAME("depth2d"); break; diff --git a/src/compiler/translator/msl/SymbolEnv.h b/src/compiler/translator/msl/SymbolEnv.h index 6dc3354dcd7..804dac4eb01 100644 --- a/src/compiler/translator/msl/SymbolEnv.h +++ b/src/compiler/translator/msl/SymbolEnv.h @@ -38,7 +38,9 @@ class VarField ANGLE_INLINE bool operator==(const VarField &other) const { - return mVariable == other.mVariable && mField == other.mField; + const int thisVarId = mVariable ? mVariable->uniqueId().get() : -1; + const int otherVarId = other.mVariable ? mVariable->uniqueId().get() : -1; + return thisVarId == otherVarId && mField == other.mField; } private: diff --git a/src/compiler/translator/msl/TranslatorMSL.cpp b/src/compiler/translator/msl/TranslatorMSL.cpp index 6f27e4bfd84..1793dfd8417 100644 --- a/src/compiler/translator/msl/TranslatorMSL.cpp +++ b/src/compiler/translator/msl/TranslatorMSL.cpp @@ -21,8 +21,8 @@ #include "compiler/translator/tree_ops/InitializeVariables.h" #include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" #include "compiler/translator/tree_ops/PreTransformTextureCubeGradDerivatives.h" +#include "compiler/translator/tree_ops/ReduceInterfaceBlocks.h" #include "compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h" -#include "compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h" #include "compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h" #include "compiler/translator/tree_ops/RewriteAtomicCounters.h" #include "compiler/translator/tree_ops/RewriteDfdy.h" @@ -33,7 +33,7 @@ #include "compiler/translator/tree_ops/msl/FixTypeConstructors.h" #include "compiler/translator/tree_ops/msl/HoistConstants.h" #include "compiler/translator/tree_ops/msl/IntroduceVertexIndexID.h" -#include "compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.h" +#include "compiler/translator/tree_ops/msl/RescopeGlobalVariables.h" #include "compiler/translator/tree_ops/msl/RewriteCaseDeclarations.h" #include "compiler/translator/tree_ops/msl/RewriteInterpolants.h" #include "compiler/translator/tree_ops/msl/RewriteOutArgs.h" @@ -108,78 +108,6 @@ class DeclareStructTypesTraverser : public TIntermTraverser TOutputMSL *mOutputMSL; }; -class DeclareDefaultUniformsTraverser : public TIntermTraverser -{ - public: - DeclareDefaultUniformsTraverser(TInfoSinkBase *sink, - ShHashFunction64 hashFunction, - NameMap *nameMap) - : TIntermTraverser(true, true, true), - mSink(sink), - mHashFunction(hashFunction), - mNameMap(nameMap), - mInDefaultUniform(false) - {} - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - const TIntermSequence &sequence = *(node->getSequence()); - - // TODO(jmadill): Compound declarations. - ASSERT(sequence.size() == 1); - - TIntermTyped *variable = sequence.front()->getAsTyped(); - const TType &type = variable->getType(); - bool isUniform = type.getQualifier() == EvqUniform && !type.isInterfaceBlock() && - !IsOpaqueType(type.getBasicType()); - - if (visit == PreVisit) - { - if (isUniform) - { - (*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " "; - mInDefaultUniform = true; - } - } - else if (visit == InVisit) - { - mInDefaultUniform = isUniform; - } - else if (visit == PostVisit) - { - if (isUniform) - { - (*mSink) << ";\n"; - - // Remove the uniform declaration from the tree so it isn't parsed again. - TIntermSequence emptyReplacement; - mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, - std::move(emptyReplacement)); - } - - mInDefaultUniform = false; - } - return true; - } - - void visitSymbol(TIntermSymbol *symbol) override - { - if (mInDefaultUniform) - { - const ImmutableString &name = symbol->variable().name(); - ASSERT(!gl::IsBuiltInName(name.data())); - (*mSink) << HashName(&symbol->variable(), mHashFunction, mNameMap) - << ArrayString(symbol->getType()); - } - } - - private: - TInfoSinkBase *mSink; - ShHashFunction64 mHashFunction; - NameMap *mNameMap; - bool mInDefaultUniform; -}; - // Declares a new variable to replace gl_DepthRange, its values are fed from a driver uniform. [[nodiscard]] bool ReplaceGLDepthRangeWithDriverUniform(TCompiler *compiler, TIntermBlock *root, @@ -217,7 +145,7 @@ TIntermSequence *GetMainSequence(TIntermBlock *root) TIntermSymbol *builtinRef = new TIntermSymbol(builtin); // Create a swizzle to "builtin.xy" - TVector swizzleOffsetXY = {0, 1}; + TVector swizzleOffsetXY = {0, 1}; TIntermSwizzle *builtinXY = new TIntermSwizzle(builtinRef, swizzleOffsetXY); // Create a symbol reference to our new variable that will hold the modified builtin. @@ -738,7 +666,7 @@ void AddFragDepthEXTDeclaration(TCompiler &compiler, TIntermBlock &root, TSymbol TIntermSymbol *positionRef = new TIntermSymbol(position); // Create a swizzle to "gl_Position.y" - TVector swizzleOffsetY; + TVector swizzleOffsetY; swizzleOffsetY.push_back(1); TIntermSwizzle *positionY = new TIntermSwizzle(positionRef, swizzleOffsetY); @@ -867,7 +795,7 @@ bool TranslatorMSL::transformDepthBeforeCorrection(TIntermBlock *root, TIntermSymbol *positionRef = new TIntermSymbol(position); // Create a swizzle to "gl_Position.z" - TVector swizzleOffsetZ = {2}; + TVector swizzleOffsetZ = {2}; TIntermSwizzle *positionZ = new TIntermSwizzle(positionRef, swizzleOffsetZ); // Create a ref to "zscale" @@ -899,12 +827,12 @@ bool TranslatorMSL::appendVertexShaderDepthCorrectionToMain( const TVariable *position = BuiltInVariable::gl_Position(); TIntermSymbol *positionRef = new TIntermSymbol(position); - TVector swizzleOffsetZ = {2}; + TVector swizzleOffsetZ = {2}; TIntermSwizzle *positionZ = new TIntermSwizzle(positionRef, swizzleOffsetZ); TIntermConstantUnion *oneHalf = CreateFloatNode(0.5f, EbpMedium); - TVector swizzleOffsetW = {3}; + TVector swizzleOffsetW = {3}; TIntermSwizzle *positionW = new TIntermSwizzle(positionRef->deepCopy(), swizzleOffsetW); // Create the expression "(gl_Position.z + gl_Position.w) * 0.5". @@ -958,18 +886,6 @@ bool TranslatorMSL::translateImpl(TInfoSinkBase &sink, return false; } - // Remove declarations of inactive shader interface variables so glslang wrapper doesn't need to - // replace them. Note: this is done before extracting samplers from structs, as removing such - // inactive samplers is not yet supported. Note also that currently, CollectVariables marks - // every field of an active uniform that's of struct type as active, i.e. no extracted sampler - // is inactive. - if (!RemoveInactiveInterfaceVariables(this, root, &getSymbolTable(), getAttributes(), - getInputVaryings(), getOutputVariables(), getUniforms(), - getInterfaceBlocks(), false)) - { - return false; - } - // Write out default uniforms into a uniform block assigned to a specific set/binding. int aggregateTypesUsedForUniforms = 0; int atomicCounterCount = 0; @@ -986,6 +902,14 @@ bool TranslatorMSL::translateImpl(TInfoSinkBase &sink, } } + if (compileOptions.rescopeGlobalVariables) + { + if (!RescopeGlobalVariables(*this, *root)) + { + return false; + } + } + // If there are any function calls that take array-of-array of opaque uniform parameters, or // other opaque uniforms that need special handling in Vulkan, such as atomic counters, // monomorphize the functions by removing said parameters and replacing them in the function @@ -1283,8 +1207,7 @@ bool TranslatorMSL::translateImpl(TInfoSinkBase &sink, DeclareRightBeforeMain(*root, *fragCoord); } - if (!RewriteDfdy(this, root, &getSymbolTable(), getShaderVersion(), specConst, - driverUniforms)) + if (!RewriteDfdy(this, root, &getSymbolTable(), getShaderVersion(), driverUniforms)) { return false; } @@ -1409,8 +1332,7 @@ bool TranslatorMSL::translateImpl(TInfoSinkBase &sink, return false; } - const bool needsExplicitBoolCasts = compileOptions.addExplicitBoolCasts; - if (!AddExplicitTypeCasts(*this, *root, symbolEnv, needsExplicitBoolCasts)) + if (!AddExplicitTypeCasts(*this, *root, symbolEnv)) { return false; } @@ -1420,7 +1342,8 @@ bool TranslatorMSL::translateImpl(TInfoSinkBase &sink, return false; } - if (!ReduceInterfaceBlocks(*this, *root, idGen)) + if (!ReduceInterfaceBlocks(*this, *root, + [&idGen]() { return idGen.createNewName().rawName(); })) { return false; } @@ -1497,7 +1420,7 @@ bool TranslatorMSL::translate(TIntermBlock *root, mValidateASTOptions.validatePrecision = false; TInfoSinkBase &sink = getInfoSink().obj; - SpecConst specConst(&getSymbolTable(), compileOptions, getShaderType()); + SpecConst specConst(&getSymbolTable(), getShaderType()); DriverUniformMetal driverUniforms(DriverUniformMode::Structure); if (!translateImpl(sink, root, compileOptions, perfDiagnostics, &specConst, &driverUniforms)) { diff --git a/src/compiler/translator/msl/UtilsMSL.cpp b/src/compiler/translator/msl/UtilsMSL.cpp index afcd9586dc9..76c29770bca 100644 --- a/src/compiler/translator/msl/UtilsMSL.cpp +++ b/src/compiler/translator/msl/UtilsMSL.cpp @@ -293,13 +293,4 @@ const char *getBuiltInMetalTypeNameString(const TType *t) ASSERT(t->getBasicType() != EbtInterfaceBlock); return getBasicMetalString(t); } - -ImmutableString GetMetalTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap) -{ - if (type.getBasicType() == EbtStruct) - return HashName(type.getStruct(), hashFunction, nameMap); - else - return ImmutableString(getBuiltInMetalTypeNameString(&type)); -} - } // namespace sh diff --git a/src/compiler/translator/msl/UtilsMSL.h b/src/compiler/translator/msl/UtilsMSL.h index 2f6c1d21650..2a5bd31ac4b 100644 --- a/src/compiler/translator/msl/UtilsMSL.h +++ b/src/compiler/translator/msl/UtilsMSL.h @@ -22,10 +22,6 @@ const char *getBasicMetalString(const TType *t); const char *getBuiltInMetalTypeNameString(const TType *t); -ImmutableString GetMetalTypeName(const TType &type, - ShHashFunction64 hashFunction, - NameMap *nameMap); - } // namespace sh #endif // COMPILER_TRANSLATOR_MSL_UTILSMSL_H_ diff --git a/src/compiler/translator/spirv/BuildSPIRV.cpp b/src/compiler/translator/spirv/BuildSPIRV.cpp index d1baf8ebf10..4c0c29d8d01 100644 --- a/src/compiler/translator/spirv/BuildSPIRV.cpp +++ b/src/compiler/translator/spirv/BuildSPIRV.cpp @@ -6,6 +6,10 @@ // BuildSPIRV: Helper for OutputSPIRV to build SPIR-V. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/spirv/BuildSPIRV.h" #include "common/spirv/spirv_instruction_builder_autogen.h" @@ -37,7 +41,8 @@ bool operator==(const SpirvType &a, const SpirvType &b) a.typeSpec.isInvariantBlock == b.typeSpec.isInvariantBlock && a.typeSpec.isRowMajorQualifiedBlock == b.typeSpec.isRowMajorQualifiedBlock && a.typeSpec.isPatchIOBlock == b.typeSpec.isPatchIOBlock && - a.typeSpec.isOrHasBoolInInterfaceBlock == b.typeSpec.isOrHasBoolInInterfaceBlock; + a.typeSpec.isOrHasBoolInInterfaceBlock == b.typeSpec.isOrHasBoolInInterfaceBlock && + a.typeSpec.precision == b.typeSpec.precision; } // Otherwise, match by the type contents. The AST transformations sometimes recreate types that @@ -47,7 +52,8 @@ bool operator==(const SpirvType &a, const SpirvType &b) a.isSamplerBaseImage == b.isSamplerBaseImage && a.typeSpec.blockStorage == b.typeSpec.blockStorage && a.typeSpec.isRowMajorQualifiedArray == b.typeSpec.isRowMajorQualifiedArray && - a.typeSpec.isOrHasBoolInInterfaceBlock == b.typeSpec.isOrHasBoolInInterfaceBlock; + a.typeSpec.isOrHasBoolInInterfaceBlock == b.typeSpec.isOrHasBoolInInterfaceBlock && + a.typeSpec.precision == b.typeSpec.precision; } namespace @@ -99,13 +105,15 @@ TLayoutBlockStorage GetBlockStorage(const TType &type) ShaderVariable ToShaderVariable(const TFieldListCollection *block, GLenum type, const angle::Span arraySizes, - bool isRowMajor) + bool isRowMajor, + bool isFloat16) { ShaderVariable var; var.type = type; var.arraySizes = {arraySizes.begin(), arraySizes.end()}; var.isRowMajorLayout = isRowMajor; + var.isFloat16 = isFloat16; if (block != nullptr) { @@ -120,8 +128,40 @@ ShaderVariable ToShaderVariable(const TFieldListCollection *block, const GLenum glType = fieldType.getStruct() != nullptr ? GL_NONE : GLVariableType(fieldType); + // In the following case: + + // precision mediump float + // struct S { + // float floatMember; + // vec2 vec2Member; + // int intMember; + // } + // uniform float floatUniform; + // uniform highp float highpFloatUniform; + // uniform S structUniform; + + // defaultUniform interface block looks like: + // defaultUniform { + // float floatUniform; + // highp float highpFloatUniform; + // S structUniform; + // } + + // iSFieldFloat16 for each defaultUniform member should be: + // defaultUniform.floatUniform: true + // defaultUniform.highpFloatUniform: false + // defaultUniform.structUniform.floatMember: true + // defaultUniform.structUniform.vec2Member: true + // defaultUniform.structUniform.intMember: false + + const bool isFieldFloat16 = + isFloat16 && + ((fieldType.getBasicType() == EbtFloat || fieldType.getBasicType() == EbtStruct) && + (fieldType.getPrecision() < EbpHigh)); + var.fields.push_back(ToShaderVariable(fieldType.getStruct(), glType, - fieldType.getArraySizes(), isFieldRowMajor)); + fieldType.getArraySizes(), isFieldRowMajor, + isFieldFloat16)); } } @@ -136,11 +176,18 @@ ShaderVariable SpirvTypeToShaderVariable(const SpirvType &type) type.block != nullptr ? EbtStruct : GLVariableType(TType(type.type, type.primarySize, type.secondarySize)); + const bool isFloat16 = (type.typeSpec.precision == SPIRVPrecisionChoice::UseFP16); - return ToShaderVariable(type.block, glType, type.arraySizes, isRowMajor); + return ToShaderVariable(type.block, glType, type.arraySizes, isRowMajor, isFloat16); } -// The following function encodes a variable in a std140 or std430 block. The variable could be: +// The following function encodes a variable in a +// 1) std140 layout block +// 2) std430 layout block +// 3) tighter packed layout block. This only applies to default uniform buffer block, and when +// 16-bit float is allowed in the default uniform buffer block +// +// The variable could be: // // - An interface block: In this case, |decorationsBlob| is provided and SPIR-V decorations are // output to this blob. @@ -151,12 +198,23 @@ ShaderVariable SpirvTypeToShaderVariable(const SpirvType &type) // uint32_t Encode(const ShaderVariable &var, bool isStd140, + bool isDefaultUniform, + bool usePackedEncoder, spirv::IdRef blockTypeId, spirv::Blob *decorationsBlob) { Std140BlockEncoder std140; Std430BlockEncoder std430; - BlockLayoutEncoder *encoder = isStd140 ? &std140 : &std430; + PackedSPIRVBlockEncoder packSPIRV; + BlockLayoutEncoder *encoder = nullptr; + if (isDefaultUniform && usePackedEncoder) + { + encoder = &packSPIRV; + } + else + { + encoder = isStd140 ? &std140 : &std430; + } ASSERT(var.isStruct()); encoder->enterAggregateType(var); @@ -171,7 +229,8 @@ uint32_t Encode(const ShaderVariable &var, if (fieldVar.isStruct()) { // For structs, recursively encode it. - const uint32_t structSize = Encode(fieldVar, isStd140, {}, nullptr); + const uint32_t structSize = + Encode(fieldVar, isStd140, isDefaultUniform, usePackedEncoder, {}, nullptr); encoder->enterAggregateType(fieldVar); fieldInfo = encoder->encodeArrayOfPreEncodedStructs(structSize, fieldVar.arraySizes); @@ -180,7 +239,10 @@ uint32_t Encode(const ShaderVariable &var, else { fieldInfo = - encoder->encodeType(fieldVar.type, fieldVar.arraySizes, fieldVar.isRowMajorLayout); + encoder->encodeType(fieldVar.type, + fieldVar.isFloat16 ? BlockLayoutEncoder::kBytesPer16BitComponent + : BlockLayoutEncoder::kBytesPerComponent, + fieldVar.arraySizes, fieldVar.isRowMajorLayout); } if (decorationsBlob) @@ -211,11 +273,23 @@ uint32_t Encode(const ShaderVariable &var, return static_cast(encoder->getCurrentOffset()); } -uint32_t GetArrayStrideInBlock(const ShaderVariable &var, bool isStd140) +uint32_t GetArrayStrideInBlock(const ShaderVariable &var, + bool isStd140, + bool isDefaultUniform, + bool usePackedEncoder) { Std140BlockEncoder std140; Std430BlockEncoder std430; - BlockLayoutEncoder *encoder = isStd140 ? &std140 : &std430; + PackedSPIRVBlockEncoder packSPIRV; + BlockLayoutEncoder *encoder = nullptr; + if (isDefaultUniform && usePackedEncoder) + { + encoder = &packSPIRV; + } + else + { + encoder = isStd140 ? &std140 : &std430; + } ASSERT(var.isArray()); @@ -226,7 +300,8 @@ uint32_t GetArrayStrideInBlock(const ShaderVariable &var, bool isStd140) ShaderVariable element = var; element.arraySizes.clear(); - const uint32_t structSize = Encode(element, isStd140, {}, nullptr); + const uint32_t structSize = + Encode(element, isStd140, isDefaultUniform, usePackedEncoder, {}, nullptr); // Stride is struct size by inner array size return structSize * var.getInnerArraySizeProduct(); @@ -234,7 +309,10 @@ uint32_t GetArrayStrideInBlock(const ShaderVariable &var, bool isStd140) // Otherwise encode the basic type. BlockMemberInfo memberInfo = - encoder->encodeType(var.type, var.arraySizes, var.isRowMajorLayout); + encoder->encodeType(var.type, + var.isFloat16 ? BlockLayoutEncoder::kBytesPer16BitComponent + : BlockLayoutEncoder::kBytesPerComponent, + var.arraySizes, var.isRowMajorLayout); // The encoder returns the array stride for the base element type (which is not an array!), so // need to multiply by the inner array sizes to get the outermost array's stride. @@ -377,7 +455,9 @@ void ApplyDecorations(spirv::IdRef id, } } // anonymous namespace -void SpirvTypeSpec::inferDefaults(const TType &type, TCompiler *compiler) +void SpirvTypeSpec::inferDefaults(const TType &type, + TCompiler *compiler, + const bool transformFloatUniformToFP16) { // Infer some defaults based on type. If necessary, this overrides some fields (if not already // specified). Otherwise, it leaves the pre-initialized values as-is. @@ -418,6 +498,52 @@ void SpirvTypeSpec::inferDefaults(const TType &type, TCompiler *compiler) type.getBasicType() == EbtBool; } + isDefaultUniform = (type.getInterfaceBlock() != nullptr && + type.getInterfaceBlock()->isDefaultUniformBlock()); + + if (precision == SPIRVPrecisionChoice::Unset) + { + // For a struct uniform and a float uniform declared as below: + // struct combo { + // float a; + // }; + // uniform float floatUniform; + // uniform combo comboUniform; + + // ANGLE creates a UBO defaultUniform and places both uniforms into the UBO: + // uniform UniformBufferObject { + // float floatUniform; + // combo comboUniform; + // } defaultUniform + + // defaultUniform: EbtInterfaceBlock + // defaultUniform.floatUniform: EbtFloat + // defaultUniform.comboUniform: EbtStruct + + // We need to set precision to UseFP16 for EbtInterfaceBlock so that the + // OpTypeStruct instruction generated for defaultUniform is using halfFloat for its' + // members: + // %defaultUniformStruct = OpTypeStruct %typeComboStruct %halfFloat + + // We need to set precision to UseFP16 for EbtFloat so that OpAccessChain + // instruction generated for accessing defaultUniform.floatUniform is using halfFloat: + // %floatUniformPtr = OpAccessChain %halfFloatUniformPtr %defaultUniformVar %const0 + + // We need to set precision to UseFP16 to EbtStruct so that OpAccessChain + // instruction generate for accessing defaultUniform.comboUniform.a is using halfFloat + // %floatUniformPtr = OpAccessChain %halfFloatUniformPtr %defaultUniformVar %const1 + // %const0 + + if ((type.getBasicType() == EbtInterfaceBlock || type.getBasicType() == EbtFloat || + type.getBasicType() == EbtStruct) && + type.getQualifier() == EvqUniform && isDefaultUniform && + type.getPrecision() < EbpHigh) + { + precision = transformFloatUniformToFP16 ? SPIRVPrecisionChoice::UseFP16 + : SPIRVPrecisionChoice::Default; + } + } + if (!isPatchIOBlock && type.isInterfaceBlock()) { isPatchIOBlock = @@ -425,6 +551,13 @@ void SpirvTypeSpec::inferDefaults(const TType &type, TCompiler *compiler) } } + // Make sure precision is set to Default before exiting this function. + // This is required before saving SpirvType to SPIRVBuilder.mTypeMap. + if (precision == SPIRVPrecisionChoice::Unset) + { + precision = SPIRVPrecisionChoice::Default; + } + // |invariant| is significant for structs as the fields of the type are decorated with Invariant // in SPIR-V. This is possible for outputs of struct type, or struct-typed fields of an // interface block. @@ -472,6 +605,25 @@ void SpirvTypeSpec::onBlockFieldSelection(const TType &fieldType) { isOrHasBoolInInterfaceBlock = false; } + + // If the entire interface block is marked with UseFP16, but the individual component is not + // 16-bit float, reset the precision to Default + // For example, following uniforms: + // uniform float uniF; + // uniform int uniI; + // is grouped in: + // struct defaultUniform { + // float unifF; + // int uniI; + // } + // defaultUniform is processed first and has precision set to UseFP16. + // When processing defaultUniform's fields, we should set precision to Default + // for uniI. + if (precision == SPIRVPrecisionChoice::UseFP16 && + (fieldType.getBasicType() != EbtFloat || fieldType.getPrecision() >= EbpHigh)) + { + precision = SPIRVPrecisionChoice::Default; + } } else { @@ -485,6 +637,8 @@ void SpirvTypeSpec::onBlockFieldSelection(const TType &fieldType) { isOrHasBoolInInterfaceBlock = fieldType.isStructureContainingType(EbtBool); } + + isInvariantBlock = fieldType.isInvariant(); } } @@ -521,6 +675,13 @@ SPIRVBuilder::SPIRVBuilder(TCompiler *compiler, // The Shader capability is always defined. addCapability(spv::CapabilityShader); + // Add Float16 Capability if we are going to transform mediump and lowp float uniforms to 16 + // bits. + if (mCompileOptions.transformFloatUniformTo16Bits) + { + addCapability(spv::CapabilityFloat16); + } + // Add Geometry or Tessellation capabilities based on shader type. if (mCompiler->getShaderType() == GL_GEOMETRY_SHADER) { @@ -598,7 +759,8 @@ SpirvType SPIRVBuilder::getSpirvType(const TType &type, const SpirvTypeSpec &typ // Automatically inherit or infer the type-specializing properties. spirvType.typeSpec = typeSpec; - spirvType.typeSpec.inferDefaults(type, mCompiler); + spirvType.typeSpec.inferDefaults(type, mCompiler, + mCompileOptions.transformFloatUniformTo16Bits); return spirvType; } @@ -649,6 +811,14 @@ const SpirvTypeData &SPIRVBuilder::getSpirvTypeData(const SpirvType &type, const return getSpirvTypeData(uintType, block); } + if (type.typeSpec.precision == SPIRVPrecisionChoice::Unset) + { + SpirvType correctedType = type; + correctedType.typeSpec.precision = SPIRVPrecisionChoice::Default; + return getSpirvTypeData(correctedType, block); + } + + ASSERT(type.typeSpec.precision != SPIRVPrecisionChoice::Unset); auto iter = mTypeMap.find(type); if (iter == mTypeMap.end()) { @@ -786,12 +956,14 @@ void SPIRVBuilder::predefineCommonTypes() // void: used by OpExtInst non-semantic instructions. This type is always present due to void // main(). type.type = EbtVoid; + type.typeSpec.precision = SPIRVPrecisionChoice::Default; id = spirv::IdRef(kIdVoid); mTypeMap.insert({type, {id}}); spirv::WriteTypeVoid(&mSpirvTypeAndConstantDecls, id); // float, vec and mat types type.type = EbtFloat; + type.typeSpec.precision = SPIRVPrecisionChoice::Default; id = spirv::IdRef(kIdFloat); mTypeMap.insert({type, {id}}); spirv::WriteTypeFloat(&mSpirvTypeAndConstantDecls, id, spirv::LiteralInteger(32), nullptr); @@ -823,6 +995,7 @@ void SPIRVBuilder::predefineCommonTypes() type.primarySize = 1; type.secondarySize = 1; + type.typeSpec.precision = SPIRVPrecisionChoice::Default; // Integer types type.type = EbtUInt; @@ -894,6 +1067,43 @@ void SPIRVBuilder::predefineCommonTypes() mTypePointerIdMap.insert({key, typePointerId}); } } + + if (mCompileOptions.transformFloatUniformTo16Bits) + { + // Add declarations for 16-bit float types + // 16-bit float (half float) + type.type = EbtFloat; + type.primarySize = 1; + type.secondarySize = 1; + type.typeSpec.precision = SPIRVPrecisionChoice::UseFP16; + id = spirv::IdRef(kIdFloat16); + mTypeMap.insert({type, {id}}); + spirv::WriteTypeFloat(&mSpirvTypeAndConstantDecls, id, spirv::LiteralInteger(16), nullptr); + // vecN ids equal vec2 id + (vec size - 2) + static_assert(kIdFloat16Vec3 == kIdFloat16Vec2 + 1); + static_assert(kIdFloat16Vec4 == kIdFloat16Vec2 + 2); + // mat type ids equal mat2 id + (primary - 2) + // Note that only square matrices are needed. + static_assert(kIdFloat16Mat3 == kIdFloat16Mat2 + 1); + static_assert(kIdFloat16Mat4 == kIdFloat16Mat2 + 2); + for (uint8_t vecSize = 2; vecSize <= 4; ++vecSize) + { + // 16-bit vec2 (half2), 16-bit vec3 (half3), 16-bit vec4 (half4) + type.primarySize = vecSize; + type.secondarySize = 1; + const spirv::IdRef vecId = spirv::IdRef(kIdFloat16Vec2 + (vecSize - 2)); + mTypeMap.insert({type, {vecId}}); + spirv::WriteTypeVector(&mSpirvTypeAndConstantDecls, vecId, spirv::IdRef(kIdFloat16), + spirv::LiteralInteger(vecSize)); + + // 16-bit mat2, 16-bit mat3, 16-bit mat4 + type.secondarySize = vecSize; + const spirv::IdRef matId = spirv::IdRef(kIdFloat16Mat2 + (vecSize - 2)); + mTypeMap.insert({type, {matId}}); + spirv::WriteTypeMatrix(&mSpirvTypeAndConstantDecls, matId, vecId, + spirv::LiteralInteger(vecSize)); + } + } } void SPIRVBuilder::writeDebugName(spirv::IdRef id, const char *name) @@ -928,6 +1138,7 @@ void SPIRVBuilder::writeBlockDebugNames(const TFieldListCollection *block, SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *block) { + ASSERT(type.typeSpec.precision != SPIRVPrecisionChoice::Unset); // Recursively declare the type. Type id is allocated afterwards purely for better id order in // output. spirv::IdRef typeId; @@ -999,14 +1210,24 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl { // Declaring a sampler. First, declare the non-sampled image and then a combined // image-sampler. + // + // For sampler buffers, combined image-sampler shouldn't be created. While this is allowed + // for SPIR-V before 1.6, it was never intended to be correct. SpirvType imageType = type; imageType.isSamplerBaseImage = true; const spirv::IdRef nonSampledId = getSpirvTypeData(imageType, nullptr).id; - typeId = getNewId({}); - spirv::WriteTypeSampledImage(&mSpirvTypeAndConstantDecls, typeId, nonSampledId); + if (IsSamplerBuffer(type.type)) + { + typeId = nonSampledId; + } + else + { + typeId = getNewId({}); + spirv::WriteTypeSampledImage(&mSpirvTypeAndConstantDecls, typeId, nonSampledId); + } } else if (IsImage(type.type) || IsSubpassInputType(type.type) || type.isSamplerBaseImage) { @@ -1085,13 +1306,15 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl const bool isInterfaceBlock = block != nullptr && block->isInterfaceBlock(); const bool isStd140 = type.typeSpec.blockStorage != EbsStd430; + const bool usePackEncoder = mCompileOptions.transformFloatUniformTo16Bits; if (!type.arraySizes.empty() && !isInterfaceBlock) { // Write the ArrayStride decoration for arrays inside interface blocks. An array of // interface blocks doesn't need a stride. const ShaderVariable var = SpirvTypeToShaderVariable(type); - const uint32_t stride = GetArrayStrideInBlock(var, isStd140); + const uint32_t stride = GetArrayStrideInBlock( + var, isStd140, type.typeSpec.isDefaultUniform, usePackEncoder); spirv::WriteDecorate(&mSpirvDecorations, typeId, spv::DecorationArrayStride, {spirv::LiteralInteger(stride)}); @@ -1100,7 +1323,8 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl { // Write the Offset decoration for interface blocks and structs in them. const ShaderVariable var = SpirvTypeToShaderVariable(type); - Encode(var, isStd140, typeId, &mSpirvDecorations); + Encode(var, isStd140, type.typeSpec.isDefaultUniform, usePackEncoder, typeId, + &mSpirvDecorations); } } @@ -1146,11 +1370,9 @@ void SPIRVBuilder::getImageTypeParameters(TBasicType type, isArrayed = true; break; case EbtSampler2DMS: - case EbtImage2DMS: isMultisampled = true; break; case EbtSampler2DMSArray: - case EbtImage2DMSArray: isArrayed = true; isMultisampled = true; break; @@ -1174,12 +1396,10 @@ void SPIRVBuilder::getImageTypeParameters(TBasicType type, isArrayed = true; break; case EbtISampler2DMS: - case EbtIImage2DMS: sampledType = EbtInt; isMultisampled = true; break; case EbtISampler2DMSArray: - case EbtIImage2DMSArray: sampledType = EbtInt; isArrayed = true; isMultisampled = true; @@ -1197,12 +1417,10 @@ void SPIRVBuilder::getImageTypeParameters(TBasicType type, isArrayed = true; break; case EbtUSampler2DMS: - case EbtUImage2DMS: sampledType = EbtUInt; isMultisampled = true; break; case EbtUSampler2DMSArray: - case EbtUImage2DMSArray: sampledType = EbtUInt; isArrayed = true; isMultisampled = true; @@ -1272,20 +1490,13 @@ void SPIRVBuilder::getImageTypeParameters(TBasicType type, // Rect images case EbtSampler2DRect: - case EbtImageRect: - *dimOut = spv::DimRect; - break; - case EbtSampler2DRectShadow: *dimOut = spv::DimRect; - isDepth = true; break; case EbtISampler2DRect: - case EbtIImageRect: sampledType = EbtInt; *dimOut = spv::DimRect; break; case EbtUSampler2DRect: - case EbtUImageRect: sampledType = EbtUInt; *dimOut = spv::DimRect; break; @@ -1334,10 +1545,10 @@ void SPIRVBuilder::getImageTypeParameters(TBasicType type, // // Dim Sampled Storage Storage Array // -------------------------------------------------------------- - // 2D Shader ImageMSArray + // 2D Shader ImageMSArray (desktop GLSL) // 3D // Cube Shader ImageCubeArray - // Rect SampledRect ImageRect + // Rect SampledRect ImageRect (desktop GLSL) // Buffer SampledBuffer ImageBuffer // // Additionally, the SubpassData Dim requires the InputAttachment capability. @@ -1361,7 +1572,8 @@ void SPIRVBuilder::getImageTypeParameters(TBasicType type, } break; case spv::DimRect: - addCapability(isSampledImage ? spv::CapabilitySampledRect : spv::CapabilityImageRect); + ASSERT(!isSampledImage); + addCapability(spv::CapabilitySampledRect); break; case spv::DimBuffer: addCapability(isSampledImage ? spv::CapabilitySampledBuffer @@ -2444,6 +2656,9 @@ void SPIRVBuilder::writeExtensions(spirv::Blob *blob) case SPIRVExtensions::FragmentShaderInterlockARB: spirv::WriteExtension(blob, "SPV_EXT_fragment_shader_interlock"); break; + case SPIRVExtensions::FragmentShadingRate: + spirv::WriteExtension(blob, "SPV_KHR_fragment_shading_rate"); + break; default: UNREACHABLE(); } @@ -2462,6 +2677,9 @@ void SPIRVBuilder::writeSourceExtensions(spirv::Blob *blob) case SPIRVExtensions::FragmentShaderInterlockARB: spirv::WriteSourceExtension(blob, "GL_ARB_fragment_shader_interlock"); break; + case SPIRVExtensions::FragmentShadingRate: + spirv::WriteSourceExtension(blob, "GL_EXT_fragment_shading_rate"); + break; default: UNREACHABLE(); } diff --git a/src/compiler/translator/spirv/BuildSPIRV.h b/src/compiler/translator/spirv/BuildSPIRV.h index dc625caa23e..5559023b64e 100644 --- a/src/compiler/translator/spirv/BuildSPIRV.h +++ b/src/compiler/translator/spirv/BuildSPIRV.h @@ -29,6 +29,14 @@ namespace sh // This type contains the pieces of information that differentiate SPIR-V types derived from the // same GLSL type. This is referred to as "SPIR-V type specialization" henceforth. struct SpirvType; +enum class SPIRVPrecisionChoice +{ + Unset = 0, + UseFP16 = 1, + Default = 2, + InvalidEnum = 3, + EnumCount = 3, +}; class SpirvTypeSpec { public: @@ -36,7 +44,7 @@ class SpirvTypeSpec // their fields or basic types. When extracting fields, array elements, columns or basic types // from a type, the following helpers are used to remove any ineffective (and thus incorrect) // specialization. - void inferDefaults(const TType &type, TCompiler *compiler); + void inferDefaults(const TType &type, TCompiler *compiler, bool transformFloatUniformToFP16); void onArrayElementSelection(bool isElementTypeBlock, bool isElementTypeArray); void onBlockFieldSelection(const TType &fieldType); void onMatrixColumnSelection(); @@ -49,6 +57,10 @@ class SpirvTypeSpec // except for non-block non-array types. TLayoutBlockStorage blockStorage = EbsUnspecified; + // The encoder ANGLE uses to calculate the member offsets within the default uniform block is + // different from encoder used to calculate the member offsets in other interface blocks. + bool isDefaultUniform = false; + // If a structure is used in two I/O blocks or output varyings with and without the invariant // qualifier, it would also have to generate two SPIR-V types, as its fields' Invariant // decorations would be different. @@ -72,6 +84,12 @@ class SpirvTypeSpec // it. This is not recursively applied, and since each I/O block has a unique type, this // doesn't actually result in duplicated types even if it's specializing the type. bool isPatchIOBlock = false; + + // The number of bits we use for the Spirv Data Type + // Unset: Initial value. Must change to UseFP16 or Default before saving to + // SPIRVBuilder.mTypeMap UseFP16: 16-bit Default: default bit size for various data types. e.g. + // 32 bit for FLoat + SPIRVPrecisionChoice precision = SPIRVPrecisionChoice::Unset; }; struct SpirvType @@ -160,17 +178,19 @@ struct SpirvTypeHash type.primarySize != type.secondarySize && type.typeSpec.blockStorage != sh::EbsUnspecified)); + // precision must be set to UseFP16 or Default when saving to hash map SPIRVBuilder.mTypeMap + ASSERT(type.typeSpec.precision != SPIRVPrecisionChoice::Unset); + size_t result = 0; if (!type.arraySizes.empty()) { - result = angle::ComputeGenericHash(type.arraySizes.data(), - type.arraySizes.size() * sizeof(type.arraySizes[0])); + result = angle::ComputeGenericHash(angle::as_byte_span(type.arraySizes)); } if (type.block != nullptr) { - return result ^ angle::ComputeGenericHash(&type.block, sizeof(type.block)) ^ + return result ^ angle::ComputeGenericHash(angle::byte_span_from_ref(type.block)) ^ static_cast(type.typeSpec.isInvariantBlock) ^ (static_cast(type.typeSpec.isRowMajorQualifiedBlock) << 1) ^ (static_cast(type.typeSpec.isRowMajorQualifiedArray) << 2) ^ @@ -192,7 +212,7 @@ struct SpirvTypeHash // Padding because ComputeGenericHash expects a key size divisible by 4 }; - return result ^ angle::ComputeGenericHash(properties, sizeof(properties)); + return result ^ angle::ComputeGenericHash(properties); } }; @@ -200,9 +220,7 @@ struct SpirvIdAndIdListHash { size_t operator()(const SpirvIdAndIdList &key) const { - return angle::ComputeGenericHash(key.idList.data(), - key.idList.size() * sizeof(key.idList[0])) ^ - key.id; + return angle::ComputeGenericHash(angle::as_byte_span(key.idList)) ^ key.id; } }; @@ -299,8 +317,11 @@ enum class SPIRVExtensions // GL_ARB_fragment_shader_interlock / SPV_EXT_fragment_shader_interlock FragmentShaderInterlockARB = 1, - InvalidEnum = 2, - EnumCount = 2, + // GL_EXT_fragment_shading_rate / SPV_KHR_fragment_shading_rate + FragmentShadingRate = 2, + + InvalidEnum = 3, + EnumCount = 3, }; // Helper class to construct SPIR-V diff --git a/src/compiler/translator/spirv/BuiltinsWorkaround.cpp b/src/compiler/translator/spirv/BuiltinsWorkaround.cpp index 7afefd7126d..6ac0a00fe84 100644 --- a/src/compiler/translator/spirv/BuiltinsWorkaround.cpp +++ b/src/compiler/translator/spirv/BuiltinsWorkaround.cpp @@ -22,73 +22,77 @@ constexpr const ImmutableString kGlVertexIDString("gl_VertexID"); class TBuiltinsWorkaround : public TIntermTraverser { public: - TBuiltinsWorkaround(TSymbolTable *symbolTable, const ShCompileOptions &options); + TBuiltinsWorkaround(TSymbolTable *symbolTable, + const ShCompileOptions &options, + const TVariable *emulatedBaseInstance) + : TIntermTraverser(true, false, false, symbolTable), + mCompileOptions(options), + mEmulatedBaseInstance(emulatedBaseInstance) + {} void visitSymbol(TIntermSymbol *node) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; private: void ensureVersionIsAtLeast(int version); const ShCompileOptions &mCompileOptions; - - bool isBaseInstanceDeclared = false; + const TVariable *mEmulatedBaseInstance; }; -TBuiltinsWorkaround::TBuiltinsWorkaround(TSymbolTable *symbolTable, const ShCompileOptions &options) - : TIntermTraverser(true, false, false, symbolTable), mCompileOptions(options) -{} - void TBuiltinsWorkaround::visitSymbol(TIntermSymbol *node) { - if (node->variable().symbolType() == SymbolType::BuiltIn) + if (node->variable().symbolType() == SymbolType::BuiltIn && + node->getName() == kGlInstanceIDString) { - if (node->getName() == kGlInstanceIDString) + TIntermSymbol *instanceIndexRef = new TIntermSymbol(BuiltInVariable::gl_InstanceIndex()); + + if (mEmulatedBaseInstance != nullptr) { - TIntermSymbol *instanceIndexRef = - new TIntermSymbol(BuiltInVariable::gl_InstanceIndex()); - - if (isBaseInstanceDeclared) - { - TIntermSymbol *baseInstanceRef = - new TIntermSymbol(BuiltInVariable::angle_BaseInstance()); - - TIntermBinary *subBaseInstance = - new TIntermBinary(EOpSub, instanceIndexRef, baseInstanceRef); - queueReplacement(subBaseInstance, OriginalNode::IS_DROPPED); - } - else - { - queueReplacement(instanceIndexRef, OriginalNode::IS_DROPPED); - } + TIntermSymbol *baseInstanceRef = new TIntermSymbol(mEmulatedBaseInstance); + + TIntermBinary *subBaseInstance = + new TIntermBinary(EOpSub, instanceIndexRef, baseInstanceRef); + queueReplacement(subBaseInstance, OriginalNode::IS_DROPPED); } - else if (node->getName() == kGlVertexIDString) + else { - TIntermSymbol *vertexIndexRef = new TIntermSymbol(BuiltInVariable::gl_VertexIndex()); - queueReplacement(vertexIndexRef, OriginalNode::IS_DROPPED); + queueReplacement(instanceIndexRef, OriginalNode::IS_DROPPED); } } + else if (node->getName() == kGlVertexIDString) + { + TIntermSymbol *vertexIndexRef = new TIntermSymbol(BuiltInVariable::gl_VertexIndex()); + queueReplacement(vertexIndexRef, OriginalNode::IS_DROPPED); + } } -bool TBuiltinsWorkaround::visitDeclaration(Visit, TIntermDeclaration *node) +const TVariable *FindEmulatedBaseInstance(TIntermBlock *root) { - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); - - for (TIntermNode *variableNode : sequence) + for (TIntermNode *node : *root->getSequence()) { - TIntermSymbol *variable = variableNode->getAsSymbolNode(); - if (variable && variable->variable().symbolType() == SymbolType::BuiltIn) + TIntermDeclaration *decl = node->getAsDeclarationNode(); + if (decl == nullptr) + { + continue; + } + + const TIntermSequence &sequence = *(decl->getSequence()); + ASSERT(!sequence.empty()); + + TIntermSymbol *symbol = sequence[0]->getAsSymbolNode(); + if (symbol == nullptr) + { + continue; + } + + if (symbol->variable().symbolType() == SymbolType::AngleInternal && + symbol->variable().name() == "angle_BaseInstance") { - if (variable->getName() == "angle_BaseInstance") - { - isBaseInstanceDeclared = true; - } + return &symbol->variable(); } } - return true; + return nullptr; } - } // anonymous namespace [[nodiscard]] bool ShaderBuiltinsWorkaround(TCompiler *compiler, @@ -96,7 +100,7 @@ bool TBuiltinsWorkaround::visitDeclaration(Visit, TIntermDeclaration *node) TSymbolTable *symbolTable, const ShCompileOptions &compileOptions) { - TBuiltinsWorkaround builtins(symbolTable, compileOptions); + TBuiltinsWorkaround builtins(symbolTable, compileOptions, FindEmulatedBaseInstance(root)); root->traverse(&builtins); if (!builtins.updateTree(compiler, root)) { diff --git a/src/compiler/translator/spirv/OutputSPIRV.cpp b/src/compiler/translator/spirv/OutputSPIRV.cpp index f7abda85287..e60e2c7464c 100644 --- a/src/compiler/translator/spirv/OutputSPIRV.cpp +++ b/src/compiler/translator/spirv/OutputSPIRV.cpp @@ -6,6 +6,10 @@ // OutputSPIRV: Generate SPIR-V from the AST. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/spirv/OutputSPIRV.h" #include "angle_gl.h" @@ -160,7 +164,7 @@ struct BuiltInResultStructHash static_cast(key.msbPrimarySize), }; - return angle::ComputeGenericHash(properties, sizeof(properties)); + return angle::ComputeGenericHash(properties); } }; @@ -223,7 +227,7 @@ class OutputSPIRVTraverser : public TIntermTraverser spirv::LiteralInteger index, spirv::IdRef typeId) const; void accessChainPushSwizzle(NodeData *data, - const TVector &swizzle, + const TVector &swizzle, spirv::IdRef typeId, uint8_t componentCount) const; void accessChainPushDynamicComponent(NodeData *data, spirv::IdRef index, spirv::IdRef typeId); @@ -249,6 +253,7 @@ class OutputSPIRVTraverser : public TIntermTraverser void declareConst(TIntermDeclaration *decl); void declareSpecConst(TIntermDeclaration *decl); spirv::IdRef createConstant(const TType &type, + spirv::IdRef typeId, TBasicType expectedBasicType, const TConstantUnion *constUnion, bool isConstantNullValue); @@ -303,6 +308,9 @@ class OutputSPIRVTraverser : public TIntermTraverser spirv::IdRef createFunctionCall(TIntermAggregate *node, spirv::IdRef resultTypeId); + const spirv::IdRef getSpirvTypeIdWithExpectedPrecisionBit(const TType &expectedType, + const TType &actualType); + void visitArrayLength(TIntermUnary *node); // Cast between types. There are two kinds of casts: @@ -318,6 +326,9 @@ class OutputSPIRVTraverser : public TIntermTraverser const TType &valueType, const TType &expectedType, spirv::IdRef *resultTypeIdOut); + spirv::IdRef castFloatType(spirv::IdRef value, + const TType &valueType, + spirv::IdRef *resultTypeIdOut); spirv::IdRef cast(spirv::IdRef value, const TType &valueType, const SpirvTypeSpec &valueTypeSpec, @@ -382,7 +393,7 @@ class OutputSPIRVTraverser : public TIntermTraverser // - TVariable, or // - TInterfaceBlock: because TIntermSymbols referencing a field of an unnamed interface block // don't reference the TVariable that defines the struct, but the TInterfaceBlock itself. - angle::HashMap mSymbolIdMap; + angle::HashMap mSymbolIdMap; // A map of TFunction to its various SPIR-V ids. angle::HashMap mFunctionIdMap; @@ -446,6 +457,7 @@ spv::StorageClass GetStorageClass(const ShCompileOptions &compileOptions, case EvqFragCoord: case EvqFrontFacing: case EvqPointCoord: + case EvqShadingRateEXT: case EvqSampleID: case EvqSamplePosition: case EvqSampleMaskIn: @@ -471,6 +483,7 @@ spv::StorageClass GetStorageClass(const ShCompileOptions &compileOptions, case EvqFragDepth: case EvqSampleMask: case EvqLayerOut: + case EvqPrimitiveShadingRateEXT: return spv::StorageClassOutput; case EvqClipDistance: @@ -531,7 +544,7 @@ spirv::IdRef OutputSPIRVTraverser::getSymbolIdAndStorageClass(const TSymbol *sym spv::StorageClass *storageClass) { *storageClass = GetStorageClass(mCompileOptions, type, mCompiler->getShaderType()); - auto iter = mSymbolIdMap.find(symbol); + auto iter = mSymbolIdMap.find(symbol->uniqueId()); if (iter != mSymbolIdMap.end()) { return iter->second; @@ -600,6 +613,18 @@ spirv::IdRef OutputSPIRVTraverser::getSymbolIdAndStorageClass(const TSymbol *sym mBuilder.addCapability(spv::CapabilitySampleRateShading); uniqueId = &symbol->uniqueId(); break; + case EvqShadingRateEXT: + name = "gl_ShadingRateEXT"; + builtInDecoration = spv::BuiltInShadingRateKHR; + mBuilder.addCapability(spv::CapabilityFragmentShadingRateKHR); + mBuilder.addExtension(SPIRVExtensions::FragmentShadingRate); + break; + case EvqPrimitiveShadingRateEXT: + name = "gl_PrimitiveShadingRateEXT"; + builtInDecoration = spv::BuiltInPrimitiveShadingRateKHR; + mBuilder.addCapability(spv::CapabilityFragmentShadingRateKHR); + mBuilder.addExtension(SPIRVExtensions::FragmentShadingRate); + break; case EvqSamplePosition: name = "gl_SamplePosition"; builtInDecoration = spv::BuiltInSamplePosition; @@ -718,6 +743,7 @@ spirv::IdRef OutputSPIRVTraverser::getSymbolIdAndStorageClass(const TSymbol *sym switch (type.getQualifier()) { case EvqLayerIn: + case EvqShadingRateEXT: case EvqSampleID: case EvqPrimitiveID: case EvqViewIDOVR: @@ -735,7 +761,7 @@ spirv::IdRef OutputSPIRVTraverser::getSymbolIdAndStorageClass(const TSymbol *sym break; } - mSymbolIdMap.insert({symbol, varId}); + mSymbolIdMap.insert({symbol->uniqueId(), varId}); return varId; } @@ -826,7 +852,7 @@ void OutputSPIRVTraverser::accessChainPushLiteral(NodeData *data, } void OutputSPIRVTraverser::accessChainPushSwizzle(NodeData *data, - const TVector &swizzle, + const TVector &swizzle, spirv::IdRef typeId, uint8_t componentCount) const { @@ -1045,8 +1071,14 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data, } // Upon loading values, cast them to the default SPIR-V variant. + accessChain.typeSpec.precision = (accessChain.typeSpec.precision == SPIRVPrecisionChoice::Unset) + ? SPIRVPrecisionChoice::Default + : accessChain.typeSpec.precision; + SpirvTypeSpec expectedTypeSpec = {}; + expectedTypeSpec.precision = SPIRVPrecisionChoice::Default; + const spirv::IdRef castResult = - cast(loadResult, valueType, accessChain.typeSpec, {}, resultTypeIdOut); + cast(loadResult, valueType, accessChain.typeSpec, expectedTypeSpec, resultTypeIdOut); return castResult; } @@ -1075,7 +1107,12 @@ void OutputSPIRVTraverser::accessChainStore(NodeData *data, // Store through the access chain. The values are always cast to the default SPIR-V type // variant when loaded from memory and operated on as such. When storing, we need to cast the // result to the variant specified by the access chain. - value = cast(value, valueType, {}, accessChain.typeSpec, nullptr); + accessChain.typeSpec.precision = (accessChain.typeSpec.precision == SPIRVPrecisionChoice::Unset) + ? SPIRVPrecisionChoice::Default + : accessChain.typeSpec.precision; + SpirvTypeSpec valueTypeSpec = {}; + valueTypeSpec.precision = SPIRVPrecisionChoice::Default; + value = cast(value, valueType, valueTypeSpec, accessChain.typeSpec, nullptr); if (!accessChain.swizzles.empty()) { @@ -1192,12 +1229,12 @@ void OutputSPIRVTraverser::declareConst(TIntermDeclaration *decl) const spirv::IdRef typeId = mBuilder.getTypeData(type, {}).id; const spirv::IdRef constId = - createConstant(type, type.getBasicType(), initializer->getConstantValue(), + createConstant(type, typeId, type.getBasicType(), initializer->getConstantValue(), initializer->isConstantNullValue()); // Remember the id of the variable for future look up. - ASSERT(mSymbolIdMap.count(variable) == 0); - mSymbolIdMap[variable] = constId; + ASSERT(mSymbolIdMap.count(variable->uniqueId()) == 0); + mSymbolIdMap.emplace(variable->uniqueId(), constId); if (!mInGlobalScope) { @@ -1230,16 +1267,16 @@ void OutputSPIRVTraverser::declareSpecConst(TIntermDeclaration *decl) type.getBasicType(), type.getLayoutQualifier().location, mBuilder.getName(variable).data()); // Remember the id of the variable for future look up. - ASSERT(mSymbolIdMap.count(variable) == 0); - mSymbolIdMap[variable] = specConstId; + ASSERT(mSymbolIdMap.count(variable->uniqueId()) == 0); + mSymbolIdMap.emplace(variable->uniqueId(), specConstId); } spirv::IdRef OutputSPIRVTraverser::createConstant(const TType &type, + spirv::IdRef typeId, TBasicType expectedBasicType, const TConstantUnion *constUnion, bool isConstantNullValue) { - const spirv::IdRef typeId = mBuilder.getTypeData(type, {}).id; spirv::IdRefList componentIds; // If the object is all zeros, use OpConstantNull to avoid creating a bunch of constants. This @@ -1259,13 +1296,14 @@ spirv::IdRef OutputSPIRVTraverser::createConstant(const TType &type, { TType elementType(type); elementType.toArrayElementType(); + const spirv::IdRef elementTypeId = mBuilder.getTypeData(elementType, {}).id; // If it's an array constant, get the constant id of each element. for (unsigned int elementIndex = 0; elementIndex < type.getOutermostArraySize(); ++elementIndex) { componentIds.push_back( - createConstant(elementType, expectedBasicType, constUnion, false)); + createConstant(elementType, elementTypeId, expectedBasicType, constUnion, false)); constUnion += elementType.getObjectSize(); } } @@ -1275,8 +1313,9 @@ spirv::IdRef OutputSPIRVTraverser::createConstant(const TType &type, for (const TField *field : type.getStruct()->fields()) { const TType *fieldType = field->type(); - componentIds.push_back( - createConstant(*fieldType, fieldType->getBasicType(), constUnion, false)); + const spirv::IdRef fieldTypeId = mBuilder.getTypeData(*fieldType, {}).id; + componentIds.push_back(createConstant(*fieldType, fieldTypeId, + fieldType->getBasicType(), constUnion, false)); constUnion += fieldType->getObjectSize(); } @@ -1747,6 +1786,16 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors( return result; } +const spirv::IdRef OutputSPIRVTraverser::getSpirvTypeIdWithExpectedPrecisionBit( + const TType &expectedType, + const TType &actualType) +{ + const SpirvType expectedSpirvType = mBuilder.getSpirvType(expectedType, {}); + SpirvTypeSpec typeSpec = {}; + typeSpec.precision = expectedSpirvType.typeSpec.precision; + return mBuilder.getTypeData(actualType, typeSpec).id; +} + spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( TIntermAggregate *node, spirv::IdRef typeId, @@ -1788,7 +1837,16 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( // directly and potentially swizzle them. TType paramColumnType(parameterType); paramColumnType.toMatrixColumnType(); - const spirv::IdRef paramColumnTypeId = mBuilder.getTypeData(paramColumnType, {}).id; + // For below case, paramComponentType (umat4.x) uses 16-bit floats, and we need to convert + // it to 32-bit to match with the float data type of Matrix constructed (mat3): + // precision mediump float; + // uniform mat4 umat4; + // void main() { + // vec3 colorComponents = mat3(umat4) * vec3(1.0, 1.0, 1.0); + // gl_FragColor = vec4(colorComponents, 1.0); + // } + const spirv::IdRef paramColumnTypeId = + getSpirvTypeIdWithExpectedPrecisionBit(type, paramColumnType); const bool needsSwizzle = parameterType.getRows() > type.getRows(); spirv::LiteralIntegerList swizzle = {spirv::LiteralInteger(0), spirv::LiteralInteger(1), @@ -1822,7 +1880,16 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( // given parameter. TType paramComponentType(parameterType); paramComponentType.toComponentType(); - const spirv::IdRef paramComponentTypeId = mBuilder.getTypeData(paramComponentType, {}).id; + // For below case, paramComponentType (vs_u_0.x) uses 16-bit float, and we need to convert + // it to 32-bit to match with the float data type of Matrix constructed (mat4): + // precision mediump float; + // uniform mat3 vs_u_0; + // void main() + // { + // gl_Position += mat4(vs_u_0) * vec4(1.0, 1.0, 1.0, 1.0); + // } + const spirv::IdRef paramComponentTypeId = + getSpirvTypeIdWithExpectedPrecisionBit(type, paramComponentType); for (uint8_t columnIndex = 0; columnIndex < type.getCols(); ++columnIndex) { @@ -1942,7 +2009,18 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node, TType componentType(argumentType); componentType.toComponentType(); componentType.setBasicType(expectedType.getBasicType()); - const spirv::IdRef componentTypeId = mBuilder.getTypeData(componentType, {}).id; + + // For this case: + // precision mediump float; + // uniform vec3 uniVec3; + // void main() { + // gl_FragColor = vec4(uniVec3, 0.0); + // } + // expectedType is 32-bit float vec4, but componentType (uniVec3) uses 16-bit floats. + // We need to change the componentType float data type to match with the + // expectedType float data type. + const spirv::IdRef componentTypeId = + getSpirvTypeIdWithExpectedPrecisionBit(expectedType, componentType); // Cast the whole vector parameter in one go. const spirv::IdRef castParameterId = @@ -1969,7 +2047,18 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node, TType componentType(argumentType); componentType.toComponentType(); - const spirv::IdRef componentTypeId = mBuilder.getTypeData(componentType, {}).id; + + // For this case: + // precision mediump float; + // uniform mat2 umat2; + // void main() + //{ + // gl_FragColor = vec4(umat2); + //} + // expectedType is 32-bit float vec4, but componentType (umat2) uses 16-bit float. + // We need to change the componentType to match with the expectedType. + const spirv::IdRef componentTypeId = + getSpirvTypeIdWithExpectedPrecisionBit(expectedType, componentType); // For matrix parameters, take components out of the matrix one by one in column-major // order. No cast is done here; it would only be required for vector constructors with @@ -2252,6 +2341,60 @@ void OutputSPIRVTraverser::visitArrayLength(TIntermUnary *node) nodeDataInitRValue(&mNodeData.back(), castResultId, intTypeId); } +// If an expression is short-circuited, it must not be executed. However, in some cases there is +// nothing to execute, such as constants, variables etc. Notably, hasSideEffects() is not +// a sufficient check, because it could include read-only operations that are out of bounds, despite +// not having any side effects. +bool IsSafeToExecuteInShortCircuit(TIntermTyped *node) +{ + // Constants and symbols are safe to execute. + if (node->getAsConstantUnion() || node->getAsSymbolNode()) + { + return true; + } + + // Swizzle is safe if the operand is safe. + { + TIntermSwizzle *asSwizzle = node->getAsSwizzleNode(); + if (asSwizzle) + { + return IsSafeToExecuteInShortCircuit(asSwizzle->getOperand()); + } + } + + // Indexing a struct or interface block is safe to execute, as long as no array index is in the + // access chain. + { + TIntermBinary *asBinary = node->getAsBinaryNode(); + if (asBinary != nullptr) + { + return (asBinary->getOp() == EOpIndexDirectInterfaceBlock || + asBinary->getOp() == EOpIndexDirectStruct) && + IsSafeToExecuteInShortCircuit(asBinary->getLeft()); + } + } + + // Constructors are safe as long as every member is safe. + { + TIntermAggregate *asAggregate = node->getAsAggregate(); + if (asAggregate != nullptr && asAggregate->getOp() == EOpConstruct) + { + for (TIntermNode *component : *asAggregate->getSequence()) + { + if (!IsSafeToExecuteInShortCircuit(component->getAsTyped())) + { + return false; + } + } + return true; + } + } + + // Assume everything else is unsafe. This includes safe but complex expressions that are better + // off not getting executed anyway. + return false; +} + bool IsShortCircuitNeeded(TIntermOperator *node) { TOperator op = node->getOp(); @@ -2264,12 +2407,9 @@ bool IsShortCircuitNeeded(TIntermOperator *node) ASSERT(node->getChildCount() == 2); - // If the right hand side does not have side effects, short-circuiting is unnecessary. - // TODO: experiment with the performance of OpLogicalAnd/Or vs short-circuit based on the - // complexity of the right hand side expression. We could potentially only allow - // OpLogicalAnd/Or if the right hand side is a constant or an access chain and have more complex - // expressions be placed inside an if block. http://anglebug.com/40096715 - return node->getChildNode(1)->getAsTyped()->hasSideEffects(); + // If the right hand side is not safe to execute, short-circuiting is needed + // For example: is_in_bounds(index) && access(data[index]) + return !IsSafeToExecuteInShortCircuit(node->getChildNode(1)->getAsTyped()); } using WriteUnaryOp = void (*)(spirv::Blob *blob, @@ -3203,11 +3343,6 @@ spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermOperator *node, { // One parameter for coordinates. ++imagePointerParameterCount; - if (IsImageMS(operandBasicType)) - { - // One parameter for samples. - ++imagePointerParameterCount; - } } ASSERT(parameterCount >= 2 + imagePointerParameterCount); @@ -3589,6 +3724,8 @@ spirv::IdRef OutputSPIRVTraverser::createImageTextureBuiltIn(TIntermOperator *no break; case EOpTextureGather: + case EOpTextureGatherComp: + case EOpTextureGatherRef: // For shadow textures, refZ (same as Dref) is specified as the last argument. // Otherwise a component may be specified which defaults to 0 if not specified. @@ -3606,9 +3743,11 @@ spirv::IdRef OutputSPIRVTraverser::createImageTextureBuiltIn(TIntermOperator *no case EOpTextureGatherOffset: case EOpTextureGatherOffsetComp: + case EOpTextureGatherOffsetRef: case EOpTextureGatherOffsets: case EOpTextureGatherOffsetsComp: + case EOpTextureGatherOffsetsRef: // textureGatherOffset and textureGatherOffsets have the following forms: // @@ -3711,8 +3850,7 @@ spirv::IdRef OutputSPIRVTraverser::createImageTextureBuiltIn(TIntermOperator *no // If an implicit-lod instruction is used outside a fragment shader, change that to an explicit // one as they are not allowed in SPIR-V outside fragment shaders. const bool noLodSupport = IsSamplerBuffer(samplerBasicType) || - IsImageBuffer(samplerBasicType) || IsSamplerMS(samplerBasicType) || - IsImageMS(samplerBasicType); + IsImageBuffer(samplerBasicType) || IsSamplerMS(samplerBasicType); const bool makeLodExplicit = mCompiler->getShaderType() != GL_FRAGMENT_SHADER && lodIndex == 0 && dPdxIndex == 0 && !noLodSupport && (spirvOp == spv::OpImageSampleImplicitLod || spirvOp == spv::OpImageFetch); @@ -3727,11 +3865,15 @@ spirv::IdRef OutputSPIRVTraverser::createImageTextureBuiltIn(TIntermOperator *no imageType.isSamplerBaseImage = true; const spirv::IdRef extractedImageTypeId = mBuilder.getSpirvTypeData(imageType, nullptr).id; - // Use OpImage to get the image out of the sampled image. - const spirv::IdRef extractedImage = mBuilder.getNewId({}); - spirv::WriteImage(mBuilder.getSpirvCurrentFunctionBlock(), extractedImageTypeId, - extractedImage, image); - image = extractedImage; + // Use OpImage to get the image out of the sampled image. Note that for sampler buffers, + // there is no sampled image type, and the image already has the non-sampled type. + if (!IsSamplerBuffer(samplerBasicType)) + { + const spirv::IdRef extractedImage = mBuilder.getNewId({}); + spirv::WriteImage(mBuilder.getSpirvCurrentFunctionBlock(), extractedImageTypeId, + extractedImage, image); + image = extractedImage; + } } // Gather operands as necessary. @@ -3879,7 +4021,6 @@ spirv::IdRef OutputSPIRVTraverser::createImageTextureBuiltIn(TIntermOperator *no // - sampler2DRect, vec4 P // - sampler3D, vec4 P // - sampler2DShadow, vec4 P - // - sampler2DRectShadow, vec4 P // // Of these cases, only (sampler2D*, vec4 P) requires moving the proj channel from .w to the // appropriate location (.y for 1D and .z for 2D). @@ -4128,6 +4269,92 @@ spirv::IdRef OutputSPIRVTraverser::createInterpolate(TIntermOperator *node, return result; } +spirv::IdRef OutputSPIRVTraverser::castFloatType(spirv::IdRef value, + const TType &valueType, + spirv::IdRef *resultTypeIdOut) +{ + ASSERT(valueType.getBasicType() == EbtFloat); + SpirvType valueSpirvType = mBuilder.getSpirvType(valueType, {}); + spirv::IdRef castTypeId; // default to invalid + spirv::IdRef castValue; // default fo invalid + // OpFConvert only works for scalar or vector data types + // If it is matrix type, we need to first extract each column, convert each column, and + // composite a new matrix + if (valueType.isMatrix()) + { + // Get the matrix column SPIR-V type Id. + // We need this type Id to create the OpCompositeExtract instruction that extract each + // column of the matrix + TType currentMatrixColumnType = valueType; + currentMatrixColumnType.toMatrixColumnType(); + SpirvType currentMatrixColumnSpirvType = mBuilder.getSpirvType(currentMatrixColumnType, {}); + // In below case: + // uniform mat3x4 uniMat3x4[5]; + // uniMat3x4[i] qualifier is EvqTemporary, in which case the + // typeSpec.precision is not set to UseFP16. + // We need to set the bit to true to get the correct 16-bit float data type. + currentMatrixColumnSpirvType.typeSpec.precision = SPIRVPrecisionChoice::UseFP16; + const spirv::IdRef currentMatrixColumnTypeId = + mBuilder.getSpirvTypeData(currentMatrixColumnSpirvType, nullptr).id; + + // Get the converted matrix column SPIR-V type Id. + // We need this type Id to creat the OpFConvert instruction that converts each column of the + // matrix + SpirvType expectedMatrixColumnSpirvType = currentMatrixColumnSpirvType; + expectedMatrixColumnSpirvType.typeSpec.precision = SPIRVPrecisionChoice::Default; + const spirv::IdRef expectedMatrixColumnTypeId = + mBuilder.getSpirvTypeData(expectedMatrixColumnSpirvType, nullptr).id; + + // Extract each column of the matrix and converted them to the expected type + const size_t matrixColCount = valueType.getCols(); + spirv::IdRefList convertedMatrixColIds; + for (size_t i = 0; i < matrixColCount; ++i) + { + // Extract each column vector from the matrix + const spirv::IdRef currentMatrixColumnExtractId = + mBuilder.getNewId(mBuilder.getDecorations(valueType)); + spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), + currentMatrixColumnTypeId, currentMatrixColumnExtractId, + value, {spirv::LiteralInteger(static_cast(i))}); + + // Convert each column + // Decorate the converted matrix column with "RelaxedPrecision", if the current matrix + // column are using 16-bit floats, so that compilers will be able to treat the converted + // matrix column as 16-bit floats. + const spirv::IdRef expectedMatrixColumnTypeExtractId = + mBuilder.getNewId(mBuilder.getDecorations(valueType)); + spirv::WriteFConvert(mBuilder.getSpirvCurrentFunctionBlock(), + expectedMatrixColumnTypeId, expectedMatrixColumnTypeExtractId, + currentMatrixColumnExtractId); + convertedMatrixColIds.push_back(expectedMatrixColumnTypeExtractId); + } + + // Finally construct the new matrix with the converted columns + valueSpirvType.typeSpec.precision = SPIRVPrecisionChoice::Default; + castTypeId = mBuilder.getSpirvTypeData(valueSpirvType, nullptr).id; + // Decorate the converted matrix with "RelaxedPrecision", too. + castValue = mBuilder.getNewId(mBuilder.getDecorations(valueType)); + spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), castTypeId, + castValue, convertedMatrixColIds); + } + else + { + valueSpirvType.typeSpec.precision = SPIRVPrecisionChoice::Default; + + castTypeId = mBuilder.getSpirvTypeData(valueSpirvType, nullptr).id; + // Decorate the converted variable with "RelaxedPrecision" + castValue = mBuilder.getNewId(mBuilder.getDecorations(valueType)); + spirv::WriteFConvert(mBuilder.getSpirvCurrentFunctionBlock(), castTypeId, castValue, value); + } + + if (resultTypeIdOut) + { + *resultTypeIdOut = castTypeId; + } + + return castValue; +} + spirv::IdRef OutputSPIRVTraverser::castBasicType(spirv::IdRef value, const TType &valueType, const TType &expectedType, @@ -4145,6 +4372,15 @@ spirv::IdRef OutputSPIRVTraverser::castBasicType(spirv::IdRef value, SpirvType valueSpirvType = mBuilder.getSpirvType(valueType, {}); valueSpirvType.type = expectedBasicType; valueSpirvType.typeSpec.isOrHasBoolInInterfaceBlock = false; + // In below case + // uniform mediump float x; + // if (bool(bool(x))) + // valueSpirvType.typeSpec.precision == SPIRVPrecisionChoice::UseFP16 + // We want to reset precision to SPIRVPrecisionChoice::Default, because 16-bit + // does not make sense for bool + SpirvType expectedSpirvType = mBuilder.getSpirvType(expectedType, {}); + valueSpirvType.typeSpec.precision = expectedSpirvType.typeSpec.precision; + const spirv::IdRef castTypeId = mBuilder.getSpirvTypeData(valueSpirvType, nullptr).id; const spirv::IdRef castValue = mBuilder.getNewId(mBuilder.getDecorations(expectedType)); @@ -4260,13 +4496,16 @@ spirv::IdRef OutputSPIRVTraverser::cast(spirv::IdRef value, const SpirvTypeSpec &expectedTypeSpec, spirv::IdRef *resultTypeIdOut) { + ASSERT(valueTypeSpec.precision != SPIRVPrecisionChoice::Unset && + expectedTypeSpec.precision != SPIRVPrecisionChoice::Unset); // If there's no difference in type specialization, there's nothing to cast. if (valueTypeSpec.blockStorage == expectedTypeSpec.blockStorage && valueTypeSpec.isInvariantBlock == expectedTypeSpec.isInvariantBlock && valueTypeSpec.isRowMajorQualifiedBlock == expectedTypeSpec.isRowMajorQualifiedBlock && valueTypeSpec.isRowMajorQualifiedArray == expectedTypeSpec.isRowMajorQualifiedArray && valueTypeSpec.isOrHasBoolInInterfaceBlock == expectedTypeSpec.isOrHasBoolInInterfaceBlock && - valueTypeSpec.isPatchIOBlock == expectedTypeSpec.isPatchIOBlock) + valueTypeSpec.isPatchIOBlock == expectedTypeSpec.isPatchIOBlock && + valueTypeSpec.precision == expectedTypeSpec.precision) { return value; } @@ -4278,11 +4517,15 @@ spirv::IdRef OutputSPIRVTraverser::cast(spirv::IdRef value, // // If SPIR-V 1.4 is available, use OpCopyLogical if possible. OpCopyLogical works on arrays and // structs, and only if the types are logically the same. This means that arrays and structs - // can be copied with this instruction despite their SpirvTypeSpec being different. The only - // exception is if there is a mismatch in the isOrHasBoolInInterfaceBlock type specialization + // can be copied with this instruction despite their SpirvTypeSpec being different. + // The only exceptions are: + // 1) If there is a mismatch in the isOrHasBoolInInterfaceBlock type specialization // as it actually changes the type of the struct members. + // 2) If there is a mismatch in the precision type specialization as it changes + // float data type between 16-bit and 32-bit. if (mCompileOptions.emitSPIRV14 && (valueType.isArray() || valueType.getStruct() != nullptr) && - valueTypeSpec.isOrHasBoolInInterfaceBlock == expectedTypeSpec.isOrHasBoolInInterfaceBlock) + valueTypeSpec.isOrHasBoolInInterfaceBlock == expectedTypeSpec.isOrHasBoolInInterfaceBlock && + valueTypeSpec.precision == expectedTypeSpec.precision) { const spirv::IdRef expectedTypeId = mBuilder.getTypeDataOverrideTypeSpec(valueType, expectedTypeSpec).id; @@ -4369,24 +4612,34 @@ spirv::IdRef OutputSPIRVTraverser::cast(spirv::IdRef value, } else { - // Bool types in interface blocks are emulated with uint. bool<->uint cast is done here. - ASSERT(valueType.getBasicType() == EbtBool); - ASSERT(valueTypeSpec.isOrHasBoolInInterfaceBlock || - expectedTypeSpec.isOrHasBoolInInterfaceBlock); - - TType emulatedValueType(valueType); - emulatedValueType.setBasicType(EbtUInt); - emulatedValueType.setPrecise(EbpLow); - - // If value is loaded as uint, it needs to change to bool. If it's bool, it needs to change - // to uint before storage. - if (valueTypeSpec.isOrHasBoolInInterfaceBlock) + ASSERT(valueType.getBasicType() == EbtBool || valueType.getBasicType() == EbtFloat); + if (valueType.getBasicType() == EbtBool) { - return castBasicType(value, emulatedValueType, valueType, resultTypeIdOut); + // Bool types in interface blocks are emulated with uint. bool<->uint cast is done + // here. + ASSERT(valueTypeSpec.isOrHasBoolInInterfaceBlock || + expectedTypeSpec.isOrHasBoolInInterfaceBlock); + TType emulatedValueType(valueType); + emulatedValueType.setBasicType(EbtUInt); + emulatedValueType.setPrecise(EbpLow); + + // If value is loaded as uint, it needs to change to bool. If it's bool, it needs to + // change to uint before storage. + if (valueTypeSpec.isOrHasBoolInInterfaceBlock) + { + return castBasicType(value, emulatedValueType, valueType, resultTypeIdOut); + } + else + { + return castBasicType(value, valueType, emulatedValueType, resultTypeIdOut); + } } else { - return castBasicType(value, valueType, emulatedValueType, resultTypeIdOut); + // 32-bit floats and 16-bit floats cast is done here + ASSERT(valueTypeSpec.precision == SPIRVPrecisionChoice::UseFP16 && + expectedTypeSpec.precision == SPIRVPrecisionChoice::Default); + return castFloatType(value, valueType, resultTypeIdOut); } } @@ -4762,7 +5015,7 @@ void OutputSPIRVTraverser::visitSymbol(TIntermSymbol *node) // They are needed to determine the derived type in an access chain, but are not promoted in // intermediate nodes' TTypes. SpirvTypeSpec typeSpec; - typeSpec.inferDefaults(type, mCompiler); + typeSpec.inferDefaults(type, mCompiler, mCompileOptions.transformFloatUniformTo16Bits); const spirv::IdRef typeId = mBuilder.getTypeData(type, typeSpec).id; @@ -4772,8 +5025,8 @@ void OutputSPIRVTraverser::visitSymbol(TIntermSymbol *node) type.getQualifier() == EvqSpecConst) { ASSERT(interfaceBlock == nullptr); - ASSERT(mSymbolIdMap.count(symbol) > 0); - nodeDataInitRValue(&mNodeData.back(), mSymbolIdMap[symbol], typeId); + ASSERT(mSymbolIdMap.count(symbol->uniqueId()) > 0); + nodeDataInitRValue(&mNodeData.back(), mSymbolIdMap[symbol->uniqueId()], typeId); return; } @@ -4809,6 +5062,7 @@ void OutputSPIRVTraverser::visitConstantUnion(TIntermConstantUnion *node) mNodeData.emplace_back(); const TType &type = node->getType(); + spirv::IdRef typeId = mBuilder.getTypeData(type, {}).id; // Find out the expected type for this constant, so it can be cast right away and not need an // instruction to do that. @@ -4839,12 +5093,18 @@ void OutputSPIRVTraverser::visitConstantUnion(TIntermConstantUnion *node) { expectedBasicType = parentAggregate->getType().getBasicType(); } + + if (expectedBasicType != type.getBasicType()) + { + TType castType = type; + castType.setBasicType(expectedBasicType); + typeId = mBuilder.getTypeData(castType, {}).id; + } } } - const spirv::IdRef typeId = mBuilder.getTypeData(type, {}).id; - const spirv::IdRef constId = createConstant(type, expectedBasicType, node->getConstantValue(), - node->isConstantNullValue()); + const spirv::IdRef constId = createConstant( + type, typeId, expectedBasicType, node->getConstantValue(), node->isConstantNullValue()); nodeDataInitRValue(&mNodeData.back(), constId, typeId); } @@ -4865,7 +5125,7 @@ bool OutputSPIRVTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) const TType &vectorType = node->getOperand()->getType(); const uint8_t vectorComponentCount = static_cast(vectorType.getNominalSize()); - const TVector &swizzle = node->getSwizzleOffsets(); + const TVector &swizzle = node->getSwizzleOffsets(); // As an optimization, do nothing if the swizzle is selecting all the components of the vector // in order. @@ -4970,7 +5230,12 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node) } resultTypeSpec = mNodeData[mNodeData.size() - 2].accessChain.typeSpec; } - const spirv::IdRef resultTypeId = mBuilder.getTypeData(node->getType(), resultTypeSpec).id; + // Workaround bugs in the transformers that don't take operator comma into account; the type of + // operator comma can be wrong if the type of RHS is changed (such as when extracting samplers + // out of structs). Fortunately, we don't need the type of the comma node at all. + const spirv::IdRef resultTypeId = + node->getOp() == EOpComma ? spirv::IdRef{} + : mBuilder.getTypeData(node->getType(), resultTypeSpec).id; // For EOpIndex* operations, push the right value as an index to the left value's access chain. // For the other operations, evaluate the expression. @@ -5080,8 +5345,8 @@ bool OutputSPIRVTraverser::visitTernary(Visit visit, TIntermTernary *node) // prior to 1.4 requires the type to be either scalar or vector. const TType &type = node->getType(); bool canUseOpSelect = (type.isScalar() || type.isVector() || mCompileOptions.emitSPIRV14) && - !node->getTrueExpression()->hasSideEffects() && - !node->getFalseExpression()->hasSideEffects(); + IsSafeToExecuteInShortCircuit(node->getTrueExpression()) && + IsSafeToExecuteInShortCircuit(node->getFalseExpression()); // Don't use OpSelect on buggy drivers. Technically this is only needed if the two sides don't // have matching use of RelaxedPrecision, but not worth being precise about it. @@ -5560,8 +5825,8 @@ bool OutputSPIRVTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionD ids.parameterTypeIds[paramIndex], paramId); // Remember the id of the variable for future look up. - ASSERT(mSymbolIdMap.count(paramVariable) == 0); - mSymbolIdMap[paramVariable] = paramId; + ASSERT(mSymbolIdMap.count(paramVariable->uniqueId()) == 0); + mSymbolIdMap.emplace(paramVariable->uniqueId(), paramId); mBuilder.writeDebugName(paramId, mBuilder.getName(paramVariable).data()); } @@ -5661,9 +5926,9 @@ bool OutputSPIRVTraverser::visitGlobalQualifierDeclaration(Visit visit, ASSERT(node->isInvariant()); const TVariable *variable = &node->getSymbol()->variable(); - ASSERT(mSymbolIdMap.count(variable) > 0); + ASSERT(mSymbolIdMap.count(variable->uniqueId()) > 0); - const spirv::IdRef variableId = mSymbolIdMap[variable]; + const spirv::IdRef variableId = mSymbolIdMap[variable->uniqueId()]; spirv::WriteDecorate(mBuilder.getSpirvDecorations(), variableId, spv::DecorationInvariant, {}); @@ -6125,13 +6390,13 @@ bool OutputSPIRVTraverser::visitDeclaration(Visit visit, TIntermDeclaration *nod // Remember the id of the variable for future look up. For interface blocks, also remember the // id of the interface block. - ASSERT(mSymbolIdMap.count(variable) == 0); - mSymbolIdMap[variable] = variableId; + ASSERT(mSymbolIdMap.count(variable->uniqueId()) == 0); + mSymbolIdMap.emplace(variable->uniqueId(), variableId); if (type.isInterfaceBlock()) { - ASSERT(mSymbolIdMap.count(type.getInterfaceBlock()) == 0); - mSymbolIdMap[type.getInterfaceBlock()] = variableId; + ASSERT(mSymbolIdMap.count(type.getInterfaceBlock()->uniqueId()) == 0); + mSymbolIdMap.emplace(type.getInterfaceBlock()->uniqueId(), variableId); } return false; diff --git a/src/compiler/translator/spirv/TranslatorSPIRV.cpp b/src/compiler/translator/spirv/TranslatorSPIRV.cpp index d2d493004cd..9cc44260491 100644 --- a/src/compiler/translator/spirv/TranslatorSPIRV.cpp +++ b/src/compiler/translator/spirv/TranslatorSPIRV.cpp @@ -9,9 +9,12 @@ // See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/spirv/TranslatorSPIRV.h" -#include "angle_gl.h" #include "common/PackedEnums.h" #include "common/utilities.h" #include "compiler/translator/ImmutableStringBuilder.h" @@ -20,10 +23,9 @@ #include "compiler/translator/spirv/BuiltinsWorkaround.h" #include "compiler/translator/spirv/OutputSPIRV.h" #include "compiler/translator/tree_ops/DeclarePerVertexBlocks.h" +#include "compiler/translator/tree_ops/GatherDefaultUniforms.h" #include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" -#include "compiler/translator/tree_ops/RecordConstantPrecision.h" #include "compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h" -#include "compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h" #include "compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h" #include "compiler/translator/tree_ops/RewriteAtomicCounters.h" #include "compiler/translator/tree_ops/RewriteDfdy.h" @@ -39,6 +41,7 @@ #include "compiler/translator/tree_ops/spirv/ReswizzleYUVOps.h" #include "compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.h" #include "compiler/translator/tree_ops/spirv/RewriteR32fImages.h" +#include "compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.h" #include "compiler/translator/tree_util/BuiltIn.h" #include "compiler/translator/tree_util/DriverUniform.h" #include "compiler/translator/tree_util/FindFunction.h" @@ -48,7 +51,6 @@ #include "compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h" #include "compiler/translator/tree_util/ReplaceVariable.h" #include "compiler/translator/tree_util/RewriteSampleMaskVariable.h" -#include "compiler/translator/tree_util/RunAtTheBeginningOfShader.h" #include "compiler/translator/tree_util/RunAtTheEndOfShader.h" #include "compiler/translator/tree_util/SpecializationConstant.h" #include "compiler/translator/util.h" @@ -62,127 +64,6 @@ constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPo constexpr ImmutableString kFlippedFragCoordName = ImmutableString("flippedFragCoord"); constexpr ImmutableString kDefaultUniformsBlockName = ImmutableString("defaultUniforms"); -bool IsDefaultUniform(const TType &type) -{ - return type.getQualifier() == EvqUniform && type.getInterfaceBlock() == nullptr && - !IsOpaqueType(type.getBasicType()); -} - -class ReplaceDefaultUniformsTraverser : public TIntermTraverser -{ - public: - ReplaceDefaultUniformsTraverser(const VariableReplacementMap &variableMap) - : TIntermTraverser(true, false, false), mVariableMap(variableMap) - {} - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - const TIntermSequence &sequence = *(node->getSequence()); - - TIntermTyped *variable = sequence.front()->getAsTyped(); - const TType &type = variable->getType(); - - if (IsDefaultUniform(type)) - { - // Remove the uniform declaration. - TIntermSequence emptyReplacement; - mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, - std::move(emptyReplacement)); - - return false; - } - - return true; - } - - void visitSymbol(TIntermSymbol *symbol) override - { - const TVariable &variable = symbol->variable(); - const TType &type = variable.getType(); - - if (!IsDefaultUniform(type) || gl::IsBuiltInName(variable.name().data())) - { - return; - } - - ASSERT(mVariableMap.count(&variable) > 0); - - queueReplacement(mVariableMap.at(&variable)->deepCopy(), OriginalNode::IS_DROPPED); - } - - private: - const VariableReplacementMap &mVariableMap; -}; - -bool DeclareDefaultUniforms(TranslatorSPIRV *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable, - gl::ShaderType shaderType) -{ - // First, collect all default uniforms and declare a uniform block. - TFieldList *uniformList = new TFieldList; - TVector uniformVars; - - for (TIntermNode *node : *root->getSequence()) - { - TIntermDeclaration *decl = node->getAsDeclarationNode(); - if (decl == nullptr) - { - continue; - } - - const TIntermSequence &sequence = *(decl->getSequence()); - - TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); - if (symbol == nullptr) - { - continue; - } - - const TType &type = symbol->getType(); - if (IsDefaultUniform(type)) - { - TType *fieldType = new TType(type); - - uniformList->push_back(new TField(fieldType, symbol->getName(), symbol->getLine(), - symbol->variable().symbolType())); - uniformVars.push_back(&symbol->variable()); - } - } - - TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); - layoutQualifier.blockStorage = EbsStd140; - const TVariable *uniformBlock = DeclareInterfaceBlock( - root, symbolTable, uniformList, EvqUniform, layoutQualifier, TMemoryQualifier::Create(), 0, - kDefaultUniformsBlockName, ImmutableString("")); - - compiler->assignSpirvId(uniformBlock->getType().getInterfaceBlock()->uniqueId(), - vk::spirv::kIdDefaultUniformsBlock); - - // Create a map from the uniform variables to new variables that reference the fields of the - // block. - VariableReplacementMap variableMap; - for (size_t fieldIndex = 0; fieldIndex < uniformVars.size(); ++fieldIndex) - { - const TVariable *variable = uniformVars[fieldIndex]; - - TType *replacementType = new TType(variable->getType()); - replacementType->setInterfaceBlockField(uniformBlock->getType().getInterfaceBlock(), - fieldIndex); - - TVariable *replacementVariable = - new TVariable(symbolTable, variable->name(), replacementType, variable->symbolType()); - - variableMap[variable] = new TIntermSymbol(replacementVariable); - } - - // Finally transform the AST and make sure references to the uniforms are replaced with the new - // variables. - ReplaceDefaultUniformsTraverser defaultTraverser(variableMap); - root->traverse(&defaultTraverser); - return defaultTraverser.updateTree(compiler, root); -} - // Replaces a builtin variable with a version that is rotated and corrects the X and Y coordinates. [[nodiscard]] bool RotateAndFlipBuiltinVariable(TCompiler *compiler, TIntermBlock *root, @@ -457,9 +338,11 @@ TIntermSequence *GetMainSequence(TIntermBlock *root) TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); layoutQualifier.blockStorage = EbsStd430; + const TInterfaceBlock *interfaceBlock = + DeclareInterfaceBlock(symbolTable, fieldList, layoutQualifier, blockName); const TVariable *xfbBuffer = - DeclareInterfaceBlock(root, symbolTable, fieldList, EvqBuffer, layoutQualifier, - TMemoryQualifier::Create(), 0, blockName, varName); + DeclareInterfaceBlockVariable(root, symbolTable, EvqBuffer, interfaceBlock, + layoutQualifier, TMemoryQualifier::Create(), 0, varName); static_assert(vk::spirv::kIdXfbEmulationBufferBlockOne == vk::spirv::kIdXfbEmulationBufferBlockZero + 1); @@ -531,7 +414,6 @@ TIntermSequence *GetMainSequence(TIntermBlock *root) const ShCompileOptions &compileOptions, TIntermBlock *root, TSymbolTable *symbolTable, - SpecConst *specConst, const DriverUniform *driverUniforms) { // In GL the viewport transformation is slightly different - see the GL 2.0 spec section "2.12.1 @@ -562,11 +444,7 @@ TIntermSequence *GetMainSequence(TIntermBlock *root) TIntermSymbol *positionSymbol = new TIntermSymbol(positionVar); // swapXY ? position.yx : position.xy - TIntermTyped *swapXY = specConst->getSwapXY(); - if (swapXY == nullptr) - { - swapXY = driverUniforms->getSwapXY(); - } + TIntermTyped *swapXY = driverUniforms->getSwapXY(); TIntermTyped *xy = new TIntermSwizzle(positionSymbol, {0, 1}); TIntermTyped *swappedXY = new TIntermSwizzle(positionSymbol->deepCopy(), {1, 0}); @@ -628,17 +506,12 @@ TIntermSequence *GetMainSequence(TIntermBlock *root) TIntermBlock *root, TIntermSequence *insertSequence, TSymbolTable *symbolTable, - SpecConst *specConst, const DriverUniform *driverUniforms) { TIntermTyped *flipXY = driverUniforms->getFlipXY(symbolTable, DriverUniformFlip::Fragment); TIntermTyped *pivot = driverUniforms->getHalfRenderArea(); - TIntermTyped *swapXY = specConst->getSwapXY(); - if (swapXY == nullptr) - { - swapXY = driverUniforms->getSwapXY(); - } + TIntermTyped *swapXY = driverUniforms->getSwapXY(); const TVariable *fragCoord = static_cast( symbolTable->findBuiltIn(ImmutableString("gl_FragCoord"), compiler->getShaderVersion())); @@ -654,7 +527,6 @@ bool HasFramebufferFetch(const TExtensionBehavior &extBehavior, IsExtensionEnabled(extBehavior, TExtension::ARM_shader_framebuffer_fetch) || IsExtensionEnabled(extBehavior, TExtension::ARM_shader_framebuffer_fetch_depth_stencil) || - IsExtensionEnabled(extBehavior, TExtension::NV_shader_framebuffer_fetch) || (compileOptions.pls.type == ShPixelLocalStorageType::FramebufferFetch && IsExtensionEnabled(extBehavior, TExtension::ANGLE_shader_pixel_local_storage)); } @@ -791,17 +663,6 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, } } - // Remove declarations of inactive shader interface variables so SPIR-V transformer doesn't need - // to replace them. Note that currently, CollectVariables marks every field of an active - // uniform that's of struct type as active, i.e. no extracted sampler is inactive, so this can - // be done before extracting samplers from structs. - if (!RemoveInactiveInterfaceVariables(this, root, &getSymbolTable(), getAttributes(), - getInputVaryings(), getOutputVariables(), getUniforms(), - getInterfaceBlocks(), true)) - { - return false; - } - // If there are any function calls that take array-of-array of opaque uniform parameters, or // other opaque uniforms that need special handling in Vulkan, such as atomic counters, // monomorphize the functions by removing said parameters and replacing them in the function @@ -854,10 +715,16 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, if (defaultUniformCount > 0) { - if (!DeclareDefaultUniforms(this, root, &getSymbolTable(), packedShaderType)) + const TVariable *uniformBlock; + if (!GatherDefaultUniforms(this, root, &getSymbolTable(), packedShaderType, + kDefaultUniformsBlockName, ImmutableString(""), &uniformBlock)) { return false; } + ASSERT(uniformBlock); + + assignSpirvId(uniformBlock->getType().getInterfaceBlock()->uniqueId(), + vk::spirv::kIdDefaultUniformsBlock); } if (getShaderType() == GL_COMPUTE_SHADER) @@ -965,7 +832,30 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, // Add support code for pre-rotation and depth correction in the vertex processing stages. if (!AddVertexTransformationSupport(this, compileOptions, root, &getSymbolTable(), - specConst, driverUniforms)) + driverUniforms)) + { + return false; + } + } + + if (IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_YUV_target)) + { + if (!EmulateYUVBuiltIns(this, root, &getSymbolTable())) + { + return false; + } + + if (!ReswizzleYUVTextureAccess(this, root, &getSymbolTable())) + { + return false; + } + } + + if (IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_YUV_target) || + IsExtensionEnabled(getExtensionBehavior(), TExtension::OES_EGL_image_external) || + IsExtensionEnabled(getExtensionBehavior(), TExtension::OES_EGL_image_external_essl3)) + { + if (!RewriteSamplerExternalTexelFetch(this, root, &getSymbolTable())) { return false; } @@ -1045,11 +935,8 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, TIntermTyped *flipNegXY = driverUniforms->getNegFlipXY(&getSymbolTable(), DriverUniformFlip::Fragment); TIntermConstantUnion *pivot = CreateFloatNode(0.5f, EbpMedium); - TIntermTyped *swapXY = specConst->getSwapXY(); - if (swapXY == nullptr) - { - swapXY = driverUniforms->getSwapXY(); - } + TIntermTyped *swapXY = driverUniforms->getSwapXY(); + if (!RotateAndFlipBuiltinVariable( this, root, GetMainSequence(root), swapXY, flipNegXY, &getSymbolTable(), BuiltInVariable::gl_PointCoord(), kFlippedPointCoordName, pivot)) @@ -1063,11 +950,7 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, TIntermTyped *flipXY = driverUniforms->getFlipXY(&getSymbolTable(), DriverUniformFlip::Fragment); TIntermConstantUnion *pivot = CreateFloatNode(0.5f, EbpMedium); - TIntermTyped *swapXY = specConst->getSwapXY(); - if (swapXY == nullptr) - { - swapXY = driverUniforms->getSwapXY(); - } + TIntermTyped *swapXY = driverUniforms->getSwapXY(); const TVariable *samplePositionBuiltin = static_cast(getSymbolTable().findBuiltIn( @@ -1083,7 +966,7 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, if (usesFragCoord) { if (!InsertFragCoordCorrection(this, compileOptions, root, GetMainSequence(root), - &getSymbolTable(), specConst, driverUniforms)) + &getSymbolTable(), driverUniforms)) { return false; } @@ -1123,14 +1006,13 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, // emulation. Declare their SPIR-V ids. assignInputAttachmentIds(inputAttachmentMap); - if (!RewriteDfdy(this, root, &getSymbolTable(), getShaderVersion(), specConst, - driverUniforms)) + if (!RewriteDfdy(this, root, &getSymbolTable(), getShaderVersion(), driverUniforms)) { return false; } if (!RewriteInterpolateAtOffset(this, root, &getSymbolTable(), getShaderVersion(), - specConst, driverUniforms)) + driverUniforms)) { return false; } @@ -1154,7 +1036,8 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, static_cast(getSymbolTable().findBuiltIn( ImmutableString("gl_NumSamples"), getShaderVersion())); TIntermTyped *numSamples = driverUniforms->getNumSamples(); - if (!ReplaceVariableWithTyped(this, root, numSamplesVar, numSamples)) + if (numSamplesVar && + !ReplaceVariableWithTyped(this, root, numSamplesVar, numSamples)) { return false; } @@ -1162,23 +1045,23 @@ bool TranslatorSPIRV::translateImpl(TIntermBlock *root, if (IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_YUV_target)) { - if (!EmulateYUVBuiltIns(this, root, &getSymbolTable())) + if (yuvOutput != nullptr && + !AdjustYUVOutput(this, root, &getSymbolTable(), *yuvOutput)) { return false; } + } - if (!ReswizzleYUVOps(this, root, &getSymbolTable(), yuvOutput)) + if (compileOptions.emulateDithering) + { + // Inject dithering code in fragment shader iff "emulateDithering" is enabled + if (!EmulateDithering(this, compileOptions, root, &getSymbolTable(), specConst, + driverUniforms)) { return false; } } - if (!EmulateDithering(this, compileOptions, root, &getSymbolTable(), specConst, - driverUniforms)) - { - return false; - } - break; } @@ -1275,7 +1158,7 @@ bool TranslatorSPIRV::translate(TIntermBlock *root, mUniqueToSpirvIdMap.clear(); mFirstUnusedSpirvId = 0; - SpecConst specConst(&getSymbolTable(), compileOptions, getShaderType()); + SpecConst specConst(&getSymbolTable(), getShaderType()); DriverUniform driverUniforms(DriverUniformMode::InterfaceBlock); DriverUniformExtended driverUniformsExt(DriverUniformMode::InterfaceBlock); @@ -1369,7 +1252,16 @@ void TranslatorSPIRV::assignSpirvIds(TIntermBlock *root) std::vector *fields = nullptr; if (type.isInterfaceBlock()) { - if (IsVaryingIn(qualifier)) + if (qualifier == EvqPerVertexIn) + { + assignSpirvId(uniqueId, vk::spirv::kIdInputPerVertexBlock); + } + else if (qualifier == EvqPerVertexOut) + { + assignSpirvId(uniqueId, vk::spirv::kIdOutputPerVertexBlock); + assignSpirvId(symbol->uniqueId(), vk::spirv::kIdOutputPerVertexVar); + } + else if (IsVaryingIn(qualifier)) { ShaderVariable *varying = FindIOBlockShaderVariable(&mInputVaryings, type.getInterfaceBlock()->name()); diff --git a/src/compiler/translator/tree_ops/DeclarePerVertexBlocks.cpp b/src/compiler/translator/tree_ops/DeclarePerVertexBlocks.cpp index e37d72a22e6..5ac640f0540 100644 --- a/src/compiler/translator/tree_ops/DeclarePerVertexBlocks.cpp +++ b/src/compiler/translator/tree_ops/DeclarePerVertexBlocks.cpp @@ -140,8 +140,6 @@ class DeclarePerVertexBlocksTraverser : public TIntermTraverser mPerVertexOutVar(nullptr), mPerVertexInVarRedeclared(false), mPerVertexOutVarRedeclared(false), - mPositionRedeclaredForSeparateShaderObject(false), - mPointSizeRedeclaredForSeparateShaderObject(false), mPerVertexOutInvariantFlags(invariantFlags), mPerVertexOutPreciseFlags(preciseFlags) {} @@ -226,9 +224,7 @@ class DeclarePerVertexBlocksTraverser : public TIntermTraverser // }; // - if (variable->symbolType() != SymbolType::BuiltIn && - !(variable->name() == "gl_Position" && mPositionRedeclaredForSeparateShaderObject) && - !(variable->name() == "gl_PointSize" && mPointSizeRedeclaredForSeparateShaderObject)) + if (variable->symbolType() != SymbolType::BuiltIn) { ASSERT(variable->name() != "gl_Position" && variable->name() != "gl_PointSize" && variable->name() != "gl_ClipDistance" && variable->name() != "gl_CullDistance" && @@ -238,7 +234,7 @@ class DeclarePerVertexBlocksTraverser : public TIntermTraverser } // If this built-in was already visited, reuse the variable defined for it. - auto replacement = mVariableMap.find(variable); + auto replacement = mVariableMap.find(variable->uniqueId()); if (replacement != mVariableMap.end()) { queueReplacement(replacement->second->deepCopy(), OriginalNode::IS_DROPPED); @@ -273,7 +269,7 @@ class DeclarePerVertexBlocksTraverser : public TIntermTraverser variable->symbolType(), variable->extensions()); TIntermSymbol *newSymbol = new TIntermSymbol(newVariable); - mVariableMap[variable] = newSymbol; + mVariableMap[variable->uniqueId()] = newSymbol; queueReplacement(newSymbol, OriginalNode::IS_DROPPED); } @@ -297,19 +293,31 @@ class DeclarePerVertexBlocksTraverser : public TIntermTraverser TIntermSequence emptyReplacement; if (symbol->getType().getQualifier() == EvqPosition) { - mPositionRedeclaredForSeparateShaderObject = true; mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, std::move(emptyReplacement)); return false; } if (symbol->getType().getQualifier() == EvqPointSize) { - mPointSizeRedeclaredForSeparateShaderObject = true; mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, std::move(emptyReplacement)); return false; } + // If gl_in is redeclared by the shader, make sure it's not overridden. + if (symbol->getType().getQualifier() == EvqPerVertexIn) + { + mPerVertexInVar = &symbol->variable(); + return false; + } + + // If gl_out is redeclared by the shader, make sure it's not overridden. + if (symbol->getType().getQualifier() == EvqPerVertexOut) + { + mPerVertexOutVar = &symbol->variable(); + return false; + } + return true; } @@ -461,9 +469,6 @@ class DeclarePerVertexBlocksTraverser : public TIntermTraverser bool mPerVertexInVarRedeclared; bool mPerVertexOutVarRedeclared; - bool mPositionRedeclaredForSeparateShaderObject; - bool mPointSizeRedeclaredForSeparateShaderObject; - // A map of already replaced built-in variables. VariableReplacementMap mVariableMap; diff --git a/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp b/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp index 4d7bbfddab1..30afadab0db 100644 --- a/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp +++ b/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp @@ -37,7 +37,6 @@ constexpr const ImmutableString kInitGlobalsString("initGlobals"); void GetDeferredInitializers(TIntermDeclaration *declaration, bool initializeUninitializedGlobals, bool canUseLoopsToInitialize, - bool highPrecisionSupported, bool forceDeferNonConstGlobalInitializers, TIntermSequence *deferredInitializersOut, std::vector *variablesToReplaceOut, @@ -94,8 +93,7 @@ void GetDeferredInitializers(TIntermDeclaration *declaration, if (symbolNode->getQualifier() == EvqGlobal) { TIntermSequence initCode; - CreateInitCode(symbolNode, canUseLoopsToInitialize, highPrecisionSupported, &initCode, - symbolTable); + CreateInitCode(symbolNode, canUseLoopsToInitialize, &initCode, symbolTable); deferredInitializersOut->insert(deferredInitializersOut->end(), initCode.begin(), initCode.end()); } @@ -134,7 +132,6 @@ bool DeferGlobalInitializers(TCompiler *compiler, TIntermBlock *root, bool initializeUninitializedGlobals, bool canUseLoopsToInitialize, - bool highPrecisionSupported, bool forceDeferNonConstGlobalInitializers, TSymbolTable *symbolTable) { @@ -149,9 +146,8 @@ bool DeferGlobalInitializers(TCompiler *compiler, if (declaration) { GetDeferredInitializers(declaration, initializeUninitializedGlobals, - canUseLoopsToInitialize, highPrecisionSupported, - forceDeferNonConstGlobalInitializers, &deferredInitializers, - &variablesToReplace, symbolTable); + canUseLoopsToInitialize, forceDeferNonConstGlobalInitializers, + &deferredInitializers, &variablesToReplace, symbolTable); } } diff --git a/src/compiler/translator/tree_ops/DeferGlobalInitializers.h b/src/compiler/translator/tree_ops/DeferGlobalInitializers.h index a6934d04fb1..6debadd6861 100644 --- a/src/compiler/translator/tree_ops/DeferGlobalInitializers.h +++ b/src/compiler/translator/tree_ops/DeferGlobalInitializers.h @@ -29,7 +29,6 @@ class TSymbolTable; TIntermBlock *root, bool initializeUninitializedGlobals, bool canUseLoopsToInitialize, - bool highPrecisionSupported, bool forceDeferNonConstGlobalInitializers, TSymbolTable *symbolTable); diff --git a/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp b/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp index 7b3770c73c9..69e70723c2f 100644 --- a/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp +++ b/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp @@ -42,7 +42,7 @@ class FindGLDrawIDTraverser : public TIntermTraverser protected: void visitSymbol(TIntermSymbol *node) override { - if (&node->variable() == BuiltInVariable::gl_DrawID()) + if (node->getQualifier() == EvqDrawID) { mVariable = &node->variable(); } @@ -72,48 +72,72 @@ class AddBaseVertexToGLVertexIDTraverser : public TIntermTraverser }; constexpr const ImmutableString kEmulatedGLBaseVertexName("angle_BaseVertex"); +constexpr const ImmutableString kEmulatedGLBaseInstanceName("angle_BaseInstance"); -class FindGLBaseVertexTraverser : public TIntermTraverser +class FindGLBaseVertexBaseInstanceTraverser : public TIntermTraverser { public: - FindGLBaseVertexTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + FindGLBaseVertexBaseInstanceTraverser() + : TIntermTraverser(true, false, false), + mBaseVertexVariable(nullptr), + mBaseInstanceVariable(nullptr) + {} - const TVariable *getGLBaseVertexBuiltinVariable() { return mVariable; } + const TVariable *getGLBaseVertexBuiltinVariable() { return mBaseVertexVariable; } + const TVariable *getGLBaseInstanceBuiltinVariable() { return mBaseInstanceVariable; } protected: void visitSymbol(TIntermSymbol *node) override { - if (&node->variable() == BuiltInVariable::gl_BaseVertex()) + switch (node->getQualifier()) { - mVariable = &node->variable(); + case EvqBaseVertex: + mBaseVertexVariable = &node->variable(); + break; + case EvqBaseInstance: + mBaseInstanceVariable = &node->variable(); + break; + default: + break; } } private: - const TVariable *mVariable; + const TVariable *mBaseVertexVariable; + const TVariable *mBaseInstanceVariable; }; -constexpr const ImmutableString kEmulatedGLBaseInstanceName("angle_BaseInstance"); - -class FindGLBaseInstanceTraverser : public TIntermTraverser +bool EmulateBuiltIn(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TVariable *builtInVariable, + const TType *type, + const ImmutableString &name, + std::vector *uniforms) { - public: - FindGLBaseInstanceTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} - - const TVariable *getGLBaseInstanceBuiltinVariable() { return mVariable; } - - protected: - void visitSymbol(TIntermSymbol *node) override - { - if (&node->variable() == BuiltInVariable::gl_BaseInstance()) - { - mVariable = &node->variable(); - } - } - - private: - const TVariable *mVariable; -}; + const TVariable *emulatedVar = + new TVariable(symbolTable, name, type, SymbolType::AngleInternal); + const TIntermSymbol *emulatedSymbol = new TIntermSymbol(emulatedVar); + + // AngleInternal variables don't get collected + ShaderVariable uniform; + uniform.name = name.data(); + uniform.mappedName = name.data(); + uniform.type = GLVariableType(*type); + uniform.precision = GLVariablePrecision(*type); + uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable); + uniform.active = true; + uniform.binding = type->getLayoutQualifier().binding; + uniform.location = type->getLayoutQualifier().location; + uniform.offset = type->getLayoutQualifier().offset; + uniform.rasterOrdered = type->getLayoutQualifier().rasterOrdered; + uniform.readonly = type->getMemoryQualifier().readonly; + uniform.writeonly = type->getMemoryQualifier().writeonly; + uniforms->push_back(uniform); + + DeclareGlobalVariable(root, emulatedVar); + return ReplaceVariableWithTyped(compiler, root, builtInVariable, emulatedSymbol); +} } // namespace @@ -128,28 +152,8 @@ bool EmulateGLDrawID(TCompiler *compiler, if (builtInVariable) { const TType *type = StaticType::Get(); - const TVariable *drawID = - new TVariable(symbolTable, kEmulatedGLDrawIDName, type, SymbolType::AngleInternal); - const TIntermSymbol *drawIDSymbol = new TIntermSymbol(drawID); - - // AngleInternal variables don't get collected - ShaderVariable uniform; - uniform.name = kEmulatedGLDrawIDName.data(); - uniform.mappedName = kEmulatedGLDrawIDName.data(); - uniform.type = GLVariableType(*type); - uniform.precision = GLVariablePrecision(*type); - uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable); - uniform.active = true; - uniform.binding = type->getLayoutQualifier().binding; - uniform.location = type->getLayoutQualifier().location; - uniform.offset = type->getLayoutQualifier().offset; - uniform.rasterOrdered = type->getLayoutQualifier().rasterOrdered; - uniform.readonly = type->getMemoryQualifier().readonly; - uniform.writeonly = type->getMemoryQualifier().writeonly; - uniforms->push_back(uniform); - - DeclareGlobalVariable(root, drawID); - if (!ReplaceVariableWithTyped(compiler, root, builtInVariable, drawIDSymbol)) + if (!EmulateBuiltIn(compiler, root, symbolTable, builtInVariable, type, + kEmulatedGLDrawIDName, uniforms)) { return false; } @@ -164,9 +168,6 @@ bool EmulateGLBaseVertexBaseInstance(TCompiler *compiler, std::vector *uniforms, bool addBaseVertexToVertexID) { - bool addBaseVertex = false, addBaseInstance = false; - ShaderVariable uniformBaseVertex, uniformBaseInstance; - if (addBaseVertexToVertexID) { // This is a workaround for Mac AMD GPU @@ -179,81 +180,38 @@ bool EmulateGLBaseVertexBaseInstance(TCompiler *compiler, } } - FindGLBaseVertexTraverser traverserBaseVertex; - root->traverse(&traverserBaseVertex); - const TVariable *builtInVariableBaseVertex = - traverserBaseVertex.getGLBaseVertexBuiltinVariable(); + FindGLBaseVertexBaseInstanceTraverser traverser; + root->traverse(&traverser); + const TVariable *builtInVariableBaseVertex = traverser.getGLBaseVertexBuiltinVariable(); + const TVariable *builtInVariableBaseInstance = traverser.getGLBaseInstanceBuiltinVariable(); if (builtInVariableBaseVertex) { - const TVariable *baseVertex = BuiltInVariable::angle_BaseVertex(); - const TType &type = baseVertex->getType(); - const TIntermSymbol *baseVertexSymbol = new TIntermSymbol(baseVertex); - - // AngleInternal variables don't get collected - uniformBaseVertex.name = kEmulatedGLBaseVertexName.data(); - uniformBaseVertex.mappedName = kEmulatedGLBaseVertexName.data(); - uniformBaseVertex.type = GLVariableType(type); - uniformBaseVertex.precision = GLVariablePrecision(type); - uniformBaseVertex.staticUse = symbolTable->isStaticallyUsed(*builtInVariableBaseVertex); - uniformBaseVertex.active = true; - uniformBaseVertex.binding = type.getLayoutQualifier().binding; - uniformBaseVertex.location = type.getLayoutQualifier().location; - uniformBaseVertex.offset = type.getLayoutQualifier().offset; - uniformBaseVertex.rasterOrdered = type.getLayoutQualifier().rasterOrdered; - uniformBaseVertex.readonly = type.getMemoryQualifier().readonly; - uniformBaseVertex.writeonly = type.getMemoryQualifier().writeonly; - addBaseVertex = true; - - DeclareGlobalVariable(root, baseVertex); - if (!ReplaceVariableWithTyped(compiler, root, builtInVariableBaseVertex, baseVertexSymbol)) + const TType *type = StaticType::Get(); + if (!EmulateBuiltIn(compiler, root, symbolTable, builtInVariableBaseVertex, type, + kEmulatedGLBaseVertexName, uniforms)) { return false; } } - FindGLBaseInstanceTraverser traverserInstance; - root->traverse(&traverserInstance); - const TVariable *builtInVariableBaseInstance = - traverserInstance.getGLBaseInstanceBuiltinVariable(); - if (builtInVariableBaseInstance) { - const TVariable *baseInstance = BuiltInVariable::angle_BaseInstance(); - const TType &type = baseInstance->getType(); - const TIntermSymbol *baseInstanceSymbol = new TIntermSymbol(baseInstance); - - // AngleInternal variables don't get collected - uniformBaseInstance.name = kEmulatedGLBaseInstanceName.data(); - uniformBaseInstance.mappedName = kEmulatedGLBaseInstanceName.data(); - uniformBaseInstance.type = GLVariableType(type); - uniformBaseInstance.precision = GLVariablePrecision(type); - uniformBaseInstance.staticUse = symbolTable->isStaticallyUsed(*builtInVariableBaseInstance); - uniformBaseInstance.active = true; - uniformBaseInstance.binding = type.getLayoutQualifier().binding; - uniformBaseInstance.location = type.getLayoutQualifier().location; - uniformBaseInstance.offset = type.getLayoutQualifier().offset; - uniformBaseInstance.rasterOrdered = type.getLayoutQualifier().rasterOrdered; - uniformBaseInstance.readonly = type.getMemoryQualifier().readonly; - uniformBaseInstance.writeonly = type.getMemoryQualifier().writeonly; - addBaseInstance = true; - - DeclareGlobalVariable(root, baseInstance); - if (!ReplaceVariableWithTyped(compiler, root, builtInVariableBaseInstance, - baseInstanceSymbol)) + const TType *type = StaticType::Get(); + if (!EmulateBuiltIn(compiler, root, symbolTable, builtInVariableBaseInstance, type, + kEmulatedGLBaseInstanceName, uniforms)) { return false; } } - // Make sure the order in uniforms is the same as the traverse order - if (addBaseInstance) - { - uniforms->push_back(uniformBaseInstance); - } - if (addBaseVertex) + // DeclareGlobalVariable prepends to the declarations, but the uniforms are appended. So if + // both base vertex and instance variables are added, the order doesn't match. Fix that here. + if (builtInVariableBaseVertex && builtInVariableBaseInstance) { - uniforms->push_back(uniformBaseVertex); + const size_t count = uniforms->size(); + ASSERT(count >= 2); + std::swap((*uniforms)[count - 1], (*uniforms)[count - 2]); } return true; diff --git a/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp b/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp deleted file mode 100644 index 00dd0131c64..00000000000 --- a/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright 2020 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. -// - -#include "compiler/translator/tree_ops/ForcePrecisionQualifier.h" -#include "angle_gl.h" -#include "common/debug.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ -class TPrecisionTraverser : public TIntermTraverser -{ - public: - TPrecisionTraverser(TSymbolTable *symbolTable); - - protected: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - - void overwriteVariablePrecision(TType *type) const; -}; - -TPrecisionTraverser::TPrecisionTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, true, true, symbolTable) -{} - -void TPrecisionTraverser::overwriteVariablePrecision(TType *type) const -{ - if (type->getPrecision() == EbpHigh) - { - type->setPrecision(EbpMedium); - } -} - -bool TPrecisionTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence &sequence = *(node->getSequence()); - TIntermTyped *variable = sequence.front()->getAsTyped(); - const TType &type = variable->getType(); - TQualifier qualifier = variable->getQualifier(); - - // Don't modify uniform since it might be shared between vertex and fragment shader - if (qualifier == EvqUniform) - { - return true; - } - - // Visit the struct. - if (type.isStructSpecifier()) - { - const TStructure *structure = type.getStruct(); - const TFieldList &fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TField *field = fields[i]; - const TType *fieldType = field->type(); - overwriteVariablePrecision((TType *)fieldType); - } - } - else if (type.getBasicType() == EbtInterfaceBlock) - { - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - const TFieldList &fields = interfaceBlock->fields(); - for (const TField *field : fields) - { - const TType *fieldType = field->type(); - overwriteVariablePrecision((TType *)fieldType); - } - } - else - { - overwriteVariablePrecision((TType *)&type); - } - } - return true; -} -} // namespace - -bool ForceShaderPrecisionToMediump(TIntermNode *root, TSymbolTable *symbolTable, GLenum shaderType) -{ - if (shaderType != GL_FRAGMENT_SHADER) - { - return true; - } - - TPrecisionTraverser traverser(symbolTable); - root->traverse(&traverser); - return true; -} - -} // namespace sh diff --git a/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h b/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h deleted file mode 100644 index c4cde254152..00000000000 --- a/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright 2020 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. -// - -#ifndef COMPILER_TRANSLATOR_TREEOPS_FORCEPRECISIONQUALIFIER_H_ -#define COMPILER_TRANSLATOR_TREEOPS_FORCEPRECISIONQUALIFIER_H_ - -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ -bool ForceShaderPrecisionToMediump(TIntermNode *root, TSymbolTable *symbolTable, GLenum shaderType); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_FORCEPRECISIONQUALIFIER_H_ diff --git a/src/compiler/translator/tree_ops/GatherDefaultUniforms.cpp b/src/compiler/translator/tree_ops/GatherDefaultUniforms.cpp new file mode 100644 index 00000000000..eec393b4452 --- /dev/null +++ b/src/compiler/translator/tree_ops/GatherDefaultUniforms.cpp @@ -0,0 +1,208 @@ +// +// Copyright 2025 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. +// + +#include "compiler/translator/tree_ops/GatherDefaultUniforms.h" + +#include "GLSLANG/ShaderVars.h" +#include "angle_gl.h" +#include "common/debug.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +class ReplaceDefaultUniformsTraverser : public TIntermTraverser +{ + public: + ReplaceDefaultUniformsTraverser(const VariableReplacementMap &variableMap) + : TIntermTraverser(true, false, false), mVariableMap(variableMap) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + + if (IsDefaultUniform(type)) + { + // Remove the uniform declaration. + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(emptyReplacement)); + + return false; + } + + return true; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + const TVariable &variable = symbol->variable(); + const TType &type = variable.getType(); + + if (!IsDefaultUniform(type) || gl::IsBuiltInName(variable.name().data())) + { + return; + } + + ASSERT(mVariableMap.count(variable.uniqueId()) > 0); + + queueReplacement(mVariableMap.at(variable.uniqueId())->deepCopy(), + OriginalNode::IS_DROPPED); + } + + private: + const VariableReplacementMap &mVariableMap; +}; + +// Fields of nameless interface blocks are TVariables. So when creating a new interface blocks we +// need to create all the TVariables representing its fields. +TIntermSymbol *CreateVariableForFieldOfNamelessInterfaceBlock(const TVariable *object, + int index, + TSymbolTable *symbolTable) +{ + ASSERT(object->getType().getInterfaceBlock()); + const TFieldList &fieldList = object->getType().getInterfaceBlock()->fields(); + + ASSERT(0 <= index); + ASSERT(static_cast(index) < fieldList.size()); + + ASSERT(object->symbolType() == SymbolType::Empty); + + TType *replacementType = new TType(*fieldList[index]->type()); + replacementType->setInterfaceBlockField(object->getType().getInterfaceBlock(), index); + + TVariable *replacementVariable = new TVariable(symbolTable, fieldList[index]->name(), + replacementType, fieldList[index]->symbolType()); + + return new TIntermSymbol(replacementVariable); +} + +} // namespace + +bool IsDefaultUniform(const TType &type) +{ + return type.getQualifier() == EvqUniform && type.getInterfaceBlock() == nullptr && + !IsOpaqueType(type.getBasicType()); +} + +TSet *GetActiveUniforms(const std::vector &defaultUniforms) +{ + auto activeUniforms = new TSet(); + for (const ShaderVariable &uniform : defaultUniforms) + { + if (uniform.active) + { + activeUniforms->insert(uniform.name); + } + } + + return activeUniforms; +} + +bool GatherDefaultUniforms(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + gl::ShaderType shaderType, + const ImmutableString &uniformBlockType, + const ImmutableString &uniformBlockVarName, + const TVariable **outUniformBlock) +{ + // First, collect all default uniforms and declare a uniform block. + TFieldList *uniformList = new TFieldList; + TVector uniformVars; + + TSet *activeUniforms = GetActiveUniforms(compiler->getUniforms()); + + for (TIntermNode *node : *root->getSequence()) + { + TIntermDeclaration *decl = node->getAsDeclarationNode(); + if (decl == nullptr) + { + continue; + } + + const TIntermSequence &sequence = *(decl->getSequence()); + + TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); + if (symbol == nullptr) + { + continue; + } + + const TType &type = symbol->getType(); + // Only gather active default uniforms. + if (IsDefaultUniform(type) && activeUniforms->count(symbol->getName()) != 0) + { + TType *fieldType = new TType(type); + + uniformList->push_back(new TField(fieldType, symbol->getName(), symbol->getLine(), + symbol->variable().symbolType())); + uniformVars.push_back(&symbol->variable()); + } + } + + VariableReplacementMap variableMap; + + if (uniformList->empty()) + { + *outUniformBlock = nullptr; + } + else + { + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.blockStorage = EbsStd140; + TInterfaceBlock *interfaceBlock = + DeclareInterfaceBlock(symbolTable, uniformList, layoutQualifier, uniformBlockType); + // Set the mIsDefaultUniformBlock bit because the interfaceBlock represents default uniform + // interfaceBlock. + // Later when traversing the AST and output SPIRV, we will rely on this bit to decide if we + // want to transform FP32 to FP16 for float based on if the float vars are inside the + // default uniform block. + interfaceBlock->setDefaultUniformBlock(); + *outUniformBlock = DeclareInterfaceBlockVariable( + root, symbolTable, EvqUniform, interfaceBlock, layoutQualifier, + TMemoryQualifier::Create(), 0, uniformBlockVarName); + + // Create a map from the uniform variables to new variables that reference the fields of the + // block. + for (size_t fieldIndex = 0; fieldIndex < uniformVars.size(); ++fieldIndex) + { + const TVariable *variable = uniformVars[fieldIndex]; + + if ((*outUniformBlock)->symbolType() == SymbolType::Empty) + { + variableMap[variable->uniqueId()] = CreateVariableForFieldOfNamelessInterfaceBlock( + *outUniformBlock, static_cast(fieldIndex), symbolTable); + } + else + { + variableMap[variable->uniqueId()] = AccessFieldOfNamedInterfaceBlock( + *outUniformBlock, static_cast(fieldIndex)); + } + } + } + + // Finally transform the AST and make sure references to the uniforms are replaced with the new + // variables. + ReplaceDefaultUniformsTraverser defaultTraverser(variableMap); + root->traverse(&defaultTraverser); + return defaultTraverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/src/compiler/translator/tree_ops/GatherDefaultUniforms.h b/src/compiler/translator/tree_ops/GatherDefaultUniforms.h new file mode 100644 index 00000000000..55409051923 --- /dev/null +++ b/src/compiler/translator/tree_ops/GatherDefaultUniforms.h @@ -0,0 +1,39 @@ +// +// Copyright 2025 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. +// +// GatherDefaultUniforms.h: gathers all default uniforms and puts them in an interface block, +// rewriting accesses of the default uniforms appropriately. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_GATHERDEFAULTUNIFORMS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_GATHERDEFAULTUNIFORMS_H_ + +#include "common/PackedGLEnums_autogen.h" +#include "compiler/translator/ImmutableString.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; +class TVariable; +class TType; + +[[nodiscard]] bool IsDefaultUniform(const TType &type); + +// Gathers all default uniforms into an interface block named `uniformBlockType`, with optional +// `uniformBlockVarName`. Rewrites accesses to the default uniform variables appropriately. Inserts +// the resulting interface block into the `root` tree and stores a pointer to the interface block in +// `outUniformBlock`. +[[nodiscard]] bool GatherDefaultUniforms(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + gl::ShaderType shaderType, + const ImmutableString &uniformBlockType, + const ImmutableString &uniformBlockVarName, + const TVariable **outUniformBlock); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_GATHERDEFAULTUNIFORMS_H_ diff --git a/src/compiler/translator/tree_ops/InitializeVariables.cpp b/src/compiler/translator/tree_ops/InitializeVariables.cpp index a37eb0e76c9..861e5f2a130 100644 --- a/src/compiler/translator/tree_ops/InitializeVariables.cpp +++ b/src/compiler/translator/tree_ops/InitializeVariables.cpp @@ -24,15 +24,22 @@ namespace sh namespace { +bool IsNamelessStruct(const TType &type) +{ + // There are two kinds of nameless structs that need to be handled here. When SymbolType is + // Empty, it's a struct that can take a temporary name. When the struct is "nameless", it + // _must_ stay without a name (because it's part of the shader's interface). + return type.getStruct() != nullptr && + (type.getStruct()->symbolType() == SymbolType::Empty || type.getStruct()->isNameless()); +} + void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable); void AddStructZeroInitSequence(const TIntermTyped *initializedNode, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable); @@ -44,20 +51,19 @@ TIntermBinary *CreateZeroInitAssignment(const TIntermTyped *initializedNode) void AddZeroInitSequence(const TIntermTyped *initializedNode, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable) { if (initializedNode->isArray()) { - AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, highPrecisionSupported, - initSequenceOut, symbolTable); + AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut, + symbolTable); } else if (initializedNode->getType().isStructureContainingArrays() || - initializedNode->getType().isNamelessStruct()) + IsNamelessStruct(initializedNode->getType())) { - AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, highPrecisionSupported, - initSequenceOut, symbolTable); + AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut, + symbolTable); } else if (initializedNode->getType().isInterfaceBlock()) { @@ -85,7 +91,6 @@ void AddZeroInitSequence(const TIntermTyped *initializedNode, void AddStructZeroInitSequence(const TIntermTyped *initializedNode, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable) { @@ -97,15 +102,13 @@ void AddStructZeroInitSequence(const TIntermTyped *initializedNode, initializedNode->deepCopy(), CreateIndexNode(i)); // Structs can't be defined inside structs, so the type of a struct field can't be a // nameless struct. - ASSERT(!element->getType().isNamelessStruct()); - AddZeroInitSequence(element, canUseLoopsToInitialize, highPrecisionSupported, - initSequenceOut, symbolTable); + ASSERT(!IsNamelessStruct(element->getType())); + AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable); } } void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable) { @@ -113,21 +116,17 @@ void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode, { TIntermBinary *element = new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i)); - AddZeroInitSequence(element, canUseLoopsToInitialize, highPrecisionSupported, - initSequenceOut, symbolTable); + AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable); } } void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable) { ASSERT(initializedNode->isArray()); - const TType *mediumpIndexType = StaticType::Get(); - const TType *highpIndexType = StaticType::Get(); TVariable *indexVariable = - CreateTempVariable(symbolTable, highPrecisionSupported ? highpIndexType : mediumpIndexType); + CreateTempVariable(symbolTable, StaticType::Get()); TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexVariable); TIntermDeclaration *indexInit = @@ -143,7 +142,7 @@ void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(), indexSymbolNode->deepCopy()); - AddZeroInitSequence(element, true, highPrecisionSupported, forLoopBodySeq, symbolTable); + AddZeroInitSequence(element, true, forLoopBodySeq, symbolTable); TIntermLoop *forLoop = new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody); @@ -152,14 +151,13 @@ void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initSequenceOut, TSymbolTable *symbolTable) { // The array elements are assigned one by one to keep the AST compatible with ESSL 1.00 which // doesn't have array assignment. We'll do this either with a for loop or just a list of // statements assigning to each array index. Note that it is important to have the array init in - // the right order to workaround http://crbug.com/709317 + // the right order to workaround http://crbug.com/40514481 bool isSmallArray = initializedNode->getOutermostArraySize() <= 1u || (initializedNode->getBasicType() != EbtStruct && !initializedNode->getType().isArrayOfArrays() && @@ -170,13 +168,12 @@ void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, { // Fragment outputs should not be indexed by non-constant indices. // Also it doesn't make sense to use loops to initialize very small arrays. - AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize, - highPrecisionSupported, initSequenceOut, symbolTable); + AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize, initSequenceOut, + symbolTable); } else { - AddArrayZeroInitForLoop(initializedNode, highPrecisionSupported, initSequenceOut, - symbolTable); + AddArrayZeroInitForLoop(initializedNode, initSequenceOut, symbolTable); } } @@ -186,8 +183,7 @@ void InsertInitCode(TCompiler *compiler, TSymbolTable *symbolTable, int shaderVersion, const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize, - bool highPrecisionSupported) + bool canUseLoopsToInitialize) { TIntermSequence *mainBody = FindMainBody(root)->getSequence(); for (const TVariable *var : variables) @@ -206,8 +202,7 @@ void InsertInitCode(TCompiler *compiler, initializedSymbol = ReferenceGlobalVariable(field->name(), *symbolTable); TIntermSequence initCode; - CreateInitCode(initializedSymbol, canUseLoopsToInitialize, highPrecisionSupported, - &initCode, symbolTable); + CreateInitCode(initializedSymbol, canUseLoopsToInitialize, &initCode, symbolTable); mainBody->insert(mainBody->begin(), initCode.begin(), initCode.end()); } @@ -228,8 +223,7 @@ void InsertInitCode(TCompiler *compiler, } TIntermSequence initCode; - CreateInitCode(initializedSymbol, canUseLoopsToInitialize, highPrecisionSupported, - &initCode, symbolTable); + CreateInitCode(initializedSymbol, canUseLoopsToInitialize, &initCode, symbolTable); mainBody->insert(mainBody->begin(), initCode.begin(), initCode.end()); } } @@ -256,12 +250,10 @@ class InitializeLocalsTraverser final : public TIntermTraverser public: InitializeLocalsTraverser(int shaderVersion, TSymbolTable *symbolTable, - bool canUseLoopsToInitialize, - bool highPrecisionSupported) + bool canUseLoopsToInitialize) : TIntermTraverser(true, false, false, symbolTable), mShaderVersion(shaderVersion), - mCanUseLoopsToInitialize(canUseLoopsToInitialize), - mHighPrecisionSupported(highPrecisionSupported) + mCanUseLoopsToInitialize(canUseLoopsToInitialize) {} void collectUnnamedOutFunctions(TIntermBlock &root) @@ -328,7 +320,7 @@ class InitializeLocalsTraverser final : public TIntermTraverser // TODO(oetuaho): Check if it makes sense to initialize using a loop, even if we // could use an initializer. It could at least reduce code size for very large // arrays, but could hurt runtime performance. - if (arrayConstructorUnavailable || symbol->getType().isNamelessStruct()) + if (arrayConstructorUnavailable || IsNamelessStruct(symbol->getType())) { // SimplifyLoopConditions should have been run so the parent node of this node // should not be a loop. @@ -338,8 +330,7 @@ class InitializeLocalsTraverser final : public TIntermTraverser // this declarator. ASSERT(node->getSequence()->size() == 1); TIntermSequence initCode; - CreateInitCode(symbol, mCanUseLoopsToInitialize, mHighPrecisionSupported, - &initCode, mSymbolTable); + CreateInitCode(symbol, mCanUseLoopsToInitialize, &initCode, mSymbolTable); insertStatementsInParentBlock(TIntermSequence(), initCode); } else @@ -396,8 +387,8 @@ class InitializeLocalsTraverser final : public TIntermTraverser continue; } - CreateInitCode(new TIntermSymbol(paramVariable), mCanUseLoopsToInitialize, - mHighPrecisionSupported, &initCode, mSymbolTable); + CreateInitCode(new TIntermSymbol(paramVariable), mCanUseLoopsToInitialize, &initCode, + mSymbolTable); } if (!initCode.empty()) @@ -429,7 +420,6 @@ class InitializeLocalsTraverser final : public TIntermTraverser private: int mShaderVersion; bool mCanUseLoopsToInitialize; - bool mHighPrecisionSupported; angle::HashMap mFunctionsToReplace; }; @@ -437,23 +427,19 @@ class InitializeLocalsTraverser final : public TIntermTraverser void CreateInitCode(const TIntermTyped *initializedSymbol, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initCode, TSymbolTable *symbolTable) { - AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, highPrecisionSupported, - initCode, symbolTable); + AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, initCode, symbolTable); } bool InitializeUninitializedLocals(TCompiler *compiler, TIntermBlock *root, int shaderVersion, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TSymbolTable *symbolTable) { - InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize, - highPrecisionSupported); + InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize); traverser.collectUnnamedOutFunctions(*root); root->traverse(&traverser); return traverser.updateTree(compiler, root); @@ -465,11 +451,10 @@ bool InitializeVariables(TCompiler *compiler, TSymbolTable *symbolTable, int shaderVersion, const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize, - bool highPrecisionSupported) + bool canUseLoopsToInitialize) { InsertInitCode(compiler, root, vars, symbolTable, shaderVersion, extensionBehavior, - canUseLoopsToInitialize, highPrecisionSupported); + canUseLoopsToInitialize); return compiler->validateAST(root); } diff --git a/src/compiler/translator/tree_ops/InitializeVariables.h b/src/compiler/translator/tree_ops/InitializeVariables.h index 23591da3b79..5745fb25d97 100644 --- a/src/compiler/translator/tree_ops/InitializeVariables.h +++ b/src/compiler/translator/tree_ops/InitializeVariables.h @@ -26,7 +26,6 @@ typedef std::vector InitVariableList; // may be an array, struct or any combination of these, as long as it contains only basic types. void CreateInitCode(const TIntermTyped *initializedSymbol, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TIntermSequence *initCode, TSymbolTable *symbolTable); @@ -35,7 +34,6 @@ void CreateInitCode(const TIntermTyped *initializedSymbol, TIntermBlock *root, int shaderVersion, bool canUseLoopsToInitialize, - bool highPrecisionSupported, TSymbolTable *symbolTable); // This function can initialize all the types that CreateInitCode is able to initialize. All @@ -52,8 +50,7 @@ void CreateInitCode(const TIntermTyped *initializedSymbol, TSymbolTable *symbolTable, int shaderVersion, const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize, - bool highPrecisionSupported); + bool canUseLoopsToInitialize); } // namespace sh diff --git a/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp b/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp index d65263ff83b..51fb85b801d 100644 --- a/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp +++ b/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp @@ -200,12 +200,12 @@ const TFunction *MonomorphizeFunction(TSymbolTable *symbolTable, originalParam->symbolType()); // Not replaced, add an identical parameter. substituteFunction->addParameter(substituteArgument); - (*argumentMapOut)[originalParam] = new TIntermSymbol(substituteArgument); + (*argumentMapOut)[originalParam->uniqueId()] = new TIntermSymbol(substituteArgument); } else { TIntermTyped *substituteArgument = (*replacedArguments)[nextReplacedArg].argument; - (*argumentMapOut)[originalParam] = substituteArgument; + (*argumentMapOut)[originalParam->uniqueId()] = substituteArgument; // Iterate over indices of the argument and create a new parameter for every non-const // index (which may be an expression). Replace the symbol in the argument with a @@ -535,7 +535,7 @@ void SortDeclarations(TIntermBlock *root) replacement.insert(replacement.end(), functionDefs.begin(), functionDefs.end()); // Replace root's sequence with |replacement|. - root->replaceAllChildren(replacement); + root->replaceAllChildren(std::move(replacement)); } bool MonomorphizeUnsupportedFunctionsImpl(TCompiler *compiler, diff --git a/src/compiler/translator/tree_ops/PruneInfiniteLoops.cpp b/src/compiler/translator/tree_ops/PruneInfiniteLoops.cpp deleted file mode 100644 index 79a3f72f971..00000000000 --- a/src/compiler/translator/tree_ops/PruneInfiniteLoops.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// -// 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. -// -// PruneInfiniteLoops.cpp: The PruneInfiniteLoops function prunes: -// -// 1. while (true) { ... } -// -// 2. bool variable = true; /* variable is never accessed */ -// while (variable) { ... } -// -// In all cases, the loop must not have EOpBreak or EOpReturn inside to be allowed to prune. -// -// In all cases, for (...; condition; ...) is treated the same as while (condition). -// -// It quickly gets error-prone when trying to detect more complicated cases. For example, it's -// temping to reject any |while (expression involving variable with no side effects)| because that's -// either while(true) or while(false), which is prune-able either way. That detects loops like -// while(variable == false), while(variable + 2 != 4). But for example -// while(coherent_buffer[variable]) may indeed not result in an infinite loop. For now, we stick to -// the basic case. - -#include "compiler/translator/tree_ops/PruneInfiniteLoops.h" - -#include "compiler/translator/Symbol.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -#include - -namespace sh -{ - -namespace -{ -using VariableSet = TUnorderedSet; - -class FindConstantVariablesTraverser : public TIntermTraverser -{ - public: - FindConstantVariablesTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable) - {} - - const VariableSet &getConstVariables() const { return mConstVariables; } - - private: - bool visitDeclaration(Visit, TIntermDeclaration *decl) override - { - // Initially, assume every variable is a constant - TIntermSequence *sequence = decl->getSequence(); - for (TIntermNode *node : *sequence) - { - TIntermSymbol *symbol = node->getAsSymbolNode(); - if (symbol == nullptr) - { - TIntermBinary *assign = node->getAsBinaryNode(); - ASSERT(assign != nullptr && assign->getOp() == EOpInitialize); - - symbol = assign->getLeft()->getAsSymbolNode(); - ASSERT(symbol != nullptr); - } - - ASSERT(mConstVariables.find(&symbol->variable()) == mConstVariables.end()); - mConstVariables.insert(&symbol->variable()); - } - - return false; - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - ASSERT(visit == PreVisit); - - // For simplicity, for now only consider conditions that are just |variable|. In that case, - // the condition is not visited, so that `visitSymbol` doesn't consider this a write. - if (loop->getInit() != nullptr) - { - loop->getInit()->traverse(this); - } - if (loop->getExpression() != nullptr) - { - loop->getExpression()->traverse(this); - } - loop->getBody()->traverse(this); - - TIntermTyped *condition = loop->getCondition(); - if (condition != nullptr && - (condition->getAsSymbolNode() == nullptr || loop->getType() == ELoopDoWhile)) - { - condition->traverse(this); - } - - return false; - } - - void visitSymbol(TIntermSymbol *symbol) override - { - // Assume write for simplicity. AST makes it difficult to tell if this is read or write. - mConstVariables.erase(&symbol->variable()); - } - - VariableSet mConstVariables; -}; - -struct LoopStats -{ - bool hasBreak = false; - bool hasReturn = false; -}; - -class PruneInfiniteLoopsTraverser : public TIntermTraverser -{ - public: - PruneInfiniteLoopsTraverser(TSymbolTable *symbolTable, const VariableSet &constVariables) - : TIntermTraverser(true, false, false, symbolTable), - mConstVariables(constVariables), - mAnyLoopsPruned(false) - {} - - bool anyLoopsPruned() const { return mAnyLoopsPruned; } - - private: - bool visitLoop(Visit visit, TIntermLoop *loop) override; - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - bool visitBranch(Visit visit, TIntermBranch *node) override; - - void onScopeBegin() { mLoopStats.push({}); } - - void onScopeEnd() - { - // Propagate |hasReturn| up the stack, it escapes every loop. - ASSERT(!mLoopStats.empty()); - bool hasReturn = mLoopStats.top().hasReturn; - mLoopStats.pop(); - - if (!mLoopStats.empty()) - { - mLoopStats.top().hasReturn = mLoopStats.top().hasReturn || hasReturn; - } - } - - bool hasLoopEscape() - { - ASSERT(!mLoopStats.empty()); - return mLoopStats.top().hasBreak || mLoopStats.top().hasReturn; - } - - const VariableSet &mConstVariables; - std::stack mLoopStats; - bool mAnyLoopsPruned; -}; - -bool PruneInfiniteLoopsTraverser::visitLoop(Visit visit, TIntermLoop *loop) -{ - onScopeBegin(); - - // Nothing in the init, condition or expression of loops can alter the control flow, just visit - // the body. - loop->getBody()->traverse(this); - - // Prune the loop if it has no breaks or returns, it's not do-while, and the condition is a - // constant variable. - TIntermTyped *condition = loop->getCondition(); - TIntermConstantUnion *constCondition = condition ? condition->getAsConstantUnion() : nullptr; - TIntermSymbol *conditionSymbol = condition ? loop->getCondition()->getAsSymbolNode() : nullptr; - - const bool isConditionConstant = - condition == nullptr || constCondition != nullptr || - (conditionSymbol != nullptr && - mConstVariables.find(&conditionSymbol->variable()) != mConstVariables.end()); - - if (isConditionConstant && loop->getType() != ELoopDoWhile && !hasLoopEscape()) - { - mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), loop, TIntermSequence{}); - mAnyLoopsPruned = true; - } - - onScopeEnd(); - - return false; -} - -bool PruneInfiniteLoopsTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - // Insert a LoopStats node for switch, just so that breaks inside the switch are not considered - // loop breaks. - onScopeBegin(); - - // Nothing in the switch expression that can alter the control flow, just visit the body. - node->getStatementList()->traverse(this); - - onScopeEnd(); - - return false; -} - -bool PruneInfiniteLoopsTraverser::visitBranch(Visit visit, TIntermBranch *node) -{ - if (!mLoopStats.empty()) - { - switch (node->getFlowOp()) - { - case EOpReturn: - mLoopStats.top().hasReturn = true; - break; - case EOpBreak: - mLoopStats.top().hasBreak = true; - break; - case EOpContinue: - case EOpKill: - // Kill and continue don't let control flow escape from the loop - break; - default: - UNREACHABLE(); - } - } - - // Only possible child is the value of a return statement, which has no significance. - return false; -} -} // namespace - -bool PruneInfiniteLoops(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable, - bool *anyLoopsPruned) -{ - *anyLoopsPruned = false; - - FindConstantVariablesTraverser constVarTransverser(symbolTable); - root->traverse(&constVarTransverser); - - PruneInfiniteLoopsTraverser pruneTraverser(symbolTable, - constVarTransverser.getConstVariables()); - root->traverse(&pruneTraverser); - *anyLoopsPruned = pruneTraverser.anyLoopsPruned(); - return pruneTraverser.updateTree(compiler, root); -} - -} // namespace sh diff --git a/src/compiler/translator/tree_ops/PruneInfiniteLoops.h b/src/compiler/translator/tree_ops/PruneInfiniteLoops.h deleted file mode 100644 index 0aae9e59dbd..00000000000 --- a/src/compiler/translator/tree_ops/PruneInfiniteLoops.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// 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. -// -// PruneInfiniteLoops.h: Attempts to remove infinite loops, used with WebGL contexts. - -#ifndef COMPILER_TRANSLATOR_TREEOPS_PRUNEINFINITELOOPS_H_ -#define COMPILER_TRANSLATOR_TREEOPS_PRUNEINFINITELOOPS_H_ - -#include "common/angleutils.h" - -namespace sh -{ -class TCompiler; -class TIntermBlock; -class TSymbolTable; - -[[nodiscard]] bool PruneInfiniteLoops(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable, - bool *anyLoopsPruned); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_PRUNEINFINITELOOPS_H_ diff --git a/src/compiler/translator/tree_ops/PruneNoOps.cpp b/src/compiler/translator/tree_ops/PruneNoOps.cpp index 45ead9f4f90..a2866f80e8e 100644 --- a/src/compiler/translator/tree_ops/PruneNoOps.cpp +++ b/src/compiler/translator/tree_ops/PruneNoOps.cpp @@ -112,6 +112,7 @@ class PruneNoOpsTraverser : private TIntermTraverser bool visitBlock(Visit visit, TIntermBlock *node) override; bool visitLoop(Visit visit, TIntermLoop *loop) override; bool visitBranch(Visit visit, TIntermBranch *node) override; + TIntermTyped *pruneNoOpCommaExpressions(TIntermTyped *statement); bool mIsBranchVisited = false; }; @@ -221,6 +222,22 @@ bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node) continue; } + // If the statement is a series of expressions delimited by comma, the resulting value is + // not used (because this is a block-level statement). Prune the no-op statements, and put + // the ones with side effect back together with comma. + if (statement->getAsBinaryNode() != nullptr) + { + statement = pruneNoOpCommaExpressions(statement->getAsBinaryNode()); + if (statement == nullptr) + { + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(node, statement, std::move(emptyReplacement)); + continue; + } + + statements[statementIndex] = statement; + } + // Visit the statement if not pruned. statement->traverse(this); } @@ -236,6 +253,40 @@ bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node) return false; } +TIntermTyped *PruneNoOpsTraverser::pruneNoOpCommaExpressions(TIntermTyped *statement) +{ + TIntermBinary *commaSeparatedExpressions = statement->getAsBinaryNode(); + if (commaSeparatedExpressions == nullptr || commaSeparatedExpressions->getOp() != EOpComma) + { + return statement; + } + + TIntermTyped *left = commaSeparatedExpressions->getLeft(); + TIntermTyped *right = commaSeparatedExpressions->getRight(); + + TIntermTyped *prunedLeft = IsNoOp(left) ? nullptr : pruneNoOpCommaExpressions(left); + TIntermTyped *prunedRight = IsNoOp(right) ? nullptr : pruneNoOpCommaExpressions(right); + + if (left == prunedLeft && right == prunedRight) + { + // Nothing got pruned. + return statement; + } + + // If either side is pruned, return the other side. Automatically returns nullptr if both sides + // are pruned. + if (prunedRight == nullptr) + { + return prunedLeft; + } + if (prunedLeft == nullptr) + { + return prunedRight; + } + + return new TIntermBinary(EOpComma, prunedLeft, prunedRight); +} + bool PruneNoOpsTraverser::visitLoop(Visit visit, TIntermLoop *loop) { if (visit != PreVisit) diff --git a/src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.cpp b/src/compiler/translator/tree_ops/ReduceInterfaceBlocks.cpp similarity index 53% rename from src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.cpp rename to src/compiler/translator/tree_ops/ReduceInterfaceBlocks.cpp index dde73e12e67..a34248b54d2 100644 --- a/src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.cpp +++ b/src/compiler/translator/tree_ops/ReduceInterfaceBlocks.cpp @@ -7,12 +7,14 @@ #include #include +#include + #include "compiler/translator/IntermRebuild.h" +#include "compiler/translator/Name.h" #include "compiler/translator/SymbolTable.h" -#include "compiler/translator/msl/AstHelpers.h" -#include "compiler/translator/msl/TranslatorMSL.h" +#include "compiler/translator/tree_ops/ReduceInterfaceBlocks.h" #include "compiler/translator/tree_ops/SeparateDeclarations.h" -#include "compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.h" +#include "compiler/translator/tree_util/IntermNode_util.h" using namespace sh; @@ -25,11 +27,11 @@ class Reducer : public TIntermRebuild { std::unordered_map mLiftedMap; std::unordered_map mInstanceMap; - IdGen &mIdGen; + InterfaceBlockInstanceVarNameGen &mInstanceVarNameGen; public: - Reducer(TCompiler &compiler, IdGen &idGen) - : TIntermRebuild(compiler, true, false), mIdGen(idGen) + Reducer(TCompiler &compiler, InterfaceBlockInstanceVarNameGen &instanceVarNameGen) + : TIntermRebuild(compiler, true, false), mInstanceVarNameGen(instanceVarNameGen) {} PreResult visitDeclarationPre(TIntermDeclaration &declNode) override @@ -44,43 +46,33 @@ class Reducer : public TIntermRebuild const SymbolType symbolType = var.symbolType(); if (const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock()) { - if (symbolType == SymbolType::Empty) + const bool isEmptySymbol = symbolType == SymbolType::Empty; + Name newInstanceVarName = + isEmptySymbol ? Name(mInstanceVarNameGen(), SymbolType::AngleInternal) + : Name(var); + + auto &structure = + *new TStructure(&mSymbolTable, interfaceBlock->name(), + &interfaceBlock->fields(), interfaceBlock->symbolType()); + auto &structVar = CreateStructTypeVariable(mSymbolTable, structure); + auto &instanceVar = + CreateInstanceVariable(mSymbolTable, structure, newInstanceVarName, + TQualifier::EvqBuffer, &type.getArraySizes()); + + if (isEmptySymbol) { - // Create instance variable - auto &structure = - *new TStructure(&mSymbolTable, interfaceBlock->name(), - &interfaceBlock->fields(), interfaceBlock->symbolType()); - auto &structVar = CreateStructTypeVariable(mSymbolTable, structure); - - auto &instanceVar = CreateInstanceVariable( - mSymbolTable, structure, mIdGen.createNewName(interfaceBlock->name()), - TQualifier::EvqBuffer, &type.getArraySizes()); mLiftedMap[interfaceBlock] = &instanceVar; - - TIntermNode *replacements[] = { - new TIntermDeclaration{new TIntermSymbol(&structVar)}, - new TIntermDeclaration{new TIntermSymbol(&instanceVar)}}; - return PreResult::Multi(std::begin(replacements), std::end(replacements)); } else { ASSERT(type.getQualifier() == TQualifier::EvqUniform); - - auto &structure = - *new TStructure(&mSymbolTable, interfaceBlock->name(), - &interfaceBlock->fields(), interfaceBlock->symbolType()); - auto &structVar = CreateStructTypeVariable(mSymbolTable, structure); - auto &instanceVar = - CreateInstanceVariable(mSymbolTable, structure, Name(var), - TQualifier::EvqBuffer, &type.getArraySizes()); - mInstanceMap[&var] = &instanceVar; - - TIntermNode *replacements[] = { - new TIntermDeclaration{new TIntermSymbol(&structVar)}, - new TIntermDeclaration{new TIntermSymbol(&instanceVar)}}; - return PreResult::Multi(std::begin(replacements), std::end(replacements)); } + + TIntermNode *replacements[] = { + new TIntermDeclaration{new TIntermSymbol(&structVar)}, + new TIntermDeclaration{new TIntermSymbol(&instanceVar)}}; + return PreResult::Multi(std::begin(replacements), std::end(replacements)); } } @@ -113,9 +105,11 @@ class Reducer : public TIntermRebuild //////////////////////////////////////////////////////////////////////////////// -bool sh::ReduceInterfaceBlocks(TCompiler &compiler, TIntermBlock &root, IdGen &idGen) +bool sh::ReduceInterfaceBlocks(TCompiler &compiler, + TIntermBlock &root, + InterfaceBlockInstanceVarNameGen nameGen) { - Reducer reducer(compiler, idGen); + Reducer reducer(compiler, nameGen); if (!reducer.rebuildRoot(root)) { return false; diff --git a/src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.h b/src/compiler/translator/tree_ops/ReduceInterfaceBlocks.h similarity index 68% rename from src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.h rename to src/compiler/translator/tree_ops/ReduceInterfaceBlocks.h index 294a077dec6..6f3bb43655f 100644 --- a/src/compiler/translator/tree_ops/msl/ReduceInterfaceBlocks.h +++ b/src/compiler/translator/tree_ops/ReduceInterfaceBlocks.h @@ -7,6 +7,8 @@ #ifndef COMPILER_TRANSLATOR_TREEOPS_MSL_REDUCEINTERFACEBLOCKS_H_ #define COMPILER_TRANSLATOR_TREEOPS_MSL_REDUCEINTERFACEBLOCKS_H_ +#include + #include "common/angleutils.h" #include "compiler/translator/Compiler.h" @@ -14,23 +16,19 @@ namespace sh { class TSymbolTable; +using InterfaceBlockInstanceVarNameGen = std::function; + // This rewrites interface block declarations only. // -// Access of interface blocks is not rewritten (e.g. TOperator::EOpIndexDirectInterfaceBlock). // -// XXX: ^ Still true? -// -// Example: -// uniform Foo { int x; }; -// Becomes: -// uniform int x; -// // Example: // uniform Foo { int x; } foo; // Becomes: // struct Foo { int x; }; uniform Foo x; // -[[nodiscard]] bool ReduceInterfaceBlocks(TCompiler &compiler, TIntermBlock &root, IdGen &idGen); +[[nodiscard]] bool ReduceInterfaceBlocks(TCompiler &compiler, + TIntermBlock &root, + InterfaceBlockInstanceVarNameGen nameGen); } // namespace sh diff --git a/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp b/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp index a5e20ebcb04..db6c0143d66 100644 --- a/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp +++ b/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp @@ -71,7 +71,7 @@ bool IsVariableActive(const std::vector &mVars, const ImmutableString return var.active; } } - UNREACHABLE(); + ASSERT(false); return true; } @@ -128,7 +128,7 @@ bool RemoveInactiveInterfaceVariablesTraverser::visitDeclaration(Visit visit, { removeDeclaration = !IsVariableActive(mInputVaryings, asSymbol->getName()); } - else if (qualifier == EvqFragmentOut) + else if (qualifier == EvqFragmentOut || qualifier == EvqFragmentInOut) { removeDeclaration = !IsVariableActive(mOutputVariables, asSymbol->getName()) && mRemoveFragmentOutputs; diff --git a/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp b/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp index 820939fc26c..57552fe9997 100644 --- a/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp +++ b/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp @@ -176,7 +176,8 @@ void RemoveUnreferencedVariablesTraverser::decrementStructTypeRefCount(const TTy void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDeclaration *node, TIntermTyped *declarator) { - if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct()) + if (declarator->getType().isStructSpecifier() && + declarator->getType().getStruct()->symbolType() != SymbolType::Empty) { unsigned int structId = declarator->getType().getStruct()->uniqueId().get(); unsigned int structRefCountInThisDeclarator = 1u; diff --git a/src/compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.cpp b/src/compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.cpp index 07e41fd00eb..ea84190197f 100644 --- a/src/compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.cpp +++ b/src/compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.cpp @@ -134,7 +134,7 @@ void FindUnusedInoutVariablesTraverser::visitSymbol(TIntermSymbol *node) // Some channels are written to ASSERT(mIsInMain); uint8_t channels = 0; - for (int channel : parentSwizzle->getSwizzleOffsets()) + for (uint32_t channel : parentSwizzle->getSwizzleOffsets()) { channels |= static_cast(1 << channel); } @@ -182,7 +182,7 @@ VariableReplacementMap FindUnusedInoutVariablesTraverser::getReplacementMap() co const TVariable *replacement = new TVariable(mSymbolTable, var->name(), newType, var->symbolType()); - replacementMap[var] = new TIntermSymbol(replacement); + replacementMap[var->uniqueId()] = new TIntermSymbol(replacement); } return replacementMap; diff --git a/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp b/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp index f92ef75bd40..83ee490122e 100644 --- a/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp +++ b/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp @@ -47,9 +47,11 @@ const TVariable *DeclareAtomicCountersBuffers(TIntermBlock *root, TSymbolTable * TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); layoutQualifier.blockStorage = EbsStd430; - return DeclareInterfaceBlock(root, symbolTable, fieldList, EvqBuffer, layoutQualifier, - coherentMemory, kMaxAtomicCounterBuffers, kAtomicCountersBlockName, - kAtomicCountersVarName); + const TInterfaceBlock *interfaceBlock = + DeclareInterfaceBlock(symbolTable, fieldList, layoutQualifier, kAtomicCountersBlockName); + return DeclareInterfaceBlockVariable(root, symbolTable, EvqBuffer, interfaceBlock, + layoutQualifier, coherentMemory, kMaxAtomicCounterBuffers, + kAtomicCountersVarName); } TIntermTyped *CreateUniformBufferOffset(const TIntermTyped *uniformBufferOffsets, int binding) diff --git a/src/compiler/translator/tree_ops/RewriteDfdy.cpp b/src/compiler/translator/tree_ops/RewriteDfdy.cpp index fd268c58159..91e58dab10e 100644 --- a/src/compiler/translator/tree_ops/RewriteDfdy.cpp +++ b/src/compiler/translator/tree_ops/RewriteDfdy.cpp @@ -24,20 +24,17 @@ namespace class Traverser : public TIntermTraverser { public: - Traverser(TSymbolTable *symbolTable, SpecConst *specConst, const DriverUniform *driverUniforms); + Traverser(TSymbolTable *symbolTable, const DriverUniform *driverUniforms); private: bool visitAggregate(Visit visit, TIntermAggregate *node) override; - SpecConst *mSpecConst = nullptr; const DriverUniform *mDriverUniforms = nullptr; }; Traverser::Traverser(TSymbolTable *symbolTable, - SpecConst *specConst, const DriverUniform *driverUniforms) : TIntermTraverser(true, false, false, symbolTable), - mSpecConst(specConst), mDriverUniforms(driverUniforms) {} @@ -78,12 +75,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) CreateBuiltInUnaryFunctionCallNode("dFdy", operand->deepCopy(), *mSymbolTable, 300); // Get rotation multiplier - TIntermTyped *swapXY = mSpecConst->getSwapXY(); - if (swapXY == nullptr) - { - swapXY = mDriverUniforms->getSwapXY(); - } - + TIntermTyped *swapXY = mDriverUniforms->getSwapXY(); TIntermTyped *swapXMultiplier = MakeSwapXMultiplier(swapXY); TIntermTyped *swapYMultiplier = MakeSwapYMultiplier(swapXY->deepCopy()); @@ -123,16 +115,9 @@ bool RewriteDfdy(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable, int shaderVersion, - SpecConst *specConst, const DriverUniform *driverUniforms) { - // dFdx/dFdy is only valid in GLSL 3.0 and later. - if (shaderVersion < 300) - { - return true; - } - - Traverser traverser(symbolTable, specConst, driverUniforms); + Traverser traverser(symbolTable, driverUniforms); root->traverse(&traverser); return traverser.updateTree(compiler, root); } diff --git a/src/compiler/translator/tree_ops/RewriteDfdy.h b/src/compiler/translator/tree_ops/RewriteDfdy.h index d1a63996968..2bf2c3fc0b8 100644 --- a/src/compiler/translator/tree_ops/RewriteDfdy.h +++ b/src/compiler/translator/tree_ops/RewriteDfdy.h @@ -17,14 +17,12 @@ namespace sh class TCompiler; class TIntermBlock; class TSymbolTable; -class SpecConst; class DriverUniform; [[nodiscard]] bool RewriteDfdy(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable, int shaderVersion, - SpecConst *specConst, const DriverUniform *driverUniforms); } // namespace sh diff --git a/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp b/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp index 580e4d1d424..b4232bdbc6d 100644 --- a/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp +++ b/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp @@ -279,6 +279,11 @@ class RewritePLSTraverser : public TIntermTraverser {expr, CreateFloatNode(0, EbpLow), CreateFloatNode(0, EbpLow), CreateFloatNode(1, EbpLow)}); break; + case EbtInt: + expr = TIntermAggregate::CreateConstructor( // "ivec4(r, 0, 0, 1)" + TType(EbtInt, 4), + {expr, CreateIndexNode(0), CreateIndexNode(0), CreateIndexNode(1)}); + break; case EbtUInt: expr = TIntermAggregate::CreateConstructor( // "uvec4(r, 0, 0, 1)" TType(EbtUInt, 4), @@ -301,7 +306,7 @@ class RewritePLSTraverser : public TIntermTraverser if (var->getType().getNominalSize() != n) { ASSERT(var->getType().getNominalSize() > n); - TVector swizzleOffsets{0, 1, 2, 3}; + TVector swizzleOffsets{0, 1, 2, 3}; swizzleOffsets.resize(n); swizzled = new TIntermSwizzle(swizzled, swizzleOffsets); } @@ -346,13 +351,13 @@ class RewritePLSToImagesTraverser : public RewritePLSTraverser TType *imageType = new TType(plsSymbol->getType()); - TLayoutQualifier layoutQualifier = imageType->getLayoutQualifier(); - switch (layoutQualifier.imageInternalFormat) + TLayoutQualifier imageLayoutQualifier = imageType->getLayoutQualifier(); + switch (imageLayoutQualifier.imageInternalFormat) { case TLayoutImageInternalFormat::EiifRGBA8: if (!mCompileOptions->pls.supportsNativeRGBA8ImageFormats) { - layoutQualifier.imageInternalFormat = EiifR32UI; + imageLayoutQualifier.imageInternalFormat = EiifR32UI; imageType->setPrecision(EbpHigh); imageType->setBasicType(EbtUImage2D); } @@ -364,7 +369,7 @@ class RewritePLSToImagesTraverser : public RewritePLSTraverser case TLayoutImageInternalFormat::EiifRGBA8I: if (!mCompileOptions->pls.supportsNativeRGBA8ImageFormats) { - layoutQualifier.imageInternalFormat = EiifR32I; + imageLayoutQualifier.imageInternalFormat = EiifR32I; imageType->setPrecision(EbpHigh); } imageType->setBasicType(EbtIImage2D); @@ -372,7 +377,7 @@ class RewritePLSToImagesTraverser : public RewritePLSTraverser case TLayoutImageInternalFormat::EiifRGBA8UI: if (!mCompileOptions->pls.supportsNativeRGBA8ImageFormats) { - layoutQualifier.imageInternalFormat = EiifR32UI; + imageLayoutQualifier.imageInternalFormat = EiifR32UI; imageType->setPrecision(EbpHigh); } imageType->setBasicType(EbtUImage2D); @@ -380,18 +385,29 @@ class RewritePLSToImagesTraverser : public RewritePLSTraverser case TLayoutImageInternalFormat::EiifR32F: imageType->setBasicType(EbtImage2D); break; + case TLayoutImageInternalFormat::EiifR32I: + imageType->setBasicType(EbtIImage2D); + break; case TLayoutImageInternalFormat::EiifR32UI: imageType->setBasicType(EbtUImage2D); break; default: UNREACHABLE(); } - layoutQualifier.rasterOrdered = - mCompileOptions->pls.fragmentSyncType == - ShFragmentSynchronizationType::RasterizerOrderViews_D3D || - mCompileOptions->pls.fragmentSyncType == - ShFragmentSynchronizationType::RasterOrderGroups_Metal; - imageType->setLayoutQualifier(layoutQualifier); + const bool noncoherentPLS = plsSymbol->getType().getLayoutQualifier().noncoherent; + // Clear the noncoherent qualifier for the image, in case it got copied over from the PLS + // variable. (noncoherent is not valid for images.) + imageLayoutQualifier.noncoherent = false; + imageLayoutQualifier.rasterOrdered = + !noncoherentPLS && (mCompileOptions->pls.fragmentSyncType == + ShFragmentSynchronizationType::RasterizerOrderViews_D3D || + mCompileOptions->pls.fragmentSyncType == + ShFragmentSynchronizationType::RasterOrderGroups_Metal); + if (!noncoherentPLS) + { + mAllPLSVarsNoncoherent = false; + } + imageType->setLayoutQualifier(imageLayoutQualifier); TMemoryQualifier memoryQualifier{}; memoryQualifier.coherent = true; @@ -583,40 +599,43 @@ class RewritePLSToImagesTraverser : public RewritePLSTraverser // can also block stores to PLS. compiler->specifyEarlyFragmentTests(); - // Delimit the beginning of a per-pixel critical section, if supported. This makes pixel - // local storage coherent. - // - // Either: GL_NV_fragment_shader_interlock - // GL_INTEL_fragment_shader_ordering - // GL_ARB_fragment_shader_interlock (may compile to - // SPV_EXT_fragment_shader_interlock) - switch (compileOptions.pls.fragmentSyncType) + if (!mAllPLSVarsNoncoherent) { - // Raster ordered resources don't need explicit synchronization calls. - case ShFragmentSynchronizationType::RasterizerOrderViews_D3D: - case ShFragmentSynchronizationType::RasterOrderGroups_Metal: - case ShFragmentSynchronizationType::NotSupported: - break; - case ShFragmentSynchronizationType::FragmentShaderInterlock_NV_GL: - mainBody->insertStatement( - plsBeginPosition, - CreateBuiltInFunctionCallNode("beginInvocationInterlockNV", {}, symbolTable, - kESSLInternalBackendBuiltIns)); - break; - case ShFragmentSynchronizationType::FragmentShaderOrdering_INTEL_GL: - mainBody->insertStatement( - plsBeginPosition, - CreateBuiltInFunctionCallNode("beginFragmentShaderOrderingINTEL", {}, - symbolTable, kESSLInternalBackendBuiltIns)); - break; - case ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL: - mainBody->insertStatement( - plsBeginPosition, - CreateBuiltInFunctionCallNode("beginInvocationInterlockARB", {}, symbolTable, - kESSLInternalBackendBuiltIns)); - break; - default: - UNREACHABLE(); + // Delimit the beginning of a per-pixel critical section, if supported. This makes pixel + // local storage coherent. + // + // Either: GL_NV_fragment_shader_interlock + // GL_INTEL_fragment_shader_ordering + // GL_ARB_fragment_shader_interlock (may compile to + // SPV_EXT_fragment_shader_interlock) + switch (compileOptions.pls.fragmentSyncType) + { + // Raster ordered resources don't need explicit synchronization calls. + case ShFragmentSynchronizationType::RasterizerOrderViews_D3D: + case ShFragmentSynchronizationType::RasterOrderGroups_Metal: + case ShFragmentSynchronizationType::NotSupported: + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_NV_GL: + mainBody->insertStatement( + plsBeginPosition, + CreateBuiltInFunctionCallNode("beginInvocationInterlockNV", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + case ShFragmentSynchronizationType::FragmentShaderOrdering_INTEL_GL: + mainBody->insertStatement( + plsBeginPosition, + CreateBuiltInFunctionCallNode("beginFragmentShaderOrderingINTEL", {}, + symbolTable, kESSLInternalBackendBuiltIns)); + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL: + mainBody->insertStatement( + plsBeginPosition, + CreateBuiltInFunctionCallNode("beginInvocationInterlockARB", {}, + symbolTable, kESSLInternalBackendBuiltIns)); + break; + default: + UNREACHABLE(); + } } } @@ -626,39 +645,43 @@ class RewritePLSToImagesTraverser : public RewritePLSTraverser TIntermBlock *mainBody, size_t plsEndPosition) override { - // Delimit the end of the PLS critical section, if required. - // - // Either: GL_NV_fragment_shader_interlock - // GL_ARB_fragment_shader_interlock (may compile to - // SPV_EXT_fragment_shader_interlock) - switch (compileOptions.pls.fragmentSyncType) + if (!mAllPLSVarsNoncoherent) { - // Raster ordered resources don't need explicit synchronization calls. - case ShFragmentSynchronizationType::RasterizerOrderViews_D3D: - case ShFragmentSynchronizationType::RasterOrderGroups_Metal: - // GL_INTEL_fragment_shader_ordering doesn't have an "end()" call. - case ShFragmentSynchronizationType::FragmentShaderOrdering_INTEL_GL: - case ShFragmentSynchronizationType::NotSupported: - break; - case ShFragmentSynchronizationType::FragmentShaderInterlock_NV_GL: + // Delimit the end of the PLS critical section, if required. + // + // Either: GL_NV_fragment_shader_interlock + // GL_ARB_fragment_shader_interlock (may compile to + // SPV_EXT_fragment_shader_interlock) + switch (compileOptions.pls.fragmentSyncType) + { + // Raster ordered resources don't need explicit synchronization calls. + case ShFragmentSynchronizationType::RasterizerOrderViews_D3D: + case ShFragmentSynchronizationType::RasterOrderGroups_Metal: + // GL_INTEL_fragment_shader_ordering doesn't have an "end()" call. + case ShFragmentSynchronizationType::FragmentShaderOrdering_INTEL_GL: + case ShFragmentSynchronizationType::NotSupported: + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_NV_GL: - mainBody->insertStatement( - plsEndPosition, - CreateBuiltInFunctionCallNode("endInvocationInterlockNV", {}, symbolTable, - kESSLInternalBackendBuiltIns)); - break; - case ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL: - mainBody->insertStatement( - plsEndPosition, - CreateBuiltInFunctionCallNode("endInvocationInterlockARB", {}, symbolTable, - kESSLInternalBackendBuiltIns)); - break; - default: - UNREACHABLE(); + mainBody->insertStatement( + plsEndPosition, + CreateBuiltInFunctionCallNode("endInvocationInterlockNV", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL: + mainBody->insertStatement( + plsEndPosition, + CreateBuiltInFunctionCallNode("endInvocationInterlockARB", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + default: + UNREACHABLE(); + } } } PLSBackingStoreMap mImages; + bool mAllPLSVarsNoncoherent = true; }; // Rewrites high level PLS operations to framebuffer fetch operations. @@ -774,6 +797,9 @@ class RewritePLSToFramebufferFetchTraverser : public RewritePLSTraverser case EiifR32F: accessVarType = new TType(EbtFloat, 1); break; + case EiifR32I: + accessVarType = new TType(EbtInt, 1); + break; case EiifR32UI: accessVarType = new TType(EbtUInt, 1); break; @@ -795,11 +821,19 @@ class RewritePLSToFramebufferFetchTraverser : public RewritePLSTraverser compiler->getResources().MaxCombinedDrawBuffersAndPixelLocalStoragePlanes - plsType.getLayoutQualifier().binding - 1; layoutQualifier.locationsSpecified = 1; - if (compileOptions.pls.fragmentSyncType == ShFragmentSynchronizationType::NotSupported) + if (compiler->getBuiltInResources().EXT_shader_framebuffer_fetch_non_coherent) { - // We're using EXT_shader_framebuffer_fetch_non_coherent, which requires the - // "noncoherent" qualifier. - layoutQualifier.noncoherent = true; + // EXT_shader_framebuffer_fetch_non_coherent requires the "noncoherent" qualifier if + // the coherent version of the extension isn't supported. The extension also allows + // us to opt into noncoherent accesses when PLS planes are specified as noncoherent + // by the shader. + // + // (Without EXT_shader_framebuffer_fetch_non_coherent, we just ignore the + // noncoherent qualifier, which is a perfectly valid implementation of the PLS + // spec.) + layoutQualifier.noncoherent = plsType.getLayoutQualifier().noncoherent || + compileOptions.pls.fragmentSyncType == + ShFragmentSynchronizationType::NotSupported; } fragmentVarType->setLayoutQualifier(layoutQualifier); @@ -871,9 +905,16 @@ bool RewritePixelLocalStorage(TCompiler *compiler, // just locking the entire main() function: // - Monomorphize all PLS calls into main(). // - Insert begin/end calls around the first/last PLS calls (and outside of flow control). - traverser->injectPrePLSCode(compiler, symbolTable, compileOptions, mainBody, 0); - traverser->injectPostPLSCode(compiler, symbolTable, compileOptions, mainBody, - mainBody->getChildCount()); + const size_t plsBeginPos = 0; + traverser->injectPrePLSCode(compiler, symbolTable, compileOptions, mainBody, plsBeginPos); + + size_t plsEndPos = mainBody->getChildCount(); + if (plsEndPos > 0 && mainBody->getChildNode(plsEndPos - 1)->getAsBranchNode() != nullptr) + { + // Make sure not to add code after terminating return, if any. + --plsEndPos; + } + traverser->injectPostPLSCode(compiler, symbolTable, compileOptions, mainBody, plsEndPos); // Assign the global pixel coord at the beginning of main(), if used. traverser->injectPixelCoordInitializationCodeIfNeeded(compiler, root, mainBody); diff --git a/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp b/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp index 7723a97f8e0..77262ed6e5b 100644 --- a/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp +++ b/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp @@ -8,8 +8,11 @@ #include "compiler/translator/tree_ops/RewriteStructSamplers.h" +#include "GLSLANG/ShaderVars.h" #include "common/hash_containers.h" #include "common/span.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableStringBuilder.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/tree_util/IntermNode_util.h" @@ -49,14 +52,23 @@ TIntermTyped *RewriteExpressionVisitBinaryHelper(TCompiler *compiler, const StructureUniformMap &structureUniformMap, const ExtractedSamplerMap &extractedSamplers) { - // Only interested in EOpIndexDirectStruct binary nodes. - if (node->getOp() != EOpIndexDirectStruct) + // Only interested in EOpIndex* binary nodes. + switch (node->getOp()) { - return nullptr; + case EOpIndexDirectInterfaceBlock: + case EOpIndexIndirect: + case EOpIndexDirect: + case EOpIndexDirectStruct: + break; + default: + return nullptr; } const TStructure *structure = node->getLeft()->getType().getStruct(); - ASSERT(structure); + if (structure == nullptr) + { + return nullptr; + } // If the result of the index is not a sampler and the struct is not replaced, there's nothing // to do. @@ -174,8 +186,6 @@ TIntermTyped *RewriteModifiedStructFieldSelectionExpression( const StructureUniformMap &structureUniformMap, const ExtractedSamplerMap &extractedSamplers) { - ASSERT(node->getOp() == EOpIndexDirectStruct); - const bool isSampler = node->getType().isSampler(); TIntermSymbol *baseUniform = nullptr; @@ -360,6 +370,23 @@ class RewriteStructSamplersTraverser final : public TIntermTraverser } private: + bool isActiveUniform(const ImmutableString &rootStructureName) + { + if (!mActiveUniforms) + { + mActiveUniforms = new TSet(); + for (const ShaderVariable &uniform : mCompiler->getUniforms()) + { + if (uniform.active) + { + mActiveUniforms->insert(uniform.name); + } + } + } + + return mActiveUniforms->count(rootStructureName) > 0; + } + // Removes all samplers from a struct specifier. void stripStructSpecifierSamplers(const TStructure *structure, TIntermSequence *newSequence) { @@ -462,7 +489,8 @@ class RewriteStructSamplersTraverser final : public TIntermTraverser for (const TField *field : structure->fields()) { - extractFieldSamplers(variable.name().data(), field, newSequence); + extractFieldSamplers(isActiveUniform(variable.name()), variable.name().data(), field, + newSequence); } // If there's a replacement structure (because there are non-sampler fields in the struct), @@ -496,7 +524,8 @@ class RewriteStructSamplersTraverser final : public TIntermTraverser } // Extracts samplers from a field of a struct. Works with nested structs and arrays. - void extractFieldSamplers(const std::string &prefix, + void extractFieldSamplers(bool inActiveUniform, + const std::string &prefix, const TField *field, TIntermSequence *newSequence) { @@ -507,7 +536,10 @@ class RewriteStructSamplersTraverser final : public TIntermTraverser if (fieldType.isSampler()) { - extractSampler(newPrefix, fieldType, newSequence); + if (inActiveUniform) + { + extractSampler(newPrefix, fieldType, newSequence); + } } else { @@ -515,7 +547,7 @@ class RewriteStructSamplersTraverser final : public TIntermTraverser const TStructure *structure = fieldType.getStruct(); for (const TField *nestedField : structure->fields()) { - extractFieldSamplers(newPrefix, nestedField, newSequence); + extractFieldSamplers(inActiveUniform, newPrefix, nestedField, newSequence); } exitArray(fieldType); } @@ -600,6 +632,9 @@ class RewriteStructSamplersTraverser final : public TIntermTraverser // A stack of array sizes. Used to figure out the array dimensions of the extracted sampler, // for example when it's nested in an array of structs in an array of structs. TVector mArraySizeStack; + + // Caches the names of all inactive uniforms. + TSet *mActiveUniforms = nullptr; }; } // anonymous namespace diff --git a/src/compiler/translator/tree_ops/RewriteStructSamplers.h b/src/compiler/translator/tree_ops/RewriteStructSamplers.h index f7b475135da..41ec8bf92d8 100644 --- a/src/compiler/translator/tree_ops/RewriteStructSamplers.h +++ b/src/compiler/translator/tree_ops/RewriteStructSamplers.h @@ -29,10 +29,10 @@ class TCompiler; class TIntermBlock; class TSymbolTable; -[[nodiscard]] bool RewriteStructSamplers(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable, - int *removedUniformsCountOut); +bool RewriteStructSamplers(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + int *removedUniformsCountOut); } // namespace sh #endif // COMPILER_TRANSLATOR_TREEOPS_REWRITESTRUCTSAMPLERS_H_ diff --git a/src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.cpp b/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp similarity index 75% rename from src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.cpp rename to src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp index 71638cb0692..ae0ab5adadc 100644 --- a/src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.cpp +++ b/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp @@ -8,13 +8,16 @@ // driver bugs around vector and matrix constructors. // -#include "compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h" +#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h" -#include "angle_gl.h" -#include "common/angleutils.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" +#if defined(ANGLE_ENABLE_GLSL) || defined(ANGLE_ENABLE_WGPU) + +# include "angle_gl.h" +# include "common/angleutils.h" +# include "compiler/translator/Compiler.h" +# include "compiler/translator/IntermNode.h" +# include "compiler/translator/tree_util/IntermNode_util.h" +# include "compiler/translator/tree_util/IntermTraverse.h" namespace sh { @@ -41,6 +44,20 @@ const TType *GetHelperType(const TType &type, TQualifier qualifier) return newType; } +// Cast a scalar to the basic type of node. No-ops if scalar is already the right type. +TIntermNode *CastScalar(TIntermAggregate *node, TIntermTyped *scalar) +{ + const TType &nodeType = node->getType(); + const TBasicType nodeBasicType = nodeType.getBasicType(); + if (scalar->getType().getBasicType() == nodeBasicType) + { + return scalar; + } + + TType castDestType(nodeBasicType, nodeType.getPrecision()); + return TIntermAggregate::CreateConstructor(castDestType, {scalar}); +} + // Traverser that converts a vector or matrix constructor to one that only uses scalars. To support // all the various places such a constructor could be found, a helper function is created for each // such constructor. The helper function takes the constructor arguments and creates the object. @@ -84,10 +101,17 @@ class ScalarizeTraverser : public TIntermTraverser // arguments. Otherwise, recursively visit the node. TIntermTyped *createConstructor(TIntermTyped *node); - void extractComponents(const TFunction *helper, + void extractComponents(TIntermAggregate *node, + const TFunction *helper, size_t componentCount, TIntermSequence *componentsOut); + void createConstructorScalarFromVector(TIntermAggregate *node, + const TFunction *helper, + TIntermSequence *constructorArgsOut); + void createConstructorScalarFromMatrix(TIntermAggregate *node, + const TFunction *helper, + TIntermSequence *constructorArgsOut); void createConstructorVectorFromScalar(TIntermAggregate *node, const TFunction *helper, TIntermSequence *constructorArgsOut); @@ -135,7 +159,12 @@ bool ScalarizeTraverser::shouldScalarize(TIntermTyped *typed) const TIntermSequence &arguments = *node->getSequence(); const TType &arg0Type = arguments[0]->getAsTyped()->getType(); - const bool isSingleVectorCast = arguments.size() == 1 && type.isVector() && + const bool isCastNonScalarToScalar = + arguments.size() == 1 && type.isScalar() && (arg0Type.isVector() || arg0Type.isMatrix()); + // In the case of a scalar constructor, early out if the constructor argument isn't a non-scalar + // (which need special handling). + const bool isInactionableScalar = type.isScalar() && !isCastNonScalarToScalar; + const bool isSingleVectorCast = arguments.size() == 1 && type.isVector() && arg0Type.isVector() && type.getNominalSize() == arg0Type.getNominalSize(); const bool isSingleMatrixCast = arguments.size() == 1 && type.isMatrix() && @@ -143,8 +172,8 @@ bool ScalarizeTraverser::shouldScalarize(TIntermTyped *typed) type.getRows() == arg0Type.getRows(); // Skip non-vector non-matrix constructors, as well as trivial constructors. - if (type.isArray() || type.getStruct() != nullptr || type.isScalar() || isSingleVectorCast || - isSingleMatrixCast) + if (type.isArray() || type.getStruct() != nullptr || isInactionableScalar || + isSingleVectorCast || isSingleMatrixCast) { return false; } @@ -207,7 +236,18 @@ TIntermTyped *ScalarizeTraverser::createConstructor(TIntermTyped *typed) const TFunction *helper = createHelper(node); TIntermSequence constructorArgs; - if (type.isVector()) + if (type.isScalar()) + { + if (arg0Type.isVector()) + { + createConstructorScalarFromVector(node, helper, &constructorArgs); + } + else if (arg0Type.isMatrix()) + { + createConstructorScalarFromMatrix(node, helper, &constructorArgs); + } + } + else if (type.isVector()) { if (arguments.size() == 1 && arg0Type.isScalar()) { @@ -240,7 +280,8 @@ TIntermTyped *ScalarizeTraverser::createConstructor(TIntermTyped *typed) // Extract enough scalar arguments from the arguments of helper to produce enough arguments for the // constructor call (given in componentCount). -void ScalarizeTraverser::extractComponents(const TFunction *helper, +void ScalarizeTraverser::extractComponents(TIntermAggregate *node, + const TFunction *helper, size_t componentCount, TIntermSequence *componentsOut) { @@ -254,7 +295,7 @@ void ScalarizeTraverser::extractComponents(const TFunction *helper, if (argumentType.isScalar()) { // For scalar parameters, there's nothing to do - componentsOut->push_back(argument); + componentsOut->push_back(CastScalar(node, argument)); continue; } if (argumentType.isVector()) @@ -265,7 +306,7 @@ void ScalarizeTraverser::extractComponents(const TFunction *helper, ++componentIndex) { componentsOut->push_back( - new TIntermSwizzle(argument->deepCopy(), {componentIndex})); + CastScalar(node, new TIntermSwizzle(argument->deepCopy(), {componentIndex}))); } continue; } @@ -285,12 +326,34 @@ void ScalarizeTraverser::extractComponents(const TFunction *helper, componentIndex < argumentType.getRows() && componentsOut->size() < componentCount; ++componentIndex) { - componentsOut->push_back(new TIntermSwizzle(col->deepCopy(), {componentIndex})); + componentsOut->push_back( + CastScalar(node, new TIntermSwizzle(col->deepCopy(), {componentIndex}))); } } } } +void ScalarizeTraverser::createConstructorScalarFromVector(TIntermAggregate *node, + const TFunction *helper, + TIntermSequence *constructorArgsOut) +{ + TIntermTyped *vec = new TIntermSymbol(helper->getParam(0)); + ASSERT(vec->getType().isVector()); + // No need to cast since the scalar constructor is the cast. + constructorArgsOut->push_back(new TIntermSwizzle(vec, {0})); +} + +void ScalarizeTraverser::createConstructorScalarFromMatrix(TIntermAggregate *node, + const TFunction *helper, + TIntermSequence *constructorArgsOut) +{ + TIntermTyped *matrix = new TIntermSymbol(helper->getParam(0)); + ASSERT(matrix->getType().isMatrix()); + TIntermTyped *col = new TIntermBinary(EOpIndexDirect, matrix, CreateIndexNode(0)); + // No need to cast since the scalar constructor is the cast. + constructorArgsOut->push_back(new TIntermSwizzle(col, {static_cast(0)})); +} + void ScalarizeTraverser::createConstructorVectorFromScalar(TIntermAggregate *node, const TFunction *helper, TIntermSequence *constructorArgsOut) @@ -302,7 +365,7 @@ void ScalarizeTraverser::createConstructorVectorFromScalar(TIntermAggregate *nod // Replicate the single scalar argument as many times as necessary. for (size_t index = 0; index < type.getNominalSize(); ++index) { - constructorArgsOut->push_back(scalar->deepCopy()); + constructorArgsOut->push_back(CastScalar(node, scalar->deepCopy())); } } @@ -310,7 +373,7 @@ void ScalarizeTraverser::createConstructorVectorFromMultiple(TIntermAggregate *n const TFunction *helper, TIntermSequence *constructorArgsOut) { - extractComponents(helper, node->getType().getNominalSize(), constructorArgsOut); + extractComponents(node, helper, node->getType().getNominalSize(), constructorArgsOut); } void ScalarizeTraverser::createConstructorMatrixFromScalar(TIntermAggregate *node, @@ -328,7 +391,7 @@ void ScalarizeTraverser::createConstructorMatrixFromScalar(TIntermAggregate *nod { if (columnIndex == rowIndex) { - constructorArgsOut->push_back(scalar->deepCopy()); + constructorArgsOut->push_back(CastScalar(node, scalar->deepCopy())); } else { @@ -344,7 +407,7 @@ void ScalarizeTraverser::createConstructorMatrixFromVectors(TIntermAggregate *no TIntermSequence *constructorArgsOut) { const TType &type = node->getType(); - extractComponents(helper, type.getCols() * type.getRows(), constructorArgsOut); + extractComponents(node, helper, type.getCols() * type.getRows(), constructorArgsOut); } void ScalarizeTraverser::createConstructorMatrixFromMatrix(TIntermAggregate *node, @@ -365,7 +428,7 @@ void ScalarizeTraverser::createConstructorMatrixFromMatrix(TIntermAggregate *nod TIntermTyped *col = new TIntermBinary(EOpIndexDirect, matrix->deepCopy(), CreateIndexNode(columnIndex)); constructorArgsOut->push_back( - new TIntermSwizzle(col, {static_cast(rowIndex)})); + CastScalar(node, new TIntermSwizzle(col, {static_cast(rowIndex)}))); } else { @@ -396,3 +459,16 @@ bool ScalarizeVecAndMatConstructorArgs(TCompiler *compiler, return scalarizer.update(compiler, root); } } // namespace sh + +#else +namespace sh +{ +bool ScalarizeVecAndMatConstructorArgs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + UNREACHABLE(); + return false; +} +} // namespace sh +#endif // defined(ANGLE_ENABLE_GLSL) || defined(ANGLE_ENABLE_WGPU) diff --git a/src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h b/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h similarity index 75% rename from src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h rename to src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h index b69a9436cd6..ca0f9a500f5 100644 --- a/src/compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h +++ b/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h @@ -21,19 +21,9 @@ class TCompiler; class TIntermBlock; class TSymbolTable; -#ifdef ANGLE_ENABLE_GLSL [[nodiscard]] bool ScalarizeVecAndMatConstructorArgs(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable); -#else -[[nodiscard]] ANGLE_INLINE bool ScalarizeVecAndMatConstructorArgs(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable) -{ - UNREACHABLE(); - return false; -} -#endif } // namespace sh diff --git a/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp b/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp index fb3f4ba1c1b..19c578d3441 100644 --- a/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp +++ b/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp @@ -50,9 +50,9 @@ class Traverser : public TIntermTraverser void visitSymbol(TIntermSymbol *symbol) override { const TVariable *variable = &symbol->variable(); - if (mVariableMap.count(variable) > 0) + if (mVariableMap.count(variable->uniqueId()) > 0) { - queueAccessChainReplacement(mVariableMap[variable]->deepCopy()); + queueAccessChainReplacement(mVariableMap[variable->uniqueId()]->deepCopy()); } } @@ -94,7 +94,7 @@ class Traverser : public TIntermTraverser newSequence.push_back(namedDecl); - mVariableMap[&asSymbol->variable()] = newSymbol; + mVariableMap[asSymbol->variable().uniqueId()] = newSymbol; mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl, std::move(newSequence)); diff --git a/src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.cpp b/src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.cpp deleted file mode 100644 index 1d276c26bb5..00000000000 --- a/src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.cpp +++ /dev/null @@ -1,143 +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. -// - -// RewriteDoWhile.cpp: rewrites do-while loops using another equivalent -// construct. - -#include "compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h" - -#include "compiler/translator/Compiler.h" -#include "compiler/translator/StaticType.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that rewrites loops of the form -// do { -// CODE; -// } while (CONDITION) -// -// to loops of the form -// bool temp = false; -// while (true) { -// if (temp) { -// if (!CONDITION) { -// break; -// } -// } -// temp = true; -// CODE; -// } -// -// The reason we don't use a simpler form, with for example just (temp && !CONDITION) in the -// while condition, is that short-circuit is often badly supported by driver shader compiler. -// The double if has the same effect, but forces shader compilers to behave. -// -// TODO(cwallez) when UnfoldShortCircuitIntoIf handles loops correctly, revisit this as we might -// be able to use while (temp || CONDITION) with temp initially set to true then run -// UnfoldShortCircuitIntoIf -class DoWhileRewriter : public TIntermTraverser -{ - public: - DoWhileRewriter(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) - {} - - bool visitBlock(Visit, TIntermBlock *node) override - { - // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal - // we are able to replace the do-while in the sequence directly as the content of the - // do-while will be traversed later. - - TIntermSequence *statements = node->getSequence(); - - // The statements vector will have new statements inserted when we encounter a do-while, - // which prevents us from using a range-based for loop. Using the usual i++ works, as - // the (two) new statements inserted replace the statement at the current position. - for (size_t i = 0; i < statements->size(); i++) - { - TIntermNode *statement = (*statements)[i]; - TIntermLoop *loop = statement->getAsLoopNode(); - - if (loop == nullptr || loop->getType() != ELoopDoWhile) - { - continue; - } - - // Found a loop to change. - const TType *boolType = StaticType::Get(); - TVariable *conditionVariable = CreateTempVariable(mSymbolTable, boolType); - - // bool temp = false; - TIntermDeclaration *tempDeclaration = - CreateTempInitDeclarationNode(conditionVariable, CreateBoolNode(false)); - - // temp = true; - TIntermBinary *assignTrue = - CreateTempAssignmentNode(conditionVariable, CreateBoolNode(true)); - - // if (temp) { - // if (!CONDITION) { - // break; - // } - // } - TIntermIfElse *breakIf = nullptr; - { - TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr); - - TIntermBlock *breakBlock = new TIntermBlock(); - breakBlock->getSequence()->push_back(breakStatement); - - TIntermUnary *negatedCondition = - new TIntermUnary(EOpLogicalNot, loop->getCondition(), nullptr); - - TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr); - - TIntermBlock *innerIfBlock = new TIntermBlock(); - innerIfBlock->getSequence()->push_back(innerIf); - - breakIf = new TIntermIfElse(CreateTempSymbolNode(conditionVariable), innerIfBlock, - nullptr); - } - - // Assemble the replacement loops, reusing the do-while loop's body and inserting our - // statements at the front. - TIntermLoop *newLoop = nullptr; - { - TIntermBlock *body = loop->getBody(); - auto sequence = body->getSequence(); - sequence->insert(sequence->begin(), assignTrue); - sequence->insert(sequence->begin(), breakIf); - - newLoop = new TIntermLoop(ELoopWhile, nullptr, CreateBoolNode(true), nullptr, body); - } - - TIntermSequence replacement; - replacement.push_back(tempDeclaration); - replacement.push_back(newLoop); - - node->replaceChildNodeWithMultiple(loop, replacement); - } - return true; - } -}; - -} // anonymous namespace - -bool RewriteDoWhile(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) -{ - DoWhileRewriter rewriter(symbolTable); - - root->traverse(&rewriter); - - return compiler->validateAST(root); -} - -} // namespace sh diff --git a/src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h b/src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h deleted file mode 100644 index f4015c29eac..00000000000 --- a/src/compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h +++ /dev/null @@ -1,39 +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. -// - -// RewriteDoWhile.h: rewrite do-while loops as while loops to work around -// driver bugs - -#ifndef COMPILER_TRANSLATOR_TREEOPS_GLSL_APPLE_REWRITEDOWHILE_H_ -#define COMPILER_TRANSLATOR_TREEOPS_GLSL_APPLE_REWRITEDOWHILE_H_ - -#include "common/angleutils.h" -#include "common/debug.h" - -namespace sh -{ - -class TCompiler; -class TIntermNode; -class TSymbolTable; - -#if ANGLE_ENABLE_GLSL && ANGLE_PLATFORM_APPLE -[[nodiscard]] bool RewriteDoWhile(TCompiler *compiler, - TIntermNode *root, - TSymbolTable *symbolTable); -#else -[[nodiscard]] ANGLE_INLINE bool RewriteDoWhile(TCompiler *compiler, - TIntermNode *root, - TSymbolTable *symbolTable) -{ - UNREACHABLE(); - return false; -} -#endif - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_GLSL_APPLE_REWRITEDOWHILE_H_ diff --git a/src/compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.cpp b/src/compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.cpp index 4e58f49eacc..3c17f3a24e4 100644 --- a/src/compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.cpp +++ b/src/compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.cpp @@ -137,7 +137,7 @@ TOperator GetIndex(TSymbolTable *symbolTable, TIntermSwizzle *asSwizzle = node->getAsSwizzleNode(); if (asSwizzle) { - for (int channel : asSwizzle->getSwizzleOffsets()) + for (uint32_t channel : asSwizzle->getSwizzleOffsets()) { indices->push_back(CreateIndexNode(channel)); } diff --git a/src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.cpp b/src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.cpp deleted file mode 100644 index ae863175e8e..00000000000 --- a/src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright 2016 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. -// - -#include "compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h" - -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - [[nodiscard]] static bool Apply(TCompiler *compiler, TIntermNode *root); - - private: - Traverser(); - bool visitUnary(Visit visit, TIntermUnary *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -bool Traverser::Apply(TCompiler *compiler, TIntermNode *root) -{ - Traverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - if (!traverser.updateTree(compiler, root)) - { - return false; - } - } - } while (traverser.mFound); - - return true; -} - -Traverser::Traverser() : TIntermTraverser(true, false, false) {} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFound) - { - return false; - } - - // Detect if the current operator is unary minus operator. - if (node->getOp() != EOpNegative) - { - return true; - } - - // Detect if the current operand is a float variable. - TIntermTyped *fValue = node->getOperand(); - if (!fValue->getType().isScalarFloat()) - { - return true; - } - - // 0.0 - float - TIntermTyped *zero = CreateZeroNode(fValue->getType()); - zero->setLine(fValue->getLine()); - TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue); - sub->setLine(fValue->getLine()); - - queueReplacement(sub, OriginalNode::IS_DROPPED); - - mFound = true; - return false; -} - -} // anonymous namespace - -bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, TIntermNode *root) -{ - return Traverser::Apply(compiler, root); -} - -} // namespace sh diff --git a/src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h b/src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h deleted file mode 100644 index cc1d951660e..00000000000 --- a/src/compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 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. -// -// Rewrite "-float" to "0.0 - float" to work around unary minus operator on float issue on Intel Mac -// OSX 10.11. - -#ifndef COMPILER_TRANSLATOR_TREEOPS_GLSL_APPLE_REWRITEUNARYMINUSOPERATORFLOAT_H_ -#define COMPILER_TRANSLATOR_TREEOPS_GLSL_APPLE_REWRITEUNARYMINUSOPERATORFLOAT_H_ - -#include "common/angleutils.h" -#include "common/debug.h" - -namespace sh -{ -class TCompiler; -class TIntermNode; - -#if ANGLE_ENABLE_GLSL && ANGLE_PLATFORM_APPLE -[[nodiscard]] bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, TIntermNode *root); -#else -[[nodiscard]] ANGLE_INLINE bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, - TIntermNode *root) -{ - UNREACHABLE(); - return false; -} -#endif - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_GLSL_APPLE_REWRITEUNARYMINUSOPERATORFLOAT_H_ diff --git a/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.cpp b/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.cpp deleted file mode 100644 index 0aa409d4f38..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Copyright 2022 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. -// - -#include "compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h" - -#include "compiler/translator/StaticType.h" -#include "compiler/translator/Symbol.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -class AggregateAssignArraysInSSBOsTraverser : public TIntermTraverser -{ - public: - AggregateAssignArraysInSSBOsTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable) - {} - - protected: - bool visitBinary(Visit visit, TIntermBinary *node) override - { - // Replace all aggregate assignments to arrays in SSBOs with element-by-element assignments. - // TODO(anglebug.com/42265833): this implementation only works for the simple case - // (assignment statement), not more complex cases such as assignment-as-expression or - // functions with side effects in the RHS. - - if (node->getOp() != EOpAssign) - { - return true; - } - else if (!node->getLeft()->getType().isArray()) - { - return true; - } - else if (!IsInShaderStorageBlock(node->getLeft())) - { - return true; - } - const TType *mediumpIndexType = StaticType::Get(); - auto *indexVariable = CreateTempVariable(mSymbolTable, mediumpIndexType); - auto *indexInit = - CreateTempInitDeclarationNode(indexVariable, CreateZeroNode(indexVariable->getType())); - auto *arraySizeNode = CreateIndexNode(node->getOutermostArraySize()); - auto *indexSymbolNode = CreateTempSymbolNode(indexVariable); - auto *cond = new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); - auto *indexIncrement = - new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr); - auto *forLoopBody = new TIntermBlock(); - auto *indexedLeft = - new TIntermBinary(EOpIndexDirect, node->getLeft(), indexSymbolNode->deepCopy()); - auto *indexedRight = - new TIntermBinary(EOpIndexDirect, node->getRight(), indexSymbolNode->deepCopy()); - auto *assign = new TIntermBinary(TOperator::EOpAssign, indexedLeft, indexedRight); - forLoopBody->appendStatement(assign); - auto *forLoop = new TIntermLoop(ELoopFor, indexInit, cond, indexIncrement, forLoopBody); - queueReplacement(forLoop, OriginalNode::IS_DROPPED); - return false; - } -}; - -} // namespace - -bool AggregateAssignArraysInSSBOs(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable) -{ - AggregateAssignArraysInSSBOsTraverser traverser(symbolTable); - root->traverse(&traverser); - return traverser.updateTree(compiler, root); -} - -} // namespace sh diff --git a/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h b/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h deleted file mode 100644 index bd487b069b3..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright 2022 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. -// - -#ifndef COMPILER_TRANSLATOR_TREEOPS_HLSL_AGGREGATEASSIGNARRAYSINSSBOS_H_ -#define COMPILER_TRANSLATOR_TREEOPS_HLSL_AGGREGATEASSIGNARRAYSINSSBOS_H_ - -#include "common/angleutils.h" - -namespace sh -{ -class TCompiler; -class TIntermBlock; -class TSymbolTable; - -[[nodiscard]] bool AggregateAssignArraysInSSBOs(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_HLSL_AGGREGATEASSIGNARRAYSINSSBOS_H_ diff --git a/src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.cpp b/src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.cpp deleted file mode 100644 index 215dd322740..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright 2022 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. -// - -#include "compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.h" - -#include "compiler/translator/StaticType.h" -#include "compiler/translator/Symbol.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -class AggregateAssignStructsInSSBOsTraverser : public TIntermTraverser -{ - public: - AggregateAssignStructsInSSBOsTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable) - {} - - protected: - bool visitBinary(Visit visit, TIntermBinary *node) override - { - // Replace all assignments to structs in SSBOs with field-by-field asignments. - // TODO(anglebug.com/42265832): this implementation only works for the simple case - // (assignment statement), not more complex cases such as assignment-as-expression or - // functions with side effects in the RHS. - const TStructure *s; - if (node->getOp() != EOpAssign) - { - return true; - } - else if (!IsInShaderStorageBlock(node->getLeft())) - { - return true; - } - else if (!(s = node->getLeft()->getType().getStruct())) - { - return true; - } - ASSERT(node->getRight()->getType().getStruct() == s); - auto *block = new TIntermBlock(); - for (int i = 0; i < static_cast(s->fields().size()); ++i) - { - auto *left = new TIntermBinary(EOpIndexDirectStruct, node->getLeft()->deepCopy(), - CreateIndexNode(i)); - auto *right = new TIntermBinary(EOpIndexDirectStruct, node->getRight()->deepCopy(), - CreateIndexNode(i)); - auto *assign = new TIntermBinary(TOperator::EOpAssign, left, right); - block->appendStatement(assign); - } - - queueReplacement(block, OriginalNode::IS_DROPPED); - return false; - } -}; - -} // namespace - -bool AggregateAssignStructsInSSBOs(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable) -{ - AggregateAssignStructsInSSBOsTraverser traverser(symbolTable); - root->traverse(&traverser); - return traverser.updateTree(compiler, root); -} - -} // namespace sh diff --git a/src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.h b/src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.h deleted file mode 100644 index 6721a7b4fd3..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/AggregateAssignStructsInSSBOs.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright 2022 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. -// - -#ifndef COMPILER_TRANSLATOR_TREEOPS_HLSL_AGGREGATEASSIGNSTRUCTSINSSBOS_H_ -#define COMPILER_TRANSLATOR_TREEOPS_HLSL_AGGREGATEASSIGNSTRUCTSINSSBOS_H_ - -#include "common/angleutils.h" - -namespace sh -{ -class TCompiler; -class TIntermBlock; -class TSymbolTable; - -[[nodiscard]] bool AggregateAssignStructsInSSBOs(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_HLSL_AGGREGATEASSIGNSTRUCTSINSSBOS_H_ diff --git a/src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.cpp b/src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.cpp deleted file mode 100644 index 150b9728e4d..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright 2018 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. -// -// Implementation of the function RewriteAtomicFunctionExpressions. -// See the header for more details. - -#include "compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.h" - -#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ -namespace -{ -// Traverser that simplifies all the atomic function expressions into the ones that can be directly -// translated into HLSL. -// -// case 1 (only for atomicExchange and atomicCompSwap): -// original: -// atomicExchange(counter, newValue); -// new: -// tempValue = atomicExchange(counter, newValue); -// -// case 2 (atomic function, temporary variable required): -// original: -// value = atomicAdd(counter, 1) * otherValue; -// someArray[atomicAdd(counter, 1)] = someOtherValue; -// new: -// value = ((tempValue = atomicAdd(counter, 1)), tempValue) * otherValue; -// someArray[((tempValue = atomicAdd(counter, 1)), tempValue)] = someOtherValue; -// -// case 3 (atomic function used directly initialize a variable): -// original: -// int value = atomicAdd(counter, 1); -// new: -// tempValue = atomicAdd(counter, 1); -// int value = tempValue; -// -class RewriteAtomicFunctionExpressionsTraverser : public TIntermTraverser -{ - public: - RewriteAtomicFunctionExpressionsTraverser(TSymbolTable *symbolTable, int shaderVersion); - - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - - private: - static bool IsAtomicExchangeOrCompSwapNoReturnValue(TIntermAggregate *node, - TIntermNode *parentNode); - static bool IsAtomicFunctionInsideExpression(TIntermAggregate *node, TIntermNode *parentNode); - - void rewriteAtomicFunctionCallNode(TIntermAggregate *oldAtomicFunctionNode); - - const TVariable *getTempVariable(const TType *type); - - int mShaderVersion; - TIntermSequence mTempVariables; -}; - -RewriteAtomicFunctionExpressionsTraverser::RewriteAtomicFunctionExpressionsTraverser( - TSymbolTable *symbolTable, - int shaderVersion) - : TIntermTraverser(false, false, true, symbolTable), mShaderVersion(shaderVersion) -{} - -void RewriteAtomicFunctionExpressionsTraverser::rewriteAtomicFunctionCallNode( - TIntermAggregate *oldAtomicFunctionNode) -{ - ASSERT(oldAtomicFunctionNode); - - const TVariable *returnVariable = getTempVariable(&oldAtomicFunctionNode->getType()); - - TIntermBinary *rewrittenNode = new TIntermBinary( - TOperator::EOpAssign, CreateTempSymbolNode(returnVariable), oldAtomicFunctionNode); - - auto *parentNode = getParentNode(); - - auto *parentBinary = parentNode->getAsBinaryNode(); - if (parentBinary && parentBinary->getOp() == EOpInitialize) - { - insertStatementInParentBlock(rewrittenNode); - queueReplacement(CreateTempSymbolNode(returnVariable), OriginalNode::IS_DROPPED); - } - else - { - // As all atomic function assignment will be converted to the last argument of an - // interlocked function, if we need the return value, assignment needs to be wrapped with - // the comma operator and the temporary variables. - if (!parentNode->getAsBlock()) - { - rewrittenNode = TIntermBinary::CreateComma( - rewrittenNode, new TIntermSymbol(returnVariable), mShaderVersion); - } - - queueReplacement(rewrittenNode, OriginalNode::IS_DROPPED); - } -} - -const TVariable *RewriteAtomicFunctionExpressionsTraverser::getTempVariable(const TType *type) -{ - TIntermDeclaration *variableDeclaration; - TVariable *returnVariable = - DeclareTempVariable(mSymbolTable, type, EvqTemporary, &variableDeclaration); - mTempVariables.push_back(variableDeclaration); - return returnVariable; -} - -bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicExchangeOrCompSwapNoReturnValue( - TIntermAggregate *node, - TIntermNode *parentNode) -{ - ASSERT(node); - return (node->getOp() == EOpAtomicExchange || node->getOp() == EOpAtomicCompSwap) && - parentNode && parentNode->getAsBlock(); -} - -bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicFunctionInsideExpression( - TIntermAggregate *node, - TIntermNode *parentNode) -{ - ASSERT(node); - // We only need to handle atomic functions with a parent that it is not block nodes. If the - // parent node is block, it means that the atomic function is not inside an expression. - if (!BuiltInGroup::IsAtomicMemory(node->getOp()) || parentNode->getAsBlock()) - { - return false; - } - - auto *parentAsBinary = parentNode->getAsBinaryNode(); - // Assignments are handled in OutputHLSL - return !parentAsBinary || (parentAsBinary->getOp() != EOpAssign || - IsInShaderStorageBlock(parentAsBinary->getLeft())); -} - -bool RewriteAtomicFunctionExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - ASSERT(visit == PostVisit); - // Skip atomic memory functions for SSBO. They will be processed in the OutputHLSL traverser. - if (BuiltInGroup::IsAtomicMemory(node->getOp()) && - IsInShaderStorageBlock((*node->getSequence())[0]->getAsTyped())) - { - return false; - } - - TIntermNode *parentNode = getParentNode(); - if (IsAtomicExchangeOrCompSwapNoReturnValue(node, parentNode) || - IsAtomicFunctionInsideExpression(node, parentNode)) - { - rewriteAtomicFunctionCallNode(node); - } - - return true; -} - -bool RewriteAtomicFunctionExpressionsTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - ASSERT(visit == PostVisit); - - if (!mTempVariables.empty() && getParentNode()->getAsFunctionDefinition()) - { - insertStatementsInBlockAtPosition(node, 0, mTempVariables, TIntermSequence()); - mTempVariables.clear(); - } - - return true; -} - -} // anonymous namespace - -bool RewriteAtomicFunctionExpressions(TCompiler *compiler, - TIntermNode *root, - TSymbolTable *symbolTable, - int shaderVersion) -{ - RewriteAtomicFunctionExpressionsTraverser traverser(symbolTable, shaderVersion); - traverser.traverse(root); - return traverser.updateTree(compiler, root); -} -} // namespace sh diff --git a/src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.h b/src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.h deleted file mode 100644 index 54ebd1e0074..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/RewriteAtomicFunctionExpressions.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright 2018 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. -// -// RewriteAtomicFunctionExpressions rewrites the expressions that contain -// atomic function calls and cannot be directly translated into HLSL into -// several simple ones that can be easily handled in the HLSL translator. -// -// We need to rewite these expressions because: -// 1. All GLSL atomic functions have return values, which all represent the -// original value of the shared or ssbo variable; while all HLSL atomic -// functions don't, and the original value can be stored in the last -// parameter of the function call. -// 2. For HLSL atomic functions, the last parameter that stores the original -// value is optional except for InterlockedExchange and -// InterlockedCompareExchange. Missing original_value in the call of -// InterlockedExchange or InterlockedCompareExchange results in a compile -// error from HLSL compiler. -// -// RewriteAtomicFunctionExpressions is a function that can modify the AST -// to ensure all the expressions that contain atomic function calls can be -// directly translated into HLSL expressions. - -#ifndef COMPILER_TRANSLATOR_TREEOPS_HLSL_REWRITE_ATOMIC_FUNCTION_EXPRESSIONS_H_ -#define COMPILER_TRANSLATOR_TREEOPS_HLSL_REWRITE_ATOMIC_FUNCTION_EXPRESSIONS_H_ - -#include "common/angleutils.h" - -namespace sh -{ -class TCompiler; -class TIntermNode; -class TSymbolTable; - -[[nodiscard]] bool RewriteAtomicFunctionExpressions(TCompiler *compiler, - TIntermNode *root, - TSymbolTable *symbolTable, - int shaderVersion); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_HLSL_REWRITE_ATOMIC_FUNCTION_EXPRESSIONS_H_ diff --git a/src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.cpp b/src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.cpp deleted file mode 100644 index 8f13be900ae..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// -// Copyright 2018 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. -// -// RewriteExpressionsWithShaderStorageBlock rewrites the expressions that contain shader storage -// block calls into several simple ones that can be easily handled in the HLSL translator. After the -// AST pass, all ssbo related blocks will be like below: -// ssbo_access_chain = ssbo_access_chain; -// ssbo_access_chain = expr_no_ssbo; -// lvalue_no_ssbo = ssbo_access_chain; -// - -#include "compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.h" - -#include "compiler/translator/Symbol.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ -namespace -{ - -bool IsIncrementOrDecrementOperator(TOperator op) -{ - switch (op) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - return true; - default: - return false; - } -} - -bool IsCompoundAssignment(TOperator op) -{ - switch (op) - { - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - return true; - default: - return false; - } -} - -// EOpIndexDirect, EOpIndexIndirect, EOpIndexDirectStruct, EOpIndexDirectInterfaceBlock belong to -// operators in SSBO access chain. -bool IsReadonlyBinaryOperatorNotInSSBOAccessChain(TOperator op) -{ - switch (op) - { - case EOpComma: - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpIMod: - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesMatrix: - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - return true; - default: - return false; - } -} - -bool HasSSBOAsFunctionArgument(TIntermSequence *arguments) -{ - for (TIntermNode *arg : *arguments) - { - TIntermTyped *typedArg = arg->getAsTyped(); - if (IsInShaderStorageBlock(typedArg)) - { - return true; - } - } - return false; -} - -class RewriteExpressionsWithShaderStorageBlockTraverser : public TIntermTraverser -{ - public: - RewriteExpressionsWithShaderStorageBlockTraverser(TSymbolTable *symbolTable); - void nextIteration(); - bool foundSSBO() const { return mFoundSSBO; } - - private: - bool visitBinary(Visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - - TIntermSymbol *insertInitStatementAndReturnTempSymbol(TIntermTyped *node, - TIntermSequence *insertions); - - bool mFoundSSBO; -}; - -RewriteExpressionsWithShaderStorageBlockTraverser:: - RewriteExpressionsWithShaderStorageBlockTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, true, false, symbolTable), mFoundSSBO(false) -{} - -TIntermSymbol * -RewriteExpressionsWithShaderStorageBlockTraverser::insertInitStatementAndReturnTempSymbol( - TIntermTyped *node, - TIntermSequence *insertions) -{ - TIntermDeclaration *variableDeclaration; - TVariable *tempVariable = - DeclareTempVariable(mSymbolTable, node, EvqTemporary, &variableDeclaration); - - insertions->push_back(variableDeclaration); - return CreateTempSymbolNode(tempVariable); -} - -bool RewriteExpressionsWithShaderStorageBlockTraverser::visitBinary(Visit visit, - TIntermBinary *node) -{ - // Make sure that the expression is caculated from left to right. - if (visit != InVisit) - { - return true; - } - - if (mFoundSSBO) - { - return false; - } - - bool rightSSBO = IsInShaderStorageBlock(node->getRight()); - bool leftSSBO = IsInShaderStorageBlock(node->getLeft()); - if (!leftSSBO && !rightSSBO) - { - return true; - } - - // case 1: Compound assigment operator - // original: - // lssbo += expr; - // new: - // var rvalue = expr; - // var temp = lssbo; - // temp += rvalue; - // lssbo = temp; - // - // original: - // lvalue_no_ssbo += rssbo; - // new: - // var rvalue = rssbo; - // lvalue_no_ssbo += rvalue; - if (IsCompoundAssignment(node->getOp())) - { - mFoundSSBO = true; - TIntermSequence insertions; - TIntermTyped *rightNode = - insertInitStatementAndReturnTempSymbol(node->getRight(), &insertions); - if (leftSSBO) - { - TIntermSymbol *tempSymbol = - insertInitStatementAndReturnTempSymbol(node->getLeft()->deepCopy(), &insertions); - TIntermBinary *tempCompoundOperate = - new TIntermBinary(node->getOp(), tempSymbol->deepCopy(), rightNode->deepCopy()); - insertions.push_back(tempCompoundOperate); - insertStatementsInParentBlock(insertions); - - TIntermBinary *assignTempValueToSSBO = - new TIntermBinary(EOpAssign, node->getLeft(), tempSymbol->deepCopy()); - queueReplacement(assignTempValueToSSBO, OriginalNode::IS_DROPPED); - } - else - { - insertStatementsInParentBlock(insertions); - TIntermBinary *compoundAssignRValueToLValue = - new TIntermBinary(node->getOp(), node->getLeft(), rightNode->deepCopy()); - queueReplacement(compoundAssignRValueToLValue, OriginalNode::IS_DROPPED); - } - } - // case 2: Readonly binary operator - // original: - // ssbo0 + ssbo1 + ssbo2; - // new: - // var temp0 = ssbo0; - // var temp1 = ssbo1; - // var temp2 = ssbo2; - // temp0 + temp1 + temp2; - else if (IsReadonlyBinaryOperatorNotInSSBOAccessChain(node->getOp()) && (leftSSBO || rightSSBO)) - { - mFoundSSBO = true; - TIntermTyped *rightNode = node->getRight(); - TIntermTyped *leftNode = node->getLeft(); - TIntermSequence insertions; - if (rightSSBO) - { - rightNode = insertInitStatementAndReturnTempSymbol(node->getRight(), &insertions); - } - if (leftSSBO) - { - leftNode = insertInitStatementAndReturnTempSymbol(node->getLeft(), &insertions); - } - - insertStatementsInParentBlock(insertions); - TIntermBinary *newExpr = - new TIntermBinary(node->getOp(), leftNode->deepCopy(), rightNode->deepCopy()); - queueReplacement(newExpr, OriginalNode::IS_DROPPED); - } - return !mFoundSSBO; -} - -// case 3: ssbo as the argument of aggregate type -// original: -// foo(ssbo); -// new: -// var tempArg = ssbo; -// foo(tempArg); -// ssbo = tempArg; (Optional based on whether ssbo is an out|input argument) -// -// original: -// foo(ssbo) * expr; -// new: -// var tempArg = ssbo; -// var tempReturn = foo(tempArg); -// ssbo = tempArg; (Optional based on whether ssbo is an out|input argument) -// tempReturn * expr; -bool RewriteExpressionsWithShaderStorageBlockTraverser::visitAggregate(Visit visit, - TIntermAggregate *node) -{ - // Make sure that visitAggregate is only executed once for same node. - if (visit != PreVisit) - { - return true; - } - - if (mFoundSSBO) - { - return false; - } - - // We still need to process the ssbo as the non-first argument of atomic memory functions. - if (BuiltInGroup::IsAtomicMemory(node->getOp()) && - IsInShaderStorageBlock((*node->getSequence())[0]->getAsTyped())) - { - return true; - } - - if (!HasSSBOAsFunctionArgument(node->getSequence())) - { - return true; - } - - mFoundSSBO = true; - TIntermSequence insertions; - TIntermSequence readBackToSSBOs; - TIntermSequence *originalArguments = node->getSequence(); - for (size_t i = 0; i < node->getChildCount(); ++i) - { - TIntermTyped *ssboArgument = (*originalArguments)[i]->getAsTyped(); - if (IsInShaderStorageBlock(ssboArgument)) - { - TIntermSymbol *argumentCopy = - insertInitStatementAndReturnTempSymbol(ssboArgument, &insertions); - if (node->getFunction() != nullptr) - { - TQualifier qual = node->getFunction()->getParam(i)->getType().getQualifier(); - if (qual == EvqParamInOut || qual == EvqParamOut) - { - TIntermBinary *readBackToSSBO = new TIntermBinary( - EOpAssign, ssboArgument->deepCopy(), argumentCopy->deepCopy()); - readBackToSSBOs.push_back(readBackToSSBO); - } - } - node->replaceChildNode(ssboArgument, argumentCopy); - } - } - - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - if (parentBlock) - { - // Aggregate node is as a single sentence. - insertions.push_back(node); - if (!readBackToSSBOs.empty()) - { - insertions.insert(insertions.end(), readBackToSSBOs.begin(), readBackToSSBOs.end()); - } - mMultiReplacements.emplace_back(parentBlock, node, std::move(insertions)); - } - else - { - // Aggregate node is inside an expression. - TIntermSymbol *tempSymbol = insertInitStatementAndReturnTempSymbol(node, &insertions); - if (!readBackToSSBOs.empty()) - { - insertions.insert(insertions.end(), readBackToSSBOs.begin(), readBackToSSBOs.end()); - } - insertStatementsInParentBlock(insertions); - queueReplacement(tempSymbol->deepCopy(), OriginalNode::IS_DROPPED); - } - - return false; -} - -bool RewriteExpressionsWithShaderStorageBlockTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFoundSSBO) - { - return false; - } - - if (!IsInShaderStorageBlock(node->getOperand())) - { - return true; - } - - // .length() is processed in OutputHLSL. - if (node->getOp() == EOpArrayLength) - { - return true; - } - - mFoundSSBO = true; - - // case 4: ssbo as the operand of ++/-- - // original: - // ++ssbo * expr; - // new: - // var temp1 = ssbo; - // var temp2 = ++temp1; - // ssbo = temp1; - // temp2 * expr; - if (IsIncrementOrDecrementOperator(node->getOp())) - { - TIntermSequence insertions; - TIntermSymbol *temp1 = - insertInitStatementAndReturnTempSymbol(node->getOperand(), &insertions); - TIntermUnary *newUnary = new TIntermUnary(node->getOp(), temp1->deepCopy(), nullptr); - TIntermSymbol *temp2 = insertInitStatementAndReturnTempSymbol(newUnary, &insertions); - TIntermBinary *readBackToSSBO = - new TIntermBinary(EOpAssign, node->getOperand()->deepCopy(), temp1->deepCopy()); - insertions.push_back(readBackToSSBO); - insertStatementsInParentBlock(insertions); - queueReplacement(temp2->deepCopy(), OriginalNode::IS_DROPPED); - } - // case 5: ssbo as the operand of readonly unary operator - // original: - // ~ssbo * expr; - // new: - // var temp = ssbo; - // ~temp * expr; - else - { - TIntermSequence insertions; - TIntermSymbol *temp = - insertInitStatementAndReturnTempSymbol(node->getOperand(), &insertions); - insertStatementsInParentBlock(insertions); - node->replaceChildNode(node->getOperand(), temp->deepCopy()); - } - return false; -} - -void RewriteExpressionsWithShaderStorageBlockTraverser::nextIteration() -{ - mFoundSSBO = false; -} - -} // anonymous namespace - -bool RewriteExpressionsWithShaderStorageBlock(TCompiler *compiler, - TIntermNode *root, - TSymbolTable *symbolTable) -{ - RewriteExpressionsWithShaderStorageBlockTraverser traverser(symbolTable); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundSSBO()) - { - if (!traverser.updateTree(compiler, root)) - { - return false; - } - } - } while (traverser.foundSSBO()); - - return true; -} -} // namespace sh diff --git a/src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.h b/src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.h deleted file mode 100644 index 4e49d0ec4be..00000000000 --- a/src/compiler/translator/tree_ops/hlsl/RewriteExpressionsWithShaderStorageBlock.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright 2018 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. -// -// RewriteExpressionsWithShaderStorageBlock rewrites the expressions that contain shader storage -// block calls into several simple ones that can be easily handled in the HLSL translator. After the -// AST pass, all ssbo related blocks will be like below: -// ssbo_access_chain = ssbo_access_chain; -// ssbo_access_chain = expr_no_ssbo; -// lvalue_no_ssbo = ssbo_access_chain; -// -// Below situations are needed to be rewritten (Details can be found in .cpp file). -// SSBO as the operand of compound assignment operators. -// SSBO as the operand of ++/--. -// SSBO as the operand of repeated assignment. -// SSBO as the operand of readonly unary/binary/ternary operators. -// SSBO as the argument of aggregate type. -// SSBO as the condition of if/switch/while/do-while/for - -#ifndef COMPILER_TRANSLATOR_TREEOPS_HLSL_REWRITE_EXPRESSIONS_WITH_SHADER_STORAGE_BLOCK_H_ -#define COMPILER_TRANSLATOR_TREEOPS_HLSL_REWRITE_EXPRESSIONS_WITH_SHADER_STORAGE_BLOCK_H_ - -#include "common/angleutils.h" - -namespace sh -{ -class TCompiler; -class TIntermNode; -class TSymbolTable; - -[[nodiscard]] bool RewriteExpressionsWithShaderStorageBlock(TCompiler *compiler, - TIntermNode *root, - TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TREEOPS_HLSL_REWRITE_EXPRESSIONS_WITH_SHADER_STORAGE_BLOCK_H_ diff --git a/src/compiler/translator/tree_ops/hlsl/SeparateExpressionsReturningArrays.cpp b/src/compiler/translator/tree_ops/hlsl/SeparateExpressionsReturningArrays.cpp index d81a3a6c6bf..7715f4690e8 100644 --- a/src/compiler/translator/tree_ops/hlsl/SeparateExpressionsReturningArrays.cpp +++ b/src/compiler/translator/tree_ops/hlsl/SeparateExpressionsReturningArrays.cpp @@ -97,8 +97,15 @@ bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate mFoundArrayExpression = true; TIntermDeclaration *arrayVariableDeclaration; - TVariable *arrayVariable = DeclareTempVariable(mSymbolTable, node->shallowCopy(), EvqTemporary, - &arrayVariableDeclaration); + const bool isConstExpression = node->hasConstantValue(); + const TConstantUnion *constValue = isConstExpression ? node->getConstantValue() : nullptr; + const TQualifier arrayVarQualifier = isConstExpression ? EvqConst : EvqTemporary; + TVariable *arrayVariable = DeclareTempVariable(mSymbolTable, node->shallowCopy(), + arrayVarQualifier, &arrayVariableDeclaration); + if (constValue != nullptr) + { + arrayVariable->shareConstPointer(constValue); + } insertStatementInParentBlock(arrayVariableDeclaration); queueReplacement(CreateTempSymbolNode(arrayVariable), OriginalNode::IS_DROPPED); diff --git a/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.cpp b/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.cpp index 06845a14b48..62782aef147 100644 --- a/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.cpp +++ b/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.cpp @@ -16,13 +16,10 @@ namespace class Rewriter : public TIntermRebuild { SymbolEnv &mSymbolEnv; - bool mNeedsExplicitBoolCasts = false; public: - Rewriter(TCompiler &compiler, SymbolEnv &symbolEnv, bool needsExplicitBoolCasts) - : TIntermRebuild(compiler, false, true), - mSymbolEnv(symbolEnv), - mNeedsExplicitBoolCasts(needsExplicitBoolCasts) + Rewriter(TCompiler &compiler, SymbolEnv &symbolEnv) + : TIntermRebuild(compiler, false, true), mSymbolEnv(symbolEnv) {} PostResult visitAggregatePost(TIntermAggregate &callNode) override @@ -40,7 +37,7 @@ class Rewriter : public TIntermRebuild const TType argType = arg.getType(); if (argType.isVector()) { - return CoerceSimple(retType, SubVector(arg, 0, 1), mNeedsExplicitBoolCasts); + return CoerceSimple(retType, SubVector(arg, 0, 1)); } } } @@ -53,15 +50,13 @@ class Rewriter : public TIntermRebuild const TType argType = arg.getType(); if (argType.isVector()) { - return CoerceSimple(retType, SubVector(arg, 0, retType.getNominalSize()), - mNeedsExplicitBoolCasts); + return CoerceSimple(retType, SubVector(arg, 0, retType.getNominalSize())); } } for (size_t i = 0; i < argCount; ++i) { TIntermTyped &arg = GetArg(callNode, i); - SetArg(callNode, i, - CoerceSimple(retType.getBasicType(), arg, mNeedsExplicitBoolCasts)); + SetArg(callNode, i, CoerceSimple(retType.getBasicType(), arg)); } } else if (retType.isMatrix()) @@ -90,12 +85,9 @@ class Rewriter : public TIntermRebuild } // anonymous namespace -bool sh::AddExplicitTypeCasts(TCompiler &compiler, - TIntermBlock &root, - SymbolEnv &symbolEnv, - bool needsExplicitBoolCasts) +bool sh::AddExplicitTypeCasts(TCompiler &compiler, TIntermBlock &root, SymbolEnv &symbolEnv) { - Rewriter rewriter(compiler, symbolEnv, needsExplicitBoolCasts); + Rewriter rewriter(compiler, symbolEnv); if (!rewriter.rebuildRoot(root)) { return false; diff --git a/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.h b/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.h index f73c050ada5..b9151d4e93e 100644 --- a/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.h +++ b/src/compiler/translator/tree_ops/msl/AddExplicitTypeCasts.h @@ -17,8 +17,7 @@ namespace sh // Adds explicit type casts into the AST where casting is done implicitly. [[nodiscard]] bool AddExplicitTypeCasts(TCompiler &compiler, TIntermBlock &root, - SymbolEnv &symbolEnv, - bool needsExplicitBoolCasts); + SymbolEnv &symbolEnv); } // namespace sh diff --git a/src/compiler/translator/tree_ops/msl/ConvertUnsupportedConstructorsToFunctionCalls.cpp b/src/compiler/translator/tree_ops/msl/ConvertUnsupportedConstructorsToFunctionCalls.cpp index e079abe5417..e959c302b3d 100644 --- a/src/compiler/translator/tree_ops/msl/ConvertUnsupportedConstructorsToFunctionCalls.cpp +++ b/src/compiler/translator/tree_ops/msl/ConvertUnsupportedConstructorsToFunctionCalls.cpp @@ -19,7 +19,7 @@ namespace void AppendMatrixElementArgument(TIntermSymbol *parameter, int colIndex, - int rowIndex, + uint32_t rowIndex, TIntermSequence *returnCtorArgs) { TIntermBinary *matColN = diff --git a/src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.cpp b/src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.cpp new file mode 100644 index 00000000000..98a4c8ca639 --- /dev/null +++ b/src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.cpp @@ -0,0 +1,252 @@ +// +// Copyright 2025 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. +// +// EnsureLoopForwardProgress is an AST traverser that inserts volatile variable +// access inside loops which it cannot prove to be finite. +// + +#include "compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +const TVariable *ViewSymbolVariable(TIntermTyped &node) +{ + TIntermSymbol *symbol = node.getAsSymbolNode(); + if (symbol == nullptr) + { + return nullptr; + } + return &symbol->variable(); +} + +bool IsReadOnlyExpr(TIntermTyped &node) +{ + switch (node.getQualifier()) + { + case EvqConst: + case EvqAttribute: + case EvqUniform: + case EvqVaryingIn: + case EvqSmoothIn: + case EvqFlatIn: + case EvqNoPerspectiveIn: + case EvqCentroidIn: + case EvqSampleIn: + case EvqNoPerspectiveCentroidIn: + case EvqNoPerspectiveSampleIn: + return true; + default: + break; + } + return false; +} + +const TVariable *computeFiniteLoopVariable(TIntermLoop *loop) +{ + // Currently matches only to loop of form: + // for (**; cond ; expr) + // where + // cond is `variable` `relation` `readonly symbol` and `variable`is of type int or uint + // expr increments or decrements the variable by one. + // Assumes ints wrap around in a defined way. + TIntermTyped *cond = loop->getCondition(); + if (cond == nullptr) + { + return nullptr; + } + TIntermTyped *expr = loop->getExpression(); + if (expr == nullptr) + { + return nullptr; + } + TIntermBinary *binCond = cond->getAsBinaryNode(); + if (binCond == nullptr) + { + return nullptr; + } + const TVariable *variable = ViewSymbolVariable(*binCond->getLeft()); + if (variable == nullptr) + { + return nullptr; + } + if (!IsInteger(variable->getType().getBasicType())) + { + return nullptr; + } + switch (binCond->getOp()) + { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + default: + return nullptr; + } + // Loop index must be compared with a constant or uniform or similar read-only variable. + if (!IsReadOnlyExpr(*binCond->getRight())) + { + return nullptr; + } + if (TIntermUnary *unary = expr->getAsUnaryNode()) + { + switch (unary->getOp()) + { + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpPostDecrement: + break; + default: + return nullptr; + } + if (variable != ViewSymbolVariable(*unary->getOperand())) + { + return nullptr; + } + } + else if (TIntermBinary *binExpr = expr->getAsBinaryNode()) + { + switch (binExpr->getOp()) + { + case EOpAddAssign: + case EOpSubAssign: + break; + default: + return nullptr; + } + if (variable != ViewSymbolVariable(*binExpr->getLeft())) + { + return nullptr; + } + const TConstantUnion *value = binExpr->getRight()->getConstantValue(); + if (value == nullptr) + { + return nullptr; + } + switch (value->getType()) + { + case EbtInt: + if (value->getIConst() == -1 || value->getIConst() == 1) + { + break; + } + return nullptr; + case EbtUInt: + if (value->getUConst() == 1) + { + break; + } + return nullptr; + default: + UNREACHABLE(); + return nullptr; + } + } + return variable; +} + +class LoopInfoStack +{ + public: + LoopInfoStack(TIntermLoop *node, LoopInfoStack *parent); + bool isFinite() const { return mVariable != nullptr; } + LoopInfoStack *getParent() const { return mParent; } + void setNotFinite() { mVariable = nullptr; } + LoopInfoStack *findLoopForVariable(const TVariable *variable); + + private: + LoopInfoStack *mParent = nullptr; + const TVariable *mVariable = nullptr; +}; + +LoopInfoStack::LoopInfoStack(TIntermLoop *node, LoopInfoStack *parent) + : mParent(parent), mVariable(computeFiniteLoopVariable(node)) +{} + +LoopInfoStack *LoopInfoStack::findLoopForVariable(const TVariable *variable) +{ + LoopInfoStack *info = this; + do + { + if (info->mVariable == variable) + { + return info; + } + info = info->mParent; + } while (info != nullptr); + return nullptr; +} + +class EnsureLoopForwardProgressTraverser final : public TLValueTrackingTraverser +{ + public: + EnsureLoopForwardProgressTraverser(TSymbolTable *symbolTable); + void visitSymbol(TIntermSymbol *node) override; + void traverseLoop(TIntermLoop *node) override; + + private: + LoopInfoStack *mLoopInfoStack = nullptr; +}; + +EnsureLoopForwardProgressTraverser::EnsureLoopForwardProgressTraverser(TSymbolTable *symbolTable) + : TLValueTrackingTraverser(true, false, false, symbolTable) +{} + +void EnsureLoopForwardProgressTraverser::traverseLoop(TIntermLoop *node) +{ + LoopInfoStack loopInfo{node, mLoopInfoStack}; + mLoopInfoStack = &loopInfo; + + ScopedNodeInTraversalPath addToPath(this, node); + node->getBody()->traverse(this); + + if (!loopInfo.isFinite()) + { + TIntermBlock *newBody = new TIntermBlock(); + TIntermSequence *sequence = newBody->getSequence(); + sequence->push_back(CreateBuiltInFunctionCallNode("loopForwardProgress", {}, *mSymbolTable, + kESSLInternalBackendBuiltIns)); + sequence->push_back(node->getBody()); + node->setBody(newBody); + } + mLoopInfoStack = mLoopInfoStack->getParent(); +} + +void EnsureLoopForwardProgressTraverser::visitSymbol(TIntermSymbol *node) +{ + if (!mLoopInfoStack) + { + return; + } + LoopInfoStack *loop = mLoopInfoStack->findLoopForVariable(&node->variable()); + if (loop != nullptr && isLValueRequiredHere()) + { + loop->setNotFinite(); + } +} + +} // namespace + +bool EnsureLoopForwardProgress(TCompiler *compiler, TIntermNode *root) +{ + EnsureLoopForwardProgressTraverser traverser(&compiler->getSymbolTable()); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.h b/src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.h new file mode 100644 index 00000000000..7f789569ef5 --- /dev/null +++ b/src/compiler/translator/tree_ops/msl/EnsureLoopForwardProgress.h @@ -0,0 +1,32 @@ +// +// Copyright 2025 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. +// +// EnsureLoopForwardProgress is an AST traverser that ensures that loops are either finite or +// invoke side-effects. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_MSL_ENSURELOOPFORWARDPROGRESS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_MSL_ENSURELOOPFORWARDPROGRESS_H_ + +#include "common/angleutils.h" +#include "common/debug.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +#ifdef ANGLE_ENABLE_METAL +[[nodiscard]] bool EnsureLoopForwardProgress(TCompiler *compiler, TIntermNode *root); +#else +[[nodiscard]] ANGLE_INLINE bool EnsureLoopForwardProgress(TCompiler *compiler, TIntermNode *root) +{ + UNREACHABLE(); + return false; +} +#endif +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_MSL_ENSURELOOPFORWARDPROGRESS_H_ diff --git a/src/compiler/translator/tree_ops/RescopeGlobalVariables.cpp b/src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.cpp similarity index 97% rename from src/compiler/translator/tree_ops/RescopeGlobalVariables.cpp rename to src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.cpp index 3eb7e7ac745..63e87a04999 100644 --- a/src/compiler/translator/tree_ops/RescopeGlobalVariables.cpp +++ b/src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.cpp @@ -6,7 +6,7 @@ #include -#include "compiler/translator/tree_ops/RescopeGlobalVariables.h" +#include "compiler/translator/tree_ops/msl/RescopeGlobalVariables.h" #include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/tree_util/ReplaceVariable.h" #include "compiler/translator/util.h" @@ -58,7 +58,7 @@ class Rescoper : public TIntermTraverser const TVariable *newVar = new TVariable(&compiler->getSymbolTable(), pair.first->name(), newType, pair.first->symbolType(), pair.first->extensions()); - replacementMap[pair.first] = new TIntermSymbol(newVar); + replacementMap[pair.first->uniqueId()] = new TIntermSymbol(newVar); movedDeclarations.insert(pair.second.declaration); } diff --git a/src/compiler/translator/tree_ops/RescopeGlobalVariables.h b/src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.h similarity index 81% rename from src/compiler/translator/tree_ops/RescopeGlobalVariables.h rename to src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.h index a981a1ddf21..455fda43c5d 100644 --- a/src/compiler/translator/tree_ops/RescopeGlobalVariables.h +++ b/src/compiler/translator/tree_ops/msl/RescopeGlobalVariables.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_TREEOPS_RESCOPEGLOBALVARIABLES_H_ -#define COMPILER_TRANSLATOR_TREEOPS_RESCOPEGLOBALVARIABLES_H_ +#ifndef COMPILER_TRANSLATOR_TREEOPS_MSL_RESCOPEGLOBALVARIABLES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_MSL_RESCOPEGLOBALVARIABLES_H_ #include "common/angleutils.h" #include "compiler/translator/Compiler.h" diff --git a/src/compiler/translator/tree_ops/msl/RewriteUnaddressableReferences.cpp b/src/compiler/translator/tree_ops/msl/RewriteUnaddressableReferences.cpp index ae3d95be356..609f7a1f1e3 100644 --- a/src/compiler/translator/tree_ops/msl/RewriteUnaddressableReferences.cpp +++ b/src/compiler/translator/tree_ops/msl/RewriteUnaddressableReferences.cpp @@ -296,14 +296,14 @@ class Rewriter2 : public TIntermRebuild } TIntermTyped &vecNode = *swizzleNode.getOperand(); - const TQualifierList &offsets = swizzleNode.getSwizzleOffsets(); + const TVector &offsets = swizzleNode.getSwizzleOffsets(); ASSERT(!offsets.empty()); ASSERT(offsets.size() <= 4); auto &args = *new TIntermSequence(); args.reserve(offsets.size() + 1); args.push_back(&vecNode); - for (int offset : offsets) + for (uint32_t offset : offsets) { args.push_back(new TIntermConstantUnion(new TConstantUnion(offset), *new TType(TBasicType::EbtInt))); diff --git a/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp b/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp index 6a4250937d1..3d21fcedde7 100644 --- a/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp +++ b/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp @@ -173,6 +173,12 @@ class Separator : public TIntermRebuild return mStmtsStack.back(); } + bool nodeExistsInCurrStmts(TIntermNode *node) + { + const auto &currStmts = getCurrStmts(); + return std::find(currStmts.begin(), currStmts.end(), node) != currStmts.end(); + } + std::unordered_map &getCurrBindingMap() { ASSERT(!mBindingMapStack.empty()); @@ -453,7 +459,16 @@ class Separator : public TIntermRebuild TIntermTyped *newRight = pullMappedExpr(right, isAssign && !isCompoundAssign); if (op == TOperator::EOpComma) { - pushBinding(node, *newRight); + // Avoid adding a redundant right child statement to the statement stack for the current + // block. This could occur because the right node is a TIntermAggregate type (such as + // EOpCallFunctionInAST type) and as part of the post traversal action for a + // TIntermAggregate node, it gets added to the statement stack. In that case, when the + // code execution reaches this point, the right node will get added again resulting in a + // reudundant statement. + if (!nodeExistsInCurrStmts(newRight)) + { + pushBinding(node, *newRight); + } return node; } else diff --git a/src/compiler/translator/tree_ops/spirv/EmulateAdvancedBlendEquations.cpp b/src/compiler/translator/tree_ops/spirv/EmulateAdvancedBlendEquations.cpp index 3ea72f40688..f2b38fbc032 100644 --- a/src/compiler/translator/tree_ops/spirv/EmulateAdvancedBlendEquations.cpp +++ b/src/compiler/translator/tree_ops/spirv/EmulateAdvancedBlendEquations.cpp @@ -1043,7 +1043,7 @@ TIntermSymbol *Builder::premultiplyAlpha(TIntermBlock *blendBlock, constexpr int kColorChannels = 3; // For each component: // symbol.x = (var.x == var.w) ? 1.0 : var.x / var.w - for (int index = 0; index < kColorChannels; index++) + for (uint32_t index = 0; index < kColorChannels; index++) { TIntermTyped *divideNode = divideFloatNode(new TIntermSwizzle(var, {index}), alpha); TIntermBinary *assignDivideNode = new TIntermBinary( @@ -1168,7 +1168,7 @@ void Builder::generateEquationSwitch(TIntermBlock *blendBlock) if (equation < gl::BlendEquationType::HslHue) { TIntermSequence constructorArgs; - for (int channel = 0; channel < 3; ++channel) + for (uint32_t channel = 0; channel < 3; ++channel) { TIntermTyped *srcChannel = new TIntermSwizzle(mSrc->deepCopy(), {channel}); TIntermTyped *dstChannel = new TIntermSwizzle(mDst->deepCopy(), {channel}); @@ -1226,7 +1226,7 @@ void Builder::generateEquationSwitch(TIntermBlock *blendBlock) uint32_t vecSize = mOutputVar->getType().getNominalSize(); if (vecSize < 4) { - TVector swizzle = {0, 1, 2, 3}; + TVector swizzle = {0, 1, 2, 3}; swizzle.resize(vecSize); blendResult = new TIntermSwizzle(blendResult, swizzle); } diff --git a/src/compiler/translator/tree_ops/spirv/EmulateDithering.cpp b/src/compiler/translator/tree_ops/spirv/EmulateDithering.cpp index 61607c7b2ce..6ef5b9524c7 100644 --- a/src/compiler/translator/tree_ops/spirv/EmulateDithering.cpp +++ b/src/compiler/translator/tree_ops/spirv/EmulateDithering.cpp @@ -209,17 +209,24 @@ void EmitFragmentOutputDither(TCompiler *compiler, TIntermSwitch *formatSwitch = new TIntermSwitch(thisDitherControl, switchBody); ditherBlock->appendStatement(formatSwitch); - // fragmentOutput.rgb += ditherValue + // Only apply dither if "const uint dither_i = (dither >> 2*location) & 3" is non-zero + // if (dither_i != 0) { + // fragmentOutput.rgb += ditherValue + // } + TIntermTyped *shouldApplyDitherCheck = + new TIntermBinary(EOpNotEqual, thisDitherControl->deepCopy(), CreateUIntNode(0)); if (type.getNominalSize() > 3) { fragmentOutput = new TIntermSwizzle(fragmentOutput, {0, 1, 2}); } - ditherBlock->appendStatement(new TIntermBinary(EOpAddAssign, fragmentOutput, ditherValue)); + TIntermBlock *applyDitherValueBlock = new TIntermBlock; + applyDitherValueBlock->appendStatement( + new TIntermBinary(EOpAddAssign, fragmentOutput, ditherValue)); // round() the output if workaround is enabled if (roundOutputAfterDithering) { - TVector swizzle = {0, 1, 2}; + TVector swizzle = {0, 1, 2}; swizzle.resize(fragmentOutput->getNominalSize()); TIntermTyped *multiplier = new TIntermSwizzle(roundMultiplier, swizzle); @@ -228,9 +235,11 @@ void EmitFragmentOutputDither(TCompiler *compiler, TIntermTyped *rounded = CreateBuiltInUnaryFunctionCallNode("round", scaledUp, *symbolTable, 300); TIntermTyped *scaledDown = new TIntermBinary(EOpDiv, rounded, multiplier->deepCopy()); - ditherBlock->appendStatement( + applyDitherValueBlock->appendStatement( new TIntermBinary(EOpAssign, fragmentOutput->deepCopy(), scaledDown)); } + ditherBlock->appendStatement( + new TIntermIfElse(shouldApplyDitherCheck, applyDitherValueBlock, nullptr)); } void EmitFragmentVariableDither(TCompiler *compiler, diff --git a/src/compiler/translator/tree_ops/spirv/EmulateFragColorData.cpp b/src/compiler/translator/tree_ops/spirv/EmulateFragColorData.cpp index 797e580852a..bb3340eb45f 100644 --- a/src/compiler/translator/tree_ops/spirv/EmulateFragColorData.cpp +++ b/src/compiler/translator/tree_ops/spirv/EmulateFragColorData.cpp @@ -41,7 +41,7 @@ class EmulateFragColorDataTraverser : public TIntermTraverser const TType &type = variable->getType(); // If this built-in was already visited, reuse the variable defined for it. - auto replacement = mVariableMap.find(variable); + auto replacement = mVariableMap.find(variable->uniqueId()); if (replacement != mVariableMap.end()) { queueReplacement(replacement->second->deepCopy(), OriginalNode::IS_DROPPED); @@ -94,7 +94,7 @@ class EmulateFragColorDataTraverser : public TIntermTraverser SymbolType::AngleInternal); TIntermSymbol *newSymbol = new TIntermSymbol(replacementVar); - mVariableMap[variable] = newSymbol; + mVariableMap[variable->uniqueId()] = newSymbol; queueReplacement(newSymbol, OriginalNode::IS_DROPPED); } diff --git a/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp b/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp index ece2e73400d..3d0f114b25c 100644 --- a/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp +++ b/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp @@ -108,7 +108,7 @@ bool InputAttachmentUsageTraverser::visitDeclaration(Visit visit, TIntermDeclara } } - return false; + return true; } bool InputAttachmentUsageTraverser::visitBinary(Visit visit, TIntermBinary *node) @@ -436,7 +436,7 @@ void InitializeFromInputAttachment(TSymbolTable *symbolTable, const int vecSize = assignVariable->getType().getNominalSize(); if (vecSize < 4) { - TVector swizzle = {0, 1, 2, 3}; + TVector swizzle = {0, 1, 2, 3}; swizzle.resize(vecSize); input = new TIntermSwizzle(input, swizzle); } @@ -531,7 +531,7 @@ void InitializeFromInputAttachment(TSymbolTable *symbolTable, outType->setQualifier(EvqFragmentOut); const TVariable *replacement = new TVariable(symbolTable, var->name(), outType, var->symbolType()); - replacementMap[var] = new TIntermSymbol(replacement); + replacementMap[var->uniqueId()] = new TIntermSymbol(replacement); } if (lastFragData != nullptr || inputAttachmentMap.depth != nullptr || @@ -604,18 +604,18 @@ void InitializeFromInputAttachment(TSymbolTable *symbolTable, if (lastFragData != nullptr) { - replacementMap[glLastFragData] = new TIntermSymbol(lastFragData); - replacementMap[glLastFragColor] = new TIntermBinary( + replacementMap[glLastFragData->uniqueId()] = new TIntermSymbol(lastFragData); + replacementMap[glLastFragColor->uniqueId()] = new TIntermBinary( EOpIndexDirect, new TIntermSymbol(lastFragData), CreateIndexNode(0)); } if (inputAttachmentMap.depth != nullptr) { - replacementMap[glLastFragDepth] = new TIntermSwizzle( + replacementMap[glLastFragDepth->uniqueId()] = new TIntermSwizzle( CreateSubpassLoadFuncCall(symbolTable, inputAttachmentMap.depth), {0}); } if (inputAttachmentMap.stencil != nullptr) { - replacementMap[glLastFragStencil] = new TIntermSwizzle( + replacementMap[glLastFragStencil->uniqueId()] = new TIntermSwizzle( CreateSubpassLoadFuncCall(symbolTable, inputAttachmentMap.stencil), {0}); } } diff --git a/src/compiler/translator/tree_ops/spirv/EmulateYUVBuiltIns.cpp b/src/compiler/translator/tree_ops/spirv/EmulateYUVBuiltIns.cpp index 2b03ab5cb89..31a3949314a 100644 --- a/src/compiler/translator/tree_ops/spirv/EmulateYUVBuiltIns.cpp +++ b/src/compiler/translator/tree_ops/spirv/EmulateYUVBuiltIns.cpp @@ -6,6 +6,10 @@ // EmulateYUVBuiltIns: Adds functions that emulate yuv_2_rgb and rgb_2_yuv built-ins. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/tree_ops/spirv/EmulateYUVBuiltIns.h" #include "compiler/translator/StaticType.h" diff --git a/src/compiler/translator/tree_ops/spirv/FlagSamplersWithTexelFetch.cpp b/src/compiler/translator/tree_ops/spirv/FlagSamplersWithTexelFetch.cpp index d2e1d41b6b3..da1109877c6 100644 --- a/src/compiler/translator/tree_ops/spirv/FlagSamplersWithTexelFetch.cpp +++ b/src/compiler/translator/tree_ops/spirv/FlagSamplersWithTexelFetch.cpp @@ -48,8 +48,17 @@ class FlagSamplersWithTexelFetchTraverser : public TIntermTraverser const TIntermSequence *sequence = node->getSequence(); ASSERT(sequence->size() > 0); + TIntermNode *samplerNode = node->getSequence()->at(0); + TIntermBinary *asBinary = samplerNode->getAsBinaryNode(); - TIntermSymbol *samplerSymbol = sequence->at(0)->getAsSymbolNode(); + // Handle cases where the argument comes from an array of samplers. + if (asBinary != nullptr) + { + ASSERT(asBinary->getOp() == TOperator::EOpIndexDirect); + samplerNode = asBinary->getLeft(); + } + + TIntermSymbol *samplerSymbol = samplerNode->getAsSymbolNode(); ASSERT(samplerSymbol != nullptr); const TVariable &samplerVariable = samplerSymbol->variable(); diff --git a/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.cpp b/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.cpp index e9c69f42582..b6763f0923a 100644 --- a/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.cpp +++ b/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.cpp @@ -10,7 +10,6 @@ #include "compiler/translator/tree_ops/spirv/EmulateYUVBuiltIns.h" -#include "compiler/translator/StaticType.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermTraverse.h" @@ -30,9 +29,9 @@ class ReswizzleYUVOpsTraverser : public TIntermTraverser bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool adjustOutput(TCompiler *compiler, TIntermBlock *root, const TIntermSymbol &yuvOutput); private: + TIntermSwizzle *transformTextureOp(TIntermAggregate *node); }; // OpenGLES and Vulkan has different color component mapping for YUV. OpenGL spec maps R_gl=y, @@ -42,32 +41,21 @@ class ReswizzleYUVOpsTraverser : public TIntermTraverser // GL order, which comes out to be R_gl=y=G_vulkan=1, G_gl=u=B_vulkan=2, B_gl=v=R_vulkan=0. i.e, {1, // 2, 0, 3}. This function will check if the aggregate is a texture{proj|fetch}(samplerExternal,...) // and if yes it will compose and return a swizzle node. -TIntermSwizzle *CheckTextureOpWithSamplerExternal2DY2YAndSwizzle(Visit visit, - TIntermAggregate *node) +TIntermSwizzle *ReswizzleYUVOpsTraverser::transformTextureOp(TIntermAggregate *node) { - if (visit != Visit::PreVisit) - { - return nullptr; - } - - if (!BuiltInGroup::IsBuiltIn(node->getOp())) - { - return nullptr; - } - - TOperator op = node->getFunction()->getBuiltInOp(); + const TOperator op = node->getOp(); if (op == EOpTexture || op == EOpTextureProj || op == EOpTexelFetch) { - TIntermSequence *arguments = node->getSequence(); - TType const &samplerType = (*arguments)[0]->getAsTyped()->getType(); + const TIntermSequence &arguments = *node->getSequence(); + TType const &samplerType = arguments[0]->getAsTyped()->getType(); + if (samplerType.getBasicType() != EbtSamplerExternal2DY2YEXT) { return nullptr; } // texture(...).gbra - TIntermSwizzle *yuvSwizzle = new TIntermSwizzle(node, {1, 2, 0, 3}); - return yuvSwizzle; + return new TIntermSwizzle(node, {1, 2, 0, 3}); } return nullptr; @@ -75,11 +63,11 @@ TIntermSwizzle *CheckTextureOpWithSamplerExternal2DY2YAndSwizzle(Visit visit, bool ReswizzleYUVOpsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { - TIntermSwizzle *yuvSwizzle = CheckTextureOpWithSamplerExternal2DY2YAndSwizzle(visit, node); + TIntermSwizzle *yuvSwizzle = transformTextureOp(node); if (yuvSwizzle != nullptr) { ASSERT(!getParentNode()->getAsSwizzleNode()); - queueReplacement(yuvSwizzle, OriginalNode::BECOMES_CHILD); + queueReplacement(yuvSwizzle, OriginalNode::IS_DROPPED); return false; } @@ -96,7 +84,7 @@ bool ReswizzleYUVOpsTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) // There is swizzle on YUV texture sampler, and we need to apply YUV swizzle first and // then followed by the original swizzle. Finally we fold the two swizzles into one. - TIntermSwizzle *yuvSwizzle = CheckTextureOpWithSamplerExternal2DY2YAndSwizzle(visit, aggregate); + TIntermSwizzle *yuvSwizzle = transformTextureOp(aggregate); if (yuvSwizzle != nullptr) { TIntermTyped *replacement = new TIntermSwizzle(yuvSwizzle, node->getSwizzleOffsets()); @@ -107,48 +95,32 @@ bool ReswizzleYUVOpsTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) return true; } +} // anonymous namespace // OpenGLES and Vulkan has different color component mapping for YUV. When we write YUV data, we // need to convert OpenGL mapping to vulkan's mapping, which comes out to be {2, 0, 1, 3}. -bool ReswizzleYUVOpsTraverser::adjustOutput(TCompiler *compiler, - TIntermBlock *root, - const TIntermSymbol &yuvOutput) +bool AdjustYUVOutput(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TIntermSymbol &yuvOutput) { TIntermBlock *block = new TIntermBlock; // output = output.brga - TVector swizzle = {2, 0, 1, 3}; - const int size = yuvOutput.getType().getNominalSize(); - if (size < 4) - { - swizzle.resize(size); - } + TVector swizzle = {2, 0, 1, 3}; + swizzle.resize(yuvOutput.getType().getNominalSize()); TIntermTyped *assignment = new TIntermBinary(EOpAssign, yuvOutput.deepCopy(), new TIntermSwizzle(yuvOutput.deepCopy(), swizzle)); block->appendStatement(assignment); - return RunAtTheEndOfShader(compiler, root, block, mSymbolTable); + return RunAtTheEndOfShader(compiler, root, block, symbolTable); } -} // anonymous namespace -bool ReswizzleYUVOps(TCompiler *compiler, - TIntermBlock *root, - TSymbolTable *symbolTable, - const TIntermSymbol *yuvOutput) +bool ReswizzleYUVTextureAccess(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) { ReswizzleYUVOpsTraverser traverser(symbolTable); root->traverse(&traverser); - - if (!traverser.updateTree(compiler, root)) - { - return false; - } - - if (yuvOutput != nullptr && !traverser.adjustOutput(compiler, root, *yuvOutput)) - { - return false; - } - return true; + return traverser.updateTree(compiler, root); } } // namespace sh diff --git a/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.h b/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.h index 65f13e3998a..614a02c501a 100644 --- a/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.h +++ b/src/compiler/translator/tree_ops/spirv/ReswizzleYUVOps.h @@ -19,10 +19,15 @@ class TCompiler; class TIntermBlock; class TSymbolTable; -[[nodiscard]] bool ReswizzleYUVOps(TCompiler *compiler, +[[nodiscard]] bool AdjustYUVOutput(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable, - const TIntermSymbol *yuvOutput); + const TIntermSymbol &yuvOutput); + +[[nodiscard]] bool ReswizzleYUVTextureAccess(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); + } // namespace sh #endif // COMPILER_TRANSLATOR_TREEOPS_SPIRV_RESWIZZLEYUVOPS_H_ diff --git a/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.cpp b/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.cpp index 003e52bcb82..9cd8f76aea8 100644 --- a/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.cpp +++ b/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.cpp @@ -26,7 +26,7 @@ namespace class Traverser : public TIntermTraverser { public: - Traverser(TSymbolTable *symbolTable, SpecConst *specConst, const DriverUniform *driverUniforms); + Traverser(TSymbolTable *symbolTable, const DriverUniform *driverUniforms); bool update(TCompiler *compiler, TIntermBlock *root); @@ -35,17 +35,14 @@ class Traverser : public TIntermTraverser const TFunction *getRotateFunc(); - SpecConst *mSpecConst = nullptr; const DriverUniform *mDriverUniforms = nullptr; TIntermFunctionDefinition *mRotateFunc = nullptr; }; Traverser::Traverser(TSymbolTable *symbolTable, - SpecConst *specConst, const DriverUniform *driverUniforms) : TIntermTraverser(true, false, false, symbolTable), - mSpecConst(specConst), mDriverUniforms(driverUniforms) {} @@ -122,12 +119,7 @@ const TFunction *Traverser::getRotateFunc() // // return (swap ? offset.yx : offset) * flip; - TIntermTyped *swapXY = mSpecConst->getSwapXY(); - if (swapXY == nullptr) - { - swapXY = mDriverUniforms->getSwapXY(); - } - + TIntermTyped *swapXY = mDriverUniforms->getSwapXY(); TIntermTyped *flipXY = mDriverUniforms->getFlipXY(mSymbolTable, DriverUniformFlip::Fragment); TIntermSwizzle *offsetYX = new TIntermSwizzle(new TIntermSymbol(offsetParam), {1, 0}); @@ -149,7 +141,6 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable, int shaderVersion, - SpecConst *specConst, const DriverUniform *driverUniforms) { // interpolateAtOffset is only valid in GLSL 3.0 and later. @@ -158,7 +149,7 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler, return true; } - Traverser traverser(symbolTable, specConst, driverUniforms); + Traverser traverser(symbolTable, driverUniforms); root->traverse(&traverser); return traverser.update(compiler, root); } diff --git a/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.h b/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.h index e2f799a97ca..0ab23feb96f 100644 --- a/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.h +++ b/src/compiler/translator/tree_ops/spirv/RewriteInterpolateAtOffset.h @@ -23,7 +23,6 @@ namespace sh class TCompiler; class TIntermBlock; class TSymbolTable; -class SpecConst; class DriverUniform; // If fragRotation = nullptr, no rotation will be applied. @@ -31,7 +30,6 @@ class DriverUniform; TIntermBlock *root, TSymbolTable *symbolTable, int shaderVersion, - SpecConst *specConst, const DriverUniform *driverUniforms); } // namespace sh diff --git a/src/compiler/translator/tree_ops/spirv/RewriteR32fImages.cpp b/src/compiler/translator/tree_ops/spirv/RewriteR32fImages.cpp index 51bd5f869ed..dba0800fcb5 100644 --- a/src/compiler/translator/tree_ops/spirv/RewriteR32fImages.cpp +++ b/src/compiler/translator/tree_ops/spirv/RewriteR32fImages.cpp @@ -300,18 +300,9 @@ class RewriteR32fImagesTraverser : public TIntermTraverser case EbtImageCube: newType->setBasicType(EbtUImageCube); break; - case EbtImage2DMS: - newType->setBasicType(EbtUImage2DMS); - break; - case EbtImage2DMSArray: - newType->setBasicType(EbtUImage2DMSArray); - break; case EbtImageCubeArray: newType->setBasicType(EbtUImageCubeArray); break; - case EbtImageRect: - newType->setBasicType(EbtUImageRect); - break; case EbtImageBuffer: newType->setBasicType(EbtUImageBuffer); break; diff --git a/src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.cpp b/src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.cpp new file mode 100644 index 00000000000..70bf27515b8 --- /dev/null +++ b/src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.cpp @@ -0,0 +1,100 @@ +// +// Copyright 2025 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. +// +// RewriteSamplerExternalTexelFetch: Rewrite texelFetch() for external samplers to texture() so that +// yuv decoding happens according to the sampler. +// + +#include "compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +// In GLES, texelFetch decodes YUV according to the sampler, while the SPIR-V equivalent +// (OpImageFetch) does not take a sampler and cannot do that. The texelFetch() call is changed to +// texture() here to get the GLES behavior. +class Traverser : public TIntermTraverser +{ + public: + Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) {} + + bool visitAggregate(Visit visit, TIntermAggregate *node) override; +}; + +bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (node->getOp() != EOpTexelFetch) + { + return true; + } + + const TIntermSequence &arguments = *node->getSequence(); + ASSERT(arguments.size() == 3); + + TIntermTyped *sampler = arguments[0]->getAsTyped(); + TIntermTyped *coords = arguments[1]->getAsTyped(); + TIntermTyped *lod = arguments[2]->getAsTyped(); + + const TBasicType samplerType = sampler->getType().getBasicType(); + if (samplerType != EbtSamplerExternalOES && samplerType != EbtSamplerExternal2DY2YEXT) + { + return true; + } + + // Change + // + // texelFetch(externalSampler, coords, lod) + // + // to + // + // texture(externalSampler, (vec2(coords) + vec2(0.5)) + // / vec2(textureSize(externalSampler, lod))) + // + // Note that |texelFetch| takes integer coordinates, while |texture| takes normalized + // coordinates. The division by |textureSize| achieves normalization. Additionally, an offset + // of half a pixel (vec2(0.5)) is added to the coordinates such that |texture|'s sampling is + // done at the center of the pixel, returning only the value of that pixel and not an + // interpolation with its neighboring pixels. + // + const TPrecision coordsPrecision = coords->getType().getPrecision(); + TType *vec2Type = new TType(EbtFloat, coordsPrecision, EvqTemporary, 2); + + // textureSize(externalSampler, lod) + TIntermTyped *textureSizeCall = + CreateBuiltInFunctionCallNode("textureSize", {sampler, lod}, *mSymbolTable, 300); + // vec2(textureSize(externalSampler, lod)) + textureSizeCall = TIntermAggregate::CreateConstructor(*vec2Type, {textureSizeCall}); + + constexpr float kHalfPixelOffset[2] = {0.5, 0.5}; + TIntermTyped *halfPixel = CreateVecNode(kHalfPixelOffset, 2, coordsPrecision); + + // vec2(coords) + TIntermTyped *scaledCoords = TIntermAggregate::CreateConstructor(*vec2Type, {coords}); + // vec2(coords) + vec2(0.5) + scaledCoords = new TIntermBinary(EOpAdd, scaledCoords, halfPixel); + // (vec2(coords) + vec2(0.5)) / vec2(textureSize(externalSampler, lod))) + scaledCoords = new TIntermBinary(EOpDiv, scaledCoords, textureSizeCall); + + TIntermTyped *textureCall = CreateBuiltInFunctionCallNode( + "texture", {sampler->deepCopy(), scaledCoords}, *mSymbolTable, 300); + queueReplacement(textureCall, OriginalNode::IS_DROPPED); + return true; +} +} // anonymous namespace + +bool RewriteSamplerExternalTexelFetch(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + Traverser traverser(symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} +} // namespace sh diff --git a/src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.h b/src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.h new file mode 100644 index 00000000000..6f4eb63456d --- /dev/null +++ b/src/compiler/translator/tree_ops/spirv/RewriteSamplerExternalTexelFetch.h @@ -0,0 +1,28 @@ +// +// Copyright 2025 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. +// +// RewriteSamplerExternalTexelFetch: Rewrite texelFetch() for external samplers to texture() so that +// yuv decoding happens according to the sampler. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_SPIRV_REWRITESAMPLEREXTERNALTEXELFETCH_H_ +#define COMPILER_TRANSLATOR_TREEOPS_SPIRV_REWRITESAMPLEREXTERNALTEXELFETCH_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool RewriteSamplerExternalTexelFetch(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_SPIRV_REWRITESAMPLEREXTERNALTEXELFETCH_H_ diff --git a/src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.cpp b/src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.cpp new file mode 100644 index 00000000000..44135a55121 --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.cpp @@ -0,0 +1,123 @@ +// +// Copyright 2025 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. +// +// EmulateMutableFunctionParams: if any function params are written to, replace +// them with a temp variable initialized at the start of the function with the value of the params, +// because params are immutable in WGSL, for now. +// + +#include "compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.h" + +#include "common/log_utils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/tree_util/DriverUniform.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/Visit.h" +#include "compiler/translator/util.h" + +namespace sh +{ +namespace +{ + +bool IsParamImmutableInWgsl(const TVariable *var) +{ + TQualifier q = var->getType().getQualifier(); + // Outparams (EvqOut, EvqInOut) are translated as pointers and don't need any extra mutability. + // EvqParamConst is obviously immutable. + return q == EvqParamIn; +} + +class EmulateMutableFunctionParamsTraverser : public TLValueTrackingTraverser +{ + public: + EmulateMutableFunctionParamsTraverser(TSymbolTable *symbolTable) + : TLValueTrackingTraverser(true, false, false, symbolTable) + {} + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *func) override + { + mCurrentFunc = func; + return true; + } + + void visitSymbol(TIntermSymbol *node) override + { + const TVariable *paramVar = &node->variable(); + // Only looking at params used within functions. + if (mInGlobalScope || !IsParamImmutableInWgsl(paramVar)) + { + return; + } + + // Keeps track of each param (TFunctionDefinition*, TVariable*) that is possibly written to. + if (isLValueRequiredHere()) + { + mParamsWrittenTo[paramVar->uniqueId()] = {mCurrentFunc, paramVar}; + } + + // Keep track of all param usage in the function, so later in traversal the param is written + // to and therefore will be replaced with a temporary, the traverser can replace this usage + // with a usage of the temporary. + mParamUsages[paramVar->uniqueId()].push_back({node, getParentNode()}); + } + + bool update(TCompiler *compiler, TIntermBlock *root) + { + for (auto &[paramId, paramInfo] : mParamsWrittenTo) + { + // Declare the temporary and initialize it with the parameter. + TIntermDeclaration *tempVarDecl = nullptr; + TVariable *tempVar = DeclareTempVariable( + mSymbolTable, new TIntermSymbol(paramInfo.paramVar), EvqTemporary, &tempVarDecl); + + // Put the declaration at the top of the function body. + insertStatementsInBlockAtPosition(paramInfo.funcDef->getBody(), 0, {tempVarDecl}, {}); + + // Replace all the references to the parameter with references to the temp var. + for (const ParamUsageInfo ¶mUse : mParamUsages[paramId]) + { + queueReplacementWithParent(paramUse.paramUsageParent, paramUse.paramUsage, + new TIntermSymbol(tempVar), OriginalNode::IS_DROPPED); + } + } + + // Apply updates and validate + return updateTree(compiler, root); + } + + private: + struct ParamInfo + { + TIntermFunctionDefinition *funcDef; + const TVariable *paramVar; + }; + struct ParamUsageInfo + { + TIntermSymbol *paramUsage; + TIntermNode *paramUsageParent; + }; + + TMap mParamsWrittenTo; + TMap> mParamUsages; + + TIntermFunctionDefinition *mCurrentFunc; +}; + +} // anonymous namespace + +bool EmulateMutableFunctionParams(TCompiler *compiler, TIntermBlock *root) +{ + EmulateMutableFunctionParamsTraverser traverser(&compiler->getSymbolTable()); + root->traverse(&traverser); + return traverser.update(compiler, root); +} +} // namespace sh diff --git a/src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.h b/src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.h new file mode 100644 index 00000000000..68a584c803f --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.h @@ -0,0 +1,46 @@ +// +// Copyright 2025 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. +// +// EmulateMutableFunctionParams: If function parameters are modified +// in the function body, they are replaced with temporary copies, since +// function parameters are always immuable in WGSL. +// +// Example: +// +// vec4 doFoo(Foo foo, float zw) +// { +// foo.x = foo.y; +// return vec4(foo.x, foo.y, zw, zw); +// } +// +// Result: +// +// vec4 doFoo(Foo foo, float zw) +// { +// Foo sbc7 = foo; +// sbc7.x = sbc7.y; +// return vec4(sbc7.x, sbc7.y, zw, zw); +// } +// +// NOTE: this an be deleted if WGSL standardized mutable function parameters. +// https://github.com/gpuweb/gpuweb/issues/4113 +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_WGSL_EMULATEMUTABLEFUNCTIONPARAMS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_WGSL_EMULATEMUTABLEFUNCTIONPARAMS_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool EmulateMutableFunctionParams(TCompiler *compiler, TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_WGSL_EMULATEMUTABLEFUNCTIONPARAMS_H_ diff --git a/src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.cpp b/src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.cpp new file mode 100644 index 00000000000..4990bfc3b90 --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.cpp @@ -0,0 +1,737 @@ +// +// Copyright 2025 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. +// +// PullExpressionsIntoFunctions: certains patterns must be pulled into +// functions. +// + +#include "compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.h" + +#include "common/log_utils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/OutputTree.h" +#include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h" +#include "compiler/translator/tree_util/DriverUniform.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/tree_util/Visit.h" +#include "compiler/translator/util.h" + +namespace sh +{ +namespace +{ + +const TType *GetHelperType(const TType &type, std::optional qualifier) +{ + // If the type does not have a precision, it typically means that none of the values that + // comprise the typed expression have precision (for example because they are constants, or + // bool), and there isn't any precision propagation happening from nearby operands. In that + // case, assign a highp precision to them; the driver will probably inline and eliminate the + // call anyway, and the precision does not affect anything. + constexpr TPrecision kDefaultPrecision = EbpHigh; + + TType *newType = new TType(type); + if (IsPrecisionApplicableToType(type.getBasicType())) + { + newType->setPrecision(type.getPrecision() != EbpUndefined ? type.getPrecision() + : kDefaultPrecision); + } + if (qualifier.has_value()) + { + newType->setQualifier(qualifier.value()); + } + + return newType; +} + +class PullExpressionsIntoFunctionsTraverser : public TIntermTraverser +{ + public: + PullExpressionsIntoFunctionsTraverser(TCompiler *compiler, TSymbolTable *symbolTable) + : TIntermTraverser(true, false, true, symbolTable), mCompiler(compiler) + {} + + // Just used to keep track of the current function. + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *func) override + { + mCurrentFunction = func; + return true; + } + + // Records a usage of a symbol if traversing an untranslatable construct. Only records usage of + // temporaries and parameters. + void visitSymbol(TIntermSymbol *symbol) override + { + TQualifier q = symbol->getType().getQualifier(); + const bool symbolIsNotGlobal = q == EvqTemporary || IsParam(q); + if (mUntranslatableConstructDepth > 0 && symbolIsNotGlobal) + { + mSymbolsInsideUntranslatableConstructs[symbol->variable().uniqueId()] = + &symbol->variable(); + } + } + + // Caches all variable declarations, in case they need to be moved into the global scope (in + // case the variable is used in an untranslatable construct, which are moved into other + // functions entirely). + bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override + { + if (visit != PreVisit) + { + return true; + } + + // No need to replace variables declared inside the untranslatable construct. + Declaration declView = ViewDeclaration(*decl); + if (mUntranslatableConstructDepth == 0 && + declView.symbol.getType().getQualifier() == EvqTemporary) + { + // Declarations should always be split into individual declarations before + ASSERT(decl->getChildCount() == 1); + + mDeclarationCache[declView.symbol.variable().uniqueId()] = {decl, getParentNode()}; + } + + return true; + } + + // -------------------------------------------------------------------- + // The rest of the traverser detects untranslatable constructs: + + bool visitTernary(Visit visit, TIntermTernary *ternary) override + { + handleUntranslatableConstruct(visit, {{ternary}, getParentNode(), mCurrentFunction}); + return true; + } + + bool visitBinary(Visit visit, TIntermBinary *binary) override + { + if (binary->getOp() == EOpComma) + { + handleUntranslatableConstruct( + visit, UntranslatableConstructAndMetadata{UntranslatableCommaOperator{binary}, + getParentNode(), mCurrentFunction}); + } + if (IsMultielementSwizzleAssignment(binary->getOp(), binary->getLeft()) && + !CanRewriteMultiElementSwizzleAssignmentEasily(binary, getParentNode())) + { + + handleUntranslatableConstruct( + visit, UntranslatableConstructAndMetadata{UntranslatableMultiElementSwizzle{binary}, + getParentNode(), mCurrentFunction}); + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override + { + const TFunction *calledFunction = aggregate->getFunction(); + if (aggregate->getOp() != EOpCallFunctionInAST || !calledFunction) + { + return true; + } + + TSet outparamVars; + bool foundIncompatibleOutparam = false; + for (size_t i = 0; i < calledFunction->getParamCount(); ++i) + { + TQualifier paramQualifier = calledFunction->getParam(i)->getType().getQualifier(); + if (IsParamOut(paramQualifier)) + { + const TVariable *argRootVariable = FindRootVariable(aggregate->getChildNode(i)); + // Any global vars as outparams can conflict (in terms of WGSL's pointer alias + // analysis) with accesses to the actual global var, so to be safe, any + // non-temporary vars as outparams are consider to be incompatible. + // WGSL also requires pointer to specify whether they are pointers to temporaries + // or module-scope variables, which makes WGSL output more complicated unless we + // only ever allow temporaries as outparams. + // This makes an exception for parameters as well, which can be treated as + // temporaries. + TQualifier q = argRootVariable->getType().getQualifier(); + if (q != EvqTemporary && !IsParam(q)) + { + foundIncompatibleOutparam = true; + break; + } + // Different temporary variables can all be used as outparams to the same function. + // In fact this is what the translation will do for incompatible calls. + if (!outparamVars.insert(argRootVariable).second) + { + foundIncompatibleOutparam = true; + break; + } + } + } + if (!foundIncompatibleOutparam) + { + return true; + } + + handleUntranslatableConstruct(visit, {aggregate, getParentNode(), mCurrentFunction}); + + return true; + } + + bool foundUntranslatableConstruct() const { return !mUntranslatableConstructs.empty(); } + + bool update(TIntermBlock *root) + { + return replaceTempVarsWithGlobals(root) && + pullUntranslatableConstructsIntoFunctions(root) && updateTree(mCompiler, root); + } + + private: + using UntranslatableTernary = TIntermTernary *; + struct UntranslatableCommaOperator + { + TIntermBinary *commaOperator; + }; + using UntranslatableFunctionCallWithOutparams = TIntermAggregate *; + struct UntranslatableMultiElementSwizzle + { + TIntermBinary *multielementSwizzle; + }; + + using UntranslatableConstruct = std::variant; + + struct UntranslatableConstructAndMetadata + { + UntranslatableConstruct construct; + TIntermNode *parent; + const TIntermFunctionDefinition *parentFunction; + }; + + void handleUntranslatableConstruct(Visit visit, UntranslatableConstructAndMetadata construct) + { + if (mInGlobalScope) + { + UNREACHABLE(); + return; + } + + // We are currently visiting an untranslatable construct. + if (visit == PostVisit) + { + // After visiting children, decrement our depth. + mUntranslatableConstructDepth--; + return; + } + + ASSERT(visit == PreVisit); + + // If inside another untranslatable construct, continue to traverse to find symbols and + // declarations but do not record more untranslatable constructs. One layer at a time! + if (mUntranslatableConstructDepth++ > 0) + { + return; + } + + mUntranslatableConstructs.push_back(std::move(construct)); + } + + bool addParamsFromOtherFunctionAndReplace(TFunction *substituteFunction, + TIntermFunctionDefinition *substituteFunctionDef, + const TIntermFunctionDefinition *oldFunction) + { + // NOTE: don't always need to forward every parameter, but it's easiest. + VariableReplacementMap argumentMap; + for (size_t paramIndex = 0; paramIndex < oldFunction->getFunction()->getParamCount(); + ++paramIndex) + { + + const TVariable *originalParam = oldFunction->getFunction()->getParam(paramIndex); + TVariable *substituteArgument = + new TVariable(mSymbolTable, originalParam->name(), &originalParam->getType(), + originalParam->symbolType()); + // Not replaced, add an identical parameter. + substituteFunction->addParameter(substituteArgument); + argumentMap[originalParam->uniqueId()] = new TIntermSymbol(substituteArgument); + } + + if (!ReplaceVariables(mCompiler, substituteFunctionDef, argumentMap)) + { + return false; + } + + return true; + } + + // Converts a ternary into an if/else block within a new function. + // Adds a new function prototype and a new function definition to the respective + // TIntermSequences. + TFunction *replaceTernary(TIntermTernary *ternary, + const TIntermFunctionDefinition *parentFunction, + TIntermSequence &newFunctionPrototypes, + TIntermSequence &newFunctionDefinitions) + { + // Pull into function with if/else, should work because all global vars. + // Can just use ternary->getTrueExpression() and ternary->getCondition() etc. directly + // because they should not reference any temporaries, and they do not need to be + // deepCopied because they are moving rather than being copied. + TIntermBranch *retTrueCase = + new TIntermBranch(TOperator::EOpReturn, ternary->getTrueExpression()); + TIntermBranch *retFalseCase = + new TIntermBranch(TOperator::EOpReturn, ternary->getFalseExpression()); + TIntermIfElse *ifElse = + new TIntermIfElse(ternary->getCondition(), new TIntermBlock({retTrueCase}), + new TIntermBlock({retFalseCase})); + TIntermBlock *substituteFunctionBody = new TIntermBlock({ifElse}); + + TFunction *substituteFunction = new TFunction( + mSymbolTable, kEmptyImmutableString, SymbolType::AngleInternal, + GetHelperType(ternary->getType(), EvqTemporary), !ternary->hasSideEffects()); + + // Make sure to insert new function definitions and prototypes. + newFunctionPrototypes.push_back(new TIntermFunctionPrototype(substituteFunction)); + TIntermFunctionDefinition *substituteFunctionDef = new TIntermFunctionDefinition( + new TIntermFunctionPrototype(substituteFunction), substituteFunctionBody); + newFunctionDefinitions.push_back(substituteFunctionDef); + + addParamsFromOtherFunctionAndReplace(substituteFunction, substituteFunctionDef, + parentFunction); + + return substituteFunction; + } + + TFunction *replaceCallToFuncWithOutparams(TIntermAggregate *funcCall, + const TIntermFunctionDefinition *parentFunction, + TIntermSequence &newFunctionPrototypes, + TIntermSequence &newFunctionDefinitions) + { + TIntermSequence initSequence; + TIntermSequence finishSequence; + + TIntermSequence newCallArgs; + + // Create temporaries for all the parameters. Arguments must be evaluated in order. + const TFunction *callee = funcCall->getFunction(); + for (size_t i = 0; i < callee->getParamCount(); i++) + { + TIntermTyped *arg = funcCall->getChildNode(i)->getAsTyped(); + ASSERT(arg); + const TVariable *param = callee->getParam(i); + TQualifier paramQ = param->getType().getQualifier(); + + // Create temp variable for each argument to the original function. + TVariable *newArg = CreateTempVariable(mSymbolTable, ¶m->getType(), EvqTemporary); + // We will use temp as the argument for the new function call. + newCallArgs.push_back(new TIntermSymbol(newArg)); + + if (paramQ == EvqParamInOut || paramQ == EvqParamOut) + { + // If inout-param, save pointer to argument. Otherwise we may evaluate arg twice, + // and even though arg must be an l-value, it can still have side effects (e.g. in + // x[i++] = ...); + TVariable *newArgPtr = + CreateTempVariable(mSymbolTable, ¶m->getType(), EvqTemporary); + TFunction *getPointerFunc = + new TFunction(mSymbolTable, ImmutableString("ANGLE_takePointer"), + SymbolType::AngleInternal, ¶m->getType(), false); + getPointerFunc->addParameter( + CreateTempVariable(mSymbolTable, ¶m->getType(), EvqParamInOut)); + TIntermSequence *getPointerCallArgs = new TIntermSequence({arg}); + TIntermAggregate *getPointerCall = + TIntermAggregate::CreateRawFunctionCall(*getPointerFunc, getPointerCallArgs); + // temp_ptr = &arg; (argument should only reference global variables) + initSequence.push_back(CreateTempInitDeclarationNode(newArgPtr, getPointerCall)); + if (paramQ == EvqParamInOut) + { + // temp = *temp_ptr; (The traverser will see the pointer variable and + // automatically dereference it.) + initSequence.push_back( + CreateTempInitDeclarationNode(newArg, new TIntermSymbol(newArgPtr))); + } + else + { + ASSERT(paramQ == EvqParamOut); + // Before the function call, just create empty var for outparam purposes. E.g.: + // temp : f32; + initSequence.push_back(CreateTempDeclarationNode(newArg)); + } + + // After the function call: + // *temp_ptr = temp; + finishSequence.push_back( + CreateTempAssignmentNode(newArgPtr, new TIntermSymbol(newArg))); + } + else if (paramQ == EvqParamIn || paramQ == EvqParamConst) + { + // temp = argument; (argument should only reference global variables), + initSequence.push_back(CreateTempInitDeclarationNode(newArg, arg)); + } + else + { + UNREACHABLE(); + } + } + + // Start the callSequence with the initSequence. + TIntermSequence callSequence = std::move(initSequence); + + // Create a call to the function with outparams. + TIntermAggregate *newCall = TIntermAggregate::CreateFunctionCall(*callee, &newCallArgs); + // If necessary, save the return value of the call. + TVariable *retVal = nullptr; + const bool needsToSaveRetVal = + funcCall->getFunction()->getReturnType().getBasicType() != EbtVoid; + if (needsToSaveRetVal) + { + retVal = CreateTempVariable(mSymbolTable, &funcCall->getFunction()->getReturnType(), + EvqTemporary); + TIntermDeclaration *savedRetVal = CreateTempInitDeclarationNode(retVal, newCall); + callSequence.push_back(savedRetVal); + } + else + { + callSequence.push_back(newCall); + } + + // Finish with the finishSequence. + callSequence.insert(callSequence.end(), finishSequence.begin(), finishSequence.end()); + + // Return a value if necessary. + if (needsToSaveRetVal) + { + callSequence.push_back( + new TIntermBranch(TOperator::EOpReturn, new TIntermSymbol(retVal))); + } + + TIntermBlock *substituteFunctionBody = new TIntermBlock(std::move(callSequence)); + + TFunction *substituteFunction = + new TFunction(mSymbolTable, kEmptyImmutableString, SymbolType::AngleInternal, + GetHelperType(funcCall->getFunction()->getReturnType(), std::nullopt), + funcCall->getFunction()->isKnownToNotHaveSideEffects()); + + // Make sure to insert new function definitions and prototypes. + newFunctionPrototypes.push_back(new TIntermFunctionPrototype(substituteFunction)); + TIntermFunctionDefinition *substituteFunctionDef = new TIntermFunctionDefinition( + new TIntermFunctionPrototype(substituteFunction), substituteFunctionBody); + newFunctionDefinitions.push_back(substituteFunctionDef); + + addParamsFromOtherFunctionAndReplace(substituteFunction, substituteFunctionDef, + parentFunction); + + return substituteFunction; + } + + TFunction *replaceSequenceOperator(TIntermBinary *sequenceOperator, + const TIntermFunctionDefinition *parentFunction, + TIntermSequence &newFunctionPrototypes, + TIntermSequence &newFunctionDefinitions) + { + ASSERT(sequenceOperator->getOp() == EOpComma); + + // Pull into function that just puts one statement after the other. + + TIntermSequence extractedStmts; + + // Flatten the nested comma operators into a sequence of statements. + std::stack> stmts; + stmts.push(sequenceOperator->getRight()); + stmts.push(sequenceOperator->getLeft()); + while (!stmts.empty()) + { + TIntermTyped *stmt = stmts.top(); + stmts.pop(); + + if (TIntermBinary *nestedSequenceOperator = stmt->getAsBinaryNode(); + nestedSequenceOperator && nestedSequenceOperator->getOp() == EOpComma) + { + stmts.push(nestedSequenceOperator->getRight()); + stmts.push(nestedSequenceOperator->getLeft()); + continue; + } + + extractedStmts.push_back(stmt); + } + + // The last statement needs a return, if it is not of type void (i.e. the type of a function + // call to a void-returning function). + TIntermNode *lastStmt = extractedStmts.back(); + if (lastStmt->getAsTyped()->getBasicType() != EbtVoid) + { + extractedStmts.back() = new TIntermBranch(TOperator::EOpReturn, lastStmt->getAsTyped()); + } + + TIntermBlock *substituteFunctionBody = new TIntermBlock(std::move(extractedStmts)); + + TFunction *substituteFunction = + new TFunction(mSymbolTable, kEmptyImmutableString, SymbolType::AngleInternal, + GetHelperType(sequenceOperator->getType(), EvqTemporary), + !sequenceOperator->hasSideEffects()); + + // Make sure to insert new function definitions and prototypes. + newFunctionPrototypes.push_back(new TIntermFunctionPrototype(substituteFunction)); + TIntermFunctionDefinition *substituteFunctionDef = new TIntermFunctionDefinition( + new TIntermFunctionPrototype(substituteFunction), substituteFunctionBody); + newFunctionDefinitions.push_back(substituteFunctionDef); + + addParamsFromOtherFunctionAndReplace(substituteFunction, substituteFunctionDef, + parentFunction); + + return substituteFunction; + } + + TFunction *replaceDifficultMultielementSwizzle(TIntermBinary *swizzleAssignment, + const TIntermFunctionDefinition *parentFunction, + TIntermSequence &newFunctionPrototypes, + TIntermSequence &newFunctionDefinitions) + { + // Pull into a function that takes the swizzle operand as an outparam, which will then be + // handled by future passes of this AST traverser if necessary. + TIntermSwizzle *oldSwizzle = swizzleAssignment->getLeft()->getAsSwizzleNode(); + ASSERT(oldSwizzle); + + TType *paramType = new TType(oldSwizzle->getOperand()->getType()); + paramType->setQualifier(swizzleAssignment->getOp() == EOpAssign ? EvqParamOut + : EvqParamInOut); + TVariable *operandParam = new TVariable(mSymbolTable, kEmptyImmutableString, paramType, + SymbolType::AngleInternal); + + // Swizzle the outparam: + TIntermSwizzle *swizzledParam = + new TIntermSwizzle(new TIntermSymbol(operandParam), oldSwizzle->getSwizzleOffsets()); + + // Assign to the swizzled outparam instead of the original + TIntermBinary *newSwizzleAssignment = new TIntermBinary( + swizzleAssignment->getOp(), swizzledParam, swizzleAssignment->getRight()); + + // The swizzle assignment has a result, so return it. + TIntermBranch *result = new TIntermBranch(TOperator::EOpReturn, swizzledParam->deepCopy()); + TIntermBlock *substituteFunctionBody = new TIntermBlock({newSwizzleAssignment, result}); + + TFunction *substituteFunction = + new TFunction(mSymbolTable, kEmptyImmutableString, SymbolType::AngleInternal, + GetHelperType(swizzleAssignment->getType(), EvqTemporary), + !swizzleAssignment->getRight()->hasSideEffects()); + + substituteFunction->addParameter(operandParam); + + // Make sure to insert new function definitions and prototypes. + newFunctionPrototypes.push_back(new TIntermFunctionPrototype(substituteFunction)); + TIntermFunctionDefinition *substituteFunctionDef = new TIntermFunctionDefinition( + new TIntermFunctionPrototype(substituteFunction), substituteFunctionBody); + newFunctionDefinitions.push_back(substituteFunctionDef); + + addParamsFromOtherFunctionAndReplace(substituteFunction, substituteFunctionDef, + parentFunction); + + return substituteFunction; + } + + bool replaceTempVarsWithGlobals(TIntermBlock *root) + { + TIntermSequence globalDeclarations; + VariableReplacementMap tempToGlobal; + for (const auto &[varId, var] : mSymbolsInsideUntranslatableConstructs) + { + auto declIt = mDeclarationCache.find(varId); + if (declIt == mDeclarationCache.end()) + { + // If the declaration is inside the untranslatable construct, it won't be in the map + // because it does not need to be replaced with a global. + continue; + } + + std::pair &declAndParent = declIt->second; + TIntermDeclaration *decl = declAndParent.first; + TIntermNode *parentOfDecl = declAndParent.second; + + ASSERT(var->getType().getQualifier() == EvqTemporary); + + TType *globalType = new TType(var->getType()); + globalType->setQualifier(EvqGlobal); + + const TVariable *replacementVariable = + new TVariable(mSymbolTable, var->name(), globalType, var->symbolType()); + + // Make sure to declare global variable replacement. Ignore the init expression, that + // will be done in the same place as the temporary declaration. + globalDeclarations.push_back(new TIntermDeclaration({replacementVariable})); + + if (TIntermBinary *binaryInitExpr = decl->getChildNode(0)->getAsBinaryNode()) + { + ASSERT(binaryInitExpr->getOp() == EOpInitialize); + TIntermBinary *newAssignment = new TIntermBinary( + EOpAssign, new TIntermSymbol(replacementVariable), binaryInitExpr->getRight()); + // Replace the declaration with the binary init expression. + parentOfDecl->replaceChildNode(decl, newAssignment); + + // The untranslatable constructs that were the RHS of this binary initialization + // expression now have a new parent, the new binary assignment expression. + for (UntranslatableConstructAndMetadata &constructAndMetadata : + mUntranslatableConstructs) + { + if (constructAndMetadata.parent == binaryInitExpr) + { + constructAndMetadata.parent = newAssignment; + } + } + } + else + { + // TODO(anglebug.com/42267100): there can be declarations inside loops, not just + // blocks. Need to remove them from there probably. Or not, and this code should + // know how to remove declarations from while loops. + if (!parentOfDecl->getAsBlock()) + { + UNIMPLEMENTED(); + continue; + } + // Delete the declaration, the global one already exists. + parentOfDecl->getAsBlock()->replaceChildNodeWithMultiple(decl, TIntermSequence()); + } + + // For ReplaceVariables() to replace the temp variable with a reference to the global. + tempToGlobal[var->uniqueId()] = new TIntermSymbol(replacementVariable); + } + + // Insert the global declarations. + const size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(root); + root->insertChildNodes(firstFunctionIndex, std::move(globalDeclarations)); + + // Replace the variables with references to the new global ones. + if (!ReplaceVariables(mCompiler, root, tempToGlobal)) + { + return false; + } + + return true; + } + + bool pullUntranslatableConstructsIntoFunctions(TIntermBlock *root) + { + TIntermSequence newFunctionPrototypes; + TIntermSequence newFunctionDefinitions; + + for (UntranslatableConstructAndMetadata &constructAndMetadata : mUntranslatableConstructs) + { + UntranslatableConstruct &construct = constructAndMetadata.construct; + TIntermNode *untranslatableNode = nullptr; + TFunction *substituteFunction = nullptr; + TIntermSequence args; + + if (TIntermTernary **ternary = std::get_if(&construct)) + { + untranslatableNode = *ternary; + substituteFunction = replaceTernary(*ternary, constructAndMetadata.parentFunction, + newFunctionPrototypes, newFunctionDefinitions); + } + else if (UntranslatableCommaOperator *commaOperator = + std::get_if(&construct)) + { + untranslatableNode = commaOperator->commaOperator; + substituteFunction = replaceSequenceOperator( + commaOperator->commaOperator, constructAndMetadata.parentFunction, + newFunctionPrototypes, newFunctionDefinitions); + } + else if (TIntermAggregate **funcCall = + std::get_if(&construct)) + { + untranslatableNode = *funcCall; + substituteFunction = + replaceCallToFuncWithOutparams(*funcCall, constructAndMetadata.parentFunction, + newFunctionPrototypes, newFunctionDefinitions); + } + else if (UntranslatableMultiElementSwizzle *multielementSwizzleAssignment = + std::get_if(&construct)) + { + untranslatableNode = multielementSwizzleAssignment->multielementSwizzle; + substituteFunction = replaceDifficultMultielementSwizzle( + multielementSwizzleAssignment->multielementSwizzle, + constructAndMetadata.parentFunction, newFunctionPrototypes, + newFunctionDefinitions); + + args.push_back(multielementSwizzleAssignment->multielementSwizzle->getLeft() + ->getAsSwizzleNode() + ->getOperand()); + } + else + { + UNREACHABLE(); + } + + // The parameters of the parent function must be passed to the new function. + for (size_t i = 0; + i < constructAndMetadata.parentFunction->getFunction()->getParamCount(); i++) + { + const TVariable *param = + constructAndMetadata.parentFunction->getFunction()->getParam(i); + args.push_back(new TIntermSymbol(param)); + } + + queueReplacementWithParent( + constructAndMetadata.parent, untranslatableNode, + TIntermAggregate::CreateFunctionCall(*substituteFunction, &args), + OriginalNode::IS_DROPPED); + } + + // Insert new function prototypes so they are defined for all the following functions. + const size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(root); + root->insertChildNodes(firstFunctionIndex, newFunctionPrototypes); + // And insert the function definitions at the end so all called functions are + // legal. + root->insertChildNodes(root->getChildCount(), newFunctionDefinitions); + + return true; + } + + TCompiler *mCompiler; + + size_t mUntranslatableConstructDepth = 0; + + const TIntermFunctionDefinition *mCurrentFunction = nullptr; + + // Tracks all the untranslatable constructs found. + TVector mUntranslatableConstructs; + + // Keeps track of all temporary variables used in untranslatable constructs. + TMap mSymbolsInsideUntranslatableConstructs; + // Keeps track of all declaration of temporary variables anywhere outside of untranslatable + // constructs, as well as the parent nodes of those temp vars. + TMap> mDeclarationCache; +}; + +} // anonymous namespace + +bool PullExpressionsIntoFunctions(TCompiler *compiler, TIntermBlock *root) +{ + // Correct the first level of untranslatable constructs. There may be nested untranslatable + // constructs, and those are handled with subsequent iterations. + do + { + PullExpressionsIntoFunctionsTraverser traverser(compiler, &compiler->getSymbolTable()); + root->traverse(&traverser); + if (traverser.foundUntranslatableConstruct()) + { + if (!traverser.update(root)) + { + return false; + } + } + else + { + break; + } + } while (true); + + return true; +} +} // namespace sh diff --git a/src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.h b/src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.h new file mode 100644 index 00000000000..af3e6599026 --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.h @@ -0,0 +1,32 @@ +// +// Copyright 2025 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. +// +// PullExpressionsIntoFunctions: Certain GLSL expressions are not translatable as single +// expressions. Those that need to be translated into multiple expressions, or into one or more +// statements, are pulled into functions and replaced by a function call. +// +// This works by pulling all temporaries used inside of ternaries into global variables, which is +// fine because recursion is not allowed in GLSL. Function parameters are much more difficult to +// pull into globals, so they are just all passed to the new function. +// +// This makes all arbitrary ternaries, comma operators, outparams, and multielement swizzle +// assignments translatable into WGSL. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_WGSL_PULLEXPRESSIONSINTOFUNCTIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_WGSL_PULLEXPRESSIONSINTOFUNCTIONS_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool PullExpressionsIntoFunctions(TCompiler *compiler, TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_WGSL_PULLEXPRESSIONSINTOFUNCTIONS_H_ diff --git a/src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.cpp b/src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.cpp new file mode 100644 index 00000000000..c5317b9a00c --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.cpp @@ -0,0 +1,259 @@ +// +// Copyright 2025 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. +// +// RewriteMixedTypeMathExprs: Some mixed-type arithmetic is legal in GLSL but not +// WGSL. Generate code to perform the arithmetic as specified in GLSL. +// + +#include "compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.h" + +#include "common/log_utils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/tree_util/DriverUniform.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ +namespace +{ + +class MixedTypeMathExprTraverser : public TIntermTraverser +{ + public: + MixedTypeMathExprTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable) + {} + + bool visitBinary(Visit visit, TIntermBinary *node) override; + + bool update(TCompiler *compiler, TIntermBlock *root); + + private: + // Create a helper function that will just construct a matrix with every element set to the + // scalar. + const TFunction *createMatrixConstructorHelper(const TType &matrixType) + { + ASSERT(matrixType.isMatrix()); + + TType *retType = new TType(matrixType); + retType->setQualifier(EvqTemporary); + + TFunction *helper = new TFunction(mSymbolTable, kEmptyImmutableString, + SymbolType::AngleInternal, retType, true); + + TType *argType = new TType(matrixType); + argType->toComponentType(); + argType->setQualifier(EvqParamIn); + + TVariable *argVar = + new TVariable(mSymbolTable, kEmptyImmutableString, argType, SymbolType::AngleInternal); + helper->addParameter(argVar); + + TIntermSequence constructorArgs; + TIntermTyped *scalar = new TIntermSymbol(argVar); + + // Create a matrix with every element set to the scalar. + for (uint8_t i = 0; i < matrixType.getCols() * matrixType.getRows(); ++i) + { + constructorArgs.push_back(CastScalar(matrixType, scalar->deepCopy())); + } + + TIntermBlock *body = new TIntermBlock; + body->appendStatement(new TIntermBranch( + EOpReturn, TIntermAggregate::CreateConstructor(matrixType, &constructorArgs))); + + mFunctionsToAdd.push_back( + new TIntermFunctionDefinition(new TIntermFunctionPrototype(helper), body)); + + return helper; + } + + // Converts a scalar into a nonscalar type that has every element set to be the scalar. + // This guarantees that `scalar` is added as a child of the returned node, so + // queueReplacementWithParent() can use BECOMES_CHILD and it will automatically be traversed by + // this traverser. + TIntermNode *convertScalarToNonScalar(const TType &nonScalarType, TIntermTyped *scalar) + { + ASSERT(!nonScalarType.isScalar()); + ASSERT(scalar->isScalar()); + + if (nonScalarType.isVector()) + { + // In WGSL, vectors have constructors that take a single scalar and fill the vector with + // that scalar. + return TIntermAggregate::CreateConstructor(nonScalarType, {scalar}); + } + else if (nonScalarType.isMatrix()) + { + // In WGSL, matrices do not have constructors that take a single scalar at all, and in + // the future if they did, they would probably only initialize the diagonal. So, create + // a helper function that does this. + const TFunction *helper = createMatrixConstructorHelper(nonScalarType); + return TIntermAggregate::CreateFunctionCall(*helper, new TIntermSequence{scalar}); + } + else + { + UNREACHABLE(); + return nullptr; + } + } + + TIntermSequence mFunctionsToAdd; +}; + +bool IsMixedTypeOkayInWgsl(const TType &nonScalarType, TOperator op) +{ + // https://www.w3.org/TR/WGSL/#arithmetic-expr:~:text=arithmetic%20expressions%20with%20mixed + if (nonScalarType.isVector()) + { + switch (op) + { + case EOpAdd: + case EOpAddAssign: + case EOpSub: + case EOpSubAssign: + case EOpMul: + case EOpMulAssign: + case EOpDiv: + case EOpDivAssign: + case EOpIMod: + case EOpIModAssign: + case EOpVectorTimesScalar: + case EOpVectorTimesScalarAssign: + return true; + default: + return false; + } + } + + if (nonScalarType.isMatrix() && op == EOpMatrixTimesScalar) + { + return true; + } + + return false; +} + +bool MixedTypeMathExprTraverser::visitBinary(Visit visit, TIntermBinary *binNode) +{ + switch (binNode->getOp()) + { + // All of the following can operate on mixed types. + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + case EOpIMod: + case EOpVectorTimesScalar: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + // Assignments work the same. + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpVectorTimesScalarAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + { + TIntermTyped *scalarNode = nullptr; + TIntermTyped *nonScalarNode = nullptr; + if (binNode->getLeft()->isScalar() && !binNode->getRight()->isScalar()) + { + scalarNode = binNode->getLeft(); + nonScalarNode = binNode->getRight(); + } + else if (!binNode->getLeft()->isScalar() && binNode->getRight()->isScalar()) + { + nonScalarNode = binNode->getLeft(); + scalarNode = binNode->getRight(); + } + else + { + break; + } + + if (IsMixedTypeOkayInWgsl(nonScalarNode->getType(), binNode->getOp())) + { + break; + } + + // TODO(anglebug.com/42267100): WGSL does not support component-wise matrix division. + if (nonScalarNode->isMatrix() && + (binNode->getOp() == EOpDiv || binNode->getOp() == EOpDivAssign)) + { + UNIMPLEMENTED(); + } + + TIntermNode *nonScalarConstructor = + convertScalarToNonScalar(nonScalarNode->getType(), scalarNode); + queueReplacementWithParent(binNode, scalarNode, nonScalarConstructor, + OriginalNode::BECOMES_CHILD); + + break; + } + + // All legal in WGSL: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + case EOpVectorTimesMatrixAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + break; + + // The types must always match for both operands in GLSL comparisons. + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + ASSERT(binNode->getLeft()->getType() == binNode->getRight()->getType()); + break; + // Only operate on booleans. + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + case EOpLogicalNot: + ASSERT(binNode->getLeft()->getBasicType() == EbtBool && + binNode->getRight()->getBasicType() == EbtBool); + break; + default: + return true; + } + + return true; +} + +bool MixedTypeMathExprTraverser::update(TCompiler *compiler, TIntermBlock *root) +{ + // Insert any added function definitions at the tope of the block + root->insertChildNodes(0, mFunctionsToAdd); + + // Apply updates and validate + return updateTree(compiler, root); +} +} // anonymous namespace + +bool RewriteMixedTypeMathExprs(TCompiler *compiler, TIntermBlock *root) +{ + MixedTypeMathExprTraverser traverser(&compiler->getSymbolTable()); + root->traverse(&traverser); + return traverser.update(compiler, root); +} +} // namespace sh diff --git a/src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.h b/src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.h new file mode 100644 index 00000000000..938cacf6593 --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.h @@ -0,0 +1,36 @@ +// +// Copyright 2025 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. +// +// RewriteMixedTypeMathExprs: Some mixed-type arithmetic is legal in GLSL but not +// WGSL. Generate code to perform the arithmetic as specified in GLSL. +// +// Example: +// uvec2 x; +// uint y; +// x &= y; +// Is transformed into: +// x &= uvec(y); +// +// Also, +// mat2 x; +// int y; +// x += y; +// Is transformed into: +// x += mat2(float(y), float(y), float(y), float(y)) +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_WGSL_REWRITEMIXEDTYPEMATHEXPRS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_WGSL_REWRITEMIXEDTYPEMATHEXPRS_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TIntermBlock; + +[[nodiscard]] bool RewriteMixedTypeMathExprs(TCompiler *compiler, TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_WGSL_REWRITEMIXEDTYPEMATHEXPRS_H_ diff --git a/src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.cpp b/src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.cpp new file mode 100644 index 00000000000..fe6880af29d --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.cpp @@ -0,0 +1,195 @@ +// +// Copyright 2025 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. +// +// RewriteMultielemntSwizzleAssignment: WGSL does not support assignment to multielement swizzles. +// This splits them into mutliple assignments to single-element swizzles. +// + +#include "compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h" +#include "common/log_utils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/IntermNode.h" + +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/DriverUniform.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ + +// Splits multielement swizzles into single-element swizzles. +class MultielementSwizzleAssignmentTraverser : public TIntermTraverser +{ + public: + MultielementSwizzleAssignmentTraverser(TCompiler *compiler) + : TIntermTraverser(true, false, false), mCompiler(compiler) + {} + + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitUnary(Visit visit, TIntermUnary *node) override; + + private: + TCompiler *mCompiler; +}; + +bool MultielementSwizzleAssignmentTraverser::visitUnary(Visit vist, TIntermUnary *unaryNode) +{ + if (!IsMultielementSwizzleAssignment(unaryNode->getOp(), unaryNode->getOperand())) + { + return true; + } + + // TODO(anglebug.com/42267100): increments and decrements should be handled by generated WGSL + // functions, and this can just be deleted. + switch (unaryNode->getOp()) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + UNIMPLEMENTED(); + break; + default: + break; + } + return true; +} + +bool MultielementSwizzleAssignmentTraverser::visitBinary(Visit visit, TIntermBinary *parentBinNode) +{ + ASSERT(visit == Visit::PreVisit); + + if (!IsMultielementSwizzleAssignment(parentBinNode->getOp(), parentBinNode->getLeft())) + { + return true; + } + + if (!CanRewriteMultiElementSwizzleAssignmentEasily(parentBinNode, getParentNode())) + { + UNREACHABLE(); + return false; + } + + TIntermSequence insertionsBefore; + + TIntermSwizzle *leftSwizzleNode = parentBinNode->getLeft()->getAsSwizzleNode(); + + // Store the RHS in a temp in case of side effects, since it will be duplicated. + TIntermDeclaration *rhsTempDeclaration; + TVariable *rhsTempVariable = + DeclareTempVariable(&mCompiler->getSymbolTable(), parentBinNode->getRight()->deepCopy(), + EvqTemporary, &rhsTempDeclaration); + insertionsBefore.push_back(rhsTempDeclaration); + + TIntermSequence singleElementSwizzleAssignments; + for (uint32_t i = 0; i < leftSwizzleNode->getSwizzleOffsets().size(); i++) + { + // CanRewriteMultiElementSwizzleAssignmentEasily() should have filtered these cases out. + ASSERT(!leftSwizzleNode->getOperand()->hasSideEffects()); + TIntermTyped *swizzleOperandCopy = leftSwizzleNode->getOperand()->deepCopy(); + TIntermSwizzle *leftSideNewSwizzle = + new TIntermSwizzle(swizzleOperandCopy, {leftSwizzleNode->getSwizzleOffsets()[i]}); + // The resulting swizzle doesn't need folding here because it would've already been folded, + // this just turned it from a multielement into a single element swizzle. + + // Most binary assignments are component-wise and so we just swizzle the right side to + // select one component for this particular single-element swizzle assignment. The only + // special case is multiplication by a matrix, which is not component-wise obviously. + TIntermTyped *newRightSide = CreateTempSymbolNode(rhsTempVariable); + TOperator newOp = parentBinNode->getOp(); + + if (newRightSide->getType().isMatrix() || newRightSide->getType().isVector()) + { + if (newRightSide->getType().isMatrix()) + { + ASSERT(parentBinNode->getOp() == EOpVectorTimesMatrixAssign); + + // The `vec.xy *= mat` is being converted to something like `vec.x = (vec.xy * + // mat).x; vec.y = (vec.xy * mat).y;` + newOp = EOpAssign; + + // TODO(anglebug.com/42267100): this matrix multiplication could be kept in a temp + // var. + newRightSide = new TIntermBinary(EOpVectorTimesMatrix, leftSwizzleNode->deepCopy(), + newRightSide); + } + + ASSERT(newRightSide->getType().isVector()); + + // Now swizzle to select the i-th element. + newRightSide = new TIntermSwizzle(newRightSide, {i}); + // No need to fold newRightSide because we are swizzling either a temporary or the + // binary matrix multiplication, so it won't be a swizzle. + } + else if (newRightSide->getType().isScalar()) + { + // Needs no special handling, and can just be unmodified as the right hand side. + } + else + { + UNREACHABLE(); + } + + // At this point the right hand side should match the type of the left hand side. + ASSERT(newRightSide->isScalar()); + ASSERT(newRightSide->getBasicType() == leftSideNewSwizzle->getBasicType()); + + singleElementSwizzleAssignments.emplace_back( + new TIntermBinary(newOp, leftSideNewSwizzle, newRightSide)); + } + + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), parentBinNode, + std::move(singleElementSwizzleAssignments)); + insertStatementsInParentBlock(insertionsBefore); + + // Already traversed the left and right sides above. + return false; +} +} // anonymous namespace + +bool RewriteMultielementSwizzleAssignment(TCompiler *compiler, TIntermBlock *root) +{ + MultielementSwizzleAssignmentTraverser traverser(compiler); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +bool IsMultielementSwizzleAssignment(TOperator op, TIntermTyped *assignedNode) +{ + if (!IsAssignment(op)) + { + return false; + } + + TIntermSwizzle *leftSwizzleNode = assignedNode->getAsSwizzleNode(); + if (!leftSwizzleNode || leftSwizzleNode->getSwizzleOffsets().size() <= 1) + { + return false; + } + + return true; +} + +// Some multielement swizzles are too complicated without other AST transformations. Namely, swizzle +// assignments that are nested within other expressions or swizzle assignments whose operand has +// side effects. This AST transformation doesn't handle those swizzle assignments. +// `multielementSwizzleAssignment` must be an assignment to a multielement swizzle as determined by +// `IsMultielementSwizzleAssignment()`. +bool CanRewriteMultiElementSwizzleAssignmentEasily(TIntermBinary *multielementSwizzleAssignment, + TIntermNode *parent) +{ + ASSERT(IsMultielementSwizzleAssignment(multielementSwizzleAssignment->getOp(), + multielementSwizzleAssignment->getLeft())); + return parent->getAsBlock() != nullptr && !multielementSwizzleAssignment->getLeft() + ->getAsSwizzleNode() + ->getOperand() + ->hasSideEffects(); +} + +} // namespace sh diff --git a/src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h b/src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h new file mode 100644 index 00000000000..14767363a3e --- /dev/null +++ b/src/compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h @@ -0,0 +1,53 @@ +// +// Copyright 2025 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. +// +// RewriteMultielementSwizzleAssignment: WGSL does not support assignment to multielement swizzles. +// This splits them into mutliple assignments to single-element swizzles. +// +// For example: +// vec3 v1 = ...; +// vec3 v2 = ...; +// v1.xy = v2.yz; +// is converted to: +// vec3 v1 = ...; +// vec3 v2 = ...; +// vec2 sbbc = v2.yz; +// v1.x = v2.x; +// v1.y = v2.y; +// +// Note that temporaries are used in order to avoid duplicated side effects in the RHS. +// +// One special case is multiplication-by-a-matrix assignment: +// vec.xy *= mat; +// is converted to something like +// vec.x = (vec.xy * mat).x; +// vec.y = (vec.xy * mat).y; +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_WGSL_REWRITE_MULTIELEMENTSWIZZLEASSIGNMENT_H_ +#define COMPILER_TRANSLATOR_TREEOPS_WGSL_REWRITE_MULTIELEMENTSWIZZLEASSIGNMENT_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +// Can only be called if CanRewriteMultiElementSwizzleAssignmentEasily() returns true for all +// multi-element swizzles assignments in the tree. +[[nodiscard]] bool RewriteMultielementSwizzleAssignment(TCompiler *compiler, TIntermBlock *root); + +[[nodiscard]] bool IsMultielementSwizzleAssignment(TOperator op, TIntermTyped *assignedNode); + +[[nodiscard]] bool CanRewriteMultiElementSwizzleAssignmentEasily( + TIntermBinary *multielementSwizzleAssignment, + TIntermNode *parent); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_WGSL_REWRITE_MULTIELEMENTSWIZZLEASSIGNMENT_H_ diff --git a/src/compiler/translator/tree_util/BuiltIn_autogen.h b/src/compiler/translator/tree_util/BuiltIn_autogen.h index 0220c6ec909..efa9b1b8d94 100644 --- a/src/compiler/translator/tree_util/BuiltIn_autogen.h +++ b/src/compiler/translator/tree_util/BuiltIn_autogen.h @@ -593,7 +593,7 @@ class BuiltInId TSymbolUniqueId(544); static constexpr const TSymbolUniqueId textureVideoWEBGL_SamplerVideoWEBGL1_Float2 = TSymbolUniqueId(545); - static constexpr const TSymbolUniqueId pt00p = TSymbolUniqueId(546); + static constexpr const TSymbolUniqueId pt00o = TSymbolUniqueId(546); static constexpr const TSymbolUniqueId texture2D_Sampler2D1_Float2_Float1 = TSymbolUniqueId(547); static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float3_Float1 = @@ -656,9 +656,9 @@ class BuiltInId static constexpr const TSymbolUniqueId texture_SamplerCubeArray1_Float4 = TSymbolUniqueId(589); static constexpr const TSymbolUniqueId pt00g = TSymbolUniqueId(590); static constexpr const TSymbolUniqueId texture_ISamplerCubeArray1_Float4 = TSymbolUniqueId(591); - static constexpr const TSymbolUniqueId pt00l = TSymbolUniqueId(592); + static constexpr const TSymbolUniqueId pt00k = TSymbolUniqueId(592); static constexpr const TSymbolUniqueId texture_USamplerCubeArray1_Float4 = TSymbolUniqueId(593); - static constexpr const TSymbolUniqueId pt00o = TSymbolUniqueId(594); + static constexpr const TSymbolUniqueId pt00n = TSymbolUniqueId(594); static constexpr const TSymbolUniqueId texture_SamplerCubeArrayShadow1_Float4_Float1 = TSymbolUniqueId(595); static constexpr const TSymbolUniqueId pt00h = TSymbolUniqueId(596); @@ -778,9 +778,9 @@ class BuiltInId static constexpr const TSymbolUniqueId textureSize_SamplerBuffer1 = TSymbolUniqueId(667); static constexpr const TSymbolUniqueId pt00f = TSymbolUniqueId(668); static constexpr const TSymbolUniqueId textureSize_ISamplerBuffer1 = TSymbolUniqueId(669); - static constexpr const TSymbolUniqueId pt00k = TSymbolUniqueId(670); + static constexpr const TSymbolUniqueId pt00j = TSymbolUniqueId(670); static constexpr const TSymbolUniqueId textureSize_USamplerBuffer1 = TSymbolUniqueId(671); - static constexpr const TSymbolUniqueId pt00n = TSymbolUniqueId(672); + static constexpr const TSymbolUniqueId pt00m = TSymbolUniqueId(672); static constexpr const TSymbolUniqueId textureSizeExt_SamplerBuffer1 = TSymbolUniqueId(673); static constexpr const TSymbolUniqueId textureSizeExt_ISamplerBuffer1 = TSymbolUniqueId(674); static constexpr const TSymbolUniqueId textureSizeExt_USamplerBuffer1 = TSymbolUniqueId(675); @@ -1194,2547 +1194,1916 @@ class BuiltInId static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2 = TSymbolUniqueId(897); static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2 = TSymbolUniqueId(898); static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2 = TSymbolUniqueId(899); - static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2_Int1 = + static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3 = TSymbolUniqueId(900); - static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2_Int1 = + static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3 = TSymbolUniqueId(901); - static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2_Int1 = + static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3 = TSymbolUniqueId(902); - static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3 = - TSymbolUniqueId(903); - static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3 = + static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3 = TSymbolUniqueId(903); + static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3 = TSymbolUniqueId(904); - static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3 = + static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3 = TSymbolUniqueId(905); - static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3_Int1 = + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4 = TSymbolUniqueId(906); - static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3_Int1 = + static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4 = TSymbolUniqueId(907); - static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3_Int1 = + static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4 = TSymbolUniqueId(908); - static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3 = TSymbolUniqueId(909); - static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3 = + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4 = + TSymbolUniqueId(909); + static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4 = TSymbolUniqueId(910); - static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3 = + static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4 = TSymbolUniqueId(911); - static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3_Int1 = + static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2_Int1 = TSymbolUniqueId(912); - static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3_Int1 = + static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2_Int1 = TSymbolUniqueId(913); - static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3_Int1 = + static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2_Int1 = TSymbolUniqueId(914); - static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4 = + static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3_Int1 = TSymbolUniqueId(915); - static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4 = + static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3_Int1 = TSymbolUniqueId(916); - static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4 = + static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3_Int1 = TSymbolUniqueId(917); - static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4_Int1 = + static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3_Int1 = TSymbolUniqueId(918); - static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4_Int1 = + static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3_Int1 = TSymbolUniqueId(919); - static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4_Int1 = + static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3_Int1 = TSymbolUniqueId(920); - static constexpr const TSymbolUniqueId textureGather_SamplerCubeArrayShadow1_Float4_Float1 = + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4_Int1 = TSymbolUniqueId(921); - static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4 = + static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4_Int1 = TSymbolUniqueId(922); - static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4 = + static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4_Int1 = TSymbolUniqueId(923); - static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4 = - TSymbolUniqueId(924); static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4_Int1 = - TSymbolUniqueId(925); + TSymbolUniqueId(924); static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4_Int1 = - TSymbolUniqueId(926); + TSymbolUniqueId(925); static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(926); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArrayShadow1_Float4_Float1 = TSymbolUniqueId(927); static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArrayShadow1_Float4_Float1 = TSymbolUniqueId(928); - static constexpr const TSymbolUniqueId textureGather_Sampler2DShadow1_Float2 = - TSymbolUniqueId(929); static constexpr const TSymbolUniqueId textureGather_Sampler2DShadow1_Float2_Float1 = - TSymbolUniqueId(930); - static constexpr const TSymbolUniqueId textureGather_Sampler2DArrayShadow1_Float3 = - TSymbolUniqueId(931); + TSymbolUniqueId(929); static constexpr const TSymbolUniqueId textureGather_Sampler2DArrayShadow1_Float3_Float1 = - TSymbolUniqueId(932); - static constexpr const TSymbolUniqueId textureGather_SamplerCubeShadow1_Float3 = - TSymbolUniqueId(933); + TSymbolUniqueId(930); static constexpr const TSymbolUniqueId textureGather_SamplerCubeShadow1_Float3_Float1 = - TSymbolUniqueId(934); + TSymbolUniqueId(931); static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2D1_Float2_Int2 = - TSymbolUniqueId(935); + TSymbolUniqueId(932); static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2D1_Float2_Int2 = - TSymbolUniqueId(936); + TSymbolUniqueId(933); static constexpr const TSymbolUniqueId textureGatherOffset_USampler2D1_Float2_Int2 = - TSymbolUniqueId(937); + TSymbolUniqueId(934); static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DArray1_Float3_Int2 = - TSymbolUniqueId(938); + TSymbolUniqueId(935); static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DArray1_Float3_Int2 = - TSymbolUniqueId(939); + TSymbolUniqueId(936); static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DArray1_Float3_Int2 = - TSymbolUniqueId(940); - static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2 = - TSymbolUniqueId(941); - static constexpr const TSymbolUniqueId - textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2 = TSymbolUniqueId(942); + TSymbolUniqueId(937); static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2D1_Float2_Int2_Int1 = - TSymbolUniqueId(943); + TSymbolUniqueId(938); static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2D1_Float2_Int2_Int1 = - TSymbolUniqueId(944); + TSymbolUniqueId(939); static constexpr const TSymbolUniqueId textureGatherOffset_USampler2D1_Float2_Int2_Int1 = - TSymbolUniqueId(945); + TSymbolUniqueId(940); static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DArray1_Float3_Int2_Int1 = - TSymbolUniqueId(946); + TSymbolUniqueId(941); static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DArray1_Float3_Int2_Int1 = - TSymbolUniqueId(947); + TSymbolUniqueId(942); static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DArray1_Float3_Int2_Int1 = - TSymbolUniqueId(948); + TSymbolUniqueId(943); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2 = + TSymbolUniqueId(944); + static constexpr const TSymbolUniqueId + textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2 = TSymbolUniqueId(945); static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2D1_Float2_4xInt2 = - TSymbolUniqueId(949); - static constexpr const TSymbolUniqueId pt10Cx4 = TSymbolUniqueId(950); + TSymbolUniqueId(946); + static constexpr const TSymbolUniqueId pt10Cx4 = TSymbolUniqueId(947); static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2D1_Float2_4xInt2 = - TSymbolUniqueId(951); + TSymbolUniqueId(948); static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2D1_Float2_4xInt2 = - TSymbolUniqueId(952); + TSymbolUniqueId(949); static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DArray1_Float3_4xInt2 = - TSymbolUniqueId(953); + TSymbolUniqueId(950); static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2DArray1_Float3_4xInt2 = - TSymbolUniqueId(954); + TSymbolUniqueId(951); static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2DArray1_Float3_4xInt2 = - TSymbolUniqueId(955); - static constexpr const TSymbolUniqueId - textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(956); - static constexpr const TSymbolUniqueId - textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(957); + TSymbolUniqueId(952); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2 = - TSymbolUniqueId(958); + TSymbolUniqueId(953); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2 = - TSymbolUniqueId(959); + TSymbolUniqueId(954); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2D1_Float2_4xInt2 = - TSymbolUniqueId(960); + TSymbolUniqueId(955); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2 = - TSymbolUniqueId(961); + TSymbolUniqueId(956); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2 = - TSymbolUniqueId(962); + TSymbolUniqueId(957); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2 = - TSymbolUniqueId(963); - static constexpr const TSymbolUniqueId - textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(964); - static constexpr const TSymbolUniqueId - textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(965); + TSymbolUniqueId(958); static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2D1_Float2_4xInt2_Int1 = - TSymbolUniqueId(966); + TSymbolUniqueId(959); static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2D1_Float2_4xInt2_Int1 = - TSymbolUniqueId(967); + TSymbolUniqueId(960); static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2D1_Float2_4xInt2_Int1 = - TSymbolUniqueId(968); + TSymbolUniqueId(961); static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DArray1_Float3_4xInt2_Int1 = - TSymbolUniqueId(969); + TSymbolUniqueId(962); static constexpr const TSymbolUniqueId - textureGatherOffsets_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(970); + textureGatherOffsets_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(963); static constexpr const TSymbolUniqueId - textureGatherOffsets_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(971); + textureGatherOffsets_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(964); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2_Int1 = - TSymbolUniqueId(972); + TSymbolUniqueId(965); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2_Int1 = - TSymbolUniqueId(973); + TSymbolUniqueId(966); static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2D1_Float2_4xInt2_Int1 = - TSymbolUniqueId(974); + TSymbolUniqueId(967); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(968); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(969); static constexpr const TSymbolUniqueId - textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(975); + textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(970); static constexpr const TSymbolUniqueId - textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(976); + textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(971); static constexpr const TSymbolUniqueId - textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(977); - static constexpr const TSymbolUniqueId textureQueryLOD_Sampler2D1_Float2 = TSymbolUniqueId(978); + textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(972); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(973); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(974); + static constexpr const TSymbolUniqueId textureQueryLOD_Sampler2D1_Float2 = TSymbolUniqueId(975); static constexpr const TSymbolUniqueId textureQueryLOD_ISampler2D1_Float2 = - TSymbolUniqueId(979); + TSymbolUniqueId(976); static constexpr const TSymbolUniqueId textureQueryLOD_USampler2D1_Float2 = - TSymbolUniqueId(980); - static constexpr const TSymbolUniqueId textureQueryLOD_Sampler3D1_Float3 = TSymbolUniqueId(981); + TSymbolUniqueId(977); + static constexpr const TSymbolUniqueId textureQueryLOD_Sampler3D1_Float3 = TSymbolUniqueId(978); static constexpr const TSymbolUniqueId textureQueryLOD_ISampler3D1_Float3 = - TSymbolUniqueId(982); + TSymbolUniqueId(979); static constexpr const TSymbolUniqueId textureQueryLOD_USampler3D1_Float3 = - TSymbolUniqueId(983); + TSymbolUniqueId(980); static constexpr const TSymbolUniqueId textureQueryLOD_SamplerCube1_Float3 = - TSymbolUniqueId(984); + TSymbolUniqueId(981); static constexpr const TSymbolUniqueId textureQueryLOD_ISamplerCube1_Float3 = - TSymbolUniqueId(985); + TSymbolUniqueId(982); static constexpr const TSymbolUniqueId textureQueryLOD_USamplerCube1_Float3 = - TSymbolUniqueId(986); + TSymbolUniqueId(983); static constexpr const TSymbolUniqueId textureQueryLOD_Sampler2DArray1_Float2 = - TSymbolUniqueId(987); + TSymbolUniqueId(984); static constexpr const TSymbolUniqueId textureQueryLOD_ISampler2DArray1_Float2 = - TSymbolUniqueId(988); + TSymbolUniqueId(985); static constexpr const TSymbolUniqueId textureQueryLOD_USampler2DArray1_Float2 = - TSymbolUniqueId(989); + TSymbolUniqueId(986); static constexpr const TSymbolUniqueId textureQueryLOD_Sampler2DShadow1_Float2 = - TSymbolUniqueId(990); + TSymbolUniqueId(987); static constexpr const TSymbolUniqueId textureQueryLOD_SamplerCubeShadow1_Float3 = - TSymbolUniqueId(991); + TSymbolUniqueId(988); static constexpr const TSymbolUniqueId textureQueryLOD_Sampler2DArrayShadow1_Float2 = - TSymbolUniqueId(992); + TSymbolUniqueId(989); static constexpr const TSymbolUniqueId textureQueryLOD_SamplerCubeArray1_Float3 = - TSymbolUniqueId(993); + TSymbolUniqueId(990); static constexpr const TSymbolUniqueId textureQueryLOD_ISamplerCubeArray1_Float3 = - TSymbolUniqueId(994); + TSymbolUniqueId(991); static constexpr const TSymbolUniqueId textureQueryLOD_USamplerCubeArray1_Float3 = - TSymbolUniqueId(995); + TSymbolUniqueId(992); static constexpr const TSymbolUniqueId textureQueryLOD_SamplerCubeArrayShadow1_Float3 = - TSymbolUniqueId(996); + TSymbolUniqueId(993); static constexpr const TSymbolUniqueId rgb_2_yuv_Float3_YuvCscStandardEXT1 = - TSymbolUniqueId(997); - static constexpr const TSymbolUniqueId pt00G = TSymbolUniqueId(998); + TSymbolUniqueId(994); + static constexpr const TSymbolUniqueId pt00G = TSymbolUniqueId(995); static constexpr const TSymbolUniqueId yuv_2_rgb_Float3_YuvCscStandardEXT1 = - TSymbolUniqueId(999); - static constexpr const TSymbolUniqueId dFdxExt_Float1 = TSymbolUniqueId(1000); - static constexpr const TSymbolUniqueId dFdxExt_Float2 = TSymbolUniqueId(1001); - static constexpr const TSymbolUniqueId dFdxExt_Float3 = TSymbolUniqueId(1002); - static constexpr const TSymbolUniqueId dFdxExt_Float4 = TSymbolUniqueId(1003); - static constexpr const TSymbolUniqueId dFdyExt_Float1 = TSymbolUniqueId(1004); - static constexpr const TSymbolUniqueId dFdyExt_Float2 = TSymbolUniqueId(1005); - static constexpr const TSymbolUniqueId dFdyExt_Float3 = TSymbolUniqueId(1006); - static constexpr const TSymbolUniqueId dFdyExt_Float4 = TSymbolUniqueId(1007); - static constexpr const TSymbolUniqueId fwidthExt_Float1 = TSymbolUniqueId(1008); - static constexpr const TSymbolUniqueId fwidthExt_Float2 = TSymbolUniqueId(1009); - static constexpr const TSymbolUniqueId fwidthExt_Float3 = TSymbolUniqueId(1010); - static constexpr const TSymbolUniqueId fwidthExt_Float4 = TSymbolUniqueId(1011); - static constexpr const TSymbolUniqueId dFdx_Float1 = TSymbolUniqueId(1012); - static constexpr const TSymbolUniqueId dFdx_Float2 = TSymbolUniqueId(1013); - static constexpr const TSymbolUniqueId dFdx_Float3 = TSymbolUniqueId(1014); - static constexpr const TSymbolUniqueId dFdx_Float4 = TSymbolUniqueId(1015); - static constexpr const TSymbolUniqueId dFdy_Float1 = TSymbolUniqueId(1016); - static constexpr const TSymbolUniqueId dFdy_Float2 = TSymbolUniqueId(1017); - static constexpr const TSymbolUniqueId dFdy_Float3 = TSymbolUniqueId(1018); - static constexpr const TSymbolUniqueId dFdy_Float4 = TSymbolUniqueId(1019); - static constexpr const TSymbolUniqueId fwidth_Float1 = TSymbolUniqueId(1020); - static constexpr const TSymbolUniqueId fwidth_Float2 = TSymbolUniqueId(1021); - static constexpr const TSymbolUniqueId fwidth_Float3 = TSymbolUniqueId(1022); - static constexpr const TSymbolUniqueId fwidth_Float4 = TSymbolUniqueId(1023); - static constexpr const TSymbolUniqueId interpolateAtCentroid_Float1 = TSymbolUniqueId(1024); - static constexpr const TSymbolUniqueId interpolateAtCentroid_Float2 = TSymbolUniqueId(1025); - static constexpr const TSymbolUniqueId interpolateAtCentroid_Float3 = TSymbolUniqueId(1026); - static constexpr const TSymbolUniqueId interpolateAtCentroid_Float4 = TSymbolUniqueId(1027); - static constexpr const TSymbolUniqueId interpolateAtSample_Float1_Int1 = TSymbolUniqueId(1028); - static constexpr const TSymbolUniqueId interpolateAtSample_Float2_Int1 = TSymbolUniqueId(1029); - static constexpr const TSymbolUniqueId interpolateAtSample_Float3_Int1 = TSymbolUniqueId(1030); - static constexpr const TSymbolUniqueId interpolateAtSample_Float4_Int1 = TSymbolUniqueId(1031); + TSymbolUniqueId(996); + static constexpr const TSymbolUniqueId dFdxExt_Float1 = TSymbolUniqueId(997); + static constexpr const TSymbolUniqueId dFdxExt_Float2 = TSymbolUniqueId(998); + static constexpr const TSymbolUniqueId dFdxExt_Float3 = TSymbolUniqueId(999); + static constexpr const TSymbolUniqueId dFdxExt_Float4 = TSymbolUniqueId(1000); + static constexpr const TSymbolUniqueId dFdyExt_Float1 = TSymbolUniqueId(1001); + static constexpr const TSymbolUniqueId dFdyExt_Float2 = TSymbolUniqueId(1002); + static constexpr const TSymbolUniqueId dFdyExt_Float3 = TSymbolUniqueId(1003); + static constexpr const TSymbolUniqueId dFdyExt_Float4 = TSymbolUniqueId(1004); + static constexpr const TSymbolUniqueId fwidthExt_Float1 = TSymbolUniqueId(1005); + static constexpr const TSymbolUniqueId fwidthExt_Float2 = TSymbolUniqueId(1006); + static constexpr const TSymbolUniqueId fwidthExt_Float3 = TSymbolUniqueId(1007); + static constexpr const TSymbolUniqueId fwidthExt_Float4 = TSymbolUniqueId(1008); + static constexpr const TSymbolUniqueId dFdx_Float1 = TSymbolUniqueId(1009); + static constexpr const TSymbolUniqueId dFdx_Float2 = TSymbolUniqueId(1010); + static constexpr const TSymbolUniqueId dFdx_Float3 = TSymbolUniqueId(1011); + static constexpr const TSymbolUniqueId dFdx_Float4 = TSymbolUniqueId(1012); + static constexpr const TSymbolUniqueId dFdy_Float1 = TSymbolUniqueId(1013); + static constexpr const TSymbolUniqueId dFdy_Float2 = TSymbolUniqueId(1014); + static constexpr const TSymbolUniqueId dFdy_Float3 = TSymbolUniqueId(1015); + static constexpr const TSymbolUniqueId dFdy_Float4 = TSymbolUniqueId(1016); + static constexpr const TSymbolUniqueId fwidth_Float1 = TSymbolUniqueId(1017); + static constexpr const TSymbolUniqueId fwidth_Float2 = TSymbolUniqueId(1018); + static constexpr const TSymbolUniqueId fwidth_Float3 = TSymbolUniqueId(1019); + static constexpr const TSymbolUniqueId fwidth_Float4 = TSymbolUniqueId(1020); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float1 = TSymbolUniqueId(1021); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float2 = TSymbolUniqueId(1022); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float3 = TSymbolUniqueId(1023); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float4 = TSymbolUniqueId(1024); + static constexpr const TSymbolUniqueId interpolateAtSample_Float1_Int1 = TSymbolUniqueId(1025); + static constexpr const TSymbolUniqueId interpolateAtSample_Float2_Int1 = TSymbolUniqueId(1026); + static constexpr const TSymbolUniqueId interpolateAtSample_Float3_Int1 = TSymbolUniqueId(1027); + static constexpr const TSymbolUniqueId interpolateAtSample_Float4_Int1 = TSymbolUniqueId(1028); static constexpr const TSymbolUniqueId interpolateAtOffset_Float1_Float2 = - TSymbolUniqueId(1032); + TSymbolUniqueId(1029); static constexpr const TSymbolUniqueId interpolateAtOffset_Float2_Float2 = - TSymbolUniqueId(1033); + TSymbolUniqueId(1030); static constexpr const TSymbolUniqueId interpolateAtOffset_Float3_Float2 = - TSymbolUniqueId(1034); + TSymbolUniqueId(1031); static constexpr const TSymbolUniqueId interpolateAtOffset_Float4_Float2 = - TSymbolUniqueId(1035); - static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float1 = TSymbolUniqueId(1036); - static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float2 = TSymbolUniqueId(1037); - static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float3 = TSymbolUniqueId(1038); - static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float4 = TSymbolUniqueId(1039); + TSymbolUniqueId(1032); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float1 = TSymbolUniqueId(1033); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float2 = TSymbolUniqueId(1034); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float3 = TSymbolUniqueId(1035); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float4 = TSymbolUniqueId(1036); static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float1_Int1 = - TSymbolUniqueId(1040); + TSymbolUniqueId(1037); static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float2_Int1 = - TSymbolUniqueId(1041); + TSymbolUniqueId(1038); static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float3_Int1 = - TSymbolUniqueId(1042); + TSymbolUniqueId(1039); static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float4_Int1 = - TSymbolUniqueId(1043); + TSymbolUniqueId(1040); static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float1_Float2 = - TSymbolUniqueId(1044); + TSymbolUniqueId(1041); static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float2_Float2 = - TSymbolUniqueId(1045); + TSymbolUniqueId(1042); static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float3_Float2 = - TSymbolUniqueId(1046); + TSymbolUniqueId(1043); static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float4_Float2 = - TSymbolUniqueId(1047); - static constexpr const TSymbolUniqueId atomicCounter_AtomicCounter1 = TSymbolUniqueId(1048); - static constexpr const TSymbolUniqueId pt00F = TSymbolUniqueId(1049); + TSymbolUniqueId(1044); + static constexpr const TSymbolUniqueId atomicCounter_AtomicCounter1 = TSymbolUniqueId(1045); + static constexpr const TSymbolUniqueId pt00F = TSymbolUniqueId(1046); static constexpr const TSymbolUniqueId atomicCounterIncrement_AtomicCounter1 = - TSymbolUniqueId(1050); + TSymbolUniqueId(1047); static constexpr const TSymbolUniqueId atomicCounterDecrement_AtomicCounter1 = - TSymbolUniqueId(1051); - static constexpr const TSymbolUniqueId atomicAdd_UInt1_UInt1 = TSymbolUniqueId(1052); - static constexpr const TSymbolUniqueId pt_io_00D = TSymbolUniqueId(1053); - static constexpr const TSymbolUniqueId atomicAdd_Int1_Int1 = TSymbolUniqueId(1054); - static constexpr const TSymbolUniqueId pt_io_00C = TSymbolUniqueId(1055); - static constexpr const TSymbolUniqueId atomicMin_UInt1_UInt1 = TSymbolUniqueId(1056); - static constexpr const TSymbolUniqueId atomicMin_Int1_Int1 = TSymbolUniqueId(1057); - static constexpr const TSymbolUniqueId atomicMax_UInt1_UInt1 = TSymbolUniqueId(1058); - static constexpr const TSymbolUniqueId atomicMax_Int1_Int1 = TSymbolUniqueId(1059); - static constexpr const TSymbolUniqueId atomicAnd_UInt1_UInt1 = TSymbolUniqueId(1060); - static constexpr const TSymbolUniqueId atomicAnd_Int1_Int1 = TSymbolUniqueId(1061); - static constexpr const TSymbolUniqueId atomicOr_UInt1_UInt1 = TSymbolUniqueId(1062); - static constexpr const TSymbolUniqueId atomicOr_Int1_Int1 = TSymbolUniqueId(1063); - static constexpr const TSymbolUniqueId atomicXor_UInt1_UInt1 = TSymbolUniqueId(1064); - static constexpr const TSymbolUniqueId atomicXor_Int1_Int1 = TSymbolUniqueId(1065); - static constexpr const TSymbolUniqueId atomicExchange_UInt1_UInt1 = TSymbolUniqueId(1066); - static constexpr const TSymbolUniqueId atomicExchange_Int1_Int1 = TSymbolUniqueId(1067); - static constexpr const TSymbolUniqueId atomicCompSwap_UInt1_UInt1_UInt1 = TSymbolUniqueId(1068); - static constexpr const TSymbolUniqueId atomicCompSwap_Int1_Int1_Int1 = TSymbolUniqueId(1069); - static constexpr const TSymbolUniqueId imageSize_Image2D1 = TSymbolUniqueId(1070); - static constexpr const TSymbolUniqueId pt00q = TSymbolUniqueId(1071); - static constexpr const TSymbolUniqueId imageSize_IImage2D1 = TSymbolUniqueId(1072); - static constexpr const TSymbolUniqueId pt00z = TSymbolUniqueId(1073); - static constexpr const TSymbolUniqueId imageSize_UImage2D1 = TSymbolUniqueId(1074); - static constexpr const TSymbolUniqueId pt01I = TSymbolUniqueId(1075); - static constexpr const TSymbolUniqueId imageSize_Image3D1 = TSymbolUniqueId(1076); - static constexpr const TSymbolUniqueId pt00r = TSymbolUniqueId(1077); - static constexpr const TSymbolUniqueId imageSize_IImage3D1 = TSymbolUniqueId(1078); - static constexpr const TSymbolUniqueId pt01A = TSymbolUniqueId(1079); - static constexpr const TSymbolUniqueId imageSize_UImage3D1 = TSymbolUniqueId(1080); - static constexpr const TSymbolUniqueId pt01J = TSymbolUniqueId(1081); - static constexpr const TSymbolUniqueId imageSize_Image2DArray1 = TSymbolUniqueId(1082); - static constexpr const TSymbolUniqueId pt00s = TSymbolUniqueId(1083); - static constexpr const TSymbolUniqueId imageSize_IImage2DArray1 = TSymbolUniqueId(1084); - static constexpr const TSymbolUniqueId pt01B = TSymbolUniqueId(1085); - static constexpr const TSymbolUniqueId imageSize_UImage2DArray1 = TSymbolUniqueId(1086); - static constexpr const TSymbolUniqueId pt01K = TSymbolUniqueId(1087); - static constexpr const TSymbolUniqueId imageSize_ImageCube1 = TSymbolUniqueId(1088); - static constexpr const TSymbolUniqueId pt00t = TSymbolUniqueId(1089); - static constexpr const TSymbolUniqueId imageSize_IImageCube1 = TSymbolUniqueId(1090); - static constexpr const TSymbolUniqueId pt01C = TSymbolUniqueId(1091); - static constexpr const TSymbolUniqueId imageSize_UImageCube1 = TSymbolUniqueId(1092); - static constexpr const TSymbolUniqueId pt01L = TSymbolUniqueId(1093); - static constexpr const TSymbolUniqueId imageSize_ImageCubeArray1 = TSymbolUniqueId(1094); - static constexpr const TSymbolUniqueId pt00w = TSymbolUniqueId(1095); - static constexpr const TSymbolUniqueId imageSize_IImageCubeArray1 = TSymbolUniqueId(1096); - static constexpr const TSymbolUniqueId pt01F = TSymbolUniqueId(1097); - static constexpr const TSymbolUniqueId imageSize_UImageCubeArray1 = TSymbolUniqueId(1098); - static constexpr const TSymbolUniqueId pt01O = TSymbolUniqueId(1099); - static constexpr const TSymbolUniqueId imageSizeExt_ImageCubeArray1 = TSymbolUniqueId(1100); - static constexpr const TSymbolUniqueId imageSizeExt_IImageCubeArray1 = TSymbolUniqueId(1101); - static constexpr const TSymbolUniqueId imageSizeExt_UImageCubeArray1 = TSymbolUniqueId(1102); - static constexpr const TSymbolUniqueId imageSize_ImageBuffer1 = TSymbolUniqueId(1103); - static constexpr const TSymbolUniqueId pt00y = TSymbolUniqueId(1104); - static constexpr const TSymbolUniqueId imageSize_IImageBuffer1 = TSymbolUniqueId(1105); - static constexpr const TSymbolUniqueId pt01H = TSymbolUniqueId(1106); - static constexpr const TSymbolUniqueId imageSize_UImageBuffer1 = TSymbolUniqueId(1107); - static constexpr const TSymbolUniqueId pt01Q = TSymbolUniqueId(1108); - static constexpr const TSymbolUniqueId imageSizeExt_ImageBuffer1 = TSymbolUniqueId(1109); - static constexpr const TSymbolUniqueId imageSizeExt_IImageBuffer1 = TSymbolUniqueId(1110); - static constexpr const TSymbolUniqueId imageSizeExt_UImageBuffer1 = TSymbolUniqueId(1111); - static constexpr const TSymbolUniqueId imageStore_Image2D1_Int2_Float4 = TSymbolUniqueId(1112); - static constexpr const TSymbolUniqueId imageStore_IImage2D1_Int2_Int4 = TSymbolUniqueId(1113); - static constexpr const TSymbolUniqueId imageStore_UImage2D1_Int2_UInt4 = TSymbolUniqueId(1114); - static constexpr const TSymbolUniqueId imageStore_Image3D1_Int3_Float4 = TSymbolUniqueId(1115); - static constexpr const TSymbolUniqueId imageStore_IImage3D1_Int3_Int4 = TSymbolUniqueId(1116); - static constexpr const TSymbolUniqueId imageStore_UImage3D1_Int3_UInt4 = TSymbolUniqueId(1117); + TSymbolUniqueId(1048); + static constexpr const TSymbolUniqueId atomicAdd_UInt1_UInt1 = TSymbolUniqueId(1049); + static constexpr const TSymbolUniqueId pt_io_00D = TSymbolUniqueId(1050); + static constexpr const TSymbolUniqueId atomicAdd_Int1_Int1 = TSymbolUniqueId(1051); + static constexpr const TSymbolUniqueId pt_io_00C = TSymbolUniqueId(1052); + static constexpr const TSymbolUniqueId atomicMin_UInt1_UInt1 = TSymbolUniqueId(1053); + static constexpr const TSymbolUniqueId atomicMin_Int1_Int1 = TSymbolUniqueId(1054); + static constexpr const TSymbolUniqueId atomicMax_UInt1_UInt1 = TSymbolUniqueId(1055); + static constexpr const TSymbolUniqueId atomicMax_Int1_Int1 = TSymbolUniqueId(1056); + static constexpr const TSymbolUniqueId atomicAnd_UInt1_UInt1 = TSymbolUniqueId(1057); + static constexpr const TSymbolUniqueId atomicAnd_Int1_Int1 = TSymbolUniqueId(1058); + static constexpr const TSymbolUniqueId atomicOr_UInt1_UInt1 = TSymbolUniqueId(1059); + static constexpr const TSymbolUniqueId atomicOr_Int1_Int1 = TSymbolUniqueId(1060); + static constexpr const TSymbolUniqueId atomicXor_UInt1_UInt1 = TSymbolUniqueId(1061); + static constexpr const TSymbolUniqueId atomicXor_Int1_Int1 = TSymbolUniqueId(1062); + static constexpr const TSymbolUniqueId atomicExchange_UInt1_UInt1 = TSymbolUniqueId(1063); + static constexpr const TSymbolUniqueId atomicExchange_Int1_Int1 = TSymbolUniqueId(1064); + static constexpr const TSymbolUniqueId atomicCompSwap_UInt1_UInt1_UInt1 = TSymbolUniqueId(1065); + static constexpr const TSymbolUniqueId atomicCompSwap_Int1_Int1_Int1 = TSymbolUniqueId(1066); + static constexpr const TSymbolUniqueId imageSize_Image2D1 = TSymbolUniqueId(1067); + static constexpr const TSymbolUniqueId pt00p = TSymbolUniqueId(1068); + static constexpr const TSymbolUniqueId imageSize_IImage2D1 = TSymbolUniqueId(1069); + static constexpr const TSymbolUniqueId pt00v = TSymbolUniqueId(1070); + static constexpr const TSymbolUniqueId imageSize_UImage2D1 = TSymbolUniqueId(1071); + static constexpr const TSymbolUniqueId pt01B = TSymbolUniqueId(1072); + static constexpr const TSymbolUniqueId imageSize_Image3D1 = TSymbolUniqueId(1073); + static constexpr const TSymbolUniqueId pt00q = TSymbolUniqueId(1074); + static constexpr const TSymbolUniqueId imageSize_IImage3D1 = TSymbolUniqueId(1075); + static constexpr const TSymbolUniqueId pt00w = TSymbolUniqueId(1076); + static constexpr const TSymbolUniqueId imageSize_UImage3D1 = TSymbolUniqueId(1077); + static constexpr const TSymbolUniqueId pt01C = TSymbolUniqueId(1078); + static constexpr const TSymbolUniqueId imageSize_Image2DArray1 = TSymbolUniqueId(1079); + static constexpr const TSymbolUniqueId pt00r = TSymbolUniqueId(1080); + static constexpr const TSymbolUniqueId imageSize_IImage2DArray1 = TSymbolUniqueId(1081); + static constexpr const TSymbolUniqueId pt00x = TSymbolUniqueId(1082); + static constexpr const TSymbolUniqueId imageSize_UImage2DArray1 = TSymbolUniqueId(1083); + static constexpr const TSymbolUniqueId pt01D = TSymbolUniqueId(1084); + static constexpr const TSymbolUniqueId imageSize_ImageCube1 = TSymbolUniqueId(1085); + static constexpr const TSymbolUniqueId pt00s = TSymbolUniqueId(1086); + static constexpr const TSymbolUniqueId imageSize_IImageCube1 = TSymbolUniqueId(1087); + static constexpr const TSymbolUniqueId pt00y = TSymbolUniqueId(1088); + static constexpr const TSymbolUniqueId imageSize_UImageCube1 = TSymbolUniqueId(1089); + static constexpr const TSymbolUniqueId pt01E = TSymbolUniqueId(1090); + static constexpr const TSymbolUniqueId imageSize_ImageCubeArray1 = TSymbolUniqueId(1091); + static constexpr const TSymbolUniqueId pt00t = TSymbolUniqueId(1092); + static constexpr const TSymbolUniqueId imageSize_IImageCubeArray1 = TSymbolUniqueId(1093); + static constexpr const TSymbolUniqueId pt00z = TSymbolUniqueId(1094); + static constexpr const TSymbolUniqueId imageSize_UImageCubeArray1 = TSymbolUniqueId(1095); + static constexpr const TSymbolUniqueId pt01F = TSymbolUniqueId(1096); + static constexpr const TSymbolUniqueId imageSizeExt_ImageCubeArray1 = TSymbolUniqueId(1097); + static constexpr const TSymbolUniqueId imageSizeExt_IImageCubeArray1 = TSymbolUniqueId(1098); + static constexpr const TSymbolUniqueId imageSizeExt_UImageCubeArray1 = TSymbolUniqueId(1099); + static constexpr const TSymbolUniqueId imageSize_ImageBuffer1 = TSymbolUniqueId(1100); + static constexpr const TSymbolUniqueId pt00u = TSymbolUniqueId(1101); + static constexpr const TSymbolUniqueId imageSize_IImageBuffer1 = TSymbolUniqueId(1102); + static constexpr const TSymbolUniqueId pt01A = TSymbolUniqueId(1103); + static constexpr const TSymbolUniqueId imageSize_UImageBuffer1 = TSymbolUniqueId(1104); + static constexpr const TSymbolUniqueId pt01G = TSymbolUniqueId(1105); + static constexpr const TSymbolUniqueId imageSizeExt_ImageBuffer1 = TSymbolUniqueId(1106); + static constexpr const TSymbolUniqueId imageSizeExt_IImageBuffer1 = TSymbolUniqueId(1107); + static constexpr const TSymbolUniqueId imageSizeExt_UImageBuffer1 = TSymbolUniqueId(1108); + static constexpr const TSymbolUniqueId imageStore_Image2D1_Int2_Float4 = TSymbolUniqueId(1109); + static constexpr const TSymbolUniqueId imageStore_IImage2D1_Int2_Int4 = TSymbolUniqueId(1110); + static constexpr const TSymbolUniqueId imageStore_UImage2D1_Int2_UInt4 = TSymbolUniqueId(1111); + static constexpr const TSymbolUniqueId imageStore_Image3D1_Int3_Float4 = TSymbolUniqueId(1112); + static constexpr const TSymbolUniqueId imageStore_IImage3D1_Int3_Int4 = TSymbolUniqueId(1113); + static constexpr const TSymbolUniqueId imageStore_UImage3D1_Int3_UInt4 = TSymbolUniqueId(1114); static constexpr const TSymbolUniqueId imageStore_Image2DArray1_Int3_Float4 = - TSymbolUniqueId(1118); + TSymbolUniqueId(1115); static constexpr const TSymbolUniqueId imageStore_IImage2DArray1_Int3_Int4 = - TSymbolUniqueId(1119); + TSymbolUniqueId(1116); static constexpr const TSymbolUniqueId imageStore_UImage2DArray1_Int3_UInt4 = - TSymbolUniqueId(1120); + TSymbolUniqueId(1117); static constexpr const TSymbolUniqueId imageStore_ImageCube1_Int3_Float4 = - TSymbolUniqueId(1121); - static constexpr const TSymbolUniqueId imageStore_IImageCube1_Int3_Int4 = TSymbolUniqueId(1122); + TSymbolUniqueId(1118); + static constexpr const TSymbolUniqueId imageStore_IImageCube1_Int3_Int4 = TSymbolUniqueId(1119); static constexpr const TSymbolUniqueId imageStore_UImageCube1_Int3_UInt4 = - TSymbolUniqueId(1123); + TSymbolUniqueId(1120); static constexpr const TSymbolUniqueId imageStore_ImageCubeArray1_Int3_Float4 = - TSymbolUniqueId(1124); + TSymbolUniqueId(1121); static constexpr const TSymbolUniqueId imageStore_IImageCubeArray1_Int3_Int4 = - TSymbolUniqueId(1125); + TSymbolUniqueId(1122); static constexpr const TSymbolUniqueId imageStore_UImageCubeArray1_Int3_UInt4 = - TSymbolUniqueId(1126); + TSymbolUniqueId(1123); static constexpr const TSymbolUniqueId imageStoreExt_ImageCubeArray1_Int3_Float4 = - TSymbolUniqueId(1127); + TSymbolUniqueId(1124); static constexpr const TSymbolUniqueId imageStoreExt_IImageCubeArray1_Int3_Int4 = - TSymbolUniqueId(1128); + TSymbolUniqueId(1125); static constexpr const TSymbolUniqueId imageStoreExt_UImageCubeArray1_Int3_UInt4 = - TSymbolUniqueId(1129); + TSymbolUniqueId(1126); static constexpr const TSymbolUniqueId imageStore_ImageBuffer1_Int1_Float4 = - TSymbolUniqueId(1130); + TSymbolUniqueId(1127); static constexpr const TSymbolUniqueId imageStore_IImageBuffer1_Int1_Int4 = - TSymbolUniqueId(1131); + TSymbolUniqueId(1128); static constexpr const TSymbolUniqueId imageStore_UImageBuffer1_Int1_UInt4 = - TSymbolUniqueId(1132); + TSymbolUniqueId(1129); static constexpr const TSymbolUniqueId imageStoreExt_ImageBuffer1_Int1_Float4 = - TSymbolUniqueId(1133); + TSymbolUniqueId(1130); static constexpr const TSymbolUniqueId imageStoreExt_IImageBuffer1_Int1_Int4 = - TSymbolUniqueId(1134); + TSymbolUniqueId(1131); static constexpr const TSymbolUniqueId imageStoreExt_UImageBuffer1_Int1_UInt4 = - TSymbolUniqueId(1135); - static constexpr const TSymbolUniqueId imageLoad_Image2D1_Int2 = TSymbolUniqueId(1136); - static constexpr const TSymbolUniqueId imageLoad_IImage2D1_Int2 = TSymbolUniqueId(1137); - static constexpr const TSymbolUniqueId imageLoad_UImage2D1_Int2 = TSymbolUniqueId(1138); - static constexpr const TSymbolUniqueId imageLoad_Image3D1_Int3 = TSymbolUniqueId(1139); - static constexpr const TSymbolUniqueId imageLoad_IImage3D1_Int3 = TSymbolUniqueId(1140); - static constexpr const TSymbolUniqueId imageLoad_UImage3D1_Int3 = TSymbolUniqueId(1141); - static constexpr const TSymbolUniqueId imageLoad_Image2DArray1_Int3 = TSymbolUniqueId(1142); - static constexpr const TSymbolUniqueId imageLoad_IImage2DArray1_Int3 = TSymbolUniqueId(1143); - static constexpr const TSymbolUniqueId imageLoad_UImage2DArray1_Int3 = TSymbolUniqueId(1144); - static constexpr const TSymbolUniqueId imageLoad_ImageCube1_Int3 = TSymbolUniqueId(1145); - static constexpr const TSymbolUniqueId imageLoad_IImageCube1_Int3 = TSymbolUniqueId(1146); - static constexpr const TSymbolUniqueId imageLoad_UImageCube1_Int3 = TSymbolUniqueId(1147); - static constexpr const TSymbolUniqueId imageLoad_ImageCubeArray1_Int3 = TSymbolUniqueId(1148); - static constexpr const TSymbolUniqueId imageLoad_IImageCubeArray1_Int3 = TSymbolUniqueId(1149); - static constexpr const TSymbolUniqueId imageLoad_UImageCubeArray1_Int3 = TSymbolUniqueId(1150); + TSymbolUniqueId(1132); + static constexpr const TSymbolUniqueId imageLoad_Image2D1_Int2 = TSymbolUniqueId(1133); + static constexpr const TSymbolUniqueId imageLoad_IImage2D1_Int2 = TSymbolUniqueId(1134); + static constexpr const TSymbolUniqueId imageLoad_UImage2D1_Int2 = TSymbolUniqueId(1135); + static constexpr const TSymbolUniqueId imageLoad_Image3D1_Int3 = TSymbolUniqueId(1136); + static constexpr const TSymbolUniqueId imageLoad_IImage3D1_Int3 = TSymbolUniqueId(1137); + static constexpr const TSymbolUniqueId imageLoad_UImage3D1_Int3 = TSymbolUniqueId(1138); + static constexpr const TSymbolUniqueId imageLoad_Image2DArray1_Int3 = TSymbolUniqueId(1139); + static constexpr const TSymbolUniqueId imageLoad_IImage2DArray1_Int3 = TSymbolUniqueId(1140); + static constexpr const TSymbolUniqueId imageLoad_UImage2DArray1_Int3 = TSymbolUniqueId(1141); + static constexpr const TSymbolUniqueId imageLoad_ImageCube1_Int3 = TSymbolUniqueId(1142); + static constexpr const TSymbolUniqueId imageLoad_IImageCube1_Int3 = TSymbolUniqueId(1143); + static constexpr const TSymbolUniqueId imageLoad_UImageCube1_Int3 = TSymbolUniqueId(1144); + static constexpr const TSymbolUniqueId imageLoad_ImageCubeArray1_Int3 = TSymbolUniqueId(1145); + static constexpr const TSymbolUniqueId imageLoad_IImageCubeArray1_Int3 = TSymbolUniqueId(1146); + static constexpr const TSymbolUniqueId imageLoad_UImageCubeArray1_Int3 = TSymbolUniqueId(1147); static constexpr const TSymbolUniqueId imageLoadExt_ImageCubeArray1_Int3 = - TSymbolUniqueId(1151); + TSymbolUniqueId(1148); static constexpr const TSymbolUniqueId imageLoadExt_IImageCubeArray1_Int3 = - TSymbolUniqueId(1152); + TSymbolUniqueId(1149); static constexpr const TSymbolUniqueId imageLoadExt_UImageCubeArray1_Int3 = - TSymbolUniqueId(1153); - static constexpr const TSymbolUniqueId imageLoad_ImageBuffer1_Int1 = TSymbolUniqueId(1154); - static constexpr const TSymbolUniqueId imageLoad_IImageBuffer1_Int1 = TSymbolUniqueId(1155); - static constexpr const TSymbolUniqueId imageLoad_UImageBuffer1_Int1 = TSymbolUniqueId(1156); - static constexpr const TSymbolUniqueId imageLoadExt_ImageBuffer1_Int1 = TSymbolUniqueId(1157); - static constexpr const TSymbolUniqueId imageLoadExt_IImageBuffer1_Int1 = TSymbolUniqueId(1158); - static constexpr const TSymbolUniqueId imageLoadExt_UImageBuffer1_Int1 = TSymbolUniqueId(1159); + TSymbolUniqueId(1150); + static constexpr const TSymbolUniqueId imageLoad_ImageBuffer1_Int1 = TSymbolUniqueId(1151); + static constexpr const TSymbolUniqueId imageLoad_IImageBuffer1_Int1 = TSymbolUniqueId(1152); + static constexpr const TSymbolUniqueId imageLoad_UImageBuffer1_Int1 = TSymbolUniqueId(1153); + static constexpr const TSymbolUniqueId imageLoadExt_ImageBuffer1_Int1 = TSymbolUniqueId(1154); + static constexpr const TSymbolUniqueId imageLoadExt_IImageBuffer1_Int1 = TSymbolUniqueId(1155); + static constexpr const TSymbolUniqueId imageLoadExt_UImageBuffer1_Int1 = TSymbolUniqueId(1156); static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1160); + TSymbolUniqueId(1157); static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1161); + TSymbolUniqueId(1158); static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1162); + TSymbolUniqueId(1159); static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1163); + TSymbolUniqueId(1160); static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1164); + TSymbolUniqueId(1161); static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1165); + TSymbolUniqueId(1162); static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1166); + TSymbolUniqueId(1163); static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1167); + TSymbolUniqueId(1164); static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1168); + TSymbolUniqueId(1165); static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1169); + TSymbolUniqueId(1166); static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1170); + TSymbolUniqueId(1167); static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1171); + TSymbolUniqueId(1168); static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1172); + TSymbolUniqueId(1169); static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1173); + TSymbolUniqueId(1170); static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1174); + TSymbolUniqueId(1171); static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1175); + TSymbolUniqueId(1172); static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1176); + TSymbolUniqueId(1173); static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1174); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_Int1 = + TSymbolUniqueId(1175); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_Int1 = + TSymbolUniqueId(1176); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_Int1 = TSymbolUniqueId(1177); - static constexpr const TSymbolUniqueId imageAtomicAdd_ImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_Int1 = TSymbolUniqueId(1178); - static constexpr const TSymbolUniqueId pt00x = TSymbolUniqueId(1179); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_Int1 = + TSymbolUniqueId(1179); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_Int1 = TSymbolUniqueId(1180); - static constexpr const TSymbolUniqueId pt01G = TSymbolUniqueId(1181); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_Int1 = + TSymbolUniqueId(1181); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_Int1 = TSymbolUniqueId(1182); - static constexpr const TSymbolUniqueId pt01P = TSymbolUniqueId(1183); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_Int1 = + TSymbolUniqueId(1183); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1184); - static constexpr const TSymbolUniqueId pt00u = TSymbolUniqueId(1185); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1185); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1186); - static constexpr const TSymbolUniqueId pt01D = TSymbolUniqueId(1187); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(1187); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1188); - static constexpr const TSymbolUniqueId pt01M = TSymbolUniqueId(1189); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1189); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1190); - static constexpr const TSymbolUniqueId pt00v = TSymbolUniqueId(1191); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1191); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1192); - static constexpr const TSymbolUniqueId pt01E = TSymbolUniqueId(1193); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_UInt1 = + TSymbolUniqueId(1193); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1194); - static constexpr const TSymbolUniqueId pt01N = TSymbolUniqueId(1195); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(1195); + static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_UInt1 = TSymbolUniqueId(1196); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1197); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1198); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1199); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1200); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1201); - static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1202); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1203); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1204); - static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1205); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1206); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1207); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1208); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1209); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1210); - static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_Int1 = TSymbolUniqueId(1211); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_Int1 = TSymbolUniqueId(1212); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_Int1 = TSymbolUniqueId(1213); - static constexpr const TSymbolUniqueId imageAtomicAdd_ImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_Int1 = TSymbolUniqueId(1214); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_Int1 = TSymbolUniqueId(1215); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_Int1 = TSymbolUniqueId(1216); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_Int1 = TSymbolUniqueId(1217); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_Int1 = TSymbolUniqueId(1218); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_Int1 = TSymbolUniqueId(1219); - static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1220); - static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1221); - static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1222); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1223); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1224); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1225); - static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1226); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1227); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1228); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_UInt1 = TSymbolUniqueId(1229); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1230); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1231); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_UInt1 = TSymbolUniqueId(1232); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1233); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1234); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1235); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1236); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1237); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1238); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1239); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1240); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1241); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1242); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1243); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1244); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1245); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1246); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_Int1 = TSymbolUniqueId(1247); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_Int1 = TSymbolUniqueId(1248); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_Int1 = TSymbolUniqueId(1249); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_Int1 = TSymbolUniqueId(1250); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_Int1 = TSymbolUniqueId(1251); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_Int1 = TSymbolUniqueId(1252); - static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_Int1 = TSymbolUniqueId(1253); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_Int1 = TSymbolUniqueId(1254); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_Int1 = TSymbolUniqueId(1255); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1256); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1257); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1258); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1259); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1260); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1261); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1262); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1263); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1264); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_UInt1 = TSymbolUniqueId(1265); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1266); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1267); - static constexpr const TSymbolUniqueId imageAtomicMin_ImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_UInt1 = TSymbolUniqueId(1268); - static constexpr const TSymbolUniqueId imageAtomicMin_IImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1269); - static constexpr const TSymbolUniqueId imageAtomicMin_UImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1270); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1271); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1272); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1273); - static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1274); - static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1275); - static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1276); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1277); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1278); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1279); - static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1280); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1281); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1282); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_Int1 = TSymbolUniqueId(1283); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_Int1 = TSymbolUniqueId(1284); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_Int1 = TSymbolUniqueId(1285); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_Int1 = TSymbolUniqueId(1286); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_Int1 = TSymbolUniqueId(1287); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_Int1 = TSymbolUniqueId(1288); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_Int1 = TSymbolUniqueId(1289); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_Int1 = TSymbolUniqueId(1290); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_Int1 = TSymbolUniqueId(1291); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1292); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1293); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1294); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1295); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1296); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1297); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1298); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1299); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1300); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_UInt1 = TSymbolUniqueId(1301); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1302); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1303); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_UInt1 = TSymbolUniqueId(1304); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1305); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1306); - static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1307); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1308); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1309); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1310); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1311); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1312); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1313); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1314); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1315); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1316); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1317); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1318); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1319); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_Int1 = TSymbolUniqueId(1319); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_Int1 = TSymbolUniqueId(1320); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_Int1 = TSymbolUniqueId(1321); - static constexpr const TSymbolUniqueId imageAtomicMax_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1322); - static constexpr const TSymbolUniqueId imageAtomicMax_IImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_Int1 = TSymbolUniqueId(1322); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_Int1 = TSymbolUniqueId(1323); - static constexpr const TSymbolUniqueId imageAtomicMax_UImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_Int1 = TSymbolUniqueId(1324); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_Int1 = TSymbolUniqueId(1325); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_Int1 = TSymbolUniqueId(1326); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_Int1 = TSymbolUniqueId(1327); - static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1328); - static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1329); - static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1330); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1331); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1332); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1333); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1334); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1335); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1336); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_UInt1 = TSymbolUniqueId(1337); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1338); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1339); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_UInt1 = TSymbolUniqueId(1340); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1341); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1342); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1343); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1344); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1345); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1346); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1347); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1348); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1349); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1350); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1351); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1352); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1353); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1354); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_Int1 = TSymbolUniqueId(1355); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_Int1 = TSymbolUniqueId(1356); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_Int1 = TSymbolUniqueId(1357); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_Int1 = TSymbolUniqueId(1358); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_Int1 = TSymbolUniqueId(1359); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_Int1 = TSymbolUniqueId(1360); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_Int1 = TSymbolUniqueId(1361); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_Int1 = TSymbolUniqueId(1362); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_Int1 = TSymbolUniqueId(1363); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1364); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1365); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1366); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1367); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1368); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1369); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1370); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1371); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1372); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_UInt1 = TSymbolUniqueId(1373); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1374); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1375); - static constexpr const TSymbolUniqueId imageAtomicAnd_ImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_UInt1 = TSymbolUniqueId(1376); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1377); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1378); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1379); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1380); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1381); - static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1382); - static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1383); - static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1384); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1385); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1386); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1387); - static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1388); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1389); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1390); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Int1 = TSymbolUniqueId(1391); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Int1 = TSymbolUniqueId(1392); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Int1 = TSymbolUniqueId(1393); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Int1 = TSymbolUniqueId(1394); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Int1 = TSymbolUniqueId(1395); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Int1 = TSymbolUniqueId(1396); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Int1 = TSymbolUniqueId(1397); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Int1 = TSymbolUniqueId(1398); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Int1 = TSymbolUniqueId(1399); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1400); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1401); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1402); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1403); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1404); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1405); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1406); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1407); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1408); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Float1 = TSymbolUniqueId(1409); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Float1 = TSymbolUniqueId(1410); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Float1 = TSymbolUniqueId(1411); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_Int1 = TSymbolUniqueId(1412); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Float1 = + TSymbolUniqueId(1412); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Float1 = TSymbolUniqueId(1413); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Float1 = TSymbolUniqueId(1414); - static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_Int1 = TSymbolUniqueId(1415); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Float1 = + TSymbolUniqueId(1415); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Float1 = TSymbolUniqueId(1416); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Float1 = TSymbolUniqueId(1417); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Float1 = TSymbolUniqueId(1418); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Float1 = TSymbolUniqueId(1419); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Float1 = TSymbolUniqueId(1420); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Float1 = TSymbolUniqueId(1421); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Float1 = TSymbolUniqueId(1422); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Float1 = TSymbolUniqueId(1423); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Float1 = TSymbolUniqueId(1424); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Float1 = TSymbolUniqueId(1425); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Float1 = TSymbolUniqueId(1426); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1 = TSymbolUniqueId(1427); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1 = TSymbolUniqueId(1428); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1 = TSymbolUniqueId(1429); - static constexpr const TSymbolUniqueId imageAtomicOr_ImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_UInt1_UInt1 = TSymbolUniqueId(1430); - static constexpr const TSymbolUniqueId imageAtomicOr_IImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_UInt1_UInt1 = TSymbolUniqueId(1431); - static constexpr const TSymbolUniqueId imageAtomicOr_UImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_UInt1_UInt1 = TSymbolUniqueId(1432); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_UInt1_UInt1 = TSymbolUniqueId(1433); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_UInt1_UInt1 = TSymbolUniqueId(1434); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_UInt1_UInt1 = TSymbolUniqueId(1435); - static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_UInt1_UInt1 = TSymbolUniqueId(1436); - static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_UInt1_UInt1 = TSymbolUniqueId(1437); - static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_UInt1_UInt1 = TSymbolUniqueId(1438); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1439); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1440); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1441); - static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1442); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1443); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1444); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_Int1_Int1 = TSymbolUniqueId(1445); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_Int1_Int1 = TSymbolUniqueId(1446); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_Int1_Int1 = TSymbolUniqueId(1447); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_Int1_Int1 = TSymbolUniqueId(1448); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_Int1_Int1 = TSymbolUniqueId(1449); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_Int1_Int1 = TSymbolUniqueId(1450); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_Int1_Int1 = TSymbolUniqueId(1451); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_Int1_Int1 = TSymbolUniqueId(1452); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_Int1_Int1 = TSymbolUniqueId(1453); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_Int1_Int1 = TSymbolUniqueId(1454); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_Int1_Int1 = TSymbolUniqueId(1455); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_Int1_Int1 = TSymbolUniqueId(1456); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_Int1_Int1 = TSymbolUniqueId(1457); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_Int1_Int1 = TSymbolUniqueId(1458); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageRect1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_Int1_Int1 = TSymbolUniqueId(1459); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_Int1_Int1 = TSymbolUniqueId(1460); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_Int1_Int1 = TSymbolUniqueId(1461); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMS1_Int2_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_Int1_Int1 = TSymbolUniqueId(1462); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_UInt1 = TSymbolUniqueId(1463); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1464); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMSArray1_Int3_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1465); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_UInt1 = TSymbolUniqueId(1466); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1467); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1468); - static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_UInt1 = TSymbolUniqueId(1469); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_UInt1 = TSymbolUniqueId(1470); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_UInt1 = TSymbolUniqueId(1471); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1472); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1473); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_UInt1 = TSymbolUniqueId(1474); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_UInt1 = TSymbolUniqueId(1475); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1476); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_UInt1 = TSymbolUniqueId(1477); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1478); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1479); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_UInt1 = TSymbolUniqueId(1480); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_Int1 = TSymbolUniqueId(1481); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_Int1 = TSymbolUniqueId(1482); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_Int1 = TSymbolUniqueId(1483); - static constexpr const TSymbolUniqueId imageAtomicXor_ImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_Int1 = TSymbolUniqueId(1484); - static constexpr const TSymbolUniqueId imageAtomicXor_IImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_Int1 = TSymbolUniqueId(1485); - static constexpr const TSymbolUniqueId imageAtomicXor_UImageRect1_Int2_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_Int1 = TSymbolUniqueId(1486); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_Int1 = TSymbolUniqueId(1487); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_Int1 = TSymbolUniqueId(1488); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMS1_Int2_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_Int1 = TSymbolUniqueId(1489); - static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_Int1 = TSymbolUniqueId(1490); - static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_Int1 = TSymbolUniqueId(1491); - static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMSArray1_Int3_Int1_Int1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_Int1 = TSymbolUniqueId(1492); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_Int1 = TSymbolUniqueId(1493); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_Int1 = TSymbolUniqueId(1494); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_Int1 = TSymbolUniqueId(1495); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1496); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1497); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_Int1 = TSymbolUniqueId(1498); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_UInt1 = TSymbolUniqueId(1499); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_UInt1 = TSymbolUniqueId(1500); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_UInt1 = TSymbolUniqueId(1501); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_UInt1 = TSymbolUniqueId(1502); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_UInt1 = TSymbolUniqueId(1503); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_UInt1 = + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_UInt1 = TSymbolUniqueId(1504); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1505); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1506); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1507); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1508); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1509); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1510); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1511); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1512); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1513); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1514); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1515); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1516); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1517); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1518); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1519); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Int1 = - TSymbolUniqueId(1520); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1521); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1522); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Int1 = - TSymbolUniqueId(1523); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1524); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1525); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1526); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1527); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1528); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1529); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1530); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1531); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1532); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1533); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1534); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1535); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1536); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1537); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1538); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1539); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1540); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1541); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1542); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1543); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1544); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1545); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1546); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Float1 = - TSymbolUniqueId(1547); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Float1 = - TSymbolUniqueId(1548); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Float1 = - TSymbolUniqueId(1549); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Float1 = - TSymbolUniqueId(1550); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Float1 = - TSymbolUniqueId(1551); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Float1 = - TSymbolUniqueId(1552); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Float1 = - TSymbolUniqueId(1553); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Float1 = - TSymbolUniqueId(1554); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Float1 = - TSymbolUniqueId(1555); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Float1 = - TSymbolUniqueId(1556); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Float1 = - TSymbolUniqueId(1557); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Float1 = - TSymbolUniqueId(1558); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Float1 = - TSymbolUniqueId(1559); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Float1 = - TSymbolUniqueId(1560); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Float1 = - TSymbolUniqueId(1561); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Float1 = - TSymbolUniqueId(1562); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Float1 = - TSymbolUniqueId(1563); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Float1 = - TSymbolUniqueId(1564); - static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_Float1 = - TSymbolUniqueId(1565); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_Float1 = - TSymbolUniqueId(1566); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_Float1 = - TSymbolUniqueId(1567); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_Float1 = - TSymbolUniqueId(1568); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_Float1 = - TSymbolUniqueId(1569); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_Float1 = - TSymbolUniqueId(1570); - static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_Float1 = - TSymbolUniqueId(1571); - static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Float1 = - TSymbolUniqueId(1572); - static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Float1 = - TSymbolUniqueId(1573); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1 = - TSymbolUniqueId(1574); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1 = - TSymbolUniqueId(1575); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1 = - TSymbolUniqueId(1576); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1577); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1578); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1579); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1580); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1581); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1582); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_UInt1_UInt1 = - TSymbolUniqueId(1583); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_UInt1_UInt1 = - TSymbolUniqueId(1584); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_UInt1_UInt1 = - TSymbolUniqueId(1585); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1586); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1587); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1588); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1589); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1590); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(1591); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageRect1_Int2_UInt1_UInt1 = - TSymbolUniqueId(1592); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageRect1_Int2_UInt1_UInt1 = - TSymbolUniqueId(1593); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageRect1_Int2_UInt1_UInt1 = - TSymbolUniqueId(1594); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMS1_Int2_Int1_UInt1_UInt1 = - TSymbolUniqueId(1595); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DMS1_Int2_Int1_UInt1_UInt1 = - TSymbolUniqueId(1596); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DMS1_Int2_Int1_UInt1_UInt1 = - TSymbolUniqueId(1597); - static constexpr const TSymbolUniqueId - imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(1598); - static constexpr const TSymbolUniqueId - imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(1599); - static constexpr const TSymbolUniqueId - imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(1600); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_Int1_Int1 = - TSymbolUniqueId(1601); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_Int1_Int1 = - TSymbolUniqueId(1602); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_Int1_Int1 = - TSymbolUniqueId(1603); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_Int1_Int1 = - TSymbolUniqueId(1604); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_Int1_Int1 = - TSymbolUniqueId(1605); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_Int1_Int1 = - TSymbolUniqueId(1606); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_Int1_Int1 = - TSymbolUniqueId(1607); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_Int1_Int1 = - TSymbolUniqueId(1608); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_Int1_Int1 = - TSymbolUniqueId(1609); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_Int1_Int1 = - TSymbolUniqueId(1610); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_Int1_Int1 = - TSymbolUniqueId(1611); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_Int1_Int1 = - TSymbolUniqueId(1612); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1613); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1614); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1615); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1616); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1617); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1618); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageRect1_Int2_Int1_Int1 = - TSymbolUniqueId(1619); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageRect1_Int2_Int1_Int1 = - TSymbolUniqueId(1620); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageRect1_Int2_Int1_Int1 = - TSymbolUniqueId(1621); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMS1_Int2_Int1_Int1_Int1 = - TSymbolUniqueId(1622); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DMS1_Int2_Int1_Int1_Int1 = - TSymbolUniqueId(1623); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DMS1_Int2_Int1_Int1_Int1 = - TSymbolUniqueId(1624); - static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_Int1_Int1 = - TSymbolUniqueId(1625); - static constexpr const TSymbolUniqueId - imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(1626); - static constexpr const TSymbolUniqueId - imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(1627); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1628); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1629); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1630); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1631); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1632); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1633); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1634); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1635); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1636); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1637); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1638); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1639); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1640); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1641); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1642); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1643); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1644); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1645); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1646); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1647); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1648); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1649); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1650); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1651); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1652); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1653); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1654); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1655); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1656); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1657); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1658); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1659); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1660); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1661); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1662); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1663); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1664); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1665); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1666); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1667); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1668); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1669); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1670); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1671); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1672); - static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1673); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1674); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1675); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1676); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1677); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1678); - static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1679); - static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1680); - static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1681); - static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1682); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1683); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1684); - static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1685); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1686); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1687); static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1688); + TSymbolUniqueId(1505); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1689); + TSymbolUniqueId(1506); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1690); + TSymbolUniqueId(1507); static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1691); + TSymbolUniqueId(1508); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1692); + TSymbolUniqueId(1509); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1693); + TSymbolUniqueId(1510); static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1694); + TSymbolUniqueId(1511); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1695); + TSymbolUniqueId(1512); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1696); + TSymbolUniqueId(1513); static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1697); + TSymbolUniqueId(1514); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1698); + TSymbolUniqueId(1515); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1699); - static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1700); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1701); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1702); - static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1703); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1704); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1705); - static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1706); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1707); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1708); + TSymbolUniqueId(1516); static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1709); + TSymbolUniqueId(1517); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1710); + TSymbolUniqueId(1518); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1711); + TSymbolUniqueId(1519); static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1712); + TSymbolUniqueId(1520); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1713); + TSymbolUniqueId(1521); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1714); + TSymbolUniqueId(1522); static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1715); + TSymbolUniqueId(1523); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1716); + TSymbolUniqueId(1524); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1717); + TSymbolUniqueId(1525); static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1718); + TSymbolUniqueId(1526); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1719); + TSymbolUniqueId(1527); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1720); + TSymbolUniqueId(1528); static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1721); + TSymbolUniqueId(1529); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1722); + TSymbolUniqueId(1530); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1723); + TSymbolUniqueId(1531); static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1724); + TSymbolUniqueId(1532); static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1725); + TSymbolUniqueId(1533); static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1726); - static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1727); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1728); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1729); - static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1730); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1731); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1732); - static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1733); - static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1734); - static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1735); + TSymbolUniqueId(1534); static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1736); + TSymbolUniqueId(1535); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1737); + TSymbolUniqueId(1536); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1738); + TSymbolUniqueId(1537); static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1739); + TSymbolUniqueId(1538); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1740); + TSymbolUniqueId(1539); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1741); + TSymbolUniqueId(1540); static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1742); + TSymbolUniqueId(1541); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1743); + TSymbolUniqueId(1542); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1744); + TSymbolUniqueId(1543); static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1745); + TSymbolUniqueId(1544); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1746); + TSymbolUniqueId(1545); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1747); + TSymbolUniqueId(1546); static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1748); + TSymbolUniqueId(1547); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1749); + TSymbolUniqueId(1548); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1750); + TSymbolUniqueId(1549); static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1751); + TSymbolUniqueId(1550); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1752); + TSymbolUniqueId(1551); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1753); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1754); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1755); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1756); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1757); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1758); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1759); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1760); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1761); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1762); + TSymbolUniqueId(1552); static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1763); + TSymbolUniqueId(1553); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1764); + TSymbolUniqueId(1554); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1765); + TSymbolUniqueId(1555); static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1766); + TSymbolUniqueId(1556); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1767); + TSymbolUniqueId(1557); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1768); + TSymbolUniqueId(1558); static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1769); + TSymbolUniqueId(1559); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1770); + TSymbolUniqueId(1560); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1771); + TSymbolUniqueId(1561); static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1772); + TSymbolUniqueId(1562); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1773); + TSymbolUniqueId(1563); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1774); + TSymbolUniqueId(1564); static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1775); + TSymbolUniqueId(1565); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1776); + TSymbolUniqueId(1566); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1777); + TSymbolUniqueId(1567); static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1778); + TSymbolUniqueId(1568); static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1779); + TSymbolUniqueId(1569); static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1780); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1781); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1782); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1783); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1784); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1785); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1786); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1787); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1788); - static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1789); + TSymbolUniqueId(1570); static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1790); + TSymbolUniqueId(1571); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1791); + TSymbolUniqueId(1572); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1792); + TSymbolUniqueId(1573); static constexpr const TSymbolUniqueId imageAtomicAndExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1793); + TSymbolUniqueId(1574); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1794); + TSymbolUniqueId(1575); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1795); + TSymbolUniqueId(1576); static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1796); + TSymbolUniqueId(1577); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1797); + TSymbolUniqueId(1578); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1798); + TSymbolUniqueId(1579); static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1799); + TSymbolUniqueId(1580); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1800); + TSymbolUniqueId(1581); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1801); + TSymbolUniqueId(1582); static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1802); + TSymbolUniqueId(1583); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1803); + TSymbolUniqueId(1584); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1804); + TSymbolUniqueId(1585); static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1805); + TSymbolUniqueId(1586); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1806); + TSymbolUniqueId(1587); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1807); - static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1808); - static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1809); - static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1810); - static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1811); - static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1812); - static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1813); - static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1814); - static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1815); - static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1816); + TSymbolUniqueId(1588); static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1817); + TSymbolUniqueId(1589); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1818); + TSymbolUniqueId(1590); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1819); + TSymbolUniqueId(1591); static constexpr const TSymbolUniqueId imageAtomicAndExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1820); + TSymbolUniqueId(1592); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1821); + TSymbolUniqueId(1593); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1822); + TSymbolUniqueId(1594); static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1823); + TSymbolUniqueId(1595); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1824); + TSymbolUniqueId(1596); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1825); + TSymbolUniqueId(1597); static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1826); + TSymbolUniqueId(1598); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1827); + TSymbolUniqueId(1599); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1828); + TSymbolUniqueId(1600); static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1829); + TSymbolUniqueId(1601); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1830); + TSymbolUniqueId(1602); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1831); + TSymbolUniqueId(1603); static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1832); + TSymbolUniqueId(1604); static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1833); + TSymbolUniqueId(1605); static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1834); - static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1835); - static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1836); - static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1837); - static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1838); - static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1839); - static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1840); - static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1841); - static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1842); - static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1843); + TSymbolUniqueId(1606); static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1844); + TSymbolUniqueId(1607); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1845); + TSymbolUniqueId(1608); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1846); + TSymbolUniqueId(1609); static constexpr const TSymbolUniqueId imageAtomicOrExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1847); + TSymbolUniqueId(1610); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1848); + TSymbolUniqueId(1611); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1849); + TSymbolUniqueId(1612); static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1850); + TSymbolUniqueId(1613); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1851); + TSymbolUniqueId(1614); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1852); + TSymbolUniqueId(1615); static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1853); + TSymbolUniqueId(1616); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1854); + TSymbolUniqueId(1617); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1855); + TSymbolUniqueId(1618); static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1856); + TSymbolUniqueId(1619); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1857); + TSymbolUniqueId(1620); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1858); + TSymbolUniqueId(1621); static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1859); + TSymbolUniqueId(1622); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1860); + TSymbolUniqueId(1623); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1861); - static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1862); - static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1863); - static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1864); - static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1865); - static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1866); - static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1867); - static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1868); - static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1869); - static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1870); + TSymbolUniqueId(1624); static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1871); + TSymbolUniqueId(1625); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1872); + TSymbolUniqueId(1626); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1873); + TSymbolUniqueId(1627); static constexpr const TSymbolUniqueId imageAtomicOrExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1874); + TSymbolUniqueId(1628); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1875); + TSymbolUniqueId(1629); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1876); + TSymbolUniqueId(1630); static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1877); + TSymbolUniqueId(1631); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1878); + TSymbolUniqueId(1632); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1879); + TSymbolUniqueId(1633); static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1880); + TSymbolUniqueId(1634); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1881); + TSymbolUniqueId(1635); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1882); + TSymbolUniqueId(1636); static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1883); + TSymbolUniqueId(1637); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1884); + TSymbolUniqueId(1638); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1885); + TSymbolUniqueId(1639); static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1886); + TSymbolUniqueId(1640); static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1887); + TSymbolUniqueId(1641); static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1888); - static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1889); - static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1890); - static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1891); - static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1892); - static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1893); - static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1894); - static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1895); - static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1896); - static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1897); + TSymbolUniqueId(1642); static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1898); + TSymbolUniqueId(1643); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1899); + TSymbolUniqueId(1644); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1900); + TSymbolUniqueId(1645); static constexpr const TSymbolUniqueId imageAtomicXorExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1901); + TSymbolUniqueId(1646); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1902); + TSymbolUniqueId(1647); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1903); + TSymbolUniqueId(1648); static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1904); + TSymbolUniqueId(1649); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1905); + TSymbolUniqueId(1650); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1906); + TSymbolUniqueId(1651); static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1907); + TSymbolUniqueId(1652); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1908); + TSymbolUniqueId(1653); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1909); + TSymbolUniqueId(1654); static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1910); + TSymbolUniqueId(1655); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1911); + TSymbolUniqueId(1656); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1912); + TSymbolUniqueId(1657); static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1913); + TSymbolUniqueId(1658); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1914); + TSymbolUniqueId(1659); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1915); - static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1916); - static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1917); - static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1918); - static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1919); - static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1920); - static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1921); - static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1922); - static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1923); - static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1924); + TSymbolUniqueId(1660); static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1925); + TSymbolUniqueId(1661); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1926); + TSymbolUniqueId(1662); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1927); + TSymbolUniqueId(1663); static constexpr const TSymbolUniqueId imageAtomicXorExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1928); + TSymbolUniqueId(1664); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1929); + TSymbolUniqueId(1665); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1930); + TSymbolUniqueId(1666); static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1931); + TSymbolUniqueId(1667); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1932); + TSymbolUniqueId(1668); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1933); + TSymbolUniqueId(1669); static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1934); + TSymbolUniqueId(1670); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1935); + TSymbolUniqueId(1671); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1936); + TSymbolUniqueId(1672); static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1937); + TSymbolUniqueId(1673); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1938); + TSymbolUniqueId(1674); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1939); + TSymbolUniqueId(1675); static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1940); + TSymbolUniqueId(1676); static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1941); + TSymbolUniqueId(1677); static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1942); - static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1943); - static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1944); - static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1945); - static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1946); - static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1947); - static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(1948); - static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1949); - static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1950); - static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(1951); + TSymbolUniqueId(1678); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_UInt1 = - TSymbolUniqueId(1952); + TSymbolUniqueId(1679); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_UInt1 = - TSymbolUniqueId(1953); + TSymbolUniqueId(1680); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_UInt1 = - TSymbolUniqueId(1954); + TSymbolUniqueId(1681); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_UInt1 = - TSymbolUniqueId(1955); + TSymbolUniqueId(1682); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_UInt1 = - TSymbolUniqueId(1956); + TSymbolUniqueId(1683); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_UInt1 = - TSymbolUniqueId(1957); + TSymbolUniqueId(1684); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_UInt1 = - TSymbolUniqueId(1958); + TSymbolUniqueId(1685); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_UInt1 = - TSymbolUniqueId(1959); + TSymbolUniqueId(1686); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_UInt1 = - TSymbolUniqueId(1960); + TSymbolUniqueId(1687); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1961); + TSymbolUniqueId(1688); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1962); + TSymbolUniqueId(1689); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_UInt1 = - TSymbolUniqueId(1963); + TSymbolUniqueId(1690); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_UInt1 = - TSymbolUniqueId(1964); + TSymbolUniqueId(1691); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1965); + TSymbolUniqueId(1692); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_UInt1 = - TSymbolUniqueId(1966); + TSymbolUniqueId(1693); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1967); + TSymbolUniqueId(1694); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1968); + TSymbolUniqueId(1695); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_UInt1 = - TSymbolUniqueId(1969); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_UInt1 = - TSymbolUniqueId(1970); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_UInt1 = - TSymbolUniqueId(1971); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_UInt1 = - TSymbolUniqueId(1972); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1973); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1974); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_UInt1 = - TSymbolUniqueId(1975); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1976); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1977); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_UInt1 = - TSymbolUniqueId(1978); + TSymbolUniqueId(1696); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_Int1 = - TSymbolUniqueId(1979); + TSymbolUniqueId(1697); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_Int1 = - TSymbolUniqueId(1980); + TSymbolUniqueId(1698); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_Int1 = - TSymbolUniqueId(1981); + TSymbolUniqueId(1699); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_Int1 = - TSymbolUniqueId(1982); + TSymbolUniqueId(1700); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_Int1 = - TSymbolUniqueId(1983); + TSymbolUniqueId(1701); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_Int1 = - TSymbolUniqueId(1984); + TSymbolUniqueId(1702); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_Int1 = - TSymbolUniqueId(1985); + TSymbolUniqueId(1703); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_Int1 = - TSymbolUniqueId(1986); + TSymbolUniqueId(1704); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_Int1 = - TSymbolUniqueId(1987); + TSymbolUniqueId(1705); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1988); + TSymbolUniqueId(1706); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1989); + TSymbolUniqueId(1707); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_Int1 = - TSymbolUniqueId(1990); + TSymbolUniqueId(1708); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_Int1 = - TSymbolUniqueId(1991); + TSymbolUniqueId(1709); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1992); + TSymbolUniqueId(1710); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_Int1 = - TSymbolUniqueId(1993); + TSymbolUniqueId(1711); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1994); + TSymbolUniqueId(1712); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1995); + TSymbolUniqueId(1713); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_Int1 = - TSymbolUniqueId(1996); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_Int1 = - TSymbolUniqueId(1997); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_Int1 = - TSymbolUniqueId(1998); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_Int1 = - TSymbolUniqueId(1999); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(2000); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(2001); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Int1 = - TSymbolUniqueId(2002); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2003); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2004); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2005); + TSymbolUniqueId(1714); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_Float1 = - TSymbolUniqueId(2006); + TSymbolUniqueId(1715); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_Float1 = - TSymbolUniqueId(2007); + TSymbolUniqueId(1716); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_Float1 = - TSymbolUniqueId(2008); + TSymbolUniqueId(1717); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_Float1 = - TSymbolUniqueId(2009); + TSymbolUniqueId(1718); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_Float1 = - TSymbolUniqueId(2010); + TSymbolUniqueId(1719); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_Float1 = - TSymbolUniqueId(2011); + TSymbolUniqueId(1720); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_Float1 = - TSymbolUniqueId(2012); + TSymbolUniqueId(1721); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_Float1 = - TSymbolUniqueId(2013); + TSymbolUniqueId(1722); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_Float1 = - TSymbolUniqueId(2014); + TSymbolUniqueId(1723); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_Float1 = - TSymbolUniqueId(2015); + TSymbolUniqueId(1724); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_Float1 = - TSymbolUniqueId(2016); + TSymbolUniqueId(1725); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_Float1 = - TSymbolUniqueId(2017); + TSymbolUniqueId(1726); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_Float1 = - TSymbolUniqueId(2018); + TSymbolUniqueId(1727); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_Float1 = - TSymbolUniqueId(2019); + TSymbolUniqueId(1728); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_Float1 = - TSymbolUniqueId(2020); + TSymbolUniqueId(1729); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_Float1 = - TSymbolUniqueId(2021); + TSymbolUniqueId(1730); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_Float1 = - TSymbolUniqueId(2022); + TSymbolUniqueId(1731); static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_Float1 = - TSymbolUniqueId(2023); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_Float1 = - TSymbolUniqueId(2024); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_Float1 = - TSymbolUniqueId(2025); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_Float1 = - TSymbolUniqueId(2026); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Float1 = - TSymbolUniqueId(2027); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Float1 = - TSymbolUniqueId(2028); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Float1 = - TSymbolUniqueId(2029); - static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Float1 = - TSymbolUniqueId(2030); - static constexpr const TSymbolUniqueId - imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Float1 = TSymbolUniqueId(2031); - static constexpr const TSymbolUniqueId - imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Float1 = TSymbolUniqueId(2032); + TSymbolUniqueId(1732); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2D1_Int2_UInt1_UInt1 = - TSymbolUniqueId(2033); + TSymbolUniqueId(1733); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2D1_Int2_UInt1_UInt1 = - TSymbolUniqueId(2034); + TSymbolUniqueId(1734); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2D1_Int2_UInt1_UInt1 = - TSymbolUniqueId(2035); + TSymbolUniqueId(1735); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image3D1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2036); + TSymbolUniqueId(1736); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage3D1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2037); + TSymbolUniqueId(1737); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage3D1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2038); + TSymbolUniqueId(1738); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCube1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2039); + TSymbolUniqueId(1739); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCube1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2040); + TSymbolUniqueId(1740); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCube1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2041); + TSymbolUniqueId(1741); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageBuffer1_Int1_UInt1_UInt1 = - TSymbolUniqueId(2042); + TSymbolUniqueId(1742); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageBuffer1_Int1_UInt1_UInt1 = - TSymbolUniqueId(2043); + TSymbolUniqueId(1743); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageBuffer1_Int1_UInt1_UInt1 = - TSymbolUniqueId(2044); + TSymbolUniqueId(1744); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2045); + TSymbolUniqueId(1745); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2046); + TSymbolUniqueId(1746); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2047); + TSymbolUniqueId(1747); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCubeArray1_Int3_UInt1_UInt1 = - TSymbolUniqueId(2048); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_IImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(2049); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_UImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(2050); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageRect1_Int2_UInt1_UInt1 = - TSymbolUniqueId(2051); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageRect1_Int2_UInt1_UInt1 = - TSymbolUniqueId(2052); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageRect1_Int2_UInt1_UInt1 = - TSymbolUniqueId(2053); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_UInt1_UInt1 = - TSymbolUniqueId(2054); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_UInt1_UInt1 = TSymbolUniqueId(2055); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_UInt1_UInt1 = TSymbolUniqueId(2056); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2057); + TSymbolUniqueId(1748); static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2058); + imageAtomicCompSwapExt_IImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1749); static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2059); + imageAtomicCompSwapExt_UImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(1750); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2D1_Int2_Int1_Int1 = - TSymbolUniqueId(2060); + TSymbolUniqueId(1751); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2D1_Int2_Int1_Int1 = - TSymbolUniqueId(2061); + TSymbolUniqueId(1752); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2D1_Int2_Int1_Int1 = - TSymbolUniqueId(2062); + TSymbolUniqueId(1753); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image3D1_Int3_Int1_Int1 = - TSymbolUniqueId(2063); + TSymbolUniqueId(1754); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage3D1_Int3_Int1_Int1 = - TSymbolUniqueId(2064); + TSymbolUniqueId(1755); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage3D1_Int3_Int1_Int1 = - TSymbolUniqueId(2065); + TSymbolUniqueId(1756); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCube1_Int3_Int1_Int1 = - TSymbolUniqueId(2066); + TSymbolUniqueId(1757); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCube1_Int3_Int1_Int1 = - TSymbolUniqueId(2067); + TSymbolUniqueId(1758); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCube1_Int3_Int1_Int1 = - TSymbolUniqueId(2068); + TSymbolUniqueId(1759); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageBuffer1_Int1_Int1_Int1 = - TSymbolUniqueId(2069); + TSymbolUniqueId(1760); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageBuffer1_Int1_Int1_Int1 = - TSymbolUniqueId(2070); + TSymbolUniqueId(1761); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageBuffer1_Int1_Int1_Int1 = - TSymbolUniqueId(2071); + TSymbolUniqueId(1762); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2072); + TSymbolUniqueId(1763); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2073); + TSymbolUniqueId(1764); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2074); + TSymbolUniqueId(1765); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCubeArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2075); + TSymbolUniqueId(1766); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCubeArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2076); + TSymbolUniqueId(1767); static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCubeArray1_Int3_Int1_Int1 = - TSymbolUniqueId(2077); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageRect1_Int2_Int1_Int1 = - TSymbolUniqueId(2078); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageRect1_Int2_Int1_Int1 = - TSymbolUniqueId(2079); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageRect1_Int2_Int1_Int1 = - TSymbolUniqueId(2080); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_Int1_Int1 = - TSymbolUniqueId(2081); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_Int1_Int1 = - TSymbolUniqueId(2082); - static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_Int1_Int1 = - TSymbolUniqueId(2083); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2084); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2085); - static constexpr const TSymbolUniqueId - imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2086); + TSymbolUniqueId(1768); static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_PixelLocalANGLE1 = - TSymbolUniqueId(2087); - static constexpr const TSymbolUniqueId pt01R = TSymbolUniqueId(2088); + TSymbolUniqueId(1769); + static constexpr const TSymbolUniqueId pt01H = TSymbolUniqueId(1770); static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_IPixelLocalANGLE1 = - TSymbolUniqueId(2089); - static constexpr const TSymbolUniqueId pt01S = TSymbolUniqueId(2090); + TSymbolUniqueId(1771); + static constexpr const TSymbolUniqueId pt01I = TSymbolUniqueId(1772); static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_UPixelLocalANGLE1 = - TSymbolUniqueId(2091); - static constexpr const TSymbolUniqueId pt01T = TSymbolUniqueId(2092); + TSymbolUniqueId(1773); + static constexpr const TSymbolUniqueId pt01J = TSymbolUniqueId(1774); static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_PixelLocalANGLE1_Float4 = - TSymbolUniqueId(2093); + TSymbolUniqueId(1775); static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_IPixelLocalANGLE1_Int4 = - TSymbolUniqueId(2094); + TSymbolUniqueId(1776); static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_UPixelLocalANGLE1_UInt4 = - TSymbolUniqueId(2095); - static constexpr const TSymbolUniqueId beginInvocationInterlockNV = TSymbolUniqueId(2096); - static constexpr const TSymbolUniqueId endInvocationInterlockNV = TSymbolUniqueId(2097); - static constexpr const TSymbolUniqueId beginFragmentShaderOrderingINTEL = TSymbolUniqueId(2098); - static constexpr const TSymbolUniqueId beginInvocationInterlockARB = TSymbolUniqueId(2099); - static constexpr const TSymbolUniqueId endInvocationInterlockARB = TSymbolUniqueId(2100); - static constexpr const TSymbolUniqueId memoryBarrier = TSymbolUniqueId(2101); - static constexpr const TSymbolUniqueId memoryBarrierAtomicCounter = TSymbolUniqueId(2102); - static constexpr const TSymbolUniqueId memoryBarrierBuffer = TSymbolUniqueId(2103); - static constexpr const TSymbolUniqueId memoryBarrierImage = TSymbolUniqueId(2104); - static constexpr const TSymbolUniqueId barrier = TSymbolUniqueId(2105); - static constexpr const TSymbolUniqueId memoryBarrierShared = TSymbolUniqueId(2106); - static constexpr const TSymbolUniqueId groupMemoryBarrier = TSymbolUniqueId(2107); - static constexpr const TSymbolUniqueId barrierTCS = TSymbolUniqueId(2108); - static constexpr const TSymbolUniqueId barrierTCSES3_2 = TSymbolUniqueId(2109); - static constexpr const TSymbolUniqueId EmitVertex = TSymbolUniqueId(2110); - static constexpr const TSymbolUniqueId EmitVertexES3_2 = TSymbolUniqueId(2111); - static constexpr const TSymbolUniqueId EndPrimitive = TSymbolUniqueId(2112); - static constexpr const TSymbolUniqueId EndPrimitiveES3_2 = TSymbolUniqueId(2113); - static constexpr const TSymbolUniqueId subpassLoad_SubpassInput1 = TSymbolUniqueId(2114); - static constexpr const TSymbolUniqueId pt01U = TSymbolUniqueId(2115); - static constexpr const TSymbolUniqueId subpassLoad_ISubpassInput1 = TSymbolUniqueId(2116); - static constexpr const TSymbolUniqueId pt01V = TSymbolUniqueId(2117); - static constexpr const TSymbolUniqueId subpassLoad_USubpassInput1 = TSymbolUniqueId(2118); - static constexpr const TSymbolUniqueId pt01W = TSymbolUniqueId(2119); - static constexpr const TSymbolUniqueId numSamples = TSymbolUniqueId(2120); - static constexpr const TSymbolUniqueId samplePosition_UInt1 = TSymbolUniqueId(2121); - static constexpr const TSymbolUniqueId interpolateAtCenter_Float1 = TSymbolUniqueId(2122); - static constexpr const TSymbolUniqueId interpolateAtCenter_Float2 = TSymbolUniqueId(2123); - static constexpr const TSymbolUniqueId interpolateAtCenter_Float3 = TSymbolUniqueId(2124); - static constexpr const TSymbolUniqueId interpolateAtCenter_Float4 = TSymbolUniqueId(2125); - static constexpr const TSymbolUniqueId saturate_Float1 = TSymbolUniqueId(2126); - static constexpr const TSymbolUniqueId saturate_Float2 = TSymbolUniqueId(2127); - static constexpr const TSymbolUniqueId saturate_Float3 = TSymbolUniqueId(2128); - static constexpr const TSymbolUniqueId saturate_Float4 = TSymbolUniqueId(2129); - static constexpr const TSymbolUniqueId gl_DepthRangeParameters = TSymbolUniqueId(2130); - static constexpr const TSymbolUniqueId gl_DepthRange = TSymbolUniqueId(2131); - static constexpr const TSymbolUniqueId gl_NumSamples = TSymbolUniqueId(2132); - static constexpr const TSymbolUniqueId gl_NumSamplesES3_2 = TSymbolUniqueId(2133); - static constexpr const TSymbolUniqueId gl_MaxVertexAttribs = TSymbolUniqueId(2134); - static constexpr const TSymbolUniqueId gl_MaxVertexUniformVectors = TSymbolUniqueId(2135); - static constexpr const TSymbolUniqueId gl_MaxVertexTextureImageUnits = TSymbolUniqueId(2136); - static constexpr const TSymbolUniqueId gl_MaxCombinedTextureImageUnits = TSymbolUniqueId(2137); - static constexpr const TSymbolUniqueId gl_MaxTextureImageUnits = TSymbolUniqueId(2138); - static constexpr const TSymbolUniqueId gl_MaxFragmentUniformVectors = TSymbolUniqueId(2139); - static constexpr const TSymbolUniqueId gl_MaxVaryingVectors = TSymbolUniqueId(2140); - static constexpr const TSymbolUniqueId gl_MaxDrawBuffers = TSymbolUniqueId(2141); - static constexpr const TSymbolUniqueId gl_MaxDualSourceDrawBuffersEXT = TSymbolUniqueId(2142); - static constexpr const TSymbolUniqueId gl_MaxVertexOutputVectors = TSymbolUniqueId(2143); - static constexpr const TSymbolUniqueId gl_MaxFragmentInputVectors = TSymbolUniqueId(2144); - static constexpr const TSymbolUniqueId gl_MinProgramTexelOffset = TSymbolUniqueId(2145); - static constexpr const TSymbolUniqueId gl_MaxProgramTexelOffset = TSymbolUniqueId(2146); - static constexpr const TSymbolUniqueId gl_MaxImageUnits = TSymbolUniqueId(2147); - static constexpr const TSymbolUniqueId gl_MaxVertexImageUniforms = TSymbolUniqueId(2148); - static constexpr const TSymbolUniqueId gl_MaxFragmentImageUniforms = TSymbolUniqueId(2149); - static constexpr const TSymbolUniqueId gl_MaxComputeImageUniforms = TSymbolUniqueId(2150); - static constexpr const TSymbolUniqueId gl_MaxCombinedImageUniforms = TSymbolUniqueId(2151); + TSymbolUniqueId(1777); + static constexpr const TSymbolUniqueId beginInvocationInterlockNV = TSymbolUniqueId(1778); + static constexpr const TSymbolUniqueId endInvocationInterlockNV = TSymbolUniqueId(1779); + static constexpr const TSymbolUniqueId beginFragmentShaderOrderingINTEL = TSymbolUniqueId(1780); + static constexpr const TSymbolUniqueId beginInvocationInterlockARB = TSymbolUniqueId(1781); + static constexpr const TSymbolUniqueId endInvocationInterlockARB = TSymbolUniqueId(1782); + static constexpr const TSymbolUniqueId memoryBarrier = TSymbolUniqueId(1783); + static constexpr const TSymbolUniqueId memoryBarrierAtomicCounter = TSymbolUniqueId(1784); + static constexpr const TSymbolUniqueId memoryBarrierBuffer = TSymbolUniqueId(1785); + static constexpr const TSymbolUniqueId memoryBarrierImage = TSymbolUniqueId(1786); + static constexpr const TSymbolUniqueId barrier = TSymbolUniqueId(1787); + static constexpr const TSymbolUniqueId memoryBarrierShared = TSymbolUniqueId(1788); + static constexpr const TSymbolUniqueId groupMemoryBarrier = TSymbolUniqueId(1789); + static constexpr const TSymbolUniqueId barrierTCS = TSymbolUniqueId(1790); + static constexpr const TSymbolUniqueId barrierTCSES3_2 = TSymbolUniqueId(1791); + static constexpr const TSymbolUniqueId EmitVertex = TSymbolUniqueId(1792); + static constexpr const TSymbolUniqueId EmitVertexES3_2 = TSymbolUniqueId(1793); + static constexpr const TSymbolUniqueId EndPrimitive = TSymbolUniqueId(1794); + static constexpr const TSymbolUniqueId EndPrimitiveES3_2 = TSymbolUniqueId(1795); + static constexpr const TSymbolUniqueId subpassLoad_SubpassInput1 = TSymbolUniqueId(1796); + static constexpr const TSymbolUniqueId pt01K = TSymbolUniqueId(1797); + static constexpr const TSymbolUniqueId subpassLoad_ISubpassInput1 = TSymbolUniqueId(1798); + static constexpr const TSymbolUniqueId pt01L = TSymbolUniqueId(1799); + static constexpr const TSymbolUniqueId subpassLoad_USubpassInput1 = TSymbolUniqueId(1800); + static constexpr const TSymbolUniqueId pt01M = TSymbolUniqueId(1801); + static constexpr const TSymbolUniqueId numSamples = TSymbolUniqueId(1802); + static constexpr const TSymbolUniqueId samplePosition_UInt1 = TSymbolUniqueId(1803); + static constexpr const TSymbolUniqueId interpolateAtCenter_Float1 = TSymbolUniqueId(1804); + static constexpr const TSymbolUniqueId interpolateAtCenter_Float2 = TSymbolUniqueId(1805); + static constexpr const TSymbolUniqueId interpolateAtCenter_Float3 = TSymbolUniqueId(1806); + static constexpr const TSymbolUniqueId interpolateAtCenter_Float4 = TSymbolUniqueId(1807); + static constexpr const TSymbolUniqueId loopForwardProgress = TSymbolUniqueId(1808); + static constexpr const TSymbolUniqueId saturate_Float1 = TSymbolUniqueId(1809); + static constexpr const TSymbolUniqueId saturate_Float2 = TSymbolUniqueId(1810); + static constexpr const TSymbolUniqueId saturate_Float3 = TSymbolUniqueId(1811); + static constexpr const TSymbolUniqueId saturate_Float4 = TSymbolUniqueId(1812); + static constexpr const TSymbolUniqueId gl_DepthRangeParameters = TSymbolUniqueId(1813); + static constexpr const TSymbolUniqueId gl_DepthRange = TSymbolUniqueId(1814); + static constexpr const TSymbolUniqueId gl_NumSamples = TSymbolUniqueId(1815); + static constexpr const TSymbolUniqueId gl_NumSamplesES3_2 = TSymbolUniqueId(1816); + static constexpr const TSymbolUniqueId gl_MaxVertexAttribs = TSymbolUniqueId(1817); + static constexpr const TSymbolUniqueId gl_MaxVertexUniformVectors = TSymbolUniqueId(1818); + static constexpr const TSymbolUniqueId gl_MaxVertexTextureImageUnits = TSymbolUniqueId(1819); + static constexpr const TSymbolUniqueId gl_MaxCombinedTextureImageUnits = TSymbolUniqueId(1820); + static constexpr const TSymbolUniqueId gl_MaxTextureImageUnits = TSymbolUniqueId(1821); + static constexpr const TSymbolUniqueId gl_MaxFragmentUniformVectors = TSymbolUniqueId(1822); + static constexpr const TSymbolUniqueId gl_MaxVaryingVectors = TSymbolUniqueId(1823); + static constexpr const TSymbolUniqueId gl_MaxDrawBuffers = TSymbolUniqueId(1824); + static constexpr const TSymbolUniqueId gl_MaxDualSourceDrawBuffersEXT = TSymbolUniqueId(1825); + static constexpr const TSymbolUniqueId gl_MaxVertexOutputVectors = TSymbolUniqueId(1826); + static constexpr const TSymbolUniqueId gl_MaxFragmentInputVectors = TSymbolUniqueId(1827); + static constexpr const TSymbolUniqueId gl_MinProgramTexelOffset = TSymbolUniqueId(1828); + static constexpr const TSymbolUniqueId gl_MaxProgramTexelOffset = TSymbolUniqueId(1829); + static constexpr const TSymbolUniqueId gl_MaxImageUnits = TSymbolUniqueId(1830); + static constexpr const TSymbolUniqueId gl_MaxVertexImageUniforms = TSymbolUniqueId(1831); + static constexpr const TSymbolUniqueId gl_MaxFragmentImageUniforms = TSymbolUniqueId(1832); + static constexpr const TSymbolUniqueId gl_MaxComputeImageUniforms = TSymbolUniqueId(1833); + static constexpr const TSymbolUniqueId gl_MaxCombinedImageUniforms = TSymbolUniqueId(1834); static constexpr const TSymbolUniqueId gl_MaxCombinedShaderOutputResources = - TSymbolUniqueId(2152); - static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupCount = TSymbolUniqueId(2153); - static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupSize = TSymbolUniqueId(2154); - static constexpr const TSymbolUniqueId gl_MaxComputeUniformComponents = TSymbolUniqueId(2155); - static constexpr const TSymbolUniqueId gl_MaxComputeTextureImageUnits = TSymbolUniqueId(2156); - static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounters = TSymbolUniqueId(2157); + TSymbolUniqueId(1835); + static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupCount = TSymbolUniqueId(1836); + static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupSize = TSymbolUniqueId(1837); + static constexpr const TSymbolUniqueId gl_MaxComputeUniformComponents = TSymbolUniqueId(1838); + static constexpr const TSymbolUniqueId gl_MaxComputeTextureImageUnits = TSymbolUniqueId(1839); + static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounters = TSymbolUniqueId(1840); static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounterBuffers = - TSymbolUniqueId(2158); - static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounters = TSymbolUniqueId(2159); - static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounters = TSymbolUniqueId(2160); - static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounters = TSymbolUniqueId(2161); - static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBindings = TSymbolUniqueId(2162); - static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounterBuffers = TSymbolUniqueId(2163); + TSymbolUniqueId(1841); + static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounters = TSymbolUniqueId(1842); + static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounters = TSymbolUniqueId(1843); + static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounters = TSymbolUniqueId(1844); + static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBindings = TSymbolUniqueId(1845); + static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounterBuffers = TSymbolUniqueId(1846); static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounterBuffers = - TSymbolUniqueId(2164); + TSymbolUniqueId(1847); static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounterBuffers = - TSymbolUniqueId(2165); - static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBufferSize = TSymbolUniqueId(2166); - static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponents = TSymbolUniqueId(2167); + TSymbolUniqueId(1848); + static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBufferSize = TSymbolUniqueId(1849); + static constexpr const TSymbolUniqueId gl_ShadingRateFlag2VerticalPixelsEXT = + TSymbolUniqueId(1850); + static constexpr const TSymbolUniqueId gl_ShadingRateFlag4VerticalPixelsEXT = + TSymbolUniqueId(1851); + static constexpr const TSymbolUniqueId gl_ShadingRateFlag2HorizontalPixelsEXT = + TSymbolUniqueId(1852); + static constexpr const TSymbolUniqueId gl_ShadingRateFlag4HorizontalPixelsEXT = + TSymbolUniqueId(1853); + static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponents = TSymbolUniqueId(1854); static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponentsES3_2 = - TSymbolUniqueId(2168); - static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponents = TSymbolUniqueId(2169); + TSymbolUniqueId(1855); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponents = TSymbolUniqueId(1856); static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponentsES3_2 = - TSymbolUniqueId(2170); - static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniforms = TSymbolUniqueId(2171); - static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniformsES3_2 = TSymbolUniqueId(2172); - static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnits = TSymbolUniqueId(2173); + TSymbolUniqueId(1857); + static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniforms = TSymbolUniqueId(1858); + static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniformsES3_2 = TSymbolUniqueId(1859); + static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnits = TSymbolUniqueId(1860); static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnitsES3_2 = - TSymbolUniqueId(2174); - static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVertices = TSymbolUniqueId(2175); + TSymbolUniqueId(1861); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVertices = TSymbolUniqueId(1862); static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVerticesES3_2 = - TSymbolUniqueId(2176); + TSymbolUniqueId(1863); static constexpr const TSymbolUniqueId gl_MaxGeometryTotalOutputComponents = - TSymbolUniqueId(2177); + TSymbolUniqueId(1864); static constexpr const TSymbolUniqueId gl_MaxGeometryTotalOutputComponentsES3_2 = - TSymbolUniqueId(2178); - static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponents = TSymbolUniqueId(2179); + TSymbolUniqueId(1865); + static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponents = TSymbolUniqueId(1866); static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponentsES3_2 = - TSymbolUniqueId(2180); - static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounters = TSymbolUniqueId(2181); + TSymbolUniqueId(1867); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounters = TSymbolUniqueId(1868); static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCountersES3_2 = - TSymbolUniqueId(2182); + TSymbolUniqueId(1869); static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounterBuffers = - TSymbolUniqueId(2183); + TSymbolUniqueId(1870); static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounterBuffersES3_2 = - TSymbolUniqueId(2184); - static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponents = TSymbolUniqueId(2185); + TSymbolUniqueId(1871); + static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponents = TSymbolUniqueId(1872); static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponentsES3_2 = - TSymbolUniqueId(2186); + TSymbolUniqueId(1873); static constexpr const TSymbolUniqueId gl_MaxTessControlOutputComponents = - TSymbolUniqueId(2187); + TSymbolUniqueId(1874); static constexpr const TSymbolUniqueId gl_MaxTessControlOutputComponentsES3_2 = - TSymbolUniqueId(2188); + TSymbolUniqueId(1875); static constexpr const TSymbolUniqueId gl_MaxTessControlTextureImageUnits = - TSymbolUniqueId(2189); + TSymbolUniqueId(1876); static constexpr const TSymbolUniqueId gl_MaxTessControlTextureImageUnitsES3_2 = - TSymbolUniqueId(2190); + TSymbolUniqueId(1877); static constexpr const TSymbolUniqueId gl_MaxTessControlUniformComponents = - TSymbolUniqueId(2191); + TSymbolUniqueId(1878); static constexpr const TSymbolUniqueId gl_MaxTessControlUniformComponentsES3_2 = - TSymbolUniqueId(2192); + TSymbolUniqueId(1879); static constexpr const TSymbolUniqueId gl_MaxTessControlTotalOutputComponents = - TSymbolUniqueId(2193); + TSymbolUniqueId(1880); static constexpr const TSymbolUniqueId gl_MaxTessControlTotalOutputComponentsES3_2 = - TSymbolUniqueId(2194); - static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniforms = TSymbolUniqueId(2195); + TSymbolUniqueId(1881); + static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniforms = TSymbolUniqueId(1882); static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniformsES3_2 = - TSymbolUniqueId(2196); - static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounters = TSymbolUniqueId(2197); + TSymbolUniqueId(1883); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounters = TSymbolUniqueId(1884); static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCountersES3_2 = - TSymbolUniqueId(2198); + TSymbolUniqueId(1885); static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounterBuffers = - TSymbolUniqueId(2199); + TSymbolUniqueId(1886); static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounterBuffersES3_2 = - TSymbolUniqueId(2200); - static constexpr const TSymbolUniqueId gl_MaxTessPatchComponents = TSymbolUniqueId(2201); - static constexpr const TSymbolUniqueId gl_MaxTessPatchComponentsES3_2 = TSymbolUniqueId(2202); - static constexpr const TSymbolUniqueId gl_MaxPatchVertices = TSymbolUniqueId(2203); - static constexpr const TSymbolUniqueId gl_MaxPatchVerticesES3_2 = TSymbolUniqueId(2204); - static constexpr const TSymbolUniqueId gl_MaxTessGenLevel = TSymbolUniqueId(2205); - static constexpr const TSymbolUniqueId gl_MaxTessGenLevelES3_2 = TSymbolUniqueId(2206); + TSymbolUniqueId(1887); + static constexpr const TSymbolUniqueId gl_MaxTessPatchComponents = TSymbolUniqueId(1888); + static constexpr const TSymbolUniqueId gl_MaxTessPatchComponentsES3_2 = TSymbolUniqueId(1889); + static constexpr const TSymbolUniqueId gl_MaxPatchVertices = TSymbolUniqueId(1890); + static constexpr const TSymbolUniqueId gl_MaxPatchVerticesES3_2 = TSymbolUniqueId(1891); + static constexpr const TSymbolUniqueId gl_MaxTessGenLevel = TSymbolUniqueId(1892); + static constexpr const TSymbolUniqueId gl_MaxTessGenLevelES3_2 = TSymbolUniqueId(1893); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationInputComponents = - TSymbolUniqueId(2207); + TSymbolUniqueId(1894); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationInputComponentsES3_2 = - TSymbolUniqueId(2208); + TSymbolUniqueId(1895); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationOutputComponents = - TSymbolUniqueId(2209); + TSymbolUniqueId(1896); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationOutputComponentsES3_2 = - TSymbolUniqueId(2210); + TSymbolUniqueId(1897); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationTextureImageUnits = - TSymbolUniqueId(2211); + TSymbolUniqueId(1898); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationTextureImageUnitsES3_2 = - TSymbolUniqueId(2212); + TSymbolUniqueId(1899); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationUniformComponents = - TSymbolUniqueId(2213); + TSymbolUniqueId(1900); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationUniformComponentsES3_2 = - TSymbolUniqueId(2214); + TSymbolUniqueId(1901); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationImageUniforms = - TSymbolUniqueId(2215); + TSymbolUniqueId(1902); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationImageUniformsES3_2 = - TSymbolUniqueId(2216); + TSymbolUniqueId(1903); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounters = - TSymbolUniqueId(2217); + TSymbolUniqueId(1904); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCountersES3_2 = - TSymbolUniqueId(2218); + TSymbolUniqueId(1905); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounterBuffers = - TSymbolUniqueId(2219); + TSymbolUniqueId(1906); static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounterBuffersES3_2 = - TSymbolUniqueId(2220); - static constexpr const TSymbolUniqueId gl_MaxSamples = TSymbolUniqueId(2221); - static constexpr const TSymbolUniqueId gl_MaxSamplesES3_2 = TSymbolUniqueId(2222); - static constexpr const TSymbolUniqueId gl_MaxClipDistancesAPPLE = TSymbolUniqueId(2223); - static constexpr const TSymbolUniqueId gl_MaxClipDistances = TSymbolUniqueId(2224); - static constexpr const TSymbolUniqueId gl_MaxCullDistances = TSymbolUniqueId(2225); + TSymbolUniqueId(1907); + static constexpr const TSymbolUniqueId gl_MaxSamples = TSymbolUniqueId(1908); + static constexpr const TSymbolUniqueId gl_MaxSamplesES3_2 = TSymbolUniqueId(1909); + static constexpr const TSymbolUniqueId gl_MaxClipDistancesAPPLE = TSymbolUniqueId(1910); + static constexpr const TSymbolUniqueId gl_MaxClipDistances = TSymbolUniqueId(1911); + static constexpr const TSymbolUniqueId gl_MaxCullDistances = TSymbolUniqueId(1912); static constexpr const TSymbolUniqueId gl_MaxCombinedClipAndCullDistances = - TSymbolUniqueId(2226); - static constexpr const TSymbolUniqueId gl_FragCoord = TSymbolUniqueId(2227); - static constexpr const TSymbolUniqueId gl_FrontFacing = TSymbolUniqueId(2228); - static constexpr const TSymbolUniqueId gl_PointCoord = TSymbolUniqueId(2229); - static constexpr const TSymbolUniqueId gl_FragColor = TSymbolUniqueId(2230); - static constexpr const TSymbolUniqueId gl_FragData = TSymbolUniqueId(2231); - static constexpr const TSymbolUniqueId gl_FragDepth = TSymbolUniqueId(2232); - static constexpr const TSymbolUniqueId gl_HelperInvocation = TSymbolUniqueId(2233); - static constexpr const TSymbolUniqueId gl_FragCoord300 = TSymbolUniqueId(2234); - static constexpr const TSymbolUniqueId gl_SecondaryFragColorEXT = TSymbolUniqueId(2235); - static constexpr const TSymbolUniqueId gl_SecondaryFragDataEXT = TSymbolUniqueId(2236); - static constexpr const TSymbolUniqueId gl_FragDepthEXT = TSymbolUniqueId(2237); - static constexpr const TSymbolUniqueId gl_LastFragData = TSymbolUniqueId(2238); - static constexpr const TSymbolUniqueId gl_LastFragColor = TSymbolUniqueId(2239); - static constexpr const TSymbolUniqueId gl_LastFragDataNV = TSymbolUniqueId(2240); - static constexpr const TSymbolUniqueId gl_LastFragColorARM = TSymbolUniqueId(2241); - static constexpr const TSymbolUniqueId gl_LastFragDepthARM = TSymbolUniqueId(2242); - static constexpr const TSymbolUniqueId gl_LastFragStencilARM = TSymbolUniqueId(2243); - static constexpr const TSymbolUniqueId gl_PrimitiveID = TSymbolUniqueId(2244); - static constexpr const TSymbolUniqueId gl_PrimitiveIDES3_2 = TSymbolUniqueId(2245); - static constexpr const TSymbolUniqueId gl_Layer = TSymbolUniqueId(2246); - static constexpr const TSymbolUniqueId gl_LayerES3_2 = TSymbolUniqueId(2247); - static constexpr const TSymbolUniqueId gl_SampleID = TSymbolUniqueId(2248); - static constexpr const TSymbolUniqueId gl_SampleIDES3_2 = TSymbolUniqueId(2249); - static constexpr const TSymbolUniqueId gl_SamplePosition = TSymbolUniqueId(2250); - static constexpr const TSymbolUniqueId gl_SamplePositionES3_2 = TSymbolUniqueId(2251); - static constexpr const TSymbolUniqueId gl_SampleMaskIn = TSymbolUniqueId(2252); - static constexpr const TSymbolUniqueId gl_SampleMaskInES3_2 = TSymbolUniqueId(2253); - static constexpr const TSymbolUniqueId gl_SampleMask = TSymbolUniqueId(2254); - static constexpr const TSymbolUniqueId gl_SampleMaskES3_2 = TSymbolUniqueId(2255); - static constexpr const TSymbolUniqueId gl_Position = TSymbolUniqueId(2256); - static constexpr const TSymbolUniqueId gl_PointSize = TSymbolUniqueId(2257); - static constexpr const TSymbolUniqueId gl_InstanceID = TSymbolUniqueId(2258); - static constexpr const TSymbolUniqueId gl_InstanceIndex = TSymbolUniqueId(2259); - static constexpr const TSymbolUniqueId gl_VertexID = TSymbolUniqueId(2260); - static constexpr const TSymbolUniqueId gl_VertexIndex = TSymbolUniqueId(2261); - static constexpr const TSymbolUniqueId gl_LayerVS = TSymbolUniqueId(2262); - static constexpr const TSymbolUniqueId gl_PointSize300 = TSymbolUniqueId(2263); - static constexpr const TSymbolUniqueId gl_DrawID = TSymbolUniqueId(2264); - static constexpr const TSymbolUniqueId gl_BaseVertex = TSymbolUniqueId(2265); - static constexpr const TSymbolUniqueId gl_BaseInstance = TSymbolUniqueId(2266); - static constexpr const TSymbolUniqueId angle_BaseVertex = TSymbolUniqueId(2267); - static constexpr const TSymbolUniqueId angle_BaseInstance = TSymbolUniqueId(2268); - static constexpr const TSymbolUniqueId gl_ClipDistanceAPPLE = TSymbolUniqueId(2269); - static constexpr const TSymbolUniqueId gl_NumWorkGroups = TSymbolUniqueId(2270); - static constexpr const TSymbolUniqueId gl_WorkGroupSize = TSymbolUniqueId(2271); - static constexpr const TSymbolUniqueId gl_WorkGroupID = TSymbolUniqueId(2272); - static constexpr const TSymbolUniqueId gl_LocalInvocationID = TSymbolUniqueId(2273); - static constexpr const TSymbolUniqueId gl_GlobalInvocationID = TSymbolUniqueId(2274); - static constexpr const TSymbolUniqueId gl_LocalInvocationIndex = TSymbolUniqueId(2275); - static constexpr const TSymbolUniqueId gl_PrimitiveIDIn = TSymbolUniqueId(2276); - static constexpr const TSymbolUniqueId gl_PrimitiveIDInES3_2 = TSymbolUniqueId(2277); - static constexpr const TSymbolUniqueId gl_InvocationID = TSymbolUniqueId(2278); - static constexpr const TSymbolUniqueId gl_InvocationIDES3_2 = TSymbolUniqueId(2279); - static constexpr const TSymbolUniqueId gl_PrimitiveIDGS = TSymbolUniqueId(2280); - static constexpr const TSymbolUniqueId gl_PrimitiveIDGSES3_2 = TSymbolUniqueId(2281); - static constexpr const TSymbolUniqueId gl_LayerGS = TSymbolUniqueId(2282); - static constexpr const TSymbolUniqueId gl_LayerGSES3_2 = TSymbolUniqueId(2283); - static constexpr const TSymbolUniqueId gl_PerVertex = TSymbolUniqueId(2284); - static constexpr const TSymbolUniqueId gl_PerVertexES3_2 = TSymbolUniqueId(2285); - static constexpr const TSymbolUniqueId gl_in = TSymbolUniqueId(2286); - static constexpr const TSymbolUniqueId gl_inES3_2 = TSymbolUniqueId(2287); - static constexpr const TSymbolUniqueId gl_PerVertexOutBlock = TSymbolUniqueId(2288); - static constexpr const TSymbolUniqueId gl_PerVertexOutBlockES3_2 = TSymbolUniqueId(2289); - static constexpr const TSymbolUniqueId gl_PositionGS = TSymbolUniqueId(2290); - static constexpr const TSymbolUniqueId gl_PositionGSES3_2 = TSymbolUniqueId(2291); - static constexpr const TSymbolUniqueId gl_PatchVerticesInTCS = TSymbolUniqueId(2292); - static constexpr const TSymbolUniqueId gl_PatchVerticesInTCSES3_2 = TSymbolUniqueId(2293); - static constexpr const TSymbolUniqueId gl_InvocationIDTCS = TSymbolUniqueId(2294); - static constexpr const TSymbolUniqueId gl_InvocationIDTCSES3_2 = TSymbolUniqueId(2295); - static constexpr const TSymbolUniqueId gl_PrimitiveIDTCS = TSymbolUniqueId(2296); - static constexpr const TSymbolUniqueId gl_PrimitiveIDTCSES3_2 = TSymbolUniqueId(2297); - static constexpr const TSymbolUniqueId gl_TessLevelOuterTCS = TSymbolUniqueId(2298); - static constexpr const TSymbolUniqueId gl_TessLevelOuterTCSES3_2 = TSymbolUniqueId(2299); - static constexpr const TSymbolUniqueId gl_TessLevelInnerTCS = TSymbolUniqueId(2300); - static constexpr const TSymbolUniqueId gl_TessLevelInnerTCSES3_2 = TSymbolUniqueId(2301); - static constexpr const TSymbolUniqueId gl_PerVertexTCS = TSymbolUniqueId(2302); - static constexpr const TSymbolUniqueId gl_PerVertexTCSES3_2 = TSymbolUniqueId(2303); - static constexpr const TSymbolUniqueId gl_inTCS = TSymbolUniqueId(2304); - static constexpr const TSymbolUniqueId gl_inTCSES3_2 = TSymbolUniqueId(2305); - static constexpr const TSymbolUniqueId gl_outTCS = TSymbolUniqueId(2306); - static constexpr const TSymbolUniqueId gl_outTCSES3_2 = TSymbolUniqueId(2307); - static constexpr const TSymbolUniqueId gl_BoundingBoxTCS = TSymbolUniqueId(2308); - static constexpr const TSymbolUniqueId gl_BoundingBoxTCSES3_2 = TSymbolUniqueId(2309); - static constexpr const TSymbolUniqueId gl_PerVertexOutTcsBlock = TSymbolUniqueId(2310); - static constexpr const TSymbolUniqueId gl_PerVertexOutTcsBlockES3_2 = TSymbolUniqueId(2311); - static constexpr const TSymbolUniqueId gl_PositionTCS = TSymbolUniqueId(2312); - static constexpr const TSymbolUniqueId gl_PositionTCSES3_2 = TSymbolUniqueId(2313); - static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCS = TSymbolUniqueId(2314); - static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCSES3_2 = TSymbolUniqueId(2315); - static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCS = TSymbolUniqueId(2316); - static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCSES3_2 = TSymbolUniqueId(2317); - static constexpr const TSymbolUniqueId gl_PatchVerticesInTES = TSymbolUniqueId(2318); - static constexpr const TSymbolUniqueId gl_PatchVerticesInTESES3_2 = TSymbolUniqueId(2319); - static constexpr const TSymbolUniqueId gl_PrimitiveIDTES = TSymbolUniqueId(2320); - static constexpr const TSymbolUniqueId gl_PrimitiveIDTESES3_2 = TSymbolUniqueId(2321); - static constexpr const TSymbolUniqueId gl_TessCoord = TSymbolUniqueId(2322); - static constexpr const TSymbolUniqueId gl_TessLevelOuterTES = TSymbolUniqueId(2323); - static constexpr const TSymbolUniqueId gl_TessLevelOuterTESES3_2 = TSymbolUniqueId(2324); - static constexpr const TSymbolUniqueId gl_TessLevelInnerTES = TSymbolUniqueId(2325); - static constexpr const TSymbolUniqueId gl_TessLevelInnerTESES3_2 = TSymbolUniqueId(2326); - static constexpr const TSymbolUniqueId gl_PerVertexTES = TSymbolUniqueId(2327); - static constexpr const TSymbolUniqueId gl_PerVertexTESES3_2 = TSymbolUniqueId(2328); - static constexpr const TSymbolUniqueId gl_inTES = TSymbolUniqueId(2329); - static constexpr const TSymbolUniqueId gl_inTESES3_2 = TSymbolUniqueId(2330); - static constexpr const TSymbolUniqueId gl_outTES = TSymbolUniqueId(2331); - static constexpr const TSymbolUniqueId gl_outTESES3_2 = TSymbolUniqueId(2332); - static constexpr const TSymbolUniqueId gl_PerVertexOutTesBlock = TSymbolUniqueId(2333); - static constexpr const TSymbolUniqueId gl_PerVertexOutTesBlockES3_2 = TSymbolUniqueId(2334); - static constexpr const TSymbolUniqueId gl_PositionTES = TSymbolUniqueId(2335); - static constexpr const TSymbolUniqueId gl_PositionTESES3_2 = TSymbolUniqueId(2336); - static constexpr const TSymbolUniqueId gl_ViewID_OVR = TSymbolUniqueId(2337); - static constexpr const TSymbolUniqueId gl_ClipDistance = TSymbolUniqueId(2338); - static constexpr const TSymbolUniqueId gl_CullDistance = TSymbolUniqueId(2339); + TSymbolUniqueId(1913); + static constexpr const TSymbolUniqueId gl_FragCoord = TSymbolUniqueId(1914); + static constexpr const TSymbolUniqueId gl_FrontFacing = TSymbolUniqueId(1915); + static constexpr const TSymbolUniqueId gl_PointCoord = TSymbolUniqueId(1916); + static constexpr const TSymbolUniqueId gl_FragColor = TSymbolUniqueId(1917); + static constexpr const TSymbolUniqueId gl_FragData = TSymbolUniqueId(1918); + static constexpr const TSymbolUniqueId gl_FragDepth = TSymbolUniqueId(1919); + static constexpr const TSymbolUniqueId gl_HelperInvocation = TSymbolUniqueId(1920); + static constexpr const TSymbolUniqueId gl_FragCoord300 = TSymbolUniqueId(1921); + static constexpr const TSymbolUniqueId gl_SecondaryFragColorEXT = TSymbolUniqueId(1922); + static constexpr const TSymbolUniqueId gl_SecondaryFragDataEXT = TSymbolUniqueId(1923); + static constexpr const TSymbolUniqueId gl_FragDepthEXT = TSymbolUniqueId(1924); + static constexpr const TSymbolUniqueId gl_LastFragData = TSymbolUniqueId(1925); + static constexpr const TSymbolUniqueId gl_LastFragColorARM = TSymbolUniqueId(1926); + static constexpr const TSymbolUniqueId gl_LastFragDepthARM = TSymbolUniqueId(1927); + static constexpr const TSymbolUniqueId gl_LastFragStencilARM = TSymbolUniqueId(1928); + static constexpr const TSymbolUniqueId gl_PrimitiveID = TSymbolUniqueId(1929); + static constexpr const TSymbolUniqueId gl_PrimitiveIDES3_2 = TSymbolUniqueId(1930); + static constexpr const TSymbolUniqueId gl_Layer = TSymbolUniqueId(1931); + static constexpr const TSymbolUniqueId gl_LayerES3_2 = TSymbolUniqueId(1932); + static constexpr const TSymbolUniqueId gl_ShadingRateEXT = TSymbolUniqueId(1933); + static constexpr const TSymbolUniqueId gl_SampleID = TSymbolUniqueId(1934); + static constexpr const TSymbolUniqueId gl_SampleIDES3_2 = TSymbolUniqueId(1935); + static constexpr const TSymbolUniqueId gl_SamplePosition = TSymbolUniqueId(1936); + static constexpr const TSymbolUniqueId gl_SamplePositionES3_2 = TSymbolUniqueId(1937); + static constexpr const TSymbolUniqueId gl_SampleMaskIn = TSymbolUniqueId(1938); + static constexpr const TSymbolUniqueId gl_SampleMaskInES3_2 = TSymbolUniqueId(1939); + static constexpr const TSymbolUniqueId gl_SampleMask = TSymbolUniqueId(1940); + static constexpr const TSymbolUniqueId gl_SampleMaskES3_2 = TSymbolUniqueId(1941); + static constexpr const TSymbolUniqueId gl_Position = TSymbolUniqueId(1942); + static constexpr const TSymbolUniqueId gl_PointSize = TSymbolUniqueId(1943); + static constexpr const TSymbolUniqueId gl_InstanceID = TSymbolUniqueId(1944); + static constexpr const TSymbolUniqueId gl_InstanceIndex = TSymbolUniqueId(1945); + static constexpr const TSymbolUniqueId gl_VertexID = TSymbolUniqueId(1946); + static constexpr const TSymbolUniqueId gl_VertexIndex = TSymbolUniqueId(1947); + static constexpr const TSymbolUniqueId gl_LayerVS = TSymbolUniqueId(1948); + static constexpr const TSymbolUniqueId gl_PointSize300 = TSymbolUniqueId(1949); + static constexpr const TSymbolUniqueId gl_DrawID = TSymbolUniqueId(1950); + static constexpr const TSymbolUniqueId gl_BaseVertex = TSymbolUniqueId(1951); + static constexpr const TSymbolUniqueId gl_BaseInstance = TSymbolUniqueId(1952); + static constexpr const TSymbolUniqueId gl_ClipDistanceAPPLE = TSymbolUniqueId(1953); + static constexpr const TSymbolUniqueId gl_PrimitiveShadingRateEXT = TSymbolUniqueId(1954); + static constexpr const TSymbolUniqueId gl_NumWorkGroups = TSymbolUniqueId(1955); + static constexpr const TSymbolUniqueId gl_WorkGroupSize = TSymbolUniqueId(1956); + static constexpr const TSymbolUniqueId gl_WorkGroupID = TSymbolUniqueId(1957); + static constexpr const TSymbolUniqueId gl_LocalInvocationID = TSymbolUniqueId(1958); + static constexpr const TSymbolUniqueId gl_GlobalInvocationID = TSymbolUniqueId(1959); + static constexpr const TSymbolUniqueId gl_LocalInvocationIndex = TSymbolUniqueId(1960); + static constexpr const TSymbolUniqueId gl_PositionGS = TSymbolUniqueId(1961); + static constexpr const TSymbolUniqueId gl_PositionGSES3_2 = TSymbolUniqueId(1962); + static constexpr const TSymbolUniqueId gl_PrimitiveIDIn = TSymbolUniqueId(1963); + static constexpr const TSymbolUniqueId gl_PrimitiveIDInES3_2 = TSymbolUniqueId(1964); + static constexpr const TSymbolUniqueId gl_InvocationID = TSymbolUniqueId(1965); + static constexpr const TSymbolUniqueId gl_InvocationIDES3_2 = TSymbolUniqueId(1966); + static constexpr const TSymbolUniqueId gl_PrimitiveIDGS = TSymbolUniqueId(1967); + static constexpr const TSymbolUniqueId gl_PrimitiveIDGSES3_2 = TSymbolUniqueId(1968); + static constexpr const TSymbolUniqueId gl_LayerGS = TSymbolUniqueId(1969); + static constexpr const TSymbolUniqueId gl_LayerGSES3_2 = TSymbolUniqueId(1970); + static constexpr const TSymbolUniqueId gl_PerVertex = TSymbolUniqueId(1971); + static constexpr const TSymbolUniqueId gl_PerVertexES3_2 = TSymbolUniqueId(1972); + static constexpr const TSymbolUniqueId gl_in = TSymbolUniqueId(1973); + static constexpr const TSymbolUniqueId gl_inES3_2 = TSymbolUniqueId(1974); + static constexpr const TSymbolUniqueId gl_PrimitiveShadingRateEXTGS = TSymbolUniqueId(1975); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTCS = TSymbolUniqueId(1976); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTCSES3_2 = TSymbolUniqueId(1977); + static constexpr const TSymbolUniqueId gl_InvocationIDTCS = TSymbolUniqueId(1978); + static constexpr const TSymbolUniqueId gl_InvocationIDTCSES3_2 = TSymbolUniqueId(1979); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTCS = TSymbolUniqueId(1980); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTCSES3_2 = TSymbolUniqueId(1981); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTCS = TSymbolUniqueId(1982); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTCSES3_2 = TSymbolUniqueId(1983); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTCS = TSymbolUniqueId(1984); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTCSES3_2 = TSymbolUniqueId(1985); + static constexpr const TSymbolUniqueId gl_PerVertexTCS = TSymbolUniqueId(1986); + static constexpr const TSymbolUniqueId gl_PerVertexTCSES3_2 = TSymbolUniqueId(1987); + static constexpr const TSymbolUniqueId gl_inTCS = TSymbolUniqueId(1988); + static constexpr const TSymbolUniqueId gl_inTCSES3_2 = TSymbolUniqueId(1989); + static constexpr const TSymbolUniqueId gl_outTCS = TSymbolUniqueId(1990); + static constexpr const TSymbolUniqueId gl_outTCSES3_2 = TSymbolUniqueId(1991); + static constexpr const TSymbolUniqueId gl_BoundingBoxTCS = TSymbolUniqueId(1992); + static constexpr const TSymbolUniqueId gl_BoundingBoxTCSES3_2 = TSymbolUniqueId(1993); + static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCS = TSymbolUniqueId(1994); + static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCSES3_2 = TSymbolUniqueId(1995); + static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCS = TSymbolUniqueId(1996); + static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCSES3_2 = TSymbolUniqueId(1997); + static constexpr const TSymbolUniqueId gl_PositionTES = TSymbolUniqueId(1998); + static constexpr const TSymbolUniqueId gl_PositionTESES3_2 = TSymbolUniqueId(1999); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTES = TSymbolUniqueId(2000); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTESES3_2 = TSymbolUniqueId(2001); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTES = TSymbolUniqueId(2002); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTESES3_2 = TSymbolUniqueId(2003); + static constexpr const TSymbolUniqueId gl_TessCoord = TSymbolUniqueId(2004); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTES = TSymbolUniqueId(2005); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTESES3_2 = TSymbolUniqueId(2006); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTES = TSymbolUniqueId(2007); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTESES3_2 = TSymbolUniqueId(2008); + static constexpr const TSymbolUniqueId gl_PerVertexTES = TSymbolUniqueId(2009); + static constexpr const TSymbolUniqueId gl_PerVertexTESES3_2 = TSymbolUniqueId(2010); + static constexpr const TSymbolUniqueId gl_inTES = TSymbolUniqueId(2011); + static constexpr const TSymbolUniqueId gl_inTESES3_2 = TSymbolUniqueId(2012); + static constexpr const TSymbolUniqueId gl_ViewID_OVR = TSymbolUniqueId(2013); + static constexpr const TSymbolUniqueId gl_ClipDistance = TSymbolUniqueId(2014); + static constexpr const TSymbolUniqueId gl_CullDistance = TSymbolUniqueId(2015); }; // class BuiltInId namespace BuiltInVariable { -const TVariable *angle_BaseInstance(); -const TVariable *angle_BaseVertex(); const TVariable *gl_BaseInstance(); const TVariable *gl_BaseVertex(); const TVariable *gl_DrawID(); @@ -3742,6 +3111,7 @@ const TVariable *gl_FragColor(); const TVariable *gl_FragCoord(); const TVariable *gl_FragCoord300(); const TVariable *gl_FragDepth(); +const TVariable *gl_FragDepthEXT(); const TVariable *gl_FrontFacing(); const TVariable *gl_GlobalInvocationID(); const TVariable *gl_HelperInvocation(); @@ -3751,7 +3121,6 @@ const TVariable *gl_InvocationID(); const TVariable *gl_InvocationIDES3_2(); const TVariable *gl_InvocationIDTCS(); const TVariable *gl_InvocationIDTCSES3_2(); -const TVariable *gl_LastFragColor(); const TVariable *gl_LastFragColorARM(); const TVariable *gl_LastFragDepthARM(); const TVariable *gl_LastFragStencilARM(); @@ -3773,6 +3142,10 @@ const TVariable *gl_PointCoord(); const TVariable *gl_PointSize(); const TVariable *gl_PointSize300(); const TVariable *gl_Position(); +const TVariable *gl_PositionGS(); +const TVariable *gl_PositionGSES3_2(); +const TVariable *gl_PositionTES(); +const TVariable *gl_PositionTESES3_2(); const TVariable *gl_PrimitiveID(); const TVariable *gl_PrimitiveIDES3_2(); const TVariable *gl_PrimitiveIDGS(); @@ -3783,11 +3156,14 @@ const TVariable *gl_PrimitiveIDTCS(); const TVariable *gl_PrimitiveIDTCSES3_2(); const TVariable *gl_PrimitiveIDTES(); const TVariable *gl_PrimitiveIDTESES3_2(); +const TVariable *gl_PrimitiveShadingRateEXT(); +const TVariable *gl_PrimitiveShadingRateEXTGS(); const TVariable *gl_SampleID(); const TVariable *gl_SampleIDES3_2(); const TVariable *gl_SamplePosition(); const TVariable *gl_SamplePositionES3_2(); const TVariable *gl_SecondaryFragColorEXT(); +const TVariable *gl_ShadingRateEXT(); const TVariable *gl_TessCoord(); const TVariable *gl_VertexID(); const TVariable *gl_VertexIndex(); diff --git a/src/compiler/translator/tree_util/DriverUniform.cpp b/src/compiler/translator/tree_util/DriverUniform.cpp index 9c8fa93c88d..2cd7df646a9 100644 --- a/src/compiler/translator/tree_util/DriverUniform.cpp +++ b/src/compiler/translator/tree_util/DriverUniform.cpp @@ -14,7 +14,6 @@ #include "compiler/translator/SymbolTable.h" #include "compiler/translator/tree_util/FindMain.h" #include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/util.h" namespace sh @@ -22,9 +21,6 @@ namespace sh namespace { -constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams"); -constexpr ImmutableString kDriverUniformsBlockName = ImmutableString("ANGLEUniformBlock"); -constexpr ImmutableString kDriverUniformsVarName = ImmutableString("ANGLEUniforms"); constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets"; constexpr const char kDepthRange[] = "depthRange"; @@ -69,9 +65,11 @@ bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbol layoutQualifier.blockStorage = EbsStd140; layoutQualifier.pushConstant = true; - mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, - layoutQualifier, TMemoryQualifier::Create(), 0, - kDriverUniformsBlockName, kDriverUniformsVarName); + const TInterfaceBlock *interfaceBlock = DeclareInterfaceBlock( + symbolTable, driverFieldList, layoutQualifier, kDriverUniformsBlockName); + mDriverUniforms = DeclareInterfaceBlockVariable(root, symbolTable, EvqUniform, interfaceBlock, + layoutQualifier, TMemoryQualifier::Create(), 0, + kDriverUniformsVarName); return mDriverUniforms != nullptr; } @@ -170,9 +168,11 @@ bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbo layoutQualifier.blockStorage = EbsStd140; layoutQualifier.pushConstant = true; - mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, - layoutQualifier, TMemoryQualifier::Create(), 0, - kDriverUniformsBlockName, kDriverUniformsVarName); + const TInterfaceBlock *interfaceBlock = DeclareInterfaceBlock( + symbolTable, driverFieldList, layoutQualifier, kDriverUniformsBlockName); + mDriverUniforms = DeclareInterfaceBlockVariable( + root, symbolTable, EvqUniform, interfaceBlock, layoutQualifier, + TMemoryQualifier::Create(), 0, kDriverUniformsVarName); } else { diff --git a/src/compiler/translator/tree_util/DriverUniform.h b/src/compiler/translator/tree_util/DriverUniform.h index d7d5ab93bfe..eb32675d31a 100644 --- a/src/compiler/translator/tree_util/DriverUniform.h +++ b/src/compiler/translator/tree_util/DriverUniform.h @@ -43,6 +43,10 @@ enum class DriverUniformFlip PreFragment, }; +constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams"); +constexpr ImmutableString kDriverUniformsBlockName = ImmutableString("ANGLEUniformBlock"); +constexpr ImmutableString kDriverUniformsVarName = ImmutableString("ANGLEUniforms"); + class DriverUniform { public: diff --git a/src/compiler/translator/tree_util/FindMain.cpp b/src/compiler/translator/tree_util/FindMain.cpp index 833948602a0..e9358493164 100644 --- a/src/compiler/translator/tree_util/FindMain.cpp +++ b/src/compiler/translator/tree_util/FindMain.cpp @@ -42,6 +42,19 @@ TIntermFunctionDefinition *FindMain(TIntermBlock *root) return nullptr; } +TIntermFunctionPrototype *FindMainPrototype(TIntermBlock *root) +{ + for (TIntermNode *node : *root->getSequence()) + { + TIntermFunctionPrototype *nodePrototype = node->getAsFunctionPrototypeNode(); + if (nodePrototype != nullptr && nodePrototype->getFunction()->isMain()) + { + return nodePrototype; + } + } + return nullptr; +} + TIntermBlock *FindMainBody(TIntermBlock *root) { TIntermFunctionDefinition *main = FindMain(root); diff --git a/src/compiler/translator/tree_util/FindMain.h b/src/compiler/translator/tree_util/FindMain.h index bbdcbe978a5..c0e5ff48ac7 100644 --- a/src/compiler/translator/tree_util/FindMain.h +++ b/src/compiler/translator/tree_util/FindMain.h @@ -15,9 +15,11 @@ namespace sh { class TIntermBlock; class TIntermFunctionDefinition; +class TIntermFunctionPrototype; size_t FindMainIndex(TIntermBlock *root); TIntermFunctionDefinition *FindMain(TIntermBlock *root); +TIntermFunctionPrototype *FindMainPrototype(TIntermBlock *root); TIntermBlock *FindMainBody(TIntermBlock *root); } // namespace sh diff --git a/src/compiler/translator/tree_util/FindPreciseNodes.cpp b/src/compiler/translator/tree_util/FindPreciseNodes.cpp index c5ecd182402..877f1e28336 100644 --- a/src/compiler/translator/tree_util/FindPreciseNodes.cpp +++ b/src/compiler/translator/tree_util/FindPreciseNodes.cpp @@ -18,10 +18,12 @@ #include "common/hash_containers.h" #include "common/hash_utils.h" +#include "common/span.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/IntermNode.h" #include "compiler/translator/Symbol.h" #include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" namespace sh { @@ -62,20 +64,6 @@ class AccessChain TVector mChain; }; -bool IsIndexOp(TOperator op) -{ - switch (op) - { - case EOpIndexDirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - case EOpIndexIndirect: - return true; - default: - return false; - } -} - const TVariable *AccessChain::build(TIntermTyped *lvalue) { if (lvalue->getAsSwizzleNode()) @@ -186,20 +174,18 @@ struct ObjectAndAccessChain bool operator==(const ObjectAndAccessChain &a, const ObjectAndAccessChain &b) { - return a.variable == b.variable && a.accessChain == b.accessChain; + return a.variable->uniqueId() == b.variable->uniqueId() && a.accessChain == b.accessChain; } struct ObjectAndAccessChainHash { size_t operator()(const ObjectAndAccessChain &object) const { - size_t result = angle::ComputeGenericHash(&object.variable, sizeof(object.variable)); + size_t result = angle::ComputeGenericHash(angle::byte_span_from_ref(object.variable)); if (!object.accessChain.getChain().empty()) { - result = - result ^ angle::ComputeGenericHash(object.accessChain.getChain().data(), - object.accessChain.getChain().size() * - sizeof(object.accessChain.getChain()[0])); + result = result ^ + angle::ComputeGenericHash(angle::as_byte_span(object.accessChain.getChain())); } return result; } diff --git a/src/compiler/translator/tree_util/IntermNode_util.cpp b/src/compiler/translator/tree_util/IntermNode_util.cpp index de137c62663..7b9e39e2ce6 100644 --- a/src/compiler/translator/tree_util/IntermNode_util.cpp +++ b/src/compiler/translator/tree_util/IntermNode_util.cpp @@ -6,10 +6,19 @@ // IntermNode_util.cpp: High-level utilities for creating AST nodes and node hierarchies. Mostly // meant to be used in AST transforms. +#include "compiler/translator/util.h" +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/FunctionLookup.h" +#include "compiler/translator/Name.h" +#include "compiler/translator/Symbol.h" #include "compiler/translator/SymbolTable.h" +#include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/Types.h" namespace sh { @@ -186,6 +195,15 @@ TIntermConstantUnion *CreateBoolNode(bool value) return new TIntermConstantUnion(u, type); } +TIntermConstantUnion *CreateYuvCscNode(TYuvCscStandardEXT value) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setYuvCscStandardEXTConst(value); + + TType type(EbtYuvCscStandardEXT, EbpUndefined, EvqConst, 1); + return new TIntermConstantUnion(u, type); +} + TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type) { ASSERT(symbolTable != nullptr); @@ -304,21 +322,27 @@ std::pair DeclareStructure( return {typeVar, instanceVar}; } -const TVariable *DeclareInterfaceBlock(TIntermBlock *root, - TSymbolTable *symbolTable, +TInterfaceBlock *DeclareInterfaceBlock(TSymbolTable *symbolTable, TFieldList *fieldList, - TQualifier qualifier, const TLayoutQualifier &layoutQualifier, - const TMemoryQualifier &memoryQualifier, - uint32_t arraySize, - const ImmutableString &blockTypeName, - const ImmutableString &blockVariableName) + const ImmutableString &blockTypeName) { // Define an interface block. TInterfaceBlock *interfaceBlock = new TInterfaceBlock( symbolTable, blockTypeName, fieldList, layoutQualifier, SymbolType::AngleInternal); - // Turn the inteface block into a declaration. + return interfaceBlock; +} + +const TVariable *DeclareInterfaceBlockVariable(TIntermBlock *root, + TSymbolTable *symbolTable, + TQualifier qualifier, + const TInterfaceBlock *interfaceBlock, + const TLayoutQualifier &layoutQualifier, + const TMemoryQualifier &memoryQualifier, + const uint32_t arraySize, + const ImmutableString &blockVariableName) +{ TType *interfaceBlockType = new TType(interfaceBlock, qualifier, layoutQualifier); interfaceBlockType->setMemoryQualifier(memoryQualifier); if (arraySize > 0) @@ -343,6 +367,96 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root, return interfaceBlockVar; } +const TVariable *FindRootVariable(TIntermNode *expr) +{ + if (TIntermBinary *binNode = expr->getAsBinaryNode()) + { + return FindRootVariable(binNode->getLeft()); + } + if (TIntermSwizzle *swizzle = expr->getAsSwizzleNode()) + { + return FindRootVariable(swizzle->getOperand()); + } + + TIntermSymbol *sym = expr->getAsSymbolNode(); + ASSERT(sym); + return &sym->variable(); +} + +const TVariable &CreateStructTypeVariable(TSymbolTable &symbolTable, const TStructure &structure) +{ + TType *type = new TType(&structure, true); + TVariable *var = new TVariable(&symbolTable, ImmutableString(""), type, SymbolType::Empty); + return *var; +} + +const TVariable &CreateInstanceVariable(TSymbolTable &symbolTable, + const TStructure &structure, + const Name &name, + TQualifier qualifier, + const angle::Span *arraySizes) +{ + TType *type = new TType(&structure, false); + type->setQualifier(qualifier); + if (arraySizes) + { + type->makeArrays(*arraySizes); + } + TVariable *var = new TVariable(&symbolTable, name.rawName(), type, name.symbolType()); + return *var; +} + +TIntermBinary &AccessField(const TVariable &structInstanceVar, const Name &name) +{ + return AccessField(*new TIntermSymbol(&structInstanceVar), name); +} + +TIntermBinary &AccessField(TIntermTyped &object, const Name &name) +{ + const TStructure *structure = object.getType().getStruct(); + ASSERT(structure); + const TFieldList &fieldList = structure->fields(); + for (int i = 0; i < static_cast(fieldList.size()); ++i) + { + TField *current = fieldList[i]; + if (Name(*current) == name) + { + return AccessFieldByIndex(object, i); + } + } + UNREACHABLE(); + return AccessFieldByIndex(object, -1); +} + +TIntermBinary &AccessFieldByIndex(TIntermTyped &object, int index) +{ + const TType &type = object.getType(); + ASSERT(!type.isArray()); + const TStructure *structure = type.getStruct(); + ASSERT(structure); + + ASSERT(0 <= index); + ASSERT(static_cast(index) < structure->fields().size()); + + return *new TIntermBinary( + TOperator::EOpIndexDirectStruct, &object, + new TIntermConstantUnion(new TConstantUnion(index), *new TType(TBasicType::EbtInt))); +} + +TIntermBinary *AccessFieldOfNamedInterfaceBlock(const TVariable *object, int index) +{ + ASSERT(object->getType().getInterfaceBlock()); + const TFieldList &fieldList = object->getType().getInterfaceBlock()->fields(); + + ASSERT(0 <= index); + ASSERT(static_cast(index) < fieldList.size()); + + ASSERT(object->symbolType() != SymbolType::Empty); + + return new TIntermBinary(TOperator::EOpIndexDirectInterfaceBlock, new TIntermSymbol(object), + CreateIndexNode(index)); +} + TIntermBlock *EnsureBlock(TIntermNode *node) { if (node == nullptr) @@ -446,4 +560,16 @@ bool EndsInBranch(TIntermBlock *block) return false; } +TIntermNode *CastScalar(const TType &type, TIntermTyped *scalar) +{ + const TBasicType basicType = type.getBasicType(); + if (scalar->getType().getBasicType() == basicType) + { + return scalar; + } + + TType castDestType(basicType, type.getPrecision()); + return TIntermAggregate::CreateConstructor(castDestType, {scalar}); +} + } // namespace sh diff --git a/src/compiler/translator/tree_util/IntermNode_util.h b/src/compiler/translator/tree_util/IntermNode_util.h index 71b46ebe4fa..95329daf27c 100644 --- a/src/compiler/translator/tree_util/IntermNode_util.h +++ b/src/compiler/translator/tree_util/IntermNode_util.h @@ -9,7 +9,10 @@ #ifndef COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ #define COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ +#include + #include "compiler/translator/IntermNode.h" +#include "compiler/translator/Name.h" #include "compiler/translator/tree_util/FindFunction.h" namespace sh @@ -33,6 +36,7 @@ TIntermConstantUnion *CreateUVecNode(const unsigned int values[], TIntermConstantUnion *CreateIndexNode(int index); TIntermConstantUnion *CreateUIntNode(unsigned int value); TIntermConstantUnion *CreateBoolNode(bool value); +TIntermConstantUnion *CreateYuvCscNode(TYuvCscStandardEXT value); // Create temporary variable of known type |type|. TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type); @@ -64,15 +68,52 @@ std::pair DeclareStructure( uint32_t arraySize, const ImmutableString &structTypeName, const ImmutableString *structInstanceName); -const TVariable *DeclareInterfaceBlock(TIntermBlock *root, - TSymbolTable *symbolTable, +TInterfaceBlock *DeclareInterfaceBlock(TSymbolTable *symbolTable, TFieldList *fieldList, - TQualifier qualifier, const TLayoutQualifier &layoutQualifier, - const TMemoryQualifier &memoryQualifier, - uint32_t arraySize, - const ImmutableString &blockTypeName, - const ImmutableString &blockVariableName); + const ImmutableString &blockTypeName); + +const TVariable *DeclareInterfaceBlockVariable(TIntermBlock *root, + TSymbolTable *symbolTable, + TQualifier qualifier, + const TInterfaceBlock *interfaceBlock, + const TLayoutQualifier &layoutQualifier, + const TMemoryQualifier &memoryQualifier, + uint32_t arraySize, + const ImmutableString &blockVariableName); + +// `expr` must be an lvalue. This will return the root variable, e.g. the root variable of +// `a[0].b[0].xy` is `a`, +const TVariable *FindRootVariable(TIntermNode *expr); + +// Creates a variable for a struct type. +const TVariable &CreateStructTypeVariable(TSymbolTable &symbolTable, const TStructure &structure); + +// Creates a variable for a struct instance. +const TVariable &CreateInstanceVariable( + TSymbolTable &symbolTable, + const TStructure &structure, + const Name &name, + TQualifier qualifier = TQualifier::EvqTemporary, + const angle::Span *arraySizes = nullptr); + +// Accesses a field for the given node with the given field name. +// The node must be a struct instance. +TIntermBinary &AccessField(const TVariable &structInstanceVar, const Name &field); + +// Accesses a field for the given node with the given field name. +// The node must be a struct instance. +TIntermBinary &AccessField(TIntermTyped &object, const Name &field); + +// Accesses a field for the given node by its field index. +// The node must be a struct instance. +TIntermBinary &AccessFieldByIndex(TIntermTyped &object, int index); + +// Accesses `object` by index, returning a binary referencing the field of the named interface +// block. +// Note: nameless interface blocks' fields are represented by individual TVariables, and so this +// helper cannot generate an access to them. +TIntermBinary *AccessFieldOfNamedInterfaceBlock(const TVariable *object, int index); // If the input node is nullptr, return nullptr. // If the input node is a block node, return it. @@ -105,10 +146,10 @@ TIntermTyped *CreateBuiltInUnaryFunctionCallNode(const char *name, const TSymbolTable &symbolTable, int shaderVersion); -inline void GetSwizzleIndex(TVector *indexOut) {} +inline void GetSwizzleIndex(TVector *indexOut) {} template -void GetSwizzleIndex(TVector *indexOut, T arg, ArgsT... args) +void GetSwizzleIndex(TVector *indexOut, T arg, ArgsT... args) { indexOut->push_back(arg); GetSwizzleIndex(indexOut, args...); @@ -117,7 +158,7 @@ void GetSwizzleIndex(TVector *indexOut, T arg, ArgsT... args) template TIntermSwizzle *CreateSwizzle(TIntermTyped *reference, ArgsT... args) { - TVector swizzleIndex; + TVector swizzleIndex; GetSwizzleIndex(&swizzleIndex, args...); return new TIntermSwizzle(reference, swizzleIndex); } @@ -128,6 +169,9 @@ TIntermSwizzle *CreateSwizzle(TIntermTyped *reference, ArgsT... args) // branch. bool EndsInBranch(TIntermBlock *block); +// Cast a scalar to the basic type of type. No-ops if scalar is already the right type. +TIntermNode *CastScalar(const TType &type, TIntermTyped *scalar); + } // namespace sh #endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ diff --git a/src/compiler/translator/tree_util/ReplaceVariable.cpp b/src/compiler/translator/tree_util/ReplaceVariable.cpp index 697cfe6c74c..11a4dd0d979 100644 --- a/src/compiler/translator/tree_util/ReplaceVariable.cpp +++ b/src/compiler/translator/tree_util/ReplaceVariable.cpp @@ -29,7 +29,7 @@ class ReplaceVariableTraverser : public TIntermTraverser void visitSymbol(TIntermSymbol *node) override { - if (&node->variable() == mToBeReplaced) + if (node->variable().uniqueId() == mToBeReplaced->uniqueId()) { queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED); } @@ -49,7 +49,7 @@ class ReplaceVariablesTraverser : public TIntermTraverser void visitSymbol(TIntermSymbol *node) override { - auto iter = mVariableMap.find(&node->variable()); + auto iter = mVariableMap.find(node->variable().uniqueId()); if (iter != mVariableMap.end()) { queueReplacement(iter->second->deepCopy(), OriginalNode::IS_DROPPED); @@ -86,12 +86,12 @@ class GetDeclaratorReplacementsTraverser : public TIntermTraverser ASSERT(asSymbol); const TVariable &variable = asSymbol->variable(); - ASSERT(mVariableMap->find(&variable) == mVariableMap->end()); + ASSERT(mVariableMap->find(variable.uniqueId()) == mVariableMap->end()); const TVariable *replacementVariable = new TVariable( mSymbolTable, variable.name(), &variable.getType(), variable.symbolType()); - (*mVariableMap)[&variable] = new TIntermSymbol(replacementVariable); + (*mVariableMap)[variable.uniqueId()] = new TIntermSymbol(replacementVariable); } return false; @@ -109,13 +109,14 @@ class GetDeclaratorReplacementsTraverser : public TIntermTraverser const TVariable *toBeReplaced, const TVariable *replacement) { + ASSERT(toBeReplaced && replacement); ReplaceVariableTraverser traverser(toBeReplaced, new TIntermSymbol(replacement)); root->traverse(&traverser); return traverser.updateTree(compiler, root); } [[nodiscard]] bool ReplaceVariables(TCompiler *compiler, - TIntermBlock *root, + TIntermNode *root, const VariableReplacementMap &variableMap) { ReplaceVariablesTraverser traverser(variableMap); @@ -137,6 +138,7 @@ void GetDeclaratorReplacements(TSymbolTable *symbolTable, const TVariable *toBeReplaced, const TIntermTyped *replacement) { + ASSERT(toBeReplaced && replacement); ReplaceVariableTraverser traverser(toBeReplaced, replacement); root->traverse(&traverser); return traverser.updateTree(compiler, root); diff --git a/src/compiler/translator/tree_util/ReplaceVariable.h b/src/compiler/translator/tree_util/ReplaceVariable.h index b8f300912e9..fe8371a103e 100644 --- a/src/compiler/translator/tree_util/ReplaceVariable.h +++ b/src/compiler/translator/tree_util/ReplaceVariable.h @@ -18,7 +18,9 @@ namespace sh class TCompiler; class TIntermBlock; class TIntermTyped; +class TIntermNode; class TSymbolTable; +class TSymbolUniqueId; class TVariable; [[nodiscard]] bool ReplaceVariable(TCompiler *compiler, @@ -30,11 +32,11 @@ class TVariable; const TVariable *toBeReplaced, const TIntermTyped *replacement); -using VariableReplacementMap = angle::HashMap; +using VariableReplacementMap = angle::HashMap; // Replace a set of variables with their corresponding expression. [[nodiscard]] bool ReplaceVariables(TCompiler *compiler, - TIntermBlock *root, + TIntermNode *root, const VariableReplacementMap &variableMap); // Find all declarators, and replace the TVariable they are declaring with a duplicate. This is diff --git a/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp b/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp index daf99185ab2..e2039ab858f 100644 --- a/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp +++ b/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp @@ -104,6 +104,17 @@ void WrapMainAndAppend(TIntermBlock *root, TIntermFunctionDefinition *newMainDefinition = new TIntermFunctionDefinition(newMainProto, newMainBody); root->appendStatement(newMainDefinition); + + // If a function prototype of main() also exists, it will need to be replaced. Otherwise it will + // continue to internally reference the TFunction of the replaced 'main' function definition. + TIntermFunctionPrototype *oldMainProto = FindMainPrototype(root); + if (oldMainProto) + { + // Replace the prototype node but initialize it with the newMain TFunction; now this newly + // created main() prototype will reference the new TFunction of newMain. + newMainProto = new TIntermFunctionPrototype(newMain); + replaced = root->replaceChildNode(oldMainProto, newMainProto); + } } } // anonymous namespace diff --git a/src/compiler/translator/tree_util/SpecializationConstant.cpp b/src/compiler/translator/tree_util/SpecializationConstant.cpp index 6a7254802c9..d05733dac60 100644 --- a/src/compiler/translator/tree_util/SpecializationConstant.cpp +++ b/src/compiler/translator/tree_util/SpecializationConstant.cpp @@ -19,8 +19,6 @@ namespace sh namespace { // Specialization constant names -constexpr ImmutableString kSurfaceRotationSpecConstVarName = - ImmutableString("ANGLESurfaceRotation"); constexpr ImmutableString kDitherSpecConstVarName = ImmutableString("ANGLEDither"); const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id) @@ -39,23 +37,14 @@ const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id) } // anonymous namespace SpecConst::SpecConst(TSymbolTable *symbolTable, - const ShCompileOptions &compileOptions, GLenum shaderType) : mSymbolTable(symbolTable), - mCompileOptions(compileOptions), - mSurfaceRotationVar(nullptr), mDitherVar(nullptr) { if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER) { return; } - - // Mark SpecConstUsage::Rotation unconditionally. gl_Position is always rotated. - if (mCompileOptions.useSpecializationConstant) - { - mUsageBits.set(vk::SpecConstUsage::Rotation); - } } SpecConst::~SpecConst() {} @@ -65,15 +54,6 @@ void SpecConst::declareSpecConsts(TIntermBlock *root) // Add specialization constant declarations. The default value of the specialization // constant is irrelevant, as it will be set when creating the pipeline. // Only emit specialized const declaration if it has been referenced. - if (mSurfaceRotationVar != nullptr) - { - TIntermDeclaration *decl = new TIntermDeclaration(); - decl->appendDeclarator( - new TIntermBinary(EOpInitialize, getRotation(), CreateBoolNode(false))); - - root->insertStatement(0, decl); - } - if (mDitherVar != nullptr) { TIntermDeclaration *decl = new TIntermDeclaration(); @@ -83,29 +63,6 @@ void SpecConst::declareSpecConsts(TIntermBlock *root) } } -TIntermSymbol *SpecConst::getRotation() -{ - if (mSurfaceRotationVar == nullptr) - { - const TType *type = MakeSpecConst(*StaticType::GetBasic(), - vk::SpecializationConstantId::SurfaceRotation); - - mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type, - SymbolType::AngleInternal); - } - return new TIntermSymbol(mSurfaceRotationVar); -} - -TIntermTyped *SpecConst::getSwapXY() -{ - if (!mCompileOptions.useSpecializationConstant) - { - return nullptr; - } - mUsageBits.set(vk::SpecConstUsage::Rotation); - return getRotation(); -} - TIntermTyped *SpecConst::getDither() { if (mDitherVar == nullptr) diff --git a/src/compiler/translator/tree_util/SpecializationConstant.h b/src/compiler/translator/tree_util/SpecializationConstant.h index 6644706567a..a0f23ebb43c 100644 --- a/src/compiler/translator/tree_util/SpecializationConstant.h +++ b/src/compiler/translator/tree_util/SpecializationConstant.h @@ -24,13 +24,9 @@ namespace sh class SpecConst { public: - SpecConst(TSymbolTable *symbolTable, const ShCompileOptions &compileOptions, GLenum shaderType); + SpecConst(TSymbolTable *symbolTable, GLenum shaderType); virtual ~SpecConst(); - // Flip/rotation - // Returns a boolean: should X and Y be swapped? - TIntermTyped *getSwapXY(); - // Dither emulation TIntermTyped *getDither(); @@ -38,13 +34,9 @@ class SpecConst SpecConstUsageBits getSpecConstUsageBits() const { return mUsageBits; } private: - TIntermSymbol *getRotation(); - // If unsupported, this should be set to null. TSymbolTable *mSymbolTable; - const ShCompileOptions &mCompileOptions; - TVariable *mSurfaceRotationVar; TVariable *mDitherVar; // Bit is set if YFlip or Rotation has been used diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp index fdd847737c5..689281aa4ca 100644 --- a/src/compiler/translator/util.cpp +++ b/src/compiler/translator/util.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // +#include "compiler/translator/IntermNode.h" +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/util.h" #include @@ -11,8 +16,9 @@ #include "common/span.h" #include "common/utilities.h" #include "compiler/preprocessor/numeric_lex.h" +#include "compiler/translator/BaseTypes.h" #include "compiler/translator/ImmutableStringBuilder.h" -#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/Symbol.h" bool atoi_clamp(const char *str, unsigned int *value) { @@ -101,14 +107,12 @@ bool IsInterpolationOut(TQualifier qualifier) } } // anonymous namespace -float NumericLexFloat32OutOfRangeToInfinity(const std::string &str) +float NumericLexFloat32OutOfRangeToInfinity(const std::string &str, bool preserveDenorms) { // Parses a decimal string using scientific notation into a floating point number. - // Out-of-range values are converted to infinity. Values that are too small to be - // represented are converted to zero. - - // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not - // matter. + // Out-of-range values are converted to infinity, and values that are too small to be + // represented are converted to zero (unless `preserveDenorms` is set). The mantissa in decimal + // scientific notation. The magnitude of the mantissa integer does not matter. unsigned int decimalMantissa = 0; size_t i = 0; bool decimalPointSeen = false; @@ -211,45 +215,60 @@ float NumericLexFloat32OutOfRangeToInfinity(const std::string &str) } } } + // Do the calculation in 64-bit to avoid overflow. long long exponentLong = static_cast(exponent) + static_cast(exponentOffset); + if (exponentLong > std::numeric_limits::max_exponent10) { return std::numeric_limits::infinity(); } - // In 32-bit float, min_exponent10 is -37 but min() is - // 1.1754943E-38. 10^-37 may be the "minimum negative integer such - // that 10 raised to that power is a normalized float", but being - // constrained to powers of ten it's above min() (which is 2^-126). - // Values below min() are flushed to zero near the end of this - // function anyway so (AFAICT) this comparison is only done to ensure - // that the exponent will not make the pow() call (below) overflow. - // Comparing against -38 (min_exponent10 - 1) will do the trick. - else if (exponentLong < std::numeric_limits::min_exponent10 - 1) + + if (!preserveDenorms) { - return 0.0f; + // In 32-bit float, min_exponent10 is -37 but min() is + // 1.1754943E-38. 10^-37 may be the "minimum negative integer such + // that 10 raised to that power is a normalized float", but being + // constrained to powers of ten it's above min() (which is 2^-126). + // Values below min() are flushed to zero near the end of this + // function anyway so (AFAICT) this comparison is only done to ensure + // that the exponent will not make the pow() call (below) overflow. + // Comparing against -38 (min_exponent10 - 1) will do the trick. + if (exponentLong < std::numeric_limits::min_exponent10 - 1) + { + return 0.0f; + } } + // The exponent is in range, so we need to actually evaluate the float. exponent = static_cast(exponentLong); double value = decimalMantissa; // Calculate the exponent offset to normalize the mantissa. int normalizationExponentOffset = 1 - mantissaDecimalDigits; + // Apply the exponent. value *= std::pow(10.0, static_cast(exponent + normalizationExponentOffset)); + if (value > static_cast(std::numeric_limits::max())) { return std::numeric_limits::infinity(); } - if (static_cast(value) < std::numeric_limits::min()) + + if (!preserveDenorms) { - return 0.0f; + if (static_cast(value) < std::numeric_limits::min()) + { + return 0.0f; + } } + + // The below cast will correctly generate denormalized values return static_cast(value); } -bool strtof_clamp(const std::string &str, float *value) +bool strtof_clamp(const std::string &str, float *value, bool preserveDenorms) { // Custom float parsing that can handle the following corner cases: // 1. The decimal mantissa is very small but the exponent is very large, putting the resulting @@ -259,7 +278,7 @@ bool strtof_clamp(const std::string &str, float *value) // 3. The value is out-of-range and should be evaluated as infinity. // 4. The value is too small and should be evaluated as zero. // See ESSL 3.00.6 section 4.1.4 for the relevant specification. - *value = NumericLexFloat32OutOfRangeToInfinity(str); + *value = NumericLexFloat32OutOfRangeToInfinity(str, preserveDenorms); return !gl::isInf(*value); } @@ -464,14 +483,45 @@ ImmutableString ArrayString(const TType &type) return arrayString; } -ImmutableString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap) +ImmutableString GetTypeName(const TType &type, + char prefix, + ShHashFunction64 hashFunction, + NameMap *nameMap) { if (type.getBasicType() == EbtStruct) - return HashName(type.getStruct(), hashFunction, nameMap); + return HashName(type.getStruct(), prefix, hashFunction, nameMap); else return ImmutableString(type.getBuiltInTypeNameString()); } +bool IsParam(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqParamOut: + case EvqParamInOut: + case EvqParamIn: + case EvqParamConst: + return true; + + default: + return false; + } +} + +bool IsParamOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqParamOut: + case EvqParamInOut: + return true; + + default: + return false; + } +} + bool IsVaryingOut(TQualifier qualifier) { switch (qualifier) @@ -920,7 +970,8 @@ bool IsRedeclarableBuiltIn(const ImmutableString &name) return name == "gl_ClipDistance" || name == "gl_CullDistance" || name == "gl_FragDepth" || name == "gl_LastFragData" || name == "gl_LastFragColorARM" || name == "gl_LastFragDepthARM" || name == "gl_LastFragStencilARM" || - name == "gl_PerVertex" || name == "gl_Position" || name == "gl_PointSize"; + name == "gl_PerVertex" || name == "gl_in" || name == "gl_out" || name == "gl_Position" || + name == "gl_PointSize"; } size_t FindFieldIndex(const TFieldList &fieldList, const char *fieldName) @@ -957,4 +1008,18 @@ Declaration ViewDeclaration(TIntermDeclaration &declNode, uint32_t index) } } +bool IsIndexOp(TOperator op) +{ + switch (op) + { + case EOpIndexDirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + case EOpIndexIndirect: + return true; + default: + return false; + } +} + } // namespace sh diff --git a/src/compiler/translator/util.h b/src/compiler/translator/util.h index ce03b9a706c..68e9b4ec719 100644 --- a/src/compiler/translator/util.h +++ b/src/compiler/translator/util.h @@ -29,7 +29,7 @@ class TIntermDeclaration; class TSymbolTable; class TIntermTyped; -float NumericLexFloat32OutOfRangeToInfinity(const std::string &str); +float NumericLexFloat32OutOfRangeToInfinity(const std::string &str, bool preserveDenorms); // strtof_clamp is like strtof but // 1. it forces C locale, i.e. forcing '.' as decimal point. @@ -37,10 +37,13 @@ float NumericLexFloat32OutOfRangeToInfinity(const std::string &str); // 3. str should be guaranteed to be in the valid format for a floating point number as defined // by the grammar in the ESSL 3.00.6 spec section 4.1.4. // Return false if overflow happens. -bool strtof_clamp(const std::string &str, float *value); +bool strtof_clamp(const std::string &str, float *value, bool preserveDenorms); GLenum GLVariableType(const TType &type); GLenum GLVariablePrecision(const TType &type); +bool IsParam(TQualifier qualifier); +// Returns true if `out` or `inout` function parameter. +bool IsParamOut(TQualifier qualifier); bool IsVaryingIn(TQualifier qualifier); bool IsVaryingOut(TQualifier qualifier); bool IsVarying(TQualifier qualifier); @@ -56,7 +59,10 @@ InterpolationType GetFieldInterpolationType(TQualifier qualifier); // 3.10 section 4.1.9. ImmutableString ArrayString(const TType &type); -ImmutableString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap); +ImmutableString GetTypeName(const TType &type, + char prefix, + ShHashFunction64 hashFunction, + NameMap *nameMap); TType GetShaderVariableBasicType(const sh::ShaderVariable &var); @@ -101,6 +107,9 @@ struct Declaration // the declarations in `declNode`. Declaration ViewDeclaration(TIntermDeclaration &declNode, uint32_t index = 0); +// Returns true if op indexes an array, struct, or interface block. +bool IsIndexOp(TOperator op); + } // namespace sh #endif // COMPILER_TRANSLATOR_UTIL_H_ diff --git a/src/compiler/translator/wgsl/OutputUniformBlocks.cpp b/src/compiler/translator/wgsl/OutputUniformBlocks.cpp index f7b094744b4..fc8fc235828 100644 --- a/src/compiler/translator/wgsl/OutputUniformBlocks.cpp +++ b/src/compiler/translator/wgsl/OutputUniformBlocks.cpp @@ -6,16 +6,22 @@ #include "compiler/translator/wgsl/OutputUniformBlocks.h" +#include + +#include "GLSLANG/ShaderVars.h" #include "angle_gl.h" #include "common/mathutil.h" #include "common/utilities.h" #include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableStringBuilder.h" #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" #include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/tree_ops/GatherDefaultUniforms.h" +#include "compiler/translator/tree_util/DriverUniform.h" #include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/util.h" #include "compiler/translator/wgsl/Utils.h" @@ -44,10 +50,19 @@ class FindUniformAddressSpaceStructs : public TIntermTraverser TIntermTyped *variable = sequence.front()->getAsTyped(); const TType &type = variable->getType(); - // TODO(anglebug.com/376553328): should eventually ASSERT that there are no default uniforms - // here. - if (type.getQualifier() == EvqUniform) + // Note: EvqBuffer is the qualifier given to structs created by ReduceInterfaceBlocks. + if (type.getQualifier() == EvqUniform || type.getQualifier() == EvqBuffer) { +#if defined(ANGLE_ENABLE_ASSERTS) + if (IsDefaultUniform(type)) + { + FATAL() + << "Found default uniform still in AST, by now all default uniforms should be " + "moved into an interface block or deleted if inactive. Uniform name = " + << variable->getAsSymbolNode()->getName(); + } +#endif + recordTypesUsedInUniformAddressSpace(&type); } @@ -89,6 +104,24 @@ bool RecordUniformBlockMetadata(TIntermBlock *root, UniformBlockMetadata &outMet return true; } +bool OutputUniformBoolOrBvecConversion(TInfoSinkBase &output, const TType &type) +{ + ASSERT(type.getBasicType() == EbtBool); + // Bools are represented by u32s in the uniform address space, and so the u32s need to + // be casted. + if (type.isVector()) + { + // Compare != to a vector of 0s, in WGSL this is componentwise and returns a bvec. + output << "(vec" << static_cast(type.getNominalSize()) << "(0u) != "; + } + else + { + output << "bool("; + } + + return true; +} + bool OutputUniformWrapperStructsAndConversions( TInfoSinkBase &output, const WGSLGenerationMetadataForUniforms &wgslGenerationMetadataForUniforms) @@ -97,7 +130,7 @@ bool OutputUniformWrapperStructsAndConversions( auto generate16AlignedWrapperStruct = [&output](const TType &type) { output << "struct " << MakeUniformWrapperStructName(&type) << "\n{\n"; output << " @align(16) " << kWrappedStructFieldName << " : "; - WriteWgslType(output, type, {}); + WriteWgslType(output, type, {WgslAddressSpace::Uniform}); output << "\n};\n"; }; @@ -145,7 +178,17 @@ bool OutputUniformWrapperStructsAndConversions( WriteWgslType(output, type, {WgslAddressSpace::NonUniform}); output << ";\n"; output << " for (var i : u32 = 0; i < " << type.getOutermostArraySize() << "; i++) {;\n"; - output << " retVal[i] = wrappedArr[i]." << kWrappedStructFieldName << ";\n"; + output << " retVal[i] = "; + if (type.getBasicType() == EbtBool) + { + OutputUniformBoolOrBvecConversion(output, type); + } + output << "wrappedArr[i]." << kWrappedStructFieldName; + if (type.getBasicType() == EbtBool) + { + output << ")"; + } + output << ";\n"; output << " }\n"; output << " return retVal;\n"; output << "}\n"; @@ -229,68 +272,126 @@ ImmutableString MakeMatCx2ConversionFunctionName(const TType *type) return BuildConcatenatedImmutableString("ANGLE_Convert_", arrStr, "Mat", type->getCols(), "x2"); } -bool OutputUniformBlocks(TCompiler *compiler, TIntermBlock *root) +bool OutputUniformBlocksAndSamplers(TCompiler *compiler, + TIntermBlock *root, + const TVariable *defaultUniformBlock) { - // TODO(anglebug.com/42267100): This should eventually just be handled the same way as a regular - // UBO, like in Vulkan which create a block out of the default uniforms with a traverser: - // https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp;l=70;drc=451093bbaf7fe812bf67d27d760f3bb64c92830b - const std::vector &basicUniforms = compiler->getUniforms(); TInfoSinkBase &output = compiler->getInfoSink().obj; GlobalVars globalVars = FindGlobalVars(root); +#if defined(ANGLE_ENABLE_ASSERTS) // Only output a struct at all if there are going to be members. - bool outputStructHeader = false; - for (const ShaderVariable &shaderVar : basicUniforms) + bool outputDefaultUniformBlockVar = false; + if (defaultUniformBlock) { - if (gl::IsOpaqueType(shaderVar.type)) - { - continue; - } - if (shaderVar.isBuiltIn()) - { - // gl_DepthRange and also the GLSL 4.2 gl_NumSamples are uniforms. - // TODO(anglebug.com/42267100): put gl_DepthRange into default uniform block. - continue; - } - if (!outputStructHeader) - { - output << "struct ANGLE_DefaultUniformBlock {\n"; - outputStructHeader = true; - } - output << " "; - // TODO(anglebug.com/42267100): some types will NOT match std140 layout here, namely matCx2, - // bool, and arrays with stride less than 16. - // (this check does not cover the unsupported case where there is an array of structs of - // size < 16). - if (shaderVar.type == GL_BOOL) + const std::vector &basicUniforms = compiler->getUniforms(); + for (const ShaderVariable &shaderVar : basicUniforms) { - return false; + if (gl::IsOpaqueType(shaderVar.type) || !shaderVar.active) + { + continue; + } + if (shaderVar.isBuiltIn()) + { + // gl_DepthRange and also the GLSL 4.2 gl_NumSamples are uniforms. + // TODO(anglebug.com/42267100): put gl_DepthRange into default uniform block. + continue; + } + + // Some uniform variables might have been deleted, for example if they were structs that + // only contained samplers (which are pulled into separate default uniforms). + ASSERT(defaultUniformBlock->getType().getInterfaceBlock()); + for (const TField *field : defaultUniformBlock->getType().getInterfaceBlock()->fields()) + { + if (field->name() == shaderVar.name) + { + outputDefaultUniformBlockVar = true; + break; + } + } } - output << shaderVar.name << " : "; + } - TIntermDeclaration *declNode = globalVars.find(shaderVar.name)->second; - const TVariable *astVar = &ViewDeclaration(*declNode).symbol.variable(); - WriteWgslType(output, astVar->getType(), {WgslAddressSpace::Uniform}); + ASSERT(outputDefaultUniformBlockVar == (defaultUniformBlock != nullptr)); +#else // defined(ANGLE_ENABLE_ASSERTS) + bool outputDefaultUniformBlockVar = (defaultUniformBlock != nullptr); +#endif // defined(ANGLE_ENABLE_ASSERTS) - output << ",\n"; - } - // TODO(anglebug.com/42267100): might need string replacement for @group(0) and @binding(0) - // annotations. All WGSL resources available to shaders share the same (group, binding) ID - // space. - if (outputStructHeader) + if (outputDefaultUniformBlockVar) { ASSERT(compiler->getShaderType() == GL_VERTEX_SHADER || compiler->getShaderType() == GL_FRAGMENT_SHADER); const uint32_t bindingIndex = compiler->getShaderType() == GL_VERTEX_SHADER ? kDefaultVertexUniformBlockBinding : kDefaultFragmentUniformBlockBinding; - output << "};\n\n" - << "@group(" << kDefaultUniformBlockBindGroup << ") @binding(" << bindingIndex + output << "@group(" << kDefaultUniformBlockBindGroup << ") @binding(" << bindingIndex << ") var " << kDefaultUniformBlockVarName << " : " << kDefaultUniformBlockVarType << ";\n"; } + // Output interface blocks. Start with driver uniforms in their own bind group. + output << "@group(" << kDriverUniformBindGroup << ") @binding(" << kDriverUniformBlockBinding + << ") var " << kDriverUniformsVarName << " : " << kDriverUniformsBlockName + << ";\n"; + // TODO(anglebug.com/376553328): now output the UBOs in `compiler->getUniformBlocks()` in its + // own bind group. + + // Output split texture/sampler variables. + for (const auto &globalVarIter : globalVars) + { + TIntermDeclaration *declNode = globalVarIter.second; + ASSERT(declNode); + + const TIntermSymbol *declSymbol = &ViewDeclaration(*declNode).symbol; + const TType &declType = declSymbol->getType(); + if (!declType.isSampler()) + { + continue; + } + + // Note that this may output ignored symbols. + output << kTextureSamplerBindingMarker << kAngleSamplerPrefix << declSymbol->getName() + << " : "; + WriteWgslSamplerType(output, declType, WgslSamplerTypeConfig::Sampler); + output << ";\n"; + + output << kTextureSamplerBindingMarker << kAngleTexturePrefix << declSymbol->getName() + << " : "; + WriteWgslSamplerType(output, declType, WgslSamplerTypeConfig::Texture); + output << ";\n"; + } + return true; } +std::string WGSLGetMappedSamplerName(const std::string &originalName) +{ + std::string samplerName = originalName; + + // Samplers in structs are extracted. + std::replace(samplerName.begin(), samplerName.end(), '.', '_'); + + // Remove array elements + auto out = samplerName.begin(); + for (auto in = samplerName.begin(); in != samplerName.end(); in++) + { + if (*in == '[') + { + while (*in != ']') + { + in++; + ASSERT(in != samplerName.end()); + } + } + else + { + *out++ = *in; + } + } + + samplerName.erase(out, samplerName.end()); + + return samplerName; +} + } // namespace sh diff --git a/src/compiler/translator/wgsl/OutputUniformBlocks.h b/src/compiler/translator/wgsl/OutputUniformBlocks.h index 67148349e7b..8b1debe3adb 100644 --- a/src/compiler/translator/wgsl/OutputUniformBlocks.h +++ b/src/compiler/translator/wgsl/OutputUniformBlocks.h @@ -16,10 +16,29 @@ namespace sh const char kDefaultUniformBlockVarType[] = "ANGLE_DefaultUniformBlock"; const char kDefaultUniformBlockVarName[] = "ANGLE_defaultUniformBlock"; -const uint32_t kDefaultUniformBlockBindGroup = 0; + +enum WgslBindGroupNumbers : uint32_t +{ + kDefaultUniformBlockBindGroup = 0, + kTextureAndSamplerBindGroup = 1, + kDriverUniformBindGroup = 2, + kMaxBindGroup = 2 +}; + const uint32_t kDefaultVertexUniformBlockBinding = 0; const uint32_t kDefaultFragmentUniformBlockBinding = 1; +const uint32_t kDriverUniformBlockBinding = 0; + +// The translator emits this dummy location, which needs to be replaced when linking the two +// separate shader stages. +const char kTextureSamplerBindingMarker[] = "@group(1) @binding(@@@@@@) var "; +// The translator emits split samplers/textures for GLSL's combined textures/samplers (combined +// textures/samplers are not supported by WGSL). The new variables are prefixed with these +// constants, respectively. +const char kAngleSamplerPrefix[] = "ANGLE_sampler_"; +const char kAngleTexturePrefix[] = "ANGLE_texture_"; + const char kWrappedStructFieldName[] = "elem"; struct UniformBlockMetadata @@ -72,9 +91,23 @@ bool IsMatCx2(const TType *type); ImmutableString MakeUnwrappingArrayConversionFunctionName(const TType *type); ImmutableString MakeMatCx2ConversionFunctionName(const TType *type); +// Bools and bvecN are represented in WGSL's uniform address space with u32 and uvecN respectively. +// This outputs the beginning of a conversion necessary to convert the bool or bvecN represented by +// `type` into an actual WGSL bool or vecN. E.g. for regular bools this will output `bool(`. +// The caller is responsible for closing the parentheses, e.g. output << +// "uniforms.bool_represented_by_u32)"; +bool OutputUniformBoolOrBvecConversion(TInfoSinkBase &output, const TType &type); + // TODO(anglebug.com/42267100): for now does not output all uniform blocks, -// just the default block. (fails for matCx2, bool.) -bool OutputUniformBlocks(TCompiler *compiler, TIntermBlock *root); +// just the default block. +// `uniformBlock` is the variable declaring an interface block of default uniforms. +bool OutputUniformBlocksAndSamplers(TCompiler *compiler, + TIntermBlock *root, + const TVariable *defaultUniformBlock); + +// GLSL sampler uniforms are extracted from structs. Given a GLSL sampler's associated name string, +// this function retrieves its new WGSL name and strips off array indices. +std::string WGSLGetMappedSamplerName(const std::string &originalName); } // namespace sh diff --git a/src/compiler/translator/wgsl/RewritePipelineVariables.cpp b/src/compiler/translator/wgsl/RewritePipelineVariables.cpp index 2721076ddd0..476af82a2d9 100644 --- a/src/compiler/translator/wgsl/RewritePipelineVariables.cpp +++ b/src/compiler/translator/wgsl/RewritePipelineVariables.cpp @@ -218,7 +218,103 @@ class RewritePipelineVarOutputBuilder const GlobalVars &globalVars, TCompiler &compiler, IOType ioType, - std::string debugString); + const std::string &debugString); + + static bool GenerateForBuiltinVar(RewritePipelineVarOutput::WgslIOBlock *ioblock, + RewritePipelineVarOutput::RewrittenVarSet *varsToReplace, + ImmutableString toStruct, + ImmutableString fromStruct, + TCompiler &compiler, + IOType ioType, + const std::string &shaderVarName) + { + + GlslToWgslBuiltinMapping wgslName; + if (!GetWgslBuiltinName(shaderVarName, compiler.getShaderType(), &wgslName)) + { + return false; + } + + const TVariable *varToReplace = wgslName.builtinVar; + + if (varToReplace == nullptr) + { + // Should be declared somewhere as a symbol. + // TODO(anglebug.com/42267100): Not sure if this ever actually occurs. Will this + // TVariable also have a declaration? Are there any gl_ variable that require or + // even allow declaration? + varToReplace = static_cast(compiler.getSymbolTable().findBuiltIn( + ImmutableString(wgslName.glslBuiltinName), compiler.getShaderVersion())); + if (kOutputVariableUses) + { + std::cout << "Var " << shaderVarName + << " did not have a BuiltIn var but does have a builtin in the symbol " + "table" + << std::endl; + } + } + + ASSERT(ioType == wgslName.ioType); + + varsToReplace->insert(varToReplace->uniqueId().get()); + + ImmutableString builtinReplacement = CreateNameToReplaceBuiltin(wgslName.glslBuiltinName); + + // E.g. `gl_VertexID_ : i32`. + ImmutableString globalType = wgslName.wgslTypeExpectedByShader.empty() + ? wgslName.wgslBuiltinType + : wgslName.wgslTypeExpectedByShader; + ImmutableString globalStructVar = + BuildConcatenatedImmutableString(builtinReplacement, " : ", globalType, ","); + ioblock->angleGlobalMembers.push_back(globalStructVar); + + if (auto *builtinAnnotation = + std::get_if(&wgslName.wgslPipelineAnnotation)) + { + // E.g. `@builtin(vertex_index) gl_VertexID_ : u32,`. + const char *builtinAnnotationStart = "@builtin("; + const char *builtinAnnotationEnd = ") "; + ImmutableString annotatedStructVar = BuildConcatenatedImmutableString( + builtinAnnotationStart, builtinAnnotation->wgslBuiltinName, builtinAnnotationEnd, + builtinReplacement, " : ", wgslName.wgslBuiltinType, ","); + ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); + } + else if (auto *locationAnnotation = + std::get_if(&wgslName.wgslPipelineAnnotation)) + { + ASSERT(locationAnnotation->location == 0); + // E.g. `@location(0) gl_FragColor_ : vec4,`. + const char *locationAnnotationStr = "@location(0) "; + ImmutableString annotatedStructVar = BuildConcatenatedImmutableString( + locationAnnotationStr, builtinReplacement, " : ", wgslName.wgslBuiltinType, ","); + ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); + } + else + { + ASSERT(std::get_if(&wgslName.wgslPipelineAnnotation)); + } + + if (!std::get_if(&wgslName.wgslPipelineAnnotation)) + { + // E.g. `ANGLE_input_global.gl_VertexID_ = u32(ANGLE_input_annotated.gl_VertexID_);` + ImmutableString conversion(nullptr); + if (wgslName.conversionFunc.empty()) + { + conversion = + BuildConcatenatedImmutableString(toStruct, ".", builtinReplacement, " = ", + fromStruct, ".", builtinReplacement, ";"); + } + else + { + conversion = BuildConcatenatedImmutableString( + toStruct, ".", builtinReplacement, " = ", wgslName.conversionFunc, "(", + fromStruct, ".", builtinReplacement, ");"); + } + ioblock->angleConversionFuncs.push_back(conversion); + } + + return true; + } }; // Given a list of `shaderVars` (as well as `compiler` and a list of global variables in the GLSL @@ -241,7 +337,7 @@ class RewritePipelineVarOutputBuilder const GlobalVars &globalVars, TCompiler &compiler, IOType ioType, - std::string debugString) + const std::string &debugString) { for (const ShaderVariable &shaderVar : shaderVars) { @@ -261,92 +357,11 @@ class RewritePipelineVarOutputBuilder if (shaderVar.isBuiltIn()) { - GlslToWgslBuiltinMapping wgslName; - if (!GetWgslBuiltinName(shaderVar.name, compiler.getShaderType(), &wgslName)) + if (!GenerateForBuiltinVar(ioblock, varsToReplace, toStruct, fromStruct, compiler, + ioType, shaderVar.name)) { return false; } - - const TVariable *varToReplace = wgslName.builtinVar; - - if (varToReplace == nullptr) - { - // Should be declared somewhere as a symbol. - // TODO(anglebug.com/42267100): Not sure if this ever actually occurs. Will this - // TVariable also have a declaration? Are there any gl_ variable that require or - // even allow declaration? - varToReplace = static_cast(compiler.getSymbolTable().findBuiltIn( - ImmutableString(wgslName.glslBuiltinName), compiler.getShaderVersion())); - if (kOutputVariableUses) - { - std::cout - << "Var " << shaderVar.name - << " did not have a BuiltIn var but does have a builtin in the symbol " - "table" - << std::endl; - } - } - - ASSERT(ioType == wgslName.ioType); - - varsToReplace->insert(varToReplace->uniqueId().get()); - - ImmutableString builtinReplacement = - CreateNameToReplaceBuiltin(wgslName.glslBuiltinName); - - // E.g. `gl_VertexID_ : i32`. - ImmutableString globalType = wgslName.wgslTypeExpectedByShader.empty() - ? wgslName.wgslBuiltinType - : wgslName.wgslTypeExpectedByShader; - ImmutableString globalStructVar = - BuildConcatenatedImmutableString(builtinReplacement, " : ", globalType, ","); - ioblock->angleGlobalMembers.push_back(globalStructVar); - - if (auto *builtinAnnotation = - std::get_if(&wgslName.wgslPipelineAnnotation)) - { - // E.g. `@builtin(vertex_index) gl_VertexID_ : u32,`. - const char *builtinAnnotationStart = "@builtin("; - const char *builtinAnnotationEnd = ") "; - ImmutableString annotatedStructVar = BuildConcatenatedImmutableString( - builtinAnnotationStart, builtinAnnotation->wgslBuiltinName, - builtinAnnotationEnd, builtinReplacement, " : ", wgslName.wgslBuiltinType, ","); - ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); - } - else if (auto *locationAnnotation = - std::get_if(&wgslName.wgslPipelineAnnotation)) - { - ASSERT(locationAnnotation->location == 0); - // E.g. `@location(0) gl_FragColor_ : vec4,`. - const char *locationAnnotationStr = "@location(0) "; - ImmutableString annotatedStructVar = - BuildConcatenatedImmutableString(locationAnnotationStr, builtinReplacement, - " : ", wgslName.wgslBuiltinType, ","); - ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); - } - else - { - ASSERT(std::get_if(&wgslName.wgslPipelineAnnotation)); - } - - if (!std::get_if(&wgslName.wgslPipelineAnnotation)) - { - // E.g. `ANGLE_input_global.gl_VertexID_ = u32(ANGLE_input_annotated.gl_VertexID_);` - ImmutableString conversion(nullptr); - if (wgslName.conversionFunc.empty()) - { - conversion = - BuildConcatenatedImmutableString(toStruct, ".", builtinReplacement, " = ", - fromStruct, ".", builtinReplacement, ";"); - } - else - { - conversion = BuildConcatenatedImmutableString( - toStruct, ".", builtinReplacement, " = ", wgslName.conversionFunc, "(", - fromStruct, ".", builtinReplacement, ");"); - } - ioblock->angleConversionFuncs.push_back(conversion); - } } else { @@ -356,10 +371,18 @@ class RewritePipelineVarOutputBuilder continue; } - TIntermDeclaration *declNode = globalVars.find(shaderVar.name)->second; + auto globalVarIt = globalVars.find(shaderVar.name); + if (globalVarIt == globalVars.end()) + { + ANGLE_LOG(ERR) << "Should have found " << shaderVar.name << " in global vars"; + return false; + } + TIntermDeclaration *declNode = globalVarIt->second; const TVariable *astVar = &ViewDeclaration(*declNode).symbol.variable(); - const ImmutableString &userVarName = astVar->name(); + TStringStream userVarNameStream; + WriteNameOf(userVarNameStream, *astVar); + TString userVarNameStr = userVarNameStream.str(); varsToReplace->insert(astVar->uniqueId().get()); @@ -368,19 +391,99 @@ class RewritePipelineVarOutputBuilder WriteWgslType(typeStream, astVar->getType(), {}); TString type = typeStream.str(); ImmutableString globalStructVar = - BuildConcatenatedImmutableString(userVarName, " : ", type.c_str(), ","); + BuildConcatenatedImmutableString(userVarNameStr.c_str(), " : ", type.c_str(), ","); ioblock->angleGlobalMembers.push_back(globalStructVar); - // E.g. `@location(@@@@@@) _uuserVar : i32,`. - const char *locationAnnotationStr = "@location(@@@@@@) "; - ImmutableString annotatedStructVar = - BuildConcatenatedImmutableString(locationAnnotationStr, globalStructVar); - ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); + if (astVar->getType().isArray()) + { + // TODO(anglebug.com/42267100): need to support arrays (of scalars, vectors, and + // matrices, maybe structs). + ANGLE_LOG(ERR) << "Shader in/out variables of array type currently not supported."; + return false; + } + else if (astVar->getType().isMatrix()) + { + // E.g. + // @location(@@@@@@) outMatArr_col0 : vec3, + // @location(@@@@@@) outMatArr_col1 : vec3, + // @location(@@@@@@) outMatArr_col2 : vec3, - // E.g. `ANGLE_input_global._uuserVar = ANGLE_input_annotated._uuserVar;` - ImmutableString conversion = BuildConcatenatedImmutableString( - toStruct, ".", userVarName, " = ", fromStruct, ".", userVarName, ";"); - ioblock->angleConversionFuncs.push_back(conversion); + TStringStream colVarList; + + // To the input/output struct, add one vector variable per matrix column. + uint8_t cols = astVar->getType().getCols(); + for (uint8_t i = 0; i < cols; i++) + { + const char *locationAnnotationStr = "@location(@@@@@@) "; + + TStringStream rowVecTypeStream; + TType rowVecAstType = astVar->getType(); + rowVecAstType.toMatrixColumnType(); + WriteWgslType(rowVecTypeStream, rowVecAstType, {}); + TString rowVecType = rowVecTypeStream.str(); + + ImmutableString colVarName = + BuildConcatenatedImmutableString(userVarNameStr.c_str(), "_col", i); + + if (ioType == IOType::Input) + { + colVarList << fromStruct << "." << colVarName; + if (i != cols - 1) + { + colVarList << ", "; + } + } + + // Add a column vec to the WGSL in/out block. + ImmutableString annotatedStructVar = BuildConcatenatedImmutableString( + locationAnnotationStr, colVarName, " : ", rowVecType.c_str(), ","); + ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); + + // When outputting matrices, they need to be split into column vectors which are + // then placed in the WGSL in/out block. + if (ioType == IOType::Output) + { + // e.g. + // ANGLE_output_annotated.outMatArr_col0 = ANGLE_output_global.outMatArr[0]; + // ANGLE_output_annotated.outMatArr_col1 = ANGLE_output_global.outMatArr[1]; + // ANGLE_output_annotated.outMatArr_col2 = ANGLE_output_global.outMatArr[2]; + ImmutableString extractColVec = BuildConcatenatedImmutableString( + toStruct, '.', colVarName, " = ", fromStruct, '.', + userVarNameStr.c_str(), '[', i, "];"); + ioblock->angleConversionFuncs.push_back(extractColVec); + } + } + + // If input, construct the global matrix var from the column vectors in the WGSL + // input block. + if (ioType == IOType::Input) + { + // e.g. ANGLE_input_global.inMat = mat3x3(ANGLE_input_annotated.inMat_col0, + // ANGLE_input_annotated.inMat_col1, ANGLE_input_annotated.inMat_col2); + ImmutableString conversion = BuildConcatenatedImmutableString( + toStruct, ".", userVarNameStr.c_str(), " = ", type.c_str(), '(', + colVarList.str().c_str(), ");"); + ioblock->angleConversionFuncs.push_back(conversion); + } + } + else + { + // The only two types supported natively by WGSL are scalars and vectors. + ASSERT((astVar->getType().isVector() || astVar->getType().isScalar()) && + !astVar->getType().isArray()); + + // E.g. `@location(@@@@@@) _uuserVar : i32,`. + const char *locationAnnotationStr = "@location(@@@@@@) "; + ImmutableString annotatedStructVar = + BuildConcatenatedImmutableString(locationAnnotationStr, globalStructVar); + ioblock->angleAnnotatedMembers.push_back(annotatedStructVar); + + // E.g. `ANGLE_input_global._uuserVar = ANGLE_input_annotated._uuserVar;` + ImmutableString conversion = + BuildConcatenatedImmutableString(toStruct, ".", userVarNameStr.c_str(), " = ", + fromStruct, ".", userVarNameStr.c_str(), ";"); + ioblock->angleConversionFuncs.push_back(conversion); + } } } @@ -394,6 +497,34 @@ bool RewritePipelineVarOutputBuilder::GenerateMainFunctionAndIOStructs( { GlobalVars globalVars = FindGlobalVars(&root); + // The Dawn WGSL compiler generates an error if there is no builtin(position) variable in a + // vertex shader, though it doesn't look like the WGSL spec requires this. GLSL doesn't require + // use of gl_Position (only that its value is undefined if not written to). So, generate a + // @builtin(position) variable by pretending gl_Position is present even if it's not. + if (compiler.getShaderType() == GL_VERTEX_SHADER) + { + bool hasPosition = false; + for (const ShaderVariable &shaderVar : compiler.getOutputVaryings()) + { + if (shaderVar.name == std::string("gl_Position")) + { + hasPosition = true; + } + } + + if (!hasPosition) + { + if (!GenerateForBuiltinVar( + &outVarReplacements.mOutputBlock, &outVarReplacements.mAngleOutputVars, + /*toStruct=*/ImmutableString(kBuiltinOutputAnnotatedStructName), + /*fromStruct=*/ImmutableString(kBuiltinOutputStructName), compiler, + IOType::Output, "gl_Position")) + { + return false; + } + } + } + if (!RewritePipelineVarOutputBuilder::GeneratePipelineStructStrings( &outVarReplacements.mInputBlock, &outVarReplacements.mAngleInputVars, /*toStruct=*/ImmutableString(kBuiltinInputStructName), @@ -506,7 +637,7 @@ bool RewritePipelineVarOutput::OutputMainFunction(TInfoSinkBase &output) { output << " " << conversionFunc << "\n"; } - output << " " << kUserDefinedNamePrefix << "main()" << ";\n"; + output << " " << '_' << kUserDefinedNamePrefix << "main()" << ";\n"; if (!mOutputBlock.angleGlobalMembers.empty()) { diff --git a/src/compiler/translator/wgsl/TranslatorWGSL.cpp b/src/compiler/translator/wgsl/TranslatorWGSL.cpp index 6445bee68de..2021af64193 100644 --- a/src/compiler/translator/wgsl/TranslatorWGSL.cpp +++ b/src/compiler/translator/wgsl/TranslatorWGSL.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/translator/wgsl/TranslatorWGSL.h" #include @@ -19,18 +23,33 @@ #include "compiler/translator/ImmutableStringBuilder.h" #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" +#include "compiler/translator/Operator_autogen.h" #include "compiler/translator/OutputTree.h" #include "compiler/translator/StaticType.h" #include "compiler/translator/SymbolUniqueId.h" #include "compiler/translator/Types.h" +#include "compiler/translator/tree_ops/GatherDefaultUniforms.h" +#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" +#include "compiler/translator/tree_ops/ReduceInterfaceBlocks.h" +#include "compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h" +#include "compiler/translator/tree_ops/RewriteStructSamplers.h" +#include "compiler/translator/tree_ops/SeparateDeclarations.h" +#include "compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h" +#include "compiler/translator/tree_ops/wgsl/EmulateMutableFunctionParams.h" +#include "compiler/translator/tree_ops/wgsl/PullExpressionsIntoFunctions.h" +#include "compiler/translator/tree_ops/wgsl/RewriteMixedTypeMathExprs.h" +#include "compiler/translator/tree_ops/wgsl/RewriteMultielementSwizzleAssignment.h" #include "compiler/translator/tree_util/BuiltIn_autogen.h" +#include "compiler/translator/tree_util/DriverUniform.h" #include "compiler/translator/tree_util/FindMain.h" #include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/tree_util/RunAtTheEndOfShader.h" +#include "compiler/translator/util.h" #include "compiler/translator/wgsl/OutputUniformBlocks.h" #include "compiler/translator/wgsl/RewritePipelineVariables.h" #include "compiler/translator/wgsl/Utils.h" +#include "compiler/translator/wgsl/WGSLProgramPrelude.h" namespace sh { @@ -47,12 +66,32 @@ struct VarDecl const TType &type; }; -bool IsDefaultUniform(const TType &type) +TUnorderedSet FindOverloadedFunctions(TIntermBlock *root) { - return type.getQualifier() == EvqUniform && type.getInterfaceBlock() == nullptr && - !IsOpaqueType(type.getBasicType()); + TSet funcNames; + TUnorderedSet uniqueIds; + for (TIntermNode *node : *root->getSequence()) + { + if (TIntermFunctionDefinition *funcDef = node->getAsFunctionDefinition()) + { + if (!funcNames.insert(funcDef->getFunction()->name()).second) + { + uniqueIds.insert(funcDef->getFunction()->uniqueId()); + } + } + } + return uniqueIds; } +struct OperatorInfo +{ + const char *opName; + std::optional wgslWrapperFn = std::nullopt; + bool isPostfix = false; + + bool IsSymbolicOperator() const { return opName && !std::isalnum(opName[0]); } +}; + // When emitting a list of statements, this determines whether a semicolon follows the statement. bool RequiresSemicolonTerminator(TIntermNode &node) { @@ -112,7 +151,9 @@ class OutputWGSLTraverser : public TIntermTraverser OutputWGSLTraverser(TInfoSinkBase *sink, RewritePipelineVarOutput *rewritePipelineVarOutput, UniformBlockMetadata *uniformBlockMetadata, - WGSLGenerationMetadataForUniforms *arrayElementTypesInUniforms); + WGSLGenerationMetadataForUniforms *arrayElementTypesInUniforms, + const TUnorderedSet *overloadedFunctions, + WGSLProgramPrelude *prelude); ~OutputWGSLTraverser() override; protected: @@ -140,10 +181,11 @@ class OutputWGSLTraverser : public TIntermTraverser struct EmitVariableDeclarationConfig { EmitTypeConfig typeConfig; - bool isParameter = false; - bool disableStructSpecifier = false; - bool needsVar = false; - bool isGlobalScope = false; + bool isParameter = false; + std::optional emitAsPointer = std::nullopt; + bool disableStructSpecifier = false; + bool isDeclaration = false; + bool isGlobalScope = false; }; void groupedTraverse(TIntermNode &node); @@ -155,11 +197,19 @@ class OutputWGSLTraverser : public TIntermTraverser const size_t size); const TConstantUnion *emitConstantUnion(const TType &type, const TConstantUnion *constUnionBegin); + bool isStatement(TIntermNode *current); + OperatorInfo useOperatorAndGetInfo(TIntermNode *current, + TOperator op, + const TType &resultType, + const TType *argType0, + const TType *argType1, + const TType *argType2); const TField &getDirectField(const TIntermTyped &fieldsNode, TIntermTyped &indexNode); void emitIndentation(); void emitOpenBrace(); void emitCloseBrace(); bool emitBlock(angle::Span nodes); + void emitFunctionName(const TFunction &func); void emitFunctionSignature(const TFunction &func); void emitFunctionReturn(const TFunction &func); void emitFunctionParameter(const TFunction &func, const TVariable ¶m); @@ -169,6 +219,7 @@ class OutputWGSLTraverser : public TIntermTraverser void emitArrayIndex(TIntermTyped &leftNode, TIntermTyped &rightNode); void emitStructIndex(TIntermBinary *binaryNode); void emitStructIndexNoUnwrapping(TIntermBinary *binaryNode); + void emitTextureBuiltin(const TOperator op, const TIntermSequence &args); bool emitForLoop(TIntermLoop *); bool emitWhileLoop(TIntermLoop *); @@ -178,21 +229,29 @@ class OutputWGSLTraverser : public TIntermTraverser const RewritePipelineVarOutput *mRewritePipelineVarOutput; const UniformBlockMetadata *mUniformBlockMetadata; WGSLGenerationMetadataForUniforms *mWGSLGenerationMetadataForUniforms; + const TUnorderedSet *mOverloadedFunctions; + WGSLProgramPrelude *mPrelude; int mIndentLevel = -1; int mLastIndentationPos = -1; + + TUnorderedSet mIsActuallyOfPointerType; }; OutputWGSLTraverser::OutputWGSLTraverser( TInfoSinkBase *sink, RewritePipelineVarOutput *rewritePipelineVarOutput, UniformBlockMetadata *uniformBlockMetadata, - WGSLGenerationMetadataForUniforms *wgslGenerationMetadataForUniforms) + WGSLGenerationMetadataForUniforms *wgslGenerationMetadataForUniforms, + const TUnorderedSet *overloadedFunctions, + WGSLProgramPrelude *prelude) : TIntermTraverser(true, false, false), mSink(*sink), mRewritePipelineVarOutput(rewritePipelineVarOutput), mUniformBlockMetadata(uniformBlockMetadata), - mWGSLGenerationMetadataForUniforms(wgslGenerationMetadataForUniforms) + mWGSLGenerationMetadataForUniforms(wgslGenerationMetadataForUniforms), + mOverloadedFunctions(overloadedFunctions), + mPrelude(prelude) {} OutputWGSLTraverser::~OutputWGSLTraverser() = default; @@ -263,7 +322,12 @@ void OutputWGSLTraverser::visitSymbol(TIntermSymbol *symbolNode) const TType &type = var.getType(); ASSERT(var.symbolType() != SymbolType::Empty); - if (type.getBasicType() == TBasicType::EbtVoid) + // Default uniforms should no longer be referenced--they should all be in an interface block by + // now. + // TODO(anglebug.com/376553328): gl_DepthRange should be handled by referencing driver + // uniforms--then the check for builtin default uniforms can be removed here. + if (type.getBasicType() == TBasicType::EbtVoid || + (IsDefaultUniform(type) && var.symbolType() != SymbolType::BuiltIn)) { UNREACHABLE(); } @@ -272,28 +336,41 @@ void OutputWGSLTraverser::visitSymbol(TIntermSymbol *symbolNode) // Accesses of pipeline variables should be rewritten as struct accesses. if (mRewritePipelineVarOutput->IsInputVar(var.uniqueId())) { - mSink << kBuiltinInputStructName << "." << var.name(); + mSink << kBuiltinInputStructName << "."; + WriteNameOf(mSink, var); } else if (mRewritePipelineVarOutput->IsOutputVar(var.uniqueId())) { - mSink << kBuiltinOutputStructName << "." << var.name(); - } - // Accesses of basic uniforms need to be converted to struct accesses. - else if (IsDefaultUniform(type)) - { - mSink << kDefaultUniformBlockVarName << "." << var.name(); + mSink << kBuiltinOutputStructName << "."; + WriteNameOf(mSink, var); } else { + // If this symbol refers to an outparam, that param was translated as a pointer and must + // be dereferenced to be accessed. + // Similarly, some symbol are actually pointers, even though in the GLSL AST they are + // regular types (as GLSL does not have pointers, just out variables). + const bool isOutParam = IsParamOut(var.getType().getQualifier()); + const bool isActuallyOfPointerType = + mIsActuallyOfPointerType.contains(symbolNode->uniqueId()); + const bool needsDereference = isOutParam || isActuallyOfPointerType; + if (needsDereference) + { + mSink << "(*"; + } WriteNameOf(mSink, var); + if (needsDereference) + { + mSink << ")"; + } } if (var.symbolType() == SymbolType::BuiltIn) { ASSERT(mRewritePipelineVarOutput->IsInputVar(var.uniqueId()) || mRewritePipelineVarOutput->IsOutputVar(var.uniqueId()) || - var.uniqueId() == BuiltInId::gl_DepthRange); - // TODO(anglebug.com/42267100): support gl_DepthRange. + type.getQualifier() == EvqDepthRange); + // TODO(anglebug.com/376553328): support gl_DepthRange. // Match the name of the struct field in `mRewritePipelineVarOutput`. mSink << "_"; } @@ -400,7 +477,7 @@ const TConstantUnion *OutputWGSLTraverser::emitConstantUnion(const TType &type, else { size_t size = type.getObjectSize(); - // If the type's size is more than 1, the type needs to be written with parantheses. This + // If the type's size is more than 1, the type needs to be written with parentheses. This // applies for vectors, matrices, and arrays. bool writeType = size > 1; if (writeType) @@ -430,170 +507,219 @@ bool OutputWGSLTraverser::visitSwizzle(Visit, TIntermSwizzle *swizzleNode) return false; } -const char *GetOperatorString(TOperator op, - const TType &resultType, - const TType *argType0, - const TType *argType1, - const TType *argType2) +bool OutputWGSLTraverser::isStatement(TIntermNode *current) +{ + if (getParentNode()->getAsLoopNode() != nullptr || getParentNode()->getAsBlock() != nullptr) + { + return current->getAsBlock() == nullptr; + } + return false; +} + +OperatorInfo OutputWGSLTraverser::useOperatorAndGetInfo(TIntermNode *current, + TOperator op, + const TType &resultType, + const TType *argType0, + const TType *argType1, + const TType *argType2) { switch (op) { case TOperator::EOpComma: // WGSL does not have a comma operator or any other way to implement "statement list as // an expression", so nested expressions will have to be pulled out into statements. - UNIMPLEMENTED(); - return "TODO_operator"; - case TOperator::EOpAssign: - return "="; + // This should have been done by a preprocessing. + UNREACHABLE(); + return {"TODO_operator"}; case TOperator::EOpInitialize: - return "="; + return {"="}; + // Assignments are always statements in WGSL and do not yield a value, so they are + // implemented as functions, unless the current expression is a statement and is a scalar + // integer, in which case the normal postfix operator will do. + case TOperator::EOpAssign: // Compound assignments now exist: https://www.w3.org/TR/WGSL/#compound-assignment-sec case TOperator::EOpAddAssign: - return "+="; case TOperator::EOpSubAssign: - return "-="; case TOperator::EOpMulAssign: - return "*="; case TOperator::EOpDivAssign: - return "/="; case TOperator::EOpIModAssign: - return "%="; case TOperator::EOpBitShiftLeftAssign: - return "<<="; case TOperator::EOpBitShiftRightAssign: - return ">>="; case TOperator::EOpBitwiseAndAssign: - return "&="; case TOperator::EOpBitwiseXorAssign: - return "^="; case TOperator::EOpBitwiseOrAssign: - return "|="; + case TOperator::EOpVectorTimesScalarAssign: + case TOperator::EOpVectorTimesMatrixAssign: + case TOperator::EOpMatrixTimesScalarAssign: + case TOperator::EOpMatrixTimesMatrixAssign: + if (isStatement(current)) + { + return {GetOperatorString(op)}; + } + else + { + return OperatorInfo{nullptr, mPrelude->assign(*argType0, *argType1, op)}; + } + case TOperator::EOpAdd: - return "+"; + return {"+"}; case TOperator::EOpSub: - return "-"; + return {"-"}; case TOperator::EOpMul: - return "*"; + return {"*"}; case TOperator::EOpDiv: - return "/"; + return {"/"}; // TODO(anglebug.com/42267100): Works different from GLSL for negative numbers. // https://github.com/gpuweb/gpuweb/discussions/2204#:~:text=not%20WGSL%3B%20etc.-,Inconsistent%20mod/%25%20operator,-At%20first%20glance // GLSL does `x - y * floor(x/y)`, WGSL does x - y * trunc(x/y). case TOperator::EOpIMod: case TOperator::EOpMod: - return "%"; + return {"%"}; + // TODO(anglebug.com/42267100): bitwise operations can be between scalars and vectors, but + // not in WGSL. case TOperator::EOpBitShiftLeft: - return "<<"; + return {"<<"}; case TOperator::EOpBitShiftRight: - return ">>"; + return {">>"}; case TOperator::EOpBitwiseAnd: - return "&"; + return {"&"}; case TOperator::EOpBitwiseXor: - return "^"; + return {"^"}; case TOperator::EOpBitwiseOr: - return "|"; + return {"|"}; case TOperator::EOpLessThan: - return "<"; + return {"<"}; case TOperator::EOpGreaterThan: - return ">"; + return {">"}; case TOperator::EOpLessThanEqual: - return "<="; + return {"<="}; case TOperator::EOpGreaterThanEqual: - return ">="; + return {">="}; // Component-wise comparisons are done with regular infix operators in WGSL: // https://www.w3.org/TR/WGSL/#comparison-expr case TOperator::EOpLessThanComponentWise: - return "<"; + return {"<"}; case TOperator::EOpLessThanEqualComponentWise: - return "<="; + return {"<="}; case TOperator::EOpGreaterThanEqualComponentWise: - return ">="; + return {">="}; case TOperator::EOpGreaterThanComponentWise: - return ">"; + return {">"}; case TOperator::EOpLogicalOr: - return "||"; + return {"||"}; // Logical XOR is only applied to boolean expressions so it's the same as "not equals". // Neither short-circuits. case TOperator::EOpLogicalXor: - return "!="; + return {"!="}; case TOperator::EOpLogicalAnd: - return "&&"; + return {"&&"}; case TOperator::EOpNegative: - return "-"; + return {"-"}; case TOperator::EOpPositive: - if (argType0->isMatrix()) - { - return ""; - } - return "+"; + return {""}; case TOperator::EOpLogicalNot: - return "!"; + return {"!"}; // Component-wise not done with normal prefix unary operator in WGSL: // https://www.w3.org/TR/WGSL/#logical-expr case TOperator::EOpNotComponentWise: - return "!"; + return {"!"}; case TOperator::EOpBitwiseNot: - return "~"; - // TODO(anglebug.com/42267100): increment operations cannot be used as expressions in WGSL. + return {"~"}; + // ++ and -- are always statements in WGSL and do not yield a value, so they are + // implemented as functions, unless the current expression is a statement and is a scalar + // integer, in which case the normal postfix operator will do. + // Note that WGSL only allows increments of scalar integers, so this also uses a function to + // increment floats. case TOperator::EOpPostIncrement: - return "++"; + if (isStatement(current) && argType0->isScalarInt()) + { + return OperatorInfo{"++", std::nullopt, /*isPostfix=*/true}; + } + else + { + return OperatorInfo{"", mPrelude->postIncrement(*argType0)}; + } case TOperator::EOpPostDecrement: - return "--"; + if (isStatement(current) && argType0->isScalarInt()) + { + return OperatorInfo{"--", std::nullopt, /*isPostfix=*/true}; + } + else + { + return OperatorInfo{"", mPrelude->postDecrement(*argType0)}; + } + // NOTE: ++ and -- can only be postfix unary operators in WGSL. If the current expression is + // a statement and is a scalar integer, just use the postfix operator, otherwise use a + // function call as above. case TOperator::EOpPreIncrement: + if (isStatement(current) && argType0->isScalarInt()) + { + return OperatorInfo{"++", std::nullopt, /*isPostfix=*/true}; + } + else + { + return OperatorInfo{"", mPrelude->preIncrement(*argType0)}; + } case TOperator::EOpPreDecrement: - // TODO(anglebug.com/42267100): pre increments and decrements do not exist in WGSL. - UNIMPLEMENTED(); - return "TODO_operator"; - case TOperator::EOpVectorTimesScalarAssign: - return "*="; - case TOperator::EOpVectorTimesMatrixAssign: - return "*="; - case TOperator::EOpMatrixTimesScalarAssign: - return "*="; - case TOperator::EOpMatrixTimesMatrixAssign: - return "*="; + if (isStatement(current) && argType0->isScalarInt()) + { + return OperatorInfo{"--", std::nullopt, /*isPostfix=*/true}; + } + else + { + return OperatorInfo{"", mPrelude->preDecrement(*argType0)}; + } case TOperator::EOpVectorTimesScalar: - return "*"; + return {"*"}; case TOperator::EOpVectorTimesMatrix: - return "*"; + return {"*"}; case TOperator::EOpMatrixTimesVector: - return "*"; + return {"*"}; case TOperator::EOpMatrixTimesScalar: - return "*"; + return {"*"}; case TOperator::EOpMatrixTimesMatrix: - return "*"; + return {"*"}; case TOperator::EOpEqualComponentWise: - return "=="; + return {"=="}; case TOperator::EOpNotEqualComponentWise: - return "!="; + return {"!="}; // TODO(anglebug.com/42267100): structs, matrices, and arrays are not comparable with WGSL's // == or !=. Comparing vectors results in a component-wise comparison returning a boolean // vector, which is different from GLSL (which use equal(vec, vec) for component-wise // comparison) case TOperator::EOpEqual: - if ((argType0->isVector() && argType1->isVector()) || - (argType0->getStruct() && argType1->getStruct()) || + if (argType0->isVector() && argType1->isVector()) + { + return {"==", WGSLWrapperFunction{ImmutableString("all("), ImmutableString(")")}}; + } + + if ((argType0->getStruct() && argType1->getStruct()) || (argType0->isArray() && argType1->isArray()) || (argType0->isMatrix() && argType1->isMatrix())) { UNIMPLEMENTED(); - return "TODO_operator"; + return {"TODO_operator"}; } - return "=="; + return {"=="}; case TOperator::EOpNotEqual: - if ((argType0->isVector() && argType1->isVector()) || - (argType0->getStruct() && argType1->getStruct()) || + if ((argType0->isVector() && argType1->isVector())) + { + return {"!=", WGSLWrapperFunction{ImmutableString("all("), ImmutableString(")")}}; + } + + if ((argType0->getStruct() && argType1->getStruct()) || (argType0->isArray() && argType1->isArray()) || (argType0->isMatrix() && argType1->isMatrix())) { UNIMPLEMENTED(); - return "TODO_operator"; + return {"TODO_operator"}; } - return "!="; + + return {"!="}; case TOperator::EOpKill: case TOperator::EOpReturn: @@ -601,158 +727,160 @@ const char *GetOperatorString(TOperator op, case TOperator::EOpContinue: // These should all be emitted in visitBranch(). UNREACHABLE(); - return "UNREACHABLE_operator"; + return {"UNREACHABLE_operator"}; case TOperator::EOpRadians: - return "radians"; + return {"radians"}; case TOperator::EOpDegrees: - return "degrees"; + return {"degrees"}; case TOperator::EOpAtan: - return argType1 == nullptr ? "atan" : "atan2"; + return argType1 == nullptr ? OperatorInfo{"atan"} : OperatorInfo{"atan2"}; case TOperator::EOpRefract: - return argType0->isVector() ? "refract" : "TODO_operator"; + return argType0->isVector() ? OperatorInfo{"refract"} : OperatorInfo{"TODO_operator"}; case TOperator::EOpDistance: - return "distance"; + return {"distance"}; case TOperator::EOpLength: - return "length"; + return {"length"}; case TOperator::EOpDot: - return argType0->isVector() ? "dot" : "*"; + return argType0->isVector() ? OperatorInfo{"dot"} : OperatorInfo{"*"}; case TOperator::EOpNormalize: - return argType0->isVector() ? "normalize" : "sign"; + return argType0->isVector() ? OperatorInfo{"normalize"} : OperatorInfo{"sign"}; case TOperator::EOpFaceforward: - return argType0->isVector() ? "faceForward" : "TODO_Operator"; + return argType0->isVector() ? OperatorInfo{"faceForward"} + : OperatorInfo{"TODO_Operator"}; case TOperator::EOpReflect: - return argType0->isVector() ? "reflect" : "TODO_Operator"; + return argType0->isVector() ? OperatorInfo{"reflect"} : OperatorInfo{"TODO_Operator"}; case TOperator::EOpMatrixCompMult: - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpOuterProduct: - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpSign: - return "sign"; + return {"sign"}; case TOperator::EOpAbs: - return "abs"; + return {"abs"}; case TOperator::EOpAll: - return "all"; + return {"all"}; case TOperator::EOpAny: - return "any"; + return {"any"}; case TOperator::EOpSin: - return "sin"; + return {"sin"}; case TOperator::EOpCos: - return "cos"; + return {"cos"}; case TOperator::EOpTan: - return "tan"; + return {"tan"}; case TOperator::EOpAsin: - return "asin"; + return {"asin"}; case TOperator::EOpAcos: - return "acos"; + return {"acos"}; case TOperator::EOpSinh: - return "sinh"; + return {"sinh"}; case TOperator::EOpCosh: - return "cosh"; + return {"cosh"}; case TOperator::EOpTanh: - return "tanh"; + return {"tanh"}; case TOperator::EOpAsinh: - return "asinh"; + return {"asinh"}; case TOperator::EOpAcosh: - return "acosh"; + return {"acosh"}; case TOperator::EOpAtanh: - return "atanh"; + return {"atanh"}; case TOperator::EOpFma: - return "fma"; + return {"fma"}; // TODO(anglebug.com/42267100): Won't accept pow(vec, f32). // https://github.com/gpuweb/gpuweb/discussions/2204#:~:text=Similarly%20pow(vec3%3Cf32%3E%2C%20f32)%20works%20in%20GLSL%20but%20not%20WGSL case TOperator::EOpPow: - return "pow"; // GLSL's pow excludes negative x + return {"pow"}; // GLSL's pow excludes negative x case TOperator::EOpExp: - return "exp"; + return {"exp"}; case TOperator::EOpExp2: - return "exp2"; + return {"exp2"}; case TOperator::EOpLog: - return "log"; + return {"log"}; case TOperator::EOpLog2: - return "log2"; + return {"log2"}; case TOperator::EOpSqrt: - return "sqrt"; + return {"sqrt"}; case TOperator::EOpFloor: - return "floor"; + return {"floor"}; case TOperator::EOpTrunc: - return "trunc"; + return {"trunc"}; case TOperator::EOpCeil: - return "ceil"; + return {"ceil"}; case TOperator::EOpFract: - return "fract"; + return {"fract"}; case TOperator::EOpMin: - return "min"; + return {"min"}; case TOperator::EOpMax: - return "max"; + return {"max"}; case TOperator::EOpRound: - return "round"; // TODO(anglebug.com/42267100): this is wrong and must round away from - // zero if there is a tie. This always rounds to the even number. + return { + "round"}; // TODO(anglebug.com/42267100): this is wrong and must round away from + // zero if there is a tie. This always rounds to the even number. case TOperator::EOpRoundEven: - return "round"; + return {"round"}; // TODO(anglebug.com/42267100): // https://github.com/gpuweb/gpuweb/discussions/2204#:~:text=clamp(vec2%3Cf32%3E%2C%20f32%2C%20f32)%20works%20in%20GLSL%20but%20not%20WGSL%3B%20etc. // Need to expand clamp(vec, low : f32, high : f32) -> // clamp(vec, vec(low), vec(high)) case TOperator::EOpClamp: - return "clamp"; + return {"clamp"}; case TOperator::EOpSaturate: - return "saturate"; + return {"saturate"}; case TOperator::EOpMix: if (!argType1->isScalar() && argType2 && argType2->getBasicType() == EbtBool) { - return "TODO_Operator"; + return {"TODO_Operator"}; } - return "mix"; + return {"mix"}; case TOperator::EOpStep: - return "step"; + return {"step"}; case TOperator::EOpSmoothstep: - return "smoothstep"; + return {"smoothstep"}; case TOperator::EOpModf: UNIMPLEMENTED(); // TODO(anglebug.com/42267100): in WGSL this returns a struct, GLSL it // uses a return value and an outparam - return "modf"; + return {"modf"}; case TOperator::EOpIsnan: case TOperator::EOpIsinf: UNIMPLEMENTED(); // TODO(anglebug.com/42267100): WGSL does not allow NaNs or infinity. // What to do about shaders that require this? // Implementations are allowed to assume overflow, infinities, and NaNs are not present // at runtime, however. https://www.w3.org/TR/WGSL/#floating-point-evaluation - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpLdexp: // TODO(anglebug.com/42267100): won't accept first arg vector, second arg scalar - return "ldexp"; + return {"ldexp"}; case TOperator::EOpFrexp: - return "frexp"; // TODO(anglebug.com/42267100): returns a struct + return {"frexp"}; // TODO(anglebug.com/42267100): returns a struct case TOperator::EOpInversesqrt: - return "inverseSqrt"; + return {"inverseSqrt"}; case TOperator::EOpCross: - return "cross"; + return {"cross"}; // TODO(anglebug.com/42267100): are these the same? dpdxCoarse() vs dpdxFine()? case TOperator::EOpDFdx: - return "dpdx"; + return {"dpdx"}; case TOperator::EOpDFdy: - return "dpdy"; + return {"dpdy"}; case TOperator::EOpFwidth: - return "fwidth"; + return {"fwidth"}; case TOperator::EOpTranspose: - return "transpose"; + return {"transpose"}; case TOperator::EOpDeterminant: - return "determinant"; + return {"determinant"}; case TOperator::EOpInverse: - return "TODO_Operator"; // No builtin invert(). - // https://github.com/gpuweb/gpuweb/issues/4115 + return {"TODO_Operator"}; // No builtin invert(). + // https://github.com/gpuweb/gpuweb/issues/4115 // TODO(anglebug.com/42267100): these interpolateAt*() are not builtin case TOperator::EOpInterpolateAtCentroid: - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpInterpolateAtSample: - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpInterpolateAtOffset: - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpInterpolateAtCenter: - return "TODO_Operator"; + return {"TODO_Operator"}; case TOperator::EOpFloatBitsToInt: case TOperator::EOpFloatBitsToUint: @@ -764,31 +892,31 @@ const char *GetOperatorString(TOperator op, switch (resultType.getBasicType()) \ { \ case TBasicType::EbtInt: \ - return "bitcast"; \ + return {"bitcast"}; \ case TBasicType::EbtUInt: \ - return "bitcast"; \ + return {"bitcast"}; \ case TBasicType::EbtFloat: \ - return "bitcast"; \ + return {"bitcast"}; \ default: \ UNIMPLEMENTED(); \ - return "TOperator_TODO"; \ + return {"TOperator_TODO"}; \ } \ while (false) -#define BITCAST_VECTOR(vecSize) \ - do \ - switch (resultType.getBasicType()) \ - { \ - case TBasicType::EbtInt: \ - return "bitcast>"; \ - case TBasicType::EbtUInt: \ - return "bitcast>"; \ - case TBasicType::EbtFloat: \ - return "bitcast>"; \ - default: \ - UNIMPLEMENTED(); \ - return "TOperator_TODO"; \ - } \ +#define BITCAST_VECTOR(vecSize) \ + do \ + switch (resultType.getBasicType()) \ + { \ + case TBasicType::EbtInt: \ + return {"bitcast>"}; \ + case TBasicType::EbtUInt: \ + return {"bitcast>"}; \ + case TBasicType::EbtFloat: \ + return {"bitcast>"}; \ + default: \ + UNIMPLEMENTED(); \ + return {"TOperator_TODO"}; \ + } \ while (false) if (resultType.isScalar()) @@ -807,13 +935,13 @@ const char *GetOperatorString(TOperator op, BITCAST_VECTOR("4"); default: UNREACHABLE(); - return nullptr; + return {nullptr}; } } else { UNIMPLEMENTED(); - return "TOperator_TODO"; + return {"TOperator_TODO"}; } #undef BITCAST_SCALAR @@ -821,61 +949,61 @@ const char *GetOperatorString(TOperator op, } case TOperator::EOpPackUnorm2x16: - return "pack2x16unorm"; + return {"pack2x16unorm"}; case TOperator::EOpPackSnorm2x16: - return "pack2x16snorm"; + return {"pack2x16snorm"}; case TOperator::EOpPackUnorm4x8: - return "pack4x8unorm"; + return {"pack4x8unorm"}; case TOperator::EOpPackSnorm4x8: - return "pack4x8snorm"; + return {"pack4x8snorm"}; case TOperator::EOpUnpackUnorm2x16: - return "unpack2x16unorm"; + return {"unpack2x16unorm"}; case TOperator::EOpUnpackSnorm2x16: - return "unpack2x16snorm"; + return {"unpack2x16snorm"}; case TOperator::EOpUnpackUnorm4x8: - return "unpack4x8unorm"; + return {"unpack4x8unorm"}; case TOperator::EOpUnpackSnorm4x8: - return "unpack4x8snorm"; + return {"unpack4x8snorm"}; case TOperator::EOpPackHalf2x16: - return "pack2x16float"; + return {"pack2x16float"}; case TOperator::EOpUnpackHalf2x16: - return "unpack2x16float"; + return {"unpack2x16float"}; case TOperator::EOpBarrier: UNREACHABLE(); - return "TOperator_TODO"; + return {"TOperator_TODO"}; case TOperator::EOpMemoryBarrier: // TODO(anglebug.com/42267100): does this exist in WGPU? Device-scoped memory barrier? // Maybe storageBarrier()? UNREACHABLE(); - return "TOperator_TODO"; + return {"TOperator_TODO"}; case TOperator::EOpGroupMemoryBarrier: - return "workgroupBarrier"; + return {"workgroupBarrier"}; case TOperator::EOpMemoryBarrierAtomicCounter: case TOperator::EOpMemoryBarrierBuffer: case TOperator::EOpMemoryBarrierShared: UNREACHABLE(); - return "TOperator_TODO"; + return {"TOperator_TODO"}; case TOperator::EOpAtomicAdd: - return "atomicAdd"; + return {"atomicAdd"}; case TOperator::EOpAtomicMin: - return "atomicMin"; + return {"atomicMin"}; case TOperator::EOpAtomicMax: - return "atomicMax"; + return {"atomicMax"}; case TOperator::EOpAtomicAnd: - return "atomicAnd"; + return {"atomicAnd"}; case TOperator::EOpAtomicOr: - return "atomicOr"; + return {"atomicOr"}; case TOperator::EOpAtomicXor: - return "atomicXor"; + return {"atomicXor"}; case TOperator::EOpAtomicExchange: - return "atomicExchange"; + return {"atomicExchange"}; case TOperator::EOpAtomicCompSwap: - return "atomicCompareExchangeWeak"; // TODO(anglebug.com/42267100): returns a struct. + return {"atomicCompareExchangeWeak"}; // TODO(anglebug.com/42267100): returns a struct. case TOperator::EOpBitfieldExtract: case TOperator::EOpBitfieldInsert: case TOperator::EOpBitfieldReverse: @@ -890,7 +1018,7 @@ const char *GetOperatorString(TOperator op, case TOperator::EOpEndPrimitive: case TOperator::EOpArrayLength: UNIMPLEMENTED(); - return "TOperator_TODO"; + return {"TOperator_TODO"}; case TOperator::EOpNull: case TOperator::EOpConstruct: @@ -901,24 +1029,11 @@ const char *GetOperatorString(TOperator op, case TOperator::EOpIndexDirectStruct: case TOperator::EOpIndexDirectInterfaceBlock: UNREACHABLE(); - return nullptr; + return {nullptr}; default: // Any other built-in function. - return nullptr; - } -} - -bool IsSymbolicOperator(TOperator op, - const TType &resultType, - const TType *argType0, - const TType *argType1) -{ - const char *operatorString = GetOperatorString(op, resultType, argType0, argType1, nullptr); - if (operatorString == nullptr) - { - return false; + return {nullptr}; } - return !std::isalnum(operatorString[0]); } const TField &OutputWGSLTraverser::getDirectField(const TIntermTyped &fieldsNode, @@ -946,6 +1061,7 @@ const TField &OutputWGSLTraverser::getDirectField(const TIntermTyped &fieldsNode return field; } +// Indexes arrays but also matrices. void OutputWGSLTraverser::emitArrayIndex(TIntermTyped &leftNode, TIntermTyped &rightNode) { TType leftType = leftNode.getType(); @@ -955,6 +1071,7 @@ void OutputWGSLTraverser::emitArrayIndex(TIntermTyped &leftNode, TIntermTyped &r // entire array back to the unwrapped type). bool needsUnwrapping = false; bool isUniformMatrixNeedingConversion = false; + bool isUniformBoolNeedingConversion = false; TIntermBinary *leftNodeBinary = leftNode.getAsBinaryNode(); if (leftNodeBinary && leftNodeBinary->getOp() == TOperator::EOpIndexDirectStruct) { @@ -968,11 +1085,23 @@ void OutputWGSLTraverser::emitArrayIndex(TIntermTyped &leftNode, TIntermTyped &r isUniformMatrixNeedingConversion = isInUniformAddressSpace && IsMatCx2(&leftType); + isUniformBoolNeedingConversion = + isInUniformAddressSpace && leftType.getBasicType() == EbtBool; + ASSERT(!needsUnwrapping || !isUniformMatrixNeedingConversion); } - // Emit the left side, which should be of type array. - if (needsUnwrapping || isUniformMatrixNeedingConversion) + enum class ConversionScope + { + kNoConversionFunction, + kConvertTheIndexedMatrix, + kConvertTheWholeArrayIndexExpression, + }; + + ConversionScope conversionFunctionScope = ConversionScope::kNoConversionFunction; + + // Emit the left side, which should be of type matrix or array (including array of matrices). + if (needsUnwrapping || isUniformMatrixNeedingConversion || isUniformBoolNeedingConversion) { if (isUniformMatrixNeedingConversion) { @@ -980,14 +1109,40 @@ void OutputWGSLTraverser::emitArrayIndex(TIntermTyped &leftNode, TIntermTyped &r // array), just convert the entire expression to a WGSL matCx2, // instead of converting the entire array of std140 matCx2s into an array of WGSL // matCx2s and then indexing into it. + // + // NOTE: this could also be indexing a column vector of a matrix. TType baseType = leftType; baseType.toArrayBaseType(); mSink << MakeMatCx2ConversionFunctionName(&baseType) << "("; // Make sure the conversion function referenced here is actually generated in the // resulting WGSL. mWGSLGenerationMetadataForUniforms->outputMatCx2Conversion.insert(baseType); + + // If this an index of a single matrix, it needs conversion *before* indexing. + // Otherwise, if this is a index of an array of matrices, it needs conversion *after* + // indexing. + if (leftType.isArray()) + { + conversionFunctionScope = ConversionScope::kConvertTheWholeArrayIndexExpression; + } + else + { + conversionFunctionScope = ConversionScope::kConvertTheIndexedMatrix; + } + } + else if (isUniformBoolNeedingConversion) + { + // Convert just this one array element into a bool instead of converting the entire + // array into an array of booleans and indexing into that. + OutputUniformBoolOrBvecConversion(mSink, leftType); + conversionFunctionScope = ConversionScope::kConvertTheWholeArrayIndexExpression; } emitStructIndexNoUnwrapping(leftNodeBinary); + + if (conversionFunctionScope == ConversionScope::kConvertTheIndexedMatrix) + { + mSink << ")"; + } } else { @@ -1047,7 +1202,8 @@ void OutputWGSLTraverser::emitArrayIndex(TIntermTyped &leftNode, TIntermTyped &r { mSink << "." << kWrappedStructFieldName; } - else if (isUniformMatrixNeedingConversion) + + if (conversionFunctionScope == ConversionScope::kConvertTheWholeArrayIndexExpression) { // Close conversion function call mSink << ")"; @@ -1068,6 +1224,9 @@ void OutputWGSLTraverser::emitStructIndex(TIntermBinary *binaryNode) bool isUniformMatrixNeedingConversion = isInUniformAddressSpace && IsMatCx2(binaryNodeType); + bool isUniformBoolNeedingConversion = + isInUniformAddressSpace && binaryNode->getBasicType() == EbtBool; + bool needsUnwrapping = ElementTypeNeedsUniformWrapperStruct(isInUniformAddressSpace, binaryNodeType); if (needsUnwrapping) @@ -1087,8 +1246,13 @@ void OutputWGSLTraverser::emitStructIndex(TIntermBinary *binaryNode) // WGSL. mWGSLGenerationMetadataForUniforms->outputMatCx2Conversion.insert(*binaryNodeType); } + else if (isUniformBoolNeedingConversion) + { + // Should only trigger in case of a boolean not in an array. + OutputUniformBoolOrBvecConversion(mSink, *binaryNodeType); + } emitStructIndexNoUnwrapping(binaryNode); - if (needsUnwrapping || isUniformMatrixNeedingConversion) + if (needsUnwrapping || isUniformMatrixNeedingConversion || isUniformBoolNeedingConversion) { mSink << ")"; } @@ -1114,10 +1278,11 @@ bool OutputWGSLTraverser::visitBinary(Visit, TIntermBinary *binaryNode) switch (op) { case TOperator::EOpIndexDirectStruct: - case TOperator::EOpIndexDirectInterfaceBlock: emitStructIndex(binaryNode); break; - + case TOperator::EOpIndexDirectInterfaceBlock: + UNREACHABLE(); // Interface blocks should have been converted into structs. + break; case TOperator::EOpIndexDirect: case TOperator::EOpIndexIndirect: emitArrayIndex(leftNode, rightNode); @@ -1129,45 +1294,51 @@ bool OutputWGSLTraverser::visitBinary(Visit, TIntermBinary *binaryNode) const TType &leftType = leftNode.getType(); const TType &rightType = rightNode.getType(); + const OperatorInfo opInfo = + useOperatorAndGetInfo(binaryNode, op, resultType, &leftType, &rightType, nullptr); + + if (opInfo.wgslWrapperFn) + { + mSink << opInfo.wgslWrapperFn->prefix; + } + + auto emitArgList = [&]() { + leftNode.traverse(this); + mSink << ", "; + rightNode.traverse(this); + }; + // x * y, x ^ y, etc. - if (IsSymbolicOperator(op, resultType, &leftType, &rightType)) + if (opInfo.IsSymbolicOperator()) { groupedTraverse(leftNode); - if (op != TOperator::EOpComma) - { - mSink << " "; - } - mSink << GetOperatorString(op, resultType, &leftType, &rightType, nullptr) << " "; + mSink << " " << opInfo.opName << " "; groupedTraverse(rightNode); } + else if (opInfo.wgslWrapperFn) + { + // Any necessary parentheses should be contained in opInfo.wgslWrapperFn->prefix and + // opInfo.wgslWrapperFn->suffix. + emitArgList(); + } // E.g. builtin function calls else { - mSink << GetOperatorString(op, resultType, &leftType, &rightType, nullptr) << "("; - leftNode.traverse(this); - mSink << ", "; - rightNode.traverse(this); + mSink << opInfo.opName << "("; + emitArgList(); mSink << ")"; } + + if (opInfo.wgslWrapperFn) + { + mSink << opInfo.wgslWrapperFn->suffix; + } } } return false; } -bool IsPostfix(TOperator op) -{ - switch (op) - { - case TOperator::EOpPostIncrement: - case TOperator::EOpPostDecrement: - return true; - - default: - return false; - } -} - bool OutputWGSLTraverser::visitUnary(Visit, TIntermUnary *unaryNode) { const TOperator op = unaryNode->getOp(); @@ -1176,29 +1347,39 @@ bool OutputWGSLTraverser::visitUnary(Visit, TIntermUnary *unaryNode) TIntermTyped &arg = *unaryNode->getOperand(); const TType &argType = arg.getType(); - const char *name = GetOperatorString(op, resultType, &argType, nullptr, nullptr); + const OperatorInfo opInfo = + useOperatorAndGetInfo(unaryNode, op, resultType, &argType, nullptr, nullptr); + + if (opInfo.wgslWrapperFn) + { + mSink << opInfo.wgslWrapperFn->prefix; + } // Examples: -x, ~x, ~x - if (IsSymbolicOperator(op, resultType, &argType, nullptr)) + if (opInfo.IsSymbolicOperator()) { - const bool postfix = IsPostfix(op); - if (!postfix) + if (!opInfo.isPostfix) { - mSink << name; + mSink << opInfo.opName; } groupedTraverse(arg); - if (postfix) + if (opInfo.isPostfix) { - mSink << name; + mSink << opInfo.opName; } } else { - mSink << name << "("; + mSink << opInfo.opName << "("; arg.traverse(this); mSink << ")"; } + if (opInfo.wgslWrapperFn) + { + mSink << opInfo.wgslWrapperFn->suffix; + } + return false; } @@ -1351,15 +1532,25 @@ void OutputWGSLTraverser::emitFunctionReturn(const TFunction &func) emitType(returnType); } -// TODO(anglebug.com/42267100): Function overloads are not supported in WGSL, so function names -// should either be emitted mangled or overloaded functions should be renamed in the AST as a -// pre-pass. As of Apr 2024, WGSL function overloads are "not coming soon" -// (https://github.com/gpuweb/gpuweb/issues/876). +void OutputWGSLTraverser::emitFunctionName(const TFunction &func) +{ + // As of Apr 2024, WGSL function overloads are "not coming soon" + // (https://github.com/gpuweb/gpuweb/issues/876). + // As of Sept 2025, WESL is working on overloads: + // https://github.com/wgsl-tooling-wg/wesl-spec/issues/58. + // So, append the symbol's ID to the overloaded functions.. + if (mOverloadedFunctions->contains(func.uniqueId())) + { + mSink << "ANGLEfunc" << func.uniqueId().get(); + } + WriteNameOf(mSink, func); +} + void OutputWGSLTraverser::emitFunctionSignature(const TFunction &func) { mSink << "fn "; - WriteNameOf(mSink, func); + emitFunctionName(func); mSink << "("; bool emitComma = false; @@ -1392,12 +1583,7 @@ void OutputWGSLTraverser::emitFunctionParameter(const TFunction &func, const TVa void OutputWGSLTraverser::visitFunctionPrototype(TIntermFunctionPrototype *funcProtoNode) { - const TFunction &func = *funcProtoNode->getFunction(); - - emitIndentation(); - // TODO(anglebug.com/42267100): output correct signature for main() if main() is declared as a - // function prototype, or perhaps just emit nothing. - emitFunctionSignature(func); + // WGSL does not need function prototypes at all. Functions can be declared out of order. } bool OutputWGSLTraverser::visitFunctionDefinition(Visit, TIntermFunctionDefinition *funcDefNode) @@ -1413,22 +1599,440 @@ bool OutputWGSLTraverser::visitFunctionDefinition(Visit, TIntermFunctionDefiniti return false; } +void OutputWGSLTraverser::emitTextureBuiltin(const TOperator op, const TIntermSequence &args) +{ + + ASSERT(BuiltInGroup::IsTexture(op)); + + // The index in the GLSL function's argument list of each particular argument, e.g. bias. + // `bias`, `lod`, `offset`, and `P` (the coordinates) are the common arguments to most texture + // functions. + size_t biasIndex = 0; + size_t lodIndex = 0; + size_t offsetIndex = 0; + size_t pIndex = 0; + + size_t dpdxIndex = 0; + size_t dpdyIndex = 0; + + // TODO(anglebug.com/389145696): These are probably incorrect translations when sampling from + // integer or unsigned integer samplers. Using texture() with a usampler + // is similar to using texelFetch(), except wrap modes are respected. Possibly, the correct mip + // levels are also selected. + + // The name of the equivalent texture function in WGSL. + ImmutableString wgslFunctionName(""); + // GLSL stuffs 1, 2, or 3 arguments into a single vector. These represent the swizzles necessary + // for extracting each argument from P to pass to the appropriate WGSL function. + ImmutableString coordsSwizzle(""); + ImmutableString arrayIndexSwizzle(""); + ImmutableString depthRefSwizzle(""); + // For the projection forms of the texture builtins, the last coordinate will divide the other + // three. This is just a swizzle for the last coordinate if the builtin call includes + // projection. + ImmutableString projectionDivisionSwizzle(""); + + ImmutableString wgslTextureVarName(""); + ImmutableString wgslSamplerVarName(""); + + constexpr char k2DCoordsSwizzle[] = ".xy"; + constexpr char k3DCoordsSwizzle[] = ".xyz"; + + constexpr char kPossibleElems[] = "xyzw"; + + // MonomorphizeUnsupportedFunctions() and RewriteStructSamplers() ensure that this is a + // reference to the global sampler. + TIntermSymbol *samplerNode = args[0]->getAsSymbolNode(); + // TODO(anglebug.com/389145696): this will fail if it's an array of samplers, which isn't yet + // handled. + if (!samplerNode) + { + UNIMPLEMENTED(); + mSink << "TODO_UNHANDLED_TEXTURE_FUNCTION()"; + return; + } + TBasicType samplerType = samplerNode->getType().getBasicType(); + ASSERT(IsSampler(samplerType)); + + bool isProj = false; + + auto setWgslTextureVarName = [&]() { + wgslTextureVarName = + BuildConcatenatedImmutableString(kAngleTexturePrefix, samplerNode->getName()); + }; + + auto setWgslSamplerVarName = [&]() { + wgslSamplerVarName = + BuildConcatenatedImmutableString(kAngleSamplerPrefix, samplerNode->getName()); + }; + + auto setTextureSampleFunctionNameFromBias = [&]() { + // TODO(anglebug.com/389145696): these are incorrect translations in vertex shaders, where + // they should probably use textureLoad() (and textureDimensions()). + if (IsShadowSampler(samplerType)) + { + if (biasIndex != 0) + { + // TODO(anglebug.com/389145696): WGSL doesn't support using bias with shadow + // samplers. + UNIMPLEMENTED(); + wgslFunctionName = ImmutableString("TODO_CANNOT_USE_BIAS_WITH_SHADOW_SAMPLER"); + } + else + { + wgslFunctionName = ImmutableString("textureSampleCompare"); + } + } + else + { + if (biasIndex == 0) + { + wgslFunctionName = ImmutableString("textureSample"); + } + else + { + + wgslFunctionName = ImmutableString("textureSampleBias"); + } + } + }; + + switch (op) + { + case EOpTextureSize: + { + lodIndex = 1; + ASSERT(args.size() == 2); + + wgslFunctionName = ImmutableString("textureDimensions"); + setWgslTextureVarName(); + } + break; + + case EOpTexelFetchOffset: + case EOpTexelFetch: + { + pIndex = 1; + lodIndex = 2; + if (args.size() == 4) + { + offsetIndex = 3; + } + ASSERT(args.size() == 3 || args.size() == 4); + + wgslFunctionName = ImmutableString("textureLoad"); + setWgslTextureVarName(); + } + break; + + // texture() use to be split into texture2D() and textureCube(). WGSL matches GLSL 3.0 and + // combines them. + case EOpTextureProj: + case EOpTexture2DProj: + case EOpTextureProjBias: + case EOpTexture2DProjBias: + isProj = true; + [[fallthrough]]; + case EOpTexture: + case EOpTexture2D: + case EOpTextureCube: + case EOpTextureBias: + case EOpTexture2DBias: + case EOpTextureCubeBias: + { + pIndex = 1; + if (args.size() == 3) + { + biasIndex = 2; + } + ASSERT(args.size() == 2 || args.size() == 3); + + setTextureSampleFunctionNameFromBias(); + setWgslTextureVarName(); + setWgslSamplerVarName(); + } + break; + + case EOpTextureProjLod: + case EOpTextureProjLodOffset: + case EOpTexture2DProjLodVS: + case EOpTexture2DProjLodEXTFS: + isProj = true; + [[fallthrough]]; + case EOpTextureLod: + case EOpTexture2DLodVS: + case EOpTextureCubeLodVS: + case EOpTexture2DLodEXTFS: + case EOpTextureCubeLodEXTFS: + case EOpTextureLodOffset: + { + pIndex = 1; + lodIndex = 2; + if (args.size() == 4) + { + offsetIndex = 3; + } + ASSERT(args.size() == 3 || args.size() == 4); + + if (IsShadowSampler(samplerType)) + { + // TODO(anglebug.com/389145696): WGSL may not support explicit LOD with shadow + // samplers. textureSampleCompareLevel() only uses mip level 0. + UNIMPLEMENTED(); + wgslFunctionName = + ImmutableString("TODO_CANNOT_USE_EXPLICIT_LOD_WITH_SHADOW_SAMPLER"); + } + else + { + wgslFunctionName = ImmutableString("textureSampleLevel"); + } + setWgslTextureVarName(); + setWgslSamplerVarName(); + } + break; + + case EOpTextureProjOffset: + case EOpTextureProjOffsetBias: + isProj = true; + [[fallthrough]]; + case EOpTextureOffset: + case EOpTextureOffsetBias: + { + pIndex = 1; + offsetIndex = 2; + if (args.size() == 4) + { + biasIndex = 3; + } + ASSERT(args.size() == 3 || args.size() == 4); + + setTextureSampleFunctionNameFromBias(); + setWgslTextureVarName(); + setWgslSamplerVarName(); + } + break; + + case EOpTextureProjGrad: + case EOpTextureProjGradOffset: + isProj = true; + [[fallthrough]]; + case EOpTextureGrad: + case EOpTextureGradOffset: + { + pIndex = 1; + dpdxIndex = 2; + dpdyIndex = 3; + if (args.size() == 5) + { + offsetIndex = 4; + } + ASSERT(args.size() == 4 || args.size() == 5); + + if (IsShadowSampler(samplerType)) + { + // TODO(anglebug.com/389145696): WGSL may not support explicit gradients with shadow + // samplers. + UNIMPLEMENTED(); + wgslFunctionName = + ImmutableString("TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER"); + } + else + { + wgslFunctionName = ImmutableString("textureSampleGrad"); + } + setWgslTextureVarName(); + setWgslSamplerVarName(); + } + break; + + default: + UNIMPLEMENTED(); + mSink << "TODO_UNHANDLED_TEXTURE_FUNCTION()"; + return; + } + + mSink << wgslFunctionName << "("; + + ASSERT(!wgslTextureVarName.empty()); + mSink << wgslTextureVarName; + + if (!wgslSamplerVarName.empty()) + { + mSink << ", " << wgslSamplerVarName; + + // If using a projection division, set the swizzle that extracts the last argument from the + // p vector. + if (isProj) + { + ASSERT(pIndex == 1); + const uint8_t vecSize = args[pIndex]->getAsTyped()->getNominalSize(); + ASSERT(vecSize == 3 || vecSize == 4); + projectionDivisionSwizzle = + BuildConcatenatedImmutableString('.', kPossibleElems[vecSize - 1]); + } + + // If sampling from an array, set the swizzle that extracts the array layer number from the + // p vector. + if (IsSampler2DArray(samplerType)) + { + arrayIndexSwizzle = ImmutableString(".z"); + } + + // If sampling from a shadow samplers, set the swizzle that extracts the D_ref argument from + // the p vector. + if (IsShadowSampler(samplerType)) + { + size_t elemIndex = 0; + if (IsSampler2D(samplerType)) + { + elemIndex = 2; + } + else if (IsSampler2DArray(samplerType) || IsSampler3D(samplerType) || + IsSamplerCube(samplerType)) + { + elemIndex = 3; + } + + depthRefSwizzle = BuildConcatenatedImmutableString('.', kPossibleElems[elemIndex]); + } + + // Finally, set the swizzle for extracting coordinates from the p vector. + if (IsSampler2D(samplerType) || IsSampler2DArray(samplerType)) + { + coordsSwizzle = ImmutableString(k2DCoordsSwizzle); + } + else if (IsSampler3D(samplerType) || IsSamplerCube(samplerType)) + { + coordsSwizzle = ImmutableString(k3DCoordsSwizzle); + } + } + + // TODO(anglebug.com/389145696): traversing the pArg multiple times is an error if it ever + // contains side effects (e.g. a function call). There is also a problem if this traverses + // function arguments in a different order, arguments with side effects that effect arguments + // that come later may be reordered incorrectly. ESSL specs defined function argument evaluation + // as left-to-right. + auto traversePArg = [&]() { + mSink << "("; + ASSERT(pIndex != 0); + args[pIndex]->traverse(this); + mSink << ")"; + }; + + auto outputProjectionDivisionIfNecessary = [&]() { + if (projectionDivisionSwizzle.empty()) + { + return; + } + mSink << " / "; + traversePArg(); + mSink << projectionDivisionSwizzle; + }; + + // The arguments to the WGSL function always appear in a certain (partial) order, so output them + // in that order. + // + // The order is always + // - texture + // - sampler + // - coordinates + // - array layer index + // - depth_ref, bias, explicit level of detail (never appear together) + // - dfdx + // - dfdy + // - offset + // + // See the texture builtin functions in the WGSL spec: + // https://www.w3.org/TR/WGSL/#texture-builtin-functions + // + // For example + // @must_use fn textureSampleLevel(t: texture_2d_array, + // s: sampler, + // coords: vec2, + // array_index: A, + // level: f32, + // offset: vec2) -> vec4 + + if (pIndex != 0) + { + mSink << ", "; + traversePArg(); + mSink << coordsSwizzle; + outputProjectionDivisionIfNecessary(); + } + + if (!arrayIndexSwizzle.empty()) + { + mSink << ", i32("; + traversePArg(); + mSink << arrayIndexSwizzle << ")"; + } + + if (!depthRefSwizzle.empty()) + { + mSink << ", "; + traversePArg(); + mSink << depthRefSwizzle; + outputProjectionDivisionIfNecessary(); + } + + if (biasIndex != 0) + { + mSink << ", "; + args[biasIndex]->traverse(this); + } + + if (lodIndex != 0) + { + mSink << ", "; + args[lodIndex]->traverse(this); + } + + if (dpdxIndex != 0) + { + mSink << ", "; + args[dpdxIndex]->traverse(this); + } + + if (dpdyIndex != 0) + { + mSink << ", "; + args[dpdyIndex]->traverse(this); + } + + if (offsetIndex != 0) + { + mSink << ", "; + // Both GLSL and WGSL require this to be a const expression. + args[offsetIndex]->traverse(this); + } + + mSink << ")"; +} + bool OutputWGSLTraverser::visitAggregate(Visit, TIntermAggregate *aggregateNode) { const TIntermSequence &args = *aggregateNode->getSequence(); + const TFunction *callee = aggregateNode->getFunction(); // Can be nullptr auto emitArgList = [&]() { mSink << "("; bool emitComma = false; - for (TIntermNode *arg : args) + for (size_t i = 0; i < args.size(); i++) { if (emitComma) { mSink << ", "; } emitComma = true; - arg->traverse(this); + + // If outparams, must pass a pointer. + if (callee && IsParamOut(callee->getParam(i)->getType().getQualifier())) + { + mSink << "&"; + } + args[i]->traverse(this); } mSink << ")"; @@ -1450,14 +2054,21 @@ bool OutputWGSLTraverser::visitAggregate(Visit, TIntermAggregate *aggregateNode) switch (op) { case TOperator::EOpCallFunctionInAST: - WriteNameOf(mSink, *aggregateNode->getFunction()); + emitFunctionName(*callee); emitArgList(); return false; default: - // Do not allow raw function calls, i.e. calls to functions - // not present in the AST. - ASSERT(op != TOperator::EOpCallInternalRawFunction); + // There is one raw call currently and that is used to get a pointer to an l-value. + if (op == EOpCallInternalRawFunction) + { + ASSERT(callee->name() == "ANGLE_takePointer"); + ASSERT(args.size() == 1); + mSink << "&"; + groupedTraverse(*aggregateNode->getChildNode(0)); + return false; + } + auto getArgType = [&](size_t index) -> const TType * { if (index < args.size()) { @@ -1472,27 +2083,25 @@ bool OutputWGSLTraverser::visitAggregate(Visit, TIntermAggregate *aggregateNode) const TType *argType1 = getArgType(1); const TType *argType2 = getArgType(2); - const char *opName = GetOperatorString(op, retType, argType0, argType1, argType2); + const OperatorInfo opInfo = + useOperatorAndGetInfo(aggregateNode, op, retType, argType0, argType1, argType2); + + if (opInfo.wgslWrapperFn) + { + mSink << opInfo.wgslWrapperFn->prefix; + } - if (IsSymbolicOperator(op, retType, argType0, argType1)) + if (opInfo.IsSymbolicOperator()) { switch (args.size()) { case 1: { TIntermNode &operandNode = *aggregateNode->getChildNode(0); - if (IsPostfix(op)) - { - mSink << opName; - groupedTraverse(operandNode); - } - else - { - groupedTraverse(operandNode); - mSink << opName; - } - return false; + mSink << opInfo.opName; + groupedTraverse(operandNode); } + break; case 2: { @@ -1500,10 +2109,10 @@ bool OutputWGSLTraverser::visitAggregate(Visit, TIntermAggregate *aggregateNode) TIntermNode &leftNode = *aggregateNode->getChildNode(0); TIntermNode &rightNode = *aggregateNode->getChildNode(1); groupedTraverse(leftNode); - mSink << " " << opName << " "; + mSink << " " << opInfo.opName << " "; groupedTraverse(rightNode); - return false; } + break; default: UNREACHABLE(); @@ -1512,18 +2121,25 @@ bool OutputWGSLTraverser::visitAggregate(Visit, TIntermAggregate *aggregateNode) } else { - if (opName == nullptr) + // Rewrite the calls to sampler functions. + if (BuiltInGroup::IsTexture(op)) { - // TODO(anglebug.com/42267100): opName should not be allowed to be nullptr - // here, but for now not all builtins are mapped to a string. - opName = "TODO_Operator"; + emitTextureBuiltin(op, args); + ASSERT(!opInfo.wgslWrapperFn.has_value()); + return false; } // If the operator is not symbolic then it is a builtin that uses function call // syntax: builtin(arg1, arg2, ..); - mSink << opName; + mSink << (opInfo.opName == nullptr ? "TODO_Operator" : opInfo.opName); emitArgList(); - return false; } + + if (opInfo.wgslWrapperFn) + { + mSink << opInfo.wgslWrapperFn->suffix; + } + + return false; } } } @@ -1594,8 +2210,7 @@ bool OutputWGSLTraverser::visitGlobalQualifierDeclaration(Visit, void OutputWGSLTraverser::emitStructDeclaration(const TType &type) { - ASSERT(type.getBasicType() == TBasicType::EbtStruct); - ASSERT(type.isStructSpecifier()); + ASSERT(type.getBasicType() == TBasicType::EbtStruct && type.isStructSpecifier()); mSink << "struct "; emitBareTypeName(type); @@ -1668,9 +2283,11 @@ void OutputWGSLTraverser::emitVariableDeclaration(const VarDecl &decl, { const TBasicType basicType = decl.type.getBasicType(); - if (decl.type.getQualifier() == EvqUniform) + if ((decl.type.getQualifier() == EvqUniform || decl.type.getQualifier() == EvqBuffer) && + evdConfig.isGlobalScope) { - // Uniforms are declared in a pre-pass, and don't need to be outputted here. + // Uniforms/interface blocks are declared in a pre-pass, and don't need to be outputted + // here. return; } @@ -1694,15 +2311,32 @@ void OutputWGSLTraverser::emitVariableDeclaration(const VarDecl &decl, ASSERT(basicType == TBasicType::EbtStruct || decl.symbolType != SymbolType::Empty || evdConfig.isParameter); - if (evdConfig.needsVar) + if (evdConfig.isDeclaration) { - // "const" and "let" probably don't need to be ever emitted because they are more for - // readability, and the GLSL compiler constant folds most (all?) the consts anyway. - mSink << "var"; - // TODO(anglebug.com/42267100): or ? - if (evdConfig.isGlobalScope) + // Pointers in WGSL must be declared with let. + if (evdConfig.emitAsPointer) + { + mSink << "let"; + } + else if (decl.type.getQualifier() == EvqConst) + { + mSink << "const"; + } + else { - mSink << ""; + mSink << "var"; + if (evdConfig.isGlobalScope) + { + if (decl.type.getQualifier() == EvqUniform) + { + ASSERT(IsOpaqueType(decl.type.getBasicType())); + mSink << ""; + } + else + { + mSink << ""; + } + } } mSink << " "; } @@ -1716,7 +2350,26 @@ void OutputWGSLTraverser::emitVariableDeclaration(const VarDecl &decl, emitNameOf(decl); } mSink << " : "; + + bool isOutParam = evdConfig.isParameter && IsParamOut(decl.type.getQualifier()); + if (isOutParam) + { + // Arguments to outparams will always be function-local due to AST pre-passes. + mSink << "ptr"; + } } bool OutputWGSLTraverser::visitDeclaration(Visit, TIntermDeclaration *declNode) @@ -1725,7 +2378,7 @@ bool OutputWGSLTraverser::visitDeclaration(Visit, TIntermDeclaration *declNode) TIntermNode &node = *declNode->getChildNode(0); EmitVariableDeclarationConfig evdConfig; - evdConfig.needsVar = true; + evdConfig.isDeclaration = true; evdConfig.isGlobalScope = mIndentLevel == 0; if (TIntermSymbol *symbolNode = node.getAsSymbolNode()) @@ -1756,6 +2409,19 @@ bool OutputWGSLTraverser::visitDeclaration(Visit, TIntermDeclaration *declNode) return false; } + if (valueNode->getAsAggregate() && valueNode->getAsAggregate()->getFunction()) + { + const TFunction *func = valueNode->getAsAggregate()->getFunction(); + if (valueNode->getAsAggregate()->getOp() == EOpCallInternalRawFunction && + func->name() == "ANGLE_takePointer") + { + mIsActuallyOfPointerType.insert(leftSymbolNode->uniqueId()); + + evdConfig.emitAsPointer = GetWgslAddressSpaceForPointer( + FindRootVariable(valueNode->getAsAggregate()->getChildNode(0))->getType()); + } + } + emitVariableDeclaration({var.symbolType(), var.name(), var.getType()}, evdConfig); mSink << " = "; groupedTraverse(*valueNode); @@ -1846,6 +2512,23 @@ bool OutputWGSLTraverser::emulateDoWhileLoop(TIntermLoop *loopNode) { ASSERT(loopNode->getType() == TLoopType::ELoopDoWhile); + // Emulate do-while with an infinite loop and a WGSL-special "continuing" and "break-if" + // statement. + // + // Example GLSL: + // do { + // // Loop body, which might contain 'continue' + // } while(condition) + // + // Becomes WGSL: + // loop { + // // Loop body, which might contain 'continue' + + // continuing { + // break if !condition; + // } + // } + TIntermNode *initNode = loopNode->getInit(); TIntermTyped *condNode = loopNode->getCondition(); TIntermTyped *exprNode = loopNode->getExpression(); @@ -1856,13 +2539,20 @@ bool OutputWGSLTraverser::emulateDoWhileLoop(TIntermLoop *loopNode) // Write an infinite loop. mSink << "loop {\n"; mIndentLevel++; + // The loop body may contain a "continue" branch. loopNode->getBody()->traverse(this); mSink << "\n"; emitIndentation(); // At the end of the loop, break if the loop condition dos not still hold. - mSink << "if (!("; + mSink << "continuing {\n"; + mIndentLevel++; + emitIndentation(); + mSink << "break if !("; condNode->traverse(this); - mSink << ") { break; }\n"; + mSink << ");\n"; + mIndentLevel--; + emitIndentation(); + mSink << "}\n"; mIndentLevel--; emitIndentation(); mSink << "}"; @@ -1936,21 +2626,199 @@ void OutputWGSLTraverser::emitType(const TType &type) WriteWgslType(mSink, type, {}); } +// Unlike Vulkan having auto viewport flipping extension, in WGPU we have to flip gl_Position.y +// manually. +// This operation performs flipping the gl_Position.y using this expression: +// gl_Position.y = gl_Position.y * negViewportScaleY +[[nodiscard]] bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + TIntermTyped *negFlipY) +{ + // Create a symbol reference to "gl_Position" + const TVariable *position = BuiltInVariable::gl_Position(); + TIntermSymbol *positionRef = new TIntermSymbol(position); + + // Create a swizzle to "gl_Position.y" + TVector swizzleOffsetY; + swizzleOffsetY.push_back(1); + TIntermSwizzle *positionY = new TIntermSwizzle(positionRef, swizzleOffsetY); + + // Create the expression "gl_Position.y * negFlipY" + TIntermBinary *inverseY = new TIntermBinary(EOpMul, positionY->deepCopy(), negFlipY); + + // Create the assignment "gl_Position.y = gl_Position.y * negViewportScaleY + TIntermTyped *positionYLHS = positionY->deepCopy(); + TIntermBinary *assignment = new TIntermBinary(TOperator::EOpAssign, positionYLHS, inverseY); + + // Append the assignment as a statement at the end of the shader. + return RunAtTheEndOfShader(compiler, root, assignment, symbolTable); +} + } // namespace TranslatorWGSL::TranslatorWGSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : TCompiler(type, spec, output) {} +bool TranslatorWGSL::preTranslateTreeModifications(TIntermBlock *root, + const TVariable **defaultUniformBlockOut) +{ + if (!PullExpressionsIntoFunctions(this, root)) + { + return false; + } + + if (!EmulateMutableFunctionParams(this, root)) + { + return false; + } + + if (!RewriteMixedTypeMathExprs(this, root)) + { + return false; + } + + if (!RewriteMultielementSwizzleAssignment(this, root)) + { + return false; + } + + int aggregateTypesUsedForUniforms = 0; + for (const auto &uniform : getUniforms()) + { + if (uniform.isStruct() || uniform.isArrayOfArrays()) + { + ++aggregateTypesUsedForUniforms; + } + } + + // TODO(anglebug.com/42267100): just use the struct mode to avoid a rewrite of the interface + // block by ReduceInterfaceBlocks into a struct. + DriverUniform driverUniforms(DriverUniformMode::InterfaceBlock); + ASSERT(getShaderType() != GL_COMPUTE_SHADER); + driverUniforms.addGraphicsDriverUniformsToShader(root, &getSymbolTable()); + + if (getShaderType() == GL_VERTEX_SHADER) + { + TIntermTyped *flipNegY = + driverUniforms.getFlipXY(&getSymbolTable(), DriverUniformFlip::PreFragment); + flipNegY = (new TIntermSwizzle(flipNegY, {1}))->fold(nullptr); + + if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(), flipNegY)) + { + return false; + } + } + + // Samplers are legal as function parameters, but samplers within structs or arrays are not + // allowed in WGSL + // (https://www.w3.org/TR/WGSL/#function-call-expr:~:text=A%20function%20parameter,a%20sampler%20type). + // TODO(anglebug.com/389145696): handle arrays of samplers here. + + // If there are any function calls that take array-of-array of opaque uniform parameters, or + // other opaque uniforms that need special handling in WebGPU, monomorphize the functions by + // removing said parameters and replacing them in the function body with the call arguments. + // + // This dramatically simplifies future transformations w.r.t to samplers in structs, array of + // arrays of opaque types, atomic counters etc. + UnsupportedFunctionArgsBitSet args{UnsupportedFunctionArgs::StructContainingSamplers, + UnsupportedFunctionArgs::ArrayOfArrayOfSamplerOrImage, + UnsupportedFunctionArgs::AtomicCounter, + UnsupportedFunctionArgs::Image}; + if (!MonomorphizeUnsupportedFunctions(this, root, &getSymbolTable(), args)) + { + return false; + } + + if (aggregateTypesUsedForUniforms > 0) + { + if (!SeparateStructFromUniformDeclarations(this, root, &getSymbolTable())) + { + return false; + } + + int removedUniformsCount; + + // Requires MonomorphizeUnsupportedFunctions() to have been run already. + if (!RewriteStructSamplers(this, root, &getSymbolTable(), &removedUniformsCount)) + { + return false; + } + } + + // Replace array of array of opaque uniforms with a flattened array. This is run after + // MonomorphizeUnsupportedFunctions and RewriteStructSamplers so that it's not possible for an + // array of array of opaque type to be partially subscripted and passed to a function. + // TODO(anglebug.com/389145696): Even single-level arrays of samplers are not allowed in WGSL. + if (!RewriteArrayOfArrayOfOpaqueUniforms(this, root, &getSymbolTable())) + { + return false; + } + + // RewriteStructSamplers should have already run at this point so there are not default + // uniforms containing samplers, even within a nested struct. + gl::ShaderType packedShaderType = gl::FromGLenum(getShaderType()); + if (!GatherDefaultUniforms(this, root, &getSymbolTable(), packedShaderType, + ImmutableString(kDefaultUniformBlockVarType), + ImmutableString(kDefaultUniformBlockVarName), + defaultUniformBlockOut)) + { + return false; + } + + // Note: It would be possible to to avoid running this AST modification by outputting + // interface blocks like structs, with the wrinkle that interface blocks don't need an instance + // variable name and so this translator would have to generate a new one and keep a map of + // TInterfaceBlock -> WGSLName in order to output field accesses of the interface block. + int uniqueStructId = 0; + if (!ReduceInterfaceBlocks(*this, *root, [&uniqueStructId]() -> ImmutableString { + return BuildConcatenatedImmutableString("ANGLE_unnamed_interface_block_", + uniqueStructId++); + })) + { + return false; + } + + return true; +} + bool TranslatorWGSL::translate(TIntermBlock *root, const ShCompileOptions &compileOptions, PerformanceDiagnostics *perfDiagnostics) { + // TODO(https://issues.angleproject.org/issues/42264589#comment3): remove this, as it is + // deprecated. + mValidateASTOptions.validateNoRawFunctionCalls = false; + + if (kOutputTreeBeforeTranslation) + { + TInfoSinkBase treeOut; + std::cout << "Initial tree for shader type " + << (getShaderType() == GL_VERTEX_SHADER ? "vertex shader" + : getShaderType() == GL_FRAGMENT_SHADER ? "fragment shader " + : "unknown") + << std::endl; + OutputTree(root, treeOut); + std::cout << treeOut.c_str(); + } + + const TVariable *defaultUniformBlock = nullptr; + + if (!preTranslateTreeModifications(root, &defaultUniformBlock)) + { + return false; + } + if (kOutputTreeBeforeTranslation) { - OutputTree(root, getInfoSink().info); - std::cout << getInfoSink().info.c_str(); + TInfoSinkBase treeOut; + std::cout << "After preTranslateTreeModifications(): " << std::endl; + getInfoSink().info.erase(); + OutputTree(root, treeOut); + std::cout << treeOut.c_str(); } + enableValidateNoMoreTransformations(); RewritePipelineVarOutput rewritePipelineVarOutput(getShaderType()); WGSLGenerationMetadataForUniforms wgslGenerationMetadataForUniforms; @@ -1959,33 +2827,55 @@ bool TranslatorWGSL::translate(TIntermBlock *root, // builtin variables are used. if (!GenerateMainFunctionAndIOStructs(*this, *root, rewritePipelineVarOutput)) { + ANGLE_LOG(ERR) << "Failed to generate WGSL main functions"; return false; } TInfoSinkBase &sink = getInfoSink().obj; - // Start writing the output structs that will be referred to by the `traverser`'s output.' - if (!rewritePipelineVarOutput.OutputStructs(sink)) - { - return false; - } - if (!OutputUniformBlocks(this, root)) - { - return false; - } + // GLSL allows derivatives to be calculated as long as control flow is dynamically uniform. WGSL + // triggers a derivative_uniformity diagnostic whenever it cannot statically determine that + // control flow is uniform, which is by default an error. Since this compiler must implement + // GLSL semantics, use a global diagnostic filter to turn derivative_uniformity diagnostics into + // warnings instead of the default error. + // See https://github.com/gpuweb/gpuweb/issues/3479 and the spec: + // https://www.w3.org/TR/WGSL/#uniformity + sink << "diagnostic(warning,derivative_uniformity);\n"; UniformBlockMetadata uniformBlockMetadata; if (!RecordUniformBlockMetadata(root, uniformBlockMetadata)) { + ANGLE_LOG(ERR) << "Failed to record uniform block metadata"; return false; } + TUnorderedSet overloadedFunctions = FindOverloadedFunctions(root); + WGSLProgramPrelude prelude; + // Generate the body of the WGSL including the GLSL main() function. TInfoSinkBase traverserOutput; OutputWGSLTraverser traverser(&traverserOutput, &rewritePipelineVarOutput, - &uniformBlockMetadata, &wgslGenerationMetadataForUniforms); + &uniformBlockMetadata, &wgslGenerationMetadataForUniforms, + &overloadedFunctions, &prelude); root->traverse(&traverser); + // The makeup of the prelude is determined by the traverser, and then must be outputted near the + // top of the program. + prelude.outputPrelude(sink); + + // Start writing the output structs that will be referred to by the `traverser`'s output.' + if (!rewritePipelineVarOutput.OutputStructs(sink)) + { + ANGLE_LOG(ERR) << "Failed to output pipeline structs"; + return false; + } + + if (!OutputUniformBlocksAndSamplers(this, root, defaultUniformBlock)) + { + ANGLE_LOG(ERR) << "Failed to output uniform blocks and samplers"; + return false; + } + sink << "\n"; OutputUniformWrapperStructsAndConversions(sink, wgslGenerationMetadataForUniforms); @@ -1996,6 +2886,7 @@ bool TranslatorWGSL::translate(TIntermBlock *root, // Write the actual WGSL main function, wgslMain(), which calls the GLSL main function. if (!rewritePipelineVarOutput.OutputMainFunction(sink)) { + ANGLE_LOG(ERR) << "Failed to output WGSL main function"; return false; } diff --git a/src/compiler/translator/wgsl/TranslatorWGSL.h b/src/compiler/translator/wgsl/TranslatorWGSL.h index d5c30e197ac..5b8fc9dbf76 100644 --- a/src/compiler/translator/wgsl/TranslatorWGSL.h +++ b/src/compiler/translator/wgsl/TranslatorWGSL.h @@ -11,12 +11,16 @@ namespace sh { +class TVariable; + class TranslatorWGSL : public TCompiler { public: TranslatorWGSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); protected: + bool preTranslateTreeModifications(TIntermBlock *root, + const TVariable **defaultUniformBlockOut); bool translate(TIntermBlock *root, const ShCompileOptions &compileOptions, PerformanceDiagnostics *perfDiagnostics) override; diff --git a/src/compiler/translator/wgsl/Utils.cpp b/src/compiler/translator/wgsl/Utils.cpp index 2937e97c7d1..1e4372b5d6b 100644 --- a/src/compiler/translator/wgsl/Utils.cpp +++ b/src/compiler/translator/wgsl/Utils.cpp @@ -6,7 +6,10 @@ #include "compiler/translator/wgsl/Utils.h" +#include "common/log_utils.h" +#include "compiler/translator/BaseTypes.h" #include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableStringBuilder.h" #include "compiler/translator/Symbol.h" #include "compiler/translator/Types.h" @@ -30,9 +33,20 @@ void WriteWgslBareTypeName(StringStreamType &output, switch (basicType) { case TBasicType::EbtVoid: - case TBasicType::EbtBool: output << type.getBasicString(); break; + case TBasicType::EbtBool: + if (config.addressSpace == WgslAddressSpace::Uniform) + { + // The uniform address space does not support bools in WGSL, so they are emulated + // with u32 (which matches gles because bools are 4-bytes long in std140). + output << "u32"; + } + else + { + output << "bool"; + } + break; // TODO(anglebug.com/42267100): is there double precision (f64) in GLSL? It doesn't really // exist in WGSL (i.e. f64 does not exist but AbstractFloat can handle 64 bits???) Metal // does not have 64 bit double precision types. It's being implemented in WGPU: @@ -58,38 +72,19 @@ void WriteWgslBareTypeName(StringStreamType &output, default: if (IsSampler(basicType)) { - // TODO(anglebug.com/42267100): possibly emit both a sampler and a texture2d. WGSL - // has sampler variables for the sampler configuration, whereas GLSL has sampler2d - // and other sampler* variables for an actual texture. - output << "texture2d<"; - switch (type.getBasicType()) - { - case EbtSampler2D: - output << "f32"; - break; - case EbtISampler2D: - output << "i32"; - break; - case EbtUSampler2D: - output << "u32"; - break; - default: - // TODO(anglebug.com/42267100): are any of the other sampler types necessary - // to translate? - UNIMPLEMENTED(); - break; - } - if (type.getMemoryQualifier().readonly || type.getMemoryQualifier().writeonly) - { - // TODO(anglebug.com/42267100): implement memory qualifiers. - UNIMPLEMENTED(); - } - output << ">"; + // Variables of sampler type should be written elsewhere since they require special + // handling; they are split into two different variables in WGSL. + + // TODO(anglebug.com/389145696): this is reachable if a sampler is passed as a + // function parameter. They should be monomorphized. + UNIMPLEMENTED(); } else if (IsImage(basicType)) { - // TODO(anglebug.com/42267100): does texture2d also correspond to GLSL's image type? - output << "texture2d<"; + // GLSL's image types are not implemented in this backend. + UNIMPLEMENTED(); + + output << "texture_storage_2d<"; switch (type.getBasicType()) { case EbtImage2D: @@ -102,15 +97,12 @@ void WriteWgslBareTypeName(StringStreamType &output, output << "u32"; break; default: - // TODO(anglebug.com/42267100): are any of the other image types necessary - // to translate? UNIMPLEMENTED(); break; } if (type.getMemoryQualifier().readonly || type.getMemoryQualifier().writeonly) { - // TODO(anglebug.com/42267100): implement memory qualifiers. - UNREACHABLE(); + UNIMPLEMENTED(); } output << ">"; } @@ -131,7 +123,7 @@ void WriteNameOf(StringStreamType &output, SymbolType symbolType, const Immutabl output << name; break; case SymbolType::UserDefined: - output << kUserDefinedNamePrefix << name; + output << '_' << kUserDefinedNamePrefix << name; break; case SymbolType::AngleInternal: output << name; @@ -147,6 +139,9 @@ void WriteWgslType(StringStreamType &output, const TType &type, const EmitTypeCo { if (type.isArray()) { + // WGSL does not support samplers anywhere inside structs or arrays. + ASSERT(!type.isSampler() && !type.isStructureContainingSamplers()); + // Examples: // array // array, 10> @@ -220,9 +215,111 @@ template void WriteWgslType(TStringStream &output, const TType &type, const EmitTypeConfig &config); +template +void WriteWgslSamplerType(StringStreamType &output, + const TType &type, + WgslSamplerTypeConfig samplerType) +{ + ASSERT(type.isSampler()); + if (samplerType == WgslSamplerTypeConfig::Texture) + { + output << "texture"; + if (IsShadowSampler(type.getBasicType())) + { + output << "_depth"; + } + + if (IsSamplerMS(type.getBasicType())) + { + output << "_multisampled"; + ASSERT(IsSampler2D(type.getBasicType())); + // Unsupported in wGSL, it seems. + ASSERT(!IsSampler2DMSArray(type.getBasicType())); + } + + if (IsSampler2D(type.getBasicType()) || IsSampler2DArray(type.getBasicType())) + { + output << "_2d"; + } + else if (IsSampler3D(type.getBasicType())) + { + output << "_3d"; + } + else if (IsSamplerCube(type.getBasicType())) + { + output << "_cube"; + } + + if (IsSamplerArray(type.getBasicType())) + { + ASSERT(!IsSampler3D(type.getBasicType())); + output << "_array"; + } + + // Shadow samplers are always floating point in both GLSL and WGSL and don't need to be + // parameterized. + if (!IsShadowSampler(type.getBasicType())) + { + output << "<"; + if (!IsIntegerSampler(type.getBasicType())) + { + output << "f32"; + } + else if (!IsIntegerSamplerUnsigned(type.getBasicType())) + { + output << "i32"; + } + else + { + output << "u32"; + } + output << ">"; + } + if (type.getMemoryQualifier().readonly || type.getMemoryQualifier().writeonly) + { + // TODO(anglebug.com/42267100): implement memory qualifiers. + UNIMPLEMENTED(); + } + } + else + { + ASSERT(samplerType == WgslSamplerTypeConfig::Sampler); + // sampler or sampler_comparison. + if (IsShadowSampler(type.getBasicType())) + { + output << "sampler_comparison"; + } + else + { + output << "sampler"; + } + } +} + +template void WriteWgslSamplerType(TInfoSinkBase &output, + const TType &type, + WgslSamplerTypeConfig samplerType); + +template void WriteWgslSamplerType(TStringStream &output, + const TType &type, + WgslSamplerTypeConfig samplerType); + ImmutableString MakeUniformWrapperStructName(const TType *type) { - return BuildConcatenatedImmutableString(kWrappedPrefix, type->getBuiltInTypeNameString()); + TType typeToOutput(*type); + + const char *typeStr; + // Bools are represented as u32s in the uniform address space (and bvecs as uvecs). + // TODO(anglebug.com/376553328): simplify by using WriteWgslType({WgslAddressSpace::Uniform}) + // here. + if (typeToOutput.getBasicType() == EbtBool) + { + typeToOutput.setBasicType(TBasicType::EbtUInt); + } + + typeStr = typeToOutput.getBuiltInTypeNameString(); + + return BuildConcatenatedImmutableString(kWrappedPrefix, typeStr); } bool ElementTypeNeedsUniformWrapperStruct(bool inUniformAddressSpace, const TType *type) @@ -245,9 +342,7 @@ bool ElementTypeNeedsUniformWrapperStruct(bool inUniformAddressSpace, const TTyp // - vec3 and vec4 are already aligned to 16, but vec2 needs to be aligned. // - Matrices are aligned to 16 automatically, except matCx2 which already needs to be handled // by specialized code anyway. - // TODO(anglebug.com/376553328): re-enable this ASSERT once matCx2 are handled. - // ASSERT(!type->isMatrix() || type->getRows() != 2); - // - WebGL2 doesn't support nested arrays so this won't either, though support wouldn't be hard. + // - WebGL2 doesn't support nested arrays so this won't either. ASSERT(!elementType.isArray()); return elementType.isScalar() || (elementType.isVector() && elementType.getNominalSize() == 2); @@ -267,4 +362,33 @@ GlobalVars FindGlobalVars(TIntermBlock *root) return globals; } +WgslPointerAddressSpace GetWgslAddressSpaceForPointer(const TType &type) +{ + switch (type.getQualifier()) + { + case EvqTemporary: + // NOTE: As of Sept 2025, parameters are immutable in WGSL (and are handled by an AST pass + // that copies parameters to temporaries). Include these here in case parameters become + // mutable in the future. + case EvqParamIn: + case EvqParamOut: + case EvqParamInOut: + return WgslPointerAddressSpace::Function; + default: + // EvqGlobal and various other shader outputs/builtins are all globals. + return WgslPointerAddressSpace::Private; + } +} + +ImmutableString StringForWgslPointerAddressSpace(WgslPointerAddressSpace as) +{ + switch (as) + { + case WgslPointerAddressSpace::Function: + return ImmutableString("function"); + case WgslPointerAddressSpace::Private: + return ImmutableString("private"); + } +} + } // namespace sh diff --git a/src/compiler/translator/wgsl/Utils.h b/src/compiler/translator/wgsl/Utils.h index 5ced54f9b0e..7ebf9f559dc 100644 --- a/src/compiler/translator/wgsl/Utils.h +++ b/src/compiler/translator/wgsl/Utils.h @@ -47,6 +47,19 @@ void WriteWgslBareTypeName(StringStreamType &output, template void WriteWgslType(StringStreamType &output, const TType &type, const EmitTypeConfig &config); +// GLSL's samplers are split into a separate sampler and texture in WGSL, so two different types +// will be emitted for a single sampler type. +enum class WgslSamplerTypeConfig +{ + Sampler, + Texture +}; + +template +void WriteWgslSamplerType(StringStreamType &output, + const TType &type, + WgslSamplerTypeConfig samplerType); + // From the type, creates a legal WGSL name for a struct that wraps it. ImmutableString MakeUniformWrapperStructName(const TType *type); @@ -57,6 +70,15 @@ bool ElementTypeNeedsUniformWrapperStruct(bool inUniformAddressSpace, const TTyp using GlobalVars = TMap; GlobalVars FindGlobalVars(TIntermBlock *root); +enum class WgslPointerAddressSpace +{ + Private, + Function +}; + +WgslPointerAddressSpace GetWgslAddressSpaceForPointer(const TType &type); +ImmutableString StringForWgslPointerAddressSpace(WgslPointerAddressSpace as); + } // namespace sh #endif // COMPILER_TRANSLATOR_WGSL_UTILS_H_ diff --git a/src/compiler/translator/wgsl/WGSLProgramPrelude.cpp b/src/compiler/translator/wgsl/WGSLProgramPrelude.cpp new file mode 100644 index 00000000000..963cdae56d7 --- /dev/null +++ b/src/compiler/translator/wgsl/WGSLProgramPrelude.cpp @@ -0,0 +1,246 @@ +// +// Copyright 2025 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. +// + +#include "compiler/translator/wgsl/WGSLProgramPrelude.h" +#include "common/log_utils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/util.h" +#include "compiler/translator/wgsl/Utils.h" + +namespace sh +{ + +namespace +{ +constexpr ImmutableString kEndParanthesis = ImmutableString(")"); + +void EmitConstructorList(TInfoSinkBase &sink, const TType &type, ImmutableString scalar) +{ + ASSERT(!type.isArray()); + ASSERT(!type.getStruct()); + + sink << "("; + size_t numScalars = 1; + if (type.isMatrix()) + { + numScalars = type.getCols() * type.getRows(); + } + for (size_t i = 0; i < numScalars; i++) + { + if (i != 0) + { + sink << ", "; + } + sink << scalar; + } + sink << ")"; +} + +ImmutableString ConcatId(const char *prefix, uint64_t funcId) +{ + return BuildConcatenatedImmutableString("ANGLE_", prefix, "_", funcId); +} + +template +uint64_t InsertIntoMapWithUniqueId(uint64_t &idCounter, TMap &map, const T &key) +{ + auto [iterator, inserted] = map.try_emplace(key, idCounter); + + if (inserted) + { + idCounter++; + } + + return iterator->second; +} +} // namespace + +WGSLWrapperFunction WGSLProgramPrelude::preIncrement(const TType &incrementedType) +{ + ASSERT(incrementedType.getBasicType() == EbtInt || incrementedType.getBasicType() == EbtUInt || + incrementedType.getBasicType() == EbtFloat); + + uint64_t uniqueId = + InsertIntoMapWithUniqueId(mUniqueFuncId, mPreIncrementedTypes, incrementedType); + switch (GetWgslAddressSpaceForPointer(incrementedType)) + { + case WgslPointerAddressSpace::Function: + return {BuildConcatenatedImmutableString(ConcatId("preIncFunc", uniqueId), "(&"), + kEndParanthesis}; + case WgslPointerAddressSpace::Private: + // EvqGlobal and various other shader outputs/builtins are all globals. + return {BuildConcatenatedImmutableString(ConcatId("preIncPriv", uniqueId), "(&"), + kEndParanthesis}; + } +} + +WGSLWrapperFunction WGSLProgramPrelude::preDecrement(const TType &decrementedType) +{ + uint64_t uniqueId = + InsertIntoMapWithUniqueId(mUniqueFuncId, mPreDecrementedTypes, decrementedType); + + switch (GetWgslAddressSpaceForPointer(decrementedType)) + { + case WgslPointerAddressSpace::Function: + return {BuildConcatenatedImmutableString(ConcatId("preDecFunc", uniqueId), "(&"), + kEndParanthesis}; + case WgslPointerAddressSpace::Private: + // EvqGlobal and various other shader outputs/builtins are all globals. + return {BuildConcatenatedImmutableString(ConcatId("preDecPriv", uniqueId), "(&"), + kEndParanthesis}; + } +} + +WGSLWrapperFunction WGSLProgramPrelude::postIncrement(const TType &incrementedType) +{ + uint64_t uniqueId = + InsertIntoMapWithUniqueId(mUniqueFuncId, mPostIncrementedTypes, incrementedType); + + switch (GetWgslAddressSpaceForPointer(incrementedType)) + { + case WgslPointerAddressSpace::Function: + return {BuildConcatenatedImmutableString(ConcatId("postIncFunc", uniqueId), "(&"), + kEndParanthesis}; + case WgslPointerAddressSpace::Private: + // EvqGlobal and various other shader outputs/builtins are all globals. + return {BuildConcatenatedImmutableString(ConcatId("postIncPriv", uniqueId), "(&"), + kEndParanthesis}; + } +} + +WGSLWrapperFunction WGSLProgramPrelude::postDecrement(const TType &decrementedType) +{ + uint64_t uniqueId = + InsertIntoMapWithUniqueId(mUniqueFuncId, mPostDecrementedTypes, decrementedType); + + switch (GetWgslAddressSpaceForPointer(decrementedType)) + { + case WgslPointerAddressSpace::Function: + return {BuildConcatenatedImmutableString(ConcatId("postDecFunc", uniqueId), "(&"), + kEndParanthesis}; + case WgslPointerAddressSpace::Private: + // EvqGlobal and various other shader outputs/builtins are all globals. + return {BuildConcatenatedImmutableString(ConcatId("postDecPriv", uniqueId), "(&"), + kEndParanthesis}; + } +} + +WGSLWrapperFunction WGSLProgramPrelude::assign(const TType &dest, const TType &src, TOperator op) +{ + uint64_t uniqueId = InsertIntoMapWithUniqueId(mUniqueFuncId, mAssigned, {dest, src, op}); + + switch (GetWgslAddressSpaceForPointer(dest)) + { + case WgslPointerAddressSpace::Function: + return {BuildConcatenatedImmutableString(ConcatId("assignFunc", uniqueId), "(&"), + kEndParanthesis}; + case WgslPointerAddressSpace::Private: + // EvqGlobal and various other shader outputs/builtins are all globals. + return {BuildConcatenatedImmutableString(ConcatId("assignPriv", uniqueId), "(&"), + kEndParanthesis}; + } +} + +void WGSLProgramPrelude::outputPrelude(TInfoSinkBase &sink) +{ + auto genPreIncOrDec = [&](ImmutableString addressSpace, const TType &type, ImmutableString op, + ImmutableString funcName) { + TStringStream typeStr; + WriteWgslType(typeStr, type, {}); + + sink << "fn " << funcName << "(x : ptr<" << addressSpace << ", " << typeStr.str() + << ">) -> " << typeStr.str() << " {\n"; + sink << " (*x) " << op << " " << typeStr.str(); + EmitConstructorList(sink, type, ImmutableString("1")); + sink << ";\n"; + sink << " return *x;\n"; + sink << "}\n"; + }; + for (const std::pair &elem : mPreIncrementedTypes) + { + + // NOTE: it's easiest just to generate increments and decrements functions for variables + // that live in either the function-local scope or the module-local scope. TType holds a + // qualifier, but its operator== and operator< ignore the qualifier. We could keep track of + // the qualifiers used but that's overkill. + genPreIncOrDec(ImmutableString("private"), elem.first, ImmutableString("+="), + ConcatId("preIncPriv", elem.second)); + genPreIncOrDec(ImmutableString("function"), elem.first, ImmutableString("+="), + ConcatId("preIncFunc", elem.second)); + } + for (const std::pair &elem : mPreDecrementedTypes) + { + + // NOTE: it's easiest just to generate increments and decrements functions for variables + // that live in either the function-local scope or the module-local scope. TType holds a + // qualifier, but its operator== and operator< ignore the qualifier. We could keep track of + // the qualifiers used but that's overkill. + genPreIncOrDec(ImmutableString("private"), elem.first, ImmutableString("-="), + ConcatId("preDecPriv", elem.second)); + genPreIncOrDec(ImmutableString("function"), elem.first, ImmutableString("-="), + ConcatId("preDecFunc", elem.second)); + } + + auto genPostIncOrDec = [&](ImmutableString addressSpace, const TType &type, ImmutableString op, + ImmutableString funcName) { + TStringStream typeStr; + WriteWgslType(typeStr, type, {}); + + sink << "fn " << funcName << "(x : ptr<" << addressSpace << ", " << typeStr.str() + << ">) -> " << typeStr.str() << " {\n"; + sink << " var old = *x;\n"; + sink << " (*x) " << op << " " << typeStr.str(); + EmitConstructorList(sink, type, ImmutableString("1")); + sink << ";\n"; + sink << " return old;\n"; + sink << "}\n"; + }; + for (const std::pair &elem : mPostIncrementedTypes) + { + // NOTE: it's easiest just to generate increments and decrements functions for variables + // that live in either the function-local scope or the module-local scope. TType holds a + // qualifier, but its operator== and operator< ignore the qualifier. We could keep track of + // the qualifiers used but that's overkill. + genPostIncOrDec(ImmutableString("private"), elem.first, ImmutableString("+="), + ConcatId("postIncPriv", elem.second)); + genPostIncOrDec(ImmutableString("function"), elem.first, ImmutableString("+="), + ConcatId("postIncFunc", elem.second)); + } + for (const std::pair &elem : mPostDecrementedTypes) + { + // NOTE: it's easiest just to generate increments and decrements functions for variables + // that live in either the function-local scope or the module-local scope. TType holds a + // qualifier, but its operator== and operator< ignore the qualifier. We could keep track of + // the qualifiers used but that's overkill. + genPostIncOrDec(ImmutableString("private"), elem.first, ImmutableString("-="), + ConcatId("postDecPriv", elem.second)); + genPostIncOrDec(ImmutableString("function"), elem.first, ImmutableString("-="), + ConcatId("postDecFunc", elem.second)); + } + + for (const auto &assigned : mAssigned) + { + auto genAssignment = [&](ImmutableString addressSpace, ImmutableString funcName) { + TStringStream destTypeStr; + WriteWgslType(destTypeStr, assigned.first.dest, {}); + TStringStream srcTypeStr; + WriteWgslType(srcTypeStr, assigned.first.src, {}); + + sink << "fn " << funcName << "(dest : ptr<" << addressSpace << ", " << destTypeStr.str() + << ">, src : " << srcTypeStr.str() << ") -> " << destTypeStr.str() << " {\n"; + sink << " *dest " << GetOperatorString(assigned.first.op) << " src;\n"; + sink << " return *dest;\n"; + sink << "}\n"; + }; + genAssignment(ImmutableString("private"), ConcatId("assignPriv", assigned.second)); + genAssignment(ImmutableString("function"), ConcatId("assignFunc", assigned.second)); + } +} + +} // namespace sh diff --git a/src/compiler/translator/wgsl/WGSLProgramPrelude.h b/src/compiler/translator/wgsl/WGSLProgramPrelude.h new file mode 100644 index 00000000000..f1c7c982031 --- /dev/null +++ b/src/compiler/translator/wgsl/WGSLProgramPrelude.h @@ -0,0 +1,60 @@ +// +// Copyright 2025 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. +// + +#ifndef COMPILER_TRANSLATOR_WGSL_WGSL_PROGRAM_PRELUDE_H_ +#define COMPILER_TRANSLATOR_WGSL_WGSL_PROGRAM_PRELUDE_H_ + +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Operator_autogen.h" + +namespace sh +{ +struct WGSLWrapperFunction +{ + ImmutableString prefix; + ImmutableString suffix; +}; + +class WGSLProgramPrelude +{ + public: + WGSLWrapperFunction preIncrement(const TType &preIncrementedType); + WGSLWrapperFunction preDecrement(const TType &preDecrementedType); + WGSLWrapperFunction postIncrement(const TType &postIncrementedType); + WGSLWrapperFunction postDecrement(const TType &postDecrementedType); + + WGSLWrapperFunction assign(const TType &dest, const TType &src, TOperator op); + + void outputPrelude(TInfoSinkBase &sink); + + private: + using FuncId = uint64_t; + + FuncId mUniqueFuncId = 0; + + TMap mPreIncrementedTypes; + TMap mPreDecrementedTypes; + TMap mPostIncrementedTypes; + TMap mPostDecrementedTypes; + + struct Assignment + { + TType dest; + TType src; + TOperator op; + + bool operator<(const Assignment &other) const + { + return std::tie(dest, src, op) < std::tie(other.dest, other.src, other.op); + } + }; + TMap mAssigned; +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_WGSL_WGSL_PROGRAM_PRELUDE_H_ diff --git a/src/feature_support_util/feature_support_util.cpp b/src/feature_support_util/feature_support_util.cpp index bb980e48f82..0c635e7adf4 100644 --- a/src/feature_support_util/feature_support_util.cpp +++ b/src/feature_support_util/feature_support_util.cpp @@ -12,6 +12,7 @@ #include #include #include "common/platform.h" +#include "common/unsafe_buffers.h" #if defined(ANGLE_PLATFORM_ANDROID) # include # include @@ -37,7 +38,8 @@ namespace angle # define INFO(...) __android_log_print(ANDROID_LOG_INFO, "ANGLE", __VA_ARGS__) # define DEBUG(...) __android_log_print(ANDROID_LOG_DEBUG, "ANGLE", __VA_ARGS__) # ifdef ANGLE_FEATURE_UTIL_LOG_VERBOSE -# define VERBOSE(...) __android_log_print(ANDROID_LOG_VERBOSE, "ANGLE", __VA_ARGS__) +# define VERBOSE(...) \ + ANGLE_UNSAFE_TODO(__android_log_print(ANDROID_LOG_VERBOSE, "ANGLE", __VA_ARGS__)) # else # define VERBOSE(...) ((void)0) # endif @@ -130,7 +132,11 @@ class StringPart { public: StringPart() = default; - explicit StringPart(const std::string part) : mPart(part), mWildcard(false) {} + explicit StringPart(const std::string &part) : mPart(part), mWildcard(false) {} + StringPart(const StringPart &) = default; + StringPart(StringPart &&) = default; + StringPart &operator=(const StringPart &) = default; + StringPart &operator=(StringPart &&) = default; ~StringPart() = default; static StringPart FromJson(const Json::Value &parent, const char *key) diff --git a/src/gpu_info_util/SystemInfo.cpp b/src/gpu_info_util/SystemInfo.cpp index 386fb2fee00..ad1695bd23d 100644 --- a/src/gpu_info_util/SystemInfo.cpp +++ b/src/gpu_info_util/SystemInfo.cpp @@ -168,6 +168,11 @@ bool IsQualcomm(VendorID vendorId) return vendorId == kVendorID_Qualcomm; } +bool IsSamsung(VendorID vendorId) +{ + return vendorId == kVendorID_Samsung; +} + bool IsGoogle(VendorID vendorId) { return vendorId == kVendorID_GOOGLE; diff --git a/src/gpu_info_util/SystemInfo.h b/src/gpu_info_util/SystemInfo.h index ea5faa9ef81..333ed4341f8 100644 --- a/src/gpu_info_util/SystemInfo.h +++ b/src/gpu_info_util/SystemInfo.h @@ -48,6 +48,7 @@ struct GPUDeviceInfo std::string driverDate; // Fields only available via GetSystemInfoVulkan: + std::string deviceName; VersionInfo detailedDriverVersion; uint8_t deviceUUID[16] = {}; uint8_t driverUUID[16] = {}; @@ -126,6 +127,7 @@ constexpr VendorID kVendorID_PoCL = 0x10006; // Known device IDs constexpr DeviceID kDeviceID_Swiftshader = 0xC0DE; +constexpr DeviceID kDeviceID_Lavapipe = 0x0; constexpr DeviceID kDeviceID_Adreno540 = 0x5040001; constexpr DeviceID kDeviceID_Adreno750 = 0x43051401; constexpr DeviceID kDeviceID_UHD630Mobile = 0x3E9B; @@ -141,7 +143,6 @@ bool IsNVIDIA(VendorID vendorId); bool IsQualcomm(VendorID vendorId); bool IsSamsung(VendorID vendorId); bool IsGoogle(VendorID vendorId); -bool IsSwiftshader(VendorID vendorId); bool IsVeriSilicon(VendorID vendorId); bool IsVMWare(VendorID vendorId); bool IsVirtIO(VendorID vendorId); diff --git a/src/gpu_info_util/SystemInfo_libpci.cpp b/src/gpu_info_util/SystemInfo_libpci.cpp index cd250f05a43..34972855f2d 100644 --- a/src/gpu_info_util/SystemInfo_libpci.cpp +++ b/src/gpu_info_util/SystemInfo_libpci.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "common/angleutils.h" #include "common/debug.h" @@ -79,6 +80,26 @@ struct LibPCI : private angle::NonCopyable decltype(&::pci_lookup_name) LookupName = nullptr; decltype(&::pci_read_byte) PCIReadByte = nullptr; + uint8_t GetRevisionId(pci_dev *device) + { + char revision_path[100]; + snprintf(revision_path, sizeof(revision_path), + "/sys/bus/pci/devices/%04x:%02x:%02x.%d/revision", device->domain, device->bus, + device->dev, device->func); + + std::ifstream file(revision_path); + if (file.is_open()) + { + uint8_t rev; + if (file >> std::hex >> rev) + { + return rev; + } + } + + return PCIReadByte(device, PCI_REVISION_ID); + } + private: void *mHandle = nullptr; bool mValid = false; @@ -102,7 +123,11 @@ bool GetPCIDevicesWithLibPCI(std::vector *devices) for (pci_dev *device = access->devices; device != nullptr; device = device->next) { +#if PCI_LIB_VERSION >= 0x030800 + pci.FillInfo(device, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_CLASS_EXT); +#else pci.FillInfo(device, PCI_FILL_IDENT | PCI_FILL_CLASS); +#endif // Skip non-GPU devices if (device->device_class >> 8 != PCI_BASE_CLASS_DISPLAY) @@ -119,7 +144,11 @@ bool GetPCIDevicesWithLibPCI(std::vector *devices) GPUDeviceInfo info; info.vendorId = device->vendor_id; info.deviceId = device->device_id; - info.revisionId = pci.PCIReadByte(device, PCI_REVISION_ID); +#if PCI_LIB_VERSION >= 0x030800 + info.revisionId = device->rev_id; +#else + info.revisionId = pci.GetRevisionId(device); +#endif devices->push_back(info); } diff --git a/src/gpu_info_util/SystemInfo_linux.cpp b/src/gpu_info_util/SystemInfo_linux.cpp index ce0c349e843..457b6ea5b01 100644 --- a/src/gpu_info_util/SystemInfo_linux.cpp +++ b/src/gpu_info_util/SystemInfo_linux.cpp @@ -71,7 +71,7 @@ bool GetPCIDevicesWithLibPCI(std::vector *devices) bool GetSystemInfo(SystemInfo *info) { - if (!GetPCIDevicesWithLibPCI(&(info->gpus))) + if (!GetPCIDevicesWithLibPCI(&(info->gpus)) || info->gpus.size() == 0) { #if defined(ANGLE_USE_VULKAN_SYSTEM_INFO) // Try vulkan backend to get GPU info @@ -81,11 +81,6 @@ bool GetSystemInfo(SystemInfo *info) #endif // defined(ANGLE_HAS_VULKAN_SYSTEM_INFO) } - if (info->gpus.size() == 0) - { - return false; - } - GetDualGPUInfo(info); for (size_t i = 0; i < info->gpus.size(); ++i) diff --git a/src/gpu_info_util/SystemInfo_macos.mm b/src/gpu_info_util/SystemInfo_macos.mm index acb7d3ee977..8da3839698b 100644 --- a/src/gpu_info_util/SystemInfo_macos.mm +++ b/src/gpu_info_util/SystemInfo_macos.mm @@ -6,6 +6,10 @@ // SystemInfo_macos.mm: implementation of the macOS-specific parts of SystemInfo.h +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gpu_info_util/SystemInfo_internal.h" #import @@ -54,11 +58,6 @@ bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *val // Gathers the vendor and device IDs for GPUs listed in the IORegistry. void GetIORegistryDevices(std::vector *devices) { -#if TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 120000 - const mach_port_t mainPort = kIOMasterPortDefault; -#else - const mach_port_t mainPort = kIOMainPortDefault; -#endif constexpr uint32_t kNumServices = 2; const char *kServiceNames[kNumServices] = {"IOGraphicsAccelerator2", "AGXAccelerator"}; const bool kServiceIsGraphicsAccelerator2[kNumServices] = {true, false}; @@ -68,7 +67,7 @@ void GetIORegistryDevices(std::vector *devices) CFMutableDictionaryRef matchDictionary = IOServiceMatching(kServiceNames[i]); io_iterator_t entryIterator; - if (IOServiceGetMatchingServices(mainPort, matchDictionary, &entryIterator) != + if (IOServiceGetMatchingServices(kIOMainPortDefault, matchDictionary, &entryIterator) != kIOReturnSuccess) { continue; @@ -148,12 +147,6 @@ void GetIORegistryDevices(std::vector *devices) void ForceGPUSwitchIndex(SystemInfo *info) { -#if TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 120000 - const mach_port_t mainPort = kIOMasterPortDefault; -#else - const mach_port_t mainPort = kIOMainPortDefault; -#endif - // Early-out if on a single-GPU system if (info->gpus.size() < 2) { @@ -169,7 +162,7 @@ void ForceGPUSwitchIndex(SystemInfo *info) return; CFMutableDictionaryRef matchDictionary = IORegistryEntryIDMatching(gpuID); - io_service_t gpuEntry = IOServiceGetMatchingService(mainPort, matchDictionary); + io_service_t gpuEntry = IOServiceGetMatchingService(kIOMainPortDefault, matchDictionary); if (gpuEntry == IO_OBJECT_NULL) { @@ -266,12 +259,6 @@ uint64_t GetGpuIDFromOpenGLDisplayMask(uint32_t displayMask) // Get VendorID from metal device's registry ID VendorID GetVendorIDFromMetalDeviceRegistryID(uint64_t registryID) { -#if TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 120000 - const mach_port_t mainPort = kIOMasterPortDefault; -#else - const mach_port_t mainPort = kIOMainPortDefault; -#endif - // Get a matching dictionary for the IOGraphicsAccelerator2 CFMutableDictionaryRef matchingDict = IORegistryEntryIDMatching(registryID); if (matchingDict == nullptr) @@ -281,7 +268,8 @@ VendorID GetVendorIDFromMetalDeviceRegistryID(uint64_t registryID) // IOServiceGetMatchingService will consume the reference on the matching dictionary, // so we don't need to release the dictionary. - io_registry_entry_t acceleratorEntry = IOServiceGetMatchingService(mainPort, matchingDict); + io_registry_entry_t acceleratorEntry = + IOServiceGetMatchingService(kIOMainPortDefault, matchingDict); if (acceleratorEntry == IO_OBJECT_NULL) { return 0; diff --git a/src/gpu_info_util/SystemInfo_vulkan.cpp b/src/gpu_info_util/SystemInfo_vulkan.cpp index 01f46859af6..be355644515 100644 --- a/src/gpu_info_util/SystemInfo_vulkan.cpp +++ b/src/gpu_info_util/SystemInfo_vulkan.cpp @@ -7,6 +7,10 @@ // SystemInfo_vulkan.cpp: Generic vulkan implementation of SystemInfo.h // TODO: Use VK_KHR_driver_properties. http://anglebug.com/42263671 +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "gpu_info_util/SystemInfo_vulkan.h" #include @@ -99,13 +103,17 @@ VersionInfo ParseNvidiaVulkanDriverVersion(uint32_t driverVersion) VersionInfo ParseQualcommVulkanDriverVersion(uint32_t driverVersion) { + VersionInfo version = {}; if ((driverVersion & 0x80000000) != 0) { - return ParseGenericDriverVersion(driverVersion); + // The major version of the new QCOM drivers seem to be 512. However, the value parsed from + // the physical device properties shows this field as 0. + version = ParseGenericDriverVersion(driverVersion); + version.major = 512; + return version; } // Older drivers with an unknown format, consider them version 0. - VersionInfo version = {}; version.minor = driverVersion; return version; } @@ -143,6 +151,54 @@ VersionInfo ParseMoltenVulkanDriverVersion(uint32_t driverVersion) return version; } +VKAPI_ATTR VkBool32 VKAPI_CALL +VVLDebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *callbackData, + void *userData) +{ + // VUID-VkDebugUtilsMessengerCallbackDataEXT-pMessage-parameter + // pMessage must be a null-terminated UTF-8 string + ASSERT(callbackData->pMessage != nullptr); + + // Log the validation error message + std::ostringstream log; + if (callbackData->pMessageIdName != nullptr) + { + log << "[ " << callbackData->pMessageIdName << " ] "; + } + log << callbackData->pMessage << std::endl; + std::string msg = log.str(); + WARN() << msg; + + bool triggerAssert = (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0; + if (triggerAssert) + { + // Trigger assert when there is validation error, so we can catch it on bots. + ASSERT(false); + } + + return VK_FALSE; +} + +constexpr const char *kVkKhronosValidationLayerName[] = {"VK_LAYER_KHRONOS_validation"}; + +bool HasKhronosValidationLayer(const std::vector &layerProps) +{ + for (const auto &layerProp : layerProps) + { + std::string layerPropLayerName = std::string(layerProp.layerName); + if (layerPropLayerName == kVkKhronosValidationLayerName[0]) + { + return true; + } + } + + WARN() << "Vulkan validation layers are missing"; + + return false; +} + class VulkanLibrary final : NonCopyable { public: @@ -150,13 +206,13 @@ class VulkanLibrary final : NonCopyable ~VulkanLibrary() { + if (mDebugUtilsMessenger) + { + mPfnDestroyDebugUtilsMessengerEXT(mInstance, mDebugUtilsMessenger, nullptr); + } if (mInstance != VK_NULL_HANDLE) { - auto pfnDestroyInstance = getProc("vkDestroyInstance"); - if (pfnDestroyInstance) - { - pfnDestroyInstance(mInstance, nullptr); - } + mPfnDestroyInstance(mInstance, nullptr); } CloseSystemLibrary(mLibVulkan); @@ -166,23 +222,20 @@ class VulkanLibrary final : NonCopyable { std::vector extensionNames; - auto pfnEnumerateInstanceExtensionProperties = - getProc( - "vkEnumerateInstanceExtensionProperties"); - if (!pfnEnumerateInstanceExtensionProperties) + if (!mPfnEnumerateInstanceExtensionProperties) { return extensionNames; } uint32_t extensionCount = 0; - if (pfnEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr) != + if (mPfnEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr) != VK_SUCCESS) { return extensionNames; } std::vector extensions(extensionCount); - if (pfnEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()) != + if (mPfnEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()) != VK_SUCCESS) { return extensionNames; @@ -213,11 +266,40 @@ class VulkanLibrary final : NonCopyable return VK_NULL_HANDLE; } + mPfnGetInstanceProcAddr = + getProcWithDLSym("vkGetInstanceProcAddr"); + if (!mPfnGetInstanceProcAddr) + { + return VK_NULL_HANDLE; + } + + mPfnCreateInstance = getProcWithDLSym("vkCreateInstance"); + if (!mPfnCreateInstance) + { + return VK_NULL_HANDLE; + } + + mPfnEnumerateInstanceLayerProperties = + getProcWithDLSym( + "vkEnumerateInstanceLayerProperties"); + if (!mPfnEnumerateInstanceLayerProperties) + { + return VK_NULL_HANDLE; + } + + mPfnEnumerateInstanceExtensionProperties = + getProcWithDLSym( + "vkEnumerateInstanceExtensionProperties"); + if (!mPfnEnumerateInstanceExtensionProperties) + { + return VK_NULL_HANDLE; + } + // Determine the available Vulkan instance version: uint32_t instanceVersion = VK_API_VERSION_1_0; #if defined(VK_VERSION_1_1) - auto pfnEnumerateInstanceVersion = - getProc("vkEnumerateInstanceVersion"); + PFN_vkEnumerateInstanceVersion pfnEnumerateInstanceVersion = + getProcWithDLSym("vkEnumerateInstanceVersion"); if (!pfnEnumerateInstanceVersion || pfnEnumerateInstanceVersion(&instanceVersion) != VK_SUCCESS) { @@ -240,6 +322,29 @@ class VulkanLibrary final : NonCopyable hasPortabilityEnumeration = true; } + // Enable vulkan validation layer + bool enableValidationLayer = false; + // Only enable validation layer when asserts are enabled +#if !defined(NDEBUG) || defined(ANGLE_ASSERT_ALWAYS_ON) + uint32_t instanceLayerCount = 0; + { + mPfnEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr); + } + std::vector instanceLayerProps(instanceLayerCount); + if (instanceLayerCount > 0) + { + mPfnEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProps.data()); + } + enableValidationLayer = HasKhronosValidationLayer(instanceLayerProps); +#endif + bool hasDebugMessengerExtension = false; + if (enableValidationLayer && + ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, availableInstanceExtensions)) + { + enabledInstanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + hasDebugMessengerExtension = true; + } + // Create a Vulkan instance: VkApplicationInfo appInfo; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -249,14 +354,32 @@ class VulkanLibrary final : NonCopyable appInfo.pEngineName = ""; appInfo.engineVersion = 1; appInfo.apiVersion = instanceVersion; - - VkInstanceCreateInfo createInstanceInfo; + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + VkInstanceCreateInfo createInstanceInfo{}; createInstanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInstanceInfo.pNext = nullptr; - createInstanceInfo.flags = 0; + if (enableValidationLayer) + { + createInstanceInfo.enabledLayerCount = 1; + createInstanceInfo.ppEnabledLayerNames = kVkKhronosValidationLayerName; + + if (hasDebugMessengerExtension) + { + constexpr VkDebugUtilsMessageSeverityFlagsEXT kSeveritiesToLog = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + + constexpr VkDebugUtilsMessageTypeFlagsEXT kMessagesToLog = + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; + + debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + debugCreateInfo.messageSeverity = kSeveritiesToLog; + debugCreateInfo.messageType = kMessagesToLog; + debugCreateInfo.pfnUserCallback = &VVLDebugUtilsMessenger; + debugCreateInfo.pUserData = nullptr; + createInstanceInfo.pNext = &debugCreateInfo; + } + } createInstanceInfo.pApplicationInfo = &appInfo; - createInstanceInfo.enabledLayerCount = 0; - createInstanceInfo.ppEnabledLayerNames = nullptr; createInstanceInfo.enabledExtensionCount = static_cast(enabledInstanceExtensions.size()); createInstanceInfo.ppEnabledExtensionNames = @@ -267,25 +390,111 @@ class VulkanLibrary final : NonCopyable createInstanceInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; } - auto pfnCreateInstance = getProc("vkCreateInstance"); - if (!pfnCreateInstance || - pfnCreateInstance(&createInstanceInfo, nullptr, &mInstance) != VK_SUCCESS) + if (mPfnCreateInstance(&createInstanceInfo, nullptr, &mInstance) != VK_SUCCESS) + { + return VK_NULL_HANDLE; + } + + mPfnDestroyInstance = getProcWithDLSym("vkDestroyInstance"); + if (!mPfnDestroyInstance) + { + return VK_NULL_HANDLE; + } + + mPfnEnumeratePhysicalDevices = + getProcWithDLSym("vkEnumeratePhysicalDevices"); + if (!mPfnEnumeratePhysicalDevices) + { + return VK_NULL_HANDLE; + } + + mPfnGetPhysicalDeviceProperties = + getProcWithDLSym("vkGetPhysicalDeviceProperties"); + if (!mPfnGetPhysicalDeviceProperties) { return VK_NULL_HANDLE; } + // Even then vkEnumerateInstanceVersion() returns VK_API_VERSION_1_1 or higher, + // mPfnGetPhysicalDeviceProperties2 can be still be nullptr if the actual vulkan device + // doesn't support VK_API_VERSION_1_1. + // Caller needs to check VkPhysicalDeviceProperties.apiVersion >= VK_API_VERSION_1_1 before + // trying to access mPfnGetPhysicalDeviceProperties2. + mPfnGetPhysicalDeviceProperties2 = + getProcWithDLSym("vkGetPhysicalDeviceProperties2"); + + if (hasDebugMessengerExtension) + { + mPfnCreateDebugUtilsMessengerEXT = + getProc("vkCreateDebugUtilsMessengerEXT"); + + mPfnDestroyDebugUtilsMessengerEXT = + getProc("vkDestroyDebugUtilsMessengerEXT"); + } + + // Set up vulkan validation layer debug messenger to relay the VVL error to the callback + // function VVLDebugUtilsMessenger. + hasDebugMessengerExtension = hasDebugMessengerExtension && + mPfnCreateDebugUtilsMessengerEXT && + mPfnDestroyDebugUtilsMessengerEXT; + if (hasDebugMessengerExtension) + { + ASSERT(debugCreateInfo.sType == + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); + mPfnCreateDebugUtilsMessengerEXT(mInstance, &debugCreateInfo, nullptr, + &mDebugUtilsMessenger); + } return mInstance; } template - Func getProc(const char *fn) const + Func getProcWithDLSym(const char *fn) const { return reinterpret_cast(angle::GetLibrarySymbol(mLibVulkan, fn)); } + template + Func getProc(const char *fn) const + { + if (mInstance == VK_NULL_HANDLE) + { + return (Func)mPfnGetInstanceProcAddr(NULL, fn); + } + else + { + return (Func)mPfnGetInstanceProcAddr(mInstance, fn); + } + } + + PFN_vkEnumeratePhysicalDevices getEnumeratePhysicalDevicesFunc() + { + return mPfnEnumeratePhysicalDevices; + } + + PFN_vkGetPhysicalDeviceProperties getPhysicalDevicePropertiesFunc() + { + return mPfnGetPhysicalDeviceProperties; + } + + PFN_vkGetPhysicalDeviceProperties2 getPhysicalDeviceProperties2Func() + { + return mPfnGetPhysicalDeviceProperties2; + } + private: void *mLibVulkan = nullptr; VkInstance mInstance = VK_NULL_HANDLE; + VkDebugUtilsMessengerEXT mDebugUtilsMessenger = VK_NULL_HANDLE; + PFN_vkGetInstanceProcAddr mPfnGetInstanceProcAddr = nullptr; + PFN_vkCreateInstance mPfnCreateInstance = nullptr; + PFN_vkDestroyInstance mPfnDestroyInstance = nullptr; + PFN_vkEnumerateInstanceLayerProperties mPfnEnumerateInstanceLayerProperties = nullptr; + PFN_vkEnumerateInstanceExtensionProperties mPfnEnumerateInstanceExtensionProperties = nullptr; + PFN_vkEnumeratePhysicalDevices mPfnEnumeratePhysicalDevices = nullptr; + PFN_vkGetPhysicalDeviceProperties mPfnGetPhysicalDeviceProperties = nullptr; + PFN_vkGetPhysicalDeviceProperties2 mPfnGetPhysicalDeviceProperties2 = nullptr; + PFN_vkCreateDebugUtilsMessengerEXT mPfnCreateDebugUtilsMessengerEXT = nullptr; + PFN_vkDestroyDebugUtilsMessengerEXT mPfnDestroyDebugUtilsMessengerEXT = nullptr; }; ANGLE_FORMAT_PRINTF(1, 2) @@ -326,15 +535,11 @@ bool GetSystemInfoVulkanWithICD(SystemInfo *info, vk::ICD preferredICD) } // Enumerate the Vulkan physical devices, which are ANGLE gpus: - auto pfnEnumeratePhysicalDevices = - vkLibrary.getProc("vkEnumeratePhysicalDevices"); - auto pfnGetPhysicalDeviceProperties = - vkLibrary.getProc("vkGetPhysicalDeviceProperties"); - auto pfnGetPhysicalDeviceProperties2 = - vkLibrary.getProc("vkGetPhysicalDeviceProperties2"); + auto pfnEnumeratePhysicalDevices = vkLibrary.getEnumeratePhysicalDevicesFunc(); + auto pfnGetPhysicalDeviceProperties = vkLibrary.getPhysicalDevicePropertiesFunc(); + auto pfnGetPhysicalDeviceProperties2 = vkLibrary.getPhysicalDeviceProperties2Func(); uint32_t physicalDeviceCount = 0; - if (!pfnEnumeratePhysicalDevices || !pfnGetPhysicalDeviceProperties || - pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr) != VK_SUCCESS) + if (pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr) != VK_SUCCESS) { return false; } @@ -375,6 +580,7 @@ bool GetSystemInfoVulkanWithICD(SystemInfo *info, vk::ICD preferredICD) GPUDeviceInfo &gpu = info->gpus[i]; gpu.vendorId = properties.vendorID; gpu.deviceId = properties.deviceID; + gpu.deviceName = properties.deviceName; memcpy(gpu.deviceUUID, deviceIDProperties.deviceUUID, VK_UUID_SIZE); memcpy(gpu.driverUUID, deviceIDProperties.driverUUID, VK_UUID_SIZE); @@ -468,7 +674,6 @@ bool GetSystemInfoVulkanWithICD(SystemInfo *info, vk::ICD preferredICD) gpu.driverApiVersion = properties.apiVersion; gpu.driverDate = ""; } - return true; } diff --git a/src/gpu_info_util/SystemInfo_win.cpp b/src/gpu_info_util/SystemInfo_win.cpp index 291acc1ef0a..32c1a3aed8f 100644 --- a/src/gpu_info_util/SystemInfo_win.cpp +++ b/src/gpu_info_util/SystemInfo_win.cpp @@ -71,10 +71,27 @@ bool GetDevicesFromDXGI(std::vector *devices) device.vendorId = desc.VendorId; device.deviceId = desc.DeviceId; device.driverVersion = o.str(); - device.systemDeviceId = - GetSystemDeviceIdFromParts(desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart); - devices->push_back(device); + // Skip duplicate devices that have the same vendorId, deviceId, and driverVersion + // but different systemDeviceId (can happen with remote desktop connections) + bool isDuplicate = false; + for (const auto &existingDevice : *devices) + { + if (existingDevice.vendorId == device.vendorId && + existingDevice.deviceId == device.deviceId && + existingDevice.driverVersion == device.driverVersion) + { + isDuplicate = true; + break; + } + } + + if (!isDuplicate) + { + device.systemDeviceId = + GetSystemDeviceIdFromParts(desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart); + devices->push_back(device); + } adapter->Release(); } @@ -105,6 +122,20 @@ bool GetSystemInfo(SystemInfo *info) // can override the heuristic to find the active GPU info->activeGPUIndex = 0; + // Special case: if WARP (Microsoft) comes first and there are multiple devices, + // set activeGPUIndex to the first non-WARP device + if (info->gpus.size() > 1 && IsMicrosoft(info->gpus[0].vendorId)) + { + for (size_t i = 1; i < info->gpus.size(); ++i) + { + if (!IsMicrosoft(info->gpus[i].vendorId)) + { + info->activeGPUIndex = static_cast(i); + break; + } + } + } + #if !defined(ANGLE_ENABLE_WINDOWS_UWP) // Override isOptimus. nvd3d9wrap.dll is loaded into all processes when Optimus is enabled. HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll"); diff --git a/src/image_util/AstcDecompressorTestUtils.h b/src/image_util/AstcDecompressorTestUtils.h index bcd8e890190..191cac6e73b 100644 --- a/src/image_util/AstcDecompressorTestUtils.h +++ b/src/image_util/AstcDecompressorTestUtils.h @@ -5,6 +5,10 @@ // // AstcDecompressorTestUtils.h: Utility functions for ASTC decompression tests +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/debug.h" @@ -65,4 +69,4 @@ std::vector makeAstcCheckerboard(int width, int height) return result; } -} // namespace testing \ No newline at end of file +} // namespace testing diff --git a/src/image_util/AstcDecompressor_unittest.cpp b/src/image_util/AstcDecompressor_unittest.cpp index e87b5ccdc28..89e3bc7b3c1 100644 --- a/src/image_util/AstcDecompressor_unittest.cpp +++ b/src/image_util/AstcDecompressor_unittest.cpp @@ -24,8 +24,10 @@ TEST(AstcDecompressor, Decompress) const int width = 1024; const int height = 1024; - auto singleThreadedPool = WorkerThreadPool::Create(1, ANGLEPlatformCurrent()); - auto multiThreadedPool = WorkerThreadPool::Create(0, ANGLEPlatformCurrent()); + auto singleThreadedPool = + WorkerThreadPool::Create(ThreadPoolType::Synchronous, 0, ANGLEPlatformCurrent()); + auto multiThreadedPool = + WorkerThreadPool::Create(ThreadPoolType::Asynchronous, 0, ANGLEPlatformCurrent()); auto &decompressor = AstcDecompressor::get(); if (!decompressor.available()) diff --git a/src/image_util/LoadToNative_unittest.cpp b/src/image_util/LoadToNative_unittest.cpp index c962a8fe8c3..af314992a01 100644 --- a/src/image_util/LoadToNative_unittest.cpp +++ b/src/image_util/LoadToNative_unittest.cpp @@ -5,6 +5,10 @@ // // LoadToNative_unittest.cpp: Unit tests for pixel loading functions. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include "common/debug.h" @@ -500,4 +504,4 @@ TEST(LoadToNative3To4, LoadByteRGBToRGBAWithUnalignedWidthAndAlignment4) TestLoadByteRGBToRGBAForAllCases(context, alignment, 5, 5, 1, 0, 0, alignment); } } -} // namespace \ No newline at end of file +} // namespace diff --git a/src/image_util/copyimage.cpp b/src/image_util/copyimage.cpp index b5c2773e214..abe271ad399 100644 --- a/src/image_util/copyimage.cpp +++ b/src/image_util/copyimage.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // copyimage.cpp: Defines image copying functions #include "image_util/copyimage.h" @@ -38,6 +42,32 @@ void CopyBGRA8ToRGBA8Fast(const uint8_t *source, } } } + +void CopyRGBA8ToRGBA8Fast(const uint8_t *source, + int srcYAxisPitch, + uint8_t *dest, + int destYAxisPitch, + int destWidth, + int destHeight) +{ + // If Y axis pitch is packed and the source is also packed and stored contiguously, copy the + // whole source to the dest in a single memcpy operation. + if (destYAxisPitch == destWidth * 4 && srcYAxisPitch == destWidth * 4) + { + size_t totalSize = destHeight * destWidth * 4; + memcpy(dest, source, totalSize); + return; + } + + // If X axis pitch is 4 bytes but Y axis pitch is not packed, copy the source to dest line by + // line. + for (int y = 0; y < destHeight; ++y) + { + const uint8_t *src = source + y * srcYAxisPitch; + uint8_t *dst = dest + y * destYAxisPitch; + memcpy(dst, src, destWidth * 4); + } +} } // namespace void CopyBGRA8ToRGBA8(const uint8_t *source, @@ -71,4 +101,34 @@ void CopyBGRA8ToRGBA8(const uint8_t *source, } } +void CopyRGBA8ToRGBA8(const uint8_t *source, + int srcXAxisPitch, + int srcYAxisPitch, + uint8_t *dest, + int destXAxisPitch, + int destYAxisPitch, + int destWidth, + int destHeight) +{ + if (srcXAxisPitch == 4 && destXAxisPitch == 4) + { + CopyRGBA8ToRGBA8Fast(source, srcYAxisPitch, dest, destYAxisPitch, destWidth, destHeight); + return; + } + + for (int y = 0; y < destHeight; ++y) + { + uint8_t *dst = dest + y * destYAxisPitch; + const uint8_t *src = source + y * srcYAxisPitch; + const uint8_t *end = src + destWidth * srcXAxisPitch; + + while (src != end) + { + *reinterpret_cast(dst) = *reinterpret_cast(src); + src += srcXAxisPitch; + dst += destXAxisPitch; + } + } +} + } // namespace angle diff --git a/src/image_util/copyimage.h b/src/image_util/copyimage.h index 9825b86f981..8a9bd4363e9 100644 --- a/src/image_util/copyimage.h +++ b/src/image_util/copyimage.h @@ -39,6 +39,15 @@ void CopyBGRA8ToRGBA8(const uint8_t *source, int destWidth, int destHeight); +void CopyRGBA8ToRGBA8(const uint8_t *source, + int srcXAxisPitch, + int srcYAxisPitch, + uint8_t *dest, + int destXAxisPitch, + int destYAxisPitch, + int destWidth, + int destHeight); + } // namespace angle #include "copyimage.inc" diff --git a/src/image_util/generatemip.inc b/src/image_util/generatemip.inc index 7a7f5abe9c7..eafe6ade3cb 100644 --- a/src/image_util/generatemip.inc +++ b/src/image_util/generatemip.inc @@ -7,6 +7,10 @@ // generatemip.inc: Defines the GenerateMip function, templated on the format // type of the image for which mip levels are being generated. +#ifdef UNSAFE_BUFFERS_BUILD +#pragma allow_unsafe_buffers +#endif + #include "common/mathutil.h" #include "image_util/imageformats.h" diff --git a/src/image_util/imageformats.cpp b/src/image_util/imageformats.cpp index e2558e98949..53f061aaf9c 100644 --- a/src/image_util/imageformats.cpp +++ b/src/image_util/imageformats.cpp @@ -280,17 +280,17 @@ void R5G6B5::average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2) void B5G6R5::readColor(gl::ColorF *dst, const B5G6R5 *src) { - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->BGR)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGR)); dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->BGR)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGR)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->BGR)); dst->alpha = 1.0f; } void B5G6R5::writeColor(B5G6R5 *dst, const gl::ColorF *src) { - dst->BGR = gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)) | + dst->BGR = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->blue)) | gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) | - gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)); + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red)); } void B5G6R5::average(B5G6R5 *dst, const B5G6R5 *src1, const B5G6R5 *src2) @@ -1841,6 +1841,48 @@ void B10G10R10A2::average(B10G10R10A2 *dst, const B10G10R10A2 *src1, const B10G1 dst->A = gl::average(src1->A, src2->A); } +void R10X6G10X6B10X6A10X6::readColor(gl::ColorF *dst, const R10X6G10X6B10X6A10X6 *src) +{ + dst->red = gl::normalizedToFloat<10>(src->R); + dst->green = gl::normalizedToFloat<10>(src->G); + dst->blue = gl::normalizedToFloat<10>(src->B); + dst->alpha = gl::normalizedToFloat<10>(src->A); +} + +void R10X6G10X6B10X6A10X6::readColor(gl::ColorUI *dst, const R10X6G10X6B10X6A10X6 *src) +{ + dst->red = static_cast(src->R); + dst->green = static_cast(src->G); + dst->blue = static_cast(src->B); + dst->alpha = static_cast(src->A); +} + +void R10X6G10X6B10X6A10X6::writeColor(R10X6G10X6B10X6A10X6 *dst, const gl::ColorF *src) +{ + dst->R = gl::floatToNormalized<10, uint16_t>(src->red); + dst->G = gl::floatToNormalized<10, uint16_t>(src->green); + dst->B = gl::floatToNormalized<10, uint16_t>(src->blue); + dst->A = gl::floatToNormalized<10, uint16_t>(src->alpha); +} + +void R10X6G10X6B10X6A10X6::writeColor(R10X6G10X6B10X6A10X6 *dst, const gl::ColorUI *src) +{ + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); +} + +void R10X6G10X6B10X6A10X6::average(R10X6G10X6B10X6A10X6 *dst, + const R10X6G10X6B10X6A10X6 *src1, + const R10X6G10X6B10X6A10X6 *src2) +{ + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); +} + void R9G9B9E5::readColor(gl::ColorF *dst, const R9G9B9E5 *src) { gl::convert999E5toRGBFloats(gl::bitCast(*src), &dst->red, &dst->green, &dst->blue); diff --git a/src/image_util/imageformats.h b/src/image_util/imageformats.h index 1fac86c652a..beead7e3c83 100644 --- a/src/image_util/imageformats.h +++ b/src/image_util/imageformats.h @@ -738,6 +738,27 @@ struct B10G10R10A2 }; static_assert(sizeof(B10G10R10A2) == 4, "B10G10R10A2 struct not 32-bits."); +struct R10X6G10X6B10X6A10X6 +{ + uint16_t R : 10; + uint16_t RX : 6; + uint16_t G : 10; + uint16_t GX : 6; + uint16_t B : 10; + uint16_t BX : 6; + uint16_t A : 10; + uint16_t AX : 6; + + static void readColor(gl::ColorF *dst, const R10X6G10X6B10X6A10X6 *src); + static void readColor(gl::ColorUI *dst, const R10X6G10X6B10X6A10X6 *src); + static void writeColor(R10X6G10X6B10X6A10X6 *dst, const gl::ColorF *src); + static void writeColor(R10X6G10X6B10X6A10X6 *dst, const gl::ColorUI *src); + static void average(R10X6G10X6B10X6A10X6 *dst, + const R10X6G10X6B10X6A10X6 *src1, + const R10X6G10X6B10X6A10X6 *src2); +}; +static_assert(sizeof(R10X6G10X6B10X6A10X6) == 8, "R10X6G10X6B10X6A10X6 struct not 64-bits."); + struct R9G9B9E5 { uint32_t R : 9; diff --git a/src/image_util/loadimage.cpp b/src/image_util/loadimage.cpp index c73750b9826..58cd3d173ab 100644 --- a/src/image_util/loadimage.cpp +++ b/src/image_util/loadimage.cpp @@ -4,7 +4,11 @@ // found in the LICENSE file. // -// angle_loadimage.cpp: Defines image loading functions. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +// loadimage.cpp: Defines image loading functions. #include "image_util/loadimage.h" @@ -52,9 +56,10 @@ inline bool supportsSSE2() namespace angle { -ImageLoadContext::ImageLoadContext() = default; -ImageLoadContext::~ImageLoadContext() = default; -ImageLoadContext::ImageLoadContext(const ImageLoadContext &other) = default; +ImageLoadContext::ImageLoadContext() = default; +ImageLoadContext::~ImageLoadContext() = default; +ImageLoadContext::ImageLoadContext(const ImageLoadContext &other) = default; +ImageLoadContext &ImageLoadContext::operator=(const ImageLoadContext &other) = default; void LoadA8ToRGBA8(const ImageLoadContext &context, size_t width, @@ -84,7 +89,7 @@ void LoadA8ToRGBA8(const ImageLoadContext &context, size_t x = 0; // Make output writes aligned - for (; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) + for (; x < width && (reinterpret_cast(&dest[x]) & 0xF) != 0; x++) { dest[x] = static_cast(source[x]) << 24; } @@ -460,6 +465,39 @@ void LoadRGB8ToBGR565(const ImageLoadContext &context, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = + priv::OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = + priv::OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint8_t r8 = source[x * 3 + 0]; + uint8_t g8 = source[x * 3 + 1]; + uint8_t b8 = source[x * 3 + 2]; + auto r5 = static_cast(r8 >> 3); + auto g6 = static_cast(g8 >> 2); + auto b5 = static_cast(b8 >> 3); + dest[x] = (b5 << 11) | (g6 << 5) | r5; + } + } + } +} + +void LoadRGB8ToRGB565(const ImageLoadContext &context, + size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) { for (size_t z = 0; z < depth; z++) { @@ -504,13 +542,11 @@ void LoadRGB565ToBGR565(const ImageLoadContext &context, priv::OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); for (size_t x = 0; x < width; x++) { - // The GL type RGB is packed with with red in the MSB, while the D3D11 type BGR - // is packed with red in the LSB auto rgb = source[x]; uint16_t r5 = gl::getShiftedData<5, 11>(rgb); uint16_t g6 = gl::getShiftedData<6, 5>(rgb); uint16_t b5 = gl::getShiftedData<5, 0>(rgb); - dest[x] = (r5 << 11) | (g6 << 5) | b5; + dest[x] = (b5 << 11) | (g6 << 5) | r5; } } } @@ -702,7 +738,7 @@ void LoadRGBA8ToBGRA8(const ImageLoadContext &context, size_t x = 0; // Make output writes aligned - for (; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) + for (; x < width && (reinterpret_cast(&dest[x]) & 15) != 0; x++) { uint32_t rgba = source[x]; dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); @@ -1115,6 +1151,40 @@ void LoadRGB10A2ToRGB565(const ImageLoadContext &context, } } +void LoadRGB10A2ToBGR565(const ImageLoadContext &context, + size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + ASSERT(IsLittleEndian()); + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const R10G10B10A2 *source = + priv::OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = + priv::OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + R10G10B10A2 rgb10a2 = source[x]; + + uint16_t r5 = static_cast(rgb10a2.R >> 5u); + uint16_t g6 = static_cast(rgb10a2.G >> 4u); + uint16_t b5 = static_cast(rgb10a2.B >> 5u); + + dest[x] = (b5 << 11) | (g6 << 5) | r5; + } + } + } +} + void LoadRGB5A1ToA1RGB5(const ImageLoadContext &context, size_t width, size_t height, diff --git a/src/image_util/loadimage.h b/src/image_util/loadimage.h index c294fa8a48f..dd8c2883244 100644 --- a/src/image_util/loadimage.h +++ b/src/image_util/loadimage.h @@ -22,6 +22,7 @@ struct ImageLoadContext ImageLoadContext(); ~ImageLoadContext(); ImageLoadContext(const ImageLoadContext &other); + ImageLoadContext &operator=(const ImageLoadContext &other); // Passed to Load* functions as the context std::shared_ptr singleThreadPool; @@ -182,6 +183,17 @@ void LoadRGB8ToBGR565(const ImageLoadContext &context, size_t outputRowPitch, size_t outputDepthPitch); +void LoadRGB8ToRGB565(const ImageLoadContext &context, + size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + void LoadRGB565ToBGR565(const ImageLoadContext &context, size_t width, size_t height, @@ -391,6 +403,17 @@ void LoadRGB10A2ToRGB565(const ImageLoadContext &context, size_t outputRowPitch, size_t outputDepthPitch); +void LoadRGB10A2ToBGR565(const ImageLoadContext &context, + size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + void LoadRGB5A1ToRGB5A1(const ImageLoadContext &context, size_t width, size_t height, diff --git a/src/image_util/loadimage.inc b/src/image_util/loadimage.inc index 9fd60b535d6..76c119ea66a 100644 --- a/src/image_util/loadimage.inc +++ b/src/image_util/loadimage.inc @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +#pragma allow_unsafe_buffers +#endif + #include "common/mathutil.h" #include diff --git a/src/image_util/loadimage_astc.cpp b/src/image_util/loadimage_astc.cpp index 408bd60470d..829caa7944f 100644 --- a/src/image_util/loadimage_astc.cpp +++ b/src/image_util/loadimage_astc.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // loadimage_astc.cpp: Decodes ASTC encoded textures. #include "image_util/AstcDecompressor.h" @@ -42,12 +46,18 @@ void LoadASTCToRGBA8Inner(const ImageLoadContext &context, // Space needed for 16 bytes of output per compressed block size_t blockSize = blockCountX * blockCountY * 16; - int32_t result = - decompressor.decompress(context.singleThreadPool, context.multiThreadPool, imgWidth, - imgHeight, blockWidth, blockHeight, input, blockSize, output); - if (result != 0) + for (size_t slice = 0; slice < depth; ++slice) { - WARN() << "ASTC decompression failed: " << decompressor.getStatusString(result); + int32_t result = + decompressor.decompress(context.singleThreadPool, context.multiThreadPool, imgWidth, + imgHeight, blockWidth, blockHeight, input, blockSize, output); + if (result != 0) + { + WARN() << "ASTC decompression failed: " << decompressor.getStatusString(result); + } + + input += inputDepthPitch; + output += outputDepthPitch; } } } // namespace angle diff --git a/src/image_util/loadimage_etc.cpp b/src/image_util/loadimage_etc.cpp index b517899296e..a34e330b997 100644 --- a/src/image_util/loadimage_etc.cpp +++ b/src/image_util/loadimage_etc.cpp @@ -6,6 +6,10 @@ // loadimage_etc.cpp: Decodes ETC and EAC encoded textures. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "image_util/loadimage.h" #include diff --git a/src/image_util/loadimage_paletted.cpp b/src/image_util/loadimage_paletted.cpp index 84145a33b0e..fd8c269c92e 100644 --- a/src/image_util/loadimage_paletted.cpp +++ b/src/image_util/loadimage_paletted.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // loadimage_paletted.cpp: Decodes GL_PALETTE_* textures. #include "image_util/loadimage.h" diff --git a/src/image_util/storeimage_paletted.cpp b/src/image_util/storeimage_paletted.cpp index 960e6a624d0..00d4e2bd04a 100644 --- a/src/image_util/storeimage_paletted.cpp +++ b/src/image_util/storeimage_paletted.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // storeimage_paletted.cpp: Encodes GL_PALETTE_* textures. #include diff --git a/src/libANGLE/AttributeMap.cpp b/src/libANGLE/AttributeMap.cpp index e0c82be1ee9..e749ee383e1 100644 --- a/src/libANGLE/AttributeMap.cpp +++ b/src/libANGLE/AttributeMap.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/AttributeMap.h" #include "common/debug.h" diff --git a/src/libANGLE/BlendStateExt_unittest.cpp b/src/libANGLE/BlendStateExt_unittest.cpp index 7f2866c597b..4686a0c27b8 100644 --- a/src/libANGLE/BlendStateExt_unittest.cpp +++ b/src/libANGLE/BlendStateExt_unittest.cpp @@ -42,16 +42,16 @@ TEST(BlendStateExt, Init) const gl::BlendStateExt blendStateExt = gl::BlendStateExt(c); ASSERT_EQ(blendStateExt.getDrawBufferCount(), c); - ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 0u); - ASSERT_EQ(blendStateExt.getAllEnabledMask().to_ulong(), allEnabledMasks[c]); + ASSERT_EQ(blendStateExt.getEnabledMask().bits(), 0u); + ASSERT_EQ(blendStateExt.getAllEnabledMask().bits(), allEnabledMasks[c]); ASSERT_EQ(blendStateExt.getColorMaskBits(), blendStateExt.getAllColorMaskBits()); ASSERT_EQ(blendStateExt.getAllColorMaskBits(), is64Bit ? allColorMasks64[c] : allColorMasks32[c]); - ASSERT_EQ(blendStateExt.getUsesAdvancedBlendEquationMask().to_ulong(), 0u); + ASSERT_EQ(blendStateExt.getUsesAdvancedBlendEquationMask().bits(), 0u); - ASSERT_EQ(blendStateExt.getUsesExtendedBlendFactorMask().to_ulong(), 0u); + ASSERT_EQ(blendStateExt.getUsesExtendedBlendFactorMask().bits(), 0u); ASSERT_EQ(blendStateExt.getSrcColorBits(), sourceColorAlpha[c]); ASSERT_EQ(blendStateExt.getSrcAlphaBits(), sourceColorAlpha[c]); @@ -93,16 +93,16 @@ TEST(BlendStateExt, BlendEnabled) gl::BlendStateExt blendStateExt = gl::BlendStateExt(c); blendStateExt.setEnabled(true); - ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), enabled[c]); + ASSERT_EQ(blendStateExt.getEnabledMask().bits(), enabled[c]); blendStateExt.setEnabled(false); - ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 0u); + ASSERT_EQ(blendStateExt.getEnabledMask().bits(), 0u); blendStateExt.setEnabledIndexed(c / 2, true); - ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 1u << (c / 2)); + ASSERT_EQ(blendStateExt.getEnabledMask().bits(), 1u << (c / 2)); blendStateExt.setEnabledIndexed(c / 2, false); - ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 0u); + ASSERT_EQ(blendStateExt.getEnabledMask().bits(), 0u); } } @@ -188,7 +188,7 @@ TEST(BlendStateExt, ColorMask) // All masks are different except the c-th { const gl::DrawBufferMask diff = blendStateExt.compareColorMask(otherColorMask); - ASSERT_EQ(diff.to_ulong(), 127u >> (8 - c)); + ASSERT_EQ(diff.bits(), 127u >> (8 - c)); } // Test that all-enabled color mask correctly compares with the current color mask @@ -197,7 +197,7 @@ TEST(BlendStateExt, ColorMask) blendStateExt.setColorMaskIndexed(c / 2, false, false, true, false); const gl::DrawBufferMask diff = blendStateExt.compareColorMask(blendStateExt.getAllColorMaskBits()); - ASSERT_EQ(diff.to_ulong(), 1u << (c / 2)); + ASSERT_EQ(diff.bits(), 1u << (c / 2)); } } } @@ -228,7 +228,7 @@ TEST(BlendStateExt, BlendEquations) const gl::DrawBufferMask diff = blendStateExt.compareEquations(otherEquationColor, otherEquationAlpha); - ASSERT_EQ(diff.to_ulong(), 40u); + ASSERT_EQ(diff.bits(), 40u); // Copy buffer 3 to buffer 0 blendStateExt.setEquationsIndexed(0, 3, blendStateExt); @@ -278,7 +278,7 @@ TEST(BlendStateExt, BlendFactors) const gl::DrawBufferMask diff = blendStateExt.compareFactors(otherSrcColor, otherDstColor, otherSrcAlpha, otherDstAlpha); - ASSERT_EQ(diff.to_ulong(), 169u); + ASSERT_EQ(diff.bits(), 169u); // Copy buffer 0 to buffer 1 blendStateExt.setFactorsIndexed(1, 0, blendStateExt); diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp index 43452e79cba..525ae59e3e9 100644 --- a/src/libANGLE/Buffer.cpp +++ b/src/libANGLE/Buffer.cpp @@ -18,10 +18,60 @@ namespace gl { namespace { -constexpr angle::SubjectIndex kImplementationSubjectIndex = 0; constexpr size_t kInvalidContentsObserverIndex = std::numeric_limits::max(); } // anonymous namespace +// VertexArrayBufferBindingMaskAndContext implementation +VertexArrayBufferBindingMaskAndContext::VertexArrayBufferBindingMaskAndContext() {} +VertexArrayBufferBindingMaskAndContext::~VertexArrayBufferBindingMaskAndContext() +{ + mBufferBindingMask.clear(); +} + +void VertexArrayBufferBindingMaskAndContext::add(const gl::Context *context, size_t bindingIndex) +{ + for (auto &contextAndMask : mBufferBindingMask) + { + if (contextAndMask.first == context) + { + contextAndMask.second.set(bindingIndex); + return; + } + } + mBufferBindingMask.emplace_back(context, VertexArrayBufferBindingMask({bindingIndex})); +} + +void VertexArrayBufferBindingMaskAndContext::remove(const gl::Context *context, size_t bindingIndex) +{ + for (auto iter = mBufferBindingMask.begin(); iter != mBufferBindingMask.end(); ++iter) + { + if (iter->first == context) + { + iter->second.reset(bindingIndex); + if (iter->second.none()) + { + mBufferBindingMask.erase(iter); + } + return; + } + } + UNREACHABLE(); +} + +VertexArrayBufferBindingMask VertexArrayBufferBindingMaskAndContext::getBufferBindingMask( + const gl::Context *context) const +{ + for (auto &contextAndMask : mBufferBindingMask) + { + if (contextAndMask.first == context) + { + return contextAndMask.second; + } + } + return VertexArrayBufferBindingMask::Zero(); +} + +// BufferState implementation BufferState::BufferState() : mLabel(), mUsage(BufferUsage::StaticDraw), @@ -44,11 +94,8 @@ BufferState::BufferState() BufferState::~BufferState() {} Buffer::Buffer(rx::GLImplFactory *factory, BufferID id) - : RefCountObject(factory->generateSerial(), id), - mImpl(factory->createBuffer(mState)), - mImplObserver(this, kImplementationSubjectIndex) + : RefCountObject(factory->generateSerial(), id), mImpl(factory->createBuffer(mState)) { - mImplObserver.bind(mImpl); } Buffer::~Buffer() @@ -67,12 +114,7 @@ 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; - } + ASSERT(context->isWebGL()); if (mState.mWebGLType == WebGLBufferType::Undefined) { @@ -117,7 +159,8 @@ angle::Result Buffer::bufferStorage(Context *context, const void *data, GLbitfield flags) { - return bufferDataImpl(context, target, data, size, BufferUsage::InvalidEnum, flags); + return bufferDataImpl(context, target, data, size, BufferUsage::DynamicDraw, flags, + BufferStorage::Immutable); } angle::Result Buffer::bufferData(Context *context, @@ -127,7 +170,34 @@ angle::Result Buffer::bufferData(Context *context, BufferUsage usage) { GLbitfield flags = (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT_EXT); - return bufferDataImpl(context, target, data, size, usage, flags); + return bufferDataImpl(context, target, data, size, usage, flags, BufferStorage::Mutable); +} + +angle::Result Buffer::setDataWithUsageFlags(const gl::Context *context, + gl::BufferBinding target, + GLeglClientBufferEXT clientBuffer, + const void *data, + size_t size, + gl::BufferUsage usage, + GLbitfield flags, + gl::BufferStorage bufferStorage) +{ + rx::BufferFeedback feedback; + angle::Result result = mImpl->setDataWithUsageFlags(context, target, clientBuffer, data, size, + usage, flags, bufferStorage, &feedback); + + applyImplFeedback(context, feedback); + + if (result == angle::Result::Stop) + { + // If setData fails, the buffer contents are undefined. Set a zero size to indicate that. + mIndexRangeCache.clear(); + mState.mSize = 0; + + // Notify when storage changes. + onStateChange(context, angle::SubjectMessage::SubjectChanged); + } + return result; } angle::Result Buffer::bufferDataImpl(Context *context, @@ -135,7 +205,8 @@ angle::Result Buffer::bufferDataImpl(Context *context, const void *data, GLsizeiptr size, BufferUsage usage, - GLbitfield flags) + GLbitfield flags, + BufferStorage bufferStorage) { const void *dataForImpl = data; @@ -163,35 +234,25 @@ angle::Result Buffer::bufferDataImpl(Context *context, dataForImpl = scratchBuffer->data(); } - if (mImpl->setDataWithUsageFlags(context, target, nullptr, dataForImpl, size, usage, flags) == - angle::Result::Stop) - { - // If setData fails, the buffer contents are undefined. Set a zero size to indicate that. - mIndexRangeCache.clear(); - mState.mSize = 0; - - // Notify when storage changes. - onStateChange(angle::SubjectMessage::SubjectChanged); - - return angle::Result::Stop; - } + ANGLE_TRY(setDataWithUsageFlags(context, target, nullptr, dataForImpl, size, usage, flags, + bufferStorage)); bool wholeBuffer = size == mState.mSize; mIndexRangeCache.clear(); mState.mUsage = usage; mState.mSize = size; - mState.mImmutable = (usage == BufferUsage::InvalidEnum); + mState.mImmutable = (bufferStorage == BufferStorage::Immutable); mState.mStorageExtUsageFlags = flags; // Notify when storage changes. if (wholeBuffer) { - onContentsChange(); + onContentsChange(context); } else { - onStateChange(angle::SubjectMessage::SubjectChanged); + onStateChange(context, angle::SubjectMessage::SubjectChanged); } return angle::Result::Continue; @@ -216,28 +277,18 @@ angle::Result Buffer::bufferExternalDataImpl(Context *context, ANGLE_TRY(unmap(context, &dontCare)); } - if (mImpl->setDataWithUsageFlags(context, target, clientBuffer, nullptr, size, - BufferUsage::InvalidEnum, flags) == angle::Result::Stop) - { - // If setData fails, the buffer contents are undefined. Set a zero size to indicate that. - mIndexRangeCache.clear(); - mState.mSize = 0; - - // Notify when storage changes. - onStateChange(angle::SubjectMessage::SubjectChanged); - - return angle::Result::Stop; - } + ANGLE_TRY(setDataWithUsageFlags(context, target, clientBuffer, nullptr, size, + BufferUsage::DynamicDraw, flags, BufferStorage::Immutable)); mIndexRangeCache.clear(); - mState.mUsage = BufferUsage::InvalidEnum; + mState.mUsage = BufferUsage::DynamicDraw; mState.mSize = size; mState.mImmutable = GL_TRUE; mState.mStorageExtUsageFlags = flags; mState.mExternal = GL_TRUE; // Notify when storage changes. - onStateChange(angle::SubjectMessage::SubjectChanged); + onStateChange(context, angle::SubjectMessage::SubjectChanged); return angle::Result::Continue; } @@ -248,13 +299,15 @@ angle::Result Buffer::bufferSubData(const Context *context, GLsizeiptr size, GLintptr offset) { - ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset)); + rx::BufferFeedback feedback; + ANGLE_TRY_WITH_FINALLY(mImpl->setSubData(context, target, data, size, offset, &feedback), + applyImplFeedback(context, feedback)); mIndexRangeCache.invalidateRange(static_cast(offset), static_cast(size)); // Notify when data changes. - onContentsChange(); + onContentsChange(context); return angle::Result::Continue; } @@ -265,14 +318,16 @@ angle::Result Buffer::copyBufferSubData(const Context *context, GLintptr destOffset, GLsizeiptr size) { - ANGLE_TRY( - mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size)); + rx::BufferFeedback feedback; + ANGLE_TRY_WITH_FINALLY(mImpl->copySubData(context, source->getImplementation(), sourceOffset, + destOffset, size, &feedback), + applyImplFeedback(context, feedback)); mIndexRangeCache.invalidateRange(static_cast(destOffset), static_cast(size)); // Notify when data changes. - onContentsChange(); + onContentsChange(context); return angle::Result::Continue; } @@ -281,8 +336,10 @@ angle::Result Buffer::map(const Context *context, GLenum access) { ASSERT(!mState.mMapped); + rx::BufferFeedback feedback; mState.mMapPointer = nullptr; - ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer)); + ANGLE_TRY_WITH_FINALLY(mImpl->map(context, access, &mState.mMapPointer, &feedback), + applyImplFeedback(context, feedback)); ASSERT(access == GL_WRITE_ONLY_OES); @@ -294,7 +351,7 @@ angle::Result Buffer::map(const Context *context, GLenum access) mIndexRangeCache.clear(); // Notify when state changes. - onStateChange(angle::SubjectMessage::SubjectMapped); + onStateChange(context, angle::SubjectMessage::SubjectMapped); return angle::Result::Continue; } @@ -307,8 +364,11 @@ angle::Result Buffer::mapRange(const Context *context, ASSERT(!mState.mMapped); ASSERT(offset + length <= mState.mSize); + rx::BufferFeedback feedback; mState.mMapPointer = nullptr; - ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer)); + ANGLE_TRY_WITH_FINALLY( + mImpl->mapRange(context, offset, length, access, &mState.mMapPointer, &feedback), + applyImplFeedback(context, feedback)); mState.mMapped = GL_TRUE; mState.mMapOffset = static_cast(offset); @@ -328,7 +388,7 @@ angle::Result Buffer::mapRange(const Context *context, } // Notify when state changes. - onStateChange(angle::SubjectMessage::SubjectMapped); + onStateChange(context, angle::SubjectMessage::SubjectMapped); return angle::Result::Continue; } @@ -337,8 +397,10 @@ angle::Result Buffer::unmap(const Context *context, GLboolean *result) { ASSERT(mState.mMapped); + rx::BufferFeedback feedback; *result = GL_FALSE; - ANGLE_TRY(mImpl->unmap(context, result)); + ANGLE_TRY_WITH_FINALLY(mImpl->unmap(context, result, &feedback), + applyImplFeedback(context, feedback)); mState.mMapped = GL_FALSE; mState.mMapPointer = nullptr; @@ -348,17 +410,17 @@ angle::Result Buffer::unmap(const Context *context, GLboolean *result) mState.mAccessFlags = 0; // Notify when data changes. - onStateChange(angle::SubjectMessage::SubjectUnmapped); + onStateChange(context, angle::SubjectMessage::SubjectUnmapped); return angle::Result::Continue; } -void Buffer::onDataChanged() +void Buffer::onDataChanged(const Context *context) { mIndexRangeCache.clear(); // Notify when data changes. - onContentsChange(); + onContentsChange(context); mImpl->onDataChanged(); } @@ -403,7 +465,7 @@ void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0); mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1; - onStateChange(angle::SubjectMessage::BindingChanged); + onStateChange(context, angle::SubjectMessage::BindingChanged); } else { @@ -419,15 +481,6 @@ angle::Result Buffer::getSubData(const gl::Context *context, return mImpl->getSubData(context, offset, size, outData); } -void Buffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) -{ - // Pass it along! - ASSERT(index == kImplementationSubjectIndex); - ASSERT(message == angle::SubjectMessage::SubjectChanged || - message == angle::SubjectMessage::InternalMemoryAllocationChanged); - onStateChange(message); -} - size_t Buffer::getContentsObserverIndex(void *observer, uint32_t bufferIndex) const { ContentsObserver contentsObserver{bufferIndex, observer}; @@ -489,19 +542,40 @@ bool Buffer::hasContentsObserver(Texture *texture) const kInvalidContentsObserverIndex; } -void Buffer::onContentsChange() +void Buffer::onStateChange(const Context *context, angle::SubjectMessage message) +{ + // Pass message to other buffer observers such as XFB and Texture + angle::Subject::onStateChange(message); + + // Apply the change directly on current context's current vertex array. All other vertex arrays + // requires a buffer rebind in order to pick up the change. + context->onBufferChanged(this, message, + mVertexArrayBufferBindingMaskAndContext.getBufferBindingMask(context)); +} + +void Buffer::onContentsChange(const Context *context) { for (const ContentsObserver &contentsObserver : mContentsObservers) { - if (contentsObserver.bufferIndex != ContentsObserver::kBufferTextureIndex) - { - static_cast(contentsObserver.observer) - ->onBufferContentsChange(contentsObserver.bufferIndex); - } - else - { - static_cast(contentsObserver.observer)->onBufferContentsChange(); - } + ASSERT(contentsObserver.bufferIndex == ContentsObserver::kBufferTextureIndex); + static_cast(contentsObserver.observer)->onBufferContentsChange(); + } + + context->onBufferChanged(this, angle::SubjectMessage::ContentsChanged, + mVertexArrayBufferBindingMaskAndContext.getBufferBindingMask(context)); +} + +void Buffer::applyImplFeedback(const gl::Context *context, const rx::BufferFeedback &feedback) +{ + // Pass it along to observer of Buffer + if (feedback.internalMemoryAllocationChanged) + { + onStateChange(context, angle::SubjectMessage::InternalMemoryAllocationChanged); + } + + if (feedback.bufferStateChanged) + { + onStateChange(context, angle::SubjectMessage::SubjectChanged); } } } // namespace gl diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h index 507f6c333ae..21321598cc2 100644 --- a/src/libANGLE/Buffer.h +++ b/src/libANGLE/Buffer.h @@ -23,6 +23,7 @@ namespace rx { class BufferImpl; +struct BufferFeedback; class GLImplFactory; } // namespace rx @@ -38,6 +39,23 @@ enum class WebGLBufferType OtherData, }; +// Track vertex array's binding index of all contexts that a buffer is bound to +class VertexArrayBufferBindingMaskAndContext final +{ + public: + VertexArrayBufferBindingMaskAndContext(); + ~VertexArrayBufferBindingMaskAndContext(); + + void add(const gl::Context *context, size_t bindingIndex); + void remove(const gl::Context *context, size_t bindingIndex); + VertexArrayBufferBindingMask getBufferBindingMask(const gl::Context *context) const; + + private: + // The expectation is that one buffer will only used in a very small number of shared contexts, + // the cost of searching in a vector is negligible. + std::vector> mBufferBindingMask; +}; + class BufferState final : angle::NonCopyable { public: @@ -95,7 +113,6 @@ ANGLE_INLINE bool operator==(const ContentsObserver &lhs, const ContentsObserver class Buffer final : public ThreadSafeRefCountObject, public LabeledObject, - public angle::ObserverInterface, public angle::Subject { public: @@ -141,7 +158,7 @@ class Buffer final : public ThreadSafeRefCountObject, angle::Result unmap(const Context *context, GLboolean *result); // These are called when another operation changes Buffer data. - void onDataChanged(); + void onDataChanged(const Context *context); angle::Result getIndexRange(const gl::Context *context, DrawElementsType type, @@ -197,8 +214,18 @@ class Buffer final : public ThreadSafeRefCountObject, GLsizeiptr size, void *outData); - // angle::ObserverInterface implementation. - void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + void addVertexArrayBinding(const gl::Context *context, size_t bindingIndex) + { + mVertexArrayBufferBindingMaskAndContext.add(context, bindingIndex); + } + void removeVertexArrayBinding(const gl::Context *context, size_t bindingIndex) + { + mVertexArrayBufferBindingMaskAndContext.remove(context, bindingIndex); + } + VertexArrayBufferBindingMask getVertexArrayBinding(const gl::Context *context) const + { + return mVertexArrayBufferBindingMaskAndContext.getBufferBindingMask(context); + } void addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex); void removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex); @@ -206,26 +233,41 @@ class Buffer final : public ThreadSafeRefCountObject, void removeContentsObserver(Texture *texture); bool hasContentsObserver(Texture *texture) const; + void applyImplFeedback(const gl::Context *context, const rx::BufferFeedback &feedback); + private: angle::Result bufferDataImpl(Context *context, BufferBinding target, const void *data, GLsizeiptr size, BufferUsage usage, - GLbitfield flags); + GLbitfield flags, + BufferStorage bufferStorage); angle::Result bufferExternalDataImpl(Context *context, BufferBinding target, GLeglClientBufferEXT clientBuffer, GLsizeiptr size, GLbitfield flags); - void onContentsChange(); + void onStateChange(const Context *context, angle::SubjectMessage message); + void onContentsChange(const Context *context); size_t getContentsObserverIndex(void *observer, uint32_t bufferIndex) const; void removeContentsObserverImpl(void *observer, uint32_t bufferIndex); + angle::Result setDataWithUsageFlags(const gl::Context *context, + gl::BufferBinding target, + GLeglClientBufferEXT clientBuffer, + const void *data, + size_t size, + gl::BufferUsage usage, + GLbitfield flags, + gl::BufferStorage bufferStorage); + BufferState mState; rx::BufferImpl *mImpl; - angle::ObserverBinding mImplObserver; + + // Current VertexArray's binding index bitmask + VertexArrayBufferBindingMaskAndContext mVertexArrayBufferBindingMaskAndContext; angle::FastVector mContentsObservers; mutable IndexRangeCache mIndexRangeCache; diff --git a/src/libANGLE/CLBuffer.h b/src/libANGLE/CLBuffer.h index d7d32589b50..64a915bf13b 100644 --- a/src/libANGLE/CLBuffer.h +++ b/src/libANGLE/CLBuffer.h @@ -9,6 +9,7 @@ #define LIBANGLE_CLBUFFER_H_ #include "libANGLE/CLMemory.h" +#include "libANGLE/cl_utils.h" namespace cl { @@ -33,6 +34,7 @@ class Buffer final : public Memory MemObjectType getType() const final; bool isSubBuffer() const; + static Buffer *Cast(cl_mem memobj); private: Buffer(Context &context, PropArray &&properties, MemFlags flags, size_t size, void *hostPtr); @@ -67,6 +69,12 @@ inline bool Buffer::isSubBuffer() const return mParent != nullptr; } +inline Buffer *Buffer::Cast(cl_mem memobj) +{ + ASSERT(cl::IsBufferType(Memory::Cast(memobj)->getType())); + return static_cast(memobj); +} + } // namespace cl #endif // LIBANGLE_CLBUFFER_H_ diff --git a/src/libANGLE/CLCommandQueue.cpp b/src/libANGLE/CLCommandQueue.cpp index f3de46c8a1a..0334e246d9c 100644 --- a/src/libANGLE/CLCommandQueue.cpp +++ b/src/libANGLE/CLCommandQueue.cpp @@ -4,9 +4,16 @@ // found in the LICENSE file. // // CLCommandQueue.cpp: Implements the cl::CommandQueue class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLCommandQueue.h" +#include "CL/cl.h" +#include "common/angleutils.h" #include "libANGLE/CLBuffer.h" #include "libANGLE/CLContext.h" #include "libANGLE/CLDevice.h" @@ -14,35 +21,43 @@ #include "libANGLE/CLImage.h" #include "libANGLE/CLKernel.h" #include "libANGLE/CLMemory.h" +#include "libANGLE/Error.h" +#include "libANGLE/cl_types.h" +#include "libANGLE/cl_utils.h" #include +#define ANGLE_CL_ENQUEUE_TRY(cmd, event) \ + do \ + { \ + if (ANGLE_UNLIKELY(IsError(cmd))) \ + { \ + if (event != nullptr) \ + { \ + Event &evt = (*event)->cast(); \ + if (evt.release()) \ + { \ + delete &evt; \ + } \ + } \ + return angle::Result::Stop; \ + } \ + } while (0) + namespace cl { namespace { -void InitializeOutputEvent(cl_event *event) +angle::Result CreateEvent(cl_event *event, CommandQueue &queue, cl_command_type commandType) { if (event != nullptr) { - *event = nullptr; - } -} - -angle::Result CheckCreateEvent(CommandQueue &queue, - cl_command_type commandType, - const rx::CLEventImpl::CreateFunc &createFunc, - cl_event *event) -{ - if (event != nullptr) - { - ASSERT(createFunc); *event = Object::Create(queue, commandType); - if (IsError((*event)->cast().initBackend(createFunc))) + if (*event == nullptr) { - SafeDelete(*event); + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY); } } return angle::Result::Continue; @@ -155,15 +170,14 @@ angle::Result CommandQueue::enqueueReadBuffer(cl_mem buffer, const Buffer &buf = buffer->cast(); const bool blocking = blockingRead != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY( - mImpl->enqueueReadBuffer(buf, blocking, offset, size, ptr, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_READ_BUFFER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_READ_BUFFER, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueReadBuffer(buf, blocking, offset, size, ptr, waitEvents, eventPtr), event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueWriteBuffer(cl_mem buffer, @@ -178,22 +192,21 @@ angle::Result CommandQueue::enqueueWriteBuffer(cl_mem buffer, const Buffer &buf = buffer->cast(); const bool blocking = blockingWrite != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueWriteBuffer(buf, blocking, offset, size, ptr, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_WRITE_BUFFER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_WRITE_BUFFER, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueWriteBuffer(buf, blocking, offset, size, ptr, waitEvents, eventPtr), event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueReadBufferRect(cl_mem buffer, cl_bool blockingRead, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, @@ -206,23 +219,24 @@ angle::Result CommandQueue::enqueueReadBufferRect(cl_mem buffer, const Buffer &buf = buffer->cast(); const bool blocking = blockingRead != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueReadBufferRect(buf, blocking, bufferOrigin, hostOrigin, region, - bufferRowPitch, bufferSlicePitch, hostRowPitch, - hostSlicePitch, ptr, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_READ_BUFFER_RECT)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueReadBufferRect(buf, blocking, bufferOrigin, hostOrigin, region, + bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, + ptr, waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_READ_BUFFER_RECT, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueWriteBufferRect(cl_mem buffer, cl_bool blockingWrite, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, @@ -235,16 +249,17 @@ angle::Result CommandQueue::enqueueWriteBufferRect(cl_mem buffer, const Buffer &buf = buffer->cast(); const bool blocking = blockingWrite != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueWriteBufferRect(buf, blocking, bufferOrigin, hostOrigin, region, - bufferRowPitch, bufferSlicePitch, hostRowPitch, - hostSlicePitch, ptr, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_WRITE_BUFFER_RECT)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueWriteBufferRect(buf, blocking, bufferOrigin, hostOrigin, region, + bufferRowPitch, bufferSlicePitch, hostRowPitch, + hostSlicePitch, ptr, waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_WRITE_BUFFER_RECT, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueCopyBuffer(cl_mem srcBuffer, @@ -259,22 +274,22 @@ angle::Result CommandQueue::enqueueCopyBuffer(cl_mem srcBuffer, const Buffer &src = srcBuffer->cast(); const Buffer &dst = dstBuffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueCopyBuffer(src, dst, srcOffset, dstOffset, size, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_COPY_BUFFER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueCopyBuffer(src, dst, srcOffset, dstOffset, size, waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueCopyBufferRect(cl_mem srcBuffer, cl_mem dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, @@ -286,16 +301,16 @@ angle::Result CommandQueue::enqueueCopyBufferRect(cl_mem srcBuffer, const Buffer &src = srcBuffer->cast(); const Buffer &dst = dstBuffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueCopyBufferRect(src, dst, srcOrigin, dstOrigin, region, srcRowPitch, - srcSlicePitch, dstRowPitch, dstSlicePitch, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_COPY_BUFFER_RECT)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER_RECT, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueCopyBufferRect(src, dst, srcOrigin, dstOrigin, region, + srcRowPitch, srcSlicePitch, dstRowPitch, + dstSlicePitch, waitEvents, eventPtr), + event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueFillBuffer(cl_mem buffer, @@ -309,15 +324,15 @@ angle::Result CommandQueue::enqueueFillBuffer(cl_mem buffer, { const Buffer &buf = buffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueFillBuffer(buf, pattern, patternSize, offset, size, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_FILL_BUFFER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_FILL_BUFFER, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueFillBuffer(buf, pattern, patternSize, offset, size, waitEvents, eventPtr), + event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueMapBuffer(cl_mem buffer, @@ -333,21 +348,21 @@ angle::Result CommandQueue::enqueueMapBuffer(cl_mem buffer, const Buffer &buf = buffer->cast(); const bool blocking = blockingMap != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueMapBuffer(buf, blocking, mapFlags, offset, size, waitEvents, - eventCreateFuncPtr, mapPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_MAP_BUFFER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueMapBuffer(buf, blocking, mapFlags, offset, size, waitEvents, + eventPtr, mapPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_MAP_BUFFER, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueReadImage(cl_mem image, cl_bool blockingRead, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, @@ -358,21 +373,21 @@ angle::Result CommandQueue::enqueueReadImage(cl_mem image, const Image &img = image->cast(); const bool blocking = blockingRead != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueReadImage(img, blocking, origin, region, rowPitch, slicePitch, ptr, - waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_READ_IMAGE)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueReadImage(img, blocking, origin, region, rowPitch, + slicePitch, ptr, waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_READ_IMAGE, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueWriteImage(cl_mem image, cl_bool blockingWrite, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, @@ -383,22 +398,22 @@ angle::Result CommandQueue::enqueueWriteImage(cl_mem image, const Image &img = image->cast(); const bool blocking = blockingWrite != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueWriteImage(img, blocking, origin, region, inputRowPitch, - inputSlicePitch, ptr, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_WRITE_IMAGE)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueWriteImage(img, blocking, origin, region, inputRowPitch, + inputSlicePitch, ptr, waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_WRITE_IMAGE, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueCopyImage(cl_mem srcImage, cl_mem dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) @@ -406,42 +421,41 @@ angle::Result CommandQueue::enqueueCopyImage(cl_mem srcImage, const Image &src = srcImage->cast(); const Image &dst = dstImage->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueCopyImage(src, dst, srcOrigin, dstOrigin, region, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_COPY_IMAGE)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_COPY_IMAGE, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueCopyImage(src, dst, srcOrigin, dstOrigin, region, waitEvents, eventPtr), + event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueFillImage(cl_mem image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Image &img = image->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY( - mImpl->enqueueFillImage(img, fillColor, origin, region, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_FILL_IMAGE)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_FILL_IMAGE, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueFillImage(img, fillColor, origin, region, waitEvents, eventPtr), event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueCopyImageToBuffer(cl_mem srcImage, cl_mem dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, cl_uint numEventsInWaitList, const cl_event *eventWaitList, @@ -450,22 +464,22 @@ angle::Result CommandQueue::enqueueCopyImageToBuffer(cl_mem srcImage, const Image &src = srcImage->cast(); const Buffer &dst = dstBuffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueCopyImageToBuffer(src, dst, srcOrigin, region, dstOffset, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_COPY_IMAGE_TO_BUFFER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueCopyImageToBuffer(src, dst, srcOrigin, region, dstOffset, + waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_COPY_IMAGE_TO_BUFFER, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueCopyBufferToImage(cl_mem srcBuffer, cl_mem dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) @@ -473,22 +487,22 @@ angle::Result CommandQueue::enqueueCopyBufferToImage(cl_mem srcBuffer, const Buffer &src = srcBuffer->cast(); const Image &dst = dstImage->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueCopyBufferToImage(src, dst, srcOffset, dstOrigin, region, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_COPY_BUFFER_TO_IMAGE)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueCopyBufferToImage(src, dst, srcOffset, dstOrigin, region, + waitEvents, eventPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER_TO_IMAGE, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueMapImage(cl_mem image, cl_bool blockingMap, MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, cl_uint numEventsInWaitList, @@ -499,15 +513,16 @@ angle::Result CommandQueue::enqueueMapImage(cl_mem image, const Image &img = image->cast(); const bool blocking = blockingMap != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueMapImage(img, blocking, mapFlags, origin, region, imageRowPitch, - imageSlicePitch, waitEvents, eventCreateFuncPtr, mapPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_MAP_IMAGE)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueMapImage(img, blocking, mapFlags, origin, region, imageRowPitch, + imageSlicePitch, waitEvents, eventPtr, mapPtr), + event); - return CheckCreateEvent(*this, CL_COMMAND_MAP_IMAGE, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueUnmapMemObject(cl_mem memobj, @@ -518,14 +533,14 @@ angle::Result CommandQueue::enqueueUnmapMemObject(cl_mem memobj, { const Memory &memory = memobj->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueUnmapMemObject(memory, mappedPtr, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_UNMAP_MEM_OBJECT)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_UNMAP_MEM_OBJECT, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueUnmapMemObject(memory, mappedPtr, waitEvents, eventPtr), + event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueMigrateMemObjects(cl_uint numMemObjects, @@ -542,14 +557,14 @@ angle::Result CommandQueue::enqueueMigrateMemObjects(cl_uint numMemObjects, memories.emplace_back(&(*memObjects++)->cast()); } const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueMigrateMemObjects(memories, flags, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_MIGRATE_MEM_OBJECTS)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_MIGRATE_MEM_OBJECTS, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueMigrateMemObjects(memories, flags, waitEvents, eventPtr), + event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueNDRangeKernel(cl_kernel kernel, @@ -560,14 +575,13 @@ angle::Result CommandQueue::enqueueNDRangeKernel(cl_kernel kernel, { const Kernel &krnl = kernel->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueNDRangeKernel(krnl, ndrange, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_NDRANGE_KERNEL)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueNDRangeKernel(krnl, ndrange, waitEvents, eventPtr), event); - return CheckCreateEvent(*this, CL_COMMAND_NDRANGE_KERNEL, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueTask(cl_kernel kernel, @@ -577,14 +591,13 @@ angle::Result CommandQueue::enqueueTask(cl_kernel kernel, { const Kernel &krnl = kernel->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueTask(krnl, waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_TASK)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueTask(krnl, waitEvents, eventPtr), event); - return CheckCreateEvent(*this, CL_COMMAND_TASK, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueNativeKernel(UserFunc userFunc, @@ -628,15 +641,15 @@ angle::Result CommandQueue::enqueueNativeKernel(UserFunc userFunc, } const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueNativeKernel(userFunc, args, cbArgs, buffers, offsets, waitEvents, - eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_NATIVE_KERNEL)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_NATIVE_KERNEL, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY( + mImpl->enqueueNativeKernel(userFunc, args, cbArgs, buffers, offsets, waitEvents, eventPtr), + event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueMarkerWithWaitList(cl_uint numEventsInWaitList, @@ -644,24 +657,23 @@ angle::Result CommandQueue::enqueueMarkerWithWaitList(cl_uint numEventsInWaitLis cl_event *event) { const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueMarkerWithWaitList(waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_MARKER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueMarkerWithWaitList(waitEvents, eventPtr), event); - return CheckCreateEvent(*this, CL_COMMAND_MARKER, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueMarker(cl_event *event) { - rx::CLEventImpl::CreateFunc eventCreateFunc; - InitializeOutputEvent(event); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_MARKER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - ANGLE_TRY(mImpl->enqueueMarker(eventCreateFunc)); + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueMarker(eventPtr), event); - return CheckCreateEvent(*this, CL_COMMAND_MARKER, eventCreateFunc, event); + return angle::Result::Continue; } angle::Result CommandQueue::enqueueWaitForEvents(cl_uint numEvents, const cl_event *eventList) @@ -674,14 +686,13 @@ angle::Result CommandQueue::enqueueBarrierWithWaitList(cl_uint numEventsInWaitLi cl_event *event) { const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); - rx::CLEventImpl::CreateFunc eventCreateFunc; - rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = - event != nullptr ? &eventCreateFunc : nullptr; - InitializeOutputEvent(event); - ANGLE_TRY(mImpl->enqueueBarrierWithWaitList(waitEvents, eventCreateFuncPtr)); + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_BARRIER)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); - return CheckCreateEvent(*this, CL_COMMAND_BARRIER, eventCreateFunc, event); + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueBarrierWithWaitList(waitEvents, eventPtr), event); + + return angle::Result::Continue; } angle::Result CommandQueue::enqueueBarrier() @@ -699,6 +710,52 @@ angle::Result CommandQueue::finish() return mImpl->finish(); } +angle::Result CommandQueue::enqueueAcquireExternalMemObjectsKHR(cl_uint numMemObjects, + const cl_mem *memObjects, + cl_uint numEventsInWaitList, + const cl_event *eventWaitList, + cl_event *event) +{ + MemoryPtrs memories; + memories.reserve(numMemObjects); + for (cl_uint index = 0; index < numMemObjects; ++index) + { + memories.emplace_back(&memObjects[index]->cast()); + } + const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); + + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_ACQUIRE_EXTERNAL_MEM_OBJECTS_KHR)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueAcquireExternalMemObjectsKHR(memories, waitEvents, eventPtr), + event); + + return angle::Result::Continue; +} + +angle::Result CommandQueue::enqueueReleaseExternalMemObjectsKHR(cl_uint numMemObjects, + const cl_mem *memObjects, + cl_uint numEventsInWaitList, + const cl_event *eventWaitList, + cl_event *event) +{ + MemoryPtrs memories; + memories.reserve(numMemObjects); + for (cl_uint index = 0; index < numMemObjects; ++index) + { + memories.emplace_back(&memObjects[index]->cast()); + } + const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); + + ANGLE_TRY(CreateEvent(event, *this, CL_COMMAND_RELEASE_EXTERNAL_MEM_OBJECTS_KHR)); + EventPtr eventPtr(event != nullptr ? &(*event)->cast() : nullptr); + + ANGLE_CL_ENQUEUE_TRY(mImpl->enqueueReleaseExternalMemObjectsKHR(memories, waitEvents, eventPtr), + event); + + return angle::Result::Continue; +} + CommandQueue::~CommandQueue() { auto queue = mDevice->mDefaultCommandQueue.synchronize(); @@ -717,6 +774,7 @@ size_t CommandQueue::getDeviceIndex() const CommandQueue::CommandQueue(Context &context, Device &device, PropArray &&propArray, + Priority priority, CommandQueueProperties properties, cl_uint size) : mContext(&context), @@ -724,6 +782,7 @@ CommandQueue::CommandQueue(Context &context, mPropArray(std::move(propArray)), mProperties(properties), mSize(size), + mPriority(priority), mImpl(nullptr) { ANGLE_CL_IMPL_TRY(context.getImpl().createCommandQueue(*this, &mImpl)); @@ -734,7 +793,11 @@ CommandQueue::CommandQueue(Context &context, } CommandQueue::CommandQueue(Context &context, Device &device, CommandQueueProperties properties) - : mContext(&context), mDevice(&device), mProperties(properties), mImpl(nullptr) + : mContext(&context), + mDevice(&device), + mProperties(properties), + mPriority(CL_QUEUE_PRIORITY_MED_KHR), + mImpl(nullptr) { ANGLE_CL_IMPL_TRY(context.getImpl().createCommandQueue(*this, &mImpl)); } diff --git a/src/libANGLE/CLCommandQueue.h b/src/libANGLE/CLCommandQueue.h index 484f2b719af..0905a0d5b71 100644 --- a/src/libANGLE/CLCommandQueue.h +++ b/src/libANGLE/CLCommandQueue.h @@ -54,9 +54,9 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueReadBufferRect(cl_mem buffer, cl_bool blockingRead, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, @@ -68,9 +68,9 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueWriteBufferRect(cl_mem buffer, cl_bool blockingWrite, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, @@ -91,9 +91,9 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueCopyBufferRect(cl_mem srcBuffer, cl_mem dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, @@ -123,8 +123,8 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueReadImage(cl_mem image, cl_bool blockingRead, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, @@ -134,8 +134,8 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueWriteImage(cl_mem image, cl_bool blockingWrite, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, @@ -145,25 +145,25 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueCopyImage(cl_mem srcImage, cl_mem dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event); angle::Result enqueueFillImage(cl_mem image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event); angle::Result enqueueCopyImageToBuffer(cl_mem srcImage, cl_mem dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, cl_uint numEventsInWaitList, const cl_event *eventWaitList, @@ -172,8 +172,8 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueCopyBufferToImage(cl_mem srcBuffer, cl_mem dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event); @@ -181,8 +181,8 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result enqueueMapImage(cl_mem image, cl_bool blockingMap, MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, cl_uint numEventsInWaitList, @@ -241,8 +241,21 @@ class CommandQueue final : public _cl_command_queue, public Object angle::Result flush(); angle::Result finish(); + angle::Result enqueueAcquireExternalMemObjectsKHR(cl_uint numMemObjects, + const cl_mem *memObjects, + cl_uint numEventsInWaitList, + const cl_event *eventWaitList, + cl_event *event); + + angle::Result enqueueReleaseExternalMemObjectsKHR(cl_uint numMemObjects, + const cl_mem *memObjects, + cl_uint numEventsInWaitList, + const cl_event *eventWaitList, + cl_event *event); + public: using PropArray = std::vector; + using Priority = cl_queue_priority_khr; static constexpr cl_uint kNoSize = std::numeric_limits::max(); @@ -262,6 +275,8 @@ class CommandQueue final : public _cl_command_queue, public Object bool hasSize() const; cl_uint getSize() const; + Priority getPriority() const; + template T &getImpl() const; @@ -271,6 +286,7 @@ class CommandQueue final : public _cl_command_queue, public Object CommandQueue(Context &context, Device &device, PropArray &&propArray, + Priority priority, CommandQueueProperties properties, cl_uint size); @@ -281,6 +297,7 @@ class CommandQueue final : public _cl_command_queue, public Object const PropArray mPropArray; angle::SynchronizedValue mProperties; const cl_uint mSize = kNoSize; + const Priority mPriority; rx::CLCommandQueueImpl::Ptr mImpl; friend class Object; @@ -326,6 +343,11 @@ inline cl_uint CommandQueue::getSize() const return mSize; } +inline CommandQueue::Priority CommandQueue::getPriority() const +{ + return mPriority; +} + template inline T &CommandQueue::getImpl() const { diff --git a/src/libANGLE/CLContext.cpp b/src/libANGLE/CLContext.cpp index 9938ee621f2..da210f99811 100644 --- a/src/libANGLE/CLContext.cpp +++ b/src/libANGLE/CLContext.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLContext.cpp: Implements the cl::Context class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLContext.h" @@ -86,6 +91,9 @@ cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device, CommandQueue::PropArray propArray; CommandQueueProperties props; cl_uint size = CommandQueue::kNoSize; + // If CL_QUEUE_PRIORITY_KHR is not specified, the default priority CL_QUEUE_PRIORITY_MED_KHR is + // used. + CommandQueue::Priority priority = CL_QUEUE_PRIORITY_MED_KHR; if (properties != nullptr) { const cl_queue_properties *propIt = properties; @@ -99,6 +107,9 @@ cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device, case CL_QUEUE_SIZE: size = static_cast(*propIt++); break; + case CL_QUEUE_PRIORITY_KHR: + priority = static_cast(*propIt++); + break; } } // Include the trailing zero @@ -106,8 +117,8 @@ cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device, propArray.reserve(propIt - properties); propArray.insert(propArray.cend(), properties, propIt); } - return Object::Create(*this, device->cast(), std::move(propArray), props, - size); + return Object::Create(*this, device->cast(), std::move(propArray), + priority, props, size); } cl_command_queue Context::createCommandQueue(cl_device_id device, CommandQueueProperties properties) @@ -370,6 +381,46 @@ void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t } } +Memory::PropArray Context::ConvertArmMemPropToMemProp(const cl_import_properties_arm *properties, + const void *handle) +{ + Memory::PropArray convertedProperties; + const NameValueProperty *propertiesIterator = + reinterpret_cast(properties); + + if (propertiesIterator != nullptr) + { + for (; propertiesIterator->name != 0; propertiesIterator++) + { + if (propertiesIterator->name == CL_IMPORT_TYPE_ARM) + { + switch (propertiesIterator->value) + { + case CL_IMPORT_TYPE_DMA_BUF_ARM: + convertedProperties.push_back(CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR); + break; + case CL_IMPORT_TYPE_HOST_ARM: + case CL_IMPORT_TYPE_ANDROID_HARDWARE_BUFFER_ARM: + // currently no equivalents for HOST or AHB types + default: + UNIMPLEMENTED(); + continue; + } + convertedProperties.push_back(reinterpret_cast(handle)); + } + else if (propertiesIterator->name == CL_IMPORT_TYPE_PROTECTED_ARM) + { + // currently no equivalent for cl_khr_external_memory + UNIMPLEMENTED(); + continue; + } + } + } + convertedProperties.push_back(0); // zero-terminator + + return convertedProperties; +} + Context::Context(Platform &platform, PropArray &&properties, DevicePtrs &&devices, diff --git a/src/libANGLE/CLContext.h b/src/libANGLE/CLContext.h index 6145726d2d6..b14fa92da0a 100644 --- a/src/libANGLE/CLContext.h +++ b/src/libANGLE/CLContext.h @@ -10,6 +10,7 @@ #define LIBANGLE_CLCONTEXT_H_ #include "libANGLE/CLDevice.h" +#include "libANGLE/CLMemory.h" #include "libANGLE/CLPlatform.h" #include "libANGLE/renderer/CLContextImpl.h" @@ -115,10 +116,13 @@ class Context final : public _cl_context, public Object bool supportsBuiltInKernel(const std::string &name) const; bool supportsImage2DFromBuffer() const; + public: static void CL_CALLBACK ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData); + static Memory::PropArray ConvertArmMemPropToMemProp(const cl_import_properties_arm *properties, + const void *handle); private: Context(Platform &platform, diff --git a/src/libANGLE/CLDevice.cpp b/src/libANGLE/CLDevice.cpp index a4717532b8a..7ef11050953 100644 --- a/src/libANGLE/CLDevice.cpp +++ b/src/libANGLE/CLDevice.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLDevice.cpp: Implements the cl::Device class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLDevice.h" @@ -151,7 +156,16 @@ angle::Result Device::getInfo(DeviceInfo name, ANGLE_TRY(mImpl->getInfoString(name, copySize, valString.data())); copyValue = valString.data(); break; - + case DeviceInfo::ExternalMemoryImportHandleTypes: + copyValue = mInfo.externalMemoryHandleSupportList.data(); + copySize = mInfo.externalMemoryHandleSupportList.size() * + sizeof(*mInfo.externalMemoryHandleSupportList.data()); + break; + case DeviceInfo::ExternalMemoryLinearImagesHandleTypes: + // TODO: revisit this later + // http://anglebug.com/378017028 + ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE); + break; // Handle all cached values case DeviceInfo::Type: copyValue = &mInfo.type; @@ -278,6 +292,19 @@ angle::Result Device::getInfo(DeviceInfo name, copySize = mInfo.partitionType.size() * sizeof(decltype(mInfo.partitionType)::value_type); break; + case DeviceInfo::IntegerDotProductCapabilities: + copyValue = &mInfo.integerDotProductCapabilities; + copySize = sizeof(mInfo.integerDotProductCapabilities); + break; + case DeviceInfo::IntegerDotProductAccelerationProperties8bit: + copyValue = &mInfo.integerDotProductAccelerationProperties8Bit; + copySize = sizeof(mInfo.integerDotProductAccelerationProperties8Bit); + break; + + case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked: + copyValue = &mInfo.integerDotProductAccelerationProperties4x8BitPacked; + copySize = sizeof(mInfo.integerDotProductAccelerationProperties4x8BitPacked); + break; // Handle all mapped values case DeviceInfo::Platform: @@ -435,12 +462,7 @@ bool Device::supportsNonUniformWorkGroups() const else { // Check older platforms support via device extension - // TODO(aannestrand) Boolean-ify these extension strings rather than string compare - // http://anglebug.com/381335059 - if (getInfo().extensions.find("cl_arm_non_uniform_work_group_size") != std::string::npos) - { - support = true; - } + support = getInfo().armNonUniformWorkGroupSize; } return support; diff --git a/src/libANGLE/CLEvent.cpp b/src/libANGLE/CLEvent.cpp index d9b8d516d3b..f9b64d8c0dd 100644 --- a/src/libANGLE/CLEvent.cpp +++ b/src/libANGLE/CLEvent.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLEvent.cpp: Implements the cl::Event class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLEvent.h" @@ -18,6 +23,10 @@ namespace cl angle::Result Event::setUserEventStatus(cl_int executionStatus) { + // we need to retain in the case of situations where any waiting thread(s) on clWaitForEvents + // get signaled here from backend/mImpl call before we completely finish this routine. + cl::EventPtr implicitRetain(this); + ANGLE_TRY(mImpl->setUserEventStatus(executionStatus)); mStatusWasChanged = true; return angle::Result::Continue; @@ -127,13 +136,15 @@ angle::Result Event::initBackend(const rx::CLEventImpl::CreateFunc &createFunc) } else { + // execute the create func lambda that was passed into this method mImpl = createFunc(*this); if (mImpl == nullptr) { ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY); } - return mImpl->onEventCreate(); } + + return angle::Result::Continue; } Event::~Event() = default; @@ -165,9 +176,7 @@ EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList) } Event::Event(Context &context) : mContext(&context), mCommandType(CL_COMMAND_USER), mImpl(nullptr) -{ - ANGLE_CL_IMPL_TRY(context.getImpl().createUserEvent(*this, &mImpl)); -} +{} Event::Event(CommandQueue &queue, cl_command_type commandType) : mContext(&queue.getContext()), diff --git a/src/libANGLE/CLEvent.h b/src/libANGLE/CLEvent.h index 67f5e0f8228..9b1b58eaf11 100644 --- a/src/libANGLE/CLEvent.h +++ b/src/libANGLE/CLEvent.h @@ -53,6 +53,7 @@ class Event final : public _cl_event, public Object void callback(cl_int commandStatus); angle::Result initBackend(const rx::CLEventImpl::CreateFunc &createFunc); + bool isBackendInitialized() const { return mImpl != nullptr; } bool isUserEvent() const { return mCommandType == CL_COMMAND_USER; } static EventPtrs Cast(cl_uint numEvents, const cl_event *eventList); diff --git a/src/libANGLE/CLImage.cpp b/src/libANGLE/CLImage.cpp index 36463baf243..fd216a89482 100644 --- a/src/libANGLE/CLImage.cpp +++ b/src/libANGLE/CLImage.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLImage.cpp: Implements the cl::Image class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLImage.h" #include "libANGLE/CLContext.h" @@ -115,23 +120,27 @@ angle::Result Image::getInfo(ImageInfo name, Image::~Image() = default; -bool Image::isRegionValid(const cl::MemOffsets &origin, const cl::Coordinate ®ion) const +bool Image::isRegionValid(const cl::Offset &origin, const cl::Extents ®ion) const { switch (getType()) { case MemObjectType::Image1D: case MemObjectType::Image1D_Buffer: - return origin.x + region.x <= mDesc.width; + return origin.x + region.width <= mDesc.width; case MemObjectType::Image2D: - return origin.x + region.x <= mDesc.width && origin.y + region.y <= mDesc.height; + return origin.x + region.width <= mDesc.width && + origin.y + region.height <= mDesc.height; case MemObjectType::Image3D: - return origin.x + region.x <= mDesc.width && origin.y + region.y <= mDesc.height && - origin.z + region.z <= mDesc.depth; + return origin.x + region.width <= mDesc.width && + origin.y + region.height <= mDesc.height && + origin.z + region.depth <= mDesc.depth; case MemObjectType::Image1D_Array: - return origin.x + region.x <= mDesc.width && origin.y + region.y <= mDesc.arraySize; + return origin.x + region.width <= mDesc.width && + origin.y + region.height <= mDesc.arraySize; case MemObjectType::Image2D_Array: - return origin.x + region.x <= mDesc.width && origin.y + region.y <= mDesc.height && - origin.z + region.z <= mDesc.arraySize; + return origin.x + region.width <= mDesc.width && + origin.y + region.height <= mDesc.height && + origin.z + region.depth <= mDesc.arraySize; default: ASSERT(false); break; diff --git a/src/libANGLE/CLImage.h b/src/libANGLE/CLImage.h index 8c960078922..1837a218c8b 100644 --- a/src/libANGLE/CLImage.h +++ b/src/libANGLE/CLImage.h @@ -37,7 +37,7 @@ class Image final : public Memory const cl_image_format &getFormat() const; const ImageDescriptor &getDescriptor() const; - bool isRegionValid(const cl::MemOffsets &origin, const cl::Coordinate ®ion) const; + bool isRegionValid(const cl::Offset &origin, const cl::Extents ®ion) const; size_t getElementSize() const; size_t getRowSize() const; diff --git a/src/libANGLE/CLKernel.cpp b/src/libANGLE/CLKernel.cpp index 95630946e94..91acd61b292 100644 --- a/src/libANGLE/CLKernel.cpp +++ b/src/libANGLE/CLKernel.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLKernel.cpp: Implements the cl::Kernel class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif #include "libANGLE/CLKernel.h" diff --git a/src/libANGLE/CLMemory.cpp b/src/libANGLE/CLMemory.cpp index 6e17ae4ab1f..4a3a85ef64a 100644 --- a/src/libANGLE/CLMemory.cpp +++ b/src/libANGLE/CLMemory.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLMemory.cpp: Implements the cl::Memory class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLMemory.h" diff --git a/src/libANGLE/CLPlatform.cpp b/src/libANGLE/CLPlatform.cpp index a15b1574aec..6c91bc47dfd 100644 --- a/src/libANGLE/CLPlatform.cpp +++ b/src/libANGLE/CLPlatform.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLPlatform.cpp: Implements the cl::Platform class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/Context.h" #include "libANGLE/capture/FrameCapture.h" @@ -160,6 +165,11 @@ angle::Result Platform::getInfo(PlatformInfo name, copyValue = kIcdSuffix; copySize = sizeof(kIcdSuffix); break; + case PlatformInfo::ExternalMemory: + copyValue = mInfo.externalMemoryHandleSupportList.data(); + copySize = mInfo.externalMemoryHandleSupportList.size() * + sizeof(*mInfo.externalMemoryHandleSupportList.data()); + break; default: ASSERT(false); ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE); @@ -283,9 +293,12 @@ Platform::~Platform() = default; Platform::Platform(const rx::CLPlatformImpl::CreateFunc &createFunc) : mImpl(createFunc(*this)), - mInfo(mImpl ? mImpl->createInfo() : rx::CLPlatformImpl::Info{}), mDevices(mImpl ? createDevices(mImpl->createDevices()) : DevicePtrs{}), - mMultiThreadPool(mImpl ? angle::WorkerThreadPool::Create(0, ANGLEPlatformCurrent()) : nullptr) + mInfo(mImpl ? mImpl->createInfo() : rx::CLPlatformImpl::Info{}), + mMultiThreadPool(mImpl ? angle::WorkerThreadPool::Create(angle::ThreadPoolType::Asynchronous, + 0, + ANGLEPlatformCurrent()) + : nullptr) {} DevicePtrs Platform::createDevices(rx::CLDeviceImpl::CreateDatas &&createDatas) diff --git a/src/libANGLE/CLPlatform.h b/src/libANGLE/CLPlatform.h index ff613a4f32d..2ef6b655aaa 100644 --- a/src/libANGLE/CLPlatform.h +++ b/src/libANGLE/CLPlatform.h @@ -89,8 +89,8 @@ class Platform final : public _cl_platform_id, public Object static PlatformPtrs &GetPointers(); const rx::CLPlatformImpl::Ptr mImpl; - const rx::CLPlatformImpl::Info mInfo; const DevicePtrs mDevices; + const rx::CLPlatformImpl::Info mInfo; std::shared_ptr mMultiThreadPool; static constexpr char kVendor[] = "ANGLE"; diff --git a/src/libANGLE/CLProgram.cpp b/src/libANGLE/CLProgram.cpp index c35c7695a23..08b984d5e73 100644 --- a/src/libANGLE/CLProgram.cpp +++ b/src/libANGLE/CLProgram.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLProgram.cpp: Implements the cl::Program class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLProgram.h" diff --git a/src/libANGLE/CLSampler.cpp b/src/libANGLE/CLSampler.cpp index 1784ac6c016..159be47db73 100644 --- a/src/libANGLE/CLSampler.cpp +++ b/src/libANGLE/CLSampler.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLSampler.cpp: Implements the cl::Sampler class. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLSampler.h" diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp index e3708d242fe..14ab9cde2e2 100644 --- a/src/libANGLE/Caps.cpp +++ b/src/libANGLE/Caps.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Caps.h" #include "common/angleutils.h" @@ -37,30 +41,6 @@ TextureCaps &TextureCaps::operator=(const TextureCaps &other) = default; TextureCaps::~TextureCaps() = default; -GLuint TextureCaps::getMaxSamples() const -{ - return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0; -} - -GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const -{ - if (requestedSamples == 0) - { - return 0; - } - - for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++) - { - GLuint samples = *i; - if (samples >= requestedSamples) - { - return samples; - } - } - - return 0; -} - TextureCaps GenerateMinimumTextureCaps(GLenum sizedInternalFormat, const Version &clientVersion, const Extensions &extensions) @@ -77,8 +57,7 @@ TextureCaps GenerateMinimumTextureCaps(GLenum sizedInternalFormat, caps.sampleCounts.insert(0); if (internalFormatInfo.isRequiredRenderbufferFormat(clientVersion)) { - if ((clientVersion.major >= 3 && clientVersion.minor >= 1) || - (clientVersion.major >= 3 && !internalFormatInfo.isInt())) + if (clientVersion >= ES_3_1 || (clientVersion == ES_3_0 && !internalFormatInfo.isInt())) { caps.sampleCounts.insert(4); } @@ -305,6 +284,7 @@ static bool DetermineRGB8TextureSupport(const TextureCapsMap &textureCaps) static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) { constexpr GLenum requiredFormats[] = { + GL_BGRA_EXT, GL_BGRA8_EXT, }; @@ -1397,9 +1377,13 @@ std::vector DisplayExtensions::getStrings() const InsertExtensionString("EGL_ANGLE_metal_create_context_ownership_identity", metalCreateContextOwnershipIdentityANGLE, &extensionStrings); InsertExtensionString("EGL_KHR_partial_update", partialUpdateKHR, &extensionStrings); InsertExtensionString("EGL_ANGLE_metal_shared_event_sync", mtlSyncSharedEventANGLE, &extensionStrings); + InsertExtensionString("EGL_ANGLE_metal_commands_scheduled_sync", mtlSyncCommandsScheduledANGLE, &extensionStrings); InsertExtensionString("EGL_ANGLE_global_fence_sync", globalFenceSyncANGLE, &extensionStrings); InsertExtensionString("EGL_ANGLE_memory_usage_report", memoryUsageReportANGLE, &extensionStrings); InsertExtensionString("EGL_EXT_surface_compression", surfaceCompressionEXT, &extensionStrings); + InsertExtensionString("EGL_ANGLE_webgpu_texture_client_buffer", webgpuTextureClientBuffer, &extensionStrings); + InsertExtensionString("EGL_ANGLE_create_context_passthrough_shaders", createContextPassthroughShadersANGLE, &extensionStrings); + InsertExtensionString("EGL_NV_context_priority_realtime", contextPriorityRealtimeNV, &extensionStrings); // clang-format on return extensionStrings; @@ -1421,6 +1405,7 @@ std::vector DeviceExtensions::getStrings() const InsertExtensionString("EGL_ANGLE_device_vulkan", deviceVulkan, &extensionStrings); InsertExtensionString("EGL_EXT_device_drm", deviceDrmEXT, &extensionStrings); InsertExtensionString("EGL_EXT_device_drm_render_node", deviceDrmRenderNodeEXT, &extensionStrings); + InsertExtensionString("EGL_ANGLE_device_webgpu", deviceWebGPU, &extensionStrings); // clang-format on diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h index dd285b0dc08..af19f520ff4 100644 --- a/src/libANGLE/Caps.h +++ b/src/libANGLE/Caps.h @@ -46,13 +46,6 @@ struct TextureCaps // Set of supported sample counts, only guaranteed to be valid in ES3. SupportedSampleSet sampleCounts; - - // Get the maximum number of samples supported - GLuint getMaxSamples() const; - - // Get the number of supported samples that is at least as many as requested. Returns 0 if - // there are no sample counts available - GLuint getNearestSamples(GLuint requestedSamples) const; }; TextureCaps GenerateMinimumTextureCaps(GLenum internalFormat, @@ -149,6 +142,11 @@ struct Limitations // TODO(http://anglebug.com/42263785): add validation code to front-end. bool noShadowSamplerCompareModeNone = false; + // Metal [[raster_order_group()]] does not work for read_write textures on AMD when the render + // pass doesn't have a color attachment on slot 0. + // http://anglebug.com/42266263 + bool noRasterOrderGroupWithoutAttachmentZero = false; + // PVRTC1 textures must be squares. bool squarePvrtc1 = false; @@ -174,10 +172,6 @@ struct Limitations // GL_ANGLE_base_vertex_base_instance is emulated and should only be exposed to WebGL. Emulated // by default in shared renderer code. bool baseInstanceBaseVertexEmulated = true; - - // EXT_base_instance is emulated and should only be exposed to WebGL. Emulated by default in - // shared renderer code. - bool baseInstanceEmulated = true; }; struct TypePrecision @@ -199,6 +193,20 @@ struct TypePrecision GLint precision = 0; }; +struct FragmentShadingRateProperties +{ + GLuint minFragmentShadingRateAttachmentTexelWidth; + GLuint minFragmentShadingRateAttachmentTexelHeight; + GLuint maxFragmentShadingRateAttachmentTexelWidth; + GLuint maxFragmentShadingRateAttachmentTexelHeight; + GLuint maxFragmentShadingRateAttachmentTexelAspectRatio; + GLuint maxFragmentShadingRateAttachmentLayers; + bool layeredShadingRateAttachments; + bool fragmentShadingRateNonTrivialCombinersSupport; + bool fragmentShadingRateWithShaderDepthStencilWritesSupport; + bool fragmentShadingRateWithSampleMaskSupport; +}; + struct Caps { Caps(); @@ -391,7 +399,6 @@ struct Caps // GL_ANGLE_shader_pixel_local_storage GLuint maxPixelLocalStoragePlanes = 0; - GLuint maxColorAttachmentsWithActivePixelLocalStorage = 0; GLuint maxCombinedDrawBuffersAndPixelLocalStoragePlanes = 0; // GL_EXT_shader_pixel_local_storage. @@ -421,9 +428,13 @@ struct Caps // GL_ARM_shader_framebuffer_fetch bool fragmentShaderFramebufferFetchMRT = false; + + // EXT_fragment_shading_rate + FragmentShadingRateProperties fragmentShadingRateProperties = {}; }; Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions); + } // namespace gl namespace egl @@ -621,12 +632,6 @@ struct DisplayExtensions // EGL_IMG_context_priority bool contextPriority = false; - // EGL_ANGLE_ggp_stream_descriptor - bool ggpStreamDescriptor = false; - - // EGL_ANGLE_swap_with_frame_token - bool swapWithFrameToken = false; - // EGL_KHR_gl_colorspace bool glColorspace = false; @@ -711,6 +716,9 @@ struct DisplayExtensions // EGL_ANGLE_metal_shared_event_sync bool mtlSyncSharedEventANGLE = false; + // EGL_ANGLE_metal_commands_scheduled_sync + bool mtlSyncCommandsScheduledANGLE = false; + // EGL_ANGLE_global_fence_sync bool globalFenceSyncANGLE = false; @@ -719,6 +727,15 @@ struct DisplayExtensions // EGL_EXT_surface_compression bool surfaceCompressionEXT = false; + + // EGL_ANGLE_webgpu_texture_client_buffer + bool webgpuTextureClientBuffer = false; + + // EXT_ANGLE_create_context_passthrough_shaders + bool createContextPassthroughShadersANGLE = false; + + // EGL_NV_context_priority_realtime + bool contextPriorityRealtimeNV = false; }; struct DeviceExtensions @@ -751,6 +768,9 @@ struct DeviceExtensions // EGL_EXT_device_drm_render_node bool deviceDrmRenderNodeEXT = false; + + // EGL_ANGLE_device_webgpu + bool deviceWebGPU = false; }; struct ClientExtensions diff --git a/src/libANGLE/Compiler.cpp b/src/libANGLE/Compiler.cpp index 1044ab1960d..81a8cefebe1 100644 --- a/src/libANGLE/Compiler.cpp +++ b/src/libANGLE/Compiler.cpp @@ -24,17 +24,25 @@ namespace // To know when to call sh::Initialize and sh::Finalize. size_t gActiveCompilers = 0; +ShShaderOutput GetShaderOutputType(const State &state, const rx::CompilerImpl *impl) +{ + if (state.usesPassthroughShaders()) + { + return SH_NULL_OUTPUT; + } + + return impl->getTranslatorOutputType(); +} + } // anonymous namespace Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Display *display) : mImplementation(implFactory->createCompiler()), mSpec(SelectShaderSpec(state)), - mOutputType(mImplementation->getTranslatorOutputType()), + mOutputType(GetShaderOutputType(state, mImplementation.get())), mResources() { - // TODO(http://anglebug.com/42262462): Update for GL version specific validation - ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 || - state.getClientMajorVersion() == 3 || state.getClientMajorVersion() == 4); + ASSERT(state.getClientVersion() >= ES_1_0 && state.getClientVersion() <= ES_3_2); { std::lock_guard lock(display->getDisplayGlobalMutex()); @@ -84,17 +92,22 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp // OES_shader_multisample_interpolation mResources.OES_shader_multisample_interpolation = extensions.shaderMultisampleInterpolationOES; mResources.OES_shader_image_atomic = extensions.shaderImageAtomicOES; - // TODO: use shader precision caps to determine if high precision is supported? - mResources.FragmentPrecisionHigh = 1; mResources.EXT_frag_depth = extensions.fragDepthEXT; - // OVR_multiview state + // OVR_multiview / OVR_multiview2 mResources.OVR_multiview = extensions.multiviewOVR; - - // OVR_multiview2 state mResources.OVR_multiview2 = extensions.multiview2OVR; mResources.MaxViewsOVR = caps.maxViews; + // Hashing and prefixing + mResources.HashFunction = nullptr; + if (mOutputType == SH_NULL_OUTPUT) + { + // Disable user variable prefixing if using the null output type. The untranslated source + // shader is used so make sure the mapped names match the input names. + mResources.UserVariableNamePrefix = '\0'; + } + // EXT_multisampled_render_to_texture and EXT_multisampled_render_to_texture2 mResources.EXT_multisampled_render_to_texture = extensions.multisampledRenderToTextureEXT; mResources.EXT_multisampled_render_to_texture2 = extensions.multisampledRenderToTexture2EXT; @@ -169,11 +182,13 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp // ANGLE_shader_pixel_local_storage. mResources.MaxPixelLocalStoragePlanes = caps.maxPixelLocalStoragePlanes; - mResources.MaxColorAttachmentsWithActivePixelLocalStorage = - caps.maxColorAttachmentsWithActivePixelLocalStorage; mResources.MaxCombinedDrawBuffersAndPixelLocalStoragePlanes = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes; + // EXT_fragment_shading_rate + mResources.EXT_fragment_shading_rate = extensions.fragmentShadingRateEXT; + mResources.EXT_fragment_shading_rate_primitive = extensions.fragmentShadingRatePrimitiveEXT; + // OES_sample_variables mResources.OES_sample_variables = extensions.sampleVariablesOES; mResources.MaxSamples = caps.maxSamples; @@ -226,7 +241,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp mResources.MinPointSize = caps.minAliasedPointSize; mResources.MaxPointSize = caps.maxAliasedPointSize; - if (state.getClientMajorVersion() == 2 && !extensions.drawBuffersEXT) + if (state.getClientVersion() == ES_2_0 && !extensions.drawBuffersEXT) { mResources.MaxDrawBuffers = 1; } @@ -235,7 +250,6 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp mResources.EXT_geometry_shader = extensions.geometryShaderEXT; mResources.OES_geometry_shader = extensions.geometryShaderOES; mResources.MaxGeometryUniformComponents = caps.maxShaderUniformComponents[ShaderType::Geometry]; - mResources.MaxGeometryUniformBlocks = caps.maxShaderUniformBlocks[ShaderType::Geometry]; mResources.MaxGeometryInputComponents = caps.maxGeometryInputComponents; mResources.MaxGeometryOutputComponents = caps.maxGeometryOutputComponents; mResources.MaxGeometryOutputVertices = caps.maxGeometryOutputVertices; @@ -245,7 +259,6 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp mResources.MaxGeometryAtomicCounterBuffers = caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry]; mResources.MaxGeometryAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Geometry]; - mResources.MaxGeometryShaderStorageBlocks = caps.maxShaderStorageBlocks[ShaderType::Geometry]; mResources.MaxGeometryShaderInvocations = caps.maxGeometryShaderInvocations; mResources.MaxGeometryImageUniforms = caps.maxShaderImageUniforms[ShaderType::Geometry]; @@ -280,9 +293,6 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp caps.maxShaderAtomicCounters[ShaderType::TessEvaluation]; mResources.MaxTessEvaluationAtomicCounterBuffers = caps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation]; - - // Subpixel bits. - mResources.SubPixelBits = static_cast(caps.subPixelBits); } Compiler::~Compiler() = default; @@ -338,8 +348,8 @@ void Compiler::putInstance(ShCompilerInstance &&instance) ShShaderSpec Compiler::SelectShaderSpec(const State &state) { - const GLint majorVersion = state.getClientMajorVersion(); - const GLint minorVersion = state.getClientMinorVersion(); + const GLint majorVersion = state.getClientVersion().getMajor(); + const GLint minorVersion = state.getClientVersion().getMinor(); bool isWebGL = state.isWebGL(); if (majorVersion >= 3) @@ -350,7 +360,7 @@ ShShaderSpec Compiler::SelectShaderSpec(const State &state) ASSERT(!isWebGL); return SH_GLES3_2_SPEC; case 1: - return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC; + return SH_GLES3_1_SPEC; case 0: return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC; default: diff --git a/src/libANGLE/Config.cpp b/src/libANGLE/Config.cpp index 743f03215bc..749b0773c54 100644 --- a/src/libANGLE/Config.cpp +++ b/src/libANGLE/Config.cpp @@ -229,6 +229,14 @@ class ConfigSorter std::vector ConfigSet::filter(const AttributeMap &attributeMap) const { std::vector result; + + // If EGL_CONFIG_ID is included, all other attributes should be ignored. + if (attributeMap.contains(EGL_CONFIG_ID)) + { + result.push_back(&ConfigSet::get(attributeMap.getAsInt(EGL_CONFIG_ID))); + return result; + } + result.reserve(mConfigs.size()); for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++) @@ -272,9 +280,6 @@ std::vector ConfigSet::filter(const AttributeMap &attributeMap) case EGL_CONFIG_CAVEAT: match = config.configCaveat == static_cast(attributeValue); break; - case EGL_CONFIG_ID: - match = config.configID == attributeValue; - break; case EGL_LEVEL: match = config.level == attributeValue; break; diff --git a/src/libANGLE/Config_unittest.cpp b/src/libANGLE/Config_unittest.cpp index a0b525e8742..ac8f47d7de4 100644 --- a/src/libANGLE/Config_unittest.cpp +++ b/src/libANGLE/Config_unittest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/src/libANGLE/Constants.h b/src/libANGLE/Constants.h index 36a37dd40b4..1db5136e1ae 100644 --- a/src/libANGLE/Constants.h +++ b/src/libANGLE/Constants.h @@ -76,14 +76,19 @@ enum // In ES 3.1 and below, the limit for active textures is 64. IMPLEMENTATION_MAX_ES31_ACTIVE_TEXTURES = 64, - // In ES 3.2 we need to support a minimum of 96 maximum textures. - IMPLEMENTATION_MAX_ACTIVE_TEXTURES = 96, + // In ES 3.2 we need to support a minimum of 96 maximum textures, but some Android + // apps assume more are available without querying limits first. + IMPLEMENTATION_MAX_ACTIVE_TEXTURES = 192, IMPLEMENTATION_MAX_IMAGE_UNITS = IMPLEMENTATION_MAX_ACTIVE_TEXTURES, // Maximum framebuffer and renderbuffer size supported. IMPLEMENTATION_MAX_FRAMEBUFFER_SIZE = 32768, IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = 32768, + // Limit uniform block size to 64KB, which is what the majority of devices support. Internally, + // ANGLE assumes 16 bits are enough to hold offsets in the UBO block. + IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE = 65536, + // Maximum number of slots allocated for atomic counter buffers. IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = 8, @@ -105,6 +110,9 @@ enum // TODO (anglebug.com/42266906): Implement support for multiple layers IMPLEMENTATION_MAX_NUM_LAYERS = 1, IMPLEMENTATION_MAX_FOCAL_POINTS = 2, + + // Maximum simultaneous handles of an object type. + IMPLEMENTATION_MAX_OBJECT_HANDLES = 1 << 24, }; namespace limits diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp index 5125ccb76e6..a120b4d131f 100644 --- a/src/libANGLE/Context.cpp +++ b/src/libANGLE/Context.cpp @@ -6,6 +6,12 @@ // Context.cpp: Implements the gl::Context class, managing all GL state and performing // rendering operations. It is the GLES2 specific implementation of EGLContext. + +#include "common/entry_points_enum_autogen.h" +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Context.inl.h" #include @@ -157,7 +163,7 @@ constexpr state::ExtendedDirtyBits kDrawInvalidateExtendedDirtyBits{}; constexpr state::DirtyBits kTilingDirtyBits{state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING}; constexpr state::ExtendedDirtyBits kTilingExtendedDirtyBits{}; -constexpr state::DirtyObjects kTilingDirtyObjects{state::DIRTY_OBJECT_DRAW_FRAMEBUFFER}; +constexpr state::DirtyObjects kTilingDirtyObjectsBase{state::DIRTY_OBJECT_DRAW_FRAMEBUFFER}; constexpr bool kEnableAEPRequirementLogging = false; @@ -201,6 +207,11 @@ angle::Result GetQueryObjectParameter(const Context *context, Query *query, GLen break; case GL_QUERY_RESULT_AVAILABLE_EXT: *params = GL_FALSE; + if (context->isContextLost()) + { + context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetQueryObjectuiv); + *params = GL_TRUE; + } break; default: UNREACHABLE(); @@ -218,6 +229,7 @@ angle::Result GetQueryObjectParameter(const Context *context, Query *query, GLen bool available = false; if (context->isContextLost()) { + context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetQueryObjectuiv); available = true; } else @@ -254,13 +266,18 @@ bool GetWebGLContext(const egl::AttributeMap &attribs) return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE); } +bool GetHardenedContext(const egl::AttributeMap &attribs) +{ + return (attribs.get(EGL_CONTEXT_HARDENED_ANGLE, EGL_FALSE) == EGL_TRUE); +} + Version GetClientVersion(egl::Display *display, const egl::AttributeMap &attribs) { - Version requestedVersion = - Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs)); + const Version requestedVersion(static_cast(GetClientMajorVersion(attribs)), + static_cast(GetClientMinorVersion(attribs))); if (GetBackwardCompatibleContext(attribs)) { - if (requestedVersion.major == 1) + if (requestedVersion < ES_2_0) { // If the user requests an ES1 context, we cannot return an ES 2+ context. return Version(1, 1); @@ -313,10 +330,11 @@ bool GetRobustAccess(const egl::AttributeMap &attribs) return (attribRobustAccess || contextFlagsRobustAccess); } -bool GetDebug(const egl::AttributeMap &attribs) +bool GetDebug(const angle::FrontendFeatures &frontendFeatures, const egl::AttributeMap &attribs) { - return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE) || - ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0); + return frontendFeatures.forceDebugContexts.enabled || + attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE || + (attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0; } bool GetNoError(const egl::AttributeMap &attribs) @@ -359,6 +377,13 @@ bool GetProtectedContent(const egl::AttributeMap &attribs) return static_cast(attribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE)); } +bool GetPassthroughShaders(egl::Display *display, const egl::AttributeMap &attribs) +{ + const angle::FrontendFeatures &frontendFeatures = display->getFrontendFeatures(); + return frontendFeatures.forcePassthroughShaders.enabled || + static_cast(attribs.getAsInt(EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE, EGL_FALSE)); +} + std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label) { std::string labelName; @@ -389,6 +414,16 @@ void GetObjectLabelBase(const std::string &objectLabel, } } +GLsizei GetMarkerLength(GLsizei length, const char *marker) +{ + if (length == 0) + { + return static_cast( + std::min(strlen(marker), std::numeric_limits::max())); + } + return length; +} + enum SubjectIndexes : angle::SubjectIndex { kTexture0SubjectIndex = 0, @@ -527,12 +562,58 @@ bool CanSupportAEP(const gl::Version &version, const gl::Extensions &extensions) return result; } + +// Temporarily turns off draw buffers being used for pixel local storage, and only if the PLS +// implementation is framebuffer fetch. +// +// NOTE: This is a little nonstandard because the glDrawBuffers entrypoint is supposed to disable +// PLS, but since we only call it when the implementation is +// ShPixelLocalStorageType::FramebufferFetch, it's not a problem. +class ScopedPLSFramebufferFetchDrawBuffersDisable +{ + public: + ScopedPLSFramebufferFetchDrawBuffersDisable(Context *context) : mContext(context) + { + GLsizei nonPLSDrawBufferCount; + if (mContext->getImplementation()->getNativePixelLocalStorageOptions().type == + ShPixelLocalStorageType::FramebufferFetch && + mContext->getPrivateState().hasActivelyOverriddenPLSDrawBuffers(&nonPLSDrawBufferCount)) + { + // Turn off the PLS draw buffers. + mHasPLSDrawBuffersWithFramebufferFetch = true; + Framebuffer *drawFramebuffer = mContext->getState().getDrawFramebuffer(); + // PLS isn't supported on the default framebuffer. + ASSERT(!drawFramebuffer->isDefault()); + const DrawBuffersVector &drawBuffers = drawFramebuffer->getDrawBufferStates(); + ASSERT(drawBuffers.size() <= std::size(mOriginalDrawBufferState)); + std::copy(drawBuffers.begin(), drawBuffers.end(), mOriginalDrawBufferState.data()); + mOriginalDrawBufferCount = static_cast(drawBuffers.size()); + // Turn off all non-PLS draw buffers. + mContext->drawBuffers(std::min(mOriginalDrawBufferCount, nonPLSDrawBufferCount), + mOriginalDrawBufferState.data()); + } + } + + ~ScopedPLSFramebufferFetchDrawBuffersDisable() + { + if (mHasPLSDrawBuffersWithFramebufferFetch) + { + // Restore the PLS draw buffers. + mContext->drawBuffers(mOriginalDrawBufferCount, mOriginalDrawBufferState.data()); + } + } + + private: + Context *const mContext; + bool mHasPLSDrawBuffersWithFramebufferFetch = false; + std::array mOriginalDrawBufferState; + GLsizei mOriginalDrawBufferCount; +}; } // anonymous namespace #if defined(ANGLE_PLATFORM_APPLE) -// TODO(angleproject:6479): Due to a bug in Apple's dyld loader, `thread_local` will cause -// excessive memory use. Temporarily avoid it by using pthread's thread -// local storage instead. +// TODO(http://anglebug.com/42264979): Due to a bug in Apple's dyld loader, `thread_local` will +// cause excessive memory use. Temporarily avoid it by using pthread's thread local storage instead. static angle::TLSIndex GetCurrentValidContextTLSIndex() { static angle::TLSIndex CurrentValidContextIndex = TLS_INVALID_INDEX; @@ -605,7 +686,7 @@ Context::Context(egl::Display *display, AllocateOrUseContextMutex(sharedContextMutex), &mOverlay, GetClientVersion(display, attribs), - GetDebug(attribs), + GetDebug(display->getFrontendFeatures(), attribs), GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs), GetRobustResourceInit(display, attribs), @@ -613,8 +694,10 @@ Context::Context(egl::Display *display, GetContextPriority(attribs), GetRobustAccess(attribs), GetProtectedContent(attribs), - GetIsExternal(attribs)), + GetIsExternal(attribs), + GetPassthroughShaders(display, attribs)), mShared(shareContext != nullptr || shareTextures != nullptr || shareSemaphores != nullptr), + mSharedContext(shareContext != nullptr), mDisplayTextureShareGroup(shareTextures != nullptr), mDisplaySemaphoreShareGroup(shareSemaphores != nullptr), mErrors(&mState.getDebug(), display->getFrontendFeatures(), attribs), @@ -623,13 +706,18 @@ Context::Context(egl::Display *display, mLabel(nullptr), mCompiler(), mConfig(config), + mFenceNVHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES), + mQueryHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES), + mTransformFeedbackHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES), mHasBeenCurrent(false), mSurfacelessSupported(displayExtensions.surfacelessContext), mCurrentDrawSurface(static_cast(EGL_NO_SURFACE)), mCurrentReadSurface(static_cast(EGL_NO_SURFACE)), mDisplay(display), mWebGLContext(GetWebGLContext(attribs)), + mHardenedContext(GetHardenedContext(attribs)), mBufferAccessValidationEnabled(false), + mRequiresRobustBehavior(false), mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)), mMemoryProgramCache(memoryProgramCache), mMemoryShaderCache(memoryShaderCache), @@ -707,8 +795,6 @@ void Context::initializeDefaultResources() mDefaultFramebuffer = std::make_unique(this, mImplementation.get()); - mFenceNVHandleAllocator.setBaseHandle(0); - // [OpenGL ES 2.0.24] section 3.7 page 83: // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have two-dimensional // and cube map texture state vectors respectively associated with them. @@ -824,7 +910,7 @@ void Context::initializeDefaultResources() for (int i = 0; i < mState.getCaps().maxUniformBufferBindings; i++) { - bindBufferRange(BufferBinding::Uniform, i, {0}, 0, -1); + bindBufferRange(BufferBinding::Uniform, i, {0}, 0, 0); } // Initialize GLES1 renderer if appropriate. @@ -842,6 +928,7 @@ void Context::initializeDefaultResources() mComputeDirtyObjects |= kComputeDirtyObjectsBase; mCopyImageDirtyBits |= kCopyImageDirtyBitsBase; mCopyImageDirtyObjects |= kCopyImageDirtyObjectsBase; + mTilingDirtyObjects |= kTilingDirtyObjectsBase; mOverlay.init(); } @@ -863,6 +950,8 @@ egl::Error Context::onDestroy(const egl::Display *display) // that still have it current. ASSERT(mIsDestroyed == true && mRefCount == 0); + ANGLE_TRY(unMakeCurrent(display)); + // Dump frame capture if enabled. getShareGroup()->getFrameCaptureShared()->onDestroyContext(this); @@ -874,8 +963,6 @@ egl::Error Context::onDestroy(const egl::Display *display) mGLES1Renderer->onDestroy(this, &mState); } - ANGLE_TRY(unMakeCurrent(display)); - mDefaultFramebuffer->onDestroy(this); mDefaultFramebuffer.reset(); @@ -898,14 +985,13 @@ egl::Error Context::onDestroy(const egl::Display *display) } mQueryMap.clear(); - for (auto vertexArray : UnsafeResourceMapIter(mVertexArrayMap)) + for (auto vertexArray : UnsafeResourceMapIter(getPrivateState().getVertexArrayMap())) { if (vertexArray.second) { vertexArray.second->onDestroy(this); } } - mVertexArrayMap.clear(); for (auto transformFeedback : UnsafeResourceMapIter(mTransformFeedbackMap)) { @@ -975,6 +1061,15 @@ egl::Error Context::makeCurrent(egl::Display *display, { mDisplay = display; + EGLint width = 0; + EGLint height = 0; + + angle::FrameCaptureShared *frameCaptureShared = getShareGroup()->getFrameCaptureShared(); + if ((frameCaptureShared->enabled() || !mHasBeenCurrent) && drawSurface != nullptr) + { + ANGLE_TRY(drawSurface->getUserSize(display, &width, &height)); + } + if (!mHasBeenCurrent) { initializeDefaultResources(); @@ -983,14 +1078,6 @@ egl::Error Context::makeCurrent(egl::Display *display, initVersionStrings(); initExtensionStrings(); - int width = 0; - int height = 0; - if (drawSurface != nullptr) - { - width = drawSurface->getWidth(); - height = drawSurface->getHeight(); - } - ContextPrivateViewport(getMutablePrivateState(), getMutablePrivateStateCache(), 0, 0, width, height); ContextPrivateScissor(getMutablePrivateState(), getMutablePrivateStateCache(), 0, 0, width, @@ -1001,7 +1088,7 @@ egl::Error Context::makeCurrent(egl::Display *display, ANGLE_TRY(unsetDefaultFramebuffer()); - getShareGroup()->getFrameCaptureShared()->onMakeCurrent(this, drawSurface); + frameCaptureShared->onMakeCurrent(this, drawSurface, width, height); // TODO(jmadill): Rework this when we support ContextImpl mState.setAllDirtyBits(); @@ -1042,52 +1129,76 @@ egl::Error Context::unMakeCurrent(const egl::Display *display) return egl::NoError(); } -BufferID Context::createBuffer() +void Context::contextLostErrorOnBlockingCall(angle::EntryPoint entryPoint) const +{ + mErrors.validationError(entryPoint, GL_CONTEXT_LOST, err::kContextLost); +} + +void Context::handleExhaustionError(angle::EntryPoint entryPoint) +{ + mErrors.validationError(entryPoint, GL_OUT_OF_MEMORY, err::kHandleExhaustion); +} + +bool Context::createBuffer(BufferID *outBuffer) { - return mState.mBufferManager->createBuffer(); + return mState.mBufferManager->createBuffer(outBuffer); } GLuint Context::createProgram() { - return mState.mShaderProgramManager->createProgram(mImplementation.get()).value; + ShaderProgramID id; + if (!mState.mShaderProgramManager->createProgram(mImplementation.get(), &id)) + { + handleExhaustionError(angle::EntryPoint::GLCreateProgram); + return 0; + } + return id.value; } GLuint Context::createShader(ShaderType type) { - return mState.mShaderProgramManager - ->createShader(mImplementation.get(), mState.getLimitations(), type) - .value; + ShaderProgramID id; + if (!mState.mShaderProgramManager->createShader(mImplementation.get(), mState.getLimitations(), + type, &id)) + { + handleExhaustionError(angle::EntryPoint::GLCreateShader); + return 0; + } + return id.value; } -TextureID Context::createTexture() +bool Context::createTexture(TextureID *outTexture) { - return mState.mTextureManager->createTexture(); + return mState.mTextureManager->createTexture(outTexture); } -RenderbufferID Context::createRenderbuffer() +bool Context::createRenderbuffer(RenderbufferID *outRenderbuffer) { - return mState.mRenderbufferManager->createRenderbuffer(); + return mState.mRenderbufferManager->createRenderbuffer(outRenderbuffer); } // Returns an unused framebuffer name -FramebufferID Context::createFramebuffer() +bool Context::createFramebuffer(FramebufferID *outFramebuffer) { - return mState.mFramebufferManager->createFramebuffer(); + return mState.mFramebufferManager->createFramebuffer(outFramebuffer); } void Context::genFencesNV(GLsizei n, FenceNVID *fences) { for (int i = 0; i < n; i++) { - GLuint handle = mFenceNVHandleAllocator.allocate(); - mFenceNVMap.assign({handle}, new FenceNV(mImplementation.get())); - fences[i] = {handle}; + if (!mFenceNVHandleAllocator.allocate(&fences[i].value)) + { + handleExhaustionError(angle::EntryPoint::GLGenFencesNV); + return; + } + mFenceNVMap.assign(fences[i], new FenceNV(mImplementation.get())); } } -ProgramPipelineID Context::createProgramPipeline() +bool Context::createProgramPipeline(ProgramPipelineID *outProgramPipeline) { - return mState.mProgramPipelineManager->createProgramPipeline(); + return mState.mProgramPipelineManager->createProgramPipeline(outProgramPipeline); } GLuint Context::createShaderProgramv(ShaderType type, GLsizei count, const GLchar *const *strings) @@ -1142,14 +1253,14 @@ GLuint Context::createShaderProgramv(ShaderType type, GLsizei count, const GLcha return 0u; } -MemoryObjectID Context::createMemoryObject() +bool Context::createMemoryObject(MemoryObjectID *outMemoryObject) { - return mState.mMemoryObjectManager->createMemoryObject(mImplementation.get()); + return mState.mMemoryObjectManager->createMemoryObject(mImplementation.get(), outMemoryObject); } -SemaphoreID Context::createSemaphore() +bool Context::createSemaphore(SemaphoreID *outSemaphore) { - return mState.mSemaphoreManager->createSemaphore(mImplementation.get()); + return mState.mSemaphoreManager->createSemaphore(mImplementation.get(), outSemaphore); } void Context::deleteBuffer(BufferID bufferName) @@ -1175,26 +1286,13 @@ void Context::deleteProgram(ShaderProgramID program) void Context::deleteTexture(TextureID textureID) { - // If a texture object is deleted while its image is bound to a pixel local storage plane on the - // currently bound draw framebuffer, and pixel local storage is active, then it is as if - // EndPixelLocalStorageANGLE() had been called with =PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE - // and of STORE_OP_STORE_ANGLE. - if (mState.getPixelLocalStorageActivePlanes() != 0) + if (mState.isTextureBoundToActivePLS(textureID)) { - PixelLocalStorage *pls = mState.getDrawFramebuffer()->peekPixelLocalStorage(); - // Even though there is a nonzero number of active PLS planes, peekPixelLocalStorage() may - // still return null if we are in the middle of deleting the active framebuffer. - if (pls != nullptr) - { - for (GLuint i = 0; i < mState.getCaps().maxPixelLocalStoragePlanes; ++i) - { - if (pls->getPlane(i).getTextureID() == textureID) - { - endPixelLocalStorageImplicit(); - break; - } - } - } + // If a texture object is deleted while its image is bound to a pixel local storage plane on + // the currently bound draw framebuffer, and pixel local storage is active, then it is as if + // EndPixelLocalStorageANGLE() had been called with + // =PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE and of STORE_OP_STORE_ANGLE. + endPixelLocalStorageImplicit(); } Texture *texture = mState.mTextureManager->getTexture(textureID); @@ -1321,11 +1419,6 @@ Sync *Context::getSync(SyncID syncPacked) const return mState.mSyncManager->getSync(syncPacked); } -VertexArray *Context::getVertexArray(VertexArrayID handle) const -{ - return mVertexArrayMap.query(handle); -} - Sampler *Context::getSampler(SamplerID handle) const { return mState.mSamplerManager->getSampler(handle); @@ -1356,7 +1449,7 @@ gl::LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) con return getProgramNoResolveLink({name}); case GL_VERTEX_ARRAY: case GL_VERTEX_ARRAY_OBJECT_EXT: - return getVertexArray({name}); + return getPrivateState().getVertexArray({name}); case GL_QUERY: case GL_QUERY_OBJECT_EXT: return getQuery({name}); @@ -1506,7 +1599,7 @@ void Context::bindVertexArray(VertexArrayID vertexArrayHandle) VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle); mState.setVertexArrayBinding(this, vertexArray); mVertexArrayObserverBinding.bind(vertexArray); - mStateCache.onVertexArrayBindingChange(this); + mPrivateStateCache.onVertexArrayBindingChange(); } void Context::bindVertexBuffer(GLuint bindingIndex, @@ -1517,7 +1610,7 @@ void Context::bindVertexBuffer(GLuint bindingIndex, Buffer *buffer = mState.mBufferManager->checkBufferAllocation(mImplementation.get(), bufferHandle); mState.bindVertexBuffer(this, bindingIndex, buffer, offset, stride); - mStateCache.onVertexArrayStateChange(this); + mPrivateStateCache.onVertexArrayStateChange(); } void Context::bindSampler(GLuint textureUnit, SamplerID samplerHandle) @@ -1577,7 +1670,7 @@ void Context::bindTransformFeedback(GLenum target, TransformFeedbackID transform TransformFeedback *transformFeedback = checkTransformFeedbackAllocation(transformFeedbackHandle); mState.setTransformFeedbackBinding(this, transformFeedback); - mStateCache.onActiveTransformFeedbackChange(this); + onActiveTransformFeedbackChange(); } void Context::bindProgramPipeline(ProgramPipelineID pipelineHandle) @@ -1635,6 +1728,14 @@ void Context::getQueryiv(QueryType target, GLenum pname, GLint *params) case GL_QUERY_COUNTER_BITS_EXT: switch (target) { + case QueryType::AnySamples: + case QueryType::AnySamplesConservative: + params[0] = 1; + break; + case QueryType::PrimitivesGenerated: + case QueryType::TransformFeedbackPrimitivesWritten: + params[0] = 32; + break; case QueryType::TimeElapsed: params[0] = getCaps().queryCounterBitsTimeElapsed; break; @@ -1796,6 +1897,11 @@ void Context::getBooleanvImpl(GLenum pname, GLboolean *params) const case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = ConvertToGLBoolean(mState.hasRobustAccess()); break; + case GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT: + *params = + mState.getCaps() + .fragmentShadingRateProperties.fragmentShadingRateNonTrivialCombinersSupport; + break; default: mState.getBooleanv(pname, params); @@ -1953,10 +2059,10 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const *params = mState.getCaps().maxProgramTexelOffset; break; case GL_MAJOR_VERSION: - *params = getClientVersion().major; + *params = getClientVersion().getMajor(); break; case GL_MINOR_VERSION: - *params = getClientVersion().minor; + *params = getClientVersion().getMinor(); break; case GL_MAX_ELEMENTS_INDICES: *params = mState.getCaps().maxElementsIndices; @@ -2051,7 +2157,7 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const *params = mState.getCaps().maxLabelLength; break; - // GL_OVR_multiview2 + // GL_OVR_multiview case GL_MAX_VIEWS_OVR: *params = mState.getCaps().maxViews; break; @@ -2326,7 +2432,7 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const // case GL_MAX_CLIP_DISTANCES_EXT: Conflict enum value case GL_MAX_CLIP_PLANES: - if (getClientVersion().major >= 2) + if (getClientVersion() >= ES_2_0) { // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance *params = mState.getCaps().maxClipDistances; @@ -2397,9 +2503,6 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const case GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE: *params = mState.getCaps().maxPixelLocalStoragePlanes; break; - case GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE: - *params = mState.getCaps().maxColorAttachmentsWithActivePixelLocalStorage; - break; case GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE: *params = mState.getCaps().maxCombinedDrawBuffersAndPixelLocalStoragePlanes; break; @@ -2408,6 +2511,10 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const *params = mState.getCaps().queryCounterBitsTimestamp; break; + case GL_SHADING_RATE_EXT: + *params = ToGLenum(mState.getShadingRateEXT()); + break; + default: ANGLE_CONTEXT_TRY(mState.getIntegerv(this, pname, params)); break; @@ -2929,6 +3036,12 @@ void Context::drawRangeElementsBaseVertex(PrimitiveMode mode, void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect) { + if (noopDrawProgram()) + { + ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent()); + return; + } + ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect)); MarkShaderStorageUsage(this); @@ -2936,6 +3049,12 @@ void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect) void Context::drawElementsIndirect(PrimitiveMode mode, DrawElementsType type, const void *indirect) { + if (noopDrawProgram()) + { + ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent()); + return; + } + ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect)); MarkShaderStorageUsage(this); @@ -2953,30 +3072,46 @@ void Context::finish() void Context::insertEventMarker(GLsizei length, const char *marker) { - ASSERT(mImplementation); - ANGLE_CONTEXT_TRY(mImplementation->insertEventMarker(length, marker)); + if (length < 0 || marker == nullptr) + { + return; // no-op, not an error + } + + // If is 0 then is assumed to be null-terminated. + ANGLE_CONTEXT_TRY(mImplementation->insertEventMarker(GetMarkerLength(length, marker), marker)); } void Context::pushGroupMarker(GLsizei length, const char *marker) { - ASSERT(mImplementation); + ASSERT(mState.getGroupMarkerCount() < getCaps().maxDebugGroupStackDepth); + if (length < 0) + { + return; // no-op, not an error + } if (marker == nullptr) { - // From the EXT_debug_marker spec, - // "If is null then an empty string is pushed on the stack." - ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(length, "")); + // If is null then an empty string is pushed on the stack. + ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(0, "")); } else { - ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(length, marker)); + // If is 0 then is assumed to be null-terminated. + ANGLE_CONTEXT_TRY( + mImplementation->pushGroupMarker(GetMarkerLength(length, marker), marker)); } + mState.incrementGroupMarkers(); } void Context::popGroupMarker() { - ASSERT(mImplementation); + // According to the spec, if there is no group marker to pop, the pop command should be ignored. + if (mState.getGroupMarkerCount() == 0) + { + return; + } ANGLE_CONTEXT_TRY(mImplementation->popGroupMarker()); + mState.decrementGroupMarkers(); } void Context::bindUniformLocation(ShaderProgramID program, @@ -3021,12 +3156,12 @@ void Context::getProgramResourceiv(ShaderProgramID program, GLuint index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *params) { const Program *programObject = getProgramResolveLink(program); - QueryProgramResourceiv(programObject, programInterface, {index}, propCount, props, bufSize, + QueryProgramResourceiv(programObject, programInterface, {index}, propCount, props, count, length, params); } @@ -3096,18 +3231,20 @@ EGLenum Context::getRenderBuffer() const return backAttachment->getSurface()->getRenderBuffer(); } +// This function should only be called by the thread where the context is current (i.e., it's not +// thread safe). VertexArray *Context::checkVertexArrayAllocation(VertexArrayID vertexArrayHandle) { // Only called after a prior call to Gen. - VertexArray *vertexArray = getVertexArray(vertexArrayHandle); + VertexArray *vertexArray = getPrivateState().getVertexArray(vertexArrayHandle); if (!vertexArray) { vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle, mState.getCaps().maxVertexAttributes, mState.getCaps().maxVertexAttribBindings); - vertexArray->setBufferAccessValidationEnabled(mBufferAccessValidationEnabled); + vertexArray->setRobustBufferAccessEnabled(mRequiresRobustBehavior); - mVertexArrayMap.assign(vertexArrayHandle, vertexArray); + getMutablePrivateState()->setVertexArray(vertexArrayHandle, vertexArray); } return vertexArray; @@ -3129,18 +3266,18 @@ TransformFeedback *Context::checkTransformFeedbackAllocation( return transformFeedback; } -bool Context::isVertexArrayGenerated(VertexArrayID vertexArray) const -{ - ASSERT(mVertexArrayMap.contains({0})); - return mVertexArrayMap.contains(vertexArray); -} - bool Context::isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const { ASSERT(mTransformFeedbackMap.contains({0})); return mTransformFeedbackMap.contains(transformFeedback); } +bool Context::isZeroTextureBound(TextureType textureType) const +{ + Texture *texture = mState.getTargetTexture(textureType); + return mZeroTextures[textureType].get() == texture; +} + void Context::detachTexture(TextureID texture) { // The State cannot unbind image observers itself, they are owned by the Context @@ -3227,7 +3364,7 @@ void Context::detachTransformFeedback(TransformFeedbackID transformFeedback) if (mState.removeTransformFeedbackBinding(this, transformFeedback)) { bindTransformFeedback(GL_TRANSFORM_FEEDBACK, {0}); - mStateCache.onActiveTransformFeedbackChange(this); + onActiveTransformFeedbackChange(); } } @@ -3241,12 +3378,6 @@ void Context::detachProgramPipeline(ProgramPipelineID pipeline) mState.detachProgramPipeline(this, pipeline); } -void Context::vertexAttribDivisor(GLuint index, GLuint divisor) -{ - mState.setVertexAttribDivisor(this, index, divisor); - mStateCache.onVertexArrayStateChange(this); -} - void Context::samplerParameteri(SamplerID sampler, GLenum pname, GLint param) { Sampler *const samplerObject = @@ -3470,7 +3601,7 @@ void Context::initVersionStrings() else { versionString << "OpenGL ES "; - versionString << clientVersion.major << "." << clientVersion.minor << ".0 (ANGLE " + versionString << clientVersion.getMajor() << "." << clientVersion.getMinor() << " (ANGLE " << angle::GetANGLEVersionString() << ")"; } @@ -3478,8 +3609,8 @@ void Context::initVersionStrings() std::ostringstream shadingLanguageVersionString; shadingLanguageVersionString << "OpenGL ES GLSL ES "; - shadingLanguageVersionString << (clientVersion.major == 2 ? 1 : clientVersion.major) << "." - << clientVersion.minor << "0 (ANGLE " + shadingLanguageVersionString << (clientVersion.getMajor() == 2 ? 1 : clientVersion.getMajor()) + << "." << clientVersion.getMinor() << "0 (ANGLE " << angle::GetANGLEVersionString() << ")"; mShadingLanguageString = MakeStaticString(shadingLanguageVersionString.str()); } @@ -3656,8 +3787,7 @@ void Context::setExtensionEnabled(const char *name, bool enabled) }; enableIfRequestable("GL_OES_draw_buffers_indexed"); enableIfRequestable("GL_EXT_draw_buffers_indexed"); - enableIfRequestable("GL_EXT_color_buffer_float"); - enableIfRequestable("GL_EXT_color_buffer_half_float"); + enableIfRequestable("GL_EXT_shader_framebuffer_fetch_non_coherent"); enableIfRequestable("GL_ANGLE_shader_pixel_local_storage_coherent"); enableIfRequestable("GL_ANGLE_shader_pixel_local_storage"); } @@ -3701,7 +3831,7 @@ void Context::beginTransformFeedback(PrimitiveMode primitiveMode) // TODO: http://anglebug.com/42265705: Handle PPOs ANGLE_CONTEXT_TRY(transformFeedback->begin(this, primitiveMode, mState.getProgram())); - mStateCache.onActiveTransformFeedbackChange(this); + onActiveTransformFeedbackChange(); } bool Context::hasActiveTransformFeedback(ShaderProgramID program) const @@ -3744,10 +3874,12 @@ Extensions Context::generateSupportedExtensions() const supportedExtensions.multiviewOVR = false; supportedExtensions.multiview2OVR = false; supportedExtensions.multiviewMultisampleANGLE = false; + supportedExtensions.multiviewMultisampledRenderToTextureOVR = false; supportedExtensions.copyTexture3dANGLE = false; supportedExtensions.textureMultisampleANGLE = false; supportedExtensions.textureQueryLodEXT = false; supportedExtensions.textureShadowLodEXT = false; + supportedExtensions.textureStorageCompressionEXT = false; supportedExtensions.textureStencil8OES = false; supportedExtensions.conservativeDepthEXT = false; supportedExtensions.drawBuffersIndexedEXT = false; @@ -3831,7 +3963,9 @@ Extensions Context::generateSupportedExtensions() const supportedExtensions.geometryShaderOES = false; supportedExtensions.gpuShader5EXT = false; supportedExtensions.gpuShader5OES = false; + supportedExtensions.multiDrawIndirectEXT = false; supportedExtensions.primitiveBoundingBoxEXT = false; + supportedExtensions.primitiveBoundingBoxOES = false; supportedExtensions.shaderImageAtomicOES = false; supportedExtensions.shaderIoBlocksEXT = false; supportedExtensions.shaderIoBlocksOES = false; @@ -3873,12 +4007,6 @@ Extensions Context::generateSupportedExtensions() const supportedExtensions.renderabilityValidationANGLE = true; } - if (getFrontendFeatures().disableDrawBuffersIndexed.enabled) - { - supportedExtensions.drawBuffersIndexedEXT = false; - supportedExtensions.drawBuffersIndexedOES = false; - } - if (getFrontendFeatures().disableAnisotropicFiltering.enabled) { supportedExtensions.textureFilterAnisotropicEXT = false; @@ -3915,12 +4043,6 @@ Extensions Context::generateSupportedExtensions() const supportedExtensions.baseVertexBaseInstanceANGLE = false; } - if (limitations.baseInstanceEmulated && - !frontendFeatures.alwaysEnableEmulatedMultidrawExtensions.enabled && !mWebGLContext) - { - supportedExtensions.baseInstanceEXT = false; - } - // Enable the no error extension if the context was created with the flag. supportedExtensions.noErrorKHR = skipValidation(); @@ -3981,6 +4103,17 @@ Extensions Context::generateSupportedExtensions() const ASSERT(supportedExtensions.textureCompressionAstcHdrKHR); } + if (supportedExtensions.textureCompressionAstcDecodeModeEXT || + supportedExtensions.textureCompressionAstcDecodeModeRgb9e5EXT) + { + // GL_KHR_texture_compression_astc_hdr, + // GL_KHR_texture_compression_astc_ldr, + // or GL_OES_texture_compression_astc is required. + ASSERT(supportedExtensions.textureCompressionAstcOES || + supportedExtensions.textureCompressionAstcLdrKHR || + supportedExtensions.textureCompressionAstcHdrKHR); + } + // GL_KHR_protected_textures // If EGL_KHR_protected_content is not supported then GL_EXT_protected_texture // can not be supported. @@ -4005,6 +4138,24 @@ Extensions Context::generateSupportedExtensions() const // Blob cache extension is provided by the ANGLE frontend supportedExtensions.blobCacheANGLE = true; + // Disable extensions that are implemented through shader compiler transformations or require + // shader translator reflection data + if (mState.usesPassthroughShaders()) + { + supportedExtensions.multiDrawANGLE = false; + supportedExtensions.shaderPixelLocalStorageANGLE = false; + supportedExtensions.shaderPixelLocalStorageCoherentANGLE = false; + supportedExtensions.blendFuncExtendedEXT = false; + if (frontendFeatures.clipCullDistanceBrokenWithPassthroughShaders.enabled) + { + supportedExtensions.clipCullDistanceEXT = false; + } + if (frontendFeatures.noperspectiveInterpolationBrokenWithPassthroughShaders.enabled) + { + supportedExtensions.shaderNoperspectiveInterpolationNV = false; + } + } + return supportedExtensions; } @@ -4254,9 +4405,9 @@ void Context::initCaps() extensions->textureCompressionAstcLdrKHR = false; } #if !defined(ANGLE_HAS_ASTCENC) - // Don't expose emulated ASTC when it's not built. - mSupportedExtensions.textureCompressionAstcLdrKHR = false; - extensions->textureCompressionAstcLdrKHR = false; + // ASTC shouldn't be exposed if decoder is not built. + ASSERT(!mSupportedExtensions.textureCompressionAstcLdrKHR); + ASSERT(!extensions->textureCompressionAstcLdrKHR); #endif } @@ -4327,8 +4478,8 @@ void Context::initCaps() "supported on some native drivers"; extensions->textureMirrorClampToEdgeEXT = false; - // NVIDIA's Vulkan driver only supports 4 draw buffers - constexpr GLint maxDrawBuffers = 4; + // Modern content is starting to require 6 + constexpr GLint maxDrawBuffers = 6; INFO() << "Limiting draw buffer count to " << maxDrawBuffers; ANGLE_LIMIT_CAP(caps->maxDrawBuffers, maxDrawBuffers); @@ -4347,6 +4498,18 @@ void Context::initCaps() "mobile"; extensions->depth32OES = false; + // https://issuetracker.google.com/445241477 + INFO() << "Disabling GL_EXT_texture_norm16 during capture, which is not widely supported"; + extensions->textureNorm16EXT = false; + + // The corresponding Vulkan extension is presently limited to ARM and Qualcomm + INFO() + << "Disabling GL_EXT_texture_compression_astc_decode_mode and " + "GL_EXT_texture_compression_astc_decode_mode_rgb9e5 during capture, which are not " + "yet widely supported"; + extensions->textureCompressionAstcDecodeModeEXT = false; + extensions->textureCompressionAstcDecodeModeRgb9e5EXT = false; + // Pixel 4 (Qualcomm) only supports 6 atomic counter buffer bindings. constexpr GLint maxAtomicCounterBufferBindings = 6; INFO() << "Limiting max atomic counter buffer bindings to " @@ -4379,11 +4542,6 @@ void Context::initCaps() INFO() << "Limiting GL_MAX_SAMPLES to " << maxSamples; ANGLE_LIMIT_CAP(caps->maxSamples, maxSamples); - // Pixel 4/5 only supports GL_MAX_VERTEX_UNIFORM_VECTORS of 256 - constexpr GLint maxVertexUniformVectors = 256; - INFO() << "Limiting GL_MAX_VERTEX_UNIFORM_VECTORS to " << maxVertexUniformVectors; - ANGLE_LIMIT_CAP(caps->maxVertexUniformVectors, maxVertexUniformVectors); - // Test if we require shadow memory for coherent buffer tracking getShareGroup()->getFrameCaptureShared()->determineMemoryProtectionSupport(this); } @@ -4411,7 +4569,6 @@ void Context::initCaps() caps->maxShaderImageUniforms[ShaderType::Fragment]; ANGLE_LIMIT_CAP(caps->maxPixelLocalStoragePlanes, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); - caps->maxColorAttachmentsWithActivePixelLocalStorage = caps->maxColorAttachments; caps->maxCombinedDrawBuffersAndPixelLocalStoragePlanes = std::min(caps->maxPixelLocalStoragePlanes + std::min(caps->maxDrawBuffers, caps->maxColorAttachments), @@ -4419,23 +4576,13 @@ void Context::initCaps() break; case ShPixelLocalStorageType::FramebufferFetch: + // When pixel local storage is implemented as framebuffer attachments, we need + // draw_buffers_indexed in order to control the blend & color mask state + // on the PLS planes independently. + ASSERT(mSupportedExtensions.drawBuffersIndexedAny()); caps->maxPixelLocalStoragePlanes = maxDrawableAttachments; ANGLE_LIMIT_CAP(caps->maxPixelLocalStoragePlanes, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); - if (!mSupportedExtensions.drawBuffersIndexedAny()) - { - // When pixel local storage is implemented as framebuffer attachments, we need - // to disable color masks and blending to its attachments. If the backend - // context doesn't have indexed blend and color mask support, then we will have - // have to disable them globally. This also means the application can't have its - // own draw buffers while PLS is active. - caps->maxColorAttachmentsWithActivePixelLocalStorage = 0; - } - else - { - caps->maxColorAttachmentsWithActivePixelLocalStorage = - maxDrawableAttachments - 1; - } caps->maxCombinedDrawBuffersAndPixelLocalStoragePlanes = maxDrawableAttachments; break; @@ -4498,7 +4645,7 @@ void Context::updateCaps() { // We may have limited the max samples for some required renderbuffer formats due to // non-conformant formats. In this case MAX_SAMPLES needs to be lowered accordingly. - GLuint formatMaxSamples = formatCaps.getMaxSamples(); + GLuint formatMaxSamples = formatCaps.sampleCounts.getMaxSamples(); // GLES 3.0.5 section 4.4.2.2: "Implementations must support creation of renderbuffers // in these required formats with up to the value of MAX_SAMPLES multisamples, with the @@ -4593,6 +4740,7 @@ void Context::updateCaps() mDrawDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); mDrawDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES_INIT); mDrawDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT); + mClearDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); mBlitDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); mBlitDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS); mComputeDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES_INIT); @@ -4600,28 +4748,26 @@ void Context::updateCaps() mReadPixelsDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS); mCopyImageDirtyBits.set(state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING); mCopyImageDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS); + mTilingDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); } - // We need to validate buffer bounds if we are in a WebGL or robust access context and the - // back-end does not support robust buffer access behaviour. - mBufferAccessValidationEnabled = (!mSupportedExtensions.robustBufferAccessBehaviorKHR && - (mState.isWebGL() || mState.hasRobustAccess())); + // If we are in a WebGL or robust access context and the back-end does not support robust buffer + // access behaviour, we need to validate the buffer bounds manually. + mRequiresRobustBehavior = mState.isWebGL() || mState.hasRobustAccess(); + mBufferAccessValidationEnabled = + !mSupportedExtensions.robustBufferAccessBehaviorKHR && mRequiresRobustBehavior; // Cache this in the VertexArrays. They need to check it in state change notifications. // Note: vertex array objects are private to context and so the map doesn't need locking - for (auto vaoIter : UnsafeResourceMapIter(mVertexArrayMap)) + for (auto vaoIter : UnsafeResourceMapIter(getPrivateState().getVertexArrayMap())) { VertexArray *vao = vaoIter.second; - vao->setBufferAccessValidationEnabled(mBufferAccessValidationEnabled); + vao->setRobustBufferAccessEnabled(mRequiresRobustBehavior); } // Reinitialize state cache after extension changes. mStateCache.initialize(this); -} - -bool Context::noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei instanceCount) const -{ - return (instanceCount == 0) || noopDraw(mode, count); + mPrivateStateCache.initialize(this); } angle::Result Context::prepareForClear(GLbitfield mask) @@ -4676,7 +4822,7 @@ angle::Result Context::prepareForInvalidate(GLenum target) { effectiveTarget = GL_DRAW_FRAMEBUFFER; } - ANGLE_TRY(mState.syncDirtyObject(this, effectiveTarget)); + ANGLE_TRY(mState.syncDirtyObject(this, effectiveTarget, Command::Invalidate)); const state::DirtyBits dirtyBits = effectiveTarget == GL_READ_FRAMEBUFFER ? kReadInvalidateDirtyBits : kDrawInvalidateDirtyBits; @@ -4782,6 +4928,10 @@ void Context::clear(GLbitfield mask) return; } + // If we have active PLS using framebuffer fetch, disable those draw buffers so we don't clear + // the pixel local store. + ScopedPLSFramebufferFetchDrawBuffersDisable scopedPLSFramebufferFetchDrawBuffersDisable(this); + // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If // color/depth/stencil masks make the clear ineffective we skip it altogether. @@ -4862,8 +5012,11 @@ void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *valu Framebuffer *framebufferObject = mState.getDrawFramebuffer(); const FramebufferAttachment *attachment = nullptr; + GLfloat clampedDepth; if (buffer == GL_DEPTH) { + clampedDepth = clamp01(values[0]); + values = &clampedDepth; attachment = framebufferObject->getDepthAttachment(); } else if (buffer == GL_COLOR && @@ -4951,7 +5104,8 @@ void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLin } ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer)); - ANGLE_CONTEXT_TRY(framebufferObject->clearBufferfi(this, buffer, drawbuffer, depth, stencil)); + ANGLE_CONTEXT_TRY( + framebufferObject->clearBufferfi(this, buffer, drawbuffer, clamp01(depth), stencil)); } void Context::readPixels(GLint x, @@ -5017,6 +5171,11 @@ void Context::copyTexImage2D(TextureTarget target, GLsizei height, GLint border) { + if (ANGLE_UNLIKELY(width == 0 || height == 0)) + { + return; + } + ANGLE_CONTEXT_TRY(prepareForCopyImage()); Rectangle sourceArea(x, y, width, height); @@ -5036,7 +5195,7 @@ void Context::copyTexSubImage2D(TextureTarget target, GLsizei width, GLsizei height) { - if (width == 0 || height == 0) + if (ANGLE_UNLIKELY(width == 0 || height == 0)) { return; } @@ -5063,7 +5222,7 @@ void Context::copyTexSubImage3D(TextureTarget target, GLsizei width, GLsizei height) { - if (width == 0 || height == 0) + if (ANGLE_UNLIKELY(width == 0 || height == 0)) { return; } @@ -5120,7 +5279,8 @@ void Context::copyImageSubData(GLuint srcName, { // Destination target is a Texture ASSERT(dstTarget == GL_TEXTURE_2D || dstTarget == GL_TEXTURE_2D_ARRAY || - dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP); + dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP || + dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY); Texture *writeTexture = getTexture(PackParam(dstName)); ANGLE_CONTEXT_TRY(syncTextureForCopy(writeTexture)); @@ -5136,7 +5296,8 @@ void Context::copyImageSubData(GLuint srcName, // Source target is a Texture ASSERT(srcTarget == GL_TEXTURE_2D || srcTarget == GL_TEXTURE_2D_ARRAY || srcTarget == GL_TEXTURE_3D || srcTarget == GL_TEXTURE_CUBE_MAP || - srcTarget == GL_TEXTURE_EXTERNAL_OES || srcTarget == GL_TEXTURE_2D_MULTISAMPLE || + srcTarget == GL_TEXTURE_CUBE_MAP_ARRAY || srcTarget == GL_TEXTURE_EXTERNAL_OES || + srcTarget == GL_TEXTURE_2D_MULTISAMPLE || srcTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES); Texture *readTexture = getTexture(PackParam(srcName)); @@ -5157,7 +5318,8 @@ void Context::copyImageSubData(GLuint srcName, // Destination target is a Texture ASSERT(dstTarget == GL_TEXTURE_2D || dstTarget == GL_TEXTURE_2D_ARRAY || dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP || - dstTarget == GL_TEXTURE_EXTERNAL_OES || dstTarget == GL_TEXTURE_2D_MULTISAMPLE || + dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY || dstTarget == GL_TEXTURE_EXTERNAL_OES || + dstTarget == GL_TEXTURE_2D_MULTISAMPLE || dstTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES); Texture *writeTexture = getTexture(PackParam(dstName)); @@ -5180,12 +5342,6 @@ void Context::framebufferTexture2D(GLenum target, Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } - if (texture.value != 0) { Texture *textureObj = getTexture(texture); @@ -5210,12 +5366,6 @@ void Context::framebufferTexture3D(GLenum target, Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } - if (texture.value != 0) { Texture *textureObj = getTexture(texture); @@ -5238,12 +5388,6 @@ void Context::framebufferRenderbuffer(GLenum target, Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } - if (renderbuffer.value != 0) { Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer); @@ -5269,12 +5413,6 @@ void Context::framebufferTextureLayer(GLenum target, Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } - if (texture.value != 0) { Texture *textureObject = getTexture(texture); @@ -5299,12 +5437,6 @@ void Context::framebufferTextureMultiview(GLenum target, Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } - if (texture.value != 0) { Texture *textureObj = getTexture(texture); @@ -5331,16 +5463,39 @@ void Context::framebufferTextureMultiview(GLenum target, mState.setObjectDirty(target); } -void Context::framebufferTexture(GLenum target, GLenum attachment, TextureID texture, GLint level) +void Context::framebufferTextureMultisampleMultiview(GLenum target, + GLenum attachment, + TextureID texturePacked, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews) { Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) + if (texturePacked.value != 0) { - endPixelLocalStorageImplicit(); + Texture *textureObj = getTexture(texturePacked); + + ImageIndex index; + ASSERT(textureObj->getType() == TextureType::_2DArray); + index = ImageIndex::Make2DArrayRange(level, baseViewIndex, numViews); + framebuffer->setAttachmentMultisampleMultiview( + this, GL_TEXTURE, attachment, index, textureObj, samples, numViews, baseViewIndex); + textureObj->onBindToMSRTTFramebuffer(); + } + else + { + framebuffer->resetAttachment(this, attachment); } + mState.setObjectDirty(target); +} + +void Context::framebufferTexture(GLenum target, GLenum attachment, TextureID texture, GLint level) +{ + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); if (texture.value != 0) { @@ -5362,10 +5517,6 @@ void Context::drawBuffers(GLsizei n, const GLenum *bufs) { Framebuffer *framebuffer = mState.getDrawFramebuffer(); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0) - { - endPixelLocalStorageImplicit(); - } framebuffer->setDrawBuffers(n, bufs); mState.setDrawFramebufferDirty(); mStateCache.onDrawFramebufferChange(this); @@ -5918,16 +6069,7 @@ void *Context::mapBufferRange(BufferBinding target, return nullptr; } - // TODO: (anglebug.com/42266294): Modify return value in entry point layer - angle::FrameCaptureShared *frameCaptureShared = getShareGroup()->getFrameCaptureShared(); - if (frameCaptureShared->enabled()) - { - return frameCaptureShared->maybeGetShadowMemoryPointer(buffer, length, access); - } - else - { - return buffer->getMapPointer(); - } + return buffer->getMapPointer(); } void Context::flushMappedBufferRange(BufferBinding /*target*/, @@ -6003,71 +6145,19 @@ void Context::blendBarrier() mImplementation->blendBarrier(); } -void Context::disableVertexAttribArray(GLuint index) -{ - mState.setEnableVertexAttribArray(index, false); - mStateCache.onVertexArrayStateChange(this); -} - -void Context::enableVertexAttribArray(GLuint index) -{ - mState.setEnableVertexAttribArray(index, true); - mStateCache.onVertexArrayStateChange(this); -} - -void Context::vertexAttribPointer(GLuint index, - GLint size, - VertexAttribType type, - GLboolean normalized, - GLsizei stride, - const void *ptr) -{ - mState.setVertexAttribPointer(this, index, mState.getTargetBuffer(BufferBinding::Array), size, - type, ConvertToBool(normalized), stride, ptr); - mStateCache.onVertexArrayStateChange(this); -} - -void Context::vertexAttribFormat(GLuint attribIndex, - GLint size, - VertexAttribType type, - GLboolean normalized, - GLuint relativeOffset) -{ - mState.setVertexAttribFormat(attribIndex, size, type, ConvertToBool(normalized), false, - relativeOffset); - mStateCache.onVertexArrayFormatChange(this); -} - -void Context::vertexAttribIFormat(GLuint attribIndex, - GLint size, - VertexAttribType type, - GLuint relativeOffset) -{ - mState.setVertexAttribFormat(attribIndex, size, type, false, true, relativeOffset); - mStateCache.onVertexArrayFormatChange(this); -} - -void Context::vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) -{ - mState.setVertexAttribBinding(this, attribIndex, bindingIndex); - mStateCache.onVertexArrayStateChange(this); -} - -void Context::vertexBindingDivisor(GLuint bindingIndex, GLuint divisor) -{ - mState.setVertexBindingDivisor(this, bindingIndex, divisor); - mStateCache.onVertexArrayFormatChange(this); -} - void Context::vertexAttribIPointer(GLuint index, GLint size, VertexAttribType type, GLsizei stride, const void *pointer) { + bool vertexAttribDirty = false; mState.setVertexAttribIPointer(this, index, mState.getTargetBuffer(BufferBinding::Array), size, - type, stride, pointer); - mStateCache.onVertexArrayStateChange(this); + type, stride, pointer, &vertexAttribDirty); + if (vertexAttribDirty) + { + mPrivateStateCache.onVertexArrayStateChange(); + } } void Context::getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) const @@ -6075,8 +6165,9 @@ void Context::getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) c const VertexAttribCurrentValueData ¤tValues = getState().getVertexAttribCurrentValue(index); const VertexArray *vao = getState().getVertexArray(); + size_t bindingIndex = vao->getBindingIndexFromAttribIndex(index); QueryVertexAttribiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index), - currentValues, pname, params); + vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params); } void Context::getVertexAttribiv(GLuint index, GLenum pname, GLint *params) @@ -6098,8 +6189,9 @@ void Context::getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) const VertexAttribCurrentValueData ¤tValues = getState().getVertexAttribCurrentValue(index); const VertexArray *vao = getState().getVertexArray(); + size_t bindingIndex = vao->getBindingIndexFromAttribIndex(index); QueryVertexAttribfv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index), - currentValues, pname, params); + vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params); } void Context::getVertexAttribfvRobust(GLuint index, @@ -6116,8 +6208,9 @@ void Context::getVertexAttribIiv(GLuint index, GLenum pname, GLint *params) const VertexAttribCurrentValueData ¤tValues = getState().getVertexAttribCurrentValue(index); const VertexArray *vao = getState().getVertexArray(); + size_t bindingIndex = vao->getBindingIndexFromAttribIndex(index); QueryVertexAttribIiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index), - currentValues, pname, params); + vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params); } void Context::getVertexAttribIivRobust(GLuint index, @@ -6134,8 +6227,9 @@ void Context::getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) const VertexAttribCurrentValueData ¤tValues = getState().getVertexAttribCurrentValue(index); const VertexArray *vao = getState().getVertexArray(); + size_t bindingIndex = vao->getBindingIndexFromAttribIndex(index); QueryVertexAttribIuiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index), - currentValues, pname, params); + vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params); } void Context::getVertexAttribIuivRobust(GLuint index, @@ -6181,9 +6275,16 @@ void Context::debugMessageInsert(GLenum source, GLsizei length, const GLchar *buf) { - std::string msg(buf, (length > 0) ? static_cast(length) : strlen(buf)); - mState.getDebug().insertMessage(source, type, id, severity, std::move(msg), gl::LOG_INFO, - angle::EntryPoint::GLDebugMessageInsert); + if (!mState.getDebug().isOutputEnabled()) + { + // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do + // not generate an error. + return; + } + + ASSERT(buf != nullptr); + const std::string msg(buf, (length < 0) ? strlen(buf) : static_cast(length)); + mState.getDebug().insertMessage(source, type, id, severity, std::move(msg), gl::LOG_INFO); } void Context::debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam) @@ -6206,7 +6307,8 @@ GLuint Context::getDebugMessageLog(GLuint count, void Context::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message) { - std::string msg(message, (length > 0) ? static_cast(length) : strlen(message)); + ASSERT(message != nullptr); + std::string msg(message, (length < 0) ? strlen(message) : static_cast(length)); ANGLE_CONTEXT_TRY(mImplementation->pushDebugGroup(this, source, id, msg)); mState.getDebug().pushGroup(source, id, std::move(msg)); } @@ -6244,13 +6346,57 @@ void Context::bufferStorageExternal(BufferBinding target, ANGLE_CONTEXT_TRY(buffer->bufferStorageExternal(this, target, size, clientBuffer, flags)); } -void Context::namedBufferStorageExternal(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags) +void Context::getFragmentShadingRates(GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates) { - UNIMPLEMENTED(); + // If is NULL then it is ignored. + if (count == nullptr) + { + return; + } + + uint32_t shadingRatesCounts = 0; + angle::ShadingRateMap SupportedFragmentShadingRateSampleCounts = + mImplementation->getSupportedFragmentShadingRateEXTSampleCounts(); + uint32_t supportedShadingRateCounts = SupportedFragmentShadingRateSampleCounts.size(); + + for (uint32_t i = 1; i < supportedShadingRateCounts; i++) + { + gl::ShadingRate shadingRate = static_cast(i); + ASSERT(shadingRate > gl::ShadingRate::Undefined && + shadingRate < gl::ShadingRate::InvalidEnum); + // Assert samples is a power of two. + ASSERT(samples >= 1 && (samples & (samples - 1)) == 0); + if ((SupportedFragmentShadingRateSampleCounts[shadingRate] & samples) == samples) + { + if (shadingRates == nullptr) + { + shadingRatesCounts++; + } + else + { + shadingRates[shadingRatesCounts++] = ToGLenum(shadingRate); + if (maxCount <= static_cast(shadingRatesCounts)) + { + break; + } + } + } + } + *count = shadingRatesCounts; +} + +void Context::framebufferShadingRate(GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight) +{ + return; } void Context::bufferData(BufferBinding target, GLsizeiptr size, const void *data, BufferUsage usage) @@ -6327,7 +6473,6 @@ void Context::bindBufferRange(BufferBinding target, if (target == BufferBinding::Uniform) { mUniformBufferObserverBindings[index].bind(object); - mState.onUniformBufferStateChange(index); mStateCache.onUniformBufferStateChange(this); } else if (target == BufferBinding::AtomicCounter) @@ -6342,10 +6487,10 @@ void Context::bindBufferRange(BufferBinding target, } else { - mStateCache.onBufferBindingChange(this); + mPrivateStateCache.onBufferBindingChange(); } - if (object) + if (object && isWebGL()) { object->onBind(this, target); } @@ -6424,7 +6569,7 @@ void Context::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val) { // According to spec 3.1 Table 20.49: Framebuffer Dependent Values, // the sample position should be queried by DRAW_FRAMEBUFFER. - ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_DRAW_FRAMEBUFFER)); + ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_DRAW_FRAMEBUFFER, Command::GetMultisample)); const Framebuffer *framebuffer = mState.getDrawFramebuffer(); switch (pname) @@ -6503,12 +6648,6 @@ void Context::framebufferTexture2DMultisample(GLenum target, Framebuffer *framebuffer = mState.getTargetFramebuffer(target); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } - if (texture.value != 0) { Texture *textureObj = getTexture(texture); @@ -6527,7 +6666,7 @@ void Context::framebufferTexture2DMultisample(GLenum target, void Context::getSynciv(SyncID syncPacked, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *values) { @@ -6536,7 +6675,7 @@ void Context::getSynciv(SyncID syncPacked, { syncObject = getSync(syncPacked); } - ANGLE_CONTEXT_TRY(QuerySynciv(this, syncObject, pname, bufSize, length, values)); + ANGLE_CONTEXT_TRY(QuerySynciv(this, syncObject, pname, count, length, values)); } void Context::getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params) @@ -6557,11 +6696,6 @@ void Context::getFramebufferParameterivRobust(GLenum target, void Context::framebufferParameteri(GLenum target, GLenum pname, GLint param) { Framebuffer *framebuffer = mState.getTargetFramebuffer(target); - if (mState.getPixelLocalStorageActivePlanes() != 0 && - framebuffer == mState.getDrawFramebuffer()) - { - endPixelLocalStorageImplicit(); - } SetFramebufferParameteri(this, framebuffer, pname, param); } @@ -6982,7 +7116,11 @@ void Context::genBuffers(GLsizei n, BufferID *buffers) { for (int i = 0; i < n; i++) { - buffers[i] = createBuffer(); + if (!createBuffer(&buffers[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenBuffers); + return; + } } } @@ -6990,7 +7128,11 @@ void Context::genFramebuffers(GLsizei n, FramebufferID *framebuffers) { for (int i = 0; i < n; i++) { - framebuffers[i] = createFramebuffer(); + if (!createFramebuffer(&framebuffers[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenFramebuffers); + return; + } } } @@ -6998,7 +7140,11 @@ void Context::genRenderbuffers(GLsizei n, RenderbufferID *renderbuffers) { for (int i = 0; i < n; i++) { - renderbuffers[i] = createRenderbuffer(); + if (!createRenderbuffer(&renderbuffers[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenRenderbuffers); + return; + } } } @@ -7006,7 +7152,11 @@ void Context::genTextures(GLsizei n, TextureID *textures) { for (int i = 0; i < n; i++) { - textures[i] = createTexture(); + if (!createTexture(&textures[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenTextures); + return; + } } } @@ -7048,6 +7198,11 @@ void Context::getAttachedShaders(ShaderProgramID program, GLint Context::getAttribLocation(ShaderProgramID program, const GLchar *name) { + if (ANGLE_UNLIKELY(nameStartsWithReservedPrefix(name))) + { + return -1; + } + Program *programObject = getProgramResolveLink(program); ASSERT(programObject); return programObject->getExecutable().getAttributeLocation(name); @@ -7142,7 +7297,8 @@ void Context::getProgramPipelineiv(ProgramPipelineID pipeline, GLenum pname, GLi ProgramPipeline *programPipeline = nullptr; if (!isContextLost()) { - programPipeline = getProgramPipeline(pipeline); + programPipeline = mState.mProgramPipelineManager->checkProgramPipelineAllocation( + mImplementation.get(), pipeline); } QueryProgramPipelineiv(this, programPipeline, pname, params); } @@ -7179,8 +7335,14 @@ void Context::getProgramPipelineInfoLog(ProgramPipelineID pipeline, } else { - *length = 0; - *infoLog = '\0'; + if (length) + { + *length = 0; + } + if (infoLog) + { + *infoLog = '\0'; + } } } @@ -7219,6 +7381,8 @@ void Context::getShaderPrecisionFormat(GLenum shadertype, GLint *range, GLint *precision) { + ASSERT(range != nullptr && precision != nullptr); + switch (shadertype) { case GL_VERTEX_SHADER: @@ -7329,6 +7493,11 @@ void Context::getUniformivRobust(ShaderProgramID program, GLint Context::getUniformLocation(ShaderProgramID program, const GLchar *name) { + if (ANGLE_UNLIKELY(nameStartsWithReservedPrefix(name))) + { + return -1; + } + Program *programObject = getProgramResolveLink(program); ASSERT(programObject); return programObject->getExecutable().getUniformLocation(name).value; @@ -7469,122 +7638,12 @@ Program *Context::getActiveLinkedProgramPPO() const return nullptr; } -void Context::uniform1f(UniformLocation location, GLfloat x) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform1fv(location, 1, &x); -} - -void Context::uniform1fv(UniformLocation location, GLsizei count, const GLfloat *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform1fv(location, count, v); -} - -void Context::setUniform1iImpl(Program *program, - UniformLocation location, - GLsizei count, - const GLint *v) -{ - program->getExecutable().setUniform1iv(this, location, count, v); -} - void Context::onSamplerUniformChange(size_t textureUnitIndex) { mState.onActiveTextureChange(this, textureUnitIndex); mStateCache.onActiveTextureChange(this); } -void Context::uniform1i(UniformLocation location, GLint x) -{ - Program *program = getActiveLinkedProgram(); - setUniform1iImpl(program, location, 1, &x); -} - -void Context::uniform1iv(UniformLocation location, GLsizei count, const GLint *v) -{ - Program *program = getActiveLinkedProgram(); - setUniform1iImpl(program, location, count, v); -} - -void Context::uniform2f(UniformLocation location, GLfloat x, GLfloat y) -{ - GLfloat xy[2] = {x, y}; - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform2fv(location, 1, xy); -} - -void Context::uniform2fv(UniformLocation location, GLsizei count, const GLfloat *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform2fv(location, count, v); -} - -void Context::uniform2i(UniformLocation location, GLint x, GLint y) -{ - GLint xy[2] = {x, y}; - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform2iv(location, 1, xy); -} - -void Context::uniform2iv(UniformLocation location, GLsizei count, const GLint *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform2iv(location, count, v); -} - -void Context::uniform3f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z) -{ - GLfloat xyz[3] = {x, y, z}; - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform3fv(location, 1, xyz); -} - -void Context::uniform3fv(UniformLocation location, GLsizei count, const GLfloat *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform3fv(location, count, v); -} - -void Context::uniform3i(UniformLocation location, GLint x, GLint y, GLint z) -{ - GLint xyz[3] = {x, y, z}; - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform3iv(location, 1, xyz); -} - -void Context::uniform3iv(UniformLocation location, GLsizei count, const GLint *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform3iv(location, count, v); -} - -void Context::uniform4f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - GLfloat xyzw[4] = {x, y, z, w}; - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform4fv(location, 1, xyzw); -} - -void Context::uniform4fv(UniformLocation location, GLsizei count, const GLfloat *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform4fv(location, count, v); -} - -void Context::uniform4i(UniformLocation location, GLint x, GLint y, GLint z, GLint w) -{ - GLint xyzw[4] = {x, y, z, w}; - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform4iv(location, 1, xyzw); -} - -void Context::uniform4iv(UniformLocation location, GLsizei count, const GLint *v) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform4iv(location, count, v); -} - void Context::uniformMatrix2fv(UniformLocation location, GLsizei count, GLboolean transpose, @@ -7631,14 +7690,6 @@ void Context::validateProgramPipeline(ProgramPipelineID pipeline) // pipeline is the program pipeline object name. The resulting program pipeline // object is a new state vector, comprising all the state and with the same initial values // listed in table 21.20. - // - // If we do not have a pipeline object that's been created with glBindProgramPipeline, we leave - // VALIDATE_STATUS at it's default false value without generating a pipeline object. - if (!getProgramPipeline(pipeline)) - { - return; - } - ProgramPipeline *programPipeline = mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(), pipeline); @@ -7670,63 +7721,16 @@ void Context::programBinary(ShaderProgramID program, ANGLE_CONTEXT_TRY(programObject->setBinary(this, binaryFormat, binary, length)); } -void Context::uniform1ui(UniformLocation location, GLuint v0) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform1uiv(location, 1, &v0); -} - -void Context::uniform2ui(UniformLocation location, GLuint v0, GLuint v1) -{ - Program *program = getActiveLinkedProgram(); - const GLuint xy[] = {v0, v1}; - program->getExecutable().setUniform2uiv(location, 1, xy); -} - -void Context::uniform3ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2) -{ - Program *program = getActiveLinkedProgram(); - const GLuint xyz[] = {v0, v1, v2}; - program->getExecutable().setUniform3uiv(location, 1, xyz); -} - -void Context::uniform4ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) -{ - Program *program = getActiveLinkedProgram(); - const GLuint xyzw[] = {v0, v1, v2, v3}; - program->getExecutable().setUniform4uiv(location, 1, xyzw); -} - -void Context::uniform1uiv(UniformLocation location, GLsizei count, const GLuint *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform1uiv(location, count, value); -} -void Context::uniform2uiv(UniformLocation location, GLsizei count, const GLuint *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform2uiv(location, count, value); -} - -void Context::uniform3uiv(UniformLocation location, GLsizei count, const GLuint *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform3uiv(location, count, value); -} - -void Context::uniform4uiv(UniformLocation location, GLsizei count, const GLuint *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniform4uiv(location, count, value); -} - void Context::genQueries(GLsizei n, QueryID *ids) { for (GLsizei i = 0; i < n; i++) { - QueryID handle = QueryID{mQueryHandleAllocator.allocate()}; - mQueryMap.assign(handle, nullptr); - ids[i] = handle; + if (!mQueryHandleAllocator.allocate(&ids[i].value)) + { + handleExhaustionError(angle::EntryPoint::GLGenQueries); + return; + } + mQueryMap.assign(ids[i], nullptr); } } @@ -7758,60 +7762,6 @@ GLboolean Context::isQuery(QueryID id) const return ConvertToGLBoolean(getQuery(id) != nullptr); } -void Context::uniformMatrix2x3fv(UniformLocation location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniformMatrix2x3fv(location, count, transpose, value); -} - -void Context::uniformMatrix3x2fv(UniformLocation location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniformMatrix3x2fv(location, count, transpose, value); -} - -void Context::uniformMatrix2x4fv(UniformLocation location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniformMatrix2x4fv(location, count, transpose, value); -} - -void Context::uniformMatrix4x2fv(UniformLocation location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniformMatrix4x2fv(location, count, transpose, value); -} - -void Context::uniformMatrix3x4fv(UniformLocation location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniformMatrix3x4fv(location, count, transpose, value); -} - -void Context::uniformMatrix4x3fv(UniformLocation location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{ - Program *program = getActiveLinkedProgram(); - program->getExecutable().setUniformMatrix4x3fv(location, count, transpose, value); -} - void Context::deleteVertexArrays(GLsizei n, const VertexArrayID *arrays) { for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) @@ -7821,46 +7771,21 @@ void Context::deleteVertexArrays(GLsizei n, const VertexArrayID *arrays) if (arrays[arrayIndex].value != 0) { VertexArray *vertexArrayObject = nullptr; - if (mVertexArrayMap.erase(vertexArray, &vertexArrayObject)) + getMutablePrivateState()->eraseVertexArray(vertexArray, &vertexArrayObject); + if (vertexArrayObject != nullptr) { - if (vertexArrayObject != nullptr) - { - detachVertexArray(vertexArray); - vertexArrayObject->onDestroy(this); - } - - mVertexArrayHandleAllocator.release(vertexArray.value); + detachVertexArray(vertexArray); + vertexArrayObject->onDestroy(this); } } } } -void Context::genVertexArrays(GLsizei n, VertexArrayID *arrays) -{ - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) - { - VertexArrayID vertexArray = {mVertexArrayHandleAllocator.allocate()}; - mVertexArrayMap.assign(vertexArray, nullptr); - arrays[arrayIndex] = vertexArray; - } -} - -GLboolean Context::isVertexArray(VertexArrayID array) const -{ - if (array.value == 0) - { - return GL_FALSE; - } - - VertexArray *vao = getVertexArray(array); - return ConvertToGLBoolean(vao != nullptr); -} - void Context::endTransformFeedback() { TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback(); ANGLE_CONTEXT_TRY(transformFeedback->end(this)); - mStateCache.onActiveTransformFeedbackChange(this); + onActiveTransformFeedbackChange(); } void Context::transformFeedbackVaryings(ShaderProgramID program, @@ -7915,9 +7840,25 @@ void Context::genTransformFeedbacks(GLsizei n, TransformFeedbackID *ids) { for (int i = 0; i < n; i++) { - TransformFeedbackID transformFeedback = {mTransformFeedbackHandleAllocator.allocate()}; - mTransformFeedbackMap.assign(transformFeedback, nullptr); - ids[i] = transformFeedback; + if (!mTransformFeedbackHandleAllocator.allocate(&ids[i].value)) + { + handleExhaustionError(angle::EntryPoint::GLGenTransformFeedbacks); + return; + } + mTransformFeedbackMap.assign(ids[i], nullptr); + } +} + +void Context::genVertexArrays(GLsizei n, VertexArrayID *ids) +{ + PrivateState *privState = getMutablePrivateState(); + for (int i = 0; i < n; i++) + { + if (!privState->allocateVertexID(&ids[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenVertexArrays); + return; + } } } @@ -7938,14 +7879,14 @@ void Context::pauseTransformFeedback() { TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback(); ANGLE_CONTEXT_TRY(transformFeedback->pause(this)); - mStateCache.onActiveTransformFeedbackChange(this); + onActiveTransformFeedbackChange(); } void Context::resumeTransformFeedback() { TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback(); ANGLE_CONTEXT_TRY(transformFeedback->resume(this)); - mStateCache.onActiveTransformFeedbackChange(this); + onActiveTransformFeedbackChange(); } void Context::getUniformuiv(ShaderProgramID program, UniformLocation location, GLuint *params) @@ -8052,7 +7993,13 @@ void Context::uniformBlockBinding(ShaderProgramID program, GLsync Context::fenceSync(GLenum condition, GLbitfield flags) { - SyncID syncHandle = mState.mSyncManager->createSync(mImplementation.get()); + SyncID syncHandle; + if (!mState.mSyncManager->createSync(mImplementation.get(), &syncHandle)) + { + handleExhaustionError(angle::EntryPoint::GLFenceSync); + return nullptr; + } + Sync *syncObject = getSync(syncHandle); if (syncObject->set(this, condition, flags) == angle::Result::Stop) { @@ -8126,7 +8073,11 @@ void Context::genSamplers(GLsizei count, SamplerID *samplers) { for (int i = 0; i < count; i++) { - samplers[i] = mState.mSamplerManager->createSampler(); + if (!mState.mSamplerManager->createSampler(&samplers[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenSamplers); + return; + } } } @@ -8148,7 +8099,7 @@ void Context::deleteSamplers(GLsizei count, const SamplerID *samplers) void Context::getInternalformativ(GLenum target, GLenum internalformat, GLenum pname, - GLsizei bufSize, + GLsizei count, GLint *params) { Texture *texture = nullptr; @@ -8158,7 +8109,7 @@ void Context::getInternalformativ(GLenum target, texture = getTextureByType(textype); } const TextureCaps &formatCaps = mState.getTextureCap(internalformat); - QueryInternalFormativ(this, texture, internalformat, formatCaps, pname, bufSize, params); + QueryInternalFormativ(this, texture, internalformat, formatCaps, pname, count, params); } void Context::getInternalformativRobust(GLenum target, @@ -8504,7 +8455,11 @@ void Context::genProgramPipelines(GLsizei count, ProgramPipelineID *pipelines) { for (int i = 0; i < count; i++) { - pipelines[i] = createProgramPipeline(); + if (!createProgramPipeline(&pipelines[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenProgramPipelines); + return; + } } } @@ -8720,7 +8675,11 @@ void Context::createMemoryObjects(GLsizei n, MemoryObjectID *memoryObjects) { for (int i = 0; i < n; i++) { - memoryObjects[i] = createMemoryObject(); + if (!createMemoryObject(&memoryObjects[i])) + { + handleExhaustionError(angle::EntryPoint::GLCreateMemoryObjectsEXT); + return; + } } } @@ -8883,7 +8842,11 @@ void Context::genSemaphores(GLsizei n, SemaphoreID *semaphores) { for (int i = 0; i < n; i++) { - semaphores[i] = createSemaphore(); + if (!createSemaphore(&semaphores[i])) + { + handleExhaustionError(angle::EntryPoint::GLGenSemaphoresEXT); + return; + } } } @@ -9015,11 +8978,6 @@ void Context::framebufferMemorylessPixelLocalStorage(GLint plane, GLenum interna Framebuffer *framebuffer = mState.getDrawFramebuffer(); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0) - { - endPixelLocalStorageImplicit(); - } - PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); if (internalformat == GL_NONE) @@ -9040,11 +8998,6 @@ void Context::framebufferTexturePixelLocalStorage(GLint plane, Framebuffer *framebuffer = mState.getDrawFramebuffer(); ASSERT(framebuffer); - if (mState.getPixelLocalStorageActivePlanes() != 0) - { - endPixelLocalStorageImplicit(); - } - PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); if (backingtexture.value == 0) @@ -9090,7 +9043,7 @@ void Context::beginPixelLocalStorage(GLsizei n, const GLenum loadops[]) PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); pls.begin(this, n, loadops); - mState.setPixelLocalStorageActivePlanes(n); + getMutablePrivateState()->setPixelLocalStorageActivePlanes(n); } void Context::endPixelLocalStorage(GLsizei n, const GLenum storeops[]) @@ -9100,7 +9053,7 @@ void Context::endPixelLocalStorage(GLsizei n, const GLenum storeops[]) PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); ASSERT(n == mState.getPixelLocalStorageActivePlanes()); - mState.setPixelLocalStorageActivePlanes(0); + getMutablePrivateState()->setPixelLocalStorageActivePlanes(0); pls.end(this, n, storeops); } @@ -9120,11 +9073,6 @@ bool Context::areBlobCacheFuncsSet() const void Context::pixelLocalStorageBarrier() { - if (getExtensions().shaderPixelLocalStorageCoherentANGLE) - { - return; - } - Framebuffer *framebuffer = mState.getDrawFramebuffer(); ASSERT(framebuffer); PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); @@ -9156,14 +9104,12 @@ void Context::framebufferPixelLocalStorageRestore() void Context::getFramebufferPixelLocalStorageParameterfv(GLint plane, GLenum pname, GLfloat *params) { - getFramebufferPixelLocalStorageParameterfvRobust( - plane, pname, std::numeric_limits::max(), nullptr, params); + QueryFramebufferPixelLocalStorageParameterfv(this, plane, pname, nullptr, params); } void Context::getFramebufferPixelLocalStorageParameteriv(GLint plane, GLenum pname, GLint *params) { - getFramebufferPixelLocalStorageParameterivRobust( - plane, pname, std::numeric_limits::max(), nullptr, params); + QueryFramebufferPixelLocalStorageParameteriv(this, plane, pname, nullptr, params); } void Context::getFramebufferPixelLocalStorageParameterfvRobust(GLint plane, @@ -9172,20 +9118,7 @@ void Context::getFramebufferPixelLocalStorageParameterfvRobust(GLint plane, GLsizei *length, GLfloat *params) { - Framebuffer *framebuffer = mState.getDrawFramebuffer(); - ASSERT(framebuffer); - PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); - - switch (pname) - { - case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: - if (length != nullptr) - { - *length = 4; - } - pls.getPlane(plane).getClearValuef(params); - break; - } + QueryFramebufferPixelLocalStorageParameterfv(this, plane, pname, length, params); } void Context::getFramebufferPixelLocalStorageParameterivRobust(GLint plane, @@ -9194,42 +9127,7 @@ void Context::getFramebufferPixelLocalStorageParameterivRobust(GLint plane, GLsizei *length, GLint *params) { - Framebuffer *framebuffer = mState.getDrawFramebuffer(); - ASSERT(framebuffer); - PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); - - switch (pname) - { - // GL_ANGLE_shader_pixel_local_storage. - case GL_PIXEL_LOCAL_FORMAT_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE: - if (length != nullptr) - { - *length = 1; - } - *params = pls.getPlane(plane).getIntegeri(pname); - break; - case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: - if (length != nullptr) - { - *length = 4; - } - pls.getPlane(plane).getClearValuei(params); - break; - case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: - { - if (length != nullptr) - { - *length = 4; - } - GLuint valueui[4]; - pls.getPlane(plane).getClearValueui(valueui); - memcpy(params, valueui, sizeof(valueui)); - break; - } - } + QueryFramebufferPixelLocalStorageParameteriv(this, plane, pname, length, params); } void Context::eGLImageTargetTexStorage(GLenum target, egl::ImageID image, const GLint *attrib_list) @@ -9240,11 +9138,6 @@ void Context::eGLImageTargetTexStorage(GLenum target, egl::ImageID image, const imageObject, attrib_list)); } -void Context::eGLImageTargetTextureStorage(GLuint texture, - egl::ImageID image, - const GLint *attrib_list) -{} - void Context::eGLImageTargetTexture2D(TextureType target, egl::ImageID image) { Texture *texture = getTextureByType(target); @@ -9264,11 +9157,6 @@ void Context::framebufferFetchBarrier() mImplementation->framebufferFetchBarrier(); } -void Context::texStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) -{ - UNIMPLEMENTED(); -} - bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const { return GetQueryParameterInfo(mState, pname, type, numParams); @@ -9333,7 +9221,7 @@ bool Context::usingDisplaySemaphoreShareGroup() const GLenum Context::getConvertedRenderbufferFormat(GLenum internalformat) const { - if (isWebGL() && mState.getClientMajorVersion() == 2 && internalformat == GL_DEPTH_STENCIL) + if (isWebGL1() && internalformat == GL_DEPTH_STENCIL) { return GL_DEPTH24_STENCIL8; } @@ -9449,12 +9337,12 @@ void Context::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess { case angle::SubjectMessage::ContentsChanged: mState.setObjectDirty(GL_VERTEX_ARRAY); - mStateCache.onVertexArrayBufferContentsChange(this); + mPrivateStateCache.onVertexArrayBufferContentsChange(); break; case angle::SubjectMessage::SubjectMapped: case angle::SubjectMessage::SubjectUnmapped: case angle::SubjectMessage::BindingChanged: - mStateCache.onVertexArrayBufferStateChange(this); + mPrivateStateCache.onVertexArrayBufferStateChange(); break; default: break; @@ -9565,7 +9453,7 @@ void Context::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess } else if (index < kUniformBufferMaxSubjectIndex) { - mState.onUniformBufferStateChange(index - kUniformBuffer0SubjectIndex); + mState.onUniformBufferStateChange(index - kUniformBuffer0SubjectIndex, message); mStateCache.onUniformBufferStateChange(this); } else if (index < kAtomicCounterBufferMaxSubjectIndex) @@ -9780,7 +9668,7 @@ void Context::genPerfMonitors(GLsizei n, GLuint *monitors) { for (GLsizei monitorIndex = 0; monitorIndex < n; ++monitorIndex) { - monitors[n] = static_cast(monitorIndex); + monitors[monitorIndex] = static_cast(monitorIndex); } } @@ -9791,7 +9679,6 @@ void Context::getPerfMonitorCounterData(GLuint monitor, GLint *bytesWritten) { using namespace angle; - const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters(); GLint byteCount = 0; switch (pname) { @@ -9803,8 +9690,10 @@ void Context::getPerfMonitorCounterData(GLuint monitor, } case GL_PERFMON_RESULT_SIZE_AMD: { + const PerfMonitorCounterGroupsInfo &perfMonitorGroups = + mImplementation->getPerfMonitorCountersInfo(); GLuint resultSize = 0; - for (const PerfMonitorCounterGroup &group : perfMonitorGroups) + for (const PerfMonitorCounterGroupInfo &group : perfMonitorGroups) { resultSize += sizeof(PerfMonitorTriplet) * group.counters.size(); } @@ -9814,6 +9703,8 @@ void Context::getPerfMonitorCounterData(GLuint monitor, } case GL_PERFMON_RESULT_AMD: { + const PerfMonitorCounterGroups &perfMonitorGroups = + mImplementation->getPerfMonitorCounters(); PerfMonitorTriplet *resultsOut = reinterpret_cast(data); GLsizei maxResults = dataSize / sizeof(PerfMonitorTriplet); GLsizei resultCount = 0; @@ -9848,9 +9739,10 @@ void Context::getPerfMonitorCounterData(GLuint monitor, void Context::getPerfMonitorCounterInfo(GLuint group, GLuint counter, GLenum pname, void *data) { using namespace angle; - const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters(); + const PerfMonitorCounterGroupsInfo &perfMonitorGroups = + mImplementation->getPerfMonitorCountersInfo(); ASSERT(group < perfMonitorGroups.size()); - const PerfMonitorCounters &counters = perfMonitorGroups[group].counters; + const PerfMonitorCountersInfo &counters = perfMonitorGroups[group].counters; ASSERT(counter < counters.size()); switch (pname) @@ -9880,9 +9772,10 @@ void Context::getPerfMonitorCounterString(GLuint group, GLchar *counterString) { using namespace angle; - const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters(); + const PerfMonitorCounterGroupsInfo &perfMonitorGroups = + mImplementation->getPerfMonitorCountersInfo(); ASSERT(group < perfMonitorGroups.size()); - const PerfMonitorCounters &counters = perfMonitorGroups[group].counters; + const PerfMonitorCountersInfo &counters = perfMonitorGroups[group].counters; ASSERT(counter < counters.size()); GetPerfMonitorString(counters[counter].name, bufSize, length, counterString); } @@ -9894,9 +9787,10 @@ void Context::getPerfMonitorCounters(GLuint group, GLuint *counters) { using namespace angle; - const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters(); + const PerfMonitorCounterGroupsInfo &perfMonitorGroups = + mImplementation->getPerfMonitorCountersInfo(); ASSERT(group < perfMonitorGroups.size()); - const PerfMonitorCounters &groupCounters = perfMonitorGroups[group].counters; + const PerfMonitorCountersInfo &groupCounters = perfMonitorGroups[group].counters; if (numCounters) { @@ -9924,7 +9818,8 @@ void Context::getPerfMonitorGroupString(GLuint group, GLchar *groupString) { using namespace angle; - const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters(); + const PerfMonitorCounterGroupsInfo &perfMonitorGroups = + mImplementation->getPerfMonitorCountersInfo(); ASSERT(group < perfMonitorGroups.size()); GetPerfMonitorString(perfMonitorGroups[group].name, bufSize, length, groupString); } @@ -9932,7 +9827,8 @@ void Context::getPerfMonitorGroupString(GLuint group, void Context::getPerfMonitorGroups(GLint *numGroups, GLsizei groupsSize, GLuint *groups) { using namespace angle; - const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters(); + const PerfMonitorCounterGroupsInfo &perfMonitorGroups = + mImplementation->getPerfMonitorCountersInfo(); if (numGroups) { @@ -9954,9 +9850,9 @@ void Context::selectPerfMonitorCounters(GLuint monitor, GLuint *counterList) {} -const angle::PerfMonitorCounterGroups &Context::getPerfMonitorCounterGroups() const +const angle::PerfMonitorCounterGroupsInfo &Context::getPerfMonitorCounterGroups() const { - return mImplementation->getPerfMonitorCounters(); + return mImplementation->getPerfMonitorCountersInfo(); } void Context::framebufferFoveationConfig(FramebufferID framebufferPacked, @@ -10018,7 +9914,7 @@ void Context::endTiling(GLbitfield preserveMask) void Context::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) { - ANGLE_CONTEXT_TRY(syncDirtyObjects(kTilingDirtyObjects, Command::Other)); + ANGLE_CONTEXT_TRY(syncDirtyObjects(mTilingDirtyObjects, Command::Other)); ANGLE_CONTEXT_TRY(syncDirtyBits(kTilingDirtyBits, kTilingExtendedDirtyBits, Command::Other)); ANGLE_CONTEXT_TRY( mImplementation->startTiling(this, Rectangle(x, y, width, height), preserveMask)); @@ -10124,6 +10020,74 @@ size_t Context::getMemoryUsage() const return memoryUsage; } +void Context::updateActiveAttribsMaskIfNeeded() const +{ + if (!mPrivateStateCache.isCachedActiveAttribMasksValid()) + { + mStateCache.updateActiveAttribsMask(this); + mPrivateStateCache.setCachedActiveAttribMasksValid(); + } +} + +AttributesMask Context::getActiveBufferedAttribsMask() const +{ + updateActiveAttribsMaskIfNeeded(); + return mStateCache.getActiveBufferedAttribsMask(mPrivateStateCache); +} + +AttributesMask Context::getActiveClientAttribsMask() const +{ + updateActiveAttribsMaskIfNeeded(); + return mStateCache.getActiveClientAttribsMask(mPrivateStateCache); +} + +AttributesMask Context::getActiveDefaultAttribsMask() const +{ + updateActiveAttribsMaskIfNeeded(); + return mStateCache.getActiveDefaultAttribsMask(mPrivateStateCache); +} + +bool Context::hasAnyEnabledClientAttrib() const +{ + updateActiveAttribsMaskIfNeeded(); + return mStateCache.hasAnyEnabledClientAttrib(mPrivateStateCache); +} + +bool Context::hasAnyActiveClientAttrib() const +{ + updateActiveAttribsMaskIfNeeded(); + return mStateCache.hasAnyActiveClientAttrib(mPrivateStateCache); +} + +GLint64 Context::getNonInstancedVertexElementLimit() const +{ + ASSERT(mBufferAccessValidationEnabled); + if (!mPrivateStateCache.isCachedVertexElementLimitValid()) + { + mStateCache.updateVertexElementLimits(this); + mPrivateStateCache.setCachedVertexElementLimitValid(); + } + return mStateCache.getNonInstancedVertexElementLimit(mPrivateStateCache); +} + +GLint64 Context::getInstancedVertexElementLimit() const +{ + ASSERT(mBufferAccessValidationEnabled); + if (!mPrivateStateCache.isCachedVertexElementLimitValid()) + { + mStateCache.updateVertexElementLimits(this); + mPrivateStateCache.setCachedVertexElementLimitValid(); + } + return mStateCache.getInstancedVertexElementLimit(mPrivateStateCache); +} + +void Context::onActiveTransformFeedbackChange() +{ + mStateCache.onActiveTransformFeedbackChange(this); + // This can only be called from current context since transform feedback are per context. + mPrivateStateCache.invalidateCachedBasicDrawElementsError(); +} + // ErrorSet implementation. ErrorSet::ErrorSet(Debug *debug, const angle::FrontendFeatures &frontendFeatures, @@ -10133,8 +10097,20 @@ ErrorSet::ErrorSet(Debug *debug, mLoseContextOnOutOfMemory(frontendFeatures.loseContextOnOutOfMemory.enabled), mContextLostForced(false), mResetStatus(GraphicsResetStatus::NoError), + mErrorMessageCount(0), + // Limit the error message spam to a small number when the context is not in debug mode, as + // some apps make invalid but harmless calls and the spam has a non-trivial cost. + // + // Note: mMaxErrorMessages is kept far from max to avoid overflowing mErrorMessageCount in + // case of multiple contexts simultaneously adding (context loss) errors, hence the division + // by 2. + mMaxErrorMessages( + GetDebug(frontendFeatures, attribs) ? std::numeric_limits::max() / 2 : 16), mSkipValidation(GetNoError(attribs)), mContextLost(0), +#if defined(ANGLE_ENABLE_ASSERTS) + mPushedErrors(0), +#endif mHasAnyErrors(0) {} @@ -10160,16 +10136,39 @@ void ErrorSet::handleError(GLenum errorCode, // Process the error, but log it with WARN severity so it shows up in logs. mDebug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, errorCode, - GL_DEBUG_SEVERITY_HIGH, std::move(formattedMessage), gl::LOG_WARN, - angle::EntryPoint::Invalid); + GL_DEBUG_SEVERITY_HIGH, std::move(formattedMessage), gl::LOG_WARN); pushError(errorCode); } void ErrorSet::validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message) { - mDebug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, errorCode, - GL_DEBUG_SEVERITY_HIGH, message, gl::LOG_INFO, entryPoint); + bool reportMessage = true; + bool isLastMessage = false; + +#if !defined(ANGLE_ENABLE_ASSERTS) && !defined(ANGLE_ALWAYS_REPORT_VALIDATION_ERRORS) + // In release mode, don't spam validation errors as they come with a performance cost, affecting + // applications that make lots of invalid but otherwise harmless calls. Instead, only report the + // first few messages. This can still be helpful to application developers who can fix the first + // few errors more easily and get more messages on the next run. + // + // The error messages are always reported for Chromium which uses the debug callback to detect + // errors instead of glGetError(). + reportMessage = + MessageCounterBelowMaxRepeat(&mErrorMessageCount, mMaxErrorMessages, &isLastMessage); +#endif + + if (reportMessage) + { + std::string completeMessage = std::string(GetEntryPointName(entryPoint)) + ": " + message; + if (isLastMessage) + { + completeMessage += " (No more validation messages will be reported)"; + } + + mDebug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, errorCode, + GL_DEBUG_SEVERITY_HIGH, completeMessage, gl::LOG_INFO); + } pushError(errorCode); } @@ -10213,6 +10212,9 @@ void ErrorSet::pushError(GLenum errorCode) { std::lock_guard lock(mMutex); mErrors.insert(errorCode); +#if defined(ANGLE_ENABLE_ASSERTS) + mPushedErrors++; +#endif mHasAnyErrors = 1; } } @@ -10324,7 +10326,6 @@ StateCache::StateCache() mCachedInstancedVertexElementLimit(0), mCachedBasicDrawStatesErrorString(kInvalidPointer), mCachedBasicDrawStatesErrorCode(GL_NO_ERROR), - mCachedBasicDrawElementsError(kInvalidPointer), mCachedProgramPipelineError(kInvalidPointer), mCachedHasAnyEnabledClientAttrib(false), mCachedTransformFeedbackActiveUnpaused(false), @@ -10335,7 +10336,7 @@ StateCache::StateCache() StateCache::~StateCache() = default; -ANGLE_INLINE void StateCache::updateVertexElementLimits(Context *context) +ANGLE_INLINE void StateCache::updateVertexElementLimits(const Context *context) { if (context->isBufferAccessValidationEnabled()) { @@ -10349,12 +10350,10 @@ void StateCache::initialize(Context *context) updateValidBindTextureTypes(context); updateValidDrawElementsTypes(context); updateBasicDrawStatesError(); - updateBasicDrawElementsError(); - updateVertexAttribTypesValidation(context); updateCanDraw(context); } -void StateCache::updateActiveAttribsMask(Context *context) +void StateCache::updateActiveAttribsMask(const Context *context) { bool isGLES1 = context->isGLES1(); const State &glState = context->getState(); @@ -10384,7 +10383,7 @@ void StateCache::updateActiveAttribsMask(Context *context) mCachedHasAnyEnabledClientAttrib = (clientAttribs & enabledAttribs).any(); } -void StateCache::updateVertexElementLimitsImpl(Context *context) +void StateCache::updateVertexElementLimitsImpl(const Context *context) { ASSERT(context->isBufferAccessValidationEnabled()); @@ -10462,21 +10461,6 @@ intptr_t StateCache::getProgramPipelineErrorImpl(const Context *context) const return mCachedProgramPipelineError; } -intptr_t StateCache::getBasicDrawElementsErrorImpl(const Context *context) const -{ - ASSERT(mCachedBasicDrawElementsError == kInvalidPointer); - mCachedBasicDrawElementsError = reinterpret_cast(ValidateDrawElementsStates(context)); - return mCachedBasicDrawElementsError; -} - -void StateCache::onVertexArrayBindingChange(Context *context) -{ - updateActiveAttribsMask(context); - updateVertexElementLimits(context); - updateBasicDrawStatesError(); - updateBasicDrawElementsError(); -} - void StateCache::onProgramExecutableChange(Context *context) { updateActiveAttribsMask(context); @@ -10489,31 +10473,6 @@ void StateCache::onProgramExecutableChange(Context *context) updateCanDraw(context); } -void StateCache::onVertexArrayFormatChange(Context *context) -{ - updateVertexElementLimits(context); -} - -void StateCache::onVertexArrayBufferContentsChange(Context *context) -{ - updateVertexElementLimits(context); - updateBasicDrawStatesError(); -} - -void StateCache::onVertexArrayStateChange(Context *context) -{ - updateActiveAttribsMask(context); - updateVertexElementLimits(context); - updateBasicDrawStatesError(); - updateBasicDrawElementsError(); -} - -void StateCache::onVertexArrayBufferStateChange(Context *context) -{ - updateBasicDrawStatesError(); - updateBasicDrawElementsError(); -} - void StateCache::onGLES1ClientStateChange(Context *context) { updateActiveAttribsMask(context); @@ -10543,7 +10502,6 @@ void StateCache::onActiveTransformFeedbackChange(Context *context) { updateTransformFeedbackActiveUnpaused(context); updateBasicDrawStatesError(); - updateBasicDrawElementsError(); updateValidDrawModes(context); } @@ -10596,9 +10554,16 @@ void StateCache::updateValidDrawModes(Context *context) return; } + bool pointsOK = true; + bool linesOK = true; + bool trisOK = true; + bool lineAdjOK = true; + bool triAdjOK = true; + if (mCachedTransformFeedbackActiveUnpaused) { TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); + mCachedValidDrawModes.fill(false); // ES Spec 3.0 validation text: // When transform feedback is active and not paused, all geometric primitives generated must @@ -10612,10 +10577,65 @@ void StateCache::updateValidDrawModes(Context *context) !context->getExtensions().tessellationShaderAny() && context->getClientVersion() < ES_3_2) { - mCachedValidDrawModes.fill(false); mCachedValidDrawModes[curTransformFeedback->getPrimitiveMode()] = true; return; } + + // From: EXT_geometry_shader + // + // Transform Feedback Allowed render primitive + // + // -------------------+---------------------------------------- + // POINTS | POINTS + // LINES | LINES, LINE_LOOP, LINE_STRIP + // TRIANGLES | TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN + // ------------------------------------------------------------ + // Table 12.1gs: Legal combinations of the transform feedback + // primitive mode, as passed to BeginTransformFeedback, and the + // current primitive mode. + const PrimitiveMode xfbMode = curTransformFeedback->getPrimitiveMode(); + + // If a geometry shader is bound, the primitive that interacts with transform feedback is + // the geometry shader's output primitive type, which is independent from its input. In that + // case, either all inputs are ok (if the output matches) or none are (if the output + // doesn't match). + if (programExecutable && programExecutable->hasLinkedShaderStage(ShaderType::Geometry)) + { + const PrimitiveMode gsOutMode = + programExecutable->getGeometryShaderOutputPrimitiveType(); + + // Note: the geometry shader output is either points, line_strip or triangle_strip. + bool matchingModes = false; + switch (gsOutMode) + { + case PrimitiveMode::Points: + matchingModes = xfbMode == PrimitiveMode::Points; + break; + case PrimitiveMode::LineStrip: + matchingModes = xfbMode == PrimitiveMode::Lines; + break; + case PrimitiveMode::TriangleStrip: + matchingModes = xfbMode == PrimitiveMode::Triangles; + break; + default: + // Invalid geometry shader output mode + ASSERT(false); + } + + if (!matchingModes) + { + // All draw modes are set to false, so every draw will fail. + return; + } + } + else + { + // When geometry shader is not involved, the draw call's primitive mode is expected to + // match the transform feedback's. + pointsOK = xfbMode == PrimitiveMode::Points; + linesOK = xfbMode == PrimitiveMode::Lines; + trisOK = xfbMode == PrimitiveMode::Triangles; + } } if (!programExecutable || !programExecutable->hasLinkedShaderStage(ShaderType::Geometry)) @@ -10626,16 +10646,18 @@ void StateCache::updateValidDrawModes(Context *context) // All draw modes are valid, since drawing without a program does not generate an error and // operations requiring a GS will trigger other validation errors. // `patchOK = false` due to checking above already enabling it if a TS is present. - setValidDrawModes(true, true, true, adjacencyOK, adjacencyOK, false); - return; + lineAdjOK = lineAdjOK && adjacencyOK; + triAdjOK = triAdjOK && adjacencyOK; + } + else + { + const PrimitiveMode gsMode = programExecutable->getGeometryShaderInputPrimitiveType(); + pointsOK = pointsOK && gsMode == PrimitiveMode::Points; + linesOK = linesOK && gsMode == PrimitiveMode::Lines; + trisOK = trisOK && gsMode == PrimitiveMode::Triangles; + lineAdjOK = lineAdjOK && gsMode == PrimitiveMode::LinesAdjacency; + triAdjOK = triAdjOK && gsMode == PrimitiveMode::TrianglesAdjacency; } - - PrimitiveMode gsMode = programExecutable->getGeometryShaderInputPrimitiveType(); - bool pointsOK = gsMode == PrimitiveMode::Points; - bool linesOK = gsMode == PrimitiveMode::Lines; - bool trisOK = gsMode == PrimitiveMode::Triangles; - bool lineAdjOK = gsMode == PrimitiveMode::LinesAdjacency; - bool triAdjOK = gsMode == PrimitiveMode::TrianglesAdjacency; setValidDrawModes(pointsOK, linesOK, trisOK, lineAdjOK, triAdjOK, false); } @@ -10643,9 +10665,9 @@ void StateCache::updateValidDrawModes(Context *context) void StateCache::updateValidBindTextureTypes(Context *context) { const Extensions &exts = context->getExtensions(); - bool isGLES3 = context->getClientMajorVersion() >= 3; - bool isGLES31 = context->getClientVersion() >= Version(3, 1); - bool isGLES32 = context->getClientVersion() >= Version(3, 2); + const bool isGLES3 = context->getClientVersion() >= ES_3_0; + const bool isGLES31 = context->getClientVersion() >= ES_3_1; + const bool isGLES32 = context->getClientVersion() >= ES_3_2; mCachedValidBindTextureTypes = {{ {TextureType::_2D, true}, @@ -10665,7 +10687,7 @@ void StateCache::updateValidBindTextureTypes(Context *context) void StateCache::updateValidDrawElementsTypes(Context *context) { bool supportsUint = - (context->getClientMajorVersion() >= 3 || context->getExtensions().elementIndexUintOES); + (context->getClientVersion() >= ES_3_0 || context->getExtensions().elementIndexUintOES); mCachedValidDrawElementsTypes = {{ {DrawElementsType::UnsignedByte, true}, @@ -10680,58 +10702,6 @@ void StateCache::updateTransformFeedbackActiveUnpaused(Context *context) mCachedTransformFeedbackActiveUnpaused = xfb && xfb->isActive() && !xfb->isPaused(); } -void StateCache::updateVertexAttribTypesValidation(Context *context) -{ - VertexAttribTypeCase halfFloatValidity = (context->getExtensions().vertexHalfFloatOES) - ? VertexAttribTypeCase::Valid - : VertexAttribTypeCase::Invalid; - - VertexAttribTypeCase vertexType1010102Validity = (context->getExtensions().vertexType1010102OES) - ? VertexAttribTypeCase::ValidSize3or4 - : VertexAttribTypeCase::Invalid; - - if (context->getClientMajorVersion() <= 2) - { - mCachedVertexAttribTypesValidation = {{ - {VertexAttribType::Byte, VertexAttribTypeCase::Valid}, - {VertexAttribType::Short, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, - {VertexAttribType::Float, VertexAttribTypeCase::Valid}, - {VertexAttribType::Fixed, VertexAttribTypeCase::Valid}, - {VertexAttribType::HalfFloatOES, halfFloatValidity}, - }}; - } - else - { - mCachedVertexAttribTypesValidation = {{ - {VertexAttribType::Byte, VertexAttribTypeCase::Valid}, - {VertexAttribType::Short, VertexAttribTypeCase::Valid}, - {VertexAttribType::Int, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid}, - {VertexAttribType::Float, VertexAttribTypeCase::Valid}, - {VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid}, - {VertexAttribType::Fixed, VertexAttribTypeCase::Valid}, - {VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only}, - {VertexAttribType::HalfFloatOES, halfFloatValidity}, - {VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only}, - {VertexAttribType::Int1010102, vertexType1010102Validity}, - {VertexAttribType::UnsignedInt1010102, vertexType1010102Validity}, - }}; - - mCachedIntegerVertexAttribTypesValidation = {{ - {VertexAttribType::Byte, VertexAttribTypeCase::Valid}, - {VertexAttribType::Short, VertexAttribTypeCase::Valid}, - {VertexAttribType::Int, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, - {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid}, - }}; - } -} - void StateCache::updateActiveShaderStorageBufferIndices(Context *context) { mCachedActiveShaderStorageBufferIndices.reset(); @@ -10785,7 +10755,71 @@ bool StateCache::isCurrentContext(const Context *context, &context->getPrivateStateCache() == privateStateCache; } -PrivateStateCache::PrivateStateCache() : mIsCachedBasicDrawStatesErrorValid(true) {} +// PrivateStateCache implementation +PrivateStateCache::PrivateStateCache() + : mIsCachedBasicDrawStatesErrorValid(true), + mIsCachedActiveAttribMasksValid(true), + mIsCachedVertexElementLimitValid(true), + mCachedBasicDrawElementsError(kInvalidPointer) +{} PrivateStateCache::~PrivateStateCache() = default; + +void PrivateStateCache::initialize(const Context *context) +{ + updateVertexAttribTypesValidation(context); + mCachedBasicDrawElementsError = kInvalidPointer; +} + +void PrivateStateCache::updateVertexAttribTypesValidation(const Context *context) +{ + VertexAttribTypeCase halfFloatValidity = (context->getExtensions().vertexHalfFloatOES) + ? VertexAttribTypeCase::Valid + : VertexAttribTypeCase::Invalid; + + VertexAttribTypeCase vertexType1010102Validity = (context->getExtensions().vertexType1010102OES) + ? VertexAttribTypeCase::ValidSize3or4 + : VertexAttribTypeCase::Invalid; + + if (context->getClientVersion() < ES_3_0) + { + mCachedVertexAttribTypesValidation = {{ + {VertexAttribType::Byte, VertexAttribTypeCase::Valid}, + {VertexAttribType::Short, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, + {VertexAttribType::Float, VertexAttribTypeCase::Valid}, + {VertexAttribType::Fixed, VertexAttribTypeCase::Valid}, + {VertexAttribType::HalfFloatOES, halfFloatValidity}, + }}; + } + else + { + mCachedVertexAttribTypesValidation = {{ + {VertexAttribType::Byte, VertexAttribTypeCase::Valid}, + {VertexAttribType::Short, VertexAttribTypeCase::Valid}, + {VertexAttribType::Int, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid}, + {VertexAttribType::Float, VertexAttribTypeCase::Valid}, + {VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid}, + {VertexAttribType::Fixed, VertexAttribTypeCase::Valid}, + {VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only}, + {VertexAttribType::HalfFloatOES, halfFloatValidity}, + {VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only}, + {VertexAttribType::Int1010102, vertexType1010102Validity}, + {VertexAttribType::UnsignedInt1010102, vertexType1010102Validity}, + }}; + + mCachedIntegerVertexAttribTypesValidation = {{ + {VertexAttribType::Byte, VertexAttribTypeCase::Valid}, + {VertexAttribType::Short, VertexAttribTypeCase::Valid}, + {VertexAttribType::Int, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, + {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid}, + }}; + } +} } // namespace gl diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h index fcc0d79ae5d..ed65d115766 100644 --- a/src/libANGLE/Context.h +++ b/src/libANGLE/Context.h @@ -11,6 +11,10 @@ #ifndef LIBANGLE_CONTEXT_H_ #define LIBANGLE_CONTEXT_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include #include @@ -119,6 +123,9 @@ class ErrorSet : angle::NonCopyable GLenum getGraphicsResetStatus(rx::ContextImpl *contextImpl); GLenum getResetStrategy() const { return mResetStrategy; } GLenum getErrorForCapture() const; +#if defined(ANGLE_ENABLE_ASSERTS) + uint32_t getPushedErrorCount() const { return mPushedErrors; } +#endif private: void setContextLost(); @@ -144,9 +151,15 @@ class ErrorSet : angle::NonCopyable bool mContextLostForced; GraphicsResetStatus mResetStatus; + std::atomic mErrorMessageCount; + uint32_t mMaxErrorMessages; + // The following are atomic and lockless as they are very frequently accessed. std::atomic_int mSkipValidation; std::atomic_int mContextLost; +#if defined(ANGLE_ENABLE_ASSERTS) + std::atomic_uint32_t mPushedErrors; // must be unsigned to handle overflows +#endif std::atomic_int mHasAnyErrors; }; @@ -166,6 +179,8 @@ class PrivateStateCache final : angle::NonCopyable PrivateStateCache(); ~PrivateStateCache(); + void initialize(const Context *context); + void onCapChange() { mIsCachedBasicDrawStatesErrorValid = false; } void onColorMaskChange() { mIsCachedBasicDrawStatesErrorValid = false; } void onDefaultVertexAttributeChange() { mIsCachedBasicDrawStatesErrorValid = false; } @@ -191,10 +206,81 @@ class PrivateStateCache final : angle::NonCopyable void onStencilStateChange() { mIsCachedBasicDrawStatesErrorValid = false; } + void onBufferBindingChange() + { + mIsCachedBasicDrawStatesErrorValid = false; + mCachedBasicDrawElementsError = kInvalidPointer; + } + + void onVertexArrayBindingChange() + { + mIsCachedActiveAttribMasksValid = false; + mIsCachedVertexElementLimitValid = false; + mIsCachedBasicDrawStatesErrorValid = false; + mCachedBasicDrawElementsError = kInvalidPointer; + } + void onVertexArrayStateChange() + { + mIsCachedActiveAttribMasksValid = false; + mIsCachedVertexElementLimitValid = false; + mIsCachedBasicDrawStatesErrorValid = false; + mCachedBasicDrawElementsError = kInvalidPointer; + } + void onVertexArrayFormatChange() { mIsCachedVertexElementLimitValid = false; } + void onVertexArrayBufferContentsChange() + { + mIsCachedVertexElementLimitValid = false; + mIsCachedBasicDrawStatesErrorValid = false; + } + void onVertexArrayBufferStateChange() + { + mIsCachedBasicDrawStatesErrorValid = false; + mCachedBasicDrawElementsError = kInvalidPointer; + } + bool isCachedBasicDrawStatesErrorValid() const { return mIsCachedBasicDrawStatesErrorValid; } void setCachedBasicDrawStatesErrorValid() const { mIsCachedBasicDrawStatesErrorValid = true; } + bool isCachedActiveAttribMasksValid() const { return mIsCachedActiveAttribMasksValid; } + void setCachedActiveAttribMasksValid() const { mIsCachedActiveAttribMasksValid = true; } + + bool isCachedVertexElementLimitValid() const { return mIsCachedVertexElementLimitValid; } + void setCachedVertexElementLimitValid() const { mIsCachedVertexElementLimitValid = true; } + + bool isCachedBasicDrawElementsErrorValid() const + { + return mCachedBasicDrawElementsError != kInvalidPointer; + } + intptr_t getBasicDrawElementsError() const + { + ASSERT(isCachedBasicDrawElementsErrorValid()); + return mCachedBasicDrawElementsError; + } + void invalidateCachedBasicDrawElementsError() + { + mCachedBasicDrawElementsError = kInvalidPointer; + } + void updateBasicDrawElementsError(intptr_t drawElementsError) const + { + ASSERT(drawElementsError != kInvalidPointer); + mCachedBasicDrawElementsError = drawElementsError; + } + + // Cannot change except on Context/Extension init. + VertexAttribTypeCase getVertexAttribTypeValidation(VertexAttribType type) const + { + return mCachedVertexAttribTypesValidation[type]; + } + VertexAttribTypeCase getIntegerVertexAttribTypeValidation(VertexAttribType type) const + { + return mCachedIntegerVertexAttribTypesValidation[type]; + } + private: + void updateVertexAttribTypesValidation(const Context *context); + + static constexpr intptr_t kInvalidPointer = 1; + // StateCache::mCachedBasicDrawStatesError* may be invalidated through numerous calls (see the // comment on getBasicDrawStatesErrorString), some of which may originate from other contexts // (through the observer interface). However, ContextPrivate* helpers may also need to @@ -202,6 +288,30 @@ class PrivateStateCache final : angle::NonCopyable // following tracks whether StateCache::mCachedBasicDrawStatesError* values are valid and is // accessed only by the context itself. mutable bool mIsCachedBasicDrawStatesErrorValid; + + // When any one of these cached values needs to be updated, we will set + // mIsCachedActiveAttribMasksValid to false. Whenever these cached value are used, we check this + // boolean and update if needed: StateCache::mCachedActiveClientAttribsMask, + // StateCache::mCachedActiveBufferedAttribsMask, StateCache::mCachedActiveDefaultAttribsMask, + // StateCache::mCachedHasAnyEnabledClientAttrib, + mutable bool mIsCachedActiveAttribMasksValid; + + // When any one of these cached values needs to be updated, we will set it to false. Whenever + // these cached value are used, we check this boolean and update if needed: + // StateCache::mCachedNonInstancedVertexElementLimit, + // StateCache::mCachedInstancedVertexElementLimit + mutable bool mIsCachedVertexElementLimitValid; + + // This only gets modified by the current context, with or without shared lock. But it is always + // thread safe since context can only be current in one thread. + mutable intptr_t mCachedBasicDrawElementsError; + + using VertexAttribTypesValidation = + angle::PackedEnumMap() + 1>; + VertexAttribTypesValidation mCachedVertexAttribTypesValidation; + VertexAttribTypesValidation mCachedIntegerVertexAttribTypesValidation; }; // Helper class for managing cache variables and state changes. @@ -219,11 +329,31 @@ class StateCache final : angle::NonCopyable // 3. onVertexArrayStateChange. // 4. onGLES1ClientStateChange. // 5. onGLES1TextureStateChange. - AttributesMask getActiveBufferedAttribsMask() const { return mCachedActiveBufferedAttribsMask; } - AttributesMask getActiveClientAttribsMask() const { return mCachedActiveClientAttribsMask; } - AttributesMask getActiveDefaultAttribsMask() const { return mCachedActiveDefaultAttribsMask; } - bool hasAnyEnabledClientAttrib() const { return mCachedHasAnyEnabledClientAttrib; } - bool hasAnyActiveClientAttrib() const { return mCachedActiveClientAttribsMask.any(); } + AttributesMask getActiveBufferedAttribsMask(const PrivateStateCache &privateStateCache) const + { + ASSERT(privateStateCache.isCachedActiveAttribMasksValid()); + return mCachedActiveBufferedAttribsMask; + } + AttributesMask getActiveClientAttribsMask(const PrivateStateCache &privateStateCache) const + { + ASSERT(privateStateCache.isCachedActiveAttribMasksValid()); + return mCachedActiveClientAttribsMask; + } + AttributesMask getActiveDefaultAttribsMask(const PrivateStateCache &privateStateCache) const + { + ASSERT(privateStateCache.isCachedActiveAttribMasksValid()); + return mCachedActiveDefaultAttribsMask; + } + bool hasAnyEnabledClientAttrib(const PrivateStateCache &privateStateCache) const + { + ASSERT(privateStateCache.isCachedActiveAttribMasksValid()); + return mCachedHasAnyEnabledClientAttrib; + } + bool hasAnyActiveClientAttrib(const PrivateStateCache &privateStateCache) const + { + ASSERT(privateStateCache.isCachedActiveAttribMasksValid()); + return mCachedActiveClientAttribsMask.any(); + } // Places that can trigger updateVertexElementLimits: // 1. onVertexArrayBindingChange. @@ -231,11 +361,16 @@ class StateCache final : angle::NonCopyable // 3. onVertexArrayFormatChange. // 4. onVertexArrayBufferChange. // 5. onVertexArrayStateChange. - GLint64 getNonInstancedVertexElementLimit() const + GLint64 getNonInstancedVertexElementLimit(const PrivateStateCache &privateStateCache) const { + ASSERT(privateStateCache.isCachedVertexElementLimitValid()); return mCachedNonInstancedVertexElementLimit; } - GLint64 getInstancedVertexElementLimit() const { return mCachedInstancedVertexElementLimit; } + GLint64 getInstancedVertexElementLimit(const PrivateStateCache &privateStateCache) const + { + ASSERT(privateStateCache.isCachedVertexElementLimitValid()); + return mCachedInstancedVertexElementLimit; + } // Places that can trigger updateBasicDrawStatesError: // 1. onVertexArrayBindingChange. @@ -291,22 +426,6 @@ class StateCache final : angle::NonCopyable return getProgramPipelineErrorImpl(context); } - // Places that can trigger updateBasicDrawElementsError: - // 1. onActiveTransformFeedbackChange. - // 2. onVertexArrayBufferStateChange. - // 3. onBufferBindingChange. - // 4. onVertexArrayStateChange. - // 5. onVertexArrayBindingStateChange. - intptr_t getBasicDrawElementsError(const Context *context) const - { - if (mCachedBasicDrawElementsError != kInvalidPointer) - { - return mCachedBasicDrawElementsError; - } - - return getBasicDrawElementsErrorImpl(context); - } - // Places that can trigger updateValidDrawModes: // 1. onProgramExecutableChange. // 2. onActiveTransformFeedbackChange. @@ -334,17 +453,6 @@ class StateCache final : angle::NonCopyable return mCachedTransformFeedbackActiveUnpaused; } - // Cannot change except on Context/Extension init. - VertexAttribTypeCase getVertexAttribTypeValidation(VertexAttribType type) const - { - return mCachedVertexAttribTypesValidation[type]; - } - - VertexAttribTypeCase getIntegerVertexAttribTypeValidation(VertexAttribType type) const - { - return mCachedIntegerVertexAttribTypesValidation[type]; - } - // Places that can trigger updateActiveShaderStorageBufferIndices: // 1. onProgramExecutableChange. StorageBuffersMask getActiveShaderStorageBufferIndices() const @@ -361,12 +469,7 @@ class StateCache final : angle::NonCopyable bool getCanDraw() const { return mCachedCanDraw; } // State change notifications. - void onVertexArrayBindingChange(Context *context); void onProgramExecutableChange(Context *context); - void onVertexArrayFormatChange(Context *context); - void onVertexArrayBufferContentsChange(Context *context); - void onVertexArrayStateChange(Context *context); - void onVertexArrayBufferStateChange(Context *context); void onGLES1TextureStateChange(Context *context); void onGLES1ClientStateChange(Context *context); void onDrawFramebufferChange(Context *context); @@ -376,15 +479,16 @@ class StateCache final : angle::NonCopyable void onUniformBufferStateChange(Context *context); void onAtomicCounterBufferStateChange(Context *context); void onShaderStorageBufferStateChange(Context *context); - void onBufferBindingChange(Context *context); + + // Cache update functions. + void updateActiveAttribsMask(const Context *context); + void updateVertexElementLimits(const Context *context); + void updateVertexElementLimitsImpl(const Context *context); private: bool isCurrentContext(const Context *context, const PrivateStateCache *privateStateCache) const; // Cache update functions. - void updateActiveAttribsMask(Context *context); - void updateVertexElementLimits(Context *context); - void updateVertexElementLimitsImpl(Context *context); void updateValidDrawModes(Context *context); void updateValidBindTextureTypes(Context *context); void updateValidDrawElementsTypes(Context *context); @@ -394,9 +498,7 @@ class StateCache final : angle::NonCopyable mCachedBasicDrawStatesErrorCode = GL_NO_ERROR; } void updateProgramPipelineError() { mCachedProgramPipelineError = kInvalidPointer; } - void updateBasicDrawElementsError() { mCachedBasicDrawElementsError = kInvalidPointer; } void updateTransformFeedbackActiveUnpaused(Context *context); - void updateVertexAttribTypesValidation(Context *context); void updateActiveShaderStorageBufferIndices(Context *context); void updateActiveImageUnitIndices(Context *context); void updateCanDraw(Context *context); @@ -411,7 +513,6 @@ class StateCache final : angle::NonCopyable intptr_t getBasicDrawStatesErrorImpl(const Context *context, const PrivateStateCache *privateStateCache) const; intptr_t getProgramPipelineErrorImpl(const Context *context) const; - intptr_t getBasicDrawElementsErrorImpl(const Context *context) const; static constexpr intptr_t kInvalidPointer = 1; @@ -467,7 +568,6 @@ class StateCache final : angle::NonCopyable mutable intptr_t mCachedBasicDrawStatesErrorString; mutable GLenum mCachedBasicDrawStatesErrorCode; - mutable intptr_t mCachedBasicDrawElementsError; // mCachedProgramPipelineError checks only the // current-program-exists subset of mCachedBasicDrawStatesError. // Therefore, mCachedProgramPipelineError follows @@ -489,19 +589,10 @@ class StateCache final : angle::NonCopyable mCachedValidBindTextureTypes; angle::PackedEnumMap() + 1> mCachedValidDrawElementsTypes; - angle::PackedEnumMap() + 1> - mCachedVertexAttribTypesValidation; - angle::PackedEnumMap() + 1> - mCachedIntegerVertexAttribTypesValidation; bool mCachedCanDraw; }; -using VertexArrayMap = ResourceMap; using QueryMap = ResourceMap; using TransformFeedbackMap = ResourceMap; @@ -537,12 +628,12 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl egl::Error unMakeCurrent(const egl::Display *display); // These create and destroy methods pass through to ResourceManager, which owns these objects. - BufferID createBuffer(); - TextureID createTexture(); - RenderbufferID createRenderbuffer(); - ProgramPipelineID createProgramPipeline(); - MemoryObjectID createMemoryObject(); - SemaphoreID createSemaphore(); + bool createBuffer(BufferID *outBuffer); + bool createTexture(TextureID *outTexture); + bool createRenderbuffer(RenderbufferID *outRenderbuffer); + bool createProgramPipeline(ProgramPipelineID *outProgramPipeline); + bool createMemoryObject(MemoryObjectID *outMemoryObject); + bool createSemaphore(SemaphoreID *outSemaphore); void deleteBuffer(BufferID buffer); void deleteTexture(TextureID texture); @@ -564,7 +655,6 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl Framebuffer *getFramebuffer(FramebufferID handle) const; Renderbuffer *getRenderbuffer(RenderbufferID handle) const; - VertexArray *getVertexArray(VertexArrayID handle) const; Sampler *getSampler(SamplerID handle) const; Query *getOrCreateQuery(QueryID handle, QueryType type); Query *getQuery(QueryID handle) const; @@ -579,9 +669,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl Compiler *getCompiler() const; - bool isVertexArrayGenerated(VertexArrayID vertexArray) const; bool isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const; + bool isZeroTextureBound(TextureType textureType) const; + bool isExternal() const { return mState.isExternal(); } void getBooleanvImpl(GLenum pname, GLboolean *params) const; @@ -592,7 +683,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl void getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) const; // Framebuffers are owned by the Context, so these methods do not pass through - FramebufferID createFramebuffer(); + bool createFramebuffer(FramebufferID *outFramebuffer); void deleteFramebuffer(FramebufferID framebuffer); bool hasActiveTransformFeedback(ShaderProgramID program) const; @@ -664,14 +755,17 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl return mState.isCurrentVertexArray(va); } - ANGLE_INLINE bool isShared() const { return mShared; } + bool isShared() const { return mShared; } + bool isSharedContext() const { return mSharedContext; } // Once a context is setShared() it cannot be undone - void setShared() { mShared = true; } + void setShared() + { + mShared = true; + mSharedContext = true; + } const State &getState() const { return mState; } const PrivateState &getPrivateState() const { return mState.privateState(); } - GLint getClientMajorVersion() const { return mState.getClientMajorVersion(); } - GLint getClientMinorVersion() const { return mState.getClientMinorVersion(); } const Version &getClientVersion() const { return mState.getClientVersion(); } const Caps &getCaps() const { return mState.getCaps(); } const TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); } @@ -687,8 +781,14 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl void markContextLost(GraphicsResetStatus status) { mErrors.markContextLost(status); } bool isContextLost() const { return mErrors.isContextLost(); } + // Some commands may need to generate a context lost error but still return a value. + // The validation layer does not generate the context lost error in such cases. + void contextLostErrorOnBlockingCall(angle::EntryPoint entryPoint) const; + ErrorSet *getMutableErrorSetForValidation() const { return &mErrors; } + void handleExhaustionError(angle::EntryPoint entryPoint); + // Specific methods needed for validation. bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const; bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) const; @@ -707,6 +807,12 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl Shader *getShaderResolveCompile(ShaderProgramID handle) const; Shader *getShaderNoResolveCompile(ShaderProgramID handle) const; + bool nameStartsWithReservedPrefix(const GLchar *name) const + { + return (strncmp(name, "gl_", 3) == 0) || + (isWebGL() && (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)); + } + ANGLE_INLINE bool isTextureGenerated(TextureID texture) const { return mState.mTextureManager->isHandleGenerated(texture); @@ -730,6 +836,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl bool isWebGL() const { return mState.isWebGL(); } bool isWebGL1() const { return mState.isWebGL1(); } + bool isHardenedContext() const { return mHardenedContext; } const char *getRendererString() const { return mRendererString; } bool isValidBufferBinding(BufferBinding binding) const { return mValidBufferBindings[binding]; } @@ -768,13 +875,19 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl angle::FrameCapture *getFrameCapture() const { return mFrameCapture.get(); } - const VertexArrayMap &getVertexArraysForCapture() const { return mVertexArrayMap; } + const VertexArrayMap &getVertexArraysForCapture() const + { + return getPrivateState().getVertexArrayMap(); + } const QueryMap &getQueriesForCapture() const { return mQueryMap; } const TransformFeedbackMap &getTransformFeedbacksForCapture() const { return mTransformFeedbackMap; } GLenum getErrorForCapture() const { return mErrors.getErrorForCapture(); } +#if defined(ANGLE_ENABLE_ASSERTS) + uint32_t getPushedErrorCount() const { return mErrors.getPushedErrorCount(); } +#endif void onPreSwap(); @@ -799,6 +912,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl egl::Error acquireExternalContext(egl::Surface *drawAndReadSurface); egl::Error releaseExternalContext(); + bool noopDrawProgram() const; bool noopDraw(PrimitiveMode mode, GLsizei count) const; bool noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei instanceCount) const; bool noopMultiDraw(GLsizei drawcount) const; @@ -834,7 +948,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl // Needed by capture serialization logic that works with a "const" Context pointer. void finishImmutable() const; - const angle::PerfMonitorCounterGroups &getPerfMonitorCounterGroups() const; + const angle::PerfMonitorCounterGroupsInfo &getPerfMonitorCounterGroups() const; // Ends the currently active pixel local storage session with GL_STORE_OP_STORE on all planes. void endPixelLocalStorageImplicit(); @@ -843,6 +957,32 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl size_t getMemoryUsage() const; + // Only used by vulkan backend. + void onSwapChainImageChanged() const { mDefaultFramebuffer->onSwapChainImageChanged(); } + void onBufferChanged(const Buffer *buffer, + const angle::SubjectMessage message, + VertexArrayBufferBindingMask vertexArrayBufferBindingMask) const + { + // Notify current vertex array of the buffer changed. Note that other vertex arrays of this + // context or other context requires rebind which will check buffer changes + // at that time. + if (vertexArrayBufferBindingMask.any()) + { + ASSERT(mState.mVertexArray != nullptr); + mState.mVertexArray->onBufferChanged(this, buffer, message, + vertexArrayBufferBindingMask); + } + } + + AttributesMask getActiveBufferedAttribsMask() const; + AttributesMask getActiveClientAttribsMask() const; + AttributesMask getActiveDefaultAttribsMask() const; + bool hasAnyEnabledClientAttrib() const; + bool hasAnyActiveClientAttrib() const; + GLint64 getNonInstancedVertexElementLimit() const; + GLint64 getInstancedVertexElementLimit() const; + void onActiveTransformFeedbackChange(); + private: void initializeDefaultResources(); void releaseSharedObjects(); @@ -854,7 +994,6 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl const state::ExtendedDirtyBits extendedBitMask, const state::DirtyObjects &objectMask, Command command); - angle::Result syncAllDirtyBits(Command command); angle::Result syncDirtyBits(const state::DirtyBits bitMask, const state::ExtendedDirtyBits extendedBitMask, Command command); @@ -904,11 +1043,13 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl MultisamplingMode mode); void onUniformBlockBindingUpdated(GLuint uniformBlockIndex); + void updateActiveAttribsMaskIfNeeded() const; void endTilingImplicit(); State mState; bool mShared; + bool mSharedContext; bool mDisplayTextureShareGroup; bool mDisplaySemaphoreShareGroup; @@ -939,9 +1080,6 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl QueryMap mQueryMap; HandleAllocator mQueryHandleAllocator; - VertexArrayMap mVertexArrayMap; - HandleAllocator mVertexArrayHandleAllocator; - TransformFeedbackMap mTransformFeedbackMap; HandleAllocator mTransformFeedbackHandleAllocator; @@ -964,14 +1102,16 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl egl::Surface *mCurrentReadSurface; egl::Display *mDisplay; const bool mWebGLContext; + const bool mHardenedContext; bool mBufferAccessValidationEnabled; + bool mRequiresRobustBehavior; const bool mExtensionsEnabled; MemoryProgramCache *mMemoryProgramCache; MemoryShaderCache *mMemoryShaderCache; state::DirtyObjects mDrawDirtyObjects; - StateCache mStateCache; + mutable StateCache mStateCache; PrivateStateCache mPrivateStateCache; state::DirtyObjects mTexImageDirtyObjects; @@ -981,6 +1121,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl state::DirtyObjects mComputeDirtyObjects; state::DirtyBits mCopyImageDirtyBits; state::DirtyObjects mCopyImageDirtyObjects; + state::DirtyObjects mTilingDirtyObjects; // Binding to container objects that use dependent state updates. angle::ObserverBinding mVertexArrayObserverBinding; diff --git a/src/libANGLE/Context.inl.h b/src/libANGLE/Context.inl.h index d8abddd2fa6..043a3147310 100644 --- a/src/libANGLE/Context.inl.h +++ b/src/libANGLE/Context.inl.h @@ -18,7 +18,7 @@ #define ANGLE_HANDLE_ERR(X) \ (void)(X); \ return; -#define ANGLE_CONTEXT_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_ERR) +#define ANGLE_CONTEXT_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, static_cast(0), ANGLE_HANDLE_ERR) namespace gl { @@ -36,6 +36,12 @@ constexpr angle::PackedEnumMap kMinimumPrimitiveCounts = {PrimitiveMode::TriangleStripAdjacency, 3}, }}; +// All bits except |DIRTY_BIT_READ_FRAMEBUFFER_BINDING| because |mDrawDirtyObjects| does not contain +// |DIRTY_OBJECT_READ_FRAMEBUFFER|, to avoid synchronizing with invalid read framebuffer state. +constexpr state::DirtyBits kDrawDirtyBits = + ~state::DirtyBits{state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING}; +constexpr state::ExtendedDirtyBits kDrawExtendedDirtyBits = state::ExtendedDirtyBits().set(); + ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context, GLsizei count, GLsizei instanceCount) @@ -54,7 +60,7 @@ ANGLE_INLINE void MarkShaderStorageUsage(const Context *context) Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get(); if (buffer) { - buffer->onDataChanged(); + buffer->onDataChanged(context); } } @@ -75,35 +81,45 @@ ANGLE_INLINE void MarkShaderStorageUsage(const Context *context) // an error. ANGLE will treat this as a no-op. // A no-op draw occurs if the count of vertices is less than the minimum required to // have a valid primitive for this mode (0 for points, 0-1 for lines, 0-2 for tris). -ANGLE_INLINE bool Context::noopDraw(PrimitiveMode mode, GLsizei count) const +ANGLE_INLINE bool Context::noopDrawProgram() const { // Make sure any pending link is done before checking whether draw is allowed. mState.ensureNoPendingLink(this); - if (!mStateCache.getCanDraw()) + // No-op when there is no active vertex shader + return !mStateCache.getCanDraw(); +} + +ANGLE_INLINE bool Context::noopDraw(PrimitiveMode mode, GLsizei count) const +{ + if (ANGLE_UNLIKELY(count < kMinimumPrimitiveCounts[mode])) { return true; } - return count < kMinimumPrimitiveCounts[mode]; + return noopDrawProgram(); } -ANGLE_INLINE bool Context::noopMultiDraw(GLsizei drawcount) const +ANGLE_INLINE bool Context::noopDrawInstanced(PrimitiveMode mode, + GLsizei count, + GLsizei instanceCount) const { - return drawcount == 0 || !mStateCache.getCanDraw(); + if (ANGLE_UNLIKELY(instanceCount < 1)) + { + return true; + } + + return noopDraw(mode, count); } -ANGLE_INLINE angle::Result Context::syncAllDirtyBits(Command command) +ANGLE_INLINE bool Context::noopMultiDraw(GLsizei drawcount) const { - constexpr state::DirtyBits kAllDirtyBits = state::DirtyBits().set(); - constexpr state::ExtendedDirtyBits kAllExtendedDirtyBits = state::ExtendedDirtyBits().set(); - const state::DirtyBits dirtyBits = mState.getDirtyBits(); - const state::ExtendedDirtyBits extendedDirtyBits = mState.getExtendedDirtyBits(); - ANGLE_TRY(mImplementation->syncState(this, dirtyBits, kAllDirtyBits, extendedDirtyBits, - kAllExtendedDirtyBits, command)); - mState.clearDirtyBits(); - mState.clearExtendedDirtyBits(); - return angle::Result::Continue; + if (ANGLE_UNLIKELY(drawcount < 1)) + { + return true; + } + + return noopDrawProgram(); } ANGLE_INLINE angle::Result Context::syncDirtyBits(const state::DirtyBits bitMask, @@ -136,7 +152,7 @@ ANGLE_INLINE angle::Result Context::prepareForDraw(PrimitiveMode mode) ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects, Command::Draw)); ASSERT(!isRobustResourceInitEnabled() || !mState.getDrawFramebuffer()->hasResourceThatNeedsInit()); - return syncAllDirtyBits(Command::Draw); + return syncDirtyBits(kDrawDirtyBits, kDrawExtendedDirtyBits, Command::Draw); } ANGLE_INLINE void Context::drawArrays(PrimitiveMode mode, GLint first, GLsizei count) @@ -169,17 +185,27 @@ ANGLE_INLINE void Context::drawElements(PrimitiveMode mode, ANGLE_CONTEXT_TRY(mImplementation->drawElements(this, mode, count, type, indices)); } -ANGLE_INLINE void StateCache::onBufferBindingChange(Context *context) -{ - updateBasicDrawStatesError(); - updateBasicDrawElementsError(); -} - ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer) { Buffer *bufferObject = mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer); + // If there is a shared context, buffer may have been modified by other context. bindBuffer + // supposedly should pick up the changes other contexts have made and update current vertex + // array. + if (bufferObject != nullptr && isSharedContext()) + { + VertexArrayBufferBindingMask bindingMask = bufferObject->getVertexArrayBinding(this); + if (bindingMask.any()) + { + ASSERT(mState.mVertexArray != nullptr); + // Update vertex array only if buffer is attached to current vertex array. + mState.mVertexArray->onSharedBufferBind(this, bufferObject, bindingMask); + mState.setObjectDirty(GL_VERTEX_ARRAY); + mPrivateStateCache.onVertexArrayBufferContentsChange(); + } + } + // Early return if rebinding the same buffer if (bufferObject == mState.getTargetBuffer(target)) { @@ -187,14 +213,253 @@ ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer) } mState.setBufferBinding(this, target, bufferObject); - mStateCache.onBufferBindingChange(this); + mPrivateStateCache.onBufferBindingChange(); - if (bufferObject) + if (bufferObject && isWebGL()) { bufferObject->onBind(this, target); } } +ANGLE_INLINE void Context::uniform1f(UniformLocation location, GLfloat x) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform1fv(location, 1, &x); +} + +ANGLE_INLINE void Context::uniform1fv(UniformLocation location, GLsizei count, const GLfloat *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform1fv(location, count, v); +} + +ANGLE_INLINE void Context::setUniform1iImpl(Program *program, + UniformLocation location, + GLsizei count, + const GLint *v) +{ + program->getExecutable().setUniform1iv(this, location, count, v); +} + +ANGLE_INLINE void Context::uniform1i(UniformLocation location, GLint x) +{ + Program *program = getActiveLinkedProgram(); + setUniform1iImpl(program, location, 1, &x); +} + +ANGLE_INLINE void Context::uniform1iv(UniformLocation location, GLsizei count, const GLint *v) +{ + Program *program = getActiveLinkedProgram(); + setUniform1iImpl(program, location, count, v); +} + +ANGLE_INLINE void Context::uniform2f(UniformLocation location, GLfloat x, GLfloat y) +{ + GLfloat xy[2] = {x, y}; + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform2fv(location, 1, xy); +} + +ANGLE_INLINE void Context::uniform2fv(UniformLocation location, GLsizei count, const GLfloat *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform2fv(location, count, v); +} + +ANGLE_INLINE void Context::uniform2i(UniformLocation location, GLint x, GLint y) +{ + GLint xy[2] = {x, y}; + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform2iv(location, 1, xy); +} + +ANGLE_INLINE void Context::uniform2iv(UniformLocation location, GLsizei count, const GLint *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform2iv(location, count, v); +} + +ANGLE_INLINE void Context::uniform3f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat xyz[3] = {x, y, z}; + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform3fv(location, 1, xyz); +} + +ANGLE_INLINE void Context::uniform3fv(UniformLocation location, GLsizei count, const GLfloat *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform3fv(location, count, v); +} + +ANGLE_INLINE void Context::uniform3i(UniformLocation location, GLint x, GLint y, GLint z) +{ + GLint xyz[3] = {x, y, z}; + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform3iv(location, 1, xyz); +} + +ANGLE_INLINE void Context::uniform3iv(UniformLocation location, GLsizei count, const GLint *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform3iv(location, count, v); +} + +ANGLE_INLINE void Context::uniform4f(UniformLocation location, + GLfloat x, + GLfloat y, + GLfloat z, + GLfloat w) +{ + GLfloat xyzw[4] = {x, y, z, w}; + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform4fv(location, 1, xyzw); +} + +ANGLE_INLINE void Context::uniform4fv(UniformLocation location, GLsizei count, const GLfloat *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform4fv(location, count, v); +} + +ANGLE_INLINE void Context::uniform4i(UniformLocation location, GLint x, GLint y, GLint z, GLint w) +{ + GLint xyzw[4] = {x, y, z, w}; + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform4iv(location, 1, xyzw); +} + +ANGLE_INLINE void Context::uniform4iv(UniformLocation location, GLsizei count, const GLint *v) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform4iv(location, count, v); +} + +ANGLE_INLINE void Context::uniform1ui(UniformLocation location, GLuint v0) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform1uiv(location, 1, &v0); +} + +ANGLE_INLINE void Context::uniform2ui(UniformLocation location, GLuint v0, GLuint v1) +{ + Program *program = getActiveLinkedProgram(); + const GLuint xy[] = {v0, v1}; + program->getExecutable().setUniform2uiv(location, 1, xy); +} + +ANGLE_INLINE void Context::uniform3ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2) +{ + Program *program = getActiveLinkedProgram(); + const GLuint xyz[] = {v0, v1, v2}; + program->getExecutable().setUniform3uiv(location, 1, xyz); +} + +ANGLE_INLINE void Context::uniform4ui(UniformLocation location, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + Program *program = getActiveLinkedProgram(); + const GLuint xyzw[] = {v0, v1, v2, v3}; + program->getExecutable().setUniform4uiv(location, 1, xyzw); +} + +ANGLE_INLINE void Context::uniform1uiv(UniformLocation location, GLsizei count, const GLuint *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform1uiv(location, count, value); +} + +ANGLE_INLINE void Context::uniform2uiv(UniformLocation location, GLsizei count, const GLuint *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform2uiv(location, count, value); +} + +ANGLE_INLINE void Context::uniform3uiv(UniformLocation location, GLsizei count, const GLuint *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform3uiv(location, count, value); +} + +ANGLE_INLINE void Context::uniform4uiv(UniformLocation location, GLsizei count, const GLuint *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniform4uiv(location, count, value); +} + +ANGLE_INLINE void Context::uniformMatrix2x3fv(UniformLocation location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniformMatrix2x3fv(location, count, transpose, value); +} + +ANGLE_INLINE void Context::uniformMatrix3x2fv(UniformLocation location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniformMatrix3x2fv(location, count, transpose, value); +} + +ANGLE_INLINE void Context::uniformMatrix2x4fv(UniformLocation location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniformMatrix2x4fv(location, count, transpose, value); +} + +ANGLE_INLINE void Context::uniformMatrix4x2fv(UniformLocation location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniformMatrix4x2fv(location, count, transpose, value); +} + +ANGLE_INLINE void Context::uniformMatrix3x4fv(UniformLocation location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniformMatrix3x4fv(location, count, transpose, value); +} + +ANGLE_INLINE void Context::uniformMatrix4x3fv(UniformLocation location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + Program *program = getActiveLinkedProgram(); + program->getExecutable().setUniformMatrix4x3fv(location, count, transpose, value); +} + +ANGLE_INLINE void Context::vertexAttribPointer(GLuint index, + GLint size, + VertexAttribType type, + GLboolean normalized, + GLsizei stride, + const void *ptr) +{ + bool vertexAttribDirty = false; + mState.setVertexAttribPointer(this, index, mState.getTargetBuffer(BufferBinding::Array), size, + type, normalized != GL_FALSE, stride, ptr, &vertexAttribDirty); + if (vertexAttribDirty) + { + mPrivateStateCache.onVertexArrayStateChange(); + } +} + } // namespace gl #endif // LIBANGLE_CONTEXT_INL_H_ diff --git a/src/libANGLE/Context_gles_1_0.cpp b/src/libANGLE/Context_gles_1_0.cpp index 39ba261f5f4..ef53bfab825 100644 --- a/src/libANGLE/Context_gles_1_0.cpp +++ b/src/libANGLE/Context_gles_1_0.cpp @@ -6,7 +6,13 @@ // Context_gles_1_0.cpp: Implements the GLES1-specific parts of Context. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Context.h" +#include "libANGLE/Context.inl.h" +#include "libANGLE/context_private_call.inl.h" #include "common/mathutil.h" #include "common/utilities.h" @@ -35,14 +41,16 @@ void Context::colorPointer(GLint size, VertexAttribType type, GLsizei stride, co void Context::disableClientState(ClientVertexArrayType clientState) { getMutableGLES1State()->setClientStateEnabled(clientState, false); - disableVertexAttribArray(vertexArrayIndex(clientState)); + ContextPrivateDisableVertexAttribArray(getMutablePrivateState(), getMutablePrivateStateCache(), + vertexArrayIndex(clientState)); mStateCache.onGLES1ClientStateChange(this); } void Context::enableClientState(ClientVertexArrayType clientState) { getMutableGLES1State()->setClientStateEnabled(clientState, true); - enableVertexAttribArray(vertexArrayIndex(clientState)); + ContextPrivateEnableVertexAttribArray(getMutablePrivateState(), getMutablePrivateStateCache(), + vertexArrayIndex(clientState)); mStateCache.onGLES1ClientStateChange(this); } diff --git a/src/libANGLE/Context_gles_2_0_autogen.h b/src/libANGLE/Context_gles_2_0_autogen.h index e9372b9ddd8..d334f346dee 100644 --- a/src/libANGLE/Context_gles_2_0_autogen.h +++ b/src/libANGLE/Context_gles_2_0_autogen.h @@ -43,11 +43,9 @@ void deleteShader(ShaderProgramID shaderPacked); \ void deleteTextures(GLsizei n, const TextureID *texturesPacked); \ void detachShader(ShaderProgramID programPacked, ShaderProgramID shaderPacked); \ - void disableVertexAttribArray(GLuint index); \ void drawArrays(PrimitiveMode modePacked, GLint first, GLsizei count); \ void drawElements(PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, \ const void *indices); \ - void enableVertexAttribArray(GLuint index); \ void finish(); \ void flush(); \ void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, \ diff --git a/src/libANGLE/Context_gles_3_0_autogen.h b/src/libANGLE/Context_gles_3_0_autogen.h index 783259cd2f4..25e66fe8d41 100644 --- a/src/libANGLE/Context_gles_3_0_autogen.h +++ b/src/libANGLE/Context_gles_3_0_autogen.h @@ -102,7 +102,6 @@ GLboolean isSampler(SamplerID samplerPacked) const; \ GLboolean isSync(SyncID syncPacked) const; \ GLboolean isTransformFeedback(TransformFeedbackID idPacked) const; \ - GLboolean isVertexArray(VertexArrayID arrayPacked) const; \ void *mapBufferRange(BufferBinding targetPacked, GLintptr offset, GLsizeiptr length, \ GLbitfield access); \ void pauseTransformFeedback(); \ @@ -153,7 +152,6 @@ void uniformMatrix4x3fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \ const GLfloat *value); \ GLboolean unmapBuffer(BufferBinding targetPacked); \ - void vertexAttribDivisor(GLuint index, GLuint divisor); \ void vertexAttribIPointer(GLuint index, GLint size, VertexAttribType typePacked, \ GLsizei stride, const void *pointer); \ void waitSync(SyncID syncPacked, GLbitfield flags, GLuint64 timeout); diff --git a/src/libANGLE/Context_gles_3_1_autogen.h b/src/libANGLE/Context_gles_3_1_autogen.h index e60c78b6290..9b3676a84f6 100644 --- a/src/libANGLE/Context_gles_3_1_autogen.h +++ b/src/libANGLE/Context_gles_3_1_autogen.h @@ -121,12 +121,6 @@ GLsizei width, GLsizei height, GLboolean fixedsamplelocations); \ void useProgramStages(ProgramPipelineID pipelinePacked, GLbitfield stages, \ ShaderProgramID programPacked); \ - void validateProgramPipeline(ProgramPipelineID pipelinePacked); \ - void vertexAttribBinding(GLuint attribindex, GLuint bindingindex); \ - void vertexAttribFormat(GLuint attribindex, GLint size, VertexAttribType typePacked, \ - GLboolean normalized, GLuint relativeoffset); \ - void vertexAttribIFormat(GLuint attribindex, GLint size, VertexAttribType typePacked, \ - GLuint relativeoffset); \ - void vertexBindingDivisor(GLuint bindingindex, GLuint divisor); + void validateProgramPipeline(ProgramPipelineID pipelinePacked); #endif // ANGLE_CONTEXT_API_3_1_AUTOGEN_H_ diff --git a/src/libANGLE/Context_gles_ext_autogen.h b/src/libANGLE/Context_gles_ext_autogen.h index a2293df8f55..aca0a45865e 100644 --- a/src/libANGLE/Context_gles_ext_autogen.h +++ b/src/libANGLE/Context_gles_ext_autogen.h @@ -76,17 +76,15 @@ void getTranslatedShaderSource(ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, \ GLchar *source); \ /* GL_APPLE_clip_distance */ \ - /* GL_ARB_sync */ \ /* GL_ARM_rgba8 */ \ /* GL_ARM_shader_framebuffer_fetch */ \ /* GL_ARM_shader_framebuffer_fetch_depth_stencil */ \ + /* GL_ARM_texture_unnormalized_coordinates */ \ /* GL_EXT_EGL_image_array */ \ /* GL_EXT_EGL_image_external_wrap_modes */ \ /* GL_EXT_EGL_image_storage */ \ void eGLImageTargetTexStorage(GLenum target, egl::ImageID imagePacked, \ const GLint *attrib_list); \ - void eGLImageTargetTextureStorage(GLuint texture, egl::ImageID imagePacked, \ - const GLint *attrib_list); \ /* GL_EXT_EGL_image_storage_compression */ \ /* GL_EXT_YUV_target */ \ /* GL_EXT_base_instance */ \ @@ -142,13 +140,19 @@ void multiDrawElementsBaseVertex(PrimitiveMode modePacked, const GLsizei *count, \ DrawElementsType typePacked, const void *const *indices, \ GLsizei drawcount, const GLint *basevertex); \ + /* GL_EXT_draw_instanced */ \ /* GL_EXT_external_buffer */ \ void bufferStorageExternal(BufferBinding targetPacked, GLintptr offset, GLsizeiptr size, \ GLeglClientBufferEXT clientBuffer, GLbitfield flags); \ - void namedBufferStorageExternal(GLuint buffer, GLintptr offset, GLsizeiptr size, \ - GLeglClientBufferEXT clientBuffer, GLbitfield flags); \ /* GL_EXT_float_blend */ \ /* GL_EXT_frag_depth */ \ + /* GL_EXT_fragment_shading_rate */ \ + void framebufferShadingRate(GLenum target, GLenum attachment, GLuint texture, GLint baseLayer, \ + GLsizei numLayers, GLsizei texelWidth, GLsizei texelHeight); \ + void getFragmentShadingRates(GLsizei samples, GLsizei maxCount, GLsizei *count, \ + GLenum *shadingRates); \ + /* GL_EXT_fragment_shading_rate_attachment */ \ + /* GL_EXT_fragment_shading_rate_primitive */ \ /* GL_EXT_geometry_shader */ \ /* GL_EXT_gpu_shader5 */ \ /* GL_EXT_instanced_arrays */ \ @@ -182,6 +186,7 @@ /* GL_EXT_memory_object_fd */ \ void importMemoryFd(MemoryObjectID memoryPacked, GLuint64 size, HandleType handleTypePacked, \ GLint fd); \ + /* GL_EXT_multi_draw_arrays */ \ /* GL_EXT_multi_draw_indirect */ \ void multiDrawArraysIndirect(PrimitiveMode modePacked, const void *indirect, \ GLsizei drawcount, GLsizei stride); \ @@ -228,6 +233,7 @@ /* GL_EXT_shader_io_blocks */ \ /* GL_EXT_shader_non_constant_global_initializers */ \ /* GL_EXT_shader_texture_lod */ \ + /* GL_EXT_shader_texture_samples */ \ /* GL_EXT_shadow_samplers */ \ /* GL_EXT_tessellation_shader */ \ /* GL_EXT_texture_border_clamp */ \ @@ -253,7 +259,6 @@ /* GL_EXT_texture_sRGB_decode */ \ /* GL_EXT_texture_shadow_lod */ \ /* GL_EXT_texture_storage */ \ - void texStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); \ /* GL_EXT_texture_storage_compression */ \ void texStorageAttribs2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, \ GLsizei height, const GLint *attrib_list); \ @@ -363,6 +368,10 @@ void framebufferTextureMultiview(GLenum target, GLenum attachment, TextureID texturePacked, \ GLint level, GLint baseViewIndex, GLsizei numViews); \ /* GL_OVR_multiview2 */ \ + /* GL_OVR_multiview_multisampled_render_to_texture */ \ + void framebufferTextureMultisampleMultiview( \ + GLenum target, GLenum attachment, TextureID texturePacked, GLint level, GLsizei samples, \ + GLint baseViewIndex, GLsizei numViews); \ /* GL_QCOM_framebuffer_foveated */ \ void framebufferFoveationConfig(FramebufferID framebufferPacked, GLuint numLayers, \ GLuint focalPointsPerLayer, GLuint requestedFeatures, \ @@ -613,6 +622,10 @@ GLsizei *length, GLint64 *params); \ void getQueryObjectui64vRobust(QueryID idPacked, GLenum pname, GLsizei bufSize, \ GLsizei *length, GLuint64 *params); \ + void getFramebufferPixelLocalStorageParameterfvRobust( \ + GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); \ + void getFramebufferPixelLocalStorageParameterivRobust( \ + GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); \ /* GL_ANGLE_robust_fragment_shader_output */ \ /* GL_ANGLE_robust_resource_initialization */ \ /* GL_ANGLE_semaphore_fuchsia */ \ @@ -633,10 +646,6 @@ void framebufferPixelLocalStorageRestore(); \ void getFramebufferPixelLocalStorageParameterfv(GLint plane, GLenum pname, GLfloat *params); \ void getFramebufferPixelLocalStorageParameteriv(GLint plane, GLenum pname, GLint *params); \ - void getFramebufferPixelLocalStorageParameterfvRobust( \ - GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); \ - void getFramebufferPixelLocalStorageParameterivRobust( \ - GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params); \ /* GL_ANGLE_shader_pixel_local_storage_coherent */ \ /* GL_ANGLE_stencil_texturing */ \ /* GL_ANGLE_texture_compression_dxt3 */ \ @@ -674,7 +683,6 @@ GLboolean unpackUnmultiplyAlpha); \ /* GL_CHROMIUM_framebuffer_mixed_samples */ \ /* GL_CHROMIUM_lose_context */ \ - void loseContext(GraphicsResetStatus currentPacked, GraphicsResetStatus otherPacked); \ - /* GL_CHROMIUM_sync_query */ + void loseContext(GraphicsResetStatus currentPacked, GraphicsResetStatus otherPacked); #endif // ANGLE_CONTEXT_API_EXT_AUTOGEN_H_ diff --git a/src/libANGLE/Debug.cpp b/src/libANGLE/Debug.cpp index 62bf9537a23..de65047db7e 100644 --- a/src/libANGLE/Debug.cpp +++ b/src/libANGLE/Debug.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // Debug.cpp: Defines debug state used for GL_KHR_debug #include "libANGLE/Debug.h" @@ -149,11 +153,10 @@ void Debug::insertMessage(GLenum source, GLuint id, GLenum severity, const std::string &message, - gl::LogSeverity logSeverity, - angle::EntryPoint entryPoint) const + gl::LogSeverity logSeverity) const { std::string messageCopy(message); - insertMessage(source, type, id, severity, std::move(messageCopy), logSeverity, entryPoint); + insertMessage(source, type, id, severity, std::move(messageCopy), logSeverity); } void Debug::insertMessage(GLenum source, @@ -161,18 +164,13 @@ void Debug::insertMessage(GLenum source, GLuint id, GLenum severity, std::string &&message, - gl::LogSeverity logSeverity, - angle::EntryPoint entryPoint) const + gl::LogSeverity logSeverity) const { { // output all messages to the debug log const char *messageTypeString = GLMessageTypeToString(type); const char *severityString = GLSeverityToString(severity); std::ostringstream messageStream; - if (entryPoint != angle::EntryPoint::Invalid) - { - messageStream << GetEntryPointName(entryPoint) << ": "; - } messageStream << "GL " << messageTypeString << ": " << severityString << ": " << message; switch (logSeverity) { @@ -327,7 +325,7 @@ void Debug::setMessageControl(GLenum source, void Debug::pushGroup(GLenum source, GLuint id, std::string &&message) { insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION, - std::string(message), gl::LOG_INFO, angle::EntryPoint::GLPushDebugGroup); + std::string(message), gl::LOG_INFO); Group g; g.source = source; @@ -345,7 +343,7 @@ void Debug::popGroup() mGroups.pop_back(); insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION, - g.message, gl::LOG_INFO, angle::EntryPoint::GLPopDebugGroup); + g.message, gl::LOG_INFO); } size_t Debug::getGroupStackDepth() const @@ -363,7 +361,7 @@ void Debug::insertPerfWarning(GLenum severity, bool isLastRepeat, const char *me // Note: insertMessage will acquire GetDebugMutex(), so it must be released before this call. insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_PERFORMANCE, 0, severity, std::move(msg), - gl::LOG_INFO, angle::EntryPoint::Invalid); + gl::LOG_INFO); } bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const diff --git a/src/libANGLE/Debug.h b/src/libANGLE/Debug.h index ad308b471a7..219676418ad 100644 --- a/src/libANGLE/Debug.h +++ b/src/libANGLE/Debug.h @@ -56,15 +56,13 @@ class Debug : angle::NonCopyable GLuint id, GLenum severity, const std::string &message, - gl::LogSeverity logSeverity, - angle::EntryPoint entryPoint) const; + gl::LogSeverity logSeverity) const; void insertMessage(GLenum source, GLenum type, GLuint id, GLenum severity, std::string &&message, - gl::LogSeverity logSeverity, - angle::EntryPoint entryPoint) const; + gl::LogSeverity logSeverity) const; void setMessageControl(GLenum source, GLenum type, @@ -174,17 +172,18 @@ class Debug : angle::NonCopyable namespace { -ANGLE_INLINE bool PerfCounterBelowMaxRepeat(std::atomic *counter, bool *isLastRepeat) +ANGLE_INLINE bool MessageCounterBelowMaxRepeat(std::atomic *counter, + uint32_t maxRepeat, + bool *isLastRepeat) { - constexpr uint32_t kMaxPerfRepeat = 4; // Stop incrementing the counter after max value to avoid unnecessary cache effects - if (counter->load(std::memory_order_relaxed) < kMaxPerfRepeat) + if (counter->load(std::memory_order_relaxed) < maxRepeat) { uint32_t count = counter->fetch_add(1, std::memory_order_relaxed); // Check not strictly necessary as worst case is an additional log, but is good practice. - if (count < kMaxPerfRepeat) + if (count < maxRepeat) { - if (count == kMaxPerfRepeat - 1) + if (count == maxRepeat - 1) { *isLastRepeat = true; } @@ -196,17 +195,18 @@ ANGLE_INLINE bool PerfCounterBelowMaxRepeat(std::atomic *counter, bool } // namespace // Generate a perf warning. Only outputs the same message a few times to avoid spamming the logs. -#define ANGLE_PERF_WARNING(debug, severity, ...) \ - do \ - { \ - static std::atomic sRepeatCount = 0; \ - bool isLastRepeat = false; \ - if (PerfCounterBelowMaxRepeat(&sRepeatCount, &isLastRepeat)) \ - { \ - char ANGLE_MESSAGE[200]; \ - snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \ - (debug).insertPerfWarning(severity, isLastRepeat, ANGLE_MESSAGE); \ - } \ +#define ANGLE_PERF_WARNING(debug, severity, ...) \ + do \ + { \ + static std::atomic sRepeatCount = 0; \ + bool isLastRepeat = false; \ + constexpr uint32_t kMaxPerfRepeat = 4; \ + if (MessageCounterBelowMaxRepeat(&sRepeatCount, kMaxPerfRepeat, &isLastRepeat)) \ + { \ + char ANGLE_MESSAGE[200]; \ + snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \ + (debug).insertPerfWarning(severity, isLastRepeat, ANGLE_MESSAGE); \ + } \ } while (0) #endif // LIBANGLE_DEBUG_H_ diff --git a/src/libANGLE/Decompress_unittest.cpp b/src/libANGLE/Decompress_unittest.cpp index dd816502d8f..f354c2bd8e1 100644 --- a/src/libANGLE/Decompress_unittest.cpp +++ b/src/libANGLE/Decompress_unittest.cpp @@ -5,6 +5,10 @@ // // Decompress_unittest.cpp: Unit tests for the |(Compress/Decompress)*Blob| functions. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "libANGLE/angletypes.h" diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp index bc2147d0e3e..72fb02c02de 100644 --- a/src/libANGLE/Display.cpp +++ b/src/libANGLE/Display.cpp @@ -8,6 +8,10 @@ // display on which graphics are drawn. Implements EGLDisplay. // [EGL 1.4] section 2.1.2 page 3. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Display.h" #include @@ -29,9 +33,11 @@ #include "common/utilities.h" #include "gpu_info_util/SystemInfo.h" #include "image_util/loadimage.h" +#include "libANGLE/Constants.h" #include "libANGLE/Context.h" #include "libANGLE/Device.h" #include "libANGLE/EGLSync.h" +#include "libANGLE/ErrorStrings.h" #include "libANGLE/Image.h" #include "libANGLE/ResourceManager.h" #include "libANGLE/Stream.h" @@ -102,9 +108,8 @@ struct TLSData TLSData::TLSData() : errorScratchSpace(0) {} #if defined(ANGLE_PLATFORM_APPLE) -// TODO(angleproject:6479): Due to a bug in Apple's dyld loader, `thread_local` will cause -// excessive memory use. Temporarily avoid it by using pthread's thread -// local storage instead. +// TODO(http://anglebug.com/42264979): Due to a bug in Apple's dyld loader, `thread_local` will +// cause excessive memory use. Temporarily avoid it by using pthread's thread local storage instead. static angle::TLSIndex GetDisplayTLSIndex() { static angle::TLSIndex DisplayIndex = TLS_INVALID_INDEX; @@ -423,12 +428,17 @@ rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType, break; # elif defined(ANGLE_PLATFORM_LINUX) -# if defined(ANGLE_USE_GBM) +# if defined(ANGLE_USE_GBM) || defined(ANGLE_USE_WAYLAND) if (platformType == 0) { impl = new rx::DisplayEGL(state); break; } + if (platformType == EGL_PLATFORM_GBM_KHR) + { + impl = new rx::DisplayEGL(state); + break; + } # endif if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE) { @@ -469,12 +479,17 @@ rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType, # if defined(ANGLE_PLATFORM_WINDOWS) impl = new rx::DisplayWGL(state); # elif defined(ANGLE_PLATFORM_LINUX) -# if defined(ANGLE_USE_GBM) +# if defined(ANGLE_USE_GBM) || defined(ANGLE_USE_WAYLAND) if (platformType == 0) { impl = new rx::DisplayEGL(state); break; } + if (platformType == EGL_PLATFORM_GBM_KHR) + { + impl = new rx::DisplayEGL(state); + break; + } # endif if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE) { @@ -581,12 +596,6 @@ rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType, impl = rx::CreateVulkanFuchsiaDisplay(state); } break; -# elif defined(ANGLE_PLATFORM_GGP) - if (rx::IsVulkanGGPDisplayAvailable()) - { - impl = rx::CreateVulkanGGPDisplay(state); - } - break; # elif defined(ANGLE_PLATFORM_APPLE) if (rx::IsVulkanMacDisplayAvailable()) { @@ -947,6 +956,9 @@ Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDe mMemoryShaderCache(mBlobCache), mGlobalTextureShareGroupUsers(0), mGlobalSemaphoreShareGroupUsers(0), + mImageHandleAllocator(gl::IMPLEMENTATION_MAX_OBJECT_HANDLES), + mSurfaceHandleAllocator(gl::IMPLEMENTATION_MAX_OBJECT_HANDLES), + mSyncHandleAllocator(gl::IMPLEMENTATION_MAX_OBJECT_HANDLES), mTerminatedByApi(false) {} @@ -1148,8 +1160,10 @@ Error Display::initialize() mDevice = nullptr; } - mState.singleThreadPool = angle::WorkerThreadPool::Create(1, ANGLEPlatformCurrent()); - mState.multiThreadPool = angle::WorkerThreadPool::Create(0, ANGLEPlatformCurrent()); + mState.singleThreadPool = angle::WorkerThreadPool::Create(angle::ThreadPoolType::Synchronous, 0, + ANGLEPlatformCurrent()); + mState.multiThreadPool = angle::WorkerThreadPool::Create(angle::ThreadPoolType::Asynchronous, 0, + ANGLEPlatformCurrent()); if (kIsContextMutexEnabled) { @@ -1400,7 +1414,12 @@ Error Display::createWindowSurface(const Config *configuration, ANGLE_TRY(restoreLostDevice()); } - SurfaceID id = {mSurfaceHandleAllocator.allocate()}; + SurfaceID id; + if (!mSurfaceHandleAllocator.allocate(&id.value)) + { + return Error(EGL_BAD_ALLOC, gl::err::kHandleExhaustion); + } + SurfacePointer surface(new WindowSurface(mImplementation, id, configuration, window, attribs, mFrontendFeatures.forceRobustResourceInit.enabled), this); @@ -1430,7 +1449,12 @@ Error Display::createPbufferSurface(const Config *configuration, ANGLE_TRY(restoreLostDevice()); } - SurfaceID id = {mSurfaceHandleAllocator.allocate()}; + SurfaceID id; + if (!mSurfaceHandleAllocator.allocate(&id.value)) + { + return Error(EGL_BAD_ALLOC, gl::err::kHandleExhaustion); + } + SurfacePointer surface(new PbufferSurface(mImplementation, id, configuration, attribs, mFrontendFeatures.forceRobustResourceInit.enabled), this); @@ -1456,7 +1480,12 @@ Error Display::createPbufferFromClientBuffer(const Config *configuration, ANGLE_TRY(restoreLostDevice()); } - SurfaceID id = {mSurfaceHandleAllocator.allocate()}; + SurfaceID id; + if (!mSurfaceHandleAllocator.allocate(&id.value)) + { + return Error(EGL_BAD_ALLOC, gl::err::kHandleExhaustion); + } + SurfacePointer surface( new PbufferSurface(mImplementation, id, configuration, buftype, clientBuffer, attribs, mFrontendFeatures.forceRobustResourceInit.enabled), @@ -1482,7 +1511,12 @@ Error Display::createPixmapSurface(const Config *configuration, ANGLE_TRY(restoreLostDevice()); } - SurfaceID id = {mSurfaceHandleAllocator.allocate()}; + SurfaceID id; + if (!mSurfaceHandleAllocator.allocate(&id.value)) + { + return Error(EGL_BAD_ALLOC, gl::err::kHandleExhaustion); + } + SurfacePointer surface( new PixmapSurface(mImplementation, id, configuration, nativePixmap, attribs, mFrontendFeatures.forceRobustResourceInit.enabled), @@ -1509,10 +1543,19 @@ Error Display::createImage(const gl::Context *context, ANGLE_TRY(restoreLostDevice()); } + ImageID id; + if (!mImageHandleAllocator.allocate(&id.value)) + { + return Error(EGL_BAD_ALLOC, gl::err::kHandleExhaustion); + } + egl::ImageSibling *sibling = nullptr; if (IsTextureTarget(target)) { - sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)}); + gl::Texture *texture = + context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)}); + texture->onBindAsEglImageSource(); + sibling = texture; } else if (IsRenderbufferTarget(target)) { @@ -1528,7 +1571,6 @@ Error Display::createImage(const gl::Context *context, } ASSERT(sibling != nullptr); - ImageID id = {mImageHandleAllocator.allocate()}; angle::UniqueObjectPointer imagePtr( new Image(mImplementation, id, context, target, sibling, attribs), this); ANGLE_TRY(imagePtr->initialize(this, context)); @@ -1683,7 +1725,11 @@ Error Display::createSync(const gl::Context *currentContext, { ASSERT(isInitialized()); - SyncID id = {mSyncHandleAllocator.allocate()}; + SyncID id; + if (!mSyncHandleAllocator.allocate(&id.value)) + { + return Error(EGL_BAD_ALLOC, gl::err::kHandleExhaustion); + } if (mImplementation->testDeviceLost()) { @@ -2131,7 +2177,7 @@ static ClientExtensions GenerateClientExtensions() extensions.platformDevice = true; #endif -#if defined(ANGLE_USE_GBM) +#if defined(ANGLE_USE_GBM) || defined(ANGLE_USE_WAYLAND) extensions.platformGbmKHR = true; #endif @@ -2379,8 +2425,10 @@ void Display::initializeFrontendFeatures() ANGLE_FEATURE_CONDITION(&mFrontendFeatures, forceMinimumMaxVertexAttributes, false); - // Reject shaders with undefined behavior. In the compiler, this only applies to WebGL. - ANGLE_FEATURE_CONDITION(&mFrontendFeatures, rejectWebglShadersWithUndefinedBehavior, true); + // When the IR is built, use it by default. +#ifdef ANGLE_IR + ANGLE_FEATURE_CONDITION(&mFrontendFeatures, useIr, true); +#endif mImplementation->initializeFrontendFeatures(&mFrontendFeatures); } diff --git a/src/libANGLE/EGLSync.cpp b/src/libANGLE/EGLSync.cpp index a06ed347091..152ed32d0cf 100644 --- a/src/libANGLE/EGLSync.cpp +++ b/src/libANGLE/EGLSync.cpp @@ -27,6 +27,7 @@ Sync::Sync(rx::EGLImplFactory *factory, EGLenum type) case EGL_SYNC_GLOBAL_FENCE_ANGLE: case EGL_SYNC_NATIVE_FENCE_ANDROID: case EGL_SYNC_METAL_SHARED_EVENT_ANGLE: + case EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE: mFence = std::unique_ptr(factory->createSync()); break; diff --git a/src/libANGLE/Error.h b/src/libANGLE/Error.h index 85168ea2301..5b140e3b648 100644 --- a/src/libANGLE/Error.h +++ b/src/libANGLE/Error.h @@ -71,10 +71,11 @@ inline Error NoError() #define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y) #define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__) -#define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \ +#define ANGLE_TRY_TEMPLATE(EXPR, FINALLY, FUNC) \ do \ { \ auto ANGLE_LOCAL_VAR = EXPR; \ + FINALLY; \ if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ { \ FUNC(ANGLE_LOCAL_VAR); \ @@ -82,7 +83,8 @@ inline Error NoError() } while (0) #define ANGLE_RETURN(X) return X; -#define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN) +#define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, static_cast(0), ANGLE_RETURN) +#define ANGLE_TRY_WITH_FINALLY(EXPR, FINALLY) ANGLE_TRY_TEMPLATE(EXPR, FINALLY, ANGLE_RETURN) // TODO(jmadill): Remove after EGL error refactor. http://anglebug.com/42261727 #define ANGLE_SWALLOW_ERR(EXPR) \ @@ -151,7 +153,8 @@ inline bool IsError(bool value) return false; \ } while (0) -#define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR) +#define ANGLE_VALIDATION_TRY(EXPR) \ + ANGLE_TRY_TEMPLATE(EXPR, static_cast(0), ANGLE_HANDLE_VALIDATION_ERR) #include "Error.inc" diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h index 21e96feefae..15f336c9270 100644 --- a/src/libANGLE/ErrorStrings.h +++ b/src/libANGLE/ErrorStrings.h @@ -16,12 +16,11 @@ namespace err // clang-format off inline constexpr const char *k3DDepthStencil = "Format cannot be GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL if target is GL_TEXTURE_3D."; -inline constexpr const char *kANGLECopyTexture3DUnavailable = "GL_ANGLE_copy_texture_3d extension not available."; inline constexpr const char *kANGLECopyTextureMissingRequiredExtension = "Copy*TextureCHROMIUM from EXTERNAL_OES to integer format requires OES_EGL_image_external_essl3."; inline constexpr const char *kAdvancedBlendEquationWithMRT = "Advanced blend equation can only be used when only one draw buffer is not NONE."; -inline constexpr const char *kAdvancedBlendExtensionNotEnabled = "GL_KHR_blend_equation_advanced extension not enabled."; inline constexpr const char *kAtomicCounterResourceName = "Active atomic counter resources are not assigned name strings."; inline constexpr const char *kAttributeListNotNull = "Attribute list must be NULL or GL_NONE."; +inline constexpr const char *kAttributeNameNull = "Attribute name is null."; inline constexpr const char *kAttributeNotMatch = "Attribute is incompatible with egl image."; inline constexpr const char *kAttributeNotValid = "Attribute is not valid."; inline constexpr const char *kAttributeZeroRequiresDivisorLimitation = "The current context doesn't support setting a non-zero divisor on the attribute with index zero. Please reorder the attributes in your vertex shader so that attribute zero can have a zero divisor."; @@ -37,7 +36,6 @@ inline constexpr const char *kBlitExtensionFromInvalidAttachmentType = "Blits ar inline constexpr const char *kBlitExtensionLinear = "Linear blit not supported in this extension."; inline constexpr const char *kBlitExtensionMultisampledDepthOrStencil = "Multisampled depth/stencil blit is not supported by this extension."; inline constexpr const char *kBlitExtensionMultisampledWholeBufferBlit = "Only whole-buffer blit is supported from a multisampled read buffer in this extension."; -inline constexpr const char *kBlitExtensionNotAvailable = "Blit extension not available."; inline constexpr const char *kBlitExtensionScaleOrFlip = "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."; inline constexpr const char *kBlitExtensionToInvalidAttachmentType = "Blits are only supported to 2D texture, renderbuffer or default framebuffer attachments in this extension."; inline constexpr const char *kBlitFeedbackLoop = "Blit feedback loop: the read and draw framebuffers are the same."; @@ -53,6 +51,7 @@ inline constexpr const char *kBlitMultisampledFormatOrBoundsMismatch = "Attempt inline constexpr const char *kBlitOnlyNearestForNonColor = "Only nearest filtering can be used when blitting buffers other than the color buffer."; inline constexpr const char *kBlitSameImageColor = "Read and write color attachments cannot be the same image."; inline constexpr const char *kBlitSameImageDepthOrStencil = "Read and write depth stencil attachments cannot be the same image."; +inline constexpr const char *kBlitSameResource = "Read and write attachments cannot be the same resource."; inline constexpr const char *kBlitToMultiview = "Attempt to write to a multi-view framebuffer."; inline constexpr const char *kBlitTypeMismatchFixedOrFloat = "If the read buffer contains fixed-point or floating-point values, the draw buffer must as well."; inline constexpr const char *kBlitTypeMismatchFixedPoint = "If the read buffer contains fixed-point values, the draw buffer must as well."; @@ -88,6 +87,8 @@ inline constexpr const char *kCubemapFacesEqualDimensions = "Each cubemap face m inline constexpr const char *kCubemapIncomplete = "Texture is not cubemap complete. All cubemaps faces must be defined and be the same size."; inline constexpr const char *kCubemapInvalidDepth = "The cubemap depth must be a multiple of 6."; inline constexpr const char *kDataTypeNotAligned = "Data is not evenly divisible into the number of bytes needed to store in memory a datum indicated by type."; +inline constexpr const char *kDebugMessageNULL = "The message is null."; +inline constexpr const char *kDebugMessageControlIdsNULL = "the of DebugMessageControl cannot be null."; inline constexpr const char *kDefaultFramebuffer = "Default framebuffer is bound."; inline constexpr const char *kDefaultFramebufferAttachmentOnUserFBO = "Invalid attachment when a user framebuffer is bound."; inline constexpr const char *kDefaultFramebufferInvalidAttachment = "Invalid attachment when the default framebuffer is bound."; @@ -101,7 +102,6 @@ inline constexpr const char *kDimensionsMustBePow2 = "Texture dimensions must be inline constexpr const char *kDispatchIndirectBufferNotBound = "Dispatch indirect buffer must be bound."; inline constexpr const char *kDrawBufferMaskMismatch = "Active draw buffers with missing fragment shader outputs."; inline constexpr const char *kDrawBuffersIndexedExtensionNotAvailable = "EXT/OES_draw_buffers_indexed is not available."; -inline constexpr const char *kES31OrDrawBuffersIndexedExtensionNotAvailable = "EXT/OES_draw_buffers_indexed or ES 3.1 are required but not available."; inline constexpr const char *kDrawBufferTypeMismatch = "Fragment shader output type does not match the bound framebuffer attachment type."; inline constexpr const char *kDrawFramebufferIncomplete = "Draw framebuffer is incomplete."; inline constexpr const char *kDrawIndirectBufferNotBound = "Draw indirect buffer must be bound."; @@ -112,14 +112,20 @@ inline constexpr const char *kEGLImageTextureFormatNotSupported = "EGL image int inline constexpr const char *kEGLImageTextureTargetMismatch = "The source EGL image is incompatible with the target texture type."; inline constexpr const char *kElementArrayBufferBoundForTransformFeedback = "It is undefined behavior to use an element array buffer that is bound for transform feedback."; inline constexpr const char *kElementArrayNoBufferOrPointer = "No element array buffer and no pointer."; +inline constexpr const char *kEntryPointBaseUnsupported = "The base command requires an extension or a higher context version."; +inline constexpr const char *kEntryPointRequiresES10 = "Command requires OpenGL ES 1.0."; +inline constexpr const char *kEntryPointRequiresES10or32 = "Command requires OpenGL ES 1.0 or 3.2."; +inline constexpr const char *kEntryPointRequiresES20 = "Command requires OpenGL ES 2.0."; +inline constexpr const char *kEntryPointRequiresES30 = "Command requires OpenGL ES 3.0."; +inline constexpr const char *kEntryPointRequiresES31 = "Command requires OpenGL ES 3.1."; +inline constexpr const char *kEntryPointRequiresES32 = "Command requires OpenGL ES 3.2."; +inline constexpr const char *kEntryPointRequiresESEXT = "Command requires an extension."; inline constexpr const char *kEnumInvalid = "Invalid enum provided."; inline constexpr const char *kEnumNotSupported = "Enum 0x%04X is currently not supported."; inline constexpr const char *kEnumRequiresGLES30 = "Enum requires GLES 3.0."; inline constexpr const char *kEnumRequiresGLES31 = "Enum requires GLES 3.1."; -inline constexpr const char *kES1or32Required = "OpenGL ES 1.x or 3.2 Required."; inline constexpr const char *kES2Required = "OpenGL ES 2.0 Required."; inline constexpr const char *kES31Required = "OpenGL ES 3.1 Required."; -inline constexpr const char *kES32Required = "OpenGL ES 3.2 Required."; inline constexpr const char *kES3Required = "OpenGL ES 3.0 Required."; inline constexpr const char *kExceedsComputeWorkGroupCountX = "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]."; inline constexpr const char *kExceedsComputeWorkGroupCountY = "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]."; @@ -133,6 +139,7 @@ inline constexpr const char *kExceedsMaxDebugGroupStackDepth = "Cannot push more inline constexpr const char *kExceedsMaxDebugMessageLength = "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."; inline constexpr const char *kExceedsMaxDrawBuffers = "Draw buffer greater than MAX_DRAW_BUFFERS."; inline constexpr const char *kExceedsMaxElement = "Element value exceeds maximum element index."; +inline constexpr const char *kExceedsMaxGroupMarkerStackDepth = "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH group markers."; inline constexpr const char *kExceedsMaxImageUnits = "Index must be within [0, MAX_IMAGE_UNITS)."; inline constexpr const char *kExceedsMaxLabelLength = "Label length is larger than GL_MAX_LABEL_LENGTH."; inline constexpr const char *kExceedsMaxShaderStorageBufferBindings = "Index must be within [0, MAX_SHADER_STORAGE_BUFFER_BINDINGS)."; @@ -158,7 +165,6 @@ inline constexpr const char *kFoveatedTextureInvalidPixelDensity = "Pixel densit inline constexpr const char *kFoveatedTextureQcomExtensionRequired = "GL_QCOM_texture_foveated not enabled."; inline constexpr const char *kFragDataBindingIndexOutOfRange = "Fragment output color index must be zero or one."; inline constexpr const char *kFragmentInputTypeNotFloatingPoint = "Fragment input type is not a floating point scalar or vector."; -inline constexpr const char *kFramebufferFetchNonCoherentExtensionNotEnabled = "GL_EXT_shader_framebuffer_fetch_non_coherent not enabled."; inline constexpr const char *kFramebufferFoveationAlreadyConfigured = "glFramebufferFoveationConfigQCOM called on a framebuffer that has already been configured for foveated rendering."; inline constexpr const char *kFramebufferFoveationAttachmentChanged = "Attachments have been changed on a framebuffer configured for foveated rendering."; inline constexpr const char *kFramebufferFoveationLayersExceedMaxArrayLayers = "Requested layer exceeds the supported maximum."; @@ -214,6 +220,7 @@ inline constexpr const char *kGetImageExtensionNotEnabled = "GL_ANGLE_get_image inline constexpr const char *kGetImageCompressed = "Texture is compressed, call GetCompressedTexImage instead."; inline constexpr const char *kGetImageNotCompressed = "Texture is not compressed, call GetTexImage instead."; inline constexpr const char *kGLES1Only = "GLES1-only function."; +inline constexpr const char *kHandleExhaustion = "Handle exhaustion."; inline constexpr const char *kImageSizeMustBeZero = "imageSize must be 0 if no texture data is provided."; inline constexpr const char *kImageSizeTooSmall = "imageSize is too small."; inline constexpr const char *kImmutableMemoryObject = "The memory object is immutable."; @@ -309,6 +316,7 @@ inline constexpr const char *kInvalidFogMode = "Invalid fog mode."; inline constexpr const char *kInvalidFogParameter = "Invalid fog parameter."; inline constexpr const char *kInvalidFormat = "Invalid format."; inline constexpr const char *kInvalidFormatCombination = "Invalid combination of format, type and internalFormat."; +inline constexpr const char *kInvalidFragDataNamePointer = "Invalid fragment output name pointer."; inline constexpr const char *kInvalidFragmentInputBinding = "No such binding."; inline constexpr const char *kInvalidFramebufferAttachmentParameter = "Invalid parameter name for framebuffer attachment."; inline constexpr const char *kInvalidFramebufferLayer = "Framebuffer layer cannot be less than 0 or greater than GL_MAX_FRAMEBUFFER_LAYERS_EXT."; @@ -383,6 +391,7 @@ inline constexpr const char *kMismatchedShaderBinaryType = "Mismatched shader bi inline constexpr const char *kInvalidShaderCount = "Invalid Shader count."; inline constexpr const char *kInvalidShaderName = "Shader object expected."; inline constexpr const char *kInvalidShaderType = "Invalid shader type."; +inline constexpr const char *kInvalidShadingCombinerOp = "Invalid shading CombinerOp."; inline constexpr const char *kInvalidShadingModel = "Invalid shading model."; inline constexpr const char *kInvalidShadingRate = "Invalid shading rate."; inline constexpr const char *kInvalidSourceTexture = "Source texture is not a valid texture object."; @@ -415,6 +424,7 @@ inline constexpr const char *kInvalidTransformFeedbackName = "name is not a vali inline constexpr const char *kInvalidType = "Invalid type."; inline constexpr const char *kInvalidUniformCount = "Only array uniforms may have count > 1."; inline constexpr const char *kInvalidUniformLocation = "Invalid uniform location."; +inline constexpr const char *kInvalidUniformValuePointer = "Invalid uniform value pointer."; inline constexpr const char *kInvalidUnpackAlignment = "Unpack alignment must be 1, 2, 4 or 8."; inline constexpr const char *kInvalidUnpackParametersForWebGL = "Invalid combination of unpack parameters for WebGL."; inline constexpr const char *kInvalidExternalUsageFlags = "Usage flags must only include bits defined by GL_ANGLE_external_objects_flags."; @@ -452,18 +462,18 @@ inline constexpr const char *kMultisampleArrayExtensionOrES32Required = "GL_OES_ inline constexpr const char *kMultisampleTextureExtensionOrES31Required = "GL_ANGLE_texture_multisample or GLES 3.1 required."; inline constexpr const char *kMultiviewActive = "The number of views in the active draw framebuffer is greater than 1."; inline constexpr const char *kMultiviewMismatch = "The number of views in the active program and draw framebuffer does not match."; -inline constexpr const char *kMultiviewNotAvailable = "OVR_multiview or OVR_multiview2 are not available."; inline constexpr const char *kMultiviewReadFramebuffer = "The active read framebuffer object has multiview attachments."; inline constexpr const char *kMultiviewTimerQuery = "There is an active query for target GL_TIME_ELAPSED_EXT when the number of views in the active draw framebuffer is greater than 1."; inline constexpr const char *kMultiviewTransformFeedback = "There is an active transform feedback object when the number of views in the active draw framebuffer is greater than 1."; inline constexpr const char *kMultiviewViewsTooLarge = "numViews cannot be greater than GL_MAX_VIEWS_ANGLE."; inline constexpr const char *kMultiviewViewsTooSmall = "numViews cannot be less than 1."; inline constexpr const char *kMustHaveElementArrayBinding = "Must have element array buffer bound."; -inline constexpr const char *kNameBeginsWithGL = "Attributes that begin with 'gl_' are not allowed."; +inline constexpr const char *kNameStartsWithReservedPrefix = "Name starts with a reserved prefix."; inline constexpr const char *kNegativeAttachments = "Negative number of attachments."; inline constexpr const char *kNegativeBaseViewIndex = "Negative baseViewIndex."; inline constexpr const char *kNegativeBufSize = "Negative bufSize."; inline constexpr const char *kNegativeCount = "Negative count."; +inline constexpr const char *kNegativeDrawcount = "Negative drawcount."; inline constexpr const char *kNegativeHeightWidthDepth = "Negative height, width, or depth."; inline constexpr const char *kNegativeLayer = "Negative layer."; inline constexpr const char *kNegativeLength = "Negative length."; @@ -478,6 +488,8 @@ inline constexpr const char *kNegativeStart = "Negative start."; inline constexpr const char *kNegativeStride = "Negative stride."; inline constexpr const char *kNegativeXYZ = "Negative x, y, or z."; inline constexpr const char *kNoActiveComputeShaderStage = "No active compute shader stage in this program."; +inline constexpr const char *kNoActiveTessellationControlShaderStage = "No active tessellation control shader stage in this program."; +inline constexpr const char *kNoActiveTessellationEvaluationShaderStage = "No active tessellation evaluation shader stage in this program."; inline constexpr const char *kNoActiveGeometryShaderStage = "No active geometry shader stage in this program."; inline constexpr const char *kNoActiveGraphicsShaderStage = "It is a undefined behaviour to render without vertex shader stage or fragment shader stage."; inline constexpr const char *kNoActiveProgramWithComputeShader = "No active program for the compute shader stage."; @@ -491,7 +503,6 @@ inline constexpr const char *kNotTextureComplete = "The texture is not complete. inline constexpr const char *kNoTransformArray = "No transform array given."; inline constexpr const char *kNoTransformFeedbackOutputVariables = "The active program has specified no output variables to record."; inline constexpr const char *kNoZeroDivisor = "At least one enabled attribute must have a divisor of zero."; -inline constexpr const char *kNVFenceNotSupported = "GL_NV_fence is not supported."; inline constexpr const char *kObjectNotGenerated = "Object cannot be used because it has not been generated."; inline constexpr const char *kOffsetAlignment = "offset must be a multiple of 4."; inline constexpr const char *kOffsetAndSizeAlignment = "Offset and size must be multiple of 4."; @@ -508,25 +519,25 @@ inline constexpr const char *kPixelDataNull = "Pixel data cannot be null."; inline constexpr const char *kPixelPackBufferBoundForTransformFeedback = "It is undefined behavior to use a pixel pack buffer that is bound for transform feedback."; inline constexpr const char *kPixelUnpackBufferBoundForTransformFeedback = "It is undefined behavior to use a pixel unpack buffer that is bound for transform feedback."; inline constexpr const char *kPLSActive = "Operation not permitted while pixel local storage is active."; +inline constexpr const char *kPLSColorAttachmentReserved = "Color attachment is actively reserved for pixel local storage."; +inline constexpr const char *kActivePLSBackingTexture = "Operation not permitted on an active pixel local storage backing texture."; inline constexpr const char *kPLSCapNotAllowed = "Cap 0x%04X cannot be enabled or disabled while pixel local storage is active."; inline constexpr const char *kPLSDefaultFramebufferBound = "Default framebuffer object name 0 does not support pixel local storage."; inline constexpr const char *kPLSDimensionsDontMatchRenderingArea = "Pixel local storage backing texture dimensions not equal to the rendering area."; inline constexpr const char *kPLSDitherEnabled = "Attempted to begin pixel local storage with GL_DITHER enabled."; -inline constexpr const char *kPLSDrawBufferExceedsAttachmentLimit = "Argument <%s> must be less than MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE when pixel local storage is active."; inline constexpr const char *kPLSDrawBufferExceedsCombinedAttachmentLimit = "Argument <%s> must be less than (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE) when pixel local storage is active."; inline constexpr const char *kPLSDrawProgramActivePlanesUnused = "Active pixel local storage plane(s) are not referenced by the draw program."; inline constexpr const char *kPLSDrawProgramFormatMismatch = "Pixel local storage formats in the draw program do not match actively bound planes."; inline constexpr const char *kPLSDrawProgramPlanesInactive = "Draw program references pixel local storage plane(s) that are not currently active."; inline constexpr const char *kPLSEnablingDeinitializedPlane = "Attempted to enable a pixel local storage plane that is in a deinitialized state."; -inline constexpr const char *kPLSExtensionNotEnabled = "GL_ANGLE_shader_pixel_local_storage not enabled."; inline constexpr const char *kPLSInactive = "Pixel local storage is not active."; inline constexpr const char *kPLSInvalidInternalformat = "Invalid pixel local storage internal format."; inline constexpr const char *kPLSInvalidLoadOperation = "Invalid pixel local storage Load Operation: 0x%04X."; inline constexpr const char *kPLSInvalidStoreOperation = "Invalid pixel local storage Store Operation: 0x%04X."; inline constexpr const char *kPLSInvalidTextureType = "Invalid pixel local storage texture type."; inline constexpr const char *kPLSKeepingMemorylessPlane = "Load Operation GL_LOAD_OP_LOAD_ANGLE is invalid for memoryless planes."; +inline constexpr const char *kPLSLevelIndexOutOfRange = "Mipmap level for PLS backing texture outside the effective base/max range."; inline constexpr const char *kPLSLoadOpsNULL = " cannot be null."; -inline constexpr const char *kPLSMaxColorAttachmentsExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE."; inline constexpr const char *kPLSMaxCombinedDrawBuffersAndPlanesExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."; inline constexpr const char *kPLSMismatchedBackingTextureSizes = "Mismatched pixel local storage backing texture sizes."; inline constexpr const char *kPLSMultisamplingEnabled = "Attempted to begin pixel local storage with a multisampled framebuffer."; @@ -543,7 +554,10 @@ inline constexpr const char *kPLSPlanesOutOfRange = "Planes must be less than or inline constexpr const char *kPLSAdvancedBlendEnabled = "Attempted to begin pixel local storage with an advanced blend equation enabled."; inline constexpr const char *kPLSAdvancedBlendNotSupported = "Advanced blend equations are not supported when pixel local storage is active."; inline constexpr const char *kPLSRasterizerDiscardEnabled = "Attempted to begin pixel local storage with GL_RASTERIZER_DISCARD enabled."; +inline constexpr const char *kPLSSingleTexImageMultiplePlanes = "A single texture slice is bound to multiple active pixel local storage planes."; +inline constexpr const char *kPLSSingleTexImagePLSAndAttachment = "A single texture slice is simultaneously bound to an active pixel local storage plane and attached to an enabled drawbuffer."; inline constexpr const char *kPLSTransformFeedbackActive = "Attempted to begin pixel local storage with transform feedback active."; +inline constexpr const char *kPLSTiledRenderingActive = "Attempted to begin pixel local storage with QCOM_tiled_rendering active."; inline constexpr const char *kPLSReservedDrawBufferInUse = "When beginning pixel local storage, glDrawBuffers must all be GL_NONE at indices greater than or equal to: min(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PLS_ANGLE, GL_MAX_COMBINED_DRAW_BUFFERS_AND_PLS_PLANES_ANGLE - )."; inline constexpr const char *kPLSSecondaryBlendEnabled = "Attempted to begin pixel local storage with a blend function requiring the secondary color input."; inline constexpr const char *kPLSSecondaryBlendNotSupported = "Blend functions requiring the secondary color input are not supported when pixel local storage is active."; @@ -553,7 +567,6 @@ inline constexpr const char *kProgramInterfaceMustBeProgramOutput = "programInte inline constexpr const char *kProgramNotBound = "A program must be bound."; inline constexpr const char *kProgramNotLinked = "Program not linked."; inline constexpr const char *kQueryActive = "Query is active."; -inline constexpr const char *kQueryExtensionNotEnabled = "Query extension not enabled."; inline constexpr const char *kQueryInactive = "Query is not active."; inline constexpr const char *kQueryTargetMismatch = "Query type does not match target."; inline constexpr const char *kReadBufferNone = "Read buffer is GL_NONE."; @@ -566,8 +579,8 @@ inline constexpr const char *kResourceMaxRenderbufferSize = "Desired resource si inline constexpr const char *kResourceMaxTextureSize = "Desired resource size is greater than max texture size."; inline constexpr const char *kRobustResourceInitializationExtensionRequired = "EGL_ANGLE_robust_resource_initialization not enabled."; inline constexpr const char *kSamplerFormatMismatch = "Mismatch between texture format and sampler type (signed/unsigned/float/shadow)."; +inline constexpr const char *kSamplesOutOfRange = "Samples value is negative or greater than maximum supported value for the format."; inline constexpr const char *kSamplerUniformValueOutOfRange = "Sampler uniform value out of range."; -inline constexpr const char *kSamplesOutOfRange = "Samples must not be greater than maximum supported value for the format."; inline constexpr const char *kSamplesZero = "Samples may not be zero."; inline constexpr const char *kShaderAttachmentHasShader = "Shader attachment already has a shader."; inline constexpr const char *kShaderSourceInvalidCharacters = "Shader source contains invalid characters."; @@ -583,7 +596,6 @@ inline constexpr const char *kStrideExceedsWebGLLimit = "Stride is over the maxi inline constexpr const char *kStrideMustBeMultipleOfType = "Stride must be a multiple of the passed in datatype."; inline constexpr const char *kSyncMissing = "Sync object does not exist."; inline constexpr const char *kTessellationShaderEXTNotEnabled = "GL_EXT_tessellation_shader extension not enabled."; -inline constexpr const char *kTessellationShaderOESNotEnabled = "GL_OES_tessellation_shader extension not enabled."; inline constexpr const char *kTessellationShaderRequiresBothControlAndEvaluation = "Tessellation requires both control and evaluation shaders."; inline constexpr const char *kTessellationShaderRequiresVertexShader = "Any command that transfers vertices to the GL requires a vertex shader if the current program uses a tessellation shader."; inline constexpr const char *kTextureBufferExtensionNotAvailable = "Texture buffer extension not available."; @@ -605,8 +617,10 @@ inline constexpr const char *kTextureLevelOutOfRange = "Level is larger than tex inline constexpr const char *kTextureNotBound = "A texture must be bound."; inline constexpr const char *kTextureNotPow2 = "The texture is a non-power-of-two texture."; inline constexpr const char *kTextureRectangleNotSupported = "Context does not support GL_ANGLE_texture_rectangle."; +inline constexpr const char *kTextureAttachmentSamplesMismatch = "Samples value must be the same for all texture attachments"; inline constexpr const char *kTextureSizeTooSmall = "Texture dimensions must all be greater than zero."; inline constexpr const char *kTextureStorageCompressionExtensionRequired = "GL_EXT_texture_storage_compression not enabled."; +inline constexpr const char *kTextureTargetInvalidForCopyImage = "Texture target is TEXTURE_BUFFER or does not match the type of the texture."; inline constexpr const char *kTextureTargetMismatch = "Textarget must match the texture target type."; inline constexpr const char *kTextureTargetMismatchWithLabel = "Textarget must match the texture target type. Requested: %d Texture's: %d label: %s."; inline constexpr const char *kTextureTargetRequiresES31 = "Texture target requires at least OpenGL ES 3.1."; @@ -632,10 +646,12 @@ inline constexpr const char *kTransformFeedbackTargetActive = "Target is TRANSFO inline constexpr const char *kTransformFeedbackUseProgram = "Cannot change active program while transform feedback is unpaused."; inline constexpr const char *kTransformFeedbackVaryingIndexOutOfRange = "Index must be less than the transform feedback varying count in the program."; inline constexpr const char *kTypeNotUnsignedShortByte = "Only UNSIGNED_SHORT and UNSIGNED_BYTE types are supported."; +inline constexpr const char *kUniformBlockNameNull = "Uniform block name can not be null."; inline constexpr const char *kUniformBufferBoundForTransformFeedback = "It is undefined behavior to use an uniform buffer that is bound for transform feedback."; inline constexpr const char *kUniformBufferOffsetAlignment = "Offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."; inline constexpr const char *kUniformBufferTooSmall = "It is undefined behaviour to use a uniform buffer that is too small."; inline constexpr const char *kUniformBufferUnbound = "It is undefined behaviour to have a used but unbound uniform buffer."; +inline constexpr const char *kUniformNameNull = "Uniform name is null."; inline constexpr const char *kUniformSizeMismatch = "Uniform size does not match uniform method."; inline constexpr const char *kUniformTypeMismatch = "Uniform type does not match uniform method."; inline constexpr const char *kUnimplementedComputeShaderPrecision = "Compute shader precision not yet implemented."; @@ -646,13 +662,12 @@ inline constexpr const char *kUnsupportedFloatBlending = "GL_BLEND with floating inline constexpr const char *kUnsupportedColorMaskForSharedExponentColorBuffer = "Color writemask for a GL_RGB9_E5 draw buffer must have the same values for red, green, and blue channels."; inline constexpr const char *kVertexArrayNoBuffer = "An enabled vertex array has no buffer."; inline constexpr const char *kVertexArrayNoBufferPointer = "An enabled vertex array has no buffer and no pointer."; +inline constexpr const char *kVertexAttributeValueNULL = "Vertex attribute cannot be null."; inline constexpr const char *kVertexBufferBoundForTransformFeedback = "It is undefined behavior to use a vertex buffer that is bound for transform feedback."; inline constexpr const char *kVertexShaderTypeMismatch = "Vertex shader input type does not match the type of the bound vertex attribute."; inline constexpr const char *kViewportNegativeSize = "Negative viewport size."; inline constexpr const char *kViewsExceedMaxArrayLayers = "baseViewIndex+numViews cannot be greater than GL_MAX_ARRAY_TEXTURE_LAYERS."; -inline constexpr const char *kWebgl2NameLengthLimitExceeded = "Location lengths must not be greater than 1024 characters."; -inline constexpr const char *kWebglBindAttribLocationReservedPrefix = "Attributes that begin with 'webgl_', or '_webgl_' are not allowed."; -inline constexpr const char *kWebglNameLengthLimitExceeded = "Location name lengths must not be greater than 256 characters."; +inline constexpr const char *kWebGLNameLengthLimitExceeded = "Name is longer than %d characters."; inline constexpr const char *kYUVOutputMissmatch = "Program and framebuffer YUV output state does not match."; inline constexpr const char *kYUVTargetExtensionRequired = "GL_EXT_YUV_target not enabled."; inline constexpr const char *kZeroBoundToTarget = "Zero is bound to target."; @@ -662,7 +677,11 @@ inline constexpr const char *kProgramPipelineDoesNotExist = "Program pipeline do inline constexpr const char *kNotAllStagesOfSeparableProgramUsed = "A program object is active for at least one, but not all of the shader stages that were present when the program was linked."; inline constexpr const char *kNoExecutableCodeInstalled = "There is no current program object specified by UseProgram, there is a current program pipeline object, and that object is empty (no executable code is installed for any stage)."; inline constexpr const char *kProgramPipelineLinkFailed = "Program pipeline link failed."; +inline constexpr const char *kProgramPipelineInfoLogNULL = "Program pipeline infolog cannot be null."; inline constexpr const char *kProtectedTexturesExtensionRequired = "GL_EXT_protected_textures not enabled."; +inline constexpr const char *kTextureCompressionASTCDecodeModeExtensionRequired = "GL_EXT_texture_compression_astc_decode_mode not enabled."; +inline constexpr const char *kTextureCompressionASTCDecodeModeRGB9E5ExtensionRequired = "GL_EXT_texture_compression_astc_decode_mode_rgb9e5 not enabled."; +inline constexpr const char *kProgramNotValid = "Program is not a program object."; // clang-format on } // namespace err diff --git a/src/libANGLE/Fence.h b/src/libANGLE/Fence.h index 5939bfb19cb..ed0ae84953b 100644 --- a/src/libANGLE/Fence.h +++ b/src/libANGLE/Fence.h @@ -30,7 +30,7 @@ class FenceNV final : angle::NonCopyable { public: explicit FenceNV(rx::GLImplFactory *factory); - virtual ~FenceNV(); + ~FenceNV(); void onDestroy(const gl::Context *context); angle::Result set(const Context *context, GLenum condition); diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp index 1b01eac27a0..9031f4b99b8 100644 --- a/src/libANGLE/Framebuffer.cpp +++ b/src/libANGLE/Framebuffer.cpp @@ -7,6 +7,10 @@ // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Framebuffer.h" #include "common/Optional.h" @@ -60,7 +64,7 @@ FramebufferStatus CheckMultiviewStateMatchesForCompleteness( if (checkAttachment->getBaseViewIndex() + checkAttachment->getNumViews() > checkAttachment->getSize().depth) { - return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, + return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, err::kFramebufferIncompleteMultiviewBaseViewMismatch); } @@ -138,8 +142,11 @@ FramebufferStatus CheckAttachmentCompleteness(const Context *context, // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is // the effective maximum texture level defined in the Mipmapping discussion of // section 3.8.10.4. - if (attachmentMipLevel < texture->getBaseLevel() || - attachmentMipLevel > texture->getMipmapMaxLevel()) + // The above condition works only if FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not + // the same as levelbase. + if (attachmentMipLevel != texture->getBaseLevel() && + (attachmentMipLevel < texture->getBaseLevel() || + attachmentMipLevel > texture->getMipmapMaxLevel())) { return FramebufferStatus::Incomplete( GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, @@ -212,13 +219,14 @@ FramebufferStatus CheckAttachmentSampleCompleteness(const Context *context, { ASSERT(attachment.isAttached()); + GLsizei currRenderToTextureSamples = attachment.getRenderToTextureSamples(); if (attachment.type() == GL_TEXTURE) { const Texture *texture = attachment.getTexture(); ASSERT(texture); GLenum sizedInternalFormat = attachment.getFormat().info->sizedInternalFormat; const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); - if (static_cast(attachment.getSamples()) > formatCaps.getMaxSamples()) + if (static_cast(attachment.getSamples()) > formatCaps.sampleCounts.getMaxSamples()) { return FramebufferStatus::Incomplete( GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, @@ -243,10 +251,11 @@ FramebufferStatus CheckAttachmentSampleCompleteness(const Context *context, { // Only check against RenderToTextureSamples if they actually exist. if (renderToTextureSamples->value() != - FramebufferAttachment::kDefaultRenderToTextureSamples) + FramebufferAttachment::kDefaultRenderToTextureSamples || + currRenderToTextureSamples != FramebufferAttachment::kDefaultRenderToTextureSamples) { FramebufferStatus sampleCountStatus = - CheckAttachmentSampleCounts(context, attachment.getRenderToTextureSamples(), + CheckAttachmentSampleCounts(context, currRenderToTextureSamples, renderToTextureSamples->value(), colorAttachment); if (!sampleCountStatus.isComplete()) { @@ -263,7 +272,8 @@ FramebufferStatus CheckAttachmentSampleCompleteness(const Context *context, { // RenderToTextureSamples takes precedence if they exist. if (renderToTextureSamples->value() == - FramebufferAttachment::kDefaultRenderToTextureSamples) + FramebufferAttachment::kDefaultRenderToTextureSamples || + currRenderToTextureSamples == FramebufferAttachment::kDefaultRenderToTextureSamples) { FramebufferStatus sampleCountStatus = CheckAttachmentSampleCounts( @@ -303,6 +313,22 @@ angle::Result InitAttachment(const Context *context, FramebufferAttachment *atta return angle::Result::Continue; } +bool ImageIndexOverlapsWithSampleTexture(const gl::ImageIndex &index, + const Texture *texture, + const Sampler *sampler) +{ + GLuint attachmentLevel = static_cast(index.getLevelIndex()); + GLuint textureEffectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel(); + GLuint textureMaxLevel = textureEffectiveBaseLevel; + if ((sampler && IsMipmapFiltered(sampler->getSamplerState().getMinFilter())) || + IsMipmapFiltered(texture->getSamplerState().getMinFilter())) + { + textureMaxLevel = texture->getMipmapMaxLevel(); + } + + return attachmentLevel >= textureEffectiveBaseLevel && attachmentLevel <= textureMaxLevel; +} + bool AttachmentOverlapsWithTexture(const FramebufferAttachment &attachment, const Texture *texture, const Sampler *sampler) @@ -312,17 +338,23 @@ bool AttachmentOverlapsWithTexture(const FramebufferAttachment &attachment, return false; } - const gl::ImageIndex &index = attachment.getTextureImageIndex(); - GLuint attachmentLevel = static_cast(index.getLevelIndex()); - GLuint textureEffectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel(); - GLuint textureMaxLevel = textureEffectiveBaseLevel; - if ((sampler && IsMipmapFiltered(sampler->getSamplerState().getMinFilter())) || - IsMipmapFiltered(texture->getSamplerState().getMinFilter())) + const gl::ImageIndex &index = attachment.getTextureImageIndex(); + return ImageIndexOverlapsWithSampleTexture(index, texture, sampler); +} + +bool PixelLocalStoragePlaneOverlapsWithTexture(const PixelLocalStoragePlane &plane, + const Texture *texture, + const Sampler *sampler) +{ + ASSERT(plane.isActive()); + + if (plane.getTextureID() != texture->id()) { - textureMaxLevel = texture->getMipmapMaxLevel(); + return false; } - return attachmentLevel >= textureEffectiveBaseLevel && attachmentLevel <= textureMaxLevel; + const gl::ImageIndex &index = plane.getTextureImageIndex(); + return ImageIndexOverlapsWithSampleTexture(index, texture, sampler); } constexpr ComponentType GetAttachmentComponentType(GLenum componentType) @@ -372,7 +404,7 @@ FramebufferState::FramebufferState(rx::UniqueSerial serial) mLabel(), mColorAttachments(1), mColorAttachmentsMask(0), - mDrawBufferStates(1, GL_BACK), + mDrawBufferStates(1, GL_NONE), mReadBufferState(GL_BACK), mDrawBufferTypeMask(), mDefaultWidth(0), @@ -510,42 +542,6 @@ const FramebufferAttachment *FramebufferState::getReadPixelsAttachment(GLenum re } } -const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const -{ - auto *colorAttachment = getFirstColorAttachment(); - if (colorAttachment) - { - return colorAttachment; - } - return getDepthOrStencilAttachment(); -} - -const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const -{ - for (const FramebufferAttachment &colorAttachment : mColorAttachments) - { - if (colorAttachment.isAttached()) - { - return &colorAttachment; - } - } - - return nullptr; -} - -const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const -{ - if (mDepthAttachment.isAttached()) - { - return &mDepthAttachment; - } - if (mStencilAttachment.isAttached()) - { - return &mStencilAttachment; - } - return nullptr; -} - const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const { if (mStencilAttachment.isAttached()) @@ -915,6 +911,11 @@ egl::Error Framebuffer::setSurfaces(const Context *context, // Ensure the backend has a chance to synchronize its content for a new backbuffer. mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0); + mState.mDrawBufferStates[0] = GL_BACK; + } + else + { + mState.mDrawBufferStates[0] = GL_NONE; } setReadSurface(context, readSurface); @@ -1337,7 +1338,7 @@ FramebufferStatus Framebuffer::checkStatusWithGLFrontEnd(const Context *context) // in GLES 2.0, all color attachments attachments must have the same number of bitplanes // in GLES 3.0, there is no such restriction - if (state.getClientMajorVersion() < 3) + if (state.getClientVersion() < ES_3_0) { if (colorbufferSize.valid()) { @@ -1515,7 +1516,7 @@ FramebufferStatus Framebuffer::checkStatusWithGLFrontEnd(const Context *context) } // Starting from ES 3.0 stencil and depth, if present, should be the same image - if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() && + if (state.getClientVersion() >= ES_3_0 && depthAttachment.isAttached() && stencilAttachment.isAttached() && stencilAttachment != depthAttachment) { return FramebufferStatus::Incomplete( @@ -1602,7 +1603,7 @@ FramebufferStatus Framebuffer::checkStatusWithGLFrontEnd(const Context *context) // In ES 2.0 and WebGL, all color attachments must have the same width and height. // In ES 3.0, there is no such restriction. - if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibilityANGLE) && + if ((state.getClientVersion() < ES_3_0 || state.getExtensions().webglCompatibilityANGLE) && !mState.attachmentsHaveSameDimensions()) { return FramebufferStatus::Incomplete( @@ -1801,7 +1802,7 @@ angle::Result Framebuffer::readPixels(const Context *context, if (packBuffer) { - packBuffer->onDataChanged(); + packBuffer->onDataChanged(context); } return angle::Result::Continue; @@ -1930,7 +1931,7 @@ void Framebuffer::setAttachment(const Context *context, ASSERT(info); GLenum sizedInternalFormat = info->sizedInternalFormat; const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); - samples = formatCaps.getNearestSamples(samples); + samples = formatCaps.sampleCounts.getNearestSamples(samples); } // Context may be null in unit tests. @@ -1982,6 +1983,19 @@ void Framebuffer::setAttachmentMultiview(const Context *context, FramebufferAttachment::kDefaultRenderToTextureSamples); } +void Framebuffer::setAttachmentMultisampleMultiview(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei samples, + GLsizei numViews, + GLint baseViewIndex) +{ + setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true, + samples); +} + void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context, GLsizei numViews, GLuint baseViewIndex, @@ -2199,23 +2213,26 @@ void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::Subject return; } - // Swapchain changes should only result in color buffer changes. - if (message == angle::SubjectMessage::SwapchainImageChanged) - { - if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX) - { - mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index); - onStateChange(angle::SubjectMessage::DirtyBitsFlagged); - } - return; - } - ASSERT(message != angle::SubjectMessage::BindingChanged); // This can be triggered by external changes to the default framebuffer. if (message == angle::SubjectMessage::SurfaceChanged) { - onStateChange(angle::SubjectMessage::SurfaceChanged); + // Ignore notification for the depth and stencil bindings. + if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX) + { + // Surface only has single color attachment. + ASSERT(index == 0); + // During syncState the bit must be already set, skip setting it again. + ASSERT(!mDirtyBitsGuard.valid() || + mDirtyBitsGuard.value().test(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0)); + if (!mDirtyBitsGuard.valid()) + { + mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0); + onStateChange(angle::SubjectMessage::DirtyBitsFlagged); + } + onStateChange(angle::SubjectMessage::SurfaceChanged); + } return; } @@ -2297,6 +2314,8 @@ bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const const ActiveTextureMask &activeTextures = executable->getActiveSamplersMask(); const ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes(); + PixelLocalStorage *pls = peekPixelLocalStorage(); + for (size_t textureIndex : activeTextures) { unsigned int uintIndex = static_cast(textureIndex); @@ -2323,6 +2342,19 @@ bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const { return true; } + + if (pls != nullptr) + { + ASSERT(glState.getPixelLocalStorageActivePlanes() > 0); + for (GLsizei i = 0; i < glState.getPixelLocalStorageActivePlanes(); ++i) + { + if (PixelLocalStoragePlaneOverlapsWithTexture(pls->getPlane(i), texture, + sampler)) + { + return true; + } + } + } } } @@ -2427,11 +2459,6 @@ void Framebuffer::setFlipY(bool flipY) invalidateCompletenessCache(); } -GLsizei Framebuffer::getNumViews() const -{ - return mState.getNumViews(); -} - GLint Framebuffer::getBaseViewIndex() const { return mState.getBaseViewIndex(); diff --git a/src/libANGLE/Framebuffer.h b/src/libANGLE/Framebuffer.h index 3d565721c0b..b584b0dcf8c 100644 --- a/src/libANGLE/Framebuffer.h +++ b/src/libANGLE/Framebuffer.h @@ -118,15 +118,7 @@ class FramebufferState final : angle::NonCopyable bool isMultiview() const; - ANGLE_INLINE GLsizei getNumViews() const - { - const FramebufferAttachment *attachment = getFirstNonNullAttachment(); - if (attachment == nullptr) - { - return FramebufferAttachment::kDefaultNumViews; - } - return attachment->getNumViews(); - } + GLsizei getNumViews() const; GLint getBaseViewIndex() const; @@ -243,6 +235,14 @@ class Framebuffer final : public angle::ObserverInterface, FramebufferAttachmentObject *resource, GLsizei numViews, GLint baseViewIndex); + void setAttachmentMultisampleMultiview(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei samples, + GLsizei numViews, + GLint baseViewIndex); void resetAttachment(const Context *context, GLenum binding); bool detachTexture(Context *context, TextureID texture); @@ -269,7 +269,7 @@ class Framebuffer final : public angle::ObserverInterface, const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const; bool isMultiview() const; bool readDisallowedByMultiview() const; - GLsizei getNumViews() const; + ANGLE_INLINE GLsizei getNumViews() const { return mState.getNumViews(); } GLint getBaseViewIndex() const; Extents getExtents() const; @@ -478,6 +478,12 @@ class Framebuffer final : public angle::ObserverInterface, // Detaches the the pixel local storage object so the Context can call deleteContextObjects(). std::unique_ptr detachPixelLocalStorage(); + void onSwapChainImageChanged() + { + mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0); + onStateChange(angle::SubjectMessage::DirtyBitsFlagged); + } + static const FramebufferID kDefaultDrawFramebufferHandle; private: @@ -578,6 +584,52 @@ inline bool FramebufferState::isDefault() const using UniqueFramebufferPointer = angle::UniqueObjectPointer; +ANGLE_INLINE const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const +{ + auto *colorAttachment = getFirstColorAttachment(); + if (colorAttachment) + { + return colorAttachment; + } + return getDepthOrStencilAttachment(); +} + +ANGLE_INLINE const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const +{ + for (const FramebufferAttachment &colorAttachment : mColorAttachments) + { + if (colorAttachment.isAttached()) + { + return &colorAttachment; + } + } + + return nullptr; +} + +ANGLE_INLINE const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const +{ + if (mDepthAttachment.isAttached()) + { + return &mDepthAttachment; + } + if (mStencilAttachment.isAttached()) + { + return &mStencilAttachment; + } + return nullptr; +} + +ANGLE_INLINE GLsizei FramebufferState::getNumViews() const +{ + const FramebufferAttachment *attachment = getFirstNonNullAttachment(); + if (attachment == nullptr) + { + return FramebufferAttachment::kDefaultNumViews; + } + return attachment->getNumViews(); +} + } // namespace gl #endif // LIBANGLE_FRAMEBUFFER_H_ diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp index 7ba301c68ed..11726ee52e9 100644 --- a/src/libANGLE/FramebufferAttachment.cpp +++ b/src/libANGLE/FramebufferAttachment.cpp @@ -130,6 +130,15 @@ void FramebufferAttachment::attach(const Context *context, mBaseViewIndex = baseViewIndex; mIsMultiview = isMultiview; mRenderToTextureSamples = type == GL_RENDERBUFFER ? kDefaultRenderToTextureSamples : samples; + if (mIsMultiview) + { + // Multiview framebuffer attachments can only be created through: + // 1) glFramebufferTextureMultiviewOVR + // 2) glNamedFramebufferTextureMultiviewOVR + // 3) glFramebufferTextureMultisampleMultiviewOVR + // All of the above method require the attachment to be texture, not renderbuffer. + ASSERT(type != GL_RENDERBUFFER); + } resource->onAttach(context, framebufferSerial); if (mResource != nullptr) @@ -142,32 +151,32 @@ void FramebufferAttachment::attach(const Context *context, GLuint FramebufferAttachment::getRedSize() const { - return getSize().empty() ? 0 : getFormat().info->redBits; + return isSpecified() ? getFormat().info->redBits : 0; } GLuint FramebufferAttachment::getGreenSize() const { - return getSize().empty() ? 0 : getFormat().info->greenBits; + return isSpecified() ? getFormat().info->greenBits : 0; } GLuint FramebufferAttachment::getBlueSize() const { - return getSize().empty() ? 0 : getFormat().info->blueBits; + return isSpecified() ? getFormat().info->blueBits : 0; } GLuint FramebufferAttachment::getAlphaSize() const { - return getSize().empty() ? 0 : getFormat().info->alphaBits; + return isSpecified() ? getFormat().info->alphaBits : 0; } GLuint FramebufferAttachment::getDepthSize() const { - return getSize().empty() ? 0 : getFormat().info->depthBits; + return isSpecified() ? getFormat().info->depthBits : 0; } GLuint FramebufferAttachment::getStencilSize() const { - return getSize().empty() ? 0 : getFormat().info->stencilBits; + return isSpecified() ? getFormat().info->stencilBits : 0; } GLenum FramebufferAttachment::getComponentType() const diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h index 4c1537547a0..9632c4f4453 100644 --- a/src/libANGLE/FramebufferAttachment.h +++ b/src/libANGLE/FramebufferAttachment.h @@ -120,6 +120,8 @@ class FramebufferAttachment final bool isRenderToTexture() const; GLsizei getRenderToTextureSamples() const; + // Explicitly resolves attachment size to use before state synchronization (e.g. validation). + angle::Result ensureSizeResolved(const Context *context) const; // The size of the underlying resource the attachment points to. The 'depth' value will // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and // Renderbuffers, it will always be 1. @@ -172,6 +174,8 @@ class FramebufferAttachment final static const GLint kDefaultRenderToTextureSamples; private: + bool isSpecified() const; + angle::Result getRenderTargetImpl(const Context *context, GLsizei samples, rx::FramebufferAttachmentRenderTarget **rtOut) const; @@ -222,6 +226,8 @@ class FramebufferAttachmentObject : public angle::Subject, public angle::Observe FramebufferAttachmentObject(); ~FramebufferAttachmentObject() override; + virtual angle::Result ensureSizeResolved(const Context *context) const = 0; + virtual bool isAttachmentSpecified(const ImageIndex &imageIndex) const = 0; virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0; virtual Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const = 0; virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0; @@ -265,6 +271,18 @@ inline const ImageIndex &FramebufferAttachment::getTextureImageIndex() const return mTarget.textureIndex(); } +inline angle::Result FramebufferAttachment::ensureSizeResolved(const Context *context) const +{ + ASSERT(mResource); + return mResource->ensureSizeResolved(context); +} + +inline bool FramebufferAttachment::isSpecified() const +{ + ASSERT(mResource); + return mResource->isAttachmentSpecified(mTarget.textureIndex()); +} + inline Extents FramebufferAttachment::getSize() const { ASSERT(mResource); diff --git a/src/libANGLE/GLES1Renderer.cpp b/src/libANGLE/GLES1Renderer.cpp index 2fec5a4db5b..f5dc051e1c8 100644 --- a/src/libANGLE/GLES1Renderer.cpp +++ b/src/libANGLE/GLES1Renderer.cpp @@ -6,6 +6,10 @@ // GLES1Renderer.cpp: Implements the GLES1Renderer renderer. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/GLES1Renderer.h" #include @@ -14,8 +18,10 @@ #include #include "common/hash_utils.h" +#include "common/span.h" #include "libANGLE/Context.h" #include "libANGLE/Context.inl.h" +#include "libANGLE/ErrorStrings.h" #include "libANGLE/Program.h" #include "libANGLE/ResourceManager.h" #include "libANGLE/Shader.h" @@ -60,7 +66,7 @@ bool operator!=(const GLES1ShaderState &a, const GLES1ShaderState &b) size_t GLES1ShaderState::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } GLES1Renderer::GLES1Renderer() : mRendererProgramInitialized(false) {} @@ -145,17 +151,26 @@ angle::Result GLES1Renderer::prepareForDraw(PrimitiveMode mode, } } + // In case of zero texture bound to draw, do not try to update the vertex attribute array. + // However, if the zero texture is enabled on the currently active texture unit, we need to + // update the vertex attribute array. + unsigned int clientActiveTexture = gles1State->getClientTextureUnit(); + bool isTextureEnabled = + tex2DEnables[clientActiveTexture] || texCubeEnables[clientActiveTexture]; + const bool needToUpdateVertexAttribArray = !context->isZeroTextureBound(TextureType::_2D) || + !context->isZeroTextureBound(TextureType::CubeMap) || + isTextureEnabled; + // If texture has been disabled on the active sampler, texture coordinate data should not be // used. However, according to the spec, a rasterized fragment is passed on unaltered to the // next stage. - if (gles1State->isDirty(GLES1State::DIRTY_GLES1_TEXTURE_UNIT_ENABLE)) + if (gles1State->isDirty(GLES1State::DIRTY_GLES1_TEXTURE_UNIT_ENABLE) && + needToUpdateVertexAttribArray) { - unsigned int clientActiveTexture = gles1State->getClientTextureUnit(); - bool isTextureEnabled = - tex2DEnables[clientActiveTexture] || texCubeEnables[clientActiveTexture]; - glState->setEnableVertexAttribArray( + context->getMutablePrivateState()->setEnableVertexAttribArray( TexCoordArrayIndex(clientActiveTexture), isTextureEnabled && gles1State->isTexCoordArrayEnabled(clientActiveTexture)); + context->getStateCache().onGLES1TextureStateChange(context); } @@ -648,16 +663,18 @@ angle::Result GLES1Renderer::compileShader(Context *context, rx::ContextImpl *implementation = context->getImplementation(); const Limitations &limitations = implementation->getNativeLimitations(); - ShaderProgramID shader = mShaderPrograms->createShader(implementation, limitations, shaderType); + if (!mShaderPrograms->createShader(implementation, limitations, shaderType, shaderOut)) + { + ANGLE_CHECK(context, false, err::kHandleExhaustion, GL_OUT_OF_MEMORY); + return angle::Result::Stop; + } - Shader *shaderObject = getShader(shader); + Shader *shaderObject = getShader(*shaderOut); ANGLE_CHECK(context, shaderObject, "Missing shader object", GL_INVALID_OPERATION); shaderObject->setSource(context, 1, &src, nullptr); shaderObject->compile(context, angle::JobResultExpectancy::Immediate); - *shaderOut = shader; - if (!shaderObject->isCompiled(context)) { GLint infoLogLength = shaderObject->getInfoLogLength(context); @@ -680,17 +697,19 @@ angle::Result GLES1Renderer::linkProgram(Context *context, const angle::HashMap &attribLocs, ShaderProgramID *programOut) { - ShaderProgramID program = mShaderPrograms->createProgram(context->getImplementation()); + if (!mShaderPrograms->createProgram(context->getImplementation(), programOut)) + { + ANGLE_CHECK(context, false, err::kHandleExhaustion, GL_OUT_OF_MEMORY); + return angle::Result::Stop; + } - Program *programObject = getProgram(program); + Program *programObject = getProgram(*programOut); ANGLE_CHECK(context, programObject, "Missing program object", GL_INVALID_OPERATION); - *programOut = program; - programObject->attachShader(context, getShader(vertexShader)); programObject->attachShader(context, getShader(fragmentShader)); - for (auto it : attribLocs) + for (const auto &it : attribLocs) { GLint index = it.first; const std::string &name = it.second; @@ -1043,8 +1062,8 @@ angle::Result GLES1Renderer::initializeRendererProgram(Context *context, ss2d << "tex_sampler" << i; sscube << "tex_cube_sampler" << i; - programState.tex2DSamplerLocs[i] = executable.getUniformLocation(ss2d.str().c_str()); - programState.texCubeSamplerLocs[i] = executable.getUniformLocation(sscube.str().c_str()); + programState.tex2DSamplerLocs[i] = executable.getUniformLocation(ss2d.str()); + programState.texCubeSamplerLocs[i] = executable.getUniformLocation(sscube.str()); } programState.textureEnvColorLoc = executable.getUniformLocation("texture_env_color"); @@ -1222,12 +1241,14 @@ void GLES1Renderer::setAttributesEnabled(Context *context, if (mask.test(index)) { gles1State->setClientStateEnabled(attrib, true); - context->enableVertexAttribArray(index); + ContextPrivateEnableVertexAttribArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index); } else { gles1State->setClientStateEnabled(attrib, false); - context->disableVertexAttribArray(index); + ContextPrivateDisableVertexAttribArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index); } } @@ -1238,12 +1259,14 @@ void GLES1Renderer::setAttributesEnabled(Context *context, if (mask.test(index)) { gles1State->setTexCoordArrayEnabled(i, true); - context->enableVertexAttribArray(index); + ContextPrivateEnableVertexAttribArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index); } else { gles1State->setTexCoordArrayEnabled(i, false); - context->disableVertexAttribArray(index); + ContextPrivateDisableVertexAttribArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index); } } } diff --git a/src/libANGLE/GLES1State.cpp b/src/libANGLE/GLES1State.cpp index 90ddc57c80a..c653a75a10a 100644 --- a/src/libANGLE/GLES1State.cpp +++ b/src/libANGLE/GLES1State.cpp @@ -7,6 +7,10 @@ // GLES1State.cpp: Implements the GLES1State class, tracking state // for GLES1 contexts. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/GLES1State.h" #include "libANGLE/Context.h" diff --git a/src/libANGLE/GlobalMutex.cpp b/src/libANGLE/GlobalMutex.cpp index c4a25360633..8c3fdb2e77e 100644 --- a/src/libANGLE/GlobalMutex.cpp +++ b/src/libANGLE/GlobalMutex.cpp @@ -8,6 +8,7 @@ #include "libANGLE/GlobalMutex.h" #include +#include #include #include "common/debug.h" diff --git a/src/libANGLE/HandleAllocator.cpp b/src/libANGLE/HandleAllocator.cpp index 3dfebe94aac..08d59957c13 100644 --- a/src/libANGLE/HandleAllocator.cpp +++ b/src/libANGLE/HandleAllocator.cpp @@ -14,6 +14,7 @@ #include #include "common/debug.h" +#include "common/mathutil.h" namespace gl { @@ -23,34 +24,16 @@ struct HandleAllocator::HandleRangeComparator bool operator()(const HandleRange &range, GLuint handle) const { return (range.end < handle); } }; -HandleAllocator::HandleAllocator() - : mBaseValue(1), - mNextValue(1), - mMaxValue(std::numeric_limits::max()), - mLoggingEnabled(false) -{ - mUnallocatedList.push_back(HandleRange(1, mMaxValue)); -} - HandleAllocator::HandleAllocator(GLuint maximumHandleValue) - : mBaseValue(1), mNextValue(1), mMaxValue(maximumHandleValue), mLoggingEnabled(false) + : mMaxValue(maximumHandleValue), mLoggingEnabled(false) { mUnallocatedList.push_back(HandleRange(1, mMaxValue)); } HandleAllocator::~HandleAllocator() {} -void HandleAllocator::setBaseHandle(GLuint value) -{ - ASSERT(mBaseValue == mNextValue); - mBaseValue = value; - mNextValue = value; -} - -GLuint HandleAllocator::allocate() +bool HandleAllocator::allocate(GLuint *outId) { - ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty()); - // Allocate from released list, logarithmic time for pop_heap. if (!mReleasedList.empty()) { @@ -63,7 +46,16 @@ GLuint HandleAllocator::allocate() WARN() << "HandleAllocator::allocate reusing " << reusedHandle << std::endl; } - return reusedHandle; + if (outId) + { + *outId = reusedHandle; + } + return true; + } + + if (mUnallocatedList.empty()) + { + return false; } // Allocate from unallocated list, constant time. @@ -78,7 +70,9 @@ GLuint HandleAllocator::allocate() } else { - listIt->begin++; + angle::CheckedNumeric checkedBegin = listIt->begin; + checkedBegin++; + listIt->begin = checkedBegin.ValueOrDie(); } if (mLoggingEnabled) @@ -86,7 +80,11 @@ GLuint HandleAllocator::allocate() WARN() << "HandleAllocator::allocate allocating " << freeListHandle << std::endl; } - return freeListHandle; + if (outId) + { + *outId = freeListHandle; + } + return true; } void HandleAllocator::release(GLuint handle) @@ -96,18 +94,27 @@ void HandleAllocator::release(GLuint handle) WARN() << "HandleAllocator::release releasing " << handle << std::endl; } + if (handle >= mMaxValue) + { + // Handle is outside the range of allocated handles, do not reclaim it. + return; + } + // Try consolidating the ranges first. for (HandleRange &handleRange : mUnallocatedList) { - if (handleRange.begin - 1 == handle) + angle::CheckedNumeric checkedBegin = handleRange.begin; + angle::CheckedNumeric checkedEnd = handleRange.end; + + if ((checkedBegin - 1).ValueOrDie() == handle) { - handleRange.begin--; + handleRange.begin = (checkedBegin - 1).ValueOrDie(); return; } - if (handleRange.end == handle - 1) + if (checkedEnd.ValueOrDie() == (handle - 1)) { - handleRange.end++; + handleRange.end = (checkedEnd + 1).ValueOrDie(); return; } } @@ -124,6 +131,13 @@ void HandleAllocator::reserve(GLuint handle) WARN() << "HandleAllocator::reserve reserving " << handle << std::endl; } + if (handle >= mMaxValue) + { + // Handle being reserved is outside the range of allocated handles. Allow this and don't + // update the tracking. + return; + } + // Clear from released list -- might be a slow operation. if (!mReleasedList.empty()) { @@ -176,8 +190,6 @@ void HandleAllocator::reset() mUnallocatedList.clear(); mUnallocatedList.push_back(HandleRange(1, mMaxValue)); mReleasedList.clear(); - mBaseValue = 1; - mNextValue = 1; } bool HandleAllocator::anyHandleAvailableForAllocation() const diff --git a/src/libANGLE/HandleAllocator.h b/src/libANGLE/HandleAllocator.h index 670bc7280e1..bf36818e2a7 100644 --- a/src/libANGLE/HandleAllocator.h +++ b/src/libANGLE/HandleAllocator.h @@ -20,16 +20,11 @@ namespace gl class HandleAllocator final : angle::NonCopyable { public: - // Maximum handle = MAX_UINT-1 - HandleAllocator(); - // Specify maximum handle value. Used for testing. - HandleAllocator(GLuint maximumHandleValue); + explicit HandleAllocator(GLuint maximumHandleValue); ~HandleAllocator(); - void setBaseHandle(GLuint value); - - GLuint allocate(); + bool allocate(GLuint *outId); void release(GLuint handle); void reserve(GLuint handle); void reset(); @@ -38,8 +33,6 @@ class HandleAllocator final : angle::NonCopyable void enableLogging(bool enabled); private: - GLuint mBaseValue; - GLuint mNextValue; const GLuint mMaxValue; // Represents an inclusive range [begin, end] diff --git a/src/libANGLE/HandleAllocator_unittest.cpp b/src/libANGLE/HandleAllocator_unittest.cpp index 01a24e615da..53766039fb4 100644 --- a/src/libANGLE/HandleAllocator_unittest.cpp +++ b/src/libANGLE/HandleAllocator_unittest.cpp @@ -6,6 +6,10 @@ // Unit tests for HandleAllocator. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "gmock/gmock.h" @@ -16,9 +20,11 @@ namespace { +constexpr GLuint kMaxHandleForTesting = std::numeric_limits::max(); + TEST(HandleAllocatorTest, ReservationsWithGaps) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); std::set allocationList; for (GLuint id = 2; id < 50; id += 2) @@ -34,7 +40,8 @@ TEST(HandleAllocatorTest, ReservationsWithGaps) std::set allocatedList; for (size_t allocationNum = 0; allocationNum < allocationList.size() * 2; ++allocationNum) { - GLuint handle = allocator.allocate(); + GLuint handle = 0; + EXPECT_TRUE(allocator.allocate(&handle)); EXPECT_EQ(0u, allocationList.count(handle)); EXPECT_EQ(0u, allocatedList.count(handle)); allocatedList.insert(handle); @@ -43,7 +50,7 @@ TEST(HandleAllocatorTest, ReservationsWithGaps) TEST(HandleAllocatorTest, Random) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); std::set allocationList; for (size_t iterationCount = 0; iterationCount < 40; ++iterationCount) @@ -60,7 +67,8 @@ TEST(HandleAllocatorTest, Random) for (size_t normalCount = 0; normalCount < 40; ++normalCount) { - GLuint normalHandle = allocator.allocate(); + GLuint normalHandle = 0; + EXPECT_TRUE(allocator.allocate(&normalHandle)); EXPECT_EQ(0u, allocationList.count(normalHandle)); allocationList.insert(normalHandle); } @@ -74,7 +82,8 @@ TEST(HandleAllocatorTest, Reallocation) for (GLuint count = 1; count < 10; count++) { - GLuint result = limitedAllocator.allocate(); + GLuint result = 0; + EXPECT_TRUE(limitedAllocator.allocate(&result)); EXPECT_EQ(count, result); } @@ -88,47 +97,50 @@ TEST(HandleAllocatorTest, Reallocation) limitedAllocator.reserve(count); } - GLint finalResult = limitedAllocator.allocate(); - EXPECT_EQ(finalResult, 1); + GLuint finalResult = 0; + EXPECT_TRUE(limitedAllocator.allocate(&finalResult)); + EXPECT_EQ(finalResult, 1u); } // The following test covers reserving a handle with max uint value. See // http://anglebug.com/42260058 TEST(HandleAllocatorTest, ReserveMaxUintHandle) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); GLuint maxUintHandle = std::numeric_limits::max(); allocator.reserve(maxUintHandle); - GLuint normalHandle = allocator.allocate(); + GLuint normalHandle = 0; + EXPECT_TRUE(allocator.allocate(&normalHandle)); EXPECT_EQ(1u, normalHandle); } // The following test covers reserving a handle with max uint value minus one then max uint value. TEST(HandleAllocatorTest, ReserveMaxUintHandle2) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); GLuint maxUintHandle = std::numeric_limits::max(); allocator.reserve(maxUintHandle - 1); allocator.reserve(maxUintHandle); - GLuint normalHandle = allocator.allocate(); + GLuint normalHandle = 0; + EXPECT_TRUE(allocator.allocate(&normalHandle)); EXPECT_EQ(1u, normalHandle); } // To test if the allocator keep the handle in a sorted order. TEST(HandleAllocatorTest, SortedOrderHandle) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); allocator.reserve(3); GLuint allocatedList[5]; for (GLuint count = 0; count < 5; count++) { - allocatedList[count] = allocator.allocate(); + EXPECT_TRUE(allocator.allocate(&allocatedList[count])); } EXPECT_EQ(1u, allocatedList[0]); @@ -141,14 +153,18 @@ TEST(HandleAllocatorTest, SortedOrderHandle) // Tests the reset method. TEST(HandleAllocatorTest, Reset) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); for (int iteration = 0; iteration < 1; ++iteration) { allocator.reserve(3); - EXPECT_EQ(1u, allocator.allocate()); - EXPECT_EQ(2u, allocator.allocate()); - EXPECT_EQ(4u, allocator.allocate()); + GLuint handle = 0; + EXPECT_TRUE(allocator.allocate(&handle)); + EXPECT_EQ(1u, handle); + EXPECT_TRUE(allocator.allocate(&handle)); + EXPECT_EQ(2u, handle); + EXPECT_TRUE(allocator.allocate(&handle)); + EXPECT_EQ(4u, handle); allocator.reset(); } } @@ -161,10 +177,15 @@ TEST(HandleAllocatorTest, ResetAndReallocate) const std::unordered_set expectedHandles = {1, 2, 3}; std::unordered_set handles; + auto allocateHandle = [&]() { + GLuint handle = 0; + EXPECT_TRUE(allocator.allocate(&handle)); + handles.insert(handle); + }; EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), true); - handles.insert(allocator.allocate()); - handles.insert(allocator.allocate()); - handles.insert(allocator.allocate()); + allocateHandle(); + allocateHandle(); + allocateHandle(); EXPECT_EQ(expectedHandles, handles); EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), false); @@ -172,9 +193,9 @@ TEST(HandleAllocatorTest, ResetAndReallocate) allocator.reset(); EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), true); - handles.insert(allocator.allocate()); - handles.insert(allocator.allocate()); - handles.insert(allocator.allocate()); + allocateHandle(); + allocateHandle(); + allocateHandle(); EXPECT_EQ(expectedHandles, handles); EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), false); } @@ -182,15 +203,16 @@ TEST(HandleAllocatorTest, ResetAndReallocate) // Covers a particular bug with reserving and allocating sub ranges. TEST(HandleAllocatorTest, ReserveAndAllocateIterated) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); for (int iteration = 0; iteration < 3; ++iteration) { allocator.reserve(5); allocator.reserve(6); - GLuint a = allocator.allocate(); - GLuint b = allocator.allocate(); - GLuint c = allocator.allocate(); + GLuint a = 0, b = 0, c = 0; + EXPECT_TRUE(allocator.allocate(&a)); + EXPECT_TRUE(allocator.allocate(&b)); + EXPECT_TRUE(allocator.allocate(&c)); allocator.release(c); allocator.release(a); allocator.release(b); @@ -202,11 +224,11 @@ TEST(HandleAllocatorTest, ReserveAndAllocateIterated) // This test reproduces invalid heap bug when reserve resources after release. TEST(HandleAllocatorTest, ReserveAfterReleaseBug) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); for (int iteration = 1; iteration <= 16; ++iteration) { - allocator.allocate(); + EXPECT_TRUE(allocator.allocate(nullptr)); } allocator.release(15); @@ -219,19 +241,19 @@ TEST(HandleAllocatorTest, ReserveAfterReleaseBug) allocator.reserve(1); - allocator.allocate(); + EXPECT_TRUE(allocator.allocate(nullptr)); } // This test is to verify that we consolidate handle ranges when releasing a handle. TEST(HandleAllocatorTest, ConsolidateRangeDuringRelease) { - gl::HandleAllocator allocator; + gl::HandleAllocator allocator(kMaxHandleForTesting); // Reserve GLuint(-1) allocator.reserve(static_cast(-1)); // Allocate a few others - allocator.allocate(); - allocator.allocate(); + EXPECT_TRUE(allocator.allocate(nullptr)); + EXPECT_TRUE(allocator.allocate(nullptr)); // Release GLuint(-1) allocator.release(static_cast(-1)); @@ -239,8 +261,38 @@ TEST(HandleAllocatorTest, ConsolidateRangeDuringRelease) // Allocate one more handle. // Since we consolidate handle ranges during a release we do not expect to get back a // handle value of GLuint(-1). - GLuint handle = allocator.allocate(); + GLuint handle = 0; + EXPECT_TRUE(allocator.allocate(&handle)); EXPECT_NE(handle, static_cast(-1)); } +// Test that HandleAllocator::allocate returns false when there are no more available handles. +TEST(HandleAllocatorTest, HandleExhaustion) +{ + constexpr size_t kCount = 16; + gl::HandleAllocator allocator(kCount); + + // Use all available handles + std::vector handles; + for (size_t iteration = 0; iteration < kCount; ++iteration) + { + GLuint handle; + EXPECT_TRUE(allocator.allocate(&handle)); + handles.push_back(handle); + } + + // allocations should fail + EXPECT_FALSE(allocator.allocate(nullptr)); + EXPECT_FALSE(allocator.anyHandleAvailableForAllocation()); + + // Release one handle, the next allocation should succeed + allocator.release(handles[0]); + EXPECT_TRUE(allocator.anyHandleAvailableForAllocation()); + EXPECT_TRUE(allocator.allocate(nullptr)); + + // The allocator is full again, allocations should fail + EXPECT_FALSE(allocator.allocate(nullptr)); + EXPECT_FALSE(allocator.anyHandleAvailableForAllocation()); +} + } // anonymous namespace diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp index ffb7a103a62..a1f7cdba713 100644 --- a/src/libANGLE/Image.cpp +++ b/src/libANGLE/Image.cpp @@ -129,6 +129,16 @@ void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const mTargetOf->setInitState(initState); } +angle::Result ImageSibling::ensureSizeResolved(const gl::Context *context) const +{ + return angle::Result::Continue; +} + +bool ImageSibling::isAttachmentSpecified(const gl::ImageIndex &imageIndex) const +{ + return !getAttachmentSize(imageIndex).empty(); +} + bool ImageSibling::isRenderable(const gl::Context *context, GLenum binding, const gl::ImageIndex &imageIndex) const diff --git a/src/libANGLE/Image.h b/src/libANGLE/Image.h index c86ffe6fd7c..fdb54a872bb 100644 --- a/src/libANGLE/Image.h +++ b/src/libANGLE/Image.h @@ -49,6 +49,8 @@ class ImageSibling : public gl::FramebufferAttachmentObject gl::InitState sourceEGLImageInitState() const; void setSourceEGLImageInitState(gl::InitState initState) const; + angle::Result ensureSizeResolved(const gl::Context *context) const override; + bool isAttachmentSpecified(const gl::ImageIndex &imageIndex) const override; bool isRenderable(const gl::Context *context, GLenum binding, const gl::ImageIndex &imageIndex) const override; diff --git a/src/libANGLE/ImageIndex.cpp b/src/libANGLE/ImageIndex.cpp index de88a0cca7a..c8dc3691cac 100644 --- a/src/libANGLE/ImageIndex.cpp +++ b/src/libANGLE/ImageIndex.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // ImageIndex.cpp: Implementation for ImageIndex methods. #include "libANGLE/ImageIndex.h" diff --git a/src/libANGLE/ImageIndexIterator_unittest.cpp b/src/libANGLE/ImageIndexIterator_unittest.cpp index 9a7a51160c7..bf99b1d42e4 100644 --- a/src/libANGLE/ImageIndexIterator_unittest.cpp +++ b/src/libANGLE/ImageIndexIterator_unittest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/src/libANGLE/IndexRangeCache.cpp b/src/libANGLE/IndexRangeCache.cpp index d16b2bd9c75..90da82c4863 100644 --- a/src/libANGLE/IndexRangeCache.cpp +++ b/src/libANGLE/IndexRangeCache.cpp @@ -81,18 +81,7 @@ void IndexRangeCache::clear() mIndexRangeCache.clear(); } -IndexRangeCache::IndexRangeKey::IndexRangeKey() - : IndexRangeCache::IndexRangeKey(DrawElementsType::InvalidEnum, 0, 0, false) -{} - -IndexRangeCache::IndexRangeKey::IndexRangeKey(DrawElementsType type_, - size_t offset_, - size_t count_, - bool primitiveRestartEnabled_) - : type(type_), offset(offset_), count(count_), primitiveRestartEnabled(primitiveRestartEnabled_) -{} - -bool IndexRangeCache::IndexRangeKey::operator<(const IndexRangeKey &rhs) const +bool IndexRangeKey::operator<(const IndexRangeKey &rhs) const { if (type != rhs.type) { diff --git a/src/libANGLE/IndexRangeCache.h b/src/libANGLE/IndexRangeCache.h index 0a0c22fe044..c6c5a30e781 100644 --- a/src/libANGLE/IndexRangeCache.h +++ b/src/libANGLE/IndexRangeCache.h @@ -20,6 +20,19 @@ namespace gl { +struct IndexRangeKey +{ + IndexRangeKey() = default; + IndexRangeKey(DrawElementsType type, size_t offset, size_t count, bool primitiveRestart); + bool operator<(const IndexRangeKey &rhs) const; + bool operator==(const IndexRangeKey &rhs) const; + + DrawElementsType type{DrawElementsType::InvalidEnum}; + size_t offset{0}; + size_t count{0}; + bool primitiveRestartEnabled{false}; +}; + class IndexRangeCache { public: @@ -41,23 +54,54 @@ class IndexRangeCache void clear(); private: - struct IndexRangeKey - { - IndexRangeKey(); - IndexRangeKey(DrawElementsType type, size_t offset, size_t count, bool primitiveRestart); + std::map mIndexRangeCache; +}; - bool operator<(const IndexRangeKey &rhs) const; +// First level cache stored inline at the query site. +class IndexRangeInlineCache +{ + public: + IndexRangeInlineCache() = default; + IndexRangeInlineCache(DrawElementsType type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + IndexRange indexRange) + : mPayload(std::move(indexRange)), mKey(type, offset, count, primitiveRestartEnabled) + {} - DrawElementsType type; - size_t offset; - size_t count; - bool primitiveRestartEnabled; - }; + bool get(DrawElementsType type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + IndexRange *indexRangeOut) + { + if (mKey == IndexRangeKey(type, offset, count, primitiveRestartEnabled)) + { + *indexRangeOut = mPayload; + return true; + } + return false; + } - typedef std::map IndexRangeMap; - IndexRangeMap mIndexRangeCache; + private: + IndexRange mPayload{IndexRange::Undefined{}}; + IndexRangeKey mKey; }; +inline IndexRangeKey::IndexRangeKey(DrawElementsType type_, + size_t offset_, + size_t count_, + bool primitiveRestartEnabled_) + : type(type_), offset(offset_), count(count_), primitiveRestartEnabled(primitiveRestartEnabled_) +{} + +inline bool IndexRangeKey::operator==(const IndexRangeKey &rhs) const +{ + return type == rhs.type && offset == rhs.offset && count == rhs.count && + primitiveRestartEnabled == rhs.primitiveRestartEnabled; +} + } // namespace gl #endif // LIBANGLE_INDEXRANGECACHE_H_ diff --git a/src/libANGLE/InfoLog.h b/src/libANGLE/InfoLog.h index 53333ea1aae..2aa09d466b0 100644 --- a/src/libANGLE/InfoLog.h +++ b/src/libANGLE/InfoLog.h @@ -9,6 +9,8 @@ #ifndef LIBANGLE_INFOLOG_H_ #define LIBANGLE_INFOLOG_H_ +#include + namespace gl { @@ -21,7 +23,7 @@ class InfoLog : angle::NonCopyable size_t getLength() const; void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; - void appendSanitized(const char *message); + void appendSanitized(std::string message); void reset(); // This helper class ensures we append a newline after writing a line. diff --git a/src/libANGLE/MemoryProgramCache.cpp b/src/libANGLE/MemoryProgramCache.cpp index ec2047d4a83..17c51c93874 100644 --- a/src/libANGLE/MemoryProgramCache.cpp +++ b/src/libANGLE/MemoryProgramCache.cpp @@ -7,6 +7,10 @@ // always have to be re-compiled. Can be used in conjunction with the platform // layer to warm up the cache from disk. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + // Include zlib first, otherwise FAR gets defined elsewhere. #define USE_SYSTEM_ZLIB #include "compression_utils_portable.h" @@ -84,8 +88,8 @@ void MemoryProgramCache::ComputeHash(const Context *context, // Add some ANGLE metadata and Context properties, such as version and back-end. hashStream.writeString(angle::GetANGLEShaderProgramVersion()); hashStream.writeInt(angle::GetANGLESHVersion()); - hashStream.writeInt(context->getClientMajorVersion()); - hashStream.writeInt(context->getClientMinorVersion()); + hashStream.writeInt(context->getClientVersion().getMajor()); + hashStream.writeInt(context->getClientVersion().getMinor()); hashStream.writeString(reinterpret_cast(context->getString(GL_RENDERER))); // Hash pre-link program properties. @@ -104,7 +108,7 @@ void MemoryProgramCache::ComputeHash(const Context *context, hashStream.writeBool(context->getShareGroup()->getFrameCaptureShared()->enabled()); // Call the secure SHA hashing function. - const std::vector &programKey = hashStream.getData(); + std::vector programKey = hashStream.takeData(); angle::base::SHA1HashBytes(programKey.data(), programKey.size(), hashOut->data()); } @@ -185,6 +189,17 @@ angle::Result MemoryProgramCache::putProgram(const egl::BlobCache::Key &programH ANGLE_TRY(program->serialize(context)); const angle::MemoryBuffer &serializedProgram = program->getSerializedBinary(); + if (serializedProgram.size() > kMaxUncompressedProgramSize) + { + std::ostringstream warningMessage; + warningMessage << "Program is too large to cache: "; + warningMessage << "program size: " << serializedProgram.size() + << ", max size: " << kMaxUncompressedProgramSize; + ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, "%s", + warningMessage.str().c_str()); + return angle::Result::Continue; + } + angle::MemoryBuffer compressedData; if (!angle::CompressBlob(serializedProgram.size(), serializedProgram.data(), &compressedData)) { diff --git a/src/libANGLE/MemoryShaderCache.cpp b/src/libANGLE/MemoryShaderCache.cpp index beda1808d0e..a995b704d06 100644 --- a/src/libANGLE/MemoryShaderCache.cpp +++ b/src/libANGLE/MemoryShaderCache.cpp @@ -94,6 +94,17 @@ angle::Result MemoryShaderCache::putShader(const Context *context, angle::MemoryBuffer serializedShader; ANGLE_TRY(shader->serialize(nullptr, &serializedShader)); + if (serializedShader.size() > kMaxUncompressedShaderSize) + { + std::ostringstream warningMessage; + warningMessage << "Shader is too large to cache: "; + warningMessage << "shader size: " << serializedShader.size() + << ", max size: " << kMaxUncompressedShaderSize; + ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, "%s", + warningMessage.str().c_str()); + return angle::Result::Continue; + } + size_t compressedSize; if (!mBlobCache.compressAndPut(context, shaderHash, std::move(serializedShader), &compressedSize)) diff --git a/src/libANGLE/Observer.cpp b/src/libANGLE/Observer.cpp index 75f51648a4c..f50d0d89cd8 100644 --- a/src/libANGLE/Observer.cpp +++ b/src/libANGLE/Observer.cpp @@ -88,6 +88,12 @@ ObserverBinding &ObserverBinding::operator=(const ObserverBinding &other) void ObserverBinding::bind(Subject *subject) { ASSERT(getObserver() || !subject); + + if (subject == mSubject) + { + return; + } + if (mSubject) { mSubject->removeObserver(this); diff --git a/src/libANGLE/Observer.h b/src/libANGLE/Observer.h index 060aedd6d6a..e8ef628e025 100644 --- a/src/libANGLE/Observer.h +++ b/src/libANGLE/Observer.h @@ -56,11 +56,11 @@ enum class SubjectMessage // to prevent having to flush pending commands and waiting for the GPU to become idle. InternalMemoryAllocationChanged, + // Indicate VkImage gets reallocated due to tile memory fallback. Only used by vulkan backend + VkImageChanged, + // Indicates an external change to the default framebuffer. SurfaceChanged, - // Indicates the system framebuffer's swapchain changed, i.e. color buffer changed but no - // depth/stencil buffer change. - SwapchainImageChanged, // Indicates a separable program's textures or images changed in the ProgramExecutable. ProgramTextureOrImageBindingChanged, diff --git a/src/libANGLE/OverlayWidgets.cpp b/src/libANGLE/OverlayWidgets.cpp index 21a8ea14da1..9fdee434005 100644 --- a/src/libANGLE/OverlayWidgets.cpp +++ b/src/libANGLE/OverlayWidgets.cpp @@ -9,6 +9,10 @@ // could respect them too, if they implement the overlay. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Overlay.h" #include "libANGLE/Overlay_font_autogen.h" diff --git a/src/libANGLE/PixelLocalStorage.cpp b/src/libANGLE/PixelLocalStorage.cpp index 77851582157..114dd0b70d9 100644 --- a/src/libANGLE/PixelLocalStorage.cpp +++ b/src/libANGLE/PixelLocalStorage.cpp @@ -8,6 +8,10 @@ // gl::PixelLocalStorage and gl::PixelLocalStoragePlane for // ANGLE_shader_pixel_local_storage. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/PixelLocalStorage.h" #include @@ -82,63 +86,110 @@ class ScopedDisableScissor : angle::NonCopyable private: Context *const mContext; - const GLint mScissorTestEnabled; + const bool mScissorTestEnabled; +}; + +class ScopedDisableRasterizerDiscard : angle::NonCopyable +{ + public: + ScopedDisableRasterizerDiscard(Context *context) + : mContext(context), + mRasterizerDiscardEnabled(mContext->getState().isRasterizerDiscardEnabled()) + { + if (mRasterizerDiscardEnabled) + { + ContextPrivateDisable(mContext->getMutablePrivateState(), + mContext->getMutablePrivateStateCache(), GL_RASTERIZER_DISCARD); + } + } + + ~ScopedDisableRasterizerDiscard() + { + if (mRasterizerDiscardEnabled) + { + ContextPrivateEnable(mContext->getMutablePrivateState(), + mContext->getMutablePrivateStateCache(), GL_RASTERIZER_DISCARD); + } + } + + private: + Context *const mContext; + const bool mRasterizerDiscardEnabled; }; class ScopedEnableColorMask : angle::NonCopyable { public: - ScopedEnableColorMask(Context *context, int numDrawBuffers) - : mContext(context), mNumDrawBuffers(numDrawBuffers) + ScopedEnableColorMask(Context *context, int firstDrawBuffer, int numDrawBuffers) + : mContext(context), mFirstDrawBuffer(firstDrawBuffer), mNumDrawBuffers(numDrawBuffers) { const State &state = mContext->getState(); + mSavedColorMasks = state.getBlendStateExt().getColorMaskBits(); if (!mContext->getExtensions().drawBuffersIndexedAny()) { - std::array &mask = mSavedColorMasks[0]; - state.getBlendStateExt().getColorMaskIndexed(0, &mask[0], &mask[1], &mask[2], &mask[3]); - ContextPrivateColorMask(mContext->getMutablePrivateState(), - mContext->getMutablePrivateStateCache(), GL_TRUE, GL_TRUE, - GL_TRUE, GL_TRUE); + const uint8_t colorMask = + BlendStateExt::ColorMaskStorage::GetValueIndexed(0, mSavedColorMasks); + if (colorMask != BlendStateExt::kColorMaskRGBA) + { + ContextPrivateColorMask(mContext->getMutablePrivateState(), + mContext->getMutablePrivateStateCache(), GL_TRUE, GL_TRUE, + GL_TRUE, GL_TRUE); + } } else { - for (int i = 0; i < mNumDrawBuffers; ++i) + const int endDrawBuffer = mFirstDrawBuffer + mNumDrawBuffers; + for (int i = mFirstDrawBuffer; i < endDrawBuffer; ++i) { - std::array &mask = mSavedColorMasks[i]; - state.getBlendStateExt().getColorMaskIndexed(i, &mask[0], &mask[1], &mask[2], - &mask[3]); - ContextPrivateColorMaski(mContext->getMutablePrivateState(), - mContext->getMutablePrivateStateCache(), i, GL_TRUE, - GL_TRUE, GL_TRUE, GL_TRUE); + const uint8_t colorMask = + BlendStateExt::ColorMaskStorage::GetValueIndexed(i, mSavedColorMasks); + if (colorMask != BlendStateExt::kColorMaskRGBA) + { + ContextPrivateColorMaski(mContext->getMutablePrivateState(), + mContext->getMutablePrivateStateCache(), i, GL_TRUE, + GL_TRUE, GL_TRUE, GL_TRUE); + } } } } ~ScopedEnableColorMask() { + bool r, g, b, a; if (!mContext->getExtensions().drawBuffersIndexedAny()) { - const std::array &mask = mSavedColorMasks[0]; - ContextPrivateColorMask(mContext->getMutablePrivateState(), - mContext->getMutablePrivateStateCache(), mask[0], mask[1], - mask[2], mask[3]); + const uint8_t colorMask = + BlendStateExt::ColorMaskStorage::GetValueIndexed(0, mSavedColorMasks); + if (colorMask != BlendStateExt::kColorMaskRGBA) + { + BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a); + ContextPrivateColorMask(mContext->getMutablePrivateState(), + mContext->getMutablePrivateStateCache(), r, g, b, a); + } } else { - for (int i = 0; i < mNumDrawBuffers; ++i) + const int endDrawBuffer = mFirstDrawBuffer + mNumDrawBuffers; + for (int i = mFirstDrawBuffer; i < endDrawBuffer; ++i) { - const std::array &mask = mSavedColorMasks[i]; - ContextPrivateColorMaski(mContext->getMutablePrivateState(), - mContext->getMutablePrivateStateCache(), i, mask[0], - mask[1], mask[2], mask[3]); + const uint8_t colorMask = + BlendStateExt::ColorMaskStorage::GetValueIndexed(i, mSavedColorMasks); + if (colorMask != BlendStateExt::kColorMaskRGBA) + { + BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a); + ContextPrivateColorMaski(mContext->getMutablePrivateState(), + mContext->getMutablePrivateStateCache(), i, r, g, b, + a); + } } } } private: Context *const mContext; + const int mFirstDrawBuffer; const int mNumDrawBuffers; - DrawBuffersArray> mSavedColorMasks; + BlendStateExt::ColorMaskStorage::Type mSavedColorMasks; }; } // namespace @@ -297,7 +348,12 @@ void PixelLocalStoragePlane::ensureBackingTextureIfMemoryless(Context *context, ASSERT(mTextureID.value == 0); // Create a new texture that backs the memoryless plane. - mTextureID = context->createTexture(); + if (!context->createTexture(&mTextureID)) + { + context->handleExhaustionError(angle::EntryPoint::GLBeginPixelLocalStorageANGLE); + return; + } + { ScopedBindTexture2D scopedBindTexture2D(context, mTextureID); context->bindTexture(TextureType::_2D, mTextureID); @@ -317,13 +373,13 @@ void PixelLocalStoragePlane::attachToDrawFramebuffer(Context *context, GLenum co ASSERT(!isDeinitialized()); // Call ensureBackingTextureIfMemoryless() first! ASSERT(mTextureID.value != 0 && context->getTexture(mTextureID) != nullptr); - if (mTextureImageIndex.usesTex3D()) // GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY. + if (mTextureImageIndex.usesTex3D()) // GL_TEXTURE_2D_ARRAY or GL_TEXTURE_CUBE_MAP_ARRAY { context->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment, mTextureID, mTextureImageIndex.getLevelIndex(), mTextureImageIndex.getLayerIndex()); } - else + else // GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP { context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER, colorAttachment, mTextureImageIndex.getTarget(), mTextureID, @@ -387,12 +443,16 @@ void PixelLocalStoragePlane::issueClearCommand(ClearCommands *clearCommands, break; } case GL_RGBA8I: + case GL_R32I: { std::array clearValue = {0, 0, 0, 0}; if (loadop == GL_LOAD_OP_CLEAR_ANGLE) { clearValue = mClearValuei; - ClampArray(clearValue, -128, 127); + if (mInternalformat == GL_RGBA8I) + { + ClampArray(clearValue, -128, 127); + } } clearCommands->cleariv(target, clearValue.data()); break; @@ -534,25 +594,6 @@ void PixelLocalStorage::begin(Context *context, GLsizei n, const GLenum loadops[ plane.markActive(true); } - // Disable blend and enable the full color mask on the draw buffers reserved for PLS. - const Caps &caps = context->getCaps(); - GLint firstPLSDrawBuffer = FirstOverriddenDrawBuffer(caps, n); - PrivateState *privateState = context->getMutablePrivateState(); - if (firstPLSDrawBuffer == 0) - { - privateState->setBlend(false); - privateState->setColorMask(true, true, true, true); - } - else - { - ASSERT(context->getExtensions().drawBuffersIndexedAny()); - for (GLint i = firstPLSDrawBuffer; i < caps.maxDrawBuffers; ++i) - { - privateState->setBlendIndexed(false, i); - privateState->setColorMaskIndexed(true, true, true, true, i); - } - } - onBegin(context, n, loadops, plsExtents); } @@ -568,7 +609,6 @@ void PixelLocalStorage::end(Context *context, GLsizei n, const GLenum storeops[] void PixelLocalStorage::barrier(Context *context) { - ASSERT(!context->getExtensions().shaderPixelLocalStorageCoherentANGLE); onBarrier(context); } @@ -651,7 +691,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage } Framebuffer *framebuffer = state.getDrawFramebuffer(); - if (mPLSOptions.renderPassNeedsAMDRasterOrderGroupsWorkaround) + if (context->getLimitations().noRasterOrderGroupWithoutAttachmentZero) { // anglebug.com/42266263 -- Metal [[raster_order_group()]] does not work for read_write // textures on AMD when the render pass doesn't have a color attachment on slot 0. To @@ -664,7 +704,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage // to a PLS plane and attaching it to the draw framebuffer. Enabling this workaround on // any other platform would yield incorrect results. // This flag is set to true iff the framebuffer has an attachment 0 and it is enabled. - mHadColorAttachment0 = framebuffer->getDrawBufferMask().test(0); + mHadColorAttachment0 = framebuffer->getColorAttachment(0) != nullptr; if (!mHadColorAttachment0) { // Indexed color masks are always available on Metal. @@ -729,6 +769,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage context->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mScratchFramebufferForClearing); } ScopedDisableScissor scopedDisableScissor(context); + ScopedDisableRasterizerDiscard scopedDisableRasterizerDiscard(context); // Bind and clear the PLS planes. size_t maxClearedAttachments = 0; @@ -748,7 +789,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage } } // Clear in batches in order to be more efficient with GL state. - ScopedEnableColorMask scopedEnableColorMask(context, + ScopedEnableColorMask scopedEnableColorMask(context, 0, static_cast(pendingClears.size())); ClearBufferCommands clearBufferCommands(context); for (size_t drawBufferIdx = 0; drawBufferIdx < pendingClears.size(); ++drawBufferIdx) @@ -797,7 +838,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage } mSavedImageBindings.clear(); - if (mPLSOptions.renderPassNeedsAMDRasterOrderGroupsWorkaround) + if (context->getLimitations().noRasterOrderGroupWithoutAttachmentZero) { if (!mHadColorAttachment0) { @@ -914,6 +955,7 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage if (needsClear) { ScopedDisableScissor scopedDisableScissor(context); + ScopedDisableRasterizerDiscard scopedDisableRasterizerDiscard(context); ClearBufferCommands clearBufferCommands(context); for (GLsizei i = 0; i < n; ++i) { @@ -921,17 +963,15 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage if (loadop != GL_LOAD_OP_LOAD_ANGLE) { GLuint drawBufferIdx = GetDrawBufferIdx(caps, i); + ScopedEnableColorMask scopedEnableColorMask(context, drawBufferIdx, 1); getPlane(i).issueClearCommand(&clearBufferCommands, drawBufferIdx, loadop); } } } - if (!context->getExtensions().shaderPixelLocalStorageCoherentANGLE) - { - // Insert a barrier if we aren't coherent, since the textures may have been rendered to - // previously. - barrier(context); - } + // Insert a barrier in case the app performs any noncoherent accesses, since the textures + // may have been accessed as attachments immediately before this call. + barrier(context); } void onEnd(Context *context, GLsizei n, const GLenum storeops[]) override @@ -974,9 +1014,24 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage context->drawBuffers(static_cast(mSavedDrawBuffers.size()), mSavedDrawBuffers.data()); mSavedDrawBuffers.clear(); + + // Insert a barrier in case the app performed any noncoherent accesses, since the textures + // may be accessed as attachments immediately after this call. + barrier(context); } - void onBarrier(Context *context) override { context->framebufferFetchBarrier(); } + void onBarrier(Context *context) override + { + if (context->getExtensions().shaderFramebufferFetchNonCoherentEXT) + { + context->framebufferFetchBarrier(); + } + else + { + // Ignore barriers if we don't have EXT_shader_framebuffer_fetch_non_coherent. + ASSERT(context->getExtensions().shaderPixelLocalStorageCoherentANGLE); + } + } private: static GLuint GetDrawBufferIdx(const Caps &caps, GLuint plsPlaneIdx) diff --git a/src/libANGLE/PixelLocalStorage.h b/src/libANGLE/PixelLocalStorage.h index 073f4d4ffda..72021755db9 100644 --- a/src/libANGLE/PixelLocalStorage.h +++ b/src/libANGLE/PixelLocalStorage.h @@ -11,6 +11,10 @@ #ifndef LIBANGLE_PIXEL_LOCAL_STORAGE_H_ #define LIBANGLE_PIXEL_LOCAL_STORAGE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLSLANG/ShaderLang.h" #include "libANGLE/Caps.h" #include "libANGLE/ImageIndex.h" @@ -119,6 +123,9 @@ class PixelLocalStoragePlane : angle::NonCopyable, public angle::ObserverInterfa angle::ObserverBinding mTextureObserver; }; +using PixelLocalStoragePlaneVector = + angle::FixedVector; + // Manages a collection of PixelLocalStoragePlanes and applies them to ANGLE's GL state. // // The main magic of ANGLE_shader_pixel_local_storage happens inside shaders, so we just emulate the @@ -143,7 +150,7 @@ class PixelLocalStorage return mPlanes[plane]; } - const PixelLocalStoragePlane *getPlanes() { return mPlanes.data(); } + const PixelLocalStoragePlaneVector &getPlanes() { return mPlanes; } size_t interruptCount() const { return mInterruptCount; } @@ -166,15 +173,6 @@ class PixelLocalStorage void interrupt(Context *); void restore(Context *); - // While pixel local storage is active, the draw buffers on and after - // 'FirstOverriddenDrawBuffer' are blocked from the client and reserved for internal use by PLS. - static GLint FirstOverriddenDrawBuffer(const Caps &caps, GLuint numActivePlanes) - { - ASSERT(numActivePlanes > 0); - return std::min(caps.maxColorAttachmentsWithActivePixelLocalStorage, - caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - numActivePlanes); - } - protected: PixelLocalStorage(const ShPixelLocalStorageOptions &, const Caps &); @@ -194,8 +192,7 @@ class PixelLocalStorage const ShPixelLocalStorageOptions mPLSOptions; private: - angle::FixedVector - mPlanes; + PixelLocalStoragePlaneVector mPlanes; size_t mInterruptCount = 0; GLsizei mActivePlanesAtInterrupt = 0; }; diff --git a/src/libANGLE/Platform.cpp b/src/libANGLE/Platform.cpp index d798fd4e86e..f81a9b1eb00 100644 --- a/src/libANGLE/Platform.cpp +++ b/src/libANGLE/Platform.cpp @@ -6,6 +6,10 @@ // Platform.cpp: Implementation methods for angle::Platform. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp index 427af2f7f0e..19204eba4f0 100644 --- a/src/libANGLE/Program.cpp +++ b/src/libANGLE/Program.cpp @@ -7,6 +7,10 @@ // Program.cpp: Implements the gl::Program class. Implements GL program objects // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Program.h" #include @@ -17,6 +21,7 @@ #include "common/debug.h" #include "common/platform.h" #include "common/platform_helpers.h" +#include "common/span_util.h" #include "common/string_utils.h" #include "common/utilities.h" #include "compiler/translator/blocklayout.h" @@ -257,23 +262,21 @@ void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const // append a sanitized message to the program info log. // The D3D compiler includes a fake file path in some of the warning or error // messages, so lets remove all occurrences of this fake file path from the log. -void InfoLog::appendSanitized(const char *message) +void InfoLog::appendSanitized(std::string message) { ensureInitialized(); - std::string msg(message); - - size_t found; - do + while (1) { - found = msg.find(g_fakepath); - if (found != std::string::npos) + size_t found = message.find(g_fakepath); + if (found == std::string::npos) { - msg.erase(found, strlen(g_fakepath)); + break; } - } while (found != std::string::npos); + message.erase(found, strlen(g_fakepath)); + } - if (!msg.empty()) + if (!message.empty()) { *mLazyStream << message << std::endl; } @@ -925,7 +928,6 @@ void Program::setupExecutableForLink(const Context *context) mState.mShaderCompileJobs[shaderType] = std::move(compileJob); mState.mAttachedShaders[shaderType] = std::move(shaderCompiledState); } - mProgram->prepareForLink(shaderImpls); const angle::FrontendFeatures &frontendFeatures = context->getFrontendFeatures(); if (frontendFeatures.dumpShaderSource.enabled) @@ -949,6 +951,19 @@ void Program::setupExecutableForLink(const Context *context) mState.mExecutable->mPod.isSeparable = mState.mSeparable; mState.mInfoLog.reset(); + + mProgram->prepareForLink(shaderImpls); + + if (context->getState().usesPassthroughShaders()) + { + mProgram->prepareForPassthroughLink(&mState.mAttachedShaders); + } +} + +void Program::syncExecutableOnSuccessfulLink() +{ + // Sync GL_PROGRAM_BINARY_RETRIEVABLE_HINT to the effective value when linking successfully. + mState.mExecutable->mBinaryRetrieveableHint = mState.mBinaryRetrieveableHint; } angle::Result Program::link(const Context *context, angle::JobResultExpectancy resultExpectancy) @@ -1247,6 +1262,8 @@ void Program::resolveLinkImpl(const Context *context) // Only successfully linked program can replace the executables. ASSERT(mLinked); + syncExecutableOnSuccessfulLink(); + // In case of a successful link, it is no longer required for the attached shaders to hold on to // the memory they have used. Therefore, the shader compilations are resolved to save memory. for (Shader *shader : mAttachedShaders) @@ -1407,7 +1424,7 @@ angle::Result Program::loadBinary(const Context *context, ASSERT(mLinkingState); unlink(); - BinaryInputStream stream(binary, length); + BinaryInputStream stream(angle::Span(static_cast(binary), length)); if (!deserialize(context, stream)) { return angle::Result::Continue; @@ -1462,7 +1479,7 @@ angle::Result Program::getBinary(Context *context, GLsizei bufSize, GLsizei *length) { - if (!mState.mBinaryRetrieveableHint) + if (!mState.mExecutable->mBinaryRetrieveableHint) { ANGLE_PERF_WARNING( context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, @@ -1510,7 +1527,7 @@ angle::Result Program::getBinary(Context *context, // release the memory. Note that implicit caching to blob cache is disabled when the // GL_PROGRAM_BINARY_RETRIEVABLE_HINT is set. If that hint is not set, serialization is // done twice, which is what the perf warning above is about! - mBinary.clear(); + mBinary.destroy(); } if (length) @@ -1551,7 +1568,7 @@ void Program::setBinaryRetrievableHint(bool retrievable) bool Program::getBinaryRetrievableHint() const { ASSERT(!mLinkingState); - return mState.mBinaryRetrieveableHint; + return mState.mExecutable->mBinaryRetrieveableHint; } int Program::getInfoLogLength() const @@ -1588,6 +1605,8 @@ unsigned int Program::getRefCount() const void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const { + ASSERT(shaders != nullptr); + int total = 0; for (const Shader *shader : mAttachedShaders) @@ -1624,6 +1643,18 @@ void Program::validate(const Caps &caps) if (mLinked) { + // According GLES 3.2 11.1.3.11 Validation: + // ValidateProgram will check for all the conditions described in this section: + // Now only check this condition: + // Any two active samplers in the set of active program objects are of different + // types, but refer to the same texture image unit. + // TODO should check other conditions in future. + if (getExecutable().validateSamplers(caps) == false) + { + mValidated = false; + mState.mInfoLog << err::kTextureTypeConflict; + return; + } mValidated = ConvertToBool(mProgram->validate(caps)); } else @@ -1967,7 +1998,9 @@ bool Program::linkUniforms(const Caps &caps, if (locationSize > caps.maxUniformLocations) { - mState.mInfoLog << "Exceeded maximum uniform location size"; + mState.mInfoLog + << "Exceeded maximum uniform location size: number of uniform locations = " + << locationSize << ", max uniform locations = " << caps.maxUniformLocations; return false; } } @@ -2069,8 +2102,9 @@ bool Program::linkAttributes(const Caps &caps, // Assign locations to attributes that don't have a binding location. for (ProgramInput &attribute : mState.mExecutable->mProgramInputs) { - // Not set by glBindAttribLocation or by location layout qualifier - if (attribute.getLocation() == -1) + // Not set by glBindAttribLocation or by location layout qualifier and not built-in + // attribute + if (!attribute.isBuiltIn() && attribute.getLocation() == -1) { int regs = VariableRegisterCount(attribute.getType()); int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs); @@ -2108,16 +2142,18 @@ bool Program::linkAttributes(const Caps &caps, for (const ProgramInput &attribute : mState.mExecutable->getProgramInputs()) { - ASSERT(attribute.isActive()); - ASSERT(attribute.getLocation() != -1); - unsigned int regs = static_cast(VariableRegisterCount(attribute.getType())); - - unsigned int location = static_cast(attribute.getLocation()); - for (unsigned int r = 0; r < regs; r++) + // Built-in active program inputs don't have a bound attribute. + if (!attribute.isBuiltIn()) { - // Built-in active program inputs don't have a bound attribute. - if (!attribute.isBuiltIn()) + ASSERT(attribute.isActive()); + ASSERT(attribute.getLocation() != -1); + unsigned int regs = + static_cast(VariableRegisterCount(attribute.getType())); + + unsigned int location = static_cast(attribute.getLocation()); + for (unsigned int r = 0; r < regs; r++) { + mState.mExecutable->mPod.activeAttribLocationsMask.set(location); mState.mExecutable->mPod.maxActiveAttribLocation = std::max(mState.mExecutable->mPod.maxActiveAttribLocation, location + 1); @@ -2152,8 +2188,8 @@ angle::Result Program::serialize(const Context *context) BinaryOutputStream stream; stream.writeBytes( - reinterpret_cast(angle::GetANGLEShaderProgramVersion()), - angle::GetANGLEShaderProgramVersionHashSize()); + angle::Span(reinterpret_cast(angle::GetANGLEShaderProgramVersion()), + angle::GetANGLEShaderProgramVersionHashSize())); stream.writeBool(angle::Is64Bit()); @@ -2164,8 +2200,8 @@ angle::Result Program::serialize(const Context *context) // nullptr context is supported when computing binary length. if (context) { - stream.writeInt(context->getClientVersion().major); - stream.writeInt(context->getClientVersion().minor); + stream.writeInt(context->getClientVersion().getMajor()); + stream.writeInt(context->getClientVersion().getMinor()); } else { @@ -2174,11 +2210,11 @@ angle::Result Program::serialize(const Context *context) } // mSeparable must be before mExecutable->save(), since it uses the value. - stream.writeBool(mState.mSeparable); - stream.writeInt(mState.mTransformFeedbackBufferMode); + stream.writeBool(mState.mExecutable->mPod.isSeparable); + stream.writeInt(mState.mExecutable->mPod.transformFeedbackBufferMode); - stream.writeInt(mState.mTransformFeedbackVaryingNames.size()); - for (const std::string &name : mState.mTransformFeedbackVaryingNames) + stream.writeInt(mState.mExecutable->mTransformFeedbackVaryingNames.size()); + for (const std::string &name : mState.mExecutable->mTransformFeedbackVaryingNames) { stream.writeString(name); } @@ -2220,23 +2256,22 @@ angle::Result Program::serialize(const Context *context) mProgram->save(context, &stream); ASSERT(mState.mExecutable->mPostLinkSubTasks.empty()); - if (!mBinary.resize(stream.length())) + if (!mBinary.resize(stream.size())) { ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, "Failed to allocate enough memory to serialize a program. (%zu bytes)", - stream.length()); + stream.size()); return angle::Result::Stop; } - memcpy(mBinary.data(), stream.data(), stream.length()); + angle::SpanMemcpy(mBinary.span(), angle::Span(stream)); return angle::Result::Continue; } bool Program::deserialize(const Context *context, BinaryInputStream &stream) { std::vector angleShaderProgramVersionString( - angle::GetANGLEShaderProgramVersionHashSize(), 0); - stream.readBytes(angleShaderProgramVersionString.data(), - angleShaderProgramVersionString.size()); + angle::GetANGLEShaderProgramVersionHashSize()); + stream.readBytes(angleShaderProgramVersionString); if (memcmp(angleShaderProgramVersionString.data(), angle::GetANGLEShaderProgramVersion(), angleShaderProgramVersionString.size()) != 0) { @@ -2265,10 +2300,10 @@ bool Program::deserialize(const Context *context, BinaryInputStream &stream) return false; } - int majorVersion = stream.readInt(); - int minorVersion = stream.readInt(); - if (majorVersion != context->getClientMajorVersion() || - minorVersion != context->getClientMinorVersion()) + const uint32_t majorVersion = stream.readInt(); + const uint32_t minorVersion = stream.readInt(); + if (majorVersion != context->getClientVersion().getMajor() || + minorVersion != context->getClientVersion().getMinor()) { mState.mInfoLog << "Cannot load program binaries across different ES context versions."; return false; @@ -2333,6 +2368,10 @@ void Program::postResolveLink(const Context *context) mState.mExecutable->initInterfaceBlockBindings(); mState.mExecutable->setUniformValuesFromBindingQualifiers(); + // Update active uniform and storage buffer block indices mask + mState.mExecutable->updateActiveUniformBufferBlocks(); + mState.mExecutable->updateActiveStorageBufferBlocks(); + if (context->getExtensions().multiDrawANGLE) { mState.mExecutable->mPod.drawIDLocation = @@ -2352,7 +2391,7 @@ void Program::cacheProgramBinaryIfNotAlready(const Context *context) { // If program caching is disabled, we already consider the binary cached. ASSERT(!context->getFrontendFeatures().disableProgramCaching.enabled || mIsBinaryCached); - if (!mLinked || mIsBinaryCached || mState.mBinaryRetrieveableHint) + if (!mLinked || mIsBinaryCached || mState.mExecutable->mBinaryRetrieveableHint) { // Program caching is disabled, the program is yet to be linked, it's already cached, or the // application has specified that it prefers to cache the program binary itself. @@ -2380,7 +2419,7 @@ void Program::cacheProgramBinaryIfNotAlready(const Context *context) // Drop the binary; the application didn't specify that it wants to retrieve the binary. If // it did, we wouldn't be implicitly caching it. - mBinary.clear(); + mBinary.destroy(); } mIsBinaryCached = true; @@ -2411,7 +2450,7 @@ void Program::dumpProgramInfo(const Context *context) const pathStream << dumpHash << ".program"; std::string path = pathStream.str(); - writeFile(path.c_str(), dump.c_str(), dump.length()); + writeFile(path.c_str(), dump); INFO() << "Dumped program: " << path; } } // namespace gl diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h index 779089a7bce..a0f0dd4de8f 100644 --- a/src/libANGLE/Program.h +++ b/src/libANGLE/Program.h @@ -382,7 +382,7 @@ class Program final : public LabeledObject, public angle::Subject { // This function helps ensure the program binary is cached, even if the backend waits for // post-link tasks without the knowledge of the front-end. - if (!mIsBinaryCached && !mState.mBinaryRetrieveableHint && + if (!mIsBinaryCached && !mState.mExecutable->mBinaryRetrieveableHint && mState.mExecutable->mPostLinkSubTasks.empty()) { cacheProgramBinaryIfNotAlready(context); @@ -461,7 +461,7 @@ class Program final : public LabeledObject, public angle::Subject } // Try to resolve linking. Inlined to make sure its overhead is as low as possible. - void resolveLink(const Context *context) + ANGLE_INLINE void resolveLink(const Context *context) { if (ANGLE_UNLIKELY(mLinkingState)) { @@ -501,6 +501,7 @@ class Program final : public LabeledObject, public angle::Subject void unlink(); void setupExecutableForLink(const Context *context); + void syncExecutableOnSuccessfulLink(); void deleteSelf(const Context *context); angle::Result linkJobImpl(const Caps &caps, diff --git a/src/libANGLE/ProgramExecutable.cpp b/src/libANGLE/ProgramExecutable.cpp index ef799037875..1c207cc2ef4 100644 --- a/src/libANGLE/ProgramExecutable.cpp +++ b/src/libANGLE/ProgramExecutable.cpp @@ -5,6 +5,11 @@ // // ProgramExecutable.cpp: Collects the interfaces common to both Programs and // ProgramPipelines in order to execute/draw with either. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/ProgramExecutable.h" @@ -576,6 +581,11 @@ void GetInterfaceBlockName(const UniformBlockIndex index, const auto &block = list[index.value]; + if (length) + { + *length = 0; + } + if (bufSize > 0) { std::string blockName = block.name; @@ -744,7 +754,8 @@ ProgramExecutable::ProgramExecutable(rx::GLImplFactory *factory, InfoLog *infoLo mInfoLog(infoLog), mCachedBaseVertex(0), mCachedBaseInstance(0), - mIsPPO(false) + mIsPPO(false), + mBinaryRetrieveableHint(false) { memset(&mPod, 0, sizeof(mPod)); reset(); @@ -789,10 +800,10 @@ void ProgramExecutable::reset() mPod.fragmentInoutIndices.reset(); - mPod.hasClipDistance = false; - mPod.hasDiscard = false; - mPod.enablesPerSampleShading = false; - mPod.hasYUVOutput = false; + mPod.hasClipDistance = false; + mPod.hasDiscard = false; + mPod.enablesPerSampleShading = false; + mPod.hasYUVOutput = false; mPod.hasDepthInputAttachment = false; mPod.hasStencilInputAttachment = false; @@ -830,6 +841,9 @@ void ProgramExecutable::reset() mActiveImagesMask.reset(); + mActiveUniformBufferBlocks.reset(); + mActiveStorageBufferBlocks.reset(); + mUniformBlockIndexToBufferBinding = {}; mProgramInputs.clear(); @@ -954,7 +968,7 @@ void ProgramExecutable::load(gl::BinaryInputStream *stream) size_t plsCount = stream->readInt(); ASSERT(mPixelLocalStorageFormats.empty()); mPixelLocalStorageFormats.resize(plsCount); - stream->readBytes(reinterpret_cast(mPixelLocalStorageFormats.data()), plsCount); + stream->readBytes(angle::as_writable_byte_span(mPixelLocalStorageFormats)); // These values are currently only used by PPOs, so only load them when the program is marked // separable to save memory. @@ -1059,8 +1073,7 @@ void ProgramExecutable::save(gl::BinaryOutputStream *stream) const // ANGLE_shader_pixel_local_storage. stream->writeInt(mPixelLocalStorageFormats.size()); - stream->writeBytes(reinterpret_cast(mPixelLocalStorageFormats.data()), - mPixelLocalStorageFormats.size()); + stream->writeBytes(angle::as_byte_span(mPixelLocalStorageFormats)); // These values are currently only used by PPOs, so only save them when the program is marked // separable to save memory. @@ -1643,7 +1656,9 @@ bool ProgramExecutable::linkValidateOutputVariables( // Don't store outputs for gl_FragDepth, gl_FragColor, etc. if (outputVariable.isBuiltIn()) + { continue; + } int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable); if (fixedLocation == -1) @@ -1694,7 +1709,9 @@ bool ProgramExecutable::linkValidateOutputVariables( // Don't store outputs for gl_FragDepth, gl_FragColor, etc. if (outputVariable.isBuiltIn()) + { continue; + } AssignOutputIndex(fragmentOutputIndices, outputVariable); ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1); @@ -1953,8 +1970,9 @@ bool ProgramExecutable::linkAtomicCounterBuffers(const Caps &caps) { auto &uniform = mUniforms[index]; - uniform.pod.blockOffset = uniform.getOffset(); - uniform.pod.blockArrayStride = uniform.isArray() ? 4 : 0; + uniform.pod.blockArrayStride = uniform.isArray() ? 4 : 0; + uniform.pod.blockOffset = + uniform.getOffset() + uniform.pod.blockArrayStride * uniform.getOuterArrayOffset(); uniform.pod.blockMatrixStride = 0; uniform.pod.flagBits.blockIsRowMajorMatrix = false; uniform.pod.flagBits.isBlock = true; @@ -2358,6 +2376,11 @@ void ProgramExecutable::getActiveAttribute(GLuint index, GLenum *type, GLchar *name) const { + if (length) + { + *length = 0; + } + if (mProgramInputs.empty()) { // Program is not successfully linked @@ -2366,11 +2389,6 @@ void ProgramExecutable::getActiveAttribute(GLuint index, name[0] = '\0'; } - if (length) - { - *length = 0; - } - *type = GL_NONE; *size = 1; return; @@ -2421,6 +2439,11 @@ void ProgramExecutable::getActiveUniform(GLuint index, GLenum *type, GLchar *name) const { + if (length) + { + *length = 0; + } + if (mUniforms.empty()) { // Program is not successfully linked @@ -2429,13 +2452,15 @@ void ProgramExecutable::getActiveUniform(GLuint index, name[0] = '\0'; } - if (length) + if (size) { - *length = 0; + *size = 0; } - *size = 0; - *type = GL_NONE; + if (type) + { + *type = GL_NONE; + } } ASSERT(index < mUniforms.size()); @@ -2447,8 +2472,14 @@ void ProgramExecutable::getActiveUniform(GLuint index, CopyStringToBuffer(name, string, bufsize, length); } - *size = clampCast(uniform.getBasicTypeElementCount()); - *type = uniform.getType(); + if (size) + { + *size = clampCast(uniform.getBasicTypeElementCount()); + } + if (type) + { + *type = uniform.getType(); + } } GLint ProgramExecutable::getActiveUniformMaxLength() const @@ -2929,6 +2960,24 @@ void ProgramExecutable::remapUniformBlockBinding(UniformBlockIndex uniformBlockI mUniformBufferBindingToUniformBlocks[uniformBlockBinding].set(uniformBlockIndex.value); } +void ProgramExecutable::updateActiveUniformBufferBlocks() +{ + for (size_t blockIndex = 0; blockIndex < mUniformBlocks.size(); blockIndex++) + { + mActiveUniformBufferBlocks.set(blockIndex, + mUniformBlocks[blockIndex].activeShaderCount() > 0); + } +} + +void ProgramExecutable::updateActiveStorageBufferBlocks() +{ + for (size_t blockIndex = 0; blockIndex < mShaderStorageBlocks.size(); blockIndex++) + { + mActiveStorageBufferBlocks.set(blockIndex, + mShaderStorageBlocks[blockIndex].activeShaderCount() > 0); + } +} + void ProgramExecutable::setUniformValuesFromBindingQualifiers() { for (unsigned int samplerIndex : mPod.samplerUniformRange) @@ -2961,7 +3010,9 @@ GLsizei ProgramExecutable::clampUniformCount(const VariableLocation &locationInf const T *v) { if (count == 1) + { return 1; + } const LinkedUniform &linkedUniform = mUniforms[locationInfo.index]; diff --git a/src/libANGLE/ProgramExecutable.h b/src/libANGLE/ProgramExecutable.h index fe5b871de60..0cf400c583b 100644 --- a/src/libANGLE/ProgramExecutable.h +++ b/src/libANGLE/ProgramExecutable.h @@ -146,10 +146,12 @@ struct ProgramOutput { ProgramOutput() = default; ProgramOutput(const sh::ShaderVariable &var); + GLenum getType() const { return pod.type; } bool isBuiltIn() const { return pod.isBuiltIn; } bool isArray() const { return pod.isArray; } int getLocation() const { return pod.location; } unsigned int getOutermostArraySize() const { return pod.outermostArraySize; } + unsigned int getBasicTypeElementCount() const { return pod.basicTypeElementCount; } void resetEffectiveLocation() { if (pod.hasImplicitLocation) @@ -322,6 +324,16 @@ class ProgramExecutable final : public angle::Subject return mActiveSamplerTypes; } + const ProgramUniformBlockMask &getActiveUniformBufferBlocks() const + { + return mActiveUniformBufferBlocks; + } + + const ProgramStorageBlockMask &getActiveStorageBufferBlocks() const + { + return mActiveStorageBufferBlocks; + } + void setActive(size_t textureUnit, const SamplerBinding &samplerBinding, const gl::LinkedUniform &samplerUniform); @@ -749,6 +761,9 @@ class ProgramExecutable final : public angle::Subject void waitForPostLinkTasks(const Context *context); + void updateActiveUniformBufferBlocks(); + void updateActiveStorageBufferBlocks(); + private: friend class Program; friend class ProgramPipeline; @@ -900,8 +915,9 @@ class ProgramExecutable final : public angle::Subject int32_t geometryShaderMaxVertices; GLenum transformFeedbackBufferMode; - // 4 bytes each. GL_OVR_multiview / GL_OVR_multiview2 + // GL_OVR_multiview int32_t numViews; + // GL_ANGLE_multi_draw int32_t drawIDLocation; @@ -936,6 +952,10 @@ class ProgramExecutable final : public angle::Subject ActiveTextureMask mActiveImagesMask; ActiveTextureArray mActiveImageShaderBits; + // Cached mask of active uniform and storage buffer blocks + ProgramUniformBlockMask mActiveUniformBufferBlocks; + ProgramStorageBlockMask mActiveStorageBufferBlocks; + // Names and mapped names of output variables that are arrays include [0] in the end, similarly // to uniforms. std::vector mOutputVariables; @@ -1022,6 +1042,8 @@ class ProgramExecutable final : public angle::Subject // Flag for an easy check for PPO without inspecting mPPOProgramExecutables bool mIsPPO; + bool mBinaryRetrieveableHint; + // Cache for sampler validation mutable Optional mCachedValidateSamplersResult; diff --git a/src/libANGLE/ProgramLinkedResources.cpp b/src/libANGLE/ProgramLinkedResources.cpp index eee5e5bf5ad..4ef52bfce12 100644 --- a/src/libANGLE/ProgramLinkedResources.cpp +++ b/src/libANGLE/ProgramLinkedResources.cpp @@ -418,6 +418,7 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor bool isImage = IsImageType(variable.type); bool isAtomicCounter = IsAtomicCounterType(variable.type); bool isFragmentInOut = variable.isFragmentInOut; + bool isTransformedFP16FloatUniform = variable.isFloat16; std::vector *uniformList = mUniforms; if (isSampler) { @@ -464,6 +465,7 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor } if (mMarkActive) { + existingUniform->isFloat16 = isTransformedFP16FloatUniform; existingUniform->active = true; existingUniform->setActive(mShaderType, true, variable.id); } @@ -485,6 +487,7 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor linkedUniform.id = variable.id; linkedUniform.imageUnitFormat = variable.imageUnitFormat; linkedUniform.isFragmentInOut = variable.isFragmentInOut; + linkedUniform.isFloat16 = variable.isFloat16; if (variable.hasParentArrayIndex()) { linkedUniform.setParentArrayIndex(variable.parentArrayIndex()); @@ -863,12 +866,38 @@ void LogInterfaceBlocksExceedLimit(InfoLog &infoLog, << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")"; } -bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks, - const std::vector &interfaceBlocks, - ShaderType shaderType, - sh::BlockType blockType, - GLuint *combinedInterfaceBlocksCount, - InfoLog &infoLog) +std::string GetInterfaceBlockSizeLimitName(sh::BlockType blockType) +{ + switch (blockType) + { + case sh::BlockType::kBlockUniform: + return "GL_MAX_UNIFORM_BLOCK_SIZE"; + case sh::BlockType::kBlockBuffer: + return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE"; + default: + UNREACHABLE(); + return ""; + } +} + +void LogInterfaceBlockExceedsSizeLimit(InfoLog &infoLog, + ShaderType shaderType, + const std::string &name, + sh::BlockType blockType, + GLuint limit) +{ + infoLog << "Size of " << GetInterfaceBlockTypeString(blockType) << " " << name << " in " + << GetShaderTypeString(shaderType) << " shader exceeds " + << GetInterfaceBlockSizeLimitName(blockType) << " (" << limit << ")"; +} + +bool ValidateInterfaceBlocks(GLuint maxInterfaceBlocks, + GLuint maxInterfaceBlockSize, + const std::vector &interfaceBlocks, + ShaderType shaderType, + sh::BlockType blockType, + GLuint *combinedInterfaceBlocksCount, + InfoLog &infoLog) { GLuint blockCount = 0; for (const sh::InterfaceBlock &block : interfaceBlocks) @@ -881,6 +910,35 @@ bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks, LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks); return false; } + + // The size of the block is not readily available and needs to be calculated. This is + // redundantly done after a successful link to gather not just the size but also derive + // the layout of the block. A future optimization may be able to reuse the size + // calculated here, but the double-traversal is likely unavoidable (once for validation, + // once for gathering link info). + sh::Std140BlockEncoder std140Encoder; + sh::Std430BlockEncoder std430Encoder; + sh::BlockLayoutEncoder *encoder = nullptr; + + if (block.layout == sh::BLOCKLAYOUT_STD430) + { + encoder = &std430Encoder; + } + else + { + encoder = &std140Encoder; + } + + sh::BlockEncoderVisitor visitor("", "", encoder); + TraverseShaderVariables(block.fields, false, &visitor); + const size_t blockSize = encoder->getCurrentOffset(); + + if (blockSize > maxInterfaceBlockSize) + { + LogInterfaceBlockExceedsSizeLimit(infoLog, shaderType, block.name, blockType, + maxInterfaceBlockSize); + return false; + } } } @@ -1757,9 +1815,9 @@ void ProgramLinkedResourcesLinker::getAtomicCounterBufferSizeMap( // binding. The end of the uniform is calculated by finding the initial offset of the // uniform and adding size of the uniform. For arrays, the size is the number of elements // times the element size (should always by 4 for atomic_units). - unsigned dataOffset = - glUniform.getOffset() + static_cast(glUniform.getBasicTypeElementCount() * - glUniform.getElementSize()); + unsigned dataOffset = glUniform.getBlockOffset() + + static_cast(glUniform.getBasicTypeElementCount() * + glUniform.getElementSize()); if (dataOffset > bufferDataSize) { bufferDataSize = dataOffset; @@ -1889,14 +1947,13 @@ bool LinkValidateProgramGlobalNames(InfoLog &infoLog, } // [OpenGL ES 3.2] Chapter 7.4.1 "Shader Interface Matching" -bool LinkValidateShaderInterfaceMatching(const std::vector &outputVaryings, - const std::vector &inputVaryings, - ShaderType frontShaderType, - ShaderType backShaderType, - int frontShaderVersion, - int backShaderVersion, - bool isSeparable, - gl::InfoLog &infoLog) +bool LinkValidateInOutNumberMatching(const std::vector &outputVaryings, + const std::vector &inputVaryings, + ShaderType frontShaderType, + ShaderType backShaderType, + int frontShaderVersion, + int backShaderVersion, + gl::InfoLog &infoLog) { ASSERT(frontShaderVersion == backShaderVersion); @@ -1907,14 +1964,14 @@ bool LinkValidateShaderInterfaceMatching(const std::vector & GetFilteredVaryings(outputVaryings, &filteredOutputVaryings); // Separable programs require the number of inputs and outputs match - if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size()) + if (filteredInputVaryings.size() < filteredOutputVaryings.size()) { infoLog << GetShaderTypeString(backShaderType) << " does not consume all varyings generated by " << GetShaderTypeString(frontShaderType); return false; } - if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size()) + if (filteredInputVaryings.size() > filteredOutputVaryings.size()) { infoLog << GetShaderTypeString(frontShaderType) << " does not generate all varyings consumed by " @@ -1922,6 +1979,26 @@ bool LinkValidateShaderInterfaceMatching(const std::vector & return false; } + return true; +} + +bool LinkValidateShaderInterfaceMatching(const std::vector &outputVaryings, + const std::vector &inputVaryings, + ShaderType frontShaderType, + ShaderType backShaderType, + int frontShaderVersion, + int backShaderVersion, + bool isSeparable, + gl::InfoLog &infoLog) +{ + ASSERT(frontShaderVersion == backShaderVersion); + + std::vector filteredInputVaryings; + std::vector filteredOutputVaryings; + + GetFilteredVaryings(inputVaryings, &filteredInputVaryings); + GetFilteredVaryings(outputVaryings, &filteredOutputVaryings); + // All inputs must match all outputs for (const sh::ShaderVariable *input : filteredInputVaryings) { @@ -2434,9 +2511,10 @@ bool LinkValidateProgramInterfaceBlocks(const Caps &caps, resources.uniformBlockLinker.getShaderBlocks(shaderType); if (!uniformBlocks.empty()) { - if (!ValidateInterfaceBlocksCount( - static_cast(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks, - shaderType, sh::BlockType::kBlockUniform, &combinedUniformBlocksCount, infoLog)) + if (!ValidateInterfaceBlocks( + static_cast(caps.maxShaderUniformBlocks[shaderType]), + static_cast(caps.maxUniformBlockSize), uniformBlocks, shaderType, + sh::BlockType::kBlockUniform, &combinedUniformBlocksCount, infoLog)) { return false; } @@ -2471,9 +2549,10 @@ bool LinkValidateProgramInterfaceBlocks(const Caps &caps, resources.shaderStorageBlockLinker.getShaderBlocks(shaderType); if (!shaderStorageBlocks.empty()) { - if (!ValidateInterfaceBlocksCount( + if (!ValidateInterfaceBlocks( static_cast(caps.maxShaderStorageBlocks[shaderType]), - shaderStorageBlocks, shaderType, sh::BlockType::kBlockBuffer, + static_cast(caps.maxShaderStorageBlockSize), shaderStorageBlocks, + shaderType, sh::BlockType::kBlockBuffer, combinedShaderStorageBlocksCountOut, infoLog)) { return false; diff --git a/src/libANGLE/ProgramLinkedResources.h b/src/libANGLE/ProgramLinkedResources.h index 6535ea24b44..93bfd4d3bd0 100644 --- a/src/libANGLE/ProgramLinkedResources.h +++ b/src/libANGLE/ProgramLinkedResources.h @@ -357,6 +357,13 @@ using InterfaceBlockMap = std::map; bool LinkValidateProgramGlobalNames(InfoLog &infoLog, const ProgramExecutable &executable, const LinkingVariables &linkingVariables); +bool LinkValidateInOutNumberMatching(const std::vector &outputVaryings, + const std::vector &inputVaryings, + ShaderType frontShaderType, + ShaderType backShaderType, + int frontShaderVersion, + int backShaderVersion, + InfoLog &infoLog); bool LinkValidateShaderInterfaceMatching(const std::vector &outputVaryings, const std::vector &inputVaryings, ShaderType frontShaderType, diff --git a/src/libANGLE/ProgramPipeline.cpp b/src/libANGLE/ProgramPipeline.cpp index 7d11aba9508..0dcf0986cc5 100644 --- a/src/libANGLE/ProgramPipeline.cpp +++ b/src/libANGLE/ProgramPipeline.cpp @@ -625,6 +625,9 @@ angle::Result ProgramPipeline::link(const Context *context) mState.mExecutable->copySamplerBindingsFromProgram(*executable); mState.mExecutable->copyImageBindingsFromProgram(*executable); } + // Update active uniform and storage buffer block indices mask + mState.mExecutable->updateActiveUniformBufferBlocks(); + mState.mExecutable->updateActiveStorageBufferBlocks(); if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Fragment)) { @@ -675,6 +678,18 @@ bool ProgramPipeline::linkVaryings() getShaderProgramExecutable(previousShaderType); ASSERT(previousExecutable); + if (previousExecutable == programExecutable) + { + continue; + } + if (!LinkValidateInOutNumberMatching( + previousExecutable->getLinkedOutputVaryings(previousShaderType), + programExecutable->getLinkedInputVaryings(shaderType), previousShaderType, + shaderType, previousExecutable->getLinkedShaderVersion(previousShaderType), + programExecutable->getLinkedShaderVersion(shaderType), mState.mInfoLog)) + { + return false; + } if (!LinkValidateShaderInterfaceMatching( previousExecutable->getLinkedOutputVaryings(previousShaderType), programExecutable->getLinkedInputVaryings(shaderType), previousShaderType, @@ -713,6 +728,7 @@ void ProgramPipeline::validate(const Context *context) const Caps &caps = context->getCaps(); mState.mValid = true; mState.mInfoLog.reset(); + bool noActiveStage = true; if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) != mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation)) @@ -728,6 +744,7 @@ void ProgramPipeline::validate(const Context *context) Program *shaderProgram = mState.mPrograms[shaderType]; if (shaderProgram) { + noActiveStage = false; shaderProgram->resolveLink(context); shaderProgram->validate(caps); std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString(); @@ -747,6 +764,13 @@ void ProgramPipeline::validate(const Context *context) } } + if (noActiveStage) + { + mState.mValid = false; + mState.mInfoLog << "Program pipeline has no active stage yet.\n"; + return; + } + intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context); if (programPipelineError) { diff --git a/src/libANGLE/RefCountObject.h b/src/libANGLE/RefCountObject.h index b01efcb336b..a4858720b33 100644 --- a/src/libANGLE/RefCountObject.h +++ b/src/libANGLE/RefCountObject.h @@ -283,6 +283,12 @@ class OffsetBindingPointer : public BindingPointer updateOffsetAndSize(newObject, offset, size); } + void assignOffsetAndSize(GLintptr offset, GLsizeiptr size) + { + mOffset = offset; + mSize = size; + } + private: ANGLE_INLINE void updateOffsetAndSize(ObjectType *newObject, GLintptr offset, GLsizeiptr size) { @@ -319,6 +325,11 @@ class SubjectBindingPointer : protected BindingPointer, public angle:: void bind(const Context *context, SubjectT *subject) { + if (subject == get()) + { + return; + } + // AddRef first in case subject == get() if (subject) { diff --git a/src/libANGLE/Renderbuffer.cpp b/src/libANGLE/Renderbuffer.cpp index f73660d5c49..3b4a039608b 100644 --- a/src/libANGLE/Renderbuffer.cpp +++ b/src/libANGLE/Renderbuffer.cpp @@ -36,7 +36,7 @@ InitState DetermineInitState(const Context *context) RenderbufferState::RenderbufferState() : mWidth(0), mHeight(0), - mFormat(GL_RGBA4), + mFormat(GL_NONE), mSamples(0), mMultisamplingMode(MultisamplingMode::Regular), mHasProtectedContent(false), @@ -166,7 +166,7 @@ angle::Result Renderbuffer::setStorageMultisample(const Context *context, // Potentially adjust "samplesIn" to a supported value const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - GLsizei samples = formatCaps.getNearestSamples(samplesIn); + GLsizei samples = formatCaps.sampleCounts.getNearestSamples(samplesIn); ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width, height, mode)); diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp index 08244416c49..ec331f9adc2 100644 --- a/src/libANGLE/ResourceManager.cpp +++ b/src/libANGLE/ResourceManager.cpp @@ -30,17 +30,23 @@ namespace { template -IDType AllocateEmptyObject(HandleAllocator *handleAllocator, - ResourceMap *objectMap) +bool AllocateEmptyObject(HandleAllocator *handleAllocator, + ResourceMap *objectMap, + IDType *outID) { - IDType handle = PackParam(handleAllocator->allocate()); - objectMap->assign(handle, nullptr); - return handle; + if (!handleAllocator->allocate(&outID->value)) + { + return false; + } + objectMap->assign(*outID, nullptr); + return true; } } // anonymous namespace -ResourceManagerBase::ResourceManagerBase() : mRefCount(1) {} +ResourceManagerBase::ResourceManagerBase() + : mHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES), mRefCount(1) +{} ResourceManagerBase::~ResourceManagerBase() = default; @@ -125,9 +131,9 @@ void BufferManager::DeleteObject(const Context *context, Buffer *buffer) buffer->release(context); } -BufferID BufferManager::createBuffer() +bool BufferManager::createBuffer(BufferID *outBuffer) { - return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap, outBuffer); } Buffer *BufferManager::getBuffer(BufferID handle) const @@ -168,14 +174,18 @@ void ShaderProgramManager::reset(const Context *context) mShaders.clear(); } -ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory, - const gl::Limitations &rendererLimitations, - ShaderType type) +bool ShaderProgramManager::createShader(rx::GLImplFactory *factory, + const gl::Limitations &rendererLimitations, + ShaderType type, + ShaderProgramID *outShader) { ASSERT(type != ShaderType::InvalidEnum); - ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()}; - mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle)); - return handle; + if (!mHandleAllocator.allocate(&outShader->value)) + { + return false; + } + mShaders.assign(*outShader, new Shader(this, factory, rendererLimitations, type, *outShader)); + return true; } void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader) @@ -188,11 +198,14 @@ Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const return mShaders.query(handle); } -ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory) +bool ShaderProgramManager::createProgram(rx::GLImplFactory *factory, ShaderProgramID *outProgram) { - ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()}; - mPrograms.assign(handle, new Program(factory, this, handle)); - return handle; + if (!mHandleAllocator.allocate(&outProgram->value)) + { + return false; + } + mPrograms.assign(*outProgram, new Program(factory, this, *outProgram)); + return true; } void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program) @@ -243,9 +256,9 @@ void TextureManager::DeleteObject(const Context *context, Texture *texture) texture->release(context); } -TextureID TextureManager::createTexture() +bool TextureManager::createTexture(TextureID *outTexture) { - return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap, outTexture); } void TextureManager::signalAllTexturesDirty() const @@ -303,9 +316,9 @@ void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *ren renderbuffer->release(context); } -RenderbufferID RenderbufferManager::createRenderbuffer() +bool RenderbufferManager::createRenderbuffer(RenderbufferID *outRenderbuffer) { - return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)}; + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap, outRenderbuffer); } Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const @@ -331,9 +344,9 @@ void SamplerManager::DeleteObject(const Context *context, Sampler *sampler) sampler->release(context); } -SamplerID SamplerManager::createSampler() +bool SamplerManager::createSampler(SamplerID *outSampler) { - return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap, outSampler); } // SyncManager Implementation. @@ -346,13 +359,16 @@ void SyncManager::DeleteObject(const Context *context, Sync *sync) sync->release(context); } -SyncID SyncManager::createSync(rx::GLImplFactory *factory) +bool SyncManager::createSync(rx::GLImplFactory *factory, SyncID *outSync) { - SyncID handle = {mHandleAllocator.allocate()}; - Sync *sync = new Sync(factory, handle); + if (!mHandleAllocator.allocate(&outSync->value)) + { + return false; + } + Sync *sync = new Sync(factory, *outSync); sync->addRef(); - mObjectMap.assign(handle, sync); - return handle; + mObjectMap.assign(*outSync, sync); + return true; } Sync *SyncManager::getSync(SyncID handle) const @@ -381,9 +397,9 @@ void FramebufferManager::DeleteObject(const Context *context, Framebuffer *frame delete framebuffer; } -FramebufferID FramebufferManager::createFramebuffer() +bool FramebufferManager::createFramebuffer(FramebufferID *outFramebuffer) { - return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap, outFramebuffer); } Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const @@ -433,9 +449,9 @@ void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipelin pipeline->release(context); } -ProgramPipelineID ProgramPipelineManager::createProgramPipeline() +bool ProgramPipelineManager::createProgramPipeline(ProgramPipelineID *outProgramPipeline) { - return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap, outProgramPipeline); } ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const @@ -467,13 +483,17 @@ void MemoryObjectManager::reset(const Context *context) mMemoryObjects.clear(); } -MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory) +bool MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory, + MemoryObjectID *outMemoryObject) { - MemoryObjectID handle = MemoryObjectID{mHandleAllocator.allocate()}; - MemoryObject *memoryObject = new MemoryObject(factory, handle); + if (!mHandleAllocator.allocate(&outMemoryObject->value)) + { + return false; + } + MemoryObject *memoryObject = new MemoryObject(factory, *outMemoryObject); memoryObject->addRef(); - mMemoryObjects.assign(handle, memoryObject); - return handle; + mMemoryObjects.assign(*outMemoryObject, memoryObject); + return true; } void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle) @@ -522,13 +542,16 @@ void SemaphoreManager::reset(const Context *context) mSemaphores.clear(); } -SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory) +bool SemaphoreManager::createSemaphore(rx::GLImplFactory *factory, SemaphoreID *outSemaphoreHandle) { - SemaphoreID handle = SemaphoreID{mHandleAllocator.allocate()}; - Semaphore *semaphore = new Semaphore(factory, handle); + if (!mHandleAllocator.allocate(&outSemaphoreHandle->value)) + { + return false; + } + Semaphore *semaphore = new Semaphore(factory, *outSemaphoreHandle); semaphore->addRef(); - mSemaphores.assign(handle, semaphore); - return handle; + mSemaphores.assign(*outSemaphoreHandle, semaphore); + return true; } void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle) diff --git a/src/libANGLE/ResourceManager.h b/src/libANGLE/ResourceManager.h index 9c52ac08413..b4f73546039 100644 --- a/src/libANGLE/ResourceManager.h +++ b/src/libANGLE/ResourceManager.h @@ -143,7 +143,7 @@ class BufferManager : public TypedResourceManagerWithTotalMemorySize { public: - BufferID createBuffer(); + bool createBuffer(BufferID *outBuffer); Buffer *getBuffer(BufferID handle) const; ANGLE_INLINE Buffer *checkBufferAllocation(rx::GLImplFactory *factory, BufferID handle) @@ -164,13 +164,14 @@ class ShaderProgramManager : public ResourceManagerBase public: ShaderProgramManager(); - ShaderProgramID createShader(rx::GLImplFactory *factory, - const Limitations &rendererLimitations, - ShaderType type); + bool createShader(rx::GLImplFactory *factory, + const Limitations &rendererLimitations, + ShaderType type, + ShaderProgramID *outShader); void deleteShader(const Context *context, ShaderProgramID shader); Shader *getShader(ShaderProgramID handle) const; - ShaderProgramID createProgram(rx::GLImplFactory *factory); + bool createProgram(rx::GLImplFactory *factory, ShaderProgramID *outProgram); void deleteProgram(const Context *context, ShaderProgramID program); ANGLE_INLINE Program *getProgram(ShaderProgramID handle) const @@ -203,7 +204,7 @@ class ShaderProgramManager : public ResourceManagerBase class TextureManager : public TypedResourceManager { public: - TextureID createTexture(); + bool createTexture(TextureID *outTexture); ANGLE_INLINE Texture *getTexture(TextureID handle) const { ASSERT(mObjectMap.query({0}) == nullptr); @@ -237,7 +238,7 @@ class RenderbufferManager : public TypedResourceManagerWithTotalMemorySize { public: - RenderbufferID createRenderbuffer(); + bool createRenderbuffer(RenderbufferID *outRenderbuffer); Renderbuffer *getRenderbuffer(RenderbufferID handle) const; Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, RenderbufferID handle) @@ -255,7 +256,7 @@ class RenderbufferManager : public TypedResourceManagerWithTotalMemorySize { public: - SamplerID createSampler(); + bool createSampler(SamplerID *outSampler); Sampler *getSampler(SamplerID handle) const { return mObjectMap.query(handle); } bool isSampler(SamplerID sampler) const { return mObjectMap.contains(sampler); } @@ -274,7 +275,7 @@ class SamplerManager : public TypedResourceManager { public: - SyncID createSync(rx::GLImplFactory *factory); + bool createSync(rx::GLImplFactory *factory, SyncID *outSync); Sync *getSync(SyncID handle) const; static void DeleteObject(const Context *context, Sync *sync); @@ -287,7 +288,7 @@ class FramebufferManager : public TypedResourceManager { public: - FramebufferID createFramebuffer(); + bool createFramebuffer(FramebufferID *outFramebuffer); Framebuffer *getFramebuffer(FramebufferID handle) const; void setDefaultFramebuffer(Framebuffer *framebuffer); Framebuffer *getDefaultFramebuffer() const; @@ -314,7 +315,7 @@ class ProgramPipelineManager : public TypedResourceManager { public: - ProgramPipelineID createProgramPipeline(); + bool createProgramPipeline(ProgramPipelineID *outProgramPipeline); ProgramPipeline *getProgramPipeline(ProgramPipelineID handle) const; ProgramPipeline *checkProgramPipelineAllocation(rx::GLImplFactory *factory, @@ -335,7 +336,7 @@ class MemoryObjectManager : public ResourceManagerBase public: MemoryObjectManager(); - MemoryObjectID createMemoryObject(rx::GLImplFactory *factory); + bool createMemoryObject(rx::GLImplFactory *factory, MemoryObjectID *outMemoryObject); void deleteMemoryObject(const Context *context, MemoryObjectID handle); MemoryObject *getMemoryObject(MemoryObjectID handle) const; @@ -353,7 +354,7 @@ class SemaphoreManager : public ResourceManagerBase public: SemaphoreManager(); - SemaphoreID createSemaphore(rx::GLImplFactory *factory); + bool createSemaphore(rx::GLImplFactory *factory, SemaphoreID *outSemaphore); void deleteSemaphore(const Context *context, SemaphoreID handle); Semaphore *getSemaphore(SemaphoreID handle) const; diff --git a/src/libANGLE/ResourceManager_unittest.cpp b/src/libANGLE/ResourceManager_unittest.cpp index c15a8d8c137..b84b393486b 100644 --- a/src/libANGLE/ResourceManager_unittest.cpp +++ b/src/libANGLE/ResourceManager_unittest.cpp @@ -48,7 +48,8 @@ TEST_F(ResourceManagerTest, ReallocateBoundTexture) EXPECT_CALL(mMockFactory, createTexture(_)).Times(1).RetiresOnSaturation(); mTextureManager->checkTextureAllocation(&mMockFactory, {1}, TextureType::_2D); - TextureID newTexture = mTextureManager->createTexture(); + TextureID newTexture; + EXPECT_TRUE(mTextureManager->createTexture(&newTexture)); EXPECT_NE(1u, newTexture.value); } @@ -57,7 +58,8 @@ TEST_F(ResourceManagerTest, ReallocateBoundBuffer) EXPECT_CALL(mMockFactory, createBuffer(_)).Times(1).RetiresOnSaturation(); mBufferManager->checkBufferAllocation(&mMockFactory, {1}); - BufferID newBuffer = mBufferManager->createBuffer(); + BufferID newBuffer; + EXPECT_TRUE(mBufferManager->createBuffer(&newBuffer)); EXPECT_NE(1u, newBuffer.value); } @@ -66,7 +68,8 @@ TEST_F(ResourceManagerTest, ReallocateBoundRenderbuffer) EXPECT_CALL(mMockFactory, createRenderbuffer(_)).Times(1).RetiresOnSaturation(); mRenderbuffermanager->checkRenderbufferAllocation(&mMockFactory, {1}); - RenderbufferID newRenderbuffer = mRenderbuffermanager->createRenderbuffer(); + RenderbufferID newRenderbuffer; + EXPECT_TRUE(mRenderbuffermanager->createRenderbuffer(&newRenderbuffer)); EXPECT_NE(1u, newRenderbuffer.value); } diff --git a/src/libANGLE/ResourceMap.h b/src/libANGLE/ResourceMap.h index 0506452f0ff..cf3462a9bdf 100644 --- a/src/libANGLE/ResourceMap.h +++ b/src/libANGLE/ResourceMap.h @@ -11,6 +11,10 @@ #ifndef LIBANGLE_RESOURCE_MAP_H_ #define LIBANGLE_RESOURCE_MAP_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -186,12 +190,21 @@ class ResourceMap final : angle::NonCopyable static ResourceType *InvalidPointer(); static constexpr intptr_t kInvalidPointer = static_cast(-1); +#if defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK) static constexpr bool kNeedsLock = ResourceMapParams::kNeedsLock; - using Mutex = typename SelectResourceMapMutex::type; - static constexpr size_t kInitialFlatResourcesSize = ResourceMapParams::kInitialFlatResourcesSize; +#else + // When share group locks are disabled, we are already in an thread-unsafe state so disable + // locking in the ResourceManager too. + static constexpr bool kNeedsLock = false; + + // Always grow from a small initial allocation when locks are disabled. Chromium uses very few + // total resources. + static constexpr size_t kInitialFlatResourcesSize = 192; +#endif + using Mutex = typename SelectResourceMapMutex::type; // 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 diff --git a/src/libANGLE/Shader.cpp b/src/libANGLE/Shader.cpp index 4a04caa488f..e24d824f358 100644 --- a/src/libANGLE/Shader.cpp +++ b/src/libANGLE/Shader.cpp @@ -8,6 +8,10 @@ // VertexShader and FragmentShader. Implements GL shader objects and related // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Shader.h" #include @@ -15,6 +19,7 @@ #include "GLSLANG/ShaderLang.h" #include "common/angle_version_info.h" +#include "common/span_util.h" #include "common/string_utils.h" #include "common/system_utils.h" #include "common/utilities.h" @@ -61,6 +66,24 @@ std::string GetShaderDumpFilePath(size_t shaderHash, const char *suffix) return path.str(); } +void GetSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) +{ + int index = 0; + + if (bufSize > 0) + { + index = std::min(bufSize - 1, static_cast(source.length())); + memcpy(buffer, source.c_str(), index); + + buffer[index] = '\0'; + } + + if (length) + { + *length = index; + } +} + class CompileTask final : public angle::Closure { public: @@ -69,7 +92,7 @@ class CompileTask final : public angle::Closure ShHandle compilerHandle, ShShaderOutput outputType, const ShCompileOptions &options, - const std::string &source, + std::shared_ptr source, size_t sourceHash, const SharedCompiledShaderState &compiledState, size_t maxComputeWorkGroupInvocations, @@ -132,7 +155,7 @@ class CompileTask final : public angle::Closure ShHandle mCompilerHandle = 0; ShShaderOutput mOutputType; ShCompileOptions mOptions; - const std::string mSource; + std::shared_ptr mSource; size_t mSourceHash = 0; SharedCompiledShaderState mCompiledState; @@ -177,7 +200,7 @@ angle::Result CompileTask::compileImpl() // Compiling from source // Call the translator and get the info log - bool result = mTranslateTask->translate(mCompilerHandle, mOptions, mSource); + bool result = mTranslateTask->translate(mCompilerHandle, mOptions, *mSource); mInfoLog = sh::GetInfoLog(mCompilerHandle); if (!result) { @@ -198,10 +221,9 @@ angle::Result CompileTask::compileImpl() angle::Result CompileTask::postTranslate() { - const bool isBinaryOutput = mOutputType == SH_SPIRV_VULKAN_OUTPUT; - mCompiledState->buildCompiledShaderState(mCompilerHandle, isBinaryOutput); + mCompiledState->buildCompiledShaderState(mCompilerHandle, mOutputType); - ASSERT(!mCompiledState->translatedSource.empty() || !mCompiledState->compiledBinary.empty()); + ASSERT(!mCompiledState->translatedSource->empty() || !mCompiledState->compiledBinary.empty()); // Validation checks for compute shaders if (mCompiledState->shaderType == ShaderType::Compute && mCompiledState->localSize.isDeclared()) @@ -234,7 +256,7 @@ angle::Result CompileTask::postTranslate() // To support reading/writing compiled binaries (SPIR-V representation), need more file // input/output facilities, and figure out the byte ordering of writing the 32-bit words to // disk. - if (isBinaryOutput) + if (!mCompiledState->compiledBinary.empty()) { INFO() << "Can not substitute compiled binary (SPIR-V) shaders yet"; } @@ -245,7 +267,8 @@ angle::Result CompileTask::postTranslate() std::string substituteShader; if (angle::ReadFileToString(substituteShaderPath, &substituteShader)) { - mCompiledState->translatedSource = std::move(substituteShader); + mCompiledState->translatedSource = + std::make_shared(std::move(substituteShader)); substitutedTranslatedShader = true; INFO() << "Translated shader substitute found, loading from " << substituteShaderPath; @@ -257,22 +280,20 @@ angle::Result CompileTask::postTranslate() // same data back to the file. if (mFrontendFeatures.dumpTranslatedShaders.enabled && !substitutedTranslatedShader) { - if (isBinaryOutput) + if (!mCompiledState->compiledBinary.empty()) { INFO() << "Can not dump compiled binary (SPIR-V) shaders yet"; } else { std::string dumpFile = GetShaderDumpFilePath(mSourceHash, suffix); - - const std::string &translatedSource = mCompiledState->translatedSource; - writeFile(dumpFile.c_str(), translatedSource.c_str(), translatedSource.length()); + writeFile(dumpFile.c_str(), *mCompiledState->translatedSource); INFO() << "Dumped translated source: " << dumpFile; } } #if defined(ANGLE_ENABLE_ASSERTS) - if (!isBinaryOutput) + if (!mCompiledState->compiledBinary.empty()) { // Suffix the translated shader with commented out un-translated shader. // Useful in diagnostics tools which capture the shader source. @@ -281,12 +302,12 @@ angle::Result CompileTask::postTranslate() shaderStream << "// GLSL\n"; shaderStream << "//\n"; - std::istringstream inputSourceStream(mSource); + std::istringstream inputSourceStream(*mSource); std::string line; while (std::getline(inputSourceStream, line)) { // Remove null characters from the source line - line.erase(std::remove(line.begin(), line.end(), '\0'), line.end()); + std::erase(line, '\0'); shaderStream << "// " << line; @@ -298,7 +319,8 @@ angle::Result CompileTask::postTranslate() shaderStream << std::endl; } - mCompiledState->translatedSource += shaderStream.str(); + mCompiledState->translatedSource = + std::make_shared(*mCompiledState->translatedSource + shaderStream.str()); } #endif // defined(ANGLE_ENABLE_ASSERTS) @@ -398,7 +420,12 @@ struct CompileJobDone final : public CompileJob ShaderState::ShaderState(ShaderType shaderType) : mCompiledState(std::make_shared(shaderType)) -{} +{ + // Small optimization to avoid allocating another shared pointer to an empty string, use the one + // from CompiledShaderState instead since it starts initialized to an empty string. + mSource = mCompiledState->translatedSource; + ASSERT(mSource && mSource->empty()); +} ShaderState::~ShaderState() {} @@ -455,50 +482,12 @@ ShaderProgramID Shader::getHandle() const return mHandle; } -std::string Shader::joinShaderSources(GLsizei count, const char *const *string, const GLint *length) -{ - // Fast path for the most common case. - if (count == 1) - { - if (length == nullptr || length[0] < 0) - return std::string(string[0]); - else - return std::string(string[0], static_cast(length[0])); - } - - // Start with totalLength of 1 to reserve space for the null terminator - size_t totalLength = 1; - - // First pass, calculate the total length of the joined string - for (GLsizei i = 0; i < count; ++i) - { - if (length == nullptr || length[i] < 0) - totalLength += std::strlen(string[i]); - else - totalLength += static_cast(length[i]); - } - - // Second pass, allocate the string and concatenate each shader source - // fragment - std::string joinedString; - joinedString.reserve(totalLength); - for (GLsizei i = 0; i < count; ++i) - { - if (length == nullptr || length[i] < 0) - joinedString.append(string[i]); - else - joinedString.append(string[i], static_cast(length[i])); - } - - return joinedString; -} - void Shader::setSource(const Context *context, GLsizei count, const char *const *string, const GLint *length) { - std::string source = joinShaderSources(count, string, length); + std::string source = JoinShaderSources(count, string, length); // Compute the hash based on the original source before any substitutions size_t sourceHash = ComputeShaderHash(source); @@ -526,11 +515,11 @@ void Shader::setSource(const Context *context, { std::string dumpFile = GetShaderDumpFilePath(sourceHash, suffix); - writeFile(dumpFile.c_str(), source.c_str(), source.length()); + writeFile(dumpFile.c_str(), source); INFO() << "Dumped shader source: " << dumpFile; } - mState.mSource = std::move(source); + mState.mSource = std::make_shared(std::move(source)); mState.mSourceHash = sourceHash; } @@ -567,19 +556,24 @@ void Shader::getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length int Shader::getSourceLength() const { - return mState.mSource.empty() ? 0 : (static_cast(mState.mSource.length()) + 1); + if (mState.mSource->empty()) + { + return 0; + } + + return static_cast(mState.mSource->length()) + 1; } int Shader::getTranslatedSourceLength(const Context *context) { resolveCompile(context); - if (mState.mCompiledState->translatedSource.empty()) + if (mState.mCompiledState->translatedSource->empty()) { return 0; } - return static_cast(mState.mCompiledState->translatedSource.length()) + 1; + return static_cast(mState.mCompiledState->translatedSource->length()) + 1; } int Shader::getTranslatedSourceWithDebugInfoLength(const Context *context) @@ -595,31 +589,9 @@ int Shader::getTranslatedSourceWithDebugInfoLength(const Context *context) return (static_cast(debugInfo.length()) + 1); } -// static -void Shader::GetSourceImpl(const std::string &source, - GLsizei bufSize, - GLsizei *length, - char *buffer) -{ - int index = 0; - - if (bufSize > 0) - { - index = std::min(bufSize - 1, static_cast(source.length())); - memcpy(buffer, source.c_str(), index); - - buffer[index] = '\0'; - } - - if (length) - { - *length = index; - } -} - void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const { - GetSourceImpl(mState.mSource, bufSize, length, buffer); + GetSourceImpl(*mState.mSource, bufSize, length, buffer); } void Shader::getTranslatedSource(const Context *context, @@ -627,13 +599,14 @@ void Shader::getTranslatedSource(const Context *context, GLsizei *length, char *buffer) { - GetSourceImpl(getTranslatedSource(context), bufSize, length, buffer); + resolveCompile(context); + GetSourceImpl(*mState.mCompiledState->translatedSource, bufSize, length, buffer); } const std::string &Shader::getTranslatedSource(const Context *context) { resolveCompile(context); - return mState.mCompiledState->translatedSource; + return *mState.mCompiledState->translatedSource; } size_t Shader::getSourceHash() const @@ -667,26 +640,28 @@ void Shader::compile(const Context *context, angle::JobResultExpectancy resultEx // Add default options to WebGL shaders to prevent unexpected behavior during // compilation. - if (context->isWebGL()) + if (context->isWebGL() || context->isHardenedContext()) { options.initGLPosition = true; options.limitCallStackDepth = true; options.limitExpressionComplexity = true; options.enforcePackingRestrictions = true; options.initSharedVariables = true; - - if (context->getFrontendFeatures().rejectWebglShadersWithUndefinedBehavior.enabled) - { - options.rejectWebglShadersWithUndefinedBehavior = true; - } + options.rejectWebglShadersWithLargeVariables = true; + options.rejectWebglShadersWithUndefinedBehavior = true; } - else + else if (!context->isWebGL()) { // Per https://github.com/KhronosGroup/WebGL/pull/3278 gl_BaseVertex/gl_BaseInstance are // removed from WebGL options.emulateGLBaseVertexBaseInstance = true; } + if (context->getFrontendFeatures().useIr.enabled) + { + options.useIR = true; + } + if (context->getFrontendFeatures().forceInitShaderVariables.enabled) { options.initOutputVariables = true; @@ -697,6 +672,11 @@ void Shader::compile(const Context *context, angle::JobResultExpectancy resultEx options.validateAST = true; #endif + if (context->getState().usesPassthroughShaders()) + { + options.skipAllValidationAndTransforms = true; + } + // Find a shader in Blob Cache Compiler *compiler = context->getCompiler(); setShaderKey(context, options, compiler->getShaderOutputType(), @@ -722,6 +702,12 @@ void Shader::compile(const Context *context, angle::JobResultExpectancy resultEx } } + if (context->getState().usesPassthroughShaders()) + { + passthroughCompile(context, &options, resultExpectancy); + return; + } + mBoundCompiler.set(context, compiler); ASSERT(mBoundCompiler.get()); @@ -866,16 +852,15 @@ angle::Result Shader::serialize(const Context *context, angle::MemoryBuffer *bin stream.writeInt(kShaderCacheIdentifier); mState.mCompiledState->serialize(stream); - ASSERT(binaryOut); - if (!binaryOut->resize(stream.length())) + if (!binaryOut->resize(stream.size())) { ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, "Failed to allocate enough memory to serialize a shader. (%zu bytes)", - stream.length()); + stream.size()); return angle::Result::Stop; } - memcpy(binaryOut->data(), stream.data(), stream.length()); + angle::SpanMemcpy(binaryOut->span(), angle::Span(stream)); return angle::Result::Continue; } @@ -919,7 +904,7 @@ bool Shader::loadBinaryImpl(const Context *context, angle::JobResultExpectancy resultExpectancy, bool generatedWithOfflineCompiler) { - BinaryInputStream stream(binary, length); + BinaryInputStream stream(angle::Span(static_cast(binary), length)); mState.mCompiledState = std::make_shared(mState.getShaderType()); @@ -930,7 +915,7 @@ bool Shader::loadBinaryImpl(const Context *context, // Validation layer should have already verified that the shader program version and shader // type match std::vector commitString(angle::GetANGLEShaderProgramVersionHashSize(), 0); - stream.readBytes(commitString.data(), commitString.size()); + stream.readBytes(commitString); ASSERT(memcmp(commitString.data(), angle::GetANGLEShaderProgramVersion(), commitString.size()) == 0); @@ -943,15 +928,15 @@ bool Shader::loadBinaryImpl(const Context *context, stream.readEnum(&outputType); // Get the shader's source string. - mState.mSource = stream.readString(); + mState.mSource = std::make_shared(stream.readString()); // In the absence of element-by-element serialize/deserialize functions, read // ShCompileOptions and ShBuiltInResources as raw binary blobs. ShCompileOptions compileOptions; - stream.readBytes(reinterpret_cast(&compileOptions), sizeof(ShCompileOptions)); + stream.readBytes(angle::byte_span_from_ref(compileOptions)); ShBuiltInResources resources; - stream.readBytes(reinterpret_cast(&resources), sizeof(ShBuiltInResources)); + stream.readBytes(angle::byte_span_from_ref(resources)); setShaderKey(context, compileOptions, outputType, resources); } @@ -988,6 +973,30 @@ bool Shader::loadBinaryImpl(const Context *context, return true; } +void Shader::passthroughCompile(const Context *context, + ShCompileOptions *compileOptions, + angle::JobResultExpectancy resultExpectancy) +{ + mState.mCompiledState = std::make_shared(mState.getShaderType()); + mState.mCompiledState->buildPassthroughCompiledShaderState(mState.mSource); + + mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED; + + // Ask the backend to prepare the translate task + std::shared_ptr translateTask = + mImplementation->compile(context, compileOptions); + + std::shared_ptr compileTask(new CompileTask( + context->getFrontendFeatures(), mState.mCompiledState, std::move(translateTask))); + + const angle::JobThreadSafety threadSafety = GetTranslateTaskThreadSafety(context); + std::shared_ptr compileEvent = + context->postCompileLinkTask(compileTask, threadSafety, resultExpectancy); + + mCompileJob = std::make_shared(); + mCompileJob->compileEvent = std::make_unique(compileTask, compileEvent); +} + void Shader::setShaderKey(const Context *context, const ShCompileOptions &compileOptions, const ShShaderOutput &outputType, diff --git a/src/libANGLE/Shader.h b/src/libANGLE/Shader.h index fb53c72fab5..2301d55c030 100644 --- a/src/libANGLE/Shader.h +++ b/src/libANGLE/Shader.h @@ -81,7 +81,7 @@ class ShaderState final : angle::NonCopyable const std::string &getLabel() const { return mLabel; } - const std::string &getSource() const { return mSource; } + const std::string &getSource() const { return *mSource; } bool compilePending() const { return mCompileStatus == CompileStatus::COMPILE_REQUESTED; } CompileStatus getCompileStatus() const { return mCompileStatus; } @@ -97,7 +97,7 @@ class ShaderState final : angle::NonCopyable friend class Shader; std::string mLabel; - std::string mSource; + std::shared_ptr mSource; size_t mSourceHash = 0; SharedCompiledShaderState mCompiledState; @@ -190,28 +190,21 @@ class Shader final : angle::NonCopyable, public LabeledObject GLsizei length, angle::JobResultExpectancy resultExpectancy); - void writeShaderKey(BinaryOutputStream *streamOut) const - { - ASSERT(streamOut && !mShaderHash.empty()); - streamOut->writeBytes(mShaderHash.data(), egl::BlobCache::kKeyLength); - return; - } + void writeShaderKey(BinaryOutputStream *streamOut) const { streamOut->writeBytes(mShaderHash); } private: ~Shader() override; - static std::string joinShaderSources(GLsizei count, - const char *const *string, - const GLint *length); - static void GetSourceImpl(const std::string &source, - GLsizei bufSize, - GLsizei *length, - char *buffer); + bool loadBinaryImpl(const Context *context, const void *binary, GLsizei length, angle::JobResultExpectancy resultExpectancy, bool generatedWithOfflineCompiler); + void passthroughCompile(const Context *context, + ShCompileOptions *compileOptions, + angle::JobResultExpectancy resultExpectancy); + // Compute a key to uniquely identify the shader object in memory caches. void setShaderKey(const Context *context, const ShCompileOptions &compileOptions, diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp index 6be85b5742e..ffefe7f1a0b 100644 --- a/src/libANGLE/State.cpp +++ b/src/libANGLE/State.cpp @@ -6,6 +6,10 @@ // State.cpp: Implements the State class, encapsulating raw GL state. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/State.h" #include @@ -115,6 +119,21 @@ bool IsTextureCompatibleWithSampler(TextureType texture, TextureType sampler) return false; } +// While pixel local storage is active, the drawbuffers on and after 'firstPLSDrawBuffer' +// are blocked from the client and reserved for internal use by PLS. +bool HasPLSOverriddenDrawBuffers(const Caps &caps, + GLuint numActivePlanes, + GLint *firstPLSDrawBuffer) +{ + if (numActivePlanes != 0) + { + *firstPLSDrawBuffer = + caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - numActivePlanes; + return *firstPLSDrawBuffer < caps.maxDrawBuffers; + } + return false; +} + uint32_t gIDCounter = 1; } // namespace @@ -173,13 +192,14 @@ void UpdateBufferBinding(const Context *context, } } -void UpdateIndexedBufferBinding(const Context *context, +bool UpdateIndexedBufferBinding(const Context *context, OffsetBindingPointer *binding, Buffer *buffer, BufferBinding target, GLintptr offset, GLsizeiptr size) { + bool isBindingDirty = context->isWebGL(); if (context->isWebGL()) { if (target == BufferBinding::TransformFeedback) @@ -193,8 +213,21 @@ void UpdateIndexedBufferBinding(const Context *context, } else { - binding->set(context, buffer, offset, size); + ASSERT(!isBindingDirty); + isBindingDirty = binding->get() != buffer || binding->getOffset() != offset || + binding->getSize() != size; + // If buffer changed, update everything otherwise update just the offset and size + if (binding->get() != buffer) + { + binding->set(context, buffer, offset, size); + } + else if (buffer != nullptr) + { + binding->assignOffsetAndSize(offset, size); + } } + + return isBindingDirty; } // These template functions must be defined before they are instantiated in kBufferSetters. @@ -244,30 +277,7 @@ template <> void State::setGenericBufferBinding(const Context *context, Buffer *buffer) { - Buffer *oldBuffer = mVertexArray->mState.mElementArrayBuffer.get(); - if (oldBuffer) - { - oldBuffer->removeObserver(&mVertexArray->mState.mElementArrayBuffer); - oldBuffer->removeContentsObserver(mVertexArray, kElementArrayBufferIndex); - if (context->isWebGL()) - { - oldBuffer->onNonTFBindingChanged(-1); - } - oldBuffer->release(context); - } - mVertexArray->mState.mElementArrayBuffer.assign(buffer); - if (buffer) - { - buffer->addObserver(&mVertexArray->mState.mElementArrayBuffer); - buffer->addContentsObserver(mVertexArray, kElementArrayBufferIndex); - if (context->isWebGL()) - { - buffer->onNonTFBindingChanged(1); - } - buffer->addRef(); - } - mVertexArray->mDirtyBits.set(VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER); - mVertexArray->mIndexRangeCache.invalidate(); + mVertexArray->bindElementBuffer(context, buffer); mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); } @@ -356,6 +366,7 @@ PrivateState::PrivateState(const Version &clientVersion, mFragmentShaderDerivativeHint(GL_NONE), mNearZ(0), mFarZ(0), + mGroupMarkerCount(0), mProvokingVertex(gl::ProvokingVertexConvention::LastVertexConvention), mActiveSampler(0), mPrimitiveRestart(false), @@ -380,7 +391,10 @@ PrivateState::PrivateState(const Version &clientVersion, mBoundingBoxMaxZ(1.0f), mBoundingBoxMaxW(1.0f), mShadingRatePreserveAspectRatio(false), - mShadingRate(ShadingRate::Undefined), + mShadingRateQCOM(ShadingRate::Undefined), + // If the shading rate has not been set, the shading rate will be SHADING_RATE_1X1_PIXELS_EXT + mShadingRateEXT(ShadingRate::_1x1), + mCombinerOps{CombinerOp::Keep, CombinerOp::Keep}, mFetchPerSample(false), mIsPerfMonitorActive(false), mTiledRendering(false), @@ -388,7 +402,9 @@ PrivateState::PrivateState(const Version &clientVersion, mClientArraysEnabled(clientArraysEnabled), mRobustResourceInit(robustResourceInit), mProgramBinaryCacheEnabled(programBinaryCacheEnabled), - mDebug(debug) + mVertexArrayPrivate(nullptr), + mDebug(debug), + mVertexArrayHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES) {} PrivateState::~PrivateState() = default; @@ -458,7 +474,7 @@ void PrivateState::initialize(Context *context) // This coherent blending is enabled by default, but can be enabled or disabled by calling // glEnable() or glDisable() with the symbolic constant GL_BLEND_ADVANCED_COHERENT_KHR. - mBlendAdvancedCoherent = context->getExtensions().blendEquationAdvancedCoherentKHR; + mBlendAdvancedCoherent = true; mPrimitiveRestart = false; @@ -484,6 +500,7 @@ void PrivateState::initializeForCapture(const Context *context) void PrivateState::reset() { mClipDistancesEnabled.reset(); + mVertexArrayMap.clear(); } void PrivateState::setColorClearValue(float red, float green, float blue, float alpha) @@ -513,13 +530,16 @@ void PrivateState::setColorMask(bool red, bool green, bool blue, bool alpha) if (hasActivelyOverriddenPLSDrawBuffers(&firstPLSDrawBuffer)) { // Some draw buffers are currently overridden by pixel local storage. Update only the - // buffers that are still visible to the client. + // buffers that are still visible to the client and defer the remaining updates until PLS + // ends. + assert(firstPLSDrawBuffer == 0 || mExtensions.drawBuffersIndexedAny()); assert(firstPLSDrawBuffer < mCaps.maxDrawBuffers); for (GLint i = 0; i < firstPLSDrawBuffer; ++i) { ASSERT(mExtensions.drawBuffersIndexedAny()); setColorMaskIndexed(red, green, blue, alpha, i); } + mPLSDeferredColorMasks = mBlendStateExt.expandColorMaskValue(red, green, blue, alpha); return; } @@ -536,8 +556,10 @@ void PrivateState::setColorMaskIndexed(bool red, bool green, bool blue, bool alp { if (isActivelyOverriddenPLSDrawBuffer(index)) { - // The indexed draw buffer is currently overridden by pixel local storage. Setting the color - // mask has no effect. + // The indexed draw buffer is currently overridden by pixel local storage. Defer this update + // until PLS ends. + BlendStateExt::ColorMaskStorage::SetValueIndexed( + index, BlendStateExt::PackColorMask(red, green, blue, alpha), &mPLSDeferredColorMasks); return; } @@ -665,13 +687,17 @@ void PrivateState::setBlend(bool enabled) if (hasActivelyOverriddenPLSDrawBuffers(&firstPLSDrawBuffer)) { // Some draw buffers are currently overridden by pixel local storage. Update only the - // buffers that are still visible to the client. + // buffers that are still visible to the client and defer the remaining updates until PLS + // ends. + assert(firstPLSDrawBuffer == 0 || mExtensions.drawBuffersIndexedAny()); assert(firstPLSDrawBuffer < mCaps.maxDrawBuffers); for (GLint i = 0; i < firstPLSDrawBuffer; ++i) { ASSERT(mExtensions.drawBuffersIndexedAny()); setBlendIndexed(enabled, i); } + mPLSDeferredBlendEnables = + enabled ? mBlendStateExt.getAllEnabledMask() : DrawBufferMask::Zero(); return; } @@ -689,8 +715,9 @@ void PrivateState::setBlendIndexed(bool enabled, GLuint index) { if (isActivelyOverriddenPLSDrawBuffer(index)) { - // The indexed draw buffer is currently overridden by pixel local storage. Enabling - // blend has no effect. + // The indexed draw buffer is currently overridden by pixel local storage. Defer this update + // until PLS ends. + mPLSDeferredBlendEnables.set(index, enabled); return; } @@ -775,7 +802,7 @@ void PrivateState::setBlendColor(float red, float green, float blue, float alpha { // In ES2 without render-to-float extensions, BlendColor clamps to [0,1] on store. // On ES3+, or with render-to-float exts enabled, it does not clamp on store. - const bool isES2 = mClientVersion.major == 2; + const bool isES2 = mClientVersion == ES_2_0; const bool hasFloatBlending = mExtensions.colorBufferFloatEXT || mExtensions.colorBufferHalfFloatEXT || mExtensions.colorBufferFloatRgbCHROMIUM || mExtensions.colorBufferFloatRgbaCHROMIUM; @@ -941,6 +968,16 @@ void PrivateState::setPolygonOffsetFill(bool enabled) } } +void PrivateState::setFetchPerSample(bool enabled) +{ + if (mFetchPerSample != enabled) + { + mFetchPerSample = enabled; + mDirtyBits.set(state::DIRTY_BIT_EXTENDED); + mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED); + } +} + void PrivateState::setPolygonOffsetParams(GLfloat factor, GLfloat units, GLfloat clamp) { // An application can pass NaN values here, so handle this gracefully @@ -1088,11 +1125,26 @@ void PrivateState::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei he } } -void PrivateState::setShadingRate(GLenum rate) +void PrivateState::setShadingRateQCOM(ShadingRate rate) { - mShadingRate = FromGLenum(rate); + mShadingRateQCOM = rate; mDirtyBits.set(state::DIRTY_BIT_EXTENDED); - mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADING_RATE); + mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM); +} + +void PrivateState::setShadingRateEXT(ShadingRate rate) +{ + mShadingRateEXT = rate; + mDirtyBits.set(state::DIRTY_BIT_EXTENDED); + mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT); +} + +void PrivateState::setShadingRateCombinerOps(CombinerOp combinerOp0, CombinerOp combinerOp1) +{ + mCombinerOps[0] = combinerOp0; + mCombinerOps[1] = combinerOp1; + mDirtyBits.set(state::DIRTY_BIT_EXTENDED); + mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT); } void PrivateState::setPackAlignment(GLint alignment) @@ -1145,20 +1197,15 @@ void PrivateState::setUnpackImageHeight(GLint imageHeight) bool PrivateState::hasActivelyOverriddenPLSDrawBuffers(GLint *firstActivePLSDrawBuffer) const { - if (mPixelLocalStorageActivePlanes != 0) - { - *firstActivePLSDrawBuffer = - PixelLocalStorage::FirstOverriddenDrawBuffer(mCaps, mPixelLocalStorageActivePlanes); - return *firstActivePLSDrawBuffer < mCaps.maxDrawBuffers; - } - return false; + return HasPLSOverriddenDrawBuffers(mCaps, mPixelLocalStorageActivePlanes, + firstActivePLSDrawBuffer); } bool PrivateState::isActivelyOverriddenPLSDrawBuffer(GLint drawbuffer) const { - return mPixelLocalStorageActivePlanes != 0 && - drawbuffer >= - PixelLocalStorage::FirstOverriddenDrawBuffer(mCaps, mPixelLocalStorageActivePlanes); + GLint firstPLSDrawBuffer; + return hasActivelyOverriddenPLSDrawBuffers(&firstPLSDrawBuffer) && + drawbuffer >= firstPLSDrawBuffer; } void PrivateState::setUnpackSkipImages(GLint skipImages) @@ -1195,7 +1242,10 @@ void PrivateState::setFramebufferSRGB(bool sRGB) mFramebufferSRGB = sRGB; mDirtyBits.set(state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE); mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER); - mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + if (isRobustResourceInitEnabled()) + { + mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + } } } @@ -1210,7 +1260,98 @@ void PrivateState::setPatchVertices(GLuint value) void PrivateState::setPixelLocalStorageActivePlanes(GLsizei n) { - mPixelLocalStorageActivePlanes = n; + if (n != 0) + { + // Pixel local storage is beginning. + ASSERT(mPixelLocalStorageActivePlanes == 0); + + GLint firstPLSDrawBuffer; + if (HasPLSOverriddenDrawBuffers(mCaps, n, &firstPLSDrawBuffer)) + { + // Save the original blend & color mask state so we can restore it when PLS ends. + mPLSDeferredBlendEnables = mBlendStateExt.getEnabledMask(); + mPLSDeferredColorMasks = mBlendStateExt.getColorMaskBits(); + + // Disable blend & enable color mask on the reserved PLS planes. + if (firstPLSDrawBuffer == 0) + { + if (mBlendStateExt.getEnabledMask().test(0)) + { + setBlend(false); + } + if (mBlendStateExt.getColorMaskIndexed(0) != BlendStateExt::kColorMaskRGBA) + { + setColorMask(true, true, true, true); + } + } + else + { + ASSERT(mExtensions.drawBuffersIndexedAny()); + for (GLint i = firstPLSDrawBuffer; i < mCaps.maxDrawBuffers; ++i) + { + if (mBlendStateExt.getEnabledMask().test(i)) + { + setBlendIndexed(false, i); + } + if (mBlendStateExt.getColorMaskIndexed(i) != BlendStateExt::kColorMaskRGBA) + { + setColorMaskIndexed(true, true, true, true, i); + } + } + } + } + + // Set mPixelLocalStorageActivePlanes last, so the setBlend()/setColorMask() calls above + // don't bounce. + mPixelLocalStorageActivePlanes = n; + } + else + { + // Pixel local storage is ending. + ASSERT(mPixelLocalStorageActivePlanes != 0); + + // Set mPixelLocalStorageActivePlanes first, so the following calls to + // setBlend()/setColorMask() don't bounce. + GLsizei formerPLSPlaneCount = mPixelLocalStorageActivePlanes; + mPixelLocalStorageActivePlanes = 0; + + GLint firstPLSDrawBuffer; + if (HasPLSOverriddenDrawBuffers(mCaps, formerPLSPlaneCount, &firstPLSDrawBuffer)) + { + bool r, g, b, a; + if (firstPLSDrawBuffer == 0) + { + if (mPLSDeferredBlendEnables.test(0)) + { + setBlend(true); + } + const uint8_t colorMask = + BlendStateExt::ColorMaskStorage::GetValueIndexed(0, mPLSDeferredColorMasks); + if (colorMask != BlendStateExt::kColorMaskRGBA) + { + BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a); + setColorMask(r, g, b, a); + } + } + else + { + for (GLint i = firstPLSDrawBuffer; i < mCaps.maxDrawBuffers; ++i) + { + if (mPLSDeferredBlendEnables.test(i)) + { + setBlendIndexed(true, i); + } + const uint8_t colorMask = + BlendStateExt::ColorMaskStorage::GetValueIndexed(i, mPLSDeferredColorMasks); + if (colorMask != BlendStateExt::kColorMaskRGBA) + { + BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a); + setColorMaskIndexed(r, g, b, a, i); + } + } + } + } + } } void PrivateState::setLineWidth(GLfloat width) @@ -1379,7 +1520,7 @@ void PrivateState::setEnableFeature(GLenum feature, bool enabled) setDither(enabled); return; case GL_COLOR_LOGIC_OP: - if (mClientVersion.major == 1) + if (mClientVersion < ES_2_0) { // Handle logicOp in GLES1 through the GLES1 state management and emulation. // Otherwise this state could be set as part of ANGLE_logic_op. @@ -1422,7 +1563,7 @@ void PrivateState::setEnableFeature(GLenum feature, bool enabled) case GL_CLIP_DISTANCE7_EXT: // NOTE(hqle): These enums are conflicted with GLES1's enums, need // to do additional check here: - if (mClientVersion.major >= 2) + if (mClientVersion >= ES_2_0) { setClipDistanceEnable(feature - GL_CLIP_DISTANCE0_EXT, enabled); return; @@ -1432,13 +1573,13 @@ void PrivateState::setEnableFeature(GLenum feature, bool enabled) mShadingRatePreserveAspectRatio = enabled; return; case GL_FETCH_PER_SAMPLE_ARM: - mFetchPerSample = enabled; + setFetchPerSample(enabled); return; default: break; } - ASSERT(mClientVersion.major == 1); + ASSERT(mClientVersion < ES_2_0); // GLES1 emulation. Need to separate from main switch due to conflict enum between // GL_CLIP_DISTANCE0_EXT & GL_CLIP_PLANE0 @@ -1550,7 +1691,7 @@ bool PrivateState::getEnableFeature(GLenum feature) const case GL_DITHER: return isDitherEnabled(); case GL_COLOR_LOGIC_OP: - if (mClientVersion.major == 1) + if (mClientVersion < ES_2_0) { // Handle logicOp in GLES1 through the GLES1 state management and emulation. break; @@ -1589,7 +1730,7 @@ bool PrivateState::getEnableFeature(GLenum feature) const case GL_CLIP_DISTANCE5_EXT: case GL_CLIP_DISTANCE6_EXT: case GL_CLIP_DISTANCE7_EXT: - if (mClientVersion.major >= 2) + if (mClientVersion >= ES_2_0) { // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as // GL_CLIP_PLANE0 instead. @@ -1602,7 +1743,7 @@ bool PrivateState::getEnableFeature(GLenum feature) const return mFetchPerSample; } - ASSERT(mClientVersion.major == 1); + ASSERT(mClientVersion < ES_2_0); switch (feature) { @@ -1688,12 +1829,7 @@ void PrivateState::getBooleanv(GLenum pname, GLboolean *params) const case GL_COLOR_WRITEMASK: { // non-indexed get returns the state of draw buffer zero - bool r, g, b, a; - mBlendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a); - params[0] = r; - params[1] = g; - params[2] = b; - params[3] = a; + getBooleani_v(GL_COLOR_WRITEMASK, 0, params); break; } case GL_CULL_FACE: @@ -1730,14 +1866,13 @@ void PrivateState::getBooleanv(GLenum pname, GLboolean *params) const *params = mDepthStencil.depthTest; break; case GL_BLEND: - // non-indexed get returns the state of draw buffer zero - *params = mBlendStateExt.getEnabledMask().test(0); + *params = isBlendEnabled(); break; case GL_DITHER: *params = mRasterizer.dither; break; case GL_COLOR_LOGIC_OP: - if (mClientVersion.major == 1) + if (mClientVersion < ES_2_0) { // Handle logicOp in GLES1 through the GLES1 state management. *params = getEnableFeature(pname); @@ -1804,7 +1939,7 @@ void PrivateState::getBooleanv(GLenum pname, GLboolean *params) const case GL_CLIP_DISTANCE5_EXT: case GL_CLIP_DISTANCE6_EXT: case GL_CLIP_DISTANCE7_EXT: - if (mClientVersion.major >= 2) + if (mClientVersion >= ES_2_0) { // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as // GL_CLIP_PLANE0 instead. @@ -1819,8 +1954,13 @@ void PrivateState::getBooleanv(GLenum pname, GLboolean *params) const case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM: *params = mCaps.fragmentShaderFramebufferFetchMRT; break; + // EXT_fragment_shading_rate + case GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT: + *params = + mCaps.fragmentShadingRateProperties.fragmentShadingRateNonTrivialCombinersSupport; + break; default: - if (mClientVersion.major == 1) + if (mClientVersion < ES_2_0) { *params = getEnableFeature(pname); } @@ -2013,7 +2153,7 @@ void PrivateState::getIntegerv(GLenum pname, GLint *params) const *params = mStencilRef; break; case GL_STENCIL_VALUE_MASK: - *params = CastMaskValue(mDepthStencil.stencilMask); + *params = mDepthStencil.stencilMask; break; case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; @@ -2022,7 +2162,7 @@ void PrivateState::getIntegerv(GLenum pname, GLint *params) const *params = mStencilBackRef; break; case GL_STENCIL_BACK_VALUE_MASK: - *params = CastMaskValue(mDepthStencil.stencilBackMask); + *params = mDepthStencil.stencilBackMask; break; case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; @@ -2065,10 +2205,10 @@ void PrivateState::getIntegerv(GLenum pname, GLint *params) const *params = ToGLenum(mBlendStateExt.getEquationAlphaIndexed(0)); break; case GL_STENCIL_WRITEMASK: - *params = CastMaskValue(mDepthStencil.stencilWritemask); + *params = mDepthStencil.stencilWritemask; break; case GL_STENCIL_BACK_WRITEMASK: - *params = CastMaskValue(mDepthStencil.stencilBackWritemask); + *params = mDepthStencil.stencilBackWritemask; break; case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; @@ -2157,7 +2297,12 @@ void PrivateState::getIntegerv(GLenum pname, GLint *params) const // GL_QCOM_shading_rate case GL_SHADING_RATE_QCOM: - *params = ToGLenum(mShadingRate); + *params = ToGLenum(mShadingRateQCOM); + break; + + // GL_EXT_fragment_shading_rate + case GL_SHADING_RATE_EXT: + *params = ToGLenum(mShadingRateEXT); break; // GL_ANGLE_shader_pixel_local_storage @@ -2175,6 +2320,7 @@ void PrivateState::getIntegerv(GLenum pname, GLint *params) const *params = mCaps.fragmentShaderFramebufferFetchMRT ? 1 : 0; break; + // GL_KHR_blend_equation_advanced_coherent case GL_BLEND_ADVANCED_COHERENT_KHR: *params = mBlendAdvancedCoherent ? 1 : 0; break; @@ -2230,8 +2376,12 @@ void PrivateState::getBooleani_v(GLenum target, GLuint index, GLboolean *data) c case GL_COLOR_WRITEMASK: { ASSERT(static_cast(index) < mBlendStateExt.getDrawBufferCount()); + const uint8_t colorMask = isActivelyOverriddenPLSDrawBuffer(index) + ? BlendStateExt::ColorMaskStorage::GetValueIndexed( + index, mPLSDeferredColorMasks) + : mBlendStateExt.getColorMaskIndexed(index); bool r, g, b, a; - mBlendStateExt.getColorMaskIndexed(index, &r, &g, &b, &a); + BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a); data[0] = r; data[1] = g; data[2] = b; @@ -2244,6 +2394,49 @@ void PrivateState::getBooleani_v(GLenum target, GLuint index, GLboolean *data) c } } +VertexArrayID PrivateState::getVertexArrayId() const +{ + ASSERT(mVertexArrayPrivate != nullptr); + return mVertexArrayPrivate->id(); +} + +void PrivateState::setVertexAttribFormat(GLuint attribIndex, + GLint size, + VertexAttribType type, + bool normalized, + bool pureInteger, + GLuint relativeOffset) +{ + mVertexArrayPrivate->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger, + relativeOffset); + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); +} + +void PrivateState::setVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) +{ + mVertexArrayPrivate->setVertexAttribBinding(attribIndex, bindingIndex); + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); +} + +void PrivateState::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor) +{ + mVertexArrayPrivate->setVertexBindingDivisor(bindingIndex, divisor); + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); +} + +void PrivateState::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) +{ + mVertexArrayPrivate->enableAttribute(attribNum, enabled); + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); +} + +void PrivateState::setVertexAttribDivisor(GLuint index, GLuint divisor) +{ + mVertexArrayPrivate->setVertexAttribDivisor(index, divisor); + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); +} + +// State implementation. State::State(const State *shareContextState, egl::ShareGroup *shareGroup, TextureManager *shareTextures, @@ -2259,12 +2452,14 @@ State::State(const State *shareContextState, EGLenum contextPriority, bool hasRobustAccess, bool hasProtectedContent, - bool isExternal) + bool isExternal, + bool passthroughShaders) : mID({gIDCounter++}), mContextPriority(contextPriority), mHasRobustAccess(hasRobustAccess), mHasProtectedContent(hasProtectedContent), mIsDebugContext(debug), + mPassthroughShaders(passthroughShaders), mShareGroup(shareGroup), mContextMutex(contextMutex), mBufferManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mBufferManager)), @@ -2658,6 +2853,29 @@ void State::invalidateTextureBindings(TextureType type) mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS); } +bool State::isTextureBoundToActivePLS(TextureID textureID) const +{ + if (getPixelLocalStorageActivePlanes() == 0) + { + return false; + } + PixelLocalStorage *pls = getDrawFramebuffer()->peekPixelLocalStorage(); + if (pls == nullptr) + { + // Even though there is a nonzero number of active PLS planes, peekPixelLocalStorage() may + // still return null if we are in the middle of deleting the active framebuffer. + return false; + } + for (GLuint i = 0; i < getCaps().maxPixelLocalStoragePlanes; ++i) + { + if (pls->getPlane(i).getTextureID() == textureID) + { + return true; + } + } + return false; +} + void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler) { if (mSamplers[textureUnit].get() == sampler) @@ -2762,6 +2980,7 @@ void State::setDrawFramebufferBinding(Framebuffer *framebuffer) if (isRobustResourceInitEnabled() && mDrawFramebuffer->hasResourceThatNeedsInit()) { mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER); } } } @@ -2810,8 +3029,11 @@ bool State::removeDrawFramebufferBinding(FramebufferID framebuffer) void State::setVertexArrayBinding(const Context *context, VertexArray *vertexArray) { + // We have to call onBindingChanged even if we are rebinding the same vertex array, because + // underlying buffer may have changed. if (mVertexArray == vertexArray) { + mVertexArray->onRebind(context); return; } @@ -2825,6 +3047,8 @@ void State::setVertexArrayBinding(const Context *context, VertexArray *vertexArr } mVertexArray = vertexArray; + mPrivateState.setVertexArrayPrivate(vertexArray); + mDirtyBits.set(state::DIRTY_BIT_VERTEX_ARRAY_BINDING); if (mVertexArray && mVertexArray->hasAnyDirtyBit()) @@ -2839,6 +3063,7 @@ bool State::removeVertexArrayBinding(const Context *context, VertexArrayID verte { mVertexArray->onBindingChanged(context, -1); mVertexArray = nullptr; + mPrivateState.setVertexArrayPrivate(nullptr); mDirtyBits.set(state::DIRTY_BIT_VERTEX_ARRAY_BINDING); mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); return true; @@ -2863,24 +3088,6 @@ void State::bindVertexBuffer(const Context *context, mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); } -void State::setVertexAttribFormat(GLuint attribIndex, - GLint size, - VertexAttribType type, - bool normalized, - bool pureInteger, - GLuint relativeOffset) -{ - getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger, - relativeOffset); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); -} - -void State::setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor) -{ - getVertexArray()->setVertexBindingDivisor(context, bindingIndex, divisor); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); -} - angle::Result State::setProgram(const Context *context, Program *newProgram) { if (newProgram && !newProgram->isLinked()) @@ -3049,7 +3256,10 @@ angle::Result State::setIndexedBufferBinding(const Context *context, GLintptr offset, GLsizeiptr size) { - setBufferBinding(context, target, buffer); + if (mBoundBuffers[target].get() != buffer) + { + setBufferBinding(context, target, buffer); + } switch (target) { @@ -3058,20 +3268,43 @@ angle::Result State::setIndexedBufferBinding(const Context *context, setBufferBinding(context, target, buffer); break; case BufferBinding::Uniform: + { mBoundUniformBuffersMask.set(index, buffer != nullptr); - UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset, - size); - onUniformBufferStateChange(index); - break; + BufferDirtyTypeBitMask dirtyTypeMask = {}; + if (mUniformBuffers[index].get() != buffer) + { + dirtyTypeMask.set(); + } + else + { + dirtyTypeMask.set(BufferDirtyType::Offset, + buffer && mUniformBuffers[index].getOffset() != offset); + dirtyTypeMask.set(BufferDirtyType::Size, + buffer && mUniformBuffers[index].getSize() != size); + } + mUniformBufferBlocksDirtyTypeMask |= dirtyTypeMask; + if (UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset, + size)) + { + onUniformBufferStateChange(index, angle::SubjectMessage::SubjectChanged); + } + } + break; case BufferBinding::AtomicCounter: mBoundAtomicCounterBuffersMask.set(index, buffer != nullptr); - UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target, - offset, size); + if (UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target, + offset, size)) + { + onAtomicCounterBufferStateChange(index); + } break; case BufferBinding::ShaderStorage: mBoundShaderStorageBuffersMask.set(index, buffer != nullptr); - UpdateIndexedBufferBinding(context, &mShaderStorageBuffers[index], buffer, target, - offset, size); + if (UpdateIndexedBufferBinding(context, &mShaderStorageBuffers[index], buffer, target, + offset, size)) + { + onShaderStorageBufferStateChange(index); + } break; default: UNREACHABLE(); @@ -3114,13 +3347,13 @@ angle::Result State::detachBuffer(Context *context, const Buffer *buffer) if (curTransformFeedback) { ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID)); - context->getStateCache().onActiveTransformFeedbackChange(context); + context->onActiveTransformFeedbackChange(); } if (mVertexArray && mVertexArray->detachBuffer(context, bufferID)) { mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); - context->getStateCache().onVertexArrayStateChange(context); + context->getMutablePrivateStateCache()->onVertexArrayStateChange(); } for (size_t uniformBufferIndex : mBoundUniformBuffersMask) @@ -3161,18 +3394,6 @@ angle::Result State::detachBuffer(Context *context, const Buffer *buffer) return angle::Result::Continue; } -void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) -{ - getVertexArray()->enableAttribute(attribNum, enabled); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); -} - -void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor) -{ - getVertexArray()->setVertexAttribDivisor(context, index, divisor); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); -} - const void *State::getVertexAttribPointer(unsigned int attribNum) const { return getVertexArray()->getVertexAttribute(attribNum).pointer; @@ -3513,7 +3734,7 @@ void State::getIntegeri_v(const Context *context, GLenum target, GLuint index, G break; case GL_VERTEX_BINDING_BUFFER: ASSERT(static_cast(index) < mVertexArray->getMaxBindings()); - *data = mVertexArray->getVertexBinding(index).getBuffer().id().value; + *data = mVertexArray->getVertexArrayBufferID(index).value; break; case GL_VERTEX_BINDING_DIVISOR: ASSERT(static_cast(index) < mVertexArray->getMaxBindings()); @@ -3789,7 +4010,7 @@ angle::Result State::syncProgramPipelineObject(const Context *context, Command c return angle::Result::Continue; } -angle::Result State::syncDirtyObject(const Context *context, GLenum target) +angle::Result State::syncDirtyObject(const Context *context, GLenum target, Command command) { state::DirtyObjects localSet; @@ -3797,16 +4018,24 @@ angle::Result State::syncDirtyObject(const Context *context, GLenum target) { case GL_READ_FRAMEBUFFER: localSet.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER); + if (mDirtyObjects.test(state::DIRTY_OBJECT_READ_ATTACHMENTS)) + { + localSet.set(state::DIRTY_OBJECT_READ_ATTACHMENTS); + } break; case GL_DRAW_FRAMEBUFFER: localSet.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER); + if (mDirtyObjects.test(state::DIRTY_OBJECT_DRAW_ATTACHMENTS)) + { + localSet.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + } break; default: UNREACHABLE(); break; } - return syncDirtyObjects(context, localSet, Command::Other); + return syncDirtyObjects(context, localSet, command); } void State::setObjectDirty(GLenum target) @@ -3914,9 +4143,10 @@ angle::Result State::onExecutableChange(const Context *context) } } - // Mark uniform blocks as _not_ dirty. When an executable changes, the backends should already - // reprocess all uniform blocks. These dirty bits only track what's made dirty afterwards. - mDirtyUniformBlocks.reset(); + // Set all active blocks dirty on executable change + mDirtyUniformBlocks = mExecutable->getActiveUniformBufferBlocks(); + // Set all types dirty on executable change + mUniformBufferBlocksDirtyTypeMask.set(); return angle::Result::Continue; } @@ -4018,14 +4248,27 @@ void State::onImageStateChange(const Context *context, size_t unit) } } -void State::onUniformBufferStateChange(size_t uniformBufferIndex) +void State::onUniformBufferStateChange(size_t uniformBufferIndex, angle::SubjectMessage message) { if (mExecutable) { // When a buffer at a given binding changes, set all blocks mapped to it dirty. mDirtyUniformBlocks |= mExecutable->getUniformBufferBlocksMappedToBinding(uniformBufferIndex); + + if (message == angle::SubjectMessage::InternalMemoryAllocationChanged) + { + mUniformBufferBlocksDirtyTypeMask.set(BufferDirtyType::Binding); + } + else + { + ASSERT(message == angle::SubjectMessage::SubjectChanged || // buffer state change + message == angle::SubjectMessage::SubjectMapped || // buffer map + message == angle::SubjectMessage::SubjectUnmapped || // buffer unmap + message == angle::SubjectMessage::BindingChanged); // XFB state change + } } + // This could be represented by a different dirty bit. Using the same one keeps it simple. mDirtyBits.set(state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS); } diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h index 4f360a49d53..b2000e87ecc 100644 --- a/src/libANGLE/State.h +++ b/src/libANGLE/State.h @@ -18,12 +18,14 @@ #include "libANGLE/ContextMutex.h" #include "libANGLE/Debug.h" #include "libANGLE/GLES1State.h" +#include "libANGLE/HandleAllocator.h" #include "libANGLE/Overlay.h" #include "libANGLE/Program.h" #include "libANGLE/ProgramExecutable.h" #include "libANGLE/ProgramPipeline.h" #include "libANGLE/RefCountObject.h" #include "libANGLE/Renderbuffer.h" +#include "libANGLE/ResourceMap.h" #include "libANGLE/Sampler.h" #include "libANGLE/Texture.h" #include "libANGLE/TransformFeedback.h" @@ -53,13 +55,6 @@ class SyncManager; class TextureManager; class VertexArray; -static constexpr Version ES_1_0 = Version(1, 0); -static constexpr Version ES_1_1 = Version(1, 1); -static constexpr Version ES_2_0 = Version(2, 0); -static constexpr Version ES_3_0 = Version(3, 0); -static constexpr Version ES_3_1 = Version(3, 1); -static constexpr Version ES_3_2 = Version(3, 2); - template using BufferBindingMap = angle::PackedEnumMap; using BoundBufferMap = BufferBindingMap>; @@ -146,9 +141,10 @@ enum DirtyBitType DIRTY_BIT_TEXTURE_BINDINGS, DIRTY_BIT_IMAGE_BINDINGS, DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING, - DIRTY_BIT_UNIFORM_BUFFER_BINDINGS, DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING, DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING, + // Top-level dirty bit. Also see mUniformBufferBlocksDirtyTypeMask. + DIRTY_BIT_UNIFORM_BUFFER_BINDINGS, DIRTY_BIT_MULTISAMPLING, DIRTY_BIT_SAMPLE_ALPHA_TO_ONE, DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples @@ -176,7 +172,9 @@ enum ExtendedDirtyBitType EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED, // NV_polygon_mode EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED, // NV_polygon_mode EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT, // shader derivative hint - EXTENDED_DIRTY_BIT_SHADING_RATE, // QCOM_shading_rate + EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED, // FETCH_PER_SAMPLE_ARM + EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM, // QCOM_shading_rate + EXTENDED_DIRTY_BIT_SHADING_RATE_EXT, // EXT_fragment_shading_rate EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED, // ANGLE_logic_op EXTENDED_DIRTY_BIT_LOGIC_OP, // ANGLE_logic_op EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT, // KHR_blend_operation_advanced_coherent @@ -193,8 +191,8 @@ enum DirtyObjectType DIRTY_OBJECT_ACTIVE_TEXTURES, // Top-level dirty bit. Also see mDirtyActiveTextures. DIRTY_OBJECT_TEXTURES_INIT, DIRTY_OBJECT_IMAGES_INIT, - DIRTY_OBJECT_READ_ATTACHMENTS, - DIRTY_OBJECT_DRAW_ATTACHMENTS, + DIRTY_OBJECT_READ_ATTACHMENTS, // Only used if robust resource init is enabled + DIRTY_OBJECT_DRAW_ATTACHMENTS, // Only used if robust resource init is enabled DIRTY_OBJECT_READ_FRAMEBUFFER, DIRTY_OBJECT_DRAW_FRAMEBUFFER, DIRTY_OBJECT_VERTEX_ARRAY, @@ -210,6 +208,8 @@ using DirtyObjects = angle::BitSet; } // namespace state +using VertexArrayMap = ResourceMap; + // This class represents the portion of the GL context's state that is purely private to the // context. Manipulating this state does not affect the other contexts in any way, nor do operations // in other contexts affect this. @@ -235,11 +235,9 @@ class PrivateState : angle::NonCopyable void reset(); const Version &getClientVersion() const { return mClientVersion; } - GLint getClientMajorVersion() const { return mClientVersion.major; } - GLint getClientMinorVersion() const { return mClientVersion.minor; } bool isWebGL() const { return getExtensions().webglCompatibilityANGLE; } - bool isWebGL1() const { return isWebGL() && getClientVersion().major == 2; } + bool isWebGL1() const { return isWebGL() && getClientVersion() == ES_2_0; } bool isGLES1() const { return getClientVersion() < ES_2_0; } const Caps &getCaps() const { return mCaps; } @@ -282,6 +280,9 @@ class PrivateState : angle::NonCopyable bool isPrimitiveRestartEnabled() const { return mPrimitiveRestart; } void setPrimitiveRestart(bool enabled); + // FETCH_PER_SAMPLE_ARM + void setFetchPerSample(bool enabled); + // Face culling state manipulation bool isCullFaceEnabled() const { return mRasterizer.cullFace; } void setCullFace(bool enabled); @@ -308,11 +309,13 @@ class PrivateState : angle::NonCopyable bool isClipDepthModeZeroToOne() const { return mClipDepthMode == ClipDepthMode::ZeroToOne; } // Blend state manipulation - bool isBlendEnabled() const { return mBlendStateExt.getEnabledMask().test(0); } + bool isBlendEnabled() const { return isBlendEnabledIndexed(0); } bool isBlendEnabledIndexed(GLuint index) const { ASSERT(static_cast(index) < mBlendStateExt.getDrawBufferCount()); - return mBlendStateExt.getEnabledMask().test(index); + return isActivelyOverriddenPLSDrawBuffer(index) + ? mPLSDeferredBlendEnables.test(index) + : mBlendStateExt.getEnabledMask().test(index); } DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendStateExt.getEnabledMask(); } void setBlend(bool enabled); @@ -426,8 +429,15 @@ class PrivateState : angle::NonCopyable const Rectangle &getViewport() const { return mViewport; } // QCOM_shading_rate helpers - void setShadingRate(GLenum rate); - ShadingRate getShadingRate() const { return mShadingRate; } + void setShadingRateQCOM(ShadingRate rate); + ShadingRate getShadingRateQCOM() const { return mShadingRateQCOM; } + + // GL_EXT_fragment_shading_rate helpers + void setShadingRateEXT(ShadingRate rate); + ShadingRate getShadingRateEXT() const { return mShadingRateEXT; } + void setShadingRateCombinerOps(CombinerOp combinerOp0, CombinerOp combinerOp1); + const std::array &getShadingRateCombinerOps() const { return mCombinerOps; } + bool getFetchPerSample() const { return mFetchPerSample; } // Pixel pack state manipulation void setPackAlignment(GLint alignment); @@ -562,6 +572,13 @@ class PrivateState : angle::NonCopyable void setVertexAttribu(GLuint index, const GLuint values[4]); void setVertexAttribi(GLuint index, const GLint values[4]); + void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); + void setVertexArrayPrivate(VertexArrayPrivate *vertexArrayPrivate) + { + mVertexArrayPrivate = vertexArrayPrivate; + } + VertexArrayPrivate *getVertexArrayPrivate() const { return mVertexArrayPrivate; } + // QCOM_tiled_rendering void setTiledRendering(bool tiledRendering) { mTiledRendering = tiledRendering; } bool isTiledRendering() const { return mTiledRendering; } @@ -591,7 +608,6 @@ class PrivateState : angle::NonCopyable const GLES1State &gles1() const { return mGLES1State; } const state::DirtyBits &getDirtyBits() const { return mDirtyBits; } - void clearDirtyBits() { mDirtyBits.reset(); } void clearDirtyBits(const state::DirtyBits &bitset) { mDirtyBits &= ~bitset; } void setAllDirtyBits() { @@ -601,7 +617,6 @@ class PrivateState : angle::NonCopyable } const state::ExtendedDirtyBits &getExtendedDirtyBits() const { return mExtendedDirtyBits; } - void clearExtendedDirtyBits() { mExtendedDirtyBits.reset(); } void clearExtendedDirtyBits(const state::ExtendedDirtyBits &bitset) { mExtendedDirtyBits &= ~bitset; @@ -613,6 +628,54 @@ class PrivateState : angle::NonCopyable void setPerfMonitorActive(bool active) { mIsPerfMonitorActive = active; } bool isPerfMonitorActive() const { return mIsPerfMonitorActive; } + bool allocateVertexID(VertexArrayID *outId) + { + if (!mVertexArrayHandleAllocator.allocate(&outId->value)) + { + return false; + } + mVertexArrayMap.assign(*outId, nullptr); + return true; + } + bool isVertexArrayGenerated(VertexArrayID vertexArray) const + { + ASSERT(mVertexArrayMap.contains({0})); + return mVertexArrayMap.contains(vertexArray); + } + VertexArray *getVertexArray(VertexArrayID handle) const + { + return mVertexArrayMap.query(handle); + } + void setVertexArray(VertexArrayID handle, VertexArray *vertexArray) + { + ASSERT(getVertexArray(handle) == nullptr); + ASSERT(vertexArray != nullptr); + return mVertexArrayMap.assign(handle, vertexArray); + } + void eraseVertexArray(VertexArrayID handle, VertexArray **vertexArrayObjectOut) + { + if (mVertexArrayMap.erase(handle, vertexArrayObjectOut)) + { + mVertexArrayHandleAllocator.release(handle.value); + } + } + const VertexArrayMap &getVertexArrayMap() const { return mVertexArrayMap; } + + void setVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex); + void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor); + void setVertexAttribDivisor(GLuint index, GLuint divisor); + VertexArrayID getVertexArrayId() const; + void setVertexAttribFormat(GLuint attribIndex, + GLint size, + VertexAttribType type, + bool normalized, + bool pureInteger, + GLuint relativeOffset); + + GLuint getGroupMarkerCount() const { return mGroupMarkerCount; } + void incrementGroupMarkers() { mGroupMarkerCount++; } + void decrementGroupMarkers() { mGroupMarkerCount--; } + private: bool hasConstantColor(GLenum sourceRGB, GLenum destRGB) const; bool hasConstantAlpha(GLenum sourceRGB, GLenum destRGB) const; @@ -665,6 +728,10 @@ class PrivateState : angle::NonCopyable ClipOrigin mClipOrigin; ClipDepthMode mClipDepthMode; + // GL_EXT_debug_marker + // Keeps track of debug group marker count. Pop calls are ignored if there is no marker to pop. + GLuint mGroupMarkerCount; + // GL_ANGLE_provoking_vertex ProvokingVertexConvention mProvokingVertex; @@ -709,6 +776,10 @@ class PrivateState : angle::NonCopyable // GL_ANGLE_shader_pixel_local_storage GLsizei mPixelLocalStorageActivePlanes; + // Overridden PLS draw buffers require no blend and a full color mask. While PLS is active, + // defer any updates to these states until it ends. + DrawBufferMask mPLSDeferredBlendEnables; + BlendStateExt::ColorMaskStorage::Type mPLSDeferredColorMasks; // GLES1 emulation: state specific to GLES1 GLES1State mGLES1State; @@ -735,7 +806,11 @@ class PrivateState : angle::NonCopyable // QCOM_shading_rate bool mShadingRatePreserveAspectRatio; - ShadingRate mShadingRate; + ShadingRate mShadingRateQCOM; + + // GL_EXT_fragment_shading_rate + ShadingRate mShadingRateEXT; + std::array mCombinerOps; // GL_ARM_shader_framebuffer_fetch bool mFetchPerSample; @@ -751,6 +826,8 @@ class PrivateState : angle::NonCopyable const bool mRobustResourceInit; const bool mProgramBinaryCacheEnabled; + VertexArrayPrivate *mVertexArrayPrivate; + Debug mDebug; // ANGLE_blob_cache @@ -760,6 +837,9 @@ class PrivateState : angle::NonCopyable state::ExtendedDirtyBits mExtendedDirtyBits; state::DirtyObjects mDirtyObjects; mutable AttributesMask mDirtyCurrentValues; + + VertexArrayMap mVertexArrayMap; + HandleAllocator mVertexArrayHandleAllocator; }; // This class represents all of the GL context's state. @@ -781,7 +861,8 @@ class State : angle::NonCopyable EGLenum contextPriority, bool hasRobustAccess, bool hasProtectedContent, - bool isExternal); + bool isExternal, + bool passthroughShaders); ~State(); void initialize(Context *context); @@ -793,8 +874,6 @@ class State : angle::NonCopyable bool hasRobustAccess() const { return mHasRobustAccess; } bool hasProtectedContent() const { return mHasProtectedContent; } bool isDebugContext() const { return mIsDebugContext; } - GLint getClientMajorVersion() const { return mPrivateState.getClientMajorVersion(); } - GLint getClientMinorVersion() const { return mPrivateState.getClientMinorVersion(); } const Version &getClientVersion() const { return mPrivateState.getClientVersion(); } egl::ShareGroup *getShareGroup() const { return mShareGroup; } @@ -809,11 +888,17 @@ class State : angle::NonCopyable bool isExternal() const { return mPrivateState.isExternal(); } + bool usesPassthroughShaders() const { return mPassthroughShaders; } + Caps *getMutableCaps() { return mPrivateState.getMutableCaps(); } TextureCapsMap *getMutableTextureCaps() { return mPrivateState.getMutableTextureCaps(); } Extensions *getMutableExtensions() { return mPrivateState.getMutableExtensions(); } Limitations *getMutableLimitations() { return mPrivateState.getMutableLimitations(); } + GLuint getGroupMarkerCount() const { return mPrivateState.getGroupMarkerCount(); } + void incrementGroupMarkers() { mPrivateState.incrementGroupMarkers(); } + void decrementGroupMarkers() { mPrivateState.decrementGroupMarkers(); } + const TextureCaps &getTextureCap(GLenum internalFormat) const { return getTextureCaps().get(internalFormat); @@ -841,6 +926,8 @@ class State : angle::NonCopyable void invalidateTextureBindings(TextureType type); + bool isTextureBoundToActivePLS(TextureID) const; + // Sampler object binding manipulation void setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler); SamplerID getSamplerId(GLuint textureUnit) const @@ -876,7 +963,6 @@ class State : angle::NonCopyable void setVertexArrayBinding(const Context *context, VertexArray *vertexArray); bool removeVertexArrayBinding(const Context *context, VertexArrayID vertexArray); VertexArrayID getVertexArrayId() const; - VertexArray *getVertexArray() const { ASSERT(mVertexArray != nullptr); @@ -912,9 +998,9 @@ class State : angle::NonCopyable return mProgram; } - Program *getLinkedProgram(const Context *context) const + ANGLE_INLINE Program *getLinkedProgram(const Context *context) const { - if (mProgram) + if (ANGLE_LIKELY(mProgram)) { mProgram->resolveLink(context); } @@ -1018,9 +1104,6 @@ class State : angle::NonCopyable // Detach a buffer from all bindings angle::Result detachBuffer(Context *context, const Buffer *buffer); - // Vertex attrib manipulation - void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); - ANGLE_INLINE void setVertexAttribPointer(const Context *context, unsigned int attribNum, Buffer *boundBuffer, @@ -1028,11 +1111,16 @@ class State : angle::NonCopyable VertexAttribType type, bool normalized, GLsizei stride, - const void *pointer) + const void *pointer, + bool *isVertexAttribDirtyOut) { + ASSERT(isVertexAttribDirtyOut); mVertexArray->setVertexAttribPointer(context, attribNum, boundBuffer, size, type, - normalized, stride, pointer); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); + normalized, stride, pointer, isVertexAttribDirtyOut); + if (*isVertexAttribDirtyOut) + { + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); + } } ANGLE_INLINE void setVertexAttribIPointer(const Context *context, @@ -1041,14 +1129,18 @@ class State : angle::NonCopyable GLint size, VertexAttribType type, GLsizei stride, - const void *pointer) + const void *pointer, + bool *isVertexAttribDirtyOut) { + ASSERT(isVertexAttribDirtyOut); mVertexArray->setVertexAttribIPointer(context, attribNum, boundBuffer, size, type, stride, - pointer); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); + pointer, isVertexAttribDirtyOut); + if (*isVertexAttribDirtyOut) + { + mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); + } } - void setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor); const void *getVertexAttribPointer(unsigned int attribNum) const; void bindVertexBuffer(const Context *context, @@ -1056,20 +1148,6 @@ class State : angle::NonCopyable Buffer *boundBuffer, GLintptr offset, GLsizei stride); - void setVertexAttribFormat(GLuint attribIndex, - GLint size, - VertexAttribType type, - bool normalized, - bool pureInteger, - GLuint relativeOffset); - - void setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex) - { - mVertexArray->setVertexAttribBinding(context, attribIndex, bindingIndex); - mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY); - } - - void setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor); // State query functions void getBooleanv(GLenum pname, GLboolean *params) const; @@ -1094,11 +1172,6 @@ class State : angle::NonCopyable { return mDirtyBits | mPrivateState.getDirtyBits(); } - void clearDirtyBits() - { - mDirtyBits.reset(); - mPrivateState.clearDirtyBits(); - } void clearDirtyBits(const state::DirtyBits &bitset) { mDirtyBits &= ~bitset; @@ -1115,11 +1188,6 @@ class State : angle::NonCopyable { return mExtendedDirtyBits | mPrivateState.getExtendedDirtyBits(); } - void clearExtendedDirtyBits() - { - mExtendedDirtyBits.reset(); - mPrivateState.clearExtendedDirtyBits(); - } void clearExtendedDirtyBits(const state::ExtendedDirtyBits &bitset) { mExtendedDirtyBits &= ~bitset; @@ -1131,11 +1199,19 @@ class State : angle::NonCopyable mDirtyObjects.reset(); mPrivateState.clearDirtyObjects(); } - void setAllDirtyObjects() { mDirtyObjects.set(); } + void setAllDirtyObjects() + { + mDirtyObjects.set(); + if (!isRobustResourceInitEnabled()) + { + mDirtyObjects.reset(state::DIRTY_OBJECT_READ_ATTACHMENTS); + mDirtyObjects.reset(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + } + } angle::Result syncDirtyObjects(const Context *context, const state::DirtyObjects &bitset, Command command); - angle::Result syncDirtyObject(const Context *context, GLenum target); + angle::Result syncDirtyObject(const Context *context, GLenum target, Command command); void setObjectDirty(GLenum target); void setTextureDirty(size_t textureUnitIndex); void setSamplerDirty(size_t samplerIndex); @@ -1143,13 +1219,19 @@ class State : angle::NonCopyable ANGLE_INLINE void setReadFramebufferDirty() { mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER); - mDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS); + if (isRobustResourceInitEnabled()) + { + mDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS); + } } ANGLE_INLINE void setDrawFramebufferDirty() { mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER); - mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + if (isRobustResourceInitEnabled()) + { + mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS); + } } void setImageUnit(const Context *context, @@ -1172,7 +1254,7 @@ class State : angle::NonCopyable void onImageStateChange(const Context *context, size_t unit); - void onUniformBufferStateChange(size_t uniformBufferIndex); + void onUniformBufferStateChange(size_t uniformBufferIndex, angle::SubjectMessage message); void onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex); void onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex); @@ -1354,7 +1436,13 @@ class State : angle::NonCopyable bool isRobustResourceInitEnabled() const { return mPrivateState.isRobustResourceInitEnabled(); } bool isProgramBinaryCacheEnabled() const { return mPrivateState.isProgramBinaryCacheEnabled(); } const Rectangle &getViewport() const { return mPrivateState.getViewport(); } - ShadingRate getShadingRate() const { return mPrivateState.getShadingRate(); } + ShadingRate getShadingRateQCOM() const { return mPrivateState.getShadingRateQCOM(); } + ShadingRate getShadingRateEXT() const { return mPrivateState.getShadingRateEXT(); } + bool getFetchPerSample() const { return mPrivateState.getFetchPerSample(); } + const std::array &getShadingRateCombinerOps() const + { + return mPrivateState.getShadingRateCombinerOps(); + } GLint getPackAlignment() const { return mPrivateState.getPackAlignment(); } bool getPackReverseRowOrder() const { return mPrivateState.getPackReverseRowOrder(); } GLint getPackRowLength() const { return mPrivateState.getPackRowLength(); } @@ -1373,10 +1461,6 @@ class State : angle::NonCopyable GLenum getCoverageModulation() const { return mPrivateState.getCoverageModulation(); } bool getFramebufferSRGB() const { return mPrivateState.getFramebufferSRGB(); } GLuint getPatchVertices() const { return mPrivateState.getPatchVertices(); } - void setPixelLocalStorageActivePlanes(GLsizei n) - { - mPrivateState.setPixelLocalStorageActivePlanes(n); - } GLsizei getPixelLocalStorageActivePlanes() const { return mPrivateState.getPixelLocalStorageActivePlanes(); @@ -1454,6 +1538,12 @@ class State : angle::NonCopyable mDirtyUniformBlocks.reset(); return dirtyBits; } + BufferDirtyTypeBitMask getAndResetUniformBufferBlocksDirtyTypeMask() const + { + BufferDirtyTypeBitMask dirtyTypeMask = mUniformBufferBlocksDirtyTypeMask; + mUniformBufferBlocksDirtyTypeMask.reset(); + return dirtyTypeMask; + } const PrivateState &privateState() const { return mPrivateState; } const GLES1State &gles1() const { return mPrivateState.gles1(); } @@ -1515,22 +1605,26 @@ class State : angle::NonCopyable handlers[state::DIRTY_OBJECT_SAMPLERS] = &State::syncSamplers; handlers[state::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT] = &State::syncProgramPipelineObject; - // If a handler is missing, reset everything for ease of static_assert - for (auto handler : handlers) - { - if (handler == nullptr) - { - return DirtyObjectHandlerArray(); - } - } - return handlers; } angle::Result dirtyObjectHandler(size_t dirtyObject, const Context *context, Command command) { static constexpr DirtyObjectHandlerArray handlers = MakeDirtyObjectHandlers(); - static_assert(handlers[0] != nullptr, "MakeDirtyObjectHandlers missing a handler"); + + // Fail with static_assert if any handler is missing. + constexpr auto existEmptyHandler = []() constexpr { + for (auto handler : handlers) + { + if (handler == nullptr) + { + return true; + } + } + return false; + }; + + static_assert(!existEmptyHandler(), "MakeDirtyObjectHandlers missing a handler"); return (this->*handlers[dirtyObject])(context, command); } @@ -1556,6 +1650,7 @@ class State : angle::NonCopyable bool mHasRobustAccess; bool mHasProtectedContent; bool mIsDebugContext; + bool mPassthroughShaders; egl::ShareGroup *mShareGroup; mutable egl::ContextMutex mContextMutex; @@ -1642,6 +1737,8 @@ class State : angle::NonCopyable // changed, or buffers in their mapped bindings have changed. This is in State because every // context needs to react to such changes. mutable ProgramUniformBlockMask mDirtyUniformBlocks; + // Fine grained dirty type for uniform buffers. + mutable BufferDirtyTypeBitMask mUniformBufferBlocksDirtyTypeMask; PrivateState mPrivateState; }; @@ -1654,6 +1751,10 @@ ANGLE_INLINE angle::Result State::syncDirtyObjects(const Context *context, mDirtyObjects |= mPrivateState.getDirtyObjects(); mPrivateState.clearDirtyObjects(); + ASSERT(isRobustResourceInitEnabled() || + (!mDirtyObjects.test(state::DIRTY_OBJECT_DRAW_ATTACHMENTS) && + !mDirtyObjects.test(state::DIRTY_OBJECT_READ_ATTACHMENTS))); + const state::DirtyObjects &dirtyObjects = mDirtyObjects & bitset; for (size_t dirtyObject : dirtyObjects) @@ -1662,6 +1763,7 @@ ANGLE_INLINE angle::Result State::syncDirtyObjects(const Context *context, } mDirtyObjects &= ~dirtyObjects; + return angle::Result::Continue; } diff --git a/src/libANGLE/Surface.cpp b/src/libANGLE/Surface.cpp index c2a98f12e23..0fdeae24589 100644 --- a/src/libANGLE/Surface.cpp +++ b/src/libANGLE/Surface.cpp @@ -183,8 +183,13 @@ Error Surface::destroyImpl(const Display *display) return NoError(); } -void Surface::postSwap(const gl::Context *context) +void Surface::postSwap(const gl::Context *context, const rx::SurfaceSwapFeedback &feedback) { + if (feedback.swapChainImageChanged) + { + context->onSwapChainImageChanged(); + } + if (mRobustResourceInitialization && mState.swapBehavior != EGL_BUFFER_PRESERVED) { mColorInitState = gl::InitState::MayNeedInit; @@ -227,6 +232,13 @@ Error Surface::initialize(const Display *display) // Must happen after implementation initialize for Android. mState.swapBehavior = mImplementation->getSwapBehavior(); + // Update render buffer based on what the impl supports. + if ((mType == EGL_WINDOW_BIT) && mRenderBuffer == EGL_SINGLE_BUFFER && + !mImplementation->supportsSingleRenderBuffer()) + { + mRenderBuffer = EGL_BACK_BUFFER; + } + if (mBuftype == EGL_IOSURFACE_ANGLE) { GLenum internalFormat = @@ -243,7 +255,7 @@ Error Surface::initialize(const Display *display) } if (mBuftype == EGL_D3D_TEXTURE_ANGLE) { - const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat(); + const angle::Format *colorFormat = mImplementation->getClientBufferTextureColorFormat(); ASSERT(colorFormat != nullptr); GLenum internalFormat = colorFormat->fboImplementationInternalFormat; mColorFormat = gl::Format(internalFormat, colorFormat->componentType); @@ -336,8 +348,9 @@ Error Surface::swap(gl::Context *context) context->getState().getOverlay()->onSwap(); ANGLE_TRY(updatePropertiesOnSwap(context)); - ANGLE_TRY(mImplementation->swap(context)); - postSwap(context); + + rx::SurfaceSwapFeedback feedback; + ANGLE_TRY_WITH_FINALLY(mImplementation->swap(context, &feedback), postSwap(context, feedback)); return NoError(); } @@ -349,21 +362,10 @@ Error Surface::swapWithDamage(gl::Context *context, const EGLint *rects, EGLint context->getState().getOverlay()->onSwap(); ANGLE_TRY(updatePropertiesOnSwap(context)); - ANGLE_TRY(mImplementation->swapWithDamage(context, rects, n_rects)); - postSwap(context); - return NoError(); -} - -Error Surface::swapWithFrameToken(gl::Context *context, EGLFrameTokenANGLE frameToken) -{ - ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithFrameToken"); - context->onPreSwap(); - context->getState().getOverlay()->onSwap(); - - ANGLE_TRY(updatePropertiesOnSwap(context)); - ANGLE_TRY(mImplementation->swapWithFrameToken(context, frameToken)); - postSwap(context); + rx::SurfaceSwapFeedback feedback; + ANGLE_TRY_WITH_FINALLY(mImplementation->swapWithDamage(context, rects, n_rects, &feedback), + postSwap(context, feedback)); return NoError(); } @@ -382,7 +384,8 @@ Error Surface::postSubBuffer(const gl::Context *context, ANGLE_TRY(updatePropertiesOnSwap(context)); ANGLE_TRY(mImplementation->postSubBuffer(context, x, y, width, height)); - postSwap(context); + rx::SurfaceSwapFeedback feedback; + postSwap(context, feedback); return NoError(); } @@ -530,39 +533,31 @@ EGLint Surface::isFixedSize() const return mFixedSize; } -EGLint Surface::getWidth() const -{ - return mFixedSize ? static_cast(mFixedWidth) : mImplementation->getWidth(); -} - -EGLint Surface::getHeight() const -{ - return mFixedSize ? static_cast(mFixedHeight) : mImplementation->getHeight(); -} - -egl::Error Surface::getUserWidth(const egl::Display *display, EGLint *value) const +gl::Extents Surface::getSize() const { - if (mFixedSize) - { - *value = static_cast(mFixedWidth); - return NoError(); - } - else - { - return mImplementation->getUserWidth(display, value); - } + return mFixedSize + ? gl::Extents(static_cast(mFixedWidth), static_cast(mFixedHeight), 1) + : mImplementation->getSize(); } -egl::Error Surface::getUserHeight(const egl::Display *display, EGLint *value) const +egl::Error Surface::getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const { + ASSERT(width != nullptr || height != nullptr); if (mFixedSize) { - *value = static_cast(mFixedHeight); + if (width != nullptr) + { + *width = static_cast(mFixedWidth); + } + if (height != nullptr) + { + *height = static_cast(mFixedHeight); + } return NoError(); } else { - return mImplementation->getUserHeight(display, value); + return mImplementation->getUserSize(display, width, height); } } @@ -614,9 +609,20 @@ Error Surface::releaseTexImageFromTexture(const gl::Context *context) return releaseRef(context->getDisplay()); } +angle::Result Surface::ensureSizeResolved(const gl::Context *context) const +{ + return mImplementation->ensureSizeResolved(context); +} + +bool Surface::isAttachmentSpecified(const gl::ImageIndex & /*imageIndex*/) const +{ + // Surface is always specified even if it has 0 sizes. + return true; +} + gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const { - return gl::Extents(getWidth(), getHeight(), 1); + return getSize(); } gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const @@ -780,9 +786,6 @@ void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess case angle::SubjectMessage::SurfaceChanged: onStateChange(angle::SubjectMessage::SurfaceChanged); break; - case angle::SubjectMessage::SwapchainImageChanged: - onStateChange(angle::SubjectMessage::SwapchainImageChanged); - break; default: UNREACHABLE(); break; @@ -898,9 +901,11 @@ EGLAttribKHR Surface::getBitmapPointer() const return static_cast((intptr_t)mLockBufferPtr); } -EGLint Surface::getCompressionRate(const egl::Display *display) const +egl::Error Surface::getCompressionRate(const egl::Display *display, + const gl::Context *context, + EGLint *rate) { - return mImplementation->getCompressionRate(display); + return mImplementation->getCompressionRate(display, context, rate); } egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes) diff --git a/src/libANGLE/Surface.h b/src/libANGLE/Surface.h index 1e8a9170082..d11702fe298 100644 --- a/src/libANGLE/Surface.h +++ b/src/libANGLE/Surface.h @@ -84,7 +84,6 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject Error prepareSwap(const gl::Context *context); Error swap(gl::Context *context); Error swapWithDamage(gl::Context *context, const EGLint *rects, EGLint n_rects); - Error swapWithFrameToken(gl::Context *context, EGLFrameTokenANGLE frameToken); Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -113,18 +112,11 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject const Config *getConfig() const; - // width and height can change with client window resizing - EGLint getWidth() const; - EGLint getHeight() const; - // Note: windows cannot be resized on Android. The approach requires - // calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR. However, that is - // expensive; and there are troublesome timing issues for other parts of - // ANGLE (which cause test failures and crashes). Therefore, a - // special-Android-only path is created just for the querying of EGL_WIDTH - // and EGL_HEIGHT. - // https://issuetracker.google.com/issues/153329980 - egl::Error getUserWidth(const egl::Display *display, EGLint *value) const; - egl::Error getUserHeight(const egl::Display *display, EGLint *value) const; + // size can change with client window resizing + // Size must be resolved before the call either during state synchronization or explicitly. + gl::Extents getSize() const; + // Unresolved Surface size until render target is first accessed (e.g. after draw). + egl::Error getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const; EGLint getPixelAspectRatio() const; EGLenum getRenderBuffer() const; EGLenum getRequestedRenderBuffer() const; @@ -154,7 +146,9 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject EGLint getLuminanceOffset() const; EGLint getBitmapPixelSize() const; EGLAttribKHR getBitmapPointer() const; - EGLint getCompressionRate(const egl::Display *display) const; + egl::Error getCompressionRate(const egl::Display *display, + const gl::Context *context, + EGLint *rate); egl::Error lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes); egl::Error unlockSurfaceKHR(const egl::Display *display); @@ -166,6 +160,9 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject EGLint isFixedSize() const; // FramebufferAttachmentObject implementation + // Explicitly resolves surface size to use before state synchronization (e.g. validation). + angle::Result ensureSizeResolved(const gl::Context *context) const override; + bool isAttachmentSpecified(const gl::ImageIndex &imageIndex) const override; gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override; gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override; GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override; @@ -307,7 +304,7 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject Error destroyImpl(const Display *display); - void postSwap(const gl::Context *context); + void postSwap(const gl::Context *context, const rx::SurfaceSwapFeedback &feedback); Error releaseRef(const Display *display); // ObserverInterface implementation. diff --git a/src/libANGLE/Surface_unittest.cpp b/src/libANGLE/Surface_unittest.cpp index b076f0f7084..602ecb249b2 100644 --- a/src/libANGLE/Surface_unittest.cpp +++ b/src/libANGLE/Surface_unittest.cpp @@ -30,8 +30,9 @@ class MockSurfaceImpl : public rx::SurfaceImpl MOCK_METHOD1(destroy, void(const egl::Display *)); MOCK_METHOD1(initialize, egl::Error(const egl::Display *)); - MOCK_METHOD1(swap, egl::Error(const gl::Context *)); - MOCK_METHOD3(swapWithDamage, egl::Error(const gl::Context *, const EGLint *, EGLint)); + MOCK_METHOD2(swap, egl::Error(const gl::Context *, SurfaceSwapFeedback *)); + MOCK_METHOD4(swapWithDamage, + egl::Error(const gl::Context *, const EGLint *, EGLint, SurfaceSwapFeedback *)); MOCK_METHOD5(postSubBuffer, egl::Error(const gl::Context *, EGLint, EGLint, EGLint, EGLint)); MOCK_METHOD2(querySurfacePointerANGLE, egl::Error(EGLint, void **)); MOCK_METHOD3(bindTexImage, egl::Error(const gl::Context *context, gl::Texture *, EGLint)); @@ -39,8 +40,7 @@ class MockSurfaceImpl : public rx::SurfaceImpl MOCK_METHOD3(getSyncValues, egl::Error(EGLuint64KHR *, EGLuint64KHR *, EGLuint64KHR *)); MOCK_METHOD2(getMscRate, egl::Error(EGLint *, EGLint *)); MOCK_METHOD2(setSwapInterval, void(const egl::Display *, EGLint)); - MOCK_CONST_METHOD0(getWidth, EGLint()); - MOCK_CONST_METHOD0(getHeight, EGLint()); + MOCK_CONST_METHOD0(getSize, gl::Extents()); MOCK_CONST_METHOD0(isPostSubBufferSupported, EGLint(void)); MOCK_CONST_METHOD0(getSwapBehavior, EGLint(void)); MOCK_METHOD5(getAttachmentRenderTarget, diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp index d6020028d21..b5a2bb3ce8e 100644 --- a/src/libANGLE/Texture.cpp +++ b/src/libANGLE/Texture.cpp @@ -6,6 +6,10 @@ // Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Texture.h" #include "common/mathutil.h" @@ -128,9 +132,11 @@ TextureState::TextureState(TextureType type) mMaxLevel(kInitialMaxLevel), mDepthStencilTextureMode(GL_DEPTH_COMPONENT), mIsInternalIncompleteTexture(false), + mIsExternalMemoryTexture(false), mHasBeenBoundAsImage(false), mHasBeenBoundAsAttachment(false), mHasBeenBoundToMSRTTFramebuffer(false), + mHasBeenBoundAsSourceOfEglImage(false), mImmutableFormat(false), mImmutableLevels(0), mUsage(GL_NONE), @@ -144,7 +150,8 @@ TextureState::TextureState(TextureType type) mCachedSamplerFormat(SamplerFormat::InvalidEnum), mCachedSamplerCompareMode(GL_NONE), mCachedSamplerFormatValid(false), - mCompressionFixedRate(GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT) + mCompressionFixedRate(GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT), + mAstcDecodePrecision(GL_RGBA16F) {} TextureState::~TextureState() {} @@ -177,7 +184,14 @@ GLuint TextureState::getEffectiveMaxLevel() const clampedMaxLevel = std::min(clampedMaxLevel, mImmutableLevels - 1); return clampedMaxLevel; } - return mMaxLevel; + if (IsMipmapSupported(mType) && IsMipmapFiltered(mSamplerState.getMinFilter())) + { + return mMaxLevel; + } + else + { + return std::max(mMaxLevel, mBaseLevel); + } } GLuint TextureState::getMipmapMaxLevel() const @@ -209,6 +223,21 @@ bool TextureState::setBaseLevel(GLuint baseLevel) return false; } +bool TextureState::setASTCDecodePrecision(GLenum astcDecodePrecision) +{ + if (mAstcDecodePrecision != astcDecodePrecision) + { + mAstcDecodePrecision = astcDecodePrecision; + return true; + } + return false; +} + +GLenum TextureState::getASTCDecodePrecision() const +{ + return mAstcDecodePrecision; +} + bool TextureState::setMaxLevel(GLuint maxLevel) { if (mMaxLevel != maxLevel) @@ -370,7 +399,7 @@ bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState, // extension, due to some underspecification problems, we must allow linear filtering // for legacy compatibility with WebGL 1.0. // See http://crbug.com/649200 - if (state.getClientMajorVersion() >= 3 && info->sized) + if (state.getClientVersion() >= ES_3_0 && info->sized) { return false; } @@ -415,10 +444,6 @@ bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &sa return mBuffer.get() != nullptr; } - if (!mImmutableFormat && mBaseLevel > mMaxLevel) - { - return false; - } const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel()); if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) @@ -434,7 +459,7 @@ bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &sa return false; } - bool npotSupport = state.getExtensions().textureNpotOES || state.getClientMajorVersion() >= 3; + bool npotSupport = state.getExtensions().textureNpotOES || state.getClientVersion() >= ES_3_0; if (!npotSupport) { if ((samplerState.getWrapS() != GL_CLAMP_TO_EDGE && @@ -501,7 +526,12 @@ bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &sa bool TextureState::computeMipmapCompleteness() const { - const GLuint maxLevel = getMipmapMaxLevel(); + const GLuint maxLevel = getMipmapMaxLevel(); + const GLuint baseLevel = getEffectiveBaseLevel(); + if (baseLevel > maxLevel) + { + return false; + } for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++) { @@ -595,17 +625,23 @@ GLuint TextureState::getEnabledLevelCount() const { GLuint levelCount = 0; const GLuint baseLevel = getEffectiveBaseLevel(); - const GLuint maxLevel = getMipmapMaxLevel(); + GLuint maxLevel = getMipmapMaxLevel(); + + // In edge case where base level > max level, make sure to get at least one level. + maxLevel = std::max(baseLevel, maxLevel); + + // Note: for cube textures, we only check the first face. + TextureTarget target = TextureTypeToTarget(mType, 0); + const Format &expectedFormat = mImageDescs[GetImageDescIndex(target, baseLevel)].format; // The mip chain will have either one or more sequential levels, or max levels, // but not a sparse one. Optional expectedSize; for (size_t enabledLevel = baseLevel; enabledLevel <= maxLevel; ++enabledLevel, ++levelCount) { - // Note: for cube textures, we only check the first face. - TextureTarget target = TextureTypeToTarget(mType, 0); size_t descIndex = GetImageDescIndex(target, enabledLevel); const Extents &levelSize = mImageDescs[descIndex].size; + const Format &levelFormat = mImageDescs[descIndex].format; if (levelSize.empty()) { @@ -627,6 +663,14 @@ GLuint TextureState::getEnabledLevelCount() const break; } } + // If the texture is bound without mipmap filtering, the max level could be incompatible + // with the base level while respecifying image storage. In this case, we check the sized + // internal format for the compatibility and enable only the effective level when it has + // changed compared to the previous image. + if (!Format::SameSized(expectedFormat, levelFormat)) + { + break; + } expectedSize = levelSize; } @@ -1023,6 +1067,19 @@ GLenum Texture::getCompareMode() const return mState.mSamplerState.getCompareMode(); } +void Texture::setASTCDecodePrecision(const Context *context, GLenum astcDecodePrecision) +{ + if (mState.setASTCDecodePrecision(astcDecodePrecision)) + { + signalDirtyState(DIRTY_BIT_ASTC_DECODE_PRECISION); + } +} + +GLenum Texture::getASTCDecodePrecision() const +{ + return mState.getASTCDecodePrecision(); +} + void Texture::setCompareFunc(const Context *context, GLenum compareFunc) { if (mState.mSamplerState.setCompareFunc(compareFunc)) @@ -1778,7 +1835,7 @@ angle::Result Texture::setStorageMultisample(Context *context, // Potentially adjust "samples" to a supported value const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); - GLsizei samples = formatCaps.getNearestSamples(samplesIn); + GLsizei samples = formatCaps.sampleCounts.getNearestSamples(samplesIn); mState.mImmutableFormat = true; mState.mImmutableLevels = static_cast(1); @@ -1817,6 +1874,7 @@ angle::Result Texture::setStorageExternalMemory(Context *context, memoryObject, offset, createFlags, usageFlags, imageCreateInfoPNext)); + mState.mIsExternalMemoryTexture = true; mState.mImmutableFormat = true; mState.mImmutableLevels = static_cast(levels); mState.clearImageDescs(); @@ -1895,9 +1953,6 @@ GLint Texture::getFormatSupportedCompressionRates(const Context *context, angle::Result Texture::generateMipmap(Context *context) { - // Release from previous calls to eglBindTexImage, to avoid calling the Impl after - ANGLE_TRY(releaseTexImageInternal(context)); - // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture // is not mip complete. egl::RefCountObjectReleaser releaseImage; @@ -1950,6 +2005,10 @@ angle::Result Texture::generateMipmap(Context *context) mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format, InitState::Initialized); + // Disconnect the texture from the surface + releaseTexImageInternalNoRedefinition(context); + mBoundSurface = nullptr; + signalDirtyStorage(InitState::Initialized); return angle::Result::Continue; @@ -2015,8 +2074,7 @@ angle::Result Texture::bindTexImageFromSurface(Context *context, egl::Surface *s // Set the image info to the size and format of the surface ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle); - Extents size(surface->getWidth(), surface->getHeight(), 1); - ImageDesc desc(size, surface->getBindTexImageFormat(), InitState::Initialized); + ImageDesc desc(surface->getSize(), surface->getBindTexImageFormat(), InitState::Initialized); mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0, desc); mState.mHasProtectedContent = surface->hasProtectedContent(); @@ -2083,7 +2141,7 @@ angle::Result Texture::releaseImageFromStream(const Context *context) return angle::Result::Continue; } -angle::Result Texture::releaseTexImageInternal(Context *context) +void Texture::releaseTexImageInternalNoRedefinition(Context *context) { if (mBoundSurface) { @@ -2095,8 +2153,16 @@ angle::Result Texture::releaseTexImageInternal(Context *context) context->handleError(GL_INVALID_OPERATION, "Error releasing tex image from texture", __FILE__, ANGLE_FUNCTION, __LINE__); } + } +} + +angle::Result Texture::releaseTexImageInternal(Context *context) +{ + releaseTexImageInternalNoRedefinition(context); - // Then, call the same method as from the surface + // Then, call the same method as from the surface + if (mBoundSurface) + { ANGLE_TRY(releaseTexImageFromSurface(context)); } return angle::Result::Continue; @@ -2237,7 +2303,7 @@ bool Texture::isRenderable(const Context *context, ->getNativeTextureCaps() .get(getAttachmentFormat(binding, imageIndex).info->sizedInternalFormat) .textureAttachment && - !mState.renderabilityValidation() && context->getClientMajorVersion() < 3) + !mState.renderabilityValidation() && context->getClientVersion() < ES_3_0) { return true; } @@ -2585,16 +2651,6 @@ void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess { switch (message) { - case angle::SubjectMessage::ContentsChanged: - if (index != kBufferSubjectIndex) - { - // ContentsChange originates from TextureStorage11::resolveAndReleaseTexture - // which resolves the underlying multisampled texture if it exists and so - // Texture will signal dirty storage to invalidate its own cache and the - // attached framebuffer's cache. - signalDirtyStorage(InitState::Initialized); - } - break; case angle::SubjectMessage::DirtyBitsFlagged: signalDirtyState(DIRTY_BIT_IMPLEMENTATION); @@ -2676,11 +2732,7 @@ void Texture::onBufferContentsChange() void Texture::onBindToMSRTTFramebuffer() { - if (!mState.mHasBeenBoundToMSRTTFramebuffer) - { - mDirtyBits.set(DIRTY_BIT_BOUND_TO_MSRTT_FRAMEBUFFER); - mState.mHasBeenBoundToMSRTTFramebuffer = true; - } + mState.mHasBeenBoundToMSRTTFramebuffer = true; } GLenum Texture::getImplementationColorReadFormat(const Context *context) const @@ -2737,4 +2789,9 @@ void Texture::onBindAsImageTexture() } } +void Texture::onBindAsEglImageSource() +{ + mState.mHasBeenBoundAsSourceOfEglImage = true; +} + } // namespace gl diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h index 8de85f02510..88c74a969ec 100644 --- a/src/libANGLE/Texture.h +++ b/src/libANGLE/Texture.h @@ -147,9 +147,11 @@ class TextureState final : private angle::NonCopyable bool renderabilityValidation() const { return mRenderabilityValidation; } GLenum getDepthStencilTextureMode() const { return mDepthStencilTextureMode; } + bool isExternalMemoryTexture() const { return mIsExternalMemoryTexture; } bool hasBeenBoundAsImage() const { return mHasBeenBoundAsImage; } bool hasBeenBoundAsAttachment() const { return mHasBeenBoundAsAttachment; } bool hasBeenBoundToMSRTTFramebuffer() const { return mHasBeenBoundToMSRTTFramebuffer; } + bool hasBeenBoundAsSourceOfEglImage() const { return mHasBeenBoundAsSourceOfEglImage; } gl::SrgbOverride getSRGBOverride() const { return mSrgbOverride; } @@ -174,6 +176,9 @@ class TextureState final : private angle::NonCopyable void setGenerateMipmapHint(GLenum hint); GLenum getGenerateMipmapHint() const; + bool setASTCDecodePrecision(GLenum astcDecodePrecision); + GLenum getASTCDecodePrecision() const; + // Return the enabled mipmap level count. GLuint getEnabledLevelCount() const; @@ -244,9 +249,14 @@ class TextureState final : private angle::NonCopyable // overhead of tail-call checks to draw calls. bool mIsInternalIncompleteTexture; + // Whether this is an external memory texture created via EXT_external_objects or + // ANGLE_external_objects_flags. + bool mIsExternalMemoryTexture; + bool mHasBeenBoundAsImage; bool mHasBeenBoundAsAttachment; bool mHasBeenBoundToMSRTTFramebuffer; + bool mHasBeenBoundAsSourceOfEglImage; bool mImmutableFormat; GLuint mImmutableLevels; @@ -286,6 +296,10 @@ class TextureState final : private angle::NonCopyable // GL_EXT_texture_storage_compression GLenum mCompressionFixedRate; + + // GL_EXT_texture_compression_astc_decode_mode + // GL_EXT_texture_compression_astc_decode_mode_rgb9e5 + GLenum mAstcDecodePrecision; }; bool operator==(const TextureState &a, const TextureState &b); @@ -361,6 +375,9 @@ class Texture final : public RefCountObject, void setCompareFunc(const Context *context, GLenum compareFunc); GLenum getCompareFunc() const; + void setASTCDecodePrecision(const Context *context, GLenum astcDecodePrecision); + GLenum getASTCDecodePrecision() const; + void setSRGBDecode(const Context *context, GLenum sRGBDecode); GLenum getSRGBDecode() const; @@ -608,6 +625,7 @@ class Texture final : public RefCountObject, const uint8_t *data); void onBindAsImageTexture(); + void onBindAsEglImageSource(); egl::Surface *getBoundSurface() const; egl::Stream *getBoundStream() const; @@ -718,14 +736,12 @@ class Texture final : public RefCountObject, DIRTY_BIT_MAX_LEVEL, DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE, DIRTY_BIT_RENDERABILITY_VALIDATION_ANGLE, + DIRTY_BIT_ASTC_DECODE_PRECISION, // Image state DIRTY_BIT_BOUND_AS_IMAGE, DIRTY_BIT_BOUND_AS_ATTACHMENT, - // Bound to MSRTT Framebuffer - DIRTY_BIT_BOUND_TO_MSRTT_FRAMEBUFFER, - // Misc DIRTY_BIT_USAGE, DIRTY_BIT_IMPLEMENTATION, @@ -770,6 +786,8 @@ class Texture final : public RefCountObject, angle::Result releaseImageFromStream(const Context *context); void invalidateCompletenessCache() const; + + void releaseTexImageInternalNoRedefinition(Context *context); angle::Result releaseTexImageInternal(Context *context); bool doesSubImageNeedInit(const Context *context, diff --git a/src/libANGLE/TransformFeedback.cpp b/src/libANGLE/TransformFeedback.cpp index 2c204b5c29f..175f0bcd464 100644 --- a/src/libANGLE/TransformFeedback.cpp +++ b/src/libANGLE/TransformFeedback.cpp @@ -149,29 +149,7 @@ angle::Result TransformFeedback::begin(const Context *context, mState.mPaused = false; mState.mVerticesDrawn = 0; bindProgram(context, program); - - // In one of the angle_unittests - "TransformFeedbackTest.SideEffectsOfStartAndStop" - // there is a code path where is a nullptr, account for that possiblity. - const ProgramExecutable *programExecutable = - context ? context->getState().getLinkedProgramExecutable(context) : nullptr; - if (programExecutable) - { - // Compute the number of vertices we can draw before overflowing the bound buffers. - auto strides = programExecutable->getTransformFeedbackStrides(); - ASSERT(strides.size() <= mState.mIndexedBuffers.size() && !strides.empty()); - GLsizeiptr minCapacity = std::numeric_limits::max(); - for (size_t index = 0; index < strides.size(); index++) - { - GLsizeiptr capacity = - GetBoundBufferAvailableSize(mState.mIndexedBuffers[index]) / strides[index]; - minCapacity = std::min(minCapacity, capacity); - } - mState.mVertexCapacity = minCapacity; - } - else - { - mState.mVertexCapacity = 0; - } + recomputeVertexCapacity(context); return angle::Result::Continue; } @@ -202,6 +180,7 @@ angle::Result TransformFeedback::resume(const Context *context) { ANGLE_TRY(mImplementation->resume(context)); mState.mPaused = false; + recomputeVertexCapacity(context); return angle::Result::Continue; } @@ -234,7 +213,7 @@ void TransformFeedback::onVerticesDrawn(const Context *context, GLsizei count, G { if (buffer.get() != nullptr) { - buffer->onDataChanged(); + buffer->onDataChanged(context); } } } @@ -255,6 +234,32 @@ void TransformFeedback::bindProgram(const Context *context, Program *program) } } +void TransformFeedback::recomputeVertexCapacity(const Context *context) +{ + // In one of the angle_unittests - "TransformFeedbackTest.SideEffectsOfStartAndStop" + // there is a code path where is a nullptr, account for that possibility. + const ProgramExecutable *programExecutable = + context ? context->getState().getLinkedProgramExecutable(context) : nullptr; + if (programExecutable) + { + // Compute the number of vertices we can draw before overflowing the bound buffers. + auto strides = programExecutable->getTransformFeedbackStrides(); + ASSERT(strides.size() <= mState.mIndexedBuffers.size() && !strides.empty()); + GLsizeiptr minCapacity = std::numeric_limits::max(); + for (size_t index = 0; index < strides.size(); index++) + { + GLsizeiptr capacity = + GetBoundBufferAvailableSize(mState.mIndexedBuffers[index]) / strides[index]; + minCapacity = std::min(minCapacity, capacity); + } + mState.mVertexCapacity = minCapacity; + } + else + { + mState.mVertexCapacity = 0; + } +} + bool TransformFeedback::hasBoundProgram(ShaderProgramID program) const { return mState.mProgram != nullptr && mState.mProgram->id().value == program.value; @@ -324,6 +329,18 @@ bool TransformFeedback::buffersBoundForOtherUseInWebGL() const return false; } +bool TransformFeedback::isBufferBound(BufferID bufferID) const +{ + for (const auto &buffer : mState.mIndexedBuffers) + { + if (buffer.id() == bufferID) + { + return true; + } + } + return false; +} + void TransformFeedback::onBindingChanged(const Context *context, bool bound) { for (auto &buffer : mState.mIndexedBuffers) diff --git a/src/libANGLE/TransformFeedback.h b/src/libANGLE/TransformFeedback.h index 5c9ffd0d87c..9eb347930c8 100644 --- a/src/libANGLE/TransformFeedback.h +++ b/src/libANGLE/TransformFeedback.h @@ -102,6 +102,10 @@ class TransformFeedback final : public RefCountObject, publ // Returns true if any buffer bound to this object is also bound to another target. bool buffersBoundForOtherUseInWebGL() const; + // Returns true if the buffer is bound to any of the indexed binding points in this transform + // feedback. + bool isBufferBound(BufferID bufferID) const; + angle::Result detachBuffer(const Context *context, BufferID bufferID); rx::TransformFeedbackImpl *getImplementation() const { return mImplementation; } @@ -110,6 +114,7 @@ class TransformFeedback final : public RefCountObject, publ private: void bindProgram(const Context *context, Program *program); + void recomputeVertexCapacity(const Context *context); TransformFeedbackState mState; rx::TransformFeedbackImpl *mImplementation; diff --git a/src/libANGLE/Uniform.cpp b/src/libANGLE/Uniform.cpp index 5d941cc508f..ee03e3758cf 100644 --- a/src/libANGLE/Uniform.cpp +++ b/src/libANGLE/Uniform.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/Uniform.h" #include "common/BinaryStream.h" #include "libANGLE/ProgramLinkedResources.h" @@ -77,6 +81,7 @@ LinkedUniform::LinkedUniform(const UsedUniform &usedUniform) SetBitField(pod.flagBits.isFragmentInOut, usedUniform.isFragmentInOut); SetBitField(pod.flagBits.texelFetchStaticUse, usedUniform.texelFetchStaticUse); + SetBitField(pod.flagBits.isFloat16, usedUniform.isFloat16); ASSERT(!usedUniform.isArray() || pod.arraySize == usedUniform.getArraySizeProduct()); } diff --git a/src/libANGLE/Uniform.h b/src/libANGLE/Uniform.h index caaf8f16397..32dab7e8026 100644 --- a/src/libANGLE/Uniform.h +++ b/src/libANGLE/Uniform.h @@ -7,6 +7,10 @@ #ifndef LIBANGLE_UNIFORM_H_ #define LIBANGLE_UNIFORM_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -122,11 +126,13 @@ struct LinkedUniform GLenum getType() const { return getUniformTypeInfo().type; } uint16_t getOuterArrayOffset() const { return pod.outerArrayOffset; } uint16_t getOuterArraySizeProduct() const { return pod.outerArraySizeProduct; } + uint16_t getBlockOffset() const { return pod.blockOffset; } int16_t getBinding() const { return pod.binding; } int16_t getOffset() const { return pod.offset; } int getBufferIndex() const { return pod.bufferIndex; } int getLocation() const { return pod.location; } GLenum getImageUnitFormat() const { return pod.imageUnitFormat; } + bool isFloat16() const { return pod.flagBits.isFloat16; } ACTIVE_VARIABLE_COMMON_INTERFACES @@ -146,6 +152,8 @@ struct LinkedUniform // maxUniformVectorsCount is 4K due to we clamp maxUniformBlockSize to 64KB. All of these // variable should be enough to pack into 16 bits to reduce the size of mUniforms. + static_assert(IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE <= + std::numeric_limits::max() + 1); int16_t binding; int16_t bufferIndex; @@ -165,7 +173,8 @@ struct LinkedUniform uint8_t isArray : 1; uint8_t blockIsRowMajorMatrix : 1; uint8_t isBlock : 1; - uint8_t padding : 3; + uint8_t isFloat16 : 1; + uint8_t padding : 2; } flagBits; uint8_t flagBitsAsUByte; }; diff --git a/src/libANGLE/VaryingPacking.cpp b/src/libANGLE/VaryingPacking.cpp index 6edf4c79fa1..9bbe21ee756 100644 --- a/src/libANGLE/VaryingPacking.cpp +++ b/src/libANGLE/VaryingPacking.cpp @@ -9,6 +9,10 @@ // allocation list for the D3D renderer. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/VaryingPacking.h" #include "common/CompiledShaderState.h" @@ -108,7 +112,7 @@ bool InterfaceVariablesMatch(const sh::ShaderVariable &front, const sh::ShaderVa // Compare names, or if shader I/O blocks, block names. const std::string &backName = back.isShaderIOBlock ? back.structOrBlockName : back.name; const std::string &frontName = front.isShaderIOBlock ? front.structOrBlockName : front.name; - return backName == frontName; + return backName == frontName && back.location == front.location; } GLint GetMaxShaderInputVectors(const Caps &caps, ShaderType shaderStage) diff --git a/src/libANGLE/VaryingPacking.h b/src/libANGLE/VaryingPacking.h index 960d20626f9..20e608779cf 100644 --- a/src/libANGLE/VaryingPacking.h +++ b/src/libANGLE/VaryingPacking.h @@ -12,6 +12,10 @@ #ifndef LIBANGLE_VARYINGPACKING_H_ #define LIBANGLE_VARYINGPACKING_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "angle_gl.h" diff --git a/src/libANGLE/Version.h b/src/libANGLE/Version.h index 0d3b502d211..1dd3d132b6e 100644 --- a/src/libANGLE/Version.h +++ b/src/libANGLE/Version.h @@ -9,26 +9,61 @@ #ifndef LIBANGLE_VERSION_H_ #define LIBANGLE_VERSION_H_ +#include + namespace gl { -struct Version +struct alignas(uint16_t) Version { - constexpr Version(); - constexpr Version(unsigned int major, unsigned int minor); + // Avoid conflicts with linux system defines +#undef major +#undef minor + + constexpr Version() = default; + constexpr Version(uint8_t major, uint8_t minor) : value((major << 8) | minor) {} + + constexpr bool operator==(const Version &other) const { return value == other.value; } + constexpr bool operator!=(const Version &other) const { return value != other.value; } + constexpr bool operator>=(const Version &other) const { return value >= other.value; } + constexpr bool operator<=(const Version &other) const { return value <= other.value; } + constexpr bool operator<(const Version &other) const { return value < other.value; } + constexpr bool operator>(const Version &other) const { return value > other.value; } + + // These functions should not be used for compare operations. + constexpr uint32_t getMajor() const { return value >> 8; } + constexpr uint32_t getMinor() const { return value & 0xFF; } - unsigned int major; - unsigned int minor; + private: + uint16_t value = 0; }; +static_assert(sizeof(Version) == 2); -bool operator==(const Version &a, const Version &b); -bool operator!=(const Version &a, const Version &b); -bool operator>=(const Version &a, const Version &b); -bool operator<=(const Version &a, const Version &b); -bool operator<(const Version &a, const Version &b); -bool operator>(const Version &a, const Version &b); -} // namespace gl +static_assert(Version().getMajor() == 0); +static_assert(Version().getMinor() == 0); +static_assert(Version(0, 255).getMajor() == 0); +static_assert(Version(0, 255).getMinor() == 255); +static_assert(Version(255, 0).getMajor() == 255); +static_assert(Version(255, 0).getMinor() == 0); +static_assert(Version(4, 5).getMajor() == 4); +static_assert(Version(4, 5).getMinor() == 5); +static_assert(Version(4, 6) == Version(4, 6)); +static_assert(Version(1, 0) != Version(1, 1)); +static_assert(Version(1, 0) != Version(2, 0)); +static_assert(Version(2, 0) > Version(1, 0)); +static_assert(Version(3, 1) > Version(3, 0)); +static_assert(Version(3, 0) > Version(1, 1)); +static_assert(Version(2, 0) < Version(3, 0)); +static_assert(Version(3, 1) < Version(3, 2)); +static_assert(Version(1, 1) < Version(2, 0)); + +static constexpr Version ES_1_0 = Version(1, 0); +static constexpr Version ES_1_1 = Version(1, 1); +static constexpr Version ES_2_0 = Version(2, 0); +static constexpr Version ES_3_0 = Version(3, 0); +static constexpr Version ES_3_1 = Version(3, 1); +static constexpr Version ES_3_2 = Version(3, 2); -#include "Version.inc" +} // namespace gl #endif // LIBANGLE_VERSION_H_ diff --git a/src/libANGLE/Version.inc b/src/libANGLE/Version.inc deleted file mode 100644 index a2bab8dc1f6..00000000000 --- a/src/libANGLE/Version.inc +++ /dev/null @@ -1,59 +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. -// - -// Version.inc: Encapsulation of a GL version. - -#include - -namespace gl -{ - -constexpr Version::Version() - : Version(0, 0) -{ -} - -// Avoid conflicts with linux system defines -#undef major -#undef minor - -constexpr Version::Version(unsigned int major_, unsigned int minor_) - : major(major_), - minor(minor_) -{ -} - -inline bool operator==(const Version &a, const Version &b) -{ - return std::tie(a.major, a.minor) == std::tie(b.major, b.minor); -} - -inline bool operator!=(const Version &a, const Version &b) -{ - return std::tie(a.major, a.minor) != std::tie(b.major, b.minor); -} - -inline bool operator>=(const Version &a, const Version &b) -{ - return std::tie(a.major, a.minor) >= std::tie(b.major, b.minor); -} - -inline bool operator<=(const Version &a, const Version &b) -{ - return std::tie(a.major, a.minor) <= std::tie(b.major, b.minor); -} - -inline bool operator<(const Version &a, const Version &b) -{ - return std::tie(a.major, a.minor) < std::tie(b.major, b.minor); -} - -inline bool operator>(const Version &a, const Version &b) -{ - return std::tie(a.major, a.minor) > std::tie(b.major, b.minor); -} - -} // namespace gl diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp index 9bc2fbe00a2..bc17874cbfa 100644 --- a/src/libANGLE/VertexArray.cpp +++ b/src/libANGLE/VertexArray.cpp @@ -17,19 +17,11 @@ namespace gl { -namespace -{ -bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex) -{ - return (subjectIndex == kElementArrayBufferIndex); -} -} // namespace - // VertexArrayState implementation. -VertexArrayState::VertexArrayState(VertexArray *vertexArray, +VertexArrayState::VertexArrayState(VertexArrayID vertexArrayID, size_t maxAttribs, size_t maxAttribBindings) - : mId(vertexArray->id()), mElementArrayBuffer(vertexArray, kElementArrayBufferIndex) + : mId(vertexArrayID) { ASSERT(maxAttribs <= maxAttribBindings); @@ -57,9 +49,7 @@ AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) } // Set an attribute using a new binding. -void VertexArrayState::setAttribBinding(const Context *context, - size_t attribIndex, - GLuint newBindingIndex) +void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex) { ASSERT(attribIndex < mVertexAttributes.size() && newBindingIndex < mVertexBindings.size()); @@ -81,87 +71,274 @@ void VertexArrayState::setAttribBinding(const Context *context, // Set the attribute using the new binding. attrib.bindingIndex = newBindingIndex; - if (context->isBufferAccessValidationEnabled()) + mEnabledAttributesMask.set(attribIndex, attrib.enabled); +} + +bool VertexArrayState::isDefault() const +{ + return mId.value == 0; +} + +// VertexArrayPrivate implementation. +VertexArrayPrivate::VertexArrayPrivate(rx::GLImplFactory *factory, + VertexArrayID id, + size_t maxAttribs, + size_t maxAttribBindings) + : mId(id), mState(mId, maxAttribs, maxAttribBindings), mRobustBufferAccessEnabled(false) +{} + +VertexArrayPrivate::~VertexArrayPrivate() {} + +void VertexArrayPrivate::setVertexAttribBinding(size_t attribIndex, GLuint newBindingIndex) +{ + ASSERT(attribIndex < getMaxAttribs() && newBindingIndex < getMaxBindings()); + + if (mState.mVertexAttributes[attribIndex].bindingIndex == newBindingIndex) { - attrib.updateCachedElementLimit(newBinding); + return; } - bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped(); - mCachedMappedArrayBuffers.set(attribIndex, isMapped); - mEnabledAttributesMask.set(attribIndex, attrib.enabled); - updateCachedMutableOrNonPersistentArrayBuffers(attribIndex); - mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mEnabledAttributesMask & + mState.setAttribBinding(attribIndex, newBindingIndex); + + if (mRobustBufferAccessEnabled) + { + VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; + attrib.updateCachedElementLimit(mState.mVertexBindings[newBindingIndex], + mCachedBufferSize[newBindingIndex]); + } + + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING); + + // Update client attribs mask. + mState.mClientMemoryAttribsMask.set(attribIndex, !mBufferBindingMask[newBindingIndex]); + + mCachedMappedArrayBuffers.set(attribIndex, mCachedBufferPropertyMapped.test(newBindingIndex)); + mCachedMutableOrImpersistentArrayBuffers.set( + attribIndex, mCachedBufferPropertyMutableOrImpersistent.test(newBindingIndex)); + mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mState.mEnabledAttributesMask & mCachedMutableOrImpersistentArrayBuffers; } -void VertexArrayState::updateCachedMutableOrNonPersistentArrayBuffers(size_t index) +const VertexAttribute &VertexArrayPrivate::getVertexAttribute(size_t attribIndex) const { - const VertexBinding &vertexBinding = mVertexBindings[index]; - const BindingPointer &buffer = vertexBinding.getBuffer(); - bool isMutableOrImpersistentArrayBuffer = - buffer.get() && - (!buffer->isImmutable() || (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0); - mCachedMutableOrImpersistentArrayBuffers.set(index, isMutableOrImpersistentArrayBuffer); + ASSERT(attribIndex < getMaxAttribs()); + return mState.mVertexAttributes[attribIndex]; } -bool VertexArrayState::isDefault() const +const VertexBinding &VertexArrayPrivate::getVertexBinding(size_t bindingIndex) const { - return mId.value == 0; + ASSERT(bindingIndex < getMaxBindings()); + return mState.mVertexBindings[bindingIndex]; } -// VertexArray implementation. -VertexArray::VertexArray(rx::GLImplFactory *factory, - VertexArrayID id, - size_t maxAttribs, - size_t maxAttribBindings) - : mId(id), - mState(this, maxAttribs, maxAttribBindings), - mVertexArray(factory->createVertexArray(mState)), - mBufferAccessValidationEnabled(false), - mContentsObservers(this) +void VertexArrayPrivate::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit) { - for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex) + mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex); + mDirtyAttribBits[attribIndex].set(dirtyAttribBit); +} + +ANGLE_INLINE void VertexArrayPrivate::clearDirtyAttribBit(size_t attribIndex, + DirtyAttribBitType dirtyAttribBit) +{ + mDirtyAttribBits[attribIndex].set(dirtyAttribBit, false); + if (mDirtyAttribBits[attribIndex].any()) { - mArrayBufferObserverBindings.emplace_back(this, attribIndex); + return; } + mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex, false); +} - mVertexArray->setContentsObservers(&mContentsObservers); +ANGLE_INLINE void VertexArrayPrivate::setDirtyBindingBit(size_t bindingIndex, + DirtyBindingBitType dirtyBindingBit) +{ + mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex); + mDirtyBindingBits[bindingIndex].set(dirtyBindingBit); } -void VertexArray::onDestroy(const Context *context) +ANGLE_INLINE void VertexArrayPrivate::updateCachedElementLimit(const VertexBinding &binding, + GLint64 bufferSize) { - bool isBound = context->isCurrentVertexArray(this); - for (size_t bindingIndex : mState.mBufferBindingMask) + ASSERT(mRobustBufferAccessEnabled); + for (size_t boundAttribute : binding.getBoundAttributesMask()) { - VertexBinding &binding = mState.mVertexBindings[bindingIndex]; - Buffer *buffer = binding.getBuffer().get(); - ASSERT(buffer != nullptr); - if (isBound) - { - buffer->onNonTFBindingChanged(-1); - } - else + mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(binding, bufferSize); + } +} + +ANGLE_INLINE void VertexArrayPrivate::updateCachedArrayBuffersMasks( + bool isMapped, + bool isImmutable, + bool isPersistent, + const AttributesMask &boundAttributesMask) +{ + if (isMapped) + { + mCachedMappedArrayBuffers |= boundAttributesMask; + } + else + { + mCachedMappedArrayBuffers &= ~boundAttributesMask; + } + + if (!isImmutable || !isPersistent) + { + mCachedMutableOrImpersistentArrayBuffers |= boundAttributesMask; + } + else + { + mCachedMutableOrImpersistentArrayBuffers &= ~boundAttributesMask; + } + + mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mState.mEnabledAttributesMask & + mCachedMutableOrImpersistentArrayBuffers; +} + +void VertexArrayPrivate::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor) +{ + ASSERT(bindingIndex < getMaxBindings()); + + VertexBinding &binding = mState.mVertexBindings[bindingIndex]; + + if (binding.getDivisor() == divisor) + { + return; + } + + binding.setDivisor(divisor); + setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR); +} + +bool VertexArrayPrivate::setVertexAttribFormatImpl(VertexAttribute *attrib, + GLint size, + VertexAttribType type, + bool normalized, + bool pureInteger, + GLuint relativeOffset) +{ + angle::FormatID formatID = GetVertexFormatID(type, normalized, size, pureInteger); + + if (formatID != attrib->format->id || attrib->relativeOffset != relativeOffset) + { + attrib->relativeOffset = relativeOffset; + attrib->format = &angle::Format::Get(formatID); + return true; + } + + return false; +} + +void VertexArrayPrivate::setVertexAttribFormat(size_t attribIndex, + GLint size, + VertexAttribType type, + bool normalized, + bool pureInteger, + GLuint relativeOffset) +{ + VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; + + ComponentType componentType = GetVertexAttributeComponentType(pureInteger, type); + SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask); + + if (setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, relativeOffset)) + { + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT); + } + + if (mRobustBufferAccessEnabled) + { + attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex], + mCachedBufferSize[attrib.bindingIndex]); + } +} + +void VertexArrayPrivate::setVertexAttribDivisor(size_t attribIndex, GLuint divisor) +{ + ASSERT(attribIndex < getMaxAttribs()); + + setVertexAttribBinding(attribIndex, static_cast(attribIndex)); + setVertexBindingDivisor(attribIndex, divisor); +} + +void VertexArrayPrivate::enableAttribute(size_t attribIndex, bool enabledState) +{ + ASSERT(attribIndex < getMaxAttribs()); + + VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; + + if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState) + { + return; + } + + attrib.enabled = enabledState; + + // Update state cache + mState.mEnabledAttributesMask.set(attribIndex, enabledState); + bool enableChanged = (mState.mEnabledAttributesMask.test(attribIndex) != + mState.mLastSyncedEnabledAttributesMask.test(attribIndex)); + + if (enableChanged) + { + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED); + } + else + { + clearDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED); + } + + mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mState.mEnabledAttributesMask & + mCachedMutableOrImpersistentArrayBuffers; +} + +bool VertexArrayPrivate::hasTransformFeedbackBindingConflict(const Context *context) const +{ + // Fast check first. + if (!mCachedBufferPropertyTransformFeedbackConflict.any()) + { + return false; + } + + const AttributesMask &activeAttribues = context->getActiveBufferedAttribsMask(); + + // Slow check. We must ensure that the conflicting attributes are enabled/active. + for (size_t attribIndex : activeAttribues) + { + const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; + if (mCachedBufferPropertyTransformFeedbackConflict[attrib.bindingIndex]) { - // un-assigning to avoid assertion, since it was already removed from buffer's observer - // list. - mArrayBufferObserverBindings[bindingIndex].assignSubject(nullptr); + return true; } - // Note: the non-contents observer is unbound in the ObserverBinding destructor. - buffer->removeContentsObserver(this, static_cast(bindingIndex)); - binding.setBuffer(context, nullptr); } - mState.mBufferBindingMask.reset(); - if (mState.mElementArrayBuffer.get()) + return false; +} + +// VertexArray implementation. +VertexArray::VertexArray(rx::GLImplFactory *factory, + VertexArrayID id, + size_t maxAttribs, + size_t maxAttribBindings) + : VertexArrayPrivate(factory, id, maxAttribs, maxAttribBindings), + mVertexArray(factory->createVertexArray(mState, mVertexArrayBuffers)) +{} + +void VertexArray::onDestroy(const Context *context) +{ + bool isBound = context->isCurrentVertexArray(this); + + for (size_t bindingIndex : mBufferBindingMask) { + Buffer *buffer = mVertexArrayBuffers[bindingIndex].get(); + ASSERT(buffer != nullptr); if (isBound) { - mState.mElementArrayBuffer->onNonTFBindingChanged(-1); + buffer->onNonTFBindingChanged(-1); + buffer->removeVertexArrayBinding(context, bindingIndex); } - mState.mElementArrayBuffer->removeContentsObserver(this, kElementArrayBufferIndex); + mVertexArrayBuffers[bindingIndex].set(context, nullptr); } - mState.mElementArrayBuffer.bind(context, nullptr); + mBufferBindingMask.reset(); mVertexArray->destroy(context); SafeDelete(mVertexArray); delete this; @@ -185,180 +362,139 @@ angle::Result VertexArray::setLabel(const Context *context, const std::string &l const std::string &VertexArray::getLabel() const { - return mState.mLabel; + return mState.getLabel(); } bool VertexArray::detachBuffer(const Context *context, BufferID bufferID) { bool isBound = context->isCurrentVertexArray(this); bool anyBufferDetached = false; - for (size_t bindingIndex : mState.mBufferBindingMask) + + for (size_t bindingIndex : mBufferBindingMask) { - VertexBinding &binding = mState.mVertexBindings[bindingIndex]; - const BindingPointer &bufferBinding = binding.getBuffer(); - if (bufferBinding.id() == bufferID) + Buffer *buffer = mVertexArrayBuffers[bindingIndex].get(); + ASSERT(buffer != nullptr); + if (buffer->id() == bufferID) { if (isBound) { - if (bufferBinding.get()) - bufferBinding->onNonTFBindingChanged(-1); + buffer->onNonTFBindingChanged(-1); } - bufferBinding->removeContentsObserver(this, static_cast(bindingIndex)); - binding.setBuffer(context, nullptr); - mArrayBufferObserverBindings[bindingIndex].reset(); - mState.mBufferBindingMask.reset(bindingIndex); - if (context->getClientVersion() >= ES_3_1 && !mState.isDefault()) + buffer->removeVertexArrayBinding(context, bindingIndex); + mVertexArrayBuffers[bindingIndex].set(context, nullptr); + mBufferBindingMask.reset(bindingIndex); + + if (bindingIndex == kElementArrayBufferIndex) { - setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER); + mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); } else { - static_assert(MAX_VERTEX_ATTRIB_BINDINGS < 8 * sizeof(uint32_t), - "Not enough bits in bindingIndex"); - // The redundant uint32_t cast here is required to avoid a warning on MSVC. - ASSERT(binding.getBoundAttributesMask() == - AttributesMask(static_cast(1 << bindingIndex))); - setDirtyAttribBit(bindingIndex, DIRTY_ATTRIB_POINTER); + VertexBinding &binding = mState.mVertexBindings[bindingIndex]; + if (context->getClientVersion() >= ES_3_1 && !mState.isDefault()) + { + setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER); + } + else + { + static_assert(MAX_VERTEX_ATTRIB_BINDINGS < 8 * sizeof(uint32_t), + "Not enough bits in bindingIndex"); + // The redundant uint32_t cast here is required to avoid a warning on MSVC. + ASSERT(binding.getBoundAttributesMask() == + AttributesMask(static_cast(1 << bindingIndex))); + setDirtyAttribBit(bindingIndex, DIRTY_ATTRIB_POINTER); + } + + for (size_t attribIndex : binding.getBoundAttributesMask()) + { + VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; + attrib.pointer = nullptr; + } + + mState.mClientMemoryAttribsMask |= binding.getBoundAttributesMask(); } anyBufferDetached = true; - mState.mClientMemoryAttribsMask |= binding.getBoundAttributesMask(); } } - if (mState.mElementArrayBuffer.get() && mState.mElementArrayBuffer->id() == bufferID) - { - if (isBound && mState.mElementArrayBuffer.get()) - mState.mElementArrayBuffer->onNonTFBindingChanged(-1); - mState.mElementArrayBuffer->removeContentsObserver(this, kElementArrayBufferIndex); - mState.mElementArrayBuffer.bind(context, nullptr); - mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); - anyBufferDetached = true; - } - return anyBufferDetached; } -const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const +ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffersBinding(size_t bindingIndex) { - ASSERT(attribIndex < getMaxAttribs()); - return mState.mVertexAttributes[attribIndex]; -} + const VertexBinding &binding = mState.mVertexBindings[bindingIndex]; + const Buffer *buffer = mVertexArrayBuffers[bindingIndex].get(); + ASSERT(mBufferBindingMask.test(bindingIndex)); + ASSERT(buffer != nullptr); -const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const -{ - ASSERT(bindingIndex < getMaxBindings()); - return mState.mVertexBindings[bindingIndex]; -} + bool isMapped = buffer->isMapped() == GL_TRUE; + bool isImmutable = buffer->isImmutable() == GL_TRUE; + bool isPersistent = (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0; -size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit) -{ - static_assert(MAX_VERTEX_ATTRIBS == MAX_VERTEX_ATTRIB_BINDINGS, - "The stride of vertex attributes should equal to that of vertex bindings."); - ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER); - return (dirtyBit - DIRTY_BIT_ATTRIB_0) % MAX_VERTEX_ATTRIBS; -} + mCachedBufferPropertyMapped.set(bindingIndex, isMapped); + mCachedBufferPropertyMutableOrImpersistent.set(bindingIndex, !isImmutable || !isPersistent); -ANGLE_INLINE void VertexArray::setDirtyAttribBit(size_t attribIndex, - DirtyAttribBitType dirtyAttribBit) -{ - mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex); - mDirtyAttribBits[attribIndex].set(dirtyAttribBit); -} - -ANGLE_INLINE void VertexArray::clearDirtyAttribBit(size_t attribIndex, - DirtyAttribBitType dirtyAttribBit) -{ - mDirtyAttribBits[attribIndex].set(dirtyAttribBit, false); - if (mDirtyAttribBits[attribIndex].any()) - { - return; - } - mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex, false); + return updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent, + binding.getBoundAttributesMask()); } -ANGLE_INLINE void VertexArray::setDirtyBindingBit(size_t bindingIndex, - DirtyBindingBitType dirtyBindingBit) +void VertexArray::bindElementBuffer(const Context *context, Buffer *boundBuffer) { - mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex); - mDirtyBindingBits[bindingIndex].set(dirtyBindingBit); -} + Buffer *oldBuffer = getElementArrayBuffer(); -ANGLE_INLINE void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding) -{ - if (!mBufferAccessValidationEnabled) - return; - - for (size_t boundAttribute : binding->getBoundAttributesMask()) + if (oldBuffer) { - mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding); + oldBuffer->removeVertexArrayBinding(context, kElementArrayBufferIndex); + if (context->isWebGL()) + { + oldBuffer->onNonTFBindingChanged(-1); + } + oldBuffer->release(context); + mBufferBindingMask.reset(kElementArrayBufferIndex); } -} -ANGLE_INLINE void VertexArray::updateCachedArrayBuffersMasks( - bool isMapped, - bool isImmutable, - bool isPersistent, - const AttributesMask &boundAttributesMask) -{ - if (isMapped) - { - mState.mCachedMappedArrayBuffers |= boundAttributesMask; - } - else - { - mState.mCachedMappedArrayBuffers &= ~boundAttributesMask; - } + mVertexArrayBuffers[kElementArrayBufferIndex].assign(boundBuffer); - if (!isImmutable || !isPersistent) + if (boundBuffer) { - mState.mCachedMutableOrImpersistentArrayBuffers |= boundAttributesMask; - } - else - { - mState.mCachedMutableOrImpersistentArrayBuffers &= ~boundAttributesMask; + boundBuffer->addVertexArrayBinding(context, kElementArrayBufferIndex); + if (context->isWebGL()) + { + boundBuffer->onNonTFBindingChanged(1); + } + boundBuffer->addRef(); + mBufferBindingMask.set(kElementArrayBufferIndex); } - mState.mCachedInvalidMappedArrayBuffer = mState.mCachedMappedArrayBuffers & - mState.mEnabledAttributesMask & - mState.mCachedMutableOrImpersistentArrayBuffers; -} - -ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffersBinding(const VertexBinding &binding) -{ - const Buffer *buffer = binding.getBuffer().get(); - bool isMapped = buffer && buffer->isMapped(); - bool isImmutable = buffer && buffer->isImmutable(); - bool isPersistent = buffer && (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0; - return updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent, - binding.getBoundAttributesMask()); -} - -ANGLE_INLINE void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, - const Buffer *buffer) -{ - const bool hasConflict = buffer && buffer->hasWebGLXFBBindingConflict(true); - mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict); + mDirtyBits.set(VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER); + mIndexRangeInlineCache = {}; } -VertexArray::DirtyBindingBits VertexArray::bindVertexBufferImpl(const Context *context, - size_t bindingIndex, - Buffer *boundBuffer, - GLintptr offset, - GLsizei stride) +ANGLE_INLINE VertexArray::DirtyBindingBits VertexArray::bindVertexBufferImpl(const Context *context, + size_t bindingIndex, + Buffer *boundBuffer, + GLintptr offset, + GLsizei stride) { ASSERT(bindingIndex < getMaxBindings()); ASSERT(context->isCurrentVertexArray(this)); VertexBinding *binding = &mState.mVertexBindings[bindingIndex]; - Buffer *oldBuffer = binding->getBuffer().get(); + Buffer *oldBuffer = mVertexArrayBuffers[bindingIndex].get(); DirtyBindingBits dirtyBindingBits; dirtyBindingBits.set(DIRTY_BINDING_BUFFER, oldBuffer != boundBuffer); dirtyBindingBits.set(DIRTY_BINDING_STRIDE, static_cast(stride) != binding->getStride()); dirtyBindingBits.set(DIRTY_BINDING_OFFSET, offset != binding->getOffset()); + if (mRobustBufferAccessEnabled) + { + GLint64 bufferSize = boundBuffer ? boundBuffer->getSize() : 0; + dirtyBindingBits.set(DIRTY_BINDING_SIZE, bufferSize != mCachedBufferSize[bindingIndex]); + mCachedBufferSize[bindingIndex] = bufferSize; + } if (dirtyBindingBits.none()) { @@ -367,55 +503,52 @@ VertexArray::DirtyBindingBits VertexArray::bindVertexBufferImpl(const Context *c if (boundBuffer != oldBuffer) { - angle::ObserverBinding *observer = &mArrayBufferObserverBindings[bindingIndex]; - observer->assignSubject(boundBuffer); - // Several nullptr checks are combined here for optimization purposes. if (oldBuffer) { oldBuffer->onNonTFBindingChanged(-1); - oldBuffer->removeObserver(observer); - oldBuffer->removeContentsObserver(this, static_cast(bindingIndex)); + oldBuffer->removeVertexArrayBinding(context, bindingIndex); oldBuffer->release(context); - mState.mBufferBindingMask.reset(bindingIndex); + mBufferBindingMask.reset(bindingIndex); } - binding->assignBuffer(boundBuffer); + mVertexArrayBuffers[bindingIndex].assign(boundBuffer); // Update client memory attribute pointers. Affects all bound attributes. if (boundBuffer) { boundBuffer->addRef(); boundBuffer->onNonTFBindingChanged(1); - boundBuffer->addObserver(observer); + boundBuffer->addVertexArrayBinding(context, bindingIndex); if (context->isWebGL()) { - mCachedTransformFeedbackConflictedBindingsMask.set( + mCachedBufferPropertyTransformFeedbackConflict.set( bindingIndex, boundBuffer->hasWebGLXFBBindingConflict(true)); } - mState.mBufferBindingMask.set(bindingIndex); + mBufferBindingMask.set(bindingIndex); mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask(); - - bool isMapped = boundBuffer->isMapped() == GL_TRUE; - bool isImmutable = boundBuffer->isImmutable() == GL_TRUE; - bool isPersistent = (boundBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0; - updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent, - binding->getBoundAttributesMask()); + updateCachedMappedArrayBuffersBinding(bindingIndex); } else { if (context->isWebGL()) { - mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, false); + mCachedBufferPropertyTransformFeedbackConflict.set(bindingIndex, false); } mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask(); + mCachedBufferPropertyMapped.set(bindingIndex, false); + mCachedBufferPropertyMutableOrImpersistent.set(bindingIndex, false); updateCachedArrayBuffersMasks(false, false, false, binding->getBoundAttributesMask()); } } binding->setOffset(offset); binding->setStride(stride); - updateCachedBufferBindingSize(binding); + + if (mRobustBufferAccessEnabled) + { + updateCachedElementLimit(*binding, mCachedBufferSize[bindingIndex]); + } return dirtyBindingBits; } @@ -428,131 +561,21 @@ void VertexArray::bindVertexBuffer(const Context *context, { const VertexArray::DirtyBindingBits dirtyBindingBits = bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride); - if (dirtyBindingBits.any()) - { - mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex); - mDirtyBindingBits[bindingIndex] |= dirtyBindingBits; - } -} - -void VertexArray::setVertexAttribBinding(const Context *context, - size_t attribIndex, - GLuint bindingIndex) -{ - ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings()); - - if (mState.mVertexAttributes[attribIndex].bindingIndex == bindingIndex) - { - return; - } - - // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable. - ASSERT(context->getClientVersion() >= ES_3_1 && !mState.isDefault()); - - mState.setAttribBinding(context, attribIndex, bindingIndex); - - setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING); - - // Update client attribs mask. - bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr; - mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer); -} - -void VertexArray::setVertexBindingDivisor(const Context *context, - size_t bindingIndex, - GLuint divisor) -{ - ASSERT(bindingIndex < getMaxBindings()); - - VertexBinding &binding = mState.mVertexBindings[bindingIndex]; - - if (binding.getDivisor() == divisor) - { - return; - } - - binding.setDivisor(divisor); - setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR); -} - -ANGLE_INLINE bool VertexArray::setVertexAttribFormatImpl(VertexAttribute *attrib, - GLint size, - VertexAttribType type, - bool normalized, - bool pureInteger, - GLuint relativeOffset) -{ - angle::FormatID formatID = GetVertexFormatID(type, normalized, size, pureInteger); - - if (formatID != attrib->format->id || attrib->relativeOffset != relativeOffset) - { - attrib->relativeOffset = relativeOffset; - attrib->format = &angle::Format::Get(formatID); - return true; - } - - return false; -} - -void VertexArray::setVertexAttribFormat(size_t attribIndex, - GLint size, - VertexAttribType type, - bool normalized, - bool pureInteger, - GLuint relativeOffset) -{ - VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; - - ComponentType componentType = GetVertexAttributeComponentType(pureInteger, type); - SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask); - if (setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, relativeOffset)) + if (!dirtyBindingBits.test(DIRTY_BINDING_BUFFER) && context->isSharedContext() && + boundBuffer != nullptr) { - setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT); + ASSERT(boundBuffer == mVertexArrayBuffers[bindingIndex].get()); + VertexArrayBufferBindingMask bindingMask = boundBuffer->getVertexArrayBinding(context); + ASSERT(!bindingMask.none()); + onSharedBufferBind(context, boundBuffer, bindingMask); } - attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]); -} - -void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor) -{ - ASSERT(attribIndex < getMaxAttribs()); - - setVertexAttribBinding(context, attribIndex, static_cast(attribIndex)); - setVertexBindingDivisor(context, attribIndex, divisor); -} - -void VertexArray::enableAttribute(size_t attribIndex, bool enabledState) -{ - ASSERT(attribIndex < getMaxAttribs()); - - VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; - - if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState) - { - return; - } - - attrib.enabled = enabledState; - - // Update state cache - mState.mEnabledAttributesMask.set(attribIndex, enabledState); - bool enableChanged = (mState.mEnabledAttributesMask.test(attribIndex) != - mState.mLastSyncedEnabledAttributesMask.test(attribIndex)); - - if (enableChanged) - { - setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED); - } - else + if (dirtyBindingBits.any()) { - clearDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED); + mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex); + mDirtyBindingBits[bindingIndex] |= dirtyBindingBits; } - - mState.updateCachedMutableOrNonPersistentArrayBuffers(attribIndex); - mState.mCachedInvalidMappedArrayBuffer = mState.mCachedMappedArrayBuffers & - mState.mEnabledAttributesMask & - mState.mCachedMutableOrImpersistentArrayBuffers; } ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context, @@ -564,8 +587,10 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context VertexAttribType type, bool normalized, GLsizei stride, - const void *pointer) + const void *pointer, + bool *isVertexAttribDirtyOut) { + ASSERT(isVertexAttribDirtyOut); ASSERT(attribIndex < getMaxAttribs()); VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; @@ -576,7 +601,7 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context if (attrib.bindingIndex != attribIndex) { - setVertexAttribBinding(context, attribIndex, static_cast(attribIndex)); + setVertexAttribBinding(attribIndex, static_cast(attribIndex)); } GLsizei effectiveStride = @@ -590,8 +615,8 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context // If we switch from an array buffer to a client pointer(or vice-versa), we set the whole // attribute dirty. This notifies the Vulkan back-end to update all its caches. - const VertexBinding &binding = mState.mVertexBindings[attribIndex]; - if ((boundBuffer == nullptr) != (binding.getBuffer().get() == nullptr)) + Buffer *oldBuffer = mVertexArrayBuffers[attrib.bindingIndex].get(); + if ((boundBuffer == nullptr) != (oldBuffer == nullptr)) { attribDirty = true; } @@ -612,10 +637,12 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context if (attribDirty) { setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER); + *isVertexAttribDirtyOut = true; } else if (dirtyBindingBits.any()) { setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER_BUFFER); + *isVertexAttribDirtyOut = true; } mState.mNullPointerClientMemoryAttribsMask.set(attribIndex, @@ -629,10 +656,11 @@ void VertexArray::setVertexAttribPointer(const Context *context, VertexAttribType type, bool normalized, GLsizei stride, - const void *pointer) + const void *pointer, + bool *isVertexAttribDirtyOut) { setVertexAttribPointerImpl(context, ComponentType::Float, false, attribIndex, boundBuffer, size, - type, normalized, stride, pointer); + type, normalized, stride, pointer, isVertexAttribDirtyOut); } void VertexArray::setVertexAttribIPointer(const Context *context, @@ -641,11 +669,12 @@ void VertexArray::setVertexAttribIPointer(const Context *context, GLint size, VertexAttribType type, GLsizei stride, - const void *pointer) + const void *pointer, + bool *isVertexAttribDirtyOut) { ComponentType componentType = GetVertexAttributeComponentType(true, type); setVertexAttribPointerImpl(context, componentType, true, attribIndex, boundBuffer, size, type, - false, stride, pointer); + false, stride, pointer, isVertexAttribDirtyOut); } angle::Result VertexArray::syncState(const Context *context) @@ -666,38 +695,90 @@ angle::Result VertexArray::syncState(const Context *context) return angle::Result::Continue; } +bool VertexArray::bufferMaskBitsPointToTheSameBuffer( + VertexArrayBufferBindingMask bufferBindingMask) const +{ + const Buffer *buffer = nullptr; + for (size_t bindingIndex : bufferBindingMask) + { + if (buffer == nullptr) + { + buffer = mVertexArrayBuffers[bindingIndex].get(); + } + else if (buffer != mVertexArrayBuffers[bindingIndex].get()) + { + return false; + } + } + return true; +} + +void VertexArray::updateBindingSizeIfChanged(const size_t bindingIndex, const GLint64 bufferSize) +{ + ASSERT(mRobustBufferAccessEnabled); + if (mCachedBufferSize[bindingIndex] != bufferSize) + { + setDirtyBindingBit(bindingIndex, DIRTY_BINDING_SIZE); + mCachedBufferSize[bindingIndex] = bufferSize; + } +} + // This becomes current vertex array on the context void VertexArray::onBind(const Context *context) { + VertexArrayBufferBindingMask bufferBindingMask = mBufferBindingMask; + + if (bufferBindingMask[kElementArrayBufferIndex]) + { + Buffer *bufferGL = getElementArrayBuffer(); + ASSERT(bufferGL != nullptr); + bufferGL->addVertexArrayBinding(context, kElementArrayBufferIndex); + bufferBindingMask.reset(kElementArrayBufferIndex); + } + else + { + ASSERT(getElementArrayBuffer() == nullptr); + } + // This vertex array becoming current. Some of the bindings we may have removed from buffer's // observer list. We need to add it back to the buffer's observer list and update dirty bits // that we may have missed while we were not observing. - for (size_t bindingIndex : mState.getBufferBindingMask()) + for (size_t bindingIndex : bufferBindingMask) { - const VertexBinding &binding = mState.getVertexBindings()[bindingIndex]; - Buffer *bufferGL = binding.getBuffer().get(); + Buffer *bufferGL = mVertexArrayBuffers[bindingIndex].get(); ASSERT(bufferGL != nullptr); + ASSERT(bindingIndex != kElementArrayBufferIndex); + bufferGL->addVertexArrayBinding(context, bindingIndex); + updateCachedMappedArrayBuffersBinding(bindingIndex); + } - bufferGL->addObserver(&mArrayBufferObserverBindings[bindingIndex]); - updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[bindingIndex]); - - if (mBufferAccessValidationEnabled) + if (mRobustBufferAccessEnabled) + { + for (size_t bindingIndex : bufferBindingMask) { - for (size_t boundAttribute : - mState.mVertexBindings[bindingIndex].getBoundAttributesMask()) - { - mState.mVertexAttributes[boundAttribute].updateCachedElementLimit( - mState.mVertexBindings[bindingIndex]); - } + Buffer *bufferGL = mVertexArrayBuffers[bindingIndex].get(); + updateBindingSizeIfChanged(bindingIndex, bufferGL->getSize()); + updateCachedElementLimit(mState.mVertexBindings[bindingIndex], + mCachedBufferSize[bindingIndex]); } + } - if (context->isWebGL()) + if (context->isWebGL()) + { + for (size_t bindingIndex : bufferBindingMask) { - updateCachedTransformFeedbackBindingValidation(bindingIndex, bufferGL); + bool hasConflict = mVertexArrayBuffers[bindingIndex]->hasWebGLXFBBindingConflict(true); + mCachedBufferPropertyTransformFeedbackConflict.set(bindingIndex, hasConflict); } } - mDirtyBits.set(DIRTY_BIT_LOST_OBSERVATION); + // Buffers may have changed while vertex array was not current, we need to check buffer's + // internal storage and set proper dirty bits if buffer has changed since last syncState. + mDirtyBits |= mVertexArray->checkBufferForDirtyBits(context, mBufferBindingMask); + + // Always reset mIndexRangeInlineCache since we lost buffer observation while unbind + mIndexRangeInlineCache = {}; + onStateChange(angle::SubjectMessage::ContentsChanged); } @@ -707,12 +788,11 @@ void VertexArray::onUnbind(const Context *context) // This vertex array becoming non-current. For performance reason, we remove it from the // buffers' observer list so that the cost of buffer sending signal to observers will not be too // expensive. - for (size_t bindingIndex : mState.mBufferBindingMask) + for (size_t bindingIndex : mBufferBindingMask) { - const VertexBinding &binding = mState.getVertexBindings()[bindingIndex]; - Buffer *bufferGL = binding.getBuffer().get(); + Buffer *bufferGL = mVertexArrayBuffers[bindingIndex].get(); ASSERT(bufferGL != nullptr); - bufferGL->removeObserver(&mArrayBufferObserverBindings[bindingIndex]); + bufferGL->removeVertexArrayBinding(context, bindingIndex); } } @@ -735,173 +815,163 @@ void VertexArray::onBindingChanged(const Context *context, int incr) if (context->isWebGL()) { - if (mState.mElementArrayBuffer.get()) + for (size_t bindingIndex : mBufferBindingMask) { - mState.mElementArrayBuffer->onNonTFBindingChanged(incr); - } - for (size_t bindingIndex : mState.mBufferBindingMask) - { - mState.mVertexBindings[bindingIndex].onContainerBindingChanged(context, incr); + ASSERT(mVertexArrayBuffers[bindingIndex].get()); + mVertexArrayBuffers[bindingIndex]->onNonTFBindingChanged(incr); } } } -VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged, - angle::SubjectIndex index) const +void VertexArray::setDependentDirtyBits(bool contentsChanged, + VertexArrayBufferBindingMask bufferBindingMask) { - if (IsElementArrayBufferSubjectIndex(index)) + DirtyBits dirtyBits(contentsChanged ? (bufferBindingMask.bits() << DIRTY_BIT_BUFFER_DATA_0) + : (bufferBindingMask.bits() << DIRTY_BIT_BINDING_0)); + ASSERT(!mDirtyBitsGuard.valid() || (mDirtyBitsGuard.value() & dirtyBits) == dirtyBits); + mDirtyBits |= dirtyBits; + + if (bufferBindingMask.test(kElementArrayBufferIndex)) { - mIndexRangeCache.invalidate(); - return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA - : DIRTY_BIT_ELEMENT_ARRAY_BUFFER; + mIndexRangeInlineCache = {}; } - else + + onStateChange(angle::SubjectMessage::ContentsChanged); +} + +void VertexArray::onSharedBufferBind(const Context *context, + const Buffer *buffer, + VertexArrayBufferBindingMask bufferBindingMask) +{ + bufferBindingMask &= mBufferBindingMask; + ASSERT(bufferBindingMask.any()); + + // vertexBufferBindingMask is bufferBindingMask without elementBuffer. + VertexArrayBufferBindingMask vertexBufferBindingMask = bufferBindingMask; + vertexBufferBindingMask.reset(kElementArrayBufferIndex); + + for (size_t bindingIndex : vertexBufferBindingMask) { - // Note: this currently just gets the top-level dirty bit. - ASSERT(index < mArrayBufferObserverBindings.size()); - return static_cast( - (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index); + updateCachedMappedArrayBuffersBinding(bindingIndex); } + + if (mRobustBufferAccessEnabled) + { + for (size_t bindingIndex : vertexBufferBindingMask) + { + ASSERT(buffer == mVertexArrayBuffers[bindingIndex].get()); + updateBindingSizeIfChanged(bindingIndex, buffer->getSize()); + updateCachedElementLimit(mState.mVertexBindings[bindingIndex], + mCachedBufferSize[bindingIndex]); + } + } + + if (context->isWebGL()) + { + if (buffer->hasWebGLXFBBindingConflict(true)) + { + mCachedBufferPropertyTransformFeedbackConflict |= vertexBufferBindingMask; + } + else + { + mCachedBufferPropertyTransformFeedbackConflict &= ~vertexBufferBindingMask; + } + } + + // Set proper dirty bits on VertexArray + mDirtyBits |= mVertexArray->checkBufferForDirtyBits(context, bufferBindingMask); + + // mIndexRangeInlineCache is no longer invalid + mIndexRangeInlineCache = {}; } -void VertexArray::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) +void VertexArray::onBufferChanged(const Context *context, + const Buffer *buffer, + angle::SubjectMessage message, + VertexArrayBufferBindingMask vertexArrayBufferBindingMask) { + VertexArrayBufferBindingMask bufferBindingMask = + vertexArrayBufferBindingMask & mBufferBindingMask; + ASSERT(buffer); + ASSERT(bufferBindingMask.any()); + ASSERT(bufferMaskBitsPointToTheSameBuffer(bufferBindingMask)); + switch (message) { case angle::SubjectMessage::SubjectChanged: - if (!IsElementArrayBufferSubjectIndex(index)) + if (mRobustBufferAccessEnabled) { - updateCachedBufferBindingSize(&mState.mVertexBindings[index]); + VertexArrayBufferBindingMask VertexBufferBindingMask = bufferBindingMask; + VertexBufferBindingMask.reset(kElementArrayBufferIndex); + for (size_t bindingIndex : VertexBufferBindingMask) + { + updateBindingSizeIfChanged(bindingIndex, buffer->getSize()); + updateCachedElementLimit(mState.mVertexBindings[bindingIndex], + mCachedBufferSize[bindingIndex]); + } } - setDependentDirtyBit(false, index); + // This has to be called after updateCachedElementLimit due to + // mCachedElementLimit dependency + setDependentDirtyBits(false, bufferBindingMask); break; case angle::SubjectMessage::BindingChanged: - if (!IsElementArrayBufferSubjectIndex(index)) + if (context->isWebGL()) { - const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get(); - updateCachedTransformFeedbackBindingValidation(index, buffer); + bufferBindingMask.reset(kElementArrayBufferIndex); + + bool hasConflict = buffer->hasWebGLXFBBindingConflict(true); + if (hasConflict) + { + mCachedBufferPropertyTransformFeedbackConflict |= bufferBindingMask; + } + else + { + mCachedBufferPropertyTransformFeedbackConflict &= ~bufferBindingMask; + } } break; case angle::SubjectMessage::SubjectMapped: - if (!IsElementArrayBufferSubjectIndex(index)) + bufferBindingMask.reset(kElementArrayBufferIndex); + for (size_t bindingIndex : bufferBindingMask) { - updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]); + updateCachedMappedArrayBuffersBinding(bindingIndex); } onStateChange(angle::SubjectMessage::SubjectMapped); break; case angle::SubjectMessage::SubjectUnmapped: - setDependentDirtyBit(true, index); - - if (!IsElementArrayBufferSubjectIndex(index)) + { + VertexArrayBufferBindingMask VertexBufferBindingMask = bufferBindingMask; + VertexBufferBindingMask.reset(kElementArrayBufferIndex); + for (size_t bindingIndex : VertexBufferBindingMask) { - updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]); + updateCachedMappedArrayBuffersBinding(bindingIndex); } + setDependentDirtyBits(true, bufferBindingMask); onStateChange(angle::SubjectMessage::SubjectUnmapped); - break; + } + break; case angle::SubjectMessage::InternalMemoryAllocationChanged: - setDependentDirtyBit(false, index); + setDependentDirtyBits(false, bufferBindingMask); break; - default: - UNREACHABLE(); - break; - } -} - -void VertexArray::setDependentDirtyBit(bool contentsChanged, angle::SubjectIndex index) -{ - DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index); - ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit)); - mDirtyBits.set(dirtyBit); - onStateChange(angle::SubjectMessage::ContentsChanged); -} - -bool VertexArray::hasTransformFeedbackBindingConflict(const Context *context) const -{ - // Fast check first. - if (!mCachedTransformFeedbackConflictedBindingsMask.any()) - { - return false; - } - - const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask(); - - // Slow check. We must ensure that the conflicting attributes are enabled/active. - for (size_t attribIndex : activeAttribues) - { - const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; - if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex]) + case angle::SubjectMessage::ContentsChanged: { - return true; + VertexArrayBufferBindingMask bufferContentObserverBindingMask = + vertexArrayBufferBindingMask & mVertexArray->getContentObserversBindingMask(); + if (bufferContentObserverBindingMask.any()) + { + setDependentDirtyBits(true, bufferBindingMask); + } } - } + break; - return false; -} - -angle::Result VertexArray::getIndexRangeImpl(const Context *context, - DrawElementsType type, - GLsizei indexCount, - const void *indices, - IndexRange *indexRangeOut) const -{ - Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get(); - if (!elementArrayBuffer) - { - *indexRangeOut = ComputeIndexRange(type, indices, indexCount, - context->getState().isPrimitiveRestartEnabled()); - return angle::Result::Continue; - } - - size_t offset = reinterpret_cast(indices); - ANGLE_TRY(elementArrayBuffer->getIndexRange(context, type, offset, indexCount, - context->getState().isPrimitiveRestartEnabled(), - indexRangeOut)); - - mIndexRangeCache.put(type, indexCount, offset, *indexRangeOut); - return angle::Result::Continue; -} - -VertexArray::IndexRangeCache::IndexRangeCache() = default; - -void VertexArray::IndexRangeCache::put(DrawElementsType type, - GLsizei indexCount, - size_t offset, - const IndexRange &indexRange) -{ - ASSERT(type != DrawElementsType::InvalidEnum); - - mTypeKey = type; - mIndexCountKey = indexCount; - mOffsetKey = offset; - mPayload = indexRange; -} - -void VertexArray::onBufferContentsChange(uint32_t bufferIndex) -{ - setDependentDirtyBit(true, bufferIndex); -} - -VertexArrayBufferContentsObservers::VertexArrayBufferContentsObservers(VertexArray *vertexArray) - : mVertexArray(vertexArray) -{} - -void VertexArrayBufferContentsObservers::enableForBuffer(Buffer *buffer, uint32_t attribIndex) -{ - buffer->addContentsObserver(mVertexArray, attribIndex); - mBufferObserversBitMask.set(attribIndex); -} - -void VertexArrayBufferContentsObservers::disableForBuffer(Buffer *buffer, uint32_t attribIndex) -{ - if (mBufferObserversBitMask.test(attribIndex)) - { - buffer->removeContentsObserver(mVertexArray, attribIndex); - mBufferObserversBitMask.reset(attribIndex); + default: + UNREACHABLE(); + break; } } } // namespace gl diff --git a/src/libANGLE/VertexArray.h b/src/libANGLE/VertexArray.h index 5ecb6351b91..413cbdd2fbd 100644 --- a/src/libANGLE/VertexArray.h +++ b/src/libANGLE/VertexArray.h @@ -16,6 +16,7 @@ #include "common/Optional.h" #include "libANGLE/Constants.h" #include "libANGLE/Debug.h" +#include "libANGLE/IndexRangeCache.h" #include "libANGLE/Observer.h" #include "libANGLE/RefCountObject.h" #include "libANGLE/VertexAttribute.h" @@ -32,17 +33,14 @@ namespace gl { class Buffer; -constexpr uint32_t kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS; - class VertexArrayState final : angle::NonCopyable { public: - VertexArrayState(VertexArray *vertexArray, size_t maxAttribs, size_t maxBindings); + VertexArrayState(VertexArrayID vertexArrayID, size_t maxAttribs, size_t maxBindings); ~VertexArrayState(); const std::string &getLabel() const { return mLabel; } - Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } size_t getMaxAttribs() const { return mVertexAttributes.size(); } size_t getMaxBindings() const { return mVertexBindings.size(); } const AttributesMask &getEnabledAttributesMask() const { return mEnabledAttributesMask; } @@ -65,7 +63,7 @@ class VertexArrayState final : angle::NonCopyable return mVertexAttributes[attribIndex].bindingIndex; } - void setAttribBinding(const Context *context, size_t attribIndex, GLuint newBindingIndex); + void setAttribBinding(size_t attribIndex, GLuint newBindingIndex); // Extra validation performed on the Vertex Array. bool hasEnabledNullPointerClientArray() const; @@ -82,28 +80,24 @@ class VertexArrayState final : angle::NonCopyable return mNullPointerClientMemoryAttribsMask; } - VertexArrayBufferBindingMask getBufferBindingMask() const { return mBufferBindingMask; } - VertexArrayID id() const { return mId; } bool isDefault() const; private: - void updateCachedMutableOrNonPersistentArrayBuffers(size_t index); - + friend class VertexArrayPrivate; friend class VertexArray; VertexArrayID mId; std::string mLabel; std::vector mVertexAttributes; - SubjectBindingPointer mElementArrayBuffer; + // mMaxVertexAttribBindings is the max size of vertex attributes. element buffer is stored in + // mVertexBindings[kElementArrayBufferIndex]. std::vector mVertexBindings; + AttributesMask mEnabledAttributesMask; ComponentTypeMask mVertexAttributesTypeMask; AttributesMask mLastSyncedEnabledAttributesMask; - // Track which binding index has a buffer bound - VertexArrayBufferBindingMask mBufferBindingMask; - // This is a performance optimization for buffer binding. Allows element array buffer updates. friend class State; @@ -113,30 +107,9 @@ class VertexArrayState final : angle::NonCopyable // attribs. AttributesMask mClientMemoryAttribsMask; AttributesMask mNullPointerClientMemoryAttribsMask; - - // Used for validation cache. Indexed by attribute. - AttributesMask mCachedMappedArrayBuffers; - AttributesMask mCachedMutableOrImpersistentArrayBuffers; - AttributesMask mCachedInvalidMappedArrayBuffer; -}; - -class VertexArrayBufferContentsObservers final : angle::NonCopyable -{ - public: - VertexArrayBufferContentsObservers(VertexArray *vertexArray); - void enableForBuffer(Buffer *buffer, uint32_t bufferIndex); - void disableForBuffer(Buffer *buffer, uint32_t bufferIndex); - bool any() const { return mBufferObserversBitMask.any(); } - - private: - VertexArray *mVertexArray; - // Bit is set when it is observing the buffer content change - gl::AttributesMask mBufferObserversBitMask; }; -class VertexArray final : public angle::ObserverInterface, - public LabeledObject, - public angle::Subject +class VertexArrayPrivate : public angle::NonCopyable { public: // Dirty bits for VertexArrays use a hierarchical design. At the top level, each attribute @@ -151,23 +124,18 @@ class VertexArray final : public angle::ObserverInterface, // the Vulkan back-end to skip performing a pipeline change for performance. enum DirtyBitType { - // This vertex array has lost buffer observation. Check against actual buffer storage is - // required. - DIRTY_BIT_LOST_OBSERVATION, - - DIRTY_BIT_ELEMENT_ARRAY_BUFFER, - DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA, - // Dirty bits for bindings. DIRTY_BIT_BINDING_0, - DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + MAX_VERTEX_ATTRIB_BINDINGS, + DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + MAX_VERTEX_ATTRIB_BINDINGS, + DIRTY_BIT_ELEMENT_ARRAY_BUFFER = DIRTY_BIT_BINDING_MAX, // We keep separate dirty bits for bound buffers whose data changed since last update. - DIRTY_BIT_BUFFER_DATA_0 = DIRTY_BIT_BINDING_MAX, - DIRTY_BIT_BUFFER_DATA_MAX = DIRTY_BIT_BUFFER_DATA_0 + MAX_VERTEX_ATTRIB_BINDINGS, + DIRTY_BIT_BUFFER_DATA_0, + DIRTY_BIT_BUFFER_DATA_MAX = DIRTY_BIT_BUFFER_DATA_0 + MAX_VERTEX_ATTRIB_BINDINGS, + DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA = DIRTY_BIT_BUFFER_DATA_MAX, // Dirty bits for attributes. - DIRTY_BIT_ATTRIB_0 = DIRTY_BIT_BUFFER_DATA_MAX, + DIRTY_BIT_ATTRIB_0, DIRTY_BIT_ATTRIB_MAX = DIRTY_BIT_ATTRIB_0 + MAX_VERTEX_ATTRIBS, DIRTY_BIT_UNKNOWN = DIRTY_BIT_ATTRIB_MAX, @@ -183,8 +151,6 @@ class VertexArray final : public angle::ObserverInterface, "BINDING dirty bits should come before DATA."); static_assert(DIRTY_BIT_BUFFER_DATA_0 < DIRTY_BIT_ATTRIB_0, "DATA dirty bits should come before ATTRIB."); - static_assert(DIRTY_BIT_LOST_OBSERVATION < DIRTY_BIT_BINDING_0, - "LOST_OBSERVATION dirty bits should come before BINDING."); enum DirtyAttribBitType { @@ -202,6 +168,7 @@ class VertexArray final : public angle::ObserverInterface, DIRTY_BINDING_DIVISOR, DIRTY_BINDING_STRIDE, DIRTY_BINDING_OFFSET, + DIRTY_BINDING_SIZE, DIRTY_BINDING_MAX, }; @@ -210,19 +177,15 @@ class VertexArray final : public angle::ObserverInterface, using DirtyBindingBits = angle::BitSet; using DirtyAttribBitsArray = std::array; using DirtyBindingBitsArray = std::array; - using DirtyObserverBindingBits = angle::BitSet; - - VertexArray(rx::GLImplFactory *factory, - VertexArrayID id, - size_t maxAttribs, - size_t maxAttribBindings); - void onDestroy(const Context *context); + VertexArrayPrivate(rx::GLImplFactory *factory, + VertexArrayID id, + size_t maxAttribs, + size_t maxAttribBindings); VertexArrayID id() const { return mId; } - angle::Result setLabel(const Context *context, const std::string &label) override; - const std::string &getLabel() const override; + void enableAttribute(size_t attribIndex, bool enabledState); const VertexBinding &getVertexBinding(size_t bindingIndex) const; const VertexAttribute &getVertexAttribute(size_t attribIndex) const; @@ -231,44 +194,8 @@ class VertexArray final : public angle::ObserverInterface, return mState.getBindingFromAttribIndex(attribIndex); } - // Returns true if the function finds and detaches a bound buffer. - bool detachBuffer(const Context *context, BufferID bufferID); - - void setVertexAttribDivisor(const Context *context, size_t index, GLuint divisor); - void enableAttribute(size_t attribIndex, bool enabledState); - - void setVertexAttribPointer(const Context *context, - size_t attribIndex, - Buffer *boundBuffer, - GLint size, - VertexAttribType type, - bool normalized, - GLsizei stride, - const void *pointer); - - void setVertexAttribIPointer(const Context *context, - size_t attribIndex, - Buffer *boundBuffer, - GLint size, - VertexAttribType type, - GLsizei stride, - const void *pointer); - - void setVertexAttribFormat(size_t attribIndex, - GLint size, - VertexAttribType type, - bool normalized, - bool pureInteger, - GLuint relativeOffset); - void bindVertexBuffer(const Context *context, - size_t bindingIndex, - Buffer *boundBuffer, - GLintptr offset, - GLsizei stride); - void setVertexAttribBinding(const Context *context, size_t attribIndex, GLuint bindingIndex); - void setVertexBindingDivisor(const Context *context, size_t bindingIndex, GLuint divisor); + void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor); - Buffer *getElementArrayBuffer() const { return mState.getElementArrayBuffer(); } size_t getMaxAttribs() const { return mState.getMaxAttribs(); } size_t getMaxBindings() const { return mState.getMaxBindings(); } @@ -281,8 +208,6 @@ class VertexArray final : public angle::ObserverInterface, return mState.getVertexBindings(); } - rx::VertexArrayImpl *getImplementation() const { return mVertexArray; } - const AttributesMask &getEnabledAttributesMask() const { return mState.getEnabledAttributesMask(); @@ -295,52 +220,44 @@ class VertexArray final : public angle::ObserverInterface, return mState.hasEnabledNullPointerClientArray(); } - bool hasInvalidMappedArrayBuffer() const - { - return mState.mCachedInvalidMappedArrayBuffer.any(); - } + bool hasInvalidMappedArrayBuffer() const { return mCachedInvalidMappedArrayBuffer.any(); } const VertexArrayState &getState() const { return mState; } - bool isBufferAccessValidationEnabled() const { return mBufferAccessValidationEnabled; } + bool isRobustBufferAccessEnabled() const { return mRobustBufferAccessEnabled; } - // Observer implementation - void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; - void onBufferContentsChange(uint32_t bufferIndex); - - static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit); - - angle::Result syncState(const Context *context); bool hasAnyDirtyBit() const { return mDirtyBits.any(); } ComponentTypeMask getAttributesTypeMask() const { return mState.mVertexAttributesTypeMask; } AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; } - void onBindingChanged(const Context *context, int incr); bool hasTransformFeedbackBindingConflict(const Context *context) const; - ANGLE_INLINE angle::Result getIndexRange(const Context *context, - DrawElementsType type, - GLsizei indexCount, - const void *indices, - IndexRange *indexRangeOut) const + void setRobustBufferAccessEnabled(bool enabled) { - Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get(); - if (elementArrayBuffer && mIndexRangeCache.get(type, indexCount, indices, indexRangeOut)) + mRobustBufferAccessEnabled = enabled; + if (mRobustBufferAccessEnabled) { - return angle::Result::Continue; + mCachedBufferSize.resize(mState.getMaxBindings(), 0); } - - return getIndexRangeImpl(context, type, indexCount, indices, indexRangeOut); } - void setBufferAccessValidationEnabled(bool enabled) + size_t getBindingIndexFromAttribIndex(size_t attribIndex) const { - mBufferAccessValidationEnabled = enabled; + return mState.getBindingIndexFromAttribIndex(attribIndex); } - private: - ~VertexArray() override; + void setVertexAttribBinding(size_t attribIndex, GLuint bindingIndex); + void setVertexAttribDivisor(size_t index, GLuint divisor); + void setVertexAttribFormat(size_t attribIndex, + GLint size, + VertexAttribType type, + bool normalized, + bool pureInteger, + GLuint relativeOffset); + + protected: + ~VertexArrayPrivate(); // This is a performance optimization for buffer binding. Allows element array buffer updates. friend class State; @@ -349,34 +266,12 @@ class VertexArray final : public angle::ObserverInterface, void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit); void clearDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit); - DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const; - void setDependentDirtyBit(bool contentsChanged, angle::SubjectIndex index); - // These are used to optimize draw call validation. - void updateCachedBufferBindingSize(VertexBinding *binding); - void updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, const Buffer *buffer); + void updateCachedElementLimit(const VertexBinding &binding, GLint64 bufferSize); void updateCachedArrayBuffersMasks(bool isMapped, bool isImmutable, bool isPersistent, const AttributesMask &boundAttributesMask); - void updateCachedMappedArrayBuffersBinding(const VertexBinding &binding); - - angle::Result getIndexRangeImpl(const Context *context, - DrawElementsType type, - GLsizei indexCount, - const void *indices, - IndexRange *indexRangeOut) const; - - void setVertexAttribPointerImpl(const Context *context, - ComponentType componentType, - bool pureInteger, - size_t attribIndex, - Buffer *boundBuffer, - GLint size, - VertexAttribType type, - bool normalized, - GLsizei stride, - const void *pointer); // These two functions return true if the state was dirty. bool setVertexAttribFormatImpl(VertexAttribute *attrib, @@ -386,15 +281,6 @@ class VertexArray final : public angle::ObserverInterface, bool pureInteger, GLuint relativeOffset); - DirtyBindingBits bindVertexBufferImpl(const Context *context, - size_t bindingIndex, - Buffer *boundBuffer, - GLintptr offset, - GLsizei stride); - - void onBind(const Context *context); - void onUnbind(const Context *context); - VertexArrayID mId; VertexArrayState mState; @@ -403,51 +289,174 @@ class VertexArray final : public angle::ObserverInterface, DirtyBindingBitsArray mDirtyBindingBits; Optional mDirtyBitsGuard; - rx::VertexArrayImpl *mVertexArray; + mutable IndexRangeInlineCache mIndexRangeInlineCache; + bool mRobustBufferAccessEnabled; + + // Cached buffer size indexed by bindingIndex, only used when mRobustBufferAccessEnabled is + // true. + std::vector mCachedBufferSize; + // Cached XFB property indexed by bindingIndex, only used for webGL + VertexArrayBufferBindingMask mCachedBufferPropertyTransformFeedbackConflict; + + // Cached buffer properties indexed by bindingIndex + VertexArrayBufferBindingMask mBufferBindingMask; + VertexArrayBufferBindingMask mCachedBufferPropertyMapped; + VertexArrayBufferBindingMask mCachedBufferPropertyMutableOrImpersistent; + + // Used for validation cache. Indexed by attribute. + AttributesMask mCachedMappedArrayBuffers; + AttributesMask mCachedMutableOrImpersistentArrayBuffers; + AttributesMask mCachedInvalidMappedArrayBuffer; +}; + +using VertexArrayBuffers = std::array, kElementArrayBufferIndex + 1>; + +class VertexArray final : public VertexArrayPrivate, public LabeledObject, public angle::Subject +{ + public: + VertexArray(rx::GLImplFactory *factory, + VertexArrayID id, + size_t maxAttribs, + size_t maxAttribBindings); + + void onDestroy(const Context *context); + + angle::Result setLabel(const Context *context, const std::string &label) override; + const std::string &getLabel() const override; + + // Returns true if the function finds and detaches a bound buffer. + bool detachBuffer(const Context *context, BufferID bufferID); + + void setVertexAttribPointer(const Context *context, + size_t attribIndex, + Buffer *boundBuffer, + GLint size, + VertexAttribType type, + bool normalized, + GLsizei stride, + const void *pointer, + bool *isVertexAttribDirtyOut); - std::vector mArrayBufferObserverBindings; + void setVertexAttribIPointer(const Context *context, + size_t attribIndex, + Buffer *boundBuffer, + GLint size, + VertexAttribType type, + GLsizei stride, + const void *pointer, + bool *isVertexAttribDirtyOut); - AttributesMask mCachedTransformFeedbackConflictedBindingsMask; + void bindElementBuffer(const Context *context, Buffer *boundBuffer); - class IndexRangeCache final : angle::NonCopyable + void bindVertexBuffer(const Context *context, + size_t bindingIndex, + Buffer *boundBuffer, + GLintptr offset, + GLsizei stride); + + Buffer *getElementArrayBuffer() const + { + return mVertexArrayBuffers[kElementArrayBufferIndex].get(); + } + Buffer *getVertexArrayBuffer(size_t bindingIndex) const { - public: - IndexRangeCache(); + return mVertexArrayBuffers[bindingIndex].get(); + } - void invalidate() { mTypeKey = DrawElementsType::InvalidEnum; } + rx::VertexArrayImpl *getImplementation() const { return mVertexArray; } - bool get(DrawElementsType type, - GLsizei indexCount, - const void *indices, - IndexRange *indexRangeOut) - { - size_t offset = reinterpret_cast(indices); - if (mTypeKey == type && mIndexCountKey == indexCount && mOffsetKey == offset) - { - *indexRangeOut = mPayload; - return true; - } - - return false; - } + const BufferID getVertexArrayBufferID(size_t bindingIndex) const + { + return mVertexArrayBuffers[bindingIndex].id(); + } - void put(DrawElementsType type, - GLsizei indexCount, - size_t offset, - const IndexRange &indexRange); + angle::Result syncState(const Context *context); - private: - DrawElementsType mTypeKey; - GLsizei mIndexCountKey; - size_t mOffsetKey; - IndexRange mPayload; - }; + void onBindingChanged(const Context *context, int incr); + void onRebind(const Context *context) { onBind(context); } - mutable IndexRangeCache mIndexRangeCache; - bool mBufferAccessValidationEnabled; - VertexArrayBufferContentsObservers mContentsObservers; + angle::Result getIndexRange(const Context *context, + DrawElementsType type, + GLsizei indexCount, + const void *indices, + bool primitiveRestartEnabled, + IndexRange *indexRangeOut) const; + + void onBufferChanged(const Context *context, + const Buffer *buffer, + angle::SubjectMessage message, + VertexArrayBufferBindingMask bufferBindingMask); + + // A buffer attached to this vertex array is being bound. It might have been modified by other + // context. + void onSharedBufferBind(const Context *context, + const Buffer *buffer, + VertexArrayBufferBindingMask bufferBindingMask); + + const VertexArrayBuffers &getBufferBindingPointers() const { return mVertexArrayBuffers; } + + private: + ~VertexArray() override; + + void setVertexAttribPointerImpl(const Context *context, + ComponentType componentType, + bool pureInteger, + size_t attribIndex, + Buffer *boundBuffer, + GLint size, + VertexAttribType type, + bool normalized, + GLsizei stride, + const void *pointer, + bool *isVertexAttribDirtyOut); + + DirtyBindingBits bindVertexBufferImpl(const Context *context, + size_t bindingIndex, + Buffer *boundBuffer, + GLintptr offset, + GLsizei stride); + + void onBind(const Context *context); + void onUnbind(const Context *context); + + void setDependentDirtyBits(bool contentsChanged, + VertexArrayBufferBindingMask bufferBindingMask); + void updateCachedMappedArrayBuffersBinding(size_t bindingIndex); + bool bufferMaskBitsPointToTheSameBuffer(VertexArrayBufferBindingMask bufferBindingMask) const; + + // Update the cached buffer size and set the dirty binding bit for later if size has changed. + void updateBindingSizeIfChanged(const size_t bindingIndex, const GLint64 bufferSize); + + VertexArrayBuffers mVertexArrayBuffers; + rx::VertexArrayImpl *mVertexArray; }; +inline angle::Result VertexArray::getIndexRange(const Context *context, + DrawElementsType type, + GLsizei indexCount, + const void *indices, + bool primitiveRestartEnabled, + IndexRange *indexRangeOut) const +{ + Buffer *elementArrayBuffer = getElementArrayBuffer(); + if (!elementArrayBuffer) + { + *indexRangeOut = ComputeIndexRange(type, indices, indexCount, primitiveRestartEnabled); + return angle::Result::Continue; + } + size_t offset = reinterpret_cast(indices); + size_t count = static_cast(indexCount); + if (mIndexRangeInlineCache.get(type, offset, count, primitiveRestartEnabled, indexRangeOut)) + { + return angle::Result::Continue; + } + ANGLE_TRY(elementArrayBuffer->getIndexRange(context, type, offset, count, + primitiveRestartEnabled, indexRangeOut)); + mIndexRangeInlineCache = + IndexRangeInlineCache{type, offset, count, primitiveRestartEnabled, *indexRangeOut}; + return angle::Result::Continue; +} + } // namespace gl #endif // LIBANGLE_VERTEXARRAY_H_ diff --git a/src/libANGLE/VertexArray_unittest.cpp b/src/libANGLE/VertexArray_unittest.cpp index f8c254e45b9..7af6da75d1c 100644 --- a/src/libANGLE/VertexArray_unittest.cpp +++ b/src/libANGLE/VertexArray_unittest.cpp @@ -15,37 +15,3 @@ using namespace gl; -// Tests that function GetIndexFromDirtyBit computes the index properly. -TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit) -{ - VertexArray::DirtyBits dirtyBits; - constexpr size_t bits[] = {2, 4, 9, 16, 25, 35}; - constexpr GLint count = sizeof(bits) / sizeof(size_t); - for (GLint i = 0; i < count; i++) - { - dirtyBits.set(bits[i]); - } - - for (size_t dirtyBit : dirtyBits) - { - const size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); - if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_0) - { - continue; - } - else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0, index); - } - else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0, index); - } - else if (dirtyBit < VertexArray::DIRTY_BIT_BUFFER_DATA_MAX) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BUFFER_DATA_0, index); - } - else - ASSERT_TRUE(false); - } -} diff --git a/src/libANGLE/VertexAttribute.cpp b/src/libANGLE/VertexAttribute.cpp index 0bc2abfa288..bd1b69254da 100644 --- a/src/libANGLE/VertexAttribute.cpp +++ b/src/libANGLE/VertexAttribute.cpp @@ -35,17 +35,10 @@ VertexBinding &VertexBinding::operator=(VertexBinding &&binding) mDivisor = binding.mDivisor; mOffset = binding.mOffset; mBoundAttributesMask = binding.mBoundAttributesMask; - std::swap(binding.mBuffer, mBuffer); } return *this; } -void VertexBinding::onContainerBindingChanged(const Context *context, int incr) const -{ - if (mBuffer.get()) - mBuffer->onNonTFBindingChanged(incr); -} - VertexAttribute::VertexAttribute(GLuint bindingIndex) : enabled(false), format(&angle::Format::Get(angle::FormatID::R32G32B32A32_FLOAT)), @@ -81,17 +74,16 @@ VertexAttribute &VertexAttribute::operator=(VertexAttribute &&attrib) return *this; } -void VertexAttribute::updateCachedElementLimit(const VertexBinding &binding) +void VertexAttribute::updateCachedElementLimit(const VertexBinding &binding, GLint64 bufferSize) { - Buffer *buffer = binding.getBuffer().get(); - if (!buffer) + if (bufferSize == 0) { mCachedElementLimit = 0; return; } angle::CheckedNumeric bufferOffset(binding.getOffset()); - angle::CheckedNumeric bufferSize(buffer->getSize()); + angle::CheckedNumeric checkedBufferSize(bufferSize); angle::CheckedNumeric attribOffset(relativeOffset); angle::CheckedNumeric attribSize(ComputeVertexAttributeTypeSize(*this)); @@ -107,7 +99,7 @@ void VertexAttribute::updateCachedElementLimit(const VertexBinding &binding) // N attributes can be accessed, the following calculates N. // // (buffer.size - buffer.offset - attrib.relativeOffset - attrib.size) / binding.stride + 1 - angle::CheckedNumeric elementLimit = (bufferSize - offset - attribSize); + angle::CheckedNumeric elementLimit = (checkedBufferSize - offset - attribSize); // Use the special integer overflow value if there was a math error. if (!elementLimit.IsValid()) diff --git a/src/libANGLE/VertexAttribute.h b/src/libANGLE/VertexAttribute.h index fdf9432d92c..40f2bb287b0 100644 --- a/src/libANGLE/VertexAttribute.h +++ b/src/libANGLE/VertexAttribute.h @@ -19,7 +19,8 @@ class VertexArray; // // Implementation of Generic Vertex Attribute Bindings for ES3.1. The members are intentionally made -// private in order to hide implementation details. +// private in order to hide implementation details. Shared object like gl::Buffer should not be +// stored here since this data structure will be accessed without shared context lock. // class VertexBinding final : angle::NonCopyable { @@ -39,18 +40,6 @@ class VertexBinding final : angle::NonCopyable GLintptr getOffset() const { return mOffset; } void setOffset(GLintptr offsetIn) { mOffset = offsetIn; } - const BindingPointer &getBuffer() const { return mBuffer; } - - ANGLE_INLINE void setBuffer(const gl::Context *context, Buffer *bufferIn) - { - mBuffer.set(context, bufferIn); - } - - // Skips ref counting for better inlined performance. - ANGLE_INLINE void assignBuffer(Buffer *bufferIn) { mBuffer.assign(bufferIn); } - - void onContainerBindingChanged(const Context *context, int incr) const; - const AttributesMask &getBoundAttributesMask() const { return mBoundAttributesMask; } void setBoundAttribute(size_t index) { mBoundAttributesMask.set(index); } @@ -62,8 +51,6 @@ class VertexBinding final : angle::NonCopyable GLuint mDivisor; GLintptr mOffset; - BindingPointer mBuffer; - // Mapping from this binding to all of the attributes that are using this binding. AttributesMask mBoundAttributesMask; }; @@ -78,7 +65,7 @@ struct VertexAttribute final : private angle::NonCopyable VertexAttribute &operator=(VertexAttribute &&attrib); // Called from VertexArray. - void updateCachedElementLimit(const VertexBinding &binding); + void updateCachedElementLimit(const VertexBinding &binding, GLint64 bufferSize); GLint64 getCachedElementLimit() const { return mCachedElementLimit; } bool enabled; // For glEnable/DisableVertexAttribArray diff --git a/src/libANGLE/VertexAttribute.inc b/src/libANGLE/VertexAttribute.inc index 0c98f091b9c..9d0c7a4319c 100644 --- a/src/libANGLE/VertexAttribute.inc +++ b/src/libANGLE/VertexAttribute.inc @@ -6,6 +6,10 @@ // VertexAttribute.inc: Inline vertex attribute methods // +#ifdef UNSAFE_BUFFERS_BUILD +#pragma allow_unsafe_buffers +#endif + namespace gl { diff --git a/src/libANGLE/angletypes.cpp b/src/libANGLE/angletypes.cpp index 21cc33ef1ed..2aef1dd3b43 100644 --- a/src/libANGLE/angletypes.cpp +++ b/src/libANGLE/angletypes.cpp @@ -4,7 +4,12 @@ // found in the LICENSE file. // -// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 +// angletypes.cpp : Defines a variety of structures and enum types that are used throughout +// libGLESv2 + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/angletypes.h" #include "libANGLE/Program.h" @@ -377,6 +382,94 @@ ImageUnit::ImageUnit(const ImageUnit &other) = default; ImageUnit::~ImageUnit() = default; +namespace +{ +// Conversion functions between indices in the SupportedSampleSet bitfield and actual sample count. +// The first bit stores the '0' sample count, bits 1 though N store each power-of-two sample count. +size_t SampleCountToBitfieldIndex(GLuint sampleCount) +{ + if (sampleCount == 0) + { + return 0; + } + + ASSERT(isPow2(sampleCount)); + return log2(sampleCount) + 1; +} + +GLuint BitfieldIndexToSampleCount(size_t bitfieldIndex) +{ + if (bitfieldIndex == 0) + { + return 0; + } + + return 1 << (bitfieldIndex - 1); +} +} // namespace + +void SupportedSampleSet::insert(GLuint sampleCount) +{ + mSupportedSamples.set(SampleCountToBitfieldIndex(sampleCount)); +} + +void SupportedSampleSet::clear() +{ + mSupportedSamples.reset(); +} + +GLuint SupportedSampleSet::getNearestSamples(GLuint requestedSamples) const +{ + if (requestedSamples == 0) + { + return 0; + } + + for (size_t sampleIndex : mSupportedSamples) + { + GLuint sampleCount = BitfieldIndexToSampleCount(sampleIndex); + if (sampleCount >= requestedSamples) + { + return sampleCount; + } + } + + return 0; +} + +GLuint SupportedSampleSet::getMaxSamples() const +{ + if (!mSupportedSamples.any()) + { + return 0; + } + + return BitfieldIndexToSampleCount(mSupportedSamples.last()); +} + +size_t SupportedSampleSet::size() const +{ + return mSupportedSamples.count(); +} + +std::vector SupportedSampleSet::sampleCounts() const +{ + std::vector sampleCounts; + sampleCounts.reserve(size()); + for (size_t sampleIndex : mSupportedSamples) + { + sampleCounts.push_back(BitfieldIndexToSampleCount(sampleIndex)); + } + return sampleCounts; +} + +SupportedSampleSet SupportedSampleSet::operator&(const SupportedSampleSet &other) const +{ + SupportedSampleSet result; + result.mSupportedSamples = mSupportedSamples & other.mSupportedSamples; + return result; +} + BlendStateExt::BlendStateExt(const size_t drawBufferCount) : mParameterMask(FactorStorage::GetMask(drawBufferCount)), mSrcColor(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)), @@ -995,10 +1088,10 @@ void Box::extend(const Box &other) depth = z1 - z0; } -bool ValidateComponentTypeMasks(unsigned long outputTypes, - unsigned long inputTypes, - unsigned long outputMask, - unsigned long inputMask) +bool ValidateComponentTypeMasks(uint64_t outputTypes, + uint64_t inputTypes, + uint64_t outputMask, + uint64_t inputMask) { static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS <= kMaxComponentTypeMaskIndex, "Output/input masks should fit into 16 bits - 1 bit per draw buffer. The " diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h index 2306a74e587..6e7bfc932d0 100644 --- a/src/libANGLE/angletypes.h +++ b/src/libANGLE/angletypes.h @@ -9,6 +9,10 @@ #ifndef LIBANGLE_ANGLETYPES_H_ #define LIBANGLE_ANGLETYPES_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/Color.h" #include "common/FixedVector.h" @@ -16,7 +20,7 @@ #include "common/PackedEnums.h" #include "common/bitset_utils.h" #include "common/hash_utils.h" -#include "common/vector_utils.h" +#include "common/span.h" #include "libANGLE/Constants.h" #include "libANGLE/Error.h" #include "libANGLE/RefCountObject.h" @@ -35,8 +39,9 @@ namespace angle template struct Extents { - Extents() : width(0), height(0), depth(0) {} - Extents(T width_, T height_, T depth_) : width(width_), height(height_), depth(depth_) {} + constexpr Extents() : width(0), height(0), depth(0) {} + constexpr Extents(T width_, T height_, T depth_) : width(width_), height(height_), depth(depth_) + {} Extents(const Extents &other) = default; Extents &operator=(const Extents &other) = default; @@ -108,6 +113,7 @@ enum class Command Invalidate, ReadPixels, TexImage, + GetMultisample, Other, }; @@ -116,6 +122,8 @@ enum CommandBlitBuffer CommandBlitBufferColor = 0x1, CommandBlitBufferDepth = 0x2, CommandBlitBufferStencil = 0x4, + + CommandBlitBufferDepthStencil = CommandBlitBufferDepth | CommandBlitBufferStencil, }; enum class InitState @@ -538,19 +546,73 @@ struct PixelPackState : PixelStoreStateBase bool reverseRowOrder = false; }; -// Used in VertexArray. -using VertexArrayBufferBindingMask = angle::BitSet; +struct SupportedSampleSet +{ + public: + // Set a sample count as being supported. Must be a power of 2 and no greater than + // IMPLEMENTATION_MAX_SAMPLES + void insert(GLuint sampleCount); + + // Reset supported sample counts. + void clear(); + + // Get the number of supported samples that is at least as many as requested. Returns 0 if + // there are no sample counts available + GLuint getNearestSamples(GLuint requestedSamples) const; + + // Get the maximum number of samples supported + GLuint getMaxSamples() const; + + // The number of supported sample counts + size_t size() const; + + // Generate a list of supported sample counts + std::vector sampleCounts() const; + + SupportedSampleSet operator&(const SupportedSampleSet &other) const; + + private: + // Bitfield of supported sample counts, each bit is represents the next power of 2. An extra bit + // is added for the '0' sample count. + static constexpr size_t kRequiredBitCount = + log2(static_cast(IMPLEMENTATION_MAX_SAMPLES)) + 1; + using SupportedSamplesBitSet = angle::BitSet; + SupportedSamplesBitSet mSupportedSamples; +}; + +// Used in VertexArray. For ease of tracking, we add vertex array element buffer to the end of +// vertex array buffer bindings. +constexpr uint32_t kElementArrayBufferIndex = MAX_VERTEX_ATTRIB_BINDINGS; +using VertexArrayBufferBindingMask = angle::BitSet; // Used in Program and VertexArray. using AttributesMask = angle::BitSet; +using BufferBindingMask = angle::BitSet; // Used in Program -using ProgramUniformBlockMask = angle::BitSet; +static_assert(IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS > + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS, + "maxCombinedShaderStorageBlocks must be greater than maxCombinedUniformBlocks"); +using ProgramBufferBlockMask = angle::BitSet; +using ProgramUniformBlockMask = ProgramBufferBlockMask; +using ProgramStorageBlockMask = ProgramBufferBlockMask; template using ProgramUniformBlockArray = std::array; template using UniformBufferBindingArray = std::array; +// Fine grained dirty type for buffers updates. +enum class BufferDirtyType +{ + Binding, + Offset, + Size, + + InvalidEnum, + EnumCount = InvalidEnum, +}; +using BufferDirtyTypeBitMask = angle::PackedEnumBitSet; + // Used in Framebuffer / Program using DrawBufferMask = angle::BitSet8; @@ -701,6 +763,8 @@ class BlendStateExt final ///////// Color Write Mask ///////// + constexpr static uint8_t kColorMaskRGBA = 0xf; + static constexpr size_t PackColorMask(const bool red, const bool green, const bool blue, @@ -992,10 +1056,10 @@ ANGLE_INLINE DrawBufferMask GetComponentTypeMaskDiff(ComponentTypeMask mask1, return DrawBufferMask(static_cast(diff | (diff >> gl::kMaxComponentTypeMaskIndex))); } -bool ValidateComponentTypeMasks(unsigned long outputTypes, - unsigned long inputTypes, - unsigned long outputMask, - unsigned long inputMask); +bool ValidateComponentTypeMasks(uint64_t outputTypes, + uint64_t inputTypes, + uint64_t outputMask, + uint64_t inputMask); // Helpers for performing WebGL 2.0 clear validation // Extracted component type has always one of these four values: @@ -1112,8 +1176,6 @@ using ActiveTextureTypeArray = ActiveTextureArray; using ImageUnitMask = angle::BitSet; -using SupportedSampleSet = std::set; - template using TransformFeedbackBuffersArray = std::array; @@ -1122,6 +1184,7 @@ using ClipDistanceEnableBits = angle::BitSet32 using QueryTypeMap = angle::PackedEnumMap; +using QueryTypeBitSet = angle::PackedEnumBitSet; constexpr size_t kBarrierVectorDefaultSize = 16; @@ -1274,6 +1337,7 @@ enum class NativeWindowSystem X11, Wayland, Gbm, + NullCompute, Other, }; @@ -1328,7 +1392,7 @@ struct hash // Simple routine to hash four ints. size_t operator()(const angle::BlobCacheKey &key) const { - return angle::ComputeGenericHash(key.data(), key.size()); + return angle::ComputeGenericHash(key); } }; } // namespace std @@ -1459,6 +1523,9 @@ class DestroyThenDelete template using UniqueObjectPointer = std::unique_ptr>; +using ShadingRateSet = PackedEnumBitSet; +using ShadingRateMap = PackedEnumMap; + } // namespace angle namespace gl @@ -1553,6 +1620,14 @@ class FoveationState std::array mFocalPoints; }; +enum class BufferStorage : bool +{ + // The buffer storage is mutable + Mutable, + // The buffer storage is immutable + Immutable, +}; + } // namespace gl #endif // LIBANGLE_ANGLETYPES_H_ diff --git a/src/libANGLE/angletypes.inc b/src/libANGLE/angletypes.inc index 862a3214a13..88dc8367870 100644 --- a/src/libANGLE/angletypes.inc +++ b/src/libANGLE/angletypes.inc @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +#pragma allow_unsafe_libc_calls +#endif + // angletypes.inc : Inline definitions of some functions from angletypes.h namespace gl diff --git a/src/libANGLE/capture/FrameCapture.cpp b/src/libANGLE/capture/FrameCapture.cpp index b5398a37130..0dc6318e7ed 100644 --- a/src/libANGLE/capture/FrameCapture.cpp +++ b/src/libANGLE/capture/FrameCapture.cpp @@ -7,6 +7,10 @@ // ANGLE Frame capture GL implementation. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/capture/FrameCapture.h" #include @@ -131,7 +135,6 @@ std::string GetCaptureTrigger() // Use the GetAndSet variant to improve future lookup times return GetAndSetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger); } - struct FmtGetSerializedContextStateFunction { FmtGetSerializedContextStateFunction(gl::ContextID contextIdIn, @@ -184,7 +187,7 @@ void WriteStringParamReplay(ReplayWriter &replayWriter, std::ostream &header, const CallCapture &call, const ParamCapture ¶m, - std::vector *binaryData) + FrameCaptureBinaryData *binaryData) { const std::vector &data = param.data[0]; // null terminate C style string @@ -196,10 +199,8 @@ void WriteStringParamReplay(ReplayWriter &replayWriter, { // Store in binary file if the string is too long. // Round up to 16-byte boundary for cross ABI safety. - size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment); - binaryData->resize(offset + str.size() + 1); - memcpy(binaryData->data() + offset, str.data(), str.size() + 1); - out << "(const char *)&gBinaryData[" << offset << "]"; + const size_t offset = binaryData->append(str.data(), str.size() + 1); + out << "(const char *)GetBinaryData(" << offset << ")"; } else if (str.find('\n') != std::string::npos) { @@ -272,7 +273,7 @@ void WriteCppReplayForCall(const CallCapture &call, ReplayWriter &replayWriter, std::ostream &out, std::ostream &header, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, size_t *maxResourceIDBufferSize) { if (call.customFunctionName == "Comment") @@ -443,7 +444,7 @@ void WriteInitReplayCall(bool compression, const char *name = GetResourceIDTypeName(resourceID); out << " // max" << name << " = " << maxIDs[resourceID] << "\n"; } - out << " InitializeReplay4(\"" << binaryDataFileName << "\", " << maxClientArraySize << ", " + out << " InitializeReplay5(\"" << binaryDataFileName << "\", " << maxClientArraySize << ", " << readBufferSize << ", " << resourceIDBufferSize << ", " << contextID; for (ResourceIDType resourceID : AllEnums()) @@ -454,6 +455,8 @@ void WriteInitReplayCall(bool compression, } out << ");\n"; + // Load binary data + out << " InitializeBinaryDataLoader();\n"; } void DeleteResourcesInReset(std::stringstream &out, @@ -495,7 +498,7 @@ void MaybeResetResources(egl::Display *display, std::stringstream &out, std::stringstream &header, ResourceTracker *resourceTracker, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, bool &anyResourceReset, size_t *maxResourceIDBufferSize) { @@ -942,7 +945,7 @@ void MaybeResetFenceSyncObjects(std::stringstream &out, ReplayWriter &replayWriter, std::stringstream &header, ResourceTracker *resourceTracker, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, size_t *maxResourceIDBufferSize) { FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls(); @@ -967,6 +970,14 @@ void Capture(std::vector *setupCalls, CallCapture &&call) setupCalls->emplace_back(std::move(call)); } +void CaptureUpdateCurrentContext(gl::ContextID contextID, std::vector *callsOut) +{ + ParamBuffer paramBuffer; + paramBuffer.addValueParam("context", ParamType::TGLuint, contextID.value); + + callsOut->emplace_back("UpdateCurrentContext", std::move(paramBuffer)); +} + void CaptureUpdateCurrentProgram(const CallCapture &call, int programParamPos, std::vector *callsOut) @@ -978,7 +989,7 @@ void CaptureUpdateCurrentProgram(const CallCapture &call, ParamBuffer paramBuffer; paramBuffer.addValueParam("program", ParamType::TGLuint, programID.value); - callsOut->emplace_back("UpdateCurrentProgram", std::move(paramBuffer)); + callsOut->emplace_back("UpdateCurrentProgramPerContext", std::move(paramBuffer)); } bool ProgramNeedsReset(const gl::Context *context, @@ -1016,7 +1027,7 @@ void MaybeResetDefaultUniforms(std::stringstream &out, std::stringstream &header, const gl::Context *context, ResourceTracker *resourceTracker, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, size_t *maxResourceIDBufferSize) { DefaultUniformLocationsPerProgramMap &defaultUniformsToReset = @@ -1055,6 +1066,12 @@ void MaybeResetDefaultUniforms(std::stringstream &out, // Emit the reset calls per modified location for (const gl::UniformLocation &location : locations) { + // If location is equal to -1, the data passed in will be silently ignored and the + // specified uniform variable will not be changed + if (location.value == -1) + { + continue; + } gl::UniformLocation baseLocation = resourceTracker->getDefaultUniformBaseLocation(programID, location); if (alreadyReset.find(baseLocation) != alreadyReset.end()) @@ -1083,7 +1100,7 @@ void MaybeResetOpaqueTypeObjects(ReplayWriter &replayWriter, std::stringstream &header, const gl::Context *context, ResourceTracker *resourceTracker, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, size_t *maxResourceIDBufferSize) { MaybeResetFenceSyncObjects(out, replayWriter, header, resourceTracker, binaryData, @@ -1098,7 +1115,7 @@ void MaybeResetContextState(ReplayWriter &replayWriter, std::stringstream &header, ResourceTracker *resourceTracker, const gl::Context *context, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, StateResetHelper &stateResetHelper, size_t *maxResourceIDBufferSize) { @@ -1233,7 +1250,7 @@ void WriteCppReplayFunctionWithParts(const gl::ContextID contextID, ReplayFunc replayFunc, ReplayWriter &replayWriter, uint32_t frameIndex, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, const std::vector &calls, std::stringstream &header, std::stringstream &out, @@ -1308,7 +1325,7 @@ void WriteCppReplayFunctionWithPartsMultiContext(const gl::ContextID contextID, ReplayFunc replayFunc, ReplayWriter &replayWriter, uint32_t frameIndex, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, std::vector &calls, std::stringstream &header, std::stringstream &out, @@ -1343,6 +1360,13 @@ void WriteCppReplayFunctionWithPartsMultiContext(const gl::ContextID contextID, maxResourceIDBufferSize); out << ";\n"; callCount++; + std::vector updateCurrentContextCall; + CaptureUpdateCurrentContext(cID, &updateCurrentContextCall); + out << " "; + WriteCppReplayForCall(updateCurrentContextCall[0], replayWriter, out, header, binaryData, + maxResourceIDBufferSize); + out << ";\n"; + callCount++; }; // Helper lambda to write a call to the call stream @@ -1459,7 +1483,7 @@ void WriteAuxiliaryContextCppSetupReplay(ReplayWriter &replayWriter, const std::string &captureLabel, uint32_t frameIndex, const std::vector &setupCalls, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, bool serializeStateEnabled, const FrameCaptureShared &frameCaptureShared, size_t *maxResourceIDBufferSize) @@ -1511,7 +1535,7 @@ void WriteShareGroupCppSetupReplay(ReplayWriter &replayWriter, uint32_t frameCount, const std::vector &setupCalls, ResourceTracker *resourceTracker, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, bool serializeStateEnabled, gl::ContextID windowSurfaceContextID, size_t *maxResourceIDBufferSize) @@ -2674,6 +2698,7 @@ void CaptureVertexArrayState(std::vector *setupCalls, { const std::vector &vertexAttribs = vertexArray->getVertexAttributes(); const std::vector &vertexBindings = vertexArray->getVertexBindings(); + const gl::BufferManager &capturedBuffers = context->getState().getBufferManagerForCapture(); gl::AttributesMask vertexPointerBindings; @@ -2685,6 +2710,7 @@ void CaptureVertexArrayState(std::vector *setupCalls, const gl::VertexAttribute &attrib = vertexAttribs[attribIndex]; const gl::VertexBinding &binding = vertexBindings[attrib.bindingIndex]; + gl::Buffer *buffer = vertexArray->getVertexArrayBuffer(attrib.bindingIndex); if (attrib.enabled != defaultAttrib.enabled) { @@ -2701,28 +2727,29 @@ void CaptureVertexArrayState(std::vector *setupCalls, } } + gl::BufferID bufferID = {0}; + if (buffer) + { + bufferID = buffer->id(); + } + // Don't capture CaptureVertexAttribPointer calls when a non-default VAO is bound, the array // buffer is null and a non-null attrib pointer is used. - bool skipInvalidAttrib = vertexArray->id().value != 0 && - binding.getBuffer().get() == nullptr && attrib.pointer != nullptr; + bool skipInvalidAttrib = + vertexArray->id().value != 0 && + (buffer == nullptr || !capturedBuffers.isHandleGenerated(bufferID)) && + attrib.pointer != nullptr; if (!skipInvalidAttrib && (attrib.format != defaultAttrib.format || attrib.pointer != defaultAttrib.pointer || binding.getStride() != defaultBinding.getStride() || - attrib.bindingIndex != defaultAttrib.bindingIndex || - binding.getBuffer().get() != nullptr)) + attrib.bindingIndex != defaultAttrib.bindingIndex || buffer != nullptr)) { // Each attribute can pull from a separate buffer, so check the binding - gl::Buffer *buffer = binding.getBuffer().get(); if (buffer != replayState->getArrayBuffer()) { replayState->setBufferBinding(context, gl::BufferBinding::Array, buffer); - gl::BufferID bufferID = {0}; - if (buffer) - { - bufferID = buffer->id(); - } Capture(setupCalls, CaptureBindBuffer(*replayState, true, gl::BufferBinding::Array, bufferID)); } @@ -2799,13 +2826,13 @@ void CaptureVertexArrayState(std::vector *setupCalls, for (size_t bindingIndex : vertexPointerBindings.flip()) { const gl::VertexBinding &binding = vertexBindings[bindingIndex]; + gl::Buffer *buffer = vertexArray->getVertexArrayBuffer(bindingIndex); - if (binding.getBuffer().id().value != 0) + if (buffer) { - Capture(setupCalls, - CaptureBindVertexBuffer(*replayState, true, static_cast(bindingIndex), - binding.getBuffer().id(), binding.getOffset(), - binding.getStride())); + Capture(setupCalls, CaptureBindVertexBuffer( + *replayState, true, static_cast(bindingIndex), + buffer->id(), binding.getOffset(), binding.getStride())); } if (binding.getDivisor() != 0) @@ -3026,7 +3053,6 @@ void CaptureCustomFenceSync(CallCapture &call, std::vector &callsOu params.addValueParam("fenceSync", ParamType::TGLuint64, params.getReturnValue().value.GLuint64Val); call.customFunctionName = "FenceSync2"; - call.isSyncPoint = true; callsOut.emplace_back(std::move(call)); } @@ -3227,7 +3253,8 @@ void GenerateLinkedProgram(const gl::Context *context, uniformBlockIndex < static_cast(executable.getUniformBlocks().size()); uniformBlockIndex++) { - GLuint blockBinding = executable.getUniformBlocks()[uniformBlockIndex].pod.inShaderBinding; + // Ensure that runtime API bindings are picked up + GLuint blockBinding = executable.getUniformBlockBinding(uniformBlockIndex); CallCapture updateCallCapture = CaptureUniformBlockBinding(replayState, true, id, {uniformBlockIndex}, blockBinding); CaptureCustomUniformBlockBinding(updateCallCapture, *setupCalls); @@ -3543,6 +3570,42 @@ void CompressPalettedTexture(angle::MemoryBuffer &data, ); } +bool BlendStateEqualPerDrawBuffer(const gl::State ¤tState) +{ + const gl::BlendStateExt ¤tBlend = currentState.getBlendStateExt(); + + // For each buffer, compare again the zero buffer state + for (unsigned int idx = 1; idx < currentBlend.getDrawBufferCount(); idx++) + { + if (currentBlend.getEnabledMask().test(0) != currentBlend.getEnabledMask().test(idx)) + { + return false; + } + + if (currentBlend.getSrcColorIndexed(0) != currentBlend.getSrcColorIndexed(idx) || + currentBlend.getDstColorIndexed(0) != currentBlend.getDstColorIndexed(idx) || + currentBlend.getSrcAlphaIndexed(0) != currentBlend.getSrcAlphaIndexed(idx) || + currentBlend.getDstAlphaIndexed(0) != currentBlend.getDstAlphaIndexed(idx)) + { + return false; + } + + if (currentBlend.getEquationColorIndexed(0) != currentBlend.getEquationColorIndexed(idx) || + currentBlend.getEquationAlphaIndexed(0) != currentBlend.getEquationAlphaIndexed(idx)) + { + return false; + } + + if (currentBlend.getColorMaskIndexed(0) != currentBlend.getColorMaskIndexed(idx)) + { + return false; + } + } + + // If we reach here, all buffer blend states match the zero buffer + return true; +} + // Capture the setup of the state that's shared by all of the contexts in the share group // See IsSharedObjectResource for the list of objects covered here. void CaptureShareGroupMidExecutionSetup( @@ -3635,7 +3698,8 @@ void CaptureShareGroupMidExecutionSetup( static_cast(buffer->getMapOffset()), static_cast(buffer->getMapLength()), (buffer->getAccessFlags() & GL_MAP_WRITE_BIT) != 0, - (buffer->getStorageExtUsageFlags() & GL_MAP_COHERENT_BIT_EXT) != 0); + (buffer->getStorageExtUsageFlags() & GL_MAP_COHERENT_BIT_EXT) != 0, + (buffer->getStorageExtUsageFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0); } else { @@ -3707,7 +3771,7 @@ void CaptureShareGroupMidExecutionSetup( gl::TextureID id = {textureIter.first}; gl::Texture *texture = textureIter.second; - if (id.value == 0) + if (id.value == 0 || texture == nullptr) { continue; } @@ -3809,6 +3873,15 @@ void CaptureShareGroupMidExecutionSetup( } }; + auto capTexParams = [&replayState, texture, &texSetupCalls](GLenum pname, + const GLint *params) { + for (std::vector *calls : texSetupCalls) + { + Capture(calls, CaptureTexParameteriv(replayState, true, texture->getType(), pname, + params)); + } + }; + if (textureSamplerState.getMinFilter() != defaultSamplerState.getMinFilter()) { capTexParam(GL_TEXTURE_MIN_FILTER, textureSamplerState.getMinFilter()); @@ -3885,6 +3958,13 @@ void CaptureShareGroupMidExecutionSetup( capTexParam(GL_TEXTURE_MAX_LEVEL, texture->getMaxLevel()); } + if (context->isGLES1() && texture->getCrop() != gl::Rectangle()) + { + const gl::Rectangle &crop = texture->getCrop(); + const GLint params[4]{crop.x, crop.y, crop.width, crop.height}; + capTexParams(GL_TEXTURE_CROP_RECT_OES, params); + } + // If the texture is immutable, initialize it with TexStorage if (texture->getImmutableFormat()) { @@ -4426,6 +4506,32 @@ void CaptureShareGroupMidExecutionSetup( } } +// Detects zombie bindings caused by texture ID reuse across shared contexts. +// Zombie bindings may exist at capture-time but should not be added as part +// of capture Setup(). See http://issuetracker.google.com/471189378. +bool IsZombieTextureBinding(const gl::State &state, + gl::TextureType type, + size_t unit, + gl::TextureID textureID) +{ + // Texture held by the context's specific hardware sampler slot + const gl::Texture *boundTexture = state.getSamplerTexture(static_cast(unit), type); + + if (boundTexture) + { + uint64_t boundSerial = boundTexture->serial().getValue(); + + // Texture from the current Resource Manager state + const gl::TextureManager &textureManager = state.getTextureManagerForCapture(); + const gl::Texture *currentTexture = textureManager.getTexture(textureID); + uint64_t currentSerial = currentTexture->serial().getValue(); + + // If the ANGLE unique object IDs differ this object has been deleted + return (boundSerial != currentSerial); + } + return false; +} + void CaptureMidExecutionSetup(const gl::Context *context, std::vector *setupCalls, StateResetHelper &resetHelper, @@ -4441,6 +4547,7 @@ void CaptureMidExecutionSetup(const gl::Context *context, auto cap = [setupCalls](CallCapture &&call) { setupCalls->emplace_back(std::move(call)); }; cap(egl::CaptureMakeCurrent(nullptr, true, nullptr, {0}, {0}, context->id(), EGL_TRUE)); + CaptureUpdateCurrentContext(context->id(), setupCalls); // Vertex input states. Must happen after buffer data initialization. Do not capture on GLES1. if (!context->isGLES1()) @@ -4515,6 +4622,12 @@ void CaptureMidExecutionSetup(const gl::Context *context, CallResetMap &resetCalls = resetHelper.getResetCalls(); Capture(&resetCalls[angle::EntryPoint::GLBindVertexArray], vertexArrayFuncs.bindVertexArray(replayState, true, currentVertexArray->id())); + gl::Buffer *elementArrayBuffer = currentVertexArray->getElementArrayBuffer(); + if (elementArrayBuffer) + { + resetHelper.setStartingBufferBinding(gl::BufferBinding::ElementArray, + currentVertexArray->getElementArrayBuffer()->id()); + } // Capture indexed buffer bindings. const gl::BufferVector &uniformIndexedBuffers = @@ -4585,6 +4698,13 @@ void CaptureMidExecutionSetup(const gl::Context *context, if (apiTextureID != replayTextureID) { + if (apiTextureID.value && + IsZombieTextureBinding(apiState, textureType, bindingIndex, apiTextureID)) + { + INFO() << "Skipping setup of partially deleted/unbound zombie texture."; + continue; + } + if (replayState.getActiveSampler() != bindingIndex) { cap(CaptureActiveTexture(replayState, true, @@ -4890,19 +5010,35 @@ void CaptureMidExecutionSetup(const gl::Context *context, gl::Query *query = queryIter->second; if (query) { - gl::QueryType queryType = query->getType(); - // Defer active queries until we've created them all if (IsQueryActive(apiState, queryID)) { continue; } - // Begin the query to generate the object - cap(CaptureBeginQuery(replayState, true, queryType, queryID)); + gl::QueryType queryType = query->getType(); + switch (queryType) + { + case gl::QueryType::AnySamples: + case gl::QueryType::AnySamplesConservative: + case gl::QueryType::PrimitivesGenerated: + case gl::QueryType::TransformFeedbackPrimitivesWritten: + case gl::QueryType::TimeElapsed: + // Begin the query to generate the object + cap(CaptureBeginQuery(replayState, true, queryType, queryID)); + // End the query since it is not active + cap(CaptureEndQuery(replayState, true, queryType)); + break; + + case gl::QueryType::Timestamp: + // Issue the query to create the object + cap(CaptureQueryCounterEXT(replayState, true, queryID, queryType)); + break; - // End the query if it was not active - cap(CaptureEndQuery(replayState, true, queryType)); + default: + UNREACHABLE(); + break; + } } } @@ -5262,70 +5398,151 @@ void CaptureMidExecutionSetup(const gl::Context *context, } // Blend state. - const gl::BlendState &defaultBlendState = replayState.getBlendState(); - const gl::BlendState ¤tBlendState = apiState.getBlendState(); - if (currentBlendState.blend != defaultBlendState.blend) + // First, check if every draw buffer blend state matches zero buffer. + // If so, we can set them all the same using calls available before ES 3.2 + if (BlendStateEqualPerDrawBuffer(apiState)) { - capCap(GL_BLEND, currentBlendState.blend); - } + const gl::BlendState &defaultBlendState = replayState.getBlendState(); + const gl::BlendState ¤tBlendState = apiState.getBlendState(); - if (currentBlendState.sourceBlendRGB != defaultBlendState.sourceBlendRGB || - currentBlendState.destBlendRGB != defaultBlendState.destBlendRGB || - currentBlendState.sourceBlendAlpha != defaultBlendState.sourceBlendAlpha || - currentBlendState.destBlendAlpha != defaultBlendState.destBlendAlpha) - { - if (context->isGLES1()) + if (currentBlendState.blend != defaultBlendState.blend) { - // Even though their states are tracked independently, in GLES1 blendAlpha - // and blendRGB cannot be set separately and are always equal - cap(CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB, - currentBlendState.destBlendRGB)); - Capture(&resetCalls[angle::EntryPoint::GLBlendFunc], - CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB, - currentBlendState.destBlendRGB)); + capCap(GL_BLEND, currentBlendState.blend); } - else + + if (currentBlendState.sourceBlendRGB != defaultBlendState.sourceBlendRGB || + currentBlendState.destBlendRGB != defaultBlendState.destBlendRGB || + currentBlendState.sourceBlendAlpha != defaultBlendState.sourceBlendAlpha || + currentBlendState.destBlendAlpha != defaultBlendState.destBlendAlpha) { - // Always use BlendFuncSeparate for non-GLES1 as it covers all cases - cap(CaptureBlendFuncSeparate( - replayState, true, currentBlendState.sourceBlendRGB, currentBlendState.destBlendRGB, - currentBlendState.sourceBlendAlpha, currentBlendState.destBlendAlpha)); - Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate], - CaptureBlendFuncSeparate(replayState, true, currentBlendState.sourceBlendRGB, + if (context->isGLES1()) + { + // Even though their states are tracked independently, in GLES1 blendAlpha + // and blendRGB cannot be set separately and are always equal + cap(CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB, + currentBlendState.destBlendRGB)); + Capture(&resetCalls[angle::EntryPoint::GLBlendFunc], + CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB, + currentBlendState.destBlendRGB)); + } + else + { + // Always use BlendFuncSeparate for non-GLES1 as it covers all cases + cap(CaptureBlendFuncSeparate(replayState, true, currentBlendState.sourceBlendRGB, currentBlendState.destBlendRGB, currentBlendState.sourceBlendAlpha, currentBlendState.destBlendAlpha)); + Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate], + CaptureBlendFuncSeparate( + replayState, true, currentBlendState.sourceBlendRGB, + currentBlendState.destBlendRGB, currentBlendState.sourceBlendAlpha, + currentBlendState.destBlendAlpha)); + } } - } - if (currentBlendState.blendEquationRGB != defaultBlendState.blendEquationRGB || - currentBlendState.blendEquationAlpha != defaultBlendState.blendEquationAlpha) - { - // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset. - cap(CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB, - currentBlendState.blendEquationAlpha)); - Capture(&resetCalls[angle::EntryPoint::GLBlendEquationSeparate], + if (currentBlendState.blendEquationRGB != defaultBlendState.blendEquationRGB || + currentBlendState.blendEquationAlpha != defaultBlendState.blendEquationAlpha) + { + // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset. + cap(CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB, + currentBlendState.blendEquationAlpha)); + Capture( + &resetCalls[angle::EntryPoint::GLBlendEquationSeparate], CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB, currentBlendState.blendEquationAlpha)); - } + } - if (currentBlendState.colorMaskRed != defaultBlendState.colorMaskRed || - currentBlendState.colorMaskGreen != defaultBlendState.colorMaskGreen || - currentBlendState.colorMaskBlue != defaultBlendState.colorMaskBlue || - currentBlendState.colorMaskAlpha != defaultBlendState.colorMaskAlpha) - { - cap(CaptureColorMask(replayState, true, - gl::ConvertToGLBoolean(currentBlendState.colorMaskRed), - gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen), - gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue), - gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha))); - Capture(&resetCalls[angle::EntryPoint::GLColorMask], - CaptureColorMask(replayState, true, + if (currentBlendState.colorMaskRed != defaultBlendState.colorMaskRed || + currentBlendState.colorMaskGreen != defaultBlendState.colorMaskGreen || + currentBlendState.colorMaskBlue != defaultBlendState.colorMaskBlue || + currentBlendState.colorMaskAlpha != defaultBlendState.colorMaskAlpha) + { + cap(CaptureColorMask(replayState, true, gl::ConvertToGLBoolean(currentBlendState.colorMaskRed), gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen), gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue), gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha))); + Capture(&resetCalls[angle::EntryPoint::GLColorMask], + CaptureColorMask(replayState, true, + gl::ConvertToGLBoolean(currentBlendState.colorMaskRed), + gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen), + gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue), + gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha))); + } + } + else + { + // Otherwise, we must use EXT_draw_buffers_indexed features to set them independently + const gl::BlendStateExt &defaultBlend = replayState.getBlendStateExt(); + const gl::BlendStateExt ¤tBlend = apiState.getBlendStateExt(); + + for (int idx = 0; idx < currentBlend.getDrawBufferCount(); idx++) + { + if (currentBlend.getEnabledMask().test(idx) != defaultBlend.getEnabledMask().test(idx)) + { + if (currentBlend.getEnabledMask().test(idx)) + { + cap(CaptureEnableiEXT(replayState, true, GL_BLEND, static_cast(idx))); + } + else + { + cap(CaptureDisableiEXT(replayState, true, GL_BLEND, static_cast(idx))); + } + } + + if (currentBlend.getSrcColorIndexed(idx) != defaultBlend.getSrcColorIndexed(idx) || + currentBlend.getDstColorIndexed(idx) != defaultBlend.getDstColorIndexed(idx) || + currentBlend.getSrcAlphaIndexed(idx) != defaultBlend.getSrcAlphaIndexed(idx) || + currentBlend.getDstAlphaIndexed(idx) != defaultBlend.getDstAlphaIndexed(idx)) + { + // Always use BlendFuncSeparate as it covers all cases + cap(CaptureBlendFuncSeparateiEXT(replayState, true, idx, + ToGLenum(currentBlend.getSrcColorIndexed(idx)), + ToGLenum(currentBlend.getDstColorIndexed(idx)), + ToGLenum(currentBlend.getSrcAlphaIndexed(idx)), + ToGLenum(currentBlend.getDstAlphaIndexed(idx)))); + Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate], + CaptureBlendFuncSeparateiEXT( + replayState, true, idx, ToGLenum(currentBlend.getSrcColorIndexed(idx)), + ToGLenum(currentBlend.getDstColorIndexed(idx)), + ToGLenum(currentBlend.getSrcAlphaIndexed(idx)), + ToGLenum(currentBlend.getDstAlphaIndexed(idx)))); + } + + if (currentBlend.getEquationColorIndexed(idx) != + defaultBlend.getEquationColorIndexed(idx) || + currentBlend.getEquationAlphaIndexed(idx) != + defaultBlend.getEquationAlphaIndexed(idx)) + { + // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset. + cap(CaptureBlendEquationSeparateiEXT( + replayState, true, idx, ToGLenum(currentBlend.getEquationColorIndexed(idx)), + ToGLenum(currentBlend.getEquationAlphaIndexed(idx)))); + Capture( + &resetCalls[angle::EntryPoint::GLBlendEquationSeparate], + CaptureBlendEquationSeparateiEXT( + replayState, true, idx, ToGLenum(currentBlend.getEquationColorIndexed(idx)), + ToGLenum(currentBlend.getEquationAlphaIndexed(idx)))); + } + + if (currentBlend.getColorMaskIndexed(idx) != defaultBlend.getColorMaskIndexed(idx)) + { + cap(CaptureColorMaskiEXT( + replayState, true, idx, + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 1), + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 2), + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 4), + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 8))); + Capture(&resetCalls[angle::EntryPoint::GLColorMask], + CaptureColorMaskiEXT( + replayState, true, idx, + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 1), + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 2), + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 4), + gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 8))); + } + } } const gl::ColorF ¤tBlendColor = apiState.getBlendColor(); @@ -5824,7 +6041,11 @@ void CoherentBuffer::removeProtection(PageSharingType sharingType) bool CoherentBufferTracker::canProtectDirectly(gl::Context *context) { - gl::BufferID bufferId = context->createBuffer(); + gl::BufferID bufferId; + if (!context->createBuffer(&bufferId)) + { + ERR() << "Failed to allocate buffer ID."; + } gl::BufferBinding targetPacked = gl::BufferBinding::Array; context->bindBuffer(targetPacked, bufferId); @@ -6199,7 +6420,8 @@ void FrameCaptureShared::trackBufferMapping(const gl::Context *context, GLintptr offset, GLsizeiptr length, bool writable, - bool coherent) + bool coherent, + bool persistent) { // Track that the buffer was mapped mResourceTracker.setBufferMapped(context->id(), id.value); @@ -6218,13 +6440,20 @@ void FrameCaptureShared::trackBufferMapping(const gl::Context *context, // Track coherent buffer // Check if capture is active to not initialize the coherent buffer tracker on the // first coherent glMapBufferRange call. - if (coherent && isCaptureActive()) + if ((coherent || persistent) && isCaptureActive()) { if (mCoherentBufferTracker.hasBeenReset()) { FATAL() << "Multi-capture not supprted for apps using persistent coherent memory"; } + // To allow for incomplete synchronization seen in popular apps, treat persistent + // writable memory as coherent. See http://issuetracker.google.com/460704266. + if (!coherent) + { + WARN() << "Treating persistent, non-coherent buffer " << id.value << " as coherent"; + } + mCoherentBufferTracker.enable(); // When not using shadow memory, adding buffers to the tracking happens here instead of // during mapping @@ -6412,6 +6641,7 @@ void FrameCaptureShared::updateCopyImageSubData(CallCapture &call) case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES: @@ -6444,6 +6674,7 @@ void FrameCaptureShared::updateCopyImageSubData(CallCapture &call) case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES: @@ -6537,7 +6768,8 @@ void FrameCaptureShared::captureCustomMapBufferFromContext(const gl::Context *co call.params.getParam("access", ParamType::TGLbitfield, 3).value.GLbitfieldVal; trackBufferMapping(context, &call, buffer->id(), buffer, offset, length, - access & GL_MAP_WRITE_BIT, access & GL_MAP_COHERENT_BIT_EXT); + access & GL_MAP_WRITE_BIT, access & GL_MAP_COHERENT_BIT_EXT, + access & GL_MAP_PERSISTENT_BIT_EXT); } else { @@ -6546,7 +6778,7 @@ void FrameCaptureShared::captureCustomMapBufferFromContext(const gl::Context *co bool writeAccess = (access == GL_WRITE_ONLY_OES || access == GL_WRITE_ONLY || access == GL_READ_WRITE); trackBufferMapping(context, &call, buffer->id(), buffer, 0, - static_cast(buffer->getSize()), writeAccess, false); + static_cast(buffer->getSize()), writeAccess, false, false); } CaptureCustomMapBuffer(entryPointName, call, callsOut, buffer->id()); @@ -6659,7 +6891,6 @@ void FrameCaptureShared::maybeOverrideEntryPoint(const gl::Context *context, CaptureCustomCreateNativeClientbuffer(inCall, outCalls); break; } - default: { // Pass the single call through @@ -6669,6 +6900,47 @@ void FrameCaptureShared::maybeOverrideEntryPoint(const gl::Context *context, } } +// Set flag if call is a syncpoint. Syncpoints are created in support of +// context call grouping in which calls from side-contexts are group together +// to minimize context transitions. Sidecontext calls are typically replayed +// first in a frame followed by calls in the main context. However, some calls +// affect global state and need to occur in their originally recorded +// position. An example of this would be if in a side-context a shader was +// deleted, but in the original trace the delete occurred in the middle of the +// frame. Replaying all of the side-context calls before the main context calls +// could result in a race condition for the shader's lifetime. +// If any of the entrypoints below occurs in a side context: +// - the side-context replay will be interrupted +// - the context will be switched to the main context to replay those calls +// - at the point in the call stream where the side-context call originally +// appeared is reached, the context will switch back to the side-context +// and those calls will be replayed until the side-context is complete or +// until another syncpoint is found. +// The intent is to ensure entrypoints that affect global state occur in their +// proper order. +void FrameCaptureShared::maybeSetSyncPoint(CallCapture &inCall) +{ + switch (inCall.entryPoint) + { + case EntryPoint::GLFenceSync: + case EntryPoint::GLCreateShader: + case EntryPoint::GLCreateProgram: + case EntryPoint::GLCreateShaderProgramv: + case EntryPoint::GLAttachShader: + case EntryPoint::GLDeleteShader: + case EntryPoint::GLDeleteProgram: + case EntryPoint::GLLinkProgram: + { + inCall.isSyncPoint = true; + break; + } + default: + { + break; + } + } +} + void FrameCaptureShared::maybeCaptureCoherentBuffers(const gl::Context *context) { if (!isCaptureActive()) @@ -6692,7 +6964,7 @@ void FrameCaptureShared::maybeCaptureDrawArraysClientData(const gl::Context *con CallCapture &call, size_t instanceCount) { - if (!context->getStateCache().hasAnyActiveClientAttrib()) + if (!context->hasAnyActiveClientAttrib()) { return; } @@ -6708,7 +6980,7 @@ void FrameCaptureShared::maybeCaptureDrawElementsClientData(const gl::Context *c CallCapture &call, size_t instanceCount) { - if (!context->getStateCache().hasAnyActiveClientAttrib()) + if (!context->hasAnyActiveClientAttrib()) { return; } @@ -6745,7 +7017,7 @@ void FrameCaptureShared::maybeCaptureDrawElementsClientData(const gl::Context *c } // index starts from 0 - captureClientArraySnapshot(context, indexRange.end + 1, instanceCount); + captureClientArraySnapshot(context, indexRange.end() + 1, instanceCount); } template @@ -7088,6 +7360,10 @@ void FrameCaptureShared::maybeCapturePreCallUpdates( // If we're capturing, track which programs have been deleted const ParamCapture ¶m = call.params.getParam("programPacked", ParamType::TShaderProgramID, 0); + if (param.value.ShaderProgramIDVal.value == 0) + { + break; // no-op + } handleDeletedResource(context, param.value.ShaderProgramIDVal); // If this assert fires, it means a ShaderProgramID has changed from program to shader @@ -7113,6 +7389,10 @@ void FrameCaptureShared::maybeCapturePreCallUpdates( // If we're capturing, track which shaders have been deleted const ParamCapture ¶m = call.params.getParam("shaderPacked", ParamType::TShaderProgramID, 0); + if (param.value.ShaderProgramIDVal.value == 0) + { + break; // no-op + } handleDeletedResource(context, param.value.ShaderProgramIDVal); // If this assert fires, it means a ShaderProgramID has changed from shader to program @@ -7195,7 +7475,7 @@ void FrameCaptureShared::maybeCapturePreCallUpdates( FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared(); frameCaptureShared->trackBufferMapping(context, &call, buffer->id(), buffer, offset, - length, writable, false); + length, writable, false, false); break; } @@ -7572,11 +7852,24 @@ void FrameCaptureShared::updateResourceCountsFromParamCapture(const ParamCapture { mHasResourceType.set(idType); + // Lambda to update the max accessed resource if ID was valid + auto updateMaxAccessedID = [&](GLuint id) -> void { + // We could check each ID using calls like isHandleGenerated or Context::isTexture, + // but let's keep it simple (and fast) for now. + constexpr unsigned int kMaxTrackedResourceID = 1000000; + if (id >= kMaxTrackedResourceID) + { + INFO() << "Not tracking potentially invalid resourceID (" << id << ") for idType " + << GetResourceIDTypeName(idType); + return; + } + mMaxAccessedResourceIDs[idType] = std::max(mMaxAccessedResourceIDs[idType], id); + }; + // Capture resource IDs for non-pointer types. if (strcmp(ParamTypeToString(param.type), "GLuint") == 0) { - mMaxAccessedResourceIDs[idType] = - std::max(mMaxAccessedResourceIDs[idType], param.value.GLuintVal); + updateMaxAccessedID(param.value.GLuintVal); } // Capture resource IDs for pointer types. if (strstr(ParamTypeToString(param.type), "GLuint *") != nullptr) @@ -7587,15 +7880,13 @@ void FrameCaptureShared::updateResourceCountsFromParamCapture(const ParamCapture size_t numHandles = param.data[0].size() / sizeof(GLuint); for (size_t handleIndex = 0; handleIndex < numHandles; ++handleIndex) { - mMaxAccessedResourceIDs[idType] = - std::max(mMaxAccessedResourceIDs[idType], dataPtr[handleIndex]); + updateMaxAccessedID(dataPtr[handleIndex]); } } } if (idType == ResourceIDType::Sync) { - mMaxAccessedResourceIDs[idType] = - std::max(mMaxAccessedResourceIDs[idType], param.value.GLuintVal); + updateMaxAccessedID(param.value.GLuintVal); } } } @@ -7651,6 +7942,7 @@ void FrameCaptureShared::captureCall(gl::Context *context, CallCapture &&inCall, size_t j = mFrameCalls.size(); + maybeSetSyncPoint(inCall); std::vector outCalls; maybeOverrideEntryPoint(context, inCall, outCalls); @@ -7761,6 +8053,10 @@ void FrameCaptureShared::maybeCapturePostCallUpdates(const gl::Context *context) { const ParamCapture ¶m = lastCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0); + if (param.value.ShaderProgramIDVal.value == 0) + { + break; // no-op + } CaptureDeleteUniformLocations(param.value.ShaderProgramIDVal, &mFrameCalls); break; } @@ -7849,7 +8145,7 @@ void FrameCaptureShared::captureClientArraySnapshot(const gl::Context *context, const gl::VertexArray *vao = context->getState().getVertexArray(); // Capture client array data. - for (size_t attribIndex : context->getStateCache().getActiveClientAttribsMask()) + for (size_t attribIndex : context->getActiveClientAttribsMask()) { const gl::VertexAttribute &attrib = vao->getVertexAttribute(attribIndex); const gl::VertexBinding &binding = vao->getVertexBinding(attrib.bindingIndex); @@ -8085,7 +8381,7 @@ void FrameCaptureShared::runMidExecutionCapture(gl::Context *mainContext) gl::State mainContextReplayState( nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, contextState.getClientVersion(), false, true, true, true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG, - contextState.hasRobustAccess(), contextState.hasProtectedContent(), false); + contextState.hasRobustAccess(), contextState.hasProtectedContent(), false, false); mainContextReplayState.initializeForCapture(mainContext); CaptureShareGroupMidExecutionSetup(mainContext, &mShareGroupSetupCalls, &mResourceTracker, @@ -8131,7 +8427,7 @@ void FrameCaptureShared::runMidExecutionCapture(gl::Context *mainContext) shareContextState.getClientVersion(), false, true, true, true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG, shareContextState.hasRobustAccess(), - shareContextState.hasProtectedContent(), false); + shareContextState.hasProtectedContent(), false, false); auxContextReplayState.initializeForCapture(shareContext.second); egl::Error error = shareContext.second->makeCurrent(display, draw, read); @@ -8168,6 +8464,10 @@ void FrameCaptureShared::onEndFrame(gl::Context *context) if (!enabled() || mFrameIndex > mCaptureEndFrame) { setCaptureInactive(); + + // Note: If this call were deferred until shutdown, multi-capture could be + // supported for traces using persistent/coherent mapped memory, see + // http://issuetracker.google.com/394107532 mCoherentBufferTracker.onEndFrame(); if (enabled()) { @@ -8198,14 +8498,14 @@ void FrameCaptureShared::onEndFrame(gl::Context *context) // On Android, we can trigger a capture during the run checkForCaptureTrigger(); + checkForCaptureEnd(); // Check for MEC. Done after checkForCaptureTrigger(), since that can modify mCaptureStartFrame. if (mFrameIndex < mCaptureStartFrame) { if (mFrameIndex == mCaptureStartFrame - 1) { - // Update output directory location - getOutputDirectory(); + initalizeTraceStorage(); // Trigger MEC. runMidExecutionCapture(context); } @@ -8214,6 +8514,12 @@ void FrameCaptureShared::onEndFrame(gl::Context *context) return; } + // If not MEC, initialize capture storage + if (mFrameIndex == 1 && mCaptureStartFrame == 1) + { + initalizeTraceStorage(); + } + ASSERT(isCaptureActive()); if (!mFrameCalls.empty()) @@ -8245,8 +8551,7 @@ void FrameCaptureShared::onEndFrame(gl::Context *context) // Save the index files after the last frame. writeCppReplayIndexFiles(context, false); - SaveBinaryData(mCompression, mOutDirectory, kSharedContextId, mCaptureLabel, mBinaryData); - mBinaryData.clear(); + mWroteIndexFile = true; INFO() << "Finished recording graphics API capture"; } @@ -8269,13 +8574,15 @@ void FrameCaptureShared::onDestroyContext(const gl::Context *context) mFrameIndex -= 1; mCaptureEndFrame = mFrameIndex; writeCppReplayIndexFiles(context, true); - SaveBinaryData(mCompression, mOutDirectory, kSharedContextId, mCaptureLabel, mBinaryData); - mBinaryData.clear(); + mWroteIndexFile = true; } } -void FrameCaptureShared::onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface) +void FrameCaptureShared::onMakeCurrent(const gl::Context *context, + const egl::Surface *drawSurface, + EGLint surfaceWidth, + EGLint surfaceHeight) { if (!drawSurface) { @@ -8284,10 +8591,18 @@ void FrameCaptureShared::onMakeCurrent(const gl::Context *context, const egl::Su // Track the width, height and color space of the draw surface as provided to makeCurrent SurfaceParams ¶ms = mDrawSurfaceParams[context->id()]; - params.extents = gl::Extents(drawSurface->getWidth(), drawSurface->getHeight(), 1); + params.extents = gl::Extents(surfaceWidth, surfaceHeight, 1); params.colorSpace = egl::FromEGLenum(drawSurface->getGLColorspace()); } +void FrameCaptureShared::initalizeTraceStorage() +{ + // Update output directory location + getOutputDirectory(); + std::string fileName = GetBinaryDataFilePath(mCompression, mCaptureLabel); + mBinaryData.initializeBinaryDataStore(mCompression, mOutDirectory, fileName); +} + void StateResetHelper::setDefaultResetCalls(const gl::Context *context, angle::EntryPoint entryPoint) { @@ -8545,8 +8860,16 @@ void ResourceTracker::onShaderProgramAccess(gl::ShaderProgramID shaderProgramID) // ... etc ... void FrameCaptureShared::writeJSON(const gl::Context *context) { + SurfaceParams noSurface; + noSurface.extents.width = 16; + noSurface.extents.height = 9; + noSurface.colorSpace = egl::ColorSpace::sRGB; + const gl::ContextID contextId = context->id(); - const SurfaceParams &surfaceParams = mDrawSurfaceParams.at(contextId); + const SurfaceParams &surfaceParams = + mDrawSurfaceParams.find(contextId) != mDrawSurfaceParams.end() + ? mDrawSurfaceParams.at(contextId) + : noSurface; const gl::State &glState = context->getState(); const egl::Config *config = context->getConfig(); const egl::AttributeMap &displayAttribs = context->getDisplay()->getAttributeMap(); @@ -8556,8 +8879,8 @@ void FrameCaptureShared::writeJSON(const gl::Context *context) JsonSerializer json; json.startGroup("TraceMetadata"); json.addScalar("CaptureRevision", GetANGLERevision()); - json.addScalar("ContextClientMajorVersion", context->getClientMajorVersion()); - json.addScalar("ContextClientMinorVersion", context->getClientMinorVersion()); + json.addScalar("ContextClientMajorVersion", context->getClientVersion().getMajor()); + json.addScalar("ContextClientMinorVersion", context->getClientVersion().getMinor()); json.addHexValue("DisplayPlatformType", displayAttribs.getAsInt(EGL_PLATFORM_ANGLE_TYPE_ANGLE)); json.addHexValue("DisplayDeviceType", displayAttribs.getAsInt(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE)); @@ -8591,6 +8914,21 @@ void FrameCaptureShared::writeJSON(const gl::Context *context) json.addBool("IsRobustResourceInitEnabled", glState.isRobustResourceInitEnabled()); json.endGroup(); + json.startGroup("BinaryMetadata"); + json.addScalar("Version", mIndexInfo.version); + json.addScalar("BlockCount", mIndexInfo.blockCount); + // These values are handled as strings to avoid json-related underflows + std::stringstream blockSizeString; + blockSizeString << mIndexInfo.blockSize; + json.addString("BlockSize", blockSizeString.str()); + std::stringstream resSizeString; + resSizeString << mIndexInfo.residentSize; + json.addString("ResidentSize", resSizeString.str()); + std::stringstream offsetString; + offsetString << mIndexInfo.indexOffset; + json.addString("IndexOffset", offsetString.str()); + json.endGroup(); + { const std::vector &traceFiles = mReplayWriter.getAndResetWrittenFiles(); json.addVectorOfStrings("TraceFiles", traceFiles); @@ -8728,6 +9066,8 @@ void FrameCaptureShared::writeCppReplayIndexFiles(const gl::Context *context, mReplayWriter.saveIndexFilesAndHeader(); + // Finalize binary data file + mIndexInfo = mBinaryData.closeBinaryDataStore(); writeJSON(context); } @@ -8756,6 +9096,7 @@ void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context, std::string proto = "void SetupReplay(void)"; std::stringstream out; + std::stringstream outMainContextSetupCall; out << proto << "\n"; out << "{\n"; @@ -8782,10 +9123,11 @@ void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context, { if (usesMidExecutionCapture()) { - // Setup the presentation (this) context first. - out << " " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Call) + // Setup the presentation (this) context last + outMainContextSetupCall + << " " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Call) << ";\n"; - out << "\n"; + outMainContextSetupCall << "\n"; } continue; @@ -8812,6 +9154,7 @@ void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context, } } } + out << outMainContextSetupCall.str(); // If there are other contexts that were initialized, we need to make the main context // current again. @@ -8820,6 +9163,7 @@ void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context, out << "\n"; out << " eglMakeCurrent(NULL, NULL, NULL, gContextMap2[" << context->id() << "]);\n"; + out << " UpdateCurrentContext(" << context->id() << ");\n"; } out << "}\n"; @@ -8928,7 +9272,8 @@ void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context, { contextChanged = true; bodyStream << " eglMakeCurrent(NULL, NULL, NULL, gContextMap2[" - << contextID.value << "]);\n\n"; + << contextID.value << "]);\n"; + bodyStream << " UpdateCurrentContext(" << contextID.value << ");\n\n"; } // Then append the Reset calls @@ -8948,6 +9293,7 @@ void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context, { resetBodyStream << " eglMakeCurrent(NULL, NULL, NULL, gContextMap2[" << context->id().value << "]);\n"; + resetBodyStream << " UpdateCurrentContext(" << context->id().value << ");\n"; } // Now that we're back on the main context, reset any additional state diff --git a/src/libANGLE/capture/FrameCapture.h b/src/libANGLE/capture/FrameCapture.h index 16a816b9c57..96725c3ded0 100644 --- a/src/libANGLE/capture/FrameCapture.h +++ b/src/libANGLE/capture/FrameCapture.h @@ -10,11 +10,16 @@ #ifndef LIBANGLE_FRAME_CAPTURE_H_ #define LIBANGLE_FRAME_CAPTURE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "sys/stat.h" #include "common/PackedEnums.h" #include "common/SimpleMutex.h" +#include "common/frame_capture_binary_data.h" #include "common/frame_capture_utils.h" #include "common/string_utils.h" #include "common/system_utils.h" @@ -30,7 +35,6 @@ namespace gl { -enum class BigGLEnum; enum class GLESEnum; } // namespace gl @@ -357,7 +361,6 @@ class ResourceTracker final : angle::NonCopyable mBufferBindingCalls.clear(); mStartingBuffersMappedInitial.clear(); mStartingBuffersMappedCurrent.clear(); - mMaxShaderPrograms = 0; mStartingFenceSyncs.clear(); mFenceSyncRegenCalls.clear(); mFenceSyncsToRegen.clear(); @@ -744,10 +747,14 @@ class FrameCaptureShared final : angle::NonCopyable void captureCall(gl::Context *context, CallCapture &&call, bool isCallValid); void checkForCaptureTrigger(); + bool checkForCaptureEnd(); void onEndFrame(gl::Context *context); void onDestroyContext(const gl::Context *context); bool onEndCLCapture(); - void onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface); + void onMakeCurrent(const gl::Context *context, + const egl::Surface *drawSurface, + EGLint surfaceWidth, + EGLint surfaceHeight); bool enabled() const { return mEnabled; } bool isCapturing() const; @@ -838,7 +845,8 @@ class FrameCaptureShared final : angle::NonCopyable GLintptr offset, GLsizeiptr length, bool writable, - bool coherent); + bool coherent, + bool persistent); void trackTextureUpdate(const gl::Context *context, const CallCapture &call); void trackImageUpdate(const gl::Context *context, const CallCapture &call); @@ -974,6 +982,8 @@ class FrameCaptureShared final : angle::NonCopyable INFO() << "Capture trigger detected, resetting capture start/end frame."; } + void initalizeTraceStorage(); + private: void writeJSON(const gl::Context *context); void writeJSONCL(); @@ -996,6 +1006,7 @@ class FrameCaptureShared final : angle::NonCopyable void reset(); void resetMidExecutionCapture(gl::Context *context); + void maybeSetSyncPoint(CallCapture &inCall); void maybeOverrideEntryPoint(const gl::Context *context, CallCapture &call, std::vector &newCalls); @@ -1036,7 +1047,8 @@ class FrameCaptureShared final : angle::NonCopyable // We save one large buffer of binary data for the whole CPP replay. // This simplifies a lot of file management. - std::vector mBinaryData; + FrameCaptureBinaryData mBinaryData; + BinaryFileIndexInfo mIndexInfo; bool mEnabled; static bool mRuntimeEnabled; @@ -1109,6 +1121,9 @@ class FrameCaptureShared final : angle::NonCopyable // you reach the content you want to capture. Currently only available on Android. uint32_t mCaptureTrigger; + // If you want to finish capture early, use the end_capture utility. + uint32_t mEndCapture; + bool mCaptureActive; std::vector mActiveFrameIndices; @@ -1499,7 +1514,10 @@ constexpr char kEnabledVarName[] = "ANGLE_CAPTURE_ENABLED"; constexpr char kOutDirectoryVarName[] = "ANGLE_CAPTURE_OUT_DIR"; constexpr char kFrameStartVarName[] = "ANGLE_CAPTURE_FRAME_START"; constexpr char kFrameEndVarName[] = "ANGLE_CAPTURE_FRAME_END"; +constexpr char kBinaryDataSizeVarName[] = "ANGLE_CAPTURE_MAX_RESIDENT_BINARY_SIZE"; +constexpr char kBlockSizeVarName[] = "ANGLE_CAPTURE_BLOCK_SIZE"; constexpr char kTriggerVarName[] = "ANGLE_CAPTURE_TRIGGER"; +constexpr char kEndCaptureVarName[] = "ANGLE_CAPTURE_END_CAPTURE"; constexpr char kCaptureLabelVarName[] = "ANGLE_CAPTURE_LABEL"; constexpr char kCompressionVarName[] = "ANGLE_CAPTURE_COMPRESSION"; constexpr char kSerializeStateVarName[] = "ANGLE_CAPTURE_SERIALIZE_STATE"; @@ -1509,7 +1527,6 @@ constexpr char kSourceExtVarName[] = "ANGLE_CAPTURE_SOURCE_EXT"; constexpr char kSourceSizeVarName[] = "ANGLE_CAPTURE_SOURCE_SIZE"; constexpr char kForceShadowVarName[] = "ANGLE_CAPTURE_FORCE_SHADOW"; -constexpr size_t kBinaryAlignment = 16; constexpr size_t kFunctionSizeLimit = 5000; // Limit based on MSVC Compiler Error C2026 @@ -1524,7 +1541,10 @@ constexpr char kAndroidEnabled[] = "debug.angle.capture.enabled"; constexpr char kAndroidOutDir[] = "debug.angle.capture.out_dir"; constexpr char kAndroidFrameStart[] = "debug.angle.capture.frame_start"; constexpr char kAndroidFrameEnd[] = "debug.angle.capture.frame_end"; +constexpr char kAndroidBinaryDataSize[] = "debug.angle.capture.max_resident_binary_size"; +constexpr char kAndroidBlockSize[] = "debug.angle.capture.block_size"; constexpr char kAndroidTrigger[] = "debug.angle.capture.trigger"; +constexpr char kAndroidEndCapture[] = "debug.angle.capture.end_capture"; constexpr char kAndroidCaptureLabel[] = "debug.angle.capture.label"; constexpr char kAndroidCompression[] = "debug.angle.capture.compression"; constexpr char kAndroidValidation[] = "debug.angle.capture.validation"; @@ -1537,30 +1557,24 @@ void WriteCppReplayForCall(const CallCapture &call, ReplayWriter &replayWriter, std::ostream &out, std::ostream &header, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, size_t *maxResourceIDBufferSize); void WriteCppReplayForCallCL(const CallCapture &call, ReplayWriter &replayWriter, std::ostream &out, std::ostream &header, - std::vector *binaryData); + FrameCaptureBinaryData *binaryData); void WriteBinaryParamReplay(ReplayWriter &replayWriter, std::ostream &out, std::ostream &header, const CallCapture &call, const ParamCapture ¶m, - std::vector *binaryData); + FrameCaptureBinaryData *binaryData); std::string GetBinaryDataFilePath(bool compression, const std::string &captureLabel); -void SaveBinaryData(bool compression, - const std::string &outDir, - gl::ContextID contextId, - const std::string &captureLabel, - const std::vector &binaryData); - void WriteStringPointerParamReplay(ReplayWriter &replayWriter, std::ostream &out, std::ostream &header, @@ -1571,7 +1585,7 @@ void WriteCppReplayFunctionWithParts(const gl::ContextID contextID, ReplayFunc replayFunc, ReplayWriter &replayWriter, uint32_t frameIndex, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, const std::vector &calls, std::stringstream &header, std::stringstream &out, @@ -1603,6 +1617,10 @@ void WriteInlineData(const std::vector &vec, std::ostream &out) void AddComment(std::vector *outCalls, const std::string &comment); +std::string GetCaptureTrigger(); + +std::string GetEndCapture(); + } // namespace angle template diff --git a/src/libANGLE/capture/FrameCaptureCL.cpp b/src/libANGLE/capture/FrameCaptureCL.cpp index c56dfd04ba7..473fa96f63d 100644 --- a/src/libANGLE/capture/FrameCaptureCL.cpp +++ b/src/libANGLE/capture/FrameCaptureCL.cpp @@ -6,6 +6,11 @@ // FrameCaptureCL.cpp: // ANGLE CL Frame capture implementation. // + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/capture/FrameCapture.h" #include "common/angle_version_info.h" @@ -39,7 +44,7 @@ namespace angle void WriteCppReplayFunctionWithPartsCL(ReplayFunc replayFunc, ReplayWriter &replayWriter, uint32_t frameIndex, - std::vector *binaryData, + FrameCaptureBinaryData *binaryData, const std::vector &calls, std::stringstream &header, std::stringstream &out) @@ -67,7 +72,7 @@ void WriteCppReplayForCallCL(const CallCapture &call, ReplayWriter &replayWriter, std::ostream &out, std::ostream &header, - std::vector *binaryData) + FrameCaptureBinaryData *binaryData) { if (call.customFunctionName == "Comment") { @@ -479,10 +484,8 @@ void WriteCppReplayForCallCL(const CallCapture &call, out << ", "; } data = ¶m.data[i]; - size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment); - binaryData->resize(offset + data->size()); - memcpy(binaryData->data() + offset, data->data(), data->size()); - out << tempStructureType << "&gBinaryData[" << offset << "]"; + const size_t offset = binaryData->append(data->data(), data->size()); + out << tempStructureType << "GetBinaryData[" << offset << "]"; } out << "};\n "; callOut << tempStructureName << ".data()"; @@ -568,9 +571,9 @@ void WriteInitReplayCallCL(bool compression, out << " // clKernelsMapSize = " << maxCLParamsSize.at(ParamType::Tcl_kernel) << "\n"; out << " // clSamplerMapSize = " << maxCLParamsSize.at(ParamType::Tcl_sampler) << "\n"; out << " // clVoidMapSize = " << maxCLParamsSize.at(ParamType::TvoidPointer) << "\n"; - out << " InitializeReplayCL(\"" << binaryDataFileName << "\", " << maxClientArraySize << ", " - << readBufferSize << ", " << maxCLParamsSize.at(ParamType::Tcl_platform_idPointer) << ", " - << maxCLParamsSize.at(ParamType::Tcl_device_idPointer) << ", " + out << " InitializeReplayCL2(\"" << binaryDataFileName << "\", " << maxClientArraySize + << ", " << readBufferSize << ", " << maxCLParamsSize.at(ParamType::Tcl_platform_idPointer) + << ", " << maxCLParamsSize.at(ParamType::Tcl_device_idPointer) << ", " << maxCLParamsSize.at(ParamType::Tcl_context) << ", " << maxCLParamsSize.at(ParamType::Tcl_command_queue) << ", " << maxCLParamsSize.at(ParamType::Tcl_mem) << ", " @@ -579,6 +582,9 @@ void WriteInitReplayCallCL(bool compression, << maxCLParamsSize.at(ParamType::Tcl_kernel) << ", " << maxCLParamsSize.at(ParamType::Tcl_sampler) << ", " << maxCLParamsSize.at(ParamType::TvoidPointer) << ");\n"; + + // Load binary data + out << " InitializeBinaryDataLoader();\n"; } void FrameCaptureShared::trackCLMemUpdate(const cl_mem *mem, bool referenced) @@ -1626,8 +1632,21 @@ void FrameCaptureShared::captureCLCall(CallCapture &&inCall, bool isCallValid) std::atexit(onCLProgramEnd); } + if (checkForCaptureEnd()) + { + onEndCLCapture(); + mCaptureEndFrame = 0; + return; + } + if (mFrameIndex <= mCaptureEndFrame) { + if ((mFrameIndex == mCaptureStartFrame - 1) || + ((mFrameIndex == 1) && (mCaptureStartFrame == 1))) + { + std::string fileName = GetBinaryDataFilePath(mCompression, mCaptureLabel); + mBinaryData.initializeBinaryDataStore(mCompression, mOutDirectory, fileName); + } // Keep track of return values from OpenCL calls updateResourceCountsFromCallCaptureCL(inCall); @@ -1671,8 +1690,6 @@ void FrameCaptureShared::captureCLCall(CallCapture &&inCall, bool isCallValid) if (mFrameIndex == mCaptureEndFrame) { writeCppReplayIndexFilesCL(); - SaveBinaryData(mCompression, mOutDirectory, kNoContextId, mCaptureLabel, - mBinaryData); } reset(); } @@ -2018,7 +2035,6 @@ bool FrameCaptureShared::onEndCLCapture() mCaptureEndFrame = mFrameIndex; writeMainContextCppReplayCL(); writeCppReplayIndexFilesCL(); - SaveBinaryData(mCompression, mOutDirectory, kNoContextId, mCaptureLabel, mBinaryData); return true; } return false; @@ -2161,6 +2177,21 @@ void FrameCaptureShared::writeJSONCL() json.addBool("IsOpenCL", true); json.endGroup(); + json.startGroup("BinaryMetadata"); + json.addScalar("Version", mIndexInfo.version); + json.addScalar("BlockCount", mIndexInfo.blockCount); + // These values are handled as strings to avoid json-related underflows + std::stringstream blockSizeString; + blockSizeString << mIndexInfo.blockSize; + json.addString("BlockSize", blockSizeString.str()); + std::stringstream resSizeString; + resSizeString << mIndexInfo.residentSize; + json.addString("ResidentSize", resSizeString.str()); + std::stringstream offsetString; + offsetString << mIndexInfo.indexOffset; + json.addString("IndexOffset", offsetString.str()); + json.endGroup(); + { const std::vector &traceFiles = mReplayWriter.getAndResetWrittenFiles(); json.addVectorOfStrings("TraceFiles", traceFiles); @@ -2202,8 +2233,7 @@ void FrameCaptureShared::saveCLGetInfo(const CallCapture &call) .value.size_tPointerVal; if (!sizePointer) { - size = - call.params.getParam("param_value_size", ParamType::Tcl_uint, 3).value.cl_uintVal; + size = call.params.getParam("num_entries", ParamType::Tcl_uint, 3).value.cl_uintVal; } else { @@ -2376,7 +2406,9 @@ void FrameCaptureShared::saveCLGetInfo(const CallCapture &call) json.addScalar(infoString, *static_cast(data)); break; case CL_PLATFORM_HOST_TIMER_RESOLUTION: +#ifdef CL_ENABLE_BETA_EXTENSIONS case CL_PLATFORM_COMMAND_BUFFER_CAPABILITIES_KHR: +#endif json.addScalar(infoString, *static_cast(data)); break; case CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR: @@ -3246,6 +3278,8 @@ void FrameCaptureShared::writeCppReplayIndexFilesCL() mReplayWriter.saveIndexFilesAndHeader(); + // Finalize binary data file + mIndexInfo = mBinaryData.closeBinaryDataStore(); writeJSONCL(); writeJSONCLGetInfo(); } diff --git a/src/libANGLE/capture/FrameCaptureCommon.cpp b/src/libANGLE/capture/FrameCaptureCommon.cpp index d4cb9623ca1..824d1d2b7e6 100644 --- a/src/libANGLE/capture/FrameCaptureCommon.cpp +++ b/src/libANGLE/capture/FrameCaptureCommon.cpp @@ -7,6 +7,10 @@ // ANGLE Frame capture implementation for both GL and CL. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/capture/FrameCapture.h" #define USE_SYSTEM_ZLIB @@ -26,43 +30,6 @@ std::string GetBinaryDataFilePath(bool compression, const std::string &captureLa return fnameStream.str(); } -void SaveBinaryData(bool compression, - const std::string &outDir, - gl::ContextID contextId, - const std::string &captureLabel, - const std::vector &binaryData) -{ - std::string binaryDataFileName = GetBinaryDataFilePath(compression, captureLabel); - std::string dataFilepath = outDir + binaryDataFileName; - - SaveFileHelper saveData(dataFilepath); - - if (compression) - { - // Save compressed data. - uLong uncompressedSize = static_cast(binaryData.size()); - uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize); - - std::vector compressedData(expectedCompressedSize, 0); - - uLong compressedSize = expectedCompressedSize; - int zResult = zlib_internal::GzipCompressHelper(compressedData.data(), &compressedSize, - binaryData.data(), uncompressedSize, - nullptr, nullptr); - - if (zResult != Z_OK) - { - FATAL() << "Error compressing binary data: " << zResult; - } - - saveData.write(compressedData.data(), compressedSize); - } - else - { - saveData.write(binaryData.data(), binaryData.size()); - } -} - template <> void WriteInlineData(const std::vector &vec, std::ostream &out) { @@ -92,7 +59,7 @@ void WriteBinaryParamReplay(ReplayWriter &replayWriter, std::ostream &header, const CallCapture &call, const ParamCapture ¶m, - std::vector *binaryData) + FrameCaptureBinaryData *binaryData) { std::string varName = replayWriter.getInlineVariableName(call.entryPoint, param.name); @@ -118,10 +85,8 @@ void WriteBinaryParamReplay(ReplayWriter &replayWriter, { // Store in binary file if data are not of type string // Round up to 16-byte boundary for cross ABI safety - size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment); - binaryData->resize(offset + data.size()); - memcpy(binaryData->data() + offset, data.data(), data.size()); - out << "(" << ParamTypeToString(overrideType) << ")&gBinaryData[" << offset << "]"; + const size_t offset = binaryData->append(data.data(), data.size()); + out << "(" << ParamTypeToString(overrideType) << ")GetBinaryData(" << offset << ")"; } } @@ -472,6 +437,7 @@ FrameCaptureShared::FrameCaptureShared() mResourceIDToSetupCalls{}, mMaxAccessedResourceIDs{}, mCaptureTrigger(0), + mEndCapture(0), mCaptureActive(false), mWindowSurfaceContextID({0}) { @@ -503,6 +469,20 @@ FrameCaptureShared::FrameCaptureShared() mCaptureEndFrame = atoi(endFromEnv.c_str()); } + std::string binaryDataSizeFromEnv = + GetEnvironmentVarOrUnCachedAndroidProperty(kBinaryDataSizeVarName, kAndroidBinaryDataSize); + if (!binaryDataSizeFromEnv.empty()) + { + mBinaryData.setBinaryDataSize(atoi(binaryDataSizeFromEnv.c_str())); + } + + std::string blockSizeFromEnv = + GetEnvironmentVarOrUnCachedAndroidProperty(kBlockSizeVarName, kAndroidBlockSize); + if (!blockSizeFromEnv.empty()) + { + mBinaryData.setBlockSize(atoi(blockSizeFromEnv.c_str())); + } + std::string captureTriggerFromEnv = GetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger); if (!captureTriggerFromEnv.empty()) @@ -513,6 +493,14 @@ FrameCaptureShared::FrameCaptureShared() resetCaptureStartEndFrames(); } + std::string endCaptureFromEnv = + GetEnvironmentVarOrUnCachedAndroidProperty(kEndCaptureVarName, kAndroidEndCapture); + if (!endCaptureFromEnv.empty()) + { + mEndCapture = atoi(endCaptureFromEnv.c_str()); + mCaptureEndFrame = std::numeric_limits::max(); + } + std::string labelFromEnv = GetEnvironmentVarOrUnCachedAndroidProperty(kCaptureLabelVarName, kAndroidCaptureLabel); // --angle-per-test-capture-label sets the env var, not properties @@ -648,6 +636,29 @@ uint32_t FrameCaptureShared::getReplayFrameIndex() const return mFrameIndex - mCaptureStartFrame + 1; } +bool FrameCaptureShared::checkForCaptureEnd() +{ + if (mEndCapture == 0) + { + return false; + } + + std::string captureEndStr = GetEndCapture(); + if (captureEndStr.empty()) + { + return false; + } + + uint32_t captureEnd = atoi(captureEndStr.c_str()); + if ((mEndCapture > 0) && (captureEnd == 0)) + { + mCaptureEndFrame = mFrameIndex; + mEndCapture = 0; + return true; + } + return false; +} + bool FrameCaptureShared::isRuntimeEnabled() { if (!mRuntimeEnabled && mRuntimeInitialized) @@ -690,9 +701,17 @@ bool FrameCaptureShared::isRuntimeEnabled() mCaptureTrigger = atoi(captureTriggerFromEnv.c_str()); } - mRuntimeEnabled = - enabledFromEnv != "0" && - (mCaptureTrigger || (mCaptureEndFrame != 0 && mCaptureEndFrame >= mCaptureStartFrame)); + uint32_t mEndCapture = 0; + std::string endCaptureFromEnv = + GetEnvironmentVarOrUnCachedAndroidProperty(kEndCaptureVarName, kAndroidEndCapture); + if (!endCaptureFromEnv.empty()) + { + mEndCapture = atoi(endCaptureFromEnv.c_str()); + } + + mRuntimeEnabled = enabledFromEnv != "0" && + (mCaptureTrigger || mEndCapture || + (mCaptureEndFrame != 0 && mCaptureEndFrame >= mCaptureStartFrame)); mRuntimeInitialized = true; return mRuntimeEnabled; @@ -944,7 +963,7 @@ void ReplayWriter::saveFrame() ASSERT(!mSourceFileExtension.empty()); std::stringstream strstr; - strstr << mFilenamePattern << "_" << std::setfill('0') << std::setw(3) << mFrameIndex << "." + strstr << mFilenamePattern << "_" << std::setfill('0') << std::setw(4) << mFrameIndex << "." << mSourceFileExtension; std::string frameFilePath = strstr.str(); @@ -1149,6 +1168,12 @@ void CaptureString(const GLchar *str, ParamCapture *paramCapture) CaptureMemory(str, strlen(str) + 1, paramCapture); } +std::string GetEndCapture() +{ + // Use the GetAndSet variant to improve future lookup times + return GetAndSetEnvironmentVarOrUnCachedAndroidProperty(kEndCaptureVarName, kAndroidEndCapture); +} + TrackedResource::TrackedResource() = default; TrackedResource::~TrackedResource() = default; diff --git a/src/libANGLE/capture/FrameCapture_mock.cpp b/src/libANGLE/capture/FrameCapture_mock.cpp index 9637045f392..19ba49f7f3d 100644 --- a/src/libANGLE/capture/FrameCapture_mock.cpp +++ b/src/libANGLE/capture/FrameCapture_mock.cpp @@ -43,7 +43,10 @@ FrameCapture::~FrameCapture() {} FrameCaptureShared::FrameCaptureShared() : mEnabled(false) {} FrameCaptureShared::~FrameCaptureShared() {} void FrameCaptureShared::onEndFrame(gl::Context *context) {} -void FrameCaptureShared::onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface) +void FrameCaptureShared::onMakeCurrent(const gl::Context *context, + const egl::Surface *drawSurface, + EGLint surfaceWidth, + EGLint surfaceHeight) {} void FrameCaptureShared::onDestroyContext(const gl::Context *context) {} void *FrameCaptureShared::maybeGetShadowMemoryPointer(gl::Buffer *buffer, diff --git a/src/libANGLE/capture/capture_cl_autogen.cpp b/src/libANGLE/capture/capture_cl_autogen.cpp index b6db70a883f..1e78d7585b4 100644 --- a/src/libANGLE/capture/capture_cl_autogen.cpp +++ b/src/libANGLE/capture/capture_cl_autogen.cpp @@ -31,37 +31,32 @@ CallCapture CaptureGetPlatformIDs(bool isCallValid, paramBuffer.addValueParam("num_entries", ParamType::Tcl_uint, num_entries); + ParamCapture platformsParam("platforms", ParamType::Tcl_platform_idPointer); if (isCallValid) { - ParamCapture platformsParam("platforms", ParamType::Tcl_platform_idPointer); InitParamValue(ParamType::Tcl_platform_idPointer, platforms, &platformsParam.value); - CaptureGetPlatformIDs_platforms(isCallValid, num_entries, platforms, num_platforms, - &platformsParam); - paramBuffer.addParam(std::move(platformsParam)); + CaptureGetPlatformIDs_platforms(num_entries, platforms, num_platforms, &platformsParam); } else { - ParamCapture platformsParam("platforms", ParamType::Tcl_platform_idPointer); InitParamValue(ParamType::Tcl_platform_idPointer, static_cast(nullptr), &platformsParam.value); - paramBuffer.addParam(std::move(platformsParam)); } + paramBuffer.addParam(std::move(platformsParam)); + ParamCapture num_platformsParam("num_platforms", ParamType::Tcl_uintPointer); if (isCallValid) { - ParamCapture num_platformsParam("num_platforms", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, num_platforms, &num_platformsParam.value); - CaptureGetPlatformIDs_num_platforms(isCallValid, num_entries, platforms, num_platforms, + CaptureGetPlatformIDs_num_platforms(num_entries, platforms, num_platforms, &num_platformsParam); - paramBuffer.addParam(std::move(num_platformsParam)); } else { - ParamCapture num_platformsParam("num_platforms", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, static_cast(nullptr), &num_platformsParam.value); - paramBuffer.addParam(std::move(num_platformsParam)); } + paramBuffer.addParam(std::move(num_platformsParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -84,40 +79,35 @@ CallCapture CaptureGetPlatformInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TPlatformInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetPlatformInfo_param_value(isCallValid, platform, param_namePacked, - param_value_size, param_value, param_value_size_ret, - ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetPlatformInfo_param_value(platform, param_namePacked, param_value_size, + param_value, param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetPlatformInfo_param_value_size_ret( - isCallValid, platform, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetPlatformInfo_param_value_size_ret(platform, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -140,37 +130,33 @@ CallCapture CaptureGetDeviceIDs(bool isCallValid, paramBuffer.addValueParam("device_typePacked", ParamType::TDeviceType, device_typePacked); paramBuffer.addValueParam("num_entries", ParamType::Tcl_uint, num_entries); + ParamCapture devicesParam("devices", ParamType::Tcl_device_idPointer); if (isCallValid) { - ParamCapture devicesParam("devices", ParamType::Tcl_device_idPointer); InitParamValue(ParamType::Tcl_device_idPointer, devices, &devicesParam.value); - CaptureGetDeviceIDs_devices(isCallValid, platform, device_typePacked, num_entries, devices, - num_devices, &devicesParam); - paramBuffer.addParam(std::move(devicesParam)); + CaptureGetDeviceIDs_devices(platform, device_typePacked, num_entries, devices, num_devices, + &devicesParam); } else { - ParamCapture devicesParam("devices", ParamType::Tcl_device_idPointer); InitParamValue(ParamType::Tcl_device_idPointer, static_cast(nullptr), &devicesParam.value); - paramBuffer.addParam(std::move(devicesParam)); } + paramBuffer.addParam(std::move(devicesParam)); + ParamCapture num_devicesParam("num_devices", ParamType::Tcl_uintPointer); if (isCallValid) { - ParamCapture num_devicesParam("num_devices", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, num_devices, &num_devicesParam.value); - CaptureGetDeviceIDs_num_devices(isCallValid, platform, device_typePacked, num_entries, - devices, num_devices, &num_devicesParam); - paramBuffer.addParam(std::move(num_devicesParam)); + CaptureGetDeviceIDs_num_devices(platform, device_typePacked, num_entries, devices, + num_devices, &num_devicesParam); } else { - ParamCapture num_devicesParam("num_devices", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, static_cast(nullptr), &num_devicesParam.value); - paramBuffer.addParam(std::move(num_devicesParam)); } + paramBuffer.addParam(std::move(num_devicesParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -193,39 +179,35 @@ CallCapture CaptureGetDeviceInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TDeviceInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetDeviceInfo_param_value(isCallValid, device, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetDeviceInfo_param_value(device, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetDeviceInfo_param_value_size_ret(isCallValid, device, param_namePacked, - param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetDeviceInfo_param_value_size_ret(device, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -248,91 +230,81 @@ CallCapture CaptureCreateContext(bool isCallValid, { ParamBuffer paramBuffer; + ParamCapture propertiesParam("properties", ParamType::Tcl_context_propertiesConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", ParamType::Tcl_context_propertiesConstPointer); InitParamValue(ParamType::Tcl_context_propertiesConstPointer, properties, &propertiesParam.value); - CaptureCreateContext_properties(isCallValid, properties, num_devices, devices, pfn_notify, - user_data, errcode_ret, &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); + CaptureCreateContext_properties(properties, num_devices, devices, pfn_notify, user_data, + errcode_ret, &propertiesParam); } else { - ParamCapture propertiesParam("properties", ParamType::Tcl_context_propertiesConstPointer); InitParamValue(ParamType::Tcl_context_propertiesConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture devicesParam("devices", ParamType::Tcl_device_idConstPointer); if (isCallValid) { - ParamCapture devicesParam("devices", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, devices, &devicesParam.value); - CaptureCreateContext_devices(isCallValid, properties, num_devices, devices, pfn_notify, - user_data, errcode_ret, &devicesParam); - paramBuffer.addParam(std::move(devicesParam)); + CaptureCreateContext_devices(properties, num_devices, devices, pfn_notify, user_data, + errcode_ret, &devicesParam); } else { - ParamCapture devicesParam("devices", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, static_cast(nullptr), &devicesParam.value); - paramBuffer.addParam(std::move(devicesParam)); } + paramBuffer.addParam(std::move(devicesParam)); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_func_type); InitParamValue(ParamType::Tcl_context_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureCreateContext_pfn_notify(isCallValid, properties, num_devices, devices, pfn_notify, - user_data, errcode_ret, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); + CaptureCreateContext_pfn_notify(properties, num_devices, devices, pfn_notify, user_data, + errcode_ret, &pfn_notifyParam); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_func_type); InitParamValue( ParamType::Tcl_context_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureCreateContext_user_data(isCallValid, properties, num_devices, devices, pfn_notify, - user_data, errcode_ret, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); + CaptureCreateContext_user_data(properties, num_devices, devices, pfn_notify, user_data, + errcode_ret, &user_dataParam); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateContext_errcode_ret(isCallValid, properties, num_devices, devices, pfn_notify, - user_data, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateContext_errcode_ret(properties, num_devices, devices, pfn_notify, user_data, + errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_context); InitParamValue(ParamType::Tcl_context, returnValue, &returnValueCapture.value); @@ -354,78 +326,67 @@ CallCapture CaptureCreateContextFromType(bool isCallValid, { ParamBuffer paramBuffer; + ParamCapture propertiesParam("properties", ParamType::Tcl_context_propertiesConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", ParamType::Tcl_context_propertiesConstPointer); InitParamValue(ParamType::Tcl_context_propertiesConstPointer, properties, &propertiesParam.value); - CaptureCreateContextFromType_properties(isCallValid, properties, device_typePacked, - pfn_notify, user_data, errcode_ret, - &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); + CaptureCreateContextFromType_properties(properties, device_typePacked, pfn_notify, + user_data, errcode_ret, &propertiesParam); } else { - ParamCapture propertiesParam("properties", ParamType::Tcl_context_propertiesConstPointer); InitParamValue(ParamType::Tcl_context_propertiesConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); paramBuffer.addValueParam("device_typePacked", ParamType::TDeviceType, device_typePacked); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_func_type); InitParamValue(ParamType::Tcl_context_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureCreateContextFromType_pfn_notify(isCallValid, properties, device_typePacked, - pfn_notify, user_data, errcode_ret, - &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); + CaptureCreateContextFromType_pfn_notify(properties, device_typePacked, pfn_notify, + user_data, errcode_ret, &pfn_notifyParam); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_func_type); InitParamValue( ParamType::Tcl_context_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureCreateContextFromType_user_data(isCallValid, properties, device_typePacked, - pfn_notify, user_data, errcode_ret, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); + CaptureCreateContextFromType_user_data(properties, device_typePacked, pfn_notify, user_data, + errcode_ret, &user_dataParam); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateContextFromType_errcode_ret(isCallValid, properties, device_typePacked, - pfn_notify, user_data, errcode_ret, - &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateContextFromType_errcode_ret(properties, device_typePacked, pfn_notify, + user_data, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_context); InitParamValue(ParamType::Tcl_context, returnValue, &returnValueCapture.value); @@ -474,39 +435,35 @@ CallCapture CaptureGetContextInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TContextInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetContextInfo_param_value(isCallValid, context, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetContextInfo_param_value(context, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetContextInfo_param_value_size_ret( - isCallValid, context, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetContextInfo_param_value_size_ret(context, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -559,40 +516,36 @@ CallCapture CaptureGetCommandQueueInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TCommandQueueInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetCommandQueueInfo_param_value(isCallValid, command_queue, param_namePacked, - param_value_size, param_value, param_value_size_ret, + CaptureGetCommandQueueInfo_param_value(command_queue, param_namePacked, param_value_size, + param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); CaptureGetCommandQueueInfo_param_value_size_ret( - isCallValid, command_queue, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + command_queue, param_namePacked, param_value_size, param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -615,36 +568,32 @@ CallCapture CaptureCreateBuffer(bool isCallValid, paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); + ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, host_ptr, &host_ptrParam.value); - CaptureCreateBuffer_host_ptr(isCallValid, context, flagsPacked, size, host_ptr, errcode_ret, + CaptureCreateBuffer_host_ptr(context, flagsPacked, size, host_ptr, errcode_ret, &host_ptrParam); - paramBuffer.addParam(std::move(host_ptrParam)); } else { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &host_ptrParam.value); - paramBuffer.addParam(std::move(host_ptrParam)); } + paramBuffer.addParam(std::move(host_ptrParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateBuffer_errcode_ret(isCallValid, context, flagsPacked, size, host_ptr, - errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateBuffer_errcode_ret(context, flagsPacked, size, host_ptr, errcode_ret, + &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -695,41 +644,37 @@ CallCapture CaptureGetSupportedImageFormats(bool isCallValid, paramBuffer.addValueParam("image_typePacked", ParamType::TMemObjectType, image_typePacked); paramBuffer.addValueParam("num_entries", ParamType::Tcl_uint, num_entries); + ParamCapture image_formatsParam("image_formats", ParamType::Tcl_image_formatPointer); if (isCallValid) { - ParamCapture image_formatsParam("image_formats", ParamType::Tcl_image_formatPointer); InitParamValue(ParamType::Tcl_image_formatPointer, image_formats, &image_formatsParam.value); - CaptureGetSupportedImageFormats_image_formats(isCallValid, context, flagsPacked, - image_typePacked, num_entries, image_formats, - num_image_formats, &image_formatsParam); - paramBuffer.addParam(std::move(image_formatsParam)); + CaptureGetSupportedImageFormats_image_formats(context, flagsPacked, image_typePacked, + num_entries, image_formats, num_image_formats, + &image_formatsParam); } else { - ParamCapture image_formatsParam("image_formats", ParamType::Tcl_image_formatPointer); InitParamValue(ParamType::Tcl_image_formatPointer, static_cast(nullptr), &image_formatsParam.value); - paramBuffer.addParam(std::move(image_formatsParam)); } + paramBuffer.addParam(std::move(image_formatsParam)); + ParamCapture num_image_formatsParam("num_image_formats", ParamType::Tcl_uintPointer); if (isCallValid) { - ParamCapture num_image_formatsParam("num_image_formats", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, num_image_formats, &num_image_formatsParam.value); CaptureGetSupportedImageFormats_num_image_formats( - isCallValid, context, flagsPacked, image_typePacked, num_entries, image_formats, - num_image_formats, &num_image_formatsParam); - paramBuffer.addParam(std::move(num_image_formatsParam)); + context, flagsPacked, image_typePacked, num_entries, image_formats, num_image_formats, + &num_image_formatsParam); } else { - ParamCapture num_image_formatsParam("num_image_formats", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, static_cast(nullptr), &num_image_formatsParam.value); - paramBuffer.addParam(std::move(num_image_formatsParam)); } + paramBuffer.addParam(std::move(num_image_formatsParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -752,39 +697,35 @@ CallCapture CaptureGetMemObjectInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TMemInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetMemObjectInfo_param_value(isCallValid, memobj, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetMemObjectInfo_param_value(memobj, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetMemObjectInfo_param_value_size_ret( - isCallValid, memobj, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetMemObjectInfo_param_value_size_ret(memobj, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -807,39 +748,35 @@ CallCapture CaptureGetImageInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TImageInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetImageInfo_param_value(isCallValid, image, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetImageInfo_param_value(image, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetImageInfo_param_value_size_ret(isCallValid, image, param_namePacked, - param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetImageInfo_param_value_size_ret(image, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -888,39 +825,35 @@ CallCapture CaptureGetSamplerInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TSamplerInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetSamplerInfo_param_value(isCallValid, sampler, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetSamplerInfo_param_value(sampler, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetSamplerInfo_param_value_size_ret( - isCallValid, sampler, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetSamplerInfo_param_value_size_ret(sampler, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -942,53 +875,47 @@ CallCapture CaptureCreateProgramWithSource(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("count", ParamType::Tcl_uint, count); + ParamCapture stringsParam("strings", ParamType::TcharConstPointerPointer); if (isCallValid) { - ParamCapture stringsParam("strings", ParamType::TcharConstPointerPointer); InitParamValue(ParamType::TcharConstPointerPointer, strings, &stringsParam.value); - CaptureCreateProgramWithSource_strings(isCallValid, context, count, strings, lengths, - errcode_ret, &stringsParam); - paramBuffer.addParam(std::move(stringsParam)); + CaptureCreateProgramWithSource_strings(context, count, strings, lengths, errcode_ret, + &stringsParam); } else { - ParamCapture stringsParam("strings", ParamType::TcharConstPointerPointer); InitParamValue(ParamType::TcharConstPointerPointer, static_cast(nullptr), &stringsParam.value); - paramBuffer.addParam(std::move(stringsParam)); } + paramBuffer.addParam(std::move(stringsParam)); + ParamCapture lengthsParam("lengths", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture lengthsParam("lengths", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, lengths, &lengthsParam.value); - CaptureCreateProgramWithSource_lengths(isCallValid, context, count, strings, lengths, - errcode_ret, &lengthsParam); - paramBuffer.addParam(std::move(lengthsParam)); + CaptureCreateProgramWithSource_lengths(context, count, strings, lengths, errcode_ret, + &lengthsParam); } else { - ParamCapture lengthsParam("lengths", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &lengthsParam.value); - paramBuffer.addParam(std::move(lengthsParam)); } + paramBuffer.addParam(std::move(lengthsParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateProgramWithSource_errcode_ret(isCallValid, context, count, strings, lengths, - errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateProgramWithSource_errcode_ret(context, count, strings, lengths, errcode_ret, + &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_program); InitParamValue(ParamType::Tcl_program, returnValue, &returnValueCapture.value); @@ -1012,90 +939,79 @@ CallCapture CaptureCreateProgramWithBinary(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); if (isCallValid) { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, device_list, &device_listParam.value); - CaptureCreateProgramWithBinary_device_list(isCallValid, context, num_devices, device_list, - lengths, binaries, binary_status, errcode_ret, + CaptureCreateProgramWithBinary_device_list(context, num_devices, device_list, lengths, + binaries, binary_status, errcode_ret, &device_listParam); - paramBuffer.addParam(std::move(device_listParam)); } else { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, static_cast(nullptr), &device_listParam.value); - paramBuffer.addParam(std::move(device_listParam)); } + paramBuffer.addParam(std::move(device_listParam)); + ParamCapture lengthsParam("lengths", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture lengthsParam("lengths", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, lengths, &lengthsParam.value); - CaptureCreateProgramWithBinary_lengths(isCallValid, context, num_devices, device_list, - lengths, binaries, binary_status, errcode_ret, - &lengthsParam); - paramBuffer.addParam(std::move(lengthsParam)); + CaptureCreateProgramWithBinary_lengths(context, num_devices, device_list, lengths, binaries, + binary_status, errcode_ret, &lengthsParam); } else { - ParamCapture lengthsParam("lengths", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &lengthsParam.value); - paramBuffer.addParam(std::move(lengthsParam)); } + paramBuffer.addParam(std::move(lengthsParam)); + ParamCapture binariesParam("binaries", ParamType::TcharUnsignedConstPointerPointer); if (isCallValid) { - ParamCapture binariesParam("binaries", ParamType::TcharUnsignedConstPointerPointer); InitParamValue(ParamType::TcharUnsignedConstPointerPointer, binaries, &binariesParam.value); - CaptureCreateProgramWithBinary_binaries(isCallValid, context, num_devices, device_list, - lengths, binaries, binary_status, errcode_ret, + CaptureCreateProgramWithBinary_binaries(context, num_devices, device_list, lengths, + binaries, binary_status, errcode_ret, &binariesParam); - paramBuffer.addParam(std::move(binariesParam)); } else { - ParamCapture binariesParam("binaries", ParamType::TcharUnsignedConstPointerPointer); InitParamValue(ParamType::TcharUnsignedConstPointerPointer, static_cast(nullptr), &binariesParam.value); - paramBuffer.addParam(std::move(binariesParam)); } + paramBuffer.addParam(std::move(binariesParam)); + ParamCapture binary_statusParam("binary_status", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture binary_statusParam("binary_status", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, binary_status, &binary_statusParam.value); - CaptureCreateProgramWithBinary_binary_status(isCallValid, context, num_devices, device_list, - lengths, binaries, binary_status, errcode_ret, + CaptureCreateProgramWithBinary_binary_status(context, num_devices, device_list, lengths, + binaries, binary_status, errcode_ret, &binary_statusParam); - paramBuffer.addParam(std::move(binary_statusParam)); } else { - ParamCapture binary_statusParam("binary_status", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &binary_statusParam.value); - paramBuffer.addParam(std::move(binary_statusParam)); } + paramBuffer.addParam(std::move(binary_statusParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateProgramWithBinary_errcode_ret(isCallValid, context, num_devices, device_list, - lengths, binaries, binary_status, errcode_ret, + CaptureCreateProgramWithBinary_errcode_ret(context, num_devices, device_list, lengths, + binaries, binary_status, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_program); InitParamValue(ParamType::Tcl_program, returnValue, &returnValueCapture.value); @@ -1144,71 +1060,63 @@ CallCapture CaptureBuildProgram(bool isCallValid, paramBuffer.addValueParam("program", ParamType::Tcl_program, program); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); if (isCallValid) { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, device_list, &device_listParam.value); - CaptureBuildProgram_device_list(isCallValid, program, num_devices, device_list, options, - pfn_notify, user_data, &device_listParam); - paramBuffer.addParam(std::move(device_listParam)); + CaptureBuildProgram_device_list(program, num_devices, device_list, options, pfn_notify, + user_data, &device_listParam); } else { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, static_cast(nullptr), &device_listParam.value); - paramBuffer.addParam(std::move(device_listParam)); } + paramBuffer.addParam(std::move(device_listParam)); + ParamCapture optionsParam("options", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture optionsParam("options", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, options, &optionsParam.value); - CaptureBuildProgram_options(isCallValid, program, num_devices, device_list, options, - pfn_notify, user_data, &optionsParam); - paramBuffer.addParam(std::move(optionsParam)); + CaptureBuildProgram_options(program, num_devices, device_list, options, pfn_notify, + user_data, &optionsParam); } else { - ParamCapture optionsParam("options", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &optionsParam.value); - paramBuffer.addParam(std::move(optionsParam)); } + paramBuffer.addParam(std::move(optionsParam)); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue(ParamType::Tcl_program_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureBuildProgram_pfn_notify(isCallValid, program, num_devices, device_list, options, - pfn_notify, user_data, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); + CaptureBuildProgram_pfn_notify(program, num_devices, device_list, options, pfn_notify, + user_data, &pfn_notifyParam); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue( ParamType::Tcl_program_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureBuildProgram_user_data(isCallValid, program, num_devices, device_list, options, - pfn_notify, user_data, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); + CaptureBuildProgram_user_data(program, num_devices, device_list, options, pfn_notify, + user_data, &user_dataParam); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1231,39 +1139,35 @@ CallCapture CaptureGetProgramInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TProgramInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetProgramInfo_param_value(isCallValid, program, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetProgramInfo_param_value(program, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetProgramInfo_param_value_size_ret( - isCallValid, program, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetProgramInfo_param_value_size_ret(program, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1288,40 +1192,36 @@ CallCapture CaptureGetProgramBuildInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TProgramBuildInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetProgramBuildInfo_param_value(isCallValid, program, device, param_namePacked, - param_value_size, param_value, param_value_size_ret, + CaptureGetProgramBuildInfo_param_value(program, device, param_namePacked, param_value_size, + param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); CaptureGetProgramBuildInfo_param_value_size_ret( - isCallValid, program, device, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + program, device, param_namePacked, param_value_size, param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1340,37 +1240,31 @@ CallCapture CaptureCreateKernel(bool isCallValid, paramBuffer.addValueParam("program", ParamType::Tcl_program, program); + ParamCapture kernel_nameParam("kernel_name", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture kernel_nameParam("kernel_name", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, kernel_name, &kernel_nameParam.value); - CaptureCreateKernel_kernel_name(isCallValid, program, kernel_name, errcode_ret, - &kernel_nameParam); - paramBuffer.addParam(std::move(kernel_nameParam)); + CaptureCreateKernel_kernel_name(program, kernel_name, errcode_ret, &kernel_nameParam); } else { - ParamCapture kernel_nameParam("kernel_name", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &kernel_nameParam.value); - paramBuffer.addParam(std::move(kernel_nameParam)); } + paramBuffer.addParam(std::move(kernel_nameParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateKernel_errcode_ret(isCallValid, program, kernel_name, errcode_ret, - &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateKernel_errcode_ret(program, kernel_name, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_kernel); InitParamValue(ParamType::Tcl_kernel, returnValue, &returnValueCapture.value); @@ -1391,37 +1285,33 @@ CallCapture CaptureCreateKernelsInProgram(bool isCallValid, paramBuffer.addValueParam("program", ParamType::Tcl_program, program); paramBuffer.addValueParam("num_kernels", ParamType::Tcl_uint, num_kernels); + ParamCapture kernelsParam("kernels", ParamType::Tcl_kernelPointer); if (isCallValid) { - ParamCapture kernelsParam("kernels", ParamType::Tcl_kernelPointer); InitParamValue(ParamType::Tcl_kernelPointer, kernels, &kernelsParam.value); - CaptureCreateKernelsInProgram_kernels(isCallValid, program, num_kernels, kernels, - num_kernels_ret, &kernelsParam); - paramBuffer.addParam(std::move(kernelsParam)); + CaptureCreateKernelsInProgram_kernels(program, num_kernels, kernels, num_kernels_ret, + &kernelsParam); } else { - ParamCapture kernelsParam("kernels", ParamType::Tcl_kernelPointer); InitParamValue(ParamType::Tcl_kernelPointer, static_cast(nullptr), &kernelsParam.value); - paramBuffer.addParam(std::move(kernelsParam)); } + paramBuffer.addParam(std::move(kernelsParam)); + ParamCapture num_kernels_retParam("num_kernels_ret", ParamType::Tcl_uintPointer); if (isCallValid) { - ParamCapture num_kernels_retParam("num_kernels_ret", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, num_kernels_ret, &num_kernels_retParam.value); - CaptureCreateKernelsInProgram_num_kernels_ret(isCallValid, program, num_kernels, kernels, + CaptureCreateKernelsInProgram_num_kernels_ret(program, num_kernels, kernels, num_kernels_ret, &num_kernels_retParam); - paramBuffer.addParam(std::move(num_kernels_retParam)); } else { - ParamCapture num_kernels_retParam("num_kernels_ret", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, static_cast(nullptr), &num_kernels_retParam.value); - paramBuffer.addParam(std::move(num_kernels_retParam)); } + paramBuffer.addParam(std::move(num_kernels_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1469,21 +1359,18 @@ CallCapture CaptureSetKernelArg(bool isCallValid, paramBuffer.addValueParam("arg_index", ParamType::Tcl_uint, arg_index); paramBuffer.addValueParam("arg_size", ParamType::Tsize_t, arg_size); + ParamCapture arg_valueParam("arg_value", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture arg_valueParam("arg_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, arg_value, &arg_valueParam.value); - CaptureSetKernelArg_arg_value(isCallValid, kernel, arg_index, arg_size, arg_value, - &arg_valueParam); - paramBuffer.addParam(std::move(arg_valueParam)); + CaptureSetKernelArg_arg_value(kernel, arg_index, arg_size, arg_value, &arg_valueParam); } else { - ParamCapture arg_valueParam("arg_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &arg_valueParam.value); - paramBuffer.addParam(std::move(arg_valueParam)); } + paramBuffer.addParam(std::move(arg_valueParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1506,39 +1393,35 @@ CallCapture CaptureGetKernelInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TKernelInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetKernelInfo_param_value(isCallValid, kernel, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetKernelInfo_param_value(kernel, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetKernelInfo_param_value_size_ret(isCallValid, kernel, param_namePacked, - param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetKernelInfo_param_value_size_ret(kernel, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1564,40 +1447,36 @@ CallCapture CaptureGetKernelWorkGroupInfo(bool isCallValid, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetKernelWorkGroupInfo_param_value(isCallValid, kernel, device, param_namePacked, + CaptureGetKernelWorkGroupInfo_param_value(kernel, device, param_namePacked, param_value_size, param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); CaptureGetKernelWorkGroupInfo_param_value_size_ret( - isCallValid, kernel, device, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + kernel, device, param_namePacked, param_value_size, param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1615,20 +1494,18 @@ CallCapture CaptureWaitForEvents(bool isCallValid, paramBuffer.addValueParam("num_events", ParamType::Tcl_uint, num_events); + ParamCapture event_listParam("event_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_listParam("event_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_list, &event_listParam.value); - CaptureWaitForEvents_event_list(isCallValid, num_events, event_list, &event_listParam); - paramBuffer.addParam(std::move(event_listParam)); + CaptureWaitForEvents_event_list(num_events, event_list, &event_listParam); } else { - ParamCapture event_listParam("event_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_listParam.value); - paramBuffer.addParam(std::move(event_listParam)); } + paramBuffer.addParam(std::move(event_listParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1651,39 +1528,35 @@ CallCapture CaptureGetEventInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TEventInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetEventInfo_param_value(isCallValid, event, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetEventInfo_param_value(event, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetEventInfo_param_value_size_ret(isCallValid, event, param_namePacked, - param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetEventInfo_param_value_size_ret(event, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1732,40 +1605,36 @@ CallCapture CaptureGetEventProfilingInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TProfilingInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetEventProfilingInfo_param_value(isCallValid, event, param_namePacked, - param_value_size, param_value, - param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetEventProfilingInfo_param_value(event, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetEventProfilingInfo_param_value_size_ret( - isCallValid, event, param_namePacked, param_value_size, param_value, - param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + CaptureGetEventProfilingInfo_param_value_size_ret(event, param_namePacked, param_value_size, + param_value, param_value_size_ret, + ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1820,59 +1689,52 @@ CallCapture CaptureEnqueueReadBuffer(bool isCallValid, paramBuffer.addValueParam("offset", ParamType::Tsize_t, offset); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); + ParamCapture ptrParam("ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, ptr, &ptrParam.value); - CaptureEnqueueReadBuffer_ptr(isCallValid, command_queue, buffer, blocking_read, offset, - size, ptr, num_events_in_wait_list, event_wait_list, event, - &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureEnqueueReadBuffer_ptr(command_queue, buffer, blocking_read, offset, size, ptr, + num_events_in_wait_list, event_wait_list, event, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueReadBuffer_event_wait_list(isCallValid, command_queue, buffer, blocking_read, - offset, size, ptr, num_events_in_wait_list, - event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueReadBuffer_event_wait_list(command_queue, buffer, blocking_read, offset, size, + ptr, num_events_in_wait_list, event_wait_list, + event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueReadBuffer_event(isCallValid, command_queue, buffer, blocking_read, offset, - size, ptr, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueReadBuffer_event(command_queue, buffer, blocking_read, offset, size, ptr, + num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1901,60 +1763,53 @@ CallCapture CaptureEnqueueWriteBuffer(bool isCallValid, paramBuffer.addValueParam("offset", ParamType::Tsize_t, offset); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); - CaptureEnqueueWriteBuffer_ptr(isCallValid, command_queue, buffer, blocking_write, offset, - size, ptr, num_events_in_wait_list, event_wait_list, event, - &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureEnqueueWriteBuffer_ptr(command_queue, buffer, blocking_write, offset, size, ptr, + num_events_in_wait_list, event_wait_list, event, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueWriteBuffer_event_wait_list( - isCallValid, command_queue, buffer, blocking_write, offset, size, ptr, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueWriteBuffer_event_wait_list(command_queue, buffer, blocking_write, offset, + size, ptr, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueWriteBuffer_event(isCallValid, command_queue, buffer, blocking_write, offset, - size, ptr, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueWriteBuffer_event(command_queue, buffer, blocking_write, offset, size, ptr, + num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -1986,40 +1841,36 @@ CallCapture CaptureEnqueueCopyBuffer(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueCopyBuffer_event_wait_list( - isCallValid, command_queue, src_buffer, dst_buffer, src_offset, dst_offset, size, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueCopyBuffer_event_wait_list(command_queue, src_buffer, dst_buffer, src_offset, + dst_offset, size, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueCopyBuffer_event(isCallValid, command_queue, src_buffer, dst_buffer, - src_offset, dst_offset, size, num_events_in_wait_list, - event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueCopyBuffer_event(command_queue, src_buffer, dst_buffer, src_offset, + dst_offset, size, num_events_in_wait_list, event_wait_list, + event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2048,97 +1899,86 @@ CallCapture CaptureEnqueueReadImage(bool isCallValid, paramBuffer.addValueParam("image", ParamType::Tcl_mem, image); paramBuffer.addValueParam("blocking_read", ParamType::Tcl_bool, blocking_read); + ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, origin, &originParam.value); - CaptureEnqueueReadImage_origin(isCallValid, command_queue, image, blocking_read, origin, - region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, + CaptureEnqueueReadImage_origin(command_queue, image, blocking_read, origin, region, + row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &originParam); - paramBuffer.addParam(std::move(originParam)); } else { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &originParam.value); - paramBuffer.addParam(std::move(originParam)); } + paramBuffer.addParam(std::move(originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueReadImage_region(isCallValid, command_queue, image, blocking_read, origin, - region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, + CaptureEnqueueReadImage_region(command_queue, image, blocking_read, origin, region, + row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("row_pitch", ParamType::Tsize_t, row_pitch); paramBuffer.addValueParam("slice_pitch", ParamType::Tsize_t, slice_pitch); + ParamCapture ptrParam("ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, ptr, &ptrParam.value); - CaptureEnqueueReadImage_ptr(isCallValid, command_queue, image, blocking_read, origin, - region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, - event_wait_list, event, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureEnqueueReadImage_ptr(command_queue, image, blocking_read, origin, region, row_pitch, + slice_pitch, ptr, num_events_in_wait_list, event_wait_list, + event, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueReadImage_event_wait_list(isCallValid, command_queue, image, blocking_read, - origin, region, row_pitch, slice_pitch, ptr, - num_events_in_wait_list, event_wait_list, event, - &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueReadImage_event_wait_list( + command_queue, image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, + num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueReadImage_event(isCallValid, command_queue, image, blocking_read, origin, - region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, + CaptureEnqueueReadImage_event(command_queue, image, blocking_read, origin, region, + row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2167,98 +2007,88 @@ CallCapture CaptureEnqueueWriteImage(bool isCallValid, paramBuffer.addValueParam("image", ParamType::Tcl_mem, image); paramBuffer.addValueParam("blocking_write", ParamType::Tcl_bool, blocking_write); + ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, origin, &originParam.value); CaptureEnqueueWriteImage_origin( - isCallValid, command_queue, image, blocking_write, origin, region, input_row_pitch, + command_queue, image, blocking_write, origin, region, input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &originParam); - paramBuffer.addParam(std::move(originParam)); } else { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &originParam.value); - paramBuffer.addParam(std::move(originParam)); } + paramBuffer.addParam(std::move(originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); CaptureEnqueueWriteImage_region( - isCallValid, command_queue, image, blocking_write, origin, region, input_row_pitch, + command_queue, image, blocking_write, origin, region, input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("input_row_pitch", ParamType::Tsize_t, input_row_pitch); paramBuffer.addValueParam("input_slice_pitch", ParamType::Tsize_t, input_slice_pitch); + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); - CaptureEnqueueWriteImage_ptr(isCallValid, command_queue, image, blocking_write, origin, - region, input_row_pitch, input_slice_pitch, ptr, + CaptureEnqueueWriteImage_ptr(command_queue, image, blocking_write, origin, region, + input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueWriteImage_event_wait_list(isCallValid, command_queue, image, blocking_write, - origin, region, input_row_pitch, input_slice_pitch, - ptr, num_events_in_wait_list, event_wait_list, - event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueWriteImage_event_wait_list(command_queue, image, blocking_write, origin, + region, input_row_pitch, input_slice_pitch, ptr, + num_events_in_wait_list, event_wait_list, event, + &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); CaptureEnqueueWriteImage_event( - isCallValid, command_queue, image, blocking_write, origin, region, input_row_pitch, + command_queue, image, blocking_write, origin, region, input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2285,94 +2115,84 @@ CallCapture CaptureEnqueueCopyImage(bool isCallValid, paramBuffer.addValueParam("src_image", ParamType::Tcl_mem, src_image); paramBuffer.addValueParam("dst_image", ParamType::Tcl_mem, dst_image); + ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, src_origin, &src_originParam.value); - CaptureEnqueueCopyImage_src_origin(isCallValid, command_queue, src_image, dst_image, - src_origin, dst_origin, region, num_events_in_wait_list, + CaptureEnqueueCopyImage_src_origin(command_queue, src_image, dst_image, src_origin, + dst_origin, region, num_events_in_wait_list, event_wait_list, event, &src_originParam); - paramBuffer.addParam(std::move(src_originParam)); } else { - ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &src_originParam.value); - paramBuffer.addParam(std::move(src_originParam)); } + paramBuffer.addParam(std::move(src_originParam)); + ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, dst_origin, &dst_originParam.value); - CaptureEnqueueCopyImage_dst_origin(isCallValid, command_queue, src_image, dst_image, - src_origin, dst_origin, region, num_events_in_wait_list, + CaptureEnqueueCopyImage_dst_origin(command_queue, src_image, dst_image, src_origin, + dst_origin, region, num_events_in_wait_list, event_wait_list, event, &dst_originParam); - paramBuffer.addParam(std::move(dst_originParam)); } else { - ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &dst_originParam.value); - paramBuffer.addParam(std::move(dst_originParam)); } + paramBuffer.addParam(std::move(dst_originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueCopyImage_region(isCallValid, command_queue, src_image, dst_image, src_origin, - dst_origin, region, num_events_in_wait_list, event_wait_list, - event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); + CaptureEnqueueCopyImage_region(command_queue, src_image, dst_image, src_origin, dst_origin, + region, num_events_in_wait_list, event_wait_list, event, + ®ionParam); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueCopyImage_event_wait_list( - isCallValid, command_queue, src_image, dst_image, src_origin, dst_origin, region, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueCopyImage_event_wait_list(command_queue, src_image, dst_image, src_origin, + dst_origin, region, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueCopyImage_event(isCallValid, command_queue, src_image, dst_image, src_origin, - dst_origin, region, num_events_in_wait_list, event_wait_list, - event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueCopyImage_event(command_queue, src_image, dst_image, src_origin, dst_origin, + region, num_events_in_wait_list, event_wait_list, event, + &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2399,78 +2219,70 @@ CallCapture CaptureEnqueueCopyImageToBuffer(bool isCallValid, paramBuffer.addValueParam("src_image", ParamType::Tcl_mem, src_image); paramBuffer.addValueParam("dst_buffer", ParamType::Tcl_mem, dst_buffer); + ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, src_origin, &src_originParam.value); - CaptureEnqueueCopyImageToBuffer_src_origin( - isCallValid, command_queue, src_image, dst_buffer, src_origin, region, dst_offset, - num_events_in_wait_list, event_wait_list, event, &src_originParam); - paramBuffer.addParam(std::move(src_originParam)); + CaptureEnqueueCopyImageToBuffer_src_origin(command_queue, src_image, dst_buffer, src_origin, + region, dst_offset, num_events_in_wait_list, + event_wait_list, event, &src_originParam); } else { - ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &src_originParam.value); - paramBuffer.addParam(std::move(src_originParam)); } + paramBuffer.addParam(std::move(src_originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueCopyImageToBuffer_region( - isCallValid, command_queue, src_image, dst_buffer, src_origin, region, dst_offset, - num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); + CaptureEnqueueCopyImageToBuffer_region(command_queue, src_image, dst_buffer, src_origin, + region, dst_offset, num_events_in_wait_list, + event_wait_list, event, ®ionParam); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("dst_offset", ParamType::Tsize_t, dst_offset); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueCopyImageToBuffer_event_wait_list( - isCallValid, command_queue, src_image, dst_buffer, src_origin, region, dst_offset, + command_queue, src_image, dst_buffer, src_origin, region, dst_offset, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueCopyImageToBuffer_event( - isCallValid, command_queue, src_image, dst_buffer, src_origin, region, dst_offset, - num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueCopyImageToBuffer_event(command_queue, src_image, dst_buffer, src_origin, + region, dst_offset, num_events_in_wait_list, + event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2498,77 +2310,69 @@ CallCapture CaptureEnqueueCopyBufferToImage(bool isCallValid, paramBuffer.addValueParam("dst_image", ParamType::Tcl_mem, dst_image); paramBuffer.addValueParam("src_offset", ParamType::Tsize_t, src_offset); + ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, dst_origin, &dst_originParam.value); - CaptureEnqueueCopyBufferToImage_dst_origin( - isCallValid, command_queue, src_buffer, dst_image, src_offset, dst_origin, region, - num_events_in_wait_list, event_wait_list, event, &dst_originParam); - paramBuffer.addParam(std::move(dst_originParam)); + CaptureEnqueueCopyBufferToImage_dst_origin(command_queue, src_buffer, dst_image, src_offset, + dst_origin, region, num_events_in_wait_list, + event_wait_list, event, &dst_originParam); } else { - ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &dst_originParam.value); - paramBuffer.addParam(std::move(dst_originParam)); } + paramBuffer.addParam(std::move(dst_originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueCopyBufferToImage_region( - isCallValid, command_queue, src_buffer, dst_image, src_offset, dst_origin, region, - num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); + CaptureEnqueueCopyBufferToImage_region(command_queue, src_buffer, dst_image, src_offset, + dst_origin, region, num_events_in_wait_list, + event_wait_list, event, ®ionParam); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueCopyBufferToImage_event_wait_list( - isCallValid, command_queue, src_buffer, dst_image, src_offset, dst_origin, region, + command_queue, src_buffer, dst_image, src_offset, dst_origin, region, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueCopyBufferToImage_event( - isCallValid, command_queue, src_buffer, dst_image, src_offset, dst_origin, region, - num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueCopyBufferToImage_event(command_queue, src_buffer, dst_image, src_offset, + dst_origin, region, num_events_in_wait_list, + event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2601,57 +2405,51 @@ CallCapture CaptureEnqueueMapBuffer(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueMapBuffer_event_wait_list( - isCallValid, command_queue, buffer, blocking_map, map_flagsPacked, offset, size, + command_queue, buffer, blocking_map, map_flagsPacked, offset, size, num_events_in_wait_list, event_wait_list, event, errcode_ret, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueMapBuffer_event(isCallValid, command_queue, buffer, blocking_map, - map_flagsPacked, offset, size, num_events_in_wait_list, - event_wait_list, event, errcode_ret, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueMapBuffer_event(command_queue, buffer, blocking_map, map_flagsPacked, offset, + size, num_events_in_wait_list, event_wait_list, event, + errcode_ret, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureEnqueueMapBuffer_errcode_ret(isCallValid, command_queue, buffer, blocking_map, - map_flagsPacked, offset, size, num_events_in_wait_list, - event_wait_list, event, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureEnqueueMapBuffer_errcode_ret(command_queue, buffer, blocking_map, map_flagsPacked, + offset, size, num_events_in_wait_list, event_wait_list, + event, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, returnValue, &returnValueCapture.value); @@ -2682,135 +2480,121 @@ CallCapture CaptureEnqueueMapImage(bool isCallValid, paramBuffer.addValueParam("blocking_map", ParamType::Tcl_bool, blocking_map); paramBuffer.addValueParam("map_flagsPacked", ParamType::TMapFlags, map_flagsPacked); + ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, origin, &originParam.value); - CaptureEnqueueMapImage_origin(isCallValid, command_queue, image, blocking_map, - map_flagsPacked, origin, region, image_row_pitch, - image_slice_pitch, num_events_in_wait_list, event_wait_list, - event, errcode_ret, &originParam); - paramBuffer.addParam(std::move(originParam)); + CaptureEnqueueMapImage_origin(command_queue, image, blocking_map, map_flagsPacked, origin, + region, image_row_pitch, image_slice_pitch, + num_events_in_wait_list, event_wait_list, event, errcode_ret, + &originParam); } else { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &originParam.value); - paramBuffer.addParam(std::move(originParam)); } + paramBuffer.addParam(std::move(originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueMapImage_region(isCallValid, command_queue, image, blocking_map, - map_flagsPacked, origin, region, image_row_pitch, - image_slice_pitch, num_events_in_wait_list, event_wait_list, - event, errcode_ret, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); + CaptureEnqueueMapImage_region(command_queue, image, blocking_map, map_flagsPacked, origin, + region, image_row_pitch, image_slice_pitch, + num_events_in_wait_list, event_wait_list, event, errcode_ret, + ®ionParam); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); + ParamCapture image_row_pitchParam("image_row_pitch", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture image_row_pitchParam("image_row_pitch", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, image_row_pitch, &image_row_pitchParam.value); - CaptureEnqueueMapImage_image_row_pitch( - isCallValid, command_queue, image, blocking_map, map_flagsPacked, origin, region, - image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, - errcode_ret, &image_row_pitchParam); - paramBuffer.addParam(std::move(image_row_pitchParam)); + CaptureEnqueueMapImage_image_row_pitch(command_queue, image, blocking_map, map_flagsPacked, + origin, region, image_row_pitch, image_slice_pitch, + num_events_in_wait_list, event_wait_list, event, + errcode_ret, &image_row_pitchParam); } else { - ParamCapture image_row_pitchParam("image_row_pitch", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), &image_row_pitchParam.value); - paramBuffer.addParam(std::move(image_row_pitchParam)); } + paramBuffer.addParam(std::move(image_row_pitchParam)); + ParamCapture image_slice_pitchParam("image_slice_pitch", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture image_slice_pitchParam("image_slice_pitch", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, image_slice_pitch, &image_slice_pitchParam.value); CaptureEnqueueMapImage_image_slice_pitch( - isCallValid, command_queue, image, blocking_map, map_flagsPacked, origin, region, - image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, - errcode_ret, &image_slice_pitchParam); - paramBuffer.addParam(std::move(image_slice_pitchParam)); + command_queue, image, blocking_map, map_flagsPacked, origin, region, image_row_pitch, + image_slice_pitch, num_events_in_wait_list, event_wait_list, event, errcode_ret, + &image_slice_pitchParam); } else { - ParamCapture image_slice_pitchParam("image_slice_pitch", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), &image_slice_pitchParam.value); - paramBuffer.addParam(std::move(image_slice_pitchParam)); } + paramBuffer.addParam(std::move(image_slice_pitchParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueMapImage_event_wait_list( - isCallValid, command_queue, image, blocking_map, map_flagsPacked, origin, region, - image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, - errcode_ret, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueMapImage_event_wait_list(command_queue, image, blocking_map, map_flagsPacked, + origin, region, image_row_pitch, image_slice_pitch, + num_events_in_wait_list, event_wait_list, event, + errcode_ret, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueMapImage_event(isCallValid, command_queue, image, blocking_map, - map_flagsPacked, origin, region, image_row_pitch, - image_slice_pitch, num_events_in_wait_list, event_wait_list, - event, errcode_ret, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueMapImage_event(command_queue, image, blocking_map, map_flagsPacked, origin, + region, image_row_pitch, image_slice_pitch, + num_events_in_wait_list, event_wait_list, event, errcode_ret, + &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureEnqueueMapImage_errcode_ret(isCallValid, command_queue, image, blocking_map, - map_flagsPacked, origin, region, image_row_pitch, - image_slice_pitch, num_events_in_wait_list, - event_wait_list, event, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureEnqueueMapImage_errcode_ret(command_queue, image, blocking_map, map_flagsPacked, + origin, region, image_row_pitch, image_slice_pitch, + num_events_in_wait_list, event_wait_list, event, + errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, returnValue, &returnValueCapture.value); @@ -2833,60 +2617,54 @@ CallCapture CaptureEnqueueUnmapMemObject(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("memobj", ParamType::Tcl_mem, memobj); + ParamCapture mapped_ptrParam("mapped_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture mapped_ptrParam("mapped_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, mapped_ptr, &mapped_ptrParam.value); - CaptureEnqueueUnmapMemObject_mapped_ptr(isCallValid, command_queue, memobj, mapped_ptr, + CaptureEnqueueUnmapMemObject_mapped_ptr(command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event, &mapped_ptrParam); - paramBuffer.addParam(std::move(mapped_ptrParam)); } else { - ParamCapture mapped_ptrParam("mapped_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &mapped_ptrParam.value); - paramBuffer.addParam(std::move(mapped_ptrParam)); } + paramBuffer.addParam(std::move(mapped_ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueUnmapMemObject_event_wait_list(isCallValid, command_queue, memobj, mapped_ptr, + CaptureEnqueueUnmapMemObject_event_wait_list(command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueUnmapMemObject_event(isCallValid, command_queue, memobj, mapped_ptr, + CaptureEnqueueUnmapMemObject_event(command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -2913,101 +2691,87 @@ CallCapture CaptureEnqueueNDRangeKernel(bool isCallValid, paramBuffer.addValueParam("kernel", ParamType::Tcl_kernel, kernel); paramBuffer.addValueParam("work_dim", ParamType::Tcl_uint, work_dim); + ParamCapture global_work_offsetParam("global_work_offset", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture global_work_offsetParam("global_work_offset", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, global_work_offset, &global_work_offsetParam.value); CaptureEnqueueNDRangeKernel_global_work_offset( - isCallValid, command_queue, kernel, work_dim, global_work_offset, global_work_size, - local_work_size, num_events_in_wait_list, event_wait_list, event, - &global_work_offsetParam); - paramBuffer.addParam(std::move(global_work_offsetParam)); + command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, + num_events_in_wait_list, event_wait_list, event, &global_work_offsetParam); } else { - ParamCapture global_work_offsetParam("global_work_offset", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &global_work_offsetParam.value); - paramBuffer.addParam(std::move(global_work_offsetParam)); } + paramBuffer.addParam(std::move(global_work_offsetParam)); + ParamCapture global_work_sizeParam("global_work_size", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture global_work_sizeParam("global_work_size", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, global_work_size, &global_work_sizeParam.value); CaptureEnqueueNDRangeKernel_global_work_size( - isCallValid, command_queue, kernel, work_dim, global_work_offset, global_work_size, - local_work_size, num_events_in_wait_list, event_wait_list, event, - &global_work_sizeParam); - paramBuffer.addParam(std::move(global_work_sizeParam)); + command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, + num_events_in_wait_list, event_wait_list, event, &global_work_sizeParam); } else { - ParamCapture global_work_sizeParam("global_work_size", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &global_work_sizeParam.value); - paramBuffer.addParam(std::move(global_work_sizeParam)); } + paramBuffer.addParam(std::move(global_work_sizeParam)); + ParamCapture local_work_sizeParam("local_work_size", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture local_work_sizeParam("local_work_size", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, local_work_size, &local_work_sizeParam.value); - CaptureEnqueueNDRangeKernel_local_work_size(isCallValid, command_queue, kernel, work_dim, - global_work_offset, global_work_size, - local_work_size, num_events_in_wait_list, - event_wait_list, event, &local_work_sizeParam); - paramBuffer.addParam(std::move(local_work_sizeParam)); + CaptureEnqueueNDRangeKernel_local_work_size( + command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, + num_events_in_wait_list, event_wait_list, event, &local_work_sizeParam); } else { - ParamCapture local_work_sizeParam("local_work_size", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &local_work_sizeParam.value); - paramBuffer.addParam(std::move(local_work_sizeParam)); } + paramBuffer.addParam(std::move(local_work_sizeParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueNDRangeKernel_event_wait_list(isCallValid, command_queue, kernel, work_dim, - global_work_offset, global_work_size, - local_work_size, num_events_in_wait_list, - event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueNDRangeKernel_event_wait_list( + command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, + num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); CaptureEnqueueNDRangeKernel_event( - isCallValid, command_queue, kernel, work_dim, global_work_offset, global_work_size, - local_work_size, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, + num_events_in_wait_list, event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3033,113 +2797,101 @@ CallCapture CaptureEnqueueNativeKernel(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); + ParamCapture user_funcParam("user_func", ParamType::Tcl_void_func_type); if (isCallValid) { - ParamCapture user_funcParam("user_func", ParamType::Tcl_void_func_type); InitParamValue(ParamType::Tcl_void_func_type, user_func, &user_funcParam.value); CaptureEnqueueNativeKernel_user_func( - isCallValid, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, - args_mem_loc, num_events_in_wait_list, event_wait_list, event, &user_funcParam); - paramBuffer.addParam(std::move(user_funcParam)); + command_queue, user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, + num_events_in_wait_list, event_wait_list, event, &user_funcParam); } else { - ParamCapture user_funcParam("user_func", ParamType::Tcl_void_func_type); InitParamValue(ParamType::Tcl_void_func_type, static_cast(nullptr), &user_funcParam.value); - paramBuffer.addParam(std::move(user_funcParam)); } + paramBuffer.addParam(std::move(user_funcParam)); + ParamCapture argsParam("args", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture argsParam("args", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, args, &argsParam.value); - CaptureEnqueueNativeKernel_args( - isCallValid, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, - args_mem_loc, num_events_in_wait_list, event_wait_list, event, &argsParam); - paramBuffer.addParam(std::move(argsParam)); + CaptureEnqueueNativeKernel_args(command_queue, user_func, args, cb_args, num_mem_objects, + mem_list, args_mem_loc, num_events_in_wait_list, + event_wait_list, event, &argsParam); } else { - ParamCapture argsParam("args", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &argsParam.value); - paramBuffer.addParam(std::move(argsParam)); } + paramBuffer.addParam(std::move(argsParam)); paramBuffer.addValueParam("cb_args", ParamType::Tsize_t, cb_args); paramBuffer.addValueParam("num_mem_objects", ParamType::Tcl_uint, num_mem_objects); + ParamCapture mem_listParam("mem_list", ParamType::Tcl_memConstPointer); if (isCallValid) { - ParamCapture mem_listParam("mem_list", ParamType::Tcl_memConstPointer); InitParamValue(ParamType::Tcl_memConstPointer, mem_list, &mem_listParam.value); CaptureEnqueueNativeKernel_mem_list( - isCallValid, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, - args_mem_loc, num_events_in_wait_list, event_wait_list, event, &mem_listParam); - paramBuffer.addParam(std::move(mem_listParam)); + command_queue, user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, + num_events_in_wait_list, event_wait_list, event, &mem_listParam); } else { - ParamCapture mem_listParam("mem_list", ParamType::Tcl_memConstPointer); InitParamValue(ParamType::Tcl_memConstPointer, static_cast(nullptr), &mem_listParam.value); - paramBuffer.addParam(std::move(mem_listParam)); } + paramBuffer.addParam(std::move(mem_listParam)); + ParamCapture args_mem_locParam("args_mem_loc", ParamType::TvoidConstPointerPointer); if (isCallValid) { - ParamCapture args_mem_locParam("args_mem_loc", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, args_mem_loc, &args_mem_locParam.value); CaptureEnqueueNativeKernel_args_mem_loc( - isCallValid, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, - args_mem_loc, num_events_in_wait_list, event_wait_list, event, &args_mem_locParam); - paramBuffer.addParam(std::move(args_mem_locParam)); + command_queue, user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, + num_events_in_wait_list, event_wait_list, event, &args_mem_locParam); } else { - ParamCapture args_mem_locParam("args_mem_loc", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, static_cast(nullptr), &args_mem_locParam.value); - paramBuffer.addParam(std::move(args_mem_locParam)); } + paramBuffer.addParam(std::move(args_mem_locParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueNativeKernel_event_wait_list( - isCallValid, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, - args_mem_loc, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + command_queue, user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, + num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueNativeKernel_event( - isCallValid, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, - args_mem_loc, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueNativeKernel_event(command_queue, user_func, args, cb_args, num_mem_objects, + mem_list, args_mem_loc, num_events_in_wait_list, + event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3162,25 +2914,22 @@ CallCapture CaptureSetCommandQueueProperty(bool isCallValid, propertiesPacked); paramBuffer.addValueParam("enable", ParamType::Tcl_bool, enable); + ParamCapture old_propertiesParam("old_properties", + ParamType::Tcl_command_queue_propertiesPointer); if (isCallValid) { - ParamCapture old_propertiesParam("old_properties", - ParamType::Tcl_command_queue_propertiesPointer); InitParamValue(ParamType::Tcl_command_queue_propertiesPointer, old_properties, &old_propertiesParam.value); - CaptureSetCommandQueueProperty_old_properties(isCallValid, command_queue, propertiesPacked, - enable, old_properties, &old_propertiesParam); - paramBuffer.addParam(std::move(old_propertiesParam)); + CaptureSetCommandQueueProperty_old_properties(command_queue, propertiesPacked, enable, + old_properties, &old_propertiesParam); } else { - ParamCapture old_propertiesParam("old_properties", - ParamType::Tcl_command_queue_propertiesPointer); InitParamValue(ParamType::Tcl_command_queue_propertiesPointer, static_cast(nullptr), &old_propertiesParam.value); - paramBuffer.addParam(std::move(old_propertiesParam)); } + paramBuffer.addParam(std::move(old_propertiesParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3205,60 +2954,53 @@ CallCapture CaptureCreateImage2D(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); + ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); if (isCallValid) { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, image_format, &image_formatParam.value); - CaptureCreateImage2D_image_format(isCallValid, context, flagsPacked, image_format, - image_width, image_height, image_row_pitch, host_ptr, - errcode_ret, &image_formatParam); - paramBuffer.addParam(std::move(image_formatParam)); + CaptureCreateImage2D_image_format(context, flagsPacked, image_format, image_width, + image_height, image_row_pitch, host_ptr, errcode_ret, + &image_formatParam); } else { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, static_cast(nullptr), &image_formatParam.value); - paramBuffer.addParam(std::move(image_formatParam)); } + paramBuffer.addParam(std::move(image_formatParam)); paramBuffer.addValueParam("image_width", ParamType::Tsize_t, image_width); paramBuffer.addValueParam("image_height", ParamType::Tsize_t, image_height); paramBuffer.addValueParam("image_row_pitch", ParamType::Tsize_t, image_row_pitch); + ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, host_ptr, &host_ptrParam.value); - CaptureCreateImage2D_host_ptr(isCallValid, context, flagsPacked, image_format, image_width, - image_height, image_row_pitch, host_ptr, errcode_ret, - &host_ptrParam); - paramBuffer.addParam(std::move(host_ptrParam)); + CaptureCreateImage2D_host_ptr(context, flagsPacked, image_format, image_width, image_height, + image_row_pitch, host_ptr, errcode_ret, &host_ptrParam); } else { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &host_ptrParam.value); - paramBuffer.addParam(std::move(host_ptrParam)); } + paramBuffer.addParam(std::move(host_ptrParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateImage2D_errcode_ret(isCallValid, context, flagsPacked, image_format, - image_width, image_height, image_row_pitch, host_ptr, - errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateImage2D_errcode_ret(context, flagsPacked, image_format, image_width, + image_height, image_row_pitch, host_ptr, errcode_ret, + &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -3285,23 +3027,21 @@ CallCapture CaptureCreateImage3D(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); + ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); if (isCallValid) { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, image_format, &image_formatParam.value); CaptureCreateImage3D_image_format( - isCallValid, context, flagsPacked, image_format, image_width, image_height, image_depth, + context, flagsPacked, image_format, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, host_ptr, errcode_ret, &image_formatParam); - paramBuffer.addParam(std::move(image_formatParam)); } else { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, static_cast(nullptr), &image_formatParam.value); - paramBuffer.addParam(std::move(image_formatParam)); } + paramBuffer.addParam(std::move(image_formatParam)); paramBuffer.addValueParam("image_width", ParamType::Tsize_t, image_width); paramBuffer.addValueParam("image_height", ParamType::Tsize_t, image_height); @@ -3309,38 +3049,34 @@ CallCapture CaptureCreateImage3D(bool isCallValid, paramBuffer.addValueParam("image_row_pitch", ParamType::Tsize_t, image_row_pitch); paramBuffer.addValueParam("image_slice_pitch", ParamType::Tsize_t, image_slice_pitch); + ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, host_ptr, &host_ptrParam.value); - CaptureCreateImage3D_host_ptr(isCallValid, context, flagsPacked, image_format, image_width, - image_height, image_depth, image_row_pitch, image_slice_pitch, - host_ptr, errcode_ret, &host_ptrParam); - paramBuffer.addParam(std::move(host_ptrParam)); + CaptureCreateImage3D_host_ptr(context, flagsPacked, image_format, image_width, image_height, + image_depth, image_row_pitch, image_slice_pitch, host_ptr, + errcode_ret, &host_ptrParam); } else { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &host_ptrParam.value); - paramBuffer.addParam(std::move(host_ptrParam)); } + paramBuffer.addParam(std::move(host_ptrParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); CaptureCreateImage3D_errcode_ret( - isCallValid, context, flagsPacked, image_format, image_width, image_height, image_depth, + context, flagsPacked, image_format, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, host_ptr, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -3358,20 +3094,18 @@ CallCapture CaptureEnqueueMarker(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueMarker_event(isCallValid, command_queue, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueMarker_event(command_queue, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3391,21 +3125,19 @@ CallCapture CaptureEnqueueWaitForEvents(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("num_events", ParamType::Tcl_uint, num_events); + ParamCapture event_listParam("event_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_listParam("event_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_list, &event_listParam.value); - CaptureEnqueueWaitForEvents_event_list(isCallValid, command_queue, num_events, event_list, + CaptureEnqueueWaitForEvents_event_list(command_queue, num_events, event_list, &event_listParam); - paramBuffer.addParam(std::move(event_listParam)); } else { - ParamCapture event_listParam("event_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_listParam.value); - paramBuffer.addParam(std::move(event_listParam)); } + paramBuffer.addParam(std::move(event_listParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3446,20 +3178,18 @@ CallCapture CaptureGetExtensionFunctionAddress(bool isCallValid, { ParamBuffer paramBuffer; + ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, func_name, &func_nameParam.value); - CaptureGetExtensionFunctionAddress_func_name(isCallValid, func_name, &func_nameParam); - paramBuffer.addParam(std::move(func_nameParam)); + CaptureGetExtensionFunctionAddress_func_name(func_name, &func_nameParam); } else { - ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &func_nameParam.value); - paramBuffer.addParam(std::move(func_nameParam)); } + paramBuffer.addParam(std::move(func_nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, returnValue, &returnValueCapture.value); @@ -3482,21 +3212,19 @@ CallCapture CaptureCreateCommandQueue(bool isCallValid, paramBuffer.addValueParam("propertiesPacked", ParamType::TCommandQueueProperties, propertiesPacked); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateCommandQueue_errcode_ret(isCallValid, context, device, propertiesPacked, - errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateCommandQueue_errcode_ret(context, device, propertiesPacked, errcode_ret, + &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_command_queue); InitParamValue(ParamType::Tcl_command_queue, returnValue, &returnValueCapture.value); @@ -3521,22 +3249,19 @@ CallCapture CaptureCreateSampler(bool isCallValid, addressing_modePacked); paramBuffer.addValueParam("filter_modePacked", ParamType::TFilterMode, filter_modePacked); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateSampler_errcode_ret(isCallValid, context, normalized_coords, - addressing_modePacked, filter_modePacked, errcode_ret, - &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateSampler_errcode_ret(context, normalized_coords, addressing_modePacked, + filter_modePacked, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_sampler); InitParamValue(ParamType::Tcl_sampler, returnValue, &returnValueCapture.value); @@ -3560,39 +3285,34 @@ CallCapture CaptureEnqueueTask(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueTask_event_wait_list(isCallValid, command_queue, kernel, - num_events_in_wait_list, event_wait_list, event, - &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueTask_event_wait_list(command_queue, kernel, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueTask_event(isCallValid, command_queue, kernel, num_events_in_wait_list, - event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueTask_event(command_queue, kernel, num_events_in_wait_list, event_wait_list, + event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3617,39 +3337,35 @@ CallCapture CaptureCreateSubBuffer(bool isCallValid, paramBuffer.addValueParam("buffer_create_type", ParamType::Tcl_buffer_create_type, buffer_create_type); + ParamCapture buffer_create_infoParam("buffer_create_info", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture buffer_create_infoParam("buffer_create_info", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, buffer_create_info, &buffer_create_infoParam.value); - CaptureCreateSubBuffer_buffer_create_info(isCallValid, buffer, flagsPacked, - buffer_create_type, buffer_create_info, - errcode_ret, &buffer_create_infoParam); - paramBuffer.addParam(std::move(buffer_create_infoParam)); + CaptureCreateSubBuffer_buffer_create_info(buffer, flagsPacked, buffer_create_type, + buffer_create_info, errcode_ret, + &buffer_create_infoParam); } else { - ParamCapture buffer_create_infoParam("buffer_create_info", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &buffer_create_infoParam.value); - paramBuffer.addParam(std::move(buffer_create_infoParam)); } + paramBuffer.addParam(std::move(buffer_create_infoParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateSubBuffer_errcode_ret(isCallValid, buffer, flagsPacked, buffer_create_type, + CaptureCreateSubBuffer_errcode_ret(buffer, flagsPacked, buffer_create_type, buffer_create_info, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -3669,38 +3385,34 @@ CallCapture CaptureSetMemObjectDestructorCallback(bool isCallValid, paramBuffer.addValueParam("memobj", ParamType::Tcl_mem, memobj); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_mem_destructor_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_mem_destructor_func_type); InitParamValue(ParamType::Tcl_mem_destructor_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureSetMemObjectDestructorCallback_pfn_notify(isCallValid, memobj, pfn_notify, user_data, + CaptureSetMemObjectDestructorCallback_pfn_notify(memobj, pfn_notify, user_data, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_mem_destructor_func_type); InitParamValue(ParamType::Tcl_mem_destructor_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureSetMemObjectDestructorCallback_user_data(isCallValid, memobj, pfn_notify, user_data, + CaptureSetMemObjectDestructorCallback_user_data(memobj, pfn_notify, user_data, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3718,20 +3430,18 @@ CallCapture CaptureCreateUserEvent(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateUserEvent_errcode_ret(isCallValid, context, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateUserEvent_errcode_ret(context, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_event); InitParamValue(ParamType::Tcl_event, returnValue, &returnValueCapture.value); @@ -3772,39 +3482,35 @@ CallCapture CaptureSetEventCallback(bool isCallValid, paramBuffer.addValueParam("command_exec_callback_type", ParamType::Tcl_int, command_exec_callback_type); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_callback_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_callback_func_type); InitParamValue(ParamType::Tcl_callback_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureSetEventCallback_pfn_notify(isCallValid, event, command_exec_callback_type, - pfn_notify, user_data, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); + CaptureSetEventCallback_pfn_notify(event, command_exec_callback_type, pfn_notify, user_data, + &pfn_notifyParam); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_callback_func_type); InitParamValue(ParamType::Tcl_callback_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureSetEventCallback_user_data(isCallValid, event, command_exec_callback_type, - pfn_notify, user_data, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); + CaptureSetEventCallback_user_data(event, command_exec_callback_type, pfn_notify, user_data, + &user_dataParam); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3836,121 +3542,109 @@ CallCapture CaptureEnqueueReadBufferRect(bool isCallValid, paramBuffer.addValueParam("buffer", ParamType::Tcl_mem, buffer); paramBuffer.addValueParam("blocking_read", ParamType::Tcl_bool, blocking_read); + ParamCapture buffer_originParam("buffer_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture buffer_originParam("buffer_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, buffer_origin, &buffer_originParam.value); CaptureEnqueueReadBufferRect_buffer_origin( - isCallValid, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, + command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &buffer_originParam); - paramBuffer.addParam(std::move(buffer_originParam)); } else { - ParamCapture buffer_originParam("buffer_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &buffer_originParam.value); - paramBuffer.addParam(std::move(buffer_originParam)); } + paramBuffer.addParam(std::move(buffer_originParam)); + ParamCapture host_originParam("host_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture host_originParam("host_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, host_origin, &host_originParam.value); CaptureEnqueueReadBufferRect_host_origin( - isCallValid, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, + command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &host_originParam); - paramBuffer.addParam(std::move(host_originParam)); } else { - ParamCapture host_originParam("host_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &host_originParam.value); - paramBuffer.addParam(std::move(host_originParam)); } + paramBuffer.addParam(std::move(host_originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); CaptureEnqueueReadBufferRect_region( - isCallValid, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, + command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("buffer_row_pitch", ParamType::Tsize_t, buffer_row_pitch); paramBuffer.addValueParam("buffer_slice_pitch", ParamType::Tsize_t, buffer_slice_pitch); paramBuffer.addValueParam("host_row_pitch", ParamType::Tsize_t, host_row_pitch); paramBuffer.addValueParam("host_slice_pitch", ParamType::Tsize_t, host_slice_pitch); + ParamCapture ptrParam("ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, ptr, &ptrParam.value); CaptureEnqueueReadBufferRect_ptr( - isCallValid, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, + command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueReadBufferRect_event_wait_list( - isCallValid, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, + command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); CaptureEnqueueReadBufferRect_event( - isCallValid, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, + command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -3982,122 +3676,110 @@ CallCapture CaptureEnqueueWriteBufferRect(bool isCallValid, paramBuffer.addValueParam("buffer", ParamType::Tcl_mem, buffer); paramBuffer.addValueParam("blocking_write", ParamType::Tcl_bool, blocking_write); + ParamCapture buffer_originParam("buffer_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture buffer_originParam("buffer_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, buffer_origin, &buffer_originParam.value); CaptureEnqueueWriteBufferRect_buffer_origin( - isCallValid, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, + command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &buffer_originParam); - paramBuffer.addParam(std::move(buffer_originParam)); } else { - ParamCapture buffer_originParam("buffer_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &buffer_originParam.value); - paramBuffer.addParam(std::move(buffer_originParam)); } + paramBuffer.addParam(std::move(buffer_originParam)); + ParamCapture host_originParam("host_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture host_originParam("host_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, host_origin, &host_originParam.value); CaptureEnqueueWriteBufferRect_host_origin( - isCallValid, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, + command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &host_originParam); - paramBuffer.addParam(std::move(host_originParam)); } else { - ParamCapture host_originParam("host_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &host_originParam.value); - paramBuffer.addParam(std::move(host_originParam)); } + paramBuffer.addParam(std::move(host_originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); CaptureEnqueueWriteBufferRect_region( - isCallValid, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, + command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("buffer_row_pitch", ParamType::Tsize_t, buffer_row_pitch); paramBuffer.addValueParam("buffer_slice_pitch", ParamType::Tsize_t, buffer_slice_pitch); paramBuffer.addValueParam("host_row_pitch", ParamType::Tsize_t, host_row_pitch); paramBuffer.addValueParam("host_slice_pitch", ParamType::Tsize_t, host_slice_pitch); + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); CaptureEnqueueWriteBufferRect_ptr( - isCallValid, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, + command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueWriteBufferRect_event_wait_list( - isCallValid, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, + command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); CaptureEnqueueWriteBufferRect_event( - isCallValid, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, + command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -4128,59 +3810,53 @@ CallCapture CaptureEnqueueCopyBufferRect(bool isCallValid, paramBuffer.addValueParam("src_buffer", ParamType::Tcl_mem, src_buffer); paramBuffer.addValueParam("dst_buffer", ParamType::Tcl_mem, dst_buffer); + ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, src_origin, &src_originParam.value); CaptureEnqueueCopyBufferRect_src_origin( - isCallValid, command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, - src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, + command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, + src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event, &src_originParam); - paramBuffer.addParam(std::move(src_originParam)); } else { - ParamCapture src_originParam("src_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &src_originParam.value); - paramBuffer.addParam(std::move(src_originParam)); } + paramBuffer.addParam(std::move(src_originParam)); + ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, dst_origin, &dst_originParam.value); CaptureEnqueueCopyBufferRect_dst_origin( - isCallValid, command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, - src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, + command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, + src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event, &dst_originParam); - paramBuffer.addParam(std::move(dst_originParam)); } else { - ParamCapture dst_originParam("dst_origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &dst_originParam.value); - paramBuffer.addParam(std::move(dst_originParam)); } + paramBuffer.addParam(std::move(dst_originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueCopyBufferRect_region( - isCallValid, command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, - src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, - event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); + CaptureEnqueueCopyBufferRect_region(command_queue, src_buffer, dst_buffer, src_origin, + dst_origin, region, src_row_pitch, src_slice_pitch, + dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, + event_wait_list, event, ®ionParam); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("src_row_pitch", ParamType::Tsize_t, src_row_pitch); paramBuffer.addValueParam("src_slice_pitch", ParamType::Tsize_t, src_slice_pitch); @@ -4189,42 +3865,38 @@ CallCapture CaptureEnqueueCopyBufferRect(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueCopyBufferRect_event_wait_list( - isCallValid, command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, - src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, + command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, + src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueCopyBufferRect_event( - isCallValid, command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, - src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, - event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueCopyBufferRect_event(command_queue, src_buffer, dst_buffer, src_origin, + dst_origin, region, src_row_pitch, src_slice_pitch, + dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, + event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -4246,60 +3918,52 @@ CallCapture CaptureCreateSubDevices(bool isCallValid, paramBuffer.addValueParam("in_device", ParamType::Tcl_device_id, in_device); + ParamCapture propertiesParam("properties", + ParamType::Tcl_device_partition_propertyConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", - ParamType::Tcl_device_partition_propertyConstPointer); InitParamValue(ParamType::Tcl_device_partition_propertyConstPointer, properties, &propertiesParam.value); - CaptureCreateSubDevices_properties(isCallValid, in_device, properties, num_devices, - out_devices, num_devices_ret, &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); + CaptureCreateSubDevices_properties(in_device, properties, num_devices, out_devices, + num_devices_ret, &propertiesParam); } else { - ParamCapture propertiesParam("properties", - ParamType::Tcl_device_partition_propertyConstPointer); InitParamValue(ParamType::Tcl_device_partition_propertyConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture out_devicesParam("out_devices", ParamType::Tcl_device_idPointer); if (isCallValid) { - ParamCapture out_devicesParam("out_devices", ParamType::Tcl_device_idPointer); InitParamValue(ParamType::Tcl_device_idPointer, out_devices, &out_devicesParam.value); - CaptureCreateSubDevices_out_devices(isCallValid, in_device, properties, num_devices, - out_devices, num_devices_ret, &out_devicesParam); - paramBuffer.addParam(std::move(out_devicesParam)); + CaptureCreateSubDevices_out_devices(in_device, properties, num_devices, out_devices, + num_devices_ret, &out_devicesParam); } else { - ParamCapture out_devicesParam("out_devices", ParamType::Tcl_device_idPointer); InitParamValue(ParamType::Tcl_device_idPointer, static_cast(nullptr), &out_devicesParam.value); - paramBuffer.addParam(std::move(out_devicesParam)); } + paramBuffer.addParam(std::move(out_devicesParam)); + ParamCapture num_devices_retParam("num_devices_ret", ParamType::Tcl_uintPointer); if (isCallValid) { - ParamCapture num_devices_retParam("num_devices_ret", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, num_devices_ret, &num_devices_retParam.value); - CaptureCreateSubDevices_num_devices_ret(isCallValid, in_device, properties, num_devices, - out_devices, num_devices_ret, - &num_devices_retParam); - paramBuffer.addParam(std::move(num_devices_retParam)); + CaptureCreateSubDevices_num_devices_ret(in_device, properties, num_devices, out_devices, + num_devices_ret, &num_devices_retParam); } else { - ParamCapture num_devices_retParam("num_devices_ret", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, static_cast(nullptr), &num_devices_retParam.value); - paramBuffer.addParam(std::move(num_devices_retParam)); } + paramBuffer.addParam(std::move(num_devices_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -4348,69 +4012,61 @@ CallCapture CaptureCreateImage(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); + ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); if (isCallValid) { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, image_format, &image_formatParam.value); - CaptureCreateImage_image_format(isCallValid, context, flagsPacked, image_format, image_desc, - host_ptr, errcode_ret, &image_formatParam); - paramBuffer.addParam(std::move(image_formatParam)); + CaptureCreateImage_image_format(context, flagsPacked, image_format, image_desc, host_ptr, + errcode_ret, &image_formatParam); } else { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, static_cast(nullptr), &image_formatParam.value); - paramBuffer.addParam(std::move(image_formatParam)); } + paramBuffer.addParam(std::move(image_formatParam)); + ParamCapture image_descParam("image_desc", ParamType::Tcl_image_descConstPointer); if (isCallValid) { - ParamCapture image_descParam("image_desc", ParamType::Tcl_image_descConstPointer); InitParamValue(ParamType::Tcl_image_descConstPointer, image_desc, &image_descParam.value); - CaptureCreateImage_image_desc(isCallValid, context, flagsPacked, image_format, image_desc, - host_ptr, errcode_ret, &image_descParam); - paramBuffer.addParam(std::move(image_descParam)); + CaptureCreateImage_image_desc(context, flagsPacked, image_format, image_desc, host_ptr, + errcode_ret, &image_descParam); } else { - ParamCapture image_descParam("image_desc", ParamType::Tcl_image_descConstPointer); InitParamValue(ParamType::Tcl_image_descConstPointer, static_cast(nullptr), &image_descParam.value); - paramBuffer.addParam(std::move(image_descParam)); } + paramBuffer.addParam(std::move(image_descParam)); + ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, host_ptr, &host_ptrParam.value); - CaptureCreateImage_host_ptr(isCallValid, context, flagsPacked, image_format, image_desc, - host_ptr, errcode_ret, &host_ptrParam); - paramBuffer.addParam(std::move(host_ptrParam)); + CaptureCreateImage_host_ptr(context, flagsPacked, image_format, image_desc, host_ptr, + errcode_ret, &host_ptrParam); } else { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &host_ptrParam.value); - paramBuffer.addParam(std::move(host_ptrParam)); } + paramBuffer.addParam(std::move(host_ptrParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateImage_errcode_ret(isCallValid, context, flagsPacked, image_format, image_desc, - host_ptr, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateImage_errcode_ret(context, flagsPacked, image_format, image_desc, host_ptr, + errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -4432,56 +4088,47 @@ CallCapture CaptureCreateProgramWithBuiltInKernels(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); if (isCallValid) { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, device_list, &device_listParam.value); - CaptureCreateProgramWithBuiltInKernels_device_list(isCallValid, context, num_devices, - device_list, kernel_names, errcode_ret, - &device_listParam); - paramBuffer.addParam(std::move(device_listParam)); + CaptureCreateProgramWithBuiltInKernels_device_list( + context, num_devices, device_list, kernel_names, errcode_ret, &device_listParam); } else { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, static_cast(nullptr), &device_listParam.value); - paramBuffer.addParam(std::move(device_listParam)); } + paramBuffer.addParam(std::move(device_listParam)); + ParamCapture kernel_namesParam("kernel_names", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture kernel_namesParam("kernel_names", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, kernel_names, &kernel_namesParam.value); - CaptureCreateProgramWithBuiltInKernels_kernel_names(isCallValid, context, num_devices, - device_list, kernel_names, errcode_ret, - &kernel_namesParam); - paramBuffer.addParam(std::move(kernel_namesParam)); + CaptureCreateProgramWithBuiltInKernels_kernel_names( + context, num_devices, device_list, kernel_names, errcode_ret, &kernel_namesParam); } else { - ParamCapture kernel_namesParam("kernel_names", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &kernel_namesParam.value); - paramBuffer.addParam(std::move(kernel_namesParam)); } + paramBuffer.addParam(std::move(kernel_namesParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateProgramWithBuiltInKernels_errcode_ret(isCallValid, context, num_devices, - device_list, kernel_names, errcode_ret, - &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateProgramWithBuiltInKernels_errcode_ret( + context, num_devices, device_list, kernel_names, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_program); InitParamValue(ParamType::Tcl_program, returnValue, &returnValueCapture.value); @@ -4509,115 +4156,102 @@ CallCapture CaptureCompileProgram(bool isCallValid, paramBuffer.addValueParam("program", ParamType::Tcl_program, program); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); if (isCallValid) { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, device_list, &device_listParam.value); - CaptureCompileProgram_device_list(isCallValid, program, num_devices, device_list, options, + CaptureCompileProgram_device_list(program, num_devices, device_list, options, num_input_headers, input_headers, header_include_names, pfn_notify, user_data, &device_listParam); - paramBuffer.addParam(std::move(device_listParam)); } else { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, static_cast(nullptr), &device_listParam.value); - paramBuffer.addParam(std::move(device_listParam)); } + paramBuffer.addParam(std::move(device_listParam)); + ParamCapture optionsParam("options", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture optionsParam("options", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, options, &optionsParam.value); - CaptureCompileProgram_options(isCallValid, program, num_devices, device_list, options, - num_input_headers, input_headers, header_include_names, - pfn_notify, user_data, &optionsParam); - paramBuffer.addParam(std::move(optionsParam)); + CaptureCompileProgram_options(program, num_devices, device_list, options, num_input_headers, + input_headers, header_include_names, pfn_notify, user_data, + &optionsParam); } else { - ParamCapture optionsParam("options", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &optionsParam.value); - paramBuffer.addParam(std::move(optionsParam)); } + paramBuffer.addParam(std::move(optionsParam)); paramBuffer.addValueParam("num_input_headers", ParamType::Tcl_uint, num_input_headers); + ParamCapture input_headersParam("input_headers", ParamType::Tcl_programConstPointer); if (isCallValid) { - ParamCapture input_headersParam("input_headers", ParamType::Tcl_programConstPointer); InitParamValue(ParamType::Tcl_programConstPointer, input_headers, &input_headersParam.value); - CaptureCompileProgram_input_headers(isCallValid, program, num_devices, device_list, options, + CaptureCompileProgram_input_headers(program, num_devices, device_list, options, num_input_headers, input_headers, header_include_names, pfn_notify, user_data, &input_headersParam); - paramBuffer.addParam(std::move(input_headersParam)); } else { - ParamCapture input_headersParam("input_headers", ParamType::Tcl_programConstPointer); InitParamValue(ParamType::Tcl_programConstPointer, static_cast(nullptr), &input_headersParam.value); - paramBuffer.addParam(std::move(input_headersParam)); } + paramBuffer.addParam(std::move(input_headersParam)); + ParamCapture header_include_namesParam("header_include_names", + ParamType::TcharConstPointerPointer); if (isCallValid) { - ParamCapture header_include_namesParam("header_include_names", - ParamType::TcharConstPointerPointer); InitParamValue(ParamType::TcharConstPointerPointer, header_include_names, &header_include_namesParam.value); CaptureCompileProgram_header_include_names( - isCallValid, program, num_devices, device_list, options, num_input_headers, - input_headers, header_include_names, pfn_notify, user_data, &header_include_namesParam); - paramBuffer.addParam(std::move(header_include_namesParam)); + program, num_devices, device_list, options, num_input_headers, input_headers, + header_include_names, pfn_notify, user_data, &header_include_namesParam); } else { - ParamCapture header_include_namesParam("header_include_names", - ParamType::TcharConstPointerPointer); InitParamValue(ParamType::TcharConstPointerPointer, static_cast(nullptr), &header_include_namesParam.value); - paramBuffer.addParam(std::move(header_include_namesParam)); } + paramBuffer.addParam(std::move(header_include_namesParam)); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue(ParamType::Tcl_program_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureCompileProgram_pfn_notify(isCallValid, program, num_devices, device_list, options, + CaptureCompileProgram_pfn_notify(program, num_devices, device_list, options, num_input_headers, input_headers, header_include_names, pfn_notify, user_data, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue( ParamType::Tcl_program_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureCompileProgram_user_data(isCallValid, program, num_devices, device_list, options, + CaptureCompileProgram_user_data(program, num_devices, device_list, options, num_input_headers, input_headers, header_include_names, pfn_notify, user_data, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -4643,112 +4277,100 @@ CallCapture CaptureLinkProgram(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("num_devices", ParamType::Tcl_uint, num_devices); + ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); if (isCallValid) { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, device_list, &device_listParam.value); - CaptureLinkProgram_device_list(isCallValid, context, num_devices, device_list, options, + CaptureLinkProgram_device_list(context, num_devices, device_list, options, num_input_programs, input_programs, pfn_notify, user_data, errcode_ret, &device_listParam); - paramBuffer.addParam(std::move(device_listParam)); } else { - ParamCapture device_listParam("device_list", ParamType::Tcl_device_idConstPointer); InitParamValue(ParamType::Tcl_device_idConstPointer, static_cast(nullptr), &device_listParam.value); - paramBuffer.addParam(std::move(device_listParam)); } + paramBuffer.addParam(std::move(device_listParam)); + ParamCapture optionsParam("options", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture optionsParam("options", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, options, &optionsParam.value); - CaptureLinkProgram_options(isCallValid, context, num_devices, device_list, options, - num_input_programs, input_programs, pfn_notify, user_data, - errcode_ret, &optionsParam); - paramBuffer.addParam(std::move(optionsParam)); + CaptureLinkProgram_options(context, num_devices, device_list, options, num_input_programs, + input_programs, pfn_notify, user_data, errcode_ret, + &optionsParam); } else { - ParamCapture optionsParam("options", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &optionsParam.value); - paramBuffer.addParam(std::move(optionsParam)); } + paramBuffer.addParam(std::move(optionsParam)); paramBuffer.addValueParam("num_input_programs", ParamType::Tcl_uint, num_input_programs); + ParamCapture input_programsParam("input_programs", ParamType::Tcl_programConstPointer); if (isCallValid) { - ParamCapture input_programsParam("input_programs", ParamType::Tcl_programConstPointer); InitParamValue(ParamType::Tcl_programConstPointer, input_programs, &input_programsParam.value); - CaptureLinkProgram_input_programs(isCallValid, context, num_devices, device_list, options, + CaptureLinkProgram_input_programs(context, num_devices, device_list, options, num_input_programs, input_programs, pfn_notify, user_data, errcode_ret, &input_programsParam); - paramBuffer.addParam(std::move(input_programsParam)); } else { - ParamCapture input_programsParam("input_programs", ParamType::Tcl_programConstPointer); InitParamValue(ParamType::Tcl_programConstPointer, static_cast(nullptr), &input_programsParam.value); - paramBuffer.addParam(std::move(input_programsParam)); } + paramBuffer.addParam(std::move(input_programsParam)); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue(ParamType::Tcl_program_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureLinkProgram_pfn_notify(isCallValid, context, num_devices, device_list, options, + CaptureLinkProgram_pfn_notify(context, num_devices, device_list, options, num_input_programs, input_programs, pfn_notify, user_data, errcode_ret, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue( ParamType::Tcl_program_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureLinkProgram_user_data(isCallValid, context, num_devices, device_list, options, - num_input_programs, input_programs, pfn_notify, user_data, - errcode_ret, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); + CaptureLinkProgram_user_data(context, num_devices, device_list, options, num_input_programs, + input_programs, pfn_notify, user_data, errcode_ret, + &user_dataParam); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureLinkProgram_errcode_ret(isCallValid, context, num_devices, device_list, options, + CaptureLinkProgram_errcode_ret(context, num_devices, device_list, options, num_input_programs, input_programs, pfn_notify, user_data, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_program); InitParamValue(ParamType::Tcl_program, returnValue, &returnValueCapture.value); @@ -4788,40 +4410,35 @@ CallCapture CaptureGetKernelArgInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TKernelArgInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetKernelArgInfo_param_value(isCallValid, kernel, arg_index, param_namePacked, - param_value_size, param_value, param_value_size_ret, - ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetKernelArgInfo_param_value(kernel, arg_index, param_namePacked, param_value_size, + param_value, param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); CaptureGetKernelArgInfo_param_value_size_ret( - isCallValid, kernel, arg_index, param_namePacked, param_value_size, param_value, + kernel, arg_index, param_namePacked, param_value_size, param_value, param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -4847,22 +4464,20 @@ CallCapture CaptureEnqueueFillBuffer(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("buffer", ParamType::Tcl_mem, buffer); + ParamCapture patternParam("pattern", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture patternParam("pattern", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pattern, &patternParam.value); - CaptureEnqueueFillBuffer_pattern(isCallValid, command_queue, buffer, pattern, pattern_size, - offset, size, num_events_in_wait_list, event_wait_list, - event, &patternParam); - paramBuffer.addParam(std::move(patternParam)); + CaptureEnqueueFillBuffer_pattern(command_queue, buffer, pattern, pattern_size, offset, size, + num_events_in_wait_list, event_wait_list, event, + &patternParam); } else { - ParamCapture patternParam("pattern", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &patternParam.value); - paramBuffer.addParam(std::move(patternParam)); } + paramBuffer.addParam(std::move(patternParam)); paramBuffer.addValueParam("pattern_size", ParamType::Tsize_t, pattern_size); paramBuffer.addValueParam("offset", ParamType::Tsize_t, offset); @@ -4870,40 +4485,36 @@ CallCapture CaptureEnqueueFillBuffer(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueFillBuffer_event_wait_list( - isCallValid, command_queue, buffer, pattern, pattern_size, offset, size, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueFillBuffer_event_wait_list(command_queue, buffer, pattern, pattern_size, + offset, size, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueFillBuffer_event(isCallValid, command_queue, buffer, pattern, pattern_size, - offset, size, num_events_in_wait_list, event_wait_list, - event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueFillBuffer_event(command_queue, buffer, pattern, pattern_size, offset, size, + num_events_in_wait_list, event_wait_list, event, + &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -4928,93 +4539,83 @@ CallCapture CaptureEnqueueFillImage(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("image", ParamType::Tcl_mem, image); + ParamCapture fill_colorParam("fill_color", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture fill_colorParam("fill_color", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, fill_color, &fill_colorParam.value); - CaptureEnqueueFillImage_fill_color(isCallValid, command_queue, image, fill_color, origin, - region, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueFillImage_fill_color(command_queue, image, fill_color, origin, region, + num_events_in_wait_list, event_wait_list, event, &fill_colorParam); - paramBuffer.addParam(std::move(fill_colorParam)); } else { - ParamCapture fill_colorParam("fill_color", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &fill_colorParam.value); - paramBuffer.addParam(std::move(fill_colorParam)); } + paramBuffer.addParam(std::move(fill_colorParam)); + ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, origin, &originParam.value); - CaptureEnqueueFillImage_origin(isCallValid, command_queue, image, fill_color, origin, - region, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueFillImage_origin(command_queue, image, fill_color, origin, region, + num_events_in_wait_list, event_wait_list, event, &originParam); - paramBuffer.addParam(std::move(originParam)); } else { - ParamCapture originParam("origin", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &originParam.value); - paramBuffer.addParam(std::move(originParam)); } + paramBuffer.addParam(std::move(originParam)); + ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, region, ®ionParam.value); - CaptureEnqueueFillImage_region(isCallValid, command_queue, image, fill_color, origin, - region, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueFillImage_region(command_queue, image, fill_color, origin, region, + num_events_in_wait_list, event_wait_list, event, ®ionParam); - paramBuffer.addParam(std::move(regionParam)); } else { - ParamCapture regionParam("region", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), ®ionParam.value); - paramBuffer.addParam(std::move(regionParam)); } + paramBuffer.addParam(std::move(regionParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueFillImage_event_wait_list(isCallValid, command_queue, image, fill_color, - origin, region, num_events_in_wait_list, - event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueFillImage_event_wait_list(command_queue, image, fill_color, origin, region, + num_events_in_wait_list, event_wait_list, event, + &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueFillImage_event(isCallValid, command_queue, image, fill_color, origin, region, + CaptureEnqueueFillImage_event(command_queue, image, fill_color, origin, region, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5038,61 +4639,55 @@ CallCapture CaptureEnqueueMigrateMemObjects(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("num_mem_objects", ParamType::Tcl_uint, num_mem_objects); + ParamCapture mem_objectsParam("mem_objects", ParamType::Tcl_memConstPointer); if (isCallValid) { - ParamCapture mem_objectsParam("mem_objects", ParamType::Tcl_memConstPointer); InitParamValue(ParamType::Tcl_memConstPointer, mem_objects, &mem_objectsParam.value); - CaptureEnqueueMigrateMemObjects_mem_objects( - isCallValid, command_queue, num_mem_objects, mem_objects, flagsPacked, - num_events_in_wait_list, event_wait_list, event, &mem_objectsParam); - paramBuffer.addParam(std::move(mem_objectsParam)); + CaptureEnqueueMigrateMemObjects_mem_objects(command_queue, num_mem_objects, mem_objects, + flagsPacked, num_events_in_wait_list, + event_wait_list, event, &mem_objectsParam); } else { - ParamCapture mem_objectsParam("mem_objects", ParamType::Tcl_memConstPointer); InitParamValue(ParamType::Tcl_memConstPointer, static_cast(nullptr), &mem_objectsParam.value); - paramBuffer.addParam(std::move(mem_objectsParam)); } + paramBuffer.addParam(std::move(mem_objectsParam)); paramBuffer.addValueParam("flagsPacked", ParamType::TMemMigrationFlags, flagsPacked); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); CaptureEnqueueMigrateMemObjects_event_wait_list( - isCallValid, command_queue, num_mem_objects, mem_objects, flagsPacked, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + command_queue, num_mem_objects, mem_objects, flagsPacked, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueMigrateMemObjects_event(isCallValid, command_queue, num_mem_objects, - mem_objects, flagsPacked, num_events_in_wait_list, - event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueMigrateMemObjects_event(command_queue, num_mem_objects, mem_objects, + flagsPacked, num_events_in_wait_list, event_wait_list, + event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5114,39 +4709,34 @@ CallCapture CaptureEnqueueMarkerWithWaitList(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueMarkerWithWaitList_event_wait_list(isCallValid, command_queue, - num_events_in_wait_list, event_wait_list, - event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueMarkerWithWaitList_event_wait_list( + command_queue, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueMarkerWithWaitList_event(isCallValid, command_queue, num_events_in_wait_list, + CaptureEnqueueMarkerWithWaitList_event(command_queue, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5168,39 +4758,34 @@ CallCapture CaptureEnqueueBarrierWithWaitList(bool isCallValid, paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueBarrierWithWaitList_event_wait_list(isCallValid, command_queue, - num_events_in_wait_list, event_wait_list, - event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueBarrierWithWaitList_event_wait_list( + command_queue, num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueBarrierWithWaitList_event(isCallValid, command_queue, num_events_in_wait_list, + CaptureEnqueueBarrierWithWaitList_event(command_queue, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5218,21 +4803,19 @@ CallCapture CaptureGetExtensionFunctionAddressForPlatform(bool isCallValid, paramBuffer.addValueParam("platform", ParamType::Tcl_platform_id, platform); + ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); if (isCallValid) { - ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, func_name, &func_nameParam.value); - CaptureGetExtensionFunctionAddressForPlatform_func_name(isCallValid, platform, func_name, + CaptureGetExtensionFunctionAddressForPlatform_func_name(platform, func_name, &func_nameParam); - paramBuffer.addParam(std::move(func_nameParam)); } else { - ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), &func_nameParam.value); - paramBuffer.addParam(std::move(func_nameParam)); } + paramBuffer.addParam(std::move(func_nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, returnValue, &returnValueCapture.value); @@ -5255,38 +4838,34 @@ CallCapture CaptureCreateCommandQueueWithProperties(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); paramBuffer.addValueParam("device", ParamType::Tcl_device_id, device); + ParamCapture propertiesParam("properties", ParamType::Tcl_queue_propertiesConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", ParamType::Tcl_queue_propertiesConstPointer); InitParamValue(ParamType::Tcl_queue_propertiesConstPointer, properties, &propertiesParam.value); - CaptureCreateCommandQueueWithProperties_properties(isCallValid, context, device, properties, - errcode_ret, &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); + CaptureCreateCommandQueueWithProperties_properties(context, device, properties, errcode_ret, + &propertiesParam); } else { - ParamCapture propertiesParam("properties", ParamType::Tcl_queue_propertiesConstPointer); InitParamValue(ParamType::Tcl_queue_propertiesConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateCommandQueueWithProperties_errcode_ret( - isCallValid, context, device, properties, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateCommandQueueWithProperties_errcode_ret(context, device, properties, + errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_command_queue); InitParamValue(ParamType::Tcl_command_queue, returnValue, &returnValueCapture.value); @@ -5312,38 +4891,34 @@ CallCapture CaptureCreatePipe(bool isCallValid, paramBuffer.addValueParam("pipe_packet_size", ParamType::Tcl_uint, pipe_packet_size); paramBuffer.addValueParam("pipe_max_packets", ParamType::Tcl_uint, pipe_max_packets); + ParamCapture propertiesParam("properties", ParamType::Tcl_pipe_propertiesConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", ParamType::Tcl_pipe_propertiesConstPointer); InitParamValue(ParamType::Tcl_pipe_propertiesConstPointer, properties, &propertiesParam.value); - CaptureCreatePipe_properties(isCallValid, context, flagsPacked, pipe_packet_size, - pipe_max_packets, properties, errcode_ret, &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); + CaptureCreatePipe_properties(context, flagsPacked, pipe_packet_size, pipe_max_packets, + properties, errcode_ret, &propertiesParam); } else { - ParamCapture propertiesParam("properties", ParamType::Tcl_pipe_propertiesConstPointer); InitParamValue(ParamType::Tcl_pipe_propertiesConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreatePipe_errcode_ret(isCallValid, context, flagsPacked, pipe_packet_size, - pipe_max_packets, properties, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreatePipe_errcode_ret(context, flagsPacked, pipe_packet_size, pipe_max_packets, + properties, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -5366,39 +4941,35 @@ CallCapture CaptureGetPipeInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TPipeInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetPipeInfo_param_value(isCallValid, pipe, param_namePacked, param_value_size, - param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetPipeInfo_param_value(pipe, param_namePacked, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); - CaptureGetPipeInfo_param_value_size_ret(isCallValid, pipe, param_namePacked, - param_value_size, param_value, param_value_size_ret, + CaptureGetPipeInfo_param_value_size_ret(pipe, param_namePacked, param_value_size, + param_value, param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5434,20 +5005,18 @@ CallCapture CaptureSVMFree(bool isCallValid, cl_context context, void *svm_point paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture svm_pointerParam("svm_pointer", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture svm_pointerParam("svm_pointer", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, svm_pointer, &svm_pointerParam.value); - CaptureSVMFree_svm_pointer(isCallValid, context, svm_pointer, &svm_pointerParam); - paramBuffer.addParam(std::move(svm_pointerParam)); + CaptureSVMFree_svm_pointer(context, svm_pointer, &svm_pointerParam); } else { - ParamCapture svm_pointerParam("svm_pointer", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &svm_pointerParam.value); - paramBuffer.addParam(std::move(svm_pointerParam)); } + paramBuffer.addParam(std::move(svm_pointerParam)); return CallCapture(angle::EntryPoint::CLSVMFree, std::move(paramBuffer)); } @@ -5462,41 +5031,36 @@ CallCapture CaptureCreateSamplerWithProperties(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture sampler_propertiesParam("sampler_properties", + ParamType::Tcl_sampler_propertiesConstPointer); if (isCallValid) { - ParamCapture sampler_propertiesParam("sampler_properties", - ParamType::Tcl_sampler_propertiesConstPointer); InitParamValue(ParamType::Tcl_sampler_propertiesConstPointer, sampler_properties, &sampler_propertiesParam.value); CaptureCreateSamplerWithProperties_sampler_properties( - isCallValid, context, sampler_properties, errcode_ret, &sampler_propertiesParam); - paramBuffer.addParam(std::move(sampler_propertiesParam)); + context, sampler_properties, errcode_ret, &sampler_propertiesParam); } else { - ParamCapture sampler_propertiesParam("sampler_properties", - ParamType::Tcl_sampler_propertiesConstPointer); InitParamValue(ParamType::Tcl_sampler_propertiesConstPointer, static_cast(nullptr), &sampler_propertiesParam.value); - paramBuffer.addParam(std::move(sampler_propertiesParam)); } + paramBuffer.addParam(std::move(sampler_propertiesParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateSamplerWithProperties_errcode_ret(isCallValid, context, sampler_properties, - errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateSamplerWithProperties_errcode_ret(context, sampler_properties, errcode_ret, + &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_sampler); InitParamValue(ParamType::Tcl_sampler, returnValue, &returnValueCapture.value); @@ -5516,21 +5080,18 @@ CallCapture CaptureSetKernelArgSVMPointer(bool isCallValid, paramBuffer.addValueParam("kernel", ParamType::Tcl_kernel, kernel); paramBuffer.addValueParam("arg_index", ParamType::Tcl_uint, arg_index); + ParamCapture arg_valueParam("arg_value", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture arg_valueParam("arg_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, arg_value, &arg_valueParam.value); - CaptureSetKernelArgSVMPointer_arg_value(isCallValid, kernel, arg_index, arg_value, - &arg_valueParam); - paramBuffer.addParam(std::move(arg_valueParam)); + CaptureSetKernelArgSVMPointer_arg_value(kernel, arg_index, arg_value, &arg_valueParam); } else { - ParamCapture arg_valueParam("arg_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &arg_valueParam.value); - paramBuffer.addParam(std::move(arg_valueParam)); } + paramBuffer.addParam(std::move(arg_valueParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5552,21 +5113,19 @@ CallCapture CaptureSetKernelExecInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TKernelExecInfo, param_namePacked); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, param_value, ¶m_valueParam.value); - CaptureSetKernelExecInfo_param_value(isCallValid, kernel, param_namePacked, - param_value_size, param_value, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureSetKernelExecInfo_param_value(kernel, param_namePacked, param_value_size, + param_value, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5594,100 +5153,88 @@ CallCapture CaptureEnqueueSVMFree(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("num_svm_pointers", ParamType::Tcl_uint, num_svm_pointers); + ParamCapture svm_pointersParam("svm_pointers", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture svm_pointersParam("svm_pointers", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, svm_pointers, &svm_pointersParam.value); - CaptureEnqueueSVMFree_svm_pointers( - isCallValid, command_queue, num_svm_pointers, svm_pointers, pfn_free_func, user_data, - num_events_in_wait_list, event_wait_list, event, &svm_pointersParam); - paramBuffer.addParam(std::move(svm_pointersParam)); + CaptureEnqueueSVMFree_svm_pointers(command_queue, num_svm_pointers, svm_pointers, + pfn_free_func, user_data, num_events_in_wait_list, + event_wait_list, event, &svm_pointersParam); } else { - ParamCapture svm_pointersParam("svm_pointers", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), &svm_pointersParam.value); - paramBuffer.addParam(std::move(svm_pointersParam)); } + paramBuffer.addParam(std::move(svm_pointersParam)); + ParamCapture pfn_free_funcParam("pfn_free_func", ParamType::Tcl_svm_free_callback_func_type); if (isCallValid) { - ParamCapture pfn_free_funcParam("pfn_free_func", - ParamType::Tcl_svm_free_callback_func_type); InitParamValue(ParamType::Tcl_svm_free_callback_func_type, pfn_free_func, &pfn_free_funcParam.value); - CaptureEnqueueSVMFree_pfn_free_func( - isCallValid, command_queue, num_svm_pointers, svm_pointers, pfn_free_func, user_data, - num_events_in_wait_list, event_wait_list, event, &pfn_free_funcParam); - paramBuffer.addParam(std::move(pfn_free_funcParam)); + CaptureEnqueueSVMFree_pfn_free_func(command_queue, num_svm_pointers, svm_pointers, + pfn_free_func, user_data, num_events_in_wait_list, + event_wait_list, event, &pfn_free_funcParam); } else { - ParamCapture pfn_free_funcParam("pfn_free_func", - ParamType::Tcl_svm_free_callback_func_type); InitParamValue( ParamType::Tcl_svm_free_callback_func_type, static_cast(nullptr), &pfn_free_funcParam.value); - paramBuffer.addParam(std::move(pfn_free_funcParam)); } + paramBuffer.addParam(std::move(pfn_free_funcParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureEnqueueSVMFree_user_data(isCallValid, command_queue, num_svm_pointers, svm_pointers, + CaptureEnqueueSVMFree_user_data(command_queue, num_svm_pointers, svm_pointers, pfn_free_func, user_data, num_events_in_wait_list, event_wait_list, event, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueSVMFree_event_wait_list( - isCallValid, command_queue, num_svm_pointers, svm_pointers, pfn_free_func, user_data, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueSVMFree_event_wait_list(command_queue, num_svm_pointers, svm_pointers, + pfn_free_func, user_data, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueSVMFree_event(isCallValid, command_queue, num_svm_pointers, svm_pointers, - pfn_free_func, user_data, num_events_in_wait_list, - event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueSVMFree_event(command_queue, num_svm_pointers, svm_pointers, pfn_free_func, + user_data, num_events_in_wait_list, event_wait_list, event, + &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5712,77 +5259,68 @@ CallCapture CaptureEnqueueSVMMemcpy(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("blocking_copy", ParamType::Tcl_bool, blocking_copy); + ParamCapture dst_ptrParam("dst_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture dst_ptrParam("dst_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, dst_ptr, &dst_ptrParam.value); - CaptureEnqueueSVMMemcpy_dst_ptr(isCallValid, command_queue, blocking_copy, dst_ptr, src_ptr, - size, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueSVMMemcpy_dst_ptr(command_queue, blocking_copy, dst_ptr, src_ptr, size, + num_events_in_wait_list, event_wait_list, event, &dst_ptrParam); - paramBuffer.addParam(std::move(dst_ptrParam)); } else { - ParamCapture dst_ptrParam("dst_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &dst_ptrParam.value); - paramBuffer.addParam(std::move(dst_ptrParam)); } + paramBuffer.addParam(std::move(dst_ptrParam)); + ParamCapture src_ptrParam("src_ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture src_ptrParam("src_ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, src_ptr, &src_ptrParam.value); - CaptureEnqueueSVMMemcpy_src_ptr(isCallValid, command_queue, blocking_copy, dst_ptr, src_ptr, - size, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueSVMMemcpy_src_ptr(command_queue, blocking_copy, dst_ptr, src_ptr, size, + num_events_in_wait_list, event_wait_list, event, &src_ptrParam); - paramBuffer.addParam(std::move(src_ptrParam)); } else { - ParamCapture src_ptrParam("src_ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &src_ptrParam.value); - paramBuffer.addParam(std::move(src_ptrParam)); } + paramBuffer.addParam(std::move(src_ptrParam)); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueSVMMemcpy_event_wait_list(isCallValid, command_queue, blocking_copy, dst_ptr, - src_ptr, size, num_events_in_wait_list, - event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueSVMMemcpy_event_wait_list(command_queue, blocking_copy, dst_ptr, src_ptr, + size, num_events_in_wait_list, event_wait_list, + event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueSVMMemcpy_event(isCallValid, command_queue, blocking_copy, dst_ptr, src_ptr, - size, num_events_in_wait_list, event_wait_list, event, - &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueSVMMemcpy_event(command_queue, blocking_copy, dst_ptr, src_ptr, size, + num_events_in_wait_list, event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5806,78 +5344,70 @@ CallCapture CaptureEnqueueSVMMemFill(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); + ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, svm_ptr, &svm_ptrParam.value); - CaptureEnqueueSVMMemFill_svm_ptr(isCallValid, command_queue, svm_ptr, pattern, pattern_size, - size, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueSVMMemFill_svm_ptr(command_queue, svm_ptr, pattern, pattern_size, size, + num_events_in_wait_list, event_wait_list, event, &svm_ptrParam); - paramBuffer.addParam(std::move(svm_ptrParam)); } else { - ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &svm_ptrParam.value); - paramBuffer.addParam(std::move(svm_ptrParam)); } + paramBuffer.addParam(std::move(svm_ptrParam)); + ParamCapture patternParam("pattern", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture patternParam("pattern", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pattern, &patternParam.value); - CaptureEnqueueSVMMemFill_pattern(isCallValid, command_queue, svm_ptr, pattern, pattern_size, - size, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueSVMMemFill_pattern(command_queue, svm_ptr, pattern, pattern_size, size, + num_events_in_wait_list, event_wait_list, event, &patternParam); - paramBuffer.addParam(std::move(patternParam)); } else { - ParamCapture patternParam("pattern", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &patternParam.value); - paramBuffer.addParam(std::move(patternParam)); } + paramBuffer.addParam(std::move(patternParam)); paramBuffer.addValueParam("pattern_size", ParamType::Tsize_t, pattern_size); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueSVMMemFill_event_wait_list(isCallValid, command_queue, svm_ptr, pattern, - pattern_size, size, num_events_in_wait_list, - event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueSVMMemFill_event_wait_list(command_queue, svm_ptr, pattern, pattern_size, + size, num_events_in_wait_list, event_wait_list, + event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueSVMMemFill_event(isCallValid, command_queue, svm_ptr, pattern, pattern_size, - size, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueSVMMemFill_event(command_queue, svm_ptr, pattern, pattern_size, size, + num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5903,60 +5433,53 @@ CallCapture CaptureEnqueueSVMMap(bool isCallValid, paramBuffer.addValueParam("blocking_map", ParamType::Tcl_bool, blocking_map); paramBuffer.addValueParam("flagsPacked", ParamType::TMapFlags, flagsPacked); + ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, svm_ptr, &svm_ptrParam.value); - CaptureEnqueueSVMMap_svm_ptr(isCallValid, command_queue, blocking_map, flagsPacked, svm_ptr, - size, num_events_in_wait_list, event_wait_list, event, + CaptureEnqueueSVMMap_svm_ptr(command_queue, blocking_map, flagsPacked, svm_ptr, size, + num_events_in_wait_list, event_wait_list, event, &svm_ptrParam); - paramBuffer.addParam(std::move(svm_ptrParam)); } else { - ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &svm_ptrParam.value); - paramBuffer.addParam(std::move(svm_ptrParam)); } + paramBuffer.addParam(std::move(svm_ptrParam)); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueSVMMap_event_wait_list(isCallValid, command_queue, blocking_map, flagsPacked, - svm_ptr, size, num_events_in_wait_list, - event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueSVMMap_event_wait_list(command_queue, blocking_map, flagsPacked, svm_ptr, + size, num_events_in_wait_list, event_wait_list, event, + &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueSVMMap_event(isCallValid, command_queue, blocking_map, flagsPacked, svm_ptr, - size, num_events_in_wait_list, event_wait_list, event, - &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueSVMMap_event(command_queue, blocking_map, flagsPacked, svm_ptr, size, + num_events_in_wait_list, event_wait_list, event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -5977,57 +5500,50 @@ CallCapture CaptureEnqueueSVMUnmap(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); + ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, svm_ptr, &svm_ptrParam.value); - CaptureEnqueueSVMUnmap_svm_ptr(isCallValid, command_queue, svm_ptr, num_events_in_wait_list, + CaptureEnqueueSVMUnmap_svm_ptr(command_queue, svm_ptr, num_events_in_wait_list, event_wait_list, event, &svm_ptrParam); - paramBuffer.addParam(std::move(svm_ptrParam)); } else { - ParamCapture svm_ptrParam("svm_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &svm_ptrParam.value); - paramBuffer.addParam(std::move(svm_ptrParam)); } + paramBuffer.addParam(std::move(svm_ptrParam)); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueSVMUnmap_event_wait_list(isCallValid, command_queue, svm_ptr, - num_events_in_wait_list, event_wait_list, event, - &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueSVMUnmap_event_wait_list(command_queue, svm_ptr, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueSVMUnmap_event(isCallValid, command_queue, svm_ptr, num_events_in_wait_list, + CaptureEnqueueSVMUnmap_event(command_queue, svm_ptr, num_events_in_wait_list, event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6066,37 +5582,33 @@ CallCapture CaptureGetDeviceAndHostTimer(bool isCallValid, paramBuffer.addValueParam("device", ParamType::Tcl_device_id, device); + ParamCapture device_timestampParam("device_timestamp", ParamType::Tcl_ulongPointer); if (isCallValid) { - ParamCapture device_timestampParam("device_timestamp", ParamType::Tcl_ulongPointer); InitParamValue(ParamType::Tcl_ulongPointer, device_timestamp, &device_timestampParam.value); - CaptureGetDeviceAndHostTimer_device_timestamp(isCallValid, device, device_timestamp, - host_timestamp, &device_timestampParam); - paramBuffer.addParam(std::move(device_timestampParam)); + CaptureGetDeviceAndHostTimer_device_timestamp(device, device_timestamp, host_timestamp, + &device_timestampParam); } else { - ParamCapture device_timestampParam("device_timestamp", ParamType::Tcl_ulongPointer); InitParamValue(ParamType::Tcl_ulongPointer, static_cast(nullptr), &device_timestampParam.value); - paramBuffer.addParam(std::move(device_timestampParam)); } + paramBuffer.addParam(std::move(device_timestampParam)); + ParamCapture host_timestampParam("host_timestamp", ParamType::Tcl_ulongPointer); if (isCallValid) { - ParamCapture host_timestampParam("host_timestamp", ParamType::Tcl_ulongPointer); InitParamValue(ParamType::Tcl_ulongPointer, host_timestamp, &host_timestampParam.value); - CaptureGetDeviceAndHostTimer_host_timestamp(isCallValid, device, device_timestamp, - host_timestamp, &host_timestampParam); - paramBuffer.addParam(std::move(host_timestampParam)); + CaptureGetDeviceAndHostTimer_host_timestamp(device, device_timestamp, host_timestamp, + &host_timestampParam); } else { - ParamCapture host_timestampParam("host_timestamp", ParamType::Tcl_ulongPointer); InitParamValue(ParamType::Tcl_ulongPointer, static_cast(nullptr), &host_timestampParam.value); - paramBuffer.addParam(std::move(host_timestampParam)); } + paramBuffer.addParam(std::move(host_timestampParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6114,21 +5626,18 @@ CallCapture CaptureGetHostTimer(bool isCallValid, paramBuffer.addValueParam("device", ParamType::Tcl_device_id, device); + ParamCapture host_timestampParam("host_timestamp", ParamType::Tcl_ulongPointer); if (isCallValid) { - ParamCapture host_timestampParam("host_timestamp", ParamType::Tcl_ulongPointer); InitParamValue(ParamType::Tcl_ulongPointer, host_timestamp, &host_timestampParam.value); - CaptureGetHostTimer_host_timestamp(isCallValid, device, host_timestamp, - &host_timestampParam); - paramBuffer.addParam(std::move(host_timestampParam)); + CaptureGetHostTimer_host_timestamp(device, host_timestamp, &host_timestampParam); } else { - ParamCapture host_timestampParam("host_timestamp", ParamType::Tcl_ulongPointer); InitParamValue(ParamType::Tcl_ulongPointer, static_cast(nullptr), &host_timestampParam.value); - paramBuffer.addParam(std::move(host_timestampParam)); } + paramBuffer.addParam(std::move(host_timestampParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6148,38 +5657,33 @@ CallCapture CaptureCreateProgramWithIL(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture ilParam("il", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ilParam("il", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, il, &ilParam.value); - CaptureCreateProgramWithIL_il(isCallValid, context, il, length, errcode_ret, &ilParam); - paramBuffer.addParam(std::move(ilParam)); + CaptureCreateProgramWithIL_il(context, il, length, errcode_ret, &ilParam); } else { - ParamCapture ilParam("il", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ilParam.value); - paramBuffer.addParam(std::move(ilParam)); } + paramBuffer.addParam(std::move(ilParam)); paramBuffer.addValueParam("length", ParamType::Tsize_t, length); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateProgramWithIL_errcode_ret(isCallValid, context, il, length, errcode_ret, - &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateProgramWithIL_errcode_ret(context, il, length, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_program); InitParamValue(ParamType::Tcl_program, returnValue, &returnValueCapture.value); @@ -6197,20 +5701,18 @@ CallCapture CaptureCloneKernel(bool isCallValid, paramBuffer.addValueParam("source_kernel", ParamType::Tcl_kernel, source_kernel); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCloneKernel_errcode_ret(isCallValid, source_kernel, errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCloneKernel_errcode_ret(source_kernel, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_kernel); InitParamValue(ParamType::Tcl_kernel, returnValue, &returnValueCapture.value); @@ -6237,59 +5739,53 @@ CallCapture CaptureGetKernelSubGroupInfo(bool isCallValid, paramBuffer.addValueParam("param_namePacked", ParamType::TKernelSubGroupInfo, param_namePacked); paramBuffer.addValueParam("input_value_size", ParamType::Tsize_t, input_value_size); + ParamCapture input_valueParam("input_value", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture input_valueParam("input_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, input_value, &input_valueParam.value); - CaptureGetKernelSubGroupInfo_input_value( - isCallValid, kernel, device, param_namePacked, input_value_size, input_value, - param_value_size, param_value, param_value_size_ret, &input_valueParam); - paramBuffer.addParam(std::move(input_valueParam)); + CaptureGetKernelSubGroupInfo_input_value(kernel, device, param_namePacked, input_value_size, + input_value, param_value_size, param_value, + param_value_size_ret, &input_valueParam); } else { - ParamCapture input_valueParam("input_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &input_valueParam.value); - paramBuffer.addParam(std::move(input_valueParam)); } + paramBuffer.addParam(std::move(input_valueParam)); paramBuffer.addValueParam("param_value_size", ParamType::Tsize_t, param_value_size); + ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, param_value, ¶m_valueParam.value); - CaptureGetKernelSubGroupInfo_param_value( - isCallValid, kernel, device, param_namePacked, input_value_size, input_value, - param_value_size, param_value, param_value_size_ret, ¶m_valueParam); - paramBuffer.addParam(std::move(param_valueParam)); + CaptureGetKernelSubGroupInfo_param_value(kernel, device, param_namePacked, input_value_size, + input_value, param_value_size, param_value, + param_value_size_ret, ¶m_valueParam); } else { - ParamCapture param_valueParam("param_value", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), ¶m_valueParam.value); - paramBuffer.addParam(std::move(param_valueParam)); } + paramBuffer.addParam(std::move(param_valueParam)); + ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); if (isCallValid) { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, param_value_size_ret, ¶m_value_size_retParam.value); CaptureGetKernelSubGroupInfo_param_value_size_ret( - isCallValid, kernel, device, param_namePacked, input_value_size, input_value, - param_value_size, param_value, param_value_size_ret, ¶m_value_size_retParam); - paramBuffer.addParam(std::move(param_value_size_retParam)); + kernel, device, param_namePacked, input_value_size, input_value, param_value_size, + param_value, param_value_size_ret, ¶m_value_size_retParam); } else { - ParamCapture param_value_size_retParam("param_value_size_ret", ParamType::Tsize_tPointer); InitParamValue(ParamType::Tsize_tPointer, static_cast(nullptr), ¶m_value_size_retParam.value); - paramBuffer.addParam(std::move(param_value_size_retParam)); } + paramBuffer.addParam(std::move(param_value_size_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6314,78 +5810,70 @@ CallCapture CaptureEnqueueSVMMigrateMem(bool isCallValid, paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); paramBuffer.addValueParam("num_svm_pointers", ParamType::Tcl_uint, num_svm_pointers); + ParamCapture svm_pointersParam("svm_pointers", ParamType::TvoidConstPointerPointer); if (isCallValid) { - ParamCapture svm_pointersParam("svm_pointers", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, svm_pointers, &svm_pointersParam.value); - CaptureEnqueueSVMMigrateMem_svm_pointers( - isCallValid, command_queue, num_svm_pointers, svm_pointers, sizes, flagsPacked, - num_events_in_wait_list, event_wait_list, event, &svm_pointersParam); - paramBuffer.addParam(std::move(svm_pointersParam)); + CaptureEnqueueSVMMigrateMem_svm_pointers(command_queue, num_svm_pointers, svm_pointers, + sizes, flagsPacked, num_events_in_wait_list, + event_wait_list, event, &svm_pointersParam); } else { - ParamCapture svm_pointersParam("svm_pointers", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, static_cast(nullptr), &svm_pointersParam.value); - paramBuffer.addParam(std::move(svm_pointersParam)); } + paramBuffer.addParam(std::move(svm_pointersParam)); + ParamCapture sizesParam("sizes", ParamType::Tsize_tConstPointer); if (isCallValid) { - ParamCapture sizesParam("sizes", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, sizes, &sizesParam.value); - CaptureEnqueueSVMMigrateMem_sizes(isCallValid, command_queue, num_svm_pointers, - svm_pointers, sizes, flagsPacked, num_events_in_wait_list, - event_wait_list, event, &sizesParam); - paramBuffer.addParam(std::move(sizesParam)); + CaptureEnqueueSVMMigrateMem_sizes(command_queue, num_svm_pointers, svm_pointers, sizes, + flagsPacked, num_events_in_wait_list, event_wait_list, + event, &sizesParam); } else { - ParamCapture sizesParam("sizes", ParamType::Tsize_tConstPointer); InitParamValue(ParamType::Tsize_tConstPointer, static_cast(nullptr), &sizesParam.value); - paramBuffer.addParam(std::move(sizesParam)); } + paramBuffer.addParam(std::move(sizesParam)); paramBuffer.addValueParam("flagsPacked", ParamType::TMemMigrationFlags, flagsPacked); paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, num_events_in_wait_list); + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); if (isCallValid) { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, &event_wait_listParam.value); - CaptureEnqueueSVMMigrateMem_event_wait_list( - isCallValid, command_queue, num_svm_pointers, svm_pointers, sizes, flagsPacked, - num_events_in_wait_list, event_wait_list, event, &event_wait_listParam); - paramBuffer.addParam(std::move(event_wait_listParam)); + CaptureEnqueueSVMMigrateMem_event_wait_list(command_queue, num_svm_pointers, svm_pointers, + sizes, flagsPacked, num_events_in_wait_list, + event_wait_list, event, &event_wait_listParam); } else { - ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), &event_wait_listParam.value); - paramBuffer.addParam(std::move(event_wait_listParam)); } + paramBuffer.addParam(std::move(event_wait_listParam)); + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); if (isCallValid) { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); - CaptureEnqueueSVMMigrateMem_event(isCallValid, command_queue, num_svm_pointers, - svm_pointers, sizes, flagsPacked, num_events_in_wait_list, - event_wait_list, event, &eventParam); - paramBuffer.addParam(std::move(eventParam)); + CaptureEnqueueSVMMigrateMem_event(command_queue, num_svm_pointers, svm_pointers, sizes, + flagsPacked, num_events_in_wait_list, event_wait_list, + event, &eventParam); } else { - ParamCapture eventParam("event", ParamType::Tcl_eventPointer); InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), &eventParam.value); - paramBuffer.addParam(std::move(eventParam)); } + paramBuffer.addParam(std::move(eventParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6406,39 +5894,34 @@ CallCapture CaptureSetProgramReleaseCallback(bool isCallValid, paramBuffer.addValueParam("program", ParamType::Tcl_program, program); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue(ParamType::Tcl_program_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureSetProgramReleaseCallback_pfn_notify(isCallValid, program, pfn_notify, user_data, + CaptureSetProgramReleaseCallback_pfn_notify(program, pfn_notify, user_data, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_program_func_type); InitParamValue( ParamType::Tcl_program_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureSetProgramReleaseCallback_user_data(isCallValid, program, pfn_notify, user_data, - &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); + CaptureSetProgramReleaseCallback_user_data(program, pfn_notify, user_data, &user_dataParam); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6460,21 +5943,19 @@ CallCapture CaptureSetProgramSpecializationConstant(bool isCallValid, paramBuffer.addValueParam("spec_id", ParamType::Tcl_uint, spec_id); paramBuffer.addValueParam("spec_size", ParamType::Tsize_t, spec_size); + ParamCapture spec_valueParam("spec_value", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture spec_valueParam("spec_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, spec_value, &spec_valueParam.value); - CaptureSetProgramSpecializationConstant_spec_value(isCallValid, program, spec_id, spec_size, - spec_value, &spec_valueParam); - paramBuffer.addParam(std::move(spec_valueParam)); + CaptureSetProgramSpecializationConstant_spec_value(program, spec_id, spec_size, spec_value, + &spec_valueParam); } else { - ParamCapture spec_valueParam("spec_value", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &spec_valueParam.value); - paramBuffer.addParam(std::move(spec_valueParam)); } + paramBuffer.addParam(std::move(spec_valueParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6496,40 +5977,36 @@ CallCapture CaptureSetContextDestructorCallback(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_destructor_func_type); if (isCallValid) { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_destructor_func_type); InitParamValue(ParamType::Tcl_context_destructor_func_type, pfn_notify, &pfn_notifyParam.value); - CaptureSetContextDestructorCallback_pfn_notify(isCallValid, context, pfn_notify, user_data, + CaptureSetContextDestructorCallback_pfn_notify(context, pfn_notify, user_data, &pfn_notifyParam); - paramBuffer.addParam(std::move(pfn_notifyParam)); } else { - ParamCapture pfn_notifyParam("pfn_notify", ParamType::Tcl_context_destructor_func_type); InitParamValue( ParamType::Tcl_context_destructor_func_type, static_cast(nullptr), &pfn_notifyParam.value); - paramBuffer.addParam(std::move(pfn_notifyParam)); } + paramBuffer.addParam(std::move(pfn_notifyParam)); + ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, user_data, &user_dataParam.value); - CaptureSetContextDestructorCallback_user_data(isCallValid, context, pfn_notify, user_data, + CaptureSetContextDestructorCallback_user_data(context, pfn_notify, user_data, &user_dataParam); - paramBuffer.addParam(std::move(user_dataParam)); } else { - ParamCapture user_dataParam("user_data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &user_dataParam.value); - paramBuffer.addParam(std::move(user_dataParam)); } + paramBuffer.addParam(std::move(user_dataParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6551,57 +6028,50 @@ CallCapture CaptureCreateBufferWithProperties(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture propertiesParam("properties", ParamType::Tcl_mem_propertiesConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", ParamType::Tcl_mem_propertiesConstPointer); InitParamValue(ParamType::Tcl_mem_propertiesConstPointer, properties, &propertiesParam.value); - CaptureCreateBufferWithProperties_properties(isCallValid, context, properties, flagsPacked, - size, host_ptr, errcode_ret, &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); + CaptureCreateBufferWithProperties_properties(context, properties, flagsPacked, size, + host_ptr, errcode_ret, &propertiesParam); } else { - ParamCapture propertiesParam("properties", ParamType::Tcl_mem_propertiesConstPointer); InitParamValue(ParamType::Tcl_mem_propertiesConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); paramBuffer.addValueParam("size", ParamType::Tsize_t, size); + ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, host_ptr, &host_ptrParam.value); - CaptureCreateBufferWithProperties_host_ptr(isCallValid, context, properties, flagsPacked, - size, host_ptr, errcode_ret, &host_ptrParam); - paramBuffer.addParam(std::move(host_ptrParam)); + CaptureCreateBufferWithProperties_host_ptr(context, properties, flagsPacked, size, host_ptr, + errcode_ret, &host_ptrParam); } else { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &host_ptrParam.value); - paramBuffer.addParam(std::move(host_ptrParam)); } + paramBuffer.addParam(std::move(host_ptrParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateBufferWithProperties_errcode_ret(isCallValid, context, properties, flagsPacked, - size, host_ptr, errcode_ret, - &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateBufferWithProperties_errcode_ret(context, properties, flagsPacked, size, + host_ptr, errcode_ret, &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -6624,93 +6094,83 @@ CallCapture CaptureCreateImageWithProperties(bool isCallValid, paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + ParamCapture propertiesParam("properties", ParamType::Tcl_mem_propertiesConstPointer); if (isCallValid) { - ParamCapture propertiesParam("properties", ParamType::Tcl_mem_propertiesConstPointer); InitParamValue(ParamType::Tcl_mem_propertiesConstPointer, properties, &propertiesParam.value); - CaptureCreateImageWithProperties_properties(isCallValid, context, properties, flagsPacked, - image_format, image_desc, host_ptr, errcode_ret, + CaptureCreateImageWithProperties_properties(context, properties, flagsPacked, image_format, + image_desc, host_ptr, errcode_ret, &propertiesParam); - paramBuffer.addParam(std::move(propertiesParam)); } else { - ParamCapture propertiesParam("properties", ParamType::Tcl_mem_propertiesConstPointer); InitParamValue(ParamType::Tcl_mem_propertiesConstPointer, static_cast(nullptr), &propertiesParam.value); - paramBuffer.addParam(std::move(propertiesParam)); } + paramBuffer.addParam(std::move(propertiesParam)); paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); + ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); if (isCallValid) { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, image_format, &image_formatParam.value); - CaptureCreateImageWithProperties_image_format(isCallValid, context, properties, flagsPacked, + CaptureCreateImageWithProperties_image_format(context, properties, flagsPacked, image_format, image_desc, host_ptr, errcode_ret, &image_formatParam); - paramBuffer.addParam(std::move(image_formatParam)); } else { - ParamCapture image_formatParam("image_format", ParamType::Tcl_image_formatConstPointer); InitParamValue(ParamType::Tcl_image_formatConstPointer, static_cast(nullptr), &image_formatParam.value); - paramBuffer.addParam(std::move(image_formatParam)); } + paramBuffer.addParam(std::move(image_formatParam)); + ParamCapture image_descParam("image_desc", ParamType::Tcl_image_descConstPointer); if (isCallValid) { - ParamCapture image_descParam("image_desc", ParamType::Tcl_image_descConstPointer); InitParamValue(ParamType::Tcl_image_descConstPointer, image_desc, &image_descParam.value); - CaptureCreateImageWithProperties_image_desc(isCallValid, context, properties, flagsPacked, - image_format, image_desc, host_ptr, errcode_ret, + CaptureCreateImageWithProperties_image_desc(context, properties, flagsPacked, image_format, + image_desc, host_ptr, errcode_ret, &image_descParam); - paramBuffer.addParam(std::move(image_descParam)); } else { - ParamCapture image_descParam("image_desc", ParamType::Tcl_image_descConstPointer); InitParamValue(ParamType::Tcl_image_descConstPointer, static_cast(nullptr), &image_descParam.value); - paramBuffer.addParam(std::move(image_descParam)); } + paramBuffer.addParam(std::move(image_descParam)); + ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, host_ptr, &host_ptrParam.value); - CaptureCreateImageWithProperties_host_ptr(isCallValid, context, properties, flagsPacked, - image_format, image_desc, host_ptr, errcode_ret, + CaptureCreateImageWithProperties_host_ptr(context, properties, flagsPacked, image_format, + image_desc, host_ptr, errcode_ret, &host_ptrParam); - paramBuffer.addParam(std::move(host_ptrParam)); } else { - ParamCapture host_ptrParam("host_ptr", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &host_ptrParam.value); - paramBuffer.addParam(std::move(host_ptrParam)); } + paramBuffer.addParam(std::move(host_ptrParam)); + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); if (isCallValid) { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); - CaptureCreateImageWithProperties_errcode_ret(isCallValid, context, properties, flagsPacked, - image_format, image_desc, host_ptr, - errcode_ret, &errcode_retParam); - paramBuffer.addParam(std::move(errcode_retParam)); + CaptureCreateImageWithProperties_errcode_ret(context, properties, flagsPacked, image_format, + image_desc, host_ptr, errcode_ret, + &errcode_retParam); } else { - ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), &errcode_retParam.value); - paramBuffer.addParam(std::move(errcode_retParam)); } + paramBuffer.addParam(std::move(errcode_retParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); @@ -6719,6 +6179,216 @@ CallCapture CaptureCreateImageWithProperties(bool isCallValid, return CallCapture(angle::EntryPoint::CLCreateImageWithProperties, std::move(paramBuffer)); } +// cl_arm_import_memory +CallCapture CaptureImportMemoryARM(bool isCallValid, + cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + cl_mem returnValue) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("context", ParamType::Tcl_context, context); + paramBuffer.addValueParam("flagsPacked", ParamType::TMemFlags, flagsPacked); + + ParamCapture propertiesParam("properties", ParamType::Tcl_import_properties_armConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_import_properties_armConstPointer, properties, + &propertiesParam.value); + CaptureImportMemoryARM_properties(context, flagsPacked, properties, memory, size, + errcode_ret, &propertiesParam); + } + else + { + InitParamValue(ParamType::Tcl_import_properties_armConstPointer, + static_cast(nullptr), + &propertiesParam.value); + } + paramBuffer.addParam(std::move(propertiesParam)); + + ParamCapture memoryParam("memory", ParamType::TvoidPointer); + if (isCallValid) + { + InitParamValue(ParamType::TvoidPointer, memory, &memoryParam.value); + CaptureImportMemoryARM_memory(context, flagsPacked, properties, memory, size, errcode_ret, + &memoryParam); + } + else + { + InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &memoryParam.value); + } + paramBuffer.addParam(std::move(memoryParam)); + + paramBuffer.addValueParam("size", ParamType::Tsize_t, size); + + ParamCapture errcode_retParam("errcode_ret", ParamType::Tcl_intPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_intPointer, errcode_ret, &errcode_retParam.value); + CaptureImportMemoryARM_errcode_ret(context, flagsPacked, properties, memory, size, + errcode_ret, &errcode_retParam); + } + else + { + InitParamValue(ParamType::Tcl_intPointer, static_cast(nullptr), + &errcode_retParam.value); + } + paramBuffer.addParam(std::move(errcode_retParam)); + + ParamCapture returnValueCapture("returnValue", ParamType::Tcl_mem); + InitParamValue(ParamType::Tcl_mem, returnValue, &returnValueCapture.value); + paramBuffer.addReturnValue(std::move(returnValueCapture)); + + return CallCapture(angle::EntryPoint::CLImportMemoryARM, std::move(paramBuffer)); +} + +// cl_khr_external_memory +CallCapture CaptureEnqueueAcquireExternalMemObjectsKHR(bool isCallValid, + cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int returnValue) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); + paramBuffer.addValueParam("num_mem_objects", ParamType::Tcl_uint, num_mem_objects); + + ParamCapture mem_objectsParam("mem_objects", ParamType::Tcl_memConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_memConstPointer, mem_objects, &mem_objectsParam.value); + CaptureEnqueueAcquireExternalMemObjectsKHR_mem_objects( + command_queue, num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, + event, &mem_objectsParam); + } + else + { + InitParamValue(ParamType::Tcl_memConstPointer, static_cast(nullptr), + &mem_objectsParam.value); + } + paramBuffer.addParam(std::move(mem_objectsParam)); + + paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, + num_events_in_wait_list); + + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, + &event_wait_listParam.value); + CaptureEnqueueAcquireExternalMemObjectsKHR_event_wait_list( + command_queue, num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, + event, &event_wait_listParam); + } + else + { + InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), + &event_wait_listParam.value); + } + paramBuffer.addParam(std::move(event_wait_listParam)); + + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); + CaptureEnqueueAcquireExternalMemObjectsKHR_event(command_queue, num_mem_objects, + mem_objects, num_events_in_wait_list, + event_wait_list, event, &eventParam); + } + else + { + InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), + &eventParam.value); + } + paramBuffer.addParam(std::move(eventParam)); + + ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); + InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); + paramBuffer.addReturnValue(std::move(returnValueCapture)); + + return CallCapture(angle::EntryPoint::CLEnqueueAcquireExternalMemObjectsKHR, + std::move(paramBuffer)); +} + +CallCapture CaptureEnqueueReleaseExternalMemObjectsKHR(bool isCallValid, + cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int returnValue) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("command_queue", ParamType::Tcl_command_queue, command_queue); + paramBuffer.addValueParam("num_mem_objects", ParamType::Tcl_uint, num_mem_objects); + + ParamCapture mem_objectsParam("mem_objects", ParamType::Tcl_memConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_memConstPointer, mem_objects, &mem_objectsParam.value); + CaptureEnqueueReleaseExternalMemObjectsKHR_mem_objects( + command_queue, num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, + event, &mem_objectsParam); + } + else + { + InitParamValue(ParamType::Tcl_memConstPointer, static_cast(nullptr), + &mem_objectsParam.value); + } + paramBuffer.addParam(std::move(mem_objectsParam)); + + paramBuffer.addValueParam("num_events_in_wait_list", ParamType::Tcl_uint, + num_events_in_wait_list); + + ParamCapture event_wait_listParam("event_wait_list", ParamType::Tcl_eventConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_eventConstPointer, event_wait_list, + &event_wait_listParam.value); + CaptureEnqueueReleaseExternalMemObjectsKHR_event_wait_list( + command_queue, num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, + event, &event_wait_listParam); + } + else + { + InitParamValue(ParamType::Tcl_eventConstPointer, static_cast(nullptr), + &event_wait_listParam.value); + } + paramBuffer.addParam(std::move(event_wait_listParam)); + + ParamCapture eventParam("event", ParamType::Tcl_eventPointer); + if (isCallValid) + { + InitParamValue(ParamType::Tcl_eventPointer, event, &eventParam.value); + CaptureEnqueueReleaseExternalMemObjectsKHR_event(command_queue, num_mem_objects, + mem_objects, num_events_in_wait_list, + event_wait_list, event, &eventParam); + } + else + { + InitParamValue(ParamType::Tcl_eventPointer, static_cast(nullptr), + &eventParam.value); + } + paramBuffer.addParam(std::move(eventParam)); + + ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); + InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); + paramBuffer.addReturnValue(std::move(returnValueCapture)); + + return CallCapture(angle::EntryPoint::CLEnqueueReleaseExternalMemObjectsKHR, + std::move(paramBuffer)); +} + // cl_khr_icd CallCapture CaptureIcdGetPlatformIDsKHR(bool isCallValid, cl_uint num_entries, @@ -6730,37 +6400,33 @@ CallCapture CaptureIcdGetPlatformIDsKHR(bool isCallValid, paramBuffer.addValueParam("num_entries", ParamType::Tcl_uint, num_entries); + ParamCapture platformsParam("platforms", ParamType::Tcl_platform_idPointer); if (isCallValid) { - ParamCapture platformsParam("platforms", ParamType::Tcl_platform_idPointer); InitParamValue(ParamType::Tcl_platform_idPointer, platforms, &platformsParam.value); - CaptureIcdGetPlatformIDsKHR_platforms(isCallValid, num_entries, platforms, num_platforms, + CaptureIcdGetPlatformIDsKHR_platforms(num_entries, platforms, num_platforms, &platformsParam); - paramBuffer.addParam(std::move(platformsParam)); } else { - ParamCapture platformsParam("platforms", ParamType::Tcl_platform_idPointer); InitParamValue(ParamType::Tcl_platform_idPointer, static_cast(nullptr), &platformsParam.value); - paramBuffer.addParam(std::move(platformsParam)); } + paramBuffer.addParam(std::move(platformsParam)); + ParamCapture num_platformsParam("num_platforms", ParamType::Tcl_uintPointer); if (isCallValid) { - ParamCapture num_platformsParam("num_platforms", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, num_platforms, &num_platformsParam.value); - CaptureIcdGetPlatformIDsKHR_num_platforms(isCallValid, num_entries, platforms, - num_platforms, &num_platformsParam); - paramBuffer.addParam(std::move(num_platformsParam)); + CaptureIcdGetPlatformIDsKHR_num_platforms(num_entries, platforms, num_platforms, + &num_platformsParam); } else { - ParamCapture num_platformsParam("num_platforms", ParamType::Tcl_uintPointer); InitParamValue(ParamType::Tcl_uintPointer, static_cast(nullptr), &num_platformsParam.value); - paramBuffer.addParam(std::move(num_platformsParam)); } + paramBuffer.addParam(std::move(num_platformsParam)); ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); @@ -6769,4 +6435,64 @@ CallCapture CaptureIcdGetPlatformIDsKHR(bool isCallValid, return CallCapture(angle::EntryPoint::CLIcdGetPlatformIDsKHR, std::move(paramBuffer)); } +CallCapture CaptureIcdGetFunctionAddressForPlatformKHR(bool isCallValid, + cl_platform_id platform, + const char *func_name, + void *returnValue) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("platform", ParamType::Tcl_platform_id, platform); + + ParamCapture func_nameParam("func_name", ParamType::TcharConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::TcharConstPointer, func_name, &func_nameParam.value); + CaptureIcdGetFunctionAddressForPlatformKHR_func_name(platform, func_name, &func_nameParam); + } + else + { + InitParamValue(ParamType::TcharConstPointer, static_cast(nullptr), + &func_nameParam.value); + } + paramBuffer.addParam(std::move(func_nameParam)); + + ParamCapture returnValueCapture("returnValue", ParamType::TvoidPointer); + InitParamValue(ParamType::TvoidPointer, returnValue, &returnValueCapture.value); + paramBuffer.addReturnValue(std::move(returnValueCapture)); + + return CallCapture(angle::EntryPoint::CLIcdGetFunctionAddressForPlatformKHR, + std::move(paramBuffer)); +} + +CallCapture CaptureIcdSetPlatformDispatchDataKHR(bool isCallValid, + cl_platform_id platform, + void *dispatch_data, + cl_int returnValue) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("platform", ParamType::Tcl_platform_id, platform); + + ParamCapture dispatch_dataParam("dispatch_data", ParamType::TvoidPointer); + if (isCallValid) + { + InitParamValue(ParamType::TvoidPointer, dispatch_data, &dispatch_dataParam.value); + CaptureIcdSetPlatformDispatchDataKHR_dispatch_data(platform, dispatch_data, + &dispatch_dataParam); + } + else + { + InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), + &dispatch_dataParam.value); + } + paramBuffer.addParam(std::move(dispatch_dataParam)); + + ParamCapture returnValueCapture("returnValue", ParamType::Tcl_int); + InitParamValue(ParamType::Tcl_int, returnValue, &returnValueCapture.value); + paramBuffer.addReturnValue(std::move(returnValueCapture)); + + return CallCapture(angle::EntryPoint::CLIcdSetPlatformDispatchDataKHR, std::move(paramBuffer)); +} + } // namespace cl diff --git a/src/libANGLE/capture/capture_cl_autogen.h b/src/libANGLE/capture/capture_cl_autogen.h index 18245d6569d..d8346811728 100644 --- a/src/libANGLE/capture/capture_cl_autogen.h +++ b/src/libANGLE/capture/capture_cl_autogen.h @@ -815,70 +815,97 @@ angle::CallCapture CaptureCreateImageWithProperties(bool isCallValid, cl_int *errcode_ret, cl_mem returnValue); +// cl_arm_import_memory +angle::CallCapture CaptureImportMemoryARM(bool isCallValid, + cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + cl_mem returnValue); + +// cl_khr_external_memory +angle::CallCapture CaptureEnqueueAcquireExternalMemObjectsKHR(bool isCallValid, + cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int returnValue); +angle::CallCapture CaptureEnqueueReleaseExternalMemObjectsKHR(bool isCallValid, + cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int returnValue); + // cl_khr_icd angle::CallCapture CaptureIcdGetPlatformIDsKHR(bool isCallValid, cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, cl_int returnValue); +angle::CallCapture CaptureIcdGetFunctionAddressForPlatformKHR(bool isCallValid, + cl_platform_id platform, + const char *func_name, + void *returnValue); +angle::CallCapture CaptureIcdSetPlatformDispatchDataKHR(bool isCallValid, + cl_platform_id platform, + void *dispatch_data, + cl_int returnValue); // Parameter Captures // CL 1.0 -void CaptureGetPlatformIDs_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureGetPlatformIDs_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture); -void CaptureGetPlatformIDs_num_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureGetPlatformIDs_num_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture); -void CaptureGetPlatformInfo_param_value(bool isCallValid, - cl_platform_id platform, +void CaptureGetPlatformInfo_param_value(cl_platform_id platform, PlatformInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetPlatformInfo_param_value_size_ret(bool isCallValid, - cl_platform_id platform, +void CaptureGetPlatformInfo_param_value_size_ret(cl_platform_id platform, PlatformInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetDeviceIDs_devices(bool isCallValid, - cl_platform_id platform, +void CaptureGetDeviceIDs_devices(cl_platform_id platform, DeviceType device_typePacked, cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices, angle::ParamCapture *paramCapture); -void CaptureGetDeviceIDs_num_devices(bool isCallValid, - cl_platform_id platform, +void CaptureGetDeviceIDs_num_devices(cl_platform_id platform, DeviceType device_typePacked, cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices, angle::ParamCapture *paramCapture); -void CaptureGetDeviceInfo_param_value(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceInfo_param_value(cl_device_id device, DeviceInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetDeviceInfo_param_value_size_ret(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceInfo_param_value_size_ret(cl_device_id device, DeviceInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContext_properties(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_properties(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -888,8 +915,7 @@ void CaptureCreateContext_properties(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContext_devices(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_devices(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -899,8 +925,7 @@ void CaptureCreateContext_devices(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContext_pfn_notify(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_pfn_notify(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -910,8 +935,7 @@ void CaptureCreateContext_pfn_notify(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContext_user_data(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_user_data(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -921,8 +945,7 @@ void CaptureCreateContext_user_data(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContext_errcode_ret(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_errcode_ret(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -932,8 +955,7 @@ void CaptureCreateContext_errcode_ret(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContextFromType_properties(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContextFromType_properties(const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, @@ -942,8 +964,7 @@ void CaptureCreateContextFromType_properties(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContextFromType_pfn_notify(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContextFromType_pfn_notify(const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, @@ -952,8 +973,7 @@ void CaptureCreateContextFromType_pfn_notify(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateContextFromType_user_data(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContextFromType_user_data(const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, @@ -963,7 +983,6 @@ void CaptureCreateContextFromType_user_data(bool isCallValid, cl_int *errcode_ret, angle::ParamCapture *paramCapture); void CaptureCreateContextFromType_errcode_ret( - bool isCallValid, const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -973,129 +992,111 @@ void CaptureCreateContextFromType_errcode_ret( void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureGetContextInfo_param_value(bool isCallValid, - cl_context context, +void CaptureGetContextInfo_param_value(cl_context context, ContextInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetContextInfo_param_value_size_ret(bool isCallValid, - cl_context context, +void CaptureGetContextInfo_param_value_size_ret(cl_context context, ContextInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetCommandQueueInfo_param_value(bool isCallValid, - cl_command_queue command_queue, +void CaptureGetCommandQueueInfo_param_value(cl_command_queue command_queue, CommandQueueInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetCommandQueueInfo_param_value_size_ret(bool isCallValid, - cl_command_queue command_queue, +void CaptureGetCommandQueueInfo_param_value_size_ret(cl_command_queue command_queue, CommandQueueInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureCreateBuffer_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateBuffer_host_ptr(cl_context context, MemFlags flagsPacked, size_t size, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateBuffer_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateBuffer_errcode_ret(cl_context context, MemFlags flagsPacked, size_t size, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureGetSupportedImageFormats_image_formats(bool isCallValid, - cl_context context, +void CaptureGetSupportedImageFormats_image_formats(cl_context context, MemFlags flagsPacked, MemObjectType image_typePacked, cl_uint num_entries, cl_image_format *image_formats, cl_uint *num_image_formats, angle::ParamCapture *paramCapture); -void CaptureGetSupportedImageFormats_num_image_formats(bool isCallValid, - cl_context context, +void CaptureGetSupportedImageFormats_num_image_formats(cl_context context, MemFlags flagsPacked, MemObjectType image_typePacked, cl_uint num_entries, cl_image_format *image_formats, cl_uint *num_image_formats, angle::ParamCapture *paramCapture); -void CaptureGetMemObjectInfo_param_value(bool isCallValid, - cl_mem memobj, +void CaptureGetMemObjectInfo_param_value(cl_mem memobj, MemInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetMemObjectInfo_param_value_size_ret(bool isCallValid, - cl_mem memobj, +void CaptureGetMemObjectInfo_param_value_size_ret(cl_mem memobj, MemInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetImageInfo_param_value(bool isCallValid, - cl_mem image, +void CaptureGetImageInfo_param_value(cl_mem image, ImageInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetImageInfo_param_value_size_ret(bool isCallValid, - cl_mem image, +void CaptureGetImageInfo_param_value_size_ret(cl_mem image, ImageInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetSamplerInfo_param_value(bool isCallValid, - cl_sampler sampler, +void CaptureGetSamplerInfo_param_value(cl_sampler sampler, SamplerInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetSamplerInfo_param_value_size_ret(bool isCallValid, - cl_sampler sampler, +void CaptureGetSamplerInfo_param_value_size_ret(cl_sampler sampler, SamplerInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithSource_strings(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithSource_strings(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithSource_lengths(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithSource_lengths(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithSource_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithSource_errcode_ret(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBinary_device_list(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_device_list(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -1103,8 +1104,7 @@ void CaptureCreateProgramWithBinary_device_list(bool isCallValid, cl_int *binary_status, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBinary_lengths(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_lengths(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -1112,8 +1112,7 @@ void CaptureCreateProgramWithBinary_lengths(bool isCallValid, cl_int *binary_status, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBinary_binaries(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_binaries(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -1121,8 +1120,7 @@ void CaptureCreateProgramWithBinary_binaries(bool isCallValid, cl_int *binary_status, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBinary_binary_status(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_binary_status(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -1130,8 +1128,7 @@ void CaptureCreateProgramWithBinary_binary_status(bool isCallValid, cl_int *binary_status, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBinary_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_errcode_ret(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -1139,8 +1136,7 @@ void CaptureCreateProgramWithBinary_errcode_ret(bool isCallValid, cl_int *binary_status, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureBuildProgram_device_list(bool isCallValid, - cl_program program, +void CaptureBuildProgram_device_list(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -1148,16 +1144,14 @@ void CaptureBuildProgram_device_list(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureBuildProgram_options(bool isCallValid, - cl_program program, +void CaptureBuildProgram_options(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureBuildProgram_pfn_notify(bool isCallValid, - cl_program program, +void CaptureBuildProgram_pfn_notify(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -1165,8 +1159,7 @@ void CaptureBuildProgram_pfn_notify(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureBuildProgram_user_data(bool isCallValid, - cl_program program, +void CaptureBuildProgram_user_data(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -1174,128 +1167,109 @@ void CaptureBuildProgram_user_data(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureGetProgramInfo_param_value(bool isCallValid, - cl_program program, +void CaptureGetProgramInfo_param_value(cl_program program, ProgramInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetProgramInfo_param_value_size_ret(bool isCallValid, - cl_program program, +void CaptureGetProgramInfo_param_value_size_ret(cl_program program, ProgramInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetProgramBuildInfo_param_value(bool isCallValid, - cl_program program, +void CaptureGetProgramBuildInfo_param_value(cl_program program, cl_device_id device, ProgramBuildInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetProgramBuildInfo_param_value_size_ret(bool isCallValid, - cl_program program, +void CaptureGetProgramBuildInfo_param_value_size_ret(cl_program program, cl_device_id device, ProgramBuildInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureCreateKernel_kernel_name(bool isCallValid, - cl_program program, +void CaptureCreateKernel_kernel_name(cl_program program, const char *kernel_name, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateKernel_errcode_ret(bool isCallValid, - cl_program program, +void CaptureCreateKernel_errcode_ret(cl_program program, const char *kernel_name, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateKernelsInProgram_kernels(bool isCallValid, - cl_program program, +void CaptureCreateKernelsInProgram_kernels(cl_program program, cl_uint num_kernels, cl_kernel *kernels, cl_uint *num_kernels_ret, angle::ParamCapture *paramCapture); -void CaptureCreateKernelsInProgram_num_kernels_ret(bool isCallValid, - cl_program program, +void CaptureCreateKernelsInProgram_num_kernels_ret(cl_program program, cl_uint num_kernels, cl_kernel *kernels, cl_uint *num_kernels_ret, angle::ParamCapture *paramCapture); -void CaptureSetKernelArg_arg_value(bool isCallValid, - cl_kernel kernel, +void CaptureSetKernelArg_arg_value(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value, angle::ParamCapture *paramCapture); -void CaptureGetKernelInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelInfo_param_value(cl_kernel kernel, KernelInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelInfo_param_value_size_ret(cl_kernel kernel, KernelInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelWorkGroupInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelWorkGroupInfo_param_value(cl_kernel kernel, cl_device_id device, KernelWorkGroupInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelWorkGroupInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelWorkGroupInfo_param_value_size_ret(cl_kernel kernel, cl_device_id device, KernelWorkGroupInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureWaitForEvents_event_list(bool isCallValid, - cl_uint num_events, +void CaptureWaitForEvents_event_list(cl_uint num_events, const cl_event *event_list, angle::ParamCapture *paramCapture); -void CaptureGetEventInfo_param_value(bool isCallValid, - cl_event event, +void CaptureGetEventInfo_param_value(cl_event event, EventInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetEventInfo_param_value_size_ret(bool isCallValid, - cl_event event, +void CaptureGetEventInfo_param_value_size_ret(cl_event event, EventInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetEventProfilingInfo_param_value(bool isCallValid, - cl_event event, +void CaptureGetEventProfilingInfo_param_value(cl_event event, ProfilingInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetEventProfilingInfo_param_value_size_ret(bool isCallValid, - cl_event event, +void CaptureGetEventProfilingInfo_param_value_size_ret(cl_event event, ProfilingInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBuffer_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBuffer_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, @@ -1305,8 +1279,7 @@ void CaptureEnqueueReadBuffer_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, @@ -1316,8 +1289,7 @@ void CaptureEnqueueReadBuffer_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBuffer_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, @@ -1327,8 +1299,7 @@ void CaptureEnqueueReadBuffer_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBuffer_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBuffer_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, @@ -1338,8 +1309,7 @@ void CaptureEnqueueWriteBuffer_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, @@ -1349,8 +1319,7 @@ void CaptureEnqueueWriteBuffer_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBuffer_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, @@ -1360,8 +1329,7 @@ void CaptureEnqueueWriteBuffer_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBuffer_event_wait_list(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, @@ -1371,8 +1339,7 @@ void CaptureEnqueueCopyBuffer_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBuffer_event(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, @@ -1382,8 +1349,7 @@ void CaptureEnqueueCopyBuffer_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_origin(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1395,8 +1361,7 @@ void CaptureEnqueueReadImage_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_region(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1408,8 +1373,7 @@ void CaptureEnqueueReadImage_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadImage_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_ptr(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1421,8 +1385,7 @@ void CaptureEnqueueReadImage_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_event_wait_list(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1434,8 +1397,7 @@ void CaptureEnqueueReadImage_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_event(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1447,8 +1409,7 @@ void CaptureEnqueueReadImage_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_origin(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1460,8 +1421,7 @@ void CaptureEnqueueWriteImage_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_region(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1473,8 +1433,7 @@ void CaptureEnqueueWriteImage_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteImage_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_ptr(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1486,8 +1445,7 @@ void CaptureEnqueueWriteImage_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_event_wait_list(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1499,8 +1457,7 @@ void CaptureEnqueueWriteImage_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_event(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1512,8 +1469,7 @@ void CaptureEnqueueWriteImage_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImage_src_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_src_origin(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1523,8 +1479,7 @@ void CaptureEnqueueCopyImage_src_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImage_dst_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_dst_origin(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1534,8 +1489,7 @@ void CaptureEnqueueCopyImage_dst_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_region(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1545,8 +1499,7 @@ void CaptureEnqueueCopyImage_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_event_wait_list(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1556,8 +1509,7 @@ void CaptureEnqueueCopyImage_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_event(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1567,8 +1519,7 @@ void CaptureEnqueueCopyImage_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImageToBuffer_src_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_src_origin(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1578,8 +1529,7 @@ void CaptureEnqueueCopyImageToBuffer_src_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImageToBuffer_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_region(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1589,8 +1539,7 @@ void CaptureEnqueueCopyImageToBuffer_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImageToBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_event_wait_list(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1600,8 +1549,7 @@ void CaptureEnqueueCopyImageToBuffer_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyImageToBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_event(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1611,8 +1559,7 @@ void CaptureEnqueueCopyImageToBuffer_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferToImage_dst_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_dst_origin(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1622,8 +1569,7 @@ void CaptureEnqueueCopyBufferToImage_dst_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferToImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_region(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1633,8 +1579,7 @@ void CaptureEnqueueCopyBufferToImage_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferToImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_event_wait_list(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1644,8 +1589,7 @@ void CaptureEnqueueCopyBufferToImage_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferToImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_event(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1655,8 +1599,7 @@ void CaptureEnqueueCopyBufferToImage_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1667,8 +1610,7 @@ void CaptureEnqueueMapBuffer_event_wait_list(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapBuffer_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1679,8 +1621,7 @@ void CaptureEnqueueMapBuffer_event(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapBuffer_errcode_ret(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapBuffer_errcode_ret(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1691,8 +1632,7 @@ void CaptureEnqueueMapBuffer_errcode_ret(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_origin(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1705,8 +1645,7 @@ void CaptureEnqueueMapImage_origin(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_region(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1719,8 +1658,7 @@ void CaptureEnqueueMapImage_region(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_image_row_pitch(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_image_row_pitch(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1733,8 +1671,7 @@ void CaptureEnqueueMapImage_image_row_pitch(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_image_slice_pitch(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_image_slice_pitch(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1747,8 +1684,7 @@ void CaptureEnqueueMapImage_image_slice_pitch(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_event_wait_list(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1761,8 +1697,7 @@ void CaptureEnqueueMapImage_event_wait_list(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_event(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1775,8 +1710,7 @@ void CaptureEnqueueMapImage_event(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMapImage_errcode_ret(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_errcode_ret(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1789,32 +1723,28 @@ void CaptureEnqueueMapImage_errcode_ret(bool isCallValid, cl_event *event, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueUnmapMemObject_mapped_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueUnmapMemObject_mapped_ptr(cl_command_queue command_queue, cl_mem memobj, void *mapped_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueUnmapMemObject_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueUnmapMemObject_event_wait_list(cl_command_queue command_queue, cl_mem memobj, void *mapped_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueUnmapMemObject_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueUnmapMemObject_event(cl_command_queue command_queue, cl_mem memobj, void *mapped_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNDRangeKernel_global_work_offset(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_global_work_offset(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1824,8 +1754,7 @@ void CaptureEnqueueNDRangeKernel_global_work_offset(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNDRangeKernel_global_work_size(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_global_work_size(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1835,8 +1764,7 @@ void CaptureEnqueueNDRangeKernel_global_work_size(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNDRangeKernel_local_work_size(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_local_work_size(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1846,8 +1774,7 @@ void CaptureEnqueueNDRangeKernel_local_work_size(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNDRangeKernel_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_event_wait_list(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1857,8 +1784,7 @@ void CaptureEnqueueNDRangeKernel_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNDRangeKernel_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_event(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1868,8 +1794,7 @@ void CaptureEnqueueNDRangeKernel_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNativeKernel_user_func(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_user_func(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1880,8 +1805,7 @@ void CaptureEnqueueNativeKernel_user_func(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNativeKernel_args(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_args(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1892,8 +1816,7 @@ void CaptureEnqueueNativeKernel_args(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNativeKernel_mem_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_mem_list(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1904,8 +1827,7 @@ void CaptureEnqueueNativeKernel_mem_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNativeKernel_args_mem_loc(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_args_mem_loc(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1916,8 +1838,7 @@ void CaptureEnqueueNativeKernel_args_mem_loc(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNativeKernel_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_event_wait_list(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1928,8 +1849,7 @@ void CaptureEnqueueNativeKernel_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueNativeKernel_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_event(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1940,14 +1860,12 @@ void CaptureEnqueueNativeKernel_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureSetCommandQueueProperty_old_properties(bool isCallValid, - cl_command_queue command_queue, +void CaptureSetCommandQueueProperty_old_properties(cl_command_queue command_queue, CommandQueueProperties propertiesPacked, cl_bool enable, cl_command_queue_properties *old_properties, angle::ParamCapture *paramCapture); -void CaptureCreateImage2D_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImage2D_image_format(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -1956,8 +1874,7 @@ void CaptureCreateImage2D_image_format(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage2D_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImage2D_host_ptr(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -1966,8 +1883,7 @@ void CaptureCreateImage2D_host_ptr(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage2D_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImage2D_errcode_ret(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -1976,8 +1892,7 @@ void CaptureCreateImage2D_errcode_ret(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage3D_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImage3D_image_format(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -1988,8 +1903,7 @@ void CaptureCreateImage3D_image_format(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage3D_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImage3D_host_ptr(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2000,8 +1914,7 @@ void CaptureCreateImage3D_host_ptr(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage3D_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImage3D_errcode_ret(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2012,40 +1925,33 @@ void CaptureCreateImage3D_errcode_ret(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueMarker_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMarker_event(cl_command_queue command_queue, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWaitForEvents_event_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWaitForEvents_event_list(cl_command_queue command_queue, cl_uint num_events, const cl_event *event_list, angle::ParamCapture *paramCapture); -void CaptureGetExtensionFunctionAddress_func_name(bool isCallValid, - const char *func_name, +void CaptureGetExtensionFunctionAddress_func_name(const char *func_name, angle::ParamCapture *paramCapture); -void CaptureCreateCommandQueue_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateCommandQueue_errcode_ret(cl_context context, cl_device_id device, CommandQueueProperties propertiesPacked, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateSampler_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateSampler_errcode_ret(cl_context context, cl_bool normalized_coords, AddressingMode addressing_modePacked, FilterMode filter_modePacked, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueTask_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueTask_event_wait_list(cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueTask_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueTask_event(cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -2053,54 +1959,46 @@ void CaptureEnqueueTask_event(bool isCallValid, angle::ParamCapture *paramCapture); // CL 1.1 -void CaptureCreateSubBuffer_buffer_create_info(bool isCallValid, - cl_mem buffer, +void CaptureCreateSubBuffer_buffer_create_info(cl_mem buffer, MemFlags flagsPacked, cl_buffer_create_type buffer_create_type, const void *buffer_create_info, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateSubBuffer_errcode_ret(bool isCallValid, - cl_mem buffer, +void CaptureCreateSubBuffer_errcode_ret(cl_mem buffer, MemFlags flagsPacked, cl_buffer_create_type buffer_create_type, const void *buffer_create_info, cl_int *errcode_ret, angle::ParamCapture *paramCapture); void CaptureSetMemObjectDestructorCallback_pfn_notify( - bool isCallValid, cl_mem memobj, void(CL_CALLBACK *pfn_notify)(cl_mem memobj, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureSetMemObjectDestructorCallback_user_data(bool isCallValid, - cl_mem memobj, +void CaptureSetMemObjectDestructorCallback_user_data(cl_mem memobj, void(CL_CALLBACK *pfn_notify)(cl_mem memobj, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCreateUserEvent_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateUserEvent_errcode_ret(cl_context context, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureSetEventCallback_pfn_notify(bool isCallValid, - cl_event event, +void CaptureSetEventCallback_pfn_notify(cl_event event, cl_int command_exec_callback_type, void(CL_CALLBACK *pfn_notify)(cl_event event, cl_int event_command_status, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureSetEventCallback_user_data(bool isCallValid, - cl_event event, +void CaptureSetEventCallback_user_data(cl_event event, cl_int command_exec_callback_type, void(CL_CALLBACK *pfn_notify)(cl_event event, cl_int event_command_status, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBufferRect_buffer_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_buffer_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2115,8 +2013,7 @@ void CaptureEnqueueReadBufferRect_buffer_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBufferRect_host_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_host_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2131,8 +2028,7 @@ void CaptureEnqueueReadBufferRect_host_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBufferRect_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_region(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2147,8 +2043,7 @@ void CaptureEnqueueReadBufferRect_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBufferRect_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2163,8 +2058,7 @@ void CaptureEnqueueReadBufferRect_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBufferRect_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2179,8 +2073,7 @@ void CaptureEnqueueReadBufferRect_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueReadBufferRect_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2195,8 +2088,7 @@ void CaptureEnqueueReadBufferRect_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBufferRect_buffer_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_buffer_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2211,8 +2103,7 @@ void CaptureEnqueueWriteBufferRect_buffer_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBufferRect_host_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_host_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2227,8 +2118,7 @@ void CaptureEnqueueWriteBufferRect_host_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBufferRect_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_region(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2243,8 +2133,7 @@ void CaptureEnqueueWriteBufferRect_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBufferRect_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2259,8 +2148,7 @@ void CaptureEnqueueWriteBufferRect_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBufferRect_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2275,8 +2163,7 @@ void CaptureEnqueueWriteBufferRect_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueWriteBufferRect_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2291,8 +2178,7 @@ void CaptureEnqueueWriteBufferRect_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferRect_src_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_src_origin(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2306,8 +2192,7 @@ void CaptureEnqueueCopyBufferRect_src_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferRect_dst_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_dst_origin(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2321,8 +2206,7 @@ void CaptureEnqueueCopyBufferRect_dst_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferRect_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_region(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2336,8 +2220,7 @@ void CaptureEnqueueCopyBufferRect_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferRect_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_event_wait_list(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2351,8 +2234,7 @@ void CaptureEnqueueCopyBufferRect_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueCopyBufferRect_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_event(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2368,82 +2250,71 @@ void CaptureEnqueueCopyBufferRect_event(bool isCallValid, angle::ParamCapture *paramCapture); // CL 1.2 -void CaptureCreateSubDevices_properties(bool isCallValid, - cl_device_id in_device, +void CaptureCreateSubDevices_properties(cl_device_id in_device, const cl_device_partition_property *properties, cl_uint num_devices, cl_device_id *out_devices, cl_uint *num_devices_ret, angle::ParamCapture *paramCapture); -void CaptureCreateSubDevices_out_devices(bool isCallValid, - cl_device_id in_device, +void CaptureCreateSubDevices_out_devices(cl_device_id in_device, const cl_device_partition_property *properties, cl_uint num_devices, cl_device_id *out_devices, cl_uint *num_devices_ret, angle::ParamCapture *paramCapture); -void CaptureCreateSubDevices_num_devices_ret(bool isCallValid, - cl_device_id in_device, +void CaptureCreateSubDevices_num_devices_ret(cl_device_id in_device, const cl_device_partition_property *properties, cl_uint num_devices, cl_device_id *out_devices, cl_uint *num_devices_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImage_image_format(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage_image_desc(bool isCallValid, - cl_context context, +void CaptureCreateImage_image_desc(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImage_host_ptr(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImage_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImage_errcode_ret(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBuiltInKernels_device_list(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBuiltInKernels_device_list(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *kernel_names, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBuiltInKernels_kernel_names(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBuiltInKernels_kernel_names(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *kernel_names, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithBuiltInKernels_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBuiltInKernels_errcode_ret(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *kernel_names, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCompileProgram_device_list(bool isCallValid, - cl_program program, +void CaptureCompileProgram_device_list(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2454,8 +2325,7 @@ void CaptureCompileProgram_device_list(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCompileProgram_options(bool isCallValid, - cl_program program, +void CaptureCompileProgram_options(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2466,8 +2336,7 @@ void CaptureCompileProgram_options(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCompileProgram_input_headers(bool isCallValid, - cl_program program, +void CaptureCompileProgram_input_headers(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2478,8 +2347,7 @@ void CaptureCompileProgram_input_headers(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCompileProgram_header_include_names(bool isCallValid, - cl_program program, +void CaptureCompileProgram_header_include_names(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2490,8 +2358,7 @@ void CaptureCompileProgram_header_include_names(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCompileProgram_pfn_notify(bool isCallValid, - cl_program program, +void CaptureCompileProgram_pfn_notify(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2502,8 +2369,7 @@ void CaptureCompileProgram_pfn_notify(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCompileProgram_user_data(bool isCallValid, - cl_program program, +void CaptureCompileProgram_user_data(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2514,8 +2380,7 @@ void CaptureCompileProgram_user_data(bool isCallValid, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureLinkProgram_device_list(bool isCallValid, - cl_context context, +void CaptureLinkProgram_device_list(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2526,8 +2391,7 @@ void CaptureLinkProgram_device_list(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureLinkProgram_options(bool isCallValid, - cl_context context, +void CaptureLinkProgram_options(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2537,8 +2401,7 @@ void CaptureLinkProgram_options(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureLinkProgram_input_programs(bool isCallValid, - cl_context context, +void CaptureLinkProgram_input_programs(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2549,8 +2412,7 @@ void CaptureLinkProgram_input_programs(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureLinkProgram_pfn_notify(bool isCallValid, - cl_context context, +void CaptureLinkProgram_pfn_notify(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2561,8 +2423,7 @@ void CaptureLinkProgram_pfn_notify(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureLinkProgram_user_data(bool isCallValid, - cl_context context, +void CaptureLinkProgram_user_data(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2573,8 +2434,7 @@ void CaptureLinkProgram_user_data(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureLinkProgram_errcode_ret(bool isCallValid, - cl_context context, +void CaptureLinkProgram_errcode_ret(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2585,24 +2445,21 @@ void CaptureLinkProgram_errcode_ret(bool isCallValid, void *user_data, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelArgInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelArgInfo_param_value(cl_kernel kernel, cl_uint arg_index, KernelArgInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelArgInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelArgInfo_param_value_size_ret(cl_kernel kernel, cl_uint arg_index, KernelArgInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillBuffer_pattern(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillBuffer_pattern(cl_command_queue command_queue, cl_mem buffer, const void *pattern, size_t pattern_size, @@ -2612,8 +2469,7 @@ void CaptureEnqueueFillBuffer_pattern(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, const void *pattern, size_t pattern_size, @@ -2623,8 +2479,7 @@ void CaptureEnqueueFillBuffer_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillBuffer_event(cl_command_queue command_queue, cl_mem buffer, const void *pattern, size_t pattern_size, @@ -2634,8 +2489,7 @@ void CaptureEnqueueFillBuffer_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillImage_fill_color(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_fill_color(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -2644,8 +2498,7 @@ void CaptureEnqueueFillImage_fill_color(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_origin(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -2654,8 +2507,7 @@ void CaptureEnqueueFillImage_origin(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_region(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -2664,8 +2516,7 @@ void CaptureEnqueueFillImage_region(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_event_wait_list(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -2674,8 +2525,7 @@ void CaptureEnqueueFillImage_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueFillImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_event(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -2684,8 +2534,7 @@ void CaptureEnqueueFillImage_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueMigrateMemObjects_mem_objects(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMigrateMemObjects_mem_objects(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, MemMigrationFlags flagsPacked, @@ -2693,8 +2542,7 @@ void CaptureEnqueueMigrateMemObjects_mem_objects(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueMigrateMemObjects_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMigrateMemObjects_event_wait_list(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, MemMigrationFlags flagsPacked, @@ -2702,8 +2550,7 @@ void CaptureEnqueueMigrateMemObjects_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueMigrateMemObjects_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMigrateMemObjects_event(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, MemMigrationFlags flagsPacked, @@ -2711,106 +2558,89 @@ void CaptureEnqueueMigrateMemObjects_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueMarkerWithWaitList_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMarkerWithWaitList_event_wait_list(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueMarkerWithWaitList_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMarkerWithWaitList_event(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueBarrierWithWaitList_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueBarrierWithWaitList_event_wait_list(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueBarrierWithWaitList_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueBarrierWithWaitList_event(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureGetExtensionFunctionAddressForPlatform_func_name(bool isCallValid, - cl_platform_id platform, +void CaptureGetExtensionFunctionAddressForPlatform_func_name(cl_platform_id platform, const char *func_name, angle::ParamCapture *paramCapture); // CL 2.0 -void CaptureCreateCommandQueueWithProperties_properties(bool isCallValid, - cl_context context, +void CaptureCreateCommandQueueWithProperties_properties(cl_context context, cl_device_id device, const cl_queue_properties *properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateCommandQueueWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateCommandQueueWithProperties_errcode_ret(cl_context context, cl_device_id device, const cl_queue_properties *properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreatePipe_properties(bool isCallValid, - cl_context context, +void CaptureCreatePipe_properties(cl_context context, MemFlags flagsPacked, cl_uint pipe_packet_size, cl_uint pipe_max_packets, const cl_pipe_properties *properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreatePipe_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreatePipe_errcode_ret(cl_context context, MemFlags flagsPacked, cl_uint pipe_packet_size, cl_uint pipe_max_packets, const cl_pipe_properties *properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureGetPipeInfo_param_value(bool isCallValid, - cl_mem pipe, +void CaptureGetPipeInfo_param_value(cl_mem pipe, PipeInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetPipeInfo_param_value_size_ret(bool isCallValid, - cl_mem pipe, +void CaptureGetPipeInfo_param_value_size_ret(cl_mem pipe, PipeInfo param_namePacked, size_t param_value_size, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureSVMFree_svm_pointer(bool isCallValid, - cl_context context, +void CaptureSVMFree_svm_pointer(cl_context context, void *svm_pointer, angle::ParamCapture *paramCapture); void CaptureCreateSamplerWithProperties_sampler_properties( - bool isCallValid, cl_context context, const cl_sampler_properties *sampler_properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateSamplerWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateSamplerWithProperties_errcode_ret(cl_context context, const cl_sampler_properties *sampler_properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureSetKernelArgSVMPointer_arg_value(bool isCallValid, - cl_kernel kernel, +void CaptureSetKernelArgSVMPointer_arg_value(cl_kernel kernel, cl_uint arg_index, const void *arg_value, angle::ParamCapture *paramCapture); -void CaptureSetKernelExecInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureSetKernelExecInfo_param_value(cl_kernel kernel, KernelExecInfo param_namePacked, size_t param_value_size, const void *param_value, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMFree_svm_pointers(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_svm_pointers(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -2822,8 +2652,7 @@ void CaptureEnqueueSVMFree_svm_pointers(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMFree_pfn_free_func(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_pfn_free_func(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -2835,8 +2664,7 @@ void CaptureEnqueueSVMFree_pfn_free_func(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMFree_user_data(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_user_data(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -2849,7 +2677,6 @@ void CaptureEnqueueSVMFree_user_data(bool isCallValid, cl_event *event, angle::ParamCapture *paramCapture); void CaptureEnqueueSVMFree_event_wait_list( - bool isCallValid, cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], @@ -2862,8 +2689,7 @@ void CaptureEnqueueSVMFree_event_wait_list( const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMFree_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_event(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -2875,8 +2701,7 @@ void CaptureEnqueueSVMFree_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemcpy_dst_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_dst_ptr(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -2885,8 +2710,7 @@ void CaptureEnqueueSVMMemcpy_dst_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemcpy_src_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_src_ptr(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -2895,8 +2719,7 @@ void CaptureEnqueueSVMMemcpy_src_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemcpy_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_event_wait_list(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -2905,8 +2728,7 @@ void CaptureEnqueueSVMMemcpy_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemcpy_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_event(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -2915,8 +2737,7 @@ void CaptureEnqueueSVMMemcpy_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemFill_svm_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_svm_ptr(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -2925,8 +2746,7 @@ void CaptureEnqueueSVMMemFill_svm_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemFill_pattern(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_pattern(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -2935,8 +2755,7 @@ void CaptureEnqueueSVMMemFill_pattern(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemFill_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_event_wait_list(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -2945,8 +2764,7 @@ void CaptureEnqueueSVMMemFill_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMemFill_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_event(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -2955,8 +2773,7 @@ void CaptureEnqueueSVMMemFill_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMap_svm_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMap_svm_ptr(cl_command_queue command_queue, cl_bool blocking_map, MapFlags flagsPacked, void *svm_ptr, @@ -2965,8 +2782,7 @@ void CaptureEnqueueSVMMap_svm_ptr(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMap_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMap_event_wait_list(cl_command_queue command_queue, cl_bool blocking_map, MapFlags flagsPacked, void *svm_ptr, @@ -2975,8 +2791,7 @@ void CaptureEnqueueSVMMap_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMap_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMap_event(cl_command_queue command_queue, cl_bool blocking_map, MapFlags flagsPacked, void *svm_ptr, @@ -2985,22 +2800,19 @@ void CaptureEnqueueSVMMap_event(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMUnmap_svm_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMUnmap_svm_ptr(cl_command_queue command_queue, void *svm_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMUnmap_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMUnmap_event_wait_list(cl_command_queue command_queue, void *svm_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMUnmap_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMUnmap_event(cl_command_queue command_queue, void *svm_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -3008,38 +2820,31 @@ void CaptureEnqueueSVMUnmap_event(bool isCallValid, angle::ParamCapture *paramCapture); // CL 2.1 -void CaptureGetDeviceAndHostTimer_device_timestamp(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceAndHostTimer_device_timestamp(cl_device_id device, cl_ulong *device_timestamp, cl_ulong *host_timestamp, angle::ParamCapture *paramCapture); -void CaptureGetDeviceAndHostTimer_host_timestamp(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceAndHostTimer_host_timestamp(cl_device_id device, cl_ulong *device_timestamp, cl_ulong *host_timestamp, angle::ParamCapture *paramCapture); -void CaptureGetHostTimer_host_timestamp(bool isCallValid, - cl_device_id device, +void CaptureGetHostTimer_host_timestamp(cl_device_id device, cl_ulong *host_timestamp, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithIL_il(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithIL_il(cl_context context, const void *il, size_t length, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateProgramWithIL_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithIL_errcode_ret(cl_context context, const void *il, size_t length, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCloneKernel_errcode_ret(bool isCallValid, - cl_kernel source_kernel, +void CaptureCloneKernel_errcode_ret(cl_kernel source_kernel, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelSubGroupInfo_input_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelSubGroupInfo_input_value(cl_kernel kernel, cl_device_id device, KernelSubGroupInfo param_namePacked, size_t input_value_size, @@ -3048,8 +2853,7 @@ void CaptureGetKernelSubGroupInfo_input_value(bool isCallValid, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelSubGroupInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelSubGroupInfo_param_value(cl_kernel kernel, cl_device_id device, KernelSubGroupInfo param_namePacked, size_t input_value_size, @@ -3058,8 +2862,7 @@ void CaptureGetKernelSubGroupInfo_param_value(bool isCallValid, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureGetKernelSubGroupInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelSubGroupInfo_param_value_size_ret(cl_kernel kernel, cl_device_id device, KernelSubGroupInfo param_namePacked, size_t input_value_size, @@ -3068,8 +2871,7 @@ void CaptureGetKernelSubGroupInfo_param_value_size_ret(bool isCallValid, void *param_value, size_t *param_value_size_ret, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMigrateMem_svm_pointers(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_svm_pointers(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -3078,8 +2880,7 @@ void CaptureEnqueueSVMMigrateMem_svm_pointers(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMigrateMem_sizes(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_sizes(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -3088,8 +2889,7 @@ void CaptureEnqueueSVMMigrateMem_sizes(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMigrateMem_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_event_wait_list(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -3098,8 +2898,7 @@ void CaptureEnqueueSVMMigrateMem_event_wait_list(bool isCallValid, const cl_event *event_wait_list, cl_event *event, angle::ParamCapture *paramCapture); -void CaptureEnqueueSVMMigrateMem_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_event(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -3110,20 +2909,17 @@ void CaptureEnqueueSVMMigrateMem_event(bool isCallValid, angle::ParamCapture *paramCapture); // CL 2.2 -void CaptureSetProgramReleaseCallback_pfn_notify(bool isCallValid, - cl_program program, +void CaptureSetProgramReleaseCallback_pfn_notify(cl_program program, void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureSetProgramReleaseCallback_user_data(bool isCallValid, - cl_program program, +void CaptureSetProgramReleaseCallback_user_data(cl_program program, void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureSetProgramSpecializationConstant_spec_value(bool isCallValid, - cl_program program, +void CaptureSetProgramSpecializationConstant_spec_value(cl_program program, cl_uint spec_id, size_t spec_size, const void *spec_value, @@ -3131,43 +2927,37 @@ void CaptureSetProgramSpecializationConstant_spec_value(bool isCallValid, // CL 3.0 void CaptureSetContextDestructorCallback_pfn_notify( - bool isCallValid, cl_context context, void(CL_CALLBACK *pfn_notify)(cl_context context, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureSetContextDestructorCallback_user_data(bool isCallValid, - cl_context context, +void CaptureSetContextDestructorCallback_user_data(cl_context context, void(CL_CALLBACK *pfn_notify)(cl_context context, void *user_data), void *user_data, angle::ParamCapture *paramCapture); -void CaptureCreateBufferWithProperties_properties(bool isCallValid, - cl_context context, +void CaptureCreateBufferWithProperties_properties(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, size_t size, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateBufferWithProperties_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateBufferWithProperties_host_ptr(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, size_t size, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateBufferWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateBufferWithProperties_errcode_ret(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, size_t size, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImageWithProperties_properties(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_properties(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -3175,8 +2965,7 @@ void CaptureCreateImageWithProperties_properties(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImageWithProperties_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_image_format(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -3184,8 +2973,7 @@ void CaptureCreateImageWithProperties_image_format(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImageWithProperties_image_desc(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_image_desc(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -3193,8 +2981,7 @@ void CaptureCreateImageWithProperties_image_desc(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImageWithProperties_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_host_ptr(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -3202,8 +2989,7 @@ void CaptureCreateImageWithProperties_host_ptr(bool isCallValid, void *host_ptr, cl_int *errcode_ret, angle::ParamCapture *paramCapture); -void CaptureCreateImageWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_errcode_ret(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -3212,17 +2998,88 @@ void CaptureCreateImageWithProperties_errcode_ret(bool isCallValid, cl_int *errcode_ret, angle::ParamCapture *paramCapture); +// cl_arm_import_memory +void CaptureImportMemoryARM_properties(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + angle::ParamCapture *paramCapture); +void CaptureImportMemoryARM_memory(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + angle::ParamCapture *paramCapture); +void CaptureImportMemoryARM_errcode_ret(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + angle::ParamCapture *paramCapture); + +// cl_khr_external_memory +void CaptureEnqueueAcquireExternalMemObjectsKHR_mem_objects(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + angle::ParamCapture *paramCapture); +void CaptureEnqueueAcquireExternalMemObjectsKHR_event_wait_list(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + angle::ParamCapture *paramCapture); +void CaptureEnqueueAcquireExternalMemObjectsKHR_event(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + angle::ParamCapture *paramCapture); +void CaptureEnqueueReleaseExternalMemObjectsKHR_mem_objects(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + angle::ParamCapture *paramCapture); +void CaptureEnqueueReleaseExternalMemObjectsKHR_event_wait_list(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + angle::ParamCapture *paramCapture); +void CaptureEnqueueReleaseExternalMemObjectsKHR_event(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + angle::ParamCapture *paramCapture); + // cl_khr_icd -void CaptureIcdGetPlatformIDsKHR_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureIcdGetPlatformIDsKHR_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture); -void CaptureIcdGetPlatformIDsKHR_num_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureIcdGetPlatformIDsKHR_num_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture); +void CaptureIcdGetFunctionAddressForPlatformKHR_func_name(cl_platform_id platform, + const char *func_name, + angle::ParamCapture *paramCapture); +void CaptureIcdSetPlatformDispatchDataKHR_dispatch_data(cl_platform_id platform, + void *dispatch_data, + angle::ParamCapture *paramCapture); } // namespace cl #endif // LIBANGLE_CAPTURE_CL_AUTOGEN_H_ diff --git a/src/libANGLE/capture/capture_cl_params.cpp b/src/libANGLE/capture/capture_cl_params.cpp index 64f823cc7d7..b1185083d4d 100644 --- a/src/libANGLE/capture/capture_cl_params.cpp +++ b/src/libANGLE/capture/capture_cl_params.cpp @@ -5,6 +5,11 @@ // // capture_cl_params.cpp: // Pointer parameter capture functions for the OpenCL entry points. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/CLImage.h" #include "libANGLE/capture/capture_cl_autogen.h" @@ -13,8 +18,7 @@ namespace cl { -void CaptureGetPlatformIDs_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureGetPlatformIDs_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture) @@ -25,8 +29,7 @@ void CaptureGetPlatformIDs_platforms(bool isCallValid, num_entries); } } -void CaptureGetPlatformIDs_num_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureGetPlatformIDs_num_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture) @@ -36,8 +39,7 @@ void CaptureGetPlatformIDs_num_platforms(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_uint); } } -void CaptureGetPlatformInfo_param_value(bool isCallValid, - cl_platform_id platform, +void CaptureGetPlatformInfo_param_value(cl_platform_id platform, PlatformInfo param_namePacked, size_t param_value_size, void *param_value, @@ -49,8 +51,7 @@ void CaptureGetPlatformInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetPlatformInfo_param_value_size_ret(bool isCallValid, - cl_platform_id platform, +void CaptureGetPlatformInfo_param_value_size_ret(cl_platform_id platform, PlatformInfo param_namePacked, size_t param_value_size, void *param_value, @@ -62,8 +63,7 @@ void CaptureGetPlatformInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetDeviceIDs_devices(bool isCallValid, - cl_platform_id platform, +void CaptureGetDeviceIDs_devices(cl_platform_id platform, DeviceType device_typePacked, cl_uint num_entries, cl_device_id *devices, @@ -78,8 +78,7 @@ void CaptureGetDeviceIDs_devices(bool isCallValid, devices, num_entries, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureGetDeviceIDs_num_devices(bool isCallValid, - cl_platform_id platform, +void CaptureGetDeviceIDs_num_devices(cl_platform_id platform, DeviceType device_typePacked, cl_uint num_entries, cl_device_id *devices, @@ -91,8 +90,7 @@ void CaptureGetDeviceIDs_num_devices(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_uint); } } -void CaptureGetDeviceInfo_param_value(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceInfo_param_value(cl_device_id device, DeviceInfo param_namePacked, size_t param_value_size, void *param_value, @@ -104,8 +102,7 @@ void CaptureGetDeviceInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetDeviceInfo_param_value_size_ret(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceInfo_param_value_size_ret(cl_device_id device, DeviceInfo param_namePacked, size_t param_value_size, void *param_value, @@ -117,8 +114,7 @@ void CaptureGetDeviceInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureCreateContext_properties(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_properties(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -139,8 +135,7 @@ void CaptureCreateContext_properties(bool isCallValid, CaptureMemory(properties, propertiesSize * sizeof(cl_context_properties), paramCapture); } } -void CaptureCreateContext_devices(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_devices(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -154,8 +149,7 @@ void CaptureCreateContext_devices(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( devices, num_devices, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureCreateContext_pfn_notify(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_pfn_notify(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -168,8 +162,7 @@ void CaptureCreateContext_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureCreateContext_user_data(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_user_data(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -183,8 +176,7 @@ void CaptureCreateContext_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureCreateContext_errcode_ret(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContext_errcode_ret(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -200,8 +192,7 @@ void CaptureCreateContext_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateContextFromType_properties(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContextFromType_properties(const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, @@ -220,8 +211,7 @@ void CaptureCreateContextFromType_properties(bool isCallValid, CaptureMemory(properties, propertiesSize * sizeof(cl_context_properties), paramCapture); } } -void CaptureCreateContextFromType_pfn_notify(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContextFromType_pfn_notify(const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, @@ -233,8 +223,7 @@ void CaptureCreateContextFromType_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureCreateContextFromType_user_data(bool isCallValid, - const cl_context_properties *properties, +void CaptureCreateContextFromType_user_data(const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, @@ -248,7 +237,6 @@ void CaptureCreateContextFromType_user_data(bool isCallValid, ¶mCapture->value); } void CaptureCreateContextFromType_errcode_ret( - bool isCallValid, const cl_context_properties *properties, DeviceType device_typePacked, void(CL_CALLBACK *pfn_notify)(const char *errinfo, @@ -264,8 +252,7 @@ void CaptureCreateContextFromType_errcode_ret( paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureGetContextInfo_param_value(bool isCallValid, - cl_context context, +void CaptureGetContextInfo_param_value(cl_context context, ContextInfo param_namePacked, size_t param_value_size, void *param_value, @@ -277,8 +264,7 @@ void CaptureGetContextInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetContextInfo_param_value_size_ret(bool isCallValid, - cl_context context, +void CaptureGetContextInfo_param_value_size_ret(cl_context context, ContextInfo param_namePacked, size_t param_value_size, void *param_value, @@ -290,8 +276,7 @@ void CaptureGetContextInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetCommandQueueInfo_param_value(bool isCallValid, - cl_command_queue command_queue, +void CaptureGetCommandQueueInfo_param_value(cl_command_queue command_queue, CommandQueueInfo param_namePacked, size_t param_value_size, void *param_value, @@ -303,8 +288,7 @@ void CaptureGetCommandQueueInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetCommandQueueInfo_param_value_size_ret(bool isCallValid, - cl_command_queue command_queue, +void CaptureGetCommandQueueInfo_param_value_size_ret(cl_command_queue command_queue, CommandQueueInfo param_namePacked, size_t param_value_size, void *param_value, @@ -316,8 +300,7 @@ void CaptureGetCommandQueueInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureCreateBuffer_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateBuffer_host_ptr(cl_context context, MemFlags flagsPacked, size_t size, void *host_ptr, @@ -329,8 +312,7 @@ void CaptureCreateBuffer_host_ptr(bool isCallValid, CaptureMemory(host_ptr, size, paramCapture); } } -void CaptureCreateBuffer_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateBuffer_errcode_ret(cl_context context, MemFlags flagsPacked, size_t size, void *host_ptr, @@ -342,8 +324,7 @@ void CaptureCreateBuffer_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureGetSupportedImageFormats_image_formats(bool isCallValid, - cl_context context, +void CaptureGetSupportedImageFormats_image_formats(cl_context context, MemFlags flagsPacked, MemObjectType image_typePacked, cl_uint num_entries, @@ -356,8 +337,7 @@ void CaptureGetSupportedImageFormats_image_formats(bool isCallValid, paramCapture->readBufferSizeBytes = num_entries * sizeof(cl_image_format); } } -void CaptureGetSupportedImageFormats_num_image_formats(bool isCallValid, - cl_context context, +void CaptureGetSupportedImageFormats_num_image_formats(cl_context context, MemFlags flagsPacked, MemObjectType image_typePacked, cl_uint num_entries, @@ -370,8 +350,7 @@ void CaptureGetSupportedImageFormats_num_image_formats(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_uint); } } -void CaptureGetMemObjectInfo_param_value(bool isCallValid, - cl_mem memobj, +void CaptureGetMemObjectInfo_param_value(cl_mem memobj, MemInfo param_namePacked, size_t param_value_size, void *param_value, @@ -383,8 +362,7 @@ void CaptureGetMemObjectInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetMemObjectInfo_param_value_size_ret(bool isCallValid, - cl_mem memobj, +void CaptureGetMemObjectInfo_param_value_size_ret(cl_mem memobj, MemInfo param_namePacked, size_t param_value_size, void *param_value, @@ -396,8 +374,7 @@ void CaptureGetMemObjectInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetImageInfo_param_value(bool isCallValid, - cl_mem image, +void CaptureGetImageInfo_param_value(cl_mem image, ImageInfo param_namePacked, size_t param_value_size, void *param_value, @@ -409,8 +386,7 @@ void CaptureGetImageInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetImageInfo_param_value_size_ret(bool isCallValid, - cl_mem image, +void CaptureGetImageInfo_param_value_size_ret(cl_mem image, ImageInfo param_namePacked, size_t param_value_size, void *param_value, @@ -422,8 +398,7 @@ void CaptureGetImageInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetSamplerInfo_param_value(bool isCallValid, - cl_sampler sampler, +void CaptureGetSamplerInfo_param_value(cl_sampler sampler, SamplerInfo param_namePacked, size_t param_value_size, void *param_value, @@ -435,8 +410,7 @@ void CaptureGetSamplerInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetSamplerInfo_param_value_size_ret(bool isCallValid, - cl_sampler sampler, +void CaptureGetSamplerInfo_param_value_size_ret(cl_sampler sampler, SamplerInfo param_namePacked, size_t param_value_size, void *param_value, @@ -448,8 +422,7 @@ void CaptureGetSamplerInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureCreateProgramWithSource_strings(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithSource_strings(cl_context context, cl_uint count, const char **strings, const size_t *lengths, @@ -474,8 +447,7 @@ void CaptureCreateProgramWithSource_strings(bool isCallValid, } } } -void CaptureCreateProgramWithSource_lengths(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithSource_lengths(cl_context context, cl_uint count, const char **strings, const size_t *lengths, @@ -487,8 +459,7 @@ void CaptureCreateProgramWithSource_lengths(bool isCallValid, CaptureMemory(lengths, count * sizeof(size_t), paramCapture); } } -void CaptureCreateProgramWithSource_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithSource_errcode_ret(cl_context context, cl_uint count, const char **strings, const size_t *lengths, @@ -500,8 +471,7 @@ void CaptureCreateProgramWithSource_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateProgramWithBinary_device_list(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_device_list(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -513,8 +483,7 @@ void CaptureCreateProgramWithBinary_device_list(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( device_list, num_devices, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureCreateProgramWithBinary_lengths(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_lengths(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -528,8 +497,7 @@ void CaptureCreateProgramWithBinary_lengths(bool isCallValid, CaptureMemory(lengths, num_devices * sizeof(size_t), paramCapture); } } -void CaptureCreateProgramWithBinary_binaries(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_binaries(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -547,8 +515,7 @@ void CaptureCreateProgramWithBinary_binaries(bool isCallValid, } } -void CaptureCreateProgramWithBinary_binary_status(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_binary_status(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -563,8 +530,7 @@ void CaptureCreateProgramWithBinary_binary_status(bool isCallValid, } } -void CaptureCreateProgramWithBinary_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBinary_errcode_ret(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, @@ -579,8 +545,7 @@ void CaptureCreateProgramWithBinary_errcode_ret(bool isCallValid, } } -void CaptureBuildProgram_device_list(bool isCallValid, - cl_program program, +void CaptureBuildProgram_device_list(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -597,8 +562,7 @@ void CaptureBuildProgram_device_list(bool isCallValid, } } -void CaptureBuildProgram_options(bool isCallValid, - cl_program program, +void CaptureBuildProgram_options(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -611,8 +575,7 @@ void CaptureBuildProgram_options(bool isCallValid, CaptureString(options, paramCapture); } } -void CaptureBuildProgram_pfn_notify(bool isCallValid, - cl_program program, +void CaptureBuildProgram_pfn_notify(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -623,8 +586,7 @@ void CaptureBuildProgram_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureBuildProgram_user_data(bool isCallValid, - cl_program program, +void CaptureBuildProgram_user_data(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -636,8 +598,7 @@ void CaptureBuildProgram_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureGetProgramInfo_param_value(bool isCallValid, - cl_program program, +void CaptureGetProgramInfo_param_value(cl_program program, ProgramInfo param_namePacked, size_t param_value_size, void *param_value, @@ -649,8 +610,7 @@ void CaptureGetProgramInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetProgramInfo_param_value_size_ret(bool isCallValid, - cl_program program, +void CaptureGetProgramInfo_param_value_size_ret(cl_program program, ProgramInfo param_namePacked, size_t param_value_size, void *param_value, @@ -662,8 +622,7 @@ void CaptureGetProgramInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetProgramBuildInfo_param_value(bool isCallValid, - cl_program program, +void CaptureGetProgramBuildInfo_param_value(cl_program program, cl_device_id device, ProgramBuildInfo param_namePacked, size_t param_value_size, @@ -676,8 +635,7 @@ void CaptureGetProgramBuildInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetProgramBuildInfo_param_value_size_ret(bool isCallValid, - cl_program program, +void CaptureGetProgramBuildInfo_param_value_size_ret(cl_program program, cl_device_id device, ProgramBuildInfo param_namePacked, size_t param_value_size, @@ -690,16 +648,14 @@ void CaptureGetProgramBuildInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureCreateKernel_kernel_name(bool isCallValid, - cl_program program, +void CaptureCreateKernel_kernel_name(cl_program program, const char *kernel_name, cl_int *errcode_ret, angle::ParamCapture *paramCapture) { CaptureString(kernel_name, paramCapture); } -void CaptureCreateKernel_errcode_ret(bool isCallValid, - cl_program program, +void CaptureCreateKernel_errcode_ret(cl_program program, const char *kernel_name, cl_int *errcode_ret, angle::ParamCapture *paramCapture) @@ -709,8 +665,7 @@ void CaptureCreateKernel_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateKernelsInProgram_kernels(bool isCallValid, - cl_program program, +void CaptureCreateKernelsInProgram_kernels(cl_program program, cl_uint num_kernels, cl_kernel *kernels, cl_uint *num_kernels_ret, @@ -728,8 +683,7 @@ void CaptureCreateKernelsInProgram_kernels(bool isCallValid, kernels, maxKernels, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureCreateKernelsInProgram_num_kernels_ret(bool isCallValid, - cl_program program, +void CaptureCreateKernelsInProgram_num_kernels_ret(cl_program program, cl_uint num_kernels, cl_kernel *kernels, cl_uint *num_kernels_ret, @@ -740,8 +694,7 @@ void CaptureCreateKernelsInProgram_num_kernels_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_uint); } } -void CaptureSetKernelArg_arg_value(bool isCallValid, - cl_kernel kernel, +void CaptureSetKernelArg_arg_value(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value, @@ -772,8 +725,7 @@ void CaptureSetKernelArg_arg_value(bool isCallValid, CaptureMemory(arg_value, arg_size, paramCapture); } } -void CaptureGetKernelInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelInfo_param_value(cl_kernel kernel, KernelInfo param_namePacked, size_t param_value_size, void *param_value, @@ -785,8 +737,7 @@ void CaptureGetKernelInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetKernelInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelInfo_param_value_size_ret(cl_kernel kernel, KernelInfo param_namePacked, size_t param_value_size, void *param_value, @@ -798,8 +749,7 @@ void CaptureGetKernelInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetKernelWorkGroupInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelWorkGroupInfo_param_value(cl_kernel kernel, cl_device_id device, KernelWorkGroupInfo param_namePacked, size_t param_value_size, @@ -812,8 +762,7 @@ void CaptureGetKernelWorkGroupInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetKernelWorkGroupInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelWorkGroupInfo_param_value_size_ret(cl_kernel kernel, cl_device_id device, KernelWorkGroupInfo param_namePacked, size_t param_value_size, @@ -826,8 +775,7 @@ void CaptureGetKernelWorkGroupInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureWaitForEvents_event_list(bool isCallValid, - cl_uint num_events, +void CaptureWaitForEvents_event_list(cl_uint num_events, const cl_event *event_list, angle::ParamCapture *paramCapture) { @@ -837,8 +785,7 @@ void CaptureWaitForEvents_event_list(bool isCallValid, event_list, num_events, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureGetEventInfo_param_value(bool isCallValid, - cl_event event, +void CaptureGetEventInfo_param_value(cl_event event, EventInfo param_namePacked, size_t param_value_size, void *param_value, @@ -850,8 +797,7 @@ void CaptureGetEventInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetEventInfo_param_value_size_ret(bool isCallValid, - cl_event event, +void CaptureGetEventInfo_param_value_size_ret(cl_event event, EventInfo param_namePacked, size_t param_value_size, void *param_value, @@ -863,8 +809,7 @@ void CaptureGetEventInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureGetEventProfilingInfo_param_value(bool isCallValid, - cl_event event, +void CaptureGetEventProfilingInfo_param_value(cl_event event, ProfilingInfo param_namePacked, size_t param_value_size, void *param_value, @@ -876,8 +821,7 @@ void CaptureGetEventProfilingInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetEventProfilingInfo_param_value_size_ret(bool isCallValid, - cl_event event, +void CaptureGetEventProfilingInfo_param_value_size_ret(cl_event event, ProfilingInfo param_namePacked, size_t param_value_size, void *param_value, @@ -889,8 +833,7 @@ void CaptureGetEventProfilingInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureEnqueueReadBuffer_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBuffer_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, @@ -903,8 +846,7 @@ void CaptureEnqueueReadBuffer_ptr(bool isCallValid, { paramCapture->readBufferSizeBytes = size; } -void CaptureEnqueueReadBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, @@ -922,8 +864,7 @@ void CaptureEnqueueReadBuffer_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueReadBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBuffer_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, @@ -940,8 +881,7 @@ void CaptureEnqueueReadBuffer_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueWriteBuffer_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBuffer_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, @@ -957,8 +897,7 @@ void CaptureEnqueueWriteBuffer_ptr(bool isCallValid, CaptureMemory(ptr, size, paramCapture); } } -void CaptureEnqueueWriteBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, @@ -976,8 +915,7 @@ void CaptureEnqueueWriteBuffer_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueWriteBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBuffer_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, @@ -994,8 +932,7 @@ void CaptureEnqueueWriteBuffer_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueCopyBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBuffer_event_wait_list(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, @@ -1013,8 +950,7 @@ void CaptureEnqueueCopyBuffer_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueCopyBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBuffer_event(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, @@ -1031,8 +967,7 @@ void CaptureEnqueueCopyBuffer_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueReadImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_origin(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1050,8 +985,7 @@ void CaptureEnqueueReadImage_origin(bool isCallValid, CaptureMemory(origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueReadImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_region(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1069,8 +1003,7 @@ void CaptureEnqueueReadImage_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueReadImage_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_ptr(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1099,8 +1032,7 @@ void CaptureEnqueueReadImage_ptr(bool isCallValid, region[0] * elementSize; } } -void CaptureEnqueueReadImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_event_wait_list(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1120,8 +1052,7 @@ void CaptureEnqueueReadImage_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueReadImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadImage_event(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t *origin, @@ -1140,8 +1071,7 @@ void CaptureEnqueueReadImage_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueWriteImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_origin(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1159,8 +1089,7 @@ void CaptureEnqueueWriteImage_origin(bool isCallValid, CaptureMemory(origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueWriteImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_region(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1178,8 +1107,7 @@ void CaptureEnqueueWriteImage_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueWriteImage_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_ptr(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1210,8 +1138,7 @@ void CaptureEnqueueWriteImage_ptr(bool isCallValid, CaptureMemory(ptr, totalSize, paramCapture); } } -void CaptureEnqueueWriteImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_event_wait_list(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1231,8 +1158,7 @@ void CaptureEnqueueWriteImage_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueWriteImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteImage_event(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t *origin, @@ -1251,8 +1177,7 @@ void CaptureEnqueueWriteImage_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueCopyImage_src_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_src_origin(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1268,8 +1193,7 @@ void CaptureEnqueueCopyImage_src_origin(bool isCallValid, CaptureMemory(src_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyImage_dst_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_dst_origin(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1285,8 +1209,7 @@ void CaptureEnqueueCopyImage_dst_origin(bool isCallValid, CaptureMemory(dst_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_region(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1302,8 +1225,7 @@ void CaptureEnqueueCopyImage_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_event_wait_list(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1321,8 +1243,7 @@ void CaptureEnqueueCopyImage_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueCopyImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImage_event(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t *src_origin, @@ -1339,8 +1260,7 @@ void CaptureEnqueueCopyImage_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueCopyImageToBuffer_src_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_src_origin(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1356,8 +1276,7 @@ void CaptureEnqueueCopyImageToBuffer_src_origin(bool isCallValid, CaptureMemory(src_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyImageToBuffer_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_region(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1373,8 +1292,7 @@ void CaptureEnqueueCopyImageToBuffer_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyImageToBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_event_wait_list(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1392,8 +1310,7 @@ void CaptureEnqueueCopyImageToBuffer_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueCopyImageToBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyImageToBuffer_event(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t *src_origin, @@ -1410,8 +1327,7 @@ void CaptureEnqueueCopyImageToBuffer_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueCopyBufferToImage_dst_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_dst_origin(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1427,8 +1343,7 @@ void CaptureEnqueueCopyBufferToImage_dst_origin(bool isCallValid, CaptureMemory(dst_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyBufferToImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_region(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1444,8 +1359,7 @@ void CaptureEnqueueCopyBufferToImage_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyBufferToImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_event_wait_list(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1463,8 +1377,7 @@ void CaptureEnqueueCopyBufferToImage_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueCopyBufferToImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferToImage_event(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, @@ -1481,8 +1394,7 @@ void CaptureEnqueueCopyBufferToImage_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueMapBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1501,8 +1413,7 @@ void CaptureEnqueueMapBuffer_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueMapBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapBuffer_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1520,8 +1431,7 @@ void CaptureEnqueueMapBuffer_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueMapBuffer_errcode_ret(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapBuffer_errcode_ret(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1538,8 +1448,7 @@ void CaptureEnqueueMapBuffer_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureEnqueueMapImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_origin(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1558,8 +1467,7 @@ void CaptureEnqueueMapImage_origin(bool isCallValid, CaptureMemory(origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueMapImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_region(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1578,8 +1486,7 @@ void CaptureEnqueueMapImage_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueMapImage_image_row_pitch(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_image_row_pitch(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1598,8 +1505,7 @@ void CaptureEnqueueMapImage_image_row_pitch(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureEnqueueMapImage_image_slice_pitch(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_image_slice_pitch(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1618,8 +1524,7 @@ void CaptureEnqueueMapImage_image_slice_pitch(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureEnqueueMapImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_event_wait_list(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1640,8 +1545,7 @@ void CaptureEnqueueMapImage_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueMapImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_event(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1661,8 +1565,7 @@ void CaptureEnqueueMapImage_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueMapImage_errcode_ret(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMapImage_errcode_ret(cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, MapFlags map_flagsPacked, @@ -1681,8 +1584,7 @@ void CaptureEnqueueMapImage_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureEnqueueUnmapMemObject_mapped_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueUnmapMemObject_mapped_ptr(cl_command_queue command_queue, cl_mem memobj, void *mapped_ptr, cl_uint num_events_in_wait_list, @@ -1692,8 +1594,7 @@ void CaptureEnqueueUnmapMemObject_mapped_ptr(bool isCallValid, { // Nothing to implement } -void CaptureEnqueueUnmapMemObject_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueUnmapMemObject_event_wait_list(cl_command_queue command_queue, cl_mem memobj, void *mapped_ptr, cl_uint num_events_in_wait_list, @@ -1708,8 +1609,7 @@ void CaptureEnqueueUnmapMemObject_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueUnmapMemObject_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueUnmapMemObject_event(cl_command_queue command_queue, cl_mem memobj, void *mapped_ptr, cl_uint num_events_in_wait_list, @@ -1723,8 +1623,7 @@ void CaptureEnqueueUnmapMemObject_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueNDRangeKernel_global_work_offset(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_global_work_offset(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1740,8 +1639,7 @@ void CaptureEnqueueNDRangeKernel_global_work_offset(bool isCallValid, CaptureMemory(global_work_offset, work_dim * sizeof(size_t), paramCapture); } } -void CaptureEnqueueNDRangeKernel_global_work_size(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_global_work_size(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1757,8 +1655,7 @@ void CaptureEnqueueNDRangeKernel_global_work_size(bool isCallValid, CaptureMemory(global_work_size, work_dim * sizeof(size_t), paramCapture); } } -void CaptureEnqueueNDRangeKernel_local_work_size(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_local_work_size(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1774,8 +1671,7 @@ void CaptureEnqueueNDRangeKernel_local_work_size(bool isCallValid, CaptureMemory(local_work_size, work_dim * sizeof(size_t), paramCapture); } } -void CaptureEnqueueNDRangeKernel_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_event_wait_list(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1793,8 +1689,7 @@ void CaptureEnqueueNDRangeKernel_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueNDRangeKernel_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNDRangeKernel_event(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, @@ -1811,8 +1706,7 @@ void CaptureEnqueueNDRangeKernel_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueNativeKernel_user_func(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_user_func(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1826,8 +1720,7 @@ void CaptureEnqueueNativeKernel_user_func(bool isCallValid, { // Nothing to implement } -void CaptureEnqueueNativeKernel_args(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_args(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1848,8 +1741,7 @@ void CaptureEnqueueNativeKernel_args(bool isCallValid, // ... CaptureMemory(args, cb_args, paramCapture); } -void CaptureEnqueueNativeKernel_mem_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_mem_list(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1864,8 +1756,7 @@ void CaptureEnqueueNativeKernel_mem_list(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( mem_list, num_mem_objects, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureEnqueueNativeKernel_args_mem_loc(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_args_mem_loc(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1880,8 +1771,7 @@ void CaptureEnqueueNativeKernel_args_mem_loc(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setOffsetsVector( args, args_mem_loc, num_mem_objects, paramCapture); } -void CaptureEnqueueNativeKernel_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_event_wait_list(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1900,8 +1790,7 @@ void CaptureEnqueueNativeKernel_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueNativeKernel_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueNativeKernel_event(cl_command_queue command_queue, void(CL_CALLBACK *user_func)(void *), void *args, size_t cb_args, @@ -1919,8 +1808,7 @@ void CaptureEnqueueNativeKernel_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureSetCommandQueueProperty_old_properties(bool isCallValid, - cl_command_queue command_queue, +void CaptureSetCommandQueueProperty_old_properties(cl_command_queue command_queue, CommandQueueProperties propertiesPacked, cl_bool enable, cl_command_queue_properties *old_properties, @@ -2027,8 +1915,7 @@ size_t GetCorrectedImageSlicePitch(size_t image_row_pitch, return corrected_image_slice_pitch; } -void CaptureCreateImage2D_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImage2D_image_format(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2043,8 +1930,7 @@ void CaptureCreateImage2D_image_format(bool isCallValid, CaptureMemory(image_format, sizeof(cl_image_format), paramCapture); } } -void CaptureCreateImage2D_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImage2D_host_ptr(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2059,8 +1945,7 @@ void CaptureCreateImage2D_host_ptr(bool isCallValid, GetCorrectedImageRowPitch(image_format, image_row_pitch, image_width) * image_height, paramCapture); } -void CaptureCreateImage2D_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImage2D_errcode_ret(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2075,8 +1960,7 @@ void CaptureCreateImage2D_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateImage3D_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImage3D_image_format(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2093,8 +1977,7 @@ void CaptureCreateImage3D_image_format(bool isCallValid, CaptureMemory(image_format, sizeof(cl_image_format), paramCapture); } } -void CaptureCreateImage3D_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImage3D_host_ptr(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2114,8 +1997,7 @@ void CaptureCreateImage3D_host_ptr(bool isCallValid, image_depth, paramCapture); } -void CaptureCreateImage3D_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImage3D_errcode_ret(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, size_t image_width, @@ -2132,8 +2014,7 @@ void CaptureCreateImage3D_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureEnqueueMarker_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMarker_event(cl_command_queue command_queue, cl_event *event, angle::ParamCapture *paramCapture) { @@ -2143,8 +2024,7 @@ void CaptureEnqueueMarker_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueWaitForEvents_event_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWaitForEvents_event_list(cl_command_queue command_queue, cl_uint num_events, const cl_event *event_list, angle::ParamCapture *paramCapture) @@ -2155,8 +2035,7 @@ void CaptureEnqueueWaitForEvents_event_list(bool isCallValid, event_list, num_events, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureGetExtensionFunctionAddress_func_name(bool isCallValid, - const char *func_name, +void CaptureGetExtensionFunctionAddress_func_name(const char *func_name, angle::ParamCapture *paramCapture) { if (func_name) @@ -2164,8 +2043,7 @@ void CaptureGetExtensionFunctionAddress_func_name(bool isCallValid, CaptureString(func_name, paramCapture); } } -void CaptureCreateCommandQueue_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateCommandQueue_errcode_ret(cl_context context, cl_device_id device, CommandQueueProperties propertiesPacked, cl_int *errcode_ret, @@ -2176,8 +2054,7 @@ void CaptureCreateCommandQueue_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateSampler_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateSampler_errcode_ret(cl_context context, cl_bool normalized_coords, AddressingMode addressing_modePacked, FilterMode filter_modePacked, @@ -2189,8 +2066,7 @@ void CaptureCreateSampler_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureEnqueueTask_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueTask_event_wait_list(cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -2204,8 +2080,7 @@ void CaptureEnqueueTask_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueTask_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueTask_event(cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -2218,8 +2093,7 @@ void CaptureEnqueueTask_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureCreateSubBuffer_buffer_create_info(bool isCallValid, - cl_mem buffer, +void CaptureCreateSubBuffer_buffer_create_info(cl_mem buffer, MemFlags flagsPacked, cl_buffer_create_type buffer_create_type, const void *buffer_create_info, @@ -2231,8 +2105,7 @@ void CaptureCreateSubBuffer_buffer_create_info(bool isCallValid, CaptureMemory(buffer_create_info, sizeof(cl_buffer_region), paramCapture); } } -void CaptureCreateSubBuffer_errcode_ret(bool isCallValid, - cl_mem buffer, +void CaptureCreateSubBuffer_errcode_ret(cl_mem buffer, MemFlags flagsPacked, cl_buffer_create_type buffer_create_type, const void *buffer_create_info, @@ -2245,7 +2118,6 @@ void CaptureCreateSubBuffer_errcode_ret(bool isCallValid, } } void CaptureSetMemObjectDestructorCallback_pfn_notify( - bool isCallValid, cl_mem memobj, void(CL_CALLBACK *pfn_notify)(cl_mem memobj, void *user_data), void *user_data, @@ -2253,8 +2125,7 @@ void CaptureSetMemObjectDestructorCallback_pfn_notify( { // Nothing to implement } -void CaptureSetMemObjectDestructorCallback_user_data(bool isCallValid, - cl_mem memobj, +void CaptureSetMemObjectDestructorCallback_user_data(cl_mem memobj, void(CL_CALLBACK *pfn_notify)(cl_mem memobj, void *user_data), void *user_data, @@ -2263,8 +2134,7 @@ void CaptureSetMemObjectDestructorCallback_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureCreateUserEvent_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateUserEvent_errcode_ret(cl_context context, cl_int *errcode_ret, angle::ParamCapture *paramCapture) { @@ -2273,8 +2143,7 @@ void CaptureCreateUserEvent_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureSetEventCallback_pfn_notify(bool isCallValid, - cl_event event, +void CaptureSetEventCallback_pfn_notify(cl_event event, cl_int command_exec_callback_type, void(CL_CALLBACK *pfn_notify)(cl_event event, cl_int event_command_status, @@ -2284,8 +2153,7 @@ void CaptureSetEventCallback_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureSetEventCallback_user_data(bool isCallValid, - cl_event event, +void CaptureSetEventCallback_user_data(cl_event event, cl_int command_exec_callback_type, void(CL_CALLBACK *pfn_notify)(cl_event event, cl_int event_command_status, @@ -2296,8 +2164,7 @@ void CaptureSetEventCallback_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureEnqueueReadBufferRect_buffer_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_buffer_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2318,8 +2185,7 @@ void CaptureEnqueueReadBufferRect_buffer_origin(bool isCallValid, CaptureMemory(buffer_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueReadBufferRect_host_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_host_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2340,8 +2206,7 @@ void CaptureEnqueueReadBufferRect_host_origin(bool isCallValid, CaptureMemory(host_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueReadBufferRect_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_region(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2362,8 +2227,7 @@ void CaptureEnqueueReadBufferRect_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueReadBufferRect_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2399,8 +2263,7 @@ void CaptureEnqueueReadBufferRect_ptr(bool isCallValid, (region[1] - 1) * computed_host_row_pitch + region[0]; } } -void CaptureEnqueueReadBufferRect_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2423,8 +2286,7 @@ void CaptureEnqueueReadBufferRect_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueReadBufferRect_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReadBufferRect_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t *buffer_origin, @@ -2446,8 +2308,7 @@ void CaptureEnqueueReadBufferRect_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueWriteBufferRect_buffer_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_buffer_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2468,8 +2329,7 @@ void CaptureEnqueueWriteBufferRect_buffer_origin(bool isCallValid, CaptureMemory(buffer_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueWriteBufferRect_host_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_host_origin(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2490,8 +2350,7 @@ void CaptureEnqueueWriteBufferRect_host_origin(bool isCallValid, CaptureMemory(host_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueWriteBufferRect_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_region(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2512,8 +2371,7 @@ void CaptureEnqueueWriteBufferRect_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueWriteBufferRect_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_ptr(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2549,8 +2407,7 @@ void CaptureEnqueueWriteBufferRect_ptr(bool isCallValid, CaptureMemory(ptr, totalSize, paramCapture); } } -void CaptureEnqueueWriteBufferRect_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_event_wait_list(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2573,8 +2430,7 @@ void CaptureEnqueueWriteBufferRect_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueWriteBufferRect_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueWriteBufferRect_event(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t *buffer_origin, @@ -2596,8 +2452,7 @@ void CaptureEnqueueWriteBufferRect_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueCopyBufferRect_src_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_src_origin(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2617,8 +2472,7 @@ void CaptureEnqueueCopyBufferRect_src_origin(bool isCallValid, CaptureMemory(src_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyBufferRect_dst_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_dst_origin(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2638,8 +2492,7 @@ void CaptureEnqueueCopyBufferRect_dst_origin(bool isCallValid, CaptureMemory(dst_origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyBufferRect_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_region(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2659,8 +2512,7 @@ void CaptureEnqueueCopyBufferRect_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueCopyBufferRect_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_event_wait_list(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2682,8 +2534,7 @@ void CaptureEnqueueCopyBufferRect_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueCopyBufferRect_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueCopyBufferRect_event(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t *src_origin, @@ -2704,8 +2555,7 @@ void CaptureEnqueueCopyBufferRect_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureCreateSubDevices_properties(bool isCallValid, - cl_device_id in_device, +void CaptureCreateSubDevices_properties(cl_device_id in_device, const cl_device_partition_property *properties, cl_uint num_devices, cl_device_id *out_devices, @@ -2722,8 +2572,7 @@ void CaptureCreateSubDevices_properties(bool isCallValid, paramCapture); } } -void CaptureCreateSubDevices_out_devices(bool isCallValid, - cl_device_id in_device, +void CaptureCreateSubDevices_out_devices(cl_device_id in_device, const cl_device_partition_property *properties, cl_uint num_devices, cl_device_id *out_devices, @@ -2738,8 +2587,7 @@ void CaptureCreateSubDevices_out_devices(bool isCallValid, out_devices, num_devices, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureCreateSubDevices_num_devices_ret(bool isCallValid, - cl_device_id in_device, +void CaptureCreateSubDevices_num_devices_ret(cl_device_id in_device, const cl_device_partition_property *properties, cl_uint num_devices, cl_device_id *out_devices, @@ -2751,8 +2599,7 @@ void CaptureCreateSubDevices_num_devices_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_uint); } } -void CaptureCreateImage_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImage_image_format(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, @@ -2765,8 +2612,7 @@ void CaptureCreateImage_image_format(bool isCallValid, CaptureMemory(image_format, sizeof(cl_image_format), paramCapture); } } -void CaptureCreateImage_image_desc(bool isCallValid, - cl_context context, +void CaptureCreateImage_image_desc(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, @@ -2779,8 +2625,7 @@ void CaptureCreateImage_image_desc(bool isCallValid, CaptureMemory(image_desc, sizeof(cl_image_desc), paramCapture); } } -void CaptureCreateImage_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImage_host_ptr(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, @@ -2820,8 +2665,7 @@ void CaptureCreateImage_host_ptr(bool isCallValid, CaptureMemory(host_ptr, image_size, paramCapture); } } -void CaptureCreateImage_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImage_errcode_ret(cl_context context, MemFlags flagsPacked, const cl_image_format *image_format, const cl_image_desc *image_desc, @@ -2834,8 +2678,7 @@ void CaptureCreateImage_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateProgramWithBuiltInKernels_device_list(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBuiltInKernels_device_list(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *kernel_names, @@ -2845,8 +2688,7 @@ void CaptureCreateProgramWithBuiltInKernels_device_list(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( device_list, num_devices, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureCreateProgramWithBuiltInKernels_kernel_names(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBuiltInKernels_kernel_names(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *kernel_names, @@ -2858,8 +2700,7 @@ void CaptureCreateProgramWithBuiltInKernels_kernel_names(bool isCallValid, CaptureString(kernel_names, paramCapture); } } -void CaptureCreateProgramWithBuiltInKernels_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithBuiltInKernels_errcode_ret(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *kernel_names, @@ -2871,8 +2712,7 @@ void CaptureCreateProgramWithBuiltInKernels_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCompileProgram_device_list(bool isCallValid, - cl_program program, +void CaptureCompileProgram_device_list(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2890,8 +2730,7 @@ void CaptureCompileProgram_device_list(bool isCallValid, device_list, num_devices, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureCompileProgram_options(bool isCallValid, - cl_program program, +void CaptureCompileProgram_options(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2908,8 +2747,7 @@ void CaptureCompileProgram_options(bool isCallValid, CaptureString(options, paramCapture); } } -void CaptureCompileProgram_input_headers(bool isCallValid, - cl_program program, +void CaptureCompileProgram_input_headers(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2924,8 +2762,7 @@ void CaptureCompileProgram_input_headers(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( input_headers, num_input_headers, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureCompileProgram_header_include_names(bool isCallValid, - cl_program program, +void CaptureCompileProgram_header_include_names(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2943,8 +2780,7 @@ void CaptureCompileProgram_header_include_names(bool isCallValid, paramCapture); } } -void CaptureCompileProgram_pfn_notify(bool isCallValid, - cl_program program, +void CaptureCompileProgram_pfn_notify(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2958,8 +2794,7 @@ void CaptureCompileProgram_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureCompileProgram_user_data(bool isCallValid, - cl_program program, +void CaptureCompileProgram_user_data(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2974,8 +2809,7 @@ void CaptureCompileProgram_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureLinkProgram_device_list(bool isCallValid, - cl_context context, +void CaptureLinkProgram_device_list(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -2993,8 +2827,7 @@ void CaptureLinkProgram_device_list(bool isCallValid, device_list, num_devices, paramCapture, &angle::FrameCaptureShared::getIndex); } } -void CaptureLinkProgram_options(bool isCallValid, - cl_context context, +void CaptureLinkProgram_options(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -3010,8 +2843,7 @@ void CaptureLinkProgram_options(bool isCallValid, CaptureString(options, paramCapture); } } -void CaptureLinkProgram_input_programs(bool isCallValid, - cl_context context, +void CaptureLinkProgram_input_programs(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -3026,8 +2858,7 @@ void CaptureLinkProgram_input_programs(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( input_programs, num_input_programs, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureLinkProgram_pfn_notify(bool isCallValid, - cl_context context, +void CaptureLinkProgram_pfn_notify(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -3041,8 +2872,7 @@ void CaptureLinkProgram_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureLinkProgram_user_data(bool isCallValid, - cl_context context, +void CaptureLinkProgram_user_data(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -3057,8 +2887,7 @@ void CaptureLinkProgram_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureLinkProgram_errcode_ret(bool isCallValid, - cl_context context, +void CaptureLinkProgram_errcode_ret(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const char *options, @@ -3075,8 +2904,7 @@ void CaptureLinkProgram_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureGetKernelArgInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelArgInfo_param_value(cl_kernel kernel, cl_uint arg_index, KernelArgInfo param_namePacked, size_t param_value_size, @@ -3089,8 +2917,7 @@ void CaptureGetKernelArgInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetKernelArgInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelArgInfo_param_value_size_ret(cl_kernel kernel, cl_uint arg_index, KernelArgInfo param_namePacked, size_t param_value_size, @@ -3103,8 +2930,7 @@ void CaptureGetKernelArgInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureEnqueueFillBuffer_pattern(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillBuffer_pattern(cl_command_queue command_queue, cl_mem buffer, const void *pattern, size_t pattern_size, @@ -3120,8 +2946,7 @@ void CaptureEnqueueFillBuffer_pattern(bool isCallValid, CaptureMemory(pattern, offset + size, paramCapture); } } -void CaptureEnqueueFillBuffer_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillBuffer_event_wait_list(cl_command_queue command_queue, cl_mem buffer, const void *pattern, size_t pattern_size, @@ -3139,8 +2964,7 @@ void CaptureEnqueueFillBuffer_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueFillBuffer_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillBuffer_event(cl_command_queue command_queue, cl_mem buffer, const void *pattern, size_t pattern_size, @@ -3157,8 +2981,7 @@ void CaptureEnqueueFillBuffer_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueFillImage_fill_color(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_fill_color(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -3221,8 +3044,7 @@ void CaptureEnqueueFillImage_fill_color(bool isCallValid, CaptureMemory(fill_color, totalSize, paramCapture); } -void CaptureEnqueueFillImage_origin(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_origin(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -3237,8 +3059,7 @@ void CaptureEnqueueFillImage_origin(bool isCallValid, CaptureMemory(origin, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueFillImage_region(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_region(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -3253,8 +3074,7 @@ void CaptureEnqueueFillImage_region(bool isCallValid, CaptureMemory(region, 3 * sizeof(size_t), paramCapture); } } -void CaptureEnqueueFillImage_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_event_wait_list(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -3271,8 +3091,7 @@ void CaptureEnqueueFillImage_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueFillImage_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueFillImage_event(cl_command_queue command_queue, cl_mem image, const void *fill_color, const size_t *origin, @@ -3288,8 +3107,7 @@ void CaptureEnqueueFillImage_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueMigrateMemObjects_mem_objects(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMigrateMemObjects_mem_objects(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, MemMigrationFlags flagsPacked, @@ -3301,8 +3119,7 @@ void CaptureEnqueueMigrateMemObjects_mem_objects(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setCLObjVectorMap( mem_objects, num_mem_objects, paramCapture, &angle::FrameCaptureShared::getIndex); } -void CaptureEnqueueMigrateMemObjects_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMigrateMemObjects_event_wait_list(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, MemMigrationFlags flagsPacked, @@ -3318,8 +3135,7 @@ void CaptureEnqueueMigrateMemObjects_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueMigrateMemObjects_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMigrateMemObjects_event(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, MemMigrationFlags flagsPacked, @@ -3334,8 +3150,7 @@ void CaptureEnqueueMigrateMemObjects_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueMarkerWithWaitList_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMarkerWithWaitList_event_wait_list(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, @@ -3348,8 +3163,7 @@ void CaptureEnqueueMarkerWithWaitList_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueMarkerWithWaitList_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueMarkerWithWaitList_event(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, @@ -3361,8 +3175,7 @@ void CaptureEnqueueMarkerWithWaitList_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueBarrierWithWaitList_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueBarrierWithWaitList_event_wait_list(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, @@ -3375,8 +3188,7 @@ void CaptureEnqueueBarrierWithWaitList_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueBarrierWithWaitList_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueBarrierWithWaitList_event(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event, @@ -3388,8 +3200,7 @@ void CaptureEnqueueBarrierWithWaitList_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureGetExtensionFunctionAddressForPlatform_func_name(bool isCallValid, - cl_platform_id platform, +void CaptureGetExtensionFunctionAddressForPlatform_func_name(cl_platform_id platform, const char *func_name, angle::ParamCapture *paramCapture) { @@ -3398,8 +3209,7 @@ void CaptureGetExtensionFunctionAddressForPlatform_func_name(bool isCallValid, CaptureString(func_name, paramCapture); } } -void CaptureCreateCommandQueueWithProperties_properties(bool isCallValid, - cl_context context, +void CaptureCreateCommandQueueWithProperties_properties(cl_context context, cl_device_id device, const cl_queue_properties *properties, cl_int *errcode_ret, @@ -3415,8 +3225,7 @@ void CaptureCreateCommandQueueWithProperties_properties(bool isCallValid, paramCapture); } } -void CaptureCreateCommandQueueWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateCommandQueueWithProperties_errcode_ret(cl_context context, cl_device_id device, const cl_queue_properties *properties, cl_int *errcode_ret, @@ -3427,8 +3236,7 @@ void CaptureCreateCommandQueueWithProperties_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreatePipe_properties(bool isCallValid, - cl_context context, +void CaptureCreatePipe_properties(cl_context context, MemFlags flagsPacked, cl_uint pipe_packet_size, cl_uint pipe_max_packets, @@ -3446,8 +3254,7 @@ void CaptureCreatePipe_properties(bool isCallValid, paramCapture); } } -void CaptureCreatePipe_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreatePipe_errcode_ret(cl_context context, MemFlags flagsPacked, cl_uint pipe_packet_size, cl_uint pipe_max_packets, @@ -3460,8 +3267,7 @@ void CaptureCreatePipe_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureGetPipeInfo_param_value(bool isCallValid, - cl_mem pipe, +void CaptureGetPipeInfo_param_value(cl_mem pipe, PipeInfo param_namePacked, size_t param_value_size, void *param_value, @@ -3473,8 +3279,7 @@ void CaptureGetPipeInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetPipeInfo_param_value_size_ret(bool isCallValid, - cl_mem pipe, +void CaptureGetPipeInfo_param_value_size_ret(cl_mem pipe, PipeInfo param_namePacked, size_t param_value_size, void *param_value, @@ -3486,15 +3291,13 @@ void CaptureGetPipeInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureSVMFree_svm_pointer(bool isCallValid, - cl_context context, +void CaptureSVMFree_svm_pointer(cl_context context, void *svm_pointer, angle::ParamCapture *paramCapture) { // Nothing to implement. svm_pointer is an SVM pointer } void CaptureCreateSamplerWithProperties_sampler_properties( - bool isCallValid, cl_context context, const cl_sampler_properties *sampler_properties, cl_int *errcode_ret, @@ -3510,8 +3313,7 @@ void CaptureCreateSamplerWithProperties_sampler_properties( paramCapture); } } -void CaptureCreateSamplerWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateSamplerWithProperties_errcode_ret(cl_context context, const cl_sampler_properties *sampler_properties, cl_int *errcode_ret, angle::ParamCapture *paramCapture) @@ -3521,16 +3323,14 @@ void CaptureCreateSamplerWithProperties_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureSetKernelArgSVMPointer_arg_value(bool isCallValid, - cl_kernel kernel, +void CaptureSetKernelArgSVMPointer_arg_value(cl_kernel kernel, cl_uint arg_index, const void *arg_value, angle::ParamCapture *paramCapture) { // Nothing to implement. arg_value is an SVM pointer } -void CaptureSetKernelExecInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureSetKernelExecInfo_param_value(cl_kernel kernel, KernelExecInfo param_namePacked, size_t param_value_size, const void *param_value, @@ -3541,8 +3341,7 @@ void CaptureSetKernelExecInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureEnqueueSVMFree_svm_pointers(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_svm_pointers(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -3561,8 +3360,7 @@ void CaptureEnqueueSVMFree_svm_pointers(bool isCallValid, const_cast(svm_pointers), num_svm_pointers, paramCapture); } } -void CaptureEnqueueSVMFree_pfn_free_func(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_pfn_free_func(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -3577,8 +3375,7 @@ void CaptureEnqueueSVMFree_pfn_free_func(bool isCallValid, { // Nothing to implement } -void CaptureEnqueueSVMFree_user_data(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_user_data(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -3595,7 +3392,6 @@ void CaptureEnqueueSVMFree_user_data(bool isCallValid, ¶mCapture->value); } void CaptureEnqueueSVMFree_event_wait_list( - bool isCallValid, cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], @@ -3616,8 +3412,7 @@ void CaptureEnqueueSVMFree_event_wait_list( &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueSVMFree_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMFree_event(cl_command_queue command_queue, cl_uint num_svm_pointers, void *svm_pointers[], void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue, @@ -3636,8 +3431,7 @@ void CaptureEnqueueSVMFree_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueSVMMemcpy_dst_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_dst_ptr(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -3653,8 +3447,7 @@ void CaptureEnqueueSVMMemcpy_dst_ptr(bool isCallValid, paramCapture->readBufferSizeBytes = size; } } -void CaptureEnqueueSVMMemcpy_src_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_src_ptr(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -3670,8 +3463,7 @@ void CaptureEnqueueSVMMemcpy_src_ptr(bool isCallValid, CaptureMemory(src_ptr, size, paramCapture); } } -void CaptureEnqueueSVMMemcpy_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_event_wait_list(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -3688,8 +3480,7 @@ void CaptureEnqueueSVMMemcpy_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueSVMMemcpy_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemcpy_event(cl_command_queue command_queue, cl_bool blocking_copy, void *dst_ptr, const void *src_ptr, @@ -3705,8 +3496,7 @@ void CaptureEnqueueSVMMemcpy_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueSVMMemFill_svm_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_svm_ptr(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -3718,8 +3508,7 @@ void CaptureEnqueueSVMMemFill_svm_ptr(bool isCallValid, { // Nothing to implement. svm_ptr is an SVM pointer } -void CaptureEnqueueSVMMemFill_pattern(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_pattern(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -3734,8 +3523,7 @@ void CaptureEnqueueSVMMemFill_pattern(bool isCallValid, CaptureMemory(pattern, pattern_size, paramCapture); } } -void CaptureEnqueueSVMMemFill_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_event_wait_list(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -3752,8 +3540,7 @@ void CaptureEnqueueSVMMemFill_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueSVMMemFill_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMemFill_event(cl_command_queue command_queue, void *svm_ptr, const void *pattern, size_t pattern_size, @@ -3769,8 +3556,7 @@ void CaptureEnqueueSVMMemFill_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueSVMMap_svm_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMap_svm_ptr(cl_command_queue command_queue, cl_bool blocking_map, MapFlags flagsPacked, void *svm_ptr, @@ -3782,8 +3568,7 @@ void CaptureEnqueueSVMMap_svm_ptr(bool isCallValid, { // Nothing to implement. svm_ptr is an SVM pointer } -void CaptureEnqueueSVMMap_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMap_event_wait_list(cl_command_queue command_queue, cl_bool blocking_map, MapFlags flagsPacked, void *svm_ptr, @@ -3800,8 +3585,7 @@ void CaptureEnqueueSVMMap_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueSVMMap_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMap_event(cl_command_queue command_queue, cl_bool blocking_map, MapFlags flagsPacked, void *svm_ptr, @@ -3817,8 +3601,7 @@ void CaptureEnqueueSVMMap_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureEnqueueSVMUnmap_svm_ptr(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMUnmap_svm_ptr(cl_command_queue command_queue, void *svm_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -3827,8 +3610,7 @@ void CaptureEnqueueSVMUnmap_svm_ptr(bool isCallValid, { // Nothing to implement. svm_ptr is an SVM pointer } -void CaptureEnqueueSVMUnmap_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMUnmap_event_wait_list(cl_command_queue command_queue, void *svm_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -3842,8 +3624,7 @@ void CaptureEnqueueSVMUnmap_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueSVMUnmap_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMUnmap_event(cl_command_queue command_queue, void *svm_ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, @@ -3856,8 +3637,7 @@ void CaptureEnqueueSVMUnmap_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureGetDeviceAndHostTimer_device_timestamp(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceAndHostTimer_device_timestamp(cl_device_id device, cl_ulong *device_timestamp, cl_ulong *host_timestamp, angle::ParamCapture *paramCapture) @@ -3867,8 +3647,7 @@ void CaptureGetDeviceAndHostTimer_device_timestamp(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_ulong); } } -void CaptureGetDeviceAndHostTimer_host_timestamp(bool isCallValid, - cl_device_id device, +void CaptureGetDeviceAndHostTimer_host_timestamp(cl_device_id device, cl_ulong *device_timestamp, cl_ulong *host_timestamp, angle::ParamCapture *paramCapture) @@ -3878,8 +3657,7 @@ void CaptureGetDeviceAndHostTimer_host_timestamp(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_ulong); } } -void CaptureGetHostTimer_host_timestamp(bool isCallValid, - cl_device_id device, +void CaptureGetHostTimer_host_timestamp(cl_device_id device, cl_ulong *host_timestamp, angle::ParamCapture *paramCapture) { @@ -3888,8 +3666,7 @@ void CaptureGetHostTimer_host_timestamp(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_ulong); } } -void CaptureCreateProgramWithIL_il(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithIL_il(cl_context context, const void *il, size_t length, cl_int *errcode_ret, @@ -3900,8 +3677,7 @@ void CaptureCreateProgramWithIL_il(bool isCallValid, CaptureMemory(il, length, paramCapture); } } -void CaptureCreateProgramWithIL_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateProgramWithIL_errcode_ret(cl_context context, const void *il, size_t length, cl_int *errcode_ret, @@ -3912,8 +3688,7 @@ void CaptureCreateProgramWithIL_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCloneKernel_errcode_ret(bool isCallValid, - cl_kernel source_kernel, +void CaptureCloneKernel_errcode_ret(cl_kernel source_kernel, cl_int *errcode_ret, angle::ParamCapture *paramCapture) { @@ -3922,8 +3697,7 @@ void CaptureCloneKernel_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureGetKernelSubGroupInfo_input_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelSubGroupInfo_input_value(cl_kernel kernel, cl_device_id device, KernelSubGroupInfo param_namePacked, size_t input_value_size, @@ -3938,8 +3712,7 @@ void CaptureGetKernelSubGroupInfo_input_value(bool isCallValid, CaptureMemory(input_value, input_value_size, paramCapture); } } -void CaptureGetKernelSubGroupInfo_param_value(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelSubGroupInfo_param_value(cl_kernel kernel, cl_device_id device, KernelSubGroupInfo param_namePacked, size_t input_value_size, @@ -3954,8 +3727,7 @@ void CaptureGetKernelSubGroupInfo_param_value(bool isCallValid, paramCapture->readBufferSizeBytes = param_value_size; } } -void CaptureGetKernelSubGroupInfo_param_value_size_ret(bool isCallValid, - cl_kernel kernel, +void CaptureGetKernelSubGroupInfo_param_value_size_ret(cl_kernel kernel, cl_device_id device, KernelSubGroupInfo param_namePacked, size_t input_value_size, @@ -3970,8 +3742,7 @@ void CaptureGetKernelSubGroupInfo_param_value_size_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(size_t); } } -void CaptureEnqueueSVMMigrateMem_svm_pointers(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_svm_pointers(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -3987,8 +3758,7 @@ void CaptureEnqueueSVMMigrateMem_svm_pointers(bool isCallValid, svm_pointers, num_svm_pointers, paramCapture); } } -void CaptureEnqueueSVMMigrateMem_sizes(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_sizes(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -4003,8 +3773,7 @@ void CaptureEnqueueSVMMigrateMem_sizes(bool isCallValid, CaptureMemory(sizes, num_svm_pointers * sizeof(size_t), paramCapture); } } -void CaptureEnqueueSVMMigrateMem_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_event_wait_list(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -4021,8 +3790,7 @@ void CaptureEnqueueSVMMigrateMem_event_wait_list(bool isCallValid, &angle::FrameCaptureShared::getIndex); } } -void CaptureEnqueueSVMMigrateMem_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueSVMMigrateMem_event(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers, const size_t *sizes, @@ -4038,8 +3806,7 @@ void CaptureEnqueueSVMMigrateMem_event(bool isCallValid, cl::Platform::GetDefault()->getFrameCaptureShared()->setIndex(event); } } -void CaptureSetProgramReleaseCallback_pfn_notify(bool isCallValid, - cl_program program, +void CaptureSetProgramReleaseCallback_pfn_notify(cl_program program, void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data, @@ -4047,8 +3814,7 @@ void CaptureSetProgramReleaseCallback_pfn_notify(bool isCallValid, { // Nothing to implement } -void CaptureSetProgramReleaseCallback_user_data(bool isCallValid, - cl_program program, +void CaptureSetProgramReleaseCallback_user_data(cl_program program, void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data, @@ -4057,8 +3823,7 @@ void CaptureSetProgramReleaseCallback_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureSetProgramSpecializationConstant_spec_value(bool isCallValid, - cl_program program, +void CaptureSetProgramSpecializationConstant_spec_value(cl_program program, cl_uint spec_id, size_t spec_size, const void *spec_value, @@ -4070,7 +3835,6 @@ void CaptureSetProgramSpecializationConstant_spec_value(bool isCallValid, } } void CaptureSetContextDestructorCallback_pfn_notify( - bool isCallValid, cl_context context, void(CL_CALLBACK *pfn_notify)(cl_context context, void *user_data), void *user_data, @@ -4078,8 +3842,7 @@ void CaptureSetContextDestructorCallback_pfn_notify( { // Nothing to implement } -void CaptureSetContextDestructorCallback_user_data(bool isCallValid, - cl_context context, +void CaptureSetContextDestructorCallback_user_data(cl_context context, void(CL_CALLBACK *pfn_notify)(cl_context context, void *user_data), void *user_data, @@ -4088,8 +3851,7 @@ void CaptureSetContextDestructorCallback_user_data(bool isCallValid, InitParamValue(angle::ParamType::TvoidPointer, static_cast(nullptr), ¶mCapture->value); } -void CaptureCreateBufferWithProperties_properties(bool isCallValid, - cl_context context, +void CaptureCreateBufferWithProperties_properties(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, size_t size, @@ -4106,8 +3868,7 @@ void CaptureCreateBufferWithProperties_properties(bool isCallValid, CaptureMemory(properties, propertiesSize, paramCapture); } } -void CaptureCreateBufferWithProperties_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateBufferWithProperties_host_ptr(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, size_t size, @@ -4120,8 +3881,7 @@ void CaptureCreateBufferWithProperties_host_ptr(bool isCallValid, CaptureMemory(host_ptr, size, paramCapture); } } -void CaptureCreateBufferWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateBufferWithProperties_errcode_ret(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, size_t size, @@ -4134,8 +3894,7 @@ void CaptureCreateBufferWithProperties_errcode_ret(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_int); } } -void CaptureCreateImageWithProperties_properties(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_properties(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -4149,8 +3908,7 @@ void CaptureCreateImageWithProperties_properties(bool isCallValid, CaptureMemory(properties, sizeof(cl_mem_properties), paramCapture); } } -void CaptureCreateImageWithProperties_image_format(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_image_format(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -4164,8 +3922,7 @@ void CaptureCreateImageWithProperties_image_format(bool isCallValid, CaptureMemory(image_format, sizeof(cl_image_format), paramCapture); } } -void CaptureCreateImageWithProperties_image_desc(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_image_desc(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -4179,8 +3936,7 @@ void CaptureCreateImageWithProperties_image_desc(bool isCallValid, CaptureMemory(image_desc, sizeof(cl_image_desc), paramCapture); } } -void CaptureCreateImageWithProperties_host_ptr(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_host_ptr(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -4218,8 +3974,7 @@ void CaptureCreateImageWithProperties_host_ptr(bool isCallValid, CaptureMemory(host_ptr, sizeof(image_size), paramCapture); } } -void CaptureCreateImageWithProperties_errcode_ret(bool isCallValid, - cl_context context, +void CaptureCreateImageWithProperties_errcode_ret(cl_context context, const cl_mem_properties *properties, MemFlags flagsPacked, const cl_image_format *image_format, @@ -4234,8 +3989,7 @@ void CaptureCreateImageWithProperties_errcode_ret(bool isCallValid, } } -void CaptureEnqueueAcquireExternalMemObjectsKHR_mem_objects(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueAcquireExternalMemObjectsKHR_mem_objects(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, cl_uint num_events_in_wait_list, @@ -4250,8 +4004,7 @@ void CaptureEnqueueAcquireExternalMemObjectsKHR_mem_objects(bool isCallValid, } } -void CaptureEnqueueAcquireExternalMemObjectsKHR_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueAcquireExternalMemObjectsKHR_event_wait_list(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, cl_uint num_events_in_wait_list, @@ -4267,8 +4020,7 @@ void CaptureEnqueueAcquireExternalMemObjectsKHR_event_wait_list(bool isCallValid } } -void CaptureEnqueueAcquireExternalMemObjectsKHR_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueAcquireExternalMemObjectsKHR_event(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, cl_uint num_events_in_wait_list, @@ -4283,8 +4035,7 @@ void CaptureEnqueueAcquireExternalMemObjectsKHR_event(bool isCallValid, } } -void CaptureEnqueueReleaseExternalMemObjectsKHR_mem_objects(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReleaseExternalMemObjectsKHR_mem_objects(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, cl_uint num_events_in_wait_list, @@ -4299,8 +4050,7 @@ void CaptureEnqueueReleaseExternalMemObjectsKHR_mem_objects(bool isCallValid, } } -void CaptureEnqueueReleaseExternalMemObjectsKHR_event_wait_list(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReleaseExternalMemObjectsKHR_event_wait_list(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, cl_uint num_events_in_wait_list, @@ -4316,8 +4066,7 @@ void CaptureEnqueueReleaseExternalMemObjectsKHR_event_wait_list(bool isCallValid } } -void CaptureEnqueueReleaseExternalMemObjectsKHR_event(bool isCallValid, - cl_command_queue command_queue, +void CaptureEnqueueReleaseExternalMemObjectsKHR_event(cl_command_queue command_queue, cl_uint num_mem_objects, const cl_mem *mem_objects, cl_uint num_events_in_wait_list, @@ -4332,8 +4081,49 @@ void CaptureEnqueueReleaseExternalMemObjectsKHR_event(bool isCallValid, } } -void CaptureIcdGetPlatformIDsKHR_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureImportMemoryARM_properties(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + angle::ParamCapture *paramCapture) +{ + if (properties) + { + CaptureMemory(properties, sizeof(cl_import_properties_arm), paramCapture); + } +} + +void CaptureImportMemoryARM_memory(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + angle::ParamCapture *paramCapture) +{ + if (memory) + { + CaptureMemory(memory, sizeof(void *), paramCapture); + } +} + +void CaptureImportMemoryARM_errcode_ret(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret, + angle::ParamCapture *paramCapture) +{ + if (errcode_ret) + { + paramCapture->readBufferSizeBytes = sizeof(cl_int); + } +} + +void CaptureIcdGetPlatformIDsKHR_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture) @@ -4344,8 +4134,7 @@ void CaptureIcdGetPlatformIDsKHR_platforms(bool isCallValid, num_entries); } } -void CaptureIcdGetPlatformIDsKHR_num_platforms(bool isCallValid, - cl_uint num_entries, +void CaptureIcdGetPlatformIDsKHR_num_platforms(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms, angle::ParamCapture *paramCapture) @@ -4355,4 +4144,21 @@ void CaptureIcdGetPlatformIDsKHR_num_platforms(bool isCallValid, paramCapture->readBufferSizeBytes = sizeof(cl_uint); } } + +void CaptureIcdGetFunctionAddressForPlatformKHR_func_name(cl_platform_id platform, + const char *func_name, + angle::ParamCapture *paramCapture) +{ + // TODO: Implement this later + // http://anglebug.com/441956395 +} + +void CaptureIcdSetPlatformDispatchDataKHR_dispatch_data(cl_platform_id platform, + void *dispatch_data, + angle::ParamCapture *paramCapture) +{ + // TODO: Implement this later + // http://anglebug.com/441956395 +} + } // namespace cl diff --git a/src/libANGLE/capture/capture_egl_autogen.cpp b/src/libANGLE/capture/capture_egl_autogen.cpp index ec39e891ac7..39911f9374d 100644 --- a/src/libANGLE/capture/capture_egl_autogen.cpp +++ b/src/libANGLE/capture/capture_egl_autogen.cpp @@ -1392,27 +1392,6 @@ CallCapture CaptureStreamPostD3DTextureANGLE(egl::Thread *thread, return CallCapture(angle::EntryPoint::EGLStreamPostD3DTextureANGLE, std::move(paramBuffer)); } -CallCapture CaptureSwapBuffersWithFrameTokenANGLE(egl::Thread *thread, - bool isCallValid, - egl::Display *dpyPacked, - SurfaceID surfacePacked, - EGLFrameTokenANGLE frametoken, - EGLBoolean returnValue) -{ - ParamBuffer paramBuffer; - - paramBuffer.addValueParam("dpyPacked", ParamType::Tegl_DisplayPointer, dpyPacked); - paramBuffer.addValueParam("surfacePacked", ParamType::TSurfaceID, surfacePacked); - paramBuffer.addValueParam("frametoken", ParamType::TEGLFrameTokenANGLE, frametoken); - - ParamCapture returnValueCapture("returnValue", ParamType::TEGLBoolean); - InitParamValue(ParamType::TEGLBoolean, returnValue, &returnValueCapture.value); - paramBuffer.addReturnValue(std::move(returnValueCapture)); - - return CallCapture(angle::EntryPoint::EGLSwapBuffersWithFrameTokenANGLE, - std::move(paramBuffer)); -} - CallCapture CaptureGetMscRateANGLE(egl::Thread *thread, bool isCallValid, egl::Display *dpyPacked, diff --git a/src/libANGLE/capture/capture_egl_autogen.h b/src/libANGLE/capture/capture_egl_autogen.h index dac07c68468..8a105b914dd 100644 --- a/src/libANGLE/capture/capture_egl_autogen.h +++ b/src/libANGLE/capture/capture_egl_autogen.h @@ -426,12 +426,6 @@ angle::CallCapture CaptureStreamPostD3DTextureANGLE(egl::Thread *thread, void *texture, const AttributeMap &attrib_listPacked, EGLBoolean returnValue); -angle::CallCapture CaptureSwapBuffersWithFrameTokenANGLE(egl::Thread *thread, - bool isCallValid, - egl::Display *dpyPacked, - SurfaceID surfacePacked, - EGLFrameTokenANGLE frametoken, - EGLBoolean returnValue); angle::CallCapture CaptureGetMscRateANGLE(egl::Thread *thread, bool isCallValid, egl::Display *dpyPacked, diff --git a/src/libANGLE/capture/capture_gles_1_0_autogen.cpp b/src/libANGLE/capture/capture_gles_1_0_autogen.cpp index 06e064522ac..25a35cc92a9 100644 --- a/src/libANGLE/capture/capture_gles_1_0_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_1_0_autogen.cpp @@ -86,20 +86,18 @@ CallCapture CaptureClipPlanef(const State &glState, bool isCallValid, GLenum p, paramBuffer.addEnumParam("p", GLESEnum::ClipPlaneName, ParamType::TGLenum, p); + ParamCapture eqnParam("eqn", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture eqnParam("eqn", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, eqn, &eqnParam.value); - CaptureClipPlanef_eqn(glState, isCallValid, p, eqn, &eqnParam); - paramBuffer.addParam(std::move(eqnParam)); + CaptureClipPlanef_eqn(glState, p, eqn, &eqnParam); } else { - ParamCapture eqnParam("eqn", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &eqnParam.value); - paramBuffer.addParam(std::move(eqnParam)); } + paramBuffer.addParam(std::move(eqnParam)); return CallCapture(angle::EntryPoint::GLClipPlanef, std::move(paramBuffer)); } @@ -113,20 +111,18 @@ CallCapture CaptureClipPlanex(const State &glState, paramBuffer.addEnumParam("plane", GLESEnum::ClipPlaneName, ParamType::TGLenum, plane); + ParamCapture equationParam("equation", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture equationParam("equation", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, equation, &equationParam.value); - CaptureClipPlanex_equation(glState, isCallValid, plane, equation, &equationParam); - paramBuffer.addParam(std::move(equationParam)); + CaptureClipPlanex_equation(glState, plane, equation, &equationParam); } else { - ParamCapture equationParam("equation", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), &equationParam.value); - paramBuffer.addParam(std::move(equationParam)); } + paramBuffer.addParam(std::move(equationParam)); return CallCapture(angle::EntryPoint::GLClipPlanex, std::move(paramBuffer)); } @@ -195,21 +191,18 @@ CallCapture CaptureColorPointer(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TVertexAttribType, typePacked); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureColorPointer_pointer(glState, isCallValid, size, typePacked, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureColorPointer_pointer(glState, size, typePacked, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLColorPointer, std::move(paramBuffer)); } @@ -265,20 +258,18 @@ CallCapture CaptureFogfv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::FogParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureFogfv_params(glState, isCallValid, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureFogfv_params(glState, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLFogfv, std::move(paramBuffer)); } @@ -299,20 +290,18 @@ CallCapture CaptureFogxv(const State &glState, bool isCallValid, GLenum pname, c paramBuffer.addEnumParam("pname", GLESEnum::FogPName, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, param, ¶mParam.value); - CaptureFogxv_param(glState, isCallValid, pname, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureFogxv_param(glState, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLFogxv, std::move(paramBuffer)); } @@ -368,20 +357,18 @@ CallCapture CaptureGetClipPlanef(const State &glState, paramBuffer.addEnumParam("plane", GLESEnum::ClipPlaneName, ParamType::TGLenum, plane); + ParamCapture equationParam("equation", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture equationParam("equation", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, equation, &equationParam.value); - CaptureGetClipPlanef_equation(glState, isCallValid, plane, equation, &equationParam); - paramBuffer.addParam(std::move(equationParam)); + CaptureGetClipPlanef_equation(glState, plane, equation, &equationParam); } else { - ParamCapture equationParam("equation", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), &equationParam.value); - paramBuffer.addParam(std::move(equationParam)); } + paramBuffer.addParam(std::move(equationParam)); return CallCapture(angle::EntryPoint::GLGetClipPlanef, std::move(paramBuffer)); } @@ -395,20 +382,18 @@ CallCapture CaptureGetClipPlanex(const State &glState, paramBuffer.addEnumParam("plane", GLESEnum::ClipPlaneName, ParamType::TGLenum, plane); + ParamCapture equationParam("equation", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture equationParam("equation", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, equation, &equationParam.value); - CaptureGetClipPlanex_equation(glState, isCallValid, plane, equation, &equationParam); - paramBuffer.addParam(std::move(equationParam)); + CaptureGetClipPlanex_equation(glState, plane, equation, &equationParam); } else { - ParamCapture equationParam("equation", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), &equationParam.value); - paramBuffer.addParam(std::move(equationParam)); } + paramBuffer.addParam(std::move(equationParam)); return CallCapture(angle::EntryPoint::GLGetClipPlanex, std::move(paramBuffer)); } @@ -419,20 +404,18 @@ CallCapture CaptureGetFixedv(const State &glState, bool isCallValid, GLenum pnam paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, params, ¶msParam.value); - CaptureGetFixedv_params(glState, isCallValid, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFixedv_params(glState, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFixedv, std::move(paramBuffer)); } @@ -448,20 +431,18 @@ CallCapture CaptureGetLightfv(const State &glState, paramBuffer.addEnumParam("light", GLESEnum::LightName, ParamType::TGLenum, light); paramBuffer.addValueParam("pnamePacked", ParamType::TLightParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetLightfv_params(glState, isCallValid, light, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetLightfv_params(glState, light, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetLightfv, std::move(paramBuffer)); } @@ -477,20 +458,18 @@ CallCapture CaptureGetLightxv(const State &glState, paramBuffer.addEnumParam("light", GLESEnum::LightName, ParamType::TGLenum, light); paramBuffer.addValueParam("pnamePacked", ParamType::TLightParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, params, ¶msParam.value); - CaptureGetLightxv_params(glState, isCallValid, light, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetLightxv_params(glState, light, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetLightxv, std::move(paramBuffer)); } @@ -506,20 +485,18 @@ CallCapture CaptureGetMaterialfv(const State &glState, paramBuffer.addEnumParam("face", GLESEnum::TriangleFace, ParamType::TGLenum, face); paramBuffer.addValueParam("pnamePacked", ParamType::TMaterialParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetMaterialfv_params(glState, isCallValid, face, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetMaterialfv_params(glState, face, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetMaterialfv, std::move(paramBuffer)); } @@ -535,20 +512,18 @@ CallCapture CaptureGetMaterialxv(const State &glState, paramBuffer.addEnumParam("face", GLESEnum::TriangleFace, ParamType::TGLenum, face); paramBuffer.addValueParam("pnamePacked", ParamType::TMaterialParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, params, ¶msParam.value); - CaptureGetMaterialxv_params(glState, isCallValid, face, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetMaterialxv_params(glState, face, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetMaterialxv, std::move(paramBuffer)); } @@ -564,21 +539,18 @@ CallCapture CaptureGetTexEnvfv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureEnvTarget, targetPacked); paramBuffer.addValueParam("pnamePacked", ParamType::TTextureEnvParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexEnvfv_params(glState, isCallValid, targetPacked, pnamePacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexEnvfv_params(glState, targetPacked, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexEnvfv, std::move(paramBuffer)); } @@ -594,20 +566,17 @@ CallCapture CaptureGetTexEnviv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureEnvTarget, targetPacked); paramBuffer.addValueParam("pnamePacked", ParamType::TTextureEnvParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexEnviv_params(glState, isCallValid, targetPacked, pnamePacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexEnviv_params(glState, targetPacked, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexEnviv, std::move(paramBuffer)); } @@ -623,21 +592,18 @@ CallCapture CaptureGetTexEnvxv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureEnvTarget, targetPacked); paramBuffer.addValueParam("pnamePacked", ParamType::TTextureEnvParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, params, ¶msParam.value); - CaptureGetTexEnvxv_params(glState, isCallValid, targetPacked, pnamePacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexEnvxv_params(glState, targetPacked, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexEnvxv, std::move(paramBuffer)); } @@ -653,21 +619,18 @@ CallCapture CaptureGetTexParameterxv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, params, ¶msParam.value); - CaptureGetTexParameterxv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterxv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterxv, std::move(paramBuffer)); } @@ -691,20 +654,18 @@ CallCapture CaptureLightModelfv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::LightModelParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureLightModelfv_params(glState, isCallValid, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureLightModelfv_params(glState, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLLightModelfv, std::move(paramBuffer)); } @@ -728,20 +689,18 @@ CallCapture CaptureLightModelxv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::LightModelParameter, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, param, ¶mParam.value); - CaptureLightModelxv_param(glState, isCallValid, pname, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureLightModelxv_param(glState, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLLightModelxv, std::move(paramBuffer)); } @@ -772,20 +731,18 @@ CallCapture CaptureLightfv(const State &glState, paramBuffer.addEnumParam("light", GLESEnum::LightName, ParamType::TGLenum, light); paramBuffer.addValueParam("pnamePacked", ParamType::TLightParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureLightfv_params(glState, isCallValid, light, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureLightfv_params(glState, light, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLLightfv, std::move(paramBuffer)); } @@ -816,20 +773,18 @@ CallCapture CaptureLightxv(const State &glState, paramBuffer.addEnumParam("light", GLESEnum::LightName, ParamType::TGLenum, light); paramBuffer.addValueParam("pnamePacked", ParamType::TLightParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, params, ¶msParam.value); - CaptureLightxv_params(glState, isCallValid, light, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureLightxv_params(glState, light, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLLightxv, std::move(paramBuffer)); } @@ -854,20 +809,18 @@ CallCapture CaptureLoadMatrixf(const State &glState, bool isCallValid, const GLf { ParamBuffer paramBuffer; + ParamCapture mParam("m", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture mParam("m", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, m, &mParam.value); - CaptureLoadMatrixf_m(glState, isCallValid, m, &mParam); - paramBuffer.addParam(std::move(mParam)); + CaptureLoadMatrixf_m(glState, m, &mParam); } else { - ParamCapture mParam("m", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &mParam.value); - paramBuffer.addParam(std::move(mParam)); } + paramBuffer.addParam(std::move(mParam)); return CallCapture(angle::EntryPoint::GLLoadMatrixf, std::move(paramBuffer)); } @@ -876,20 +829,18 @@ CallCapture CaptureLoadMatrixx(const State &glState, bool isCallValid, const GLf { ParamBuffer paramBuffer; + ParamCapture mParam("m", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture mParam("m", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, m, &mParam.value); - CaptureLoadMatrixx_m(glState, isCallValid, m, &mParam); - paramBuffer.addParam(std::move(mParam)); + CaptureLoadMatrixx_m(glState, m, &mParam); } else { - ParamCapture mParam("m", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), &mParam.value); - paramBuffer.addParam(std::move(mParam)); } + paramBuffer.addParam(std::move(mParam)); return CallCapture(angle::EntryPoint::GLLoadMatrixx, std::move(paramBuffer)); } @@ -929,20 +880,18 @@ CallCapture CaptureMaterialfv(const State &glState, paramBuffer.addEnumParam("face", GLESEnum::TriangleFace, ParamType::TGLenum, face); paramBuffer.addValueParam("pnamePacked", ParamType::TMaterialParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureMaterialfv_params(glState, isCallValid, face, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureMaterialfv_params(glState, face, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLMaterialfv, std::move(paramBuffer)); } @@ -973,20 +922,18 @@ CallCapture CaptureMaterialxv(const State &glState, paramBuffer.addEnumParam("face", GLESEnum::TriangleFace, ParamType::TGLenum, face); paramBuffer.addValueParam("pnamePacked", ParamType::TMaterialParameter, pnamePacked); + ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, param, ¶mParam.value); - CaptureMaterialxv_param(glState, isCallValid, face, pnamePacked, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureMaterialxv_param(glState, face, pnamePacked, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLMaterialxv, std::move(paramBuffer)); } @@ -1004,20 +951,18 @@ CallCapture CaptureMultMatrixf(const State &glState, bool isCallValid, const GLf { ParamBuffer paramBuffer; + ParamCapture mParam("m", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture mParam("m", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, m, &mParam.value); - CaptureMultMatrixf_m(glState, isCallValid, m, &mParam); - paramBuffer.addParam(std::move(mParam)); + CaptureMultMatrixf_m(glState, m, &mParam); } else { - ParamCapture mParam("m", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &mParam.value); - paramBuffer.addParam(std::move(mParam)); } + paramBuffer.addParam(std::move(mParam)); return CallCapture(angle::EntryPoint::GLMultMatrixf, std::move(paramBuffer)); } @@ -1026,20 +971,18 @@ CallCapture CaptureMultMatrixx(const State &glState, bool isCallValid, const GLf { ParamBuffer paramBuffer; + ParamCapture mParam("m", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture mParam("m", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, m, &mParam.value); - CaptureMultMatrixx_m(glState, isCallValid, m, &mParam); - paramBuffer.addParam(std::move(mParam)); + CaptureMultMatrixx_m(glState, m, &mParam); } else { - ParamCapture mParam("m", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), &mParam.value); - paramBuffer.addParam(std::move(mParam)); } + paramBuffer.addParam(std::move(mParam)); return CallCapture(angle::EntryPoint::GLMultMatrixx, std::move(paramBuffer)); } @@ -1123,21 +1066,18 @@ CallCapture CaptureNormalPointer(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TVertexAttribType, typePacked); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureNormalPointer_pointer(glState, isCallValid, typePacked, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureNormalPointer_pointer(glState, typePacked, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLNormalPointer, std::move(paramBuffer)); } @@ -1206,20 +1146,18 @@ CallCapture CapturePointParameterfv(const State &glState, paramBuffer.addValueParam("pnamePacked", ParamType::TPointParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CapturePointParameterfv_params(glState, isCallValid, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CapturePointParameterfv_params(glState, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLPointParameterfv, std::move(paramBuffer)); } @@ -1246,20 +1184,18 @@ CallCapture CapturePointParameterxv(const State &glState, paramBuffer.addValueParam("pnamePacked", ParamType::TPointParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, params, ¶msParam.value); - CapturePointParameterxv_params(glState, isCallValid, pnamePacked, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CapturePointParameterxv_params(glState, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLPointParameterxv, std::move(paramBuffer)); } @@ -1400,21 +1336,18 @@ CallCapture CaptureTexCoordPointer(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TVertexAttribType, typePacked); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureTexCoordPointer_pointer(glState, isCallValid, size, typePacked, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureTexCoordPointer_pointer(glState, size, typePacked, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLTexCoordPointer, std::move(paramBuffer)); } @@ -1445,21 +1378,18 @@ CallCapture CaptureTexEnvfv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureEnvTarget, targetPacked); paramBuffer.addValueParam("pnamePacked", ParamType::TTextureEnvParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureTexEnvfv_params(glState, isCallValid, targetPacked, pnamePacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexEnvfv_params(glState, targetPacked, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexEnvfv, std::move(paramBuffer)); } @@ -1490,21 +1420,18 @@ CallCapture CaptureTexEnviv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureEnvTarget, targetPacked); paramBuffer.addValueParam("pnamePacked", ParamType::TTextureEnvParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexEnviv_params(glState, isCallValid, targetPacked, pnamePacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexEnviv_params(glState, targetPacked, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexEnviv, std::move(paramBuffer)); } @@ -1535,21 +1462,18 @@ CallCapture CaptureTexEnvxv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureEnvTarget, targetPacked); paramBuffer.addValueParam("pnamePacked", ParamType::TTextureEnvParameter, pnamePacked); + ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, params, ¶msParam.value); - CaptureTexEnvxv_params(glState, isCallValid, targetPacked, pnamePacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexEnvxv_params(glState, targetPacked, pnamePacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexEnvxv, std::move(paramBuffer)); } @@ -1580,21 +1504,18 @@ CallCapture CaptureTexParameterxv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, params, ¶msParam.value); - CaptureTexParameterxv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterxv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterxv, std::move(paramBuffer)); } @@ -1642,21 +1563,18 @@ CallCapture CaptureVertexPointer(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TVertexAttribType, typePacked); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureVertexPointer_pointer(glState, isCallValid, size, typePacked, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureVertexPointer_pointer(glState, size, typePacked, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLVertexPointer, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_1_0_autogen.h b/src/libANGLE/capture/capture_gles_1_0_autogen.h index 530dcbaad0e..b50b28780c9 100644 --- a/src/libANGLE/capture/capture_gles_1_0_autogen.h +++ b/src/libANGLE/capture/capture_gles_1_0_autogen.h @@ -387,194 +387,159 @@ angle::CallCapture CaptureVertexPointer(const State &glState, // Parameter Captures void CaptureClipPlanef_eqn(const State &glState, - bool isCallValid, GLenum p, const GLfloat *eqn, angle::ParamCapture *paramCapture); void CaptureClipPlanex_equation(const State &glState, - bool isCallValid, GLenum plane, const GLfixed *equation, angle::ParamCapture *paramCapture); void CaptureColorPointer_pointer(const State &glState, - bool isCallValid, GLint size, VertexAttribType typePacked, GLsizei stride, const void *pointer, angle::ParamCapture *paramCapture); void CaptureFogfv_params(const State &glState, - bool isCallValid, GLenum pname, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureFogxv_param(const State &glState, - bool isCallValid, GLenum pname, const GLfixed *param, angle::ParamCapture *paramCapture); void CaptureGetClipPlanef_equation(const State &glState, - bool isCallValid, GLenum plane, GLfloat *equation, angle::ParamCapture *paramCapture); void CaptureGetClipPlanex_equation(const State &glState, - bool isCallValid, GLenum plane, GLfixed *equation, angle::ParamCapture *paramCapture); void CaptureGetFixedv_params(const State &glState, - bool isCallValid, GLenum pname, GLfixed *params, angle::ParamCapture *paramCapture); void CaptureGetLightfv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetLightxv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, GLfixed *params, angle::ParamCapture *paramCapture); void CaptureGetMaterialfv_params(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetMaterialxv_params(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, GLfixed *params, angle::ParamCapture *paramCapture); void CaptureGetTexEnvfv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexEnviv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexEnvxv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLfixed *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterxv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLfixed *params, angle::ParamCapture *paramCapture); void CaptureLightModelfv_params(const State &glState, - bool isCallValid, GLenum pname, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureLightModelxv_param(const State &glState, - bool isCallValid, GLenum pname, const GLfixed *param, angle::ParamCapture *paramCapture); void CaptureLightfv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureLightxv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, const GLfixed *params, angle::ParamCapture *paramCapture); void CaptureLoadMatrixf_m(const State &glState, - bool isCallValid, const GLfloat *m, angle::ParamCapture *paramCapture); void CaptureLoadMatrixx_m(const State &glState, - bool isCallValid, const GLfixed *m, angle::ParamCapture *paramCapture); void CaptureMaterialfv_params(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureMaterialxv_param(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, const GLfixed *param, angle::ParamCapture *paramCapture); void CaptureMultMatrixf_m(const State &glState, - bool isCallValid, const GLfloat *m, angle::ParamCapture *paramCapture); void CaptureMultMatrixx_m(const State &glState, - bool isCallValid, const GLfixed *m, angle::ParamCapture *paramCapture); void CaptureNormalPointer_pointer(const State &glState, - bool isCallValid, VertexAttribType typePacked, GLsizei stride, const void *pointer, angle::ParamCapture *paramCapture); void CapturePointParameterfv_params(const State &glState, - bool isCallValid, PointParameter pnamePacked, const GLfloat *params, angle::ParamCapture *paramCapture); void CapturePointParameterxv_params(const State &glState, - bool isCallValid, PointParameter pnamePacked, const GLfixed *params, angle::ParamCapture *paramCapture); void CaptureTexCoordPointer_pointer(const State &glState, - bool isCallValid, GLint size, VertexAttribType typePacked, GLsizei stride, const void *pointer, angle::ParamCapture *paramCapture); void CaptureTexEnvfv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureTexEnviv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexEnvxv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, const GLfixed *params, angle::ParamCapture *paramCapture); void CaptureTexParameterxv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLfixed *params, angle::ParamCapture *paramCapture); void CaptureVertexPointer_pointer(const State &glState, - bool isCallValid, GLint size, VertexAttribType typePacked, GLsizei stride, diff --git a/src/libANGLE/capture/capture_gles_1_0_params.cpp b/src/libANGLE/capture/capture_gles_1_0_params.cpp index fe8af795d98..883f874d8c4 100644 --- a/src/libANGLE/capture/capture_gles_1_0_params.cpp +++ b/src/libANGLE/capture/capture_gles_1_0_params.cpp @@ -15,7 +15,6 @@ namespace gl { void CaptureClipPlanef_eqn(const State &glState, - bool isCallValid, GLenum p, const GLfloat *eqn, ParamCapture *paramCapture) @@ -24,7 +23,6 @@ void CaptureClipPlanef_eqn(const State &glState, } void CaptureClipPlanex_equation(const State &glState, - bool isCallValid, GLenum plane, const GLfixed *equation, ParamCapture *paramCapture) @@ -33,7 +31,6 @@ void CaptureClipPlanex_equation(const State &glState, } void CaptureColorPointer_pointer(const State &glState, - bool isCallValid, GLint size, VertexAttribType typePacked, GLsizei stride, @@ -44,7 +41,6 @@ void CaptureColorPointer_pointer(const State &glState, } void CaptureFogfv_params(const State &glState, - bool isCallValid, GLenum pname, const GLfloat *params, ParamCapture *paramCapture) @@ -54,7 +50,6 @@ void CaptureFogfv_params(const State &glState, } void CaptureFogxv_param(const State &glState, - bool isCallValid, GLenum pname, const GLfixed *param, ParamCapture *paramCapture) @@ -63,7 +58,6 @@ void CaptureFogxv_param(const State &glState, } void CaptureGetClipPlanef_equation(const State &glState, - bool isCallValid, GLenum plane, GLfloat *equation, ParamCapture *paramCapture) @@ -72,7 +66,6 @@ void CaptureGetClipPlanef_equation(const State &glState, } void CaptureGetClipPlanex_equation(const State &glState, - bool isCallValid, GLenum plane, GLfixed *equation, ParamCapture *paramCapture) @@ -81,7 +74,6 @@ void CaptureGetClipPlanex_equation(const State &glState, } void CaptureGetFixedv_params(const State &glState, - bool isCallValid, GLenum pname, GLfixed *params, ParamCapture *paramCapture) @@ -90,7 +82,6 @@ void CaptureGetFixedv_params(const State &glState, } void CaptureGetLightfv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, GLfloat *params, @@ -101,7 +92,6 @@ void CaptureGetLightfv_params(const State &glState, } void CaptureGetLightxv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, GLfixed *params, @@ -111,7 +101,6 @@ void CaptureGetLightxv_params(const State &glState, } void CaptureGetMaterialfv_params(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, GLfloat *params, @@ -122,7 +111,6 @@ void CaptureGetMaterialfv_params(const State &glState, } void CaptureGetMaterialxv_params(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, GLfixed *params, @@ -132,7 +120,6 @@ void CaptureGetMaterialxv_params(const State &glState, } void CaptureGetTexEnvfv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLfloat *params, @@ -143,7 +130,6 @@ void CaptureGetTexEnvfv_params(const State &glState, } void CaptureGetTexEnviv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLint *params, @@ -153,7 +139,6 @@ void CaptureGetTexEnviv_params(const State &glState, } void CaptureGetTexEnvxv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLfixed *params, @@ -163,7 +148,6 @@ void CaptureGetTexEnvxv_params(const State &glState, } void CaptureGetTexParameterxv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLfixed *params, @@ -174,7 +158,6 @@ void CaptureGetTexParameterxv_params(const State &glState, } void CaptureLightModelfv_params(const State &glState, - bool isCallValid, GLenum pname, const GLfloat *params, ParamCapture *paramCapture) @@ -184,7 +167,6 @@ void CaptureLightModelfv_params(const State &glState, } void CaptureLightModelxv_param(const State &glState, - bool isCallValid, GLenum pname, const GLfixed *param, ParamCapture *paramCapture) @@ -194,7 +176,6 @@ void CaptureLightModelxv_param(const State &glState, } void CaptureLightfv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, const GLfloat *params, @@ -205,7 +186,6 @@ void CaptureLightfv_params(const State &glState, } void CaptureLightxv_params(const State &glState, - bool isCallValid, GLenum light, LightParameter pnamePacked, const GLfixed *params, @@ -215,24 +195,17 @@ void CaptureLightxv_params(const State &glState, CaptureMemory(params, sizeof(GLfixed) * size, paramCapture); } -void CaptureLoadMatrixf_m(const State &glState, - bool isCallValid, - const GLfloat *m, - ParamCapture *paramCapture) +void CaptureLoadMatrixf_m(const State &glState, const GLfloat *m, ParamCapture *paramCapture) { CaptureMemory(m, sizeof(GLfloat) * 16, paramCapture); } -void CaptureLoadMatrixx_m(const State &glState, - bool isCallValid, - const GLfixed *m, - ParamCapture *paramCapture) +void CaptureLoadMatrixx_m(const State &glState, const GLfixed *m, ParamCapture *paramCapture) { UNIMPLEMENTED(); } void CaptureMaterialfv_params(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, const GLfloat *params, @@ -243,7 +216,6 @@ void CaptureMaterialfv_params(const State &glState, } void CaptureMaterialxv_param(const State &glState, - bool isCallValid, GLenum face, MaterialParameter pnamePacked, const GLfixed *param, @@ -253,24 +225,17 @@ void CaptureMaterialxv_param(const State &glState, CaptureMemory(param, sizeof(GLfixed) * size, paramCapture); } -void CaptureMultMatrixf_m(const State &glState, - bool isCallValid, - const GLfloat *m, - ParamCapture *paramCapture) +void CaptureMultMatrixf_m(const State &glState, const GLfloat *m, ParamCapture *paramCapture) { CaptureMemory(m, sizeof(GLfloat) * 16, paramCapture); } -void CaptureMultMatrixx_m(const State &glState, - bool isCallValid, - const GLfixed *m, - ParamCapture *paramCapture) +void CaptureMultMatrixx_m(const State &glState, const GLfixed *m, ParamCapture *paramCapture) { UNIMPLEMENTED(); } void CaptureNormalPointer_pointer(const State &glState, - bool isCallValid, VertexAttribType typePacked, GLsizei stride, const void *pointer, @@ -280,7 +245,6 @@ void CaptureNormalPointer_pointer(const State &glState, } void CapturePointParameterfv_params(const State &glState, - bool isCallValid, PointParameter pnamePacked, const GLfloat *params, ParamCapture *paramCapture) @@ -289,7 +253,6 @@ void CapturePointParameterfv_params(const State &glState, } void CapturePointParameterxv_params(const State &glState, - bool isCallValid, PointParameter pnamePacked, const GLfixed *params, ParamCapture *paramCapture) @@ -298,7 +261,6 @@ void CapturePointParameterxv_params(const State &glState, } void CaptureTexCoordPointer_pointer(const State &glState, - bool isCallValid, GLint size, VertexAttribType typePacked, GLsizei stride, @@ -309,7 +271,6 @@ void CaptureTexCoordPointer_pointer(const State &glState, } void CaptureTexEnvfv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, const GLfloat *params, @@ -320,7 +281,6 @@ void CaptureTexEnvfv_params(const State &glState, } void CaptureTexEnviv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, const GLint *params, @@ -330,7 +290,6 @@ void CaptureTexEnviv_params(const State &glState, } void CaptureTexEnvxv_params(const State &glState, - bool isCallValid, TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, const GLfixed *params, @@ -340,7 +299,6 @@ void CaptureTexEnvxv_params(const State &glState, } void CaptureTexParameterxv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLfixed *params, @@ -351,7 +309,6 @@ void CaptureTexParameterxv_params(const State &glState, } void CaptureVertexPointer_pointer(const State &glState, - bool isCallValid, GLint size, VertexAttribType typePacked, GLsizei stride, diff --git a/src/libANGLE/capture/capture_gles_2_0_autogen.cpp b/src/libANGLE/capture/capture_gles_2_0_autogen.cpp index eafd8d4180d..ef7dfe112c9 100644 --- a/src/libANGLE/capture/capture_gles_2_0_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_2_0_autogen.cpp @@ -52,21 +52,18 @@ CallCapture CaptureBindAttribLocation(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureBindAttribLocation_name(glState, isCallValid, programPacked, index, name, - &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureBindAttribLocation_name(glState, programPacked, index, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLBindAttribLocation, std::move(paramBuffer)); } @@ -207,21 +204,18 @@ CallCapture CaptureBufferData(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); paramBuffer.addValueParam("size", ParamType::TGLsizeiptr, size); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureBufferData_data(glState, isCallValid, targetPacked, size, data, usagePacked, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureBufferData_data(glState, targetPacked, size, data, usagePacked, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); paramBuffer.addValueParam("usagePacked", ParamType::TBufferUsage, usagePacked); @@ -241,21 +235,18 @@ CallCapture CaptureBufferSubData(const State &glState, paramBuffer.addValueParam("offset", ParamType::TGLintptr, offset); paramBuffer.addValueParam("size", ParamType::TGLsizeiptr, size); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureBufferSubData_data(glState, isCallValid, targetPacked, offset, size, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureBufferSubData_data(glState, targetPacked, offset, size, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLBufferSubData, std::move(paramBuffer)); } @@ -370,21 +361,19 @@ CallCapture CaptureCompressedTexImage2D(const State &glState, paramBuffer.addValueParam("border", ParamType::TGLint, border); paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexImage2D_data(glState, isCallValid, targetPacked, level, internalformat, - width, height, border, imageSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexImage2D_data(glState, targetPacked, level, internalformat, width, + height, border, imageSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexImage2D, std::move(paramBuffer)); } @@ -412,22 +401,19 @@ CallCapture CaptureCompressedTexSubImage2D(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::InternalFormat, ParamType::TGLenum, format); paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexSubImage2D_data(glState, isCallValid, targetPacked, level, xoffset, - yoffset, width, height, format, imageSize, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexSubImage2D_data(glState, targetPacked, level, xoffset, yoffset, width, + height, format, imageSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexSubImage2D, std::move(paramBuffer)); } @@ -528,21 +514,18 @@ CallCapture CaptureDeleteBuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); if (isCallValid) { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); InitParamValue(ParamType::TBufferIDConstPointer, buffersPacked, &buffersPackedParam.value); - CaptureDeleteBuffers_buffersPacked(glState, isCallValid, n, buffersPacked, - &buffersPackedParam); - paramBuffer.addParam(std::move(buffersPackedParam)); + CaptureDeleteBuffers_buffersPacked(glState, n, buffersPacked, &buffersPackedParam); } else { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); InitParamValue(ParamType::TBufferIDConstPointer, static_cast(nullptr), &buffersPackedParam.value); - paramBuffer.addParam(std::move(buffersPackedParam)); } + paramBuffer.addParam(std::move(buffersPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteBuffers, std::move(paramBuffer)); } @@ -556,24 +539,21 @@ CallCapture CaptureDeleteFramebuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture framebuffersPackedParam("framebuffersPacked", + ParamType::TFramebufferIDConstPointer); if (isCallValid) { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDConstPointer); InitParamValue(ParamType::TFramebufferIDConstPointer, framebuffersPacked, &framebuffersPackedParam.value); - CaptureDeleteFramebuffers_framebuffersPacked(glState, isCallValid, n, framebuffersPacked, + CaptureDeleteFramebuffers_framebuffersPacked(glState, n, framebuffersPacked, &framebuffersPackedParam); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } else { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDConstPointer); InitParamValue(ParamType::TFramebufferIDConstPointer, static_cast(nullptr), &framebuffersPackedParam.value); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } + paramBuffer.addParam(std::move(framebuffersPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteFramebuffers, std::move(paramBuffer)); } @@ -598,25 +578,22 @@ CallCapture CaptureDeleteRenderbuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture renderbuffersPackedParam("renderbuffersPacked", + ParamType::TRenderbufferIDConstPointer); if (isCallValid) { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDConstPointer); InitParamValue(ParamType::TRenderbufferIDConstPointer, renderbuffersPacked, &renderbuffersPackedParam.value); - CaptureDeleteRenderbuffers_renderbuffersPacked(glState, isCallValid, n, renderbuffersPacked, + CaptureDeleteRenderbuffers_renderbuffersPacked(glState, n, renderbuffersPacked, &renderbuffersPackedParam); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } else { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDConstPointer); InitParamValue(ParamType::TRenderbufferIDConstPointer, static_cast(nullptr), &renderbuffersPackedParam.value); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } + paramBuffer.addParam(std::move(renderbuffersPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteRenderbuffers, std::move(paramBuffer)); } @@ -641,22 +618,19 @@ CallCapture CaptureDeleteTextures(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); if (isCallValid) { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, texturesPacked, &texturesPackedParam.value); - CaptureDeleteTextures_texturesPacked(glState, isCallValid, n, texturesPacked, - &texturesPackedParam); - paramBuffer.addParam(std::move(texturesPackedParam)); + CaptureDeleteTextures_texturesPacked(glState, n, texturesPacked, &texturesPackedParam); } else { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, static_cast(nullptr), &texturesPackedParam.value); - paramBuffer.addParam(std::move(texturesPackedParam)); } + paramBuffer.addParam(std::move(texturesPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteTextures, std::move(paramBuffer)); } @@ -748,21 +722,18 @@ CallCapture CaptureDrawElements(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); return CallCapture(angle::EntryPoint::GLDrawElements, std::move(paramBuffer)); } @@ -856,21 +827,18 @@ CallCapture CaptureGenBuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDPointer); if (isCallValid) { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDPointer); InitParamValue(ParamType::TBufferIDPointer, buffersPacked, &buffersPackedParam.value); - CaptureGenBuffers_buffersPacked(glState, isCallValid, n, buffersPacked, - &buffersPackedParam); - paramBuffer.addParam(std::move(buffersPackedParam)); + CaptureGenBuffers_buffersPacked(glState, n, buffersPacked, &buffersPackedParam); } else { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDPointer); InitParamValue(ParamType::TBufferIDPointer, static_cast(nullptr), &buffersPackedParam.value); - paramBuffer.addParam(std::move(buffersPackedParam)); } + paramBuffer.addParam(std::move(buffersPackedParam)); return CallCapture(angle::EntryPoint::GLGenBuffers, std::move(paramBuffer)); } @@ -884,24 +852,20 @@ CallCapture CaptureGenFramebuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture framebuffersPackedParam("framebuffersPacked", ParamType::TFramebufferIDPointer); if (isCallValid) { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDPointer); InitParamValue(ParamType::TFramebufferIDPointer, framebuffersPacked, &framebuffersPackedParam.value); - CaptureGenFramebuffers_framebuffersPacked(glState, isCallValid, n, framebuffersPacked, + CaptureGenFramebuffers_framebuffersPacked(glState, n, framebuffersPacked, &framebuffersPackedParam); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } else { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDPointer); InitParamValue(ParamType::TFramebufferIDPointer, static_cast(nullptr), &framebuffersPackedParam.value); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } + paramBuffer.addParam(std::move(framebuffersPackedParam)); return CallCapture(angle::EntryPoint::GLGenFramebuffers, std::move(paramBuffer)); } @@ -915,24 +879,20 @@ CallCapture CaptureGenRenderbuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture renderbuffersPackedParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer); if (isCallValid) { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDPointer); InitParamValue(ParamType::TRenderbufferIDPointer, renderbuffersPacked, &renderbuffersPackedParam.value); - CaptureGenRenderbuffers_renderbuffersPacked(glState, isCallValid, n, renderbuffersPacked, + CaptureGenRenderbuffers_renderbuffersPacked(glState, n, renderbuffersPacked, &renderbuffersPackedParam); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } else { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDPointer); InitParamValue(ParamType::TRenderbufferIDPointer, static_cast(nullptr), &renderbuffersPackedParam.value); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } + paramBuffer.addParam(std::move(renderbuffersPackedParam)); return CallCapture(angle::EntryPoint::GLGenRenderbuffers, std::move(paramBuffer)); } @@ -946,21 +906,18 @@ CallCapture CaptureGenTextures(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDPointer); if (isCallValid) { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDPointer); InitParamValue(ParamType::TTextureIDPointer, texturesPacked, &texturesPackedParam.value); - CaptureGenTextures_texturesPacked(glState, isCallValid, n, texturesPacked, - &texturesPackedParam); - paramBuffer.addParam(std::move(texturesPackedParam)); + CaptureGenTextures_texturesPacked(glState, n, texturesPacked, &texturesPackedParam); } else { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDPointer); InitParamValue(ParamType::TTextureIDPointer, static_cast(nullptr), &texturesPackedParam.value); - paramBuffer.addParam(std::move(texturesPackedParam)); } + paramBuffer.addParam(std::move(texturesPackedParam)); return CallCapture(angle::EntryPoint::GLGenTextures, std::move(paramBuffer)); } @@ -990,66 +947,58 @@ CallCapture CaptureGetActiveAttrib(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetActiveAttrib_length(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetActiveAttrib_length(glState, programPacked, index, bufSize, length, size, type, + name, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture sizeParam("size", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture sizeParam("size", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, size, &sizeParam.value); - CaptureGetActiveAttrib_size(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &sizeParam); - paramBuffer.addParam(std::move(sizeParam)); + CaptureGetActiveAttrib_size(glState, programPacked, index, bufSize, length, size, type, + name, &sizeParam); } else { - ParamCapture sizeParam("size", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &sizeParam.value); - paramBuffer.addParam(std::move(sizeParam)); } + paramBuffer.addParam(std::move(sizeParam)); + ParamCapture typeParam("type", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture typeParam("type", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, type, &typeParam.value); - CaptureGetActiveAttrib_type(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &typeParam); - paramBuffer.addParam(std::move(typeParam)); + CaptureGetActiveAttrib_type(glState, programPacked, index, bufSize, length, size, type, + name, &typeParam); } else { - ParamCapture typeParam("type", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &typeParam.value); - paramBuffer.addParam(std::move(typeParam)); } + paramBuffer.addParam(std::move(typeParam)); + ParamCapture nameParam("name", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, name, &nameParam.value); - CaptureGetActiveAttrib_name(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetActiveAttrib_name(glState, programPacked, index, bufSize, length, size, type, + name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLGetActiveAttrib, std::move(paramBuffer)); } @@ -1070,66 +1019,58 @@ CallCapture CaptureGetActiveUniform(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetActiveUniform_length(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetActiveUniform_length(glState, programPacked, index, bufSize, length, size, type, + name, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture sizeParam("size", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture sizeParam("size", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, size, &sizeParam.value); - CaptureGetActiveUniform_size(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &sizeParam); - paramBuffer.addParam(std::move(sizeParam)); + CaptureGetActiveUniform_size(glState, programPacked, index, bufSize, length, size, type, + name, &sizeParam); } else { - ParamCapture sizeParam("size", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &sizeParam.value); - paramBuffer.addParam(std::move(sizeParam)); } + paramBuffer.addParam(std::move(sizeParam)); + ParamCapture typeParam("type", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture typeParam("type", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, type, &typeParam.value); - CaptureGetActiveUniform_type(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &typeParam); - paramBuffer.addParam(std::move(typeParam)); + CaptureGetActiveUniform_type(glState, programPacked, index, bufSize, length, size, type, + name, &typeParam); } else { - ParamCapture typeParam("type", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &typeParam.value); - paramBuffer.addParam(std::move(typeParam)); } + paramBuffer.addParam(std::move(typeParam)); + ParamCapture nameParam("name", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, name, &nameParam.value); - CaptureGetActiveUniform_name(glState, isCallValid, programPacked, index, bufSize, length, - size, type, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetActiveUniform_name(glState, programPacked, index, bufSize, length, size, type, + name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLGetActiveUniform, std::move(paramBuffer)); } @@ -1146,38 +1087,34 @@ CallCapture CaptureGetAttachedShaders(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("maxCount", ParamType::TGLsizei, maxCount); + ParamCapture countParam("count", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture countParam("count", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, count, &countParam.value); - CaptureGetAttachedShaders_count(glState, isCallValid, programPacked, maxCount, count, - shadersPacked, &countParam); - paramBuffer.addParam(std::move(countParam)); + CaptureGetAttachedShaders_count(glState, programPacked, maxCount, count, shadersPacked, + &countParam); } else { - ParamCapture countParam("count", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &countParam.value); - paramBuffer.addParam(std::move(countParam)); } + paramBuffer.addParam(std::move(countParam)); + ParamCapture shadersPackedParam("shadersPacked", ParamType::TShaderProgramIDPointer); if (isCallValid) { - ParamCapture shadersPackedParam("shadersPacked", ParamType::TShaderProgramIDPointer); InitParamValue(ParamType::TShaderProgramIDPointer, shadersPacked, &shadersPackedParam.value); - CaptureGetAttachedShaders_shadersPacked(glState, isCallValid, programPacked, maxCount, - count, shadersPacked, &shadersPackedParam); - paramBuffer.addParam(std::move(shadersPackedParam)); + CaptureGetAttachedShaders_shadersPacked(glState, programPacked, maxCount, count, + shadersPacked, &shadersPackedParam); } else { - ParamCapture shadersPackedParam("shadersPacked", ParamType::TShaderProgramIDPointer); InitParamValue(ParamType::TShaderProgramIDPointer, static_cast(nullptr), &shadersPackedParam.value); - paramBuffer.addParam(std::move(shadersPackedParam)); } + paramBuffer.addParam(std::move(shadersPackedParam)); return CallCapture(angle::EntryPoint::GLGetAttachedShaders, std::move(paramBuffer)); } @@ -1192,20 +1129,18 @@ CallCapture CaptureGetAttribLocation(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetAttribLocation_name(glState, isCallValid, programPacked, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetAttribLocation_name(glState, programPacked, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLint); InitParamValue(ParamType::TGLint, returnValue, &returnValueCapture.value); @@ -1223,20 +1158,18 @@ CallCapture CaptureGetBooleanv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TGLbooleanPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, data, &dataParam.value); - CaptureGetBooleanv_data(glState, isCallValid, pname, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetBooleanv_data(glState, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetBooleanv, std::move(paramBuffer)); } @@ -1252,20 +1185,17 @@ CallCapture CaptureGetBufferParameteriv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetBufferParameteriv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferParameteriv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferParameteriv, std::move(paramBuffer)); } @@ -1287,20 +1217,18 @@ CallCapture CaptureGetFloatv(const State &glState, bool isCallValid, GLenum pnam paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, data, &dataParam.value); - CaptureGetFloatv_data(glState, isCallValid, pname, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetFloatv_data(glState, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetFloatv, std::move(paramBuffer)); } @@ -1320,20 +1248,18 @@ CallCapture CaptureGetFramebufferAttachmentParameteriv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::FramebufferAttachmentParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferAttachmentParameteriv_params(glState, isCallValid, target, attachment, - pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferAttachmentParameteriv_params(glState, target, attachment, pname, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferAttachmentParameteriv, std::move(paramBuffer)); @@ -1345,19 +1271,17 @@ CallCapture CaptureGetIntegerv(const State &glState, bool isCallValid, GLenum pn paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, data, &dataParam.value); - CaptureGetIntegerv_data(glState, isCallValid, pname, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetIntegerv_data(glState, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetIntegerv, std::move(paramBuffer)); } @@ -1374,37 +1298,33 @@ CallCapture CaptureGetProgramInfoLog(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramInfoLog_length(glState, isCallValid, programPacked, bufSize, length, - infoLog, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramInfoLog_length(glState, programPacked, bufSize, length, infoLog, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, infoLog, &infoLogParam.value); - CaptureGetProgramInfoLog_infoLog(glState, isCallValid, programPacked, bufSize, length, - infoLog, &infoLogParam); - paramBuffer.addParam(std::move(infoLogParam)); + CaptureGetProgramInfoLog_infoLog(glState, programPacked, bufSize, length, infoLog, + &infoLogParam); } else { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &infoLogParam.value); - paramBuffer.addParam(std::move(infoLogParam)); } + paramBuffer.addParam(std::move(infoLogParam)); return CallCapture(angle::EntryPoint::GLGetProgramInfoLog, std::move(paramBuffer)); } @@ -1420,20 +1340,17 @@ CallCapture CaptureGetProgramiv(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addEnumParam("pname", GLESEnum::ProgramPropertyARB, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramiv_params(glState, isCallValid, programPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramiv_params(glState, programPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramiv, std::move(paramBuffer)); } @@ -1450,20 +1367,17 @@ CallCapture CaptureGetRenderbufferParameteriv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::RenderbufferParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetRenderbufferParameteriv_params(glState, isCallValid, target, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetRenderbufferParameteriv_params(glState, target, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetRenderbufferParameteriv, std::move(paramBuffer)); } @@ -1480,37 +1394,33 @@ CallCapture CaptureGetShaderInfoLog(const State &glState, paramBuffer.addValueParam("shaderPacked", ParamType::TShaderProgramID, shaderPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetShaderInfoLog_length(glState, isCallValid, shaderPacked, bufSize, length, infoLog, + CaptureGetShaderInfoLog_length(glState, shaderPacked, bufSize, length, infoLog, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, infoLog, &infoLogParam.value); - CaptureGetShaderInfoLog_infoLog(glState, isCallValid, shaderPacked, bufSize, length, - infoLog, &infoLogParam); - paramBuffer.addParam(std::move(infoLogParam)); + CaptureGetShaderInfoLog_infoLog(glState, shaderPacked, bufSize, length, infoLog, + &infoLogParam); } else { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &infoLogParam.value); - paramBuffer.addParam(std::move(infoLogParam)); } + paramBuffer.addParam(std::move(infoLogParam)); return CallCapture(angle::EntryPoint::GLGetShaderInfoLog, std::move(paramBuffer)); } @@ -1528,36 +1438,32 @@ CallCapture CaptureGetShaderPrecisionFormat(const State &glState, paramBuffer.addEnumParam("precisiontype", GLESEnum::PrecisionType, ParamType::TGLenum, precisiontype); + ParamCapture rangeParam("range", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture rangeParam("range", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, range, &rangeParam.value); - CaptureGetShaderPrecisionFormat_range(glState, isCallValid, shadertype, precisiontype, - range, precision, &rangeParam); - paramBuffer.addParam(std::move(rangeParam)); + CaptureGetShaderPrecisionFormat_range(glState, shadertype, precisiontype, range, precision, + &rangeParam); } else { - ParamCapture rangeParam("range", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &rangeParam.value); - paramBuffer.addParam(std::move(rangeParam)); } + paramBuffer.addParam(std::move(rangeParam)); + ParamCapture precisionParam("precision", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture precisionParam("precision", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, precision, &precisionParam.value); - CaptureGetShaderPrecisionFormat_precision(glState, isCallValid, shadertype, precisiontype, - range, precision, &precisionParam); - paramBuffer.addParam(std::move(precisionParam)); + CaptureGetShaderPrecisionFormat_precision(glState, shadertype, precisiontype, range, + precision, &precisionParam); } else { - ParamCapture precisionParam("precision", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &precisionParam.value); - paramBuffer.addParam(std::move(precisionParam)); } + paramBuffer.addParam(std::move(precisionParam)); return CallCapture(angle::EntryPoint::GLGetShaderPrecisionFormat, std::move(paramBuffer)); } @@ -1574,37 +1480,31 @@ CallCapture CaptureGetShaderSource(const State &glState, paramBuffer.addValueParam("shaderPacked", ParamType::TShaderProgramID, shaderPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetShaderSource_length(glState, isCallValid, shaderPacked, bufSize, length, source, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetShaderSource_length(glState, shaderPacked, bufSize, length, source, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture sourceParam("source", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture sourceParam("source", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, source, &sourceParam.value); - CaptureGetShaderSource_source(glState, isCallValid, shaderPacked, bufSize, length, source, - &sourceParam); - paramBuffer.addParam(std::move(sourceParam)); + CaptureGetShaderSource_source(glState, shaderPacked, bufSize, length, source, &sourceParam); } else { - ParamCapture sourceParam("source", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &sourceParam.value); - paramBuffer.addParam(std::move(sourceParam)); } + paramBuffer.addParam(std::move(sourceParam)); return CallCapture(angle::EntryPoint::GLGetShaderSource, std::move(paramBuffer)); } @@ -1620,19 +1520,17 @@ CallCapture CaptureGetShaderiv(const State &glState, paramBuffer.addValueParam("shaderPacked", ParamType::TShaderProgramID, shaderPacked); paramBuffer.addEnumParam("pname", GLESEnum::ShaderParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetShaderiv_params(glState, isCallValid, shaderPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetShaderiv_params(glState, shaderPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetShaderiv, std::move(paramBuffer)); } @@ -1664,21 +1562,18 @@ CallCapture CaptureGetTexParameterfv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexParameterfv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterfv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterfv, std::move(paramBuffer)); } @@ -1694,20 +1589,17 @@ CallCapture CaptureGetTexParameteriv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexParameteriv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameteriv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameteriv, std::move(paramBuffer)); } @@ -1722,20 +1614,18 @@ CallCapture CaptureGetUniformLocation(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetUniformLocation_name(glState, isCallValid, programPacked, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetUniformLocation_name(glState, programPacked, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLint); InitParamValue(ParamType::TGLint, returnValue, &returnValueCapture.value); @@ -1755,21 +1645,18 @@ CallCapture CaptureGetUniformfv(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetUniformfv_params(glState, isCallValid, programPacked, locationPacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetUniformfv_params(glState, programPacked, locationPacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetUniformfv, std::move(paramBuffer)); } @@ -1785,20 +1672,17 @@ CallCapture CaptureGetUniformiv(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetUniformiv_params(glState, isCallValid, programPacked, locationPacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetUniformiv_params(glState, programPacked, locationPacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetUniformiv, std::move(paramBuffer)); } @@ -1814,21 +1698,18 @@ CallCapture CaptureGetVertexAttribPointerv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture pointerParam("pointer", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, pointer, &pointerParam.value); - CaptureGetVertexAttribPointerv_pointer(glState, isCallValid, index, pname, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureGetVertexAttribPointerv_pointer(glState, index, pname, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribPointerv, std::move(paramBuffer)); } @@ -1844,20 +1725,18 @@ CallCapture CaptureGetVertexAttribfv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetVertexAttribfv_params(glState, isCallValid, index, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribfv_params(glState, index, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribfv, std::move(paramBuffer)); } @@ -1873,19 +1752,17 @@ CallCapture CaptureGetVertexAttribiv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetVertexAttribiv_params(glState, isCallValid, index, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribiv_params(glState, index, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribiv, std::move(paramBuffer)); } @@ -2074,20 +1951,17 @@ CallCapture CaptureReadPixels(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, pixels, &pixelsParam.value); - CaptureReadPixels_pixels(glState, isCallValid, x, y, width, height, format, type, pixels, - &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureReadPixels_pixels(glState, x, y, width, height, format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLReadPixels, std::move(paramBuffer)); } @@ -2159,41 +2033,37 @@ CallCapture CaptureShaderBinary(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture shadersPackedParam("shadersPacked", ParamType::TShaderProgramIDConstPointer); if (isCallValid) { - ParamCapture shadersPackedParam("shadersPacked", ParamType::TShaderProgramIDConstPointer); InitParamValue(ParamType::TShaderProgramIDConstPointer, shadersPacked, &shadersPackedParam.value); - CaptureShaderBinary_shadersPacked(glState, isCallValid, count, shadersPacked, binaryFormat, - binary, length, &shadersPackedParam); - paramBuffer.addParam(std::move(shadersPackedParam)); + CaptureShaderBinary_shadersPacked(glState, count, shadersPacked, binaryFormat, binary, + length, &shadersPackedParam); } else { - ParamCapture shadersPackedParam("shadersPacked", ParamType::TShaderProgramIDConstPointer); InitParamValue(ParamType::TShaderProgramIDConstPointer, static_cast(nullptr), &shadersPackedParam.value); - paramBuffer.addParam(std::move(shadersPackedParam)); } + paramBuffer.addParam(std::move(shadersPackedParam)); paramBuffer.addEnumParam("binaryFormat", GLESEnum::ShaderBinaryFormat, ParamType::TGLenum, binaryFormat); + ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, binary, &binaryParam.value); - CaptureShaderBinary_binary(glState, isCallValid, count, shadersPacked, binaryFormat, binary, - length, &binaryParam); - paramBuffer.addParam(std::move(binaryParam)); + CaptureShaderBinary_binary(glState, count, shadersPacked, binaryFormat, binary, length, + &binaryParam); } else { - ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &binaryParam.value); - paramBuffer.addParam(std::move(binaryParam)); } + paramBuffer.addParam(std::move(binaryParam)); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); @@ -2212,37 +2082,31 @@ CallCapture CaptureShaderSource(const State &glState, paramBuffer.addValueParam("shaderPacked", ParamType::TShaderProgramID, shaderPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture stringParam("string", ParamType::TGLcharConstPointerPointer); if (isCallValid) { - ParamCapture stringParam("string", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, string, &stringParam.value); - CaptureShaderSource_string(glState, isCallValid, shaderPacked, count, string, length, - &stringParam); - paramBuffer.addParam(std::move(stringParam)); + CaptureShaderSource_string(glState, shaderPacked, count, string, length, &stringParam); } else { - ParamCapture stringParam("string", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, static_cast(nullptr), &stringParam.value); - paramBuffer.addParam(std::move(stringParam)); } + paramBuffer.addParam(std::move(stringParam)); + ParamCapture lengthParam("length", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, length, &lengthParam.value); - CaptureShaderSource_length(glState, isCallValid, shaderPacked, count, string, length, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureShaderSource_length(glState, shaderPacked, count, string, length, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); return CallCapture(angle::EntryPoint::GLShaderSource, std::move(paramBuffer)); } @@ -2356,21 +2220,19 @@ CallCapture CaptureTexImage2D(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexImage2D_pixels(glState, isCallValid, targetPacked, level, internalformat, width, - height, border, format, type, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexImage2D_pixels(glState, targetPacked, level, internalformat, width, height, + border, format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexImage2D, std::move(paramBuffer)); } @@ -2401,21 +2263,18 @@ CallCapture CaptureTexParameterfv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureTexParameterfv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterfv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterfv, std::move(paramBuffer)); } @@ -2446,21 +2305,18 @@ CallCapture CaptureTexParameteriv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexParameteriv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameteriv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameteriv, std::move(paramBuffer)); } @@ -2488,21 +2344,19 @@ CallCapture CaptureTexSubImage2D(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexSubImage2D_pixels(glState, isCallValid, targetPacked, level, xoffset, yoffset, - width, height, format, type, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexSubImage2D_pixels(glState, targetPacked, level, xoffset, yoffset, width, height, + format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexSubImage2D, std::move(paramBuffer)); } @@ -2531,20 +2385,18 @@ CallCapture CaptureUniform1fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniform1fv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform1fv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform1fv, std::move(paramBuffer)); } @@ -2573,20 +2425,18 @@ CallCapture CaptureUniform1iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureUniform1iv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform1iv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform1iv, std::move(paramBuffer)); } @@ -2617,20 +2467,18 @@ CallCapture CaptureUniform2fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniform2fv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform2fv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform2fv, std::move(paramBuffer)); } @@ -2661,20 +2509,18 @@ CallCapture CaptureUniform2iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureUniform2iv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform2iv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform2iv, std::move(paramBuffer)); } @@ -2707,20 +2553,18 @@ CallCapture CaptureUniform3fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniform3fv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform3fv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform3fv, std::move(paramBuffer)); } @@ -2753,20 +2597,18 @@ CallCapture CaptureUniform3iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureUniform3iv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform3iv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform3iv, std::move(paramBuffer)); } @@ -2801,20 +2643,18 @@ CallCapture CaptureUniform4fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniform4fv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform4fv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform4fv, std::move(paramBuffer)); } @@ -2849,20 +2689,18 @@ CallCapture CaptureUniform4iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureUniform4iv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform4iv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform4iv, std::move(paramBuffer)); } @@ -2880,21 +2718,19 @@ CallCapture CaptureUniformMatrix2fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix2fv_value(glState, isCallValid, locationPacked, count, transpose, value, + CaptureUniformMatrix2fv_value(glState, locationPacked, count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix2fv, std::move(paramBuffer)); } @@ -2912,21 +2748,19 @@ CallCapture CaptureUniformMatrix3fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix3fv_value(glState, isCallValid, locationPacked, count, transpose, value, + CaptureUniformMatrix3fv_value(glState, locationPacked, count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix3fv, std::move(paramBuffer)); } @@ -2944,21 +2778,19 @@ CallCapture CaptureUniformMatrix4fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix4fv_value(glState, isCallValid, locationPacked, count, transpose, value, + CaptureUniformMatrix4fv_value(glState, locationPacked, count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix4fv, std::move(paramBuffer)); } @@ -3002,20 +2834,18 @@ CallCapture CaptureVertexAttrib1fv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture vParam("v", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, v, &vParam.value); - CaptureVertexAttrib1fv_v(glState, isCallValid, index, v, &vParam); - paramBuffer.addParam(std::move(vParam)); + CaptureVertexAttrib1fv_v(glState, index, v, &vParam); } else { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &vParam.value); - paramBuffer.addParam(std::move(vParam)); } + paramBuffer.addParam(std::move(vParam)); return CallCapture(angle::EntryPoint::GLVertexAttrib1fv, std::move(paramBuffer)); } @@ -3044,20 +2874,18 @@ CallCapture CaptureVertexAttrib2fv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture vParam("v", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, v, &vParam.value); - CaptureVertexAttrib2fv_v(glState, isCallValid, index, v, &vParam); - paramBuffer.addParam(std::move(vParam)); + CaptureVertexAttrib2fv_v(glState, index, v, &vParam); } else { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &vParam.value); - paramBuffer.addParam(std::move(vParam)); } + paramBuffer.addParam(std::move(vParam)); return CallCapture(angle::EntryPoint::GLVertexAttrib2fv, std::move(paramBuffer)); } @@ -3088,20 +2916,18 @@ CallCapture CaptureVertexAttrib3fv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture vParam("v", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, v, &vParam.value); - CaptureVertexAttrib3fv_v(glState, isCallValid, index, v, &vParam); - paramBuffer.addParam(std::move(vParam)); + CaptureVertexAttrib3fv_v(glState, index, v, &vParam); } else { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &vParam.value); - paramBuffer.addParam(std::move(vParam)); } + paramBuffer.addParam(std::move(vParam)); return CallCapture(angle::EntryPoint::GLVertexAttrib3fv, std::move(paramBuffer)); } @@ -3134,20 +2960,18 @@ CallCapture CaptureVertexAttrib4fv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture vParam("v", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, v, &vParam.value); - CaptureVertexAttrib4fv_v(glState, isCallValid, index, v, &vParam); - paramBuffer.addParam(std::move(vParam)); + CaptureVertexAttrib4fv_v(glState, index, v, &vParam); } else { - ParamCapture vParam("v", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &vParam.value); - paramBuffer.addParam(std::move(vParam)); } + paramBuffer.addParam(std::move(vParam)); return CallCapture(angle::EntryPoint::GLVertexAttrib4fv, std::move(paramBuffer)); } @@ -3169,21 +2993,19 @@ CallCapture CaptureVertexAttribPointer(const State &glState, paramBuffer.addValueParam("normalized", ParamType::TGLboolean, normalized); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureVertexAttribPointer_pointer(glState, isCallValid, index, size, typePacked, - normalized, stride, pointer, &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureVertexAttribPointer_pointer(glState, index, size, typePacked, normalized, stride, + pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLVertexAttribPointer, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_2_0_autogen.h b/src/libANGLE/capture/capture_gles_2_0_autogen.h index 57369bbce1a..3ac55907dad 100644 --- a/src/libANGLE/capture/capture_gles_2_0_autogen.h +++ b/src/libANGLE/capture/capture_gles_2_0_autogen.h @@ -682,27 +682,23 @@ angle::CallCapture CaptureViewport(const State &glState, // Parameter Captures void CaptureBindAttribLocation_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureBufferData_data(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLsizeiptr size, const void *data, BufferUsage usagePacked, angle::ParamCapture *paramCapture); void CaptureBufferSubData_data(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLintptr offset, GLsizeiptr size, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexImage2D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -713,7 +709,6 @@ void CaptureCompressedTexImage2D_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexSubImage2D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -725,54 +720,44 @@ void CaptureCompressedTexSubImage2D_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureDeleteBuffers_buffersPacked(const State &glState, - bool isCallValid, GLsizei n, const BufferID *buffersPacked, angle::ParamCapture *paramCapture); void CaptureDeleteFramebuffers_framebuffersPacked(const State &glState, - bool isCallValid, GLsizei n, const FramebufferID *framebuffersPacked, angle::ParamCapture *paramCapture); void CaptureDeleteRenderbuffers_renderbuffersPacked(const State &glState, - bool isCallValid, GLsizei n, const RenderbufferID *renderbuffersPacked, angle::ParamCapture *paramCapture); void CaptureDeleteTextures_texturesPacked(const State &glState, - bool isCallValid, GLsizei n, const TextureID *texturesPacked, angle::ParamCapture *paramCapture); void CaptureDrawElements_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, const void *indices, angle::ParamCapture *paramCapture); void CaptureGenBuffers_buffersPacked(const State &glState, - bool isCallValid, GLsizei n, BufferID *buffersPacked, angle::ParamCapture *paramCapture); void CaptureGenFramebuffers_framebuffersPacked(const State &glState, - bool isCallValid, GLsizei n, FramebufferID *framebuffersPacked, angle::ParamCapture *paramCapture); void CaptureGenRenderbuffers_renderbuffersPacked(const State &glState, - bool isCallValid, GLsizei n, RenderbufferID *renderbuffersPacked, angle::ParamCapture *paramCapture); void CaptureGenTextures_texturesPacked(const State &glState, - bool isCallValid, GLsizei n, TextureID *texturesPacked, angle::ParamCapture *paramCapture); void CaptureGetActiveAttrib_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -782,7 +767,6 @@ void CaptureGetActiveAttrib_length(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveAttrib_size(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -792,7 +776,6 @@ void CaptureGetActiveAttrib_size(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveAttrib_type(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -802,7 +785,6 @@ void CaptureGetActiveAttrib_type(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveAttrib_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -812,7 +794,6 @@ void CaptureGetActiveAttrib_name(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveUniform_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -822,7 +803,6 @@ void CaptureGetActiveUniform_length(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveUniform_size(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -832,7 +812,6 @@ void CaptureGetActiveUniform_size(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveUniform_type(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -842,7 +821,6 @@ void CaptureGetActiveUniform_type(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetActiveUniform_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -852,175 +830,147 @@ void CaptureGetActiveUniform_name(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetAttachedShaders_count(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei maxCount, GLsizei *count, ShaderProgramID *shadersPacked, angle::ParamCapture *paramCapture); void CaptureGetAttachedShaders_shadersPacked(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei maxCount, GLsizei *count, ShaderProgramID *shadersPacked, angle::ParamCapture *paramCapture); void CaptureGetAttribLocation_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetBooleanv_data(const State &glState, - bool isCallValid, GLenum pname, GLboolean *data, angle::ParamCapture *paramCapture); void CaptureGetBufferParameteriv_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetFloatv_data(const State &glState, - bool isCallValid, GLenum pname, GLfloat *data, angle::ParamCapture *paramCapture); void CaptureGetFramebufferAttachmentParameteriv_params(const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetIntegerv_data(const State &glState, - bool isCallValid, GLenum pname, GLint *data, angle::ParamCapture *paramCapture); void CaptureGetProgramInfoLog_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetProgramInfoLog_infoLog(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetProgramiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetRenderbufferParameteriv_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetShaderInfoLog_length(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetShaderInfoLog_infoLog(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetShaderPrecisionFormat_range(const State &glState, - bool isCallValid, GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision, angle::ParamCapture *paramCapture); void CaptureGetShaderPrecisionFormat_precision(const State &glState, - bool isCallValid, GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision, angle::ParamCapture *paramCapture); void CaptureGetShaderSource_length(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, GLchar *source, angle::ParamCapture *paramCapture); void CaptureGetShaderSource_source(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, GLchar *source, angle::ParamCapture *paramCapture); void CaptureGetShaderiv_params(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterfv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameteriv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetUniformLocation_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetUniformfv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetUniformiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribPointerv_pointer(const State &glState, - bool isCallValid, GLuint index, GLenum pname, void **pointer, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribfv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribiv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureReadPixels_pixels(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -1030,7 +980,6 @@ void CaptureReadPixels_pixels(const State &glState, void *pixels, angle::ParamCapture *paramCapture); void CaptureShaderBinary_shadersPacked(const State &glState, - bool isCallValid, GLsizei count, const ShaderProgramID *shadersPacked, GLenum binaryFormat, @@ -1038,7 +987,6 @@ void CaptureShaderBinary_shadersPacked(const State &glState, GLsizei length, angle::ParamCapture *paramCapture); void CaptureShaderBinary_binary(const State &glState, - bool isCallValid, GLsizei count, const ShaderProgramID *shadersPacked, GLenum binaryFormat, @@ -1046,21 +994,18 @@ void CaptureShaderBinary_binary(const State &glState, GLsizei length, angle::ParamCapture *paramCapture); void CaptureShaderSource_string(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei count, const GLchar *const *string, const GLint *length, angle::ParamCapture *paramCapture); void CaptureShaderSource_length(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei count, const GLchar *const *string, const GLint *length, angle::ParamCapture *paramCapture); void CaptureTexImage2D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -1072,19 +1017,16 @@ void CaptureTexImage2D_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTexParameterfv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureTexParameteriv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexSubImage2D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -1096,96 +1038,80 @@ void CaptureTexSubImage2D_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureUniform1fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniform1iv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureUniform2fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniform2iv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureUniform3fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniform3iv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureUniform4fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniform4iv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix2fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix3fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix4fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureVertexAttrib1fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, angle::ParamCapture *paramCapture); void CaptureVertexAttrib2fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, angle::ParamCapture *paramCapture); void CaptureVertexAttrib3fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, angle::ParamCapture *paramCapture); void CaptureVertexAttrib4fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, angle::ParamCapture *paramCapture); void CaptureVertexAttribPointer_pointer(const State &glState, - bool isCallValid, GLuint index, GLint size, VertexAttribType typePacked, diff --git a/src/libANGLE/capture/capture_gles_2_0_params.cpp b/src/libANGLE/capture/capture_gles_2_0_params.cpp index 701eb3c4e36..4823c08a67c 100644 --- a/src/libANGLE/capture/capture_gles_2_0_params.cpp +++ b/src/libANGLE/capture/capture_gles_2_0_params.cpp @@ -20,7 +20,6 @@ namespace gl // Parameter Captures void CaptureBindAttribLocation_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, const GLchar *name, @@ -30,7 +29,6 @@ void CaptureBindAttribLocation_name(const State &glState, } void CaptureBufferData_data(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLsizeiptr size, const void *data, @@ -44,7 +42,6 @@ void CaptureBufferData_data(const State &glState, } void CaptureBufferSubData_data(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLintptr offset, GLsizeiptr size, @@ -55,7 +52,6 @@ void CaptureBufferSubData_data(const State &glState, } void CaptureCompressedTexImage2D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -80,7 +76,6 @@ void CaptureCompressedTexImage2D_data(const State &glState, } void CaptureCompressedTexSubImage2D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -92,12 +87,11 @@ void CaptureCompressedTexSubImage2D_data(const State &glState, const void *data, ParamCapture *paramCapture) { - CaptureCompressedTexImage2D_data(glState, isCallValid, targetPacked, level, 0, width, height, 0, - imageSize, data, paramCapture); + CaptureCompressedTexImage2D_data(glState, targetPacked, level, 0, width, height, 0, imageSize, + data, paramCapture); } void CaptureDeleteBuffers_buffersPacked(const State &glState, - bool isCallValid, GLsizei n, const BufferID *buffers, ParamCapture *paramCapture) @@ -106,7 +100,6 @@ void CaptureDeleteBuffers_buffersPacked(const State &glState, } void CaptureDeleteFramebuffers_framebuffersPacked(const State &glState, - bool isCallValid, GLsizei n, const FramebufferID *framebuffers, ParamCapture *paramCapture) @@ -115,7 +108,6 @@ void CaptureDeleteFramebuffers_framebuffersPacked(const State &glState, } void CaptureDeleteRenderbuffers_renderbuffersPacked(const State &glState, - bool isCallValid, GLsizei n, const RenderbufferID *renderbuffers, ParamCapture *paramCapture) @@ -124,7 +116,6 @@ void CaptureDeleteRenderbuffers_renderbuffersPacked(const State &glState, } void CaptureDeleteTextures_texturesPacked(const State &glState, - bool isCallValid, GLsizei n, const TextureID *textures, ParamCapture *paramCapture) @@ -133,7 +124,6 @@ void CaptureDeleteTextures_texturesPacked(const State &glState, } void CaptureDrawElements_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -153,7 +143,6 @@ void CaptureDrawElements_indices(const State &glState, } void CaptureGenBuffers_buffersPacked(const State &glState, - bool isCallValid, GLsizei n, BufferID *buffers, ParamCapture *paramCapture) @@ -162,7 +151,6 @@ void CaptureGenBuffers_buffersPacked(const State &glState, } void CaptureGenFramebuffers_framebuffersPacked(const State &glState, - bool isCallValid, GLsizei n, FramebufferID *framebuffers, ParamCapture *paramCapture) @@ -171,7 +159,6 @@ void CaptureGenFramebuffers_framebuffersPacked(const State &glState, } void CaptureGenRenderbuffers_renderbuffersPacked(const State &glState, - bool isCallValid, GLsizei n, RenderbufferID *renderbuffers, ParamCapture *paramCapture) @@ -180,7 +167,6 @@ void CaptureGenRenderbuffers_renderbuffersPacked(const State &glState, } void CaptureGenTextures_texturesPacked(const State &glState, - bool isCallValid, GLsizei n, TextureID *textures, ParamCapture *paramCapture) @@ -189,7 +175,6 @@ void CaptureGenTextures_texturesPacked(const State &glState, } void CaptureGetActiveAttrib_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -203,7 +188,6 @@ void CaptureGetActiveAttrib_length(const State &glState, } void CaptureGetActiveAttrib_size(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -217,7 +201,6 @@ void CaptureGetActiveAttrib_size(const State &glState, } void CaptureGetActiveAttrib_type(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -231,7 +214,6 @@ void CaptureGetActiveAttrib_type(const State &glState, } void CaptureGetActiveAttrib_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -245,7 +227,6 @@ void CaptureGetActiveAttrib_name(const State &glState, } void CaptureGetActiveUniform_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -259,7 +240,6 @@ void CaptureGetActiveUniform_length(const State &glState, } void CaptureGetActiveUniform_size(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -273,7 +253,6 @@ void CaptureGetActiveUniform_size(const State &glState, } void CaptureGetActiveUniform_type(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -287,7 +266,6 @@ void CaptureGetActiveUniform_type(const State &glState, } void CaptureGetActiveUniform_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -301,7 +279,6 @@ void CaptureGetActiveUniform_name(const State &glState, } void CaptureGetAttachedShaders_count(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei maxCount, GLsizei *count, @@ -312,7 +289,6 @@ void CaptureGetAttachedShaders_count(const State &glState, } void CaptureGetAttachedShaders_shadersPacked(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei maxCount, GLsizei *count, @@ -323,7 +299,6 @@ void CaptureGetAttachedShaders_shadersPacked(const State &glState, } void CaptureGetAttribLocation_name(const State &glState, - bool isCallValid, ShaderProgramID program, const GLchar *name, ParamCapture *paramCapture) @@ -332,7 +307,6 @@ void CaptureGetAttribLocation_name(const State &glState, } void CaptureGetBooleanv_data(const State &glState, - bool isCallValid, GLenum pname, GLboolean *data, ParamCapture *paramCapture) @@ -341,7 +315,6 @@ void CaptureGetBooleanv_data(const State &glState, } void CaptureGetBufferParameteriv_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLint *params, @@ -351,7 +324,6 @@ void CaptureGetBufferParameteriv_params(const State &glState, } void CaptureGetFloatv_data(const State &glState, - bool isCallValid, GLenum pname, GLfloat *data, ParamCapture *paramCapture) @@ -360,7 +332,6 @@ void CaptureGetFloatv_data(const State &glState, } void CaptureGetFramebufferAttachmentParameteriv_params(const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, @@ -372,7 +343,6 @@ void CaptureGetFramebufferAttachmentParameteriv_params(const State &glState, } void CaptureGetIntegerv_data(const State &glState, - bool isCallValid, GLenum pname, GLint *data, ParamCapture *paramCapture) @@ -381,7 +351,6 @@ void CaptureGetIntegerv_data(const State &glState, } void CaptureGetProgramInfoLog_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei bufSize, GLsizei *length, @@ -392,7 +361,6 @@ void CaptureGetProgramInfoLog_length(const State &glState, } void CaptureGetProgramInfoLog_infoLog(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei bufSize, GLsizei *length, @@ -405,7 +373,6 @@ void CaptureGetProgramInfoLog_infoLog(const State &glState, } void CaptureGetProgramiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum pname, GLint *params, @@ -418,7 +385,6 @@ void CaptureGetProgramiv_params(const State &glState, } void CaptureGetRenderbufferParameteriv_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLint *params, @@ -428,7 +394,6 @@ void CaptureGetRenderbufferParameteriv_params(const State &glState, } void CaptureGetShaderInfoLog_length(const State &glState, - bool isCallValid, ShaderProgramID shader, GLsizei bufSize, GLsizei *length, @@ -439,7 +404,6 @@ void CaptureGetShaderInfoLog_length(const State &glState, } void CaptureGetShaderInfoLog_infoLog(const State &glState, - bool isCallValid, ShaderProgramID shader, GLsizei bufSize, GLsizei *length, @@ -452,7 +416,6 @@ void CaptureGetShaderInfoLog_infoLog(const State &glState, } void CaptureGetShaderPrecisionFormat_range(const State &glState, - bool isCallValid, GLenum shadertype, GLenum precisiontype, GLint *range, @@ -464,7 +427,6 @@ void CaptureGetShaderPrecisionFormat_range(const State &glState, } void CaptureGetShaderPrecisionFormat_precision(const State &glState, - bool isCallValid, GLenum shadertype, GLenum precisiontype, GLint *range, @@ -475,7 +437,6 @@ void CaptureGetShaderPrecisionFormat_precision(const State &glState, } void CaptureGetShaderSource_length(const State &glState, - bool isCallValid, ShaderProgramID shader, GLsizei bufSize, GLsizei *length, @@ -486,7 +447,6 @@ void CaptureGetShaderSource_length(const State &glState, } void CaptureGetShaderSource_source(const State &glState, - bool isCallValid, ShaderProgramID shader, GLsizei bufSize, GLsizei *length, @@ -497,7 +457,6 @@ void CaptureGetShaderSource_source(const State &glState, } void CaptureGetShaderiv_params(const State &glState, - bool isCallValid, ShaderProgramID shader, GLenum pname, GLint *params, @@ -510,7 +469,6 @@ void CaptureGetShaderiv_params(const State &glState, } void CaptureGetTexParameterfv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLfloat *params, @@ -522,7 +480,6 @@ void CaptureGetTexParameterfv_params(const State &glState, } void CaptureGetTexParameteriv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLint *params, @@ -534,7 +491,6 @@ void CaptureGetTexParameteriv_params(const State &glState, } void CaptureGetUniformLocation_name(const State &glState, - bool isCallValid, ShaderProgramID program, const GLchar *name, ParamCapture *paramCapture) @@ -543,7 +499,6 @@ void CaptureGetUniformLocation_name(const State &glState, } void CaptureGetUniformfv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLfloat *params, @@ -554,7 +509,6 @@ void CaptureGetUniformfv_params(const State &glState, } void CaptureGetUniformiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLint *params, @@ -565,7 +519,6 @@ void CaptureGetUniformiv_params(const State &glState, } void CaptureGetVertexAttribPointerv_pointer(const State &glState, - bool isCallValid, GLuint index, GLenum pname, void **pointer, @@ -575,7 +528,6 @@ void CaptureGetVertexAttribPointerv_pointer(const State &glState, } void CaptureGetVertexAttribfv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLfloat *params, @@ -586,7 +538,6 @@ void CaptureGetVertexAttribfv_params(const State &glState, } void CaptureGetVertexAttribiv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLint *params, @@ -597,7 +548,6 @@ void CaptureGetVertexAttribiv_params(const State &glState, } void CaptureReadPixels_pixels(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -619,7 +569,6 @@ void CaptureReadPixels_pixels(const State &glState, } void CaptureShaderBinary_shadersPacked(const State &glState, - bool isCallValid, GLsizei count, const ShaderProgramID *shaders, GLenum binaryformat, @@ -631,7 +580,6 @@ void CaptureShaderBinary_shadersPacked(const State &glState, } void CaptureShaderBinary_binary(const State &glState, - bool isCallValid, GLsizei count, const ShaderProgramID *shaders, GLenum binaryformat, @@ -643,7 +591,6 @@ void CaptureShaderBinary_binary(const State &glState, } void CaptureShaderSource_string(const State &glState, - bool isCallValid, ShaderProgramID shader, GLsizei count, const GLchar *const *string, @@ -654,7 +601,6 @@ void CaptureShaderSource_string(const State &glState, } void CaptureShaderSource_length(const State &glState, - bool isCallValid, ShaderProgramID shader, GLsizei count, const GLchar *const *string, @@ -670,7 +616,6 @@ void CaptureShaderSource_length(const State &glState, } void CaptureTexImage2D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -738,7 +683,6 @@ void CaptureTexImage2D_pixels(const State &glState, } void CaptureTexParameterfv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLfloat *params, @@ -748,7 +692,6 @@ void CaptureTexParameterfv_params(const State &glState, } void CaptureTexParameteriv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLint *params, @@ -758,7 +701,6 @@ void CaptureTexParameteriv_params(const State &glState, } void CaptureTexSubImage2D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -770,12 +712,11 @@ void CaptureTexSubImage2D_pixels(const State &glState, const void *pixels, ParamCapture *paramCapture) { - CaptureTexImage2D_pixels(glState, isCallValid, targetPacked, level, 0, width, height, 0, format, - type, pixels, paramCapture); + CaptureTexImage2D_pixels(glState, targetPacked, level, 0, width, height, 0, format, type, + pixels, paramCapture); } void CaptureUniform1fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLfloat *value, @@ -785,7 +726,6 @@ void CaptureUniform1fv_value(const State &glState, } void CaptureUniform1iv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLint *value, @@ -795,7 +735,6 @@ void CaptureUniform1iv_value(const State &glState, } void CaptureUniform2fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLfloat *value, @@ -805,7 +744,6 @@ void CaptureUniform2fv_value(const State &glState, } void CaptureUniform2iv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLint *value, @@ -815,7 +753,6 @@ void CaptureUniform2iv_value(const State &glState, } void CaptureUniform3fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLfloat *value, @@ -825,7 +762,6 @@ void CaptureUniform3fv_value(const State &glState, } void CaptureUniform3iv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLint *value, @@ -835,7 +771,6 @@ void CaptureUniform3iv_value(const State &glState, } void CaptureUniform4fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLfloat *value, @@ -845,7 +780,6 @@ void CaptureUniform4fv_value(const State &glState, } void CaptureUniform4iv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLint *value, @@ -855,7 +789,6 @@ void CaptureUniform4iv_value(const State &glState, } void CaptureUniformMatrix2fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -866,7 +799,6 @@ void CaptureUniformMatrix2fv_value(const State &glState, } void CaptureUniformMatrix3fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -877,7 +809,6 @@ void CaptureUniformMatrix3fv_value(const State &glState, } void CaptureUniformMatrix4fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -888,7 +819,6 @@ void CaptureUniformMatrix4fv_value(const State &glState, } void CaptureVertexAttrib1fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, ParamCapture *paramCapture) @@ -897,7 +827,6 @@ void CaptureVertexAttrib1fv_v(const State &glState, } void CaptureVertexAttrib2fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, ParamCapture *paramCapture) @@ -906,7 +835,6 @@ void CaptureVertexAttrib2fv_v(const State &glState, } void CaptureVertexAttrib3fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, ParamCapture *paramCapture) @@ -915,7 +843,6 @@ void CaptureVertexAttrib3fv_v(const State &glState, } void CaptureVertexAttrib4fv_v(const State &glState, - bool isCallValid, GLuint index, const GLfloat *v, ParamCapture *paramCapture) @@ -924,7 +851,6 @@ void CaptureVertexAttrib4fv_v(const State &glState, } void CaptureVertexAttribPointer_pointer(const State &glState, - bool isCallValid, GLuint index, GLint size, VertexAttribType typePacked, diff --git a/src/libANGLE/capture/capture_gles_3_0_autogen.cpp b/src/libANGLE/capture/capture_gles_3_0_autogen.cpp index 81e1b2c1171..59ba9cc53e8 100644 --- a/src/libANGLE/capture/capture_gles_3_0_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_3_0_autogen.cpp @@ -173,20 +173,18 @@ CallCapture CaptureClearBufferfv(const State &glState, paramBuffer.addEnumParam("buffer", GLESEnum::Buffer, ParamType::TGLenum, buffer); paramBuffer.addValueParam("drawbuffer", ParamType::TGLint, drawbuffer); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureClearBufferfv_value(glState, isCallValid, buffer, drawbuffer, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureClearBufferfv_value(glState, buffer, drawbuffer, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLClearBufferfv, std::move(paramBuffer)); } @@ -202,20 +200,18 @@ CallCapture CaptureClearBufferiv(const State &glState, paramBuffer.addEnumParam("buffer", GLESEnum::Buffer, ParamType::TGLenum, buffer); paramBuffer.addValueParam("drawbuffer", ParamType::TGLint, drawbuffer); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureClearBufferiv_value(glState, isCallValid, buffer, drawbuffer, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureClearBufferiv_value(glState, buffer, drawbuffer, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLClearBufferiv, std::move(paramBuffer)); } @@ -231,20 +227,18 @@ CallCapture CaptureClearBufferuiv(const State &glState, paramBuffer.addEnumParam("buffer", GLESEnum::Buffer, ParamType::TGLenum, buffer); paramBuffer.addValueParam("drawbuffer", ParamType::TGLint, drawbuffer); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureClearBufferuiv_value(glState, isCallValid, buffer, drawbuffer, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureClearBufferuiv_value(glState, buffer, drawbuffer, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLClearBufferuiv, std::move(paramBuffer)); } @@ -293,21 +287,19 @@ CallCapture CaptureCompressedTexImage3D(const State &glState, paramBuffer.addValueParam("border", ParamType::TGLint, border); paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexImage3D_data(glState, isCallValid, targetPacked, level, internalformat, - width, height, depth, border, imageSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexImage3D_data(glState, targetPacked, level, internalformat, width, + height, depth, border, imageSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexImage3D, std::move(paramBuffer)); } @@ -339,22 +331,20 @@ CallCapture CaptureCompressedTexSubImage3D(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::InternalFormat, ParamType::TGLenum, format); paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexSubImage3D_data(glState, isCallValid, targetPacked, level, xoffset, - yoffset, zoffset, width, height, depth, format, - imageSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexSubImage3D_data(glState, targetPacked, level, xoffset, yoffset, zoffset, + width, height, depth, format, imageSize, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexSubImage3D, std::move(paramBuffer)); } @@ -414,20 +404,18 @@ CallCapture CaptureDeleteQueries(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDConstPointer); if (isCallValid) { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDConstPointer); InitParamValue(ParamType::TQueryIDConstPointer, idsPacked, &idsPackedParam.value); - CaptureDeleteQueries_idsPacked(glState, isCallValid, n, idsPacked, &idsPackedParam); - paramBuffer.addParam(std::move(idsPackedParam)); + CaptureDeleteQueries_idsPacked(glState, n, idsPacked, &idsPackedParam); } else { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDConstPointer); InitParamValue(ParamType::TQueryIDConstPointer, static_cast(nullptr), &idsPackedParam.value); - paramBuffer.addParam(std::move(idsPackedParam)); } + paramBuffer.addParam(std::move(idsPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteQueries, std::move(paramBuffer)); } @@ -441,22 +429,19 @@ CallCapture CaptureDeleteSamplers(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture samplersPackedParam("samplersPacked", ParamType::TSamplerIDConstPointer); if (isCallValid) { - ParamCapture samplersPackedParam("samplersPacked", ParamType::TSamplerIDConstPointer); InitParamValue(ParamType::TSamplerIDConstPointer, samplersPacked, &samplersPackedParam.value); - CaptureDeleteSamplers_samplersPacked(glState, isCallValid, count, samplersPacked, - &samplersPackedParam); - paramBuffer.addParam(std::move(samplersPackedParam)); + CaptureDeleteSamplers_samplersPacked(glState, count, samplersPacked, &samplersPackedParam); } else { - ParamCapture samplersPackedParam("samplersPacked", ParamType::TSamplerIDConstPointer); InitParamValue(ParamType::TSamplerIDConstPointer, static_cast(nullptr), &samplersPackedParam.value); - paramBuffer.addParam(std::move(samplersPackedParam)); } + paramBuffer.addParam(std::move(samplersPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteSamplers, std::move(paramBuffer)); } @@ -479,22 +464,19 @@ CallCapture CaptureDeleteTransformFeedbacks(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture idsPackedParam("idsPacked", ParamType::TTransformFeedbackIDConstPointer); if (isCallValid) { - ParamCapture idsPackedParam("idsPacked", ParamType::TTransformFeedbackIDConstPointer); InitParamValue(ParamType::TTransformFeedbackIDConstPointer, idsPacked, &idsPackedParam.value); - CaptureDeleteTransformFeedbacks_idsPacked(glState, isCallValid, n, idsPacked, - &idsPackedParam); - paramBuffer.addParam(std::move(idsPackedParam)); + CaptureDeleteTransformFeedbacks_idsPacked(glState, n, idsPacked, &idsPackedParam); } else { - ParamCapture idsPackedParam("idsPacked", ParamType::TTransformFeedbackIDConstPointer); InitParamValue(ParamType::TTransformFeedbackIDConstPointer, static_cast(nullptr), &idsPackedParam.value); - paramBuffer.addParam(std::move(idsPackedParam)); } + paramBuffer.addParam(std::move(idsPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteTransformFeedbacks, std::move(paramBuffer)); } @@ -508,22 +490,19 @@ CallCapture CaptureDeleteVertexArrays(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDConstPointer); if (isCallValid) { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDConstPointer); InitParamValue(ParamType::TVertexArrayIDConstPointer, arraysPacked, &arraysPackedParam.value); - CaptureDeleteVertexArrays_arraysPacked(glState, isCallValid, n, arraysPacked, - &arraysPackedParam); - paramBuffer.addParam(std::move(arraysPackedParam)); + CaptureDeleteVertexArrays_arraysPacked(glState, n, arraysPacked, &arraysPackedParam); } else { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDConstPointer); InitParamValue(ParamType::TVertexArrayIDConstPointer, static_cast(nullptr), &arraysPackedParam.value); - paramBuffer.addParam(std::move(arraysPackedParam)); } + paramBuffer.addParam(std::move(arraysPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteVertexArrays, std::move(paramBuffer)); } @@ -554,20 +533,18 @@ CallCapture CaptureDrawBuffers(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture bufsParam("bufs", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture bufsParam("bufs", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, bufs, &bufsParam.value); - CaptureDrawBuffers_bufs(glState, isCallValid, n, bufs, &bufsParam); - paramBuffer.addParam(std::move(bufsParam)); + CaptureDrawBuffers_bufs(glState, n, bufs, &bufsParam); } else { - ParamCapture bufsParam("bufs", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &bufsParam.value); - paramBuffer.addParam(std::move(bufsParam)); } + paramBuffer.addParam(std::move(bufsParam)); return CallCapture(angle::EntryPoint::GLDrawBuffers, std::move(paramBuffer)); } @@ -586,21 +563,19 @@ CallCapture CaptureDrawElementsInstanced(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstanced_indices(glState, isCallValid, modePacked, count, typePacked, - indices, instancecount, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstanced_indices(glState, modePacked, count, typePacked, indices, + instancecount, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instancecount", ParamType::TGLsizei, instancecount); @@ -624,21 +599,19 @@ CallCapture CaptureDrawRangeElements(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawRangeElements_indices(glState, isCallValid, modePacked, start, end, count, - typePacked, indices, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawRangeElements_indices(glState, modePacked, start, end, count, typePacked, + indices, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); return CallCapture(angle::EntryPoint::GLDrawRangeElements, std::move(paramBuffer)); } @@ -718,20 +691,18 @@ CallCapture CaptureGenQueries(const State &glState, bool isCallValid, GLsizei n, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDPointer); if (isCallValid) { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDPointer); InitParamValue(ParamType::TQueryIDPointer, idsPacked, &idsPackedParam.value); - CaptureGenQueries_idsPacked(glState, isCallValid, n, idsPacked, &idsPackedParam); - paramBuffer.addParam(std::move(idsPackedParam)); + CaptureGenQueries_idsPacked(glState, n, idsPacked, &idsPackedParam); } else { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDPointer); InitParamValue(ParamType::TQueryIDPointer, static_cast(nullptr), &idsPackedParam.value); - paramBuffer.addParam(std::move(idsPackedParam)); } + paramBuffer.addParam(std::move(idsPackedParam)); return CallCapture(angle::EntryPoint::GLGenQueries, std::move(paramBuffer)); } @@ -745,21 +716,18 @@ CallCapture CaptureGenSamplers(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture samplersPackedParam("samplersPacked", ParamType::TSamplerIDPointer); if (isCallValid) { - ParamCapture samplersPackedParam("samplersPacked", ParamType::TSamplerIDPointer); InitParamValue(ParamType::TSamplerIDPointer, samplersPacked, &samplersPackedParam.value); - CaptureGenSamplers_samplersPacked(glState, isCallValid, count, samplersPacked, - &samplersPackedParam); - paramBuffer.addParam(std::move(samplersPackedParam)); + CaptureGenSamplers_samplersPacked(glState, count, samplersPacked, &samplersPackedParam); } else { - ParamCapture samplersPackedParam("samplersPacked", ParamType::TSamplerIDPointer); InitParamValue(ParamType::TSamplerIDPointer, static_cast(nullptr), &samplersPackedParam.value); - paramBuffer.addParam(std::move(samplersPackedParam)); } + paramBuffer.addParam(std::move(samplersPackedParam)); return CallCapture(angle::EntryPoint::GLGenSamplers, std::move(paramBuffer)); } @@ -773,20 +741,18 @@ CallCapture CaptureGenTransformFeedbacks(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture idsPackedParam("idsPacked", ParamType::TTransformFeedbackIDPointer); if (isCallValid) { - ParamCapture idsPackedParam("idsPacked", ParamType::TTransformFeedbackIDPointer); InitParamValue(ParamType::TTransformFeedbackIDPointer, idsPacked, &idsPackedParam.value); - CaptureGenTransformFeedbacks_idsPacked(glState, isCallValid, n, idsPacked, &idsPackedParam); - paramBuffer.addParam(std::move(idsPackedParam)); + CaptureGenTransformFeedbacks_idsPacked(glState, n, idsPacked, &idsPackedParam); } else { - ParamCapture idsPackedParam("idsPacked", ParamType::TTransformFeedbackIDPointer); InitParamValue(ParamType::TTransformFeedbackIDPointer, static_cast(nullptr), &idsPackedParam.value); - paramBuffer.addParam(std::move(idsPackedParam)); } + paramBuffer.addParam(std::move(idsPackedParam)); return CallCapture(angle::EntryPoint::GLGenTransformFeedbacks, std::move(paramBuffer)); } @@ -800,21 +766,18 @@ CallCapture CaptureGenVertexArrays(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDPointer); if (isCallValid) { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDPointer); InitParamValue(ParamType::TVertexArrayIDPointer, arraysPacked, &arraysPackedParam.value); - CaptureGenVertexArrays_arraysPacked(glState, isCallValid, n, arraysPacked, - &arraysPackedParam); - paramBuffer.addParam(std::move(arraysPackedParam)); + CaptureGenVertexArrays_arraysPacked(glState, n, arraysPacked, &arraysPackedParam); } else { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDPointer); InitParamValue(ParamType::TVertexArrayIDPointer, static_cast(nullptr), &arraysPackedParam.value); - paramBuffer.addParam(std::move(arraysPackedParam)); } + paramBuffer.addParam(std::move(arraysPackedParam)); return CallCapture(angle::EntryPoint::GLGenVertexArrays, std::move(paramBuffer)); } @@ -834,39 +797,34 @@ CallCapture CaptureGetActiveUniformBlockName(const State &glState, uniformBlockIndexPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetActiveUniformBlockName_length(glState, isCallValid, programPacked, - uniformBlockIndexPacked, bufSize, length, - uniformBlockName, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetActiveUniformBlockName_length(glState, programPacked, uniformBlockIndexPacked, + bufSize, length, uniformBlockName, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture uniformBlockNameParam("uniformBlockName", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture uniformBlockNameParam("uniformBlockName", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, uniformBlockName, &uniformBlockNameParam.value); - CaptureGetActiveUniformBlockName_uniformBlockName(glState, isCallValid, programPacked, + CaptureGetActiveUniformBlockName_uniformBlockName(glState, programPacked, uniformBlockIndexPacked, bufSize, length, uniformBlockName, &uniformBlockNameParam); - paramBuffer.addParam(std::move(uniformBlockNameParam)); } else { - ParamCapture uniformBlockNameParam("uniformBlockName", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &uniformBlockNameParam.value); - paramBuffer.addParam(std::move(uniformBlockNameParam)); } + paramBuffer.addParam(std::move(uniformBlockNameParam)); return CallCapture(angle::EntryPoint::GLGetActiveUniformBlockName, std::move(paramBuffer)); } @@ -885,20 +843,18 @@ CallCapture CaptureGetActiveUniformBlockiv(const State &glState, uniformBlockIndexPacked); paramBuffer.addEnumParam("pname", GLESEnum::UniformBlockPName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetActiveUniformBlockiv_params(glState, isCallValid, programPacked, - uniformBlockIndexPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetActiveUniformBlockiv_params(glState, programPacked, uniformBlockIndexPacked, + pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetActiveUniformBlockiv, std::move(paramBuffer)); } @@ -916,39 +872,35 @@ CallCapture CaptureGetActiveUniformsiv(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("uniformCount", ParamType::TGLsizei, uniformCount); + ParamCapture uniformIndicesParam("uniformIndices", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture uniformIndicesParam("uniformIndices", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, uniformIndices, &uniformIndicesParam.value); - CaptureGetActiveUniformsiv_uniformIndices(glState, isCallValid, programPacked, uniformCount, + CaptureGetActiveUniformsiv_uniformIndices(glState, programPacked, uniformCount, uniformIndices, pname, params, &uniformIndicesParam); - paramBuffer.addParam(std::move(uniformIndicesParam)); } else { - ParamCapture uniformIndicesParam("uniformIndices", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &uniformIndicesParam.value); - paramBuffer.addParam(std::move(uniformIndicesParam)); } + paramBuffer.addParam(std::move(uniformIndicesParam)); paramBuffer.addEnumParam("pname", GLESEnum::UniformPName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetActiveUniformsiv_params(glState, isCallValid, programPacked, uniformCount, - uniformIndices, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetActiveUniformsiv_params(glState, programPacked, uniformCount, uniformIndices, + pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetActiveUniformsiv, std::move(paramBuffer)); } @@ -964,21 +916,18 @@ CallCapture CaptureGetBufferParameteri64v(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, params, ¶msParam.value); - CaptureGetBufferParameteri64v_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferParameteri64v_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferParameteri64v, std::move(paramBuffer)); } @@ -994,21 +943,18 @@ CallCapture CaptureGetBufferPointerv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetBufferPointerv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferPointerv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferPointerv, std::move(paramBuffer)); } @@ -1023,20 +969,18 @@ CallCapture CaptureGetFragDataLocation(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetFragDataLocation_name(glState, isCallValid, programPacked, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetFragDataLocation_name(glState, programPacked, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLint); InitParamValue(ParamType::TGLint, returnValue, &returnValueCapture.value); @@ -1056,20 +1000,18 @@ CallCapture CaptureGetInteger64i_v(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::GetPName, ParamType::TGLenum, target); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture dataParam("data", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, data, &dataParam.value); - CaptureGetInteger64i_v_data(glState, isCallValid, target, index, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetInteger64i_v_data(glState, target, index, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetInteger64i_v, std::move(paramBuffer)); } @@ -1083,20 +1025,18 @@ CallCapture CaptureGetInteger64v(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, data, &dataParam.value); - CaptureGetInteger64v_data(glState, isCallValid, pname, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetInteger64v_data(glState, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetInteger64v, std::move(paramBuffer)); } @@ -1112,19 +1052,17 @@ CallCapture CaptureGetIntegeri_v(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::GetPName, ParamType::TGLenum, target); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture dataParam("data", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, data, &dataParam.value); - CaptureGetIntegeri_v_data(glState, isCallValid, target, index, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetIntegeri_v_data(glState, target, index, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetIntegeri_v, std::move(paramBuffer)); } @@ -1145,20 +1083,18 @@ CallCapture CaptureGetInternalformativ(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::InternalFormatPName, ParamType::TGLenum, pname); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetInternalformativ_params(glState, isCallValid, target, internalformat, pname, - count, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetInternalformativ_params(glState, target, internalformat, pname, count, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetInternalformativ, std::move(paramBuffer)); } @@ -1176,52 +1112,46 @@ CallCapture CaptureGetProgramBinary(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramBinary_length(glState, isCallValid, programPacked, bufSize, length, - binaryFormat, binary, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramBinary_length(glState, programPacked, bufSize, length, binaryFormat, + binary, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture binaryFormatParam("binaryFormat", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture binaryFormatParam("binaryFormat", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, binaryFormat, &binaryFormatParam.value); - CaptureGetProgramBinary_binaryFormat(glState, isCallValid, programPacked, bufSize, length, - binaryFormat, binary, &binaryFormatParam); - paramBuffer.addParam(std::move(binaryFormatParam)); + CaptureGetProgramBinary_binaryFormat(glState, programPacked, bufSize, length, binaryFormat, + binary, &binaryFormatParam); } else { - ParamCapture binaryFormatParam("binaryFormat", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &binaryFormatParam.value); - paramBuffer.addParam(std::move(binaryFormatParam)); } + paramBuffer.addParam(std::move(binaryFormatParam)); + ParamCapture binaryParam("binary", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture binaryParam("binary", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, binary, &binaryParam.value); - CaptureGetProgramBinary_binary(glState, isCallValid, programPacked, bufSize, length, - binaryFormat, binary, &binaryParam); - paramBuffer.addParam(std::move(binaryParam)); + CaptureGetProgramBinary_binary(glState, programPacked, bufSize, length, binaryFormat, + binary, &binaryParam); } else { - ParamCapture binaryParam("binary", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &binaryParam.value); - paramBuffer.addParam(std::move(binaryParam)); } + paramBuffer.addParam(std::move(binaryParam)); return CallCapture(angle::EntryPoint::GLGetProgramBinary, std::move(paramBuffer)); } @@ -1238,21 +1168,18 @@ CallCapture CaptureGetQueryObjectuiv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::QueryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetQueryObjectuiv_params(glState, isCallValid, idPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectuiv_params(glState, idPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectuiv, std::move(paramBuffer)); } @@ -1268,19 +1195,17 @@ CallCapture CaptureGetQueryiv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TQueryType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::QueryParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetQueryiv_params(glState, isCallValid, targetPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryiv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryiv, std::move(paramBuffer)); } @@ -1296,21 +1221,18 @@ CallCapture CaptureGetSamplerParameterfv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterF, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetSamplerParameterfv_params(glState, isCallValid, samplerPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterfv_params(glState, samplerPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterfv, std::move(paramBuffer)); } @@ -1326,20 +1248,17 @@ CallCapture CaptureGetSamplerParameteriv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetSamplerParameteriv_params(glState, isCallValid, samplerPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameteriv_params(glState, samplerPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameteriv, std::move(paramBuffer)); } @@ -1376,36 +1295,30 @@ CallCapture CaptureGetSynciv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::SyncParameterName, ParamType::TGLenum, pname); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetSynciv_length(glState, isCallValid, syncPacked, pname, count, length, values, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetSynciv_length(glState, syncPacked, pname, count, length, values, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture valuesParam("values", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture valuesParam("values", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, values, &valuesParam.value); - CaptureGetSynciv_values(glState, isCallValid, syncPacked, pname, count, length, values, - &valuesParam); - paramBuffer.addParam(std::move(valuesParam)); + CaptureGetSynciv_values(glState, syncPacked, pname, count, length, values, &valuesParam); } else { - ParamCapture valuesParam("values", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &valuesParam.value); - paramBuffer.addParam(std::move(valuesParam)); } + paramBuffer.addParam(std::move(valuesParam)); return CallCapture(angle::EntryPoint::GLGetSynciv, std::move(paramBuffer)); } @@ -1426,67 +1339,59 @@ CallCapture CaptureGetTransformFeedbackVarying(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTransformFeedbackVarying_length(glState, isCallValid, programPacked, index, - bufSize, length, size, type, name, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTransformFeedbackVarying_length(glState, programPacked, index, bufSize, length, + size, type, name, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture sizeParam("size", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture sizeParam("size", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, size, &sizeParam.value); - CaptureGetTransformFeedbackVarying_size(glState, isCallValid, programPacked, index, bufSize, - length, size, type, name, &sizeParam); - paramBuffer.addParam(std::move(sizeParam)); + CaptureGetTransformFeedbackVarying_size(glState, programPacked, index, bufSize, length, + size, type, name, &sizeParam); } else { - ParamCapture sizeParam("size", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &sizeParam.value); - paramBuffer.addParam(std::move(sizeParam)); } + paramBuffer.addParam(std::move(sizeParam)); + ParamCapture typeParam("type", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture typeParam("type", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, type, &typeParam.value); - CaptureGetTransformFeedbackVarying_type(glState, isCallValid, programPacked, index, bufSize, - length, size, type, name, &typeParam); - paramBuffer.addParam(std::move(typeParam)); + CaptureGetTransformFeedbackVarying_type(glState, programPacked, index, bufSize, length, + size, type, name, &typeParam); } else { - ParamCapture typeParam("type", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &typeParam.value); - paramBuffer.addParam(std::move(typeParam)); } + paramBuffer.addParam(std::move(typeParam)); + ParamCapture nameParam("name", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, name, &nameParam.value); - CaptureGetTransformFeedbackVarying_name(glState, isCallValid, programPacked, index, bufSize, - length, size, type, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetTransformFeedbackVarying_name(glState, programPacked, index, bufSize, length, + size, type, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLGetTransformFeedbackVarying, std::move(paramBuffer)); } @@ -1501,22 +1406,20 @@ CallCapture CaptureGetUniformBlockIndex(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); + ParamCapture uniformBlockNameParam("uniformBlockName", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture uniformBlockNameParam("uniformBlockName", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, uniformBlockName, &uniformBlockNameParam.value); - CaptureGetUniformBlockIndex_uniformBlockName(glState, isCallValid, programPacked, - uniformBlockName, &uniformBlockNameParam); - paramBuffer.addParam(std::move(uniformBlockNameParam)); + CaptureGetUniformBlockIndex_uniformBlockName(glState, programPacked, uniformBlockName, + &uniformBlockNameParam); } else { - ParamCapture uniformBlockNameParam("uniformBlockName", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &uniformBlockNameParam.value); - paramBuffer.addParam(std::move(uniformBlockNameParam)); } + paramBuffer.addParam(std::move(uniformBlockNameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLuint); InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value); @@ -1537,38 +1440,34 @@ CallCapture CaptureGetUniformIndices(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("uniformCount", ParamType::TGLsizei, uniformCount); + ParamCapture uniformNamesParam("uniformNames", ParamType::TGLcharConstPointerPointer); if (isCallValid) { - ParamCapture uniformNamesParam("uniformNames", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, uniformNames, &uniformNamesParam.value); - CaptureGetUniformIndices_uniformNames(glState, isCallValid, programPacked, uniformCount, - uniformNames, uniformIndices, &uniformNamesParam); - paramBuffer.addParam(std::move(uniformNamesParam)); + CaptureGetUniformIndices_uniformNames(glState, programPacked, uniformCount, uniformNames, + uniformIndices, &uniformNamesParam); } else { - ParamCapture uniformNamesParam("uniformNames", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, static_cast(nullptr), &uniformNamesParam.value); - paramBuffer.addParam(std::move(uniformNamesParam)); } + paramBuffer.addParam(std::move(uniformNamesParam)); + ParamCapture uniformIndicesParam("uniformIndices", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture uniformIndicesParam("uniformIndices", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, uniformIndices, &uniformIndicesParam.value); - CaptureGetUniformIndices_uniformIndices(glState, isCallValid, programPacked, uniformCount, - uniformNames, uniformIndices, &uniformIndicesParam); - paramBuffer.addParam(std::move(uniformIndicesParam)); + CaptureGetUniformIndices_uniformIndices(glState, programPacked, uniformCount, uniformNames, + uniformIndices, &uniformIndicesParam); } else { - ParamCapture uniformIndicesParam("uniformIndices", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &uniformIndicesParam.value); - paramBuffer.addParam(std::move(uniformIndicesParam)); } + paramBuffer.addParam(std::move(uniformIndicesParam)); return CallCapture(angle::EntryPoint::GLGetUniformIndices, std::move(paramBuffer)); } @@ -1584,21 +1483,18 @@ CallCapture CaptureGetUniformuiv(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetUniformuiv_params(glState, isCallValid, programPacked, locationPacked, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetUniformuiv_params(glState, programPacked, locationPacked, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetUniformuiv, std::move(paramBuffer)); } @@ -1614,19 +1510,17 @@ CallCapture CaptureGetVertexAttribIiv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addEnumParam("pname", GLESEnum::VertexAttribEnum, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetVertexAttribIiv_params(glState, isCallValid, index, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribIiv_params(glState, index, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribIiv, std::move(paramBuffer)); } @@ -1642,20 +1536,18 @@ CallCapture CaptureGetVertexAttribIuiv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addEnumParam("pname", GLESEnum::VertexAttribEnum, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetVertexAttribIuiv_params(glState, isCallValid, index, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribIuiv_params(glState, index, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribIuiv, std::move(paramBuffer)); } @@ -1671,21 +1563,19 @@ CallCapture CaptureInvalidateFramebuffer(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); paramBuffer.addValueParam("numAttachments", ParamType::TGLsizei, numAttachments); + ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, attachments, &attachmentsParam.value); - CaptureInvalidateFramebuffer_attachments(glState, isCallValid, target, numAttachments, - attachments, &attachmentsParam); - paramBuffer.addParam(std::move(attachmentsParam)); + CaptureInvalidateFramebuffer_attachments(glState, target, numAttachments, attachments, + &attachmentsParam); } else { - ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &attachmentsParam.value); - paramBuffer.addParam(std::move(attachmentsParam)); } + paramBuffer.addParam(std::move(attachmentsParam)); return CallCapture(angle::EntryPoint::GLInvalidateFramebuffer, std::move(paramBuffer)); } @@ -1705,22 +1595,19 @@ CallCapture CaptureInvalidateSubFramebuffer(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); paramBuffer.addValueParam("numAttachments", ParamType::TGLsizei, numAttachments); + ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, attachments, &attachmentsParam.value); - CaptureInvalidateSubFramebuffer_attachments(glState, isCallValid, target, numAttachments, - attachments, x, y, width, height, - &attachmentsParam); - paramBuffer.addParam(std::move(attachmentsParam)); + CaptureInvalidateSubFramebuffer_attachments(glState, target, numAttachments, attachments, x, + y, width, height, &attachmentsParam); } else { - ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &attachmentsParam.value); - paramBuffer.addParam(std::move(attachmentsParam)); } + paramBuffer.addParam(std::move(attachmentsParam)); paramBuffer.addValueParam("x", ParamType::TGLint, x); paramBuffer.addValueParam("y", ParamType::TGLint, y); @@ -1852,21 +1739,19 @@ CallCapture CaptureProgramBinary(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addEnumParam("binaryFormat", GLESEnum::AllEnums, ParamType::TGLenum, binaryFormat); + ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, binary, &binaryParam.value); - CaptureProgramBinary_binary(glState, isCallValid, programPacked, binaryFormat, binary, - length, &binaryParam); - paramBuffer.addParam(std::move(binaryParam)); + CaptureProgramBinary_binary(glState, programPacked, binaryFormat, binary, length, + &binaryParam); } else { - ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &binaryParam.value); - paramBuffer.addParam(std::move(binaryParam)); } + paramBuffer.addParam(std::move(binaryParam)); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); @@ -1950,21 +1835,18 @@ CallCapture CaptureSamplerParameterfv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterF, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, param, ¶mParam.value); - CaptureSamplerParameterfv_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterfv_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterfv, std::move(paramBuffer)); } @@ -1995,21 +1877,18 @@ CallCapture CaptureSamplerParameteriv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, param, ¶mParam.value); - CaptureSamplerParameteriv_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameteriv_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameteriv, std::move(paramBuffer)); } @@ -2039,21 +1918,19 @@ CallCapture CaptureTexImage3D(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexImage3D_pixels(glState, isCallValid, targetPacked, level, internalformat, width, - height, depth, border, format, type, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexImage3D_pixels(glState, targetPacked, level, internalformat, width, height, depth, + border, format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexImage3D, std::move(paramBuffer)); } @@ -2127,22 +2004,19 @@ CallCapture CaptureTexSubImage3D(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexSubImage3D_pixels(glState, isCallValid, targetPacked, level, xoffset, yoffset, - zoffset, width, height, depth, format, type, pixels, - &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexSubImage3D_pixels(glState, targetPacked, level, xoffset, yoffset, zoffset, width, + height, depth, format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexSubImage3D, std::move(paramBuffer)); } @@ -2159,21 +2033,19 @@ CallCapture CaptureTransformFeedbackVaryings(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture varyingsParam("varyings", ParamType::TGLcharConstPointerPointer); if (isCallValid) { - ParamCapture varyingsParam("varyings", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, varyings, &varyingsParam.value); - CaptureTransformFeedbackVaryings_varyings(glState, isCallValid, programPacked, count, - varyings, bufferMode, &varyingsParam); - paramBuffer.addParam(std::move(varyingsParam)); + CaptureTransformFeedbackVaryings_varyings(glState, programPacked, count, varyings, + bufferMode, &varyingsParam); } else { - ParamCapture varyingsParam("varyings", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, static_cast(nullptr), &varyingsParam.value); - paramBuffer.addParam(std::move(varyingsParam)); } + paramBuffer.addParam(std::move(varyingsParam)); paramBuffer.addEnumParam("bufferMode", GLESEnum::TransformFeedbackBufferMode, ParamType::TGLenum, bufferMode); @@ -2205,20 +2077,18 @@ CallCapture CaptureUniform1uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureUniform1uiv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform1uiv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform1uiv, std::move(paramBuffer)); } @@ -2249,20 +2119,18 @@ CallCapture CaptureUniform2uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureUniform2uiv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform2uiv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform2uiv, std::move(paramBuffer)); } @@ -2295,20 +2163,18 @@ CallCapture CaptureUniform3uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureUniform3uiv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform3uiv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform3uiv, std::move(paramBuffer)); } @@ -2343,20 +2209,18 @@ CallCapture CaptureUniform4uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureUniform4uiv_value(glState, isCallValid, locationPacked, count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniform4uiv_value(glState, locationPacked, count, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniform4uiv, std::move(paramBuffer)); } @@ -2390,21 +2254,19 @@ CallCapture CaptureUniformMatrix2x3fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix2x3fv_value(glState, isCallValid, locationPacked, count, transpose, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniformMatrix2x3fv_value(glState, locationPacked, count, transpose, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix2x3fv, std::move(paramBuffer)); } @@ -2422,21 +2284,19 @@ CallCapture CaptureUniformMatrix2x4fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix2x4fv_value(glState, isCallValid, locationPacked, count, transpose, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniformMatrix2x4fv_value(glState, locationPacked, count, transpose, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix2x4fv, std::move(paramBuffer)); } @@ -2454,21 +2314,19 @@ CallCapture CaptureUniformMatrix3x2fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix3x2fv_value(glState, isCallValid, locationPacked, count, transpose, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniformMatrix3x2fv_value(glState, locationPacked, count, transpose, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix3x2fv, std::move(paramBuffer)); } @@ -2486,21 +2344,19 @@ CallCapture CaptureUniformMatrix3x4fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix3x4fv_value(glState, isCallValid, locationPacked, count, transpose, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniformMatrix3x4fv_value(glState, locationPacked, count, transpose, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix3x4fv, std::move(paramBuffer)); } @@ -2518,21 +2374,19 @@ CallCapture CaptureUniformMatrix4x2fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix4x2fv_value(glState, isCallValid, locationPacked, count, transpose, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniformMatrix4x2fv_value(glState, locationPacked, count, transpose, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix4x2fv, std::move(paramBuffer)); } @@ -2550,21 +2404,19 @@ CallCapture CaptureUniformMatrix4x3fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureUniformMatrix4x3fv_value(glState, isCallValid, locationPacked, count, transpose, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureUniformMatrix4x3fv_value(glState, locationPacked, count, transpose, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLUniformMatrix4x3fv, std::move(paramBuffer)); } @@ -2626,20 +2478,18 @@ CallCapture CaptureVertexAttribI4iv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture vParam("v", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture vParam("v", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, v, &vParam.value); - CaptureVertexAttribI4iv_v(glState, isCallValid, index, v, &vParam); - paramBuffer.addParam(std::move(vParam)); + CaptureVertexAttribI4iv_v(glState, index, v, &vParam); } else { - ParamCapture vParam("v", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &vParam.value); - paramBuffer.addParam(std::move(vParam)); } + paramBuffer.addParam(std::move(vParam)); return CallCapture(angle::EntryPoint::GLVertexAttribI4iv, std::move(paramBuffer)); } @@ -2672,20 +2522,18 @@ CallCapture CaptureVertexAttribI4uiv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture vParam("v", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture vParam("v", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, v, &vParam.value); - CaptureVertexAttribI4uiv_v(glState, isCallValid, index, v, &vParam); - paramBuffer.addParam(std::move(vParam)); + CaptureVertexAttribI4uiv_v(glState, index, v, &vParam); } else { - ParamCapture vParam("v", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &vParam.value); - paramBuffer.addParam(std::move(vParam)); } + paramBuffer.addParam(std::move(vParam)); return CallCapture(angle::EntryPoint::GLVertexAttribI4uiv, std::move(paramBuffer)); } @@ -2705,21 +2553,19 @@ CallCapture CaptureVertexAttribIPointer(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TVertexAttribType, typePacked); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureVertexAttribIPointer_pointer(glState, isCallValid, index, size, typePacked, stride, - pointer, &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureVertexAttribIPointer_pointer(glState, index, size, typePacked, stride, pointer, + &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLVertexAttribIPointer, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_3_0_autogen.h b/src/libANGLE/capture/capture_gles_3_0_autogen.h index 1ff8c389f70..bd8dd873b40 100644 --- a/src/libANGLE/capture/capture_gles_3_0_autogen.h +++ b/src/libANGLE/capture/capture_gles_3_0_autogen.h @@ -597,25 +597,21 @@ angle::CallCapture CaptureWaitSync(const State &glState, // Parameter Captures void CaptureClearBufferfv_value(const State &glState, - bool isCallValid, GLenum buffer, GLint drawbuffer, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureClearBufferiv_value(const State &glState, - bool isCallValid, GLenum buffer, GLint drawbuffer, const GLint *value, angle::ParamCapture *paramCapture); void CaptureClearBufferuiv_value(const State &glState, - bool isCallValid, GLenum buffer, GLint drawbuffer, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureCompressedTexImage3D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -627,7 +623,6 @@ void CaptureCompressedTexImage3D_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexSubImage3D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -641,32 +636,26 @@ void CaptureCompressedTexSubImage3D_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureDeleteQueries_idsPacked(const State &glState, - bool isCallValid, GLsizei n, const QueryID *idsPacked, angle::ParamCapture *paramCapture); void CaptureDeleteSamplers_samplersPacked(const State &glState, - bool isCallValid, GLsizei count, const SamplerID *samplersPacked, angle::ParamCapture *paramCapture); void CaptureDeleteTransformFeedbacks_idsPacked(const State &glState, - bool isCallValid, GLsizei n, const TransformFeedbackID *idsPacked, angle::ParamCapture *paramCapture); void CaptureDeleteVertexArrays_arraysPacked(const State &glState, - bool isCallValid, GLsizei n, const VertexArrayID *arraysPacked, angle::ParamCapture *paramCapture); void CaptureDrawBuffers_bufs(const State &glState, - bool isCallValid, GLsizei n, const GLenum *bufs, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstanced_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -674,7 +663,6 @@ void CaptureDrawElementsInstanced_indices(const State &glState, GLsizei instancecount, angle::ParamCapture *paramCapture); void CaptureDrawRangeElements_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLuint start, GLuint end, @@ -683,27 +671,22 @@ void CaptureDrawRangeElements_indices(const State &glState, const void *indices, angle::ParamCapture *paramCapture); void CaptureGenQueries_idsPacked(const State &glState, - bool isCallValid, GLsizei n, QueryID *idsPacked, angle::ParamCapture *paramCapture); void CaptureGenSamplers_samplersPacked(const State &glState, - bool isCallValid, GLsizei count, SamplerID *samplersPacked, angle::ParamCapture *paramCapture); void CaptureGenTransformFeedbacks_idsPacked(const State &glState, - bool isCallValid, GLsizei n, TransformFeedbackID *idsPacked, angle::ParamCapture *paramCapture); void CaptureGenVertexArrays_arraysPacked(const State &glState, - bool isCallValid, GLsizei n, VertexArrayID *arraysPacked, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformBlockName_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformBlockIndex uniformBlockIndexPacked, GLsizei bufSize, @@ -711,7 +694,6 @@ void CaptureGetActiveUniformBlockName_length(const State &glState, GLchar *uniformBlockName, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformBlockName_uniformBlockName(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformBlockIndex uniformBlockIndexPacked, GLsizei bufSize, @@ -719,14 +701,12 @@ void CaptureGetActiveUniformBlockName_uniformBlockName(const State &glState, GLchar *uniformBlockName, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformBlockiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformBlockIndex uniformBlockIndexPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformsiv_uniformIndices(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei uniformCount, const GLuint *uniformIndices, @@ -734,7 +714,6 @@ void CaptureGetActiveUniformsiv_uniformIndices(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformsiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei uniformCount, const GLuint *uniformIndices, @@ -742,41 +721,34 @@ void CaptureGetActiveUniformsiv_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetBufferParameteri64v_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLint64 *params, angle::ParamCapture *paramCapture); void CaptureGetBufferPointerv_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, void **params, angle::ParamCapture *paramCapture); void CaptureGetFragDataLocation_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetInteger64i_v_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetInteger64v_data(const State &glState, - bool isCallValid, GLenum pname, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetIntegeri_v_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLint *data, angle::ParamCapture *paramCapture); void CaptureGetInternalformativ_params(const State &glState, - bool isCallValid, GLenum target, GLenum internalformat, GLenum pname, @@ -784,7 +756,6 @@ void CaptureGetInternalformativ_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramBinary_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, @@ -792,7 +763,6 @@ void CaptureGetProgramBinary_length(const State &glState, void *binary, angle::ParamCapture *paramCapture); void CaptureGetProgramBinary_binaryFormat(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, @@ -800,7 +770,6 @@ void CaptureGetProgramBinary_binaryFormat(const State &glState, void *binary, angle::ParamCapture *paramCapture); void CaptureGetProgramBinary_binary(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, @@ -808,31 +777,26 @@ void CaptureGetProgramBinary_binary(const State &glState, void *binary, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectuiv_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryiv_params(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterfv_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameteriv_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSynciv_length(const State &glState, - bool isCallValid, SyncID syncPacked, GLenum pname, GLsizei count, @@ -840,7 +804,6 @@ void CaptureGetSynciv_length(const State &glState, GLint *values, angle::ParamCapture *paramCapture); void CaptureGetSynciv_values(const State &glState, - bool isCallValid, SyncID syncPacked, GLenum pname, GLsizei count, @@ -848,7 +811,6 @@ void CaptureGetSynciv_values(const State &glState, GLint *values, angle::ParamCapture *paramCapture); void CaptureGetTransformFeedbackVarying_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -858,7 +820,6 @@ void CaptureGetTransformFeedbackVarying_length(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetTransformFeedbackVarying_size(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -868,7 +829,6 @@ void CaptureGetTransformFeedbackVarying_size(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetTransformFeedbackVarying_type(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -878,7 +838,6 @@ void CaptureGetTransformFeedbackVarying_type(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetTransformFeedbackVarying_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint index, GLsizei bufSize, @@ -888,50 +847,42 @@ void CaptureGetTransformFeedbackVarying_name(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetUniformBlockIndex_uniformBlockName(const State &glState, - bool isCallValid, ShaderProgramID programPacked, const GLchar *uniformBlockName, angle::ParamCapture *paramCapture); void CaptureGetUniformIndices_uniformNames(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei uniformCount, const GLchar *const *uniformNames, GLuint *uniformIndices, angle::ParamCapture *paramCapture); void CaptureGetUniformIndices_uniformIndices(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei uniformCount, const GLchar *const *uniformNames, GLuint *uniformIndices, angle::ParamCapture *paramCapture); void CaptureGetUniformuiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribIiv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribIuiv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureInvalidateFramebuffer_attachments(const State &glState, - bool isCallValid, GLenum target, GLsizei numAttachments, const GLenum *attachments, angle::ParamCapture *paramCapture); void CaptureInvalidateSubFramebuffer_attachments(const State &glState, - bool isCallValid, GLenum target, GLsizei numAttachments, const GLenum *attachments, @@ -941,26 +892,22 @@ void CaptureInvalidateSubFramebuffer_attachments(const State &glState, GLsizei height, angle::ParamCapture *paramCapture); void CaptureProgramBinary_binary(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum binaryFormat, const void *binary, GLsizei length, angle::ParamCapture *paramCapture); void CaptureSamplerParameterfv_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLfloat *param, angle::ParamCapture *paramCapture); void CaptureSamplerParameteriv_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLint *param, angle::ParamCapture *paramCapture); void CaptureTexImage3D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -973,7 +920,6 @@ void CaptureTexImage3D_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTexSubImage3D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -987,90 +933,76 @@ void CaptureTexSubImage3D_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTransformFeedbackVaryings_varyings(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei count, const GLchar *const *varyings, GLenum bufferMode, angle::ParamCapture *paramCapture); void CaptureUniform1uiv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureUniform2uiv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureUniform3uiv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureUniform4uiv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix2x3fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix2x4fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix3x2fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix3x4fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix4x2fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureUniformMatrix4x3fv_value(const State &glState, - bool isCallValid, UniformLocation locationPacked, GLsizei count, GLboolean transpose, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureVertexAttribI4iv_v(const State &glState, - bool isCallValid, GLuint index, const GLint *v, angle::ParamCapture *paramCapture); void CaptureVertexAttribI4uiv_v(const State &glState, - bool isCallValid, GLuint index, const GLuint *v, angle::ParamCapture *paramCapture); void CaptureVertexAttribIPointer_pointer(const State &glState, - bool isCallValid, GLuint index, GLint size, VertexAttribType typePacked, diff --git a/src/libANGLE/capture/capture_gles_3_0_params.cpp b/src/libANGLE/capture/capture_gles_3_0_params.cpp index f9639f74850..747dc02b98a 100644 --- a/src/libANGLE/capture/capture_gles_3_0_params.cpp +++ b/src/libANGLE/capture/capture_gles_3_0_params.cpp @@ -3,8 +3,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// capture_gles3_params.cpp: +// capture_gles_3_0_params.cpp: // Pointer parameter capture functions for the OpenGL ES 3.0 entry points. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/capture/capture_gles_2_0_autogen.h" #include "libANGLE/capture/capture_gles_3_0_autogen.h" @@ -14,7 +19,6 @@ using namespace angle; namespace gl { void CaptureClearBufferfv_value(const State &glState, - bool isCallValid, GLenum buffer, GLint drawbuffer, const GLfloat *value, @@ -24,7 +28,6 @@ void CaptureClearBufferfv_value(const State &glState, } void CaptureClearBufferiv_value(const State &glState, - bool isCallValid, GLenum buffer, GLint drawbuffer, const GLint *value, @@ -34,7 +37,6 @@ void CaptureClearBufferiv_value(const State &glState, } void CaptureClearBufferuiv_value(const State &glState, - bool isCallValid, GLenum buffer, GLint drawbuffer, const GLuint *value, @@ -44,7 +46,6 @@ void CaptureClearBufferuiv_value(const State &glState, } void CaptureCompressedTexImage3D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -70,7 +71,6 @@ void CaptureCompressedTexImage3D_data(const State &glState, } void CaptureCompressedTexSubImage3D_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -84,12 +84,11 @@ void CaptureCompressedTexSubImage3D_data(const State &glState, const void *data, ParamCapture *paramCapture) { - CaptureCompressedTexImage3D_data(glState, isCallValid, targetPacked, level, 0, width, height, - depth, 0, imageSize, data, paramCapture); + CaptureCompressedTexImage3D_data(glState, targetPacked, level, 0, width, height, depth, 0, + imageSize, data, paramCapture); } void CaptureDeleteQueries_idsPacked(const State &glState, - bool isCallValid, GLsizei n, const QueryID *ids, ParamCapture *paramCapture) @@ -98,7 +97,6 @@ void CaptureDeleteQueries_idsPacked(const State &glState, } void CaptureDeleteSamplers_samplersPacked(const State &glState, - bool isCallValid, GLsizei count, const SamplerID *samplers, ParamCapture *paramCapture) @@ -107,7 +105,6 @@ void CaptureDeleteSamplers_samplersPacked(const State &glState, } void CaptureDeleteTransformFeedbacks_idsPacked(const State &glState, - bool isCallValid, GLsizei n, const TransformFeedbackID *ids, ParamCapture *paramCapture) @@ -116,7 +113,6 @@ void CaptureDeleteTransformFeedbacks_idsPacked(const State &glState, } void CaptureDeleteVertexArrays_arraysPacked(const State &glState, - bool isCallValid, GLsizei n, const VertexArrayID *arrays, ParamCapture *paramCapture) @@ -125,7 +121,6 @@ void CaptureDeleteVertexArrays_arraysPacked(const State &glState, } void CaptureDrawBuffers_bufs(const State &glState, - bool isCallValid, GLsizei n, const GLenum *bufs, ParamCapture *paramCapture) @@ -134,7 +129,6 @@ void CaptureDrawBuffers_bufs(const State &glState, } void CaptureDrawElementsInstanced_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -142,12 +136,10 @@ void CaptureDrawElementsInstanced_indices(const State &glState, GLsizei instancecount, ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - paramCapture); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, paramCapture); } void CaptureDrawRangeElements_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLuint start, GLuint end, @@ -156,12 +148,10 @@ void CaptureDrawRangeElements_indices(const State &glState, const void *indices, ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - paramCapture); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, paramCapture); } void CaptureGenQueries_idsPacked(const State &glState, - bool isCallValid, GLsizei n, QueryID *ids, ParamCapture *paramCapture) @@ -170,7 +160,6 @@ void CaptureGenQueries_idsPacked(const State &glState, } void CaptureGenSamplers_samplersPacked(const State &glState, - bool isCallValid, GLsizei count, SamplerID *samplers, ParamCapture *paramCapture) @@ -179,7 +168,6 @@ void CaptureGenSamplers_samplersPacked(const State &glState, } void CaptureGenTransformFeedbacks_idsPacked(const State &glState, - bool isCallValid, GLsizei n, TransformFeedbackID *ids, ParamCapture *paramCapture) @@ -188,7 +176,6 @@ void CaptureGenTransformFeedbacks_idsPacked(const State &glState, } void CaptureGenVertexArrays_arraysPacked(const State &glState, - bool isCallValid, GLsizei n, VertexArrayID *arrays, ParamCapture *paramCapture) @@ -197,7 +184,6 @@ void CaptureGenVertexArrays_arraysPacked(const State &glState, } void CaptureGetActiveUniformBlockName_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformBlockIndex uniformBlockIndex, GLsizei bufSize, @@ -215,7 +201,6 @@ void CaptureGetActiveUniformBlockName_length(const State &glState, } void CaptureGetActiveUniformBlockName_uniformBlockName(const State &glState, - bool isCallValid, ShaderProgramID program, UniformBlockIndex uniformBlockIndex, GLsizei bufSize, @@ -230,7 +215,6 @@ void CaptureGetActiveUniformBlockName_uniformBlockName(const State &glState, } void CaptureGetActiveUniformBlockiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformBlockIndex uniformBlockIndex, GLenum pname, @@ -242,7 +226,6 @@ void CaptureGetActiveUniformBlockiv_params(const State &glState, } void CaptureGetActiveUniformsiv_uniformIndices(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei uniformCount, const GLuint *uniformIndices, @@ -258,7 +241,6 @@ void CaptureGetActiveUniformsiv_uniformIndices(const State &glState, } void CaptureGetActiveUniformsiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei uniformCount, const GLuint *uniformIndices, @@ -274,17 +256,16 @@ void CaptureGetActiveUniformsiv_params(const State &glState, } void CaptureGetBufferParameteri64v_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLint64 *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // This only returns one value + paramCapture->readBufferSizeBytes = sizeof(GLuint); } void CaptureGetBufferPointerv_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, void **params, @@ -294,7 +275,6 @@ void CaptureGetBufferPointerv_params(const State &glState, } void CaptureGetFragDataLocation_name(const State &glState, - bool isCallValid, ShaderProgramID program, const GLchar *name, ParamCapture *paramCapture) @@ -303,7 +283,6 @@ void CaptureGetFragDataLocation_name(const State &glState, } void CaptureGetInteger64i_v_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLint64 *data, @@ -313,7 +292,6 @@ void CaptureGetInteger64i_v_data(const State &glState, } void CaptureGetInteger64v_data(const State &glState, - bool isCallValid, GLenum pname, GLint64 *data, ParamCapture *paramCapture) @@ -322,7 +300,6 @@ void CaptureGetInteger64v_data(const State &glState, } void CaptureGetIntegeri_v_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLint *data, @@ -332,45 +309,34 @@ void CaptureGetIntegeri_v_data(const State &glState, } void CaptureGetInternalformativ_params(const State &glState, - bool isCallValid, GLenum target, GLenum internalformat, GLenum pname, - GLsizei bufSize, + GLsizei count, GLint *params, ParamCapture *paramCapture) { - // From the OpenGL ES 3.0 spec: - // - // The information retrieved will be written to memory addressed by the pointer specified in - // params. - // - // No more than bufSize integers will be written to this memory. - // - // If pname is GL_NUM_SAMPLE_COUNTS, the number of sample counts that would be returned by - // querying GL_SAMPLES will be returned in params. - // - // If pname is GL_SAMPLES, the sample counts supported for internalformat and target are written - // into params in descending numeric order. Only positive values are returned. - // - // Querying GL_SAMPLES with bufSize of one will return just the maximum supported number of - // samples for this format. - - if (bufSize == 0) - return; - - if (params) + if (params != nullptr) { - // For GL_NUM_SAMPLE_COUNTS, only one value is returned - // For GL_SAMPLES, two values will be returned, unless bufSize limits it to one - uint32_t paramCount = (pname == GL_SAMPLES && bufSize > 1) ? 2 : 1; - + // GL_NUM_SAMPLE_COUNTS and GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT + size_t paramCount = 1; + switch (pname) + { + case GL_SAMPLES: + // Maximum case: 1, 2, 4, 8, 16, 32 (IMPLEMENTATION_MAX_SAMPLES) + paramCount = rx::Log2(gl::IMPLEMENTATION_MAX_SAMPLES) + 1; + break; + case GL_SURFACE_COMPRESSION_EXT: + // From SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT to + // SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT + paramCount = 12; + break; + } paramCapture->readBufferSizeBytes = sizeof(GLint) * paramCount; } } void CaptureGetProgramBinary_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei bufSize, GLsizei *length, @@ -385,7 +351,6 @@ void CaptureGetProgramBinary_length(const State &glState, } void CaptureGetProgramBinary_binaryFormat(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei bufSize, GLsizei *length, @@ -397,7 +362,6 @@ void CaptureGetProgramBinary_binaryFormat(const State &glState, } void CaptureGetProgramBinary_binary(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei bufSize, GLsizei *length, @@ -424,7 +388,6 @@ void CaptureGetProgramBinary_binary(const State &glState, } void CaptureGetQueryObjectuiv_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLuint *params, @@ -435,7 +398,6 @@ void CaptureGetQueryObjectuiv_params(const State &glState, } void CaptureGetQueryiv_params(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLint *params, @@ -446,7 +408,6 @@ void CaptureGetQueryiv_params(const State &glState, } void CaptureGetSamplerParameterfv_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLfloat *params, @@ -457,7 +418,6 @@ void CaptureGetSamplerParameterfv_params(const State &glState, } void CaptureGetSamplerParameteriv_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLint *params, @@ -468,43 +428,35 @@ void CaptureGetSamplerParameteriv_params(const State &glState, } void CaptureGetSynciv_length(const State &glState, - bool isCallValid, SyncID syncPacked, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *values, ParamCapture *paramCapture) { - if (length) + if (length != nullptr) { paramCapture->readBufferSizeBytes = sizeof(GLsizei); } } void CaptureGetSynciv_values(const State &glState, - bool isCallValid, SyncID syncPacked, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *values, ParamCapture *paramCapture) { - // Spec: On success, GetSynciv replaces up to bufSize integers in values with the corresponding - // property values of the object being queried. The actual number of integers replaced is - // returned in *length.If length is NULL, no length is returned. - if (bufSize == 0) - return; - - if (values) + // All sync parameters return only one value. + if (values != nullptr) { - paramCapture->readBufferSizeBytes = sizeof(GLint) * bufSize; + paramCapture->readBufferSizeBytes = sizeof(GLint); } } void CaptureGetTransformFeedbackVarying_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -518,7 +470,6 @@ void CaptureGetTransformFeedbackVarying_length(const State &glState, } void CaptureGetTransformFeedbackVarying_size(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -532,7 +483,6 @@ void CaptureGetTransformFeedbackVarying_size(const State &glState, } void CaptureGetTransformFeedbackVarying_type(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -546,7 +496,6 @@ void CaptureGetTransformFeedbackVarying_type(const State &glState, } void CaptureGetTransformFeedbackVarying_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint index, GLsizei bufSize, @@ -560,7 +509,6 @@ void CaptureGetTransformFeedbackVarying_name(const State &glState, } void CaptureGetUniformBlockIndex_uniformBlockName(const State &glState, - bool isCallValid, ShaderProgramID program, const GLchar *uniformBlockName, ParamCapture *paramCapture) @@ -569,7 +517,6 @@ void CaptureGetUniformBlockIndex_uniformBlockName(const State &glState, } void CaptureGetUniformIndices_uniformNames(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei uniformCount, const GLchar *const *uniformNames, @@ -583,7 +530,6 @@ void CaptureGetUniformIndices_uniformNames(const State &glState, } void CaptureGetUniformIndices_uniformIndices(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei uniformCount, const GLchar *const *uniformNames, @@ -594,7 +540,6 @@ void CaptureGetUniformIndices_uniformIndices(const State &glState, } void CaptureGetUniformuiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLuint *params, @@ -605,7 +550,6 @@ void CaptureGetUniformuiv_params(const State &glState, } void CaptureGetVertexAttribIiv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLint *params, @@ -617,7 +561,6 @@ void CaptureGetVertexAttribIiv_params(const State &glState, } void CaptureGetVertexAttribIuiv_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLuint *params, @@ -629,7 +572,6 @@ void CaptureGetVertexAttribIuiv_params(const State &glState, } void CaptureInvalidateFramebuffer_attachments(const State &glState, - bool isCallValid, GLenum target, GLsizei numAttachments, const GLenum *attachments, @@ -640,7 +582,6 @@ void CaptureInvalidateFramebuffer_attachments(const State &glState, } void CaptureInvalidateSubFramebuffer_attachments(const State &glState, - bool isCallValid, GLenum target, GLsizei numAttachments, const GLenum *attachments, @@ -654,7 +595,6 @@ void CaptureInvalidateSubFramebuffer_attachments(const State &glState, } void CaptureProgramBinary_binary(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum binaryFormat, const void *binary, @@ -665,7 +605,6 @@ void CaptureProgramBinary_binary(const State &glState, } void CaptureSamplerParameterfv_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, const GLfloat *param, @@ -675,7 +614,6 @@ void CaptureSamplerParameterfv_param(const State &glState, } void CaptureSamplerParameteriv_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, const GLint *param, @@ -685,7 +623,6 @@ void CaptureSamplerParameteriv_param(const State &glState, } void CaptureTexImage3D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -722,7 +659,6 @@ void CaptureTexImage3D_pixels(const State &glState, } void CaptureTexSubImage3D_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -736,12 +672,11 @@ void CaptureTexSubImage3D_pixels(const State &glState, const void *pixels, ParamCapture *paramCapture) { - CaptureTexImage3D_pixels(glState, isCallValid, targetPacked, level, 0, width, height, depth, 0, - format, type, pixels, paramCapture); + CaptureTexImage3D_pixels(glState, targetPacked, level, 0, width, height, depth, 0, format, type, + pixels, paramCapture); } void CaptureTransformFeedbackVaryings_varyings(const State &glState, - bool isCallValid, ShaderProgramID program, GLsizei count, const GLchar *const *varyings, @@ -755,7 +690,6 @@ void CaptureTransformFeedbackVaryings_varyings(const State &glState, } void CaptureUniform1uiv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLuint *value, @@ -765,7 +699,6 @@ void CaptureUniform1uiv_value(const State &glState, } void CaptureUniform2uiv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLuint *value, @@ -775,7 +708,6 @@ void CaptureUniform2uiv_value(const State &glState, } void CaptureUniform3uiv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLuint *value, @@ -785,7 +717,6 @@ void CaptureUniform3uiv_value(const State &glState, } void CaptureUniform4uiv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, const GLuint *value, @@ -795,7 +726,6 @@ void CaptureUniform4uiv_value(const State &glState, } void CaptureUniformMatrix2x3fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -806,7 +736,6 @@ void CaptureUniformMatrix2x3fv_value(const State &glState, } void CaptureUniformMatrix2x4fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -817,7 +746,6 @@ void CaptureUniformMatrix2x4fv_value(const State &glState, } void CaptureUniformMatrix3x2fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -828,7 +756,6 @@ void CaptureUniformMatrix3x2fv_value(const State &glState, } void CaptureUniformMatrix3x4fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -839,7 +766,6 @@ void CaptureUniformMatrix3x4fv_value(const State &glState, } void CaptureUniformMatrix4x2fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -850,7 +776,6 @@ void CaptureUniformMatrix4x2fv_value(const State &glState, } void CaptureUniformMatrix4x3fv_value(const State &glState, - bool isCallValid, UniformLocation location, GLsizei count, GLboolean transpose, @@ -861,7 +786,6 @@ void CaptureUniformMatrix4x3fv_value(const State &glState, } void CaptureVertexAttribI4iv_v(const State &glState, - bool isCallValid, GLuint index, const GLint *v, ParamCapture *paramCapture) @@ -870,7 +794,6 @@ void CaptureVertexAttribI4iv_v(const State &glState, } void CaptureVertexAttribI4uiv_v(const State &glState, - bool isCallValid, GLuint index, const GLuint *v, ParamCapture *paramCapture) @@ -879,7 +802,6 @@ void CaptureVertexAttribI4uiv_v(const State &glState, } void CaptureVertexAttribIPointer_pointer(const State &glState, - bool isCallValid, GLuint index, GLint size, VertexAttribType typePacked, @@ -887,8 +809,8 @@ void CaptureVertexAttribIPointer_pointer(const State &glState, const void *pointer, ParamCapture *paramCapture) { - CaptureVertexAttribPointer_pointer(glState, isCallValid, index, size, typePacked, false, stride, - pointer, paramCapture); + CaptureVertexAttribPointer_pointer(glState, index, size, typePacked, false, stride, pointer, + paramCapture); } } // namespace gl diff --git a/src/libANGLE/capture/capture_gles_3_1_autogen.cpp b/src/libANGLE/capture/capture_gles_3_1_autogen.cpp index e2e95d6810b..c8235d94357 100644 --- a/src/libANGLE/capture/capture_gles_3_1_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_3_1_autogen.cpp @@ -95,21 +95,18 @@ CallCapture CaptureCreateShaderProgramv(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TShaderType, typePacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture stringsParam("strings", ParamType::TGLcharConstPointerPointer); if (isCallValid) { - ParamCapture stringsParam("strings", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, strings, &stringsParam.value); - CaptureCreateShaderProgramv_strings(glState, isCallValid, typePacked, count, strings, - &stringsParam); - paramBuffer.addParam(std::move(stringsParam)); + CaptureCreateShaderProgramv_strings(glState, typePacked, count, strings, &stringsParam); } else { - ParamCapture stringsParam("strings", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, static_cast(nullptr), &stringsParam.value); - paramBuffer.addParam(std::move(stringsParam)); } + paramBuffer.addParam(std::move(stringsParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLuint); InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value); @@ -127,25 +124,21 @@ CallCapture CaptureDeleteProgramPipelines(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDConstPointer); if (isCallValid) { - ParamCapture pipelinesPackedParam("pipelinesPacked", - ParamType::TProgramPipelineIDConstPointer); InitParamValue(ParamType::TProgramPipelineIDConstPointer, pipelinesPacked, &pipelinesPackedParam.value); - CaptureDeleteProgramPipelines_pipelinesPacked(glState, isCallValid, n, pipelinesPacked, + CaptureDeleteProgramPipelines_pipelinesPacked(glState, n, pipelinesPacked, &pipelinesPackedParam); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } else { - ParamCapture pipelinesPackedParam("pipelinesPacked", - ParamType::TProgramPipelineIDConstPointer); InitParamValue(ParamType::TProgramPipelineIDConstPointer, static_cast(nullptr), &pipelinesPackedParam.value); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } + paramBuffer.addParam(std::move(pipelinesPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteProgramPipelines, std::move(paramBuffer)); } @@ -185,21 +178,18 @@ CallCapture CaptureDrawArraysIndirect(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indirect, &indirectParam.value); - CaptureDrawArraysIndirect_indirect(glState, isCallValid, modePacked, indirect, - &indirectParam); - paramBuffer.addParam(std::move(indirectParam)); + CaptureDrawArraysIndirect_indirect(glState, modePacked, indirect, &indirectParam); } else { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indirectParam.value); - paramBuffer.addParam(std::move(indirectParam)); } + paramBuffer.addParam(std::move(indirectParam)); return CallCapture(angle::EntryPoint::GLDrawArraysIndirect, std::move(paramBuffer)); } @@ -215,21 +205,19 @@ CallCapture CaptureDrawElementsIndirect(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indirect, &indirectParam.value); - CaptureDrawElementsIndirect_indirect(glState, isCallValid, modePacked, typePacked, indirect, + CaptureDrawElementsIndirect_indirect(glState, modePacked, typePacked, indirect, &indirectParam); - paramBuffer.addParam(std::move(indirectParam)); } else { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indirectParam.value); - paramBuffer.addParam(std::move(indirectParam)); } + paramBuffer.addParam(std::move(indirectParam)); return CallCapture(angle::EntryPoint::GLDrawElementsIndirect, std::move(paramBuffer)); } @@ -259,22 +247,20 @@ CallCapture CaptureGenProgramPipelines(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer); if (isCallValid) { - ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer); InitParamValue(ParamType::TProgramPipelineIDPointer, pipelinesPacked, &pipelinesPackedParam.value); - CaptureGenProgramPipelines_pipelinesPacked(glState, isCallValid, n, pipelinesPacked, + CaptureGenProgramPipelines_pipelinesPacked(glState, n, pipelinesPacked, &pipelinesPackedParam); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } else { - ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer); InitParamValue(ParamType::TProgramPipelineIDPointer, static_cast(nullptr), &pipelinesPackedParam.value); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } + paramBuffer.addParam(std::move(pipelinesPackedParam)); return CallCapture(angle::EntryPoint::GLGenProgramPipelines, std::move(paramBuffer)); } @@ -290,20 +276,18 @@ CallCapture CaptureGetBooleani_v(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::BufferTargetARB, ParamType::TGLenum, target); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture dataParam("data", ParamType::TGLbooleanPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, data, &dataParam.value); - CaptureGetBooleani_v_data(glState, isCallValid, target, index, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetBooleani_v_data(glState, target, index, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetBooleani_v, std::move(paramBuffer)); } @@ -320,20 +304,17 @@ CallCapture CaptureGetFramebufferParameteriv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::FramebufferAttachmentParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferParameteriv_params(glState, isCallValid, target, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferParameteriv_params(glState, target, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferParameteriv, std::move(paramBuffer)); } @@ -349,20 +330,18 @@ CallCapture CaptureGetMultisamplefv(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture valParam("val", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture valParam("val", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, val, &valParam.value); - CaptureGetMultisamplefv_val(glState, isCallValid, pname, index, val, &valParam); - paramBuffer.addParam(std::move(valParam)); + CaptureGetMultisamplefv_val(glState, pname, index, val, &valParam); } else { - ParamCapture valParam("val", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), &valParam.value); - paramBuffer.addParam(std::move(valParam)); } + paramBuffer.addParam(std::move(valParam)); return CallCapture(angle::EntryPoint::GLGetMultisamplefv, std::move(paramBuffer)); } @@ -381,20 +360,18 @@ CallCapture CaptureGetProgramInterfaceiv(const State &glState, programInterface); paramBuffer.addEnumParam("pname", GLESEnum::ProgramInterfacePName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramInterfaceiv_params(glState, isCallValid, programPacked, programInterface, - pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramInterfaceiv_params(glState, programPacked, programInterface, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramInterfaceiv, std::move(paramBuffer)); } @@ -411,37 +388,33 @@ CallCapture CaptureGetProgramPipelineInfoLog(const State &glState, paramBuffer.addValueParam("pipelinePacked", ParamType::TProgramPipelineID, pipelinePacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramPipelineInfoLog_length(glState, isCallValid, pipelinePacked, bufSize, - length, infoLog, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramPipelineInfoLog_length(glState, pipelinePacked, bufSize, length, infoLog, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, infoLog, &infoLogParam.value); - CaptureGetProgramPipelineInfoLog_infoLog(glState, isCallValid, pipelinePacked, bufSize, - length, infoLog, &infoLogParam); - paramBuffer.addParam(std::move(infoLogParam)); + CaptureGetProgramPipelineInfoLog_infoLog(glState, pipelinePacked, bufSize, length, infoLog, + &infoLogParam); } else { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &infoLogParam.value); - paramBuffer.addParam(std::move(infoLogParam)); } + paramBuffer.addParam(std::move(infoLogParam)); return CallCapture(angle::EntryPoint::GLGetProgramPipelineInfoLog, std::move(paramBuffer)); } @@ -457,20 +430,17 @@ CallCapture CaptureGetProgramPipelineiv(const State &glState, paramBuffer.addValueParam("pipelinePacked", ParamType::TProgramPipelineID, pipelinePacked); paramBuffer.addEnumParam("pname", GLESEnum::PipelineParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramPipelineiv_params(glState, isCallValid, pipelinePacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramPipelineiv_params(glState, pipelinePacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramPipelineiv, std::move(paramBuffer)); } @@ -488,21 +458,19 @@ CallCapture CaptureGetProgramResourceIndex(const State &glState, paramBuffer.addEnumParam("programInterface", GLESEnum::ProgramInterface, ParamType::TGLenum, programInterface); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetProgramResourceIndex_name(glState, isCallValid, programPacked, programInterface, - name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetProgramResourceIndex_name(glState, programPacked, programInterface, name, + &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLuint); InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value); @@ -524,21 +492,19 @@ CallCapture CaptureGetProgramResourceLocation(const State &glState, paramBuffer.addEnumParam("programInterface", GLESEnum::ProgramInterface, ParamType::TGLenum, programInterface); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetProgramResourceLocation_name(glState, isCallValid, programPacked, - programInterface, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetProgramResourceLocation_name(glState, programPacked, programInterface, name, + &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLint); InitParamValue(ParamType::TGLint, returnValue, &returnValueCapture.value); @@ -564,36 +530,32 @@ CallCapture CaptureGetProgramResourceName(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramResourceName_length(glState, isCallValid, programPacked, programInterface, - index, bufSize, length, name, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramResourceName_length(glState, programPacked, programInterface, index, + bufSize, length, name, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture nameParam("name", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, name, &nameParam.value); - CaptureGetProgramResourceName_name(glState, isCallValid, programPacked, programInterface, - index, bufSize, length, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetProgramResourceName_name(glState, programPacked, programInterface, index, bufSize, + length, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLGetProgramResourceName, std::move(paramBuffer)); } @@ -617,57 +579,48 @@ CallCapture CaptureGetProgramResourceiv(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("propCount", ParamType::TGLsizei, propCount); + ParamCapture propsParam("props", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture propsParam("props", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, props, &propsParam.value); - CaptureGetProgramResourceiv_props(glState, isCallValid, programPacked, programInterface, - index, propCount, props, count, length, params, - &propsParam); - paramBuffer.addParam(std::move(propsParam)); + CaptureGetProgramResourceiv_props(glState, programPacked, programInterface, index, + propCount, props, count, length, params, &propsParam); } else { - ParamCapture propsParam("props", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &propsParam.value); - paramBuffer.addParam(std::move(propsParam)); } + paramBuffer.addParam(std::move(propsParam)); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramResourceiv_length(glState, isCallValid, programPacked, programInterface, - index, propCount, props, count, length, params, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramResourceiv_length(glState, programPacked, programInterface, index, + propCount, props, count, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramResourceiv_params(glState, isCallValid, programPacked, programInterface, - index, propCount, props, count, length, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramResourceiv_params(glState, programPacked, programInterface, index, + propCount, props, count, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramResourceiv, std::move(paramBuffer)); } @@ -685,21 +638,19 @@ CallCapture CaptureGetTexLevelParameterfv(const State &glState, paramBuffer.addValueParam("level", ParamType::TGLint, level); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexLevelParameterfv_params(glState, isCallValid, targetPacked, level, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexLevelParameterfv_params(glState, targetPacked, level, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexLevelParameterfv, std::move(paramBuffer)); } @@ -717,20 +668,18 @@ CallCapture CaptureGetTexLevelParameteriv(const State &glState, paramBuffer.addValueParam("level", ParamType::TGLint, level); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexLevelParameteriv_params(glState, isCallValid, targetPacked, level, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexLevelParameteriv_params(glState, targetPacked, level, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexLevelParameteriv, std::move(paramBuffer)); } @@ -801,21 +750,19 @@ CallCapture CaptureProgramUniform1fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform1fv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform1fv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform1fv, std::move(paramBuffer)); } @@ -848,21 +795,19 @@ CallCapture CaptureProgramUniform1iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform1iv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform1iv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform1iv, std::move(paramBuffer)); } @@ -895,21 +840,19 @@ CallCapture CaptureProgramUniform1uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform1uiv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform1uiv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform1uiv, std::move(paramBuffer)); } @@ -944,21 +887,19 @@ CallCapture CaptureProgramUniform2fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform2fv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform2fv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform2fv, std::move(paramBuffer)); } @@ -993,21 +934,19 @@ CallCapture CaptureProgramUniform2iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform2iv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform2iv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform2iv, std::move(paramBuffer)); } @@ -1042,21 +981,19 @@ CallCapture CaptureProgramUniform2uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform2uiv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform2uiv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform2uiv, std::move(paramBuffer)); } @@ -1093,21 +1030,19 @@ CallCapture CaptureProgramUniform3fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform3fv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform3fv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform3fv, std::move(paramBuffer)); } @@ -1144,21 +1079,19 @@ CallCapture CaptureProgramUniform3iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform3iv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform3iv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform3iv, std::move(paramBuffer)); } @@ -1195,21 +1128,19 @@ CallCapture CaptureProgramUniform3uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform3uiv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform3uiv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform3uiv, std::move(paramBuffer)); } @@ -1248,21 +1179,19 @@ CallCapture CaptureProgramUniform4fv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform4fv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform4fv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform4fv, std::move(paramBuffer)); } @@ -1301,21 +1230,19 @@ CallCapture CaptureProgramUniform4iv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform4iv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform4iv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform4iv, std::move(paramBuffer)); } @@ -1354,21 +1281,19 @@ CallCapture CaptureProgramUniform4uiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform4uiv_value(glState, isCallValid, programPacked, locationPacked, count, - value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform4uiv_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform4uiv, std::move(paramBuffer)); } @@ -1388,21 +1313,19 @@ CallCapture CaptureProgramUniformMatrix2fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix2fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix2fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix2fv, std::move(paramBuffer)); } @@ -1422,21 +1345,19 @@ CallCapture CaptureProgramUniformMatrix2x3fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix2x3fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix2x3fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix2x3fv, std::move(paramBuffer)); } @@ -1456,21 +1377,19 @@ CallCapture CaptureProgramUniformMatrix2x4fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix2x4fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix2x4fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix2x4fv, std::move(paramBuffer)); } @@ -1490,21 +1409,19 @@ CallCapture CaptureProgramUniformMatrix3fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix3fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix3fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix3fv, std::move(paramBuffer)); } @@ -1524,21 +1441,19 @@ CallCapture CaptureProgramUniformMatrix3x2fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix3x2fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix3x2fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix3x2fv, std::move(paramBuffer)); } @@ -1558,21 +1473,19 @@ CallCapture CaptureProgramUniformMatrix3x4fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix3x4fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix3x4fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix3x4fv, std::move(paramBuffer)); } @@ -1592,21 +1505,19 @@ CallCapture CaptureProgramUniformMatrix4fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix4fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix4fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix4fv, std::move(paramBuffer)); } @@ -1626,21 +1537,19 @@ CallCapture CaptureProgramUniformMatrix4x2fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix4x2fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix4x2fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix4x2fv, std::move(paramBuffer)); } @@ -1660,21 +1569,19 @@ CallCapture CaptureProgramUniformMatrix4x3fv(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix4x3fv_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix4x3fv_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix4x3fv, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_3_1_autogen.h b/src/libANGLE/capture/capture_gles_3_1_autogen.h index 4dc89cf9ab6..6bf9cf68b40 100644 --- a/src/libANGLE/capture/capture_gles_3_1_autogen.h +++ b/src/libANGLE/capture/capture_gles_3_1_autogen.h @@ -422,91 +422,76 @@ angle::CallCapture CaptureVertexBindingDivisor(const State &glState, // Parameter Captures void CaptureCreateShaderProgramv_strings(const State &glState, - bool isCallValid, ShaderType typePacked, GLsizei count, const GLchar *const *strings, angle::ParamCapture *paramCapture); void CaptureDeleteProgramPipelines_pipelinesPacked(const State &glState, - bool isCallValid, GLsizei n, const ProgramPipelineID *pipelinesPacked, angle::ParamCapture *paramCapture); void CaptureDrawArraysIndirect_indirect(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const void *indirect, angle::ParamCapture *paramCapture); void CaptureDrawElementsIndirect_indirect(const State &glState, - bool isCallValid, PrimitiveMode modePacked, DrawElementsType typePacked, const void *indirect, angle::ParamCapture *paramCapture); void CaptureGenProgramPipelines_pipelinesPacked(const State &glState, - bool isCallValid, GLsizei n, ProgramPipelineID *pipelinesPacked, angle::ParamCapture *paramCapture); void CaptureGetBooleani_v_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLboolean *data, angle::ParamCapture *paramCapture); void CaptureGetFramebufferParameteriv_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetMultisamplefv_val(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLfloat *val, angle::ParamCapture *paramCapture); void CaptureGetProgramInterfaceiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramPipelineInfoLog_length(const State &glState, - bool isCallValid, ProgramPipelineID pipelinePacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetProgramPipelineInfoLog_infoLog(const State &glState, - bool isCallValid, ProgramPipelineID pipelinePacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetProgramPipelineiv_params(const State &glState, - bool isCallValid, ProgramPipelineID pipelinePacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceIndex_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceLocation_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceName_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLuint index, @@ -515,7 +500,6 @@ void CaptureGetProgramResourceName_length(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceName_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLuint index, @@ -524,7 +508,6 @@ void CaptureGetProgramResourceName_name(const State &glState, GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceiv_props(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLuint index, @@ -535,7 +518,6 @@ void CaptureGetProgramResourceiv_props(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceiv_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLuint index, @@ -546,7 +528,6 @@ void CaptureGetProgramResourceiv_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLuint index, @@ -557,105 +538,90 @@ void CaptureGetProgramResourceiv_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterfv_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameteriv_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureProgramUniform1fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform1iv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform1uiv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform2fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform2iv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform2uiv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform3fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform3iv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform3uiv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform4fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform4iv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform4uiv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix2fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -663,7 +629,6 @@ void CaptureProgramUniformMatrix2fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix2x3fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -671,7 +636,6 @@ void CaptureProgramUniformMatrix2x3fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix2x4fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -679,7 +643,6 @@ void CaptureProgramUniformMatrix2x4fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix3fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -687,7 +650,6 @@ void CaptureProgramUniformMatrix3fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix3x2fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -695,7 +657,6 @@ void CaptureProgramUniformMatrix3x2fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix3x4fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -703,7 +664,6 @@ void CaptureProgramUniformMatrix3x4fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix4fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -711,7 +671,6 @@ void CaptureProgramUniformMatrix4fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix4x2fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -719,7 +678,6 @@ void CaptureProgramUniformMatrix4x2fv_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix4x3fv_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, diff --git a/src/libANGLE/capture/capture_gles_3_1_params.cpp b/src/libANGLE/capture/capture_gles_3_1_params.cpp index 0a50daf4c3b..4b6d181ba4d 100644 --- a/src/libANGLE/capture/capture_gles_3_1_params.cpp +++ b/src/libANGLE/capture/capture_gles_3_1_params.cpp @@ -14,7 +14,6 @@ namespace gl { void CaptureCreateShaderProgramv_strings(const State &glState, - bool isCallValid, ShaderType typePacked, GLsizei count, const GLchar *const *strings, @@ -24,7 +23,6 @@ void CaptureCreateShaderProgramv_strings(const State &glState, } void CaptureDeleteProgramPipelines_pipelinesPacked(const State &glState, - bool isCallValid, GLsizei n, const ProgramPipelineID *pipelines, ParamCapture *paramCapture) @@ -33,7 +31,6 @@ void CaptureDeleteProgramPipelines_pipelinesPacked(const State &glState, } void CaptureDrawArraysIndirect_indirect(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const void *indirect, ParamCapture *paramCapture) @@ -42,11 +39,10 @@ void CaptureDrawArraysIndirect_indirect(const State &glState, // including the DrawArraysIndirectCommand structure, be in buffer objects, // and may not be called when the default vertex array object is bound. // Indirect pointer is automatically captured in capture_gles_3_1_autogen.cpp - assert(!isCallValid || glState.getTargetBuffer(gl::BufferBinding::DrawIndirect)); + assert(glState.getTargetBuffer(gl::BufferBinding::DrawIndirect)); } void CaptureDrawElementsIndirect_indirect(const State &glState, - bool isCallValid, PrimitiveMode modePacked, DrawElementsType typePacked, const void *indirect, @@ -56,11 +52,10 @@ void CaptureDrawElementsIndirect_indirect(const State &glState, // including the DrawElementsIndirectCommand structure, be in buffer objects, // and may not be called when the default vertex array object is bound // Indirect pointer is automatically captured in capture_gles_3_1_autogen.cpp - assert(!isCallValid || glState.getTargetBuffer(gl::BufferBinding::DrawIndirect)); + assert(glState.getTargetBuffer(gl::BufferBinding::DrawIndirect)); } void CaptureGenProgramPipelines_pipelinesPacked(const State &glState, - bool isCallValid, GLsizei n, ProgramPipelineID *pipelines, ParamCapture *paramCapture) @@ -69,7 +64,6 @@ void CaptureGenProgramPipelines_pipelinesPacked(const State &glState, } void CaptureGetBooleani_v_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLboolean *data, @@ -79,7 +73,6 @@ void CaptureGetBooleani_v_data(const State &glState, } void CaptureGetFramebufferParameteriv_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLint *params, @@ -90,7 +83,6 @@ void CaptureGetFramebufferParameteriv_params(const State &glState, } void CaptureGetMultisamplefv_val(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLfloat *val, @@ -101,7 +93,6 @@ void CaptureGetMultisamplefv_val(const State &glState, } void CaptureGetProgramInterfaceiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLenum pname, @@ -112,7 +103,6 @@ void CaptureGetProgramInterfaceiv_params(const State &glState, } void CaptureGetProgramPipelineInfoLog_length(const State &glState, - bool isCallValid, ProgramPipelineID pipeline, GLsizei bufSize, GLsizei *length, @@ -126,7 +116,6 @@ void CaptureGetProgramPipelineInfoLog_length(const State &glState, } void CaptureGetProgramPipelineInfoLog_infoLog(const State &glState, - bool isCallValid, ProgramPipelineID pipeline, GLsizei bufSize, GLsizei *length, @@ -148,7 +137,6 @@ void CaptureGetProgramPipelineInfoLog_infoLog(const State &glState, } void CaptureGetProgramPipelineiv_params(const State &glState, - bool isCallValid, ProgramPipelineID pipeline, GLenum pname, GLint *params, @@ -158,7 +146,6 @@ void CaptureGetProgramPipelineiv_params(const State &glState, } void CaptureGetProgramResourceIndex_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, const GLchar *name, @@ -168,7 +155,6 @@ void CaptureGetProgramResourceIndex_name(const State &glState, } void CaptureGetProgramResourceLocation_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, const GLchar *name, @@ -178,7 +164,6 @@ void CaptureGetProgramResourceLocation_name(const State &glState, } void CaptureGetProgramResourceName_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLuint index, @@ -191,7 +176,6 @@ void CaptureGetProgramResourceName_length(const State &glState, } void CaptureGetProgramResourceName_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLuint index, @@ -204,13 +188,12 @@ void CaptureGetProgramResourceName_name(const State &glState, } void CaptureGetProgramResourceiv_props(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *params, ParamCapture *paramCapture) @@ -219,13 +202,12 @@ void CaptureGetProgramResourceiv_props(const State &glState, } void CaptureGetProgramResourceiv_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *params, ParamCapture *paramCapture) @@ -234,25 +216,23 @@ void CaptureGetProgramResourceiv_length(const State &glState, } void CaptureGetProgramResourceiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *params, ParamCapture *paramCapture) { // Prefer to only capture as many parameters as are returned, // but if this is not known, then capture the whole buffer - int paramLength = length != nullptr ? *length : bufSize; + int paramLength = length != nullptr ? *length : count; CaptureMemory(params, sizeof(GLint) * paramLength, paramCapture); } void CaptureGetTexLevelParameterfv_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -263,7 +243,6 @@ void CaptureGetTexLevelParameterfv_params(const State &glState, } void CaptureGetTexLevelParameteriv_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -274,7 +253,6 @@ void CaptureGetTexLevelParameteriv_params(const State &glState, } void CaptureProgramUniform1fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -285,7 +263,6 @@ void CaptureProgramUniform1fv_value(const State &glState, } void CaptureProgramUniform1iv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -296,7 +273,6 @@ void CaptureProgramUniform1iv_value(const State &glState, } void CaptureProgramUniform1uiv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -307,7 +283,6 @@ void CaptureProgramUniform1uiv_value(const State &glState, } void CaptureProgramUniform2fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -318,7 +293,6 @@ void CaptureProgramUniform2fv_value(const State &glState, } void CaptureProgramUniform2iv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -329,7 +303,6 @@ void CaptureProgramUniform2iv_value(const State &glState, } void CaptureProgramUniform2uiv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -340,7 +313,6 @@ void CaptureProgramUniform2uiv_value(const State &glState, } void CaptureProgramUniform3fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -351,7 +323,6 @@ void CaptureProgramUniform3fv_value(const State &glState, } void CaptureProgramUniform3iv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -362,7 +333,6 @@ void CaptureProgramUniform3iv_value(const State &glState, } void CaptureProgramUniform3uiv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -373,7 +343,6 @@ void CaptureProgramUniform3uiv_value(const State &glState, } void CaptureProgramUniform4fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -384,7 +353,6 @@ void CaptureProgramUniform4fv_value(const State &glState, } void CaptureProgramUniform4iv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -395,7 +363,6 @@ void CaptureProgramUniform4iv_value(const State &glState, } void CaptureProgramUniform4uiv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -406,7 +373,6 @@ void CaptureProgramUniform4uiv_value(const State &glState, } void CaptureProgramUniformMatrix2fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -418,7 +384,6 @@ void CaptureProgramUniformMatrix2fv_value(const State &glState, } void CaptureProgramUniformMatrix2x3fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -430,7 +395,6 @@ void CaptureProgramUniformMatrix2x3fv_value(const State &glState, } void CaptureProgramUniformMatrix2x4fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -442,7 +406,6 @@ void CaptureProgramUniformMatrix2x4fv_value(const State &glState, } void CaptureProgramUniformMatrix3fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -454,7 +417,6 @@ void CaptureProgramUniformMatrix3fv_value(const State &glState, } void CaptureProgramUniformMatrix3x2fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -466,7 +428,6 @@ void CaptureProgramUniformMatrix3x2fv_value(const State &glState, } void CaptureProgramUniformMatrix3x4fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -478,7 +439,6 @@ void CaptureProgramUniformMatrix3x4fv_value(const State &glState, } void CaptureProgramUniformMatrix4fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -490,7 +450,6 @@ void CaptureProgramUniformMatrix4fv_value(const State &glState, } void CaptureProgramUniformMatrix4x2fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, @@ -502,7 +461,6 @@ void CaptureProgramUniformMatrix4x2fv_value(const State &glState, } void CaptureProgramUniformMatrix4x3fv_value(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei count, diff --git a/src/libANGLE/capture/capture_gles_3_2_autogen.cpp b/src/libANGLE/capture/capture_gles_3_2_autogen.cpp index 236387d2783..14b5786f5a1 100644 --- a/src/libANGLE/capture/capture_gles_3_2_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_3_2_autogen.cpp @@ -156,21 +156,18 @@ CallCapture CaptureDebugMessageCallback(const State &glState, paramBuffer.addValueParam("callback", ParamType::TGLDEBUGPROC, callback); + ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, userParam, &userParamParam.value); - CaptureDebugMessageCallback_userParam(glState, isCallValid, callback, userParam, - &userParamParam); - paramBuffer.addParam(std::move(userParamParam)); + CaptureDebugMessageCallback_userParam(glState, callback, userParam, &userParamParam); } else { - ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &userParamParam.value); - paramBuffer.addParam(std::move(userParamParam)); } + paramBuffer.addParam(std::move(userParamParam)); return CallCapture(angle::EntryPoint::GLDebugMessageCallback, std::move(paramBuffer)); } @@ -191,21 +188,19 @@ CallCapture CaptureDebugMessageControl(const State &glState, paramBuffer.addEnumParam("severity", GLESEnum::DebugSeverity, ParamType::TGLenum, severity); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture idsParam("ids", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture idsParam("ids", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, ids, &idsParam.value); - CaptureDebugMessageControl_ids(glState, isCallValid, source, type, severity, count, ids, - enabled, &idsParam); - paramBuffer.addParam(std::move(idsParam)); + CaptureDebugMessageControl_ids(glState, source, type, severity, count, ids, enabled, + &idsParam); } else { - ParamCapture idsParam("ids", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &idsParam.value); - paramBuffer.addParam(std::move(idsParam)); } + paramBuffer.addParam(std::move(idsParam)); paramBuffer.addValueParam("enabled", ParamType::TGLboolean, enabled); @@ -229,21 +224,18 @@ CallCapture CaptureDebugMessageInsert(const State &glState, paramBuffer.addEnumParam("severity", GLESEnum::DebugSeverity, ParamType::TGLenum, severity); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture bufParam("buf", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture bufParam("buf", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, buf, &bufParam.value); - CaptureDebugMessageInsert_buf(glState, isCallValid, source, type, id, severity, length, buf, - &bufParam); - paramBuffer.addParam(std::move(bufParam)); + CaptureDebugMessageInsert_buf(glState, source, type, id, severity, length, buf, &bufParam); } else { - ParamCapture bufParam("buf", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &bufParam.value); - paramBuffer.addParam(std::move(bufParam)); } + paramBuffer.addParam(std::move(bufParam)); return CallCapture(angle::EntryPoint::GLDebugMessageInsert, std::move(paramBuffer)); } @@ -272,21 +264,19 @@ CallCapture CaptureDrawElementsBaseVertex(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsBaseVertex_indices(glState, isCallValid, modePacked, count, typePacked, - indices, basevertex, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsBaseVertex_indices(glState, modePacked, count, typePacked, indices, + basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -308,22 +298,20 @@ CallCapture CaptureDrawElementsInstancedBaseVertex(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstancedBaseVertex_indices(glState, isCallValid, modePacked, count, - typePacked, indices, instancecount, - basevertex, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstancedBaseVertex_indices(glState, modePacked, count, typePacked, + indices, instancecount, basevertex, + &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instancecount", ParamType::TGLsizei, instancecount); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -350,22 +338,19 @@ CallCapture CaptureDrawRangeElementsBaseVertex(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawRangeElementsBaseVertex_indices(glState, isCallValid, modePacked, start, end, - count, typePacked, indices, basevertex, - &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawRangeElementsBaseVertex_indices(glState, modePacked, start, end, count, + typePacked, indices, basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -417,102 +402,88 @@ CallCapture CaptureGetDebugMessageLog(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLuint, count); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture sourcesParam("sources", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture sourcesParam("sources", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, sources, &sourcesParam.value); - CaptureGetDebugMessageLog_sources(glState, isCallValid, count, bufSize, sources, types, ids, - severities, lengths, messageLog, &sourcesParam); - paramBuffer.addParam(std::move(sourcesParam)); + CaptureGetDebugMessageLog_sources(glState, count, bufSize, sources, types, ids, severities, + lengths, messageLog, &sourcesParam); } else { - ParamCapture sourcesParam("sources", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &sourcesParam.value); - paramBuffer.addParam(std::move(sourcesParam)); } + paramBuffer.addParam(std::move(sourcesParam)); + ParamCapture typesParam("types", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture typesParam("types", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, types, &typesParam.value); - CaptureGetDebugMessageLog_types(glState, isCallValid, count, bufSize, sources, types, ids, - severities, lengths, messageLog, &typesParam); - paramBuffer.addParam(std::move(typesParam)); + CaptureGetDebugMessageLog_types(glState, count, bufSize, sources, types, ids, severities, + lengths, messageLog, &typesParam); } else { - ParamCapture typesParam("types", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &typesParam.value); - paramBuffer.addParam(std::move(typesParam)); } + paramBuffer.addParam(std::move(typesParam)); + ParamCapture idsParam("ids", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture idsParam("ids", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, ids, &idsParam.value); - CaptureGetDebugMessageLog_ids(glState, isCallValid, count, bufSize, sources, types, ids, - severities, lengths, messageLog, &idsParam); - paramBuffer.addParam(std::move(idsParam)); + CaptureGetDebugMessageLog_ids(glState, count, bufSize, sources, types, ids, severities, + lengths, messageLog, &idsParam); } else { - ParamCapture idsParam("ids", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &idsParam.value); - paramBuffer.addParam(std::move(idsParam)); } + paramBuffer.addParam(std::move(idsParam)); + ParamCapture severitiesParam("severities", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture severitiesParam("severities", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, severities, &severitiesParam.value); - CaptureGetDebugMessageLog_severities(glState, isCallValid, count, bufSize, sources, types, - ids, severities, lengths, messageLog, - &severitiesParam); - paramBuffer.addParam(std::move(severitiesParam)); + CaptureGetDebugMessageLog_severities(glState, count, bufSize, sources, types, ids, + severities, lengths, messageLog, &severitiesParam); } else { - ParamCapture severitiesParam("severities", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &severitiesParam.value); - paramBuffer.addParam(std::move(severitiesParam)); } + paramBuffer.addParam(std::move(severitiesParam)); + ParamCapture lengthsParam("lengths", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthsParam("lengths", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, lengths, &lengthsParam.value); - CaptureGetDebugMessageLog_lengths(glState, isCallValid, count, bufSize, sources, types, ids, - severities, lengths, messageLog, &lengthsParam); - paramBuffer.addParam(std::move(lengthsParam)); + CaptureGetDebugMessageLog_lengths(glState, count, bufSize, sources, types, ids, severities, + lengths, messageLog, &lengthsParam); } else { - ParamCapture lengthsParam("lengths", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthsParam.value); - paramBuffer.addParam(std::move(lengthsParam)); } + paramBuffer.addParam(std::move(lengthsParam)); + ParamCapture messageLogParam("messageLog", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture messageLogParam("messageLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, messageLog, &messageLogParam.value); - CaptureGetDebugMessageLog_messageLog(glState, isCallValid, count, bufSize, sources, types, - ids, severities, lengths, messageLog, - &messageLogParam); - paramBuffer.addParam(std::move(messageLogParam)); + CaptureGetDebugMessageLog_messageLog(glState, count, bufSize, sources, types, ids, + severities, lengths, messageLog, &messageLogParam); } else { - ParamCapture messageLogParam("messageLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &messageLogParam.value); - paramBuffer.addParam(std::move(messageLogParam)); } + paramBuffer.addParam(std::move(messageLogParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLuint); InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value); @@ -549,37 +520,32 @@ CallCapture CaptureGetObjectLabel(const State &glState, paramBuffer.addValueParam("name", ParamType::TGLuint, name); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetObjectLabel_length(glState, isCallValid, identifier, name, bufSize, length, label, + CaptureGetObjectLabel_length(glState, identifier, name, bufSize, length, label, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture labelParam("label", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, label, &labelParam.value); - CaptureGetObjectLabel_label(glState, isCallValid, identifier, name, bufSize, length, label, - &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureGetObjectLabel_label(glState, identifier, name, bufSize, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLGetObjectLabel, std::move(paramBuffer)); } @@ -593,54 +559,46 @@ CallCapture CaptureGetObjectPtrLabel(const State &glState, { ParamBuffer paramBuffer; + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); - CaptureGetObjectPtrLabel_ptr(glState, isCallValid, ptr, bufSize, length, label, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureGetObjectPtrLabel_ptr(glState, ptr, bufSize, length, label, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetObjectPtrLabel_length(glState, isCallValid, ptr, bufSize, length, label, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetObjectPtrLabel_length(glState, ptr, bufSize, length, label, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture labelParam("label", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, label, &labelParam.value); - CaptureGetObjectPtrLabel_label(glState, isCallValid, ptr, bufSize, length, label, - &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureGetObjectPtrLabel_label(glState, ptr, bufSize, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLGetObjectPtrLabel, std::move(paramBuffer)); } @@ -651,20 +609,18 @@ CallCapture CaptureGetPointerv(const State &glState, bool isCallValid, GLenum pn paramBuffer.addEnumParam("pname", GLESEnum::GetPointervPName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetPointerv_params(glState, isCallValid, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetPointerv_params(glState, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetPointerv, std::move(paramBuffer)); } @@ -680,20 +636,17 @@ CallCapture CaptureGetSamplerParameterIiv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIiv_params(glState, isCallValid, samplerPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterIiv_params(glState, samplerPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIiv, std::move(paramBuffer)); } @@ -709,21 +662,18 @@ CallCapture CaptureGetSamplerParameterIuiv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIuiv_params(glState, isCallValid, samplerPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterIuiv_params(glState, samplerPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIuiv, std::move(paramBuffer)); } @@ -739,20 +689,17 @@ CallCapture CaptureGetTexParameterIiv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexParameterIiv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIiv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIiv, std::move(paramBuffer)); } @@ -768,21 +715,18 @@ CallCapture CaptureGetTexParameterIuiv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetTexParameterIuiv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIuiv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIuiv, std::move(paramBuffer)); } @@ -800,21 +744,19 @@ CallCapture CaptureGetnUniformfv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetnUniformfv_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformfv_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformfv, std::move(paramBuffer)); } @@ -832,20 +774,18 @@ CallCapture CaptureGetnUniformiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetnUniformiv_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformiv_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformiv, std::move(paramBuffer)); } @@ -863,21 +803,19 @@ CallCapture CaptureGetnUniformuiv(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetnUniformuiv_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformuiv_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformuiv, std::move(paramBuffer)); } @@ -923,21 +861,18 @@ CallCapture CaptureObjectLabel(const State &glState, paramBuffer.addValueParam("name", ParamType::TGLuint, name); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture labelParam("label", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, label, &labelParam.value); - CaptureObjectLabel_label(glState, isCallValid, identifier, name, length, label, - &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureObjectLabel_label(glState, identifier, name, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLObjectLabel, std::move(paramBuffer)); } @@ -950,37 +885,33 @@ CallCapture CaptureObjectPtrLabel(const State &glState, { ParamBuffer paramBuffer; + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); - CaptureObjectPtrLabel_ptr(glState, isCallValid, ptr, length, label, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureObjectPtrLabel_ptr(glState, ptr, length, label, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture labelParam("label", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, label, &labelParam.value); - CaptureObjectPtrLabel_label(glState, isCallValid, ptr, length, label, &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureObjectPtrLabel_label(glState, ptr, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLObjectPtrLabel, std::move(paramBuffer)); } @@ -1043,21 +974,18 @@ CallCapture CapturePushDebugGroup(const State &glState, paramBuffer.addValueParam("id", ParamType::TGLuint, id); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture messageParam("message", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture messageParam("message", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, message, &messageParam.value); - CapturePushDebugGroup_message(glState, isCallValid, source, id, length, message, - &messageParam); - paramBuffer.addParam(std::move(messageParam)); + CapturePushDebugGroup_message(glState, source, id, length, message, &messageParam); } else { - ParamCapture messageParam("message", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &messageParam.value); - paramBuffer.addParam(std::move(messageParam)); } + paramBuffer.addParam(std::move(messageParam)); return CallCapture(angle::EntryPoint::GLPushDebugGroup, std::move(paramBuffer)); } @@ -1083,20 +1011,18 @@ CallCapture CaptureReadnPixels(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture dataParam("data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, data, &dataParam.value); - CaptureReadnPixels_data(glState, isCallValid, x, y, width, height, format, type, bufSize, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureReadnPixels_data(glState, x, y, width, height, format, type, bufSize, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLReadnPixels, std::move(paramBuffer)); } @@ -1112,21 +1038,18 @@ CallCapture CaptureSamplerParameterIiv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIiv_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIiv_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIiv, std::move(paramBuffer)); } @@ -1142,21 +1065,18 @@ CallCapture CaptureSamplerParameterIuiv(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIuiv_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIuiv_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIuiv, std::move(paramBuffer)); } @@ -1208,21 +1128,18 @@ CallCapture CaptureTexParameterIiv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexParameterIiv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIiv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIiv, std::move(paramBuffer)); } @@ -1238,21 +1155,18 @@ CallCapture CaptureTexParameterIuiv(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, params, ¶msParam.value); - CaptureTexParameterIuiv_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIuiv_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIuiv, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_3_2_autogen.h b/src/libANGLE/capture/capture_gles_3_2_autogen.h index 9e0de6771c6..5059f037c83 100644 --- a/src/libANGLE/capture/capture_gles_3_2_autogen.h +++ b/src/libANGLE/capture/capture_gles_3_2_autogen.h @@ -288,12 +288,10 @@ angle::CallCapture CaptureTexStorage3DMultisample(const State &glState, // Parameter Captures void CaptureDebugMessageCallback_userParam(const State &glState, - bool isCallValid, GLDEBUGPROC callback, const void *userParam, angle::ParamCapture *paramCapture); void CaptureDebugMessageControl_ids(const State &glState, - bool isCallValid, GLenum source, GLenum type, GLenum severity, @@ -302,7 +300,6 @@ void CaptureDebugMessageControl_ids(const State &glState, GLboolean enabled, angle::ParamCapture *paramCapture); void CaptureDebugMessageInsert_buf(const State &glState, - bool isCallValid, GLenum source, GLenum type, GLuint id, @@ -311,7 +308,6 @@ void CaptureDebugMessageInsert_buf(const State &glState, const GLchar *buf, angle::ParamCapture *paramCapture); void CaptureDrawElementsBaseVertex_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -319,7 +315,6 @@ void CaptureDrawElementsBaseVertex_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedBaseVertex_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -328,7 +323,6 @@ void CaptureDrawElementsInstancedBaseVertex_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawRangeElementsBaseVertex_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLuint start, GLuint end, @@ -338,7 +332,6 @@ void CaptureDrawRangeElementsBaseVertex_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLog_sources(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -349,7 +342,6 @@ void CaptureGetDebugMessageLog_sources(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLog_types(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -360,7 +352,6 @@ void CaptureGetDebugMessageLog_types(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLog_ids(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -371,7 +362,6 @@ void CaptureGetDebugMessageLog_ids(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLog_severities(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -382,7 +372,6 @@ void CaptureGetDebugMessageLog_severities(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLog_lengths(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -393,7 +382,6 @@ void CaptureGetDebugMessageLog_lengths(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLog_messageLog(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -404,7 +392,6 @@ void CaptureGetDebugMessageLog_messageLog(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetObjectLabel_length(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei bufSize, @@ -412,7 +399,6 @@ void CaptureGetObjectLabel_length(const State &glState, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectLabel_label(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei bufSize, @@ -420,104 +406,88 @@ void CaptureGetObjectLabel_label(const State &glState, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectPtrLabel_ptr(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectPtrLabel_length(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectPtrLabel_label(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetPointerv_params(const State &glState, - bool isCallValid, GLenum pname, void **params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIiv_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIuiv_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIuiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformfv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformuiv_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLuint *params, angle::ParamCapture *paramCapture); void CaptureObjectLabel_label(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CaptureObjectPtrLabel_ptr(const State &glState, - bool isCallValid, const void *ptr, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CaptureObjectPtrLabel_label(const State &glState, - bool isCallValid, const void *ptr, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CapturePushDebugGroup_message(const State &glState, - bool isCallValid, GLenum source, GLuint id, GLsizei length, const GLchar *message, angle::ParamCapture *paramCapture); void CaptureReadnPixels_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -528,25 +498,21 @@ void CaptureReadnPixels_data(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIiv_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLint *param, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIuiv_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLuint *param, angle::ParamCapture *paramCapture); void CaptureTexParameterIiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexParameterIuiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLuint *params, diff --git a/src/libANGLE/capture/capture_gles_3_2_params.cpp b/src/libANGLE/capture/capture_gles_3_2_params.cpp index 0cf37887ca0..804127f632e 100644 --- a/src/libANGLE/capture/capture_gles_3_2_params.cpp +++ b/src/libANGLE/capture/capture_gles_3_2_params.cpp @@ -15,7 +15,6 @@ namespace gl { void CaptureDebugMessageCallback_userParam(const State &glState, - bool isCallValid, GLDEBUGPROC callback, const void *userParam, ParamCapture *userParamParam) @@ -24,7 +23,6 @@ void CaptureDebugMessageCallback_userParam(const State &glState, } void CaptureDebugMessageControl_ids(const State &glState, - bool isCallValid, GLenum source, GLenum type, GLenum severity, @@ -37,7 +35,6 @@ void CaptureDebugMessageControl_ids(const State &glState, } void CaptureDebugMessageInsert_buf(const State &glState, - bool isCallValid, GLenum source, GLenum type, GLuint id, @@ -50,7 +47,6 @@ void CaptureDebugMessageInsert_buf(const State &glState, } void CaptureDrawElementsBaseVertex_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -58,12 +54,10 @@ void CaptureDrawElementsBaseVertex_indices(const State &glState, GLint basevertex, ParamCapture *indicesParam) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - indicesParam); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, indicesParam); } void CaptureDrawElementsInstancedBaseVertex_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -76,7 +70,6 @@ void CaptureDrawElementsInstancedBaseVertex_indices(const State &glState, } void CaptureDrawRangeElementsBaseVertex_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLuint start, GLuint end, @@ -90,7 +83,6 @@ void CaptureDrawRangeElementsBaseVertex_indices(const State &glState, } void CaptureGetDebugMessageLog_sources(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -105,7 +97,6 @@ void CaptureGetDebugMessageLog_sources(const State &glState, } void CaptureGetDebugMessageLog_types(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -120,7 +111,6 @@ void CaptureGetDebugMessageLog_types(const State &glState, } void CaptureGetDebugMessageLog_ids(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -135,7 +125,6 @@ void CaptureGetDebugMessageLog_ids(const State &glState, } void CaptureGetDebugMessageLog_severities(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -150,7 +139,6 @@ void CaptureGetDebugMessageLog_severities(const State &glState, } void CaptureGetDebugMessageLog_lengths(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -165,7 +153,6 @@ void CaptureGetDebugMessageLog_lengths(const State &glState, } void CaptureGetDebugMessageLog_messageLog(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -180,7 +167,6 @@ void CaptureGetDebugMessageLog_messageLog(const State &glState, } void CaptureGetObjectLabel_length(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei bufSize, @@ -192,7 +178,6 @@ void CaptureGetObjectLabel_length(const State &glState, } void CaptureGetObjectLabel_label(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei bufSize, @@ -204,7 +189,6 @@ void CaptureGetObjectLabel_label(const State &glState, } void CaptureGetObjectPtrLabel_ptr(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, @@ -215,7 +199,6 @@ void CaptureGetObjectPtrLabel_ptr(const State &glState, } void CaptureGetObjectPtrLabel_length(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, @@ -226,7 +209,6 @@ void CaptureGetObjectPtrLabel_length(const State &glState, } void CaptureGetObjectPtrLabel_label(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, @@ -237,7 +219,6 @@ void CaptureGetObjectPtrLabel_label(const State &glState, } void CaptureGetPointerv_params(const State &glState, - bool isCallValid, GLenum pname, void **params, ParamCapture *paramCapture) @@ -246,7 +227,6 @@ void CaptureGetPointerv_params(const State &glState, } void CaptureGetSamplerParameterIiv_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLint *params, @@ -257,7 +237,6 @@ void CaptureGetSamplerParameterIiv_params(const State &glState, } void CaptureGetSamplerParameterIuiv_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLuint *params, @@ -268,7 +247,6 @@ void CaptureGetSamplerParameterIuiv_params(const State &glState, } void CaptureGetTexParameterIiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLint *params, @@ -280,7 +258,6 @@ void CaptureGetTexParameterIiv_params(const State &glState, } void CaptureGetTexParameterIuiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLuint *params, @@ -292,7 +269,6 @@ void CaptureGetTexParameterIuiv_params(const State &glState, } void CaptureGetnUniformfv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -303,7 +279,6 @@ void CaptureGetnUniformfv_params(const State &glState, } void CaptureGetnUniformiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -314,7 +289,6 @@ void CaptureGetnUniformiv_params(const State &glState, } void CaptureGetnUniformuiv_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -325,7 +299,6 @@ void CaptureGetnUniformuiv_params(const State &glState, } void CaptureObjectLabel_label(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei length, @@ -336,7 +309,6 @@ void CaptureObjectLabel_label(const State &glState, } void CaptureObjectPtrLabel_ptr(const State &glState, - bool isCallValid, const void *ptr, GLsizei length, const GLchar *label, @@ -346,7 +318,6 @@ void CaptureObjectPtrLabel_ptr(const State &glState, } void CaptureObjectPtrLabel_label(const State &glState, - bool isCallValid, const void *ptr, GLsizei length, const GLchar *label, @@ -356,7 +327,6 @@ void CaptureObjectPtrLabel_label(const State &glState, } void CapturePushDebugGroup_message(const State &glState, - bool isCallValid, GLenum source, GLuint id, GLsizei length, @@ -367,7 +337,6 @@ void CapturePushDebugGroup_message(const State &glState, } void CaptureReadnPixels_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -382,7 +351,6 @@ void CaptureReadnPixels_data(const State &glState, } void CaptureSamplerParameterIiv_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, const GLint *param, @@ -392,7 +360,6 @@ void CaptureSamplerParameterIiv_param(const State &glState, } void CaptureSamplerParameterIuiv_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, const GLuint *param, @@ -402,7 +369,6 @@ void CaptureSamplerParameterIuiv_param(const State &glState, } void CaptureTexParameterIiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLint *params, @@ -412,7 +378,6 @@ void CaptureTexParameterIiv_params(const State &glState, } void CaptureTexParameterIuiv_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLuint *params, diff --git a/src/libANGLE/capture/capture_gles_ext_autogen.cpp b/src/libANGLE/capture/capture_gles_ext_autogen.cpp index e510fed3161..bf2a517fc06 100644 --- a/src/libANGLE/capture/capture_gles_ext_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_ext_autogen.cpp @@ -37,20 +37,18 @@ CallCapture CaptureDeletePerfMonitorsAMD(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture monitorsParam("monitors", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture monitorsParam("monitors", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, monitors, &monitorsParam.value); - CaptureDeletePerfMonitorsAMD_monitors(glState, isCallValid, n, monitors, &monitorsParam); - paramBuffer.addParam(std::move(monitorsParam)); + CaptureDeletePerfMonitorsAMD_monitors(glState, n, monitors, &monitorsParam); } else { - ParamCapture monitorsParam("monitors", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &monitorsParam.value); - paramBuffer.addParam(std::move(monitorsParam)); } + paramBuffer.addParam(std::move(monitorsParam)); return CallCapture(angle::EntryPoint::GLDeletePerfMonitorsAMD, std::move(paramBuffer)); } @@ -73,20 +71,18 @@ CallCapture CaptureGenPerfMonitorsAMD(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture monitorsParam("monitors", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture monitorsParam("monitors", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, monitors, &monitorsParam.value); - CaptureGenPerfMonitorsAMD_monitors(glState, isCallValid, n, monitors, &monitorsParam); - paramBuffer.addParam(std::move(monitorsParam)); + CaptureGenPerfMonitorsAMD_monitors(glState, n, monitors, &monitorsParam); } else { - ParamCapture monitorsParam("monitors", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &monitorsParam.value); - paramBuffer.addParam(std::move(monitorsParam)); } + paramBuffer.addParam(std::move(monitorsParam)); return CallCapture(angle::EntryPoint::GLGenPerfMonitorsAMD, std::move(paramBuffer)); } @@ -105,36 +101,32 @@ CallCapture CaptureGetPerfMonitorCounterDataAMD(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("dataSize", ParamType::TGLsizei, dataSize); + ParamCapture dataParam("data", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, data, &dataParam.value); - CaptureGetPerfMonitorCounterDataAMD_data(glState, isCallValid, monitor, pname, dataSize, - data, bytesWritten, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetPerfMonitorCounterDataAMD_data(glState, monitor, pname, dataSize, data, + bytesWritten, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); + ParamCapture bytesWrittenParam("bytesWritten", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture bytesWrittenParam("bytesWritten", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, bytesWritten, &bytesWrittenParam.value); - CaptureGetPerfMonitorCounterDataAMD_bytesWritten( - glState, isCallValid, monitor, pname, dataSize, data, bytesWritten, &bytesWrittenParam); - paramBuffer.addParam(std::move(bytesWrittenParam)); + CaptureGetPerfMonitorCounterDataAMD_bytesWritten(glState, monitor, pname, dataSize, data, + bytesWritten, &bytesWrittenParam); } else { - ParamCapture bytesWrittenParam("bytesWritten", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &bytesWrittenParam.value); - paramBuffer.addParam(std::move(bytesWrittenParam)); } + paramBuffer.addParam(std::move(bytesWrittenParam)); return CallCapture(angle::EntryPoint::GLGetPerfMonitorCounterDataAMD, std::move(paramBuffer)); } @@ -152,20 +144,17 @@ CallCapture CaptureGetPerfMonitorCounterInfoAMD(const State &glState, paramBuffer.addValueParam("counter", ParamType::TGLuint, counter); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, data, &dataParam.value); - CaptureGetPerfMonitorCounterInfoAMD_data(glState, isCallValid, group, counter, pname, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetPerfMonitorCounterInfoAMD_data(glState, group, counter, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetPerfMonitorCounterInfoAMD, std::move(paramBuffer)); } @@ -184,38 +173,33 @@ CallCapture CaptureGetPerfMonitorCounterStringAMD(const State &glState, paramBuffer.addValueParam("counter", ParamType::TGLuint, counter); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetPerfMonitorCounterStringAMD_length(glState, isCallValid, group, counter, bufSize, - length, counterString, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetPerfMonitorCounterStringAMD_length(glState, group, counter, bufSize, length, + counterString, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture counterStringParam("counterString", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture counterStringParam("counterString", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, counterString, &counterStringParam.value); - CaptureGetPerfMonitorCounterStringAMD_counterString(glState, isCallValid, group, counter, - bufSize, length, counterString, - &counterStringParam); - paramBuffer.addParam(std::move(counterStringParam)); + CaptureGetPerfMonitorCounterStringAMD_counterString( + glState, group, counter, bufSize, length, counterString, &counterStringParam); } else { - ParamCapture counterStringParam("counterString", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &counterStringParam.value); - paramBuffer.addParam(std::move(counterStringParam)); } + paramBuffer.addParam(std::move(counterStringParam)); return CallCapture(angle::EntryPoint::GLGetPerfMonitorCounterStringAMD, std::move(paramBuffer)); } @@ -232,58 +216,50 @@ CallCapture CaptureGetPerfMonitorCountersAMD(const State &glState, paramBuffer.addValueParam("group", ParamType::TGLuint, group); + ParamCapture numCountersParam("numCounters", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture numCountersParam("numCounters", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, numCounters, &numCountersParam.value); - CaptureGetPerfMonitorCountersAMD_numCounters(glState, isCallValid, group, numCounters, - maxActiveCounters, counterSize, counters, - &numCountersParam); - paramBuffer.addParam(std::move(numCountersParam)); + CaptureGetPerfMonitorCountersAMD_numCounters(glState, group, numCounters, maxActiveCounters, + counterSize, counters, &numCountersParam); } else { - ParamCapture numCountersParam("numCounters", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &numCountersParam.value); - paramBuffer.addParam(std::move(numCountersParam)); } + paramBuffer.addParam(std::move(numCountersParam)); + ParamCapture maxActiveCountersParam("maxActiveCounters", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture maxActiveCountersParam("maxActiveCounters", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, maxActiveCounters, &maxActiveCountersParam.value); - CaptureGetPerfMonitorCountersAMD_maxActiveCounters(glState, isCallValid, group, numCounters, + CaptureGetPerfMonitorCountersAMD_maxActiveCounters(glState, group, numCounters, maxActiveCounters, counterSize, counters, &maxActiveCountersParam); - paramBuffer.addParam(std::move(maxActiveCountersParam)); } else { - ParamCapture maxActiveCountersParam("maxActiveCounters", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &maxActiveCountersParam.value); - paramBuffer.addParam(std::move(maxActiveCountersParam)); } + paramBuffer.addParam(std::move(maxActiveCountersParam)); paramBuffer.addValueParam("counterSize", ParamType::TGLsizei, counterSize); + ParamCapture countersParam("counters", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture countersParam("counters", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, counters, &countersParam.value); - CaptureGetPerfMonitorCountersAMD_counters(glState, isCallValid, group, numCounters, - maxActiveCounters, counterSize, counters, - &countersParam); - paramBuffer.addParam(std::move(countersParam)); + CaptureGetPerfMonitorCountersAMD_counters(glState, group, numCounters, maxActiveCounters, + counterSize, counters, &countersParam); } else { - ParamCapture countersParam("counters", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &countersParam.value); - paramBuffer.addParam(std::move(countersParam)); } + paramBuffer.addParam(std::move(countersParam)); return CallCapture(angle::EntryPoint::GLGetPerfMonitorCountersAMD, std::move(paramBuffer)); } @@ -300,37 +276,33 @@ CallCapture CaptureGetPerfMonitorGroupStringAMD(const State &glState, paramBuffer.addValueParam("group", ParamType::TGLuint, group); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetPerfMonitorGroupStringAMD_length(glState, isCallValid, group, bufSize, length, - groupString, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetPerfMonitorGroupStringAMD_length(glState, group, bufSize, length, groupString, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture groupStringParam("groupString", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture groupStringParam("groupString", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, groupString, &groupStringParam.value); - CaptureGetPerfMonitorGroupStringAMD_groupString(glState, isCallValid, group, bufSize, - length, groupString, &groupStringParam); - paramBuffer.addParam(std::move(groupStringParam)); + CaptureGetPerfMonitorGroupStringAMD_groupString(glState, group, bufSize, length, + groupString, &groupStringParam); } else { - ParamCapture groupStringParam("groupString", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &groupStringParam.value); - paramBuffer.addParam(std::move(groupStringParam)); } + paramBuffer.addParam(std::move(groupStringParam)); return CallCapture(angle::EntryPoint::GLGetPerfMonitorGroupStringAMD, std::move(paramBuffer)); } @@ -343,39 +315,34 @@ CallCapture CaptureGetPerfMonitorGroupsAMD(const State &glState, { ParamBuffer paramBuffer; + ParamCapture numGroupsParam("numGroups", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture numGroupsParam("numGroups", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, numGroups, &numGroupsParam.value); - CaptureGetPerfMonitorGroupsAMD_numGroups(glState, isCallValid, numGroups, groupsSize, - groups, &numGroupsParam); - paramBuffer.addParam(std::move(numGroupsParam)); + CaptureGetPerfMonitorGroupsAMD_numGroups(glState, numGroups, groupsSize, groups, + &numGroupsParam); } else { - ParamCapture numGroupsParam("numGroups", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &numGroupsParam.value); - paramBuffer.addParam(std::move(numGroupsParam)); } + paramBuffer.addParam(std::move(numGroupsParam)); paramBuffer.addValueParam("groupsSize", ParamType::TGLsizei, groupsSize); + ParamCapture groupsParam("groups", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture groupsParam("groups", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, groups, &groupsParam.value); - CaptureGetPerfMonitorGroupsAMD_groups(glState, isCallValid, numGroups, groupsSize, groups, - &groupsParam); - paramBuffer.addParam(std::move(groupsParam)); + CaptureGetPerfMonitorGroupsAMD_groups(glState, numGroups, groupsSize, groups, &groupsParam); } else { - ParamCapture groupsParam("groups", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &groupsParam.value); - paramBuffer.addParam(std::move(groupsParam)); } + paramBuffer.addParam(std::move(groupsParam)); return CallCapture(angle::EntryPoint::GLGetPerfMonitorGroupsAMD, std::move(paramBuffer)); } @@ -395,22 +362,19 @@ CallCapture CaptureSelectPerfMonitorCountersAMD(const State &glState, paramBuffer.addValueParam("group", ParamType::TGLuint, group); paramBuffer.addValueParam("numCounters", ParamType::TGLint, numCounters); + ParamCapture counterListParam("counterList", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture counterListParam("counterList", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, counterList, &counterListParam.value); - CaptureSelectPerfMonitorCountersAMD_counterList(glState, isCallValid, monitor, enable, - group, numCounters, counterList, - &counterListParam); - paramBuffer.addParam(std::move(counterListParam)); + CaptureSelectPerfMonitorCountersAMD_counterList( + glState, monitor, enable, group, numCounters, counterList, &counterListParam); } else { - ParamCapture counterListParam("counterList", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &counterListParam.value); - paramBuffer.addParam(std::move(counterListParam)); } + paramBuffer.addParam(std::move(counterListParam)); return CallCapture(angle::EntryPoint::GLSelectPerfMonitorCountersAMD, std::move(paramBuffer)); } @@ -451,22 +415,20 @@ CallCapture CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE(const State paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( - glState, isCallValid, modePacked, count, typePacked, indices, instanceCount, baseVertex, + glState, modePacked, count, typePacked, indices, instanceCount, baseVertex, baseInstance, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instanceCount", ParamType::TGLsizei, instanceCount); paramBuffer.addValueParam("baseVertex", ParamType::TGLint, baseVertex); @@ -489,73 +451,65 @@ CallCapture CaptureMultiDrawArraysInstancedBaseInstanceANGLE(const State &glStat paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, firsts, &firstsParam.value); - CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts( - glState, isCallValid, modePacked, firsts, counts, instanceCounts, baseInstances, - drawcount, &firstsParam); - paramBuffer.addParam(std::move(firstsParam)); + CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts(glState, modePacked, firsts, counts, + instanceCounts, baseInstances, + drawcount, &firstsParam); } else { - ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &firstsParam.value); - paramBuffer.addParam(std::move(firstsParam)); } + paramBuffer.addParam(std::move(firstsParam)); + ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, counts, &countsParam.value); - CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts( - glState, isCallValid, modePacked, firsts, counts, instanceCounts, baseInstances, - drawcount, &countsParam); - paramBuffer.addParam(std::move(countsParam)); + CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts(glState, modePacked, firsts, counts, + instanceCounts, baseInstances, + drawcount, &countsParam); } else { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countsParam.value); - paramBuffer.addParam(std::move(countsParam)); } + paramBuffer.addParam(std::move(countsParam)); + ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, instanceCounts, &instanceCountsParam.value); CaptureMultiDrawArraysInstancedBaseInstanceANGLE_instanceCounts( - glState, isCallValid, modePacked, firsts, counts, instanceCounts, baseInstances, - drawcount, &instanceCountsParam); - paramBuffer.addParam(std::move(instanceCountsParam)); + glState, modePacked, firsts, counts, instanceCounts, baseInstances, drawcount, + &instanceCountsParam); } else { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &instanceCountsParam.value); - paramBuffer.addParam(std::move(instanceCountsParam)); } + paramBuffer.addParam(std::move(instanceCountsParam)); + ParamCapture baseInstancesParam("baseInstances", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture baseInstancesParam("baseInstances", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, baseInstances, &baseInstancesParam.value); CaptureMultiDrawArraysInstancedBaseInstanceANGLE_baseInstances( - glState, isCallValid, modePacked, firsts, counts, instanceCounts, baseInstances, - drawcount, &baseInstancesParam); - paramBuffer.addParam(std::move(baseInstancesParam)); + glState, modePacked, firsts, counts, instanceCounts, baseInstances, drawcount, + &baseInstancesParam); } else { - ParamCapture baseInstancesParam("baseInstances", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &baseInstancesParam.value); - paramBuffer.addParam(std::move(baseInstancesParam)); } + paramBuffer.addParam(std::move(baseInstancesParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); @@ -579,92 +533,82 @@ CallCapture CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE( paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, counts, &countsParam.value); CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_counts( - glState, isCallValid, modePacked, counts, typePacked, indices, instanceCounts, - baseVertices, baseInstances, drawcount, &countsParam); - paramBuffer.addParam(std::move(countsParam)); + glState, modePacked, counts, typePacked, indices, instanceCounts, baseVertices, + baseInstances, drawcount, &countsParam); } else { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countsParam.value); - paramBuffer.addParam(std::move(countsParam)); } + paramBuffer.addParam(std::move(countsParam)); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, indices, &indicesParam.value); CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( - glState, isCallValid, modePacked, counts, typePacked, indices, instanceCounts, - baseVertices, baseInstances, drawcount, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + glState, modePacked, counts, typePacked, indices, instanceCounts, baseVertices, + baseInstances, drawcount, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); + ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, instanceCounts, &instanceCountsParam.value); CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_instanceCounts( - glState, isCallValid, modePacked, counts, typePacked, indices, instanceCounts, - baseVertices, baseInstances, drawcount, &instanceCountsParam); - paramBuffer.addParam(std::move(instanceCountsParam)); + glState, modePacked, counts, typePacked, indices, instanceCounts, baseVertices, + baseInstances, drawcount, &instanceCountsParam); } else { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &instanceCountsParam.value); - paramBuffer.addParam(std::move(instanceCountsParam)); } + paramBuffer.addParam(std::move(instanceCountsParam)); + ParamCapture baseVerticesParam("baseVertices", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture baseVerticesParam("baseVertices", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, baseVertices, &baseVerticesParam.value); CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseVertices( - glState, isCallValid, modePacked, counts, typePacked, indices, instanceCounts, - baseVertices, baseInstances, drawcount, &baseVerticesParam); - paramBuffer.addParam(std::move(baseVerticesParam)); + glState, modePacked, counts, typePacked, indices, instanceCounts, baseVertices, + baseInstances, drawcount, &baseVerticesParam); } else { - ParamCapture baseVerticesParam("baseVertices", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &baseVerticesParam.value); - paramBuffer.addParam(std::move(baseVerticesParam)); } + paramBuffer.addParam(std::move(baseVerticesParam)); + ParamCapture baseInstancesParam("baseInstances", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture baseInstancesParam("baseInstances", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, baseInstances, &baseInstancesParam.value); CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseInstances( - glState, isCallValid, modePacked, counts, typePacked, indices, instanceCounts, - baseVertices, baseInstances, drawcount, &baseInstancesParam); - paramBuffer.addParam(std::move(baseInstancesParam)); + glState, modePacked, counts, typePacked, indices, instanceCounts, baseVertices, + baseInstances, drawcount, &baseInstancesParam); } else { - ParamCapture baseInstancesParam("baseInstances", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &baseInstancesParam.value); - paramBuffer.addParam(std::move(baseInstancesParam)); } + paramBuffer.addParam(std::move(baseInstancesParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); @@ -683,21 +627,18 @@ CallCapture CaptureBlobCacheCallbacksANGLE(const State &glState, paramBuffer.addValueParam("set", ParamType::TGLSETBLOBPROCANGLE, set); paramBuffer.addValueParam("get", ParamType::TGLGETBLOBPROCANGLE, get); + ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, userParam, &userParamParam.value); - CaptureBlobCacheCallbacksANGLE_userParam(glState, isCallValid, set, get, userParam, - &userParamParam); - paramBuffer.addParam(std::move(userParamParam)); + CaptureBlobCacheCallbacksANGLE_userParam(glState, set, get, userParam, &userParamParam); } else { - ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &userParamParam.value); - paramBuffer.addParam(std::move(userParamParam)); } + paramBuffer.addParam(std::move(userParamParam)); return CallCapture(angle::EntryPoint::GLBlobCacheCallbacksANGLE, std::move(paramBuffer)); } @@ -711,20 +652,18 @@ CallCapture CaptureGetPointervANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetPointervANGLE_params(glState, isCallValid, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetPointervANGLE_params(glState, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetPointervANGLE, std::move(paramBuffer)); } @@ -870,20 +809,18 @@ CallCapture CaptureGetTexImageANGLE(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, pixels, &pixelsParam.value); - CaptureGetTexImageANGLE_pixels(glState, isCallValid, targetPacked, level, format, type, - pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureGetTexImageANGLE_pixels(glState, targetPacked, level, format, type, pixels, + &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLGetTexImageANGLE, std::move(paramBuffer)); } @@ -899,20 +836,18 @@ CallCapture CaptureGetCompressedTexImageANGLE(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureTarget, targetPacked); paramBuffer.addValueParam("level", ParamType::TGLint, level); + ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, pixels, &pixelsParam.value); - CaptureGetCompressedTexImageANGLE_pixels(glState, isCallValid, targetPacked, level, pixels, + CaptureGetCompressedTexImageANGLE_pixels(glState, targetPacked, level, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLGetCompressedTexImageANGLE, std::move(paramBuffer)); } @@ -930,20 +865,18 @@ CallCapture CaptureGetRenderbufferImageANGLE(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, pixels, &pixelsParam.value); - CaptureGetRenderbufferImageANGLE_pixels(glState, isCallValid, target, format, type, pixels, + CaptureGetRenderbufferImageANGLE_pixels(glState, target, format, type, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLGetRenderbufferImageANGLE, std::move(paramBuffer)); } @@ -961,20 +894,18 @@ CallCapture CaptureGetTexLevelParameterivANGLE(const State &glState, paramBuffer.addValueParam("level", ParamType::TGLint, level); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexLevelParameterivANGLE_params(glState, isCallValid, targetPacked, level, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexLevelParameterivANGLE_params(glState, targetPacked, level, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexLevelParameterivANGLE, std::move(paramBuffer)); } @@ -992,21 +923,19 @@ CallCapture CaptureGetTexLevelParameterfvANGLE(const State &glState, paramBuffer.addValueParam("level", ParamType::TGLint, level); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexLevelParameterfvANGLE_params(glState, isCallValid, targetPacked, level, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexLevelParameterfvANGLE_params(glState, targetPacked, level, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexLevelParameterfvANGLE, std::move(paramBuffer)); } @@ -1042,21 +971,19 @@ CallCapture CaptureDrawElementsInstancedANGLE(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstancedANGLE_indices(glState, isCallValid, modePacked, count, - typePacked, indices, primcount, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstancedANGLE_indices(glState, modePacked, count, typePacked, indices, + primcount, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("primcount", ParamType::TGLsizei, primcount); @@ -1114,25 +1041,21 @@ CallCapture CaptureTexStorageMemFlags2DANGLE(const State &glState, createFlags); paramBuffer.addEnumParam("usageFlags", GLESEnum::AllEnums, ParamType::TGLbitfield, usageFlags); + ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, imageCreateInfoPNext, &imageCreateInfoPNextParam.value); CaptureTexStorageMemFlags2DANGLE_imageCreateInfoPNext( - glState, isCallValid, targetPacked, levels, internalFormat, width, height, memoryPacked, - offset, createFlags, usageFlags, imageCreateInfoPNext, &imageCreateInfoPNextParam); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); + glState, targetPacked, levels, internalFormat, width, height, memoryPacked, offset, + createFlags, usageFlags, imageCreateInfoPNext, &imageCreateInfoPNextParam); } else { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &imageCreateInfoPNextParam.value); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); } + paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); return CallCapture(angle::EntryPoint::GLTexStorageMemFlags2DANGLE, std::move(paramBuffer)); } @@ -1166,26 +1089,22 @@ CallCapture CaptureTexStorageMemFlags2DMultisampleANGLE(const State &glState, createFlags); paramBuffer.addEnumParam("usageFlags", GLESEnum::AllEnums, ParamType::TGLbitfield, usageFlags); + ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, imageCreateInfoPNext, &imageCreateInfoPNextParam.value); CaptureTexStorageMemFlags2DMultisampleANGLE_imageCreateInfoPNext( - glState, isCallValid, targetPacked, samples, internalFormat, width, height, - fixedSampleLocations, memoryPacked, offset, createFlags, usageFlags, - imageCreateInfoPNext, &imageCreateInfoPNextParam); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); + glState, targetPacked, samples, internalFormat, width, height, fixedSampleLocations, + memoryPacked, offset, createFlags, usageFlags, imageCreateInfoPNext, + &imageCreateInfoPNextParam); } else { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &imageCreateInfoPNextParam.value); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); } + paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); return CallCapture(angle::EntryPoint::GLTexStorageMemFlags2DMultisampleANGLE, std::move(paramBuffer)); @@ -1220,26 +1139,21 @@ CallCapture CaptureTexStorageMemFlags3DANGLE(const State &glState, createFlags); paramBuffer.addEnumParam("usageFlags", GLESEnum::AllEnums, ParamType::TGLbitfield, usageFlags); + ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, imageCreateInfoPNext, &imageCreateInfoPNextParam.value); CaptureTexStorageMemFlags3DANGLE_imageCreateInfoPNext( - glState, isCallValid, targetPacked, levels, internalFormat, width, height, depth, - memoryPacked, offset, createFlags, usageFlags, imageCreateInfoPNext, - &imageCreateInfoPNextParam); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); + glState, targetPacked, levels, internalFormat, width, height, depth, memoryPacked, + offset, createFlags, usageFlags, imageCreateInfoPNext, &imageCreateInfoPNextParam); } else { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &imageCreateInfoPNextParam.value); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); } + paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); return CallCapture(angle::EntryPoint::GLTexStorageMemFlags3DANGLE, std::move(paramBuffer)); } @@ -1275,26 +1189,22 @@ CallCapture CaptureTexStorageMemFlags3DMultisampleANGLE(const State &glState, createFlags); paramBuffer.addEnumParam("usageFlags", GLESEnum::AllEnums, ParamType::TGLbitfield, usageFlags); + ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, imageCreateInfoPNext, &imageCreateInfoPNextParam.value); CaptureTexStorageMemFlags3DMultisampleANGLE_imageCreateInfoPNext( - glState, isCallValid, targetPacked, samples, internalFormat, width, height, depth, + glState, targetPacked, samples, internalFormat, width, height, depth, fixedSampleLocations, memoryPacked, offset, createFlags, usageFlags, imageCreateInfoPNext, &imageCreateInfoPNextParam); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); } else { - ParamCapture imageCreateInfoPNextParam("imageCreateInfoPNext", - ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &imageCreateInfoPNextParam.value); - paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); } + paramBuffer.addParam(std::move(imageCreateInfoPNextParam)); return CallCapture(angle::EntryPoint::GLTexStorageMemFlags3DMultisampleANGLE, std::move(paramBuffer)); @@ -1328,37 +1238,33 @@ CallCapture CaptureMultiDrawArraysANGLE(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, firsts, &firstsParam.value); - CaptureMultiDrawArraysANGLE_firsts(glState, isCallValid, modePacked, firsts, counts, - drawcount, &firstsParam); - paramBuffer.addParam(std::move(firstsParam)); + CaptureMultiDrawArraysANGLE_firsts(glState, modePacked, firsts, counts, drawcount, + &firstsParam); } else { - ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &firstsParam.value); - paramBuffer.addParam(std::move(firstsParam)); } + paramBuffer.addParam(std::move(firstsParam)); + ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, counts, &countsParam.value); - CaptureMultiDrawArraysANGLE_counts(glState, isCallValid, modePacked, firsts, counts, - drawcount, &countsParam); - paramBuffer.addParam(std::move(countsParam)); + CaptureMultiDrawArraysANGLE_counts(glState, modePacked, firsts, counts, drawcount, + &countsParam); } else { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countsParam.value); - paramBuffer.addParam(std::move(countsParam)); } + paramBuffer.addParam(std::move(countsParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); @@ -1377,56 +1283,47 @@ CallCapture CaptureMultiDrawArraysInstancedANGLE(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, firsts, &firstsParam.value); - CaptureMultiDrawArraysInstancedANGLE_firsts(glState, isCallValid, modePacked, firsts, - counts, instanceCounts, drawcount, - &firstsParam); - paramBuffer.addParam(std::move(firstsParam)); + CaptureMultiDrawArraysInstancedANGLE_firsts(glState, modePacked, firsts, counts, + instanceCounts, drawcount, &firstsParam); } else { - ParamCapture firstsParam("firsts", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &firstsParam.value); - paramBuffer.addParam(std::move(firstsParam)); } + paramBuffer.addParam(std::move(firstsParam)); + ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, counts, &countsParam.value); - CaptureMultiDrawArraysInstancedANGLE_counts(glState, isCallValid, modePacked, firsts, - counts, instanceCounts, drawcount, - &countsParam); - paramBuffer.addParam(std::move(countsParam)); + CaptureMultiDrawArraysInstancedANGLE_counts(glState, modePacked, firsts, counts, + instanceCounts, drawcount, &countsParam); } else { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countsParam.value); - paramBuffer.addParam(std::move(countsParam)); } + paramBuffer.addParam(std::move(countsParam)); + ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, instanceCounts, &instanceCountsParam.value); - CaptureMultiDrawArraysInstancedANGLE_instanceCounts(glState, isCallValid, modePacked, - firsts, counts, instanceCounts, - drawcount, &instanceCountsParam); - paramBuffer.addParam(std::move(instanceCountsParam)); + CaptureMultiDrawArraysInstancedANGLE_instanceCounts( + glState, modePacked, firsts, counts, instanceCounts, drawcount, &instanceCountsParam); } else { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &instanceCountsParam.value); - paramBuffer.addParam(std::move(instanceCountsParam)); } + paramBuffer.addParam(std::move(instanceCountsParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); @@ -1445,39 +1342,35 @@ CallCapture CaptureMultiDrawElementsANGLE(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, counts, &countsParam.value); - CaptureMultiDrawElementsANGLE_counts(glState, isCallValid, modePacked, counts, typePacked, - indices, drawcount, &countsParam); - paramBuffer.addParam(std::move(countsParam)); + CaptureMultiDrawElementsANGLE_counts(glState, modePacked, counts, typePacked, indices, + drawcount, &countsParam); } else { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countsParam.value); - paramBuffer.addParam(std::move(countsParam)); } + paramBuffer.addParam(std::move(countsParam)); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, indices, &indicesParam.value); - CaptureMultiDrawElementsANGLE_indices(glState, isCallValid, modePacked, counts, typePacked, - indices, drawcount, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureMultiDrawElementsANGLE_indices(glState, modePacked, counts, typePacked, indices, + drawcount, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); @@ -1497,58 +1390,52 @@ CallCapture CaptureMultiDrawElementsInstancedANGLE(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, counts, &countsParam.value); - CaptureMultiDrawElementsInstancedANGLE_counts(glState, isCallValid, modePacked, counts, - typePacked, indices, instanceCounts, - drawcount, &countsParam); - paramBuffer.addParam(std::move(countsParam)); + CaptureMultiDrawElementsInstancedANGLE_counts(glState, modePacked, counts, typePacked, + indices, instanceCounts, drawcount, + &countsParam); } else { - ParamCapture countsParam("counts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countsParam.value); - paramBuffer.addParam(std::move(countsParam)); } + paramBuffer.addParam(std::move(countsParam)); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, indices, &indicesParam.value); - CaptureMultiDrawElementsInstancedANGLE_indices(glState, isCallValid, modePacked, counts, - typePacked, indices, instanceCounts, - drawcount, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureMultiDrawElementsInstancedANGLE_indices(glState, modePacked, counts, typePacked, + indices, instanceCounts, drawcount, + &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); + ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, instanceCounts, &instanceCountsParam.value); - CaptureMultiDrawElementsInstancedANGLE_instanceCounts( - glState, isCallValid, modePacked, counts, typePacked, indices, instanceCounts, - drawcount, &instanceCountsParam); - paramBuffer.addParam(std::move(instanceCountsParam)); + CaptureMultiDrawElementsInstancedANGLE_instanceCounts(glState, modePacked, counts, + typePacked, indices, instanceCounts, + drawcount, &instanceCountsParam); } else { - ParamCapture instanceCountsParam("instanceCounts", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &instanceCountsParam.value); - paramBuffer.addParam(std::move(instanceCountsParam)); } + paramBuffer.addParam(std::move(instanceCountsParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); @@ -1585,20 +1472,18 @@ CallCapture CaptureRequestExtensionANGLE(const State &glState, bool isCallValid, { ParamBuffer paramBuffer; + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureRequestExtensionANGLE_name(glState, isCallValid, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureRequestExtensionANGLE_name(glState, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLRequestExtensionANGLE, std::move(paramBuffer)); } @@ -1607,20 +1492,18 @@ CallCapture CaptureDisableExtensionANGLE(const State &glState, bool isCallValid, { ParamBuffer paramBuffer; + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureDisableExtensionANGLE_name(glState, isCallValid, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureDisableExtensionANGLE_name(glState, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLDisableExtensionANGLE, std::move(paramBuffer)); } @@ -1637,37 +1520,31 @@ CallCapture CaptureGetBooleanvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetBooleanvRobustANGLE_length(glState, isCallValid, pname, bufSize, length, params, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetBooleanvRobustANGLE_length(glState, pname, bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLbooleanPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, params, ¶msParam.value); - CaptureGetBooleanvRobustANGLE_params(glState, isCallValid, pname, bufSize, length, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBooleanvRobustANGLE_params(glState, pname, bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBooleanvRobustANGLE, std::move(paramBuffer)); } @@ -1686,36 +1563,32 @@ CallCapture CaptureGetBufferParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetBufferParameterivRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetBufferParameterivRobustANGLE_length(glState, targetPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetBufferParameterivRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferParameterivRobustANGLE_params(glState, targetPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferParameterivRobustANGLE, std::move(paramBuffer)); @@ -1733,37 +1606,31 @@ CallCapture CaptureGetFloatvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetFloatvRobustANGLE_length(glState, isCallValid, pname, bufSize, length, params, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetFloatvRobustANGLE_length(glState, pname, bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetFloatvRobustANGLE_params(glState, isCallValid, pname, bufSize, length, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFloatvRobustANGLE_params(glState, pname, bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFloatvRobustANGLE, std::move(paramBuffer)); } @@ -1784,36 +1651,32 @@ CallCapture CaptureGetFramebufferAttachmentParameterivRobustANGLE(const State &g paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); CaptureGetFramebufferAttachmentParameterivRobustANGLE_length( - glState, isCallValid, target, attachment, pname, bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + glState, target, attachment, pname, bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); CaptureGetFramebufferAttachmentParameterivRobustANGLE_params( - glState, isCallValid, target, attachment, pname, bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + glState, target, attachment, pname, bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferAttachmentParameterivRobustANGLE, std::move(paramBuffer)); @@ -1831,36 +1694,30 @@ CallCapture CaptureGetIntegervRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetIntegervRobustANGLE_length(glState, isCallValid, pname, bufSize, length, data, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetIntegervRobustANGLE_length(glState, pname, bufSize, length, data, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture dataParam("data", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, data, &dataParam.value); - CaptureGetIntegervRobustANGLE_data(glState, isCallValid, pname, bufSize, length, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetIntegervRobustANGLE_data(glState, pname, bufSize, length, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetIntegervRobustANGLE, std::move(paramBuffer)); } @@ -1879,36 +1736,32 @@ CallCapture CaptureGetProgramivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramivRobustANGLE_length(glState, isCallValid, programPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramivRobustANGLE_length(glState, programPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramivRobustANGLE_params(glState, isCallValid, programPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramivRobustANGLE_params(glState, programPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramivRobustANGLE, std::move(paramBuffer)); } @@ -1927,36 +1780,32 @@ CallCapture CaptureGetRenderbufferParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetRenderbufferParameterivRobustANGLE_length(glState, isCallValid, target, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetRenderbufferParameterivRobustANGLE_length(glState, target, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetRenderbufferParameterivRobustANGLE_params(glState, isCallValid, target, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetRenderbufferParameterivRobustANGLE_params(glState, target, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetRenderbufferParameterivRobustANGLE, std::move(paramBuffer)); @@ -1976,36 +1825,32 @@ CallCapture CaptureGetShaderivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetShaderivRobustANGLE_length(glState, isCallValid, shaderPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetShaderivRobustANGLE_length(glState, shaderPacked, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetShaderivRobustANGLE_params(glState, isCallValid, shaderPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetShaderivRobustANGLE_params(glState, shaderPacked, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetShaderivRobustANGLE, std::move(paramBuffer)); } @@ -2024,37 +1869,33 @@ CallCapture CaptureGetTexParameterfvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTexParameterfvRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTexParameterfvRobustANGLE_length(glState, targetPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexParameterfvRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterfvRobustANGLE_params(glState, targetPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterfvRobustANGLE, std::move(paramBuffer)); } @@ -2073,36 +1914,32 @@ CallCapture CaptureGetTexParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTexParameterivRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTexParameterivRobustANGLE_length(glState, targetPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexParameterivRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterivRobustANGLE_params(glState, targetPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterivRobustANGLE, std::move(paramBuffer)); } @@ -2121,37 +1958,33 @@ CallCapture CaptureGetUniformfvRobustANGLE(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetUniformfvRobustANGLE_length(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetUniformfvRobustANGLE_length(glState, programPacked, locationPacked, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetUniformfvRobustANGLE_params(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetUniformfvRobustANGLE_params(glState, programPacked, locationPacked, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetUniformfvRobustANGLE, std::move(paramBuffer)); } @@ -2170,36 +2003,32 @@ CallCapture CaptureGetUniformivRobustANGLE(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetUniformivRobustANGLE_length(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetUniformivRobustANGLE_length(glState, programPacked, locationPacked, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetUniformivRobustANGLE_params(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetUniformivRobustANGLE_params(glState, programPacked, locationPacked, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetUniformivRobustANGLE, std::move(paramBuffer)); } @@ -2218,37 +2047,33 @@ CallCapture CaptureGetVertexAttribfvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetVertexAttribfvRobustANGLE_length(glState, isCallValid, index, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetVertexAttribfvRobustANGLE_length(glState, index, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetVertexAttribfvRobustANGLE_params(glState, isCallValid, index, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribfvRobustANGLE_params(glState, index, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribfvRobustANGLE, std::move(paramBuffer)); } @@ -2267,36 +2092,32 @@ CallCapture CaptureGetVertexAttribivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetVertexAttribivRobustANGLE_length(glState, isCallValid, index, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetVertexAttribivRobustANGLE_length(glState, index, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetVertexAttribivRobustANGLE_params(glState, isCallValid, index, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribivRobustANGLE_params(glState, index, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribivRobustANGLE, std::move(paramBuffer)); } @@ -2315,37 +2136,33 @@ CallCapture CaptureGetVertexAttribPointervRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetVertexAttribPointervRobustANGLE_length(glState, isCallValid, index, pname, - bufSize, length, pointer, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetVertexAttribPointervRobustANGLE_length(glState, index, pname, bufSize, length, + pointer, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture pointerParam("pointer", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, pointer, &pointerParam.value); - CaptureGetVertexAttribPointervRobustANGLE_pointer(glState, isCallValid, index, pname, - bufSize, length, pointer, &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureGetVertexAttribPointervRobustANGLE_pointer(glState, index, pname, bufSize, length, + pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribPointervRobustANGLE, std::move(paramBuffer)); @@ -2375,69 +2192,60 @@ CallCapture CaptureReadPixelsRobustANGLE(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureReadPixelsRobustANGLE_length(glState, isCallValid, x, y, width, height, format, type, - bufSize, length, columns, rows, pixels, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureReadPixelsRobustANGLE_length(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, pixels, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture columnsParam("columns", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture columnsParam("columns", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, columns, &columnsParam.value); - CaptureReadPixelsRobustANGLE_columns(glState, isCallValid, x, y, width, height, format, - type, bufSize, length, columns, rows, pixels, - &columnsParam); - paramBuffer.addParam(std::move(columnsParam)); + CaptureReadPixelsRobustANGLE_columns(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, pixels, &columnsParam); } else { - ParamCapture columnsParam("columns", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &columnsParam.value); - paramBuffer.addParam(std::move(columnsParam)); } + paramBuffer.addParam(std::move(columnsParam)); + ParamCapture rowsParam("rows", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture rowsParam("rows", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, rows, &rowsParam.value); - CaptureReadPixelsRobustANGLE_rows(glState, isCallValid, x, y, width, height, format, type, - bufSize, length, columns, rows, pixels, &rowsParam); - paramBuffer.addParam(std::move(rowsParam)); + CaptureReadPixelsRobustANGLE_rows(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, pixels, &rowsParam); } else { - ParamCapture rowsParam("rows", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &rowsParam.value); - paramBuffer.addParam(std::move(rowsParam)); } + paramBuffer.addParam(std::move(rowsParam)); + ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, pixels, &pixelsParam.value); - CaptureReadPixelsRobustANGLE_pixels(glState, isCallValid, x, y, width, height, format, type, - bufSize, length, columns, rows, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureReadPixelsRobustANGLE_pixels(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLReadPixelsRobustANGLE, std::move(paramBuffer)); } @@ -2467,22 +2275,20 @@ CallCapture CaptureTexImage2DRobustANGLE(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexImage2DRobustANGLE_pixels(glState, isCallValid, targetPacked, level, - internalformat, width, height, border, format, type, - bufSize, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexImage2DRobustANGLE_pixels(glState, targetPacked, level, internalformat, width, + height, border, format, type, bufSize, pixels, + &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexImage2DRobustANGLE, std::move(paramBuffer)); } @@ -2500,21 +2306,19 @@ CallCapture CaptureTexParameterfvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureTexParameterfvRobustANGLE_params(glState, isCallValid, targetPacked, pname, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterfvRobustANGLE_params(glState, targetPacked, pname, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterfvRobustANGLE, std::move(paramBuffer)); } @@ -2532,21 +2336,19 @@ CallCapture CaptureTexParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexParameterivRobustANGLE_params(glState, isCallValid, targetPacked, pname, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterivRobustANGLE_params(glState, targetPacked, pname, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterivRobustANGLE, std::move(paramBuffer)); } @@ -2576,22 +2378,20 @@ CallCapture CaptureTexSubImage2DRobustANGLE(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexSubImage2DRobustANGLE_pixels(glState, isCallValid, targetPacked, level, xoffset, - yoffset, width, height, format, type, bufSize, - pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexSubImage2DRobustANGLE_pixels(glState, targetPacked, level, xoffset, yoffset, + width, height, format, type, bufSize, pixels, + &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexSubImage2DRobustANGLE, std::move(paramBuffer)); } @@ -2623,22 +2423,20 @@ CallCapture CaptureTexImage3DRobustANGLE(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexImage3DRobustANGLE_pixels(glState, isCallValid, targetPacked, level, - internalformat, width, height, depth, border, format, - type, bufSize, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexImage3DRobustANGLE_pixels(glState, targetPacked, level, internalformat, width, + height, depth, border, format, type, bufSize, pixels, + &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexImage3DRobustANGLE, std::move(paramBuffer)); } @@ -2672,22 +2470,20 @@ CallCapture CaptureTexSubImage3DRobustANGLE(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexSubImage3DRobustANGLE_pixels(glState, isCallValid, targetPacked, level, xoffset, - yoffset, zoffset, width, height, depth, format, type, - bufSize, pixels, &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexSubImage3DRobustANGLE_pixels(glState, targetPacked, level, xoffset, yoffset, + zoffset, width, height, depth, format, type, bufSize, + pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexSubImage3DRobustANGLE, std::move(paramBuffer)); } @@ -2716,22 +2512,20 @@ CallCapture CaptureCompressedTexImage2DRobustANGLE(const State &glState, paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); paramBuffer.addValueParam("dataSize", ParamType::TGLsizei, dataSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexImage2DRobustANGLE_data(glState, isCallValid, targetPacked, level, - internalformat, width, height, border, - imageSize, dataSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexImage2DRobustANGLE_data(glState, targetPacked, level, internalformat, + width, height, border, imageSize, dataSize, + data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexImage2DRobustANGLE, std::move(paramBuffer)); @@ -2762,22 +2556,20 @@ CallCapture CaptureCompressedTexSubImage2DRobustANGLE(const State &glState, paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); paramBuffer.addValueParam("dataSize", ParamType::TGLsizei, dataSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexSubImage2DRobustANGLE_data(glState, isCallValid, targetPacked, level, - xoffset, yoffset, width, height, format, - imageSize, dataSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexSubImage2DRobustANGLE_data(glState, targetPacked, level, xoffset, + yoffset, width, height, format, imageSize, + dataSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexSubImage2DRobustANGLE, std::move(paramBuffer)); @@ -2809,22 +2601,20 @@ CallCapture CaptureCompressedTexImage3DRobustANGLE(const State &glState, paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); paramBuffer.addValueParam("dataSize", ParamType::TGLsizei, dataSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexImage3DRobustANGLE_data(glState, isCallValid, targetPacked, level, - internalformat, width, height, depth, border, - imageSize, dataSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexImage3DRobustANGLE_data(glState, targetPacked, level, internalformat, + width, height, depth, border, imageSize, + dataSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexImage3DRobustANGLE, std::move(paramBuffer)); @@ -2859,22 +2649,20 @@ CallCapture CaptureCompressedTexSubImage3DRobustANGLE(const State &glState, paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); paramBuffer.addValueParam("dataSize", ParamType::TGLsizei, dataSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); CaptureCompressedTexSubImage3DRobustANGLE_data( - glState, isCallValid, targetPacked, level, xoffset, yoffset, zoffset, width, height, - depth, format, imageSize, dataSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + glState, targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, + imageSize, dataSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexSubImage3DRobustANGLE, std::move(paramBuffer)); @@ -2894,36 +2682,32 @@ CallCapture CaptureGetQueryivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetQueryivRobustANGLE_length(glState, isCallValid, targetPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetQueryivRobustANGLE_length(glState, targetPacked, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetQueryivRobustANGLE_params(glState, isCallValid, targetPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryivRobustANGLE_params(glState, targetPacked, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryivRobustANGLE, std::move(paramBuffer)); } @@ -2942,37 +2726,33 @@ CallCapture CaptureGetQueryObjectuivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetQueryObjectuivRobustANGLE_length(glState, isCallValid, idPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetQueryObjectuivRobustANGLE_length(glState, idPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetQueryObjectuivRobustANGLE_params(glState, isCallValid, idPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectuivRobustANGLE_params(glState, idPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectuivRobustANGLE, std::move(paramBuffer)); } @@ -2991,37 +2771,33 @@ CallCapture CaptureGetBufferPointervRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetBufferPointervRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetBufferPointervRobustANGLE_length(glState, targetPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetBufferPointervRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferPointervRobustANGLE_params(glState, targetPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferPointervRobustANGLE, std::move(paramBuffer)); } @@ -3040,36 +2816,32 @@ CallCapture CaptureGetIntegeri_vRobustANGLE(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetIntegeri_vRobustANGLE_length(glState, isCallValid, target, index, bufSize, length, - data, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetIntegeri_vRobustANGLE_length(glState, target, index, bufSize, length, data, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture dataParam("data", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, data, &dataParam.value); - CaptureGetIntegeri_vRobustANGLE_data(glState, isCallValid, target, index, bufSize, length, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetIntegeri_vRobustANGLE_data(glState, target, index, bufSize, length, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetIntegeri_vRobustANGLE, std::move(paramBuffer)); } @@ -3091,36 +2863,32 @@ CallCapture CaptureGetInternalformativRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetInternalformativRobustANGLE_length(glState, isCallValid, target, internalformat, - pname, bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetInternalformativRobustANGLE_length(glState, target, internalformat, pname, + bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetInternalformativRobustANGLE_params(glState, isCallValid, target, internalformat, - pname, bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetInternalformativRobustANGLE_params(glState, target, internalformat, pname, + bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetInternalformativRobustANGLE, std::move(paramBuffer)); } @@ -3139,36 +2907,32 @@ CallCapture CaptureGetVertexAttribIivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetVertexAttribIivRobustANGLE_length(glState, isCallValid, index, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetVertexAttribIivRobustANGLE_length(glState, index, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetVertexAttribIivRobustANGLE_params(glState, isCallValid, index, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribIivRobustANGLE_params(glState, index, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribIivRobustANGLE, std::move(paramBuffer)); } @@ -3187,37 +2951,33 @@ CallCapture CaptureGetVertexAttribIuivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetVertexAttribIuivRobustANGLE_length(glState, isCallValid, index, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetVertexAttribIuivRobustANGLE_length(glState, index, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetVertexAttribIuivRobustANGLE_params(glState, isCallValid, index, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetVertexAttribIuivRobustANGLE_params(glState, index, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetVertexAttribIuivRobustANGLE, std::move(paramBuffer)); } @@ -3236,37 +2996,33 @@ CallCapture CaptureGetUniformuivRobustANGLE(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetUniformuivRobustANGLE_length(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetUniformuivRobustANGLE_length(glState, programPacked, locationPacked, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetUniformuivRobustANGLE_params(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetUniformuivRobustANGLE_params(glState, programPacked, locationPacked, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetUniformuivRobustANGLE, std::move(paramBuffer)); } @@ -3288,38 +3044,34 @@ CallCapture CaptureGetActiveUniformBlockivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetActiveUniformBlockivRobustANGLE_length(glState, isCallValid, programPacked, + CaptureGetActiveUniformBlockivRobustANGLE_length(glState, programPacked, uniformBlockIndexPacked, pname, bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetActiveUniformBlockivRobustANGLE_params(glState, isCallValid, programPacked, + CaptureGetActiveUniformBlockivRobustANGLE_params(glState, programPacked, uniformBlockIndexPacked, pname, bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetActiveUniformBlockivRobustANGLE, std::move(paramBuffer)); @@ -3337,37 +3089,31 @@ CallCapture CaptureGetInteger64vRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetInteger64vRobustANGLE_length(glState, isCallValid, pname, bufSize, length, data, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetInteger64vRobustANGLE_length(glState, pname, bufSize, length, data, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture dataParam("data", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, data, &dataParam.value); - CaptureGetInteger64vRobustANGLE_data(glState, isCallValid, pname, bufSize, length, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetInteger64vRobustANGLE_data(glState, pname, bufSize, length, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetInteger64vRobustANGLE, std::move(paramBuffer)); } @@ -3386,37 +3132,33 @@ CallCapture CaptureGetInteger64i_vRobustANGLE(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetInteger64i_vRobustANGLE_length(glState, isCallValid, target, index, bufSize, - length, data, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetInteger64i_vRobustANGLE_length(glState, target, index, bufSize, length, data, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture dataParam("data", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, data, &dataParam.value); - CaptureGetInteger64i_vRobustANGLE_data(glState, isCallValid, target, index, bufSize, length, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetInteger64i_vRobustANGLE_data(glState, target, index, bufSize, length, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetInteger64i_vRobustANGLE, std::move(paramBuffer)); } @@ -3435,37 +3177,33 @@ CallCapture CaptureGetBufferParameteri64vRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetBufferParameteri64vRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetBufferParameteri64vRobustANGLE_length(glState, targetPacked, pname, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, params, ¶msParam.value); - CaptureGetBufferParameteri64vRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferParameteri64vRobustANGLE_params(glState, targetPacked, pname, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferParameteri64vRobustANGLE, std::move(paramBuffer)); @@ -3484,21 +3222,19 @@ CallCapture CaptureSamplerParameterivRobustANGLE(const State &glState, paramBuffer.addValueParam("pname", ParamType::TGLuint, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramParam("param", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterivRobustANGLE_param(glState, isCallValid, samplerPacked, pname, - bufSize, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterivRobustANGLE_param(glState, samplerPacked, pname, bufSize, param, + ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterivRobustANGLE, std::move(paramBuffer)); } @@ -3516,21 +3252,19 @@ CallCapture CaptureSamplerParameterfvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramParam("param", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, param, ¶mParam.value); - CaptureSamplerParameterfvRobustANGLE_param(glState, isCallValid, samplerPacked, pname, - bufSize, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterfvRobustANGLE_param(glState, samplerPacked, pname, bufSize, param, + ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterfvRobustANGLE, std::move(paramBuffer)); } @@ -3549,36 +3283,32 @@ CallCapture CaptureGetSamplerParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetSamplerParameterivRobustANGLE_length(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetSamplerParameterivRobustANGLE_length(glState, samplerPacked, pname, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterivRobustANGLE_params(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterivRobustANGLE_params(glState, samplerPacked, pname, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterivRobustANGLE, std::move(paramBuffer)); @@ -3598,37 +3328,33 @@ CallCapture CaptureGetSamplerParameterfvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetSamplerParameterfvRobustANGLE_length(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetSamplerParameterfvRobustANGLE_length(glState, samplerPacked, pname, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetSamplerParameterfvRobustANGLE_params(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterfvRobustANGLE_params(glState, samplerPacked, pname, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterfvRobustANGLE, std::move(paramBuffer)); @@ -3648,36 +3374,32 @@ CallCapture CaptureGetFramebufferParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetFramebufferParameterivRobustANGLE_length(glState, isCallValid, target, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetFramebufferParameterivRobustANGLE_length(glState, target, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferParameterivRobustANGLE_params(glState, isCallValid, target, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferParameterivRobustANGLE_params(glState, target, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferParameterivRobustANGLE, std::move(paramBuffer)); @@ -3700,38 +3422,32 @@ CallCapture CaptureGetProgramInterfaceivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramInterfaceivRobustANGLE_length(glState, isCallValid, programPacked, - programInterface, pname, bufSize, length, - params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramInterfaceivRobustANGLE_length( + glState, programPacked, programInterface, pname, bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramInterfaceivRobustANGLE_params(glState, isCallValid, programPacked, - programInterface, pname, bufSize, length, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramInterfaceivRobustANGLE_params( + glState, programPacked, programInterface, pname, bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramInterfaceivRobustANGLE, std::move(paramBuffer)); @@ -3751,37 +3467,33 @@ CallCapture CaptureGetBooleani_vRobustANGLE(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetBooleani_vRobustANGLE_length(glState, isCallValid, target, index, bufSize, length, - data, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetBooleani_vRobustANGLE_length(glState, target, index, bufSize, length, data, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture dataParam("data", ParamType::TGLbooleanPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, data, &dataParam.value); - CaptureGetBooleani_vRobustANGLE_data(glState, isCallValid, target, index, bufSize, length, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetBooleani_vRobustANGLE_data(glState, target, index, bufSize, length, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLbooleanPointer); InitParamValue(ParamType::TGLbooleanPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetBooleani_vRobustANGLE, std::move(paramBuffer)); } @@ -3800,37 +3512,33 @@ CallCapture CaptureGetMultisamplefvRobustANGLE(const State &glState, paramBuffer.addValueParam("index", ParamType::TGLuint, index); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetMultisamplefvRobustANGLE_length(glState, isCallValid, pname, index, bufSize, - length, val, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetMultisamplefvRobustANGLE_length(glState, pname, index, bufSize, length, val, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture valParam("val", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture valParam("val", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, val, &valParam.value); - CaptureGetMultisamplefvRobustANGLE_val(glState, isCallValid, pname, index, bufSize, length, - val, &valParam); - paramBuffer.addParam(std::move(valParam)); + CaptureGetMultisamplefvRobustANGLE_val(glState, pname, index, bufSize, length, val, + &valParam); } else { - ParamCapture valParam("val", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), &valParam.value); - paramBuffer.addParam(std::move(valParam)); } + paramBuffer.addParam(std::move(valParam)); return CallCapture(angle::EntryPoint::GLGetMultisamplefvRobustANGLE, std::move(paramBuffer)); } @@ -3851,38 +3559,32 @@ CallCapture CaptureGetTexLevelParameterivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTexLevelParameterivRobustANGLE_length(glState, isCallValid, targetPacked, level, - pname, bufSize, length, params, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTexLevelParameterivRobustANGLE_length(glState, targetPacked, level, pname, + bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexLevelParameterivRobustANGLE_params(glState, isCallValid, targetPacked, level, - pname, bufSize, length, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexLevelParameterivRobustANGLE_params(glState, targetPacked, level, pname, + bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexLevelParameterivRobustANGLE, std::move(paramBuffer)); @@ -3904,39 +3606,33 @@ CallCapture CaptureGetTexLevelParameterfvRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTexLevelParameterfvRobustANGLE_length(glState, isCallValid, targetPacked, level, - pname, bufSize, length, params, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTexLevelParameterfvRobustANGLE_length(glState, targetPacked, level, pname, + bufSize, length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexLevelParameterfvRobustANGLE_params(glState, isCallValid, targetPacked, level, - pname, bufSize, length, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexLevelParameterfvRobustANGLE_params(glState, targetPacked, level, pname, + bufSize, length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexLevelParameterfvRobustANGLE, std::move(paramBuffer)); @@ -3954,37 +3650,33 @@ CallCapture CaptureGetPointervRobustANGLERobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetPointervRobustANGLERobustANGLE_length(glState, isCallValid, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetPointervRobustANGLERobustANGLE_length(glState, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetPointervRobustANGLERobustANGLE_params(glState, isCallValid, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetPointervRobustANGLERobustANGLE_params(glState, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetPointervRobustANGLERobustANGLE, std::move(paramBuffer)); @@ -4014,70 +3706,60 @@ CallCapture CaptureReadnPixelsRobustANGLE(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureReadnPixelsRobustANGLE_length(glState, isCallValid, x, y, width, height, format, - type, bufSize, length, columns, rows, data, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureReadnPixelsRobustANGLE_length(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, data, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture columnsParam("columns", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture columnsParam("columns", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, columns, &columnsParam.value); - CaptureReadnPixelsRobustANGLE_columns(glState, isCallValid, x, y, width, height, format, - type, bufSize, length, columns, rows, data, - &columnsParam); - paramBuffer.addParam(std::move(columnsParam)); + CaptureReadnPixelsRobustANGLE_columns(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, data, &columnsParam); } else { - ParamCapture columnsParam("columns", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &columnsParam.value); - paramBuffer.addParam(std::move(columnsParam)); } + paramBuffer.addParam(std::move(columnsParam)); + ParamCapture rowsParam("rows", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture rowsParam("rows", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, rows, &rowsParam.value); - CaptureReadnPixelsRobustANGLE_rows(glState, isCallValid, x, y, width, height, format, type, - bufSize, length, columns, rows, data, &rowsParam); - paramBuffer.addParam(std::move(rowsParam)); + CaptureReadnPixelsRobustANGLE_rows(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, data, &rowsParam); } else { - ParamCapture rowsParam("rows", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &rowsParam.value); - paramBuffer.addParam(std::move(rowsParam)); } + paramBuffer.addParam(std::move(rowsParam)); + ParamCapture dataParam("data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, data, &dataParam.value); - CaptureReadnPixelsRobustANGLE_data(glState, isCallValid, x, y, width, height, format, type, - bufSize, length, columns, rows, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureReadnPixelsRobustANGLE_data(glState, x, y, width, height, format, type, bufSize, + length, columns, rows, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLReadnPixelsRobustANGLE, std::move(paramBuffer)); } @@ -4096,37 +3778,33 @@ CallCapture CaptureGetnUniformfvRobustANGLE(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetnUniformfvRobustANGLE_length(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetnUniformfvRobustANGLE_length(glState, programPacked, locationPacked, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetnUniformfvRobustANGLE_params(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformfvRobustANGLE_params(glState, programPacked, locationPacked, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformfvRobustANGLE, std::move(paramBuffer)); } @@ -4145,36 +3823,32 @@ CallCapture CaptureGetnUniformivRobustANGLE(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetnUniformivRobustANGLE_length(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetnUniformivRobustANGLE_length(glState, programPacked, locationPacked, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetnUniformivRobustANGLE_params(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformivRobustANGLE_params(glState, programPacked, locationPacked, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformivRobustANGLE, std::move(paramBuffer)); } @@ -4193,37 +3867,33 @@ CallCapture CaptureGetnUniformuivRobustANGLE(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetnUniformuivRobustANGLE_length(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetnUniformuivRobustANGLE_length(glState, programPacked, locationPacked, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetnUniformuivRobustANGLE_params(glState, isCallValid, programPacked, locationPacked, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformuivRobustANGLE_params(glState, programPacked, locationPacked, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformuivRobustANGLE, std::move(paramBuffer)); } @@ -4241,21 +3911,19 @@ CallCapture CaptureTexParameterIivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexParameterIivRobustANGLE_params(glState, isCallValid, targetPacked, pname, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIivRobustANGLE_params(glState, targetPacked, pname, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIivRobustANGLE, std::move(paramBuffer)); } @@ -4273,21 +3941,19 @@ CallCapture CaptureTexParameterIuivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, params, ¶msParam.value); - CaptureTexParameterIuivRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIuivRobustANGLE_params(glState, targetPacked, pname, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIuivRobustANGLE, std::move(paramBuffer)); } @@ -4306,36 +3972,32 @@ CallCapture CaptureGetTexParameterIivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTexParameterIivRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTexParameterIivRobustANGLE_length(glState, targetPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexParameterIivRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIivRobustANGLE_params(glState, targetPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIivRobustANGLE, std::move(paramBuffer)); } @@ -4354,37 +4016,33 @@ CallCapture CaptureGetTexParameterIuivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTexParameterIuivRobustANGLE_length(glState, isCallValid, targetPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTexParameterIuivRobustANGLE_length(glState, targetPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetTexParameterIuivRobustANGLE_params(glState, isCallValid, targetPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIuivRobustANGLE_params(glState, targetPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIuivRobustANGLE, std::move(paramBuffer)); } @@ -4402,21 +4060,19 @@ CallCapture CaptureSamplerParameterIivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramParam("param", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIivRobustANGLE_param(glState, isCallValid, samplerPacked, pname, - bufSize, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIivRobustANGLE_param(glState, samplerPacked, pname, bufSize, param, + ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIivRobustANGLE, std::move(paramBuffer)); } @@ -4434,21 +4090,19 @@ CallCapture CaptureSamplerParameterIuivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramParam("param", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIuivRobustANGLE_param(glState, isCallValid, samplerPacked, pname, - bufSize, param, ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIuivRobustANGLE_param(glState, samplerPacked, pname, bufSize, param, + ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIuivRobustANGLE, std::move(paramBuffer)); @@ -4468,36 +4122,32 @@ CallCapture CaptureGetSamplerParameterIivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetSamplerParameterIivRobustANGLE_length(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetSamplerParameterIivRobustANGLE_length(glState, samplerPacked, pname, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIivRobustANGLE_params(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterIivRobustANGLE_params(glState, samplerPacked, pname, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIivRobustANGLE, std::move(paramBuffer)); @@ -4517,37 +4167,33 @@ CallCapture CaptureGetSamplerParameterIuivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetSamplerParameterIuivRobustANGLE_length(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetSamplerParameterIuivRobustANGLE_length(glState, samplerPacked, pname, bufSize, + length, params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIuivRobustANGLE_params(glState, isCallValid, samplerPacked, pname, - bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSamplerParameterIuivRobustANGLE_params(glState, samplerPacked, pname, bufSize, + length, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIuivRobustANGLE, std::move(paramBuffer)); @@ -4567,36 +4213,32 @@ CallCapture CaptureGetQueryObjectivRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetQueryObjectivRobustANGLE_length(glState, isCallValid, idPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetQueryObjectivRobustANGLE_length(glState, idPacked, pname, bufSize, length, params, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetQueryObjectivRobustANGLE_params(glState, isCallValid, idPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectivRobustANGLE_params(glState, idPacked, pname, bufSize, length, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectivRobustANGLE, std::move(paramBuffer)); } @@ -4615,37 +4257,33 @@ CallCapture CaptureGetQueryObjecti64vRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetQueryObjecti64vRobustANGLE_length(glState, isCallValid, idPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetQueryObjecti64vRobustANGLE_length(glState, idPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, params, ¶msParam.value); - CaptureGetQueryObjecti64vRobustANGLE_params(glState, isCallValid, idPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjecti64vRobustANGLE_params(glState, idPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjecti64vRobustANGLE, std::move(paramBuffer)); } @@ -4664,41 +4302,128 @@ CallCapture CaptureGetQueryObjectui64vRobustANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetQueryObjectui64vRobustANGLE_length(glState, isCallValid, idPacked, pname, bufSize, - length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetQueryObjectui64vRobustANGLE_length(glState, idPacked, pname, bufSize, length, + params, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); InitParamValue(ParamType::TGLuint64Pointer, params, ¶msParam.value); - CaptureGetQueryObjectui64vRobustANGLE_params(glState, isCallValid, idPacked, pname, bufSize, - length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectui64vRobustANGLE_params(glState, idPacked, pname, bufSize, length, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); InitParamValue(ParamType::TGLuint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectui64vRobustANGLE, std::move(paramBuffer)); } +CallCapture CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE(const State &glState, + bool isCallValid, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("plane", ParamType::TGLint, plane); + paramBuffer.addEnumParam("pname", GLESEnum::PLSQueryFloat, ParamType::TGLenum, pname); + paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); + CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_length( + glState, plane, pname, bufSize, length, params, &lengthParam); + } + else + { + InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), + &lengthParam.value); + } + paramBuffer.addParam(std::move(lengthParam)); + + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); + CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_params( + glState, plane, pname, bufSize, length, params, ¶msParam); + } + else + { + InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), + ¶msParam.value); + } + paramBuffer.addParam(std::move(paramsParam)); + + return CallCapture(angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE, + std::move(paramBuffer)); +} + +CallCapture CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE(const State &glState, + bool isCallValid, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("plane", ParamType::TGLint, plane); + paramBuffer.addEnumParam("pname", GLESEnum::PLSQueryInt, ParamType::TGLenum, pname); + paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); + CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_length( + glState, plane, pname, bufSize, length, params, &lengthParam); + } + else + { + InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), + &lengthParam.value); + } + paramBuffer.addParam(std::move(lengthParam)); + + ParamCapture paramsParam("params", ParamType::TGLintPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); + CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_params( + glState, plane, pname, bufSize, length, params, ¶msParam); + } + else + { + InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); + } + paramBuffer.addParam(std::move(paramsParam)); + + return CallCapture(angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivRobustANGLE, + std::move(paramBuffer)); +} + CallCapture CaptureImportSemaphoreZirconHandleANGLE(const State &glState, bool isCallValid, SemaphoreID semaphorePacked, @@ -4757,21 +4482,18 @@ CallCapture CaptureFramebufferPixelLocalClearValuefvANGLE(const State &glState, paramBuffer.addValueParam("plane", ParamType::TGLint, plane); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureFramebufferPixelLocalClearValuefvANGLE_value(glState, isCallValid, plane, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureFramebufferPixelLocalClearValuefvANGLE_value(glState, plane, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLFramebufferPixelLocalClearValuefvANGLE, std::move(paramBuffer)); @@ -4786,21 +4508,18 @@ CallCapture CaptureFramebufferPixelLocalClearValueivANGLE(const State &glState, paramBuffer.addValueParam("plane", ParamType::TGLint, plane); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureFramebufferPixelLocalClearValueivANGLE_value(glState, isCallValid, plane, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureFramebufferPixelLocalClearValueivANGLE_value(glState, plane, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLFramebufferPixelLocalClearValueivANGLE, std::move(paramBuffer)); @@ -4815,21 +4534,18 @@ CallCapture CaptureFramebufferPixelLocalClearValueuivANGLE(const State &glState, paramBuffer.addValueParam("plane", ParamType::TGLint, plane); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureFramebufferPixelLocalClearValueuivANGLE_value(glState, isCallValid, plane, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureFramebufferPixelLocalClearValueuivANGLE_value(glState, plane, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLFramebufferPixelLocalClearValueuivANGLE, std::move(paramBuffer)); @@ -4844,20 +4560,18 @@ CallCapture CaptureBeginPixelLocalStorageANGLE(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture loadopsParam("loadops", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture loadopsParam("loadops", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, loadops, &loadopsParam.value); - CaptureBeginPixelLocalStorageANGLE_loadops(glState, isCallValid, n, loadops, &loadopsParam); - paramBuffer.addParam(std::move(loadopsParam)); + CaptureBeginPixelLocalStorageANGLE_loadops(glState, n, loadops, &loadopsParam); } else { - ParamCapture loadopsParam("loadops", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &loadopsParam.value); - paramBuffer.addParam(std::move(loadopsParam)); } + paramBuffer.addParam(std::move(loadopsParam)); return CallCapture(angle::EntryPoint::GLBeginPixelLocalStorageANGLE, std::move(paramBuffer)); } @@ -4871,21 +4585,18 @@ CallCapture CaptureEndPixelLocalStorageANGLE(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture storeopsParam("storeops", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture storeopsParam("storeops", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, storeops, &storeopsParam.value); - CaptureEndPixelLocalStorageANGLE_storeops(glState, isCallValid, n, storeops, - &storeopsParam); - paramBuffer.addParam(std::move(storeopsParam)); + CaptureEndPixelLocalStorageANGLE_storeops(glState, n, storeops, &storeopsParam); } else { - ParamCapture storeopsParam("storeops", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &storeopsParam.value); - paramBuffer.addParam(std::move(storeopsParam)); } + paramBuffer.addParam(std::move(storeopsParam)); return CallCapture(angle::EntryPoint::GLEndPixelLocalStorageANGLE, std::move(paramBuffer)); } @@ -4925,21 +4636,19 @@ CallCapture CaptureGetFramebufferPixelLocalStorageParameterfvANGLE(const State & paramBuffer.addValueParam("plane", ParamType::TGLint, plane); paramBuffer.addEnumParam("pname", GLESEnum::PLSQueryFloat, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params(glState, isCallValid, plane, - pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params(glState, plane, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvANGLE, std::move(paramBuffer)); @@ -4956,124 +4665,23 @@ CallCapture CaptureGetFramebufferPixelLocalStorageParameterivANGLE(const State & paramBuffer.addValueParam("plane", ParamType::TGLint, plane); paramBuffer.addEnumParam("pname", GLESEnum::PLSQueryInt, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params(glState, isCallValid, plane, - pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params(glState, plane, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivANGLE, std::move(paramBuffer)); } -CallCapture CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE(const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params) -{ - ParamBuffer paramBuffer; - - paramBuffer.addValueParam("plane", ParamType::TGLint, plane); - paramBuffer.addEnumParam("pname", GLESEnum::PLSQueryFloat, ParamType::TGLenum, pname); - paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); - - if (isCallValid) - { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); - InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_length( - glState, isCallValid, plane, pname, bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); - } - else - { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); - InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), - &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); - } - - if (isCallValid) - { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); - InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_params( - glState, isCallValid, plane, pname, bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); - } - else - { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); - InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), - ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); - } - - return CallCapture(angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE, - std::move(paramBuffer)); -} - -CallCapture CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE(const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params) -{ - ParamBuffer paramBuffer; - - paramBuffer.addValueParam("plane", ParamType::TGLint, plane); - paramBuffer.addEnumParam("pname", GLESEnum::PLSQueryInt, ParamType::TGLenum, pname); - paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); - - if (isCallValid) - { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); - InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_length( - glState, isCallValid, plane, pname, bufSize, length, params, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); - } - else - { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); - InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), - &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); - } - - if (isCallValid) - { - ParamCapture paramsParam("params", ParamType::TGLintPointer); - InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_params( - glState, isCallValid, plane, pname, bufSize, length, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); - } - else - { - ParamCapture paramsParam("params", ParamType::TGLintPointer); - InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); - } - - return CallCapture(angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivRobustANGLE, - std::move(paramBuffer)); -} - CallCapture CaptureTexImage2DExternalANGLE(const State &glState, bool isCallValid, TextureTarget targetPacked, @@ -5143,20 +4751,18 @@ CallCapture CaptureGetMultisamplefvANGLE(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture valParam("val", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture valParam("val", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, val, &valParam.value); - CaptureGetMultisamplefvANGLE_val(glState, isCallValid, pname, index, val, &valParam); - paramBuffer.addParam(std::move(valParam)); + CaptureGetMultisamplefvANGLE_val(glState, pname, index, val, &valParam); } else { - ParamCapture valParam("val", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), &valParam.value); - paramBuffer.addParam(std::move(valParam)); } + paramBuffer.addParam(std::move(valParam)); return CallCapture(angle::EntryPoint::GLGetMultisamplefvANGLE, std::move(paramBuffer)); } @@ -5186,37 +4792,33 @@ CallCapture CaptureGetTranslatedShaderSourceANGLE(const State &glState, paramBuffer.addValueParam("shaderPacked", ParamType::TShaderProgramID, shaderPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetTranslatedShaderSourceANGLE_length(glState, isCallValid, shaderPacked, bufSize, - length, source, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetTranslatedShaderSourceANGLE_length(glState, shaderPacked, bufSize, length, source, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture sourceParam("source", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture sourceParam("source", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, source, &sourceParam.value); - CaptureGetTranslatedShaderSourceANGLE_source(glState, isCallValid, shaderPacked, bufSize, - length, source, &sourceParam); - paramBuffer.addParam(std::move(sourceParam)); + CaptureGetTranslatedShaderSourceANGLE_source(glState, shaderPacked, bufSize, length, source, + &sourceParam); } else { - ParamCapture sourceParam("source", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &sourceParam.value); - paramBuffer.addParam(std::move(sourceParam)); } + paramBuffer.addParam(std::move(sourceParam)); return CallCapture(angle::EntryPoint::GLGetTranslatedShaderSourceANGLE, std::move(paramBuffer)); } @@ -5231,38 +4833,34 @@ CallCapture CaptureAcquireTexturesANGLE(const State &glState, paramBuffer.addValueParam("numTextures", ParamType::TGLuint, numTextures); + ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); if (isCallValid) { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, texturesPacked, &texturesPackedParam.value); - CaptureAcquireTexturesANGLE_texturesPacked(glState, isCallValid, numTextures, - texturesPacked, layouts, &texturesPackedParam); - paramBuffer.addParam(std::move(texturesPackedParam)); + CaptureAcquireTexturesANGLE_texturesPacked(glState, numTextures, texturesPacked, layouts, + &texturesPackedParam); } else { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, static_cast(nullptr), &texturesPackedParam.value); - paramBuffer.addParam(std::move(texturesPackedParam)); } + paramBuffer.addParam(std::move(texturesPackedParam)); + ParamCapture layoutsParam("layouts", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture layoutsParam("layouts", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, layouts, &layoutsParam.value); - CaptureAcquireTexturesANGLE_layouts(glState, isCallValid, numTextures, texturesPacked, - layouts, &layoutsParam); - paramBuffer.addParam(std::move(layoutsParam)); + CaptureAcquireTexturesANGLE_layouts(glState, numTextures, texturesPacked, layouts, + &layoutsParam); } else { - ParamCapture layoutsParam("layouts", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &layoutsParam.value); - paramBuffer.addParam(std::move(layoutsParam)); } + paramBuffer.addParam(std::move(layoutsParam)); return CallCapture(angle::EntryPoint::GLAcquireTexturesANGLE, std::move(paramBuffer)); } @@ -5277,38 +4875,34 @@ CallCapture CaptureReleaseTexturesANGLE(const State &glState, paramBuffer.addValueParam("numTextures", ParamType::TGLuint, numTextures); + ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); if (isCallValid) { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, texturesPacked, &texturesPackedParam.value); - CaptureReleaseTexturesANGLE_texturesPacked(glState, isCallValid, numTextures, - texturesPacked, layouts, &texturesPackedParam); - paramBuffer.addParam(std::move(texturesPackedParam)); + CaptureReleaseTexturesANGLE_texturesPacked(glState, numTextures, texturesPacked, layouts, + &texturesPackedParam); } else { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, static_cast(nullptr), &texturesPackedParam.value); - paramBuffer.addParam(std::move(texturesPackedParam)); } + paramBuffer.addParam(std::move(texturesPackedParam)); + ParamCapture layoutsParam("layouts", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture layoutsParam("layouts", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, layouts, &layoutsParam.value); - CaptureReleaseTexturesANGLE_layouts(glState, isCallValid, numTextures, texturesPacked, - layouts, &layoutsParam); - paramBuffer.addParam(std::move(layoutsParam)); + CaptureReleaseTexturesANGLE_layouts(glState, numTextures, texturesPacked, layouts, + &layoutsParam); } else { - ParamCapture layoutsParam("layouts", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &layoutsParam.value); - paramBuffer.addParam(std::move(layoutsParam)); } + paramBuffer.addParam(std::move(layoutsParam)); return CallCapture(angle::EntryPoint::GLReleaseTexturesANGLE, std::move(paramBuffer)); } @@ -5324,21 +4918,19 @@ CallCapture CaptureBindUniformLocationCHROMIUM(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureBindUniformLocationCHROMIUM_name(glState, isCallValid, programPacked, locationPacked, - name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureBindUniformLocationCHROMIUM_name(glState, programPacked, locationPacked, name, + &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLBindUniformLocationCHROMIUM, std::move(paramBuffer)); } @@ -5461,56 +5053,23 @@ CallCapture CaptureEGLImageTargetTexStorageEXT(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::AllEnums, ParamType::TGLenum, target); paramBuffer.addValueParam("imagePacked", ParamType::TImageID, imagePacked); + ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, attrib_list, &attrib_listParam.value); - CaptureEGLImageTargetTexStorageEXT_attrib_list(glState, isCallValid, target, imagePacked, - attrib_list, &attrib_listParam); - paramBuffer.addParam(std::move(attrib_listParam)); + CaptureEGLImageTargetTexStorageEXT_attrib_list(glState, target, imagePacked, attrib_list, + &attrib_listParam); } else { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &attrib_listParam.value); - paramBuffer.addParam(std::move(attrib_listParam)); } + paramBuffer.addParam(std::move(attrib_listParam)); return CallCapture(angle::EntryPoint::GLEGLImageTargetTexStorageEXT, std::move(paramBuffer)); } -CallCapture CaptureEGLImageTargetTextureStorageEXT(const State &glState, - bool isCallValid, - GLuint texture, - egl::ImageID imagePacked, - const GLint *attrib_list) -{ - ParamBuffer paramBuffer; - - paramBuffer.addValueParam("texture", ParamType::TGLuint, texture); - paramBuffer.addValueParam("imagePacked", ParamType::TImageID, imagePacked); - - if (isCallValid) - { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); - InitParamValue(ParamType::TGLintConstPointer, attrib_list, &attrib_listParam.value); - CaptureEGLImageTargetTextureStorageEXT_attrib_list( - glState, isCallValid, texture, imagePacked, attrib_list, &attrib_listParam); - paramBuffer.addParam(std::move(attrib_listParam)); - } - else - { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); - InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), - &attrib_listParam.value); - paramBuffer.addParam(std::move(attrib_listParam)); - } - - return CallCapture(angle::EntryPoint::GLEGLImageTargetTextureStorageEXT, - std::move(paramBuffer)); -} - CallCapture CaptureDrawArraysInstancedBaseInstanceEXT(const State &glState, bool isCallValid, PrimitiveMode modePacked, @@ -5546,22 +5105,20 @@ CallCapture CaptureDrawElementsInstancedBaseInstanceEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstancedBaseInstanceEXT_indices(glState, isCallValid, modePacked, count, - typePacked, indices, instancecount, - baseinstance, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstancedBaseInstanceEXT_indices(glState, modePacked, count, typePacked, + indices, instancecount, baseinstance, + &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instancecount", ParamType::TGLsizei, instancecount); paramBuffer.addValueParam("baseinstance", ParamType::TGLuint, baseinstance); @@ -5586,22 +5143,20 @@ CallCapture CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT(const State &g paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT_indices( - glState, isCallValid, modePacked, count, typePacked, indices, instancecount, basevertex, + glState, modePacked, count, typePacked, indices, instancecount, basevertex, baseinstance, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instancecount", ParamType::TGLsizei, instancecount); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -5622,21 +5177,18 @@ CallCapture CaptureBindFragDataLocationEXT(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("color", ParamType::TGLuint, color); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureBindFragDataLocationEXT_name(glState, isCallValid, programPacked, color, name, - &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureBindFragDataLocationEXT_name(glState, programPacked, color, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLBindFragDataLocationEXT, std::move(paramBuffer)); } @@ -5654,21 +5206,19 @@ CallCapture CaptureBindFragDataLocationIndexedEXT(const State &glState, paramBuffer.addValueParam("colorNumber", ParamType::TGLuint, colorNumber); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureBindFragDataLocationIndexedEXT_name(glState, isCallValid, programPacked, colorNumber, - index, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureBindFragDataLocationIndexedEXT_name(glState, programPacked, colorNumber, index, name, + &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); return CallCapture(angle::EntryPoint::GLBindFragDataLocationIndexedEXT, std::move(paramBuffer)); } @@ -5683,20 +5233,18 @@ CallCapture CaptureGetFragDataIndexEXT(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetFragDataIndexEXT_name(glState, isCallValid, programPacked, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetFragDataIndexEXT_name(glState, programPacked, name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLint); InitParamValue(ParamType::TGLint, returnValue, &returnValueCapture.value); @@ -5718,21 +5266,19 @@ CallCapture CaptureGetProgramResourceLocationIndexEXT(const State &glState, paramBuffer.addEnumParam("programInterface", GLESEnum::ProgramInterface, ParamType::TGLenum, programInterface); + ParamCapture nameParam("name", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value); - CaptureGetProgramResourceLocationIndexEXT_name(glState, isCallValid, programPacked, - programInterface, name, &nameParam); - paramBuffer.addParam(std::move(nameParam)); + CaptureGetProgramResourceLocationIndexEXT_name(glState, programPacked, programInterface, + name, &nameParam); } else { - ParamCapture nameParam("name", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &nameParam.value); - paramBuffer.addParam(std::move(nameParam)); } + paramBuffer.addParam(std::move(nameParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLint); InitParamValue(ParamType::TGLint, returnValue, &returnValueCapture.value); @@ -5754,21 +5300,18 @@ CallCapture CaptureBufferStorageEXT(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); paramBuffer.addValueParam("size", ParamType::TGLsizeiptr, size); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureBufferStorageEXT_data(glState, isCallValid, targetPacked, size, data, flags, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureBufferStorageEXT_data(glState, targetPacked, size, data, flags, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); paramBuffer.addEnumParam("flags", GLESEnum::BufferStorageMask, ParamType::TGLbitfield, flags); @@ -5790,21 +5333,18 @@ CallCapture CaptureClearTexImageEXT(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureClearTexImageEXT_data(glState, isCallValid, texturePacked, level, format, type, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureClearTexImageEXT_data(glState, texturePacked, level, format, type, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLClearTexImageEXT, std::move(paramBuffer)); } @@ -5836,22 +5376,19 @@ CallCapture CaptureClearTexSubImageEXT(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureClearTexSubImageEXT_data(glState, isCallValid, texturePacked, level, xoffset, - yoffset, zoffset, width, height, depth, format, type, data, - &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureClearTexSubImageEXT_data(glState, texturePacked, level, xoffset, yoffset, zoffset, + width, height, depth, format, type, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLClearTexSubImageEXT, std::move(paramBuffer)); } @@ -5924,37 +5461,32 @@ CallCapture CaptureGetObjectLabelEXT(const State &glState, paramBuffer.addValueParam("object", ParamType::TGLuint, object); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetObjectLabelEXT_length(glState, isCallValid, type, object, bufSize, length, label, + CaptureGetObjectLabelEXT_length(glState, type, object, bufSize, length, label, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture labelParam("label", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, label, &labelParam.value); - CaptureGetObjectLabelEXT_label(glState, isCallValid, type, object, bufSize, length, label, - &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureGetObjectLabelEXT_label(glState, type, object, bufSize, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLGetObjectLabelEXT, std::move(paramBuffer)); } @@ -5972,20 +5504,18 @@ CallCapture CaptureLabelObjectEXT(const State &glState, paramBuffer.addValueParam("object", ParamType::TGLuint, object); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture labelParam("label", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, label, &labelParam.value); - CaptureLabelObjectEXT_label(glState, isCallValid, type, object, length, label, &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureLabelObjectEXT_label(glState, type, object, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLLabelObjectEXT, std::move(paramBuffer)); } @@ -5999,20 +5529,18 @@ CallCapture CaptureInsertEventMarkerEXT(const State &glState, paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture markerParam("marker", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture markerParam("marker", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, marker, &markerParam.value); - CaptureInsertEventMarkerEXT_marker(glState, isCallValid, length, marker, &markerParam); - paramBuffer.addParam(std::move(markerParam)); + CaptureInsertEventMarkerEXT_marker(glState, length, marker, &markerParam); } else { - ParamCapture markerParam("marker", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &markerParam.value); - paramBuffer.addParam(std::move(markerParam)); } + paramBuffer.addParam(std::move(markerParam)); return CallCapture(angle::EntryPoint::GLInsertEventMarkerEXT, std::move(paramBuffer)); } @@ -6033,20 +5561,18 @@ CallCapture CapturePushGroupMarkerEXT(const State &glState, paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture markerParam("marker", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture markerParam("marker", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, marker, &markerParam.value); - CapturePushGroupMarkerEXT_marker(glState, isCallValid, length, marker, &markerParam); - paramBuffer.addParam(std::move(markerParam)); + CapturePushGroupMarkerEXT_marker(glState, length, marker, &markerParam); } else { - ParamCapture markerParam("marker", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &markerParam.value); - paramBuffer.addParam(std::move(markerParam)); } + paramBuffer.addParam(std::move(markerParam)); return CallCapture(angle::EntryPoint::GLPushGroupMarkerEXT, std::move(paramBuffer)); } @@ -6062,21 +5588,19 @@ CallCapture CaptureDiscardFramebufferEXT(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); paramBuffer.addValueParam("numAttachments", ParamType::TGLsizei, numAttachments); + ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, attachments, &attachmentsParam.value); - CaptureDiscardFramebufferEXT_attachments(glState, isCallValid, target, numAttachments, - attachments, &attachmentsParam); - paramBuffer.addParam(std::move(attachmentsParam)); + CaptureDiscardFramebufferEXT_attachments(glState, target, numAttachments, attachments, + &attachmentsParam); } else { - ParamCapture attachmentsParam("attachments", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &attachmentsParam.value); - paramBuffer.addParam(std::move(attachmentsParam)); } + paramBuffer.addParam(std::move(attachmentsParam)); return CallCapture(angle::EntryPoint::GLDiscardFramebufferEXT, std::move(paramBuffer)); } @@ -6103,20 +5627,18 @@ CallCapture CaptureDeleteQueriesEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDConstPointer); if (isCallValid) { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDConstPointer); InitParamValue(ParamType::TQueryIDConstPointer, idsPacked, &idsPackedParam.value); - CaptureDeleteQueriesEXT_idsPacked(glState, isCallValid, n, idsPacked, &idsPackedParam); - paramBuffer.addParam(std::move(idsPackedParam)); + CaptureDeleteQueriesEXT_idsPacked(glState, n, idsPacked, &idsPackedParam); } else { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDConstPointer); InitParamValue(ParamType::TQueryIDConstPointer, static_cast(nullptr), &idsPackedParam.value); - paramBuffer.addParam(std::move(idsPackedParam)); } + paramBuffer.addParam(std::move(idsPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteQueriesEXT, std::move(paramBuffer)); } @@ -6139,20 +5661,18 @@ CallCapture CaptureGenQueriesEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDPointer); if (isCallValid) { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDPointer); InitParamValue(ParamType::TQueryIDPointer, idsPacked, &idsPackedParam.value); - CaptureGenQueriesEXT_idsPacked(glState, isCallValid, n, idsPacked, &idsPackedParam); - paramBuffer.addParam(std::move(idsPackedParam)); + CaptureGenQueriesEXT_idsPacked(glState, n, idsPacked, &idsPackedParam); } else { - ParamCapture idsPackedParam("idsPacked", ParamType::TQueryIDPointer); InitParamValue(ParamType::TQueryIDPointer, static_cast(nullptr), &idsPackedParam.value); - paramBuffer.addParam(std::move(idsPackedParam)); } + paramBuffer.addParam(std::move(idsPackedParam)); return CallCapture(angle::EntryPoint::GLGenQueriesEXT, std::move(paramBuffer)); } @@ -6166,20 +5686,18 @@ CallCapture CaptureGetInteger64vEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, data, &dataParam.value); - CaptureGetInteger64vEXT_data(glState, isCallValid, pname, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetInteger64vEXT_data(glState, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetInteger64vEXT, std::move(paramBuffer)); } @@ -6196,21 +5714,18 @@ CallCapture CaptureGetQueryObjecti64vEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::QueryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, params, ¶msParam.value); - CaptureGetQueryObjecti64vEXT_params(glState, isCallValid, idPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjecti64vEXT_params(glState, idPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLint64Pointer); InitParamValue(ParamType::TGLint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjecti64vEXT, std::move(paramBuffer)); } @@ -6227,20 +5742,17 @@ CallCapture CaptureGetQueryObjectivEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::QueryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetQueryObjectivEXT_params(glState, isCallValid, idPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectivEXT_params(glState, idPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectivEXT, std::move(paramBuffer)); } @@ -6257,21 +5769,18 @@ CallCapture CaptureGetQueryObjectui64vEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::QueryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); InitParamValue(ParamType::TGLuint64Pointer, params, ¶msParam.value); - CaptureGetQueryObjectui64vEXT_params(glState, isCallValid, idPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectui64vEXT_params(glState, idPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); InitParamValue(ParamType::TGLuint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectui64vEXT, std::move(paramBuffer)); } @@ -6288,21 +5797,18 @@ CallCapture CaptureGetQueryObjectuivEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::QueryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetQueryObjectuivEXT_params(glState, isCallValid, idPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryObjectuivEXT_params(glState, idPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryObjectuivEXT, std::move(paramBuffer)); } @@ -6318,20 +5824,17 @@ CallCapture CaptureGetQueryivEXT(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TQueryType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::QueryParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetQueryivEXT_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetQueryivEXT_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetQueryivEXT, std::move(paramBuffer)); } @@ -6374,20 +5877,18 @@ CallCapture CaptureDrawBuffersEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture bufsParam("bufs", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture bufsParam("bufs", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, bufs, &bufsParam.value); - CaptureDrawBuffersEXT_bufs(glState, isCallValid, n, bufs, &bufsParam); - paramBuffer.addParam(std::move(bufsParam)); + CaptureDrawBuffersEXT_bufs(glState, n, bufs, &bufsParam); } else { - ParamCapture bufsParam("bufs", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &bufsParam.value); - paramBuffer.addParam(std::move(bufsParam)); } + paramBuffer.addParam(std::move(bufsParam)); return CallCapture(angle::EntryPoint::GLDrawBuffersEXT, std::move(paramBuffer)); } @@ -6527,21 +6028,19 @@ CallCapture CaptureDrawElementsBaseVertexEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsBaseVertexEXT_indices(glState, isCallValid, modePacked, count, - typePacked, indices, basevertex, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsBaseVertexEXT_indices(glState, modePacked, count, typePacked, indices, + basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -6563,22 +6062,20 @@ CallCapture CaptureDrawElementsInstancedBaseVertexEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstancedBaseVertexEXT_indices(glState, isCallValid, modePacked, count, - typePacked, indices, instancecount, - basevertex, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstancedBaseVertexEXT_indices(glState, modePacked, count, typePacked, + indices, instancecount, basevertex, + &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instancecount", ParamType::TGLsizei, instancecount); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -6605,22 +6102,19 @@ CallCapture CaptureDrawRangeElementsBaseVertexEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawRangeElementsBaseVertexEXT_indices(glState, isCallValid, modePacked, start, end, - count, typePacked, indices, basevertex, - &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawRangeElementsBaseVertexEXT_indices( + glState, modePacked, start, end, count, typePacked, indices, basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -6640,120 +6134,56 @@ CallCapture CaptureMultiDrawElementsBaseVertexEXT(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture countParam("count", ParamType::TGLsizeiConstPointer); if (isCallValid) { - ParamCapture countParam("count", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, count, &countParam.value); - CaptureMultiDrawElementsBaseVertexEXT_count(glState, isCallValid, modePacked, count, - typePacked, indices, drawcount, basevertex, - &countParam); - paramBuffer.addParam(std::move(countParam)); + CaptureMultiDrawElementsBaseVertexEXT_count(glState, modePacked, count, typePacked, indices, + drawcount, basevertex, &countParam); } else { - ParamCapture countParam("count", ParamType::TGLsizeiConstPointer); InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), &countParam.value); - paramBuffer.addParam(std::move(countParam)); } + paramBuffer.addParam(std::move(countParam)); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, indices, &indicesParam.value); - CaptureMultiDrawElementsBaseVertexEXT_indices(glState, isCallValid, modePacked, count, - typePacked, indices, drawcount, basevertex, - &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureMultiDrawElementsBaseVertexEXT_indices( + glState, modePacked, count, typePacked, indices, drawcount, basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); InitParamValue(ParamType::TvoidConstPointerPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); + ParamCapture basevertexParam("basevertex", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture basevertexParam("basevertex", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, basevertex, &basevertexParam.value); - CaptureMultiDrawElementsBaseVertexEXT_basevertex(glState, isCallValid, modePacked, count, - typePacked, indices, drawcount, basevertex, + CaptureMultiDrawElementsBaseVertexEXT_basevertex(glState, modePacked, count, typePacked, + indices, drawcount, basevertex, &basevertexParam); - paramBuffer.addParam(std::move(basevertexParam)); } else { - ParamCapture basevertexParam("basevertex", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &basevertexParam.value); - paramBuffer.addParam(std::move(basevertexParam)); } + paramBuffer.addParam(std::move(basevertexParam)); return CallCapture(angle::EntryPoint::GLMultiDrawElementsBaseVertexEXT, std::move(paramBuffer)); } -CallCapture CaptureBufferStorageExternalEXT(const State &glState, - bool isCallValid, - BufferBinding targetPacked, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags) -{ - ParamBuffer paramBuffer; - - paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); - paramBuffer.addValueParam("offset", ParamType::TGLintptr, offset); - paramBuffer.addValueParam("size", ParamType::TGLsizeiptr, size); - paramBuffer.addValueParam("clientBuffer", ParamType::TGLeglClientBufferEXT, clientBuffer); - paramBuffer.addEnumParam("flags", GLESEnum::BufferStorageMask, ParamType::TGLbitfield, flags); - - return CallCapture(angle::EntryPoint::GLBufferStorageExternalEXT, std::move(paramBuffer)); -} - -CallCapture CaptureNamedBufferStorageExternalEXT(const State &glState, - bool isCallValid, - GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags) -{ - ParamBuffer paramBuffer; - - paramBuffer.addValueParam("buffer", ParamType::TGLuint, buffer); - paramBuffer.addValueParam("offset", ParamType::TGLintptr, offset); - paramBuffer.addValueParam("size", ParamType::TGLsizeiptr, size); - paramBuffer.addValueParam("clientBuffer", ParamType::TGLeglClientBufferEXT, clientBuffer); - paramBuffer.addEnumParam("flags", GLESEnum::BufferStorageMask, ParamType::TGLbitfield, flags); - - return CallCapture(angle::EntryPoint::GLNamedBufferStorageExternalEXT, std::move(paramBuffer)); -} - -CallCapture CaptureFramebufferTextureEXT(const State &glState, - bool isCallValid, - GLenum target, - GLenum attachment, - TextureID texturePacked, - GLint level) -{ - ParamBuffer paramBuffer; - - paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); - paramBuffer.addEnumParam("attachment", GLESEnum::FramebufferAttachment, ParamType::TGLenum, - attachment); - paramBuffer.addValueParam("texturePacked", ParamType::TTextureID, texturePacked); - paramBuffer.addValueParam("level", ParamType::TGLint, level); - - return CallCapture(angle::EntryPoint::GLFramebufferTextureEXT, std::move(paramBuffer)); -} - CallCapture CaptureDrawArraysInstancedEXT(const State &glState, bool isCallValid, PrimitiveMode modePacked, @@ -6785,27 +6215,151 @@ CallCapture CaptureDrawElementsInstancedEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstancedEXT_indices(glState, isCallValid, modePacked, count, typePacked, - indices, primcount, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstancedEXT_indices(glState, modePacked, count, typePacked, indices, + primcount, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("primcount", ParamType::TGLsizei, primcount); return CallCapture(angle::EntryPoint::GLDrawElementsInstancedEXT, std::move(paramBuffer)); } +CallCapture CaptureBufferStorageExternalEXT(const State &glState, + bool isCallValid, + BufferBinding targetPacked, + GLintptr offset, + GLsizeiptr size, + GLeglClientBufferEXT clientBuffer, + GLbitfield flags) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); + paramBuffer.addValueParam("offset", ParamType::TGLintptr, offset); + paramBuffer.addValueParam("size", ParamType::TGLsizeiptr, size); + paramBuffer.addValueParam("clientBuffer", ParamType::TGLeglClientBufferEXT, clientBuffer); + paramBuffer.addEnumParam("flags", GLESEnum::BufferStorageMask, ParamType::TGLbitfield, flags); + + return CallCapture(angle::EntryPoint::GLBufferStorageExternalEXT, std::move(paramBuffer)); +} + +CallCapture CaptureFramebufferShadingRateEXT(const State &glState, + bool isCallValid, + GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight) +{ + ParamBuffer paramBuffer; + + paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); + paramBuffer.addEnumParam("attachment", GLESEnum::FramebufferAttachment, ParamType::TGLenum, + attachment); + paramBuffer.addValueParam("texture", ParamType::TGLuint, texture); + paramBuffer.addValueParam("baseLayer", ParamType::TGLint, baseLayer); + paramBuffer.addValueParam("numLayers", ParamType::TGLsizei, numLayers); + paramBuffer.addValueParam("texelWidth", ParamType::TGLsizei, texelWidth); + paramBuffer.addValueParam("texelHeight", ParamType::TGLsizei, texelHeight); + + return CallCapture(angle::EntryPoint::GLFramebufferShadingRateEXT, std::move(paramBuffer)); +} + +CallCapture CaptureGetFragmentShadingRatesEXT(const State &glState, + bool isCallValid, + GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("samples", ParamType::TGLsizei, samples); + paramBuffer.addValueParam("maxCount", ParamType::TGLsizei, maxCount); + + ParamCapture countParam("count", ParamType::TGLsizeiPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLsizeiPointer, count, &countParam.value); + CaptureGetFragmentShadingRatesEXT_count(glState, samples, maxCount, count, shadingRates, + &countParam); + } + else + { + InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), + &countParam.value); + } + paramBuffer.addParam(std::move(countParam)); + + ParamCapture shadingRatesParam("shadingRates", ParamType::TGLenumPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLenumPointer, shadingRates, &shadingRatesParam.value); + CaptureGetFragmentShadingRatesEXT_shadingRates(glState, samples, maxCount, count, + shadingRates, &shadingRatesParam); + } + else + { + InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), + &shadingRatesParam.value); + } + paramBuffer.addParam(std::move(shadingRatesParam)); + + return CallCapture(angle::EntryPoint::GLGetFragmentShadingRatesEXT, std::move(paramBuffer)); +} + +CallCapture CaptureShadingRateEXT(const State &glState, bool isCallValid, ShadingRate ratePacked) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("ratePacked", ParamType::TShadingRate, ratePacked); + + return CallCapture(angle::EntryPoint::GLShadingRateEXT, std::move(paramBuffer)); +} + +CallCapture CaptureShadingRateCombinerOpsEXT(const State &glState, + bool isCallValid, + CombinerOp combinerOp0Packed, + CombinerOp combinerOp1Packed) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("combinerOp0Packed", ParamType::TCombinerOp, combinerOp0Packed); + paramBuffer.addValueParam("combinerOp1Packed", ParamType::TCombinerOp, combinerOp1Packed); + + return CallCapture(angle::EntryPoint::GLShadingRateCombinerOpsEXT, std::move(paramBuffer)); +} + +CallCapture CaptureFramebufferTextureEXT(const State &glState, + bool isCallValid, + GLenum target, + GLenum attachment, + TextureID texturePacked, + GLint level) +{ + ParamBuffer paramBuffer; + + paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); + paramBuffer.addEnumParam("attachment", GLESEnum::FramebufferAttachment, ParamType::TGLenum, + attachment); + paramBuffer.addValueParam("texturePacked", ParamType::TTextureID, texturePacked); + paramBuffer.addValueParam("level", ParamType::TGLint, level); + + return CallCapture(angle::EntryPoint::GLFramebufferTextureEXT, std::move(paramBuffer)); +} + CallCapture CaptureVertexAttribDivisorEXT(const State &glState, bool isCallValid, GLuint index, @@ -6883,24 +6437,20 @@ CallCapture CaptureCreateMemoryObjectsEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture memoryObjectsPackedParam("memoryObjectsPacked", ParamType::TMemoryObjectIDPointer); if (isCallValid) { - ParamCapture memoryObjectsPackedParam("memoryObjectsPacked", - ParamType::TMemoryObjectIDPointer); InitParamValue(ParamType::TMemoryObjectIDPointer, memoryObjectsPacked, &memoryObjectsPackedParam.value); - CaptureCreateMemoryObjectsEXT_memoryObjectsPacked( - glState, isCallValid, n, memoryObjectsPacked, &memoryObjectsPackedParam); - paramBuffer.addParam(std::move(memoryObjectsPackedParam)); + CaptureCreateMemoryObjectsEXT_memoryObjectsPacked(glState, n, memoryObjectsPacked, + &memoryObjectsPackedParam); } else { - ParamCapture memoryObjectsPackedParam("memoryObjectsPacked", - ParamType::TMemoryObjectIDPointer); InitParamValue(ParamType::TMemoryObjectIDPointer, static_cast(nullptr), &memoryObjectsPackedParam.value); - paramBuffer.addParam(std::move(memoryObjectsPackedParam)); } + paramBuffer.addParam(std::move(memoryObjectsPackedParam)); return CallCapture(angle::EntryPoint::GLCreateMemoryObjectsEXT, std::move(paramBuffer)); } @@ -6914,25 +6464,22 @@ CallCapture CaptureDeleteMemoryObjectsEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture memoryObjectsPackedParam("memoryObjectsPacked", + ParamType::TMemoryObjectIDConstPointer); if (isCallValid) { - ParamCapture memoryObjectsPackedParam("memoryObjectsPacked", - ParamType::TMemoryObjectIDConstPointer); InitParamValue(ParamType::TMemoryObjectIDConstPointer, memoryObjectsPacked, &memoryObjectsPackedParam.value); - CaptureDeleteMemoryObjectsEXT_memoryObjectsPacked( - glState, isCallValid, n, memoryObjectsPacked, &memoryObjectsPackedParam); - paramBuffer.addParam(std::move(memoryObjectsPackedParam)); + CaptureDeleteMemoryObjectsEXT_memoryObjectsPacked(glState, n, memoryObjectsPacked, + &memoryObjectsPackedParam); } else { - ParamCapture memoryObjectsPackedParam("memoryObjectsPacked", - ParamType::TMemoryObjectIDConstPointer); InitParamValue(ParamType::TMemoryObjectIDConstPointer, static_cast(nullptr), &memoryObjectsPackedParam.value); - paramBuffer.addParam(std::move(memoryObjectsPackedParam)); } + paramBuffer.addParam(std::move(memoryObjectsPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteMemoryObjectsEXT, std::move(paramBuffer)); } @@ -6949,20 +6496,18 @@ CallCapture CaptureGetMemoryObjectParameterivEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::MemoryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetMemoryObjectParameterivEXT_params(glState, isCallValid, memoryObjectPacked, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetMemoryObjectParameterivEXT_params(glState, memoryObjectPacked, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetMemoryObjectParameterivEXT, std::move(paramBuffer)); } @@ -6976,20 +6521,18 @@ CallCapture CaptureGetUnsignedBytevEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::GetPName, ParamType::TGLenum, pname); + ParamCapture dataParam("data", ParamType::TGLubytePointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLubytePointer); InitParamValue(ParamType::TGLubytePointer, data, &dataParam.value); - CaptureGetUnsignedBytevEXT_data(glState, isCallValid, pname, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetUnsignedBytevEXT_data(glState, pname, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLubytePointer); InitParamValue(ParamType::TGLubytePointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetUnsignedBytevEXT, std::move(paramBuffer)); } @@ -7005,20 +6548,18 @@ CallCapture CaptureGetUnsignedBytei_vEXT(const State &glState, paramBuffer.addEnumParam("target", GLESEnum::AllEnums, ParamType::TGLenum, target); paramBuffer.addValueParam("index", ParamType::TGLuint, index); + ParamCapture dataParam("data", ParamType::TGLubytePointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TGLubytePointer); InitParamValue(ParamType::TGLubytePointer, data, &dataParam.value); - CaptureGetUnsignedBytei_vEXT_data(glState, isCallValid, target, index, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureGetUnsignedBytei_vEXT_data(glState, target, index, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TGLubytePointer); InitParamValue(ParamType::TGLubytePointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLGetUnsignedBytei_vEXT, std::move(paramBuffer)); } @@ -7051,21 +6592,19 @@ CallCapture CaptureMemoryObjectParameterivEXT(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::MemoryObjectParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureMemoryObjectParameterivEXT_params(glState, isCallValid, memoryObjectPacked, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureMemoryObjectParameterivEXT_params(glState, memoryObjectPacked, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLMemoryObjectParameterivEXT, std::move(paramBuffer)); } @@ -7191,6 +6730,95 @@ CallCapture CaptureImportMemoryFdEXT(const State &glState, return CallCapture(angle::EntryPoint::GLImportMemoryFdEXT, std::move(paramBuffer)); } +CallCapture CaptureMultiDrawArraysEXT(const State &glState, + bool isCallValid, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + + ParamCapture firstParam("first", ParamType::TGLintConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLintConstPointer, first, &firstParam.value); + CaptureMultiDrawArraysEXT_first(glState, modePacked, first, count, primcount, &firstParam); + } + else + { + InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), + &firstParam.value); + } + paramBuffer.addParam(std::move(firstParam)); + + ParamCapture countParam("count", ParamType::TGLsizeiConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLsizeiConstPointer, count, &countParam.value); + CaptureMultiDrawArraysEXT_count(glState, modePacked, first, count, primcount, &countParam); + } + else + { + InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), + &countParam.value); + } + paramBuffer.addParam(std::move(countParam)); + + paramBuffer.addValueParam("primcount", ParamType::TGLsizei, primcount); + + return CallCapture(angle::EntryPoint::GLMultiDrawArraysEXT, std::move(paramBuffer)); +} + +CallCapture CaptureMultiDrawElementsEXT(const State &glState, + bool isCallValid, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount) +{ + ParamBuffer paramBuffer; + + paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + + ParamCapture countParam("count", ParamType::TGLsizeiConstPointer); + if (isCallValid) + { + InitParamValue(ParamType::TGLsizeiConstPointer, count, &countParam.value); + CaptureMultiDrawElementsEXT_count(glState, modePacked, count, typePacked, indices, + primcount, &countParam); + } + else + { + InitParamValue(ParamType::TGLsizeiConstPointer, static_cast(nullptr), + &countParam.value); + } + paramBuffer.addParam(std::move(countParam)); + + paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + + ParamCapture indicesParam("indices", ParamType::TvoidConstPointerPointer); + if (isCallValid) + { + InitParamValue(ParamType::TvoidConstPointerPointer, indices, &indicesParam.value); + CaptureMultiDrawElementsEXT_indices(glState, modePacked, count, typePacked, indices, + primcount, &indicesParam); + } + else + { + InitParamValue(ParamType::TvoidConstPointerPointer, + static_cast(nullptr), &indicesParam.value); + } + paramBuffer.addParam(std::move(indicesParam)); + + paramBuffer.addValueParam("primcount", ParamType::TGLsizei, primcount); + + return CallCapture(angle::EntryPoint::GLMultiDrawElementsEXT, std::move(paramBuffer)); +} + CallCapture CaptureMultiDrawArraysIndirectEXT(const State &glState, bool isCallValid, PrimitiveMode modePacked, @@ -7202,21 +6830,19 @@ CallCapture CaptureMultiDrawArraysIndirectEXT(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); + ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indirect, &indirectParam.value); - CaptureMultiDrawArraysIndirectEXT_indirect(glState, isCallValid, modePacked, indirect, - drawcount, stride, &indirectParam); - paramBuffer.addParam(std::move(indirectParam)); + CaptureMultiDrawArraysIndirectEXT_indirect(glState, modePacked, indirect, drawcount, stride, + &indirectParam); } else { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indirectParam.value); - paramBuffer.addParam(std::move(indirectParam)); } + paramBuffer.addParam(std::move(indirectParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); @@ -7237,21 +6863,19 @@ CallCapture CaptureMultiDrawElementsIndirectEXT(const State &glState, paramBuffer.addValueParam("modePacked", ParamType::TPrimitiveMode, modePacked); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indirect, &indirectParam.value); - CaptureMultiDrawElementsIndirectEXT_indirect(glState, isCallValid, modePacked, typePacked, - indirect, drawcount, stride, &indirectParam); - paramBuffer.addParam(std::move(indirectParam)); + CaptureMultiDrawElementsIndirectEXT_indirect(glState, modePacked, typePacked, indirect, + drawcount, stride, &indirectParam); } else { - ParamCapture indirectParam("indirect", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indirectParam.value); - paramBuffer.addParam(std::move(indirectParam)); } + paramBuffer.addParam(std::move(indirectParam)); paramBuffer.addValueParam("drawcount", ParamType::TGLsizei, drawcount); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); @@ -7369,21 +6993,19 @@ CallCapture CaptureGetnUniformfvEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetnUniformfvEXT_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformfvEXT_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformfvEXT, std::move(paramBuffer)); } @@ -7401,20 +7023,18 @@ CallCapture CaptureGetnUniformivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetnUniformivEXT_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformivEXT_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformivEXT, std::move(paramBuffer)); } @@ -7440,20 +7060,18 @@ CallCapture CaptureReadnPixelsEXT(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture dataParam("data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, data, &dataParam.value); - CaptureReadnPixelsEXT_data(glState, isCallValid, x, y, width, height, format, type, bufSize, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureReadnPixelsEXT_data(glState, x, y, width, height, format, type, bufSize, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLReadnPixelsEXT, std::move(paramBuffer)); } @@ -7467,22 +7085,20 @@ CallCapture CaptureDeleteSemaphoresEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture semaphoresPackedParam("semaphoresPacked", ParamType::TSemaphoreIDConstPointer); if (isCallValid) { - ParamCapture semaphoresPackedParam("semaphoresPacked", ParamType::TSemaphoreIDConstPointer); InitParamValue(ParamType::TSemaphoreIDConstPointer, semaphoresPacked, &semaphoresPackedParam.value); - CaptureDeleteSemaphoresEXT_semaphoresPacked(glState, isCallValid, n, semaphoresPacked, + CaptureDeleteSemaphoresEXT_semaphoresPacked(glState, n, semaphoresPacked, &semaphoresPackedParam); - paramBuffer.addParam(std::move(semaphoresPackedParam)); } else { - ParamCapture semaphoresPackedParam("semaphoresPacked", ParamType::TSemaphoreIDConstPointer); InitParamValue(ParamType::TSemaphoreIDConstPointer, static_cast(nullptr), &semaphoresPackedParam.value); - paramBuffer.addParam(std::move(semaphoresPackedParam)); } + paramBuffer.addParam(std::move(semaphoresPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteSemaphoresEXT, std::move(paramBuffer)); } @@ -7496,22 +7112,20 @@ CallCapture CaptureGenSemaphoresEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture semaphoresPackedParam("semaphoresPacked", ParamType::TSemaphoreIDPointer); if (isCallValid) { - ParamCapture semaphoresPackedParam("semaphoresPacked", ParamType::TSemaphoreIDPointer); InitParamValue(ParamType::TSemaphoreIDPointer, semaphoresPacked, &semaphoresPackedParam.value); - CaptureGenSemaphoresEXT_semaphoresPacked(glState, isCallValid, n, semaphoresPacked, + CaptureGenSemaphoresEXT_semaphoresPacked(glState, n, semaphoresPacked, &semaphoresPackedParam); - paramBuffer.addParam(std::move(semaphoresPackedParam)); } else { - ParamCapture semaphoresPackedParam("semaphoresPacked", ParamType::TSemaphoreIDPointer); InitParamValue(ParamType::TSemaphoreIDPointer, static_cast(nullptr), &semaphoresPackedParam.value); - paramBuffer.addParam(std::move(semaphoresPackedParam)); } + paramBuffer.addParam(std::move(semaphoresPackedParam)); return CallCapture(angle::EntryPoint::GLGenSemaphoresEXT, std::move(paramBuffer)); } @@ -7527,21 +7141,19 @@ CallCapture CaptureGetSemaphoreParameterui64vEXT(const State &glState, paramBuffer.addValueParam("semaphorePacked", ParamType::TSemaphoreID, semaphorePacked); paramBuffer.addEnumParam("pname", GLESEnum::SemaphoreParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); InitParamValue(ParamType::TGLuint64Pointer, params, ¶msParam.value); - CaptureGetSemaphoreParameterui64vEXT_params(glState, isCallValid, semaphorePacked, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetSemaphoreParameterui64vEXT_params(glState, semaphorePacked, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuint64Pointer); InitParamValue(ParamType::TGLuint64Pointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSemaphoreParameterui64vEXT, std::move(paramBuffer)); } @@ -7573,21 +7185,19 @@ CallCapture CaptureSemaphoreParameterui64vEXT(const State &glState, paramBuffer.addValueParam("semaphorePacked", ParamType::TSemaphoreID, semaphorePacked); paramBuffer.addEnumParam("pname", GLESEnum::SemaphoreParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuint64ConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuint64ConstPointer); InitParamValue(ParamType::TGLuint64ConstPointer, params, ¶msParam.value); - CaptureSemaphoreParameterui64vEXT_params(glState, isCallValid, semaphorePacked, pname, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureSemaphoreParameterui64vEXT_params(glState, semaphorePacked, pname, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuint64ConstPointer); InitParamValue(ParamType::TGLuint64ConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLSemaphoreParameterui64vEXT, std::move(paramBuffer)); } @@ -7606,59 +7216,53 @@ CallCapture CaptureSignalSemaphoreEXT(const State &glState, paramBuffer.addValueParam("semaphorePacked", ParamType::TSemaphoreID, semaphorePacked); paramBuffer.addValueParam("numBufferBarriers", ParamType::TGLuint, numBufferBarriers); + ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); if (isCallValid) { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); InitParamValue(ParamType::TBufferIDConstPointer, buffersPacked, &buffersPackedParam.value); - CaptureSignalSemaphoreEXT_buffersPacked( - glState, isCallValid, semaphorePacked, numBufferBarriers, buffersPacked, - numTextureBarriers, texturesPacked, dstLayouts, &buffersPackedParam); - paramBuffer.addParam(std::move(buffersPackedParam)); + CaptureSignalSemaphoreEXT_buffersPacked(glState, semaphorePacked, numBufferBarriers, + buffersPacked, numTextureBarriers, texturesPacked, + dstLayouts, &buffersPackedParam); } else { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); InitParamValue(ParamType::TBufferIDConstPointer, static_cast(nullptr), &buffersPackedParam.value); - paramBuffer.addParam(std::move(buffersPackedParam)); } + paramBuffer.addParam(std::move(buffersPackedParam)); paramBuffer.addValueParam("numTextureBarriers", ParamType::TGLuint, numTextureBarriers); + ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); if (isCallValid) { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, texturesPacked, &texturesPackedParam.value); - CaptureSignalSemaphoreEXT_texturesPacked( - glState, isCallValid, semaphorePacked, numBufferBarriers, buffersPacked, - numTextureBarriers, texturesPacked, dstLayouts, &texturesPackedParam); - paramBuffer.addParam(std::move(texturesPackedParam)); + CaptureSignalSemaphoreEXT_texturesPacked(glState, semaphorePacked, numBufferBarriers, + buffersPacked, numTextureBarriers, texturesPacked, + dstLayouts, &texturesPackedParam); } else { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, static_cast(nullptr), &texturesPackedParam.value); - paramBuffer.addParam(std::move(texturesPackedParam)); } + paramBuffer.addParam(std::move(texturesPackedParam)); + ParamCapture dstLayoutsParam("dstLayouts", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture dstLayoutsParam("dstLayouts", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, dstLayouts, &dstLayoutsParam.value); - CaptureSignalSemaphoreEXT_dstLayouts(glState, isCallValid, semaphorePacked, - numBufferBarriers, buffersPacked, numTextureBarriers, - texturesPacked, dstLayouts, &dstLayoutsParam); - paramBuffer.addParam(std::move(dstLayoutsParam)); + CaptureSignalSemaphoreEXT_dstLayouts(glState, semaphorePacked, numBufferBarriers, + buffersPacked, numTextureBarriers, texturesPacked, + dstLayouts, &dstLayoutsParam); } else { - ParamCapture dstLayoutsParam("dstLayouts", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &dstLayoutsParam.value); - paramBuffer.addParam(std::move(dstLayoutsParam)); } + paramBuffer.addParam(std::move(dstLayoutsParam)); return CallCapture(angle::EntryPoint::GLSignalSemaphoreEXT, std::move(paramBuffer)); } @@ -7677,59 +7281,53 @@ CallCapture CaptureWaitSemaphoreEXT(const State &glState, paramBuffer.addValueParam("semaphorePacked", ParamType::TSemaphoreID, semaphorePacked); paramBuffer.addValueParam("numBufferBarriers", ParamType::TGLuint, numBufferBarriers); + ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); if (isCallValid) { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); InitParamValue(ParamType::TBufferIDConstPointer, buffersPacked, &buffersPackedParam.value); - CaptureWaitSemaphoreEXT_buffersPacked(glState, isCallValid, semaphorePacked, - numBufferBarriers, buffersPacked, numTextureBarriers, - texturesPacked, srcLayouts, &buffersPackedParam); - paramBuffer.addParam(std::move(buffersPackedParam)); + CaptureWaitSemaphoreEXT_buffersPacked(glState, semaphorePacked, numBufferBarriers, + buffersPacked, numTextureBarriers, texturesPacked, + srcLayouts, &buffersPackedParam); } else { - ParamCapture buffersPackedParam("buffersPacked", ParamType::TBufferIDConstPointer); InitParamValue(ParamType::TBufferIDConstPointer, static_cast(nullptr), &buffersPackedParam.value); - paramBuffer.addParam(std::move(buffersPackedParam)); } + paramBuffer.addParam(std::move(buffersPackedParam)); paramBuffer.addValueParam("numTextureBarriers", ParamType::TGLuint, numTextureBarriers); + ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); if (isCallValid) { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, texturesPacked, &texturesPackedParam.value); - CaptureWaitSemaphoreEXT_texturesPacked(glState, isCallValid, semaphorePacked, - numBufferBarriers, buffersPacked, numTextureBarriers, - texturesPacked, srcLayouts, &texturesPackedParam); - paramBuffer.addParam(std::move(texturesPackedParam)); + CaptureWaitSemaphoreEXT_texturesPacked(glState, semaphorePacked, numBufferBarriers, + buffersPacked, numTextureBarriers, texturesPacked, + srcLayouts, &texturesPackedParam); } else { - ParamCapture texturesPackedParam("texturesPacked", ParamType::TTextureIDConstPointer); InitParamValue(ParamType::TTextureIDConstPointer, static_cast(nullptr), &texturesPackedParam.value); - paramBuffer.addParam(std::move(texturesPackedParam)); } + paramBuffer.addParam(std::move(texturesPackedParam)); + ParamCapture srcLayoutsParam("srcLayouts", ParamType::TGLenumConstPointer); if (isCallValid) { - ParamCapture srcLayoutsParam("srcLayouts", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, srcLayouts, &srcLayoutsParam.value); - CaptureWaitSemaphoreEXT_srcLayouts(glState, isCallValid, semaphorePacked, numBufferBarriers, + CaptureWaitSemaphoreEXT_srcLayouts(glState, semaphorePacked, numBufferBarriers, buffersPacked, numTextureBarriers, texturesPacked, srcLayouts, &srcLayoutsParam); - paramBuffer.addParam(std::move(srcLayoutsParam)); } else { - ParamCapture srcLayoutsParam("srcLayouts", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), &srcLayoutsParam.value); - paramBuffer.addParam(std::move(srcLayoutsParam)); } + paramBuffer.addParam(std::move(srcLayoutsParam)); return CallCapture(angle::EntryPoint::GLWaitSemaphoreEXT, std::move(paramBuffer)); } @@ -7777,7 +7375,7 @@ CallCapture CaptureCreateShaderProgramvEXT(const State &glState, bool isCallValid, ShaderType typePacked, GLsizei count, - const GLchar **strings, + const GLchar *const *strings, GLuint returnValue) { ParamBuffer paramBuffer; @@ -7785,21 +7383,18 @@ CallCapture CaptureCreateShaderProgramvEXT(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TShaderType, typePacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture stringsParam("strings", ParamType::TGLcharConstPointerPointer); if (isCallValid) { - ParamCapture stringsParam("strings", ParamType::TGLcharConstPointerPointer); InitParamValue(ParamType::TGLcharConstPointerPointer, strings, &stringsParam.value); - CaptureCreateShaderProgramvEXT_strings(glState, isCallValid, typePacked, count, strings, - &stringsParam); - paramBuffer.addParam(std::move(stringsParam)); + CaptureCreateShaderProgramvEXT_strings(glState, typePacked, count, strings, &stringsParam); } else { - ParamCapture stringsParam("strings", ParamType::TGLcharConstPointerPointer); - InitParamValue(ParamType::TGLcharConstPointerPointer, static_cast(nullptr), - &stringsParam.value); - paramBuffer.addParam(std::move(stringsParam)); + InitParamValue(ParamType::TGLcharConstPointerPointer, + static_cast(nullptr), &stringsParam.value); } + paramBuffer.addParam(std::move(stringsParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLuint); InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value); @@ -7817,25 +7412,21 @@ CallCapture CaptureDeleteProgramPipelinesEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDConstPointer); if (isCallValid) { - ParamCapture pipelinesPackedParam("pipelinesPacked", - ParamType::TProgramPipelineIDConstPointer); InitParamValue(ParamType::TProgramPipelineIDConstPointer, pipelinesPacked, &pipelinesPackedParam.value); - CaptureDeleteProgramPipelinesEXT_pipelinesPacked(glState, isCallValid, n, pipelinesPacked, + CaptureDeleteProgramPipelinesEXT_pipelinesPacked(glState, n, pipelinesPacked, &pipelinesPackedParam); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } else { - ParamCapture pipelinesPackedParam("pipelinesPacked", - ParamType::TProgramPipelineIDConstPointer); InitParamValue(ParamType::TProgramPipelineIDConstPointer, static_cast(nullptr), &pipelinesPackedParam.value); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } + paramBuffer.addParam(std::move(pipelinesPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteProgramPipelinesEXT, std::move(paramBuffer)); } @@ -7849,22 +7440,20 @@ CallCapture CaptureGenProgramPipelinesEXT(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer); if (isCallValid) { - ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer); InitParamValue(ParamType::TProgramPipelineIDPointer, pipelinesPacked, &pipelinesPackedParam.value); - CaptureGenProgramPipelinesEXT_pipelinesPacked(glState, isCallValid, n, pipelinesPacked, + CaptureGenProgramPipelinesEXT_pipelinesPacked(glState, n, pipelinesPacked, &pipelinesPackedParam); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } else { - ParamCapture pipelinesPackedParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer); InitParamValue(ParamType::TProgramPipelineIDPointer, static_cast(nullptr), &pipelinesPackedParam.value); - paramBuffer.addParam(std::move(pipelinesPackedParam)); } + paramBuffer.addParam(std::move(pipelinesPackedParam)); return CallCapture(angle::EntryPoint::GLGenProgramPipelinesEXT, std::move(paramBuffer)); } @@ -7881,37 +7470,33 @@ CallCapture CaptureGetProgramPipelineInfoLogEXT(const State &glState, paramBuffer.addValueParam("pipelinePacked", ParamType::TProgramPipelineID, pipelinePacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramPipelineInfoLogEXT_length(glState, isCallValid, pipelinePacked, bufSize, - length, infoLog, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramPipelineInfoLogEXT_length(glState, pipelinePacked, bufSize, length, + infoLog, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, infoLog, &infoLogParam.value); - CaptureGetProgramPipelineInfoLogEXT_infoLog(glState, isCallValid, pipelinePacked, bufSize, - length, infoLog, &infoLogParam); - paramBuffer.addParam(std::move(infoLogParam)); + CaptureGetProgramPipelineInfoLogEXT_infoLog(glState, pipelinePacked, bufSize, length, + infoLog, &infoLogParam); } else { - ParamCapture infoLogParam("infoLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &infoLogParam.value); - paramBuffer.addParam(std::move(infoLogParam)); } + paramBuffer.addParam(std::move(infoLogParam)); return CallCapture(angle::EntryPoint::GLGetProgramPipelineInfoLogEXT, std::move(paramBuffer)); } @@ -7927,20 +7512,17 @@ CallCapture CaptureGetProgramPipelineivEXT(const State &glState, paramBuffer.addValueParam("pipelinePacked", ParamType::TProgramPipelineID, pipelinePacked); paramBuffer.addEnumParam("pname", GLESEnum::PipelineParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetProgramPipelineivEXT_params(glState, isCallValid, pipelinePacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetProgramPipelineivEXT_params(glState, pipelinePacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetProgramPipelineivEXT, std::move(paramBuffer)); } @@ -8004,21 +7586,19 @@ CallCapture CaptureProgramUniform1fvEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform1fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform1fvEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform1fvEXT, std::move(paramBuffer)); } @@ -8051,21 +7631,19 @@ CallCapture CaptureProgramUniform1ivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform1ivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform1ivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform1ivEXT, std::move(paramBuffer)); } @@ -8098,21 +7676,19 @@ CallCapture CaptureProgramUniform1uivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform1uivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform1uivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform1uivEXT, std::move(paramBuffer)); } @@ -8147,21 +7723,19 @@ CallCapture CaptureProgramUniform2fvEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform2fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform2fvEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform2fvEXT, std::move(paramBuffer)); } @@ -8196,21 +7770,19 @@ CallCapture CaptureProgramUniform2ivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform2ivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform2ivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform2ivEXT, std::move(paramBuffer)); } @@ -8245,21 +7817,19 @@ CallCapture CaptureProgramUniform2uivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform2uivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform2uivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform2uivEXT, std::move(paramBuffer)); } @@ -8296,21 +7866,19 @@ CallCapture CaptureProgramUniform3fvEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform3fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform3fvEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform3fvEXT, std::move(paramBuffer)); } @@ -8347,21 +7915,19 @@ CallCapture CaptureProgramUniform3ivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform3ivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform3ivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform3ivEXT, std::move(paramBuffer)); } @@ -8398,21 +7964,19 @@ CallCapture CaptureProgramUniform3uivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform3uivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform3uivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform3uivEXT, std::move(paramBuffer)); } @@ -8451,21 +8015,19 @@ CallCapture CaptureProgramUniform4fvEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniform4fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform4fvEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform4fvEXT, std::move(paramBuffer)); } @@ -8504,21 +8066,19 @@ CallCapture CaptureProgramUniform4ivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, value, &valueParam.value); - CaptureProgramUniform4ivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform4ivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform4ivEXT, std::move(paramBuffer)); } @@ -8557,21 +8117,19 @@ CallCapture CaptureProgramUniform4uivEXT(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture valueParam("value", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, value, &valueParam.value); - CaptureProgramUniform4uivEXT_value(glState, isCallValid, programPacked, locationPacked, - count, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniform4uivEXT_value(glState, programPacked, locationPacked, count, value, + &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniform4uivEXT, std::move(paramBuffer)); } @@ -8591,21 +8149,19 @@ CallCapture CaptureProgramUniformMatrix2fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix2fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix2fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix2fvEXT, std::move(paramBuffer)); } @@ -8625,22 +8181,19 @@ CallCapture CaptureProgramUniformMatrix2x3fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix2x3fvEXT_value(glState, isCallValid, programPacked, - locationPacked, count, transpose, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix2x3fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT, std::move(paramBuffer)); } @@ -8660,22 +8213,19 @@ CallCapture CaptureProgramUniformMatrix2x4fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix2x4fvEXT_value(glState, isCallValid, programPacked, - locationPacked, count, transpose, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix2x4fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT, std::move(paramBuffer)); } @@ -8695,21 +8245,19 @@ CallCapture CaptureProgramUniformMatrix3fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix3fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix3fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix3fvEXT, std::move(paramBuffer)); } @@ -8729,22 +8277,19 @@ CallCapture CaptureProgramUniformMatrix3x2fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix3x2fvEXT_value(glState, isCallValid, programPacked, - locationPacked, count, transpose, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix3x2fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT, std::move(paramBuffer)); } @@ -8764,22 +8309,19 @@ CallCapture CaptureProgramUniformMatrix3x4fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix3x4fvEXT_value(glState, isCallValid, programPacked, - locationPacked, count, transpose, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix3x4fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT, std::move(paramBuffer)); } @@ -8799,21 +8341,19 @@ CallCapture CaptureProgramUniformMatrix4fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix4fvEXT_value(glState, isCallValid, programPacked, locationPacked, - count, transpose, value, &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix4fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix4fvEXT, std::move(paramBuffer)); } @@ -8833,22 +8373,19 @@ CallCapture CaptureProgramUniformMatrix4x2fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix4x2fvEXT_value(glState, isCallValid, programPacked, - locationPacked, count, transpose, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix4x2fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT, std::move(paramBuffer)); } @@ -8868,22 +8405,19 @@ CallCapture CaptureProgramUniformMatrix4x3fvEXT(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("transpose", ParamType::TGLboolean, transpose); + ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, value, &valueParam.value); - CaptureProgramUniformMatrix4x3fvEXT_value(glState, isCallValid, programPacked, - locationPacked, count, transpose, value, - &valueParam); - paramBuffer.addParam(std::move(valueParam)); + CaptureProgramUniformMatrix4x3fvEXT_value(glState, programPacked, locationPacked, count, + transpose, value, &valueParam); } else { - ParamCapture valueParam("value", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &valueParam.value); - paramBuffer.addParam(std::move(valueParam)); } + paramBuffer.addParam(std::move(valueParam)); return CallCapture(angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT, std::move(paramBuffer)); } @@ -8946,20 +8480,18 @@ CallCapture CaptureGetSamplerParameterIivEXT(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIivEXT_params(glState, isCallValid, samplerPacked, pname, params, + CaptureGetSamplerParameterIivEXT_params(glState, samplerPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIivEXT, std::move(paramBuffer)); } @@ -8975,21 +8507,19 @@ CallCapture CaptureGetSamplerParameterIuivEXT(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIuivEXT_params(glState, isCallValid, samplerPacked, pname, params, + CaptureGetSamplerParameterIuivEXT_params(glState, samplerPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIuivEXT, std::move(paramBuffer)); } @@ -9005,20 +8535,17 @@ CallCapture CaptureGetTexParameterIivEXT(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexParameterIivEXT_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIivEXT_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIivEXT, std::move(paramBuffer)); } @@ -9034,21 +8561,18 @@ CallCapture CaptureGetTexParameterIuivEXT(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetTexParameterIuivEXT_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIuivEXT_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIuivEXT, std::move(paramBuffer)); } @@ -9064,21 +8588,18 @@ CallCapture CaptureSamplerParameterIivEXT(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIivEXT_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIivEXT_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIivEXT, std::move(paramBuffer)); } @@ -9094,21 +8615,18 @@ CallCapture CaptureSamplerParameterIuivEXT(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIuivEXT_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIuivEXT_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIuivEXT, std::move(paramBuffer)); } @@ -9124,21 +8642,18 @@ CallCapture CaptureTexParameterIivEXT(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexParameterIivEXT_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIivEXT_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIivEXT, std::move(paramBuffer)); } @@ -9154,21 +8669,18 @@ CallCapture CaptureTexParameterIuivEXT(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, params, ¶msParam.value); - CaptureTexParameterIuivEXT_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIuivEXT_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIuivEXT, std::move(paramBuffer)); } @@ -9209,24 +8721,6 @@ CallCapture CaptureTexBufferRangeEXT(const State &glState, return CallCapture(angle::EntryPoint::GLTexBufferRangeEXT, std::move(paramBuffer)); } -CallCapture CaptureTexStorage1DEXT(const State &glState, - bool isCallValid, - GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width) -{ - ParamBuffer paramBuffer; - - paramBuffer.addEnumParam("target", GLESEnum::TextureTarget, ParamType::TGLenum, target); - paramBuffer.addValueParam("levels", ParamType::TGLsizei, levels); - paramBuffer.addEnumParam("internalformat", GLESEnum::SizedInternalFormat, ParamType::TGLenum, - internalformat); - paramBuffer.addValueParam("width", ParamType::TGLsizei, width); - - return CallCapture(angle::EntryPoint::GLTexStorage1DEXT, std::move(paramBuffer)); -} - CallCapture CaptureTexStorage2DEXT(const State &glState, bool isCallValid, TextureType targetPacked, @@ -9287,22 +8781,19 @@ CallCapture CaptureTexStorageAttribs2DEXT(const State &glState, paramBuffer.addValueParam("width", ParamType::TGLsizei, width); paramBuffer.addValueParam("height", ParamType::TGLsizei, height); + ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, attrib_list, &attrib_listParam.value); - CaptureTexStorageAttribs2DEXT_attrib_list(glState, isCallValid, target, levels, - internalformat, width, height, attrib_list, - &attrib_listParam); - paramBuffer.addParam(std::move(attrib_listParam)); + CaptureTexStorageAttribs2DEXT_attrib_list(glState, target, levels, internalformat, width, + height, attrib_list, &attrib_listParam); } else { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &attrib_listParam.value); - paramBuffer.addParam(std::move(attrib_listParam)); } + paramBuffer.addParam(std::move(attrib_listParam)); return CallCapture(angle::EntryPoint::GLTexStorageAttribs2DEXT, std::move(paramBuffer)); } @@ -9327,22 +8818,19 @@ CallCapture CaptureTexStorageAttribs3DEXT(const State &glState, paramBuffer.addValueParam("height", ParamType::TGLsizei, height); paramBuffer.addValueParam("depth", ParamType::TGLsizei, depth); + ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, attrib_list, &attrib_listParam.value); - CaptureTexStorageAttribs3DEXT_attrib_list(glState, isCallValid, target, levels, - internalformat, width, height, depth, attrib_list, - &attrib_listParam); - paramBuffer.addParam(std::move(attrib_listParam)); + CaptureTexStorageAttribs3DEXT_attrib_list(glState, target, levels, internalformat, width, + height, depth, attrib_list, &attrib_listParam); } else { - ParamCapture attrib_listParam("attrib_list", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &attrib_listParam.value); - paramBuffer.addParam(std::move(attrib_listParam)); } + paramBuffer.addParam(std::move(attrib_listParam)); return CallCapture(angle::EntryPoint::GLTexStorageAttribs3DEXT, std::move(paramBuffer)); } @@ -9363,21 +8851,18 @@ CallCapture CaptureDebugMessageCallbackKHR(const State &glState, paramBuffer.addValueParam("callback", ParamType::TGLDEBUGPROCKHR, callback); + ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, userParam, &userParamParam.value); - CaptureDebugMessageCallbackKHR_userParam(glState, isCallValid, callback, userParam, - &userParamParam); - paramBuffer.addParam(std::move(userParamParam)); + CaptureDebugMessageCallbackKHR_userParam(glState, callback, userParam, &userParamParam); } else { - ParamCapture userParamParam("userParam", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &userParamParam.value); - paramBuffer.addParam(std::move(userParamParam)); } + paramBuffer.addParam(std::move(userParamParam)); return CallCapture(angle::EntryPoint::GLDebugMessageCallbackKHR, std::move(paramBuffer)); } @@ -9398,21 +8883,19 @@ CallCapture CaptureDebugMessageControlKHR(const State &glState, paramBuffer.addEnumParam("severity", GLESEnum::DebugSeverity, ParamType::TGLenum, severity); paramBuffer.addValueParam("count", ParamType::TGLsizei, count); + ParamCapture idsParam("ids", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture idsParam("ids", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, ids, &idsParam.value); - CaptureDebugMessageControlKHR_ids(glState, isCallValid, source, type, severity, count, ids, - enabled, &idsParam); - paramBuffer.addParam(std::move(idsParam)); + CaptureDebugMessageControlKHR_ids(glState, source, type, severity, count, ids, enabled, + &idsParam); } else { - ParamCapture idsParam("ids", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), &idsParam.value); - paramBuffer.addParam(std::move(idsParam)); } + paramBuffer.addParam(std::move(idsParam)); paramBuffer.addValueParam("enabled", ParamType::TGLboolean, enabled); @@ -9436,21 +8919,19 @@ CallCapture CaptureDebugMessageInsertKHR(const State &glState, paramBuffer.addEnumParam("severity", GLESEnum::DebugSeverity, ParamType::TGLenum, severity); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture bufParam("buf", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture bufParam("buf", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, buf, &bufParam.value); - CaptureDebugMessageInsertKHR_buf(glState, isCallValid, source, type, id, severity, length, - buf, &bufParam); - paramBuffer.addParam(std::move(bufParam)); + CaptureDebugMessageInsertKHR_buf(glState, source, type, id, severity, length, buf, + &bufParam); } else { - ParamCapture bufParam("buf", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &bufParam.value); - paramBuffer.addParam(std::move(bufParam)); } + paramBuffer.addParam(std::move(bufParam)); return CallCapture(angle::EntryPoint::GLDebugMessageInsertKHR, std::move(paramBuffer)); } @@ -9472,102 +8953,88 @@ CallCapture CaptureGetDebugMessageLogKHR(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLuint, count); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture sourcesParam("sources", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture sourcesParam("sources", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, sources, &sourcesParam.value); - CaptureGetDebugMessageLogKHR_sources(glState, isCallValid, count, bufSize, sources, types, - ids, severities, lengths, messageLog, &sourcesParam); - paramBuffer.addParam(std::move(sourcesParam)); + CaptureGetDebugMessageLogKHR_sources(glState, count, bufSize, sources, types, ids, + severities, lengths, messageLog, &sourcesParam); } else { - ParamCapture sourcesParam("sources", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &sourcesParam.value); - paramBuffer.addParam(std::move(sourcesParam)); } + paramBuffer.addParam(std::move(sourcesParam)); + ParamCapture typesParam("types", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture typesParam("types", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, types, &typesParam.value); - CaptureGetDebugMessageLogKHR_types(glState, isCallValid, count, bufSize, sources, types, - ids, severities, lengths, messageLog, &typesParam); - paramBuffer.addParam(std::move(typesParam)); + CaptureGetDebugMessageLogKHR_types(glState, count, bufSize, sources, types, ids, severities, + lengths, messageLog, &typesParam); } else { - ParamCapture typesParam("types", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &typesParam.value); - paramBuffer.addParam(std::move(typesParam)); } + paramBuffer.addParam(std::move(typesParam)); + ParamCapture idsParam("ids", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture idsParam("ids", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, ids, &idsParam.value); - CaptureGetDebugMessageLogKHR_ids(glState, isCallValid, count, bufSize, sources, types, ids, - severities, lengths, messageLog, &idsParam); - paramBuffer.addParam(std::move(idsParam)); + CaptureGetDebugMessageLogKHR_ids(glState, count, bufSize, sources, types, ids, severities, + lengths, messageLog, &idsParam); } else { - ParamCapture idsParam("ids", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &idsParam.value); - paramBuffer.addParam(std::move(idsParam)); } + paramBuffer.addParam(std::move(idsParam)); + ParamCapture severitiesParam("severities", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture severitiesParam("severities", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, severities, &severitiesParam.value); - CaptureGetDebugMessageLogKHR_severities(glState, isCallValid, count, bufSize, sources, - types, ids, severities, lengths, messageLog, - &severitiesParam); - paramBuffer.addParam(std::move(severitiesParam)); + CaptureGetDebugMessageLogKHR_severities(glState, count, bufSize, sources, types, ids, + severities, lengths, messageLog, &severitiesParam); } else { - ParamCapture severitiesParam("severities", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &severitiesParam.value); - paramBuffer.addParam(std::move(severitiesParam)); } + paramBuffer.addParam(std::move(severitiesParam)); + ParamCapture lengthsParam("lengths", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthsParam("lengths", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, lengths, &lengthsParam.value); - CaptureGetDebugMessageLogKHR_lengths(glState, isCallValid, count, bufSize, sources, types, - ids, severities, lengths, messageLog, &lengthsParam); - paramBuffer.addParam(std::move(lengthsParam)); + CaptureGetDebugMessageLogKHR_lengths(glState, count, bufSize, sources, types, ids, + severities, lengths, messageLog, &lengthsParam); } else { - ParamCapture lengthsParam("lengths", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthsParam.value); - paramBuffer.addParam(std::move(lengthsParam)); } + paramBuffer.addParam(std::move(lengthsParam)); + ParamCapture messageLogParam("messageLog", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture messageLogParam("messageLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, messageLog, &messageLogParam.value); - CaptureGetDebugMessageLogKHR_messageLog(glState, isCallValid, count, bufSize, sources, - types, ids, severities, lengths, messageLog, - &messageLogParam); - paramBuffer.addParam(std::move(messageLogParam)); + CaptureGetDebugMessageLogKHR_messageLog(glState, count, bufSize, sources, types, ids, + severities, lengths, messageLog, &messageLogParam); } else { - ParamCapture messageLogParam("messageLog", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &messageLogParam.value); - paramBuffer.addParam(std::move(messageLogParam)); } + paramBuffer.addParam(std::move(messageLogParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLuint); InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value); @@ -9590,37 +9057,33 @@ CallCapture CaptureGetObjectLabelKHR(const State &glState, paramBuffer.addValueParam("name", ParamType::TGLuint, name); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetObjectLabelKHR_length(glState, isCallValid, identifier, name, bufSize, length, - label, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetObjectLabelKHR_length(glState, identifier, name, bufSize, length, label, + &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture labelParam("label", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, label, &labelParam.value); - CaptureGetObjectLabelKHR_label(glState, isCallValid, identifier, name, bufSize, length, - label, &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureGetObjectLabelKHR_label(glState, identifier, name, bufSize, length, label, + &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLGetObjectLabelKHR, std::move(paramBuffer)); } @@ -9634,55 +9097,46 @@ CallCapture CaptureGetObjectPtrLabelKHR(const State &glState, { ParamBuffer paramBuffer; + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); - CaptureGetObjectPtrLabelKHR_ptr(glState, isCallValid, ptr, bufSize, length, label, - &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureGetObjectPtrLabelKHR_ptr(glState, ptr, bufSize, length, label, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetObjectPtrLabelKHR_length(glState, isCallValid, ptr, bufSize, length, label, - &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetObjectPtrLabelKHR_length(glState, ptr, bufSize, length, label, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture labelParam("label", ParamType::TGLcharPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, label, &labelParam.value); - CaptureGetObjectPtrLabelKHR_label(glState, isCallValid, ptr, bufSize, length, label, - &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureGetObjectPtrLabelKHR_label(glState, ptr, bufSize, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharPointer); InitParamValue(ParamType::TGLcharPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLGetObjectPtrLabelKHR, std::move(paramBuffer)); } @@ -9696,20 +9150,18 @@ CallCapture CaptureGetPointervKHR(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetPointervKHR_params(glState, isCallValid, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetPointervKHR_params(glState, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetPointervKHR, std::move(paramBuffer)); } @@ -9728,21 +9180,18 @@ CallCapture CaptureObjectLabelKHR(const State &glState, paramBuffer.addValueParam("name", ParamType::TGLuint, name); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture labelParam("label", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, label, &labelParam.value); - CaptureObjectLabelKHR_label(glState, isCallValid, identifier, name, length, label, - &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureObjectLabelKHR_label(glState, identifier, name, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLObjectLabelKHR, std::move(paramBuffer)); } @@ -9755,37 +9204,33 @@ CallCapture CaptureObjectPtrLabelKHR(const State &glState, { ParamBuffer paramBuffer; + ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, ptr, &ptrParam.value); - CaptureObjectPtrLabelKHR_ptr(glState, isCallValid, ptr, length, label, &ptrParam); - paramBuffer.addParam(std::move(ptrParam)); + CaptureObjectPtrLabelKHR_ptr(glState, ptr, length, label, &ptrParam); } else { - ParamCapture ptrParam("ptr", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &ptrParam.value); - paramBuffer.addParam(std::move(ptrParam)); } + paramBuffer.addParam(std::move(ptrParam)); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture labelParam("label", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, label, &labelParam.value); - CaptureObjectPtrLabelKHR_label(glState, isCallValid, ptr, length, label, &labelParam); - paramBuffer.addParam(std::move(labelParam)); + CaptureObjectPtrLabelKHR_label(glState, ptr, length, label, &labelParam); } else { - ParamCapture labelParam("label", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &labelParam.value); - paramBuffer.addParam(std::move(labelParam)); } + paramBuffer.addParam(std::move(labelParam)); return CallCapture(angle::EntryPoint::GLObjectPtrLabelKHR, std::move(paramBuffer)); } @@ -9810,21 +9255,18 @@ CallCapture CapturePushDebugGroupKHR(const State &glState, paramBuffer.addValueParam("id", ParamType::TGLuint, id); paramBuffer.addValueParam("length", ParamType::TGLsizei, length); + ParamCapture messageParam("message", ParamType::TGLcharConstPointer); if (isCallValid) { - ParamCapture messageParam("message", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, message, &messageParam.value); - CapturePushDebugGroupKHR_message(glState, isCallValid, source, id, length, message, - &messageParam); - paramBuffer.addParam(std::move(messageParam)); + CapturePushDebugGroupKHR_message(glState, source, id, length, message, &messageParam); } else { - ParamCapture messageParam("message", ParamType::TGLcharConstPointer); InitParamValue(ParamType::TGLcharConstPointer, static_cast(nullptr), &messageParam.value); - paramBuffer.addParam(std::move(messageParam)); } + paramBuffer.addParam(std::move(messageParam)); return CallCapture(angle::EntryPoint::GLPushDebugGroupKHR, std::move(paramBuffer)); } @@ -9864,21 +9306,19 @@ CallCapture CaptureGetnUniformfvKHR(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetnUniformfvKHR_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformfvKHR_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformfvKHR, std::move(paramBuffer)); } @@ -9896,20 +9336,18 @@ CallCapture CaptureGetnUniformivKHR(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetnUniformivKHR_params(glState, isCallValid, programPacked, locationPacked, bufSize, - params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformivKHR_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformivKHR, std::move(paramBuffer)); } @@ -9927,21 +9365,19 @@ CallCapture CaptureGetnUniformuivKHR(const State &glState, paramBuffer.addValueParam("locationPacked", ParamType::TUniformLocation, locationPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetnUniformuivKHR_params(glState, isCallValid, programPacked, locationPacked, - bufSize, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetnUniformuivKHR_params(glState, programPacked, locationPacked, bufSize, params, + ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetnUniformuivKHR, std::move(paramBuffer)); } @@ -9967,20 +9403,18 @@ CallCapture CaptureReadnPixelsKHR(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture dataParam("data", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, data, &dataParam.value); - CaptureReadnPixelsKHR_data(glState, isCallValid, x, y, width, height, format, type, bufSize, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureReadnPixelsKHR_data(glState, x, y, width, height, format, type, bufSize, data, + &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLReadnPixelsKHR, std::move(paramBuffer)); } @@ -10013,20 +9447,17 @@ CallCapture CaptureGetFramebufferParameterivMESA(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::FramebufferAttachmentParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferParameterivMESA_params(glState, isCallValid, target, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferParameterivMESA_params(glState, target, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferParameterivMESA, std::move(paramBuffer)); } @@ -10040,21 +9471,18 @@ CallCapture CaptureDeleteFencesNV(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture fencesPackedParam("fencesPacked", ParamType::TFenceNVIDConstPointer); if (isCallValid) { - ParamCapture fencesPackedParam("fencesPacked", ParamType::TFenceNVIDConstPointer); InitParamValue(ParamType::TFenceNVIDConstPointer, fencesPacked, &fencesPackedParam.value); - CaptureDeleteFencesNV_fencesPacked(glState, isCallValid, n, fencesPacked, - &fencesPackedParam); - paramBuffer.addParam(std::move(fencesPackedParam)); + CaptureDeleteFencesNV_fencesPacked(glState, n, fencesPacked, &fencesPackedParam); } else { - ParamCapture fencesPackedParam("fencesPacked", ParamType::TFenceNVIDConstPointer); InitParamValue(ParamType::TFenceNVIDConstPointer, static_cast(nullptr), &fencesPackedParam.value); - paramBuffer.addParam(std::move(fencesPackedParam)); } + paramBuffer.addParam(std::move(fencesPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteFencesNV, std::move(paramBuffer)); } @@ -10077,20 +9505,18 @@ CallCapture CaptureGenFencesNV(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture fencesPackedParam("fencesPacked", ParamType::TFenceNVIDPointer); if (isCallValid) { - ParamCapture fencesPackedParam("fencesPacked", ParamType::TFenceNVIDPointer); InitParamValue(ParamType::TFenceNVIDPointer, fencesPacked, &fencesPackedParam.value); - CaptureGenFencesNV_fencesPacked(glState, isCallValid, n, fencesPacked, &fencesPackedParam); - paramBuffer.addParam(std::move(fencesPackedParam)); + CaptureGenFencesNV_fencesPacked(glState, n, fencesPacked, &fencesPackedParam); } else { - ParamCapture fencesPackedParam("fencesPacked", ParamType::TFenceNVIDPointer); InitParamValue(ParamType::TFenceNVIDPointer, static_cast(nullptr), &fencesPackedParam.value); - paramBuffer.addParam(std::move(fencesPackedParam)); } + paramBuffer.addParam(std::move(fencesPackedParam)); return CallCapture(angle::EntryPoint::GLGenFencesNV, std::move(paramBuffer)); } @@ -10106,19 +9532,17 @@ CallCapture CaptureGetFenceivNV(const State &glState, paramBuffer.addValueParam("fencePacked", ParamType::TFenceNVID, fencePacked); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFenceivNV_params(glState, isCallValid, fencePacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFenceivNV_params(glState, fencePacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFenceivNV, std::move(paramBuffer)); } @@ -10422,21 +9846,19 @@ CallCapture CaptureDrawElementsBaseVertexOES(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsBaseVertexOES_indices(glState, isCallValid, modePacked, count, - typePacked, indices, basevertex, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsBaseVertexOES_indices(glState, modePacked, count, typePacked, indices, + basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -10458,22 +9880,20 @@ CallCapture CaptureDrawElementsInstancedBaseVertexOES(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawElementsInstancedBaseVertexOES_indices(glState, isCallValid, modePacked, count, - typePacked, indices, instancecount, - basevertex, &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawElementsInstancedBaseVertexOES_indices(glState, modePacked, count, typePacked, + indices, instancecount, basevertex, + &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("instancecount", ParamType::TGLsizei, instancecount); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -10500,22 +9920,19 @@ CallCapture CaptureDrawRangeElementsBaseVertexOES(const State &glState, paramBuffer.addValueParam("count", ParamType::TGLsizei, count); paramBuffer.addValueParam("typePacked", ParamType::TDrawElementsType, typePacked); + ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, indices, &indicesParam.value); - CaptureDrawRangeElementsBaseVertexOES_indices(glState, isCallValid, modePacked, start, end, - count, typePacked, indices, basevertex, - &indicesParam); - paramBuffer.addParam(std::move(indicesParam)); + CaptureDrawRangeElementsBaseVertexOES_indices( + glState, modePacked, start, end, count, typePacked, indices, basevertex, &indicesParam); } else { - ParamCapture indicesParam("indices", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &indicesParam.value); - paramBuffer.addParam(std::move(indicesParam)); } + paramBuffer.addParam(std::move(indicesParam)); paramBuffer.addValueParam("basevertex", ParamType::TGLint, basevertex); @@ -10545,20 +9962,18 @@ CallCapture CaptureDrawTexfvOES(const State &glState, bool isCallValid, const GL { ParamBuffer paramBuffer; + ParamCapture coordsParam("coords", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture coordsParam("coords", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, coords, &coordsParam.value); - CaptureDrawTexfvOES_coords(glState, isCallValid, coords, &coordsParam); - paramBuffer.addParam(std::move(coordsParam)); + CaptureDrawTexfvOES_coords(glState, coords, &coordsParam); } else { - ParamCapture coordsParam("coords", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), &coordsParam.value); - paramBuffer.addParam(std::move(coordsParam)); } + paramBuffer.addParam(std::move(coordsParam)); return CallCapture(angle::EntryPoint::GLDrawTexfvOES, std::move(paramBuffer)); } @@ -10586,20 +10001,18 @@ CallCapture CaptureDrawTexivOES(const State &glState, bool isCallValid, const GL { ParamBuffer paramBuffer; + ParamCapture coordsParam("coords", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture coordsParam("coords", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, coords, &coordsParam.value); - CaptureDrawTexivOES_coords(glState, isCallValid, coords, &coordsParam); - paramBuffer.addParam(std::move(coordsParam)); + CaptureDrawTexivOES_coords(glState, coords, &coordsParam); } else { - ParamCapture coordsParam("coords", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), &coordsParam.value); - paramBuffer.addParam(std::move(coordsParam)); } + paramBuffer.addParam(std::move(coordsParam)); return CallCapture(angle::EntryPoint::GLDrawTexivOES, std::move(paramBuffer)); } @@ -10627,20 +10040,18 @@ CallCapture CaptureDrawTexsvOES(const State &glState, bool isCallValid, const GL { ParamBuffer paramBuffer; + ParamCapture coordsParam("coords", ParamType::TGLshortConstPointer); if (isCallValid) { - ParamCapture coordsParam("coords", ParamType::TGLshortConstPointer); InitParamValue(ParamType::TGLshortConstPointer, coords, &coordsParam.value); - CaptureDrawTexsvOES_coords(glState, isCallValid, coords, &coordsParam); - paramBuffer.addParam(std::move(coordsParam)); + CaptureDrawTexsvOES_coords(glState, coords, &coordsParam); } else { - ParamCapture coordsParam("coords", ParamType::TGLshortConstPointer); InitParamValue(ParamType::TGLshortConstPointer, static_cast(nullptr), &coordsParam.value); - paramBuffer.addParam(std::move(coordsParam)); } + paramBuffer.addParam(std::move(coordsParam)); return CallCapture(angle::EntryPoint::GLDrawTexsvOES, std::move(paramBuffer)); } @@ -10668,20 +10079,18 @@ CallCapture CaptureDrawTexxvOES(const State &glState, bool isCallValid, const GL { ParamBuffer paramBuffer; + ParamCapture coordsParam("coords", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture coordsParam("coords", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, coords, &coordsParam.value); - CaptureDrawTexxvOES_coords(glState, isCallValid, coords, &coordsParam); - paramBuffer.addParam(std::move(coordsParam)); + CaptureDrawTexxvOES_coords(glState, coords, &coordsParam); } else { - ParamCapture coordsParam("coords", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), &coordsParam.value); - paramBuffer.addParam(std::move(coordsParam)); } + paramBuffer.addParam(std::move(coordsParam)); return CallCapture(angle::EntryPoint::GLDrawTexxvOES, std::move(paramBuffer)); } @@ -10737,24 +10146,21 @@ CallCapture CaptureDeleteFramebuffersOES(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture framebuffersPackedParam("framebuffersPacked", + ParamType::TFramebufferIDConstPointer); if (isCallValid) { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDConstPointer); InitParamValue(ParamType::TFramebufferIDConstPointer, framebuffersPacked, &framebuffersPackedParam.value); - CaptureDeleteFramebuffersOES_framebuffersPacked(glState, isCallValid, n, framebuffersPacked, + CaptureDeleteFramebuffersOES_framebuffersPacked(glState, n, framebuffersPacked, &framebuffersPackedParam); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } else { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDConstPointer); InitParamValue(ParamType::TFramebufferIDConstPointer, static_cast(nullptr), &framebuffersPackedParam.value); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } + paramBuffer.addParam(std::move(framebuffersPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteFramebuffersOES, std::move(paramBuffer)); } @@ -10768,25 +10174,22 @@ CallCapture CaptureDeleteRenderbuffersOES(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture renderbuffersPackedParam("renderbuffersPacked", + ParamType::TRenderbufferIDConstPointer); if (isCallValid) { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDConstPointer); InitParamValue(ParamType::TRenderbufferIDConstPointer, renderbuffersPacked, &renderbuffersPackedParam.value); - CaptureDeleteRenderbuffersOES_renderbuffersPacked( - glState, isCallValid, n, renderbuffersPacked, &renderbuffersPackedParam); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); + CaptureDeleteRenderbuffersOES_renderbuffersPacked(glState, n, renderbuffersPacked, + &renderbuffersPackedParam); } else { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDConstPointer); InitParamValue(ParamType::TRenderbufferIDConstPointer, static_cast(nullptr), &renderbuffersPackedParam.value); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } + paramBuffer.addParam(std::move(renderbuffersPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteRenderbuffersOES, std::move(paramBuffer)); } @@ -10839,24 +10242,20 @@ CallCapture CaptureGenFramebuffersOES(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture framebuffersPackedParam("framebuffersPacked", ParamType::TFramebufferIDPointer); if (isCallValid) { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDPointer); InitParamValue(ParamType::TFramebufferIDPointer, framebuffersPacked, &framebuffersPackedParam.value); - CaptureGenFramebuffersOES_framebuffersPacked(glState, isCallValid, n, framebuffersPacked, + CaptureGenFramebuffersOES_framebuffersPacked(glState, n, framebuffersPacked, &framebuffersPackedParam); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } else { - ParamCapture framebuffersPackedParam("framebuffersPacked", - ParamType::TFramebufferIDPointer); InitParamValue(ParamType::TFramebufferIDPointer, static_cast(nullptr), &framebuffersPackedParam.value); - paramBuffer.addParam(std::move(framebuffersPackedParam)); } + paramBuffer.addParam(std::move(framebuffersPackedParam)); return CallCapture(angle::EntryPoint::GLGenFramebuffersOES, std::move(paramBuffer)); } @@ -10870,24 +10269,20 @@ CallCapture CaptureGenRenderbuffersOES(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture renderbuffersPackedParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer); if (isCallValid) { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDPointer); InitParamValue(ParamType::TRenderbufferIDPointer, renderbuffersPacked, &renderbuffersPackedParam.value); - CaptureGenRenderbuffersOES_renderbuffersPacked(glState, isCallValid, n, renderbuffersPacked, + CaptureGenRenderbuffersOES_renderbuffersPacked(glState, n, renderbuffersPacked, &renderbuffersPackedParam); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } else { - ParamCapture renderbuffersPackedParam("renderbuffersPacked", - ParamType::TRenderbufferIDPointer); InitParamValue(ParamType::TRenderbufferIDPointer, static_cast(nullptr), &renderbuffersPackedParam.value); - paramBuffer.addParam(std::move(renderbuffersPackedParam)); } + paramBuffer.addParam(std::move(renderbuffersPackedParam)); return CallCapture(angle::EntryPoint::GLGenRenderbuffersOES, std::move(paramBuffer)); } @@ -10918,20 +10313,18 @@ CallCapture CaptureGetFramebufferAttachmentParameterivOES(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::FramebufferAttachmentParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetFramebufferAttachmentParameterivOES_params( - glState, isCallValid, target, attachment, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetFramebufferAttachmentParameterivOES_params(glState, target, attachment, pname, + params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetFramebufferAttachmentParameterivOES, std::move(paramBuffer)); @@ -10949,20 +10342,17 @@ CallCapture CaptureGetRenderbufferParameterivOES(const State &glState, paramBuffer.addEnumParam("pname", GLESEnum::RenderbufferParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetRenderbufferParameterivOES_params(glState, isCallValid, target, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetRenderbufferParameterivOES_params(glState, target, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetRenderbufferParameterivOES, std::move(paramBuffer)); } @@ -11048,52 +10438,46 @@ CallCapture CaptureGetProgramBinaryOES(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addValueParam("bufSize", ParamType::TGLsizei, bufSize); + ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); if (isCallValid) { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, length, &lengthParam.value); - CaptureGetProgramBinaryOES_length(glState, isCallValid, programPacked, bufSize, length, - binaryFormat, binary, &lengthParam); - paramBuffer.addParam(std::move(lengthParam)); + CaptureGetProgramBinaryOES_length(glState, programPacked, bufSize, length, binaryFormat, + binary, &lengthParam); } else { - ParamCapture lengthParam("length", ParamType::TGLsizeiPointer); InitParamValue(ParamType::TGLsizeiPointer, static_cast(nullptr), &lengthParam.value); - paramBuffer.addParam(std::move(lengthParam)); } + paramBuffer.addParam(std::move(lengthParam)); + ParamCapture binaryFormatParam("binaryFormat", ParamType::TGLenumPointer); if (isCallValid) { - ParamCapture binaryFormatParam("binaryFormat", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, binaryFormat, &binaryFormatParam.value); - CaptureGetProgramBinaryOES_binaryFormat(glState, isCallValid, programPacked, bufSize, - length, binaryFormat, binary, &binaryFormatParam); - paramBuffer.addParam(std::move(binaryFormatParam)); + CaptureGetProgramBinaryOES_binaryFormat(glState, programPacked, bufSize, length, + binaryFormat, binary, &binaryFormatParam); } else { - ParamCapture binaryFormatParam("binaryFormat", ParamType::TGLenumPointer); InitParamValue(ParamType::TGLenumPointer, static_cast(nullptr), &binaryFormatParam.value); - paramBuffer.addParam(std::move(binaryFormatParam)); } + paramBuffer.addParam(std::move(binaryFormatParam)); + ParamCapture binaryParam("binary", ParamType::TvoidPointer); if (isCallValid) { - ParamCapture binaryParam("binary", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, binary, &binaryParam.value); - CaptureGetProgramBinaryOES_binary(glState, isCallValid, programPacked, bufSize, length, - binaryFormat, binary, &binaryParam); - paramBuffer.addParam(std::move(binaryParam)); + CaptureGetProgramBinaryOES_binary(glState, programPacked, bufSize, length, binaryFormat, + binary, &binaryParam); } else { - ParamCapture binaryParam("binary", ParamType::TvoidPointer); InitParamValue(ParamType::TvoidPointer, static_cast(nullptr), &binaryParam.value); - paramBuffer.addParam(std::move(binaryParam)); } + paramBuffer.addParam(std::move(binaryParam)); return CallCapture(angle::EntryPoint::GLGetProgramBinaryOES, std::move(paramBuffer)); } @@ -11110,21 +10494,19 @@ CallCapture CaptureProgramBinaryOES(const State &glState, paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked); paramBuffer.addEnumParam("binaryFormat", GLESEnum::AllEnums, ParamType::TGLenum, binaryFormat); + ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, binary, &binaryParam.value); - CaptureProgramBinaryOES_binary(glState, isCallValid, programPacked, binaryFormat, binary, - length, &binaryParam); - paramBuffer.addParam(std::move(binaryParam)); + CaptureProgramBinaryOES_binary(glState, programPacked, binaryFormat, binary, length, + &binaryParam); } else { - ParamCapture binaryParam("binary", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &binaryParam.value); - paramBuffer.addParam(std::move(binaryParam)); } + paramBuffer.addParam(std::move(binaryParam)); paramBuffer.addValueParam("length", ParamType::TGLint, length); @@ -11142,21 +10524,18 @@ CallCapture CaptureGetBufferPointervOES(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TBufferBinding, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::AllEnums, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, params, ¶msParam.value); - CaptureGetBufferPointervOES_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetBufferPointervOES_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TvoidPointerPointer); InitParamValue(ParamType::TvoidPointerPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetBufferPointervOES, std::move(paramBuffer)); } @@ -11227,21 +10606,18 @@ CallCapture CaptureMatrixIndexPointerOES(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureMatrixIndexPointerOES_pointer(glState, isCallValid, size, type, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureMatrixIndexPointerOES_pointer(glState, size, type, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLMatrixIndexPointerOES, std::move(paramBuffer)); } @@ -11259,21 +10635,18 @@ CallCapture CaptureWeightPointerOES(const State &glState, paramBuffer.addEnumParam("type", GLESEnum::AllEnums, ParamType::TGLenum, type); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CaptureWeightPointerOES_pointer(glState, isCallValid, size, type, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CaptureWeightPointerOES_pointer(glState, size, type, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLWeightPointerOES, std::move(paramBuffer)); } @@ -11289,21 +10662,18 @@ CallCapture CapturePointSizePointerOES(const State &glState, paramBuffer.addValueParam("typePacked", ParamType::TVertexAttribType, typePacked); paramBuffer.addValueParam("stride", ParamType::TGLsizei, stride); + ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pointer, &pointerParam.value); - CapturePointSizePointerOES_pointer(glState, isCallValid, typePacked, stride, pointer, - &pointerParam); - paramBuffer.addParam(std::move(pointerParam)); + CapturePointSizePointerOES_pointer(glState, typePacked, stride, pointer, &pointerParam); } else { - ParamCapture pointerParam("pointer", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pointerParam.value); - paramBuffer.addParam(std::move(pointerParam)); } + paramBuffer.addParam(std::move(pointerParam)); return CallCapture(angle::EntryPoint::GLPointSizePointerOES, std::move(paramBuffer)); } @@ -11341,35 +10711,31 @@ CallCapture CaptureQueryMatrixxOES(const State &glState, { ParamBuffer paramBuffer; + ParamCapture mantissaParam("mantissa", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture mantissaParam("mantissa", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, mantissa, &mantissaParam.value); - CaptureQueryMatrixxOES_mantissa(glState, isCallValid, mantissa, exponent, &mantissaParam); - paramBuffer.addParam(std::move(mantissaParam)); + CaptureQueryMatrixxOES_mantissa(glState, mantissa, exponent, &mantissaParam); } else { - ParamCapture mantissaParam("mantissa", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), &mantissaParam.value); - paramBuffer.addParam(std::move(mantissaParam)); } + paramBuffer.addParam(std::move(mantissaParam)); + ParamCapture exponentParam("exponent", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture exponentParam("exponent", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, exponent, &exponentParam.value); - CaptureQueryMatrixxOES_exponent(glState, isCallValid, mantissa, exponent, &exponentParam); - paramBuffer.addParam(std::move(exponentParam)); + CaptureQueryMatrixxOES_exponent(glState, mantissa, exponent, &exponentParam); } else { - ParamCapture exponentParam("exponent", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), &exponentParam.value); - paramBuffer.addParam(std::move(exponentParam)); } + paramBuffer.addParam(std::move(exponentParam)); ParamCapture returnValueCapture("returnValue", ParamType::TGLbitfield); InitParamValue(ParamType::TGLbitfield, returnValue, &returnValueCapture.value); @@ -11424,22 +10790,19 @@ CallCapture CaptureCompressedTexImage3DOES(const State &glState, paramBuffer.addValueParam("border", ParamType::TGLint, border); paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexImage3DOES_data(glState, isCallValid, targetPacked, level, - internalformat, width, height, depth, border, imageSize, - data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexImage3DOES_data(glState, targetPacked, level, internalformat, width, + height, depth, border, imageSize, data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexImage3DOES, std::move(paramBuffer)); } @@ -11471,22 +10834,20 @@ CallCapture CaptureCompressedTexSubImage3DOES(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::InternalFormat, ParamType::TGLenum, format); paramBuffer.addValueParam("imageSize", ParamType::TGLsizei, imageSize); + ParamCapture dataParam("data", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, data, &dataParam.value); - CaptureCompressedTexSubImage3DOES_data(glState, isCallValid, targetPacked, level, xoffset, - yoffset, zoffset, width, height, depth, format, - imageSize, data, &dataParam); - paramBuffer.addParam(std::move(dataParam)); + CaptureCompressedTexSubImage3DOES_data(glState, targetPacked, level, xoffset, yoffset, + zoffset, width, height, depth, format, imageSize, + data, &dataParam); } else { - ParamCapture dataParam("data", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &dataParam.value); - paramBuffer.addParam(std::move(dataParam)); } + paramBuffer.addParam(std::move(dataParam)); return CallCapture(angle::EntryPoint::GLCompressedTexSubImage3DOES, std::move(paramBuffer)); } @@ -11566,22 +10927,19 @@ CallCapture CaptureTexImage3DOES(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexImage3DOES_pixels(glState, isCallValid, targetPacked, level, internalformat, - width, height, depth, border, format, type, pixels, - &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexImage3DOES_pixels(glState, targetPacked, level, internalformat, width, height, + depth, border, format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexImage3DOES, std::move(paramBuffer)); } @@ -11613,22 +10971,19 @@ CallCapture CaptureTexSubImage3DOES(const State &glState, paramBuffer.addEnumParam("format", GLESEnum::PixelFormat, ParamType::TGLenum, format); paramBuffer.addEnumParam("type", GLESEnum::PixelType, ParamType::TGLenum, type); + ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); if (isCallValid) { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, pixels, &pixelsParam.value); - CaptureTexSubImage3DOES_pixels(glState, isCallValid, targetPacked, level, xoffset, yoffset, - zoffset, width, height, depth, format, type, pixels, - &pixelsParam); - paramBuffer.addParam(std::move(pixelsParam)); + CaptureTexSubImage3DOES_pixels(glState, targetPacked, level, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, &pixelsParam); } else { - ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer); InitParamValue(ParamType::TvoidConstPointer, static_cast(nullptr), &pixelsParam.value); - paramBuffer.addParam(std::move(pixelsParam)); } + paramBuffer.addParam(std::move(pixelsParam)); return CallCapture(angle::EntryPoint::GLTexSubImage3DOES, std::move(paramBuffer)); } @@ -11644,20 +10999,18 @@ CallCapture CaptureGetSamplerParameterIivOES(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIivOES_params(glState, isCallValid, samplerPacked, pname, params, + CaptureGetSamplerParameterIivOES_params(glState, samplerPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIivOES, std::move(paramBuffer)); } @@ -11673,21 +11026,19 @@ CallCapture CaptureGetSamplerParameterIuivOES(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetSamplerParameterIuivOES_params(glState, isCallValid, samplerPacked, pname, params, + CaptureGetSamplerParameterIuivOES_params(glState, samplerPacked, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetSamplerParameterIuivOES, std::move(paramBuffer)); } @@ -11703,20 +11054,17 @@ CallCapture CaptureGetTexParameterIivOES(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexParameterIivOES_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIivOES_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIivOES, std::move(paramBuffer)); } @@ -11732,21 +11080,18 @@ CallCapture CaptureGetTexParameterIuivOES(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::GetTextureParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, params, ¶msParam.value); - CaptureGetTexParameterIuivOES_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexParameterIuivOES_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexParameterIuivOES, std::move(paramBuffer)); } @@ -11762,21 +11107,18 @@ CallCapture CaptureSamplerParameterIivOES(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIivOES_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIivOES_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIivOES, std::move(paramBuffer)); } @@ -11792,21 +11134,18 @@ CallCapture CaptureSamplerParameterIuivOES(const State &glState, paramBuffer.addValueParam("samplerPacked", ParamType::TSamplerID, samplerPacked); paramBuffer.addEnumParam("pname", GLESEnum::SamplerParameterI, ParamType::TGLenum, pname); + ParamCapture paramParam("param", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, param, ¶mParam.value); - CaptureSamplerParameterIuivOES_param(glState, isCallValid, samplerPacked, pname, param, - ¶mParam); - paramBuffer.addParam(std::move(paramParam)); + CaptureSamplerParameterIuivOES_param(glState, samplerPacked, pname, param, ¶mParam); } else { - ParamCapture paramParam("param", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶mParam.value); - paramBuffer.addParam(std::move(paramParam)); } + paramBuffer.addParam(std::move(paramParam)); return CallCapture(angle::EntryPoint::GLSamplerParameterIuivOES, std::move(paramBuffer)); } @@ -11822,21 +11161,18 @@ CallCapture CaptureTexParameterIivOES(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexParameterIivOES_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIivOES_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIivOES, std::move(paramBuffer)); } @@ -11852,21 +11188,18 @@ CallCapture CaptureTexParameterIuivOES(const State &glState, paramBuffer.addValueParam("targetPacked", ParamType::TTextureType, targetPacked); paramBuffer.addEnumParam("pname", GLESEnum::TextureParameterName, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, params, ¶msParam.value); - CaptureTexParameterIuivOES_params(glState, isCallValid, targetPacked, pname, params, - ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexParameterIuivOES_params(glState, targetPacked, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLuintConstPointer); InitParamValue(ParamType::TGLuintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexParameterIuivOES, std::move(paramBuffer)); } @@ -11918,20 +11251,18 @@ CallCapture CaptureGetTexGenfvOES(const State &glState, paramBuffer.addEnumParam("coord", GLESEnum::TextureCoordName, ParamType::TGLenum, coord); paramBuffer.addEnumParam("pname", GLESEnum::TextureGenParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, params, ¶msParam.value); - CaptureGetTexGenfvOES_params(glState, isCallValid, coord, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexGenfvOES_params(glState, coord, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatPointer); InitParamValue(ParamType::TGLfloatPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexGenfvOES, std::move(paramBuffer)); } @@ -11947,19 +11278,17 @@ CallCapture CaptureGetTexGenivOES(const State &glState, paramBuffer.addEnumParam("coord", GLESEnum::TextureCoordName, ParamType::TGLenum, coord); paramBuffer.addEnumParam("pname", GLESEnum::TextureGenParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, params, ¶msParam.value); - CaptureGetTexGenivOES_params(glState, isCallValid, coord, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexGenivOES_params(glState, coord, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintPointer); InitParamValue(ParamType::TGLintPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexGenivOES, std::move(paramBuffer)); } @@ -11975,20 +11304,18 @@ CallCapture CaptureGetTexGenxvOES(const State &glState, paramBuffer.addEnumParam("coord", GLESEnum::TextureCoordName, ParamType::TGLenum, coord); paramBuffer.addEnumParam("pname", GLESEnum::TextureGenParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfixedPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, params, ¶msParam.value); - CaptureGetTexGenxvOES_params(glState, isCallValid, coord, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureGetTexGenxvOES_params(glState, coord, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedPointer); InitParamValue(ParamType::TGLfixedPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLGetTexGenxvOES, std::move(paramBuffer)); } @@ -12019,20 +11346,18 @@ CallCapture CaptureTexGenfvOES(const State &glState, paramBuffer.addEnumParam("coord", GLESEnum::TextureCoordName, ParamType::TGLenum, coord); paramBuffer.addEnumParam("pname", GLESEnum::TextureGenParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, params, ¶msParam.value); - CaptureTexGenfvOES_params(glState, isCallValid, coord, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexGenfvOES_params(glState, coord, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfloatConstPointer); InitParamValue(ParamType::TGLfloatConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexGenfvOES, std::move(paramBuffer)); } @@ -12063,20 +11388,18 @@ CallCapture CaptureTexGenivOES(const State &glState, paramBuffer.addEnumParam("coord", GLESEnum::TextureCoordName, ParamType::TGLenum, coord); paramBuffer.addEnumParam("pname", GLESEnum::TextureGenParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLintConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, params, ¶msParam.value); - CaptureTexGenivOES_params(glState, isCallValid, coord, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexGenivOES_params(glState, coord, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLintConstPointer); InitParamValue(ParamType::TGLintConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexGenivOES, std::move(paramBuffer)); } @@ -12107,20 +11430,18 @@ CallCapture CaptureTexGenxvOES(const State &glState, paramBuffer.addEnumParam("coord", GLESEnum::TextureCoordName, ParamType::TGLenum, coord); paramBuffer.addEnumParam("pname", GLESEnum::TextureGenParameter, ParamType::TGLenum, pname); + ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); if (isCallValid) { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, params, ¶msParam.value); - CaptureTexGenxvOES_params(glState, isCallValid, coord, pname, params, ¶msParam); - paramBuffer.addParam(std::move(paramsParam)); + CaptureTexGenxvOES_params(glState, coord, pname, params, ¶msParam); } else { - ParamCapture paramsParam("params", ParamType::TGLfixedConstPointer); InitParamValue(ParamType::TGLfixedConstPointer, static_cast(nullptr), ¶msParam.value); - paramBuffer.addParam(std::move(paramsParam)); } + paramBuffer.addParam(std::move(paramsParam)); return CallCapture(angle::EntryPoint::GLTexGenxvOES, std::move(paramBuffer)); } @@ -12169,22 +11490,19 @@ CallCapture CaptureDeleteVertexArraysOES(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDConstPointer); if (isCallValid) { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDConstPointer); InitParamValue(ParamType::TVertexArrayIDConstPointer, arraysPacked, &arraysPackedParam.value); - CaptureDeleteVertexArraysOES_arraysPacked(glState, isCallValid, n, arraysPacked, - &arraysPackedParam); - paramBuffer.addParam(std::move(arraysPackedParam)); + CaptureDeleteVertexArraysOES_arraysPacked(glState, n, arraysPacked, &arraysPackedParam); } else { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDConstPointer); InitParamValue(ParamType::TVertexArrayIDConstPointer, static_cast(nullptr), &arraysPackedParam.value); - paramBuffer.addParam(std::move(arraysPackedParam)); } + paramBuffer.addParam(std::move(arraysPackedParam)); return CallCapture(angle::EntryPoint::GLDeleteVertexArraysOES, std::move(paramBuffer)); } @@ -12198,21 +11516,18 @@ CallCapture CaptureGenVertexArraysOES(const State &glState, paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDPointer); if (isCallValid) { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDPointer); InitParamValue(ParamType::TVertexArrayIDPointer, arraysPacked, &arraysPackedParam.value); - CaptureGenVertexArraysOES_arraysPacked(glState, isCallValid, n, arraysPacked, - &arraysPackedParam); - paramBuffer.addParam(std::move(arraysPackedParam)); + CaptureGenVertexArraysOES_arraysPacked(glState, n, arraysPacked, &arraysPackedParam); } else { - ParamCapture arraysPackedParam("arraysPacked", ParamType::TVertexArrayIDPointer); InitParamValue(ParamType::TVertexArrayIDPointer, static_cast(nullptr), &arraysPackedParam.value); - paramBuffer.addParam(std::move(arraysPackedParam)); } + paramBuffer.addParam(std::move(arraysPackedParam)); return CallCapture(angle::EntryPoint::GLGenVertexArraysOES, std::move(paramBuffer)); } @@ -12255,6 +11570,31 @@ CallCapture CaptureFramebufferTextureMultiviewOVR(const State &glState, return CallCapture(angle::EntryPoint::GLFramebufferTextureMultiviewOVR, std::move(paramBuffer)); } +CallCapture CaptureFramebufferTextureMultisampleMultiviewOVR(const State &glState, + bool isCallValid, + GLenum target, + GLenum attachment, + TextureID texturePacked, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews) +{ + ParamBuffer paramBuffer; + + paramBuffer.addEnumParam("target", GLESEnum::FramebufferTarget, ParamType::TGLenum, target); + paramBuffer.addEnumParam("attachment", GLESEnum::FramebufferAttachment, ParamType::TGLenum, + attachment); + paramBuffer.addValueParam("texturePacked", ParamType::TTextureID, texturePacked); + paramBuffer.addValueParam("level", ParamType::TGLint, level); + paramBuffer.addValueParam("samples", ParamType::TGLsizei, samples); + paramBuffer.addValueParam("baseViewIndex", ParamType::TGLint, baseViewIndex); + paramBuffer.addValueParam("numViews", ParamType::TGLsizei, numViews); + + return CallCapture(angle::EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR, + std::move(paramBuffer)); +} + CallCapture CaptureFramebufferFoveationConfigQCOM(const State &glState, bool isCallValid, FramebufferID framebufferPacked, @@ -12270,22 +11610,20 @@ CallCapture CaptureFramebufferFoveationConfigQCOM(const State &glState, paramBuffer.addValueParam("focalPointsPerLayer", ParamType::TGLuint, focalPointsPerLayer); paramBuffer.addValueParam("requestedFeatures", ParamType::TGLuint, requestedFeatures); + ParamCapture providedFeaturesParam("providedFeatures", ParamType::TGLuintPointer); if (isCallValid) { - ParamCapture providedFeaturesParam("providedFeatures", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, providedFeatures, &providedFeaturesParam.value); CaptureFramebufferFoveationConfigQCOM_providedFeatures( - glState, isCallValid, framebufferPacked, numLayers, focalPointsPerLayer, - requestedFeatures, providedFeatures, &providedFeaturesParam); - paramBuffer.addParam(std::move(providedFeaturesParam)); + glState, framebufferPacked, numLayers, focalPointsPerLayer, requestedFeatures, + providedFeatures, &providedFeaturesParam); } else { - ParamCapture providedFeaturesParam("providedFeatures", ParamType::TGLuintPointer); InitParamValue(ParamType::TGLuintPointer, static_cast(nullptr), &providedFeaturesParam.value); - paramBuffer.addParam(std::move(providedFeaturesParam)); } + paramBuffer.addParam(std::move(providedFeaturesParam)); return CallCapture(angle::EntryPoint::GLFramebufferFoveationConfigQCOM, std::move(paramBuffer)); } @@ -12316,11 +11654,11 @@ CallCapture CaptureFramebufferFoveationParametersQCOM(const State &glState, std::move(paramBuffer)); } -CallCapture CaptureShadingRateQCOM(const State &glState, bool isCallValid, GLenum rate) +CallCapture CaptureShadingRateQCOM(const State &glState, bool isCallValid, ShadingRate ratePacked) { ParamBuffer paramBuffer; - paramBuffer.addEnumParam("rate", GLESEnum::ShadingRateQCOM, ParamType::TGLenum, rate); + paramBuffer.addValueParam("ratePacked", ParamType::TShadingRate, ratePacked); return CallCapture(angle::EntryPoint::GLShadingRateQCOM, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_ext_autogen.h b/src/libANGLE/capture/capture_gles_ext_autogen.h index a0d195afeac..5fb783ec441 100644 --- a/src/libANGLE/capture/capture_gles_ext_autogen.h +++ b/src/libANGLE/capture/capture_gles_ext_autogen.h @@ -880,6 +880,22 @@ angle::CallCapture CaptureGetQueryObjectui64vRobustANGLE(const State &glState, GLsizei bufSize, GLsizei *length, GLuint64 *params); +angle::CallCapture CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE( + const State &glState, + bool isCallValid, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params); +angle::CallCapture CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE( + const State &glState, + bool isCallValid, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params); // GL_ANGLE_robust_fragment_shader_output @@ -940,22 +956,6 @@ angle::CallCapture CaptureGetFramebufferPixelLocalStorageParameterivANGLE(const GLint plane, GLenum pname, GLint *params); -angle::CallCapture CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params); -angle::CallCapture CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params); // GL_ANGLE_stencil_texturing @@ -1023,14 +1023,14 @@ angle::CallCapture CaptureReleaseTexturesANGLE(const State &glState, // GL_APPLE_clip_distance -// GL_ARB_sync - // GL_ARM_rgba8 // GL_ARM_shader_framebuffer_fetch // GL_ARM_shader_framebuffer_fetch_depth_stencil +// GL_ARM_texture_unnormalized_coordinates + // GL_CHROMIUM_bind_uniform_location angle::CallCapture CaptureBindUniformLocationCHROMIUM(const State &glState, bool isCallValid, @@ -1093,11 +1093,6 @@ angle::CallCapture CaptureEGLImageTargetTexStorageEXT(const State &glState, GLenum target, egl::ImageID imagePacked, const GLint *attrib_list); -angle::CallCapture CaptureEGLImageTargetTextureStorageEXT(const State &glState, - bool isCallValid, - GLuint texture, - egl::ImageID imagePacked, - const GLint *attrib_list); // GL_EXT_EGL_image_storage_compression @@ -1391,6 +1386,21 @@ angle::CallCapture CaptureMultiDrawElementsBaseVertexEXT(const State &glState, GLsizei drawcount, const GLint *basevertex); +// GL_EXT_draw_instanced +angle::CallCapture CaptureDrawArraysInstancedEXT(const State &glState, + bool isCallValid, + PrimitiveMode modePacked, + GLint start, + GLsizei count, + GLsizei primcount); +angle::CallCapture CaptureDrawElementsInstancedEXT(const State &glState, + bool isCallValid, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLsizei primcount); + // GL_EXT_external_buffer angle::CallCapture CaptureBufferStorageExternalEXT(const State &glState, bool isCallValid, @@ -1399,16 +1409,33 @@ angle::CallCapture CaptureBufferStorageExternalEXT(const State &glState, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); -angle::CallCapture CaptureNamedBufferStorageExternalEXT(const State &glState, - bool isCallValid, - GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags); // GL_EXT_float_blend +// GL_EXT_fragment_shading_rate +angle::CallCapture CaptureFramebufferShadingRateEXT(const State &glState, + bool isCallValid, + GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight); +angle::CallCapture CaptureGetFragmentShadingRatesEXT(const State &glState, + bool isCallValid, + GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates); +angle::CallCapture CaptureShadingRateEXT(const State &glState, + bool isCallValid, + ShadingRate ratePacked); +angle::CallCapture CaptureShadingRateCombinerOpsEXT(const State &glState, + bool isCallValid, + CombinerOp combinerOp0Packed, + CombinerOp combinerOp1Packed); + // GL_EXT_geometry_shader angle::CallCapture CaptureFramebufferTextureEXT(const State &glState, bool isCallValid, @@ -1420,19 +1447,6 @@ angle::CallCapture CaptureFramebufferTextureEXT(const State &glState, // GL_EXT_gpu_shader5 // GL_EXT_instanced_arrays -angle::CallCapture CaptureDrawArraysInstancedEXT(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLint start, - GLsizei count, - GLsizei primcount); -angle::CallCapture CaptureDrawElementsInstancedEXT(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLsizei primcount); angle::CallCapture CaptureVertexAttribDivisorEXT(const State &glState, bool isCallValid, GLuint index, @@ -1539,6 +1553,21 @@ angle::CallCapture CaptureImportMemoryFdEXT(const State &glState, HandleType handleTypePacked, GLint fd); +// GL_EXT_multi_draw_arrays +angle::CallCapture CaptureMultiDrawArraysEXT(const State &glState, + bool isCallValid, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount); +angle::CallCapture CaptureMultiDrawElementsEXT(const State &glState, + bool isCallValid, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount); + // GL_EXT_multi_draw_indirect angle::CallCapture CaptureMultiDrawArraysIndirectEXT(const State &glState, bool isCallValid, @@ -1694,7 +1723,7 @@ angle::CallCapture CaptureCreateShaderProgramvEXT(const State &glState, bool isCallValid, ShaderType typePacked, GLsizei count, - const GLchar **strings, + const GLchar *const *strings, GLuint returnValue); angle::CallCapture CaptureDeleteProgramPipelinesEXT(const State &glState, bool isCallValid, @@ -1957,6 +1986,8 @@ angle::CallCapture CaptureFramebufferFetchBarrierEXT(const State &glState, bool // GL_EXT_shader_texture_lod +// GL_EXT_shader_texture_samples + // GL_EXT_shadow_samplers // GL_EXT_tessellation_shader @@ -2060,12 +2091,6 @@ angle::CallCapture CaptureTexBufferRangeEXT(const State &glState, // GL_EXT_texture_shadow_lod // GL_EXT_texture_storage -angle::CallCapture CaptureTexStorage1DEXT(const State &glState, - bool isCallValid, - GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width); angle::CallCapture CaptureTexStorage2DEXT(const State &glState, bool isCallValid, TextureType targetPacked, @@ -2286,6 +2311,8 @@ angle::CallCapture CaptureBlitFramebufferNV(const State &glState, GLbitfield mask, GLenum filter); +// GL_NV_pack_subimage + // GL_NV_pixel_buffer_object // GL_NV_polygon_mode @@ -2885,6 +2912,17 @@ angle::CallCapture CaptureFramebufferTextureMultiviewOVR(const State &glState, // GL_OVR_multiview2 +// GL_OVR_multiview_multisampled_render_to_texture +angle::CallCapture CaptureFramebufferTextureMultisampleMultiviewOVR(const State &glState, + bool isCallValid, + GLenum target, + GLenum attachment, + TextureID texturePacked, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews); + // GL_QCOM_framebuffer_foveated angle::CallCapture CaptureFramebufferFoveationConfigQCOM(const State &glState, bool isCallValid, @@ -2907,7 +2945,9 @@ angle::CallCapture CaptureFramebufferFoveationParametersQCOM(const State &glStat // GL_QCOM_render_shared_exponent // GL_QCOM_shading_rate -angle::CallCapture CaptureShadingRateQCOM(const State &glState, bool isCallValid, GLenum rate); +angle::CallCapture CaptureShadingRateQCOM(const State &glState, + bool isCallValid, + ShadingRate ratePacked); // GL_QCOM_texture_foveated angle::CallCapture CaptureTextureFoveationParametersQCOM(const State &glState, @@ -2936,17 +2976,14 @@ angle::CallCapture CaptureStartTilingQCOM(const State &glState, // Parameter Captures void CaptureDeletePerfMonitorsAMD_monitors(const State &glState, - bool isCallValid, GLsizei n, GLuint *monitors, angle::ParamCapture *paramCapture); void CaptureGenPerfMonitorsAMD_monitors(const State &glState, - bool isCallValid, GLsizei n, GLuint *monitors, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCounterDataAMD_data(const State &glState, - bool isCallValid, GLuint monitor, GLenum pname, GLsizei dataSize, @@ -2954,7 +2991,6 @@ void CaptureGetPerfMonitorCounterDataAMD_data(const State &glState, GLint *bytesWritten, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCounterDataAMD_bytesWritten(const State &glState, - bool isCallValid, GLuint monitor, GLenum pname, GLsizei dataSize, @@ -2962,14 +2998,12 @@ void CaptureGetPerfMonitorCounterDataAMD_bytesWritten(const State &glState, GLint *bytesWritten, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCounterInfoAMD_data(const State &glState, - bool isCallValid, GLuint group, GLuint counter, GLenum pname, void *data, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCounterStringAMD_length(const State &glState, - bool isCallValid, GLuint group, GLuint counter, GLsizei bufSize, @@ -2977,7 +3011,6 @@ void CaptureGetPerfMonitorCounterStringAMD_length(const State &glState, GLchar *counterString, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCounterStringAMD_counterString(const State &glState, - bool isCallValid, GLuint group, GLuint counter, GLsizei bufSize, @@ -2985,7 +3018,6 @@ void CaptureGetPerfMonitorCounterStringAMD_counterString(const State &glState, GLchar *counterString, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCountersAMD_numCounters(const State &glState, - bool isCallValid, GLuint group, GLint *numCounters, GLint *maxActiveCounters, @@ -2993,7 +3025,6 @@ void CaptureGetPerfMonitorCountersAMD_numCounters(const State &glState, GLuint *counters, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCountersAMD_maxActiveCounters(const State &glState, - bool isCallValid, GLuint group, GLint *numCounters, GLint *maxActiveCounters, @@ -3001,7 +3032,6 @@ void CaptureGetPerfMonitorCountersAMD_maxActiveCounters(const State &glState, GLuint *counters, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorCountersAMD_counters(const State &glState, - bool isCallValid, GLuint group, GLint *numCounters, GLint *maxActiveCounters, @@ -3009,33 +3039,28 @@ void CaptureGetPerfMonitorCountersAMD_counters(const State &glState, GLuint *counters, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorGroupStringAMD_length(const State &glState, - bool isCallValid, GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorGroupStringAMD_groupString(const State &glState, - bool isCallValid, GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorGroupsAMD_numGroups(const State &glState, - bool isCallValid, GLint *numGroups, GLsizei groupsSize, GLuint *groups, angle::ParamCapture *paramCapture); void CaptureGetPerfMonitorGroupsAMD_groups(const State &glState, - bool isCallValid, GLint *numGroups, GLsizei groupsSize, GLuint *groups, angle::ParamCapture *paramCapture); void CaptureSelectPerfMonitorCountersAMD_counterList(const State &glState, - bool isCallValid, GLuint monitor, GLboolean enable, GLuint group, @@ -3044,7 +3069,6 @@ void CaptureSelectPerfMonitorCountersAMD_counterList(const State &glState, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -3054,7 +3078,6 @@ void CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( GLuint baseInstance, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3063,7 +3086,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts(const State &glStat GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3073,7 +3095,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts(const State &glStat angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_instanceCounts( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3083,7 +3104,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_instanceCounts( angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_baseInstances( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3093,7 +3113,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_baseInstances( angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_counts( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3105,7 +3124,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_counts( angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3117,7 +3135,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_instanceCounts( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3129,7 +3146,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_instanceCounts angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseVertices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3141,7 +3157,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseVertices( angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseInstances( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3152,18 +3167,15 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseInstances( GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureBlobCacheCallbacksANGLE_userParam(const State &glState, - bool isCallValid, GLSETBLOBPROCANGLE set, GLGETBLOBPROCANGLE get, const void *userParam, angle::ParamCapture *paramCapture); void CaptureGetPointervANGLE_params(const State &glState, - bool isCallValid, GLenum pname, void **params, angle::ParamCapture *paramCapture); void CaptureGetTexImageANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum format, @@ -3171,34 +3183,29 @@ void CaptureGetTexImageANGLE_pixels(const State &glState, void *pixels, angle::ParamCapture *paramCapture); void CaptureGetCompressedTexImageANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, void *pixels, angle::ParamCapture *paramCapture); void CaptureGetRenderbufferImageANGLE_pixels(const State &glState, - bool isCallValid, GLenum target, GLenum format, GLenum type, void *pixels, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterivANGLE_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterfvANGLE_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedANGLE_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -3206,7 +3213,6 @@ void CaptureDrawElementsInstancedANGLE_indices(const State &glState, GLsizei primcount, angle::ParamCapture *paramCapture); void CaptureTexStorageMemFlags2DANGLE_imageCreateInfoPNext(const State &glState, - bool isCallValid, TextureType targetPacked, GLsizei levels, GLenum internalFormat, @@ -3220,7 +3226,6 @@ void CaptureTexStorageMemFlags2DANGLE_imageCreateInfoPNext(const State &glState, angle::ParamCapture *paramCapture); void CaptureTexStorageMemFlags2DMultisampleANGLE_imageCreateInfoPNext( const State &glState, - bool isCallValid, TextureType targetPacked, GLsizei samples, GLenum internalFormat, @@ -3234,7 +3239,6 @@ void CaptureTexStorageMemFlags2DMultisampleANGLE_imageCreateInfoPNext( const void *imageCreateInfoPNext, angle::ParamCapture *paramCapture); void CaptureTexStorageMemFlags3DANGLE_imageCreateInfoPNext(const State &glState, - bool isCallValid, TextureType targetPacked, GLsizei levels, GLenum internalFormat, @@ -3249,7 +3253,6 @@ void CaptureTexStorageMemFlags3DANGLE_imageCreateInfoPNext(const State &glState, angle::ParamCapture *paramCapture); void CaptureTexStorageMemFlags3DMultisampleANGLE_imageCreateInfoPNext( const State &glState, - bool isCallValid, TextureType targetPacked, GLsizei samples, GLenum internalFormat, @@ -3264,21 +3267,18 @@ void CaptureTexStorageMemFlags3DMultisampleANGLE_imageCreateInfoPNext( const void *imageCreateInfoPNext, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysANGLE_firsts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedANGLE_firsts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3286,7 +3286,6 @@ void CaptureMultiDrawArraysInstancedANGLE_firsts(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3294,7 +3293,6 @@ void CaptureMultiDrawArraysInstancedANGLE_counts(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysInstancedANGLE_instanceCounts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -3302,7 +3300,6 @@ void CaptureMultiDrawArraysInstancedANGLE_instanceCounts(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3310,7 +3307,6 @@ void CaptureMultiDrawElementsANGLE_counts(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsANGLE_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3318,7 +3314,6 @@ void CaptureMultiDrawElementsANGLE_indices(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3327,7 +3322,6 @@ void CaptureMultiDrawElementsInstancedANGLE_counts(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedANGLE_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3336,7 +3330,6 @@ void CaptureMultiDrawElementsInstancedANGLE_indices(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsInstancedANGLE_instanceCounts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -3345,29 +3338,24 @@ void CaptureMultiDrawElementsInstancedANGLE_instanceCounts(const State &glState, GLsizei drawcount, angle::ParamCapture *paramCapture); void CaptureRequestExtensionANGLE_name(const State &glState, - bool isCallValid, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureDisableExtensionANGLE_name(const State &glState, - bool isCallValid, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetBooleanvRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *params, angle::ParamCapture *paramCapture); void CaptureGetBooleanvRobustANGLE_params(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *params, angle::ParamCapture *paramCapture); void CaptureGetBufferParameterivRobustANGLE_length(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -3375,7 +3363,6 @@ void CaptureGetBufferParameterivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetBufferParameterivRobustANGLE_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -3383,14 +3370,12 @@ void CaptureGetBufferParameterivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetFloatvRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetFloatvRobustANGLE_params(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, @@ -3398,7 +3383,6 @@ void CaptureGetFloatvRobustANGLE_params(const State &glState, angle::ParamCapture *paramCapture); void CaptureGetFramebufferAttachmentParameterivRobustANGLE_length( const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, @@ -3408,7 +3392,6 @@ void CaptureGetFramebufferAttachmentParameterivRobustANGLE_length( angle::ParamCapture *paramCapture); void CaptureGetFramebufferAttachmentParameterivRobustANGLE_params( const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, @@ -3417,21 +3400,18 @@ void CaptureGetFramebufferAttachmentParameterivRobustANGLE_params( GLint *params, angle::ParamCapture *paramCapture); void CaptureGetIntegervRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data, angle::ParamCapture *paramCapture); void CaptureGetIntegervRobustANGLE_data(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data, angle::ParamCapture *paramCapture); void CaptureGetProgramivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum pname, GLsizei bufSize, @@ -3439,7 +3419,6 @@ void CaptureGetProgramivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum pname, GLsizei bufSize, @@ -3447,7 +3426,6 @@ void CaptureGetProgramivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetRenderbufferParameterivRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -3455,7 +3433,6 @@ void CaptureGetRenderbufferParameterivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetRenderbufferParameterivRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -3463,7 +3440,6 @@ void CaptureGetRenderbufferParameterivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetShaderivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLenum pname, GLsizei bufSize, @@ -3471,7 +3447,6 @@ void CaptureGetShaderivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetShaderivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLenum pname, GLsizei bufSize, @@ -3479,7 +3454,6 @@ void CaptureGetShaderivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterfvRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -3487,7 +3461,6 @@ void CaptureGetTexParameterfvRobustANGLE_length(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -3495,7 +3468,6 @@ void CaptureGetTexParameterfvRobustANGLE_params(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterivRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -3503,7 +3475,6 @@ void CaptureGetTexParameterivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -3511,7 +3482,6 @@ void CaptureGetTexParameterivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetUniformfvRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -3519,7 +3489,6 @@ void CaptureGetUniformfvRobustANGLE_length(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetUniformfvRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -3527,7 +3496,6 @@ void CaptureGetUniformfvRobustANGLE_params(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetUniformivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -3535,7 +3503,6 @@ void CaptureGetUniformivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetUniformivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -3543,7 +3510,6 @@ void CaptureGetUniformivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribfvRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3551,7 +3517,6 @@ void CaptureGetVertexAttribfvRobustANGLE_length(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribfvRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3559,7 +3524,6 @@ void CaptureGetVertexAttribfvRobustANGLE_params(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribivRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3567,7 +3531,6 @@ void CaptureGetVertexAttribivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribivRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3575,7 +3538,6 @@ void CaptureGetVertexAttribivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribPointervRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3583,7 +3545,6 @@ void CaptureGetVertexAttribPointervRobustANGLE_length(const State &glState, void **pointer, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribPointervRobustANGLE_pointer(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3591,7 +3552,6 @@ void CaptureGetVertexAttribPointervRobustANGLE_pointer(const State &glState, void **pointer, angle::ParamCapture *paramCapture); void CaptureReadPixelsRobustANGLE_length(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -3605,7 +3565,6 @@ void CaptureReadPixelsRobustANGLE_length(const State &glState, void *pixels, angle::ParamCapture *paramCapture); void CaptureReadPixelsRobustANGLE_columns(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -3619,7 +3578,6 @@ void CaptureReadPixelsRobustANGLE_columns(const State &glState, void *pixels, angle::ParamCapture *paramCapture); void CaptureReadPixelsRobustANGLE_rows(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -3633,7 +3591,6 @@ void CaptureReadPixelsRobustANGLE_rows(const State &glState, void *pixels, angle::ParamCapture *paramCapture); void CaptureReadPixelsRobustANGLE_pixels(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -3647,7 +3604,6 @@ void CaptureReadPixelsRobustANGLE_pixels(const State &glState, void *pixels, angle::ParamCapture *paramCapture); void CaptureTexImage2DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -3660,21 +3616,18 @@ void CaptureTexImage2DRobustANGLE_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTexParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureTexParameterivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexSubImage2DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -3687,7 +3640,6 @@ void CaptureTexSubImage2DRobustANGLE_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTexImage3DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -3701,7 +3653,6 @@ void CaptureTexImage3DRobustANGLE_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTexSubImage3DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -3716,7 +3667,6 @@ void CaptureTexSubImage3DRobustANGLE_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureCompressedTexImage2DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -3728,7 +3678,6 @@ void CaptureCompressedTexImage2DRobustANGLE_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexSubImage2DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLsizei xoffset, @@ -3741,7 +3690,6 @@ void CaptureCompressedTexSubImage2DRobustANGLE_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexImage3DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -3754,7 +3702,6 @@ void CaptureCompressedTexImage3DRobustANGLE_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexSubImage3DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -3769,7 +3716,6 @@ void CaptureCompressedTexSubImage3DRobustANGLE_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureGetQueryivRobustANGLE_length(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLsizei bufSize, @@ -3777,7 +3723,6 @@ void CaptureGetQueryivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryivRobustANGLE_params(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLsizei bufSize, @@ -3785,7 +3730,6 @@ void CaptureGetQueryivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectuivRobustANGLE_length(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -3793,7 +3737,6 @@ void CaptureGetQueryObjectuivRobustANGLE_length(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectuivRobustANGLE_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -3801,7 +3744,6 @@ void CaptureGetQueryObjectuivRobustANGLE_params(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetBufferPointervRobustANGLE_length(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -3809,7 +3751,6 @@ void CaptureGetBufferPointervRobustANGLE_length(const State &glState, void **params, angle::ParamCapture *paramCapture); void CaptureGetBufferPointervRobustANGLE_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -3817,7 +3758,6 @@ void CaptureGetBufferPointervRobustANGLE_params(const State &glState, void **params, angle::ParamCapture *paramCapture); void CaptureGetIntegeri_vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -3825,7 +3765,6 @@ void CaptureGetIntegeri_vRobustANGLE_length(const State &glState, GLint *data, angle::ParamCapture *paramCapture); void CaptureGetIntegeri_vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -3833,7 +3772,6 @@ void CaptureGetIntegeri_vRobustANGLE_data(const State &glState, GLint *data, angle::ParamCapture *paramCapture); void CaptureGetInternalformativRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum internalformat, GLenum pname, @@ -3842,7 +3780,6 @@ void CaptureGetInternalformativRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetInternalformativRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum internalformat, GLenum pname, @@ -3851,7 +3788,6 @@ void CaptureGetInternalformativRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribIivRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3859,7 +3795,6 @@ void CaptureGetVertexAttribIivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribIivRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3867,7 +3802,6 @@ void CaptureGetVertexAttribIivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribIuivRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3875,7 +3809,6 @@ void CaptureGetVertexAttribIuivRobustANGLE_length(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetVertexAttribIuivRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -3883,7 +3816,6 @@ void CaptureGetVertexAttribIuivRobustANGLE_params(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetUniformuivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -3891,7 +3823,6 @@ void CaptureGetUniformuivRobustANGLE_length(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetUniformuivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -3899,7 +3830,6 @@ void CaptureGetUniformuivRobustANGLE_params(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformBlockivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformBlockIndex uniformBlockIndexPacked, GLenum pname, @@ -3908,7 +3838,6 @@ void CaptureGetActiveUniformBlockivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetActiveUniformBlockivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformBlockIndex uniformBlockIndexPacked, GLenum pname, @@ -3917,21 +3846,18 @@ void CaptureGetActiveUniformBlockivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetInteger64vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetInteger64vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetInteger64i_vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -3939,7 +3865,6 @@ void CaptureGetInteger64i_vRobustANGLE_length(const State &glState, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetInteger64i_vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -3947,7 +3872,6 @@ void CaptureGetInteger64i_vRobustANGLE_data(const State &glState, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetBufferParameteri64vRobustANGLE_length(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -3955,7 +3879,6 @@ void CaptureGetBufferParameteri64vRobustANGLE_length(const State &glState, GLint64 *params, angle::ParamCapture *paramCapture); void CaptureGetBufferParameteri64vRobustANGLE_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -3963,21 +3886,18 @@ void CaptureGetBufferParameteri64vRobustANGLE_params(const State &glState, GLint64 *params, angle::ParamCapture *paramCapture); void CaptureSamplerParameterivRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLuint pname, GLsizei bufSize, const GLint *param, angle::ParamCapture *paramCapture); void CaptureSamplerParameterfvRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, const GLfloat *param, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterivRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -3985,7 +3905,6 @@ void CaptureGetSamplerParameterivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterivRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -3993,7 +3912,6 @@ void CaptureGetSamplerParameterivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterfvRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -4001,7 +3919,6 @@ void CaptureGetSamplerParameterfvRobustANGLE_length(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -4009,7 +3926,6 @@ void CaptureGetSamplerParameterfvRobustANGLE_params(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetFramebufferParameterivRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -4017,7 +3933,6 @@ void CaptureGetFramebufferParameterivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetFramebufferParameterivRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -4025,7 +3940,6 @@ void CaptureGetFramebufferParameterivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramInterfaceivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLenum pname, @@ -4034,7 +3948,6 @@ void CaptureGetProgramInterfaceivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramInterfaceivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, GLenum pname, @@ -4043,7 +3956,6 @@ void CaptureGetProgramInterfaceivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetBooleani_vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -4051,7 +3963,6 @@ void CaptureGetBooleani_vRobustANGLE_length(const State &glState, GLboolean *data, angle::ParamCapture *paramCapture); void CaptureGetBooleani_vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -4059,7 +3970,6 @@ void CaptureGetBooleani_vRobustANGLE_data(const State &glState, GLboolean *data, angle::ParamCapture *paramCapture); void CaptureGetMultisamplefvRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLsizei bufSize, @@ -4067,7 +3977,6 @@ void CaptureGetMultisamplefvRobustANGLE_length(const State &glState, GLfloat *val, angle::ParamCapture *paramCapture); void CaptureGetMultisamplefvRobustANGLE_val(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLsizei bufSize, @@ -4075,7 +3984,6 @@ void CaptureGetMultisamplefvRobustANGLE_val(const State &glState, GLfloat *val, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterivRobustANGLE_length(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -4084,7 +3992,6 @@ void CaptureGetTexLevelParameterivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterivRobustANGLE_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -4093,7 +4000,6 @@ void CaptureGetTexLevelParameterivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterfvRobustANGLE_length(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -4102,7 +4008,6 @@ void CaptureGetTexLevelParameterfvRobustANGLE_length(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexLevelParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -4111,21 +4016,18 @@ void CaptureGetTexLevelParameterfvRobustANGLE_params(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetPointervRobustANGLERobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, void **params, angle::ParamCapture *paramCapture); void CaptureGetPointervRobustANGLERobustANGLE_params(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, void **params, angle::ParamCapture *paramCapture); void CaptureReadnPixelsRobustANGLE_length(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -4139,7 +4041,6 @@ void CaptureReadnPixelsRobustANGLE_length(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureReadnPixelsRobustANGLE_columns(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -4153,7 +4054,6 @@ void CaptureReadnPixelsRobustANGLE_columns(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureReadnPixelsRobustANGLE_rows(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -4167,7 +4067,6 @@ void CaptureReadnPixelsRobustANGLE_rows(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureReadnPixelsRobustANGLE_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -4181,7 +4080,6 @@ void CaptureReadnPixelsRobustANGLE_data(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureGetnUniformfvRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -4189,7 +4087,6 @@ void CaptureGetnUniformfvRobustANGLE_length(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformfvRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -4197,7 +4094,6 @@ void CaptureGetnUniformfvRobustANGLE_params(const State &glState, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -4205,7 +4101,6 @@ void CaptureGetnUniformivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -4213,7 +4108,6 @@ void CaptureGetnUniformivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformuivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -4221,7 +4115,6 @@ void CaptureGetnUniformuivRobustANGLE_length(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformuivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, @@ -4229,21 +4122,18 @@ void CaptureGetnUniformuivRobustANGLE_params(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureTexParameterIivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexParameterIuivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, const GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIivRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -4251,7 +4141,6 @@ void CaptureGetTexParameterIivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -4259,7 +4148,6 @@ void CaptureGetTexParameterIivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIuivRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -4267,7 +4155,6 @@ void CaptureGetTexParameterIuivRobustANGLE_length(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIuivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -4275,21 +4162,18 @@ void CaptureGetTexParameterIuivRobustANGLE_params(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIivRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, const GLint *param, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIuivRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, const GLuint *param, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIivRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -4297,7 +4181,6 @@ void CaptureGetSamplerParameterIivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIivRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -4305,7 +4188,6 @@ void CaptureGetSamplerParameterIivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIuivRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -4313,7 +4195,6 @@ void CaptureGetSamplerParameterIuivRobustANGLE_length(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIuivRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLsizei bufSize, @@ -4321,7 +4202,6 @@ void CaptureGetSamplerParameterIuivRobustANGLE_params(const State &glState, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectivRobustANGLE_length(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -4329,7 +4209,6 @@ void CaptureGetQueryObjectivRobustANGLE_length(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectivRobustANGLE_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -4337,7 +4216,6 @@ void CaptureGetQueryObjectivRobustANGLE_params(const State &glState, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjecti64vRobustANGLE_length(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -4345,7 +4223,6 @@ void CaptureGetQueryObjecti64vRobustANGLE_length(const State &glState, GLint64 *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjecti64vRobustANGLE_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -4353,7 +4230,6 @@ void CaptureGetQueryObjecti64vRobustANGLE_params(const State &glState, GLint64 *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectui64vRobustANGLE_length(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, @@ -4361,55 +4237,14 @@ void CaptureGetQueryObjectui64vRobustANGLE_length(const State &glState, GLuint64 *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectui64vRobustANGLE_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params, angle::ParamCapture *paramCapture); -void CaptureFramebufferPixelLocalClearValuefvANGLE_value(const State &glState, - bool isCallValid, - GLint plane, - const GLfloat *value, - angle::ParamCapture *paramCapture); -void CaptureFramebufferPixelLocalClearValueivANGLE_value(const State &glState, - bool isCallValid, - GLint plane, - const GLint *value, - angle::ParamCapture *paramCapture); -void CaptureFramebufferPixelLocalClearValueuivANGLE_value(const State &glState, - bool isCallValid, - GLint plane, - const GLuint *value, - angle::ParamCapture *paramCapture); -void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState, - bool isCallValid, - GLsizei n, - const GLenum *loadops, - angle::ParamCapture *paramCapture); -void CaptureEndPixelLocalStorageANGLE_storeops(const State &glState, - bool isCallValid, - GLsizei n, - const GLenum *storeops, - angle::ParamCapture *paramCapture); -void CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLfloat *params, - angle::ParamCapture *paramCapture); -void CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLint *params, - angle::ParamCapture *paramCapture); void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_length( const State &glState, - bool isCallValid, GLint plane, GLenum pname, GLsizei bufSize, @@ -4418,7 +4253,6 @@ void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_length( angle::ParamCapture *paramCapture); void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_params( const State &glState, - bool isCallValid, GLint plane, GLenum pname, GLsizei bufSize, @@ -4427,7 +4261,6 @@ void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_params( angle::ParamCapture *paramCapture); void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_length( const State &glState, - bool isCallValid, GLint plane, GLenum pname, GLsizei bufSize, @@ -4436,77 +4269,92 @@ void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_length( angle::ParamCapture *paramCapture); void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_params( const State &glState, - bool isCallValid, GLint plane, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params, angle::ParamCapture *paramCapture); +void CaptureFramebufferPixelLocalClearValuefvANGLE_value(const State &glState, + GLint plane, + const GLfloat *value, + angle::ParamCapture *paramCapture); +void CaptureFramebufferPixelLocalClearValueivANGLE_value(const State &glState, + GLint plane, + const GLint *value, + angle::ParamCapture *paramCapture); +void CaptureFramebufferPixelLocalClearValueuivANGLE_value(const State &glState, + GLint plane, + const GLuint *value, + angle::ParamCapture *paramCapture); +void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState, + GLsizei n, + const GLenum *loadops, + angle::ParamCapture *paramCapture); +void CaptureEndPixelLocalStorageANGLE_storeops(const State &glState, + GLsizei n, + const GLenum *storeops, + angle::ParamCapture *paramCapture); +void CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params( + const State &glState, + GLint plane, + GLenum pname, + GLfloat *params, + angle::ParamCapture *paramCapture); +void CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params( + const State &glState, + GLint plane, + GLenum pname, + GLint *params, + angle::ParamCapture *paramCapture); void CaptureGetMultisamplefvANGLE_val(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLfloat *val, angle::ParamCapture *paramCapture); void CaptureGetTranslatedShaderSourceANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, GLchar *source, angle::ParamCapture *paramCapture); void CaptureGetTranslatedShaderSourceANGLE_source(const State &glState, - bool isCallValid, ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, GLchar *source, angle::ParamCapture *paramCapture); void CaptureAcquireTexturesANGLE_texturesPacked(const State &glState, - bool isCallValid, GLuint numTextures, const TextureID *texturesPacked, const GLenum *layouts, angle::ParamCapture *paramCapture); void CaptureAcquireTexturesANGLE_layouts(const State &glState, - bool isCallValid, GLuint numTextures, const TextureID *texturesPacked, const GLenum *layouts, angle::ParamCapture *paramCapture); void CaptureReleaseTexturesANGLE_texturesPacked(const State &glState, - bool isCallValid, GLuint numTextures, const TextureID *texturesPacked, GLenum *layouts, angle::ParamCapture *paramCapture); void CaptureReleaseTexturesANGLE_layouts(const State &glState, - bool isCallValid, GLuint numTextures, const TextureID *texturesPacked, GLenum *layouts, angle::ParamCapture *paramCapture); void CaptureBindUniformLocationCHROMIUM_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureEGLImageTargetTexStorageEXT_attrib_list(const State &glState, - bool isCallValid, GLenum target, egl::ImageID imagePacked, const GLint *attrib_list, angle::ParamCapture *paramCapture); -void CaptureEGLImageTargetTextureStorageEXT_attrib_list(const State &glState, - bool isCallValid, - GLuint texture, - egl::ImageID imagePacked, - const GLint *attrib_list, - angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedBaseInstanceEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -4516,7 +4364,6 @@ void CaptureDrawElementsInstancedBaseInstanceEXT_indices(const State &glState, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT_indices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -4526,38 +4373,32 @@ void CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT_indices( GLuint baseinstance, angle::ParamCapture *paramCapture); void CaptureBindFragDataLocationEXT_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint color, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureBindFragDataLocationIndexedEXT_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLuint colorNumber, GLuint index, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetFragDataIndexEXT_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureGetProgramResourceLocationIndexEXT_name(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum programInterface, const GLchar *name, angle::ParamCapture *paramCapture); void CaptureBufferStorageEXT_data(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLsizeiptr size, const void *data, GLbitfield flags, angle::ParamCapture *paramCapture); void CaptureClearTexImageEXT_data(const State &glState, - bool isCallValid, TextureID texturePacked, GLint level, GLenum format, @@ -4565,7 +4406,6 @@ void CaptureClearTexImageEXT_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureClearTexSubImageEXT_data(const State &glState, - bool isCallValid, TextureID texturePacked, GLint level, GLint xoffset, @@ -4579,7 +4419,6 @@ void CaptureClearTexSubImageEXT_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureGetObjectLabelEXT_length(const State &glState, - bool isCallValid, GLenum type, GLuint object, GLsizei bufSize, @@ -4587,7 +4426,6 @@ void CaptureGetObjectLabelEXT_length(const State &glState, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectLabelEXT_label(const State &glState, - bool isCallValid, GLenum type, GLuint object, GLsizei bufSize, @@ -4595,80 +4433,66 @@ void CaptureGetObjectLabelEXT_label(const State &glState, GLchar *label, angle::ParamCapture *paramCapture); void CaptureLabelObjectEXT_label(const State &glState, - bool isCallValid, GLenum type, GLuint object, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CaptureInsertEventMarkerEXT_marker(const State &glState, - bool isCallValid, GLsizei length, const GLchar *marker, angle::ParamCapture *paramCapture); void CapturePushGroupMarkerEXT_marker(const State &glState, - bool isCallValid, GLsizei length, const GLchar *marker, angle::ParamCapture *paramCapture); void CaptureDiscardFramebufferEXT_attachments(const State &glState, - bool isCallValid, GLenum target, GLsizei numAttachments, const GLenum *attachments, angle::ParamCapture *paramCapture); void CaptureDeleteQueriesEXT_idsPacked(const State &glState, - bool isCallValid, GLsizei n, const QueryID *idsPacked, angle::ParamCapture *paramCapture); void CaptureGenQueriesEXT_idsPacked(const State &glState, - bool isCallValid, GLsizei n, QueryID *idsPacked, angle::ParamCapture *paramCapture); void CaptureGetInteger64vEXT_data(const State &glState, - bool isCallValid, GLenum pname, GLint64 *data, angle::ParamCapture *paramCapture); void CaptureGetQueryObjecti64vEXT_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLint64 *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectivEXT_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectui64vEXT_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLuint64 *params, angle::ParamCapture *paramCapture); void CaptureGetQueryObjectuivEXT_params(const State &glState, - bool isCallValid, QueryID idPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetQueryivEXT_params(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureDrawBuffersEXT_bufs(const State &glState, - bool isCallValid, GLsizei n, const GLenum *bufs, angle::ParamCapture *paramCapture); void CaptureDrawElementsBaseVertexEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -4676,7 +4500,6 @@ void CaptureDrawElementsBaseVertexEXT_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedBaseVertexEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -4685,7 +4508,6 @@ void CaptureDrawElementsInstancedBaseVertexEXT_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawRangeElementsBaseVertexEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLuint start, GLuint end, @@ -4695,7 +4517,6 @@ void CaptureDrawRangeElementsBaseVertexEXT_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsBaseVertexEXT_count(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *count, DrawElementsType typePacked, @@ -4704,7 +4525,6 @@ void CaptureMultiDrawElementsBaseVertexEXT_count(const State &glState, const GLint *basevertex, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsBaseVertexEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *count, DrawElementsType typePacked, @@ -4713,7 +4533,6 @@ void CaptureMultiDrawElementsBaseVertexEXT_indices(const State &glState, const GLint *basevertex, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsBaseVertexEXT_basevertex(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *count, DrawElementsType typePacked, @@ -4722,55 +4541,84 @@ void CaptureMultiDrawElementsBaseVertexEXT_basevertex(const State &glState, const GLint *basevertex, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, const void *indices, GLsizei primcount, angle::ParamCapture *paramCapture); +void CaptureGetFragmentShadingRatesEXT_count(const State &glState, + GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates, + angle::ParamCapture *paramCapture); +void CaptureGetFragmentShadingRatesEXT_shadingRates(const State &glState, + GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates, + angle::ParamCapture *paramCapture); void CaptureCreateMemoryObjectsEXT_memoryObjectsPacked(const State &glState, - bool isCallValid, GLsizei n, MemoryObjectID *memoryObjectsPacked, angle::ParamCapture *paramCapture); void CaptureDeleteMemoryObjectsEXT_memoryObjectsPacked(const State &glState, - bool isCallValid, GLsizei n, const MemoryObjectID *memoryObjectsPacked, angle::ParamCapture *paramCapture); void CaptureGetMemoryObjectParameterivEXT_params(const State &glState, - bool isCallValid, MemoryObjectID memoryObjectPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetUnsignedBytevEXT_data(const State &glState, - bool isCallValid, GLenum pname, GLubyte *data, angle::ParamCapture *paramCapture); void CaptureGetUnsignedBytei_vEXT_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLubyte *data, angle::ParamCapture *paramCapture); void CaptureMemoryObjectParameterivEXT_params(const State &glState, - bool isCallValid, MemoryObjectID memoryObjectPacked, GLenum pname, const GLint *params, angle::ParamCapture *paramCapture); +void CaptureMultiDrawArraysEXT_first(const State &glState, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount, + angle::ParamCapture *paramCapture); +void CaptureMultiDrawArraysEXT_count(const State &glState, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount, + angle::ParamCapture *paramCapture); +void CaptureMultiDrawElementsEXT_count(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount, + angle::ParamCapture *paramCapture); +void CaptureMultiDrawElementsEXT_indices(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount, + angle::ParamCapture *paramCapture); void CaptureMultiDrawArraysIndirectEXT_indirect(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const void *indirect, GLsizei drawcount, GLsizei stride, angle::ParamCapture *paramCapture); void CaptureMultiDrawElementsIndirectEXT_indirect(const State &glState, - bool isCallValid, PrimitiveMode modePacked, DrawElementsType typePacked, const void *indirect, @@ -4778,21 +4626,18 @@ void CaptureMultiDrawElementsIndirectEXT_indirect(const State &glState, GLsizei stride, angle::ParamCapture *paramCapture); void CaptureGetnUniformfvEXT_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformivEXT_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLint *params, angle::ParamCapture *paramCapture); void CaptureReadnPixelsEXT_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -4803,29 +4648,24 @@ void CaptureReadnPixelsEXT_data(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureDeleteSemaphoresEXT_semaphoresPacked(const State &glState, - bool isCallValid, GLsizei n, const SemaphoreID *semaphoresPacked, angle::ParamCapture *paramCapture); void CaptureGenSemaphoresEXT_semaphoresPacked(const State &glState, - bool isCallValid, GLsizei n, SemaphoreID *semaphoresPacked, angle::ParamCapture *paramCapture); void CaptureGetSemaphoreParameterui64vEXT_params(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLenum pname, GLuint64 *params, angle::ParamCapture *paramCapture); void CaptureSemaphoreParameterui64vEXT_params(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLenum pname, const GLuint64 *params, angle::ParamCapture *paramCapture); void CaptureSignalSemaphoreEXT_buffersPacked(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLuint numBufferBarriers, const BufferID *buffersPacked, @@ -4834,7 +4674,6 @@ void CaptureSignalSemaphoreEXT_buffersPacked(const State &glState, const GLenum *dstLayouts, angle::ParamCapture *paramCapture); void CaptureSignalSemaphoreEXT_texturesPacked(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLuint numBufferBarriers, const BufferID *buffersPacked, @@ -4843,7 +4682,6 @@ void CaptureSignalSemaphoreEXT_texturesPacked(const State &glState, const GLenum *dstLayouts, angle::ParamCapture *paramCapture); void CaptureSignalSemaphoreEXT_dstLayouts(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLuint numBufferBarriers, const BufferID *buffersPacked, @@ -4852,7 +4690,6 @@ void CaptureSignalSemaphoreEXT_dstLayouts(const State &glState, const GLenum *dstLayouts, angle::ParamCapture *paramCapture); void CaptureWaitSemaphoreEXT_buffersPacked(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLuint numBufferBarriers, const BufferID *buffersPacked, @@ -4861,7 +4698,6 @@ void CaptureWaitSemaphoreEXT_buffersPacked(const State &glState, const GLenum *srcLayouts, angle::ParamCapture *paramCapture); void CaptureWaitSemaphoreEXT_texturesPacked(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLuint numBufferBarriers, const BufferID *buffersPacked, @@ -4870,7 +4706,6 @@ void CaptureWaitSemaphoreEXT_texturesPacked(const State &glState, const GLenum *srcLayouts, angle::ParamCapture *paramCapture); void CaptureWaitSemaphoreEXT_srcLayouts(const State &glState, - bool isCallValid, SemaphoreID semaphorePacked, GLuint numBufferBarriers, const BufferID *buffersPacked, @@ -4879,127 +4714,108 @@ void CaptureWaitSemaphoreEXT_srcLayouts(const State &glState, const GLenum *srcLayouts, angle::ParamCapture *paramCapture); void CaptureCreateShaderProgramvEXT_strings(const State &glState, - bool isCallValid, ShaderType typePacked, GLsizei count, - const GLchar **strings, + const GLchar *const *strings, angle::ParamCapture *paramCapture); void CaptureDeleteProgramPipelinesEXT_pipelinesPacked(const State &glState, - bool isCallValid, GLsizei n, const ProgramPipelineID *pipelinesPacked, angle::ParamCapture *paramCapture); void CaptureGenProgramPipelinesEXT_pipelinesPacked(const State &glState, - bool isCallValid, GLsizei n, ProgramPipelineID *pipelinesPacked, angle::ParamCapture *paramCapture); void CaptureGetProgramPipelineInfoLogEXT_length(const State &glState, - bool isCallValid, ProgramPipelineID pipelinePacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetProgramPipelineInfoLogEXT_infoLog(const State &glState, - bool isCallValid, ProgramPipelineID pipelinePacked, GLsizei bufSize, GLsizei *length, GLchar *infoLog, angle::ParamCapture *paramCapture); void CaptureGetProgramPipelineivEXT_params(const State &glState, - bool isCallValid, ProgramPipelineID pipelinePacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureProgramUniform1fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform1ivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform1uivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform2fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform2ivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform2uivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform3fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform3ivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform3uivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform4fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform4ivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniform4uivEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, const GLuint *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix2fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5007,7 +4823,6 @@ void CaptureProgramUniformMatrix2fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix2x3fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5015,7 +4830,6 @@ void CaptureProgramUniformMatrix2x3fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix2x4fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5023,7 +4837,6 @@ void CaptureProgramUniformMatrix2x4fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix3fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5031,7 +4844,6 @@ void CaptureProgramUniformMatrix3fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix3x2fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5039,7 +4851,6 @@ void CaptureProgramUniformMatrix3x2fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix3x4fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5047,7 +4858,6 @@ void CaptureProgramUniformMatrix3x4fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix4fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5055,7 +4865,6 @@ void CaptureProgramUniformMatrix4fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix4x2fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5063,7 +4872,6 @@ void CaptureProgramUniformMatrix4x2fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureProgramUniformMatrix4x3fvEXT_value(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei count, @@ -5071,55 +4879,46 @@ void CaptureProgramUniformMatrix4x3fvEXT_value(const State &glState, const GLfloat *value, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIivEXT_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIuivEXT_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIivEXT_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIuivEXT_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIivEXT_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLint *param, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIuivEXT_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLuint *param, angle::ParamCapture *paramCapture); void CaptureTexParameterIivEXT_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexParameterIuivEXT_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLuint *params, angle::ParamCapture *paramCapture); void CaptureTexStorageAttribs2DEXT_attrib_list(const State &glState, - bool isCallValid, GLenum target, GLsizei levels, GLenum internalformat, @@ -5128,7 +4927,6 @@ void CaptureTexStorageAttribs2DEXT_attrib_list(const State &glState, const GLint *attrib_list, angle::ParamCapture *paramCapture); void CaptureTexStorageAttribs3DEXT_attrib_list(const State &glState, - bool isCallValid, GLenum target, GLsizei levels, GLenum internalformat, @@ -5138,12 +4936,10 @@ void CaptureTexStorageAttribs3DEXT_attrib_list(const State &glState, const GLint *attrib_list, angle::ParamCapture *paramCapture); void CaptureDebugMessageCallbackKHR_userParam(const State &glState, - bool isCallValid, GLDEBUGPROCKHR callback, const void *userParam, angle::ParamCapture *paramCapture); void CaptureDebugMessageControlKHR_ids(const State &glState, - bool isCallValid, GLenum source, GLenum type, GLenum severity, @@ -5152,7 +4948,6 @@ void CaptureDebugMessageControlKHR_ids(const State &glState, GLboolean enabled, angle::ParamCapture *paramCapture); void CaptureDebugMessageInsertKHR_buf(const State &glState, - bool isCallValid, GLenum source, GLenum type, GLuint id, @@ -5161,7 +4956,6 @@ void CaptureDebugMessageInsertKHR_buf(const State &glState, const GLchar *buf, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLogKHR_sources(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -5172,7 +4966,6 @@ void CaptureGetDebugMessageLogKHR_sources(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLogKHR_types(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -5183,7 +4976,6 @@ void CaptureGetDebugMessageLogKHR_types(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLogKHR_ids(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -5194,7 +4986,6 @@ void CaptureGetDebugMessageLogKHR_ids(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLogKHR_severities(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -5205,7 +4996,6 @@ void CaptureGetDebugMessageLogKHR_severities(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLogKHR_lengths(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -5216,7 +5006,6 @@ void CaptureGetDebugMessageLogKHR_lengths(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetDebugMessageLogKHR_messageLog(const State &glState, - bool isCallValid, GLuint count, GLsizei bufSize, GLenum *sources, @@ -5227,7 +5016,6 @@ void CaptureGetDebugMessageLogKHR_messageLog(const State &glState, GLchar *messageLog, angle::ParamCapture *paramCapture); void CaptureGetObjectLabelKHR_length(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei bufSize, @@ -5235,7 +5023,6 @@ void CaptureGetObjectLabelKHR_length(const State &glState, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectLabelKHR_label(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei bufSize, @@ -5243,80 +5030,68 @@ void CaptureGetObjectLabelKHR_label(const State &glState, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectPtrLabelKHR_ptr(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectPtrLabelKHR_length(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetObjectPtrLabelKHR_label(const State &glState, - bool isCallValid, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label, angle::ParamCapture *paramCapture); void CaptureGetPointervKHR_params(const State &glState, - bool isCallValid, GLenum pname, void **params, angle::ParamCapture *paramCapture); void CaptureObjectLabelKHR_label(const State &glState, - bool isCallValid, GLenum identifier, GLuint name, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CaptureObjectPtrLabelKHR_ptr(const State &glState, - bool isCallValid, const void *ptr, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CaptureObjectPtrLabelKHR_label(const State &glState, - bool isCallValid, const void *ptr, GLsizei length, const GLchar *label, angle::ParamCapture *paramCapture); void CapturePushDebugGroupKHR_message(const State &glState, - bool isCallValid, GLenum source, GLuint id, GLsizei length, const GLchar *message, angle::ParamCapture *paramCapture); void CaptureGetnUniformfvKHR_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformivKHR_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetnUniformuivKHR_params(const State &glState, - bool isCallValid, ShaderProgramID programPacked, UniformLocation locationPacked, GLsizei bufSize, GLuint *params, angle::ParamCapture *paramCapture); void CaptureReadnPixelsKHR_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -5327,29 +5102,24 @@ void CaptureReadnPixelsKHR_data(const State &glState, void *data, angle::ParamCapture *paramCapture); void CaptureGetFramebufferParameterivMESA_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureDeleteFencesNV_fencesPacked(const State &glState, - bool isCallValid, GLsizei n, const FenceNVID *fencesPacked, angle::ParamCapture *paramCapture); void CaptureGenFencesNV_fencesPacked(const State &glState, - bool isCallValid, GLsizei n, FenceNVID *fencesPacked, angle::ParamCapture *paramCapture); void CaptureGetFenceivNV_params(const State &glState, - bool isCallValid, FenceNVID fencePacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureDrawElementsBaseVertexOES_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -5357,7 +5127,6 @@ void CaptureDrawElementsBaseVertexOES_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawElementsInstancedBaseVertexOES_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -5366,7 +5135,6 @@ void CaptureDrawElementsInstancedBaseVertexOES_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawRangeElementsBaseVertexOES_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLuint start, GLuint end, @@ -5376,56 +5144,45 @@ void CaptureDrawRangeElementsBaseVertexOES_indices(const State &glState, GLint basevertex, angle::ParamCapture *paramCapture); void CaptureDrawTexfvOES_coords(const State &glState, - bool isCallValid, const GLfloat *coords, angle::ParamCapture *paramCapture); void CaptureDrawTexivOES_coords(const State &glState, - bool isCallValid, const GLint *coords, angle::ParamCapture *paramCapture); void CaptureDrawTexsvOES_coords(const State &glState, - bool isCallValid, const GLshort *coords, angle::ParamCapture *paramCapture); void CaptureDrawTexxvOES_coords(const State &glState, - bool isCallValid, const GLfixed *coords, angle::ParamCapture *paramCapture); void CaptureDeleteFramebuffersOES_framebuffersPacked(const State &glState, - bool isCallValid, GLsizei n, const FramebufferID *framebuffersPacked, angle::ParamCapture *paramCapture); void CaptureDeleteRenderbuffersOES_renderbuffersPacked(const State &glState, - bool isCallValid, GLsizei n, const RenderbufferID *renderbuffersPacked, angle::ParamCapture *paramCapture); void CaptureGenFramebuffersOES_framebuffersPacked(const State &glState, - bool isCallValid, GLsizei n, FramebufferID *framebuffersPacked, angle::ParamCapture *paramCapture); void CaptureGenRenderbuffersOES_renderbuffersPacked(const State &glState, - bool isCallValid, GLsizei n, RenderbufferID *renderbuffersPacked, angle::ParamCapture *paramCapture); void CaptureGetFramebufferAttachmentParameterivOES_params(const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetRenderbufferParameterivOES_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetProgramBinaryOES_length(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, @@ -5433,7 +5190,6 @@ void CaptureGetProgramBinaryOES_length(const State &glState, void *binary, angle::ParamCapture *paramCapture); void CaptureGetProgramBinaryOES_binaryFormat(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, @@ -5441,7 +5197,6 @@ void CaptureGetProgramBinaryOES_binaryFormat(const State &glState, void *binary, angle::ParamCapture *paramCapture); void CaptureGetProgramBinaryOES_binary(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, @@ -5449,50 +5204,42 @@ void CaptureGetProgramBinaryOES_binary(const State &glState, void *binary, angle::ParamCapture *paramCapture); void CaptureProgramBinaryOES_binary(const State &glState, - bool isCallValid, ShaderProgramID programPacked, GLenum binaryFormat, const void *binary, GLint length, angle::ParamCapture *paramCapture); void CaptureGetBufferPointervOES_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, void **params, angle::ParamCapture *paramCapture); void CaptureMatrixIndexPointerOES_pointer(const State &glState, - bool isCallValid, GLint size, GLenum type, GLsizei stride, const void *pointer, angle::ParamCapture *paramCapture); void CaptureWeightPointerOES_pointer(const State &glState, - bool isCallValid, GLint size, GLenum type, GLsizei stride, const void *pointer, angle::ParamCapture *paramCapture); void CapturePointSizePointerOES_pointer(const State &glState, - bool isCallValid, VertexAttribType typePacked, GLsizei stride, const void *pointer, angle::ParamCapture *paramCapture); void CaptureQueryMatrixxOES_mantissa(const State &glState, - bool isCallValid, GLfixed *mantissa, GLint *exponent, angle::ParamCapture *paramCapture); void CaptureQueryMatrixxOES_exponent(const State &glState, - bool isCallValid, GLfixed *mantissa, GLint *exponent, angle::ParamCapture *paramCapture); void CaptureCompressedTexImage3DOES_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -5504,7 +5251,6 @@ void CaptureCompressedTexImage3DOES_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureCompressedTexSubImage3DOES_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -5518,7 +5264,6 @@ void CaptureCompressedTexSubImage3DOES_data(const State &glState, const void *data, angle::ParamCapture *paramCapture); void CaptureTexImage3DOES_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -5531,7 +5276,6 @@ void CaptureTexImage3DOES_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureTexSubImage3DOES_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -5545,101 +5289,84 @@ void CaptureTexSubImage3DOES_pixels(const State &glState, const void *pixels, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIivOES_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetSamplerParameterIuivOES_params(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIivOES_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexParameterIuivOES_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLuint *params, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIivOES_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLint *param, angle::ParamCapture *paramCapture); void CaptureSamplerParameterIuivOES_param(const State &glState, - bool isCallValid, SamplerID samplerPacked, GLenum pname, const GLuint *param, angle::ParamCapture *paramCapture); void CaptureTexParameterIivOES_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexParameterIuivOES_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, const GLuint *params, angle::ParamCapture *paramCapture); void CaptureGetTexGenfvOES_params(const State &glState, - bool isCallValid, GLenum coord, GLenum pname, GLfloat *params, angle::ParamCapture *paramCapture); void CaptureGetTexGenivOES_params(const State &glState, - bool isCallValid, GLenum coord, GLenum pname, GLint *params, angle::ParamCapture *paramCapture); void CaptureGetTexGenxvOES_params(const State &glState, - bool isCallValid, GLenum coord, GLenum pname, GLfixed *params, angle::ParamCapture *paramCapture); void CaptureTexGenfvOES_params(const State &glState, - bool isCallValid, GLenum coord, GLenum pname, const GLfloat *params, angle::ParamCapture *paramCapture); void CaptureTexGenivOES_params(const State &glState, - bool isCallValid, GLenum coord, GLenum pname, const GLint *params, angle::ParamCapture *paramCapture); void CaptureTexGenxvOES_params(const State &glState, - bool isCallValid, GLenum coord, GLenum pname, const GLfixed *params, angle::ParamCapture *paramCapture); void CaptureDeleteVertexArraysOES_arraysPacked(const State &glState, - bool isCallValid, GLsizei n, const VertexArrayID *arraysPacked, angle::ParamCapture *paramCapture); void CaptureGenVertexArraysOES_arraysPacked(const State &glState, - bool isCallValid, GLsizei n, VertexArrayID *arraysPacked, angle::ParamCapture *paramCapture); void CaptureFramebufferFoveationConfigQCOM_providedFeatures(const State &glState, - bool isCallValid, FramebufferID framebufferPacked, GLuint numLayers, GLuint focalPointsPerLayer, diff --git a/src/libANGLE/capture/capture_gles_ext_params.cpp b/src/libANGLE/capture/capture_gles_ext_params.cpp index 531ac6d4b51..c2a27782940 100644 --- a/src/libANGLE/capture/capture_gles_ext_params.cpp +++ b/src/libANGLE/capture/capture_gles_ext_params.cpp @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// capture_glesext_params.cpp: +// capture_gles_ext_params.cpp: // Pointer parameter capture functions for the OpenGL ES extension entry points. #include "libANGLE/capture/capture_gles_ext_autogen.h" @@ -16,9 +16,163 @@ using namespace angle; namespace gl { + +// GL_AMD_performance_monitor +void CaptureDeletePerfMonitorsAMD_monitors(const State &glState, + GLsizei n, + GLuint *monitors, + angle::ParamCapture *paramCapture) +{ + CaptureArray(monitors, n, paramCapture); +} + +void CaptureGenPerfMonitorsAMD_monitors(const State &glState, + GLsizei n, + GLuint *monitors, + angle::ParamCapture *paramCapture) +{ + CaptureArray(monitors, n, paramCapture); +} + +void CaptureGetPerfMonitorCounterDataAMD_data(const State &glState, + GLuint monitor, + GLenum pname, + GLsizei dataSize, + GLuint *data, + GLint *bytesWritten, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = dataSize; +} + +void CaptureGetPerfMonitorCounterDataAMD_bytesWritten(const State &glState, + GLuint monitor, + GLenum pname, + GLsizei dataSize, + GLuint *data, + GLint *bytesWritten, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = sizeof(GLint); +} + +void CaptureGetPerfMonitorCounterInfoAMD_data(const State &glState, + GLuint group, + GLuint counter, + GLenum pname, + void *data, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureGetPerfMonitorCounterStringAMD_length(const State &glState, + GLuint group, + GLuint counter, + GLsizei bufSize, + GLsizei *length, + GLchar *counterString, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = sizeof(GLsizei); +} + +void CaptureGetPerfMonitorCounterStringAMD_counterString(const State &glState, + GLuint group, + GLuint counter, + GLsizei bufSize, + GLsizei *length, + GLchar *counterString, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = bufSize; +} + +void CaptureGetPerfMonitorCountersAMD_numCounters(const State &glState, + GLuint group, + GLint *numCounters, + GLint *maxActiveCounters, + GLsizei counterSize, + GLuint *counters, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = sizeof(GLint); +} + +void CaptureGetPerfMonitorCountersAMD_maxActiveCounters(const State &glState, + GLuint group, + GLint *numCounters, + GLint *maxActiveCounters, + GLsizei counterSize, + GLuint *counters, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = sizeof(GLint); +} + +void CaptureGetPerfMonitorCountersAMD_counters(const State &glState, + GLuint group, + GLint *numCounters, + GLint *maxActiveCounters, + GLsizei counterSize, + GLuint *counters, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = counterSize * sizeof(GLuint); +} + +void CaptureGetPerfMonitorGroupStringAMD_length(const State &glState, + GLuint group, + GLsizei bufSize, + GLsizei *length, + GLchar *groupString, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = sizeof(GLsizei); +} + +void CaptureGetPerfMonitorGroupStringAMD_groupString(const State &glState, + GLuint group, + GLsizei bufSize, + GLsizei *length, + GLchar *groupString, + angle::ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = bufSize; +} + +void CaptureGetPerfMonitorGroupsAMD_numGroups(const State &glState, + GLint *numGroups, + GLsizei groupsSize, + GLuint *groups, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureGetPerfMonitorGroupsAMD_groups(const State &glState, + GLint *numGroups, + GLsizei groupsSize, + GLuint *groups, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureSelectPerfMonitorCountersAMD_counterList(const State &glState, + GLuint monitor, + GLboolean enable, + GLuint group, + GLint numCounters, + GLuint *counterList, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +// GL_ANGLE_base_vertex_base_instance void CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -32,7 +186,6 @@ void CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( } void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -42,10 +195,9 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts(const State &glStat angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); -} // namespace gl +} void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -59,7 +211,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts(const State &glStat void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_instanceCounts( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -73,7 +224,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_instanceCounts( void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_baseInstances( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -87,7 +237,6 @@ void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_baseInstances( void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_counts( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -103,7 +252,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_counts( void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -119,7 +267,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices( void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_instanceCounts( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -135,7 +282,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_instanceCounts void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseVertices( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -151,7 +297,6 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseVertices( void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseInstances( const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -165,202 +310,198 @@ void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseInstances( UNIMPLEMENTED(); } -void CaptureDrawElementsInstancedANGLE_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLsizei primcount, - ParamCapture *paramCapture) +// GL_ANGLE_blob_cache +void CaptureBlobCacheCallbacksANGLE_userParam(const State &glState, + GLSETBLOBPROCANGLE set, + GLGETBLOBPROCANGLE get, + const void *userParam, + angle::ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - paramCapture); + // Skipped } -void CaptureDrawElementsInstancedBaseInstanceEXT_indices(const State &glState, - bool isCallValid, - PrimitiveMode mode, - GLsizei count, - DrawElementsType type, - const void *indices, - GLsizei instancecount, - GLuint baseinstance, - angle::ParamCapture *indicesParam) +void CaptureGetPointervANGLE_params(const State &glState, + GLenum pname, + void **params, + angle::ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, mode, count, type, indices, indicesParam); + // Skipped } -void CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT_indices( - const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLsizei instancecount, - GLint basevertex, - GLuint baseInstance, - angle::ParamCapture *indicesParam) +// GL_ANGLE_get_image +void CaptureGetTexImageANGLE_pixels(const State &glState, + TextureTarget target, + GLint level, + GLenum format, + GLenum type, + void *pixels, + angle::ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - indicesParam); -} + if (glState.getTargetBuffer(gl::BufferBinding::PixelPack)) + { + // If a pixel pack buffer is bound, this is an offset, not a pointer + paramCapture->value.voidPointerVal = pixels; + return; + } -void CaptureDrawElementsBaseVertexEXT_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLint basevertex, - ParamCapture *indicesParam) -{ - UNIMPLEMENTED(); -} + const Texture *texture = glState.getTargetTexture(TextureTargetToType(target)); + ASSERT(texture); -void CaptureDrawElementsInstancedBaseVertexEXT_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLsizei instancecount, - GLint basevertex, - ParamCapture *indicesParam) -{ - UNIMPLEMENTED(); + // Use a conservative upper bound instead of an exact size to be simple. + static constexpr GLsizei kMaxPixelSize = 32; + size_t width = texture->getWidth(target, level); + size_t height = texture->getHeight(target, level); + size_t depth = texture->getDepth(target, level); + paramCapture->readBufferSizeBytes = kMaxPixelSize * width * height * depth; } -void CaptureMultiDrawArraysIndirectEXT_indirect(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - const void *indirect, - GLsizei drawcount, - GLsizei stride, - angle::ParamCapture *paramCapture) +void CaptureGetCompressedTexImageANGLE_pixels(const State &glState, + TextureTarget target, + GLint level, + void *pixels, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + const Texture *texture = glState.getTargetTexture(TextureTargetToType(target)); + ASSERT(texture); + const gl::InternalFormat *formatInfo = texture->getFormat(target, level).info; + const gl::Extents &levelExtents = texture->getExtents(target, level); + + GLuint size; + bool result = formatInfo->computeCompressedImageSize(levelExtents, &size); + ASSERT(result); + paramCapture->readBufferSizeBytes = size; } -void CaptureMultiDrawElementsIndirectEXT_indirect(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - DrawElementsType typePacked, - const void *indirect, - GLsizei drawcount, - GLsizei stride, - angle::ParamCapture *paramCapture) +void CaptureGetRenderbufferImageANGLE_pixels(const State &glState, + GLenum target, + GLenum format, + GLenum type, + void *pixels, + angle::ParamCapture *paramCapture) { - if (glState.getTargetBuffer(gl::BufferBinding::DrawIndirect) != nullptr) - { - paramCapture->value.voidConstPointerVal = indirect; - } - else + if (glState.getTargetBuffer(gl::BufferBinding::PixelPack)) { - if (stride == 0) - { - stride = sizeof(DrawElementsIndirectCommand); - } - CaptureMemory(indirect, stride * drawcount, paramCapture); + // If a pixel pack buffer is bound, this is an offset, not a pointer + paramCapture->value.voidPointerVal = pixels; + return; } + + const Renderbuffer *renderbuffer = glState.getCurrentRenderbuffer(); + ASSERT(renderbuffer); + + // Use a conservative upper bound instead of an exact size to be simple. + static constexpr GLsizei kMaxPixelSize = 32; + size_t width = renderbuffer->getWidth(); + size_t height = renderbuffer->getHeight(); + paramCapture->readBufferSizeBytes = kMaxPixelSize * width * height; } -void CaptureDrawRangeElementsBaseVertexEXT_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLuint start, - GLuint end, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLint basevertex, - ParamCapture *indicesParam) +// GL_ANGLE_get_tex_level_parameter +void CaptureGetTexLevelParameterivANGLE_params(const State &glState, + TextureTarget targetPacked, + GLint level, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + paramCapture->readBufferSizeBytes = sizeof(GLint); } -void CaptureMultiDrawElementsBaseVertexEXT_count(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - const GLsizei *count, - DrawElementsType typePacked, - const void *const *indices, - GLsizei drawcount, - const GLint *basevertex, - ParamCapture *countParam) +void CaptureGetTexLevelParameterfvANGLE_params(const State &glState, + TextureTarget targetPacked, + GLint level, + GLenum pname, + GLfloat *params, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + paramCapture->readBufferSizeBytes = sizeof(GLfloat); } -void CaptureMultiDrawElementsBaseVertexEXT_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - const GLsizei *count, - DrawElementsType typePacked, - const void *const *indices, - GLsizei drawcount, - const GLint *basevertex, - ParamCapture *indicesParam) +// GL_ANGLE_instanced_arrays +void CaptureDrawElementsInstancedANGLE_indices(const State &glState, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLsizei primcount, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, paramCapture); } -void CaptureMultiDrawElementsBaseVertexEXT_basevertex(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - const GLsizei *count, - DrawElementsType typePacked, - const void *const *indices, - GLsizei drawcount, - const GLint *basevertex, - ParamCapture *basevertexParam) +// GL_ANGLE_memory_object_flags +void CaptureTexStorageMemFlags2DANGLE_imageCreateInfoPNext(const State &glState, + TextureType targetPacked, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + MemoryObjectID memoryPacked, + GLuint64 offset, + GLbitfield createFlags, + GLbitfield usageFlags, + const void *imageCreateInfoPNext, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureDrawElementsBaseVertexOES_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLint basevertex, - ParamCapture *indicesParam) +void CaptureTexStorageMemFlags2DMultisampleANGLE_imageCreateInfoPNext( + const State &glState, + TextureType targetPacked, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLboolean fixedSampleLocations, + MemoryObjectID memoryPacked, + GLuint64 offset, + GLbitfield createFlags, + GLbitfield usageFlags, + const void *imageCreateInfoPNext, + angle::ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - indicesParam); + UNIMPLEMENTED(); } -void CaptureDrawElementsInstancedBaseVertexOES_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLsizei instancecount, - GLint basevertex, - ParamCapture *indicesParam) +void CaptureTexStorageMemFlags3DANGLE_imageCreateInfoPNext(const State &glState, + TextureType targetPacked, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + MemoryObjectID memoryPacked, + GLuint64 offset, + GLbitfield createFlags, + GLbitfield usageFlags, + const void *imageCreateInfoPNext, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureDrawRangeElementsBaseVertexOES_indices(const State &glState, - bool isCallValid, - PrimitiveMode modePacked, - GLuint start, - GLuint end, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLint basevertex, - ParamCapture *indicesParam) +void CaptureTexStorageMemFlags3DMultisampleANGLE_imageCreateInfoPNext( + const State &glState, + TextureType targetPacked, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLboolean fixedSampleLocations, + MemoryObjectID memoryPacked, + GLuint64 offset, + GLbitfield createFlags, + GLbitfield usageFlags, + const void *imageCreateInfoPNext, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } +// GL_ANGLE_multi_draw void CaptureMultiDrawArraysANGLE_firsts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -371,7 +512,6 @@ void CaptureMultiDrawArraysANGLE_firsts(const State &glState, } void CaptureMultiDrawArraysANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -382,7 +522,6 @@ void CaptureMultiDrawArraysANGLE_counts(const State &glState, } void CaptureMultiDrawArraysInstancedANGLE_firsts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -394,7 +533,6 @@ void CaptureMultiDrawArraysInstancedANGLE_firsts(const State &glState, } void CaptureMultiDrawArraysInstancedANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -406,7 +544,6 @@ void CaptureMultiDrawArraysInstancedANGLE_counts(const State &glState, } void CaptureMultiDrawArraysInstancedANGLE_instanceCounts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, @@ -418,7 +555,6 @@ void CaptureMultiDrawArraysInstancedANGLE_instanceCounts(const State &glState, } void CaptureMultiDrawElementsANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -430,7 +566,6 @@ void CaptureMultiDrawElementsANGLE_counts(const State &glState, } void CaptureMultiDrawElementsANGLE_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -442,7 +577,6 @@ void CaptureMultiDrawElementsANGLE_indices(const State &glState, } void CaptureMultiDrawElementsInstancedANGLE_counts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -455,7 +589,6 @@ void CaptureMultiDrawElementsInstancedANGLE_counts(const State &glState, } void CaptureMultiDrawElementsInstancedANGLE_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -468,7 +601,6 @@ void CaptureMultiDrawElementsInstancedANGLE_indices(const State &glState, } void CaptureMultiDrawElementsInstancedANGLE_instanceCounts(const State &glState, - bool isCallValid, PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, @@ -480,8 +612,8 @@ void CaptureMultiDrawElementsInstancedANGLE_instanceCounts(const State &glState, UNIMPLEMENTED(); } +// GL_ANGLE_request_extension void CaptureRequestExtensionANGLE_name(const State &glState, - bool isCallValid, const GLchar *name, ParamCapture *paramCapture) { @@ -489,15 +621,14 @@ void CaptureRequestExtensionANGLE_name(const State &glState, } void CaptureDisableExtensionANGLE_name(const State &glState, - bool isCallValid, const GLchar *name, ParamCapture *paramCapture) { CaptureString(name, paramCapture); } +// GL_ANGLE_robust_client_memory void CaptureGetBooleanvRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, @@ -508,7 +639,6 @@ void CaptureGetBooleanvRobustANGLE_length(const State &glState, } void CaptureGetBooleanvRobustANGLE_params(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, @@ -519,7 +649,6 @@ void CaptureGetBooleanvRobustANGLE_params(const State &glState, } void CaptureGetBufferParameterivRobustANGLE_length(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -531,7 +660,6 @@ void CaptureGetBufferParameterivRobustANGLE_length(const State &glState, } void CaptureGetBufferParameterivRobustANGLE_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -543,29 +671,26 @@ void CaptureGetBufferParameterivRobustANGLE_params(const State &glState, } void CaptureGetFloatvRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } void CaptureGetFloatvRobustANGLE_params(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetFloatv_data(glState, pname, params, paramCapture); } void CaptureGetFramebufferAttachmentParameterivRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, @@ -578,7 +703,6 @@ void CaptureGetFramebufferAttachmentParameterivRobustANGLE_length(const State &g } void CaptureGetFramebufferAttachmentParameterivRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum attachment, GLenum pname, @@ -591,7 +715,6 @@ void CaptureGetFramebufferAttachmentParameterivRobustANGLE_params(const State &g } void CaptureGetIntegervRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, @@ -602,18 +725,16 @@ void CaptureGetIntegervRobustANGLE_length(const State &glState, } void CaptureGetIntegervRobustANGLE_data(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data, ParamCapture *paramCapture) { - CaptureGetParameter(glState, pname, sizeof(GLint) * bufSize, paramCapture); + CaptureGetParameter(glState, pname, sizeof(GLint), paramCapture); } void CaptureGetProgramivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum pname, GLsizei bufSize, @@ -625,7 +746,6 @@ void CaptureGetProgramivRobustANGLE_length(const State &glState, } void CaptureGetProgramivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum pname, GLsizei bufSize, @@ -637,7 +757,6 @@ void CaptureGetProgramivRobustANGLE_params(const State &glState, } void CaptureGetRenderbufferParameterivRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -649,7 +768,6 @@ void CaptureGetRenderbufferParameterivRobustANGLE_length(const State &glState, } void CaptureGetRenderbufferParameterivRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -661,7 +779,6 @@ void CaptureGetRenderbufferParameterivRobustANGLE_params(const State &glState, } void CaptureGetShaderivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID shader, GLenum pname, GLsizei bufSize, @@ -669,11 +786,10 @@ void CaptureGetShaderivRobustANGLE_length(const State &glState, GLint *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } void CaptureGetShaderivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID shader, GLenum pname, GLsizei bufSize, @@ -681,11 +797,10 @@ void CaptureGetShaderivRobustANGLE_params(const State &glState, GLint *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetShaderiv_params(glState, shader, pname, params, paramCapture); } void CaptureGetTexParameterfvRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -697,7 +812,6 @@ void CaptureGetTexParameterfvRobustANGLE_length(const State &glState, } void CaptureGetTexParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -709,7 +823,6 @@ void CaptureGetTexParameterfvRobustANGLE_params(const State &glState, } void CaptureGetTexParameterivRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -721,7 +834,6 @@ void CaptureGetTexParameterivRobustANGLE_length(const State &glState, } void CaptureGetTexParameterivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -733,7 +845,6 @@ void CaptureGetTexParameterivRobustANGLE_params(const State &glState, } void CaptureGetUniformfvRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -745,7 +856,6 @@ void CaptureGetUniformfvRobustANGLE_length(const State &glState, } void CaptureGetUniformfvRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -757,7 +867,6 @@ void CaptureGetUniformfvRobustANGLE_params(const State &glState, } void CaptureGetUniformivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -769,7 +878,6 @@ void CaptureGetUniformivRobustANGLE_length(const State &glState, } void CaptureGetUniformivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -781,7 +889,6 @@ void CaptureGetUniformivRobustANGLE_params(const State &glState, } void CaptureGetVertexAttribfvRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -793,7 +900,6 @@ void CaptureGetVertexAttribfvRobustANGLE_length(const State &glState, } void CaptureGetVertexAttribfvRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -805,7 +911,6 @@ void CaptureGetVertexAttribfvRobustANGLE_params(const State &glState, } void CaptureGetVertexAttribivRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -817,7 +922,6 @@ void CaptureGetVertexAttribivRobustANGLE_length(const State &glState, } void CaptureGetVertexAttribivRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -829,7 +933,6 @@ void CaptureGetVertexAttribivRobustANGLE_params(const State &glState, } void CaptureGetVertexAttribPointervRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -841,7 +944,6 @@ void CaptureGetVertexAttribPointervRobustANGLE_length(const State &glState, } void CaptureGetVertexAttribPointervRobustANGLE_pointer(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -853,7 +955,6 @@ void CaptureGetVertexAttribPointervRobustANGLE_pointer(const State &glState, } void CaptureReadPixelsRobustANGLE_length(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -877,7 +978,6 @@ void CaptureReadPixelsRobustANGLE_length(const State &glState, } void CaptureReadPixelsRobustANGLE_columns(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -901,7 +1001,6 @@ void CaptureReadPixelsRobustANGLE_columns(const State &glState, } void CaptureReadPixelsRobustANGLE_rows(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -925,7 +1024,6 @@ void CaptureReadPixelsRobustANGLE_rows(const State &glState, } void CaptureReadPixelsRobustANGLE_pixels(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -950,7 +1048,6 @@ void CaptureReadPixelsRobustANGLE_pixels(const State &glState, } void CaptureTexImage2DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -977,7 +1074,6 @@ void CaptureTexImage2DRobustANGLE_pixels(const State &glState, } void CaptureTexParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -988,7 +1084,6 @@ void CaptureTexParameterfvRobustANGLE_params(const State &glState, } void CaptureTexParameterivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -999,7 +1094,6 @@ void CaptureTexParameterivRobustANGLE_params(const State &glState, } void CaptureTexSubImage2DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -1026,7 +1120,6 @@ void CaptureTexSubImage2DRobustANGLE_pixels(const State &glState, } void CaptureTexImage3DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint internalformat, @@ -1040,11 +1133,11 @@ void CaptureTexImage3DRobustANGLE_pixels(const State &glState, const void *pixels, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureTexImage3D_pixels(glState, targetPacked, level, internalformat, width, height, depth, + border, format, type, pixels, paramCapture); } void CaptureTexSubImage3DRobustANGLE_pixels(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -1059,11 +1152,11 @@ void CaptureTexSubImage3DRobustANGLE_pixels(const State &glState, const void *pixels, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureTexSubImage3D_pixels(glState, targetPacked, level, xoffset, yoffset, zoffset, width, + height, depth, format, type, pixels, paramCapture); } void CaptureCompressedTexImage2DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -1075,11 +1168,11 @@ void CaptureCompressedTexImage2DRobustANGLE_data(const State &glState, const GLvoid *data, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureCompressedTexImage2D_data(glState, targetPacked, level, internalformat, width, height, + border, imageSize, data, paramCapture); } void CaptureCompressedTexSubImage2DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLsizei xoffset, @@ -1092,11 +1185,11 @@ void CaptureCompressedTexSubImage2DRobustANGLE_data(const State &glState, const GLvoid *data, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureCompressedTexSubImage2D_data(glState, targetPacked, level, xoffset, yoffset, width, + height, format, imageSize, data, paramCapture); } void CaptureCompressedTexImage3DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum internalformat, @@ -1109,11 +1202,11 @@ void CaptureCompressedTexImage3DRobustANGLE_data(const State &glState, const GLvoid *data, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureCompressedTexImage3D_data(glState, targetPacked, level, internalformat, width, height, + depth, border, imageSize, data, paramCapture); } void CaptureCompressedTexSubImage3DRobustANGLE_data(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLint xoffset, @@ -1128,11 +1221,12 @@ void CaptureCompressedTexSubImage3DRobustANGLE_data(const State &glState, const GLvoid *data, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureCompressedTexSubImage3D_data(glState, targetPacked, level, xoffset, yoffset, zoffset, + width, height, depth, format, imageSize, data, + paramCapture); } void CaptureGetQueryivRobustANGLE_length(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLsizei bufSize, @@ -1144,7 +1238,6 @@ void CaptureGetQueryivRobustANGLE_length(const State &glState, } void CaptureGetQueryivRobustANGLE_params(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLsizei bufSize, @@ -1156,7 +1249,6 @@ void CaptureGetQueryivRobustANGLE_params(const State &glState, } void CaptureGetQueryObjectuivRobustANGLE_length(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -1168,7 +1260,6 @@ void CaptureGetQueryObjectuivRobustANGLE_length(const State &glState, } void CaptureGetQueryObjectuivRobustANGLE_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -1180,7 +1271,6 @@ void CaptureGetQueryObjectuivRobustANGLE_params(const State &glState, } void CaptureGetBufferPointervRobustANGLE_length(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -1192,7 +1282,6 @@ void CaptureGetBufferPointervRobustANGLE_length(const State &glState, } void CaptureGetBufferPointervRobustANGLE_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -1204,7 +1293,6 @@ void CaptureGetBufferPointervRobustANGLE_params(const State &glState, } void CaptureGetIntegeri_vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -1216,7 +1304,6 @@ void CaptureGetIntegeri_vRobustANGLE_length(const State &glState, } void CaptureGetIntegeri_vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -1228,7 +1315,6 @@ void CaptureGetIntegeri_vRobustANGLE_data(const State &glState, } void CaptureGetInternalformativRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum internalformat, GLenum pname, @@ -1237,11 +1323,10 @@ void CaptureGetInternalformativRobustANGLE_length(const State &glState, GLint *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } void CaptureGetInternalformativRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum internalformat, GLenum pname, @@ -1250,11 +1335,11 @@ void CaptureGetInternalformativRobustANGLE_params(const State &glState, GLint *params, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetInternalformativ_params(glState, target, internalformat, pname, bufSize, params, + paramCapture); } void CaptureGetVertexAttribIivRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -1266,7 +1351,6 @@ void CaptureGetVertexAttribIivRobustANGLE_length(const State &glState, } void CaptureGetVertexAttribIivRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -1278,7 +1362,6 @@ void CaptureGetVertexAttribIivRobustANGLE_params(const State &glState, } void CaptureGetVertexAttribIuivRobustANGLE_length(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -1290,7 +1373,6 @@ void CaptureGetVertexAttribIuivRobustANGLE_length(const State &glState, } void CaptureGetVertexAttribIuivRobustANGLE_params(const State &glState, - bool isCallValid, GLuint index, GLenum pname, GLsizei bufSize, @@ -1302,7 +1384,6 @@ void CaptureGetVertexAttribIuivRobustANGLE_params(const State &glState, } void CaptureGetUniformuivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1314,7 +1395,6 @@ void CaptureGetUniformuivRobustANGLE_length(const State &glState, } void CaptureGetUniformuivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1326,7 +1406,6 @@ void CaptureGetUniformuivRobustANGLE_params(const State &glState, } void CaptureGetActiveUniformBlockivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformBlockIndex uniformBlockIndex, GLenum pname, @@ -1339,7 +1418,6 @@ void CaptureGetActiveUniformBlockivRobustANGLE_length(const State &glState, } void CaptureGetActiveUniformBlockivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformBlockIndex uniformBlockIndex, GLenum pname, @@ -1352,29 +1430,26 @@ void CaptureGetActiveUniformBlockivRobustANGLE_params(const State &glState, } void CaptureGetInteger64vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } void CaptureGetInteger64vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data, ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetParameter(glState, pname, sizeof(GLint64), paramCapture); } void CaptureGetInteger64i_vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -1386,7 +1461,6 @@ void CaptureGetInteger64i_vRobustANGLE_length(const State &glState, } void CaptureGetInteger64i_vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -1398,7 +1472,6 @@ void CaptureGetInteger64i_vRobustANGLE_data(const State &glState, } void CaptureGetBufferParameteri64vRobustANGLE_length(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -1410,7 +1483,6 @@ void CaptureGetBufferParameteri64vRobustANGLE_length(const State &glState, } void CaptureGetBufferParameteri64vRobustANGLE_params(const State &glState, - bool isCallValid, BufferBinding targetPacked, GLenum pname, GLsizei bufSize, @@ -1422,7 +1494,6 @@ void CaptureGetBufferParameteri64vRobustANGLE_params(const State &glState, } void CaptureSamplerParameterivRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID sampler, GLuint pname, GLsizei bufSize, @@ -1433,7 +1504,6 @@ void CaptureSamplerParameterivRobustANGLE_param(const State &glState, } void CaptureSamplerParameterfvRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1444,7 +1514,6 @@ void CaptureSamplerParameterfvRobustANGLE_param(const State &glState, } void CaptureGetSamplerParameterivRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1456,7 +1525,6 @@ void CaptureGetSamplerParameterivRobustANGLE_length(const State &glState, } void CaptureGetSamplerParameterivRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1468,7 +1536,6 @@ void CaptureGetSamplerParameterivRobustANGLE_params(const State &glState, } void CaptureGetSamplerParameterfvRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1480,7 +1547,6 @@ void CaptureGetSamplerParameterfvRobustANGLE_length(const State &glState, } void CaptureGetSamplerParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1492,7 +1558,6 @@ void CaptureGetSamplerParameterfvRobustANGLE_params(const State &glState, } void CaptureGetFramebufferParameterivRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -1504,7 +1569,6 @@ void CaptureGetFramebufferParameterivRobustANGLE_length(const State &glState, } void CaptureGetFramebufferParameterivRobustANGLE_params(const State &glState, - bool isCallValid, GLenum target, GLenum pname, GLsizei bufSize, @@ -1516,7 +1580,6 @@ void CaptureGetFramebufferParameterivRobustANGLE_params(const State &glState, } void CaptureGetProgramInterfaceivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLenum pname, @@ -1529,7 +1592,6 @@ void CaptureGetProgramInterfaceivRobustANGLE_length(const State &glState, } void CaptureGetProgramInterfaceivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, GLenum pname, @@ -1542,7 +1604,6 @@ void CaptureGetProgramInterfaceivRobustANGLE_params(const State &glState, } void CaptureGetBooleani_vRobustANGLE_length(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -1554,7 +1615,6 @@ void CaptureGetBooleani_vRobustANGLE_length(const State &glState, } void CaptureGetBooleani_vRobustANGLE_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLsizei bufSize, @@ -1566,7 +1626,6 @@ void CaptureGetBooleani_vRobustANGLE_data(const State &glState, } void CaptureGetMultisamplefvRobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLsizei bufSize, @@ -1578,7 +1637,6 @@ void CaptureGetMultisamplefvRobustANGLE_length(const State &glState, } void CaptureGetMultisamplefvRobustANGLE_val(const State &glState, - bool isCallValid, GLenum pname, GLuint index, GLsizei bufSize, @@ -1590,7 +1648,6 @@ void CaptureGetMultisamplefvRobustANGLE_val(const State &glState, } void CaptureGetTexLevelParameterivRobustANGLE_length(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -1603,7 +1660,6 @@ void CaptureGetTexLevelParameterivRobustANGLE_length(const State &glState, } void CaptureGetTexLevelParameterivRobustANGLE_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -1616,7 +1672,6 @@ void CaptureGetTexLevelParameterivRobustANGLE_params(const State &glState, } void CaptureGetTexLevelParameterfvRobustANGLE_length(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -1629,7 +1684,6 @@ void CaptureGetTexLevelParameterfvRobustANGLE_length(const State &glState, } void CaptureGetTexLevelParameterfvRobustANGLE_params(const State &glState, - bool isCallValid, TextureTarget targetPacked, GLint level, GLenum pname, @@ -1642,7 +1696,6 @@ void CaptureGetTexLevelParameterfvRobustANGLE_params(const State &glState, } void CaptureGetPointervRobustANGLERobustANGLE_length(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, @@ -1653,7 +1706,6 @@ void CaptureGetPointervRobustANGLERobustANGLE_length(const State &glState, } void CaptureGetPointervRobustANGLERobustANGLE_params(const State &glState, - bool isCallValid, GLenum pname, GLsizei bufSize, GLsizei *length, @@ -1664,7 +1716,6 @@ void CaptureGetPointervRobustANGLERobustANGLE_params(const State &glState, } void CaptureReadnPixelsRobustANGLE_length(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -1682,7 +1733,6 @@ void CaptureReadnPixelsRobustANGLE_length(const State &glState, } void CaptureReadnPixelsRobustANGLE_columns(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -1700,7 +1750,6 @@ void CaptureReadnPixelsRobustANGLE_columns(const State &glState, } void CaptureReadnPixelsRobustANGLE_rows(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -1718,7 +1767,6 @@ void CaptureReadnPixelsRobustANGLE_rows(const State &glState, } void CaptureReadnPixelsRobustANGLE_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -1736,7 +1784,6 @@ void CaptureReadnPixelsRobustANGLE_data(const State &glState, } void CaptureGetnUniformfvRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1748,7 +1795,6 @@ void CaptureGetnUniformfvRobustANGLE_length(const State &glState, } void CaptureGetnUniformfvRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1760,7 +1806,6 @@ void CaptureGetnUniformfvRobustANGLE_params(const State &glState, } void CaptureGetnUniformivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1772,7 +1817,6 @@ void CaptureGetnUniformivRobustANGLE_length(const State &glState, } void CaptureGetnUniformivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1784,7 +1828,6 @@ void CaptureGetnUniformivRobustANGLE_params(const State &glState, } void CaptureGetnUniformuivRobustANGLE_length(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1796,7 +1839,6 @@ void CaptureGetnUniformuivRobustANGLE_length(const State &glState, } void CaptureGetnUniformuivRobustANGLE_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -1808,7 +1850,6 @@ void CaptureGetnUniformuivRobustANGLE_params(const State &glState, } void CaptureTexParameterIivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -1819,7 +1860,6 @@ void CaptureTexParameterIivRobustANGLE_params(const State &glState, } void CaptureTexParameterIuivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -1830,7 +1870,6 @@ void CaptureTexParameterIuivRobustANGLE_params(const State &glState, } void CaptureGetTexParameterIivRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -1842,7 +1881,6 @@ void CaptureGetTexParameterIivRobustANGLE_length(const State &glState, } void CaptureGetTexParameterIivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -1854,7 +1892,6 @@ void CaptureGetTexParameterIivRobustANGLE_params(const State &glState, } void CaptureGetTexParameterIuivRobustANGLE_length(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -1866,7 +1903,6 @@ void CaptureGetTexParameterIuivRobustANGLE_length(const State &glState, } void CaptureGetTexParameterIuivRobustANGLE_params(const State &glState, - bool isCallValid, TextureType targetPacked, GLenum pname, GLsizei bufSize, @@ -1878,7 +1914,6 @@ void CaptureGetTexParameterIuivRobustANGLE_params(const State &glState, } void CaptureSamplerParameterIivRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1889,7 +1924,6 @@ void CaptureSamplerParameterIivRobustANGLE_param(const State &glState, } void CaptureSamplerParameterIuivRobustANGLE_param(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1900,7 +1934,6 @@ void CaptureSamplerParameterIuivRobustANGLE_param(const State &glState, } void CaptureGetSamplerParameterIivRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1912,7 +1945,6 @@ void CaptureGetSamplerParameterIivRobustANGLE_length(const State &glState, } void CaptureGetSamplerParameterIivRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1924,7 +1956,6 @@ void CaptureGetSamplerParameterIivRobustANGLE_params(const State &glState, } void CaptureGetSamplerParameterIuivRobustANGLE_length(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1936,7 +1967,6 @@ void CaptureGetSamplerParameterIuivRobustANGLE_length(const State &glState, } void CaptureGetSamplerParameterIuivRobustANGLE_params(const State &glState, - bool isCallValid, SamplerID sampler, GLenum pname, GLsizei bufSize, @@ -1948,7 +1978,6 @@ void CaptureGetSamplerParameterIuivRobustANGLE_params(const State &glState, } void CaptureGetQueryObjectivRobustANGLE_length(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -1960,7 +1989,6 @@ void CaptureGetQueryObjectivRobustANGLE_length(const State &glState, } void CaptureGetQueryObjectivRobustANGLE_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -1972,7 +2000,6 @@ void CaptureGetQueryObjectivRobustANGLE_params(const State &glState, } void CaptureGetQueryObjecti64vRobustANGLE_length(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -1984,7 +2011,6 @@ void CaptureGetQueryObjecti64vRobustANGLE_length(const State &glState, } void CaptureGetQueryObjecti64vRobustANGLE_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -1996,7 +2022,6 @@ void CaptureGetQueryObjecti64vRobustANGLE_params(const State &glState, } void CaptureGetQueryObjectui64vRobustANGLE_length(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -2008,7 +2033,6 @@ void CaptureGetQueryObjectui64vRobustANGLE_length(const State &glState, } void CaptureGetQueryObjectui64vRobustANGLE_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLsizei bufSize, @@ -2019,332 +2043,253 @@ void CaptureGetQueryObjectui64vRobustANGLE_params(const State &glState, UNIMPLEMENTED(); } -void CaptureGetTexLevelParameterivANGLE_params(const State &glState, - bool isCallValid, - TextureTarget targetPacked, - GLint level, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) +void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_length( + const State &glState, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params, + angle::ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLint); + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } -void CaptureGetTexLevelParameterfvANGLE_params(const State &glState, - bool isCallValid, - TextureTarget targetPacked, - GLint level, - GLenum pname, - GLfloat *params, - ParamCapture *paramCapture) +void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_params( + const State &glState, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params, + angle::ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLfloat); + CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params(glState, plane, pname, params, + paramCapture); } -void CaptureGetMultisamplefvANGLE_val(const State &glState, - bool isCallValid, - GLenum pname, - GLuint index, - GLfloat *val, - ParamCapture *paramCapture) +void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_length( + const State &glState, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params, + angle::ParamCapture *paramCapture) { - // GL_SAMPLE_POSITION_ANGLE: 2 floats - paramCapture->readBufferSizeBytes = sizeof(GLfloat) * 2; + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } -void CaptureGetTranslatedShaderSourceANGLE_length(const State &glState, - bool isCallValid, - ShaderProgramID shader, - GLsizei bufsize, - GLsizei *length, - GLchar *source, - ParamCapture *paramCapture) +void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_params( + const State &glState, + GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params(glState, plane, pname, params, + paramCapture); } -void CaptureGetTranslatedShaderSourceANGLE_source(const State &glState, - bool isCallValid, - ShaderProgramID shader, - GLsizei bufsize, - GLsizei *length, - GLchar *source, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureBindUniformLocationCHROMIUM_name(const State &glState, - bool isCallValid, - ShaderProgramID program, - UniformLocation location, - const GLchar *name, - ParamCapture *paramCapture) +// GL_ANGLE_shader_pixel_local_storage +void CaptureFramebufferPixelLocalClearValuefvANGLE_value(const State &glState, + GLint plane, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - CaptureString(name, paramCapture); + CaptureArray(value, 4, paramCapture); } -void CaptureMatrixLoadfCHROMIUM_matrix(const State &glState, - bool isCallValid, - GLenum matrixMode, - const GLfloat *matrix, - ParamCapture *paramCapture) +void CaptureFramebufferPixelLocalClearValueivANGLE_value(const State &glState, + GLint plane, + const GLint *value, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(value, 4, paramCapture); } -void CapturePathCommandsCHROMIUM_commands(const State &glState, - bool isCallValid, - PathID path, - GLsizei numCommands, - const GLubyte *commands, - GLsizei numCoords, - GLenum coordType, - const void *coords, - ParamCapture *paramCapture) +void CaptureFramebufferPixelLocalClearValueuivANGLE_value(const State &glState, + GLint plane, + const GLuint *value, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(value, 4, paramCapture); } -void CapturePathCommandsCHROMIUM_coords(const State &glState, - bool isCallValid, - PathID path, - GLsizei numCommands, - const GLubyte *commands, - GLsizei numCoords, - GLenum coordType, - const void *coords, - ParamCapture *paramCapture) +void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState, + GLsizei n, + const GLenum loadops[], + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(loadops, n, paramCapture); } -void CaptureGetPathParameterfvCHROMIUM_value(const State &glState, - bool isCallValid, - PathID path, - GLenum pname, - GLfloat *value, - ParamCapture *paramCapture) +void CaptureEndPixelLocalStorageANGLE_storeops(const State &glState, + GLsizei n, + const GLenum *storeops, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(storeops, n, paramCapture); } -void CaptureGetPathParameterivCHROMIUM_value(const State &glState, - bool isCallValid, - PathID path, - GLenum pname, - GLint *value, - ParamCapture *paramCapture) +void CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params( + const State &glState, + GLint plane, + GLenum pname, + GLfloat *params, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + size_t numParams = 1; + switch (pname) + { + case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: + numParams = 4; + break; + } + paramCapture->readBufferSizeBytes = sizeof(GLfloat) * numParams; } -void CaptureCoverFillPathInstancedCHROMIUM_paths(const State &glState, - bool isCallValid, - GLsizei numPath, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +void CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params( + const State &glState, + GLint plane, + GLenum pname, + GLint *params, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + size_t numParams = 1; + switch (pname) + { + case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: + numParams = 4; + break; + } + paramCapture->readBufferSizeBytes = sizeof(GLint) * numParams; } -void CaptureCoverFillPathInstancedCHROMIUM_transformValues(const State &glState, - bool isCallValid, - GLsizei numPath, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +// GL_ANGLE_texture_multisample +void CaptureGetMultisamplefvANGLE_val(const State &glState, + GLenum pname, + GLuint index, + GLfloat *val, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // GL_SAMPLE_POSITION_ANGLE: 2 floats + paramCapture->readBufferSizeBytes = sizeof(GLfloat) * 2; } -void CaptureCoverStrokePathInstancedCHROMIUM_paths(const State &glState, - bool isCallValid, - GLsizei numPath, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +// GL_ANGLE_translated_shader_source +void CaptureGetTranslatedShaderSourceANGLE_length(const State &glState, + ShaderProgramID shader, + GLsizei bufsize, + GLsizei *length, + GLchar *source, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureCoverStrokePathInstancedCHROMIUM_transformValues(const State &glState, - bool isCallValid, - GLsizei numPath, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +void CaptureGetTranslatedShaderSourceANGLE_source(const State &glState, + ShaderProgramID shader, + GLsizei bufsize, + GLsizei *length, + GLchar *source, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureStencilStrokePathInstancedCHROMIUM_paths(const State &glState, - bool isCallValid, - GLsizei numPath, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLint reference, - GLuint mask, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +// GL_ANGLE_vulkan_image +void CaptureAcquireTexturesANGLE_texturesPacked(const State &glState, + GLuint numTextures, + const TextureID *textures, + const GLenum *layouts, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(textures, numTextures, paramCapture); } -void CaptureStencilStrokePathInstancedCHROMIUM_transformValues(const State &glState, - bool isCallValid, - GLsizei numPath, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLint reference, - GLuint mask, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +void CaptureAcquireTexturesANGLE_layouts(const State &glState, + GLuint numTextures, + const TextureID *texturesPacked, + const GLenum *layouts, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(layouts, numTextures * sizeof(GLenum), paramCapture); } -void CaptureStencilFillPathInstancedCHROMIUM_paths(const State &glState, - bool isCallValid, - GLsizei numPaths, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum fillMode, - GLuint mask, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +void CaptureReleaseTexturesANGLE_texturesPacked(const State &glState, + GLuint numTextures, + const TextureID *textures, + GLenum *layouts, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(textures, numTextures, paramCapture); } -void CaptureStencilFillPathInstancedCHROMIUM_transformValues(const State &glState, - bool isCallValid, - GLsizei numPaths, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum fillMode, - GLuint mask, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +void CaptureReleaseTexturesANGLE_layouts(const State &glState, + GLuint numTextures, + const TextureID *texturesPacked, + GLenum *layouts, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureStencilThenCoverFillPathInstancedCHROMIUM_paths(const State &glState, - bool isCallValid, - GLsizei numPaths, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum fillMode, - GLuint mask, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +// GL_CHROMIUM_bind_uniform_location +void CaptureBindUniformLocationCHROMIUM_name(const State &glState, + ShaderProgramID program, + UniformLocation location, + const GLchar *name, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureString(name, paramCapture); } -void CaptureStencilThenCoverFillPathInstancedCHROMIUM_transformValues( - const State &glState, - bool isCallValid, - GLsizei numPaths, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLenum fillMode, - GLuint mask, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +// GL_EXT_EGL_image_storage +void CaptureEGLImageTargetTexStorageEXT_attrib_list(const State &glState, + GLenum target, + egl::ImageID image, + const GLint *attrib_list, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureStencilThenCoverStrokePathInstancedCHROMIUM_paths(const State &glState, - bool isCallValid, - GLsizei numPaths, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLint reference, - GLuint mask, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) +// GL_EXT_base_instance +void CaptureDrawElementsInstancedBaseInstanceEXT_indices(const State &glState, + PrimitiveMode mode, + GLsizei count, + DrawElementsType type, + const void *indices, + GLsizei instancecount, + GLuint baseinstance, + angle::ParamCapture *indicesParam) { - UNIMPLEMENTED(); + CaptureDrawElements_indices(glState, mode, count, type, indices, indicesParam); } -void CaptureStencilThenCoverStrokePathInstancedCHROMIUM_transformValues( +void CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT_indices( const State &glState, - bool isCallValid, - GLsizei numPaths, - GLenum pathNameType, - const void *paths, - PathID pathBase, - GLint reference, - GLuint mask, - GLenum coverMode, - GLenum transformType, - const GLfloat *transformValues, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureBindFragmentInputLocationCHROMIUM_name(const State &glState, - bool isCallValid, - ShaderProgramID programs, - GLint location, - const GLchar *name, - ParamCapture *paramCapture) -{ - CaptureString(name, paramCapture); -} - -void CaptureProgramPathFragmentInputGenCHROMIUM_coeffs(const State &glState, - bool isCallValid, - ShaderProgramID program, - GLint location, - GLenum genMode, - GLint components, - const GLfloat *coeffs, - ParamCapture *paramCapture) + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLsizei instancecount, + GLint basevertex, + GLuint baseInstance, + angle::ParamCapture *indicesParam) { - UNIMPLEMENTED(); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, indicesParam); } +// GL_EXT_blend_func_extended void CaptureBindFragDataLocationEXT_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint color, const GLchar *name, @@ -2354,7 +2299,6 @@ void CaptureBindFragDataLocationEXT_name(const State &glState, } void CaptureBindFragDataLocationIndexedEXT_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLuint colorNumber, GLuint index, @@ -2365,7 +2309,6 @@ void CaptureBindFragDataLocationIndexedEXT_name(const State &glState, } void CaptureGetFragDataIndexEXT_name(const State &glState, - bool isCallValid, ShaderProgramID program, const GLchar *name, ParamCapture *paramCapture) @@ -2374,7 +2317,6 @@ void CaptureGetFragDataIndexEXT_name(const State &glState, } void CaptureGetProgramResourceLocationIndexEXT_name(const State &glState, - bool isCallValid, ShaderProgramID program, GLenum programInterface, const GLchar *name, @@ -2383,8 +2325,98 @@ void CaptureGetProgramResourceLocationIndexEXT_name(const State &glState, CaptureString(name, paramCapture); } +// GL_EXT_buffer_storage +void CaptureBufferStorageEXT_data(const State &glState, + BufferBinding targetPacked, + GLsizeiptr size, + const void *data, + GLbitfield flags, + angle::ParamCapture *paramCapture) +{ + if (data) + { + CaptureMemory(data, size, paramCapture); + } +} + +// GL_EXT_clear_texture +void CaptureClearTexImageEXT_data(const State &glState, + TextureID texturePacked, + GLint level, + GLenum format, + GLenum type, + const void *data, + angle::ParamCapture *paramCapture) +{ + if (!data) + { + return; + } + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format, type); + GLuint captureSize = internalFormatInfo.computePixelBytes(type); + CaptureMemory(data, captureSize, paramCapture); +} + +void CaptureClearTexSubImageEXT_data(const State &glState, + TextureID texturePacked, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLenum type, + const void *data, + angle::ParamCapture *paramCapture) +{ + if (!data) + { + return; + } + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format, type); + GLuint captureSize = internalFormatInfo.computePixelBytes(type); + CaptureMemory(data, captureSize, paramCapture); +} + +// GL_EXT_debug_label +void CaptureGetObjectLabelEXT_length(const State &glState, + GLenum type, + GLuint object, + GLsizei bufSize, + GLsizei *length, + GLchar *label, + angle::ParamCapture *paramCapture) +{ + // Skipped +} + +void CaptureGetObjectLabelEXT_label(const State &glState, + GLenum type, + GLuint object, + GLsizei bufSize, + GLsizei *length, + GLchar *label, + angle::ParamCapture *paramCapture) +{ + // Skipped +} + +void CaptureLabelObjectEXT_label(const State &glState, + GLenum type, + GLuint object, + GLsizei length, + const GLchar *label, + angle::ParamCapture *paramCapture) +{ + // Skipped +} + +// GL_EXT_debug_marker void CaptureInsertEventMarkerEXT_marker(const State &glState, - bool isCallValid, GLsizei length, const GLchar *marker, ParamCapture *paramCapture) @@ -2393,7 +2425,6 @@ void CaptureInsertEventMarkerEXT_marker(const State &glState, } void CapturePushGroupMarkerEXT_marker(const State &glState, - bool isCallValid, GLsizei length, const GLchar *marker, ParamCapture *paramCapture) @@ -2401,8 +2432,8 @@ void CapturePushGroupMarkerEXT_marker(const State &glState, // Skipped } +// GL_EXT_discard_framebuffer void CaptureDiscardFramebufferEXT_attachments(const State &glState, - bool isCallValid, GLenum target, GLsizei numAttachments, const GLenum *attachments, @@ -2411,8 +2442,8 @@ void CaptureDiscardFramebufferEXT_attachments(const State &glState, CaptureArray(attachments, numAttachments, paramCapture); } +// GL_EXT_disjoint_timer_query void CaptureDeleteQueriesEXT_idsPacked(const State &glState, - bool isCallValid, GLsizei n, const QueryID *ids, ParamCapture *paramCapture) @@ -2421,7 +2452,6 @@ void CaptureDeleteQueriesEXT_idsPacked(const State &glState, } void CaptureGenQueriesEXT_idsPacked(const State &glState, - bool isCallValid, GLsizei n, QueryID *ids, ParamCapture *paramCapture) @@ -2429,28 +2459,15 @@ void CaptureGenQueriesEXT_idsPacked(const State &glState, CaptureGenHandles(n, ids, paramCapture); } -// For each of the GetQueryObject functions below, the spec states: -// -// There may be an indeterminate delay before a query object's -// result value is available. If pname is QUERY_RESULT_AVAILABLE, -// FALSE is returned if such a delay would be required; otherwise -// TRUE is returned. It must always be true that if any query -// object returns a result available of TRUE, all queries of the -// same type issued prior to that query must also return TRUE. -// Repeatedly querying QUERY_RESULT_AVAILABLE for any given query -// object is guaranteed to return TRUE eventually. -// -// If pname is QUERY_RESULT, then the query object's result value is -// returned as a single integer in params. If the value is so large -// in magnitude that it cannot be represented with the requested -// type, then the nearest value representable using the requested type -// is returned. Querying QUERY_RESULT for any given query object -// forces that query to complete within a finite amount of time. -// -// Thus, return a single value for each param. -// +void CaptureGetInteger64vEXT_data(const State &glState, + GLenum pname, + GLint64 *data, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + void CaptureGetQueryObjecti64vEXT_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLint64 *params, @@ -2459,17 +2476,7 @@ void CaptureGetQueryObjecti64vEXT_params(const State &glState, paramCapture->readBufferSizeBytes = sizeof(GLint64); } -void CaptureGetInteger64vEXT_data(const State &glState, - bool isCallValid, - GLenum pname, - GLint64 *data, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - void CaptureGetQueryObjectivEXT_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLint *params, @@ -2479,7 +2486,6 @@ void CaptureGetQueryObjectivEXT_params(const State &glState, } void CaptureGetQueryObjectui64vEXT_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLuint64 *params, @@ -2489,7 +2495,6 @@ void CaptureGetQueryObjectui64vEXT_params(const State &glState, } void CaptureGetQueryObjectuivEXT_params(const State &glState, - bool isCallValid, QueryID id, GLenum pname, GLuint *params, @@ -2499,7 +2504,6 @@ void CaptureGetQueryObjectuivEXT_params(const State &glState, } void CaptureGetQueryivEXT_params(const State &glState, - bool isCallValid, QueryType targetPacked, GLenum pname, GLint *params, @@ -2508,17 +2512,90 @@ void CaptureGetQueryivEXT_params(const State &glState, CaptureMemory(params, sizeof(GLint), paramCapture); } +// GL_EXT_draw_buffers void CaptureDrawBuffersEXT_bufs(const State &glState, - bool isCallValid, GLsizei n, const GLenum *bufs, ParamCapture *paramCapture) { - CaptureDrawBuffers_bufs(glState, isCallValid, n, bufs, paramCapture); + CaptureDrawBuffers_bufs(glState, n, bufs, paramCapture); +} + +// GL_EXT_draw_elements_base_vertex +void CaptureDrawElementsBaseVertexEXT_indices(const State &glState, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLint basevertex, + ParamCapture *indicesParam) +{ + UNIMPLEMENTED(); +} + +void CaptureDrawElementsInstancedBaseVertexEXT_indices(const State &glState, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLsizei instancecount, + GLint basevertex, + ParamCapture *indicesParam) +{ + UNIMPLEMENTED(); +} + +void CaptureDrawRangeElementsBaseVertexEXT_indices(const State &glState, + PrimitiveMode modePacked, + GLuint start, + GLuint end, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLint basevertex, + ParamCapture *indicesParam) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawElementsBaseVertexEXT_count(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei drawcount, + const GLint *basevertex, + ParamCapture *countParam) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawElementsBaseVertexEXT_indices(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei drawcount, + const GLint *basevertex, + ParamCapture *indicesParam) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawElementsBaseVertexEXT_basevertex(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei drawcount, + const GLint *basevertex, + ParamCapture *basevertexParam) +{ + UNIMPLEMENTED(); } +// GL_EXT_draw_instanced void CaptureDrawElementsInstancedEXT_indices(const State &glState, - bool isCallValid, PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, @@ -2526,12 +2603,31 @@ void CaptureDrawElementsInstancedEXT_indices(const State &glState, GLsizei primcount, ParamCapture *paramCapture) { - CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices, - paramCapture); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, paramCapture); +} + +// GL_EXT_fragment_shading_rate +void CaptureGetFragmentShadingRatesEXT_count(const State &glState, + GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} +void CaptureGetFragmentShadingRatesEXT_shadingRates(const State &glState, + GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); } +// GL_EXT_memory_object void CaptureCreateMemoryObjectsEXT_memoryObjectsPacked(const State &glState, - bool isCallValid, GLsizei n, MemoryObjectID *memoryObjects, ParamCapture *paramCapture) @@ -2540,7 +2636,6 @@ void CaptureCreateMemoryObjectsEXT_memoryObjectsPacked(const State &glState, } void CaptureDeleteMemoryObjectsEXT_memoryObjectsPacked(const State &glState, - bool isCallValid, GLsizei n, const MemoryObjectID *memoryObjects, ParamCapture *paramCapture) @@ -2549,7 +2644,6 @@ void CaptureDeleteMemoryObjectsEXT_memoryObjectsPacked(const State &glState, } void CaptureGetMemoryObjectParameterivEXT_params(const State &glState, - bool isCallValid, MemoryObjectID memoryObject, GLenum pname, GLint *params, @@ -2559,7 +2653,6 @@ void CaptureGetMemoryObjectParameterivEXT_params(const State &glState, } void CaptureGetUnsignedBytevEXT_data(const State &glState, - bool isCallValid, GLenum pname, GLubyte *data, ParamCapture *paramCapture) @@ -2568,7 +2661,6 @@ void CaptureGetUnsignedBytevEXT_data(const State &glState, } void CaptureGetUnsignedBytei_vEXT_data(const State &glState, - bool isCallValid, GLenum target, GLuint index, GLubyte *data, @@ -2578,7 +2670,6 @@ void CaptureGetUnsignedBytei_vEXT_data(const State &glState, } void CaptureMemoryObjectParameterivEXT_params(const State &glState, - bool isCallValid, MemoryObjectID memoryObject, GLenum pname, const GLint *params, @@ -2587,8 +2678,84 @@ void CaptureMemoryObjectParameterivEXT_params(const State &glState, CaptureMemory(params, sizeof(GLint), paramCapture); } +// GL_EXT_multi_draw_arrays +void CaptureMultiDrawArraysEXT_first(const State &glState, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawArraysEXT_count(const State &glState, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawElementsEXT_count(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawElementsEXT_indices(const State &glState, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +// GL_EXT_multi_draw_indirect +void CaptureMultiDrawArraysIndirectEXT_indirect(const State &glState, + PrimitiveMode modePacked, + const void *indirect, + GLsizei drawcount, + GLsizei stride, + angle::ParamCapture *paramCapture) +{ + UNIMPLEMENTED(); +} + +void CaptureMultiDrawElementsIndirectEXT_indirect(const State &glState, + PrimitiveMode modePacked, + DrawElementsType typePacked, + const void *indirect, + GLsizei drawcount, + GLsizei stride, + angle::ParamCapture *paramCapture) +{ + if (glState.getTargetBuffer(gl::BufferBinding::DrawIndirect) != nullptr) + { + paramCapture->value.voidConstPointerVal = indirect; + } + else + { + if (stride == 0) + { + stride = sizeof(DrawElementsIndirectCommand); + } + CaptureMemory(indirect, stride * drawcount, paramCapture); + } +} + +// GL_EXT_robustness void CaptureGetnUniformfvEXT_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -2599,7 +2766,6 @@ void CaptureGetnUniformfvEXT_params(const State &glState, } void CaptureGetnUniformivEXT_params(const State &glState, - bool isCallValid, ShaderProgramID program, UniformLocation location, GLsizei bufSize, @@ -2610,7 +2776,6 @@ void CaptureGetnUniformivEXT_params(const State &glState, } void CaptureReadnPixelsEXT_data(const State &glState, - bool isCallValid, GLint x, GLint y, GLsizei width, @@ -2624,56 +2789,8 @@ void CaptureReadnPixelsEXT_data(const State &glState, UNIMPLEMENTED(); } -void CaptureGetnUniformfvKHR_params(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei bufSize, - GLfloat *params, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetnUniformivKHR_params(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei bufSize, - GLint *params, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetnUniformuivKHR_params(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei bufSize, - GLuint *params, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureReadnPixelsKHR_data(const State &glState, - bool isCallValid, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLsizei bufSize, - void *data, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - +// GL_EXT_semaphore void CaptureDeleteSemaphoresEXT_semaphoresPacked(const State &glState, - bool isCallValid, GLsizei n, const SemaphoreID *semaphores, ParamCapture *paramCapture) @@ -2682,7 +2799,6 @@ void CaptureDeleteSemaphoresEXT_semaphoresPacked(const State &glState, } void CaptureGenSemaphoresEXT_semaphoresPacked(const State &glState, - bool isCallValid, GLsizei n, SemaphoreID *semaphores, ParamCapture *paramCapture) @@ -2691,7 +2807,6 @@ void CaptureGenSemaphoresEXT_semaphoresPacked(const State &glState, } void CaptureGetSemaphoreParameterui64vEXT_params(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLenum pname, GLuint64 *params, @@ -2701,7 +2816,6 @@ void CaptureGetSemaphoreParameterui64vEXT_params(const State &glState, } void CaptureSemaphoreParameterui64vEXT_params(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLenum pname, const GLuint64 *params, @@ -2711,7 +2825,6 @@ void CaptureSemaphoreParameterui64vEXT_params(const State &glState, } void CaptureSignalSemaphoreEXT_buffersPacked(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLuint numBufferBarriers, const BufferID *buffers, @@ -2724,7 +2837,6 @@ void CaptureSignalSemaphoreEXT_buffersPacked(const State &glState, } void CaptureSignalSemaphoreEXT_texturesPacked(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLuint numBufferBarriers, const BufferID *buffers, @@ -2737,7 +2849,6 @@ void CaptureSignalSemaphoreEXT_texturesPacked(const State &glState, } void CaptureSignalSemaphoreEXT_dstLayouts(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLuint numBufferBarriers, const BufferID *buffers, @@ -2751,7 +2862,6 @@ void CaptureSignalSemaphoreEXT_dstLayouts(const State &glState, } void CaptureWaitSemaphoreEXT_buffersPacked(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLuint numBufferBarriers, const BufferID *buffers, @@ -2764,7 +2874,6 @@ void CaptureWaitSemaphoreEXT_buffersPacked(const State &glState, } void CaptureWaitSemaphoreEXT_texturesPacked(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLuint numBufferBarriers, const BufferID *buffers, @@ -2777,7 +2886,6 @@ void CaptureWaitSemaphoreEXT_texturesPacked(const State &glState, } void CaptureWaitSemaphoreEXT_srcLayouts(const State &glState, - bool isCallValid, SemaphoreID semaphore, GLuint numBufferBarriers, const BufferID *buffers, @@ -2789,1710 +2897,1111 @@ void CaptureWaitSemaphoreEXT_srcLayouts(const State &glState, CaptureArray(srcLayouts, (numBufferBarriers + numTextureBarriers), paramCapture); } -void CaptureGetSamplerParameterIivEXT_params(const State &glState, - bool isCallValid, - SamplerID samplerPacked, - GLenum pname, - GLint *params, - angle::ParamCapture *paramCapture) +// GL_EXT_separate_shader_objects +void CaptureCreateShaderProgramvEXT_strings(const State &glState, + ShaderType typePacked, + GLsizei count, + const GLchar *const *strings, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetSamplerParameterIuivEXT_params(const State &glState, - bool isCallValid, - SamplerID samplerPacked, - GLenum pname, - GLuint *params, - angle::ParamCapture *paramCapture) +void CaptureDeleteProgramPipelinesEXT_pipelinesPacked(const State &glState, + GLsizei n, + const ProgramPipelineID *pipelinesPacked, + angle::ParamCapture *paramCapture) { - // Skipped + CaptureArray(pipelinesPacked, n, paramCapture); } -void CaptureGetTexParameterIivEXT_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - GLint *params, - angle::ParamCapture *paramCapture) +void CaptureGenProgramPipelinesEXT_pipelinesPacked(const State &glState, + GLsizei n, + ProgramPipelineID *pipelinesPacked, + angle::ParamCapture *paramCapture) { - // Skipped + CaptureGenHandles(n, pipelinesPacked, paramCapture); } -void CaptureGetTexParameterIuivEXT_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - GLuint *params, - angle::ParamCapture *paramCapture) +void CaptureGetProgramPipelineInfoLogEXT_length(const State &glState, + ProgramPipelineID pipelinePacked, + GLsizei bufSize, + GLsizei *length, + GLchar *infoLog, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureSamplerParameterIivEXT_param(const State &glState, - bool isCallValid, - SamplerID samplerPacked, - GLenum pname, - const GLint *param, - angle::ParamCapture *paramCapture) +void CaptureGetProgramPipelineInfoLogEXT_infoLog(const State &glState, + ProgramPipelineID pipelinePacked, + GLsizei bufSize, + GLsizei *length, + GLchar *infoLog, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureSamplerParameterIuivEXT_param(const State &glState, - bool isCallValid, - SamplerID samplerPacked, - GLenum pname, - const GLuint *param, - angle::ParamCapture *paramCapture) +void CaptureGetProgramPipelineivEXT_params(const State &glState, + ProgramPipelineID pipelinePacked, + GLenum pname, + GLint *params, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureTexParameterIivEXT_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - const GLint *params, - angle::ParamCapture *paramCapture) +void CaptureProgramUniform1fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureTexParameterIuivEXT_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - const GLuint *params, +void CaptureProgramUniform1ivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLint *value, angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureDebugMessageCallbackKHR_userParam(const State &glState, - bool isCallValid, - GLDEBUGPROCKHR callback, - const void *userParam, - ParamCapture *paramCapture) +void CaptureProgramUniform1uivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLuint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureDebugMessageControlKHR_ids(const State &glState, - bool isCallValid, - GLenum source, - GLenum type, - GLenum severity, +void CaptureProgramUniform2fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, GLsizei count, - const GLuint *ids, - GLboolean enabled, - ParamCapture *paramCapture) -{ - // Skipped -} - -void CaptureDebugMessageInsertKHR_buf(const State &glState, - bool isCallValid, - GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *buf, - ParamCapture *paramCapture) + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetDebugMessageLogKHR_sources(const State &glState, - bool isCallValid, - GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog, - ParamCapture *paramCapture) +void CaptureProgramUniform2ivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetDebugMessageLogKHR_types(const State &glState, - bool isCallValid, - GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog, - ParamCapture *paramCapture) +void CaptureProgramUniform2uivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLuint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetDebugMessageLogKHR_ids(const State &glState, - bool isCallValid, - GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog, - ParamCapture *paramCapture) +void CaptureProgramUniform3fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetDebugMessageLogKHR_severities(const State &glState, - bool isCallValid, - GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog, - ParamCapture *paramCapture) +void CaptureProgramUniform3ivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetDebugMessageLogKHR_lengths(const State &glState, - bool isCallValid, - GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog, - ParamCapture *paramCapture) +void CaptureProgramUniform3uivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLuint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetDebugMessageLogKHR_messageLog(const State &glState, - bool isCallValid, - GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog, - ParamCapture *paramCapture) +void CaptureProgramUniform4fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectLabelKHR_length(const State &glState, - bool isCallValid, - GLenum identifier, - GLuint name, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniform4ivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectLabelKHR_label(const State &glState, - bool isCallValid, - GLenum identifier, - GLuint name, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniform4uivEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + const GLuint *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectLabelEXT_length(const State &glState, - bool isCallValid, - GLenum type, - GLuint object, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - angle::ParamCapture *paramCapture) +void CaptureProgramUniformMatrix2fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectLabelEXT_label(const State &glState, - bool isCallValid, - GLenum type, - GLuint object, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - angle::ParamCapture *paramCapture) +void CaptureProgramUniformMatrix2x3fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureLabelObjectEXT_label(const State &glState, - bool isCallValid, - GLenum type, - GLuint object, - GLsizei length, - const GLchar *label, - angle::ParamCapture *paramCapture) +void CaptureProgramUniformMatrix2x4fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectPtrLabelKHR_ptr(const State &glState, - bool isCallValid, - const void *ptr, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniformMatrix3fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectPtrLabelKHR_length(const State &glState, - bool isCallValid, - const void *ptr, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniformMatrix3x2fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetObjectPtrLabelKHR_label(const State &glState, - bool isCallValid, - const void *ptr, - GLsizei bufSize, - GLsizei *length, - GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniformMatrix3x4fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureGetPointervKHR_params(const State &glState, - bool isCallValid, - GLenum pname, - void **params, - ParamCapture *paramCapture) +void CaptureProgramUniformMatrix4fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureObjectLabelKHR_label(const State &glState, - bool isCallValid, - GLenum identifier, - GLuint name, - GLsizei length, - const GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniformMatrix4x2fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureObjectPtrLabelKHR_ptr(const State &glState, - bool isCallValid, - const void *ptr, - GLsizei length, - const GLchar *label, - ParamCapture *paramCapture) +void CaptureProgramUniformMatrix4x3fvEXT_value(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + angle::ParamCapture *paramCapture) { - // Skipped + UNIMPLEMENTED(); } -void CaptureObjectPtrLabelKHR_label(const State &glState, - bool isCallValid, - const void *ptr, - GLsizei length, - const GLchar *label, - ParamCapture *paramCapture) +// GL_EXT_texture_border_clamp +void CaptureGetSamplerParameterIivEXT_params(const State &glState, + SamplerID samplerPacked, + GLenum pname, + GLint *params, + angle::ParamCapture *paramCapture) { // Skipped } -void CapturePushDebugGroupKHR_message(const State &glState, - bool isCallValid, - GLenum source, - GLuint id, - GLsizei length, - const GLchar *message, - ParamCapture *paramCapture) +void CaptureGetSamplerParameterIuivEXT_params(const State &glState, + SamplerID samplerPacked, + GLenum pname, + GLuint *params, + angle::ParamCapture *paramCapture) { // Skipped } -void CaptureGetFramebufferParameterivMESA_params(const State &glState, - bool isCallValid, - GLenum target, - GLenum pname, - GLint *params, - angle::ParamCapture *paramCapture) +void CaptureGetTexParameterIivEXT_params(const State &glState, + TextureType targetPacked, + GLenum pname, + GLint *params, + angle::ParamCapture *paramCapture) { // Skipped } -void CaptureDeleteFencesNV_fencesPacked(const State &glState, - bool isCallValid, - GLsizei n, - const FenceNVID *fences, - ParamCapture *paramCapture) +void CaptureGetTexParameterIuivEXT_params(const State &glState, + TextureType targetPacked, + GLenum pname, + GLuint *params, + angle::ParamCapture *paramCapture) { - CaptureMemory(fences, n * sizeof(FenceNVID), paramCapture); + // Skipped } -void CaptureGenFencesNV_fencesPacked(const State &glState, - bool isCallValid, - GLsizei n, - FenceNVID *fences, - ParamCapture *paramCapture) +void CaptureSamplerParameterIivEXT_param(const State &glState, + SamplerID samplerPacked, + GLenum pname, + const GLint *param, + angle::ParamCapture *paramCapture) { - CaptureGenHandles(n, fences, paramCapture); + // Skipped } -void CaptureGetFenceivNV_params(const State &glState, - bool isCallValid, - FenceNVID fence, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) +void CaptureSamplerParameterIuivEXT_param(const State &glState, + SamplerID samplerPacked, + GLenum pname, + const GLuint *param, + angle::ParamCapture *paramCapture) { - CaptureMemory(params, sizeof(GLint), paramCapture); + // Skipped } -void CaptureDrawTexfvOES_coords(const State &glState, - bool isCallValid, - const GLfloat *coords, - ParamCapture *paramCapture) +void CaptureTexParameterIivEXT_params(const State &glState, + TextureType targetPacked, + GLenum pname, + const GLint *params, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureDrawTexivOES_coords(const State &glState, - bool isCallValid, - const GLint *coords, - ParamCapture *paramCapture) +void CaptureTexParameterIuivEXT_params(const State &glState, + TextureType targetPacked, + GLenum pname, + const GLuint *params, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureTexParameterIuiv_params(glState, targetPacked, pname, params, paramCapture); } -void CaptureDrawTexsvOES_coords(const State &glState, - bool isCallValid, - const GLshort *coords, - ParamCapture *paramCapture) +// GL_EXT_texture_storage_compression +void CaptureTexStorageAttribs2DEXT_attrib_list(const State &glState, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + const GLint *attrib_list, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureDrawTexxvOES_coords(const State &glState, - bool isCallValid, - const GLfixed *coords, - ParamCapture *paramCapture) +void CaptureTexStorageAttribs3DEXT_attrib_list(const State &glState, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + const GLint *attrib_list, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureDeleteFramebuffersOES_framebuffersPacked(const State &glState, - bool isCallValid, - GLsizei n, - const FramebufferID *framebuffers, - ParamCapture *paramCapture) +// GL_KHR_debug +void CaptureDebugMessageCallbackKHR_userParam(const State &glState, + GLDEBUGPROCKHR callback, + const void *userParam, + ParamCapture *paramCapture) { - CaptureArray(framebuffers, n, paramCapture); + // Skipped } -void CaptureDeleteRenderbuffersOES_renderbuffersPacked(const State &glState, - bool isCallValid, - GLsizei n, - const RenderbufferID *renderbuffers, - ParamCapture *paramCapture) +void CaptureDebugMessageControlKHR_ids(const State &glState, + GLenum source, + GLenum type, + GLenum severity, + GLsizei count, + const GLuint *ids, + GLboolean enabled, + ParamCapture *paramCapture) { - CaptureArray(renderbuffers, n, paramCapture); + // Skipped } -void CaptureGenFramebuffersOES_framebuffersPacked(const State &glState, - bool isCallValid, - GLsizei n, - FramebufferID *framebuffers, - ParamCapture *paramCapture) +void CaptureDebugMessageInsertKHR_buf(const State &glState, + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *buf, + ParamCapture *paramCapture) { - CaptureGenHandles(n, framebuffers, paramCapture); + // Skipped } -void CaptureGenRenderbuffersOES_renderbuffersPacked(const State &glState, - bool isCallValid, - GLsizei n, - RenderbufferID *renderbuffers, - ParamCapture *paramCapture) +void CaptureGetDebugMessageLogKHR_sources(const State &glState, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog, + ParamCapture *paramCapture) { - CaptureGenHandles(n, renderbuffers, paramCapture); + // Skipped } -void CaptureGetFramebufferAttachmentParameterivOES_params(const State &glState, - bool isCallValid, - GLenum target, - GLenum attachment, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) -{ - CaptureMemory(params, sizeof(GLint), paramCapture); -} - -void CaptureGetRenderbufferParameterivOES_params(const State &glState, - bool isCallValid, - GLenum target, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) +void CaptureGetDebugMessageLogKHR_types(const State &glState, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog, + ParamCapture *paramCapture) { - CaptureMemory(params, sizeof(GLint), paramCapture); + // Skipped } -void CaptureGetProgramBinaryOES_length(const State &glState, - bool isCallValid, - ShaderProgramID program, - GLsizei bufSize, - GLsizei *length, - GLenum *binaryFormat, - void *binary, - ParamCapture *paramCapture) +void CaptureGetDebugMessageLogKHR_ids(const State &glState, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLsizei); + // Skipped } -void CaptureGetProgramBinaryOES_binaryFormat(const State &glState, - bool isCallValid, - ShaderProgramID program, +void CaptureGetDebugMessageLogKHR_severities(const State &glState, + GLuint count, GLsizei bufSize, - GLsizei *length, - GLenum *binaryFormat, - void *binary, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog, ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLenum); -} - -void CaptureGetProgramBinaryOES_binary(const State &glState, - bool isCallValid, - ShaderProgramID program, - GLsizei bufSize, - GLsizei *length, - GLenum *binaryFormat, - void *binary, - ParamCapture *paramCapture) -{ - paramCapture->readBufferSizeBytes = bufSize; -} - -void CaptureProgramBinaryOES_binary(const State &glState, - bool isCallValid, - ShaderProgramID program, - GLenum binaryFormat, - const void *binary, - GLint length, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetBufferPointervOES_params(const State &glState, - bool isCallValid, - BufferBinding targetPacked, - GLenum pname, - void **params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); + // Skipped } -void CaptureMatrixIndexPointerOES_pointer(const State &glState, - bool isCallValid, - GLint size, - GLenum type, - GLsizei stride, - const void *pointer, +void CaptureGetDebugMessageLogKHR_lengths(const State &glState, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog, ParamCapture *paramCapture) { - UNIMPLEMENTED(); -} - -void CaptureWeightPointerOES_pointer(const State &glState, - bool isCallValid, - GLint size, - GLenum type, - GLsizei stride, - const void *pointer, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CapturePointSizePointerOES_pointer(const State &glState, - bool isCallValid, - VertexAttribType typePacked, - GLsizei stride, - const void *pointer, - ParamCapture *paramCapture) -{ - CaptureVertexPointerGLES1(glState, ClientVertexArrayType::PointSize, pointer, paramCapture); + // Skipped } -void CaptureQueryMatrixxOES_mantissa(const State &glState, - bool isCallValid, - GLfixed *mantissa, - GLint *exponent, - ParamCapture *paramCapture) +void CaptureGetDebugMessageLogKHR_messageLog(const State &glState, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureQueryMatrixxOES_exponent(const State &glState, - bool isCallValid, - GLfixed *mantissa, - GLint *exponent, +void CaptureGetObjectLabelKHR_length(const State &glState, + GLenum identifier, + GLuint name, + GLsizei bufSize, + GLsizei *length, + GLchar *label, ParamCapture *paramCapture) { - UNIMPLEMENTED(); -} - -void CaptureCompressedTexImage3DOES_data(const State &glState, - bool isCallValid, - TextureTarget targetPacked, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLsizei imageSize, - const void *data, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureCompressedTexSubImage3DOES_data(const State &glState, - bool isCallValid, - TextureTarget targetPacked, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLsizei imageSize, - const void *data, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); + // Skipped } -void CaptureTexImage3DOES_pixels(const State &glState, - bool isCallValid, - TextureTarget targetPacked, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - const void *pixels, - ParamCapture *paramCapture) +void CaptureGetObjectLabelKHR_label(const State &glState, + GLenum identifier, + GLuint name, + GLsizei bufSize, + GLsizei *length, + GLchar *label, + ParamCapture *paramCapture) { - CaptureTexImage3D_pixels(glState, isCallValid, targetPacked, level, internalformat, width, - height, depth, border, format, type, pixels, paramCapture); + // Skipped } -void CaptureTexSubImage3DOES_pixels(const State &glState, - bool isCallValid, - TextureTarget targetPacked, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *pixels, - ParamCapture *paramCapture) +void CaptureGetObjectPtrLabelKHR_ptr(const State &glState, + const void *ptr, + GLsizei bufSize, + GLsizei *length, + GLchar *label, + ParamCapture *paramCapture) { - CaptureTexSubImage3D_pixels(glState, isCallValid, targetPacked, level, xoffset, yoffset, - zoffset, width, height, depth, format, type, pixels, paramCapture); + // Skipped } -void CaptureGetSamplerParameterIivOES_params(const State &glState, - bool isCallValid, - SamplerID sampler, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) +void CaptureGetObjectPtrLabelKHR_length(const State &glState, + const void *ptr, + GLsizei bufSize, + GLsizei *length, + GLchar *label, + ParamCapture *paramCapture) { - CaptureGetSamplerParameterIiv_params(glState, isCallValid, sampler, pname, params, - paramCapture); + // Skipped } -void CaptureGetSamplerParameterIuivOES_params(const State &glState, - bool isCallValid, - SamplerID sampler, - GLenum pname, - GLuint *params, - ParamCapture *paramCapture) +void CaptureGetObjectPtrLabelKHR_label(const State &glState, + const void *ptr, + GLsizei bufSize, + GLsizei *length, + GLchar *label, + ParamCapture *paramCapture) { - CaptureGetSamplerParameterIuiv_params(glState, isCallValid, sampler, pname, params, - paramCapture); + // Skipped } -void CaptureGetTexParameterIivOES_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) +void CaptureGetPointervKHR_params(const State &glState, + GLenum pname, + void **params, + ParamCapture *paramCapture) { - CaptureGetTexParameterIiv_params(glState, isCallValid, targetPacked, pname, params, - paramCapture); + // Skipped } -void CaptureGetTexParameterIuivOES_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - GLuint *params, - ParamCapture *paramCapture) -{ - CaptureGetTexParameterIuiv_params(glState, isCallValid, targetPacked, pname, params, - paramCapture); -} - -void CaptureSamplerParameterIivOES_param(const State &glState, - bool isCallValid, - SamplerID sampler, - GLenum pname, - const GLint *param, - ParamCapture *paramCapture) -{ - CaptureSamplerParameterIiv_param(glState, isCallValid, sampler, pname, param, paramCapture); -} - -void CaptureSamplerParameterIuivOES_param(const State &glState, - bool isCallValid, - SamplerID sampler, - GLenum pname, - const GLuint *param, - ParamCapture *paramCapture) -{ - CaptureSamplerParameterIuiv_param(glState, isCallValid, sampler, pname, param, paramCapture); -} - -void CaptureTexParameterIivOES_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - const GLint *params, - ParamCapture *paramCapture) -{ - CaptureTexParameterIiv_params(glState, isCallValid, targetPacked, pname, params, paramCapture); -} - -void CaptureTexParameterIuivOES_params(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLenum pname, - const GLuint *params, - ParamCapture *paramCapture) -{ - CaptureTexParameterIuiv_params(glState, isCallValid, targetPacked, pname, params, paramCapture); -} - -void CaptureGetTexGenfvOES_params(const State &glState, - bool isCallValid, - GLenum coord, - GLenum pname, - GLfloat *params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetTexGenivOES_params(const State &glState, - bool isCallValid, - GLenum coord, - GLenum pname, - GLint *params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetTexGenxvOES_params(const State &glState, - bool isCallValid, - GLenum coord, - GLenum pname, - GLfixed *params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureTexGenfvOES_params(const State &glState, - bool isCallValid, - GLenum coord, - GLenum pname, - const GLfloat *params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureTexGenivOES_params(const State &glState, - bool isCallValid, - GLenum coord, - GLenum pname, - const GLint *params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureTexGenxvOES_params(const State &glState, - bool isCallValid, - GLenum coord, - GLenum pname, - const GLfixed *params, - ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureDeleteVertexArraysOES_arraysPacked(const State &glState, - bool isCallValid, - GLsizei n, - const VertexArrayID *arrays, - ParamCapture *paramCapture) -{ - CaptureDeleteVertexArrays_arraysPacked(glState, isCallValid, n, arrays, paramCapture); -} - -void CaptureGenVertexArraysOES_arraysPacked(const State &glState, - bool isCallValid, - GLsizei n, - VertexArrayID *arrays, - ParamCapture *paramCapture) -{ - CaptureGenVertexArrays_arraysPacked(glState, isCallValid, n, arrays, paramCapture); -} - -void CaptureBlobCacheCallbacksANGLE_userParam(const State &glState, - bool isCallValid, - GLSETBLOBPROCANGLE set, - GLGETBLOBPROCANGLE get, - const void *userParam, - angle::ParamCapture *paramCapture) -{ - // Skipped -} - -void CaptureGetPointervANGLE_params(const State &glState, - bool isCallValid, - GLenum pname, - void **params, - angle::ParamCapture *paramCapture) -{ - // Skipped -} - -void CaptureGetTexImageANGLE_pixels(const State &glState, - bool isCallValid, - TextureTarget target, - GLint level, - GLenum format, - GLenum type, - void *pixels, - angle::ParamCapture *paramCapture) -{ - if (glState.getTargetBuffer(gl::BufferBinding::PixelPack)) - { - // If a pixel pack buffer is bound, this is an offset, not a pointer - paramCapture->value.voidPointerVal = pixels; - return; - } - - const Texture *texture = glState.getTargetTexture(TextureTargetToType(target)); - ASSERT(texture); - - // Use a conservative upper bound instead of an exact size to be simple. - static constexpr GLsizei kMaxPixelSize = 32; - size_t width = texture->getWidth(target, level); - size_t height = texture->getHeight(target, level); - size_t depth = texture->getDepth(target, level); - paramCapture->readBufferSizeBytes = kMaxPixelSize * width * height * depth; -} - -void CaptureGetCompressedTexImageANGLE_pixels(const State &glState, - bool isCallValid, - TextureTarget target, - GLint level, - void *pixels, - angle::ParamCapture *paramCapture) -{ - const Texture *texture = glState.getTargetTexture(TextureTargetToType(target)); - ASSERT(texture); - const gl::InternalFormat *formatInfo = texture->getFormat(target, level).info; - const gl::Extents &levelExtents = texture->getExtents(target, level); - - GLuint size; - bool result = formatInfo->computeCompressedImageSize(levelExtents, &size); - ASSERT(result); - paramCapture->readBufferSizeBytes = size; -} - -void CaptureGetRenderbufferImageANGLE_pixels(const State &glState, - bool isCallValid, - GLenum target, - GLenum format, - GLenum type, - void *pixels, - angle::ParamCapture *paramCapture) -{ - if (glState.getTargetBuffer(gl::BufferBinding::PixelPack)) - { - // If a pixel pack buffer is bound, this is an offset, not a pointer - paramCapture->value.voidPointerVal = pixels; - return; - } - - const Renderbuffer *renderbuffer = glState.getCurrentRenderbuffer(); - ASSERT(renderbuffer); - - // Use a conservative upper bound instead of an exact size to be simple. - static constexpr GLsizei kMaxPixelSize = 32; - size_t width = renderbuffer->getWidth(); - size_t height = renderbuffer->getHeight(); - paramCapture->readBufferSizeBytes = kMaxPixelSize * width * height; -} - -void CaptureBufferStorageEXT_data(const State &glState, - bool isCallValid, - BufferBinding targetPacked, - GLsizeiptr size, - const void *data, - GLbitfield flags, - angle::ParamCapture *paramCapture) -{ - if (data) - { - CaptureMemory(data, size, paramCapture); - } -} - -// GL_EXT_clear_texture -void CaptureClearTexImageEXT_data(const State &glState, - bool isCallValid, - TextureID texturePacked, - GLint level, - GLenum format, - GLenum type, - const void *data, - angle::ParamCapture *paramCapture) -{ - if (!data) - { - return; - } - - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format, type); - GLuint captureSize = internalFormatInfo.computePixelBytes(type); - CaptureMemory(data, captureSize, paramCapture); -} - -void CaptureClearTexSubImageEXT_data(const State &glState, - bool isCallValid, - TextureID texturePacked, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *data, - angle::ParamCapture *paramCapture) -{ - if (!data) - { - return; - } - - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format, type); - GLuint captureSize = internalFormatInfo.computePixelBytes(type); - CaptureMemory(data, captureSize, paramCapture); -} - -// GL_EXT_separate_shader_objects -void CaptureCreateShaderProgramvEXT_strings(const State &glState, - bool isCallValid, - ShaderType typePacked, - GLsizei count, - const GLchar **strings, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureDeleteProgramPipelinesEXT_pipelinesPacked(const State &glState, - bool isCallValid, - GLsizei n, - const ProgramPipelineID *pipelinesPacked, - angle::ParamCapture *paramCapture) -{ - CaptureArray(pipelinesPacked, n, paramCapture); -} - -void CaptureGenProgramPipelinesEXT_pipelinesPacked(const State &glState, - bool isCallValid, - GLsizei n, - ProgramPipelineID *pipelinesPacked, - angle::ParamCapture *paramCapture) -{ - CaptureGenHandles(n, pipelinesPacked, paramCapture); -} - -void CaptureGetProgramPipelineInfoLogEXT_length(const State &glState, - bool isCallValid, - ProgramPipelineID pipelinePacked, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetProgramPipelineInfoLogEXT_infoLog(const State &glState, - bool isCallValid, - ProgramPipelineID pipelinePacked, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureGetProgramPipelineivEXT_params(const State &glState, - bool isCallValid, - ProgramPipelineID pipelinePacked, - GLenum pname, - GLint *params, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureProgramUniform1fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLfloat *value, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureProgramUniform1ivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLint *value, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureProgramUniform1uivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLuint *value, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureProgramUniform2fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureObjectLabelKHR_label(const State &glState, + GLenum identifier, + GLuint name, + GLsizei length, + const GLchar *label, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureProgramUniform2ivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLint *value, - angle::ParamCapture *paramCapture) +void CaptureObjectPtrLabelKHR_ptr(const State &glState, + const void *ptr, + GLsizei length, + const GLchar *label, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureProgramUniform2uivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLuint *value, - angle::ParamCapture *paramCapture) +void CaptureObjectPtrLabelKHR_label(const State &glState, + const void *ptr, + GLsizei length, + const GLchar *label, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureProgramUniform3fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CapturePushDebugGroupKHR_message(const State &glState, + GLenum source, + GLuint id, + GLsizei length, + const GLchar *message, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureProgramUniform3ivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLint *value, - angle::ParamCapture *paramCapture) +// GL_KHR_robustness +void CaptureGetnUniformfvKHR_params(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei bufSize, + GLfloat *params, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureProgramUniform3uivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLuint *value, - angle::ParamCapture *paramCapture) +void CaptureGetnUniformivKHR_params(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei bufSize, + GLint *params, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureProgramUniform4fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureGetnUniformuivKHR_params(const State &glState, + ShaderProgramID programPacked, + UniformLocation locationPacked, + GLsizei bufSize, + GLuint *params, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureProgramUniform4ivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLint *value, - angle::ParamCapture *paramCapture) +void CaptureReadnPixelsKHR_data(const State &glState, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufSize, + void *data, + angle::ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureProgramUniform4uivEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - const GLuint *value, - angle::ParamCapture *paramCapture) +// GL_MESA_framebuffer_flip_y +void CaptureGetFramebufferParameterivMESA_params(const State &glState, + GLenum target, + GLenum pname, + GLint *params, + angle::ParamCapture *paramCapture) { - UNIMPLEMENTED(); + // Skipped } -void CaptureProgramUniformMatrix2fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +// GL_NV_fence +void CaptureDeleteFencesNV_fencesPacked(const State &glState, + GLsizei n, + const FenceNVID *fences, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureMemory(fences, n * sizeof(FenceNVID), paramCapture); } -void CaptureProgramUniformMatrix2x3fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureGenFencesNV_fencesPacked(const State &glState, + GLsizei n, + FenceNVID *fences, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGenHandles(n, fences, paramCapture); } -void CaptureProgramUniformMatrix2x4fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureGetFenceivNV_params(const State &glState, + FenceNVID fence, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureMemory(params, sizeof(GLint), paramCapture); } -void CaptureProgramUniformMatrix3fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +// GL_OES_draw_elements_base_vertex +void CaptureDrawElementsBaseVertexOES_indices(const State &glState, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLint basevertex, + ParamCapture *indicesParam) { - UNIMPLEMENTED(); + CaptureDrawElements_indices(glState, modePacked, count, typePacked, indices, indicesParam); } -void CaptureProgramUniformMatrix3x2fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureDrawElementsInstancedBaseVertexOES_indices(const State &glState, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLsizei instancecount, + GLint basevertex, + ParamCapture *indicesParam) { UNIMPLEMENTED(); } -void CaptureProgramUniformMatrix3x4fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureDrawRangeElementsBaseVertexOES_indices(const State &glState, + PrimitiveMode modePacked, + GLuint start, + GLuint end, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLint basevertex, + ParamCapture *indicesParam) { UNIMPLEMENTED(); } -void CaptureProgramUniformMatrix4fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +// GL_OES_draw_texture +void CaptureDrawTexfvOES_coords(const State &glState, + const GLfloat *coords, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureProgramUniformMatrix4x2fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureDrawTexivOES_coords(const State &glState, + const GLint *coords, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureProgramUniformMatrix4x3fvEXT_value(const State &glState, - bool isCallValid, - ShaderProgramID programPacked, - UniformLocation locationPacked, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureDrawTexsvOES_coords(const State &glState, + const GLshort *coords, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureEGLImageTargetTexStorageEXT_attrib_list(const State &glState, - bool isCallValid, - GLenum target, - egl::ImageID image, - const GLint *attrib_list, - angle::ParamCapture *paramCapture) +void CaptureDrawTexxvOES_coords(const State &glState, + const GLfixed *coords, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureEGLImageTargetTextureStorageEXT_attrib_list(const State &glState, - bool isCallValid, - GLuint texture, - egl::ImageID image, - const GLint *attrib_list, - angle::ParamCapture *paramCapture) +// GL_OES_framebuffer_object +void CaptureDeleteFramebuffersOES_framebuffersPacked(const State &glState, + GLsizei n, + const FramebufferID *framebuffers, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(framebuffers, n, paramCapture); } -void CaptureTexStorageMemFlags2DANGLE_imageCreateInfoPNext(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - MemoryObjectID memoryPacked, - GLuint64 offset, - GLbitfield createFlags, - GLbitfield usageFlags, - const void *imageCreateInfoPNext, - angle::ParamCapture *paramCapture) +void CaptureDeleteRenderbuffersOES_renderbuffersPacked(const State &glState, + GLsizei n, + const RenderbufferID *renderbuffers, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureArray(renderbuffers, n, paramCapture); } -void CaptureTexStorageMemFlags2DMultisampleANGLE_imageCreateInfoPNext( - const State &glState, - bool isCallValid, - TextureType targetPacked, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLboolean fixedSampleLocations, - MemoryObjectID memoryPacked, - GLuint64 offset, - GLbitfield createFlags, - GLbitfield usageFlags, - const void *imageCreateInfoPNext, - angle::ParamCapture *paramCapture) +void CaptureGenFramebuffersOES_framebuffersPacked(const State &glState, + GLsizei n, + FramebufferID *framebuffers, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGenHandles(n, framebuffers, paramCapture); } -void CaptureTexStorageMemFlags3DANGLE_imageCreateInfoPNext(const State &glState, - bool isCallValid, - TextureType targetPacked, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - MemoryObjectID memoryPacked, - GLuint64 offset, - GLbitfield createFlags, - GLbitfield usageFlags, - const void *imageCreateInfoPNext, - angle::ParamCapture *paramCapture) +void CaptureGenRenderbuffersOES_renderbuffersPacked(const State &glState, + GLsizei n, + RenderbufferID *renderbuffers, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGenHandles(n, renderbuffers, paramCapture); } -void CaptureTexStorageMemFlags3DMultisampleANGLE_imageCreateInfoPNext( - const State &glState, - bool isCallValid, - TextureType targetPacked, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedSampleLocations, - MemoryObjectID memoryPacked, - GLuint64 offset, - GLbitfield createFlags, - GLbitfield usageFlags, - const void *imageCreateInfoPNext, - angle::ParamCapture *paramCapture) +void CaptureGetFramebufferAttachmentParameterivOES_params(const State &glState, + GLenum target, + GLenum attachment, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureMemory(params, sizeof(GLint), paramCapture); } -void CaptureAcquireTexturesANGLE_texturesPacked(const State &glState, - bool isCallValid, - GLuint numTextures, - const TextureID *textures, - const GLenum *layouts, - angle::ParamCapture *paramCapture) +void CaptureGetRenderbufferParameterivOES_params(const State &glState, + GLenum target, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - CaptureArray(textures, numTextures, paramCapture); + CaptureMemory(params, sizeof(GLint), paramCapture); } -void CaptureAcquireTexturesANGLE_layouts(const State &glState, - bool isCallValid, - GLuint numTextures, - const TextureID *texturesPacked, - const GLenum *layouts, - angle::ParamCapture *paramCapture) +// GL_OES_get_program_binary +void CaptureGetProgramBinaryOES_length(const State &glState, + ShaderProgramID program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary, + ParamCapture *paramCapture) { - CaptureArray(layouts, numTextures * sizeof(GLenum), paramCapture); + paramCapture->readBufferSizeBytes = sizeof(GLsizei); } -void CaptureReleaseTexturesANGLE_texturesPacked(const State &glState, - bool isCallValid, - GLuint numTextures, - const TextureID *textures, - GLenum *layouts, - angle::ParamCapture *paramCapture) +void CaptureGetProgramBinaryOES_binaryFormat(const State &glState, + ShaderProgramID program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary, + ParamCapture *paramCapture) { - CaptureArray(textures, numTextures, paramCapture); + paramCapture->readBufferSizeBytes = sizeof(GLenum); } -void CaptureReleaseTexturesANGLE_layouts(const State &glState, - bool isCallValid, - GLuint numTextures, - const TextureID *texturesPacked, - GLenum *layouts, - angle::ParamCapture *paramCapture) +void CaptureGetProgramBinaryOES_binary(const State &glState, + ShaderProgramID program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary, + ParamCapture *paramCapture) +{ + paramCapture->readBufferSizeBytes = bufSize; +} + +void CaptureProgramBinaryOES_binary(const State &glState, + ShaderProgramID program, + GLenum binaryFormat, + const void *binary, + GLint length, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureDeletePerfMonitorsAMD_monitors(const State &glState, - bool isCallValid, - GLsizei n, - GLuint *monitors, - angle::ParamCapture *paramCapture) +// GL_OES_mapbuffer +void CaptureGetBufferPointervOES_params(const State &glState, + BufferBinding targetPacked, + GLenum pname, + void **params, + ParamCapture *paramCapture) { - CaptureArray(monitors, n, paramCapture); + UNIMPLEMENTED(); } -void CaptureGenPerfMonitorsAMD_monitors(const State &glState, - bool isCallValid, - GLsizei n, - GLuint *monitors, - angle::ParamCapture *paramCapture) +// GL_OES_matrix_palette +void CaptureMatrixIndexPointerOES_pointer(const State &glState, + GLint size, + GLenum type, + GLsizei stride, + const void *pointer, + ParamCapture *paramCapture) { - CaptureArray(monitors, n, paramCapture); + UNIMPLEMENTED(); } -void CaptureGetPerfMonitorCounterDataAMD_data(const State &glState, - bool isCallValid, - GLuint monitor, - GLenum pname, - GLsizei dataSize, - GLuint *data, - GLint *bytesWritten, - angle::ParamCapture *paramCapture) +void CaptureWeightPointerOES_pointer(const State &glState, + GLint size, + GLenum type, + GLsizei stride, + const void *pointer, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = dataSize; + UNIMPLEMENTED(); } -void CaptureGetPerfMonitorCounterDataAMD_bytesWritten(const State &glState, - bool isCallValid, - GLuint monitor, - GLenum pname, - GLsizei dataSize, - GLuint *data, - GLint *bytesWritten, - angle::ParamCapture *paramCapture) +// GL_OES_point_size_array +void CapturePointSizePointerOES_pointer(const State &glState, + VertexAttribType typePacked, + GLsizei stride, + const void *pointer, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLint); + CaptureVertexPointerGLES1(glState, ClientVertexArrayType::PointSize, pointer, paramCapture); } -void CaptureGetPerfMonitorCounterInfoAMD_data(const State &glState, - bool isCallValid, - GLuint group, - GLuint counter, - GLenum pname, - void *data, - angle::ParamCapture *paramCapture) +// GL_OES_query_matrix +void CaptureQueryMatrixxOES_mantissa(const State &glState, + GLfixed *mantissa, + GLint *exponent, + ParamCapture *paramCapture) { UNIMPLEMENTED(); } -void CaptureGetPerfMonitorCounterStringAMD_length(const State &glState, - bool isCallValid, - GLuint group, - GLuint counter, - GLsizei bufSize, - GLsizei *length, - GLchar *counterString, - angle::ParamCapture *paramCapture) +void CaptureQueryMatrixxOES_exponent(const State &glState, + GLfixed *mantissa, + GLint *exponent, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLsizei); + UNIMPLEMENTED(); } -void CaptureGetPerfMonitorCounterStringAMD_counterString(const State &glState, - bool isCallValid, - GLuint group, - GLuint counter, - GLsizei bufSize, - GLsizei *length, - GLchar *counterString, - angle::ParamCapture *paramCapture) +// GL_OES_texture_3D +void CaptureCompressedTexImage3DOES_data(const State &glState, + TextureTarget targetPacked, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLsizei imageSize, + const void *data, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = bufSize; + CaptureCompressedTexImage3D_data(glState, targetPacked, level, internalformat, width, height, + depth, border, imageSize, data, paramCapture); } -void CaptureGetPerfMonitorCountersAMD_numCounters(const State &glState, - bool isCallValid, - GLuint group, - GLint *numCounters, - GLint *maxActiveCounters, - GLsizei counterSize, - GLuint *counters, - angle::ParamCapture *paramCapture) +void CaptureCompressedTexSubImage3DOES_data(const State &glState, + TextureTarget targetPacked, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLsizei imageSize, + const void *data, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLint); + UNIMPLEMENTED(); } -void CaptureGetPerfMonitorCountersAMD_maxActiveCounters(const State &glState, - bool isCallValid, - GLuint group, - GLint *numCounters, - GLint *maxActiveCounters, - GLsizei counterSize, - GLuint *counters, - angle::ParamCapture *paramCapture) +void CaptureTexImage3DOES_pixels(const State &glState, + TextureTarget targetPacked, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const void *pixels, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLint); + CaptureTexImage3D_pixels(glState, targetPacked, level, internalformat, width, height, depth, + border, format, type, pixels, paramCapture); } -void CaptureGetPerfMonitorCountersAMD_counters(const State &glState, - bool isCallValid, - GLuint group, - GLint *numCounters, - GLint *maxActiveCounters, - GLsizei counterSize, - GLuint *counters, - angle::ParamCapture *paramCapture) +void CaptureTexSubImage3DOES_pixels(const State &glState, + TextureTarget targetPacked, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLenum type, + const void *pixels, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = counterSize * sizeof(GLuint); + CaptureTexSubImage3D_pixels(glState, targetPacked, level, xoffset, yoffset, zoffset, width, + height, depth, format, type, pixels, paramCapture); } -void CaptureGetPerfMonitorGroupStringAMD_length(const State &glState, - bool isCallValid, - GLuint group, - GLsizei bufSize, - GLsizei *length, - GLchar *groupString, - angle::ParamCapture *paramCapture) +// GL_OES_texture_border_clamp +void CaptureGetSamplerParameterIivOES_params(const State &glState, + SamplerID sampler, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLsizei); + CaptureGetSamplerParameterIiv_params(glState, sampler, pname, params, paramCapture); } -void CaptureGetPerfMonitorGroupStringAMD_groupString(const State &glState, - bool isCallValid, - GLuint group, - GLsizei bufSize, - GLsizei *length, - GLchar *groupString, - angle::ParamCapture *paramCapture) +void CaptureGetSamplerParameterIuivOES_params(const State &glState, + SamplerID sampler, + GLenum pname, + GLuint *params, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = bufSize; + CaptureGetSamplerParameterIuiv_params(glState, sampler, pname, params, paramCapture); } -void CaptureGetPerfMonitorGroupsAMD_numGroups(const State &glState, - bool isCallValid, - GLint *numGroups, - GLsizei groupsSize, - GLuint *groups, - angle::ParamCapture *paramCapture) +void CaptureGetTexParameterIivOES_params(const State &glState, + TextureType targetPacked, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetTexParameterIiv_params(glState, targetPacked, pname, params, paramCapture); } -void CaptureGetPerfMonitorGroupsAMD_groups(const State &glState, - bool isCallValid, - GLint *numGroups, - GLsizei groupsSize, - GLuint *groups, - angle::ParamCapture *paramCapture) +void CaptureGetTexParameterIuivOES_params(const State &glState, + TextureType targetPacked, + GLenum pname, + GLuint *params, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureGetTexParameterIuiv_params(glState, targetPacked, pname, params, paramCapture); } -void CaptureSelectPerfMonitorCountersAMD_counterList(const State &glState, - bool isCallValid, - GLuint monitor, - GLboolean enable, - GLuint group, - GLint numCounters, - GLuint *counterList, - angle::ParamCapture *paramCapture) +void CaptureSamplerParameterIivOES_param(const State &glState, + SamplerID sampler, + GLenum pname, + const GLint *param, + ParamCapture *paramCapture) { - UNIMPLEMENTED(); + CaptureSamplerParameterIiv_param(glState, sampler, pname, param, paramCapture); } -// ANGLE_shader_pixel_local_storage. -void CaptureFramebufferPixelLocalClearValuefvANGLE_value(const State &glState, - bool isCallValid, - GLint plane, - const GLfloat *value, - angle::ParamCapture *paramCapture) +void CaptureSamplerParameterIuivOES_param(const State &glState, + SamplerID sampler, + GLenum pname, + const GLuint *param, + ParamCapture *paramCapture) { - CaptureArray(value, 4, paramCapture); + CaptureSamplerParameterIuiv_param(glState, sampler, pname, param, paramCapture); } -void CaptureFramebufferPixelLocalClearValueivANGLE_value(const State &glState, - bool isCallValid, - GLint plane, - const GLint *value, - angle::ParamCapture *paramCapture) +void CaptureTexParameterIivOES_params(const State &glState, + TextureType targetPacked, + GLenum pname, + const GLint *params, + ParamCapture *paramCapture) { - CaptureArray(value, 4, paramCapture); + CaptureTexParameterIiv_params(glState, targetPacked, pname, params, paramCapture); } -void CaptureFramebufferPixelLocalClearValueuivANGLE_value(const State &glState, - bool isCallValid, - GLint plane, - const GLuint *value, - angle::ParamCapture *paramCapture) +void CaptureTexParameterIuivOES_params(const State &glState, + TextureType targetPacked, + GLenum pname, + const GLuint *params, + ParamCapture *paramCapture) { - CaptureArray(value, 4, paramCapture); + CaptureTexParameterIuiv_params(glState, targetPacked, pname, params, paramCapture); } -void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState, - bool isCallValid, - GLsizei n, - const GLenum loadops[], - angle::ParamCapture *paramCapture) +// GL_OES_texture_cube_map +void CaptureGetTexGenfvOES_params(const State &glState, + GLenum coord, + GLenum pname, + GLfloat *params, + ParamCapture *paramCapture) { - CaptureArray(loadops, n, paramCapture); + UNIMPLEMENTED(); } -void CaptureEndPixelLocalStorageANGLE_storeops(const State &glState, - bool isCallValid, - GLsizei n, - const GLenum *storeops, - angle::ParamCapture *paramCapture) +void CaptureGetTexGenivOES_params(const State &glState, + GLenum coord, + GLenum pname, + GLint *params, + ParamCapture *paramCapture) { - CaptureArray(storeops, n, paramCapture); + UNIMPLEMENTED(); } -void CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLfloat *params, - angle::ParamCapture *paramCapture) +void CaptureGetTexGenxvOES_params(const State &glState, + GLenum coord, + GLenum pname, + GLfixed *params, + ParamCapture *paramCapture) { - switch (pname) - { - case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: - CaptureGetParameter(glState, pname, sizeof(GLfloat) * 4, paramCapture); - break; - } + UNIMPLEMENTED(); } -void CaptureGetFramebufferPixelLocalStorageParameterivANGLE_params( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLint *params, - angle::ParamCapture *paramCapture) +void CaptureTexGenfvOES_params(const State &glState, + GLenum coord, + GLenum pname, + const GLfloat *params, + ParamCapture *paramCapture) { - switch (pname) - { - case GL_PIXEL_LOCAL_FORMAT_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE: - CaptureGetParameter(glState, pname, sizeof(GLint), paramCapture); - break; - case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: - case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: - CaptureGetParameter(glState, pname, sizeof(GLint) * 4, paramCapture); - break; - } + UNIMPLEMENTED(); } -void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_length( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params, - angle::ParamCapture *paramCapture) +void CaptureTexGenivOES_params(const State &glState, + GLenum coord, + GLenum pname, + const GLint *params, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLsizei); + UNIMPLEMENTED(); } -void CaptureGetFramebufferPixelLocalStorageParameterfvRobustANGLE_params( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params, - angle::ParamCapture *paramCapture) +void CaptureTexGenxvOES_params(const State &glState, + GLenum coord, + GLenum pname, + const GLfixed *params, + ParamCapture *paramCapture) { - CaptureGetParameter(glState, pname, sizeof(GLfloat) * bufSize, paramCapture); + UNIMPLEMENTED(); } -void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_length( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params, - angle::ParamCapture *paramCapture) +// GL_OES_vertex_array_object +void CaptureDeleteVertexArraysOES_arraysPacked(const State &glState, + GLsizei n, + const VertexArrayID *arrays, + ParamCapture *paramCapture) { - paramCapture->readBufferSizeBytes = sizeof(GLsizei); + CaptureDeleteVertexArrays_arraysPacked(glState, n, arrays, paramCapture); } -void CaptureGetFramebufferPixelLocalStorageParameterivRobustANGLE_params( - const State &glState, - bool isCallValid, - GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params, - angle::ParamCapture *paramCapture) +void CaptureGenVertexArraysOES_arraysPacked(const State &glState, + GLsizei n, + VertexArrayID *arrays, + ParamCapture *paramCapture) { - CaptureGetParameter(glState, pname, sizeof(GLint) * bufSize, paramCapture); + CaptureGenVertexArrays_arraysPacked(glState, n, arrays, paramCapture); } +// GL_QCOM_framebuffer_foveated void CaptureFramebufferFoveationConfigQCOM_providedFeatures(const State &glState, - bool isCallValid, FramebufferID framebufferPacked, GLuint numLayers, GLuint focalPointsPerLayer, @@ -4503,30 +4012,4 @@ void CaptureFramebufferFoveationConfigQCOM_providedFeatures(const State &glState UNIMPLEMENTED(); } -void CaptureTexStorageAttribs2DEXT_attrib_list(const State &glState, - bool isCallValid, - GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height, - const GLint *attrib_list, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} - -void CaptureTexStorageAttribs3DEXT_attrib_list(const State &glState, - bool isCallValid, - GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - const GLint *attrib_list, - angle::ParamCapture *paramCapture) -{ - UNIMPLEMENTED(); -} } // namespace gl diff --git a/src/libANGLE/capture/serialize.cpp b/src/libANGLE/capture/serialize.cpp index e1468b37ee6..8c124f06257 100644 --- a/src/libANGLE/capture/serialize.cpp +++ b/src/libANGLE/capture/serialize.cpp @@ -7,6 +7,10 @@ // ANGLE GL state serialization. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/capture/serialize.h" #include "common/Color.h" @@ -196,7 +200,7 @@ void SerializeBindingPointerVector( { std::ostringstream s; s << std::setfill('0') << std::setw(3) << i; - json->addScalar(s.str().c_str(), obj.id().value); + json->addScalar(s.str(), obj.id().value); } } } @@ -291,6 +295,9 @@ Result SerializeFramebufferAttachment(const gl::Context *context, json->addScalar("ViewIndex", framebufferAttachment.getBaseViewIndex()); json->addScalar("Samples", framebufferAttachment.getRenderToTextureSamples()); + // Need to resolve the size before getting it below. + ANGLE_TRY(framebufferAttachment.ensureSizeResolved(context)); + { GroupScope extentsGroup(json, "Extents"); SerializeExtents(json, framebufferAttachment.getSize()); @@ -313,7 +320,7 @@ Result SerializeFramebufferAttachment(const gl::Context *context, MemoryBuffer *pixelsPtr = nullptr; ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment, scratchBuffer, &pixelsPtr)); - json->addBlob("Data", pixelsPtr->data(), pixelsPtr->size()); + json->addBlob("Data", *pixelsPtr); } else { @@ -539,8 +546,8 @@ void SerializeContextState(JsonSerializer *json, const gl::State &state) { GroupScope group(json, "ContextState"); json->addScalar("Priority", state.getContextPriority()); - json->addScalar("Major", state.getClientMajorVersion()); - json->addScalar("Minor", state.getClientMinorVersion()); + json->addScalar("Major", state.getClientVersion().getMajor()); + json->addScalar("Minor", state.getClientVersion().getMinor()); SerializeColorFWithGroup(json, "ColorClearValue", state.getColorClearValue()); json->addScalar("DepthClearValue", state.getDepthClearValue()); json->addScalar("StencilClearValue", state.getStencilClearValue()); @@ -591,7 +598,7 @@ void SerializeContextState(JsonSerializer *json, const gl::State &state) } ASSERT(state.getVertexArray()); json->addScalar("VertexArrayID", state.getVertexArray()->id().value); - json->addScalar("CurrentValuesTypeMask", state.getCurrentValuesTypeMask().to_ulong()); + json->addScalar("CurrentValuesTypeMask", state.getCurrentValuesTypeMask().bits()); json->addScalar("ActiveSampler", state.getActiveSampler()); { GroupScope boundTexturesGroup(json, "BoundTextures"); @@ -603,8 +610,14 @@ void SerializeContextState(JsonSerializer *json, const gl::State &state) SerializeBindingPointerVector(json, textures); } } - json->addScalar("TexturesIncompatibleWithSamplers", - state.getTexturesIncompatibleWithSamplers().to_ulong()); + + std::vector texturesIncompatibleWithSamplersVector; + for (size_t index = 0; index < gl::ActiveTextureMask::ArraySize(); index++) + { + auto value = state.getTexturesIncompatibleWithSamplers().bits(index); + texturesIncompatibleWithSamplersVector.push_back(value); + } + json->addVector("TexturesIncompatibleWithSamplers", texturesIncompatibleWithSamplersVector); { GroupScope texturesCacheGroup(json, "ActiveTexturesCache"); @@ -681,11 +694,11 @@ void SerializeContextState(JsonSerializer *json, const gl::State &state) json->addScalar("ProgramBinaryCacheEnabled", state.isProgramBinaryCacheEnabled()); json->addScalar("TextureRectangleEnabled", state.isTextureRectangleEnabled()); json->addScalar("MaxShaderCompilerThreads", state.getMaxShaderCompilerThreads()); - json->addScalar("EnabledClipDistances", state.getEnabledClipDistances().to_ulong()); + json->addScalar("EnabledClipDistances", state.getEnabledClipDistances().bits()); json->addScalar("BlendFuncConstantAlphaDrawBuffers", - state.getBlendFuncConstantAlphaDrawBuffers().to_ulong()); + state.getBlendFuncConstantAlphaDrawBuffers().bits()); json->addScalar("BlendFuncConstantColorDrawBuffers", - state.getBlendFuncConstantColorDrawBuffers().to_ulong()); + state.getBlendFuncConstantColorDrawBuffers().bits()); json->addScalar("SimultaneousConstantColorAndAlphaBlendFunc", state.noSimultaneousConstantColorAndAlphaBlendFunc()); } @@ -716,7 +729,7 @@ Result SerializeBuffer(const gl::Context *context, const_cast(context), scratchBuffer->getInitialized(static_cast(buffer->getSize()), &dataPtr, 0)); ANGLE_TRY(buffer->getSubData(context, 0, dataPtr->size(), dataPtr->data())); - json->addBlob("data", dataPtr->data(), dataPtr->size()); + json->addBlob("data", *dataPtr); } else { @@ -834,7 +847,7 @@ Result SerializeRenderbuffer(const gl::Context *context, ANGLE_TRY(renderbuffer->getImplementation()->getRenderbufferImage( context, packState, nullptr, readFormat, readType, pixelsPtr->data())); - json->addBlob("Pixels", pixelsPtr->data(), pixelsPtr->size()); + json->addBlob("Pixels", *pixelsPtr); } } else @@ -924,7 +937,7 @@ void SerializeCompiledShaderState(JsonSerializer *json, const gl::SharedCompiled { json->addCString("Type", gl::ShaderTypeToString(state->shaderType)); json->addScalar("Version", state->shaderVersion); - json->addString("TranslatedSource", state->translatedSource); + json->addString("TranslatedSource", *state->translatedSource); json->addVectorAsHash("CompiledBinary", state->compiledBinary); SerializeWorkGroupSize(json, state->localSize); SerializeShaderVariablesVector(json, state->inputVaryings); @@ -1017,7 +1030,7 @@ void SerializeBufferVariablesVector(JsonSerializer *json, json->addScalar("Type", bufferVariable.pod.type); json->addScalar("Precision", bufferVariable.pod.precision); - json->addScalar("activeUseBits", bufferVariable.activeShaders().to_ulong()); + json->addScalar("activeUseBits", bufferVariable.activeShaders().bits()); for (const gl::ShaderType shaderType : gl::AllShaderTypes()) { json->addScalar( @@ -1295,7 +1308,7 @@ Result SerializeTextureData(JsonSerializer *json, ANGLE_TRY(texture->getTexImage(context, packState, nullptr, index.getTarget(), index.getLevelIndex(), glFormat, glType, texelsPtr->data())); - json->addBlob(label.str(), texelsPtr->data(), texelsPtr->size()); + json->addBlob(label.str(), *texelsPtr); } } else @@ -1343,8 +1356,20 @@ void SerializeVertexAttributeVector(JsonSerializer *json, } void SerializeVertexBindingsVector(JsonSerializer *json, - const std::vector &vertexBindings) + const std::vector &vertexBindings, + const gl::VertexArrayBuffers &vertexBuffers) { + ASSERT(vertexBindings.size() <= gl::kElementArrayBufferIndex); + gl::Buffer *elementBuffer = vertexBuffers[gl::kElementArrayBufferIndex].get(); + if (elementBuffer) + { + json->addScalar("ElementArrayBufferID", elementBuffer->id().value); + } + else + { + json->addScalar("ElementArrayBufferID", 0); + } + for (size_t bindingIndex = 0; bindingIndex < vertexBindings.size(); ++bindingIndex) { GroupScope group(json, "VertexBinding", static_cast(bindingIndex)); @@ -1352,8 +1377,8 @@ void SerializeVertexBindingsVector(JsonSerializer *json, json->addScalar("Stride", vertexBinding.getStride()); json->addScalar("Divisor", vertexBinding.getDivisor()); json->addScalar("Offset", vertexBinding.getOffset()); - json->addScalar("BufferID", vertexBinding.getBuffer().id().value); - json->addScalar("BoundAttributesMask", vertexBinding.getBoundAttributesMask().to_ulong()); + json->addScalar("BufferID", vertexBuffers[bindingIndex].id().value); + json->addScalar("BoundAttributesMask", vertexBinding.getBoundAttributesMask().bits()); } } @@ -1361,32 +1386,21 @@ void SerializeVertexArrayState(JsonSerializer *json, const gl::VertexArrayState { json->addString("Label", vertexArrayState.getLabel()); SerializeVertexAttributeVector(json, vertexArrayState.getVertexAttributes()); - if (vertexArrayState.getElementArrayBuffer()) - { - json->addScalar("ElementArrayBufferID", - vertexArrayState.getElementArrayBuffer()->id().value); - } - else - { - json->addScalar("ElementArrayBufferID", 0); - } - SerializeVertexBindingsVector(json, vertexArrayState.getVertexBindings()); - json->addScalar("EnabledAttributesMask", - vertexArrayState.getEnabledAttributesMask().to_ulong()); + json->addScalar("EnabledAttributesMask", vertexArrayState.getEnabledAttributesMask().bits()); json->addScalar("VertexAttributesTypeMask", - vertexArrayState.getVertexAttributesTypeMask().to_ulong()); + vertexArrayState.getVertexAttributesTypeMask().bits()); json->addScalar("ClientMemoryAttribsMask", - vertexArrayState.getClientMemoryAttribsMask().to_ulong()); + vertexArrayState.getClientMemoryAttribsMask().bits()); json->addScalar("NullPointerClientMemoryAttribsMask", - vertexArrayState.getNullPointerClientMemoryAttribsMask().to_ulong()); + vertexArrayState.getNullPointerClientMemoryAttribsMask().bits()); } void SerializeVertexArray(JsonSerializer *json, gl::VertexArray *vertexArray) { GroupScope group(json, "VertexArray", vertexArray->id().value); SerializeVertexArrayState(json, vertexArray->getState()); - json->addScalar("BufferAccessValidationEnabled", - vertexArray->isBufferAccessValidationEnabled()); + SerializeVertexBindingsVector(json, vertexArray->getVertexBindings(), + vertexArray->getBufferBindingPointers()); } } // namespace diff --git a/src/libANGLE/cl_types.h b/src/libANGLE/cl_types.h index e8b0bbeb5ca..c90eb1a6fed 100644 --- a/src/libANGLE/cl_types.h +++ b/src/libANGLE/cl_types.h @@ -4,10 +4,15 @@ // found in the LICENSE file. // // cl_types.h: Defines common types for the OpenCL support in ANGLE. +// #ifndef LIBANGLE_CLTYPES_H_ #define LIBANGLE_CLTYPES_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #if defined(ANGLE_ENABLE_CL) # include "libANGLE/CLBitField.h" # include "libANGLE/CLRefPointer.h" @@ -15,6 +20,7 @@ # include "libANGLE/angletypes.h" # include "common/PackedCLEnums_autogen.h" +# include "common/WorkerThread.h" # include "common/angleutils.h" // Include frequently used standard headers @@ -61,6 +67,7 @@ using KernelPtrs = std::vector; using MemoryPtrs = std::vector; using PlatformPtrs = std::vector; using ProgramPtrs = std::vector; +using SamplerPtrs = std::vector; using WorkgroupSize = std::array; using GlobalWorkOffset = std::array; @@ -71,6 +78,7 @@ template using EventStatusMap = std::array; using Extents = angle::Extents; +constexpr Extents kExtentsZero(0, 0, 0); using Offset = angle::Offset; constexpr Offset kOffsetZero(0, 0, 0); @@ -113,9 +121,57 @@ struct BufferRect return ((mRowPitch * (mOrigin.y + row)) + (mOrigin.x * mElementSize)) + // row offset (mSlicePitch * (mOrigin.z + slice)); // slice offset } + // Calculates the offset of the starting position of the rectangle + size_t getBufferOffset() const { return getRowOffset(0, 0); } + + size_t getRowPitch() const { return mRowPitch; } + size_t getSlicePitch() const { return mSlicePitch; } + + // Given the offset, row pitch, slice pitch, this returns the size of the buffer in which this + // rect sits. + // + // row_pitch + // +------------------------------+ + // | origin | + // | +---------------+ | + // | | |height | + // | | | | + // | | width | | + // +------+---------------+-------+ + // - size of the buffer is + // - initial offset to start of rect + // - + size of the rectangle + // - - (extra regions for the last slice and row) + size_t getRectSize() const + { + // Treat: + // S: mSlicePitch, R: mRowPitch, O: Offset(xyz_dim), D: mSize.depth, H: mSize.height, + // W: mSize.width, E: mElementSize + // + // strideHeightPadding == (S / R) - H + // strideRowPadding == R - (W * E) + // + // getRectSize() = + // getBufferOffset() // initial offset to the start of rect + // + (S * D) // size of the rectangle + // - (strideHeightPadding * R) // extraneous region for the last slice + // - strideRowPadding // extraneous region for the last row + // + // Where: + // getBufferOffset() == getRowOffset(0,0) == S(Oz) + R(Oy) + (Ox * E) + // getRowOffset(s, r) == S(Oz + s) + R(Oy + r) + (Ox * E) + // + // Simplifies to: + // getRectSize() = S(Oz) + R(Oy) + (Ox * E) + (S * D) - R(S/R - H) - R - (W * E) + // getRectSize() = S(Oz + (D - 1)) + R(Oy + (H - 1)) + (Ox * E) + (W * E) + // ... + // getRectSize() = getRowOffset((D - 1), (H - 1)) + (W * E) - size_t getRowPitch() { return mRowPitch; } - size_t getSlicePitch() { return mSlicePitch; } + // The end of the rect is the beginning of the last row + the length of the row. + // This logic excludes paddings for the last row / slice. + return getRowOffset(mSize.depth - 1, mSize.height - 1) + mSize.width * mElementSize; + } + const Extents &getExtents() const { return mSize; } Offset mOrigin; Extents mSize; size_t mRowPitch; @@ -171,18 +227,6 @@ struct ImageDescriptor } }; -struct MemOffsets -{ - size_t x, y, z; -}; -constexpr MemOffsets kMemOffsetsZero{0, 0, 0}; - -struct Coordinate -{ - size_t x, y, z; -}; -constexpr Coordinate kCoordinateZero{0, 0, 0}; - struct NDRange { NDRange(cl_uint workDimensionsIn, @@ -314,6 +358,26 @@ struct NDRange bool nullLocalWorkSize{false}; }; +// name-value pair for cl_properties lists +struct NameValueProperty +{ + cl_properties name; + cl_properties value; +}; + +// this Defer class provides the user with a closure that executes on its destruction +template +class Defer : public angle::Closure +{ + public: + Defer(F &&func) : mFunc(std::forward(func)) {} + ~Defer() override { operator()(); } + void operator()() override { mFunc(); } + + private: + F mFunc; +}; + } // namespace cl #endif // ANGLE_ENABLE_CL diff --git a/src/libANGLE/cl_utils.h b/src/libANGLE/cl_utils.h index d7ca129b082..3af832e725c 100644 --- a/src/libANGLE/cl_utils.h +++ b/src/libANGLE/cl_utils.h @@ -30,9 +30,9 @@ } \ } while (0) -#define ANGLE_CL_IMPL_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, (void)) +#define ANGLE_CL_IMPL_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, static_cast(0), (void)) #define ANGLE_CL_IMPL_TRY_ERROR(EXPR, ERROR) \ - ANGLE_TRY_TEMPLATE(EXPR, ANGLE_CL_RETURN_ERROR(ERROR); (void)) + ANGLE_TRY_TEMPLATE(EXPR, static_cast(0), ANGLE_CL_RETURN_ERROR(ERROR); (void)) namespace cl { diff --git a/src/libANGLE/context_private_call.inl.h b/src/libANGLE/context_private_call.inl.h index 91175da79b0..a2abb1fc36b 100644 --- a/src/libANGLE/context_private_call.inl.h +++ b/src/libANGLE/context_private_call.inl.h @@ -4,9 +4,13 @@ // found in the LICENSE file. // -// context_private_call.cpp: +// context_private_call.inl.h: // Helpers that set/get state that is entirely locally accessed by the context. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/context_private_call_autogen.h" #include "common/debug.h" @@ -473,11 +477,26 @@ inline void ContextPrivateClipControl(PrivateState *privateState, privateState->setClipControl(origin, depth); } -inline void ContextPrivateShadingRate(PrivateState *privateState, - PrivateStateCache *privateStateCache, - GLenum rate) +inline void ContextPrivateShadingRateQCOM(PrivateState *privateState, + PrivateStateCache *privateStateCache, + ShadingRate rate) +{ + privateState->setShadingRateQCOM(rate); +} + +inline void ContextPrivateShadingRateEXT(PrivateState *privateState, + PrivateStateCache *privateStateCache, + ShadingRate rate) { - privateState->setShadingRate(rate); + privateState->setShadingRateEXT(rate); +} + +inline void ContextPrivateShadingRateCombinerOps(PrivateState *privateState, + PrivateStateCache *privateStateCache, + CombinerOp combinerOp0, + CombinerOp combinerOp1) +{ + privateState->setShadingRateCombinerOps(combinerOp0, combinerOp1); } inline void ContextPrivateBlendColor(PrivateState *privateState, @@ -495,7 +514,8 @@ inline void ContextPrivateBlendEquation(PrivateState *privateState, GLenum mode) { privateState->setBlendEquation(mode, mode); - if (privateState->getExtensions().blendEquationAdvancedKHR) + if (privateState->getExtensions().blendEquationAdvancedKHR || + privateState->getClientVersion() >= ES_3_2) { privateStateCache->onBlendEquationOrFuncChange(); } @@ -507,7 +527,8 @@ inline void ContextPrivateBlendEquationi(PrivateState *privateState, GLenum mode) { privateState->setBlendEquationIndexed(mode, mode, buf); - if (privateState->getExtensions().blendEquationAdvancedKHR) + if (privateState->getExtensions().blendEquationAdvancedKHR || + privateState->getClientVersion() >= ES_3_2) { privateStateCache->onBlendEquationOrFuncChange(); } @@ -519,7 +540,8 @@ inline void ContextPrivateBlendEquationSeparate(PrivateState *privateState, GLenum modeAlpha) { privateState->setBlendEquation(modeRGB, modeAlpha); - if (privateState->getExtensions().blendEquationAdvancedKHR) + if (privateState->getExtensions().blendEquationAdvancedKHR || + privateState->getClientVersion() >= ES_3_2) { privateStateCache->onBlendEquationOrFuncChange(); } @@ -532,7 +554,8 @@ inline void ContextPrivateBlendEquationSeparatei(PrivateState *privateState, GLenum modeAlpha) { privateState->setBlendEquationIndexed(modeRGB, modeAlpha, buf); - if (privateState->getExtensions().blendEquationAdvancedKHR) + if (privateState->getExtensions().blendEquationAdvancedKHR || + privateState->getClientVersion() >= ES_3_2) { privateStateCache->onBlendEquationOrFuncChange(); } @@ -694,51 +717,52 @@ inline void ContextPrivatePixelStorei(PrivateState *privateState, break; case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + ASSERT(privateState->getExtensions().packReverseRowOrderANGLE); privateState->setPackReverseRowOrder(param != 0); break; case GL_UNPACK_ROW_LENGTH: - ASSERT(privateState->getClientMajorVersion() >= 3 || + ASSERT(privateState->getClientVersion() >= ES_3_0 || privateState->getExtensions().unpackSubimageEXT); privateState->setUnpackRowLength(param); break; case GL_UNPACK_IMAGE_HEIGHT: - ASSERT(privateState->getClientMajorVersion() >= 3); + ASSERT(privateState->getClientVersion() >= ES_3_0); privateState->setUnpackImageHeight(param); break; case GL_UNPACK_SKIP_IMAGES: - ASSERT(privateState->getClientMajorVersion() >= 3); + ASSERT(privateState->getClientVersion() >= ES_3_0); privateState->setUnpackSkipImages(param); break; case GL_UNPACK_SKIP_ROWS: - ASSERT((privateState->getClientMajorVersion() >= 3) || + ASSERT((privateState->getClientVersion() >= ES_3_0) || privateState->getExtensions().unpackSubimageEXT); privateState->setUnpackSkipRows(param); break; case GL_UNPACK_SKIP_PIXELS: - ASSERT((privateState->getClientMajorVersion() >= 3) || + ASSERT((privateState->getClientVersion() >= ES_3_0) || privateState->getExtensions().unpackSubimageEXT); privateState->setUnpackSkipPixels(param); break; case GL_PACK_ROW_LENGTH: - ASSERT((privateState->getClientMajorVersion() >= 3) || + ASSERT((privateState->getClientVersion() >= ES_3_0) || privateState->getExtensions().packSubimageNV); privateState->setPackRowLength(param); break; case GL_PACK_SKIP_ROWS: - ASSERT((privateState->getClientMajorVersion() >= 3) || + ASSERT((privateState->getClientVersion() >= ES_3_0) || privateState->getExtensions().packSubimageNV); privateState->setPackSkipRows(param); break; case GL_PACK_SKIP_PIXELS: - ASSERT((privateState->getClientMajorVersion() >= 3) || + ASSERT((privateState->getClientVersion() >= ES_3_0) || privateState->getExtensions().packSubimageNV); privateState->setPackSkipPixels(param); break; @@ -1493,4 +1517,97 @@ inline void ContextPrivateTranslatex(PrivateState *privateState, ContextPrivateTranslatef(privateState, privateStateCache, ConvertFixedToFloat(x), ConvertFixedToFloat(y), ConvertFixedToFloat(z)); } + +inline GLboolean ContextPrivateIsVertexArray(PrivateState *privateState, + PrivateStateCache *privateStateCache, + VertexArrayID array) +{ + if (array.value == 0) + { + return GL_FALSE; + } + + VertexArray *vao = privateState->getVertexArray(array); + return ConvertToGLBoolean(vao != nullptr); +} + +inline void ContextPrivateDisableVertexAttribArray(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint index) +{ + const VertexArrayPrivate *vao = privateState->getVertexArrayPrivate(); + if (!vao->getEnabledAttributesMask().test(index)) + { + return; + } + + privateState->setEnableVertexAttribArray(index, false); + privateStateCache->onVertexArrayStateChange(); +} + +inline void ContextPrivateEnableVertexAttribArray(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint index) +{ + const VertexArrayPrivate *vao = privateState->getVertexArrayPrivate(); + if (vao->getEnabledAttributesMask().test(index)) + { + return; + } + + privateState->setEnableVertexAttribArray(index, true); + privateStateCache->onVertexArrayStateChange(); +} + +inline void ContextPrivateVertexAttribDivisor(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint index, + GLuint divisor) +{ + privateState->setVertexAttribDivisor(index, divisor); + privateStateCache->onVertexArrayStateChange(); +} + +inline void ContextPrivateVertexAttribBinding(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint attribIndex, + GLuint bindingIndex) +{ + privateState->setVertexAttribBinding(attribIndex, bindingIndex); + privateStateCache->onVertexArrayStateChange(); +} + +inline void ContextPrivateVertexBindingDivisor(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint bindingIndex, + GLuint divisor) +{ + privateState->setVertexBindingDivisor(bindingIndex, divisor); + privateStateCache->onVertexArrayFormatChange(); +} + +inline void ContextPrivateVertexAttribFormat(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint attribIndex, + GLint size, + VertexAttribType type, + GLboolean normalized, + GLuint relativeOffset) +{ + privateState->setVertexAttribFormat(attribIndex, size, type, ConvertToBool(normalized), false, + relativeOffset); + privateStateCache->onVertexArrayFormatChange(); +} + +inline void ContextPrivateVertexAttribIFormat(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint attribIndex, + GLint size, + VertexAttribType type, + GLuint relativeOffset) +{ + privateState->setVertexAttribFormat(attribIndex, size, type, false, true, relativeOffset); + privateStateCache->onVertexArrayFormatChange(); +} + } // namespace gl diff --git a/src/libANGLE/context_private_call_autogen.h b/src/libANGLE/context_private_call_autogen.h index 6182bc2c39a..014103060e6 100644 --- a/src/libANGLE/context_private_call_autogen.h +++ b/src/libANGLE/context_private_call_autogen.h @@ -75,9 +75,15 @@ void ContextPrivateDepthRangef(PrivateState *privateState, void ContextPrivateDisable(PrivateState *privateState, PrivateStateCache *privateStateCache, GLenum cap); +void ContextPrivateDisableVertexAttribArray(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint index); void ContextPrivateEnable(PrivateState *privateState, PrivateStateCache *privateStateCache, GLenum cap); +void ContextPrivateEnableVertexAttribArray(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint index); void ContextPrivateFrontFace(PrivateState *privateState, PrivateStateCache *privateStateCache, GLenum mode); @@ -182,6 +188,13 @@ void ContextPrivateViewport(PrivateState *privateState, GLint y, GLsizei width, GLsizei height); +GLboolean ContextPrivateIsVertexArray(PrivateState *privateState, + PrivateStateCache *privateStateCache, + VertexArrayID arrayPacked); +void ContextPrivateVertexAttribDivisor(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint index, + GLuint divisor); void ContextPrivateVertexAttribI4i(PrivateState *privateState, PrivateStateCache *privateStateCache, GLuint index, @@ -208,6 +221,27 @@ void ContextPrivateSampleMaski(PrivateState *privateState, PrivateStateCache *privateStateCache, GLuint maskNumber, GLbitfield mask); +void ContextPrivateVertexAttribBinding(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint attribindex, + GLuint bindingindex); +void ContextPrivateVertexAttribFormat(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint attribindex, + GLint size, + VertexAttribType typePacked, + GLboolean normalized, + GLuint relativeoffset); +void ContextPrivateVertexAttribIFormat(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint attribindex, + GLint size, + VertexAttribType typePacked, + GLuint relativeoffset); +void ContextPrivateVertexBindingDivisor(PrivateState *privateState, + PrivateStateCache *privateStateCache, + GLuint bindingindex, + GLuint divisor); void ContextPrivateBlendEquationSeparatei(PrivateState *privateState, PrivateStateCache *privateStateCache, GLuint buf, @@ -619,6 +653,13 @@ void ContextPrivateClipControl(PrivateState *privateState, PrivateStateCache *privateStateCache, ClipOrigin originPacked, ClipDepthMode depthPacked); +void ContextPrivateShadingRateEXT(PrivateState *privateState, + PrivateStateCache *privateStateCache, + ShadingRate ratePacked); +void ContextPrivateShadingRateCombinerOps(PrivateState *privateState, + PrivateStateCache *privateStateCache, + CombinerOp combinerOp0Packed, + CombinerOp combinerOp1Packed); void ContextPrivatePolygonOffsetClamp(PrivateState *privateState, PrivateStateCache *privateStateCache, GLfloat factor, @@ -628,9 +669,9 @@ void ContextPrivatePolygonModeNV(PrivateState *privateState, PrivateStateCache *privateStateCache, GLenum face, PolygonMode modePacked); -void ContextPrivateShadingRate(PrivateState *privateState, - PrivateStateCache *privateStateCache, - GLenum rate); +void ContextPrivateShadingRateQCOM(PrivateState *privateState, + PrivateStateCache *privateStateCache, + ShadingRate ratePacked); } // namespace gl #endif // LIBANGLE_CONTEXT_PRIVATE_CALL_AUTOGEN_H_ diff --git a/src/libANGLE/entry_points_utils.cpp b/src/libANGLE/entry_points_utils.cpp deleted file mode 100644 index 6cde6922b44..00000000000 --- a/src/libANGLE/entry_points_utils.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright 2022 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. -// -// entry_point_utils: -// These helpers are used in GL/GLES entry point routines. - -#include "libANGLE/entry_points_utils.h" - -#include "libANGLE/ErrorStrings.h" - -namespace gl -{ -bool GeneratePixelLocalStorageActiveError(const PrivateState &state, - ErrorSet *errors, - angle::EntryPoint entryPoint) -{ - ASSERT(state.getPixelLocalStorageActivePlanes() != 0); - errors->validationError(entryPoint, GL_INVALID_OPERATION, err::kPLSActive); - return false; -} -} // namespace gl diff --git a/src/libANGLE/entry_points_utils.h b/src/libANGLE/entry_points_utils.h index 50e74ca6a65..4f62c7fb61a 100644 --- a/src/libANGLE/entry_points_utils.h +++ b/src/libANGLE/entry_points_utils.h @@ -102,18 +102,6 @@ inline int CID(const Context *context) { return context == nullptr ? 0 : static_cast(context->id().value); } - -bool GeneratePixelLocalStorageActiveError(const PrivateState &state, - ErrorSet *errors, - angle::EntryPoint entryPoint); - -ANGLE_INLINE bool ValidatePixelLocalStorageInactive(const PrivateState &state, - ErrorSet *errors, - angle::EntryPoint entryPoint) -{ - return state.getPixelLocalStorageActivePlanes() == 0 || - GeneratePixelLocalStorageActiveError(state, errors, entryPoint); -} } // namespace gl namespace egl diff --git a/src/libANGLE/es3_format_type_combinations.json b/src/libANGLE/es3_format_type_combinations.json index 91e3ad574f2..6ed0b8e5d49 100644 --- a/src/libANGLE/es3_format_type_combinations.json +++ b/src/libANGLE/es3_format_type_combinations.json @@ -102,8 +102,10 @@ ], "From GL_EXT_sRGB": [ + [ "GL_SRGB8", "GL_SRGB_EXT", "GL_UNSIGNED_BYTE" ], [ "GL_SRGB8_ALPHA8_EXT", "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ], - [ "GL_SRGB8", "GL_SRGB_EXT", "GL_UNSIGNED_BYTE" ] + [ "GL_SRGB_EXT", "GL_RGB", "GL_UNSIGNED_BYTE" ], + [ "GL_SRGB_ALPHA_EXT", "GL_RGBA", "GL_UNSIGNED_BYTE" ] ], "From GL_EXT_texture_sRGB_R8": [ @@ -188,6 +190,7 @@ "From GL_ANGLE_rgbx_internal_format": [ [ "GL_RGBX8_ANGLE", "GL_RGB", "GL_UNSIGNED_BYTE" ], - [ "GL_RGBX8_SRGB_ANGLEX", "GL_RGB", "GL_UNSIGNED_BYTE" ] + [ "GL_RGBX8_SRGB_ANGLEX", "GL_RGB", "GL_UNSIGNED_BYTE" ], + [ "GL_RGBX8_ANGLE", "GL_RGBA", "GL_UNSIGNED_BYTE" ] ] } diff --git a/src/libANGLE/format_map_autogen.cpp b/src/libANGLE/format_map_autogen.cpp index 128e64391cb..60bdec68d22 100644 --- a/src/libANGLE/format_map_autogen.cpp +++ b/src/libANGLE/format_map_autogen.cpp @@ -1271,6 +1271,7 @@ bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat case GL_RGB565: case GL_SRGB8: case GL_RGB: + case GL_SRGB_EXT: case GL_RGBX8_ANGLE: case GL_RGBX8_SRGB_ANGLEX: return true; @@ -1410,6 +1411,8 @@ bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat case GL_RGBA4: case GL_SRGB8_ALPHA8: case GL_RGBA: + case GL_SRGB_ALPHA_EXT: + case GL_RGBX8_ANGLE: return true; default: break; diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp index c2a180b1d83..6246aa2a8d6 100644 --- a/src/libANGLE/formatutils.cpp +++ b/src/libANGLE/formatutils.cpp @@ -6,6 +6,10 @@ // formatutils.cpp: Queries for GL image formats. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/formatutils.h" #include "anglebase/no_destructor.h" @@ -75,12 +79,7 @@ static bool NeverSupported(const Version &, const Extensions &) return false; } -static bool RequireES1(const Version &clientVersion, const Extensions &extensions) -{ - return clientVersion.major == 1; -} - -template +template static bool RequireES(const Version &clientVersion, const Extensions &) { return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion); @@ -94,7 +93,7 @@ static bool RequireExt(const Version &, const Extensions &extensions) } // Check for a minimum client version or a single extension -template +template static bool RequireESOrExt(const Version &clientVersion, const Extensions &extensions) { return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) || @@ -102,8 +101,8 @@ static bool RequireESOrExt(const Version &clientVersion, const Extensions &exten } // Check for a minimum client version or two extensions -template static bool RequireESOrExtAndExt(const Version &clientVersion, const Extensions &extensions) @@ -113,8 +112,8 @@ static bool RequireESOrExtAndExt(const Version &clientVersion, const Extensions } // Check for a minimum client version or at least one of two extensions -template static bool RequireESOrExtOrExt(const Version &clientVersion, const Extensions &extensions) @@ -373,7 +372,7 @@ InternalFormat::InternalFormat() format(GL_NONE), type(GL_NONE), componentType(GL_NONE), - colorEncoding(GL_NONE), + colorEncoding(GL_LINEAR), textureSupport(NeverSupported), filterSupport(NeverSupported), textureAttachmentSupport(NeverSupported), @@ -470,7 +469,7 @@ bool InternalFormat::isRequiredRenderbufferFormat(const Version &version) const default: break; } - if (version.major < 3) + if (version < ES_3_0) { return false; } @@ -502,12 +501,7 @@ bool InternalFormat::isRequiredRenderbufferFormat(const Version &version) const default: break; } - if (version.major < 3) - { - return false; - } - - if (format == GL_BGRA_EXT) + if (version < ES_3_0) { return false; } @@ -587,7 +581,8 @@ static GLenum EquivalentBlitInternalFormat(GLenum internalformat) // sized, even if there is a swizzle (for example, blitting from a // multisampled RGBA8 renderbuffer to a BGRA8 texture). This could // be expanded and/or autogenerated if that is found necessary. - if (internalformat == GL_BGRA8_EXT || internalformat == GL_BGRA8_SRGB_ANGLEX) + if (internalformat == GL_BGRA_EXT || internalformat == GL_BGRA8_EXT || + internalformat == GL_BGRA8_SRGB_ANGLEX) { return GL_RGBA8; } @@ -1136,6 +1131,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() AddRGBAFormat(&map, GL_RGBA32I, true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported); AddRGBAFormat(&map, GL_RGBA32UI, true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported); + AddRGBAFormat(&map, GL_BGRA_EXT, true, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>); AddRGBAFormat(&map, GL_BGRA8_EXT, true, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>); AddRGBAFormat(&map, GL_BGRA4_ANGLEX, true, 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>); AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX, true, 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>); @@ -1149,6 +1145,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() // Special format which is not really supported, so always false for all supports. AddRGBAFormat(&map, GL_BGR565_ANGLEX, true, 5, 6, 5, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported); AddRGBAFormat(&map, GL_BGR10_A2_ANGLEX, true, 10, 10, 10, 2, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported); + AddRGBAFormat(&map, GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX, true, 10, 10, 10, 10, 0, GL_RGBA, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported); // Special format to emulate RGB8 with RGBA8 within ANGLE. AddRGBAXFormat(&map, GL_RGBX8_ANGLE, true, FB< 8, 8, 8, 0, 8, 0>(), GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, NeverSupported); @@ -1302,17 +1299,17 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() AddCompressedFormat(&map, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionBptcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); // Paletted formats - // | Internal format | | PS | Format | CC | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend - AddPalettedFormat(&map, GL_PALETTE4_RGB8_OES, 4, 3, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE4_RGBA8_OES, 4, 4, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE4_R5_G6_B5_OES, 4, 2, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE4_RGBA4_OES, 4, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE4_RGB5_A1_OES, 4, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE8_RGB8_OES, 8, 3, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE8_RGBA8_OES, 8, 4, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE8_R5_G6_B5_OES, 8, 2, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE8_RGBA4_OES, 8, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); - AddPalettedFormat(&map, GL_PALETTE8_RGB5_A1_OES, 8, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + // | Internal format | | PS | Format | CC | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend + AddPalettedFormat(&map, GL_PALETTE4_RGB8_OES, 4, 3, GL_RGB, 3, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE4_RGBA8_OES, 4, 4, GL_RGBA, 4, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE4_R5_G6_B5_OES, 4, 2, GL_RGB, 3, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE4_RGBA4_OES, 4, 2, GL_RGBA, 4, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE4_RGB5_A1_OES, 4, 2, GL_RGBA, 4, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE8_RGB8_OES, 8, 3, GL_RGB, 3, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE8_RGBA8_OES, 8, 4, GL_RGBA, 4, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE8_R5_G6_B5_OES, 8, 2, GL_RGB, 3, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE8_RGBA4_OES, 8, 2, GL_RGBA, 4, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); + AddPalettedFormat(&map, GL_PALETTE8_RGB5_A1_OES, 8, 2, GL_RGBA, 4, RequireExt<&Extensions::compressedPalettedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); // From GL_IMG_texture_compression_pvrtc // | Internal format | W | H | D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend @@ -1392,7 +1389,6 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() AddRGBAXFormat(&map, GL_RGBA, false, FB< 8, 8, 8, 8, 0, 0>(), GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported); AddRGBAXFormat(&map, GL_SRGB, false, FB< 8, 8, 8, 0, 0, 0>(), GL_SRGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::sRGBEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported); AddRGBAXFormat(&map, GL_SRGB_ALPHA_EXT, false, FB< 8, 8, 8, 8, 0, 0>(), GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::sRGBEXT>, AlwaysSupported, RequireExt<&Extensions::sRGBEXT>, NeverSupported, NeverSupported); - AddRGBAFormat(&map, GL_BGRA_EXT, false, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, NeverSupported, NeverSupported); // Unsized integer formats // |Internal format |sized | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend diff --git a/src/libANGLE/formatutils.h b/src/libANGLE/formatutils.h index 3cff8bbddc4..d0c02f5100f 100644 --- a/src/libANGLE/formatutils.h +++ b/src/libANGLE/formatutils.h @@ -9,6 +9,10 @@ #ifndef LIBANGLE_FORMATUTILS_H_ #define LIBANGLE_FORMATUTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include @@ -352,9 +356,6 @@ ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat) nativeVisualId = angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat); #endif -#if defined(ANGLE_PLATFORM_LINUX) && defined(ANGLE_USES_GBM) - nativeVisualId = angle::GLInternalFormatToGbmFourCCFormat(internalFormat.internalFormat); -#endif return nativeVisualId; } diff --git a/src/libANGLE/gen_extensions.py b/src/libANGLE/gen_extensions.py index 841532ad928..ed91c4fb43e 100644 --- a/src/libANGLE/gen_extensions.py +++ b/src/libANGLE/gen_extensions.py @@ -138,7 +138,7 @@ class TextureCapsMap; return info; }}; - auto enableableDisablableExtension = [&](ExtensionBool member) {{ + [[maybe_unused]] auto enableableDisablableExtension = [&](ExtensionBool member) {{ ExtensionInfo info = enableableExtension(member); info.Disablable = true; return info; diff --git a/src/libANGLE/gles_extensions_autogen.cpp b/src/libANGLE/gles_extensions_autogen.cpp index dab7ecf2b7f..e40558e729e 100644 --- a/src/libANGLE/gles_extensions_autogen.cpp +++ b/src/libANGLE/gles_extensions_autogen.cpp @@ -22,7 +22,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() return info; }; - auto enableableDisablableExtension = [&](ExtensionBool member) { + [[maybe_unused]] auto enableableDisablableExtension = [&](ExtensionBool member) { ExtensionInfo info = enableableExtension(member); info.Disablable = true; return info; @@ -40,8 +40,8 @@ const ExtensionInfoMap &GetExtensionInfoMap() // GLES 2.0 extension strings // -------------------------- map["GL_EXT_base_instance"] = enableableExtension(&Extensions::baseInstanceEXT); - map["GL_KHR_blend_equation_advanced"] = esOnlyExtension(&Extensions::blendEquationAdvancedKHR); - map["GL_KHR_blend_equation_advanced_coherent"] = esOnlyExtension(&Extensions::blendEquationAdvancedCoherentKHR); + map["GL_KHR_blend_equation_advanced"] = enableableExtension(&Extensions::blendEquationAdvancedKHR); + map["GL_KHR_blend_equation_advanced_coherent"] = enableableExtension(&Extensions::blendEquationAdvancedCoherentKHR); map["GL_EXT_blend_func_extended"] = enableableExtension(&Extensions::blendFuncExtendedEXT); map["GL_EXT_blend_minmax"] = enableableExtension(&Extensions::blendMinmaxEXT); map["GL_EXT_buffer_storage"] = enableableExtension(&Extensions::bufferStorageEXT); @@ -84,6 +84,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_OES_draw_buffers_indexed"] = enableableExtension(&Extensions::drawBuffersIndexedOES); map["GL_EXT_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexEXT); map["GL_OES_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexOES); + map["GL_EXT_draw_instanced"] = enableableExtension(&Extensions::drawInstancedEXT); map["GL_OES_EGL_image"] = enableableExtension(&Extensions::EGLImageOES); map["GL_EXT_EGL_image_array"] = enableableExtension(&Extensions::EGLImageArrayEXT); map["GL_OES_EGL_image_external"] = enableableExtension(&Extensions::EGLImageExternalOES); @@ -100,6 +101,9 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_NV_fence"] = esOnlyExtension(&Extensions::fenceNV); map["GL_EXT_float_blend"] = enableableExtension(&Extensions::floatBlendEXT); map["GL_EXT_frag_depth"] = enableableExtension(&Extensions::fragDepthEXT); + map["GL_EXT_fragment_shading_rate"] = enableableExtension(&Extensions::fragmentShadingRateEXT); + map["GL_EXT_fragment_shading_rate_attachment"] = enableableExtension(&Extensions::fragmentShadingRateAttachmentEXT); + map["GL_EXT_fragment_shading_rate_primitive"] = enableableExtension(&Extensions::fragmentShadingRatePrimitiveEXT); map["GL_ANGLE_framebuffer_blit"] = enableableExtension(&Extensions::framebufferBlitANGLE); map["GL_NV_framebuffer_blit"] = enableableExtension(&Extensions::framebufferBlitNV); map["GL_MESA_framebuffer_flip_y"] = enableableExtension(&Extensions::framebufferFlipYMESA); @@ -115,12 +119,14 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_EXT_map_buffer_range"] = enableableExtension(&Extensions::mapBufferRangeEXT); map["GL_EXT_memory_object"] = enableableExtension(&Extensions::memoryObjectEXT); map["GL_EXT_memory_object_fd"] = enableableExtension(&Extensions::memoryObjectFdEXT); + map["GL_EXT_multi_draw_arrays"] = enableableExtension(&Extensions::multiDrawArraysEXT); map["GL_EXT_multi_draw_indirect"] = enableableExtension(&Extensions::multiDrawIndirectEXT); map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibilityEXT); map["GL_EXT_multisampled_render_to_texture"] = enableableExtension(&Extensions::multisampledRenderToTextureEXT); map["GL_EXT_multisampled_render_to_texture2"] = enableableExtension(&Extensions::multisampledRenderToTexture2EXT); map["GL_OVR_multiview"] = enableableExtension(&Extensions::multiviewOVR); map["GL_OVR_multiview2"] = enableableExtension(&Extensions::multiview2OVR); + map["GL_OVR_multiview_multisampled_render_to_texture"] = enableableExtension(&Extensions::multiviewMultisampledRenderToTextureOVR); map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noErrorKHR); map["GL_EXT_occlusion_query_boolean"] = enableableExtension(&Extensions::occlusionQueryBooleanEXT); map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencilOES); @@ -131,8 +137,8 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_NV_pixel_buffer_object"] = enableableExtension(&Extensions::pixelBufferObjectNV); map["GL_NV_polygon_mode"] = enableableExtension(&Extensions::polygonModeNV); map["GL_EXT_polygon_offset_clamp"] = enableableExtension(&Extensions::polygonOffsetClampEXT); - map["GL_EXT_primitive_bounding_box"] = esOnlyExtension(&Extensions::primitiveBoundingBoxEXT); - map["GL_OES_primitive_bounding_box"] = esOnlyExtension(&Extensions::primitiveBoundingBoxOES); + map["GL_EXT_primitive_bounding_box"] = enableableExtension(&Extensions::primitiveBoundingBoxEXT); + map["GL_OES_primitive_bounding_box"] = enableableExtension(&Extensions::primitiveBoundingBoxOES); map["GL_EXT_protected_textures"] = enableableExtension(&Extensions::protectedTexturesEXT); map["GL_EXT_pvrtc_sRGB"] = enableableExtension(&Extensions::pvrtcSRGBEXT); map["GL_NV_read_depth"] = enableableExtension(&Extensions::readDepthNV); @@ -165,13 +171,13 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_EXT_shader_non_constant_global_initializers"] = enableableExtension(&Extensions::shaderNonConstantGlobalInitializersEXT); map["GL_NV_shader_noperspective_interpolation"] = enableableExtension(&Extensions::shaderNoperspectiveInterpolationNV); map["GL_EXT_shader_texture_lod"] = enableableExtension(&Extensions::shaderTextureLodEXT); + map["GL_EXT_shader_texture_samples"] = enableableExtension(&Extensions::shaderTextureSamplesEXT); map["GL_QCOM_shading_rate"] = enableableExtension(&Extensions::shadingRateQCOM); map["GL_EXT_shadow_samplers"] = enableableExtension(&Extensions::shadowSamplersEXT); map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGBEXT); map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControlEXT); map["GL_OES_standard_derivatives"] = enableableExtension(&Extensions::standardDerivativesOES); map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContextOES); - map["GL_ARB_sync"] = enableableExtension(&Extensions::syncARB); map["GL_EXT_tessellation_shader"] = enableableExtension(&Extensions::tessellationShaderEXT); map["GL_OES_tessellation_shader"] = enableableExtension(&Extensions::tessellationShaderOES); map["GL_OES_texture_3D"] = enableableExtension(&Extensions::texture3DOES); @@ -217,6 +223,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_EXT_texture_storage_compression"] = enableableExtension(&Extensions::textureStorageCompressionEXT); map["GL_OES_texture_storage_multisample_2d_array"] = enableableExtension(&Extensions::textureStorageMultisample2dArrayOES); map["GL_EXT_texture_type_2_10_10_10_REV"] = enableableExtension(&Extensions::textureType2101010REVEXT); + map["GL_ARM_texture_unnormalized_coordinates"] = enableableExtension(&Extensions::textureUnnormalizedCoordinatesARM); map["GL_ANGLE_texture_usage"] = enableableExtension(&Extensions::textureUsageANGLE); map["GL_QCOM_tiled_rendering"] = enableableExtension(&Extensions::tiledRenderingQCOM); map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSourceANGLE); @@ -273,12 +280,11 @@ const ExtensionInfoMap &GetExtensionInfoMap() map["GL_ANGLE_shader_pixel_local_storage"] = enableableExtension(&Extensions::shaderPixelLocalStorageANGLE); map["GL_ANGLE_shader_pixel_local_storage_coherent"] = enableableExtension(&Extensions::shaderPixelLocalStorageCoherentANGLE); map["GL_ANGLE_stencil_texturing"] = enableableExtension(&Extensions::stencilTexturingANGLE); - map["GL_CHROMIUM_sync_query"] = enableableExtension(&Extensions::syncQueryCHROMIUM); map["GL_ANGLE_texture_compression_dxt3"] = enableableExtension(&Extensions::textureCompressionDxt3ANGLE); map["GL_ANGLE_texture_compression_dxt5"] = enableableExtension(&Extensions::textureCompressionDxt5ANGLE); map["GL_ANGLE_texture_external_update"] = enableableExtension(&Extensions::textureExternalUpdateANGLE); map["GL_ANGLE_texture_multisample"] = enableableExtension(&Extensions::textureMultisampleANGLE); - map["GL_ANGLE_texture_rectangle"] = enableableDisablableExtension(&Extensions::textureRectangleANGLE); + map["GL_ANGLE_texture_rectangle"] = enableableExtension(&Extensions::textureRectangleANGLE); map["GL_ANGLE_vulkan_image"] = enableableExtension(&Extensions::vulkanImageANGLE); map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibilityANGLE); map["GL_ANGLE_yuv_internal_format"] = enableableExtension(&Extensions::yuvInternalFormatANGLE); diff --git a/src/libANGLE/gles_extensions_autogen.h b/src/libANGLE/gles_extensions_autogen.h index fb1a993e026..b527f5cb15c 100644 --- a/src/libANGLE/gles_extensions_autogen.h +++ b/src/libANGLE/gles_extensions_autogen.h @@ -218,6 +218,9 @@ struct Extensions // GL_OES_draw_elements_base_vertex bool drawElementsBaseVertexOES = false; + // GL_EXT_draw_instanced + bool drawInstancedEXT = false; + // GL_OES_EGL_image bool EGLImageOES = false; @@ -266,6 +269,15 @@ struct Extensions // GL_EXT_frag_depth bool fragDepthEXT = false; + // GL_EXT_fragment_shading_rate + bool fragmentShadingRateEXT = false; + + // GL_EXT_fragment_shading_rate_attachment + bool fragmentShadingRateAttachmentEXT = false; + + // GL_EXT_fragment_shading_rate_primitive + bool fragmentShadingRatePrimitiveEXT = false; + // GL_ANGLE_framebuffer_blit bool framebufferBlitANGLE = false; @@ -311,6 +323,9 @@ struct Extensions // GL_EXT_memory_object_fd bool memoryObjectFdEXT = false; + // GL_EXT_multi_draw_arrays + bool multiDrawArraysEXT = false; + // GL_EXT_multi_draw_indirect bool multiDrawIndirectEXT = false; @@ -329,6 +344,9 @@ struct Extensions // GL_OVR_multiview2 bool multiview2OVR = false; + // GL_OVR_multiview_multisampled_render_to_texture + bool multiviewMultisampledRenderToTextureOVR = false; + // GL_KHR_no_error bool noErrorKHR = false; @@ -461,6 +479,9 @@ struct Extensions // GL_EXT_shader_texture_lod bool shaderTextureLodEXT = false; + // GL_EXT_shader_texture_samples + bool shaderTextureSamplesEXT = false; + // GL_QCOM_shading_rate bool shadingRateQCOM = false; @@ -479,9 +500,6 @@ struct Extensions // GL_OES_surfaceless_context bool surfacelessContextOES = false; - // GL_ARB_sync - bool syncARB = false; - // GL_EXT_tessellation_shader bool tessellationShaderEXT = false; @@ -617,6 +635,9 @@ struct Extensions // GL_EXT_texture_type_2_10_10_10_REV bool textureType2101010REVEXT = false; + // GL_ARM_texture_unnormalized_coordinates + bool textureUnnormalizedCoordinatesARM = false; + // GL_ANGLE_texture_usage bool textureUsageANGLE = false; @@ -779,9 +800,6 @@ struct Extensions // GL_ANGLE_stencil_texturing bool stencilTexturingANGLE = false; - // GL_CHROMIUM_sync_query - bool syncQueryCHROMIUM = false; - // GL_ANGLE_texture_compression_dxt3 bool textureCompressionDxt3ANGLE = false; diff --git a/src/libANGLE/histogram_macros.h b/src/libANGLE/histogram_macros.h index cf27a895a1b..6ce2c17abe9 100644 --- a/src/libANGLE/histogram_macros.h +++ b/src/libANGLE/histogram_macros.h @@ -65,46 +65,33 @@ // Scoped class which logs its time on this earth as a UMA statistic. This is // recommended for when you want a histogram which measures the time it takes -// for a method to execute. This measures up to 10 seconds. -#define SCOPED_ANGLE_HISTOGRAM_TIMER(name) \ - SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__) - -// Similar scoped histogram timer, but this uses ANGLE_HISTOGRAM_LONG_TIMES_100, -// which measures up to an hour, and uses 100 buckets. This is more expensive -// to store, so only use if this often takes >10 seconds. -#define SCOPED_ANGLE_HISTOGRAM_LONG_TIMER(name) \ - SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__) +// for a method to execute. This measures in microseconds. +#define SCOPED_ANGLE_HISTOGRAM_TIMER_US(name) \ + SCOPED_ANGLE_HISTOGRAM_TIMER_US_EXPANDER(name, __COUNTER__) // This nested macro is necessary to expand __COUNTER__ to an actual value. -#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \ - SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) +#define SCOPED_ANGLE_HISTOGRAM_TIMER_US_EXPANDER(name, key) \ + SCOPED_ANGLE_HISTOGRAM_TIMER_US_UNIQUE(name, key) -#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \ - class [[nodiscard]] ScopedHistogramTimer##key \ +#define SCOPED_ANGLE_HISTOGRAM_TIMER_US_UNIQUE(name, key) \ + class [[nodiscard]] ScopedHistogramTimerUs##key \ { \ public: \ - ScopedHistogramTimer##key() \ + ScopedHistogramTimerUs##key() \ : constructed_(ANGLEPlatformCurrent()->currentTime(ANGLEPlatformCurrent())) \ {} \ - ~ScopedHistogramTimer##key() \ + ~ScopedHistogramTimerUs##key() \ { \ if (constructed_ == 0) \ return; \ auto *platform = ANGLEPlatformCurrent(); \ double elapsed = platform->currentTime(platform) - constructed_; \ - int elapsedMS = static_cast(elapsed * 1000.0); \ - if (is_long) \ - { \ - ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \ - } \ - else \ - { \ - ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \ - } \ + int elapsedUS = static_cast(elapsed * 1e6); \ + ANGLE_HISTOGRAM_COUNTS(name, elapsedUS); \ } \ \ private: \ double constructed_; \ - } scoped_histogram_timer_##key + } scoped_histogram_timer_us_##key #endif // LIBANGLE_HISTOGRAM_MACROS_H_ diff --git a/src/libANGLE/queryconversions.cpp b/src/libANGLE/queryconversions.cpp index a68f996f4d7..c78f41d1f18 100644 --- a/src/libANGLE/queryconversions.cpp +++ b/src/libANGLE/queryconversions.cpp @@ -6,6 +6,10 @@ // queryconversions.cpp: Implementation of state query cast conversions +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/queryconversions.h" #include @@ -54,6 +58,22 @@ QueryT CastFromStateValueToInt(GLenum pname, NativeT value) return clampCast(value); } +template +QueryT CastFromStateValueToFloat(GLenum pname, NativeT value) +{ + switch (pname) + { + // For mask values, their floating-point values should be positive, not -1. + case GL_STENCIL_VALUE_MASK: + case GL_STENCIL_BACK_VALUE_MASK: + case GL_STENCIL_WRITEMASK: + case GL_STENCIL_BACK_WRITEMASK: + return static_cast(static_cast(value)); + default: + return static_cast(value); + } +} + template NativeT CastQueryValueToInt(GLenum pname, QueryT value) { @@ -78,11 +98,6 @@ NativeT CastQueryValueToInt(GLenum pname, QueryT value) } // anonymous namespace -GLint CastMaskValue(GLuint value) -{ - return clampCast(value); -} - template QueryT CastFromGLintStateValue(GLenum pname, InternalT value) { @@ -116,7 +131,7 @@ QueryT CastFromStateValue(GLenum pname, NativeT value) case GL_UINT_64_ANGLEX: return CastFromStateValueToInt(pname, value); case GL_FLOAT: - return static_cast(value); + return CastFromStateValueToFloat(pname, value); case GL_BOOL: return static_cast(value == static_cast(0) ? GL_FALSE : GL_TRUE); default: diff --git a/src/libANGLE/queryconversions.h b/src/libANGLE/queryconversions.h index 6dab8e697c0..8740c803052 100644 --- a/src/libANGLE/queryconversions.h +++ b/src/libANGLE/queryconversions.h @@ -58,8 +58,6 @@ struct GLTypeToGLenum static constexpr GLenum value = GL_FLOAT; }; -GLint CastMaskValue(GLuint value); - template QueryT CastFromGLintStateValue(GLenum pname, InternalT value); diff --git a/src/libANGLE/queryutils.cpp b/src/libANGLE/queryutils.cpp index 8a6c0a4dd02..28ccb8a288d 100644 --- a/src/libANGLE/queryutils.cpp +++ b/src/libANGLE/queryutils.cpp @@ -6,6 +6,10 @@ // queryutils.cpp: Utilities for querying values from GL objects +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/queryutils.h" #include @@ -21,6 +25,7 @@ #include "libANGLE/Framebuffer.h" #include "libANGLE/GLES1State.h" #include "libANGLE/MemoryObject.h" +#include "libANGLE/PixelLocalStorage.h" #include "libANGLE/Program.h" #include "libANGLE/Renderbuffer.h" #include "libANGLE/Sampler.h" @@ -392,6 +397,9 @@ void QueryTexParameterBase(const Context *context, *params = CastFromGLintStateValue(pname, texture->getImageCompressionRate(context)); break; + case GL_TEXTURE_ASTC_DECODE_PRECISION_EXT: + *params = CastFromGLintStateValue(pname, texture->getASTCDecodePrecision()); + break; default: UNREACHABLE(); break; @@ -517,6 +525,9 @@ void SetTexParameterBase(Context *context, Texture *texture, GLenum pname, const case GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM: texture->setMinPixelDensity(ConvertToGLfloat(params[0])); break; + case GL_TEXTURE_ASTC_DECODE_PRECISION_EXT: + texture->setASTCDecodePrecision(context, ConvertToGLenum(pname, params[0])); + break; default: UNREACHABLE(); break; @@ -626,6 +637,7 @@ void SetSamplerParameterBase(Context *context, template void QueryVertexAttribBase(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const CurrentDataType (¤tValueData)[CurrentValueCount], GLenum pname, ParamType *params) @@ -656,7 +668,7 @@ void QueryVertexAttribBase(const VertexAttribute &attrib, CastFromStateValue(pname, static_cast(attrib.format->isNorm())); break; case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - *params = CastFromGLintStateValue(pname, binding.getBuffer().id().value); + *params = CastFromGLintStateValue(pname, buffer ? buffer->id().value : 0); break; case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: *params = CastFromStateValue(pname, binding.getDivisor()); @@ -1041,7 +1053,7 @@ template void GetShaderVariableBufferResourceProperty(const ShaderVariableT &buffer, GLenum pname, GLint *params, - GLsizei bufSize, + GLsizei count, GLsizei *outputPosition) { @@ -1055,7 +1067,7 @@ void GetShaderVariableBufferResourceProperty(const ShaderVariableT &buffer, break; case GL_ACTIVE_VARIABLES: for (size_t memberIndex = 0; - memberIndex < buffer.memberIndexes.size() && *outputPosition < bufSize; + memberIndex < buffer.memberIndexes.size() && *outputPosition < count; ++memberIndex) { params[(*outputPosition)++] = clampCast(buffer.memberIndexes[memberIndex]); @@ -1090,7 +1102,7 @@ void GetShaderVariableBufferResourceProperty(const ShaderVariableT &buffer, void GetInterfaceBlockResourceProperty(const InterfaceBlock &block, GLenum pname, GLint *params, - GLsizei bufSize, + GLsizei count, GLsizei *outputPosition) { if (pname == GL_NAME_LENGTH) @@ -1098,18 +1110,18 @@ void GetInterfaceBlockResourceProperty(const InterfaceBlock &block, params[(*outputPosition)++] = clampCast(block.nameWithArrayIndex().size() + 1); return; } - GetShaderVariableBufferResourceProperty(block, pname, params, bufSize, outputPosition); + GetShaderVariableBufferResourceProperty(block, pname, params, count, outputPosition); } void GetUniformBlockResourceProperty(const Program *program, GLuint blockIndex, GLenum pname, GLint *params, - GLsizei bufSize, + GLsizei count, GLsizei *outputPosition) { - ASSERT(*outputPosition < bufSize); + ASSERT(*outputPosition < count); if (pname == GL_BUFFER_BINDING) { @@ -1118,18 +1130,18 @@ void GetUniformBlockResourceProperty(const Program *program, } const auto &block = program->getExecutable().getUniformBlockByIndex(blockIndex); - GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition); + GetInterfaceBlockResourceProperty(block, pname, params, count, outputPosition); } void GetShaderStorageBlockResourceProperty(const Program *program, GLuint blockIndex, GLenum pname, GLint *params, - GLsizei bufSize, + GLsizei count, GLsizei *outputPosition) { - ASSERT(*outputPosition < bufSize); + ASSERT(*outputPosition < count); if (pname == GL_BUFFER_BINDING) { @@ -1139,18 +1151,18 @@ void GetShaderStorageBlockResourceProperty(const Program *program, } const auto &block = program->getExecutable().getShaderStorageBlockByIndex(blockIndex); - GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition); + GetInterfaceBlockResourceProperty(block, pname, params, count, outputPosition); } void GetAtomicCounterBufferResourceProperty(const Program *program, GLuint index, GLenum pname, GLint *params, - GLsizei bufSize, + GLsizei count, GLsizei *outputPosition) { - ASSERT(*outputPosition < bufSize); + ASSERT(*outputPosition < count); if (pname == GL_BUFFER_BINDING) { @@ -1159,7 +1171,7 @@ void GetAtomicCounterBufferResourceProperty(const Program *program, } const auto &buffer = program->getExecutable().getAtomicCounterBuffers()[index]; - GetShaderVariableBufferResourceProperty(buffer, pname, params, bufSize, outputPosition); + GetShaderVariableBufferResourceProperty(buffer, pname, params, count, outputPosition); } bool IsTextureEnvEnumParameter(TextureEnvParameter pname) @@ -1375,6 +1387,7 @@ void QueryProgramiv(Context *context, Program *program, GLenum pname, GLint *par case GL_COMPLETION_STATUS_KHR: if (context->isContextLost()) { + context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetProgramiv); *params = GL_TRUE; } else @@ -1513,7 +1526,9 @@ void QueryRenderbufferiv(const Context *context, } else { - *params = renderbuffer->getFormat().info->internalFormat; + *params = (renderbuffer->getFormat().info->internalFormat == GL_NONE) + ? GL_RGBA4 + : renderbuffer->getFormat().info->internalFormat; } break; case GL_RENDERBUFFER_RED_SIZE: @@ -1573,6 +1588,7 @@ void QueryShaderiv(const Context *context, Shader *shader, GLenum pname, GLint * case GL_COMPLETION_STATUS_KHR: if (context->isContextLost()) { + context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetShaderiv); *params = GL_TRUE; } else @@ -1675,20 +1691,24 @@ void QuerySamplerParameterIuiv(const Sampler *sampler, GLenum pname, GLuint *par void QueryVertexAttribfv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLfloat *params) { - QueryVertexAttribBase(attrib, binding, currentValueData.Values.FloatValues, pname, params); + QueryVertexAttribBase(attrib, binding, buffer, currentValueData.Values.FloatValues, pname, + params); } void QueryVertexAttribiv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLint *params) { - QueryVertexAttribBase(attrib, binding, currentValueData.Values.FloatValues, pname, params); + QueryVertexAttribBase(attrib, binding, buffer, currentValueData.Values.FloatValues, pname, + params); } void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer) @@ -1707,20 +1727,23 @@ void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void void QueryVertexAttribIiv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLint *params) { - QueryVertexAttribBase(attrib, binding, currentValueData.Values.IntValues, pname, params); + QueryVertexAttribBase(attrib, binding, buffer, currentValueData.Values.IntValues, pname, + params); } void QueryVertexAttribIuiv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLuint *params) { - QueryVertexAttribBase(attrib, binding, currentValueData.Values.UnsignedIntValues, pname, + QueryVertexAttribBase(attrib, binding, buffer, currentValueData.Values.UnsignedIntValues, pname, params); } @@ -1739,22 +1762,25 @@ void QueryInternalFormativ(const Context *context, GLenum internalformat, const TextureCaps &format, GLenum pname, - GLsizei bufSize, + GLsizei count, GLint *params) { + if (count < 1) + { + return; + } + switch (pname) { case GL_NUM_SAMPLE_COUNTS: - if (bufSize != 0) - { - *params = clampCast(format.sampleCounts.size()); - } + *params = clampCast(format.sampleCounts.size()); break; case GL_SAMPLES: { - size_t returnCount = std::min(bufSize, format.sampleCounts.size()); - auto sampleReverseIt = format.sampleCounts.rbegin(); + size_t returnCount = std::min(count, format.sampleCounts.size()); + auto sampleCounts = format.sampleCounts.sampleCounts(); + auto sampleReverseIt = sampleCounts.rbegin(); for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex) { params[sampleIndex] = *sampleReverseIt++; @@ -1766,15 +1792,14 @@ void QueryInternalFormativ(const Context *context, if (texture != nullptr) { *params = texture->getFormatSupportedCompressionRates(context, internalformat, - bufSize, nullptr); + count, nullptr); } break; case GL_SURFACE_COMPRESSION_EXT: if (texture != nullptr) { - texture->getFormatSupportedCompressionRates(context, internalformat, bufSize, - params); + texture->getFormatSupportedCompressionRates(context, internalformat, count, params); } break; @@ -1814,17 +1839,112 @@ void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, G } } +template +void QueryFramebufferPixelLocalStorageParameterBase(Context *context, + GLint plane, + GLenum pname, + GLsizei *length, + ParamType *params) +{ + const PixelLocalStoragePlane &planeObject = + context->getState().getDrawFramebuffer()->getPixelLocalStorage(context).getPlane(plane); + switch (pname) + { + case GL_PIXEL_LOCAL_FORMAT_ANGLE: + case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE: + case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: + case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE: + if (length != nullptr) + { + *length = 1; + } + *params = clampCast(planeObject.getIntegeri(pname)); + break; + case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: + { + if (length != nullptr) + { + *length = 4; + } + GLfloat p[4]; + planeObject.getClearValuef(p); + params[0] = clampCast(p[0]); + params[1] = clampCast(p[1]); + params[2] = clampCast(p[2]); + params[3] = clampCast(p[3]); + break; + } + case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: + { + if (length != nullptr) + { + *length = 4; + } + GLint p[4]; + planeObject.getClearValuei(p); + params[0] = clampCast(p[0]); + params[1] = clampCast(p[1]); + params[2] = clampCast(p[2]); + params[3] = clampCast(p[3]); + break; + } + case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: + { + if (length != nullptr) + { + *length = 4; + } + // There is no unsigned int PLS state query + if constexpr (std::numeric_limits::is_integer) + { + planeObject.getClearValueui(reinterpret_cast(params)); + } + else + { + GLuint p[4]; + planeObject.getClearValueui(p); + params[0] = clampCast(p[0]); + params[1] = clampCast(p[1]); + params[2] = clampCast(p[2]); + params[3] = clampCast(p[3]); + } + break; + } + default: + UNREACHABLE(); + break; + } +} + +void QueryFramebufferPixelLocalStorageParameterfv(Context *context, + GLint plane, + GLenum pname, + GLsizei *length, + GLfloat *params) +{ + QueryFramebufferPixelLocalStorageParameterBase(context, plane, pname, length, params); +} + +void QueryFramebufferPixelLocalStorageParameteriv(Context *context, + GLint plane, + GLenum pname, + GLsizei *length, + GLint *params) +{ + QueryFramebufferPixelLocalStorageParameterBase(context, plane, pname, length, params); +} + angle::Result QuerySynciv(const Context *context, const Sync *sync, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *values) { ASSERT(sync != nullptr || pname == GL_SYNC_STATUS); - // All queries return one value, exit early if the buffer can't fit anything. - if (bufSize < 1) + // All queries return one value, exit early if the requested count is less. + if (count < 1) { if (length != nullptr) { @@ -1847,6 +1967,7 @@ angle::Result QuerySynciv(const Context *context, case GL_SYNC_STATUS: if (context->isContextLost()) { + context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetSynciv); *values = GL_SIGNALED; } else @@ -2216,7 +2337,7 @@ void QueryProgramResourceiv(const Program *program, UniformBlockIndex index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *params) { @@ -2230,9 +2351,8 @@ void QueryProgramResourceiv(const Program *program, *length = 0; } - if (bufSize == 0) + if (count < 1) { - // No room to write the results return; } @@ -2262,18 +2382,18 @@ void QueryProgramResourceiv(const Program *program, break; case GL_UNIFORM_BLOCK: - GetUniformBlockResourceProperty(program, index.value, props[i], params, bufSize, + GetUniformBlockResourceProperty(program, index.value, props[i], params, count, &pos); break; case GL_SHADER_STORAGE_BLOCK: - GetShaderStorageBlockResourceProperty(program, index.value, props[i], params, - bufSize, &pos); + GetShaderStorageBlockResourceProperty(program, index.value, props[i], params, count, + &pos); break; case GL_ATOMIC_COUNTER_BUFFER: GetAtomicCounterBufferResourceProperty(program, index.value, props[i], params, - bufSize, &pos); + count, &pos); break; case GL_TRANSFORM_FEEDBACK_VARYING: @@ -2286,7 +2406,7 @@ void QueryProgramResourceiv(const Program *program, UNREACHABLE(); params[i] = GL_INVALID_VALUE; } - if (pos == bufSize) + if (pos == count) { // Most properties return one value, but GL_ACTIVE_VARIABLES returns an array of values. // This checks not to break buffer bounds for such case. @@ -3203,7 +3323,7 @@ bool GetQueryParameterInfo(const State &glState, { const Caps &caps = glState.getCaps(); const Extensions &extensions = glState.getExtensions(); - GLint clientMajorVersion = glState.getClientMajorVersion(); + const Version &clientVersion = glState.getClientVersion(); // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due @@ -3317,7 +3437,7 @@ bool GetQueryParameterInfo(const State &glState, case GL_MAX_DRAW_BUFFERS_EXT: case GL_MAX_COLOR_ATTACHMENTS_EXT: { - if ((clientMajorVersion < 3) && !extensions.drawBuffersEXT) + if ((clientVersion < ES_3_0) && !extensions.drawBuffersEXT) { return false; } @@ -3327,7 +3447,7 @@ bool GetQueryParameterInfo(const State &glState, } case GL_BLEND_ADVANCED_COHERENT_KHR: { - if (clientMajorVersion < 2 || !extensions.blendEquationAdvancedCoherentKHR) + if (!extensions.blendEquationAdvancedCoherentKHR) { return false; } @@ -3399,7 +3519,7 @@ bool GetQueryParameterInfo(const State &glState, } case GL_COLOR_LOGIC_OP: { - if (clientMajorVersion == 1) + if (clientVersion < ES_2_0) { // Handle logicOp in GLES1 through GLES1 state management. break; @@ -3503,7 +3623,7 @@ bool GetQueryParameterInfo(const State &glState, case GL_CLIP_DISTANCE5_EXT: case GL_CLIP_DISTANCE6_EXT: case GL_CLIP_DISTANCE7_EXT: - if (clientMajorVersion < 2) + if (clientVersion < ES_2_0) { break; } @@ -3560,6 +3680,22 @@ bool GetQueryParameterInfo(const State &glState, *type = GL_INT; *numParams = 1; return true; + case GL_SHADING_RATE_EXT: + if (!extensions.fragmentShadingRateEXT) + { + return false; + } + *type = GL_INT; + *numParams = 1; + return true; + case GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT: + if (!extensions.fragmentShadingRateEXT) + { + return false; + } + *type = GL_BOOL; + *numParams = 1; + return true; } if (glState.getClientVersion() >= Version(3, 2)) @@ -3685,7 +3821,7 @@ bool GetQueryParameterInfo(const State &glState, { // GL_DRAW_FRAMEBUFFER_BINDING equivalent to GL_FRAMEBUFFER_BINDING case GL_READ_FRAMEBUFFER_BINDING: - if ((clientMajorVersion < 3) && !extensions.framebufferBlitAny()) + if ((clientVersion < ES_3_0) && !extensions.framebufferBlitAny()) { return false; } @@ -3694,7 +3830,7 @@ bool GetQueryParameterInfo(const State &glState, return true; case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - if ((clientMajorVersion < 3) && !extensions.getProgramBinaryOES) + if ((clientVersion < ES_3_0) && !extensions.getProgramBinaryOES) { return false; } @@ -3703,7 +3839,7 @@ bool GetQueryParameterInfo(const State &glState, return true; case GL_PROGRAM_BINARY_FORMATS_OES: - if ((clientMajorVersion < 3) && !extensions.getProgramBinaryOES) + if ((clientVersion < ES_3_0) && !extensions.getProgramBinaryOES) { return false; } @@ -3714,7 +3850,7 @@ bool GetQueryParameterInfo(const State &glState, case GL_PACK_ROW_LENGTH: case GL_PACK_SKIP_ROWS: case GL_PACK_SKIP_PIXELS: - if ((clientMajorVersion < 3) && !extensions.packSubimageNV) + if ((clientVersion < ES_3_0) && !extensions.packSubimageNV) { return false; } @@ -3724,7 +3860,7 @@ bool GetQueryParameterInfo(const State &glState, case GL_UNPACK_ROW_LENGTH: case GL_UNPACK_SKIP_ROWS: case GL_UNPACK_SKIP_PIXELS: - if ((clientMajorVersion < 3) && !extensions.unpackSubimageEXT) + if ((clientVersion < ES_3_0) && !extensions.unpackSubimageEXT) { return false; } @@ -3732,7 +3868,7 @@ bool GetQueryParameterInfo(const State &glState, *numParams = 1; return true; case GL_VERTEX_ARRAY_BINDING: - if ((clientMajorVersion < 3) && !extensions.vertexArrayObjectOES) + if ((clientVersion < ES_3_0) && !extensions.vertexArrayObjectOES) { return false; } @@ -3741,7 +3877,7 @@ bool GetQueryParameterInfo(const State &glState, return true; case GL_PIXEL_PACK_BUFFER_BINDING: case GL_PIXEL_UNPACK_BUFFER_BINDING: - if ((clientMajorVersion < 3) && !extensions.pixelBufferObjectNV) + if ((clientVersion < ES_3_0) && !extensions.pixelBufferObjectNV) { return false; } @@ -3751,7 +3887,7 @@ bool GetQueryParameterInfo(const State &glState, case GL_MAX_SAMPLES: static_assert(GL_MAX_SAMPLES_ANGLE == GL_MAX_SAMPLES, "GL_MAX_SAMPLES_ANGLE not equal to GL_MAX_SAMPLES"); - if ((clientMajorVersion < 3) && !(extensions.framebufferMultisampleANGLE || + if ((clientVersion < ES_3_0) && !(extensions.framebufferMultisampleANGLE || extensions.multisampledRenderToTextureEXT)) { return false; @@ -3760,7 +3896,7 @@ bool GetQueryParameterInfo(const State &glState, *numParams = 1; return true; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT: - if ((clientMajorVersion < 3) && !extensions.standardDerivativesOES) + if ((clientVersion < ES_3_0) && !extensions.standardDerivativesOES) { return false; } @@ -3768,7 +3904,7 @@ bool GetQueryParameterInfo(const State &glState, *numParams = 1; return true; case GL_TEXTURE_BINDING_3D: - if ((clientMajorVersion < 3) && !extensions.texture3DOES) + if ((clientVersion < ES_3_0) && !extensions.texture3DOES) { return false; } @@ -3776,7 +3912,7 @@ bool GetQueryParameterInfo(const State &glState, *numParams = 1; return true; case GL_MAX_3D_TEXTURE_SIZE: - if ((clientMajorVersion < 3) && !extensions.texture3DOES) + if ((clientVersion < ES_3_0) && !extensions.texture3DOES) { return false; } @@ -3796,7 +3932,7 @@ bool GetQueryParameterInfo(const State &glState, return true; } - if ((extensions.multiview2OVR || extensions.multiviewOVR) && pname == GL_MAX_VIEWS_OVR) + if (extensions.multiviewOVR && pname == GL_MAX_VIEWS_OVR) { *type = GL_INT; *numParams = 1; @@ -4098,7 +4234,6 @@ bool GetQueryParameterInfo(const State &glState, switch (pname) { case GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE: - case GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE: case GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE: case GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE: *type = GL_INT; @@ -4625,10 +4760,10 @@ void QueryContextAttrib(const gl::Context *context, EGLint attribute, EGLint *va break; case EGL_CONTEXT_MAJOR_VERSION: static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_CLIENT_VERSION); - *value = context->getClientMajorVersion(); + *value = context->getClientVersion().getMajor(); break; case EGL_CONTEXT_MINOR_VERSION: - *value = context->getClientMinorVersion(); + *value = context->getClientVersion().getMinor(); break; case EGL_RENDER_BUFFER: *value = context->getRenderBuffer(); @@ -4676,7 +4811,7 @@ egl::Error QuerySurfaceAttrib(const Display *display, *value = surface->getConfig()->configID; break; case EGL_HEIGHT: - ANGLE_TRY(surface->getUserHeight(display, value)); + ANGLE_TRY(surface->getUserSize(display, nullptr, value)); break; case EGL_HORIZONTAL_RESOLUTION: *value = surface->getHorizontalResolution(); @@ -4739,7 +4874,7 @@ egl::Error QuerySurfaceAttrib(const Display *display, *value = surface->getVerticalResolution(); break; case EGL_WIDTH: - ANGLE_TRY(surface->getUserWidth(display, value)); + ANGLE_TRY(surface->getUserSize(display, value, nullptr)); break; case EGL_POST_SUB_BUFFER_SUPPORTED_NV: *value = surface->isPostSubBufferSupported(); @@ -4790,7 +4925,7 @@ egl::Error QuerySurfaceAttrib(const Display *display, *value = surface->hasProtectedContent(); break; case EGL_SURFACE_COMPRESSION_EXT: - *value = surface->getCompressionRate(display); + ANGLE_TRY(surface->getCompressionRate(display, context, value)); break; default: UNREACHABLE(); diff --git a/src/libANGLE/queryutils.h b/src/libANGLE/queryutils.h index d09d2e57c67..ce2c85401fe 100644 --- a/src/libANGLE/queryutils.h +++ b/src/libANGLE/queryutils.h @@ -88,12 +88,14 @@ void QuerySamplerParameterIuiv(const Sampler *sampler, GLenum pname, GLuint *par // functions. void QueryVertexAttribfv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLfloat *params); void QueryVertexAttribiv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLint *params); @@ -102,12 +104,14 @@ void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void void QueryVertexAttribIiv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLint *params); void QueryVertexAttribIuiv(const VertexAttribute &attrib, const VertexBinding &binding, + const Buffer *buffer, const VertexAttribCurrentValueData ¤tValueData, GLenum pname, GLuint *params); @@ -122,15 +126,26 @@ void QueryInternalFormativ(const Context *context, GLenum internalformat, const TextureCaps &format, GLenum pname, - GLsizei bufSize, + GLsizei count, GLint *params); void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params); +void QueryFramebufferPixelLocalStorageParameterfv(Context *context, + GLint plane, + GLenum pname, + GLsizei *length, + GLfloat *params); +void QueryFramebufferPixelLocalStorageParameteriv(Context *context, + GLint plane, + GLenum pname, + GLsizei *length, + GLint *params); + angle::Result QuerySynciv(const Context *context, const Sync *sync, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *values); @@ -182,7 +197,7 @@ void QueryProgramResourceiv(const Program *program, UniformBlockIndex index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, GLsizei *length, GLint *params); diff --git a/src/libANGLE/renderer/BufferImpl.cpp b/src/libANGLE/renderer/BufferImpl.cpp index 9cd3c5b6f62..0ede6fbab91 100644 --- a/src/libANGLE/renderer/BufferImpl.cpp +++ b/src/libANGLE/renderer/BufferImpl.cpp @@ -26,9 +26,11 @@ angle::Result BufferImpl::setDataWithUsageFlags(const gl::Context *context, const void *data, size_t size, gl::BufferUsage usage, - GLbitfield flags) + GLbitfield flags, + gl::BufferStorage bufferStorage, + BufferFeedback *feedback) { - return setData(context, target, data, size, usage); + return setData(context, target, data, size, usage, feedback); } angle::Result BufferImpl::onLabelUpdate(const gl::Context *context) diff --git a/src/libANGLE/renderer/BufferImpl.h b/src/libANGLE/renderer/BufferImpl.h index 6238a4def3d..eebc23767c9 100644 --- a/src/libANGLE/renderer/BufferImpl.h +++ b/src/libANGLE/renderer/BufferImpl.h @@ -14,6 +14,7 @@ #include "common/mathutil.h" #include "libANGLE/Error.h" #include "libANGLE/Observer.h" +#include "libANGLE/angletypes.h" #include @@ -25,6 +26,15 @@ class Context; namespace rx { +struct BufferFeedback +{ + bool hasFeedback() const { return internalMemoryAllocationChanged || bufferStateChanged; } + // buffer's backend storage was reallocated due to optimizations to prevent having to flush + // pending commands and waiting for the GPU to become idle. + bool internalMemoryAllocationChanged = false; + // The buffer's state (size, storage etc) have changed. + bool bufferStateChanged = false; +}; // We use two set of Subject messages. The CONTENTS_CHANGED message is signaled whenever data // changes, to trigger re-translation or other events. Some buffers only need to be updated when the // underlying driver object changes - this is notified via the STORAGE_CHANGED message. @@ -32,7 +42,7 @@ class BufferImpl : public angle::Subject { public: BufferImpl(const gl::BufferState &state) : mState(state) {} - ~BufferImpl() override {} + virtual ~BufferImpl() override {} virtual void destroy(const gl::Context *context) {} virtual angle::Result setDataWithUsageFlags(const gl::Context *context, @@ -41,29 +51,40 @@ class BufferImpl : public angle::Subject const void *data, size_t size, gl::BufferUsage usage, - GLbitfield flags); + GLbitfield flags, + gl::BufferStorage bufferStorage, + BufferFeedback *feedback); virtual angle::Result setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) = 0; + gl::BufferUsage usage, + BufferFeedback *feedback) = 0; virtual angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) = 0; + size_t offset, + BufferFeedback *feedback) = 0; virtual angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) = 0; - virtual angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) = 0; + GLsizeiptr size, + BufferFeedback *feedback) = 0; + virtual angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) = 0; virtual angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) = 0; - virtual angle::Result unmap(const gl::Context *context, GLboolean *result) = 0; + void **mapPtr, + BufferFeedback *feedback) = 0; + virtual angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) = 0; virtual angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, diff --git a/src/libANGLE/renderer/BufferImpl_mock.h b/src/libANGLE/renderer/BufferImpl_mock.h index 7d6901d79d8..8079e4c3319 100644 --- a/src/libANGLE/renderer/BufferImpl_mock.h +++ b/src/libANGLE/renderer/BufferImpl_mock.h @@ -22,26 +22,40 @@ class MockBufferImpl : public BufferImpl MockBufferImpl() : BufferImpl(mMockState) {} ~MockBufferImpl() { destructor(); } - MOCK_METHOD5(setData, + MOCK_METHOD6(setData, angle::Result(const gl::Context *, gl::BufferBinding, const void *, size_t, - gl::BufferUsage)); - MOCK_METHOD5( - setSubData, - angle::Result(const gl::Context *, gl::BufferBinding, const void *, size_t, size_t)); - MOCK_METHOD5(copySubData, + gl::BufferUsage, + BufferFeedback *)); + MOCK_METHOD6(setSubData, + angle::Result(const gl::Context *, + gl::BufferBinding, + const void *, + size_t, + size_t, + BufferFeedback *)); + MOCK_METHOD6(copySubData, angle::Result(const gl::Context *contextImpl, BufferImpl *, GLintptr, GLintptr, - GLsizeiptr)); - MOCK_METHOD3(map, angle::Result(const gl::Context *contextImpl, GLenum, void **)); - MOCK_METHOD5( - mapRange, - angle::Result(const gl::Context *contextImpl, size_t, size_t, GLbitfield, void **)); - MOCK_METHOD2(unmap, angle::Result(const gl::Context *contextImpl, GLboolean *result)); + GLsizeiptr, + BufferFeedback *)); + MOCK_METHOD4(map, + angle::Result(const gl::Context *contextImpl, GLenum, void **, BufferFeedback *)); + MOCK_METHOD6(mapRange, + angle::Result(const gl::Context *contextImpl, + size_t, + size_t, + GLbitfield, + void **, + BufferFeedback *)); + MOCK_METHOD3(unmap, + angle::Result(const gl::Context *contextImpl, + GLboolean *result, + BufferFeedback *)); MOCK_METHOD6(getIndexRange, angle::Result(const gl::Context *, diff --git a/src/libANGLE/renderer/CLCommandQueueImpl.h b/src/libANGLE/renderer/CLCommandQueueImpl.h index ebeeaf79b22..f5493dc6c96 100644 --- a/src/libANGLE/renderer/CLCommandQueueImpl.h +++ b/src/libANGLE/renderer/CLCommandQueueImpl.h @@ -29,7 +29,7 @@ class CLCommandQueueImpl : angle::NonCopyable size_t size, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueWriteBuffer(const cl::Buffer &buffer, bool blocking, @@ -37,33 +37,33 @@ class CLCommandQueueImpl : angle::NonCopyable size_t size, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueReadBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueWriteBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueCopyBuffer(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, @@ -71,19 +71,19 @@ class CLCommandQueueImpl : angle::NonCopyable size_t dstOffset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueCopyBufferRect(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, size_t dstSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueFillBuffer(const cl::Buffer &buffer, const void *pattern, @@ -91,7 +91,7 @@ class CLCommandQueueImpl : angle::NonCopyable size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueMapBuffer(const cl::Buffer &buffer, bool blocking, @@ -99,113 +99,121 @@ class CLCommandQueueImpl : angle::NonCopyable size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) = 0; virtual angle::Result enqueueReadImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueWriteImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueCopyImage(const cl::Image &srcImage, const cl::Image &dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueFillImage(const cl::Image &image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueCopyImageToBuffer(const cl::Image &srcImage, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueCopyBufferToImage(const cl::Buffer &srcBuffer, const cl::Image &dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueMapImage(const cl::Image &image, bool blocking, cl::MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) = 0; virtual angle::Result enqueueUnmapMemObject(const cl::Memory &memory, void *mappedPtr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueMigrateMemObjects(const cl::MemoryPtrs &memObjects, cl::MemMigrationFlags flags, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueNDRangeKernel(const cl::Kernel &kernel, const cl::NDRange &ndrange, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueTask(const cl::Kernel &kernel, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueNativeKernel(cl::UserFunc userFunc, void *args, size_t cbArgs, const cl::BufferPtrs &buffers, - const std::vector bufferPtrOffsets, + const std::vector &bufferPtrOffsets, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueMarkerWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; - virtual angle::Result enqueueMarker(CLEventImpl::CreateFunc &eventCreateFunc) = 0; + virtual angle::Result enqueueMarker(cl::EventPtr &event) = 0; virtual angle::Result enqueueWaitForEvents(const cl::EventPtrs &events) = 0; virtual angle::Result enqueueBarrierWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) = 0; + cl::EventPtr &event) = 0; virtual angle::Result enqueueBarrier() = 0; virtual angle::Result flush() = 0; virtual angle::Result finish() = 0; + virtual angle::Result enqueueAcquireExternalMemObjectsKHR(const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) = 0; + + virtual angle::Result enqueueReleaseExternalMemObjectsKHR(const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) = 0; + protected: const cl::CommandQueue &mCommandQueue; }; diff --git a/src/libANGLE/renderer/CLEventImpl.h b/src/libANGLE/renderer/CLEventImpl.h index 34cf971a24c..8d7006a524f 100644 --- a/src/libANGLE/renderer/CLEventImpl.h +++ b/src/libANGLE/renderer/CLEventImpl.h @@ -22,8 +22,6 @@ class CLEventImpl : angle::NonCopyable CLEventImpl(const cl::Event &event); virtual ~CLEventImpl(); - virtual angle::Result onEventCreate() = 0; - virtual angle::Result getCommandExecutionStatus(cl_int &executionStatus) = 0; virtual angle::Result setUserEventStatus(cl_int executionStatus) = 0; diff --git a/src/libANGLE/renderer/CLExtensions.cpp b/src/libANGLE/renderer/CLExtensions.cpp index 230500c94f1..5e2aba8ebdf 100644 --- a/src/libANGLE/renderer/CLExtensions.cpp +++ b/src/libANGLE/renderer/CLExtensions.cpp @@ -50,6 +50,13 @@ void CLExtensions::initializeExtensions(std::string &&extensionStr) khrICD = hasExtension("cl_khr_icd"); khrInt64BaseAtomics = hasExtension("cl_khr_int64_base_atomics"); khrInt64ExtendedAtomics = hasExtension("cl_khr_int64_extended_atomics"); + khrIntegerDotProduct = hasExtension("cl_khr_integer_dot_product"); + khrExternalMemory = hasExtension("cl_khr_external_memory"); + khrPriorityHints = hasExtension("cl_khr_priority_hints"); + + armNonUniformWorkGroupSize = hasExtension("cl_arm_non_uniform_work_group_size"); + armImportMemory = hasExtension("cl_arm_import_memory"); + armImportMemoryDMABuf = hasExtension("cl_arm_import_memory_dma_buf"); } void CLExtensions::initializeVersionedExtensions(const NameVersionVector &versionedExtList) @@ -69,4 +76,20 @@ void CLExtensions::initializeVersionedExtensions(const NameVersionVector &versio return initializeExtensions(std::move(extensionString)); } +bool CLExtensions::populateSupportedExternalMemoryHandleTypes( + ExternalMemoryHandleBitset supportedHandles) +{ + externalMemoryHandleSupport = supportedHandles; + + if (externalMemoryHandleSupport.test(cl::ExternalMemoryHandle::OpaqueFd)) + { + externalMemoryHandleSupportList.push_back(cl::ToCLenum(cl::ExternalMemoryHandle::OpaqueFd)); + } + if (externalMemoryHandleSupport.test(cl::ExternalMemoryHandle::DmaBuf)) + { + externalMemoryHandleSupportList.push_back(cl::ToCLenum(cl::ExternalMemoryHandle::DmaBuf)); + } + return externalMemoryHandleSupport.any(); +} + } // namespace rx diff --git a/src/libANGLE/renderer/CLExtensions.h b/src/libANGLE/renderer/CLExtensions.h index d0602f6edcb..6221fc56d43 100644 --- a/src/libANGLE/renderer/CLExtensions.h +++ b/src/libANGLE/renderer/CLExtensions.h @@ -27,12 +27,31 @@ struct CLExtensions void initializeExtensions(std::string &&extensionStr); void initializeVersionedExtensions(const NameVersionVector &versionedExtList); + using ExternalMemoryHandleType = cl_external_memory_handle_type_khr; + using ExternalMemoryHandleBitset = angle::PackedEnumBitSet; + using ExternalMemoryHandleFixedVector = + angle::FixedVector(cl::ExternalMemoryHandle::EnumCount)>; + using SupportedDepthOrderTypes = angle::PackedEnumBitSet; + + bool populateSupportedExternalMemoryHandleTypes(ExternalMemoryHandleBitset supportedHandles); + std::string versionStr; cl_version version = 0u; std::string extensions; NameVersionVector extensionsWithVersion; + cl_device_integer_dot_product_capabilities_khr integerDotProductCapabilities; + cl_device_integer_dot_product_acceleration_properties_khr + integerDotProductAccelerationProperties8Bit; + cl_device_integer_dot_product_acceleration_properties_khr + integerDotProductAccelerationProperties4x8BitPacked; + ExternalMemoryHandleBitset externalMemoryHandleSupport; + // keep an "OpenCL list" version of supported external memory types + ExternalMemoryHandleFixedVector externalMemoryHandleSupportList; + SupportedDepthOrderTypes supportedDepthOrderTypes; + // These Khronos extension names must be returned by all devices that support OpenCL 1.1. bool khrByteAddressableStore = false; // cl_khr_byte_addressable_store bool khrGlobalInt32BaseAtomics = false; // cl_khr_global_int32_base_atomics @@ -53,6 +72,13 @@ struct CLExtensions bool khrICD = false; // cl_khr_icd bool khrInt64BaseAtomics = false; // cl_khr_int64_base_atomics bool khrInt64ExtendedAtomics = false; // cl_khr_int64_extended_atomics + bool khrIntegerDotProduct = false; // cl_khr_integer_dot_product + bool khrExternalMemory = false; // cl_khr_external_memory + bool khrPriorityHints = false; // cl_khr_priority_hints + + bool armNonUniformWorkGroupSize = false; // cl_arm_non_uniform_work_group_size + bool armImportMemory = false; // cl_arm_import_memory + bool armImportMemoryDMABuf = false; // cl_arm_import_memory_dma_buf }; } // namespace rx diff --git a/src/libANGLE/renderer/ContextImpl.cpp b/src/libANGLE/renderer/ContextImpl.cpp index 122dd5364a8..a50cc11b14a 100644 --- a/src/libANGLE/renderer/ContextImpl.cpp +++ b/src/libANGLE/renderer/ContextImpl.cpp @@ -49,6 +49,11 @@ angle::Result ContextImpl::handleNoopDrawEvent() return angle::Result::Continue; } +angle::Result ContextImpl::handleNoopMultiDrawEvent() +{ + return angle::Result::Continue; +} + void ContextImpl::setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache) { mMemoryProgramCache = memoryProgramCache; @@ -98,9 +103,22 @@ angle::Result ContextImpl::releaseTextures(const gl::Context *context, return angle::Result::Stop; } +const angle::PerfMonitorCounterGroupsInfo &ContextImpl::getPerfMonitorCountersInfo() const +{ + static angle::base::NoDestructor sCountersInfo; + return *sCountersInfo; +} + const angle::PerfMonitorCounterGroups &ContextImpl::getPerfMonitorCounters() { static angle::base::NoDestructor sCounters; return *sCounters; } + +const angle::ShadingRateMap &ContextImpl::getSupportedFragmentShadingRateEXTSampleCounts() const +{ + UNREACHABLE(); + static angle::ShadingRateMap empty; + return empty; +} } // namespace rx diff --git a/src/libANGLE/renderer/ContextImpl.h b/src/libANGLE/renderer/ContextImpl.h index 1cd8e4f3964..5b1cf26b04e 100644 --- a/src/libANGLE/renderer/ContextImpl.h +++ b/src/libANGLE/renderer/ContextImpl.h @@ -190,6 +190,7 @@ class ContextImpl : public GLImplFactory const std::string &message) = 0; virtual angle::Result popDebugGroup(const gl::Context *context) = 0; virtual angle::Result handleNoopDrawEvent(); + virtual angle::Result handleNoopMultiDrawEvent(); // KHR_parallel_shader_compile virtual void setMaxShaderCompilerThreads(GLuint count) {} @@ -225,13 +226,15 @@ class ContextImpl : public GLImplFactory virtual angle::Result onMakeCurrent(const gl::Context *context) = 0; virtual angle::Result onUnMakeCurrent(const gl::Context *context); + // EXT_fragment_shading_rate + virtual const angle::ShadingRateMap &getSupportedFragmentShadingRateEXTSampleCounts() const; + // Native capabilities, unmodified by gl::Context. virtual gl::Caps getNativeCaps() const = 0; virtual const gl::TextureCapsMap &getNativeTextureCaps() const = 0; virtual const gl::Extensions &getNativeExtensions() const = 0; virtual const gl::Limitations &getNativeLimitations() const = 0; virtual const ShPixelLocalStorageOptions &getNativePixelLocalStorageOptions() const = 0; - virtual angle::Result dispatchCompute(const gl::Context *context, GLuint numGroupsX, GLuint numGroupsY, @@ -244,8 +247,6 @@ class ContextImpl : public GLImplFactory GLbitfield barriers) = 0; const gl::State &getState() const { return mState; } - int getClientMajorVersion() const { return mState.getClientMajorVersion(); } - int getClientMinorVersion() const { return mState.getClientMinorVersion(); } const gl::Caps &getCaps() const { return mState.getCaps(); } const gl::TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); } const gl::Extensions &getExtensions() const { return mState.getExtensions(); } @@ -279,6 +280,7 @@ class ContextImpl : public GLImplFactory gl::TextureBarrierVector *textureBarriers); // AMD_performance_monitor + virtual const angle::PerfMonitorCounterGroupsInfo &getPerfMonitorCountersInfo() const; virtual const angle::PerfMonitorCounterGroups &getPerfMonitorCounters(); protected: diff --git a/src/libANGLE/renderer/DisplayImpl.cpp b/src/libANGLE/renderer/DisplayImpl.cpp index 6deb8709420..8b4573f4d9d 100644 --- a/src/libANGLE/renderer/DisplayImpl.cpp +++ b/src/libANGLE/renderer/DisplayImpl.cpp @@ -126,7 +126,7 @@ angle::NativeWindowSystem DisplayImpl::getWindowSystem() const return angle::NativeWindowSystem::Other; } -bool DisplayImpl::supportsDmaBufFormat(EGLint format) const +bool DisplayImpl::supportsDmaBufFormat(EGLint format) { UNREACHABLE(); return false; diff --git a/src/libANGLE/renderer/DisplayImpl.h b/src/libANGLE/renderer/DisplayImpl.h index bab35296994..af7cdac0d50 100644 --- a/src/libANGLE/renderer/DisplayImpl.h +++ b/src/libANGLE/renderer/DisplayImpl.h @@ -122,7 +122,7 @@ class DisplayImpl : public EGLImplFactory, public angle::Subject virtual angle::NativeWindowSystem getWindowSystem() const; - virtual bool supportsDmaBufFormat(EGLint format) const; + virtual bool supportsDmaBufFormat(EGLint format); virtual egl::Error queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats); virtual egl::Error queryDmaBufModifiers(EGLint format, EGLint max_modifiers, diff --git a/src/libANGLE/renderer/EGLReusableSync.cpp b/src/libANGLE/renderer/EGLReusableSync.cpp index ab171d4f1a8..799cd89bb7e 100644 --- a/src/libANGLE/renderer/EGLReusableSync.cpp +++ b/src/libANGLE/renderer/EGLReusableSync.cpp @@ -8,6 +8,8 @@ #include "libANGLE/renderer/EGLReusableSync.h" +#include + #include "libANGLE/Context.h" #include "libANGLE/renderer/ContextImpl.h" diff --git a/src/libANGLE/renderer/Format.h b/src/libANGLE/renderer/Format.h index e45f1ad4bc1..adc0028dc00 100644 --- a/src/libANGLE/renderer/Format.h +++ b/src/libANGLE/renderer/Format.h @@ -12,6 +12,10 @@ #ifndef LIBANGLE_RENDERER_FORMAT_H_ #define LIBANGLE_RENDERER_FORMAT_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/cl_types.h" #include "libANGLE/renderer/FormatID_autogen.h" #include "libANGLE/renderer/renderer_utils.h" diff --git a/src/libANGLE/renderer/FormatID_autogen.h b/src/libANGLE/renderer/FormatID_autogen.h index f797807237d..d9760382b67 100644 --- a/src/libANGLE/renderer/FormatID_autogen.h +++ b/src/libANGLE/renderer/FormatID_autogen.h @@ -121,6 +121,7 @@ enum class FormatID : uint8_t ETC2_R8G8B8A8_UNORM_BLOCK, ETC2_R8G8B8_SRGB_BLOCK, ETC2_R8G8B8_UNORM_BLOCK, + G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, G8_B8R8_2PLANE_420_UNORM, G8_B8_R8_3PLANE_420_UNORM, L16A16_FLOAT, @@ -155,6 +156,7 @@ enum class FormatID : uint8_t R10G10B10A2_UNORM, R10G10B10A2_USCALED, R10G10B10X2_UNORM, + R10X6G10X6B10X6A10X6_UNORM, R11G11B10_FLOAT, R16G16B16A16_FLOAT, R16G16B16A16_SINT, @@ -268,7 +270,7 @@ enum class FormatID : uint8_t EXTERNAL7 }; -constexpr uint32_t kNumANGLEFormats = 249; +constexpr uint32_t kNumANGLEFormats = 251; } // namespace angle diff --git a/src/libANGLE/renderer/Format_table_autogen.cpp b/src/libANGLE/renderer/Format_table_autogen.cpp index 52b0d592323..2f40149800d 100644 --- a/src/libANGLE/renderer/Format_table_autogen.cpp +++ b/src/libANGLE/renderer/Format_table_autogen.cpp @@ -20,7 +20,10 @@ namespace angle static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {angle::FormatID::R8G8B8A8_UNORM, CopyBGRA8ToRGBA8}; +static constexpr rx::FastCopyFunctionMap::Entry RGBAEntry = {angle::FormatID::R8G8B8A8_UNORM, + CopyRGBA8ToRGBA8}; static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {&BGRAEntry, 1}; +static constexpr rx::FastCopyFunctionMap RGBACopyFunctions = {&RGBAEntry, 1}; static constexpr rx::FastCopyFunctionMap NoCopyFunctions; const Format gFormatInfoTable[] = { @@ -129,6 +132,7 @@ const Format gFormatInfoTable[] = { { FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 16, 0, true, false, false, false, false, gl::VertexAttribType::UnsignedByte }, { FormatID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false, false, true, false, gl::VertexAttribType::Byte }, { FormatID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false, false, false, false, gl::VertexAttribType::UnsignedByte }, + { FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE, GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 0, 0, 0, 0, 5, std::numeric_limits::max(), false, false, false, false, true, gl::VertexAttribType::InvalidEnum }, { FormatID::G8_B8R8_2PLANE_420_UNORM, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, true, gl::VertexAttribType::UnsignedByte }, { FormatID::G8_B8_R8_3PLANE_420_UNORM, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, true, gl::VertexAttribType::UnsignedByte }, { FormatID::L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA16F_EXT, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_FLOAT, 0, 0, 0, 16, 16, 0, 0, 4, std::numeric_limits::max(), false, false, false, false, false, gl::VertexAttribType::Float }, @@ -163,6 +167,7 @@ const Format gFormatInfoTable[] = { { FormatID::R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt2101010 }, { FormatID::R10G10B10A2_USCALED, GL_RGB10_A2_USCALED_ANGLEX, GL_RGB10_A2_USCALED_ANGLEX, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits::max(), false, false, true, false, false, gl::VertexAttribType::UnsignedInt2101010 }, { FormatID::R10G10B10X2_UNORM, GL_RGB10_EXT, GL_RGB10_EXT, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt2101010 }, + { FormatID::R10X6G10X6B10X6A10X6_UNORM, GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX, GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 10, 0, 0, 0, 6, std::numeric_limits::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum }, { FormatID::R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_FLOAT, 11, 11, 10, 0, 0, 0, 0, 4, std::numeric_limits::max(), false, false, false, false, false, gl::VertexAttribType::Float }, { FormatID::R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA16F, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_FLOAT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::HalfFloat }, { FormatID::R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA16I, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_INT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::Short }, @@ -233,8 +238,8 @@ const Format gFormatInfoTable[] = { { FormatID::R8G8B8A8_TYPELESS, GL_RGBA8, GL_RGBA8, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte }, { FormatID::R8G8B8A8_TYPELESS_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte }, { FormatID::R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA8UI, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte }, - { FormatID::R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte }, - { FormatID::R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte }, + { FormatID::R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip, RGBACopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte }, + { FormatID::R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip, RGBACopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte }, { FormatID::R8G8B8A8_USCALED, GL_RGBA8_USCALED_ANGLEX, GL_RGBA8_USCALED_ANGLEX, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, true, false, false, gl::VertexAttribType::UnsignedByte }, { FormatID::R8G8B8X8_UNORM, GL_RGBX8_ANGLE, GL_RGBX8_ANGLE, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte }, { FormatID::R8G8B8X8_UNORM_SRGB, GL_RGBX8_SRGB_ANGLEX, GL_RGBX8_SRGB_ANGLEX, GenerateMip, NoCopyFunctions, ReadColor, WriteColor, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits::max(), false, false, false, true, false, gl::VertexAttribType::Byte }, @@ -314,6 +319,8 @@ FormatID Format::InternalFormatToID(GLenum internalFormat) return FormatID::B8G8R8A8_TYPELESS; case GL_BGRA8_TYPELESS_SRGB_ANGLEX: return FormatID::B8G8R8A8_TYPELESS_SRGB; + case GL_BGRA_EXT: + return FormatID::B8G8R8A8_UNORM; case GL_BGRX8_ANGLEX: return FormatID::B8G8R8X8_UNORM; case GL_BGRX8_SRGB_ANGLEX: @@ -498,6 +505,8 @@ FormatID Format::InternalFormatToID(GLenum internalFormat) return FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK; case GL_ETC1_RGB8_OES: return FormatID::ETC1_R8G8B8_UNORM_BLOCK; + case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE: + return FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16; case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE: return FormatID::G8_B8R8_2PLANE_420_UNORM; case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE: @@ -540,6 +549,8 @@ FormatID Format::InternalFormatToID(GLenum internalFormat) return FormatID::PALETTE8_R4G4B4A4_UNORM; case GL_PALETTE8_RGBA8_OES: return FormatID::PALETTE8_R8G8B8A8_UNORM; + case GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX: + return FormatID::R10X6G10X6B10X6A10X6_UNORM; case GL_R11F_G11F_B10F: return FormatID::R11G11B10_FLOAT; case GL_R16F: diff --git a/src/libANGLE/renderer/GLImplFactory.h b/src/libANGLE/renderer/GLImplFactory.h index 3f17b99ed7b..ba7985f49c1 100644 --- a/src/libANGLE/renderer/GLImplFactory.h +++ b/src/libANGLE/renderer/GLImplFactory.h @@ -79,7 +79,9 @@ class GLImplFactory : angle::NonCopyable virtual BufferImpl *createBuffer(const gl::BufferState &state) = 0; // Vertex Array creation - virtual VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) = 0; + virtual VertexArrayImpl *createVertexArray( + const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) = 0; // Query and Fence creation virtual QueryImpl *createQuery(gl::QueryType type) = 0; diff --git a/src/libANGLE/renderer/ProgramImpl.h b/src/libANGLE/renderer/ProgramImpl.h index 1a14d574c4b..c56180532f4 100644 --- a/src/libANGLE/renderer/ProgramImpl.h +++ b/src/libANGLE/renderer/ProgramImpl.h @@ -93,6 +93,11 @@ class ProgramImpl : angle::NonCopyable virtual void setSeparable(bool separable) = 0; virtual void prepareForLink(const gl::ShaderMap &shaders) {} + virtual void prepareForPassthroughLink( + gl::ShaderMap *outAttachedShaders) + { + UNREACHABLE(); + } virtual angle::Result link(const gl::Context *context, std::shared_ptr *linkTaskOut) = 0; virtual GLboolean validate(const gl::Caps &caps) = 0; diff --git a/src/libANGLE/renderer/SurfaceImpl.cpp b/src/libANGLE/renderer/SurfaceImpl.cpp index 7e3dfd47004..de2e0e199a0 100644 --- a/src/libANGLE/renderer/SurfaceImpl.cpp +++ b/src/libANGLE/renderer/SurfaceImpl.cpp @@ -32,19 +32,13 @@ egl::Error SurfaceImpl::prepareSwap(const gl::Context *) egl::Error SurfaceImpl::swapWithDamage(const gl::Context *context, const EGLint *rects, - EGLint n_rects) + EGLint n_rects, + SurfaceSwapFeedback *feedback) { UNREACHABLE(); return egl::Error(EGL_BAD_SURFACE, "swapWithDamage implementation missing."); } -egl::Error SurfaceImpl::swapWithFrameToken(const gl::Context *context, - EGLFrameTokenANGLE frameToken) -{ - UNREACHABLE(); - return egl::Error(EGL_BAD_DISPLAY); -} - egl::Error SurfaceImpl::postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -94,7 +88,7 @@ void SurfaceImpl::setTimestampsEnabled(bool enabled) UNREACHABLE(); } -const angle::Format *SurfaceImpl::getD3DTextureColorFormat() const +const angle::Format *SurfaceImpl::getClientBufferTextureColorFormat() const { UNREACHABLE(); return nullptr; @@ -134,15 +128,28 @@ egl::Error SurfaceImpl::getFrameTimestamps(EGLuint64KHR frameId, UNREACHABLE(); return egl::Error(EGL_BAD_DISPLAY); } -egl::Error SurfaceImpl::getUserWidth(const egl::Display *display, EGLint *value) const + +angle::Result SurfaceImpl::ensureSizeResolved(const gl::Context *context) { - *value = getWidth(); - return egl::NoError(); + return angle::Result::Continue; } -egl::Error SurfaceImpl::getUserHeight(const egl::Display *display, EGLint *value) const +egl::Error SurfaceImpl::getUserSize(const egl::Display *display, + EGLint *width, + EGLint *height) const { - *value = getHeight(); + // Override getUserSize() if it is not the same as getSize() or if its usage is suboptimal. + // In case of override use "final" for both methods when possible to prevent accidental bugs. + const gl::Extents size = getSize(); + ASSERT(size.depth == 1); + if (width != nullptr) + { + *width = size.width; + } + if (height != nullptr) + { + *height = size.height; + } return egl::NoError(); } @@ -189,10 +196,17 @@ egl::Error SurfaceImpl::setRenderBuffer(EGLint renderBuffer) return egl::NoError(); } -EGLint SurfaceImpl::getCompressionRate(const egl::Display *display) const +egl::Error SurfaceImpl::getCompressionRate(const egl::Display *display, + const gl::Context *context, + EGLint *rate) { - UNREACHABLE(); - return EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT; + *rate = EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT; + return egl::NoError(); +} + +bool SurfaceImpl::supportsSingleRenderBuffer() const +{ + return false; } } // namespace rx diff --git a/src/libANGLE/renderer/SurfaceImpl.h b/src/libANGLE/renderer/SurfaceImpl.h index 8b059007e4c..7f94d5ed91e 100644 --- a/src/libANGLE/renderer/SurfaceImpl.h +++ b/src/libANGLE/renderer/SurfaceImpl.h @@ -41,6 +41,11 @@ using SupportedCompositorTimings = angle::PackedEnumBitSet; namespace rx { +struct SurfaceSwapFeedback +{ + bool swapChainImageChanged = false; +}; + class SurfaceImpl : public FramebufferAttachmentObjectImpl { public: @@ -52,12 +57,11 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl virtual egl::Error makeCurrent(const gl::Context *context); virtual egl::Error unMakeCurrent(const gl::Context *context); virtual egl::Error prepareSwap(const gl::Context *); - virtual egl::Error swap(const gl::Context *context) = 0; + virtual egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) = 0; virtual egl::Error swapWithDamage(const gl::Context *context, const EGLint *rects, - EGLint n_rects); - virtual egl::Error swapWithFrameToken(const gl::Context *context, - EGLFrameTokenANGLE frameToken); + EGLint n_rects, + SurfaceSwapFeedback *feedback); virtual egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -75,18 +79,15 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl virtual void setFixedWidth(EGLint width); virtual void setFixedHeight(EGLint height); - // width and height can change with client window resizing - virtual EGLint getWidth() const = 0; - virtual EGLint getHeight() const = 0; - // Note: windows cannot be resized on Android. The approach requires - // calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR. However, that is - // expensive; and there are troublesome timing issues for other parts of - // ANGLE (which cause test failures and crashes). Therefore, a - // special-Android-only path is created just for the querying of EGL_WIDTH - // and EGL_HEIGHT. - // https://issuetracker.google.com/issues/153329980 - virtual egl::Error getUserWidth(const egl::Display *display, EGLint *value) const; - virtual egl::Error getUserHeight(const egl::Display *display, EGLint *value) const; + // Explicitly resolves surface size to use before state synchronization (e.g. validation). + virtual angle::Result ensureSizeResolved(const gl::Context *context); + // size can change with client window resizing + // Size must be resolved before the call either during state synchronization or explicitly. + virtual gl::Extents getSize() const = 0; + // Unresolved Surface size until render target is first accessed (e.g. after draw). + virtual egl::Error getUserSize(const egl::Display *display, + EGLint *width, + EGLint *height) const; virtual EGLint isPostSubBufferSupported() const; virtual EGLint getSwapBehavior() const = 0; @@ -96,8 +97,8 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl virtual egl::Error detachFromFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) = 0; - // Used to query color format from pbuffers created from D3D textures. - virtual const angle::Format *getD3DTextureColorFormat() const; + // Used to query color format from pbuffers created from D3D and WebGPU textures. + virtual const angle::Format *getClientBufferTextureColorFormat() const; // EGL_ANDROID_get_frame_timestamps virtual void setTimestampsEnabled(bool enabled); @@ -127,7 +128,11 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl virtual egl::Error setRenderBuffer(EGLint renderBuffer); - virtual EGLint getCompressionRate(const egl::Display *display) const; + virtual egl::Error getCompressionRate(const egl::Display *display, + const gl::Context *context, + EGLint *rate); + + virtual bool supportsSingleRenderBuffer() const; protected: const egl::SurfaceState &mState; diff --git a/src/libANGLE/renderer/VertexArrayImpl.h b/src/libANGLE/renderer/VertexArrayImpl.h index 8e33c901c2c..6b4166a8b94 100644 --- a/src/libANGLE/renderer/VertexArrayImpl.h +++ b/src/libANGLE/renderer/VertexArrayImpl.h @@ -12,6 +12,7 @@ #include "common/angleutils.h" #include "libANGLE/Buffer.h" #include "libANGLE/VertexArray.h" +#include "libANGLE/angletypes.h" // This is a helper X macro for iterating over all dirty attribs/bindings. Useful for dirty bits. static_assert(gl::MAX_VERTEX_ATTRIBS == 16, "Invalid max vertex attribs"); @@ -31,7 +32,19 @@ class ContextImpl; class VertexArrayImpl : angle::NonCopyable { public: - VertexArrayImpl(const gl::VertexArrayState &state) : mState(state) {} + VertexArrayImpl(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers) + : mState(state), mVertexArrayBuffers(vertexArrayBuffers) + { + // ElementBuffer always observe the buffer content change. + mContentsObserverBindingsMask.set(gl::kElementArrayBufferIndex); + } + + // This gives backend an opportunity to check buffers to see if buffer has been modified that + // requires VertexArray sync. + virtual gl::VertexArray::DirtyBits checkBufferForDirtyBits( + const gl::Context *context, + const gl::VertexArrayBufferBindingMask bufferBindingMask); // It's up to the implementation to reset the attrib and binding dirty bits. // This is faster than the front-end having to clear all the bits after they have been scanned. @@ -45,18 +58,48 @@ class VertexArrayImpl : angle::NonCopyable const gl::VertexArrayState &getState() const { return mState; } - void setContentsObservers(gl::VertexArrayBufferContentsObservers *observers) + gl::VertexArrayBufferBindingMask getContentObserversBindingMask() const { - mContentsObservers = observers; + return mContentsObserverBindingsMask; } virtual angle::Result onLabelUpdate(const gl::Context *context); + gl::Buffer *getElementArrayBuffer() const + { + return mVertexArrayBuffers[gl::kElementArrayBufferIndex].get(); + } + gl::Buffer *getVertexArrayBuffer(size_t bindingIndex) const + { + ASSERT(bindingIndex != gl::kElementArrayBufferIndex); + return mVertexArrayBuffers[bindingIndex].get(); + } + + const gl::BindingPointer &getBufferBindingPointer(size_t bindingIndex) const + { + return mVertexArrayBuffers[bindingIndex]; + } + protected: const gl::VertexArrayState &mState; - gl::VertexArrayBufferContentsObservers *mContentsObservers = nullptr; + const gl::VertexArrayBuffers &mVertexArrayBuffers; + // Tracks back end's needs for buffer content change at each binding index. If the bit is set, + // current context's VertexArray will be notified when a related buffer data has changed along + // with this bit mask. + gl::VertexArrayBufferBindingMask mContentsObserverBindingsMask; }; +inline gl::VertexArray::DirtyBits VertexArrayImpl::checkBufferForDirtyBits( + const gl::Context *context, + const gl::VertexArrayBufferBindingMask bufferBindingMask) +{ + // For now we just simply assume buffer storage has changed and always dirty all + // binding points. + uint64_t bits = bufferBindingMask.bits(); + bits <<= gl::VertexArray::DIRTY_BIT_BINDING_0; + return gl::VertexArray::DirtyBits(bits); +} + inline angle::Result VertexArrayImpl::syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, gl::VertexArray::DirtyAttribBitsArray *attribBits, diff --git a/src/libANGLE/renderer/angle_format_data.json b/src/libANGLE/renderer/angle_format_data.json index e10a56d6864..ae6c7541e6f 100644 --- a/src/libANGLE/renderer/angle_format_data.json +++ b/src/libANGLE/renderer/angle_format_data.json @@ -300,5 +300,12 @@ }, "G8_B8R8_2PLANE_420_UNORM": { "channelStruct": "R8G8B8" + }, + "R10X6G10X6B10X6A10X6_UNORM": { + "glInternalFormat": "GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX", + "channelStruct": "R10X6G10X6B10X6A10X6" + }, + "G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16": { + "channelStruct": "R8G8B8" } } diff --git a/src/libANGLE/renderer/angle_format_map.json b/src/libANGLE/renderer/angle_format_map.json index 15d7ce8ff60..a35fcfb8ddd 100644 --- a/src/libANGLE/renderer/angle_format_map.json +++ b/src/libANGLE/renderer/angle_format_map.json @@ -5,8 +5,9 @@ [ "GL_BGR565_ANGLEX", "B5G6R5_UNORM" ], [ "GL_BGR5_A1_ANGLEX", "B5G5R5A1_UNORM" ], [ "GL_BGRA4_ANGLEX", "B4G4R4A4_UNORM" ], + [ "GL_BGRA_EXT", "B8G8R8A8_UNORM" ], [ "GL_BGRA8_EXT", "B8G8R8A8_UNORM" ], - [ "GL_BGRA8_SRGB_ANGLEX", "B8G8R8A8_UNORM_SRGB"], + [ "GL_BGRA8_SRGB_ANGLEX", "B8G8R8A8_UNORM_SRGB" ], [ "GL_BGRX8_ANGLEX", "B8G8R8X8_UNORM" ], [ "GL_BGRX8_SRGB_ANGLEX", "B8G8R8X8_UNORM_SRGB" ], [ "GL_RGBX8_ANGLE", "R8G8B8X8_UNORM" ], @@ -222,6 +223,7 @@ [ "GL_X2_RGB10_SSCALED_ANGLEX", "X2R10G10B10_SSCALED_VERTEX" ], [ "GL_X2_RGB10_UNORM_ANGLEX", "X2R10G10B10_UNORM_VERTEX" ], [ "GL_X2_RGB10_SNORM_ANGLEX", "X2R10G10B10_SNORM_VERTEX" ], + [ "GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX", "R10X6G10X6B10X6A10X6_UNORM" ], [ "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG", "PVRTC1_RGB_4BPP_UNORM_BLOCK" ], [ "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG", "PVRTC1_RGB_2BPP_UNORM_BLOCK" ], [ "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG", "PVRTC1_RGBA_4BPP_UNORM_BLOCK" ], @@ -241,5 +243,6 @@ [ "GL_PALETTE8_RGBA8_OES", "PALETTE8_R8G8B8A8_UNORM" ], [ "GL_PALETTE8_R5_G6_B5_OES", "PALETTE8_R5G6B5_UNORM" ], [ "GL_PALETTE8_RGBA4_OES", "PALETTE8_R4G4B4A4_UNORM" ], - [ "GL_PALETTE8_RGB5_A1_OES", "PALETTE8_R5G5B5A1_UNORM" ] + [ "GL_PALETTE8_RGB5_A1_OES", "PALETTE8_R5G5B5A1_UNORM" ], + [ "GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE", "G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16" ] ] diff --git a/src/libANGLE/renderer/cl/CLCommandQueueCL.cpp b/src/libANGLE/renderer/cl/CLCommandQueueCL.cpp index 08066ab476c..5f42f5de421 100644 --- a/src/libANGLE/renderer/cl/CLCommandQueueCL.cpp +++ b/src/libANGLE/renderer/cl/CLCommandQueueCL.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLCommandQueueCL.cpp: Implements the class methods for CLCommandQueueCL. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/cl/CLCommandQueueCL.h" @@ -15,6 +20,7 @@ #include "libANGLE/CLBuffer.h" #include "libANGLE/CLCommandQueue.h" #include "libANGLE/CLContext.h" +#include "libANGLE/CLEvent.h" #include "libANGLE/CLImage.h" #include "libANGLE/CLKernel.h" #include "libANGLE/CLMemory.h" @@ -25,14 +31,15 @@ namespace rx namespace { -void CheckCreateEvent(cl_event nativeEvent, CLEventImpl::CreateFunc *createFunc) +angle::Result CreateEventBackend(cl_event nativeEvent, cl::EventPtr &event) { - if (createFunc != nullptr) + if (event != nullptr) { - *createFunc = [nativeEvent](const cl::Event &event) { + ANGLE_TRY(event->initBackend([nativeEvent](const cl::Event &event) { return CLEventImpl::Ptr(new CLEventCL(event, nativeEvent)); - }; + })); } + return angle::Result::Continue; } } // namespace @@ -76,7 +83,7 @@ angle::Result CLCommandQueueCL::enqueueReadBuffer(const cl::Buffer &buffer, size_t size, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeBuffer = buffer.getImpl().getNative(); const cl_bool block = blocking ? CL_TRUE : CL_FALSE; @@ -84,14 +91,13 @@ angle::Result CLCommandQueueCL::enqueueReadBuffer(const cl::Buffer &buffer, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueReadBuffer(mNative, nativeBuffer, block, offset, size, ptr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueWriteBuffer(const cl::Buffer &buffer, @@ -100,7 +106,7 @@ angle::Result CLCommandQueueCL::enqueueWriteBuffer(const cl::Buffer &buffer, size_t size, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeBuffer = buffer.getImpl().getNative(); const cl_bool block = blocking ? CL_TRUE : CL_FALSE; @@ -108,28 +114,27 @@ angle::Result CLCommandQueueCL::enqueueWriteBuffer(const cl::Buffer &buffer, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueWriteBuffer(mNative, nativeBuffer, block, offset, size, ptr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueReadBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeBuffer = buffer.getImpl().getNative(); const cl_bool block = blocking ? CL_TRUE : CL_FALSE; @@ -137,32 +142,31 @@ angle::Result CLCommandQueueCL::enqueueReadBufferRect(const cl::Buffer &buffer, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t bufferOriginArray[3] = {bufferOrigin.x, bufferOrigin.y, bufferOrigin.z}; size_t hostOriginArray[3] = {hostOrigin.x, hostOrigin.y, hostOrigin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueReadBufferRect( mNative, nativeBuffer, block, bufferOriginArray, hostOriginArray, regionArray, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueWriteBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeBuffer = buffer.getImpl().getNative(); const cl_bool block = blocking ? CL_TRUE : CL_FALSE; @@ -170,18 +174,17 @@ angle::Result CLCommandQueueCL::enqueueWriteBufferRect(const cl::Buffer &buffer, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t bufferOriginArray[3] = {bufferOrigin.x, bufferOrigin.y, bufferOrigin.z}; size_t hostOriginArray[3] = {hostOrigin.x, hostOrigin.y, hostOrigin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueWriteBufferRect( mNative, nativeBuffer, block, bufferOriginArray, hostOriginArray, regionArray, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueCopyBuffer(const cl::Buffer &srcBuffer, @@ -190,7 +193,7 @@ angle::Result CLCommandQueueCL::enqueueCopyBuffer(const cl::Buffer &srcBuffer, size_t dstOffset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeSrc = srcBuffer.getImpl().getNative(); const cl_mem nativeDst = dstBuffer.getImpl().getNative(); @@ -198,27 +201,26 @@ angle::Result CLCommandQueueCL::enqueueCopyBuffer(const cl::Buffer &srcBuffer, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueCopyBuffer(mNative, nativeSrc, nativeDst, srcOffset, dstOffset, size, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueCopyBufferRect(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, size_t dstSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeSrc = srcBuffer.getImpl().getNative(); const cl_mem nativeDst = dstBuffer.getImpl().getNative(); @@ -226,17 +228,16 @@ angle::Result CLCommandQueueCL::enqueueCopyBufferRect(const cl::Buffer &srcBuffe const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t srcOriginArray[3] = {srcOrigin.x, srcOrigin.y, srcOrigin.z}; size_t dstOriginArray[3] = {dstOrigin.x, dstOrigin.y, dstOrigin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueCopyBufferRect( mNative, nativeSrc, nativeDst, srcOriginArray, dstOriginArray, regionArray, srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueFillBuffer(const cl::Buffer &buffer, @@ -245,21 +246,20 @@ angle::Result CLCommandQueueCL::enqueueFillBuffer(const cl::Buffer &buffer, size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeBuffer = buffer.getImpl().getNative(); const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueFillBuffer(mNative, nativeBuffer, pattern, patternSize, offset, size, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueMapBuffer(const cl::Buffer &buffer, @@ -268,7 +268,7 @@ angle::Result CLCommandQueueCL::enqueueMapBuffer(const cl::Buffer &buffer, size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) { const cl_mem nativeBuffer = buffer.getImpl().getNative(); @@ -277,7 +277,7 @@ angle::Result CLCommandQueueCL::enqueueMapBuffer(const cl::Buffer &buffer, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; cl_int errorCode = CL_SUCCESS; mapPtr = mNative->getDispatch().clEnqueueMapBuffer(mNative, nativeBuffer, block, mapFlags.get(), @@ -285,19 +285,18 @@ angle::Result CLCommandQueueCL::enqueueMapBuffer(const cl::Buffer &buffer, nativeEventPtr, &errorCode); ANGLE_CL_TRY(errorCode); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueReadImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeImage = image.getImpl().getNative(); const cl_bool block = blocking ? CL_TRUE : CL_FALSE; @@ -305,27 +304,26 @@ angle::Result CLCommandQueueCL::enqueueReadImage(const cl::Image &image, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t originArray[3] = {origin.x, origin.y, origin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueReadImage( mNative, nativeImage, block, originArray, regionArray, rowPitch, slicePitch, ptr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueWriteImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeImage = image.getImpl().getNative(); const cl_bool block = blocking ? CL_TRUE : CL_FALSE; @@ -333,25 +331,24 @@ angle::Result CLCommandQueueCL::enqueueWriteImage(const cl::Image &image, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t originArray[3] = {origin.x, origin.y, origin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueWriteImage( mNative, nativeImage, block, originArray, regionArray, inputRowPitch, inputSlicePitch, ptr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueCopyImage(const cl::Image &srcImage, const cl::Image &dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeSrc = srcImage.getImpl().getNative(); const cl_mem nativeDst = dstImage.getImpl().getNative(); @@ -359,50 +356,48 @@ angle::Result CLCommandQueueCL::enqueueCopyImage(const cl::Image &srcImage, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t srcOriginArray[3] = {srcOrigin.x, srcOrigin.y, srcOrigin.z}; size_t dstOriginArray[3] = {dstOrigin.x, dstOrigin.y, dstOrigin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueCopyImage( mNative, nativeSrc, nativeDst, srcOriginArray, dstOriginArray, regionArray, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueFillImage(const cl::Image &image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeImage = image.getImpl().getNative(); const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t originArray[3] = {origin.x, origin.y, origin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueFillImage(mNative, nativeImage, fillColor, originArray, regionArray, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueCopyImageToBuffer(const cl::Image &srcImage, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeSrc = srcImage.getImpl().getNative(); const cl_mem nativeDst = dstBuffer.getImpl().getNative(); @@ -410,25 +405,24 @@ angle::Result CLCommandQueueCL::enqueueCopyImageToBuffer(const cl::Image &srcIma const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t srcOriginArray[3] = {srcOrigin.x, srcOrigin.y, srcOrigin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueCopyImageToBuffer( mNative, nativeSrc, nativeDst, srcOriginArray, regionArray, dstOffset, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueCopyBufferToImage(const cl::Buffer &srcBuffer, const cl::Image &dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeSrc = srcBuffer.getImpl().getNative(); const cl_mem nativeDst = dstImage.getImpl().getNative(); @@ -436,27 +430,26 @@ angle::Result CLCommandQueueCL::enqueueCopyBufferToImage(const cl::Buffer &srcBu const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t dstOriginArray[3] = {dstOrigin.x, dstOrigin.y, dstOrigin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueCopyBufferToImage( mNative, nativeSrc, nativeDst, srcOffset, dstOriginArray, regionArray, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueMapImage(const cl::Image &image, bool blocking, cl::MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) { const cl_mem nativeImage = image.getImpl().getNative(); @@ -465,9 +458,9 @@ angle::Result CLCommandQueueCL::enqueueMapImage(const cl::Image &image, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; size_t originArray[3] = {origin.x, origin.y, origin.z}; - size_t regionArray[3] = {region.x, region.y, region.z}; + size_t regionArray[3] = {region.width, region.height, region.depth}; cl_int errorCode = CL_SUCCESS; mapPtr = mNative->getDispatch().clEnqueueMapImage( @@ -483,33 +476,31 @@ angle::Result CLCommandQueueCL::enqueueMapImage(const cl::Image &image, *imageSlicePitch = 0u; } - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueUnmapMemObject(const cl::Memory &memory, void *mappedPtr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_mem nativeMemory = memory.getImpl().getNative(); const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueUnmapMemObject( mNative, nativeMemory, mappedPtr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueMigrateMemObjects(const cl::MemoryPtrs &memObjects, cl::MemMigrationFlags flags, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::vector nativeMemories; nativeMemories.reserve(memObjects.size()); @@ -522,27 +513,26 @@ angle::Result CLCommandQueueCL::enqueueMigrateMemObjects(const cl::MemoryPtrs &m const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueMigrateMemObjects( mNative, numMemories, nativeMemories.data(), flags.get(), numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueNDRangeKernel(const cl::Kernel &kernel, const cl::NDRange &ndrange, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_kernel nativeKernel = kernel.getImpl().getNative(); const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; std::array globalWorkOffset{ndrange.globalWorkOffset[0], ndrange.globalWorkOffset[1], ndrange.globalWorkOffset[2]}; std::array globalWorkSize{ndrange.globalWorkSize[0], ndrange.globalWorkSize[1], @@ -554,35 +544,33 @@ angle::Result CLCommandQueueCL::enqueueNDRangeKernel(const cl::Kernel &kernel, mNative, nativeKernel, ndrange.workDimensions, globalWorkOffset.data(), globalWorkSize.data(), localWorkSize.data(), numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueTask(const cl::Kernel &kernel, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const cl_kernel nativeKernel = kernel.getImpl().getNative(); const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueTask(mNative, nativeKernel, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueNativeKernel(cl::UserFunc userFunc, void *args, size_t cbArgs, const cl::BufferPtrs &buffers, - const std::vector bufferPtrOffsets, + const std::vector &bufferPtrOffsets, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::vector funcArgs; std::vector locs; @@ -622,42 +610,37 @@ angle::Result CLCommandQueueCL::enqueueNativeKernel(cl::UserFunc userFunc, const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueNativeKernel( mNative, userFunc, args, cbArgs, numBuffers, nativeBuffersPtr, locsPtr, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueMarkerWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueMarkerWithWaitList( mNative, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } -angle::Result CLCommandQueueCL::enqueueMarker(CLEventImpl::CreateFunc &eventCreateFunc) +angle::Result CLCommandQueueCL::enqueueMarker(cl::EventPtr &event) { cl_event nativeEvent = nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueMarker(mNative, &nativeEvent)); - eventCreateFunc = [nativeEvent](const cl::Event &event) { - return CLEventImpl::Ptr(new CLEventCL(event, nativeEvent)); - }; - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueWaitForEvents(const cl::EventPtrs &events) @@ -671,19 +654,18 @@ angle::Result CLCommandQueueCL::enqueueWaitForEvents(const cl::EventPtrs &events } angle::Result CLCommandQueueCL::enqueueBarrierWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { const std::vector nativeEvents = CLEventCL::Cast(waitEvents); const cl_uint numEvents = static_cast(nativeEvents.size()); const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); cl_event nativeEvent = nullptr; - cl_event *const nativeEventPtr = eventCreateFunc != nullptr ? &nativeEvent : nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; ANGLE_CL_TRY(mNative->getDispatch().clEnqueueBarrierWithWaitList( mNative, numEvents, nativeEventsPtr, nativeEventPtr)); - CheckCreateEvent(nativeEvent, eventCreateFunc); - return angle::Result::Continue; + return CreateEventBackend(nativeEvent, event); } angle::Result CLCommandQueueCL::enqueueBarrier() @@ -704,4 +686,70 @@ angle::Result CLCommandQueueCL::finish() return angle::Result::Continue; } +angle::Result CLCommandQueueCL::enqueueAcquireExternalMemObjectsKHR( + const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) +{ + std::vector nativeMemories; + nativeMemories.reserve(memObjects.size()); + for (const cl::MemoryPtr &memory : memObjects) + { + nativeMemories.emplace_back(memory->getImpl().getNative()); + } + const cl_uint numMemories = static_cast(nativeMemories.size()); + const std::vector nativeEvents = CLEventCL::Cast(waitEvents); + const cl_uint numEvents = static_cast(nativeEvents.size()); + const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); + cl_event nativeEvent = nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; + + clEnqueueAcquireExternalMemObjectsKHR_fn clEnqueueAcquireExternalMemObjectsKHR = + reinterpret_cast( + mNative->getDispatch().clGetExtensionFunctionAddress( + "clEnqueueAcquireExternalMemObjectsKHR")); + + if (clEnqueueAcquireExternalMemObjectsKHR != nullptr) + { + ANGLE_CL_TRY(clEnqueueAcquireExternalMemObjectsKHR(mNative, numMemories, + nativeMemories.data(), numEvents, + nativeEventsPtr, nativeEventPtr)); + ANGLE_TRY(CreateEventBackend(nativeEvent, event)); + } + return angle::Result::Continue; +} + +angle::Result CLCommandQueueCL::enqueueReleaseExternalMemObjectsKHR( + const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) +{ + std::vector nativeMemories; + nativeMemories.reserve(memObjects.size()); + for (const cl::MemoryPtr &memory : memObjects) + { + nativeMemories.emplace_back(memory->getImpl().getNative()); + } + const cl_uint numMemories = static_cast(nativeMemories.size()); + const std::vector nativeEvents = CLEventCL::Cast(waitEvents); + const cl_uint numEvents = static_cast(nativeEvents.size()); + const cl_event *const nativeEventsPtr = nativeEvents.empty() ? nullptr : nativeEvents.data(); + cl_event nativeEvent = nullptr; + cl_event *const nativeEventPtr = event != nullptr ? &nativeEvent : nullptr; + + clEnqueueReleaseExternalMemObjectsKHR_fn clEnqueueReleaseExternalMemObjectsKHR = + reinterpret_cast( + mNative->getDispatch().clGetExtensionFunctionAddress( + "clEnqueueReleaseExternalMemObjectsKHR")); + + if (clEnqueueReleaseExternalMemObjectsKHR != nullptr) + { + ANGLE_CL_TRY(clEnqueueReleaseExternalMemObjectsKHR(mNative, numMemories, + nativeMemories.data(), numEvents, + nativeEventsPtr, nativeEventPtr)); + ANGLE_TRY(CreateEventBackend(nativeEvent, event)); + } + return angle::Result::Continue; +} + } // namespace rx diff --git a/src/libANGLE/renderer/cl/CLCommandQueueCL.h b/src/libANGLE/renderer/cl/CLCommandQueueCL.h index fb296543b2d..7c593be522a 100644 --- a/src/libANGLE/renderer/cl/CLCommandQueueCL.h +++ b/src/libANGLE/renderer/cl/CLCommandQueueCL.h @@ -30,7 +30,7 @@ class CLCommandQueueCL : public CLCommandQueueImpl size_t size, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueWriteBuffer(const cl::Buffer &buffer, bool blocking, @@ -38,33 +38,33 @@ class CLCommandQueueCL : public CLCommandQueueImpl size_t size, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueReadBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueWriteBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyBuffer(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, @@ -72,19 +72,19 @@ class CLCommandQueueCL : public CLCommandQueueImpl size_t dstOffset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyBufferRect(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, size_t dstSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueFillBuffer(const cl::Buffer &buffer, const void *pattern, @@ -92,7 +92,7 @@ class CLCommandQueueCL : public CLCommandQueueImpl size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMapBuffer(const cl::Buffer &buffer, bool blocking, @@ -100,113 +100,121 @@ class CLCommandQueueCL : public CLCommandQueueImpl size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) override; angle::Result enqueueReadImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueWriteImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyImage(const cl::Image &srcImage, const cl::Image &dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueFillImage(const cl::Image &image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyImageToBuffer(const cl::Image &srcImage, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyBufferToImage(const cl::Buffer &srcBuffer, const cl::Image &dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMapImage(const cl::Image &image, bool blocking, cl::MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) override; angle::Result enqueueUnmapMemObject(const cl::Memory &memory, void *mappedPtr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMigrateMemObjects(const cl::MemoryPtrs &memObjects, cl::MemMigrationFlags flags, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueNDRangeKernel(const cl::Kernel &kernel, const cl::NDRange &ndrange, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueTask(const cl::Kernel &kernel, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueNativeKernel(cl::UserFunc userFunc, void *args, size_t cbArgs, const cl::BufferPtrs &buffers, - const std::vector bufferPtrOffsets, + const std::vector &bufferPtrOffsets, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMarkerWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; - angle::Result enqueueMarker(CLEventImpl::CreateFunc &eventCreateFunc) override; + angle::Result enqueueMarker(cl::EventPtr &event) override; angle::Result enqueueWaitForEvents(const cl::EventPtrs &events) override; angle::Result enqueueBarrierWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueBarrier() override; angle::Result flush() override; angle::Result finish() override; + angle::Result enqueueAcquireExternalMemObjectsKHR(const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) override; + + angle::Result enqueueReleaseExternalMemObjectsKHR(const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) override; + private: const cl_command_queue mNative; }; diff --git a/src/libANGLE/renderer/cl/CLContextCL.cpp b/src/libANGLE/renderer/cl/CLContextCL.cpp index 972f0c8bb09..f60d333d9a9 100644 --- a/src/libANGLE/renderer/cl/CLContextCL.cpp +++ b/src/libANGLE/renderer/cl/CLContextCL.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLContextCL.cpp: Implements the class methods for CLContextCL. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/cl/CLContextCL.h" diff --git a/src/libANGLE/renderer/cl/CLEventCL.cpp b/src/libANGLE/renderer/cl/CLEventCL.cpp index 4d99160b63d..3dcc1d58c11 100644 --- a/src/libANGLE/renderer/cl/CLEventCL.cpp +++ b/src/libANGLE/renderer/cl/CLEventCL.cpp @@ -24,11 +24,6 @@ CLEventCL::~CLEventCL() } } -angle::Result CLEventCL::onEventCreate() -{ - return angle::Result::Continue; -} - angle::Result CLEventCL::getCommandExecutionStatus(cl_int &executionStatus) { ANGLE_CL_TRY(mNative->getDispatch().clGetEventInfo(mNative, CL_EVENT_COMMAND_EXECUTION_STATUS, diff --git a/src/libANGLE/renderer/cl/CLEventCL.h b/src/libANGLE/renderer/cl/CLEventCL.h index 4f83385646d..a28505cca4c 100644 --- a/src/libANGLE/renderer/cl/CLEventCL.h +++ b/src/libANGLE/renderer/cl/CLEventCL.h @@ -23,8 +23,6 @@ class CLEventCL : public CLEventImpl cl_event getNative() const; - angle::Result onEventCreate() override; - angle::Result getCommandExecutionStatus(cl_int &executionStatus) override; angle::Result setUserEventStatus(cl_int executionStatus) override; diff --git a/src/libANGLE/renderer/cl/CLPlatformCL.cpp b/src/libANGLE/renderer/cl/CLPlatformCL.cpp index 528b2054f35..9e73a8ac9a9 100644 --- a/src/libANGLE/renderer/cl/CLPlatformCL.cpp +++ b/src/libANGLE/renderer/cl/CLPlatformCL.cpp @@ -16,9 +16,12 @@ #include "libANGLE/renderer/cl/CLDeviceCL.h" #include "libANGLE/renderer/cl/cl_util.h" +namespace OpenCLIcdLoader +{ extern "C" { #include "icd.h" } // extern "C" +} // namespace OpenCLIcdLoader namespace rx { @@ -430,7 +433,7 @@ void CLPlatformCL::Initialize(CreateFuncs &createFuncs, bool isIcd) // Using khrIcdInitialize() of the third party Khronos OpenCL ICD Loader to // enumerate the available OpenCL implementations on the system. They will be // stored in the singly linked list khrIcdVendors of the C struct KHRicdVendor. - khrIcdInitialize(); + OpenCLIcdLoader::khrIcdInitialize(); // The ICD loader will also enumerate ANGLE's OpenCL library if it is registered. Our // OpenCL entry points for the ICD enumeration are reentrant, but at this point of the @@ -439,7 +442,8 @@ void CLPlatformCL::Initialize(CreateFuncs &createFuncs, bool isIcd) // Iterating through the singly linked list khrIcdVendors to create // an ANGLE CL pass-through platform for each found ICD platform. - for (KHRicdVendor *vendorIt = khrIcdVendors; vendorIt != nullptr; vendorIt = vendorIt->next) + for (OpenCLIcdLoader::KHRicdVendor *vendorIt = OpenCLIcdLoader::khrIcdVendors; + vendorIt != nullptr; vendorIt = vendorIt->next) { cl_platform_id nativePlatform = vendorIt->platform; createFuncs.emplace_back([nativePlatform, isIcd](const cl::Platform &platform) { diff --git a/src/libANGLE/renderer/cl/cl_util.cpp b/src/libANGLE/renderer/cl/cl_util.cpp index 168d16d996e..66e0116ff5f 100644 --- a/src/libANGLE/renderer/cl/cl_util.cpp +++ b/src/libANGLE/renderer/cl/cl_util.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // cl_utils.cpp: Helper functions for the CL back end +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/cl/cl_util.h" diff --git a/src/libANGLE/renderer/cl/cl_util.h b/src/libANGLE/renderer/cl/cl_util.h index 37e58fb094f..eeaab13f152 100644 --- a/src/libANGLE/renderer/cl/cl_util.h +++ b/src/libANGLE/renderer/cl/cl_util.h @@ -47,7 +47,9 @@ inline const CLExtensionSet &GetSupportedCLExtensions() "cl_khr_fp64", "cl_khr_icd", "cl_khr_int64_base_atomics", - "cl_khr_int64_extended_atomics" + "cl_khr_int64_extended_atomics", + + "cl_arm_non_uniform_work_group_size" // clang-format on }); diff --git a/src/libANGLE/renderer/copyvertex.inc.h b/src/libANGLE/renderer/copyvertex.inc.h index 3478de1d04a..10a6d856930 100644 --- a/src/libANGLE/renderer/copyvertex.inc.h +++ b/src/libANGLE/renderer/copyvertex.inc.h @@ -6,6 +6,10 @@ // copyvertex.inc.h: Implementation of vertex buffer copying and conversion functions +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + namespace rx { diff --git a/src/libANGLE/renderer/d3d/BufferD3D.cpp b/src/libANGLE/renderer/d3d/BufferD3D.cpp index 464bd6d4a83..51c8022a574 100644 --- a/src/libANGLE/renderer/d3d/BufferD3D.cpp +++ b/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -6,6 +6,10 @@ // BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/BufferD3D.h" #include "common/mathutil.h" @@ -47,7 +51,9 @@ void BufferD3D::updateSerial() mSerial = mNextSerial++; } -void BufferD3D::updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage) +void BufferD3D::updateD3DBufferUsage(const gl::Context *context, + gl::BufferUsage usage, + BufferFeedback *feedback) { switch (usage) { @@ -59,7 +65,7 @@ void BufferD3D::updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage case gl::BufferUsage::StreamCopy: case gl::BufferUsage::StreamRead: mUsage = D3DBufferUsage::STATIC; - initializeStaticData(context); + initializeStaticData(context, feedback); break; case gl::BufferUsage::DynamicDraw: @@ -71,7 +77,7 @@ void BufferD3D::updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage } } -void BufferD3D::initializeStaticData(const gl::Context *context) +void BufferD3D::initializeStaticData(const gl::Context *context, BufferFeedback *feedback) { if (mStaticVertexBuffers.empty()) { @@ -140,7 +146,7 @@ StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAt return newStaticBuffer; } -void BufferD3D::invalidateStaticData(const gl::Context *context) +void BufferD3D::invalidateStaticData(const gl::Context *context, BufferFeedback *feedback) { emptyStaticBufferCache(); @@ -153,14 +159,16 @@ void BufferD3D::invalidateStaticData(const gl::Context *context) // buffers so that they are populated the next time we use this buffer. if (mUsage == D3DBufferUsage::STATIC) { - initializeStaticData(context); + initializeStaticData(context, feedback); } mUnmodifiedDataUse = 0; } // Creates static buffers if sufficient used data has been left unmodified -void BufferD3D::promoteStaticUsage(const gl::Context *context, size_t dataSize) +void BufferD3D::promoteStaticUsage(const gl::Context *context, + size_t dataSize, + BufferFeedback *feedback) { if (mUsage == D3DBufferUsage::DYNAMIC) { @@ -169,7 +177,7 @@ void BufferD3D::promoteStaticUsage(const gl::Context *context, size_t dataSize) if (mUnmodifiedDataUse > 3 * getSize()) { - updateD3DBufferUsage(context, gl::BufferUsage::StaticDraw); + updateD3DBufferUsage(context, gl::BufferUsage::StaticDraw, feedback); } } } diff --git a/src/libANGLE/renderer/d3d/BufferD3D.h b/src/libANGLE/renderer/d3d/BufferD3D.h index 19ea78c6ebb..79adcb33ebe 100644 --- a/src/libANGLE/renderer/d3d/BufferD3D.h +++ b/src/libANGLE/renderer/d3d/BufferD3D.h @@ -43,7 +43,8 @@ class BufferD3D : public BufferImpl virtual size_t getSize() const = 0; virtual bool supportsDirectBinding() const = 0; - virtual angle::Result markTransformFeedbackUsage(const gl::Context *context) = 0; + virtual angle::Result markTransformFeedbackUsage(const gl::Context *context, + BufferFeedback *feedback) = 0; virtual angle::Result getData(const gl::Context *context, const uint8_t **outData) = 0; // Warning: you should ensure binding really matches attrib.bindingIndex before using this @@ -52,10 +53,10 @@ class BufferD3D : public BufferImpl const gl::VertexBinding &binding); StaticIndexBufferInterface *getStaticIndexBuffer(); - virtual void initializeStaticData(const gl::Context *context); - virtual void invalidateStaticData(const gl::Context *context); + virtual void initializeStaticData(const gl::Context *context, BufferFeedback *feedback); + virtual void invalidateStaticData(const gl::Context *context, BufferFeedback *feedback); - void promoteStaticUsage(const gl::Context *context, size_t dataSize); + void promoteStaticUsage(const gl::Context *context, size_t dataSize, BufferFeedback *feedback); angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, @@ -69,7 +70,9 @@ class BufferD3D : public BufferImpl protected: void updateSerial(); - void updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage); + void updateD3DBufferUsage(const gl::Context *context, + gl::BufferUsage usage, + BufferFeedback *feedback); void emptyStaticBufferCache(); BufferFactoryD3D *mFactory; diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp index aafd3ad140d..689a3bfcee7 100644 --- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp +++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -29,10 +29,6 @@ namespace rx namespace { -// kShaderStorageDeclarationString must be the same as outputHLSL. -constexpr const char kShaderStorageDeclarationString[] = - "// @@ SHADER STORAGE DECLARATION STRING @@"; - const char *HLSLComponentTypeString(GLenum componentType) { switch (componentType) @@ -130,39 +126,6 @@ void WriteArrayString(std::ostringstream &strstr, unsigned int i) strstr << "]"; } -bool ReplaceShaderStorageDeclaration(const std::vector &shaderStorageBlocks, - std::string *hlsl, - size_t baseUAVRegister, - gl::ShaderType shaderType) -{ - std::string ssboHeader; - std::ostringstream out(ssboHeader); - for (const ShaderStorageBlock &ssbo : shaderStorageBlocks) - { - size_t uavRegister = baseUAVRegister + ssbo.registerIndex; - std::string name = ssbo.name; - if (ssbo.arraySize > 0) - { - for (unsigned int arrayIndex = 0; arrayIndex < ssbo.arraySize; arrayIndex++) - { - out << "RWByteAddressBuffer "; - out << "dx_" << name << "_" << arrayIndex << ": register(u"; - out << uavRegister + arrayIndex << ");\n"; - } - } - else - { - out << "RWByteAddressBuffer "; - out << "_" << name << ": register(u" << uavRegister << ");\n"; - } - } - if (out.str().empty()) - { - return true; - } - return angle::ReplaceSubstring(hlsl, kShaderStorageDeclarationString, out.str()); -} - constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; constexpr const char *VERTEX_OUTPUT_STUB_STRING = "@@ VERTEX OUTPUT @@"; constexpr const char *PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; @@ -183,7 +146,6 @@ std::string DynamicHLSL::GenerateVertexShaderForInputLayout( const std::string &sourceShader, const InputLayout &inputLayout, const std::vector &shaderAttributes, - const std::vector &shaderStorageBlocks, size_t baseUAVRegister) { std::ostringstream structStream; @@ -200,7 +162,12 @@ std::string DynamicHLSL::GenerateVertexShaderForInputLayout( const gl::ProgramInput &shaderAttribute = shaderAttributes[attributeIndex]; if (!shaderAttribute.name.empty()) { - ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); + // Built-in attributes do not count + if (!shaderAttribute.isBuiltIn()) + { + ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); + } + angle::FormatID vertexFormatID = inputIndex < inputLayout.size() ? inputLayout[inputIndex] : angle::FormatID::NONE; @@ -273,7 +240,10 @@ std::string DynamicHLSL::GenerateVertexShaderForInputLayout( initStream << ";\n"; - inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.getType())); + if (!shaderAttribute.isBuiltIn()) + { + inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.getType())); + } } } @@ -289,10 +259,6 @@ std::string DynamicHLSL::GenerateVertexShaderForInputLayout( angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str()); ASSERT(success); - success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &vertexHLSL, baseUAVRegister, - gl::ShaderType::Vertex); - ASSERT(success); - return vertexHLSL; } @@ -304,7 +270,6 @@ std::string DynamicHLSL::GeneratePixelShaderForOutputSignature( FragDepthUsage fragDepthUsage, bool usesSampleMask, const std::vector &outputLayout, - const std::vector &shaderStorageBlocks, size_t baseUAVRegister) { const int shaderModel = renderer->getMajorShaderModel(); @@ -400,10 +365,6 @@ std::string DynamicHLSL::GeneratePixelShaderForOutputSignature( angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str()); ASSERT(success); - success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &pixelHLSL, baseUAVRegister, - gl::ShaderType::Fragment); - ASSERT(success); - return pixelHLSL; } @@ -431,12 +392,22 @@ std::string DynamicHLSL::GenerateShaderForImage2DBindSignature( void DynamicHLSL::GenerateVaryingLinkHLSL(RendererD3D *renderer, const VaryingPacking &varyingPacking, const BuiltinInfo &builtins, + FragDepthUsage fragDepthUsage, bool programUsesPointSize, std::ostringstream &hlslStream) { ASSERT(builtins.dxPosition.enabled); hlslStream << "{\n"; - hlslStream << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; + hlslStream << " "; + if (fragDepthUsage == FragDepthUsage::Greater || fragDepthUsage == FragDepthUsage::Less) + { + // When conservative depth output is used and the pixel shader runs at pixel-frequency, + // input position must use centroid interpolation to avoid HLSL compilation errors. + // NOTE: Accuracy can be improved by using sample interpolation here, + // when a shader already runs at sample-frequency. + hlslStream << "centroid "; + } + hlslStream << "float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; if (builtins.glPosition.enabled) { @@ -580,8 +551,8 @@ void DynamicHLSL::GenerateShaderLinkHLSL( std::ostringstream vertexStream; vertexStream << "struct VS_OUTPUT\n"; const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex]; - GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(), - vertexStream); + GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, FragDepthUsage::Unused, + builtinsD3D.usesPointSize(), vertexStream); std::ostringstream vertexGenerateOutput; vertexGenerateOutput << "VS_OUTPUT generateOutput(VS_INPUT input)\n" @@ -805,7 +776,7 @@ void DynamicHLSL::GenerateShaderLinkHLSL( if (vertexShader) { - std::string vertexSource = vertexShader->translatedSource; + std::string vertexSource = *vertexShader->translatedSource; angle::ReplaceSubstring(&vertexSource, std::string(MAIN_PROLOGUE_STUB_STRING), " initAttributes(input);\n"); angle::ReplaceSubstring(&vertexSource, std::string(VERTEX_OUTPUT_STUB_STRING), @@ -817,7 +788,8 @@ void DynamicHLSL::GenerateShaderLinkHLSL( std::ostringstream pixelStream; pixelStream << "struct PS_INPUT\n"; - GenerateVaryingLinkHLSL(renderer, varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(), + GenerateVaryingLinkHLSL(renderer, varyingPacking, pixelBuiltins, + programMetadata.getFragDepthUsage(), builtinsD3D.usesPointSize(), pixelStream); pixelStream << "\n"; @@ -1106,7 +1078,7 @@ void DynamicHLSL::GenerateShaderLinkHLSL( if (fragmentShader) { - std::string pixelSource = fragmentShader->translatedSource; + std::string pixelSource = *fragmentShader->translatedSource; std::ostringstream pixelMainParametersStream; pixelMainParametersStream << "PS_INPUT input"; @@ -1152,12 +1124,12 @@ std::string DynamicHLSL::GenerateGeometryShaderPreamble(RendererD3D *renderer, const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex]; preambleStream << "struct GS_INPUT\n"; - GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(), - preambleStream); + GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, FragDepthUsage::Unused, + builtinsD3D.usesPointSize(), preambleStream); preambleStream << "\n" "struct GS_OUTPUT\n"; GenerateVaryingLinkHLSL(renderer, varyingPacking, builtinsD3D[gl::ShaderType::Geometry], - builtinsD3D.usesPointSize(), preambleStream); + FragDepthUsage::Unused, builtinsD3D.usesPointSize(), preambleStream); preambleStream << "\n" << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n" diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/libANGLE/renderer/d3d/DynamicHLSL.h index ee3e53b56b5..29c0fd5b069 100644 --- a/src/libANGLE/renderer/d3d/DynamicHLSL.h +++ b/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -38,7 +38,6 @@ namespace rx { class ProgramD3DMetadata; class ShaderD3D; -struct ShaderStorageBlock; // This class needs to match OutputHLSL::decorate class DecorateVariable final : angle::NonCopyable @@ -152,7 +151,6 @@ class DynamicHLSL : angle::NonCopyable const std::string &sourceShader, const gl::InputLayout &inputLayout, const std::vector &shaderAttributes, - const std::vector &shaderStorageBlocks, size_t baseUAVRegister); static std::string GeneratePixelShaderForOutputSignature( RendererD3D *renderer, @@ -161,7 +159,6 @@ class DynamicHLSL : angle::NonCopyable FragDepthUsage fragDepthUsage, bool usesSampleMask, const std::vector &outputLayout, - const std::vector &shaderStorageBlocks, size_t baseUAVRegister); static std::string GenerateShaderForImage2DBindSignature( ProgramExecutableD3D &executableD3D, @@ -207,6 +204,7 @@ class DynamicHLSL : angle::NonCopyable static void GenerateVaryingLinkHLSL(RendererD3D *renderer, const gl::VaryingPacking &varyingPacking, const BuiltinInfo &builtins, + FragDepthUsage fragDepthUsage, bool programUsesPointSize, std::ostringstream &hlslStream); diff --git a/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp index 5d1e86864df..83c5cb85189 100644 --- a/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp +++ b/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp @@ -350,28 +350,6 @@ std::string getImage2DGroupReturnType(Image2DHLSLGroup group, Image2DMethod meth } } -std::string getImageMetadata(Image2DHLSLGroup group) -{ - switch (group) - { - case IMAGE2D_R_FLOAT4: - case IMAGE2D_R_UNORM: - case IMAGE2D_R_SNORM: - case IMAGE2D_R_UINT4: - case IMAGE2D_R_INT4: - return "readonlyImageMetadata[imageIndex - readonlyImageIndexStart]"; - case IMAGE2D_W_FLOAT4: - case IMAGE2D_W_UNORM: - case IMAGE2D_W_SNORM: - case IMAGE2D_W_UINT4: - case IMAGE2D_W_INT4: - return "imageMetadata[imageIndex - imageIndexStart]"; - default: - UNREACHABLE(); - return "unknown image method"; - } -} - void OutputImage2DFunctionArgumentList(std::ostringstream &out, Image2DHLSLGroup group, Image2DMethod method) @@ -543,8 +521,7 @@ void OutputImage2DLoadFunction(std::ostringstream &out, if (texture3DCount == totalCount) { out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; - out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)];\n"; + out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, 0)];\n"; } else { @@ -567,8 +544,7 @@ void OutputImage2DLoadFunction(std::ostringstream &out, } out << " {\n"; out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; - out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)];\n"; + out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, 0)];\n"; out << " }\n"; } } @@ -578,16 +554,14 @@ void OutputImage2DLoadFunction(std::ostringstream &out, if (texture2DArrayCount == totalCount) { out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; - out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)];\n"; + out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, 0)];\n"; } else { out << " else\n"; out << " {\n"; out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; - out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)];\n"; + out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, 0)];\n"; out << " }\n"; } } @@ -634,8 +608,7 @@ void OutputImage2DStoreFunction(std::ostringstream &out, if (texture3DCount == totalCount) { out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; - out << " " << declarationStr << "3D[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)] = data;\n"; + out << " " << declarationStr << "3D[index][uint3(p.x, p.y, 0)] = data;\n"; } else { @@ -658,8 +631,7 @@ void OutputImage2DStoreFunction(std::ostringstream &out, } out << " {\n"; out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; - out << " " << declarationStr << "3D[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)] = data;\n"; + out << " " << declarationStr << "3D[index][uint3(p.x, p.y, 0)] = data;\n"; out << " }\n"; } } @@ -669,16 +641,14 @@ void OutputImage2DStoreFunction(std::ostringstream &out, if (texture2DArrayCount == totalCount) { out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; - out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)] = data;\n"; + out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, 0)] = data;\n"; } else { out << " else\n"; out << " {\n"; out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; - out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, " - << getImageMetadata(textureGroup) << ".layer)] = data;\n"; + out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, 0)] = data;\n"; out << " }\n"; } } diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp index f70dbfa782e..e7366aaa2a8 100644 --- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp +++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -8,6 +8,10 @@ #include "libANGLE/renderer/d3d/FramebufferD3D.h" +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/bitset_utils.h" #include "libANGLE/Context.h" #include "libANGLE/ErrorStrings.h" diff --git a/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/libANGLE/renderer/d3d/HLSLCompiler.cpp index 115786f9ae4..253b533e4e5 100644 --- a/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +++ b/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/HLSLCompiler.h" #include @@ -212,7 +216,7 @@ angle::Result HLSLCompiler::compileToBinary(d3d::Context *context, std::ostringstream stream; stream << "#line 2 \"" << sourcePath << "\"\n\n" << hlsl; std::string sourceText = stream.str(); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + writeFile(sourcePath.c_str(), sourceText.c_str()); #endif auto *platform = ANGLEPlatformCurrent(); @@ -242,7 +246,7 @@ angle::Result HLSLCompiler::compileToBinary(d3d::Context *context, SafeRelease(errorMessage); ANGLE_TRACE_EVENT1("gpu.angle", "D3DCompile::Error", "error", errorMessage); - infoLog.appendSanitized(message.c_str()); + infoLog.appendSanitized(message); // This produces unbelievable amounts of spam in about:gpu. // WARN() << std::endl << hlsl; diff --git a/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/src/libANGLE/renderer/d3d/IndexDataManager.cpp index dd8f45342f9..e4fe6c61a5f 100644 --- a/src/libANGLE/renderer/d3d/IndexDataManager.cpp +++ b/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -7,6 +7,10 @@ // IndexDataManager.cpp: Defines the IndexDataManager, a class that // runs the Buffer translation process for index buffers. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/IndexDataManager.h" #include "common/utilities.h" @@ -192,7 +196,9 @@ angle::Result IndexDataManager::prepareIndexData(const gl::Context *context, if (staticBufferInitialized && !staticBufferUsable) { - buffer->invalidateStaticData(context); + BufferFeedback feedback; + buffer->invalidateStaticData(context, &feedback); + glBuffer->applyImplFeedback(context, feedback); staticBuffer = nullptr; } @@ -204,7 +210,9 @@ angle::Result IndexDataManager::prepareIndexData(const gl::Context *context, ANGLE_TRY(streamIndexData(context, bufferData + offset, count, srcType, dstType, primitiveRestartFixedIndexEnabled, translated)); - buffer->promoteStaticUsage(context, count << srcTypeShift); + BufferFeedback feedback; + buffer->promoteStaticUsage(context, count << srcTypeShift, &feedback); + glBuffer->applyImplFeedback(context, feedback); } else { @@ -301,8 +309,9 @@ angle::Result GetIndexTranslationDestType(const gl::Context *context, gl::IndexRange indexRange; ANGLE_TRY(context->getState().getVertexArray()->getIndexRange( - context, indexType, indexCount, indices, &indexRange)); - if (indexRange.end == gl::GetPrimitiveRestartIndex(indexType)) + context, indexType, indexCount, indices, + context->getState().isPrimitiveRestartEnabled(), &indexRange)); + if (indexRange.end() == gl::GetPrimitiveRestartIndex(indexType)) { *destTypeOut = gl::DrawElementsType::UnsignedInt; return angle::Result::Continue; diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp index e462ca8e11d..bc259914363 100644 --- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp +++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -6,10 +6,15 @@ // ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/ProgramD3D.h" #include "common/MemoryBuffer.h" #include "common/bitset_utils.h" +#include "common/span_util.h" #include "common/string_utils.h" #include "common/utilities.h" #include "libANGLE/Context.h" @@ -200,7 +205,7 @@ bool ProgramD3DMetadata::usesBroadcast(const gl::Version &clientVersion) const { const SharedCompiledShaderStateD3D &shader = mAttachedShaders[gl::ShaderType::Fragment]; return shader && shader->usesFragColor && shader->usesMultipleRenderTargets && - clientVersion.major < 3; + clientVersion < gl::ES_3_0; } bool ProgramD3DMetadata::usesSecondaryColor() const @@ -395,24 +400,6 @@ class ProgramD3D::GetGeometryExecutableTask : public GetExecutableTask gl::ProvokingVertexConvention mProvokingVertex; }; -class ProgramD3D::GetComputeExecutableTask : public GetExecutableTask -{ - public: - GetComputeExecutableTask(ProgramD3D *program, const SharedCompiledShaderStateD3D &shader) - : GetExecutableTask(program, shader) - {} - ~GetComputeExecutableTask() override = default; - - void operator()() override - { - ANGLE_TRACE_EVENT0("gpu.angle", "GetComputeExecutableTask::run"); - - mExecutable->updateCachedImage2DBindLayoutFromShader(gl::ShaderType::Compute); - mResult = mExecutable->getComputeExecutableForImage2DBindLayout( - this, mProgram->mRenderer, &mShaderExecutable, &mInfoLog); - } -}; - class ProgramD3D::LinkLoadTaskD3D : public d3d::Context, public LinkTask { public: @@ -505,25 +492,15 @@ void ProgramD3D::LinkTaskD3D::link(const gl::ProgramLinkedResources &resources, return; } - // Create the subtasks - if (mExecutable->hasShaderStage(gl::ShaderType::Compute)) - { - linkSubTasksOut->push_back(std::make_shared( - mProgram, mProgram->getAttachedShader(gl::ShaderType::Compute))); - } - else - { - // Geometry shaders are currently only used internally, so there is no corresponding shader - // object at the interface level. For now the geometry shader debug info is prepended to the - // vertex shader. - linkSubTasksOut->push_back(std::make_shared( - mProgram, mProgram->getAttachedShader(gl::ShaderType::Vertex))); - linkSubTasksOut->push_back(std::make_shared( - mProgram, mProgram->getAttachedShader(gl::ShaderType::Fragment))); - linkSubTasksOut->push_back(std::make_shared( - mProgram, mProgram->getAttachedShader(gl::ShaderType::Vertex), mCaps, - mProvokingVertex)); - } + // Geometry shaders are currently only used internally, so there is no corresponding shader + // object at the interface level. For now the geometry shader debug info is prepended to the + // vertex shader. + linkSubTasksOut->push_back(std::make_shared( + mProgram, mProgram->getAttachedShader(gl::ShaderType::Vertex))); + linkSubTasksOut->push_back(std::make_shared( + mProgram, mProgram->getAttachedShader(gl::ShaderType::Fragment))); + linkSubTasksOut->push_back(std::make_shared( + mProgram, mProgram->getAttachedShader(gl::ShaderType::Vertex), mCaps, mProvokingVertex)); } class ProgramD3D::LoadTaskD3D final : public LinkLoadTaskD3D @@ -542,7 +519,7 @@ class ProgramD3D::LoadTaskD3D final : public LinkLoadTaskD3D ASSERT(linkSubTasksOut && linkSubTasksOut->empty()); ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty()); - gl::BinaryInputStream stream(mStreamData.data(), mStreamData.size()); + gl::BinaryInputStream stream(mStreamData); mResult = mExecutable->loadBinaryShaderExecutables(this, mProgram->mRenderer, &stream); return; @@ -585,14 +562,14 @@ angle::Result ProgramD3D::load(const gl::Context *context, // Copy the remaining data from the stream locally so that the client can't modify it when // loading off thread. angle::MemoryBuffer streamData; - const size_t dataSize = stream->remainingSize(); - if (!streamData.resize(dataSize)) + angle::Span remaining = stream->remainingSpan(); + if (!streamData.resize(remaining.size())) { mState.getExecutable().getInfoLog() << "Failed to copy program binary data to local buffer."; return angle::Result::Stop; } - memcpy(streamData.data(), stream->data() + stream->offset(), dataSize); + angle::SpanMemcpy(angle::Span(streamData), remaining); // Note: pretty much all the above can also be moved to the task *loadTaskOut = std::shared_ptr(new LoadTaskD3D(this, std::move(streamData))); @@ -649,36 +626,6 @@ angle::Result ProgramD3D::linkJobImpl(d3d::Context *context, { ProgramExecutableD3D *executableD3D = getExecutable(); - const gl::SharedCompiledShaderState &computeShader = - mState.getAttachedShader(gl::ShaderType::Compute); - if (computeShader) - { - const gl::SharedCompiledShaderState &shader = - mState.getAttachedShader(gl::ShaderType::Compute); - executableD3D->mShaderHLSL[gl::ShaderType::Compute] = shader->translatedSource; - - executableD3D->mShaderSamplers[gl::ShaderType::Compute].resize( - caps.maxShaderTextureImageUnits[gl::ShaderType::Compute]); - executableD3D->mImages[gl::ShaderType::Compute].resize(caps.maxImageUnits); - executableD3D->mReadonlyImages[gl::ShaderType::Compute].resize(caps.maxImageUnits); - - executableD3D->mShaderUniformsDirty.set(gl::ShaderType::Compute); - - linkResources(resources); - - for (const sh::ShaderVariable &uniform : computeShader->uniforms) - { - if (gl::IsImageType(uniform.type) && gl::IsImage2DType(uniform.type)) - { - executableD3D->mImage2DUniforms[gl::ShaderType::Compute].push_back(uniform); - } - } - - executableD3D->defineUniformsAndAssignRegisters(mRenderer, mState.getAttachedShaders()); - - return angle::Result::Continue; - } - for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes) { const gl::SharedCompiledShaderState &shader = mState.getAttachedShader(shaderType); @@ -794,7 +741,6 @@ void ProgramD3D::linkResources(const gl::ProgramLinkedResources &resources) ProgramExecutableD3D *executableD3D = getExecutable(); executableD3D->initializeUniformBlocks(); - executableD3D->initializeShaderStorageBlocks(mState.getAttachedShaders()); } } // namespace rx diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h index 9c9da91a6b3..4cc5b1d22b7 100644 --- a/src/libANGLE/renderer/d3d/ProgramD3D.h +++ b/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -102,7 +102,6 @@ class ProgramD3D : public ProgramImpl class GetVertexExecutableTask; class GetPixelExecutableTask; class GetGeometryExecutableTask; - class GetComputeExecutableTask; class LinkLoadTaskD3D; class LinkTaskD3D; class LoadTaskD3D; diff --git a/src/libANGLE/renderer/d3d/ProgramExecutableD3D.cpp b/src/libANGLE/renderer/d3d/ProgramExecutableD3D.cpp index 06723a9e144..5d545a61bfc 100644 --- a/src/libANGLE/renderer/d3d/ProgramExecutableD3D.cpp +++ b/src/libANGLE/renderer/d3d/ProgramExecutableD3D.cpp @@ -4,10 +4,16 @@ // found in the LICENSE file. // // ProgramExecutableD3D.cpp: Implementation of ProgramExecutableD3D. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h" #include "common/bitset_utils.h" +#include "common/span.h" #include "common/string_utils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" @@ -395,13 +401,6 @@ D3DPixelExecutable::~D3DPixelExecutable() SafeDelete(mShaderExecutable); } -D3DComputeExecutable::D3DComputeExecutable(const gl::ImageUnitTextureTypeMap &signature, - std::unique_ptr shaderExecutable) - : mSignature(signature), mShaderExecutable(std::move(shaderExecutable)) -{} - -D3DComputeExecutable::~D3DComputeExecutable() {} - D3DSampler::D3DSampler() : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D) {} @@ -417,7 +416,6 @@ ProgramExecutableD3D::ProgramExecutableD3D(const gl::ProgramExecutable *executab mDirtySamplerMapping(true), mUsedImageRange({}), mUsedReadonlyImageRange({}), - mUsedAtomicCounterRange({}), mSerial(issueSerial()) { reset(); @@ -431,7 +429,6 @@ void ProgramExecutableD3D::reset() { mVertexExecutables.clear(); mPixelExecutables.clear(); - mComputeExecutables.clear(); for (auto &geometryExecutable : mGeometryExecutables) { @@ -454,8 +451,6 @@ void ProgramExecutableD3D::reset() SafeDeleteContainer(mD3DUniforms); mD3DUniformBlocks.clear(); - mD3DShaderStorageBlocks.clear(); - mComputeAtomicCounterBufferRegisterIndices.fill({}); for (gl::ShaderType shaderType : gl::AllShaderTypes()) { @@ -466,7 +461,6 @@ void ProgramExecutableD3D::reset() } mUsedShaderSamplerRanges.fill({0, 0}); - mUsedAtomicCounterRange.fill({0, 0}); mDirtySamplerMapping = true; mUsedImageRange.fill({0, 0}); mUsedReadonlyImageRange.fill({0, 0}); @@ -492,8 +486,7 @@ bool ProgramExecutableD3D::load(const gl::Context *context, reset(); DeviceIdentifier binaryDeviceIdentifier = {}; - stream->readBytes(reinterpret_cast(&binaryDeviceIdentifier), - sizeof(DeviceIdentifier)); + stream->readBytes(angle::byte_span_from_ref(binaryDeviceIdentifier)); DeviceIdentifier identifier = renderer->getAdapterIdentifier(); if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0) @@ -532,8 +525,8 @@ bool ProgramExecutableD3D::load(const gl::Context *context, mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh); } - for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment}) { + const gl::ShaderType shaderType = gl::ShaderType::Fragment; size_t imageCount = stream->readInt(); for (size_t imageIndex = 0; imageIndex < imageCount; ++imageIndex) { @@ -560,34 +553,16 @@ bool ProgramExecutableD3D::load(const gl::Context *context, mUsedImageRange[shaderType] = gl::RangeUI(imageRangeLow, imageRangeHigh); mUsedReadonlyImageRange[shaderType] = gl::RangeUI(readonlyImageRangeLow, readonlyImageRangeHigh); - - unsigned int atomicCounterRangeLow, atomicCounterRangeHigh; - stream->readInt(&atomicCounterRangeLow); - stream->readInt(&atomicCounterRangeHigh); - mUsedAtomicCounterRange[shaderType] = - gl::RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh); } - size_t shaderStorageBlockCount = stream->readInt(); if (stream->error()) { infoLog << "Invalid program binary."; return false; } - ASSERT(mD3DShaderStorageBlocks.empty()); - for (size_t blockIndex = 0; blockIndex < shaderStorageBlockCount; ++blockIndex) - { - D3DInterfaceBlock shaderStorageBlock; - for (gl::ShaderType shaderType : gl::AllShaderTypes()) - { - stream->readInt(&shaderStorageBlock.mShaderRegisterIndexes[shaderType]); - } - mD3DShaderStorageBlocks.push_back(shaderStorageBlock); - } - - for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment}) { + const gl::ShaderType shaderType = gl::ShaderType::Fragment; size_t image2DUniformCount = stream->readInt(); if (stream->error()) { @@ -605,12 +580,6 @@ bool ProgramExecutableD3D::load(const gl::Context *context, } } - for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++ii) - { - unsigned int index = stream->readInt(); - mComputeAtomicCounterBufferRegisterIndices[ii] = index; - } - size_t uniformCount = stream->readInt(); if (stream->error()) { @@ -680,8 +649,7 @@ bool ProgramExecutableD3D::load(const gl::Context *context, for (gl::ShaderType shaderType : gl::AllShaderTypes()) { stream->readString(&mShaderHLSL[shaderType]); - stream->readBytes(reinterpret_cast(&mShaderWorkarounds[shaderType]), - sizeof(CompilerWorkaroundsD3D)); + stream->readBytes(angle::byte_span_from_ref(mShaderWorkarounds[shaderType])); } stream->readEnum(&mFragDepthUsage); @@ -713,9 +681,7 @@ angle::Result ProgramExecutableD3D::loadBinaryShaderExecutables(d3d::Context *co RendererD3D *renderer, gl::BinaryInputStream *stream) { - gl::InfoLog &infoLog = mExecutable->getInfoLog(); - const unsigned char *binary = reinterpret_cast(stream->data()); - + gl::InfoLog &infoLog = mExecutable->getInfoLog(); bool separateAttribs = mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS; size_t vertexShaderCount = stream->readInt(); @@ -730,8 +696,7 @@ angle::Result ProgramExecutableD3D::loadBinaryShaderExecutables(d3d::Context *co } size_t vertexShaderSize = stream->readInt(); - const unsigned char *vertexShaderFunction = binary + stream->offset(); - + const unsigned char *vertexShaderFunction = stream->remainingSpan().data(); ShaderExecutableD3D *shaderExecutable = nullptr; ANGLE_TRY(renderer->loadExecutable(contextD3D, vertexShaderFunction, vertexShaderSize, @@ -777,7 +742,7 @@ angle::Result ProgramExecutableD3D::loadBinaryShaderExecutables(d3d::Context *co } size_t pixelShaderSize = stream->readInt(); - const unsigned char *pixelShaderFunction = binary + stream->offset(); + const unsigned char *pixelShaderFunction = stream->remainingSpan().data(); ShaderExecutableD3D *shaderExecutable = nullptr; ANGLE_TRY(renderer->loadExecutable(contextD3D, pixelShaderFunction, pixelShaderSize, @@ -805,9 +770,8 @@ angle::Result ProgramExecutableD3D::loadBinaryShaderExecutables(d3d::Context *co continue; } - const unsigned char *geometryShaderFunction = binary + stream->offset(); - - ShaderExecutableD3D *geometryExecutable = nullptr; + const unsigned char *geometryShaderFunction = stream->remainingSpan().data(); + ShaderExecutableD3D *geometryExecutable = nullptr; ANGLE_TRY(renderer->loadExecutable(contextD3D, geometryShaderFunction, geometryShaderSize, gl::ShaderType::Geometry, mStreamOutVaryings, separateAttribs, &geometryExecutable)); @@ -823,45 +787,7 @@ angle::Result ProgramExecutableD3D::loadBinaryShaderExecutables(d3d::Context *co stream->skip(geometryShaderSize); } - size_t computeShaderCount = stream->readInt(); - for (size_t computeShaderIndex = 0; computeShaderIndex < computeShaderCount; - computeShaderIndex++) - { - size_t signatureCount = stream->readInt(); - gl::ImageUnitTextureTypeMap signatures; - for (size_t signatureIndex = 0; signatureIndex < signatureCount; signatureIndex++) - { - unsigned int imageUint; - gl::TextureType textureType; - stream->readInt(&imageUint); - stream->readEnum(&textureType); - signatures.insert(std::pair(imageUint, textureType)); - } - - size_t computeShaderSize = stream->readInt(); - const unsigned char *computeShaderFunction = binary + stream->offset(); - - ShaderExecutableD3D *computeExecutable = nullptr; - ANGLE_TRY(renderer->loadExecutable(contextD3D, computeShaderFunction, computeShaderSize, - gl::ShaderType::Compute, std::vector(), - false, &computeExecutable)); - - if (!computeExecutable) - { - infoLog << "Could not create compute shader."; - return angle::Result::Stop; - } - - // add new binary - mComputeExecutables.push_back( - std::unique_ptr(new D3DComputeExecutable( - signatures, std::unique_ptr(computeExecutable)))); - - stream->skip(computeShaderSize); - } - - for (const gl::ShaderType shaderType : - {gl::ShaderType::Vertex, gl::ShaderType::Fragment, gl::ShaderType::Compute}) + for (const gl::ShaderType shaderType : {gl::ShaderType::Vertex, gl::ShaderType::Fragment}) { size_t bindLayoutCount = stream->readInt(); for (size_t bindLayoutIndex = 0; bindLayoutIndex < bindLayoutCount; bindLayoutIndex++) @@ -886,8 +812,7 @@ void ProgramExecutableD3D::save(const gl::Context *context, // When we load the binary again later, we can validate the device identifier before trying to // compile any HLSL DeviceIdentifier binaryIdentifier = renderer->getAdapterIdentifier(); - stream->writeBytes(reinterpret_cast(&binaryIdentifier), - sizeof(DeviceIdentifier)); + stream->writeBytes(angle::byte_span_from_ref(binaryIdentifier)); stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); @@ -910,8 +835,8 @@ void ProgramExecutableD3D::save(const gl::Context *context, stream->writeInt(mUsedShaderSamplerRanges[shaderType].high()); } - for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment}) { + const gl::ShaderType shaderType = gl::ShaderType::Fragment; stream->writeInt(mImages[shaderType].size()); for (size_t imageIndex = 0; imageIndex < mImages[shaderType].size(); ++imageIndex) { @@ -930,21 +855,10 @@ void ProgramExecutableD3D::save(const gl::Context *context, stream->writeInt(mUsedImageRange[shaderType].high()); stream->writeInt(mUsedReadonlyImageRange[shaderType].low()); stream->writeInt(mUsedReadonlyImageRange[shaderType].high()); - stream->writeInt(mUsedAtomicCounterRange[shaderType].low()); - stream->writeInt(mUsedAtomicCounterRange[shaderType].high()); } - stream->writeInt(mD3DShaderStorageBlocks.size()); - for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks) - { - for (gl::ShaderType shaderType : gl::AllShaderTypes()) - { - stream->writeIntOrNegOne(shaderStorageBlock.mShaderRegisterIndexes[shaderType]); - } - } - - for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment}) { + const gl::ShaderType shaderType = gl::ShaderType::Fragment; stream->writeInt(mImage2DUniforms[shaderType].size()); for (const sh::ShaderVariable &image2DUniform : mImage2DUniforms[shaderType]) { @@ -952,11 +866,6 @@ void ProgramExecutableD3D::save(const gl::Context *context, } } - for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++ii) - { - stream->writeInt(mComputeAtomicCounterBufferRegisterIndices[ii]); - } - stream->writeInt(mD3DUniforms.size()); for (const D3DUniform *uniform : mD3DUniforms) { @@ -994,8 +903,7 @@ void ProgramExecutableD3D::save(const gl::Context *context, for (gl::ShaderType shaderType : gl::AllShaderTypes()) { stream->writeString(mShaderHLSL[shaderType]); - stream->writeBytes(reinterpret_cast(&mShaderWorkarounds[shaderType]), - sizeof(CompilerWorkaroundsD3D)); + stream->writeBytes(angle::byte_span_from_ref(mShaderWorkarounds[shaderType])); } stream->writeEnum(mFragDepthUsage); @@ -1039,7 +947,7 @@ void ProgramExecutableD3D::save(const gl::Context *context, stream->writeInt(vertexShaderSize); const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); - stream->writeBytes(vertexBlob, vertexShaderSize); + stream->writeBytes(angle::Span(vertexBlob, vertexShaderSize)); } stream->writeInt(mPixelExecutables.size()); @@ -1067,7 +975,7 @@ void ProgramExecutableD3D::save(const gl::Context *context, stream->writeInt(pixelShaderSize); const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); - stream->writeBytes(pixelBlob, pixelShaderSize); + stream->writeBytes(angle::Span(pixelBlob, pixelShaderSize)); } for (auto const &geometryExecutable : mGeometryExecutables) @@ -1080,32 +988,10 @@ void ProgramExecutableD3D::save(const gl::Context *context, size_t geometryShaderSize = geometryExecutable->getLength(); stream->writeInt(geometryShaderSize); - stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize); - } - - stream->writeInt(mComputeExecutables.size()); - for (size_t computeExecutableIndex = 0; computeExecutableIndex < mComputeExecutables.size(); - computeExecutableIndex++) - { - D3DComputeExecutable *computeExecutable = mComputeExecutables[computeExecutableIndex].get(); - - const gl::ImageUnitTextureTypeMap signatures = computeExecutable->signature(); - stream->writeInt(signatures.size()); - for (const auto &signature : signatures) - { - stream->writeInt(signature.first); - stream->writeEnum(signature.second); - } - - size_t computeShaderSize = computeExecutable->shaderExecutable()->getLength(); - stream->writeInt(computeShaderSize); - - const uint8_t *computeBlob = computeExecutable->shaderExecutable()->getFunction(); - stream->writeBytes(computeBlob, computeShaderSize); + stream->writeBytes(angle::Span(geometryExecutable->getFunction(), geometryShaderSize)); } - for (const gl::ShaderType shaderType : - {gl::ShaderType::Vertex, gl::ShaderType::Fragment, gl::ShaderType::Compute}) + for (const gl::ShaderType shaderType : {gl::ShaderType::Vertex, gl::ShaderType::Fragment}) { stream->writeInt(mImage2DBindLayoutCache[shaderType].size()); for (auto &image2DBindLayout : mImage2DBindLayoutCache[shaderType]) @@ -1139,11 +1025,6 @@ bool ProgramExecutableD3D::hasPixelExecutableForCachedOutputLayout() return mCachedPixelExecutableIndex.valid(); } -bool ProgramExecutableD3D::hasComputeExecutableForCachedImage2DBindLayout() -{ - return mCachedComputeExecutableIndex.valid(); -} - void ProgramExecutableD3D::dirtyAllUniforms() { mShaderUniformsDirty = mExecutable->getLinkedShaderStages(); @@ -1154,26 +1035,6 @@ void ProgramExecutableD3D::markUniformsClean() mShaderUniformsDirty.reset(); } -unsigned int ProgramExecutableD3D::getAtomicCounterBufferRegisterIndex( - GLuint binding, - gl::ShaderType shaderType) const -{ - if (shaderType != gl::ShaderType::Compute) - { - // Implement atomic counters for non-compute shaders - // http://anglebug.com/42260658 - UNIMPLEMENTED(); - } - return mComputeAtomicCounterBufferRegisterIndices[binding]; -} - -unsigned int ProgramExecutableD3D::getShaderStorageBufferRegisterIndex( - GLuint blockIndex, - gl::ShaderType shaderType) const -{ - return mD3DShaderStorageBlocks[blockIndex].mShaderRegisterIndexes[shaderType]; -} - const std::vector &ProgramExecutableD3D::getShaderUniformBufferCache( gl::ShaderType shaderType) const { @@ -1343,8 +1204,7 @@ angle::Result ProgramExecutableD3D::getVertexExecutableForCachedInputLayout( // Generate new dynamic layout with attribute conversions std::string vertexHLSL = DynamicHLSL::GenerateVertexShaderForInputLayout( renderer, mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, - mExecutable->getProgramInputs(), mShaderStorageBlocks[gl::ShaderType::Vertex], - mPixelShaderKey.size()); + mExecutable->getProgramInputs(), mPixelShaderKey.size()); std::string finalVertexHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature( *this, gl::ShaderType::Vertex, mAttachedShaders[gl::ShaderType::Vertex], vertexHLSL, mImage2DUniforms[gl::ShaderType::Vertex], mImage2DBindLayoutCache[gl::ShaderType::Vertex], @@ -1454,8 +1314,7 @@ angle::Result ProgramExecutableD3D::getPixelExecutableForCachedOutputLayout( std::string pixelHLSL = DynamicHLSL::GeneratePixelShaderForOutputSignature( renderer, mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mFragDepthUsage, - mUsesSampleMask, mPixelShaderOutputLayoutCache, - mShaderStorageBlocks[gl::ShaderType::Fragment], mPixelShaderKey.size()); + mUsesSampleMask, mPixelShaderOutputLayoutCache, mPixelShaderKey.size()); std::string finalPixelHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature( *this, gl::ShaderType::Fragment, mAttachedShaders[gl::ShaderType::Fragment], pixelHLSL, @@ -1491,53 +1350,6 @@ angle::Result ProgramExecutableD3D::getPixelExecutableForCachedOutputLayout( return angle::Result::Continue; } -angle::Result ProgramExecutableD3D::getComputeExecutableForImage2DBindLayout( - d3d::Context *context, - RendererD3D *renderer, - ShaderExecutableD3D **outExecutable, - gl::InfoLog *infoLog) -{ - ANGLE_TRACE_EVENT0("gpu.angle", - "ProgramExecutableD3D::getComputeExecutableForImage2DBindLayout"); - if (mCachedComputeExecutableIndex.valid()) - { - *outExecutable = - mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable(); - return angle::Result::Continue; - } - - std::string finalComputeHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature( - *this, gl::ShaderType::Compute, mAttachedShaders[gl::ShaderType::Compute], - mShaderHLSL[gl::ShaderType::Compute], mImage2DUniforms[gl::ShaderType::Compute], - mImage2DBindLayoutCache[gl::ShaderType::Compute], 0u); - - // Generate new compute executable - ShaderExecutableD3D *computeExecutable = nullptr; - - gl::InfoLog tempInfoLog; - gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; - - ANGLE_TRY(renderer->compileToExecutable(context, *currentInfoLog, finalComputeHLSL, - gl::ShaderType::Compute, std::vector(), - false, CompilerWorkaroundsD3D(), &computeExecutable)); - - if (computeExecutable) - { - mComputeExecutables.push_back(std::unique_ptr( - new D3DComputeExecutable(mImage2DBindLayoutCache[gl::ShaderType::Compute], - std::unique_ptr(computeExecutable)))); - mCachedComputeExecutableIndex = mComputeExecutables.size() - 1; - } - else if (!infoLog) - { - ERR() << "Error compiling dynamic compute executable:" << std::endl - << tempInfoLog.str() << std::endl; - } - *outExecutable = computeExecutable; - - return angle::Result::Continue; -} - bool ProgramExecutableD3D::hasNamedUniform(const std::string &name) { for (D3DUniform *d3dUniform : mD3DUniforms) @@ -1563,6 +1375,11 @@ void ProgramExecutableD3D::initAttribLocationsToD3DSemantic( int semanticIndex = 0; for (const sh::ShaderVariable &attribute : vertexShader->activeAttributes) { + if (attribute.isBuiltIn()) + { + continue; + } + int regCount = gl::VariableRegisterCount(attribute.type); GLuint location = mExecutable->getAttributeLocation(attribute.name); ASSERT(location != std::numeric_limits::max()); @@ -1619,62 +1436,6 @@ void ProgramExecutableD3D::initializeUniformBlocks() } } -void ProgramExecutableD3D::initializeShaderStorageBlocks( - const gl::ShaderMap &shaders) -{ - if (mExecutable->getShaderStorageBlocks().empty()) - { - return; - } - - ASSERT(mD3DShaderStorageBlocks.empty()); - - // Assign registers and update sizes. - for (const gl::InterfaceBlock &shaderStorageBlock : mExecutable->getShaderStorageBlocks()) - { - unsigned int shaderStorageBlockElement = - shaderStorageBlock.pod.isArray ? shaderStorageBlock.pod.arrayElement : 0; - D3DInterfaceBlock d3dShaderStorageBlock; - - for (gl::ShaderType shaderType : gl::AllShaderTypes()) - { - if (shaderStorageBlock.isActive(shaderType)) - { - ASSERT(mAttachedShaders[shaderType]); - unsigned int baseRegister = - mAttachedShaders[shaderType]->getShaderStorageBlockRegister( - shaderStorageBlock.name); - - d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] = - baseRegister + shaderStorageBlockElement; - } - } - mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock); - } - - for (gl::ShaderType shaderType : gl::AllShaderTypes()) - { - const gl::SharedCompiledShaderState &shader = shaders[shaderType]; - if (!shader) - { - continue; - } - for (const sh::InterfaceBlock &ssbo : shader->shaderStorageBlocks) - { - if (!ssbo.active) - { - continue; - } - ShaderStorageBlock block; - block.name = !ssbo.instanceName.empty() ? ssbo.instanceName : ssbo.name; - block.arraySize = ssbo.isArray() ? ssbo.arraySize : 0; - block.registerIndex = - mAttachedShaders[shaderType]->getShaderStorageBlockRegister(ssbo.name); - mShaderStorageBlocks[shaderType].push_back(block); - } - } -} - void ProgramExecutableD3D::initializeUniformStorage(RendererD3D *renderer, const gl::ShaderBitSet &availableShaderStages) { @@ -1750,9 +1511,6 @@ void ProgramExecutableD3D::updateCachedImage2DBindLayoutFromShader(gl::ShaderTyp &mImage2DBindLayoutCache[shaderType]); switch (shaderType) { - case gl::ShaderType::Compute: - updateCachedComputeExecutableIndex(); - break; case gl::ShaderType::Fragment: updateCachedPixelExecutableIndex(); break; @@ -1857,9 +1615,6 @@ void ProgramExecutableD3D::updateCachedImage2DBindLayout(const gl::Context *cont case gl::ShaderType::Fragment: updateCachedPixelExecutableIndex(); break; - case gl::ShaderType::Compute: - updateCachedComputeExecutableIndex(); - break; default: ASSERT(false); break; @@ -1893,21 +1648,6 @@ void ProgramExecutableD3D::updateCachedPixelExecutableIndex() } } -void ProgramExecutableD3D::updateCachedComputeExecutableIndex() -{ - mCachedComputeExecutableIndex.reset(); - for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size(); - executableIndex++) - { - if (mComputeExecutables[executableIndex]->matchesSignature( - mImage2DBindLayoutCache[gl::ShaderType::Compute])) - { - mCachedComputeExecutableIndex = executableIndex; - break; - } - } -} - void ProgramExecutableD3D::updateUniformBufferCache(const gl::Caps &caps) { if (mExecutable->getUniformBlocks().empty()) @@ -2014,17 +1754,13 @@ void ProgramExecutableD3D::defineUniformsAndAssignRegisters( } assignAllSamplerRegisters(shaders); - assignAllAtomicCounterRegisters(); // Samplers and readonly images share shader input resource slot, adjust low value of // readonly image range. - for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment}) { + const gl::ShaderType shaderType = gl::ShaderType::Fragment; mUsedReadonlyImageRange[shaderType] = gl::RangeUI(mUsedShaderSamplerRanges[shaderType].high(), mUsedShaderSamplerRanges[shaderType].high()); - // Atomic counter buffers and non-readonly images share input resource slots - mUsedImageRange[shaderType] = gl::RangeUI(mUsedAtomicCounterRange[shaderType].high(), - mUsedAtomicCounterRange[shaderType].high()); } assignAllImageRegisters(); initializeUniformStorage(renderer, attachedShaders); @@ -2071,14 +1807,6 @@ void ProgramExecutableD3D::defineUniformBase(gl::ShaderType shaderType, sh::TraverseShaderVariable(uniform, false, &visitor); return; } - else if (gl::IsAtomicCounterType(uniform.type)) - { - UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::UnorderedAccessView, - &stubEncoder, uniformMap); - sh::TraverseShaderVariable(uniform, false, &visitor); - mAtomicBindingMap[uniform.name] = uniform.binding; - return; - } const SharedCompiledShaderStateD3D &shaderD3D = mAttachedShaders[shaderType]; unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name); @@ -2173,81 +1901,10 @@ void ProgramExecutableD3D::assignAllImageRegisters() } } -void ProgramExecutableD3D::assignAllAtomicCounterRegisters() -{ - if (mAtomicBindingMap.empty()) - { - return; - } - const SharedCompiledShaderStateD3D &computeShader = mAttachedShaders[gl::ShaderType::Compute]; - if (computeShader) - { - auto ®isterIndices = mComputeAtomicCounterBufferRegisterIndices; - for (auto &atomicBinding : mAtomicBindingMap) - { - ASSERT(computeShader->hasUniform(atomicBinding.first)); - unsigned int currentRegister = computeShader->getUniformRegister(atomicBinding.first); - ASSERT(currentRegister != GL_INVALID_INDEX); - const int kBinding = atomicBinding.second; - - registerIndices[kBinding] = currentRegister; - - mUsedAtomicCounterRange[gl::ShaderType::Compute].extend(currentRegister); - } - } - else - { - // Implement atomic counters for non-compute shaders - // http://anglebug.com/42260658 - UNIMPLEMENTED(); - } -} - void ProgramExecutableD3D::assignImageRegisters(size_t uniformIndex) { - D3DUniform *d3dUniform = mD3DUniforms[uniformIndex]; - ASSERT(d3dUniform->isImage()); - // If the uniform is an array of arrays, then we have separate entries for each inner array in - // mD3DUniforms. However, the image register info is stored in the shader only for the - // outermost array. - std::vector subscripts; - const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts); - unsigned int registerOffset = mExecutable->getUniforms()[uniformIndex].pod.parentArrayIndex * - d3dUniform->getArraySizeProduct(); - - const SharedCompiledShaderStateD3D &computeShader = mAttachedShaders[gl::ShaderType::Compute]; - if (computeShader) - { - ASSERT(computeShader->hasUniform(baseName)); - d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] = - computeShader->getUniformRegister(baseName) + registerOffset; - ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX); - auto bindingIter = mImageBindingMap.find(baseName); - ASSERT(bindingIter != mImageBindingMap.end()); - if (d3dUniform->regType == HLSLRegisterType::Texture) - { - AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute], - bindingIter->second, d3dUniform->getArraySizeProduct(), - mReadonlyImages[gl::ShaderType::Compute], - &mUsedReadonlyImageRange[gl::ShaderType::Compute]); - } - else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView) - { - AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute], - bindingIter->second, d3dUniform->getArraySizeProduct(), - mImages[gl::ShaderType::Compute], - &mUsedImageRange[gl::ShaderType::Compute]); - } - else - { - UNREACHABLE(); - } - } - else - { - // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader. - UNIMPLEMENTED(); - } + // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader. + UNIMPLEMENTED(); } // static @@ -2610,9 +2267,9 @@ void ProgramExecutableD3D::setUniformMatrixfvInternal(GLint location, { if (targetUniform->mShaderData[shaderType]) { - SetFloatUniformMatrixHLSL::Run(arrayElementOffset, elementCount, countIn, - transpose, value, - targetUniform->mShaderData[shaderType]); + SetFloatUniformMatrixHLSL::Run( + arrayElementOffset, elementCount, countIn, transpose, value, + targetUniform->mShaderData[shaderType], false); mShaderUniformsDirty.set(shaderType); } } @@ -2630,7 +2287,7 @@ void ProgramExecutableD3D::getUniformInternal(GLint location, DestT *dataOut) co if (gl::IsMatrixType(uniform.getType())) { GetMatrixUniform(uniform.getType(), dataOut, reinterpret_cast(srcPointer), - true); + true, false); } else { diff --git a/src/libANGLE/renderer/d3d/ProgramExecutableD3D.h b/src/libANGLE/renderer/d3d/ProgramExecutableD3D.h index fe26ddf744c..ad9cf340fdc 100644 --- a/src/libANGLE/renderer/d3d/ProgramExecutableD3D.h +++ b/src/libANGLE/renderer/d3d/ProgramExecutableD3D.h @@ -101,13 +101,6 @@ struct D3DUniformBlock : D3DInterfaceBlock gl::ShaderMap mStructureByteStrides; }; -struct ShaderStorageBlock -{ - std::string name; - unsigned int arraySize = 0; - unsigned int registerIndex = 0; -}; - struct D3DUBOCache { unsigned int registerIndex; @@ -199,26 +192,6 @@ class D3DPixelExecutable ShaderExecutableD3D *mShaderExecutable; }; -class D3DComputeExecutable -{ - public: - D3DComputeExecutable(const gl::ImageUnitTextureTypeMap &signature, - std::unique_ptr shaderExecutable); - ~D3DComputeExecutable(); - - bool matchesSignature(const gl::ImageUnitTextureTypeMap &signature) const - { - return mSignature == signature; - } - - const gl::ImageUnitTextureTypeMap &signature() const { return mSignature; } - ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable.get(); } - - private: - gl::ImageUnitTextureTypeMap mSignature; - std::unique_ptr mShaderExecutable; -}; - struct D3DSampler { D3DSampler(); @@ -314,7 +287,6 @@ class ProgramExecutableD3D : public ProgramExecutableImpl const gl::State &state, gl::PrimitiveMode drawMode); bool hasPixelExecutableForCachedOutputLayout(); - bool hasComputeExecutableForCachedImage2DBindLayout(); bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); } bool areShaderUniformsDirty(gl::ShaderType shaderType) const @@ -340,10 +312,6 @@ class ProgramExecutableD3D : public ProgramExecutableImpl { return mAttribLocationToD3DSemantic; } - unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding, - gl::ShaderType shaderType) const; - unsigned int getShaderStorageBufferRegisterIndex(GLuint blockIndex, - gl::ShaderType shaderType) const; const std::vector &getShaderUniformBufferCache(gl::ShaderType shaderType) const; const std::vector &getShaderUniformBufferCacheUseSB( gl::ShaderType shaderType) const; @@ -385,10 +353,6 @@ class ProgramExecutableD3D : public ProgramExecutableImpl RendererD3D *renderer, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); - angle::Result getComputeExecutableForImage2DBindLayout(d3d::Context *context, - RendererD3D *renderer, - ShaderExecutableD3D **outExecutable, - gl::InfoLog *infoLog); bool hasShaderStage(gl::ShaderType shaderType) const { @@ -435,13 +399,11 @@ class ProgramExecutableD3D : public ProgramExecutableImpl void reset(); void initializeUniformBlocks(); - void initializeShaderStorageBlocks(const gl::ShaderMap &shaders); void initializeUniformStorage(RendererD3D *renderer, const gl::ShaderBitSet &availableShaderStages); void updateCachedVertexExecutableIndex(); void updateCachedPixelExecutableIndex(); - void updateCachedComputeExecutableIndex(); void defineUniformsAndAssignRegisters( RendererD3D *renderer, @@ -460,7 +422,6 @@ class ProgramExecutableD3D : public ProgramExecutableImpl gl::RangeUI *outUsedRange); void assignAllImageRegisters(); - void assignAllAtomicCounterRegisters(); void assignImageRegisters(size_t uniformIndex); static void AssignImages(unsigned int startImageIndex, int startLogicalImageUnit, @@ -482,7 +443,6 @@ class ProgramExecutableD3D : public ProgramExecutableImpl std::vector> mPixelExecutables; angle::PackedEnumMap> mGeometryExecutables; - std::vector> mComputeExecutables; gl::ShaderMap mShaderHLSL; gl::ShaderMap mShaderWorkarounds; @@ -512,7 +472,6 @@ class ProgramExecutableD3D : public ProgramExecutableImpl gl::ShaderMap> mReadonlyImages; gl::ShaderMap mUsedImageRange; gl::ShaderMap mUsedReadonlyImageRange; - gl::ShaderMap mUsedAtomicCounterRange; // Cache for pixel shader output layout to save reallocations. std::vector mPixelShaderOutputLayoutCache; @@ -529,16 +488,10 @@ class ProgramExecutableD3D : public ProgramExecutableImpl std::vector mStreamOutVaryings; std::vector mD3DUniforms; std::map mImageBindingMap; - std::map mAtomicBindingMap; std::vector mD3DUniformBlocks; - std::vector mD3DShaderStorageBlocks; - gl::ShaderMap> mShaderStorageBlocks; - std::array - mComputeAtomicCounterBufferRegisterIndices; gl::ShaderMap> mImage2DUniforms; gl::ShaderMap mImage2DBindLayoutCache; - Optional mCachedComputeExecutableIndex; gl::ShaderBitSet mShaderUniformsDirty; diff --git a/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp index 9026e97d2ca..6a714008ac4 100644 --- a/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp +++ b/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp @@ -69,7 +69,7 @@ angle::Result RenderbufferD3D::setStorageMultisample(const gl::Context *context, // been validated and generated GL_INVALID_VALUE. const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat); ANGLE_CHECK_GL_ALLOC(GetImplAs(context), - static_cast(samples) <= formatCaps.getMaxSamples()); + static_cast(samples) <= formatCaps.sampleCounts.getMaxSamples()); RenderTargetD3D *newRT = nullptr; ANGLE_TRY( diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/libANGLE/renderer/d3d/ShaderD3D.cpp index 6d17380f704..67d573d7775 100644 --- a/src/libANGLE/renderer/d3d/ShaderD3D.cpp +++ b/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -70,7 +70,7 @@ class ShaderTranslateTaskD3D final : public ShaderTranslateTask void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledState) override { - const std::string &translatedSource = compiledState.translatedSource; + const std::string &translatedSource = *compiledState.translatedSource; CompiledShaderStateD3D *state = mShader.get(); // Note: We shouldn't need to cache this. @@ -91,8 +91,6 @@ class ShaderTranslateTaskD3D final : public ShaderTranslateTask translatedSource.find("GL_USES_SAMPLE_MASK_IN") != std::string::npos; state->usesSampleMask = translatedSource.find("GL_USES_SAMPLE_MASK_OUT") != std::string::npos; - state->usesHelperInvocation = - translatedSource.find("GL_USES_HELPER_INVOCATION") != std::string::npos; state->usesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; state->usesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos; state->usesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; @@ -147,19 +145,6 @@ class ShaderTranslateTaskD3D final : public ShaderTranslateTask state->slowCompilingUniformBlockSet = GetSlowCompilingUniformBlockSet(sh::GetSlowCompilingUniformBlockSet(compiler)); - for (const sh::InterfaceBlock &interfaceBlock : compiledState.shaderStorageBlocks) - { - if (interfaceBlock.active) - { - unsigned int index = static_cast(-1); - bool blockRegisterResult = - sh::GetShaderStorageBlockRegister(compiler, interfaceBlock.name, &index); - ASSERT(blockRegisterResult); - - state->shaderStorageBlockRegisterMap[interfaceBlock.name] = index; - } - } - state->debugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n"; } @@ -178,7 +163,6 @@ CompiledShaderStateD3D::CompiledShaderStateD3D() usesSecondaryColor(false), usesFragCoord(false), usesFrontFacing(false), - usesHelperInvocation(false), usesPointSize(false), usesPointCoord(false), usesDepthRange(false), @@ -263,13 +247,6 @@ bool CompiledShaderStateD3D::shouldUniformBlockUseStructuredBuffer( return uniformBlockUseStructuredBufferMap.find(blockName)->second; } -unsigned int CompiledShaderStateD3D::getShaderStorageBlockRegister( - const std::string &blockName) const -{ - ASSERT(shaderStorageBlockRegisterMap.count(blockName) > 0); - return shaderStorageBlockRegisterMap.find(blockName)->second; -} - bool CompiledShaderStateD3D::useImage2DFunction(const std::string &functionName) const { if (usedImage2DFunctionNames.empty()) @@ -303,7 +280,7 @@ std::shared_ptr ShaderD3D::compile(const gl::Context *conte if (gl::DebugAnnotationsActive(context)) { sourcePath = angle::CreateTemporaryFile().value(); - writeFile(sourcePath.c_str(), source.c_str(), source.length()); + writeFile(sourcePath.c_str(), source); options->lineDirectives = true; options->sourcePath = true; } @@ -336,15 +313,11 @@ std::shared_ptr ShaderD3D::compile(const gl::Context *conte { options->skipD3DConstantRegisterZero = true; } - if (features.forceAtomicValueResolution.enabled) - { - options->forceAtomicValueResolution = true; - } if (features.allowTranslateUniformBlockToStructuredBuffer.enabled) { options->allowTranslateUniformBlockToStructuredBuffer = true; } - if (extensions.multiviewOVR || extensions.multiview2OVR) + if (extensions.multiviewOVR) { options->initializeBuiltinsForInstancedMultiview = true; } diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/libANGLE/renderer/d3d/ShaderD3D.h index 35cbcb192d8..c4bb1864a9e 100644 --- a/src/libANGLE/renderer/d3d/ShaderD3D.h +++ b/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -63,7 +63,6 @@ struct CompiledShaderStateD3D : angle::NonCopyable unsigned int getUniformBlockRegister(const std::string &blockName) const; bool shouldUniformBlockUseStructuredBuffer(const std::string &blockName) const; - unsigned int getShaderStorageBlockRegister(const std::string &blockName) const; bool useImage2DFunction(const std::string &functionName) const; const std::set &getSlowCompilingUniformBlockSet() const; void appendDebugInfo(const std::string &info) { debugInfo += info; } @@ -78,7 +77,6 @@ struct CompiledShaderStateD3D : angle::NonCopyable bool usesSecondaryColor; bool usesFragCoord; bool usesFrontFacing; - bool usesHelperInvocation; bool usesPointSize; bool usesPointCoord; bool usesDepthRange; @@ -101,7 +99,6 @@ struct CompiledShaderStateD3D : angle::NonCopyable std::map uniformBlockRegisterMap; std::map uniformBlockUseStructuredBufferMap; std::set slowCompilingUniformBlockSet; - std::map shaderStorageBlockRegisterMap; unsigned int readonlyImage2DRegisterIndex; unsigned int image2DRegisterIndex; std::set usedImage2DFunctionNames; diff --git a/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp index eab3becc915..ecb3e70a3df 100644 --- a/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp +++ b/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp @@ -7,6 +7,10 @@ // ShaderExecutable.cpp: Implements a class to contain D3D shader executable // implementation details. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" #include "common/angleutils.h" diff --git a/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index c557b767e67..8dcc225c10e 100644 --- a/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +++ b/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -312,8 +312,8 @@ egl::Error SurfaceD3D::swapRect(DisplayD3D *displayD3D, egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D) { RECT client; - int clientWidth = getWidth(); - int clientHeight = getHeight(); + int clientWidth = mWidth; + int clientHeight = mHeight; bool sizeDirty = false; if (!mFixedSize && !mNativeWindow->isIconic()) { @@ -329,13 +329,13 @@ egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D) // information. clientWidth = client.right - client.left; clientHeight = client.bottom - client.top; - sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + sizeDirty = clientWidth != mWidth || clientHeight != mHeight; } else if (mFixedSize) { clientWidth = mFixedWidth; clientHeight = mFixedHeight; - sizeDirty = mFixedWidth != getWidth() || mFixedHeight != getHeight(); + sizeDirty = mFixedWidth != mWidth || mFixedHeight != mHeight; } if (mSwapIntervalDirty) @@ -350,7 +350,7 @@ egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D) return egl::NoError(); } -egl::Error SurfaceD3D::swap(const gl::Context *context) +egl::Error SurfaceD3D::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { DisplayD3D *displayD3D = GetImplAs(context->getDisplay()); return swapRect(displayD3D, 0, 0, mWidth, mHeight); @@ -392,14 +392,9 @@ void SurfaceD3D::setFixedHeight(EGLint height) mFixedHeight = height; } -EGLint SurfaceD3D::getWidth() const +gl::Extents SurfaceD3D::getSize() const { - return mWidth; -} - -EGLint SurfaceD3D::getHeight() const -{ - return mHeight; + return gl::Extents(mWidth, mHeight, 1); } EGLint SurfaceD3D::isPostSubBufferSupported() const @@ -429,7 +424,7 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) return egl::NoError(); } -const angle::Format *SurfaceD3D::getD3DTextureColorFormat() const +const angle::Format *SurfaceD3D::getClientBufferTextureColorFormat() const { return mColorFormat; } diff --git a/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/libANGLE/renderer/d3d/SurfaceD3D.h index 6775fcdbaab..62d1224075a 100644 --- a/src/libANGLE/renderer/d3d/SurfaceD3D.h +++ b/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -31,7 +31,7 @@ class SurfaceD3D : public SurfaceImpl egl::Error initialize(const egl::Display *display) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -48,8 +48,7 @@ class SurfaceD3D : public SurfaceImpl void setFixedWidth(EGLint width) override; void setFixedHeight(EGLint height) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; @@ -70,7 +69,7 @@ class SurfaceD3D : public SurfaceImpl GLenum binding, const gl::ImageIndex &imageIndex) override; - const angle::Format *getD3DTextureColorFormat() const override; + const angle::Format *getClientBufferTextureColorFormat() const override; egl::Error attachToFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) override; diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp index 942c77eecac..527ac917325 100644 --- a/src/libANGLE/renderer/d3d/TextureD3D.cpp +++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -6,8 +6,14 @@ // TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/TextureD3D.h" +#include + #include "common/mathutil.h" #include "common/utilities.h" #include "libANGLE/Buffer.h" @@ -73,6 +79,30 @@ bool IsRenderTargetUsage(GLenum usage) { return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); } + +angle::Result SnapshotReadFramebufferToImage(const gl::Context *context, + RendererD3D *renderer, + gl::TextureType type, + GLenum sizedInternalFormat, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *sourceFBO, + std::unique_ptr *outImage) +{ + ASSERT(outImage != nullptr); + + ContextD3D *contextD3D = GetImplAs(context); + outImage->reset(renderer->createImage()); + ANGLE_CHECK_GL_ALLOC(contextD3D, outImage->get() != nullptr); + + const bool redefineResult = (*outImage)->redefine( + type, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1), true); + ANGLE_CHECK_GL_ALLOC(contextD3D, redefineResult); + + ANGLE_TRY( + (*outImage)->copyFromFramebuffer(context, gl::Offset(0, 0, 0), sourceArea, sourceFBO)); + return angle::Result::Continue; +} + } // namespace TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer) @@ -90,6 +120,51 @@ TextureD3D::~TextureD3D() ASSERT(!mTexStorage); } +angle::Result TextureD3D::handleCopyImageSelfCopyRedefine( + const gl::Context *context, + gl::TextureType snapshotType, + GLenum sizedInternalFormat, + const gl::Rectangle &sourceArea, + const gl::Extents &destExtents, + bool outside, + const gl::ImageIndex &destIndex, + gl::Framebuffer *source, + const std::function &redefineDest) +{ + gl::Extents fbSize = source->getReadColorAttachment()->getSize(); + gl::Rectangle clippedArea; + if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea)) + { + return angle::Result::Continue; + } + + const gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0); + + std::unique_ptr sourceCopy; + ANGLE_TRY(SnapshotReadFramebufferToImage(context, mRenderer, snapshotType, sizedInternalFormat, + clippedArea, source, &sourceCopy)); + + ANGLE_TRY(redefineDest(destExtents)); + + if (outside && (context->isWebGL() || context->isRobustResourceInitEnabled())) + { + ANGLE_TRY(initializeContents(context, GL_NONE, destIndex)); + } + + ImageD3D *destImage = nullptr; + ANGLE_TRY(getImageAndSyncFromStorage(context, destIndex, &destImage)); + + const gl::Box sourceBox(0, 0, 0, clippedArea.width, clippedArea.height, 1); + ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceCopy.get(), sourceBox, destOffset, + false, false, false)); + + mDirtyImages = true; + const gl::Box destRegion(destOffset.x, destOffset.y, 0, clippedArea.width, clippedArea.height, + 1); + ANGLE_TRY(commitRegion(context, destIndex, destRegion)); + return angle::Result::Continue; +} + angle::Result TextureD3D::getNativeTexture(const gl::Context *context, TextureStorage **outStorage) { // ensure the underlying texture is created @@ -713,9 +788,8 @@ angle::Result TextureD3D::setBaseLevel(const gl::Context *context, GLuint baseLe while (iterator.hasNext()) { const gl::ImageIndex index = iterator.next(); - const GLsizei samples = getRenderToTextureSamples(); RenderTargetD3D *renderTarget = nullptr; - ANGLE_TRY(mTexStorage->findRenderTarget(context, index, samples, &renderTarget)); + ANGLE_TRY(mTexStorage->findRenderTarget(context, index, &renderTarget)); if (renderTarget) { ANGLE_TRY(getImage(index)->copyFromTexStorage(context, index, mTexStorage)); @@ -850,7 +924,7 @@ angle::Result TextureD3D::initializeContents(const gl::Context *context, ANGLE_TRY(ensureRenderTarget(context)); ASSERT(mTexStorage); RenderTargetD3D *renderTarget = nullptr; - ANGLE_TRY(mTexStorage->getRenderTarget(context, index, 0, &renderTarget)); + ANGLE_TRY(mTexStorage->getRenderTarget(context, index, &renderTarget)); ANGLE_TRY(mRenderer->initRenderTarget(context, renderTarget)); // Force image clean again, the texture storage may have been re-created and the image used. @@ -903,15 +977,6 @@ angle::Result TextureD3D::initializeContents(const gl::Context *context, return angle::Result::Continue; } -GLsizei TextureD3D::getRenderToTextureSamples() -{ - if (mTexStorage) - { - return mTexStorage->getRenderToTextureSamples(); - } - return 0; -} - void TextureD3D::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) { onStateChange(message); @@ -1021,14 +1086,13 @@ angle::Result TextureD3D_2D::setImage(const gl::Context *context, // Attempt a fast gpu copy of the pixel data to the surface if (mTexStorage) { - ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex())); } if (isFastUnpackable(unpackBuffer, unpack, internalFormatInfo.sizedInternalFormat) && isLevelComplete(index.getLevelIndex())) { // Will try to create RT storage if it does not exist RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget)); + ANGLE_TRY(getRenderTarget(context, index, 0, &destRenderTarget)); gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()), 1); @@ -1064,12 +1128,11 @@ angle::Result TextureD3D_2D::setSubImage(const gl::Context *context, GLenum mipFormat = getInternalFormat(index.getLevelIndex()); if (mTexStorage) { - ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex())); } if (isFastUnpackable(unpackBuffer, unpack, mipFormat) && isLevelComplete(index.getLevelIndex())) { RenderTargetD3D *renderTarget = nullptr; - ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &renderTarget)); + ANGLE_TRY(getRenderTarget(context, index, 0, &renderTarget)); ASSERT(!mImageArray[index.getLevelIndex()]->isDirty()); return fastUnpackPixels(context, unpack, unpackBuffer, pixels, area, mipFormat, type, @@ -1124,8 +1187,6 @@ angle::Result TextureD3D_2D::copyImage(const gl::Context *context, const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE); gl::Extents sourceExtents(sourceArea.width, sourceArea.height, 1); - ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat, - sourceExtents, false)); gl::Extents fbSize = source->getReadColorAttachment()->getSize(); @@ -1134,6 +1195,26 @@ angle::Result TextureD3D_2D::copyImage(const gl::Context *context, sourceArea.x + sourceArea.width > fbSize.width || sourceArea.y + sourceArea.height > fbSize.height; + const gl::FramebufferAttachment *readAttachment = source->getReadColorAttachment(); + const bool isSelfCopy = readAttachment && readAttachment->type() == GL_TEXTURE && + GetImplAs(readAttachment->getTexture()) == this && + readAttachment->mipLevel() == index.getLevelIndex(); + + // If redefining the destination would invalidate the source attachment, snapshot the source + // first. + if (isSelfCopy) + { + return handleCopyImageSelfCopyRedefine( + context, gl::TextureType::_2D, internalFormatInfo.sizedInternalFormat, sourceArea, + sourceExtents, outside, index, source, [&](const gl::Extents &extents) { + return redefineImage(context, index.getLevelIndex(), + internalFormatInfo.sizedInternalFormat, extents, false); + }); + } + + ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat, + sourceExtents, false)); + // WebGL requires that pixels that would be outside the framebuffer are treated as zero values, // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside. // Same thing for robust resource init. @@ -1396,8 +1477,7 @@ angle::Result TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surfa { GLenum internalformat = surface->getConfig()->renderTargetFormat; - gl::Extents size(surface->getWidth(), surface->getHeight(), 1); - ANGLE_TRY(redefineImage(context, 0, internalformat, size, true)); + ANGLE_TRY(redefineImage(context, 0, internalformat, surface->getSize(), true)); ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask())); @@ -1490,7 +1570,7 @@ angle::Result TextureD3D_2D::getRenderTarget(const gl::Context *context, ANGLE_TRY(ensureRenderTarget(context)); ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex())); - return mTexStorage->getRenderTarget(context, index, samples, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } bool TextureD3D_2D::isValidLevel(int level) const @@ -1894,8 +1974,6 @@ angle::Result TextureD3D_Cube::copyImage(const gl::Context *context, gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE); gl::Extents size(sourceArea.width, sourceArea.height, 1); - ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(), - internalFormatInfo.sizedInternalFormat, size, false)); gl::Extents fbSize = source->getReadColorAttachment()->getSize(); @@ -1904,6 +1982,25 @@ angle::Result TextureD3D_Cube::copyImage(const gl::Context *context, sourceArea.x + sourceArea.width > fbSize.width || sourceArea.y + sourceArea.height > fbSize.height; + const gl::FramebufferAttachment *readAttachment = source->getReadColorAttachment(); + const bool isSelfCopy = readAttachment && readAttachment->type() == GL_TEXTURE && + GetImplAs(readAttachment->getTexture()) == this && + readAttachment->mipLevel() == index.getLevelIndex() && + readAttachment->cubeMapFace() == index.getTarget(); + + if (isSelfCopy) + { + return handleCopyImageSelfCopyRedefine( + context, gl::TextureType::CubeMap, internalFormatInfo.sizedInternalFormat, sourceArea, + size, outside, index, source, [&](const gl::Extents &extents) { + return redefineImage(context, faceIndex, index.getLevelIndex(), + internalFormatInfo.sizedInternalFormat, extents, false); + }); + } + + ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(), + internalFormatInfo.sizedInternalFormat, size, false)); + // WebGL requires that pixels that would be outside the framebuffer are treated as zero values, // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside. // Same thing for robust resource init. @@ -2221,7 +2318,7 @@ angle::Result TextureD3D_Cube::getRenderTarget(const gl::Context *context, ANGLE_TRY(ensureRenderTarget(context)); ANGLE_TRY(updateStorageFaceLevel(context, index.cubeMapFaceIndex(), index.getLevelIndex())); - return mTexStorage->getRenderTarget(context, index, samples, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } angle::Result TextureD3D_Cube::initializeStorage(const gl::Context *context, BindFlags bindFlags) @@ -2594,7 +2691,7 @@ angle::Result TextureD3D_3D::setImage(const gl::Context *context, { // Will try to create RT storage if it does not exist RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget)); + ANGLE_TRY(getRenderTarget(context, index, 0, &destRenderTarget)); gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()), getDepth(index.getLevelIndex())); @@ -2632,7 +2729,7 @@ angle::Result TextureD3D_3D::setSubImage(const gl::Context *context, if (isFastUnpackable(unpackBuffer, unpack, mipFormat) && isLevelComplete(index.getLevelIndex())) { RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget)); + ANGLE_TRY(getRenderTarget(context, index, 0, &destRenderTarget)); ASSERT(!mImageArray[index.getLevelIndex()]->isDirty()); return fastUnpackPixels(context, unpack, unpackBuffer, pixels, area, mipFormat, type, @@ -2927,7 +3024,7 @@ angle::Result TextureD3D_3D::getRenderTarget(const gl::Context *context, ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex())); } - return mTexStorage->getRenderTarget(context, index, samples, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } angle::Result TextureD3D_3D::initializeStorage(const gl::Context *context, BindFlags bindFlags) @@ -3668,7 +3765,7 @@ angle::Result TextureD3D_2DArray::getRenderTarget(const gl::Context *context, // ensure the underlying texture is created ANGLE_TRY(ensureRenderTarget(context)); ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex())); - return mTexStorage->getRenderTarget(context, index, samples, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } angle::Result TextureD3D_2DArray::initializeStorage(const gl::Context *context, BindFlags bindFlags) @@ -4233,7 +4330,7 @@ angle::Result TextureD3D_2DMultisample::getRenderTarget(const gl::Context *conte // ensure the underlying texture is created ANGLE_TRY(ensureRenderTarget(context)); - return mTexStorage->getRenderTarget(context, index, samples, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } gl::ImageIndexIterator TextureD3D_2DMultisample::imageIterator() const @@ -4351,7 +4448,7 @@ angle::Result TextureD3D_2DMultisampleArray::getRenderTarget(const gl::Context * // ensure the underlying texture is created ANGLE_TRY(ensureRenderTarget(context)); - return mTexStorage->getRenderTarget(context, index, samples, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } gl::ImageIndexIterator TextureD3D_2DMultisampleArray::imageIterator() const diff --git a/src/libANGLE/renderer/d3d/TextureD3D.h b/src/libANGLE/renderer/d3d/TextureD3D.h index f5b8f61f233..8e89c3e022a 100644 --- a/src/libANGLE/renderer/d3d/TextureD3D.h +++ b/src/libANGLE/renderer/d3d/TextureD3D.h @@ -9,6 +9,8 @@ #ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ #define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ +#include + #include "common/Color.h" #include "libANGLE/Constants.h" #include "libANGLE/Stream.h" @@ -120,8 +122,6 @@ class TextureD3D : public TextureImpl, public angle::ObserverInterface GLenum binding, const gl::ImageIndex &imageIndex) override; - GLsizei getRenderToTextureSamples(); - angle::Result ensureUnorderedAccess(const gl::Context *context); angle::Result onLabelUpdate(const gl::Context *context) override; @@ -191,6 +191,17 @@ class TextureD3D : public TextureImpl, public angle::ObserverInterface const gl::ImageIndex &index, const gl::Box ®ion); + angle::Result handleCopyImageSelfCopyRedefine( + const gl::Context *context, + gl::TextureType snapshotType, + GLenum sizedInternalFormat, + const gl::Rectangle &sourceArea, + const gl::Extents &destExtents, + bool outside, + const gl::ImageIndex &destIndex, + gl::Framebuffer *source, + const std::function &redefineDest); + angle::Result releaseTexStorage(const gl::Context *context, const gl::TexLevelMask ©StorageToImagesMask); diff --git a/src/libANGLE/renderer/d3d/TextureStorage.h b/src/libANGLE/renderer/d3d/TextureStorage.h index 9940a3c88d6..75ba9bb498b 100644 --- a/src/libANGLE/renderer/d3d/TextureStorage.h +++ b/src/libANGLE/renderer/d3d/TextureStorage.h @@ -56,11 +56,9 @@ class TextureStorage : public angle::Subject virtual angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const = 0; virtual angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) = 0; virtual angle::Result generateMipmap(const gl::Context *context, const gl::ImageIndex &sourceIndex, @@ -83,11 +81,6 @@ class TextureStorage : public angle::Subject virtual void invalidateTextures() {} - // RenderToTexture methods - virtual angle::Result releaseMultisampledTexStorageForLevel(size_t level); - virtual angle::Result resolveTexture(const gl::Context *context); - virtual GLsizei getRenderToTextureSamples() const; - // Called by outer object when label has changed via KHR_debug extension void setLabel(const std::string &newLabel); @@ -109,21 +102,6 @@ inline angle::Result TextureStorage::useLevelZeroWorkaroundTexture(const gl::Con return angle::Result::Continue; } -inline angle::Result TextureStorage::releaseMultisampledTexStorageForLevel(size_t level) -{ - return angle::Result::Continue; -} - -inline angle::Result TextureStorage::resolveTexture(const gl::Context *context) -{ - return angle::Result::Continue; -} - -inline GLsizei TextureStorage::getRenderToTextureSamples() const -{ - return 0; -} - inline void TextureStorage::setLabel(const std::string &newLabel) { mKHRDebugLabel = newLabel; diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp index 558db8cdbdd..22cbae26e79 100644 --- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp +++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -4,9 +4,13 @@ // found in the LICENSE file. // -// VertexDataManager.h: Defines the VertexDataManager, a class that +// VertexDataManager.cpp: Defines the VertexDataManager, a class that // runs the Buffer translation process. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/VertexDataManager.h" #include "common/bitset_utils.h" @@ -72,7 +76,8 @@ int ElementsInBuffer(const gl::VertexAttribute &attrib, // Warning: you should ensure binding really matches attrib.bindingIndex before using this function. bool DirectStoragePossible(const gl::Context *context, const gl::VertexAttribute &attrib, - const gl::VertexBinding &binding) + const gl::VertexBinding &binding, + const gl::Buffer *buffer) { // Current value attribs may not use direct storage. if (!attrib.enabled) @@ -80,7 +85,6 @@ bool DirectStoragePossible(const gl::Context *context, return false; } - gl::Buffer *buffer = binding.getBuffer().get(); if (!buffer) { return false; @@ -128,6 +132,7 @@ TranslatedAttribute::TranslatedAttribute() : active(false), attribute(nullptr), binding(nullptr), + bufferBindingPointer(nullptr), currentValueType(gl::VertexAttribType::InvalidEnum), baseOffset(0), usesFirstVertexOffset(false), @@ -162,7 +167,8 @@ angle::Result TranslatedAttribute::computeOffset(const gl::Context *context, // Warning: you should ensure binding really matches attrib.bindingIndex before using this function. VertexStorageType ClassifyAttributeStorage(const gl::Context *context, const gl::VertexAttribute &attrib, - const gl::VertexBinding &binding) + const gl::VertexBinding &binding, + const gl::Buffer *buffer) { // If attribute is disabled, we use the current value. if (!attrib.enabled) @@ -171,14 +177,13 @@ VertexStorageType ClassifyAttributeStorage(const gl::Context *context, } // If specified with immediate data, we must use dynamic storage. - gl::Buffer *buffer = binding.getBuffer().get(); if (!buffer) { return VertexStorageType::DYNAMIC; } // Check if the buffer supports direct storage. - if (DirectStoragePossible(context, attrib, binding)) + if (DirectStoragePossible(context, attrib, binding, buffer)) { return VertexStorageType::DIRECT; } @@ -276,10 +281,13 @@ angle::Result VertexDataManager::prepareVertexData( translated->active = true; translated->attribute = &attrib; translated->binding = &binding; + translated->bufferBindingPointer = + &vertexArray->getBufferBindingPointers()[attrib.bindingIndex]; translated->currentValueType = currentValueData.Type; translated->divisor = binding.getDivisor(); - switch (ClassifyAttributeStorage(context, attrib, binding)) + switch (ClassifyAttributeStorage(context, attrib, binding, + vertexArray->getVertexArrayBuffer(attrib.bindingIndex))) { case VertexStorageType::STATIC: { @@ -328,11 +336,12 @@ void VertexDataManager::StoreDirectAttrib(const gl::Context *context, const auto &attrib = *directAttrib->attribute; const auto &binding = *directAttrib->binding; - gl::Buffer *buffer = binding.getBuffer().get(); + ASSERT(directAttrib->bufferBindingPointer); + gl::Buffer *buffer = directAttrib->bufferBindingPointer->get(); ASSERT(buffer); BufferD3D *bufferD3D = GetImplAs(buffer); - ASSERT(DirectStoragePossible(context, attrib, binding)); + ASSERT(DirectStoragePossible(context, attrib, binding, buffer)); directAttrib->vertexBuffer.set(nullptr); directAttrib->storage = bufferD3D; directAttrib->serial = bufferD3D->getSerial(); @@ -352,8 +361,9 @@ angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context, const auto &attrib = *translated->attribute; const auto &binding = *translated->binding; - gl::Buffer *buffer = binding.getBuffer().get(); - ASSERT(buffer && attrib.enabled && !DirectStoragePossible(context, attrib, binding)); + ASSERT(translated->bufferBindingPointer); + gl::Buffer *buffer = translated->bufferBindingPointer->get(); + ASSERT(buffer && attrib.enabled && !DirectStoragePossible(context, attrib, binding, buffer)); BufferD3D *bufferD3D = GetImplAs(buffer); // Compute source data pointer @@ -468,15 +478,16 @@ void VertexDataManager::PromoteDynamicAttribs( { const auto &dynamicAttrib = translatedAttribs[attribIndex]; ASSERT(dynamicAttrib.attribute && dynamicAttrib.binding); - const auto &binding = *dynamicAttrib.binding; - - gl::Buffer *buffer = binding.getBuffer().get(); + ASSERT(dynamicAttrib.bufferBindingPointer); + gl::Buffer *buffer = dynamicAttrib.bufferBindingPointer->get(); if (buffer) { // Note: this multiplication can overflow. It should not be a security problem. BufferD3D *bufferD3D = GetImplAs(buffer); size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute); - bufferD3D->promoteStaticUsage(context, count * typeSize); + BufferFeedback feedback; + bufferD3D->promoteStaticUsage(context, count * typeSize, &feedback); + buffer->applyImplFeedback(context, feedback); } } } @@ -491,10 +502,11 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex ASSERT(translatedAttrib.attribute && translatedAttrib.binding); const auto &attrib = *translatedAttrib.attribute; const auto &binding = *translatedAttrib.binding; + ASSERT(translatedAttrib.bufferBindingPointer); + gl::Buffer *buffer = translatedAttrib.bufferBindingPointer->get(); - ASSERT(!DirectStoragePossible(context, attrib, binding)); + ASSERT(!buffer || !DirectStoragePossible(context, attrib, binding, buffer)); - gl::Buffer *buffer = binding.getBuffer().get(); BufferD3D *bufferD3D = buffer ? GetImplAs(buffer) : nullptr; ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib, binding) == nullptr); @@ -536,8 +548,8 @@ angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context, ASSERT(translated->attribute && translated->binding); const auto &attrib = *translated->attribute; const auto &binding = *translated->binding; - - gl::Buffer *buffer = binding.getBuffer().get(); + ASSERT(translated->bufferBindingPointer); + gl::Buffer *buffer = translated->bufferBindingPointer->get(); ASSERT(buffer || attrib.pointer); ASSERT(attrib.enabled); diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.h b/src/libANGLE/renderer/d3d/VertexDataManager.h index 50400db0279..5b797720165 100644 --- a/src/libANGLE/renderer/d3d/VertexDataManager.h +++ b/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -61,6 +61,7 @@ struct TranslatedAttribute const gl::VertexAttribute *attribute; const gl::VertexBinding *binding; + const gl::BindingPointer *bufferBindingPointer; gl::VertexAttribType currentValueType; unsigned int baseOffset; bool usesFirstVertexOffset; @@ -84,7 +85,8 @@ enum class VertexStorageType // Given a vertex attribute, return the type of storage it will use. VertexStorageType ClassifyAttributeStorage(const gl::Context *context, const gl::VertexAttribute &attrib, - const gl::VertexBinding &binding); + const gl::VertexBinding &binding, + const gl::Buffer *buffer); class VertexDataManager : angle::NonCopyable { diff --git a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp index af6e83e7ee0..98bf6b2931c 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -6,6 +6,10 @@ // Blit11.cpp: Texture copy utility class. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/Blit11.h" #include diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index 2f568fea649..64c9a431e6f 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -4,7 +4,11 @@ // found in the LICENSE file. // -// Buffer11.cpp Defines the Buffer11 class. +// Buffer11.cpp: Defines the Buffer11 class. + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" @@ -26,7 +30,6 @@ namespace rx namespace { - template GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index) { @@ -124,8 +127,12 @@ class Buffer11::BufferStorage : angle::NonCopyable size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) = 0; - virtual angle::Result resize(const gl::Context *context, size_t size, bool preserveData) = 0; + CopyResult *resultOut, + BufferFeedback *feedback) = 0; + virtual angle::Result resize(const gl::Context *context, + size_t size, + bool preserveData, + BufferFeedback *feedback) = 0; virtual angle::Result map(const gl::Context *context, size_t offset, @@ -155,7 +162,7 @@ class Buffer11::BufferStorage : angle::NonCopyable class Buffer11::NativeStorage : public Buffer11::BufferStorage { public: - NativeStorage(Renderer11 *renderer, BufferUsage usage, const angle::Subject *onStorageChanged); + NativeStorage(Renderer11 *renderer, BufferUsage usage); ~NativeStorage() override; bool isCPUAccessible(GLbitfield access) const override; @@ -168,8 +175,12 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) override; - angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override; + CopyResult *resultOut, + BufferFeedback *feedback) override; + angle::Result resize(const gl::Context *context, + size_t size, + bool preserveData, + BufferFeedback *feedback) override; angle::Result map(const gl::Context *context, size_t offset, @@ -188,7 +199,6 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage protected: d3d11::Buffer mBuffer; - const angle::Subject *mOnStorageChanged; private: static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, @@ -205,13 +215,12 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage class Buffer11::StructuredBufferStorage : public Buffer11::NativeStorage { public: - StructuredBufferStorage(Renderer11 *renderer, - BufferUsage usage, - const angle::Subject *onStorageChanged); + StructuredBufferStorage(Renderer11 *renderer, BufferUsage usage); ~StructuredBufferStorage() override; angle::Result resizeStructuredBuffer(const gl::Context *context, unsigned int size, - unsigned int structureByteStride); + unsigned int structureByteStride, + BufferFeedback *feedback); angle::Result getStructuredBufferRangeSRV(const gl::Context *context, unsigned int offset, unsigned int size, @@ -239,8 +248,12 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) override; - angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override; + CopyResult *resultOut, + BufferFeedback *feedback) override; + angle::Result resize(const gl::Context *context, + size_t size, + bool preserveData, + BufferFeedback *feedback) override; angle::Result map(const gl::Context *context, size_t offset, @@ -259,7 +272,6 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage TextureHelper11 mStagingTexture; angle::MemoryBuffer mMemoryBuffer; std::unique_ptr mQueuedPackCommand; - PackPixelsParams mPackParams; bool mDataModified; }; @@ -281,8 +293,12 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) override; - angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override; + CopyResult *resultOut, + BufferFeedback *feedback) override; + angle::Result resize(const gl::Context *context, + size_t size, + bool preserveData, + BufferFeedback *feedback) override; angle::Result map(const gl::Context *context, size_t offset, @@ -336,10 +352,11 @@ angle::Result Buffer11::setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { - updateD3DBufferUsage(context, usage); - return setSubData(context, target, data, size, 0); + updateD3DBufferUsage(context, usage, feedback); + return setSubData(context, target, data, size, 0, feedback); } angle::Result Buffer11::getData(const gl::Context *context, const uint8_t **outData) @@ -353,8 +370,9 @@ angle::Result Buffer11::getData(const gl::Context *context, const uint8_t **outD } SystemMemoryStorage *systemMemoryStorage = nullptr; - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &systemMemoryStorage)); - + BufferFeedback feedback; + ANGLE_TRY( + getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &systemMemoryStorage, &feedback)); ASSERT(systemMemoryStorage->getSize() >= mSize); *outData = systemMemoryStorage->getSystemCopy()->data(); @@ -365,7 +383,8 @@ angle::Result Buffer11::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { size_t requiredSize = size + offset; @@ -386,19 +405,22 @@ angle::Result Buffer11::setSubData(const gl::Context *context, !mRenderer->getFeatures().useSystemMemoryForConstantBuffers.enabled) { BufferStorage *latestStorage = nullptr; - ANGLE_TRY(getLatestBufferStorage(context, &latestStorage)); + ANGLE_TRY(getLatestBufferStorage(context, &latestStorage, feedback)); if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_STRUCTURED)) { - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_STRUCTURED, &writeBuffer)); + ANGLE_TRY( + getBufferStorage(context, BUFFER_USAGE_STRUCTURED, &writeBuffer, feedback)); } else { - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &writeBuffer)); + ANGLE_TRY( + getBufferStorage(context, BUFFER_USAGE_UNIFORM, &writeBuffer, feedback)); } } else { - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer)); + ANGLE_TRY( + getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer, feedback)); } } else if (supportsDirectBinding()) @@ -407,7 +429,8 @@ angle::Result Buffer11::setSubData(const gl::Context *context, } else { - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer)); + ANGLE_TRY( + getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer, feedback)); } ASSERT(writeBuffer); @@ -417,7 +440,7 @@ angle::Result Buffer11::setSubData(const gl::Context *context, if (writeBuffer->getSize() < requiredSize) { bool preserveData = (offset > 0); - ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData)); + ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData, feedback)); } ANGLE_TRY(writeBuffer->setData(context, static_cast(data), offset, size)); @@ -425,7 +448,7 @@ angle::Result Buffer11::setSubData(const gl::Context *context, } mSize = std::max(mSize, requiredSize); - invalidateStaticData(context); + invalidateStaticData(context, feedback); return angle::Result::Continue; } @@ -434,13 +457,14 @@ angle::Result Buffer11::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { Buffer11 *sourceBuffer = GetAs(source); ASSERT(sourceBuffer != nullptr); BufferStorage *copyDest = nullptr; - ANGLE_TRY(getLatestBufferStorage(context, ©Dest)); + ANGLE_TRY(getLatestBufferStorage(context, ©Dest, feedback)); if (!copyDest) { @@ -448,7 +472,7 @@ angle::Result Buffer11::copySubData(const gl::Context *context, } BufferStorage *copySource = nullptr; - ANGLE_TRY(sourceBuffer->getLatestBufferStorage(context, ©Source)); + ANGLE_TRY(sourceBuffer->getLatestBufferStorage(context, ©Source, feedback)); if (!copySource) { @@ -474,8 +498,8 @@ angle::Result Buffer11::copySubData(const gl::Context *context, { if (copySource->getUsage() == BUFFER_USAGE_STAGING) { - ANGLE_TRY( - getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, ©Source)); + ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, + ©Source, feedback)); } else { @@ -485,33 +509,37 @@ angle::Result Buffer11::copySubData(const gl::Context *context, CopyResult copyResult = CopyResult::NOT_RECREATED; ANGLE_TRY(copyDest->copyFromStorage(context, copySource, sourceOffset, size, destOffset, - ©Result)); + ©Result, feedback)); onStorageUpdate(copyDest); mSize = std::max(mSize, destOffset + size); - invalidateStaticData(context); + invalidateStaticData(context, feedback); return angle::Result::Continue; } -angle::Result Buffer11::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result Buffer11::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield // and call mapRange. ASSERT(access == GL_WRITE_ONLY_OES); - return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr); + return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr, feedback); } angle::Result Buffer11::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { ASSERT(!mMappedStorage); BufferStorage *latestStorage = nullptr; - ANGLE_TRY(getLatestBufferStorage(context, &latestStorage)); + ANGLE_TRY(getLatestBufferStorage(context, &latestStorage, feedback)); if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || latestStorage->getUsage() == BUFFER_USAGE_STAGING)) @@ -533,7 +561,7 @@ angle::Result Buffer11::mapRange(const gl::Context *context, { // Update the data revision immediately, since the data might be changed at any time onStorageUpdate(mMappedStorage); - invalidateStaticData(context); + invalidateStaticData(context, feedback); } uint8_t *mappedBuffer = nullptr; @@ -544,7 +572,9 @@ angle::Result Buffer11::mapRange(const gl::Context *context, return angle::Result::Continue; } -angle::Result Buffer11::unmap(const gl::Context *context, GLboolean *result) +angle::Result Buffer11::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { ASSERT(mMappedStorage); mMappedStorage->unmap(); @@ -556,9 +586,10 @@ angle::Result Buffer11::unmap(const gl::Context *context, GLboolean *result) return angle::Result::Continue; } -angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context) +angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context, + BufferFeedback *feedback) { - ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK)); + ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, feedback)); return angle::Result::Continue; } @@ -584,7 +615,9 @@ void Buffer11::updateDeallocThreshold(BufferUsage usage) } // Free the storage if we decide it isn't being used very often. -angle::Result Buffer11::checkForDeallocation(const gl::Context *context, BufferUsage usage) +angle::Result Buffer11::checkForDeallocation(const gl::Context *context, + BufferUsage usage, + BufferFeedback *feedback) { mIdleness[usage]++; @@ -592,7 +625,7 @@ angle::Result Buffer11::checkForDeallocation(const gl::Context *context, BufferU if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage]) { BufferStorage *latestStorage = nullptr; - ANGLE_TRY(getLatestBufferStorage(context, &latestStorage)); + ANGLE_TRY(getLatestBufferStorage(context, &latestStorage, feedback)); if (latestStorage != storage) { SafeDelete(storage); @@ -620,41 +653,48 @@ void Buffer11::markBufferUsage(BufferUsage usage) mIdleness[usage] = 0; } -angle::Result Buffer11::markBufferUsage(const gl::Context *context, BufferUsage usage) +angle::Result Buffer11::markBufferUsage(const gl::Context *context, + BufferUsage usage, + BufferFeedback *feedback) { BufferStorage *bufferStorage = nullptr; - ANGLE_TRY(getBufferStorage(context, usage, &bufferStorage)); + ANGLE_TRY(getBufferStorage(context, usage, &bufferStorage, feedback)); if (bufferStorage) { onStorageUpdate(bufferStorage); } - invalidateStaticData(context); + invalidateStaticData(context, feedback); return angle::Result::Continue; } angle::Result Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage) { + BufferFeedback feedback; + if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory()) { - ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY)); + ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY, &feedback)); } if (currentUsage != BUFFER_USAGE_STAGING) { - ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING)); + ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING, &feedback)); } + ASSERT(feedback.bufferStateChanged == false); + return angle::Result::Continue; } angle::Result Buffer11::getBuffer(const gl::Context *context, BufferUsage usage, - ID3D11Buffer **bufferOut) + ID3D11Buffer **bufferOut, + BufferFeedback *feedback) { NativeStorage *storage = nullptr; - ANGLE_TRY(getBufferStorage(context, usage, &storage)); + ANGLE_TRY(getBufferStorage(context, usage, &storage, feedback)); *bufferOut = storage->getBuffer().get(); return angle::Result::Continue; } @@ -664,19 +704,20 @@ angle::Result Buffer11::getConstantBufferRange(const gl::Context *context, GLsizeiptr size, const d3d11::Buffer **bufferOut, UINT *firstConstantOut, - UINT *numConstantsOut) + UINT *numConstantsOut, + BufferFeedback *feedback) { NativeStorage *bufferStorage = nullptr; if ((offset == 0 && size < static_cast(mRenderer->getNativeCaps().maxUniformBlockSize)) || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets) { - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &bufferStorage)); + ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &bufferStorage, feedback)); CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut); } else { - ANGLE_TRY(getConstantBufferRangeStorage(context, offset, size, &bufferStorage)); + ANGLE_TRY(getConstantBufferRangeStorage(context, offset, size, &bufferStorage, feedback)); *firstConstantOut = 0; *numConstantsOut = 0; } @@ -685,25 +726,26 @@ angle::Result Buffer11::getConstantBufferRange(const gl::Context *context, return angle::Result::Continue; } -angle::Result Buffer11::markRawBufferUsage(const gl::Context *context) +angle::Result Buffer11::markRawBufferUsage(const gl::Context *context, BufferFeedback *feedback) { - ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_RAW_UAV)); + ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_RAW_UAV, feedback)); return angle::Result::Continue; } -angle::Result Buffer11::markTypedBufferUsage(const gl::Context *context) +angle::Result Buffer11::markTypedBufferUsage(const gl::Context *context, BufferFeedback *feedback) { - ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_TYPED_UAV)); + ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_TYPED_UAV, feedback)); return angle::Result::Continue; } angle::Result Buffer11::getRawUAVRange(const gl::Context *context, GLintptr offset, GLsizeiptr size, - d3d11::UnorderedAccessView **uavOut) + d3d11::UnorderedAccessView **uavOut, + BufferFeedback *feedback) { NativeStorage *nativeStorage = nullptr; - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage)); + ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage, feedback)); return nativeStorage->getRawUAV(context, static_cast(offset), static_cast(size), uavOut); @@ -711,19 +753,21 @@ angle::Result Buffer11::getRawUAVRange(const gl::Context *context, angle::Result Buffer11::getSRV(const gl::Context *context, DXGI_FORMAT srvFormat, - const d3d11::ShaderResourceView **srvOut) + const d3d11::ShaderResourceView **srvOut, + BufferFeedback *feedback) { NativeStorage *nativeStorage = nullptr; - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK, &nativeStorage)); + ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK, &nativeStorage, feedback)); return nativeStorage->getSRVForFormat(context, srvFormat, srvOut); } angle::Result Buffer11::packPixels(const gl::Context *context, const gl::FramebufferAttachment &readAttachment, - const PackPixelsParams ¶ms) + const PackPixelsParams ¶ms, + BufferFeedback *feedback) { PackStorage *packStorage = nullptr; - ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK, &packStorage)); + ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK, &packStorage, feedback)); ASSERT(packStorage); ANGLE_TRY(packStorage->packPixels(context, readAttachment, params)); @@ -748,7 +792,8 @@ size_t Buffer11::getTotalCPUBufferMemoryBytes() const template angle::Result Buffer11::getBufferStorage(const gl::Context *context, BufferUsage usage, - StorageOutT **storageOut) + StorageOutT **storageOut, + BufferFeedback *feedback) { ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT); BufferStorage *&newStorage = mBufferStorages[usage]; @@ -763,12 +808,12 @@ angle::Result Buffer11::getBufferStorage(const gl::Context *context, // resize buffer if (newStorage->getSize() < mSize) { - ANGLE_TRY(newStorage->resize(context, mSize, true)); + ANGLE_TRY(newStorage->resize(context, mSize, true, feedback)); } ASSERT(newStorage); - ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize)); + ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize, feedback)); ANGLE_TRY(garbageCollection(context, usage)); *storageOut = GetAs(newStorage); @@ -786,18 +831,19 @@ Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage) return new SystemMemoryStorage(mRenderer); case BUFFER_USAGE_INDEX: case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: - return new NativeStorage(mRenderer, usage, this); + return new NativeStorage(mRenderer, usage); case BUFFER_USAGE_STRUCTURED: - return new StructuredBufferStorage(mRenderer, usage, nullptr); + return new StructuredBufferStorage(mRenderer, usage); default: - return new NativeStorage(mRenderer, usage, nullptr); + return new NativeStorage(mRenderer, usage); } } angle::Result Buffer11::getConstantBufferRangeStorage(const gl::Context *context, GLintptr offset, GLsizeiptr size, - Buffer11::NativeStorage **storageOut) + Buffer11::NativeStorage **storageOut, + BufferFeedback *feedback) { BufferStorage *newStorage; { @@ -840,7 +886,7 @@ angle::Result Buffer11::getConstantBufferRangeStorage(const gl::Context *context mConstantBufferRangeStoragesCache.erase(iter); } - ANGLE_TRY(newStorage->resize(context, size, false)); + ANGLE_TRY(newStorage->resize(context, size, false, feedback)); mConstantBufferStorageAdditionalSize += sizeDelta; // We don't copy the old data when resizing the constant buffer because the data may be @@ -849,7 +895,7 @@ angle::Result Buffer11::getConstantBufferRangeStorage(const gl::Context *context newStorage->setDataRevision(0); } - ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size)); + ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size, feedback)); ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_UNIFORM)); *storageOut = GetAs(newStorage); return angle::Result::Continue; @@ -859,7 +905,8 @@ angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context, unsigned int offset, unsigned int size, unsigned int structureByteStride, - const d3d11::ShaderResourceView **srvOut) + const d3d11::ShaderResourceView **srvOut, + BufferFeedback *feedback) { BufferStorage *newStorage; @@ -906,8 +953,8 @@ angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context, mStructuredBufferRangeStoragesCache.erase(iter); } - ANGLE_TRY( - structuredBufferStorage->resizeStructuredBuffer(context, size, structureByteStride)); + ANGLE_TRY(structuredBufferStorage->resizeStructuredBuffer(context, size, + structureByteStride, feedback)); mStructuredBufferStorageAdditionalSize += sizeDelta; // We don't copy the old data when resizing the structured buffer because the data may be @@ -916,7 +963,8 @@ angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context, newStorage->setDataRevision(0); } - ANGLE_TRY(updateBufferStorage(context, newStorage, offset, static_cast(size))); + ANGLE_TRY( + updateBufferStorage(context, newStorage, offset, static_cast(size), feedback)); ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_STRUCTURED)); ANGLE_TRY(structuredBufferStorage->getStructuredBufferRangeSRV(context, offset, size, structureByteStride, srvOut)); @@ -926,10 +974,11 @@ angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context, angle::Result Buffer11::updateBufferStorage(const gl::Context *context, BufferStorage *storage, size_t sourceOffset, - size_t storageSize) + size_t storageSize, + BufferFeedback *feedback) { BufferStorage *latestBuffer = nullptr; - ANGLE_TRY(getLatestBufferStorage(context, &latestBuffer)); + ANGLE_TRY(getLatestBufferStorage(context, &latestBuffer, feedback)); ASSERT(storage); @@ -962,15 +1011,15 @@ angle::Result Buffer11::updateBufferStorage(const gl::Context *context, CopyResult copyResult = CopyResult::NOT_RECREATED; ANGLE_TRY(stagingBuffer->copyFromStorage(context, latestBuffer, 0, latestBuffer->getSize(), - 0, ©Result)); + 0, ©Result, feedback)); onCopyStorage(stagingBuffer, latestBuffer); latestBuffer = stagingBuffer; } CopyResult copyResult = CopyResult::NOT_RECREATED; - ANGLE_TRY( - storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0, ©Result)); + ANGLE_TRY(storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0, + ©Result, feedback)); // If the D3D buffer has been recreated, we should update our serial. if (copyResult == CopyResult::RECREATED) { @@ -981,12 +1030,13 @@ angle::Result Buffer11::updateBufferStorage(const gl::Context *context, } angle::Result Buffer11::getLatestBufferStorage(const gl::Context *context, - Buffer11::BufferStorage **storageOut) const + Buffer11::BufferStorage **storageOut, + BufferFeedback *feedback) const { // resize buffer if (mLatestBufferStorage && mLatestBufferStorage->getSize() < mSize) { - ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true)); + ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true, feedback)); } *storageOut = mLatestBufferStorage; @@ -996,7 +1046,8 @@ angle::Result Buffer11::getLatestBufferStorage(const gl::Context *context, template angle::Result Buffer11::getStagingStorage(const gl::Context *context, StorageOutT **storageOut) { - return getBufferStorage(context, BUFFER_USAGE_STAGING, storageOut); + BufferFeedback feedback; + return getBufferStorage(context, BUFFER_USAGE_STAGING, storageOut, &feedback); } size_t Buffer11::getSize() const @@ -1011,16 +1062,16 @@ bool Buffer11::supportsDirectBinding() const return (mUsage == D3DBufferUsage::STATIC); } -void Buffer11::initializeStaticData(const gl::Context *context) +void Buffer11::initializeStaticData(const gl::Context *context, BufferFeedback *feedback) { - BufferD3D::initializeStaticData(context); - onStateChange(angle::SubjectMessage::SubjectChanged); + BufferD3D::initializeStaticData(context, feedback); + feedback->bufferStateChanged = true; } -void Buffer11::invalidateStaticData(const gl::Context *context) +void Buffer11::invalidateStaticData(const gl::Context *context, BufferFeedback *feedback) { - BufferD3D::invalidateStaticData(context); - onStateChange(angle::SubjectMessage::SubjectChanged); + BufferD3D::invalidateStaticData(context, feedback); + feedback->bufferStateChanged = true; } void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source) @@ -1042,7 +1093,6 @@ void Buffer11::onStorageUpdate(BufferStorage *updatedStorage) } // Buffer11::BufferStorage implementation - Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) {} @@ -1070,10 +1120,8 @@ angle::Result Buffer11::BufferStorage::setData(const gl::Context *context, // Buffer11::NativeStorage implementation -Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, - BufferUsage usage, - const angle::Subject *onStorageChanged) - : BufferStorage(renderer, usage), mBuffer(), mOnStorageChanged(onStorageChanged) +Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) + : BufferStorage(renderer, usage), mBuffer() {} Buffer11::NativeStorage::~NativeStorage() @@ -1100,7 +1148,8 @@ angle::Result Buffer11::NativeStorage::copyFromStorage(const gl::Context *contex size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) + CopyResult *resultOut, + BufferFeedback *feedback) { size_t requiredSize = destOffset + size; @@ -1108,7 +1157,7 @@ angle::Result Buffer11::NativeStorage::copyFromStorage(const gl::Context *contex bool preserveData = (destOffset > 0); if (!mBuffer.valid() || mBufferSize < requiredSize) { - ANGLE_TRY(resize(context, requiredSize, preserveData)); + ANGLE_TRY(resize(context, requiredSize, preserveData, feedback)); *resultOut = CopyResult::RECREATED; } else @@ -1165,7 +1214,8 @@ angle::Result Buffer11::NativeStorage::copyFromStorage(const gl::Context *contex angle::Result Buffer11::NativeStorage::resize(const gl::Context *context, size_t size, - bool preserveData) + bool preserveData, + BufferFeedback *feedback) { if (size == 0) { @@ -1211,11 +1261,7 @@ angle::Result Buffer11::NativeStorage::resize(const gl::Context *context, // Free the UAVs. clearUAVs(); - // Notify that the storage has changed. - if (mOnStorageChanged) - { - mOnStorageChanged->onStateChange(angle::SubjectMessage::SubjectChanged); - } + feedback->bufferStateChanged = true; return angle::Result::Continue; } @@ -1398,10 +1444,8 @@ void Buffer11::NativeStorage::clearUAVs() mBufferRawUAVs.clear(); } -Buffer11::StructuredBufferStorage::StructuredBufferStorage(Renderer11 *renderer, - BufferUsage usage, - const angle::Subject *onStorageChanged) - : NativeStorage(renderer, usage, onStorageChanged), mStructuredBufferResourceView() +Buffer11::StructuredBufferStorage::StructuredBufferStorage(Renderer11 *renderer, BufferUsage usage) + : NativeStorage(renderer, usage), mStructuredBufferResourceView() {} Buffer11::StructuredBufferStorage::~StructuredBufferStorage() @@ -1412,7 +1456,8 @@ Buffer11::StructuredBufferStorage::~StructuredBufferStorage() angle::Result Buffer11::StructuredBufferStorage::resizeStructuredBuffer( const gl::Context *context, unsigned int size, - unsigned int structureByteStride) + unsigned int structureByteStride, + BufferFeedback *feedback) { if (size == 0) { @@ -1441,11 +1486,7 @@ angle::Result Buffer11::StructuredBufferStorage::resizeStructuredBuffer( mStructuredBufferResourceView.reset(); - // Notify that the storage has changed. - if (mOnStorageChanged) - { - mOnStorageChanged->onStateChange(angle::SubjectMessage::SubjectChanged); - } + feedback->bufferStateChanged = true; return angle::Result::Continue; } @@ -1490,7 +1531,8 @@ angle::Result Buffer11::PackStorage::copyFromStorage(const gl::Context *context, size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) + CopyResult *resultOut, + BufferFeedback *feedback) { ANGLE_TRY(flushQueuedPackCommand(context)); @@ -1507,7 +1549,8 @@ angle::Result Buffer11::PackStorage::copyFromStorage(const gl::Context *context, angle::Result Buffer11::PackStorage::resize(const gl::Context *context, size_t size, - bool preserveData) + bool preserveData, + BufferFeedback *feedback) { if (size != mBufferSize) { @@ -1553,24 +1596,30 @@ angle::Result Buffer11::PackStorage::packPixels(const gl::Context *context, RenderTarget11 *renderTarget = nullptr; ANGLE_TRY(readAttachment.getRenderTarget(context, 0, &renderTarget)); - const TextureHelper11 &srcTexture = renderTarget->getTexture(); - ASSERT(srcTexture.valid()); + const TextureHelper11 *srcTexture = &renderTarget->getTexture(); + ASSERT(srcTexture->valid()); unsigned int srcSubresource = renderTarget->getSubresourceIndex(); + TextureHelper11 resolvedTexture; + if (srcTexture->getSampleCount() > 1) + { + ANGLE_TRY(mRenderer->resolveMultisampledTexture(context, renderTarget, false, false, + &resolvedTexture)); + srcTexture = &resolvedTexture; + srcSubresource = 0; + } + mQueuedPackCommand.reset(new PackPixelsParams(params)); gl::Extents srcTextureSize(params.area.width, params.area.height, 1); - if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() || + if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture->getFormat() || mStagingTexture.getExtents() != srcTextureSize) { - ANGLE_TRY(mRenderer->createStagingTexture(context, srcTexture.getTextureType(), - srcTexture.getFormatSet(), srcTextureSize, + ANGLE_TRY(mRenderer->createStagingTexture(context, srcTexture->getTextureType(), + srcTexture->getFormatSet(), srcTextureSize, StagingAccess::READ, &mStagingTexture)); } - // ReadPixels from multisampled FBOs isn't supported in current GL - ASSERT(srcTexture.getSampleCount() <= 1); - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); D3D11_BOX srcBox; srcBox.left = params.area.x; @@ -1587,7 +1636,7 @@ angle::Result Buffer11::PackStorage::packPixels(const gl::Context *context, srcBox.back = srcBox.front + 1; // Asynchronous copy - immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture.get(), + immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture->get(), srcSubresource, &srcBox); return angle::Result::Continue; @@ -1618,7 +1667,8 @@ angle::Result Buffer11::SystemMemoryStorage::copyFromStorage(const gl::Context * size_t sourceOffset, size_t size, size_t destOffset, - CopyResult *resultOut) + CopyResult *resultOut, + BufferFeedback *feedback) { ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT)); uint8_t *sourceData = nullptr; @@ -1632,7 +1682,8 @@ angle::Result Buffer11::SystemMemoryStorage::copyFromStorage(const gl::Context * angle::Result Buffer11::SystemMemoryStorage::resize(const gl::Context *context, size_t size, - bool preserveData) + bool preserveData, + BufferFeedback *feedback) { if (mSystemCopy.size() < size) { diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/libANGLE/renderer/d3d/d3d11/Buffer11.h index 7a96a14ea25..620f96fa329 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -56,25 +56,31 @@ class Buffer11 : public BufferD3D angle::Result getBuffer(const gl::Context *context, BufferUsage usage, - ID3D11Buffer **bufferOut); + ID3D11Buffer **bufferOut, + BufferFeedback *feedback); + angle::Result getConstantBufferRange(const gl::Context *context, GLintptr offset, GLsizeiptr size, const d3d11::Buffer **bufferOut, UINT *firstConstantOut, - UINT *numConstantsOut); + UINT *numConstantsOut, + BufferFeedback *feedback); angle::Result getStructuredBufferRangeSRV(const gl::Context *context, unsigned int offset, unsigned int size, unsigned int structureByteStride, - const d3d11::ShaderResourceView **srvOut); + const d3d11::ShaderResourceView **srvOut, + BufferFeedback *feedback); angle::Result getSRV(const gl::Context *context, DXGI_FORMAT srvFormat, - const d3d11::ShaderResourceView **srvOut); + const d3d11::ShaderResourceView **srvOut, + BufferFeedback *feedback); angle::Result getRawUAVRange(const gl::Context *context, GLintptr offset, GLsizeiptr size, - d3d11::UnorderedAccessView **uavOut); + d3d11::UnorderedAccessView **uavOut, + BufferFeedback *feedback); angle::Result getTypedUAVRange(const gl::Context *context, GLintptr offset, @@ -82,45 +88,56 @@ class Buffer11 : public BufferD3D DXGI_FORMAT format, d3d11::UnorderedAccessView **uavOut); - angle::Result markRawBufferUsage(const gl::Context *context); - angle::Result markTypedBufferUsage(const gl::Context *context); + angle::Result markRawBufferUsage(const gl::Context *context, BufferFeedback *feedback); + angle::Result markTypedBufferUsage(const gl::Context *context, BufferFeedback *feedback); bool isMapped() const { return mMappedStorage != nullptr; } angle::Result packPixels(const gl::Context *context, const gl::FramebufferAttachment &readAttachment, - const PackPixelsParams ¶ms); + const PackPixelsParams ¶ms, + BufferFeedback *feedback); size_t getTotalCPUBufferMemoryBytes() const; // BufferD3D implementation size_t getSize() const override; bool supportsDirectBinding() const override; angle::Result getData(const gl::Context *context, const uint8_t **outData) override; - void initializeStaticData(const gl::Context *context) override; - void invalidateStaticData(const gl::Context *context) override; + void initializeStaticData(const gl::Context *context, BufferFeedback *feedback) override; + void invalidateStaticData(const gl::Context *context, BufferFeedback *feedback) override; // BufferImpl implementation angle::Result setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; - angle::Result markTransformFeedbackUsage(const gl::Context *context) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; + angle::Result markTransformFeedbackUsage(const gl::Context *context, + BufferFeedback *feedback) override; private: class BufferStorage; @@ -153,13 +170,16 @@ class Buffer11 : public BufferD3D }; void markBufferUsage(BufferUsage usage); - angle::Result markBufferUsage(const gl::Context *context, BufferUsage usage); + angle::Result markBufferUsage(const gl::Context *context, + BufferUsage usage, + BufferFeedback *feedback); angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage); angle::Result updateBufferStorage(const gl::Context *context, BufferStorage *storage, size_t sourceOffset, - size_t storageSize); + size_t storageSize, + BufferFeedback *feedback); angle::Result getNativeStorageForUAV(const gl::Context *context, Buffer11::NativeStorage **storageOut); @@ -167,24 +187,29 @@ class Buffer11 : public BufferD3D template angle::Result getBufferStorage(const gl::Context *context, BufferUsage usage, - StorageOutT **storageOut); + StorageOutT **storageOut, + BufferFeedback *feedback); template angle::Result getStagingStorage(const gl::Context *context, StorageOutT **storageOut); angle::Result getLatestBufferStorage(const gl::Context *context, - BufferStorage **storageOut) const; + BufferStorage **storageOut, + BufferFeedback *feedback) const; angle::Result getConstantBufferRangeStorage(const gl::Context *context, GLintptr offset, GLsizeiptr size, - NativeStorage **storageOut); + NativeStorage **storageOut, + BufferFeedback *feedback); BufferStorage *allocateStorage(BufferUsage usage); void updateDeallocThreshold(BufferUsage usage); // Free the storage if we decide it isn't being used very often. - angle::Result checkForDeallocation(const gl::Context *context, BufferUsage usage); + angle::Result checkForDeallocation(const gl::Context *context, + BufferUsage usage, + BufferFeedback *feedback); // For some cases of uniform buffer storage, we can't deallocate system memory storage. bool canDeallocateSystemMemory() const; diff --git a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp index 0a22f52ea68..9a02fff5ad3 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -1,4 +1,4 @@ - +// // Copyright 2013 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. @@ -6,6 +6,10 @@ // Clear11.cpp: Framebuffer clear utility class. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/d3d/d3d11/Clear11.h" #include @@ -390,7 +394,7 @@ angle::Result Clear11::clearFramebuffer(const gl::Context *context, clearParams.scissor.height == 0) { // The check assumes that the viewport offsets are not negative as according to the - // OVR_multiview2 spec. + // OVR_multiview spec. // Scissor rect is outside the renderbuffer or is an empty rect. return angle::Result::Continue; } @@ -442,8 +446,7 @@ angle::Result Clear11::clearFramebuffer(const gl::Context *context, } RenderTarget11 *renderTarget = nullptr; - ANGLE_TRY(attachment.getRenderTarget(context, attachment.getRenderToTextureSamples(), - &renderTarget)); + ANGLE_TRY(attachment.getRenderTarget(context, 0, &renderTarget)); const gl::InternalFormat &formatInfo = *attachment.getFormat().info; @@ -538,9 +541,7 @@ angle::Result Clear11::clearFramebuffer(const gl::Context *context, RenderTarget11 *depthStencilRenderTarget = nullptr; ASSERT(depthStencilAttachment != nullptr); - ANGLE_TRY(depthStencilAttachment->getRenderTarget( - context, depthStencilAttachment->getRenderToTextureSamples(), - &depthStencilRenderTarget)); + ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, 0, &depthStencilRenderTarget)); dsv = depthStencilRenderTarget->getDepthStencilView().get(); ASSERT(dsv != nullptr); diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp index 9d61f3fab2f..780737a8732 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp @@ -7,14 +7,21 @@ // D3D11-specific functionality associated with a GL Context. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/Context11.h" +#include + #include "common/entry_points_enum_autogen.h" #include "common/string_utils.h" #include "image_util/loadimage.h" #include "libANGLE/Context.h" #include "libANGLE/Context.inl.h" #include "libANGLE/MemoryProgramCache.h" +#include "libANGLE/histogram_macros.h" #include "libANGLE/renderer/OverlayImpl.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h" @@ -205,9 +212,10 @@ BufferImpl *Context11::createBuffer(const gl::BufferState &state) return buffer; } -VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data) +VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) { - return new VertexArray11(data); + return new VertexArray11(data, vertexArrayBuffers); } QueryImpl *Context11::createQuery(gl::QueryType type) @@ -323,7 +331,8 @@ ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *contex { gl::IndexRange indexRange; ANGLE_TRY(context->getState().getVertexArray()->getIndexRange( - context, indexType, indexCount, indices, &indexRange)); + context, indexType, indexCount, indices, + context->getState().isPrimitiveRestartEnabled(), &indexRange)); GLint startVertex; ANGLE_TRY(ComputeStartVertex(GetImplAs(context), indexRange, baseVertex, &startVertex)); @@ -472,8 +481,9 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context, // make sure we are using the correct 'baseVertex'. This parameter does not exist for the // direct drawElements. gl::IndexRange indexRange; - ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count, - indices, &indexRange)); + ANGLE_TRY(context->getState().getVertexArray()->getIndexRange( + context, type, cmd->count, indices, context->getState().isPrimitiveRestartEnabled(), + &indexRange)); GLint startVertex; ANGLE_TRY(ComputeStartVertex(GetImplAs(context), indexRange, cmd->baseVertex, @@ -482,7 +492,7 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context, ANGLE_TRY(mRenderer->getStateManager()->updateState( context, mode, startVertex, cmd->count, type, indices, cmd->primCount, cmd->baseVertex, cmd->baseInstance, true)); - return mRenderer->drawElements(context, mode, static_cast(indexRange.start), + return mRenderer->drawElements(context, mode, static_cast(indexRange.start()), cmd->count, type, indices, cmd->primCount, 0, cmd->baseInstance, true); } @@ -549,7 +559,6 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context, ASSERT(counts[drawID] > 0); \ DRAW_CALL(drawType, instanced, bvbi); \ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \ - gl::MarkShaderStorageUsage(context); \ } \ /* reset the uniform to zero for non-multi-draw uses of the program */ \ ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(0); \ @@ -784,12 +793,11 @@ angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker) angle::Result Context11::popGroupMarker() { - const char *marker = nullptr; if (!mMarkerStack.empty()) { - marker = mMarkerStack.top().c_str(); + std::string marker = std::move(mMarkerStack.top()); mMarkerStack.pop(); - mRenderer->getDebugAnnotatorContext()->endEvent(marker, + mRenderer->getDebugAnnotatorContext()->endEvent(marker.c_str(), angle::EntryPoint::GLPopGroupMarkerEXT); } return angle::Result::Continue; @@ -913,19 +921,7 @@ gl::Caps Context11::getNativeCaps() const // version: // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) // as the value of max draw buffers because UAVs are not used. - // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8 - // slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value - // of max combined shader output resources is limited to 7, thus only 7 RTV slots can be - // used simultaneously. - // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64 - // slots. Currently we allocate 60 slots for combined shader output resources, so we can use - // at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously. - if (mState.getClientVersion() >= gl::ES_3_1 && - mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0) - { - caps.maxDrawBuffers = caps.maxCombinedShaderOutputResources; - caps.maxColorAttachments = caps.maxCombinedShaderOutputResources; - } + // - ES 3.1 is not supported. return caps; } @@ -955,12 +951,14 @@ angle::Result Context11::dispatchCompute(const gl::Context *context, GLuint numGroupsY, GLuint numGroupsZ) { - return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ); + UNIMPLEMENTED(); + return angle::Result::Stop; } angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) { - return mRenderer->dispatchComputeIndirect(context, indirect); + UNIMPLEMENTED(); + return angle::Result::Stop; } angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context, @@ -1041,46 +1039,6 @@ angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context * return angle::Result::Continue; } -angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context) -{ - const auto &glState = context->getState(); - gl::ProgramExecutable *executable = glState.getProgramExecutable(); - ProgramExecutableD3D *executableD3D = GetImplAs(executable); - - executableD3D->updateCachedImage2DBindLayout(context, gl::ShaderType::Compute); - - bool recompileCS = !executableD3D->hasComputeExecutableForCachedImage2DBindLayout(); - - if (!recompileCS) - { - return angle::Result::Continue; - } - - // Load the compiler if necessary and recompile the programs. - ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this)); - - gl::InfoLog infoLog; - - ShaderExecutableD3D *computeExe = nullptr; - ANGLE_TRY(executableD3D->getComputeExecutableForImage2DBindLayout(this, mRenderer, &computeExe, - &infoLog)); - if (!executableD3D->hasComputeExecutableForCachedImage2DBindLayout()) - { - ASSERT(infoLog.getLength() > 0); - ERR() << "Dynamic recompilation error log: " << infoLog.str(); - ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable"); - } - - // Refresh the program cache entry. - gl::Program *program = glState.getProgram(); - if (mMemoryProgramCache && IsSameExecutable(&program->getExecutable(), executable)) - { - ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program)); - } - - return angle::Result::Continue; -} - angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers) { return angle::Result::Continue; @@ -1106,7 +1064,7 @@ angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context * TextureD3D *textureD3D = GetImplAs(glTexture); gl::ImageIndex index = gl::ImageIndex::Make2DMultisample(); RenderTargetD3D *renderTarget = nullptr; - GLsizei texSamples = textureD3D->getRenderToTextureSamples(); + GLsizei texSamples = 0; ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget)); return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0); @@ -1129,6 +1087,8 @@ void Context11::handleResult(HRESULT hr, { HRESULT removalReason = mRenderer->getDevice()->GetDeviceRemovedReason(); errorStream << " (removal reason: " << gl::FmtHR(removalReason) << ")"; + ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3DDeviceRemovedReason", + static_cast(removalReason)); mRenderer->notifyDeviceLost(); } diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/libANGLE/renderer/d3d/d3d11/Context11.h index 5766986c1a8..93fc111e36e 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Context11.h +++ b/src/libANGLE/renderer/d3d/d3d11/Context11.h @@ -49,7 +49,8 @@ class Context11 : public ContextD3D, public MultisampleTextureInitializer BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; @@ -254,7 +255,6 @@ class Context11 : public ContextD3D, public MultisampleTextureInitializer angle::Result triggerDrawCallProgramRecompilation(const gl::Context *context, gl::PrimitiveMode drawMode); - angle::Result triggerDispatchCallProgramRecompilation(const gl::Context *context); angle::Result getIncompleteTexture(const gl::Context *context, gl::TextureType type, gl::Texture **textureOut); diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp index 0242465c914..0aed65b1d81 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -6,6 +6,10 @@ // Framebuffer11.cpp: Implements the Framebuffer11 class. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" #include "common/bitset_utils.h" @@ -289,7 +293,10 @@ angle::Result Framebuffer11::readPixelsImpl(const gl::Context *context, pack.reverseRowOrder, packBuffer, reinterpret_cast(pixels)); - return packBufferStorage->packPixels(context, *readAttachment, packParams); + BufferFeedback feedback; + ANGLE_TRY(packBufferStorage->packPixels(context, *readAttachment, packParams, &feedback)); + packBuffer->applyImplFeedback(context, feedback); + return angle::Result::Continue; } return mRenderer->readFromAttachment(context, *readAttachment, area, format, type, @@ -327,8 +334,7 @@ angle::Result Framebuffer11::blitImpl(const gl::Context *context, if (drawBuffer.isAttached() && drawBufferStates[colorAttachment] != GL_NONE) { RenderTargetD3D *drawRenderTarget = nullptr; - ANGLE_TRY(drawBuffer.getRenderTarget( - context, drawBuffer.getRenderToTextureSamples(), &drawRenderTarget)); + ANGLE_TRY(drawBuffer.getRenderTarget(context, 0, &drawRenderTarget)); ASSERT(drawRenderTarget); const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer); @@ -384,8 +390,7 @@ angle::Result Framebuffer11::blitImpl(const gl::Context *context, const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); ASSERT(drawBuffer); RenderTargetD3D *drawRenderTarget = nullptr; - ANGLE_TRY(drawBuffer->getRenderTarget(context, drawBuffer->getRenderToTextureSamples(), - &drawRenderTarget)); + ANGLE_TRY(drawBuffer->getRenderTarget(context, 0, &drawRenderTarget)); ASSERT(drawRenderTarget); bool invertDest = UsePresentPathFast(mRenderer, drawBuffer); @@ -443,6 +448,8 @@ angle::Result Framebuffer11::getSamplePosition(const gl::Context *context, const gl::FramebufferAttachment *attachment = mState.getFirstNonNullAttachment(); ASSERT(attachment); GLsizei sampleCount = attachment->getSamples(); + // GL_OVR_multiview_multisampled_render_to_texture is not supported on D3D backend + ASSERT(!(attachment->isRenderToTexture() && attachment->isMultiview())); rx::GetSamplePosition(sampleCount, index, xy); return angle::Result::Continue; diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp index a12ff376031..8b18ce74e7a 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -7,6 +7,10 @@ // Image11.h: Implements the rx::Image11 class, which acts as the interface to // the actual underlying resources of a Texture +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/Image11.h" #include "common/utilities.h" diff --git a/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp index 7630b341fa4..eafba6ad6b6 100644 --- a/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -6,6 +6,10 @@ // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" #include "libANGLE/Context.h" diff --git a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h index 1a7f15e900a..a67a3a5b7ff 100644 --- a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h +++ b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -18,6 +18,7 @@ #include #include "common/angleutils.h" +#include "common/span.h" #include "libANGLE/Constants.h" #include "libANGLE/Error.h" #include "libANGLE/SizedMRUCache.h" @@ -51,7 +52,7 @@ struct hash { size_t operator()(const rx::PackedAttributeLayout &value) const { - return angle::ComputeGenericHash(value); + return angle::ComputeGenericHash(angle::byte_span_from_ref(value)); } }; } // namespace std diff --git a/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp b/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp index d0f6906f1ea..4a1a807c992 100644 --- a/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp @@ -9,6 +9,10 @@ // mapped memory so that ASAN and MSAN can catch memory errors done with a // pointer to the mapped texture memory. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" diff --git a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp index 9649a91dd3a..b806942caf4 100644 --- a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -184,8 +184,11 @@ angle::Result PixelTransfer11::copyBufferToTexture(const gl::Context *context, ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); Buffer11 *bufferStorage11 = GetAs(unpackBuffer->getImplementation()); const d3d11::ShaderResourceView *bufferSRV = nullptr; - ANGLE_TRY(bufferStorage11->getSRV(context, srvFormat, &bufferSRV)); + BufferFeedback feedback; + ANGLE_TRY(bufferStorage11->getSRV(context, srvFormat, &bufferSRV, &feedback)); + ASSERT(bufferSRV != nullptr); + unpackBuffer->applyImplFeedback(context, feedback); const d3d11::RenderTargetView &textureRTV = GetAs(destRenderTarget)->getRenderTargetView(); diff --git a/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/libANGLE/renderer/d3d/d3d11/Query11.cpp index a1eea39a7b6..2cc1a4b86c8 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -36,9 +36,6 @@ GLuint64 MergeQueryResults(gl::QueryType type, GLuint64 currentResult, GLuint64 case gl::QueryType::Timestamp: return newResult; - case gl::QueryType::CommandsCompleted: - return newResult; - default: UNREACHABLE(); return 0; @@ -404,23 +401,6 @@ angle::Result Query11::testQuery(Context11 *context11, QueryState *queryState) } break; - case gl::QueryType::CommandsCompleted: - { - ASSERT(queryState->query.valid()); - BOOL completed = 0; - HRESULT result = - context->GetData(queryState->query.get(), &completed, sizeof(completed), 0); - ANGLE_TRY_HR(context11, result, "Failed to get the data of an internal query"); - - if (result == S_OK) - { - queryState->finished = true; - ASSERT(completed == TRUE); - mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE; - } - } - break; - default: UNREACHABLE(); break; diff --git a/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp index 324e598a06a..0d78abd4d71 100644 --- a/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -7,6 +7,10 @@ // RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render // state objects. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" #include diff --git a/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h index bd853fe86e4..cf42651952c 100644 --- a/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -11,6 +11,7 @@ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ #include "common/angleutils.h" +#include "common/span.h" #include "libANGLE/Error.h" #include "libANGLE/SizedMRUCache.h" #include "libANGLE/angletypes.h" @@ -25,7 +26,7 @@ struct hash { size_t operator()(const rx::d3d11::BlendStateKey &key) const { - return angle::ComputeGenericHash(key); + return angle::ComputeGenericHash(angle::byte_span_from_ref(key)); } }; @@ -34,7 +35,7 @@ struct hash { size_t operator()(const rx::d3d11::RasterizerStateKey &key) const { - return angle::ComputeGenericHash(key); + return angle::ComputeGenericHash(angle::byte_span_from_ref(key)); } }; @@ -43,14 +44,17 @@ struct hash { size_t operator()(const gl::DepthStencilState &key) const { - return angle::ComputeGenericHash(key); + return angle::ComputeGenericHash(angle::byte_span_from_ref(key)); } }; template <> struct hash { - size_t operator()(const gl::SamplerState &key) const { return angle::ComputeGenericHash(key); } + size_t operator()(const gl::SamplerState &key) const + { + return angle::ComputeGenericHash(angle::byte_span_from_ref(key)); + } }; } // namespace std diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 851660ca5d1..b074753b5d4 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -6,6 +6,10 @@ // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include @@ -117,6 +121,8 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) case D3D_FEATURE_LEVEL_11_0: return ANGLE_FEATURE_LEVEL_11_0; case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_12_1: return ANGLE_FEATURE_LEVEL_11_1; default: return ANGLE_FEATURE_LEVEL_INVALID; @@ -412,8 +418,6 @@ Renderer11::Renderer11(egl::Display *display) mCreateDebugDevice(false), mStateCache(), mStateManager(this), - mLastHistogramUpdateTime( - ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())), mDebug(nullptr), mScratchMemoryBuffer(ScratchMemoryBufferLifetime) { @@ -430,7 +434,6 @@ Renderer11::Renderer11(egl::Display *display) mRenderer11DeviceCaps.supportsClearView = false; mRenderer11DeviceCaps.supportsConstantBufferOffsets = false; mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false; - mRenderer11DeviceCaps.supportsDXGI1_2 = false; mRenderer11DeviceCaps.allowES3OnFL10_0 = false; mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats = false; mRenderer11DeviceCaps.supportsUAVLoadStoreCommonFormats = false; @@ -455,6 +458,17 @@ Renderer11::Renderer11(egl::Display *display) EGLint requestedMinorVersion = static_cast( attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)); + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 12) + { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_12_1); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_12_0); + } + } if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) { if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) @@ -706,7 +720,7 @@ egl::Error Renderer11::initializeDXGIAdapter() return initializeAdapterFromDevice(); } - else + else if (mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE) { angle::ComPtr factory; HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); @@ -716,8 +730,8 @@ egl::Error Renderer11::initializeDXGIAdapter() "Could not create DXGI factory"); } - // If the developer requests a specific adapter, honor their request regardless of the value - // of EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE. + // Prefer EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE over specific adapter requests if the user + // requests a non-hardware adapter. const egl::AttributeMap &attributes = mDisplay->getAttributeMap(); // Check EGL_ANGLE_platform_angle_d3d_luid long high = static_cast(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0)); @@ -759,9 +773,26 @@ egl::Error Renderer11::initializeDXGIAdapter() } } - // For requested driver types besides Hardware such as Warp, Reference, or Null - // allow D3D11CreateDevice to pick the adapter by passing it the driver type. - if (!mDxgiAdapter && mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE) + if (!mDxgiAdapter) + { + // Iterate through all adapters and choose the first non-WARP one + angle::ComPtr temp; + + for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++) + { + DXGI_ADAPTER_DESC desc; + if (SUCCEEDED(temp->GetDesc(&desc))) + { + if (!IsMicrosoft(desc.VendorId)) + { + mDxgiAdapter = std::move(temp); + break; + } + } + } + } + + if (!mDxgiAdapter) { hr = factory->EnumAdapters(0, &mDxgiAdapter); if (FAILED(hr)) @@ -771,6 +802,21 @@ egl::Error Renderer11::initializeDXGIAdapter() } } } + else + { + // For requested driver types besides Hardware such as Warp, Reference, or Null + // allow D3D11CreateDevice to pick the adapter by passing it the driver type. + + const egl::AttributeMap &attributes = mDisplay->getAttributeMap(); + if (attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0) != 0 || + attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0) != 0) + { + WARN() << "Non-hardware EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE requested at the same " + "time as non-default EGL_PLATFORM_ANGLE_D3D_LUID values. Ignoring requested " + "adapter."; + } + } + return egl::NoError(); } @@ -932,13 +978,16 @@ egl::Error Renderer11::initializeD3DDevice() result = callD3D11CreateDevice(D3D11CreateDevice, true); } - if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && - mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) + std::vector::iterator ite; + if (result == E_INVALIDARG && + (ite = std::lower_bound(mAvailableFeatureLevels.begin(), + mAvailableFeatureLevels.end(), D3D_FEATURE_LEVEL_11_1, + std::greater{})) != mAvailableFeatureLevels.end()) { // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. - // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature + // Try again without passing D3D_FEATURE_LEVEL_11_1+ in case we have other feature // levels to fall back on. - mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); + mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin(), ite + 1); if (createD3D11on12Device) { result = @@ -968,13 +1017,16 @@ egl::Error Renderer11::initializeD3DDevice() result = callD3D11CreateDevice(D3D11CreateDevice, false); } - if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && - mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) + std::vector::iterator ite; + if (result == E_INVALIDARG && + (ite = std::lower_bound(mAvailableFeatureLevels.begin(), + mAvailableFeatureLevels.end(), D3D_FEATURE_LEVEL_11_1, + std::greater{})) != mAvailableFeatureLevels.end()) { // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature // levels to fall back on. - mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); + mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin(), ite + 1); if (createD3D11on12Device) { result = @@ -1057,9 +1109,6 @@ egl::Error Renderer11::initializeDevice() ASSERT(!mPixelTransfer); mPixelTransfer = new PixelTransfer11(this); - // Gather stats on DXGI and D3D feature level - ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2); - ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel); // We don't actually request a 11_1 device, because of complications with the platform @@ -1176,33 +1225,24 @@ void Renderer11::populateRenderer11DeviceCaps() PopulateFormatDeviceCaps(mDevice.Get(), DXGI_FORMAT_B5G5R5A1_UNORM, &mRenderer11DeviceCaps.B5G5R5A1support, &mRenderer11DeviceCaps.B5G5R5A1maxSamples); - - angle::ComPtr dxgiAdapter2; - mDxgiAdapter.As(&dxgiAdapter2); - mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr); } gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig( const gl::TextureCaps &colorBufferFormatCaps, const gl::TextureCaps &depthStencilBufferFormatCaps) const { - gl::SupportedSampleSet sampleCounts; - // Generate a new set from the set intersection of sample counts between the color and depth // format caps. - std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(), - colorBufferFormatCaps.sampleCounts.end(), - depthStencilBufferFormatCaps.sampleCounts.begin(), - depthStencilBufferFormatCaps.sampleCounts.end(), - std::inserter(sampleCounts, sampleCounts.begin())); + gl::SupportedSampleSet sampleCounts = + colorBufferFormatCaps.sampleCounts & depthStencilBufferFormatCaps.sampleCounts; // Format of GL_NONE results in no supported sample counts. // Add back the color sample counts to the supported sample set. - if (depthStencilBufferFormatCaps.sampleCounts.empty()) + if (depthStencilBufferFormatCaps.sampleCounts.getMaxSamples() == 0) { sampleCounts = colorBufferFormatCaps.sampleCounts; } - else if (colorBufferFormatCaps.sampleCounts.empty()) + else if (colorBufferFormatCaps.sampleCounts.getMaxSamples() == 0) { // Likewise, add back the depth sample counts to the supported sample set. sampleCounts = depthStencilBufferFormatCaps.sampleCounts; @@ -1285,7 +1325,7 @@ egl::ConfigSet Renderer11::generateConfigs() const gl::SupportedSampleSet sampleCounts = generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps); - for (GLuint sampleCount : sampleCounts) + for (GLuint sampleCount : sampleCounts.sampleCounts()) { egl::Config config; config.renderTargetFormat = colorBufferInternalFormat; @@ -1317,7 +1357,7 @@ egl::ConfigSet Renderer11::generateConfigs() } // We can only support conformant ES3 on FL 10.1+ - if (maxVersion.major >= 3) + if (maxVersion >= gl::ES_3_0) { config.conformant |= EGL_OPENGL_ES3_BIT_KHR; } @@ -1338,7 +1378,7 @@ egl::ConfigSet Renderer11::generateConfigs() // Can't support ES3 at all without feature level 10.1 config.renderableType = EGL_OPENGL_ES2_BIT; - if (maxVersion.major >= 3) + if (maxVersion >= gl::ES_3_0) { config.renderableType |= EGL_OPENGL_ES3_BIT_KHR; } @@ -1384,8 +1424,7 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions // If present path fast is active then the surface orientation extension isn't supported outExtensions->surfaceOrientation = !mPresentPathFastEnabled; - // D3D11 does not support present with dirty rectangles until DXGI 1.2. - outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2; + outExtensions->postSubBuffer = true; outExtensions->image = true; outExtensions->imageBase = true; @@ -1856,8 +1895,6 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, Context11 *context11 = GetImplAs(context); - ANGLE_TRY(markRawBufferUsage(context)); - ProgramExecutableD3D *executableD3D = mStateManager.getProgramExecutableD3D(); GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(executableD3D, instanceCount); @@ -1917,8 +1954,6 @@ angle::Result Renderer11::drawElements(const gl::Context *context, return angle::Result::Continue; } - ANGLE_TRY(markRawBufferUsage(context)); - // Transform feedback is not allowed for DrawElements, this error should have been caught at the // API validation layer. const gl::State &glState = context->getState(); @@ -1961,8 +1996,6 @@ angle::Result Renderer11::drawArraysIndirect(const gl::Context *context, const v return angle::Result::Continue; } - ANGLE_TRY(markRawBufferUsage(context)); - const gl::State &glState = context->getState(); ASSERT(!glState.isTransformFeedbackActiveUnpaused()); @@ -1973,7 +2006,10 @@ angle::Result Renderer11::drawArraysIndirect(const gl::Context *context, const v uintptr_t offset = reinterpret_cast(indirect); ID3D11Buffer *buffer = nullptr; - ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); + BufferFeedback feedback; + ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer, &feedback)); + drawIndirectBuffer->applyImplFeedback(context, feedback); + mDeviceContext->DrawInstancedIndirect(buffer, static_cast(offset)); return angle::Result::Continue; } @@ -1985,8 +2021,6 @@ angle::Result Renderer11::drawElementsIndirect(const gl::Context *context, const return angle::Result::Continue; } - ANGLE_TRY(markRawBufferUsage(context)); - const gl::State &glState = context->getState(); ASSERT(!glState.isTransformFeedbackActiveUnpaused()); @@ -1996,7 +2030,9 @@ angle::Result Renderer11::drawElementsIndirect(const gl::Context *context, const uintptr_t offset = reinterpret_cast(indirect); ID3D11Buffer *buffer = nullptr; - ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); + BufferFeedback feedback; + ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer, &feedback)); + drawIndirectBuffer->applyImplFeedback(context, feedback); mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast(offset)); return angle::Result::Continue; } @@ -2043,7 +2079,10 @@ angle::Result Renderer11::drawLineLoop(const gl::Context *context, GetLineLoopIndices(indices, type, static_cast(count), glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); - + if (ANGLE_UNLIKELY(mScratchIndexDataBuffer.empty())) + { + return angle::Result::Continue; + } unsigned int spaceNeeded = static_cast(sizeof(GLuint) * mScratchIndexDataBuffer.size()); ANGLE_TRY( @@ -2441,6 +2480,8 @@ int Renderer11::getMajorShaderModel() const { switch (mRenderer11DeviceCaps.featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 @@ -2460,6 +2501,8 @@ int Renderer11::getMinorShaderModel() const { switch (mRenderer11DeviceCaps.featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 @@ -2479,6 +2522,8 @@ std::string Renderer11::getShaderModelSuffix() const { switch (mRenderer11DeviceCaps.featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return ""; @@ -2578,8 +2623,7 @@ angle::Result Renderer11::copyImage2D(const gl::Context *context, gl::ImageIndex index = gl::ImageIndex::Make2D(level); RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), - &destRenderTarget)); + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); ASSERT(destRenderTarget); ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, @@ -2604,8 +2648,7 @@ angle::Result Renderer11::copyImageCube(const gl::Context *context, gl::ImageIndex index = gl::ImageIndex::MakeCubeMapFace(target, level); RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), - &destRenderTarget)); + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); ASSERT(destRenderTarget); ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, @@ -2629,8 +2672,7 @@ angle::Result Renderer11::copyImage3D(const gl::Context *context, gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), - &destRenderTarget)); + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); ASSERT(destRenderTarget); ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, @@ -2654,8 +2696,7 @@ angle::Result Renderer11::copyImage2DArray(const gl::Context *context, gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); RenderTargetD3D *destRenderTarget = nullptr; - ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), - &destRenderTarget)); + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); ASSERT(destRenderTarget); ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, @@ -2780,8 +2821,7 @@ angle::Result Renderer11::copyTexture(const gl::Context *context, } RenderTargetD3D *destRenderTargetD3D = nullptr; - ANGLE_TRY(destStorage11->getRenderTarget( - context, destIndex, destStorage11->getRenderToTextureSamples(), &destRenderTargetD3D)); + ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D)); RenderTarget11 *destRenderTarget11 = GetAs(destRenderTargetD3D); @@ -2865,7 +2905,7 @@ angle::Result Renderer11::createRenderTarget(const gl::Context *context, const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps); const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); + GLuint supportedSamples = textureCaps.sampleCounts.getNearestSamples(samples); Context11 *context11 = GetImplAs(context); @@ -3073,13 +3113,6 @@ angle::Result Renderer11::loadExecutable(d3d::Context *context, *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader)); } break; - case gl::ShaderType::Compute: - { - d3d11::ComputeShader computeShader; - ANGLE_TRY(allocateResource(context, shaderData, &computeShader)); - *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader)); - } - break; default: ANGLE_HR_UNREACHABLE(context); } @@ -3109,9 +3142,6 @@ angle::Result Renderer11::compileToExecutable(d3d::Context *context, case gl::ShaderType::Geometry: profileStream << "gs"; break; - case gl::ShaderType::Compute: - profileStream << "cs"; - break; default: ANGLE_HR_UNREACHABLE(context); } @@ -3924,7 +3954,7 @@ angle::Result Renderer11::blitRenderbufferRect(const gl::Context *context, bool Renderer11::isES3Capable() const { - return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps).major > 2); + return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps) >= gl::ES_3_0); } RendererClass Renderer11::getRendererClass() const @@ -3932,37 +3962,6 @@ RendererClass Renderer11::getRendererClass() const return RENDERER_D3D11; } -void Renderer11::onSwap() -{ - // Send histogram updates every half hour - const double kHistogramUpdateInterval = 30 * 60; - - auto *platform = ANGLEPlatformCurrent(); - const double currentTime = platform->monotonicallyIncreasingTime(platform); - const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; - - if (timeSinceLastUpdate > kHistogramUpdateInterval) - { - updateHistograms(); - mLastHistogramUpdateTime = currentTime; - } -} - -void Renderer11::updateHistograms() -{ - // Update the buffer CPU memory histogram - { - size_t sizeSum = 0; - for (const Buffer11 *buffer : mAliveBuffers) - { - sizeSum += buffer->getTotalCPUBufferMemoryBytes(); - } - const int kOneMegaByte = 1024 * 1024; - ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB", - static_cast(sizeSum) / kOneMegaByte); - } -} - void Renderer11::onBufferCreate(const Buffer11 *created) { mAliveBuffers.insert(created); @@ -4164,8 +4163,7 @@ gl::Version Renderer11::getMaxSupportedESVersion() const gl::Version Renderer11::getMaxConformantESVersion() const { - // 3.1 support is in progress. - return std::min(getMaxSupportedESVersion(), gl::Version(3, 0)); + return getMaxSupportedESVersion(); } DebugAnnotatorContext11 *Renderer11::getDebugAnnotatorContext() @@ -4173,54 +4171,6 @@ DebugAnnotatorContext11 *Renderer11::getDebugAnnotatorContext() return &mAnnotatorContext; } -angle::Result Renderer11::dispatchCompute(const gl::Context *context, - GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ) -{ - const gl::State &glState = context->getState(); - const gl::ProgramExecutable *executable = glState.getProgramExecutable(); - if (executable->getShaderStorageBlocks().size() > 0 || - executable->getAtomicCounterBuffers().size() > 0) - { - ANGLE_TRY(markRawBufferUsage(context)); - } - ANGLE_TRY(markTypedBufferUsage(context)); - ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ)); - mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ); - - return angle::Result::Continue; -} -angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) -{ - const auto &glState = context->getState(); - const gl::ProgramExecutable *executable = glState.getProgramExecutable(); - if (executable->getShaderStorageBlocks().size() > 0 || - executable->getAtomicCounterBuffers().size() > 0) - { - ANGLE_TRY(markRawBufferUsage(context)); - } - - auto *dispatchIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DispatchIndirect); - ASSERT(dispatchIndirectBuffer); - - Buffer11 *storage = GetImplAs(dispatchIndirectBuffer); - const uint8_t *bufferData = nullptr; - // TODO(jie.a.chen@intel.com): num_groups_x,y,z have to be written into the driver constant - // buffer for the built-in variable gl_NumWorkGroups. There is an opportunity for optimization - // to use GPU->GPU copy instead. - // http://anglebug.com/42261508 - ANGLE_TRY(storage->getData(context, &bufferData)); - const GLuint *groups = reinterpret_cast(bufferData + indirect); - ANGLE_TRY(mStateManager.updateStateForCompute(context, groups[0], groups[1], groups[2])); - - ID3D11Buffer *buffer = nullptr; - ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); - - mDeviceContext->DispatchIndirect(buffer, static_cast(indirect)); - return angle::Result::Continue; -} - angle::Result Renderer11::createStagingTexture(const gl::Context *context, ResourceType textureType, const d3d11::Format &formatSet, @@ -4397,59 +4347,6 @@ angle::Result Renderer11::mapResource(const gl::Context *context, return angle::Result::Continue; } -angle::Result Renderer11::markTypedBufferUsage(const gl::Context *context) -{ - const gl::State &glState = context->getState(); - ProgramExecutableD3D *executableD3D = - GetImplAs(glState.getProgramExecutable()); - gl::RangeUI imageRange = executableD3D->getUsedImageRange(gl::ShaderType::Compute, false); - for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++) - { - GLint imageUnitIndex = executableD3D->getImageMapping(gl::ShaderType::Compute, imageIndex, - false, context->getCaps()); - ASSERT(imageUnitIndex != -1); - const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); - if (imageUnit.texture.get()->getType() == gl::TextureType::Buffer) - { - Buffer11 *buffer11 = GetImplAs(imageUnit.texture.get()->getBuffer().get()); - ANGLE_TRY(buffer11->markTypedBufferUsage(context)); - } - } - return angle::Result::Continue; -} - -angle::Result Renderer11::markRawBufferUsage(const gl::Context *context) -{ - const gl::State &glState = context->getState(); - const gl::ProgramExecutable *executable = glState.getProgramExecutable(); - for (size_t blockIndex = 0; blockIndex < executable->getShaderStorageBlocks().size(); - blockIndex++) - { - GLuint binding = executable->getShaderStorageBlockBinding(static_cast(blockIndex)); - const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding); - if (shaderStorageBuffer.get() != nullptr) - { - Buffer11 *bufferStorage = GetImplAs(shaderStorageBuffer.get()); - ANGLE_TRY(bufferStorage->markRawBufferUsage(context)); - } - } - - const std::vector &atomicCounterBuffers = - executable->getAtomicCounterBuffers(); - for (size_t index = 0; index < atomicCounterBuffers.size(); ++index) - { - const GLuint binding = executable->getAtomicCounterBufferBinding(index); - const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding); - - if (buffer.get() != nullptr) - { - Buffer11 *bufferStorage = GetImplAs(buffer.get()); - ANGLE_TRY(bufferStorage->markRawBufferUsage(context)); - } - } - return angle::Result::Continue; -} - angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context) { const gl::State &glState = context->getState(); @@ -4461,7 +4358,9 @@ angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context) if (binding.get() != nullptr) { BufferD3D *bufferD3D = GetImplAs(binding.get()); - ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context)); + BufferFeedback feedback; + ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context, &feedback)); + binding.get()->applyImplFeedback(context, feedback); } } diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h index 9aceb6bad98..2b2b4c9131e 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -49,7 +49,6 @@ struct Renderer11DeviceCaps Renderer11DeviceCaps(); D3D_FEATURE_LEVEL featureLevel; - bool supportsDXGI1_2; // Support for DXGI 1.2 bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView bool supportsConstantBufferOffsets; // Support for Constant buffer offset bool supportsVpRtIndexWriteFromVertexShader; // VP/RT can be selected in the Vertex Shader @@ -386,7 +385,6 @@ class Renderer11 : public RendererD3D RendererClass getRendererClass() const override; StateManager11 *getStateManager() { return &mStateManager; } - void onSwap(); void onBufferCreate(const Buffer11 *created); void onBufferDelete(const Buffer11 *deleted); @@ -422,12 +420,6 @@ class Renderer11 : public RendererD3D gl::Version getMaxSupportedESVersion() const override; gl::Version getMaxConformantESVersion() const override; - angle::Result dispatchCompute(const gl::Context *context, - GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ); - angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect); - angle::Result createStagingTexture(const gl::Context *context, ResourceType textureType, const d3d11::Format &formatSet, @@ -504,6 +496,12 @@ class Renderer11 : public RendererD3D std::string getVendorString() const override; std::string getVersionString(bool includeFullVersion) const override; + angle::Result resolveMultisampledTexture(const gl::Context *context, + RenderTarget11 *renderTarget, + bool depth, + bool stencil, + TextureHelper11 *textureOut); + private: void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, @@ -528,12 +526,6 @@ class Renderer11 : public RendererD3D int baseVertex, int instances); - angle::Result resolveMultisampledTexture(const gl::Context *context, - RenderTarget11 *renderTarget, - bool depth, - bool stencil, - TextureHelper11 *textureOut); - void populateRenderer11DeviceCaps(); void updateHistograms(); @@ -604,8 +596,6 @@ class Renderer11 : public RendererD3D // Created objects state tracking std::set mAliveBuffers; - double mLastHistogramUpdateTime; - angle::ComPtr mDevice12; angle::ComPtr mCommandQueue; diff --git a/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp index 41f547230d3..d13aa40345d 100644 --- a/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp @@ -9,6 +9,7 @@ #include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" #include "common/debug.h" +#include "libANGLE/histogram_macros.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" @@ -123,14 +124,6 @@ HRESULT CreateResource(ID3D11Device *device, return device->CreateBuffer(desc, initData, buffer); } -HRESULT CreateResource(ID3D11Device *device, - const ShaderData *desc, - void * /*initData*/, - ID3D11ComputeShader **resourceOut) -{ - return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut); -} - HRESULT CreateResource(ID3D11Device *device, const D3D11_DEPTH_STENCIL_DESC *desc, void * /*initData*/, @@ -178,6 +171,7 @@ HRESULT CreateResource(ID3D11Device *device, void * /*initData*/, ID3D11PixelShader **resourceOut) { + SCOPED_ANGLE_HISTOGRAM_TIMER_US("GPU.ANGLE.D3D11.CreatePixelShaderUs"); return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut); } @@ -250,6 +244,7 @@ HRESULT CreateResource(ID3D11Device *device, void * /*initData*/, ID3D11VertexShader **resourceOut) { + SCOPED_ANGLE_HISTOGRAM_TIMER_US("GPU.ANGLE.D3D11.CreateVertexShaderUs"); return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut); } diff --git a/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h index b013ab8358b..67302c5fce6 100644 --- a/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h +++ b/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h @@ -55,7 +55,6 @@ using ShaderData = WrappedArray; #define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \ OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \ - OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \ OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \ OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \ ID3D11Resource) \ diff --git a/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp index a30ca417c17..3fed75c3ccd 100644 --- a/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -23,8 +23,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, mPixelExecutable(std::move(executable)), mVertexExecutable(), mGeometryExecutable(), - mStreamOutExecutable(), - mComputeExecutable() + mStreamOutExecutable() {} ShaderExecutable11::ShaderExecutable11(const void *function, @@ -35,8 +34,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, mPixelExecutable(), mVertexExecutable(std::move(executable)), mGeometryExecutable(), - mStreamOutExecutable(std::move(streamOut)), - mComputeExecutable() + mStreamOutExecutable(std::move(streamOut)) {} ShaderExecutable11::ShaderExecutable11(const void *function, @@ -46,19 +44,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, mPixelExecutable(), mVertexExecutable(), mGeometryExecutable(std::move(executable)), - mStreamOutExecutable(), - mComputeExecutable() -{} - -ShaderExecutable11::ShaderExecutable11(const void *function, - size_t length, - d3d11::ComputeShader &&executable) - : ShaderExecutableD3D(function, length), - mPixelExecutable(), - mVertexExecutable(), - mGeometryExecutable(), - mStreamOutExecutable(), - mComputeExecutable(std::move(executable)) + mStreamOutExecutable() {} ShaderExecutable11::~ShaderExecutable11() {} @@ -83,11 +69,6 @@ const d3d11::GeometryShader &ShaderExecutable11::getStreamOutShader() const return mStreamOutExecutable; } -const d3d11::ComputeShader &ShaderExecutable11::getComputeShader() const -{ - return mComputeExecutable; -} - UniformStorage11::UniformStorage11(size_t initialSize) : UniformStorageD3D(initialSize), mConstantBuffer() {} diff --git a/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h index 75c71b32388..22eb5863145 100644 --- a/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h +++ b/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -32,7 +32,6 @@ class ShaderExecutable11 : public ShaderExecutableD3D d3d11::VertexShader &&executable, d3d11::GeometryShader &&streamOut); ShaderExecutable11(const void *function, size_t length, d3d11::GeometryShader &&executable); - ShaderExecutable11(const void *function, size_t length, d3d11::ComputeShader &&executable); ~ShaderExecutable11() override; @@ -40,14 +39,12 @@ class ShaderExecutable11 : public ShaderExecutableD3D const d3d11::VertexShader &getVertexShader() const; const d3d11::GeometryShader &getGeometryShader() const; const d3d11::GeometryShader &getStreamOutShader() const; - const d3d11::ComputeShader &getComputeShader() const; private: d3d11::PixelShader mPixelExecutable; d3d11::VertexShader mVertexExecutable; d3d11::GeometryShader mGeometryExecutable; d3d11::GeometryShader mStreamOutExecutable; - d3d11::ComputeShader mComputeExecutable; }; class UniformStorage11 : public UniformStorageD3D diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp index 2dfa743313b..1465d7a5dbc 100644 --- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -6,6 +6,10 @@ // StateManager11.cpp: Defines a class for caching D3D11 state +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/StateManager11.h" #include "common/angleutils.h" @@ -102,47 +106,6 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR return false; } -bool ImageIndexConflictsWithUAV(const gl::ImageIndex &index, D3D11_UNORDERED_ACCESS_VIEW_DESC desc) -{ - unsigned mipLevel = index.getLevelIndex(); - gl::TextureType textureType = index.getType(); - - switch (desc.ViewDimension) - { - case D3D11_UAV_DIMENSION_TEXTURE2D: - { - return textureType == gl::TextureType::_2D && mipLevel == desc.Texture2D.MipSlice; - } - - case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: - { - GLint layerIndex = index.getLayerIndex(); - unsigned mipSlice = desc.Texture2DArray.MipSlice; - unsigned firstArraySlice = desc.Texture2DArray.FirstArraySlice; - unsigned lastArraySlice = firstArraySlice + desc.Texture2DArray.ArraySize; - - return (textureType == gl::TextureType::_2DArray || - textureType == gl::TextureType::CubeMap) && - (mipLevel == mipSlice && gl::RangeUI(firstArraySlice, lastArraySlice) - .contains(static_cast(layerIndex))); - } - - case D3D11_UAV_DIMENSION_TEXTURE3D: - { - GLint layerIndex = index.getLayerIndex(); - unsigned mipSlice = desc.Texture3D.MipSlice; - unsigned firstWSlice = desc.Texture3D.FirstWSlice; - unsigned lastWSlice = firstWSlice + desc.Texture3D.WSize; - - return textureType == gl::TextureType::_3D && - (mipLevel == mipSlice && - gl::RangeUI(firstWSlice, lastWSlice).contains(static_cast(layerIndex))); - } - default: - return false; - } -} - // Does *not* increment the resource ref count!! ID3D11Resource *GetViewResource(ID3D11View *view) { @@ -295,8 +258,6 @@ void ShaderConstants11::init(const gl::Caps &caps) for (gl::ShaderType shaderType : gl::AllShaderTypes()) { mShaderSamplerMetadata[shaderType].resize(caps.maxShaderTextureImageUnits[shaderType]); - mShaderReadonlyImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]); - mShaderImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]); } } @@ -308,8 +269,6 @@ size_t ShaderConstants11::GetShaderConstantsStructSize(gl::ShaderType shaderType return sizeof(Vertex); case gl::ShaderType::Fragment: return sizeof(Pixel); - case gl::ShaderType::Compute: - return sizeof(Compute); // TODO(jiawei.shao@intel.com): return geometry shader constant struct size case gl::ShaderType::Geometry: @@ -325,9 +284,7 @@ size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const { ASSERT(shaderType != gl::ShaderType::InvalidEnum); return GetShaderConstantsStructSize(shaderType) + - mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata) + - mShaderImageMetadata[shaderType].size() * sizeof(ImageMetadata) + - mShaderReadonlyImageMetadata[shaderType].size() * sizeof(ImageMetadata); + mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata); } void ShaderConstants11::markDirty() @@ -405,35 +362,6 @@ bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, return dirty; } -bool ShaderConstants11::updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit) -{ - bool dirty = false; - - if (data->layer != static_cast(imageUnit.layer)) - { - data->layer = static_cast(imageUnit.layer); - dirty = true; - } - - if (data->level != static_cast(imageUnit.level)) - { - data->level = static_cast(imageUnit.level); - dirty = true; - } - - return dirty; -} - -void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ) -{ - mCompute.numWorkGroups[0] = numGroupsX; - mCompute.numWorkGroups[1] = numGroupsY; - mCompute.numWorkGroups[2] = numGroupsZ; - mShaderConstantsDirty.set(gl::ShaderType::Compute); -} - void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport, const D3D11_VIEWPORT &dxViewport, const gl::Offset &glFragCoordOffset, @@ -521,31 +449,6 @@ void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType, } } -bool ShaderConstants11::onImageChange(gl::ShaderType shaderType, - unsigned int imageIndex, - const gl::ImageUnit &imageUnit) -{ - ASSERT(shaderType != gl::ShaderType::InvalidEnum); - bool dirty = false; - if (imageUnit.access == GL_READ_ONLY) - { - if (updateImageMetadata(&mShaderReadonlyImageMetadata[shaderType][imageIndex], imageUnit)) - { - mNumActiveShaderReadonlyImages[shaderType] = 0; - dirty = true; - } - } - else - { - if (updateImageMetadata(&mShaderImageMetadata[shaderType][imageIndex], imageUnit)) - { - mNumActiveShaderImages[shaderType] = 0; - dirty = true; - } - } - return dirty; -} - void ShaderConstants11::onClipOriginChange(bool lowerLeft) { mVertex.clipControlOrigin = lowerLeft ? -1.0f : 1.0f; @@ -596,29 +499,17 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, { // Re-upload the sampler meta-data if the current program uses more samplers // than we previously uploaded. - const int numSamplers = executableD3D.getUsedSamplerRange(shaderType).length(); - const int numReadonlyImages = executableD3D.getUsedImageRange(shaderType, true).length(); - const int numImages = executableD3D.getUsedImageRange(shaderType, false).length(); + const int numSamplers = executableD3D.getUsedSamplerRange(shaderType).length(); - const bool dirty = mShaderConstantsDirty[shaderType] || - (mNumActiveShaderSamplers[shaderType] < numSamplers) || - (mNumActiveShaderReadonlyImages[shaderType] < numReadonlyImages) || - (mNumActiveShaderImages[shaderType] < numImages); + const bool dirty = + mShaderConstantsDirty[shaderType] || (mNumActiveShaderSamplers[shaderType] < numSamplers); const size_t dataSize = GetShaderConstantsStructSize(shaderType); const uint8_t *samplerData = reinterpret_cast(mShaderSamplerMetadata[shaderType].data()); const size_t samplerDataSize = sizeof(SamplerMetadata) * numSamplers; - const uint8_t *readonlyImageData = - reinterpret_cast(mShaderReadonlyImageMetadata[shaderType].data()); - const size_t readonlyImageDataSize = sizeof(ImageMetadata) * numReadonlyImages; - const uint8_t *imageData = - reinterpret_cast(mShaderImageMetadata[shaderType].data()); - const size_t imageDataSize = sizeof(ImageMetadata) * numImages; - - mNumActiveShaderSamplers[shaderType] = numSamplers; - mNumActiveShaderReadonlyImages[shaderType] = numReadonlyImages; - mNumActiveShaderImages[shaderType] = numImages; + + mNumActiveShaderSamplers[shaderType] = numSamplers; mShaderConstantsDirty.set(shaderType, false); const uint8_t *data = nullptr; @@ -630,9 +521,6 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, case gl::ShaderType::Fragment: data = reinterpret_cast(&mPixel); break; - case gl::ShaderType::Compute: - data = reinterpret_cast(&mCompute); - break; default: UNREACHABLE(); break; @@ -651,14 +539,8 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, 0, &mapping)); memcpy(mapping.pData, data, dataSize); - memcpy(static_cast(mapping.pData) + dataSize, samplerData, - sizeof(SamplerMetadata) * numSamplers); - - memcpy(static_cast(mapping.pData) + dataSize + samplerDataSize, readonlyImageData, - readonlyImageDataSize); - memcpy( - static_cast(mapping.pData) + dataSize + samplerDataSize + readonlyImageDataSize, - imageData, imageDataSize); + memcpy(static_cast(mapping.pData) + dataSize, samplerData, samplerDataSize); + renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0); return angle::Result::Continue; @@ -740,19 +622,8 @@ StateManager11::StateManager11(Renderer11 *renderer) mInternalDirtyBits.set(); mInternalDirtyBits.reset(DIRTY_BIT_GRAPHICS_SRV_STATE); mInternalDirtyBits.reset(DIRTY_BIT_GRAPHICS_UAV_STATE); - mInternalDirtyBits.reset(DIRTY_BIT_COMPUTE_SRV_STATE); - mInternalDirtyBits.reset(DIRTY_BIT_COMPUTE_UAV_STATE); mGraphicsDirtyBitsMask.set(); - mGraphicsDirtyBitsMask.reset(DIRTY_BIT_COMPUTE_SRV_STATE); - mGraphicsDirtyBitsMask.reset(DIRTY_BIT_COMPUTE_UAV_STATE); - mComputeDirtyBitsMask.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); - mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORMS); - mComputeDirtyBitsMask.set(DIRTY_BIT_DRIVER_UNIFORMS); - mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS); - mComputeDirtyBitsMask.set(DIRTY_BIT_SHADERS); - mComputeDirtyBitsMask.set(DIRTY_BIT_COMPUTE_SRV_STATE); - mComputeDirtyBitsMask.set(DIRTY_BIT_COMPUTE_UAV_STATE); // Initially all current value attributes must be updated on first use. mDirtyCurrentValueAttribs.set(); @@ -777,12 +648,6 @@ void StateManager11::setShaderResourceInternal(gl::ShaderType shaderType, { ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr; - if (srvPtr) - { - uintptr_t resource = reinterpret_cast(GetViewResource(srvPtr)); - unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute, - resource, nullptr); - } switch (shaderType) { @@ -792,16 +657,6 @@ void StateManager11::setShaderResourceInternal(gl::ShaderType shaderType, case gl::ShaderType::Fragment: deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr); break; - case gl::ShaderType::Compute: - { - if (srvPtr) - { - uintptr_t resource = reinterpret_cast(GetViewResource(srvPtr)); - unsetConflictingRTVs(resource); - } - deviceContext->CSSetShaderResources(resourceSlot, 1, &srvPtr); - break; - } default: UNREACHABLE(); } @@ -815,31 +670,11 @@ void StateManager11::setUnorderedAccessViewInternal(UINT resourceSlot, const UAVType *uav, UAVList *uavList) { - ASSERT(static_cast(resourceSlot) < mCurComputeUAVs.size()); - const ViewRecord &record = mCurComputeUAVs[resourceSlot]; - - if (record.view != reinterpret_cast(uav)) + ID3D11UnorderedAccessView *uavPtr = uav ? uav->get() : nullptr; + uavList->data[resourceSlot] = uavPtr; + if (static_cast(resourceSlot) > uavList->highestUsed) { - ID3D11UnorderedAccessView *uavPtr = uav ? uav->get() : nullptr; - // We need to make sure that resource being set to UnorderedAccessView slot |resourceSlot| - // is not bound on SRV. - if (uavPtr) - { - uintptr_t resource = reinterpret_cast(GetViewResource(uavPtr)); - unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Vertex, - resource, nullptr, false); - unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Fragment, - resource, nullptr, false); - unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Compute, - resource, nullptr, false); - } - uavList->data[resourceSlot] = uavPtr; - if (static_cast(resourceSlot) > uavList->highestUsed) - { - uavList->highestUsed = resourceSlot; - } - - mCurComputeUAVs.update(resourceSlot, uavPtr); + uavList->highestUsed = resourceSlot; } } @@ -881,67 +716,6 @@ void StateManager11::checkPresentPath(const gl::Context *context) } } -angle::Result StateManager11::updateStateForCompute(const gl::Context *context, - GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ) -{ - mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ); - - if (mExecutableD3D->isSamplerMappingDirty()) - { - mExecutableD3D->updateSamplerMapping(); - invalidateTexturesAndSamplers(); - } - - if (mDirtySwizzles) - { - ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute)); - mDirtySwizzles = false; - } - - if (mExecutableD3D->anyShaderUniformsDirty()) - { - mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); - } - - auto dirtyBitsCopy = mInternalDirtyBits & mComputeDirtyBitsMask; - mInternalDirtyBits &= ~mComputeDirtyBitsMask; - - for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter) - { - switch (*iter) - { - case DIRTY_BIT_COMPUTE_SRV_STATE: - // Avoid to call syncTexturesForCompute function two times. - iter.resetLaterBit(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); - ANGLE_TRY(syncTexturesForCompute(context)); - break; - case DIRTY_BIT_COMPUTE_UAV_STATE: - ANGLE_TRY(syncUAVsForCompute(context)); - break; - case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE: - ANGLE_TRY(syncTexturesForCompute(context)); - break; - case DIRTY_BIT_PROGRAM_UNIFORMS: - case DIRTY_BIT_DRIVER_UNIFORMS: - ANGLE_TRY(applyComputeUniforms(context, mExecutableD3D)); - break; - case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS: - ANGLE_TRY(syncUniformBuffers(context)); - break; - case DIRTY_BIT_SHADERS: - ANGLE_TRY(syncProgramForCompute(context)); - break; - default: - UNREACHABLE(); - break; - } - } - - return angle::Result::Continue; -} - void StateManager11::syncState(const gl::Context *context, const gl::state::DirtyBits &dirtyBits, const gl::state::ExtendedDirtyBits &extendedDirtyBits, @@ -1152,10 +926,8 @@ void StateManager11::syncState(const gl::Context *context, invalidateProgramUniformBuffers(); break; case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING: - invalidateProgramAtomicCounterBuffers(); break; case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING: - invalidateProgramShaderStorageBuffers(); break; case gl::state::DIRTY_BIT_TEXTURE_BINDINGS: invalidateTexturesAndSamplers(); @@ -1181,26 +953,22 @@ void StateManager11::syncState(const gl::Context *context, invalidateTexturesAndSamplers(); invalidateProgramUniforms(); invalidateProgramUniformBuffers(); - invalidateProgramAtomicCounterBuffers(); - invalidateProgramShaderStorageBuffers(); invalidateDriverUniforms(); + mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE); const gl::ProgramExecutable *executable = state.getProgramExecutable(); ASSERT(executable); mExecutableD3D = GetImplAs(executable); - if (!executable || command != gl::Command::Dispatch) + mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY); + invalidateVertexBuffer(); + invalidateRenderTarget(); + // If OVR_multiview is enabled, the attribute divisor has to be updated for + // each binding. + if (mIsMultiviewEnabled && mVertexArray11) { - mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY); - invalidateVertexBuffer(); - invalidateRenderTarget(); - // If OVR_multiview2 is enabled, the attribute divisor has to be updated for - // each binding. When using compute, there could be no vertex array. - if (mIsMultiviewEnabled && mVertexArray11) - { - ASSERT(mExecutableD3D); - ASSERT(mVertexArray11 == GetImplAs(state.getVertexArray())); - int numViews = executable->usesMultiview() ? executable->getNumViews() : 1; - mVertexArray11->markAllAttributeDivisorsForAdjustment(numViews); - } + ASSERT(mExecutableD3D); + ASSERT(mVertexArray11 == GetImplAs(state.getVertexArray())); + int numViews = executable->usesMultiview() ? executable->getNumViews() : 1; + mVertexArray11->markAllAttributeDivisorsForAdjustment(numViews); } break; } @@ -1256,6 +1024,8 @@ void StateManager11::syncState(const gl::Context *context, mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; + case gl::state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED: + break; } } break; @@ -1672,25 +1442,11 @@ void StateManager11::invalidateProgramUniformBuffers() mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS); } -void StateManager11::invalidateProgramAtomicCounterBuffers() -{ - mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE); - mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE); -} - -void StateManager11::invalidateProgramShaderStorageBuffers() -{ - mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE); - mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE); -} - void StateManager11::invalidateImageBindings() { mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_SRV_STATE); mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE); - mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRV_STATE); - mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE); mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); } @@ -1830,8 +1586,6 @@ void StateManager11::unsetConflictingView(gl::PipelineType pipeline, unsetConflictingSRVs(pipeline, gl::ShaderType::Vertex, resource, nullptr, isRenderTarget); unsetConflictingSRVs(pipeline, gl::ShaderType::Fragment, resource, nullptr, isRenderTarget); - unsetConflictingSRVs(pipeline, gl::ShaderType::Compute, resource, nullptr, isRenderTarget); - unsetConflictingUAVs(pipeline, gl::ShaderType::Compute, resource, nullptr); } void StateManager11::unsetConflictingSRVs(gl::PipelineType pipeline, @@ -1864,45 +1618,12 @@ void StateManager11::unsetConflictingSRVs(gl::PipelineType pipeline, case gl::PipelineType::GraphicsPipeline: mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_SRV_STATE); break; - case gl::PipelineType::ComputePipeline: - mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRV_STATE); - break; default: UNREACHABLE(); } } } -void StateManager11::unsetConflictingUAVs(gl::PipelineType pipeline, - gl::ShaderType shaderType, - uintptr_t resource, - const gl::ImageIndex *index) -{ - ASSERT(shaderType == gl::ShaderType::Compute); - bool foundOne = false; - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - size_t count = std::min(mCurComputeUAVs.size(), mCurComputeUAVs.highestUsed() + 1); - for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex) - { - auto &record = mCurComputeUAVs[resourceIndex]; - - if (record.view && record.resource == resource && - (!index || ImageIndexConflictsWithUAV(*index, record.desc))) - { - deviceContext->CSSetUnorderedAccessViews(static_cast(resourceIndex), 1, - &mNullUAVs[0], nullptr); - mCurComputeUAVs.update(resourceIndex, nullptr); - foundOne = true; - } - } - - if (foundOne && pipeline == gl::PipelineType::GraphicsPipeline) - { - mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE); - } -} - template void StateManager11::unsetConflictingRTVs(uintptr_t resource, CacheType &viewCache) { @@ -1945,10 +1666,6 @@ void StateManager11::unsetConflictingAttachmentResources( resourcePtr, &index, false); unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment, resourcePtr, &index, false); - unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute, - resourcePtr, &index, false); - unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute, - resourcePtr, &index); } else if (attachment.type() == GL_FRAMEBUFFER_DEFAULT) { @@ -1957,10 +1674,6 @@ void StateManager11::unsetConflictingAttachmentResources( resourcePtr, nullptr, false); unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment, resourcePtr, nullptr, false); - unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute, - resourcePtr, nullptr, false); - unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute, - resourcePtr, nullptr); } } @@ -1982,7 +1695,6 @@ angle::Result StateManager11::ensureInitialized(const gl::Context *context) } mCurRTVs.initialize(caps.maxColorAttachments); mCurrentDSV.initialize(1); - mCurComputeUAVs.initialize(caps.maxImageUnits); // Initialize cached NULL SRV block mNullSRVs.resize(caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment], nullptr); @@ -1993,7 +1705,7 @@ angle::Result StateManager11::ensureInitialized(const gl::Context *context) mShaderConstants.init(caps); - mIsMultiviewEnabled = extensions.multiviewOVR || extensions.multiview2OVR; + mIsMultiviewEnabled = extensions.multiviewOVR; mIndependentBlendStates = extensions.drawBuffersIndexedAny(); // requires FL10_1 @@ -2142,6 +1854,8 @@ angle::Result StateManager11::syncCurrentValueAttribs( currentValueAttrib->currentValueType = currentValue.Type; currentValueAttrib->attribute = attrib; currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex]; + currentValueAttrib->bufferBindingPointer = + &mVertexArray11->getBufferBindingPointer(attrib->bindingIndex); mDirtyVertexBufferRange.extend(static_cast(attribIndex)); @@ -2407,8 +2121,7 @@ angle::Result StateManager11::updateState(const gl::Context *context, } } - // Check that we haven't set any dirty bits in the flushing of the dirty bits loop, except - // DIRTY_BIT_COMPUTE_SRVUAV_STATE dirty bit. + // Check that we haven't set any dirty bits in the flushing of the dirty bits loop. ASSERT((mInternalDirtyBits & mGraphicsDirtyBitsMask).none()); return angle::Result::Continue; @@ -2504,19 +2217,6 @@ void StateManager11::setPixelShader(const d3d11::PixelShader *shader) } } -void StateManager11::setComputeShader(const d3d11::ComputeShader *shader) -{ - ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); - - if (serial != mAppliedShaders[gl::ShaderType::Compute]) - { - ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr; - mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0); - mAppliedShaders[gl::ShaderType::Compute] = serial; - invalidateShaders(); - } -} - void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) { ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -2741,9 +2441,6 @@ angle::Result StateManager11::setSamplerState(const gl::Context *context, case gl::ShaderType::Fragment: deviceContext->PSSetSamplers(index, 1, &dxSamplerState); break; - case gl::ShaderType::Compute: - deviceContext->CSSetSamplers(index, 1, &dxSamplerState); - break; case gl::ShaderType::Geometry: deviceContext->GSSetSamplers(index, 1, &dxSamplerState); break; @@ -2760,7 +2457,7 @@ angle::Result StateManager11::setSamplerState(const gl::Context *context, // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the // sampler state since having it in contiguous memory makes it possible to memcpy to a constant // buffer, and it doesn't affect the state set by - // PSSetSamplers/VSSetSamplers/CSSetSamplers/GSSetSamplers. + // PSSetSamplers/VSSetSamplers/GSSetSamplers. mShaderConstants.onSamplerChange(type, index, *texture, samplerState); return angle::Result::Continue; @@ -2800,29 +2497,12 @@ angle::Result StateManager11::setTextureForSampler(const gl::Context *context, (type == gl::ShaderType::Fragment && index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) || (type == gl::ShaderType::Vertex && - index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) || - (type == gl::ShaderType::Compute && - index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute])); + index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex])); setShaderResourceInternal(type, index, textureSRV); return angle::Result::Continue; } -angle::Result StateManager11::setImageState(const gl::Context *context, - gl::ShaderType type, - int index, - const gl::ImageUnit &imageUnit) -{ - ASSERT(index < mRenderer->getNativeCaps().maxShaderImageUniforms[type]); - - if (mShaderConstants.onImageChange(type, index, imageUnit)) - { - invalidateDriverUniforms(); - } - - return angle::Result::Continue; -} - // For each Direct3D sampler of either the pixel or vertex stage, // looks up the corresponding OpenGL texture image unit and texture type, // and sets the texture and its addressing/filtering state (or NULL when inactive). @@ -2882,11 +2562,6 @@ angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context, mExecutableD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps); ASSERT(imageUnitIndex != -1); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); - if (!imageUnit.layered) - { - ANGLE_TRY(setImageState(context, gl::ShaderType::Compute, - readonlyImageIndex - readonlyImageRange.low(), imageUnit)); - } ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, imageUnit)); } @@ -2906,22 +2581,12 @@ angle::Result StateManager11::getUAVsForRWImages(const gl::Context *context, GLint imageUnitIndex = mExecutableD3D->getImageMapping(shaderType, imageIndex, false, caps); ASSERT(imageUnitIndex != -1); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); - if (!imageUnit.layered) - { - ANGLE_TRY(setImageState(context, shaderType, imageIndex - imageRange.low(), imageUnit)); - } ANGLE_TRY(getUAVForRWImage(context, shaderType, imageIndex, imageUnit, uavList)); } return angle::Result::Continue; } -angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context) -{ - ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute)); - return angle::Result::Continue; -} - angle::Result StateManager11::setTextureForImage(const gl::Context *context, gl::ShaderType type, int index, @@ -3065,29 +2730,6 @@ angle::Result StateManager11::syncProgram(const gl::Context *context, gl::Primit return angle::Result::Continue; } -angle::Result StateManager11::syncProgramForCompute(const gl::Context *context) -{ - Context11 *context11 = GetImplAs(context); - ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context)); - - mExecutableD3D->updateCachedImage2DBindLayout(context, gl::ShaderType::Compute); - - // Binaries must be compiled before the sync. - ASSERT(mExecutableD3D->hasComputeExecutableForCachedImage2DBindLayout()); - - ShaderExecutableD3D *computeExe = nullptr; - ANGLE_TRY(mExecutableD3D->getComputeExecutableForImage2DBindLayout( - context11, context11->getRenderer(), &computeExe, nullptr)); - - const d3d11::ComputeShader *computeShader = - (computeExe ? &GetAs(computeExe)->getComputeShader() : nullptr); - setComputeShader(computeShader); - // Explicitly clear the shaders dirty bit. - mInternalDirtyBits.reset(DIRTY_BIT_SHADERS); - - return angle::Result::Continue; -} - angle::Result StateManager11::syncVertexBuffersAndInputLayout( const gl::Context *context, gl::PrimitiveMode mode, @@ -3162,8 +2804,10 @@ angle::Result StateManager11::applyVertexBuffers(const gl::Context *context, } else { + BufferFeedback feedback; ANGLE_TRY(bufferStorage->getBuffer( - context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer)); + context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer, &feedback)); + attrib.bufferBindingPointer->get()->applyImplFeedback(context, feedback); } vertexStride = attrib.stride; @@ -3189,7 +2833,7 @@ angle::Result StateManager11::applyIndexBuffer(const gl::Context *context, } gl::DrawElementsType destElementType = mVertexArray11->getCachedDestinationIndexType(); - gl::Buffer *elementArrayBuffer = mVertexArray11->getState().getElementArrayBuffer(); + gl::Buffer *elementArrayBuffer = mVertexArray11->getElementArrayBuffer(); TranslatedIndexData indexInfo; ANGLE_TRY(mIndexDataManager.prepareIndexData(context, indexType, destElementType, indexCount, @@ -3203,7 +2847,9 @@ angle::Result StateManager11::applyIndexBuffer(const gl::Context *context, if (indexInfo.storage) { Buffer11 *storage = GetAs(indexInfo.storage); - ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer)); + BufferFeedback feedback; + ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer, &feedback)); + elementArrayBuffer->applyImplFeedback(context, feedback); } else { @@ -3475,54 +3121,6 @@ angle::Result StateManager11::applyDriverUniforms(const gl::Context *context) return angle::Result::Continue; } -angle::Result StateManager11::applyComputeUniforms(const gl::Context *context, - ProgramExecutableD3D *executableD3D) -{ - UniformStorage11 *computeUniformStorage = - GetAs(executableD3D->getShaderUniformStorage(gl::ShaderType::Compute)); - ASSERT(computeUniformStorage); - - const d3d11::Buffer *constantBuffer = nullptr; - ANGLE_TRY(computeUniformStorage->getConstantBuffer(context, mRenderer, &constantBuffer)); - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - if (computeUniformStorage->size() > 0 && - executableD3D->areShaderUniformsDirty(gl::ShaderType::Compute)) - { - UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer); - executableD3D->markUniformsClean(); - } - - if (mCurrentComputeConstantBuffer != constantBuffer->getSerial()) - { - deviceContext->CSSetConstantBuffers( - d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, - constantBuffer->getPointer()); - mCurrentComputeConstantBuffer = constantBuffer->getSerial(); - } - - if (!mShaderDriverConstantBuffers[gl::ShaderType::Compute].valid()) - { - size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::ShaderType::Compute); - - D3D11_BUFFER_DESC constantBufferDescription = {}; - d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); - ANGLE_TRY( - mRenderer->allocateResource(GetImplAs(context), constantBufferDescription, - &mShaderDriverConstantBuffers[gl::ShaderType::Compute])); - ID3D11Buffer *buffer = mShaderDriverConstantBuffers[gl::ShaderType::Compute].get(); - deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, - &buffer); - } - - ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, gl::ShaderType::Compute, - *executableD3D, - mShaderDriverConstantBuffers[gl::ShaderType::Compute])); - - return angle::Result::Continue; -} - angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *context, gl::ShaderType shaderType) { @@ -3554,10 +3152,12 @@ angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *con UINT firstConstant = 0; UINT numConstants = 0; + BufferFeedback feedback; ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, uniformBufferSize, &constantBuffer, - &firstConstant, &numConstants)); + &firstConstant, &numConstants, &feedback)); ASSERT(constantBuffer); + uniformBuffer.get()->applyImplFeedback(context, feedback); switch (shaderType) { @@ -3616,33 +3216,6 @@ angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *con break; } - case gl::ShaderType::Compute: - { - if (mCurrentConstantBufferCS[bufferIndex] == constantBuffer->getSerial() && - mCurrentConstantBufferCSOffset[bufferIndex] == uniformBufferOffset && - mCurrentConstantBufferCSSize[bufferIndex] == uniformBufferSize) - { - continue; - } - - if (firstConstant != 0 && uniformBufferSize != 0) - { - deviceContext1->CSSetConstantBuffers1(cache.registerIndex, 1, - constantBuffer->getPointer(), - &firstConstant, &numConstants); - } - else - { - deviceContext->CSSetConstantBuffers(cache.registerIndex, 1, - constantBuffer->getPointer()); - } - - mCurrentConstantBufferCS[cache.registerIndex] = constantBuffer->getSerial(); - mCurrentConstantBufferCSOffset[cache.registerIndex] = uniformBufferOffset; - mCurrentConstantBufferCSSize[cache.registerIndex] = uniformBufferSize; - break; - } - // TODO(jiawei.shao@intel.com): update geometry shader uniform buffers. case gl::ShaderType::Geometry: UNIMPLEMENTED(); @@ -3672,9 +3245,11 @@ angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *con Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); const d3d11::ShaderResourceView *bufferSRV = nullptr; + BufferFeedback feedback; ANGLE_TRY(bufferStorage->getStructuredBufferRangeSRV( context, static_cast(uniformBufferOffset), cache.byteWidth, - cache.structureByteStride, &bufferSRV)); + cache.structureByteStride, &bufferSRV, &feedback)); + uniformBuffer.get()->applyImplFeedback(context, feedback); ASSERT(bufferSRV->valid()); setShaderResourceInternal(shaderType, cache.registerIndex, bufferSRV); @@ -3683,126 +3258,15 @@ angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *con return angle::Result::Continue; } -angle::Result StateManager11::getUAVsForShaderStorageBuffers(const gl::Context *context, - gl::ShaderType shaderType, - UAVList *uavList) -{ - const gl::State &glState = context->getState(); - const gl::ProgramExecutable *executable = glState.getProgramExecutable(); - angle::FixedVector - previouslyBound; - for (size_t blockIndex = 0; blockIndex < executable->getShaderStorageBlocks().size(); - blockIndex++) - { - GLuint binding = executable->getShaderStorageBlockBinding(static_cast(blockIndex)); - const unsigned int registerIndex = mExecutableD3D->getShaderStorageBufferRegisterIndex( - static_cast(blockIndex), shaderType); - // It means this block is active but not statically used. - if (registerIndex == GL_INVALID_INDEX) - { - continue; - } - const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding); - if (shaderStorageBuffer.get() == nullptr) - { - // We didn't see a driver error like atomic buffer did. But theoretically, the same - // thing should be done. - setUnorderedAccessViewInternal(registerIndex, nullptr, - uavList); - continue; - } - - Buffer11 *bufferStorage = GetImplAs(shaderStorageBuffer.get()); - if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) != - previouslyBound.end()) - { - // D3D11 doesn't support binding a buffer multiple times - // http://anglebug.com/42261718 - ERR() << "Writing to multiple blocks on the same buffer is not allowed."; - return angle::Result::Stop; - } - previouslyBound.push_back(bufferStorage); - - d3d11::UnorderedAccessView *uavPtr = nullptr; - GLsizeiptr viewSize = 0; - // Bindings only have a valid size if bound using glBindBufferRange - if (shaderStorageBuffer.getSize() > 0) - { - viewSize = shaderStorageBuffer.getSize(); - } - // We use the buffer size for glBindBufferBase - else - { - viewSize = bufferStorage->getSize(); - } - ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize, - &uavPtr)); - - setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList); - } - - return angle::Result::Continue; -} - angle::Result StateManager11::syncUniformBuffers(const gl::Context *context) { mExecutableD3D->updateUniformBufferCache(context->getCaps()); - if (mExecutableD3D->hasShaderStage(gl::ShaderType::Compute)) - { - ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Compute)); - } - else + ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex)); + ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment)); + if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry)) { - ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex)); - ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment)); - if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry)) - { - ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry)); - } - } - - return angle::Result::Continue; -} - -angle::Result StateManager11::getUAVsForAtomicCounterBuffers(const gl::Context *context, - gl::ShaderType shaderType, - UAVList *uavList) -{ - const gl::State &glState = context->getState(); - const gl::ProgramExecutable *executable = glState.getProgramExecutable(); - const std::vector &atomicCounterBuffers = - executable->getAtomicCounterBuffers(); - for (size_t index = 0; index < atomicCounterBuffers.size(); ++index) - { - const GLuint binding = executable->getAtomicCounterBufferBinding(index); - const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding); - const unsigned int registerIndex = - mExecutableD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType); - ASSERT(registerIndex != GL_INVALID_INDEX); - if (buffer.get() == nullptr) - { - // The atomic counter is used in shader. However, there is no buffer binding to it. We - // should clear the corresponding UAV in case the previous view type is a texture not a - // buffer. Otherwise, below error will be reported. The Unordered Access View dimension - // declared in the shader code (BUFFER) does not match the view type bound to slot 0 - // of the Compute Shader unit (TEXTURE2D). - setUnorderedAccessViewInternal(registerIndex, nullptr, - uavList); - continue; - } - - Buffer11 *bufferStorage = GetImplAs(buffer.get()); - // TODO(enrico.galli@intel.com): Check to make sure that we aren't binding the same buffer - // multiple times, as this is unsupported by D3D11. http://anglebug.com/42261818 - - // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the - // buffer size for glBindBufferBase - GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize(); - d3d11::UnorderedAccessView *uavPtr = nullptr; - ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr)); - - setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList); + ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry)); } return angle::Result::Continue; @@ -3812,9 +3276,7 @@ angle::Result StateManager11::getUAVsForShader(const gl::Context *context, gl::ShaderType shaderType, UAVList *uavList) { - ANGLE_TRY(getUAVsForShaderStorageBuffers(context, shaderType, uavList)); ANGLE_TRY(getUAVsForRWImages(context, shaderType, uavList)); - ANGLE_TRY(getUAVsForAtomicCounterBuffers(context, shaderType, uavList)); return angle::Result::Continue; } @@ -3838,22 +3300,6 @@ angle::Result StateManager11::syncUAVsForGraphics(const gl::Context *context) return angle::Result::Continue; } -angle::Result StateManager11::syncUAVsForCompute(const gl::Context *context) -{ - UAVList uavList(mRenderer->getNativeCaps().maxImageUnits); - - ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Compute, &uavList)); - - if (uavList.highestUsed >= 0) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->CSSetUnorderedAccessViews(0, uavList.highestUsed + 1, uavList.data.data(), - nullptr); - } - - return angle::Result::Continue; -} - angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context) { const auto &glState = context->getState(); diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h index 972f6d155ef..0e02a8f3aef 100644 --- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h +++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -38,7 +38,6 @@ class ShaderConstants11 : angle::NonCopyable size_t getRequiredBufferSize(gl::ShaderType shaderType) const; void markDirty(); - void setComputeWorkGroups(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ); void onViewportChange(const gl::Rectangle &glViewport, const D3D11_VIEWPORT &dxViewport, const gl::Offset &glFragCoordOffset, @@ -50,9 +49,6 @@ class ShaderConstants11 : angle::NonCopyable unsigned int samplerIndex, const gl::Texture &texture, const gl::SamplerState &samplerState); - bool onImageChange(gl::ShaderType shaderType, - unsigned int imageIndex, - const gl::ImageUnit &imageUnit); void onClipOriginChange(bool lowerLeft); bool onClipDepthModeChange(bool zeroToOne); bool onClipDistancesEnabledChange(const uint32_t value); @@ -124,13 +120,6 @@ class ShaderConstants11 : angle::NonCopyable static constexpr uint32_t kPixelMiscMultisamplingMask = 0x1; static_assert(sizeof(Pixel) % 16u == 0, "D3D11 constant buffers must be multiples of 16 bytes"); - struct Compute - { - Compute() : numWorkGroups{0u}, padding(0u) {} - unsigned int numWorkGroups[3]; - unsigned int padding; // This just pads the struct to 16 bytes - }; - struct SamplerMetadata { SamplerMetadata() : baseLevel(0), wrapModes(0), padding{0}, intBorderColor{0} {} @@ -144,17 +133,6 @@ class ShaderConstants11 : angle::NonCopyable static_assert(sizeof(SamplerMetadata) == 32u, "Sampler metadata struct must be two 4-vec --> 32 bytes."); - struct ImageMetadata - { - ImageMetadata() : layer(0), level(0), padding{0} {} - - int layer; - unsigned int level; - int padding[2]; // This just pads the struct to 16 bytes - }; - static_assert(sizeof(ImageMetadata) == 16u, - "Image metadata struct must be one 4-vec --> 16 bytes."); - static size_t GetShaderConstantsStructSize(gl::ShaderType shaderType); // Return true if dirty. @@ -162,20 +140,12 @@ class ShaderConstants11 : angle::NonCopyable const gl::Texture &texture, const gl::SamplerState &samplerState); - // Return true if dirty. - bool updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit); - Vertex mVertex; Pixel mPixel; - Compute mCompute; gl::ShaderBitSet mShaderConstantsDirty; gl::ShaderMap> mShaderSamplerMetadata; gl::ShaderMap mNumActiveShaderSamplers; - gl::ShaderMap> mShaderReadonlyImageMetadata; - gl::ShaderMap mNumActiveShaderReadonlyImages; - gl::ShaderMap> mShaderImageMetadata; - gl::ShaderMap mNumActiveShaderImages; }; class StateManager11 final : angle::NonCopyable @@ -191,11 +161,6 @@ class StateManager11 final : angle::NonCopyable const gl::state::ExtendedDirtyBits &extendedDirtyBits, gl::Command command); - angle::Result updateStateForCompute(const gl::Context *context, - GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ); - void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); // These invalidations methods are called externally. @@ -273,7 +238,6 @@ class StateManager11 final : angle::NonCopyable void setVertexShader(const d3d11::VertexShader *shader); void setGeometryShader(const d3d11::GeometryShader *shader); void setPixelShader(const d3d11::PixelShader *shader); - void setComputeShader(const d3d11::ComputeShader *shader); void setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer); void setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer); void setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, UINT stencilRef); @@ -292,10 +256,6 @@ class StateManager11 final : angle::NonCopyable GLint startVertex, GLsizei emulatedInstanceId); - // TODO(jmadill): Should be private. - angle::Result applyComputeUniforms(const gl::Context *context, - ProgramExecutableD3D *executableD3D); - // Only used in testing. InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } @@ -328,10 +288,6 @@ class StateManager11 final : angle::NonCopyable uintptr_t resource, const gl::ImageIndex *index, bool isRenderTarget); - void unsetConflictingUAVs(gl::PipelineType pipeline, - gl::ShaderType shaderType, - uintptr_t resource, - const gl::ImageIndex *index); template void unsetConflictingRTVs(uintptr_t resource, CacheType &viewCache); @@ -360,12 +316,10 @@ class StateManager11 final : angle::NonCopyable angle::Result syncFramebuffer(const gl::Context *context); angle::Result syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode); - angle::Result syncProgramForCompute(const gl::Context *context); angle::Result syncTextures(const gl::Context *context); angle::Result applyTexturesForSRVs(const gl::Context *context, gl::ShaderType shaderType); angle::Result applyTexturesForUAVs(const gl::Context *context, gl::ShaderType shaderType); - angle::Result syncTexturesForCompute(const gl::Context *context); angle::Result setSamplerState(const gl::Context *context, gl::ShaderType type, @@ -377,10 +331,6 @@ class StateManager11 final : angle::NonCopyable int index, gl::Texture *texture, const gl::SamplerState &sampler); - angle::Result setImageState(const gl::Context *context, - gl::ShaderType type, - int index, - const gl::ImageUnit &imageUnit); angle::Result setTextureForImage(const gl::Context *context, gl::ShaderType type, int index, @@ -408,29 +358,19 @@ class StateManager11 final : angle::NonCopyable angle::Result applyUniforms(const gl::Context *context); angle::Result applyUniformsForShader(const gl::Context *context, gl::ShaderType shaderType); - angle::Result getUAVsForShaderStorageBuffers(const gl::Context *context, - gl::ShaderType shaderType, - UAVList *uavList); - angle::Result syncUniformBuffers(const gl::Context *context); angle::Result syncUniformBuffersForShader(const gl::Context *context, gl::ShaderType shaderType); - angle::Result getUAVsForAtomicCounterBuffers(const gl::Context *context, - gl::ShaderType shaderType, - UAVList *uavList); angle::Result getUAVsForShader(const gl::Context *context, gl::ShaderType shaderType, UAVList *uavList); angle::Result syncUAVsForGraphics(const gl::Context *context); - angle::Result syncUAVsForCompute(const gl::Context *context); angle::Result syncTransformFeedbackBuffers(const gl::Context *context); // These are currently only called internally. void invalidateDriverUniforms(); void invalidateProgramUniforms(); void invalidateConstantBuffer(unsigned int slot); - void invalidateProgramAtomicCounterBuffers(); - void invalidateProgramShaderStorageBuffers(); void invalidateImageBindings(); // Called by the Framebuffer11 directly. @@ -476,12 +416,10 @@ class StateManager11 final : angle::NonCopyable // DIRTY_BIT_SHADERS and DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE should be dealt before // DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS for update image layers. DIRTY_BIT_SHADERS, - // DIRTY_BIT_GRAPHICS_SRV_STATE and DIRTY_BIT_COMPUTE_SRV_STATE should be lower + // DIRTY_BIT_GRAPHICS_SRV_STATE should be lower // bits than DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE. DIRTY_BIT_GRAPHICS_SRV_STATE, DIRTY_BIT_GRAPHICS_UAV_STATE, - DIRTY_BIT_COMPUTE_SRV_STATE, - DIRTY_BIT_COMPUTE_UAV_STATE, DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE, DIRTY_BIT_PROGRAM_UNIFORMS, DIRTY_BIT_DRIVER_UNIFORMS, @@ -501,7 +439,6 @@ class StateManager11 final : angle::NonCopyable // Internal dirty bits. DirtyBits mInternalDirtyBits; DirtyBits mGraphicsDirtyBitsMask; - DirtyBits mComputeDirtyBitsMask; bool mCurSampleAlphaToCoverage; @@ -587,7 +524,6 @@ class StateManager11 final : angle::NonCopyable using RTVCache = ViewCache; using DSVCache = ViewCache; gl::ShaderMap mCurShaderSRVs; - UAVCache mCurComputeUAVs; RTVCache mCurRTVs; DSVCache mCurrentDSV; @@ -646,7 +582,6 @@ class StateManager11 final : angle::NonCopyable // Driver Constants. gl::ShaderMap mShaderDriverConstantBuffers; - ResourceSerial mCurrentComputeConstantBuffer; ResourceSerial mCurrentGeometryConstantBuffer; template @@ -665,14 +600,6 @@ class StateManager11 final : angle::NonCopyable FragmentConstantBufferArray mCurrentConstantBufferPSOffset; FragmentConstantBufferArray mCurrentConstantBufferPSSize; - template - using ComputeConstantBufferArray = - std::array; - - ComputeConstantBufferArray mCurrentConstantBufferCS; - ComputeConstantBufferArray mCurrentConstantBufferCSOffset; - ComputeConstantBufferArray mCurrentConstantBufferCSSize; - // Currently applied transform feedback buffers UniqueSerial mAppliedTFSerial; diff --git a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index b9758191501..517e6fde6f5 100644 --- a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -6,6 +6,10 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" #include @@ -650,10 +654,7 @@ EGLint SwapChain11::reset(DisplayD3D *displayD3D, } } - if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) - { - mSwapChain1 = d3d11::DynamicCastComObject(mSwapChain); - } + mSwapChain1 = d3d11::DynamicCastComObject(mSwapChain); ID3D11Texture2D *backbufferTex = nullptr; hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), @@ -801,14 +802,7 @@ EGLint SwapChain11::swapRect(DisplayD3D *displayD3D, } EGLint result = present(displayD3D, x, y, width, height); - if (result != EGL_SUCCESS) - { - return result; - } - - mRenderer->onSwap(); - - return EGL_SUCCESS; + return result; } EGLint SwapChain11::copyOffscreenToBackbuffer(DisplayD3D *displayD3D, diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp index 9b1a08df66d..ebe2cdfe81a 100644 --- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -8,6 +8,10 @@ // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 // texture. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include @@ -72,14 +76,6 @@ bool TextureStorage11::ImageKey::operator<(const ImageKey &rhs) const std::tie(rhs.level, rhs.layered, rhs.layer, rhs.access, rhs.format); } -MultisampledRenderToTextureInfo::MultisampledRenderToTextureInfo(const GLsizei samples, - const gl::ImageIndex &indexSS, - const gl::ImageIndex &indexMS) - : samples(samples), indexSS(indexSS), indexMS(indexMS), msTextureNeedsResolve(false) -{} - -MultisampledRenderToTextureInfo::~MultisampledRenderToTextureInfo() {} - TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, @@ -238,7 +234,6 @@ angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context, const gl::SamplerState &sampler, const d3d11::SharedSRV **outSRV) { - ANGLE_TRY(resolveTexture(context)); // Make sure to add the level offset for our tiny compressed texture workaround const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel(); const bool swizzleRequired = SwizzleRequired(textureState); @@ -367,7 +362,6 @@ angle::Result TextureStorage11::getSRVLevel(const gl::Context *context, { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ANGLE_TRY(resolveTexture(context)); if (srvType == SRVType::Stencil) { if (!mLevelStencilSRVs[mipLevel].valid()) @@ -414,7 +408,6 @@ angle::Result TextureStorage11::getSRVLevels(const gl::Context *context, bool forceLinearSampler, const d3d11::SharedSRV **outSRV) { - ANGLE_TRY(resolveTexture(context)); unsigned int mipLevels = maxLevel - baseLevel + 1; // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, @@ -444,7 +437,6 @@ angle::Result TextureStorage11::getSRVForImage(const gl::Context *context, const gl::ImageUnit &imageUnit, const d3d11::SharedSRV **outSRV) { - ANGLE_TRY(resolveTexture(context)); // TODO(Xinghua.cao@intel.com): Add solution to handle swizzle required. ImageKey key(imageUnit.level, (imageUnit.layered == GL_TRUE), imageUnit.layer, imageUnit.access, imageUnit.format); @@ -477,7 +469,6 @@ angle::Result TextureStorage11::getUAVForImage(const gl::Context *context, const gl::ImageUnit &imageUnit, const d3d11::SharedUAV **outUAV) { - ANGLE_TRY(resolveTexture(context)); // TODO(Xinghua.cao@intel.com): Add solution to handle swizzle required. ImageKey key(imageUnit.level, (imageUnit.layered == GL_TRUE), imageUnit.layer, imageUnit.access, imageUnit.format); @@ -501,7 +492,7 @@ angle::Result TextureStorage11::getCachedOrCreateUAVForImage(const gl::Context * d3d11::Format::Get(key.format, mRenderer->getRenderer11DeviceCaps()).uavFormat; ASSERT(format != DXGI_FORMAT_UNKNOWN); d3d11::SharedUAV uav; - ANGLE_TRY(createUAVForImage(context, key.level, format, *texture, &uav)); + ANGLE_TRY(createUAVForImage(context, key, format, *texture, &uav)); const auto &insertIt = mUavCacheForImage.insert(std::make_pair(key, std::move(uav))); *outUAV = &insertIt.first->second; return angle::Result::Continue; @@ -515,7 +506,6 @@ const d3d11::Format &TextureStorage11::getFormatSet() const angle::Result TextureStorage11::generateSwizzles(const gl::Context *context, const gl::TextureState &textureState) { - ANGLE_TRY(resolveTexture(context)); gl::SwizzleState swizzleTarget = GetEffectiveSwizzle(textureState); for (int level = 0; level < getLevelCount(); level++) { @@ -579,7 +569,6 @@ angle::Result TextureStorage11::updateSubresourceLevel(const gl::Context *contex const gl::Box ©Area) { ASSERT(srcTexture.valid()); - ANGLE_TRY(resolveTexture(context)); const GLint level = index.getLevelIndex(); markLevelDirty(level); @@ -720,7 +709,6 @@ angle::Result TextureStorage11::copySubresourceLevel(const gl::Context *context, { ASSERT(dstTexture.valid()); - ANGLE_TRY(resolveTexture(context)); const TextureHelper11 *srcTexture = nullptr; // If the zero-LOD workaround is active and we want to update a level greater than zero, then we @@ -786,15 +774,14 @@ angle::Result TextureStorage11::generateMipmap(const gl::Context *context, { ASSERT(sourceIndex.getLayerIndex() == destIndex.getLayerIndex()); - ANGLE_TRY(resolveTexture(context)); markLevelDirty(destIndex.getLevelIndex()); RenderTargetD3D *source = nullptr; - ANGLE_TRY(getRenderTarget(context, sourceIndex, 0, &source)); + ANGLE_TRY(getRenderTarget(context, sourceIndex, &source)); // dest will always have 0 since, we have just released the MS Texture struct RenderTargetD3D *dest = nullptr; - ANGLE_TRY(getRenderTarget(context, destIndex, 0, &dest)); + ANGLE_TRY(getRenderTarget(context, destIndex, &dest)); RenderTarget11 *srcRT11 = GetAs(source); RenderTarget11 *dstRT11 = GetAs(dest); @@ -843,7 +830,6 @@ angle::Result TextureStorage11::copyToStorage(const gl::Context *context, { ASSERT(destStorage); - ANGLE_TRY(resolveTexture(context)); const TextureHelper11 *sourceResouce = nullptr; ANGLE_TRY(getResource(context, &sourceResouce)); @@ -874,7 +860,6 @@ angle::Result TextureStorage11::setData(const gl::Context *context, { ASSERT(!image->isDirty()); - ANGLE_TRY(resolveTexture(context)); markLevelDirty(index.getLevelIndex()); const TextureHelper11 *resource = nullptr; @@ -1005,107 +990,6 @@ angle::Result TextureStorage11::initDropStencilTexture(const gl::Context *contex return angle::Result::Continue; } -angle::Result TextureStorage11::resolveTextureHelper(const gl::Context *context, - const TextureHelper11 &texture) -{ - UINT subresourceIndexSS; - ANGLE_TRY(getSubresourceIndex(context, mMSTexInfo->indexSS, &subresourceIndexSS)); - UINT subresourceIndexMS; - ANGLE_TRY(getSubresourceIndex(context, mMSTexInfo->indexMS, &subresourceIndexMS)); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - const TextureHelper11 *resource = nullptr; - ANGLE_TRY(mMSTexInfo->msTex->getResource(context, &resource)); - deviceContext->ResolveSubresource(texture.get(), subresourceIndexSS, resource->get(), - subresourceIndexMS, texture.getFormat()); - mMSTexInfo->msTextureNeedsResolve = false; - return angle::Result::Continue; -} - -angle::Result TextureStorage11::releaseMultisampledTexStorageForLevel(size_t level) -{ - if (mMSTexInfo && mMSTexInfo->indexSS.getLevelIndex() == static_cast(level)) - { - mMSTexInfo->msTex.reset(); - onStateChange(angle::SubjectMessage::ContentsChanged); - } - return angle::Result::Continue; -} - -GLsizei TextureStorage11::getRenderToTextureSamples() const -{ - if (mMSTexInfo) - { - return mMSTexInfo->samples; - } - return 0; -} - -angle::Result TextureStorage11::findMultisampledRenderTarget(const gl::Context *context, - const gl::ImageIndex &index, - GLsizei samples, - RenderTargetD3D **outRT) const -{ - const int level = index.getLevelIndex(); - if (!mMSTexInfo || level != mMSTexInfo->indexSS.getLevelIndex() || - samples != mMSTexInfo->samples || !mMSTexInfo->msTex) - { - *outRT = nullptr; - return angle::Result::Continue; - } - RenderTargetD3D *rt; - ANGLE_TRY(mMSTexInfo->msTex->findRenderTarget(context, mMSTexInfo->indexMS, samples, &rt)); - *outRT = rt; - return angle::Result::Continue; -} - -angle::Result TextureStorage11::getMultisampledRenderTarget(const gl::Context *context, - const gl::ImageIndex &index, - GLsizei samples, - RenderTargetD3D **outRT) -{ - const int level = index.getLevelIndex(); - if (!mMSTexInfo || level != mMSTexInfo->indexSS.getLevelIndex() || - samples != mMSTexInfo->samples || !mMSTexInfo->msTex) - { - // if mMSTexInfo already exists, then we want to resolve and release it - // since the mMSTexInfo must be for a different sample count or level - ANGLE_TRY(resolveTexture(context)); - - // Now we can create a new object for the correct sample and level - GLsizei width = getLevelWidth(level); - GLsizei height = getLevelHeight(level); - GLenum internalFormat = mFormatInfo.internalFormat; - std::unique_ptr texMS( - GetAs(mRenderer->createTextureStorage2DMultisample( - internalFormat, width, height, level, samples, true, mKHRDebugLabel))); - - // make sure multisample object has the blitted information. - gl::Rectangle area(0, 0, width, height); - RenderTargetD3D *readRenderTarget = nullptr; - // use incoming index here since the index will correspond to the single sampled texture - ANGLE_TRY(getRenderTarget(context, index, 0, &readRenderTarget)); - gl::ImageIndex indexMS = gl::ImageIndex::Make2DMultisample(); - RenderTargetD3D *drawRenderTarget = nullptr; - ANGLE_TRY(texMS->getRenderTarget(context, indexMS, samples, &drawRenderTarget)); - - // blit SS -> MS - // mask: GL_COLOR_BUFFER_BIT, filter: GL_NEAREST - ANGLE_TRY(mRenderer->blitRenderbufferRect(context, area, area, 0, 0, readRenderTarget, - drawRenderTarget, GL_NEAREST, nullptr, true, - false, false)); - mMSTexInfo = std::make_unique(samples, index, indexMS); - mMSTexInfo->msTex = std::move(texMS); - } - RenderTargetD3D *rt; - ANGLE_TRY(mMSTexInfo->msTex->getRenderTarget(context, mMSTexInfo->indexMS, samples, &rt)); - // By returning the multisampled render target to the caller, the render target - // is expected to be changed so we need to resolve to a single sampled texture - // next time resolveTexture is called. - mMSTexInfo->msTextureNeedsResolve = true; - *outRT = rt; - return angle::Result::Continue; -} - TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain, const std::string &label) @@ -1392,7 +1276,6 @@ angle::Result TextureStorage11_2D::getMippedResource(const gl::Context *context, angle::Result TextureStorage11_2D::ensureTextureExists(const gl::Context *context, int mipLevels) { // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. - ANGLE_TRY(resolveTexture(context)); bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled ? (mipLevels == 1) && (mMipLevels > 1) : false; @@ -1436,7 +1319,6 @@ angle::Result TextureStorage11_2D::ensureTextureExists(const gl::Context *contex angle::Result TextureStorage11_2D::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ASSERT(!index.hasLayer()); @@ -1444,12 +1326,6 @@ angle::Result TextureStorage11_2D::findRenderTarget(const gl::Context *context, const int level = index.getLevelIndex(); ASSERT(level >= 0 && level < getLevelCount()); - bool needMS = samples > 0; - if (needMS) - { - return findMultisampledRenderTarget(context, index, samples, outRT); - } - ASSERT(outRT); if (mRenderTarget[level]) { @@ -1470,7 +1346,6 @@ angle::Result TextureStorage11_2D::findRenderTarget(const gl::Context *context, angle::Result TextureStorage11_2D::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); @@ -1478,15 +1353,6 @@ angle::Result TextureStorage11_2D::getRenderTarget(const gl::Context *context, const int level = index.getLevelIndex(); ASSERT(level >= 0 && level < getLevelCount()); - bool needMS = samples > 0; - if (needMS) - { - return getMultisampledRenderTarget(context, index, samples, outRT); - } - else - { - ANGLE_TRY(resolveTexture(context)); - } // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could @@ -1648,7 +1514,7 @@ angle::Result TextureStorage11_2D::createSRVForImage(const gl::Context *context, } angle::Result TextureStorage11_2D::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) @@ -1657,7 +1523,7 @@ angle::Result TextureStorage11_2D::createUAVForImage(const gl::Context *context, D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; - uavDesc.Texture2D.MipSlice = mTopLevel + level; + uavDesc.Texture2D.MipSlice = mTopLevel + key.level; ANGLE_TRY( mRenderer->allocateResource(GetImplAs(context), uavDesc, texture.get(), outUAV)); outUAV->setLabels("TexStorage2D.UAVForImage", &mKHRDebugLabel); @@ -1756,16 +1622,6 @@ angle::Result TextureStorage11_2D::ensureDropStencilTexture(const gl::Context *c return angle::Result::Continue; } -angle::Result TextureStorage11_2D::resolveTexture(const gl::Context *context) -{ - if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve) - { - ANGLE_TRY(resolveTextureHelper(context, mTexture)); - onStateChange(angle::SubjectMessage::ContentsChanged); - } - return angle::Result::Continue; -} - TextureStorage11_External::TextureStorage11_External( Renderer11 *renderer, egl::Stream *stream, @@ -1871,7 +1727,6 @@ angle::Result TextureStorage11_External::getMippedResource(const gl::Context *co angle::Result TextureStorage11_External::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { // Render targets are not supported for external textures @@ -1881,7 +1736,6 @@ angle::Result TextureStorage11_External::findRenderTarget(const gl::Context *con angle::Result TextureStorage11_External::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { // Render targets are not supported for external textures @@ -1928,7 +1782,7 @@ angle::Result TextureStorage11_External::createSRVForImage(const gl::Context *co } angle::Result TextureStorage11_External::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) @@ -1993,7 +1847,7 @@ angle::Result TextureStorage11ImmutableBase::createSRVForImage(const gl::Context } angle::Result TextureStorage11ImmutableBase::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) @@ -2085,7 +1939,6 @@ angle::Result TextureStorage11_EGLImage::getMippedResource(const gl::Context *co angle::Result TextureStorage11_EGLImage::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { // Since the render target of an EGL image will be updated when orphaning, trying to find a @@ -2096,7 +1949,6 @@ angle::Result TextureStorage11_EGLImage::findRenderTarget(const gl::Context *con angle::Result TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); @@ -2595,7 +2447,6 @@ angle::Result TextureStorage11_Cube::getMippedResource(const gl::Context *contex angle::Result TextureStorage11_Cube::ensureTextureExists(const gl::Context *context, int mipLevels) { // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. - ANGLE_TRY(resolveTexture(context)); bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled ? (mipLevels == 1) && (mMipLevels > 1) : false; @@ -2631,7 +2482,6 @@ angle::Result TextureStorage11_Cube::ensureTextureExists(const gl::Context *cont angle::Result TextureStorage11_Cube::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { const int faceIndex = index.cubeMapFaceIndex(); @@ -2640,12 +2490,6 @@ angle::Result TextureStorage11_Cube::findRenderTarget(const gl::Context *context ASSERT(level >= 0 && level < getLevelCount()); ASSERT(faceIndex >= 0 && faceIndex < static_cast(gl::kCubeFaceCount)); - bool needMS = samples > 0; - if (needMS) - { - return findMultisampledRenderTarget(context, index, samples, outRT); - } - if (!mRenderTarget[faceIndex][level]) { if (mUseLevelZeroTexture) @@ -2692,7 +2536,6 @@ angle::Result TextureStorage11_Cube::createRenderTargetSRV(const gl::Context *co angle::Result TextureStorage11_Cube::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { const int faceIndex = index.cubeMapFaceIndex(); @@ -2701,15 +2544,6 @@ angle::Result TextureStorage11_Cube::getRenderTarget(const gl::Context *context, ASSERT(level >= 0 && level < getLevelCount()); ASSERT(faceIndex >= 0 && faceIndex < static_cast(gl::kCubeFaceCount)); - bool needMS = samples > 0; - if (needMS) - { - return getMultisampledRenderTarget(context, index, samples, outRT); - } - else - { - ANGLE_TRY(resolveTexture(context)); - } Context11 *context11 = GetImplAs(context); @@ -2892,7 +2726,7 @@ angle::Result TextureStorage11_Cube::createSRVForImage(const gl::Context *contex } angle::Result TextureStorage11_Cube::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) @@ -2901,9 +2735,9 @@ angle::Result TextureStorage11_Cube::createUAVForImage(const gl::Context *contex D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; - uavDesc.Texture2DArray.MipSlice = mTopLevel + level; - uavDesc.Texture2DArray.FirstArraySlice = 0; - uavDesc.Texture2DArray.ArraySize = gl::kCubeFaceCount; + uavDesc.Texture2DArray.MipSlice = mTopLevel + key.level; + uavDesc.Texture2DArray.FirstArraySlice = key.layered ? 0 : key.layer; + uavDesc.Texture2DArray.ArraySize = key.layered ? gl::kCubeFaceCount : 1; ANGLE_TRY( mRenderer->allocateResource(GetImplAs(context), uavDesc, texture.get(), outUAV)); outUAV->setLabels("TexStorageCube.UAVForImage", &mKHRDebugLabel); @@ -3004,16 +2838,6 @@ angle::Result TextureStorage11_Cube::ensureDropStencilTexture(const gl::Context return angle::Result::Continue; } -angle::Result TextureStorage11_Cube::resolveTexture(const gl::Context *context) -{ - if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve) - { - ANGLE_TRY(resolveTextureHelper(context, mTexture)); - onStateChange(angle::SubjectMessage::ContentsChanged); - } - return angle::Result::Continue; -} - void TextureStorage11_Cube::onLabelUpdate() { if (mTexture.valid()) @@ -3213,7 +3037,7 @@ angle::Result TextureStorage11_3D::createSRVForImage(const gl::Context *context, } angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) @@ -3222,9 +3046,9 @@ angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context, D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; - uavDesc.Texture3D.MipSlice = mTopLevel + level; - uavDesc.Texture3D.FirstWSlice = 0; - uavDesc.Texture3D.WSize = mTextureDepth; + uavDesc.Texture3D.MipSlice = mTopLevel + key.level; + uavDesc.Texture3D.FirstWSlice = key.layered ? 0 : key.layer; + uavDesc.Texture3D.WSize = key.layered ? mTextureDepth : 1; ANGLE_TRY( mRenderer->allocateResource(GetImplAs(context), uavDesc, texture.get(), outUAV)); outUAV->setLabels("TexStorage3D.UAVForImage", &mKHRDebugLabel); @@ -3233,7 +3057,6 @@ angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context, angle::Result TextureStorage11_3D::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { const int mipLevel = index.getLevelIndex(); @@ -3263,7 +3086,6 @@ angle::Result TextureStorage11_3D::findRenderTarget(const gl::Context *context, angle::Result TextureStorage11_3D::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { const int mipLevel = index.getLevelIndex(); @@ -3611,7 +3433,7 @@ angle::Result TextureStorage11_2DArray::createSRVForImage(const gl::Context *con } angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) @@ -3620,9 +3442,9 @@ angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *con D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; - uavDesc.Texture2DArray.MipSlice = mTopLevel + level; - uavDesc.Texture2DArray.FirstArraySlice = 0; - uavDesc.Texture2DArray.ArraySize = mTextureDepth; + uavDesc.Texture2DArray.MipSlice = mTopLevel + key.level; + uavDesc.Texture2DArray.FirstArraySlice = key.layered ? 0 : key.layer; + uavDesc.Texture2DArray.ArraySize = key.layered ? mTextureDepth : 1; ANGLE_TRY( mRenderer->allocateResource(GetImplAs(context), uavDesc, texture.get(), outUAV)); outUAV->setLabels("TexStorage2DArray.UAVForImage", &mKHRDebugLabel); @@ -3631,7 +3453,6 @@ angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *con angle::Result TextureStorage11_2DArray::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ASSERT(index.hasLayer()); @@ -3677,7 +3498,6 @@ angle::Result TextureStorage11_2DArray::createRenderTargetSRV(const gl::Context angle::Result TextureStorage11_2DArray::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(index.hasLayer()); @@ -3944,7 +3764,7 @@ angle::Result TextureStorage11_2DMultisample::ensureTextureExists(const gl::Cont const gl::TextureCaps &textureCaps = mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat); - GLuint supportedSamples = textureCaps.getNearestSamples(mSamples); + GLuint supportedSamples = textureCaps.sampleCounts.getNearestSamples(mSamples); desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples); @@ -3958,7 +3778,6 @@ angle::Result TextureStorage11_2DMultisample::ensureTextureExists(const gl::Cont angle::Result TextureStorage11_2DMultisample::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ASSERT(!index.hasLayer()); @@ -3973,7 +3792,6 @@ angle::Result TextureStorage11_2DMultisample::findRenderTarget(const gl::Context angle::Result TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); @@ -4165,7 +3983,7 @@ angle::Result TextureStorage11_2DMultisampleArray::ensureTextureExists(const gl: const gl::TextureCaps &textureCaps = mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat); - GLuint supportedSamples = textureCaps.getNearestSamples(mSamples); + GLuint supportedSamples = textureCaps.sampleCounts.getNearestSamples(mSamples); desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples); @@ -4179,7 +3997,6 @@ angle::Result TextureStorage11_2DMultisampleArray::ensureTextureExists(const gl: angle::Result TextureStorage11_2DMultisampleArray::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ASSERT(index.hasLayer()); @@ -4225,7 +4042,6 @@ angle::Result TextureStorage11_2DMultisampleArray::createRenderTargetSRV( angle::Result TextureStorage11_2DMultisampleArray::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(index.hasLayer()); @@ -4385,7 +4201,10 @@ angle::Result TextureStorage11_Buffer::initTexture(const gl::Context *context) { ID3D11Buffer *buffer = nullptr; Buffer11 *buffer11 = GetImplAs(mBuffer.get()); - ANGLE_TRY(buffer11->getBuffer(context, rx::BufferUsage::BUFFER_USAGE_TYPED_UAV, &buffer)); + BufferFeedback feedback; + ANGLE_TRY(buffer11->getBuffer(context, rx::BufferUsage::BUFFER_USAGE_TYPED_UAV, &buffer, + &feedback)); + mBuffer.get()->applyImplFeedback(context, feedback); mTexture.set(buffer, mFormatInfo); mTexture.get()->AddRef(); } @@ -4409,7 +4228,6 @@ angle::Result TextureStorage11_Buffer::getMippedResource(const gl::Context *cont angle::Result TextureStorage11_Buffer::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ANGLE_HR_UNREACHABLE(GetImplAs(context)); @@ -4418,7 +4236,6 @@ angle::Result TextureStorage11_Buffer::findRenderTarget(const gl::Context *conte angle::Result TextureStorage11_Buffer::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ANGLE_HR_UNREACHABLE(GetImplAs(context)); @@ -4489,7 +4306,7 @@ angle::Result TextureStorage11_Buffer::createSRVForImage(const gl::Context *cont return angle::Result::Continue; } angle::Result TextureStorage11_Buffer::createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h index 777ce837400..c535ba48333 100644 --- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -39,28 +39,6 @@ class TextureStorage11_2DMultisample; template using CubeFaceArray = std::array; -struct MultisampledRenderToTextureInfo -{ - MultisampledRenderToTextureInfo(const GLsizei samples, - const gl::ImageIndex &indexSS, - const gl::ImageIndex &indexMS); - ~MultisampledRenderToTextureInfo(); - - // How many samples the multisampled texture contains - GLsizei samples; - // This is the image index for the single sampled texture - // This will hold the relevant level information - gl::ImageIndex indexSS; - // This is the image index for the multisampled texture - // For multisampled indexes, there is no level Index since they should - // account for the entire level. - gl::ImageIndex indexMS; - // True when multisampled texture has been written to and needs to be - // resolved to the single sampled texture - bool msTextureNeedsResolve; - std::unique_ptr msTex; -}; - class TextureStorage11 : public TextureStorage { public: @@ -144,8 +122,6 @@ class TextureStorage11 : public TextureStorage const gl::ImageIndex &index, Image11 *incomingImage) = 0; - GLsizei getRenderToTextureSamples() const override; - protected: TextureStorage11(Renderer11 *renderer, UINT bindFlags, @@ -200,29 +176,30 @@ class TextureStorage11 : public TextureStorage DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) = 0; + + struct ImageKey + { + ImageKey(); + ImageKey(int level, bool layered, int layer, GLenum access, GLenum format); + bool operator<(const ImageKey &rhs) const; + int level; + bool layered; + int layer; + GLenum access; + GLenum format; + }; + virtual angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, - d3d11::SharedUAV *outUAV) = 0; + d3d11::SharedUAV *outUAV) = 0; void verifySwizzleExists(const gl::SwizzleState &swizzleState); // Clear all cached non-swizzle SRVs and invalidate the swizzle cache. void clearSRVCache(); - // Helper for resolving MS shadowed texture - angle::Result resolveTextureHelper(const gl::Context *context, const TextureHelper11 &texture); - angle::Result releaseMultisampledTexStorageForLevel(size_t level) override; - angle::Result findMultisampledRenderTarget(const gl::Context *context, - const gl::ImageIndex &index, - GLsizei samples, - RenderTargetD3D **outRT) const; - angle::Result getMultisampledRenderTarget(const gl::Context *context, - const gl::ImageIndex &index, - GLsizei samples, - RenderTargetD3D **outRT); - Renderer11 *mRenderer; int mTopLevel; unsigned int mMipLevels; @@ -235,8 +212,6 @@ class TextureStorage11 : public TextureStorage gl::TexLevelArray mSwizzleCache; TextureHelper11 mDropStencilTexture; - std::unique_ptr mMSTexInfo; - private: const UINT mBindFlags; const UINT mMiscFlags; @@ -266,18 +241,6 @@ class TextureStorage11 : public TextureStorage using SRVCacheForSampler = std::map; SRVCacheForSampler mSrvCacheForSampler; - struct ImageKey - { - ImageKey(); - ImageKey(int level, bool layered, int layer, GLenum access, GLenum format); - bool operator<(const ImageKey &rhs) const; - int level; - bool layered; - int layer; - GLenum access; - GLenum format; - }; - angle::Result getCachedOrCreateSRVForImage(const gl::Context *context, const ImageKey &key, const d3d11::SharedSRV **outSRV); @@ -317,13 +280,10 @@ class TextureStorage11_2D : public TextureStorage11 const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) override; - angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; void associateImage(Image11 *image, const gl::ImageIndex &index) override; @@ -349,8 +309,6 @@ class TextureStorage11_2D : public TextureStorage11 angle::Result ensureTextureExists(const gl::Context *context, int mipLevels); - angle::Result resolveTexture(const gl::Context *context) override; - private: angle::Result createSRVForSampler(const gl::Context *context, int baseLevel, @@ -364,7 +322,7 @@ class TextureStorage11_2D : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; @@ -412,11 +370,11 @@ class TextureStorage11_External : public TextureStorage11 const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; @@ -449,7 +407,7 @@ class TextureStorage11_External : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; @@ -485,7 +443,7 @@ class TextureStorage11ImmutableBase : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; @@ -515,11 +473,11 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; @@ -590,11 +548,11 @@ class TextureStorage11_Cube : public TextureStorage11 const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; @@ -622,8 +580,6 @@ class TextureStorage11_Cube : public TextureStorage11 angle::Result ensureTextureExists(const gl::Context *context, int mipLevels); - angle::Result resolveTexture(const gl::Context *context) override; - private: angle::Result createSRVForSampler(const gl::Context *context, int baseLevel, @@ -637,7 +593,7 @@ class TextureStorage11_Cube : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; @@ -683,11 +639,11 @@ class TextureStorage11_3D : public TextureStorage11 // Handles both layer and non-layer RTs angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; void associateImage(Image11 *image, const gl::ImageIndex &index) override; @@ -718,7 +674,7 @@ class TextureStorage11_3D : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; @@ -754,11 +710,11 @@ class TextureStorage11_2DArray : public TextureStorage11 const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; void associateImage(Image11 *image, const gl::ImageIndex &index) override; @@ -814,7 +770,7 @@ class TextureStorage11_2DArray : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; @@ -854,11 +810,11 @@ class TextureStorage11_2DMultisample final : public TextureStorage11ImmutableBas const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; @@ -911,11 +867,11 @@ class TextureStorage11_2DMultisampleArray final : public TextureStorage11Immutab const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; @@ -970,11 +926,11 @@ class TextureStorage11_Buffer : public TextureStorage11 const TextureHelper11 **outResource) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, + RenderTargetD3D **outRT) override; void onLabelUpdate() override; @@ -1006,7 +962,7 @@ class TextureStorage11_Buffer : public TextureStorage11 const TextureHelper11 &texture, d3d11::SharedSRV *outSRV) override; angle::Result createUAVForImage(const gl::Context *context, - int level, + const ImageKey &key, DXGI_FORMAT format, const TextureHelper11 &texture, d3d11::SharedUAV *outUAV) override; diff --git a/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp index 6c4b8b0647b..4620f67310a 100644 --- a/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp @@ -109,8 +109,10 @@ angle::Result TransformFeedback11::getSOBuffers(const gl::Context *context, if (binding.get() != nullptr) { Buffer11 *storage = GetImplAs(binding.get()); + BufferFeedback feedback; ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, - &mBuffers[bindingIdx])); + &mBuffers[bindingIdx], &feedback)); + binding.get()->applyImplFeedback(context, feedback); } } diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp index 1e8ce52ea05..0f6ecb17ec6 100644 --- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp @@ -19,8 +19,9 @@ using namespace angle; namespace rx { -VertexArray11::VertexArray11(const gl::VertexArrayState &data) - : VertexArrayImpl(data), +VertexArray11::VertexArray11(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) + : VertexArrayImpl(data, vertexArrayBuffers), mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE), mTranslatedAttribs(data.getMaxAttribs()), mAppliedNumViewsToDivisor(1), @@ -88,18 +89,6 @@ angle::Result VertexArray11::syncState(const gl::Context *context, size_t dirtyBit = *iter; switch (dirtyBit) { - case gl::VertexArray::DIRTY_BIT_LOST_OBSERVATION: - { - // If vertex array was not observing while unbound, we need to check buffer's - // internal storage and take action if buffer has changed while not observing. - // For now we just simply assume buffer storage has changed and always dirty all - // binding points. - iter.setLaterBits( - gl::VertexArray::DirtyBits(mState.getBufferBindingMask().to_ulong() - << gl::VertexArray::DIRTY_BIT_BINDING_0)); - break; - } - case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER: case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA: { @@ -218,7 +207,7 @@ angle::Result VertexArray11::updateElementArrayStorage(const gl::Context *contex unsigned int offset = static_cast(reinterpret_cast(indices)); mCurrentElementArrayStorage = - ClassifyIndexStorage(context->getState(), mState.getElementArrayBuffer(), indexType, + ClassifyIndexStorage(context->getState(), getElementArrayBuffer(), indexType, mCachedDestinationIndexType, offset); return angle::Result::Continue; @@ -230,8 +219,9 @@ void VertexArray11::updateVertexAttribStorage(const gl::Context *context, { const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex); const gl::VertexBinding &binding = mState.getBindingFromAttribIndex(attribIndex); + const gl::Buffer *buffer = getVertexArrayBuffer(attrib.bindingIndex); - VertexStorageType newStorageType = ClassifyAttributeStorage(context, attrib, binding); + VertexStorageType newStorageType = ClassifyAttributeStorage(context, attrib, binding, buffer); // Note: having an unchanged storage type doesn't mean the attribute is clean. mAttribsToTranslate.set(attribIndex, newStorageType != VertexStorageType::DYNAMIC); @@ -271,6 +261,8 @@ angle::Result VertexArray11::updateDirtyAttribs(const gl::Context *context, // Record basic attrib info translatedAttrib->attribute = &attribs[dirtyAttribIndex]; translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex]; + translatedAttrib->bufferBindingPointer = + &getBufferBindingPointer(translatedAttrib->attribute->bindingIndex); translatedAttrib->currentValueType = currentValue.Type; translatedAttrib->divisor = translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; @@ -329,6 +321,8 @@ angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context, // Record basic attrib info dynamicAttrib->attribute = &attribs[dynamicAttribIndex]; dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex]; + dynamicAttrib->bufferBindingPointer = + &getBufferBindingPointer(dynamicAttrib->attribute->bindingIndex); dynamicAttrib->currentValueType = currentValue.Type; dynamicAttrib->divisor = dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; } diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h index 6cc14af82e2..bea6549827a 100644 --- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h +++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -21,7 +21,8 @@ class Renderer11; class VertexArray11 : public VertexArrayImpl { public: - VertexArray11(const gl::VertexArrayState &data); + VertexArray11(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers); ~VertexArray11() override; void destroy(const gl::Context *context) override; diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp index 9daa8f83f99..eed665e3b2f 100644 --- a/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -6,6 +6,10 @@ // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" #include "libANGLE/Buffer.h" diff --git a/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp b/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp index 0e64f78d53c..df340856499 100644 --- a/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp @@ -118,9 +118,7 @@ HRESULT CompositorNativeWindow11::createSwapChain(ID3D11Device *device, swapChainDesc.Scaling = DXGI_SCALING_STRETCH; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.AlphaMode = mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; -#ifndef ANGLE_ENABLE_WINDOWS_UWP - swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; -#endif + swapChainDesc.Flags = 0; Microsoft::WRL::ComPtr swapChain1; hr = factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1); if (SUCCEEDED(hr)) diff --git a/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h b/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h index aec331a76ca..688f9377245 100644 --- a/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h +++ b/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h @@ -12,7 +12,7 @@ #include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" -#include +#include #include #include #include diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp index 3c7e75319d1..6cc69493164 100644 --- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -7,6 +7,10 @@ // renderer11_utils.cpp: Conversion functions and other utility routines // specific to the D3D11 renderer. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include @@ -38,9 +42,6 @@ namespace d3d11_gl { namespace { -// TODO(xinghua.cao@intel.com): Get a more accurate limit. -static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0; - // Helper functor for querying DXGI support. Saves passing the parameters repeatedly. class DXGISupportHelper : angle::NonCopyable { @@ -96,7 +97,7 @@ gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion, if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) { texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; - if (maxClientVersion.major > 2) + if (maxClientVersion >= gl::ES_3_0) { texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; } @@ -150,6 +151,8 @@ bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -172,6 +175,8 @@ float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; @@ -198,6 +203,8 @@ bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -225,6 +232,8 @@ bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -247,6 +256,8 @@ bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -279,6 +290,8 @@ bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -300,6 +313,8 @@ bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -329,6 +344,8 @@ bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -349,6 +366,8 @@ bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -373,6 +392,8 @@ int GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; @@ -397,6 +418,8 @@ int GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; @@ -421,6 +444,8 @@ int GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; @@ -445,6 +470,8 @@ int GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; @@ -468,6 +495,8 @@ int GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; @@ -491,6 +520,8 @@ int GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; @@ -525,6 +556,8 @@ int GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -553,6 +586,8 @@ int GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -575,6 +610,8 @@ int GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; @@ -601,6 +638,8 @@ int GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; @@ -626,6 +665,8 @@ int GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - @@ -664,6 +705,8 @@ int GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) // Levels 10_0+, // even if it's unused in the shader (e.g. for transform feedback). TODO: This could // be improved. + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -690,6 +733,8 @@ int GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); @@ -715,6 +760,8 @@ int GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; @@ -742,6 +789,8 @@ int GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; @@ -767,6 +816,8 @@ int GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - @@ -793,6 +844,8 @@ int GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); @@ -818,6 +871,8 @@ int GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; @@ -839,103 +894,10 @@ int GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) } } -std::array GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, - D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, - D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}}; - default: - return {{0, 0, 0}}; - } -} - -std::array GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y, - D3D11_CS_THREAD_GROUP_MAX_Z}}; - default: - return {{0, 0, 0}}; - } -} - -int GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP; - default: - return 0; - } -} - -int GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - // In D3D11 the maximum total size of all variables with the groupshared storage class is - // 32kb. - // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-syntax - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return 32768; - default: - return 0; - } -} - -int GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - default: - return 0; - } -} - -int GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - - d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; - default: - return 0; - } -} - -int GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - default: - return 0; - } -} - void SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel, gl::Caps *caps) { ASSERT(caps); - GLuint reservedUAVsForAtomicCounterBuffers = 0u; - // For pixel shaders, the render targets and unordered access views share the same resource // slots when being written out. // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476465(v=vs.85).aspx @@ -943,76 +905,35 @@ void SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel, gl::Caps *caps) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: - // Currently we allocate 4 UAV slots for atomic counter buffers on feature level 11_1. - reservedUAVsForAtomicCounterBuffers = 4u; maxNumRTVsAndUAVs = D3D11_1_UAV_SLOT_COUNT; break; case D3D_FEATURE_LEVEL_11_0: - // Currently we allocate 1 UAV slot for atomic counter buffers on feature level 11_0. - reservedUAVsForAtomicCounterBuffers = 1u; maxNumRTVsAndUAVs = D3D11_PS_CS_UAV_REGISTER_COUNT; break; default: return; } - // Set limits on atomic counter buffers in fragment shaders and compute shaders. - caps->maxCombinedAtomicCounterBuffers = reservedUAVsForAtomicCounterBuffers; - caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Compute] = - reservedUAVsForAtomicCounterBuffers; - caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Fragment] = - reservedUAVsForAtomicCounterBuffers; - caps->maxAtomicCounterBufferBindings = reservedUAVsForAtomicCounterBuffers; - - // Setting MAX_COMPUTE_ATOMIC_COUNTERS to a conservative number of 1024 * the number of UAV - // reserved for atomic counters. It could theoretically be set to max buffer size / 4 but that - // number could cause problems. - caps->maxCombinedAtomicCounters = reservedUAVsForAtomicCounterBuffers * 1024; - caps->maxShaderAtomicCounters[gl::ShaderType::Compute] = caps->maxCombinedAtomicCounters; - - // See - // https://docs.microsoft.com/en-us/windows/desktop/direct3d11/overviews-direct3d-11-resources-limits - // Resource size (in MB) for any of the preceding resources is min(max(128,0.25f * (amount of - // dedicated VRAM)), 2048) MB. So we set it to 128MB to keep same with GL backend. - GLint maxResourceSize = D3D11_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM * 1024 * 1024; - caps->maxShaderStorageBlockSize = maxResourceSize; - - caps->maxAtomicCounterBufferSize = maxResourceSize; - - // Allocate the remaining slots for images and shader storage blocks. + // Allocate all the slots for images. // The maximum number of fragment shader outputs depends on the current context version, so we // will not set it here. See comments in Context11::initialize(). - caps->maxCombinedShaderOutputResources = - maxNumRTVsAndUAVs - reservedUAVsForAtomicCounterBuffers; - - // Set limits on images and shader storage blocks in fragment shaders and compute shaders. - caps->maxCombinedShaderStorageBlocks = caps->maxCombinedShaderOutputResources; - caps->maxShaderStorageBlocks[gl::ShaderType::Compute] = caps->maxCombinedShaderOutputResources; - caps->maxShaderStorageBlocks[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources; - caps->maxShaderStorageBufferBindings = caps->maxCombinedShaderOutputResources; + caps->maxCombinedShaderOutputResources = maxNumRTVsAndUAVs; + // Set limits on images and shader storage blocks in fragment shaders. caps->maxImageUnits = caps->maxCombinedShaderOutputResources; caps->maxCombinedImageUniforms = caps->maxCombinedShaderOutputResources; - caps->maxShaderImageUniforms[gl::ShaderType::Compute] = caps->maxCombinedShaderOutputResources; caps->maxShaderImageUniforms[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources; // On feature level 11_1, UAVs are also available in vertex shaders and geometry shaders. - if (featureLevel == D3D_FEATURE_LEVEL_11_1) + if (featureLevel >= D3D_FEATURE_LEVEL_11_1) { - caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Vertex] = - caps->maxCombinedAtomicCounterBuffers; - caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] = - caps->maxCombinedAtomicCounterBuffers; - caps->maxShaderImageUniforms[gl::ShaderType::Vertex] = caps->maxCombinedShaderOutputResources; - caps->maxShaderStorageBlocks[gl::ShaderType::Vertex] = - caps->maxCombinedShaderOutputResources; caps->maxShaderImageUniforms[gl::ShaderType::Geometry] = caps->maxCombinedShaderOutputResources; - caps->maxShaderStorageBlocks[gl::ShaderType::Geometry] = - caps->maxCombinedShaderOutputResources; } } @@ -1020,6 +941,8 @@ int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; @@ -1044,6 +967,8 @@ int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; @@ -1068,6 +993,8 @@ int GetMinimumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm- + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return -32; @@ -1090,6 +1017,8 @@ int GetMaximumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm- + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return 31; @@ -1117,6 +1046,8 @@ size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; @@ -1142,6 +1073,8 @@ int GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; @@ -1166,6 +1099,8 @@ int GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: @@ -1188,6 +1123,8 @@ int GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / @@ -1214,6 +1151,8 @@ int GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH; @@ -1255,6 +1194,8 @@ unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -1276,6 +1217,8 @@ unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -1297,10 +1240,12 @@ gl::Version GetMaximumClientVersion(const Renderer11DeviceCaps &caps) { switch (caps.featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: - return gl::Version(3, 1); case D3D_FEATURE_LEVEL_10_1: + // 3.1 could theoretically be supported on FL 11.0+, but is not supported in ANGLE. return gl::Version(3, 0); case D3D_FEATURE_LEVEL_10_0: @@ -1323,15 +1268,12 @@ gl::Version GetMaximumClientVersion(const Renderer11DeviceCaps &caps) } } -D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31() -{ - return kMinimumFeatureLevelForES31; -} - unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; @@ -1352,6 +1294,8 @@ bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel) // The multiview extensions can always be supported in D3D11 through geometry shaders. switch (featureLevel) { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return true; @@ -1365,6 +1309,8 @@ int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { // D3D10+ only allows 1 sample mask. + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -1528,24 +1474,13 @@ void GenerateCaps(ID3D11Device *device, caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); - // Compute shader limits - caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel); - caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel); - caps->maxComputeWorkGroupInvocations = GetMaxComputeWorkGroupInvocations(featureLevel); - caps->maxComputeSharedMemorySize = GetMaxComputeSharedMemorySize(featureLevel); - caps->maxShaderUniformComponents[gl::ShaderType::Compute] = - GetMaximumComputeUniformVectors(featureLevel) * 4; - caps->maxShaderUniformBlocks[gl::ShaderType::Compute] = - GetMaximumComputeUniformBlocks(featureLevel); - caps->maxShaderTextureImageUnits[gl::ShaderType::Compute] = - GetMaximumComputeTextureUnits(featureLevel); - SetUAVRelatedResourceLimits(featureLevel, caps); // Aggregate shader limits caps->maxUniformBufferBindings = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] + caps->maxShaderUniformBlocks[gl::ShaderType::Fragment]; - caps->maxUniformBlockSize = static_cast(GetMaximumConstantBufferSize(featureLevel)); + caps->maxUniformBlockSize = static_cast(std::min( + gl::IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE, GetMaximumConstantBufferSize(featureLevel))); // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1. caps->maxUniformLocations = 1024; @@ -1560,13 +1495,6 @@ void GenerateCaps(ID3D11Device *device, caps->maxCombinedUniformBlocks = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] + caps->maxShaderUniformBlocks[gl::ShaderType::Fragment]; - // A shader storage block will be translated to a structure in HLSL. So We reference the HLSL - // structure packing rules - // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx. The - // resulting size of any structure will always be evenly divisible by sizeof(four-component - // vector). - caps->shaderStorageBufferOffsetAlignment = 16; - for (gl::ShaderType shaderType : gl::AllShaderTypes()) { caps->maxCombinedShaderUniformComponents[shaderType] = @@ -1662,7 +1590,7 @@ void GenerateCaps(ID3D11Device *device, extensions->stencilTexturingANGLE = (featureLevel >= D3D_FEATURE_LEVEL_10_1); extensions->multiviewOVR = IsMultiviewSupported(featureLevel); extensions->multiview2OVR = IsMultiviewSupported(featureLevel); - if (extensions->multiviewOVR || extensions->multiview2OVR) + if (extensions->multiviewOVR) { caps->maxViews = std::min(static_cast(GetMaximum2DTextureArraySize(featureLevel)), GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel)); @@ -1680,7 +1608,6 @@ void GenerateCaps(ID3D11Device *device, extensions->unpackSubimageEXT = true; extensions->packSubimageNV = true; extensions->lossyEtcDecodeANGLE = true; - extensions->syncQueryCHROMIUM = GetEventQuerySupport(featureLevel); extensions->copyTextureCHROMIUM = true; extensions->copyCompressedTextureCHROMIUM = true; extensions->textureStorageMultisample2dArrayOES = true; @@ -1695,8 +1622,7 @@ void GenerateCaps(ID3D11Device *device, caps->maxInterpolationOffset = +0.4375f; // +0.5 - (2 ^ -4) } extensions->multiviewMultisampleANGLE = - ((extensions->multiviewOVR || extensions->multiview2OVR) && - extensions->textureStorageMultisample2dArrayOES); + (extensions->multiviewOVR && extensions->textureStorageMultisample2dArrayOES); extensions->copyTexture3dANGLE = true; extensions->textureBorderClampEXT = true; extensions->textureBorderClampOES = true; @@ -1711,10 +1637,6 @@ void GenerateCaps(ID3D11Device *device, extensions->baseVertexBaseInstanceShaderBuiltinANGLE = true; extensions->drawElementsBaseVertexOES = true; extensions->drawElementsBaseVertexEXT = true; - if (!strstr(description, "Adreno")) - { - extensions->multisampledRenderToTextureEXT = true; - } extensions->videoTextureWEBGL = true; // D3D11 cannot support reading depth texture as a luminance texture. @@ -2144,8 +2066,6 @@ D3D11_QUERY ConvertQueryType(gl::QueryType type) case gl::QueryType::Timestamp: // A disjoint query is also created for timestamp return D3D11_QUERY_TIMESTAMP_DISJOINT; - case gl::QueryType::CommandsCompleted: - return D3D11_QUERY_EVENT; default: UNREACHABLE(); return D3D11_QUERY_EVENT; @@ -2438,12 +2358,6 @@ template angle::Result LazyResource::resolveImpl( const D3D11_BLEND_DESC &desc, void *initData, const char *name); -template angle::Result LazyResource::resolveImpl( - d3d::Context *context, - Renderer11 *renderer, - const ShaderData &desc, - void *initData, - const char *name); template angle::Result LazyResource::resolveImpl( d3d::Context *context, Renderer11 *renderer, @@ -2546,7 +2460,6 @@ void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps, ANGLE_FEATURE_CONDITION(features, flushAfterEndingTransformFeedback, isNvidia); ANGLE_FEATURE_CONDITION(features, getDimensionsIgnoresBaseLevel, isNvidia); ANGLE_FEATURE_CONDITION(features, skipVSConstantRegisterZero, isNvidia); - ANGLE_FEATURE_CONDITION(features, forceAtomicValueResolution, isNvidia); ANGLE_FEATURE_CONDITION(features, preAddTexelFetchOffsets, isIntel); ANGLE_FEATURE_CONDITION(features, useSystemMemoryForConstantBuffers, isIntel); diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h index 75a4feac098..8c3ee454fcb 100644 --- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h +++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -7,9 +7,14 @@ // renderer11_utils.h: Conversion functions and other utility routines // specific to the D3D11 renderer. + #ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include @@ -82,8 +87,6 @@ void GenerateCaps(ID3D11Device *device, gl::Limitations *limitations, ShPixelLocalStorageOptions *); -D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31(); - } // namespace d3d11_gl namespace d3d11 diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json index 6c66877a5bd..b876cd31b41 100644 --- a/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json +++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json @@ -131,7 +131,7 @@ "blue": 8, "alpha": 8 }, - "siwzzleFormat": "GL_RGBA8" + "swizzleFormat": "GL_RGBA8" }, "B8G8R8A8_TYPELESS": { "texFormat": "DXGI_FORMAT_B8G8R8A8_TYPELESS", @@ -248,6 +248,21 @@ }, "glInternalFormat": "GL_RGB10_A2" }, + "R10X6G10X6B10X6A10X6_UNORM": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "typelessFormat": "DXGI_FORMAT_R16G16B16A16_TYPELESS", + "channels": "rgba", + "componentType": "unorm", + "bits": { + "red": 10, + "green": 10, + "blue": 10, + "alpha": 10 + }, + "glInternalFormat": "GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX" + }, "BC1_RGBA_UNORM_BLOCK": { "texFormat": "DXGI_FORMAT_BC1_UNORM", "srvFormat": "DXGI_FORMAT_BC1_UNORM", @@ -777,11 +792,11 @@ }, "glInternalFormat": "GL_RGBA32UI" }, - "B5G6R5_UNORM": { + "R5G6B5_UNORM": { "texFormat": "DXGI_FORMAT_B5G6R5_UNORM", "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM", "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM", - "channels": "bgr", + "channels": "rgb", "componentType": "unorm", "bits": { "red": 5, diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json index a62bd060dfc..3df75f19662 100644 --- a/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json +++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json @@ -2,6 +2,7 @@ "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT", "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT", "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM", + "GL_BGRA_EXT": "B8G8R8A8_UNORM", "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM", "GL_BGRA8_SRGB_ANGLEX": "B8G8R8A8_UNORM_SRGB", "GL_COMPRESSED_R11_EAC": "R16_UNORM", @@ -81,7 +82,7 @@ "GL_RGB16F": "R16G16B16A16_FLOAT", "GL_RGB16I": "R16G16B16A16_SINT", "GL_RGB16UI": "R16G16B16A16_UINT", - "GL_RGB565": "B5G6R5_UNORM", + "GL_RGB565": "R5G6B5_UNORM", "GL_RGB5_A1": "B5G5R5A1_UNORM", "GL_RGB8": "R8G8B8A8_UNORM", "GL_RGB8I": "R8G8B8A8_SINT", diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp index c6f0db8a80f..4abe99b34dc 100644 --- a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp @@ -121,43 +121,6 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev nullptr); return info; } - case GL_BGR565_ANGLEX: - { - if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) - { - static constexpr Format info(GL_BGR565_ANGLEX, - angle::FormatID::B5G6R5_UNORM, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - GL_RGBA8, - nullptr); - return info; - } - else - { - static constexpr Format info(GL_BGR565_ANGLEX, - angle::FormatID::R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_R8G8B8A8_TYPELESS, - GL_RGBA8, - nullptr); - return info; - } - } case GL_BGR5_A1_ANGLEX: { static constexpr Format info(GL_BGR5_A1_ANGLEX, @@ -222,7 +185,24 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS, - GL_BGRA8_SRGB_ANGLEX, + GL_RGBA8, + nullptr); + return info; + } + case GL_BGRA_EXT: + { + static constexpr Format info(GL_BGRA_EXT, + angle::FormatID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_TYPELESS, + GL_BGRA8_EXT, nullptr); return info; } @@ -2338,6 +2318,23 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev nullptr); return info; } + case GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX: + { + static constexpr Format info(GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX, + angle::FormatID::R10X6G10X6B10X6A10X6_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_TYPELESS, + GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX, + nullptr); + return info; + } case GL_R11F_G11F_B10F: { static constexpr Format info(GL_R11F_G11F_B10F, @@ -2972,7 +2969,7 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) { static constexpr Format info(GL_RGB565, - angle::FormatID::B5G6R5_UNORM, + angle::FormatID::R5G6B5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN, diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h index a90cfcf701e..98d8152efa6 100644 --- a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h +++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h @@ -36,7 +36,7 @@ inline bool SupportsFormat(DXGI_FORMAT format, const Renderer11DeviceCaps &devic D3D11_FORMAT_SUPPORT_RENDER_TARGET; UINT minimumRequiredSamples = 0; - if (d3d11_gl::GetMaximumClientVersion(deviceCaps).major > 2) + if (d3d11_gl::GetMaximumClientVersion(deviceCaps) >= gl::ES_3_0) { mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D; diff --git a/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp index 429159b4cb2..50a9b44c85b 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp @@ -6,6 +6,10 @@ // Blit9.cpp: Surface copy utility class. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/Blit9.h" #include "libANGLE/Context.h" diff --git a/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp index dbf875134bd..18dd4d09604 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -4,7 +4,11 @@ // found in the LICENSE file. // -// Buffer9.cpp Defines the Buffer9 class. +// Buffer9.cpp: Defines the Buffer9 class. + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/d3d/d3d9/Buffer9.h" @@ -37,7 +41,8 @@ angle::Result Buffer9::setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { if (size > mMemory.size()) { @@ -50,9 +55,9 @@ angle::Result Buffer9::setData(const gl::Context *context, memcpy(mMemory.data(), data, size); } - updateD3DBufferUsage(context, usage); + updateD3DBufferUsage(context, usage, feedback); - invalidateStaticData(context); + invalidateStaticData(context, feedback); return angle::Result::Continue; } @@ -74,7 +79,8 @@ angle::Result Buffer9::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { if (offset + size > mMemory.size()) { @@ -87,7 +93,7 @@ angle::Result Buffer9::setSubData(const gl::Context *context, memcpy(mMemory.data() + offset, data, size); } - invalidateStaticData(context); + invalidateStaticData(context, feedback); return angle::Result::Continue; } @@ -96,7 +102,8 @@ angle::Result Buffer9::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { // Note: this method is currently unreachable Buffer9 *sourceBuffer = GetAs(source); @@ -104,13 +111,16 @@ angle::Result Buffer9::copySubData(const gl::Context *context, memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); - invalidateStaticData(context); + invalidateStaticData(context, feedback); return angle::Result::Continue; } // We do not support buffer mapping in D3D9 -angle::Result Buffer9::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result Buffer9::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { ANGLE_HR_UNREACHABLE(GetImplAs(context)); return angle::Result::Stop; @@ -120,19 +130,23 @@ angle::Result Buffer9::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { ANGLE_HR_UNREACHABLE(GetImplAs(context)); return angle::Result::Stop; } -angle::Result Buffer9::unmap(const gl::Context *context, GLboolean *result) +angle::Result Buffer9::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { ANGLE_HR_UNREACHABLE(GetImplAs(context)); return angle::Result::Stop; } -angle::Result Buffer9::markTransformFeedbackUsage(const gl::Context *context) +angle::Result Buffer9::markTransformFeedbackUsage(const gl::Context *context, + BufferFeedback *feedback) { ANGLE_HR_UNREACHABLE(GetImplAs(context)); return angle::Result::Stop; diff --git a/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/libANGLE/renderer/d3d/d3d9/Buffer9.h index dad120d75b9..ecd78618cd0 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Buffer9.h +++ b/src/libANGLE/renderer/d3d/d3d9/Buffer9.h @@ -33,25 +33,35 @@ class Buffer9 : public BufferD3D gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; - angle::Result markTransformFeedbackUsage(const gl::Context *context) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; + angle::Result markTransformFeedbackUsage(const gl::Context *context, + BufferFeedback *feedback) override; private: angle::MemoryBuffer mMemory; diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp index b9a0ed12c54..99c1e17d327 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp @@ -9,6 +9,8 @@ #include "libANGLE/renderer/d3d/d3d9/Context9.h" +#include + #include "common/entry_points_enum_autogen.h" #include "common/string_utils.h" #include "image_util/loadimage.h" @@ -103,9 +105,10 @@ BufferImpl *Context9::createBuffer(const gl::BufferState &state) return new Buffer9(state, mRenderer); } -VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data) +VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) { - return new VertexArray9(data); + return new VertexArray9(data, vertexArrayBuffers); } QueryImpl *Context9::createQuery(gl::QueryType type) @@ -405,12 +408,11 @@ angle::Result Context9::pushGroupMarker(GLsizei length, const char *marker) angle::Result Context9::popGroupMarker() { - const char *marker = nullptr; if (!mMarkerStack.empty()) { - marker = mMarkerStack.top().c_str(); + std::string marker = std::move(mMarkerStack.top()); mMarkerStack.pop(); - mRenderer->getAnnotator()->endEvent(nullptr, marker, + mRenderer->getAnnotator()->endEvent(nullptr, marker.c_str(), angle::EntryPoint::GLPopGroupMarkerEXT); } return angle::Result::Continue; diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/libANGLE/renderer/d3d/d3d9/Context9.h index 81097e5e7e5..8cf106f8371 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Context9.h +++ b/src/libANGLE/renderer/d3d/d3d9/Context9.h @@ -47,7 +47,8 @@ class Context9 : public ContextD3D BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; diff --git a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp index f90fefac20e..2ec71ef4dd1 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -243,6 +243,8 @@ angle::Result Framebuffer9::blitImpl(const gl::Context *context, const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0); ASSERT(drawBuffer); + // GL_OVR_multiview_multisampled_render_to_texture is not supported on D3D backend + ASSERT(!(drawBuffer->isRenderToTexture() && drawBuffer->isMultiview())); RenderTarget9 *drawRenderTarget = nullptr; ANGLE_TRY( @@ -361,6 +363,8 @@ angle::Result Framebuffer9::blitImpl(const gl::Context *context, const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); ASSERT(drawBuffer); + // GL_OVR_multiview_multisampled_render_to_texture is not supported on D3D backend + ASSERT(!(drawBuffer->isRenderToTexture() && drawBuffer->isMultiview())); RenderTarget9 *drawDepthStencil = nullptr; ANGLE_TRY( diff --git a/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/libANGLE/renderer/d3d/d3d9/Image9.cpp index 707b2b2731c..c4e4688abcd 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Image9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -7,6 +7,10 @@ // Image9.cpp: Implements the rx::Image9 class, which acts as the interface to // the actual underlying surfaces of a Texture. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/Image9.h" #include "common/utilities.h" @@ -943,7 +947,7 @@ angle::Result Image9::copyFromTexStorage(const gl::Context *context, TextureStorage *source) { RenderTargetD3D *renderTarget = nullptr; - ANGLE_TRY(source->getRenderTarget(context, imageIndex, 0, &renderTarget)); + ANGLE_TRY(source->getRenderTarget(context, imageIndex, &renderTarget)); gl::Rectangle sourceArea(0, 0, mWidth, mHeight); return copyFromRTInternal(GetImplAs(context), gl::Offset(), sourceArea, renderTarget); diff --git a/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/src/libANGLE/renderer/d3d/d3d9/Query9.cpp index aeefd6a29f2..e6572085905 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Query9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Query9.cpp @@ -138,18 +138,6 @@ angle::Result Query9::testQuery(Context9 *context9) break; } - case gl::QueryType::CommandsCompleted: - { - BOOL completed = FALSE; - result = mQuery->GetData(&completed, sizeof(completed), D3DGETDATA_FLUSH); - if (result == S_OK) - { - mQueryFinished = true; - mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE; - } - break; - } - default: UNREACHABLE(); break; diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index b7462edd55e..c81d071a801 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -6,6 +6,10 @@ // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" #include @@ -1165,6 +1169,8 @@ angle::Result Renderer9::updateState(const gl::Context *context, gl::PrimitiveMo if (firstColorAttachment) { ASSERT(firstColorAttachment->isAttached()); + // GL_OVR_multiview_multisampled_render_to_texture is not supported on D3D backend + ASSERT(!(firstColorAttachment->isRenderToTexture() && firstColorAttachment->isMultiview())); RenderTarget9 *renderTarget = nullptr; ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(), &renderTarget)); @@ -1204,6 +1210,8 @@ angle::Result Renderer9::setBlendDepthRasterStates(const gl::Context *context, if (firstColorAttachment) { ASSERT(firstColorAttachment->isAttached()); + // GL_OVR_multiview_multisampled_render_to_texture is not supported on D3D backend + ASSERT(!(firstColorAttachment->isRenderToTexture() && firstColorAttachment->isMultiview())); RenderTarget9 *renderTarget = nullptr; ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(), &renderTarget)); @@ -1496,16 +1504,17 @@ angle::Result Renderer9::drawElementsImpl(const gl::Context *context, ANGLE_TRY(applyIndexBuffer(context, indices, count, mode, type, &indexInfo)); gl::IndexRange indexRange; - ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, indices, - &indexRange)); + ANGLE_TRY(context->getState().getVertexArray()->getIndexRange( + context, type, count, indices, context->getState().isPrimitiveRestartEnabled(), + &indexRange)); size_t vertexCount = indexRange.vertexCount(); - ANGLE_TRY(applyVertexBuffer(context, mode, static_cast(indexRange.start), + ANGLE_TRY(applyVertexBuffer(context, mode, static_cast(indexRange.start()), static_cast(vertexCount), instances, &indexInfo)); startScene(); - int minIndex = static_cast(indexRange.start); + int minIndex = static_cast(indexRange.start()); gl::VertexArray *vao = context->getState().getVertexArray(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); @@ -2604,7 +2613,7 @@ angle::Result Renderer9::createRenderTarget(const gl::Context *context, const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format); const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); + GLuint supportedSamples = textureCaps.sampleCounts.getNearestSamples(samples); IDirect3DTexture9 *texture = nullptr; IDirect3DSurface9 *renderTarget = nullptr; diff --git a/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp index b18645eb6e9..49519229772 100644 --- a/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp @@ -5,6 +5,11 @@ // // StateManager9.cpp: Defines a class for caching D3D9 state + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/StateManager9.h" #include "common/bitset_utils.h" diff --git a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp index 9d3f15d08d9..f87b8c3e8cb 100644 --- a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp @@ -8,6 +8,10 @@ // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the // D3D9 texture. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" #include "common/utilities.h" @@ -192,7 +196,6 @@ angle::Result TextureStorage9_2D::getSurfaceLevel(const gl::Context *context, angle::Result TextureStorage9_2D::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ASSERT(index.getLevelIndex() < getLevelCount()); @@ -204,7 +207,6 @@ angle::Result TextureStorage9_2D::findRenderTarget(const gl::Context *context, angle::Result TextureStorage9_2D::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(index.getLevelIndex() < getLevelCount()); @@ -330,7 +332,6 @@ angle::Result TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *conte angle::Result TextureStorage9_EGLImage::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { // Since the render target of a EGL image will be updated when orphaning, trying to find a cache @@ -341,12 +342,10 @@ angle::Result TextureStorage9_EGLImage::findRenderTarget(const gl::Context *cont angle::Result TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); ASSERT(index.getLevelIndex() == 0); - ASSERT(samples == 0); return mImage->getRenderTarget(context, outRT); } @@ -469,12 +468,10 @@ angle::Result TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context, angle::Result TextureStorage9_Cube::findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const { ASSERT(outRT); ASSERT(index.getLevelIndex() == 0); - ASSERT(samples == 0); ASSERT(index.getType() == gl::TextureType::CubeMap && gl::IsCubeMapFaceTarget(index.getTarget())); @@ -486,12 +483,10 @@ angle::Result TextureStorage9_Cube::findRenderTarget(const gl::Context *context, angle::Result TextureStorage9_Cube::getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) { ASSERT(outRT); ASSERT(index.getLevelIndex() == 0); - ASSERT(samples == 0); ASSERT(index.getType() == gl::TextureType::CubeMap && gl::IsCubeMapFaceTarget(index.getTarget())); diff --git a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h index 938a3c5aac6..8e14af6e0ea 100644 --- a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h +++ b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h @@ -93,11 +93,9 @@ class TextureStorage9_2D : public TextureStorage9 IDirect3DSurface9 **outSurface) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) override; angle::Result getBaseTexture(const gl::Context *context, IDirect3DBaseTexture9 **outTexture) override; @@ -127,11 +125,9 @@ class TextureStorage9_EGLImage final : public TextureStorage9 IDirect3DSurface9 **outSurface) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) override; angle::Result getBaseTexture(const gl::Context *context, IDirect3DBaseTexture9 **outTexture) override; @@ -164,11 +160,9 @@ class TextureStorage9_Cube : public TextureStorage9 IDirect3DSurface9 **outSurface) override; angle::Result findRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) const override; angle::Result getRenderTarget(const gl::Context *context, const gl::ImageIndex &index, - GLsizei samples, RenderTargetD3D **outRT) override; angle::Result getBaseTexture(const gl::Context *context, IDirect3DBaseTexture9 **outTexture) override; diff --git a/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h index b9fcf19e69a..2e18e0883c5 100644 --- a/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h +++ b/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -9,6 +9,10 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ #define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Context.h" #include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/d3d/d3d9/Context9.h" @@ -21,7 +25,9 @@ class Renderer9; class VertexArray9 : public VertexArrayImpl { public: - VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {} + VertexArray9(const gl::VertexArrayState &data, const gl::VertexArrayBuffers &vertexArrayBuffers) + : VertexArrayImpl(data, vertexArrayBuffers) + {} angle::Result syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, diff --git a/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp index 915928686aa..dccdf2a9329 100644 --- a/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -6,6 +6,10 @@ // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" #include "libANGLE/Buffer.h" diff --git a/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp index 9679dd0dde1..7d0d511dfcb 100644 --- a/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -6,6 +6,10 @@ // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" #include "libANGLE/Context.h" diff --git a/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp index 482ecbba5d9..4b030671bf5 100644 --- a/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp @@ -7,6 +7,10 @@ // formatutils9.cpp: Queries for GL image formats and their translations to D3D9 // formats. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/d3d/d3d9/formatutils9.h" #include "image_util/copyimage.h" @@ -148,6 +152,7 @@ static D3D9FormatMap BuildD3D9FormatMap() InsertD3D9FormatInfo(&map, GL_SRGB8, D3DFMT_X8R8G8B8, D3DFMT_UNKNOWN, LoadRGB8ToBGRX8 ); InsertD3D9FormatInfo(&map, GL_SRGB8_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_BGRA_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ); InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ); InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); diff --git a/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp index 24614a07cd8..52e9cdad65a 100644 --- a/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -365,8 +365,6 @@ D3DQUERYTYPE ConvertQueryType(gl::QueryType type) case gl::QueryType::AnySamples: case gl::QueryType::AnySamplesConservative: return D3DQUERYTYPE_OCCLUSION; - case gl::QueryType::CommandsCompleted: - return D3DQUERYTYPE_EVENT; default: UNREACHABLE(); return static_cast(0); @@ -481,6 +479,11 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, textureCaps.sampleCounts.insert(1); for (unsigned int i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) { + if (!gl::isPow2(i)) + { + continue; + } + D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); HRESULT result = d3d9->CheckDeviceMultiSampleType( @@ -521,7 +524,7 @@ void GenerateCaps(IDirect3D9 *d3d9, adapter, currentDisplayMode.Format); textureCapsMap->insert(internalFormat, textureCaps); - maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + maxSamples = std::max(maxSamples, textureCaps.sampleCounts.getMaxSamples()); } // GL core feature limits @@ -761,7 +764,6 @@ void GenerateCaps(IDirect3D9 *d3d9, extensions->EGLImageExternalOES = true; extensions->unpackSubimageEXT = true; extensions->packSubimageNV = true; - extensions->syncQueryCHROMIUM = extensions->fenceNV; extensions->copyTextureCHROMIUM = true; extensions->textureBorderClampEXT = true; extensions->textureBorderClampOES = true; diff --git a/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h index fb172448d10..1d0638316b5 100644 --- a/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h +++ b/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h @@ -10,6 +10,10 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ #define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include diff --git a/src/libANGLE/renderer/driver_utils.cpp b/src/libANGLE/renderer/driver_utils.cpp index 2520b9031ad..52d1a8c226e 100644 --- a/src/libANGLE/renderer/driver_utils.cpp +++ b/src/libANGLE/renderer/driver_utils.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // driver_utils.h : provides more information about current driver. #include diff --git a/src/libANGLE/renderer/driver_utils.h b/src/libANGLE/renderer/driver_utils.h index 156c3adfbee..e45132b7806 100644 --- a/src/libANGLE/renderer/driver_utils.h +++ b/src/libANGLE/renderer/driver_utils.h @@ -45,7 +45,6 @@ enum VendorID : uint32_t enum AndroidDeviceID : uint32_t { - ANDROID_DEVICE_ID_UNKNOWN = 0x0, ANDROID_DEVICE_ID_NEXUS5X = 0x4010800, ANDROID_DEVICE_ID_PIXEL2 = 0x5040001, ANDROID_DEVICE_ID_PIXEL1XL = 0x5030004, @@ -53,6 +52,7 @@ enum AndroidDeviceID : uint32_t ANDROID_DEVICE_ID_GALAXYA23 = 0x6010901, ANDROID_DEVICE_ID_GALAXYS23 = 0x43050A01, ANDROID_DEVICE_ID_SWIFTSHADER = 0xC0DE, + ANDROID_DEVICE_ID_LAVAPIPE = 0x0, }; inline bool IsAMD(uint32_t vendorId) @@ -132,6 +132,11 @@ inline bool IsVirtIO(uint32_t vendorId) return vendorId == VENDOR_ID_VIRTIO; } +inline bool IsMesa(uint32_t vendorId) +{ + return vendorId == VENDOR_ID_MESA; +} + inline bool IsNexus5X(uint32_t vendorId, uint32_t deviceId) { return IsQualcomm(vendorId) && deviceId == ANDROID_DEVICE_ID_NEXUS5X; @@ -167,6 +172,11 @@ inline bool IsSwiftshader(uint32_t vendorId, uint32_t deviceId) return IsGoogle(vendorId) && deviceId == ANDROID_DEVICE_ID_SWIFTSHADER; } +inline bool IsLavapipe(uint32_t vendorId, uint32_t deviceId) +{ + return IsMesa(vendorId) && deviceId == ANDROID_DEVICE_ID_LAVAPIPE; +} + std::string GetVendorString(uint32_t vendorId); bool IsSandyBridge(uint32_t DeviceId); diff --git a/src/libANGLE/renderer/dxgi_support_table_autogen.cpp b/src/libANGLE/renderer/dxgi_support_table_autogen.cpp index 56bbaed0dba..f8efe9ff097 100644 --- a/src/libANGLE/renderer/dxgi_support_table_autogen.cpp +++ b/src/libANGLE/renderer/dxgi_support_table_autogen.cpp @@ -3031,6 +3031,8 @@ const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL feat case D3D_FEATURE_LEVEL_11_0: return GetDXGISupport_11_0(dxgiFormat); case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_12_1: return GetDXGISupport_11_1(dxgiFormat); default: return GetDefaultSupport(); diff --git a/src/libANGLE/renderer/gen_angle_format_table.py b/src/libANGLE/renderer/gen_angle_format_table.py index 7ac8a7556a5..ce82d753b43 100644 --- a/src/libANGLE/renderer/gen_angle_format_table.py +++ b/src/libANGLE/renderer/gen_angle_format_table.py @@ -67,7 +67,10 @@ static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {{angle::FormatID::R8G8B8A8_UNORM, CopyBGRA8ToRGBA8}}; +static constexpr rx::FastCopyFunctionMap::Entry RGBAEntry = {{angle::FormatID::R8G8B8A8_UNORM, + CopyRGBA8ToRGBA8}}; static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {{&BGRAEntry, 1}}; +static constexpr rx::FastCopyFunctionMap RGBACopyFunctions = {{&RGBAEntry, 1}}; static constexpr rx::FastCopyFunctionMap NoCopyFunctions; const Format gFormatInfoTable[] = {{ @@ -325,6 +328,7 @@ def get_vertex_attrib_type(format_id): has_r16 = "R16" in format_id has_r32 = "R32" in format_id has_r10 = "R10" in format_id + has_r10x6 = "R10X6" in format_id has_vertex = "VERTEX" in format_id if has_fixed: @@ -336,6 +340,9 @@ def get_vertex_attrib_type(format_id): if has_r8: return "Byte" if has_s else "UnsignedByte" + if has_r10x6: + return "InvalidEnum" + if has_r10: if has_vertex: return "Int1010102" if has_s else "UnsignedInt1010102" @@ -399,6 +406,12 @@ def json_to_table_data(format_id, json, angle_to_gl): if format_id == "B8G8R8A8_UNORM": parsed["fastCopyFunctions"] = "BGRACopyFunctions" + if format_id == "R8G8B8A8_UNORM": + parsed["fastCopyFunctions"] = "RGBACopyFunctions" + + if format_id == "R8G8B8A8_UNORM_SRGB": + parsed["fastCopyFunctions"] = "RGBACopyFunctions" + is_block = format_id.endswith("_BLOCK") pixel_bytes = 0 diff --git a/src/libANGLE/renderer/gen_dxgi_support_tables.py b/src/libANGLE/renderer/gen_dxgi_support_tables.py index a688063a729..c145847ed05 100644 --- a/src/libANGLE/renderer/gen_dxgi_support_tables.py +++ b/src/libANGLE/renderer/gen_dxgi_support_tables.py @@ -157,6 +157,8 @@ case D3D_FEATURE_LEVEL_11_0: return GetDXGISupport_11_0(dxgiFormat); case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_12_1: return GetDXGISupport_11_1(dxgiFormat); default: return GetDefaultSupport(); diff --git a/src/libANGLE/renderer/gl/BUILD.gn b/src/libANGLE/renderer/gl/BUILD.gn index 7e50ce353d1..6be94901ed9 100644 --- a/src/libANGLE/renderer/gl/BUILD.gn +++ b/src/libANGLE/renderer/gl/BUILD.gn @@ -7,7 +7,7 @@ import("../../../../gni/angle.gni") import("gl_backend.gni") -if (angle_has_build && ozone_platform_gbm) { +if (angle_use_gbm) { import("//build/config/linux/pkg_config.gni") } @@ -18,10 +18,7 @@ config("angle_gl_backend_config") { if (angle_enable_gl_desktop_backend) { defines += [ "ANGLE_ENABLE_GL_DESKTOP_BACKEND" ] } - if (angle_enable_gl_null) { - defines += [ "ANGLE_ENABLE_OPENGL_NULL" ] - } - if (ozone_platform_gbm) { + if (angle_use_gbm) { defines += [ "ANGLE_USE_GBM" ] } if (is_apple) { diff --git a/src/libANGLE/renderer/gl/BlitGL.cpp b/src/libANGLE/renderer/gl/BlitGL.cpp index eb5cfa87316..19780ad0295 100644 --- a/src/libANGLE/renderer/gl/BlitGL.cpp +++ b/src/libANGLE/renderer/gl/BlitGL.cpp @@ -6,6 +6,10 @@ // BlitGL.cpp: Implements the BlitGL class, a helper for blitting textures +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/BlitGL.h" #include "common/FixedVector.h" @@ -374,7 +378,7 @@ angle::Result BlitGL::copySubImageToLUMAWorkaroundTexture(const gl::Context *con } nativegl::CopyTexImageImageFormat copyTexImageFormat = - nativegl::GetCopyTexImageImageFormat(mFunctions, mFeatures, readFormat, readType); + nativegl::GetCopyTexImageImageFormat(mFunctions, mFeatures, readFormat); mStateManager->bindTexture(gl::TextureType::_2D, mScratchTextures[0]); ANGLE_GL_TRY_ALWAYS_CHECK( @@ -543,7 +547,7 @@ angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context, const gl::InternalFormat &sourceInternalFormat = *readAttachment->getFormat().info; nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat( - mFunctions, mFeatures, sourceInternalFormat.internalFormat, sourceInternalFormat.type); + mFunctions, mFeatures, sourceInternalFormat.internalFormat); const FramebufferGL *sourceGL = GetImplAs(source); mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceGL->getFramebufferID()); mStateManager->bindTexture(gl::TextureType::_2D, textureId); diff --git a/src/libANGLE/renderer/gl/BufferGL.cpp b/src/libANGLE/renderer/gl/BufferGL.cpp index df0f4417555..53760da3d4e 100644 --- a/src/libANGLE/renderer/gl/BufferGL.cpp +++ b/src/libANGLE/renderer/gl/BufferGL.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // BufferGL.cpp: Implements the class methods for BufferGL. #include "libANGLE/renderer/gl/BufferGL.h" @@ -84,7 +88,8 @@ angle::Result BufferGL::setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); @@ -123,7 +128,8 @@ angle::Result BufferGL::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); @@ -147,7 +153,8 @@ angle::Result BufferGL::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); @@ -178,7 +185,10 @@ angle::Result BufferGL::copySubData(const gl::Context *context, return angle::Result::Continue; } -angle::Result BufferGL::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result BufferGL::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); @@ -223,7 +233,8 @@ angle::Result BufferGL::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); @@ -255,7 +266,9 @@ angle::Result BufferGL::mapRange(const gl::Context *context, return angle::Result::Continue; } -angle::Result BufferGL::unmap(const gl::Context *context, GLboolean *result) +angle::Result BufferGL::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); @@ -320,7 +333,7 @@ angle::Result BufferGL::getIndexRange(const gl::Context *context, else { // Workaround the null driver not having map support. - *outRange = gl::IndexRange(0, 0, 1); + *outRange = gl::IndexRange(0, 0); } } diff --git a/src/libANGLE/renderer/gl/BufferGL.h b/src/libANGLE/renderer/gl/BufferGL.h index aece53f8e1c..e5c03b2418a 100644 --- a/src/libANGLE/renderer/gl/BufferGL.h +++ b/src/libANGLE/renderer/gl/BufferGL.h @@ -32,24 +32,33 @@ class BufferGL : public BufferImpl gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, diff --git a/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp b/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp index 9af41d804a9..efbbb6e8be2 100644 --- a/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp +++ b/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp @@ -42,6 +42,8 @@ void ClearMultiviewGL::clearMultiviewFBO(const gl::FramebufferState &state, const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment(); if (firstAttachment->isMultiview()) { + // GL_OVR_multiview_multisampled_render_to_texture is not supported on GL backend + ASSERT(!firstAttachment->isRenderToTexture()); clearLayeredFBO(state, clearCommandType, mask, buffer, drawbuffer, values, depth, stencil); } } @@ -60,7 +62,7 @@ void ClearMultiviewGL::clearLayeredFBO(const gl::FramebufferState &state, mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer); const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment(); - ASSERT(firstAttachment->isMultiview()); + ASSERT(firstAttachment->isMultiview() && !firstAttachment->isRenderToTexture()); const auto &drawBuffers = state.getDrawBufferStates(); mFunctions->drawBuffers(static_cast(drawBuffers.size()), drawBuffers.data()); diff --git a/src/libANGLE/renderer/gl/CompilerGL.cpp b/src/libANGLE/renderer/gl/CompilerGL.cpp index c0954969d89..3d08c4fa39d 100644 --- a/src/libANGLE/renderer/gl/CompilerGL.cpp +++ b/src/libANGLE/renderer/gl/CompilerGL.cpp @@ -17,7 +17,7 @@ namespace rx { CompilerGL::CompilerGL(const ContextGL *context) - : mTranslatorOutputType(GetShaderOutputType(context->getFunctions())) + : mTranslatorOutputType(GetShaderOutputType(context->getFeaturesGL(), context->getFunctions())) {} ShShaderOutput CompilerGL::getTranslatorOutputType() const diff --git a/src/libANGLE/renderer/gl/ContextGL.cpp b/src/libANGLE/renderer/gl/ContextGL.cpp index 527fc0a7db8..3f7f5c45df1 100644 --- a/src/libANGLE/renderer/gl/ContextGL.cpp +++ b/src/libANGLE/renderer/gl/ContextGL.cpp @@ -7,6 +7,10 @@ // OpenGL-specific functionality associated with a GL Context. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/ContextGL.h" #include "libANGLE/Context.h" @@ -142,7 +146,8 @@ BufferImpl *ContextGL::createBuffer(const gl::BufferState &state) return new BufferGL(state, buffer); } -VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data) +VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) { const FunctionsGL *functions = getFunctions(); const angle::FeaturesGL &features = getFeaturesGL(); @@ -158,27 +163,20 @@ VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data) { StateManagerGL *stateManager = getStateManager(); - return new VertexArrayGL(data, stateManager->getDefaultVAO(), + return new VertexArrayGL(data, stateManager->getDefaultVAO(), vertexArrayBuffers, stateManager->getDefaultVAOState()); } else { GLuint vao = 0; functions->genVertexArrays(1, &vao); - return new VertexArrayGL(data, vao); + return new VertexArrayGL(data, vao, vertexArrayBuffers); } } QueryImpl *ContextGL::createQuery(gl::QueryType type) { - switch (type) - { - case gl::QueryType::CommandsCompleted: - return new SyncQueryGL(type, getFunctions()); - - default: - return new StandardQueryGL(type, getFunctions(), getStateManager()); - } + return new StandardQueryGL(type, getFunctions(), getStateManager()); } FenceNVImpl *ContextGL::createFenceNV() @@ -257,7 +255,7 @@ ANGLE_INLINE angle::Result ContextGL::setDrawArraysState(const gl::Context *cont GLsizei instanceCount) { const angle::FeaturesGL &features = getFeaturesGL(); - if (context->getStateCache().hasAnyActiveClientAttrib() || + if (context->hasAnyActiveClientAttrib() || (features.shiftInstancedArrayDataWithOffset.enabled && first > 0)) { const gl::State &glState = context->getState(); @@ -302,7 +300,6 @@ ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *co const gl::State &glState = context->getState(); const gl::ProgramExecutable *executable = getState().getProgramExecutable(); const gl::VertexArray *vao = glState.getVertexArray(); - const gl::StateCache &stateCache = context->getStateCache(); const angle::FeaturesGL &features = getFeaturesGL(); if (features.shiftInstancedArrayDataWithOffset.enabled) @@ -313,7 +310,7 @@ ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *co ANGLE_TRY(vaoGL->recoverForcedStreamingAttributesForDrawArraysInstanced(context)); } - if (stateCache.hasAnyActiveClientAttrib() || vao->getElementArrayBuffer() == nullptr) + if (context->hasAnyActiveClientAttrib() || vao->getElementArrayBuffer() == nullptr) { const VertexArrayGL *vaoGL = GetImplAs(vao); ANGLE_TRY(vaoGL->syncDrawElementsState(context, executable->getActiveAttribLocationsMask(), @@ -406,8 +403,8 @@ gl::AttributesMask ContextGL::updateAttributesForBaseInstance(GLuint baseInstanc const char *p = static_cast(attrib.pointer); const size_t sourceStride = gl::ComputeVertexAttributeStride(attrib, binding); const void *newPointer = p + sourceStride * baseInstance; - - const BufferGL *buffer = GetImplAs(binding.getBuffer().get()); + const BufferGL *buffer = GetImplAs( + mState.getVertexArray()->getVertexArrayBuffer(attrib.bindingIndex)); // We often stream data from scratch buffers when client side data is being used // and that information is in VertexArrayGL. // Assert that the buffer is non-null because this case isn't handled. @@ -440,11 +437,10 @@ void ContextGL::resetUpdatedAttributes(gl::AttributesMask attribMask) { const gl::VertexAttribute &attrib = mState.getVertexArray()->getVertexAttributes()[attribIndex]; - const gl::VertexBinding &binding = - (mState.getVertexArray()->getVertexBindings())[attrib.bindingIndex]; - getStateManager()->bindBuffer( - gl::BufferBinding::Array, - GetImplAs(binding.getBuffer().get())->getBufferID()); + const gl::Buffer *buffer = + mState.getVertexArray()->getVertexArrayBuffer(attrib.bindingIndex); + getStateManager()->bindBuffer(gl::BufferBinding::Array, + GetImplAs(buffer)->getBufferID()); if (attrib.format->isPureInt()) { functions->vertexAttribIPointer(static_cast(attribIndex), diff --git a/src/libANGLE/renderer/gl/ContextGL.h b/src/libANGLE/renderer/gl/ContextGL.h index d1bf303085e..28bd587a05f 100644 --- a/src/libANGLE/renderer/gl/ContextGL.h +++ b/src/libANGLE/renderer/gl/ContextGL.h @@ -68,7 +68,8 @@ class ContextGL : public ContextImpl BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; diff --git a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp index eef3c282d67..11bb36bd9ec 100644 --- a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp +++ b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp @@ -13,10 +13,6 @@ #include "libANGLE/Version.h" #include "libANGLE/renderer/gl/FunctionsGL.h" -#if defined(ANGLE_ENABLE_OPENGL_NULL) -# include "libANGLE/renderer/gl/null_functions.h" -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - #define ASSIGN(NAME, FP) \ do \ { \ @@ -2243,6 +2239,20 @@ void DispatchTableGL::initProcsGLES(const gl::Version &version, ASSIGN("glReadnPixelsKHR", readnPixels); } + if (extensions.count("GL_MESA_sampler_objects") != 0) + { + ASSIGN("glBindSampler", bindSampler); + ASSIGN("glDeleteSamplers", deleteSamplers); + ASSIGN("glGenSamplers", genSamplers); + ASSIGN("glGetSamplerParameterfv", getSamplerParameterfv); + ASSIGN("glGetSamplerParameteriv", getSamplerParameteriv); + ASSIGN("glIsSampler", isSampler); + ASSIGN("glSamplerParameterf", samplerParameterf); + ASSIGN("glSamplerParameterfv", samplerParameterfv); + ASSIGN("glSamplerParameteri", samplerParameteri); + ASSIGN("glSamplerParameteriv", samplerParameteriv); + } + if (extensions.count("GL_NV_framebuffer_blit") != 0) { ASSIGN("glBlitFramebufferNV", blitFramebufferNV); @@ -2259,6 +2269,11 @@ void DispatchTableGL::initProcsGLES(const gl::Version &version, ASSIGN("glEGLImageTargetTexture2DOES", eGLImageTargetTexture2DOES); } + if (extensions.count("GL_OES_EGL_image_external") != 0) + { + ASSIGN("glEGLImageTargetTexture2DOES", eGLImageTargetTexture2DOES); + } + if (extensions.count("GL_OES_copy_image") != 0) { ASSIGN("glCopyImageSubDataOES", copyImageSubData); @@ -2901,2883 +2916,8 @@ void DispatchTableGL::initProcsSharedExtensions(const std::set &ext if (extensions.count("GL_OVR_multiview") != 0) { ASSIGN("glFramebufferTextureMultiviewOVR", framebufferTextureMultiviewOVR); + ASSIGN("glNamedFramebufferTextureMultiviewOVR", namedFramebufferTextureMultiviewOVR); } } -#if defined(ANGLE_ENABLE_OPENGL_NULL) -void DispatchTableGL::initProcsDesktopGLNULL(const gl::Version &version, - const std::set &extensions) -{ -# if defined(ANGLE_ENABLE_GL_DESKTOP_BACKEND) - if (extensions.count("GL_ARB_ES2_compatibility") != 0) - { - clearDepthf = &glClearDepthfNULL; - depthRangef = &glDepthRangefNULL; - getShaderPrecisionFormat = &glGetShaderPrecisionFormatNULL; - releaseShaderCompiler = &glReleaseShaderCompilerNULL; - shaderBinary = &glShaderBinaryNULL; - } - - if (extensions.count("GL_ARB_ES3_1_compatibility") != 0) - { - memoryBarrierByRegion = &glMemoryBarrierByRegionNULL; - } - - if (extensions.count("GL_ARB_ES3_2_compatibility") != 0) - { - primitiveBoundingBox = &glPrimitiveBoundingBoxNULL; - } - - if (extensions.count("GL_ARB_base_instance") != 0) - { - drawArraysInstancedBaseInstance = &glDrawArraysInstancedBaseInstanceNULL; - drawElementsInstancedBaseInstance = &glDrawElementsInstancedBaseInstanceNULL; - drawElementsInstancedBaseVertexBaseInstance = - &glDrawElementsInstancedBaseVertexBaseInstanceNULL; - } - - if (extensions.count("GL_ARB_blend_func_extended") != 0) - { - bindFragDataLocationIndexed = &glBindFragDataLocationIndexedNULL; - getFragDataIndex = &glGetFragDataIndexNULL; - } - - if (extensions.count("GL_ARB_buffer_storage") != 0) - { - bufferStorage = &glBufferStorageNULL; - } - - if (extensions.count("GL_ARB_clear_buffer_object") != 0) - { - clearBufferData = &glClearBufferDataNULL; - clearBufferSubData = &glClearBufferSubDataNULL; - } - - if (extensions.count("GL_ARB_clear_texture") != 0) - { - clearTexImage = &glClearTexImageNULL; - clearTexSubImage = &glClearTexSubImageNULL; - } - - if (extensions.count("GL_ARB_clip_control") != 0) - { - clipControl = &glClipControlNULL; - } - - if (extensions.count("GL_ARB_color_buffer_float") != 0) - { - clampColor = &glClampColorNULL; - } - - if (extensions.count("GL_ARB_compute_shader") != 0) - { - dispatchCompute = &glDispatchComputeNULL; - dispatchComputeIndirect = &glDispatchComputeIndirectNULL; - } - - if (extensions.count("GL_ARB_copy_buffer") != 0) - { - copyBufferSubData = &glCopyBufferSubDataNULL; - } - - if (extensions.count("GL_ARB_copy_image") != 0) - { - copyImageSubData = &glCopyImageSubDataNULL; - } - - if (extensions.count("GL_ARB_debug_output") != 0) - { - debugMessageCallback = &glDebugMessageCallbackNULL; - debugMessageControl = &glDebugMessageControlNULL; - debugMessageInsert = &glDebugMessageInsertNULL; - getDebugMessageLog = &glGetDebugMessageLogNULL; - } - - if (extensions.count("GL_ARB_direct_state_access") != 0) - { - bindTextureUnit = &glBindTextureUnitNULL; - blitNamedFramebuffer = &glBlitNamedFramebufferNULL; - checkNamedFramebufferStatus = &glCheckNamedFramebufferStatusNULL; - clearNamedBufferData = &glClearNamedBufferDataNULL; - clearNamedBufferSubData = &glClearNamedBufferSubDataNULL; - clearNamedFramebufferfi = &glClearNamedFramebufferfiNULL; - clearNamedFramebufferfv = &glClearNamedFramebufferfvNULL; - clearNamedFramebufferiv = &glClearNamedFramebufferivNULL; - clearNamedFramebufferuiv = &glClearNamedFramebufferuivNULL; - compressedTextureSubImage1D = &glCompressedTextureSubImage1DNULL; - compressedTextureSubImage2D = &glCompressedTextureSubImage2DNULL; - compressedTextureSubImage3D = &glCompressedTextureSubImage3DNULL; - copyNamedBufferSubData = &glCopyNamedBufferSubDataNULL; - copyTextureSubImage1D = &glCopyTextureSubImage1DNULL; - copyTextureSubImage2D = &glCopyTextureSubImage2DNULL; - copyTextureSubImage3D = &glCopyTextureSubImage3DNULL; - createBuffers = &glCreateBuffersNULL; - createFramebuffers = &glCreateFramebuffersNULL; - createProgramPipelines = &glCreateProgramPipelinesNULL; - createQueries = &glCreateQueriesNULL; - createRenderbuffers = &glCreateRenderbuffersNULL; - createSamplers = &glCreateSamplersNULL; - createTextures = &glCreateTexturesNULL; - createTransformFeedbacks = &glCreateTransformFeedbacksNULL; - createVertexArrays = &glCreateVertexArraysNULL; - disableVertexArrayAttrib = &glDisableVertexArrayAttribNULL; - enableVertexArrayAttrib = &glEnableVertexArrayAttribNULL; - flushMappedNamedBufferRange = &glFlushMappedNamedBufferRangeNULL; - generateTextureMipmap = &glGenerateTextureMipmapNULL; - getCompressedTextureImage = &glGetCompressedTextureImageNULL; - getNamedBufferParameteri64v = &glGetNamedBufferParameteri64vNULL; - getNamedBufferParameteriv = &glGetNamedBufferParameterivNULL; - getNamedBufferPointerv = &glGetNamedBufferPointervNULL; - getNamedBufferSubData = &glGetNamedBufferSubDataNULL; - getNamedFramebufferAttachmentParameteriv = &glGetNamedFramebufferAttachmentParameterivNULL; - getNamedFramebufferParameteriv = &glGetNamedFramebufferParameterivNULL; - getNamedRenderbufferParameteriv = &glGetNamedRenderbufferParameterivNULL; - getQueryBufferObjecti64v = &glGetQueryBufferObjecti64vNULL; - getQueryBufferObjectiv = &glGetQueryBufferObjectivNULL; - getQueryBufferObjectui64v = &glGetQueryBufferObjectui64vNULL; - getQueryBufferObjectuiv = &glGetQueryBufferObjectuivNULL; - getTextureImage = &glGetTextureImageNULL; - getTextureLevelParameterfv = &glGetTextureLevelParameterfvNULL; - getTextureLevelParameteriv = &glGetTextureLevelParameterivNULL; - getTextureParameterIiv = &glGetTextureParameterIivNULL; - getTextureParameterIuiv = &glGetTextureParameterIuivNULL; - getTextureParameterfv = &glGetTextureParameterfvNULL; - getTextureParameteriv = &glGetTextureParameterivNULL; - getTransformFeedbacki64_v = &glGetTransformFeedbacki64_vNULL; - getTransformFeedbacki_v = &glGetTransformFeedbacki_vNULL; - getTransformFeedbackiv = &glGetTransformFeedbackivNULL; - getVertexArrayIndexed64iv = &glGetVertexArrayIndexed64ivNULL; - getVertexArrayIndexediv = &glGetVertexArrayIndexedivNULL; - getVertexArrayiv = &glGetVertexArrayivNULL; - invalidateNamedFramebufferData = &glInvalidateNamedFramebufferDataNULL; - invalidateNamedFramebufferSubData = &glInvalidateNamedFramebufferSubDataNULL; - mapNamedBuffer = &glMapNamedBufferNULL; - mapNamedBufferRange = &glMapNamedBufferRangeNULL; - namedBufferData = &glNamedBufferDataNULL; - namedBufferStorage = &glNamedBufferStorageNULL; - namedBufferSubData = &glNamedBufferSubDataNULL; - namedFramebufferDrawBuffer = &glNamedFramebufferDrawBufferNULL; - namedFramebufferDrawBuffers = &glNamedFramebufferDrawBuffersNULL; - namedFramebufferParameteri = &glNamedFramebufferParameteriNULL; - namedFramebufferReadBuffer = &glNamedFramebufferReadBufferNULL; - namedFramebufferRenderbuffer = &glNamedFramebufferRenderbufferNULL; - namedFramebufferTexture = &glNamedFramebufferTextureNULL; - namedFramebufferTextureLayer = &glNamedFramebufferTextureLayerNULL; - namedRenderbufferStorage = &glNamedRenderbufferStorageNULL; - namedRenderbufferStorageMultisample = &glNamedRenderbufferStorageMultisampleNULL; - textureBuffer = &glTextureBufferNULL; - textureBufferRange = &glTextureBufferRangeNULL; - textureParameterIiv = &glTextureParameterIivNULL; - textureParameterIuiv = &glTextureParameterIuivNULL; - textureParameterf = &glTextureParameterfNULL; - textureParameterfv = &glTextureParameterfvNULL; - textureParameteri = &glTextureParameteriNULL; - textureParameteriv = &glTextureParameterivNULL; - textureStorage1D = &glTextureStorage1DNULL; - textureStorage2D = &glTextureStorage2DNULL; - textureStorage2DMultisample = &glTextureStorage2DMultisampleNULL; - textureStorage3D = &glTextureStorage3DNULL; - textureStorage3DMultisample = &glTextureStorage3DMultisampleNULL; - textureSubImage1D = &glTextureSubImage1DNULL; - textureSubImage2D = &glTextureSubImage2DNULL; - textureSubImage3D = &glTextureSubImage3DNULL; - transformFeedbackBufferBase = &glTransformFeedbackBufferBaseNULL; - transformFeedbackBufferRange = &glTransformFeedbackBufferRangeNULL; - unmapNamedBuffer = &glUnmapNamedBufferNULL; - vertexArrayAttribBinding = &glVertexArrayAttribBindingNULL; - vertexArrayAttribFormat = &glVertexArrayAttribFormatNULL; - vertexArrayAttribIFormat = &glVertexArrayAttribIFormatNULL; - vertexArrayAttribLFormat = &glVertexArrayAttribLFormatNULL; - vertexArrayBindingDivisor = &glVertexArrayBindingDivisorNULL; - vertexArrayElementBuffer = &glVertexArrayElementBufferNULL; - vertexArrayVertexBuffer = &glVertexArrayVertexBufferNULL; - vertexArrayVertexBuffers = &glVertexArrayVertexBuffersNULL; - } - - if (extensions.count("GL_ARB_draw_buffers") != 0) - { - drawBuffers = &glDrawBuffersNULL; - } - - if (extensions.count("GL_ARB_draw_buffers_blend") != 0) - { - blendEquationSeparatei = &glBlendEquationSeparateiNULL; - blendEquationi = &glBlendEquationiNULL; - blendFuncSeparatei = &glBlendFuncSeparateiNULL; - blendFunci = &glBlendFunciNULL; - } - - if (extensions.count("GL_ARB_draw_elements_base_vertex") != 0) - { - drawElementsBaseVertex = &glDrawElementsBaseVertexNULL; - drawElementsInstancedBaseVertex = &glDrawElementsInstancedBaseVertexNULL; - drawRangeElementsBaseVertex = &glDrawRangeElementsBaseVertexNULL; - multiDrawElementsBaseVertex = &glMultiDrawElementsBaseVertexNULL; - } - - if (extensions.count("GL_ARB_draw_indirect") != 0) - { - drawArraysIndirect = &glDrawArraysIndirectNULL; - drawElementsIndirect = &glDrawElementsIndirectNULL; - } - - if (extensions.count("GL_ARB_draw_instanced") != 0) - { - drawArraysInstanced = &glDrawArraysInstancedNULL; - drawElementsInstanced = &glDrawElementsInstancedNULL; - } - - if (extensions.count("GL_ARB_fragment_program") != 0) - { - getProgramiv = &glGetProgramivNULL; - isProgram = &glIsProgramNULL; - } - - if (extensions.count("GL_ARB_framebuffer_no_attachments") != 0) - { - framebufferParameteri = &glFramebufferParameteriNULL; - getFramebufferParameteriv = &glGetFramebufferParameterivNULL; - } - - if (extensions.count("GL_ARB_framebuffer_object") != 0) - { - bindFramebuffer = &glBindFramebufferNULL; - bindRenderbuffer = &glBindRenderbufferNULL; - blitFramebuffer = &glBlitFramebufferNULL; - checkFramebufferStatus = &glCheckFramebufferStatusNULL; - deleteFramebuffers = &glDeleteFramebuffersNULL; - deleteRenderbuffers = &glDeleteRenderbuffersNULL; - framebufferRenderbuffer = &glFramebufferRenderbufferNULL; - framebufferTexture1D = &glFramebufferTexture1DNULL; - framebufferTexture2D = &glFramebufferTexture2DNULL; - framebufferTexture3D = &glFramebufferTexture3DNULL; - framebufferTextureLayer = &glFramebufferTextureLayerNULL; - genFramebuffers = &glGenFramebuffersNULL; - genRenderbuffers = &glGenRenderbuffersNULL; - generateMipmap = &glGenerateMipmapNULL; - getFramebufferAttachmentParameteriv = &glGetFramebufferAttachmentParameterivNULL; - getRenderbufferParameteriv = &glGetRenderbufferParameterivNULL; - isFramebuffer = &glIsFramebufferNULL; - isRenderbuffer = &glIsRenderbufferNULL; - renderbufferStorage = &glRenderbufferStorageNULL; - renderbufferStorageMultisample = &glRenderbufferStorageMultisampleNULL; - } - - if (extensions.count("GL_ARB_geometry_shader4") != 0) - { - framebufferTexture = &glFramebufferTextureNULL; - framebufferTextureLayer = &glFramebufferTextureLayerNULL; - programParameteri = &glProgramParameteriNULL; - } - - if (extensions.count("GL_ARB_get_program_binary") != 0) - { - getProgramBinary = &glGetProgramBinaryNULL; - programBinary = &glProgramBinaryNULL; - programParameteri = &glProgramParameteriNULL; - } - - if (extensions.count("GL_ARB_get_texture_sub_image") != 0) - { - getCompressedTextureSubImage = &glGetCompressedTextureSubImageNULL; - getTextureSubImage = &glGetTextureSubImageNULL; - } - - if (extensions.count("GL_ARB_gpu_shader_fp64") != 0) - { - getUniformdv = &glGetUniformdvNULL; - uniform1d = &glUniform1dNULL; - uniform1dv = &glUniform1dvNULL; - uniform2d = &glUniform2dNULL; - uniform2dv = &glUniform2dvNULL; - uniform3d = &glUniform3dNULL; - uniform3dv = &glUniform3dvNULL; - uniform4d = &glUniform4dNULL; - uniform4dv = &glUniform4dvNULL; - uniformMatrix2dv = &glUniformMatrix2dvNULL; - uniformMatrix2x3dv = &glUniformMatrix2x3dvNULL; - uniformMatrix2x4dv = &glUniformMatrix2x4dvNULL; - uniformMatrix3dv = &glUniformMatrix3dvNULL; - uniformMatrix3x2dv = &glUniformMatrix3x2dvNULL; - uniformMatrix3x4dv = &glUniformMatrix3x4dvNULL; - uniformMatrix4dv = &glUniformMatrix4dvNULL; - uniformMatrix4x2dv = &glUniformMatrix4x2dvNULL; - uniformMatrix4x3dv = &glUniformMatrix4x3dvNULL; - } - - if (extensions.count("GL_ARB_imaging") != 0) - { - blendColor = &glBlendColorNULL; - blendEquation = &glBlendEquationNULL; - } - - if (extensions.count("GL_ARB_instanced_arrays") != 0) - { - vertexAttribDivisor = &glVertexAttribDivisorNULL; - } - - if (extensions.count("GL_ARB_internalformat_query") != 0) - { - getInternalformativ = &glGetInternalformativNULL; - } - - if (extensions.count("GL_ARB_internalformat_query2") != 0) - { - getInternalformati64v = &glGetInternalformati64vNULL; - } - - if (extensions.count("GL_ARB_invalidate_subdata") != 0) - { - invalidateBufferData = &glInvalidateBufferDataNULL; - invalidateBufferSubData = &glInvalidateBufferSubDataNULL; - invalidateFramebuffer = &glInvalidateFramebufferNULL; - invalidateSubFramebuffer = &glInvalidateSubFramebufferNULL; - invalidateTexImage = &glInvalidateTexImageNULL; - invalidateTexSubImage = &glInvalidateTexSubImageNULL; - } - - if (extensions.count("GL_ARB_map_buffer_range") != 0) - { - flushMappedBufferRange = &glFlushMappedBufferRangeNULL; - mapBufferRange = &glMapBufferRangeNULL; - } - - if (extensions.count("GL_ARB_multi_bind") != 0) - { - bindBuffersBase = &glBindBuffersBaseNULL; - bindBuffersRange = &glBindBuffersRangeNULL; - bindImageTextures = &glBindImageTexturesNULL; - bindSamplers = &glBindSamplersNULL; - bindTextures = &glBindTexturesNULL; - bindVertexBuffers = &glBindVertexBuffersNULL; - } - - if (extensions.count("GL_ARB_multi_draw_indirect") != 0) - { - multiDrawArraysIndirect = &glMultiDrawArraysIndirectNULL; - multiDrawElementsIndirect = &glMultiDrawElementsIndirectNULL; - } - - if (extensions.count("GL_ARB_multisample") != 0) - { - sampleCoverage = &glSampleCoverageNULL; - } - - if (extensions.count("GL_ARB_multitexture") != 0) - { - activeTexture = &glActiveTextureNULL; - } - - if (extensions.count("GL_ARB_occlusion_query") != 0) - { - beginQuery = &glBeginQueryNULL; - deleteQueries = &glDeleteQueriesNULL; - endQuery = &glEndQueryNULL; - genQueries = &glGenQueriesNULL; - getQueryObjectiv = &glGetQueryObjectivNULL; - getQueryObjectuiv = &glGetQueryObjectuivNULL; - getQueryiv = &glGetQueryivNULL; - isQuery = &glIsQueryNULL; - } - - if (extensions.count("GL_ARB_parallel_shader_compile") != 0) - { - maxShaderCompilerThreadsARB = &glMaxShaderCompilerThreadsARBNULL; - } - - if (extensions.count("GL_ARB_point_parameters") != 0) - { - pointParameterf = &glPointParameterfNULL; - pointParameterfv = &glPointParameterfvNULL; - } - - if (extensions.count("GL_ARB_program_interface_query") != 0) - { - getProgramInterfaceiv = &glGetProgramInterfaceivNULL; - getProgramResourceIndex = &glGetProgramResourceIndexNULL; - getProgramResourceLocation = &glGetProgramResourceLocationNULL; - getProgramResourceLocationIndex = &glGetProgramResourceLocationIndexNULL; - getProgramResourceName = &glGetProgramResourceNameNULL; - getProgramResourceiv = &glGetProgramResourceivNULL; - } - - if (extensions.count("GL_ARB_provoking_vertex") != 0) - { - provokingVertex = &glProvokingVertexNULL; - } - - if (extensions.count("GL_ARB_robustness") != 0) - { - getGraphicsResetStatus = &glGetGraphicsResetStatusNULL; - getnCompressedTexImage = &glGetnCompressedTexImageNULL; - getnTexImage = &glGetnTexImageNULL; - getnUniformdv = &glGetnUniformdvNULL; - getnUniformfv = &glGetnUniformfvNULL; - getnUniformiv = &glGetnUniformivNULL; - getnUniformuiv = &glGetnUniformuivNULL; - readnPixels = &glReadnPixelsNULL; - } - - if (extensions.count("GL_ARB_sample_shading") != 0) - { - minSampleShading = &glMinSampleShadingNULL; - } - - if (extensions.count("GL_ARB_sampler_objects") != 0) - { - bindSampler = &glBindSamplerNULL; - deleteSamplers = &glDeleteSamplersNULL; - genSamplers = &glGenSamplersNULL; - getSamplerParameterIiv = &glGetSamplerParameterIivNULL; - getSamplerParameterIuiv = &glGetSamplerParameterIuivNULL; - getSamplerParameterfv = &glGetSamplerParameterfvNULL; - getSamplerParameteriv = &glGetSamplerParameterivNULL; - isSampler = &glIsSamplerNULL; - samplerParameterIiv = &glSamplerParameterIivNULL; - samplerParameterIuiv = &glSamplerParameterIuivNULL; - samplerParameterf = &glSamplerParameterfNULL; - samplerParameterfv = &glSamplerParameterfvNULL; - samplerParameteri = &glSamplerParameteriNULL; - samplerParameteriv = &glSamplerParameterivNULL; - } - - if (extensions.count("GL_ARB_separate_shader_objects") != 0) - { - activeShaderProgram = &glActiveShaderProgramNULL; - bindProgramPipeline = &glBindProgramPipelineNULL; - createShaderProgramv = &glCreateShaderProgramvNULL; - deleteProgramPipelines = &glDeleteProgramPipelinesNULL; - genProgramPipelines = &glGenProgramPipelinesNULL; - getProgramPipelineInfoLog = &glGetProgramPipelineInfoLogNULL; - getProgramPipelineiv = &glGetProgramPipelineivNULL; - isProgramPipeline = &glIsProgramPipelineNULL; - programParameteri = &glProgramParameteriNULL; - programUniform1d = &glProgramUniform1dNULL; - programUniform1dv = &glProgramUniform1dvNULL; - programUniform1f = &glProgramUniform1fNULL; - programUniform1fv = &glProgramUniform1fvNULL; - programUniform1i = &glProgramUniform1iNULL; - programUniform1iv = &glProgramUniform1ivNULL; - programUniform1ui = &glProgramUniform1uiNULL; - programUniform1uiv = &glProgramUniform1uivNULL; - programUniform2d = &glProgramUniform2dNULL; - programUniform2dv = &glProgramUniform2dvNULL; - programUniform2f = &glProgramUniform2fNULL; - programUniform2fv = &glProgramUniform2fvNULL; - programUniform2i = &glProgramUniform2iNULL; - programUniform2iv = &glProgramUniform2ivNULL; - programUniform2ui = &glProgramUniform2uiNULL; - programUniform2uiv = &glProgramUniform2uivNULL; - programUniform3d = &glProgramUniform3dNULL; - programUniform3dv = &glProgramUniform3dvNULL; - programUniform3f = &glProgramUniform3fNULL; - programUniform3fv = &glProgramUniform3fvNULL; - programUniform3i = &glProgramUniform3iNULL; - programUniform3iv = &glProgramUniform3ivNULL; - programUniform3ui = &glProgramUniform3uiNULL; - programUniform3uiv = &glProgramUniform3uivNULL; - programUniform4d = &glProgramUniform4dNULL; - programUniform4dv = &glProgramUniform4dvNULL; - programUniform4f = &glProgramUniform4fNULL; - programUniform4fv = &glProgramUniform4fvNULL; - programUniform4i = &glProgramUniform4iNULL; - programUniform4iv = &glProgramUniform4ivNULL; - programUniform4ui = &glProgramUniform4uiNULL; - programUniform4uiv = &glProgramUniform4uivNULL; - programUniformMatrix2dv = &glProgramUniformMatrix2dvNULL; - programUniformMatrix2fv = &glProgramUniformMatrix2fvNULL; - programUniformMatrix2x3dv = &glProgramUniformMatrix2x3dvNULL; - programUniformMatrix2x3fv = &glProgramUniformMatrix2x3fvNULL; - programUniformMatrix2x4dv = &glProgramUniformMatrix2x4dvNULL; - programUniformMatrix2x4fv = &glProgramUniformMatrix2x4fvNULL; - programUniformMatrix3dv = &glProgramUniformMatrix3dvNULL; - programUniformMatrix3fv = &glProgramUniformMatrix3fvNULL; - programUniformMatrix3x2dv = &glProgramUniformMatrix3x2dvNULL; - programUniformMatrix3x2fv = &glProgramUniformMatrix3x2fvNULL; - programUniformMatrix3x4dv = &glProgramUniformMatrix3x4dvNULL; - programUniformMatrix3x4fv = &glProgramUniformMatrix3x4fvNULL; - programUniformMatrix4dv = &glProgramUniformMatrix4dvNULL; - programUniformMatrix4fv = &glProgramUniformMatrix4fvNULL; - programUniformMatrix4x2dv = &glProgramUniformMatrix4x2dvNULL; - programUniformMatrix4x2fv = &glProgramUniformMatrix4x2fvNULL; - programUniformMatrix4x3dv = &glProgramUniformMatrix4x3dvNULL; - programUniformMatrix4x3fv = &glProgramUniformMatrix4x3fvNULL; - useProgramStages = &glUseProgramStagesNULL; - validateProgramPipeline = &glValidateProgramPipelineNULL; - } - - if (extensions.count("GL_ARB_shader_atomic_counters") != 0) - { - getActiveAtomicCounterBufferiv = &glGetActiveAtomicCounterBufferivNULL; - } - - if (extensions.count("GL_ARB_shader_image_load_store") != 0) - { - bindImageTexture = &glBindImageTextureNULL; - memoryBarrier = &glMemoryBarrierNULL; - } - - if (extensions.count("GL_ARB_shader_objects") != 0) - { - compileShader = &glCompileShaderNULL; - getActiveUniform = &glGetActiveUniformNULL; - getShaderSource = &glGetShaderSourceNULL; - getUniformLocation = &glGetUniformLocationNULL; - getUniformfv = &glGetUniformfvNULL; - getUniformiv = &glGetUniformivNULL; - linkProgram = &glLinkProgramNULL; - shaderSource = &glShaderSourceNULL; - uniform1f = &glUniform1fNULL; - uniform1fv = &glUniform1fvNULL; - uniform1i = &glUniform1iNULL; - uniform1iv = &glUniform1ivNULL; - uniform2f = &glUniform2fNULL; - uniform2fv = &glUniform2fvNULL; - uniform2i = &glUniform2iNULL; - uniform2iv = &glUniform2ivNULL; - uniform3f = &glUniform3fNULL; - uniform3fv = &glUniform3fvNULL; - uniform3i = &glUniform3iNULL; - uniform3iv = &glUniform3ivNULL; - uniform4f = &glUniform4fNULL; - uniform4fv = &glUniform4fvNULL; - uniform4i = &glUniform4iNULL; - uniform4iv = &glUniform4ivNULL; - uniformMatrix2fv = &glUniformMatrix2fvNULL; - uniformMatrix3fv = &glUniformMatrix3fvNULL; - uniformMatrix4fv = &glUniformMatrix4fvNULL; - validateProgram = &glValidateProgramNULL; - } - - if (extensions.count("GL_ARB_shader_storage_buffer_object") != 0) - { - shaderStorageBlockBinding = &glShaderStorageBlockBindingNULL; - } - - if (extensions.count("GL_ARB_shader_subroutine") != 0) - { - getActiveSubroutineName = &glGetActiveSubroutineNameNULL; - getActiveSubroutineUniformName = &glGetActiveSubroutineUniformNameNULL; - getActiveSubroutineUniformiv = &glGetActiveSubroutineUniformivNULL; - getProgramStageiv = &glGetProgramStageivNULL; - getSubroutineIndex = &glGetSubroutineIndexNULL; - getSubroutineUniformLocation = &glGetSubroutineUniformLocationNULL; - getUniformSubroutineuiv = &glGetUniformSubroutineuivNULL; - uniformSubroutinesuiv = &glUniformSubroutinesuivNULL; - } - - if (extensions.count("GL_ARB_sync") != 0) - { - clientWaitSync = &glClientWaitSyncNULL; - deleteSync = &glDeleteSyncNULL; - fenceSync = &glFenceSyncNULL; - getInteger64v = &glGetInteger64vNULL; - getSynciv = &glGetSyncivNULL; - isSync = &glIsSyncNULL; - waitSync = &glWaitSyncNULL; - } - - if (extensions.count("GL_ARB_tessellation_shader") != 0) - { - patchParameterfv = &glPatchParameterfvNULL; - patchParameteri = &glPatchParameteriNULL; - } - - if (extensions.count("GL_ARB_texture_barrier") != 0) - { - textureBarrier = &glTextureBarrierNULL; - } - - if (extensions.count("GL_ARB_texture_buffer_object") != 0) - { - texBuffer = &glTexBufferNULL; - } - - if (extensions.count("GL_ARB_texture_buffer_range") != 0) - { - texBufferRange = &glTexBufferRangeNULL; - } - - if (extensions.count("GL_ARB_texture_compression") != 0) - { - compressedTexImage1D = &glCompressedTexImage1DNULL; - compressedTexImage2D = &glCompressedTexImage2DNULL; - compressedTexImage3D = &glCompressedTexImage3DNULL; - compressedTexSubImage1D = &glCompressedTexSubImage1DNULL; - compressedTexSubImage2D = &glCompressedTexSubImage2DNULL; - compressedTexSubImage3D = &glCompressedTexSubImage3DNULL; - getCompressedTexImage = &glGetCompressedTexImageNULL; - } - - if (extensions.count("GL_ARB_texture_multisample") != 0) - { - getMultisamplefv = &glGetMultisamplefvNULL; - sampleMaski = &glSampleMaskiNULL; - texImage2DMultisample = &glTexImage2DMultisampleNULL; - texImage3DMultisample = &glTexImage3DMultisampleNULL; - } - - if (extensions.count("GL_ARB_texture_storage") != 0) - { - texStorage1D = &glTexStorage1DNULL; - texStorage2D = &glTexStorage2DNULL; - texStorage3D = &glTexStorage3DNULL; - } - - if (extensions.count("GL_ARB_texture_storage_multisample") != 0) - { - texStorage2DMultisample = &glTexStorage2DMultisampleNULL; - texStorage3DMultisample = &glTexStorage3DMultisampleNULL; - } - - if (extensions.count("GL_ARB_texture_view") != 0) - { - textureView = &glTextureViewNULL; - } - - if (extensions.count("GL_ARB_timer_query") != 0) - { - getQueryObjecti64v = &glGetQueryObjecti64vNULL; - getQueryObjectui64v = &glGetQueryObjectui64vNULL; - queryCounter = &glQueryCounterNULL; - } - - if (extensions.count("GL_ARB_transform_feedback2") != 0) - { - bindTransformFeedback = &glBindTransformFeedbackNULL; - deleteTransformFeedbacks = &glDeleteTransformFeedbacksNULL; - drawTransformFeedback = &glDrawTransformFeedbackNULL; - genTransformFeedbacks = &glGenTransformFeedbacksNULL; - isTransformFeedback = &glIsTransformFeedbackNULL; - pauseTransformFeedback = &glPauseTransformFeedbackNULL; - resumeTransformFeedback = &glResumeTransformFeedbackNULL; - } - - if (extensions.count("GL_ARB_transform_feedback3") != 0) - { - beginQueryIndexed = &glBeginQueryIndexedNULL; - drawTransformFeedbackStream = &glDrawTransformFeedbackStreamNULL; - endQueryIndexed = &glEndQueryIndexedNULL; - getQueryIndexediv = &glGetQueryIndexedivNULL; - } - - if (extensions.count("GL_ARB_transform_feedback_instanced") != 0) - { - drawTransformFeedbackInstanced = &glDrawTransformFeedbackInstancedNULL; - drawTransformFeedbackStreamInstanced = &glDrawTransformFeedbackStreamInstancedNULL; - } - - if (extensions.count("GL_ARB_uniform_buffer_object") != 0) - { - bindBufferBase = &glBindBufferBaseNULL; - bindBufferRange = &glBindBufferRangeNULL; - getActiveUniformBlockName = &glGetActiveUniformBlockNameNULL; - getActiveUniformBlockiv = &glGetActiveUniformBlockivNULL; - getActiveUniformName = &glGetActiveUniformNameNULL; - getActiveUniformsiv = &glGetActiveUniformsivNULL; - getIntegeri_v = &glGetIntegeri_vNULL; - getUniformBlockIndex = &glGetUniformBlockIndexNULL; - getUniformIndices = &glGetUniformIndicesNULL; - uniformBlockBinding = &glUniformBlockBindingNULL; - } - - if (extensions.count("GL_ARB_vertex_array_object") != 0) - { - bindVertexArray = &glBindVertexArrayNULL; - deleteVertexArrays = &glDeleteVertexArraysNULL; - genVertexArrays = &glGenVertexArraysNULL; - isVertexArray = &glIsVertexArrayNULL; - } - - if (extensions.count("GL_ARB_vertex_attrib_64bit") != 0) - { - getVertexAttribLdv = &glGetVertexAttribLdvNULL; - vertexAttribL1d = &glVertexAttribL1dNULL; - vertexAttribL1dv = &glVertexAttribL1dvNULL; - vertexAttribL2d = &glVertexAttribL2dNULL; - vertexAttribL2dv = &glVertexAttribL2dvNULL; - vertexAttribL3d = &glVertexAttribL3dNULL; - vertexAttribL3dv = &glVertexAttribL3dvNULL; - vertexAttribL4d = &glVertexAttribL4dNULL; - vertexAttribL4dv = &glVertexAttribL4dvNULL; - vertexAttribLPointer = &glVertexAttribLPointerNULL; - } - - if (extensions.count("GL_ARB_vertex_attrib_binding") != 0) - { - bindVertexBuffer = &glBindVertexBufferNULL; - vertexAttribBinding = &glVertexAttribBindingNULL; - vertexAttribFormat = &glVertexAttribFormatNULL; - vertexAttribIFormat = &glVertexAttribIFormatNULL; - vertexAttribLFormat = &glVertexAttribLFormatNULL; - vertexBindingDivisor = &glVertexBindingDivisorNULL; - } - - if (extensions.count("GL_ARB_vertex_buffer_object") != 0) - { - bindBuffer = &glBindBufferNULL; - bufferData = &glBufferDataNULL; - bufferSubData = &glBufferSubDataNULL; - deleteBuffers = &glDeleteBuffersNULL; - genBuffers = &glGenBuffersNULL; - getBufferParameteriv = &glGetBufferParameterivNULL; - getBufferPointerv = &glGetBufferPointervNULL; - getBufferSubData = &glGetBufferSubDataNULL; - isBuffer = &glIsBufferNULL; - mapBuffer = &glMapBufferNULL; - unmapBuffer = &glUnmapBufferNULL; - } - - if (extensions.count("GL_ARB_vertex_program") != 0) - { - disableVertexAttribArray = &glDisableVertexAttribArrayNULL; - enableVertexAttribArray = &glEnableVertexAttribArrayNULL; - getProgramiv = &glGetProgramivNULL; - getVertexAttribPointerv = &glGetVertexAttribPointervNULL; - getVertexAttribdv = &glGetVertexAttribdvNULL; - getVertexAttribfv = &glGetVertexAttribfvNULL; - getVertexAttribiv = &glGetVertexAttribivNULL; - isProgram = &glIsProgramNULL; - vertexAttrib1d = &glVertexAttrib1dNULL; - vertexAttrib1dv = &glVertexAttrib1dvNULL; - vertexAttrib1f = &glVertexAttrib1fNULL; - vertexAttrib1fv = &glVertexAttrib1fvNULL; - vertexAttrib1s = &glVertexAttrib1sNULL; - vertexAttrib1sv = &glVertexAttrib1svNULL; - vertexAttrib2d = &glVertexAttrib2dNULL; - vertexAttrib2dv = &glVertexAttrib2dvNULL; - vertexAttrib2f = &glVertexAttrib2fNULL; - vertexAttrib2fv = &glVertexAttrib2fvNULL; - vertexAttrib2s = &glVertexAttrib2sNULL; - vertexAttrib2sv = &glVertexAttrib2svNULL; - vertexAttrib3d = &glVertexAttrib3dNULL; - vertexAttrib3dv = &glVertexAttrib3dvNULL; - vertexAttrib3f = &glVertexAttrib3fNULL; - vertexAttrib3fv = &glVertexAttrib3fvNULL; - vertexAttrib3s = &glVertexAttrib3sNULL; - vertexAttrib3sv = &glVertexAttrib3svNULL; - vertexAttrib4Nbv = &glVertexAttrib4NbvNULL; - vertexAttrib4Niv = &glVertexAttrib4NivNULL; - vertexAttrib4Nsv = &glVertexAttrib4NsvNULL; - vertexAttrib4Nub = &glVertexAttrib4NubNULL; - vertexAttrib4Nubv = &glVertexAttrib4NubvNULL; - vertexAttrib4Nuiv = &glVertexAttrib4NuivNULL; - vertexAttrib4Nusv = &glVertexAttrib4NusvNULL; - vertexAttrib4bv = &glVertexAttrib4bvNULL; - vertexAttrib4d = &glVertexAttrib4dNULL; - vertexAttrib4dv = &glVertexAttrib4dvNULL; - vertexAttrib4f = &glVertexAttrib4fNULL; - vertexAttrib4fv = &glVertexAttrib4fvNULL; - vertexAttrib4iv = &glVertexAttrib4ivNULL; - vertexAttrib4s = &glVertexAttrib4sNULL; - vertexAttrib4sv = &glVertexAttrib4svNULL; - vertexAttrib4ubv = &glVertexAttrib4ubvNULL; - vertexAttrib4uiv = &glVertexAttrib4uivNULL; - vertexAttrib4usv = &glVertexAttrib4usvNULL; - vertexAttribPointer = &glVertexAttribPointerNULL; - } - - if (extensions.count("GL_ARB_vertex_shader") != 0) - { - bindAttribLocation = &glBindAttribLocationNULL; - disableVertexAttribArray = &glDisableVertexAttribArrayNULL; - enableVertexAttribArray = &glEnableVertexAttribArrayNULL; - getActiveAttrib = &glGetActiveAttribNULL; - getAttribLocation = &glGetAttribLocationNULL; - getVertexAttribPointerv = &glGetVertexAttribPointervNULL; - getVertexAttribdv = &glGetVertexAttribdvNULL; - getVertexAttribfv = &glGetVertexAttribfvNULL; - getVertexAttribiv = &glGetVertexAttribivNULL; - vertexAttrib1d = &glVertexAttrib1dNULL; - vertexAttrib1dv = &glVertexAttrib1dvNULL; - vertexAttrib1f = &glVertexAttrib1fNULL; - vertexAttrib1fv = &glVertexAttrib1fvNULL; - vertexAttrib1s = &glVertexAttrib1sNULL; - vertexAttrib1sv = &glVertexAttrib1svNULL; - vertexAttrib2d = &glVertexAttrib2dNULL; - vertexAttrib2dv = &glVertexAttrib2dvNULL; - vertexAttrib2f = &glVertexAttrib2fNULL; - vertexAttrib2fv = &glVertexAttrib2fvNULL; - vertexAttrib2s = &glVertexAttrib2sNULL; - vertexAttrib2sv = &glVertexAttrib2svNULL; - vertexAttrib3d = &glVertexAttrib3dNULL; - vertexAttrib3dv = &glVertexAttrib3dvNULL; - vertexAttrib3f = &glVertexAttrib3fNULL; - vertexAttrib3fv = &glVertexAttrib3fvNULL; - vertexAttrib3s = &glVertexAttrib3sNULL; - vertexAttrib3sv = &glVertexAttrib3svNULL; - vertexAttrib4Nbv = &glVertexAttrib4NbvNULL; - vertexAttrib4Niv = &glVertexAttrib4NivNULL; - vertexAttrib4Nsv = &glVertexAttrib4NsvNULL; - vertexAttrib4Nub = &glVertexAttrib4NubNULL; - vertexAttrib4Nubv = &glVertexAttrib4NubvNULL; - vertexAttrib4Nuiv = &glVertexAttrib4NuivNULL; - vertexAttrib4Nusv = &glVertexAttrib4NusvNULL; - vertexAttrib4bv = &glVertexAttrib4bvNULL; - vertexAttrib4d = &glVertexAttrib4dNULL; - vertexAttrib4dv = &glVertexAttrib4dvNULL; - vertexAttrib4f = &glVertexAttrib4fNULL; - vertexAttrib4fv = &glVertexAttrib4fvNULL; - vertexAttrib4iv = &glVertexAttrib4ivNULL; - vertexAttrib4s = &glVertexAttrib4sNULL; - vertexAttrib4sv = &glVertexAttrib4svNULL; - vertexAttrib4ubv = &glVertexAttrib4ubvNULL; - vertexAttrib4uiv = &glVertexAttrib4uivNULL; - vertexAttrib4usv = &glVertexAttrib4usvNULL; - vertexAttribPointer = &glVertexAttribPointerNULL; - } - - if (extensions.count("GL_ARB_vertex_type_2_10_10_10_rev") != 0) - { - vertexAttribP1ui = &glVertexAttribP1uiNULL; - vertexAttribP1uiv = &glVertexAttribP1uivNULL; - vertexAttribP2ui = &glVertexAttribP2uiNULL; - vertexAttribP2uiv = &glVertexAttribP2uivNULL; - vertexAttribP3ui = &glVertexAttribP3uiNULL; - vertexAttribP3uiv = &glVertexAttribP3uivNULL; - vertexAttribP4ui = &glVertexAttribP4uiNULL; - vertexAttribP4uiv = &glVertexAttribP4uivNULL; - } - - if (extensions.count("GL_ARB_viewport_array") != 0) - { - depthRangeArrayv = &glDepthRangeArrayvNULL; - depthRangeIndexed = &glDepthRangeIndexedNULL; - getDoublei_v = &glGetDoublei_vNULL; - getFloati_v = &glGetFloati_vNULL; - scissorArrayv = &glScissorArrayvNULL; - scissorIndexed = &glScissorIndexedNULL; - scissorIndexedv = &glScissorIndexedvNULL; - viewportArrayv = &glViewportArrayvNULL; - viewportIndexedf = &glViewportIndexedfNULL; - viewportIndexedfv = &glViewportIndexedfvNULL; - } - - if (extensions.count("GL_EXT_blend_color") != 0) - { - blendColor = &glBlendColorNULL; - } - - if (extensions.count("GL_EXT_blend_equation_separate") != 0) - { - blendEquationSeparate = &glBlendEquationSeparateNULL; - } - - if (extensions.count("GL_EXT_blend_func_separate") != 0) - { - blendFuncSeparate = &glBlendFuncSeparateNULL; - } - - if (extensions.count("GL_EXT_blend_minmax") != 0) - { - blendEquation = &glBlendEquationNULL; - } - - if (extensions.count("GL_EXT_copy_texture") != 0) - { - copyTexImage1D = &glCopyTexImage1DNULL; - copyTexImage2D = &glCopyTexImage2DNULL; - copyTexSubImage1D = &glCopyTexSubImage1DNULL; - copyTexSubImage2D = &glCopyTexSubImage2DNULL; - copyTexSubImage3D = &glCopyTexSubImage3DNULL; - } - - if (extensions.count("GL_EXT_direct_state_access") != 0) - { - checkNamedFramebufferStatus = &glCheckNamedFramebufferStatusNULL; - clearNamedBufferData = &glClearNamedBufferDataNULL; - clearNamedBufferSubData = &glClearNamedBufferSubDataNULL; - compressedTextureSubImage1D = &glCompressedTextureSubImage1DNULL; - compressedTextureSubImage2D = &glCompressedTextureSubImage2DNULL; - compressedTextureSubImage3D = &glCompressedTextureSubImage3DNULL; - copyTextureSubImage1D = &glCopyTextureSubImage1DNULL; - copyTextureSubImage2D = &glCopyTextureSubImage2DNULL; - copyTextureSubImage3D = &glCopyTextureSubImage3DNULL; - disableVertexArrayAttrib = &glDisableVertexArrayAttribNULL; - enableVertexArrayAttrib = &glEnableVertexArrayAttribNULL; - flushMappedNamedBufferRange = &glFlushMappedNamedBufferRangeNULL; - generateTextureMipmap = &glGenerateTextureMipmapNULL; - getCompressedTextureImage = &glGetCompressedTextureImageNULL; - getDoublei_v = &glGetDoublei_vNULL; - getFloati_v = &glGetFloati_vNULL; - getFramebufferParameteriv = &glGetFramebufferParameterivNULL; - getNamedBufferParameteriv = &glGetNamedBufferParameterivNULL; - getNamedBufferPointerv = &glGetNamedBufferPointervNULL; - getNamedBufferSubData = &glGetNamedBufferSubDataNULL; - getNamedFramebufferAttachmentParameteriv = &glGetNamedFramebufferAttachmentParameterivNULL; - getNamedFramebufferParameteriv = &glGetNamedFramebufferParameterivNULL; - getNamedRenderbufferParameteriv = &glGetNamedRenderbufferParameterivNULL; - getTextureImage = &glGetTextureImageNULL; - getTextureLevelParameterfv = &glGetTextureLevelParameterfvNULL; - getTextureLevelParameteriv = &glGetTextureLevelParameterivNULL; - getTextureParameterIiv = &glGetTextureParameterIivNULL; - getTextureParameterIuiv = &glGetTextureParameterIuivNULL; - getTextureParameterfv = &glGetTextureParameterfvNULL; - getTextureParameteriv = &glGetTextureParameterivNULL; - mapNamedBuffer = &glMapNamedBufferNULL; - mapNamedBufferRange = &glMapNamedBufferRangeNULL; - namedBufferData = &glNamedBufferDataNULL; - namedBufferStorage = &glNamedBufferStorageNULL; - namedBufferSubData = &glNamedBufferSubDataNULL; - namedFramebufferParameteri = &glNamedFramebufferParameteriNULL; - namedFramebufferRenderbuffer = &glNamedFramebufferRenderbufferNULL; - namedFramebufferTexture = &glNamedFramebufferTextureNULL; - namedFramebufferTextureLayer = &glNamedFramebufferTextureLayerNULL; - namedRenderbufferStorage = &glNamedRenderbufferStorageNULL; - namedRenderbufferStorageMultisample = &glNamedRenderbufferStorageMultisampleNULL; - programUniform1d = &glProgramUniform1dNULL; - programUniform1dv = &glProgramUniform1dvNULL; - programUniform1f = &glProgramUniform1fNULL; - programUniform1fv = &glProgramUniform1fvNULL; - programUniform1i = &glProgramUniform1iNULL; - programUniform1iv = &glProgramUniform1ivNULL; - programUniform1ui = &glProgramUniform1uiNULL; - programUniform1uiv = &glProgramUniform1uivNULL; - programUniform2d = &glProgramUniform2dNULL; - programUniform2dv = &glProgramUniform2dvNULL; - programUniform2f = &glProgramUniform2fNULL; - programUniform2fv = &glProgramUniform2fvNULL; - programUniform2i = &glProgramUniform2iNULL; - programUniform2iv = &glProgramUniform2ivNULL; - programUniform2ui = &glProgramUniform2uiNULL; - programUniform2uiv = &glProgramUniform2uivNULL; - programUniform3d = &glProgramUniform3dNULL; - programUniform3dv = &glProgramUniform3dvNULL; - programUniform3f = &glProgramUniform3fNULL; - programUniform3fv = &glProgramUniform3fvNULL; - programUniform3i = &glProgramUniform3iNULL; - programUniform3iv = &glProgramUniform3ivNULL; - programUniform3ui = &glProgramUniform3uiNULL; - programUniform3uiv = &glProgramUniform3uivNULL; - programUniform4d = &glProgramUniform4dNULL; - programUniform4dv = &glProgramUniform4dvNULL; - programUniform4f = &glProgramUniform4fNULL; - programUniform4fv = &glProgramUniform4fvNULL; - programUniform4i = &glProgramUniform4iNULL; - programUniform4iv = &glProgramUniform4ivNULL; - programUniform4ui = &glProgramUniform4uiNULL; - programUniform4uiv = &glProgramUniform4uivNULL; - programUniformMatrix2dv = &glProgramUniformMatrix2dvNULL; - programUniformMatrix2fv = &glProgramUniformMatrix2fvNULL; - programUniformMatrix2x3dv = &glProgramUniformMatrix2x3dvNULL; - programUniformMatrix2x3fv = &glProgramUniformMatrix2x3fvNULL; - programUniformMatrix2x4dv = &glProgramUniformMatrix2x4dvNULL; - programUniformMatrix2x4fv = &glProgramUniformMatrix2x4fvNULL; - programUniformMatrix3dv = &glProgramUniformMatrix3dvNULL; - programUniformMatrix3fv = &glProgramUniformMatrix3fvNULL; - programUniformMatrix3x2dv = &glProgramUniformMatrix3x2dvNULL; - programUniformMatrix3x2fv = &glProgramUniformMatrix3x2fvNULL; - programUniformMatrix3x4dv = &glProgramUniformMatrix3x4dvNULL; - programUniformMatrix3x4fv = &glProgramUniformMatrix3x4fvNULL; - programUniformMatrix4dv = &glProgramUniformMatrix4dvNULL; - programUniformMatrix4fv = &glProgramUniformMatrix4fvNULL; - programUniformMatrix4x2dv = &glProgramUniformMatrix4x2dvNULL; - programUniformMatrix4x2fv = &glProgramUniformMatrix4x2fvNULL; - programUniformMatrix4x3dv = &glProgramUniformMatrix4x3dvNULL; - programUniformMatrix4x3fv = &glProgramUniformMatrix4x3fvNULL; - textureBuffer = &glTextureBufferNULL; - textureBufferRange = &glTextureBufferRangeNULL; - textureParameterIiv = &glTextureParameterIivNULL; - textureParameterIuiv = &glTextureParameterIuivNULL; - textureParameterf = &glTextureParameterfNULL; - textureParameterfv = &glTextureParameterfvNULL; - textureParameteri = &glTextureParameteriNULL; - textureParameteriv = &glTextureParameterivNULL; - textureStorage2DMultisample = &glTextureStorage2DMultisampleNULL; - textureStorage3DMultisample = &glTextureStorage3DMultisampleNULL; - textureSubImage1D = &glTextureSubImage1DNULL; - textureSubImage2D = &glTextureSubImage2DNULL; - textureSubImage3D = &glTextureSubImage3DNULL; - unmapNamedBuffer = &glUnmapNamedBufferNULL; - } - - if (extensions.count("GL_EXT_draw_range_elements") != 0) - { - drawRangeElements = &glDrawRangeElementsNULL; - } - - if (extensions.count("GL_EXT_framebuffer_blit") != 0) - { - blitFramebuffer = &glBlitFramebufferNULL; - blitFramebufferEXT = &glBlitFramebufferEXTNULL; - } - - if (extensions.count("GL_EXT_framebuffer_multisample") != 0) - { - renderbufferStorageMultisample = &glRenderbufferStorageMultisampleNULL; - renderbufferStorageMultisampleEXT = &glRenderbufferStorageMultisampleEXTNULL; - } - - if (extensions.count("GL_EXT_framebuffer_object") != 0) - { - bindFramebuffer = &glBindFramebufferNULL; - bindRenderbuffer = &glBindRenderbufferNULL; - checkFramebufferStatus = &glCheckFramebufferStatusNULL; - deleteFramebuffers = &glDeleteFramebuffersNULL; - deleteRenderbuffers = &glDeleteRenderbuffersNULL; - framebufferRenderbuffer = &glFramebufferRenderbufferNULL; - framebufferTexture1D = &glFramebufferTexture1DNULL; - framebufferTexture2D = &glFramebufferTexture2DNULL; - framebufferTexture3D = &glFramebufferTexture3DNULL; - genFramebuffers = &glGenFramebuffersNULL; - genRenderbuffers = &glGenRenderbuffersNULL; - generateMipmap = &glGenerateMipmapNULL; - getFramebufferAttachmentParameteriv = &glGetFramebufferAttachmentParameterivNULL; - getRenderbufferParameteriv = &glGetRenderbufferParameterivNULL; - isFramebuffer = &glIsFramebufferNULL; - isRenderbuffer = &glIsRenderbufferNULL; - renderbufferStorage = &glRenderbufferStorageNULL; - } - - if (extensions.count("GL_EXT_geometry_shader4") != 0) - { - programParameteri = &glProgramParameteriNULL; - } - - if (extensions.count("GL_EXT_gpu_shader4") != 0) - { - bindFragDataLocation = &glBindFragDataLocationNULL; - getFragDataLocation = &glGetFragDataLocationNULL; - getUniformuiv = &glGetUniformuivNULL; - getVertexAttribIiv = &glGetVertexAttribIivNULL; - getVertexAttribIuiv = &glGetVertexAttribIuivNULL; - uniform1ui = &glUniform1uiNULL; - uniform1uiv = &glUniform1uivNULL; - uniform2ui = &glUniform2uiNULL; - uniform2uiv = &glUniform2uivNULL; - uniform3ui = &glUniform3uiNULL; - uniform3uiv = &glUniform3uivNULL; - uniform4ui = &glUniform4uiNULL; - uniform4uiv = &glUniform4uivNULL; - vertexAttribI1i = &glVertexAttribI1iNULL; - vertexAttribI1iv = &glVertexAttribI1ivNULL; - vertexAttribI1ui = &glVertexAttribI1uiNULL; - vertexAttribI1uiv = &glVertexAttribI1uivNULL; - vertexAttribI2i = &glVertexAttribI2iNULL; - vertexAttribI2iv = &glVertexAttribI2ivNULL; - vertexAttribI2ui = &glVertexAttribI2uiNULL; - vertexAttribI2uiv = &glVertexAttribI2uivNULL; - vertexAttribI3i = &glVertexAttribI3iNULL; - vertexAttribI3iv = &glVertexAttribI3ivNULL; - vertexAttribI3ui = &glVertexAttribI3uiNULL; - vertexAttribI3uiv = &glVertexAttribI3uivNULL; - vertexAttribI4bv = &glVertexAttribI4bvNULL; - vertexAttribI4i = &glVertexAttribI4iNULL; - vertexAttribI4iv = &glVertexAttribI4ivNULL; - vertexAttribI4sv = &glVertexAttribI4svNULL; - vertexAttribI4ubv = &glVertexAttribI4ubvNULL; - vertexAttribI4ui = &glVertexAttribI4uiNULL; - vertexAttribI4uiv = &glVertexAttribI4uivNULL; - vertexAttribI4usv = &glVertexAttribI4usvNULL; - vertexAttribIPointer = &glVertexAttribIPointerNULL; - } - - if (extensions.count("GL_EXT_point_parameters") != 0) - { - pointParameterf = &glPointParameterfNULL; - pointParameterfv = &glPointParameterfvNULL; - } - - if (extensions.count("GL_EXT_polygon_offset") != 0) - { - polygonOffset = &glPolygonOffsetNULL; - } - - if (extensions.count("GL_EXT_provoking_vertex") != 0) - { - provokingVertex = &glProvokingVertexNULL; - } - - if (extensions.count("GL_EXT_shader_image_load_store") != 0) - { - bindImageTexture = &glBindImageTextureNULL; - memoryBarrier = &glMemoryBarrierNULL; - } - - if (extensions.count("GL_EXT_subtexture") != 0) - { - texSubImage1D = &glTexSubImage1DNULL; - texSubImage2D = &glTexSubImage2DNULL; - } - - if (extensions.count("GL_EXT_texture3D") != 0) - { - texImage3D = &glTexImage3DNULL; - texSubImage3D = &glTexSubImage3DNULL; - } - - if (extensions.count("GL_EXT_texture_array") != 0) - { - framebufferTextureLayer = &glFramebufferTextureLayerNULL; - } - - if (extensions.count("GL_EXT_texture_buffer_object") != 0) - { - texBuffer = &glTexBufferNULL; - texBufferEXT = &glTexBufferEXTNULL; - } - - if (extensions.count("GL_EXT_texture_integer") != 0) - { - getTexParameterIiv = &glGetTexParameterIivNULL; - getTexParameterIuiv = &glGetTexParameterIuivNULL; - texParameterIiv = &glTexParameterIivNULL; - texParameterIuiv = &glTexParameterIuivNULL; - } - - if (extensions.count("GL_EXT_texture_object") != 0) - { - bindTexture = &glBindTextureNULL; - deleteTextures = &glDeleteTexturesNULL; - genTextures = &glGenTexturesNULL; - isTexture = &glIsTextureNULL; - } - - if (extensions.count("GL_EXT_timer_query") != 0) - { - getQueryObjecti64v = &glGetQueryObjecti64vNULL; - getQueryObjectui64v = &glGetQueryObjectui64vNULL; - } - - if (extensions.count("GL_EXT_transform_feedback") != 0) - { - beginTransformFeedback = &glBeginTransformFeedbackNULL; - bindBufferBase = &glBindBufferBaseNULL; - bindBufferRange = &glBindBufferRangeNULL; - endTransformFeedback = &glEndTransformFeedbackNULL; - getTransformFeedbackVarying = &glGetTransformFeedbackVaryingNULL; - transformFeedbackVaryings = &glTransformFeedbackVaryingsNULL; - } - - if (extensions.count("GL_EXT_vertex_array") != 0) - { - drawArrays = &glDrawArraysNULL; - getPointerv = &glGetPointervNULL; - } - - if (extensions.count("GL_EXT_vertex_attrib_64bit") != 0) - { - getVertexAttribLdv = &glGetVertexAttribLdvNULL; - vertexAttribL1d = &glVertexAttribL1dNULL; - vertexAttribL1dv = &glVertexAttribL1dvNULL; - vertexAttribL2d = &glVertexAttribL2dNULL; - vertexAttribL2dv = &glVertexAttribL2dvNULL; - vertexAttribL3d = &glVertexAttribL3dNULL; - vertexAttribL3dv = &glVertexAttribL3dvNULL; - vertexAttribL4d = &glVertexAttribL4dNULL; - vertexAttribL4dv = &glVertexAttribL4dvNULL; - vertexAttribLPointer = &glVertexAttribLPointerNULL; - } - - if (extensions.count("GL_KHR_debug") != 0) - { - debugMessageCallback = &glDebugMessageCallbackNULL; - debugMessageControl = &glDebugMessageControlNULL; - debugMessageInsert = &glDebugMessageInsertNULL; - getDebugMessageLog = &glGetDebugMessageLogNULL; - getObjectLabel = &glGetObjectLabelNULL; - getObjectPtrLabel = &glGetObjectPtrLabelNULL; - getPointerv = &glGetPointervNULL; - objectLabel = &glObjectLabelNULL; - objectPtrLabel = &glObjectPtrLabelNULL; - popDebugGroup = &glPopDebugGroupNULL; - pushDebugGroup = &glPushDebugGroupNULL; - } - - if (extensions.count("GL_KHR_robustness") != 0) - { - getGraphicsResetStatus = &glGetGraphicsResetStatusNULL; - getnUniformfv = &glGetnUniformfvNULL; - getnUniformiv = &glGetnUniformivNULL; - getnUniformuiv = &glGetnUniformuivNULL; - readnPixels = &glReadnPixelsNULL; - } - - if (extensions.count("GL_NV_geometry_program4") != 0) - { - framebufferTexture = &glFramebufferTextureNULL; - framebufferTextureLayer = &glFramebufferTextureLayerNULL; - } - - if (extensions.count("GL_NV_vertex_program4") != 0) - { - getVertexAttribIiv = &glGetVertexAttribIivNULL; - getVertexAttribIuiv = &glGetVertexAttribIuivNULL; - vertexAttribI1i = &glVertexAttribI1iNULL; - vertexAttribI1iv = &glVertexAttribI1ivNULL; - vertexAttribI1ui = &glVertexAttribI1uiNULL; - vertexAttribI1uiv = &glVertexAttribI1uivNULL; - vertexAttribI2i = &glVertexAttribI2iNULL; - vertexAttribI2iv = &glVertexAttribI2ivNULL; - vertexAttribI2ui = &glVertexAttribI2uiNULL; - vertexAttribI2uiv = &glVertexAttribI2uivNULL; - vertexAttribI3i = &glVertexAttribI3iNULL; - vertexAttribI3iv = &glVertexAttribI3ivNULL; - vertexAttribI3ui = &glVertexAttribI3uiNULL; - vertexAttribI3uiv = &glVertexAttribI3uivNULL; - vertexAttribI4bv = &glVertexAttribI4bvNULL; - vertexAttribI4i = &glVertexAttribI4iNULL; - vertexAttribI4iv = &glVertexAttribI4ivNULL; - vertexAttribI4sv = &glVertexAttribI4svNULL; - vertexAttribI4ubv = &glVertexAttribI4ubvNULL; - vertexAttribI4ui = &glVertexAttribI4uiNULL; - vertexAttribI4uiv = &glVertexAttribI4uivNULL; - vertexAttribI4usv = &glVertexAttribI4usvNULL; - vertexAttribIPointer = &glVertexAttribIPointerNULL; - } - - if (extensions.count("GL_OES_single_precision") != 0) - { - clearDepthf = &glClearDepthfNULL; - depthRangef = &glDepthRangefNULL; - } - - if (version >= gl::Version(1, 0)) - { - blendFunc = &glBlendFuncNULL; - clear = &glClearNULL; - clearColor = &glClearColorNULL; - clearDepth = &glClearDepthNULL; - clearStencil = &glClearStencilNULL; - colorMask = &glColorMaskNULL; - cullFace = &glCullFaceNULL; - depthFunc = &glDepthFuncNULL; - depthMask = &glDepthMaskNULL; - depthRange = &glDepthRangeNULL; - disable = &glDisableNULL; - drawBuffer = &glDrawBufferNULL; - enable = &glEnableNULL; - finish = &glFinishNULL; - flush = &glFlushNULL; - frontFace = &glFrontFaceNULL; - getBooleanv = &glGetBooleanvNULL; - getDoublev = &glGetDoublevNULL; - getError = &glGetErrorNULL; - getFloatv = &glGetFloatvNULL; - getIntegerv = &glGetIntegervNULL; - getString = &glGetStringNULL; - getTexImage = &glGetTexImageNULL; - getTexLevelParameterfv = &glGetTexLevelParameterfvNULL; - getTexLevelParameteriv = &glGetTexLevelParameterivNULL; - getTexParameterfv = &glGetTexParameterfvNULL; - getTexParameteriv = &glGetTexParameterivNULL; - hint = &glHintNULL; - isEnabled = &glIsEnabledNULL; - lineWidth = &glLineWidthNULL; - logicOp = &glLogicOpNULL; - pixelStoref = &glPixelStorefNULL; - pixelStorei = &glPixelStoreiNULL; - pointSize = &glPointSizeNULL; - polygonMode = &glPolygonModeNULL; - readBuffer = &glReadBufferNULL; - readPixels = &glReadPixelsNULL; - scissor = &glScissorNULL; - stencilFunc = &glStencilFuncNULL; - stencilMask = &glStencilMaskNULL; - stencilOp = &glStencilOpNULL; - texImage1D = &glTexImage1DNULL; - texImage2D = &glTexImage2DNULL; - texParameterf = &glTexParameterfNULL; - texParameterfv = &glTexParameterfvNULL; - texParameteri = &glTexParameteriNULL; - texParameteriv = &glTexParameterivNULL; - viewport = &glViewportNULL; - } - - if (version >= gl::Version(1, 1)) - { - bindTexture = &glBindTextureNULL; - copyTexImage1D = &glCopyTexImage1DNULL; - copyTexImage2D = &glCopyTexImage2DNULL; - copyTexSubImage1D = &glCopyTexSubImage1DNULL; - copyTexSubImage2D = &glCopyTexSubImage2DNULL; - deleteTextures = &glDeleteTexturesNULL; - drawArrays = &glDrawArraysNULL; - drawElements = &glDrawElementsNULL; - genTextures = &glGenTexturesNULL; - isTexture = &glIsTextureNULL; - polygonOffset = &glPolygonOffsetNULL; - texSubImage1D = &glTexSubImage1DNULL; - texSubImage2D = &glTexSubImage2DNULL; - } - - if (version >= gl::Version(1, 2)) - { - copyTexSubImage3D = &glCopyTexSubImage3DNULL; - drawRangeElements = &glDrawRangeElementsNULL; - texImage3D = &glTexImage3DNULL; - texSubImage3D = &glTexSubImage3DNULL; - } - - if (version >= gl::Version(1, 3)) - { - activeTexture = &glActiveTextureNULL; - compressedTexImage1D = &glCompressedTexImage1DNULL; - compressedTexImage2D = &glCompressedTexImage2DNULL; - compressedTexImage3D = &glCompressedTexImage3DNULL; - compressedTexSubImage1D = &glCompressedTexSubImage1DNULL; - compressedTexSubImage2D = &glCompressedTexSubImage2DNULL; - compressedTexSubImage3D = &glCompressedTexSubImage3DNULL; - getCompressedTexImage = &glGetCompressedTexImageNULL; - sampleCoverage = &glSampleCoverageNULL; - } - - if (version >= gl::Version(1, 4)) - { - blendColor = &glBlendColorNULL; - blendEquation = &glBlendEquationNULL; - blendFuncSeparate = &glBlendFuncSeparateNULL; - multiDrawArrays = &glMultiDrawArraysNULL; - multiDrawElements = &glMultiDrawElementsNULL; - pointParameterf = &glPointParameterfNULL; - pointParameterfv = &glPointParameterfvNULL; - pointParameteri = &glPointParameteriNULL; - pointParameteriv = &glPointParameterivNULL; - } - - if (version >= gl::Version(1, 5)) - { - beginQuery = &glBeginQueryNULL; - bindBuffer = &glBindBufferNULL; - bufferData = &glBufferDataNULL; - bufferSubData = &glBufferSubDataNULL; - deleteBuffers = &glDeleteBuffersNULL; - deleteQueries = &glDeleteQueriesNULL; - endQuery = &glEndQueryNULL; - genBuffers = &glGenBuffersNULL; - genQueries = &glGenQueriesNULL; - getBufferParameteriv = &glGetBufferParameterivNULL; - getBufferPointerv = &glGetBufferPointervNULL; - getBufferSubData = &glGetBufferSubDataNULL; - getQueryObjectiv = &glGetQueryObjectivNULL; - getQueryObjectuiv = &glGetQueryObjectuivNULL; - getQueryiv = &glGetQueryivNULL; - isBuffer = &glIsBufferNULL; - isQuery = &glIsQueryNULL; - mapBuffer = &glMapBufferNULL; - unmapBuffer = &glUnmapBufferNULL; - } - - if (version >= gl::Version(2, 0)) - { - attachShader = &glAttachShaderNULL; - bindAttribLocation = &glBindAttribLocationNULL; - blendEquationSeparate = &glBlendEquationSeparateNULL; - compileShader = &glCompileShaderNULL; - createProgram = &glCreateProgramNULL; - createShader = &glCreateShaderNULL; - deleteProgram = &glDeleteProgramNULL; - deleteShader = &glDeleteShaderNULL; - detachShader = &glDetachShaderNULL; - disableVertexAttribArray = &glDisableVertexAttribArrayNULL; - drawBuffers = &glDrawBuffersNULL; - enableVertexAttribArray = &glEnableVertexAttribArrayNULL; - getActiveAttrib = &glGetActiveAttribNULL; - getActiveUniform = &glGetActiveUniformNULL; - getAttachedShaders = &glGetAttachedShadersNULL; - getAttribLocation = &glGetAttribLocationNULL; - getProgramInfoLog = &glGetProgramInfoLogNULL; - getProgramiv = &glGetProgramivNULL; - getShaderInfoLog = &glGetShaderInfoLogNULL; - getShaderSource = &glGetShaderSourceNULL; - getShaderiv = &glGetShaderivNULL; - getUniformLocation = &glGetUniformLocationNULL; - getUniformfv = &glGetUniformfvNULL; - getUniformiv = &glGetUniformivNULL; - getVertexAttribPointerv = &glGetVertexAttribPointervNULL; - getVertexAttribdv = &glGetVertexAttribdvNULL; - getVertexAttribfv = &glGetVertexAttribfvNULL; - getVertexAttribiv = &glGetVertexAttribivNULL; - isProgram = &glIsProgramNULL; - isShader = &glIsShaderNULL; - linkProgram = &glLinkProgramNULL; - shaderSource = &glShaderSourceNULL; - stencilFuncSeparate = &glStencilFuncSeparateNULL; - stencilMaskSeparate = &glStencilMaskSeparateNULL; - stencilOpSeparate = &glStencilOpSeparateNULL; - uniform1f = &glUniform1fNULL; - uniform1fv = &glUniform1fvNULL; - uniform1i = &glUniform1iNULL; - uniform1iv = &glUniform1ivNULL; - uniform2f = &glUniform2fNULL; - uniform2fv = &glUniform2fvNULL; - uniform2i = &glUniform2iNULL; - uniform2iv = &glUniform2ivNULL; - uniform3f = &glUniform3fNULL; - uniform3fv = &glUniform3fvNULL; - uniform3i = &glUniform3iNULL; - uniform3iv = &glUniform3ivNULL; - uniform4f = &glUniform4fNULL; - uniform4fv = &glUniform4fvNULL; - uniform4i = &glUniform4iNULL; - uniform4iv = &glUniform4ivNULL; - uniformMatrix2fv = &glUniformMatrix2fvNULL; - uniformMatrix3fv = &glUniformMatrix3fvNULL; - uniformMatrix4fv = &glUniformMatrix4fvNULL; - useProgram = &glUseProgramNULL; - validateProgram = &glValidateProgramNULL; - vertexAttrib1d = &glVertexAttrib1dNULL; - vertexAttrib1dv = &glVertexAttrib1dvNULL; - vertexAttrib1f = &glVertexAttrib1fNULL; - vertexAttrib1fv = &glVertexAttrib1fvNULL; - vertexAttrib1s = &glVertexAttrib1sNULL; - vertexAttrib1sv = &glVertexAttrib1svNULL; - vertexAttrib2d = &glVertexAttrib2dNULL; - vertexAttrib2dv = &glVertexAttrib2dvNULL; - vertexAttrib2f = &glVertexAttrib2fNULL; - vertexAttrib2fv = &glVertexAttrib2fvNULL; - vertexAttrib2s = &glVertexAttrib2sNULL; - vertexAttrib2sv = &glVertexAttrib2svNULL; - vertexAttrib3d = &glVertexAttrib3dNULL; - vertexAttrib3dv = &glVertexAttrib3dvNULL; - vertexAttrib3f = &glVertexAttrib3fNULL; - vertexAttrib3fv = &glVertexAttrib3fvNULL; - vertexAttrib3s = &glVertexAttrib3sNULL; - vertexAttrib3sv = &glVertexAttrib3svNULL; - vertexAttrib4Nbv = &glVertexAttrib4NbvNULL; - vertexAttrib4Niv = &glVertexAttrib4NivNULL; - vertexAttrib4Nsv = &glVertexAttrib4NsvNULL; - vertexAttrib4Nub = &glVertexAttrib4NubNULL; - vertexAttrib4Nubv = &glVertexAttrib4NubvNULL; - vertexAttrib4Nuiv = &glVertexAttrib4NuivNULL; - vertexAttrib4Nusv = &glVertexAttrib4NusvNULL; - vertexAttrib4bv = &glVertexAttrib4bvNULL; - vertexAttrib4d = &glVertexAttrib4dNULL; - vertexAttrib4dv = &glVertexAttrib4dvNULL; - vertexAttrib4f = &glVertexAttrib4fNULL; - vertexAttrib4fv = &glVertexAttrib4fvNULL; - vertexAttrib4iv = &glVertexAttrib4ivNULL; - vertexAttrib4s = &glVertexAttrib4sNULL; - vertexAttrib4sv = &glVertexAttrib4svNULL; - vertexAttrib4ubv = &glVertexAttrib4ubvNULL; - vertexAttrib4uiv = &glVertexAttrib4uivNULL; - vertexAttrib4usv = &glVertexAttrib4usvNULL; - vertexAttribPointer = &glVertexAttribPointerNULL; - } - - if (version >= gl::Version(2, 1)) - { - uniformMatrix2x3fv = &glUniformMatrix2x3fvNULL; - uniformMatrix2x4fv = &glUniformMatrix2x4fvNULL; - uniformMatrix3x2fv = &glUniformMatrix3x2fvNULL; - uniformMatrix3x4fv = &glUniformMatrix3x4fvNULL; - uniformMatrix4x2fv = &glUniformMatrix4x2fvNULL; - uniformMatrix4x3fv = &glUniformMatrix4x3fvNULL; - } - - if (version >= gl::Version(3, 0)) - { - beginConditionalRender = &glBeginConditionalRenderNULL; - beginTransformFeedback = &glBeginTransformFeedbackNULL; - bindBufferBase = &glBindBufferBaseNULL; - bindBufferRange = &glBindBufferRangeNULL; - bindFragDataLocation = &glBindFragDataLocationNULL; - bindFramebuffer = &glBindFramebufferNULL; - bindRenderbuffer = &glBindRenderbufferNULL; - bindVertexArray = &glBindVertexArrayNULL; - blitFramebuffer = &glBlitFramebufferNULL; - checkFramebufferStatus = &glCheckFramebufferStatusNULL; - clampColor = &glClampColorNULL; - clearBufferfi = &glClearBufferfiNULL; - clearBufferfv = &glClearBufferfvNULL; - clearBufferiv = &glClearBufferivNULL; - clearBufferuiv = &glClearBufferuivNULL; - colorMaski = &glColorMaskiNULL; - deleteFramebuffers = &glDeleteFramebuffersNULL; - deleteRenderbuffers = &glDeleteRenderbuffersNULL; - deleteVertexArrays = &glDeleteVertexArraysNULL; - disablei = &glDisableiNULL; - enablei = &glEnableiNULL; - endConditionalRender = &glEndConditionalRenderNULL; - endTransformFeedback = &glEndTransformFeedbackNULL; - flushMappedBufferRange = &glFlushMappedBufferRangeNULL; - framebufferRenderbuffer = &glFramebufferRenderbufferNULL; - framebufferTexture1D = &glFramebufferTexture1DNULL; - framebufferTexture2D = &glFramebufferTexture2DNULL; - framebufferTexture3D = &glFramebufferTexture3DNULL; - framebufferTextureLayer = &glFramebufferTextureLayerNULL; - genFramebuffers = &glGenFramebuffersNULL; - genRenderbuffers = &glGenRenderbuffersNULL; - genVertexArrays = &glGenVertexArraysNULL; - generateMipmap = &glGenerateMipmapNULL; - getBooleani_v = &glGetBooleani_vNULL; - getFragDataLocation = &glGetFragDataLocationNULL; - getFramebufferAttachmentParameteriv = &glGetFramebufferAttachmentParameterivNULL; - getIntegeri_v = &glGetIntegeri_vNULL; - getRenderbufferParameteriv = &glGetRenderbufferParameterivNULL; - getStringi = &glGetStringiNULL; - getTexParameterIiv = &glGetTexParameterIivNULL; - getTexParameterIuiv = &glGetTexParameterIuivNULL; - getTransformFeedbackVarying = &glGetTransformFeedbackVaryingNULL; - getUniformuiv = &glGetUniformuivNULL; - getVertexAttribIiv = &glGetVertexAttribIivNULL; - getVertexAttribIuiv = &glGetVertexAttribIuivNULL; - isEnabledi = &glIsEnablediNULL; - isFramebuffer = &glIsFramebufferNULL; - isRenderbuffer = &glIsRenderbufferNULL; - isVertexArray = &glIsVertexArrayNULL; - mapBufferRange = &glMapBufferRangeNULL; - renderbufferStorage = &glRenderbufferStorageNULL; - renderbufferStorageMultisample = &glRenderbufferStorageMultisampleNULL; - texParameterIiv = &glTexParameterIivNULL; - texParameterIuiv = &glTexParameterIuivNULL; - transformFeedbackVaryings = &glTransformFeedbackVaryingsNULL; - uniform1ui = &glUniform1uiNULL; - uniform1uiv = &glUniform1uivNULL; - uniform2ui = &glUniform2uiNULL; - uniform2uiv = &glUniform2uivNULL; - uniform3ui = &glUniform3uiNULL; - uniform3uiv = &glUniform3uivNULL; - uniform4ui = &glUniform4uiNULL; - uniform4uiv = &glUniform4uivNULL; - vertexAttribI1i = &glVertexAttribI1iNULL; - vertexAttribI1iv = &glVertexAttribI1ivNULL; - vertexAttribI1ui = &glVertexAttribI1uiNULL; - vertexAttribI1uiv = &glVertexAttribI1uivNULL; - vertexAttribI2i = &glVertexAttribI2iNULL; - vertexAttribI2iv = &glVertexAttribI2ivNULL; - vertexAttribI2ui = &glVertexAttribI2uiNULL; - vertexAttribI2uiv = &glVertexAttribI2uivNULL; - vertexAttribI3i = &glVertexAttribI3iNULL; - vertexAttribI3iv = &glVertexAttribI3ivNULL; - vertexAttribI3ui = &glVertexAttribI3uiNULL; - vertexAttribI3uiv = &glVertexAttribI3uivNULL; - vertexAttribI4bv = &glVertexAttribI4bvNULL; - vertexAttribI4i = &glVertexAttribI4iNULL; - vertexAttribI4iv = &glVertexAttribI4ivNULL; - vertexAttribI4sv = &glVertexAttribI4svNULL; - vertexAttribI4ubv = &glVertexAttribI4ubvNULL; - vertexAttribI4ui = &glVertexAttribI4uiNULL; - vertexAttribI4uiv = &glVertexAttribI4uivNULL; - vertexAttribI4usv = &glVertexAttribI4usvNULL; - vertexAttribIPointer = &glVertexAttribIPointerNULL; - } - - if (version >= gl::Version(3, 1)) - { - copyBufferSubData = &glCopyBufferSubDataNULL; - drawArraysInstanced = &glDrawArraysInstancedNULL; - drawElementsInstanced = &glDrawElementsInstancedNULL; - getActiveUniformBlockName = &glGetActiveUniformBlockNameNULL; - getActiveUniformBlockiv = &glGetActiveUniformBlockivNULL; - getActiveUniformName = &glGetActiveUniformNameNULL; - getActiveUniformsiv = &glGetActiveUniformsivNULL; - getUniformBlockIndex = &glGetUniformBlockIndexNULL; - getUniformIndices = &glGetUniformIndicesNULL; - primitiveRestartIndex = &glPrimitiveRestartIndexNULL; - texBuffer = &glTexBufferNULL; - uniformBlockBinding = &glUniformBlockBindingNULL; - } - - if (version >= gl::Version(3, 2)) - { - clientWaitSync = &glClientWaitSyncNULL; - deleteSync = &glDeleteSyncNULL; - drawElementsBaseVertex = &glDrawElementsBaseVertexNULL; - drawElementsInstancedBaseVertex = &glDrawElementsInstancedBaseVertexNULL; - drawRangeElementsBaseVertex = &glDrawRangeElementsBaseVertexNULL; - fenceSync = &glFenceSyncNULL; - framebufferTexture = &glFramebufferTextureNULL; - getBufferParameteri64v = &glGetBufferParameteri64vNULL; - getInteger64i_v = &glGetInteger64i_vNULL; - getInteger64v = &glGetInteger64vNULL; - getMultisamplefv = &glGetMultisamplefvNULL; - getSynciv = &glGetSyncivNULL; - isSync = &glIsSyncNULL; - multiDrawElementsBaseVertex = &glMultiDrawElementsBaseVertexNULL; - provokingVertex = &glProvokingVertexNULL; - sampleMaski = &glSampleMaskiNULL; - texImage2DMultisample = &glTexImage2DMultisampleNULL; - texImage3DMultisample = &glTexImage3DMultisampleNULL; - waitSync = &glWaitSyncNULL; - } - - if (version >= gl::Version(3, 3)) - { - bindFragDataLocationIndexed = &glBindFragDataLocationIndexedNULL; - bindSampler = &glBindSamplerNULL; - deleteSamplers = &glDeleteSamplersNULL; - genSamplers = &glGenSamplersNULL; - getFragDataIndex = &glGetFragDataIndexNULL; - getQueryObjecti64v = &glGetQueryObjecti64vNULL; - getQueryObjectui64v = &glGetQueryObjectui64vNULL; - getSamplerParameterIiv = &glGetSamplerParameterIivNULL; - getSamplerParameterIuiv = &glGetSamplerParameterIuivNULL; - getSamplerParameterfv = &glGetSamplerParameterfvNULL; - getSamplerParameteriv = &glGetSamplerParameterivNULL; - isSampler = &glIsSamplerNULL; - queryCounter = &glQueryCounterNULL; - samplerParameterIiv = &glSamplerParameterIivNULL; - samplerParameterIuiv = &glSamplerParameterIuivNULL; - samplerParameterf = &glSamplerParameterfNULL; - samplerParameterfv = &glSamplerParameterfvNULL; - samplerParameteri = &glSamplerParameteriNULL; - samplerParameteriv = &glSamplerParameterivNULL; - vertexAttribDivisor = &glVertexAttribDivisorNULL; - vertexAttribP1ui = &glVertexAttribP1uiNULL; - vertexAttribP1uiv = &glVertexAttribP1uivNULL; - vertexAttribP2ui = &glVertexAttribP2uiNULL; - vertexAttribP2uiv = &glVertexAttribP2uivNULL; - vertexAttribP3ui = &glVertexAttribP3uiNULL; - vertexAttribP3uiv = &glVertexAttribP3uivNULL; - vertexAttribP4ui = &glVertexAttribP4uiNULL; - vertexAttribP4uiv = &glVertexAttribP4uivNULL; - } - - if (version >= gl::Version(4, 0)) - { - beginQueryIndexed = &glBeginQueryIndexedNULL; - bindTransformFeedback = &glBindTransformFeedbackNULL; - blendEquationSeparatei = &glBlendEquationSeparateiNULL; - blendEquationi = &glBlendEquationiNULL; - blendFuncSeparatei = &glBlendFuncSeparateiNULL; - blendFunci = &glBlendFunciNULL; - deleteTransformFeedbacks = &glDeleteTransformFeedbacksNULL; - drawArraysIndirect = &glDrawArraysIndirectNULL; - drawElementsIndirect = &glDrawElementsIndirectNULL; - drawTransformFeedback = &glDrawTransformFeedbackNULL; - drawTransformFeedbackStream = &glDrawTransformFeedbackStreamNULL; - endQueryIndexed = &glEndQueryIndexedNULL; - genTransformFeedbacks = &glGenTransformFeedbacksNULL; - getActiveSubroutineName = &glGetActiveSubroutineNameNULL; - getActiveSubroutineUniformName = &glGetActiveSubroutineUniformNameNULL; - getActiveSubroutineUniformiv = &glGetActiveSubroutineUniformivNULL; - getProgramStageiv = &glGetProgramStageivNULL; - getQueryIndexediv = &glGetQueryIndexedivNULL; - getSubroutineIndex = &glGetSubroutineIndexNULL; - getSubroutineUniformLocation = &glGetSubroutineUniformLocationNULL; - getUniformSubroutineuiv = &glGetUniformSubroutineuivNULL; - getUniformdv = &glGetUniformdvNULL; - isTransformFeedback = &glIsTransformFeedbackNULL; - minSampleShading = &glMinSampleShadingNULL; - patchParameterfv = &glPatchParameterfvNULL; - patchParameteri = &glPatchParameteriNULL; - pauseTransformFeedback = &glPauseTransformFeedbackNULL; - resumeTransformFeedback = &glResumeTransformFeedbackNULL; - uniform1d = &glUniform1dNULL; - uniform1dv = &glUniform1dvNULL; - uniform2d = &glUniform2dNULL; - uniform2dv = &glUniform2dvNULL; - uniform3d = &glUniform3dNULL; - uniform3dv = &glUniform3dvNULL; - uniform4d = &glUniform4dNULL; - uniform4dv = &glUniform4dvNULL; - uniformMatrix2dv = &glUniformMatrix2dvNULL; - uniformMatrix2x3dv = &glUniformMatrix2x3dvNULL; - uniformMatrix2x4dv = &glUniformMatrix2x4dvNULL; - uniformMatrix3dv = &glUniformMatrix3dvNULL; - uniformMatrix3x2dv = &glUniformMatrix3x2dvNULL; - uniformMatrix3x4dv = &glUniformMatrix3x4dvNULL; - uniformMatrix4dv = &glUniformMatrix4dvNULL; - uniformMatrix4x2dv = &glUniformMatrix4x2dvNULL; - uniformMatrix4x3dv = &glUniformMatrix4x3dvNULL; - uniformSubroutinesuiv = &glUniformSubroutinesuivNULL; - } - - if (version >= gl::Version(4, 1)) - { - activeShaderProgram = &glActiveShaderProgramNULL; - bindProgramPipeline = &glBindProgramPipelineNULL; - clearDepthf = &glClearDepthfNULL; - createShaderProgramv = &glCreateShaderProgramvNULL; - deleteProgramPipelines = &glDeleteProgramPipelinesNULL; - depthRangeArrayv = &glDepthRangeArrayvNULL; - depthRangeIndexed = &glDepthRangeIndexedNULL; - depthRangef = &glDepthRangefNULL; - genProgramPipelines = &glGenProgramPipelinesNULL; - getDoublei_v = &glGetDoublei_vNULL; - getFloati_v = &glGetFloati_vNULL; - getProgramBinary = &glGetProgramBinaryNULL; - getProgramPipelineInfoLog = &glGetProgramPipelineInfoLogNULL; - getProgramPipelineiv = &glGetProgramPipelineivNULL; - getShaderPrecisionFormat = &glGetShaderPrecisionFormatNULL; - getVertexAttribLdv = &glGetVertexAttribLdvNULL; - isProgramPipeline = &glIsProgramPipelineNULL; - programBinary = &glProgramBinaryNULL; - programParameteri = &glProgramParameteriNULL; - programUniform1d = &glProgramUniform1dNULL; - programUniform1dv = &glProgramUniform1dvNULL; - programUniform1f = &glProgramUniform1fNULL; - programUniform1fv = &glProgramUniform1fvNULL; - programUniform1i = &glProgramUniform1iNULL; - programUniform1iv = &glProgramUniform1ivNULL; - programUniform1ui = &glProgramUniform1uiNULL; - programUniform1uiv = &glProgramUniform1uivNULL; - programUniform2d = &glProgramUniform2dNULL; - programUniform2dv = &glProgramUniform2dvNULL; - programUniform2f = &glProgramUniform2fNULL; - programUniform2fv = &glProgramUniform2fvNULL; - programUniform2i = &glProgramUniform2iNULL; - programUniform2iv = &glProgramUniform2ivNULL; - programUniform2ui = &glProgramUniform2uiNULL; - programUniform2uiv = &glProgramUniform2uivNULL; - programUniform3d = &glProgramUniform3dNULL; - programUniform3dv = &glProgramUniform3dvNULL; - programUniform3f = &glProgramUniform3fNULL; - programUniform3fv = &glProgramUniform3fvNULL; - programUniform3i = &glProgramUniform3iNULL; - programUniform3iv = &glProgramUniform3ivNULL; - programUniform3ui = &glProgramUniform3uiNULL; - programUniform3uiv = &glProgramUniform3uivNULL; - programUniform4d = &glProgramUniform4dNULL; - programUniform4dv = &glProgramUniform4dvNULL; - programUniform4f = &glProgramUniform4fNULL; - programUniform4fv = &glProgramUniform4fvNULL; - programUniform4i = &glProgramUniform4iNULL; - programUniform4iv = &glProgramUniform4ivNULL; - programUniform4ui = &glProgramUniform4uiNULL; - programUniform4uiv = &glProgramUniform4uivNULL; - programUniformMatrix2dv = &glProgramUniformMatrix2dvNULL; - programUniformMatrix2fv = &glProgramUniformMatrix2fvNULL; - programUniformMatrix2x3dv = &glProgramUniformMatrix2x3dvNULL; - programUniformMatrix2x3fv = &glProgramUniformMatrix2x3fvNULL; - programUniformMatrix2x4dv = &glProgramUniformMatrix2x4dvNULL; - programUniformMatrix2x4fv = &glProgramUniformMatrix2x4fvNULL; - programUniformMatrix3dv = &glProgramUniformMatrix3dvNULL; - programUniformMatrix3fv = &glProgramUniformMatrix3fvNULL; - programUniformMatrix3x2dv = &glProgramUniformMatrix3x2dvNULL; - programUniformMatrix3x2fv = &glProgramUniformMatrix3x2fvNULL; - programUniformMatrix3x4dv = &glProgramUniformMatrix3x4dvNULL; - programUniformMatrix3x4fv = &glProgramUniformMatrix3x4fvNULL; - programUniformMatrix4dv = &glProgramUniformMatrix4dvNULL; - programUniformMatrix4fv = &glProgramUniformMatrix4fvNULL; - programUniformMatrix4x2dv = &glProgramUniformMatrix4x2dvNULL; - programUniformMatrix4x2fv = &glProgramUniformMatrix4x2fvNULL; - programUniformMatrix4x3dv = &glProgramUniformMatrix4x3dvNULL; - programUniformMatrix4x3fv = &glProgramUniformMatrix4x3fvNULL; - releaseShaderCompiler = &glReleaseShaderCompilerNULL; - scissorArrayv = &glScissorArrayvNULL; - scissorIndexed = &glScissorIndexedNULL; - scissorIndexedv = &glScissorIndexedvNULL; - shaderBinary = &glShaderBinaryNULL; - useProgramStages = &glUseProgramStagesNULL; - validateProgramPipeline = &glValidateProgramPipelineNULL; - vertexAttribL1d = &glVertexAttribL1dNULL; - vertexAttribL1dv = &glVertexAttribL1dvNULL; - vertexAttribL2d = &glVertexAttribL2dNULL; - vertexAttribL2dv = &glVertexAttribL2dvNULL; - vertexAttribL3d = &glVertexAttribL3dNULL; - vertexAttribL3dv = &glVertexAttribL3dvNULL; - vertexAttribL4d = &glVertexAttribL4dNULL; - vertexAttribL4dv = &glVertexAttribL4dvNULL; - vertexAttribLPointer = &glVertexAttribLPointerNULL; - viewportArrayv = &glViewportArrayvNULL; - viewportIndexedf = &glViewportIndexedfNULL; - viewportIndexedfv = &glViewportIndexedfvNULL; - } - - if (version >= gl::Version(4, 2)) - { - bindImageTexture = &glBindImageTextureNULL; - drawArraysInstancedBaseInstance = &glDrawArraysInstancedBaseInstanceNULL; - drawElementsInstancedBaseInstance = &glDrawElementsInstancedBaseInstanceNULL; - drawElementsInstancedBaseVertexBaseInstance = - &glDrawElementsInstancedBaseVertexBaseInstanceNULL; - drawTransformFeedbackInstanced = &glDrawTransformFeedbackInstancedNULL; - drawTransformFeedbackStreamInstanced = &glDrawTransformFeedbackStreamInstancedNULL; - getActiveAtomicCounterBufferiv = &glGetActiveAtomicCounterBufferivNULL; - getInternalformativ = &glGetInternalformativNULL; - memoryBarrier = &glMemoryBarrierNULL; - texStorage1D = &glTexStorage1DNULL; - texStorage2D = &glTexStorage2DNULL; - texStorage3D = &glTexStorage3DNULL; - } - - if (version >= gl::Version(4, 3)) - { - bindVertexBuffer = &glBindVertexBufferNULL; - clearBufferData = &glClearBufferDataNULL; - clearBufferSubData = &glClearBufferSubDataNULL; - copyImageSubData = &glCopyImageSubDataNULL; - debugMessageCallback = &glDebugMessageCallbackNULL; - debugMessageControl = &glDebugMessageControlNULL; - debugMessageInsert = &glDebugMessageInsertNULL; - dispatchCompute = &glDispatchComputeNULL; - dispatchComputeIndirect = &glDispatchComputeIndirectNULL; - framebufferParameteri = &glFramebufferParameteriNULL; - getDebugMessageLog = &glGetDebugMessageLogNULL; - getFramebufferParameteriv = &glGetFramebufferParameterivNULL; - getInternalformati64v = &glGetInternalformati64vNULL; - getObjectLabel = &glGetObjectLabelNULL; - getObjectPtrLabel = &glGetObjectPtrLabelNULL; - getPointerv = &glGetPointervNULL; - getProgramInterfaceiv = &glGetProgramInterfaceivNULL; - getProgramResourceIndex = &glGetProgramResourceIndexNULL; - getProgramResourceLocation = &glGetProgramResourceLocationNULL; - getProgramResourceLocationIndex = &glGetProgramResourceLocationIndexNULL; - getProgramResourceName = &glGetProgramResourceNameNULL; - getProgramResourceiv = &glGetProgramResourceivNULL; - invalidateBufferData = &glInvalidateBufferDataNULL; - invalidateBufferSubData = &glInvalidateBufferSubDataNULL; - invalidateFramebuffer = &glInvalidateFramebufferNULL; - invalidateSubFramebuffer = &glInvalidateSubFramebufferNULL; - invalidateTexImage = &glInvalidateTexImageNULL; - invalidateTexSubImage = &glInvalidateTexSubImageNULL; - multiDrawArraysIndirect = &glMultiDrawArraysIndirectNULL; - multiDrawElementsIndirect = &glMultiDrawElementsIndirectNULL; - objectLabel = &glObjectLabelNULL; - objectPtrLabel = &glObjectPtrLabelNULL; - popDebugGroup = &glPopDebugGroupNULL; - pushDebugGroup = &glPushDebugGroupNULL; - shaderStorageBlockBinding = &glShaderStorageBlockBindingNULL; - texBufferRange = &glTexBufferRangeNULL; - texStorage2DMultisample = &glTexStorage2DMultisampleNULL; - texStorage3DMultisample = &glTexStorage3DMultisampleNULL; - textureView = &glTextureViewNULL; - vertexAttribBinding = &glVertexAttribBindingNULL; - vertexAttribFormat = &glVertexAttribFormatNULL; - vertexAttribIFormat = &glVertexAttribIFormatNULL; - vertexAttribLFormat = &glVertexAttribLFormatNULL; - vertexBindingDivisor = &glVertexBindingDivisorNULL; - } - - if (version >= gl::Version(4, 4)) - { - bindBuffersBase = &glBindBuffersBaseNULL; - bindBuffersRange = &glBindBuffersRangeNULL; - bindImageTextures = &glBindImageTexturesNULL; - bindSamplers = &glBindSamplersNULL; - bindTextures = &glBindTexturesNULL; - bindVertexBuffers = &glBindVertexBuffersNULL; - bufferStorage = &glBufferStorageNULL; - clearTexImage = &glClearTexImageNULL; - clearTexSubImage = &glClearTexSubImageNULL; - } - - if (version >= gl::Version(4, 5)) - { - bindTextureUnit = &glBindTextureUnitNULL; - blitNamedFramebuffer = &glBlitNamedFramebufferNULL; - checkNamedFramebufferStatus = &glCheckNamedFramebufferStatusNULL; - clearNamedBufferData = &glClearNamedBufferDataNULL; - clearNamedBufferSubData = &glClearNamedBufferSubDataNULL; - clearNamedFramebufferfi = &glClearNamedFramebufferfiNULL; - clearNamedFramebufferfv = &glClearNamedFramebufferfvNULL; - clearNamedFramebufferiv = &glClearNamedFramebufferivNULL; - clearNamedFramebufferuiv = &glClearNamedFramebufferuivNULL; - clipControl = &glClipControlNULL; - compressedTextureSubImage1D = &glCompressedTextureSubImage1DNULL; - compressedTextureSubImage2D = &glCompressedTextureSubImage2DNULL; - compressedTextureSubImage3D = &glCompressedTextureSubImage3DNULL; - copyNamedBufferSubData = &glCopyNamedBufferSubDataNULL; - copyTextureSubImage1D = &glCopyTextureSubImage1DNULL; - copyTextureSubImage2D = &glCopyTextureSubImage2DNULL; - copyTextureSubImage3D = &glCopyTextureSubImage3DNULL; - createBuffers = &glCreateBuffersNULL; - createFramebuffers = &glCreateFramebuffersNULL; - createProgramPipelines = &glCreateProgramPipelinesNULL; - createQueries = &glCreateQueriesNULL; - createRenderbuffers = &glCreateRenderbuffersNULL; - createSamplers = &glCreateSamplersNULL; - createTextures = &glCreateTexturesNULL; - createTransformFeedbacks = &glCreateTransformFeedbacksNULL; - createVertexArrays = &glCreateVertexArraysNULL; - disableVertexArrayAttrib = &glDisableVertexArrayAttribNULL; - enableVertexArrayAttrib = &glEnableVertexArrayAttribNULL; - flushMappedNamedBufferRange = &glFlushMappedNamedBufferRangeNULL; - generateTextureMipmap = &glGenerateTextureMipmapNULL; - getCompressedTextureImage = &glGetCompressedTextureImageNULL; - getCompressedTextureSubImage = &glGetCompressedTextureSubImageNULL; - getGraphicsResetStatus = &glGetGraphicsResetStatusNULL; - getNamedBufferParameteri64v = &glGetNamedBufferParameteri64vNULL; - getNamedBufferParameteriv = &glGetNamedBufferParameterivNULL; - getNamedBufferPointerv = &glGetNamedBufferPointervNULL; - getNamedBufferSubData = &glGetNamedBufferSubDataNULL; - getNamedFramebufferAttachmentParameteriv = &glGetNamedFramebufferAttachmentParameterivNULL; - getNamedFramebufferParameteriv = &glGetNamedFramebufferParameterivNULL; - getNamedRenderbufferParameteriv = &glGetNamedRenderbufferParameterivNULL; - getQueryBufferObjecti64v = &glGetQueryBufferObjecti64vNULL; - getQueryBufferObjectiv = &glGetQueryBufferObjectivNULL; - getQueryBufferObjectui64v = &glGetQueryBufferObjectui64vNULL; - getQueryBufferObjectuiv = &glGetQueryBufferObjectuivNULL; - getTextureImage = &glGetTextureImageNULL; - getTextureLevelParameterfv = &glGetTextureLevelParameterfvNULL; - getTextureLevelParameteriv = &glGetTextureLevelParameterivNULL; - getTextureParameterIiv = &glGetTextureParameterIivNULL; - getTextureParameterIuiv = &glGetTextureParameterIuivNULL; - getTextureParameterfv = &glGetTextureParameterfvNULL; - getTextureParameteriv = &glGetTextureParameterivNULL; - getTextureSubImage = &glGetTextureSubImageNULL; - getTransformFeedbacki64_v = &glGetTransformFeedbacki64_vNULL; - getTransformFeedbacki_v = &glGetTransformFeedbacki_vNULL; - getTransformFeedbackiv = &glGetTransformFeedbackivNULL; - getVertexArrayIndexed64iv = &glGetVertexArrayIndexed64ivNULL; - getVertexArrayIndexediv = &glGetVertexArrayIndexedivNULL; - getVertexArrayiv = &glGetVertexArrayivNULL; - getnCompressedTexImage = &glGetnCompressedTexImageNULL; - getnTexImage = &glGetnTexImageNULL; - getnUniformdv = &glGetnUniformdvNULL; - getnUniformfv = &glGetnUniformfvNULL; - getnUniformiv = &glGetnUniformivNULL; - getnUniformuiv = &glGetnUniformuivNULL; - invalidateNamedFramebufferData = &glInvalidateNamedFramebufferDataNULL; - invalidateNamedFramebufferSubData = &glInvalidateNamedFramebufferSubDataNULL; - mapNamedBuffer = &glMapNamedBufferNULL; - mapNamedBufferRange = &glMapNamedBufferRangeNULL; - memoryBarrierByRegion = &glMemoryBarrierByRegionNULL; - namedBufferData = &glNamedBufferDataNULL; - namedBufferStorage = &glNamedBufferStorageNULL; - namedBufferSubData = &glNamedBufferSubDataNULL; - namedFramebufferDrawBuffer = &glNamedFramebufferDrawBufferNULL; - namedFramebufferDrawBuffers = &glNamedFramebufferDrawBuffersNULL; - namedFramebufferParameteri = &glNamedFramebufferParameteriNULL; - namedFramebufferReadBuffer = &glNamedFramebufferReadBufferNULL; - namedFramebufferRenderbuffer = &glNamedFramebufferRenderbufferNULL; - namedFramebufferTexture = &glNamedFramebufferTextureNULL; - namedFramebufferTextureLayer = &glNamedFramebufferTextureLayerNULL; - namedRenderbufferStorage = &glNamedRenderbufferStorageNULL; - namedRenderbufferStorageMultisample = &glNamedRenderbufferStorageMultisampleNULL; - readnPixels = &glReadnPixelsNULL; - textureBarrier = &glTextureBarrierNULL; - textureBuffer = &glTextureBufferNULL; - textureBufferRange = &glTextureBufferRangeNULL; - textureParameterIiv = &glTextureParameterIivNULL; - textureParameterIuiv = &glTextureParameterIuivNULL; - textureParameterf = &glTextureParameterfNULL; - textureParameterfv = &glTextureParameterfvNULL; - textureParameteri = &glTextureParameteriNULL; - textureParameteriv = &glTextureParameterivNULL; - textureStorage1D = &glTextureStorage1DNULL; - textureStorage2D = &glTextureStorage2DNULL; - textureStorage2DMultisample = &glTextureStorage2DMultisampleNULL; - textureStorage3D = &glTextureStorage3DNULL; - textureStorage3DMultisample = &glTextureStorage3DMultisampleNULL; - textureSubImage1D = &glTextureSubImage1DNULL; - textureSubImage2D = &glTextureSubImage2DNULL; - textureSubImage3D = &glTextureSubImage3DNULL; - transformFeedbackBufferBase = &glTransformFeedbackBufferBaseNULL; - transformFeedbackBufferRange = &glTransformFeedbackBufferRangeNULL; - unmapNamedBuffer = &glUnmapNamedBufferNULL; - vertexArrayAttribBinding = &glVertexArrayAttribBindingNULL; - vertexArrayAttribFormat = &glVertexArrayAttribFormatNULL; - vertexArrayAttribIFormat = &glVertexArrayAttribIFormatNULL; - vertexArrayAttribLFormat = &glVertexArrayAttribLFormatNULL; - vertexArrayBindingDivisor = &glVertexArrayBindingDivisorNULL; - vertexArrayElementBuffer = &glVertexArrayElementBufferNULL; - vertexArrayVertexBuffer = &glVertexArrayVertexBufferNULL; - vertexArrayVertexBuffers = &glVertexArrayVertexBuffersNULL; - } -# endif // defined(ANGLE_ENABLE_GL_DESKTOP_BACKEND) -} - -void DispatchTableGL::initProcsGLESNULL(const gl::Version &version, - const std::set &extensions) -{ - if (extensions.count("GL_EXT_base_instance") != 0) - { - drawArraysInstancedBaseInstance = &glDrawArraysInstancedBaseInstanceNULL; - drawElementsInstancedBaseInstance = &glDrawElementsInstancedBaseInstanceNULL; - drawElementsInstancedBaseVertexBaseInstance = - &glDrawElementsInstancedBaseVertexBaseInstanceNULL; - } - - if (extensions.count("GL_EXT_blend_func_extended") != 0) - { - bindFragDataLocation = &glBindFragDataLocationNULL; - bindFragDataLocationIndexed = &glBindFragDataLocationIndexedNULL; - getFragDataIndex = &glGetFragDataIndexNULL; - getProgramResourceLocationIndex = &glGetProgramResourceLocationIndexNULL; - } - - if (extensions.count("GL_EXT_buffer_storage") != 0) - { - bufferStorage = &glBufferStorageNULL; - } - - if (extensions.count("GL_EXT_clear_texture") != 0) - { - clearTexImage = &glClearTexImageNULL; - clearTexSubImage = &glClearTexSubImageNULL; - } - - if (extensions.count("GL_EXT_clip_control") != 0) - { - clipControl = &glClipControlNULL; - } - - if (extensions.count("GL_EXT_copy_image") != 0) - { - copyImageSubData = &glCopyImageSubDataNULL; - } - - if (extensions.count("GL_EXT_discard_framebuffer") != 0) - { - discardFramebufferEXT = &glDiscardFramebufferEXTNULL; - } - - if (extensions.count("GL_EXT_disjoint_timer_query") != 0) - { - beginQuery = &glBeginQueryNULL; - deleteQueries = &glDeleteQueriesNULL; - endQuery = &glEndQueryNULL; - genQueries = &glGenQueriesNULL; - getInteger64v = &glGetInteger64vNULL; - getQueryObjecti64v = &glGetQueryObjecti64vNULL; - getQueryObjectiv = &glGetQueryObjectivNULL; - getQueryObjectui64v = &glGetQueryObjectui64vNULL; - getQueryObjectuiv = &glGetQueryObjectuivNULL; - getQueryiv = &glGetQueryivNULL; - isQuery = &glIsQueryNULL; - queryCounter = &glQueryCounterNULL; - } - - if (extensions.count("GL_EXT_draw_buffers") != 0) - { - drawBuffers = &glDrawBuffersNULL; - } - - if (extensions.count("GL_EXT_draw_buffers_indexed") != 0) - { - blendEquationSeparatei = &glBlendEquationSeparateiNULL; - blendEquationi = &glBlendEquationiNULL; - blendFuncSeparatei = &glBlendFuncSeparateiNULL; - blendFunci = &glBlendFunciNULL; - colorMaski = &glColorMaskiNULL; - disablei = &glDisableiNULL; - enablei = &glEnableiNULL; - isEnabledi = &glIsEnablediNULL; - } - - if (extensions.count("GL_EXT_draw_elements_base_vertex") != 0) - { - drawElementsBaseVertex = &glDrawElementsBaseVertexNULL; - drawElementsInstancedBaseVertex = &glDrawElementsInstancedBaseVertexNULL; - drawRangeElementsBaseVertex = &glDrawRangeElementsBaseVertexNULL; - multiDrawElementsBaseVertex = &glMultiDrawElementsBaseVertexNULL; - } - - if (extensions.count("GL_EXT_draw_transform_feedback") != 0) - { - drawTransformFeedback = &glDrawTransformFeedbackNULL; - drawTransformFeedbackInstanced = &glDrawTransformFeedbackInstancedNULL; - } - - if (extensions.count("GL_EXT_geometry_shader") != 0) - { - framebufferTexture = &glFramebufferTextureNULL; - } - - if (extensions.count("GL_EXT_instanced_arrays") != 0) - { - vertexAttribDivisor = &glVertexAttribDivisorNULL; - } - - if (extensions.count("GL_EXT_map_buffer_range") != 0) - { - flushMappedBufferRange = &glFlushMappedBufferRangeNULL; - mapBufferRange = &glMapBufferRangeNULL; - } - - if (extensions.count("GL_EXT_multi_draw_indirect") != 0) - { - multiDrawArraysIndirect = &glMultiDrawArraysIndirectNULL; - multiDrawElementsIndirect = &glMultiDrawElementsIndirectNULL; - } - - if (extensions.count("GL_EXT_multisampled_render_to_texture") != 0) - { - framebufferTexture2DMultisampleEXT = &glFramebufferTexture2DMultisampleEXTNULL; - renderbufferStorageMultisample = &glRenderbufferStorageMultisampleNULL; - renderbufferStorageMultisampleEXT = &glRenderbufferStorageMultisampleEXTNULL; - } - - if (extensions.count("GL_EXT_multiview_draw_buffers") != 0) - { - getIntegeri_v = &glGetIntegeri_vNULL; - } - - if (extensions.count("GL_EXT_occlusion_query_boolean") != 0) - { - beginQuery = &glBeginQueryNULL; - deleteQueries = &glDeleteQueriesNULL; - endQuery = &glEndQueryNULL; - genQueries = &glGenQueriesNULL; - getQueryObjectuiv = &glGetQueryObjectuivNULL; - getQueryiv = &glGetQueryivNULL; - isQuery = &glIsQueryNULL; - } - - if (extensions.count("GL_EXT_primitive_bounding_box") != 0) - { - primitiveBoundingBox = &glPrimitiveBoundingBoxNULL; - } - - if (extensions.count("GL_EXT_robustness") != 0) - { - getGraphicsResetStatus = &glGetGraphicsResetStatusNULL; - getnUniformfv = &glGetnUniformfvNULL; - getnUniformiv = &glGetnUniformivNULL; - readnPixels = &glReadnPixelsNULL; - } - - if (extensions.count("GL_EXT_separate_shader_objects") != 0) - { - activeShaderProgram = &glActiveShaderProgramNULL; - bindProgramPipeline = &glBindProgramPipelineNULL; - createShaderProgramv = &glCreateShaderProgramvNULL; - deleteProgramPipelines = &glDeleteProgramPipelinesNULL; - genProgramPipelines = &glGenProgramPipelinesNULL; - getProgramPipelineInfoLog = &glGetProgramPipelineInfoLogNULL; - getProgramPipelineiv = &glGetProgramPipelineivNULL; - isProgramPipeline = &glIsProgramPipelineNULL; - programParameteri = &glProgramParameteriNULL; - programUniform1f = &glProgramUniform1fNULL; - programUniform1fv = &glProgramUniform1fvNULL; - programUniform1i = &glProgramUniform1iNULL; - programUniform1iv = &glProgramUniform1ivNULL; - programUniform1ui = &glProgramUniform1uiNULL; - programUniform1uiv = &glProgramUniform1uivNULL; - programUniform2f = &glProgramUniform2fNULL; - programUniform2fv = &glProgramUniform2fvNULL; - programUniform2i = &glProgramUniform2iNULL; - programUniform2iv = &glProgramUniform2ivNULL; - programUniform2ui = &glProgramUniform2uiNULL; - programUniform2uiv = &glProgramUniform2uivNULL; - programUniform3f = &glProgramUniform3fNULL; - programUniform3fv = &glProgramUniform3fvNULL; - programUniform3i = &glProgramUniform3iNULL; - programUniform3iv = &glProgramUniform3ivNULL; - programUniform3ui = &glProgramUniform3uiNULL; - programUniform3uiv = &glProgramUniform3uivNULL; - programUniform4f = &glProgramUniform4fNULL; - programUniform4fv = &glProgramUniform4fvNULL; - programUniform4i = &glProgramUniform4iNULL; - programUniform4iv = &glProgramUniform4ivNULL; - programUniform4ui = &glProgramUniform4uiNULL; - programUniform4uiv = &glProgramUniform4uivNULL; - programUniformMatrix2fv = &glProgramUniformMatrix2fvNULL; - programUniformMatrix2x3fv = &glProgramUniformMatrix2x3fvNULL; - programUniformMatrix2x4fv = &glProgramUniformMatrix2x4fvNULL; - programUniformMatrix3fv = &glProgramUniformMatrix3fvNULL; - programUniformMatrix3x2fv = &glProgramUniformMatrix3x2fvNULL; - programUniformMatrix3x4fv = &glProgramUniformMatrix3x4fvNULL; - programUniformMatrix4fv = &glProgramUniformMatrix4fvNULL; - programUniformMatrix4x2fv = &glProgramUniformMatrix4x2fvNULL; - programUniformMatrix4x3fv = &glProgramUniformMatrix4x3fvNULL; - useProgramStages = &glUseProgramStagesNULL; - validateProgramPipeline = &glValidateProgramPipelineNULL; - } - - if (extensions.count("GL_EXT_tessellation_shader") != 0) - { - patchParameteri = &glPatchParameteriNULL; - } - - if (extensions.count("GL_EXT_texture_border_clamp") != 0) - { - getSamplerParameterIiv = &glGetSamplerParameterIivNULL; - getSamplerParameterIuiv = &glGetSamplerParameterIuivNULL; - getTexParameterIiv = &glGetTexParameterIivNULL; - getTexParameterIuiv = &glGetTexParameterIuivNULL; - samplerParameterIiv = &glSamplerParameterIivNULL; - samplerParameterIuiv = &glSamplerParameterIuivNULL; - texParameterIiv = &glTexParameterIivNULL; - texParameterIuiv = &glTexParameterIuivNULL; - } - - if (extensions.count("GL_EXT_texture_buffer") != 0) - { - texBuffer = &glTexBufferNULL; - texBufferEXT = &glTexBufferEXTNULL; - texBufferRange = &glTexBufferRangeNULL; - texBufferRangeEXT = &glTexBufferRangeEXTNULL; - } - - if (extensions.count("GL_EXT_texture_view") != 0) - { - textureView = &glTextureViewNULL; - } - - if (extensions.count("GL_IMG_multisampled_render_to_texture") != 0) - { - framebufferTexture2DMultisampleIMG = &glFramebufferTexture2DMultisampleIMGNULL; - renderbufferStorageMultisampleIMG = &glRenderbufferStorageMultisampleIMGNULL; - } - - if (extensions.count("GL_KHR_debug") != 0) - { - debugMessageCallback = &glDebugMessageCallbackNULL; - debugMessageControl = &glDebugMessageControlNULL; - debugMessageInsert = &glDebugMessageInsertNULL; - getDebugMessageLog = &glGetDebugMessageLogNULL; - getObjectLabel = &glGetObjectLabelNULL; - getObjectPtrLabel = &glGetObjectPtrLabelNULL; - getPointerv = &glGetPointervNULL; - objectLabel = &glObjectLabelNULL; - objectPtrLabel = &glObjectPtrLabelNULL; - popDebugGroup = &glPopDebugGroupNULL; - pushDebugGroup = &glPushDebugGroupNULL; - } - - if (extensions.count("GL_KHR_robustness") != 0) - { - getGraphicsResetStatus = &glGetGraphicsResetStatusNULL; - getnUniformfv = &glGetnUniformfvNULL; - getnUniformiv = &glGetnUniformivNULL; - getnUniformuiv = &glGetnUniformuivNULL; - readnPixels = &glReadnPixelsNULL; - } - - if (extensions.count("GL_NV_framebuffer_blit") != 0) - { - blitFramebufferNV = &glBlitFramebufferNVNULL; - } - - if (extensions.count("GL_NV_polygon_mode") != 0) - { - polygonModeNV = &glPolygonModeNVNULL; - } - - if (extensions.count("GL_OES_EGL_image") != 0) - { - eGLImageTargetRenderbufferStorageOES = &glEGLImageTargetRenderbufferStorageOESNULL; - eGLImageTargetTexture2DOES = &glEGLImageTargetTexture2DOESNULL; - } - - if (extensions.count("GL_OES_copy_image") != 0) - { - copyImageSubData = &glCopyImageSubDataNULL; - } - - if (extensions.count("GL_OES_draw_buffers_indexed") != 0) - { - blendEquationSeparatei = &glBlendEquationSeparateiNULL; - blendEquationi = &glBlendEquationiNULL; - blendFuncSeparatei = &glBlendFuncSeparateiNULL; - blendFunci = &glBlendFunciNULL; - colorMaski = &glColorMaskiNULL; - disablei = &glDisableiNULL; - enablei = &glEnableiNULL; - isEnabledi = &glIsEnablediNULL; - } - - if (extensions.count("GL_OES_draw_elements_base_vertex") != 0) - { - drawElementsBaseVertex = &glDrawElementsBaseVertexNULL; - drawElementsInstancedBaseVertex = &glDrawElementsInstancedBaseVertexNULL; - drawRangeElementsBaseVertex = &glDrawRangeElementsBaseVertexNULL; - multiDrawElementsBaseVertex = &glMultiDrawElementsBaseVertexNULL; - } - - if (extensions.count("GL_OES_geometry_shader") != 0) - { - framebufferTexture = &glFramebufferTextureNULL; - } - - if (extensions.count("GL_OES_get_program_binary") != 0) - { - getProgramBinary = &glGetProgramBinaryNULL; - programBinary = &glProgramBinaryNULL; - } - - if (extensions.count("GL_OES_mapbuffer") != 0) - { - getBufferPointerv = &glGetBufferPointervNULL; - mapBuffer = &glMapBufferNULL; - unmapBuffer = &glUnmapBufferNULL; - } - - if (extensions.count("GL_OES_primitive_bounding_box") != 0) - { - primitiveBoundingBox = &glPrimitiveBoundingBoxNULL; - } - - if (extensions.count("GL_OES_sample_shading") != 0) - { - minSampleShading = &glMinSampleShadingNULL; - } - - if (extensions.count("GL_OES_tessellation_shader") != 0) - { - patchParameteri = &glPatchParameteriNULL; - } - - if (extensions.count("GL_OES_texture_3D") != 0) - { - compressedTexImage3D = &glCompressedTexImage3DNULL; - compressedTexSubImage3D = &glCompressedTexSubImage3DNULL; - copyTexSubImage3D = &glCopyTexSubImage3DNULL; - framebufferTexture3D = &glFramebufferTexture3DNULL; - texImage3D = &glTexImage3DNULL; - texSubImage3D = &glTexSubImage3DNULL; - } - - if (extensions.count("GL_OES_texture_border_clamp") != 0) - { - getSamplerParameterIiv = &glGetSamplerParameterIivNULL; - getSamplerParameterIuiv = &glGetSamplerParameterIuivNULL; - getTexParameterIiv = &glGetTexParameterIivNULL; - getTexParameterIuiv = &glGetTexParameterIuivNULL; - samplerParameterIiv = &glSamplerParameterIivNULL; - samplerParameterIuiv = &glSamplerParameterIuivNULL; - texParameterIiv = &glTexParameterIivNULL; - texParameterIuiv = &glTexParameterIuivNULL; - } - - if (extensions.count("GL_OES_texture_buffer") != 0) - { - texBuffer = &glTexBufferNULL; - texBufferOES = &glTexBufferOESNULL; - texBufferRange = &glTexBufferRangeNULL; - texBufferRangeOES = &glTexBufferRangeOESNULL; - } - - if (extensions.count("GL_OES_texture_storage_multisample_2d_array") != 0) - { - texStorage3DMultisample = &glTexStorage3DMultisampleNULL; - } - - if (extensions.count("GL_OES_texture_view") != 0) - { - textureView = &glTextureViewNULL; - } - - if (extensions.count("GL_OES_vertex_array_object") != 0) - { - bindVertexArray = &glBindVertexArrayNULL; - deleteVertexArrays = &glDeleteVertexArraysNULL; - genVertexArrays = &glGenVertexArraysNULL; - isVertexArray = &glIsVertexArrayNULL; - } - - if (extensions.count("GL_OES_viewport_array") != 0) - { - disablei = &glDisableiNULL; - enablei = &glEnableiNULL; - getFloati_v = &glGetFloati_vNULL; - isEnabledi = &glIsEnablediNULL; - scissorArrayv = &glScissorArrayvNULL; - scissorIndexed = &glScissorIndexedNULL; - scissorIndexedv = &glScissorIndexedvNULL; - viewportArrayv = &glViewportArrayvNULL; - viewportIndexedf = &glViewportIndexedfNULL; - viewportIndexedfv = &glViewportIndexedfvNULL; - } - - if (extensions.count("GL_QCOM_tiled_rendering") != 0) - { - endTilingQCOM = &glEndTilingQCOMNULL; - startTilingQCOM = &glStartTilingQCOMNULL; - } - - if (version >= gl::Version(2, 0)) - { - activeTexture = &glActiveTextureNULL; - attachShader = &glAttachShaderNULL; - bindAttribLocation = &glBindAttribLocationNULL; - bindBuffer = &glBindBufferNULL; - bindFramebuffer = &glBindFramebufferNULL; - bindRenderbuffer = &glBindRenderbufferNULL; - bindTexture = &glBindTextureNULL; - blendColor = &glBlendColorNULL; - blendEquation = &glBlendEquationNULL; - blendEquationSeparate = &glBlendEquationSeparateNULL; - blendFunc = &glBlendFuncNULL; - blendFuncSeparate = &glBlendFuncSeparateNULL; - bufferData = &glBufferDataNULL; - bufferSubData = &glBufferSubDataNULL; - checkFramebufferStatus = &glCheckFramebufferStatusNULL; - clear = &glClearNULL; - clearColor = &glClearColorNULL; - clearDepthf = &glClearDepthfNULL; - clearStencil = &glClearStencilNULL; - colorMask = &glColorMaskNULL; - compileShader = &glCompileShaderNULL; - compressedTexImage2D = &glCompressedTexImage2DNULL; - compressedTexSubImage2D = &glCompressedTexSubImage2DNULL; - copyTexImage2D = &glCopyTexImage2DNULL; - copyTexSubImage2D = &glCopyTexSubImage2DNULL; - createProgram = &glCreateProgramNULL; - createShader = &glCreateShaderNULL; - cullFace = &glCullFaceNULL; - deleteBuffers = &glDeleteBuffersNULL; - deleteFramebuffers = &glDeleteFramebuffersNULL; - deleteProgram = &glDeleteProgramNULL; - deleteRenderbuffers = &glDeleteRenderbuffersNULL; - deleteShader = &glDeleteShaderNULL; - deleteTextures = &glDeleteTexturesNULL; - depthFunc = &glDepthFuncNULL; - depthMask = &glDepthMaskNULL; - depthRangef = &glDepthRangefNULL; - detachShader = &glDetachShaderNULL; - disable = &glDisableNULL; - disableVertexAttribArray = &glDisableVertexAttribArrayNULL; - drawArrays = &glDrawArraysNULL; - drawElements = &glDrawElementsNULL; - enable = &glEnableNULL; - enableVertexAttribArray = &glEnableVertexAttribArrayNULL; - finish = &glFinishNULL; - flush = &glFlushNULL; - framebufferRenderbuffer = &glFramebufferRenderbufferNULL; - framebufferTexture2D = &glFramebufferTexture2DNULL; - frontFace = &glFrontFaceNULL; - genBuffers = &glGenBuffersNULL; - genFramebuffers = &glGenFramebuffersNULL; - genRenderbuffers = &glGenRenderbuffersNULL; - genTextures = &glGenTexturesNULL; - generateMipmap = &glGenerateMipmapNULL; - getActiveAttrib = &glGetActiveAttribNULL; - getActiveUniform = &glGetActiveUniformNULL; - getAttachedShaders = &glGetAttachedShadersNULL; - getAttribLocation = &glGetAttribLocationNULL; - getBooleanv = &glGetBooleanvNULL; - getBufferParameteriv = &glGetBufferParameterivNULL; - getError = &glGetErrorNULL; - getFloatv = &glGetFloatvNULL; - getFramebufferAttachmentParameteriv = &glGetFramebufferAttachmentParameterivNULL; - getIntegerv = &glGetIntegervNULL; - getProgramInfoLog = &glGetProgramInfoLogNULL; - getProgramiv = &glGetProgramivNULL; - getRenderbufferParameteriv = &glGetRenderbufferParameterivNULL; - getShaderInfoLog = &glGetShaderInfoLogNULL; - getShaderPrecisionFormat = &glGetShaderPrecisionFormatNULL; - getShaderSource = &glGetShaderSourceNULL; - getShaderiv = &glGetShaderivNULL; - getString = &glGetStringNULL; - getTexParameterfv = &glGetTexParameterfvNULL; - getTexParameteriv = &glGetTexParameterivNULL; - getUniformLocation = &glGetUniformLocationNULL; - getUniformfv = &glGetUniformfvNULL; - getUniformiv = &glGetUniformivNULL; - getVertexAttribPointerv = &glGetVertexAttribPointervNULL; - getVertexAttribfv = &glGetVertexAttribfvNULL; - getVertexAttribiv = &glGetVertexAttribivNULL; - hint = &glHintNULL; - isBuffer = &glIsBufferNULL; - isEnabled = &glIsEnabledNULL; - isFramebuffer = &glIsFramebufferNULL; - isProgram = &glIsProgramNULL; - isRenderbuffer = &glIsRenderbufferNULL; - isShader = &glIsShaderNULL; - isTexture = &glIsTextureNULL; - lineWidth = &glLineWidthNULL; - linkProgram = &glLinkProgramNULL; - pixelStorei = &glPixelStoreiNULL; - polygonOffset = &glPolygonOffsetNULL; - readPixels = &glReadPixelsNULL; - releaseShaderCompiler = &glReleaseShaderCompilerNULL; - renderbufferStorage = &glRenderbufferStorageNULL; - sampleCoverage = &glSampleCoverageNULL; - scissor = &glScissorNULL; - shaderBinary = &glShaderBinaryNULL; - shaderSource = &glShaderSourceNULL; - stencilFunc = &glStencilFuncNULL; - stencilFuncSeparate = &glStencilFuncSeparateNULL; - stencilMask = &glStencilMaskNULL; - stencilMaskSeparate = &glStencilMaskSeparateNULL; - stencilOp = &glStencilOpNULL; - stencilOpSeparate = &glStencilOpSeparateNULL; - texImage2D = &glTexImage2DNULL; - texParameterf = &glTexParameterfNULL; - texParameterfv = &glTexParameterfvNULL; - texParameteri = &glTexParameteriNULL; - texParameteriv = &glTexParameterivNULL; - texSubImage2D = &glTexSubImage2DNULL; - uniform1f = &glUniform1fNULL; - uniform1fv = &glUniform1fvNULL; - uniform1i = &glUniform1iNULL; - uniform1iv = &glUniform1ivNULL; - uniform2f = &glUniform2fNULL; - uniform2fv = &glUniform2fvNULL; - uniform2i = &glUniform2iNULL; - uniform2iv = &glUniform2ivNULL; - uniform3f = &glUniform3fNULL; - uniform3fv = &glUniform3fvNULL; - uniform3i = &glUniform3iNULL; - uniform3iv = &glUniform3ivNULL; - uniform4f = &glUniform4fNULL; - uniform4fv = &glUniform4fvNULL; - uniform4i = &glUniform4iNULL; - uniform4iv = &glUniform4ivNULL; - uniformMatrix2fv = &glUniformMatrix2fvNULL; - uniformMatrix3fv = &glUniformMatrix3fvNULL; - uniformMatrix4fv = &glUniformMatrix4fvNULL; - useProgram = &glUseProgramNULL; - validateProgram = &glValidateProgramNULL; - vertexAttrib1f = &glVertexAttrib1fNULL; - vertexAttrib1fv = &glVertexAttrib1fvNULL; - vertexAttrib2f = &glVertexAttrib2fNULL; - vertexAttrib2fv = &glVertexAttrib2fvNULL; - vertexAttrib3f = &glVertexAttrib3fNULL; - vertexAttrib3fv = &glVertexAttrib3fvNULL; - vertexAttrib4f = &glVertexAttrib4fNULL; - vertexAttrib4fv = &glVertexAttrib4fvNULL; - vertexAttribPointer = &glVertexAttribPointerNULL; - viewport = &glViewportNULL; - } - - if (version >= gl::Version(3, 0)) - { - beginQuery = &glBeginQueryNULL; - beginTransformFeedback = &glBeginTransformFeedbackNULL; - bindBufferBase = &glBindBufferBaseNULL; - bindBufferRange = &glBindBufferRangeNULL; - bindSampler = &glBindSamplerNULL; - bindTransformFeedback = &glBindTransformFeedbackNULL; - bindVertexArray = &glBindVertexArrayNULL; - blitFramebuffer = &glBlitFramebufferNULL; - clearBufferfi = &glClearBufferfiNULL; - clearBufferfv = &glClearBufferfvNULL; - clearBufferiv = &glClearBufferivNULL; - clearBufferuiv = &glClearBufferuivNULL; - clientWaitSync = &glClientWaitSyncNULL; - compressedTexImage3D = &glCompressedTexImage3DNULL; - compressedTexSubImage3D = &glCompressedTexSubImage3DNULL; - copyBufferSubData = &glCopyBufferSubDataNULL; - copyTexSubImage3D = &glCopyTexSubImage3DNULL; - deleteQueries = &glDeleteQueriesNULL; - deleteSamplers = &glDeleteSamplersNULL; - deleteSync = &glDeleteSyncNULL; - deleteTransformFeedbacks = &glDeleteTransformFeedbacksNULL; - deleteVertexArrays = &glDeleteVertexArraysNULL; - drawArraysInstanced = &glDrawArraysInstancedNULL; - drawBuffers = &glDrawBuffersNULL; - drawElementsInstanced = &glDrawElementsInstancedNULL; - drawRangeElements = &glDrawRangeElementsNULL; - endQuery = &glEndQueryNULL; - endTransformFeedback = &glEndTransformFeedbackNULL; - fenceSync = &glFenceSyncNULL; - flushMappedBufferRange = &glFlushMappedBufferRangeNULL; - framebufferTextureLayer = &glFramebufferTextureLayerNULL; - genQueries = &glGenQueriesNULL; - genSamplers = &glGenSamplersNULL; - genTransformFeedbacks = &glGenTransformFeedbacksNULL; - genVertexArrays = &glGenVertexArraysNULL; - getActiveUniformBlockName = &glGetActiveUniformBlockNameNULL; - getActiveUniformBlockiv = &glGetActiveUniformBlockivNULL; - getActiveUniformsiv = &glGetActiveUniformsivNULL; - getBufferParameteri64v = &glGetBufferParameteri64vNULL; - getBufferPointerv = &glGetBufferPointervNULL; - getFragDataLocation = &glGetFragDataLocationNULL; - getInteger64i_v = &glGetInteger64i_vNULL; - getInteger64v = &glGetInteger64vNULL; - getIntegeri_v = &glGetIntegeri_vNULL; - getInternalformativ = &glGetInternalformativNULL; - getProgramBinary = &glGetProgramBinaryNULL; - getQueryObjectuiv = &glGetQueryObjectuivNULL; - getQueryiv = &glGetQueryivNULL; - getSamplerParameterfv = &glGetSamplerParameterfvNULL; - getSamplerParameteriv = &glGetSamplerParameterivNULL; - getStringi = &glGetStringiNULL; - getSynciv = &glGetSyncivNULL; - getTransformFeedbackVarying = &glGetTransformFeedbackVaryingNULL; - getUniformBlockIndex = &glGetUniformBlockIndexNULL; - getUniformIndices = &glGetUniformIndicesNULL; - getUniformuiv = &glGetUniformuivNULL; - getVertexAttribIiv = &glGetVertexAttribIivNULL; - getVertexAttribIuiv = &glGetVertexAttribIuivNULL; - invalidateFramebuffer = &glInvalidateFramebufferNULL; - invalidateSubFramebuffer = &glInvalidateSubFramebufferNULL; - isQuery = &glIsQueryNULL; - isSampler = &glIsSamplerNULL; - isSync = &glIsSyncNULL; - isTransformFeedback = &glIsTransformFeedbackNULL; - isVertexArray = &glIsVertexArrayNULL; - mapBufferRange = &glMapBufferRangeNULL; - pauseTransformFeedback = &glPauseTransformFeedbackNULL; - programBinary = &glProgramBinaryNULL; - programParameteri = &glProgramParameteriNULL; - readBuffer = &glReadBufferNULL; - renderbufferStorageMultisample = &glRenderbufferStorageMultisampleNULL; - resumeTransformFeedback = &glResumeTransformFeedbackNULL; - samplerParameterf = &glSamplerParameterfNULL; - samplerParameterfv = &glSamplerParameterfvNULL; - samplerParameteri = &glSamplerParameteriNULL; - samplerParameteriv = &glSamplerParameterivNULL; - texImage3D = &glTexImage3DNULL; - texStorage2D = &glTexStorage2DNULL; - texStorage3D = &glTexStorage3DNULL; - texSubImage3D = &glTexSubImage3DNULL; - transformFeedbackVaryings = &glTransformFeedbackVaryingsNULL; - uniform1ui = &glUniform1uiNULL; - uniform1uiv = &glUniform1uivNULL; - uniform2ui = &glUniform2uiNULL; - uniform2uiv = &glUniform2uivNULL; - uniform3ui = &glUniform3uiNULL; - uniform3uiv = &glUniform3uivNULL; - uniform4ui = &glUniform4uiNULL; - uniform4uiv = &glUniform4uivNULL; - uniformBlockBinding = &glUniformBlockBindingNULL; - uniformMatrix2x3fv = &glUniformMatrix2x3fvNULL; - uniformMatrix2x4fv = &glUniformMatrix2x4fvNULL; - uniformMatrix3x2fv = &glUniformMatrix3x2fvNULL; - uniformMatrix3x4fv = &glUniformMatrix3x4fvNULL; - uniformMatrix4x2fv = &glUniformMatrix4x2fvNULL; - uniformMatrix4x3fv = &glUniformMatrix4x3fvNULL; - unmapBuffer = &glUnmapBufferNULL; - vertexAttribDivisor = &glVertexAttribDivisorNULL; - vertexAttribI4i = &glVertexAttribI4iNULL; - vertexAttribI4iv = &glVertexAttribI4ivNULL; - vertexAttribI4ui = &glVertexAttribI4uiNULL; - vertexAttribI4uiv = &glVertexAttribI4uivNULL; - vertexAttribIPointer = &glVertexAttribIPointerNULL; - waitSync = &glWaitSyncNULL; - } - - if (version >= gl::Version(3, 1)) - { - activeShaderProgram = &glActiveShaderProgramNULL; - bindImageTexture = &glBindImageTextureNULL; - bindProgramPipeline = &glBindProgramPipelineNULL; - bindVertexBuffer = &glBindVertexBufferNULL; - createShaderProgramv = &glCreateShaderProgramvNULL; - deleteProgramPipelines = &glDeleteProgramPipelinesNULL; - dispatchCompute = &glDispatchComputeNULL; - dispatchComputeIndirect = &glDispatchComputeIndirectNULL; - drawArraysIndirect = &glDrawArraysIndirectNULL; - drawElementsIndirect = &glDrawElementsIndirectNULL; - framebufferParameteri = &glFramebufferParameteriNULL; - genProgramPipelines = &glGenProgramPipelinesNULL; - getBooleani_v = &glGetBooleani_vNULL; - getFramebufferParameteriv = &glGetFramebufferParameterivNULL; - getMultisamplefv = &glGetMultisamplefvNULL; - getProgramInterfaceiv = &glGetProgramInterfaceivNULL; - getProgramPipelineInfoLog = &glGetProgramPipelineInfoLogNULL; - getProgramPipelineiv = &glGetProgramPipelineivNULL; - getProgramResourceIndex = &glGetProgramResourceIndexNULL; - getProgramResourceLocation = &glGetProgramResourceLocationNULL; - getProgramResourceName = &glGetProgramResourceNameNULL; - getProgramResourceiv = &glGetProgramResourceivNULL; - getTexLevelParameterfv = &glGetTexLevelParameterfvNULL; - getTexLevelParameteriv = &glGetTexLevelParameterivNULL; - isProgramPipeline = &glIsProgramPipelineNULL; - memoryBarrier = &glMemoryBarrierNULL; - memoryBarrierByRegion = &glMemoryBarrierByRegionNULL; - programUniform1f = &glProgramUniform1fNULL; - programUniform1fv = &glProgramUniform1fvNULL; - programUniform1i = &glProgramUniform1iNULL; - programUniform1iv = &glProgramUniform1ivNULL; - programUniform1ui = &glProgramUniform1uiNULL; - programUniform1uiv = &glProgramUniform1uivNULL; - programUniform2f = &glProgramUniform2fNULL; - programUniform2fv = &glProgramUniform2fvNULL; - programUniform2i = &glProgramUniform2iNULL; - programUniform2iv = &glProgramUniform2ivNULL; - programUniform2ui = &glProgramUniform2uiNULL; - programUniform2uiv = &glProgramUniform2uivNULL; - programUniform3f = &glProgramUniform3fNULL; - programUniform3fv = &glProgramUniform3fvNULL; - programUniform3i = &glProgramUniform3iNULL; - programUniform3iv = &glProgramUniform3ivNULL; - programUniform3ui = &glProgramUniform3uiNULL; - programUniform3uiv = &glProgramUniform3uivNULL; - programUniform4f = &glProgramUniform4fNULL; - programUniform4fv = &glProgramUniform4fvNULL; - programUniform4i = &glProgramUniform4iNULL; - programUniform4iv = &glProgramUniform4ivNULL; - programUniform4ui = &glProgramUniform4uiNULL; - programUniform4uiv = &glProgramUniform4uivNULL; - programUniformMatrix2fv = &glProgramUniformMatrix2fvNULL; - programUniformMatrix2x3fv = &glProgramUniformMatrix2x3fvNULL; - programUniformMatrix2x4fv = &glProgramUniformMatrix2x4fvNULL; - programUniformMatrix3fv = &glProgramUniformMatrix3fvNULL; - programUniformMatrix3x2fv = &glProgramUniformMatrix3x2fvNULL; - programUniformMatrix3x4fv = &glProgramUniformMatrix3x4fvNULL; - programUniformMatrix4fv = &glProgramUniformMatrix4fvNULL; - programUniformMatrix4x2fv = &glProgramUniformMatrix4x2fvNULL; - programUniformMatrix4x3fv = &glProgramUniformMatrix4x3fvNULL; - sampleMaski = &glSampleMaskiNULL; - texStorage2DMultisample = &glTexStorage2DMultisampleNULL; - useProgramStages = &glUseProgramStagesNULL; - validateProgramPipeline = &glValidateProgramPipelineNULL; - vertexAttribBinding = &glVertexAttribBindingNULL; - vertexAttribFormat = &glVertexAttribFormatNULL; - vertexAttribIFormat = &glVertexAttribIFormatNULL; - vertexBindingDivisor = &glVertexBindingDivisorNULL; - } - - if (version >= gl::Version(3, 2)) - { - blendBarrier = &glBlendBarrierNULL; - blendEquationSeparatei = &glBlendEquationSeparateiNULL; - blendEquationi = &glBlendEquationiNULL; - blendFuncSeparatei = &glBlendFuncSeparateiNULL; - blendFunci = &glBlendFunciNULL; - colorMaski = &glColorMaskiNULL; - copyImageSubData = &glCopyImageSubDataNULL; - debugMessageCallback = &glDebugMessageCallbackNULL; - debugMessageControl = &glDebugMessageControlNULL; - debugMessageInsert = &glDebugMessageInsertNULL; - disablei = &glDisableiNULL; - drawElementsBaseVertex = &glDrawElementsBaseVertexNULL; - drawElementsInstancedBaseVertex = &glDrawElementsInstancedBaseVertexNULL; - drawRangeElementsBaseVertex = &glDrawRangeElementsBaseVertexNULL; - enablei = &glEnableiNULL; - framebufferTexture = &glFramebufferTextureNULL; - getDebugMessageLog = &glGetDebugMessageLogNULL; - getGraphicsResetStatus = &glGetGraphicsResetStatusNULL; - getObjectLabel = &glGetObjectLabelNULL; - getObjectPtrLabel = &glGetObjectPtrLabelNULL; - getPointerv = &glGetPointervNULL; - getSamplerParameterIiv = &glGetSamplerParameterIivNULL; - getSamplerParameterIuiv = &glGetSamplerParameterIuivNULL; - getTexParameterIiv = &glGetTexParameterIivNULL; - getTexParameterIuiv = &glGetTexParameterIuivNULL; - getnUniformfv = &glGetnUniformfvNULL; - getnUniformiv = &glGetnUniformivNULL; - getnUniformuiv = &glGetnUniformuivNULL; - isEnabledi = &glIsEnablediNULL; - minSampleShading = &glMinSampleShadingNULL; - objectLabel = &glObjectLabelNULL; - objectPtrLabel = &glObjectPtrLabelNULL; - patchParameteri = &glPatchParameteriNULL; - popDebugGroup = &glPopDebugGroupNULL; - primitiveBoundingBox = &glPrimitiveBoundingBoxNULL; - pushDebugGroup = &glPushDebugGroupNULL; - readnPixels = &glReadnPixelsNULL; - samplerParameterIiv = &glSamplerParameterIivNULL; - samplerParameterIuiv = &glSamplerParameterIuivNULL; - texBuffer = &glTexBufferNULL; - texBufferRange = &glTexBufferRangeNULL; - texParameterIiv = &glTexParameterIivNULL; - texParameterIuiv = &glTexParameterIuivNULL; - texStorage3DMultisample = &glTexStorage3DMultisampleNULL; - } -} - -void DispatchTableGL::initProcsSharedExtensionsNULL(const std::set &extensions) -{ - if (extensions.count("GL_EXT_debug_label") != 0) - { - getObjectLabel = &glGetObjectLabelNULL; - } - - if (extensions.count("GL_EXT_debug_marker") != 0) - { - insertEventMarkerEXT = &glInsertEventMarkerEXTNULL; - popGroupMarkerEXT = &glPopGroupMarkerEXTNULL; - pushGroupMarkerEXT = &glPushGroupMarkerEXTNULL; - } - - if (extensions.count("GL_EXT_draw_instanced") != 0) - { - drawArraysInstanced = &glDrawArraysInstancedNULL; - drawElementsInstanced = &glDrawElementsInstancedNULL; - } - - if (extensions.count("GL_EXT_memory_object") != 0) - { - bufferStorageMemEXT = &glBufferStorageMemEXTNULL; - createMemoryObjectsEXT = &glCreateMemoryObjectsEXTNULL; - deleteMemoryObjectsEXT = &glDeleteMemoryObjectsEXTNULL; - getMemoryObjectParameterivEXT = &glGetMemoryObjectParameterivEXTNULL; - getUnsignedBytei_vEXT = &glGetUnsignedBytei_vEXTNULL; - getUnsignedBytevEXT = &glGetUnsignedBytevEXTNULL; - isMemoryObjectEXT = &glIsMemoryObjectEXTNULL; - memoryObjectParameterivEXT = &glMemoryObjectParameterivEXTNULL; - namedBufferStorageMemEXT = &glNamedBufferStorageMemEXTNULL; - texStorageMem2DEXT = &glTexStorageMem2DEXTNULL; - texStorageMem2DMultisampleEXT = &glTexStorageMem2DMultisampleEXTNULL; - texStorageMem3DEXT = &glTexStorageMem3DEXTNULL; - texStorageMem3DMultisampleEXT = &glTexStorageMem3DMultisampleEXTNULL; - textureStorageMem2DEXT = &glTextureStorageMem2DEXTNULL; - textureStorageMem2DMultisampleEXT = &glTextureStorageMem2DMultisampleEXTNULL; - textureStorageMem3DEXT = &glTextureStorageMem3DEXTNULL; - textureStorageMem3DMultisampleEXT = &glTextureStorageMem3DMultisampleEXTNULL; - } - - if (extensions.count("GL_EXT_memory_object_fd") != 0) - { - importMemoryFdEXT = &glImportMemoryFdEXTNULL; - } - - if (extensions.count("GL_EXT_memory_object_win32") != 0) - { - importMemoryWin32HandleEXT = &glImportMemoryWin32HandleEXTNULL; - importMemoryWin32NameEXT = &glImportMemoryWin32NameEXTNULL; - } - - if (extensions.count("GL_EXT_multi_draw_arrays") != 0) - { - multiDrawArrays = &glMultiDrawArraysNULL; - multiDrawElements = &glMultiDrawElementsNULL; - } - - if (extensions.count("GL_EXT_polygon_offset_clamp") != 0) - { - polygonOffsetClampEXT = &glPolygonOffsetClampEXTNULL; - } - - if (extensions.count("GL_EXT_semaphore") != 0) - { - deleteSemaphoresEXT = &glDeleteSemaphoresEXTNULL; - genSemaphoresEXT = &glGenSemaphoresEXTNULL; - getSemaphoreParameterui64vEXT = &glGetSemaphoreParameterui64vEXTNULL; - getUnsignedBytei_vEXT = &glGetUnsignedBytei_vEXTNULL; - getUnsignedBytevEXT = &glGetUnsignedBytevEXTNULL; - isSemaphoreEXT = &glIsSemaphoreEXTNULL; - semaphoreParameterui64vEXT = &glSemaphoreParameterui64vEXTNULL; - signalSemaphoreEXT = &glSignalSemaphoreEXTNULL; - waitSemaphoreEXT = &glWaitSemaphoreEXTNULL; - } - - if (extensions.count("GL_EXT_semaphore_fd") != 0) - { - importSemaphoreFdEXT = &glImportSemaphoreFdEXTNULL; - } - - if (extensions.count("GL_EXT_semaphore_win32") != 0) - { - importSemaphoreWin32HandleEXT = &glImportSemaphoreWin32HandleEXTNULL; - importSemaphoreWin32NameEXT = &glImportSemaphoreWin32NameEXTNULL; - } - - if (extensions.count("GL_EXT_shader_framebuffer_fetch_non_coherent") != 0) - { - framebufferFetchBarrierEXT = &glFramebufferFetchBarrierEXTNULL; - } - - if (extensions.count("GL_EXT_texture_storage") != 0) - { - texStorage1D = &glTexStorage1DNULL; - texStorage2D = &glTexStorage2DNULL; - texStorage3D = &glTexStorage3DNULL; - textureStorage1D = &glTextureStorage1DNULL; - textureStorage2D = &glTextureStorage2DNULL; - textureStorage3D = &glTextureStorage3DNULL; - } - - if (extensions.count("GL_KHR_blend_equation_advanced") != 0) - { - blendBarrier = &glBlendBarrierNULL; - } - - if (extensions.count("GL_KHR_parallel_shader_compile") != 0) - { - maxShaderCompilerThreadsKHR = &glMaxShaderCompilerThreadsKHRNULL; - } - - if (extensions.count("GL_MESA_framebuffer_flip_y") != 0) - { - framebufferParameteriMESA = &glFramebufferParameteriMESANULL; - } - - if (extensions.count("GL_NV_fence") != 0) - { - deleteFencesNV = &glDeleteFencesNVNULL; - finishFenceNV = &glFinishFenceNVNULL; - genFencesNV = &glGenFencesNVNULL; - getFenceivNV = &glGetFenceivNVNULL; - isFenceNV = &glIsFenceNVNULL; - setFenceNV = &glSetFenceNVNULL; - testFenceNV = &glTestFenceNVNULL; - } - - if (extensions.count("GL_NV_framebuffer_mixed_samples") != 0) - { - coverageModulationNV = &glCoverageModulationNVNULL; - } - - if (extensions.count("GL_NV_internalformat_sample_query") != 0) - { - getInternalformatSampleivNV = &glGetInternalformatSampleivNVNULL; - } - - if (extensions.count("GL_OVR_multiview") != 0) - { - framebufferTextureMultiviewOVR = &glFramebufferTextureMultiviewOVRNULL; - } -} -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - } // namespace rx diff --git a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h index 2893f6a1b74..4b5c17c5695 100644 --- a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h +++ b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h @@ -827,8 +827,9 @@ class DispatchTableGL : angle::NonCopyable PFNGLTEXBUFFEROESPROC texBufferOES = nullptr; PFNGLTEXBUFFERRANGEOESPROC texBufferRangeOES = nullptr; - // GL_OVR_multiview2 + // GL_OVR_multiview PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC framebufferTextureMultiviewOVR = nullptr; + PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC namedFramebufferTextureMultiviewOVR = nullptr; // GL_QCOM_tiled_rendering PFNGLENDTILINGQCOMPROC endTilingQCOM = nullptr; @@ -844,13 +845,6 @@ class DispatchTableGL : angle::NonCopyable void initProcsDesktopGL(const gl::Version &version, const std::set &extensions); void initProcsGLES(const gl::Version &version, const std::set &extensions); void initProcsSharedExtensions(const std::set &extensions); - -#if defined(ANGLE_ENABLE_OPENGL_NULL) - void initProcsDesktopGLNULL(const gl::Version &version, - const std::set &extensions); - void initProcsGLESNULL(const gl::Version &version, const std::set &extensions); - void initProcsSharedExtensionsNULL(const std::set &extensions); -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) }; } // namespace rx diff --git a/src/libANGLE/renderer/gl/DisplayGL.cpp b/src/libANGLE/renderer/gl/DisplayGL.cpp index 1b17bffd727..e8aa88eb377 100644 --- a/src/libANGLE/renderer/gl/DisplayGL.cpp +++ b/src/libANGLE/renderer/gl/DisplayGL.cpp @@ -163,6 +163,10 @@ void DisplayGL::generateExtensions(egl::DisplayExtensions *outExtensions) const // Advertise robust resource initialization on all OpenGL backends for testing even though it is // not fully implemented. outExtensions->robustResourceInitializationANGLE = true; + + outExtensions->createContextPassthroughShadersANGLE = + !getRenderer()->getFeatures().disablePassthroughShaders.enabled && + getRenderer()->getFunctions()->standard == STANDARD_GL_ES; } egl::Error DisplayGL::makeCurrentSurfaceless(gl::Context *context) diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp index 83741858925..ecea51f64e2 100644 --- a/src/libANGLE/renderer/gl/FramebufferGL.cpp +++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // FramebufferGL.cpp: Implements the class methods for FramebufferGL. #include "libANGLE/renderer/gl/FramebufferGL.h" @@ -93,6 +97,9 @@ void BindFramebufferAttachment(const FunctionsGL *functions, { if (attachment->isRenderToTexture()) { + // GL_OVR_multiview_multisampled_render_to_texture is not supported on GL + // backend + ASSERT(!attachment->isMultiview()); if (functions->framebufferTexture2DMultisampleEXT) { functions->framebufferTexture2DMultisampleEXT( @@ -139,6 +146,9 @@ void BindFramebufferAttachment(const FunctionsGL *functions, { if (attachment->isMultiview()) { + // GL_OVR_multiview_multisampled_render_to_texture is not supported on GL + // backend + ASSERT(!attachment->isRenderToTexture()); ASSERT(functions->framebufferTexture); functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(), @@ -208,6 +218,8 @@ bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabl { return false; } + // GL_OVR_multiview_multisampled_render_to_texture is not supported on GL backend + ASSERT(!colorAttachment.isRenderToTexture()); attachment = &colorAttachment; allTextureArraysAreFullyAttached = allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment); @@ -221,6 +233,8 @@ bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabl { return false; } + // GL_OVR_multiview_multisampled_render_to_texture is not supported on GL backend + ASSERT(!depthAttachment->isRenderToTexture()); attachment = depthAttachment; allTextureArraysAreFullyAttached = allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment); @@ -232,6 +246,8 @@ bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabl { return false; } + // GL_OVR_multiview_multisampled_render_to_texture is not supported on GL backend + ASSERT(!stencilAttachment->isRenderToTexture()); attachment = stencilAttachment; allTextureArraysAreFullyAttached = allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment); diff --git a/src/libANGLE/renderer/gl/FunctionsGL.cpp b/src/libANGLE/renderer/gl/FunctionsGL.cpp index 9d8c7a4f4be..c85ef6270cb 100644 --- a/src/libANGLE/renderer/gl/FunctionsGL.cpp +++ b/src/libANGLE/renderer/gl/FunctionsGL.cpp @@ -30,14 +30,16 @@ static void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, // number.minor number.release number, where the numbers all have one or more // digits *outStandard = STANDARD_GL_DESKTOP; - *outVersion = gl::Version(version[0] - '0', version[2] - '0'); + *outVersion = gl::Version(static_cast(version[0] - '0'), + static_cast(version[2] - '0')); } else { // ES spec states that the GL_VERSION string will be in the following format: // "OpenGL ES N.M vendor-specific information" *outStandard = STANDARD_GL_ES; - *outVersion = gl::Version(version[10] - '0', version[12] - '0'); + *outVersion = gl::Version(static_cast(version[10] - '0'), + static_cast(version[12] - '0')); } } @@ -59,40 +61,6 @@ static std::vector GetIndexedExtensions(PFNGLGETINTEGERVPROC getInt return result; } -#if defined(ANGLE_ENABLE_OPENGL_NULL) -static GLenum INTERNAL_GL_APIENTRY StubCheckFramebufferStatus(GLenum) -{ - return GL_FRAMEBUFFER_COMPLETE; -} - -static void INTERNAL_GL_APIENTRY StubGetProgramiv(GLuint program, GLenum pname, GLint *params) -{ - switch (pname) - { - case GL_LINK_STATUS: - *params = GL_TRUE; - break; - case GL_VALIDATE_STATUS: - *params = GL_TRUE; - break; - default: - break; - } -} - -static void INTERNAL_GL_APIENTRY StubGetShaderiv(GLuint program, GLenum pname, GLint *params) -{ - switch (pname) - { - case GL_COMPILE_STATUS: - *params = GL_TRUE; - break; - default: - break; - } -} -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - #define ASSIGN(NAME, FP) FP = reinterpret_cast(loadProcAddress(NAME)) FunctionsGL::FunctionsGL() : version(), standard(), extensions() {} @@ -131,11 +99,6 @@ void FunctionsGL::initialize(const egl::AttributeMap &displayAttributes) // Load the entry points -#if defined(ANGLE_ENABLE_OPENGL_NULL) - EGLint deviceType = - static_cast(displayAttributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_NONE)); -#endif // defined(ANGLE_ENABLE_GL_NULL) - switch (standard) { case STANDARD_GL_DESKTOP: @@ -147,19 +110,10 @@ void FunctionsGL::initialize(const egl::AttributeMap &displayAttributes) getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); } -#if defined(ANGLE_ENABLE_OPENGL_NULL) - if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE) - { - initProcsDesktopGLNULL(version, extensionSet); - } - else -#endif // defined(ANGLE_ENABLE_GL_NULL) - { - initProcsDesktopGL(version, extensionSet); - // Test that ANGLE_ENABLE_GL_DESKTOP_BACKEND has been enabled - // See http://anglebug.com/42266631 - ASSERT(getString != nullptr && getError != nullptr); - } + initProcsDesktopGL(version, extensionSet); + // Test that ANGLE_ENABLE_GL_DESKTOP_BACKEND has been enabled + // See http://anglebug.com/42266631 + ASSERT(getString != nullptr && getError != nullptr); break; } @@ -167,17 +121,7 @@ void FunctionsGL::initialize(const egl::AttributeMap &displayAttributes) { // No profiles in GLES profile = 0; - -#if defined(ANGLE_ENABLE_OPENGL_NULL) - if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE) - { - initProcsGLESNULL(version, extensionSet); - } - else -#endif // defined(ANGLE_ENABLE_GL_NULL) - { - initProcsGLES(version, extensionSet); - } + initProcsGLES(version, extensionSet); break; } @@ -186,17 +130,7 @@ void FunctionsGL::initialize(const egl::AttributeMap &displayAttributes) break; } -#if defined(ANGLE_ENABLE_OPENGL_NULL) - if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE) - { - initProcsSharedExtensionsNULL(extensionSet); - initializeStubFunctionsForNULLDriver(extensionSet); - } - else -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - { - initProcsSharedExtensions(extensionSet); - } + initProcsSharedExtensions(extensionSet); } bool FunctionsGL::isAtLeastGL(const gl::Version &glVersion) const @@ -233,41 +167,4 @@ bool FunctionsGL::hasGLESExtension(const std::string &ext) const { return standard == STANDARD_GL_ES && hasExtension(ext); } - -#if defined(ANGLE_ENABLE_OPENGL_NULL) -void FunctionsGL::initializeStubFunctionsForNULLDriver(const std::set &extensionSet) -{ - // This is a quick hack to get the NULL driver working, but we might want to implement a true - // NULL/stub driver that never calls into the OS. See Chromium's implementation in - // ui/gl/gl_stub_api.cc. This might be useful for testing things like perf scaling due to - // the caps returned by the drivers (i.e. number of texture units) or a true NULL back-end - // that could be used in a VM for things like fuzzing. - // TODO(jmadill): Implement true no-op/stub back-end. - ASSIGN("glGetString", getString); - ASSIGN("glGetStringi", getStringi); - ASSIGN("glGetIntegerv", getIntegerv); - ASSIGN("glGetIntegeri_v", getIntegeri_v); - - getProgramiv = &StubGetProgramiv; - getShaderiv = &StubGetShaderiv; - checkFramebufferStatus = &StubCheckFramebufferStatus; - - if (isAtLeastGLES(gl::Version(3, 0)) || isAtLeastGL(gl::Version(4, 2)) || - extensionSet.count("GL_ARB_internalformat_query") > 0) - { - ASSIGN("glGetInternalformativ", getInternalformativ); - } - - if (isAtLeastGL(gl::Version(4, 3))) - { - ASSIGN("glGetInternalformati64v", getInternalformati64v); - } - - if (extensionSet.count("GL_NV_internalformat_sample_query") > 0) - { - ASSIGN("glGetInternalformatSampleivNV", getInternalformatSampleivNV); - } -} -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - } // namespace rx diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp index b6fc85313f5..a708b7ede22 100644 --- a/src/libANGLE/renderer/gl/ProgramGL.cpp +++ b/src/libANGLE/renderer/gl/ProgramGL.cpp @@ -6,6 +6,10 @@ // ProgramGL.cpp: Implements the class methods for ProgramGL. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/ProgramGL.h" #include "common/WorkerThread.h" @@ -89,6 +93,17 @@ std::string GetTransformFeedbackVaryingMappedName(const gl::SharedCompiledShader return std::string(); } +std::string TrimArraySuffix(const char *inputName, size_t nameLen) +{ + std::string name(inputName, nameLen); + size_t open = name.find_last_of('['); + if (open != std::string::npos && name.back() == ']') + { + name = name.substr(0, open); + } + return name; +} + } // anonymous namespace class ProgramGL::LinkTaskGL final : public LinkTask @@ -98,12 +113,14 @@ class ProgramGL::LinkTaskGL final : public LinkTask bool hasNativeParallelCompile, const FunctionsGL *functions, const gl::Extensions &extensions, - GLuint programID) + GLuint programID, + bool passthroughShaders) : mProgram(program), mHasNativeParallelCompile(hasNativeParallelCompile), mFunctions(functions), mExtensions(extensions), - mProgramID(programID) + mProgramID(programID), + mPassthroughShaders(passthroughShaders) {} ~LinkTaskGL() override = default; @@ -115,7 +132,14 @@ class ProgramGL::LinkTaskGL final : public LinkTask ASSERT(linkSubTasksOut && linkSubTasksOut->empty()); ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty()); - mResult = mProgram->linkJobImpl(mExtensions); + if (mPassthroughShaders) + { + mResult = mProgram->passthroughLinkJobImpl(mExtensions); + } + else + { + mResult = mProgram->linkJobImpl(mExtensions); + } // If there is no native parallel compile, do the post-link right away. if (mResult == angle::Result::Continue && !mHasNativeParallelCompile) @@ -156,6 +180,7 @@ class ProgramGL::LinkTaskGL final : public LinkTask const FunctionsGL *mFunctions; const gl::Extensions &mExtensions; const GLuint mProgramID; + const bool mPassthroughShaders; angle::Result mResult = angle::Result::Continue; @@ -201,11 +226,11 @@ angle::Result ProgramGL::load(const gl::Context *context, // Read the binary format, size and blob GLenum binaryFormat = stream->readInt(); GLint binaryLength = stream->readInt(); - const uint8_t *binary = stream->data() + stream->offset(); + angle::Span binary = stream->remainingSpan().first(binaryLength); stream->skip(binaryLength); // Load the binary - mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength); + mFunctions->programBinary(mProgramID, binaryFormat, binary.data(), binaryLength); // Verify that the program linked. Ensure failure if program binary is intentionally corrupted, // even if the corruption didn't really cause a failure. @@ -245,7 +270,7 @@ void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream) ++binary[0]; } - stream->writeBytes(binary.data(), binaryLength); + stream->writeBytes(angle::as_byte_span(binary).first(binaryLength)); // Re-apply UBO bindings to work around driver bugs. if (features.reapplyUBOBindingsAfterUsingBinaryProgram.enabled) @@ -283,75 +308,141 @@ void ProgramGL::prepareForLink(const gl::ShaderMap &shaders) } } -angle::Result ProgramGL::link(const gl::Context *context, std::shared_ptr *linkTaskOut) +void ProgramGL::prepareForPassthroughLink( + gl::ShaderMap *outAttachedShaders) { - ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::link"); + ASSERT(mAttachedShaders[gl::ShaderType::Compute] == 0); - *linkTaskOut = std::make_shared(this, mRenderer->hasNativeParallelCompile(), - mFunctions, context->getExtensions(), mProgramID); + attachShaders(); + applyTransformFeedbackState(); - return angle::Result::Continue; -} + // Bind only the attribute locations that the frontend requested. Automatically assigned + // locations are queried after link and given back to the frontend. + for (const auto &attributeBinding : mState.getAttributeBindings()) + { + mFunctions->bindAttribLocation(mProgramID, attributeBinding.second, + attributeBinding.first.c_str()); + } -angle::Result ProgramGL::linkJobImpl(const gl::Extensions &extensions) -{ - ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::linkJobImpl"); - const gl::ProgramExecutable &executable = mState.getExecutable(); - ProgramExecutableGL *executableGL = getExecutable(); + mFunctions->linkProgram(mProgramID); - if (mAttachedShaders[gl::ShaderType::Compute] != 0) + if (!checkLinkStatus()) { - mFunctions->attachShader(mProgramID, mAttachedShaders[gl::ShaderType::Compute]); + return; } - else + + // Gather the uniforms from the linked program. We can't distinguish if they are from the + // fragment or vertex shader so set all the uniforms on both stages. + std::vector uniforms; { - // Set the transform feedback state - std::vector transformFeedbackVaryingMappedNames; - const gl::ShaderType tfShaderType = - executable.hasLinkedShaderStage(gl::ShaderType::Geometry) ? gl::ShaderType::Geometry - : gl::ShaderType::Vertex; - const gl::SharedCompiledShaderState &tfShaderState = mState.getAttachedShader(tfShaderType); - for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames()) - { - std::string tfVaryingMappedName = - GetTransformFeedbackVaryingMappedName(tfShaderState, tfVarying); - transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName); - } + GLint numUniforms = 0; + mFunctions->getProgramiv(mProgramID, GL_ACTIVE_UNIFORMS, &numUniforms); - if (transformFeedbackVaryingMappedNames.empty()) - { - // Only clear the transform feedback state if transform feedback varyings have already - // been set. - if (executableGL->mHasAppliedTransformFeedbackVaryings) - { - ASSERT(mFunctions->transformFeedbackVaryings); - mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr, - mState.getTransformFeedbackBufferMode()); - executableGL->mHasAppliedTransformFeedbackVaryings = false; - } - } - else + GLint activeUniformMaxLength = 0; + mFunctions->getProgramiv(mProgramID, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength); + + std::vector uniformNameBuf(activeUniformMaxLength, 0); + for (GLint uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) { - ASSERT(mFunctions->transformFeedbackVaryings); - std::vector transformFeedbackVaryings; - for (const auto &varying : transformFeedbackVaryingMappedNames) + GLsizei length = 0; + GLint size = 0; + GLenum type = GL_NONE; + mFunctions->getActiveUniform(mProgramID, uniformIndex, activeUniformMaxLength, &length, + &size, &type, uniformNameBuf.data()); + + std::string name = TrimArraySuffix(uniformNameBuf.data(), length); + + sh::ShaderVariable uniform(type); + uniform.precision = GL_HIGH_FLOAT; + uniform.name = name; + uniform.mappedName = std::move(name); + uniform.staticUse = true; + uniform.active = true; + if (size > 1) { - transformFeedbackVaryings.push_back(varying.c_str()); + uniform.setArraySize(size); } - mFunctions->transformFeedbackVaryings( - mProgramID, static_cast(transformFeedbackVaryingMappedNames.size()), - &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode()); - executableGL->mHasAppliedTransformFeedbackVaryings = true; + + uniforms.push_back(std::move(uniform)); } + } - for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes) + // Reflect the attribute information from the linked program. + { + gl::SharedCompiledShaderState originalVertexState = + mState.getAttachedShader(gl::ShaderType::Vertex); + gl::SharedCompiledShaderState vertexState = + std::make_shared(*originalVertexState.get()); + + GLint numAttributes = 0; + mFunctions->getProgramiv(mProgramID, GL_ACTIVE_ATTRIBUTES, &numAttributes); + + GLint activeAttributeMaxLength = 0; + mFunctions->getProgramiv(mProgramID, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, + &activeAttributeMaxLength); + + std::vector attribNameBuf(activeAttributeMaxLength, 0); + for (GLint attribIndex = 0; attribIndex < numAttributes; attribIndex++) { - if (mAttachedShaders[shaderType] != 0) - { - mFunctions->attachShader(mProgramID, mAttachedShaders[shaderType]); - } + GLsizei length = 0; + GLint size = 0; + GLenum type = GL_NONE; + mFunctions->getActiveAttrib(mProgramID, attribIndex, activeAttributeMaxLength, &length, + &size, &type, attribNameBuf.data()); + + sh::ShaderVariable attribute(type); + attribute.precision = GL_HIGH_FLOAT; + attribute.name = std::string(attribNameBuf.data(), length); + attribute.mappedName = attribute.name; + attribute.staticUse = true; + attribute.active = true; + attribute.location = mFunctions->getAttribLocation(mProgramID, attribNameBuf.data()); + attribute.hasImplicitLocation = false; + + vertexState->allAttributes.push_back(attribute); + vertexState->activeAttributes.push_back(std::move(attribute)); } + vertexState->uniforms = uniforms; + + (*outAttachedShaders)[gl::ShaderType::Vertex] = vertexState; + } + + // Outputs are not reflectable from a linked program with only ES2/3. + { + gl::SharedCompiledShaderState originalFragmentState = + mState.getAttachedShader(gl::ShaderType::Fragment); + gl::SharedCompiledShaderState fragmentState = + std::make_shared(*originalFragmentState.get()); + + fragmentState->uniforms = std::move(uniforms); + + (*outAttachedShaders)[gl::ShaderType::Fragment] = fragmentState; + } +} + +angle::Result ProgramGL::link(const gl::Context *context, std::shared_ptr *linkTaskOut) +{ + ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::link"); + + *linkTaskOut = std::make_shared(this, mRenderer->hasNativeParallelCompile(), + mFunctions, context->getExtensions(), mProgramID, + context->getState().usesPassthroughShaders()); + + return angle::Result::Continue; +} + +angle::Result ProgramGL::linkJobImpl(const gl::Extensions &extensions) +{ + ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::linkJobImpl"); + const gl::ProgramExecutable &executable = mState.getExecutable(); + + attachShaders(); + + if (mAttachedShaders[gl::ShaderType::Compute] == 0) + { + applyTransformFeedbackState(); + // Bind attribute locations to match the GL layer. for (const gl::ProgramInput &attribute : executable.getProgramInputs()) { @@ -516,6 +607,74 @@ angle::Result ProgramGL::postLinkJobImpl(const gl::ProgramLinkedResources &resou return angle::Result::Continue; } +angle::Result ProgramGL::passthroughLinkJobImpl(const gl::Extensions &extensions) +{ + ASSERT(!extensions.blendFuncExtendedEXT); + return angle::Result::Continue; +} + +void ProgramGL::attachShaders() +{ + if (mAttachedShaders[gl::ShaderType::Compute] != 0) + { + mFunctions->attachShader(mProgramID, mAttachedShaders[gl::ShaderType::Compute]); + } + else + { + for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes) + { + if (mAttachedShaders[shaderType] != 0) + { + mFunctions->attachShader(mProgramID, mAttachedShaders[shaderType]); + } + } + } +} + +void ProgramGL::applyTransformFeedbackState() +{ + const gl::ProgramExecutable &executable = mState.getExecutable(); + ProgramExecutableGL *executableGL = getExecutable(); + + std::vector transformFeedbackVaryingMappedNames; + const gl::ShaderType tfShaderType = executable.hasLinkedShaderStage(gl::ShaderType::Geometry) + ? gl::ShaderType::Geometry + : gl::ShaderType::Vertex; + const gl::SharedCompiledShaderState &tfShaderState = mState.getAttachedShader(tfShaderType); + for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames()) + { + std::string tfVaryingMappedName = + GetTransformFeedbackVaryingMappedName(tfShaderState, tfVarying); + transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName); + } + + if (transformFeedbackVaryingMappedNames.empty()) + { + // Only clear the transform feedback state if transform feedback varyings have already + // been set. + if (executableGL->mHasAppliedTransformFeedbackVaryings) + { + ASSERT(mFunctions->transformFeedbackVaryings); + mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr, + mState.getTransformFeedbackBufferMode()); + executableGL->mHasAppliedTransformFeedbackVaryings = false; + } + } + else + { + ASSERT(mFunctions->transformFeedbackVaryings); + std::vector transformFeedbackVaryings; + for (const auto &varying : transformFeedbackVaryingMappedNames) + { + transformFeedbackVaryings.push_back(varying.c_str()); + } + mFunctions->transformFeedbackVaryings( + mProgramID, static_cast(transformFeedbackVaryingMappedNames.size()), + &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode()); + executableGL->mHasAppliedTransformFeedbackVaryings = true; + } +} + GLboolean ProgramGL::validate(const gl::Caps & /*caps*/) { // TODO(jmadill): implement validate diff --git a/src/libANGLE/renderer/gl/ProgramGL.h b/src/libANGLE/renderer/gl/ProgramGL.h index 7d0911a20c8..a788d476344 100644 --- a/src/libANGLE/renderer/gl/ProgramGL.h +++ b/src/libANGLE/renderer/gl/ProgramGL.h @@ -48,6 +48,8 @@ class ProgramGL : public ProgramImpl void setSeparable(bool separable) override; void prepareForLink(const gl::ShaderMap &shaders) override; + void prepareForPassthroughLink( + gl::ShaderMap *outAttachedShaders) override; angle::Result link(const gl::Context *contextImpl, std::shared_ptr *linkTaskOut) override; GLboolean validate(const gl::Caps &caps) override; @@ -76,9 +78,13 @@ class ProgramGL : public ProgramImpl friend class LinkTaskGL; friend class PostLinkGL; + angle::Result passthroughLinkJobImpl(const gl::Extensions &extensions); angle::Result linkJobImpl(const gl::Extensions &extensions); angle::Result postLinkJobImpl(const gl::ProgramLinkedResources &resources); + void attachShaders(); + void applyTransformFeedbackState(); + bool checkLinkStatus(); bool getUniformBlockSize(const std::string &blockName, diff --git a/src/libANGLE/renderer/gl/QueryGL.cpp b/src/libANGLE/renderer/gl/QueryGL.cpp index 6baaca31f5f..fbd3613fe4f 100644 --- a/src/libANGLE/renderer/gl/QueryGL.cpp +++ b/src/libANGLE/renderer/gl/QueryGL.cpp @@ -233,200 +233,4 @@ angle::Result StandardQueryGL::flush(const gl::Context *context, bool force) return angle::Result::Continue; } - -class SyncProviderGL -{ - public: - virtual ~SyncProviderGL() {} - virtual angle::Result init(const gl::Context *context, gl::QueryType queryType) - { - return angle::Result::Continue; - } - virtual angle::Result flush(const gl::Context *context, bool force, bool *finished) = 0; -}; - -class SyncProviderGLSync : public SyncProviderGL -{ - public: - SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr) {} - - ~SyncProviderGLSync() override { mFunctions->deleteSync(mSync); } - - angle::Result init(const gl::Context *context, gl::QueryType type) override - { - ContextGL *contextGL = GetImplAs(context); - mSync = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - ANGLE_CHECK(contextGL, mSync != 0, "glFenceSync failed to create a GLsync object.", - GL_OUT_OF_MEMORY); - contextGL->markWorkSubmitted(); - return angle::Result::Continue; - } - - angle::Result flush(const gl::Context *context, bool force, bool *finished) override - { - if (force) - { - mFunctions->clientWaitSync(mSync, 0, 0); - *finished = true; - } - else - { - GLint value = 0; - mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value); - *finished = (value == GL_SIGNALED); - } - - return angle::Result::Continue; - } - - private: - const FunctionsGL *mFunctions; - GLsync mSync; -}; - -class SyncProviderGLQuery : public SyncProviderGL -{ - public: - SyncProviderGLQuery(const FunctionsGL *functions) : mFunctions(functions), mQuery(0) {} - - angle::Result init(const gl::Context *context, gl::QueryType type) override - { - StateManagerGL *stateManager = GetStateManagerGL(context); - - mFunctions->genQueries(1, &mQuery); - ANGLE_TRY(stateManager->pauseQuery(context, type)); - mFunctions->beginQuery(ToGLenum(type), mQuery); - mFunctions->endQuery(ToGLenum(type)); - return stateManager->resumeQuery(context, type); - } - - ~SyncProviderGLQuery() override { mFunctions->deleteQueries(1, &mQuery); } - - angle::Result flush(const gl::Context *context, bool force, bool *finished) override - { - if (force) - { - GLint result = 0; - mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result); - *finished = true; - } - else - { - GLint available = 0; - mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available); - *finished = (available == GL_TRUE); - } - - return angle::Result::Continue; - } - - private: - const FunctionsGL *mFunctions; - GLuint mQuery; -}; - -SyncQueryGL::SyncQueryGL(gl::QueryType type, const FunctionsGL *functions) - : QueryGL(type), mFunctions(functions), mSyncProvider(nullptr), mFinished(false) -{ - ASSERT(IsSupported(mFunctions)); - ASSERT(type == gl::QueryType::CommandsCompleted); -} - -SyncQueryGL::~SyncQueryGL() {} - -bool SyncQueryGL::IsSupported(const FunctionsGL *functions) -{ - return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions); -} - -angle::Result SyncQueryGL::begin(const gl::Context *context) -{ - return angle::Result::Continue; -} - -angle::Result SyncQueryGL::end(const gl::Context *context) -{ - if (nativegl::SupportsFenceSync(mFunctions)) - { - mSyncProvider.reset(new SyncProviderGLSync(mFunctions)); - } - else if (nativegl::SupportsOcclusionQueries(mFunctions)) - { - mSyncProvider.reset(new SyncProviderGLQuery(mFunctions)); - } - else - { - ANGLE_GL_UNREACHABLE(GetImplAs(context)); - } - ANGLE_TRY(mSyncProvider->init(context, gl::QueryType::AnySamples)); - return angle::Result::Continue; -} - -angle::Result SyncQueryGL::queryCounter(const gl::Context *context) -{ - UNREACHABLE(); - return angle::Result::Continue; -} - -angle::Result SyncQueryGL::getResult(const gl::Context *context, GLint *params) -{ - return getResultBase(context, params); -} - -angle::Result SyncQueryGL::getResult(const gl::Context *context, GLuint *params) -{ - return getResultBase(context, params); -} - -angle::Result SyncQueryGL::getResult(const gl::Context *context, GLint64 *params) -{ - return getResultBase(context, params); -} - -angle::Result SyncQueryGL::getResult(const gl::Context *context, GLuint64 *params) -{ - return getResultBase(context, params); -} - -angle::Result SyncQueryGL::isResultAvailable(const gl::Context *context, bool *available) -{ - ANGLE_TRY(flush(context, false)); - *available = mFinished; - return angle::Result::Continue; -} - -angle::Result SyncQueryGL::pause(const gl::Context *context) -{ - return angle::Result::Continue; -} - -angle::Result SyncQueryGL::resume(const gl::Context *context) -{ - return angle::Result::Continue; -} - -angle::Result SyncQueryGL::flush(const gl::Context *context, bool force) -{ - if (mSyncProvider == nullptr) - { - ASSERT(mFinished); - return angle::Result::Continue; - } - - ANGLE_TRY(mSyncProvider->flush(context, force, &mFinished)); - if (mFinished) - { - mSyncProvider.reset(); - } - - return angle::Result::Continue; -} - -template -angle::Result SyncQueryGL::getResultBase(const gl::Context *context, T *params) -{ - ANGLE_TRY(flush(context, true)); - *params = static_cast(mFinished ? GL_TRUE : GL_FALSE); - return angle::Result::Continue; -} } // namespace rx diff --git a/src/libANGLE/renderer/gl/QueryGL.h b/src/libANGLE/renderer/gl/QueryGL.h index fe02cef2b54..43ceb3f1fc3 100644 --- a/src/libANGLE/renderer/gl/QueryGL.h +++ b/src/libANGLE/renderer/gl/QueryGL.h @@ -67,39 +67,6 @@ class StandardQueryGL : public QueryGL std::deque mPendingQueries; GLuint64 mResultSum; }; - -class SyncProviderGL; -class SyncQueryGL : public QueryGL -{ - public: - SyncQueryGL(gl::QueryType type, const FunctionsGL *functions); - ~SyncQueryGL() override; - - static bool IsSupported(const FunctionsGL *functions); - - angle::Result begin(const gl::Context *context) override; - angle::Result end(const gl::Context *context) override; - angle::Result queryCounter(const gl::Context *context) override; - angle::Result getResult(const gl::Context *context, GLint *params) override; - angle::Result getResult(const gl::Context *context, GLuint *params) override; - angle::Result getResult(const gl::Context *context, GLint64 *params) override; - angle::Result getResult(const gl::Context *context, GLuint64 *params) override; - angle::Result isResultAvailable(const gl::Context *context, bool *available) override; - - angle::Result pause(const gl::Context *context) override; - angle::Result resume(const gl::Context *context) override; - - private: - angle::Result flush(const gl::Context *context, bool force); - - template - angle::Result getResultBase(const gl::Context *context, T *params); - - const FunctionsGL *mFunctions; - - std::unique_ptr mSyncProvider; - bool mFinished; -}; } // namespace rx #endif // LIBANGLE_RENDERER_GL_QUERYGL_H_ diff --git a/src/libANGLE/renderer/gl/RendererGL.cpp b/src/libANGLE/renderer/gl/RendererGL.cpp index c617812027b..6ad286c1e34 100644 --- a/src/libANGLE/renderer/gl/RendererGL.cpp +++ b/src/libANGLE/renderer/gl/RendererGL.cpp @@ -6,6 +6,10 @@ // RendererGL.cpp: Implements the class methods for RendererGL. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/gl/RendererGL.h" #include diff --git a/src/libANGLE/renderer/gl/ShaderGL.cpp b/src/libANGLE/renderer/gl/ShaderGL.cpp index c172223ee43..fac33fc2c9b 100644 --- a/src/libANGLE/renderer/gl/ShaderGL.cpp +++ b/src/libANGLE/renderer/gl/ShaderGL.cpp @@ -91,7 +91,7 @@ class ShaderTranslateTaskGL final : public ShaderTranslateTask private: void startCompile(const gl::CompiledShaderState &compiledState) { - const char *source = compiledState.translatedSource.c_str(); + const char *source = compiledState.translatedSource->c_str(); mFunctions->shaderSource(mShaderID, 1, &source, nullptr); mFunctions->compileShader(mShaderID); } @@ -124,11 +124,13 @@ std::shared_ptr ShaderGL::compile(const gl::Context *contex { ContextGL *contextGL = GetImplAs(context); const FunctionsGL *functions = GetFunctionsGL(context); + const angle::FeaturesGL &features = GetFeaturesGL(context); options->initGLPosition = true; bool isWebGL = context->isWebGL(); - if (isWebGL && mState.getShaderType() != gl::ShaderType::Compute) + if (isWebGL || (features.initFragmentOutputVariables.enabled && + mState.getShaderType() == gl::ShaderType::Fragment)) { options->initOutputVariables = true; } @@ -138,18 +140,6 @@ std::shared_ptr ShaderGL::compile(const gl::Context *contex options->disableARBTextureRectangle = true; } - const angle::FeaturesGL &features = GetFeaturesGL(context); - - if (features.initFragmentOutputVariables.enabled) - { - options->initFragmentOutputVariables = true; - } - - if (features.doWhileGLSLCausesGPUHang.enabled) - { - options->rewriteDoWhileLoops = true; - } - if (features.emulateAbsIntFunction.enabled) { options->emulateAbsIntFunction = true; @@ -160,11 +150,6 @@ std::shared_ptr ShaderGL::compile(const gl::Context *contex options->addAndTrueToLoopCondition = true; } - if (features.emulateIsnanFloat.enabled) - { - options->emulateIsnanFloatFunction = true; - } - if (features.emulateAtan2Float.enabled) { options->emulateAtan2FloatFunction = true; @@ -180,11 +165,6 @@ std::shared_ptr ShaderGL::compile(const gl::Context *contex options->removeInvariantAndCentroidForESSL3 = true; } - if (features.rewriteFloatUnaryMinusOperator.enabled) - { - options->rewriteFloatUnaryMinusOperator = true; - } - if (!features.dontInitializeUninitializedLocals.enabled) { options->initializeUninitializedLocals = true; @@ -303,7 +283,7 @@ std::shared_ptr ShaderGL::load(const gl::Context *context, std::string ShaderGL::getDebugInfo() const { - return mState.getCompiledState()->translatedSource; + return *mState.getCompiledState()->translatedSource; } GLuint ShaderGL::getShaderID() const diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp index 9d9f67b0cb2..f1da30007ad 100644 --- a/src/libANGLE/renderer/gl/StateManagerGL.cpp +++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp @@ -6,6 +6,10 @@ // StateManagerGL.h: Defines a class for caching applied OpenGL state +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/StateManagerGL.h" #include @@ -116,13 +120,14 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, mClipDepthMode(gl::ClipDepthMode::NegativeOneToOne), mBlendColor(0, 0, 0, 0), mBlendStateExt(rendererCaps.maxDrawBuffers), - mBlendAdvancedCoherent(extensions.blendEquationAdvancedCoherentKHR), + mBlendAdvancedCoherent(true), mIndependentBlendStates(extensions.drawBuffersIndexedAny()), mSampleAlphaToCoverageEnabled(false), mSampleCoverageEnabled(false), mSampleCoverageValue(1.0f), mSampleCoverageInvert(false), mSampleMaskEnabled(false), + mSampleCoverageEverChanged(false), mDepthTestEnabled(false), mDepthFunc(GL_LESS), mDepthMask(true), @@ -168,7 +173,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, mMultisamplingEnabled(true), mSampleAlphaToOneEnabled(false), mCoverageModulation(GL_NONE), - mIsMultiviewEnabled(extensions.multiviewOVR || extensions.multiview2OVR), + mIsMultiviewEnabled(extensions.multiviewOVR), mProvokingVertex(GL_LAST_VERTEX_CONVENTION), mMaxClipDistances(rendererCaps.maxClipDistances), mLogicOpEnabled(false), @@ -964,7 +969,7 @@ angle::Result StateManagerGL::onMakeCurrent(const gl::Context *context) // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set // this state here since MakeCurrent is expected to be called less frequently than draw calls. - setTextureCubemapSeamlessEnabled(context->getClientMajorVersion() >= 3); + setTextureCubemapSeamlessEnabled(context->getClientVersion() >= gl::ES_3_0); return angle::Result::Continue; } @@ -1603,15 +1608,20 @@ void StateManagerGL::setSampleCoverageEnabled(bool enabled) } } +void StateManagerGL::forceSetSampleCoverage(float value, bool invert) +{ + mSampleCoverageValue = value; + mSampleCoverageInvert = invert; + mSampleCoverageEverChanged = true; + mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert); + mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE); +} + void StateManagerGL::setSampleCoverage(float value, bool invert) { if (mSampleCoverageValue != value || mSampleCoverageInvert != invert) { - mSampleCoverageValue = value; - mSampleCoverageInvert = invert; - mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert); - - mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE); + forceSetSampleCoverage(value, invert); } } @@ -2005,26 +2015,9 @@ void StateManagerGL::setClearDepth(float clearDepth) void StateManagerGL::setClearColor(const gl::ColorF &clearColor) { - gl::ColorF modifiedClearColor = clearColor; - if (mFeatures.clearToZeroOrOneBroken.enabled && - (clearColor.red == 1.0f || clearColor.red == 0.0f) && - (clearColor.green == 1.0f || clearColor.green == 0.0f) && - (clearColor.blue == 1.0f || clearColor.blue == 0.0f) && - (clearColor.alpha == 1.0f || clearColor.alpha == 0.0f)) + if (mClearColor != clearColor) { - if (clearColor.alpha == 1.0f) - { - modifiedClearColor.alpha = 2.0f; - } - else - { - modifiedClearColor.alpha = -1.0f; - } - } - - if (mClearColor != modifiedClearColor) - { - mClearColor = modifiedClearColor; + mClearColor = clearColor; mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue, mClearColor.alpha); @@ -2261,6 +2254,11 @@ angle::Result StateManagerGL::syncState(const gl::Context *context, mHasSeparateFramebufferBindings ? GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER, framebufferGL->getFramebufferID()); + if (mFeatures.resetSampleCoverageOnFBOChange.enabled && mSampleCoverageEverChanged) + { + forceSetSampleCoverage(mSampleCoverageValue, mSampleCoverageInvert); + } + const gl::ProgramExecutable *executable = state.getProgramExecutable(); if (executable) { @@ -2512,12 +2510,15 @@ angle::Result StateManagerGL::syncState(const gl::Context *context, case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT: // These hints aren't forwarded to GL yet. break; - case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE: + case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM: + case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT: // Unimplemented extensions. break; case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT: setBlendAdvancedCoherent(state.isBlendAdvancedCoherentEnabled()); break; + case gl::state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED: + break; default: UNREACHABLE(); break; diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h index 5f75a696b3a..bad9aa5dfc4 100644 --- a/src/libANGLE/renderer/gl/StateManagerGL.h +++ b/src/libANGLE/renderer/gl/StateManagerGL.h @@ -232,6 +232,7 @@ class StateManagerGL final : angle::NonCopyable void setSampleAlphaToCoverageEnabled(bool enabled); void setSampleCoverageEnabled(bool enabled); void setSampleCoverage(float value, bool invert); + void forceSetSampleCoverage(float value, bool invert); void setSampleMaskEnabled(bool enabled); void setSampleMaski(GLuint maskNumber, GLbitfield mask); @@ -515,6 +516,7 @@ class StateManagerGL final : angle::NonCopyable bool mSampleCoverageInvert; bool mSampleMaskEnabled; gl::SampleMaskArray mSampleMaskValues; + bool mSampleCoverageEverChanged; bool mDepthTestEnabled; GLenum mDepthFunc; diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp index 8bf6b7827f3..34037f22651 100644 --- a/src/libANGLE/renderer/gl/TextureGL.cpp +++ b/src/libANGLE/renderer/gl/TextureGL.cpp @@ -6,6 +6,10 @@ // TextureGL.cpp: Implements the class methods for TextureGL. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/TextureGL.h" #include "common/bitset_utils.h" @@ -709,7 +713,12 @@ angle::Result TextureGL::copyImage(const gl::Context *context, const gl::InternalFormat &originalInternalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); nativegl::CopyTexImageImageFormat copyTexImageFormat = - nativegl::GetCopyTexImageImageFormat(functions, features, internalFormat, type); + nativegl::GetCopyTexImageImageFormat(functions, features, internalFormat); + const gl::InternalFormat ©InternalFormatInfo = + gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat, GL_UNSIGNED_BYTE); + nativegl::TexImageFormat initTexImageFormat = + nativegl::GetTexImageFormat(functions, features, internalFormat, + copyInternalFormatInfo.format, copyInternalFormatInfo.type); stateManager->bindTexture(getType(), mTextureID); @@ -732,8 +741,9 @@ angle::Result TextureGL::copyImage(const gl::Context *context, // framebuffer. if (requiresInitialization) { - GLuint pixelBytes = - gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat, type).pixelBytes; + const gl::InternalFormat &initFormatInfo = + gl::GetInternalFormatInfo(initTexImageFormat.format, initTexImageFormat.type); + GLuint pixelBytes = initFormatInfo.pixelBytes; angle::MemoryBuffer *zero; ANGLE_CHECK_GL_ALLOC( contextGL, @@ -744,18 +754,11 @@ angle::Result TextureGL::copyImage(const gl::Context *context, ANGLE_TRY(stateManager->setPixelUnpackState(context, unpack)); ANGLE_TRY(stateManager->setPixelUnpackBuffer(context, nullptr)); - // getImplementationColorReadType aligns the type with ES client version - if (type == GL_HALF_FLOAT_OES && functions->standard == STANDARD_GL_DESKTOP) - { - type = GL_HALF_FLOAT; - } - ANGLE_GL_TRY_ALWAYS_CHECK( context, functions->texImage2D(ToGLenum(target), static_cast(level), copyTexImageFormat.internalFormat, sourceArea.width, - sourceArea.height, 0, - gl::GetUnsizedFormat(copyTexImageFormat.internalFormat), - type, zero->data())); + sourceArea.height, 0, initTexImageFormat.format, + initTexImageFormat.type, zero->data())); } // Clip source area to framebuffer and copy if remaining area is not empty. @@ -783,6 +786,17 @@ angle::Result TextureGL::copyImage(const gl::Context *context, } } + bool isSelfCopy = false; + if (readBuffer && readBuffer->type() == GL_TEXTURE) + { + TextureGL *sourceTexture = GetImplAs(readBuffer->getTexture()); + const bool isSameCubeFace = + readBuffer->cubeMapFace() == gl::TextureTarget::InvalidEnum || + readBuffer->cubeMapFace() == target; + isSelfCopy = sourceTexture && sourceTexture->mTextureID == mTextureID && + readBuffer->mipLevel() == static_cast(level) && isSameCubeFace; + } + LevelInfoGL levelInfo = GetLevelInfo(features, originalInternalFormatInfo, copyTexImageFormat.internalFormat); gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0); @@ -828,20 +842,73 @@ angle::Result TextureGL::copyImage(const gl::Context *context, } else { - if (features.emulateCopyTexImage2D.enabled) + if (isSelfCopy) { - if (type == GL_HALF_FLOAT_OES && functions->standard == STANDARD_GL_DESKTOP) - { - type = GL_HALF_FLOAT; - } + // Avoid redefining the texture before the copy, as that would invalidate the + // source attachment. Copy through a temporary texture first. + + GLuint tempTex = 0; + ANGLE_GL_TRY(context, functions->genTextures(1, &tempTex)); + + // Always use a 2D temp texture to keep the attachment complete (especially for + // cube maps in ES, which require all faces to be defined). + stateManager->bindTexture(gl::TextureType::_2D, tempTex); + ANGLE_GL_TRY(context, + functions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0)); + ANGLE_GL_TRY(context, + functions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); + ANGLE_GL_TRY(context, functions->texParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + ANGLE_GL_TRY(context, functions->texParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + ANGLE_GL_TRY_ALWAYS_CHECK( + context, functions->texImage2D( + GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, + clippedArea.width, clippedArea.height, 0, + initTexImageFormat.format, initTexImageFormat.type, nullptr)); + ANGLE_GL_TRY(context, functions->copyTexSubImage2D( + GL_TEXTURE_2D, 0, 0, 0, clippedArea.x, clippedArea.y, + clippedArea.width, clippedArea.height)); + + GLuint tempFBO = 0; + ANGLE_GL_TRY(context, functions->genFramebuffers(1, &tempFBO)); + const GLenum readFramebufferTarget = + stateManager->getHasSeparateFramebufferBindings() ? GL_READ_FRAMEBUFFER + : GL_FRAMEBUFFER; + stateManager->bindFramebuffer(readFramebufferTarget, tempFBO); + ANGLE_GL_TRY(context, functions->framebufferTexture2D( + readFramebufferTarget, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tempTex, 0)); + + // Redefine the destination texture after the temp framebuffer is set up. + stateManager->bindTexture(getType(), mTextureID); + ANGLE_GL_TRY_ALWAYS_CHECK( + context, + functions->texImage2D(ToGLenum(target), static_cast(level), + copyTexImageFormat.internalFormat, sourceArea.width, + sourceArea.height, 0, initTexImageFormat.format, + initTexImageFormat.type, nullptr)); + + ANGLE_GL_TRY(context, + functions->copyTexSubImage2D( + ToGLenum(target), static_cast(level), destOffset.x, + destOffset.y, 0, 0, clippedArea.width, clippedArea.height)); + + stateManager->deleteFramebuffer(tempFBO); + stateManager->deleteTexture(tempTex); + // Restore the read framebuffer binding for the rest of this function. + stateManager->bindFramebuffer(readFramebufferTarget, + sourceFramebufferGL->getFramebufferID()); + } + else if (features.emulateCopyTexImage2D.enabled) + { ANGLE_GL_TRY_ALWAYS_CHECK( context, - functions->texImage2D( - ToGLenum(target), static_cast(level), - copyTexImageFormat.internalFormat, sourceArea.width, sourceArea.height, - 0, gl::GetUnsizedFormat(copyTexImageFormat.internalFormat), type, - nullptr)); + functions->texImage2D(ToGLenum(target), static_cast(level), + copyTexImageFormat.internalFormat, sourceArea.width, + sourceArea.height, 0, initTexImageFormat.format, + initTexImageFormat.type, nullptr)); ANGLE_GL_TRY_ALWAYS_CHECK( context, functions->copyTexSubImage2D(ToGLenum(target), static_cast(level), 0, @@ -1847,7 +1914,6 @@ angle::Result TextureGL::syncState(const gl::Context *context, break; case gl::Texture::DIRTY_BIT_BOUND_AS_IMAGE: case gl::Texture::DIRTY_BIT_BOUND_AS_ATTACHMENT: - case gl::Texture::DIRTY_BIT_BOUND_TO_MSRTT_FRAMEBUFFER: // Only used for Vulkan. break; @@ -2124,18 +2190,18 @@ angle::Result TextureGL::syncTextureStateSwizzle(const gl::Context *context, case GL_GREEN: case GL_BLUE: - if (context->getClientMajorVersion() <= 2) - { - // In OES_depth_texture/ARB_depth_texture, depth - // textures are treated as luminance. - resultSwizzle = GL_RED; - } - else + if (context->getClientVersion() >= gl::ES_3_0) { // In GLES 3.0, depth textures are treated as RED // textures, so green and blue should be 0. resultSwizzle = GL_ZERO; } + else + { + // In OES_depth_texture, depth + // textures are treated as luminance. + resultSwizzle = GL_RED; + } break; case GL_ALPHA: @@ -2292,10 +2358,46 @@ angle::Result TextureGL::initializeContents(const gl::Context *context, StateManagerGL *stateManager = GetStateManagerGL(context); const angle::FeaturesGL &features = GetFeaturesGL(context); - bool shouldUseClear = !nativegl::SupportsTexImage(getType()); + const gl::ImageDesc &desc = mState.getImageDesc(imageIndex); + const gl::InternalFormat &internalFormatInfo = *desc.format.info; + + // Clearing cube maps with EXT_clear_texture has inconsistent results. The drivers often clear + // the entire level when only one face is specified. + if (functions->clearTexImage && !internalFormatInfo.compressed && + getType() != gl::TextureType::CubeMap && + !features.disableClearTexImageForRobustInit.enabled) + { + nativegl::TexSubImageFormat nativeSubImageFormat = nativegl::GetTexSubImageFormat( + functions, features, internalFormatInfo.format, internalFormatInfo.type); + + // Some drivers may use color mask state when clearing textures. + contextGL->getStateManager()->setColorMask(true, true, true, true); + + // The largest GL data format is 16 bytes (RGBA32F) + static constexpr std::array data = {0}; + CHECK(internalFormatInfo.pixelBytes <= data.size()); + if (imageIndex.hasLayer()) + { + ANGLE_GL_TRY(context, functions->clearTexSubImage( + mTextureID, imageIndex.getLevelIndex(), 0, 0, + imageIndex.getLayerIndex(), desc.size.width, desc.size.height, + imageIndex.getLayerCount(), nativeSubImageFormat.format, + nativeSubImageFormat.type, data.data())); + } + else + { + ANGLE_GL_TRY(context, functions->clearTexImage(mTextureID, imageIndex.getLevelIndex(), + nativeSubImageFormat.format, + nativeSubImageFormat.type, data.data())); + } + + contextGL->markWorkSubmitted(); + return angle::Result::Continue; + } + GLenum nativeInternalFormat = getLevelInfo(imageIndex.getTarget(), imageIndex.getLevelIndex()).nativeInternalFormat; - if ((features.allowClearForRobustResourceInit.enabled || shouldUseClear) && + if (features.allowClearForRobustResourceInit.enabled && nativegl::SupportsNativeRendering(functions, mState.getType(), nativeInternalFormat)) { BlitGL *blitter = GetBlitGL(context); @@ -2315,8 +2417,6 @@ angle::Result TextureGL::initializeContents(const gl::Context *context, // Either the texture is not renderable or was incomplete when clearing, fall back to a data // upload ASSERT(nativegl::SupportsTexImage(getType())); - const gl::ImageDesc &desc = mState.getImageDesc(imageIndex); - const gl::InternalFormat &internalFormatInfo = *desc.format.info; gl::PixelUnpackState unpackState; unpackState.alignment = 1; diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp index d3143ef92d2..489cbffbce5 100644 --- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp +++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp @@ -6,6 +6,10 @@ // VertexArrayGL.cpp: Implements the class methods for VertexArrayGL. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/VertexArrayGL.h" #include "common/bitset_utils.h" @@ -39,10 +43,10 @@ bool SameVertexAttribFormat(const VertexAttributeGL &a, const VertexAttribute &b return a.format == b.format && a.relativeOffset == b.relativeOffset; } -bool SameVertexBuffer(const VertexBindingGL &a, const VertexBinding &b) +bool SameVertexBuffer(const VertexBindingGL &a, const VertexBinding &b, const gl::Buffer *buffer) { return a.stride == b.getStride() && a.offset == b.getOffset() && - a.buffer == GetNativeBufferID(b.getBuffer().get()); + a.buffer == GetNativeBufferID(buffer); } bool SameIndexBuffer(const VertexArrayStateGL *a, const gl::Buffer *frontendBuffer) @@ -109,8 +113,10 @@ static angle::Result ValidateStateHelperGetVertexAttribiv(const gl::Context *con } } // anonymous namespace -VertexArrayGL::VertexArrayGL(const VertexArrayState &state, GLuint id) - : VertexArrayImpl(state), +VertexArrayGL::VertexArrayGL(const VertexArrayState &state, + GLuint id, + const VertexArrayBuffers &vertexArrayBuffers) + : VertexArrayImpl(state, vertexArrayBuffers), mVertexArrayID(id), mOwnsNativeState(true), mNativeState(new VertexArrayStateGL(state.getMaxAttribs(), state.getMaxBindings())) @@ -120,8 +126,12 @@ VertexArrayGL::VertexArrayGL(const VertexArrayState &state, GLuint id) VertexArrayGL::VertexArrayGL(const gl::VertexArrayState &state, GLuint id, + const gl::VertexArrayBuffers &vertexArrayBuffers, VertexArrayStateGL *sharedState) - : VertexArrayImpl(state), mVertexArrayID(id), mOwnsNativeState(false), mNativeState(sharedState) + : VertexArrayImpl(state, vertexArrayBuffers), + mVertexArrayID(id), + mOwnsNativeState(false), + mNativeState(sharedState) { ASSERT(mNativeState); mForcedStreamingAttributesFirstOffsets.fill(0); @@ -173,7 +183,7 @@ angle::Result VertexArrayGL::syncClientSideData(const gl::Context *context, angle::Result VertexArrayGL::updateElementArrayBufferBinding(const gl::Context *context) const { - gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer(); + gl::Buffer *elementArrayBuffer = getElementArrayBuffer(); if (!SameIndexBuffer(mNativeState, elementArrayBuffer)) { GLuint elementArrayBufferId = @@ -202,8 +212,7 @@ angle::Result VertexArrayGL::syncDrawState(const gl::Context *context, // Check if any attributes need to be streamed, determines if the index range needs to be // computed - gl::AttributesMask needsStreamingAttribs = - context->getStateCache().getActiveClientAttribsMask(); + gl::AttributesMask needsStreamingAttribs = context->getActiveClientAttribsMask(); if (nativegl::CanUseClientSideArrays(functions, mVertexArrayID)) { needsStreamingAttribs.reset(); @@ -221,8 +230,7 @@ angle::Result VertexArrayGL::syncDrawState(const gl::Context *context, else { // Not an indexed call, set the range to [first, first + count - 1] - indexRange.start = first; - indexRange.end = first + count - 1; + indexRange = IndexRange(first, first + count - 1); if (features.shiftInstancedArrayDataWithOffset.enabled && first > 0) { @@ -282,7 +290,7 @@ angle::Result VertexArrayGL::syncIndexData(const gl::Context *context, const FunctionsGL *functions = GetFunctionsGL(context); - gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer(); + gl::Buffer *elementArrayBuffer = getElementArrayBuffer(); // Need to check the range of indices if attributes need to be streamed if (elementArrayBuffer) @@ -292,7 +300,7 @@ angle::Result VertexArrayGL::syncIndexData(const gl::Context *context, if (attributesNeedStreaming) { ptrdiff_t elementArrayBufferOffset = reinterpret_cast(indices); - ANGLE_TRY(mState.getElementArrayBuffer()->getIndexRange( + ANGLE_TRY(getElementArrayBuffer()->getIndexRange( context, type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange)); } @@ -421,7 +429,7 @@ angle::Result VertexArrayGL::streamAttributes( // If first is greater than zero, a slack space needs to be left at the beginning of the buffer // for each attribute so that the same 'first' argument can be passed into the draw call. const size_t bufferEmptySpace = - attribsToStream.count() * maxAttributeDataSize * indexRange.start; + attribsToStream.count() * maxAttributeDataSize * indexRange.start(); const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace; stateManager->bindBuffer(gl::BufferBinding::Array, mStreamingArrayBuffer); @@ -443,7 +451,7 @@ angle::Result VertexArrayGL::streamAttributes( { uint8_t *bufferPointer = MapBufferRangeWithFallback(functions, GL_ARRAY_BUFFER, 0, requiredBufferSize, GL_MAP_WRITE_BIT); - size_t curBufferOffset = maxAttributeDataSize * indexRange.start; + size_t curBufferOffset = maxAttributeDataSize * indexRange.start(); const auto &attribs = mState.getVertexAttributes(); const auto &bindings = mState.getVertexBindings(); @@ -468,7 +476,7 @@ angle::Result VertexArrayGL::streamAttributes( // a non-instanced draw call const size_t firstIndex = (adjustedDivisor == 0 || applyExtraOffsetWorkaroundForInstancedAttributes) - ? indexRange.start + ? indexRange.start() : 0; // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state. @@ -485,13 +493,13 @@ angle::Result VertexArrayGL::streamAttributes( { const size_t originalStreamedVertexCount = streamedVertexCount; streamedVertexCount = - (instanceCount + indexRange.start + adjustedDivisor - 1u) / adjustedDivisor; + (instanceCount + indexRange.start() + adjustedDivisor - 1u) / adjustedDivisor; const size_t copySize = sourceStride * originalStreamedVertexCount; // the real data in the buffer we are streaming - const gl::Buffer *bindingBufferPointer = binding.getBuffer().get(); + const gl::Buffer *bindingBufferPointer = getVertexArrayBuffer(attrib.bindingIndex); if (!bindingBufferPointer) { if (!inputPointer) @@ -570,10 +578,10 @@ angle::Result VertexArrayGL::streamAttributes( mArrayBuffers[idx].set(context, nullptr); mNativeState->bindings[idx].buffer = mStreamingArrayBuffer; - // There's maxAttributeDataSize * indexRange.start of empty space allocated for each + // There's maxAttributeDataSize * indexRange.start() of empty space allocated for each // streaming attributes curBufferOffset += - destStride * streamedVertexCount + maxAttributeDataSize * indexRange.start; + destStride * streamedVertexCount + maxAttributeDataSize * indexRange.start(); } unmapResult = ANGLE_GL_TRY(context, functions->unmapBuffer(GL_ARRAY_BUFFER)); @@ -612,8 +620,9 @@ angle::Result VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstan ASSERT(IsVertexAttribPointerSupported(idx, attrib)); const auto &binding = bindings[attrib.bindingIndex]; - const auto buffer = GetImplAs(binding.getBuffer().get()); - stateManager->bindBuffer(gl::BufferBinding::Array, buffer->getBufferID()); + gl::Buffer *buffer = getVertexArrayBuffer(attrib.bindingIndex); + const BufferGL *bufferGL = GetImplAs(buffer); + stateManager->bindBuffer(gl::BufferBinding::Array, bufferGL->getBufferID()); ANGLE_TRY(callVertexAttribPointer(context, static_cast(idx), attrib, static_cast(binding.getStride()), @@ -627,8 +636,8 @@ angle::Result VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstan mNativeState->bindings[idx].stride = binding.getStride(); mNativeState->bindings[idx].offset = binding.getOffset(); - mArrayBuffers[idx].set(context, binding.getBuffer().get()); - mNativeState->bindings[idx].buffer = buffer->getBufferID(); + mArrayBuffers[idx].set(context, buffer); + mNativeState->bindings[idx].buffer = bufferGL->getBufferID(); } attributeMask->reset(); @@ -690,8 +699,7 @@ angle::Result VertexArrayGL::updateAttribPointer(const gl::Context *context, siz // - Skip the attribute that is disabled and uses a client memory pointer. // - Skip the attribute whose buffer is detached by BindVertexBuffer. Since it cannot have a // client memory pointer either, it must be disabled and shouldn't affect the draw. - const auto &bindingBuffer = binding.getBuffer(); - gl::Buffer *arrayBuffer = bindingBuffer.get(); + gl::Buffer *arrayBuffer = getVertexArrayBuffer(attribIndex); if (arrayBuffer == nullptr && !canUseClientArrays) { // Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if @@ -707,7 +715,7 @@ angle::Result VertexArrayGL::updateAttribPointer(const gl::Context *context, siz // update attribPointer in this function. if (SameVertexAttribFormat(mNativeState->attributes[attribIndex], attrib) && (mNativeState->attributes[attribIndex].bindingIndex == attrib.bindingIndex) && - SameVertexBuffer(mNativeState->bindings[attribIndex], binding) && + SameVertexBuffer(mNativeState->bindings[attribIndex], binding, arrayBuffer) && (!canUseClientArrays || SameAttribPointer(mNativeState->attributes[attribIndex], attrib))) { return angle::Result::Continue; @@ -728,9 +736,10 @@ angle::Result VertexArrayGL::updateAttribPointer(const gl::Context *context, siz stateManager->bindBuffer(gl::BufferBinding::Array, bufferId); if (features.ensureNonEmptyBufferIsBoundForDraw.enabled && bufferGL->getBufferSize() == 0) { + BufferFeedback feedback; constexpr uint32_t data = 0; ANGLE_TRY(bufferGL->setData(context, gl::BufferBinding::Array, &data, sizeof(data), - gl::BufferUsage::StaticDraw)); + gl::BufferUsage::StaticDraw, &feedback)); ASSERT(bufferGL->getBufferSize() > 0); } ANGLE_TRY(callVertexAttribPointer(context, static_cast(attribIndex), attrib, @@ -855,12 +864,12 @@ angle::Result VertexArrayGL::updateBindingBuffer(const gl::Context *context, siz ASSERT(supportVertexAttribBinding(context)); const VertexBinding &binding = mState.getVertexBinding(bindingIndex); - if (SameVertexBuffer(mNativeState->bindings[bindingIndex], binding)) + gl::Buffer *arrayBuffer = getVertexArrayBuffer(bindingIndex); + if (SameVertexBuffer(mNativeState->bindings[bindingIndex], binding, arrayBuffer)) { return angle::Result::Continue; } - gl::Buffer *arrayBuffer = binding.getBuffer().get(); GLuint bufferId = GetNativeBufferID(arrayBuffer); const FunctionsGL *functions = GetFunctionsGL(context); @@ -979,6 +988,9 @@ angle::Result VertexArrayGL::syncDirtyBinding( ANGLE_TRY(updateBindingDivisor(context, bindingIndex)); break; + case VertexArray::DIRTY_BINDING_SIZE: + break; + default: UNREACHABLE(); break; @@ -1016,18 +1028,6 @@ angle::Result VertexArrayGL::syncState(const gl::Context *context, size_t dirtyBit = *iter; switch (dirtyBit) { - case gl::VertexArray::DIRTY_BIT_LOST_OBSERVATION: - { - // If vertex array was not observing while unbound, we need to check buffer's - // internal storage and take action if buffer has changed while not observing. - // For now we just simply assume buffer storage has changed and always dirty all - // binding points. - iter.setLaterBits( - gl::VertexArray::DirtyBits(mState.getBufferBindingMask().to_ulong() - << gl::VertexArray::DIRTY_BIT_BINDING_0)); - break; - } - case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER: ANGLE_TRY(updateElementArrayBufferBinding(context)); break; diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/libANGLE/renderer/gl/VertexArrayGL.h index 12aaf1e40e7..2b08576bbef 100644 --- a/src/libANGLE/renderer/gl/VertexArrayGL.h +++ b/src/libANGLE/renderer/gl/VertexArrayGL.h @@ -25,8 +25,13 @@ struct VertexArrayStateGL; class VertexArrayGL : public VertexArrayImpl { public: - VertexArrayGL(const gl::VertexArrayState &data, GLuint id); - VertexArrayGL(const gl::VertexArrayState &data, GLuint id, VertexArrayStateGL *sharedState); + VertexArrayGL(const gl::VertexArrayState &data, + GLuint id, + const gl::VertexArrayBuffers &vertexArrayBuffers); + VertexArrayGL(const gl::VertexArrayState &data, + GLuint id, + const gl::VertexArrayBuffers &vertexArrayBuffers, + VertexArrayStateGL *sharedState); ~VertexArrayGL() override; void destroy(const gl::Context *context) override; diff --git a/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.cpp b/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.cpp index 9044dde9b29..d1835bc78d2 100644 --- a/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.cpp +++ b/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.cpp @@ -7,6 +7,10 @@ // PBufferSurfaceCGL.cpp: an implementation of PBuffers created from IOSurfaces using // EGL_ANGLE_iosurface_client_buffer +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h" #include @@ -139,7 +143,7 @@ egl::Error IOSurfaceSurfaceCGL::unMakeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error IOSurfaceSurfaceCGL::swap(const gl::Context *context) +egl::Error IOSurfaceSurfaceCGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -202,14 +206,9 @@ void IOSurfaceSurfaceCGL::setSwapInterval(const egl::Display *display, EGLint in UNREACHABLE(); } -EGLint IOSurfaceSurfaceCGL::getWidth() const -{ - return mWidth; -} - -EGLint IOSurfaceSurfaceCGL::getHeight() const +gl::Extents IOSurfaceSurfaceCGL::getSize() const { - return mHeight; + return gl::Extents(mWidth, mHeight, 1); } EGLint IOSurfaceSurfaceCGL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h b/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h index 2b1e6127230..c387d5458af 100644 --- a/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h +++ b/src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h @@ -42,7 +42,7 @@ class IOSurfaceSurfaceCGL : public SurfaceGL egl::Error makeCurrent(const gl::Context *context) override; egl::Error unMakeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -55,8 +55,7 @@ class IOSurfaceSurfaceCGL : public SurfaceGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.cpp b/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.cpp index 74baded106e..c7e45b7ce09 100644 --- a/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.cpp +++ b/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.cpp @@ -70,7 +70,7 @@ egl::Error PbufferSurfaceCGL::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error PbufferSurfaceCGL::swap(const gl::Context *context) +egl::Error PbufferSurfaceCGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -106,15 +106,11 @@ egl::Error PbufferSurfaceCGL::releaseTexImage(const gl::Context *context, EGLint void PbufferSurfaceCGL::setSwapInterval(const egl::Display *display, EGLint interval) {} -EGLint PbufferSurfaceCGL::getWidth() const +gl::Extents PbufferSurfaceCGL::getSize() const { - return mWidth; + return gl::Extents(mWidth, mHeight, 1); } -EGLint PbufferSurfaceCGL::getHeight() const -{ - return mHeight; -} EGLint PbufferSurfaceCGL::isPostSubBufferSupported() const { diff --git a/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h b/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h index 0439a6518ee..08f512cb9da 100644 --- a/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h +++ b/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h @@ -31,7 +31,7 @@ class PbufferSurfaceCGL : public SurfaceGL egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -44,8 +44,7 @@ class PbufferSurfaceCGL : public SurfaceGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h index 8f834859196..477b780b53c 100644 --- a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h +++ b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h @@ -69,7 +69,7 @@ class WindowSurfaceCGL : public SurfaceGL egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -82,8 +82,8 @@ class WindowSurfaceCGL : public SurfaceGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const final; + egl::Error getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const final; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm index bbe107b52c5..0ab68427835 100644 --- a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm +++ b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm @@ -6,6 +6,10 @@ // WindowSurfaceCGL.cpp: CGL implementation of egl::Surface for windows +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #import "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h" #import @@ -205,8 +209,9 @@ - (void)drawInCGLContext:(CGLContextObj)glContext { EnsureCGLContextIsCurrent ensureContextCurrent(mContext); - unsigned width = getWidth(); - unsigned height = getHeight(); + gl::Extents size = getSize(); + unsigned width = size.width; + unsigned height = size.height; for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i) { @@ -240,7 +245,7 @@ - (void)drawInCGLContext:(CGLContextObj)glContext return egl::Error(EGL_SUCCESS); } -egl::Error WindowSurfaceCGL::swap(const gl::Context *context) +egl::Error WindowSurfaceCGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { const FunctionsGL *functions = GetFunctionsGL(context); StateManagerGL *stateManager = GetStateManagerGL(context); @@ -254,9 +259,10 @@ - (void)drawInCGLContext:(CGLContextObj)glContext } pthread_mutex_unlock(&mSwapState.mutex); - unsigned width = getWidth(); - unsigned height = getHeight(); - auto &texture = *mSwapState.beingRendered; + gl::Extents size = getSize(); + unsigned width = size.width; + unsigned height = size.height; + auto &texture = *mSwapState.beingRendered; if (mSwapLayer.contentsScale != mLayer.contentsScale || texture.width != width || texture.height != height) { @@ -316,14 +322,29 @@ - (void)drawInCGLContext:(CGLContextObj)glContext // TODO(cwallez) investigate implementing swap intervals other than 0 } -EGLint WindowSurfaceCGL::getWidth() const +gl::Extents WindowSurfaceCGL::getSize() const { - return static_cast(CGRectGetWidth([mLayer frame]) * [mLayer contentsScale]); + EGLint width, height; + egl::Error error = WindowSurfaceCGL::getUserSize(nullptr, &width, &height); + ASSERT(!error.isError()); + return gl::Extents(width, height, 1); } -EGLint WindowSurfaceCGL::getHeight() const +egl::Error WindowSurfaceCGL::getUserSize(const egl::Display *display, + EGLint *width, + EGLint *height) const { - return static_cast(CGRectGetHeight([mLayer frame]) * [mLayer contentsScale]); + CGRect frame = [mLayer frame]; + CGFloat scale = [mLayer contentsScale]; + if (width != nullptr) + { + *width = static_cast(CGRectGetWidth(frame) * scale); + } + if (height != nullptr) + { + *height = static_cast(CGRectGetHeight(frame) * scale); + } + return egl::NoError(); } EGLint WindowSurfaceCGL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp index acada69f435..646f6ca16c9 100644 --- a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp +++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp @@ -6,6 +6,10 @@ // DisplayEGL.cpp: Common across EGL parts of platform specific egl::Display implementations +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/gl/egl/DisplayEGL.h" #include "common/debug.h" @@ -46,7 +50,8 @@ std::vector RenderableTypesFromPlatformAttrib(const rx::FunctionsEGL *eg static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR, "Extension define must match core"); - gl::Version eglVersion(egl->majorVersion, egl->minorVersion); + const gl::Version eglVersion(static_cast(egl->majorVersion), + static_cast(egl->minorVersion)); if (eglVersion >= gl::Version(1, 5) || egl->hasExtension("EGL_KHR_create_context")) { renderableTypes.push_back(EGL_OPENGL_ES3_BIT); @@ -117,7 +122,8 @@ egl::Error DisplayEGL::initializeContext(EGLContext shareContext, const egl::AttributeMap &eglAttributes, EGLContext *outContext) const { - gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion); + const gl::Version eglVersion(static_cast(mEGL->majorVersion), + static_cast(mEGL->minorVersion)); EGLint requestedMajor = eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); @@ -156,9 +162,9 @@ egl::Error DisplayEGL::initializeContext(EGLContext shareContext, { egl::AttributeMap versionAttribs; versionAttribs.insert(EGL_CONTEXT_MAJOR_VERSION, - static_cast(version.major)); + static_cast(version.getMajor())); versionAttribs.insert(EGL_CONTEXT_MINOR_VERSION, - static_cast(version.minor)); + static_cast(version.getMinor())); contextAttribLists.push_back(std::move(versionAttribs)); } @@ -315,7 +321,8 @@ egl::Error DisplayEGL::initialize(egl::Display *display) ANGLE_TRY( mEGL->initialize(platformType, display->getNativeDisplayId(), getEGLPath(), eglHandle)); - gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion); + const gl::Version eglVersion(static_cast(mEGL->majorVersion), + static_cast(mEGL->minorVersion)); if (eglVersion < gl::Version(1, 4)) { return egl::Error(EGL_NOT_INITIALIZED, "EGL >= 1.4 is required"); @@ -451,8 +458,19 @@ class ExternalSurfaceEGL : public SurfaceEGL egl::Error initialize(const egl::Display *display) override { return egl::NoError(); } EGLint getSwapBehavior() const override { return EGL_BUFFER_DESTROYED; } - EGLint getWidth() const override { return mWidth; } - EGLint getHeight() const override { return mHeight; } + gl::Extents getSize() const final { return gl::Extents(mWidth, mHeight, 1); } + egl::Error getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const final + { + if (width != nullptr) + { + *width = mWidth; + } + if (height != nullptr) + { + *height = mHeight; + } + return egl::NoError(); + } bool isExternal() const override { return true; } private: @@ -641,6 +659,8 @@ egl::ConfigSet DisplayEGL::generateConfigs() getConfigAttribIfExtension(configs[i], EGL_COLOR_COMPONENT_TYPE_EXT, &config.colorComponentType, "EGL_EXT_pixel_format_float", EGL_COLOR_COMPONENT_TYPE_FIXED_EXT); + getConfigAttribIfExtension(configs[i], EGL_RECORDABLE_ANDROID, &config.recordable, + "EGL_ANDROID_recordable", EGL_FALSE); config.surfaceType = fixSurfaceType(config.surfaceType); @@ -822,13 +842,15 @@ void DisplayEGL::destroyNativeContext(EGLContext context) void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const { - gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion); + const gl::Version eglVersion(static_cast(mEGL->majorVersion), + static_cast(mEGL->minorVersion)); outExtensions->createContextRobustness = mEGL->hasExtension("EGL_EXT_create_context_robustness"); outExtensions->postSubBuffer = false; // Since SurfaceEGL::postSubBuffer is not implemented outExtensions->presentationTime = mEGL->hasExtension("EGL_ANDROID_presentation_time"); + outExtensions->recordable = mEGL->hasExtension("EGL_ANDROID_recordable"); // Contexts are virtualized so textures and semaphores can be shared globally outExtensions->displayTextureShareGroup = true; @@ -1044,7 +1066,7 @@ DeviceImpl *DisplayEGL::createDevice() return new DeviceEGL(this); } -bool DisplayEGL::supportsDmaBufFormat(EGLint format) const +bool DisplayEGL::supportsDmaBufFormat(EGLint format) { return std::find(std::begin(mDrmFormats), std::end(mDrmFormats), format) != std::end(mDrmFormats); diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.h b/src/libANGLE/renderer/gl/egl/DisplayEGL.h index eee714ce4da..e9793dc02f8 100644 --- a/src/libANGLE/renderer/gl/egl/DisplayEGL.h +++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.h @@ -103,7 +103,7 @@ class DisplayEGL : public DisplayGL DeviceImpl *createDevice() override; - bool supportsDmaBufFormat(EGLint format) const override; + bool supportsDmaBufFormat(EGLint format) override; egl::Error queryDmaBufFormats(EGLint maxFormats, EGLint *formats, EGLint *numFormats) override; egl::Error queryDmaBufModifiers(EGLint format, EGLint maxModifiers, diff --git a/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp b/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp index cb52de22fb7..58e88973876 100644 --- a/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp +++ b/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp @@ -43,6 +43,7 @@ bool IsValidPlatformTypeForPlatformDisplayConnection(EGLAttrib platformType) switch (platformType) { case EGL_PLATFORM_SURFACELESS_MESA: + case EGL_PLATFORM_GBM_KHR: return true; default: break; @@ -246,7 +247,10 @@ egl::Error FunctionsEGL::initialize(EGLAttrib platformType, EGLNativeDisplayType queryExtensions(); #if defined(ANGLE_HAS_LIBDRM) - mEGLDisplay = getPreferredDisplay(&majorVersion, &minorVersion); + if (platformType != EGL_PLATFORM_GBM_KHR || !nativeDisplay) + { + mEGLDisplay = getPreferredDisplay(&majorVersion, &minorVersion); + } #endif // defined(ANGLE_HAS_LIBDRM) if (mEGLDisplay == EGL_NO_DISPLAY) @@ -420,6 +424,12 @@ EGLDisplay FunctionsEGL::getPlatformDisplay(EGLAttrib platformType, if (!hasExtension("EGL_MESA_platform_surfaceless")) return EGL_NO_DISPLAY; break; + case EGL_PLATFORM_GBM_KHR: + if (!hasExtension("EGL_KHR_platform_gbm") && !hasExtension("EGL_MESA_platform_gbm")) + { + return EGL_NO_DISPLAY; + } + break; default: UNREACHABLE(); return EGL_NO_DISPLAY; diff --git a/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp b/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp index 64f2edccfad..9d61275a5c5 100644 --- a/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp +++ b/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp @@ -37,20 +37,20 @@ egl::Error SurfaceEGL::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error SurfaceEGL::swap(const gl::Context *context) +egl::Error SurfaceEGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { egl::Display::GetCurrentThreadUnlockedTailCall()->add( [egl = mEGL, surface = mSurface](void *resultOut) { ANGLE_UNUSED_VARIABLE(resultOut); *static_cast(resultOut) = egl->swapBuffers(surface); }); - return egl::NoError(); } egl::Error SurfaceEGL::swapWithDamage(const gl::Context *context, const EGLint *rects, - EGLint n_rects) + EGLint n_rects, + SurfaceSwapFeedback *feedback) { if (mHasSwapBuffersWithDamage) { @@ -129,20 +129,27 @@ void SurfaceEGL::setSwapInterval(const egl::Display *display, EGLint interval) } } -EGLint SurfaceEGL::getWidth() const +gl::Extents SurfaceEGL::getSize() const { - EGLint value; - EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value); - ASSERT(success == EGL_TRUE); - return value; + EGLint width, height; + egl::Error error = SurfaceEGL::getUserSize(nullptr, &width, &height); + ASSERT(!error.isError()); + return gl::Extents(width, height, 1); } -EGLint SurfaceEGL::getHeight() const +egl::Error SurfaceEGL::getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const { - EGLint value; - EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value); - ASSERT(success == EGL_TRUE); - return value; + if (width != nullptr) + { + EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, width); + ASSERT(success == EGL_TRUE); + } + if (height != nullptr) + { + EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, height); + ASSERT(success == EGL_TRUE); + } + return egl::NoError(); } EGLint SurfaceEGL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/egl/SurfaceEGL.h b/src/libANGLE/renderer/gl/egl/SurfaceEGL.h index 66e01f2be27..1b9eee791a7 100644 --- a/src/libANGLE/renderer/gl/egl/SurfaceEGL.h +++ b/src/libANGLE/renderer/gl/egl/SurfaceEGL.h @@ -24,10 +24,11 @@ class SurfaceEGL : public SurfaceGL ~SurfaceEGL() override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error swapWithDamage(const gl::Context *context, const EGLint *rects, - EGLint n_rects) override; + EGLint n_rects, + SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -40,8 +41,10 @@ class SurfaceEGL : public SurfaceGL EGLint buffer) override; egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; // finalized in ExternalSurfaceEGL + egl::Error getUserSize(const egl::Display *display, + EGLint *width, + EGLint *height) const override; // finalized in ExternalSurfaceEGL EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/egl/egl_utils.cpp b/src/libANGLE/renderer/gl/egl/egl_utils.cpp index 78ecd362f52..386a3e5d1dd 100644 --- a/src/libANGLE/renderer/gl/egl/egl_utils.cpp +++ b/src/libANGLE/renderer/gl/egl/egl_utils.cpp @@ -6,6 +6,10 @@ // egl_utils.cpp: Utility routines specific to the EGL->EGL implementation. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/egl/egl_utils.h" #include "common/debug.h" diff --git a/src/libANGLE/renderer/gl/formatutilsgl.cpp b/src/libANGLE/renderer/gl/formatutilsgl.cpp index 4325dcf3c5f..24ea1cfb93d 100644 --- a/src/libANGLE/renderer/gl/formatutilsgl.cpp +++ b/src/libANGLE/renderer/gl/formatutilsgl.cpp @@ -23,7 +23,7 @@ namespace nativegl { SupportRequirement::SupportRequirement() - : version(std::numeric_limits::max(), std::numeric_limits::max()), + : version(std::numeric_limits::max(), std::numeric_limits::max()), versionExtensions(), requiredExtensions() {} @@ -41,38 +41,35 @@ InternalFormat::InternalFormat(const InternalFormat &other) = default; InternalFormat::~InternalFormat() {} // supported = version || vertexExt -static inline SupportRequirement VersionOrExts(GLuint major, - GLuint minor, +static inline SupportRequirement VersionOrExts(uint8_t major, + uint8_t minor, const std::string &versionExt) { SupportRequirement requirement; - requirement.version.major = major; - requirement.version.minor = minor; + requirement.version = gl::Version(major, minor); angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions); return requirement; } // supported = requiredExt && (version || requiredWithoutVersionExt) static inline SupportRequirement ExtAndVersionOrExt(const std::string &requiredExt, - GLuint major, - GLuint minor, + uint8_t major, + uint8_t minor, const std::string &requiredWithoutVersionExt) { SupportRequirement requirement; requirement.requiredExtensions.resize(1); angle::SplitStringAlongWhitespace(requiredExt, &requirement.requiredExtensions[0]); - requirement.version.major = major; - requirement.version.minor = minor; + requirement.version = gl::Version(major, minor); angle::SplitStringAlongWhitespace(requiredWithoutVersionExt, &requirement.versionExtensions); return requirement; } // supported = version -static inline SupportRequirement VersionOnly(GLuint major, GLuint minor) +static inline SupportRequirement VersionOnly(uint8_t major, uint8_t minor) { SupportRequirement requirement; - requirement.version.major = major; - requirement.version.minor = minor; + requirement.version = gl::Version(major, minor); return requirement; } @@ -80,8 +77,7 @@ static inline SupportRequirement VersionOnly(GLuint major, GLuint minor) static inline SupportRequirement ExtsOnly(const std::vector &exts) { SupportRequirement requirement; - requirement.version.major = 0; - requirement.version.minor = 0; + requirement.version = gl::Version(); requirement.requiredExtensions.resize(exts.size()); for (size_t i = 0; i < exts.size(); i++) { @@ -106,8 +102,7 @@ static inline SupportRequirement ExtsOnly(const std::string &ext1, const std::st static inline SupportRequirement AlwaysSupported() { SupportRequirement requirement; - requirement.version.major = 0; - requirement.version.minor = 0; + requirement.version = gl::Version(); return requirement; } @@ -115,8 +110,8 @@ static inline SupportRequirement AlwaysSupported() static inline SupportRequirement NeverSupported() { SupportRequirement requirement; - requirement.version.major = std::numeric_limits::max(); - requirement.version.minor = std::numeric_limits::max(); + requirement.version = + gl::Version(std::numeric_limits::max(), std::numeric_limits::max()); return requirement; } @@ -526,10 +521,11 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions, result = GL_RGB8; } - if (internalFormat.sizedInternalFormat == GL_BGRA8_EXT) + if (internalFormat.sizedInternalFormat == GL_BGRA_EXT || + internalFormat.sizedInternalFormat == GL_BGRA8_EXT) { - // GLES accepts GL_BGRA as an internal format but desktop GL only accepts it as a type. - // Update the internal format to GL_RGBA. + // GLES accepts GL_BGRA as an internal format but desktop GL only accepts it as a + // format. Update the internal format to GL_RGBA8. result = GL_RGBA8; } @@ -615,6 +611,71 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions, result = internalFormat.sizedInternalFormat; } } + else if (internalFormat.sizedInternalFormat == GL_BGRA_EXT) + { + // GL_BGRA_EXT and GL_BGRA8_EXT are both allowed as sized internal formats now, but not + // all drivers support that behavior. Map to the previously sized for internal format. + // http://anglebug.com/42267264 + result = GL_BGRA8_EXT; + } + } + + return result; +} + +static GLenum GetTexImageNativeInternalFormat(const FunctionsGL *functions, + const angle::FeaturesGL &features, + const gl::InternalFormat &internalFormat) +{ + GLenum result = internalFormat.internalFormat; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + result = GetNativeInternalFormat(functions, features, internalFormat); + } + else if (functions->isAtLeastGLES(gl::Version(3, 0))) + { + if (internalFormat.sizedInternalFormat == GL_BGRA_EXT || + internalFormat.sizedInternalFormat == GL_BGRA8_EXT) + { + // GL_BGRA_EXT and GL_BGRA8_EXT are both allowed as sized internal formats now, but + // not all drivers support that behavior. For *TexImage*, map to the previously + // *unsized* internal format. http://anglebug.com/42267264 + result = GL_BGRA_EXT; + } + else + { + result = GetNativeInternalFormat(functions, features, internalFormat); + } + } + + return result; +} + +static GLenum GetTexStorageNativeInternalFormat(const FunctionsGL *functions, + const angle::FeaturesGL &features, + const gl::InternalFormat &internalFormat) +{ + GLenum result = internalFormat.internalFormat; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + result = GetNativeInternalFormat(functions, features, internalFormat); + } + else if (functions->isAtLeastGLES(gl::Version(3, 0))) + { + if (internalFormat.sizedInternalFormat == GL_BGRA_EXT || + internalFormat.sizedInternalFormat == GL_BGRA8_EXT) + { + // GL_BGRA_EXT and GL_BGRA8_EXT are both allowed as sized internal formats now, but not + // all drivers support that behavior. For *TexStorage*, map to the previously *sized* + // internal format. http://anglebug.com/42267264 + result = GL_BGRA8_EXT; + } + else + { + result = GetNativeInternalFormat(functions, features, internalFormat); + } } return result; @@ -797,7 +858,7 @@ TexImageFormat GetTexImageFormat(const FunctionsGL *functions, GLenum type) { TexImageFormat result; - result.internalFormat = GetNativeInternalFormat( + result.internalFormat = GetTexImageNativeInternalFormat( functions, features, gl::GetInternalFormatInfo(internalFormat, type)); result.format = GetNativeFormat(functions, features, format, type); result.type = GetNativeType(functions, features, format, type); @@ -835,12 +896,12 @@ CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *fu CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions, const angle::FeaturesGL &features, - GLenum internalFormat, - GLenum framebufferType) + GLenum internalFormat) { CopyTexImageImageFormat result; - result.internalFormat = GetNativeInternalFormat( - functions, features, gl::GetInternalFormatInfo(internalFormat, framebufferType)); + const gl::InternalFormat &formatInfo = + gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE); + result.internalFormat = GetTexImageNativeInternalFormat(functions, features, formatInfo); return result; } @@ -858,7 +919,8 @@ TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions, } else { - result.internalFormat = GetNativeInternalFormat(functions, features, sizedFormatInfo); + result.internalFormat = + GetTexStorageNativeInternalFormat(functions, features, sizedFormatInfo); } return result; diff --git a/src/libANGLE/renderer/gl/formatutilsgl.h b/src/libANGLE/renderer/gl/formatutilsgl.h index 8dbc5ea5650..15e66985218 100644 --- a/src/libANGLE/renderer/gl/formatutilsgl.h +++ b/src/libANGLE/renderer/gl/formatutilsgl.h @@ -107,8 +107,7 @@ struct CopyTexImageImageFormat }; CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions, const angle::FeaturesGL &features, - GLenum internalFormat, - GLenum framebufferType); + GLenum internalFormat); struct TexStorageFormat { diff --git a/src/libANGLE/renderer/gl/functionsgl_typedefs.h b/src/libANGLE/renderer/gl/functionsgl_typedefs.h index b0b04863a16..5d7c77fd109 100644 --- a/src/libANGLE/renderer/gl/functionsgl_typedefs.h +++ b/src/libANGLE/renderer/gl/functionsgl_typedefs.h @@ -1745,13 +1745,21 @@ typedef void(INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATSAMPLEIVNVPROC)(GLenum GLsizei bufSize, GLint *params); -// GL_OVR_multiview2 +// GL_OVR_multiview typedef void(INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +typedef void(INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)( + GLuint framebuffer, + GLenum attachment, + GLuint texture, + GLint level, + GLint baseViewIndex, + GLsizei numViews); + // EXT_debug_marker typedef void(INTERNAL_GL_APIENTRY *PFNGLINSERTEVENTMARKEREXTPROC)(GLsizei length, const GLchar *marker); diff --git a/src/libANGLE/renderer/gl/generate_gl_dispatch_table.py b/src/libANGLE/renderer/gl/generate_gl_dispatch_table.py index 8848cf28800..5e3a4b002cf 100644 --- a/src/libANGLE/renderer/gl/generate_gl_dispatch_table.py +++ b/src/libANGLE/renderer/gl/generate_gl_dispatch_table.py @@ -66,12 +66,6 @@ class DispatchTableGL : angle::NonCopyable void initProcsDesktopGL(const gl::Version &version, const std::set &extensions); void initProcsGLES(const gl::Version &version, const std::set &extensions); void initProcsSharedExtensions(const std::set &extensions); - -#if defined(ANGLE_ENABLE_OPENGL_NULL) - void initProcsDesktopGLNULL(const gl::Version &version, const std::set &extensions); - void initProcsGLESNULL(const gl::Version &version, const std::set &extensions); - void initProcsSharedExtensionsNULL(const std::set &extensions); -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) }}; }} // namespace rx @@ -104,10 +98,6 @@ def format_ep_decl(entry_point): #include "libANGLE/Version.h" #include "libANGLE/renderer/gl/FunctionsGL.h" -#if defined(ANGLE_ENABLE_OPENGL_NULL) -#include "libANGLE/renderer/gl/null_functions.h" -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - #define ASSIGN(NAME, FP) do {{ FP = reinterpret_cast(loadProcAddress(NAME)); }} while (0) namespace rx @@ -135,29 +125,6 @@ def format_ep_decl(entry_point): {both_extensions_data} }} -#if defined(ANGLE_ENABLE_OPENGL_NULL) -void DispatchTableGL::initProcsDesktopGLNULL(const gl::Version &version, const std::set &extensions) -{{ -#if defined(ANGLE_ENABLE_GL_DESKTOP_BACKEND) -{gl_null_extensions_data} - -{gl_null_data} -#endif // defined(ANGLE_ENABLE_GL_DESKTOP_BACKEND) -}} - -void DispatchTableGL::initProcsGLESNULL(const gl::Version &version, const std::set &extensions) -{{ -{gles2_null_extensions_data} - -{gles2_null_data} -}} - -void DispatchTableGL::initProcsSharedExtensionsNULL(const std::set &extensions) -{{ -{both_null_extensions_data} -}} -#endif // defined(ANGLE_ENABLE_OPENGL_NULL) - }} // namespace rx """ @@ -181,69 +148,10 @@ def format_extension_requirements_lines(extension, entry_points, api): return '\n'.join(lines) -def assign_null_line(line): - m = re.match(r' ASSIGN\("gl.*", (.+)\);', line) - if m: - name = m.group(1) - return ' ' + name + ' = &gl' + name[0].upper() + name[1:] + 'NULL;' - else: - return line - - -def assign_null(entry): - return '\n'.join([assign_null_line(line) for line in entry.split('\n')]) - - -def nullify(data): - return [assign_null(entry) for entry in data] - - def format_param(param): return "".join(param.itertext()) -null_functions_header_template = """// GENERATED FILE - DO NOT EDIT. -// Generated by {script_name} using data from {data_source_name} and gl.xml. -// -// Copyright 2017 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. -// -// {file_name}: -// Declares the NULL/Stub bindings for the OpenGL back-end. - -#ifndef LIBGLESV2_RENDERER_GL_NULL_GL_FUNCTIONS_AUTOGEN_H_ -#define LIBGLESV2_RENDERER_GL_NULL_GL_FUNCTIONS_AUTOGEN_H_ - -#include "libANGLE/renderer/gl/functionsgl_typedefs.h" - -namespace rx -{{ -{table_data} -}} // namespace rx - -#endif // LIBGLESV2_RENDERER_GL_NULL_GL_FUNCTIONS_AUTOGEN_H_ -""" - -null_functions_source_template = """// GENERATED FILE - DO NOT EDIT. -// Generated by {script_name} using data from {data_source_name} and gl.xml. -// -// Copyright 2017 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. -// -// {file_name}: -// Defines the NULL/Stub bindings for the OpenGL back-end. - -#include "libANGLE/renderer/gl/null_functions.h" - -namespace rx -{{ -{table_data} -}} // namespace rx -""" - - def main(): # auto_script parameters. @@ -256,8 +164,6 @@ def main(): outputs = [ 'DispatchTableGL_autogen.cpp', 'DispatchTableGL_autogen.h', - 'null_functions.cpp', - 'null_functions.h', ] if sys.argv[1] == 'inputs': @@ -273,8 +179,6 @@ def main(): 'xml', 'gl.xml') dispatch_header_path = 'DispatchTableGL_autogen.h' dispatch_source_path = 'DispatchTableGL_autogen.cpp' - null_functions_header_path = 'null_functions.h' - null_functions_source_path = 'null_functions.cpp' # Load the JSON and XML data. data_source_name = 'gl_bindings_data.json' @@ -444,12 +348,7 @@ def main(): gl_extensions_data="\n\n".join(gl_extensions_data), gles2_data="\n\n".join(gles2_data), gles2_extensions_data="\n\n".join(gles2_extensions_data), - both_extensions_data="\n\n".join(both_extensions_data), - gl_null_data="\n\n".join(nullify(gl_data)), - gl_null_extensions_data="\n\n".join(nullify(gl_extensions_data)), - gles2_null_data="\n\n".join(nullify(gles2_data)), - gles2_null_extensions_data="\n\n".join(nullify(gles2_extensions_data)), - both_null_extensions_data="\n\n".join(nullify(both_extensions_data))) + both_extensions_data="\n\n".join(both_extensions_data)) with open(dispatch_source_path, "w") as out: out.write(dispatch_table_source) @@ -479,26 +378,6 @@ def main(): command_defs[command_name] = entry - null_decls = [command_decls[entry_point] for entry_point in sorted(all_entry_points)] - null_stubs = [command_defs[entry_point] for entry_point in sorted(all_entry_points)] - - null_functions_header = null_functions_header_template.format( - script_name=os.path.basename(sys.argv[0]), - data_source_name=data_source_name, - file_name=null_functions_header_path, - table_data="\n".join(null_decls)) - - with open(null_functions_header_path, "w") as out: - out.write(null_functions_header) - - null_functions_source = null_functions_source_template.format( - script_name=os.path.basename(sys.argv[0]), - data_source_name=data_source_name, - file_name=null_functions_source_path, - table_data="\n\n".join(null_stubs)) - - with open(null_functions_source_path, "w") as out: - out.write(null_functions_source) return 0 diff --git a/src/libANGLE/renderer/gl/gl_backend.gni b/src/libANGLE/renderer/gl/gl_backend.gni index b6b997e2591..c4801b59c56 100644 --- a/src/libANGLE/renderer/gl/gl_backend.gni +++ b/src/libANGLE/renderer/gl/gl_backend.gni @@ -4,10 +4,6 @@ import("../../../../gni/angle.gni") -declare_args() { - angle_enable_gl_null = true -} - gl_backend_sources = [ "BlitGL.cpp", "BlitGL.h", @@ -176,10 +172,3 @@ if (angle_enable_cgl) { "cgl/WindowSurfaceCGL.mm", ] } - -if (angle_enable_gl_null) { - gl_backend_sources += [ - "null_functions.cpp", - "null_functions.h", - ] -} diff --git a/src/libANGLE/renderer/gl/gl_bindings_data.json b/src/libANGLE/renderer/gl/gl_bindings_data.json index 4f3f4965309..5a7816788db 100644 --- a/src/libANGLE/renderer/gl/gl_bindings_data.json +++ b/src/libANGLE/renderer/gl/gl_bindings_data.json @@ -774,10 +774,11 @@ [ "MaxShaderCompilerThreadsKHR" ], - - "GL_OVR_multiview2": + + "GL_OVR_multiview": [ - "FramebufferTextureMultiviewOVR" + "FramebufferTextureMultiviewOVR", + "NamedFramebufferTextureMultiviewOVR" ], "GL_EXT_memory_object": diff --git a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp index e455725a454..5af16cb059b 100644 --- a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp +++ b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // DisplayGLX.cpp: GLX implementation of egl::Display #include @@ -300,9 +304,10 @@ egl::Error DisplayGLX::initialize(egl::Display *display) return egl::Error(EGL_NOT_INITIALIZED, "Context lost for unknown reason."); } } - // TODO(cwallez, angleproject:1303) Disable the OpenGL ES backend on Linux NVIDIA and Intel as - // it has problems on our automated testing. An OpenGL ES backend might not trigger this test if - // there is no Desktop OpenGL support, but that's not the case in our automated testing. + // TODO(cwallez, http://anglebug.com/42260314) Disable the OpenGL ES backend on Linux NVIDIA and + // Intel as it has problems on our automated testing. An OpenGL ES backend might not trigger + // this test if there is no Desktop OpenGL support, but that's not the case in our automated + // testing. VendorID vendor = GetVendorID(functionsGL.get()); bool isOpenGLES = eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) == @@ -478,13 +483,14 @@ egl::Error DisplayGLX::initializeContext(glx::FBConfig config, } // Create a context of the requested version, if any. - gl::Version requestedVersion(static_cast(eglAttributes.get( - EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)), - static_cast(eglAttributes.get( - EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE))); - if (static_cast(requestedVersion.major) != EGL_DONT_CARE && - static_cast(requestedVersion.minor) != EGL_DONT_CARE) - { + const EGLint clientMajorVersion = static_cast( + eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)); + const EGLint clientMinorVersion = static_cast( + eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)); + if (clientMajorVersion != EGL_DONT_CARE && clientMinorVersion != EGL_DONT_CARE) + { + const gl::Version requestedVersion(static_cast(clientMajorVersion), + static_cast(clientMinorVersion)); if (!(profileMask & GLX_CONTEXT_ES2_PROFILE_BIT_EXT) && requestedVersion >= gl::Version(3, 2)) { @@ -914,10 +920,10 @@ egl::Error DisplayGLX::createContextAttribs(glx::FBConfig, if (version.valid()) { attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); - attribs.push_back(version.value().major); + attribs.push_back(version.value().getMajor()); attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); - attribs.push_back(version.value().minor); + attribs.push_back(version.value().getMinor()); } if (profileMask != 0 && mHasARBCreateContextProfile) diff --git a/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp index a2be909094b..939e2fc55b4 100644 --- a/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp +++ b/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp @@ -69,7 +69,7 @@ egl::Error PbufferSurfaceGLX::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error PbufferSurfaceGLX::swap(const gl::Context *context) +egl::Error PbufferSurfaceGLX::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -105,14 +105,9 @@ egl::Error PbufferSurfaceGLX::releaseTexImage(const gl::Context *context, EGLint void PbufferSurfaceGLX::setSwapInterval(const egl::Display *display, EGLint interval) {} -EGLint PbufferSurfaceGLX::getWidth() const +gl::Extents PbufferSurfaceGLX::getSize() const { - return mWidth; -} - -EGLint PbufferSurfaceGLX::getHeight() const -{ - return mHeight; + return gl::Extents(mWidth, mHeight, 1); } EGLint PbufferSurfaceGLX::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h index 3108ca9ba62..35a2ae4c51e 100644 --- a/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h +++ b/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h @@ -31,7 +31,7 @@ class PbufferSurfaceGLX : public SurfaceGLX egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -44,8 +44,7 @@ class PbufferSurfaceGLX : public SurfaceGLX egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.cpp b/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.cpp index 8daec12d4b6..8c9369a906f 100644 --- a/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.cpp +++ b/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.cpp @@ -143,7 +143,7 @@ egl::Error PixmapSurfaceGLX::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error PixmapSurfaceGLX::swap(const gl::Context *context) +egl::Error PixmapSurfaceGLX::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { UNREACHABLE(); return egl::NoError(); @@ -182,14 +182,9 @@ egl::Error PixmapSurfaceGLX::releaseTexImage(const gl::Context *context, EGLint void PixmapSurfaceGLX::setSwapInterval(const egl::Display *display, EGLint interval) {} -EGLint PixmapSurfaceGLX::getWidth() const +gl::Extents PixmapSurfaceGLX::getSize() const { - return mWidth; -} - -EGLint PixmapSurfaceGLX::getHeight() const -{ - return mHeight; + return gl::Extents(mWidth, mHeight, 1); } EGLint PixmapSurfaceGLX::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h b/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h index f51bed394c8..18d7a0a9b10 100644 --- a/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h +++ b/src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h @@ -30,7 +30,7 @@ class PixmapSurfaceGLX : public SurfaceGLX egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -43,8 +43,7 @@ class PixmapSurfaceGLX : public SurfaceGLX egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp index 7c81b9a6d2b..7fc5387de20 100644 --- a/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp +++ b/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp @@ -151,7 +151,7 @@ egl::Error WindowSurfaceGLX::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error WindowSurfaceGLX::swap(const gl::Context *context) +egl::Error WindowSurfaceGLX::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { // We need to swap before resizing as some drivers clobber the back buffer // when the window is resized. @@ -205,41 +205,22 @@ void WindowSurfaceGLX::setSwapInterval(const egl::Display *display, EGLint inter mSwapControl.targetSwapInterval = interval; } -EGLint WindowSurfaceGLX::getWidth() const +gl::Extents WindowSurfaceGLX::getSize() const { if (mUseChildWindow) { // If there's a child window, the size of the window is always the same as the cached // size of its parent. - return mParentWidth; + return gl::Extents(mParentWidth, mParentHeight, 1); } else { unsigned int parentWidth, parentHeight; if (!getWindowDimensions(mParent, &parentWidth, &parentHeight)) { - return mParentWidth; + return gl::Extents(mParentWidth, mParentHeight, 1); } - return parentWidth; - } -} - -EGLint WindowSurfaceGLX::getHeight() const -{ - if (mUseChildWindow) - { - // If there's a child window, the size of the window is always the same as the cached - // size of its parent. - return mParentHeight; - } - else - { - unsigned int parentWidth, parentHeight; - if (!getWindowDimensions(mParent, &parentWidth, &parentHeight)) - { - return mParentHeight; - } - return parentHeight; + return gl::Extents(parentWidth, parentHeight, 1); } } diff --git a/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h index 3a2d63187a5..47cfe874937 100644 --- a/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h +++ b/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h @@ -34,7 +34,7 @@ class WindowSurfaceGLX : public SurfaceGLX egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -47,8 +47,7 @@ class WindowSurfaceGLX : public SurfaceGLX egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/null_functions.cpp b/src/libANGLE/renderer/gl/null_functions.cpp deleted file mode 100644 index 18a7c74868c..00000000000 --- a/src/libANGLE/renderer/gl/null_functions.cpp +++ /dev/null @@ -1,3276 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by generate_gl_dispatch_table.py using data from gl_bindings_data.json and gl.xml. -// -// Copyright 2017 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. -// -// null_functions.cpp: -// Defines the NULL/Stub bindings for the OpenGL back-end. - -#include "libANGLE/renderer/gl/null_functions.h" - -namespace rx -{ -void INTERNAL_GL_APIENTRY glActiveShaderProgramNULL(GLuint pipeline, GLuint program) {} - -void INTERNAL_GL_APIENTRY glActiveTextureNULL(GLenum texture) {} - -void INTERNAL_GL_APIENTRY glAttachShaderNULL(GLuint program, GLuint shader) {} - -void INTERNAL_GL_APIENTRY glBeginConditionalRenderNULL(GLuint id, GLenum mode) {} - -void INTERNAL_GL_APIENTRY glBeginQueryNULL(GLenum target, GLuint id) {} - -void INTERNAL_GL_APIENTRY glBeginQueryIndexedNULL(GLenum target, GLuint index, GLuint id) {} - -void INTERNAL_GL_APIENTRY glBeginTransformFeedbackNULL(GLenum primitiveMode) {} - -void INTERNAL_GL_APIENTRY glBindAttribLocationNULL(GLuint program, GLuint index, const GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glBindBufferNULL(GLenum target, GLuint buffer) {} - -void INTERNAL_GL_APIENTRY glBindBufferBaseNULL(GLenum target, GLuint index, GLuint buffer) {} - -void INTERNAL_GL_APIENTRY -glBindBufferRangeNULL(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glBindBuffersBaseNULL(GLenum target, - GLuint first, - GLsizei count, - const GLuint *buffers) -{} - -void INTERNAL_GL_APIENTRY glBindBuffersRangeNULL(GLenum target, - GLuint first, - GLsizei count, - const GLuint *buffers, - const GLintptr *offsets, - const GLsizeiptr *sizes) -{} - -void INTERNAL_GL_APIENTRY glBindFragDataLocationNULL(GLuint program, - GLuint color, - const GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glBindFragDataLocationIndexedNULL(GLuint program, - GLuint colorNumber, - GLuint index, - const GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glBindFramebufferNULL(GLenum target, GLuint framebuffer) {} - -void INTERNAL_GL_APIENTRY glBindImageTextureNULL(GLuint unit, - GLuint texture, - GLint level, - GLboolean layered, - GLint layer, - GLenum access, - GLenum format) -{} - -void INTERNAL_GL_APIENTRY glBindImageTexturesNULL(GLuint first, - GLsizei count, - const GLuint *textures) -{} - -void INTERNAL_GL_APIENTRY glBindProgramPipelineNULL(GLuint pipeline) {} - -void INTERNAL_GL_APIENTRY glBindRenderbufferNULL(GLenum target, GLuint renderbuffer) {} - -void INTERNAL_GL_APIENTRY glBindSamplerNULL(GLuint unit, GLuint sampler) {} - -void INTERNAL_GL_APIENTRY glBindSamplersNULL(GLuint first, GLsizei count, const GLuint *samplers) {} - -void INTERNAL_GL_APIENTRY glBindTextureNULL(GLenum target, GLuint texture) {} - -void INTERNAL_GL_APIENTRY glBindTextureUnitNULL(GLuint unit, GLuint texture) {} - -void INTERNAL_GL_APIENTRY glBindTexturesNULL(GLuint first, GLsizei count, const GLuint *textures) {} - -void INTERNAL_GL_APIENTRY glBindTransformFeedbackNULL(GLenum target, GLuint id) {} - -void INTERNAL_GL_APIENTRY glBindVertexArrayNULL(GLuint array) {} - -void INTERNAL_GL_APIENTRY glBindVertexBufferNULL(GLuint bindingindex, - GLuint buffer, - GLintptr offset, - GLsizei stride) -{} - -void INTERNAL_GL_APIENTRY glBindVertexBuffersNULL(GLuint first, - GLsizei count, - const GLuint *buffers, - const GLintptr *offsets, - const GLsizei *strides) -{} - -void INTERNAL_GL_APIENTRY glBlendBarrierNULL() {} - -void INTERNAL_GL_APIENTRY glBlendColorNULL(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -{} - -void INTERNAL_GL_APIENTRY glBlendEquationNULL(GLenum mode) {} - -void INTERNAL_GL_APIENTRY glBlendEquationSeparateNULL(GLenum modeRGB, GLenum modeAlpha) {} - -void INTERNAL_GL_APIENTRY glBlendEquationSeparateiNULL(GLuint buf, GLenum modeRGB, GLenum modeAlpha) -{} - -void INTERNAL_GL_APIENTRY glBlendEquationiNULL(GLuint buf, GLenum mode) {} - -void INTERNAL_GL_APIENTRY glBlendFuncNULL(GLenum sfactor, GLenum dfactor) {} - -void INTERNAL_GL_APIENTRY glBlendFuncSeparateNULL(GLenum sfactorRGB, - GLenum dfactorRGB, - GLenum sfactorAlpha, - GLenum dfactorAlpha) -{} - -void INTERNAL_GL_APIENTRY -glBlendFuncSeparateiNULL(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) -{} - -void INTERNAL_GL_APIENTRY glBlendFunciNULL(GLuint buf, GLenum src, GLenum dst) {} - -void INTERNAL_GL_APIENTRY glBlitFramebufferNULL(GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter) -{} - -void INTERNAL_GL_APIENTRY glBlitFramebufferEXTNULL(GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter) -{} - -void INTERNAL_GL_APIENTRY glBlitFramebufferNVNULL(GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter) -{} - -void INTERNAL_GL_APIENTRY glBlitNamedFramebufferNULL(GLuint readFramebuffer, - GLuint drawFramebuffer, - GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter) -{} - -void INTERNAL_GL_APIENTRY glBufferDataNULL(GLenum target, - GLsizeiptr size, - const void *data, - GLenum usage) -{} - -void INTERNAL_GL_APIENTRY glBufferStorageNULL(GLenum target, - GLsizeiptr size, - const void *data, - GLbitfield flags) -{} - -void INTERNAL_GL_APIENTRY glBufferStorageMemEXTNULL(GLenum target, - GLsizeiptr size, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glBufferSubDataNULL(GLenum target, - GLintptr offset, - GLsizeiptr size, - const void *data) -{} - -GLenum INTERNAL_GL_APIENTRY glCheckFramebufferStatusNULL(GLenum target) -{ - return static_cast(0); -} - -GLenum INTERNAL_GL_APIENTRY glCheckNamedFramebufferStatusNULL(GLuint framebuffer, GLenum target) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glClampColorNULL(GLenum target, GLenum clamp) {} - -void INTERNAL_GL_APIENTRY glClearNULL(GLbitfield mask) {} - -void INTERNAL_GL_APIENTRY glClearBufferDataNULL(GLenum target, - GLenum internalformat, - GLenum format, - GLenum type, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glClearBufferSubDataNULL(GLenum target, - GLenum internalformat, - GLintptr offset, - GLsizeiptr size, - GLenum format, - GLenum type, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glClearBufferfiNULL(GLenum buffer, - GLint drawbuffer, - GLfloat depth, - GLint stencil) -{} - -void INTERNAL_GL_APIENTRY glClearBufferfvNULL(GLenum buffer, GLint drawbuffer, const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glClearBufferivNULL(GLenum buffer, GLint drawbuffer, const GLint *value) -{} - -void INTERNAL_GL_APIENTRY glClearBufferuivNULL(GLenum buffer, GLint drawbuffer, const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glClearColorNULL(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -{} - -void INTERNAL_GL_APIENTRY glClearDepthNULL(GLdouble depth) {} - -void INTERNAL_GL_APIENTRY glClearDepthfNULL(GLfloat d) {} - -void INTERNAL_GL_APIENTRY glClearNamedBufferDataNULL(GLuint buffer, - GLenum internalformat, - GLenum format, - GLenum type, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glClearNamedBufferSubDataNULL(GLuint buffer, - GLenum internalformat, - GLintptr offset, - GLsizeiptr size, - GLenum format, - GLenum type, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glClearNamedFramebufferfiNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - GLfloat depth, - GLint stencil) -{} - -void INTERNAL_GL_APIENTRY glClearNamedFramebufferfvNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glClearNamedFramebufferivNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - const GLint *value) -{} - -void INTERNAL_GL_APIENTRY glClearNamedFramebufferuivNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glClearStencilNULL(GLint s) {} - -void INTERNAL_GL_APIENTRY -glClearTexImageNULL(GLuint texture, GLint level, GLenum format, GLenum type, const void *data) -{} - -void INTERNAL_GL_APIENTRY glClearTexSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *data) -{} - -GLenum INTERNAL_GL_APIENTRY glClientWaitSyncNULL(GLsync sync, GLbitfield flags, GLuint64 timeout) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glClipControlNULL(GLenum origin, GLenum depth) {} - -void INTERNAL_GL_APIENTRY glColorMaskNULL(GLboolean red, - GLboolean green, - GLboolean blue, - GLboolean alpha) -{} - -void INTERNAL_GL_APIENTRY -glColorMaskiNULL(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) -{} - -void INTERNAL_GL_APIENTRY glCompileShaderNULL(GLuint shader) {} - -void INTERNAL_GL_APIENTRY glCompressedTexImage1DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLint border, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTexImage2DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTexImage3DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTexSubImage1DNULL(GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTexSubImage2DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTexSubImage3DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTextureSubImage1DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTextureSubImage2DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCompressedTextureSubImage3DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLsizei imageSize, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glCopyBufferSubDataNULL(GLenum readTarget, - GLenum writeTarget, - GLintptr readOffset, - GLintptr writeOffset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glCopyImageSubDataNULL(GLuint srcName, - GLenum srcTarget, - GLint srcLevel, - GLint srcX, - GLint srcY, - GLint srcZ, - GLuint dstName, - GLenum dstTarget, - GLint dstLevel, - GLint dstX, - GLint dstY, - GLint dstZ, - GLsizei srcWidth, - GLsizei srcHeight, - GLsizei srcDepth) -{} - -void INTERNAL_GL_APIENTRY glCopyNamedBufferSubDataNULL(GLuint readBuffer, - GLuint writeBuffer, - GLintptr readOffset, - GLintptr writeOffset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glCopyTexImage1DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLint x, - GLint y, - GLsizei width, - GLint border) -{} - -void INTERNAL_GL_APIENTRY glCopyTexImage2DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLint border) -{} - -void INTERNAL_GL_APIENTRY -glCopyTexSubImage1DNULL(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) -{} - -void INTERNAL_GL_APIENTRY glCopyTexSubImage2DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glCopyTexSubImage3DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glCopyTextureSubImage1DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint x, - GLint y, - GLsizei width) -{} - -void INTERNAL_GL_APIENTRY glCopyTextureSubImage2DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glCopyTextureSubImage3DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glCoverageModulationNVNULL(GLenum components) {} - -void INTERNAL_GL_APIENTRY glCreateBuffersNULL(GLsizei n, GLuint *buffers) {} - -void INTERNAL_GL_APIENTRY glCreateFramebuffersNULL(GLsizei n, GLuint *framebuffers) {} - -void INTERNAL_GL_APIENTRY glCreateMemoryObjectsEXTNULL(GLsizei n, GLuint *memoryObjects) {} - -GLuint INTERNAL_GL_APIENTRY glCreateProgramNULL() -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glCreateProgramPipelinesNULL(GLsizei n, GLuint *pipelines) {} - -void INTERNAL_GL_APIENTRY glCreateQueriesNULL(GLenum target, GLsizei n, GLuint *ids) {} - -void INTERNAL_GL_APIENTRY glCreateRenderbuffersNULL(GLsizei n, GLuint *renderbuffers) {} - -void INTERNAL_GL_APIENTRY glCreateSamplersNULL(GLsizei n, GLuint *samplers) {} - -GLuint INTERNAL_GL_APIENTRY glCreateShaderNULL(GLenum type) -{ - return static_cast(0); -} - -GLuint INTERNAL_GL_APIENTRY glCreateShaderProgramvNULL(GLenum type, - GLsizei count, - const GLchar *const *strings) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glCreateTexturesNULL(GLenum target, GLsizei n, GLuint *textures) {} - -void INTERNAL_GL_APIENTRY glCreateTransformFeedbacksNULL(GLsizei n, GLuint *ids) {} - -void INTERNAL_GL_APIENTRY glCreateVertexArraysNULL(GLsizei n, GLuint *arrays) {} - -void INTERNAL_GL_APIENTRY glCullFaceNULL(GLenum mode) {} - -void INTERNAL_GL_APIENTRY glDebugMessageCallbackNULL(GLDEBUGPROC callback, const void *userParam) {} - -void INTERNAL_GL_APIENTRY glDebugMessageControlNULL(GLenum source, - GLenum type, - GLenum severity, - GLsizei count, - const GLuint *ids, - GLboolean enabled) -{} - -void INTERNAL_GL_APIENTRY glDebugMessageInsertNULL(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *buf) -{} - -void INTERNAL_GL_APIENTRY glDeleteBuffersNULL(GLsizei n, const GLuint *buffers) {} - -void INTERNAL_GL_APIENTRY glDeleteFencesNVNULL(GLsizei n, const GLuint *fences) {} - -void INTERNAL_GL_APIENTRY glDeleteFramebuffersNULL(GLsizei n, const GLuint *framebuffers) {} - -void INTERNAL_GL_APIENTRY glDeleteMemoryObjectsEXTNULL(GLsizei n, const GLuint *memoryObjects) {} - -void INTERNAL_GL_APIENTRY glDeleteProgramNULL(GLuint program) {} - -void INTERNAL_GL_APIENTRY glDeleteProgramPipelinesNULL(GLsizei n, const GLuint *pipelines) {} - -void INTERNAL_GL_APIENTRY glDeleteQueriesNULL(GLsizei n, const GLuint *ids) {} - -void INTERNAL_GL_APIENTRY glDeleteRenderbuffersNULL(GLsizei n, const GLuint *renderbuffers) {} - -void INTERNAL_GL_APIENTRY glDeleteSamplersNULL(GLsizei count, const GLuint *samplers) {} - -void INTERNAL_GL_APIENTRY glDeleteSemaphoresEXTNULL(GLsizei n, const GLuint *semaphores) {} - -void INTERNAL_GL_APIENTRY glDeleteShaderNULL(GLuint shader) {} - -void INTERNAL_GL_APIENTRY glDeleteSyncNULL(GLsync sync) {} - -void INTERNAL_GL_APIENTRY glDeleteTexturesNULL(GLsizei n, const GLuint *textures) {} - -void INTERNAL_GL_APIENTRY glDeleteTransformFeedbacksNULL(GLsizei n, const GLuint *ids) {} - -void INTERNAL_GL_APIENTRY glDeleteVertexArraysNULL(GLsizei n, const GLuint *arrays) {} - -void INTERNAL_GL_APIENTRY glDepthFuncNULL(GLenum func) {} - -void INTERNAL_GL_APIENTRY glDepthMaskNULL(GLboolean flag) {} - -void INTERNAL_GL_APIENTRY glDepthRangeNULL(GLdouble n, GLdouble f) {} - -void INTERNAL_GL_APIENTRY glDepthRangeArrayvNULL(GLuint first, GLsizei count, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glDepthRangeIndexedNULL(GLuint index, GLdouble n, GLdouble f) {} - -void INTERNAL_GL_APIENTRY glDepthRangefNULL(GLfloat n, GLfloat f) {} - -void INTERNAL_GL_APIENTRY glDetachShaderNULL(GLuint program, GLuint shader) {} - -void INTERNAL_GL_APIENTRY glDisableNULL(GLenum cap) {} - -void INTERNAL_GL_APIENTRY glDisableVertexArrayAttribNULL(GLuint vaobj, GLuint index) {} - -void INTERNAL_GL_APIENTRY glDisableVertexAttribArrayNULL(GLuint index) {} - -void INTERNAL_GL_APIENTRY glDisableiNULL(GLenum target, GLuint index) {} - -void INTERNAL_GL_APIENTRY glDiscardFramebufferEXTNULL(GLenum target, - GLsizei numAttachments, - const GLenum *attachments) -{} - -void INTERNAL_GL_APIENTRY glDispatchComputeNULL(GLuint num_groups_x, - GLuint num_groups_y, - GLuint num_groups_z) -{} - -void INTERNAL_GL_APIENTRY glDispatchComputeIndirectNULL(GLintptr indirect) {} - -void INTERNAL_GL_APIENTRY glDrawArraysNULL(GLenum mode, GLint first, GLsizei count) {} - -void INTERNAL_GL_APIENTRY glDrawArraysIndirectNULL(GLenum mode, const void *indirect) {} - -void INTERNAL_GL_APIENTRY glDrawArraysInstancedNULL(GLenum mode, - GLint first, - GLsizei count, - GLsizei instancecount) -{} - -void INTERNAL_GL_APIENTRY glDrawArraysInstancedBaseInstanceNULL(GLenum mode, - GLint first, - GLsizei count, - GLsizei instancecount, - GLuint baseinstance) -{} - -void INTERNAL_GL_APIENTRY glDrawBufferNULL(GLenum buf) {} - -void INTERNAL_GL_APIENTRY glDrawBuffersNULL(GLsizei n, const GLenum *bufs) {} - -void INTERNAL_GL_APIENTRY glDrawElementsNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices) -{} - -void INTERNAL_GL_APIENTRY glDrawElementsBaseVertexNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLint basevertex) -{} - -void INTERNAL_GL_APIENTRY glDrawElementsIndirectNULL(GLenum mode, GLenum type, const void *indirect) -{} - -void INTERNAL_GL_APIENTRY glDrawElementsInstancedNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount) -{} - -void INTERNAL_GL_APIENTRY glDrawElementsInstancedBaseInstanceNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount, - GLuint baseinstance) -{} - -void INTERNAL_GL_APIENTRY glDrawElementsInstancedBaseVertexNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount, - GLint basevertex) -{} - -void INTERNAL_GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount, - GLint basevertex, - GLuint baseinstance) -{} - -void INTERNAL_GL_APIENTRY glDrawRangeElementsNULL(GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const void *indices) -{} - -void INTERNAL_GL_APIENTRY glDrawRangeElementsBaseVertexNULL(GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const void *indices, - GLint basevertex) -{} - -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackNULL(GLenum mode, GLuint id) {} - -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackInstancedNULL(GLenum mode, - GLuint id, - GLsizei instancecount) -{} - -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackStreamNULL(GLenum mode, GLuint id, GLuint stream) -{} - -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackStreamInstancedNULL(GLenum mode, - GLuint id, - GLuint stream, - GLsizei instancecount) -{} - -void INTERNAL_GL_APIENTRY glEGLImageTargetRenderbufferStorageOESNULL(GLenum target, - GLeglImageOES image) -{} - -void INTERNAL_GL_APIENTRY glEGLImageTargetTexture2DOESNULL(GLenum target, GLeglImageOES image) {} - -void INTERNAL_GL_APIENTRY glEnableNULL(GLenum cap) {} - -void INTERNAL_GL_APIENTRY glEnableVertexArrayAttribNULL(GLuint vaobj, GLuint index) {} - -void INTERNAL_GL_APIENTRY glEnableVertexAttribArrayNULL(GLuint index) {} - -void INTERNAL_GL_APIENTRY glEnableiNULL(GLenum target, GLuint index) {} - -void INTERNAL_GL_APIENTRY glEndConditionalRenderNULL() {} - -void INTERNAL_GL_APIENTRY glEndQueryNULL(GLenum target) {} - -void INTERNAL_GL_APIENTRY glEndQueryIndexedNULL(GLenum target, GLuint index) {} - -void INTERNAL_GL_APIENTRY glEndTilingQCOMNULL(GLbitfield preserveMask) {} - -void INTERNAL_GL_APIENTRY glEndTransformFeedbackNULL() {} - -GLsync INTERNAL_GL_APIENTRY glFenceSyncNULL(GLenum condition, GLbitfield flags) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glFinishNULL() {} - -void INTERNAL_GL_APIENTRY glFinishFenceNVNULL(GLuint fence) {} - -void INTERNAL_GL_APIENTRY glFlushNULL() {} - -void INTERNAL_GL_APIENTRY glFlushMappedBufferRangeNULL(GLenum target, - GLintptr offset, - GLsizeiptr length) -{} - -void INTERNAL_GL_APIENTRY glFlushMappedNamedBufferRangeNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr length) -{} - -void INTERNAL_GL_APIENTRY glFramebufferFetchBarrierEXTNULL() {} - -void INTERNAL_GL_APIENTRY glFramebufferParameteriNULL(GLenum target, GLenum pname, GLint param) {} - -void INTERNAL_GL_APIENTRY glFramebufferParameteriMESANULL(GLenum target, GLenum pname, GLint param) -{} - -void INTERNAL_GL_APIENTRY glFramebufferRenderbufferNULL(GLenum target, - GLenum attachment, - GLenum renderbuffertarget, - GLuint renderbuffer) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTextureNULL(GLenum target, - GLenum attachment, - GLuint texture, - GLint level) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTexture1DNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTexture2DNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTexture2DMultisampleEXTNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level, - GLsizei samples) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTexture2DMultisampleIMGNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level, - GLsizei samples) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTexture3DNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level, - GLint zoffset) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTextureLayerNULL(GLenum target, - GLenum attachment, - GLuint texture, - GLint level, - GLint layer) -{} - -void INTERNAL_GL_APIENTRY glFramebufferTextureMultiviewOVRNULL(GLenum target, - GLenum attachment, - GLuint texture, - GLint level, - GLint baseViewIndex, - GLsizei numViews) -{} - -void INTERNAL_GL_APIENTRY glFrontFaceNULL(GLenum mode) {} - -void INTERNAL_GL_APIENTRY glGenBuffersNULL(GLsizei n, GLuint *buffers) {} - -void INTERNAL_GL_APIENTRY glGenFencesNVNULL(GLsizei n, GLuint *fences) {} - -void INTERNAL_GL_APIENTRY glGenFramebuffersNULL(GLsizei n, GLuint *framebuffers) {} - -void INTERNAL_GL_APIENTRY glGenProgramPipelinesNULL(GLsizei n, GLuint *pipelines) {} - -void INTERNAL_GL_APIENTRY glGenQueriesNULL(GLsizei n, GLuint *ids) {} - -void INTERNAL_GL_APIENTRY glGenRenderbuffersNULL(GLsizei n, GLuint *renderbuffers) {} - -void INTERNAL_GL_APIENTRY glGenSamplersNULL(GLsizei count, GLuint *samplers) {} - -void INTERNAL_GL_APIENTRY glGenSemaphoresEXTNULL(GLsizei n, GLuint *semaphores) {} - -void INTERNAL_GL_APIENTRY glGenTexturesNULL(GLsizei n, GLuint *textures) {} - -void INTERNAL_GL_APIENTRY glGenTransformFeedbacksNULL(GLsizei n, GLuint *ids) {} - -void INTERNAL_GL_APIENTRY glGenVertexArraysNULL(GLsizei n, GLuint *arrays) {} - -void INTERNAL_GL_APIENTRY glGenerateMipmapNULL(GLenum target) {} - -void INTERNAL_GL_APIENTRY glGenerateTextureMipmapNULL(GLuint texture) {} - -void INTERNAL_GL_APIENTRY glGetActiveAtomicCounterBufferivNULL(GLuint program, - GLuint bufferIndex, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetActiveAttribNULL(GLuint program, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLint *size, - GLenum *type, - GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glGetActiveSubroutineNameNULL(GLuint program, - GLenum shadertype, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glGetActiveSubroutineUniformNameNULL(GLuint program, - GLenum shadertype, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glGetActiveSubroutineUniformivNULL(GLuint program, - GLenum shadertype, - GLuint index, - GLenum pname, - GLint *values) -{} - -void INTERNAL_GL_APIENTRY glGetActiveUniformNULL(GLuint program, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLint *size, - GLenum *type, - GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glGetActiveUniformBlockNameNULL(GLuint program, - GLuint uniformBlockIndex, - GLsizei bufSize, - GLsizei *length, - GLchar *uniformBlockName) -{} - -void INTERNAL_GL_APIENTRY glGetActiveUniformBlockivNULL(GLuint program, - GLuint uniformBlockIndex, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetActiveUniformNameNULL(GLuint program, - GLuint uniformIndex, - GLsizei bufSize, - GLsizei *length, - GLchar *uniformName) -{} - -void INTERNAL_GL_APIENTRY glGetActiveUniformsivNULL(GLuint program, - GLsizei uniformCount, - const GLuint *uniformIndices, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetAttachedShadersNULL(GLuint program, - GLsizei maxCount, - GLsizei *count, - GLuint *shaders) -{} - -GLint INTERNAL_GL_APIENTRY glGetAttribLocationNULL(GLuint program, const GLchar *name) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetBooleani_vNULL(GLenum target, GLuint index, GLboolean *data) {} - -void INTERNAL_GL_APIENTRY glGetBooleanvNULL(GLenum pname, GLboolean *data) {} - -void INTERNAL_GL_APIENTRY glGetBufferParameteri64vNULL(GLenum target, GLenum pname, GLint64 *params) -{} - -void INTERNAL_GL_APIENTRY glGetBufferParameterivNULL(GLenum target, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetBufferPointervNULL(GLenum target, GLenum pname, void **params) {} - -void INTERNAL_GL_APIENTRY glGetBufferSubDataNULL(GLenum target, - GLintptr offset, - GLsizeiptr size, - void *data) -{} - -void INTERNAL_GL_APIENTRY glGetCompressedTexImageNULL(GLenum target, GLint level, void *img) {} - -void INTERNAL_GL_APIENTRY glGetCompressedTextureImageNULL(GLuint texture, - GLint level, - GLsizei bufSize, - void *pixels) -{} - -void INTERNAL_GL_APIENTRY glGetCompressedTextureSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLsizei bufSize, - void *pixels) -{} - -GLuint INTERNAL_GL_APIENTRY glGetDebugMessageLogNULL(GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetDoublei_vNULL(GLenum target, GLuint index, GLdouble *data) {} - -void INTERNAL_GL_APIENTRY glGetDoublevNULL(GLenum pname, GLdouble *data) {} - -GLenum INTERNAL_GL_APIENTRY glGetErrorNULL() -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetFenceivNVNULL(GLuint fence, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetFloati_vNULL(GLenum target, GLuint index, GLfloat *data) {} - -void INTERNAL_GL_APIENTRY glGetFloatvNULL(GLenum pname, GLfloat *data) {} - -GLint INTERNAL_GL_APIENTRY glGetFragDataIndexNULL(GLuint program, const GLchar *name) -{ - return static_cast(0); -} - -GLint INTERNAL_GL_APIENTRY glGetFragDataLocationNULL(GLuint program, const GLchar *name) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetFramebufferAttachmentParameterivNULL(GLenum target, - GLenum attachment, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetFramebufferParameterivNULL(GLenum target, - GLenum pname, - GLint *params) -{} - -GLenum INTERNAL_GL_APIENTRY glGetGraphicsResetStatusNULL() -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetInteger64i_vNULL(GLenum target, GLuint index, GLint64 *data) {} - -void INTERNAL_GL_APIENTRY glGetInteger64vNULL(GLenum pname, GLint64 *data) {} - -void INTERNAL_GL_APIENTRY glGetIntegeri_vNULL(GLenum target, GLuint index, GLint *data) {} - -void INTERNAL_GL_APIENTRY glGetIntegervNULL(GLenum pname, GLint *data) {} - -void INTERNAL_GL_APIENTRY glGetInternalformatSampleivNVNULL(GLenum target, - GLenum internalformat, - GLsizei samples, - GLenum pname, - GLsizei count, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetInternalformati64vNULL(GLenum target, - GLenum internalformat, - GLenum pname, - GLsizei count, - GLint64 *params) -{} - -void INTERNAL_GL_APIENTRY glGetInternalformativNULL(GLenum target, - GLenum internalformat, - GLenum pname, - GLsizei count, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetMemoryObjectParameterivEXTNULL(GLuint memoryObject, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetMultisamplefvNULL(GLenum pname, GLuint index, GLfloat *val) {} - -void INTERNAL_GL_APIENTRY glGetNamedBufferParameteri64vNULL(GLuint buffer, - GLenum pname, - GLint64 *params) -{} - -void INTERNAL_GL_APIENTRY glGetNamedBufferParameterivNULL(GLuint buffer, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetNamedBufferPointervNULL(GLuint buffer, GLenum pname, void **params) -{} - -void INTERNAL_GL_APIENTRY glGetNamedBufferSubDataNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - void *data) -{} - -void INTERNAL_GL_APIENTRY glGetNamedFramebufferAttachmentParameterivNULL(GLuint framebuffer, - GLenum attachment, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetNamedFramebufferParameterivNULL(GLuint framebuffer, - GLenum pname, - GLint *param) -{} - -void INTERNAL_GL_APIENTRY glGetNamedRenderbufferParameterivNULL(GLuint renderbuffer, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetObjectLabelNULL(GLenum identifier, - GLuint name, - GLsizei bufSize, - GLsizei *length, - GLchar *label) -{} - -void INTERNAL_GL_APIENTRY glGetObjectPtrLabelNULL(const void *ptr, - GLsizei bufSize, - GLsizei *length, - GLchar *label) -{} - -void INTERNAL_GL_APIENTRY glGetPointervNULL(GLenum pname, void **params) {} - -void INTERNAL_GL_APIENTRY glGetProgramBinaryNULL(GLuint program, - GLsizei bufSize, - GLsizei *length, - GLenum *binaryFormat, - void *binary) -{} - -void INTERNAL_GL_APIENTRY glGetProgramInfoLogNULL(GLuint program, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog) -{} - -void INTERNAL_GL_APIENTRY glGetProgramInterfaceivNULL(GLuint program, - GLenum programInterface, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetProgramPipelineInfoLogNULL(GLuint pipeline, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog) -{} - -void INTERNAL_GL_APIENTRY glGetProgramPipelineivNULL(GLuint pipeline, GLenum pname, GLint *params) -{} - -GLuint INTERNAL_GL_APIENTRY glGetProgramResourceIndexNULL(GLuint program, - GLenum programInterface, - const GLchar *name) -{ - return static_cast(0); -} - -GLint INTERNAL_GL_APIENTRY glGetProgramResourceLocationNULL(GLuint program, - GLenum programInterface, - const GLchar *name) -{ - return static_cast(0); -} - -GLint INTERNAL_GL_APIENTRY glGetProgramResourceLocationIndexNULL(GLuint program, - GLenum programInterface, - const GLchar *name) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetProgramResourceNameNULL(GLuint program, - GLenum programInterface, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glGetProgramResourceivNULL(GLuint program, - GLenum programInterface, - GLuint index, - GLsizei propCount, - const GLenum *props, - GLsizei count, - GLsizei *length, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetProgramStageivNULL(GLuint program, - GLenum shadertype, - GLenum pname, - GLint *values) -{} - -void INTERNAL_GL_APIENTRY glGetProgramivNULL(GLuint program, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetQueryBufferObjecti64vNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset) -{} - -void INTERNAL_GL_APIENTRY glGetQueryBufferObjectivNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset) -{} - -void INTERNAL_GL_APIENTRY glGetQueryBufferObjectui64vNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset) -{} - -void INTERNAL_GL_APIENTRY glGetQueryBufferObjectuivNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset) -{} - -void INTERNAL_GL_APIENTRY glGetQueryIndexedivNULL(GLenum target, - GLuint index, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetQueryObjecti64vNULL(GLuint id, GLenum pname, GLint64 *params) {} - -void INTERNAL_GL_APIENTRY glGetQueryObjectivNULL(GLuint id, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetQueryObjectui64vNULL(GLuint id, GLenum pname, GLuint64 *params) {} - -void INTERNAL_GL_APIENTRY glGetQueryObjectuivNULL(GLuint id, GLenum pname, GLuint *params) {} - -void INTERNAL_GL_APIENTRY glGetQueryivNULL(GLenum target, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetRenderbufferParameterivNULL(GLenum target, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetSamplerParameterIivNULL(GLuint sampler, GLenum pname, GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetSamplerParameterIuivNULL(GLuint sampler, - GLenum pname, - GLuint *params) -{} - -void INTERNAL_GL_APIENTRY glGetSamplerParameterfvNULL(GLuint sampler, GLenum pname, GLfloat *params) -{} - -void INTERNAL_GL_APIENTRY glGetSamplerParameterivNULL(GLuint sampler, GLenum pname, GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetSemaphoreParameterui64vEXTNULL(GLuint semaphore, - GLenum pname, - GLuint64 *params) -{} - -void INTERNAL_GL_APIENTRY glGetShaderInfoLogNULL(GLuint shader, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog) -{} - -void INTERNAL_GL_APIENTRY glGetShaderPrecisionFormatNULL(GLenum shadertype, - GLenum precisiontype, - GLint *range, - GLint *precision) -{} - -void INTERNAL_GL_APIENTRY glGetShaderSourceNULL(GLuint shader, - GLsizei bufSize, - GLsizei *length, - GLchar *source) -{} - -void INTERNAL_GL_APIENTRY glGetShaderivNULL(GLuint shader, GLenum pname, GLint *params) {} - -const GLubyte *INTERNAL_GL_APIENTRY glGetStringNULL(GLenum name) -{ - return static_cast(0); -} - -const GLubyte *INTERNAL_GL_APIENTRY glGetStringiNULL(GLenum name, GLuint index) -{ - return static_cast(0); -} - -GLuint INTERNAL_GL_APIENTRY glGetSubroutineIndexNULL(GLuint program, - GLenum shadertype, - const GLchar *name) -{ - return static_cast(0); -} - -GLint INTERNAL_GL_APIENTRY glGetSubroutineUniformLocationNULL(GLuint program, - GLenum shadertype, - const GLchar *name) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY -glGetSyncivNULL(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values) -{} - -void INTERNAL_GL_APIENTRY -glGetTexImageNULL(GLenum target, GLint level, GLenum format, GLenum type, void *pixels) -{} - -void INTERNAL_GL_APIENTRY glGetTexLevelParameterfvNULL(GLenum target, - GLint level, - GLenum pname, - GLfloat *params) -{} - -void INTERNAL_GL_APIENTRY glGetTexLevelParameterivNULL(GLenum target, - GLint level, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetTexParameterIivNULL(GLenum target, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetTexParameterIuivNULL(GLenum target, GLenum pname, GLuint *params) {} - -void INTERNAL_GL_APIENTRY glGetTexParameterfvNULL(GLenum target, GLenum pname, GLfloat *params) {} - -void INTERNAL_GL_APIENTRY glGetTexParameterivNULL(GLenum target, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetTextureImageNULL(GLuint texture, - GLint level, - GLenum format, - GLenum type, - GLsizei bufSize, - void *pixels) -{} - -void INTERNAL_GL_APIENTRY glGetTextureLevelParameterfvNULL(GLuint texture, - GLint level, - GLenum pname, - GLfloat *params) -{} - -void INTERNAL_GL_APIENTRY glGetTextureLevelParameterivNULL(GLuint texture, - GLint level, - GLenum pname, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetTextureParameterIivNULL(GLuint texture, GLenum pname, GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetTextureParameterIuivNULL(GLuint texture, - GLenum pname, - GLuint *params) -{} - -void INTERNAL_GL_APIENTRY glGetTextureParameterfvNULL(GLuint texture, GLenum pname, GLfloat *params) -{} - -void INTERNAL_GL_APIENTRY glGetTextureParameterivNULL(GLuint texture, GLenum pname, GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetTextureSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - GLsizei bufSize, - void *pixels) -{} - -void INTERNAL_GL_APIENTRY glGetTransformFeedbackVaryingNULL(GLuint program, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLsizei *size, - GLenum *type, - GLchar *name) -{} - -void INTERNAL_GL_APIENTRY glGetTransformFeedbacki64_vNULL(GLuint xfb, - GLenum pname, - GLuint index, - GLint64 *param) -{} - -void INTERNAL_GL_APIENTRY glGetTransformFeedbacki_vNULL(GLuint xfb, - GLenum pname, - GLuint index, - GLint *param) -{} - -void INTERNAL_GL_APIENTRY glGetTransformFeedbackivNULL(GLuint xfb, GLenum pname, GLint *param) {} - -GLuint INTERNAL_GL_APIENTRY glGetUniformBlockIndexNULL(GLuint program, - const GLchar *uniformBlockName) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetUniformIndicesNULL(GLuint program, - GLsizei uniformCount, - const GLchar *const *uniformNames, - GLuint *uniformIndices) -{} - -GLint INTERNAL_GL_APIENTRY glGetUniformLocationNULL(GLuint program, const GLchar *name) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glGetUniformSubroutineuivNULL(GLenum shadertype, - GLint location, - GLuint *params) -{} - -void INTERNAL_GL_APIENTRY glGetUniformdvNULL(GLuint program, GLint location, GLdouble *params) {} - -void INTERNAL_GL_APIENTRY glGetUniformfvNULL(GLuint program, GLint location, GLfloat *params) {} - -void INTERNAL_GL_APIENTRY glGetUniformivNULL(GLuint program, GLint location, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetUniformuivNULL(GLuint program, GLint location, GLuint *params) {} - -void INTERNAL_GL_APIENTRY glGetUnsignedBytei_vEXTNULL(GLenum target, GLuint index, GLubyte *data) {} - -void INTERNAL_GL_APIENTRY glGetUnsignedBytevEXTNULL(GLenum pname, GLubyte *data) {} - -void INTERNAL_GL_APIENTRY glGetVertexArrayIndexed64ivNULL(GLuint vaobj, - GLuint index, - GLenum pname, - GLint64 *param) -{} - -void INTERNAL_GL_APIENTRY glGetVertexArrayIndexedivNULL(GLuint vaobj, - GLuint index, - GLenum pname, - GLint *param) -{} - -void INTERNAL_GL_APIENTRY glGetVertexArrayivNULL(GLuint vaobj, GLenum pname, GLint *param) {} - -void INTERNAL_GL_APIENTRY glGetVertexAttribIivNULL(GLuint index, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetVertexAttribIuivNULL(GLuint index, GLenum pname, GLuint *params) {} - -void INTERNAL_GL_APIENTRY glGetVertexAttribLdvNULL(GLuint index, GLenum pname, GLdouble *params) {} - -void INTERNAL_GL_APIENTRY glGetVertexAttribPointervNULL(GLuint index, GLenum pname, void **pointer) -{} - -void INTERNAL_GL_APIENTRY glGetVertexAttribdvNULL(GLuint index, GLenum pname, GLdouble *params) {} - -void INTERNAL_GL_APIENTRY glGetVertexAttribfvNULL(GLuint index, GLenum pname, GLfloat *params) {} - -void INTERNAL_GL_APIENTRY glGetVertexAttribivNULL(GLuint index, GLenum pname, GLint *params) {} - -void INTERNAL_GL_APIENTRY glGetnCompressedTexImageNULL(GLenum target, - GLint lod, - GLsizei bufSize, - void *pixels) -{} - -void INTERNAL_GL_APIENTRY glGetnTexImageNULL(GLenum target, - GLint level, - GLenum format, - GLenum type, - GLsizei bufSize, - void *pixels) -{} - -void INTERNAL_GL_APIENTRY glGetnUniformdvNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLdouble *params) -{} - -void INTERNAL_GL_APIENTRY glGetnUniformfvNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLfloat *params) -{} - -void INTERNAL_GL_APIENTRY glGetnUniformivNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLint *params) -{} - -void INTERNAL_GL_APIENTRY glGetnUniformuivNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLuint *params) -{} - -void INTERNAL_GL_APIENTRY glHintNULL(GLenum target, GLenum mode) {} - -void INTERNAL_GL_APIENTRY glImportMemoryFdEXTNULL(GLuint memory, - GLuint64 size, - GLenum handleType, - GLint fd) -{} - -void INTERNAL_GL_APIENTRY glImportMemoryWin32HandleEXTNULL(GLuint memory, - GLuint64 size, - GLenum handleType, - void *handle) -{} - -void INTERNAL_GL_APIENTRY glImportMemoryWin32NameEXTNULL(GLuint memory, - GLuint64 size, - GLenum handleType, - const void *name) -{} - -void INTERNAL_GL_APIENTRY glImportSemaphoreFdEXTNULL(GLuint semaphore, GLenum handleType, GLint fd) -{} - -void INTERNAL_GL_APIENTRY glImportSemaphoreWin32HandleEXTNULL(GLuint semaphore, - GLenum handleType, - void *handle) -{} - -void INTERNAL_GL_APIENTRY glImportSemaphoreWin32NameEXTNULL(GLuint semaphore, - GLenum handleType, - const void *name) -{} - -void INTERNAL_GL_APIENTRY glInsertEventMarkerEXTNULL(GLsizei length, const GLchar *marker) {} - -void INTERNAL_GL_APIENTRY glInvalidateBufferDataNULL(GLuint buffer) {} - -void INTERNAL_GL_APIENTRY glInvalidateBufferSubDataNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr length) -{} - -void INTERNAL_GL_APIENTRY glInvalidateFramebufferNULL(GLenum target, - GLsizei numAttachments, - const GLenum *attachments) -{} - -void INTERNAL_GL_APIENTRY glInvalidateNamedFramebufferDataNULL(GLuint framebuffer, - GLsizei numAttachments, - const GLenum *attachments) -{} - -void INTERNAL_GL_APIENTRY glInvalidateNamedFramebufferSubDataNULL(GLuint framebuffer, - GLsizei numAttachments, - const GLenum *attachments, - GLint x, - GLint y, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glInvalidateSubFramebufferNULL(GLenum target, - GLsizei numAttachments, - const GLenum *attachments, - GLint x, - GLint y, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glInvalidateTexImageNULL(GLuint texture, GLint level) {} - -void INTERNAL_GL_APIENTRY glInvalidateTexSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth) -{} - -GLboolean INTERNAL_GL_APIENTRY glIsBufferNULL(GLuint buffer) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsEnabledNULL(GLenum cap) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsEnablediNULL(GLenum target, GLuint index) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsFenceNVNULL(GLuint fence) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsFramebufferNULL(GLuint framebuffer) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsMemoryObjectEXTNULL(GLuint memoryObject) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsProgramNULL(GLuint program) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsProgramPipelineNULL(GLuint pipeline) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsQueryNULL(GLuint id) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsRenderbufferNULL(GLuint renderbuffer) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsSamplerNULL(GLuint sampler) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsSemaphoreEXTNULL(GLuint semaphore) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsShaderNULL(GLuint shader) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsSyncNULL(GLsync sync) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsTextureNULL(GLuint texture) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsTransformFeedbackNULL(GLuint id) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glIsVertexArrayNULL(GLuint array) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glLineWidthNULL(GLfloat width) {} - -void INTERNAL_GL_APIENTRY glLinkProgramNULL(GLuint program) {} - -void INTERNAL_GL_APIENTRY glLogicOpNULL(GLenum opcode) {} - -void *INTERNAL_GL_APIENTRY glMapBufferNULL(GLenum target, GLenum access) -{ - return static_cast(0); -} - -void *INTERNAL_GL_APIENTRY glMapBufferRangeNULL(GLenum target, - GLintptr offset, - GLsizeiptr length, - GLbitfield access) -{ - return static_cast(0); -} - -void *INTERNAL_GL_APIENTRY glMapNamedBufferNULL(GLuint buffer, GLenum access) -{ - return static_cast(0); -} - -void *INTERNAL_GL_APIENTRY glMapNamedBufferRangeNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr length, - GLbitfield access) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsARBNULL(GLuint count) {} - -void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsKHRNULL(GLuint count) {} - -void INTERNAL_GL_APIENTRY glMemoryBarrierNULL(GLbitfield barriers) {} - -void INTERNAL_GL_APIENTRY glMemoryBarrierByRegionNULL(GLbitfield barriers) {} - -void INTERNAL_GL_APIENTRY glMemoryObjectParameterivEXTNULL(GLuint memoryObject, - GLenum pname, - const GLint *params) -{} - -void INTERNAL_GL_APIENTRY glMinSampleShadingNULL(GLfloat value) {} - -void INTERNAL_GL_APIENTRY glMultiDrawArraysNULL(GLenum mode, - const GLint *first, - const GLsizei *count, - GLsizei drawcount) -{} - -void INTERNAL_GL_APIENTRY glMultiDrawArraysIndirectNULL(GLenum mode, - const void *indirect, - GLsizei drawcount, - GLsizei stride) -{} - -void INTERNAL_GL_APIENTRY glMultiDrawElementsNULL(GLenum mode, - const GLsizei *count, - GLenum type, - const void *const *indices, - GLsizei drawcount) -{} - -void INTERNAL_GL_APIENTRY glMultiDrawElementsBaseVertexNULL(GLenum mode, - const GLsizei *count, - GLenum type, - const void *const *indices, - GLsizei drawcount, - const GLint *basevertex) -{} - -void INTERNAL_GL_APIENTRY glMultiDrawElementsIndirectNULL(GLenum mode, - GLenum type, - const void *indirect, - GLsizei drawcount, - GLsizei stride) -{} - -void INTERNAL_GL_APIENTRY glNamedBufferDataNULL(GLuint buffer, - GLsizeiptr size, - const void *data, - GLenum usage) -{} - -void INTERNAL_GL_APIENTRY glNamedBufferStorageNULL(GLuint buffer, - GLsizeiptr size, - const void *data, - GLbitfield flags) -{} - -void INTERNAL_GL_APIENTRY glNamedBufferStorageMemEXTNULL(GLuint buffer, - GLsizeiptr size, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glNamedBufferSubDataNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - const void *data) -{} - -void INTERNAL_GL_APIENTRY glNamedFramebufferDrawBufferNULL(GLuint framebuffer, GLenum buf) {} - -void INTERNAL_GL_APIENTRY glNamedFramebufferDrawBuffersNULL(GLuint framebuffer, - GLsizei n, - const GLenum *bufs) -{} - -void INTERNAL_GL_APIENTRY glNamedFramebufferParameteriNULL(GLuint framebuffer, - GLenum pname, - GLint param) -{} - -void INTERNAL_GL_APIENTRY glNamedFramebufferReadBufferNULL(GLuint framebuffer, GLenum src) {} - -void INTERNAL_GL_APIENTRY glNamedFramebufferRenderbufferNULL(GLuint framebuffer, - GLenum attachment, - GLenum renderbuffertarget, - GLuint renderbuffer) -{} - -void INTERNAL_GL_APIENTRY glNamedFramebufferTextureNULL(GLuint framebuffer, - GLenum attachment, - GLuint texture, - GLint level) -{} - -void INTERNAL_GL_APIENTRY glNamedFramebufferTextureLayerNULL(GLuint framebuffer, - GLenum attachment, - GLuint texture, - GLint level, - GLint layer) -{} - -void INTERNAL_GL_APIENTRY glNamedRenderbufferStorageNULL(GLuint renderbuffer, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glNamedRenderbufferStorageMultisampleNULL(GLuint renderbuffer, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glObjectLabelNULL(GLenum identifier, - GLuint name, - GLsizei length, - const GLchar *label) -{} - -void INTERNAL_GL_APIENTRY glObjectPtrLabelNULL(const void *ptr, GLsizei length, const GLchar *label) -{} - -void INTERNAL_GL_APIENTRY glPatchParameterfvNULL(GLenum pname, const GLfloat *values) {} - -void INTERNAL_GL_APIENTRY glPatchParameteriNULL(GLenum pname, GLint value) {} - -void INTERNAL_GL_APIENTRY glPauseTransformFeedbackNULL() {} - -void INTERNAL_GL_APIENTRY glPixelStorefNULL(GLenum pname, GLfloat param) {} - -void INTERNAL_GL_APIENTRY glPixelStoreiNULL(GLenum pname, GLint param) {} - -void INTERNAL_GL_APIENTRY glPointParameterfNULL(GLenum pname, GLfloat param) {} - -void INTERNAL_GL_APIENTRY glPointParameterfvNULL(GLenum pname, const GLfloat *params) {} - -void INTERNAL_GL_APIENTRY glPointParameteriNULL(GLenum pname, GLint param) {} - -void INTERNAL_GL_APIENTRY glPointParameterivNULL(GLenum pname, const GLint *params) {} - -void INTERNAL_GL_APIENTRY glPointSizeNULL(GLfloat size) {} - -void INTERNAL_GL_APIENTRY glPolygonModeNULL(GLenum face, GLenum mode) {} - -void INTERNAL_GL_APIENTRY glPolygonModeNVNULL(GLenum face, GLenum mode) {} - -void INTERNAL_GL_APIENTRY glPolygonOffsetNULL(GLfloat factor, GLfloat units) {} - -void INTERNAL_GL_APIENTRY glPolygonOffsetClampEXTNULL(GLfloat factor, GLfloat units, GLfloat clamp) -{} - -void INTERNAL_GL_APIENTRY glPopDebugGroupNULL() {} - -void INTERNAL_GL_APIENTRY glPopGroupMarkerEXTNULL() {} - -void INTERNAL_GL_APIENTRY glPrimitiveBoundingBoxNULL(GLfloat minX, - GLfloat minY, - GLfloat minZ, - GLfloat minW, - GLfloat maxX, - GLfloat maxY, - GLfloat maxZ, - GLfloat maxW) -{} - -void INTERNAL_GL_APIENTRY glPrimitiveRestartIndexNULL(GLuint index) {} - -void INTERNAL_GL_APIENTRY glProgramBinaryNULL(GLuint program, - GLenum binaryFormat, - const void *binary, - GLsizei length) -{} - -void INTERNAL_GL_APIENTRY glProgramParameteriNULL(GLuint program, GLenum pname, GLint value) {} - -void INTERNAL_GL_APIENTRY glProgramUniform1dNULL(GLuint program, GLint location, GLdouble v0) {} - -void INTERNAL_GL_APIENTRY glProgramUniform1dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform1fNULL(GLuint program, GLint location, GLfloat v0) {} - -void INTERNAL_GL_APIENTRY glProgramUniform1fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform1iNULL(GLuint program, GLint location, GLint v0) {} - -void INTERNAL_GL_APIENTRY glProgramUniform1ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform1uiNULL(GLuint program, GLint location, GLuint v0) {} - -void INTERNAL_GL_APIENTRY glProgramUniform1uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2dNULL(GLuint program, - GLint location, - GLdouble v0, - GLdouble v1) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2fNULL(GLuint program, - GLint location, - GLfloat v0, - GLfloat v1) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2iNULL(GLuint program, GLint location, GLint v0, GLint v1) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2uiNULL(GLuint program, - GLint location, - GLuint v0, - GLuint v1) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform2uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY -glProgramUniform3dNULL(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform3dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY -glProgramUniform3fNULL(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform3fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY -glProgramUniform3iNULL(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform3ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value) -{} - -void INTERNAL_GL_APIENTRY -glProgramUniform3uiNULL(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform3uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform4dNULL(GLuint program, - GLint location, - GLdouble v0, - GLdouble v1, - GLdouble v2, - GLdouble v3) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform4dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform4fNULL(GLuint program, - GLint location, - GLfloat v0, - GLfloat v1, - GLfloat v2, - GLfloat v3) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform4fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY -glProgramUniform4iNULL(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform4ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value) -{} - -void INTERNAL_GL_APIENTRY -glProgramUniform4uiNULL(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) -{} - -void INTERNAL_GL_APIENTRY glProgramUniform4uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x3dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x3fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x4dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x4fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x2dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x2fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x4dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x4fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x2dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x2fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x3dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x3fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glProvokingVertexNULL(GLenum mode) {} - -void INTERNAL_GL_APIENTRY glPushDebugGroupNULL(GLenum source, - GLuint id, - GLsizei length, - const GLchar *message) -{} - -void INTERNAL_GL_APIENTRY glPushGroupMarkerEXTNULL(GLsizei length, const GLchar *marker) {} - -void INTERNAL_GL_APIENTRY glQueryCounterNULL(GLuint id, GLenum target) {} - -void INTERNAL_GL_APIENTRY glReadBufferNULL(GLenum src) {} - -void INTERNAL_GL_APIENTRY glReadPixelsNULL(GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - void *pixels) -{} - -void INTERNAL_GL_APIENTRY glReadnPixelsNULL(GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLsizei bufSize, - void *data) -{} - -void INTERNAL_GL_APIENTRY glReleaseShaderCompilerNULL() {} - -void INTERNAL_GL_APIENTRY glRenderbufferStorageNULL(GLenum target, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glRenderbufferStorageMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glRenderbufferStorageMultisampleEXTNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glRenderbufferStorageMultisampleIMGNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glResumeTransformFeedbackNULL() {} - -void INTERNAL_GL_APIENTRY glSampleCoverageNULL(GLfloat value, GLboolean invert) {} - -void INTERNAL_GL_APIENTRY glSampleMaskiNULL(GLuint maskNumber, GLbitfield mask) {} - -void INTERNAL_GL_APIENTRY glSamplerParameterIivNULL(GLuint sampler, - GLenum pname, - const GLint *param) -{} - -void INTERNAL_GL_APIENTRY glSamplerParameterIuivNULL(GLuint sampler, - GLenum pname, - const GLuint *param) -{} - -void INTERNAL_GL_APIENTRY glSamplerParameterfNULL(GLuint sampler, GLenum pname, GLfloat param) {} - -void INTERNAL_GL_APIENTRY glSamplerParameterfvNULL(GLuint sampler, - GLenum pname, - const GLfloat *param) -{} - -void INTERNAL_GL_APIENTRY glSamplerParameteriNULL(GLuint sampler, GLenum pname, GLint param) {} - -void INTERNAL_GL_APIENTRY glSamplerParameterivNULL(GLuint sampler, GLenum pname, const GLint *param) -{} - -void INTERNAL_GL_APIENTRY glScissorNULL(GLint x, GLint y, GLsizei width, GLsizei height) {} - -void INTERNAL_GL_APIENTRY glScissorArrayvNULL(GLuint first, GLsizei count, const GLint *v) {} - -void INTERNAL_GL_APIENTRY -glScissorIndexedNULL(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glScissorIndexedvNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY glSemaphoreParameterui64vEXTNULL(GLuint semaphore, - GLenum pname, - const GLuint64 *params) -{} - -void INTERNAL_GL_APIENTRY glSetFenceNVNULL(GLuint fence, GLenum condition) {} - -void INTERNAL_GL_APIENTRY glShaderBinaryNULL(GLsizei count, - const GLuint *shaders, - GLenum binaryFormat, - const void *binary, - GLsizei length) -{} - -void INTERNAL_GL_APIENTRY glShaderSourceNULL(GLuint shader, - GLsizei count, - const GLchar *const *string, - const GLint *length) -{} - -void INTERNAL_GL_APIENTRY glShaderStorageBlockBindingNULL(GLuint program, - GLuint storageBlockIndex, - GLuint storageBlockBinding) -{} - -void INTERNAL_GL_APIENTRY glSignalSemaphoreEXTNULL(GLuint semaphore, - GLuint numBufferBarriers, - const GLuint *buffers, - GLuint numTextureBarriers, - const GLuint *textures, - const GLenum *dstLayouts) -{} - -void INTERNAL_GL_APIENTRY -glStartTilingQCOMNULL(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) -{} - -void INTERNAL_GL_APIENTRY glStencilFuncNULL(GLenum func, GLint ref, GLuint mask) {} - -void INTERNAL_GL_APIENTRY glStencilFuncSeparateNULL(GLenum face, - GLenum func, - GLint ref, - GLuint mask) -{} - -void INTERNAL_GL_APIENTRY glStencilMaskNULL(GLuint mask) {} - -void INTERNAL_GL_APIENTRY glStencilMaskSeparateNULL(GLenum face, GLuint mask) {} - -void INTERNAL_GL_APIENTRY glStencilOpNULL(GLenum fail, GLenum zfail, GLenum zpass) {} - -void INTERNAL_GL_APIENTRY glStencilOpSeparateNULL(GLenum face, - GLenum sfail, - GLenum dpfail, - GLenum dppass) -{} - -GLboolean INTERNAL_GL_APIENTRY glTestFenceNVNULL(GLuint fence) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glTexBufferNULL(GLenum target, GLenum internalformat, GLuint buffer) {} - -void INTERNAL_GL_APIENTRY glTexBufferEXTNULL(GLenum target, GLenum internalformat, GLuint buffer) {} - -void INTERNAL_GL_APIENTRY glTexBufferOESNULL(GLenum target, GLenum internalformat, GLuint buffer) {} - -void INTERNAL_GL_APIENTRY glTexBufferRangeNULL(GLenum target, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glTexBufferRangeEXTNULL(GLenum target, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glTexBufferRangeOESNULL(GLenum target, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glTexImage1DNULL(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLint border, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTexImage2DNULL(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTexImage2DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLboolean fixedsamplelocations) -{} - -void INTERNAL_GL_APIENTRY glTexImage3DNULL(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTexImage3DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedsamplelocations) -{} - -void INTERNAL_GL_APIENTRY glTexParameterIivNULL(GLenum target, GLenum pname, const GLint *params) {} - -void INTERNAL_GL_APIENTRY glTexParameterIuivNULL(GLenum target, GLenum pname, const GLuint *params) -{} - -void INTERNAL_GL_APIENTRY glTexParameterfNULL(GLenum target, GLenum pname, GLfloat param) {} - -void INTERNAL_GL_APIENTRY glTexParameterfvNULL(GLenum target, GLenum pname, const GLfloat *params) -{} - -void INTERNAL_GL_APIENTRY glTexParameteriNULL(GLenum target, GLenum pname, GLint param) {} - -void INTERNAL_GL_APIENTRY glTexParameterivNULL(GLenum target, GLenum pname, const GLint *params) {} - -void INTERNAL_GL_APIENTRY glTexStorage1DNULL(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width) -{} - -void INTERNAL_GL_APIENTRY glTexStorage2DNULL(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glTexStorage2DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLboolean fixedsamplelocations) -{} - -void INTERNAL_GL_APIENTRY glTexStorage3DNULL(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth) -{} - -void INTERNAL_GL_APIENTRY glTexStorage3DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedsamplelocations) -{} - -void INTERNAL_GL_APIENTRY glTexStorageMem2DEXTNULL(GLenum target, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTexStorageMem2DMultisampleEXTNULL(GLenum target, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTexStorageMem3DEXTNULL(GLenum target, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTexStorageMem3DMultisampleEXTNULL(GLenum target, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTexSubImage1DNULL(GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTexSubImage2DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTexSubImage3DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTextureBarrierNULL() {} - -void INTERNAL_GL_APIENTRY glTextureBufferNULL(GLuint texture, GLenum internalformat, GLuint buffer) -{} - -void INTERNAL_GL_APIENTRY glTextureBufferRangeNULL(GLuint texture, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glTextureParameterIivNULL(GLuint texture, - GLenum pname, - const GLint *params) -{} - -void INTERNAL_GL_APIENTRY glTextureParameterIuivNULL(GLuint texture, - GLenum pname, - const GLuint *params) -{} - -void INTERNAL_GL_APIENTRY glTextureParameterfNULL(GLuint texture, GLenum pname, GLfloat param) {} - -void INTERNAL_GL_APIENTRY glTextureParameterfvNULL(GLuint texture, - GLenum pname, - const GLfloat *param) -{} - -void INTERNAL_GL_APIENTRY glTextureParameteriNULL(GLuint texture, GLenum pname, GLint param) {} - -void INTERNAL_GL_APIENTRY glTextureParameterivNULL(GLuint texture, GLenum pname, const GLint *param) -{} - -void INTERNAL_GL_APIENTRY glTextureStorage1DNULL(GLuint texture, - GLsizei levels, - GLenum internalformat, - GLsizei width) -{} - -void INTERNAL_GL_APIENTRY glTextureStorage2DNULL(GLuint texture, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height) -{} - -void INTERNAL_GL_APIENTRY glTextureStorage2DMultisampleNULL(GLuint texture, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLboolean fixedsamplelocations) -{} - -void INTERNAL_GL_APIENTRY glTextureStorage3DNULL(GLuint texture, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth) -{} - -void INTERNAL_GL_APIENTRY glTextureStorage3DMultisampleNULL(GLuint texture, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedsamplelocations) -{} - -void INTERNAL_GL_APIENTRY glTextureStorageMem2DEXTNULL(GLuint texture, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTextureStorageMem2DMultisampleEXTNULL(GLuint texture, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTextureStorageMem3DEXTNULL(GLuint texture, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTextureStorageMem3DMultisampleEXTNULL(GLuint texture, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset) -{} - -void INTERNAL_GL_APIENTRY glTextureSubImage1DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTextureSubImage2DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTextureSubImage3DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *pixels) -{} - -void INTERNAL_GL_APIENTRY glTextureViewNULL(GLuint texture, - GLenum target, - GLuint origtexture, - GLenum internalformat, - GLuint minlevel, - GLuint numlevels, - GLuint minlayer, - GLuint numlayers) -{} - -void INTERNAL_GL_APIENTRY glTransformFeedbackBufferBaseNULL(GLuint xfb, GLuint index, GLuint buffer) -{} - -void INTERNAL_GL_APIENTRY glTransformFeedbackBufferRangeNULL(GLuint xfb, - GLuint index, - GLuint buffer, - GLintptr offset, - GLsizeiptr size) -{} - -void INTERNAL_GL_APIENTRY glTransformFeedbackVaryingsNULL(GLuint program, - GLsizei count, - const GLchar *const *varyings, - GLenum bufferMode) -{} - -void INTERNAL_GL_APIENTRY glUniform1dNULL(GLint location, GLdouble x) {} - -void INTERNAL_GL_APIENTRY glUniform1dvNULL(GLint location, GLsizei count, const GLdouble *value) {} - -void INTERNAL_GL_APIENTRY glUniform1fNULL(GLint location, GLfloat v0) {} - -void INTERNAL_GL_APIENTRY glUniform1fvNULL(GLint location, GLsizei count, const GLfloat *value) {} - -void INTERNAL_GL_APIENTRY glUniform1iNULL(GLint location, GLint v0) {} - -void INTERNAL_GL_APIENTRY glUniform1ivNULL(GLint location, GLsizei count, const GLint *value) {} - -void INTERNAL_GL_APIENTRY glUniform1uiNULL(GLint location, GLuint v0) {} - -void INTERNAL_GL_APIENTRY glUniform1uivNULL(GLint location, GLsizei count, const GLuint *value) {} - -void INTERNAL_GL_APIENTRY glUniform2dNULL(GLint location, GLdouble x, GLdouble y) {} - -void INTERNAL_GL_APIENTRY glUniform2dvNULL(GLint location, GLsizei count, const GLdouble *value) {} - -void INTERNAL_GL_APIENTRY glUniform2fNULL(GLint location, GLfloat v0, GLfloat v1) {} - -void INTERNAL_GL_APIENTRY glUniform2fvNULL(GLint location, GLsizei count, const GLfloat *value) {} - -void INTERNAL_GL_APIENTRY glUniform2iNULL(GLint location, GLint v0, GLint v1) {} - -void INTERNAL_GL_APIENTRY glUniform2ivNULL(GLint location, GLsizei count, const GLint *value) {} - -void INTERNAL_GL_APIENTRY glUniform2uiNULL(GLint location, GLuint v0, GLuint v1) {} - -void INTERNAL_GL_APIENTRY glUniform2uivNULL(GLint location, GLsizei count, const GLuint *value) {} - -void INTERNAL_GL_APIENTRY glUniform3dNULL(GLint location, GLdouble x, GLdouble y, GLdouble z) {} - -void INTERNAL_GL_APIENTRY glUniform3dvNULL(GLint location, GLsizei count, const GLdouble *value) {} - -void INTERNAL_GL_APIENTRY glUniform3fNULL(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {} - -void INTERNAL_GL_APIENTRY glUniform3fvNULL(GLint location, GLsizei count, const GLfloat *value) {} - -void INTERNAL_GL_APIENTRY glUniform3iNULL(GLint location, GLint v0, GLint v1, GLint v2) {} - -void INTERNAL_GL_APIENTRY glUniform3ivNULL(GLint location, GLsizei count, const GLint *value) {} - -void INTERNAL_GL_APIENTRY glUniform3uiNULL(GLint location, GLuint v0, GLuint v1, GLuint v2) {} - -void INTERNAL_GL_APIENTRY glUniform3uivNULL(GLint location, GLsizei count, const GLuint *value) {} - -void INTERNAL_GL_APIENTRY -glUniform4dNULL(GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{} - -void INTERNAL_GL_APIENTRY glUniform4dvNULL(GLint location, GLsizei count, const GLdouble *value) {} - -void INTERNAL_GL_APIENTRY -glUniform4fNULL(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) -{} - -void INTERNAL_GL_APIENTRY glUniform4fvNULL(GLint location, GLsizei count, const GLfloat *value) {} - -void INTERNAL_GL_APIENTRY glUniform4iNULL(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {} - -void INTERNAL_GL_APIENTRY glUniform4ivNULL(GLint location, GLsizei count, const GLint *value) {} - -void INTERNAL_GL_APIENTRY -glUniform4uiNULL(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) -{} - -void INTERNAL_GL_APIENTRY glUniform4uivNULL(GLint location, GLsizei count, const GLuint *value) {} - -void INTERNAL_GL_APIENTRY glUniformBlockBindingNULL(GLuint program, - GLuint uniformBlockIndex, - GLuint uniformBlockBinding) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix2dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix2fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix2x3dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix2x3fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix2x4dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix2x4fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix3dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix3fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix3x2dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix3x2fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix3x4dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix3x4fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix4dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix4fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix4x2dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix4x2fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix4x3dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value) -{} - -void INTERNAL_GL_APIENTRY glUniformMatrix4x3fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value) -{} - -void INTERNAL_GL_APIENTRY glUniformSubroutinesuivNULL(GLenum shadertype, - GLsizei count, - const GLuint *indices) -{} - -GLboolean INTERNAL_GL_APIENTRY glUnmapBufferNULL(GLenum target) -{ - return static_cast(0); -} - -GLboolean INTERNAL_GL_APIENTRY glUnmapNamedBufferNULL(GLuint buffer) -{ - return static_cast(0); -} - -void INTERNAL_GL_APIENTRY glUseProgramNULL(GLuint program) {} - -void INTERNAL_GL_APIENTRY glUseProgramStagesNULL(GLuint pipeline, GLbitfield stages, GLuint program) -{} - -void INTERNAL_GL_APIENTRY glValidateProgramNULL(GLuint program) {} - -void INTERNAL_GL_APIENTRY glValidateProgramPipelineNULL(GLuint pipeline) {} - -void INTERNAL_GL_APIENTRY glVertexArrayAttribBindingNULL(GLuint vaobj, - GLuint attribindex, - GLuint bindingindex) -{} - -void INTERNAL_GL_APIENTRY glVertexArrayAttribFormatNULL(GLuint vaobj, - GLuint attribindex, - GLint size, - GLenum type, - GLboolean normalized, - GLuint relativeoffset) -{} - -void INTERNAL_GL_APIENTRY glVertexArrayAttribIFormatNULL(GLuint vaobj, - GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset) -{} - -void INTERNAL_GL_APIENTRY glVertexArrayAttribLFormatNULL(GLuint vaobj, - GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset) -{} - -void INTERNAL_GL_APIENTRY glVertexArrayBindingDivisorNULL(GLuint vaobj, - GLuint bindingindex, - GLuint divisor) -{} - -void INTERNAL_GL_APIENTRY glVertexArrayElementBufferNULL(GLuint vaobj, GLuint buffer) {} - -void INTERNAL_GL_APIENTRY glVertexArrayVertexBufferNULL(GLuint vaobj, - GLuint bindingindex, - GLuint buffer, - GLintptr offset, - GLsizei stride) -{} - -void INTERNAL_GL_APIENTRY glVertexArrayVertexBuffersNULL(GLuint vaobj, - GLuint first, - GLsizei count, - const GLuint *buffers, - const GLintptr *offsets, - const GLsizei *strides) -{} - -void INTERNAL_GL_APIENTRY glVertexAttrib1dNULL(GLuint index, GLdouble x) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib1dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib1fNULL(GLuint index, GLfloat x) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib1fvNULL(GLuint index, const GLfloat *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib1sNULL(GLuint index, GLshort x) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib1svNULL(GLuint index, const GLshort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib2dNULL(GLuint index, GLdouble x, GLdouble y) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib2dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib2fNULL(GLuint index, GLfloat x, GLfloat y) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib2fvNULL(GLuint index, const GLfloat *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib2sNULL(GLuint index, GLshort x, GLshort y) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib2svNULL(GLuint index, const GLshort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib3dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib3dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib3fNULL(GLuint index, GLfloat x, GLfloat y, GLfloat z) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib3fvNULL(GLuint index, const GLfloat *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib3sNULL(GLuint index, GLshort x, GLshort y, GLshort z) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib3svNULL(GLuint index, const GLshort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4NbvNULL(GLuint index, const GLbyte *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4NivNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4NsvNULL(GLuint index, const GLshort *v) {} - -void INTERNAL_GL_APIENTRY -glVertexAttrib4NubNULL(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) -{} - -void INTERNAL_GL_APIENTRY glVertexAttrib4NubvNULL(GLuint index, const GLubyte *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4NuivNULL(GLuint index, const GLuint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4NusvNULL(GLuint index, const GLushort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4bvNULL(GLuint index, const GLbyte *v) {} - -void INTERNAL_GL_APIENTRY -glVertexAttrib4dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{} - -void INTERNAL_GL_APIENTRY glVertexAttrib4dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY -glVertexAttrib4fNULL(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{} - -void INTERNAL_GL_APIENTRY glVertexAttrib4fvNULL(GLuint index, const GLfloat *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4ivNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY -glVertexAttrib4sNULL(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) -{} - -void INTERNAL_GL_APIENTRY glVertexAttrib4svNULL(GLuint index, const GLshort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4ubvNULL(GLuint index, const GLubyte *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4uivNULL(GLuint index, const GLuint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttrib4usvNULL(GLuint index, const GLushort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribBindingNULL(GLuint attribindex, GLuint bindingindex) {} - -void INTERNAL_GL_APIENTRY glVertexAttribDivisorNULL(GLuint index, GLuint divisor) {} - -void INTERNAL_GL_APIENTRY glVertexAttribFormatNULL(GLuint attribindex, - GLint size, - GLenum type, - GLboolean normalized, - GLuint relativeoffset) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribI1iNULL(GLuint index, GLint x) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI1ivNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI1uiNULL(GLuint index, GLuint x) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI1uivNULL(GLuint index, const GLuint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI2iNULL(GLuint index, GLint x, GLint y) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI2ivNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI2uiNULL(GLuint index, GLuint x, GLuint y) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI2uivNULL(GLuint index, const GLuint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI3iNULL(GLuint index, GLint x, GLint y, GLint z) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI3ivNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI3uiNULL(GLuint index, GLuint x, GLuint y, GLuint z) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI3uivNULL(GLuint index, const GLuint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI4bvNULL(GLuint index, const GLbyte *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI4iNULL(GLuint index, GLint x, GLint y, GLint z, GLint w) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI4ivNULL(GLuint index, const GLint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI4svNULL(GLuint index, const GLshort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI4ubvNULL(GLuint index, const GLubyte *v) {} - -void INTERNAL_GL_APIENTRY -glVertexAttribI4uiNULL(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribI4uivNULL(GLuint index, const GLuint *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribI4usvNULL(GLuint index, const GLushort *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribIFormatNULL(GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribIPointerNULL(GLuint index, - GLint size, - GLenum type, - GLsizei stride, - const void *pointer) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribL1dNULL(GLuint index, GLdouble x) {} - -void INTERNAL_GL_APIENTRY glVertexAttribL1dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribL2dNULL(GLuint index, GLdouble x, GLdouble y) {} - -void INTERNAL_GL_APIENTRY glVertexAttribL2dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribL3dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z) {} - -void INTERNAL_GL_APIENTRY glVertexAttribL3dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY -glVertexAttribL4dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribL4dvNULL(GLuint index, const GLdouble *v) {} - -void INTERNAL_GL_APIENTRY glVertexAttribLFormatNULL(GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribLPointerNULL(GLuint index, - GLint size, - GLenum type, - GLsizei stride, - const void *pointer) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP1uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP1uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP2uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP2uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP3uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP3uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP4uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribP4uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value) -{} - -void INTERNAL_GL_APIENTRY glVertexAttribPointerNULL(GLuint index, - GLint size, - GLenum type, - GLboolean normalized, - GLsizei stride, - const void *pointer) -{} - -void INTERNAL_GL_APIENTRY glVertexBindingDivisorNULL(GLuint bindingindex, GLuint divisor) {} - -void INTERNAL_GL_APIENTRY glViewportNULL(GLint x, GLint y, GLsizei width, GLsizei height) {} - -void INTERNAL_GL_APIENTRY glViewportArrayvNULL(GLuint first, GLsizei count, const GLfloat *v) {} - -void INTERNAL_GL_APIENTRY -glViewportIndexedfNULL(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h) -{} - -void INTERNAL_GL_APIENTRY glViewportIndexedfvNULL(GLuint index, const GLfloat *v) {} - -void INTERNAL_GL_APIENTRY glWaitSemaphoreEXTNULL(GLuint semaphore, - GLuint numBufferBarriers, - const GLuint *buffers, - GLuint numTextureBarriers, - const GLuint *textures, - const GLenum *srcLayouts) -{} - -void INTERNAL_GL_APIENTRY glWaitSyncNULL(GLsync sync, GLbitfield flags, GLuint64 timeout) {} -} // namespace rx diff --git a/src/libANGLE/renderer/gl/null_functions.h b/src/libANGLE/renderer/gl/null_functions.h deleted file mode 100644 index f5c9b4e542a..00000000000 --- a/src/libANGLE/renderer/gl/null_functions.h +++ /dev/null @@ -1,2092 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by generate_gl_dispatch_table.py using data from gl_bindings_data.json and gl.xml. -// -// Copyright 2017 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. -// -// null_functions.h: -// Declares the NULL/Stub bindings for the OpenGL back-end. - -#ifndef LIBGLESV2_RENDERER_GL_NULL_GL_FUNCTIONS_AUTOGEN_H_ -#define LIBGLESV2_RENDERER_GL_NULL_GL_FUNCTIONS_AUTOGEN_H_ - -#include "libANGLE/renderer/gl/functionsgl_typedefs.h" - -namespace rx -{ -void INTERNAL_GL_APIENTRY glActiveShaderProgramNULL(GLuint pipeline, GLuint program); -void INTERNAL_GL_APIENTRY glActiveTextureNULL(GLenum texture); -void INTERNAL_GL_APIENTRY glAttachShaderNULL(GLuint program, GLuint shader); -void INTERNAL_GL_APIENTRY glBeginConditionalRenderNULL(GLuint id, GLenum mode); -void INTERNAL_GL_APIENTRY glBeginQueryNULL(GLenum target, GLuint id); -void INTERNAL_GL_APIENTRY glBeginQueryIndexedNULL(GLenum target, GLuint index, GLuint id); -void INTERNAL_GL_APIENTRY glBeginTransformFeedbackNULL(GLenum primitiveMode); -void INTERNAL_GL_APIENTRY glBindAttribLocationNULL(GLuint program, - GLuint index, - const GLchar *name); -void INTERNAL_GL_APIENTRY glBindBufferNULL(GLenum target, GLuint buffer); -void INTERNAL_GL_APIENTRY glBindBufferBaseNULL(GLenum target, GLuint index, GLuint buffer); -void INTERNAL_GL_APIENTRY -glBindBufferRangeNULL(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -void INTERNAL_GL_APIENTRY glBindBuffersBaseNULL(GLenum target, - GLuint first, - GLsizei count, - const GLuint *buffers); -void INTERNAL_GL_APIENTRY glBindBuffersRangeNULL(GLenum target, - GLuint first, - GLsizei count, - const GLuint *buffers, - const GLintptr *offsets, - const GLsizeiptr *sizes); -void INTERNAL_GL_APIENTRY glBindFragDataLocationNULL(GLuint program, - GLuint color, - const GLchar *name); -void INTERNAL_GL_APIENTRY glBindFragDataLocationIndexedNULL(GLuint program, - GLuint colorNumber, - GLuint index, - const GLchar *name); -void INTERNAL_GL_APIENTRY glBindFramebufferNULL(GLenum target, GLuint framebuffer); -void INTERNAL_GL_APIENTRY glBindImageTextureNULL(GLuint unit, - GLuint texture, - GLint level, - GLboolean layered, - GLint layer, - GLenum access, - GLenum format); -void INTERNAL_GL_APIENTRY glBindImageTexturesNULL(GLuint first, - GLsizei count, - const GLuint *textures); -void INTERNAL_GL_APIENTRY glBindProgramPipelineNULL(GLuint pipeline); -void INTERNAL_GL_APIENTRY glBindRenderbufferNULL(GLenum target, GLuint renderbuffer); -void INTERNAL_GL_APIENTRY glBindSamplerNULL(GLuint unit, GLuint sampler); -void INTERNAL_GL_APIENTRY glBindSamplersNULL(GLuint first, GLsizei count, const GLuint *samplers); -void INTERNAL_GL_APIENTRY glBindTextureNULL(GLenum target, GLuint texture); -void INTERNAL_GL_APIENTRY glBindTextureUnitNULL(GLuint unit, GLuint texture); -void INTERNAL_GL_APIENTRY glBindTexturesNULL(GLuint first, GLsizei count, const GLuint *textures); -void INTERNAL_GL_APIENTRY glBindTransformFeedbackNULL(GLenum target, GLuint id); -void INTERNAL_GL_APIENTRY glBindVertexArrayNULL(GLuint array); -void INTERNAL_GL_APIENTRY glBindVertexBufferNULL(GLuint bindingindex, - GLuint buffer, - GLintptr offset, - GLsizei stride); -void INTERNAL_GL_APIENTRY glBindVertexBuffersNULL(GLuint first, - GLsizei count, - const GLuint *buffers, - const GLintptr *offsets, - const GLsizei *strides); -void INTERNAL_GL_APIENTRY glBlendBarrierNULL(); -void INTERNAL_GL_APIENTRY glBlendColorNULL(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void INTERNAL_GL_APIENTRY glBlendEquationNULL(GLenum mode); -void INTERNAL_GL_APIENTRY glBlendEquationSeparateNULL(GLenum modeRGB, GLenum modeAlpha); -void INTERNAL_GL_APIENTRY glBlendEquationSeparateiNULL(GLuint buf, - GLenum modeRGB, - GLenum modeAlpha); -void INTERNAL_GL_APIENTRY glBlendEquationiNULL(GLuint buf, GLenum mode); -void INTERNAL_GL_APIENTRY glBlendFuncNULL(GLenum sfactor, GLenum dfactor); -void INTERNAL_GL_APIENTRY glBlendFuncSeparateNULL(GLenum sfactorRGB, - GLenum dfactorRGB, - GLenum sfactorAlpha, - GLenum dfactorAlpha); -void INTERNAL_GL_APIENTRY glBlendFuncSeparateiNULL(GLuint buf, - GLenum srcRGB, - GLenum dstRGB, - GLenum srcAlpha, - GLenum dstAlpha); -void INTERNAL_GL_APIENTRY glBlendFunciNULL(GLuint buf, GLenum src, GLenum dst); -void INTERNAL_GL_APIENTRY glBlitFramebufferNULL(GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter); -void INTERNAL_GL_APIENTRY glBlitFramebufferEXTNULL(GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter); -void INTERNAL_GL_APIENTRY glBlitFramebufferNVNULL(GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter); -void INTERNAL_GL_APIENTRY glBlitNamedFramebufferNULL(GLuint readFramebuffer, - GLuint drawFramebuffer, - GLint srcX0, - GLint srcY0, - GLint srcX1, - GLint srcY1, - GLint dstX0, - GLint dstY0, - GLint dstX1, - GLint dstY1, - GLbitfield mask, - GLenum filter); -void INTERNAL_GL_APIENTRY glBufferDataNULL(GLenum target, - GLsizeiptr size, - const void *data, - GLenum usage); -void INTERNAL_GL_APIENTRY glBufferStorageNULL(GLenum target, - GLsizeiptr size, - const void *data, - GLbitfield flags); -void INTERNAL_GL_APIENTRY glBufferStorageMemEXTNULL(GLenum target, - GLsizeiptr size, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glBufferSubDataNULL(GLenum target, - GLintptr offset, - GLsizeiptr size, - const void *data); -GLenum INTERNAL_GL_APIENTRY glCheckFramebufferStatusNULL(GLenum target); -GLenum INTERNAL_GL_APIENTRY glCheckNamedFramebufferStatusNULL(GLuint framebuffer, GLenum target); -void INTERNAL_GL_APIENTRY glClampColorNULL(GLenum target, GLenum clamp); -void INTERNAL_GL_APIENTRY glClearNULL(GLbitfield mask); -void INTERNAL_GL_APIENTRY glClearBufferDataNULL(GLenum target, - GLenum internalformat, - GLenum format, - GLenum type, - const void *data); -void INTERNAL_GL_APIENTRY glClearBufferSubDataNULL(GLenum target, - GLenum internalformat, - GLintptr offset, - GLsizeiptr size, - GLenum format, - GLenum type, - const void *data); -void INTERNAL_GL_APIENTRY glClearBufferfiNULL(GLenum buffer, - GLint drawbuffer, - GLfloat depth, - GLint stencil); -void INTERNAL_GL_APIENTRY glClearBufferfvNULL(GLenum buffer, - GLint drawbuffer, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glClearBufferivNULL(GLenum buffer, GLint drawbuffer, const GLint *value); -void INTERNAL_GL_APIENTRY glClearBufferuivNULL(GLenum buffer, - GLint drawbuffer, - const GLuint *value); -void INTERNAL_GL_APIENTRY glClearColorNULL(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void INTERNAL_GL_APIENTRY glClearDepthNULL(GLdouble depth); -void INTERNAL_GL_APIENTRY glClearDepthfNULL(GLfloat d); -void INTERNAL_GL_APIENTRY glClearNamedBufferDataNULL(GLuint buffer, - GLenum internalformat, - GLenum format, - GLenum type, - const void *data); -void INTERNAL_GL_APIENTRY glClearNamedBufferSubDataNULL(GLuint buffer, - GLenum internalformat, - GLintptr offset, - GLsizeiptr size, - GLenum format, - GLenum type, - const void *data); -void INTERNAL_GL_APIENTRY glClearNamedFramebufferfiNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - GLfloat depth, - GLint stencil); -void INTERNAL_GL_APIENTRY glClearNamedFramebufferfvNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glClearNamedFramebufferivNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - const GLint *value); -void INTERNAL_GL_APIENTRY glClearNamedFramebufferuivNULL(GLuint framebuffer, - GLenum buffer, - GLint drawbuffer, - const GLuint *value); -void INTERNAL_GL_APIENTRY glClearStencilNULL(GLint s); -void INTERNAL_GL_APIENTRY -glClearTexImageNULL(GLuint texture, GLint level, GLenum format, GLenum type, const void *data); -void INTERNAL_GL_APIENTRY glClearTexSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *data); -GLenum INTERNAL_GL_APIENTRY glClientWaitSyncNULL(GLsync sync, GLbitfield flags, GLuint64 timeout); -void INTERNAL_GL_APIENTRY glClipControlNULL(GLenum origin, GLenum depth); -void INTERNAL_GL_APIENTRY glColorMaskNULL(GLboolean red, - GLboolean green, - GLboolean blue, - GLboolean alpha); -void INTERNAL_GL_APIENTRY -glColorMaskiNULL(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -void INTERNAL_GL_APIENTRY glCompileShaderNULL(GLuint shader); -void INTERNAL_GL_APIENTRY glCompressedTexImage1DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLint border, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTexImage2DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTexImage3DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTexSubImage1DNULL(GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTexSubImage2DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTexSubImage3DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTextureSubImage1DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTextureSubImage2DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCompressedTextureSubImage3DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLsizei imageSize, - const void *data); -void INTERNAL_GL_APIENTRY glCopyBufferSubDataNULL(GLenum readTarget, - GLenum writeTarget, - GLintptr readOffset, - GLintptr writeOffset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glCopyImageSubDataNULL(GLuint srcName, - GLenum srcTarget, - GLint srcLevel, - GLint srcX, - GLint srcY, - GLint srcZ, - GLuint dstName, - GLenum dstTarget, - GLint dstLevel, - GLint dstX, - GLint dstY, - GLint dstZ, - GLsizei srcWidth, - GLsizei srcHeight, - GLsizei srcDepth); -void INTERNAL_GL_APIENTRY glCopyNamedBufferSubDataNULL(GLuint readBuffer, - GLuint writeBuffer, - GLintptr readOffset, - GLintptr writeOffset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glCopyTexImage1DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLint x, - GLint y, - GLsizei width, - GLint border); -void INTERNAL_GL_APIENTRY glCopyTexImage2DNULL(GLenum target, - GLint level, - GLenum internalformat, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLint border); -void INTERNAL_GL_APIENTRY -glCopyTexSubImage1DNULL(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -void INTERNAL_GL_APIENTRY glCopyTexSubImage2DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glCopyTexSubImage3DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glCopyTextureSubImage1DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint x, - GLint y, - GLsizei width); -void INTERNAL_GL_APIENTRY glCopyTextureSubImage2DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glCopyTextureSubImage3DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glCoverageModulationNVNULL(GLenum components); -void INTERNAL_GL_APIENTRY glCreateBuffersNULL(GLsizei n, GLuint *buffers); -void INTERNAL_GL_APIENTRY glCreateFramebuffersNULL(GLsizei n, GLuint *framebuffers); -void INTERNAL_GL_APIENTRY glCreateMemoryObjectsEXTNULL(GLsizei n, GLuint *memoryObjects); -GLuint INTERNAL_GL_APIENTRY glCreateProgramNULL(); -void INTERNAL_GL_APIENTRY glCreateProgramPipelinesNULL(GLsizei n, GLuint *pipelines); -void INTERNAL_GL_APIENTRY glCreateQueriesNULL(GLenum target, GLsizei n, GLuint *ids); -void INTERNAL_GL_APIENTRY glCreateRenderbuffersNULL(GLsizei n, GLuint *renderbuffers); -void INTERNAL_GL_APIENTRY glCreateSamplersNULL(GLsizei n, GLuint *samplers); -GLuint INTERNAL_GL_APIENTRY glCreateShaderNULL(GLenum type); -GLuint INTERNAL_GL_APIENTRY glCreateShaderProgramvNULL(GLenum type, - GLsizei count, - const GLchar *const *strings); -void INTERNAL_GL_APIENTRY glCreateTexturesNULL(GLenum target, GLsizei n, GLuint *textures); -void INTERNAL_GL_APIENTRY glCreateTransformFeedbacksNULL(GLsizei n, GLuint *ids); -void INTERNAL_GL_APIENTRY glCreateVertexArraysNULL(GLsizei n, GLuint *arrays); -void INTERNAL_GL_APIENTRY glCullFaceNULL(GLenum mode); -void INTERNAL_GL_APIENTRY glDebugMessageCallbackNULL(GLDEBUGPROC callback, const void *userParam); -void INTERNAL_GL_APIENTRY glDebugMessageControlNULL(GLenum source, - GLenum type, - GLenum severity, - GLsizei count, - const GLuint *ids, - GLboolean enabled); -void INTERNAL_GL_APIENTRY glDebugMessageInsertNULL(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *buf); -void INTERNAL_GL_APIENTRY glDeleteBuffersNULL(GLsizei n, const GLuint *buffers); -void INTERNAL_GL_APIENTRY glDeleteFencesNVNULL(GLsizei n, const GLuint *fences); -void INTERNAL_GL_APIENTRY glDeleteFramebuffersNULL(GLsizei n, const GLuint *framebuffers); -void INTERNAL_GL_APIENTRY glDeleteMemoryObjectsEXTNULL(GLsizei n, const GLuint *memoryObjects); -void INTERNAL_GL_APIENTRY glDeleteProgramNULL(GLuint program); -void INTERNAL_GL_APIENTRY glDeleteProgramPipelinesNULL(GLsizei n, const GLuint *pipelines); -void INTERNAL_GL_APIENTRY glDeleteQueriesNULL(GLsizei n, const GLuint *ids); -void INTERNAL_GL_APIENTRY glDeleteRenderbuffersNULL(GLsizei n, const GLuint *renderbuffers); -void INTERNAL_GL_APIENTRY glDeleteSamplersNULL(GLsizei count, const GLuint *samplers); -void INTERNAL_GL_APIENTRY glDeleteSemaphoresEXTNULL(GLsizei n, const GLuint *semaphores); -void INTERNAL_GL_APIENTRY glDeleteShaderNULL(GLuint shader); -void INTERNAL_GL_APIENTRY glDeleteSyncNULL(GLsync sync); -void INTERNAL_GL_APIENTRY glDeleteTexturesNULL(GLsizei n, const GLuint *textures); -void INTERNAL_GL_APIENTRY glDeleteTransformFeedbacksNULL(GLsizei n, const GLuint *ids); -void INTERNAL_GL_APIENTRY glDeleteVertexArraysNULL(GLsizei n, const GLuint *arrays); -void INTERNAL_GL_APIENTRY glDepthFuncNULL(GLenum func); -void INTERNAL_GL_APIENTRY glDepthMaskNULL(GLboolean flag); -void INTERNAL_GL_APIENTRY glDepthRangeNULL(GLdouble n, GLdouble f); -void INTERNAL_GL_APIENTRY glDepthRangeArrayvNULL(GLuint first, GLsizei count, const GLdouble *v); -void INTERNAL_GL_APIENTRY glDepthRangeIndexedNULL(GLuint index, GLdouble n, GLdouble f); -void INTERNAL_GL_APIENTRY glDepthRangefNULL(GLfloat n, GLfloat f); -void INTERNAL_GL_APIENTRY glDetachShaderNULL(GLuint program, GLuint shader); -void INTERNAL_GL_APIENTRY glDisableNULL(GLenum cap); -void INTERNAL_GL_APIENTRY glDisableVertexArrayAttribNULL(GLuint vaobj, GLuint index); -void INTERNAL_GL_APIENTRY glDisableVertexAttribArrayNULL(GLuint index); -void INTERNAL_GL_APIENTRY glDisableiNULL(GLenum target, GLuint index); -void INTERNAL_GL_APIENTRY glDiscardFramebufferEXTNULL(GLenum target, - GLsizei numAttachments, - const GLenum *attachments); -void INTERNAL_GL_APIENTRY glDispatchComputeNULL(GLuint num_groups_x, - GLuint num_groups_y, - GLuint num_groups_z); -void INTERNAL_GL_APIENTRY glDispatchComputeIndirectNULL(GLintptr indirect); -void INTERNAL_GL_APIENTRY glDrawArraysNULL(GLenum mode, GLint first, GLsizei count); -void INTERNAL_GL_APIENTRY glDrawArraysIndirectNULL(GLenum mode, const void *indirect); -void INTERNAL_GL_APIENTRY glDrawArraysInstancedNULL(GLenum mode, - GLint first, - GLsizei count, - GLsizei instancecount); -void INTERNAL_GL_APIENTRY glDrawArraysInstancedBaseInstanceNULL(GLenum mode, - GLint first, - GLsizei count, - GLsizei instancecount, - GLuint baseinstance); -void INTERNAL_GL_APIENTRY glDrawBufferNULL(GLenum buf); -void INTERNAL_GL_APIENTRY glDrawBuffersNULL(GLsizei n, const GLenum *bufs); -void INTERNAL_GL_APIENTRY glDrawElementsNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices); -void INTERNAL_GL_APIENTRY glDrawElementsBaseVertexNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLint basevertex); -void INTERNAL_GL_APIENTRY glDrawElementsIndirectNULL(GLenum mode, - GLenum type, - const void *indirect); -void INTERNAL_GL_APIENTRY glDrawElementsInstancedNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount); -void INTERNAL_GL_APIENTRY glDrawElementsInstancedBaseInstanceNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount, - GLuint baseinstance); -void INTERNAL_GL_APIENTRY glDrawElementsInstancedBaseVertexNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount, - GLint basevertex); -void INTERNAL_GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceNULL(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei instancecount, - GLint basevertex, - GLuint baseinstance); -void INTERNAL_GL_APIENTRY glDrawRangeElementsNULL(GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const void *indices); -void INTERNAL_GL_APIENTRY glDrawRangeElementsBaseVertexNULL(GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const void *indices, - GLint basevertex); -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackNULL(GLenum mode, GLuint id); -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackInstancedNULL(GLenum mode, - GLuint id, - GLsizei instancecount); -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackStreamNULL(GLenum mode, GLuint id, GLuint stream); -void INTERNAL_GL_APIENTRY glDrawTransformFeedbackStreamInstancedNULL(GLenum mode, - GLuint id, - GLuint stream, - GLsizei instancecount); -void INTERNAL_GL_APIENTRY glEGLImageTargetRenderbufferStorageOESNULL(GLenum target, - GLeglImageOES image); -void INTERNAL_GL_APIENTRY glEGLImageTargetTexture2DOESNULL(GLenum target, GLeglImageOES image); -void INTERNAL_GL_APIENTRY glEnableNULL(GLenum cap); -void INTERNAL_GL_APIENTRY glEnableVertexArrayAttribNULL(GLuint vaobj, GLuint index); -void INTERNAL_GL_APIENTRY glEnableVertexAttribArrayNULL(GLuint index); -void INTERNAL_GL_APIENTRY glEnableiNULL(GLenum target, GLuint index); -void INTERNAL_GL_APIENTRY glEndConditionalRenderNULL(); -void INTERNAL_GL_APIENTRY glEndQueryNULL(GLenum target); -void INTERNAL_GL_APIENTRY glEndQueryIndexedNULL(GLenum target, GLuint index); -void INTERNAL_GL_APIENTRY glEndTilingQCOMNULL(GLbitfield preserveMask); -void INTERNAL_GL_APIENTRY glEndTransformFeedbackNULL(); -GLsync INTERNAL_GL_APIENTRY glFenceSyncNULL(GLenum condition, GLbitfield flags); -void INTERNAL_GL_APIENTRY glFinishNULL(); -void INTERNAL_GL_APIENTRY glFinishFenceNVNULL(GLuint fence); -void INTERNAL_GL_APIENTRY glFlushNULL(); -void INTERNAL_GL_APIENTRY glFlushMappedBufferRangeNULL(GLenum target, - GLintptr offset, - GLsizeiptr length); -void INTERNAL_GL_APIENTRY glFlushMappedNamedBufferRangeNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr length); -void INTERNAL_GL_APIENTRY glFramebufferFetchBarrierEXTNULL(); -void INTERNAL_GL_APIENTRY glFramebufferParameteriNULL(GLenum target, GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glFramebufferParameteriMESANULL(GLenum target, GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glFramebufferRenderbufferNULL(GLenum target, - GLenum attachment, - GLenum renderbuffertarget, - GLuint renderbuffer); -void INTERNAL_GL_APIENTRY glFramebufferTextureNULL(GLenum target, - GLenum attachment, - GLuint texture, - GLint level); -void INTERNAL_GL_APIENTRY glFramebufferTexture1DNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level); -void INTERNAL_GL_APIENTRY glFramebufferTexture2DNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level); -void INTERNAL_GL_APIENTRY glFramebufferTexture2DMultisampleEXTNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level, - GLsizei samples); -void INTERNAL_GL_APIENTRY glFramebufferTexture2DMultisampleIMGNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level, - GLsizei samples); -void INTERNAL_GL_APIENTRY glFramebufferTexture3DNULL(GLenum target, - GLenum attachment, - GLenum textarget, - GLuint texture, - GLint level, - GLint zoffset); -void INTERNAL_GL_APIENTRY glFramebufferTextureLayerNULL(GLenum target, - GLenum attachment, - GLuint texture, - GLint level, - GLint layer); -void INTERNAL_GL_APIENTRY glFramebufferTextureMultiviewOVRNULL(GLenum target, - GLenum attachment, - GLuint texture, - GLint level, - GLint baseViewIndex, - GLsizei numViews); -void INTERNAL_GL_APIENTRY glFrontFaceNULL(GLenum mode); -void INTERNAL_GL_APIENTRY glGenBuffersNULL(GLsizei n, GLuint *buffers); -void INTERNAL_GL_APIENTRY glGenFencesNVNULL(GLsizei n, GLuint *fences); -void INTERNAL_GL_APIENTRY glGenFramebuffersNULL(GLsizei n, GLuint *framebuffers); -void INTERNAL_GL_APIENTRY glGenProgramPipelinesNULL(GLsizei n, GLuint *pipelines); -void INTERNAL_GL_APIENTRY glGenQueriesNULL(GLsizei n, GLuint *ids); -void INTERNAL_GL_APIENTRY glGenRenderbuffersNULL(GLsizei n, GLuint *renderbuffers); -void INTERNAL_GL_APIENTRY glGenSamplersNULL(GLsizei count, GLuint *samplers); -void INTERNAL_GL_APIENTRY glGenSemaphoresEXTNULL(GLsizei n, GLuint *semaphores); -void INTERNAL_GL_APIENTRY glGenTexturesNULL(GLsizei n, GLuint *textures); -void INTERNAL_GL_APIENTRY glGenTransformFeedbacksNULL(GLsizei n, GLuint *ids); -void INTERNAL_GL_APIENTRY glGenVertexArraysNULL(GLsizei n, GLuint *arrays); -void INTERNAL_GL_APIENTRY glGenerateMipmapNULL(GLenum target); -void INTERNAL_GL_APIENTRY glGenerateTextureMipmapNULL(GLuint texture); -void INTERNAL_GL_APIENTRY glGetActiveAtomicCounterBufferivNULL(GLuint program, - GLuint bufferIndex, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetActiveAttribNULL(GLuint program, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLint *size, - GLenum *type, - GLchar *name); -void INTERNAL_GL_APIENTRY glGetActiveSubroutineNameNULL(GLuint program, - GLenum shadertype, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLchar *name); -void INTERNAL_GL_APIENTRY glGetActiveSubroutineUniformNameNULL(GLuint program, - GLenum shadertype, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLchar *name); -void INTERNAL_GL_APIENTRY glGetActiveSubroutineUniformivNULL(GLuint program, - GLenum shadertype, - GLuint index, - GLenum pname, - GLint *values); -void INTERNAL_GL_APIENTRY glGetActiveUniformNULL(GLuint program, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLint *size, - GLenum *type, - GLchar *name); -void INTERNAL_GL_APIENTRY glGetActiveUniformBlockNameNULL(GLuint program, - GLuint uniformBlockIndex, - GLsizei bufSize, - GLsizei *length, - GLchar *uniformBlockName); -void INTERNAL_GL_APIENTRY glGetActiveUniformBlockivNULL(GLuint program, - GLuint uniformBlockIndex, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetActiveUniformNameNULL(GLuint program, - GLuint uniformIndex, - GLsizei bufSize, - GLsizei *length, - GLchar *uniformName); -void INTERNAL_GL_APIENTRY glGetActiveUniformsivNULL(GLuint program, - GLsizei uniformCount, - const GLuint *uniformIndices, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetAttachedShadersNULL(GLuint program, - GLsizei maxCount, - GLsizei *count, - GLuint *shaders); -GLint INTERNAL_GL_APIENTRY glGetAttribLocationNULL(GLuint program, const GLchar *name); -void INTERNAL_GL_APIENTRY glGetBooleani_vNULL(GLenum target, GLuint index, GLboolean *data); -void INTERNAL_GL_APIENTRY glGetBooleanvNULL(GLenum pname, GLboolean *data); -void INTERNAL_GL_APIENTRY glGetBufferParameteri64vNULL(GLenum target, - GLenum pname, - GLint64 *params); -void INTERNAL_GL_APIENTRY glGetBufferParameterivNULL(GLenum target, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetBufferPointervNULL(GLenum target, GLenum pname, void **params); -void INTERNAL_GL_APIENTRY glGetBufferSubDataNULL(GLenum target, - GLintptr offset, - GLsizeiptr size, - void *data); -void INTERNAL_GL_APIENTRY glGetCompressedTexImageNULL(GLenum target, GLint level, void *img); -void INTERNAL_GL_APIENTRY glGetCompressedTextureImageNULL(GLuint texture, - GLint level, - GLsizei bufSize, - void *pixels); -void INTERNAL_GL_APIENTRY glGetCompressedTextureSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLsizei bufSize, - void *pixels); -GLuint INTERNAL_GL_APIENTRY glGetDebugMessageLogNULL(GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog); -void INTERNAL_GL_APIENTRY glGetDoublei_vNULL(GLenum target, GLuint index, GLdouble *data); -void INTERNAL_GL_APIENTRY glGetDoublevNULL(GLenum pname, GLdouble *data); -GLenum INTERNAL_GL_APIENTRY glGetErrorNULL(); -void INTERNAL_GL_APIENTRY glGetFenceivNVNULL(GLuint fence, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetFloati_vNULL(GLenum target, GLuint index, GLfloat *data); -void INTERNAL_GL_APIENTRY glGetFloatvNULL(GLenum pname, GLfloat *data); -GLint INTERNAL_GL_APIENTRY glGetFragDataIndexNULL(GLuint program, const GLchar *name); -GLint INTERNAL_GL_APIENTRY glGetFragDataLocationNULL(GLuint program, const GLchar *name); -void INTERNAL_GL_APIENTRY glGetFramebufferAttachmentParameterivNULL(GLenum target, - GLenum attachment, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetFramebufferParameterivNULL(GLenum target, - GLenum pname, - GLint *params); -GLenum INTERNAL_GL_APIENTRY glGetGraphicsResetStatusNULL(); -void INTERNAL_GL_APIENTRY glGetInteger64i_vNULL(GLenum target, GLuint index, GLint64 *data); -void INTERNAL_GL_APIENTRY glGetInteger64vNULL(GLenum pname, GLint64 *data); -void INTERNAL_GL_APIENTRY glGetIntegeri_vNULL(GLenum target, GLuint index, GLint *data); -void INTERNAL_GL_APIENTRY glGetIntegervNULL(GLenum pname, GLint *data); -void INTERNAL_GL_APIENTRY glGetInternalformatSampleivNVNULL(GLenum target, - GLenum internalformat, - GLsizei samples, - GLenum pname, - GLsizei count, - GLint *params); -void INTERNAL_GL_APIENTRY glGetInternalformati64vNULL(GLenum target, - GLenum internalformat, - GLenum pname, - GLsizei count, - GLint64 *params); -void INTERNAL_GL_APIENTRY glGetInternalformativNULL(GLenum target, - GLenum internalformat, - GLenum pname, - GLsizei count, - GLint *params); -void INTERNAL_GL_APIENTRY glGetMemoryObjectParameterivEXTNULL(GLuint memoryObject, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetMultisamplefvNULL(GLenum pname, GLuint index, GLfloat *val); -void INTERNAL_GL_APIENTRY glGetNamedBufferParameteri64vNULL(GLuint buffer, - GLenum pname, - GLint64 *params); -void INTERNAL_GL_APIENTRY glGetNamedBufferParameterivNULL(GLuint buffer, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetNamedBufferPointervNULL(GLuint buffer, GLenum pname, void **params); -void INTERNAL_GL_APIENTRY glGetNamedBufferSubDataNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - void *data); -void INTERNAL_GL_APIENTRY glGetNamedFramebufferAttachmentParameterivNULL(GLuint framebuffer, - GLenum attachment, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetNamedFramebufferParameterivNULL(GLuint framebuffer, - GLenum pname, - GLint *param); -void INTERNAL_GL_APIENTRY glGetNamedRenderbufferParameterivNULL(GLuint renderbuffer, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetObjectLabelNULL(GLenum identifier, - GLuint name, - GLsizei bufSize, - GLsizei *length, - GLchar *label); -void INTERNAL_GL_APIENTRY glGetObjectPtrLabelNULL(const void *ptr, - GLsizei bufSize, - GLsizei *length, - GLchar *label); -void INTERNAL_GL_APIENTRY glGetPointervNULL(GLenum pname, void **params); -void INTERNAL_GL_APIENTRY glGetProgramBinaryNULL(GLuint program, - GLsizei bufSize, - GLsizei *length, - GLenum *binaryFormat, - void *binary); -void INTERNAL_GL_APIENTRY glGetProgramInfoLogNULL(GLuint program, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog); -void INTERNAL_GL_APIENTRY glGetProgramInterfaceivNULL(GLuint program, - GLenum programInterface, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetProgramPipelineInfoLogNULL(GLuint pipeline, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog); -void INTERNAL_GL_APIENTRY glGetProgramPipelineivNULL(GLuint pipeline, GLenum pname, GLint *params); -GLuint INTERNAL_GL_APIENTRY glGetProgramResourceIndexNULL(GLuint program, - GLenum programInterface, - const GLchar *name); -GLint INTERNAL_GL_APIENTRY glGetProgramResourceLocationNULL(GLuint program, - GLenum programInterface, - const GLchar *name); -GLint INTERNAL_GL_APIENTRY glGetProgramResourceLocationIndexNULL(GLuint program, - GLenum programInterface, - const GLchar *name); -void INTERNAL_GL_APIENTRY glGetProgramResourceNameNULL(GLuint program, - GLenum programInterface, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLchar *name); -void INTERNAL_GL_APIENTRY glGetProgramResourceivNULL(GLuint program, - GLenum programInterface, - GLuint index, - GLsizei propCount, - const GLenum *props, - GLsizei count, - GLsizei *length, - GLint *params); -void INTERNAL_GL_APIENTRY glGetProgramStageivNULL(GLuint program, - GLenum shadertype, - GLenum pname, - GLint *values); -void INTERNAL_GL_APIENTRY glGetProgramivNULL(GLuint program, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetQueryBufferObjecti64vNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset); -void INTERNAL_GL_APIENTRY glGetQueryBufferObjectivNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset); -void INTERNAL_GL_APIENTRY glGetQueryBufferObjectui64vNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset); -void INTERNAL_GL_APIENTRY glGetQueryBufferObjectuivNULL(GLuint id, - GLuint buffer, - GLenum pname, - GLintptr offset); -void INTERNAL_GL_APIENTRY glGetQueryIndexedivNULL(GLenum target, - GLuint index, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetQueryObjecti64vNULL(GLuint id, GLenum pname, GLint64 *params); -void INTERNAL_GL_APIENTRY glGetQueryObjectivNULL(GLuint id, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetQueryObjectui64vNULL(GLuint id, GLenum pname, GLuint64 *params); -void INTERNAL_GL_APIENTRY glGetQueryObjectuivNULL(GLuint id, GLenum pname, GLuint *params); -void INTERNAL_GL_APIENTRY glGetQueryivNULL(GLenum target, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetRenderbufferParameterivNULL(GLenum target, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetSamplerParameterIivNULL(GLuint sampler, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetSamplerParameterIuivNULL(GLuint sampler, - GLenum pname, - GLuint *params); -void INTERNAL_GL_APIENTRY glGetSamplerParameterfvNULL(GLuint sampler, - GLenum pname, - GLfloat *params); -void INTERNAL_GL_APIENTRY glGetSamplerParameterivNULL(GLuint sampler, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetSemaphoreParameterui64vEXTNULL(GLuint semaphore, - GLenum pname, - GLuint64 *params); -void INTERNAL_GL_APIENTRY glGetShaderInfoLogNULL(GLuint shader, - GLsizei bufSize, - GLsizei *length, - GLchar *infoLog); -void INTERNAL_GL_APIENTRY glGetShaderPrecisionFormatNULL(GLenum shadertype, - GLenum precisiontype, - GLint *range, - GLint *precision); -void INTERNAL_GL_APIENTRY glGetShaderSourceNULL(GLuint shader, - GLsizei bufSize, - GLsizei *length, - GLchar *source); -void INTERNAL_GL_APIENTRY glGetShaderivNULL(GLuint shader, GLenum pname, GLint *params); -const GLubyte *INTERNAL_GL_APIENTRY glGetStringNULL(GLenum name); -const GLubyte *INTERNAL_GL_APIENTRY glGetStringiNULL(GLenum name, GLuint index); -GLuint INTERNAL_GL_APIENTRY glGetSubroutineIndexNULL(GLuint program, - GLenum shadertype, - const GLchar *name); -GLint INTERNAL_GL_APIENTRY glGetSubroutineUniformLocationNULL(GLuint program, - GLenum shadertype, - const GLchar *name); -void INTERNAL_GL_APIENTRY -glGetSyncivNULL(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); -void INTERNAL_GL_APIENTRY -glGetTexImageNULL(GLenum target, GLint level, GLenum format, GLenum type, void *pixels); -void INTERNAL_GL_APIENTRY glGetTexLevelParameterfvNULL(GLenum target, - GLint level, - GLenum pname, - GLfloat *params); -void INTERNAL_GL_APIENTRY glGetTexLevelParameterivNULL(GLenum target, - GLint level, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetTexParameterIivNULL(GLenum target, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetTexParameterIuivNULL(GLenum target, GLenum pname, GLuint *params); -void INTERNAL_GL_APIENTRY glGetTexParameterfvNULL(GLenum target, GLenum pname, GLfloat *params); -void INTERNAL_GL_APIENTRY glGetTexParameterivNULL(GLenum target, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetTextureImageNULL(GLuint texture, - GLint level, - GLenum format, - GLenum type, - GLsizei bufSize, - void *pixels); -void INTERNAL_GL_APIENTRY glGetTextureLevelParameterfvNULL(GLuint texture, - GLint level, - GLenum pname, - GLfloat *params); -void INTERNAL_GL_APIENTRY glGetTextureLevelParameterivNULL(GLuint texture, - GLint level, - GLenum pname, - GLint *params); -void INTERNAL_GL_APIENTRY glGetTextureParameterIivNULL(GLuint texture, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetTextureParameterIuivNULL(GLuint texture, - GLenum pname, - GLuint *params); -void INTERNAL_GL_APIENTRY glGetTextureParameterfvNULL(GLuint texture, - GLenum pname, - GLfloat *params); -void INTERNAL_GL_APIENTRY glGetTextureParameterivNULL(GLuint texture, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetTextureSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - GLsizei bufSize, - void *pixels); -void INTERNAL_GL_APIENTRY glGetTransformFeedbackVaryingNULL(GLuint program, - GLuint index, - GLsizei bufSize, - GLsizei *length, - GLsizei *size, - GLenum *type, - GLchar *name); -void INTERNAL_GL_APIENTRY glGetTransformFeedbacki64_vNULL(GLuint xfb, - GLenum pname, - GLuint index, - GLint64 *param); -void INTERNAL_GL_APIENTRY glGetTransformFeedbacki_vNULL(GLuint xfb, - GLenum pname, - GLuint index, - GLint *param); -void INTERNAL_GL_APIENTRY glGetTransformFeedbackivNULL(GLuint xfb, GLenum pname, GLint *param); -GLuint INTERNAL_GL_APIENTRY glGetUniformBlockIndexNULL(GLuint program, - const GLchar *uniformBlockName); -void INTERNAL_GL_APIENTRY glGetUniformIndicesNULL(GLuint program, - GLsizei uniformCount, - const GLchar *const *uniformNames, - GLuint *uniformIndices); -GLint INTERNAL_GL_APIENTRY glGetUniformLocationNULL(GLuint program, const GLchar *name); -void INTERNAL_GL_APIENTRY glGetUniformSubroutineuivNULL(GLenum shadertype, - GLint location, - GLuint *params); -void INTERNAL_GL_APIENTRY glGetUniformdvNULL(GLuint program, GLint location, GLdouble *params); -void INTERNAL_GL_APIENTRY glGetUniformfvNULL(GLuint program, GLint location, GLfloat *params); -void INTERNAL_GL_APIENTRY glGetUniformivNULL(GLuint program, GLint location, GLint *params); -void INTERNAL_GL_APIENTRY glGetUniformuivNULL(GLuint program, GLint location, GLuint *params); -void INTERNAL_GL_APIENTRY glGetUnsignedBytei_vEXTNULL(GLenum target, GLuint index, GLubyte *data); -void INTERNAL_GL_APIENTRY glGetUnsignedBytevEXTNULL(GLenum pname, GLubyte *data); -void INTERNAL_GL_APIENTRY glGetVertexArrayIndexed64ivNULL(GLuint vaobj, - GLuint index, - GLenum pname, - GLint64 *param); -void INTERNAL_GL_APIENTRY glGetVertexArrayIndexedivNULL(GLuint vaobj, - GLuint index, - GLenum pname, - GLint *param); -void INTERNAL_GL_APIENTRY glGetVertexArrayivNULL(GLuint vaobj, GLenum pname, GLint *param); -void INTERNAL_GL_APIENTRY glGetVertexAttribIivNULL(GLuint index, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetVertexAttribIuivNULL(GLuint index, GLenum pname, GLuint *params); -void INTERNAL_GL_APIENTRY glGetVertexAttribLdvNULL(GLuint index, GLenum pname, GLdouble *params); -void INTERNAL_GL_APIENTRY glGetVertexAttribPointervNULL(GLuint index, GLenum pname, void **pointer); -void INTERNAL_GL_APIENTRY glGetVertexAttribdvNULL(GLuint index, GLenum pname, GLdouble *params); -void INTERNAL_GL_APIENTRY glGetVertexAttribfvNULL(GLuint index, GLenum pname, GLfloat *params); -void INTERNAL_GL_APIENTRY glGetVertexAttribivNULL(GLuint index, GLenum pname, GLint *params); -void INTERNAL_GL_APIENTRY glGetnCompressedTexImageNULL(GLenum target, - GLint lod, - GLsizei bufSize, - void *pixels); -void INTERNAL_GL_APIENTRY glGetnTexImageNULL(GLenum target, - GLint level, - GLenum format, - GLenum type, - GLsizei bufSize, - void *pixels); -void INTERNAL_GL_APIENTRY glGetnUniformdvNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLdouble *params); -void INTERNAL_GL_APIENTRY glGetnUniformfvNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLfloat *params); -void INTERNAL_GL_APIENTRY glGetnUniformivNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLint *params); -void INTERNAL_GL_APIENTRY glGetnUniformuivNULL(GLuint program, - GLint location, - GLsizei bufSize, - GLuint *params); -void INTERNAL_GL_APIENTRY glHintNULL(GLenum target, GLenum mode); -void INTERNAL_GL_APIENTRY glImportMemoryFdEXTNULL(GLuint memory, - GLuint64 size, - GLenum handleType, - GLint fd); -void INTERNAL_GL_APIENTRY glImportMemoryWin32HandleEXTNULL(GLuint memory, - GLuint64 size, - GLenum handleType, - void *handle); -void INTERNAL_GL_APIENTRY glImportMemoryWin32NameEXTNULL(GLuint memory, - GLuint64 size, - GLenum handleType, - const void *name); -void INTERNAL_GL_APIENTRY glImportSemaphoreFdEXTNULL(GLuint semaphore, GLenum handleType, GLint fd); -void INTERNAL_GL_APIENTRY glImportSemaphoreWin32HandleEXTNULL(GLuint semaphore, - GLenum handleType, - void *handle); -void INTERNAL_GL_APIENTRY glImportSemaphoreWin32NameEXTNULL(GLuint semaphore, - GLenum handleType, - const void *name); -void INTERNAL_GL_APIENTRY glInsertEventMarkerEXTNULL(GLsizei length, const GLchar *marker); -void INTERNAL_GL_APIENTRY glInvalidateBufferDataNULL(GLuint buffer); -void INTERNAL_GL_APIENTRY glInvalidateBufferSubDataNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr length); -void INTERNAL_GL_APIENTRY glInvalidateFramebufferNULL(GLenum target, - GLsizei numAttachments, - const GLenum *attachments); -void INTERNAL_GL_APIENTRY glInvalidateNamedFramebufferDataNULL(GLuint framebuffer, - GLsizei numAttachments, - const GLenum *attachments); -void INTERNAL_GL_APIENTRY glInvalidateNamedFramebufferSubDataNULL(GLuint framebuffer, - GLsizei numAttachments, - const GLenum *attachments, - GLint x, - GLint y, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glInvalidateSubFramebufferNULL(GLenum target, - GLsizei numAttachments, - const GLenum *attachments, - GLint x, - GLint y, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glInvalidateTexImageNULL(GLuint texture, GLint level); -void INTERNAL_GL_APIENTRY glInvalidateTexSubImageNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth); -GLboolean INTERNAL_GL_APIENTRY glIsBufferNULL(GLuint buffer); -GLboolean INTERNAL_GL_APIENTRY glIsEnabledNULL(GLenum cap); -GLboolean INTERNAL_GL_APIENTRY glIsEnablediNULL(GLenum target, GLuint index); -GLboolean INTERNAL_GL_APIENTRY glIsFenceNVNULL(GLuint fence); -GLboolean INTERNAL_GL_APIENTRY glIsFramebufferNULL(GLuint framebuffer); -GLboolean INTERNAL_GL_APIENTRY glIsMemoryObjectEXTNULL(GLuint memoryObject); -GLboolean INTERNAL_GL_APIENTRY glIsProgramNULL(GLuint program); -GLboolean INTERNAL_GL_APIENTRY glIsProgramPipelineNULL(GLuint pipeline); -GLboolean INTERNAL_GL_APIENTRY glIsQueryNULL(GLuint id); -GLboolean INTERNAL_GL_APIENTRY glIsRenderbufferNULL(GLuint renderbuffer); -GLboolean INTERNAL_GL_APIENTRY glIsSamplerNULL(GLuint sampler); -GLboolean INTERNAL_GL_APIENTRY glIsSemaphoreEXTNULL(GLuint semaphore); -GLboolean INTERNAL_GL_APIENTRY glIsShaderNULL(GLuint shader); -GLboolean INTERNAL_GL_APIENTRY glIsSyncNULL(GLsync sync); -GLboolean INTERNAL_GL_APIENTRY glIsTextureNULL(GLuint texture); -GLboolean INTERNAL_GL_APIENTRY glIsTransformFeedbackNULL(GLuint id); -GLboolean INTERNAL_GL_APIENTRY glIsVertexArrayNULL(GLuint array); -void INTERNAL_GL_APIENTRY glLineWidthNULL(GLfloat width); -void INTERNAL_GL_APIENTRY glLinkProgramNULL(GLuint program); -void INTERNAL_GL_APIENTRY glLogicOpNULL(GLenum opcode); -void *INTERNAL_GL_APIENTRY glMapBufferNULL(GLenum target, GLenum access); -void *INTERNAL_GL_APIENTRY glMapBufferRangeNULL(GLenum target, - GLintptr offset, - GLsizeiptr length, - GLbitfield access); -void *INTERNAL_GL_APIENTRY glMapNamedBufferNULL(GLuint buffer, GLenum access); -void *INTERNAL_GL_APIENTRY glMapNamedBufferRangeNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr length, - GLbitfield access); -void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsARBNULL(GLuint count); -void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsKHRNULL(GLuint count); -void INTERNAL_GL_APIENTRY glMemoryBarrierNULL(GLbitfield barriers); -void INTERNAL_GL_APIENTRY glMemoryBarrierByRegionNULL(GLbitfield barriers); -void INTERNAL_GL_APIENTRY glMemoryObjectParameterivEXTNULL(GLuint memoryObject, - GLenum pname, - const GLint *params); -void INTERNAL_GL_APIENTRY glMinSampleShadingNULL(GLfloat value); -void INTERNAL_GL_APIENTRY glMultiDrawArraysNULL(GLenum mode, - const GLint *first, - const GLsizei *count, - GLsizei drawcount); -void INTERNAL_GL_APIENTRY glMultiDrawArraysIndirectNULL(GLenum mode, - const void *indirect, - GLsizei drawcount, - GLsizei stride); -void INTERNAL_GL_APIENTRY glMultiDrawElementsNULL(GLenum mode, - const GLsizei *count, - GLenum type, - const void *const *indices, - GLsizei drawcount); -void INTERNAL_GL_APIENTRY glMultiDrawElementsBaseVertexNULL(GLenum mode, - const GLsizei *count, - GLenum type, - const void *const *indices, - GLsizei drawcount, - const GLint *basevertex); -void INTERNAL_GL_APIENTRY glMultiDrawElementsIndirectNULL(GLenum mode, - GLenum type, - const void *indirect, - GLsizei drawcount, - GLsizei stride); -void INTERNAL_GL_APIENTRY glNamedBufferDataNULL(GLuint buffer, - GLsizeiptr size, - const void *data, - GLenum usage); -void INTERNAL_GL_APIENTRY glNamedBufferStorageNULL(GLuint buffer, - GLsizeiptr size, - const void *data, - GLbitfield flags); -void INTERNAL_GL_APIENTRY glNamedBufferStorageMemEXTNULL(GLuint buffer, - GLsizeiptr size, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glNamedBufferSubDataNULL(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - const void *data); -void INTERNAL_GL_APIENTRY glNamedFramebufferDrawBufferNULL(GLuint framebuffer, GLenum buf); -void INTERNAL_GL_APIENTRY glNamedFramebufferDrawBuffersNULL(GLuint framebuffer, - GLsizei n, - const GLenum *bufs); -void INTERNAL_GL_APIENTRY glNamedFramebufferParameteriNULL(GLuint framebuffer, - GLenum pname, - GLint param); -void INTERNAL_GL_APIENTRY glNamedFramebufferReadBufferNULL(GLuint framebuffer, GLenum src); -void INTERNAL_GL_APIENTRY glNamedFramebufferRenderbufferNULL(GLuint framebuffer, - GLenum attachment, - GLenum renderbuffertarget, - GLuint renderbuffer); -void INTERNAL_GL_APIENTRY glNamedFramebufferTextureNULL(GLuint framebuffer, - GLenum attachment, - GLuint texture, - GLint level); -void INTERNAL_GL_APIENTRY glNamedFramebufferTextureLayerNULL(GLuint framebuffer, - GLenum attachment, - GLuint texture, - GLint level, - GLint layer); -void INTERNAL_GL_APIENTRY glNamedRenderbufferStorageNULL(GLuint renderbuffer, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glNamedRenderbufferStorageMultisampleNULL(GLuint renderbuffer, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glObjectLabelNULL(GLenum identifier, - GLuint name, - GLsizei length, - const GLchar *label); -void INTERNAL_GL_APIENTRY glObjectPtrLabelNULL(const void *ptr, - GLsizei length, - const GLchar *label); -void INTERNAL_GL_APIENTRY glPatchParameterfvNULL(GLenum pname, const GLfloat *values); -void INTERNAL_GL_APIENTRY glPatchParameteriNULL(GLenum pname, GLint value); -void INTERNAL_GL_APIENTRY glPauseTransformFeedbackNULL(); -void INTERNAL_GL_APIENTRY glPixelStorefNULL(GLenum pname, GLfloat param); -void INTERNAL_GL_APIENTRY glPixelStoreiNULL(GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glPointParameterfNULL(GLenum pname, GLfloat param); -void INTERNAL_GL_APIENTRY glPointParameterfvNULL(GLenum pname, const GLfloat *params); -void INTERNAL_GL_APIENTRY glPointParameteriNULL(GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glPointParameterivNULL(GLenum pname, const GLint *params); -void INTERNAL_GL_APIENTRY glPointSizeNULL(GLfloat size); -void INTERNAL_GL_APIENTRY glPolygonModeNULL(GLenum face, GLenum mode); -void INTERNAL_GL_APIENTRY glPolygonModeNVNULL(GLenum face, GLenum mode); -void INTERNAL_GL_APIENTRY glPolygonOffsetNULL(GLfloat factor, GLfloat units); -void INTERNAL_GL_APIENTRY glPolygonOffsetClampEXTNULL(GLfloat factor, GLfloat units, GLfloat clamp); -void INTERNAL_GL_APIENTRY glPopDebugGroupNULL(); -void INTERNAL_GL_APIENTRY glPopGroupMarkerEXTNULL(); -void INTERNAL_GL_APIENTRY glPrimitiveBoundingBoxNULL(GLfloat minX, - GLfloat minY, - GLfloat minZ, - GLfloat minW, - GLfloat maxX, - GLfloat maxY, - GLfloat maxZ, - GLfloat maxW); -void INTERNAL_GL_APIENTRY glPrimitiveRestartIndexNULL(GLuint index); -void INTERNAL_GL_APIENTRY glProgramBinaryNULL(GLuint program, - GLenum binaryFormat, - const void *binary, - GLsizei length); -void INTERNAL_GL_APIENTRY glProgramParameteriNULL(GLuint program, GLenum pname, GLint value); -void INTERNAL_GL_APIENTRY glProgramUniform1dNULL(GLuint program, GLint location, GLdouble v0); -void INTERNAL_GL_APIENTRY glProgramUniform1dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniform1fNULL(GLuint program, GLint location, GLfloat v0); -void INTERNAL_GL_APIENTRY glProgramUniform1fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniform1iNULL(GLuint program, GLint location, GLint v0); -void INTERNAL_GL_APIENTRY glProgramUniform1ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value); -void INTERNAL_GL_APIENTRY glProgramUniform1uiNULL(GLuint program, GLint location, GLuint v0); -void INTERNAL_GL_APIENTRY glProgramUniform1uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value); -void INTERNAL_GL_APIENTRY glProgramUniform2dNULL(GLuint program, - GLint location, - GLdouble v0, - GLdouble v1); -void INTERNAL_GL_APIENTRY glProgramUniform2dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniform2fNULL(GLuint program, - GLint location, - GLfloat v0, - GLfloat v1); -void INTERNAL_GL_APIENTRY glProgramUniform2fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniform2iNULL(GLuint program, - GLint location, - GLint v0, - GLint v1); -void INTERNAL_GL_APIENTRY glProgramUniform2ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value); -void INTERNAL_GL_APIENTRY glProgramUniform2uiNULL(GLuint program, - GLint location, - GLuint v0, - GLuint v1); -void INTERNAL_GL_APIENTRY glProgramUniform2uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value); -void INTERNAL_GL_APIENTRY -glProgramUniform3dNULL(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); -void INTERNAL_GL_APIENTRY glProgramUniform3dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value); -void INTERNAL_GL_APIENTRY -glProgramUniform3fNULL(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -void INTERNAL_GL_APIENTRY glProgramUniform3fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value); -void INTERNAL_GL_APIENTRY -glProgramUniform3iNULL(GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -void INTERNAL_GL_APIENTRY glProgramUniform3ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value); -void INTERNAL_GL_APIENTRY -glProgramUniform3uiNULL(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -void INTERNAL_GL_APIENTRY glProgramUniform3uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value); -void INTERNAL_GL_APIENTRY glProgramUniform4dNULL(GLuint program, - GLint location, - GLdouble v0, - GLdouble v1, - GLdouble v2, - GLdouble v3); -void INTERNAL_GL_APIENTRY glProgramUniform4dvNULL(GLuint program, - GLint location, - GLsizei count, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniform4fNULL(GLuint program, - GLint location, - GLfloat v0, - GLfloat v1, - GLfloat v2, - GLfloat v3); -void INTERNAL_GL_APIENTRY glProgramUniform4fvNULL(GLuint program, - GLint location, - GLsizei count, - const GLfloat *value); -void INTERNAL_GL_APIENTRY -glProgramUniform4iNULL(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -void INTERNAL_GL_APIENTRY glProgramUniform4ivNULL(GLuint program, - GLint location, - GLsizei count, - const GLint *value); -void INTERNAL_GL_APIENTRY -glProgramUniform4uiNULL(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -void INTERNAL_GL_APIENTRY glProgramUniform4uivNULL(GLuint program, - GLint location, - GLsizei count, - const GLuint *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x3dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x3fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x4dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix2x4fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x2dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x2fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x4dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix3x4fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x2dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x2fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x3dvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glProgramUniformMatrix4x3fvNULL(GLuint program, - GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glProvokingVertexNULL(GLenum mode); -void INTERNAL_GL_APIENTRY glPushDebugGroupNULL(GLenum source, - GLuint id, - GLsizei length, - const GLchar *message); -void INTERNAL_GL_APIENTRY glPushGroupMarkerEXTNULL(GLsizei length, const GLchar *marker); -void INTERNAL_GL_APIENTRY glQueryCounterNULL(GLuint id, GLenum target); -void INTERNAL_GL_APIENTRY glReadBufferNULL(GLenum src); -void INTERNAL_GL_APIENTRY glReadPixelsNULL(GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - void *pixels); -void INTERNAL_GL_APIENTRY glReadnPixelsNULL(GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLsizei bufSize, - void *data); -void INTERNAL_GL_APIENTRY glReleaseShaderCompilerNULL(); -void INTERNAL_GL_APIENTRY glRenderbufferStorageNULL(GLenum target, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glRenderbufferStorageMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glRenderbufferStorageMultisampleEXTNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glRenderbufferStorageMultisampleIMGNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glResumeTransformFeedbackNULL(); -void INTERNAL_GL_APIENTRY glSampleCoverageNULL(GLfloat value, GLboolean invert); -void INTERNAL_GL_APIENTRY glSampleMaskiNULL(GLuint maskNumber, GLbitfield mask); -void INTERNAL_GL_APIENTRY glSamplerParameterIivNULL(GLuint sampler, - GLenum pname, - const GLint *param); -void INTERNAL_GL_APIENTRY glSamplerParameterIuivNULL(GLuint sampler, - GLenum pname, - const GLuint *param); -void INTERNAL_GL_APIENTRY glSamplerParameterfNULL(GLuint sampler, GLenum pname, GLfloat param); -void INTERNAL_GL_APIENTRY glSamplerParameterfvNULL(GLuint sampler, - GLenum pname, - const GLfloat *param); -void INTERNAL_GL_APIENTRY glSamplerParameteriNULL(GLuint sampler, GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glSamplerParameterivNULL(GLuint sampler, - GLenum pname, - const GLint *param); -void INTERNAL_GL_APIENTRY glScissorNULL(GLint x, GLint y, GLsizei width, GLsizei height); -void INTERNAL_GL_APIENTRY glScissorArrayvNULL(GLuint first, GLsizei count, const GLint *v); -void INTERNAL_GL_APIENTRY -glScissorIndexedNULL(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); -void INTERNAL_GL_APIENTRY glScissorIndexedvNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY glSemaphoreParameterui64vEXTNULL(GLuint semaphore, - GLenum pname, - const GLuint64 *params); -void INTERNAL_GL_APIENTRY glSetFenceNVNULL(GLuint fence, GLenum condition); -void INTERNAL_GL_APIENTRY glShaderBinaryNULL(GLsizei count, - const GLuint *shaders, - GLenum binaryFormat, - const void *binary, - GLsizei length); -void INTERNAL_GL_APIENTRY glShaderSourceNULL(GLuint shader, - GLsizei count, - const GLchar *const *string, - const GLint *length); -void INTERNAL_GL_APIENTRY glShaderStorageBlockBindingNULL(GLuint program, - GLuint storageBlockIndex, - GLuint storageBlockBinding); -void INTERNAL_GL_APIENTRY glSignalSemaphoreEXTNULL(GLuint semaphore, - GLuint numBufferBarriers, - const GLuint *buffers, - GLuint numTextureBarriers, - const GLuint *textures, - const GLenum *dstLayouts); -void INTERNAL_GL_APIENTRY -glStartTilingQCOMNULL(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); -void INTERNAL_GL_APIENTRY glStencilFuncNULL(GLenum func, GLint ref, GLuint mask); -void INTERNAL_GL_APIENTRY glStencilFuncSeparateNULL(GLenum face, - GLenum func, - GLint ref, - GLuint mask); -void INTERNAL_GL_APIENTRY glStencilMaskNULL(GLuint mask); -void INTERNAL_GL_APIENTRY glStencilMaskSeparateNULL(GLenum face, GLuint mask); -void INTERNAL_GL_APIENTRY glStencilOpNULL(GLenum fail, GLenum zfail, GLenum zpass); -void INTERNAL_GL_APIENTRY glStencilOpSeparateNULL(GLenum face, - GLenum sfail, - GLenum dpfail, - GLenum dppass); -GLboolean INTERNAL_GL_APIENTRY glTestFenceNVNULL(GLuint fence); -void INTERNAL_GL_APIENTRY glTexBufferNULL(GLenum target, GLenum internalformat, GLuint buffer); -void INTERNAL_GL_APIENTRY glTexBufferEXTNULL(GLenum target, GLenum internalformat, GLuint buffer); -void INTERNAL_GL_APIENTRY glTexBufferOESNULL(GLenum target, GLenum internalformat, GLuint buffer); -void INTERNAL_GL_APIENTRY glTexBufferRangeNULL(GLenum target, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glTexBufferRangeEXTNULL(GLenum target, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glTexBufferRangeOESNULL(GLenum target, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glTexImage1DNULL(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLint border, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTexImage2DNULL(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTexImage2DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLboolean fixedsamplelocations); -void INTERNAL_GL_APIENTRY glTexImage3DNULL(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTexImage3DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedsamplelocations); -void INTERNAL_GL_APIENTRY glTexParameterIivNULL(GLenum target, GLenum pname, const GLint *params); -void INTERNAL_GL_APIENTRY glTexParameterIuivNULL(GLenum target, GLenum pname, const GLuint *params); -void INTERNAL_GL_APIENTRY glTexParameterfNULL(GLenum target, GLenum pname, GLfloat param); -void INTERNAL_GL_APIENTRY glTexParameterfvNULL(GLenum target, GLenum pname, const GLfloat *params); -void INTERNAL_GL_APIENTRY glTexParameteriNULL(GLenum target, GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glTexParameterivNULL(GLenum target, GLenum pname, const GLint *params); -void INTERNAL_GL_APIENTRY glTexStorage1DNULL(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width); -void INTERNAL_GL_APIENTRY glTexStorage2DNULL(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glTexStorage2DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLboolean fixedsamplelocations); -void INTERNAL_GL_APIENTRY glTexStorage3DNULL(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth); -void INTERNAL_GL_APIENTRY glTexStorage3DMultisampleNULL(GLenum target, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedsamplelocations); -void INTERNAL_GL_APIENTRY glTexStorageMem2DEXTNULL(GLenum target, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTexStorageMem2DMultisampleEXTNULL(GLenum target, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTexStorageMem3DEXTNULL(GLenum target, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTexStorageMem3DMultisampleEXTNULL(GLenum target, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTexSubImage1DNULL(GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTexSubImage2DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTexSubImage3DNULL(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTextureBarrierNULL(); -void INTERNAL_GL_APIENTRY glTextureBufferNULL(GLuint texture, GLenum internalformat, GLuint buffer); -void INTERNAL_GL_APIENTRY glTextureBufferRangeNULL(GLuint texture, - GLenum internalformat, - GLuint buffer, - GLintptr offset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glTextureParameterIivNULL(GLuint texture, - GLenum pname, - const GLint *params); -void INTERNAL_GL_APIENTRY glTextureParameterIuivNULL(GLuint texture, - GLenum pname, - const GLuint *params); -void INTERNAL_GL_APIENTRY glTextureParameterfNULL(GLuint texture, GLenum pname, GLfloat param); -void INTERNAL_GL_APIENTRY glTextureParameterfvNULL(GLuint texture, - GLenum pname, - const GLfloat *param); -void INTERNAL_GL_APIENTRY glTextureParameteriNULL(GLuint texture, GLenum pname, GLint param); -void INTERNAL_GL_APIENTRY glTextureParameterivNULL(GLuint texture, - GLenum pname, - const GLint *param); -void INTERNAL_GL_APIENTRY glTextureStorage1DNULL(GLuint texture, - GLsizei levels, - GLenum internalformat, - GLsizei width); -void INTERNAL_GL_APIENTRY glTextureStorage2DNULL(GLuint texture, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height); -void INTERNAL_GL_APIENTRY glTextureStorage2DMultisampleNULL(GLuint texture, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLboolean fixedsamplelocations); -void INTERNAL_GL_APIENTRY glTextureStorage3DNULL(GLuint texture, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth); -void INTERNAL_GL_APIENTRY glTextureStorage3DMultisampleNULL(GLuint texture, - GLsizei samples, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedsamplelocations); -void INTERNAL_GL_APIENTRY glTextureStorageMem2DEXTNULL(GLuint texture, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTextureStorageMem2DMultisampleEXTNULL(GLuint texture, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTextureStorageMem3DEXTNULL(GLuint texture, - GLsizei levels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTextureStorageMem3DMultisampleEXTNULL(GLuint texture, - GLsizei samples, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLboolean fixedSampleLocations, - GLuint memory, - GLuint64 offset); -void INTERNAL_GL_APIENTRY glTextureSubImage1DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTextureSubImage2DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTextureSubImage3DNULL(GLuint texture, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void *pixels); -void INTERNAL_GL_APIENTRY glTextureViewNULL(GLuint texture, - GLenum target, - GLuint origtexture, - GLenum internalformat, - GLuint minlevel, - GLuint numlevels, - GLuint minlayer, - GLuint numlayers); -void INTERNAL_GL_APIENTRY glTransformFeedbackBufferBaseNULL(GLuint xfb, - GLuint index, - GLuint buffer); -void INTERNAL_GL_APIENTRY glTransformFeedbackBufferRangeNULL(GLuint xfb, - GLuint index, - GLuint buffer, - GLintptr offset, - GLsizeiptr size); -void INTERNAL_GL_APIENTRY glTransformFeedbackVaryingsNULL(GLuint program, - GLsizei count, - const GLchar *const *varyings, - GLenum bufferMode); -void INTERNAL_GL_APIENTRY glUniform1dNULL(GLint location, GLdouble x); -void INTERNAL_GL_APIENTRY glUniform1dvNULL(GLint location, GLsizei count, const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniform1fNULL(GLint location, GLfloat v0); -void INTERNAL_GL_APIENTRY glUniform1fvNULL(GLint location, GLsizei count, const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniform1iNULL(GLint location, GLint v0); -void INTERNAL_GL_APIENTRY glUniform1ivNULL(GLint location, GLsizei count, const GLint *value); -void INTERNAL_GL_APIENTRY glUniform1uiNULL(GLint location, GLuint v0); -void INTERNAL_GL_APIENTRY glUniform1uivNULL(GLint location, GLsizei count, const GLuint *value); -void INTERNAL_GL_APIENTRY glUniform2dNULL(GLint location, GLdouble x, GLdouble y); -void INTERNAL_GL_APIENTRY glUniform2dvNULL(GLint location, GLsizei count, const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniform2fNULL(GLint location, GLfloat v0, GLfloat v1); -void INTERNAL_GL_APIENTRY glUniform2fvNULL(GLint location, GLsizei count, const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniform2iNULL(GLint location, GLint v0, GLint v1); -void INTERNAL_GL_APIENTRY glUniform2ivNULL(GLint location, GLsizei count, const GLint *value); -void INTERNAL_GL_APIENTRY glUniform2uiNULL(GLint location, GLuint v0, GLuint v1); -void INTERNAL_GL_APIENTRY glUniform2uivNULL(GLint location, GLsizei count, const GLuint *value); -void INTERNAL_GL_APIENTRY glUniform3dNULL(GLint location, GLdouble x, GLdouble y, GLdouble z); -void INTERNAL_GL_APIENTRY glUniform3dvNULL(GLint location, GLsizei count, const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniform3fNULL(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -void INTERNAL_GL_APIENTRY glUniform3fvNULL(GLint location, GLsizei count, const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniform3iNULL(GLint location, GLint v0, GLint v1, GLint v2); -void INTERNAL_GL_APIENTRY glUniform3ivNULL(GLint location, GLsizei count, const GLint *value); -void INTERNAL_GL_APIENTRY glUniform3uiNULL(GLint location, GLuint v0, GLuint v1, GLuint v2); -void INTERNAL_GL_APIENTRY glUniform3uivNULL(GLint location, GLsizei count, const GLuint *value); -void INTERNAL_GL_APIENTRY -glUniform4dNULL(GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void INTERNAL_GL_APIENTRY glUniform4dvNULL(GLint location, GLsizei count, const GLdouble *value); -void INTERNAL_GL_APIENTRY -glUniform4fNULL(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -void INTERNAL_GL_APIENTRY glUniform4fvNULL(GLint location, GLsizei count, const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniform4iNULL(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -void INTERNAL_GL_APIENTRY glUniform4ivNULL(GLint location, GLsizei count, const GLint *value); -void INTERNAL_GL_APIENTRY -glUniform4uiNULL(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -void INTERNAL_GL_APIENTRY glUniform4uivNULL(GLint location, GLsizei count, const GLuint *value); -void INTERNAL_GL_APIENTRY glUniformBlockBindingNULL(GLuint program, - GLuint uniformBlockIndex, - GLuint uniformBlockBinding); -void INTERNAL_GL_APIENTRY glUniformMatrix2dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix2fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix2x3dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix2x3fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix2x4dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix2x4fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix3dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix3fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix3x2dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix3x2fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix3x4dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix3x4fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix4dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix4fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix4x2dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix4x2fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformMatrix4x3dvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLdouble *value); -void INTERNAL_GL_APIENTRY glUniformMatrix4x3fvNULL(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value); -void INTERNAL_GL_APIENTRY glUniformSubroutinesuivNULL(GLenum shadertype, - GLsizei count, - const GLuint *indices); -GLboolean INTERNAL_GL_APIENTRY glUnmapBufferNULL(GLenum target); -GLboolean INTERNAL_GL_APIENTRY glUnmapNamedBufferNULL(GLuint buffer); -void INTERNAL_GL_APIENTRY glUseProgramNULL(GLuint program); -void INTERNAL_GL_APIENTRY glUseProgramStagesNULL(GLuint pipeline, - GLbitfield stages, - GLuint program); -void INTERNAL_GL_APIENTRY glValidateProgramNULL(GLuint program); -void INTERNAL_GL_APIENTRY glValidateProgramPipelineNULL(GLuint pipeline); -void INTERNAL_GL_APIENTRY glVertexArrayAttribBindingNULL(GLuint vaobj, - GLuint attribindex, - GLuint bindingindex); -void INTERNAL_GL_APIENTRY glVertexArrayAttribFormatNULL(GLuint vaobj, - GLuint attribindex, - GLint size, - GLenum type, - GLboolean normalized, - GLuint relativeoffset); -void INTERNAL_GL_APIENTRY glVertexArrayAttribIFormatNULL(GLuint vaobj, - GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset); -void INTERNAL_GL_APIENTRY glVertexArrayAttribLFormatNULL(GLuint vaobj, - GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset); -void INTERNAL_GL_APIENTRY glVertexArrayBindingDivisorNULL(GLuint vaobj, - GLuint bindingindex, - GLuint divisor); -void INTERNAL_GL_APIENTRY glVertexArrayElementBufferNULL(GLuint vaobj, GLuint buffer); -void INTERNAL_GL_APIENTRY glVertexArrayVertexBufferNULL(GLuint vaobj, - GLuint bindingindex, - GLuint buffer, - GLintptr offset, - GLsizei stride); -void INTERNAL_GL_APIENTRY glVertexArrayVertexBuffersNULL(GLuint vaobj, - GLuint first, - GLsizei count, - const GLuint *buffers, - const GLintptr *offsets, - const GLsizei *strides); -void INTERNAL_GL_APIENTRY glVertexAttrib1dNULL(GLuint index, GLdouble x); -void INTERNAL_GL_APIENTRY glVertexAttrib1dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY glVertexAttrib1fNULL(GLuint index, GLfloat x); -void INTERNAL_GL_APIENTRY glVertexAttrib1fvNULL(GLuint index, const GLfloat *v); -void INTERNAL_GL_APIENTRY glVertexAttrib1sNULL(GLuint index, GLshort x); -void INTERNAL_GL_APIENTRY glVertexAttrib1svNULL(GLuint index, const GLshort *v); -void INTERNAL_GL_APIENTRY glVertexAttrib2dNULL(GLuint index, GLdouble x, GLdouble y); -void INTERNAL_GL_APIENTRY glVertexAttrib2dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY glVertexAttrib2fNULL(GLuint index, GLfloat x, GLfloat y); -void INTERNAL_GL_APIENTRY glVertexAttrib2fvNULL(GLuint index, const GLfloat *v); -void INTERNAL_GL_APIENTRY glVertexAttrib2sNULL(GLuint index, GLshort x, GLshort y); -void INTERNAL_GL_APIENTRY glVertexAttrib2svNULL(GLuint index, const GLshort *v); -void INTERNAL_GL_APIENTRY glVertexAttrib3dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z); -void INTERNAL_GL_APIENTRY glVertexAttrib3dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY glVertexAttrib3fNULL(GLuint index, GLfloat x, GLfloat y, GLfloat z); -void INTERNAL_GL_APIENTRY glVertexAttrib3fvNULL(GLuint index, const GLfloat *v); -void INTERNAL_GL_APIENTRY glVertexAttrib3sNULL(GLuint index, GLshort x, GLshort y, GLshort z); -void INTERNAL_GL_APIENTRY glVertexAttrib3svNULL(GLuint index, const GLshort *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4NbvNULL(GLuint index, const GLbyte *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4NivNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4NsvNULL(GLuint index, const GLshort *v); -void INTERNAL_GL_APIENTRY -glVertexAttrib4NubNULL(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -void INTERNAL_GL_APIENTRY glVertexAttrib4NubvNULL(GLuint index, const GLubyte *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4NuivNULL(GLuint index, const GLuint *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4NusvNULL(GLuint index, const GLushort *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4bvNULL(GLuint index, const GLbyte *v); -void INTERNAL_GL_APIENTRY -glVertexAttrib4dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void INTERNAL_GL_APIENTRY glVertexAttrib4dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY -glVertexAttrib4fNULL(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void INTERNAL_GL_APIENTRY glVertexAttrib4fvNULL(GLuint index, const GLfloat *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4ivNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY -glVertexAttrib4sNULL(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -void INTERNAL_GL_APIENTRY glVertexAttrib4svNULL(GLuint index, const GLshort *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4ubvNULL(GLuint index, const GLubyte *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4uivNULL(GLuint index, const GLuint *v); -void INTERNAL_GL_APIENTRY glVertexAttrib4usvNULL(GLuint index, const GLushort *v); -void INTERNAL_GL_APIENTRY glVertexAttribBindingNULL(GLuint attribindex, GLuint bindingindex); -void INTERNAL_GL_APIENTRY glVertexAttribDivisorNULL(GLuint index, GLuint divisor); -void INTERNAL_GL_APIENTRY glVertexAttribFormatNULL(GLuint attribindex, - GLint size, - GLenum type, - GLboolean normalized, - GLuint relativeoffset); -void INTERNAL_GL_APIENTRY glVertexAttribI1iNULL(GLuint index, GLint x); -void INTERNAL_GL_APIENTRY glVertexAttribI1ivNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI1uiNULL(GLuint index, GLuint x); -void INTERNAL_GL_APIENTRY glVertexAttribI1uivNULL(GLuint index, const GLuint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI2iNULL(GLuint index, GLint x, GLint y); -void INTERNAL_GL_APIENTRY glVertexAttribI2ivNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI2uiNULL(GLuint index, GLuint x, GLuint y); -void INTERNAL_GL_APIENTRY glVertexAttribI2uivNULL(GLuint index, const GLuint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI3iNULL(GLuint index, GLint x, GLint y, GLint z); -void INTERNAL_GL_APIENTRY glVertexAttribI3ivNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI3uiNULL(GLuint index, GLuint x, GLuint y, GLuint z); -void INTERNAL_GL_APIENTRY glVertexAttribI3uivNULL(GLuint index, const GLuint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI4bvNULL(GLuint index, const GLbyte *v); -void INTERNAL_GL_APIENTRY glVertexAttribI4iNULL(GLuint index, GLint x, GLint y, GLint z, GLint w); -void INTERNAL_GL_APIENTRY glVertexAttribI4ivNULL(GLuint index, const GLint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI4svNULL(GLuint index, const GLshort *v); -void INTERNAL_GL_APIENTRY glVertexAttribI4ubvNULL(GLuint index, const GLubyte *v); -void INTERNAL_GL_APIENTRY -glVertexAttribI4uiNULL(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -void INTERNAL_GL_APIENTRY glVertexAttribI4uivNULL(GLuint index, const GLuint *v); -void INTERNAL_GL_APIENTRY glVertexAttribI4usvNULL(GLuint index, const GLushort *v); -void INTERNAL_GL_APIENTRY glVertexAttribIFormatNULL(GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset); -void INTERNAL_GL_APIENTRY glVertexAttribIPointerNULL(GLuint index, - GLint size, - GLenum type, - GLsizei stride, - const void *pointer); -void INTERNAL_GL_APIENTRY glVertexAttribL1dNULL(GLuint index, GLdouble x); -void INTERNAL_GL_APIENTRY glVertexAttribL1dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY glVertexAttribL2dNULL(GLuint index, GLdouble x, GLdouble y); -void INTERNAL_GL_APIENTRY glVertexAttribL2dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY glVertexAttribL3dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z); -void INTERNAL_GL_APIENTRY glVertexAttribL3dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY -glVertexAttribL4dNULL(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void INTERNAL_GL_APIENTRY glVertexAttribL4dvNULL(GLuint index, const GLdouble *v); -void INTERNAL_GL_APIENTRY glVertexAttribLFormatNULL(GLuint attribindex, - GLint size, - GLenum type, - GLuint relativeoffset); -void INTERNAL_GL_APIENTRY glVertexAttribLPointerNULL(GLuint index, - GLint size, - GLenum type, - GLsizei stride, - const void *pointer); -void INTERNAL_GL_APIENTRY glVertexAttribP1uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value); -void INTERNAL_GL_APIENTRY glVertexAttribP1uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value); -void INTERNAL_GL_APIENTRY glVertexAttribP2uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value); -void INTERNAL_GL_APIENTRY glVertexAttribP2uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value); -void INTERNAL_GL_APIENTRY glVertexAttribP3uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value); -void INTERNAL_GL_APIENTRY glVertexAttribP3uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value); -void INTERNAL_GL_APIENTRY glVertexAttribP4uiNULL(GLuint index, - GLenum type, - GLboolean normalized, - GLuint value); -void INTERNAL_GL_APIENTRY glVertexAttribP4uivNULL(GLuint index, - GLenum type, - GLboolean normalized, - const GLuint *value); -void INTERNAL_GL_APIENTRY glVertexAttribPointerNULL(GLuint index, - GLint size, - GLenum type, - GLboolean normalized, - GLsizei stride, - const void *pointer); -void INTERNAL_GL_APIENTRY glVertexBindingDivisorNULL(GLuint bindingindex, GLuint divisor); -void INTERNAL_GL_APIENTRY glViewportNULL(GLint x, GLint y, GLsizei width, GLsizei height); -void INTERNAL_GL_APIENTRY glViewportArrayvNULL(GLuint first, GLsizei count, const GLfloat *v); -void INTERNAL_GL_APIENTRY -glViewportIndexedfNULL(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); -void INTERNAL_GL_APIENTRY glViewportIndexedfvNULL(GLuint index, const GLfloat *v); -void INTERNAL_GL_APIENTRY glWaitSemaphoreEXTNULL(GLuint semaphore, - GLuint numBufferBarriers, - const GLuint *buffers, - GLuint numTextureBarriers, - const GLuint *textures, - const GLenum *srcLayouts); -void INTERNAL_GL_APIENTRY glWaitSyncNULL(GLsync sync, GLbitfield flags, GLuint64 timeout); -} // namespace rx - -#endif // LIBGLESV2_RENDERER_GL_NULL_GL_FUNCTIONS_AUTOGEN_H_ diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp index a54b3a31679..a2c6e473d95 100644 --- a/src/libANGLE/renderer/gl/renderergl_utils.cpp +++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp @@ -7,11 +7,16 @@ // renderergl_utils.cpp: Conversion functions and other utility routines // specific to the OpenGL renderer. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/gl/renderergl_utils.h" #include #include +#include "GLSLANG/ShaderLang.h" #include "common/android_util.h" #include "common/mathutil.h" #include "common/platform.h" @@ -205,6 +210,18 @@ bool IsPowerVrRogue(const FunctionsGL *functions) return angle::BeginsWith(nativeGLRenderer, powerVRRogue); } +bool IsHuaweiMaleoon(const FunctionsGL *functions) +{ + const char *nativeGLVendor = GetString(functions, GL_VENDOR); + const char *nativeGLRenderer = GetString(functions, GL_RENDERER); + return (std::string(nativeGLVendor).find("HUAWEI") != std::string::npos) && + (std::string(nativeGLRenderer).find("Maleoon") != std::string::npos); +} + +bool PrecisionMeetsSpecForHighpFloat(const gl::TypePrecision &precision) +{ + return precision.range[0] >= 62 && precision.range[1] >= 62 && precision.precision >= 16; +} } // namespace SwapControlData::SwapControlData() @@ -275,68 +292,65 @@ uint32_t GetDeviceID(const FunctionsGL *functions) return 0; } -ShShaderOutput GetShaderOutputType(const FunctionsGL *functions) +ShShaderOutput GetShaderOutputType(const angle::FeaturesGL &features, const FunctionsGL *functions) { ASSERT(functions); if (functions->standard == STANDARD_GL_DESKTOP) { // GLSL outputs - if (functions->isAtLeastGL(gl::Version(4, 5))) - { - return SH_GLSL_450_CORE_OUTPUT; - } - else if (functions->isAtLeastGL(gl::Version(4, 4))) + if (!features.emitMaxGlsl400ForTesting.enabled) { - return SH_GLSL_440_CORE_OUTPUT; - } - else if (functions->isAtLeastGL(gl::Version(4, 3))) - { - return SH_GLSL_430_CORE_OUTPUT; - } - else if (functions->isAtLeastGL(gl::Version(4, 2))) - { - return SH_GLSL_420_CORE_OUTPUT; - } - else if (functions->isAtLeastGL(gl::Version(4, 1))) - { - return SH_GLSL_410_CORE_OUTPUT; + if (functions->isAtLeastGL(gl::Version(4, 5))) + { + return SH_GLSL_450_CORE_OUTPUT; + } + if (functions->isAtLeastGL(gl::Version(4, 4))) + { + return SH_GLSL_440_CORE_OUTPUT; + } + if (functions->isAtLeastGL(gl::Version(4, 3))) + { + return SH_GLSL_430_CORE_OUTPUT; + } + if (functions->isAtLeastGL(gl::Version(4, 2))) + { + return SH_GLSL_420_CORE_OUTPUT; + } + if (functions->isAtLeastGL(gl::Version(4, 1))) + { + return SH_GLSL_410_CORE_OUTPUT; + } } - else if (functions->isAtLeastGL(gl::Version(4, 0))) + if (functions->isAtLeastGL(gl::Version(4, 0))) { return SH_GLSL_400_CORE_OUTPUT; } - else if (functions->isAtLeastGL(gl::Version(3, 3))) + if (functions->isAtLeastGL(gl::Version(3, 3))) { return SH_GLSL_330_CORE_OUTPUT; } - else if (functions->isAtLeastGL(gl::Version(3, 2))) + if (functions->isAtLeastGL(gl::Version(3, 2))) { return SH_GLSL_150_CORE_OUTPUT; } - else if (functions->isAtLeastGL(gl::Version(3, 1))) + if (functions->isAtLeastGL(gl::Version(3, 1))) { return SH_GLSL_140_OUTPUT; } - else if (functions->isAtLeastGL(gl::Version(3, 0))) + if (functions->isAtLeastGL(gl::Version(3, 0))) { return SH_GLSL_130_OUTPUT; } - else - { - return SH_GLSL_COMPATIBILITY_OUTPUT; - } + return SH_GLSL_COMPATIBILITY_OUTPUT; } - else if (functions->standard == STANDARD_GL_ES) + if (functions->standard == STANDARD_GL_ES) { // ESSL outputs return SH_ESSL_OUTPUT; } - else - { - UNREACHABLE(); - return ShShaderOutput(0); - } + UNREACHABLE(); + return ShShaderOutput(0); } namespace nativegl_gl @@ -562,7 +576,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, { GLenum queryInternalFormat = internalFormat; - if (internalFormat == GL_BGRA8_EXT) + if (internalFormat == GL_BGRA8_EXT || internalFormat == GL_BGRA_EXT) { // Querying GL_NUM_SAMPLE_COUNTS for GL_BGRA8_EXT generates an INVALID_ENUM on some // drivers. It seems however that allocating a multisampled renderbuffer of this format @@ -596,6 +610,12 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, continue; } + // Supporting MSAA=1 is not required on OpenGL for non-conformant drivers. + if (features.disableMSAASampleCount1.enabled && samples[sampleIndex] == 1) + { + continue; + } + // Some NVIDIA drivers expose multisampling modes implemented as a combination of // multisampling and supersampling. These are non-conformant and should not be // exposed through ANGLE. Query which formats are conformant from the driver if @@ -617,7 +637,15 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, } if (conformant == GL_TRUE) { - textureCaps.sampleCounts.insert(samples[sampleIndex]); + if (gl::isPow2(samples[sampleIndex])) + { + textureCaps.sampleCounts.insert(samples[sampleIndex]); + } + else + { + WARN() << "Skipping unexpected sample count " << samples[sampleIndex] + << " for internal format " << gl::FmtHex(queryInternalFormat) << "."; + } } } } @@ -629,7 +657,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, const gl::InternalFormat &glFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat); if (textureCaps.renderbuffer && !glFormatInfo.isInt() && glFormatInfo.isRequiredRenderbufferFormat(gl::Version(3, 0)) && - textureCaps.getMaxSamples() < 4) + textureCaps.sampleCounts.getMaxSamples() < 4) { LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); } @@ -923,6 +951,12 @@ void GenerateCaps(const FunctionsGL *functions, caps->fragmentHighpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_INT); caps->fragmentMediumpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_INT); caps->fragmentLowpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_INT); + + // highp support is required. + if (!PrecisionMeetsSpecForHighpFloat(caps->fragmentHighpFloat)) + { + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } } else { @@ -1056,9 +1090,8 @@ void GenerateCaps(const FunctionsGL *functions, caps->maxCombinedShaderUniformComponents[gl::ShaderType::Fragment] = QuerySingleGLInt64(functions, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS); - // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size - // currently), some drivers expose an excessively large value. - caps->maxUniformBlockSize = std::min(0x10000, caps->maxUniformBlockSize); + caps->maxUniformBlockSize = + std::min(gl::IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE, caps->maxUniformBlockSize); } else { @@ -1348,6 +1381,12 @@ void GenerateCaps(const FunctionsGL *functions, caps->maxImageUnits = QuerySingleGLInt(functions, GL_MAX_IMAGE_UNITS); caps->maxCombinedImageUniforms = QuerySingleGLInt(functions, GL_MAX_COMBINED_IMAGE_UNIFORMS); + if (features.forceMaxCombinedShaderOutputResources.enabled) + { + caps->maxCombinedShaderOutputResources = caps->maxCombinedImageUniforms + + caps->maxCombinedShaderStorageBlocks + + caps->maxColorAttachments; + } } else { @@ -1449,7 +1488,6 @@ void GenerateCaps(const FunctionsGL *functions, functions->hasGLExtension("GL_ARB_pixel_buffer_object") || functions->hasGLExtension("GL_EXT_pixel_buffer_object") || functions->hasGLESExtension("GL_NV_pixel_buffer_object"); - extensions->syncARB = nativegl::SupportsFenceSync(functions); extensions->mapbufferOES = functions->isAtLeastGL(gl::Version(1, 5)) || functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_mapbuffer"); @@ -1692,7 +1730,7 @@ void GenerateCaps(const FunctionsGL *functions, functions->hasGLExtension("GL_ARB_stencil_texturing") || functions->isAtLeastGLES(gl::Version(3, 1)); - if (features.supportsShaderFramebufferFetchEXT.enabled) + if (features.supportsShaderFramebufferFetchEXT.enabled && extensions->drawBuffersIndexedAny()) { // We can support PLS natively, probably in tiled memory. extensions->shaderPixelLocalStorageANGLE = true; @@ -1783,7 +1821,6 @@ void GenerateCaps(const FunctionsGL *functions, } extensions->copyTextureCHROMIUM = true; - extensions->syncQueryCHROMIUM = SyncQueryGL::IsSupported(functions); // Note that OES_texture_storage_multisample_2d_array support could be extended down to GL 3.2 // if we emulated texStorage* API on top of texImage*. @@ -1792,8 +1829,8 @@ void GenerateCaps(const FunctionsGL *functions, functions->hasGLExtension("GL_ARB_texture_storage_multisample") || functions->hasGLESExtension("GL_OES_texture_storage_multisample_2d_array"); - extensions->multiviewMultisampleANGLE = extensions->textureStorageMultisample2dArrayOES && - (extensions->multiviewOVR || extensions->multiview2OVR); + extensions->multiviewMultisampleANGLE = + extensions->textureStorageMultisample2dArrayOES && extensions->multiviewOVR; extensions->textureMultisampleANGLE = functions->isAtLeastGL(gl::Version(3, 2)) || functions->hasGLExtension("GL_ARB_texture_multisample") || @@ -1931,9 +1968,8 @@ void GenerateCaps(const FunctionsGL *functions, // EXT_blend_func_extended is not implemented on top of ARB_blend_func_extended // because the latter does not support fragment shader output layout qualifiers. - extensions->blendFuncExtendedEXT = !features.disableBlendFuncExtended.enabled && - (functions->isAtLeastGL(gl::Version(3, 3)) || - functions->hasGLESExtension("GL_EXT_blend_func_extended")); + extensions->blendFuncExtendedEXT = functions->isAtLeastGL(gl::Version(3, 3)) || + functions->hasGLESExtension("GL_EXT_blend_func_extended"); if (extensions->blendFuncExtendedEXT) { // TODO(http://anglebug.com/40644593): Support greater values of @@ -1956,25 +1992,26 @@ void GenerateCaps(const FunctionsGL *functions, functions->hasGLESExtension("GL_EXT_draw_elements_base_vertex")); // EXT_base_instance - extensions->baseInstanceEXT = - !features.disableBaseInstanceVertex.enabled && - (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 2)) || - functions->hasGLESExtension("GL_OES_draw_elements_base_vertex") || - functions->hasGLESExtension("GL_EXT_draw_elements_base_vertex") || - functions->hasGLESExtension("GL_EXT_base_instance")); + // Unlike the ANGLE variant, this extension is exposed only if supported natively. + extensions->baseInstanceEXT = !features.disableBaseInstanceVertex.enabled && + (functions->isAtLeastGL(gl::Version(4, 2)) || + functions->hasGLExtension("GL_ARB_base_instance") || + functions->hasGLESExtension("GL_EXT_base_instance")); // ANGLE_base_vertex_base_instance_shader_builtin extensions->baseVertexBaseInstanceShaderBuiltinANGLE = extensions->baseVertexBaseInstanceANGLE; // OES_draw_elements_base_vertex extensions->drawElementsBaseVertexOES = - functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 2)) || - functions->hasGLESExtension("GL_OES_draw_elements_base_vertex"); + !features.disableBaseInstanceVertex.enabled && + (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 2)) || + functions->hasGLESExtension("GL_OES_draw_elements_base_vertex")); // EXT_draw_elements_base_vertex extensions->drawElementsBaseVertexEXT = - functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 2)) || - functions->hasGLESExtension("GL_EXT_draw_elements_base_vertex"); + !features.disableBaseInstanceVertex.enabled && + (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 2)) || + functions->hasGLESExtension("GL_EXT_draw_elements_base_vertex")); // ANGLE_compressed_texture_etc // Expose this extension only when we support the formats or we're running on top of a native @@ -2260,6 +2297,7 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature bool isVMWare = IsVMWare(vendor); bool hasAMD = systemInfo.hasAMDGPU(); bool isMali = IsARM(vendor); + bool isHuaweiMaleoon = IsHuaweiMaleoon(functions); std::array mesaVersion = {0, 0, 0}; bool isMesa = IsMesa(functions, &mesaVersion); @@ -2295,11 +2333,6 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ANGLE_FEATURE_CONDITION(features, addAndTrueToLoopCondition, IsApple() && isIntel); - // Ported from gpu_driver_bug_list.json (#191) - ANGLE_FEATURE_CONDITION( - features, emulateIsnanFloat, - isIntel && IsApple() && IsSkylake(device) && GetMacOSVersion() < OSVersion(10, 13, 2)); - // https://anglebug.com/42266803 ANGLE_FEATURE_CONDITION(features, clearsWithGapsNeedFlush, !isMesa && isQualcomm && qualcommVersion < 490); @@ -2313,15 +2346,6 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature features, useUnusedBlocksWithStandardOrSharedLayout, (IsApple() && functions->standard == STANDARD_GL_DESKTOP) || (IsLinux() && isAMD)); - // Ported from gpu_driver_bug_list.json (#187) - ANGLE_FEATURE_CONDITION(features, doWhileGLSLCausesGPUHang, - IsApple() && functions->standard == STANDARD_GL_DESKTOP && - GetMacOSVersion() < OSVersion(10, 11, 0)); - - // Ported from gpu_driver_bug_list.json (#211) - ANGLE_FEATURE_CONDITION(features, rewriteFloatUnaryMinusOperator, - IsApple() && isIntel && GetMacOSVersion() < OSVersion(10, 12, 0)); - ANGLE_FEATURE_CONDITION(features, vertexIDDoesNotIncludeBaseVertex, IsApple() && isAMD); // Triggers a bug on Marshmallow Adreno (4xx?) driver. @@ -2371,10 +2395,6 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ANGLE_FEATURE_CONDITION(features, dontUseLoopsToInitializeVariables, (!isMesa && isQualcomm) || (isIntel && IsApple())); - // Intel macOS condition ported from gpu_driver_bug_list.json (#327) - ANGLE_FEATURE_CONDITION(features, disableBlendFuncExtended, - IsApple() && isIntel && GetMacOSVersion() < OSVersion(10, 14, 0)); - ANGLE_FEATURE_CONDITION(features, avoidBindFragDataLocation, !isMesa && isQualcomm); ANGLE_FEATURE_CONDITION(features, unsizedSRGBReadPixelsDoesntTransform, !isMesa && isQualcomm); @@ -2392,11 +2412,17 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature // 4 is a lowest common denominator that is always supported. ANGLE_FEATURE_CONDITION(features, limitMaxMSAASamplesTo4, IsAndroid() || (IsApple() && (isIntel || isAMD || isNvidia))); + ANGLE_FEATURE_CONDITION(features, disableMSAASampleCount1, isHuaweiMaleoon); ANGLE_FEATURE_CONDITION(features, limitMax3dArrayTextureSizeTo1024, isIntelLinuxLessThanKernelVersion5); ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, IsApple()); + // NVidia and PowerVR Rogue report MAX_COMBINED_SHADER_OUTPUT_RESOURCES incorrectly. + // Force it to the sum of all sublimits. + ANGLE_FEATURE_CONDITION(features, forceMaxCombinedShaderOutputResources, + isNvidia || IsPowerVrRogue(functions)); + // The WebGL conformance/uniforms/out-of-bounds-uniform-array-access test has been seen to fail // on AMD and Android devices. // This test is also flaky on Linux Nvidia. So we just turn it on everywhere and don't rely on @@ -2408,9 +2434,6 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ANGLE_FEATURE_CONDITION(features, resetTexImage2DBaseLevel, IsApple() && isIntel && GetMacOSVersion() >= OSVersion(10, 12, 4)); - ANGLE_FEATURE_CONDITION(features, clearToZeroOrOneBroken, - IsApple() && isIntel && GetMacOSVersion() < OSVersion(10, 12, 6)); - ANGLE_FEATURE_CONDITION(features, adjustSrcDstRegionForBlitFramebuffer, IsLinux() || (IsAndroid() && isNvidia) || (IsWindows() && isNvidia) || (IsApple() && functions->standard == STANDARD_GL_ES)); @@ -2533,12 +2556,12 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ANGLE_FEATURE_CONDITION(features, promotePackedFormatsTo8BitPerChannel, IsApple() && hasAMD); - // crbug.com/1171371 + // http://crbug.com/40166134 // If output variable gl_FragColor is written by fragment shader, it may cause context lost with // Adreno 42x and 3xx. ANGLE_FEATURE_CONDITION(features, initFragmentOutputVariables, IsAdreno42xOr3xx(functions)); - // http://crbug.com/1144207 + // http://crbug.com/40155422 // The Mac bot with Intel Iris GPU seems unaffected by this bug. Exclude the Haswell family for // now. ANGLE_FEATURE_CONDITION(features, shiftInstancedArrayDataWithOffset, @@ -2665,8 +2688,10 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature functions->standard == STANDARD_GL_ES && isMesa && mesaVersion < (std::array{23, 1, 7})); - // http://anglebug.com/42266610 - ANGLE_FEATURE_CONDITION(features, disableBaseInstanceVertex, IsMaliValhall(functions)); + // Mali bug: http://anglebug.com/42266610 + // Linux speculative bugs: http://crbug.com/427956856, http://anglebug.com/431097618 + ANGLE_FEATURE_CONDITION(features, disableBaseInstanceVertex, + IsMaliValhall(functions) || IsLinux()); // Mali: http://crbug.com/40063287 // Nvidia: http://crbug.com/328015191 @@ -2689,7 +2714,7 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature // BGRA formats do not appear to be accepted by the qualcomm driver despite the extension being // exposed. - ANGLE_FEATURE_CONDITION(features, bgraTexImageFormatsBroken, IsQualcomm(vendor)); + ANGLE_FEATURE_CONDITION(features, bgraTexImageFormatsBroken, !isMesa && isQualcomm); // https://github.com/flutter/flutter/issues/47164 // https://github.com/flutter/flutter/issues/47804 @@ -2707,6 +2732,19 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ANGLE_FEATURE_CONDITION( features, disableBlendEquationAdvanced, (isIntel && IsWindows()) || IsAdreno4xx(functions) || IsAdreno5xx(functions) || isMali); + + // Adreno drivers cache some internal values based on glSampleCoverage and + // number of samples in currently bound FBO and require to reset sample + // coverage each time FBO changes. + ANGLE_FEATURE_CONDITION(features, resetSampleCoverageOnFBOChange, isQualcomm); + + // Mali 400 series drivers fail linking shaders when passthrough shaders are enabled. Likely due + // to not querying correct information from varyings and uniforms. + ANGLE_FEATURE_CONDITION(features, disablePassthroughShaders, IsAdreno4xx(functions)); + + // IMG GL drivers crash in glClearTexImage on various format/type combinations such as packed + // types, LUMA and depth stencil. + ANGLE_FEATURE_CONDITION(features, disableClearTexImageForRobustInit, IsPowerVR(vendor)); } void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features) @@ -2717,8 +2755,10 @@ void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFea std::array mesaVersion = {0, 0, 0}; bool isMesa = IsMesa(functions, &mesaVersion); + // Program binaries don't contain transform feedback varyings on multiple vendors' GPUs. + // https://crbug.com/442879525 for the latest example on Imagination / PowerVR. ANGLE_FEATURE_CONDITION(features, disableProgramCachingForTransformFeedback, - !isMesa && isQualcomm); + (!isMesa && isQualcomm) || IsPowerVR(vendor)); // https://crbug.com/480992 // Disable shader program cache to workaround PowerVR Rogue issues. ANGLE_FEATURE_CONDITION(features, disableProgramBinary, IsPowerVrRogue(functions)); @@ -2734,6 +2774,14 @@ void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFea ANGLE_FEATURE_CONDITION(features, linkJobIsThreadSafe, false); ANGLE_FEATURE_CONDITION(features, cacheCompiledShader, true); + + // GL_EXT_clip_cull_distance and GL_NV_shader_noperspective_interpolation are broken on QCOM + // without ANGLE workarounds: the former does not allow built-in redeclarations outside of + // interface blocks and the latter does not compile unless the shader version is at least 310 + // es. + ANGLE_FEATURE_CONDITION(features, clipCullDistanceBrokenWithPassthroughShaders, isQualcomm); + ANGLE_FEATURE_CONDITION(features, noperspectiveInterpolationBrokenWithPassthroughShaders, + isQualcomm); } void ReInitializeFeaturesAtGPUSwitch(const FunctionsGL *functions, angle::FeaturesGL *features) @@ -2788,12 +2836,6 @@ bool SupportsCompute(const FunctionsGL *functions) functions->hasGLExtension("GL_ARB_shader_storage_buffer_object"))); } -bool SupportsFenceSync(const FunctionsGL *functions) -{ - return functions->isAtLeastGL(gl::Version(3, 2)) || functions->hasGLExtension("GL_ARB_sync") || - functions->isAtLeastGLES(gl::Version(3, 0)); -} - bool SupportsOcclusionQueries(const FunctionsGL *functions) { return functions->isAtLeastGL(gl::Version(1, 5)) || diff --git a/src/libANGLE/renderer/gl/renderergl_utils.h b/src/libANGLE/renderer/gl/renderergl_utils.h index 7f8bd6ea77d..5574e2aab7a 100644 --- a/src/libANGLE/renderer/gl/renderergl_utils.h +++ b/src/libANGLE/renderer/gl/renderergl_utils.h @@ -63,7 +63,7 @@ struct SwapControlData }; VendorID GetVendorID(const FunctionsGL *functions); -ShShaderOutput GetShaderOutputType(const FunctionsGL *functions); +ShShaderOutput GetShaderOutputType(const angle::FeaturesGL &features, const FunctionsGL *functions); // Helpers for extracting the GL helper objects out of a context const FunctionsGL *GetFunctionsGL(const gl::Context *context); @@ -132,7 +132,6 @@ bool SupportsVertexArrayObjects(const FunctionsGL *functions); bool CanUseDefaultVertexArrayObject(const FunctionsGL *functions); bool CanUseClientSideArrays(const FunctionsGL *functions, GLuint vao); bool SupportsCompute(const FunctionsGL *functions); -bool SupportsFenceSync(const FunctionsGL *functions); bool SupportsOcclusionQueries(const FunctionsGL *functions); bool SupportsNativeRendering(const FunctionsGL *functions, gl::TextureType type, diff --git a/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp b/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp index 01da3d5ebe1..851a45359cc 100644 --- a/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp +++ b/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp @@ -393,7 +393,7 @@ egl::Error D3DTextureSurfaceWGL::unMakeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error D3DTextureSurfaceWGL::swap(const gl::Context *context) +egl::Error D3DTextureSurfaceWGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -485,14 +485,9 @@ void D3DTextureSurfaceWGL::setSwapInterval(const egl::Display *display, EGLint i UNIMPLEMENTED(); } -EGLint D3DTextureSurfaceWGL::getWidth() const +gl::Extents D3DTextureSurfaceWGL::getSize() const { - return static_cast(mWidth); -} - -EGLint D3DTextureSurfaceWGL::getHeight() const -{ - return static_cast(mHeight); + return gl::Extents(static_cast(mWidth), static_cast(mHeight), 1); } EGLint D3DTextureSurfaceWGL::isPostSubBufferSupported() const @@ -510,7 +505,7 @@ HDC D3DTextureSurfaceWGL::getDC() const return mDeviceContext; } -const angle::Format *D3DTextureSurfaceWGL::getD3DTextureColorFormat() const +const angle::Format *D3DTextureSurfaceWGL::getClientBufferTextureColorFormat() const { return mColorFormat; } diff --git a/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h b/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h index 3ea590fef0f..118082217a0 100644 --- a/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h +++ b/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h @@ -45,7 +45,7 @@ class D3DTextureSurfaceWGL : public SurfaceWGL egl::Error makeCurrent(const gl::Context *context) override; egl::Error unMakeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -58,14 +58,13 @@ class D3DTextureSurfaceWGL : public SurfaceWGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; HDC getDC() const override; - const angle::Format *getD3DTextureColorFormat() const override; + const angle::Format *getClientBufferTextureColorFormat() const override; egl::Error attachToFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) override; diff --git a/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp b/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp index 6e7f3e8c9ef..4e4df1a0b0a 100644 --- a/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp +++ b/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp @@ -125,7 +125,8 @@ egl::Error DXGISwapChainWindowSurfaceWGL::makeCurrent(const gl::Context *context return egl::NoError(); } -egl::Error DXGISwapChainWindowSurfaceWGL::swap(const gl::Context *context) +egl::Error DXGISwapChainWindowSurfaceWGL::swap(const gl::Context *context, + SurfaceSwapFeedback *feedback) { mFunctionsGL->flush(); @@ -264,14 +265,9 @@ void DXGISwapChainWindowSurfaceWGL::setSwapInterval(const egl::Display *display, mSwapInterval = interval; } -EGLint DXGISwapChainWindowSurfaceWGL::getWidth() const +gl::Extents DXGISwapChainWindowSurfaceWGL::getSize() const { - return static_cast(mWidth); -} - -EGLint DXGISwapChainWindowSurfaceWGL::getHeight() const -{ - return static_cast(mHeight); + return gl::Extents(static_cast(mWidth), static_cast(mHeight), 1); } EGLint DXGISwapChainWindowSurfaceWGL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h b/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h index aee503cdf79..7684fedfdad 100644 --- a/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h +++ b/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h @@ -39,7 +39,7 @@ class DXGISwapChainWindowSurfaceWGL : public SurfaceWGL egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -52,8 +52,7 @@ class DXGISwapChainWindowSurfaceWGL : public SurfaceWGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp index 0950b513203..443be9c79d4 100644 --- a/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp +++ b/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp @@ -791,13 +791,14 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)); // Create a context of the requested version, if any. - gl::Version requestedVersion(static_cast(eglAttributes.get( - EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)), - static_cast(eglAttributes.get( - EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE))); - if (static_cast(requestedVersion.major) != EGL_DONT_CARE && - static_cast(requestedVersion.minor) != EGL_DONT_CARE) - { + const EGLint clientMajorVersion = static_cast( + eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)); + const EGLint clientMinorVersion = static_cast( + eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)); + if (clientMajorVersion != EGL_DONT_CARE && clientMinorVersion != EGL_DONT_CARE) + { + const gl::Version requestedVersion(static_cast(clientMajorVersion), + static_cast(clientMinorVersion)); int profileMask = 0; if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && requestedVersion >= gl::Version(3, 2)) @@ -844,10 +845,10 @@ HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMa } attribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); - attribs.push_back(version.major); + attribs.push_back(version.getMajor()); attribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); - attribs.push_back(version.minor); + attribs.push_back(version.getMinor()); if (profileMask != 0) { diff --git a/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp index 9ac37444b77..67449f8a656 100644 --- a/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp +++ b/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp @@ -130,7 +130,7 @@ egl::Error PbufferSurfaceWGL::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error PbufferSurfaceWGL::swap(const gl::Context *context) +egl::Error PbufferSurfaceWGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -192,14 +192,9 @@ egl::Error PbufferSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint void PbufferSurfaceWGL::setSwapInterval(const egl::Display *display, EGLint interval) {} -EGLint PbufferSurfaceWGL::getWidth() const +gl::Extents PbufferSurfaceWGL::getSize() const { - return mWidth; -} - -EGLint PbufferSurfaceWGL::getHeight() const -{ - return mHeight; + return gl::Extents(mWidth, mHeight, 1); } EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h index 2c10f90f5dc..314d92daec4 100644 --- a/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h +++ b/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h @@ -35,7 +35,7 @@ class PbufferSurfaceWGL : public SurfaceWGL egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -48,8 +48,7 @@ class PbufferSurfaceWGL : public SurfaceWGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp index d292fe25508..c1d1b3bf4d8 100644 --- a/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp +++ b/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp @@ -100,7 +100,7 @@ egl::Error WindowSurfaceWGL::makeCurrent(const gl::Context *context) return egl::NoError(); } -egl::Error WindowSurfaceWGL::swap(const gl::Context *context) +egl::Error WindowSurfaceWGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { if (!mFunctionsWGL->swapBuffers(mDeviceContext)) { @@ -149,24 +149,14 @@ void WindowSurfaceWGL::setSwapInterval(const egl::Display *display, EGLint inter } } -EGLint WindowSurfaceWGL::getWidth() const +gl::Extents WindowSurfaceWGL::getSize() const { RECT rect; if (!GetClientRect(mWindow, &rect)) { - return 0; + return gl::Extents(0, 0, 1); } - return rect.right - rect.left; -} - -EGLint WindowSurfaceWGL::getHeight() const -{ - RECT rect; - if (!GetClientRect(mWindow, &rect)) - { - return 0; - } - return rect.bottom - rect.top; + return gl::Extents(rect.right - rect.left, rect.bottom - rect.top, 1); } EGLint WindowSurfaceWGL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h index f279ff3b2dc..5a81305f6c5 100644 --- a/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h +++ b/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h @@ -31,7 +31,7 @@ class WindowSurfaceWGL : public SurfaceWGL egl::Error initialize(const egl::Display *display) override; egl::Error makeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -44,8 +44,7 @@ class WindowSurfaceWGL : public SurfaceWGL egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/load_functions_data.json b/src/libANGLE/renderer/load_functions_data.json index 910f2dd42f5..512f6a6f964 100644 --- a/src/libANGLE/renderer/load_functions_data.json +++ b/src/libANGLE/renderer/load_functions_data.json @@ -194,7 +194,7 @@ }, "GL_BGRA_EXT": { "NONE": { - "GL_UNSIGNED_BYTE": "UnreachableLoadFunction" + "GL_UNSIGNED_BYTE": "LoadToNative" } }, "GL_COMPRESSED_RGB8_ETC2": { @@ -454,7 +454,7 @@ }, "GL_BGR565_ANGLEX": { "B5G6R5_UNORM": { - "GL_UNSIGNED_SHORT_5_6_5": "LoadRGB565ToBGR565", + "GL_UNSIGNED_SHORT_5_6_5": "LoadToNative", "GL_UNSIGNED_BYTE": "LoadRGB8ToBGR565" }, "R8G8B8A8_UNORM": { @@ -595,6 +595,11 @@ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction" } }, + "GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX": { + "R10X6G10X6B10X6A10X6_UNORM": { + "GL_UNSIGNED_SHORT": "LoadToNative" + } + }, "GL_COMPRESSED_RG11_EAC": { "R16G16_UNORM": { "GL_UNSIGNED_BYTE": "LoadEACRG11ToRG16" @@ -763,7 +768,7 @@ }, "GL_RGB565": { "R5G6B5_UNORM" : { - "GL_UNSIGNED_BYTE": "LoadRGB8ToBGR565", + "GL_UNSIGNED_BYTE": "LoadRGB8ToRGB565", "GL_UNSIGNED_SHORT_5_6_5": "LoadToNative", "GL_UNSIGNED_INT_2_10_10_10_REV_EXT": "LoadRGB10A2ToRGB565" }, @@ -773,7 +778,8 @@ }, "B5G6R5_UNORM": { "GL_UNSIGNED_BYTE": "LoadRGB8ToBGR565", - "GL_UNSIGNED_SHORT_5_6_5": "LoadToNative" + "GL_UNSIGNED_SHORT_5_6_5": "LoadRGB565ToBGR565", + "GL_UNSIGNED_INT_2_10_10_10_REV_EXT": "LoadRGB10A2ToBGR565" } }, "GL_LUMINANCE16F_EXT": { @@ -1335,6 +1341,11 @@ "GL_UNSIGNED_BYTE": "UnimplementedLoadFunction" } }, + "GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE": { + "NONE": { + "GL_UNSIGNED_BYTE": "UnimplementedLoadFunction" + } + }, "GL_G8_B8R8_2PLANE_420_UNORM_ANGLE": { "NONE": { "GL_UNSIGNED_BYTE": "LoadYuvToNative" diff --git a/src/libANGLE/renderer/load_functions_table_autogen.cpp b/src/libANGLE/renderer/load_functions_table_autogen.cpp index a740f852521..0d30da0cdc3 100644 --- a/src/libANGLE/renderer/load_functions_table_autogen.cpp +++ b/src/libANGLE/renderer/load_functions_table_autogen.cpp @@ -233,7 +233,7 @@ LoadImageFunctionInfo BGR565_ANGLEX_to_B5G6R5_UNORM(GLenum type) case GL_UNSIGNED_BYTE: return LoadImageFunctionInfo(LoadRGB8ToBGR565, true); case GL_UNSIGNED_SHORT_5_6_5: - return LoadImageFunctionInfo(LoadRGB565ToBGR565, true); + return LoadImageFunctionInfo(LoadToNative, false); default: UNREACHABLE(); return LoadImageFunctionInfo(UnreachableLoadFunction, true); @@ -311,7 +311,7 @@ LoadImageFunctionInfo BGRA_EXT_to_default(GLenum type) switch (type) { case GL_UNSIGNED_BYTE: - return LoadImageFunctionInfo(UnreachableLoadFunction, true); + return LoadImageFunctionInfo(LoadToNative, false); default: UNREACHABLE(); return LoadImageFunctionInfo(UnreachableLoadFunction, true); @@ -2022,6 +2022,18 @@ LoadImageFunctionInfo ETC1_RGB8_OES_to_R8G8B8A8_UNORM(GLenum type) } } +LoadImageFunctionInfo G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE_to_default(GLenum type) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + return LoadImageFunctionInfo(UnimplementedLoadFunction, true); + default: + UNREACHABLE(); + return LoadImageFunctionInfo(UnreachableLoadFunction, true); + } +} + LoadImageFunctionInfo G8_B8R8_2PLANE_420_UNORM_ANGLE_to_default(GLenum type) { switch (type) @@ -2438,6 +2450,18 @@ LoadImageFunctionInfo PALETTE8_RGBA8_OES_to_R8G8B8A8_UNORM(GLenum type) } } +LoadImageFunctionInfo R10X6G10X6B10X6A10X6_UNORM_ANGLEX_to_R10X6G10X6B10X6A10X6_UNORM(GLenum type) +{ + switch (type) + { + case GL_UNSIGNED_SHORT: + return LoadImageFunctionInfo(LoadToNative, false); + default: + UNREACHABLE(); + return LoadImageFunctionInfo(UnreachableLoadFunction, true); + } +} + LoadImageFunctionInfo R11F_G11F_B10F_to_R11G11B10_FLOAT(GLenum type) { switch (type) @@ -3240,8 +3264,10 @@ LoadImageFunctionInfo RGB565_to_B5G6R5_UNORM(GLenum type) { case GL_UNSIGNED_BYTE: return LoadImageFunctionInfo(LoadRGB8ToBGR565, true); + case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: + return LoadImageFunctionInfo(LoadRGB10A2ToBGR565, true); case GL_UNSIGNED_SHORT_5_6_5: - return LoadImageFunctionInfo(LoadToNative, false); + return LoadImageFunctionInfo(LoadRGB565ToBGR565, true); default: UNREACHABLE(); return LoadImageFunctionInfo(UnreachableLoadFunction, true); @@ -3253,7 +3279,7 @@ LoadImageFunctionInfo RGB565_to_R5G6B5_UNORM(GLenum type) switch (type) { case GL_UNSIGNED_BYTE: - return LoadImageFunctionInfo(LoadRGB8ToBGR565, true); + return LoadImageFunctionInfo(LoadRGB8ToRGB565, true); case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: return LoadImageFunctionInfo(LoadRGB10A2ToRGB565, true); case GL_UNSIGNED_SHORT_5_6_5: @@ -4655,6 +4681,8 @@ LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, FormatID angleFormat) } break; } + case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE: + return G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE_to_default; case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE: return G8_B8R8_2PLANE_420_UNORM_ANGLE_to_default; case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE: @@ -4874,6 +4902,17 @@ LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, FormatID angleFormat) } break; } + case GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX: + { + switch (angleFormat) + { + case FormatID::R10X6G10X6B10X6A10X6_UNORM: + return R10X6G10X6B10X6A10X6_UNORM_ANGLEX_to_R10X6G10X6B10X6A10X6_UNORM; + default: + break; + } + break; + } case GL_R11F_G11F_B10F: { switch (angleFormat) diff --git a/src/libANGLE/renderer/metal/BUILD.gn b/src/libANGLE/renderer/metal/BUILD.gn index 96e9ee84208..50ac42a5b9a 100644 --- a/src/libANGLE/renderer/metal/BUILD.gn +++ b/src/libANGLE/renderer/metal/BUILD.gn @@ -24,20 +24,56 @@ config("angle_metal_backend_config") { } if (metal_internal_shader_compilation_supported) { + template("run_metal_tool") { + action(target_name) { + forward_variables_from(invoker, + [ + "deps", + "sources", + "outputs", + "metal_tool", + ]) + script = "shaders/metal_wrapper.py" + if (use_system_xcode) { + # System Xcode: run metal and metallib via xcrun. Since Xcode 26.0, the + # Metal toolchain has been unbundled from Xcode, and must be installed + # separately by running `xcodebuild -downloadComponent MetalToolchain`. + # There is a vestigial metal executable in mac_bin_path, but it’s + # incapable of running successfuly without the + # rest of the Metal toolchain surrounding it. `xcrun` is able to find + # and run the correct Metal toolchain when properly installed. + # + # If you’re using system Xcode and your build fails with this message: + # error: error: cannot execute tool 'metal' due to missing Metal Toolchain; use: xcodebuild -downloadComponent MetalToolchain + # then do what the error message suggests, and then retry your build. + args = [ + "xcrun", + metal_tool, + ] + } else { + # Hermetic Xcode: at least for now, the Metal toolchain is + # “spliced” into the location in the hermetic toolchain where it lived + # before Xcode 26.0, so it can be run directly from there. + args = [ mac_bin_path + metal_tool ] + } + + args += invoker.args + } + } + _metal_internal_shaders_air_file = "$root_gen_dir/angle/mtl_internal_shaders_autogen.air" - action("angle_metal_internal_shaders_to_air") { - script = "shaders/metal_wrapper.py" - - outputs = [ _metal_internal_shaders_air_file ] - + run_metal_tool("angle_metal_internal_shaders_to_air") { _metal_internal_shaders_metal_source = "shaders/mtl_internal_shaders_autogen.metal" sources = [ _metal_internal_shaders_metal_source ] + outputs = [ _metal_internal_shaders_air_file ] + + metal_tool = "metal" + args = [ - mac_bin_path + "metal", "-c", rebase_path(_metal_internal_shaders_metal_source, root_build_dir), "-o", @@ -60,17 +96,16 @@ if (metal_internal_shader_compilation_supported) { _metal_internal_shaders_metallib_file = "$root_gen_dir/angle/mtl_internal_shaders_autogen.metallib" - action("angle_metal_internal_shaders_to_mtllib") { - script = "shaders/metal_wrapper.py" - - outputs = [ _metal_internal_shaders_metallib_file ] + run_metal_tool("angle_metal_internal_shaders_to_mtllib") { + deps = [ ":angle_metal_internal_shaders_to_air" ] sources = [ _metal_internal_shaders_air_file ] - deps = [ ":angle_metal_internal_shaders_to_air" ] + outputs = [ _metal_internal_shaders_metallib_file ] + + metal_tool = "metallib" args = [ - mac_bin_path + "metallib", rebase_path(_metal_internal_shaders_air_file, root_build_dir), "-o", rebase_path(_metal_internal_shaders_metallib_file, root_build_dir), diff --git a/src/libANGLE/renderer/metal/BufferMtl.h b/src/libANGLE/renderer/metal/BufferMtl.h index 8162f103382..6535c8a4f97 100644 --- a/src/libANGLE/renderer/metal/BufferMtl.h +++ b/src/libANGLE/renderer/metal/BufferMtl.h @@ -122,24 +122,33 @@ class BufferMtl : public BufferImpl, public BufferHolderMtl gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, @@ -187,20 +196,23 @@ class BufferMtl : public BufferImpl, public BufferHolderMtl angle::Result allocateNewMetalBuffer(ContextMtl *contextMtl, MTLStorageMode storageMode, size_t size, - bool returnOldBufferImmediately); + bool returnOldBufferImmediately, + BufferFeedback *feedback); angle::Result setDataImpl(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage); + gl::BufferUsage usage, + BufferFeedback *feedback); angle::Result setSubDataImpl(const gl::Context *context, const void *data, size_t size, - size_t offset); + size_t offset, + BufferFeedback *feedback); - angle::Result commitShadowCopy(ContextMtl *contextMtl); - angle::Result commitShadowCopy(ContextMtl *contextMtl, size_t size); + angle::Result commitShadowCopy(ContextMtl *contextMtl, BufferFeedback *feedback); + angle::Result commitShadowCopy(ContextMtl *contextMtl, size_t size, BufferFeedback *feedback); void markConversionBuffersDirty(); void clearConversionBuffers(); @@ -208,7 +220,8 @@ class BufferMtl : public BufferImpl, public BufferHolderMtl angle::Result putDataInNewBufferAndStartUsingNewBuffer(ContextMtl *contextMtl, const uint8_t *srcPtr, size_t sizeToCopy, - size_t offset); + size_t offset, + BufferFeedback *feedback); angle::Result updateExistingBufferViaBlitFromStagingBuffer(ContextMtl *contextMtl, const uint8_t *srcPtr, size_t sizeToCopy, @@ -220,7 +233,8 @@ class BufferMtl : public BufferImpl, public BufferHolderMtl angle::Result updateShadowCopyThenCopyShadowToNewBuffer(ContextMtl *contextMtl, const uint8_t *srcPtr, size_t sizeToCopy, - size_t offset); + size_t offset, + BufferFeedback *feedback); bool clientShadowCopyDataNeedSync(ContextMtl *contextMtl); void ensureShadowCopySyncedFromGPU(ContextMtl *contextMtl); diff --git a/src/libANGLE/renderer/metal/BufferMtl.mm b/src/libANGLE/renderer/metal/BufferMtl.mm index 4ac920f02e6..6ffe10c8a32 100644 --- a/src/libANGLE/renderer/metal/BufferMtl.mm +++ b/src/libANGLE/renderer/metal/BufferMtl.mm @@ -7,6 +7,10 @@ // Implements the class methods for BufferMtl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/BufferMtl.h" #include "common/debug.h" @@ -122,25 +126,28 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) gl::BufferBinding target, const void *data, size_t intendedSize, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { - return setDataImpl(context, target, data, intendedSize, usage); + return setDataImpl(context, target, data, intendedSize, usage, feedback); } angle::Result BufferMtl::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { - return setSubDataImpl(context, data, size, offset); + return setSubDataImpl(context, data, size, offset, feedback); } angle::Result BufferMtl::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { if (!source) { @@ -167,7 +174,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) return angle::Result::Continue; } return setSubDataImpl(context, srcMtl->getBufferDataReadOnly(contextMtl) + sourceOffset, - size, destOffset); + size, destOffset, feedback); } mtl::BlitCommandEncoder *blitEncoder = contextMtl->getBlitCommandEncoder(); @@ -176,26 +183,30 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) return angle::Result::Continue; } -angle::Result BufferMtl::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result BufferMtl::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { GLbitfield mapRangeAccess = 0; if ((access & GL_WRITE_ONLY_OES) != 0 || (access & GL_READ_WRITE) != 0) { mapRangeAccess |= GL_MAP_WRITE_BIT; } - return mapRange(context, 0, size(), mapRangeAccess, mapPtr); + return mapRange(context, 0, size(), mapRangeAccess, mapPtr, feedback); } angle::Result BufferMtl::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { if (access & GL_MAP_INVALIDATE_BUFFER_BIT) { ANGLE_TRY(setDataImpl(context, gl::BufferBinding::InvalidEnum, nullptr, size(), - mState.getUsage())); + mState.getUsage(), feedback)); } if (mapPtr) @@ -216,7 +227,9 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) return angle::Result::Continue; } -angle::Result BufferMtl::unmap(const gl::Context *context, GLboolean *result) +angle::Result BufferMtl::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { ContextMtl *contextMtl = mtl::GetImpl(context); size_t offset = static_cast(mState.getMapOffset()); @@ -251,7 +264,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) else { // commit shadow copy data to GPU synchronously - ANGLE_TRY(commitShadowCopy(contextMtl)); + ANGLE_TRY(commitShadowCopy(contextMtl, feedback)); } } @@ -508,7 +521,8 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) angle::Result BufferMtl::allocateNewMetalBuffer(ContextMtl *contextMtl, MTLStorageMode storageMode, size_t size, - bool returnOldBufferImmediately) + bool returnOldBufferImmediately, + BufferFeedback *feedback) { mtl::BufferManager &bufferManager = contextMtl->getBufferManager(); if (returnOldBufferImmediately && mBuffer) @@ -520,7 +534,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) } ANGLE_TRY(bufferManager.getBuffer(contextMtl, storageMode, size, mBuffer)); - onStateChange(angle::SubjectMessage::InternalMemoryAllocationChanged); + feedback->internalMemoryAllocationChanged = true; return angle::Result::Continue; } @@ -529,7 +543,8 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) gl::BufferBinding target, const void *data, size_t intendedSize, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { ContextMtl *contextMtl = mtl::GetImpl(context); const angle::FeaturesMtl &features = contextMtl->getDisplay()->getFeatures(); @@ -560,7 +575,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) // Re-create the buffer auto storageMode = mtl::Buffer::getStorageModeForUsage(contextMtl, usage); ANGLE_TRY(allocateNewMetalBuffer(contextMtl, storageMode, adjustedSize, - /*returnOldBufferImmediately=*/true)); + /*returnOldBufferImmediately=*/true, feedback)); #ifndef NDEBUG ANGLE_MTL_OBJC_SCOPE @@ -579,7 +594,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) if (data) { - ANGLE_TRY(setSubDataImpl(context, data, intendedSize, 0)); + ANGLE_TRY(setSubDataImpl(context, data, intendedSize, 0, feedback)); } return angle::Result::Continue; @@ -636,7 +651,8 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) angle::Result BufferMtl::putDataInNewBufferAndStartUsingNewBuffer(ContextMtl *contextMtl, const uint8_t *srcPtr, size_t sizeToCopy, - size_t offset) + size_t offset, + BufferFeedback *feedback) { ASSERT(isOffsetAndSizeMetalBlitCompatible(offset, sizeToCopy)); @@ -644,7 +660,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) auto storageMode = mtl::Buffer::getStorageModeForUsage(contextMtl, mUsage); ANGLE_TRY(allocateNewMetalBuffer(contextMtl, storageMode, mGLSize, - /*returnOldBufferImmediately=*/false)); + /*returnOldBufferImmediately=*/false, feedback)); mBuffer->get().label = [NSString stringWithFormat:@"BufferMtl=%p(%lu)", this, ++mRevisionCount]; uint8_t *ptr = mBuffer->mapWithOpt(contextMtl, false, true); @@ -688,7 +704,8 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) angle::Result BufferMtl::updateShadowCopyThenCopyShadowToNewBuffer(ContextMtl *contextMtl, const uint8_t *srcPtr, size_t sizeToCopy, - size_t offset) + size_t offset, + BufferFeedback *feedback) { // 1. Before copying data from client, we need to synchronize modified data from GPU to // shadow copy first. @@ -698,13 +715,14 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) std::copy(srcPtr, srcPtr + sizeToCopy, mShadowCopy.data() + offset); // 3. Copy data from shadow copy to GPU. - return commitShadowCopy(contextMtl); + return commitShadowCopy(contextMtl, feedback); } angle::Result BufferMtl::setSubDataImpl(const gl::Context *context, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { if (!data) { @@ -730,7 +748,8 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) if (mShadowCopy.size() > 0) { - return updateShadowCopyThenCopyShadowToNewBuffer(contextMtl, srcPtr, sizeToCopy, offset); + return updateShadowCopyThenCopyShadowToNewBuffer(contextMtl, srcPtr, sizeToCopy, offset, + feedback); } else { @@ -749,7 +768,7 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) else { return putDataInNewBufferAndStartUsingNewBuffer(contextMtl, srcPtr, sizeToCopy, - offset); + offset, feedback); } } else @@ -759,18 +778,20 @@ bool isOffsetAndSizeMetalBlitCompatible(size_t offset, size_t size) } } -angle::Result BufferMtl::commitShadowCopy(ContextMtl *contextMtl) +angle::Result BufferMtl::commitShadowCopy(ContextMtl *contextMtl, BufferFeedback *feedback) { - return commitShadowCopy(contextMtl, mGLSize); + return commitShadowCopy(contextMtl, mGLSize, feedback); } -angle::Result BufferMtl::commitShadowCopy(ContextMtl *contextMtl, size_t size) +angle::Result BufferMtl::commitShadowCopy(ContextMtl *contextMtl, + size_t size, + BufferFeedback *feedback) { auto storageMode = mtl::Buffer::getStorageModeForUsage(contextMtl, mUsage); size_t bufferSize = (mGLSize == 0 ? mShadowCopy.size() : mGLSize); ANGLE_TRY(allocateNewMetalBuffer(contextMtl, storageMode, bufferSize, - /*returnOldBufferImmediately=*/true)); + /*returnOldBufferImmediately=*/true, feedback)); if (size) { diff --git a/src/libANGLE/renderer/metal/ContextMtl.h b/src/libANGLE/renderer/metal/ContextMtl.h index 91da728d1a8..933dd614ee5 100644 --- a/src/libANGLE/renderer/metal/ContextMtl.h +++ b/src/libANGLE/renderer/metal/ContextMtl.h @@ -237,7 +237,8 @@ class ContextMtl : public ContextImpl, public mtl::Context BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; @@ -320,6 +321,8 @@ class ContextMtl : public ContextImpl, public mtl::Context uint64_t queueEventSignal(id event, uint64_t value); void serverWaitEvent(id event, uint64_t value); + void markResourceWrittenByCommandBuffer(const mtl::ResourceRef &resource); + const mtl::ClearColorValue &getClearColorValue() const; const mtl::WriteMaskArray &getWriteMaskArray() const; float getClearDepthValue() const; @@ -339,9 +342,6 @@ class ContextMtl : public ContextImpl, public mtl::Context gl::SamplerFormat format, gl::Texture **textureOut); - // Recommended to call these methods to end encoding instead of invoking the encoder's - // endEncoding() directly. - void endRenderEncoding(mtl::RenderCommandEncoder *encoder); // Ends any active command encoder void endEncoding(bool forceSaveRenderPassContent); @@ -349,6 +349,8 @@ class ContextMtl : public ContextImpl, public mtl::Context void present(const gl::Context *context, id presentationDrawable); angle::Result finishCommandBuffer(); + void addCommandBufferScheduledCallback(std::function callback); + // Check whether compatible render pass has been started. Compatible render pass is a render // pass having the same attachments, and possibly having different load/store options. bool hasStartedRenderPass(const mtl::RenderPassDesc &desc); @@ -366,6 +368,9 @@ class ContextMtl : public ContextImpl, public mtl::Context // The previous content of texture will be loaded mtl::RenderCommandEncoder *getTextureRenderCommandEncoder(const mtl::TextureRef &textureTarget, const mtl::ImageNativeIndex &index); + mtl::RenderCommandEncoder *getTextureRenderCommandEncoder(const mtl::TextureRef &textureTarget, + mtl::MipmapNativeLevel level, + uint32_t layer); // The previous content of texture will be loaded if clearColor is not provided mtl::RenderCommandEncoder *getRenderTargetCommandEncoderWithClear( const RenderTargetMtl &renderTarget, diff --git a/src/libANGLE/renderer/metal/ContextMtl.mm b/src/libANGLE/renderer/metal/ContextMtl.mm index 95e0c28b41b..bd50c076a7f 100644 --- a/src/libANGLE/renderer/metal/ContextMtl.mm +++ b/src/libANGLE/renderer/metal/ContextMtl.mm @@ -7,6 +7,10 @@ // Implements the class methods for ContextMtl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/ContextMtl.h" #include @@ -125,20 +129,6 @@ bool IsTransformFeedbackOnly(const gl::State &glState) return glState.isTransformFeedbackActiveUnpaused() && glState.isRasterizerDiscardEnabled(); } -std::string ConvertMarkerToString(GLsizei length, const char *marker) -{ - std::string cppString; - if (length == 0) - { - cppString = marker; - } - else - { - cppString.assign(marker, length); - } - return cppString; -} - // This class constructs line loop's last segment buffer inside begin() method // and perform the draw of the line loop's last segment inside destructor class LineLoopLastSegmentHelper @@ -884,8 +874,8 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) const void *indices, GLint baseVertex) { - UNIMPLEMENTED(); - return angle::Result::Stop; + ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); + return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0); } angle::Result ContextMtl::drawElementsInstanced(const gl::Context *context, @@ -955,9 +945,8 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) const void *indices, GLint baseVertex) { - // NOTE(hqle): ES 3.2 - UNIMPLEMENTED(); - return angle::Result::Stop; + ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); + return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0); } angle::Result ContextMtl::drawArraysIndirect(const gl::Context *context, @@ -1077,12 +1066,13 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) // EXT_debug_marker angle::Result ContextMtl::insertEventMarker(GLsizei length, const char *marker) { + mCmdBuffer.insertDebugSignpost(std::string(marker, length)); return checkCommandBufferError(); } angle::Result ContextMtl::pushGroupMarker(GLsizei length, const char *marker) { - mCmdBuffer.pushDebugGroup(ConvertMarkerToString(length, marker)); + mCmdBuffer.pushDebugGroup(std::string(marker, length)); return checkCommandBufferError(); } @@ -1523,9 +1513,10 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) } // Vertex Array creation -VertexArrayImpl *ContextMtl::createVertexArray(const gl::VertexArrayState &state) +VertexArrayImpl *ContextMtl::createVertexArray(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers) { - return new VertexArrayMtl(state, this); + return new VertexArrayMtl(state, vertexArrayBuffers, this); } // Query and Fence creation @@ -1676,7 +1667,7 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) { mDirtyBits.set(); - invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); + invalidateDefaultAttributes(context->getActiveDefaultAttribsMask()); } void ContextMtl::invalidateDefaultAttribute(size_t attribIndex) @@ -1784,27 +1775,6 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) return mIncompleteTextures.getIncompleteTexture(context, type, format, nullptr, textureOut); } -void ContextMtl::endRenderEncoding(mtl::RenderCommandEncoder *encoder) -{ - // End any pending visibility query in the render pass - if (mOcclusionQuery) - { - disableActiveOcclusionQueryInRenderPass(); - } - - if (mBlitEncoder.valid()) - { - mBlitEncoder.endEncoding(); - } - - mOcclusionQueryPool.prepareRenderPassVisibilityPoolBuffer(this); - - encoder->endEncoding(); - - // Resolve visibility results - mOcclusionQueryPool.resolveVisibilityResults(this); -} - void ContextMtl::endBlitAndComputeEncoding() { if (mBlitEncoder.valid()) @@ -1831,13 +1801,20 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) mRenderEncoder.setStoreAction(MTLStoreActionStore); } - endRenderEncoding(&mRenderEncoder); - } - // End blit encoder after render encoder, as endRenderEncoding() might create a - // blit encoder to resolve the visibility results. - if (mBlitEncoder.valid()) - { - mBlitEncoder.endEncoding(); + disableActiveOcclusionQueryInRenderPass(); + + mOcclusionQueryPool.prepareRenderPassVisibilityPoolBuffer(this); + + mRenderEncoder.endEncoding(); + + mOcclusionQueryPool.resolveVisibilityResults(this); + + // End blit encoder after render encoder, as occlusion query pool might create a + // blit encoder to resolve the visibility results. + if (mBlitEncoder.valid()) + { + mBlitEncoder.endEncoding(); + } } } @@ -1890,6 +1867,12 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) return checkCommandBufferError(); } +void ContextMtl::addCommandBufferScheduledCallback(std::function callback) +{ + mCmdBuffer.cmdQueue().addCommandBufferScheduledCallback(mCmdBuffer.getQueueSerial(), + std::move(callback)); +} + bool ContextMtl::hasStartedRenderPass(const mtl::RenderPassDesc &desc) { return mRenderEncoder.valid() && @@ -1956,14 +1939,23 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) mtl::RenderCommandEncoder *ContextMtl::getTextureRenderCommandEncoder( const mtl::TextureRef &textureTarget, const mtl::ImageNativeIndex &index) +{ + return getTextureRenderCommandEncoder(textureTarget, index.getNativeLevel(), + index.hasLayer() ? index.getLayerIndex() : 0); +} + +mtl::RenderCommandEncoder *ContextMtl::getTextureRenderCommandEncoder( + const mtl::TextureRef &textureTarget, + mtl::MipmapNativeLevel level, + uint32_t layer) { ASSERT(textureTarget && textureTarget->valid()); mtl::RenderPassDesc rpDesc; rpDesc.colorAttachments[0].texture = textureTarget; - rpDesc.colorAttachments[0].level = index.getNativeLevel(); - rpDesc.colorAttachments[0].sliceOrDepth = index.hasLayer() ? index.getLayerIndex() : 0; + rpDesc.colorAttachments[0].level = level; + rpDesc.colorAttachments[0].sliceOrDepth = layer; rpDesc.numColorAttachments = 1; rpDesc.rasterSampleCount = textureTarget->samples(); @@ -2012,7 +2004,6 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) return &mBlitEncoder; } - endEncoding(true); ensureCommandBufferReady(); return &mBlitEncoder.restart(); @@ -2043,7 +2034,6 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) return &mComputeEncoder; } - endEncoding(true); ensureCommandBufferReady(); return &mComputeEncoder.restart(); @@ -2386,12 +2376,18 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) mCmdBuffer.serverWaitEvent(event, value); } +void ContextMtl::markResourceWrittenByCommandBuffer(const mtl::ResourceRef &resource) +{ + ensureCommandBufferReady(); + mCmdBuffer.setWriteDependency(resource, /*isRenderCommand=*/false); +} + void ContextMtl::updateProgramExecutable(const gl::Context *context) { // Need to rebind textures invalidateCurrentTextures(); // Need to re-upload default attributes - invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); + invalidateDefaultAttributes(context->getActiveDefaultAttribsMask()); // Render pipeline need to be re-applied invalidateRenderPipeline(); } @@ -2400,7 +2396,7 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs) { const gl::State &glState = getState(); mVertexArray = mtl::GetImpl(glState.getVertexArray()); - invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); + invalidateDefaultAttributes(context->getActiveDefaultAttribsMask()); invalidateRenderPipeline(); } @@ -2516,7 +2512,7 @@ static bool isDrawNoOp(const mtl::RenderPipelineDesc &descriptor, // instances=0 means no instanced draw. GLsizei instanceCount = instances ? instances : 1; - if (context->getStateCache().hasAnyActiveClientAttrib()) + if (context->hasAnyActiveClientAttrib()) { ANGLE_TRY(mVertexArray->updateClientAttribs(context, firstVertex, vertexOrIndexCount, instanceCount, indexTypeOrNone, indices)); diff --git a/src/libANGLE/renderer/metal/DisplayMtl.mm b/src/libANGLE/renderer/metal/DisplayMtl.mm index e5ba0b115cf..41bc2717277 100644 --- a/src/libANGLE/renderer/metal/DisplayMtl.mm +++ b/src/libANGLE/renderer/metal/DisplayMtl.mm @@ -6,6 +6,10 @@ // DisplayMtl.mm: Metal implementation of DisplayImpl +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/DisplayMtl.h" #include @@ -427,7 +431,7 @@ bool IsMetalDisplayAvailable() // FIXME: None of the feature conditions are checked for simulator support. return gl::Version(3, 0); #else - if (supportsEitherGPUFamily(3, 1)) + if (supportsEitherGPUFamily(4, 1)) { return mtl::kMaxSupportedGLVersion; } @@ -487,8 +491,11 @@ bool IsMetalDisplayAvailable() // EGL_ANGLE_metal_create_context_ownership_identity outExtensions->metalCreateContextOwnershipIdentityANGLE = true; - // EGL_ANGLE_metal_sync_shared_event + // EGL_ANGLE_metal_shared_event_sync outExtensions->mtlSyncSharedEventANGLE = true; + + // EGL_ANGLE_metal_commands_scheduled_sync + outExtensions->mtlSyncCommandsScheduledANGLE = true; } void DisplayMtl::generateCaps(egl::Caps *outCaps) const @@ -746,15 +753,7 @@ bool IsMetalDisplayAvailable() // Metal-Feature-Set-Tables.pdf says that max supported point size is 511. We limit it to 64 // for now. http://anglebug.com/42263403 - // NOTE(kpiddington): This seems to be fixed in macOS Monterey - if (@available(macOS 12.0, *)) - { - mNativeCaps.maxAliasedPointSize = 511; - } - else - { - mNativeCaps.maxAliasedPointSize = 64; - } + mNativeCaps.maxAliasedPointSize = 511; mNativeCaps.minAliasedLineWidth = 1.0f; mNativeCaps.maxAliasedLineWidth = 1.0f; @@ -859,6 +858,7 @@ bool IsMetalDisplayAvailable() // Fill in additional limits for UBOs and SSBOs. mNativeCaps.maxUniformBufferBindings = mNativeCaps.maxCombinedUniformBlocks; + static_assert(mtl::kMaxUBOSize <= gl::IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE); mNativeCaps.maxUniformBlockSize = mtl::kMaxUBOSize; // Default according to GLES 3.0 spec. if (supportsAppleGPUFamily(1)) { @@ -904,6 +904,21 @@ bool IsMetalDisplayAvailable() // Apple platforms require PVRTC1 textures to be squares. mNativeLimitations.squarePvrtc1 = true; + + if (mFeatures.disableProgrammableBlending.enabled || !supportsAppleGPUFamily(1)) + { + const MTLReadWriteTextureTier readWriteTextureTier = [mMetalDevice readWriteTextureSupport]; + if (readWriteTextureTier != MTLReadWriteTextureTierNone) + { + const bool rasterOrderGroupsSupported = !mFeatures.disableRasterOrderGroups.enabled && + [mMetalDevice areRasterOrderGroupsSupported]; + + if (rasterOrderGroupsSupported && isAMD()) + { + mNativeLimitations.noRasterOrderGroupWithoutAttachmentZero = true; + } + } + } } void DisplayMtl::initializeExtensions() const @@ -944,12 +959,6 @@ bool IsMetalDisplayAvailable() mNativeExtensions.multiDrawIndirectEXT = true; mNativeExtensions.translatedShaderSourceANGLE = true; mNativeExtensions.discardFramebufferEXT = true; - // TODO(anglebug.com/42264909): Apple's implementation exposed - // mNativeExtensions.textureRectangle = true here and - // EGL_TEXTURE_RECTANGLE_ANGLE as the eglBindTexImage texture target on - // macOS. This no longer seems necessary as IOSurfaces can be bound to - // regular 2D textures with Metal, and causes other problems such as - // breaking the SPIR-V Metal compiler. mNativeExtensions.multisampledRenderToTextureEXT = (supportsAppleGPUFamily(1) || @@ -1051,9 +1060,6 @@ bool IsMetalDisplayAvailable() // GL_OES_EGL_sync mNativeExtensions.EGLSyncOES = true; - - // GL_ARB_sync - mNativeExtensions.syncARB = true; } // GL_KHR_parallel_shader_compile @@ -1064,6 +1070,9 @@ bool IsMetalDisplayAvailable() mNativeExtensions.baseVertexBaseInstanceShaderBuiltinANGLE = mFeatures.hasBaseVertexInstancedDraw.enabled; + mNativeExtensions.drawElementsBaseVertexEXT = mFeatures.hasBaseVertexInstancedDraw.enabled; + mNativeExtensions.drawElementsBaseVertexOES = mFeatures.hasBaseVertexInstancedDraw.enabled; + // Metal uses the opposite provoking vertex as GLES so emulation is required to use the GLES // behaviour. Allow users to change the provoking vertex for improved performance. mNativeExtensions.provokingVertexANGLE = true; @@ -1108,15 +1117,6 @@ bool IsMetalDisplayAvailable() !mFeatures.disableRWTextureTier2Support.enabled && readWriteTextureTier == MTLReadWriteTextureTier2; - if (rasterOrderGroupsSupported && isAMD()) - { - // anglebug.com/42266263 -- [[raster_order_group()]] does not work for read_write - // textures on AMD when the render pass doesn't have a color attachment on slot 0. - // To work around this we attach one of the PLS textures to GL_COLOR_ATTACHMENT0, if - // there isn't one already. - mNativePLSOptions.renderPassNeedsAMDRasterOrderGroupsWorkaround = true; - } - mNativeExtensions.shaderPixelLocalStorageANGLE = true; mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = rasterOrderGroupsSupported; @@ -1126,8 +1126,6 @@ bool IsMetalDisplayAvailable() gl::IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); mNativeCaps.maxPixelLocalStoragePlanes = gl::IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES; - mNativeCaps.maxColorAttachmentsWithActivePixelLocalStorage = - gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; mNativeCaps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes = gl::IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; @@ -1247,11 +1245,6 @@ bool IsMetalDisplayAvailable() supportsAppleGPUFamily(1) && !isSimulator); ANGLE_FEATURE_CONDITION((&mFeatures), emulateTransformFeedback, true); - ANGLE_FEATURE_CONDITION((&mFeatures), intelExplicitBoolCastWorkaround, - isIntel() && GetMacOSVersion() < OSVersion(11, 0, 0)); - ANGLE_FEATURE_CONDITION((&mFeatures), intelDisableFastMath, - isIntel() && GetMacOSVersion() < OSVersion(12, 0, 0)); - ANGLE_FEATURE_CONDITION((&mFeatures), emulateAlphaToCoverage, isSimulator || !supportsAppleGPUFamily(1)); @@ -1319,10 +1312,8 @@ bool IsMetalDisplayAvailable() mFeatures.allowSamplerCompareGradient.enabled); // Metal compiler optimizations may remove infinite loops causing crashes later in shader - // execution. http://crbug.com/1513738 - // Disabled on Mac11 due to test failures. http://crbug.com/1522730 - ANGLE_FEATURE_CONDITION((&mFeatures), injectAsmStatementIntoLoopBodies, - !isOSX || GetMacOSVersion() >= OSVersion(12, 0, 0)); + // execution. http://crbug.com/41486305 + ANGLE_FEATURE_CONDITION((&mFeatures), ensureLoopForwardProgress, true); } angle::Result DisplayMtl::initializeShaderLibrary() diff --git a/src/libANGLE/renderer/metal/FrameBufferMtl.mm b/src/libANGLE/renderer/metal/FrameBufferMtl.mm index d0c19c6e25c..41115775407 100644 --- a/src/libANGLE/renderer/metal/FrameBufferMtl.mm +++ b/src/libANGLE/renderer/metal/FrameBufferMtl.mm @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// FramebufferMtl.mm: +// FrameBufferMtl.mm: // Implements the class methods for FramebufferMtl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/angletypes.h" #include "libANGLE/renderer/metal/ContextMtl.h" @@ -1751,11 +1755,11 @@ void RoundValueAndAdjustCorrespondingValue(float a, params.texture = texture; params.textureArea = area; params.textureLevel = renderTarget->getLevelIndex(); - params.textureSliceOrDeph = renderTarget->getLayerIndex(); + params.textureSliceOrDepth = renderTarget->getLayerIndex(); params.reverseTextureRowOrder = reverseRowOrder; - ANGLE_TRY(contextMtl->getDisplay()->getUtils().packPixelsFromTextureToBuffer( - contextMtl, *actualDstAngleFormat, params)); + ANGLE_TRY(contextMtl->getDisplay()->getUtils().packPixelsCS(contextMtl, + *actualDstAngleFormat, params)); } else { diff --git a/src/libANGLE/renderer/metal/IOSurfaceSurfaceMtl.mm b/src/libANGLE/renderer/metal/IOSurfaceSurfaceMtl.mm index 7c0ccdf3888..0da3d9a52e4 100644 --- a/src/libANGLE/renderer/metal/IOSurfaceSurfaceMtl.mm +++ b/src/libANGLE/renderer/metal/IOSurfaceSurfaceMtl.mm @@ -129,6 +129,15 @@ int FindIOSurfaceFormatIndex(GLenum internalFormat, GLenum type) // Initialize offscreen texture if needed: ANGLE_TO_EGL_TRY(ensureColorTextureCreated(context)); + if (mColorTexture) + { + // Mark the resource as written by command buffer so that we wait for command buffer finish + // before doing a readback on the CPU via getBytes. It's necessary to synchronize with the + // shared event wait in the command buffer if the previous user of the IOSurface did not + // call waitUntilScheduled e.g. Chromium will skip waitUntilScheduled on single GPU systems. + contextMtl->markResourceWrittenByCommandBuffer(mColorTexture); + } + return OffscreenSurfaceMtl::bindTexImage(context, texture, buffer); } diff --git a/src/libANGLE/renderer/metal/ProgramExecutableMtl.mm b/src/libANGLE/renderer/metal/ProgramExecutableMtl.mm index b574cf19942..59bd582baf6 100644 --- a/src/libANGLE/renderer/metal/ProgramExecutableMtl.mm +++ b/src/libANGLE/renderer/metal/ProgramExecutableMtl.mm @@ -4,6 +4,11 @@ // found in the LICENSE file. // // ProgramExecutableMtl.cpp: Implementation of ProgramExecutableMtl. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/metal/ProgramExecutableMtl.h" @@ -126,7 +131,7 @@ inline void copy_matrix_row_major(void *dst, } } } -// TODO(angleproject:7979) Upgrade ANGLE Uniform buffer remapper to compute shaders +// TODO(http://anglebug.com/42266442) Upgrade ANGLE Uniform buffer remapper to compute shaders angle::Result ConvertUniformBufferData(ContextMtl *contextMtl, const UBOConversionInfo &blockConversionInfo, mtl::BufferPool *dynamicBuffer, @@ -352,9 +357,7 @@ void ReadFromDefaultUniformBlockWithElementSize(int componentCount, // Convert to actual binary shader angle::ObjCPtr err; - const bool disableFastMath = - context->getDisplay()->getFeatures().intelDisableFastMath.enabled || - translatedMslInfo->hasIsnanOrIsinf; + const bool disableFastMath = translatedMslInfo->hasIsnanOrIsinf; const bool usesInvariance = translatedMslInfo->hasInvariant; translatedMslInfo->metalLibrary = libraryCache.getOrCompileShaderLibrary( context->getDisplay(), translatedMslInfo->metalShaderSource, substitutionMacros, @@ -785,7 +788,7 @@ void ReadFromDefaultUniformBlockWithElementSize(int componentCount, return angle::Result::Continue; } -// TODO(angleproject:7979) Upgrade ANGLE Uniform buffer remapper to compute shaders +// TODO(http://anglebug.com/42266442) Upgrade ANGLE Uniform buffer remapper to compute shaders void ProgramExecutableMtl::initUniformBlocksRemapper(const gl::SharedCompiledShaderState &shader) { std::unordered_map conversionMap; diff --git a/src/libANGLE/renderer/metal/ProgramMtl.mm b/src/libANGLE/renderer/metal/ProgramMtl.mm index 63880a15642..8ad80b50b71 100644 --- a/src/libANGLE/renderer/metal/ProgramMtl.mm +++ b/src/libANGLE/renderer/metal/ProgramMtl.mm @@ -314,8 +314,7 @@ void load(std::vector> *linkSubTasksOut, mtl::TranslatedShaderInfo *translateInfo = &executableMtl->mMslShaderTranslateInfo[shaderType]; std::map macros = GetDefaultSubstitutionDictionary(); - const bool disableFastMath = displayMtl->getFeatures().intelDisableFastMath.enabled || - translateInfo->hasIsnanOrIsinf; + const bool disableFastMath = translateInfo->hasIsnanOrIsinf; const bool usesInvariance = translateInfo->hasInvariant; // Check if the shader is already in the cache and use it instead of spawning a new thread diff --git a/src/libANGLE/renderer/metal/ProvokingVertexHelper.h b/src/libANGLE/renderer/metal/ProvokingVertexHelper.h index 408b43e5351..53897533446 100644 --- a/src/libANGLE/renderer/metal/ProvokingVertexHelper.h +++ b/src/libANGLE/renderer/metal/ProvokingVertexHelper.h @@ -54,19 +54,14 @@ class ProvokingVertexHelper : angle::NonCopyable mtl::ComputeCommandEncoder *getComputeCommandEncoder(); private: - angle::Result getComputePipleineState( - ContextMtl *context, - const mtl::ProvokingVertexComputePipelineDesc &desc, - angle::ObjCPtr> *outComputePipeline); - - angle::Result prepareCommandEncoderForDescriptor(ContextMtl *context, - mtl::ComputeCommandEncoder *encoder, - mtl::ProvokingVertexComputePipelineDesc desc); + angle::Result prepareCommandEncoderForFunction(ContextMtl *context, + mtl::ComputeCommandEncoder *encoder, + uint32_t indexBufferKey, + bool isForGenerateIndices); mtl::BufferPool mIndexBuffers; - - std::unordered_map>> - mComputeFunctions; + std::unordered_map>> mFixIndexBufferFunctions; + std::unordered_map>> mGenIndexBufferFunctions; }; } // namespace rx #endif /* LIBANGLE_RENDERER_METAL_PROVOKINGVERTEXHELPER_H */ diff --git a/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm b/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm index ae11a5b3eff..407117b7622 100644 --- a/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm +++ b/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm @@ -114,12 +114,11 @@ static inline uint indexCountForPrimCount(const uint fixIndexBufferKey, const ui mIndexBuffers.releaseInFlightBuffers(contextMtl); } -static uint buildIndexBufferKey(const mtl::ProvokingVertexComputePipelineDesc &pipelineDesc) +static uint buildIndexBufferKey(gl::DrawElementsType elementType, + bool doPrimPrestart, + gl::PrimitiveMode primMode) { uint indexBufferKey = 0; - gl::DrawElementsType elementType = (gl::DrawElementsType)pipelineDesc.elementType; - bool doPrimPrestart = pipelineDesc.primitiveRestartEnabled; - gl::PrimitiveMode primMode = pipelineDesc.primitiveMode; switch (elementType) { case gl::DrawElementsType::UnsignedShort: @@ -141,50 +140,37 @@ static uint buildIndexBufferKey(const mtl::ProvokingVertexComputePipelineDesc &p return indexBufferKey; } -angle::Result ProvokingVertexHelper::getComputePipleineState( +angle::Result ProvokingVertexHelper::prepareCommandEncoderForFunction( ContextMtl *context, - const mtl::ProvokingVertexComputePipelineDesc &desc, - angle::ObjCPtr> *outComputePipeline) + mtl::ComputeCommandEncoder *encoder, + uint32_t indexBufferKey, + bool isForGenerateIndices) { - auto iter = mComputeFunctions.find(desc); - if (iter != mComputeFunctions.end()) - { - return context->getPipelineCache().getComputePipeline(context, iter->second, - outComputePipeline); - } - - id provokingVertexLibrary = context->getDisplay()->getDefaultShadersLib(); - uint indexBufferKey = buildIndexBufferKey(desc); - auto fcValues = angle::adoptObjCPtr([[MTLFunctionConstantValues alloc] init]); - [fcValues setConstantValue:&indexBufferKey type:MTLDataTypeUInt withName:@"fixIndexBufferKey"]; + auto &functionMap = isForGenerateIndices ? mGenIndexBufferFunctions : mFixIndexBufferFunctions; + NSString *functionName = isForGenerateIndices ? @"genIndexBuffer" : @"fixIndexBuffer"; angle::ObjCPtr> computeShader; - if (desc.generateIndices) + auto iter = functionMap.find(indexBufferKey); + if (iter != functionMap.end()) { - ANGLE_TRY(CreateMslShader(context, provokingVertexLibrary, @"genIndexBuffer", - fcValues.get(), &computeShader)); + computeShader = iter->second; } else { - ANGLE_TRY(CreateMslShader(context, provokingVertexLibrary, @"fixIndexBuffer", - fcValues.get(), &computeShader)); - } - mComputeFunctions[desc] = computeShader; - - return context->getPipelineCache().getComputePipeline(context, computeShader, - outComputePipeline); -} + id provokingVertexLibrary = context->getDisplay()->getDefaultShadersLib(); + auto fcValues = angle::adoptObjCPtr([[MTLFunctionConstantValues alloc] init]); + [fcValues setConstantValue:&indexBufferKey + type:MTLDataTypeUInt + withName:@"fixIndexBufferKey"]; -angle::Result ProvokingVertexHelper::prepareCommandEncoderForDescriptor( - ContextMtl *context, - mtl::ComputeCommandEncoder *encoder, - mtl::ProvokingVertexComputePipelineDesc desc) -{ + ANGLE_TRY(CreateMslShader(context, provokingVertexLibrary, functionName, fcValues.get(), + &computeShader)); + functionMap[indexBufferKey] = computeShader; + } angle::ObjCPtr> pipelineState; - ANGLE_TRY(getComputePipleineState(context, desc, &pipelineState)); - + ANGLE_TRY( + context->getPipelineCache().getComputePipeline(context, computeShader, &pipelineState)); encoder->setComputePipelineState(pipelineState); - return angle::Result::Continue; } @@ -203,30 +189,26 @@ static uint buildIndexBufferKey(const mtl::ProvokingVertexComputePipelineDesc &p // Get specialized program // Upload index buffer // dispatch per-primitive? - mtl::ProvokingVertexComputePipelineDesc pipelineDesc; - pipelineDesc.elementType = (uint8_t)elementsType; - pipelineDesc.primitiveMode = primitiveMode; - pipelineDesc.primitiveRestartEnabled = primitiveRestartEnabled; - pipelineDesc.generateIndices = false; - uint indexBufferKey = buildIndexBufferKey(pipelineDesc); - uint primCount = primCountForIndexCount(indexBufferKey, (uint32_t)indexCount); + uint indexBufferKey = buildIndexBufferKey(elementsType, primitiveRestartEnabled, primitiveMode); + uint primCount = primCountForIndexCount(indexBufferKey, (uint32_t)indexCount); uint newIndexCount = indexCountForPrimCount(indexBufferKey, primCount); size_t indexSize = gl::GetDrawElementsTypeSize(elementsType); size_t newOffset = 0; mtl::BufferRef newBuffer; ANGLE_TRY(mIndexBuffers.allocate(context, newIndexCount * indexSize + indexOffset, nullptr, &newBuffer, &newOffset)); - uint indexCountEncoded = (uint)indexCount; auto threadsPerThreadgroup = MTLSizeMake(MIN(primCount, 64u), 1, 1); mtl::ComputeCommandEncoder *encoder = context->getComputeCommandEncoderWithoutEndingRenderEncoder(); - ANGLE_TRY(prepareCommandEncoderForDescriptor(context, encoder, pipelineDesc)); + const bool isForGenerateIndices = false; + ANGLE_TRY( + prepareCommandEncoderForFunction(context, encoder, indexBufferKey, isForGenerateIndices)); encoder->setBuffer(indexBuffer, static_cast(indexOffset), 0); encoder->setBufferForWrite( newBuffer, static_cast(indexOffset) + static_cast(newOffset), 1); - encoder->setData(&indexCountEncoded, 2); - encoder->setData(&primCount, 3); + encoder->setData(static_cast(indexCount), 2); + encoder->setData(primCount, 3); encoder->dispatch( MTLSizeMake((primCount + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, 1, 1), @@ -251,31 +233,26 @@ static uint buildIndexBufferKey(const mtl::ProvokingVertexComputePipelineDesc &p // Get specialized program // Upload index buffer // dispatch per-primitive? - mtl::ProvokingVertexComputePipelineDesc pipelineDesc; - pipelineDesc.elementType = (uint8_t)elementsType; - pipelineDesc.primitiveMode = primitiveMode; - pipelineDesc.primitiveRestartEnabled = false; - pipelineDesc.generateIndices = true; - uint indexBufferKey = buildIndexBufferKey(pipelineDesc); - uint primCount = primCountForIndexCount(indexBufferKey, (uint32_t)indexCount); + const bool primitiveRestartEnabled = false; + uint indexBufferKey = buildIndexBufferKey(elementsType, primitiveRestartEnabled, primitiveMode); + uint primCount = primCountForIndexCount(indexBufferKey, (uint32_t)indexCount); uint newIndexCount = indexCountForPrimCount(indexBufferKey, primCount); size_t indexSize = gl::GetDrawElementsTypeSize(elementsType); size_t newIndexOffset = 0; mtl::BufferRef newBuffer; ANGLE_TRY(mIndexBuffers.allocate(context, newIndexCount * indexSize, nullptr, &newBuffer, &newIndexOffset)); - uint indexCountEncoded = static_cast(indexCount); - uint firstVertexEncoded = static_cast(first); - uint indexOffsetEncoded = static_cast(newIndexOffset); auto threadsPerThreadgroup = MTLSizeMake(MIN(primCount, 64u), 1, 1); mtl::ComputeCommandEncoder *encoder = context->getComputeCommandEncoderWithoutEndingRenderEncoder(); - ANGLE_TRY(prepareCommandEncoderForDescriptor(context, encoder, pipelineDesc)); - encoder->setBufferForWrite(newBuffer, indexOffsetEncoded, 1); - encoder->setData(indexCountEncoded, 2); + const bool isForGenerateIndices = true; + ANGLE_TRY( + prepareCommandEncoderForFunction(context, encoder, indexBufferKey, isForGenerateIndices)); + encoder->setBufferForWrite(newBuffer, static_cast(newIndexOffset), 1); + encoder->setData(static_cast(indexCount), 2); encoder->setData(primCount, 3); - encoder->setData(firstVertexEncoded, 4); + encoder->setData(static_cast(first), 4); encoder->dispatch( MTLSizeMake((primCount + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, 1, 1), diff --git a/src/libANGLE/renderer/metal/QueryMtl.mm b/src/libANGLE/renderer/metal/QueryMtl.mm index bce1b75b27e..f0d3483130b 100644 --- a/src/libANGLE/renderer/metal/QueryMtl.mm +++ b/src/libANGLE/renderer/metal/QueryMtl.mm @@ -7,6 +7,10 @@ // Defines the class interface for QueryMtl, implementing QueryImpl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/QueryMtl.h" #include "libANGLE/renderer/metal/ContextMtl.h" diff --git a/src/libANGLE/renderer/metal/RenderBufferMtl.mm b/src/libANGLE/renderer/metal/RenderBufferMtl.mm index 36bc1d75473..31b8baa8007 100644 --- a/src/libANGLE/renderer/metal/RenderBufferMtl.mm +++ b/src/libANGLE/renderer/metal/RenderBufferMtl.mm @@ -70,7 +70,7 @@ const gl::TextureCaps &textureCaps = contextMtl->getTextureCaps().get(mFormat.intendedFormatId); - actualSamples = textureCaps.getNearestSamples(actualSamples); + actualSamples = textureCaps.sampleCounts.getNearestSamples(actualSamples); ANGLE_CHECK(contextMtl, actualSamples != 0, gl::err::kInternalError, GL_INVALID_VALUE); } diff --git a/src/libANGLE/renderer/metal/ShaderMtl.mm b/src/libANGLE/renderer/metal/ShaderMtl.mm index 5a99d2e853e..1fa654d5de2 100644 --- a/src/libANGLE/renderer/metal/ShaderMtl.mm +++ b/src/libANGLE/renderer/metal/ShaderMtl.mm @@ -68,6 +68,8 @@ void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledSta options->separateCompoundStructDeclarations = true; + options->forceDeferNonConstGlobalInitializers = true; + if (context->isWebGL() && mState.getShaderType() != gl::ShaderType::Compute) { options->initOutputVariables = true; @@ -76,12 +78,6 @@ void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledSta options->metal.generateShareableShaders = displayMtl->getFeatures().generateShareableShaders.enabled; - if (displayMtl->getFeatures().intelExplicitBoolCastWorkaround.enabled || - options->metal.generateShareableShaders) - { - options->addExplicitBoolCasts = true; - } - options->clampPointSize = true; #if TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST options->clampFragDepth = true; @@ -92,6 +88,8 @@ void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledSta options->emulateAlphaToCoverage = true; } + options->removeInactiveVariables = true; + // Constants: options->metal.driverUniformsBindingIndex = mtl::kDriverUniformsBindingIndex; options->metal.defaultUniformsBindingIndex = mtl::kDefaultUniformsBindingIndex; @@ -112,6 +110,10 @@ void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledSta { options->metal.injectAsmStatementIntoLoopBodies = true; } + if (displayMtl->getFeatures().ensureLoopForwardProgress.enabled) + { + options->ensureLoopForwardProgress = true; + } return std::shared_ptr(new ShaderTranslateTaskMtl(mCompiledState)); } @@ -125,7 +127,7 @@ void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledSta std::string ShaderMtl::getDebugInfo() const { - return mState.getCompiledState()->translatedSource; + return *mState.getCompiledState()->translatedSource; } } // namespace rx diff --git a/src/libANGLE/renderer/metal/SurfaceMtl.h b/src/libANGLE/renderer/metal/SurfaceMtl.h index 1bb07a95ea9..004de337a61 100644 --- a/src/libANGLE/renderer/metal/SurfaceMtl.h +++ b/src/libANGLE/renderer/metal/SurfaceMtl.h @@ -47,7 +47,7 @@ class SurfaceMtl : public SurfaceImpl egl::Error makeCurrent(const gl::Context *context) override; egl::Error unMakeCurrent(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -65,9 +65,6 @@ class SurfaceMtl : public SurfaceImpl void setFixedWidth(EGLint width) override; void setFixedHeight(EGLint height) override; - EGLint getWidth() const override; - EGLint getHeight() const override; - EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; @@ -139,7 +136,7 @@ class WindowSurfaceMtl : public SurfaceMtl egl::Error initialize(const egl::Display *display) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; EGLint getSwapBehavior() const override; @@ -148,9 +145,8 @@ class WindowSurfaceMtl : public SurfaceMtl GLenum binding, const gl::ImageIndex &imageIndex) override; - // width and height can change with client window resizing - EGLint getWidth() const override; - EGLint getHeight() const override; + // size can change with client window resizing + gl::Extents getSize() const override; angle::Result getAttachmentRenderTarget(const gl::Context *context, GLenum binding, const gl::ImageIndex &imageIndex, @@ -200,10 +196,9 @@ class OffscreenSurfaceMtl : public SurfaceMtl void destroy(const egl::Display *display) override; - EGLint getWidth() const override; - EGLint getHeight() const override; + gl::Extents getSize() const override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error bindTexImage(const gl::Context *context, gl::Texture *texture, diff --git a/src/libANGLE/renderer/metal/SurfaceMtl.mm b/src/libANGLE/renderer/metal/SurfaceMtl.mm index 49fd773dbeb..e57fb5018b0 100644 --- a/src/libANGLE/renderer/metal/SurfaceMtl.mm +++ b/src/libANGLE/renderer/metal/SurfaceMtl.mm @@ -159,7 +159,7 @@ return egl::NoError(); } -egl::Error SurfaceMtl::swap(const gl::Context *context) +egl::Error SurfaceMtl::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -216,24 +216,6 @@ UNIMPLEMENTED(); } -EGLint SurfaceMtl::getWidth() const -{ - if (mColorTexture) - { - return static_cast(mColorTexture->widthAt0()); - } - return 0; -} - -EGLint SurfaceMtl::getHeight() const -{ - if (mColorTexture) - { - return static_cast(mColorTexture->heightAt0()); - } - return 0; -} - EGLint SurfaceMtl::isPostSubBufferSupported() const { return EGL_FALSE; @@ -498,7 +480,7 @@ return egl::NoError(); } -egl::Error WindowSurfaceMtl::swap(const gl::Context *context) +egl::Error WindowSurfaceMtl::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { ANGLE_TO_EGL_TRY(swapImpl(context)); @@ -512,15 +494,11 @@ #endif } -// width and height can change with client window resizing -EGLint WindowSurfaceMtl::getWidth() const -{ - return static_cast(mCurrentKnownDrawableSize.width); -} - -EGLint WindowSurfaceMtl::getHeight() const +// size can change with client window resizing +gl::Extents WindowSurfaceMtl::getSize() const { - return static_cast(mCurrentKnownDrawableSize.height); + return gl::Extents(static_cast(mCurrentKnownDrawableSize.width), + static_cast(mCurrentKnownDrawableSize.height), 1); } EGLint WindowSurfaceMtl::getSwapBehavior() const @@ -750,17 +728,12 @@ SurfaceMtl::destroy(display); } -EGLint OffscreenSurfaceMtl::getWidth() const -{ - return mSize.width; -} - -EGLint OffscreenSurfaceMtl::getHeight() const +gl::Extents OffscreenSurfaceMtl::getSize() const { - return mSize.height; + return mSize; } -egl::Error OffscreenSurfaceMtl::swap(const gl::Context *context) +egl::Error OffscreenSurfaceMtl::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { // Check for surface resize. ANGLE_TO_EGL_TRY(ensureTexturesSizeCorrect(context)); diff --git a/src/libANGLE/renderer/metal/SyncMtl.h b/src/libANGLE/renderer/metal/SyncMtl.h index 205b51d9b8a..2a12f1811c4 100644 --- a/src/libANGLE/renderer/metal/SyncMtl.h +++ b/src/libANGLE/renderer/metal/SyncMtl.h @@ -95,7 +95,7 @@ class EGLSyncMtl final : public EGLSyncImpl private: angle::ObjCPtr> mSharedEvent; - + EGLenum mType = EGL_NONE; std::unique_ptr mSync; }; diff --git a/src/libANGLE/renderer/metal/SyncMtl.mm b/src/libANGLE/renderer/metal/SyncMtl.mm index 22a7d754238..baf76a97c99 100644 --- a/src/libANGLE/renderer/metal/SyncMtl.mm +++ b/src/libANGLE/renderer/metal/SyncMtl.mm @@ -208,6 +208,76 @@ static uint64_t SanitizeTimeout(uint64_t timeout) angle::ObjCPtr> mMetalEvent; uint64_t mEncodedCommandBufferSerial = 0; }; + +class CommandsScheduledSyncImpl : public SyncImpl +{ + public: + CommandsScheduledSyncImpl() = default; + ~CommandsScheduledSyncImpl() override = default; + + angle::Result set(ContextMtl *contextMtl) + { + contextMtl->addCommandBufferScheduledCallback([state = mState] { + std::lock_guard lock(state->mutex); + state->signaled = true; + state->cv.notify_one(); + }); + contextMtl->flushCommandBuffer(mtl::NoWait); + return angle::Result::Continue; + } + + angle::Result clientWait(ContextMtl *contextMtl, + bool flushCommands, + uint64_t timeout, + GLenum *outResult) override + { + std::unique_lock lock(mState->mutex); + if (mState->signaled) + { + *outResult = GL_ALREADY_SIGNALED; + return angle::Result::Continue; + } + + if (timeout == 0) + { + *outResult = GL_TIMEOUT_EXPIRED; + return angle::Result::Continue; + } + + if (!mState->cv.wait_for(lock, std::chrono::nanoseconds(SanitizeTimeout(timeout)), + [state = mState] { return state->signaled; })) + { + *outResult = GL_TIMEOUT_EXPIRED; + return angle::Result::Continue; + } + + ASSERT(mState->signaled); + *outResult = GL_CONDITION_SATISFIED; + return angle::Result::Continue; + } + + angle::Result serverWait(ContextMtl *contextMtl) override + { + // Not supported for this sync type. + return angle::Result::Continue; + } + + angle::Result getStatus(DisplayMtl *displayMtl, bool *signaled) override + { + std::lock_guard lock(mState->mutex); + *signaled = mState->signaled; + return angle::Result::Continue; + } + + private: + struct State + { + std::condition_variable cv; + std::mutex mutex; + bool signaled = false; + }; + std::shared_ptr mState{std::make_shared()}; +}; } // namespace mtl // FenceNVMtl implementation @@ -336,7 +406,6 @@ static uint64_t SanitizeTimeout(uint64_t timeout) return egl::Error(EGL_BAD_ALLOC, "eglCreateSyncKHR failed to create sync object"); } mSync = std::move(impl); - break; } @@ -379,11 +448,23 @@ static uint64_t SanitizeTimeout(uint64_t timeout) break; } + case EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE: + { + auto impl = std::make_unique(); + if (IsError(impl->set(contextMtl))) + { + return egl::Error(EGL_BAD_ALLOC, "eglCreateSyncKHR failed to create sync object"); + } + mSync = std::move(impl); + break; + } + default: UNREACHABLE(); return egl::Error(EGL_BAD_ALLOC); } + mType = type; return egl::NoError(); } @@ -395,9 +476,15 @@ static uint64_t SanitizeTimeout(uint64_t timeout) { ASSERT((flags & ~EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) == 0); + // Allow null context only for EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE. + if (mType != EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE && !context) + { + return egl::Error(EGL_BAD_CONTEXT); + } + bool flush = (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) != 0; GLenum result = GL_NONE; - ContextMtl *contextMtl = mtl::GetImpl(context); + ContextMtl *contextMtl = context ? mtl::GetImpl(context) : nullptr; if (IsError(mSync->clientWait(contextMtl, flush, static_cast(timeout), &result))) { return egl::Error(EGL_BAD_ALLOC); diff --git a/src/libANGLE/renderer/metal/TextureMtl.h b/src/libANGLE/renderer/metal/TextureMtl.h index 7593d5c5915..65283cdb644 100644 --- a/src/libANGLE/renderer/metal/TextureMtl.h +++ b/src/libANGLE/renderer/metal/TextureMtl.h @@ -311,7 +311,7 @@ class TextureMtl : public TextureImpl size_t pixelsDepthPitch, gl::Buffer *unpackBuffer, const uint8_t *pixels, - const mtl::TextureRef &image); + const ImageDefinitionMtl &imageDef); // Convert pixels to suported format before uploading to texture angle::Result convertAndSetPerSliceSubImage(const gl::Context *context, @@ -324,7 +324,7 @@ class TextureMtl : public TextureImpl size_t pixelsDepthPitch, gl::Buffer *unpackBuffer, const uint8_t *pixels, - const mtl::TextureRef &image); + const ImageDefinitionMtl &imageDef); angle::Result generateMipmapCPU(const gl::Context *context); diff --git a/src/libANGLE/renderer/metal/TextureMtl.mm b/src/libANGLE/renderer/metal/TextureMtl.mm index 317e2fa2ca7..9301862a49a 100644 --- a/src/libANGLE/renderer/metal/TextureMtl.mm +++ b/src/libANGLE/renderer/metal/TextureMtl.mm @@ -1,4 +1,3 @@ - // // Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,6 +7,10 @@ // Implements the class methods for TextureMtl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/TextureMtl.h" #include @@ -685,7 +688,7 @@ GLenum OverrideSwizzleValue(const gl::Context *context, if (format.actualAngleFormat().hasDepthOrStencilBits()) { ASSERT(!format.swizzled); - if (context->getState().getClientMajorVersion() >= 3 && glInternalFormat.sized) + if (context->getState().getClientVersion() >= gl::ES_3_0 && glInternalFormat.sized) { // ES 3.1 spec: treat depth and stencil textures as red textures during sampling. if (swizzle == GL_GREEN || swizzle == GL_BLUE) @@ -1110,7 +1113,7 @@ uint32_t height(GLuint glLevel) const // for cube maps so that texture wrap modes are ignored. if ((mState.getType() == gl::TextureType::CubeMap || mState.getType() == gl::TextureType::CubeMapArray) && - context->getState().getClientMajorVersion() >= 3) + context->getState().getClientVersion() >= gl::ES_3_0) { samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge; samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge; @@ -1128,6 +1131,9 @@ uint32_t height(GLuint glLevel) const uint32_t maxLevel = std::min(mNativeTextureStorage->getMaxSupportedGLLevel(), mState.getEffectiveMaxLevel()); + // In edge case where base level > max level, clamp up to base level. + maxLevel = std::max(maxLevel, mState.getEffectiveBaseLevel()); + mtl::TextureRef nativeViewFromBaseToMaxLevelRef; if (maxLevel == mNativeTextureStorage->getMaxSupportedGLLevel() && mState.getEffectiveBaseLevel() == mNativeTextureStorage->getBaseGLLevel()) @@ -1172,11 +1178,16 @@ uint32_t height(GLuint glLevel) const return angle::Result::Continue; } + // Account for clamping in createViewFromBaseToMaxLevel() to avoid redundant storage + // re-creation when max < base (e.g., base=7 with max toggling 1->2->3 should not re-create). + GLuint effectiveMaxForStorage = + std::max(mState.getMipmapMaxLevel(), mState.getEffectiveBaseLevel()); + if (mState.getEffectiveBaseLevel() == mNativeTextureStorage->getBaseGLLevel() && - mState.getMipmapMaxLevel() == mNativeTextureStorage->getMaxSupportedGLLevel()) + effectiveMaxForStorage == mNativeTextureStorage->getMaxSupportedGLLevel()) { ASSERT(mState.getBaseLevelDesc().size == mNativeTextureStorage->sizeAt0()); - // If level range remain the same, don't recreate the texture storage. + // If effective level range remains the same, don't recreate the texture storage. // This might feel unnecessary at first since the front-end might prevent redundant base/max // level change already. However, there are cases that cause native storage to be created // before base/max level dirty bit is passed to Metal backend and lead to unwanted problems. @@ -1743,9 +1754,10 @@ uint32_t height(GLuint glLevel) const } // Generate mip level - angleFormat.mipGenerationFunction( - prevLevelWidth, prevLevelHeight, 1, prevLevelData.get(), prevLevelRowPitch, - prevLevelDepthPitch, dstLevelData.get(), dstRowPitch, dstDepthPitch); + angleFormat.mipGenerationFunction(prevLevelWidth, prevLevelHeight, prevLevelDepth, + prevLevelData.get(), prevLevelRowPitch, + prevLevelDepthPitch, dstLevelData.get(), dstRowPitch, + dstDepthPitch); mtl::MipmapNativeLevel nativeLevel = mViewFromBaseToMaxLevel->getNativeLevel(glLevel); @@ -1949,12 +1961,12 @@ uint32_t height(GLuint glLevel) const { format = MTLPixelFormatX32_Stencil8; } -# if TARGET_OS_OSX || TARGET_OS_MACCATALYST +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST else if (format == MTLPixelFormatDepth24Unorm_Stencil8) { format = MTLPixelFormatX24_Stencil8; } -# endif +#endif } mSwizzleStencilSamplingView = mNativeTextureStorage->createMipsSwizzleView( @@ -2179,7 +2191,7 @@ uint32_t height(GLuint glLevel) const ContextMtl *contextMtl = mtl::GetImpl(context); ANGLE_TRY(ensureImageCreated(context, index)); - mtl::TextureRef &image = getImage(index); + ImageDefinitionMtl &imageDef = getImageDefinition(index); GLuint sourceRowPitch = 0; GLuint sourceDepthPitch = 0; @@ -2222,7 +2234,7 @@ uint32_t height(GLuint glLevel) const const uint8_t *srcPixels = usablePixels + slice * sourceDepthPitch; ANGLE_TRY(setPerSliceSubImage(context, sliceIndex, mtlRegion, formatInfo, type, srcAngleFormat, sourceRowPitch, sourceDepthPitch, - unpackBuffer, srcPixels, image)); + unpackBuffer, srcPixels, imageDef)); } } else @@ -2232,7 +2244,7 @@ uint32_t height(GLuint glLevel) const ANGLE_TRY(setPerSliceSubImage(context, 0, mtlRegion, formatInfo, type, srcAngleFormat, sourceRowPitch, sourceDepthPitch, unpackBuffer, usablePixels, - image)); + imageDef)); } return angle::Result::Continue; @@ -2248,20 +2260,21 @@ uint32_t height(GLuint glLevel) const size_t pixelsDepthPitch, gl::Buffer *unpackBuffer, const uint8_t *pixels, - const mtl::TextureRef &image) + const ImageDefinitionMtl &imageDef) { // If source pixels are luminance or RGB8, we need to convert them to RGBA - if (mFormat.needConversion(pixelsAngleFormat.id)) + ContextMtl *contextMtl = mtl::GetImpl(context); + mtl::Format imageFormat = contextMtl->getPixelFormat(imageDef.formatID); + + if (imageFormat.needConversion(pixelsAngleFormat.id)) { return convertAndSetPerSliceSubImage(context, slice, mtlArea, internalFormat, type, pixelsAngleFormat, pixelsRowPitch, pixelsDepthPitch, - unpackBuffer, pixels, image); + unpackBuffer, pixels, imageDef); } // No conversion needed. - ContextMtl *contextMtl = mtl::GetImpl(context); - if (unpackBuffer) { uintptr_t offset = reinterpret_cast(pixels); @@ -2269,26 +2282,26 @@ uint32_t height(GLuint glLevel) const ANGLE_CHECK_GL_MATH(contextMtl, internalFormat.computeRowPitch( type, static_cast(mtlArea.size.width), /** aligment */ 1, /** rowLength */ 0, &minRowPitch)); - if (offset % mFormat.actualAngleFormat().pixelBytes || pixelsRowPitch < minRowPitch) + if (offset % imageFormat.actualAngleFormat().pixelBytes || pixelsRowPitch < minRowPitch) { // offset is not divisible by pixelByte or the source row pitch is smaller than minimum // row pitch, use convertAndSetPerSliceSubImage() function. return convertAndSetPerSliceSubImage(context, slice, mtlArea, internalFormat, type, pixelsAngleFormat, pixelsRowPitch, - pixelsDepthPitch, unpackBuffer, pixels, image); + pixelsDepthPitch, unpackBuffer, pixels, imageDef); } BufferMtl *unpackBufferMtl = mtl::GetImpl(unpackBuffer); - if (mFormat.hasDepthAndStencilBits()) + if (imageFormat.hasDepthAndStencilBits()) { // NOTE(hqle): packed depth & stencil texture cannot copy from buffer directly, needs // to split its depth & stencil data and copy separately. const uint8_t *clientData = unpackBufferMtl->getBufferDataReadOnly(contextMtl); clientData += offset; - ANGLE_TRY(UploadTextureContents(context, mFormat.actualAngleFormat(), mtlArea, - mtl::kZeroNativeMipLevel, slice, clientData, - pixelsRowPitch, pixelsDepthPitch, false, image)); + ANGLE_TRY(UploadTextureContents( + context, imageFormat.actualAngleFormat(), mtlArea, mtl::kZeroNativeMipLevel, slice, + clientData, pixelsRowPitch, pixelsDepthPitch, false, imageDef.image)); } else { @@ -2296,7 +2309,7 @@ uint32_t height(GLuint glLevel) const // PVRTC1 blocks are stored in a reflected Morton order // and need to be linearized for buffer uploads in Metal. // This step is skipped for textures that have only one block. - if (mFormat.isPVRTC() && mtlArea.size.height > 4) + if (imageFormat.isPVRTC() && mtlArea.size.height > 4) { // PVRTC1 inherent requirement. ASSERT(gl::isPow2(mtlArea.size.width) && gl::isPow2(mtlArea.size.height)); @@ -2334,9 +2347,9 @@ uint32_t height(GLuint glLevel) const { // Current command buffer implementation does not support 64-bit offsets. ANGLE_CHECK_GL_MATH(contextMtl, offset <= std::numeric_limits::max()); + size_t imageSize = pixelsRowPitch * mtlArea.size.height; mtl::BufferRef stagingBuffer; - ANGLE_TRY( - mtl::Buffer::MakeBuffer(contextMtl, pixelsDepthPitch, nullptr, &stagingBuffer)); + ANGLE_TRY(mtl::Buffer::MakeBuffer(contextMtl, imageSize, nullptr, &stagingBuffer)); ASSERT(pixelsAngleFormat.pixelBytes == 4 && offset % 4 == 0); ANGLE_TRY(SaturateDepth(contextMtl, sourceBuffer, stagingBuffer, @@ -2347,20 +2360,22 @@ uint32_t height(GLuint glLevel) const offset = 0; } + size_t srcBytesPerImage = mtlArea.size.depth > 1 ? pixelsDepthPitch : 0; + // Use blit encoder to copy - mtl::BlitCommandEncoder *blitEncoder = - GetBlitCommandEncoderForResources(contextMtl, {sourceBuffer.get(), image.get()}); + mtl::BlitCommandEncoder *blitEncoder = GetBlitCommandEncoderForResources( + contextMtl, {sourceBuffer.get(), imageDef.image.get()}); CopyBufferToOriginalTextureIfDstIsAView( - contextMtl, blitEncoder, sourceBuffer, offset, pixelsRowPitch, pixelsDepthPitch, - mtlArea.size, image, slice, mtl::kZeroNativeMipLevel, mtlArea.origin, - mFormat.isPVRTC() ? MTLBlitOptionRowLinearPVRTC : MTLBlitOptionNone); + contextMtl, blitEncoder, sourceBuffer, offset, pixelsRowPitch, srcBytesPerImage, + mtlArea.size, imageDef.image, slice, mtl::kZeroNativeMipLevel, mtlArea.origin, + imageFormat.isPVRTC() ? MTLBlitOptionRowLinearPVRTC : MTLBlitOptionNone); } } else { - ANGLE_TRY(UploadTextureContents(context, mFormat.actualAngleFormat(), mtlArea, + ANGLE_TRY(UploadTextureContents(context, imageFormat.actualAngleFormat(), mtlArea, mtl::kZeroNativeMipLevel, slice, pixels, pixelsRowPitch, - pixelsDepthPitch, false, image)); + pixelsDepthPitch, false, imageDef.image)); } return angle::Result::Continue; } @@ -2375,11 +2390,12 @@ uint32_t height(GLuint glLevel) const size_t pixelsDepthPitch, gl::Buffer *unpackBuffer, const uint8_t *pixels, - const mtl::TextureRef &image) + const ImageDefinitionMtl &imageDef) { - ASSERT(image && image->valid()); + ASSERT(imageDef.image && imageDef.image->valid()); ContextMtl *contextMtl = mtl::GetImpl(context); + mtl::Format imageFormat = contextMtl->getPixelFormat(imageDef.formatID); if (unpackBuffer) { @@ -2389,47 +2405,54 @@ uint32_t height(GLuint glLevel) const uint32_t offset = static_cast(reinterpret_cast(pixels)); BufferMtl *unpackBufferMtl = mtl::GetImpl(unpackBuffer); - if (!mFormat.getCaps().writable || mFormat.hasDepthOrStencilBits() || - mFormat.intendedAngleFormat().isBlock) + if (!imageFormat.getCaps().isRenderable() || imageFormat.hasDepthOrStencilBits() || + imageFormat.intendedAngleFormat().isBlock || + !contextMtl->getDisplay()->getUtils().isPixelsUnpackSupported(pixelsAngleFormat)) { // Unsupported format, use CPU path. const uint8_t *clientData = unpackBufferMtl->getBufferDataReadOnly(contextMtl); clientData += offset; - ANGLE_TRY(convertAndSetPerSliceSubImage(context, slice, mtlArea, internalFormat, type, - pixelsAngleFormat, pixelsRowPitch, - pixelsDepthPitch, nullptr, clientData, image)); + ANGLE_TRY(convertAndSetPerSliceSubImage( + context, slice, mtlArea, internalFormat, type, pixelsAngleFormat, pixelsRowPitch, + pixelsDepthPitch, nullptr, clientData, imageDef)); } else { - // Use compute shader + // Use shaders mtl::CopyPixelsFromBufferParams params; params.buffer = unpackBufferMtl->getCurrentBuffer(); params.bufferStartOffset = offset; params.bufferRowPitch = static_cast(pixelsRowPitch); params.bufferDepthPitch = static_cast(pixelsDepthPitch); - params.texture = image; - params.textureArea = mtl::MTLRegionToGLBox(mtlArea); + params.texture = imageDef.image; + params.textureArea = mtl::MTLRegionToGLRect(mtlArea); // If texture is not array, slice must be zero, if texture is array, mtlArea.origin.z // must be zero. // This is because this function uses Metal convention: where slice is only used for // array textures, and z layer of mtlArea.origin is only used for 3D textures. - ASSERT(slice == 0 || params.textureArea.z == 0); + ASSERT(slice == 0 || mtlArea.origin.z == 0); // For mtl::RenderUtils we convert to OpenGL convention: z layer is used as either array // texture's slice or 3D texture's layer index. - params.textureArea.z += slice; + params.textureSliceOrDepth = std::max(slice, static_cast(mtlArea.origin.z)); + + for (uint32_t z = 0; z < static_cast(mtlArea.size.depth); ++z) + { + ANGLE_TRY(contextMtl->getDisplay()->getUtils().unpackPixelsWithDraw( + context, pixelsAngleFormat, params)); - ANGLE_TRY(contextMtl->getDisplay()->getUtils().unpackPixelsFromBufferToTexture( - contextMtl, pixelsAngleFormat, params)); + params.textureSliceOrDepth++; + params.bufferStartOffset += params.bufferDepthPitch; + } } } // if (unpackBuffer) else { - LoadImageFunctionInfo loadFunctionInfo = mFormat.textureLoadFunctions - ? mFormat.textureLoadFunctions(type) + LoadImageFunctionInfo loadFunctionInfo = imageFormat.textureLoadFunctions + ? imageFormat.textureLoadFunctions(type) : LoadImageFunctionInfo(); - const angle::Format &dstFormat = angle::Format::Get(mFormat.actualFormatId); + const angle::Format &dstFormat = angle::Format::Get(imageFormat.actualFormatId); const size_t dstRowPitch = dstFormat.pixelBytes * mtlArea.size.width; // It is very important to avoid allocating a new buffer for each row during these @@ -2437,9 +2460,9 @@ uint32_t height(GLuint glLevel) const const bool kAvoidStagingBuffers = true; // Check if original image data is compressed: - if (mFormat.intendedAngleFormat().isBlock) + if (imageFormat.intendedAngleFormat().isBlock) { - if (mFormat.intendedFormatId != mFormat.actualFormatId) + if (imageFormat.intendedFormatId != imageFormat.actualFormatId) { ASSERT(loadFunctionInfo.loadFunction); @@ -2456,21 +2479,24 @@ uint32_t height(GLuint glLevel) const decompressBuf.data(), dstRowPitch, dstDepthPitch); // Upload to texture - ANGLE_TRY(UploadTextureContents( - context, dstFormat, mtlArea, mtl::kZeroNativeMipLevel, slice, - decompressBuf.data(), dstRowPitch, dstDepthPitch, kAvoidStagingBuffers, image)); + ANGLE_TRY(UploadTextureContents(context, dstFormat, mtlArea, + mtl::kZeroNativeMipLevel, slice, + decompressBuf.data(), dstRowPitch, dstDepthPitch, + kAvoidStagingBuffers, imageDef.image)); } else { // Assert that we're filling the level in it's entierety. - ASSERT(mtlArea.size.width == static_cast(image->sizeAt0().width)); - ASSERT(mtlArea.size.height == static_cast(image->sizeAt0().height)); + ASSERT(mtlArea.size.width == + static_cast(imageDef.image->sizeAt0().width)); + ASSERT(mtlArea.size.height == + static_cast(imageDef.image->sizeAt0().height)); const size_t dstDepthPitch = dstRowPitch * mtlArea.size.height; ANGLE_TRY(UploadTextureContents( context, dstFormat, mtlArea, mtl::kZeroNativeMipLevel, slice, pixels, - dstRowPitch, dstDepthPitch, kAvoidStagingBuffers, image)); + dstRowPitch, dstDepthPitch, kAvoidStagingBuffers, imageDef.image)); } - } // if (mFormat.intendedAngleFormat().isBlock) + } // if (imageFormat.intendedAngleFormat().isBlock) else { // Create scratch row buffer @@ -2495,7 +2521,7 @@ uint32_t height(GLuint glLevel) const mtlRow.size.width, 1, 1, psrc, pixelsRowPitch, 0, conversionRow.data(), dstRowPitch, 0); } - else if (mFormat.hasDepthOrStencilBits()) + else if (imageFormat.hasDepthOrStencilBits()) { ConvertDepthStencilData(mtlRow.size, pixelsAngleFormat, pixelsRowPitch, 0, psrc, dstFormat, nullptr, dstRowPitch, 0, @@ -2512,13 +2538,14 @@ uint32_t height(GLuint glLevel) const } // Upload to texture - ANGLE_TRY(UploadTextureContents( - context, dstFormat, mtlRow, mtl::kZeroNativeMipLevel, slice, - conversionRow.data(), dstRowPitch, 0, kAvoidStagingBuffers, image)); + ANGLE_TRY(UploadTextureContents(context, dstFormat, mtlRow, + mtl::kZeroNativeMipLevel, slice, + conversionRow.data(), dstRowPitch, 0, + kAvoidStagingBuffers, imageDef.image)); } } } // if (mFormat.intendedAngleFormat().isBlock) - } // if (unpackBuffer) + } // if (unpackBuffer) return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/metal/TransformFeedbackMtl.mm b/src/libANGLE/renderer/metal/TransformFeedbackMtl.mm index 5dd9a305bc4..a8446de973e 100644 --- a/src/libANGLE/renderer/metal/TransformFeedbackMtl.mm +++ b/src/libANGLE/renderer/metal/TransformFeedbackMtl.mm @@ -7,6 +7,10 @@ // Defines the class interface for TransformFeedbackMtl, implementing TransformFeedbackImpl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/TransformFeedbackMtl.h" #include "common/debug.h" diff --git a/src/libANGLE/renderer/metal/VertexArrayMtl.h b/src/libANGLE/renderer/metal/VertexArrayMtl.h index 22bc12112f5..b7981ba547b 100644 --- a/src/libANGLE/renderer/metal/VertexArrayMtl.h +++ b/src/libANGLE/renderer/metal/VertexArrayMtl.h @@ -25,7 +25,9 @@ class ContextMtl; class VertexArrayMtl : public VertexArrayImpl { public: - VertexArrayMtl(const gl::VertexArrayState &state, ContextMtl *context); + VertexArrayMtl(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers, + ContextMtl *context); ~VertexArrayMtl() override; void destroy(const gl::Context *context) override; diff --git a/src/libANGLE/renderer/metal/VertexArrayMtl.mm b/src/libANGLE/renderer/metal/VertexArrayMtl.mm index 051fed3b2f8..6cd57d3e34c 100644 --- a/src/libANGLE/renderer/metal/VertexArrayMtl.mm +++ b/src/libANGLE/renderer/metal/VertexArrayMtl.mm @@ -7,6 +7,10 @@ // Implements the class methods for VertexArrayMtl. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/VertexArrayMtl.h" #include @@ -205,8 +209,10 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) } // namespace // VertexArrayMtl implementation -VertexArrayMtl::VertexArrayMtl(const gl::VertexArrayState &state, ContextMtl *context) - : VertexArrayImpl(state), +VertexArrayMtl::VertexArrayMtl(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers, + ContextMtl *context) + : VertexArrayImpl(state, vertexArrayBuffers), mDefaultFloatVertexFormat( context->getVertexFormat(angle::FormatID::R32G32B32A32_FLOAT, false)) { @@ -289,18 +295,6 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) size_t dirtyBit = *iter; switch (dirtyBit) { - case gl::VertexArray::DIRTY_BIT_LOST_OBSERVATION: - { - // If vertex array was not observing while unbound, we need to check buffer's - // internal storage and take action if buffer has changed while not observing. - // For now we just simply assume buffer storage has changed and always dirty all - // binding points. - iter.setLaterBits( - gl::VertexArray::DirtyBits(mState.getBufferBindingMask().to_ulong() - << gl::VertexArray::DIRTY_BIT_BINDING_0)); - break; - } - case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER: case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA: { @@ -386,6 +380,11 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) std::array currentAttribFormats{}; for (auto &input : executable->getProgramInputs()) { + if (input.isBuiltIn()) + { + continue; + } + ASSERT(input.getLocation() != -1); ASSERT(input.getLocation() < static_cast(mtl::kMaxVertexAttribs)); currentAttribFormats[input.getLocation()] = GetCurrentAttribFormat(input.getType()); @@ -519,7 +518,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) const void *indices) { ContextMtl *contextMtl = mtl::GetImpl(context); - const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask(); + const gl::AttributesMask &clientAttribs = context->getActiveClientAttribsMask(); ASSERT(clientAttribs.any()); @@ -537,7 +536,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) { const gl::VertexAttribute &attrib = attribs[attribIndex]; const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; - ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr); + ASSERT(attrib.enabled && getVertexArrayBuffer(attrib.bindingIndex) == nullptr); // Source client memory pointer const uint8_t *src = static_cast(attrib.pointer); @@ -647,10 +646,11 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) { ContextMtl *contextMtl = mtl::GetImpl(glContext); ASSERT(mtl::kMaxVertexAttribs > attribIndex); + mContentsObserverBindingsMask.reset(attrib.bindingIndex); if (attrib.enabled) { - gl::Buffer *bufferGL = binding.getBuffer().get(); + gl::Buffer *bufferGL = getVertexArrayBuffer(attrib.bindingIndex); const mtl::VertexFormat &format = contextMtl->getVertexFormat(attrib.format->id, false); if (bufferGL) @@ -659,7 +659,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) // https://bugs.webkit.org/show_bug.cgi?id=236733 // even non-converted buffers need to be observed for potential // data rebinds. - mContentsObservers->enableForBuffer(bufferGL, static_cast(attribIndex)); + mContentsObserverBindingsMask.set(attrib.bindingIndex); bool needConversion = format.actualFormatId != format.intendedFormatId || (binding.getOffset() % mtl::kVertexAttribBufferStrideAlignment) != 0 || @@ -705,7 +705,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) size_t *idxBufferOffsetOut, gl::DrawElementsType *indexTypeOut) { - const gl::Buffer *glElementArrayBuffer = getState().getElementArrayBuffer(); + const gl::Buffer *glElementArrayBuffer = getElementArrayBuffer(); size_t convertedOffset = reinterpret_cast(indices); if (!glElementArrayBuffer) @@ -763,7 +763,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) } const std::vector *restartIndices; std::vector clientIndexRange; - const gl::Buffer *glElementArrayBuffer = getState().getElementArrayBuffer(); + const gl::Buffer *glElementArrayBuffer = getElementArrayBuffer(); if (glElementArrayBuffer) { BufferMtl *idxBuffer = mtl::GetImpl(glElementArrayBuffer); @@ -862,7 +862,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) ContextMtl *contextMtl = mtl::GetImpl(glContext); const gl::State &glState = glContext->getState(); - BufferMtl *idxBuffer = mtl::GetImpl(getState().getElementArrayBuffer()); + BufferMtl *idxBuffer = mtl::GetImpl(getElementArrayBuffer()); IndexConversionBufferMtl *conversion = idxBuffer->getIndexConversionBuffer( contextMtl, indexType, glState.isPrimitiveRestartEnabled(), offsetModulo); @@ -938,7 +938,7 @@ inline MTLVertexFormat GetCurrentAttribFormat(GLenum type) mtl::BufferRef *idxBufferOut, size_t *idxBufferOffsetOut) { - ASSERT(getState().getElementArrayBuffer() == nullptr); + ASSERT(getElementArrayBuffer() == nullptr); ContextMtl *contextMtl = mtl::GetImpl(context); auto srcData = static_cast(sourcePointer); diff --git a/src/libANGLE/renderer/metal/blocklayoutMetal.cpp b/src/libANGLE/renderer/metal/blocklayoutMetal.cpp index 4becaf3e1b3..1986eb7de4a 100644 --- a/src/libANGLE/renderer/metal/blocklayoutMetal.cpp +++ b/src/libANGLE/renderer/metal/blocklayoutMetal.cpp @@ -251,6 +251,7 @@ void MetalAlignmentVisitor::visitVariable(const sh::ShaderVariable &variable, bo BlockLayoutEncoderMTL::BlockLayoutEncoderMTL() : BlockLayoutEncoder() {} void BlockLayoutEncoderMTL::getBlockLayoutInfo(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, @@ -283,19 +284,21 @@ void BlockLayoutEncoderMTL::getBlockLayoutInfo(GLenum type, *arrayStrideOut = arrayStride; } sh::BlockMemberInfo BlockLayoutEncoderMTL::encodeType(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix) { int arrayStride; int matrixStride; - getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride); + getBlockLayoutInfo(type, bytesPerComponent, arraySizes, isRowMajorMatrix, &arrayStride, + &matrixStride); const sh::BlockMemberInfo memberInfo( type, static_cast(mCurrentOffset), static_cast(arrayStride), static_cast(matrixStride), gl::ArraySizeProduct(arraySizes), isRowMajorMatrix); assert(memberInfo.offset >= 0); - advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); + advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); return memberInfo; } @@ -353,6 +356,7 @@ size_t BlockLayoutEncoderMTL::getShaderVariableSize(const sh::ShaderVariable &st } void BlockLayoutEncoderMTL::advanceOffset(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, diff --git a/src/libANGLE/renderer/metal/blocklayoutMetal.h b/src/libANGLE/renderer/metal/blocklayoutMetal.h index 85f8591e87c..4cb22d8dc74 100644 --- a/src/libANGLE/renderer/metal/blocklayoutMetal.h +++ b/src/libANGLE/renderer/metal/blocklayoutMetal.h @@ -48,6 +48,7 @@ class BlockLayoutEncoderMTL : public sh::BlockLayoutEncoder ~BlockLayoutEncoderMTL() override {} sh::BlockMemberInfo encodeType(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix) override; // Advance the offset based on struct size and array dimensions. Size can be calculated with @@ -66,11 +67,13 @@ class BlockLayoutEncoderMTL : public sh::BlockLayoutEncoder private: void getBlockLayoutInfo(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override; void advanceOffset(GLenum type, + size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, diff --git a/src/libANGLE/renderer/metal/file_hooking/shader_cache_file_hooking.cpp b/src/libANGLE/renderer/metal/file_hooking/shader_cache_file_hooking.cpp index a62778234a5..0bf77cdb2c4 100644 --- a/src/libANGLE/renderer/metal/file_hooking/shader_cache_file_hooking.cpp +++ b/src/libANGLE/renderer/metal/file_hooking/shader_cache_file_hooking.cpp @@ -9,6 +9,10 @@ // time. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include #include diff --git a/src/libANGLE/renderer/metal/mtl_buffer_manager.mm b/src/libANGLE/renderer/metal/mtl_buffer_manager.mm index 846ab8ff0c9..cab4928836d 100644 --- a/src/libANGLE/renderer/metal/mtl_buffer_manager.mm +++ b/src/libANGLE/renderer/metal/mtl_buffer_manager.mm @@ -7,6 +7,10 @@ // Implements the class methods for BufferManager. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_buffer_manager.h" #include "libANGLE/renderer/metal/ContextMtl.h" diff --git a/src/libANGLE/renderer/metal/mtl_buffer_pool.mm b/src/libANGLE/renderer/metal/mtl_buffer_pool.mm index 2791fd12e1e..c369a0f76aa 100644 --- a/src/libANGLE/renderer/metal/mtl_buffer_pool.mm +++ b/src/libANGLE/renderer/metal/mtl_buffer_pool.mm @@ -7,6 +7,10 @@ // Implements the class methods for BufferPool. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_buffer_pool.h" #include "libANGLE/renderer/metal/ContextMtl.h" diff --git a/src/libANGLE/renderer/metal/mtl_command_buffer.h b/src/libANGLE/renderer/metal/mtl_command_buffer.h index a4786802ae1..22cc8a52125 100644 --- a/src/libANGLE/renderer/metal/mtl_command_buffer.h +++ b/src/libANGLE/renderer/metal/mtl_command_buffer.h @@ -11,6 +11,10 @@ #ifndef LIBANGLE_RENDERER_METAL_COMMANDENBUFFERMTL_H_ #define LIBANGLE_RENDERER_METAL_COMMANDENBUFFERMTL_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #import #import #include @@ -100,6 +104,9 @@ class CommandQueue final : public WrappedObject>, angle::Non bool isSerialCompleted(uint64_t serial) const; bool waitUntilSerialCompleted(uint64_t serial, uint64_t timeoutNs) const; + bool isSerialScheduled(uint64_t serial) const; + void addCommandBufferScheduledCallback(uint64_t serial, std::function callback); + CommandQueue &operator=(id metalQueue) { set(metalQueue); @@ -107,6 +114,7 @@ class CommandQueue final : public WrappedObject>, angle::Non } angle::ObjCPtr> makeMetalCommandBuffer(uint64_t *queueSerialOut); + void onCommandBufferCommitted(id buf, uint64_t serial); uint64_t getNextRenderPassEncoderSerial(); @@ -119,10 +127,18 @@ class CommandQueue final : public WrappedObject>, angle::Non MTLCommandBufferError popCmdBufferError() { return mCmdBufferError.pop(); } private: + using ParentClass = WrappedObject>; + void onCommandBufferCompleted(id buf, uint64_t serial, uint64_t timeElapsedEntry); - using ParentClass = WrappedObject>; + + void onCommandBufferScheduled(uint64_t serial); + + void addCommandBufferToTimeElapsedEntry(std::lock_guard &lg, uint64_t id); + void recordCommandBufferTimeElapsed(std::lock_guard &lg, + uint64_t id, + double seconds); struct CmdBufferQueueEntry { @@ -133,6 +149,7 @@ class CommandQueue final : public WrappedObject>, angle::Non uint64_t mQueueSerialCounter = 1; AtomicSerial mCommittedBufferSerial; + AtomicSerial mScheduledBufferSerial; AtomicSerial mCompletedBufferSerial; uint64_t mRenderEncoderCounter = 1; @@ -158,10 +175,7 @@ class CommandQueue final : public WrappedObject>, angle::Non AtomicCommandBufferError mCmdBufferError; - void addCommandBufferToTimeElapsedEntry(std::lock_guard &lg, uint64_t id); - void recordCommandBufferTimeElapsed(std::lock_guard &lg, - uint64_t id, - double seconds); + angle::HashMap>> mCommandBufferScheduledCallbacks; }; class CommandBuffer final : public WrappedObject>, angle::NonCopyable @@ -189,7 +203,7 @@ class CommandBuffer final : public WrappedObject>, angle::N uint64_t queueEventSignal(id event, uint64_t value); void serverWaitEvent(id event, uint64_t value); - void insertDebugSign(const std::string &marker); + void insertDebugSignpost(const std::string &marker); void pushDebugGroup(const std::string &marker); void popDebugGroup(); @@ -240,7 +254,7 @@ class CommandBuffer final : public WrappedObject>, angle::N mutable std::mutex mLock; - std::vector mPendingDebugSigns; + std::vector mPendingDebugSignposts; struct PendingEvent { angle::ObjCPtr> event; @@ -252,7 +266,6 @@ class CommandBuffer final : public WrappedObject>, angle::N angle::HashSet mResourceList; size_t mWorkingResourceSize = 0; bool mCommitted = false; - CommandBufferFinishOperation mLastWaitOp = mtl::NoWait; }; class CommandEncoder : public WrappedObject>, angle::NonCopyable @@ -275,7 +288,7 @@ class CommandEncoder : public WrappedObject>, angle::NonCo CommandEncoder &markResourceBeingWrittenByGPU(const BufferRef &buffer); CommandEncoder &markResourceBeingWrittenByGPU(const TextureRef &texture); - void insertDebugSign(NSString *label); + void insertDebugSignpost(NSString *label); virtual void pushDebugGroup(NSString *label); virtual void popDebugGroup(); @@ -290,7 +303,7 @@ class CommandEncoder : public WrappedObject>, angle::NonCo void set(id metalCmdEncoder); - virtual void insertDebugSignImpl(NSString *marker); + virtual void insertDebugSignpostImpl(NSString *marker); private: bool isRenderEncoder() const { return getType() == Type::RENDER; } @@ -502,13 +515,13 @@ class RenderCommandEncoder final : public CommandEncoder uint32_t offset, uint32_t index); RenderCommandEncoder &setBytes(gl::ShaderType shaderType, - const uint8_t *bytes, + const void *bytes, size_t size, uint32_t index); - template + template >> RenderCommandEncoder &setData(gl::ShaderType shaderType, const T &data, uint32_t index) { - return setBytes(shaderType, reinterpret_cast(&data), sizeof(T), index); + return setBytes(shaderType, &data, sizeof(data), index); } RenderCommandEncoder &setSamplerState(gl::ShaderType shaderType, id state, @@ -602,7 +615,7 @@ class RenderCommandEncoder final : public CommandEncoder { return static_cast>(CommandEncoder::get()); } - void insertDebugSignImpl(NSString *label) override; + void insertDebugSignpostImpl(NSString *label) override; void initAttachmentWriteDependencyAndScissorRect(const RenderPassAttachmentDesc &attachment); void initWriteDependency(const TextureRef &texture); @@ -723,11 +736,11 @@ class ComputeCommandEncoder final : public CommandEncoder ComputeCommandEncoder &setBufferForWrite(const BufferRef &buffer, uint32_t offset, uint32_t index); - ComputeCommandEncoder &setBytes(const uint8_t *bytes, size_t size, uint32_t index); + ComputeCommandEncoder &setBytes(const void *bytes, size_t size, uint32_t index); template ComputeCommandEncoder &setData(const T &data, uint32_t index) { - return setBytes(reinterpret_cast(&data), sizeof(T), index); + return setBytes(&data, sizeof(data), index); } ComputeCommandEncoder &setSamplerState(id state, float lodMinClamp, diff --git a/src/libANGLE/renderer/metal/mtl_command_buffer.mm b/src/libANGLE/renderer/metal/mtl_command_buffer.mm index ab7d4b54ee8..31448a46384 100644 --- a/src/libANGLE/renderer/metal/mtl_command_buffer.mm +++ b/src/libANGLE/renderer/metal/mtl_command_buffer.mm @@ -8,6 +8,10 @@ // MTLCommandEncoder's wrappers. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/metal/mtl_command_buffer.h" #include @@ -76,7 +80,7 @@ PROC(UseResource) \ PROC(MemoryBarrier) \ PROC(MemoryBarrierWithResource) \ - PROC(InsertDebugsign) \ + PROC(InsertDebugSignpost) \ PROC(PushDebugGroup) \ PROC(PopDebugGroup) @@ -402,8 +406,8 @@ inline void MemoryBarrierWithResourceCmd(id encoder, [resource ANGLE_MTL_RELEASE]; } -inline void InsertDebugsignCmd(id encoder, - IntermediateCommandStream *stream) +inline void InsertDebugSignpostCmd(id encoder, + IntermediateCommandStream *stream) { NSString *label = stream->fetch(); [encoder insertDebugSignpost:label]; @@ -593,6 +597,26 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) return true; } +bool CommandQueue::isSerialScheduled(uint64_t serial) const +{ + return mScheduledBufferSerial.load() >= serial; +} + +void CommandQueue::addCommandBufferScheduledCallback(uint64_t serial, + std::function callback) +{ + std::lock_guard lg(mLock); + if (isSerialScheduled(serial)) + { + // Run the callback immediately if the command buffer for `serial` was already scheduled. + callback(); + } + else + { + mCommandBufferScheduledCallbacks[serial].push_back(std::move(callback)); + } +} + angle::ObjCPtr> CommandQueue::makeMetalCommandBuffer(uint64_t *queueSerialOut) { ANGLE_MTL_OBJC_SCOPE @@ -613,6 +637,10 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) addCommandBufferToTimeElapsedEntry(lg, timeElapsedEntry); } + [metalCmdBuffer addScheduledHandler:^(id buf) { + onCommandBufferScheduled(serial); + }]; + [metalCmdBuffer addCompletedHandler:^(id buf) { onCommandBufferCompleted(buf, serial, timeElapsedEntry); }]; @@ -632,6 +660,25 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) mCommittedBufferSerial.storeMaxValue(serial); } +void CommandQueue::onCommandBufferScheduled(uint64_t serial) +{ + std::vector> callbacks; + { + std::lock_guard lg(mLock); + auto it = mCommandBufferScheduledCallbacks.find(serial); + if (it != mCommandBufferScheduledCallbacks.end()) + { + callbacks = std::move(it->second); + mCommandBufferScheduledCallbacks.erase(it); + } + mScheduledBufferSerial.storeMaxValue(serial); + } + for (const auto &callback : callbacks) + { + callback(); + } +} + void CommandQueue::onCommandBufferCompleted(id buf, uint64_t serial, uint64_t timeElapsedEntry) @@ -825,19 +872,17 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) case WaitUntilScheduled: // Only wait if we haven't already waited - if (mLastWaitOp == NoWait) + if (!mCmdQueue.isSerialScheduled(mQueueSerial)) { [get() waitUntilScheduled]; - mLastWaitOp = WaitUntilScheduled; } break; case WaitUntilFinished: // Only wait if we haven't already waited until finished. - if (mLastWaitOp != WaitUntilFinished) + if (!mCmdQueue.isSerialCompleted(mQueueSerial)) { [get() waitUntilCompleted]; - mLastWaitOp = WaitUntilFinished; } break; } @@ -940,7 +985,6 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) set(metalCmdBuffer); mQueueSerial = serial; mCommitted = false; - mLastWaitOp = mtl::NoWait; for (std::string &marker : mDebugGroups) { @@ -950,7 +994,7 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) ASSERT(metalCmdBuffer); } -void CommandBuffer::insertDebugSign(const std::string &marker) +void CommandBuffer::insertDebugSignpost(const std::string &marker) { mtl::CommandEncoder *currentEncoder = getPendingCommandEncoder(); if (currentEncoder) @@ -958,12 +1002,12 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) ANGLE_MTL_OBJC_SCOPE { NSString *label = cppLabelToObjC(marker); - currentEncoder->insertDebugSign(label); + currentEncoder->insertDebugSignpost(label); } } else { - mPendingDebugSigns.push_back(marker); + mPendingDebugSignposts.push_back(marker); } } @@ -1044,15 +1088,15 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) mActiveBlitOrComputeEncoder = encoder; } - for (std::string &marker : mPendingDebugSigns) + for (std::string &marker : mPendingDebugSignposts) { ANGLE_MTL_OBJC_SCOPE { NSString *label = cppLabelToObjC(marker); - encoder->insertDebugSign(label); + encoder->insertDebugSignpost(label); } } - mPendingDebugSigns.clear(); + mPendingDebugSignposts.clear(); } void CommandBuffer::invalidateActiveCommandEncoder(CommandEncoder *encoder) @@ -1234,12 +1278,12 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) [get() popDebugGroup]; } -void CommandEncoder::insertDebugSign(NSString *label) +void CommandEncoder::insertDebugSignpost(NSString *label) { - insertDebugSignImpl(label); + insertDebugSignpostImpl(label); } -void CommandEncoder::insertDebugSignImpl(NSString *label) +void CommandEncoder::insertDebugSignpostImpl(NSString *label) { // Default implementation [get() insertDebugSignpost:label]; @@ -1945,7 +1989,7 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) } RenderCommandEncoder &RenderCommandEncoder::setBytes(gl::ShaderType shaderType, - const uint8_t *bytes, + const void *bytes, size_t size, uint32_t index) { @@ -1960,7 +2004,7 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) mCommands.push(static_cast(mSetBytesCmds[shaderType])) .push(size) - .push(bytes, size) + .push(reinterpret_cast(bytes), size) .push(index); return *this; @@ -2243,10 +2287,10 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) return *this; } -void RenderCommandEncoder::insertDebugSignImpl(NSString *label) +void RenderCommandEncoder::insertDebugSignpostImpl(NSString *label) { // Defer the insertion until endEncoding() - mCommands.push(CmdType::InsertDebugsign).push([label ANGLE_MTL_RETAIN]); + mCommands.push(CmdType::InsertDebugSignpost).push([label ANGLE_MTL_RETAIN]); } void RenderCommandEncoder::pushDebugGroup(NSString *label) @@ -2661,7 +2705,7 @@ void RandomizeClearValue(ObjCAttachmentDescriptor *objCRenderPassAttachment) return setBuffer(buffer, offset, index); } -ComputeCommandEncoder &ComputeCommandEncoder::setBytes(const uint8_t *bytes, +ComputeCommandEncoder &ComputeCommandEncoder::setBytes(const void *bytes, size_t size, uint32_t index) { diff --git a/src/libANGLE/renderer/metal/mtl_common.h b/src/libANGLE/renderer/metal/mtl_common.h index 434a8b56faa..6d9ad791ac4 100644 --- a/src/libANGLE/renderer/metal/mtl_common.h +++ b/src/libANGLE/renderer/metal/mtl_common.h @@ -99,7 +99,7 @@ constexpr uint32_t kMaxColorTargetBitsApple1To3 = 256; constexpr uint32_t kMaxColorTargetBitsApple4Plus = 512; constexpr uint32_t kMaxColorTargetBitsMacAndCatalyst = std::numeric_limits::max(); -constexpr uint32_t kMaxShaderUBOs = 12; +constexpr uint32_t kMaxShaderUBOs = 16; constexpr uint32_t kMaxUBOSize = 16384; constexpr uint32_t kMaxShaderXFBs = gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; diff --git a/src/libANGLE/renderer/metal/mtl_format_utils.mm b/src/libANGLE/renderer/metal/mtl_format_utils.mm index b6fb44c79e2..193b445b8d6 100644 --- a/src/libANGLE/renderer/metal/mtl_format_utils.mm +++ b/src/libANGLE/renderer/metal/mtl_format_utils.mm @@ -8,6 +8,10 @@ // to respective MTLPixelFormat and MTLVertexFormat. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_format_utils.h" #include "common/debug.h" diff --git a/src/libANGLE/renderer/metal/mtl_msl_utils.mm b/src/libANGLE/renderer/metal/mtl_msl_utils.mm index b702a4071b6..be06ab1c206 100644 --- a/src/libANGLE/renderer/metal/mtl_msl_utils.mm +++ b/src/libANGLE/renderer/metal/mtl_msl_utils.mm @@ -201,7 +201,7 @@ bool MappedSamplerNameNeedsUserDefinedPrefix(const std::string &originalName) if (MappedSamplerNameNeedsUserDefinedPrefix(originalName)) { - samplerName = sh::kUserDefinedNamePrefix + samplerName; + samplerName = kUserDefinedNamePrefix + samplerName; } return samplerName; @@ -214,7 +214,7 @@ void MSLGetShaderSource(const gl::ProgramState &programState, for (const gl::ShaderType shaderType : gl::AllShaderTypes()) { const gl::SharedCompiledShaderState &glShader = programState.getAttachedShader(shaderType); - (*shaderSourcesOut)[shaderType] = glShader ? glShader->translatedSource : ""; + (*shaderSourcesOut)[shaderType] = glShader ? *glShader->translatedSource : ""; } } @@ -232,7 +232,7 @@ void GetAssignedSamplerBindings(const sh::TranslatorMetalReflection *reflection, // Assign sequential index for subsequent array elements const bool structSampler = structSamplers.find(name) != structSamplers.end(); const std::string mappedName = - structSampler ? name : MSLGetMappedSamplerName(sh::kUserDefinedNamePrefix + name); + structSampler ? name : MSLGetMappedSamplerName(kUserDefinedNamePrefix + name); auto original = originalBindings.find(mappedName); if (original != originalBindings.end()) { @@ -260,6 +260,11 @@ void GetAssignedSamplerBindings(const sh::TranslatorMetalReflection *reflection, std::array maxComponents{}; for (auto &attribute : executable.getProgramInputs()) { + if (attribute.isBuiltIn()) + { + continue; + } + const int location = attribute.getLocation(); const int registers = gl::VariableRegisterCount(attribute.getType()); const uint8_t components = gl::VariableColumnCount(attribute.getType()); @@ -274,6 +279,11 @@ void GetAssignedSamplerBindings(const sh::TranslatorMetalReflection *reflection, std::ostringstream stream; for (auto &attribute : executable.getProgramInputs()) { + if (attribute.isBuiltIn()) + { + continue; + } + const int location = attribute.getLocation(); const int registers = gl::VariableRegisterCount(attribute.getType()); const uint8_t components = gl::VariableColumnCount(attribute.getType()); @@ -329,6 +339,11 @@ void GetAssignedSamplerBindings(const sh::TranslatorMetalReflection *reflection, std::unordered_map attributeBindings; for (auto &attribute : programAttributes) { + if (attribute.isBuiltIn()) + { + continue; + } + const int registers = gl::VariableRegisterCount(attribute.getType()); for (int i = 0; i < registers; i++) { diff --git a/src/libANGLE/renderer/metal/mtl_pipeline_cache.mm b/src/libANGLE/renderer/metal/mtl_pipeline_cache.mm index 34b832d9c75..a9ddff71d93 100644 --- a/src/libANGLE/renderer/metal/mtl_pipeline_cache.mm +++ b/src/libANGLE/renderer/metal/mtl_pipeline_cache.mm @@ -7,6 +7,10 @@ // Defines classes for caching of mtl pipelines // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_pipeline_cache.h" #include "libANGLE/ErrorStrings.h" diff --git a/src/libANGLE/renderer/metal/mtl_render_utils.h b/src/libANGLE/renderer/metal/mtl_render_utils.h index c635204d640..d2c16b82b8a 100644 --- a/src/libANGLE/renderer/metal/mtl_render_utils.h +++ b/src/libANGLE/renderer/metal/mtl_render_utils.h @@ -13,6 +13,7 @@ #import #include +#include #include "libANGLE/angletypes.h" #include "libANGLE/renderer/metal/RenderTargetMtl.h" @@ -157,24 +158,20 @@ struct CopyPixelsCommonParams uint32_t bufferRowPitch = 0; TextureRef texture; + + gl::Rectangle textureArea = {}; + uint32_t textureSliceOrDepth = 0; }; struct CopyPixelsFromBufferParams : CopyPixelsCommonParams { uint32_t bufferDepthPitch = 0; - - // z offset is: - // - slice index if texture is array. - // - depth if texture is 3d. - gl::Box textureArea; }; struct CopyPixelsToBufferParams : CopyPixelsCommonParams { - gl::Rectangle textureArea; MipmapNativeLevel textureLevel = kZeroNativeMipLevel; - uint32_t textureSliceOrDeph = 0; - bool reverseTextureRowOrder; + bool reverseTextureRowOrder = false; }; struct VertexFormatConvertParams @@ -255,30 +252,51 @@ class ColorBlitUtils final : angle::NonCopyable const ColorBlitParams ¶ms); private: + ANGLE_ENABLE_STRUCT_PADDING_WARNINGS struct ShaderKey { - uint32_t numColorAttachments = 0; int sourceTextureType = 0; - bool unmultiplyAlpha = false; - bool premultiplyAlpha = false; - bool transformLinearToSrgb = false; + uint32_t numColorAttachments : 29; + uint32_t unmultiplyAlpha : 1; + uint32_t premultiplyAlpha : 1; + uint32_t transformLinearToSrgb : 1; + ShaderKey() + : numColorAttachments(0), + unmultiplyAlpha(false), + premultiplyAlpha(false), + transformLinearToSrgb(false) + {} + ShaderKey(int sourceTextureType, + uint32_t numColorAttachments, + bool unmultiplyAlpha, + bool premultiplyAlpha, + bool transformLinearToSrgb) + : sourceTextureType(sourceTextureType), + numColorAttachments(numColorAttachments), + unmultiplyAlpha(unmultiplyAlpha != premultiplyAlpha ? unmultiplyAlpha : false), + premultiplyAlpha(unmultiplyAlpha != premultiplyAlpha ? premultiplyAlpha : false), + transformLinearToSrgb(transformLinearToSrgb) + {} bool operator==(const ShaderKey &other) const { - return numColorAttachments == other.numColorAttachments && + return sourceTextureType == other.sourceTextureType && + numColorAttachments == other.numColorAttachments && unmultiplyAlpha == other.unmultiplyAlpha && premultiplyAlpha == other.premultiplyAlpha && - transformLinearToSrgb == other.transformLinearToSrgb && - sourceTextureType == other.sourceTextureType; + transformLinearToSrgb == other.transformLinearToSrgb; } struct Hash { size_t operator()(const ShaderKey &k) const noexcept { - return angle::HashMultiple(k.numColorAttachments, k.unmultiplyAlpha, - k.premultiplyAlpha, k.sourceTextureType); + return angle::HashMultiple(k.sourceTextureType, k.numColorAttachments, + k.unmultiplyAlpha, k.premultiplyAlpha, + k.transformLinearToSrgb); } }; }; + ANGLE_DISABLE_STRUCT_PADDING_WARNINGS + static_assert(sizeof(ShaderKey) == 8); angle::Result ensureShadersInitialized(ContextMtl *ctx, const ShaderKey &key, angle::ObjCPtr> *fragmentShaderOut); @@ -387,18 +405,6 @@ class IndexGeneratorUtils final : angle::NonCopyable angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms); - angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated); - - angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated); - - angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated); - private: // Index generator compute shaders: // - First dimension: index type. @@ -457,11 +463,6 @@ class IndexGeneratorUtils final : angle::NonCopyable ContextMtl *contextMtl, const IndexGenerationParams ¶ms); - angle::Result generatePrimitiveRestartBuffer(ContextMtl *contextMtl, - unsigned numVerticesPerPrimitive, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated); - IndexConversionShaderArray mIndexConversionShaders; IndexConversionShaderArray mTriFanFromElemArrayGeneratorShaders; @@ -531,27 +532,38 @@ class CopyPixelsUtils final : angle::NonCopyable CopyPixelsUtils() = default; CopyPixelsUtils(const std::string &readShaderName, const std::string &writeShaderName); - angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl, - const angle::Format &srcAngleFormat, - const CopyPixelsFromBufferParams ¶ms); - angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl, - const angle::Format &dstAngleFormat, - const CopyPixelsToBufferParams ¶ms); + angle::Result unpackPixelsWithDraw(const gl::Context *context, + const angle::Format &srcAngleFormat, + const CopyPixelsFromBufferParams ¶ms); + angle::Result packPixelsCS(ContextMtl *contextMtl, + const angle::Format &dstAngleFormat, + const CopyPixelsToBufferParams ¶ms); private: - angle::Result getPixelsCopyPipeline( + angle::Result getT2BComputePipeline( ContextMtl *contextMtl, const angle::Format &angleFormat, const TextureRef &texture, - bool bufferWrite, angle::ObjCPtr> *outComputePipeline); - // Copy pixels between buffer and texture compute pipelines: - // - First dimension: pixel format. - // - Second dimension: texture type * (buffer read/write flag) - using PixelsCopyComputeShaderArray = - std::array>, mtl_shader::kTextureTypeCount * 2>, + angle::Result getB2TRenderPipeline( + ContextMtl *contextMtl, + RenderCommandEncoder *cmdEncoder, + const angle::Format &angleFormat, + angle::ObjCPtr> *outRenderPipeline); + // Compute functions that copy pixels from texture to buffer: + // - First dimension: pixel format key. + // - Second dimension: texture type key. + using T2BComputeShaderArray = + std::array>, mtl_shader::kTextureTypeCount>, angle::kNumANGLEFormats>; - PixelsCopyComputeShaderArray mPixelsCopyComputeShaders; + T2BComputeShaderArray mT2BComputeShaders; + + // Render pipeline functions that copy pixels from buffer to texture: + // - Keyed by pixel formats. + using B2TFragmentShaderArray = + std::array>, angle::kNumANGLEFormats>; + B2TFragmentShaderArray mB2TFragmentShaders; + angle::ObjCPtr> mB2TVertexShader; const std::string mReadShaderName; const std::string mWriteShaderName; @@ -723,12 +735,13 @@ class RenderUtils : angle::NonCopyable bool sRGBMipmap, NativeTexLevelArray *mipmapOutputViews); - angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl, - const angle::Format &srcAngleFormat, - const CopyPixelsFromBufferParams ¶ms); - angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl, - const angle::Format &dstAngleFormat, - const CopyPixelsToBufferParams ¶ms); + bool isPixelsUnpackSupported(const angle::Format &format) const; + angle::Result unpackPixelsWithDraw(const gl::Context *context, + const angle::Format &srcAngleFormat, + const CopyPixelsFromBufferParams ¶ms); + angle::Result packPixelsCS(ContextMtl *contextMtl, + const angle::Format &dstAngleFormat, + const CopyPixelsToBufferParams ¶ms); // See VertexFormatConversionUtils::convertVertexFormatToFloatCS() angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl, @@ -749,12 +762,6 @@ class RenderUtils : angle::NonCopyable const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); - angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated); - angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated); angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); @@ -779,6 +786,8 @@ class RenderUtils : angle::NonCopyable VertexFormatConversionUtils mVertexFormatUtils; BlockLinearizationUtils mBlockLinearizationUtils; DepthSaturationUtils mDepthSaturationUtils; + + const std::unordered_set mPixelUnpackSupportedFormats; }; } // namespace mtl diff --git a/src/libANGLE/renderer/metal/mtl_render_utils.mm b/src/libANGLE/renderer/metal/mtl_render_utils.mm index 5745d4e39da..c11203e2a35 100644 --- a/src/libANGLE/renderer/metal/mtl_render_utils.mm +++ b/src/libANGLE/renderer/metal/mtl_render_utils.mm @@ -7,6 +7,10 @@ // Implements the class methods for RenderUtils. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_render_utils.h" #include @@ -111,14 +115,13 @@ // See libANGLE/renderer/metal/shaders/copy_buffer.metal struct CopyPixelFromBufferUniforms { - uint32_t copySize[3]; - uint32_t padding1; - uint32_t textureOffset[3]; - uint32_t padding2; uint32_t bufferStartOffset; uint32_t pixelSize; uint32_t bufferRowPitch; uint32_t bufferDepthPitch; + + uint32_t textureOffset[2]; + uint8_t padding[8]; }; struct WritePixelToBufferUniforms { @@ -153,6 +156,77 @@ uint32_t padding[3]; }; +constexpr angle::FormatID kSupportedPixelUnpackFormats[] = { + // Float formats + angle::FormatID::R5G6B5_UNORM, + angle::FormatID::R8G8B8A8_UNORM, + angle::FormatID::R8G8B8A8_UNORM_SRGB, + angle::FormatID::R8G8B8A8_SNORM, + angle::FormatID::B8G8R8A8_UNORM, + angle::FormatID::B8G8R8A8_UNORM_SRGB, + angle::FormatID::R8G8B8_UNORM, + angle::FormatID::R8G8B8_UNORM_SRGB, + angle::FormatID::R8G8B8_SNORM, + angle::FormatID::L8_UNORM, + angle::FormatID::L8A8_UNORM, + angle::FormatID::R5G5B5A1_UNORM, + angle::FormatID::R4G4B4A4_UNORM, + angle::FormatID::R8_UNORM, + angle::FormatID::R8_SNORM, + angle::FormatID::R8G8_UNORM, + angle::FormatID::R8G8_SNORM, + angle::FormatID::R16_FLOAT, + angle::FormatID::R16_SNORM, + angle::FormatID::R16_UNORM, + angle::FormatID::A16_FLOAT, + angle::FormatID::L16_FLOAT, + angle::FormatID::L16A16_FLOAT, + angle::FormatID::R16G16_FLOAT, + angle::FormatID::R16G16_SNORM, + angle::FormatID::R16G16_UNORM, + angle::FormatID::R16G16B16_FLOAT, + angle::FormatID::R16G16B16_SNORM, + angle::FormatID::R16G16B16_UNORM, + angle::FormatID::R16G16B16A16_FLOAT, + angle::FormatID::R16G16B16A16_SNORM, + angle::FormatID::R16G16B16A16_UNORM, + angle::FormatID::R32_FLOAT, + angle::FormatID::A32_FLOAT, + angle::FormatID::L32_FLOAT, + angle::FormatID::L32A32_FLOAT, + angle::FormatID::R32G32_FLOAT, + angle::FormatID::R32G32B32_FLOAT, + angle::FormatID::R32G32B32A32_FLOAT, + + // Int formats + angle::FormatID::R8_SINT, + angle::FormatID::R8G8_SINT, + angle::FormatID::R8G8B8_SINT, + angle::FormatID::R8G8B8A8_SINT, + angle::FormatID::R16_SINT, + angle::FormatID::R16G16_SINT, + angle::FormatID::R16G16B16_SINT, + angle::FormatID::R16G16B16A16_SINT, + angle::FormatID::R32_SINT, + angle::FormatID::R32G32_SINT, + angle::FormatID::R32G32B32_SINT, + angle::FormatID::R32G32B32A32_SINT, + + // Uint formats + angle::FormatID::R8_UINT, + angle::FormatID::R8G8_UINT, + angle::FormatID::R8G8B8_UINT, + angle::FormatID::R8G8B8A8_UINT, + angle::FormatID::R16_UINT, + angle::FormatID::R16G16_UINT, + angle::FormatID::R16G16B16_UINT, + angle::FormatID::R16G16B16A16_UINT, + angle::FormatID::R32_UINT, + angle::FormatID::R32G32_UINT, + angle::FormatID::R32G32B32_UINT, + angle::FormatID::R32G32B32A32_UINT, +}; + // Class to automatically disable occlusion query upon entering block and re-able it upon // exiting block. struct ScopedDisableOcclusionQuery @@ -312,146 +386,36 @@ void GetBlitTexCoords(const NormalizedCoords &normalizedCoords, return angle::Result::Continue; } -template -angle::Result GenPrimitiveRestartBuffer(ContextMtl *contextMtl, - GLsizei count, - GLsizei indicesPerPrimitive, - const T *indices, - const BufferRef &dstBuffer, - uint32_t dstOffset, - size_t *indicesGenerated) +// Converts line loop vertices to line strip vertices. +// Returns number of vertices written. +template +size_t CopyLineLoopIndices(GLsizei indexCount, + const uint8_t *indices, + bool usePrimitiveRestart, + uint8_t *outIndices) { - constexpr T kSrcPrimitiveRestartIndex = std::numeric_limits::max(); - uint32_t *dstPtr = reinterpret_cast(dstBuffer->map(contextMtl) + dstOffset); - GLsizei readValueLoc = 0; - T readValue = 0; - uint32_t dstIdx = 0; - memcpy(&readValue, indices, sizeof(readValue)); - while (readValue == kSrcPrimitiveRestartIndex) + if (usePrimitiveRestart) { - - ++readValueLoc; - memcpy(&readValue, indices + readValueLoc, sizeof(readValue)); + return CopyLineLoopIndicesWithRestart(indexCount, indices, outIndices); } - while (readValueLoc + indicesPerPrimitive <= count) + if (indexCount <= 0) { - - uint32_t primIndicies[3]; - bool foundPrimitive = true; - for (int k = 0; k < indicesPerPrimitive; ++k) - { - memcpy(&readValue, indices + readValueLoc, sizeof(readValue)); - ++readValueLoc; - if (readValue == kSrcPrimitiveRestartIndex) - { - foundPrimitive = false; - break; - } - else - { - primIndicies[k] = (uint32_t)readValue; - } - } - if (foundPrimitive) - { - memcpy(&dstPtr[dstIdx], primIndicies, (indicesPerPrimitive) * sizeof(uint32_t)); - dstIdx += indicesPerPrimitive; - } + return 0; } - if (indicesGenerated) - *indicesGenerated = dstIdx; - return angle::Result::Continue; -} - -template -angle::Result GenLineLoopFromClientElements(ContextMtl *contextMtl, - GLsizei count, - bool primitiveRestartEnabled, - const T *indices, - const BufferRef &dstBuffer, - uint32_t dstOffset, - uint32_t *indicesGenerated) -{ - ASSERT(count >= 2); - constexpr T kSrcPrimitiveRestartIndex = std::numeric_limits::max(); - const uint32_t kDstPrimitiveRestartIndex = std::numeric_limits::max(); - - uint32_t *dstPtr = reinterpret_cast(dstBuffer->map(contextMtl) + dstOffset); - // lineLoopFirstIdx: value of of current line loop's first vertex index. Can change when - // encounter a primitive restart index. - T lineLoopFirstIdx; - memcpy(&lineLoopFirstIdx, indices, sizeof(lineLoopFirstIdx)); - - if (primitiveRestartEnabled) + In firstValue; + memcpy(&firstValue, indices, sizeof(In)); + for (GLsizei i = 0; i < indexCount; ++i) { - // lineLoopFirstIdxLoc: location of current line loop's first vertex in the source buffer. - GLsizei lineLoopFirstIdxLoc = 0; - while (lineLoopFirstIdx == kSrcPrimitiveRestartIndex) - { - memcpy(&dstPtr[lineLoopFirstIdxLoc++], &kDstPrimitiveRestartIndex, - sizeof(kDstPrimitiveRestartIndex)); - memcpy(&lineLoopFirstIdx, indices + lineLoopFirstIdxLoc, sizeof(lineLoopFirstIdx)); - } - - // dstIdx : value of index to be written to dest buffer - uint32_t dstIdx = lineLoopFirstIdx; - memcpy(&dstPtr[lineLoopFirstIdxLoc], &dstIdx, sizeof(dstIdx)); - // dstWritten: number of indices written to dest buffer - uint32_t dstWritten = lineLoopFirstIdxLoc + 1; - - for (GLsizei i = lineLoopFirstIdxLoc + 1; i < count; ++i) - { - // srcIdx : value of index from source buffer - T srcIdx; - memcpy(&srcIdx, indices + i, sizeof(srcIdx)); - if (srcIdx == kSrcPrimitiveRestartIndex) - { - // breaking line strip - dstIdx = lineLoopFirstIdx; - memcpy(&dstPtr[dstWritten++], &dstIdx, sizeof(dstIdx)); - memcpy(&dstPtr[dstWritten++], &kDstPrimitiveRestartIndex, - sizeof(kDstPrimitiveRestartIndex)); - lineLoopFirstIdxLoc = i + 1; - } - else - { - dstIdx = srcIdx; - memcpy(&dstPtr[dstWritten++], &dstIdx, sizeof(dstIdx)); - if (lineLoopFirstIdxLoc == i) - { - lineLoopFirstIdx = srcIdx; - } - } - } - - if (lineLoopFirstIdxLoc < count) - { - // last segment - dstIdx = lineLoopFirstIdx; - memcpy(&dstPtr[dstWritten++], &dstIdx, sizeof(dstIdx)); - } - - *indicesGenerated = dstWritten; + In value; + memcpy(&value, indices, sizeof(In)); + indices += sizeof(In); + Out outValue = value; + memcpy(outIndices, &outValue, sizeof(Out)); + outIndices += sizeof(Out); } - else - { - uint32_t dstIdx = lineLoopFirstIdx; - memcpy(dstPtr, &dstIdx, sizeof(dstIdx)); - memcpy(dstPtr + count, &dstIdx, sizeof(dstIdx)); - for (GLsizei i = 1; i < count; ++i) - { - T srcIdx; - memcpy(&srcIdx, indices + i, sizeof(srcIdx)); - - dstIdx = srcIdx; - memcpy(dstPtr + i, &dstIdx, sizeof(dstIdx)); - } - - *indicesGenerated = count + 1; - } - dstBuffer->unmapAndFlushSubset(contextMtl, dstOffset, (*indicesGenerated) * sizeof(uint32_t)); - - return angle::Result::Continue; + Out outFirstValue = firstValue; + memcpy(outIndices, &outFirstValue, sizeof(Out)); + return indexCount + 1; } template @@ -507,9 +471,9 @@ int GetPixelTypeIndex(const angle::Format &angleFormat) } } -angle::Result EnsureComputeShaderInitialized(ContextMtl *context, - NSString *functionName, - angle::ObjCPtr> *shaderOut) +angle::Result EnsureShaderInitialized(ContextMtl *context, + NSString *functionName, + angle::ObjCPtr> *shaderOut) { angle::ObjCPtr> &shader = *shaderOut; if (shader) @@ -526,15 +490,15 @@ int GetPixelTypeIndex(const angle::Format &angleFormat) } } -angle::Result EnsureSpecializedComputeShaderInitialized(ContextMtl *context, - NSString *functionName, - MTLFunctionConstantValues *funcConstants, - angle::ObjCPtr> *shaderOut) +angle::Result EnsureSpecializedShaderInitialized(ContextMtl *context, + NSString *functionName, + MTLFunctionConstantValues *funcConstants, + angle::ObjCPtr> *shaderOut) { if (!funcConstants) { // Non specialized constants provided, use default creation function. - return EnsureComputeShaderInitialized(context, functionName, shaderOut); + return EnsureShaderInitialized(context, functionName, shaderOut); } angle::ObjCPtr> &shader = *shaderOut; @@ -795,9 +759,11 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ColorBlitUtils("blitFloatFS")}, mCopyTextureFloatToUIntUtils("copyTextureFloatToUIntFS"), mCopyPixelsUtils{ - CopyPixelsUtils("readFromBufferToIntTexture", "writeFromIntTextureToBuffer"), - CopyPixelsUtils("readFromBufferToUIntTexture", "writeFromUIntTextureToBuffer"), - CopyPixelsUtils("readFromBufferToFloatTexture", "writeFromFloatTextureToBuffer")} + CopyPixelsUtils("readFromBufferToIntTextureFS", "writeFromIntTextureToBufferCS"), + CopyPixelsUtils("readFromBufferToUIntTextureFS", "writeFromUIntTextureToBufferCS"), + CopyPixelsUtils("readFromBufferToFloatTextureFS", "writeFromFloatTextureToBufferCS")}, + mPixelUnpackSupportedFormats(std::begin(kSupportedPixelUnpackFormats), + std::end(kSupportedPixelUnpackFormats)) {} // Clear current framebuffer @@ -925,26 +891,6 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, { return mIndexUtils.generateLineLoopLastSegmentFromElementsArray(contextMtl, params); } -angle::Result RenderUtils::generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - return mIndexUtils.generatePrimitiveRestartPointsBuffer(contextMtl, params, indicesGenerated); -} -angle::Result RenderUtils::generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - return mIndexUtils.generatePrimitiveRestartLinesBuffer(contextMtl, params, indicesGenerated); -} -angle::Result RenderUtils::generatePrimitiveRestartTrianglesBuffer( - ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - return mIndexUtils.generatePrimitiveRestartTrianglesBuffer(contextMtl, params, - indicesGenerated); -} void RenderUtils::combineVisibilityResult( ContextMtl *contextMtl, @@ -968,21 +914,25 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, return mMipmapUtils.generateMipmapCS(contextMtl, srcTexture, sRGBMipmap, mipmapOutputViews); } -angle::Result RenderUtils::unpackPixelsFromBufferToTexture(ContextMtl *contextMtl, - const angle::Format &srcAngleFormat, - const CopyPixelsFromBufferParams ¶ms) +bool RenderUtils::isPixelsUnpackSupported(const angle::Format &format) const { + return mPixelUnpackSupportedFormats.count(format.id) != 0; +} + +angle::Result RenderUtils::unpackPixelsWithDraw(const gl::Context *context, + const angle::Format &srcAngleFormat, + const CopyPixelsFromBufferParams ¶ms) +{ + ASSERT(isPixelsUnpackSupported(srcAngleFormat)); int index = GetPixelTypeIndex(srcAngleFormat); - return mCopyPixelsUtils[index].unpackPixelsFromBufferToTexture(contextMtl, srcAngleFormat, - params); + return mCopyPixelsUtils[index].unpackPixelsWithDraw(context, srcAngleFormat, params); } -angle::Result RenderUtils::packPixelsFromTextureToBuffer(ContextMtl *contextMtl, - const angle::Format &dstAngleFormat, - const CopyPixelsToBufferParams ¶ms) +angle::Result RenderUtils::packPixelsCS(ContextMtl *contextMtl, + const angle::Format &dstAngleFormat, + const CopyPixelsToBufferParams ¶ms) { int index = GetPixelTypeIndex(dstAngleFormat); - return mCopyPixelsUtils[index].packPixelsFromTextureToBuffer(contextMtl, dstAngleFormat, - params); + return mCopyPixelsUtils[index].packPixelsCS(contextMtl, dstAngleFormat, params); } angle::Result RenderUtils::convertVertexFormatToFloatCS(ContextMtl *contextMtl, @@ -1256,20 +1206,24 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, angle::ObjCPtr funcConstants = angle::adoptObjCPtr([[MTLFunctionConstantValues alloc] init]); + bool unmultiplyAlpha = key.unmultiplyAlpha; + bool premultiplyAlpha = key.premultiplyAlpha; + bool transformLinearToSrgb = key.transformLinearToSrgb; // Set alpha multiply flags - [funcConstants setConstantValue:&key.unmultiplyAlpha + [funcConstants setConstantValue:&unmultiplyAlpha type:MTLDataTypeBool withName:UNMULTIPLY_ALPHA_CONSTANT_NAME]; - [funcConstants setConstantValue:&key.premultiplyAlpha + [funcConstants setConstantValue:&premultiplyAlpha type:MTLDataTypeBool withName:PREMULTIPLY_ALPHA_CONSTANT_NAME]; - [funcConstants setConstantValue:&key.transformLinearToSrgb + [funcConstants setConstantValue:&transformLinearToSrgb type:MTLDataTypeBool withName:TRANSFORM_LINEAR_TO_SRGB_CONSTANT_NAME]; + uint32_t numColorAttachments = key.numColorAttachments; // We create blit shader pipeline cache for each number of color outputs. // So blit k color outputs will use mBlitRenderPipelineCache[k-1] for example: - [funcConstants setConstantValue:&key.numColorAttachments + [funcConstants setConstantValue:&numColorAttachments type:MTLDataTypeUInt withName:NUM_COLOR_OUTPUTS_CONSTANT_NAME]; @@ -1305,15 +1259,9 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, pipelineDesc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; - ShaderKey key; - key.numColorAttachments = renderPassDesc.numColorAttachments; - key.sourceTextureType = GetShaderTextureType(params.src); - key.transformLinearToSrgb = params.transformLinearToSrgb; - if (params.unpackPremultiplyAlpha != params.unpackUnmultiplyAlpha) - { - key.unmultiplyAlpha = params.unpackUnmultiplyAlpha; - key.premultiplyAlpha = params.unpackPremultiplyAlpha; - } + ShaderKey key(GetShaderTextureType(params.src), renderPassDesc.numColorAttachments, + params.unpackUnmultiplyAlpha, params.unpackPremultiplyAlpha, + params.transformLinearToSrgb); angle::ObjCPtr> *fragmentShader = &mBlitFragmentShaders[key]; ANGLE_TRY(ensureShadersInitialized(contextMtl, key, fragmentShader)); @@ -1450,8 +1398,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, { ANGLE_MTL_OBJC_SCOPE { - auto shaderLib = contextMtl->getDisplay()->getDefaultShadersLib(); - NSError *err = nil; + auto shaderLib = contextMtl->getDisplay()->getDefaultShadersLib(); + NSError *err = nil; angle::ObjCPtr funcConstants = angle::adoptObjCPtr([[MTLFunctionConstantValues alloc] init]); @@ -1488,8 +1436,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, pipelineDesc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; angle::ObjCPtr> *fragmentShader = nullptr; - int depthTextureType = GetShaderTextureType(params.src); - int stencilTextureType = GetShaderTextureType(params.srcStencil); + int depthTextureType = GetShaderTextureType(params.src); + int stencilTextureType = GetShaderTextureType(params.srcStencil); if (params.src && params.srcStencil) { fragmentShader = &mDepthStencilBlitFragmentShaders[depthTextureType][stencilTextureType]; @@ -1699,9 +1647,9 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, uint32_t srcOffset, angle::ObjCPtr> *outComputePipeline) { - size_t elementSize = gl::GetDrawElementsTypeSize(srcType); - BOOL aligned = (srcOffset % elementSize) == 0; - int srcTypeKey = static_cast(srcType); + size_t elementSize = gl::GetDrawElementsTypeSize(srcType); + BOOL aligned = (srcOffset % elementSize) == 0; + int srcTypeKey = static_cast(srcType); angle::ObjCPtr> &shader = mIndexConversionShaders[srcTypeKey][aligned ? 1 : 0]; if (!shader) @@ -1733,8 +1681,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, UNREACHABLE(); } - ANGLE_TRY(EnsureSpecializedComputeShaderInitialized(contextMtl, shaderName, - funcConstants, &shader)); + ANGLE_TRY( + EnsureSpecializedShaderInitialized(contextMtl, shaderName, funcConstants, &shader)); } } @@ -1795,8 +1743,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, type:MTLDataTypeBool withName:SOURCE_IDX_IS_U32_CONSTANT_NAME]; - ANGLE_TRY(EnsureSpecializedComputeShaderInitialized(contextMtl, shaderName, - funcConstants, &shader)); + ANGLE_TRY( + EnsureSpecializedShaderInitialized(contextMtl, shaderName, funcConstants, &shader)); } } @@ -1808,8 +1756,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outComputePipeline) { - ANGLE_TRY(EnsureComputeShaderInitialized(contextMtl, @"genTriFanIndicesFromArray", - &mTriFanFromArraysGeneratorShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"genTriFanIndicesFromArray", + &mTriFanFromArraysGeneratorShader)); return contextMtl->getPipelineCache().getComputePipeline( contextMtl, mTriFanFromArraysGeneratorShader, outComputePipeline); } @@ -1818,8 +1766,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outComputePipeline) { - ANGLE_TRY(EnsureComputeShaderInitialized(contextMtl, @"genLineLoopIndicesFromArray", - &mLineLoopFromArraysGeneratorShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"genLineLoopIndicesFromArray", + &mLineLoopFromArraysGeneratorShader)); return contextMtl->getPipelineCache().getComputePipeline( contextMtl, mLineLoopFromArraysGeneratorShader, outComputePipeline); } @@ -2089,28 +2037,34 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated) { + uint8_t *dstIndices = params.dstBuffer->map(contextMtl, params.dstOffset); + if (dstIndices == nullptr) + { + return angle::Result::Stop; + } + const uint8_t *indices = static_cast(params.indices); + size_t dstIndexCount = 0; switch (params.srcType) { case gl::DrawElementsType::UnsignedByte: - return GenLineLoopFromClientElements( - contextMtl, params.indexCount, params.primitiveRestartEnabled, - static_cast(params.indices), params.dstBuffer, params.dstOffset, - indicesGenerated); + dstIndexCount = CopyLineLoopIndices( + params.indexCount, indices, params.primitiveRestartEnabled, dstIndices); + break; case gl::DrawElementsType::UnsignedShort: - return GenLineLoopFromClientElements( - contextMtl, params.indexCount, params.primitiveRestartEnabled, - static_cast(params.indices), params.dstBuffer, params.dstOffset, - indicesGenerated); + dstIndexCount = CopyLineLoopIndices( + params.indexCount, indices, params.primitiveRestartEnabled, dstIndices); + break; case gl::DrawElementsType::UnsignedInt: - return GenLineLoopFromClientElements( - contextMtl, params.indexCount, params.primitiveRestartEnabled, - static_cast(params.indices), params.dstBuffer, params.dstOffset, - indicesGenerated); + dstIndexCount = CopyLineLoopIndices( + params.indexCount, indices, params.primitiveRestartEnabled, dstIndices); + break; default: UNREACHABLE(); } - - return angle::Result::Stop; + params.dstBuffer->unmapAndFlushSubset(contextMtl, params.dstOffset, + dstIndexCount * sizeof(uint32_t)); + *indicesGenerated = static_cast(dstIndexCount); + return angle::Result::Continue; } angle::Result IndexGeneratorUtils::generateLineLoopLastSegment(ContextMtl *contextMtl, @@ -2187,63 +2141,13 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, return generateLineLoopLastSegment(contextMtl, first, last, params.dstBuffer, params.dstOffset); } -angle::Result IndexGeneratorUtils::generatePrimitiveRestartBuffer( - ContextMtl *contextMtl, - unsigned numVerticesPerPrimitive, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - switch (params.srcType) - { - case gl::DrawElementsType::UnsignedByte: - return GenPrimitiveRestartBuffer(contextMtl, params.indexCount, numVerticesPerPrimitive, - static_cast(params.indices), - params.dstBuffer, params.dstOffset, indicesGenerated); - case gl::DrawElementsType::UnsignedShort: - return GenPrimitiveRestartBuffer(contextMtl, params.indexCount, numVerticesPerPrimitive, - static_cast(params.indices), - params.dstBuffer, params.dstOffset, indicesGenerated); - case gl::DrawElementsType::UnsignedInt: - return GenPrimitiveRestartBuffer(contextMtl, params.indexCount, numVerticesPerPrimitive, - static_cast(params.indices), - params.dstBuffer, params.dstOffset, indicesGenerated); - default: - UNREACHABLE(); - return angle::Result::Stop; - } -} - -angle::Result IndexGeneratorUtils::generatePrimitiveRestartTrianglesBuffer( - ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - return generatePrimitiveRestartBuffer(contextMtl, 3, params, indicesGenerated); -} - -angle::Result IndexGeneratorUtils::generatePrimitiveRestartLinesBuffer( - ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - return generatePrimitiveRestartBuffer(contextMtl, 2, params, indicesGenerated); -} - -angle::Result IndexGeneratorUtils::generatePrimitiveRestartPointsBuffer( - ContextMtl *contextMtl, - const IndexGenerationParams ¶ms, - size_t *indicesGenerated) -{ - return generatePrimitiveRestartBuffer(contextMtl, 1, params, indicesGenerated); -} - angle::Result VisibilityResultUtils::getVisibilityResultCombinePipeline( ContextMtl *contextMtl, bool keepOldValue, angle::ObjCPtr> *outComputePipeline) { // There is no guarantee Objective-C's BOOL is equal to bool, so casting just in case. - BOOL keepOldValueVal = keepOldValue; + BOOL keepOldValueVal = keepOldValue; angle::ObjCPtr> &shader = mVisibilityResultCombineComputeShaders[keepOldValueVal]; if (!shader) @@ -2257,8 +2161,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, type:MTLDataTypeBool withName:VISIBILITY_RESULT_KEEP_OLD_VAL_CONSTANT_NAME]; - ANGLE_TRY(EnsureSpecializedComputeShaderInitialized( - contextMtl, @"combineVisibilityResult", funcConstants, &shader)); + ANGLE_TRY(EnsureSpecializedShaderInitialized(contextMtl, @"combineVisibilityResult", + funcConstants, &shader)); } } @@ -2310,8 +2214,7 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outComputePipeline) { - ANGLE_TRY( - EnsureComputeShaderInitialized(contextMtl, @"generate3DMipmaps", &m3DMipGeneratorShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"generate3DMipmaps", &m3DMipGeneratorShader)); return contextMtl->getPipelineCache().getComputePipeline(contextMtl, m3DMipGeneratorShader, outComputePipeline); } @@ -2320,8 +2223,7 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outComputePipeline) { - ANGLE_TRY( - EnsureComputeShaderInitialized(contextMtl, @"generate2DMipmaps", &m2DMipGeneratorShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"generate2DMipmaps", &m2DMipGeneratorShader)); return contextMtl->getPipelineCache().getComputePipeline(contextMtl, m2DMipGeneratorShader, outComputePipeline); } @@ -2330,8 +2232,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outComputePipeline) { - ANGLE_TRY(EnsureComputeShaderInitialized(contextMtl, @"generate2DArrayMipmaps", - &m2DArrayMipGeneratorShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"generate2DArrayMipmaps", + &m2DArrayMipGeneratorShader)); return contextMtl->getPipelineCache().getComputePipeline(contextMtl, m2DArrayMipGeneratorShader, outComputePipeline); } @@ -2340,8 +2242,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outComputePipeline) { - ANGLE_TRY(EnsureComputeShaderInitialized(contextMtl, @"generateCubeMipmaps", - &mCubeMipGeneratorShader)); + ANGLE_TRY( + EnsureShaderInitialized(contextMtl, @"generateCubeMipmaps", &mCubeMipGeneratorShader)); return contextMtl->getPipelineCache().getComputePipeline(contextMtl, mCubeMipGeneratorShader, outComputePipeline); } @@ -2472,22 +2374,20 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, : mReadShaderName(readShaderName), mWriteShaderName(writeShaderName) {} -angle::Result CopyPixelsUtils::getPixelsCopyPipeline( +angle::Result CopyPixelsUtils::getT2BComputePipeline( ContextMtl *contextMtl, const angle::Format &angleFormat, const TextureRef &texture, - bool bufferWrite, angle::ObjCPtr> *outComputePipeline) { int formatIDValue = static_cast(angleFormat.id); int shaderTextureType = GetShaderTextureType(texture); - int index2 = mtl_shader::kTextureTypeCount * (bufferWrite ? 1 : 0) + shaderTextureType; - auto &shader = mPixelsCopyComputeShaders[formatIDValue][index2]; + auto &shader = mT2BComputeShaders[formatIDValue][shaderTextureType]; if (!shader) { - // Pipeline not cached, create it now: + // Shader not cached, create it now: ANGLE_MTL_OBJC_SCOPE { angle::ObjCPtr funcConstants = @@ -2500,18 +2400,10 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, type:MTLDataTypeInt withName:PIXEL_COPY_TEXTURE_TYPE_CONSTANT_NAME]; - NSString *shaderName = nil; - if (bufferWrite) - { - shaderName = [NSString stringWithUTF8String:mWriteShaderName.c_str()]; - } - else - { - shaderName = [NSString stringWithUTF8String:mReadShaderName.c_str()]; - } + NSString *shaderName = [NSString stringWithUTF8String:mWriteShaderName.c_str()]; - ANGLE_TRY(EnsureSpecializedComputeShaderInitialized(contextMtl, shaderName, - funcConstants, &shader)); + ANGLE_TRY( + EnsureSpecializedShaderInitialized(contextMtl, shaderName, funcConstants, &shader)); } } @@ -2519,55 +2411,117 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, outComputePipeline); } -angle::Result CopyPixelsUtils::unpackPixelsFromBufferToTexture( +angle::Result CopyPixelsUtils::getB2TRenderPipeline( ContextMtl *contextMtl, - const angle::Format &srcAngleFormat, - const CopyPixelsFromBufferParams ¶ms) + RenderCommandEncoder *cmdEncoder, + const angle::Format &angleFormat, + angle::ObjCPtr> *outRenderPipeline) { - ComputeCommandEncoder *cmdEncoder = contextMtl->getComputeCommandEncoder(); + + // Vertex shader + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"readFromBufferToTextureVS", &mB2TVertexShader)); + + // Fragment shader: + int formatIDValue = static_cast(angleFormat.id); + auto &fragmentShader = mB2TFragmentShaders[formatIDValue]; + + if (!fragmentShader) + { + // Shader not cached, create it now: + ANGLE_MTL_OBJC_SCOPE + { + angle::ObjCPtr funcConstants = + angle::adoptObjCPtr([[MTLFunctionConstantValues alloc] init]); + + [funcConstants setConstantValue:&formatIDValue + type:MTLDataTypeInt + withName:COPY_FORMAT_TYPE_CONSTANT_NAME]; + + NSString *shaderName = [NSString stringWithUTF8String:mReadShaderName.c_str()]; + + ANGLE_TRY(EnsureSpecializedShaderInitialized(contextMtl, shaderName, funcConstants, + &fragmentShader)); + } + } + + RenderPipelineDesc pipelineDesc; + const RenderPassDesc &renderPassDesc = cmdEncoder->renderPassDesc(); + renderPassDesc.populateRenderPipelineOutputDesc(&pipelineDesc.outputDescriptor); + + pipelineDesc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; + + return contextMtl->getPipelineCache().getRenderPipeline( + contextMtl, mB2TVertexShader, fragmentShader, pipelineDesc, outRenderPipeline); +} + +angle::Result CopyPixelsUtils::unpackPixelsWithDraw(const gl::Context *context, + const angle::Format &srcAngleFormat, + const CopyPixelsFromBufferParams ¶ms) +{ + ContextMtl *contextMtl = mtl::GetImpl(context); + RenderCommandEncoder *cmdEncoder = contextMtl->getTextureRenderCommandEncoder( + params.texture, kZeroNativeMipLevel, params.textureSliceOrDepth); ASSERT(cmdEncoder); - angle::ObjCPtr> pipeline; - ANGLE_TRY(getPixelsCopyPipeline(contextMtl, srcAngleFormat, params.texture, false, &pipeline)); + angle::ObjCPtr> pipeline; + ANGLE_TRY(getB2TRenderPipeline(contextMtl, cmdEncoder, srcAngleFormat, &pipeline)); - cmdEncoder->setComputePipelineState(pipeline); - cmdEncoder->setBuffer(params.buffer, 0, 1); - cmdEncoder->setTextureForWrite(params.texture, 0); + // Setup states + SetupFullscreenQuadDrawCommonStates(cmdEncoder); + cmdEncoder->setRenderPipelineState(pipeline); + cmdEncoder->setFragmentBuffer(params.buffer, 0, 1); + + id dsState = + contextMtl->getDisplay()->getStateCache().getNullDepthStencilState( + contextMtl->getMetalDevice()); + cmdEncoder->setDepthStencilState(dsState); + + // Viewports + MTLViewport viewport; + MTLScissorRect scissorRect; + + const gl::Rectangle rect(params.textureArea.x, params.textureArea.y, params.textureArea.width, + params.textureArea.height); + viewport = GetViewport(rect); + + scissorRect = GetScissorRect(rect); + cmdEncoder->setViewport(viewport); + cmdEncoder->setScissorRect(scissorRect); + + // uniform CopyPixelFromBufferUniforms options; - options.copySize[0] = params.textureArea.width; - options.copySize[1] = params.textureArea.height; - options.copySize[2] = params.textureArea.depth; options.bufferStartOffset = params.bufferStartOffset; options.pixelSize = srcAngleFormat.pixelBytes; options.bufferRowPitch = params.bufferRowPitch; options.bufferDepthPitch = params.bufferDepthPitch; options.textureOffset[0] = params.textureArea.x; options.textureOffset[1] = params.textureArea.y; - options.textureOffset[2] = params.textureArea.z; - cmdEncoder->setData(options, 0); - - NSUInteger w = pipeline.get().threadExecutionWidth; - MTLSize threadsPerThreadgroup = MTLSizeMake(w, 1, 1); + cmdEncoder->setFragmentData(options, 0); - MTLSize threads = - MTLSizeMake(params.textureArea.width, params.textureArea.height, params.textureArea.depth); + angle::Result result; + { + // Need to disable occlusion query, otherwise blitting will affect the occlusion counting + ScopedDisableOcclusionQuery disableOcclusionQuery(contextMtl, cmdEncoder, &result); + // Draw the screen aligned quad + cmdEncoder->draw(MTLPrimitiveTypeTriangleStrip, 0, 4); + } - DispatchCompute(contextMtl, cmdEncoder, - /** allowNonUniform */ true, threads, threadsPerThreadgroup); + // Invalidate current context's state + contextMtl->invalidateState(context); - return angle::Result::Continue; + return result; } -angle::Result CopyPixelsUtils::packPixelsFromTextureToBuffer(ContextMtl *contextMtl, - const angle::Format &dstAngleFormat, - const CopyPixelsToBufferParams ¶ms) +angle::Result CopyPixelsUtils::packPixelsCS(ContextMtl *contextMtl, + const angle::Format &dstAngleFormat, + const CopyPixelsToBufferParams ¶ms) { ComputeCommandEncoder *cmdEncoder = contextMtl->getComputeCommandEncoder(); ASSERT(cmdEncoder); angle::ObjCPtr> pipeline; - ANGLE_TRY(getPixelsCopyPipeline(contextMtl, dstAngleFormat, params.texture, true, &pipeline)); + ANGLE_TRY(getT2BComputePipeline(contextMtl, dstAngleFormat, params.texture, &pipeline)); cmdEncoder->setComputePipelineState(pipeline); cmdEncoder->setTexture(params.texture, 0); @@ -2582,7 +2536,7 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, options.textureOffset[0] = params.textureArea.x; options.textureOffset[1] = params.textureArea.y; options.textureLevel = params.textureLevel.get(); - options.textureLayer = params.textureSliceOrDeph; + options.textureLayer = params.textureSliceOrDepth; options.reverseTextureRowOrder = params.reverseTextureRowOrder; cmdEncoder->setData(options, 0); @@ -2763,8 +2717,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outPipelineState) { - ANGLE_TRY(EnsureComputeShaderInitialized(contextMtl, @"expandVertexFormatComponentsCS", - &mComponentsExpandComputeShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"expandVertexFormatComponentsCS", + &mComponentsExpandComputeShader)); return contextMtl->getPipelineCache().getComputePipeline( contextMtl, mComponentsExpandComputeShader, outPipelineState); } @@ -2778,7 +2732,7 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, { if (!mComponentsExpandVertexShader) { - id shaderLib = contextMtl->getDisplay()->getDefaultShadersLib(); + id shaderLib = contextMtl->getDisplay()->getDefaultShadersLib(); mComponentsExpandVertexShader = angle::adoptObjCPtr( [shaderLib newFunctionWithName:@"expandVertexFormatComponentsVS"]); ANGLE_CHECK(contextMtl, mComponentsExpandVertexShader, gl::err::kInternalError, @@ -2814,7 +2768,7 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, type:MTLDataTypeInt withName:COPY_FORMAT_TYPE_CONSTANT_NAME]; - ANGLE_TRY(EnsureSpecializedComputeShaderInitialized( + ANGLE_TRY(EnsureSpecializedShaderInitialized( contextMtl, @"convertToFloatVertexFormatCS", funcConstants, &shader)); } } @@ -2893,8 +2847,8 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outPipelineState) { - ANGLE_TRY(EnsureComputeShaderInitialized(contextMtl, @"linearizeBlocks", - &mLinearizeBlocksComputeShader)); + ANGLE_TRY( + EnsureShaderInitialized(contextMtl, @"linearizeBlocks", &mLinearizeBlocksComputeShader)); return contextMtl->getPipelineCache().getComputePipeline( contextMtl, mLinearizeBlocksComputeShader, outPipelineState); } @@ -2931,8 +2885,7 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder, ContextMtl *contextMtl, angle::ObjCPtr> *outPipelineState) { - ANGLE_TRY( - EnsureComputeShaderInitialized(contextMtl, @"saturateDepth", &mSaturateDepthComputeShader)); + ANGLE_TRY(EnsureShaderInitialized(contextMtl, @"saturateDepth", &mSaturateDepthComputeShader)); return contextMtl->getPipelineCache().getComputePipeline( contextMtl, mSaturateDepthComputeShader, outPipelineState); } diff --git a/src/libANGLE/renderer/metal/mtl_resources.h b/src/libANGLE/renderer/metal/mtl_resources.h index 1632afc5c09..f622b484570 100644 --- a/src/libANGLE/renderer/metal/mtl_resources.h +++ b/src/libANGLE/renderer/metal/mtl_resources.h @@ -430,7 +430,7 @@ class Buffer final : public Resource, public WrappedObject> const uint8_t *data); const uint8_t *mapReadOnly(ContextMtl *context); - uint8_t *map(ContextMtl *context); + uint8_t *map(ContextMtl *context, size_t offset = 0); uint8_t *mapWithOpt(ContextMtl *context, bool readonly, bool noSync); void unmap(ContextMtl *context); diff --git a/src/libANGLE/renderer/metal/mtl_resources.mm b/src/libANGLE/renderer/metal/mtl_resources.mm index 2cf7d6c6ab7..2fa27bd06fc 100644 --- a/src/libANGLE/renderer/metal/mtl_resources.mm +++ b/src/libANGLE/renderer/metal/mtl_resources.mm @@ -7,6 +7,10 @@ // Implements wrapper classes for Metal's MTLTexture and MTLBuffer. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_resources.h" #include @@ -1147,9 +1151,11 @@ bool needMultisampleColorFormatShaderReadWorkaround(ContextMtl *context, MTLText return mapWithOpt(context, true, false); } -uint8_t *Buffer::map(ContextMtl *context) +uint8_t *Buffer::map(ContextMtl *context, size_t offset) { - return mapWithOpt(context, false, false); + ASSERT(offset < size()); + uint8_t *result = mapWithOpt(context, false, false); + return result != nullptr ? result + offset : nullptr; } uint8_t *Buffer::mapWithOpt(ContextMtl *context, bool readonly, bool noSync) diff --git a/src/libANGLE/renderer/metal/mtl_state_cache.h b/src/libANGLE/renderer/metal/mtl_state_cache.h index c196037667e..6e718e4c4c6 100644 --- a/src/libANGLE/renderer/metal/mtl_state_cache.h +++ b/src/libANGLE/renderer/metal/mtl_state_cache.h @@ -11,6 +11,10 @@ #ifndef LIBANGLE_RENDERER_METAL_MTL_STATE_CACHE_H_ #define LIBANGLE_RENDERER_METAL_MTL_STATE_CACHE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #import #include @@ -34,23 +38,25 @@ class ContextMtl; namespace mtl { -struct alignas(1) StencilDesc + +ANGLE_ENABLE_STRUCT_PADDING_WARNINGS +struct alignas(4) StencilDesc { bool operator==(const StencilDesc &rhs) const; // Set default values void reset(); - // Use uint8_t instead of MTLStencilOperation to compact space - uint8_t stencilFailureOperation : 3; - uint8_t depthFailureOperation : 3; - uint8_t depthStencilPassOperation : 3; + // Use bitfield instead of MTLStencilOperation to compact space + uint16_t stencilFailureOperation : 4; + uint16_t depthFailureOperation : 4; + uint16_t depthStencilPassOperation : 4; - // Use uint8_t instead of MTLCompareFunction to compact space - uint8_t stencilCompareFunction : 3; + // Use bitfield instead of MTLCompareFunction to compact space + uint16_t stencilCompareFunction : 4; - uint8_t readMask : 8; - uint8_t writeMask : 8; + uint16_t readMask : 8; + uint16_t writeMask : 8; }; struct alignas(4) DepthStencilDesc @@ -83,9 +89,9 @@ struct alignas(4) DepthStencilDesc StencilDesc backFaceStencil; StencilDesc frontFaceStencil; - // Use uint8_t instead of MTLCompareFunction to compact space - uint8_t depthCompareFunction : 3; - bool depthWriteEnabled : 1; + // Use bitfield instead of MTLCompareFunction to compact space + uint16_t depthCompareFunction; + uint16_t depthWriteEnabled; }; struct alignas(4) SamplerDesc @@ -105,20 +111,20 @@ struct alignas(4) SamplerDesc size_t hash() const; - // Use uint8_t instead of MTLSamplerAddressMode to compact space - uint8_t rAddressMode : 3; - uint8_t sAddressMode : 3; - uint8_t tAddressMode : 3; + // Use bitfield instead of MTLSamplerAddressMode to compact space + uint16_t rAddressMode : 3; + uint16_t sAddressMode : 3; + uint16_t tAddressMode : 3; - // Use uint8_t instead of MTLSamplerMinMagFilter to compact space - uint8_t minFilter : 1; - uint8_t magFilter : 1; - uint8_t mipFilter : 2; + uint16_t maxAnisotropy : 5; - uint8_t maxAnisotropy : 5; + // Use bitfield instead of MTLSamplerMinMagFilter to compact space + uint16_t minFilter : 1; + uint16_t magFilter : 1; + uint16_t mipFilter : 2; - // Use uint8_t instead of MTLCompareFunction to compact space - uint8_t compareFunction : 3; + // Use bitfield instead of MTLCompareFunction to compact space + uint16_t compareFunction : 14; }; struct VertexAttributeDesc @@ -129,11 +135,11 @@ struct VertexAttributeDesc } inline bool operator!=(const VertexAttributeDesc &rhs) const { return !(*this == rhs); } - // Use uint8_t instead of MTLVertexFormat to compact space - uint8_t format : 6; + // Use uint16_t instead of MTLVertexFormat to compact space + uint16_t format; // Offset is only used for default attributes buffer. So 8 bits are enough. - uint8_t offset : 8; - uint8_t bufferIndex : 5; + uint16_t offset : 8; + uint16_t bufferIndex : 8; }; struct VertexBufferLayoutDesc @@ -147,8 +153,7 @@ struct VertexBufferLayoutDesc uint32_t stepRate; uint32_t stride; - // Use uint8_t instead of MTLVertexStepFunction to compact space - uint8_t stepFunction; + uint32_t stepFunction; }; struct VertexDesc @@ -156,11 +161,11 @@ struct VertexDesc VertexAttributeDesc attributes[kMaxVertexAttribs]; VertexBufferLayoutDesc layouts[kMaxVertexAttribs]; - uint8_t numAttribs; - uint8_t numBufferLayouts; + uint16_t numAttribs; + uint16_t numBufferLayouts; }; -struct BlendDesc +struct alignas(2) BlendDesc { bool operator==(const BlendDesc &rhs) const; BlendDesc &operator=(const BlendDesc &src) = default; @@ -171,20 +176,20 @@ struct BlendDesc void updateWriteMask(const uint8_t angleMask); - // Use uint8_t instead of MTLColorWriteMask to compact space - uint8_t writeMask : 4; + // Use bitfield instead of MTLColorWriteMask to compact space + uint16_t writeMask : 4; - // Use uint8_t instead of MTLBlendOperation to compact space - uint8_t alphaBlendOperation : 3; - uint8_t rgbBlendOperation : 3; + uint16_t blendingEnabled : 1; - // Use uint8_t instead of MTLBlendFactor to compact space - uint8_t destinationAlphaBlendFactor : 5; - uint8_t destinationRGBBlendFactor : 5; - uint8_t sourceAlphaBlendFactor : 5; - uint8_t sourceRGBBlendFactor : 5; + // Use bitfield instead of MTLBlendOperation to compact space + uint16_t alphaBlendOperation : 3; + uint16_t rgbBlendOperation : 3; - bool blendingEnabled : 1; + // Use bitfield instead of MTLBlendFactor to compact space + uint16_t destinationAlphaBlendFactor : 5; + uint16_t destinationRGBBlendFactor : 5; + uint16_t sourceAlphaBlendFactor : 5; + uint16_t sourceRGBBlendFactor : 6; }; using BlendDescArray = std::array; @@ -205,23 +210,21 @@ struct alignas(2) RenderPipelineColorAttachmentDesc : public BlendDesc void reset(MTLPixelFormat format, const BlendDesc &blendDesc); // Use uint16_t instead of MTLPixelFormat to compact space - uint16_t pixelFormat : 16; + uint16_t pixelFormat; }; -struct RenderPipelineOutputDesc +struct alignas(2) RenderPipelineOutputDesc { - bool operator==(const RenderPipelineOutputDesc &rhs) const; - void updateEnabledDrawBuffers(gl::DrawBufferMask enabledBuffers); std::array colorAttachments; // Use uint16_t instead of MTLPixelFormat to compact space - uint16_t depthAttachmentPixelFormat : 16; - uint16_t stencilAttachmentPixelFormat : 16; + uint16_t depthAttachmentPixelFormat; + uint16_t stencilAttachmentPixelFormat; - uint8_t numColorAttachments; - uint8_t rasterSampleCount; + uint16_t numColorAttachments : 8; + uint16_t rasterSampleCount : 8; }; enum class RenderPipelineRasterization : uint32_t @@ -266,34 +269,19 @@ struct alignas(4) RenderPipelineDesc RenderPipelineOutputDesc outputDescriptor; - // Use uint8_t instead of MTLPrimitiveTopologyClass to compact space. - uint8_t inputPrimitiveTopology : 2; + // Use bitfield instead of MTLPrimitiveTopologyClass to compact space. + uint16_t inputPrimitiveTopology : 8; - bool alphaToCoverageEnabled : 1; + uint16_t alphaToCoverageEnabled : 8; // These flags are for emulation and do not correspond to any flags in // MTLRenderPipelineDescriptor descriptor. These flags should be used by // RenderPipelineCacheSpecializeShaderFactory. - RenderPipelineRasterization rasterizationType : 2; + RenderPipelineRasterization rasterizationType; }; -struct alignas(4) ProvokingVertexComputePipelineDesc -{ - ProvokingVertexComputePipelineDesc(); - ProvokingVertexComputePipelineDesc(const ProvokingVertexComputePipelineDesc &src); - ProvokingVertexComputePipelineDesc(ProvokingVertexComputePipelineDesc &&src); - ProvokingVertexComputePipelineDesc &operator=(const ProvokingVertexComputePipelineDesc &src); - - bool operator==(const ProvokingVertexComputePipelineDesc &rhs) const; - bool operator!=(const ProvokingVertexComputePipelineDesc &rhs) const; - size_t hash() const; - - gl::PrimitiveMode primitiveMode; - uint8_t elementType; - bool primitiveRestartEnabled; - bool generateIndices; -}; +ANGLE_DISABLE_STRUCT_PADDING_WARNINGS struct RenderPassAttachmentDesc { @@ -424,14 +412,6 @@ struct hash size_t operator()(const rx::mtl::RenderPipelineDesc &key) const { return key.hash(); } }; -template <> -struct hash -{ - size_t operator()(const rx::mtl::ProvokingVertexComputePipelineDesc &key) const - { - return key.hash(); - } -}; } // namespace std namespace rx diff --git a/src/libANGLE/renderer/metal/mtl_state_cache.mm b/src/libANGLE/renderer/metal/mtl_state_cache.mm index 7acb9c322a0..b26ddc850b2 100644 --- a/src/libANGLE/renderer/metal/mtl_state_cache.mm +++ b/src/libANGLE/renderer/metal/mtl_state_cache.mm @@ -8,12 +8,17 @@ // C struct versions of Metal sampler, depth stencil, render pass, render pipeline descriptors. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_state_cache.h" #include #include "common/debug.h" #include "common/hash_utils.h" +#include "common/span.h" #include "libANGLE/renderer/metal/ContextMtl.h" #include "libANGLE/renderer/metal/mtl_resources.h" #include "libANGLE/renderer/metal/mtl_utils.h" @@ -398,7 +403,7 @@ MTLColorWriteMask AdjustColorWriteMaskForSharedExponent(MTLColorWriteMask mask) size_t DepthStencilDesc::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } // SamplerDesc implementation @@ -466,7 +471,7 @@ MTLColorWriteMask AdjustColorWriteMaskForSharedExponent(MTLColorWriteMask mask) size_t SamplerDesc::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } // BlendDesc implementation @@ -576,25 +581,6 @@ MTLColorWriteMask AdjustColorWriteMaskForSharedExponent(MTLColorWriteMask mask) } // RenderPipelineOutputDesc implementation -bool RenderPipelineOutputDesc::operator==(const RenderPipelineOutputDesc &rhs) const -{ - if (numColorAttachments != rhs.numColorAttachments) - { - return false; - } - - for (uint8_t i = 0; i < numColorAttachments; ++i) - { - if (colorAttachments[i] != rhs.colorAttachments[i]) - { - return false; - } - } - - return ANGLE_PROP_EQ(*this, rhs, depthAttachmentPixelFormat) && - ANGLE_PROP_EQ(*this, rhs, stencilAttachmentPixelFormat); -} - void RenderPipelineOutputDesc::updateEnabledDrawBuffers(gl::DrawBufferMask enabledBuffers) { for (uint32_t colorIndex = 0; colorIndex < this->numColorAttachments; ++colorIndex) @@ -640,7 +626,7 @@ MTLColorWriteMask AdjustColorWriteMaskForSharedExponent(MTLColorWriteMask mask) size_t RenderPipelineDesc::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } bool RenderPipelineDesc::rasterizationEnabled() const @@ -823,6 +809,11 @@ MTLColorWriteMask AdjustColorWriteMaskForSharedExponent(MTLColorWriteMask mask) return false; } + if (rasterSampleCount != other.rasterSampleCount) + { + return false; + } + return depthAttachment.equalIgnoreLoadStoreOptions(other.depthAttachment) && stencilAttachment.equalIgnoreLoadStoreOptions(other.stencilAttachment); } @@ -884,42 +875,6 @@ MTLColorWriteMask AdjustColorWriteMaskForSharedExponent(MTLColorWriteMask mask) } } -// ProvokingVertexPipelineDesc -ProvokingVertexComputePipelineDesc::ProvokingVertexComputePipelineDesc() -{ - memset(this, 0, sizeof(*this)); -} -ProvokingVertexComputePipelineDesc::ProvokingVertexComputePipelineDesc( - const ProvokingVertexComputePipelineDesc &src) -{ - memcpy(this, &src, sizeof(*this)); -} -ProvokingVertexComputePipelineDesc::ProvokingVertexComputePipelineDesc( - ProvokingVertexComputePipelineDesc &&src) -{ - memcpy(this, &src, sizeof(*this)); -} -ProvokingVertexComputePipelineDesc &ProvokingVertexComputePipelineDesc::operator=( - const ProvokingVertexComputePipelineDesc &src) -{ - memcpy(this, &src, sizeof(*this)); - return *this; -} -bool ProvokingVertexComputePipelineDesc::operator==( - const ProvokingVertexComputePipelineDesc &rhs) const -{ - return memcmp(this, &rhs, sizeof(*this)) == 0; -} -bool ProvokingVertexComputePipelineDesc::operator!=( - const ProvokingVertexComputePipelineDesc &rhs) const -{ - return !(*this == rhs); -} -size_t ProvokingVertexComputePipelineDesc::hash() const -{ - return angle::ComputeGenericHash(*this); -} - // StateCache implementation StateCache::StateCache(const angle::FeaturesMtl &features) : mFeatures(features) {} diff --git a/src/libANGLE/renderer/metal/mtl_utils.h b/src/libANGLE/renderer/metal/mtl_utils.h index a397d4e1179..6c3d729f661 100644 --- a/src/libANGLE/renderer/metal/mtl_utils.h +++ b/src/libANGLE/renderer/metal/mtl_utils.h @@ -191,6 +191,7 @@ NSUInteger ComputeTotalSizeUsedForMTLRenderPipelineDescriptor( const Context *context, const mtl::ContextDevice &device); +gl::Rectangle MTLRegionToGLRect(const MTLRegion &mtlRegion); gl::Box MTLRegionToGLBox(const MTLRegion &mtlRegion); MipmapNativeLevel GetNativeMipLevel(GLuint level, GLuint base); diff --git a/src/libANGLE/renderer/metal/mtl_utils.mm b/src/libANGLE/renderer/metal/mtl_utils.mm index bc867af3faf..9c4ddf726a3 100644 --- a/src/libANGLE/renderer/metal/mtl_utils.mm +++ b/src/libANGLE/renderer/metal/mtl_utils.mm @@ -8,6 +8,10 @@ // to Metal enums and so on. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/mtl_utils.h" #include @@ -856,12 +860,7 @@ static MTLLanguageVersion GetUserSetOrHighestMSLVersion(const MTLLanguageVersion case 3: return MTLLanguageVersion2_3; case 4: - if (@available(macOS 12.0, *)) - { - return MTLLanguageVersion2_4; - } - assert(0 && "MSL 2.4 requires macOS 12."); - break; + return MTLLanguageVersion2_4; default: assert(0 && "Unsupported MSL Minor Language Version."); } @@ -895,9 +894,26 @@ static MTLLanguageVersion GetUserSetOrHighestMSLVersion(const MTLLanguageVersion // Mark all positions in VS with attribute invariant as non-optimizable options.get().preserveInvariance = usesInvariance; - if (disableFastMath) +// mathMode and mathFloatingPointFunctions are only available with macOS 15+ and iPhoneOS 18+ +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 150000 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 180000 || \ + __TV_OS_VERSION_MAX_ALLOWED >= 180000 || TARGET_OS_VISION + if (@available(macOS 15.0, iOS 18.0, *)) { - options.get().fastMathEnabled = false; + if (disableFastMath) + { + options.get().mathMode = MTLMathModeSafe; + options.get().mathFloatingPointFunctions = MTLMathFloatingPointFunctionsPrecise; + } + else + { + options.get().mathMode = MTLMathModeFast; + options.get().mathFloatingPointFunctions = MTLMathFloatingPointFunctionsFast; + } + } + else +#endif + { + options.get().fastMathEnabled = !disableFastMath; } options.get().languageVersion = @@ -1533,6 +1549,13 @@ NSUInteger ComputeTotalSizeUsedForMTLRenderPipelineDescriptor( return currentRenderTargetSize; } +gl::Rectangle MTLRegionToGLRect(const MTLRegion &mtlRegion) +{ + return gl::Rectangle(static_cast(mtlRegion.origin.x), static_cast(mtlRegion.origin.y), + static_cast(mtlRegion.size.width), + static_cast(mtlRegion.size.height)); +} + gl::Box MTLRegionToGLBox(const MTLRegion &mtlRegion) { return gl::Box(static_cast(mtlRegion.origin.x), static_cast(mtlRegion.origin.y), diff --git a/src/libANGLE/renderer/metal/renderermtl_utils.cpp b/src/libANGLE/renderer/metal/renderermtl_utils.cpp index 15ae5247bfb..d6a6ac06257 100644 --- a/src/libANGLE/renderer/metal/renderermtl_utils.cpp +++ b/src/libANGLE/renderer/metal/renderermtl_utils.cpp @@ -7,6 +7,10 @@ // Helper methods pertaining to the Metal back-end. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/metal/renderermtl_utils.h" #include "libANGLE/renderer/renderer_utils.h" diff --git a/src/libANGLE/renderer/metal/shaders/common.h b/src/libANGLE/renderer/metal/shaders/common.h index 6576cdcd4f1..2317fc70ffc 100644 --- a/src/libANGLE/renderer/metal/shaders/common.h +++ b/src/libANGLE/renderer/metal/shaders/common.h @@ -148,7 +148,7 @@ static inline float4 linearToSRGB(float4 color) } template -static inline Short bytesToShort(constant uchar *input, uint offset) +static inline Short bytesToShort(const device uchar *input, uint offset) { Short inputLo = input[offset]; Short inputHi = input[offset + 1]; @@ -157,7 +157,7 @@ static inline Short bytesToShort(constant uchar *input, uint offset) } template -static inline Int bytesToInt(constant uchar *input, uint offset) +static inline Int bytesToInt(const device uchar *input, uint offset) { Int input0 = input[offset]; Int input1 = input[offset + 1]; diff --git a/src/libANGLE/renderer/metal/shaders/copy_buffer.metal b/src/libANGLE/renderer/metal/shaders/copy_buffer.metal index e864f4c53a8..b395335cec4 100644 --- a/src/libANGLE/renderer/metal/shaders/copy_buffer.metal +++ b/src/libANGLE/renderer/metal/shaders/copy_buffer.metal @@ -26,18 +26,17 @@ constant bool kCopyTextureType2DMS = kCopyTextureType == kTextureType2DMultis constant bool kCopyTextureTypeCube = kCopyTextureType == kTextureTypeCube; constant bool kCopyTextureType3D = kCopyTextureType == kTextureType3D; -struct CopyPixelParams +struct B2TParams { - uint3 copySize; - uint3 textureOffset; - uint bufferStartOffset; uint pixelSize; uint bufferRowPitch; uint bufferDepthPitch; + + uint2 textureOffset; }; -struct WritePixelParams +struct T2BParams { uint2 copySize; uint2 textureOffset; @@ -71,18 +70,9 @@ struct WritePixelParams NAME_PREFIX##TextureCube // Params for reading from buffer to texture -#define DEST_TEXTURE_PARAMS(TYPE) TEXTURE_PARAMS(TYPE, access::write, dst) -#define FORWARD_DEST_TEXTURE_PARAMS FORWARD_TEXTURE_PARAMS(dst) - -#define COMMON_READ_KERNEL_PARAMS(TEXTURE_TYPE) \ - ushort3 gIndices [[thread_position_in_grid]], \ - constant CopyPixelParams &options[[buffer(0)]], \ - constant uchar *buffer [[buffer(1)]], \ - DEST_TEXTURE_PARAMS(TEXTURE_TYPE) - #define COMMON_READ_FUNC_PARAMS \ uint bufferOffset, \ - constant uchar *buffer + const device uchar *buffer #define FORWARD_COMMON_READ_FUNC_PARAMS bufferOffset, buffer @@ -97,13 +87,13 @@ struct WritePixelParams #define COMMON_WRITE_KERNEL_PARAMS(TEXTURE_TYPE) \ ushort2 gIndices [[thread_position_in_grid]], \ - constant WritePixelParams &options[[buffer(0)]], \ + constant T2BParams &options[[buffer(0)]], \ SRC_TEXTURE_PARAMS(TEXTURE_TYPE), \ device uchar *buffer [[buffer(1)]] \ #define COMMON_WRITE_FUNC_PARAMS(TYPE) \ ushort2 gIndices, \ - constant WritePixelParams &options,\ + constant T2BParams &options,\ uint bufferOffset, \ vec color, \ device uchar *buffer \ @@ -116,35 +106,10 @@ struct WritePixelParams // clang-format on -// Write to texture code based on texture type: -template -static inline void textureWrite(ushort3 gIndices, - constant CopyPixelParams &options, - vec color, - DEST_TEXTURE_PARAMS(T)) -{ - uint3 writeIndices = options.textureOffset + uint3(gIndices); - switch (kCopyTextureType) - { - case kTextureType2D: - dstTexture2d.write(color, writeIndices.xy); - break; - case kTextureType2DArray: - dstTexture2dArray.write(color, writeIndices.xy, writeIndices.z); - break; - case kTextureType3D: - dstTexture3d.write(color, writeIndices); - break; - case kTextureTypeCube: - dstTextureCube.write(color, writeIndices.xy, writeIndices.z); - break; - } -} - // Read from texture code based on texture type: template static inline vec textureRead(ushort2 gIndices, - constant WritePixelParams &options, + constant T2BParams &options, SRC_TEXTURE_PARAMS(T)) { vec color; @@ -175,21 +140,12 @@ static inline vec textureRead(ushort2 gIndices, return color; } -// Calculate offset into buffer: -#define CALC_BUFFER_READ_OFFSET(pixelSize) \ - options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + \ - gIndices.y * options.bufferRowPitch + gIndices.x * pixelSize) - -#define CALC_BUFFER_WRITE_OFFSET(pixelSize) \ - options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * pixelSize) - // Per format handling code: -#define READ_FORMAT_SWITCH_CASE(format) \ - case FormatID::format: { \ - auto color = read##format(FORWARD_COMMON_READ_FUNC_PARAMS); \ - textureWrite(gIndices, options, color, FORWARD_DEST_TEXTURE_PARAMS); \ - } \ - break; +#define READ_FORMAT_SWITCH_CASE(format) \ + case FormatID::format: \ + { \ + return read##format(FORWARD_COMMON_READ_FUNC_PARAMS); \ + } #define WRITE_FORMAT_SWITCH_CASE(format) \ case FormatID::format: { \ @@ -198,13 +154,6 @@ static inline vec textureRead(ushort2 gIndices, } \ break; -#define READ_KERNEL_GUARD \ - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || \ - gIndices.z >= options.copySize.z) \ - { \ - return; \ - } - #define WRITE_KERNEL_GUARD \ if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) \ { \ @@ -1324,10 +1273,25 @@ ALIAS_READ_INT_FUNCS(32) ALIAS_READ_INT_FUNC(R10G10B10A2) // Copy pixels from buffer to texture -kernel void readFromBufferToFloatTexture(COMMON_READ_KERNEL_PARAMS(float)) +static inline uint getB2TReadOffset(float2 position, constant B2TParams &options) { - READ_KERNEL_GUARD + uint2 iposition = static_cast(position) - options.textureOffset; + return options.bufferStartOffset + + (iposition.y * options.bufferRowPitch + iposition.x * options.pixelSize); +} + +vertex float4 readFromBufferToTextureVS(unsigned int vid [[vertex_id]]) +{ + float4 output; + output.xy = select(float2(-1.0f), float2(1.0f), bool2(vid & uint2(2, 1))); + output.zw = float2(0.0, 1.0); + return output; +} +fragment float4 readFromBufferToFloatTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) +{ #define SUPPORTED_FORMATS(PROC) \ PROC(R5G6B5_UNORM) \ PROC(R8G8B8A8_UNORM) \ @@ -1369,7 +1333,7 @@ kernel void readFromBufferToFloatTexture(COMMON_READ_KERNEL_PARAMS(float)) PROC(R32G32B32_FLOAT) \ PROC(R32G32B32A32_FLOAT) - uint bufferOffset = CALC_BUFFER_READ_OFFSET(options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { @@ -1377,12 +1341,14 @@ kernel void readFromBufferToFloatTexture(COMMON_READ_KERNEL_PARAMS(float)) } #undef SUPPORTED_FORMATS + + return float4(0.0); } -kernel void readFromBufferToIntTexture(COMMON_READ_KERNEL_PARAMS(int)) +fragment int4 readFromBufferToIntTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) { - READ_KERNEL_GUARD - #define SUPPORTED_FORMATS(PROC) \ PROC(R8_SINT) \ PROC(R8G8_SINT) \ @@ -1397,7 +1363,7 @@ kernel void readFromBufferToIntTexture(COMMON_READ_KERNEL_PARAMS(int)) PROC(R32G32B32_SINT) \ PROC(R32G32B32A32_SINT) - uint bufferOffset = CALC_BUFFER_READ_OFFSET(options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { @@ -1405,12 +1371,14 @@ kernel void readFromBufferToIntTexture(COMMON_READ_KERNEL_PARAMS(int)) } #undef SUPPORTED_FORMATS + + return int4(0); } -kernel void readFromBufferToUIntTexture(COMMON_READ_KERNEL_PARAMS(uint)) +fragment uint4 readFromBufferToUIntTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) { - READ_KERNEL_GUARD - #define SUPPORTED_FORMATS(PROC) \ PROC(R8_UINT) \ PROC(R8G8_UINT) \ @@ -1425,7 +1393,7 @@ kernel void readFromBufferToUIntTexture(COMMON_READ_KERNEL_PARAMS(uint)) PROC(R32G32B32_UINT) \ PROC(R32G32B32A32_UINT) - uint bufferOffset = CALC_BUFFER_READ_OFFSET(options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { @@ -1433,10 +1401,18 @@ kernel void readFromBufferToUIntTexture(COMMON_READ_KERNEL_PARAMS(uint)) } #undef SUPPORTED_FORMATS + + return uint4(0); } // Copy pixels from texture to buffer -kernel void writeFromFloatTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(float)) +static inline uint getT2BWriteOffset(ushort2 position, constant T2BParams &options) +{ + return options.bufferStartOffset + + (position.y * options.bufferRowPitch + position.x * options.pixelSize); +} + +kernel void writeFromFloatTextureToBufferCS(COMMON_WRITE_KERNEL_PARAMS(float)) { WRITE_KERNEL_GUARD @@ -1478,7 +1454,7 @@ kernel void writeFromFloatTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(float)) PROC(R32G32_FLOAT) \ PROC(R32G32B32A32_FLOAT) - uint bufferOffset = CALC_BUFFER_WRITE_OFFSET(options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { @@ -1488,7 +1464,7 @@ kernel void writeFromFloatTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(float)) #undef SUPPORTED_FORMATS } -kernel void writeFromIntTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(int)) +kernel void writeFromIntTextureToBufferCS(COMMON_WRITE_KERNEL_PARAMS(int)) { WRITE_KERNEL_GUARD @@ -1503,7 +1479,7 @@ kernel void writeFromIntTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(int)) PROC(R32G32_SINT) \ PROC(R32G32B32A32_SINT) - uint bufferOffset = CALC_BUFFER_WRITE_OFFSET(options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { @@ -1513,7 +1489,7 @@ kernel void writeFromIntTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(int)) #undef SUPPORTED_FORMATS } -kernel void writeFromUIntTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(uint)) +kernel void writeFromUIntTextureToBufferCS(COMMON_WRITE_KERNEL_PARAMS(uint)) { WRITE_KERNEL_GUARD @@ -1528,7 +1504,7 @@ kernel void writeFromUIntTextureToBuffer(COMMON_WRITE_KERNEL_PARAMS(uint)) PROC(R32G32_UINT) \ PROC(R32G32B32A32_UINT) - uint bufferOffset = CALC_BUFFER_WRITE_OFFSET(options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { @@ -1609,7 +1585,7 @@ inline void writeFloatVertex(constant CopyVertexParams &options, // Function to convert from any vertex format to float vertex format static inline void convertToFloatVertexFormat(uint index, constant CopyVertexParams &options, - constant uchar *srcBuffer, + const device uchar *srcBuffer, device uchar *dstBuffer) { #define SUPPORTED_FORMATS(PROC) \ @@ -1644,7 +1620,7 @@ static inline void convertToFloatVertexFormat(uint index, // Kernel to convert from any vertex format to float vertex format kernel void convertToFloatVertexFormatCS(uint index [[thread_position_in_grid]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { ANGLE_KERNEL_GUARD(index, options.vertexCount); @@ -1654,7 +1630,7 @@ kernel void convertToFloatVertexFormatCS(uint index [[thread_position_in_grid]], // Vertex shader to convert from any vertex format to float vertex format vertex void convertToFloatVertexFormatVS(uint index [[vertex_id]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { convertToFloatVertexFormat(index, options, srcBuffer, dstBuffer); @@ -1663,7 +1639,7 @@ vertex void convertToFloatVertexFormatVS(uint index [[vertex_id]], // Function to expand (or just simply copy) the components of the vertex static inline void expandVertexFormatComponents(uint index, constant CopyVertexParams &options, - constant uchar *srcBuffer, + const device uchar *srcBuffer, device uchar *dstBuffer) { uint srcOffset = options.srcBufferStartOffset + options.srcStride * index; @@ -1702,7 +1678,7 @@ static inline void expandVertexFormatComponents(uint index, // Kernel to expand (or just simply copy) the components of the vertex kernel void expandVertexFormatComponentsCS(uint index [[thread_position_in_grid]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { ANGLE_KERNEL_GUARD(index, options.vertexCount); @@ -1713,7 +1689,7 @@ kernel void expandVertexFormatComponentsCS(uint index [[thread_position_in_grid] // Vertex shader to expand (or just simply copy) the components of the vertex vertex void expandVertexFormatComponentsVS(uint index [[vertex_id]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { expandVertexFormatComponents(index, options, srcBuffer, dstBuffer); @@ -1722,7 +1698,7 @@ vertex void expandVertexFormatComponentsVS(uint index [[vertex_id]], // Kernel to linearize PVRTC1 texture blocks kernel void linearizeBlocks(ushort2 position [[thread_position_in_grid]], constant uint2 *dimensions [[buffer(0)]], - constant uint2 *srcBuffer [[buffer(1)]], + const device uint2 *srcBuffer [[buffer(1)]], device uint2 *dstBuffer [[buffer(2)]]) { if (any(uint2(position) >= *dimensions)) @@ -1740,7 +1716,7 @@ kernel void linearizeBlocks(ushort2 position [[thread_position_in_grid]], // Kernel to saturate floating-point depth data kernel void saturateDepth(uint2 position [[thread_position_in_grid]], constant uint3 *dimensions [[buffer(0)]], - device float *srcBuffer [[buffer(1)]], + const device float *srcBuffer [[buffer(1)]], device float *dstBuffer [[buffer(2)]]) { if (any(position >= (*dimensions).xy)) diff --git a/src/libANGLE/renderer/metal/shaders/gen_indices.metal b/src/libANGLE/renderer/metal/shaders/gen_indices.metal index ecea885af32..60c807c4565 100644 --- a/src/libANGLE/renderer/metal/shaders/gen_indices.metal +++ b/src/libANGLE/renderer/metal/shaders/gen_indices.metal @@ -27,26 +27,26 @@ struct IndexConversionParams #define ANGLE_IDX_CONVERSION_GUARD(IDX, OPTS) ANGLE_KERNEL_GUARD(IDX, OPTS.indexCount) -inline ushort getIndexAligned(constant ushort *inputAligned, uint offset, uint idx) +inline ushort getIndexAligned(const device ushort *inputAligned, uint offset, uint idx) { return inputAligned[offset / 2 + idx]; } -inline uint getIndexAligned(constant uint *inputAligned, uint offset, uint idx) +inline uint getIndexAligned(const device uint *inputAligned, uint offset, uint idx) { return inputAligned[offset / 4 + idx]; } -inline uchar getIndexAligned(constant uchar *input, uint offset, uint idx) +inline uchar getIndexAligned(const device uchar *input, uint offset, uint idx) { return input[offset + idx]; } -inline ushort getIndexUnalignedU16(constant uchar *input, uint offset, uint idx) +inline ushort getIndexUnalignedU16(const device uchar *input, uint offset, uint idx) { ushort inputLo = input[offset + 2 * idx]; ushort inputHi = input[offset + 2 * idx + 1]; // Little endian conversion: return inputLo | (inputHi << 8); } -inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx) +inline uint getIndexUnalignedU32(const device uchar *input, uint offset, uint idx) { uint input0 = input[offset + 4 * idx]; uint input1 = input[offset + 4 * idx + 1]; @@ -58,7 +58,7 @@ inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx) kernel void convertIndexU8ToU16(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input [[buffer(1)]], + const device uchar *input [[buffer(1)]], device ushort *output [[buffer(2)]]) { ANGLE_IDX_CONVERSION_GUARD(idx, options); @@ -77,9 +77,9 @@ kernel void convertIndexU8ToU16(uint idx [[thread_position_in_grid]], kernel void convertIndexU16(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input + const device uchar *input [[buffer(1), function_constant(kSourceBufferUnaligned)]], - constant ushort *inputAligned + const device ushort *inputAligned [[buffer(1), function_constant(kSourceBufferAligned)]], device ushort *output [[buffer(2)]]) { @@ -99,9 +99,9 @@ kernel void convertIndexU16(uint idx [[thread_position_in_grid]], kernel void convertIndexU32(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input + const device uchar *input [[buffer(1), function_constant(kSourceBufferUnaligned)]], - constant uint *inputAligned + const device uint *inputAligned [[buffer(1), function_constant(kSourceBufferAligned)]], device uint *output [[buffer(2)]]) { @@ -144,9 +144,9 @@ kernel void genTriFanIndicesFromArray(uint idx [[thread_position_in_grid]], inline uint getIndexU32(uint offset, uint idx, - constant uchar *inputU8 [[function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 [[function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 [[function_constant(kUseSourceBufferU32)]]) + const device uchar *inputU8 [[function_constant(kUseSourceBufferU8)]], + const device ushort *inputU16 [[function_constant(kUseSourceBufferU16)]], + const device uint *inputU32 [[function_constant(kUseSourceBufferU32)]]) { if (kUseSourceBufferU8) { @@ -176,11 +176,11 @@ inline uint getIndexU32(uint offset, // of indices starting from the 3rd. kernel void genTriFanIndicesFromElements(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *inputU8 + const device uchar *inputU8 [[buffer(1), function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 + const device ushort *inputU16 [[buffer(1), function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 + const device uint *inputU32 [[buffer(1), function_constant(kUseSourceBufferU32)]], device uint *output [[buffer(2)]]) { @@ -208,11 +208,11 @@ kernel void genLineLoopIndicesFromArray(uint idx [[thread_position_in_grid]], // Generate line loop indices for glDrawElements() kernel void genLineLoopIndicesFromElements(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *inputU8 + const device uchar *inputU8 [[buffer(1), function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 + const device ushort *inputU16 [[buffer(1), function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 + const device uint *inputU32 [[buffer(1), function_constant(kUseSourceBufferU32)]], device uint *output [[buffer(2)]]) { diff --git a/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_autogen.metal b/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_autogen.metal index 40dfb7aa5ef..d0002936043 100644 --- a/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_autogen.metal +++ b/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_autogen.metal @@ -121,14 +121,14 @@ static inline float4 linearToSRGB(float4 color) return float4(linearToSRGB(color.r), linearToSRGB(color.g), linearToSRGB(color.b), color.a); } template -static inline Short bytesToShort(constant uchar *input, uint offset) +static inline Short bytesToShort(const device uchar *input, uint offset) { Short inputLo = input[offset]; Short inputHi = input[offset + 1]; return inputLo | (inputHi << 8); } template -static inline Int bytesToInt(constant uchar *input, uint offset) +static inline Int bytesToInt(const device uchar *input, uint offset) { Int input0 = input[offset]; Int input1 = input[offset + 1]; @@ -576,25 +576,25 @@ struct IndexConversionParams uint32_t indexCount; bool primitiveRestartEnabled; }; -inline ushort getIndexAligned(constant ushort *inputAligned, uint offset, uint idx) +inline ushort getIndexAligned(const device ushort *inputAligned, uint offset, uint idx) { return inputAligned[offset / 2 + idx]; } -inline uint getIndexAligned(constant uint *inputAligned, uint offset, uint idx) +inline uint getIndexAligned(const device uint *inputAligned, uint offset, uint idx) { return inputAligned[offset / 4 + idx]; } -inline uchar getIndexAligned(constant uchar *input, uint offset, uint idx) +inline uchar getIndexAligned(const device uchar *input, uint offset, uint idx) { return input[offset + idx]; } -inline ushort getIndexUnalignedU16(constant uchar *input, uint offset, uint idx) +inline ushort getIndexUnalignedU16(const device uchar *input, uint offset, uint idx) { ushort inputLo = input[offset + 2 * idx]; ushort inputHi = input[offset + 2 * idx + 1]; return inputLo | (inputHi << 8); } -inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx) +inline uint getIndexUnalignedU32(const device uchar *input, uint offset, uint idx) { uint input0 = input[offset + 4 * idx]; uint input1 = input[offset + 4 * idx + 1]; @@ -604,7 +604,7 @@ inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx) } kernel void convertIndexU8ToU16(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input [[buffer(1)]], + const device uchar *input [[buffer(1)]], device ushort *output [[buffer(2)]]) { if (idx >= options.indexCount) { return; }; @@ -620,9 +620,9 @@ kernel void convertIndexU8ToU16(uint idx [[thread_position_in_grid]], } kernel void convertIndexU16(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input + const device uchar *input [[buffer(1), function_constant(kSourceBufferUnaligned)]], - constant ushort *inputAligned + const device ushort *inputAligned [[buffer(1), function_constant(kSourceBufferAligned)]], device ushort *output [[buffer(2)]]) { @@ -640,9 +640,9 @@ kernel void convertIndexU16(uint idx [[thread_position_in_grid]], } kernel void convertIndexU32(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input + const device uchar *input [[buffer(1), function_constant(kSourceBufferUnaligned)]], - constant uint *inputAligned + const device uint *inputAligned [[buffer(1), function_constant(kSourceBufferAligned)]], device uint *output [[buffer(2)]]) { @@ -675,9 +675,9 @@ kernel void genTriFanIndicesFromArray(uint idx [[thread_position_in_grid]], } inline uint getIndexU32(uint offset, uint idx, - constant uchar *inputU8 [[function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 [[function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 [[function_constant(kUseSourceBufferU32)]]) + const device uchar *inputU8 [[function_constant(kUseSourceBufferU8)]], + const device ushort *inputU16 [[function_constant(kUseSourceBufferU16)]], + const device uint *inputU32 [[function_constant(kUseSourceBufferU32)]]) { if (kUseSourceBufferU8) { @@ -703,11 +703,11 @@ inline uint getIndexU32(uint offset, } kernel void genTriFanIndicesFromElements(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *inputU8 + const device uchar *inputU8 [[buffer(1), function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 + const device ushort *inputU16 [[buffer(1), function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 + const device uint *inputU32 [[buffer(1), function_constant(kUseSourceBufferU32)]], device uint *output [[buffer(2)]]) { @@ -727,11 +727,11 @@ kernel void genLineLoopIndicesFromArray(uint idx [[thread_position_in_grid]], } kernel void genLineLoopIndicesFromElements(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *inputU8 + const device uchar *inputU8 [[buffer(1), function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 + const device ushort *inputU16 [[buffer(1), function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 + const device uint *inputU32 [[buffer(1), function_constant(kUseSourceBufferU32)]], device uint *output [[buffer(2)]]) { @@ -1173,6 +1173,7 @@ enum ETC2_R8G8B8A8_UNORM_BLOCK, ETC2_R8G8B8_SRGB_BLOCK, ETC2_R8G8B8_UNORM_BLOCK, + G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, G8_B8R8_2PLANE_420_UNORM, G8_B8_R8_3PLANE_420_UNORM, L16A16_FLOAT, @@ -1207,6 +1208,7 @@ enum R10G10B10A2_UNORM, R10G10B10A2_USCALED, R10G10B10X2_UNORM, + R10X6G10X6B10X6A10X6_UNORM, R11G11B10_FLOAT, R16G16B16A16_FLOAT, R16G16B16A16_SINT, @@ -1331,16 +1333,15 @@ constant bool kCopyTextureType2DArray = kCopyTextureType == kTextureType2DArray; constant bool kCopyTextureType2DMS = kCopyTextureType == kTextureType2DMultisample; constant bool kCopyTextureTypeCube = kCopyTextureType == kTextureTypeCube; constant bool kCopyTextureType3D = kCopyTextureType == kTextureType3D; -struct CopyPixelParams +struct B2TParams { - uint3 copySize; - uint3 textureOffset; uint bufferStartOffset; uint pixelSize; uint bufferRowPitch; uint bufferDepthPitch; + uint2 textureOffset; }; -struct WritePixelParams +struct T2BParams { uint2 copySize; uint2 textureOffset; @@ -1352,31 +1353,8 @@ struct WritePixelParams bool reverseTextureRowOrder; }; template -static inline void textureWrite(ushort3 gIndices, - constant CopyPixelParams &options, - vec color, - texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) -{ - uint3 writeIndices = options.textureOffset + uint3(gIndices); - switch (kCopyTextureType) - { - case kTextureType2D: - dstTexture2d.write(color, writeIndices.xy); - break; - case kTextureType2DArray: - dstTexture2dArray.write(color, writeIndices.xy, writeIndices.z); - break; - case kTextureType3D: - dstTexture3d.write(color, writeIndices); - break; - case kTextureTypeCube: - dstTextureCube.write(color, writeIndices.xy, writeIndices.z); - break; - } -} -template static inline vec textureRead(ushort2 gIndices, - constant WritePixelParams &options, + constant T2BParams &options, texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]]) { vec color; @@ -1406,7 +1384,7 @@ static inline vec textureRead(ushort2 gIndices, } return color; } -static inline float4 readR5G6B5_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR5G6B5_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; ushort src = bytesToShort(buffer, bufferOffset); @@ -1416,14 +1394,14 @@ static inline float4 readR5G6B5_UNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR5G6B5_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR5G6B5_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { ushort dst = shiftData<5, 11>(floatToNormalized<5, ushort>(color.r)) | shiftData<6, 5>(floatToNormalized<6, ushort>(color.g)) | shiftData<5, 0>(floatToNormalized<5, ushort>(color.b)); shortToBytes(dst, bufferOffset, buffer); } -static inline float4 readR4G4B4A4_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR4G4B4A4_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; ushort src = bytesToShort(buffer, bufferOffset); @@ -1433,7 +1411,7 @@ static inline float4 readR4G4B4A4_UNORM(uint bufferOffset, constant uchar *buffe color.a = normalizedToFloat<4>(getShiftedData<4, 0>(src)); return color; } -static inline void writeR4G4B4A4_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR4G4B4A4_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { ushort dst = shiftData<4, 12>(floatToNormalized<4, ushort>(color.r)) | shiftData<4, 8>(floatToNormalized<4, ushort>(color.g)) | @@ -1442,7 +1420,7 @@ static inline void writeR4G4B4A4_UNORM(ushort2 gIndices, constant WritePixelPara ; shortToBytes(dst, bufferOffset, buffer); } -static inline float4 readR5G5B5A1_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR5G5B5A1_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; ushort src = bytesToShort(buffer, bufferOffset); @@ -1452,7 +1430,7 @@ static inline float4 readR5G5B5A1_UNORM(uint bufferOffset, constant uchar *buffe color.a = normalizedToFloat<1>(getShiftedData<1, 0>(src)); return color; } -static inline void writeR5G5B5A1_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR5G5B5A1_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { ushort dst = shiftData<5, 11>(floatToNormalized<5, ushort>(color.r)) | shiftData<5, 6>(floatToNormalized<5, ushort>(color.g)) | @@ -1461,7 +1439,7 @@ static inline void writeR5G5B5A1_UNORM(ushort2 gIndices, constant WritePixelPara ; shortToBytes(dst, bufferOffset, buffer); } -static inline int4 readR10G10B10A2_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR10G10B10A2_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; int src = bytesToInt(buffer, bufferOffset); @@ -1479,7 +1457,7 @@ static inline int4 readR10G10B10A2_SINT(uint bufferOffset, constant uchar *buffe color.a = (isAlphaNegative * alphaNegMask) | color.a; return color; } -static inline uint4 readR10G10B10A2_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR10G10B10A2_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; uint src = bytesToInt(buffer, bufferOffset); @@ -1489,7 +1467,7 @@ static inline uint4 readR10G10B10A2_UINT(uint bufferOffset, constant uchar *buff color.a = getShiftedData<2, 30>(src); return color; } -static inline float4 readR8G8B8A8(uint bufferOffset, constant uchar *buffer, bool isSRGB) +static inline float4 readR8G8B8A8(uint bufferOffset, const device uchar *buffer, bool isSRGB) { float4 color; uint src = bytesToInt(buffer, bufferOffset); @@ -1503,7 +1481,7 @@ static inline float4 readR8G8B8A8(uint bufferOffset, constant uchar *buffer, boo } return color; } -static inline void writeR8G8B8A8(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) +static inline void writeR8G8B8A8(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) { uint dst; if (isSRGB) @@ -1516,7 +1494,7 @@ static inline void writeR8G8B8A8(ushort2 gIndices, constant WritePixelParams &op } intToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8(uint bufferOffset, constant uchar *buffer, bool isSRGB) +static inline float4 readR8G8B8(uint bufferOffset, const device uchar *buffer, bool isSRGB) { float4 color; color.r = normalizedToFloat(buffer[bufferOffset]); @@ -1529,7 +1507,7 @@ static inline float4 readR8G8B8(uint bufferOffset, constant uchar *buffer, bool } return color; } -static inline void writeR8G8B8(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) +static inline void writeR8G8B8(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) { color.a = 1.0; uint dst; @@ -1543,19 +1521,19 @@ static inline void writeR8G8B8(ushort2 gIndices, constant WritePixelParams &opti } int24bitToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8A8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8A8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; uint src = bytesToInt(buffer, bufferOffset); color = unpack_snorm4x8_to_float(src); return color; } -static inline void writeR8G8B8A8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { uint dst = pack_float_to_snorm4x8(color); intToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat<7, char>(buffer[bufferOffset]); @@ -1564,89 +1542,89 @@ static inline float4 readR8G8B8_SNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8G8B8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { uint dst = pack_float_to_snorm4x8(color); int24bitToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8A8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8A8_UNORM(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, false); } -static inline void writeR8G8B8A8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, false); } -static inline float4 readR8G8B8A8_UNORM_SRGB(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8A8_UNORM_SRGB(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, true); } -static inline void writeR8G8B8A8_UNORM_SRGB(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_UNORM_SRGB(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, true); } -static inline float4 readB8G8R8A8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readB8G8R8A8_UNORM(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, false).bgra; } -static inline void writeB8G8R8A8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeB8G8R8A8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { color.rgba = color.bgra; return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, false); } -static inline float4 readB8G8R8A8_UNORM_SRGB(uint bufferOffset, constant uchar *buffer) +static inline float4 readB8G8R8A8_UNORM_SRGB(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, true).bgra; } -static inline void writeB8G8R8A8_UNORM_SRGB(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeB8G8R8A8_UNORM_SRGB(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { color.rgba = color.bgra; return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, true); } -static inline float4 readR8G8B8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8_UNORM(uint bufferOffset, const device uchar *buffer) { return readR8G8B8(bufferOffset, buffer, false); } -static inline void writeR8G8B8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8(gIndices, options, bufferOffset, color, buffer, false); } -static inline float4 readR8G8B8_UNORM_SRGB(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8_UNORM_SRGB(uint bufferOffset, const device uchar *buffer) { return readR8G8B8(bufferOffset, buffer, true); } -static inline void writeR8G8B8_UNORM_SRGB(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8_UNORM_SRGB(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8(gIndices, options, bufferOffset, color, buffer, true); } -static inline float4 readL8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readL8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = float3(normalizedToFloat(buffer[bufferOffset])); color.a = 1.0; return color; } -static inline void writeL8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); } -static inline void writeA8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeA8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.a); } -static inline float4 readL8A8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readL8A8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = float3(normalizedToFloat(buffer[bufferOffset])); color.a = normalizedToFloat(buffer[bufferOffset + 1]); return color; } -static inline void writeL8A8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL8A8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); buffer[bufferOffset + 1] = floatToNormalized(color.a); } -static inline float4 readR8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(buffer[bufferOffset]); @@ -1654,11 +1632,11 @@ static inline float4 readR8_UNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); } -static inline float4 readR8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat<7, char>(buffer[bufferOffset]); @@ -1666,11 +1644,11 @@ static inline float4 readR8_SNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = as_type(floatToNormalized(color.r)); } -static inline int4 readR8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1678,11 +1656,11 @@ static inline int4 readR8_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); } -static inline uint4 readR8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1690,11 +1668,11 @@ static inline uint4 readR8_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); } -static inline float4 readR8G8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(buffer[bufferOffset]); @@ -1703,12 +1681,12 @@ static inline float4 readR8G8_UNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8G8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); buffer[bufferOffset + 1] = floatToNormalized(color.g); } -static inline float4 readR8G8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat<7, char>(buffer[bufferOffset]); @@ -1717,12 +1695,12 @@ static inline float4 readR8G8_SNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8G8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = as_type(floatToNormalized(color.r)); buffer[bufferOffset + 1] = as_type(floatToNormalized(color.g)); } -static inline int4 readR8G8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8G8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1731,12 +1709,12 @@ static inline int4 readR8G8_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8G8_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); } -static inline uint4 readR8G8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8G8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1745,12 +1723,12 @@ static inline uint4 readR8G8_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8G8_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); } -static inline int4 readR8G8B8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8G8B8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1759,7 +1737,7 @@ static inline int4 readR8G8B8_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline uint4 readR8G8B8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8G8B8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1768,7 +1746,7 @@ static inline uint4 readR8G8B8_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline int4 readR8G8B8A8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8G8B8A8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1777,14 +1755,14 @@ static inline int4 readR8G8B8A8_SINT(uint bufferOffset, constant uchar *buffer) color.a = as_type(buffer[bufferOffset + 3]); return color; } -static inline void writeR8G8B8A8_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); buffer[bufferOffset + 2] = static_cast(color.b); buffer[bufferOffset + 3] = static_cast(color.a); } -static inline uint4 readR8G8B8A8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8G8B8A8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1793,14 +1771,14 @@ static inline uint4 readR8G8B8A8_UINT(uint bufferOffset, constant uchar *buffer) color.a = as_type(buffer[bufferOffset + 3]); return color; } -static inline void writeR8G8B8A8_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); buffer[bufferOffset + 2] = static_cast(color.b); buffer[bufferOffset + 3] = static_cast(color.a); } -static inline float4 readR16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1808,12 +1786,12 @@ static inline float4 readR16_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); } template -static inline float4 readR16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -1822,11 +1800,11 @@ static inline float4 readR16_NORM(uint bufferOffset, constant uchar *buffer) return color; } template -static inline void writeR16_NORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_NORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(floatToNormalized(color.r), bufferOffset, buffer); } -static inline int4 readR16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1834,11 +1812,11 @@ static inline int4 readR16_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); } -static inline uint4 readR16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1846,45 +1824,45 @@ static inline uint4 readR16_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); } -static inline float4 readA16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readA16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.a = as_type(bytesToShort(buffer, bufferOffset)); color.rgb = 0.0; return color; } -static inline void writeA16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeA16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.a)), bufferOffset, buffer); } -static inline float4 readL16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToShort(buffer, bufferOffset)); color.a = 1.0; return color; } -static inline void writeL16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); } -static inline float4 readL16A16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL16A16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToShort(buffer, bufferOffset)); color.a = as_type(bytesToShort(buffer, bufferOffset + 2)); return color; } -static inline void writeL16A16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL16A16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); shortToBytes(as_type(static_cast(color.a)), bufferOffset + 2, buffer); } -static inline float4 readR16G16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1893,13 +1871,13 @@ static inline float4 readR16G16_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR16G16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); shortToBytes(as_type(static_cast(color.g)), bufferOffset + 2, buffer); } template -static inline float4 readR16G16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -1909,12 +1887,12 @@ static inline float4 readR16G16_NORM(uint bufferOffset, constant uchar *buffer) return color; } template -static inline void writeR16G16_NORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_NORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(floatToNormalized(color.r), bufferOffset, buffer); shortToBytes(floatToNormalized(color.g), bufferOffset + 2, buffer); } -static inline int4 readR16G16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16G16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1923,12 +1901,12 @@ static inline int4 readR16G16_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16G16_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); } -static inline uint4 readR16G16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16G16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1937,12 +1915,12 @@ static inline uint4 readR16G16_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16G16_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); } -static inline float4 readR16G16B16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1952,7 +1930,7 @@ static inline float4 readR16G16B16_FLOAT(uint bufferOffset, constant uchar *buff return color; } template -static inline float4 readR16G16B16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -1961,7 +1939,7 @@ static inline float4 readR16G16B16_NORM(uint bufferOffset, constant uchar *buffe color.a = 1.0; return color; } -static inline int4 readR16G16B16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16G16B16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1970,7 +1948,7 @@ static inline int4 readR16G16B16_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline uint4 readR16G16B16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16G16B16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1979,7 +1957,7 @@ static inline uint4 readR16G16B16_UINT(uint bufferOffset, constant uchar *buffer color.a = 1; return color; } -static inline float4 readR16G16B16A16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16A16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1988,7 +1966,7 @@ static inline float4 readR16G16B16A16_FLOAT(uint bufferOffset, constant uchar *b color.a = as_type(bytesToShort(buffer, bufferOffset + 6)); return color; } -static inline void writeR16G16B16A16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); shortToBytes(as_type(static_cast(color.g)), bufferOffset + 2, buffer); @@ -1996,7 +1974,7 @@ static inline void writeR16G16B16A16_FLOAT(ushort2 gIndices, constant WritePixel shortToBytes(as_type(static_cast(color.a)), bufferOffset + 6, buffer); } template -static inline float4 readR16G16B16A16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16A16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -2006,14 +1984,14 @@ static inline float4 readR16G16B16A16_NORM(uint bufferOffset, constant uchar *bu return color; } template -static inline void writeR16G16B16A16_NORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_NORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(floatToNormalized(color.r), bufferOffset, buffer); shortToBytes(floatToNormalized(color.g), bufferOffset + 2, buffer); shortToBytes(floatToNormalized(color.b), bufferOffset + 4, buffer); shortToBytes(floatToNormalized(color.a), bufferOffset + 6, buffer); } -static inline int4 readR16G16B16A16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16G16B16A16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -2022,14 +2000,14 @@ static inline int4 readR16G16B16A16_SINT(uint bufferOffset, constant uchar *buff color.a = bytesToShort(buffer, bufferOffset + 6); return color; } -static inline void writeR16G16B16A16_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); shortToBytes(static_cast(color.b), bufferOffset + 4, buffer); shortToBytes(static_cast(color.a), bufferOffset + 6, buffer); } -static inline uint4 readR16G16B16A16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16G16B16A16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -2038,14 +2016,14 @@ static inline uint4 readR16G16B16A16_UINT(uint bufferOffset, constant uchar *buf color.a = bytesToShort(buffer, bufferOffset + 6); return color; } -static inline void writeR16G16B16A16_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); shortToBytes(static_cast(color.b), bufferOffset + 4, buffer); shortToBytes(static_cast(color.a), bufferOffset + 6, buffer); } -static inline float4 readR32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2053,12 +2031,12 @@ static inline float4 readR32_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); } template -static inline float4 readR32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2066,29 +2044,29 @@ static inline float4 readR32_NORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline float4 readA32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readA32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.a = as_type(bytesToInt(buffer, bufferOffset)); color.rgb = 0.0; return color; } -static inline void writeA32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeA32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.a), bufferOffset, buffer); } -static inline float4 readL32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToInt(buffer, bufferOffset)); color.a = 1.0; return color; } -static inline void writeL32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); } -static inline int4 readR32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2096,11 +2074,11 @@ static inline int4 readR32_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); } -static inline float4 readR32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2109,7 +2087,7 @@ static inline float4 readR32_FIXED(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline uint4 readR32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2117,23 +2095,23 @@ static inline uint4 readR32_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); } -static inline float4 readL32A32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL32A32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToInt(buffer, bufferOffset)); color.a = as_type(bytesToInt(buffer, bufferOffset + 4)); return color; } -static inline void writeL32A32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL32A32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); intToBytes(as_type(color.a), bufferOffset + 4, buffer); } -static inline float4 readR32G32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2142,13 +2120,13 @@ static inline float4 readR32G32_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR32G32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); intToBytes(as_type(color.g), bufferOffset + 4, buffer); } template -static inline float4 readR32G32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2157,7 +2135,7 @@ static inline float4 readR32G32_NORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline int4 readR32G32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32G32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2166,12 +2144,12 @@ static inline int4 readR32G32_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32G32_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); } -static inline float4 readR32G32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2181,7 +2159,7 @@ static inline float4 readR32G32_FIXED(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline uint4 readR32G32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32G32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2190,12 +2168,12 @@ static inline uint4 readR32G32_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32G32_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); } -static inline float4 readR32G32B32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2205,7 +2183,7 @@ static inline float4 readR32G32B32_FLOAT(uint bufferOffset, constant uchar *buff return color; } template -static inline float4 readR32G32B32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2214,7 +2192,7 @@ static inline float4 readR32G32B32_NORM(uint bufferOffset, constant uchar *buffe color.a = 1.0; return color; } -static inline int4 readR32G32B32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32G32B32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2223,7 +2201,7 @@ static inline int4 readR32G32B32_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline float4 readR32G32B32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2233,7 +2211,7 @@ static inline float4 readR32G32B32_FIXED(uint bufferOffset, constant uchar *buff color.a = 1.0; return color; } -static inline uint4 readR32G32B32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32G32B32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2242,7 +2220,7 @@ static inline uint4 readR32G32B32_UINT(uint bufferOffset, constant uchar *buffer color.a = 1; return color; } -static inline float4 readR32G32B32A32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32A32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2251,7 +2229,7 @@ static inline float4 readR32G32B32A32_FLOAT(uint bufferOffset, constant uchar *b color.a = as_type(bytesToInt(buffer, bufferOffset + 12)); return color; } -static inline void writeR32G32B32A32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32B32A32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); intToBytes(as_type(color.g), bufferOffset + 4, buffer); @@ -2259,7 +2237,7 @@ static inline void writeR32G32B32A32_FLOAT(ushort2 gIndices, constant WritePixel intToBytes(as_type(color.a), bufferOffset + 12, buffer); } template -static inline float4 readR32G32B32A32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32A32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2268,7 +2246,7 @@ static inline float4 readR32G32B32A32_NORM(uint bufferOffset, constant uchar *bu color.a = normalizedToFloat(bytesToInt(buffer, bufferOffset + 12)); return color; } -static inline int4 readR32G32B32A32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32G32B32A32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2277,14 +2255,14 @@ static inline int4 readR32G32B32A32_SINT(uint bufferOffset, constant uchar *buff color.a = bytesToInt(buffer, bufferOffset + 12); return color; } -static inline void writeR32G32B32A32_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32B32A32_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); intToBytes(color.b, bufferOffset + 8, buffer); intToBytes(color.a, bufferOffset + 12, buffer); } -static inline float4 readR32G32B32A32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32A32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2294,7 +2272,7 @@ static inline float4 readR32G32B32A32_FIXED(uint bufferOffset, constant uchar *b color.a = bytesToInt(buffer, bufferOffset + 12) * kDivisor; return color; } -static inline uint4 readR32G32B32A32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32G32B32A32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2303,66 +2281,90 @@ static inline uint4 readR32G32B32A32_UINT(uint bufferOffset, constant uchar *buf color.a = bytesToInt(buffer, bufferOffset + 12); return color; } -static inline void writeR32G32B32A32_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32B32A32_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); intToBytes(color.b, bufferOffset + 8, buffer); intToBytes(color.a, bufferOffset + 12, buffer); } -static inline int4 readR8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8_SINT(bufferOffset, buffer); } static inline uint4 readR8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8_UINT(bufferOffset, buffer); } static inline int4 readR8G8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8A8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8A8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8A8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8A8_UINT(bufferOffset, buffer); } -static inline int4 readR16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16_SINT(bufferOffset, buffer); } static inline uint4 readR16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16_UINT(bufferOffset, buffer); } static inline int4 readR16G16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16A16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16A16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16A16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16A16_UINT(bufferOffset, buffer); } -static inline int4 readR32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32_SINT(bufferOffset, buffer); } static inline uint4 readR32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32_UINT(bufferOffset, buffer); } static inline int4 readR32G32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32A32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32A32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32A32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32A32_UINT(bufferOffset, buffer); } -static inline int4 readR10G10B10A2_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR10G10B10A2_SINT(bufferOffset, buffer); } static inline uint4 readR10G10B10A2_USCALED(uint bufferOffset, constant uchar *buffer) { return readR10G10B10A2_UINT(bufferOffset, buffer); } -kernel void readFromBufferToFloatTexture(ushort3 gIndices [[thread_position_in_grid]], constant CopyPixelParams &options[[buffer(0)]], constant uchar *buffer [[buffer(1)]], texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) +static inline int4 readR8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8_SINT(bufferOffset, buffer); } static inline uint4 readR8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8_UINT(bufferOffset, buffer); } static inline int4 readR8G8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8A8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8A8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8_UINT(bufferOffset, buffer); } +static inline int4 readR16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16_SINT(bufferOffset, buffer); } static inline uint4 readR16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16_UINT(bufferOffset, buffer); } static inline int4 readR16G16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16A16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16A16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16A16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16A16_UINT(bufferOffset, buffer); } +static inline int4 readR32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32_SINT(bufferOffset, buffer); } static inline uint4 readR32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32_UINT(bufferOffset, buffer); } static inline int4 readR32G32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32A32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32A32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32A32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32A32_UINT(bufferOffset, buffer); } +static inline int4 readR10G10B10A2_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR10G10B10A2_SINT(bufferOffset, buffer); } static inline uint4 readR10G10B10A2_USCALED(uint bufferOffset, const device uchar *buffer) { return readR10G10B10A2_UINT(bufferOffset, buffer); } +static inline uint getB2TReadOffset(float2 position, constant B2TParams &options) { - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || gIndices.z >= options.copySize.z) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint2 iposition = static_cast(position) - options.textureOffset; + return options.bufferStartOffset + + (iposition.y * options.bufferRowPitch + iposition.x * options.pixelSize); +} +vertex float4 readFromBufferToTextureVS(unsigned int vid [[vertex_id]]) +{ + float4 output; + output.xy = select(float2(-1.0f), float2(1.0f), bool2(vid & uint2(2, 1))); + output.zw = float2(0.0, 1.0); + return output; +} +fragment float4 readFromBufferToFloatTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) +{ + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { - case FormatID::R5G6B5_UNORM: { auto color = readR5G6B5_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_UNORM: { auto color = readR8G8B8A8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_UNORM_SRGB: { auto color = readR8G8B8A8_UNORM_SRGB(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_SNORM: { auto color = readR8G8B8A8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::B8G8R8A8_UNORM: { auto color = readB8G8R8A8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::B8G8R8A8_UNORM_SRGB: { auto color = readB8G8R8A8_UNORM_SRGB(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_UNORM: { auto color = readR8G8B8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_UNORM_SRGB: { auto color = readR8G8B8_UNORM_SRGB(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_SNORM: { auto color = readR8G8B8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L8_UNORM: { auto color = readL8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L8A8_UNORM: { auto color = readL8A8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R5G5B5A1_UNORM: { auto color = readR5G5B5A1_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R4G4B4A4_UNORM: { auto color = readR4G4B4A4_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8_UNORM: { auto color = readR8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8_SNORM: { auto color = readR8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_UNORM: { auto color = readR8G8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_SNORM: { auto color = readR8G8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_FLOAT: { auto color = readR16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_SNORM: { auto color = readR16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_UNORM: { auto color = readR16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::A16_FLOAT: { auto color = readA16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L16_FLOAT: { auto color = readL16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L16A16_FLOAT: { auto color = readL16A16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_FLOAT: { auto color = readR16G16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_SNORM: { auto color = readR16G16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_UNORM: { auto color = readR16G16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_FLOAT: { auto color = readR16G16B16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_SNORM: { auto color = readR16G16B16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_UNORM: { auto color = readR16G16B16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_FLOAT: { auto color = readR16G16B16A16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_SNORM: { auto color = readR16G16B16A16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_UNORM: { auto color = readR16G16B16A16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32_FLOAT: { auto color = readR32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::A32_FLOAT: { auto color = readA32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L32_FLOAT: { auto color = readL32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L32A32_FLOAT: { auto color = readL32A32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32_FLOAT: { auto color = readR32G32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32_FLOAT: { auto color = readR32G32B32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32A32_FLOAT: { auto color = readR32G32B32A32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; + case FormatID::R5G6B5_UNORM: { return readR5G6B5_UNORM(bufferOffset, buffer); } case FormatID::R8G8B8A8_UNORM: { return readR8G8B8A8_UNORM(bufferOffset, buffer); } case FormatID::R8G8B8A8_UNORM_SRGB: { return readR8G8B8A8_UNORM_SRGB(bufferOffset, buffer); } case FormatID::R8G8B8A8_SNORM: { return readR8G8B8A8_SNORM(bufferOffset, buffer); } case FormatID::B8G8R8A8_UNORM: { return readB8G8R8A8_UNORM(bufferOffset, buffer); } case FormatID::B8G8R8A8_UNORM_SRGB: { return readB8G8R8A8_UNORM_SRGB(bufferOffset, buffer); } case FormatID::R8G8B8_UNORM: { return readR8G8B8_UNORM(bufferOffset, buffer); } case FormatID::R8G8B8_UNORM_SRGB: { return readR8G8B8_UNORM_SRGB(bufferOffset, buffer); } case FormatID::R8G8B8_SNORM: { return readR8G8B8_SNORM(bufferOffset, buffer); } case FormatID::L8_UNORM: { return readL8_UNORM(bufferOffset, buffer); } case FormatID::L8A8_UNORM: { return readL8A8_UNORM(bufferOffset, buffer); } case FormatID::R5G5B5A1_UNORM: { return readR5G5B5A1_UNORM(bufferOffset, buffer); } case FormatID::R4G4B4A4_UNORM: { return readR4G4B4A4_UNORM(bufferOffset, buffer); } case FormatID::R8_UNORM: { return readR8_UNORM(bufferOffset, buffer); } case FormatID::R8_SNORM: { return readR8_SNORM(bufferOffset, buffer); } case FormatID::R8G8_UNORM: { return readR8G8_UNORM(bufferOffset, buffer); } case FormatID::R8G8_SNORM: { return readR8G8_SNORM(bufferOffset, buffer); } case FormatID::R16_FLOAT: { return readR16_FLOAT(bufferOffset, buffer); } case FormatID::R16_SNORM: { return readR16_NORM(bufferOffset, buffer); } case FormatID::R16_UNORM: { return readR16_NORM(bufferOffset, buffer); } case FormatID::A16_FLOAT: { return readA16_FLOAT(bufferOffset, buffer); } case FormatID::L16_FLOAT: { return readL16_FLOAT(bufferOffset, buffer); } case FormatID::L16A16_FLOAT: { return readL16A16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16_FLOAT: { return readR16G16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16_SNORM: { return readR16G16_NORM(bufferOffset, buffer); } case FormatID::R16G16_UNORM: { return readR16G16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16_FLOAT: { return readR16G16B16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16B16_SNORM: { return readR16G16B16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16_UNORM: { return readR16G16B16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16A16_FLOAT: { return readR16G16B16A16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16B16A16_SNORM: { return readR16G16B16A16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16A16_UNORM: { return readR16G16B16A16_NORM(bufferOffset, buffer); } case FormatID::R32_FLOAT: { return readR32_FLOAT(bufferOffset, buffer); } case FormatID::A32_FLOAT: { return readA32_FLOAT(bufferOffset, buffer); } case FormatID::L32_FLOAT: { return readL32_FLOAT(bufferOffset, buffer); } case FormatID::L32A32_FLOAT: { return readL32A32_FLOAT(bufferOffset, buffer); } case FormatID::R32G32_FLOAT: { return readR32G32_FLOAT(bufferOffset, buffer); } case FormatID::R32G32B32_FLOAT: { return readR32G32B32_FLOAT(bufferOffset, buffer); } case FormatID::R32G32B32A32_FLOAT: { return readR32G32B32A32_FLOAT(bufferOffset, buffer); } } + return float4(0.0); } -kernel void readFromBufferToIntTexture(ushort3 gIndices [[thread_position_in_grid]], constant CopyPixelParams &options[[buffer(0)]], constant uchar *buffer [[buffer(1)]], texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) +fragment int4 readFromBufferToIntTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) { - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || gIndices.z >= options.copySize.z) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { - case FormatID::R8_SINT: { auto color = readR8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_SINT: { auto color = readR8G8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_SINT: { auto color = readR8G8B8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_SINT: { auto color = readR8G8B8A8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_SINT: { auto color = readR16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_SINT: { auto color = readR16G16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_SINT: { auto color = readR16G16B16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_SINT: { auto color = readR16G16B16A16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32_SINT: { auto color = readR32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32_SINT: { auto color = readR32G32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32_SINT: { auto color = readR32G32B32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32A32_SINT: { auto color = readR32G32B32A32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; + case FormatID::R8_SINT: { return readR8_SINT(bufferOffset, buffer); } case FormatID::R8G8_SINT: { return readR8G8_SINT(bufferOffset, buffer); } case FormatID::R8G8B8_SINT: { return readR8G8B8_SINT(bufferOffset, buffer); } case FormatID::R8G8B8A8_SINT: { return readR8G8B8A8_SINT(bufferOffset, buffer); } case FormatID::R16_SINT: { return readR16_SINT(bufferOffset, buffer); } case FormatID::R16G16_SINT: { return readR16G16_SINT(bufferOffset, buffer); } case FormatID::R16G16B16_SINT: { return readR16G16B16_SINT(bufferOffset, buffer); } case FormatID::R16G16B16A16_SINT: { return readR16G16B16A16_SINT(bufferOffset, buffer); } case FormatID::R32_SINT: { return readR32_SINT(bufferOffset, buffer); } case FormatID::R32G32_SINT: { return readR32G32_SINT(bufferOffset, buffer); } case FormatID::R32G32B32_SINT: { return readR32G32B32_SINT(bufferOffset, buffer); } case FormatID::R32G32B32A32_SINT: { return readR32G32B32A32_SINT(bufferOffset, buffer); } } + return int4(0); } -kernel void readFromBufferToUIntTexture(ushort3 gIndices [[thread_position_in_grid]], constant CopyPixelParams &options[[buffer(0)]], constant uchar *buffer [[buffer(1)]], texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) +fragment uint4 readFromBufferToUIntTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) { - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || gIndices.z >= options.copySize.z) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { - case FormatID::R8_UINT: { auto color = readR8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_UINT: { auto color = readR8G8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_UINT: { auto color = readR8G8B8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_UINT: { auto color = readR8G8B8A8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_UINT: { auto color = readR16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_UINT: { auto color = readR16G16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_UINT: { auto color = readR16G16B16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_UINT: { auto color = readR16G16B16A16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32_UINT: { auto color = readR32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32_UINT: { auto color = readR32G32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32_UINT: { auto color = readR32G32B32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32A32_UINT: { auto color = readR32G32B32A32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; + case FormatID::R8_UINT: { return readR8_UINT(bufferOffset, buffer); } case FormatID::R8G8_UINT: { return readR8G8_UINT(bufferOffset, buffer); } case FormatID::R8G8B8_UINT: { return readR8G8B8_UINT(bufferOffset, buffer); } case FormatID::R8G8B8A8_UINT: { return readR8G8B8A8_UINT(bufferOffset, buffer); } case FormatID::R16_UINT: { return readR16_UINT(bufferOffset, buffer); } case FormatID::R16G16_UINT: { return readR16G16_UINT(bufferOffset, buffer); } case FormatID::R16G16B16_UINT: { return readR16G16B16_UINT(bufferOffset, buffer); } case FormatID::R16G16B16A16_UINT: { return readR16G16B16A16_UINT(bufferOffset, buffer); } case FormatID::R32_UINT: { return readR32_UINT(bufferOffset, buffer); } case FormatID::R32G32_UINT: { return readR32G32_UINT(bufferOffset, buffer); } case FormatID::R32G32B32_UINT: { return readR32G32B32_UINT(bufferOffset, buffer); } case FormatID::R32G32B32A32_UINT: { return readR32G32B32A32_UINT(bufferOffset, buffer); } } + return uint4(0); +} +static inline uint getT2BWriteOffset(ushort2 position, constant T2BParams &options) +{ + return options.bufferStartOffset + + (position.y * options.bufferRowPitch + position.x * options.pixelSize); } -kernel void writeFromFloatTextureToBuffer(ushort2 gIndices [[thread_position_in_grid]], constant WritePixelParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) +kernel void writeFromFloatTextureToBufferCS(ushort2 gIndices [[thread_position_in_grid]], constant T2BParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) { if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { case FormatID::R5G6B5_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR5G6B5_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_UNORM_SRGB: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_UNORM_SRGB(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::B8G8R8A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeB8G8R8A8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::B8G8R8A8_UNORM_SRGB: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeB8G8R8A8_UNORM_SRGB(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8_UNORM_SRGB: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8_UNORM_SRGB(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeA8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L8A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL8A8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R5G5B5A1_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR5G5B5A1_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R4G4B4A4_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR4G4B4A4_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::A16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeA16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L16A16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL16A16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::A32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeA32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L32A32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL32A32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32B32A32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32B32A32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; } } -kernel void writeFromIntTextureToBuffer(ushort2 gIndices [[thread_position_in_grid]], constant WritePixelParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) +kernel void writeFromIntTextureToBufferCS(ushort2 gIndices [[thread_position_in_grid]], constant T2BParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) { if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { case FormatID::R8_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32B32A32_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32B32A32_SINT(gIndices, options, bufferOffset, color, buffer); } break; } } -kernel void writeFromUIntTextureToBuffer(ushort2 gIndices [[thread_position_in_grid]], constant WritePixelParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) +kernel void writeFromUIntTextureToBufferCS(ushort2 gIndices [[thread_position_in_grid]], constant T2BParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) { if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { case FormatID::R8_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32B32A32_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32B32A32_UINT(gIndices, options, bufferOffset, color, buffer); } break; @@ -2406,7 +2408,7 @@ inline void writeFloatVertex(constant CopyVertexParams &options, } static inline void convertToFloatVertexFormat(uint index, constant CopyVertexParams &options, - constant uchar *srcBuffer, + const device uchar *srcBuffer, device uchar *dstBuffer) { uint bufferOffset = options.srcBufferStartOffset + options.srcStride * index; @@ -2417,7 +2419,7 @@ static inline void convertToFloatVertexFormat(uint index, } kernel void convertToFloatVertexFormatCS(uint index [[thread_position_in_grid]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { if (index >= options.vertexCount) { return; }; @@ -2425,14 +2427,14 @@ kernel void convertToFloatVertexFormatCS(uint index [[thread_position_in_grid]], } vertex void convertToFloatVertexFormatVS(uint index [[vertex_id]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { convertToFloatVertexFormat(index, options, srcBuffer, dstBuffer); } static inline void expandVertexFormatComponents(uint index, constant CopyVertexParams &options, - constant uchar *srcBuffer, + const device uchar *srcBuffer, device uchar *dstBuffer) { uint srcOffset = options.srcBufferStartOffset + options.srcStride * index; @@ -2465,7 +2467,7 @@ static inline void expandVertexFormatComponents(uint index, } kernel void expandVertexFormatComponentsCS(uint index [[thread_position_in_grid]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { if (index >= options.vertexCount) { return; }; @@ -2473,14 +2475,14 @@ kernel void expandVertexFormatComponentsCS(uint index [[thread_position_in_grid] } vertex void expandVertexFormatComponentsVS(uint index [[vertex_id]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { expandVertexFormatComponents(index, options, srcBuffer, dstBuffer); } kernel void linearizeBlocks(ushort2 position [[thread_position_in_grid]], constant uint2 *dimensions [[buffer(0)]], - constant uint2 *srcBuffer [[buffer(1)]], + const device uint2 *srcBuffer [[buffer(1)]], device uint2 *dstBuffer [[buffer(2)]]) { if (any(uint2(position) >= *dimensions)) @@ -2496,7 +2498,7 @@ kernel void linearizeBlocks(ushort2 position [[thread_position_in_grid]], } kernel void saturateDepth(uint2 position [[thread_position_in_grid]], constant uint3 *dimensions [[buffer(0)]], - device float *srcBuffer [[buffer(1)]], + const device float *srcBuffer [[buffer(1)]], device float *dstBuffer [[buffer(2)]]) { if (any(position >= (*dimensions).xy)) diff --git a/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_src_autogen.h b/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_src_autogen.h index 46b11274850..ffd87b11dca 100644 --- a/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_src_autogen.h +++ b/src/libANGLE/renderer/metal/shaders/mtl_internal_shaders_src_autogen.h @@ -122,14 +122,14 @@ static inline float4 linearToSRGB(float4 color) return float4(linearToSRGB(color.r), linearToSRGB(color.g), linearToSRGB(color.b), color.a); } template -static inline Short bytesToShort(constant uchar *input, uint offset) +static inline Short bytesToShort(const device uchar *input, uint offset) { Short inputLo = input[offset]; Short inputHi = input[offset + 1]; return inputLo | (inputHi << 8); } template -static inline Int bytesToInt(constant uchar *input, uint offset) +static inline Int bytesToInt(const device uchar *input, uint offset) { Int input0 = input[offset]; Int input1 = input[offset + 1]; @@ -577,25 +577,25 @@ struct IndexConversionParams uint32_t indexCount; bool primitiveRestartEnabled; }; -inline ushort getIndexAligned(constant ushort *inputAligned, uint offset, uint idx) +inline ushort getIndexAligned(const device ushort *inputAligned, uint offset, uint idx) { return inputAligned[offset / 2 + idx]; } -inline uint getIndexAligned(constant uint *inputAligned, uint offset, uint idx) +inline uint getIndexAligned(const device uint *inputAligned, uint offset, uint idx) { return inputAligned[offset / 4 + idx]; } -inline uchar getIndexAligned(constant uchar *input, uint offset, uint idx) +inline uchar getIndexAligned(const device uchar *input, uint offset, uint idx) { return input[offset + idx]; } -inline ushort getIndexUnalignedU16(constant uchar *input, uint offset, uint idx) +inline ushort getIndexUnalignedU16(const device uchar *input, uint offset, uint idx) { ushort inputLo = input[offset + 2 * idx]; ushort inputHi = input[offset + 2 * idx + 1]; return inputLo | (inputHi << 8); } -inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx) +inline uint getIndexUnalignedU32(const device uchar *input, uint offset, uint idx) { uint input0 = input[offset + 4 * idx]; uint input1 = input[offset + 4 * idx + 1]; @@ -605,7 +605,7 @@ inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx) } kernel void convertIndexU8ToU16(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input [[buffer(1)]], + const device uchar *input [[buffer(1)]], device ushort *output [[buffer(2)]]) { if (idx >= options.indexCount) { return; }; @@ -621,9 +621,9 @@ kernel void convertIndexU8ToU16(uint idx [[thread_position_in_grid]], } kernel void convertIndexU16(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input + const device uchar *input [[buffer(1), function_constant(kSourceBufferUnaligned)]], - constant ushort *inputAligned + const device ushort *inputAligned [[buffer(1), function_constant(kSourceBufferAligned)]], device ushort *output [[buffer(2)]]) { @@ -641,9 +641,9 @@ kernel void convertIndexU16(uint idx [[thread_position_in_grid]], } kernel void convertIndexU32(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *input + const device uchar *input [[buffer(1), function_constant(kSourceBufferUnaligned)]], - constant uint *inputAligned + const device uint *inputAligned [[buffer(1), function_constant(kSourceBufferAligned)]], device uint *output [[buffer(2)]]) { @@ -676,9 +676,9 @@ kernel void genTriFanIndicesFromArray(uint idx [[thread_position_in_grid]], } inline uint getIndexU32(uint offset, uint idx, - constant uchar *inputU8 [[function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 [[function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 [[function_constant(kUseSourceBufferU32)]]) + const device uchar *inputU8 [[function_constant(kUseSourceBufferU8)]], + const device ushort *inputU16 [[function_constant(kUseSourceBufferU16)]], + const device uint *inputU32 [[function_constant(kUseSourceBufferU32)]]) { if (kUseSourceBufferU8) { @@ -704,11 +704,11 @@ inline uint getIndexU32(uint offset, } kernel void genTriFanIndicesFromElements(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *inputU8 + const device uchar *inputU8 [[buffer(1), function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 + const device ushort *inputU16 [[buffer(1), function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 + const device uint *inputU32 [[buffer(1), function_constant(kUseSourceBufferU32)]], device uint *output [[buffer(2)]]) { @@ -728,11 +728,11 @@ kernel void genLineLoopIndicesFromArray(uint idx [[thread_position_in_grid]], } kernel void genLineLoopIndicesFromElements(uint idx [[thread_position_in_grid]], constant IndexConversionParams &options [[buffer(0)]], - constant uchar *inputU8 + const device uchar *inputU8 [[buffer(1), function_constant(kUseSourceBufferU8)]], - constant ushort *inputU16 + const device ushort *inputU16 [[buffer(1), function_constant(kUseSourceBufferU16)]], - constant uint *inputU32 + const device uint *inputU32 [[buffer(1), function_constant(kUseSourceBufferU32)]], device uint *output [[buffer(2)]]) { @@ -1174,6 +1174,7 @@ enum ETC2_R8G8B8A8_UNORM_BLOCK, ETC2_R8G8B8_SRGB_BLOCK, ETC2_R8G8B8_UNORM_BLOCK, + G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, G8_B8R8_2PLANE_420_UNORM, G8_B8_R8_3PLANE_420_UNORM, L16A16_FLOAT, @@ -1208,6 +1209,7 @@ enum R10G10B10A2_UNORM, R10G10B10A2_USCALED, R10G10B10X2_UNORM, + R10X6G10X6B10X6A10X6_UNORM, R11G11B10_FLOAT, R16G16B16A16_FLOAT, R16G16B16A16_SINT, @@ -1332,16 +1334,15 @@ constant bool kCopyTextureType2DArray = kCopyTextureType == kTextureType2DArray; constant bool kCopyTextureType2DMS = kCopyTextureType == kTextureType2DMultisample; constant bool kCopyTextureTypeCube = kCopyTextureType == kTextureTypeCube; constant bool kCopyTextureType3D = kCopyTextureType == kTextureType3D; -struct CopyPixelParams +struct B2TParams { - uint3 copySize; - uint3 textureOffset; uint bufferStartOffset; uint pixelSize; uint bufferRowPitch; uint bufferDepthPitch; + uint2 textureOffset; }; -struct WritePixelParams +struct T2BParams { uint2 copySize; uint2 textureOffset; @@ -1353,31 +1354,8 @@ struct WritePixelParams bool reverseTextureRowOrder; }; template -static inline void textureWrite(ushort3 gIndices, - constant CopyPixelParams &options, - vec color, - texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) -{ - uint3 writeIndices = options.textureOffset + uint3(gIndices); - switch (kCopyTextureType) - { - case kTextureType2D: - dstTexture2d.write(color, writeIndices.xy); - break; - case kTextureType2DArray: - dstTexture2dArray.write(color, writeIndices.xy, writeIndices.z); - break; - case kTextureType3D: - dstTexture3d.write(color, writeIndices); - break; - case kTextureTypeCube: - dstTextureCube.write(color, writeIndices.xy, writeIndices.z); - break; - } -} -template static inline vec textureRead(ushort2 gIndices, - constant WritePixelParams &options, + constant T2BParams &options, texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]]) { vec color; @@ -1407,7 +1385,7 @@ static inline vec textureRead(ushort2 gIndices, } return color; } -static inline float4 readR5G6B5_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR5G6B5_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; ushort src = bytesToShort(buffer, bufferOffset); @@ -1417,14 +1395,14 @@ static inline float4 readR5G6B5_UNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR5G6B5_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR5G6B5_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { ushort dst = shiftData<5, 11>(floatToNormalized<5, ushort>(color.r)) | shiftData<6, 5>(floatToNormalized<6, ushort>(color.g)) | shiftData<5, 0>(floatToNormalized<5, ushort>(color.b)); shortToBytes(dst, bufferOffset, buffer); } -static inline float4 readR4G4B4A4_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR4G4B4A4_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; ushort src = bytesToShort(buffer, bufferOffset); @@ -1434,7 +1412,7 @@ static inline float4 readR4G4B4A4_UNORM(uint bufferOffset, constant uchar *buffe color.a = normalizedToFloat<4>(getShiftedData<4, 0>(src)); return color; } -static inline void writeR4G4B4A4_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR4G4B4A4_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { ushort dst = shiftData<4, 12>(floatToNormalized<4, ushort>(color.r)) | shiftData<4, 8>(floatToNormalized<4, ushort>(color.g)) | @@ -1443,7 +1421,7 @@ static inline void writeR4G4B4A4_UNORM(ushort2 gIndices, constant WritePixelPara ; shortToBytes(dst, bufferOffset, buffer); } -static inline float4 readR5G5B5A1_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR5G5B5A1_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; ushort src = bytesToShort(buffer, bufferOffset); @@ -1453,7 +1431,7 @@ static inline float4 readR5G5B5A1_UNORM(uint bufferOffset, constant uchar *buffe color.a = normalizedToFloat<1>(getShiftedData<1, 0>(src)); return color; } -static inline void writeR5G5B5A1_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR5G5B5A1_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { ushort dst = shiftData<5, 11>(floatToNormalized<5, ushort>(color.r)) | shiftData<5, 6>(floatToNormalized<5, ushort>(color.g)) | @@ -1462,7 +1440,7 @@ static inline void writeR5G5B5A1_UNORM(ushort2 gIndices, constant WritePixelPara ; shortToBytes(dst, bufferOffset, buffer); } -static inline int4 readR10G10B10A2_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR10G10B10A2_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; int src = bytesToInt(buffer, bufferOffset); @@ -1480,7 +1458,7 @@ static inline int4 readR10G10B10A2_SINT(uint bufferOffset, constant uchar *buffe color.a = (isAlphaNegative * alphaNegMask) | color.a; return color; } -static inline uint4 readR10G10B10A2_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR10G10B10A2_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; uint src = bytesToInt(buffer, bufferOffset); @@ -1490,7 +1468,7 @@ static inline uint4 readR10G10B10A2_UINT(uint bufferOffset, constant uchar *buff color.a = getShiftedData<2, 30>(src); return color; } -static inline float4 readR8G8B8A8(uint bufferOffset, constant uchar *buffer, bool isSRGB) +static inline float4 readR8G8B8A8(uint bufferOffset, const device uchar *buffer, bool isSRGB) { float4 color; uint src = bytesToInt(buffer, bufferOffset); @@ -1504,7 +1482,7 @@ static inline float4 readR8G8B8A8(uint bufferOffset, constant uchar *buffer, boo } return color; } -static inline void writeR8G8B8A8(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) +static inline void writeR8G8B8A8(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) { uint dst; if (isSRGB) @@ -1517,7 +1495,7 @@ static inline void writeR8G8B8A8(ushort2 gIndices, constant WritePixelParams &op } intToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8(uint bufferOffset, constant uchar *buffer, bool isSRGB) +static inline float4 readR8G8B8(uint bufferOffset, const device uchar *buffer, bool isSRGB) { float4 color; color.r = normalizedToFloat(buffer[bufferOffset]); @@ -1530,7 +1508,7 @@ static inline float4 readR8G8B8(uint bufferOffset, constant uchar *buffer, bool } return color; } -static inline void writeR8G8B8(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) +static inline void writeR8G8B8(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer, bool isSRGB) { color.a = 1.0; uint dst; @@ -1544,19 +1522,19 @@ static inline void writeR8G8B8(ushort2 gIndices, constant WritePixelParams &opti } int24bitToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8A8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8A8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; uint src = bytesToInt(buffer, bufferOffset); color = unpack_snorm4x8_to_float(src); return color; } -static inline void writeR8G8B8A8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { uint dst = pack_float_to_snorm4x8(color); intToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat<7, char>(buffer[bufferOffset]); @@ -1565,89 +1543,89 @@ static inline float4 readR8G8B8_SNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8G8B8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { uint dst = pack_float_to_snorm4x8(color); int24bitToBytes(dst, bufferOffset, buffer); } -static inline float4 readR8G8B8A8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8A8_UNORM(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, false); } -static inline void writeR8G8B8A8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, false); } -static inline float4 readR8G8B8A8_UNORM_SRGB(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8A8_UNORM_SRGB(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, true); } -static inline void writeR8G8B8A8_UNORM_SRGB(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_UNORM_SRGB(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, true); } -static inline float4 readB8G8R8A8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readB8G8R8A8_UNORM(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, false).bgra; } -static inline void writeB8G8R8A8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeB8G8R8A8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { color.rgba = color.bgra; return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, false); } -static inline float4 readB8G8R8A8_UNORM_SRGB(uint bufferOffset, constant uchar *buffer) +static inline float4 readB8G8R8A8_UNORM_SRGB(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8(bufferOffset, buffer, true).bgra; } -static inline void writeB8G8R8A8_UNORM_SRGB(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeB8G8R8A8_UNORM_SRGB(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { color.rgba = color.bgra; return writeR8G8B8A8(gIndices, options, bufferOffset, color, buffer, true); } -static inline float4 readR8G8B8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8_UNORM(uint bufferOffset, const device uchar *buffer) { return readR8G8B8(bufferOffset, buffer, false); } -static inline void writeR8G8B8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8(gIndices, options, bufferOffset, color, buffer, false); } -static inline float4 readR8G8B8_UNORM_SRGB(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8B8_UNORM_SRGB(uint bufferOffset, const device uchar *buffer) { return readR8G8B8(bufferOffset, buffer, true); } -static inline void writeR8G8B8_UNORM_SRGB(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8_UNORM_SRGB(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { return writeR8G8B8(gIndices, options, bufferOffset, color, buffer, true); } -static inline float4 readL8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readL8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = float3(normalizedToFloat(buffer[bufferOffset])); color.a = 1.0; return color; } -static inline void writeL8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); } -static inline void writeA8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeA8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.a); } -static inline float4 readL8A8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readL8A8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = float3(normalizedToFloat(buffer[bufferOffset])); color.a = normalizedToFloat(buffer[bufferOffset + 1]); return color; } -static inline void writeL8A8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL8A8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); buffer[bufferOffset + 1] = floatToNormalized(color.a); } -static inline float4 readR8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(buffer[bufferOffset]); @@ -1655,11 +1633,11 @@ static inline float4 readR8_UNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); } -static inline float4 readR8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat<7, char>(buffer[bufferOffset]); @@ -1667,11 +1645,11 @@ static inline float4 readR8_SNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = as_type(floatToNormalized(color.r)); } -static inline int4 readR8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1679,11 +1657,11 @@ static inline int4 readR8_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); } -static inline uint4 readR8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1691,11 +1669,11 @@ static inline uint4 readR8_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); } -static inline float4 readR8G8_UNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8_UNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(buffer[bufferOffset]); @@ -1704,12 +1682,12 @@ static inline float4 readR8G8_UNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8G8_UNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_UNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = floatToNormalized(color.r); buffer[bufferOffset + 1] = floatToNormalized(color.g); } -static inline float4 readR8G8_SNORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR8G8_SNORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat<7, char>(buffer[bufferOffset]); @@ -1718,12 +1696,12 @@ static inline float4 readR8G8_SNORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR8G8_SNORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_SNORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = as_type(floatToNormalized(color.r)); buffer[bufferOffset + 1] = as_type(floatToNormalized(color.g)); } -static inline int4 readR8G8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8G8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1732,12 +1710,12 @@ static inline int4 readR8G8_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8G8_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); } -static inline uint4 readR8G8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8G8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1746,12 +1724,12 @@ static inline uint4 readR8G8_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR8G8_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); } -static inline int4 readR8G8B8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8G8B8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1760,7 +1738,7 @@ static inline int4 readR8G8B8_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline uint4 readR8G8B8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8G8B8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1769,7 +1747,7 @@ static inline uint4 readR8G8B8_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline int4 readR8G8B8A8_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR8G8B8A8_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = as_type(buffer[bufferOffset]); @@ -1778,14 +1756,14 @@ static inline int4 readR8G8B8A8_SINT(uint bufferOffset, constant uchar *buffer) color.a = as_type(buffer[bufferOffset + 3]); return color; } -static inline void writeR8G8B8A8_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); buffer[bufferOffset + 2] = static_cast(color.b); buffer[bufferOffset + 3] = static_cast(color.a); } -static inline uint4 readR8G8B8A8_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR8G8B8A8_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = as_type(buffer[bufferOffset]); @@ -1794,14 +1772,14 @@ static inline uint4 readR8G8B8A8_UINT(uint bufferOffset, constant uchar *buffer) color.a = as_type(buffer[bufferOffset + 3]); return color; } -static inline void writeR8G8B8A8_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR8G8B8A8_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { buffer[bufferOffset] = static_cast(color.r); buffer[bufferOffset + 1] = static_cast(color.g); buffer[bufferOffset + 2] = static_cast(color.b); buffer[bufferOffset + 3] = static_cast(color.a); } -static inline float4 readR16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1809,12 +1787,12 @@ static inline float4 readR16_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); } template -static inline float4 readR16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -1823,11 +1801,11 @@ static inline float4 readR16_NORM(uint bufferOffset, constant uchar *buffer) return color; } template -static inline void writeR16_NORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_NORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(floatToNormalized(color.r), bufferOffset, buffer); } -static inline int4 readR16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1835,11 +1813,11 @@ static inline int4 readR16_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); } -static inline uint4 readR16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1847,45 +1825,45 @@ static inline uint4 readR16_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); } -static inline float4 readA16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readA16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.a = as_type(bytesToShort(buffer, bufferOffset)); color.rgb = 0.0; return color; } -static inline void writeA16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeA16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.a)), bufferOffset, buffer); } -static inline float4 readL16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToShort(buffer, bufferOffset)); color.a = 1.0; return color; } -static inline void writeL16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); } -static inline float4 readL16A16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL16A16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToShort(buffer, bufferOffset)); color.a = as_type(bytesToShort(buffer, bufferOffset + 2)); return color; } -static inline void writeL16A16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL16A16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); shortToBytes(as_type(static_cast(color.a)), bufferOffset + 2, buffer); } -static inline float4 readR16G16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1894,13 +1872,13 @@ static inline float4 readR16G16_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR16G16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); shortToBytes(as_type(static_cast(color.g)), bufferOffset + 2, buffer); } template -static inline float4 readR16G16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -1910,12 +1888,12 @@ static inline float4 readR16G16_NORM(uint bufferOffset, constant uchar *buffer) return color; } template -static inline void writeR16G16_NORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_NORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(floatToNormalized(color.r), bufferOffset, buffer); shortToBytes(floatToNormalized(color.g), bufferOffset + 2, buffer); } -static inline int4 readR16G16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16G16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1924,12 +1902,12 @@ static inline int4 readR16G16_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16G16_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); } -static inline uint4 readR16G16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16G16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1938,12 +1916,12 @@ static inline uint4 readR16G16_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR16G16_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); } -static inline float4 readR16G16B16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1953,7 +1931,7 @@ static inline float4 readR16G16B16_FLOAT(uint bufferOffset, constant uchar *buff return color; } template -static inline float4 readR16G16B16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -1962,7 +1940,7 @@ static inline float4 readR16G16B16_NORM(uint bufferOffset, constant uchar *buffe color.a = 1.0; return color; } -static inline int4 readR16G16B16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16G16B16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1971,7 +1949,7 @@ static inline int4 readR16G16B16_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline uint4 readR16G16B16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16G16B16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -1980,7 +1958,7 @@ static inline uint4 readR16G16B16_UINT(uint bufferOffset, constant uchar *buffer color.a = 1; return color; } -static inline float4 readR16G16B16A16_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16A16_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToShort(buffer, bufferOffset)); @@ -1989,7 +1967,7 @@ static inline float4 readR16G16B16A16_FLOAT(uint bufferOffset, constant uchar *b color.a = as_type(bytesToShort(buffer, bufferOffset + 6)); return color; } -static inline void writeR16G16B16A16_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(as_type(static_cast(color.r)), bufferOffset, buffer); shortToBytes(as_type(static_cast(color.g)), bufferOffset + 2, buffer); @@ -1997,7 +1975,7 @@ static inline void writeR16G16B16A16_FLOAT(ushort2 gIndices, constant WritePixel shortToBytes(as_type(static_cast(color.a)), bufferOffset + 6, buffer); } template -static inline float4 readR16G16B16A16_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR16G16B16A16_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToShort(buffer, bufferOffset)); @@ -2007,14 +1985,14 @@ static inline float4 readR16G16B16A16_NORM(uint bufferOffset, constant uchar *bu return color; } template -static inline void writeR16G16B16A16_NORM(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_NORM(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(floatToNormalized(color.r), bufferOffset, buffer); shortToBytes(floatToNormalized(color.g), bufferOffset + 2, buffer); shortToBytes(floatToNormalized(color.b), bufferOffset + 4, buffer); shortToBytes(floatToNormalized(color.a), bufferOffset + 6, buffer); } -static inline int4 readR16G16B16A16_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR16G16B16A16_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -2023,14 +2001,14 @@ static inline int4 readR16G16B16A16_SINT(uint bufferOffset, constant uchar *buff color.a = bytesToShort(buffer, bufferOffset + 6); return color; } -static inline void writeR16G16B16A16_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); shortToBytes(static_cast(color.b), bufferOffset + 4, buffer); shortToBytes(static_cast(color.a), bufferOffset + 6, buffer); } -static inline uint4 readR16G16B16A16_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR16G16B16A16_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToShort(buffer, bufferOffset); @@ -2039,14 +2017,14 @@ static inline uint4 readR16G16B16A16_UINT(uint bufferOffset, constant uchar *buf color.a = bytesToShort(buffer, bufferOffset + 6); return color; } -static inline void writeR16G16B16A16_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR16G16B16A16_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { shortToBytes(static_cast(color.r), bufferOffset, buffer); shortToBytes(static_cast(color.g), bufferOffset + 2, buffer); shortToBytes(static_cast(color.b), bufferOffset + 4, buffer); shortToBytes(static_cast(color.a), bufferOffset + 6, buffer); } -static inline float4 readR32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2054,12 +2032,12 @@ static inline float4 readR32_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); } template -static inline float4 readR32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2067,29 +2045,29 @@ static inline float4 readR32_NORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline float4 readA32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readA32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.a = as_type(bytesToInt(buffer, bufferOffset)); color.rgb = 0.0; return color; } -static inline void writeA32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeA32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.a), bufferOffset, buffer); } -static inline float4 readL32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToInt(buffer, bufferOffset)); color.a = 1.0; return color; } -static inline void writeL32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); } -static inline int4 readR32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2097,11 +2075,11 @@ static inline int4 readR32_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); } -static inline float4 readR32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2110,7 +2088,7 @@ static inline float4 readR32_FIXED(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline uint4 readR32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2118,23 +2096,23 @@ static inline uint4 readR32_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); } -static inline float4 readL32A32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readL32A32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.rgb = as_type(bytesToInt(buffer, bufferOffset)); color.a = as_type(bytesToInt(buffer, bufferOffset + 4)); return color; } -static inline void writeL32A32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeL32A32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); intToBytes(as_type(color.a), bufferOffset + 4, buffer); } -static inline float4 readR32G32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2143,13 +2121,13 @@ static inline float4 readR32G32_FLOAT(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline void writeR32G32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); intToBytes(as_type(color.g), bufferOffset + 4, buffer); } template -static inline float4 readR32G32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2158,7 +2136,7 @@ static inline float4 readR32G32_NORM(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline int4 readR32G32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32G32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2167,12 +2145,12 @@ static inline int4 readR32G32_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32G32_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); } -static inline float4 readR32G32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2182,7 +2160,7 @@ static inline float4 readR32G32_FIXED(uint bufferOffset, constant uchar *buffer) color.a = 1.0; return color; } -static inline uint4 readR32G32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32G32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2191,12 +2169,12 @@ static inline uint4 readR32G32_UINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline void writeR32G32_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); } -static inline float4 readR32G32B32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2206,7 +2184,7 @@ static inline float4 readR32G32B32_FLOAT(uint bufferOffset, constant uchar *buff return color; } template -static inline float4 readR32G32B32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2215,7 +2193,7 @@ static inline float4 readR32G32B32_NORM(uint bufferOffset, constant uchar *buffe color.a = 1.0; return color; } -static inline int4 readR32G32B32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32G32B32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2224,7 +2202,7 @@ static inline int4 readR32G32B32_SINT(uint bufferOffset, constant uchar *buffer) color.a = 1; return color; } -static inline float4 readR32G32B32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2234,7 +2212,7 @@ static inline float4 readR32G32B32_FIXED(uint bufferOffset, constant uchar *buff color.a = 1.0; return color; } -static inline uint4 readR32G32B32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32G32B32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2243,7 +2221,7 @@ static inline uint4 readR32G32B32_UINT(uint bufferOffset, constant uchar *buffer color.a = 1; return color; } -static inline float4 readR32G32B32A32_FLOAT(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32A32_FLOAT(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = as_type(bytesToInt(buffer, bufferOffset)); @@ -2252,7 +2230,7 @@ static inline float4 readR32G32B32A32_FLOAT(uint bufferOffset, constant uchar *b color.a = as_type(bytesToInt(buffer, bufferOffset + 12)); return color; } -static inline void writeR32G32B32A32_FLOAT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32B32A32_FLOAT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(as_type(color.r), bufferOffset, buffer); intToBytes(as_type(color.g), bufferOffset + 4, buffer); @@ -2260,7 +2238,7 @@ static inline void writeR32G32B32A32_FLOAT(ushort2 gIndices, constant WritePixel intToBytes(as_type(color.a), bufferOffset + 12, buffer); } template -static inline float4 readR32G32B32A32_NORM(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32A32_NORM(uint bufferOffset, const device uchar *buffer) { float4 color; color.r = normalizedToFloat(bytesToInt(buffer, bufferOffset)); @@ -2269,7 +2247,7 @@ static inline float4 readR32G32B32A32_NORM(uint bufferOffset, constant uchar *bu color.a = normalizedToFloat(bytesToInt(buffer, bufferOffset + 12)); return color; } -static inline int4 readR32G32B32A32_SINT(uint bufferOffset, constant uchar *buffer) +static inline int4 readR32G32B32A32_SINT(uint bufferOffset, const device uchar *buffer) { int4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2278,14 +2256,14 @@ static inline int4 readR32G32B32A32_SINT(uint bufferOffset, constant uchar *buff color.a = bytesToInt(buffer, bufferOffset + 12); return color; } -static inline void writeR32G32B32A32_SINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32B32A32_SINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); intToBytes(color.b, bufferOffset + 8, buffer); intToBytes(color.a, bufferOffset + 12, buffer); } -static inline float4 readR32G32B32A32_FIXED(uint bufferOffset, constant uchar *buffer) +static inline float4 readR32G32B32A32_FIXED(uint bufferOffset, const device uchar *buffer) { float4 color; constexpr float kDivisor = 1.0f / (1 << 16); @@ -2295,7 +2273,7 @@ static inline float4 readR32G32B32A32_FIXED(uint bufferOffset, constant uchar *b color.a = bytesToInt(buffer, bufferOffset + 12) * kDivisor; return color; } -static inline uint4 readR32G32B32A32_UINT(uint bufferOffset, constant uchar *buffer) +static inline uint4 readR32G32B32A32_UINT(uint bufferOffset, const device uchar *buffer) { uint4 color; color.r = bytesToInt(buffer, bufferOffset); @@ -2304,66 +2282,90 @@ static inline uint4 readR32G32B32A32_UINT(uint bufferOffset, constant uchar *buf color.a = bytesToInt(buffer, bufferOffset + 12); return color; } -static inline void writeR32G32B32A32_UINT(ushort2 gIndices, constant WritePixelParams &options, uint bufferOffset, vec color, device uchar *buffer) +static inline void writeR32G32B32A32_UINT(ushort2 gIndices, constant T2BParams &options, uint bufferOffset, vec color, device uchar *buffer) { intToBytes(color.r, bufferOffset, buffer); intToBytes(color.g, bufferOffset + 4, buffer); intToBytes(color.b, bufferOffset + 8, buffer); intToBytes(color.a, bufferOffset + 12, buffer); } -static inline int4 readR8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8_SINT(bufferOffset, buffer); } static inline uint4 readR8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8_UINT(bufferOffset, buffer); } static inline int4 readR8G8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8A8_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8A8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8A8_USCALED(uint bufferOffset, constant uchar *buffer) { return readR8G8B8A8_UINT(bufferOffset, buffer); } -static inline int4 readR16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16_SINT(bufferOffset, buffer); } static inline uint4 readR16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16_UINT(bufferOffset, buffer); } static inline int4 readR16G16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16A16_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16A16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16A16_USCALED(uint bufferOffset, constant uchar *buffer) { return readR16G16B16A16_UINT(bufferOffset, buffer); } -static inline int4 readR32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32_SINT(bufferOffset, buffer); } static inline uint4 readR32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32_UINT(bufferOffset, buffer); } static inline int4 readR32G32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32A32_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32A32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32A32_USCALED(uint bufferOffset, constant uchar *buffer) { return readR32G32B32A32_UINT(bufferOffset, buffer); } -static inline int4 readR10G10B10A2_SSCALED(uint bufferOffset, constant uchar *buffer) { return readR10G10B10A2_SINT(bufferOffset, buffer); } static inline uint4 readR10G10B10A2_USCALED(uint bufferOffset, constant uchar *buffer) { return readR10G10B10A2_UINT(bufferOffset, buffer); } -kernel void readFromBufferToFloatTexture(ushort3 gIndices [[thread_position_in_grid]], constant CopyPixelParams &options[[buffer(0)]], constant uchar *buffer [[buffer(1)]], texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) +static inline int4 readR8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8_SINT(bufferOffset, buffer); } static inline uint4 readR8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8_UINT(bufferOffset, buffer); } static inline int4 readR8G8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8_UINT(bufferOffset, buffer); } static inline int4 readR8G8B8A8_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8_SINT(bufferOffset, buffer); } static inline uint4 readR8G8B8A8_USCALED(uint bufferOffset, const device uchar *buffer) { return readR8G8B8A8_UINT(bufferOffset, buffer); } +static inline int4 readR16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16_SINT(bufferOffset, buffer); } static inline uint4 readR16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16_UINT(bufferOffset, buffer); } static inline int4 readR16G16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16_UINT(bufferOffset, buffer); } static inline int4 readR16G16B16A16_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16A16_SINT(bufferOffset, buffer); } static inline uint4 readR16G16B16A16_USCALED(uint bufferOffset, const device uchar *buffer) { return readR16G16B16A16_UINT(bufferOffset, buffer); } +static inline int4 readR32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32_SINT(bufferOffset, buffer); } static inline uint4 readR32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32_UINT(bufferOffset, buffer); } static inline int4 readR32G32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32_UINT(bufferOffset, buffer); } static inline int4 readR32G32B32A32_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32A32_SINT(bufferOffset, buffer); } static inline uint4 readR32G32B32A32_USCALED(uint bufferOffset, const device uchar *buffer) { return readR32G32B32A32_UINT(bufferOffset, buffer); } +static inline int4 readR10G10B10A2_SSCALED(uint bufferOffset, const device uchar *buffer) { return readR10G10B10A2_SINT(bufferOffset, buffer); } static inline uint4 readR10G10B10A2_USCALED(uint bufferOffset, const device uchar *buffer) { return readR10G10B10A2_UINT(bufferOffset, buffer); } +static inline uint getB2TReadOffset(float2 position, constant B2TParams &options) { - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || gIndices.z >= options.copySize.z) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint2 iposition = static_cast(position) - options.textureOffset; + return options.bufferStartOffset + + (iposition.y * options.bufferRowPitch + iposition.x * options.pixelSize); +} +vertex float4 readFromBufferToTextureVS(unsigned int vid [[vertex_id]]) +{ + float4 output; + output.xy = select(float2(-1.0f), float2(1.0f), bool2(vid & uint2(2, 1))); + output.zw = float2(0.0, 1.0); + return output; +} +fragment float4 readFromBufferToFloatTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) +{ + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { - case FormatID::R5G6B5_UNORM: { auto color = readR5G6B5_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_UNORM: { auto color = readR8G8B8A8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_UNORM_SRGB: { auto color = readR8G8B8A8_UNORM_SRGB(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_SNORM: { auto color = readR8G8B8A8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::B8G8R8A8_UNORM: { auto color = readB8G8R8A8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::B8G8R8A8_UNORM_SRGB: { auto color = readB8G8R8A8_UNORM_SRGB(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_UNORM: { auto color = readR8G8B8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_UNORM_SRGB: { auto color = readR8G8B8_UNORM_SRGB(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_SNORM: { auto color = readR8G8B8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L8_UNORM: { auto color = readL8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L8A8_UNORM: { auto color = readL8A8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R5G5B5A1_UNORM: { auto color = readR5G5B5A1_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R4G4B4A4_UNORM: { auto color = readR4G4B4A4_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8_UNORM: { auto color = readR8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8_SNORM: { auto color = readR8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_UNORM: { auto color = readR8G8_UNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_SNORM: { auto color = readR8G8_SNORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_FLOAT: { auto color = readR16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_SNORM: { auto color = readR16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_UNORM: { auto color = readR16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::A16_FLOAT: { auto color = readA16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L16_FLOAT: { auto color = readL16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L16A16_FLOAT: { auto color = readL16A16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_FLOAT: { auto color = readR16G16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_SNORM: { auto color = readR16G16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_UNORM: { auto color = readR16G16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_FLOAT: { auto color = readR16G16B16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_SNORM: { auto color = readR16G16B16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_UNORM: { auto color = readR16G16B16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_FLOAT: { auto color = readR16G16B16A16_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_SNORM: { auto color = readR16G16B16A16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_UNORM: { auto color = readR16G16B16A16_NORM(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32_FLOAT: { auto color = readR32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::A32_FLOAT: { auto color = readA32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L32_FLOAT: { auto color = readL32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::L32A32_FLOAT: { auto color = readL32A32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32_FLOAT: { auto color = readR32G32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32_FLOAT: { auto color = readR32G32B32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32A32_FLOAT: { auto color = readR32G32B32A32_FLOAT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; + case FormatID::R5G6B5_UNORM: { return readR5G6B5_UNORM(bufferOffset, buffer); } case FormatID::R8G8B8A8_UNORM: { return readR8G8B8A8_UNORM(bufferOffset, buffer); } case FormatID::R8G8B8A8_UNORM_SRGB: { return readR8G8B8A8_UNORM_SRGB(bufferOffset, buffer); } case FormatID::R8G8B8A8_SNORM: { return readR8G8B8A8_SNORM(bufferOffset, buffer); } case FormatID::B8G8R8A8_UNORM: { return readB8G8R8A8_UNORM(bufferOffset, buffer); } case FormatID::B8G8R8A8_UNORM_SRGB: { return readB8G8R8A8_UNORM_SRGB(bufferOffset, buffer); } case FormatID::R8G8B8_UNORM: { return readR8G8B8_UNORM(bufferOffset, buffer); } case FormatID::R8G8B8_UNORM_SRGB: { return readR8G8B8_UNORM_SRGB(bufferOffset, buffer); } case FormatID::R8G8B8_SNORM: { return readR8G8B8_SNORM(bufferOffset, buffer); } case FormatID::L8_UNORM: { return readL8_UNORM(bufferOffset, buffer); } case FormatID::L8A8_UNORM: { return readL8A8_UNORM(bufferOffset, buffer); } case FormatID::R5G5B5A1_UNORM: { return readR5G5B5A1_UNORM(bufferOffset, buffer); } case FormatID::R4G4B4A4_UNORM: { return readR4G4B4A4_UNORM(bufferOffset, buffer); } case FormatID::R8_UNORM: { return readR8_UNORM(bufferOffset, buffer); } case FormatID::R8_SNORM: { return readR8_SNORM(bufferOffset, buffer); } case FormatID::R8G8_UNORM: { return readR8G8_UNORM(bufferOffset, buffer); } case FormatID::R8G8_SNORM: { return readR8G8_SNORM(bufferOffset, buffer); } case FormatID::R16_FLOAT: { return readR16_FLOAT(bufferOffset, buffer); } case FormatID::R16_SNORM: { return readR16_NORM(bufferOffset, buffer); } case FormatID::R16_UNORM: { return readR16_NORM(bufferOffset, buffer); } case FormatID::A16_FLOAT: { return readA16_FLOAT(bufferOffset, buffer); } case FormatID::L16_FLOAT: { return readL16_FLOAT(bufferOffset, buffer); } case FormatID::L16A16_FLOAT: { return readL16A16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16_FLOAT: { return readR16G16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16_SNORM: { return readR16G16_NORM(bufferOffset, buffer); } case FormatID::R16G16_UNORM: { return readR16G16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16_FLOAT: { return readR16G16B16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16B16_SNORM: { return readR16G16B16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16_UNORM: { return readR16G16B16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16A16_FLOAT: { return readR16G16B16A16_FLOAT(bufferOffset, buffer); } case FormatID::R16G16B16A16_SNORM: { return readR16G16B16A16_NORM(bufferOffset, buffer); } case FormatID::R16G16B16A16_UNORM: { return readR16G16B16A16_NORM(bufferOffset, buffer); } case FormatID::R32_FLOAT: { return readR32_FLOAT(bufferOffset, buffer); } case FormatID::A32_FLOAT: { return readA32_FLOAT(bufferOffset, buffer); } case FormatID::L32_FLOAT: { return readL32_FLOAT(bufferOffset, buffer); } case FormatID::L32A32_FLOAT: { return readL32A32_FLOAT(bufferOffset, buffer); } case FormatID::R32G32_FLOAT: { return readR32G32_FLOAT(bufferOffset, buffer); } case FormatID::R32G32B32_FLOAT: { return readR32G32B32_FLOAT(bufferOffset, buffer); } case FormatID::R32G32B32A32_FLOAT: { return readR32G32B32A32_FLOAT(bufferOffset, buffer); } } + return float4(0.0); } -kernel void readFromBufferToIntTexture(ushort3 gIndices [[thread_position_in_grid]], constant CopyPixelParams &options[[buffer(0)]], constant uchar *buffer [[buffer(1)]], texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) +fragment int4 readFromBufferToIntTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) { - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || gIndices.z >= options.copySize.z) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { - case FormatID::R8_SINT: { auto color = readR8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_SINT: { auto color = readR8G8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_SINT: { auto color = readR8G8B8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_SINT: { auto color = readR8G8B8A8_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_SINT: { auto color = readR16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_SINT: { auto color = readR16G16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_SINT: { auto color = readR16G16B16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_SINT: { auto color = readR16G16B16A16_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32_SINT: { auto color = readR32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32_SINT: { auto color = readR32G32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32_SINT: { auto color = readR32G32B32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32A32_SINT: { auto color = readR32G32B32A32_SINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; + case FormatID::R8_SINT: { return readR8_SINT(bufferOffset, buffer); } case FormatID::R8G8_SINT: { return readR8G8_SINT(bufferOffset, buffer); } case FormatID::R8G8B8_SINT: { return readR8G8B8_SINT(bufferOffset, buffer); } case FormatID::R8G8B8A8_SINT: { return readR8G8B8A8_SINT(bufferOffset, buffer); } case FormatID::R16_SINT: { return readR16_SINT(bufferOffset, buffer); } case FormatID::R16G16_SINT: { return readR16G16_SINT(bufferOffset, buffer); } case FormatID::R16G16B16_SINT: { return readR16G16B16_SINT(bufferOffset, buffer); } case FormatID::R16G16B16A16_SINT: { return readR16G16B16A16_SINT(bufferOffset, buffer); } case FormatID::R32_SINT: { return readR32_SINT(bufferOffset, buffer); } case FormatID::R32G32_SINT: { return readR32G32_SINT(bufferOffset, buffer); } case FormatID::R32G32B32_SINT: { return readR32G32B32_SINT(bufferOffset, buffer); } case FormatID::R32G32B32A32_SINT: { return readR32G32B32A32_SINT(bufferOffset, buffer); } } + return int4(0); } -kernel void readFromBufferToUIntTexture(ushort3 gIndices [[thread_position_in_grid]], constant CopyPixelParams &options[[buffer(0)]], constant uchar *buffer [[buffer(1)]], texture2d dstTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array dstTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d dstTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube dstTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]]) +fragment uint4 readFromBufferToUIntTextureFS(float4 position [[position]], + constant B2TParams &options [[buffer(0)]], + const device uchar *buffer [[buffer(1)]]) { - if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y || gIndices.z >= options.copySize.z) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.z * options.bufferDepthPitch + gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getB2TReadOffset(position.xy, options); switch (kCopyFormatType) { - case FormatID::R8_UINT: { auto color = readR8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8_UINT: { auto color = readR8G8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8_UINT: { auto color = readR8G8B8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R8G8B8A8_UINT: { auto color = readR8G8B8A8_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16_UINT: { auto color = readR16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16_UINT: { auto color = readR16G16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16_UINT: { auto color = readR16G16B16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R16G16B16A16_UINT: { auto color = readR16G16B16A16_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32_UINT: { auto color = readR32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32_UINT: { auto color = readR32G32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32_UINT: { auto color = readR32G32B32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; case FormatID::R32G32B32A32_UINT: { auto color = readR32G32B32A32_UINT(bufferOffset, buffer); textureWrite(gIndices, options, color, dstTexture2d, dstTexture2dArray, dstTexture3d, dstTextureCube); } break; + case FormatID::R8_UINT: { return readR8_UINT(bufferOffset, buffer); } case FormatID::R8G8_UINT: { return readR8G8_UINT(bufferOffset, buffer); } case FormatID::R8G8B8_UINT: { return readR8G8B8_UINT(bufferOffset, buffer); } case FormatID::R8G8B8A8_UINT: { return readR8G8B8A8_UINT(bufferOffset, buffer); } case FormatID::R16_UINT: { return readR16_UINT(bufferOffset, buffer); } case FormatID::R16G16_UINT: { return readR16G16_UINT(bufferOffset, buffer); } case FormatID::R16G16B16_UINT: { return readR16G16B16_UINT(bufferOffset, buffer); } case FormatID::R16G16B16A16_UINT: { return readR16G16B16A16_UINT(bufferOffset, buffer); } case FormatID::R32_UINT: { return readR32_UINT(bufferOffset, buffer); } case FormatID::R32G32_UINT: { return readR32G32_UINT(bufferOffset, buffer); } case FormatID::R32G32B32_UINT: { return readR32G32B32_UINT(bufferOffset, buffer); } case FormatID::R32G32B32A32_UINT: { return readR32G32B32A32_UINT(bufferOffset, buffer); } } + return uint4(0); +} +static inline uint getT2BWriteOffset(ushort2 position, constant T2BParams &options) +{ + return options.bufferStartOffset + + (position.y * options.bufferRowPitch + position.x * options.pixelSize); } -kernel void writeFromFloatTextureToBuffer(ushort2 gIndices [[thread_position_in_grid]], constant WritePixelParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) +kernel void writeFromFloatTextureToBufferCS(ushort2 gIndices [[thread_position_in_grid]], constant T2BParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) { if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { case FormatID::R5G6B5_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR5G6B5_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_UNORM_SRGB: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_UNORM_SRGB(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::B8G8R8A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeB8G8R8A8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::B8G8R8A8_UNORM_SRGB: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeB8G8R8A8_UNORM_SRGB(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8_UNORM_SRGB: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8_UNORM_SRGB(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeA8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L8A8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL8A8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R5G5B5A1_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR5G5B5A1_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R4G4B4A4_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR4G4B4A4_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_UNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_SNORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::A16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeA16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L16A16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL16A16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_SNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_UNORM: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_NORM(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::A32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeA32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::L32A32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeL32A32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32B32A32_FLOAT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32B32A32_FLOAT(gIndices, options, bufferOffset, color, buffer); } break; } } -kernel void writeFromIntTextureToBuffer(ushort2 gIndices [[thread_position_in_grid]], constant WritePixelParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) +kernel void writeFromIntTextureToBufferCS(ushort2 gIndices [[thread_position_in_grid]], constant T2BParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) { if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { case FormatID::R8_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32_SINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32B32A32_SINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32B32A32_SINT(gIndices, options, bufferOffset, color, buffer); } break; } } -kernel void writeFromUIntTextureToBuffer(ushort2 gIndices [[thread_position_in_grid]], constant WritePixelParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) +kernel void writeFromUIntTextureToBufferCS(ushort2 gIndices [[thread_position_in_grid]], constant T2BParams &options[[buffer(0)]], texture2d srcTexture2d [[texture(0), function_constant(kCopyTextureType2D)]], texture2d_array srcTexture2dArray [[texture(0), function_constant(kCopyTextureType2DArray)]], texture3d srcTexture3d [[texture(0), function_constant(kCopyTextureType3D)]], texturecube srcTextureCube [[texture(0), function_constant(kCopyTextureTypeCube)]], texture2d_ms srcTexture2dMS [[texture(0), function_constant(kCopyTextureType2DMS)]], device uchar *buffer [[buffer(1)]]) { if (gIndices.x >= options.copySize.x || gIndices.y >= options.copySize.y) { return; } - uint bufferOffset = options.bufferStartOffset + (gIndices.y * options.bufferRowPitch + gIndices.x * options.pixelSize); + uint bufferOffset = getT2BWriteOffset(gIndices, options); switch (kCopyFormatType) { case FormatID::R8_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R8G8B8A8_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR8G8B8A8_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R16G16B16A16_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR16G16B16A16_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32_UINT(gIndices, options, bufferOffset, color, buffer); } break; case FormatID::R32G32B32A32_UINT: { auto color = textureRead(gIndices, options, srcTexture2d, srcTexture2dArray, srcTexture3d, srcTextureCube, srcTexture2dMS); writeR32G32B32A32_UINT(gIndices, options, bufferOffset, color, buffer); } break; @@ -2407,7 +2409,7 @@ inline void writeFloatVertex(constant CopyVertexParams &options, } static inline void convertToFloatVertexFormat(uint index, constant CopyVertexParams &options, - constant uchar *srcBuffer, + const device uchar *srcBuffer, device uchar *dstBuffer) { uint bufferOffset = options.srcBufferStartOffset + options.srcStride * index; @@ -2418,7 +2420,7 @@ static inline void convertToFloatVertexFormat(uint index, } kernel void convertToFloatVertexFormatCS(uint index [[thread_position_in_grid]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { if (index >= options.vertexCount) { return; }; @@ -2426,14 +2428,14 @@ kernel void convertToFloatVertexFormatCS(uint index [[thread_position_in_grid]], } vertex void convertToFloatVertexFormatVS(uint index [[vertex_id]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { convertToFloatVertexFormat(index, options, srcBuffer, dstBuffer); } static inline void expandVertexFormatComponents(uint index, constant CopyVertexParams &options, - constant uchar *srcBuffer, + const device uchar *srcBuffer, device uchar *dstBuffer) { uint srcOffset = options.srcBufferStartOffset + options.srcStride * index; @@ -2466,7 +2468,7 @@ static inline void expandVertexFormatComponents(uint index, } kernel void expandVertexFormatComponentsCS(uint index [[thread_position_in_grid]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { if (index >= options.vertexCount) { return; }; @@ -2474,14 +2476,14 @@ kernel void expandVertexFormatComponentsCS(uint index [[thread_position_in_grid] } vertex void expandVertexFormatComponentsVS(uint index [[vertex_id]], constant CopyVertexParams &options [[buffer(0)]], - constant uchar *srcBuffer [[buffer(1)]], + const device uchar *srcBuffer [[buffer(1)]], device uchar *dstBuffer [[buffer(2)]]) { expandVertexFormatComponents(index, options, srcBuffer, dstBuffer); } kernel void linearizeBlocks(ushort2 position [[thread_position_in_grid]], constant uint2 *dimensions [[buffer(0)]], - constant uint2 *srcBuffer [[buffer(1)]], + const device uint2 *srcBuffer [[buffer(1)]], device uint2 *dstBuffer [[buffer(2)]]) { if (any(uint2(position) >= *dimensions)) @@ -2497,7 +2499,7 @@ kernel void linearizeBlocks(ushort2 position [[thread_position_in_grid]], } kernel void saturateDepth(uint2 position [[thread_position_in_grid]], constant uint3 *dimensions [[buffer(0)]], - device float *srcBuffer [[buffer(1)]], + const device float *srcBuffer [[buffer(1)]], device float *dstBuffer [[buffer(2)]]) { if (any(position >= (*dimensions).xy)) diff --git a/src/libANGLE/renderer/null/BufferNULL.cpp b/src/libANGLE/renderer/null/BufferNULL.cpp index 42914ff2e0a..16e1b37fc04 100644 --- a/src/libANGLE/renderer/null/BufferNULL.cpp +++ b/src/libANGLE/renderer/null/BufferNULL.cpp @@ -7,6 +7,10 @@ // Implements the class methods for BufferNULL. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/null/BufferNULL.h" #include "common/debug.h" @@ -36,7 +40,9 @@ angle::Result BufferNULL::setDataWithUsageFlags(const gl::Context *context, const void *data, size_t size, gl::BufferUsage usage, - GLbitfield flags) + GLbitfield flags, + gl::BufferStorage bufferStorage, + BufferFeedback *feedback) { ANGLE_CHECK_GL_ALLOC(GetImplAs(context), mAllocationTracker->updateMemoryAllocation(mData.size(), size)); @@ -53,7 +59,8 @@ angle::Result BufferNULL::setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { ANGLE_CHECK_GL_ALLOC(GetImplAs(context), mAllocationTracker->updateMemoryAllocation(mData.size(), size)); @@ -70,7 +77,8 @@ angle::Result BufferNULL::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { if (size > 0) { @@ -83,7 +91,8 @@ angle::Result BufferNULL::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { BufferNULL *sourceNULL = GetAs(source); if (size > 0) @@ -93,7 +102,10 @@ angle::Result BufferNULL::copySubData(const gl::Context *context, return angle::Result::Continue; } -angle::Result BufferNULL::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result BufferNULL::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { *mapPtr = mData.data(); return angle::Result::Continue; @@ -103,13 +115,16 @@ angle::Result BufferNULL::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { *mapPtr = mData.data() + offset; return angle::Result::Continue; } -angle::Result BufferNULL::unmap(const gl::Context *context, GLboolean *result) +angle::Result BufferNULL::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { *result = GL_TRUE; return angle::Result::Continue; diff --git a/src/libANGLE/renderer/null/BufferNULL.h b/src/libANGLE/renderer/null/BufferNULL.h index b0faea2b367..38ca86f26fc 100644 --- a/src/libANGLE/renderer/null/BufferNULL.h +++ b/src/libANGLE/renderer/null/BufferNULL.h @@ -29,29 +29,40 @@ class BufferNULL : public BufferImpl const void *data, size_t size, gl::BufferUsage usage, - GLbitfield flags) override; + GLbitfield flags, + gl::BufferStorage bufferStorage, + BufferFeedback *feedback) override; angle::Result setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, diff --git a/src/libANGLE/renderer/null/ContextNULL.cpp b/src/libANGLE/renderer/null/ContextNULL.cpp index 0969a328db0..6f8b1d58d6d 100644 --- a/src/libANGLE/renderer/null/ContextNULL.cpp +++ b/src/libANGLE/renderer/null/ContextNULL.cpp @@ -91,6 +91,7 @@ ContextNULL::ContextNULL(const gl::State &state, mExtensions.textureStorageEXT = true; mExtensions.rgb8Rgba8OES = true; + mExtensions.colorBufferFloatEXT = state.getClientVersion() >= gl::Version(3, 0); mExtensions.textureCompressionDxt1EXT = true; mExtensions.textureCompressionDxt3ANGLE = true; mExtensions.textureCompressionDxt5ANGLE = true; @@ -464,9 +465,10 @@ BufferImpl *ContextNULL::createBuffer(const gl::BufferState &state) return new BufferNULL(state, mAllocationTracker); } -VertexArrayImpl *ContextNULL::createVertexArray(const gl::VertexArrayState &data) +VertexArrayImpl *ContextNULL::createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) { - return new VertexArrayNULL(data); + return new VertexArrayNULL(data, vertexArrayBuffers); } QueryImpl *ContextNULL::createQuery(gl::QueryType type) diff --git a/src/libANGLE/renderer/null/ContextNULL.h b/src/libANGLE/renderer/null/ContextNULL.h index 26a00dbc5e7..bca01224ace 100644 --- a/src/libANGLE/renderer/null/ContextNULL.h +++ b/src/libANGLE/renderer/null/ContextNULL.h @@ -225,7 +225,8 @@ class ContextNULL : public ContextImpl BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; diff --git a/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/libANGLE/renderer/null/FramebufferNULL.cpp index 8874d3e28d7..e44faadbea6 100644 --- a/src/libANGLE/renderer/null/FramebufferNULL.cpp +++ b/src/libANGLE/renderer/null/FramebufferNULL.cpp @@ -7,6 +7,10 @@ // Implements the class methods for FramebufferNULL. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/null/FramebufferNULL.h" #include "common/debug.h" diff --git a/src/libANGLE/renderer/null/SurfaceNULL.cpp b/src/libANGLE/renderer/null/SurfaceNULL.cpp index 83e8e613cc0..f6bc6e4d6ce 100644 --- a/src/libANGLE/renderer/null/SurfaceNULL.cpp +++ b/src/libANGLE/renderer/null/SurfaceNULL.cpp @@ -25,7 +25,7 @@ egl::Error SurfaceNULL::initialize(const egl::Display *display) return egl::NoError(); } -egl::Error SurfaceNULL::swap(const gl::Context *context) +egl::Error SurfaceNULL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -71,16 +71,10 @@ egl::Error SurfaceNULL::getMscRate(EGLint *numerator, EGLint *denominator) void SurfaceNULL::setSwapInterval(const egl::Display *display, EGLint interval) {} -EGLint SurfaceNULL::getWidth() const +gl::Extents SurfaceNULL::getSize() const { // TODO(geofflang): Read from an actual window? - return 100; -} - -EGLint SurfaceNULL::getHeight() const -{ - // TODO(geofflang): Read from an actual window? - return 100; + return gl::Extents(100, 100, 1); } EGLint SurfaceNULL::isPostSubBufferSupported() const diff --git a/src/libANGLE/renderer/null/SurfaceNULL.h b/src/libANGLE/renderer/null/SurfaceNULL.h index 7cd32109420..6773e1878d2 100644 --- a/src/libANGLE/renderer/null/SurfaceNULL.h +++ b/src/libANGLE/renderer/null/SurfaceNULL.h @@ -22,7 +22,7 @@ class SurfaceNULL : public SurfaceImpl ~SurfaceNULL() override; egl::Error initialize(const egl::Display *display) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -37,9 +37,8 @@ class SurfaceNULL : public SurfaceImpl egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - // width and height can change with client window resizing - EGLint getWidth() const override; - EGLint getHeight() const override; + // size can change with client window resizing + gl::Extents getSize() const override; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; diff --git a/src/libANGLE/renderer/null/VertexArrayNULL.cpp b/src/libANGLE/renderer/null/VertexArrayNULL.cpp index 187ca798d71..59678d5753b 100644 --- a/src/libANGLE/renderer/null/VertexArrayNULL.cpp +++ b/src/libANGLE/renderer/null/VertexArrayNULL.cpp @@ -7,6 +7,10 @@ // Implements the class methods for VertexArrayNULL. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/null/VertexArrayNULL.h" #include "common/debug.h" @@ -14,7 +18,10 @@ namespace rx { -VertexArrayNULL::VertexArrayNULL(const gl::VertexArrayState &data) : VertexArrayImpl(data) {} +VertexArrayNULL::VertexArrayNULL(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) + : VertexArrayImpl(data, vertexArrayBuffers) +{} angle::Result VertexArrayNULL::syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, diff --git a/src/libANGLE/renderer/null/VertexArrayNULL.h b/src/libANGLE/renderer/null/VertexArrayNULL.h index 9e786eab0e8..4c66a4e4951 100644 --- a/src/libANGLE/renderer/null/VertexArrayNULL.h +++ b/src/libANGLE/renderer/null/VertexArrayNULL.h @@ -18,7 +18,8 @@ namespace rx class VertexArrayNULL : public VertexArrayImpl { public: - VertexArrayNULL(const gl::VertexArrayState &data); + VertexArrayNULL(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers); angle::Result syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, diff --git a/src/libANGLE/renderer/renderer_utils.cpp b/src/libANGLE/renderer/renderer_utils.cpp index 6d326f88a64..1fe20bb9554 100644 --- a/src/libANGLE/renderer/renderer_utils.cpp +++ b/src/libANGLE/renderer/renderer_utils.cpp @@ -7,6 +7,10 @@ // Helper methods pertaining to most or all back-ends. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/renderer_utils.h" #include "common/base/anglebase/numerics/checked_math.h" @@ -24,8 +28,8 @@ #include "libANGLE/renderer/Format.h" #include "platform/Feature.h" -#include #include +#include namespace angle { @@ -74,7 +78,7 @@ void FeatureInfo::applyOverride(bool state) // FeatureSetBase implementation void FeatureSetBase::reset() { - for (auto iter : members) + for (const auto &iter : members) { FeatureInfo *feature = iter.second; feature->enabled = false; @@ -82,12 +86,15 @@ void FeatureSetBase::reset() } } -void FeatureSetBase::overrideFeatures(const std::vector &featureNames, bool enabled) +std::string FeatureSetBase::overrideFeatures(const std::vector &featureNames, + bool enabled) { + std::stringstream featureStream; + for (const std::string &name : featureNames) { const bool hasWildcard = name.back() == '*'; - for (auto iter : members) + for (const auto &iter : members) { const std::string &featureName = iter.first; FeatureInfo *feature = iter.second; @@ -99,6 +106,12 @@ void FeatureSetBase::overrideFeatures(const std::vector &featureNam feature->applyOverride(enabled); + if (featureStream.str().empty()) + { + featureStream << "Feature overrides: "; + } + featureStream << featureName << (enabled ? " enabled, " : " disabled, "); + // If name has a wildcard, try to match it with all features. Otherwise, bail on first // match, as names are unique. if (!hasWildcard) @@ -107,13 +120,20 @@ void FeatureSetBase::overrideFeatures(const std::vector &featureNam } } } + + if (!featureStream.str().empty()) + { + featureStream << std::endl; + } + + return featureStream.str(); } void FeatureSetBase::populateFeatureList(FeatureList *features) const { - for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++) + for (const auto &member : members) { - features->push_back(it->second); + features->push_back(member.second); } } } // namespace angle @@ -253,28 +273,113 @@ template -void ExpandMatrix(T *target, const GLfloat *value) +void ExpandMatrix(T *target, const GLfloat *value, const bool isFloat16) { static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!"); - - // Clamp the staging data's size to the last written value so that data packed just after this - // matrix is not overwritten. - constexpr int kDstFlatSize = - GetFlattenedIndex(colsSrc - 1, rowsSrc - 1) + 1; - T staging[kDstFlatSize] = {0}; - - for (int r = 0; r < rowsSrc; r++) + if (!isFloat16) { - for (int c = 0; c < colsSrc; c++) + // Clamp the staging data's size to the last written value so that data packed just after + // this matrix is not overwritten. + constexpr int kDstFlatSize = + GetFlattenedIndex(colsSrc - 1, rowsSrc - 1) + 1; + T staging[kDstFlatSize] = {0}; + + for (int r = 0; r < rowsSrc; r++) { - int srcIndex = GetFlattenedIndex(c, r); - int dstIndex = GetFlattenedIndex(c, r); + for (int c = 0; c < colsSrc; c++) + { + int srcIndex = GetFlattenedIndex(c, r); + int dstIndex = GetFlattenedIndex(c, r); - staging[dstIndex] = static_cast(value[srcIndex]); + staging[dstIndex] = static_cast(value[srcIndex]); + } } + + memcpy(target, staging, kDstFlatSize * sizeof(T)); + return; } - memcpy(target, staging, kDstFlatSize * sizeof(T)); + // If we reach here, we need to transform uniform matrix data from 32-bit to 16-bit. + // This path is only expected to execute on Vulkan backend. + // Vulkan SpirvMatrix Rule: each column / row of the matrix must be aligned to 16 bytes + // We need to copy to the destination row by row / column by column, because we need to + // leave padding for each row / each column. + static_assert(IsDstColumnMajor ? (rowsDst == 4) : (colsDst == 4), + "matrix is not correctly padded"); + if (IsDstColumnMajor) + { + // If (IsDstColumnMajor == true), copy column by column + constexpr int kDstMatrixComponentSize = rowsDst; + constexpr int kSrcMatrixColSize = rowsSrc; + for (int c = 0; c < colsSrc; ++c) + { + GLshort staging[kSrcMatrixColSize] = {0}; + for (int r = 0; r < rowsSrc; r++) + { + int srcIndex = GetFlattenedIndex(c, r); + int dstIndex = GetFlattenedIndex(0, r); + ASSERT(dstIndex < kSrcMatrixColSize); + staging[dstIndex] = gl::float32ToFloat16(value[srcIndex]); + } + memcpy(target, staging, kSrcMatrixColSize * sizeof(GLshort)); + // If it is not the last column, set the remaining of the current column to 0, so + // that shader is not accessing uninitialized memory. + // If it is the last column, don't touch the remaining of the current column. + // Because we may pack other data tightly right after the last column. See + // http://anglebug.com/42266878. + // e.g. For example, for a 3*3 matrix, in the target memory, we end up with: + // Last column: + // |2-byte half float|2-byte half float|2-byte half float|10-byte untouched| + // Other columns: + // |2-byte half float|2-byte half float|2-byte half float|10-byte of 0| + if (c < colsSrc - 1) + { + size_t remainingColumnSize = + kDstMatrixComponentSize * sizeof(GLfloat) - kSrcMatrixColSize * sizeof(GLshort); + GLshort *remainingColumnStartPos = + reinterpret_cast(target) + kSrcMatrixColSize; + memset(remainingColumnStartPos, 0, remainingColumnSize); + } + target += kDstMatrixComponentSize; + } + } + else + { + // If (IsDstColumnMajor == false), copy row by row + constexpr int kDstMatrixComponentSize = colsDst; + constexpr int kSrcMatrixRowSize = colsSrc; + for (int r = 0; r < rowsSrc; ++r) + { + GLshort staging[kSrcMatrixRowSize] = {0}; + for (int c = 0; c < colsSrc; c++) + { + int srcIndex = GetFlattenedIndex(c, r); + int dstIndex = GetFlattenedIndex(0, r); + ASSERT(dstIndex < kSrcMatrixRowSize); + staging[dstIndex] = gl::float32ToFloat16(value[srcIndex]); + } + memcpy(target, staging, kSrcMatrixRowSize * sizeof(GLshort)); + // If it is not the last row, set the remaining of the current row to 0, so + // that shader is not accessing uninitialized memory. + // If it is the last row, don't touch the remaining of the current row. Because + // we may pack other data tightly right after the last row. See + // http://anglebug.com/42266878. + // e.g. For example, for a 3*3 matrix, in the target memory, we end up with: + // Last row: + // |2-byte half float|2-byte half float|2-byte half float|10-byte untouched| + // Other rows: + // |2-byte half float|2-byte half float|2-byte half float|10-byte of 0| + if (r < rowsSrc - 1) + { + size_t remainingRowSize = + kDstMatrixComponentSize * sizeof(GLfloat) - kSrcMatrixRowSize * sizeof(GLshort); + GLshort *remainingRowStartPos = + reinterpret_cast(target) + kSrcMatrixRowSize; + memset(remainingRowStartPos, 0, remainingRowSize); + } + target += kDstMatrixComponentSize; + } + } } template (countIn)); @@ -299,7 +405,7 @@ void SetFloatUniformMatrix(unsigned int arrayElementOffset, for (unsigned int i = 0; i < count; i++) { ExpandMatrix(target, value); + rowsDst>(target, value, isFloat16); target += targetMatrixStride; value += colsSrc * rowsSrc; @@ -385,6 +491,7 @@ PackPixelsParams::PackPixelsParams() : destFormat(nullptr), outputPitch(0), packBuffer(nullptr), + reverseRowOrder(false), offset(0), rotation(SurfaceRotation::Identity) {} @@ -692,10 +799,6 @@ void CopyImageCHROMIUM(const uint8_t *sourceData, } // IncompleteTextureSet implementation. -IncompleteTextureSet::IncompleteTextureSet() {} - -IncompleteTextureSet::~IncompleteTextureSet() {} - void IncompleteTextureSet::onDestroy(const gl::Context *context) { // Clear incomplete textures. @@ -843,7 +946,7 @@ angle::Result IncompleteTextureSet::getIncompleteTexture( #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \ template void SetFloatUniformMatrix##api::Run( \ - unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *) + unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *, bool) ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3); @@ -861,9 +964,9 @@ ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4); #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC -#define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \ - template void SetFloatUniformMatrix##api::Run(unsigned int, unsigned int, GLsizei, \ - GLboolean, const GLfloat *, uint8_t *) +#define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \ + template void SetFloatUniformMatrix##api::Run( \ + unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *, bool) template struct SetFloatUniformMatrixGLSL @@ -873,7 +976,8 @@ struct SetFloatUniformMatrixGLSL GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData); + uint8_t *targetData, + bool isFloat16); }; ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4); @@ -882,9 +986,9 @@ ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4); #undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC -#define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \ - template void SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \ - GLboolean, const GLfloat *, uint8_t *) +#define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \ + template void SetFloatUniformMatrix##api<4, rows>::Run( \ + unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *, bool) template struct SetFloatUniformMatrixHLSL<4, rows> @@ -894,7 +998,8 @@ struct SetFloatUniformMatrixHLSL<4, rows> GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData); + uint8_t *targetData, + bool isFloat16); }; ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2); @@ -909,22 +1014,55 @@ void SetFloatUniformMatrixGLSL::Run(unsigned int arrayElementOffset, GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData) + uint8_t *targetData, + const bool isFloat16) { const bool isSrcColumnMajor = !transpose; if (isSrcColumnMajor) { - // Both src and dst matrixs are has same layout, - // a single memcpy updates all the matrices - constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4; - SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value, - targetData); + if (isFloat16) + { + // If we need to transform float number in matrix from 32-bit to 16-bit before writing + // to memory, even if both src and dst have the same layout, we can't do + // SetFloatUniformMatrixFast(). because we need to + // 1) transform the src data from 32-bit to 16-bit + // 2) make sure each column aligns to 16 bytes + // For example, if this is the src column major 4*4 matrix: + // | 4-byte float | 4-byte float | 4-byte float | 4-byte float | + // ______________ ______________ ______________ ______________ + // | 4-byte float | 4-byte float | 4-byte float | 4-byte float | + // ______________ ______________ ______________ ______________ + // | 4-byte float | 4-byte float | 4-byte float | 4-byte float | + // ______________ ______________ ______________ ______________ + // | 4-byte float | 4-byte float | 4-byte float | 4-byte float | + + // Then in the dst column major 4*4 matrix, it needs to be + // | 2-byte half float | 2-byte half float | 2-byte half float | 2-byte half float | + // ___________________ ___________________ ___________________ ___________________ + // | 2-byte half float | 2-byte half float | 2-byte half float | 2-byte half float | + // ___________________ ___________________ ___________________ ___________________ + // | 2-byte half float | 2-byte half float | 2-byte half float | 2-byte half float | + // ___________________ ___________________ ___________________ ___________________ + // | 2-byte half float | 2-byte half float | 2-byte half float | 2-byte half float | + // ___________________ ___________________ ___________________ ___________________ + // | 8-byte padding | 8-byte padding | 8-byte padding | 8-byte padding | + SetFloatUniformMatrix( + arrayElementOffset, elementCount, countIn, value, targetData, isFloat16); + } + else + { + // Both src and dst matrixs are has same layout, and we don't need to transform data + // from 32-bit to 16-bit, a single memcpy updates all the matrices + constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4; + SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, + value, targetData); + } } else { // fallback to general cases SetFloatUniformMatrix(arrayElementOffset, elementCount, - countIn, value, targetData); + countIn, value, targetData, isFloat16); } } @@ -934,19 +1072,20 @@ void SetFloatUniformMatrixGLSL::Run(unsigned int arrayElementOffset, GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData) + uint8_t *targetData, + const bool isFloat16) { const bool isSrcColumnMajor = !transpose; // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows. if (isSrcColumnMajor) { - SetFloatUniformMatrix(arrayElementOffset, elementCount, - countIn, value, targetData); + SetFloatUniformMatrix( + arrayElementOffset, elementCount, countIn, value, targetData, isFloat16); } else { - SetFloatUniformMatrix(arrayElementOffset, elementCount, - countIn, value, targetData); + SetFloatUniformMatrix( + arrayElementOffset, elementCount, countIn, value, targetData, isFloat16); } } @@ -956,7 +1095,8 @@ void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset, GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData) + uint8_t *targetData, + const bool isFloat16) { const bool isSrcColumnMajor = !transpose; if (!isSrcColumnMajor) @@ -971,7 +1111,7 @@ void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset, { // fallback to general cases SetFloatUniformMatrix(arrayElementOffset, elementCount, - countIn, value, targetData); + countIn, value, targetData, isFloat16); } } @@ -981,44 +1121,91 @@ void SetFloatUniformMatrixHLSL::Run(unsigned int arrayElementOffset, GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData) + uint8_t *targetData, + const bool isFloat16) { const bool isSrcColumnMajor = !transpose; // Internally store matrices as row-major to accomodate HLSL matrix indexing. Each row is // padded to 4 columns. if (!isSrcColumnMajor) { - SetFloatUniformMatrix(arrayElementOffset, elementCount, - countIn, value, targetData); + SetFloatUniformMatrix( + arrayElementOffset, elementCount, countIn, value, targetData, isFloat16); } else { - SetFloatUniformMatrix(arrayElementOffset, elementCount, - countIn, value, targetData); + SetFloatUniformMatrix( + arrayElementOffset, elementCount, countIn, value, targetData, isFloat16); } } -template void GetMatrixUniform(GLenum, GLint *, const GLint *, bool); -template void GetMatrixUniform(GLenum, GLuint *, const GLuint *, bool); +template void GetMatrixUniform(GLenum, GLint *, const GLint *, bool, bool); +template void GetMatrixUniform(GLenum, GLuint *, const GLuint *, bool, bool); -void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose) +void GetMatrixUniform(GLenum type, + GLfloat *dataOut, + const GLfloat *source, + bool transpose, + bool isFloat16) { int columns = gl::VariableColumnCount(type); int rows = gl::VariableRowCount(type); - for (GLint col = 0; col < columns; ++col) + if (isFloat16) { - for (GLint row = 0; row < rows; ++row) + // If we transformed float from 32-bit to 16-bit before writing to memory, + // we need to transform them back to 32-bit after reading. + constexpr GLint kInputStride = 4; + for (GLint col = 0; col < columns; ++col) { - GLfloat *outptr = dataOut + ((col * rows) + row); - const GLfloat *inptr = - transpose ? source + ((row * 4) + col) : source + ((col * 4) + row); - *outptr = *inptr; + for (GLint outputRow = 0; outputRow < rows; /*outputRow is incremented inside*/) + { + // Each iteration processes two packed 16-bit floats from the memory. + // Therefore, the sourceRow index increments once for every two outputRow. + GLint sourceRow = outputRow / 2; + // Calculate the linear index for the source data based on transpose mode. + const size_t sourceIndex = + transpose ? (sourceRow * kInputStride + col) : (col * kInputStride + sourceRow); + // Copy the two packed 16-bit float values from the source. + GLshort packedValues[2]; + memcpy(packedValues, &source[sourceIndex], sizeof(packedValues)); + + // Unpack and write the first value + // The destination is always treated as column-major. + size_t destIndex = col * rows + outputRow; + dataOut[destIndex] = gl::float16ToFloat32(packedValues[0]); + outputRow++; + + // Unpack and write the second value (if it fits in the destination) + if (outputRow < rows) + { + destIndex = col * rows + outputRow; + dataOut[destIndex] = gl::float16ToFloat32(packedValues[1]); + outputRow++; + } + } + } + } + else + { + for (GLint col = 0; col < columns; ++col) + { + for (GLint row = 0; row < rows; ++row) + { + GLfloat *outptr = dataOut + ((col * rows) + row); + const GLfloat *inptr = + transpose ? source + ((row * 4) + col) : source + ((col * 4) + row); + *outptr = *inptr; + } } } } template -void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose) +void GetMatrixUniform(GLenum type, + NonFloatT *dataOut, + const NonFloatT *source, + bool transpose, + bool isFloat16) { UNREACHABLE(); } @@ -1028,17 +1215,39 @@ BufferAndLayout::BufferAndLayout() = default; BufferAndLayout::~BufferAndLayout() = default; template -void UpdateBufferWithLayout(GLsizei count, - uint32_t arrayIndex, - int componentCount, - const T *v, - const sh::BlockMemberInfo &layoutInfo, - angle::MemoryBuffer *uniformData) +ANGLE_NOINLINE void UpdateBufferWithLayoutStrided(GLsizei count, + uint32_t arrayIndex, + int componentCount, + const T *v, + const sh::BlockMemberInfo &layoutInfo, + angle::MemoryBuffer *uniformData) { const int elementSize = sizeof(T) * componentCount; + uint8_t *dst = uniformData->data() + layoutInfo.offset; + int maxIndex = arrayIndex + count; + for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex; + writeIndex++, readIndex++) + { + const int arrayOffset = writeIndex * layoutInfo.arrayStride; + uint8_t *writePtr = dst + arrayOffset; + const T *readPtr = v + (readIndex * componentCount); + ASSERT(writePtr + elementSize <= uniformData->data() + uniformData->size()); + memcpy(writePtr, readPtr, elementSize); + } +} +template +ANGLE_INLINE void UpdateBufferWithLayout(GLsizei count, + uint32_t arrayIndex, + int componentCount, + const T *v, + const sh::BlockMemberInfo &layoutInfo, + angle::MemoryBuffer *uniformData) +{ + const int elementSize = sizeof(T) * componentCount; uint8_t *dst = uniformData->data() + layoutInfo.offset; - if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize) + if (ANGLE_LIKELY(layoutInfo.arrayStride == 0) || + ANGLE_LIKELY(layoutInfo.arrayStride == elementSize)) { uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride; uint8_t *writePtr = dst + arrayOffset; @@ -1048,16 +1257,8 @@ void UpdateBufferWithLayout(GLsizei count, else { // Have to respect the arrayStride between each element of the array. - int maxIndex = arrayIndex + count; - for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex; - writeIndex++, readIndex++) - { - const int arrayOffset = writeIndex * layoutInfo.arrayStride; - uint8_t *writePtr = dst + arrayOffset; - const T *readPtr = v + (readIndex * componentCount); - ASSERT(writePtr + elementSize <= uniformData->data() + uniformData->size()); - memcpy(writePtr, readPtr, elementSize); - } + UpdateBufferWithLayoutStrided(count, arrayIndex, componentCount, v, layoutInfo, + uniformData); } } @@ -1066,24 +1267,79 @@ void ReadFromBufferWithLayout(int componentCount, uint32_t arrayIndex, T *dst, const sh::BlockMemberInfo &layoutInfo, - const angle::MemoryBuffer *uniformData) + const angle::MemoryBuffer *uniformData, + bool isFloat16) { ASSERT(layoutInfo.offset != -1); const int elementSize = sizeof(T) * componentCount; - const uint8_t *source = uniformData->data() + layoutInfo.offset; - - if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize) + const uint8_t *source = uniformData->data() + layoutInfo.offset; + const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride; + // Special case when the expected data read back is GLfloat, it is possible we need to + // transform the data in memory from GLshort to GLfloat. + if constexpr (std::is_same::value) { - const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride; - memcpy(dst, readPtr, elementSize); + if (isFloat16) + { + // check that dst is aligned to 4 bytes (size of GLfloat) + ASSERT(reinterpret_cast(dst) % 4 == 0); + // check that readPtr is aligned to 2 bytes (size of GLshort) + ASSERT(reinterpret_cast(readPtr) % 2 == 0); + const GLshort *transformedValues = reinterpret_cast(readPtr); + for (size_t index = 0; index < static_cast(componentCount); ++index) + { + dst[index] = gl::float16ToFloat32(transformedValues[index]); + } + // skip the generic case below + return; + } } - else + // Generic case where no data transform is needed + memcpy(dst, readPtr, elementSize); +} + +template +ANGLE_NOINLINE void SetUniformAsBool(const gl::ProgramExecutable *executable, + GLint location, + GLsizei count, + const T *v, + GLenum entryPointType, + DefaultUniformBlockMap *defaultUniformBlocks, + gl::ShaderBitSet *defaultUniformBlocksDirty) +{ + const gl::VariableLocation &locationInfo = executable->getUniformLocations()[location]; + const gl::LinkedUniform &linkedUniform = executable->getUniforms()[locationInfo.index]; + + for (const gl::ShaderType shaderType : executable->getLinkedShaderStages()) { - // Have to respect the arrayStride between each element of the array. - const int arrayOffset = arrayIndex * layoutInfo.arrayStride; - const uint8_t *readPtr = source + arrayOffset; - memcpy(dst, readPtr, elementSize); + BufferAndLayout &uniformBlock = *(*defaultUniformBlocks)[shaderType]; + const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location]; + + // Assume an offset of -1 means the block is unused. + if (layoutInfo.offset == -1) + { + continue; + } + + const GLint componentCount = linkedUniform.getElementComponents(); + + ASSERT(linkedUniform.getType() == gl::VariableBoolVectorType(entryPointType)); + + GLint initialArrayOffset = + locationInfo.arrayIndex * layoutInfo.arrayStride + layoutInfo.offset; + for (GLint i = 0; i < count; i++) + { + GLint elementOffset = i * layoutInfo.arrayStride + initialArrayOffset; + GLint *dst = reinterpret_cast(uniformBlock.uniformData.data() + elementOffset); + const T *source = v + i * componentCount; + + for (int c = 0; c < componentCount; c++) + { + dst[c] = (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE; + } + } + + defaultUniformBlocksDirty->set(shaderType); } } @@ -1101,8 +1357,69 @@ void SetUniform(const gl::ProgramExecutable *executable, ASSERT(!linkedUniform.isSampler()); - if (linkedUniform.getType() == entryPointType) + if (ANGLE_LIKELY(linkedUniform.getType() == entryPointType)) { + const GLint componentCount = linkedUniform.getElementComponents(); + if constexpr (std::is_same::value) + { + if (linkedUniform.isFloat16()) + { + // Special case where we need to transform the 32-bit float to 16-bit float before + // storing. + for (const gl::ShaderType shaderType : executable->getLinkedShaderStages()) + { + BufferAndLayout &uniformBlock = *(*defaultUniformBlocks)[shaderType]; + const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location]; + + // Assume an offset of -1 means the block is unused. + if (layoutInfo.offset == -1) + { + continue; + } + + const int elementSize = sizeof(GLshort) * componentCount; + uint8_t *dst = uniformBlock.uniformData.data() + layoutInfo.offset; + int maxIndex = locationInfo.arrayIndex + count; + for (int writeIndex = locationInfo.arrayIndex, readIndex = 0; + writeIndex < maxIndex; writeIndex++, readIndex++) + { + const int arrayOffset = writeIndex * layoutInfo.arrayStride; + uint8_t *writePtr = dst + arrayOffset; + // check that writePtr is aligned to 2 bytes (size of GLshort) + ASSERT(reinterpret_cast(writePtr) % 2 == 0); + const GLfloat *readPtr = v + (readIndex * componentCount); + // check that readPtr is aligned to 4 bytes (size of GLfloat) + ASSERT(reinterpret_cast(readPtr) % 4 == 0); + // Ensure the uniformBlock.uniformData has enough space + ASSERT(writePtr + elementSize <= + uniformBlock.uniformData.data() + uniformBlock.uniformData.size()); + // Transform each original GLfloat data to GLshort + GLshort *dstGLShortPtr = reinterpret_cast(writePtr); + for (int componentIndex = 0; componentIndex < componentCount; + ++componentIndex) + { + dstGLShortPtr[componentIndex] = + gl::float32ToFloat16(readPtr[componentIndex]); + } + // Add paddings of 0 if the next item written to the destination memory is + // not tightly packed to the current item + if (writeIndex + 1 < maxIndex) + { + const int paddingSize = (writeIndex + 1) * layoutInfo.arrayStride - + arrayOffset - elementSize; + if (paddingSize > 0) + { + memset(writePtr + elementSize, 0, paddingSize); + } + } + } + defaultUniformBlocksDirty->set(shaderType); + } + // Skip the generic case below + return; + } + } + // Generic case where data transformation is not required for (const gl::ShaderType shaderType : executable->getLinkedShaderStages()) { BufferAndLayout &uniformBlock = *(*defaultUniformBlocks)[shaderType]; @@ -1114,7 +1431,6 @@ void SetUniform(const gl::ProgramExecutable *executable, continue; } - const GLint componentCount = linkedUniform.getElementComponents(); UpdateBufferWithLayout(count, locationInfo.arrayIndex, componentCount, v, layoutInfo, &uniformBlock.uniformData); defaultUniformBlocksDirty->set(shaderType); @@ -1122,38 +1438,8 @@ void SetUniform(const gl::ProgramExecutable *executable, } else { - for (const gl::ShaderType shaderType : executable->getLinkedShaderStages()) - { - BufferAndLayout &uniformBlock = *(*defaultUniformBlocks)[shaderType]; - const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location]; - - // Assume an offset of -1 means the block is unused. - if (layoutInfo.offset == -1) - { - continue; - } - - const GLint componentCount = linkedUniform.getElementComponents(); - - ASSERT(linkedUniform.getType() == gl::VariableBoolVectorType(entryPointType)); - - GLint initialArrayOffset = - locationInfo.arrayIndex * layoutInfo.arrayStride + layoutInfo.offset; - for (GLint i = 0; i < count; i++) - { - GLint elementOffset = i * layoutInfo.arrayStride + initialArrayOffset; - GLint *dst = - reinterpret_cast(uniformBlock.uniformData.data() + elementOffset); - const T *source = v + i * componentCount; - - for (int c = 0; c < componentCount; c++) - { - dst[c] = (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE; - } - } - - defaultUniformBlocksDirty->set(shaderType); - } + SetUniformAsBool(executable, location, count, v, entryPointType, defaultUniformBlocks, + defaultUniformBlocksDirty); } } template void SetUniform(const gl::ProgramExecutable *executable, @@ -1203,7 +1489,7 @@ void SetUniformMatrixfv(const gl::ProgramExecutable *executable, SetFloatUniformMatrixGLSL::Run( locationInfo.arrayIndex, linkedUniform.getBasicTypeElementCount(), count, transpose, - value, uniformBlock.uniformData.data() + layoutInfo.offset); + value, uniformBlock.uniformData.data() + layoutInfo.offset, linkedUniform.isFloat16()); defaultUniformBlocksDirty->set(shaderType); } @@ -1251,12 +1537,12 @@ void GetUniform(const gl::ProgramExecutable *executable, const uint8_t *ptrToElement = uniformBlock.uniformData.data() + layoutInfo.offset + (locationInfo.arrayIndex * layoutInfo.arrayStride); GetMatrixUniform(linkedUniform.getType(), v, reinterpret_cast(ptrToElement), - false); + false, linkedUniform.isFloat16()); } else { ReadFromBufferWithLayout(linkedUniform.getElementComponents(), locationInfo.arrayIndex, v, - layoutInfo, &uniformBlock.uniformData); + layoutInfo, &uniformBlock.uniformData, linkedUniform.isFloat16()); } } @@ -1288,15 +1574,10 @@ angle::Result ComputeStartVertex(ContextImpl *contextImpl, GLint baseVertex, GLint *firstVertexOut) { - // The entire index range should be within the limits of a 32-bit uint because the largest - // GL index type is GL_UNSIGNED_INT. - ASSERT(indexRange.start <= std::numeric_limits::max() && - indexRange.end <= std::numeric_limits::max()); - // The base vertex is only used in DrawElementsIndirect. Given the assertion above and the // type of mBaseVertex (GLint), adding them both as 64-bit ints is safe. int64_t startVertexInt64 = - static_cast(baseVertex) + static_cast(indexRange.start); + static_cast(baseVertex) + static_cast(indexRange.start()); // OpenGL ES 3.2 spec section 10.5: "Behavior of DrawElementsOneInstance is undefined if the // vertex ID is negative for any element" @@ -1326,7 +1607,8 @@ angle::Result GetVertexRangeInfo(const gl::Context *context, { gl::IndexRange indexRange; ANGLE_TRY(context->getState().getVertexArray()->getIndexRange( - context, indexTypeOrInvalid, vertexOrIndexCount, indices, &indexRange)); + context, indexTypeOrInvalid, vertexOrIndexCount, indices, + context->getState().isPrimitiveRestartEnabled(), &indexRange)); ANGLE_TRY(ComputeStartVertex(context->getImplementation(), indexRange, baseVertex, startVertexOut)); *vertexCountOut = indexRange.vertexCount(); @@ -1367,37 +1649,13 @@ gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &r return clippedRect; } -void LogFeatureStatus(const angle::FeatureSetBase &features, - const std::vector &featureNames, - bool enabled) -{ - for (const std::string &name : featureNames) - { - const bool hasWildcard = name.back() == '*'; - for (auto iter : features.getFeatures()) - { - const std::string &featureName = iter.first; - - if (!angle::FeatureNameMatch(featureName, name)) - { - continue; - } - - INFO() << "Feature: " << featureName << (enabled ? " enabled" : " disabled"); - - if (!hasWildcard) - { - break; - } - } - } -} - void ApplyFeatureOverrides(angle::FeatureSetBase *features, const angle::FeatureOverrides &overrides) { - features->overrideFeatures(overrides.enabled, true); - features->overrideFeatures(overrides.disabled, false); + std::stringstream featureStream; + + featureStream << features->overrideFeatures(overrides.enabled, true); + featureStream << features->overrideFeatures(overrides.disabled, false); // Override with environment as well. constexpr char kAngleFeatureOverridesEnabledEnvName[] = "ANGLE_FEATURE_OVERRIDES_ENABLED"; @@ -1413,11 +1671,42 @@ void ApplyFeatureOverrides(angle::FeatureSetBase *features, angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty( kAngleFeatureOverridesDisabledEnvName, kAngleFeatureOverridesDisabledPropertyName, ":"); - features->overrideFeatures(overridesEnabled, true); - LogFeatureStatus(*features, overridesEnabled, true); + featureStream << features->overrideFeatures(overridesEnabled, true); + featureStream << features->overrideFeatures(overridesDisabled, false); + + if (!featureStream.str().empty()) + { + INFO() << featureStream.str(); + } +} - features->overrideFeatures(overridesDisabled, false); - LogFeatureStatus(*features, overridesDisabled, false); +void StreamEmulatedLineLoopIndices(gl::DrawElementsType glIndexType, + GLsizei indexCount, + const uint8_t *srcPtr, + uint8_t *outPtr, + bool shouldConvertUint8) +{ + switch (glIndexType) + { + case gl::DrawElementsType::UnsignedByte: + if (shouldConvertUint8) + { + CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); + } + else + { + CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); + } + break; + case gl::DrawElementsType::UnsignedShort: + CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); + break; + case gl::DrawElementsType::UnsignedInt: + CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); + break; + default: + UNREACHABLE(); + } } void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy) @@ -1463,6 +1752,7 @@ void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy) #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \ do \ { \ + bool anyDraw = false; \ for (GLsizei drawID = 0; drawID < drawcount; ++drawID) \ { \ if (ANGLE_NOOP_DRAW(instanced)) \ @@ -1476,9 +1766,14 @@ void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy) ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi)); \ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \ gl::MarkShaderStorageUsage(context); \ + anyDraw = true; \ } \ /* reset the uniform to zero for non-multi-draw uses of the program */ \ ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(0); \ + if (!anyDraw) \ + { \ + ANGLE_TRY(contextImpl->handleNoopMultiDrawEvent()); \ + } \ } while (0) angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl, diff --git a/src/libANGLE/renderer/renderer_utils.h b/src/libANGLE/renderer/renderer_utils.h index e90d9e4fe09..e38916cc2a1 100644 --- a/src/libANGLE/renderer/renderer_utils.h +++ b/src/libANGLE/renderer/renderer_utils.h @@ -10,6 +10,10 @@ #ifndef LIBANGLE_RENDERER_RENDERER_UTILS_H_ #define LIBANGLE_RENDERER_RENDERER_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -73,10 +77,10 @@ bool IsRotatedAspectRatio(SurfaceRotation rotation); using SpecConstUsageBits = angle::PackedEnumBitSet; -void RotateRectangle(const SurfaceRotation rotation, - const bool flipY, - const int framebufferWidth, - const int framebufferHeight, +void RotateRectangle(SurfaceRotation rotation, + bool flipY, + int framebufferWidth, + int framebufferHeight, const gl::Rectangle &incoming, gl::Rectangle *outgoing); @@ -226,8 +230,8 @@ class MultisampleTextureInitializer class IncompleteTextureSet final : angle::NonCopyable { public: - IncompleteTextureSet(); - ~IncompleteTextureSet(); + IncompleteTextureSet() = default; + ~IncompleteTextureSet() = default; void onDestroy(const gl::Context *context); @@ -253,7 +257,8 @@ struct SetFloatUniformMatrixGLSL GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData); + uint8_t *targetData, + bool isFloat16); }; template @@ -264,14 +269,23 @@ struct SetFloatUniformMatrixHLSL GLsizei countIn, GLboolean transpose, const GLfloat *value, - uint8_t *targetData); + uint8_t *targetData, + bool isFloat16); }; // Helper method to de-tranpose a matrix uniform for an API query. -void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose); +void GetMatrixUniform(GLenum type, + GLfloat *dataOut, + const GLfloat *source, + bool transpose, + bool isFloat16); template -void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose); +void GetMatrixUniform(GLenum type, + NonFloatT *dataOut, + const NonFloatT *source, + bool transpose, + bool isFloat16); // Contains a CPU-side buffer and its data layout, used as a shadow buffer for default uniform // blocks in VK and WGPU backends. @@ -301,7 +315,8 @@ void ReadFromBufferWithLayout(int componentCount, uint32_t arrayIndex, T *dst, const sh::BlockMemberInfo &layoutInfo, - const angle::MemoryBuffer *uniformData); + const angle::MemoryBuffer *uniformData, + bool isFloat16); using DefaultUniformBlockMap = gl::ShaderMap>; @@ -408,8 +423,9 @@ inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexTyp // Writes the line-strip vertices for a line loop to outPtr, // where outLimit is calculated as in GetPrimitiveRestartIndexCount. +// Returns number of vertices written. template -void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr) +size_t CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr) { constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType(); constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType(); @@ -443,8 +459,15 @@ void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, u // Close the last loop if it has more than one vertex. *(outIndices++) = inIndices[loopStartIndex]; } + return static_cast(outIndices - reinterpret_cast(outPtr)); } +void StreamEmulatedLineLoopIndices(gl::DrawElementsType glIndexType, + GLsizei indexCount, + const uint8_t *srcPtr, + uint8_t *outPtr, + bool shouldConvertUint8); + void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy); angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl, @@ -540,6 +563,13 @@ GLint LimitToInt(const LargerInt physicalDeviceValue) std::min(physicalDeviceValue, static_cast(std::numeric_limits::max()))); } +template +GLint LimitToIntAnd(const LargerInt physicalDeviceValue, const uint64_t cap) +{ + LargerInt result = LimitToInt(physicalDeviceValue); + return static_cast(std::min(static_cast(result), cap)); +} + bool TextureHasAnyRedefinedLevels(const gl::CubeFaceArray &redefinedLevels); bool IsTextureLevelRedefined(const gl::CubeFaceArray &redefinedLevels, gl::TextureType textureType, diff --git a/src/libANGLE/renderer/serial_utils.h b/src/libANGLE/renderer/serial_utils.h index 7146690c95a..beeb7c80689 100644 --- a/src/libANGLE/renderer/serial_utils.h +++ b/src/libANGLE/renderer/serial_utils.h @@ -10,6 +10,7 @@ #ifndef LIBANGLE_RENDERER_SERIAL_UTILS_H_ #define LIBANGLE_RENDERER_SERIAL_UTILS_H_ +#include #include #include #include diff --git a/src/libANGLE/renderer/vulkan/AllocatorHelperPool.cpp b/src/libANGLE/renderer/vulkan/AllocatorHelperPool.cpp index 26cb0aaa704..c7ea21b169c 100644 --- a/src/libANGLE/renderer/vulkan/AllocatorHelperPool.cpp +++ b/src/libANGLE/renderer/vulkan/AllocatorHelperPool.cpp @@ -17,8 +17,7 @@ namespace vk void DedicatedCommandBlockAllocator::resetAllocator() { - mAllocator.pop(); - mAllocator.push(); + mAllocator.reset(); } void DedicatedCommandBlockPool::reset(CommandBufferCommandTracker *commandBufferTracker) diff --git a/src/libANGLE/renderer/vulkan/AllocatorHelperPool.h b/src/libANGLE/renderer/vulkan/AllocatorHelperPool.h index e1a2cdcc10b..ea37c1e3304 100644 --- a/src/libANGLE/renderer/vulkan/AllocatorHelperPool.h +++ b/src/libANGLE/renderer/vulkan/AllocatorHelperPool.h @@ -10,6 +10,10 @@ #ifndef LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERPOOL_H_ #define LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERPOOL_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/PoolAlloc.h" #include "common/vulkan/vk_headers.h" #include "libANGLE/renderer/vulkan/vk_command_buffer_utils.h" @@ -32,26 +36,14 @@ class DedicatedCommandBlockAllocator public: DedicatedCommandBlockAllocator() = default; void resetAllocator(); - bool hasAllocatorLinks() const { return false; } - - static constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024; - void init() - { - mAllocator.initialize(kDefaultPoolAllocatorPageSize, 1); - // Push a scope into the pool allocator so we can easily free and re-init on reset() - mAllocator.push(); - } - - // Placeholder functions for attaching and detaching the allocator. - void attachAllocator(DedicatedCommandMemoryAllocator *allocator) {} - DedicatedCommandMemoryAllocator *detachAllocator(bool isCommandBufferEmpty) { return nullptr; } DedicatedCommandMemoryAllocator *getAllocator() { return &mAllocator; } private: + static constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024; // Using a pool allocator per CBH to avoid threading issues that occur w/ shared allocator // between multiple CBHs. - DedicatedCommandMemoryAllocator mAllocator; + DedicatedCommandMemoryAllocator mAllocator{kDefaultPoolAllocatorPageSize, 1}; }; // Used in SecondaryCommandBuffer @@ -125,11 +117,6 @@ class DedicatedCommandBlockPool final *headerOut = updateHeaderAndAllocatorParams(allocationSize); } - // Placeholder functions - void terminateLastCommandBlock() {} - void attachAllocator(vk::DedicatedCommandMemoryAllocator *source) {} - void detachAllocator(vk::DedicatedCommandMemoryAllocator *destination) {} - private: void allocateNewBlock(size_t blockSize = kBlockSize); diff --git a/src/libANGLE/renderer/vulkan/AllocatorHelperRing.cpp b/src/libANGLE/renderer/vulkan/AllocatorHelperRing.cpp deleted file mode 100644 index 3b73fb303b6..00000000000 --- a/src/libANGLE/renderer/vulkan/AllocatorHelperRing.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// Copyright 2022 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. -// -// AllocatorHelperRing: -// Implements the ring buffer allocator helpers used in the command buffers. -// - -#include "libANGLE/renderer/vulkan/AllocatorHelperRing.h" -#include "libANGLE/renderer/vulkan/SecondaryCommandBuffer.h" - -namespace rx -{ -namespace vk -{ - -void SharedCommandBlockAllocator::resetAllocator() -{ - ASSERT(!mAllocator || !mAllocator->isShared()); - - if (mAllocSharedCP) - { - mAllocSharedCP->releaseAndUpdate(&mAllocReleaseCP); - mAllocSharedCP = nullptr; - } - - ASSERT(!mAllocSharedCP && !mAllocReleaseCP.valid()); -} - -void SharedCommandBlockAllocator::attachAllocator(SharedCommandMemoryAllocator *allocator) -{ - ASSERT(allocator); - ASSERT(!mAllocator); - mAllocator = allocator; - if (mAllocator->isShared()) - { - mAllocator->releaseToSharedCP(); - } -} - -SharedCommandMemoryAllocator *SharedCommandBlockAllocator::detachAllocator( - bool isCommandBufferEmpty) -{ - ASSERT(mAllocator); - if (!isCommandBufferEmpty) - { - // Must call reset() after detach from non-empty command buffer (OK to have an empty RP) - ASSERT(!mAllocSharedCP && !mAllocReleaseCP.valid()); - mAllocSharedCP = mAllocator->acquireSharedCP(); - mAllocReleaseCP = mAllocator->get().getReleaseCheckPoint(); - } - SharedCommandMemoryAllocator *result = mAllocator; - mAllocator = nullptr; - return result; -} - -void SharedCommandBlockPool::attachAllocator(SharedCommandMemoryAllocator *source) -{ - ASSERT(source); - RingBufferAllocator &sourceIn = source->get(); - - ASSERT(sourceIn.valid()); - ASSERT(mCommandBuffer->hasEmptyCommands()); - ASSERT(mLastCommandBlock == nullptr); - ASSERT(mFinishedCommandSize == 0); - ASSERT(!mAllocator.valid()); - mAllocator = std::move(sourceIn); - mAllocator.setFragmentReserve(kCommandHeaderSize); - pushNewCommandBlock(mAllocator.allocate(0)); - mAllocator.setListener(this); -} - -void SharedCommandBlockPool::detachAllocator(SharedCommandMemoryAllocator *destination) -{ - ASSERT(destination); - RingBufferAllocator &destinationOut = destination->get(); - ASSERT(!destinationOut.valid()); - - ASSERT(mAllocator.valid()); - mAllocator.setListener(nullptr); - finishLastCommandBlock(); - if (mFinishedCommandSize == 0) - { - mCommandBuffer->clearCommands(); - } - else - { - mAllocator.setFragmentReserve(0); - (void)mAllocator.allocate(sizeof(kCommandHeaderSize)); - } - destinationOut = std::move(mAllocator); -} - -void SharedCommandBlockPool::pushNewCommandBlock(uint8_t *block) -{ - mLastCommandBlock = block; - mCommandBuffer->pushToCommands(block); -} - -void SharedCommandBlockPool::finishLastCommandBlock() -{ - mFinishedCommandSize = getCommandSize(); - terminateLastCommandBlock(); - mLastCommandBlock = nullptr; -} - -void SharedCommandBlockPool::onRingBufferNewFragment() -{ - pushNewCommandBlock(mAllocator.getPointer()); -} - -void SharedCommandBlockPool::onRingBufferFragmentEnd() -{ - finishLastCommandBlock(); -} - -void SharedCommandBlockPool::getMemoryUsageStats(size_t *usedMemoryOut, - size_t *allocatedMemoryOut) const -{ - *usedMemoryOut = getCommandSize(); - *allocatedMemoryOut = getCommandSize(); -} - -} // namespace vk -} // namespace rx diff --git a/src/libANGLE/renderer/vulkan/AllocatorHelperRing.h b/src/libANGLE/renderer/vulkan/AllocatorHelperRing.h deleted file mode 100644 index 75defd52fe2..00000000000 --- a/src/libANGLE/renderer/vulkan/AllocatorHelperRing.h +++ /dev/null @@ -1,160 +0,0 @@ -// -// Copyright 2022 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. -// -// AllocatorHelperRing: -// Manages the ring buffer allocators used in the command buffers. -// - -#ifndef LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERRING_H_ -#define LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERRING_H_ - -#include "common/RingBufferAllocator.h" -#include "common/vulkan/vk_headers.h" -#include "libANGLE/renderer/vulkan/vk_command_buffer_utils.h" -#include "libANGLE/renderer/vulkan/vk_wrapper.h" - -namespace rx -{ -namespace vk -{ -namespace priv -{ -class SecondaryCommandBuffer; -} // namespace priv - -using SharedCommandMemoryAllocator = angle::SharedRingBufferAllocator; -using RingBufferAllocator = angle::RingBufferAllocator; - -// Used in CommandBufferHelperCommon -class SharedCommandBlockAllocator -{ - public: - SharedCommandBlockAllocator() : mAllocator(nullptr), mAllocSharedCP(nullptr) {} - void resetAllocator(); - bool hasAllocatorLinks() const { return mAllocator || mAllocSharedCP; } - - void init() {} - - void attachAllocator(SharedCommandMemoryAllocator *allocator); - SharedCommandMemoryAllocator *detachAllocator(bool isCommandBufferEmpty); - - SharedCommandMemoryAllocator *getAllocator() { return mAllocator; } - - private: - // Using a ring buffer allocator for less memory overhead (observed with the async queue - // ex-feature) - SharedCommandMemoryAllocator *mAllocator; - angle::SharedRingBufferAllocatorCheckPoint *mAllocSharedCP; - angle::RingBufferAllocatorCheckPoint mAllocReleaseCP; -}; - -// Used in SecondaryCommandBuffer -class SharedCommandBlockPool final : angle::RingBufferAllocateListener -{ - public: - SharedCommandBlockPool() - : mLastCommandBlock(nullptr), mFinishedCommandSize(0), mCommandBuffer(nullptr) - {} - - static constexpr size_t kCommandHeaderSize = 4; - using CommandHeaderIDType = uint16_t; - // Make sure the size of command header ID type is less than total command header size. - static_assert(sizeof(CommandHeaderIDType) < kCommandHeaderSize, "Check size of CommandHeader"); - - void setCommandBuffer(priv::SecondaryCommandBuffer *commandBuffer) - { - mCommandBuffer = commandBuffer; - } - void resetCommandBuffer() { mCommandBuffer = nullptr; } - - void reset(CommandBufferCommandTracker *commandBufferTracker) - { - mLastCommandBlock = nullptr; - mFinishedCommandSize = 0; - if (mAllocator.valid()) - { - mAllocator.release(mAllocator.getReleaseCheckPoint()); - pushNewCommandBlock(mAllocator.allocate(0)); - } - } - - angle::Result initialize(SharedCommandMemoryAllocator *allocator) - { - return angle::Result::Continue; - } - - // Always valid (even if allocator is detached). - bool valid() const { return true; } - bool empty() const { return getCommandSize() == 0; } - - void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const; - - void terminateLastCommandBlock() - { - if (mLastCommandBlock) - { - ASSERT(mAllocator.valid()); - ASSERT(mAllocator.getPointer() >= mLastCommandBlock); - ASSERT(mAllocator.getFragmentSize() >= kCommandHeaderSize); - reinterpret_cast(*(mAllocator.getPointer())) = 0; - } - } - - // Initialize the SecondaryCommandBuffer by setting the allocator it will use - void attachAllocator(SharedCommandMemoryAllocator *source); - void detachAllocator(SharedCommandMemoryAllocator *destination); - - void onNewVariableSizedCommand(const size_t requiredSize, - const size_t allocationSize, - uint8_t **headerOut) - { - *headerOut = allocateCommand(allocationSize); - } - void onNewCommand(const size_t requiredSize, const size_t allocationSize, uint8_t **headerOut) - { - *headerOut = allocateCommand(allocationSize); - } - - private: - uint8_t *allocateCommand(size_t allocationSize) - { - ASSERT(mLastCommandBlock); - return mAllocator.allocate(static_cast(allocationSize)); - } - - // The following is used to give the size of the command buffer in bytes - uint32_t getCommandSize() const - { - uint32_t result = mFinishedCommandSize; - if (mLastCommandBlock) - { - ASSERT(mAllocator.valid()); - ASSERT(mAllocator.getPointer() >= mLastCommandBlock); - result += static_cast(mAllocator.getPointer() - mLastCommandBlock); - } - return result; - } - - void pushNewCommandBlock(uint8_t *block); - void finishLastCommandBlock(); - - // Functions derived from RingBufferAllocateListener - virtual void onRingBufferNewFragment() override; - virtual void onRingBufferFragmentEnd() override; - - // Using a ring buffer allocator for less memory overhead (observed with the async queue - // ex-feature) - RingBufferAllocator mAllocator; - uint8_t *mLastCommandBlock; - uint32_t mFinishedCommandSize; - - // Points to the parent command buffer. - priv::SecondaryCommandBuffer *mCommandBuffer; -}; - -} // namespace vk -} // namespace rx - -#endif // LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERRING_H_ diff --git a/src/libANGLE/renderer/vulkan/BUILD.gn b/src/libANGLE/renderer/vulkan/BUILD.gn index b20197793ba..e37790b2eb5 100644 --- a/src/libANGLE/renderer/vulkan/BUILD.gn +++ b/src/libANGLE/renderer/vulkan/BUILD.gn @@ -16,8 +16,8 @@ declare_args() { # Enable custom (cpu-side) secondary command buffers angle_enable_custom_vulkan_cmd_buffers = true - # Enable Vulkan GPU trace event capability - angle_enable_vulkan_gpu_trace_events = false + # Enable compute only queue for OpenCL Vulkan backend + angle_enable_cl_compute_only_pipe = true } declare_args() { @@ -29,9 +29,6 @@ declare_args() { angle_enable_custom_vulkan_render_pass_cmd_buffers = angle_enable_custom_vulkan_cmd_buffers - # Enable shared ring buffer command buffer allocator - angle_enable_vulkan_shared_ring_buffer_cmd_alloc = false - # Enable using CRC for pipeline cache data angle_enable_crc_for_pipeline_cache = true } @@ -63,9 +60,6 @@ config("angle_vulkan_backend_config") { if (angle_enable_swiftshader) { defines += [ "ANGLE_ENABLE_SWIFTSHADER" ] } - if (angle_enable_vulkan_gpu_trace_events) { - defines += [ "ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS=1" ] - } if (angle_enable_vulkan_validation_layers) { defines += [ "ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS" ] } @@ -73,9 +67,6 @@ config("angle_vulkan_backend_config") { defines += [ "ANGLE_ENABLE_VULKAN_API_DUMP_LAYER" ] } - defines += [ "ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC=" + - "${angle_enable_vulkan_shared_ring_buffer_cmd_alloc}" ] - # Ensures that the memory allocation logging can only be enabled with debug layers. assert(angle_debug_layers_enabled || !angle_enable_memory_alloc_logging) if (angle_enable_memory_alloc_logging) { @@ -121,6 +112,7 @@ template("angle_vulkan_backend_template") { angle_source_set(target_name) { sources = vulkan_backend_sources libs = [] + defines = [] deps = [ ":angle_vk_mem_alloc_wrapper", "$angle_root:angle_abseil", @@ -149,6 +141,9 @@ template("angle_vulkan_backend_template") { "$angle_root/third_party/spirv-tools/src/include", "$angle_root/third_party/clspv/src/include", ] + if (angle_enable_cl_compute_only_pipe) { + defines += [ "ANGLE_OPENCL_COMPUTE_ONLY_PIPE" ] + } } public_deps = [ @@ -169,8 +164,6 @@ template("angle_vulkan_backend_template") { data_deps = [] - defines = [] - if (angle_enable_vulkan_validation_layers) { defines += [ "ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT" ] data_deps += [ "$angle_root/src/common/vulkan:vulkan_validation_layers" ] diff --git a/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/libANGLE/renderer/vulkan/BufferVk.cpp index 6eab24e9892..85e1d6395e2 100644 --- a/src/libANGLE/renderer/vulkan/BufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/BufferVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for BufferVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/BufferVk.h" #include "common/FixedVector.h" @@ -284,19 +288,19 @@ angle::Result CopyBuffers(ContextVk *contextVk, ASSERT(srcBuffer->valid() && dstBuffer->valid()); // Enqueue a copy command on the GPU - vk::CommandBufferAccess access; + vk::CommandResources resources; if (srcBuffer->getBufferSerial() == dstBuffer->getBufferSerial()) { - access.onBufferSelfCopy(srcBuffer); + resources.onBufferSelfCopy(srcBuffer); } else { - access.onBufferTransferRead(srcBuffer); - access.onBufferTransferWrite(dstBuffer); + resources.onBufferTransferRead(srcBuffer); + resources.onBufferTransferWrite(dstBuffer); } vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); commandBuffer->copyBuffer(srcBuffer->getBuffer(), dstBuffer->getBuffer(), regionCount, copyRegions); @@ -444,29 +448,26 @@ angle::Result BufferVk::setDataWithUsageFlags(const gl::Context *context, const void *data, size_t size, gl::BufferUsage usage, - GLbitfield flags) + GLbitfield flags, + gl::BufferStorage bufferStorage, + BufferFeedback *feedback) { ContextVk *contextVk = vk::GetImpl(context); VkMemoryPropertyFlags memoryPropertyFlags = 0; bool persistentMapRequired = false; const bool isExternalBuffer = clientBuffer != nullptr; - switch (usage) + if (bufferStorage == gl::BufferStorage::Immutable) { - case gl::BufferUsage::InvalidEnum: - { - // glBufferStorage API call - memoryPropertyFlags = - GetStorageMemoryType(contextVk->getRenderer(), flags, isExternalBuffer); - persistentMapRequired = (flags & GL_MAP_PERSISTENT_BIT_EXT) != 0; - break; - } - default: - { - // glBufferData API call - memoryPropertyFlags = GetPreferredMemoryType(contextVk->getRenderer(), target, usage); - break; - } + // glBufferStorage API call + memoryPropertyFlags = + GetStorageMemoryType(contextVk->getRenderer(), flags, isExternalBuffer); + persistentMapRequired = (flags & GL_MAP_PERSISTENT_BIT_EXT) != 0; + } + else + { + // glBufferData API call + memoryPropertyFlags = GetPreferredMemoryType(contextVk->getRenderer(), target, usage); } if (isExternalBuffer) @@ -483,20 +484,21 @@ angle::Result BufferVk::setDataWithUsageFlags(const gl::Context *context, return angle::Result::Continue; } - return setDataWithMemoryType(context, target, data, size, memoryPropertyFlags, usage); + return setDataWithMemoryType(context, target, data, size, memoryPropertyFlags, usage, feedback); } angle::Result BufferVk::setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { ContextVk *contextVk = vk::GetImpl(context); // Assume host visible/coherent memory available. VkMemoryPropertyFlags memoryPropertyFlags = GetPreferredMemoryType(contextVk->getRenderer(), target, usage); - return setDataWithMemoryType(context, target, data, size, memoryPropertyFlags, usage); + return setDataWithMemoryType(context, target, data, size, memoryPropertyFlags, usage, feedback); } angle::Result BufferVk::setDataWithMemoryType(const gl::Context *context, @@ -504,7 +506,8 @@ angle::Result BufferVk::setDataWithMemoryType(const gl::Context *context, const void *data, size_t size, VkMemoryPropertyFlags memoryPropertyFlags, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { ContextVk *contextVk = vk::GetImpl(context); vk::Renderer *renderer = contextVk->getRenderer(); @@ -537,7 +540,7 @@ angle::Result BufferVk::setDataWithMemoryType(const gl::Context *context, mUsageType = usageType; mMemoryPropertyFlags = memoryPropertyFlags; ANGLE_TRY(GetMemoryTypeIndex(contextVk, size, memoryPropertyFlags, &mMemoryTypeIndex)); - ANGLE_TRY(acquireBufferHelper(contextVk, size, mUsageType)); + ANGLE_TRY(acquireBufferHelper(contextVk, size, mUsageType, feedback)); } else if (size != static_cast(mState.getSize())) { @@ -549,7 +552,7 @@ angle::Result BufferVk::setDataWithMemoryType(const gl::Context *context, // vertex array. The reason vertex array is observing the buffer's storage change is // because they uses VkBuffer. Now VkBuffer have changed, vertex array needs to // re-process it just like storage has been reallocated. - onStateChange(angle::SubjectMessage::InternalMemoryAllocationChanged); + internalMemoryAllocationChanged(feedback); } } @@ -559,7 +562,7 @@ angle::Result BufferVk::setDataWithMemoryType(const gl::Context *context, dataSource.data = data; // Handle full-buffer updates similarly to glBufferSubData - ANGLE_TRY(setDataImpl(contextVk, size, dataSource, size, 0, updateType)); + ANGLE_TRY(setDataImpl(contextVk, size, dataSource, size, 0, updateType, feedback)); } return angle::Result::Continue; @@ -569,7 +572,8 @@ angle::Result BufferVk::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { ASSERT(mBuffer.valid()); @@ -578,14 +582,15 @@ angle::Result BufferVk::setSubData(const gl::Context *context, ContextVk *contextVk = vk::GetImpl(context); return setDataImpl(contextVk, static_cast(mState.getSize()), dataSource, size, offset, - BufferUpdateType::ContentsUpdate); + BufferUpdateType::ContentsUpdate, feedback); } angle::Result BufferVk::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { ASSERT(mBuffer.valid()); @@ -599,7 +604,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ASSERT(dataSource.buffer->valid()); return setDataImpl(contextVk, static_cast(mState.getSize()), dataSource, size, - destOffset, BufferUpdateType::ContentsUpdate); + destOffset, BufferUpdateType::ContentsUpdate, feedback); } angle::Result BufferVk::allocStagingBuffer(ContextVk *contextVk, @@ -664,7 +669,7 @@ angle::Result BufferVk::handleDeviceLocalBufferMap(ContextVk *contextVk, VkBufferCopy copyRegion = {mBuffer.getOffset() + offset, mStagingBuffer.getOffset(), size}; ANGLE_TRY(CopyBuffers(contextVk, &mBuffer, &mStagingBuffer, 1, ©Region)); ANGLE_TRY(mStagingBuffer.waitForIdle(contextVk, "GPU stall due to mapping device local buffer", - RenderPassClosureReason::DeviceLocalBufferMap)); + QueueSubmitReason::DeviceLocalBufferMap)); // Since coherent is prefer, we may end up getting non-coherent. Always call invalidate here (it // will check memory flag before it actually calls into driver). ANGLE_TRY(mStagingBuffer.invalidate(renderer)); @@ -687,33 +692,42 @@ angle::Result BufferVk::mapHostVisibleBuffer(ContextVk *contextVk, return angle::Result::Continue; } -angle::Result BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result BufferVk::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { ASSERT(mBuffer.valid()); ASSERT(access == GL_WRITE_ONLY_OES); - return mapImpl(vk::GetImpl(context), GL_MAP_WRITE_BIT, mapPtr); + return mapImpl(vk::GetImpl(context), GL_MAP_WRITE_BIT, mapPtr, feedback); } angle::Result BufferVk::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { - return mapRangeImpl(vk::GetImpl(context), offset, length, access, mapPtr); + return mapRangeImpl(vk::GetImpl(context), offset, length, access, mapPtr, feedback); } -angle::Result BufferVk::mapImpl(ContextVk *contextVk, GLbitfield access, void **mapPtr) +angle::Result BufferVk::mapImpl(ContextVk *contextVk, + GLbitfield access, + void **mapPtr, + BufferFeedback *feedback) { - return mapRangeImpl(contextVk, 0, static_cast(mState.getSize()), access, mapPtr); + return mapRangeImpl(contextVk, 0, static_cast(mState.getSize()), access, mapPtr, + feedback); } angle::Result BufferVk::ghostMappedBuffer(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { // We shouldn't get here if it is external memory ASSERT(!isExternalBuffer()); @@ -725,7 +739,7 @@ angle::Result BufferVk::ghostMappedBuffer(ContextVk *contextVk, // case the caller only updates a portion of the new buffer. vk::BufferHelper src = std::move(mBuffer); ANGLE_TRY(acquireBufferHelper(contextVk, static_cast(mState.getSize()), - BufferUsageType::Dynamic)); + BufferUsageType::Dynamic, feedback)); // Before returning the new buffer, map the previous buffer and copy its entire // contents into the new buffer. @@ -769,7 +783,8 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { vk::Renderer *renderer = contextVk->getRenderer(); ASSERT(mBuffer.valid()); @@ -802,8 +817,8 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, // If there are unflushed write commands for the resource, flush them. if (contextVk->hasUnsubmittedUse(mBuffer.getWriteResourceUse())) { - ANGLE_TRY(contextVk->flushAndSubmitCommands( - nullptr, nullptr, RenderPassClosureReason::BufferWriteThenMap)); + ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, nullptr, + QueueSubmitReason::BufferWriteThenMap)); } ANGLE_TRY(renderer->finishResourceUse(contextVk, mBuffer.getWriteResourceUse())); } @@ -841,7 +856,7 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, if (entireBufferInvalidated) { ANGLE_TRY(acquireBufferHelper(contextVk, static_cast(mState.getSize()), - BufferUsageType::Dynamic)); + BufferUsageType::Dynamic, feedback)); return mapHostVisibleBuffer(contextVk, offset, access, mapPtrBytes); } @@ -857,18 +872,20 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, if (renderer->hasResourceUseFinished(mBuffer.getWriteResourceUse())) { // This will keep the new buffer mapped and update mapPtr, so return immediately. - return ghostMappedBuffer(contextVk, offset, length, access, mapPtr); + return ghostMappedBuffer(contextVk, offset, length, access, mapPtr, feedback); } // Write case (worst case, buffer in use for write) ANGLE_TRY(mBuffer.waitForIdle(contextVk, "GPU stall due to mapping buffer in use by the GPU", - RenderPassClosureReason::BufferInUseWhenSynchronizedMap)); + QueueSubmitReason::BufferInUseWhenSynchronizedMap)); return mapHostVisibleBuffer(contextVk, offset, access, mapPtrBytes); } -angle::Result BufferVk::unmap(const gl::Context *context, GLboolean *result) +angle::Result BufferVk::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { - ANGLE_TRY(unmapImpl(vk::GetImpl(context))); + ANGLE_TRY(unmapImpl(vk::GetImpl(context), feedback)); // This should be false if the contents have been corrupted through external means. Vulkan // doesn't provide such information. @@ -877,7 +894,7 @@ angle::Result BufferVk::unmap(const gl::Context *context, GLboolean *result) return angle::Result::Continue; } -angle::Result BufferVk::unmapImpl(ContextVk *contextVk) +angle::Result BufferVk::unmapImpl(ContextVk *contextVk, BufferFeedback *feedback) { ASSERT(mBuffer.valid()); @@ -931,9 +948,9 @@ angle::Result BufferVk::getSubData(const gl::Context *context, ASSERT(mBuffer.valid()); ContextVk *contextVk = vk::GetImpl(context); void *mapPtr; - ANGLE_TRY(mapRangeImpl(contextVk, offset, size, GL_MAP_READ_BIT, &mapPtr)); + ANGLE_TRY(mapRangeForReadAccessOnly(contextVk, offset, size, &mapPtr)); memcpy(outData, mapPtr, size); - return unmapImpl(contextVk); + return unmapReadAccessOnly(contextVk); } angle::Result BufferVk::getIndexRange(const gl::Context *context, @@ -950,17 +967,16 @@ angle::Result BufferVk::getIndexRange(const gl::Context *context, // Could be removed if https://github.com/KhronosGroup/Vulkan-Tools/issues/84 is fixed. if (renderer->isMockICDEnabled()) { - outRange->start = 0; - outRange->end = 0; + *outRange = {}; return angle::Result::Continue; } ANGLE_TRACE_EVENT0("gpu.angle", "BufferVk::getIndexRange"); void *mapPtr; - ANGLE_TRY(mapRangeImpl(contextVk, offset, getSize(), GL_MAP_READ_BIT, &mapPtr)); + ANGLE_TRY(mapRangeForReadAccessOnly(contextVk, offset, getSize(), &mapPtr)); *outRange = gl::ComputeIndexRange(type, mapPtr, count, primitiveRestartEnabled); - ANGLE_TRY(unmapImpl(contextVk)); + ANGLE_TRY(unmapReadAccessOnly(contextVk)); return angle::Result::Continue; } @@ -1062,19 +1078,19 @@ angle::Result BufferVk::stagedUpdate(ContextVk *contextVk, else { // Check for self-dependency. - vk::CommandBufferAccess access; + vk::CommandResources resources; if (dataSource.buffer->getBufferSerial() == mBuffer.getBufferSerial()) { - access.onBufferSelfCopy(&mBuffer); + resources.onBufferSelfCopy(&mBuffer); } else { - access.onBufferTransferRead(dataSource.buffer); - access.onBufferTransferWrite(&mBuffer); + resources.onBufferTransferRead(dataSource.buffer); + resources.onBufferTransferWrite(&mBuffer); } vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Enqueue a copy command on the GPU. const VkBufferCopy copyRegion = {dataSource.bufferOffset + dataSource.buffer->getOffset(), @@ -1093,7 +1109,8 @@ angle::Result BufferVk::acquireAndUpdate(ContextVk *contextVk, const BufferDataSource &dataSource, size_t updateSize, size_t updateOffset, - BufferUpdateType updateType) + BufferUpdateType updateType, + BufferFeedback *feedback) { // We shouldn't get here if this is external memory ASSERT(!isExternalBuffer()); @@ -1132,7 +1149,7 @@ angle::Result BufferVk::acquireAndUpdate(ContextVk *contextVk, } } - ANGLE_TRY(acquireBufferHelper(contextVk, bufferSize, BufferUsageType::Dynamic)); + ANGLE_TRY(acquireBufferHelper(contextVk, bufferSize, BufferUsageType::Dynamic, feedback)); ANGLE_TRY(updateBuffer(contextVk, bufferSize, dataSource, updateSize, updateOffset)); constexpr int kMaxCopyRegions = 2; @@ -1189,7 +1206,8 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk, const BufferDataSource &dataSource, size_t updateSize, size_t updateOffset, - BufferUpdateType updateType) + BufferUpdateType updateType, + BufferFeedback *feedback) { // if the buffer is currently in use // if it isn't an external buffer and not a self-copy and sub data size meets threshold @@ -1232,7 +1250,7 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk, ShouldAllocateNewMemoryForUpdate(contextVk, updateSize, bufferSize))) { ANGLE_TRY(acquireAndUpdate(contextVk, bufferSize, dataSource, updateSize, updateOffset, - updateType)); + updateType, feedback)); } else { @@ -1307,7 +1325,8 @@ void BufferVk::onDataChanged() angle::Result BufferVk::acquireBufferHelper(ContextVk *contextVk, size_t sizeInBytes, - BufferUsageType usageType) + BufferUsageType usageType, + BufferFeedback *feedback) { vk::Renderer *renderer = contextVk->getRenderer(); size_t size = roundUpPow2(sizeInBytes, kBufferSizeGranularity); @@ -1326,7 +1345,7 @@ angle::Result BufferVk::acquireBufferHelper(ContextVk *contextVk, // dirty bits can be set. This allows the buffer views pointing to the old buffer to // be recreated and point to the new buffer, along with updating the descriptor sets // to use the new buffer. - onStateChange(angle::SubjectMessage::InternalMemoryAllocationChanged); + internalMemoryAllocationChanged(feedback); return angle::Result::Continue; } @@ -1385,10 +1404,8 @@ bool BufferVk::shouldRedefineStorage(vk::Renderer *renderer, } else { - size_t paddedBufferSize = - (renderer->getFeatures().padBuffersToMaxVertexAttribStride.enabled) - ? (size + static_cast(renderer->getMaxVertexAttribStride())) - : size; + const size_t paddedBufferSize = + static_cast(renderer->padVertexAttribBufferSizeIfNeeded(size)); size_t sizeInBytes = roundUpPow2(paddedBufferSize, kBufferSizeGranularity); size_t alignedSize = roundUp(sizeInBytes, renderer->getDefaultBufferAlignment()); if (alignedSize > mBuffer.getSize()) diff --git a/src/libANGLE/renderer/vulkan/BufferVk.h b/src/libANGLE/renderer/vulkan/BufferVk.h index 59fd765a312..c22557459ba 100644 --- a/src/libANGLE/renderer/vulkan/BufferVk.h +++ b/src/libANGLE/renderer/vulkan/BufferVk.h @@ -143,6 +143,8 @@ struct BufferDataSource VkBufferUsageFlags GetDefaultBufferUsageFlags(vk::Renderer *renderer); +// TransformFeedbackVk is still observing BufferVk, so make it Subject class until we remove that +// observer. class BufferVk : public BufferImpl { public: @@ -161,29 +163,40 @@ class BufferVk : public BufferImpl const void *data, size_t size, gl::BufferUsage usage, - GLbitfield flags) override; + GLbitfield flags, + gl::BufferStorage bufferStorage, + BufferFeedback *feedback) override; angle::Result setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; angle::Result getSubData(const gl::Context *context, GLintptr offset, GLsizeiptr size, @@ -211,18 +224,51 @@ class BufferVk : public BufferImpl bool isBufferValid() const { return mBuffer.valid(); } bool isCurrentlyInUse(vk::Renderer *renderer) const; - angle::Result mapImpl(ContextVk *contextVk, GLbitfield access, void **mapPtr); + angle::Result mapForReadAccessOnly(ContextVk *contextVk, void **mapPtr) + { + BufferFeedback feedback; + ANGLE_TRY(mapImpl(contextVk, GL_MAP_READ_BIT, mapPtr, &feedback)); + // read should not change main buffer storage that GPU uses + ASSERT(!feedback.hasFeedback()); + return angle::Result::Continue; + } + angle::Result mapRangeForReadAccessOnly(ContextVk *contextVk, + VkDeviceSize offset, + VkDeviceSize length, + void **mapPtr) + { + BufferFeedback feedback; + ANGLE_TRY(mapRangeImpl(contextVk, offset, length, GL_MAP_READ_BIT, mapPtr, &feedback)); + // read should not change main buffer storage that GPU uses + ASSERT(!feedback.hasFeedback()); + return angle::Result::Continue; + } + angle::Result unmapReadAccessOnly(ContextVk *contextVk) + { + BufferFeedback feedback; + ANGLE_TRY(unmapImpl(contextVk, &feedback)); + // read should not change main buffer storage that GPU uses + ASSERT(!feedback.hasFeedback()); + return angle::Result::Continue; + } + + angle::Result mapImpl(ContextVk *contextVk, + GLbitfield access, + void **mapPtr, + BufferFeedback *feedback); angle::Result mapRangeImpl(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize length, GLbitfield access, - void **mapPtr); - angle::Result unmapImpl(ContextVk *contextVk); + void **mapPtr, + BufferFeedback *feedback); + angle::Result unmapImpl(ContextVk *contextVk, BufferFeedback *feedback); angle::Result ghostMappedBuffer(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize length, GLbitfield access, - void **mapPtr); + void **mapPtr, + BufferFeedback *feedback); VertexConversionBuffer *getVertexConversionBuffer( vk::Renderer *renderer, @@ -252,13 +298,15 @@ class BufferVk : public BufferImpl const BufferDataSource &dataSource, size_t updateSize, size_t updateOffset, - BufferUpdateType updateType); + BufferUpdateType updateType, + BufferFeedback *feedback); angle::Result setDataWithMemoryType(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, VkMemoryPropertyFlags memoryPropertyFlags, - gl::BufferUsage usage); + gl::BufferUsage usage, + BufferFeedback *feedback); angle::Result handleDeviceLocalBufferMap(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size, @@ -272,14 +320,16 @@ class BufferVk : public BufferImpl const BufferDataSource &dataSource, size_t updateSize, size_t updateOffset, - BufferUpdateType updateType); + BufferUpdateType updateType, + BufferFeedback *feedback); angle::Result release(ContextVk *context); void dataUpdated(); void dataRangeUpdated(const RangeDeviceSize &range); angle::Result acquireBufferHelper(ContextVk *contextVk, size_t sizeInBytes, - BufferUsageType usageType); + BufferUsageType usageType, + BufferFeedback *feedback); bool isExternalBuffer() const { return mClientBuffer != nullptr; } BufferUpdateType calculateBufferUpdateTypeOnFullUpdate( @@ -295,6 +345,12 @@ class BufferVk : public BufferImpl void releaseConversionBuffers(vk::Context *context); + void internalMemoryAllocationChanged(BufferFeedback *feedback) + { + feedback->internalMemoryAllocationChanged = true; + onStateChange(angle::SubjectMessage::InternalMemoryAllocationChanged); + } + vk::BufferHelper mBuffer; // If not null, this is the external memory pointer passed from client API. diff --git a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp index c399fa45ffa..a95746d0a26 100644 --- a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp @@ -4,8 +4,15 @@ // found in the LICENSE file. // // CLCommandQueueVk.cpp: Implements the class methods for CLCommandQueueVk. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "common/PackedCLEnums_autogen.h" +#include "common/SimpleMutex.h" +#include "common/log_utils.h" #include "common/system_utils.h" #include "libANGLE/renderer/vulkan/CLCommandQueueVk.h" @@ -47,28 +54,35 @@ namespace rx namespace { -static constexpr size_t kTimeoutInMS = 10000; -static constexpr size_t kSleepInMS = 500; -static constexpr size_t kTimeoutCheckIterations = kTimeoutInMS / kSleepInMS; - -angle::Result SetEventsWithQueueSerialToState(const cl::EventPtrs &eventList, - const QueueSerial &queueSerial, - cl::ExecutionStatus state) +// Given an image and rect region to copy in to a buffer, calculate the VKBufferImageCopy struct to +// be using in VkCmd's. +VkBufferImageCopy CalculateBufferImageCopyRegion(const size_t bufferOffset, + const uint32_t rowPitch, + const uint32_t slicePitch, + const cl::Offset &origin, + const cl::Extents ®ion, + CLImageVk *imageVk) { - - ASSERT(state < cl::ExecutionStatus::EnumCount); - - for (cl::EventPtr event : eventList) - { - CLEventVk *eventVk = &event->getImpl(); - if (!eventVk->isUserEvent() && eventVk->usedByCommandBuffer(queueSerial)) - { - ANGLE_TRY(eventVk->setStatusAndExecuteCallback(cl::ToCLenum(state))); - } - } - return angle::Result::Continue; + VkBufferImageCopy copyRegion{ + .bufferOffset = bufferOffset, + .bufferRowLength = + rowPitch == 0 ? 0 : rowPitch / static_cast(imageVk->getElementSize()), + .bufferImageHeight = rowPitch == 0 ? 0 : slicePitch / rowPitch, + .imageSubresource = imageVk->getSubresourceLayersForCopy(origin, region, imageVk->getType(), + ImageCopyWith::Buffer), + .imageOffset = cl_vk::GetOffset(origin), + .imageExtent = cl_vk::GetExtent(region)}; + ASSERT((copyRegion.bufferRowLength == 0 && copyRegion.bufferImageHeight == 0) || + (copyRegion.bufferRowLength >= region.width && + copyRegion.bufferImageHeight >= region.height)); + + return copyRegion; } +constexpr size_t kTimeoutInMS = 10000; +constexpr size_t kSleepInMS = 500; +constexpr size_t kTimeoutCheckIterations = kTimeoutInMS / kSleepInMS; + DispatchWorkThread::DispatchWorkThread(CLCommandQueueVk *commandQueue) : mCommandQueue(commandQueue), mIsTerminating(false), @@ -168,6 +182,71 @@ angle::Result DispatchWorkThread::finishLoop() return angle::Result::Continue; } +egl::ContextPriority convertClToEglPriority(cl_queue_priority_khr priority) +{ + switch (priority) + { + case CL_QUEUE_PRIORITY_HIGH_KHR: + return egl::ContextPriority::High; + case CL_QUEUE_PRIORITY_MED_KHR: + return egl::ContextPriority::Medium; + case CL_QUEUE_PRIORITY_LOW_KHR: + return egl::ContextPriority::Low; + default: + UNREACHABLE(); + return egl::ContextPriority::Medium; + } +} + +class HostTransferConfigVisitor +{ + public: + HostTransferConfigVisitor(CLBufferVk &buffer) : bufferVk(buffer) {} + + angle::Result operator()(const HostReadTransferConfig &transferConfig) + { + switch (transferConfig.getType()) + { + case CL_COMMAND_READ_BUFFER: + ANGLE_TRY(bufferVk.syncHost(CLBufferVk::SyncHostDirection::ToHost)); + break; + case CL_COMMAND_READ_BUFFER_RECT: + ANGLE_TRY(bufferVk.syncHost(CLBufferVk::SyncHostDirection::ToHost, + transferConfig.getHostRect())); + break; + case CL_COMMAND_READ_IMAGE: + ANGLE_TRY(bufferVk.syncHost(CLBufferVk::SyncHostDirection::ToHost, + transferConfig.getHostRect())); + break; + default: + UNREACHABLE(); + break; + } + return angle::Result::Continue; + } + + angle::Result operator()(const HostWriteTransferConfig &transferConfig) + { + switch (transferConfig.getType()) + { + + case CL_COMMAND_WRITE_BUFFER: + case CL_COMMAND_WRITE_BUFFER_RECT: + case CL_COMMAND_FILL_BUFFER: + case CL_COMMAND_WRITE_IMAGE: + // Nothing to do here + break; + default: + UNIMPLEMENTED(); + break; + } + return angle::Result::Continue; + } + + private: + CLBufferVk &bufferVk; +}; + } // namespace CLCommandQueueVk::CLCommandQueueVk(const cl::CommandQueue &commandQueue) @@ -176,9 +255,11 @@ CLCommandQueueVk::CLCommandQueueVk(const cl::CommandQueue &commandQueue) mDevice(&commandQueue.getDevice().getImpl()), mPrintfBuffer(nullptr), mComputePassCommands(nullptr), + mCommandState(mContext->getRenderer(), + vk::ProtectionType::Unprotected, + convertClToEglPriority(mCommandQueue.getPriority())), mQueueSerialIndex(kInvalidQueueSerialIndex), mNeedPrintfHandling(false), - mPrintfInfos(nullptr), mFinishHandler(this) {} @@ -192,10 +273,10 @@ angle::Result CLCommandQueueVk::init() renderer->getQueueFamilyIndex(), getProtectionType()), CL_OUT_OF_RESOURCES); - ANGLE_CL_IMPL_TRY_ERROR(mContext->getRenderer()->getOutsideRenderPassCommandBufferHelper( - mContext, &mCommandPool.outsideRenderPassPool, - &mOutsideRenderPassCommandsAllocator, &mComputePassCommands), - CL_OUT_OF_RESOURCES); + ANGLE_CL_IMPL_TRY_ERROR( + mContext->getRenderer()->getOutsideRenderPassCommandBufferHelper( + mContext, &mCommandPool.outsideRenderPassPool, &mComputePassCommands), + CL_OUT_OF_RESOURCES); // Generate initial QueueSerial for command buffer helper ANGLE_CL_IMPL_TRY_ERROR(mContext->getRenderer()->allocateQueueSerialIndex(&mQueueSerialIndex), @@ -215,6 +296,10 @@ angle::Result CLCommandQueueVk::init() CLCommandQueueVk::~CLCommandQueueVk() { + VkDevice vkDevice = mContext->getDevice(); + + mCommandState.destroy(vkDevice); + mFinishHandler.terminate(); ASSERT(mComputePassCommands->empty()); @@ -228,8 +313,6 @@ CLCommandQueueVk::~CLCommandQueueVk() delete mPrintfBuffer; } - VkDevice vkDevice = mContext->getDevice(); - if (mQueueSerialIndex != kInvalidQueueSerialIndex) { mContext->getRenderer()->releaseQueueSerialIndex(mQueueSerialIndex); @@ -254,34 +337,28 @@ angle::Result CLCommandQueueVk::enqueueReadBuffer(const cl::Buffer &buffer, size_t size, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - CLBufferVk *bufferVk = &buffer.getImpl(); + CLBufferVk *bufferVk = &buffer.getImpl(); if (blocking) { ANGLE_TRY(finishInternal()); ANGLE_TRY(bufferVk->copyTo(ptr, offset, size)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Complete)); } else { // Stage a transfer routine - HostTransferConfig transferConfig; - transferConfig.type = CL_COMMAND_READ_BUFFER; - transferConfig.offset = offset; - transferConfig.size = size; - transferConfig.dstHostPtr = ptr; + HostReadTransferConfig transferConfig(CL_COMMAND_READ_BUFFER, size, offset, ptr); ANGLE_TRY(addToHostTransferList(bufferVk, transferConfig)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); } - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueWriteBuffer(const cl::Buffer &buffer, @@ -290,62 +367,52 @@ angle::Result CLCommandQueueVk::enqueueWriteBuffer(const cl::Buffer &buffer, size_t size, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); auto bufferVk = &buffer.getImpl(); - if (blocking) { ANGLE_TRY(finishInternal()); ANGLE_TRY(bufferVk->copyFrom(ptr, offset, size)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Complete)); } else { // Stage a transfer routine - HostTransferConfig config; - config.type = CL_COMMAND_WRITE_BUFFER; - config.offset = offset; - config.size = size; - config.srcHostPtr = ptr; + HostWriteTransferConfig config(CL_COMMAND_WRITE_BUFFER, size, offset, ptr); ANGLE_TRY(addToHostTransferList(bufferVk, config)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); } - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueReadBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - auto bufferVk = &buffer.getImpl(); - - cl::BufferRect bufferRect{cl::Offset{bufferOrigin.x, bufferOrigin.y, bufferOrigin.z}, - cl::Extents{region.x, region.y, region.z}, bufferRowPitch, - bufferSlicePitch, 1}; - cl::BufferRect ptrRect{cl::Offset{hostOrigin.x, hostOrigin.y, hostOrigin.z}, - cl::Extents{region.x, region.y, region.z}, hostRowPitch, hostSlicePitch, - 1}; + auto bufferVk = &buffer.getImpl(); + cl::BufferRect bufferRect{bufferOrigin, region, bufferRowPitch, bufferSlicePitch, 1}; + cl::BufferRect ptrRect{hostOrigin, region, hostRowPitch, hostSlicePitch, 1}; if (blocking) { @@ -355,45 +422,36 @@ angle::Result CLCommandQueueVk::enqueueReadBufferRect(const cl::Buffer &buffer, else { // Stage a transfer routine - HostTransferConfig config; - config.type = CL_COMMAND_READ_BUFFER_RECT; - config.srcRect = bufferRect; - config.dstRect = ptrRect; - config.dstHostPtr = ptr; - config.size = bufferVk->getSize(); + HostReadTransferConfig config(CL_COMMAND_READ_BUFFER_RECT, ptrRect.getRectSize(), ptr, + bufferRect, ptrRect); ANGLE_TRY(addToHostTransferList(bufferVk, config)); } - ANGLE_TRY(createEvent(eventCreateFunc, - blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueWriteBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - auto bufferVk = &buffer.getImpl(); - cl::BufferRect bufferRect{cl::Offset{bufferOrigin.x, bufferOrigin.y, bufferOrigin.z}, - cl::Extents{region.x, region.y, region.z}, bufferRowPitch, - bufferSlicePitch, 1}; - - cl::BufferRect ptrRect{cl::Offset{hostOrigin.x, hostOrigin.y, hostOrigin.z}, - cl::Extents{region.x, region.y, region.z}, hostRowPitch, hostSlicePitch, - 1}; + auto bufferVk = &buffer.getImpl(); + cl::BufferRect bufferRect{bufferOrigin, region, bufferRowPitch, bufferSlicePitch, 1}; + cl::BufferRect ptrRect{hostOrigin, region, hostRowPitch, hostSlicePitch, 1}; if (blocking) { @@ -403,18 +461,12 @@ angle::Result CLCommandQueueVk::enqueueWriteBufferRect(const cl::Buffer &buffer, else { // Stage a transfer routine - HostTransferConfig config; - config.type = CL_COMMAND_WRITE_BUFFER_RECT; - config.srcRect = ptrRect; - config.dstRect = bufferRect; - config.srcHostPtr = ptr; - config.size = bufferVk->getSize(); + HostWriteTransferConfig config(CL_COMMAND_WRITE_BUFFER_RECT, ptrRect.getRectSize(), + const_cast(ptr), bufferRect, ptrRect); ANGLE_TRY(addToHostTransferList(bufferVk, config)); } - ANGLE_TRY(createEvent(eventCreateFunc, - blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueCopyBuffer(const cl::Buffer &srcBuffer, @@ -423,30 +475,31 @@ angle::Result CLCommandQueueVk::enqueueCopyBuffer(const cl::Buffer &srcBuffer, size_t dstOffset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); CLBufferVk *srcBufferVk = &srcBuffer.getImpl(); CLBufferVk *dstBufferVk = &dstBuffer.getImpl(); - vk::CommandBufferAccess access; + vk::CommandResources resources; if (srcBufferVk->isSubBuffer() && dstBufferVk->isSubBuffer() && (srcBufferVk->getParent() == dstBufferVk->getParent())) { // this is a self copy - access.onBufferSelfCopy(&srcBufferVk->getBuffer()); + resources.onBufferSelfCopy(&srcBufferVk->getBuffer()); } else { - access.onBufferTransferRead(&srcBufferVk->getBuffer()); - access.onBufferTransferWrite(&dstBufferVk->getBuffer()); + resources.onBufferTransferRead(&srcBufferVk->getBuffer()); + resources.onBufferTransferWrite(&dstBufferVk->getBuffer()); } vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(getCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(getCommandBuffer(resources, &commandBuffer)); VkBufferCopy copyRegion = {srcOffset, dstOffset, size}; // update the offset in the case of sub-buffers @@ -461,44 +514,47 @@ angle::Result CLCommandQueueVk::enqueueCopyBuffer(const cl::Buffer &srcBuffer, commandBuffer->copyBuffer(srcBufferVk->getBuffer().getBuffer(), dstBufferVk->getBuffer().getBuffer(), 1, ©Region); - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueCopyBufferRect(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, size_t dstSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Complete)); ANGLE_TRY(processWaitlist(waitEvents)); ANGLE_TRY(finishInternal()); - cl::BufferRect srcRect{cl::Offset{srcOrigin.x, srcOrigin.y, srcOrigin.z}, - cl::Extents{region.x, region.y, region.z}, srcRowPitch, srcSlicePitch, - 1}; + cl::BufferRect srcRect{srcOrigin, region, srcRowPitch, srcSlicePitch, 1}; - cl::BufferRect dstRect{cl::Offset{dstOrigin.x, dstOrigin.y, dstOrigin.z}, - cl::Extents{region.x, region.y, region.z}, dstRowPitch, dstSlicePitch, - 1}; + cl::BufferRect dstRect{dstOrigin, region, dstRowPitch, dstSlicePitch, 1}; + + auto srcBufferVk = &srcBuffer.getImpl(); + auto dstBufferVk = &dstBuffer.getImpl(); - auto srcBufferVk = &srcBuffer.getImpl(); - auto dstBufferVk = &dstBuffer.getImpl(); uint8_t *mapPointer = nullptr; ANGLE_TRY(srcBufferVk->map(mapPointer)); - ASSERT(mapPointer); + cl::Defer deferUnmap([&srcBufferVk]() { srcBufferVk->unmap(); }); + + if (srcBuffer.getFlags().intersects(CL_MEM_USE_HOST_PTR) && !srcBufferVk->supportsZeroCopy()) + { + // UHP needs special handling when zero-copy is not supported + ANGLE_TRY(srcBufferVk->copyTo(mapPointer, 0, srcBufferVk->getSize())); + } + ANGLE_TRY(dstBufferVk->setRect(static_cast(mapPointer), srcRect, dstRect)); - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Complete)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueFillBuffer(const cl::Buffer &buffer, @@ -507,26 +563,20 @@ angle::Result CLCommandQueueVk::enqueueFillBuffer(const cl::Buffer &buffer, size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); CLBufferVk *bufferVk = &buffer.getImpl(); // Stage a transfer routine - HostTransferConfig config; - config.type = CL_COMMAND_FILL_BUFFER; - config.patternSize = patternSize; - config.offset = offset; - config.size = size; - config.srcHostPtr = pattern; + HostWriteTransferConfig config(CL_COMMAND_FILL_BUFFER, size, offset, pattern, patternSize); ANGLE_TRY(addToHostTransferList(bufferVk, config)); - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueMapBuffer(const cl::Buffer &buffer, @@ -535,76 +585,58 @@ angle::Result CLCommandQueueVk::enqueueMapBuffer(const cl::Buffer &buffer, size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - cl::ExecutionStatus eventComplete = cl::ExecutionStatus::Queued; - if (blocking || !eventCreateFunc) + if (blocking) { ANGLE_TRY(finishInternal()); - eventComplete = cl::ExecutionStatus::Complete; } CLBufferVk *bufferVk = &buffer.getImpl(); uint8_t *mapPointer = nullptr; - if (buffer.getFlags().intersects(CL_MEM_USE_HOST_PTR)) - { - ANGLE_TRY(finishInternal()); - mapPointer = static_cast(buffer.getHostPtr()) + offset; - ANGLE_TRY(bufferVk->copyTo(mapPointer, offset, size)); - eventComplete = cl::ExecutionStatus::Complete; - } - else - { - ANGLE_TRY(bufferVk->map(mapPointer, offset)); - } - mapPtr = static_cast(mapPointer); + ANGLE_TRY(bufferVk->map(mapPointer, offset)); + mapPtr = mapPointer; - if (bufferVk->isCurrentlyInUse()) + if (buffer.getFlags().intersects(CL_MEM_USE_HOST_PTR) && !bufferVk->supportsZeroCopy()) { - eventComplete = cl::ExecutionStatus::Queued; + // UHP needs special handling when zero-copy is not supported + ANGLE_TRY(bufferVk->copyTo(mapPointer, offset, size)); } - ANGLE_TRY(createEvent(eventCreateFunc, eventComplete)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::copyImageToFromBuffer(CLImageVk &imageVk, - vk::BufferHelper &buffer, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, - size_t bufferOffset, + CLBufferVk &buffer, + VkBufferImageCopy copyRegion, ImageBufferCopyDirection direction) { - vk::CommandBufferAccess access; + vk::Renderer *renderer = mContext->getRenderer(); + + vk::CommandResources resources; vk::OutsideRenderPassCommandBuffer *commandBuffer; VkImageAspectFlags aspectFlags = imageVk.getImage().getAspectFlags(); if (direction == ImageBufferCopyDirection::ToBuffer) { - access.onImageTransferRead(aspectFlags, &imageVk.getImage()); - access.onBufferTransferWrite(&buffer); + resources.onImageTransferRead(aspectFlags, &imageVk.getImage()); + resources.onBufferTransferWrite(&buffer.getBuffer()); } else { - access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, - static_cast(imageVk.getArraySize()), aspectFlags, - &imageVk.getImage()); - access.onBufferTransferRead(&buffer); - } - ANGLE_TRY(getCommandBuffer(access, &commandBuffer)); - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = bufferOffset; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageExtent = cl_vk::GetExtent(imageVk.getExtentForCopy(region)); - copyRegion.imageOffset = cl_vk::GetOffset(imageVk.getOffsetForCopy(origin)); - copyRegion.imageSubresource = imageVk.getSubresourceLayersForCopy( - origin, region, imageVk.getType(), ImageCopyWith::Buffer); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, + static_cast(imageVk.getArraySize()), aspectFlags, + &imageVk.getImage()); + resources.onBufferTransferRead(&buffer.getBuffer()); + } + ANGLE_TRY(getCommandBuffer(resources, &commandBuffer)); + if (imageVk.isWritable()) { // We need an execution barrier if image can be written to by kernel @@ -617,9 +649,9 @@ angle::Result CLCommandQueueVk::copyImageToFromBuffer(CLImageVk &imageVk, memBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; if (direction == ImageBufferCopyDirection::ToBuffer) { - commandBuffer->copyImageToBuffer(imageVk.getImage().getImage(), - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer.getBuffer().getHandle(), 1, ©Region); + commandBuffer->copyImageToBuffer( + imageVk.getImage().getImage(), imageVk.getImage().getCurrentLayout(renderer), + buffer.getBuffer().getBuffer().getHandle(), 1, ©Region); mComputePassCommands->getCommandBuffer().pipelineBarrier( VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memBarrier, 0, @@ -627,9 +659,9 @@ angle::Result CLCommandQueueVk::copyImageToFromBuffer(CLImageVk &imageVk, } else { - commandBuffer->copyBufferToImage(buffer.getBuffer().getHandle(), - imageVk.getImage().getImage(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); + commandBuffer->copyBufferToImage( + buffer.getBuffer().getBuffer().getHandle(), imageVk.getImage().getImage(), + imageVk.getImage().getCurrentLayout(renderer), 1, ©Region); mComputePassCommands->getCommandBuffer().pipelineBarrier( VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memBarrier, @@ -639,22 +671,39 @@ angle::Result CLCommandQueueVk::copyImageToFromBuffer(CLImageVk &imageVk, return angle::Result::Continue; } +template angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, - HostTransferConfig transferConfig) + HostTransferConfig transferConfig) { // TODO(aannestrand): Flush here if we reach some max-transfer-buffer heuristic // http://anglebug.com/377545840 - cl::Memory *transferBufferHandle = - cl::Buffer::Cast(this->mContext->getFrontendObject().createBuffer( - nullptr, cl::MemFlags{CL_MEM_READ_WRITE}, srcBuffer->getSize(), nullptr)); + cl::Memory *transferBufferHandle = nullptr; + cl::MemFlags transferBufferMemFlag = cl::MemFlags(CL_MEM_READ_WRITE); + + // We insert an appropriate copy command in the command stream. For the host ptr, we create CL + // buffer with UHP flags to reflect the contents on the host side. + switch (transferConfig.getType()) + { + case CL_COMMAND_WRITE_BUFFER: + case CL_COMMAND_WRITE_BUFFER_RECT: + case CL_COMMAND_READ_BUFFER: + case CL_COMMAND_READ_BUFFER_RECT: + transferBufferMemFlag.set(CL_MEM_USE_HOST_PTR); + break; + default: // zero-copy attempt is not supported for CL_COMMAND_FILL_BUFFER + break; + } + + transferBufferHandle = cl::Buffer::Cast(this->mContext->getFrontendObject().createBuffer( + nullptr, transferBufferMemFlag, transferConfig.getSize(), + const_cast(transferConfig.getHostPtr()))); if (transferBufferHandle == nullptr) { ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); } HostTransferEntry transferEntry{transferConfig, cl::MemoryPtr{transferBufferHandle}}; - mCommandsStateMap[mComputePassCommands->getQueueSerial()].hostTransferList.emplace_back( - transferEntry); + mCommandsStateMap.addHostTransferEntry(mComputePassCommands->getQueueSerial(), transferEntry); // Release initialization reference, lifetime controlled by RefPointer. transferBufferHandle->release(); @@ -678,14 +727,11 @@ angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, VkMemoryBarrier memBarrier = {}; memBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; CLBufferVk &transferBufferHandleVk = transferBufferHandle->getImpl(); - switch (transferConfig.type) + switch (transferConfig.getType()) { case CL_COMMAND_WRITE_BUFFER: { - VkBufferCopy copyRegion = {transferConfig.offset, transferConfig.offset, - transferConfig.size}; - ANGLE_TRY(transferBufferHandleVk.copyFrom(transferConfig.srcHostPtr, - transferConfig.offset, transferConfig.size)); + VkBufferCopy copyRegion = {0, transferConfig.getOffset(), transferConfig.getSize()}; copyRegion.srcOffset += transferBufferHandleVk.getOffset(); copyRegion.dstOffset += srcBuffer->getOffset(); mComputePassCommands->getCommandBuffer().copyBuffer( @@ -700,10 +746,8 @@ angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, } case CL_COMMAND_WRITE_BUFFER_RECT: { - ANGLE_TRY(transferBufferHandleVk.setRect( - transferConfig.srcHostPtr, transferConfig.srcRect, transferConfig.dstRect)); - for (VkBufferCopy ©Region : - transferBufferHandleVk.rectCopyRegions(transferConfig.dstRect)) + for (VkBufferCopy ©Region : cl_vk::CalculateRectCopyRegions( + transferConfig.getHostRect(), transferConfig.getBufferRect())) { copyRegion.srcOffset += transferBufferHandleVk.getOffset(); copyRegion.dstOffset += srcBuffer->getOffset(); @@ -721,8 +765,7 @@ angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, } case CL_COMMAND_READ_BUFFER: { - VkBufferCopy copyRegion = {transferConfig.offset, transferConfig.offset, - transferConfig.size}; + VkBufferCopy copyRegion = {transferConfig.getOffset(), 0, transferConfig.getSize()}; copyRegion.srcOffset += srcBuffer->getOffset(); copyRegion.dstOffset += transferBufferHandleVk.getOffset(); mComputePassCommands->getCommandBuffer().copyBuffer( @@ -737,8 +780,8 @@ angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, } case CL_COMMAND_READ_BUFFER_RECT: { - for (VkBufferCopy ©Region : - transferBufferHandleVk.rectCopyRegions(transferConfig.srcRect)) + for (VkBufferCopy ©Region : cl_vk::CalculateRectCopyRegions( + transferConfig.getBufferRect(), transferConfig.getHostRect())) { copyRegion.srcOffset += srcBuffer->getOffset(); copyRegion.dstOffset += transferBufferHandleVk.getOffset(); @@ -756,13 +799,14 @@ angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, } case CL_COMMAND_FILL_BUFFER: { - VkBufferCopy copyRegion = {transferConfig.offset, transferConfig.offset, - transferConfig.size}; - ANGLE_TRY(transferBufferHandleVk.fillWithPattern( - transferConfig.srcHostPtr, transferConfig.patternSize, transferConfig.offset, - transferConfig.size)); - copyRegion.srcOffset += transferBufferHandleVk.getOffset(); - copyRegion.dstOffset += srcBuffer->getOffset(); + // Fill the staging buffer with the pattern and then insert a copy command from staging + // buffer to buffer + ANGLE_TRY(transferBufferHandleVk.fillWithPattern(transferConfig.getHostPtr(), + transferConfig.getPatternSize(), 0, + transferConfig.getSize())); + VkBufferCopy copyRegion = { + transferBufferHandleVk.getOffset(), // source is the staging buffer + transferConfig.getOffset() + srcBuffer->getOffset(), transferConfig.getSize()}; mComputePassCommands->getCommandBuffer().copyBuffer( transferBufferHandleVk.getBuffer().getBuffer(), srcBuffer->getBuffer().getBuffer(), 1, ©Region); @@ -787,161 +831,176 @@ angle::Result CLCommandQueueVk::addToHostTransferList(CLBufferVk *srcBuffer, return angle::Result::Continue; } +template angle::Result CLCommandQueueVk::addToHostTransferList(CLImageVk *srcImage, - HostTransferConfig transferConfig) + HostTransferConfig transferConfig) { // TODO(aannestrand): Flush here if we reach some max-transfer-buffer heuristic // http://anglebug.com/377545840 - CommandsState &commandsState = mCommandsStateMap[mComputePassCommands->getQueueSerial()]; - cl::Memory *transferBufferHandle = - cl::Buffer::Cast(this->mContext->getFrontendObject().createBuffer( - nullptr, cl::MemFlags{CL_MEM_READ_WRITE}, srcImage->getSize(), nullptr)); + cl::Memory *transferBufferHandle = nullptr; + cl::MemFlags transferBufferMemFlag = cl::MemFlags(CL_MEM_READ_WRITE); + + // We insert an appropriate copy command in the command stream. For the host ptr, we create CL + // buffer with UHP flags to reflect the contents on the host side. + switch (transferConfig.getType()) + { + case CL_COMMAND_WRITE_IMAGE: + case CL_COMMAND_READ_IMAGE: + transferBufferMemFlag.set(CL_MEM_USE_HOST_PTR); + break; + default: + break; + } + + transferBufferHandle = cl::Buffer::Cast(this->mContext->getFrontendObject().createBuffer( + nullptr, transferBufferMemFlag, transferConfig.getSize(), + const_cast(transferConfig.getHostPtr()))); if (transferBufferHandle == nullptr) { ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); } HostTransferEntry transferEntry{transferConfig, cl::MemoryPtr{transferBufferHandle}}; - commandsState.hostTransferList.emplace_back(transferEntry); + mCommandsStateMap.addHostTransferEntry(mComputePassCommands->getQueueSerial(), transferEntry); // Release initialization reference, lifetime controlled by RefPointer. transferBufferHandle->release(); - // Enqueue blit CLBufferVk &transferBufferHandleVk = transferBufferHandle->getImpl(); - ANGLE_TRY(copyImageToFromBuffer(*srcImage, transferBufferHandleVk.getBuffer(), - transferConfig.origin, transferConfig.region, 0, - ImageBufferCopyDirection::ToBuffer)); + ImageBufferCopyDirection direction = ImageBufferCopyDirection::ToBuffer; - return angle::Result::Continue; + switch (transferConfig.getType()) + { + case CL_COMMAND_WRITE_IMAGE: + direction = ImageBufferCopyDirection::ToImage; + break; + case CL_COMMAND_READ_IMAGE: + direction = ImageBufferCopyDirection::ToBuffer; + break; + default: + UNREACHABLE(); + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + } + + VkBufferImageCopy copyRegion = CalculateBufferImageCopyRegion( + 0, static_cast(transferConfig.getRowPitch()), + static_cast(transferConfig.getSlicePitch()), transferConfig.getOrigin(), + transferConfig.getRegion(), srcImage); + + return copyImageToFromBuffer(*srcImage, transferBufferHandleVk, copyRegion, direction); } angle::Result CLCommandQueueVk::enqueueReadImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) + { std::scoped_lock sl(mCommandQueueMutex); - CLImageVk &imageVk = image.getImpl(); - size_t size = (region.x * region.y * region.z * imageVk.getElementSize()); + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - if (imageVk.isStagingBufferInitialized() == false) + CLImageVk &imageVk = image.getImpl(); + cl::BufferRect ptrRect{cl::kOffsetZero, region, rowPitch, slicePitch, imageVk.getElementSize()}; + + if (imageVk.getParentType() == cl::MemObjectType::Buffer) { - ANGLE_TRY(imageVk.createStagingBuffer(imageVk.getSize())); + // TODO: implement this later + // http://anglebug.com/444481344 + UNIMPLEMENTED(); + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); } + // Create a transfer buffer and push it in update list + HostReadTransferConfig transferConfig(CL_COMMAND_READ_IMAGE, ptrRect.getRectSize(), ptr, + rowPitch, slicePitch, imageVk.getElementSize(), origin, + region); + + ANGLE_TRY(addToHostTransferList(&imageVk, transferConfig)); + if (blocking) { - ANGLE_TRY(copyImageToFromBuffer(imageVk, imageVk.getStagingBuffer(), origin, region, 0, - ImageBufferCopyDirection::ToBuffer)); ANGLE_TRY(finishInternal()); - if (rowPitch == 0 && slicePitch == 0) - { - ANGLE_TRY(imageVk.copyStagingTo(ptr, 0, size)); - } - else - { - ANGLE_TRY(imageVk.copyStagingToFromWithPitch(ptr, region, rowPitch, slicePitch, - StagingBufferCopyDirection::ToHost)); - } - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Complete)); - } - else - { - // Create a transfer buffer and push it in update list - HostTransferConfig transferConfig; - transferConfig.type = CL_COMMAND_READ_IMAGE; - transferConfig.size = size; - transferConfig.dstHostPtr = ptr; - transferConfig.origin = origin; - transferConfig.region = region; - transferConfig.rowPitch = rowPitch; - transferConfig.slicePitch = slicePitch; - transferConfig.elementSize = imageVk.getElementSize(); - ANGLE_TRY(addToHostTransferList(&imageVk, transferConfig)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); } - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueWriteImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + + ANGLE_TRY(preEnqueueOps( + event, blocking ? cl::ExecutionStatus::Complete : cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); CLImageVk &imageVk = image.getImpl(); - size_t size = (region.x * region.y * region.z * imageVk.getElementSize()); - cl::ExecutionStatus eventInitialState = cl::ExecutionStatus::Queued; - if (imageVk.isStagingBufferInitialized() == false) - { - ANGLE_TRY(imageVk.createStagingBuffer(imageVk.getSize())); - } + cl::BufferRect ptrRect{cl::kOffsetZero, region, inputRowPitch, inputSlicePitch, + imageVk.getElementSize()}; - if (inputRowPitch == 0 && inputSlicePitch == 0) - { - ANGLE_TRY(imageVk.copyStagingFrom((void *)ptr, 0, size)); - } - else + if (imageVk.getParentType() == cl::MemObjectType::Buffer) { - ANGLE_TRY(imageVk.copyStagingToFromWithPitch((void *)ptr, region, inputRowPitch, - inputSlicePitch, - StagingBufferCopyDirection::ToStagingBuffer)); + // TODO: implement this later + // http://anglebug.com/444481344 + UNIMPLEMENTED(); + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); } - ANGLE_TRY(copyImageToFromBuffer(imageVk, imageVk.getStagingBuffer(), origin, region, 0, - ImageBufferCopyDirection::ToImage)); + // Create a transfer buffer and push it in update list + HostWriteTransferConfig transferConfig(CL_COMMAND_WRITE_IMAGE, ptrRect.getRectSize(), + const_cast(ptr), inputRowPitch, inputSlicePitch, + imageVk.getElementSize(), origin, region); + + ANGLE_TRY(addToHostTransferList(&imageVk, transferConfig)); if (blocking) { ANGLE_TRY(finishInternal()); - eventInitialState = cl::ExecutionStatus::Complete; } - ANGLE_TRY(createEvent(eventCreateFunc, eventInitialState)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueCopyImage(const cl::Image &srcImage, const cl::Image &dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); auto srcImageVk = &srcImage.getImpl(); auto dstImageVk = &dstImage.getImpl(); - vk::CommandBufferAccess access; + vk::CommandResources resources; vk::OutsideRenderPassCommandBuffer *commandBuffer; VkImageAspectFlags dstAspectFlags = srcImageVk->getImage().getAspectFlags(); VkImageAspectFlags srcAspectFlags = dstImageVk->getImage().getAspectFlags(); - access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, dstAspectFlags, - &dstImageVk->getImage()); - access.onImageTransferRead(srcAspectFlags, &srcImageVk->getImage()); - ANGLE_TRY(getCommandBuffer(access, &commandBuffer)); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, dstAspectFlags, + &dstImageVk->getImage()); + resources.onImageTransferRead(srcAspectFlags, &srcImageVk->getImage()); + ANGLE_TRY(getCommandBuffer(resources, &commandBuffer)); VkImageCopy copyRegion = {}; copyRegion.extent = cl_vk::GetExtent(srcImageVk->getExtentForCopy(region)); @@ -957,24 +1016,25 @@ angle::Result CLCommandQueueVk::enqueueCopyImage(const cl::Image &srcImage, ANGLE_TRY(insertBarrier()); } - commandBuffer->copyImage( - srcImageVk->getImage().getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dstImageVk->getImage().getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); + vk::Renderer *renderer = mContext->getRenderer(); + commandBuffer->copyImage(srcImageVk->getImage().getImage(), + srcImageVk->getImage().getCurrentLayout(renderer), + dstImageVk->getImage().getImage(), + dstImageVk->getImage().getCurrentLayout(renderer), 1, ©Region); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueFillImage(const cl::Image &image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); CLImageVk &imageVk = image.getImpl(); @@ -983,134 +1043,123 @@ angle::Result CLCommandQueueVk::enqueueFillImage(const cl::Image &image, imageVk.packPixels(fillColor, &packedColor); - if (imageVk.isStagingBufferInitialized() == false) - { - ANGLE_TRY(imageVk.createStagingBuffer(imageVk.getSize())); - } + CLBufferVk *stagingBuffer = nullptr; + ANGLE_TRY(imageVk.getOrCreateStagingBuffer(&stagingBuffer)); + ASSERT(stagingBuffer); - ANGLE_TRY(copyImageToFromBuffer(imageVk, imageVk.getStagingBuffer(), cl::kMemOffsetsZero, - {extent.width, extent.height, extent.depth}, 0, + VkBufferImageCopy copyRegion = + CalculateBufferImageCopyRegion(0, 0, 0, cl::kOffsetZero, extent, &imageVk); + ANGLE_TRY(copyImageToFromBuffer(imageVk, *stagingBuffer, copyRegion, ImageBufferCopyDirection::ToBuffer)); ANGLE_TRY(finishInternal()); - uint8_t *mapPointer = nullptr; - ANGLE_TRY(imageVk.map(mapPointer, 0)); - imageVk.fillImageWithColor(origin, region, mapPointer, &packedColor); - imageVk.unmap(); - mapPointer = nullptr; - ANGLE_TRY(copyImageToFromBuffer(imageVk, imageVk.getStagingBuffer(), cl::kMemOffsetsZero, - {extent.width, extent.height, extent.depth}, 0, - ImageBufferCopyDirection::ToImage)); + ANGLE_TRY(imageVk.fillImageWithColor(origin, region, &packedColor)); - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); + copyRegion = CalculateBufferImageCopyRegion(0, 0, 0, cl::kOffsetZero, extent, &imageVk); + ANGLE_TRY(copyImageToFromBuffer(imageVk, *stagingBuffer, copyRegion, + ImageBufferCopyDirection::ToImage)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueCopyImageToBuffer(const cl::Image &srcImage, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); - CLImageVk &srcImageVk = srcImage.getImpl(); - CLBufferVk &dstBufferVk = dstBuffer.getImpl(); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - ANGLE_TRY(copyImageToFromBuffer(srcImageVk, dstBufferVk.getBuffer(), srcOrigin, region, - dstOffset, ImageBufferCopyDirection::ToBuffer)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); + CLImageVk &srcImageVk = srcImage.getImpl(); + CLBufferVk &dstBufferVk = dstBuffer.getImpl(); + VkBufferImageCopy copyRegion = + CalculateBufferImageCopyRegion(dstOffset, 0, 0, srcOrigin, region, &srcImageVk); + ANGLE_TRY(copyImageToFromBuffer(srcImageVk, dstBufferVk, copyRegion, + ImageBufferCopyDirection::ToBuffer)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueCopyBufferToImage(const cl::Buffer &srcBuffer, const cl::Image &dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); - CLBufferVk &srcBufferVk = srcBuffer.getImpl(); - CLImageVk &dstImageVk = dstImage.getImpl(); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - ANGLE_TRY(copyImageToFromBuffer(dstImageVk, srcBufferVk.getBuffer(), dstOrigin, region, - srcOffset, ImageBufferCopyDirection::ToImage)); - - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); + CLBufferVk &srcBufferVk = srcBuffer.getImpl(); + CLImageVk &dstImageVk = dstImage.getImpl(); + VkBufferImageCopy copyRegion = + CalculateBufferImageCopyRegion(srcOffset, 0, 0, dstOrigin, region, &dstImageVk); + ANGLE_TRY(copyImageToFromBuffer(dstImageVk, srcBufferVk, copyRegion, + ImageBufferCopyDirection::ToImage)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueMapImage(const cl::Image &image, bool blocking, cl::MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Complete)); ANGLE_TRY(processWaitlist(waitEvents)); - // TODO: Look into better enqueue handling of this map-op if non-blocking - // https://anglebug.com/376722715 CLImageVk *imageVk = &image.getImpl(); cl::Extents extent = imageVk->getImageExtent(); - if (blocking) - { - ANGLE_TRY(finishInternal()); - } + size_t elementSize = imageVk->getElementSize(); + size_t rowPitch = imageVk->getRowPitch(); + size_t offset = + (origin.x * elementSize) + (origin.y * rowPitch) + (origin.z * extent.height * rowPitch); + size_t size = (region.width * region.height * region.depth * elementSize); mComputePassCommands->imageRead(mContext, imageVk->getImage().getAspectFlags(), - vk::ImageLayout::TransferSrc, &imageVk->getImage()); + vk::ImageAccess::TransferSrc, &imageVk->getImage()); - if (imageVk->isStagingBufferInitialized() == false) - { - ANGLE_TRY(imageVk->createStagingBuffer(imageVk->getSize())); - } + CLBufferVk *stagingBuffer = nullptr; + ANGLE_TRY(imageVk->getOrCreateStagingBuffer(&stagingBuffer)); - ANGLE_TRY(copyImageToFromBuffer(*imageVk, imageVk->getStagingBuffer(), cl::kMemOffsetsZero, - {extent.width, extent.height, extent.depth}, 0, + VkBufferImageCopy copyRegion = + CalculateBufferImageCopyRegion(0, 0, 0, cl::kOffsetZero, extent, imageVk); + ANGLE_TRY(copyImageToFromBuffer(*imageVk, *stagingBuffer, copyRegion, ImageBufferCopyDirection::ToBuffer)); + if (blocking) { ANGLE_TRY(finishInternal()); } uint8_t *mapPointer = nullptr; - size_t elementSize = imageVk->getElementSize(); - size_t rowPitch = (extent.width * elementSize); - size_t offset = - (origin.x * elementSize) + (origin.y * rowPitch) + (origin.z * extent.height * rowPitch); - size_t size = (region.x * region.y * region.z * elementSize); + ANGLE_TRY(imageVk->map(mapPointer, offset)); + mapPtr = mapPointer; if (image.getFlags().intersects(CL_MEM_USE_HOST_PTR)) { - mapPointer = static_cast(image.getHostPtr()) + offset; ANGLE_TRY(imageVk->copyTo(mapPointer, offset, size)); } - else - { - ANGLE_TRY(imageVk->map(mapPointer, offset)); - } - mapPtr = static_cast(mapPointer); - - *imageRowPitch = rowPitch; + // The staging buffer is tightly packed, with no rowpitch and slicepitch. And in UHP case, row + // and slice are always zero. + *imageRowPitch = extent.width * elementSize; switch (imageVk->getDescriptor().type) { case cl::MemObjectType::Image1D: @@ -1133,25 +1182,22 @@ angle::Result CLCommandQueueVk::enqueueMapImage(const cl::Image &image, break; } - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Complete)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueUnmapMemObject(const cl::Memory &memory, void *mappedPtr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - cl::ExecutionStatus eventComplete = cl::ExecutionStatus::Queued; - if (!eventCreateFunc) + if (!event) { ANGLE_TRY(finishInternal()); - eventComplete = cl::ExecutionStatus::Complete; } if (memory.getType() == cl::MemObjectType::Buffer) @@ -1161,7 +1207,6 @@ angle::Result CLCommandQueueVk::enqueueUnmapMemObject(const cl::Memory &memory, { ANGLE_TRY(finishInternal()); ANGLE_TRY(bufferVk.copyFrom(memory.getHostPtr(), 0, bufferVk.getSize())); - eventComplete = cl::ExecutionStatus::Complete; } } else if (memory.getType() != cl::MemObjectType::Pipe) @@ -1173,12 +1218,17 @@ angle::Result CLCommandQueueVk::enqueueUnmapMemObject(const cl::Memory &memory, uint8_t *mapPointer = static_cast(memory.getHostPtr()); ANGLE_TRY(imageVk.copyStagingFrom(mapPointer, 0, imageVk.getSize())); } - cl::Extents extent = imageVk.getImageExtent(); - ANGLE_TRY(copyImageToFromBuffer(imageVk, imageVk.getStagingBuffer(), cl::kMemOffsetsZero, - {extent.width, extent.height, extent.depth}, 0, + cl::Extents extent = imageVk.getImageExtent(); + CLBufferVk *stagingBuffer = nullptr; + ANGLE_TRY(imageVk.getOrCreateStagingBuffer(&stagingBuffer)); + ASSERT(stagingBuffer); + + VkBufferImageCopy copyRegion = + CalculateBufferImageCopyRegion(0, 0, 0, cl::kOffsetZero, extent, &imageVk); + ANGLE_TRY(copyImageToFromBuffer(imageVk, *stagingBuffer, copyRegion, ImageBufferCopyDirection::ToImage)); + ANGLE_TRY(finishInternal()); - eventComplete = cl::ExecutionStatus::Complete; } else { @@ -1188,18 +1238,18 @@ angle::Result CLCommandQueueVk::enqueueUnmapMemObject(const cl::Memory &memory, } memory.getImpl().unmap(); - ANGLE_TRY(createEvent(eventCreateFunc, eventComplete)); - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueMigrateMemObjects(const cl::MemoryPtrs &memObjects, cl::MemMigrationFlags flags, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Complete)); ANGLE_TRY(processWaitlist(waitEvents)); if (mCommandQueue.getContext().getDevices().size() > 1) @@ -1210,18 +1260,17 @@ angle::Result CLCommandQueueVk::enqueueMigrateMemObjects(const cl::MemoryPtrs &m ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); } - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Complete)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueNDRangeKernel(const cl::Kernel &kernel, const cl::NDRange &ndrange, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); vk::PipelineCacheAccess pipelineCache; @@ -1320,55 +1369,53 @@ angle::Result CLCommandQueueVk::enqueueNDRangeKernel(const cl::Kernel &kernel, uniformRegionWorkgroupCount[2]); } - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueTask(const cl::Kernel &kernel, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { constexpr size_t globalWorkSize[3] = {1, 0, 0}; constexpr size_t localWorkSize[3] = {1, 0, 0}; cl::NDRange ndrange(1, nullptr, globalWorkSize, localWorkSize); - return enqueueNDRangeKernel(kernel, ndrange, waitEvents, eventCreateFunc); + return enqueueNDRangeKernel(kernel, ndrange, waitEvents, event); } angle::Result CLCommandQueueVk::enqueueNativeKernel(cl::UserFunc userFunc, void *args, size_t cbArgs, const cl::BufferPtrs &buffers, - const std::vector bufferPtrOffsets, + const std::vector &bufferPtrOffsets, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { UNIMPLEMENTED(); ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); } angle::Result CLCommandQueueVk::enqueueMarkerWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); ANGLE_TRY(processWaitlist(waitEvents)); - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); - return angle::Result::Continue; + return postEnqueueOps(event); } -angle::Result CLCommandQueueVk::enqueueMarker(CLEventImpl::CreateFunc &eventCreateFunc) +angle::Result CLCommandQueueVk::enqueueMarker(cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); + // This deprecated API is essentially a super-set of clEnqueueBarrier, where we also return // an event object (i.e. marker) since clEnqueueBarrier does not provide this ANGLE_TRY(insertBarrier()); - ANGLE_TRY(createEvent(&eventCreateFunc, cl::ExecutionStatus::Queued)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::enqueueWaitForEvents(const cl::EventPtrs &events) @@ -1382,10 +1429,12 @@ angle::Result CLCommandQueueVk::enqueueWaitForEvents(const cl::EventPtrs &events } angle::Result CLCommandQueueVk::enqueueBarrierWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) + cl::EventPtr &event) { std::scoped_lock sl(mCommandQueueMutex); + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Queued)); + // The barrier command either waits for a list of events to complete, or if the list is // empty it waits for all commands previously enqueued in command_queue to complete before // it completes @@ -1398,9 +1447,7 @@ angle::Result CLCommandQueueVk::enqueueBarrierWithWaitList(const cl::EventPtrs & ANGLE_TRY(processWaitlist(waitEvents)); } - ANGLE_TRY(createEvent(eventCreateFunc, cl::ExecutionStatus::Queued)); - - return angle::Result::Continue; + return postEnqueueOps(event); } angle::Result CLCommandQueueVk::insertBarrier() @@ -1449,74 +1496,98 @@ angle::Result CLCommandQueueVk::finish() return finishInternal(); } -angle::Result CLCommandQueueVk::syncHostBuffers(HostTransferEntries &hostTransferList) +angle::Result CLCommandQueueVk::enqueueAcquireExternalMemObjectsKHR( + const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) { - if (!hostTransferList.empty()) + std::scoped_lock sl(mCommandQueueMutex); + + // for Vulkan imported memory, Vulkan driver already acquired ownership during buffer/image + // create with properties, so nothing left to do here other than event processing + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Complete)); + ANGLE_TRY(processWaitlist(waitEvents)); + + return postEnqueueOps(event); +} + +angle::Result CLCommandQueueVk::enqueueReleaseExternalMemObjectsKHR( + const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) +{ + std::scoped_lock sl(mCommandQueueMutex); + + // since we dup'ed the fd during buffer/image create with properties, there is no "releasing" + // back to user (unlike VkImportMemoryFdInfoKHR), thus nothing left to do here except for + // event processing + ANGLE_TRY(preEnqueueOps(event, cl::ExecutionStatus::Complete)); + ANGLE_TRY(processWaitlist(waitEvents)); + + return postEnqueueOps(event); +} + +angle::Result CLCommandQueueVk::addMemoryDependencies(const CLKernelArgument *arg) +{ + if (IsCLKernelArgumentReadonly(*arg)) { - for (const HostTransferEntry &hostTransferEntry : hostTransferList) - { - const HostTransferConfig &transferConfig = hostTransferEntry.transferConfig; - CLBufferVk &transferBufferVk = - hostTransferEntry.transferBufferHandle->getImpl(); - switch (hostTransferEntry.transferConfig.type) - { - case CL_COMMAND_FILL_BUFFER: - case CL_COMMAND_WRITE_BUFFER: - case CL_COMMAND_WRITE_BUFFER_RECT: - // Nothing left to do here - break; - case CL_COMMAND_READ_BUFFER: - case CL_COMMAND_READ_IMAGE: - if (transferConfig.rowPitch == 0 && transferConfig.slicePitch == 0) - { - ANGLE_TRY(transferBufferVk.copyTo( - transferConfig.dstHostPtr, transferConfig.offset, transferConfig.size)); - } - else - { - ANGLE_TRY(transferBufferVk.copyToWithPitch( - transferConfig.dstHostPtr, transferConfig.offset, transferConfig.size, - transferConfig.rowPitch, transferConfig.slicePitch, - transferConfig.region, transferConfig.elementSize)); - } - break; - case CL_COMMAND_READ_BUFFER_RECT: - ANGLE_TRY(transferBufferVk.getRect( - transferConfig.srcRect, transferConfig.dstRect, transferConfig.dstHostPtr)); - break; - default: - UNIMPLEMENTED(); - break; - } - } + return addMemoryDependencies(GetCLKernelArgumentMemoryHandle(*arg), + MemoryHandleAccess::ReadOnly); + } + else + { + return addMemoryDependencies(GetCLKernelArgumentMemoryHandle(*arg), + MemoryHandleAccess::Writeable); } - hostTransferList.clear(); - - return angle::Result::Continue; } -angle::Result CLCommandQueueVk::addMemoryDependencies(cl::Memory *clMem) +angle::Result CLCommandQueueVk::addMemoryDependencies(cl::Memory *clMem, MemoryHandleAccess access) { - cl::Memory *parentMem = clMem->getParent() ? clMem->getParent().get() : nullptr; + bool isWritable = access == MemoryHandleAccess::Writeable; + cl::Memory *parentMem = clMem->getParent().get(); // Take an usage count - mCommandsStateMap[mComputePassCommands->getQueueSerial()].memories.emplace_back(clMem); + mCommandsStateMap.addMemory(mComputePassCommands->getQueueSerial(), clMem); - // Handle possible resource RAW hazard - bool insertBarrier = false; - if (clMem->getFlags().intersects(CL_MEM_READ_WRITE)) + // Handle possible resource hazards + bool needsBarrier = false; + // A barrier is needed in the following cases + // - Presence of a pending write, irrespective of the current usage + // - A write usage with a pending read + if (mWriteDependencyTracker.contains(clMem) || mWriteDependencyTracker.contains(parentMem) || + mWriteDependencyTracker.size() == kMaxDependencyTrackerSize) + { + needsBarrier = true; + } + else if (isWritable && (mReadDependencyTracker.contains(clMem) || + mReadDependencyTracker.contains(parentMem) || + mReadDependencyTracker.size() == kMaxDependencyTrackerSize)) { - // Texel buffers have backing buffer objects - if (mDependencyTracker.contains(clMem) || mDependencyTracker.contains(parentMem) || - mDependencyTracker.size() == kMaxDependencyTrackerSize) + needsBarrier = true; + } + + // If a barrier is inserted with the current usage, we can safely clear existing dependencies as + // this barrier signalling ensures their completion. + if (needsBarrier) + { + mReadDependencyTracker.clear(); + mWriteDependencyTracker.clear(); + } + // Add the current mem object, to the appropriate dependency list + if (isWritable) + { + mWriteDependencyTracker.insert(clMem); + if (parentMem) { - insertBarrier = true; - mDependencyTracker.clear(); + mWriteDependencyTracker.insert(parentMem); } - mDependencyTracker.insert(clMem); + } + else + { + mReadDependencyTracker.insert(clMem); if (parentMem) { - mDependencyTracker.insert(parentMem); + mReadDependencyTracker.insert(parentMem); } } @@ -1526,14 +1597,11 @@ angle::Result CLCommandQueueVk::addMemoryDependencies(cl::Memory *clMem) CLImageVk &vkMem = clMem->getImpl(); mComputePassCommands->imageWrite(mContext, gl::LevelIndex(0), 0, 1, vkMem.getImage().getAspectFlags(), - vk::ImageLayout::ComputeShaderWrite, &vkMem.getImage()); + vk::ImageAccess::ComputeShaderWrite, &vkMem.getImage()); } - else if (insertBarrier && cl::IsBufferType(clMem->getType())) + if (needsBarrier) { - CLBufferVk &vkMem = clMem->getImpl(); - - mComputePassCommands->bufferWrite(mContext, VK_ACCESS_SHADER_WRITE_BIT, - vk::PipelineStage::ComputeShader, &vkMem.getBuffer()); + ANGLE_TRY(insertBarrier()); } return angle::Result::Continue; @@ -1541,45 +1609,66 @@ angle::Result CLCommandQueueVk::addMemoryDependencies(cl::Memory *clMem) angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) { + vk::Renderer *renderer = mContext->getRenderer(); bool podBufferPresent = false; uint32_t podBinding = 0; VkDescriptorType podDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - bool needsBarrier = false; const CLProgramVk::DeviceProgramData *devProgramData = kernelVk.getProgram()->getDeviceProgramData(mCommandQueue.getDevice().getNative()); ASSERT(devProgramData != nullptr); - // Set the descriptor set layouts and allocate descriptor sets - // The descriptor set layouts are setup in the order of their appearance, as Vulkan requires - // them to point to valid handles. angle::EnumIterator layoutIndex(DescriptorSetIndex::LiteralSampler); for (DescriptorSetIndex index : angle::AllEnums()) { if (!kernelVk.getDescriptorSetLayoutDesc(index).empty()) { - // Setup the descriptor layout - ANGLE_CL_IMPL_TRY_ERROR(mContext->getDescriptorSetLayoutCache()->getDescriptorSetLayout( - mContext, kernelVk.getDescriptorSetLayoutDesc(index), - &kernelVk.getDescriptorSetLayouts()[*layoutIndex]), - CL_INVALID_OPERATION); - ASSERT(kernelVk.getDescriptorSetLayouts()[*layoutIndex]->valid()); - - // Allocate descriptor set ANGLE_TRY(mContext->allocateDescriptorSet(&kernelVk, index, layoutIndex, mComputePassCommands)); ++layoutIndex; } } - // Setup the pipeline layout - ANGLE_CL_IMPL_TRY_ERROR(kernelVk.initPipelineLayout(), CL_INVALID_OPERATION); - // Retain kernel object until we finish executing it later - mCommandsStateMap[mComputePassCommands->getQueueSerial()].kernels.emplace_back( - &kernelVk.getFrontendObject()); + mCommandsStateMap.addKernel(mComputePassCommands->getQueueSerial(), + &kernelVk.getFrontendObject()); - // Process each kernel argument/resource + // Process descriptor sets used by the kernel vk::DescriptorSetArray updateDescriptorSetsBuilders; + + UpdateDescriptorSetsBuilder &literalSamplerDescSetBuilder = + updateDescriptorSetsBuilders[DescriptorSetIndex::LiteralSampler]; + + // Create/Setup Literal Sampler + for (const ClspvLiteralSampler &literalSampler : devProgramData->reflectionData.literalSamplers) + { + cl::SamplerPtr clLiteralSampler = + cl::SamplerPtr(cl::Sampler::Cast(this->mContext->getFrontendObject().createSampler( + literalSampler.normalizedCoords, literalSampler.addressingMode, + literalSampler.filterMode))); + + // Release immediately to ensure correct refcount + clLiteralSampler->release(); + ASSERT(clLiteralSampler != nullptr); + CLSamplerVk &vkLiteralSampler = clLiteralSampler->getImpl(); + + VkDescriptorImageInfo &samplerInfo = + literalSamplerDescSetBuilder.allocDescriptorImageInfo(); + samplerInfo.sampler = vkLiteralSampler.getSamplerHelper().get().getHandle(); + samplerInfo.imageView = VK_NULL_HANDLE; + samplerInfo.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkWriteDescriptorSet &writeDescriptorSet = + literalSamplerDescSetBuilder.allocWriteDescriptorSet(); + writeDescriptorSet.descriptorCount = 1; + writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; + writeDescriptorSet.pImageInfo = &samplerInfo; + writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSet.dstSet = kernelVk.getDescriptorSet(DescriptorSetIndex::LiteralSampler); + writeDescriptorSet.dstBinding = literalSampler.binding; + + mCommandsStateMap.addSampler(mComputePassCommands->getQueueSerial(), clLiteralSampler); + } + CLKernelArguments args = kernelVk.getArgs(); UpdateDescriptorSetsBuilder &kernelArgDescSetBuilder = updateDescriptorSetsBuilders[DescriptorSetIndex::KernelArguments]; @@ -1591,10 +1680,11 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) case NonSemanticClspvReflectionArgumentUniform: case NonSemanticClspvReflectionArgumentStorageBuffer: { - cl::Memory *clMem = cl::Buffer::Cast(static_cast(arg.handle)); + cl::Memory *clMem = GetCLKernelArgumentMemoryHandle(arg); + ASSERT(clMem); CLBufferVk &vkMem = clMem->getImpl(); - ANGLE_TRY(addMemoryDependencies(clMem)); + ANGLE_TRY(addMemoryDependencies(&arg)); // Update buffer/descriptor info VkDescriptorBufferInfo &bufferInfo = @@ -1674,10 +1764,11 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) case NonSemanticClspvReflectionArgumentStorageImage: case NonSemanticClspvReflectionArgumentSampledImage: { - cl::Memory *clMem = cl::Image::Cast(static_cast(arg.handle)); - CLImageVk &vkMem = clMem->getImpl(); + cl::Memory *clMem = GetCLKernelArgumentMemoryHandle(arg); + ASSERT(clMem); + CLImageVk &vkMem = clMem->getImpl(); - ANGLE_TRY(addMemoryDependencies(clMem)); + ANGLE_TRY(addMemoryDependencies(&arg)); cl_image_format imageFormat = vkMem.getFormat(); const VkPushConstantRange *imageDataChannelOrderRange = @@ -1703,12 +1794,12 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) // Update image/descriptor info VkDescriptorImageInfo &imageInfo = kernelArgDescSetBuilder.allocDescriptorImageInfo(); - imageInfo.imageLayout = - arg.type == NonSemanticClspvReflectionArgumentStorageImage - ? VK_IMAGE_LAYOUT_GENERAL - : vkMem.getImage().getCurrentLayout(mContext->getRenderer()); - imageInfo.imageView = vkMem.getImageView().getHandle(); - imageInfo.sampler = VK_NULL_HANDLE; + // TODO: Can't this always be vkMem.getImage().getCurrentLayout(renderer)? + imageInfo.imageLayout = arg.type == NonSemanticClspvReflectionArgumentStorageImage + ? VK_IMAGE_LAYOUT_GENERAL + : vkMem.getImage().getCurrentLayout(renderer); + imageInfo.imageView = vkMem.getImageView().getHandle(); + imageInfo.sampler = VK_NULL_HANDLE; VkWriteDescriptorSet &writeDescriptorSet = kernelArgDescSetBuilder.allocWriteDescriptorSet(); writeDescriptorSet.descriptorCount = 1; @@ -1726,10 +1817,10 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) case NonSemanticClspvReflectionArgumentUniformTexelBuffer: case NonSemanticClspvReflectionArgumentStorageTexelBuffer: { - cl::Memory *clMem = cl::Image::Cast(static_cast(arg.handle)); + cl::Memory *clMem = GetCLKernelArgumentMemoryHandle(arg); CLImageVk &vkMem = clMem->getImpl(); - ANGLE_TRY(addMemoryDependencies(clMem)); + ANGLE_TRY(addMemoryDependencies(&arg)); VkBufferView &bufferView = kernelArgDescSetBuilder.allocBufferView(); const vk::BufferView *vkBufferView = nullptr; @@ -1765,8 +1856,70 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) } break; } - case NonSemanticClspvReflectionArgumentPointerUniform: case NonSemanticClspvReflectionArgumentPointerPushConstant: + { + unsigned char *argPushConstOrigin = + &(kernelVk.getPodArgumentPushConstantsData()[arg.pushConstOffset]); + if (static_cast(arg.handle) == NULL) + { + // If the argument is a buffer object, the arg_value pointer can be NULL or + // point to a NULL value in which case a NULL value will be used as the value + // for the argument declared as a pointer to global or constant memory in the + // kernel. + uint64_t null = 0; + std::memcpy(argPushConstOrigin, &null, arg.handleSize); + } + else + { + cl::Memory *clMem = cl::Buffer::Cast(static_cast(arg.handle)); + CLBufferVk &vkMem = clMem->getImpl(); + + ANGLE_TRY(addMemoryDependencies(&arg)); + + uint64_t devAddr = + vkMem.getBuffer().getDeviceAddress(mContext) + vkMem.getOffset(); + std::memcpy(argPushConstOrigin, &devAddr, arg.handleSize); + } + + mComputePassCommands->getCommandBuffer().pushConstants( + kernelVk.getPipelineLayout(), VK_SHADER_STAGE_COMPUTE_BIT, + roundDownPow2(arg.pushConstOffset, 4u), roundUpPow2(arg.pushConstantSize, 4u), + argPushConstOrigin); + + break; + } + case NonSemanticClspvReflectionArgumentPointerUniform: + { + ASSERT(kernelVk.getPodBuffer()->getSize() >= arg.handleSize + arg.podUniformOffset); + if (static_cast(arg.handle) == NULL) + { + // If the argument is a buffer object, the arg_value pointer can be NULL or + // point to a NULL value in which case a NULL value will be used as the value + // for the argument declared as a pointer to global or constant memory in the + // kernel. + uint64_t null = 0; + ANGLE_TRY(kernelVk.getPodBuffer()->getImpl().copyFrom( + &null, arg.podStorageBufferOffset, arg.handleSize)); + } + else + { + cl::Memory *clMem = cl::Buffer::Cast(static_cast(arg.handle)); + CLBufferVk &vkMem = clMem->getImpl(); + ANGLE_TRY(addMemoryDependencies(&arg)); + uint64_t devAddr = + vkMem.getBuffer().getDeviceAddress(mContext) + vkMem.getOffset(); + ANGLE_TRY(kernelVk.getPodBuffer()->getImpl().copyFrom( + &devAddr, arg.podStorageBufferOffset, arg.handleSize)); + } + + if (!podBufferPresent) + { + podBufferPresent = true; + podBinding = arg.descriptorBinding; + podDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + } + break; + } default: { UNIMPLEMENTED(); @@ -1776,6 +1929,8 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) } if (podBufferPresent) { + // POD arguments exceeded the push constant size and are packaged in a storage buffer. Setup + // commands and dependencies accordingly. cl::MemoryPtr clMem = kernelVk.getPodBuffer(); ASSERT(clMem != nullptr); CLBufferVk &vkMem = clMem->getImpl(); @@ -1785,7 +1940,14 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) bufferInfo.offset = clMem->getOffset(); bufferInfo.buffer = vkMem.getBuffer().getBuffer().getHandle(); - ANGLE_TRY(addMemoryDependencies(clMem.get())); + if (clMem->getFlags().intersects(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY)) + { + ANGLE_TRY(addMemoryDependencies(clMem.get(), MemoryHandleAccess::Writeable)); + } + else + { + ANGLE_TRY(addMemoryDependencies(clMem.get(), MemoryHandleAccess::ReadOnly)); + } VkWriteDescriptorSet &writeDescriptorSet = kernelArgDescSetBuilder.allocWriteDescriptorSet(); @@ -1800,6 +1962,32 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) writeDescriptorSet.pBufferInfo = &bufferInfo; } + // Create Module Constant Data Buffer + if (devProgramData->reflectionData.pushConstants.contains( + NonSemanticClspvReflectionConstantDataPointerPushConstant)) + { + cl::MemoryPtr clMem = + kernelVk.getProgram()->getOrCreateModuleConstantDataBuffer(kernelVk.getKernelName()); + CLBufferVk &vkMem = clMem->getImpl(); + uint64_t devAddr = vkMem.getBuffer().getDeviceAddress(mContext) + vkMem.getOffset(); + + if (clMem->getFlags().intersects(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY)) + { + ANGLE_TRY(addMemoryDependencies(clMem.get(), MemoryHandleAccess::Writeable)); + } + else + { + ANGLE_TRY(addMemoryDependencies(clMem.get(), MemoryHandleAccess::ReadOnly)); + } + + const VkPushConstantRange *pushConstantRangePtr = + &devProgramData->reflectionData.pushConstants.at( + NonSemanticClspvReflectionConstantDataPointerPushConstant); + mComputePassCommands->getCommandBuffer().pushConstants( + kernelVk.getPipelineLayout(), VK_SHADER_STAGE_COMPUTE_BIT, pushConstantRangePtr->offset, + pushConstantRangePtr->size, &devAddr); + } + // process the printf storage buffer if (kernelVk.usesPrintf()) { @@ -1813,23 +2001,37 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) // The spec calls out *The first 4 bytes of the buffer should be zero-initialized.* memset(mapPointer, 0, 4); - auto &bufferInfo = printfDescSetBuilder.allocDescriptorBufferInfo(); - bufferInfo.range = clMem->getSize(); - bufferInfo.offset = clMem->getOffset(); - bufferInfo.buffer = vkMem.getBuffer().getBuffer().getHandle(); - - auto &writeDescriptorSet = printfDescSetBuilder.allocWriteDescriptorSet(); - writeDescriptorSet.descriptorCount = 1; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - writeDescriptorSet.pBufferInfo = &bufferInfo; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = kernelVk.getDescriptorSet(DescriptorSetIndex::Printf); - writeDescriptorSet.dstBinding = kernelVk.getProgram() - ->getDeviceProgramData(kernelVk.getKernelName().c_str()) - ->reflectionData.printfBufferStorage.binding; + if (kernelVk.usesPrintfBufferPointerPushConstant()) + { + const VkPushConstantRange *pushConstantRangePtr = + &devProgramData->reflectionData.pushConstants.at( + NonSemanticClspvReflectionPrintfBufferPointerPushConstant); + uint64_t devAddr = vkMem.getBuffer().getDeviceAddress(mContext) + vkMem.getOffset(); + // Push printf push-constant to command buffer + mComputePassCommands->getCommandBuffer().pushConstants( + kernelVk.getPipelineLayout(), VK_SHADER_STAGE_COMPUTE_BIT, + pushConstantRangePtr->offset, pushConstantRangePtr->size, &devAddr); + } + else + { + auto &bufferInfo = printfDescSetBuilder.allocDescriptorBufferInfo(); + bufferInfo.range = clMem->getSize(); + bufferInfo.offset = clMem->getOffset(); + bufferInfo.buffer = vkMem.getBuffer().getBuffer().getHandle(); + + auto &writeDescriptorSet = printfDescSetBuilder.allocWriteDescriptorSet(); + writeDescriptorSet.descriptorCount = 1; + writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + writeDescriptorSet.pBufferInfo = &bufferInfo; + writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSet.dstSet = kernelVk.getDescriptorSet(DescriptorSetIndex::Printf); + writeDescriptorSet.dstBinding = + kernelVk.getProgram() + ->getDeviceProgramData(kernelVk.getKernelName().c_str()) + ->reflectionData.printfBufferStorage.binding; + } mNeedPrintfHandling = true; - mPrintfInfos = kernelVk.getProgram()->getPrintfDescriptors(kernelVk.getKernelName()); } angle::EnumIterator descriptorSetIndex(DescriptorSetIndex::LiteralSampler); @@ -1839,7 +2041,7 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) { mContext->getPerfCounters().writeDescriptorSets = updateDescriptorSetsBuilders[index].flushDescriptorSetUpdates( - mContext->getRenderer()->getDevice()); + renderer->getDevice()); VkDescriptorSet descriptorSet = kernelVk.getDescriptorSet(index); mComputePassCommands->getCommandBuffer().bindDescriptorSets( @@ -1850,11 +2052,6 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk) } } - if (needsBarrier) - { - ANGLE_TRY(insertBarrier()); - } - return angle::Result::Continue; } @@ -1928,11 +2125,15 @@ angle::Result CLCommandQueueVk::flushComputePassCommands() VK_PIPELINE_STAGE_HOST_BIT, memoryBarrier); } + if (mContext->getRenderer()->getFeatures().debugClDumpCommandStream.enabled) + { + addCommandBufferDiagnostics(mComputePassCommands->getCommandDiagnostics()); + } + // get hold of the queue serial that is flushed, post the flush the command buffer will be reset mLastFlushedQueueSerial = mComputePassCommands->getQueueSerial(); // Here, we flush our compute cmds to RendererVk's primary command buffer - ANGLE_TRY(mContext->getRenderer()->flushOutsideRPCommands( - mContext, getProtectionType(), egl::ContextPriority::Medium, &mComputePassCommands)); + ANGLE_TRY(mCommandState.flushOutsideRPCommands(mContext, &mComputePassCommands)); mContext->getPerfCounters().flushedOutsideRenderPassCommandBuffers++; @@ -1940,34 +2141,35 @@ angle::Result CLCommandQueueVk::flushComputePassCommands() mComputePassCommands->setQueueSerial( mQueueSerialIndex, mContext->getRenderer()->generateQueueSerial(mQueueSerialIndex)); - return angle::Result::Continue; + return mCommandsStateMap.setEventsWithQueueSerialToState(mLastFlushedQueueSerial, + cl::ExecutionStatus::Submitted); } angle::Result CLCommandQueueVk::processWaitlist(const cl::EventPtrs &waitEvents) { if (!waitEvents.empty()) { - bool insertedBarrier = false; + bool needsBarrier = false; for (const cl::EventPtr &event : waitEvents) { - if (event->getImpl().isUserEvent() || - event->getCommandQueue() != &mCommandQueue) + if (event->isUserEvent() || event->getCommandQueue() != &mCommandQueue) { - // We cannot use a barrier in these cases, therefore defer the event - // handling till submission time - // TODO: Perhaps we could utilize VkEvents here instead and have GPU wait(s) - // https://anglebug.com/42267109 + // Track the user and external cq events separately mExternalEvents.push_back(event); } - else if (event->getCommandQueue() == &mCommandQueue && !insertedBarrier) + if (!event->isUserEvent()) { - // As long as there is at least one dependant command in same queue, - // we just need to insert one execution barrier - ANGLE_TRY(insertBarrier()); - - insertedBarrier = true; + // At the moment, the vulkan backend is set up with single queue for all the command + // buffer recording (only if the Vk Queue priorities match). + // So inserting a barrier (in this case) is enough to ensure dependencies here. + needsBarrier |= + event->getCommandQueue()->getPriority() == mCommandQueue.getPriority(); } } + if (needsBarrier) + { + ANGLE_TRY(insertBarrier()); + } } return angle::Result::Continue; } @@ -1978,10 +2180,14 @@ angle::Result CLCommandQueueVk::submitCommands() ASSERT(hasCommandsPendingSubmission()); + if (mContext->getRenderer()->getFeatures().debugClDumpCommandStream.enabled) + { + mContext->dumpCommandStreamDiagnostics(); + } + // Kick off renderer submit - ANGLE_TRY(mContext->getRenderer()->submitCommands(mContext, getProtectionType(), - egl::ContextPriority::Medium, nullptr, - nullptr, {}, mLastFlushedQueueSerial)); + ANGLE_TRY(mContext->getRenderer()->submitCommands( + mContext, nullptr, nullptr, mLastFlushedQueueSerial, std::move(mCommandState))); mLastSubmittedQueueSerial = mLastFlushedQueueSerial; @@ -1989,25 +2195,52 @@ angle::Result CLCommandQueueVk::submitCommands() // and should be moved to garbage list. mContext->getRenderer()->cleanupPendingSubmissionGarbage(); - return angle::Result::Continue; + return mCommandsStateMap.setEventsWithQueueSerialToState(mLastSubmittedQueueSerial, + cl::ExecutionStatus::Running); } -angle::Result CLCommandQueueVk::createEvent(CLEventImpl::CreateFunc *createFunc, - cl::ExecutionStatus initialStatus) +angle::Result CLCommandQueueVk::preEnqueueOps(cl::EventPtr &event, + cl::ExecutionStatus initialStatus) { - if (createFunc != nullptr) + if (event != nullptr) { - *createFunc = [initialStatus, queueSerial = mComputePassCommands->getQueueSerial()]( - const cl::Event &event) { - auto eventVk = new (std::nothrow) CLEventVk(event, initialStatus, queueSerial); + ANGLE_TRY(event->initBackend([initialStatus](const cl::Event &event) { + auto eventVk = new (std::nothrow) CLEventVk(event, initialStatus); if (eventVk == nullptr) { ERR() << "Failed to create cmd event obj!"; return CLEventImpl::Ptr(nullptr); } return CLEventImpl::Ptr(eventVk); - }; + })); + } + + return angle::Result::Continue; +} + +angle::Result CLCommandQueueVk::postEnqueueOps(const cl::EventPtr &event) +{ + if (event != nullptr) + { + ASSERT(event->isBackendInitialized() && "backend event state is invalid!"); + + cl_int status; + CLEventVk &eventVk = event->getImpl(); + ANGLE_TRY(eventVk.getCommandExecutionStatus(status)); + if (cl::FromCLenum(status) == cl::ExecutionStatus::Complete) + { + // skip event association if command is already complete + return angle::Result::Continue; + } + eventVk.setQueueSerial(mComputePassCommands->getQueueSerial()); + mCommandsStateMap.addEvent(eventVk.getQueueSerial(), event); + } + + if (mContext->getRenderer()->getFeatures().clSerializedExecution.enabled) + { + ANGLE_TRY(finishInternal()); } + return angle::Result::Continue; } @@ -2038,15 +2271,8 @@ angle::Result CLCommandQueueVk::resetCommandBufferWithError(cl_int errorCode) QueueSerial currentSerial = mComputePassCommands->getQueueSerial(); mComputePassCommands->getCommandBuffer().reset(); - for (cl::EventPtr event : mCommandsStateMap[currentSerial].events) - { - CLEventVk *eventVk = &event->getImpl(); - if (!eventVk->isUserEvent()) - { - ANGLE_TRY( - eventVk->setStatusAndExecuteCallback(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST)); - } - } + ANGLE_TRY(mCommandsStateMap.setEventsWithQueueSerialToState(currentSerial, + cl::ExecutionStatus::InvalidEnum)); mCommandsStateMap.erase(currentSerial); mExternalEvents.clear(); @@ -2067,19 +2293,17 @@ angle::Result CLCommandQueueVk::finishQueueSerialInternal(const QueueSerial queu ANGLE_TRY(mContext->getRenderer()->finishQueueSerial(mContext, queueSerial)); // Ensure memory objects are synced back to host CPU - ANGLE_TRY(syncHostBuffers(mCommandsStateMap[queueSerial].hostTransferList)); + ANGLE_TRY(mCommandsStateMap.processQueueSerial(queueSerial)); if (mNeedPrintfHandling) { - ANGLE_TRY(processPrintfBuffer()); mNeedPrintfHandling = false; } // Events associated with this queue serial and ready to be marked complete - ANGLE_TRY(SetEventsWithQueueSerialToState(mCommandsStateMap[queueSerial].events, queueSerial, - cl::ExecutionStatus::Complete)); + ANGLE_TRY(mCommandsStateMap.setEventsWithQueueSerialToState(queueSerial, + cl::ExecutionStatus::Complete)); - mExternalEvents.clear(); mCommandsStateMap.erase(queueSerial); return angle::Result::Continue; @@ -2122,23 +2346,29 @@ angle::Result CLCommandQueueVk::flushInternal() } else { - // Otherwise, we just need to submit/finish for dependant event queues - // here that are not associated with this queue - ANGLE_TRY(depEvent->getCommandQueue()->finish()); + if (depEvent->getCommandQueue()->getPriority() != mCommandQueue.getPriority()) + { + // this implicitly means that different Vk Queues are used between the + // dependency event queue and this queue. thus, sync/finish here to ensure + // dependencies. + // TODO: Look into Vk Semaphores here to track GPU-side only + // https://anglebug.com/42267109 + ANGLE_TRY(depEvent->getCommandQueue()->finish()); + } + else + { + // We have inserted appropriate pipeline barriers, we just need to flush the + // dependent queue before we submit the commands here. + ANGLE_TRY(depEvent->getCommandQueue()->flush()); + } } } mExternalEvents.clear(); } ANGLE_TRY(flushComputePassCommands()); - CommandsState commandsState = mCommandsStateMap[mLastFlushedQueueSerial]; - ANGLE_TRY(SetEventsWithQueueSerialToState(commandsState.events, mLastFlushedQueueSerial, - cl::ExecutionStatus::Submitted)); - ANGLE_TRY(submitCommands()); ASSERT(!hasCommandsPendingSubmission()); - ANGLE_TRY(SetEventsWithQueueSerialToState(commandsState.events, mLastSubmittedQueueSerial, - cl::ExecutionStatus::Running)); } return angle::Result::Continue; @@ -2154,68 +2384,51 @@ angle::Result CLCommandQueueVk::finishInternal() // Helper function to insert appropriate memory barriers before accessing the resources in the // command buffer. -angle::Result CLCommandQueueVk::onResourceAccess(const vk::CommandBufferAccess &access) +angle::Result CLCommandQueueVk::onResourceAccess(const vk::CommandResources &resources) { // Buffers - for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers()) + for (const vk::CommandResourceBuffer &readBuffer : resources.getReadBuffers()) { - if (mComputePassCommands->usesBufferForWrite(*bufferAccess.buffer)) + if (mComputePassCommands->usesBufferForWrite(*readBuffer.buffer)) { // read buffers only need a new command buffer if previously used for write ANGLE_TRY(flushInternal()); } - mComputePassCommands->bufferRead(mContext, bufferAccess.accessType, bufferAccess.stage, - bufferAccess.buffer); + mComputePassCommands->bufferRead(mContext, readBuffer.accessType, readBuffer.stage, + readBuffer.buffer); } - for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers()) + for (const vk::CommandResourceBuffer &writeBuffer : resources.getWriteBuffers()) { - if (mComputePassCommands->usesBuffer(*bufferAccess.buffer)) + if (mComputePassCommands->usesBuffer(*writeBuffer.buffer)) { // write buffers always need a new command buffer ANGLE_TRY(flushInternal()); } - mComputePassCommands->bufferWrite(mContext, bufferAccess.accessType, bufferAccess.stage, - bufferAccess.buffer); - if (bufferAccess.buffer->isHostVisible()) + mComputePassCommands->bufferWrite(mContext, writeBuffer.accessType, writeBuffer.stage, + writeBuffer.buffer); + if (writeBuffer.buffer->isHostVisible()) { // currently all are host visible so nothing to do } } - for (const vk::CommandBufferBufferExternalAcquireRelease &bufferAcquireRelease : - access.getExternalAcquireReleaseBuffers()) + for (const vk::CommandResourceBufferExternalAcquireRelease &bufferAcquireRelease : + resources.getExternalAcquireReleaseBuffers()) { mComputePassCommands->retainResourceForWrite(bufferAcquireRelease.buffer); } - for (const vk::CommandBufferResourceAccess &resourceAccess : access.getAccessResources()) + for (const vk::CommandResourceGeneric &genericResource : resources.getGenericResources()) { - mComputePassCommands->retainResource(resourceAccess.resource); + mComputePassCommands->retainResource(genericResource.resource); } return angle::Result::Continue; } -angle::Result CLCommandQueueVk::processPrintfBuffer() -{ - ASSERT(mPrintfBuffer); - ASSERT(mNeedPrintfHandling); - ASSERT(mPrintfInfos); - - cl::MemoryPtr clMem = getOrCreatePrintfBuffer(); - CLBufferVk &vkMem = clMem->getImpl(); - - unsigned char *data = nullptr; - ANGLE_TRY(vkMem.map(data, 0)); - ANGLE_TRY(ClspvProcessPrintfBuffer(data, vkMem.getSize(), mPrintfInfos)); - vkMem.unmap(); - - return angle::Result::Continue; -} - // A single CL buffer is setup for every command queue of size kPrintfBufferSize. This can be // expanded later, if more storage is needed. cl::MemoryPtr CLCommandQueueVk::getOrCreatePrintfBuffer() @@ -2225,6 +2438,8 @@ cl::MemoryPtr CLCommandQueueVk::getOrCreatePrintfBuffer() mPrintfBuffer = cl::Buffer::Cast(mContext->getFrontendObject().createBuffer( nullptr, cl::MemFlags(CL_MEM_READ_WRITE), kPrintfBufferSize, nullptr)); } + mCommandsStateMap.addPrintfBuffer(mComputePassCommands->getQueueSerial(), mPrintfBuffer); + return cl::MemoryPtr(mPrintfBuffer); } @@ -2234,14 +2449,72 @@ bool CLCommandQueueVk::hasUserEventDependency() const [](const cl::EventPtr event) { return event->isUserEvent(); }); } -void CLCommandQueueVk::addEventReference(CLEventVk &eventVk) +void CLCommandQueueVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics) +{ + mContext->addCommandBufferDiagnostics(commandBufferDiagnostics); +} + +angle::Result CommandsStateMap::setEventsWithQueueSerialToState(const QueueSerial &queueSerial, + cl::ExecutionStatus executionStatus) { - ASSERT(eventVk.getQueueSerial().valid()); - ASSERT(eventVk.getQueueSerial().getIndex() == mQueueSerialIndex); + std::unique_lock ul(mMutex); + cl_int newStatus = executionStatus == cl::ExecutionStatus::InvalidEnum + ? CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST + : cl::ToCLenum(executionStatus); + for (const auto &[serial, state] : mCommandsState) + { + if (serial <= queueSerial) + { + for (cl::EventPtr event : state.mEvents) + { + CLEventVk *eventVk = &event->getImpl(); + cl_int currentStatus = CL_QUEUED; + ANGLE_TRY(eventVk->getCommandExecutionStatus(currentStatus)); + if (!eventVk->isUserEvent() && currentStatus > newStatus) + { + ANGLE_TRY(eventVk->setStatusAndExecuteCallback(newStatus)); + } + } + } + } + return angle::Result::Continue; +} - std::lock_guard lock(mCommandQueueMutex); +angle::Result CommandsStateMap::processQueueSerial(const QueueSerial queueSerial) +{ + std::unique_lock ul(mMutex); + HostTransferEntries list = mCommandsState[queueSerial].mHostTransferList; + for (const HostTransferEntry &hostTransferEntry : list) + { + ANGLE_TRY(std::visit(HostTransferConfigVisitor( + hostTransferEntry.transferBufferHandle->getImpl()), + hostTransferEntry.transferConfig)); + } + list.clear(); + + cl::KernelPtrs kernels = mCommandsState[queueSerial].mKernels; + + for (cl::KernelPtr kernel : kernels) + { + CLKernelVk *kernelVk = &kernel->getImpl(); + + if (kernelVk->usesPrintf()) + { + ASSERT(kernels.size() == 1); - mCommandsStateMap[eventVk.getQueueSerial()].events.emplace_back(&eventVk.getFrontendObject()); + auto printfInfos = + kernelVk->getProgram()->getPrintfDescriptors(kernelVk->getKernelName()); + + CLBufferVk &vkMem = mCommandsState[queueSerial].mPrintfBuffer->getImpl(); + + unsigned char *data = nullptr; + ANGLE_TRY(vkMem.map(data, 0)); + ANGLE_TRY(ClspvProcessPrintfBuffer(data, vkMem.getSize(), printfInfos)); + vkMem.unmap(); + } + } + + return angle::Result::Continue; } } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h index ca90b7cd5bd..c74d18a12ad 100644 --- a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h +++ b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h @@ -13,8 +13,10 @@ #include #include "common/PackedCLEnums_autogen.h" +#include "common/SimpleMutex.h" #include "common/hash_containers.h" +#include "libANGLE/CLBuffer.h" #include "libANGLE/renderer/vulkan/CLContextVk.h" #include "libANGLE/renderer/vulkan/CLEventVk.h" #include "libANGLE/renderer/vulkan/CLKernelVk.h" @@ -56,32 +58,104 @@ class CLCommandQueueVk; namespace { - -struct HostTransferConfig +template +class HostTransferConfig { - HostTransferConfig() - : srcRect(cl::Offset{}, cl::Extents{}, 0, 0, 0), dstRect(cl::Offset{}, cl::Extents{}, 0, 0) - {} - cl_command_type type{0}; - size_t size = 0; - size_t offset = 0; - void *dstHostPtr = nullptr; - - // Source host pointer that can contain data/pattern/etc - const void *srcHostPtr = nullptr; - - size_t patternSize = 0; - size_t rowPitch = 0; - size_t slicePitch = 0; - size_t elementSize = 0; - cl::MemOffsets origin; - cl::Coordinate region; - cl::BufferRect srcRect; - cl::BufferRect dstRect; + public: + // HostTransferConfig is only relevant for certain commands that has host ptr involved, its + // state is only setup for those cases. + HostTransferConfig(cl_command_type type, size_t size, size_t offset, T *ptr) + : mType(type), + mSize(size), + mOffset(offset), + mHostPtr(ptr), + mBufferRect(cl::Offset{}, cl::Extents{}, 0, 0, 0), + mHostRect(cl::Offset{}, cl::Extents{}, 0, 0, 0) + { + ASSERT(type == CL_COMMAND_READ_BUFFER || type == CL_COMMAND_WRITE_BUFFER); + } + HostTransferConfig(cl_command_type type, + size_t size, + T *ptr, + cl::BufferRect bufferRect, + cl::BufferRect hostRect) + : mType(type), mSize(size), mHostPtr(ptr), mBufferRect(bufferRect), mHostRect(hostRect) + { + ASSERT(type == CL_COMMAND_READ_BUFFER_RECT || type == CL_COMMAND_WRITE_BUFFER_RECT); + } + HostTransferConfig(cl_command_type type, + size_t size, + size_t offset, + T *pattern, + size_t patternSize) + : mType(type), + mSize(size), + mOffset(offset), + mHostPtr(pattern), + mPatternSize(patternSize), + mBufferRect(cl::Offset{}, cl::Extents{}, 0, 0, 0), + mHostRect(cl::Offset{}, cl::Extents{}, 0, 0, 0) + { + ASSERT(type == CL_COMMAND_FILL_BUFFER); + } + HostTransferConfig(cl_command_type type, + size_t size, + void *ptr, + size_t rowPitch, + size_t slicePitch, + size_t elementSize, + cl::Offset origin, + cl::Extents region) + : mType(type), + mSize(size), + mHostPtr(ptr), + mRowPitch(rowPitch), + mSlicePitch(slicePitch), + mElementSize(elementSize), + mOrigin(origin), + mRegion(region), + mBufferRect(cl::Offset{}, cl::Extents{}, 0, 0, 0), + mHostRect(cl::kOffsetZero, region, rowPitch, slicePitch, elementSize) + { + ASSERT(type == CL_COMMAND_READ_IMAGE || type == CL_COMMAND_WRITE_IMAGE); + } + cl_command_type getType() const { return mType; } + size_t getSize() const { return mSize; } + size_t getOffset() const { return mOffset; } + T *getHostPtr() const { return mHostPtr; } + size_t getPatternSize() const { return mPatternSize; } + size_t getRowPitch() const { return mRowPitch; } + size_t getSlicePitch() const { return mSlicePitch; } + size_t getElementSize() const { return mElementSize; } + const cl::Offset &getOrigin() const { return mOrigin; } + const cl::Extents &getRegion() const { return mRegion; } + const cl::BufferRect &getBufferRect() const { return mBufferRect; } + const cl::BufferRect &getHostRect() const { return mHostRect; } + + private: + cl_command_type mType{0}; + size_t mSize = 0; + size_t mOffset = 0; + + T *mHostPtr = nullptr; + + size_t mPatternSize = 0; + size_t mRowPitch = 0; + size_t mSlicePitch = 0; + size_t mElementSize = 0; + cl::Offset mOrigin = cl::kOffsetZero; + cl::Extents mRegion = cl::kExtentsZero; + cl::BufferRect mBufferRect; + cl::BufferRect mHostRect; }; + +// We use HostTransferConfig for enqueueing a staged op for read/write operations to/from host +// pointers. As such we set up two instances one as const void and other as void. +using HostWriteTransferConfig = HostTransferConfig; +using HostReadTransferConfig = HostTransferConfig; struct HostTransferEntry { - HostTransferConfig transferConfig; + std::variant transferConfig; cl::MemoryPtr transferBufferHandle; }; using HostTransferEntries = std::vector; @@ -116,14 +190,81 @@ class DispatchWorkThread SerialIndex mQueueSerialIndex; }; -struct CommandsState +// CommandsStateMap captures all the objects that need post-processing once the submitted job on +// them has finished. All the objects take a refcount to ensure they are alive until the command is +// finished. +class CommandsStateMap { - cl::EventPtrs events; - cl::MemoryPtrs memories; - cl::KernelPtrs kernels; - HostTransferEntries hostTransferList; + public: + CommandsStateMap() = default; + ~CommandsStateMap() = default; + + void addPrintfBuffer(const QueueSerial queueSerial, cl::Memory *printfBuffer) + { + std::unique_lock ul(mMutex); + mCommandsState[queueSerial].mPrintfBuffer = cl::MemoryPtr(printfBuffer); + } + void addMemory(const QueueSerial queueSerial, cl::Memory *mem) + { + std::unique_lock ul(mMutex); + mCommandsState[queueSerial].mMemories.emplace_back(mem); + } + void addEvent(const QueueSerial queueSerial, cl::EventPtr event) + { + std::unique_lock ul(mMutex); + mCommandsState[queueSerial].mEvents.push_back(event); + } + void addKernel(const QueueSerial queueSerial, cl::Kernel *kernel) + { + std::unique_lock ul(mMutex); + mCommandsState[queueSerial].mKernels.emplace_back(kernel); + } + void addSampler(const QueueSerial queueSerial, cl::SamplerPtr sampler) + { + std::unique_lock ul(mMutex); + mCommandsState[queueSerial].mSamplers.push_back(sampler); + } + void addHostTransferEntry(const QueueSerial queueSerial, HostTransferEntry hostTransferEntry) + { + std::unique_lock ul(mMutex); + mCommandsState[queueSerial].mHostTransferList.push_back(hostTransferEntry); + } + void erase(const QueueSerial queueSerial) + { + std::unique_lock ul(mMutex); + mCommandsState.erase(queueSerial); + } + void clear() + { + std::unique_lock ul(mMutex); + mCommandsState.clear(); + } + cl::MemoryPtr getPrintfBuffer(const QueueSerial queueSerial) + { + std::unique_lock ul(mMutex); + return mCommandsState[queueSerial].mPrintfBuffer; + } + + angle::Result setEventsWithQueueSerialToState(const QueueSerial &queueSerial, + cl::ExecutionStatus executionStatus); + angle::Result processQueueSerial(const QueueSerial queueSerial); + + private: + struct CommandsState + { + cl::EventPtrs mEvents; + cl::MemoryPtrs mMemories; + cl::KernelPtrs mKernels; + cl::SamplerPtrs mSamplers; + cl::MemoryPtr mPrintfBuffer; + HostTransferEntries mHostTransferList; + }; + + // The entries are added and removed in different threads, so protect the map during insertion + // and removal. + angle::SimpleMutex mMutex; + angle::HashMap mCommandsState; }; -using CommandsStateMap = angle::HashMap; } // namespace @@ -143,7 +284,7 @@ class CLCommandQueueVk : public CLCommandQueueImpl size_t size, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueWriteBuffer(const cl::Buffer &buffer, bool blocking, @@ -151,33 +292,33 @@ class CLCommandQueueVk : public CLCommandQueueImpl size_t size, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueReadBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueWriteBufferRect(const cl::Buffer &buffer, bool blocking, - const cl::MemOffsets &bufferOrigin, - const cl::MemOffsets &hostOrigin, - const cl::Coordinate ®ion, + const cl::Offset &bufferOrigin, + const cl::Offset &hostOrigin, + const cl::Extents ®ion, size_t bufferRowPitch, size_t bufferSlicePitch, size_t hostRowPitch, size_t hostSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyBuffer(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, @@ -185,19 +326,19 @@ class CLCommandQueueVk : public CLCommandQueueImpl size_t dstOffset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyBufferRect(const cl::Buffer &srcBuffer, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, size_t dstSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueFillBuffer(const cl::Buffer &buffer, const void *pattern, @@ -205,7 +346,7 @@ class CLCommandQueueVk : public CLCommandQueueImpl size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMapBuffer(const cl::Buffer &buffer, bool blocking, @@ -213,107 +354,107 @@ class CLCommandQueueVk : public CLCommandQueueImpl size_t offset, size_t size, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) override; angle::Result enqueueReadImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t rowPitch, size_t slicePitch, void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueWriteImage(const cl::Image &image, bool blocking, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyImage(const cl::Image &srcImage, const cl::Image &dstImage, - const cl::MemOffsets &srcOrigin, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueFillImage(const cl::Image &image, const void *fillColor, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyImageToBuffer(const cl::Image &srcImage, const cl::Buffer &dstBuffer, - const cl::MemOffsets &srcOrigin, - const cl::Coordinate ®ion, + const cl::Offset &srcOrigin, + const cl::Extents ®ion, size_t dstOffset, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueCopyBufferToImage(const cl::Buffer &srcBuffer, const cl::Image &dstImage, size_t srcOffset, - const cl::MemOffsets &dstOrigin, - const cl::Coordinate ®ion, + const cl::Offset &dstOrigin, + const cl::Extents ®ion, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMapImage(const cl::Image &image, bool blocking, cl::MapFlags mapFlags, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + const cl::Offset &origin, + const cl::Extents ®ion, size_t *imageRowPitch, size_t *imageSlicePitch, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc, + cl::EventPtr &event, void *&mapPtr) override; angle::Result enqueueUnmapMemObject(const cl::Memory &memory, void *mappedPtr, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMigrateMemObjects(const cl::MemoryPtrs &memObjects, cl::MemMigrationFlags flags, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueNDRangeKernel(const cl::Kernel &kernel, const cl::NDRange &ndrange, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueTask(const cl::Kernel &kernel, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueNativeKernel(cl::UserFunc userFunc, void *args, size_t cbArgs, const cl::BufferPtrs &buffers, - const std::vector bufferPtrOffsets, + const std::vector &bufferPtrOffsets, const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueMarkerWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; - angle::Result enqueueMarker(CLEventImpl::CreateFunc &eventCreateFunc) override; + angle::Result enqueueMarker(cl::EventPtr &event) override; angle::Result enqueueWaitForEvents(const cl::EventPtrs &events) override; angle::Result enqueueBarrierWithWaitList(const cl::EventPtrs &waitEvents, - CLEventImpl::CreateFunc *eventCreateFunc) override; + cl::EventPtr &event) override; angle::Result enqueueBarrier() override; @@ -321,6 +462,14 @@ class CLCommandQueueVk : public CLCommandQueueImpl angle::Result finish() override; + angle::Result enqueueAcquireExternalMemObjectsKHR(const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) override; + + angle::Result enqueueReleaseExternalMemObjectsKHR(const cl::MemoryPtrs &memObjects, + const cl::EventPtrs &waitEvents, + cl::EventPtr &event) override; + CLPlatformVk *getPlatform() { return mContext->getPlatform(); } CLContextVk *getContext() { return mContext; } @@ -335,15 +484,13 @@ class CLCommandQueueVk : public CLCommandQueueImpl return mLastFlushedQueueSerial != mLastSubmittedQueueSerial; } - void addEventReference(CLEventVk &eventVk); - private: static constexpr size_t kMaxDependencyTrackerSize = 64; static constexpr size_t kMaxHostBufferUpdateListSize = 16; angle::Result resetCommandBufferWithError(cl_int errorCode); - vk::ProtectionType getProtectionType() const { return vk::ProtectionType::Unprotected; } + vk::ProtectionType getProtectionType() const { return mCommandState.getProtectionType(); } // Create-update-bind the kernel's descriptor set, put push-constants in cmd buffer, capture // kernel resources, and handle kernel execution dependencies @@ -358,43 +505,52 @@ class CLCommandQueueVk : public CLCommandQueueImpl // event status updates etc. This is a blocking call. angle::Result finishQueueSerialInternal(const QueueSerial queueSerial); - angle::Result syncHostBuffers(HostTransferEntries &hostTransferList); + // Flush commands recorded in this queue's secondary command buffer to renderer primary command + // buffer. angle::Result flushComputePassCommands(); + angle::Result processWaitlist(const cl::EventPtrs &waitEvents); - angle::Result createEvent(CLEventImpl::CreateFunc *createFunc, - cl::ExecutionStatus initialStatus); + angle::Result preEnqueueOps(cl::EventPtr &event, cl::ExecutionStatus initialStatus); + angle::Result postEnqueueOps(const cl::EventPtr &event); - angle::Result onResourceAccess(const vk::CommandBufferAccess &access); - angle::Result getCommandBuffer(const vk::CommandBufferAccess &access, + angle::Result onResourceAccess(const vk::CommandResources &resources); + angle::Result getCommandBuffer(const vk::CommandResources &resources, vk::OutsideRenderPassCommandBuffer **commandBufferOut) { - ANGLE_TRY(onResourceAccess(access)); + ANGLE_TRY(onResourceAccess(resources)); *commandBufferOut = &mComputePassCommands->getCommandBuffer(); return angle::Result::Continue; } - angle::Result processPrintfBuffer(); angle::Result copyImageToFromBuffer(CLImageVk &imageVk, - vk::BufferHelper &buffer, - const cl::MemOffsets &origin, - const cl::Coordinate ®ion, - size_t bufferOffset, + CLBufferVk &buffer, + VkBufferImageCopy copyRegion, ImageBufferCopyDirection writeToBuffer); bool hasUserEventDependency() const; angle::Result insertBarrier(); - angle::Result addMemoryDependencies(cl::Memory *clMem); + angle::Result addMemoryDependencies(const CLKernelArgument *arg); + enum class MemoryHandleAccess + { + ReadOnly, + Writeable, + }; + angle::Result addMemoryDependencies(cl::Memory *mem, MemoryHandleAccess access); angle::Result submitEmptyCommand(); + void addCommandBufferDiagnostics(const std::string &addCommandBufferDiagnostics); + CLContextVk *mContext; const CLDeviceVk *mDevice; cl::Memory *mPrintfBuffer; vk::SecondaryCommandPools mCommandPool; vk::OutsideRenderPassCommandBufferHelper *mComputePassCommands; - vk::SecondaryCommandMemoryAllocator mOutsideRenderPassCommandsAllocator; + + // vulkan primary command buffer + vk::CommandsState mCommandState; // Queue Serials for this command queue SerialIndex mQueueSerialIndex; @@ -407,19 +563,23 @@ class CLCommandQueueVk : public CLCommandQueueImpl cl::EventPtrs mExternalEvents; // Keep track of kernel resources on prior kernel enqueues - angle::HashSet mDependencyTracker; + angle::HashSet mWriteDependencyTracker; + angle::HashSet mReadDependencyTracker; CommandsStateMap mCommandsStateMap; // printf handling bool mNeedPrintfHandling; - const angle::HashMap *mPrintfInfos; // Host buffer transferring routines - angle::Result addToHostTransferList(CLBufferVk *srcBuffer, HostTransferConfig transferEntry); - angle::Result addToHostTransferList(CLImageVk *srcImage, HostTransferConfig transferEntry); + template + angle::Result addToHostTransferList(CLBufferVk *srcBuffer, HostTransferConfig transferEntry); + template + angle::Result addToHostTransferList(CLImageVk *srcImage, HostTransferConfig transferEntry); DispatchWorkThread mFinishHandler; + + std::vector mCommandBufferDiagnostics; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLContextVk.cpp b/src/libANGLE/renderer/vulkan/CLContextVk.cpp index 5fc75d07a59..d6fd8035751 100644 --- a/src/libANGLE/renderer/vulkan/CLContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLContextVk.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLContextVk.cpp: Implements the class methods for CLContextVk. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif #include "libANGLE/renderer/vulkan/CLContextVk.h" #include "common/PackedEnums.h" @@ -12,12 +17,12 @@ #include "libANGLE/renderer/vulkan/CLMemoryVk.h" #include "libANGLE/renderer/vulkan/CLProgramVk.h" #include "libANGLE/renderer/vulkan/CLSamplerVk.h" -#include "libANGLE/renderer/vulkan/DisplayVk.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" #include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/CLBuffer.h" +#include "libANGLE/CLCommandQueue.h" #include "libANGLE/CLContext.h" #include "libANGLE/CLEvent.h" #include "libANGLE/CLImage.h" @@ -188,6 +193,25 @@ angle::Result CLContextVk::getSupportedImageFormats(cl::MemFlags flags, supportedFormats.push_back(format); } } + + if (cl::Is2DImage(imageType)) + { + CLExtensions::SupportedDepthOrderTypes supportedDepthOrderTypesUnion; + for (const cl::DevicePtr &device : mContext.getDevices()) + { + // clGetSupportedImageFormats returns a union of image formats supported by all devices + // in the context + supportedDepthOrderTypesUnion |= device->getInfo().supportedDepthOrderTypes; + } + for (const cl::ImageChannelType imageChannelType : angle::AllEnums()) + { + if (supportedDepthOrderTypesUnion.test(imageChannelType)) + { + supportedFormats.push_back({CL_DEPTH, cl::ToCLenum(imageChannelType)}); + } + } + } + if (numImageFormats != nullptr) { *numImageFormats = static_cast(supportedFormats.size()); @@ -333,8 +357,8 @@ angle::Result CLContextVk::linkProgram(const cl::Program &program, angle::Result CLContextVk::createUserEvent(const cl::Event &event, CLEventImpl::Ptr *eventOut) { - *eventOut = CLEventImpl::Ptr( - new (std::nothrow) CLEventVk(event, cl::ExecutionStatus::Submitted, QueueSerial())); + *eventOut = + CLEventImpl::Ptr(new (std::nothrow) CLEventVk(event, cl::ExecutionStatus::Submitted)); if (*eventOut == nullptr) { ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY); @@ -374,4 +398,40 @@ angle::Result CLContextVk::allocateDescriptorSet( return kernelVk->allocateDescriptorSet(index, layoutIndex, computePassCommands); } +angle::Result CLContextVk::initializeDescriptorPools(CLKernelVk *kernelVk) +{ + std::lock_guard lock(mDescriptorSetMutex); + + return kernelVk->initializeDescriptorPools(); +} + +void CLContextVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics) +{ + mCommandBufferDiagnostics.push_back(commandBufferDiagnostics); +} + +void CLContextVk::dumpCommandStreamDiagnostics() +{ + std::ostream &out = std::cout; + if (mCommandBufferDiagnostics.empty()) + { + return; + } + + out << "digraph {\n" << " node [shape=box fontname=\"Consolas\"]\n"; + + for (size_t index = 0; index < mCommandBufferDiagnostics.size(); ++index) + { + std::string_view payload = mCommandBufferDiagnostics[index]; + out << " cb" << index << " [label =\"" << payload << "\"];\n"; + } + for (size_t index = 0; index < mCommandBufferDiagnostics.size() - 1; ++index) + { + out << " cb" << index << " -> cb" << index + 1 << "\n"; + } + mCommandBufferDiagnostics.clear(); + + out << "}\n"; +} + } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLContextVk.h b/src/libANGLE/renderer/vulkan/CLContextVk.h index 52e91d83614..7aef1631685 100644 --- a/src/libANGLE/renderer/vulkan/CLContextVk.h +++ b/src/libANGLE/renderer/vulkan/CLContextVk.h @@ -106,6 +106,10 @@ class CLContextVk : public CLContextImpl, public vk::Context DescriptorSetIndex index, angle::EnumIterator layoutIndex, vk::OutsideRenderPassCommandBufferHelper *computePassCommands); + angle::Result initializeDescriptorPools(CLKernelVk *kernelVk); + + void addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics); + void dumpCommandStreamDiagnostics(); private: void handleDeviceLost() const; @@ -130,6 +134,8 @@ class CLContextVk : public CLContextImpl, public vk::Context const cl::DevicePtrs mAssociatedDevices; + std::vector mCommandBufferDiagnostics; + // Table of minimum required image formats for OpenCL static constexpr cl_image_format kMinSupportedFormatsReadOrWrite[11] = { {CL_RGBA, CL_UNORM_INT8}, {CL_RGBA, CL_UNSIGNED_INT8}, {CL_RGBA, CL_SIGNED_INT8}, diff --git a/src/libANGLE/renderer/vulkan/CLDeviceVk.cpp b/src/libANGLE/renderer/vulkan/CLDeviceVk.cpp index 25393c7212b..b395697dbb9 100644 --- a/src/libANGLE/renderer/vulkan/CLDeviceVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLDeviceVk.cpp @@ -4,8 +4,14 @@ // found in the LICENSE file. // // CLDeviceVk.cpp: Implements the class methods for CLDeviceVk. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/vulkan/CLDeviceVk.h" +#include "libANGLE/renderer/driver_utils.h" #include "libANGLE/renderer/vulkan/clspv_utils.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" @@ -44,6 +50,23 @@ CLDeviceVk::CLDeviceVk(const cl::Device &device, vk::Renderer *renderer) {cl::DeviceInfo::PrintfBufferSize, 1024 * 1024}, {cl::DeviceInfo::PreferredWorkGroupSizeMultiple, 16}, }; + + // Minimum float configs/support required + cl_ulong halfFPConfig = 0; + cl_ulong singleFPConfig = CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN | CL_FP_FMA; + cl_ulong doubleFPConfig = 0; + + if (mRenderer->getFeatures().supportsShaderFloat16.enabled) + { + halfFPConfig |= CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN; + } + + if (mRenderer->getFeatures().supportsShaderFloat64.enabled) + { + doubleFPConfig |= CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | + CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM; + } + mInfoULong = { {cl::DeviceInfo::LocalMemSize, props.limits.maxComputeSharedMemorySize}, {cl::DeviceInfo::SVM_Capabilities, 0}, @@ -54,14 +77,16 @@ CLDeviceVk::CLDeviceVk(const cl::Device &device, vk::Renderer *renderer) // TODO(aannestrand) Update these hardcoded platform/device queries // http://anglebug.com/42266935 - {cl::DeviceInfo::HalfFpConfig, 0}, - {cl::DeviceInfo::DoubleFpConfig, 0}, + {cl::DeviceInfo::HalfFpConfig, halfFPConfig}, + {cl::DeviceInfo::DoubleFpConfig, doubleFPConfig}, {cl::DeviceInfo::GlobalMemCacheSize, 0}, {cl::DeviceInfo::GlobalMemSize, 1024 * 1024 * 1024}, {cl::DeviceInfo::MaxConstantBufferSize, 64 * 1024}, - {cl::DeviceInfo::SingleFpConfig, CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN | CL_FP_FMA}, + {cl::DeviceInfo::SingleFpConfig, singleFPConfig}, {cl::DeviceInfo::AtomicMemoryCapabilities, - CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP}, + CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP | + CL_DEVICE_ATOMIC_ORDER_ACQ_REL | CL_DEVICE_ATOMIC_SCOPE_DEVICE | + CL_DEVICE_ATOMIC_ORDER_SEQ_CST}, // TODO (http://anglebug.com/379669750) Add these based on the Vulkan features query {cl::DeviceInfo::AtomicFenceCapabilities, CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_ORDER_ACQ_REL | @@ -93,7 +118,8 @@ CLDeviceVk::CLDeviceVk(const cl::Device &device, vk::Renderer *renderer) // TODO(aannestrand) Update these hardcoded platform/device queries // http://anglebug.com/42266935 - {cl::DeviceInfo::AddressBits, 32}, + {cl::DeviceInfo::AddressBits, + mRenderer->getFeatures().supportsBufferDeviceAddress.enabled ? 64 : 32}, {cl::DeviceInfo::EndianLittle, CL_TRUE}, {cl::DeviceInfo::LocalMemType, CL_LOCAL}, // TODO (http://anglebug.com/379669750) Vulkan reports a big sampler count number, we dont @@ -112,16 +138,16 @@ CLDeviceVk::CLDeviceVk(const cl::Device &device, vk::Renderer *renderer) {cl::DeviceInfo::NativeVectorWidthInt, 1}, {cl::DeviceInfo::NativeVectorWidthLong, 1}, {cl::DeviceInfo::NativeVectorWidthFloat, 1}, - {cl::DeviceInfo::NativeVectorWidthDouble, 1}, - {cl::DeviceInfo::NativeVectorWidthHalf, 0}, + {cl::DeviceInfo::NativeVectorWidthDouble, mRenderer->getNativeVectorWidthDouble()}, + {cl::DeviceInfo::NativeVectorWidthHalf, mRenderer->getNativeVectorWidthHalf()}, {cl::DeviceInfo::PartitionMaxSubDevices, 0}, + {cl::DeviceInfo::PreferredVectorWidthChar, 4}, + {cl::DeviceInfo::PreferredVectorWidthShort, 8}, {cl::DeviceInfo::PreferredVectorWidthInt, 1}, {cl::DeviceInfo::PreferredVectorWidthLong, 1}, - {cl::DeviceInfo::PreferredVectorWidthChar, 4}, - {cl::DeviceInfo::PreferredVectorWidthHalf, 0}, - {cl::DeviceInfo::PreferredVectorWidthShort, 2}, {cl::DeviceInfo::PreferredVectorWidthFloat, 1}, - {cl::DeviceInfo::PreferredVectorWidthDouble, 0}, + {cl::DeviceInfo::PreferredVectorWidthDouble, mRenderer->getPreferredVectorWidthDouble()}, + {cl::DeviceInfo::PreferredVectorWidthHalf, mRenderer->getPreferredVectorWidthHalf()}, {cl::DeviceInfo::PreferredLocalAtomicAlignment, 0}, {cl::DeviceInfo::PreferredGlobalAtomicAlignment, 0}, {cl::DeviceInfo::PreferredPlatformAtomicAlignment, 0}, @@ -156,8 +182,8 @@ CLDeviceImpl::Info CLDeviceVk::createInfo(cl::DeviceType type) const info.image3D_MaxWidth = properties.limits.maxImageDimension3D; info.image3D_MaxHeight = properties.limits.maxImageDimension3D; info.image3D_MaxDepth = properties.limits.maxImageDimension3D; - // TODO (http://anglebug.com/379669750) For now set it minimum requirement. - info.imageMaxBufferSize = 65536; + // Max number of pixels for a 1D image created from a buffer object. + info.imageMaxBufferSize = properties.limits.maxTexelBufferElements; info.imageMaxArraySize = properties.limits.maxImageArrayLayers; info.imagePitchAlignment = 0u; info.imageBaseAddressAlignment = 0u; @@ -193,11 +219,80 @@ CLDeviceImpl::Info CLDeviceVk::createInfo(cl::DeviceType type) const cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_local_int32_extended_atomics"}, }; + + CLExtensions::ExternalMemoryHandleBitset supportedHandles; + supportedHandles.set(cl::ExternalMemoryHandle::OpaqueFd, supportsExternalMemoryFd()); + supportedHandles.set(cl::ExternalMemoryHandle::DmaBuf, supportsExternalMemoryDmaBuf()); + + // Populate other extensions based on feature support + if (info.populateSupportedExternalMemoryHandleTypes(supportedHandles)) + { + versionedExtensionList.push_back( + cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_external_memory"}); + + // cl_arm_import_memory is layered on top of cl_arm_import_memory + bool reportBaseArmImportMemString = false; + if (supportedHandles.test(cl::ExternalMemoryHandle::DmaBuf)) + { + versionedExtensionList.push_back(cl_name_version{ + .version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_arm_import_memory_dma_buf"}); + reportBaseArmImportMemString = true; + } + if (reportBaseArmImportMemString) + { + versionedExtensionList.push_back(cl_name_version{.version = CL_MAKE_VERSION(1, 11, 0), + .name = "cl_arm_import_memory"}); + } + } + if (mRenderer->getFeatures().supportsShaderFloat16.enabled) + { + versionedExtensionList.push_back( + cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_fp16"}); + } + if (mRenderer->getFeatures().supportsShaderFloat64.enabled) + { + versionedExtensionList.push_back( + cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_fp64"}); + } if (info.imageSupport && info.image3D_MaxDepth > 1) { versionedExtensionList.push_back( cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_3d_image_writes"}); } + if (mRenderer->getQueueFamilyProperties().queueCount > 1) + { + versionedExtensionList.push_back( + cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_priority_hints"}); + } + + info.integerDotProductCapabilities = getIntegerDotProductCapabilities(); + info.integerDotProductAccelerationProperties8Bit = + getIntegerDotProductAccelerationProperties8Bit(); + info.integerDotProductAccelerationProperties4x8BitPacked = + getIntegerDotProductAccelerationProperties4x8BitPacked(); + + if (mRenderer->getFeatures().supportsShaderIntegerDotProduct.enabled) + { + versionedExtensionList.push_back(cl_name_version{.version = CL_MAKE_VERSION(2, 0, 0), + .name = "cl_khr_integer_dot_product"}); + } + + // cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics + if (mRenderer->getFeatures().supportsShaderAtomicInt64.enabled) + { + versionedExtensionList.push_back(cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), + .name = "cl_khr_int64_base_atomics"}); + versionedExtensionList.push_back(cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), + .name = "cl_khr_int64_extended_atomics"}); + } + + // cl_khr_depth_images + if (setupAndReportDepthImageSupport(info)) + { + versionedExtensionList.push_back( + cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_depth_images"}); + } + info.initializeVersionedExtensions(std::move(versionedExtensionList)); if (!mRenderer->getFeatures().supportsUniformBufferStandardLayout.enabled) @@ -222,6 +317,23 @@ CLDeviceImpl::Info CLDeviceVk::createInfo(cl::DeviceType type) const cl_name_version{.version = CL_MAKE_VERSION(3, 0, 0), .name = "__opencl_c_int64"}); } + if (mRenderer->getFeatures().supportsShaderIntegerDotProduct.enabled) + { + info.OpenCL_C_Features.push_back( + cl_name_version{.version = CL_MAKE_VERSION(3, 0, 0), + .name = "__opencl_c_integer_dot_product_input_4x8bit"}); + info.OpenCL_C_Features.push_back( + cl_name_version{.version = CL_MAKE_VERSION(3, 0, 0), + .name = "__opencl_c_integer_dot_product_input_4x8bit_packed"}); + } + + info.OpenCL_C_Features.push_back(cl_name_version{.version = CL_MAKE_VERSION(3, 0, 0), + .name = "__opencl_c_atomic_order_acq_rel"}); + info.OpenCL_C_Features.push_back(cl_name_version{.version = CL_MAKE_VERSION(3, 0, 0), + .name = "__opencl_c_atomic_order_seq_cst"}); + info.OpenCL_C_Features.push_back(cl_name_version{.version = CL_MAKE_VERSION(3, 0, 0), + .name = "__opencl_c_atomic_scope_device"}); + return info; } @@ -275,6 +387,16 @@ angle::Result CLDeviceVk::getInfoString(cl::DeviceInfo name, size_t size, char * ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE); } +bool CLDeviceVk::supportsExternalMemoryFd() const +{ + return mRenderer->getFeatures().supportsExternalMemoryFd.enabled; +} + +bool CLDeviceVk::supportsExternalMemoryDmaBuf() const +{ + return mRenderer->getFeatures().supportsExternalMemoryDmaBuf.enabled; +} + angle::Result CLDeviceVk::createSubDevices(const cl_device_partition_property *properties, cl_uint numDevices, CreateFuncs &subDevices, @@ -287,7 +409,6 @@ angle::Result CLDeviceVk::createSubDevices(const cl_device_partition_property *p cl::WorkgroupSize CLDeviceVk::selectWorkGroupSize(const cl::NDRange &ndrange) const { // Limit total work-group size to the Vulkan device's limit - const VkPhysicalDeviceProperties &props = mRenderer->getPhysicalDeviceProperties(); uint32_t maxSize = static_cast(mInfoSizeT.at(cl::DeviceInfo::MaxWorkGroupSize)); maxSize = std::min(maxSize, 64u); @@ -301,7 +422,7 @@ cl::WorkgroupSize CLDeviceVk::selectWorkGroupSize(const cl::NDRange &ndrange) co cl::WorkgroupSize newLocalSize = localSize; newLocalSize[i] *= 2; - if (newLocalSize[i] <= props.limits.maxComputeWorkGroupCount[i] && + if (newLocalSize[i] <= ndrange.globalWorkSize[i] && newLocalSize[0] * newLocalSize[1] * newLocalSize[2] <= maxSize) { localSize = newLocalSize; @@ -313,4 +434,106 @@ cl::WorkgroupSize CLDeviceVk::selectWorkGroupSize(const cl::NDRange &ndrange) co return localSize; } +cl_device_integer_dot_product_capabilities_khr CLDeviceVk::getIntegerDotProductCapabilities() const +{ + cl_device_integer_dot_product_capabilities_khr integerDotProductCapabilities = {}; + + if (mRenderer->getFeatures().supportsShaderIntegerDotProduct.enabled) + { + // If the VK extension is supported, then all the caps mentioned in the CL spec are + // supported by default. + integerDotProductCapabilities = (CL_DEVICE_INTEGER_DOT_PRODUCT_INPUT_4x8BIT_PACKED_KHR | + CL_DEVICE_INTEGER_DOT_PRODUCT_INPUT_4x8BIT_KHR); + } + + return integerDotProductCapabilities; +} + +cl_device_integer_dot_product_acceleration_properties_khr +CLDeviceVk::getIntegerDotProductAccelerationProperties8Bit() const +{ + + cl_device_integer_dot_product_acceleration_properties_khr + integerDotProductAccelerationProperties = {}; + const VkPhysicalDeviceShaderIntegerDotProductProperties &integerDotProductProps = + mRenderer->getPhysicalDeviceShaderIntegerDotProductProperties(); + + integerDotProductAccelerationProperties.signed_accelerated = + integerDotProductProps.integerDotProduct8BitSignedAccelerated; + integerDotProductAccelerationProperties.unsigned_accelerated = + integerDotProductProps.integerDotProduct8BitUnsignedAccelerated; + integerDotProductAccelerationProperties.mixed_signedness_accelerated = + integerDotProductProps.integerDotProduct8BitMixedSignednessAccelerated; + integerDotProductAccelerationProperties.accumulating_saturating_signed_accelerated = + integerDotProductProps.integerDotProductAccumulatingSaturating8BitSignedAccelerated; + integerDotProductAccelerationProperties.accumulating_saturating_unsigned_accelerated = + integerDotProductProps.integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + integerDotProductAccelerationProperties.accumulating_saturating_mixed_signedness_accelerated = + integerDotProductProps + .integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + + return integerDotProductAccelerationProperties; +} + +cl_device_integer_dot_product_acceleration_properties_khr +CLDeviceVk::getIntegerDotProductAccelerationProperties4x8BitPacked() const +{ + + cl_device_integer_dot_product_acceleration_properties_khr + integerDotProductAccelerationProperties = {}; + const VkPhysicalDeviceShaderIntegerDotProductProperties &integerDotProductProps = + mRenderer->getPhysicalDeviceShaderIntegerDotProductProperties(); + + integerDotProductAccelerationProperties.signed_accelerated = + integerDotProductProps.integerDotProduct4x8BitPackedSignedAccelerated; + integerDotProductAccelerationProperties.unsigned_accelerated = + integerDotProductProps.integerDotProduct4x8BitPackedUnsignedAccelerated; + integerDotProductAccelerationProperties.mixed_signedness_accelerated = + integerDotProductProps.integerDotProduct4x8BitPackedMixedSignednessAccelerated; + integerDotProductAccelerationProperties.accumulating_saturating_signed_accelerated = + integerDotProductProps.integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + integerDotProductAccelerationProperties.accumulating_saturating_unsigned_accelerated = + integerDotProductProps + .integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + integerDotProductAccelerationProperties.accumulating_saturating_mixed_signedness_accelerated = + integerDotProductProps + .integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + + return integerDotProductAccelerationProperties; +} + +bool CLDeviceVk::setupAndReportDepthImageSupport(Info &info) const +{ + if (IsNvidia(getRenderer()->getPhysicalDeviceProperties().vendorID)) + { + // TODO(aannestrand) CTS validation issue with (cl_copy_images.2D use_pitches) on nvidia + // platform, disable its cl_khr_depth_images support for now + // http://anglebug.com/472472687 + return false; + } + + constexpr VkFlags kDepthFeatures = + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + + // for reporting the extension string, we only need CL_FLOAT and CL_UNORM_INT16 + // https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#minimum-list-of-supported-image-formats + CLExtensions::SupportedDepthOrderTypes minimumDepthOrderTypeSupport; + minimumDepthOrderTypeSupport.set(cl::ImageChannelType::Float); + minimumDepthOrderTypeSupport.set(cl::ImageChannelType::UnormInt16); + + for (const cl::ImageChannelType imageChannelType : angle::AllEnums()) + { + angle::FormatID format = angle::Format::CLDEPTHFormatToID(cl::ToCLenum(imageChannelType)); + if (format != angle::FormatID::NONE && + mRenderer->hasImageFormatFeatureBits(format, kDepthFeatures)) + { + info.supportedDepthOrderTypes.set(imageChannelType); + } + } + + // check/return-true if the minimum support is there + return (info.supportedDepthOrderTypes & minimumDepthOrderTypeSupport) == + minimumDepthOrderTypeSupport; +} + } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLDeviceVk.h b/src/libANGLE/renderer/vulkan/CLDeviceVk.h index a366e7622d2..365f4cbdc0f 100644 --- a/src/libANGLE/renderer/vulkan/CLDeviceVk.h +++ b/src/libANGLE/renderer/vulkan/CLDeviceVk.h @@ -33,7 +33,8 @@ class CLDeviceVk : public CLDeviceImpl angle::Result getInfoSizeT(cl::DeviceInfo name, size_t *value) const override; angle::Result getInfoStringLength(cl::DeviceInfo name, size_t *value) const override; angle::Result getInfoString(cl::DeviceInfo name, size_t size, char *value) const override; - + bool supportsExternalMemoryFd() const; + bool supportsExternalMemoryDmaBuf() const; angle::Result createSubDevices(const cl_device_partition_property *properties, cl_uint numDevices, CreateFuncs &subDevices, @@ -51,6 +52,13 @@ class CLDeviceVk : public CLDeviceImpl angle::HashMap mInfoULong; angle::HashMap mInfoSizeT; angle::HashMap mInfoString; + cl_device_integer_dot_product_capabilities_khr getIntegerDotProductCapabilities() const; + cl_device_integer_dot_product_acceleration_properties_khr + getIntegerDotProductAccelerationProperties8Bit() const; + cl_device_integer_dot_product_acceleration_properties_khr + getIntegerDotProductAccelerationProperties4x8BitPacked() const; + bool populateSupportedExternalMemoryHandleTypes(Info &info) const; + bool setupAndReportDepthImageSupport(Info &info) const; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLEventVk.cpp b/src/libANGLE/renderer/vulkan/CLEventVk.cpp index bc1dedc7d7b..34b43c89404 100644 --- a/src/libANGLE/renderer/vulkan/CLEventVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLEventVk.cpp @@ -4,49 +4,38 @@ // found in the LICENSE file. // // CLEventVk.cpp: Implements the class methods for CLEventVk. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif #include "libANGLE/renderer/vulkan/CLEventVk.h" -#include "libANGLE/renderer/vulkan/CLCommandQueueVk.h" + +#include "libANGLE/CLCommandQueue.h" #include "libANGLE/cl_utils.h" namespace rx { -CLEventVk::CLEventVk(const cl::Event &event, - const cl::ExecutionStatus initialStatus, - const QueueSerial eventSerial) +CLEventVk::CLEventVk(const cl::Event &event, const cl::ExecutionStatus initialStatus) : CLEventImpl(event), mStatus(cl::ToCLenum(initialStatus)), mProfilingTimestamps(ProfilingTimestamps{}), - mQueueSerial(eventSerial) + mQueueSerial(QueueSerial()) { ANGLE_CL_IMPL_TRY(setTimestamp(*mStatus)); } CLEventVk::~CLEventVk() {} -angle::Result CLEventVk::onEventCreate() +void CLEventVk::setQueueSerial(QueueSerial queueSerial) { - ASSERT(!isUserEvent()); - ASSERT(mQueueSerial.valid()); + ASSERT(!isUserEvent() && "user-event should not hold a QueueSerial!"); + ASSERT(!mQueueSerial.valid() && "we can only set event QueueSerial once!"); - if (cl::FromCLenum(*mStatus) == cl::ExecutionStatus::Complete) - { - // Submission finished at this point, just set event to complete - ANGLE_TRY(setStatusAndExecuteCallback(CL_COMPLETE)); - } - else - { - getFrontendObject().getCommandQueue()->getImpl().addEventReference(*this); - if (getFrontendObject().getCommandQueue()->getProperties().intersects( - CL_QUEUE_PROFILING_ENABLE)) - { - // Block for profiling so that we get timestamps per-command - ANGLE_TRY(getFrontendObject().getCommandQueue()->getImpl().finish()); - } - } - return angle::Result::Continue; + mQueueSerial = queueSerial; } angle::Result CLEventVk::getCommandExecutionStatus(cl_int &executionStatus) @@ -131,17 +120,18 @@ angle::Result CLEventVk::waitForUserEventStatus() { ASSERT(isUserEvent()); - cl_int status = CL_QUEUED; + // User is responsible for setting the user-event object, we need to wait for that event + // (We dont care what the outcome is, just need to wait until that event triggers) std::unique_lock ul(mUserEventMutex); - ANGLE_TRY(getCommandExecutionStatus(status)); - if (status > CL_COMPLETE) - { - // User is responsible for setting the user-event object, we need to wait for that event - // (We dont care what the outcome is, just need to wait until that event triggers) - INFO() << "Waiting for user-event (" << &mEvent - << ") to be set! (aka clSetUserEventStatus)"; - mUserEventCondition.wait(ul); - } + mUserEventCondition.wait(ul, [this]() { + cl_int status = *mStatus; + if (status > CL_COMPLETE) + { + INFO() << "waiting for user-event (" << &mEvent << ") to be set"; + return false; + } + return true; + }); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/CLEventVk.h b/src/libANGLE/renderer/vulkan/CLEventVk.h index d78187b9f27..1285fbf8896 100644 --- a/src/libANGLE/renderer/vulkan/CLEventVk.h +++ b/src/libANGLE/renderer/vulkan/CLEventVk.h @@ -11,14 +11,9 @@ #include #include -#include "libANGLE/renderer/vulkan/CLContextVk.h" -#include "libANGLE/renderer/vulkan/cl_types.h" -#include "libANGLE/renderer/vulkan/vk_resource.h" - #include "libANGLE/renderer/CLEventImpl.h" +#include "libANGLE/renderer/serial_utils.h" -#include "libANGLE/CLCommandQueue.h" -#include "libANGLE/CLContext.h" #include "libANGLE/CLEvent.h" namespace rx @@ -27,22 +22,14 @@ namespace rx class CLEventVk : public CLEventImpl { public: - CLEventVk(const cl::Event &event, - const cl::ExecutionStatus initialStatus, - const QueueSerial eventSerial); + CLEventVk(const cl::Event &event, const cl::ExecutionStatus initialStatus); ~CLEventVk() override; cl_int getCommandType() const { return mEvent.getCommandType(); } bool isUserEvent() const { return mEvent.isUserEvent(); } cl::Event &getFrontendObject() { return const_cast(mEvent); } const QueueSerial &getQueueSerial() { return mQueueSerial; } - bool usedByCommandBuffer(const QueueSerial &commandBufferQueueSerial) const - { - ASSERT(commandBufferQueueSerial.valid()); - return mQueueSerial == commandBufferQueueSerial; - } - - angle::Result onEventCreate() override; + void setQueueSerial(QueueSerial queueSerial); angle::Result getCommandExecutionStatus(cl_int &executionStatus) override; @@ -75,7 +62,7 @@ class CLEventVk : public CLEventImpl cl_ulong commandCompleteTS; }; angle::SynchronizedValue mProfilingTimestamps; - const QueueSerial mQueueSerial; + QueueSerial mQueueSerial; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLKernelVk.cpp b/src/libANGLE/renderer/vulkan/CLKernelVk.cpp index e76b4c72d11..bf36a9af757 100644 --- a/src/libANGLE/renderer/vulkan/CLKernelVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLKernelVk.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // CLKernelVk.cpp: Implements the class methods for CLKernelVk. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif #include "common/PackedEnums.h" @@ -18,12 +23,60 @@ #include "libANGLE/CLContext.h" #include "libANGLE/CLKernel.h" #include "libANGLE/CLProgram.h" -#include "libANGLE/cl_utils.h" #include "spirv/unified1/NonSemanticClspvReflection.h" +#include + namespace rx { +cl::Memory *GetCLKernelArgumentMemoryHandle(const CLKernelArgument &kernelArgument) +{ + if (!kernelArgument.used) + { + return nullptr; + } + + return cl::Memory::Cast(static_cast(kernelArgument.handle)); +} + +// Function to check if a kernel argument is read only. This will be used to insert appropriate +// barriers in the command buffer. Ideally, we could use the kernel argument access qualifier to +// determine read only attribute. For now, the query is based on the cl memory flags to keep the +// existing functionality in tact. +bool IsCLKernelArgumentReadonly(const CLKernelArgument &kernelArgument) +{ + // if not used, can safely assume readonly + if (!kernelArgument.used) + { + return true; + } + + switch (kernelArgument.type) + { + case NonSemanticClspvReflectionArgumentPodUniform: + case NonSemanticClspvReflectionArgumentUniform: + case NonSemanticClspvReflectionArgumentPointerUniform: + case NonSemanticClspvReflectionArgumentUniformTexelBuffer: + case NonSemanticClspvReflectionConstantDataStorageBuffer: + { + return true; + } + case NonSemanticClspvReflectionArgumentStorageBuffer: + case NonSemanticClspvReflectionArgumentStorageTexelBuffer: + case NonSemanticClspvReflectionArgumentStorageImage: + case NonSemanticClspvReflectionArgumentSampledImage: + { + const cl::Memory *mem = cl::Memory::Cast(*static_cast(kernelArgument.handle)); + return mem->getFlags().intersects(CL_MEM_READ_ONLY); + } + default: + { + return false; + } + } +} + CLKernelVk::CLKernelVk(const cl::Kernel &kernel, std::string &name, std::string &attributes, @@ -55,9 +108,21 @@ CLKernelVk::~CLKernelVk() angle::Result CLKernelVk::init() { + const CLProgramVk::DeviceProgramData *deviceProgramData = + mProgram->getDeviceProgramData(mName.c_str()); + + // Literal sampler handling + for (const ClspvLiteralSampler &literalSampler : + deviceProgramData->reflectionData.literalSamplers) + { + mDescriptorSetLayoutDescs[DescriptorSetIndex::LiteralSampler].addBinding( + literalSampler.binding, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, + nullptr); + } + vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc = mDescriptorSetLayoutDescs[DescriptorSetIndex::KernelArguments]; - VkPushConstantRange pcRange = mProgram->getDeviceProgramData(mName.c_str())->pushConstRange; + VkPushConstantRange pcRange = deviceProgramData->pushConstRange; size_t podBufferSize = 0; bool podFound = false; @@ -70,11 +135,11 @@ angle::Result CLKernelVk::init() descType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; break; case NonSemanticClspvReflectionArgumentUniform: - case NonSemanticClspvReflectionArgumentPointerUniform: descType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; break; case NonSemanticClspvReflectionArgumentPodUniform: case NonSemanticClspvReflectionArgumentPodStorageBuffer: + case NonSemanticClspvReflectionArgumentPointerUniform: { uint32_t newPodBufferSize = arg.podStorageBufferOffset + arg.podStorageBufferSize; podBufferSize = newPodBufferSize > podBufferSize ? newPodBufferSize : podBufferSize; @@ -82,13 +147,14 @@ angle::Result CLKernelVk::init() { continue; } - descType = arg.type == NonSemanticClspvReflectionArgumentPodUniform - ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER - : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descType = arg.type == NonSemanticClspvReflectionArgumentPodStorageBuffer + ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; podFound = true; break; } case NonSemanticClspvReflectionArgumentPodPushConstant: + case NonSemanticClspvReflectionArgumentPointerPushConstant: // Get existing push constant range and see if we need to update if (arg.pushConstOffset + arg.pushConstantSize > pcRange.offset + pcRange.size) { @@ -127,11 +193,10 @@ angle::Result CLKernelVk::init() nullptr, cl::MemFlags(CL_MEM_READ_ONLY), podBufferSize, nullptr))); } - if (usesPrintf()) + if (usesPrintf() && !usesPrintfBufferPointerPushConstant()) { mDescriptorSetLayoutDescs[DescriptorSetIndex::Printf].addBinding( - mProgram->getDeviceProgramData(mName.c_str()) - ->reflectionData.printfBufferStorage.binding, + deviceProgramData->reflectionData.printfBufferStorage.binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr); } @@ -148,19 +213,31 @@ angle::Result CLKernelVk::init() } } - // push constant setup - // push constant size must be multiple of 4 - pcRange.size = roundUpPow2(pcRange.size, 4u); - mPodArgumentPushConstants.resize(pcRange.size); - - // push constant offset must be multiple of 4, round down to ensure this + // push constant range size and offset both need to be a multiple of 4 + pcRange.size = roundUpPow2(pcRange.size, 4u); pcRange.offset = roundDownPow2(pcRange.offset, 4u); - mPipelineLayoutDesc.updatePushConstantRange(pcRange.stageFlags, pcRange.offset, pcRange.size); + mPodArgumentPushConstants.resize(pcRange.size); + + angle::EnumIterator layoutIndex(DescriptorSetIndex::LiteralSampler); + for (DescriptorSetIndex index : angle::AllEnums()) + { + if (!getDescriptorSetLayoutDesc(index).empty()) + { + ANGLE_CL_IMPL_TRY_ERROR(mContext->getDescriptorSetLayoutCache()->getDescriptorSetLayout( + mContext, getDescriptorSetLayoutDesc(index), + &getDescriptorSetLayouts()[*layoutIndex]), + CL_INVALID_OPERATION); + ASSERT(getDescriptorSetLayouts()[*layoutIndex]->valid()); + ++layoutIndex; + } + } + ANGLE_CL_IMPL_TRY_ERROR(initPipelineLayout(), CL_INVALID_OPERATION); + // initialize the descriptor pools // descriptor pools are setup as per their indices - return initializeDescriptorPools(); + return mContext->initializeDescriptorPools(this); } angle::Result CLKernelVk::setArg(cl_uint argIndex, size_t argSize, const void *argValue) @@ -174,7 +251,7 @@ angle::Result CLKernelVk::setArg(cl_uint argIndex, size_t argSize, const void *a ASSERT(mPodArgumentPushConstants.size() >= arg.pushConstantSize + arg.pushConstOffset); arg.handle = &mPodArgumentPushConstants[arg.pushConstOffset]; - arg.handleSize = argSize; + arg.handleSize = std::min(argSize, static_cast(arg.pushConstantSize)); if (argSize > 0 && argValue != nullptr) { // Copy the contents since app is free to delete/reassign the contents after @@ -190,22 +267,19 @@ angle::Result CLKernelVk::setArg(cl_uint argIndex, size_t argSize, const void *a argValue, arg.podStorageBufferOffset, argSize)); } break; - case NonSemanticClspvReflectionArgumentWorkgroup: - ASSERT(arg.workgroupSize != 0); - mSpecConstants.push_back( - KernelSpecConstant{.ID = arg.workgroupSpecId, - .data = static_cast(argSize / arg.workgroupSize)}); - break; case NonSemanticClspvReflectionArgumentUniform: case NonSemanticClspvReflectionArgumentStorageBuffer: case NonSemanticClspvReflectionArgumentStorageImage: case NonSemanticClspvReflectionArgumentSampledImage: case NonSemanticClspvReflectionArgumentUniformTexelBuffer: case NonSemanticClspvReflectionArgumentStorageTexelBuffer: + case NonSemanticClspvReflectionArgumentPointerPushConstant: + case NonSemanticClspvReflectionArgumentPointerUniform: ASSERT(argSize == sizeof(cl_mem *)); arg.handle = *static_cast(argValue); arg.handleSize = argSize; break; + case NonSemanticClspvReflectionArgumentWorkgroup: default: // Just store ptr and size (if we end up here) arg.handle = const_cast(argValue); @@ -328,12 +402,19 @@ angle::Result CLKernelVk::getOrCreateComputePipeline(vk::PipelineCacheAccess *pi constantDataOffset += sizeof(uint32_t); } // Populate kernel specialization constants (if any) - for (const auto &specConstant : mSpecConstants) + for (const auto &arg : mArgs) { - specConstantData.push_back(specConstant.data); - mapEntries.push_back(VkSpecializationMapEntry{ - .constantID = specConstant.ID, .offset = constantDataOffset, .size = sizeof(uint32_t)}); - constantDataOffset += sizeof(uint32_t); + if (arg.used && arg.type == NonSemanticClspvReflectionArgumentWorkgroup) + { + ASSERT(arg.workgroupBufferElemSize != 0); + + specConstantData.push_back( + static_cast(arg.handleSize / arg.workgroupBufferElemSize)); + mapEntries.push_back(VkSpecializationMapEntry{.constantID = arg.workgroupBufferSpecId, + .offset = constantDataOffset, + .size = sizeof(uint32_t)}); + constantDataOffset += sizeof(uint32_t); + } } VkSpecializationInfo computeSpecializationInfo{ .mapEntryCount = static_cast(mapEntries.size()), @@ -356,6 +437,13 @@ bool CLKernelVk::usesPrintf() const NonSemanticClspvReflectionMayUsePrintf; } +bool CLKernelVk::usesPrintfBufferPointerPushConstant() const +{ + return mProgram->getDeviceProgramData(mName.c_str()) + ->reflectionData.pushConstants.contains( + NonSemanticClspvReflectionPrintfBufferPointerPushConstant); +} + angle::Result CLKernelVk::initializeDescriptorPools() { for (DescriptorSetIndex index : angle::AllEnums()) diff --git a/src/libANGLE/renderer/vulkan/CLKernelVk.h b/src/libANGLE/renderer/vulkan/CLKernelVk.h index ba07c4e6bf3..da385677bc4 100644 --- a/src/libANGLE/renderer/vulkan/CLKernelVk.h +++ b/src/libANGLE/renderer/vulkan/CLKernelVk.h @@ -8,13 +8,14 @@ #ifndef LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_ #define LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_ +#include "libANGLE/renderer/vulkan/CLMemoryVk.h" #include "libANGLE/renderer/vulkan/cl_types.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_utils.h" -#include "libANGLE/CLMemory.h" #include "libANGLE/renderer/CLKernelImpl.h" + #include "vulkan/vulkan_core.h" namespace rx @@ -38,14 +39,14 @@ struct CLKernelArgument uint32_t op3; uint32_t descriptorSet; uint32_t pushConstOffset; - uint32_t workgroupSpecId; + uint32_t workgroupBufferSpecId; }; union { uint32_t op4; uint32_t descriptorBinding; uint32_t pushConstantSize; - uint32_t workgroupSize; + uint32_t workgroupBufferElemSize; }; union { @@ -64,6 +65,8 @@ struct CLKernelArgument }; using CLKernelArguments = std::vector; using CLKernelArgsMap = angle::HashMap; +bool IsCLKernelArgumentReadonly(const CLKernelArgument &kernelArgument); +cl::Memory *GetCLKernelArgumentMemoryHandle(const CLKernelArgument &kernelArgument); class CLKernelVk : public CLKernelImpl { @@ -134,16 +137,17 @@ class CLKernelVk : public CLKernelImpl cl::MemoryPtr getPodBuffer() { return mPodBuffer; } bool usesPrintf() const; + bool usesPrintfBufferPointerPushConstant() const; angle::Result allocateDescriptorSet( DescriptorSetIndex index, angle::EnumIterator layoutIndex, vk::OutsideRenderPassCommandBufferHelper *computePassCommands); - private: // Initialize the descriptor pools for this kernel resources angle::Result initializeDescriptorPools(); + private: CLProgramVk *mProgram; CLContextVk *mContext; std::string mName; @@ -155,7 +159,6 @@ class CLKernelVk : public CLKernelImpl vk::ShaderProgramHelper mShaderProgramHelper; ComputePipelineCache mComputePipelineCache; - KernelSpecConstants mSpecConstants; // Pipeline and DescriptorSetLayout Shared pointers vk::PipelineLayoutPtr mPipelineLayout; diff --git a/src/libANGLE/renderer/vulkan/CLMemoryVk.cpp b/src/libANGLE/renderer/vulkan/CLMemoryVk.cpp index 704179c8d5a..81cf21a3a67 100644 --- a/src/libANGLE/renderer/vulkan/CLMemoryVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLMemoryVk.cpp @@ -4,9 +4,17 @@ // found in the LICENSE file. // // CLMemoryVk.cpp: Implements the class methods for CLMemoryVk. +// -#include "libANGLE/renderer/vulkan/CLMemoryVk.h" +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "common/log_utils.h" + +#include #include "libANGLE/renderer/vulkan/CLContextVk.h" +#include "libANGLE/renderer/vulkan/CLMemoryVk.h" #include "libANGLE/renderer/vulkan/vk_cl_utils.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" #include "libANGLE/renderer/vulkan/vk_utils.h" @@ -21,6 +29,7 @@ #include "libANGLE/CLImage.h" #include "libANGLE/CLMemory.h" #include "libANGLE/Error.h" +#include "libANGLE/cl_types.h" #include "libANGLE/cl_utils.h" #include "CL/cl_half.h" @@ -79,6 +88,49 @@ angle::FormatID CLImageFormatToAngleFormat(cl_image_format format) } } +bool GetExternalMemoryHandleInfo(const cl_mem_properties *properties, + VkExternalMemoryHandleTypeFlagBits *vkExtMemoryHandleType, + int32_t *fd) +{ + bool propertyStatus = true; + const cl::NameValueProperty *propertyIterator = + reinterpret_cast(properties); + while (propertyIterator->name != 0) + { + switch (propertyIterator->name) + { + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR: + *vkExtMemoryHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + break; + case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR: + *vkExtMemoryHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + break; + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR: + *vkExtMemoryHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; + break; + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR: + *vkExtMemoryHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + break; + default: + propertyStatus = false; + break; + } + + if (propertyStatus) + { + *fd = *(reinterpret_cast(propertyIterator->value)); + if (*fd < 0) + { + propertyStatus = false; + } + break; + } + propertyIterator++; + } + + return propertyStatus; +} + } // namespace CLMemoryVk::CLMemoryVk(const cl::Memory &memory) @@ -97,7 +149,8 @@ CLMemoryVk::~CLMemoryVk() VkBufferUsageFlags CLMemoryVk::getVkUsageFlags() { - return cl_vk::GetBufferUsageFlags(mMemory.getFlags()); + return cl_vk::GetBufferUsageFlags(mMemory.getFlags(), + mContext->getFeatures().supportsBufferDeviceAddress.enabled); } VkMemoryPropertyFlags CLMemoryVk::getVkMemPropertyFlags() @@ -107,38 +160,39 @@ VkMemoryPropertyFlags CLMemoryVk::getVkMemPropertyFlags() angle::Result CLMemoryVk::map(uint8_t *&ptrOut, size_t offset) { - if (!isMapped()) + if (getFlags().intersects(CL_MEM_USE_HOST_PTR)) + { + // as per spec, the returned pointer for USE_HOST_PTR will be derived from the hostptr... + ASSERT(mMemory.getHostPtr()); + ptrOut = static_cast(mMemory.getHostPtr()) + offset; + } + else { - ANGLE_TRY(mapImpl()); + // ...otherwise we just map the VK memory to cpu va space + ANGLE_TRY(mapBufferHelper(ptrOut)); + ptrOut += offset; } - ptrOut = mMappedMemory + offset; + return angle::Result::Continue; } angle::Result CLMemoryVk::copyTo(void *dst, size_t srcOffset, size_t size) { uint8_t *src = nullptr; - ANGLE_TRY(map(src, srcOffset)); + ANGLE_TRY(mapBufferHelper(src)); + src += srcOffset; std::memcpy(dst, src, size); - unmap(); - return angle::Result::Continue; -} - -angle::Result CLMemoryVk::copyTo(CLMemoryVk *dst, size_t srcOffset, size_t dstOffset, size_t size) -{ - uint8_t *dstPtr = nullptr; - ANGLE_TRY(dst->map(dstPtr, dstOffset)); - ANGLE_TRY(copyTo(dstPtr, srcOffset, size)); - dst->unmap(); + unmapBufferHelper(); return angle::Result::Continue; } angle::Result CLMemoryVk::copyFrom(const void *src, size_t srcOffset, size_t size) { uint8_t *dst = nullptr; - ANGLE_TRY(map(dst, srcOffset)); + ANGLE_TRY(mapBufferHelper(dst)); + dst += srcOffset; std::memcpy(dst, src, size); - unmap(); + unmapBufferHelper(); return angle::Result::Continue; } @@ -178,11 +232,25 @@ CLBufferVk::~CLBufferVk() { if (isMapped()) { - unmap(); + unmapBufferHelper(); } mBuffer.destroy(mRenderer); } +bool CLBufferVk::isHostPtrAligned() const +{ + VkDeviceSize alignment = + mRenderer->getPhysicalDeviceExternalMemoryHostProperties().minImportedHostPointerAlignment; + return reinterpret_cast(mMemory.getHostPtr()) % alignment == 0 && + getSize() % alignment == 0; +} + +bool CLBufferVk::supportsZeroCopy() const +{ + return mRenderer->getFeatures().supportsExternalMemoryHost.enabled && + mMemory.getFlags().intersects(CL_MEM_USE_HOST_PTR) && isHostPtrAligned(); +} + vk::BufferHelper &CLBufferVk::getBuffer() { if (isSubBuffer()) @@ -192,24 +260,128 @@ vk::BufferHelper &CLBufferVk::getBuffer() return mBuffer; } +// For UHP buffers, the buffer contents and hostptr have to be in sync at appropriate times. Ensure +// that if zero copy is not supported. +angle::Result CLBufferVk::syncHost(CLBufferVk::SyncHostDirection direction) +{ + switch (direction) + { + case CLBufferVk::SyncHostDirection::FromHost: + if (getFlags().intersects(CL_MEM_USE_HOST_PTR) && !supportsZeroCopy()) + { + ANGLE_CL_IMPL_TRY_ERROR( + setDataImpl(static_cast(getHostPtr()), getSize(), 0), + CL_OUT_OF_RESOURCES); + } + break; + case CLBufferVk::SyncHostDirection::ToHost: + if (getFlags().intersects(CL_MEM_USE_HOST_PTR) && !supportsZeroCopy()) + { + ANGLE_TRY(copyTo(getHostPtr(), 0, getSize())); + } + break; + default: + UNREACHABLE(); + break; + } + return angle::Result::Continue; +} + +// This is to sync only a rectangular region between hostptr and buffer contents. Intended to be +// used for READ/WRITE_RECT. +angle::Result CLBufferVk::syncHost(CLBufferVk::SyncHostDirection direction, cl::BufferRect hostRect) +{ + switch (direction) + { + case CLBufferVk::SyncHostDirection::FromHost: + if (getFlags().intersects(CL_MEM_USE_HOST_PTR) && !supportsZeroCopy()) + { + ANGLE_TRY(setRect(getHostPtr(), hostRect, hostRect)); + } + break; + case CLBufferVk::SyncHostDirection::ToHost: + if (getFlags().intersects(CL_MEM_USE_HOST_PTR) && !supportsZeroCopy()) + { + ANGLE_TRY(getRect(hostRect, hostRect, getHostPtr())); + } + break; + default: + UNREACHABLE(); + break; + } + return angle::Result::Continue; +} + angle::Result CLBufferVk::create(void *hostPtr) { + const cl_mem_properties *properties = getFrontendObject().getProperties().data(); + if (properties) + { + const cl::NameValueProperty *property = + reinterpret_cast(properties); + if (property->name != 0) + { + return createWithProperties(); + } + } + if (!isSubBuffer()) { VkBufferCreateInfo createInfo = mDefaultBufferCreateInfo; createInfo.size = getSize(); VkMemoryPropertyFlags memFlags = getVkMemPropertyFlags(); - if (IsError(mBuffer.init(mContext, createInfo, memFlags))) + + if (supportsZeroCopy()) { - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + return mBuffer.initHostExternal(mContext, memFlags, createInfo, hostPtr); } - if (mMemory.getFlags().intersects(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) + + ANGLE_CL_IMPL_TRY_ERROR(mBuffer.init(mContext, createInfo, memFlags), CL_OUT_OF_RESOURCES); + // We need to copy the data from hostptr in the case of CHP buffer. + if (getFlags().intersects(CL_MEM_COPY_HOST_PTR)) { - ASSERT(hostPtr); ANGLE_CL_IMPL_TRY_ERROR(setDataImpl(static_cast(hostPtr), getSize(), 0), CL_OUT_OF_RESOURCES); } + ANGLE_TRY(syncHost(CLBufferVk::SyncHostDirection::FromHost)); + } + return angle::Result::Continue; +} + +angle::Result CLBufferVk::createWithProperties() +{ + ASSERT(!isSubBuffer()); + + int32_t sharedBufferFD = -1; + VkExternalMemoryHandleTypeFlagBits vkExtMemoryHandleType; + const cl_mem_properties *properties = getFrontendObject().getProperties().data(); + if (GetExternalMemoryHandleInfo(properties, &vkExtMemoryHandleType, &sharedBufferFD)) + { +#if defined(ANGLE_PLATFORM_WINDOWS) + UNIMPLEMENTED(); + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); +#else + VkBufferCreateInfo createInfo = mDefaultBufferCreateInfo; + createInfo.size = getSize(); + VkMemoryPropertyFlags memFlags = getVkMemPropertyFlags(); + + // VK_KHR_external_memory assumes the ownership of the buffer as part of the import + // operation. No such requirement is present with cl_khr_external_memory and + // cl_arm_import_memory extension. So we dup the fd for now, and let the application still + // hold on to the fd. + if (IsError(mBuffer.initAndAcquireFromExternalMemory( + mContext, memFlags, createInfo, vkExtMemoryHandleType, dup(sharedBufferFD)))) + { + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + } +#endif + } + else + { + // Don't expect to be here, as validation layer should have caught unsupported uses. + UNREACHABLE(); } + return angle::Result::Continue; } @@ -218,120 +390,138 @@ angle::Result CLBufferVk::copyToWithPitch(void *hostPtr, size_t size, size_t rowPitch, size_t slicePitch, - cl::Coordinate region, + cl::Extents region, const size_t elementSize) { uint8_t *ptrInBase = nullptr; uint8_t *ptrOutBase = nullptr; cl::BufferRect stagingBufferRect{ {static_cast(0), static_cast(0), static_cast(0)}, - {region.x, region.y, region.z}, + {region.width, region.height, region.depth}, 0, 0, elementSize}; ptrOutBase = static_cast(hostPtr); - ANGLE_TRY(getBuffer().map(mContext, &ptrInBase)); + ANGLE_TRY(mapBufferHelper(ptrInBase)); + cl::Defer deferUnmap([this]() { unmapBufferHelper(); }); - for (size_t slice = 0; slice < region.z; slice++) + for (size_t slice = 0; slice < region.depth; slice++) { - for (size_t row = 0; row < region.y; row++) + for (size_t row = 0; row < region.height; row++) { size_t stagingBufferOffset = stagingBufferRect.getRowOffset(slice, row); size_t hostPtrOffset = (slice * slicePitch + row * rowPitch); uint8_t *dst = ptrOutBase + hostPtrOffset; uint8_t *src = ptrInBase + stagingBufferOffset; - memcpy(dst, src, region.x * elementSize); + memcpy(dst, src, region.width * elementSize); } } - getBuffer().unmap(mContext->getRenderer()); return angle::Result::Continue; } -angle::Result CLBufferVk::mapImpl() +angle::Result CLBufferVk::mapBufferHelper(uint8_t *&ptrOut) { - ASSERT(!isMapped()); - - if (isSubBuffer()) + if (!isMapped()) { - ANGLE_TRY(mParent->map(mMappedMemory, getOffset())); - return angle::Result::Continue; + if (isSubBuffer()) + { + return mapParentBufferHelper(ptrOut); + } + + std::lock_guard lock(mMutex); + ANGLE_TRY(mBuffer.map(mContext, &mMappedMemory)); + ++mMapCount; } - ANGLE_TRY(mBuffer.map(mContext, &mMappedMemory)); + ptrOut = mMappedMemory; + ASSERT(ptrOut); + return angle::Result::Continue; } -void CLBufferVk::unmapImpl() +angle::Result CLBufferVk::mapParentBufferHelper(uint8_t *&ptrOut) { - if (!isSubBuffer()) - { - mBuffer.unmap(mRenderer); - } - mMappedMemory = nullptr; + ASSERT(getParent()); + + ANGLE_TRY(getParent()->mapBufferHelper(ptrOut)); + ptrOut += getOffset(); + return angle::Result::Continue; } -angle::Result CLBufferVk::setRect(const void *data, - const cl::BufferRect &srcRect, - const cl::BufferRect &rect) +void CLBufferVk::unmapBufferHelper() { - ASSERT(srcRect.valid() && rect.valid()); - ASSERT(srcRect.mSize == rect.mSize); - - uint8_t *mapPtr = nullptr; - ANGLE_TRY(map(mapPtr)); - const uint8_t *srcData = reinterpret_cast(data); - for (size_t slice = 0; slice < rect.mSize.depth; slice++) + if (isSubBuffer()) { - for (size_t row = 0; row < rect.mSize.height; row++) - { - const uint8_t *src = srcData + srcRect.getRowOffset(slice, row); - uint8_t *dst = mapPtr + rect.getRowOffset(slice, row); - - memcpy(dst, src, srcRect.mSize.width * srcRect.mElementSize); - } + getParent()->unmapBufferHelper(); + return; } - return angle::Result::Continue; + std::lock_guard lock(mMutex); + getBuffer().unmap(mContext->getRenderer()); + if (--mMapCount == 0u) + { + mMappedMemory = nullptr; + } } -angle::Result CLBufferVk::getRect(const cl::BufferRect &srcRect, - const cl::BufferRect &outRect, - void *outData) +angle::Result CLBufferVk::updateRect(UpdateRectOperation op, + void *data, + const cl::BufferRect &dataRect, + const cl::BufferRect &bufferRect) { - ASSERT(srcRect.valid() && outRect.valid()); - ASSERT(srcRect.mSize == outRect.mSize); + ASSERT(dataRect.valid() && bufferRect.valid()); + ASSERT(dataRect.mSize == bufferRect.mSize && dataRect.mElementSize == bufferRect.mElementSize); - uint8_t *mapPtr = nullptr; - ANGLE_TRY(map(mapPtr)); - uint8_t *dstData = reinterpret_cast(outData); - for (size_t slice = 0; slice < srcRect.mSize.depth; slice++) + uint8_t *bufferPtr = nullptr; + ANGLE_TRY(mapBufferHelper(bufferPtr)); + cl::Defer deferUnmap([this]() { unmapBufferHelper(); }); + + uint8_t *dataUint8Ptr = reinterpret_cast(data); + for (size_t slice = 0; slice < bufferRect.mSize.depth; slice++) { - for (size_t row = 0; row < srcRect.mSize.height; row++) + for (size_t row = 0; row < bufferRect.mSize.height; row++) { - const uint8_t *src = mapPtr + srcRect.getRowOffset(slice, row); - uint8_t *dst = dstData + outRect.getRowOffset(slice, row); + uint8_t *offsetDataPtr = dataUint8Ptr + dataRect.getRowOffset(slice, row); + uint8_t *offsetBufferPtr = bufferPtr + bufferRect.getRowOffset(slice, row); + size_t updateSize = dataRect.mSize.width * dataRect.mElementSize; - memcpy(dst, src, srcRect.mSize.width * srcRect.mElementSize); + switch (op) + { + case UpdateRectOperation::Read: + { + // Read from this buffer + memcpy(offsetDataPtr, offsetBufferPtr, updateSize); + break; + } + case UpdateRectOperation::Write: + { + // Write to this buffer + memcpy(offsetBufferPtr, offsetDataPtr, updateSize); + break; + } + default: + { + UNREACHABLE(); + break; + } + } } } - return angle::Result::Continue; } -std::vector CLBufferVk::rectCopyRegions(const cl::BufferRect &bufferRect) +angle::Result CLBufferVk::setRect(const void *data, + const cl::BufferRect &dataRect, + const cl::BufferRect &bufferRect) { - std::vector copyRegions; - for (unsigned int slice = 0; slice < bufferRect.mSize.depth; slice++) - { - for (unsigned int row = 0; row < bufferRect.mSize.height; row++) - { - VkBufferCopy copyRegion = {}; - copyRegion.size = bufferRect.mSize.width * bufferRect.mElementSize; - copyRegion.srcOffset = copyRegion.dstOffset = bufferRect.getRowOffset(slice, row); - copyRegions.push_back(copyRegion); - } - } - return copyRegions; + return updateRect(UpdateRectOperation::Write, const_cast(data), dataRect, bufferRect); +} + +angle::Result CLBufferVk::getRect(const cl::BufferRect &bufferRect, + const cl::BufferRect &dataRect, + void *outData) +{ + return updateRect(UpdateRectOperation::Read, outData, dataRect, bufferRect); } // offset is for mapped pointer @@ -366,10 +556,31 @@ bool CLBufferVk::isCurrentlyInUse() const return !mRenderer->hasResourceUseFinished(mBuffer.getResourceUse()); } +template <> +CLBufferVk *CLImageVk::getParent() const +{ + if (mParent) + { + ASSERT(cl::IsBufferType(getParentType())); + return static_cast(mParent); + } + return nullptr; +} + +template <> +CLImageVk *CLImageVk::getParent() const +{ + if (mParent) + { + ASSERT(cl::IsImageType(getParentType())); + return static_cast(mParent); + } + return nullptr; +} + VkImageUsageFlags CLImageVk::getVkImageUsageFlags() { - VkImageUsageFlags usageFlags = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + VkImageUsageFlags usageFlags = vk::kImageUsageTransferBits; if (mMemory.getFlags().intersects(CL_MEM_WRITE_ONLY)) { @@ -409,22 +620,22 @@ VkImageType CLImageVk::getVkImageType(const cl::ImageDescriptor &desc) return imageType; } -angle::Result CLImageVk::createStagingBuffer(size_t size) +angle::Result CLImageVk::getOrCreateStagingBuffer(CLBufferVk **clBufferOut) { - const VkBufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - nullptr, - 0, - size, - getVkUsageFlags(), - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr}; - if (IsError(mStagingBuffer.init(mContext, createInfo, getVkMemPropertyFlags()))) + ASSERT(clBufferOut && "cannot pass nullptr to clBufferOut!"); + + std::lock_guard lock(mMutex); + + if (!cl::Buffer::IsValid(mStagingBuffer)) { - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + mStagingBuffer = cl::Buffer::Cast(mContext->getFrontendObject().createBuffer( + nullptr, cl::MemFlags(CL_MEM_READ_WRITE), getSize(), nullptr)); + if (!cl::Buffer::IsValid(mStagingBuffer)) + { + ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + } } - - mStagingBufferInitialized = true; + *clBufferOut = &mStagingBuffer->getImpl(); return angle::Result::Continue; } @@ -432,46 +643,53 @@ angle::Result CLImageVk::copyStagingFrom(void *ptr, size_t offset, size_t size) { uint8_t *ptrOut; uint8_t *ptrIn = static_cast(ptr); - ANGLE_TRY(getStagingBuffer().map(mContext, &ptrOut)); + + ANGLE_TRY(mapBufferHelper(ptrOut)); + cl::Defer deferUnmap([this]() { unmapBufferHelper(); }); + std::memcpy(ptrOut, ptrIn + offset, size); - ANGLE_TRY(getStagingBuffer().flush(mRenderer)); - getStagingBuffer().unmap(mContext->getRenderer()); + return angle::Result::Continue; } angle::Result CLImageVk::copyStagingTo(void *ptr, size_t offset, size_t size) { uint8_t *ptrOut; - ANGLE_TRY(getStagingBuffer().map(mContext, &ptrOut)); - ANGLE_TRY(getStagingBuffer().invalidate(mRenderer)); + + ANGLE_TRY(mapBufferHelper(ptrOut)); + cl::Defer deferUnmap([this]() { unmapBufferHelper(); }); + std::memcpy(ptr, ptrOut + offset, size); - getStagingBuffer().unmap(mContext->getRenderer()); + return angle::Result::Continue; } angle::Result CLImageVk::copyStagingToFromWithPitch(void *hostPtr, - const cl::Coordinate ®ion, + const cl::Extents ®ion, const size_t rowPitch, const size_t slicePitch, StagingBufferCopyDirection copyStagingTo) { uint8_t *ptrInBase = nullptr; uint8_t *ptrOutBase = nullptr; - cl::BufferRect stagingBufferRect{{}, {region.x, region.y, region.z}, 0, 0, getElementSize()}; + cl::BufferRect stagingBufferRect{ + {}, {region.width, region.height, region.depth}, 0, 0, getElementSize()}; if (copyStagingTo == StagingBufferCopyDirection::ToHost) { ptrOutBase = static_cast(hostPtr); - ANGLE_TRY(getStagingBuffer().map(mContext, &ptrInBase)); + ANGLE_TRY(mapBufferHelper(ptrInBase)); } else { ptrInBase = static_cast(hostPtr); - ANGLE_TRY(getStagingBuffer().map(mContext, &ptrOutBase)); + ANGLE_TRY(mapBufferHelper(ptrOutBase)); } - for (size_t slice = 0; slice < region.z; slice++) + cl::Defer deferUnmap([this]() { unmapBufferHelper(); }); + + for (size_t slice = 0; slice < region.depth; slice++) { - for (size_t row = 0; row < region.y; row++) + for (size_t row = 0; row < region.height; row++) { size_t stagingBufferOffset = stagingBufferRect.getRowOffset(slice, row); size_t hostPtrOffset = (slice * slicePitch + row * rowPitch); @@ -481,10 +699,9 @@ angle::Result CLImageVk::copyStagingToFromWithPitch(void *hostPtr, uint8_t *src = (copyStagingTo == StagingBufferCopyDirection::ToHost) ? ptrInBase + stagingBufferOffset : ptrInBase + hostPtrOffset; - memcpy(dst, src, region.x * getElementSize()); + memcpy(dst, src, region.width * getElementSize()); } } - getStagingBuffer().unmap(mContext->getRenderer()); return angle::Result::Continue; } @@ -492,7 +709,7 @@ CLImageVk::CLImageVk(const cl::Image &image) : CLMemoryVk(image), mExtent(cl::GetExtentFromDescriptor(image.getDescriptor())), mAngleFormat(CLImageFormatToAngleFormat(image.getFormat())), - mStagingBufferInitialized(false), + mStagingBuffer(nullptr), mImageViewType(cl_vk::GetImageViewType(image.getDescriptor().type)) { if (image.getParent()) @@ -515,9 +732,9 @@ CLImageVk::~CLImageVk() mImage.destroy(mRenderer); mImageView.destroy(mContext->getDevice()); - if (isStagingBufferInitialized()) + if (cl::Memory::IsValid(mStagingBuffer) && mStagingBuffer->release()) { - mStagingBuffer.destroy(mRenderer); + SafeDelete(mStagingBuffer); } } @@ -547,17 +764,16 @@ angle::Result CLImageVk::create(void *hostPtr) } } - ANGLE_CL_IMPL_TRY_ERROR( - mImage.initStaging(mContext, false, mRenderer->getMemoryProperties(), - getVkImageType(getDescriptor()), cl_vk::GetExtent(mExtent), mAngleFormat, - mAngleFormat, VK_SAMPLE_COUNT_1_BIT, getVkImageUsageFlags(), 1, - (uint32_t)getArraySize()), - CL_OUT_OF_RESOURCES); + ANGLE_CL_IMPL_TRY_ERROR(mImage.initStaging(mContext, false, getVkImageType(getDescriptor()), + cl_vk::GetExtent(mExtent), mAngleFormat, + mAngleFormat, VK_SAMPLE_COUNT_1_BIT, + getVkImageUsageFlags(), 1, (uint32_t)getArraySize()), + CL_OUT_OF_RESOURCES); if (mMemory.getFlags().intersects(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) { ASSERT(hostPtr); - ANGLE_CL_IMPL_TRY_ERROR(createStagingBuffer(getSize()), CL_OUT_OF_RESOURCES); + if (getDescriptor().rowPitch == 0 && getDescriptor().slicePitch == 0) { ANGLE_CL_IMPL_TRY_ERROR(copyStagingFrom(hostPtr, 0, getSize()), CL_OUT_OF_RESOURCES); @@ -574,13 +790,18 @@ angle::Result CLImageVk::create(void *hostPtr) copyRegion.bufferImageHeight = 0; copyRegion.imageExtent = cl_vk::GetExtent(getExtentForCopy({mExtent.width, mExtent.height, mExtent.depth})); - copyRegion.imageOffset = cl_vk::GetOffset(getOffsetForCopy(cl::kMemOffsetsZero)); + copyRegion.imageOffset = cl_vk::GetOffset(cl::kOffsetZero); copyRegion.imageSubresource = getSubresourceLayersForCopy( - cl::kMemOffsetsZero, {mExtent.width, mExtent.height, mExtent.depth}, getType(), + cl::kOffsetZero, {mExtent.width, mExtent.height, mExtent.depth}, getType(), ImageCopyWith::Buffer); - ANGLE_CL_IMPL_TRY_ERROR(mImage.copyToBufferOneOff(mContext, &mStagingBuffer, copyRegion), - CL_OUT_OF_RESOURCES); + // copy over the hostptr bits here to image in a one-off copy cmd + CLBufferVk *stagingBuffer = nullptr; + ANGLE_TRY(getOrCreateStagingBuffer(&stagingBuffer)); + ASSERT(stagingBuffer); + ANGLE_CL_IMPL_TRY_ERROR( + mImage.copyToBufferOneOff(mContext, &stagingBuffer->getBuffer(), copyRegion), + CL_OUT_OF_RESOURCES); } ANGLE_TRY(initImageViewImpl()); @@ -655,8 +876,10 @@ void CLImageVk::packPixels(const void *fillColor, PixelColor *packedColor) else { for (unsigned int i = 0; i < channelCount; i++) + { packedColor->u8[i] = static_cast(NormalizeFloatValue(srcVector[i], 255.f)); + } } break; } @@ -664,68 +887,86 @@ void CLImageVk::packPixels(const void *fillColor, PixelColor *packedColor) { int *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->s8[i] = static_cast(std::clamp(srcVector[i], -128, 127)); + } break; } case CL_UNSIGNED_INT8: { unsigned int *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->u8[i] = static_cast( std::clamp(static_cast(srcVector[i]), static_cast(0), static_cast(255))); + } break; } case CL_UNORM_INT16: { float *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->u16[i] = static_cast(NormalizeFloatValue(srcVector[i], 65535.f)); + } break; } case CL_SIGNED_INT16: { int *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->s16[i] = static_cast(std::clamp(srcVector[i], -32768, 32767)); + } break; } case CL_UNSIGNED_INT16: { unsigned int *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->u16[i] = static_cast( std::clamp(static_cast(srcVector[i]), static_cast(0), static_cast(65535))); + } break; } case CL_HALF_FLOAT: { float *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->fp16[i] = cl_half_from_float(srcVector[i], CL_HALF_RTE); + } break; } case CL_SIGNED_INT32: { int *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->s32[i] = static_cast(srcVector[i]); + } break; } case CL_UNSIGNED_INT32: { unsigned int *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->u32[i] = static_cast(srcVector[i]); + } break; } case CL_FLOAT: { float *srcVector = static_cast(const_cast(fillColor)); for (unsigned int i = 0; i < channelCount; i++) + { packedColor->fp32[i] = srcVector[i]; + } break; } default: @@ -734,37 +975,44 @@ void CLImageVk::packPixels(const void *fillColor, PixelColor *packedColor) } } -void CLImageVk::fillImageWithColor(const cl::MemOffsets &origin, - const cl::Coordinate ®ion, - uint8_t *imagePtr, - PixelColor *packedColor) +angle::Result CLImageVk::fillImageWithColor(const cl::Offset &origin, + const cl::Extents ®ion, + PixelColor *packedColor) { size_t elementSize = getElementSize(); cl::BufferRect stagingBufferRect{ {}, {mExtent.width, mExtent.height, mExtent.depth}, 0, 0, elementSize}; + + uint8_t *imagePtr = nullptr; + ANGLE_TRY(mapBufferHelper(imagePtr)); + cl::Defer deferUnmap([this]() { unmapBufferHelper(); }); + uint8_t *ptrBase = imagePtr + (origin.z * stagingBufferRect.getSlicePitch()) + (origin.y * stagingBufferRect.getRowPitch()) + (origin.x * elementSize); - for (size_t slice = 0; slice < region.z; slice++) + + for (size_t slice = 0; slice < region.depth; slice++) { - for (size_t row = 0; row < region.y; row++) + for (size_t row = 0; row < region.height; row++) { size_t stagingBufferOffset = stagingBufferRect.getRowOffset(slice, row); uint8_t *pixelPtr = ptrBase + stagingBufferOffset; - for (size_t x = 0; x < region.x; x++) + for (size_t x = 0; x < region.width; x++) { memcpy(pixelPtr, packedColor, elementSize); pixelPtr += elementSize; } } } + + return angle::Result::Continue; } -cl::Extents CLImageVk::getExtentForCopy(const cl::Coordinate ®ion) +cl::Extents CLImageVk::getExtentForCopy(const cl::Extents ®ion) { cl::Extents extent = {}; - extent.width = region.x; - extent.height = region.y; - extent.depth = region.z; + extent.width = region.width; + extent.height = region.height; + extent.depth = region.depth; switch (getDescriptor().type) { case cl::MemObjectType::Image1D_Array: @@ -781,7 +1029,7 @@ cl::Extents CLImageVk::getExtentForCopy(const cl::Coordinate ®ion) return extent; } -cl::Offset CLImageVk::getOffsetForCopy(const cl::MemOffsets &origin) +cl::Offset CLImageVk::getOffsetForCopy(const cl::Offset &origin) { cl::Offset offset = {}; offset.x = origin.x; @@ -802,8 +1050,8 @@ cl::Offset CLImageVk::getOffsetForCopy(const cl::MemOffsets &origin) return offset; } -VkImageSubresourceLayers CLImageVk::getSubresourceLayersForCopy(const cl::MemOffsets &origin, - const cl::Coordinate ®ion, +VkImageSubresourceLayers CLImageVk::getSubresourceLayersForCopy(const cl::Offset &origin, + const cl::Extents ®ion, cl::MemObjectType copyToType, ImageCopyWith imageCopy) { @@ -816,7 +1064,7 @@ VkImageSubresourceLayers CLImageVk::getSubresourceLayersForCopy(const cl::MemOff subresource.baseArrayLayer = static_cast(origin.y); if (imageCopy == ImageCopyWith::Image) { - subresource.layerCount = static_cast(region.y); + subresource.layerCount = static_cast(region.height); } else { @@ -832,7 +1080,7 @@ VkImageSubresourceLayers CLImageVk::getSubresourceLayersForCopy(const cl::MemOff } else if (imageCopy == ImageCopyWith::Image) { - subresource.layerCount = static_cast(region.z); + subresource.layerCount = static_cast(region.depth); } else { @@ -847,28 +1095,55 @@ VkImageSubresourceLayers CLImageVk::getSubresourceLayersForCopy(const cl::MemOff return subresource; } -angle::Result CLImageVk::mapImpl() +angle::Result CLImageVk::mapBufferHelper(uint8_t *&ptrOut) { - ASSERT(!isMapped()); - - if (mParent) + if (!isMapped()) { - ANGLE_TRY(mParent->map(mMappedMemory, getOffset())); - return angle::Result::Continue; + if (mParent) + { + return mapParentBufferHelper(ptrOut); + } + + CLBufferVk *stagingBuffer = nullptr; + ANGLE_TRY(getOrCreateStagingBuffer(&stagingBuffer)); + ASSERT(stagingBuffer); + ANGLE_TRY(stagingBuffer->mapBufferHelper(mMappedMemory)); } + ASSERT(mMappedMemory); + ptrOut = mMappedMemory; - ASSERT(isStagingBufferInitialized()); - ANGLE_TRY(getStagingBuffer().map(mContext, &mMappedMemory)); + return angle::Result::Continue; +} +angle::Result CLImageVk::mapParentBufferHelper(uint8_t *&ptrOut) +{ + ASSERT(mParent); + + if (cl::IsBufferType(getParentType())) + { + ANGLE_TRY(getParent()->mapBufferHelper(ptrOut)); + } + else if (cl::IsImageType(getParentType())) + { + ANGLE_TRY(getParent()->mapBufferHelper(ptrOut)); + } + else + { + UNREACHABLE(); + } + ptrOut += getOffset(); return angle::Result::Continue; } -void CLImageVk::unmapImpl() + +void CLImageVk::unmapBufferHelper() { - if (!mParent) + if (mParent) { - getStagingBuffer().unmap(mContext->getRenderer()); + getParent()->unmapBufferHelper(); + return; } - mMappedMemory = nullptr; + ASSERT(mStagingBuffer); + mStagingBuffer->getImpl().unmapBufferHelper(); } size_t CLImageVk::getRowPitch() const @@ -881,28 +1156,6 @@ size_t CLImageVk::getSlicePitch() const return getFrontendObject().getSliceSize(); } -template <> -CLBufferVk *CLImageVk::getParent() const -{ - if (mParent) - { - ASSERT(cl::IsBufferType(getParentType())); - return static_cast(mParent); - } - return nullptr; -} - -template <> -CLImageVk *CLImageVk::getParent() const -{ - if (mParent) - { - ASSERT(cl::IsImageType(getParentType())); - return static_cast(mParent); - } - return nullptr; -} - cl::MemObjectType CLImageVk::getParentType() const { if (mParent) @@ -923,7 +1176,8 @@ angle::Result CLImageVk::getBufferView(const vk::BufferView **viewOut) return mBufferViews.getView( mContext, parent->getBuffer(), parent->getOffset(), - mContext->getRenderer()->getFormat(CLImageFormatToAngleFormat(getFormat())), viewOut); + mContext->getRenderer()->getFormat(CLImageFormatToAngleFormat(getFormat())), viewOut, + nullptr); } } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLMemoryVk.h b/src/libANGLE/renderer/vulkan/CLMemoryVk.h index 6f4ea5b02d0..ed5c478de67 100644 --- a/src/libANGLE/renderer/vulkan/CLMemoryVk.h +++ b/src/libANGLE/renderer/vulkan/CLMemoryVk.h @@ -11,6 +11,7 @@ #include "common/PackedCLEnums_autogen.h" #include "common/SimpleMutex.h" +#include "libANGLE/cl_types.h" #include "libANGLE/renderer/vulkan/cl_types.h" #include "libANGLE/renderer/vulkan/vk_helpers.h" @@ -50,7 +51,7 @@ class CLMemoryVk : public CLMemoryImpl CLMemoryImpl::Ptr *subBufferOut) override; angle::Result map(uint8_t *&ptrOut, size_t offset = 0); - void unmap() { unmapImpl(); } + void unmap() { unmapBufferHelper(); } VkBufferUsageFlags getVkUsageFlags(); VkMemoryPropertyFlags getVkMemPropertyFlags(); @@ -58,9 +59,9 @@ class CLMemoryVk : public CLMemoryImpl size_t getOffset() const { return mMemory.getOffset(); } cl::MemFlags getFlags() const { return mMemory.getFlags(); } cl::MemObjectType getType() const { return mMemory.getType(); } + void *getHostPtr() const { return mMemory.getHostPtr(); } angle::Result copyTo(void *ptr, size_t offset, size_t size); - angle::Result copyTo(CLMemoryVk *dst, size_t srcOffset, size_t dstOffset, size_t size); angle::Result copyFrom(const void *ptr, size_t offset, size_t size); bool isWritable() @@ -76,13 +77,14 @@ class CLMemoryVk : public CLMemoryImpl protected: CLMemoryVk(const cl::Memory &memory); - virtual angle::Result mapImpl() = 0; - virtual void unmapImpl() = 0; + virtual angle::Result mapBufferHelper(uint8_t *&ptrOut) = 0; + virtual angle::Result mapParentBufferHelper(uint8_t *&ptrOut) = 0; + virtual void unmapBufferHelper() = 0; CLContextVk *mContext; vk::Renderer *mRenderer; vk::Allocation mAllocation; - angle::SimpleMutex mMapLock; + angle::SimpleMutex mMutex; uint8_t *mMappedMemory; uint32_t mMapCount; CLMemoryVk *mParent; @@ -98,14 +100,17 @@ class CLBufferVk : public CLMemoryVk CLBufferVk *getParent() { return static_cast(mParent); } const cl::Buffer &getFrontendObject() { return reinterpret_cast(mMemory); } + bool supportsZeroCopy() const; + bool isHostPtrAligned() const; + angle::Result create(void *hostPtr); - angle::Result createStagingBuffer(size_t size); + angle::Result copyToWithPitch(void *hostPtr, size_t srcOffset, size_t size, size_t rowPitch, size_t slicePitch, - cl::Coordinate region, + cl::Extents region, const size_t elementSize); angle::Result fillWithPattern(const void *pattern, @@ -120,24 +125,47 @@ class CLBufferVk : public CLMemoryVk bool isSubBuffer() const { return mParent != nullptr; } angle::Result setRect(const void *data, - const cl::BufferRect &srcRect, + const cl::BufferRect &dataRect, const cl::BufferRect &bufferRect); - angle::Result getRect(const cl::BufferRect &srcRect, - const cl::BufferRect &outRect, + angle::Result getRect(const cl::BufferRect &bufferRect, + const cl::BufferRect &dataRect, void *outData); - std::vector rectCopyRegions(const cl::BufferRect &bufferRect); bool isCurrentlyInUse() const override; size_t getSize() const override { return mMemory.getSize(); } - private: - angle::Result mapImpl() override; - void unmapImpl() override; + // syncHost routines for handling any needed host side updates + enum class SyncHostDirection + { + ToHost, + FromHost + }; + angle::Result syncHost(CLBufferVk::SyncHostDirection direction); + angle::Result syncHost(CLBufferVk::SyncHostDirection direction, cl::BufferRect hostRect); + private: + angle::Result mapBufferHelper(uint8_t *&ptrOut) override; + angle::Result mapParentBufferHelper(uint8_t *&ptrOut) override; + void unmapBufferHelper() override; angle::Result setDataImpl(const uint8_t *data, size_t size, size_t offset); + angle::Result createWithProperties(); + + enum class UpdateRectOperation + { + Read, + Write + }; + angle::Result updateRect(UpdateRectOperation readWriteOp, + void *data, + const cl::BufferRect &dataRect, + const cl::BufferRect &bufferRect); vk::BufferHelper mBuffer; VkBufferCreateInfo mDefaultBufferCreateInfo; + + // allows access to private buffer routines in the case where the image's parent memory is a + // buffer type + friend class CLImageVk; }; class CLImageVk : public CLMemoryVk @@ -146,8 +174,11 @@ class CLImageVk : public CLMemoryVk CLImageVk(const cl::Image &image); ~CLImageVk() override; - vk::ImageHelper &getImage() { return mImage; } - vk::BufferHelper &getStagingBuffer() { return mStagingBuffer; } + vk::ImageHelper &getImage() + { + ASSERT(mImage.valid()); + return mImage; + } const cl::Image &getFrontendObject() const { return reinterpret_cast(mMemory); @@ -161,6 +192,7 @@ class CLImageVk : public CLMemoryVk size_t getSlicePitch() const; cl::MemObjectType getParentType() const; + template T *getParent() const; @@ -170,29 +202,26 @@ class CLImageVk : public CLMemoryVk bool isCurrentlyInUse() const override; bool containsHostMemExtension(); - angle::Result createStagingBuffer(size_t size); + angle::Result getOrCreateStagingBuffer(CLBufferVk **clBufferOut); angle::Result copyStagingFrom(void *ptr, size_t offset, size_t size); angle::Result copyStagingTo(void *ptr, size_t offset, size_t size); angle::Result copyStagingToFromWithPitch(void *ptr, - const cl::Coordinate ®ion, + const cl::Extents ®ion, const size_t rowPitch, const size_t slicePitch, StagingBufferCopyDirection copyStagingTo); VkImageUsageFlags getVkImageUsageFlags(); VkImageType getVkImageType(const cl::ImageDescriptor &desc); - bool isStagingBufferInitialized() { return mStagingBufferInitialized; } - cl::Extents getImageExtent() { return mExtent; } - uint8_t *getMappedPtr() { return mMappedMemory; } + cl::Extents getImageExtent() const { return mExtent; } vk::ImageView &getImageView() { return mImageView; } void packPixels(const void *fillColor, PixelColor *packedColor); - void fillImageWithColor(const cl::MemOffsets &origin, - const cl::Coordinate ®ion, - uint8_t *imagePtr, - PixelColor *packedColor); - cl::Extents getExtentForCopy(const cl::Coordinate ®ion); - cl::Offset getOffsetForCopy(const cl::MemOffsets &origin); - VkImageSubresourceLayers getSubresourceLayersForCopy(const cl::MemOffsets &origin, - const cl::Coordinate ®ion, + angle::Result fillImageWithColor(const cl::Offset &origin, + const cl::Extents ®ion, + PixelColor *packedColor); + cl::Offset getOffsetForCopy(const cl::Offset &origin); + cl::Extents getExtentForCopy(const cl::Extents ®ion); + VkImageSubresourceLayers getSubresourceLayersForCopy(const cl::Offset &origin, + const cl::Extents ®ion, cl::MemObjectType copyToType, ImageCopyWith imageCopy); @@ -200,18 +229,18 @@ class CLImageVk : public CLMemoryVk private: angle::Result initImageViewImpl(); - - angle::Result mapImpl() override; - void unmapImpl() override; + angle::Result mapBufferHelper(uint8_t *&ptrOut) override; + angle::Result mapParentBufferHelper(uint8_t *&ptrOut) override; + void unmapBufferHelper() override; angle::Result setDataImpl(const uint8_t *data, size_t size, size_t offset); size_t calculateRowPitch(); size_t calculateSlicePitch(size_t imageRowPitch); vk::ImageHelper mImage; - vk::BufferHelper mStagingBuffer; cl::Extents mExtent; angle::FormatID mAngleFormat; - bool mStagingBufferInitialized; + + cl::Buffer *mStagingBuffer; vk::ImageView mImageView; VkImageViewType mImageViewType; diff --git a/src/libANGLE/renderer/vulkan/CLPlatformVk.cpp b/src/libANGLE/renderer/vulkan/CLPlatformVk.cpp index 305c50b44fe..bfe30e866a3 100644 --- a/src/libANGLE/renderer/vulkan/CLPlatformVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLPlatformVk.cpp @@ -30,6 +30,12 @@ constexpr vk::UseDebugLayers kUseDebugLayers = vk::UseDebugLayers::YesIfAvailabl #else constexpr vk::UseDebugLayers kUseDebugLayers = vk::UseDebugLayers::No; #endif + +#if defined(ANGLE_OPENCL_COMPUTE_ONLY_PIPE) +constexpr bool kUseComputeOnlyQueue = true; +#else +constexpr bool kUseComputeOnlyQueue = false; +#endif } // namespace angle::Result CLPlatformVk::initBackendRenderer() @@ -72,7 +78,54 @@ CLPlatformImpl::Info CLPlatformVk::createInfo() const info.hostTimerRes = 0u; info.version = GetVersion(); + // check all devices to see which device-extensions can be promoted to platform-extensions + bool platformSupportsBaseInt64Atomics = true; + bool platformSupportsExtendedInt64Atomics = true; + bool platformSupportsDepthImages = true; + CLExtensions::ExternalMemoryHandleBitset supportedHandles; + supportedHandles.set(); // set support for all types initially + for (const cl::DevicePtr &platformDevice : mPlatform.getDevices()) + { + platformSupportsBaseInt64Atomics &= platformDevice->getInfo().khrInt64BaseAtomics; + platformSupportsExtendedInt64Atomics &= platformDevice->getInfo().khrInt64ExtendedAtomics; + platformSupportsDepthImages &= platformDevice->getInfo().khrDepthImages; + supportedHandles &= platformDevice->getInfo().externalMemoryHandleSupport; + } + + if (info.populateSupportedExternalMemoryHandleTypes(supportedHandles)) + { + extList.push_back(cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_external_memory"}); + + // cl_arm_import_memory is layered on top of cl_arm_import_memory + bool reportBaseArmImportMemString = false; + if (supportedHandles.test(cl::ExternalMemoryHandle::DmaBuf)) + { + extList.push_back( + cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_arm_import_memory_dma_buf"}); + reportBaseArmImportMemString = true; + } + if (reportBaseArmImportMemString) + { + extList.push_back(cl_name_version{CL_MAKE_VERSION(1, 11, 0), "cl_arm_import_memory"}); + } + } + if (platformSupportsBaseInt64Atomics) + { + extList.push_back(cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_int64_base_atomics"}); + } + if (platformSupportsExtendedInt64Atomics) + { + extList.push_back( + cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_int64_extended_atomics"}); + } + if (platformSupportsDepthImages) + { + extList.push_back( + cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_depth_images"}); + } + info.initializeVersionedExtensions(std::move(extList)); + return info; } @@ -124,31 +177,6 @@ angle::Result CLPlatformVk::createContextFromType(cl::Context &context, bool userSync, CLContextImpl::Ptr *contextOut) { - const VkPhysicalDeviceType &vkPhysicalDeviceType = - getRenderer()->getPhysicalDeviceProperties().deviceType; - - if (deviceType.intersects(CL_DEVICE_TYPE_CPU) && - vkPhysicalDeviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) - { - ANGLE_CL_RETURN_ERROR(CL_DEVICE_NOT_FOUND); - } - else if (deviceType.intersects(CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_DEFAULT)) - { - switch (vkPhysicalDeviceType) - { - case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: - case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: - case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: - break; - default: - ANGLE_CL_RETURN_ERROR(CL_DEVICE_NOT_FOUND); - } - } - else - { - ANGLE_CL_RETURN_ERROR(CL_DEVICE_NOT_FOUND); - } - cl::DevicePtrs devices; for (const auto &platformDevice : mPlatform.getDevices()) { @@ -218,27 +246,14 @@ void CLPlatformVk::handleError(VkResult result, angle::NativeWindowSystem CLPlatformVk::getWindowSystem() { -#if defined(ANGLE_ENABLE_VULKAN) -# if defined(ANGLE_PLATFORM_LINUX) -# if defined(ANGLE_USE_GBM) - return angle::NativeWindowSystem::Gbm; -# elif defined(ANGLE_USE_X11) - return angle::NativeWindowSystem::X11; -# elif defined(ANGLE_USE_WAYLAND) - return angle::NativeWindowSystem::Wayland; -# else - handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__); - return angle::NativeWindowSystem::Other; -# endif -# elif defined(ANGLE_PLATFORM_ANDROID) - return angle::NativeWindowSystem::Other; -# else - handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__); - return angle::NativeWindowSystem::Other; -# endif -#elif - UNREACHABLE(); -#endif + if (kUseComputeOnlyQueue) + { + return angle::NativeWindowSystem::NullCompute; + } + else + { + return angle::NativeWindowSystem::Other; + } } const char *CLPlatformVk::getWSIExtension() diff --git a/src/libANGLE/renderer/vulkan/CLPlatformVk.h b/src/libANGLE/renderer/vulkan/CLPlatformVk.h index 9e9350ce999..53838e3f478 100644 --- a/src/libANGLE/renderer/vulkan/CLPlatformVk.h +++ b/src/libANGLE/renderer/vulkan/CLPlatformVk.h @@ -62,6 +62,7 @@ class CLPlatformVk : public CLPlatformImpl, public vk::ErrorContext, public vk:: std::shared_ptr postMultiThreadWorkerTask( const std::shared_ptr &task) override; void notifyDeviceLost() override; + GlobalOps::Api getFrontendApi() const override { return GlobalOps::Api::OpenCL; } private: explicit CLPlatformVk(const cl::Platform &platform); diff --git a/src/libANGLE/renderer/vulkan/CLProgramVk.cpp b/src/libANGLE/renderer/vulkan/CLProgramVk.cpp index 170f8cb57d7..65e01eac87a 100644 --- a/src/libANGLE/renderer/vulkan/CLProgramVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLProgramVk.cpp @@ -4,8 +4,14 @@ // found in the LICENSE file. // // CLProgramVk.cpp: Implements the class methods for CLProgramVk. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/vulkan/CLProgramVk.h" +#include "libANGLE/CLBuffer.h" #include "libANGLE/renderer/vulkan/CLContextVk.h" #include "libANGLE/renderer/vulkan/clspv_utils.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h" @@ -247,6 +253,35 @@ spv_result_t ParseReflection(CLProgramVk::SpvReflectionData &reflectionData, reflectionData.specConstantsUsed[SpecConstantType::GlobalOffsetY] = true; reflectionData.specConstantsUsed[SpecConstantType::GlobalOffsetZ] = true; break; + case NonSemanticClspvReflectionConstantDataPointerPushConstant: + { + std::string data = reflectionData.spvStrLookup[spvInstr.words[7]]; + + // Data must be an OpString that encodes the hexbytes of the constant data. + // https://github.khronos.org/SPIRV-Registry/nonsemantic/NonSemantic.ClspvReflection.html + // Each byte of binary data is represented by two hexadecimal digits, so the + // number of digits must be even + ASSERT(data.size() % 2 == 0); + + reflectionData.constantDataBufferInfo.bufferData = + angle::HexStringToUintVector(data); + + uint32_t set = 0; + uint32_t binding = 0; + uint32_t pcOffset = 0; + pcOffset = reflectionData.spvIntLookup[spvInstr.words[5]]; + + // Add push constant + reflectionData.pushConstants[spvInstr.words[4]] = { + .stageFlags = 0, .offset = pcOffset, .size = CHAR_BIT}; + + // Set constant data buffer + reflectionData.constantDataBufferInfo.set = set; + reflectionData.constantDataBufferInfo.binding = binding; + reflectionData.constantDataBufferInfo.pcOffset = pcOffset; + + break; + } case NonSemanticClspvReflectionPrintfInfo: { // Info on the format string used in the builtin printf call in kernel @@ -275,11 +310,10 @@ spv_result_t ParseReflection(CLProgramVk::SpvReflectionData &reflectionData, } case NonSemanticClspvReflectionPrintfBufferPointerPushConstant: { - ERR() << "Shouldn't be here. Support of printf builtin function is enabled " - "through " - "PrintfBufferStorageBuffer. Check optins passed down to clspv"; - UNREACHABLE(); - return SPV_UNSUPPORTED; + uint32_t pcOffset = reflectionData.spvIntLookup[spvInstr.words[5]]; + reflectionData.pushConstants[spvInstr.words[4]] = { + .stageFlags = 0, .offset = pcOffset, .size = CHAR_BIT}; + break; } case NonSemanticClspvReflectionNormalizedSamplerMaskPushConstant: case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant: @@ -293,6 +327,22 @@ spv_result_t ParseReflection(CLProgramVk::SpvReflectionData &reflectionData, {.pcRange = pcRange, .ordinal = ordinal}); break; } + case NonSemanticClspvReflectionLiteralSampler: + { + uint32_t descriptorSet = reflectionData.spvIntLookup[spvInstr.words[5]]; + ASSERT(descriptorSet < static_cast(DescriptorSetIndex::EnumCount)); + uint32_t binding = reflectionData.spvIntLookup[spvInstr.words[6]]; + uint32_t mask = reflectionData.spvIntLookup[spvInstr.words[7]]; + cl_bool normalizedCoords = clspv_cl::IsNormalizedCoords(mask); + cl::AddressingMode addressingMode = clspv_cl::GetAddressingMode(mask); + cl::FilterMode filterMode = clspv_cl::GetFilterMode(mask); + reflectionData.literalSamplers.push_back({.descriptorSet = descriptorSet, + .binding = binding, + .normalizedCoords = normalizedCoords, + .addressingMode = addressingMode, + .filterMode = filterMode}); + break; + } default: break; } @@ -329,6 +379,11 @@ std::string ProcessBuildOptions(const std::vector &optionTokens, processedOptions += " --output-format=bc"; continue; } + else if (optionToken == "-cl-std=CL2.0") + { + processedOptions += " -cl-std=CL2.0 -inline-entry-points"; + continue; + } processedOptions += " " + optionToken; } @@ -364,7 +419,8 @@ void CLAsyncBuildTask::operator()() CLProgramVk::CLProgramVk(const cl::Program &program) : CLProgramImpl(program), mContext(&program.getContext().getImpl()), - mAsyncBuildEvent(std::make_shared()) + mAsyncBuildEvent(std::make_shared()), + mModuleConstantDataBuffer(nullptr) {} angle::Result CLProgramVk::init() @@ -480,7 +536,13 @@ angle::Result CLProgramVk::init(const size_t *lengths, return angle::Result::Continue; } -CLProgramVk::~CLProgramVk() {} +CLProgramVk::~CLProgramVk() +{ + if (mModuleConstantDataBuffer) + { + mModuleConstantDataBuffer.release(); + } +} angle::Result CLProgramVk::build(const cl::DevicePtrs &devices, const char *options, @@ -545,7 +607,7 @@ angle::Result CLProgramVk::compile(const cl::DevicePtrs &devices, ERR() << "Failed to create output path(s) for header(s)!"; ANGLE_CL_RETURN_ERROR(CL_INVALID_OPERATION); } - writeFile(headerFilePath.c_str(), inputHeaderSrc.data(), inputHeaderSrc.size()); + writeFile(headerFilePath.c_str(), inputHeaderSrc); } setBuildStatus(devicePtrs, CL_BUILD_IN_PROGRESS); @@ -816,6 +878,30 @@ const CLProgramVk::DeviceProgramData *CLProgramVk::getDeviceProgramData( return nullptr; } +cl::MemoryPtr CLProgramVk::getOrCreateModuleConstantDataBuffer(const std::string &kernelName) +{ + const DeviceProgramData *devProgram = getDeviceProgramData(kernelName.c_str()); + ASSERT(devProgram); + const std::vector &initData = + devProgram->reflectionData.constantDataBufferInfo.bufferData; + void *initDataPtr = reinterpret_cast(const_cast(initData.data())); + + if (!mModuleConstantDataBuffer) + { + mModuleConstantDataBuffer = + cl::MemoryPtr(cl::Buffer::Cast(this->mContext->getFrontendObject().createBuffer( + nullptr, cl::MemFlags(CL_MEM_USE_HOST_PTR), initData.size(), initDataPtr))); + // Release initialization reference, lifetime controlled by RefPointer. + mModuleConstantDataBuffer->release(); + } + else + { + // reading that this buffer is already present and is sufficient to hold initData + ASSERT(mModuleConstantDataBuffer->getSize() == initData.size()); + } + return mModuleConstantDataBuffer; +} + bool CLProgramVk::buildInternal(const cl::DevicePtrs &devices, std::string options, std::string internalOptions, diff --git a/src/libANGLE/renderer/vulkan/CLProgramVk.h b/src/libANGLE/renderer/vulkan/CLProgramVk.h index a3ee77481da..83ddd47be16 100644 --- a/src/libANGLE/renderer/vulkan/CLProgramVk.h +++ b/src/libANGLE/renderer/vulkan/CLProgramVk.h @@ -13,6 +13,7 @@ #include "common/SimpleMutex.h" #include "common/hash_containers.h" +#include "libANGLE/CLSampler.h" #include "libANGLE/renderer/vulkan/CLContextVk.h" #include "libANGLE/renderer/vulkan/CLKernelVk.h" #include "libANGLE/renderer/vulkan/cl_types.h" @@ -61,6 +62,8 @@ class CLProgramVk : public CLProgramImpl angle::HashSet kernelIDs; ClspvPrintfBufferStorage printfBufferStorage; angle::HashMap printfInfoMap; + std::vector literalSamplers; + ClspvConstantDataBufferInfo constantDataBufferInfo; }; // Output binary structure (for CL_PROGRAM_BINARIES query) @@ -331,6 +334,7 @@ class CLProgramVk : public CLProgramImpl const DeviceProgramData *getDeviceProgramData(const _cl_device_id *device) const; CLPlatformVk *getPlatform() { return mContext->getPlatform(); } const vk::ShaderModulePtr &getShaderModule() const { return mShader; } + cl::MemoryPtr getOrCreateModuleConstantDataBuffer(const std::string &kernelName); bool buildInternal(const cl::DevicePtrs &devices, std::string options, @@ -351,8 +355,8 @@ class CLProgramVk : public CLProgramImpl vk::ShaderModulePtr mShader; DevicePrograms mAssociatedDevicePrograms; angle::SimpleMutex mProgramMutex; - std::shared_ptr mAsyncBuildEvent; + cl::MemoryPtr mModuleConstantDataBuffer; }; class CLAsyncBuildTask : public angle::Closure diff --git a/src/libANGLE/renderer/vulkan/CLSamplerVk.cpp b/src/libANGLE/renderer/vulkan/CLSamplerVk.cpp index bb2a67e5eb9..4feea0a7802 100644 --- a/src/libANGLE/renderer/vulkan/CLSamplerVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLSamplerVk.cpp @@ -175,7 +175,7 @@ angle::Result CLSamplerVk::create() angle::Result CLSamplerVk::createNormalized() { - if (mSamplerHelperNormalized.valid()) + if (!mSamplerHelperNormalized.valid()) { mDefaultSamplerCreateInfo.unnormalizedCoordinates = false; ANGLE_TRY(mSamplerHelperNormalized.init(mContext, mDefaultSamplerCreateInfo)); diff --git a/src/libANGLE/renderer/vulkan/CommandQueue.cpp b/src/libANGLE/renderer/vulkan/CommandQueue.cpp index c21a3f96439..5164f8cf191 100644 --- a/src/libANGLE/renderer/vulkan/CommandQueue.cpp +++ b/src/libANGLE/renderer/vulkan/CommandQueue.cpp @@ -8,9 +8,11 @@ // #include "libANGLE/renderer/vulkan/CommandQueue.h" +#include #include "common/system_utils.h" #include "libANGLE/renderer/vulkan/SyncVk.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" +#include "vulkan/vulkan_core.h" namespace rx { @@ -109,6 +111,7 @@ void RecyclableFence::destroy(VkDevice device) { if (mRecycler != nullptr) { + mFence.reset(device); mRecycler->recycle(std::move(mFence)); } else @@ -134,7 +137,6 @@ void FenceRecycler::fetch(VkDevice device, Fence *fenceOut) if (!mRecycler.empty()) { mRecycler.fetch(fenceOut); - fenceOut->reset(device); } } @@ -168,7 +170,7 @@ CommandBatch &CommandBatch::operator=(CommandBatch &&other) return *this; } -void CommandBatch::destroy(VkDevice device) +ANGLE_INLINE void CommandBatch::destroy(VkDevice device) { if (mPrimaryCommands.valid()) { @@ -185,13 +187,14 @@ void CommandBatch::destroy(VkDevice device) // Do not clean other members to catch invalid reuse attempt with ASSERTs. } -angle::Result CommandBatch::release(ErrorContext *context) +ANGLE_INLINE angle::Result CommandBatch::release(ErrorContext *context, + WhenToResetCommandBuffer whenToReset) { if (mPrimaryCommands.valid()) { ASSERT(mCommandPoolAccess != nullptr); ANGLE_TRY(mCommandPoolAccess->collectPrimaryCommandBuffer(context, mProtectionType, - &mPrimaryCommands)); + &mPrimaryCommands, whenToReset)); } mSecondaryCommands.releaseCommandBuffers(); mFence.reset(); @@ -200,22 +203,22 @@ angle::Result CommandBatch::release(ErrorContext *context) return angle::Result::Continue; } -void CommandBatch::setQueueSerial(const QueueSerial &serial) +ANGLE_INLINE void CommandBatch::setQueueSerial(const QueueSerial &serial) { ASSERT(serial.valid()); ASSERT(!mQueueSerial.valid()); mQueueSerial = serial; } -void CommandBatch::setProtectionType(ProtectionType protectionType) +ANGLE_INLINE void CommandBatch::setProtectionType(ProtectionType protectionType) { ASSERT(protectionType != ProtectionType::InvalidEnum); ASSERT(mProtectionType == ProtectionType::InvalidEnum); mProtectionType = protectionType; } -void CommandBatch::setPrimaryCommands(PrimaryCommandBuffer &&primaryCommands, - CommandPoolAccess *commandPoolAccess) +ANGLE_INLINE void CommandBatch::setPrimaryCommands(PrimaryCommandBuffer &&primaryCommands, + CommandPoolAccess *commandPoolAccess) { // primaryCommands is optional. ASSERT(!(primaryCommands.valid() && commandPoolAccess == nullptr)); @@ -225,14 +228,15 @@ void CommandBatch::setPrimaryCommands(PrimaryCommandBuffer &&primaryCommands, mCommandPoolAccess = commandPoolAccess; } -void CommandBatch::setSecondaryCommands(SecondaryCommandBufferCollector &&secondaryCommands) +ANGLE_INLINE void CommandBatch::setSecondaryCommands( + SecondaryCommandBufferCollector &&secondaryCommands) { // secondaryCommands is optional. ASSERT(mSecondaryCommands.empty()); mSecondaryCommands = std::move(secondaryCommands); } -VkResult CommandBatch::initFence(VkDevice device, FenceRecycler *recycler) +ANGLE_INLINE VkResult CommandBatch::initFence(VkDevice device, FenceRecycler *recycler) { ASSERT(!hasFence()); auto fence = SharedFence::MakeShared(device); @@ -245,56 +249,56 @@ VkResult CommandBatch::initFence(VkDevice device, FenceRecycler *recycler) return result; } -void CommandBatch::setExternalFence(SharedExternalFence &&externalFence) +ANGLE_INLINE void CommandBatch::setExternalFence(SharedExternalFence &&externalFence) { - ASSERT(!hasFence()); + ASSERT(!mExternalFence); mExternalFence = std::move(externalFence); } -const QueueSerial &CommandBatch::getQueueSerial() const +ANGLE_INLINE const QueueSerial &CommandBatch::getQueueSerial() const { ASSERT(mQueueSerial.valid()); return mQueueSerial; } -const PrimaryCommandBuffer &CommandBatch::getPrimaryCommands() const +ANGLE_INLINE const PrimaryCommandBuffer &CommandBatch::getPrimaryCommands() const { return mPrimaryCommands; } -const SharedExternalFence &CommandBatch::getExternalFence() +ANGLE_INLINE const SharedExternalFence &CommandBatch::getExternalFence() { return mExternalFence; } -bool CommandBatch::hasFence() const +ANGLE_INLINE bool CommandBatch::hasFence() const { - ASSERT(!mExternalFence || !mFence); ASSERT(!mFence || mFence->valid()); return mFence || mExternalFence; } -VkFence CommandBatch::getFenceHandle() const +ANGLE_INLINE VkFence CommandBatch::getFenceHandle() const { ASSERT(hasFence()); return mFence ? mFence->get().getHandle() : mExternalFence->getHandle(); } -VkResult CommandBatch::getFenceStatus(VkDevice device) const +ANGLE_INLINE VkResult CommandBatch::getFenceStatus(VkDevice device) const { ASSERT(hasFence()); return mFence ? mFence->get().getStatus(device) : mExternalFence->getStatus(device); } -VkResult CommandBatch::waitFence(VkDevice device, uint64_t timeout) const +ANGLE_INLINE VkResult CommandBatch::waitFence(VkDevice device, uint64_t timeout) const { ASSERT(hasFence()); return mFence ? mFence->get().wait(device, timeout) : mExternalFence->wait(device, timeout); } -VkResult CommandBatch::waitFenceUnlocked(VkDevice device, - uint64_t timeout, - std::unique_lock *lock) const +ANGLE_INLINE VkResult +CommandBatch::waitFenceUnlocked(VkDevice device, + uint64_t timeout, + std::unique_lock *lock) const { ASSERT(hasFence()); VkResult status; @@ -394,6 +398,9 @@ void CleanUpThread::processTasks() angle::Result CleanUpThread::processTasksImpl(bool *exitThread) { + WhenToResetCommandBuffer whenToReset = mRenderer->getFeatures().asyncCommandBufferReset.enabled + ? WhenToResetCommandBuffer::Now + : WhenToResetCommandBuffer::Defer; while (true) { std::unique_lock lock(mMutex); @@ -412,10 +419,10 @@ angle::Result CleanUpThread::processTasksImpl(bool *exitThread) ANGLE_TRY(mCommandQueue->checkCompletedCommands(this)); // Reset command buffer and clean up garbage - if (mRenderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled() && + if (mRenderer->getFeatures().asyncGarbageCleanup.enabled && mCommandQueue->hasFinishedCommands()) { - ANGLE_TRY(mCommandQueue->releaseFinishedCommands(this)); + ANGLE_TRY(mCommandQueue->releaseFinishedCommands(this, whenToReset)); } mRenderer->cleanupGarbage(nullptr); } @@ -442,9 +449,9 @@ void CleanUpThread::destroy(ErrorContext *context) } // Perform any lingering clean up right away. - if (mRenderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled()) + if (mRenderer->getFeatures().asyncGarbageCleanup.enabled) { - (void)mCommandQueue->releaseFinishedCommands(context); + (void)mCommandQueue->releaseFinishedCommands(context, WhenToResetCommandBuffer::Now); mRenderer->cleanupGarbage(nullptr); } @@ -454,152 +461,140 @@ void CleanUpThread::destroy(ErrorContext *context) } } -CommandPoolAccess::CommandPoolAccess() = default; -CommandPoolAccess::~CommandPoolAccess() = default; +// CommandsState implementation. +CommandsState::CommandsState(Renderer *renderer, + ProtectionType protectionType, + egl::ContextPriority priority) + : mCmdPoolMutex(renderer->getCommandPoolAccess().mCmdPoolMutex), + mProtectionType(protectionType), + mPriority(priority) +{} -// CommandPoolAccess public API implementation. These must be thread safe and never called from -// CommandPoolAccess class itself. -angle::Result CommandPoolAccess::initCommandPool(ErrorContext *context, - ProtectionType protectionType, - const uint32_t queueFamilyIndex) +CommandsState::~CommandsState() +{ + ASSERT(mWaitSemaphores.empty()); + ASSERT(mWaitSemaphoreStageMasks.empty()); + ASSERT(!mPrimaryCommands.valid()); +} + +void CommandsState::destroy(VkDevice device) { std::lock_guard lock(mCmdPoolMutex); - PersistentCommandPool &commandPool = mPrimaryCommandPoolMap[protectionType]; - return commandPool.init(context, protectionType, queueFamilyIndex); + mWaitSemaphores.clear(); + mWaitSemaphoreStageMasks.clear(); + mPrimaryCommands.destroy(device); + mSecondaryCommands.releaseCommandBuffers(); } -void CommandPoolAccess::destroy(VkDevice device) +angle::Result CommandsState::getCommandsAndWaitSemaphores( + ErrorContext *context, + CommandPoolAccess *commandPoolAccess, + CommandBatch *batch, + std::vector *waitSemaphoresOut, + std::vector *waitSemaphoreStageMasksOut) { std::lock_guard lock(mCmdPoolMutex); - for (auto &protectionMap : mCommandsStateMap) - { - for (CommandsState &state : protectionMap) - { - state.waitSemaphores.clear(); - state.waitSemaphoreStageMasks.clear(); - state.primaryCommands.destroy(device); - state.secondaryCommands.releaseCommandBuffers(); - } - } - for (PersistentCommandPool &commandPool : mPrimaryCommandPoolMap) + ASSERT(mPrimaryCommands.valid() || mSecondaryCommands.empty()); + + // Store the primary CommandBuffer and the reference to CommandPoolAccess in the in-flight list. + if (mPrimaryCommands.valid()) { - commandPool.destroy(device); + ANGLE_VK_TRY(context, mPrimaryCommands.end()); } -} -void CommandPoolAccess::destroyPrimaryCommandBuffer(VkDevice device, - PrimaryCommandBuffer *primaryCommands) const -{ - ASSERT(primaryCommands->valid()); + batch->setPrimaryCommands(std::move(mPrimaryCommands), commandPoolAccess); + // Store secondary Command Buffers. + batch->setSecondaryCommands(std::move(mSecondaryCommands)); - // Does not require a pool mutex lock. - primaryCommands->destroy(device); + // Store wait semaphores. + *waitSemaphoresOut = std::move(mWaitSemaphores); + *waitSemaphoreStageMasksOut = std::move(mWaitSemaphoreStageMasks); + + return angle::Result::Continue; } -angle::Result CommandPoolAccess::collectPrimaryCommandBuffer(ErrorContext *context, - const ProtectionType protectionType, - PrimaryCommandBuffer *primaryCommands) +angle::Result CommandsState::ensurePrimaryCommandBufferValidLocked(ErrorContext *context) { - ASSERT(primaryCommands->valid()); - std::lock_guard lock(mCmdPoolMutex); + Renderer *renderer = context->getRenderer(); - PersistentCommandPool &commandPool = mPrimaryCommandPoolMap[protectionType]; - ANGLE_TRY(commandPool.collect(context, std::move(*primaryCommands))); + if (mPrimaryCommands.valid()) + { + return angle::Result::Continue; + } + else + { + ANGLE_TRY(renderer->getCommandPoolAccess().allocatePrimaryCommandBufferLocked( + context, mProtectionType, &mPrimaryCommands)); + + VkCommandBufferBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + beginInfo.pInheritanceInfo = nullptr; + ANGLE_VK_TRY(context, mPrimaryCommands.begin(beginInfo)); + } return angle::Result::Continue; } -angle::Result CommandPoolAccess::flushOutsideRPCommands( - Context *context, - ProtectionType protectionType, - egl::ContextPriority priority, - OutsideRenderPassCommandBufferHelper **outsideRPCommands) +angle::Result CommandsState::insertSubmitDebugMarker(ErrorContext *context, + QueueSubmitReason reason) { + Renderer *renderer = context->getRenderer(); + if (!renderer->enableDebugUtils() && !renderer->angleDebuggerMode()) + { + return angle::Result::Continue; + } + std::lock_guard lock(mCmdPoolMutex); - ANGLE_TRY(ensurePrimaryCommandBufferValidLocked(context, protectionType, priority)); - CommandsState &state = mCommandsStateMap[priority][protectionType]; - return (*outsideRPCommands)->flushToPrimary(context, &state); + ANGLE_TRY(ensurePrimaryCommandBufferValidLocked(context)); + + renderer->insertSubmitDebugMarkerInCommandBuffer(mPrimaryCommands, reason); + return angle::Result::Continue; } -angle::Result CommandPoolAccess::flushRenderPassCommands( - Context *context, - const ProtectionType &protectionType, - const egl::ContextPriority &priority, - const RenderPass &renderPass, - VkFramebuffer framebufferOverride, - RenderPassCommandBufferHelper **renderPassCommands) +// CommandPoolAccess public API implementation. These must be thread safe and never called from +// CommandPoolAccess class itself. +CommandPoolAccess::CommandPoolAccess() = default; +CommandPoolAccess::~CommandPoolAccess() = default; + +angle::Result CommandPoolAccess::initCommandPool(ErrorContext *context, + ProtectionType protectionType, + const uint32_t queueFamilyIndex) { std::lock_guard lock(mCmdPoolMutex); - ANGLE_TRY(ensurePrimaryCommandBufferValidLocked(context, protectionType, priority)); - CommandsState &state = mCommandsStateMap[priority][protectionType]; - return (*renderPassCommands)->flushToPrimary(context, &state, renderPass, framebufferOverride); + PersistentCommandPool &commandPool = mPrimaryCommandPoolMap[protectionType]; + return commandPool.init(context, protectionType, queueFamilyIndex); } -void CommandPoolAccess::flushWaitSemaphores( - ProtectionType protectionType, - egl::ContextPriority priority, - std::vector &&waitSemaphores, - std::vector &&waitSemaphoreStageMasks) +void CommandPoolAccess::destroy(VkDevice device) { - ASSERT(!waitSemaphores.empty()); - ASSERT(waitSemaphores.size() == waitSemaphoreStageMasks.size()); std::lock_guard lock(mCmdPoolMutex); + for (PersistentCommandPool &commandPool : mPrimaryCommandPoolMap) + { + commandPool.destroy(device); + } +} - CommandsState &state = mCommandsStateMap[priority][protectionType]; - - state.waitSemaphores.insert(state.waitSemaphores.end(), waitSemaphores.begin(), - waitSemaphores.end()); - state.waitSemaphoreStageMasks.insert(state.waitSemaphoreStageMasks.end(), - waitSemaphoreStageMasks.begin(), - waitSemaphoreStageMasks.end()); +void CommandPoolAccess::destroyPrimaryCommandBuffer(VkDevice device, + PrimaryCommandBuffer *primaryCommands) const +{ + ASSERT(primaryCommands->valid()); - waitSemaphores.clear(); - waitSemaphoreStageMasks.clear(); + // Does not require a pool mutex lock. + primaryCommands->destroy(device); } -angle::Result CommandPoolAccess::getCommandsAndWaitSemaphores( - ErrorContext *context, - ProtectionType protectionType, - egl::ContextPriority priority, - CommandBatch *batchOut, - std::vector &&imagesToTransitionToForeign, - std::vector *waitSemaphoresOut, - std::vector *waitSemaphoreStageMasksOut) +angle::Result CommandPoolAccess::collectPrimaryCommandBuffer(ErrorContext *context, + const ProtectionType protectionType, + PrimaryCommandBuffer *primaryCommands, + WhenToResetCommandBuffer whenToReset) { + ASSERT(primaryCommands->valid()); std::lock_guard lock(mCmdPoolMutex); - CommandsState &state = mCommandsStateMap[priority][protectionType]; - ASSERT(state.primaryCommands.valid() || state.secondaryCommands.empty()); - - // If there are foreign images to transition, issue the barrier now. - if (!imagesToTransitionToForeign.empty()) - { - // It is possible for another thread to have made a submission just now, such that there is - // no primary command buffer anymore. In that case, one has to be allocated to hold the - // barriers. - ANGLE_TRY(ensurePrimaryCommandBufferValidLocked(context, protectionType, priority)); - - state.primaryCommands.pipelineBarrier( - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, static_cast(imagesToTransitionToForeign.size()), - imagesToTransitionToForeign.data()); - imagesToTransitionToForeign.clear(); - } - - // Store the primary CommandBuffer and the reference to CommandPoolAccess in the in-flight list. - if (state.primaryCommands.valid()) - { - ANGLE_VK_TRY(context, state.primaryCommands.end()); - } - batchOut->setPrimaryCommands(std::move(state.primaryCommands), this); - - // Store secondary Command Buffers. - batchOut->setSecondaryCommands(std::move(state.secondaryCommands)); - - // Store wait semaphores. - *waitSemaphoresOut = std::move(state.waitSemaphores); - *waitSemaphoreStageMasksOut = std::move(state.waitSemaphoreStageMasks); + PersistentCommandPool &commandPool = mPrimaryCommandPoolMap[protectionType]; + ANGLE_TRY(commandPool.collect(context, std::move(*primaryCommands), whenToReset)); return angle::Result::Continue; } @@ -842,14 +837,11 @@ bool CommandQueue::isBusy(Renderer *renderer) const return false; } -angle::Result CommandQueue::submitCommands( - ErrorContext *context, - ProtectionType protectionType, - egl::ContextPriority priority, - VkSemaphore signalSemaphore, - SharedExternalFence &&externalFence, - std::vector &&imagesToTransitionToForeign, - const QueueSerial &submitQueueSerial) +angle::Result CommandQueue::submitCommands(ErrorContext *context, + VkSemaphore signalSemaphore, + SharedExternalFence &&externalFence, + const QueueSerial &submitQueueSerial, + CommandsState &&commandsState) { ANGLE_TRACE_EVENT0("gpu.angle", "CommandQueue::submitCommands"); std::lock_guard lock(mQueueSubmitMutex); @@ -863,14 +855,13 @@ angle::Result CommandQueue::submitCommands( CommandBatch &batch = scopedBatch.get(); batch.setQueueSerial(submitQueueSerial); - batch.setProtectionType(protectionType); + batch.setProtectionType(commandsState.getProtectionType()); std::vector waitSemaphores; std::vector waitSemaphoreStageMasks; - ANGLE_TRY(mCommandPoolAccess.getCommandsAndWaitSemaphores( - context, protectionType, priority, &batch, std::move(imagesToTransitionToForeign), - &waitSemaphores, &waitSemaphoreStageMasks)); + ANGLE_TRY(commandsState.getCommandsAndWaitSemaphores( + context, &mCommandPoolAccess, &batch, &waitSemaphores, &waitSemaphoreStageMasks)); mPerfCounters.commandQueueWaitSemaphoresTotal += waitSemaphores.size(); @@ -887,7 +878,8 @@ angle::Result CommandQueue::submitCommands( waitSemaphoreStageMasks, signalSemaphore); // No need protected submission if no commands to submit. - if (protectionType == ProtectionType::Protected && batch.getPrimaryCommands().valid()) + if (commandsState.getProtectionType() == ProtectionType::Protected && + batch.getPrimaryCommands().valid()) { protectedSubmitInfo.sType = VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO; protectedSubmitInfo.pNext = nullptr; @@ -895,11 +887,15 @@ angle::Result CommandQueue::submitCommands( submitInfo.pNext = &protectedSubmitInfo; } - if (!externalFence) + // Initializing a fence is not required if the batch already has an external fence and does + // not need an extra fence after its submission. + const bool needsOwnedFence = + renderer->getFeatures().enableExtraSubmitFence.enabled || !externalFence; + if (needsOwnedFence) { - ANGLE_VK_TRY(context, batch.initFence(context->getDevice(), &mFenceRecycler)); + ANGLE_VK_TRY(context, batch.initFence(device, &mFenceRecycler)); } - else + if (externalFence) { batch.setExternalFence(std::move(externalFence)); } @@ -908,7 +904,8 @@ angle::Result CommandQueue::submitCommands( ++mPerfCounters.vkQueueSubmitCallsPerFrame; } - return queueSubmitLocked(context, priority, submitInfo, scopedBatch, submitQueueSerial); + return queueSubmitLocked(context, commandsState.getPriority(), submitInfo, scopedBatch, + submitQueueSerial); } angle::Result CommandQueue::queueSubmitOneOff(ErrorContext *context, @@ -989,7 +986,7 @@ angle::Result CommandQueue::queueSubmitLocked(ErrorContext *context, if (mNumAllCommands == mFinishedCommandBatches.capacity()) { std::lock_guard lock(mCmdReleaseMutex); - ANGLE_TRY(releaseFinishedCommandsLocked(context)); + ANGLE_TRY(releaseFinishedCommandsLocked(context, WhenToResetCommandBuffer::Now)); } // Assert will succeed since mNumAllCommands is incremented only in this method below. ASSERT(mNumAllCommands < mFinishedCommandBatches.capacity()); @@ -999,12 +996,21 @@ angle::Result CommandQueue::queueSubmitLocked(ErrorContext *context, CommandBatch &batch = commandBatch.get(); VkQueue queue = getQueue(contextPriority); - VkFence fence = batch.getFenceHandle(); - ASSERT(fence != VK_NULL_HANDLE); - ANGLE_VK_TRY(context, vkQueueSubmit(queue, 1, &submitInfo, fence)); - if (batch.getExternalFence()) { + VkFence externalFenceHandle = batch.getExternalFence()->getHandle(); + ASSERT(externalFenceHandle != VK_NULL_HANDLE); + ANGLE_VK_TRY(context, vkQueueSubmit(queue, 1, &submitInfo, externalFenceHandle)); + + // If enabled, there will be an extra fence submitted after the primary commands. + if (renderer->getFeatures().enableExtraSubmitFence.enabled) + { + VkFence extraSubmitFence = batch.getFenceHandle(); + VkSubmitInfo fenceSubmitInfo = {}; + fenceSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + ANGLE_VK_TRY(context, vkQueueSubmit(queue, 1, &fenceSubmitInfo, extraSubmitFence)); + } + // exportFd is exporting VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR type handle which // obeys copy semantics. This means that the fence must already be signaled or the work // to signal it is in the graphics pipeline at the time we export the fd. @@ -1012,10 +1018,16 @@ angle::Result CommandQueue::queueSubmitLocked(ErrorContext *context, ExternalFence &externalFence = *batch.getExternalFence(); VkFenceGetFdInfoKHR fenceGetFdInfo = {}; fenceGetFdInfo.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR; - fenceGetFdInfo.fence = externalFence.getHandle(); + fenceGetFdInfo.fence = externalFenceHandle; fenceGetFdInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR; externalFence.exportFd(renderer->getDevice(), fenceGetFdInfo); } + else + { + VkFence fence = batch.getFenceHandle(); + ASSERT(fence != VK_NULL_HANDLE); + ANGLE_VK_TRY(context, vkQueueSubmit(queue, 1, &submitInfo, fence)); + } } pushInFlightBatchLocked(commandBatch.release()); @@ -1050,14 +1062,14 @@ void CommandQueue::resetPerFramePerfCounters() angle::Result CommandQueue::releaseFinishedCommandsAndCleanupGarbage(ErrorContext *context) { Renderer *renderer = context->getRenderer(); - if (renderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled()) + if (renderer->getFeatures().asyncGarbageCleanup.enabled) { renderer->requestAsyncCommandsAndGarbageCleanup(context); } else { // Do immediate command buffer reset and garbage cleanup - ANGLE_TRY(releaseFinishedCommands(context)); + ANGLE_TRY(releaseFinishedCommands(context, WhenToResetCommandBuffer::Now)); renderer->cleanupGarbage(nullptr); } @@ -1152,7 +1164,8 @@ void CommandQueue::onCommandBatchFinishedLocked(CommandBatch &&batch) moveInFlightBatchToFinishedQueueLocked(std::move(batch)); } -angle::Result CommandQueue::releaseFinishedCommandsLocked(ErrorContext *context) +angle::Result CommandQueue::releaseFinishedCommandsLocked(ErrorContext *context, + WhenToResetCommandBuffer whenToReset) { ANGLE_TRACE_EVENT0("gpu.angle", "releaseFinishedCommandsLocked"); @@ -1160,7 +1173,7 @@ angle::Result CommandQueue::releaseFinishedCommandsLocked(ErrorContext *context) { CommandBatch &batch = mFinishedCommandBatches.front(); ASSERT(batch.getQueueSerial() <= mLastCompletedSerials); - ANGLE_TRY(batch.release(context)); + ANGLE_TRY(batch.release(context, whenToReset)); popFinishedBatchLocked(); } @@ -1216,12 +1229,14 @@ void CommandQueue::popInFlightBatchLocked() } // QueuePriorities: -constexpr float kVulkanQueuePriorityLow = 0.0; -constexpr float kVulkanQueuePriorityMedium = 0.4; -constexpr float kVulkanQueuePriorityHigh = 1.0; +constexpr float kVulkanQueuePriorityLow = 0.0; +constexpr float kVulkanQueuePriorityMedium = 0.4; +constexpr float kVulkanQueuePriorityHigh = 0.8; +constexpr float kVulkanQueuePriorityRealtime = 1.0; const float QueueFamily::kQueuePriorities[static_cast(egl::ContextPriority::EnumCount)] = - {kVulkanQueuePriorityMedium, kVulkanQueuePriorityHigh, kVulkanQueuePriorityLow}; + {kVulkanQueuePriorityMedium, kVulkanQueuePriorityHigh, kVulkanQueuePriorityRealtime, + kVulkanQueuePriorityLow}; DeviceQueueMap::~DeviceQueueMap() {} @@ -1249,9 +1264,10 @@ void DeviceQueueMap::initialize(VkDevice device, uint32_t queueCount) { // QueueIndexing: - constexpr uint32_t kQueueIndexMedium = 0; - constexpr uint32_t kQueueIndexHigh = 1; - constexpr uint32_t kQueueIndexLow = 2; + constexpr uint32_t kQueueIndexMedium = 0; + constexpr uint32_t kQueueIndexHigh = 1; + constexpr uint32_t kQueueIndexRealtime = 2; + constexpr uint32_t kQueueIndexLow = 3; ASSERT(queueCount); ASSERT((queueIndex + queueCount) <= queueFamily.getProperties()->queueCount); @@ -1277,8 +1293,29 @@ void DeviceQueueMap::initialize(VkDevice device, mQueueAndIndices[egl::ContextPriority::High] = mQueueAndIndices[egl::ContextPriority::Medium]; } - // If at least 3 queues, Low has its own queue. Adjust Low priority. + + // If at least 3 queues, Realtime has its own queue if (queueCount > 2) + { + GetDeviceQueue(device, makeProtected, mQueueFamilyIndex, queueIndex + kQueueIndexRealtime, + &queue); + mQueueAndIndices[egl::ContextPriority::Realtime] = {egl::ContextPriority::Realtime, queue, + queueIndex + kQueueIndexRealtime}; + } + else if (queueCount > 1) + { + // If only 2 queues, Realtime uses queue of High priority + mQueueAndIndices[egl::ContextPriority::Realtime] = + mQueueAndIndices[egl::ContextPriority::High]; + } + else + { + mQueueAndIndices[egl::ContextPriority::Realtime] = + mQueueAndIndices[egl::ContextPriority::Medium]; + } + + // If at least 4 queues, Low has its own queue. Adjust Low priority. + if (queueCount > 3) { GetDeviceQueue(device, makeProtected, mQueueFamilyIndex, queueIndex + kQueueIndexLow, &queue); @@ -1300,32 +1337,36 @@ void QueueFamily::initialize(const VkQueueFamilyProperties &queueFamilyPropertie } uint32_t QueueFamily::FindIndex(const std::vector &queueFamilyProperties, - VkQueueFlags flags, - int32_t matchNumber, + VkQueueFlags includeFlags, + VkQueueFlags optionalFlags, + VkQueueFlags excludeFlags, uint32_t *matchCount) { - uint32_t index = QueueFamily::kInvalidIndex; - uint32_t count = 0; - - for (uint32_t familyIndex = 0; familyIndex < queueFamilyProperties.size(); ++familyIndex) + // check with both include and optional flags + VkQueueFlags preferredFlags = includeFlags | optionalFlags; + auto findIndexPredicate = [&preferredFlags, + &excludeFlags](const VkQueueFamilyProperties &queueInfo) { + return (queueInfo.queueFlags & excludeFlags) == 0 && + (queueInfo.queueFlags & preferredFlags) == preferredFlags; + }; + + auto it = std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.end(), + findIndexPredicate); + if (it == queueFamilyProperties.end()) { - const auto &queueInfo = queueFamilyProperties[familyIndex]; - if ((queueInfo.queueFlags & flags) == flags) - { - ASSERT(queueInfo.queueCount > 0); - count++; - if ((index == QueueFamily::kInvalidIndex) && (matchNumber-- == 0)) - { - index = familyIndex; - } - } + // didn't find a match, exclude the optional flags from the list + preferredFlags = includeFlags; + it = std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.end(), + findIndexPredicate); } - if (matchCount) + if (it == queueFamilyProperties.end()) { - *matchCount = count; + *matchCount = 0; + return QueueFamily::kInvalidIndex; } - return index; + *matchCount = 1; + return static_cast(std::distance(queueFamilyProperties.begin(), it)); } } // namespace vk diff --git a/src/libANGLE/renderer/vulkan/CommandQueue.h b/src/libANGLE/renderer/vulkan/CommandQueue.h index 18aa2024918..dcf6bbae82d 100644 --- a/src/libANGLE/renderer/vulkan/CommandQueue.h +++ b/src/libANGLE/renderer/vulkan/CommandQueue.h @@ -20,6 +20,7 @@ #include "common/vulkan/vk_headers.h" #include "libANGLE/renderer/vulkan/PersistentCommandPool.h" #include "libANGLE/renderer/vulkan/vk_helpers.h" +#include "vulkan/vulkan_core.h" namespace rx { @@ -87,7 +88,7 @@ class CommandBatch final : angle::NonCopyable CommandBatch &operator=(CommandBatch &&other); void destroy(VkDevice device); - angle::Result release(ErrorContext *context); + angle::Result release(ErrorContext *context, WhenToResetCommandBuffer whenToReset); void setQueueSerial(const QueueSerial &serial); void setProtectionType(ProtectionType protectionType); @@ -101,6 +102,8 @@ class CommandBatch final : angle::NonCopyable const PrimaryCommandBuffer &getPrimaryCommands() const; const SharedExternalFence &getExternalFence(); + // Accessing the shared fence is prioritized before the shared external fence, since the shared + // fence may be used in an extra empty submission after the external fence (via a feature flag). bool hasFence() const; VkFence getFenceHandle() const; VkResult getFenceStatus(VkDevice device) const; @@ -129,8 +132,9 @@ class QueueFamily final : angle::NonCopyable static const uint32_t kInvalidIndex = std::numeric_limits::max(); static uint32_t FindIndex(const std::vector &queueFamilyProperties, - VkQueueFlags flags, - int32_t matchNumber, // 0 = first match, 1 = second match ... + VkQueueFlags includeFlags, + VkQueueFlags optionalFlags, + VkQueueFlags excludeFlags, uint32_t *matchCount); static const uint32_t kQueueCount = static_cast(egl::ContextPriority::EnumCount); static const float kQueuePriorities[static_cast(egl::ContextPriority::EnumCount)]; @@ -202,61 +206,114 @@ class DeviceQueueMap final angle::PackedEnumMap mQueueAndIndices; }; -class CommandPoolAccess : angle::NonCopyable +class CommandsState : angle::NonCopyable { public: - CommandPoolAccess(); - ~CommandPoolAccess(); - angle::Result initCommandPool(ErrorContext *context, - ProtectionType protectionType, - const uint32_t queueFamilyIndex); + CommandsState(Renderer *renderer, + ProtectionType protectionType, + egl::ContextPriority contextPriority); + ~CommandsState(); + void destroy(VkDevice device); - void destroyPrimaryCommandBuffer(VkDevice device, PrimaryCommandBuffer *primaryCommands) const; - angle::Result collectPrimaryCommandBuffer(ErrorContext *context, - const ProtectionType protectionType, - PrimaryCommandBuffer *primaryCommands); + angle::Result flushOutsideRPCommands(Context *context, - ProtectionType protectionType, - egl::ContextPriority priority, - OutsideRenderPassCommandBufferHelper **outsideRPCommands); + OutsideRenderPassCommandBufferHelper **outsideRPCommands) + { + ANGLE_TRACE_EVENT0("gpu.angle", "CommandsState::flushOutsideRPCommands"); + std::lock_guard lock(mCmdPoolMutex); + ANGLE_TRY(ensurePrimaryCommandBufferValidLocked(context)); + ANGLE_TRY((*outsideRPCommands)->flushToPrimary(context, this, &mPrimaryCommands)); + // Restart the command buffer. + return (*outsideRPCommands)->reset(context, &mSecondaryCommands); + } + angle::Result flushRenderPassCommands(Context *context, - const ProtectionType &protectionType, - const egl::ContextPriority &priority, const RenderPass &renderPass, VkFramebuffer framebufferOverride, - RenderPassCommandBufferHelper **renderPassCommands); + RenderPassCommandBufferHelper **renderPassCommands) + { + ANGLE_TRACE_EVENT0("gpu.angle", "CommandsState::flushRenderPassCommands"); + std::lock_guard lock(mCmdPoolMutex); + ANGLE_TRY(ensurePrimaryCommandBufferValidLocked(context)); + ANGLE_TRY((*renderPassCommands) + ->flushToPrimary(context, this, &mPrimaryCommands, renderPass, + framebufferOverride)); + // Restart the command buffer. + return (*renderPassCommands)->reset(context, &mSecondaryCommands); + } - void flushWaitSemaphores(ProtectionType protectionType, - egl::ContextPriority priority, - std::vector &&waitSemaphores, - std::vector &&waitSemaphoreStageMasks); + void flushImagesTransitionToForeign( + std::vector &&imagesToTransitionToForeign) + { + std::lock_guard lock(mCmdPoolMutex); + // If we have foreign images to transit, we must have already issued some barrier, which + // means command buffer can't be empty. + ASSERT(mPrimaryCommands.valid()); + + mPrimaryCommands.pipelineBarrier( + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, + nullptr, static_cast(imagesToTransitionToForeign.size()), + imagesToTransitionToForeign.data()); + imagesToTransitionToForeign.clear(); + } angle::Result getCommandsAndWaitSemaphores( ErrorContext *context, - ProtectionType protectionType, - egl::ContextPriority priority, - CommandBatch *batchOut, - std::vector &&imagesToTransitionToForeign, + CommandPoolAccess *commandPoolAccess, + CommandBatch *batch, std::vector *waitSemaphoresOut, std::vector *waitSemaphoreStageMasksOut); + void addWaitSemaphore(VkSemaphore waitSemaphores, VkPipelineStageFlags waitSemaphoreStageMasks) + { + mWaitSemaphores.emplace_back(waitSemaphores); + mWaitSemaphoreStageMasks.emplace_back(waitSemaphoreStageMasks); + } + + bool hasWaitSemaphoresPendingSubmission() const { return !mWaitSemaphores.empty(); } + + void setPriority(egl::ContextPriority newPriority) { mPriority = newPriority; } + egl::ContextPriority getPriority() const { return mPriority; } + ProtectionType getProtectionType() const { return mProtectionType; } + + angle::Result insertSubmitDebugMarker(ErrorContext *context, QueueSubmitReason reason); + private: - angle::Result ensurePrimaryCommandBufferValidLocked(ErrorContext *context, - const ProtectionType &protectionType, - const egl::ContextPriority &priority) + angle::Result ensurePrimaryCommandBufferValidLocked(ErrorContext *context); + + // Command pool mutex lock shared with CommandPoolAccess + angle::SimpleMutex &mCmdPoolMutex; + // This is immutable + const vk::ProtectionType mProtectionType; + egl::ContextPriority mPriority; + + std::vector mWaitSemaphores; + std::vector mWaitSemaphoreStageMasks; + PrimaryCommandBuffer mPrimaryCommands; + SecondaryCommandBufferCollector mSecondaryCommands; +}; + +class CommandPoolAccess : angle::NonCopyable +{ + public: + CommandPoolAccess(); + ~CommandPoolAccess(); + angle::Result initCommandPool(ErrorContext *context, + ProtectionType protectionType, + const uint32_t queueFamilyIndex); + void destroy(VkDevice device); + void destroyPrimaryCommandBuffer(VkDevice device, PrimaryCommandBuffer *primaryCommands) const; + angle::Result collectPrimaryCommandBuffer(ErrorContext *context, + const ProtectionType protectionType, + PrimaryCommandBuffer *primaryCommands, + WhenToResetCommandBuffer whenToReset); + + private: + angle::Result allocatePrimaryCommandBufferLocked(ErrorContext *context, + const ProtectionType &protectionType, + PrimaryCommandBuffer *primaryCommandsOut) { - CommandsState &state = mCommandsStateMap[priority][protectionType]; - if (state.primaryCommands.valid()) - { - return angle::Result::Continue; - } - ANGLE_TRY(mPrimaryCommandPoolMap[protectionType].allocate(context, &state.primaryCommands)); - VkCommandBufferBeginInfo beginInfo = {}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - beginInfo.pInheritanceInfo = nullptr; - ANGLE_VK_TRY(context, state.primaryCommands.begin(beginInfo)); - return angle::Result::Continue; + return mPrimaryCommandPoolMap[protectionType].allocate(context, primaryCommandsOut); } // This mutex ensures vulkan command pool is externally synchronized. @@ -266,14 +323,10 @@ class CommandPoolAccess : angle::NonCopyable // 1) recording commands on any command buffers allocated from the same command pool // 2) allocate, free, reset command buffers from the same command pool. // 3) any operations on the command pool itself + friend class CommandsState; mutable angle::SimpleMutex mCmdPoolMutex; using PrimaryCommandPoolMap = angle::PackedEnumMap; - using CommandsStateMap = - angle::PackedEnumMap>; - - CommandsStateMap mCommandsStateMap; // Keeps a free list of reusable primary command buffers. PrimaryCommandPoolMap mPrimaryCommandPoolMap; }; @@ -349,12 +402,10 @@ class CommandQueue : angle::NonCopyable bool isBusy(Renderer *renderer) const; angle::Result submitCommands(ErrorContext *context, - ProtectionType protectionType, - egl::ContextPriority priority, VkSemaphore signalSemaphore, SharedExternalFence &&externalFence, - std::vector &&imagesToTransitionToForeign, - const QueueSerial &submitQueueSerial); + const QueueSerial &submitQueueSerial, + CommandsState &&commandsState); angle::Result queueSubmitOneOff(ErrorContext *context, ProtectionType protectionType, @@ -388,36 +439,7 @@ class CommandQueue : angle::NonCopyable return angle::Result::Continue; } - ANGLE_INLINE void flushWaitSemaphores( - ProtectionType protectionType, - egl::ContextPriority priority, - std::vector &&waitSemaphores, - std::vector &&waitSemaphoreStageMasks) - { - return mCommandPoolAccess.flushWaitSemaphores(protectionType, priority, - std::move(waitSemaphores), - std::move(waitSemaphoreStageMasks)); - } - ANGLE_INLINE angle::Result flushOutsideRPCommands( - Context *context, - ProtectionType protectionType, - egl::ContextPriority priority, - OutsideRenderPassCommandBufferHelper **outsideRPCommands) - { - return mCommandPoolAccess.flushOutsideRPCommands(context, protectionType, priority, - outsideRPCommands); - } - ANGLE_INLINE angle::Result flushRenderPassCommands( - Context *context, - ProtectionType protectionType, - const egl::ContextPriority &priority, - const RenderPass &renderPass, - VkFramebuffer framebufferOverride, - RenderPassCommandBufferHelper **renderPassCommands) - { - return mCommandPoolAccess.flushRenderPassCommands( - context, protectionType, priority, renderPass, framebufferOverride, renderPassCommands); - } + CommandPoolAccess &getCommandPoolAccess() { return mCommandPoolAccess; } const angle::VulkanPerfCounters getPerfCounters() const; void resetPerFramePerfCounters(); @@ -425,13 +447,16 @@ class CommandQueue : angle::NonCopyable // Release finished commands and clean up garbage immediately, or request async clean up if // enabled. angle::Result releaseFinishedCommandsAndCleanupGarbage(ErrorContext *context); - angle::Result releaseFinishedCommands(ErrorContext *context) + angle::Result releaseFinishedCommands(ErrorContext *context, + WhenToResetCommandBuffer whenToReset) { std::lock_guard lock(mCmdReleaseMutex); - return releaseFinishedCommandsLocked(context); + return releaseFinishedCommandsLocked(context, whenToReset); } angle::Result postSubmitCheck(ErrorContext *context); + bool isInFlightCommandsEmpty() const; + // Try to cleanup garbage and return if something was cleaned. Otherwise, wait for the // mInFlightCommands and retry. angle::Result cleanupSomeGarbage(ErrorContext *context, @@ -449,7 +474,8 @@ class CommandQueue : angle::NonCopyable std::unique_lock *lock); void onCommandBatchFinishedLocked(CommandBatch &&batch); // Walk mFinishedCommands, reset and recycle all command buffers. - angle::Result releaseFinishedCommandsLocked(ErrorContext *context); + angle::Result releaseFinishedCommandsLocked(ErrorContext *context, + WhenToResetCommandBuffer whenToReset); // Walk mInFlightCommands, check and update mLastCompletedSerials for all commands that are // finished angle::Result checkCompletedCommandsLocked(ErrorContext *context); @@ -501,6 +527,11 @@ class CommandQueue : angle::NonCopyable angle::VulkanPerfCounters mPerfCounters; }; +ANGLE_INLINE bool CommandQueue::isInFlightCommandsEmpty() const +{ + return mInFlightCommands.empty(); +} + // A helper thread used to clean up garbage class CleanUpThread : public ErrorContext { @@ -577,8 +608,8 @@ class [[nodiscard]] ScopedPrimaryCommandBuffer final DeviceScoped unlockAndRelease() { - ASSERT(mCommandBuffer.get().valid() && mPoolLock.owns_lock() || - !mCommandBuffer.get().valid() && mPoolLock.mutex() == nullptr); + ASSERT((mCommandBuffer.get().valid() && mPoolLock.owns_lock()) || + (!mCommandBuffer.get().valid() && mPoolLock.mutex() == nullptr)); mPoolLock = {}; return std::move(mCommandBuffer); } diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp index ca3d50f0745..59d44328dd0 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for ContextVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/ContextVk.h" #include "common/bitset_utils.h" @@ -54,6 +58,9 @@ namespace // If the total size of copyBufferToImage commands in the outside command buffer reaches the // threshold below, the latter is flushed. static constexpr VkDeviceSize kMaxBufferToImageCopySize = 64 * 1024 * 1024; +// If the number of render passes in a command buffer reaches the threshold below, it will be +// flushed and submitted. +static constexpr VkDeviceSize kMaxRenderPassCountPerCommandBuffer = 128; // The number of queueSerials we will reserve for outsideRenderPassCommands when we generate one for // RenderPassCommands. static constexpr size_t kMaxReservedOutsideRenderPassQueueSerials = 15; @@ -67,6 +74,10 @@ static constexpr GLbitfield kWriteAfterAccessImageMemoryBarriers = static constexpr GLbitfield kWriteAfterAccessMemoryBarriers = kWriteAfterAccessImageMemoryBarriers | GL_SHADER_STORAGE_BARRIER_BIT; +// The number of minimum commands in the command buffer to prefer submit at FBO boundary or +// immediately submit when the device is idle after calling to flush. +static constexpr size_t kMinCommandCountToSubmit = 1024; + // For shader uniforms such as gl_DepthRange and the viewport size. struct GraphicsDriverUniforms { @@ -93,6 +104,7 @@ struct GraphicsDriverUniforms // - Sample count // - Enabled clip planes // - Depth transformation + // - layered FBO uint32_t misc; }; static_assert(sizeof(GraphicsDriverUniforms) % (sizeof(uint32_t) * 4) == 0, @@ -156,21 +168,39 @@ GLenum DefaultGLErrorCode(VkResult result) } } -constexpr gl::ShaderMap kShaderReadOnlyImageLayouts = { - {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly}, - {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersReadOnly}, - {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersReadOnly}, - {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersReadOnly}, - {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly}, - {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}}; - -constexpr gl::ShaderMap kShaderWriteImageLayouts = { - {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite}, - {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersWrite}, - {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersWrite}, - {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersWrite}, - {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite}, - {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}}; +constexpr gl::ShaderMap kShaderReadOnlyImageAccess = { + {gl::ShaderType::Vertex, vk::ImageAccess::VertexShaderReadOnly}, + {gl::ShaderType::TessControl, vk::ImageAccess::PreFragmentShadersReadOnly}, + {gl::ShaderType::TessEvaluation, vk::ImageAccess::PreFragmentShadersReadOnly}, + {gl::ShaderType::Geometry, vk::ImageAccess::PreFragmentShadersReadOnly}, + {gl::ShaderType::Fragment, vk::ImageAccess::FragmentShaderReadOnly}, + {gl::ShaderType::Compute, vk::ImageAccess::ComputeShaderReadOnly}}; + +constexpr gl::ShaderMap kShaderWriteImageAccess = { + {gl::ShaderType::Vertex, vk::ImageAccess::VertexShaderWrite}, + {gl::ShaderType::TessControl, vk::ImageAccess::PreFragmentShadersWrite}, + {gl::ShaderType::TessEvaluation, vk::ImageAccess::PreFragmentShadersWrite}, + {gl::ShaderType::Geometry, vk::ImageAccess::PreFragmentShadersWrite}, + {gl::ShaderType::Fragment, vk::ImageAccess::FragmentShaderWrite}, + {gl::ShaderType::Compute, vk::ImageAccess::ComputeShaderWrite}}; + +constexpr angle::PackedEnumMap kPrimitiveTopologyClass = {{ + {gl::PrimitiveMode::Points, gl::PrimitiveMode::Points}, + {gl::PrimitiveMode::Lines, gl::PrimitiveMode::Lines}, + {gl::PrimitiveMode::LineLoop, gl::PrimitiveMode::Lines}, + {gl::PrimitiveMode::LineStrip, gl::PrimitiveMode::Lines}, + {gl::PrimitiveMode::Triangles, gl::PrimitiveMode::Triangles}, + {gl::PrimitiveMode::TriangleStrip, gl::PrimitiveMode::Triangles}, + {gl::PrimitiveMode::TriangleFan, gl::PrimitiveMode::Triangles}, + {gl::PrimitiveMode::LinesAdjacency, gl::PrimitiveMode::Lines}, + {gl::PrimitiveMode::LineStripAdjacency, gl::PrimitiveMode::Lines}, + {gl::PrimitiveMode::TrianglesAdjacency, gl::PrimitiveMode::Triangles}, + {gl::PrimitiveMode::TriangleStripAdjacency, gl::PrimitiveMode::Triangles}, + {gl::PrimitiveMode::Patches, gl::PrimitiveMode::Patches}, + // Use Unused1 as a placeholder for "uninitialized". Using that instead of InvalidEnum allows a + // look up in this table and avoid special-casing it. + {gl::PrimitiveMode::Unused1, gl::PrimitiveMode::InvalidEnum}, +}}; constexpr VkBufferUsageFlags kVertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; constexpr size_t kDynamicVertexDataSize = 16 * 1024; @@ -263,15 +293,6 @@ SurfaceRotation DetermineSurfaceRotation(const gl::Framebuffer *framebuffer, } } -// Should not generate a copy with modern C++. -EventName GetTraceEventName(const char *title, uint64_t counter) -{ - EventName buf; - snprintf(buf.data(), kMaxGpuEventNameLen - 1, "%s %llu", title, - static_cast(counter)); - return buf; -} - vk::ResourceAccess GetColorAccess(const gl::State &state, const gl::FramebufferState &framebufferState, const gl::DrawBufferMask &emulatedAlphaMask, @@ -378,7 +399,7 @@ bool IsStencilSamplerBinding(const gl::ProgramExecutable &executable, size_t tex return isStencilTexture; } -vk::ImageLayout GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper &image, +vk::ImageAccess GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper &image, gl::ShaderType firstShader) { const bool isDepthTexture = @@ -401,8 +422,8 @@ vk::ImageLayout GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper & if ((isDepthTexture && !isDepthReadOnlyAttachment) || (isStencilTexture && !isStencilReadOnlyAttachment)) { - return isFS ? vk::ImageLayout::DepthStencilFragmentShaderFeedback - : vk::ImageLayout::DepthStencilAllShadersFeedback; + return isFS ? vk::ImageAccess::DepthStencilFragmentShaderFeedback + : vk::ImageAccess::DepthStencilAllShadersFeedback; } if (isDepthReadOnlyAttachment) @@ -410,14 +431,14 @@ vk::ImageLayout GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper & if (isStencilReadOnlyAttachment) { // Depth read + stencil read - return isFS ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead - : vk::ImageLayout::DepthReadStencilReadAllShadersRead; + return isFS ? vk::ImageAccess::DepthReadStencilReadFragmentShaderRead + : vk::ImageAccess::DepthReadStencilReadAllShadersRead; } else { // Depth read + stencil write - return isFS ? vk::ImageLayout::DepthReadStencilWriteFragmentShaderDepthRead - : vk::ImageLayout::DepthReadStencilWriteAllShadersDepthRead; + return isFS ? vk::ImageAccess::DepthReadStencilWriteFragmentShaderDepthRead + : vk::ImageAccess::DepthReadStencilWriteAllShadersDepthRead; } } else @@ -425,19 +446,19 @@ vk::ImageLayout GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper & if (isStencilReadOnlyAttachment) { // Depth write + stencil read - return isFS ? vk::ImageLayout::DepthWriteStencilReadFragmentShaderStencilRead - : vk::ImageLayout::DepthWriteStencilReadAllShadersStencilRead; + return isFS ? vk::ImageAccess::DepthWriteStencilReadFragmentShaderStencilRead + : vk::ImageAccess::DepthWriteStencilReadAllShadersStencilRead; } else { // Depth write + stencil write: This is definitely a feedback loop and is handled above. UNREACHABLE(); - return vk::ImageLayout::DepthStencilAllShadersFeedback; + return vk::ImageAccess::DepthStencilAllShadersFeedback; } } } -vk::ImageLayout GetImageReadLayout(TextureVk *textureVk, +vk::ImageAccess GetImageReadAccess(TextureVk *textureVk, const gl::ProgramExecutable &executable, size_t textureUnit, PipelineType pipelineType) @@ -448,8 +469,8 @@ vk::ImageLayout GetImageReadLayout(TextureVk *textureVk, // we consider this image's layout as writeable. if (textureVk->hasBeenBoundAsImage() && executable.hasImages()) { - return pipelineType == PipelineType::Compute ? vk::ImageLayout::ComputeShaderWrite - : vk::ImageLayout::AllGraphicsShadersWrite; + return pipelineType == PipelineType::Compute ? vk::ImageAccess::ComputeShaderWrite + : vk::ImageAccess::AllGraphicsShadersWrite; } gl::ShaderBitSet remainingShaderBits = @@ -487,8 +508,8 @@ vk::ImageLayout GetImageReadLayout(TextureVk *textureVk, image.setRenderPassUsageFlag(vk::RenderPassUsage::ColorTextureSampler); - return isFragmentShaderOnly ? vk::ImageLayout::ColorWriteFragmentShaderFeedback - : vk::ImageLayout::ColorWriteAllShadersFeedback; + return isFragmentShaderOnly ? vk::ImageAccess::ColorWriteFragmentShaderFeedback + : vk::ImageAccess::ColorWriteAllShadersFeedback; } if (image.isDepthOrStencil()) @@ -498,8 +519,8 @@ vk::ImageLayout GetImageReadLayout(TextureVk *textureVk, // split a RenderPass to transition a depth texture from shader-read to read-only. // This improves performance in Manhattan. Future optimizations are likely possible // here including using specialized barriers without breaking the RenderPass. - return isFragmentShaderOnly ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead - : vk::ImageLayout::DepthReadStencilReadAllShadersRead; + return isFragmentShaderOnly ? vk::ImageAccess::DepthReadStencilReadFragmentShaderRead + : vk::ImageAccess::DepthReadStencilReadAllShadersRead; } // We barrier against either: @@ -508,14 +529,14 @@ vk::ImageLayout GetImageReadLayout(TextureVk *textureVk, // - Pre-fragment only (vertex, geometry and tessellation together) if (remainingShaderBits.any() || firstShader != lastShader) { - return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersReadOnly - : vk::ImageLayout::PreFragmentShadersReadOnly; + return lastShader == gl::ShaderType::Fragment ? vk::ImageAccess::AllGraphicsShadersReadOnly + : vk::ImageAccess::PreFragmentShadersReadOnly; } - return kShaderReadOnlyImageLayouts[firstShader]; + return kShaderReadOnlyImageAccess[firstShader]; } -vk::ImageLayout GetImageWriteLayoutAndSubresource(const gl::ImageUnit &imageUnit, +vk::ImageAccess GetImageWriteAccessAndSubresource(const gl::ImageUnit &imageUnit, vk::ImageHelper &image, gl::ShaderBitSet shaderStages, gl::LevelIndex *levelOut, @@ -542,11 +563,11 @@ vk::ImageLayout GetImageWriteLayoutAndSubresource(const gl::ImageUnit &imageUnit // - Pre-fragment only (vertex, geometry and tessellation together) if (shaderStages.any() || firstShader != lastShader) { - return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersWrite - : vk::ImageLayout::PreFragmentShadersWrite; + return lastShader == gl::ShaderType::Fragment ? vk::ImageAccess::AllGraphicsShadersWrite + : vk::ImageAccess::PreFragmentShadersWrite; } - return kShaderWriteImageLayouts[firstShader]; + return kShaderWriteImageAccess[firstShader]; } template @@ -577,16 +598,11 @@ void OnImageBufferWrite(vk::Context *context, vk::BufferHelper &buffer = bufferVk->getBuffer(); VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; commandBufferHelper->bufferWrite(context, accessFlags, stages, &buffer); + bufferVk->onDataChanged(); } constexpr angle::PackedEnumMap kRenderPassClosureReason = {{ {RenderPassClosureReason::AlreadySpecifiedElsewhere, nullptr}, - {RenderPassClosureReason::ContextDestruction, "Render pass closed due to context destruction"}, - {RenderPassClosureReason::ContextChange, "Render pass closed due to context change"}, - {RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush()"}, - {RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish()"}, - {RenderPassClosureReason::EGLSwapBuffers, "Render pass closed due to eglSwapBuffers()"}, - {RenderPassClosureReason::EGLWaitClient, "Render pass closed due to eglWaitClient()"}, {RenderPassClosureReason::SurfaceUnMakeCurrent, "Render pass closed due to onSurfaceUnMakeCurrent()"}, {RenderPassClosureReason::FramebufferBindingChange, @@ -610,8 +626,9 @@ constexpr angle::PackedEnumMap kRenderPas "Render pass closed due to depth/stencil attachment write after feedback loop"}, {RenderPassClosureReason::PipelineBindWhileXfbActive, "Render pass closed due to graphics pipeline change while transform feedback is active"}, - {RenderPassClosureReason::BufferWriteThenMap, - "Render pass closed due to mapping buffer being written to by said render pass"}, + {RenderPassClosureReason::XfbWriteThenTextureBuffer, + "Render pass closed due to read of texture buffer previously used as transform feedback " + "output in render pass"}, {RenderPassClosureReason::BufferWriteThenOutOfRPRead, "Render pass closed due to non-render-pass read of buffer that was written to in render pass"}, {RenderPassClosureReason::BufferUseThenOutOfRPWrite, @@ -620,8 +637,8 @@ constexpr angle::PackedEnumMap kRenderPas "Render pass closed due to non-render-pass read of image that was used in render pass"}, {RenderPassClosureReason::ImageUseThenOutOfRPWrite, "Render pass closed due to non-render-pass write of image that was used in render pass"}, - {RenderPassClosureReason::XfbWriteThenComputeRead, - "Render pass closed due to compute read of buffer previously used as transform feedback " + {RenderPassClosureReason::XfbWriteThenUniformBufferRead, + "Render pass closed due to read of buffer previously used as transform feedback " "output in render pass"}, {RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer, "Render pass closed due to indirect dispatch buffer previously used as transform feedback " @@ -629,7 +646,6 @@ constexpr angle::PackedEnumMap kRenderPas {RenderPassClosureReason::ImageAttachmentThenComputeRead, "Render pass closed due to compute read of image previously used as framebuffer attachment in " "render pass"}, - {RenderPassClosureReason::GetQueryResult, "Render pass closed due to getting query result"}, {RenderPassClosureReason::BeginNonRenderPassQuery, "Render pass closed due to non-render-pass query begin"}, {RenderPassClosureReason::EndNonRenderPassQuery, @@ -637,28 +653,19 @@ constexpr angle::PackedEnumMap kRenderPas {RenderPassClosureReason::TimestampQuery, "Render pass closed due to timestamp query"}, {RenderPassClosureReason::EndRenderPassQuery, "Render pass closed due to switch from query enabled draw to query disabled draw"}, - {RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels()"}, {RenderPassClosureReason::BufferUseThenReleaseToExternal, "Render pass closed due to buffer (used by render pass) release to external"}, {RenderPassClosureReason::ImageUseThenReleaseToExternal, "Render pass closed due to image (used by render pass) release to external"}, - {RenderPassClosureReason::BufferInUseWhenSynchronizedMap, - "Render pass closed due to mapping buffer in use by GPU without GL_MAP_UNSYNCHRONIZED_BIT"}, {RenderPassClosureReason::GLMemoryBarrierThenStorageResource, "Render pass closed due to glMemoryBarrier before storage output in render pass"}, {RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier, "Render pass closed due to glMemoryBarrier after storage output in render pass"}, - {RenderPassClosureReason::ExternalSemaphoreSignal, - "Render pass closed due to external semaphore signal"}, {RenderPassClosureReason::SyncObjectInit, "Render pass closed due to sync object insertion"}, - {RenderPassClosureReason::SyncObjectWithFdInit, - "Render pass closed due to sync object with fd insertion"}, {RenderPassClosureReason::SyncObjectClientWait, "Render pass closed due to sync object client wait"}, - {RenderPassClosureReason::SyncObjectServerWait, - "Render pass closed due to sync object server wait"}, - {RenderPassClosureReason::SyncObjectGetStatus, - "Render pass closed due to sync object get status"}, + {RenderPassClosureReason::ForeignImageRelease, + "Render pass closed due to release of foreign image"}, {RenderPassClosureReason::XfbPause, "Render pass closed due to transform feedback pause"}, {RenderPassClosureReason::FramebufferFetchEmulation, "Render pass closed due to framebuffer fetch emulation"}, @@ -670,17 +677,28 @@ constexpr angle::PackedEnumMap kRenderPas "Render pass closed due to fallback to CPU when copying texture"}, {RenderPassClosureReason::TextureReformatToRenderable, "Render pass closed due to reformatting texture to a renderable fallback"}, - {RenderPassClosureReason::DeviceLocalBufferMap, - "Render pass closed due to mapping device local buffer"}, {RenderPassClosureReason::PrepareForBlit, "Render pass closed prior to draw-based blit"}, {RenderPassClosureReason::PrepareForImageCopy, "Render pass closed prior to draw-based image copy"}, + {RenderPassClosureReason::GenerateMipmapWithDraw, + "Temporary render pass used to generate mipmap using draws"}, + {RenderPassClosureReason::TemporaryForClearTexture, + "Temporary render pass used for clear texture closed"}, {RenderPassClosureReason::TemporaryForImageClear, "Temporary render pass used for image clear closed"}, {RenderPassClosureReason::TemporaryForImageCopy, "Temporary render pass used for image copy closed"}, {RenderPassClosureReason::TemporaryForOverlayDraw, "Temporary render pass used for overlay draw closed"}, + {RenderPassClosureReason::GraphicsTextureImageAccessThenComputeAccess, + "Render pass closed due to implicit layout transition when image is used in compute after " + "sampling"}, + {RenderPassClosureReason::OutOfReservedQueueSerialForOutsideCommands, + "Render pass closed due to running out of reserved serials"}, + {RenderPassClosureReason::LegacyDithering, "Render pass closed due to updating legacy dither"}, + {RenderPassClosureReason::SubmitCommands, "Render pass closed at command buffer submission"}, + {RenderPassClosureReason::TileMemorySimulatedClear, + "Temporary render pass used for tile memory clear simulation"}, }}; VkDependencyFlags GetLocalDependencyFlags(ContextVk *contextVk) @@ -725,112 +743,12 @@ bool IsAnySamplesQuery(gl::QueryType type) return type == gl::QueryType::AnySamples || type == gl::QueryType::AnySamplesConservative; } -enum class GraphicsPipelineSubsetRenderPass -{ - Unused, - Required, -}; - -template -angle::Result CreateGraphicsPipelineSubset(ContextVk *contextVk, - const vk::GraphicsPipelineDesc &desc, - vk::GraphicsPipelineTransitionBits transition, - GraphicsPipelineSubsetRenderPass renderPass, - Cache *cache, - vk::PipelineCacheAccess *pipelineCache, - vk::PipelineHelper **pipelineOut) -{ - const vk::PipelineLayout unusedPipelineLayout; - const vk::ShaderModuleMap unusedShaders; - const vk::SpecializationConstants unusedSpecConsts = {}; - - if (*pipelineOut != nullptr && !transition.any()) - { - return angle::Result::Continue; - } - - if (*pipelineOut != nullptr) - { - ASSERT((*pipelineOut)->valid()); - if ((*pipelineOut)->findTransition(transition, desc, pipelineOut)) - { - return angle::Result::Continue; - } - } - - vk::PipelineHelper *oldPipeline = *pipelineOut; - - const vk::GraphicsPipelineDesc *descPtr = nullptr; - if (!cache->getPipeline(desc, &descPtr, pipelineOut)) - { - const vk::RenderPass unusedRenderPass; - const vk::RenderPass *compatibleRenderPass = &unusedRenderPass; - if (renderPass == GraphicsPipelineSubsetRenderPass::Required) - { - // Pull in a compatible RenderPass if used by this subset. - ANGLE_TRY(contextVk->getCompatibleRenderPass(desc.getRenderPassDesc(), - &compatibleRenderPass)); - } - - ANGLE_TRY(cache->createPipeline(contextVk, pipelineCache, *compatibleRenderPass, - unusedPipelineLayout, unusedShaders, unusedSpecConsts, - PipelineSource::Draw, desc, &descPtr, pipelineOut)); - } - - if (oldPipeline) - { - oldPipeline->addTransition(transition, descPtr, *pipelineOut); - } - - return angle::Result::Continue; -} - bool QueueSerialsHaveDifferentIndexOrSmaller(const QueueSerial &queueSerial1, const QueueSerial &queueSerial2) { return queueSerial1.getIndex() != queueSerial2.getIndex() || queueSerial1 < queueSerial2; } -void UpdateImagesWithSharedCacheKey(const gl::ActiveTextureArray &activeImages, - const std::vector &imageBindings, - const vk::SharedDescriptorSetCacheKey &sharedCacheKey) -{ - for (const gl::ImageBinding &imageBinding : imageBindings) - { - uint32_t arraySize = static_cast(imageBinding.boundImageUnits.size()); - for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement) - { - GLuint imageUnit = imageBinding.boundImageUnits[arrayElement]; - // For simplicity, we do not check if uniform is active or duplicate. The worst case is - // we unnecessarily delete the cache entry when image bound to inactive uniform is - // destroyed. - activeImages[imageUnit]->onNewDescriptorSet(sharedCacheKey); - } - } -} - -void UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer &bufferBinding, - VkDescriptorType descriptorType, - const vk::SharedDescriptorSetCacheKey &sharedCacheKey) -{ - if (bufferBinding.get() != nullptr) - { - // For simplicity, we do not check if uniform is active or duplicate. The worst case is - // we unnecessarily delete the cache entry when buffer bound to inactive uniform is - // destroyed. - BufferVk *bufferVk = vk::GetImpl(bufferBinding.get()); - vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); - if (vk::IsDynamicDescriptor(descriptorType)) - { - bufferHelper.getBufferBlock()->onNewDescriptorSet(sharedCacheKey); - } - else - { - bufferHelper.onNewDescriptorSet(sharedCacheKey); - } - } -} - void GenerateTextureUnitSamplerIndexMap( const std::vector &samplerBoundTextureUnits, std::unordered_map *textureUnitSamplerIndexMapOut) @@ -842,6 +760,37 @@ void GenerateTextureUnitSamplerIndexMap( {samplerBoundTextureUnits[samplerIndex], static_cast(samplerIndex)}); } } + +GLenum ConvertImageAccessToGLImageLayout(vk::Renderer *renderer, vk::ImageAccess imageAccess) +{ + switch (renderer->getVkImageLayout(imageAccess)) + { + case VK_IMAGE_LAYOUT_UNDEFINED: + return GL_NONE; + case VK_IMAGE_LAYOUT_GENERAL: + return GL_LAYOUT_GENERAL_EXT; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return GL_LAYOUT_COLOR_ATTACHMENT_EXT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return GL_LAYOUT_SHADER_READ_ONLY_EXT; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return GL_LAYOUT_TRANSFER_SRC_EXT; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return GL_LAYOUT_TRANSFER_DST_EXT; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT; + default: + break; + } + UNREACHABLE(); + return GL_NONE; +} } // anonymous namespace void ContextVk::flushDescriptorSetUpdates() @@ -882,10 +831,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere mRenderPassCommandBuffer(nullptr), mCurrentGraphicsPipeline(nullptr), mCurrentGraphicsPipelineShaders(nullptr), - mCurrentGraphicsPipelineVertexInput(nullptr), - mCurrentGraphicsPipelineFragmentOutput(nullptr), mCurrentComputePipeline(nullptr), - mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum), + mCurrentDrawMode(gl::PrimitiveMode::Unused1), mCurrentWindowSurface(nullptr), mCurrentRotationDrawFramebuffer(SurfaceRotation::Identity), mCurrentRotationReadFramebuffer(SurfaceRotation::Identity), @@ -900,29 +847,30 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere mClearDepthStencilValue{}, mClearColorMasks(0), mDeferredMemoryBarriers(0), + mSampleShadingEnabled(false), mFlipYForCurrentSurface(false), mFlipViewportForDrawFramebuffer(false), mFlipViewportForReadFramebuffer(false), mIsAnyHostVisibleBufferWritten(false), mCurrentQueueSerialIndex(kInvalidQueueSerialIndex), + mInitialContextPriority(renderer->getDriverPriority(GetContextPriority(state))), + mCommandState(renderer, + vk::ConvertProtectionBoolToType(state.hasProtectedContent()), + mInitialContextPriority), mOutsideRenderPassCommands(nullptr), mRenderPassCommands(nullptr), mQueryEventType(GraphicsEventCmdBuf::NotInQueryCmd), - mGpuEventsEnabled(false), mPrimaryBufferEventCounter(0), mHasDeferredFlush(false), mHasAnyCommandsPendingSubmission(false), mIsInColorFramebufferFetchMode(false), mAllowRenderPassToReactivate(true), + mUseSizePointerForBindingVertexBuffers(false), mTotalBufferToImageCopySize(0), mEstimatedPendingImageGarbageSize(0), - mHasWaitSemaphoresPendingSubmission(false), - mGpuClockSync{std::numeric_limits::max(), std::numeric_limits::max()}, - mGpuEventTimestampOrigin(0), - mInitialContextPriority(renderer->getDriverPriority(GetContextPriority(state))), - mContextPriority(mInitialContextPriority), - mProtectionType(vk::ConvertProtectionBoolToType(state.hasProtectedContent())), - mShareGroupVk(vk::GetImpl(state.getShareGroup())) + mRenderPassCountSinceSubmit(0), + mShareGroupVk(vk::GetImpl(state.getShareGroup())), + mCommandsPendingSubmissionCount(0) { ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::ContextVk"); memset(&mClearColorValue, 0, sizeof(mClearColorValue)); @@ -946,10 +894,10 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere // begun. However, using ANGLE's SecondaryCommandBuffer, the Vulkan command buffer (which is // the primary command buffer) is not ended, so technically we don't need to rebind these. mNewGraphicsCommandBufferDirtyBits = DirtyBits{ - DIRTY_BIT_RENDER_PASS, DIRTY_BIT_COLOR_ACCESS, DIRTY_BIT_DEPTH_STENCIL_ACCESS, - DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_VERTEX_BUFFERS, - DIRTY_BIT_INDEX_BUFFER, DIRTY_BIT_SHADER_RESOURCES, DIRTY_BIT_DESCRIPTOR_SETS, - DIRTY_BIT_DRIVER_UNIFORMS, + DIRTY_BIT_RENDER_PASS, DIRTY_BIT_COLOR_ACCESS, DIRTY_BIT_DEPTH_STENCIL_ACCESS, + DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_VERTEX_BUFFERS, + DIRTY_BIT_INDEX_BUFFER, DIRTY_BIT_UNIFORM_BUFFERS, DIRTY_BIT_SHADER_RESOURCES, + DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DRIVER_UNIFORMS, }; if (getFeatures().supportsTransformFeedbackExtension.enabled || getFeatures().emulateTransformFeedback.enabled) @@ -958,8 +906,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere } mNewComputeCommandBufferDirtyBits = - DirtyBits{DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_SHADER_RESOURCES, - DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DRIVER_UNIFORMS}; + DirtyBits{DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_UNIFORM_BUFFERS, + DIRTY_BIT_SHADER_RESOURCES, DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DRIVER_UNIFORMS}; mDynamicStateDirtyBits = DirtyBits{ DIRTY_BIT_DYNAMIC_VIEWPORT, DIRTY_BIT_DYNAMIC_SCISSOR, @@ -980,6 +928,10 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere { mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_FRONT_FACE); } + if (mRenderer->getFeatures().usePrimitiveTopologyDynamicState.enabled) + { + mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_PRIMITIVE_TOPOLOGY); + } if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled) { mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE); @@ -1042,7 +994,9 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere &ContextVk::handleDirtyGraphicsPipelineBinding; mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures; mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] = - &ContextVk::handleDirtyGraphicsVertexBuffers; + getFeatures().supportsVertexInputDynamicState.enabled + ? &ContextVk::handleDirtyGraphicsVertexBuffersVertexInputDynamicStateEnabled + : &ContextVk::handleDirtyGraphicsVertexBuffersVertexInputDynamicStateDisabled; mGraphicsDirtyBitHandlers[DIRTY_BIT_INDEX_BUFFER] = &ContextVk::handleDirtyGraphicsIndexBuffer; mGraphicsDirtyBitHandlers[DIRTY_BIT_UNIFORMS] = &ContextVk::handleDirtyGraphicsUniforms; mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] = @@ -1091,6 +1045,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere &ContextVk::handleDirtyGraphicsDynamicCullMode; mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_FRONT_FACE] = &ContextVk::handleDirtyGraphicsDynamicFrontFace; + mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_PRIMITIVE_TOPOLOGY] = + &ContextVk::handleDirtyGraphicsDynamicPrimitiveTopology; mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE] = &ContextVk::handleDirtyGraphicsDynamicDepthTestEnable; mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE] = @@ -1244,30 +1200,39 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere mShareGroupRefCountedEventsGarbageRecycler = mShareGroupVk->getRefCountedEventsGarbageRecycler(); - mDeviceQueueIndex = renderer->getDeviceQueueIndex(mContextPriority); + mDeviceQueueIndex = renderer->getDeviceQueueIndex(getPriority()); + angle::PerfMonitorCounterGroupInfo vulkanGroupInfo; angle::PerfMonitorCounterGroup vulkanGroup; - vulkanGroup.name = "vulkan"; + vulkanGroupInfo.name = "vulkan"; #define ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP(COUNTER) \ - { \ - angle::PerfMonitorCounter counter; \ - counter.name = #COUNTER; \ - counter.value = 0; \ - vulkanGroup.counters.push_back(counter); \ - } + vulkanGroupInfo.counters.emplace_back(#COUNTER); \ + vulkanGroup.counters.emplace_back(0); ANGLE_VK_PERF_COUNTERS_X(ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP) #undef ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP - mPerfMonitorCounters.push_back(vulkanGroup); + mPerfMonitorCountersInfo.emplace_back(std::move(vulkanGroupInfo)); + mPerfMonitorCounters.emplace_back(std::move(vulkanGroup)); + + mCurrentGarbage.reserve(32); + + mUseSizePointerForBindingVertexBuffers = + getFeatures().forceSizePointerForBoundVertexBuffers.enabled || hasRobustAccess(); } ContextVk::~ContextVk() {} void ContextVk::onDestroy(const gl::Context *context) { + VkDevice device = getDevice(); + + ASSERT(mImagesWithTileMemory.empty()); + + mCommandState.destroy(device); + // If there is a context lost, destroy all the command buffers and resources regardless of // whether they finished execution on GPU. if (mRenderer->isDeviceLost()) @@ -1279,7 +1244,7 @@ void ContextVk::onDestroy(const gl::Context *context) mIncompleteTextures.onDestroy(context); // Flush and complete current outstanding work before destruction. - (void)finishImpl(RenderPassClosureReason::ContextDestruction); + (void)finishImpl(QueueSubmitReason::ContextDestruction); // The finish call could also generate device loss. if (mRenderer->isDeviceLost()) @@ -1290,8 +1255,6 @@ void ContextVk::onDestroy(const gl::Context *context) // Everything must be finished ASSERT(mRenderer->hasResourceUseFinished(mSubmittedResourceUse)); - VkDevice device = getDevice(); - mShareGroupVk->cleanupRefCountedEventGarbage(); mDefaultUniformStorage.release(this); @@ -1313,10 +1276,6 @@ void ContextVk::onDestroy(const gl::Context *context) mOutsideRenderPassCommands->releaseCommandPool(); mRenderPassCommands->releaseCommandPool(); - // Detach functions are only used for ring buffer allocators. - mOutsideRenderPassCommands->detachAllocator(); - mRenderPassCommands->detachAllocator(); - mRenderer->recycleOutsideRenderPassCommandBufferHelper(&mOutsideRenderPassCommands); mRenderer->recycleRenderPassCommandBufferHelper(&mRenderPassCommands); @@ -1326,12 +1285,11 @@ void ContextVk::onDestroy(const gl::Context *context) mRenderPassCache.destroy(this); mShaderLibrary.destroy(device); - mGpuEventQueryPool.destroy(device); // Must release all Vulkan secondary command buffers before destroying the pools. if ((!vk::OutsideRenderPassCommandBuffer::ExecutesInline() || !vk::RenderPassCommandBuffer::ExecutesInline()) && - mRenderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled()) + mRenderer->getFeatures().asyncGarbageCleanup.enabled) { // This will also reset Primary command buffers which is REQUIRED on some buggy Vulkan // implementations. @@ -1427,17 +1385,6 @@ angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadCont kDynamicVertexDataSize, true); } -#if ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS - angle::PlatformMethods *platform = ANGLEPlatformCurrent(); - ASSERT(platform); - - // GPU tracing workaround for anglebug.com/42261625. The renderer should not emit gpu events - // during platform discovery. - const unsigned char *gpuEventsEnabled = - platform->getTraceCategoryEnabledFlag(platform, "gpu.angle.gpu"); - mGpuEventsEnabled = gpuEventsEnabled && *gpuEventsEnabled; -#endif - // Assign initial command buffers from queue ANGLE_TRY(vk::OutsideRenderPassCommandBuffer::InitializeCommandPool( this, &mCommandPools.outsideRenderPassPool, mRenderer->getQueueFamilyIndex(), @@ -1446,10 +1393,9 @@ angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadCont this, &mCommandPools.renderPassPool, mRenderer->getQueueFamilyIndex(), getProtectionType())); ANGLE_TRY(mRenderer->getOutsideRenderPassCommandBufferHelper( - this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommandsAllocator, - &mOutsideRenderPassCommands)); - ANGLE_TRY(mRenderer->getRenderPassCommandBufferHelper( - this, &mCommandPools.renderPassPool, &mRenderPassCommandsAllocator, &mRenderPassCommands)); + this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommands)); + ANGLE_TRY(mRenderer->getRenderPassCommandBufferHelper(this, &mCommandPools.renderPassPool, + &mRenderPassCommands)); // Allocate queueSerial index and generate queue serial for commands. ANGLE_TRY(allocateQueueSerialIndex()); @@ -1458,20 +1404,6 @@ angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadCont mLastFlushedQueueSerial = QueueSerial(mCurrentQueueSerialIndex, Serial()); mLastSubmittedQueueSerial = mLastFlushedQueueSerial; - if (mGpuEventsEnabled) - { - // GPU events should only be available if timestamp queries are available. - ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0); - // Calculate the difference between CPU and GPU clocks for GPU event reporting. - ANGLE_TRY(mGpuEventQueryPool.init(this, VK_QUERY_TYPE_TIMESTAMP, - vk::kDefaultTimestampQueryPoolSize)); - ANGLE_TRY(synchronizeCpuGpuTime()); - - EventName eventName = GetTraceEventName("Primary", mPrimaryBufferEventCounter); - ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(), - TRACE_EVENT_PHASE_BEGIN, eventName)); - } - size_t minAlignment = static_cast( mRenderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment); mDefaultUniformStorage.init(mRenderer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, minAlignment, @@ -1504,6 +1436,11 @@ angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadCont } } + if (getFeatures().supportsTileMemoryHeap.enabled) + { + mImagesWithTileMemory.reserve(4); + } + return angle::Result::Continue; } @@ -1519,8 +1456,9 @@ bool ContextVk::hasSomethingToFlush() const const bool isSingleBufferedWindowWithStagedUpdates = isSingleBufferedWindowCurrent() && mCurrentWindowSurface->hasStagedUpdates(); - return (mHasAnyCommandsPendingSubmission || hasActiveRenderPass() || - !mOutsideRenderPassCommands->empty() || isSingleBufferedWindowWithStagedUpdates); + return mHasAnyCommandsPendingSubmission || hasActiveRenderPass() || + !mOutsideRenderPassCommands->empty() || isSingleBufferedWindowWithStagedUpdates || + hasForeignImagesToTransition(); } angle::Result ContextVk::flushImpl(const gl::Context *context) @@ -1542,6 +1480,26 @@ angle::Result ContextVk::flushImpl(const gl::Context *context) const bool frontBufferRenderingEnabled = isSingleBufferedWindow || drawFramebufferVk->hasFrontBufferUsage(); + // In case there is enough workload pending submission and the device is idle, we call for + // submission to keep the device busy. + uint32_t currentRPCommandCount = + mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount() + + mCommandsPendingSubmissionCount; + if (currentRPCommandCount >= kMinCommandCountToSubmit) + { + if (!mRenderer->isInFlightCommandsEmpty()) + { + ANGLE_TRY(mRenderer->checkCompletedCommands(this)); + } + + // If the device is now idle, the pending work should be submitted. + if (mRenderer->isInFlightCommandsEmpty()) + { + ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::GLFlush)); + return angle::Result::Continue; + } + } + if (hasActiveRenderPass() && !frontBufferRenderingEnabled) { mHasDeferredFlush = true; @@ -1551,10 +1509,10 @@ angle::Result ContextVk::flushImpl(const gl::Context *context) if (isSingleBufferedWindow && mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled) { - return mCurrentWindowSurface->onSharedPresentContextFlush(context); + return mCurrentWindowSurface->onSharedPresentContextFlush(this); } - return flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::GLFlush); + return flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::GLFlush); } angle::Result ContextVk::flush(const gl::Context *context) @@ -1563,7 +1521,7 @@ angle::Result ContextVk::flush(const gl::Context *context) if (!mCurrentWindowSurface || isSingleBufferedWindowCurrent()) { - ANGLE_TRY(onFramebufferBoundary(context)); + ANGLE_TRY(onFrameBoundary(context)); } return angle::Result::Continue; @@ -1576,27 +1534,25 @@ angle::Result ContextVk::finish(const gl::Context *context) if (mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled && singleBufferedFlush) { - ANGLE_TRY(mCurrentWindowSurface->onSharedPresentContextFlush(context)); + ANGLE_TRY(mCurrentWindowSurface->onSharedPresentContextFlush(this)); // While call above performs implicit flush, don't skip |finishImpl| below, since we still // need to wait for submitted commands. } - ANGLE_TRY(finishImpl(RenderPassClosureReason::GLFinish)); - - syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters()); + ANGLE_TRY(finishImpl(QueueSubmitReason::GLFinish)); if (!mCurrentWindowSurface || singleBufferedFlush) { - ANGLE_TRY(onFramebufferBoundary(context)); + ANGLE_TRY(onFrameBoundary(context)); } return angle::Result::Continue; } -angle::Result ContextVk::onFramebufferBoundary(const gl::Context *contextGL) +angle::Result ContextVk::onFrameBoundary(const gl::Context *contextGL) { - mShareGroupVk->onFramebufferBoundary(); - return mRenderer->syncPipelineCacheVk(this, mRenderer->getGlobalOps(), contextGL); + mShareGroupVk->onFrameBoundary(); + return mRenderer->onFrameBoundary(contextGL); } angle::Result ContextVk::setupDraw(const gl::Context *context, @@ -1611,9 +1567,18 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, // Set any dirty bits that depend on draw call parameters or other objects. if (mode != mCurrentDrawMode) { - invalidateCurrentGraphicsPipeline(); - mCurrentDrawMode = mode; - mGraphicsPipelineDesc->updateTopology(&mGraphicsPipelineTransition, mCurrentDrawMode); + updateTopology(mode); + } + + // Submit pending commands if the number of write-commands in the current render pass reaches a + // threshold to avoid delaying the submission too much. + if (ANGLE_UNLIKELY(mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount() > + mRenderer->getMinRenderPassWriteCommandCountToEarlySubmit()) && + (mCommandsPendingSubmissionCount > 0)) + { + ANGLE_TRY( + submitCommands(nullptr, nullptr, QueueSubmitReason::RenderPassCommandLimitReached)); + mCommandsPendingSubmissionCount = 0; } // Must be called before the command buffer is started. Can call finish. @@ -1689,7 +1654,7 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, } VertexArrayVk *vertexArrayVk = getVertexArray(); - const gl::Buffer *elementArrayBuffer = vertexArrayVk->getState().getElementArrayBuffer(); + const gl::Buffer *elementArrayBuffer = vertexArrayVk->getElementArrayBuffer(); if (!elementArrayBuffer) { BufferBindingDirty bindingDirty; @@ -1736,8 +1701,7 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, mRenderer->hasResourceUseFinished(bufferHelper.getResourceUse())) { uint8_t *src = nullptr; - ANGLE_TRY( - bufferVk->mapImpl(this, GL_MAP_READ_BIT, reinterpret_cast(&src))); + ANGLE_TRY(bufferVk->mapForReadAccessOnly(this, reinterpret_cast(&src))); // Note: bufferOffset is not added here because mapImpl already adds it. src += reinterpret_cast(indices); const size_t byteCount = static_cast(elementArrayBuffer->getSize()) - @@ -1745,7 +1709,7 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, BufferBindingDirty bindingDirty; ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, byteCount, src, &bindingDirty)); - ANGLE_TRY(bufferVk->unmapImpl(this)); + ANGLE_TRY(bufferVk->unmapReadAccessOnly(this)); } else { @@ -1848,6 +1812,10 @@ angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context, vk::BufferHelper *indexBufferHelperOut = nullptr; vk::BufferHelper *indirectBufferHelperOut = nullptr; + // Reset the index buffer offset + mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER); + mCurrentIndexBufferOffset = 0; + VertexArrayVk *vertexArrayVk = getVertexArray(); ANGLE_TRY(vertexArrayVk->handleLineLoopIndirectDraw(context, indirectBuffer, indirectBufferOffset, &indexBufferHelperOut, @@ -2141,15 +2109,19 @@ angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator * DirtyBits dirtyBitMask) { ASSERT(mDirtyDefaultAttribsMask.any()); - - gl::AttributesMask attribsMask = - mDirtyDefaultAttribsMask & mState.getProgramExecutable()->getAttributesMask(); VertexArrayVk *vertexArrayVk = getVertexArray(); + + gl::AttributesMask attribsMask = mDirtyDefaultAttribsMask; + attribsMask &= ~vertexArrayVk->getCurrentEnabledAttribsMask(); + attribsMask &= mState.getProgramExecutable()->getAttributesMask(); + for (size_t attribIndex : attribsMask) { ANGLE_TRY(vertexArrayVk->updateDefaultAttrib(this, attribIndex)); } + ANGLE_TRY(onVertexArrayChange(attribsMask)); + mDirtyDefaultAttribsMask.reset(); return angle::Result::Continue; } @@ -2179,8 +2151,8 @@ angle::Result ContextVk::createGraphicsPipeline() // - If VK_EXT_graphics_pipeline_library is not supported, create a new monolithic pipeline // - If VK_EXT_graphics_pipeline_library is supported: // * Create the Shaders subset of the pipeline through the program executable - // * Create the VertexInput and FragmentOutput subsets - // * Link them together through the program executable + // * Create the complete pipeline by providing the VertexInput and FragmentOutput states as + // well as the Shaders library. if (mCurrentGraphicsPipeline == nullptr) { // Not found in cache @@ -2195,13 +2167,8 @@ angle::Result ContextVk::createGraphicsPipeline() { const vk::GraphicsPipelineTransitionBits kShadersTransitionBitsMask = vk::GetGraphicsPipelineTransitionBitsMask(vk::GraphicsPipelineSubset::Shaders); - const vk::GraphicsPipelineTransitionBits kVertexInputTransitionBitsMask = - vk::GetGraphicsPipelineTransitionBitsMask(vk::GraphicsPipelineSubset::VertexInput); - const vk::GraphicsPipelineTransitionBits kFragmentOutputTransitionBitsMask = - vk::GetGraphicsPipelineTransitionBitsMask( - vk::GraphicsPipelineSubset::FragmentOutput); - // Recreate the shaders subset if necessary + // Recreate the Shaders subset if necessary const vk::GraphicsPipelineTransitionBits shadersTransitionBits = mGraphicsPipelineLibraryTransition & kShadersTransitionBitsMask; if (mCurrentGraphicsPipelineShaders == nullptr || shadersTransitionBits.any()) @@ -2239,44 +2206,11 @@ angle::Result ContextVk::createGraphicsPipeline() } } - // If blobs are reused between the pipeline libraries and the monolithic pipelines (so - // |mergeProgramPipelineCachesToGlobalCache| would be enabled because merging the - // pipelines would be beneficial), directly use the global cache for the vertex input - // and fragment output pipelines. This _may_ cause stalls as the worker thread that - // creates pipelines is also holding the same lock. - // - // On the other hand, if there is not going to be any reuse of blobs, use a private - // pipeline cache to avoid the aforementioned potential stall. - vk::PipelineCacheAccess interfacePipelineCacheStorage; - vk::PipelineCacheAccess *interfacePipelineCache = &pipelineCache; - if (!getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled) - { - ANGLE_TRY(ensureInterfacePipelineCache()); - interfacePipelineCacheStorage.init(&mInterfacePipelinesCache, nullptr); - interfacePipelineCache = &interfacePipelineCacheStorage; - } - - // Recreate the vertex input subset if necessary - ANGLE_TRY(CreateGraphicsPipelineSubset( - this, *mGraphicsPipelineDesc, - mGraphicsPipelineLibraryTransition & kVertexInputTransitionBitsMask, - GraphicsPipelineSubsetRenderPass::Unused, - mShareGroupVk->getVertexInputGraphicsPipelineCache(), interfacePipelineCache, - &mCurrentGraphicsPipelineVertexInput)); - - // Recreate the fragment output subset if necessary - ANGLE_TRY(CreateGraphicsPipelineSubset( - this, *mGraphicsPipelineDesc, - mGraphicsPipelineLibraryTransition & kFragmentOutputTransitionBitsMask, - GraphicsPipelineSubsetRenderPass::Required, - mShareGroupVk->getFragmentOutputGraphicsPipelineCache(), interfacePipelineCache, - &mCurrentGraphicsPipelineFragmentOutput)); - - // Link the three subsets into one pipeline. - ANGLE_TRY(executableVk->linkGraphicsPipelineLibraries( - this, &pipelineCache, *mGraphicsPipelineDesc, mCurrentGraphicsPipelineVertexInput, - mCurrentGraphicsPipelineShaders, mCurrentGraphicsPipelineFragmentOutput, &descPtr, - &mCurrentGraphicsPipeline)); + // Link the shaders subset into a complete pipeline that includes vertex input and + // fragment output subsets. + ANGLE_TRY(executableVk->createLinkedGraphicsPipeline( + this, &pipelineCache, *mGraphicsPipelineDesc, mCurrentGraphicsPipelineShaders, + &descPtr, &mCurrentGraphicsPipeline)); // Reset the transition bits for pipeline libraries, they are only made to be up-to-date // here. @@ -2429,7 +2363,8 @@ angle::Result ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode( angle::Result ContextVk::handleDirtyAnySamplePassedQueryEnd(DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask) { - if (mRenderPassCommands->started()) + // If we are using tile memory, don't enable this optimization to prevent fallback. + if (mRenderPassCommands->started() && mImagesWithTileMemory.empty()) { // When we switch from query enabled draw to query disabled draw, we do immediate flush to // ensure the query result will be ready early so that application thread calling @@ -2632,11 +2567,11 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( // layers. Therefore we can't verify it has no staged updates right here. vk::ImageHelper &image = textureVk->getImage(); - const vk::ImageLayout imageLayout = - GetImageReadLayout(textureVk, *executable, textureUnit, pipelineType); + const vk::ImageAccess imageAccess = + GetImageReadAccess(textureVk, *executable, textureUnit, pipelineType); // Ensure the image is in the desired layout - commandBufferHelper->imageRead(this, image.getAspectFlags(), imageLayout, &image); + commandBufferHelper->imageRead(this, image.getAspectFlags(), imageAccess, &image); } if (executable->hasTextures()) @@ -2661,113 +2596,169 @@ angle::Result ContextVk::handleDirtyComputeTextures(DirtyBits::Iterator *dirtyBi return handleDirtyTexturesImpl(mOutsideRenderPassCommands, PipelineType::Compute); } -angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator, - DirtyBits dirtyBitMask) +angle::Result ContextVk::handleDirtyGraphicsVertexBuffersVertexInputDynamicStateEnabled( + DirtyBits::Iterator *dirtyBitsIterator, + DirtyBits dirtyBitMask) { + ASSERT(getFeatures().supportsVertexInputDynamicState.enabled); const gl::ProgramExecutable *executable = mState.getProgramExecutable(); VertexArrayVk *vertexArrayVk = getVertexArray(); - uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation(); + const uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation(); const gl::AttribArray &bufferHandles = vertexArrayVk->getCurrentArrayBufferHandles(); const gl::AttribArray &bufferOffsets = vertexArrayVk->getCurrentArrayBufferOffsets(); + const gl::ComponentTypeMask vertexAttributesTypeMask = + vertexArrayVk->getCurrentVertexAttributesTypeMask(); + const gl::ComponentTypeMask &programAttribsTypeMask = executable->getAttributesTypeMask(); - if (mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled || - getFeatures().supportsVertexInputDynamicState.enabled) + if (ANGLE_LIKELY(vertexAttributesTypeMask == programAttribsTypeMask)) { - const gl::AttribArray &bufferStrides = - vertexArrayVk->getCurrentArrayBufferStrides(); - const gl::AttribArray &bufferFormats = - vertexArrayVk->getCurrentArrayBufferFormats(); - gl::AttribArray strides = {}; - const gl::AttribArray &bufferDivisors = - vertexArrayVk->getCurrentArrayBufferDivisors(); - const gl::AttribArray &bufferRelativeOffsets = - vertexArrayVk->getCurrentArrayBufferRelativeOffsets(); - const gl::AttributesMask &bufferCompressed = - vertexArrayVk->getCurrentArrayBufferCompressed(); - - gl::AttribVector bindingDescs; - gl::AttribVector attributeDescs; + const gl::AttribArray &bindingDescs = + vertexArrayVk->getVertexInputBindingDescs(); + const gl::AttribArray &attributeDescs = + vertexArrayVk->getVertexInputAttribDescs(); + + mRenderPassCommandBuffer->setVertexInput(maxAttrib, bindingDescs.data(), maxAttrib, + attributeDescs.data()); + } + else + { + // Make a local copy of descs and patch the mismatched attributes + gl::AttribArray bindingDescs; + gl::AttribArray attributeDescs; + + memcpy(bindingDescs.data(), vertexArrayVk->getVertexInputBindingDescs().data(), + maxAttrib * sizeof(VkVertexInputBindingDescription2EXT)); + memcpy(attributeDescs.data(), vertexArrayVk->getVertexInputAttribDescs().data(), + maxAttrib * sizeof(VkVertexInputAttributeDescription2EXT)); - // Set stride to 0 for mismatching formats between the program's declared attribute and that - // which is specified in glVertexAttribPointer. See comment in vk_cache_utils.cpp - // (initializePipeline) for more details. const gl::AttributesMask &activeAttribLocations = executable->getNonBuiltinAttribLocationsMask(); - const gl::ComponentTypeMask &programAttribsTypeMask = executable->getAttributesTypeMask(); - for (size_t attribIndex : activeAttribLocations) { - const angle::Format &intendedFormat = - mRenderer->getFormat(bufferFormats[attribIndex]).getIntendedFormat(); - - const gl::ComponentType attribType = GetVertexAttributeComponentType( - intendedFormat.isPureInt(), intendedFormat.vertexAttribType); + const gl::ComponentType attribType = + gl::GetComponentTypeMask(vertexAttributesTypeMask, attribIndex); const gl::ComponentType programAttribType = gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex); - const bool mismatchingType = - attribType != programAttribType && (programAttribType == gl::ComponentType::Float || - attribType == gl::ComponentType::Float); - strides[attribIndex] = mismatchingType ? 0 : bufferStrides[attribIndex]; - - if (getFeatures().supportsVertexInputDynamicState.enabled) + // Set stride to 0 for mismatching formats between the program's declared attribute and + // that which is specified in glVertexAttribPointer. See comment in vk_cache_utils.cpp + // (initializePipeline) for more details. + const bool mismatchingType = attribType != programAttribType; + if (mismatchingType) { - VkVertexInputBindingDescription2EXT bindingDesc = {}; - VkVertexInputAttributeDescription2EXT attribDesc = {}; - bindingDesc.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT; - bindingDesc.binding = static_cast(attribIndex); - bindingDesc.stride = static_cast(strides[attribIndex]); - bindingDesc.divisor = - bufferDivisors[attribIndex] > mRenderer->getMaxVertexAttribDivisor() - ? 1 - : bufferDivisors[attribIndex]; - if (bindingDesc.divisor != 0) + angle::FormatID originalFormatID = + vertexArrayVk->getCurrentArrayBufferFormatID(attribIndex); + + if (programAttribType == gl::ComponentType::Float || + attribType == gl::ComponentType::Float) { - bindingDesc.inputRate = - static_cast(VK_VERTEX_INPUT_RATE_INSTANCE); + bindingDescs[attribIndex].stride = 0; + angle::FormatID patchFormatID = + vk::PatchVertexAttribComponentType(originalFormatID, programAttribType); + attributeDescs[attribIndex].format = + mRenderer->getFormat(patchFormatID).getActualBufferVkFormat(mRenderer); } else { - bindingDesc.inputRate = - static_cast(VK_VERTEX_INPUT_RATE_VERTEX); - // Divisor value is ignored by the implementation when using - // VK_VERTEX_INPUT_RATE_VERTEX, but it is set to 1 to avoid a validation error - // due to a validation layer issue. - bindingDesc.divisor = 1; + const vk::Format &format = mRenderer->getFormat(originalFormatID); + const angle::Format &intendedFormat = format.getIntendedFormat(); + // When converting from an unsigned to a signed format or vice versa, attempt to + // match the bit width. + angle::FormatID convertedFormatID = gl::ConvertFormatSignedness(intendedFormat); + const vk::Format &convertedFormat = mRenderer->getFormat(convertedFormatID); + attributeDescs[attribIndex].format = + convertedFormat.getActualBufferVkFormat(mRenderer); } + } + } - attribDesc.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT; - attribDesc.binding = static_cast(attribIndex); - attribDesc.format = vk::GraphicsPipelineDesc::getPipelineVertexInputStateFormat( - this, bufferFormats[attribIndex], bufferCompressed[attribIndex], - programAttribType, static_cast(attribIndex)); - attribDesc.location = static_cast(attribIndex); - attribDesc.offset = bufferRelativeOffsets[attribIndex]; + mRenderPassCommandBuffer->setVertexInput(maxAttrib, bindingDescs.data(), maxAttrib, + attributeDescs.data()); + } - bindingDescs.push_back(bindingDesc); - attributeDescs.push_back(attribDesc); + if (maxAttrib > 0) + { + if (getFeatures().supportsBindVertexBuffers2.enabled) + { + // Since the strides are already set in setVertexInput(), they need not be set here. + if (mUseSizePointerForBindingVertexBuffers) + { + const gl::AttribArray &bufferSizes = + vertexArrayVk->getCurrentArrayBufferSizes(); + mRenderPassCommandBuffer->bindVertexBuffers2NoStride( + 0, maxAttrib, bufferHandles.data(), bufferOffsets.data(), bufferSizes.data()); } + else + { + mRenderPassCommandBuffer->bindVertexBuffers2NoSizeNoStride( + 0, maxAttrib, bufferHandles.data(), bufferOffsets.data()); + } + } + else + { + mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(), + bufferOffsets.data()); } + } + // Mark all active vertex buffers as accessed. + mRenderPassCommands->buffersVertexAttribRead(this, vertexArrayVk->getCurrentArrayBuffers(), + maxAttrib); + + return angle::Result::Continue; +} + +angle::Result ContextVk::handleDirtyGraphicsVertexBuffersVertexInputDynamicStateDisabled( + DirtyBits::Iterator *dirtyBitsIterator, + DirtyBits dirtyBitMask) +{ + ASSERT(!getFeatures().supportsVertexInputDynamicState.enabled); + const gl::ProgramExecutable *executable = mState.getProgramExecutable(); + VertexArrayVk *vertexArrayVk = getVertexArray(); + const uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation(); + const gl::AttribArray &bufferHandles = vertexArrayVk->getCurrentArrayBufferHandles(); + const gl::AttribArray &bufferOffsets = + vertexArrayVk->getCurrentArrayBufferOffsets(); + + if (getFeatures().useVertexInputBindingStrideDynamicState.enabled) + { + // Set stride to 0 for mismatching formats between the program's declared attribute and that + // which is specified in glVertexAttribPointer. See comment in vk_cache_utils.cpp + // (initializePipeline) for more details. + const gl::AttributesMask &activeAttribLocations = + executable->getNonBuiltinAttribLocationsMask(); + const gl::ComponentTypeMask vertexAttributesTypeMask = + vertexArrayVk->getCurrentVertexAttributesTypeMask(); + const gl::ComponentTypeMask &programAttribsTypeMask = executable->getAttributesTypeMask(); + gl::AttribArray strides = {}; - if (getFeatures().supportsVertexInputDynamicState.enabled) + for (size_t attribIndex : activeAttribLocations) { - mRenderPassCommandBuffer->setVertexInput( - static_cast(bindingDescs.size()), bindingDescs.data(), - static_cast(attributeDescs.size()), attributeDescs.data()); - if (bindingDescs.size() != 0) - { + const gl::ComponentType attribType = + gl::GetComponentTypeMask(vertexAttributesTypeMask, attribIndex); + const gl::ComponentType programAttribType = + gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex); - mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(), - bufferOffsets.data()); - } + const bool mismatchingType = + attribType != programAttribType && (programAttribType == gl::ComponentType::Float || + attribType == gl::ComponentType::Float); + strides[attribIndex] = + mismatchingType ? 0 : vertexArrayVk->getCurrentArrayBufferStride(attribIndex); + } + + ASSERT(getFeatures().supportsBindVertexBuffers2.enabled); + if (mUseSizePointerForBindingVertexBuffers) + { + const gl::AttribArray &bufferSizes = + vertexArrayVk->getCurrentArrayBufferSizes(); + mRenderPassCommandBuffer->bindVertexBuffers2(0, maxAttrib, bufferHandles.data(), + bufferOffsets.data(), bufferSizes.data(), + strides.data()); } else { - // TODO: Use the sizes parameters here to fix the robustness issue worked around in - // crbug.com/1310038 - mRenderPassCommandBuffer->bindVertexBuffers2( - 0, maxAttrib, bufferHandles.data(), bufferOffsets.data(), nullptr, strides.data()); + mRenderPassCommandBuffer->bindVertexBuffers2NoSize( + 0, maxAttrib, bufferHandles.data(), bufferOffsets.data(), strides.data()); } } else @@ -2776,19 +2767,9 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *d bufferOffsets.data()); } - const gl::AttribArray &arrayBufferResources = - vertexArrayVk->getCurrentArrayBuffers(); - // Mark all active vertex buffers as accessed. - for (uint32_t attribIndex = 0; attribIndex < maxAttrib; ++attribIndex) - { - vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex]; - if (arrayBuffer) - { - mRenderPassCommands->bufferRead(this, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - vk::PipelineStage::VertexInput, arrayBuffer); - } - } + mRenderPassCommands->buffersVertexAttribRead(this, vertexArrayVk->getCurrentArrayBuffers(), + maxAttrib); return angle::Result::Continue; } @@ -2799,12 +2780,27 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dir vk::BufferHelper *elementArrayBuffer = mCurrentIndexBuffer; ASSERT(elementArrayBuffer != nullptr); - VkDeviceSize bufferOffset; - const vk::Buffer &buffer = elementArrayBuffer->getBufferForVertexArray( - this, elementArrayBuffer->getSize(), &bufferOffset); + if (getFeatures().supportsMaintenance5.enabled) + { + // The bound size is from the start offset to the end of the element buffer, and should be + // aligned to the element type byte size. + VkDeviceSize alignedSize = + roundDownPow2(elementArrayBuffer->getSize() - mCurrentIndexBufferOffset, + static_cast(1 << ToUnderlying(mCurrentDrawElementsType))); + mRenderPassCommandBuffer->bindIndexBuffer2( + elementArrayBuffer->getBuffer(), + elementArrayBuffer->getOffset() + mCurrentIndexBufferOffset, alignedSize, + getVkIndexType(mCurrentDrawElementsType)); + } + else + { + VkDeviceSize bufferOffset; + const vk::Buffer &buffer = elementArrayBuffer->getIndexBufferForVertexArray( + this, elementArrayBuffer->getSize(), &bufferOffset); - mRenderPassCommandBuffer->bindIndexBuffer(buffer, bufferOffset + mCurrentIndexBufferOffset, - getVkIndexType(mCurrentDrawElementsType)); + mRenderPassCommandBuffer->bindIndexBuffer(buffer, bufferOffset + mCurrentIndexBufferOffset, + getVkIndexType(mCurrentDrawElementsType)); + } mRenderPassCommands->bufferRead(this, VK_ACCESS_INDEX_READ_BIT, vk::PipelineStage::VertexInput, elementArrayBuffer); @@ -2856,103 +2852,24 @@ angle::Result ContextVk::handleDirtyShaderResourcesImpl(CommandBufferHelperT *co { const gl::ProgramExecutable *executable = mState.getProgramExecutable(); ASSERT(executable); - - // DIRTY_BIT_UNIFORM_BUFFERS is set when uniform buffer bindings change. - // DIRTY_BIT_SHADER_RESOURCES gets set when the program executable has changed. In that case, - // this function will update entire the shader resource descriptorSet. This means there is no - // need to process uniform buffer bindings again. - dirtyBitsIterator->resetLaterBit(DIRTY_BIT_UNIFORM_BUFFERS); - - // This function processes uniform buffers, so it doesn't matter which are dirty. The following - // makes sure the dirty bits are reset. - mState.getAndResetDirtyUniformBlocks(); - - const bool hasImages = executable->hasImages(); - const bool hasStorageBuffers = executable->hasStorageBuffers(); - const bool hasAtomicCounterBuffers = executable->hasAtomicCounterBuffers(); - const bool hasUniformBuffers = executable->hasUniformBuffers(); - const bool hasFramebufferFetch = executable->usesColorFramebufferFetch() || - executable->usesDepthFramebufferFetch() || - executable->usesStencilFramebufferFetch(); - - if (!hasUniformBuffers && !hasStorageBuffers && !hasAtomicCounterBuffers && !hasImages && - !hasFramebufferFetch) - { - return angle::Result::Continue; - } - - const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits; - ProgramExecutableVk *executableVk = vk::GetImpl(executable); - const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap(); - - mShaderBufferWriteDescriptorDescs = executableVk->getShaderResourceWriteDescriptorDescs(); - // Update writeDescriptorDescs with inputAttachments - mShaderBufferWriteDescriptorDescs.updateInputAttachments( - *executable, variableInfoMap, vk::GetImpl(mState.getDrawFramebuffer())); - - mShaderBuffersDescriptorDesc.resize( - mShaderBufferWriteDescriptorDescs.getTotalDescriptorCount()); - if (hasUniformBuffers) - { - mShaderBuffersDescriptorDesc.updateShaderBuffers( - this, commandBufferHelper, *executable, variableInfoMap, - mState.getOffsetBindingPointerUniformBuffers(), executable->getUniformBlocks(), - executableVk->getUniformBufferDescriptorType(), limits.maxUniformBufferRange, - mEmptyBuffer, mShaderBufferWriteDescriptorDescs, mDeferredMemoryBarriers); - } - if (hasStorageBuffers) - { - mShaderBuffersDescriptorDesc.updateShaderBuffers( - this, commandBufferHelper, *executable, variableInfoMap, - mState.getOffsetBindingPointerShaderStorageBuffers(), - executable->getShaderStorageBlocks(), executableVk->getStorageBufferDescriptorType(), - limits.maxStorageBufferRange, mEmptyBuffer, mShaderBufferWriteDescriptorDescs, - mDeferredMemoryBarriers); - } - if (hasAtomicCounterBuffers) - { - mShaderBuffersDescriptorDesc.updateAtomicCounters( - this, commandBufferHelper, *executable, variableInfoMap, - mState.getOffsetBindingPointerAtomicCounterBuffers(), - executable->getAtomicCounterBuffers(), limits.minStorageBufferOffsetAlignment, - mEmptyBuffer, mShaderBufferWriteDescriptorDescs); - } - if (hasImages) + if (executable->hasImages()) { + // Update active images ANGLE_TRY(updateActiveImages(commandBufferHelper)); - ANGLE_TRY(mShaderBuffersDescriptorDesc.updateImages(this, *executable, variableInfoMap, - mActiveImages, mState.getImageUnits(), - mShaderBufferWriteDescriptorDescs)); } - if (hasFramebufferFetch) - { - ANGLE_TRY(mShaderBuffersDescriptorDesc.updateInputAttachments( - this, *executable, variableInfoMap, vk::GetImpl(mState.getDrawFramebuffer()), - mShaderBufferWriteDescriptorDescs)); - } - - mDeferredMemoryBarriers = 0; - vk::SharedDescriptorSetCacheKey newSharedCacheKey; - ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet( - this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(), - mShaderBufferWriteDescriptorDescs, mShaderBuffersDescriptorDesc, &newSharedCacheKey)); - - if (newSharedCacheKey) - { - // A new cache entry has been created. We record this cache key in the images and buffers so - // that the descriptorSet cache can be destroyed when buffer/image is destroyed. - updateShaderResourcesWithSharedCacheKey(newSharedCacheKey); - } - - // Record usage of storage buffers and images in the command buffer to aid handling of - // glMemoryBarrier. - if (hasImages || hasStorageBuffers || hasAtomicCounterBuffers) - { - commandBufferHelper->setHasShaderStorageOutput(); - } + ProgramExecutableVk *executableVk = vk::GetImpl(executable); + ASSERT(executableVk); + const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits; + GLbitfield memoryBarriers = mDeferredMemoryBarriers; + mDeferredMemoryBarriers = 0; - return angle::Result::Continue; + return executableVk->updateShaderResourcesDescInfo( + this, commandBufferHelper, vk::GetImpl(mState.getDrawFramebuffer()), + mState.getOffsetBindingPointerShaderStorageBuffers(), + mState.getOffsetBindingPointerAtomicCounterBuffers(), limits, mEmptyBuffer, memoryBarriers, + mActiveImages, mState.getImageUnits(), getCurrentFrameCount(), + mShareGroupVk->getUpdateDescriptorSetsBuilder()); } angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator, @@ -2968,43 +2885,50 @@ angle::Result ContextVk::handleDirtyComputeShaderResources(DirtyBits::Iterator * dirtyBitsIterator); } -template -angle::Result ContextVk::handleDirtyUniformBuffersImpl(CommandBufferT *commandBufferHelper) +void ContextVk::updateUniformBufferBlocksOffset() { gl::ProgramExecutable *executable = mState.getProgramExecutable(); ASSERT(executable); ASSERT(executable->hasUniformBuffers()); + ProgramExecutableVk *executableVk = vk::GetImpl(executable); + ASSERT(executableVk); + ASSERT(executableVk->usesDynamicUniformBufferDescriptors()); - const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits; - ProgramExecutableVk *executableVk = vk::GetImpl(executable); - const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap(); - - gl::ProgramUniformBlockMask dirtyBits = mState.getAndResetDirtyUniformBlocks(); - for (size_t blockIndex : dirtyBits) + gl::ProgramUniformBlockMask dirtyBlocks = + mState.getAndResetDirtyUniformBlocks() & executable->getActiveUniformBufferBlocks(); + for (size_t blockIndex : dirtyBlocks) { const GLuint binding = executable->getUniformBlockBinding(blockIndex); - mShaderBuffersDescriptorDesc.updateOneShaderBuffer( - this, commandBufferHelper, variableInfoMap, - mState.getOffsetBindingPointerUniformBuffers(), - executable->getUniformBlocks()[blockIndex], binding, - executableVk->getUniformBufferDescriptorType(), limits.maxUniformBufferRange, - mEmptyBuffer, mShaderBufferWriteDescriptorDescs, mDeferredMemoryBarriers); + executableVk->updateOneUniformBufferOffset( + blockIndex, mState.getOffsetBindingPointerUniformBuffers()[binding]); } - vk::SharedDescriptorSetCacheKey newSharedCacheKey; - ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet( - this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(), - mShaderBufferWriteDescriptorDescs, mShaderBuffersDescriptorDesc, &newSharedCacheKey)); + // Mark descriptor sets dirty + mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS); +} - if (newSharedCacheKey) +template +angle::Result ContextVk::handleDirtyUniformBuffersImpl(CommandBufferT *commandBufferHelper) +{ + gl::ProgramExecutable *executable = mState.getProgramExecutable(); + ASSERT(executable); + + // Processes all uniform buffer blocks irrespective of dirty state. + // Reset dirty bits + mState.getAndResetDirtyUniformBlocks(); + + if (!executable->hasUniformBuffers()) { - // A new cache entry has been created. We record this cache key in the images and - // buffers so that the descriptorSet cache can be destroyed when buffer/image is - // destroyed. - updateShaderResourcesWithSharedCacheKey(newSharedCacheKey); + return angle::Result::Continue; } - return angle::Result::Continue; + const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits; + ProgramExecutableVk *executableVk = vk::GetImpl(executable); + + return executableVk->updateUniformBuffersDescInfo( + this, commandBufferHelper, mState.getOffsetBindingPointerUniformBuffers(), + limits.maxUniformBufferRange, mEmptyBuffer, getCurrentFrameCount(), + mShareGroupVk->getUpdateDescriptorSetsBuilder()); } angle::Result ContextVk::handleDirtyGraphicsUniformBuffers(DirtyBits::Iterator *dirtyBitsIterator, @@ -3052,29 +2976,10 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation( ProgramExecutableVk *executableVk = vk::GetImpl(executable); vk::BufferHelper *currentUniformBuffer = mDefaultUniformStorage.getCurrentBuffer(); - const vk::WriteDescriptorDescs &writeDescriptorDescs = - executableVk->getDefaultUniformWriteDescriptorDescs(transformFeedbackVk); - - vk::DescriptorSetDescBuilder uniformsAndXfbDesc(writeDescriptorDescs.getTotalDescriptorCount()); - uniformsAndXfbDesc.updateUniformsAndXfb( - this, *executable, writeDescriptorDescs, currentUniformBuffer, mEmptyBuffer, - mState.isTransformFeedbackActiveUnpaused(), transformFeedbackVk); - - vk::SharedDescriptorSetCacheKey newSharedCacheKey; - ANGLE_TRY(executableVk->updateUniformsAndXfbDescriptorSet( - this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(), - writeDescriptorDescs, currentUniformBuffer, &uniformsAndXfbDesc, &newSharedCacheKey)); - - if (newSharedCacheKey) - { - if (currentUniformBuffer) - { - currentUniformBuffer->getBufferBlock()->onNewDescriptorSet(newSharedCacheKey); - } - transformFeedbackVk->onNewDescriptorSet(*executable, newSharedCacheKey); - } - - return angle::Result::Continue; + return executableVk->updateUniformsAndXfbDescInfo( + this, currentUniformBuffer, mEmptyBuffer, getCurrentFrameCount(), + mShareGroupVk->getUpdateDescriptorSetsBuilder(), mState.isTransformFeedbackActiveUnpaused(), + transformFeedbackVk); } angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension( @@ -3304,6 +3209,14 @@ angle::Result ContextVk::handleDirtyGraphicsDynamicFrontFace(DirtyBits::Iterator return angle::Result::Continue; } +angle::Result ContextVk::handleDirtyGraphicsDynamicPrimitiveTopology( + DirtyBits::Iterator *dirtyBitsIterator, + DirtyBits dirtyBitMask) +{ + mRenderPassCommandBuffer->setPrimitiveTopology(gl_vk::GetPrimitiveTopology(mCurrentDrawMode)); + return angle::Result::Continue; +} + angle::Result ContextVk::handleDirtyGraphicsDynamicDepthTestEnable( DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask) @@ -3411,17 +3324,40 @@ angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate( DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask) { + // Shading rate may be set either via QCOM_shading_rate or EXT_fragment_shading_rate, which are + // in conflict. Given EXT_fragment_shading_rate is more comprehensive, shading rate from that + // extension is used if set, with fall back to QCOM_shading_rate otherwise. + gl::ShadingRate shadingRate = getState().getShadingRateEXT(); + const bool isQCOM = shadingRate == gl::ShadingRate::_1x1; + if (isQCOM) + { + shadingRate = getState().getShadingRateQCOM(); + if (shadingRate == gl::ShadingRate::Undefined) + { + // Shading rate has not been set. Since this is dynamic state, set it to 1x1. Note that + // getShadingRateEXT doesn't return Undefined, only the QCOM version does. + shadingRate = gl::ShadingRate::_1x1; + } + } + ASSERT(shadingRate != gl::ShadingRate::Undefined); + + // If FETCH_PER_SAMPLE_ARM is enabled, the fragment shading rate is set to 1x1. Similarly, if + // foveation is enabled, the fragment shading rate should be set to 1x1 FramebufferVk *drawFramebufferVk = vk::GetImpl(mState.getDrawFramebuffer()); const bool isFoveationEnabled = drawFramebufferVk->isFoveationEnabled(); - gl::ShadingRate shadingRate = - isFoveationEnabled ? gl::ShadingRate::_1x1 : getState().getShadingRate(); - if (shadingRate == gl::ShadingRate::Undefined) + if (getState().getFetchPerSample() || isFoveationEnabled) { - // Shading rate has not been set. Since this is dynamic state, set it to 1x1 shadingRate = gl::ShadingRate::_1x1; } + // With the QCOM extension, some shading rates are optional but there is no way to query them. + // The code is expected to automatically fall back to a supported rate. With EXT, the rates are + // validated to be supported. + // + // The 1x1, 1x2, 2x1 and 2x2 rates are required by ANGLE before exposing either extension. The + // QCOM extension only exposes 4x2 and 4x4 additionally, which may need a fallback. The other + // 4x rates are exposed only in the EXT extension. const bool shadingRateSupported = mRenderer->isShadingRateSupported(shadingRate); VkExtent2D fragmentSize = {}; @@ -3437,6 +3373,11 @@ angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate( fragmentSize.width = 1; fragmentSize.height = 2; break; + case gl::ShadingRate::_1x4: + ASSERT(shadingRateSupported); + fragmentSize.width = 1; + fragmentSize.height = 4; + break; case gl::ShadingRate::_2x1: ASSERT(shadingRateSupported); fragmentSize.width = 2; @@ -3447,7 +3388,18 @@ angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate( fragmentSize.width = 2; fragmentSize.height = 2; break; + case gl::ShadingRate::_2x4: + ASSERT(shadingRateSupported); + fragmentSize.width = 2; + fragmentSize.height = 4; + break; + case gl::ShadingRate::_4x1: + ASSERT(shadingRateSupported); + fragmentSize.width = 4; + fragmentSize.height = 1; + break; case gl::ShadingRate::_4x2: + ASSERT(shadingRateSupported || isQCOM); if (shadingRateSupported) { fragmentSize.width = 4; @@ -3461,6 +3413,7 @@ angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate( } break; case gl::ShadingRate::_4x4: + ASSERT(shadingRateSupported || isQCOM); if (shadingRateSupported) { fragmentSize.width = 4; @@ -3478,11 +3431,37 @@ angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate( return angle::Result::Stop; } + // Note: Combiner ops are KEEP by default, and don't exist with the QCOM extension. + const std::array &combinerOps = getState().getShadingRateCombinerOps(); + + VkFragmentShadingRateCombinerOpKHR vkCombinerOp0 = + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; + switch (combinerOps[0]) + { + case gl::CombinerOp::Keep: + vkCombinerOp0 = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; + break; + case gl::CombinerOp::Replace: + vkCombinerOp0 = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; + break; + case gl::CombinerOp::Min: + vkCombinerOp0 = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR; + break; + case gl::CombinerOp::Max: + vkCombinerOp0 = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR; + break; + case gl::CombinerOp::Mul: + vkCombinerOp0 = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR; + break; + default: + UNREACHABLE(); + return angle::Result::Stop; + } + VkFragmentShadingRateCombinerOpKHR shadingRateCombinerOp[2] = { - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}; + vkCombinerOp0, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}; - // If foveated rendering is enabled update combiner op + // If foveated rendering is enabled with the QCOM extension, combiner op [1] should be REPLACE. if (isFoveationEnabled) { shadingRateCombinerOp[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; @@ -3560,6 +3539,8 @@ void ContextVk::syncObjectPerfCounters(const angle::VulkanPerfCounters &commandQ .accumulateDescriptorCacheStats(VulkanCacheType::UniformsAndXfbDescriptors, this); mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::Texture] .accumulateDescriptorCacheStats(VulkanCacheType::TextureDescriptors, this); + mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::UniformBuffers] + .accumulateDescriptorCacheStats(VulkanCacheType::UniformBuffersDescriptors, this); mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::ShaderResource] .accumulateDescriptorCacheStats(VulkanCacheType::ShaderResourcesDescriptors, this); @@ -3574,6 +3555,12 @@ void ContextVk::syncObjectPerfCounters(const angle::VulkanPerfCounters &commandQ mPerfCounters.textureDescriptorSetCacheMisses = texCacheStats.getMissCount(); mPerfCounters.textureDescriptorSetCacheTotalSize = texCacheStats.getSize(); + const CacheStats &uniBufCacheStats = + mVulkanCacheStats[VulkanCacheType::UniformBuffersDescriptors]; + mPerfCounters.uniformBuffersDescriptorSetCacheHits = uniBufCacheStats.getHitCount(); + mPerfCounters.uniformBuffersDescriptorSetCacheMisses = uniBufCacheStats.getMissCount(); + mPerfCounters.uniformBuffersDescriptorSetCacheTotalSize = uniBufCacheStats.getSize(); + const CacheStats &resCacheStats = mVulkanCacheStats[VulkanCacheType::ShaderResourcesDescriptors]; mPerfCounters.shaderResourcesDescriptorSetCacheHits = resCacheStats.getHitCount(); @@ -3581,8 +3568,8 @@ void ContextVk::syncObjectPerfCounters(const angle::VulkanPerfCounters &commandQ mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize = resCacheStats.getSize(); mPerfCounters.descriptorSetCacheTotalSize = - uniCacheStats.getSize() + texCacheStats.getSize() + resCacheStats.getSize() + - mVulkanCacheStats[VulkanCacheType::DriverUniformsDescriptors].getSize(); + uniCacheStats.getSize() + texCacheStats.getSize() + uniBufCacheStats.getSize() + + resCacheStats.getSize(); mPerfCounters.descriptorSetCacheKeySizeBytes = 0; @@ -3740,31 +3727,31 @@ void ContextVk::addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *comman angle::Result ContextVk::submitCommands(const vk::Semaphore *signalSemaphore, const vk::SharedExternalFence *externalFence, - Submit submission) + QueueSubmitReason reason) { + // Since we just about to flush, deferred flush is no longer deferred. + mHasDeferredFlush = false; + if (kEnableCommandStreamDiagnostics) { dumpCommandStreamDiagnostics(); } - if (!mCurrentGarbage.empty() && submission == Submit::AllCommands) + // If there are foreign images to transition, issue the barrier now. + if (!mImagesToTransitionToForeign.empty()) { - // Clean up garbage. - vk::ResourceUse use(mLastFlushedQueueSerial); - size_t capacity = mCurrentGarbage.capacity(); - mRenderer->collectGarbage(use, std::move(mCurrentGarbage)); - // Make sure we don't lose capacity after the move to avoid storage reallocation. - mCurrentGarbage.reserve(capacity); + mCommandState.flushImagesTransitionToForeign(std::move(mImagesToTransitionToForeign)); } - ASSERT(mLastFlushedQueueSerial.valid()); - ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial, - mLastFlushedQueueSerial)); + if (!mImagesWithTileMemory.empty()) + { + ANGLE_TRY(finalizeImagesWithTileMemory()); + } - finalizeAllForeignImages(); - ANGLE_TRY(mRenderer->submitCommands( - this, getProtectionType(), mContextPriority, signalSemaphore, externalFence, - std::move(mImagesToTransitionToForeign), mLastFlushedQueueSerial)); + ANGLE_TRY(mCommandState.insertSubmitDebugMarker(this, reason)); + + ANGLE_TRY(mRenderer->submitCommands(this, signalSemaphore, externalFence, + mLastFlushedQueueSerial, std::move(mCommandState))); mLastSubmittedQueueSerial = mLastFlushedQueueSerial; mSubmittedResourceUse.setQueueSerial(mLastSubmittedQueueSerial); @@ -3778,11 +3765,6 @@ angle::Result ContextVk::submitCommands(const vk::Semaphore *signalSemaphore, mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits; - if (mGpuEventsEnabled) - { - ANGLE_TRY(checkCompletedGpuEvents()); - } - mTotalBufferToImageCopySize = 0; mEstimatedPendingImageGarbageSize = 0; @@ -3803,10 +3785,13 @@ angle::Result ContextVk::onCopyUpdate(VkDeviceSize size, bool *commandBufferWasF *commandBufferWasFlushedOut = false; mTotalBufferToImageCopySize += size; - // If the copy size exceeds the specified threshold, submit the outside command buffer. - if (mTotalBufferToImageCopySize >= kMaxBufferToImageCopySize) + // If the copy size exceeds the specified threshold, submit the outside command buffer. When + // there are images with tile memory in use, avoid submission by trying to avoid triggering tile + // memory fallback. + if (mTotalBufferToImageCopySize >= kMaxBufferToImageCopySize && mImagesWithTileMemory.empty()) { - ANGLE_TRY(flushAndSubmitOutsideRenderPassCommands()); + ANGLE_TRY(flushAndSubmitOutsideRenderPassCommands( + QueueSubmitReason::BufferToImageUpdateLimitReached)); *commandBufferWasFlushedOut = true; } return angle::Result::Continue; @@ -3815,328 +3800,16 @@ angle::Result ContextVk::onCopyUpdate(VkDeviceSize size, bool *commandBufferWasF void ContextVk::addToPendingImageGarbage(vk::ResourceUse use, VkDeviceSize size) { if (!mRenderer->hasResourceUseFinished(use)) - { - mEstimatedPendingImageGarbageSize += size; - } -} - -bool ContextVk::hasExcessPendingGarbage() const -{ - VkDeviceSize trackedPendingGarbage = - mRenderer->getPendingSuballocationGarbageSize() + mEstimatedPendingImageGarbageSize; - return trackedPendingGarbage >= mRenderer->getPendingGarbageSizeLimit(); -} - -angle::Result ContextVk::synchronizeCpuGpuTime() -{ - ASSERT(mGpuEventsEnabled); - - angle::PlatformMethods *platform = ANGLEPlatformCurrent(); - ASSERT(platform); - - // To synchronize CPU and GPU times, we need to get the CPU timestamp as close as possible - // to the GPU timestamp. The process of getting the GPU timestamp is as follows: - // - // CPU GPU - // - // Record command buffer - // with timestamp query - // - // Submit command buffer - // - // Post-submission work Begin execution - // - // ???? Write timestamp Tgpu - // - // ???? End execution - // - // ???? Return query results - // - // ???? - // - // Get query results - // - // The areas of unknown work (????) on the CPU indicate that the CPU may or may not have - // finished post-submission work while the GPU is executing in parallel. With no further - // work, querying CPU timestamps before submission and after getting query results give the - // bounds to Tgpu, which could be quite large. - // - // Using VkEvents, the GPU can be made to wait for the CPU and vice versa, in an effort to - // reduce this range. This function implements the following procedure: - // - // CPU GPU - // - // Record command buffer - // with timestamp query - // - // Submit command buffer - // - // Post-submission work Begin execution - // - // ???? Set Event GPUReady - // - // Wait on Event GPUReady Wait on Event CPUReady - // - // Get CPU Time Ts Wait on Event CPUReady - // - // Set Event CPUReady Wait on Event CPUReady - // - // Get CPU Time Tcpu Get GPU Time Tgpu - // - // Wait on Event GPUDone Set Event GPUDone - // - // Get CPU Time Te End Execution - // - // Idle Return query results - // - // Get query results - // - // If Te-Ts > epsilon, a GPU or CPU interruption can be assumed and the operation can be - // retried. Once Te-Ts < epsilon, Tcpu can be taken to presumably match Tgpu. Finding an - // epsilon that's valid for all devices may be difficult, so the loop can be performed only - // a limited number of times and the Tcpu,Tgpu pair corresponding to smallest Te-Ts used for - // calibration. - // - // Note: Once VK_EXT_calibrated_timestamps is ubiquitous, this should be redone. - - ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::synchronizeCpuGpuTime"); - - // Create a query used to receive the GPU timestamp - vk::QueryHelper timestampQuery; - ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, ×tampQuery, 1)); - - // Create the three events - VkEventCreateInfo eventCreateInfo = {}; - eventCreateInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - eventCreateInfo.flags = 0; - - VkDevice device = getDevice(); - vk::DeviceScoped cpuReady(device), gpuReady(device), gpuDone(device); - ANGLE_VK_TRY(this, cpuReady.get().init(device, eventCreateInfo)); - ANGLE_VK_TRY(this, gpuReady.get().init(device, eventCreateInfo)); - ANGLE_VK_TRY(this, gpuDone.get().init(device, eventCreateInfo)); - - constexpr uint32_t kRetries = 10; - - // Time suffixes used are S for seconds and Cycles for cycles - double tightestRangeS = 1e6f; - double TcpuS = 0; - uint64_t TgpuCycles = 0; - for (uint32_t i = 0; i < kRetries; ++i) - { - // Reset the events - ANGLE_VK_TRY(this, cpuReady.get().reset(device)); - ANGLE_VK_TRY(this, gpuReady.get().reset(device)); - ANGLE_VK_TRY(this, gpuDone.get().reset(device)); - - // Record the command buffer - vk::ScopedPrimaryCommandBuffer scopedCommandBuffer(device); - - ANGLE_TRY( - mRenderer->getCommandBufferOneOff(this, getProtectionType(), &scopedCommandBuffer)); - vk::PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get(); - - commandBuffer.setEvent(gpuReady.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); - commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0, - nullptr); - timestampQuery.writeTimestampToPrimary(this, &commandBuffer); - - commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); - - ANGLE_VK_TRY(this, commandBuffer.end()); - - QueueSerial submitSerial; - // vkEvent's are externally synchronized, therefore need work to be submitted before calling - // vkGetEventStatus - ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(scopedCommandBuffer), - getProtectionType(), mContextPriority, - VK_NULL_HANDLE, 0, &submitSerial)); - - // Track it with the submitSerial. - timestampQuery.setQueueSerial(submitSerial); - - // Wait for GPU to be ready. This is a short busy wait. - VkResult result = VK_EVENT_RESET; - do - { - result = gpuReady.get().getStatus(device); - if (result != VK_EVENT_SET && result != VK_EVENT_RESET) - { - ANGLE_VK_TRY(this, result); - } - } while (result == VK_EVENT_RESET); - - double TsS = platform->monotonicallyIncreasingTime(platform); - - // Tell the GPU to go ahead with the timestamp query. - ANGLE_VK_TRY(this, cpuReady.get().set(device)); - double cpuTimestampS = platform->monotonicallyIncreasingTime(platform); - - // Wait for GPU to be done. Another short busy wait. - do - { - result = gpuDone.get().getStatus(device); - if (result != VK_EVENT_SET && result != VK_EVENT_RESET) - { - ANGLE_VK_TRY(this, result); - } - } while (result == VK_EVENT_RESET); - - double TeS = platform->monotonicallyIncreasingTime(platform); - - // Get the query results - ANGLE_TRY(mRenderer->finishQueueSerial(this, submitSerial)); - - vk::QueryResult gpuTimestampCycles(1); - ANGLE_TRY(timestampQuery.getUint64Result(this, &gpuTimestampCycles)); - - // Use the first timestamp queried as origin. - if (mGpuEventTimestampOrigin == 0) - { - mGpuEventTimestampOrigin = - gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex); - } - - // Take these CPU and GPU timestamps if there is better confidence. - double confidenceRangeS = TeS - TsS; - if (confidenceRangeS < tightestRangeS) - { - tightestRangeS = confidenceRangeS; - TcpuS = cpuTimestampS; - TgpuCycles = gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex); - } - } - - mGpuEventQueryPool.freeQuery(this, ×tampQuery); - - // timestampPeriod gives nanoseconds/cycle. - double TgpuS = - (TgpuCycles - mGpuEventTimestampOrigin) * - static_cast(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) / - 1'000'000'000.0; - - flushGpuEvents(TgpuS, TcpuS); - - mGpuClockSync.gpuTimestampS = TgpuS; - mGpuClockSync.cpuTimestampS = TcpuS; - - return angle::Result::Continue; -} - -angle::Result ContextVk::traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer, - char phase, - const EventName &name) -{ - ASSERT(mGpuEventsEnabled); - - GpuEventQuery gpuEvent; - gpuEvent.name = name; - gpuEvent.phase = phase; - ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper, 1)); - - gpuEvent.queryHelper.writeTimestamp(this, commandBuffer); - - mInFlightGpuEventQueries.push_back(std::move(gpuEvent)); - return angle::Result::Continue; -} - -angle::Result ContextVk::checkCompletedGpuEvents() -{ - ASSERT(mGpuEventsEnabled); - - angle::PlatformMethods *platform = ANGLEPlatformCurrent(); - ASSERT(platform); - - int finishedCount = 0; - - for (GpuEventQuery &eventQuery : mInFlightGpuEventQueries) - { - ASSERT(mRenderer->hasResourceUseSubmitted(eventQuery.queryHelper.getResourceUse())); - // Only check the timestamp query if the submission has finished. - if (!mRenderer->hasResourceUseFinished(eventQuery.queryHelper.getResourceUse())) - { - break; - } - - // See if the results are available. - vk::QueryResult gpuTimestampCycles(1); - bool available = false; - ANGLE_TRY(eventQuery.queryHelper.getUint64ResultNonBlocking(this, &gpuTimestampCycles, - &available)); - if (!available) - { - break; - } - - mGpuEventQueryPool.freeQuery(this, &eventQuery.queryHelper); - - GpuEvent gpuEvent; - gpuEvent.gpuTimestampCycles = - gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex); - gpuEvent.name = eventQuery.name; - gpuEvent.phase = eventQuery.phase; - - mGpuEvents.emplace_back(gpuEvent); - - ++finishedCount; - } - - mInFlightGpuEventQueries.erase(mInFlightGpuEventQueries.begin(), - mInFlightGpuEventQueries.begin() + finishedCount); - - return angle::Result::Continue; -} - -void ContextVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS) -{ - if (mGpuEvents.empty()) - { - return; - } - - angle::PlatformMethods *platform = ANGLEPlatformCurrent(); - ASSERT(platform); - - // Find the slope of the clock drift for adjustment - double lastGpuSyncTimeS = mGpuClockSync.gpuTimestampS; - double lastGpuSyncDiffS = mGpuClockSync.cpuTimestampS - mGpuClockSync.gpuTimestampS; - double gpuSyncDriftSlope = 0; - - double nextGpuSyncTimeS = nextSyncGpuTimestampS; - double nextGpuSyncDiffS = nextSyncCpuTimestampS - nextSyncGpuTimestampS; - - // No gpu trace events should have been generated before the clock sync, so if there is no - // "previous" clock sync, there should be no gpu events (i.e. the function early-outs - // above). - ASSERT(mGpuClockSync.gpuTimestampS != std::numeric_limits::max() && - mGpuClockSync.cpuTimestampS != std::numeric_limits::max()); - - gpuSyncDriftSlope = - (nextGpuSyncDiffS - lastGpuSyncDiffS) / (nextGpuSyncTimeS - lastGpuSyncTimeS); - - for (const GpuEvent &gpuEvent : mGpuEvents) - { - double gpuTimestampS = - (gpuEvent.gpuTimestampCycles - mGpuEventTimestampOrigin) * - static_cast( - getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) * - 1e-9; - - // Account for clock drift. - gpuTimestampS += lastGpuSyncDiffS + gpuSyncDriftSlope * (gpuTimestampS - lastGpuSyncTimeS); - - // Generate the trace now that the GPU timestamp is available and clock drifts are - // accounted for. - static long long eventId = 1; - static const unsigned char *categoryEnabled = - TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, "gpu.angle.gpu"); - platform->addTraceEvent(platform, gpuEvent.phase, categoryEnabled, gpuEvent.name.data(), - eventId++, gpuTimestampS, 0, nullptr, nullptr, nullptr, - TRACE_EVENT_FLAG_NONE); + { + mEstimatedPendingImageGarbageSize += size; } +} - mGpuEvents.clear(); +bool ContextVk::hasExcessPendingGarbage() const +{ + VkDeviceSize trackedPendingGarbage = + mRenderer->getPendingSuballocationGarbageSize() + mEstimatedPendingImageGarbageSize; + return trackedPendingGarbage >= mRenderer->getPendingGarbageSizeLimit(); } void ContextVk::clearAllGarbage() @@ -4640,7 +4313,7 @@ angle::Result ContextVk::multiDrawElementsInstancedBaseVertexBaseInstance( angle::Result ContextVk::optimizeRenderPassForPresent(vk::ImageViewHelper *colorImageView, vk::ImageHelper *colorImage, vk::ImageHelper *colorImageMS, - vk::PresentMode presentMode, + bool isSharedPresentMode, bool *imageResolved) { // Note: mRenderPassCommandBuffer may be nullptr because the render pass is marked for closure. @@ -4677,7 +4350,7 @@ angle::Result ContextVk::optimizeRenderPassForPresent(vk::ImageViewHelper *color // image is the target of resolve, but that resolve cannot happen with the render pass, do not // apply this optimization; the image has to be moved out of PRESENT_SRC to be resolved after // this call. - if (getFeatures().supportsPresentation.enabled && + if (getFeatures().supportsPresentation.enabled && !isSharedPresentMode && (!colorImageMS->valid() || resolveWithRenderPass)) { ASSERT(colorImage != nullptr); @@ -4701,19 +4374,17 @@ angle::Result ContextVk::optimizeRenderPassForPresent(vk::ImageViewHelper *color mRenderPassCommands->addColorResolveAttachment(0, colorImage, resolveImageView->getHandle(), gl::LevelIndex(0), 0, 1, {}); onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::ColorWrite, colorImage); + vk::ImageAccess::ColorWrite, colorImage); - // Invalidate the surface. See comment in WindowSurfaceVk::doDeferredAcquireNextImage on - // why this is not done when in DEMAND_REFRESH mode. - if (presentMode != vk::PresentMode::SharedDemandRefreshKHR) + // Invalidate the surface. + // See comment in WindowSurfaceVk::acquireNextSwapchainImage on why this is not done when + // in shared present mode. + if (!isSharedPresentMode) { commandBufferHelper.invalidateRenderPassColorAttachment( mState, 0, vk::PackedAttachmentIndex(0), fullExtent); } - ANGLE_TRY( - flushCommandsAndEndRenderPass(RenderPassClosureReason::AlreadySpecifiedElsewhere)); - *imageResolved = true; mPerfCounters.swapchainResolveInSubpass++; @@ -4737,7 +4408,8 @@ gl::GraphicsResetStatus ContextVk::getResetStatus() angle::Result ContextVk::insertEventMarker(GLsizei length, const char *marker) { - insertEventMarkerImpl(GL_DEBUG_SOURCE_APPLICATION, marker); + // Use length because marker does not have to be null-terminated. + insertEventMarkerImpl(GL_DEBUG_SOURCE_APPLICATION, std::string(marker, length).c_str()); return angle::Result::Continue; } @@ -4763,7 +4435,8 @@ void ContextVk::insertEventMarkerImpl(GLenum source, const char *marker) angle::Result ContextVk::pushGroupMarker(GLsizei length, const char *marker) { - return pushDebugGroupImpl(GL_DEBUG_SOURCE_APPLICATION, 0, marker); + // Use length because marker does not have to be null-terminated. + return pushDebugGroupImpl(GL_DEBUG_SOURCE_APPLICATION, 0, std::string(marker, length).c_str()); } angle::Result ContextVk::popGroupMarker() @@ -4895,6 +4568,23 @@ angle::Result ContextVk::handleNoopDrawEvent() return handleDirtyEventLogImpl(mRenderPassCommandBuffer); } +angle::Result ContextVk::handleNoopMultiDrawEvent() +{ + // Normally, when a draw call is no-op'd by the front-end, the objects are not synced. This is + // important because no draw call will follow. In particular, FramebufferVk::syncState picks up + // deferred clears with the assumption that the following call to the backend will handle them. + // In the case of multi-draw, FramebufferVk::syncState is always called, but all the individual + // draw calls (as issued by |MULTI_DRAW_BLOCK()|) may be no-op'd. In that case, the deferred + // clears are left in FramebufferVk, which is invalid. + // + // This call is made in case all draw calls of multi-draw are no-op'd, so deferred clears can be + // handled. + FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer()); + framebufferVk->restageDeferredClearsAfterNoopDraw(this); + + return handleNoopDrawEvent(); +} + angle::Result ContextVk::handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType) { ASSERT(mQueryEventType == GraphicsEventCmdBuf::NotInQueryCmd || mEventLog.empty()); @@ -5154,6 +4844,39 @@ void ContextVk::updateFrontFace() } } +ANGLE_INLINE void ContextVk::updateTopology(gl::PrimitiveMode mode) +{ + ASSERT(mode != mCurrentDrawMode); + + gl::PrimitiveMode pipelineTopology = mode; + const gl::PrimitiveMode currentMode = mCurrentDrawMode; + mCurrentDrawMode = mode; + + // When VK_EXT_extended_dynamic_state is enabled, all that's needed in the graphics pipeline + // desc is the topology "class", and the exact topology is specified dynamically. + // + // Note: VK_EXT_extended_dynamic_state3's dynamicPrimitiveTopologyUnrestricted property + // indicates that the dynamically set primitive topology doesn't need to match even the topology + // class used to create the pipeline. That property seems to only be set on Nvidia. + if (getFeatures().usePrimitiveTopologyDynamicState.enabled) + { + // Update the exact mode dynamically + mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_PRIMITIVE_TOPOLOGY); + + // Only update the pipeline desc if the primitive class has changed + pipelineTopology = kPrimitiveTopologyClass[mode]; + const bool isTopologyClassChanged = + pipelineTopology != kPrimitiveTopologyClass[currentMode]; + if (!isTopologyClassChanged) + { + return; + } + } + + invalidateCurrentGraphicsPipeline(); + mGraphicsPipelineDesc->updateTopology(&mGraphicsPipelineTransition, pipelineTopology); +} + void ContextVk::updateDepthRange(float nearPlane, float farPlane) { // GLES2.0 Section 2.12.1: Each of n and f are clamped to lie within [0, 1], as are all @@ -5489,7 +5212,7 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co invalidateCurrentGraphicsPipeline(); // No additional work is needed here. We will update the pipeline desc // later. - invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); + invalidateDefaultAttributes(context->getActiveDefaultAttribsMask()); invalidateVertexAndIndexBuffers(); // If VK_EXT_vertex_input_dynamic_state is enabled then vkCmdSetVertexInputEXT must be // called in the current command buffer prior to the draw command, even if there are no @@ -5843,9 +5566,31 @@ angle::Result ContextVk::syncState(const gl::Context *context, // If we are switching from user FBO to system frame buffer, we always submit work // first so that these FBO rendering will not have to wait for ANI semaphore (which // draw to system frame buffer must wait for). - if ((getFeatures().preferSubmitAtFBOBoundary.enabled || - mState.getDrawFramebuffer()->isDefault()) && - mRenderPassCommands->started()) + + // To reduce CPU overhead if submission at FBO boundary is preferred, the deferred + // flush is triggered after the currently accumulated command count for the render + // pass command buffer hits a threshold kMinCommandCountToSubmit). + uint32_t currentRPCommandCount = + mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount() + + mCommandsPendingSubmissionCount; + bool allowExceptionForSubmitAtBoundary = mRenderer->isInFlightCommandsEmpty(); + + // For performance reasons, in the case of a clear or invalidate GL command, a + // deferred flush can be triggered if the corresponding feature flag is enabled. + if (getFeatures().forceSubmitExceptionsAtFBOBoundary.enabled) + { + allowExceptionForSubmitAtBoundary |= + command == gl::Command::Clear || command == gl::Command::Invalidate; + } + + bool shouldSubmitAtFBOBoundary = + getFeatures().preferSubmitAtFBOBoundary.enabled && + (currentRPCommandCount >= kMinCommandCountToSubmit || + allowExceptionForSubmitAtBoundary); + + // If we are using tile memory, don't enable this optimization to prevent fallback. + if ((shouldSubmitAtFBOBoundary || mState.getDrawFramebuffer()->isDefault()) && + mRenderPassCommands->started() && mImagesWithTileMemory.empty()) { // This will behave as if user called glFlush, but the actual flush will be // triggered at endRenderPass time. @@ -5892,8 +5637,8 @@ angle::Result ContextVk::syncState(const gl::Context *context, break; case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING: { - invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); - ANGLE_TRY(vertexArrayVk->updateActiveAttribInfo(this)); + invalidateDefaultAttributes(context->getActiveDefaultAttribsMask()); + ANGLE_TRY(onVertexArrayChange(vertexArrayVk->getCurrentEnabledAttribsMask())); ANGLE_TRY(onIndexBufferChange(vertexArrayVk->getCurrentElementArrayBuffer())); break; } @@ -5913,20 +5658,31 @@ angle::Result ContextVk::syncState(const gl::Context *context, invalidateCurrentDefaultUniforms(); updateAdvancedBlendEquations(programExecutable); vk::GetImpl(programExecutable)->onProgramBind(); + static_assert(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS > + gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE, + "Dirty bit order"); + iter.setLaterBit(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS); static_assert( gl::state::DIRTY_BIT_TEXTURE_BINDINGS > gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE, "Dirty bit order"); iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS); ANGLE_TRY(invalidateCurrentShaderResources(command)); - invalidateDriverUniforms(); ANGLE_TRY(invalidateProgramExecutableHelper(context)); - static_assert( - gl::state::DIRTY_BIT_SAMPLE_SHADING > gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE, - "Dirty bit order"); - if (getFeatures().explicitlyEnablePerSampleShading.enabled) + // Handle sample shading state transitions for graphics programs + if (programExecutable->hasLinkedGraphicsShader()) { - iter.setLaterBit(gl::state::DIRTY_BIT_SAMPLE_SHADING); + const bool programEnablesSampleShading = + programExecutable->enablesPerSampleShading(); + if ((mSampleShadingEnabled || programEnablesSampleShading) && + getFeatures().explicitlyEnablePerSampleShading.enabled) + { + static_assert(gl::state::DIRTY_BIT_SAMPLE_SHADING > + gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE, + "Dirty bit order"); + iter.setLaterBit(gl::state::DIRTY_BIT_SAMPLE_SHADING); + } + mSampleShadingEnabled = programEnablesSampleShading; } break; @@ -5957,13 +5713,36 @@ angle::Result ContextVk::syncState(const gl::Context *context, "Dirty bit order"); iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING); break; - case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: - ANGLE_TRY(invalidateCurrentShaderUniformBuffers(command)); - break; case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING: ANGLE_TRY(invalidateCurrentShaderResources(command)); invalidateDriverUniforms(); break; + case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: + { + ASSERT(programExecutable); + if (programExecutable->getActiveUniformBufferBlocks().any()) + { + constexpr gl::BufferDirtyTypeBitMask kOnlyOffsetDirtyMask{ + gl::BufferDirtyType::Offset}; + const gl::BufferDirtyTypeBitMask currentDirtyTypeMask = + glState.getAndResetUniformBufferBlocksDirtyTypeMask(); + if (vk::GetImpl(programExecutable)->usesDynamicUniformBufferDescriptors() && + currentDirtyTypeMask == kOnlyOffsetDirtyMask) + { + updateUniformBufferBlocksOffset(); + } + else + { + ANGLE_TRY(invalidateCurrentShaderUniformBuffers()); + } + } + else + { + // Current program has no active uniforms, reset dirty bits + glState.getAndResetDirtyUniformBlocks(); + } + break; + } case gl::state::DIRTY_BIT_MULTISAMPLING: // When disabled, this should configure the pipeline to render as if single-sampled, // and write the results to all samples of a pixel regardless of coverage. See @@ -6082,7 +5861,9 @@ angle::Result ContextVk::syncState(const gl::Context *context, gl_vk::GetLogicOp(gl::ToGLenum(glState.getLogicOp()))); } break; - case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE: + case gl::state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED: + case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM: + case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT: if (getFeatures().supportsFragmentShadingRate.enabled) { mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE); @@ -6176,14 +5957,15 @@ angle::Result ContextVk::onMakeCurrent(const gl::Context *context) angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context) { - ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::ContextChange)); + ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::ContextChange)); mCurrentWindowSurface = nullptr; if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex) { releaseQueueSerialIndex(); } - return angle::Result::Continue; + + return onFrameBoundary(context); } angle::Result ContextVk::onSurfaceUnMakeCurrent(WindowSurfaceVk *surface) @@ -6202,8 +5984,8 @@ angle::Result ContextVk::onSurfaceUnMakeCurrent(WindowSurfaceVk *surface) { // May be nullptr if only used as a readSurface. ASSERT(mCurrentWindowSurface == surface || mCurrentWindowSurface == nullptr); - ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, - RenderPassClosureReason::SurfaceUnMakeCurrent)); + ANGLE_TRY( + flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::SurfaceUnMakeCurrent)); mCurrentWindowSurface = nullptr; } ASSERT(mCurrentWindowSurface == nullptr); @@ -6211,8 +5993,7 @@ angle::Result ContextVk::onSurfaceUnMakeCurrent(WindowSurfaceVk *surface) // Everything must be flushed and submitted. ASSERT(mOutsideRenderPassCommands->empty()); ASSERT(!mRenderPassCommands->started()); - ASSERT(mWaitSemaphores.empty()); - ASSERT(!mHasWaitSemaphoresPendingSubmission); + ASSERT(!mCommandState.hasWaitSemaphoresPendingSubmission()); ASSERT(mLastSubmittedQueueSerial == mLastFlushedQueueSerial); return angle::Result::Continue; } @@ -6239,7 +6020,7 @@ angle::Result ContextVk::onSurfaceUnMakeCurrent(OffscreenSurfaceVk *surface) // Everything must be flushed but may be pending submission. ASSERT(mOutsideRenderPassCommands->empty()); ASSERT(!mRenderPassCommands->started()); - ASSERT(mWaitSemaphores.empty()); + ASSERT(!mCommandState.hasWaitSemaphoresPendingSubmission()); return angle::Result::Continue; } @@ -6276,21 +6057,6 @@ void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState, const SurfaceRotation rotation = getSurfaceRotationImpl(glState.getDrawFramebuffer(), currentDrawSurface); mCurrentRotationDrawFramebuffer = rotation; - - if (!getFeatures().preferDriverUniformOverSpecConst.enabled) - { - const bool isRotatedAspectRatio = IsRotatedAspectRatio(rotation); - // Update spec consts - if (isRotatedAspectRatio != mGraphicsPipelineDesc->getSurfaceRotation()) - { - // surface rotation are specialization constants, which affects program compilation. - // When rotation changes, we need to update GraphicsPipelineDesc so that the correct - // pipeline program object will be retrieved. - mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition, - isRotatedAspectRatio); - invalidateCurrentGraphicsPipeline(); - } - } } void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState, @@ -6305,6 +6071,11 @@ gl::Caps ContextVk::getNativeCaps() const return mRenderer->getNativeCaps(); } +const angle::ShadingRateMap &ContextVk::getSupportedFragmentShadingRateEXTSampleCounts() const +{ + return mRenderer->getSupportedFragmentShadingRateEXTSampleCounts(); +} + const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const { return mRenderer->getNativeTextureCaps(); @@ -6365,9 +6136,10 @@ BufferImpl *ContextVk::createBuffer(const gl::BufferState &state) return new BufferVk(state); } -VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state) +VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers) { - return new VertexArrayVk(this, state); + return new VertexArrayVk(this, state, vertexArrayBuffers); } QueryImpl *ContextVk::createQuery(gl::QueryType type) @@ -6455,22 +6227,14 @@ angle::Result ContextVk::invalidateCurrentShaderResources(gl::Command command) const bool hasImages = executable->hasImages(); const bool hasStorageBuffers = executable->hasStorageBuffers() || executable->hasAtomicCounterBuffers(); - const bool hasUniformBuffers = executable->hasUniformBuffers(); - if (hasUniformBuffers || hasStorageBuffers || hasImages || - executable->usesColorFramebufferFetch() || executable->usesDepthFramebufferFetch() || - executable->usesStencilFramebufferFetch()) + if (hasStorageBuffers || hasImages || executable->usesColorFramebufferFetch() || + executable->usesDepthFramebufferFetch() || executable->usesStencilFramebufferFetch()) { mGraphicsDirtyBits |= kResourcesAndDescSetDirtyBits; mComputeDirtyBits |= kResourcesAndDescSetDirtyBits; } - // Take care of read-after-write hazards that require implicit synchronization. - if (hasUniformBuffers && command == gl::Command::Dispatch) - { - ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite()); - } - // Take care of implicit layout transition by compute program access-after-read. if (hasImages && command == gl::Command::Dispatch) { @@ -6492,75 +6256,24 @@ angle::Result ContextVk::invalidateCurrentShaderResources(gl::Command command) return angle::Result::Continue; } -angle::Result ContextVk::invalidateCurrentShaderUniformBuffers(gl::Command command) +angle::Result ContextVk::invalidateCurrentShaderUniformBuffers() { const gl::ProgramExecutable *executable = mState.getProgramExecutable(); ASSERT(executable); + ASSERT(executable->hasUniformBuffers()); + ASSERT(executable->getActiveUniformBufferBlocks().any()); - if (executable->hasUniformBuffers()) - { - if (executable->hasLinkedShaderStage(gl::ShaderType::Compute)) - { - mComputeDirtyBits |= kUniformBuffersAndDescSetDirtyBits; - } - else - { - mGraphicsDirtyBits |= kUniformBuffersAndDescSetDirtyBits; - } - - if (command == gl::Command::Dispatch) - { - // Take care of read-after-write hazards that require implicit synchronization. - ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite()); - } - } - return angle::Result::Continue; -} - -void ContextVk::updateShaderResourcesWithSharedCacheKey( - const vk::SharedDescriptorSetCacheKey &sharedCacheKey) -{ - const gl::ProgramExecutable *executable = mState.getProgramExecutable(); - ProgramExecutableVk *executableVk = vk::GetImpl(executable); - - if (executable->hasUniformBuffers()) - { - const std::vector &blocks = executable->getUniformBlocks(); - for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex) - { - const GLuint binding = executable->getUniformBlockBinding(bufferIndex); - UpdateBufferWithSharedCacheKey(mState.getOffsetBindingPointerUniformBuffers()[binding], - executableVk->getUniformBufferDescriptorType(), - sharedCacheKey); - } - } - if (executable->hasStorageBuffers()) - { - const std::vector &blocks = executable->getShaderStorageBlocks(); - for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex) - { - const GLuint binding = executable->getShaderStorageBlockBinding(bufferIndex); - UpdateBufferWithSharedCacheKey( - mState.getOffsetBindingPointerShaderStorageBuffers()[binding], - executableVk->getStorageBufferDescriptorType(), sharedCacheKey); - } - } - if (executable->hasAtomicCounterBuffers()) + if (executable->hasLinkedShaderStage(gl::ShaderType::Compute)) { - const std::vector &blocks = executable->getAtomicCounterBuffers(); - for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex) - { - const GLuint binding = executable->getAtomicCounterBufferBinding(bufferIndex); - UpdateBufferWithSharedCacheKey( - mState.getOffsetBindingPointerAtomicCounterBuffers()[binding], - executableVk->getAtomicCounterBufferDescriptorType(), sharedCacheKey); - } + mComputeDirtyBits |= kUniformBuffersAndDescSetDirtyBits; } - if (executable->hasImages()) + else { - UpdateImagesWithSharedCacheKey(mActiveImages, executable->getImageBindings(), - sharedCacheKey); + mGraphicsDirtyBits |= kUniformBuffersAndDescSetDirtyBits; } + + // Take care of read-after-write hazards that require implicit synchronization. + return endRenderPassIfUniformBufferReadAfterTransformFeedbackWrite(); } void ContextVk::invalidateGraphicsDriverUniforms() @@ -6878,7 +6591,7 @@ angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield ba // other commands. For the latter, since storage buffer and images are not tracked in command // buffers, we can't rely on the command buffers being flushed in the usual way when recording // these commands (i.e. through |getOutsideRenderPassCommandBuffer()| and - // |vk::CommandBufferAccess|). Conservatively flushing command buffers with any storage output + // |vk::CommandResources|). Conservatively flushing command buffers with any storage output // simplifies this use case. If this needs to be avoided in the future, // |getOutsideRenderPassCommandBuffer()| can be modified to flush the command buffers if they // have had any storage output. @@ -6974,11 +6687,12 @@ angle::Result ContextVk::acquireTextures(const gl::Context *context, { TextureVk *textureVk = vk::GetImpl(textureBarrier.texture); vk::ImageHelper &image = textureVk->getImage(); - vk::ImageLayout layout = vk::GetImageLayoutFromGLImageLayout(this, textureBarrier.layout); + vk::ImageAccess imageAccess = + vk::GetImageAccessFromGLImageLayout(this, textureBarrier.layout); // Image should not be accessed while unowned. Emulated formats may have staged updates // to clear the image after initialization. ASSERT(!image.hasStagedUpdatesInAllocatedLevels() || image.hasEmulatedImageChannels()); - image.setCurrentImageLayout(getRenderer(), layout); + image.setCurrentImageAccess(getRenderer(), imageAccess); } return angle::Result::Continue; } @@ -6996,11 +6710,11 @@ angle::Result ContextVk::releaseTextures(const gl::Context *context, ANGLE_TRY(onImageReleaseToExternal(image)); textureBarrier.layout = - vk::ConvertImageLayoutToGLImageLayout(image.getCurrentImageLayout()); + ConvertImageAccessToGLImageLayout(mRenderer, image.getCurrentImageAccess()); } return flushAndSubmitCommands(nullptr, nullptr, - RenderPassClosureReason::ImageUseThenReleaseToExternal); + QueueSubmitReason::ImageUseThenReleaseToExternal); } vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType) @@ -7226,6 +6940,7 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator * mRenderPassCommands->getCommandBuffer().pushConstants( executableVk->getPipelineLayout(), getRenderer()->getSupportedVulkanShaderStageMask(), 0, driverUniformSize, driverUniforms); + mPerfCounters.graphicsDriverUniformsUpdated++; return angle::Result::Continue; } @@ -7247,6 +6962,7 @@ angle::Result ContextVk::handleDirtyComputeDriverUniforms(DirtyBits::Iterator *d mOutsideRenderPassCommands->getCommandBuffer().pushConstants( executableVk->getPipelineLayout(), getRenderer()->getSupportedVulkanShaderStageMask(), 0, driverUniformSize, &driverUniforms); + mPerfCounters.graphicsDriverUniformsUpdated++; return angle::Result::Continue; } @@ -7268,6 +6984,15 @@ void ContextVk::handleError(VkResult errorCode, if (errorCode == VK_ERROR_DEVICE_LOST) { + VkResult deviceLostInfoErrorCode = getRenderer()->retrieveDeviceLostDetails(); + if (deviceLostInfoErrorCode != VK_SUCCESS) + { + errorStream << std::endl + << "Unable to retrieve VK_ERROR_DEVICE_LOST details due to Vulkan error (" + << deviceLostInfoErrorCode + << "): " << VulkanResultString(deviceLostInfoErrorCode) << "."; + } + WARN() << errorStream.str(); handleDeviceLost(); } @@ -7325,7 +7050,7 @@ angle::Result ContextVk::initBufferAllocation(vk::BufferHelper *bufferHelper, // the garbage. if (result != VK_SUCCESS) { - ANGLE_TRY(finishImpl(RenderPassClosureReason::OutOfMemory)); + ANGLE_TRY(finishImpl(QueueSubmitReason::OutOfMemory)); INFO() << "Context flushed due to out-of-memory error."; result = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize, alignment, bufferUsageType, pool); @@ -7347,7 +7072,6 @@ angle::Result ContextVk::initBufferAllocation(vk::BufferHelper *bufferHelper, angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper, bool hasProtectedContent, - const vk::MemoryProperties &memoryProperties, VkMemoryPropertyFlags flags, vk::MemoryAllocationType allocationType) { @@ -7366,9 +7090,9 @@ angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper, bool allocateDedicatedMemory = mRenderer->getImageMemorySuballocator().needsDedicatedMemory(memoryRequirements.size); - VkResult result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags, - &memoryRequirements, allocateDedicatedMemory, - allocationType, &outputFlags, &outputSize); + VkResult result = + imageHelper->initMemory(this, flags, oomExcludedFlags, &memoryRequirements, + allocateDedicatedMemory, allocationType, &outputFlags, &outputSize); if (ANGLE_LIKELY(result == VK_SUCCESS)) { if (mRenderer->getFeatures().allocateNonZeroMemory.enabled) @@ -7395,9 +7119,9 @@ angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper, if (anyGarbageCleaned) { someGarbageCleaned = true; - result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags, - &memoryRequirements, allocateDedicatedMemory, - allocationType, &outputFlags, &outputSize); + result = imageHelper->initMemory(this, flags, oomExcludedFlags, &memoryRequirements, + allocateDedicatedMemory, allocationType, &outputFlags, + &outputSize); } } while (result != VK_SUCCESS && anyGarbageCleaned); @@ -7411,11 +7135,11 @@ angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper, // the garbage. if (result != VK_SUCCESS) { - ANGLE_TRY(finishImpl(RenderPassClosureReason::OutOfMemory)); + ANGLE_TRY(finishImpl(QueueSubmitReason::OutOfMemory)); INFO() << "Context flushed due to out-of-memory error."; - result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags, - &memoryRequirements, allocateDedicatedMemory, - allocationType, &outputFlags, &outputSize); + result = imageHelper->initMemory(this, flags, oomExcludedFlags, &memoryRequirements, + allocateDedicatedMemory, allocationType, &outputFlags, + &outputSize); } // If no fallback has worked so far, we should record the failed allocation information in case @@ -7438,9 +7162,9 @@ angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper, if (result != VK_SUCCESS) { oomExcludedFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags, - &memoryRequirements, allocateDedicatedMemory, - allocationType, &outputFlags, &outputSize); + result = imageHelper->initMemory(this, flags, oomExcludedFlags, &memoryRequirements, + allocateDedicatedMemory, allocationType, &outputFlags, + &outputSize); INFO() << "Allocation failed. Removed the DEVICE_LOCAL bit requirement | Allocation result: " << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL"); @@ -7466,7 +7190,6 @@ angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper, { ANGLE_TRY(imageHelper->initializeNonZeroMemory(this, hasProtectedContent, outputFlags, outputSize)); - imageHelper->getImage().getHandle(); } return angle::Result::Continue; @@ -7478,8 +7201,8 @@ angle::Result ContextVk::releaseBufferAllocation(vk::BufferHelper *bufferHelper) if (ANGLE_UNLIKELY(hasExcessPendingGarbage())) { - ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, - RenderPassClosureReason::ExcessivePendingGarbage)); + ANGLE_TRY( + flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::ExcessivePendingGarbage)); } return angle::Result::Continue; } @@ -7603,6 +7326,14 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context, gl::Co if (textureType == gl::TextureType::Buffer) { + vk::BufferHelper *buffer = textureVk->getPossiblyEmulatedTextureBuffer(this); + + if (mCurrentTransformFeedbackQueueSerial.valid() && + buffer->writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial)) + { + ANGLE_TRY(flushCommandsAndEndRenderPass( + RenderPassClosureReason::XfbWriteThenTextureBuffer)); + } continue; } @@ -7745,10 +7476,10 @@ angle::Result ContextVk::updateActiveImages(CommandBufferHelperT *commandBufferH gl::LevelIndex level; uint32_t layerStart = 0; uint32_t layerCount = 0; - const vk::ImageLayout imageLayout = GetImageWriteLayoutAndSubresource( + const vk::ImageAccess imageAccess = GetImageWriteAccessAndSubresource( imageUnit, *image, shaderStages, &level, &layerStart, &layerCount); - if (imageLayout == image->getCurrentImageLayout() && !memoryBarrierRequired) + if (imageAccess == image->getCurrentImageAccess() && !memoryBarrierRequired) { // GL spec does not require implementation to do WAW barriers for shader image access. // If there is no layout change, we skip the barrier here unless there is prior @@ -7758,16 +7489,33 @@ angle::Result ContextVk::updateActiveImages(CommandBufferHelperT *commandBufferH else { commandBufferHelper->imageWrite(this, level, layerStart, layerCount, - image->getAspectFlags(), imageLayout, image); + image->getAspectFlags(), imageAccess, image); } } return angle::Result::Continue; } +void ContextVk::prepareToSubmitAllCommands() +{ + if (!mCurrentGarbage.empty()) + { + // Clean up garbage. + vk::ResourceUse use(mLastFlushedQueueSerial); + size_t capacity = mCurrentGarbage.capacity(); + mRenderer->collectGarbage(use, std::move(mCurrentGarbage)); + // Make sure we don't lose capacity after the move to avoid storage reallocation. + mCurrentGarbage.reserve(capacity); + } + ASSERT(mLastFlushedQueueSerial.valid()); + ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial, + mLastFlushedQueueSerial)); + finalizeAllForeignImages(); +} + angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemaphore, const vk::SharedExternalFence *externalFence, - RenderPassClosureReason renderPassClosureReason) + QueueSubmitReason queueSubmitReason) { // Even if render pass does not have any command, we may still need to submit it in case it has // CLEAR loadOp. @@ -7776,7 +7524,8 @@ angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemap bool someCommandAlreadyFlushedNeedsSubmit = mLastFlushedQueueSerial != mLastSubmittedQueueSerial; bool someOtherReasonNeedsSubmit = signalSemaphore != nullptr || externalFence != nullptr || - mHasWaitSemaphoresPendingSubmission; + mCommandState.hasWaitSemaphoresPendingSubmission() || + hasForeignImagesToTransition(); if (!someCommandsNeedFlush && !someCommandAlreadyFlushedNeedsSubmit && !someOtherReasonNeedsSubmit) @@ -7790,7 +7539,8 @@ angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemap { // If any of secondary command buffer not empty, we need to do flush // Avoid calling vkQueueSubmit() twice, since submitCommands() below will do that. - ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit(renderPassClosureReason)); + ANGLE_TRY( + flushCommandsAndEndRenderPassWithoutSubmit(RenderPassClosureReason::SubmitCommands)); } else if (someCommandAlreadyFlushedNeedsSubmit) { @@ -7822,13 +7572,6 @@ angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemap mIsAnyHostVisibleBufferWritten = false; } - if (mGpuEventsEnabled) - { - EventName eventName = GetTraceEventName("Primary", mPrimaryBufferEventCounter); - ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(), - TRACE_EVENT_PHASE_END, eventName)); - } - // This will handle any commands that might be recorded above as well as flush any wait // semaphores. ANGLE_TRY(flushOutsideRenderPassCommands()); @@ -7858,34 +7601,25 @@ angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemap mHasInFlightStreamedVertexBuffers.reset(); } - ASSERT(mWaitSemaphores.empty()); - ASSERT(mWaitSemaphoreStageMasks.empty()); - - ANGLE_TRY(submitCommands(signalSemaphore, externalFence, Submit::AllCommands)); + prepareToSubmitAllCommands(); + ANGLE_TRY(submitCommands(signalSemaphore, externalFence, queueSubmitReason)); + mCommandsPendingSubmissionCount = 0; + mRenderPassCountSinceSubmit = 0; + ASSERT(!mCommandState.hasWaitSemaphoresPendingSubmission()); ASSERT(mOutsideRenderPassCommands->getQueueSerial() > mLastSubmittedQueueSerial); mHasAnyCommandsPendingSubmission = false; - mHasWaitSemaphoresPendingSubmission = false; onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere); - if (mGpuEventsEnabled) - { - EventName eventName = GetTraceEventName("Primary", ++mPrimaryBufferEventCounter); - ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(), - TRACE_EVENT_PHASE_BEGIN, eventName)); - } - - // Since we just flushed, deferred flush is no longer deferred. - mHasDeferredFlush = false; return angle::Result::Continue; } -angle::Result ContextVk::finishImpl(RenderPassClosureReason renderPassClosureReason) +angle::Result ContextVk::finishImpl(QueueSubmitReason queueSubmitReason) { ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::finishImpl"); - ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, renderPassClosureReason)); + ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, queueSubmitReason)); // You must have to wait for all queue indices ever used to finish. Just wait for // mLastSubmittedQueueSerial (which only contains current index) to finish is not enough, if it @@ -7894,32 +7628,11 @@ angle::Result ContextVk::finishImpl(RenderPassClosureReason renderPassClosureRea clearAllGarbage(); - if (mGpuEventsEnabled) - { - // This loop should in practice execute once since the queue is already idle. - while (mInFlightGpuEventQueries.size() > 0) - { - ANGLE_TRY(checkCompletedGpuEvents()); - } - // Recalculate the CPU/GPU time difference to account for clock drifting. Avoid - // unnecessary synchronization if there is no event to be adjusted (happens when - // finish() gets called multiple times towards the end of the application). - if (mGpuEvents.size() > 0) - { - ANGLE_TRY(synchronizeCpuGpuTime()); - } - } + syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters()); return angle::Result::Continue; } -void ContextVk::addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask) -{ - mWaitSemaphores.push_back(semaphore); - mWaitSemaphoreStageMasks.push_back(stageMask); - mHasWaitSemaphoresPendingSubmission = true; -} - angle::Result ContextVk::getCompatibleRenderPass(const vk::RenderPassDesc &desc, const vk::RenderPass **renderPassOut) { @@ -7988,11 +7701,15 @@ angle::Result ContextVk::getTimestamp(uint64_t *timestampOut) vk::PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get(); timestampQuery.writeTimestampToPrimary(this, &commandBuffer); + + mRenderer->insertSubmitDebugMarkerInCommandBuffer(commandBuffer, + QueueSubmitReason::CopyBufferToSurfaceImage); + ANGLE_VK_TRY(this, commandBuffer.end()); QueueSerial submitQueueSerial; ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(scopedCommandBuffer), - getProtectionType(), mContextPriority, VK_NULL_HANDLE, 0, + getProtectionType(), getPriority(), VK_NULL_HANDLE, 0, &submitQueueSerial)); // Track it with the submitSerial. timestampQuery.setQueueSerial(submitQueueSerial); @@ -8060,7 +7777,12 @@ void ContextVk::finalizeImageLayout(vk::ImageHelper *image, UniqueSerial imageSi if (image->isForeignImage() && !image->isReleasedToForeign()) { - finalizeForeignImage(image); + // Note: Foreign images may be shared between different textures. If another texture starts + // to use the image while the barrier-to-foreign is cached in the context, it will attempt + // to acquire the image from foreign while the release is still cached. A submission is + // made to finalize the queue family ownership transfer back to foreign. + (void)flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::ForeignImageRelease); + ASSERT(!hasForeignImagesToTransition()); } } @@ -8074,9 +7796,12 @@ angle::Result ContextVk::beginNewRenderPass( const vk::PackedClearValuesArray &clearValues, vk::RenderPassCommandBuffer **commandBufferOut) { - // End any currently outstanding render pass. The render pass is normally closed before reaching - // here for various reasons, except typically when UtilsVk needs to start one. - ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass)); + if (mRenderPassCommands->started()) + { + // End any currently outstanding render pass. The render pass is normally closed before + // reaching here for various reasons, except typically when UtilsVk needs to start one. + ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass)); + } // Now generate queueSerial for the renderPass. QueueSerial renderPassQueueSerial; @@ -8087,6 +7812,7 @@ angle::Result ContextVk::beginNewRenderPass( this, std::move(framebuffer), renderArea, renderPassDesc, renderPassAttachmentOps, colorAttachmentCount, depthStencilAttachmentIndex, clearValues, renderPassQueueSerial, commandBufferOut)); + mRenderPassCountSinceSubmit++; // By default all render pass should allow to be reactivated. mAllowRenderPassToReactivate = true; @@ -8188,14 +7914,6 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutSubmit(RenderPassCl onRenderPassFinished(reason); - if (mGpuEventsEnabled) - { - EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses); - ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(), - TRACE_EVENT_PHASE_BEGIN, eventName)); - ANGLE_TRY(flushOutsideRenderPassCommands()); - } - addOverlayUsedBuffersCount(mRenderPassCommands); pauseTransformFeedbackIfActiveUnpaused(); @@ -8242,9 +7960,14 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutSubmit(RenderPassCl { mIsAnyHostVisibleBufferWritten = true; } - ANGLE_TRY(mRenderer->flushRenderPassCommands(this, getProtectionType(), mContextPriority, - *renderPass, framebufferOverride, - &mRenderPassCommands)); + + // The counter for pending submission count is used for possible submission at FBO boundary and + // flush. + mCommandsPendingSubmissionCount += + mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount(); + + ANGLE_TRY(mCommandState.flushRenderPassCommands(this, *renderPass, framebufferOverride, + &mRenderPassCommands)); // We just flushed outSideRenderPassCommands above, and any future use of // outsideRenderPassCommands must have a queueSerial bigger than renderPassCommands. To ensure @@ -8254,14 +7977,6 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutSubmit(RenderPassCl // Generate a new serial for outside commands. generateOutsideRenderPassCommandsQueueSerial(); - if (mGpuEventsEnabled) - { - EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses); - ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(), - TRACE_EVENT_PHASE_END, eventName)); - ANGLE_TRY(flushOutsideRenderPassCommands()); - } - mHasAnyCommandsPendingSubmission = true; return angle::Result::Continue; } @@ -8275,16 +7990,31 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass(RenderPassClosureReason r ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit(reason)); - if (mHasDeferredFlush || hasExcessPendingGarbage()) + // In some cases, it is recommended to flush and submit the command buffer to boost performance + // or avoid too much memory allocation. + QueueSubmitReason submitReason; + if (mHasDeferredFlush) { - // If we have deferred glFlush call in the middle of render pass, or if there is too much - // pending garbage, perform a flush now. - RenderPassClosureReason flushImplReason = - (hasExcessPendingGarbage()) ? RenderPassClosureReason::ExcessivePendingGarbage - : RenderPassClosureReason::AlreadySpecifiedElsewhere; - ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, flushImplReason)); + // If we have deferred glFlush call in the middle of render pass, perform a flush now. + submitReason = QueueSubmitReason::DeferredFlush; } - return angle::Result::Continue; + else if (hasExcessPendingGarbage()) + { + // If there is too much pending garbage, perform a flush now. + submitReason = QueueSubmitReason::ExcessivePendingGarbage; + } + else if (mRenderPassCountSinceSubmit >= kMaxRenderPassCountPerCommandBuffer) + { + // If there are too many render passes in the command buffer, perform a flush now. + submitReason = QueueSubmitReason::RenderPassCountLimitReached; + } + else + { + // Let more commands accumulate before submitting the command buffer. + return angle::Result::Continue; + } + + return flushAndSubmitCommands(nullptr, nullptr, submitReason); } angle::Result ContextVk::flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator, @@ -8339,8 +8069,7 @@ angle::Result ContextVk::onSyncObjectInit(vk::SyncHelper *syncHelper, SyncFenceS // pass). if (scope != SyncFenceScope::CurrentContextToShareGroup || !mRenderPassCommands->started()) { - ANGLE_TRY( - flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::SyncObjectInit)); + ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::SyncObjectInit)); // Even if no commands is generated, and flushAndSubmitCommands bails out, queueSerial is // valid since Context initialization. It will always test finished/signaled. ASSERT(mLastSubmittedQueueSerial.valid()); @@ -8471,25 +8200,18 @@ uint32_t GetDriverUniformSize(vk::ErrorContext *context, PipelineType pipelineTy } } -angle::Result ContextVk::flushAndSubmitOutsideRenderPassCommands() +angle::Result ContextVk::flushAndSubmitOutsideRenderPassCommands(QueueSubmitReason reason) { ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushAndSubmitOutsideRenderPassCommands"); ANGLE_TRY(flushOutsideRenderPassCommands()); - return submitCommands(nullptr, nullptr, Submit::OutsideRenderPassCommandsOnly); + ASSERT(mLastFlushedQueueSerial.valid()); + ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial, + mLastFlushedQueueSerial)); + return submitCommands(nullptr, nullptr, reason); } angle::Result ContextVk::flushOutsideRenderPassCommands() { - if (!mWaitSemaphores.empty()) - { - ASSERT(mHasWaitSemaphoresPendingSubmission); - ANGLE_TRY(mRenderer->flushWaitSemaphores(getProtectionType(), mContextPriority, - std::move(mWaitSemaphores), - std::move(mWaitSemaphoreStageMasks))); - } - ASSERT(mWaitSemaphores.empty()); - ASSERT(mWaitSemaphoreStageMasks.empty()); - if (mOutsideRenderPassCommands->empty()) { return angle::Result::Continue; @@ -8520,8 +8242,7 @@ angle::Result ContextVk::flushOutsideRenderPassCommands() { mIsAnyHostVisibleBufferWritten = true; } - ANGLE_TRY(mRenderer->flushOutsideRPCommands(this, getProtectionType(), mContextPriority, - &mOutsideRenderPassCommands)); + ANGLE_TRY(mCommandState.flushOutsideRPCommands(this, &mOutsideRenderPassCommands)); // Make sure appropriate dirty bits are set, in case another thread makes a submission before // the next dispatch call. @@ -8581,6 +8302,7 @@ angle::Result ContextVk::beginRenderPassQuery(QueryVk *queryVk) ASSERT(mActiveRenderPassQueries[type] == nullptr); mActiveRenderPassQueries[type] = queryVk; + mActiveRenderPassQueryBitmask.set(type); return angle::Result::Continue; } @@ -8617,6 +8339,7 @@ angle::Result ContextVk::endRenderPassQuery(QueryVk *queryVk) ASSERT(mActiveRenderPassQueries[type] == queryVk); mActiveRenderPassQueries[type] = nullptr; + mActiveRenderPassQueryBitmask.reset(type); return angle::Result::Continue; } @@ -8701,6 +8424,8 @@ bool ContextVk::isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery( QueryVk *ContextVk::getActiveRenderPassQuery(gl::QueryType queryType) const { + ASSERT(mActiveRenderPassQueryBitmask[queryType] == + (mActiveRenderPassQueries[queryType] != nullptr)); return mActiveRenderPassQueries[queryType]; } @@ -8836,80 +8561,81 @@ angle::Result ContextVk::switchToReadOnlyDepthStencilMode(gl::Texture *texture, return angle::Result::Continue; } -angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access) +angle::Result ContextVk::onResourceAccess(const vk::CommandResources &resources) { - ANGLE_TRY(flushCommandBuffersIfNecessary(access)); + ANGLE_TRY(flushCommandBuffersIfNecessary(resources)); - for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages()) + for (const vk::CommandResourceImage &readImage : resources.getReadImages()) { - vk::ImageHelper *image = imageAccess.image; + vk::ImageHelper *image = readImage.image; ASSERT(!isRenderPassStartedAndUsesImage(*image)); - imageAccess.image->recordReadBarrier(this, imageAccess.aspectFlags, imageAccess.imageLayout, - mOutsideRenderPassCommands); - mOutsideRenderPassCommands->retainImage(image); + readImage.image->recordReadBarrier(this, readImage.aspectFlags, readImage.imageAccess, + mOutsideRenderPassCommands); + mOutsideRenderPassCommands->retainImage(mRenderer, image); } - for (const vk::CommandBufferImageSubresourceAccess &imageReadAccess : - access.getReadImageSubresources()) + for (const vk::CommandResourceImageSubresource &readImageSubresource : + resources.getReadImageSubresources()) { - vk::ImageHelper *image = imageReadAccess.access.image; + vk::ImageHelper *image = readImageSubresource.image.image; ASSERT(!isRenderPassStartedAndUsesImage(*image)); image->recordReadSubresourceBarrier( - this, imageReadAccess.access.aspectFlags, imageReadAccess.access.imageLayout, - imageReadAccess.levelStart, imageReadAccess.levelCount, imageReadAccess.layerStart, - imageReadAccess.layerCount, mOutsideRenderPassCommands); - mOutsideRenderPassCommands->retainImage(image); + this, readImageSubresource.image.aspectFlags, readImageSubresource.image.imageAccess, + readImageSubresource.levelStart, readImageSubresource.levelCount, + readImageSubresource.layerStart, readImageSubresource.layerCount, + mOutsideRenderPassCommands); + mOutsideRenderPassCommands->retainImage(mRenderer, image); } - for (const vk::CommandBufferImageSubresourceAccess &imageWrite : access.getWriteImages()) + for (const vk::CommandResourceImageSubresource &writeImage : resources.getWriteImages()) { - vk::ImageHelper *image = imageWrite.access.image; + vk::ImageHelper *image = writeImage.image.image; ASSERT(!isRenderPassStartedAndUsesImage(*image)); - image->recordWriteBarrier(this, imageWrite.access.aspectFlags, - imageWrite.access.imageLayout, imageWrite.levelStart, - imageWrite.levelCount, imageWrite.layerStart, - imageWrite.layerCount, mOutsideRenderPassCommands); - mOutsideRenderPassCommands->retainImage(image); - image->onWrite(imageWrite.levelStart, imageWrite.levelCount, imageWrite.layerStart, - imageWrite.layerCount, imageWrite.access.aspectFlags); + image->recordWriteBarrier(this, writeImage.image.aspectFlags, writeImage.image.imageAccess, + writeImage.levelStart, writeImage.levelCount, + writeImage.layerStart, writeImage.layerCount, + mOutsideRenderPassCommands); + mOutsideRenderPassCommands->retainImage(mRenderer, image); + image->onWrite(writeImage.levelStart, writeImage.levelCount, writeImage.layerStart, + writeImage.layerCount, writeImage.image.aspectFlags); } - for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers()) + for (const vk::CommandResourceBuffer &readBuffer : resources.getReadBuffers()) { - ASSERT(!isRenderPassStartedAndUsesBufferForWrite(*bufferAccess.buffer)); - ASSERT(!mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer)); + ASSERT(!isRenderPassStartedAndUsesBufferForWrite(*readBuffer.buffer)); + ASSERT(!mOutsideRenderPassCommands->usesBufferForWrite(*readBuffer.buffer)); - mOutsideRenderPassCommands->bufferRead(this, bufferAccess.accessType, bufferAccess.stage, - bufferAccess.buffer); + mOutsideRenderPassCommands->bufferRead(this, readBuffer.accessType, readBuffer.stage, + readBuffer.buffer); } - for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers()) + for (const vk::CommandResourceBuffer &writeBuffer : resources.getWriteBuffers()) { - ASSERT(!isRenderPassStartedAndUsesBuffer(*bufferAccess.buffer)); - ASSERT(!mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer)); + ASSERT(!isRenderPassStartedAndUsesBuffer(*writeBuffer.buffer)); + ASSERT(!mOutsideRenderPassCommands->usesBuffer(*writeBuffer.buffer)); - mOutsideRenderPassCommands->bufferWrite(this, bufferAccess.accessType, bufferAccess.stage, - bufferAccess.buffer); + mOutsideRenderPassCommands->bufferWrite(this, writeBuffer.accessType, writeBuffer.stage, + writeBuffer.buffer); } - for (const vk::CommandBufferBufferExternalAcquireRelease &bufferAcquireRelease : - access.getExternalAcquireReleaseBuffers()) + for (const vk::CommandResourceBufferExternalAcquireRelease &bufferAcquireRelease : + resources.getExternalAcquireReleaseBuffers()) { mOutsideRenderPassCommands->retainResourceForWrite(bufferAcquireRelease.buffer); } - for (const vk::CommandBufferResourceAccess &resourceAccess : access.getAccessResources()) + for (const vk::CommandResourceGeneric &genericResource : resources.getGenericResources()) { - mOutsideRenderPassCommands->retainResource(resourceAccess.resource); + mOutsideRenderPassCommands->retainResource(genericResource.resource); } return angle::Result::Continue; } -angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access) +angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandResources &resources) { // Go over resources and decide whether the render pass needs to close, whether the outside // render pass commands need to be flushed, or neither. Note that closing the render pass @@ -8919,13 +8645,13 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA // that once at the end. // Read images only need to close the render pass if they need a layout transition. - for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages()) + for (const vk::CommandResourceImage &readImage : resources.getReadImages()) { // Note that different read methods are not compatible. A shader read uses a different // layout than a transfer read. So we cannot support simultaneous read usage as easily as // for Buffers. TODO: Don't close the render pass if the image was only used read-only in // the render pass. http://anglebug.com/42263557 - if (isRenderPassStartedAndUsesImage(*imageAccess.image)) + if (isRenderPassStartedAndUsesImage(*readImage.image)) { return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead); } @@ -8934,19 +8660,19 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA // In cases where the image has both read and write permissions, the render pass should be // closed if there is a read from a previously written subresource (in a specific level/layer), // or a write to a previously read one. - for (const vk::CommandBufferImageSubresourceAccess &imageSubresourceAccess : - access.getReadImageSubresources()) + for (const vk::CommandResourceImageSubresource &readImageSubresource : + resources.getReadImageSubresources()) { - if (isRenderPassStartedAndUsesImage(*imageSubresourceAccess.access.image)) + if (isRenderPassStartedAndUsesImage(*readImageSubresource.image.image)) { return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead); } } // Write images only need to close the render pass if they need a layout transition. - for (const vk::CommandBufferImageSubresourceAccess &imageWrite : access.getWriteImages()) + for (const vk::CommandResourceImageSubresource &writeImage : resources.getWriteImages()) { - if (isRenderPassStartedAndUsesImage(*imageWrite.access.image)) + if (isRenderPassStartedAndUsesImage(*writeImage.image.image)) { return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPWrite); } @@ -8955,28 +8681,28 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA bool shouldCloseOutsideRenderPassCommands = false; // Read buffers only need a new command buffer if previously used for write. - for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers()) + for (const vk::CommandResourceBuffer &readBuffer : resources.getReadBuffers()) { - if (isRenderPassStartedAndUsesBufferForWrite(*bufferAccess.buffer)) + if (isRenderPassStartedAndUsesBufferForWrite(*readBuffer.buffer)) { return flushCommandsAndEndRenderPass( RenderPassClosureReason::BufferWriteThenOutOfRPRead); } - else if (mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer)) + else if (mOutsideRenderPassCommands->usesBufferForWrite(*readBuffer.buffer)) { shouldCloseOutsideRenderPassCommands = true; } } // Write buffers always need a new command buffer if previously used. - for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers()) + for (const vk::CommandResourceBuffer &writeBuffer : resources.getWriteBuffers()) { - if (isRenderPassStartedAndUsesBuffer(*bufferAccess.buffer)) + if (isRenderPassStartedAndUsesBuffer(*writeBuffer.buffer)) { return flushCommandsAndEndRenderPass( RenderPassClosureReason::BufferUseThenOutOfRPWrite); } - else if (mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer)) + else if (mOutsideRenderPassCommands->usesBuffer(*writeBuffer.buffer)) { shouldCloseOutsideRenderPassCommands = true; } @@ -8990,7 +8716,7 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA return angle::Result::Continue; } -angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite() +angle::Result ContextVk::endRenderPassIfUniformBufferReadAfterTransformFeedbackWrite() { // Similar to flushCommandBuffersIfNecessary(), but using uniform buffers currently bound and // used by the current (compute) program. This is to handle read-after-write hazards where the @@ -9001,7 +8727,7 @@ angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite() } const gl::ProgramExecutable *executable = mState.getProgramExecutable(); - ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute)); + ASSERT(executable); // Uniform buffers: const std::vector &blocks = executable->getUniformBlocks(); @@ -9020,7 +8746,8 @@ angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite() vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer(); if (buffer.writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial)) { - return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenComputeRead); + return flushCommandsAndEndRenderPass( + RenderPassClosureReason::XfbWriteThenUniformBufferRead); } } @@ -9101,15 +8828,30 @@ angle::Result ContextVk::endRenderPassIfComputeAccessAfterGraphicsImageAccess() return angle::Result::Continue; } +const angle::PerfMonitorCounterGroupsInfo &ContextVk::getPerfMonitorCountersInfo() const +{ + return mPerfMonitorCountersInfo; +} + const angle::PerfMonitorCounterGroups &ContextVk::getPerfMonitorCounters() { syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters()); - angle::PerfMonitorCounters &counters = - angle::GetPerfMonitorCounterGroup(mPerfMonitorCounters, "vulkan").counters; + ASSERT(mPerfMonitorCountersInfo.size() == 1); + ASSERT(mPerfMonitorCounters.size() == 1); + + const angle::PerfMonitorCounterGroupInfo &info = mPerfMonitorCountersInfo[0]; + angle::PerfMonitorCounters &counters = mPerfMonitorCounters[0].counters; -#define ANGLE_UPDATE_PERF_MAP(COUNTER) \ - angle::GetPerfMonitorCounter(counters, #COUNTER).value = mPerfCounters.COUNTER; + ASSERT(info.name == "vulkan"); + ASSERT(info.counters.size() == counters.size()); + + uint32_t counterIndex = 0; + +#define ANGLE_UPDATE_PERF_MAP(COUNTER) \ + ASSERT(info.counters.size() > counterIndex); \ + ASSERT(info.counters[counterIndex].name == #COUNTER); \ + counters[counterIndex++].value = mPerfCounters.COUNTER; ANGLE_VK_PERF_COUNTERS_X(ANGLE_UPDATE_PERF_MAP) @@ -9253,20 +8995,176 @@ void ContextVk::resetPerFramePerfCounters() .resetDescriptorCacheStats(); mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::Texture] .resetDescriptorCacheStats(); + mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::UniformBuffers] + .resetDescriptorCacheStats(); mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::ShaderResource] .resetDescriptorCacheStats(); } -angle::Result ContextVk::ensureInterfacePipelineCache() +angle::Result ContextVk::onVertexArrayChange(const gl::AttributesMask dirtyAttribBits) +{ + const VertexArrayVk &vertexArray = *getVertexArray(); + + if (ANGLE_UNLIKELY(!getFeatures().supportsVertexInputDynamicState.enabled)) + { + invalidateCurrentGraphicsPipeline(); + + for (size_t attribIndex : dirtyAttribBits) + { + const GLuint staticStride = + mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled + ? 0 + : vertexArray.getCurrentArrayBufferStride(attribIndex); + + GLuint divisor = vertexArray.getCurrentArrayBufferDivisor(attribIndex); + ASSERT(divisor <= mRenderer->getMaxVertexAttribDivisor()); + + mGraphicsPipelineDesc->updateVertexInput( + this, &mGraphicsPipelineTransition, static_cast(attribIndex), + staticStride, divisor, vertexArray.getCurrentArrayBufferFormatID(attribIndex), + vertexArray.getCurrentArrayBufferRelativeOffset(attribIndex)); + } + } + + if (ANGLE_UNLIKELY(mCurrentTransformFeedbackQueueSerial.valid())) + { + const gl::AttribArray &buffers = vertexArray.getCurrentArrayBuffers(); + bool breakRenderPass = false; + for (size_t attribIndex : dirtyAttribBits) + { + ASSERT(buffers[attribIndex] != nullptr); + if (buffers[attribIndex]->writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial)) + { + breakRenderPass = true; + break; + } + } + + if (breakRenderPass) + { + ANGLE_TRY(flushCommandsAndEndRenderPass( + RenderPassClosureReason::XfbWriteThenVertexIndexBuffer)); + } + } + + mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS); + return angle::Result::Continue; +} + +void ContextVk::addImageWithTileMemory(vk::ImageHelper *imageToAdd) +{ + ASSERT(imageToAdd->useTileMemory()); + if (std::find(mImagesWithTileMemory.begin(), mImagesWithTileMemory.end(), imageToAdd) != + mImagesWithTileMemory.end()) + { + // Already added. + return; + } + + // If this is first time added, it must have no valid data + ASSERT(!imageToAdd->isVkImageContentDefined()); + + if (getFeatures().supportsTileMemoryHeap.enabled) + { + mOutsideRenderPassCommands->getCommandBuffer().bindTileMemory( + imageToAdd->getDeviceMemory()); + } + + mImagesWithTileMemory.emplace_back(imageToAdd); +} + +void ContextVk::removeImageWithTileMemory(const vk::ImageHelper *imageToRemove) +{ + ASSERT(imageToRemove->useTileMemory()); + auto iter = + std::find(mImagesWithTileMemory.begin(), mImagesWithTileMemory.end(), imageToRemove); + if (iter != mImagesWithTileMemory.end()) + { + mImagesWithTileMemory.erase(iter); + } +} + +bool ContextVk::isImageWithTileMemoryFinalized(const vk::ImageHelper *image) const +{ + ASSERT(image->useTileMemory()); + return std::find(mImagesWithTileMemory.begin(), mImagesWithTileMemory.end(), image) == + mImagesWithTileMemory.end(); +} + +angle::Result ContextVk::finalizeImagesWithTileMemory() { - if (!mInterfacePipelinesCache.valid()) + ASSERT(!mImagesWithTileMemory.empty()); + + // Check all images with tile memory to see if they have valid content or not. tile memory are + // transient, we must reallocate to keep data valid across command buffer boundary. + for (auto iter = mImagesWithTileMemory.begin(); iter != mImagesWithTileMemory.end();) + { + vk::ImageHelper *image = *iter; + // Other context may have submitted command buffer and causes it fallback already, so check + // again. + if (image->isVkImageContentDefined() && image->useTileMemory()) + { + ANGLE_TRY(image->fallbackFromTileMemory(this)); + ASSERT(!image->useTileMemory()); + iter = mImagesWithTileMemory.erase(iter); + } + else + { + ++iter; + } + } + + if (getFeatures().supportsTileMemoryHeap.enabled) + { + // We dont explicitly unbind tileMemory here. They occur implicitly at endCommandBiuffer + // time + } + else { - VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; - pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + ASSERT(getFeatures().simulateTileMemoryForTesting.enabled); - ANGLE_VK_TRY(this, mInterfacePipelinesCache.init(getDevice(), pipelineCacheCreateInfo)); + // clear VkImage to simulate the transient nature of tile memory + UtilsVk::ClearTextureParameters params = {}; + params.level = vk::LevelIndex(0); + params.layer = 0; + params.clearValue = {}; + params.clearArea = gl::Box(0, 0, 0, 0, 0, 1); + for (vk::ImageHelper *image : mImagesWithTileMemory) + { + // Other context may have triggered fallback already, so check + // again. + if (image->useTileMemory() && !image->isVkImageContentDefined()) + { + params.aspectFlags = image->getAspectFlags(); + params.clearArea.width = image->getExtents().width; + params.clearArea.height = image->getExtents().height; + ANGLE_TRY(mUtils.clearTextureNoFlush(this, image, params)); + + // Since this may called from submitCommands, use no submit version to avoid + // recursion. + ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit( + RenderPassClosureReason::TileMemorySimulatedClear)); + ASSERT(mLastFlushedQueueSerial > mLastSubmittedQueueSerial); + + // clearTextureNoFlush may have set content valid again, remove the bits to keep + // content as invalid. + image->invalidateEntireLevelContent(this, gl::LevelIndex(0)); + image->invalidateEntireLevelStencilContent(this, gl::LevelIndex(0)); + } + } } + mImagesWithTileMemory.clear(); + return angle::Result::Continue; } + +void ContextVk::restoreAllGraphicsState() +{ + // Recover states that may have been changed by UtilsVk::depthStencilBlitResolve. We dirty all + // states except DIRTY_BIT_RENDER_PASS so that render pass could still reused. + DirtyBits allDrawStateDirtyBits = + mNewGraphicsCommandBufferDirtyBits & ~DirtyBits{DIRTY_BIT_RENDER_PASS}; + mGraphicsDirtyBits |= allDrawStateDirtyBits; +} } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h index 6671d42b824..e3905b5a6f6 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.h +++ b/src/libANGLE/renderer/vulkan/ContextVk.h @@ -42,9 +42,6 @@ class WindowSurfaceVk; class OffscreenSurfaceVk; class ShareGroupVk; -static constexpr uint32_t kMaxGpuEventNameLen = 32; -using EventName = std::array; - using ContextVkDescriptorSetList = angle::PackedEnumMap; using CounterPipelineTypeMap = angle::PackedEnumMap; @@ -319,6 +316,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText const gl::Limitations &getNativeLimitations() const override; const ShPixelLocalStorageOptions &getNativePixelLocalStorageOptions() const override; + // FragmentShadingRateEXT + const angle::ShadingRateMap &getSupportedFragmentShadingRateEXTSampleCounts() const override; + // Shader creation CompilerImpl *createCompiler() override; ShaderImpl *createShader(const gl::ShaderState &state) override; @@ -339,7 +339,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; @@ -393,14 +394,14 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // Sets effective Context Priority. Changed by ShareGroupVk. void setPriority(egl::ContextPriority newPriority) { - mContextPriority = newPriority; - mDeviceQueueIndex = mRenderer->getDeviceQueueIndex(mContextPriority); + mCommandState.setPriority(newPriority); + mDeviceQueueIndex = mRenderer->getDeviceQueueIndex(newPriority); } VkDevice getDevice() const; // Effective Context Priority - egl::ContextPriority getPriority() const { return mContextPriority; } - vk::ProtectionType getProtectionType() const { return mProtectionType; } + egl::ContextPriority getPriority() const { return mCommandState.getPriority(); } + vk::ProtectionType getProtectionType() const { return mCommandState.getProtectionType(); } ANGLE_INLINE const angle::FeaturesVk &getFeatures() const { return mRenderer->getFeatures(); } @@ -409,15 +410,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText mGraphicsDirtyBits |= kIndexAndVertexDirtyBits; } - angle::Result onVertexBufferChange(const vk::BufferHelper *vertexBuffer); - - angle::Result onVertexAttributeChange(size_t attribIndex, - GLuint stride, - GLuint divisor, - angle::FormatID format, - bool compressed, - GLuint relativeOffset, - const vk::BufferHelper *vertexBuffer); + angle::Result onVertexArrayChange(const gl::AttributesMask dirtyAttribBits); void invalidateDefaultAttribute(size_t attribIndex); void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask); @@ -454,7 +447,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText angle::Result optimizeRenderPassForPresent(vk::ImageViewHelper *colorImageView, vk::ImageHelper *colorImage, vk::ImageHelper *colorImageMS, - vk::PresentMode presentMode, + bool isSharedPresentMode, bool *imageResolved); vk::DynamicQueryPool *getQueryPool(gl::QueryType queryType); @@ -479,11 +472,14 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText angle::Result flushAndSubmitCommands(const vk::Semaphore *semaphore, const vk::SharedExternalFence *externalFence, - RenderPassClosureReason renderPassClosureReason); + QueueSubmitReason queueSubmitReason); - angle::Result finishImpl(RenderPassClosureReason renderPassClosureReason); + angle::Result finishImpl(QueueSubmitReason queueSubmitReason); - void addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask); + void addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask) + { + mCommandState.addWaitSemaphore(semaphore, stageMask); + } template void addGarbage(T *object) @@ -505,18 +501,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText angle::Result getTimestamp(uint64_t *timestampOut); - // Create Begin/End/Instant GPU trace events, which take their timestamps from GPU queries. - // The events are queued until the query results are available. Possible values for `phase` - // are TRACE_EVENT_PHASE_* - ANGLE_INLINE angle::Result traceGpuEvent(vk::OutsideRenderPassCommandBuffer *commandBuffer, - char phase, - const EventName &name) - { - if (mGpuEventsEnabled) - return traceGpuEventImpl(commandBuffer, phase, name); - return angle::Result::Continue; - } - const gl::Debug &getDebug() const { return mState.getDebug(); } const gl::OverlayType *getOverlay() const { return mState.getOverlay(); } @@ -524,23 +508,23 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText angle::Result onImageReleaseToExternal(const vk::ImageHelper &image); void onImageRenderPassRead(VkImageAspectFlags aspectFlags, - vk::ImageLayout imageLayout, + vk::ImageAccess imageAccess, vk::ImageHelper *image) { ASSERT(mRenderPassCommands->started()); - mRenderPassCommands->imageRead(this, aspectFlags, imageLayout, image); + mRenderPassCommands->imageRead(this, aspectFlags, imageAccess, image); } void onImageRenderPassWrite(gl::LevelIndex level, uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - vk::ImageLayout imageLayout, + vk::ImageAccess imageAccess, vk::ImageHelper *image) { ASSERT(mRenderPassCommands->started()); mRenderPassCommands->imageWrite(this, level, layerStart, layerCount, aspectFlags, - imageLayout, image); + imageAccess, image); } void onColorDraw(gl::LevelIndex level, @@ -577,6 +561,15 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ASSERT(mRenderPassCommands->started()); mRenderPassCommands->depthStencilImagesDraw(level, layerStart, layerCount, image, resolveImage, imageSiblingSerial); + + if (image && image->useTileMemory()) + { + addImageWithTileMemory(image); + } + if (resolveImage && resolveImage->useTileMemory()) + { + addImageWithTileMemory(resolveImage); + } } void onDepthStencilResolve(gl::LevelIndex level, uint32_t layerStart, @@ -587,6 +580,10 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText UniqueSerial imageSiblingSerial) { ASSERT(mRenderPassCommands->started()); + if (image && image->useTileMemory()) + { + addImageWithTileMemory(image); + } mRenderPassCommands->addDepthStencilResolveAttachment( image, view, aspects, level, layerStart, layerCount, imageSiblingSerial); } @@ -600,19 +597,19 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText void finalizeImageLayout(vk::ImageHelper *image, UniqueSerial imageSiblingSerial); angle::Result getOutsideRenderPassCommandBuffer( - const vk::CommandBufferAccess &access, + const vk::CommandResources &resources, vk::OutsideRenderPassCommandBuffer **commandBufferOut) { - ANGLE_TRY(onResourceAccess(access)); + ANGLE_TRY(onResourceAccess(resources)); *commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer(); return angle::Result::Continue; } angle::Result getOutsideRenderPassCommandBufferHelper( - const vk::CommandBufferAccess &access, + const vk::CommandResources &resources, vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut) { - ANGLE_TRY(onResourceAccess(access)); + ANGLE_TRY(onResourceAccess(resources)); *commandBufferHelperOut = mOutsideRenderPassCommands; return angle::Result::Continue; } @@ -627,7 +624,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText angle::Result submitStagedTextureUpdates() { // Staged updates are recorded in outside RP command buffer, submit them. - return flushOutsideRenderPassCommands(); + return flushAndSubmitOutsideRenderPassCommands(QueueSubmitReason::ForceSubmitStagedTexture); } angle::Result beginNewRenderPass(vk::RenderPassFramebuffer &&framebuffer, @@ -641,6 +638,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText void disableRenderPassReactivation() { mAllowRenderPassToReactivate = false; } + bool hasStartedRenderPass() const { return mRenderPassCommands->started(); } + // Only returns true if we have a started RP and we've run setupDraw. bool hasActiveRenderPass() const { @@ -699,7 +698,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText angle::Result startNextSubpass(); angle::Result flushCommandsAndEndRenderPass(RenderPassClosureReason reason); angle::Result flushCommandsAndEndRenderPassWithoutSubmit(RenderPassClosureReason reason); - angle::Result flushAndSubmitOutsideRenderPassCommands(); + angle::Result flushAndSubmitOutsideRenderPassCommands(QueueSubmitReason reason); angle::Result syncExternalMemory(); @@ -795,6 +794,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText return mIsInColorFramebufferFetchMode; } + const angle::PerfMonitorCounterGroupsInfo &getPerfMonitorCountersInfo() const override; const angle::PerfMonitorCounterGroups &getPerfMonitorCounters() override; void resetPerFramePerfCounters(); @@ -861,8 +861,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText BufferUsageType bufferUsageType); angle::Result initImageAllocation(vk::ImageHelper *imageHelper, bool hasProtectedContent, - const vk::MemoryProperties &memoryProperties, - VkMemoryPropertyFlags flags, + VkMemoryPropertyFlags memoryPropertyFlags, vk::MemoryAllocationType allocationType); angle::Result releaseBufferAllocation(vk::BufferHelper *bufferHelper); @@ -889,10 +888,18 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText bool hasExcessPendingGarbage() const; - angle::Result onFramebufferBoundary(const gl::Context *contextGL); + angle::Result onFrameBoundary(const gl::Context *contextGL); uint32_t getCurrentFrameCount() const { return mShareGroupVk->getCurrentFrameCount(); } + bool isImageWithTileMemoryFinalized(const vk::ImageHelper *image) const; + void addImageWithTileMemory(vk::ImageHelper *imageToAdd); + void removeImageWithTileMemory(const vk::ImageHelper *imageToRemove); + + // Restore all graphics state based on current gl::State. + void restoreAllGraphicsState(); + bool hasActiveRenderPassQuery() const { return mActiveRenderPassQueryBitmask.any(); } + private: // Dirty bits. enum DirtyBitType : size_t @@ -930,9 +937,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText DIRTY_BIT_INDEX_BUFFER, DIRTY_BIT_UNIFORMS, DIRTY_BIT_DRIVER_UNIFORMS, - // Shader resources excluding textures, which are handled separately. - DIRTY_BIT_SHADER_RESOURCES, DIRTY_BIT_UNIFORM_BUFFERS, + // Shader resources excluding uniform buffers and textures, which are handled separately. + DIRTY_BIT_SHADER_RESOURCES, DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS, DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME, DIRTY_BIT_DESCRIPTOR_SETS, @@ -952,6 +959,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // - In VK_EXT_extended_dynamic_state DIRTY_BIT_DYNAMIC_CULL_MODE, DIRTY_BIT_DYNAMIC_FRONT_FACE, + DIRTY_BIT_DYNAMIC_PRIMITIVE_TOPOLOGY, DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE, DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE, DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP, @@ -1006,9 +1014,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText "Render pass using dirty bit must be handled after the render pass dirty bit"); static_assert(DIRTY_BIT_SHADER_RESOURCES > DIRTY_BIT_RENDER_PASS, "Render pass using dirty bit must be handled after the render pass dirty bit"); - static_assert( - DIRTY_BIT_UNIFORM_BUFFERS > DIRTY_BIT_SHADER_RESOURCES, - "Uniform buffer using dirty bit must be handled after the shader resource dirty bit"); static_assert(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS > DIRTY_BIT_RENDER_PASS, "Render pass using dirty bit must be handled after the render pass dirty bit"); static_assert(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME > DIRTY_BIT_RENDER_PASS, @@ -1041,6 +1046,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText "Render pass using dirty bit must be handled after the render pass dirty bit"); static_assert(DIRTY_BIT_DYNAMIC_FRONT_FACE > DIRTY_BIT_RENDER_PASS, "Render pass using dirty bit must be handled after the render pass dirty bit"); + static_assert(DIRTY_BIT_DYNAMIC_PRIMITIVE_TOPOLOGY > DIRTY_BIT_RENDER_PASS, + "Render pass using dirty bit must be handled after the render pass dirty bit"); static_assert(DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE > DIRTY_BIT_RENDER_PASS, "Render pass using dirty bit must be handled after the render pass dirty bit"); static_assert(DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE > DIRTY_BIT_RENDER_PASS, @@ -1069,39 +1076,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText using ComputeDirtyBitHandler = angle::Result (ContextVk::*)(DirtyBits::Iterator *dirtyBitsIterator); - // The GpuEventQuery struct holds together a timestamp query and enough data to create a - // trace event based on that. Use traceGpuEvent to insert such queries. They will be readback - // when the results are available, without inserting a GPU bubble. - // - // - eventName will be the reported name of the event - // - phase is either 'B' (duration begin), 'E' (duration end) or 'i' (instant // event). - // See Google's "Trace Event Format": - // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU - // - serial is the serial of the batch the query was submitted on. Until the batch is - // submitted, the query is not checked to avoid incuring a flush. - struct GpuEventQuery final - { - EventName name; - char phase; - vk::QueryHelper queryHelper; - }; - - // Once a query result is available, the timestamp is read and a GpuEvent object is kept until - // the next clock sync, at which point the clock drift is compensated in the results before - // handing them off to the application. - struct GpuEvent final - { - uint64_t gpuTimestampCycles; - std::array name; - char phase; - }; - - struct GpuClockSyncInfo - { - double gpuTimestampS; - double cpuTimestampS; - }; - class ScopedDescriptorSetUpdates; bool isSingleBufferedWindowCurrent() const; @@ -1160,6 +1134,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText float nearPlane, float farPlane); void updateFrontFace(); + void updateTopology(gl::PrimitiveMode mode); void updateDepthRange(float nearPlane, float farPlane); void updateMissingAttachments(); void updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples); @@ -1193,11 +1168,12 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText void invalidateCurrentDefaultUniforms(); angle::Result invalidateCurrentTextures(const gl::Context *context, gl::Command command); angle::Result invalidateCurrentShaderResources(gl::Command command); - angle::Result invalidateCurrentShaderUniformBuffers(gl::Command command); + angle::Result invalidateCurrentShaderUniformBuffers(); void invalidateGraphicsDriverUniforms(); void invalidateDriverUniforms(); angle::Result handleNoopDrawEvent() override; + angle::Result handleNoopMultiDrawEvent() override; // Handlers for graphics pipeline dirty bits. angle::Result handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator, @@ -1223,8 +1199,12 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText DirtyBits dirtyBitMask); angle::Result handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask); - angle::Result handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator, - DirtyBits dirtyBitMask); + angle::Result handleDirtyGraphicsVertexBuffersVertexInputDynamicStateEnabled( + DirtyBits::Iterator *dirtyBitsIterator, + DirtyBits dirtyBitMask); + angle::Result handleDirtyGraphicsVertexBuffersVertexInputDynamicStateDisabled( + DirtyBits::Iterator *dirtyBitsIterator, + DirtyBits dirtyBitMask); angle::Result handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask); angle::Result handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator, @@ -1270,6 +1250,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText DirtyBits dirtyBitMask); angle::Result handleDirtyGraphicsDynamicFrontFace(DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask); + angle::Result handleDirtyGraphicsDynamicPrimitiveTopology( + DirtyBits::Iterator *dirtyBitsIterator, + DirtyBits dirtyBitMask); angle::Result handleDirtyGraphicsDynamicDepthTestEnable(DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask); angle::Result handleDirtyGraphicsDynamicDepthWriteEnable(DirtyBits::Iterator *dirtyBitsIterator, @@ -1329,23 +1312,14 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText void writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut, size_t offsetsSize); - enum class Submit - { - OutsideRenderPassCommandsOnly, - AllCommands, - }; + void updateUniformBufferBlocksOffset(); + void prepareToSubmitAllCommands(); angle::Result submitCommands(const vk::Semaphore *signalSemaphore, const vk::SharedExternalFence *externalFence, - Submit submission); + QueueSubmitReason reason); angle::Result flushImpl(const gl::Context *context); - angle::Result synchronizeCpuGpuTime(); - angle::Result traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer, - char phase, - const EventName &name); - angle::Result checkCompletedGpuEvents(); - void flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS); void handleDeviceLost(); bool shouldEmulateSeamfulCubeMapSampling() const; void clearAllGarbage(); @@ -1378,12 +1352,12 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // preserve the order of operations: // // - Transform feedback write (in render pass), then vertex/index read (in render pass) - // - Transform feedback write (in render pass), then ubo read (outside render pass) + // - Transform feedback write (in render pass), then ubo read (inside/outside render pass) // - Framebuffer attachment write (in render pass), then texture sample (outside render pass) // * Note that texture sampling inside render pass would cause a feedback loop // angle::Result endRenderPassIfTransformFeedbackBuffer(const vk::BufferHelper *buffer); - angle::Result endRenderPassIfComputeReadAfterTransformFeedbackWrite(); + angle::Result endRenderPassIfUniformBufferReadAfterTransformFeedbackWrite(); angle::Result endRenderPassIfComputeAccessAfterGraphicsImageAccess(); // Update read-only depth feedback loop mode. Typically called from @@ -1398,8 +1372,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText FramebufferVk *drawFramebuffer, bool isStencilTexture); - angle::Result onResourceAccess(const vk::CommandBufferAccess &access); - angle::Result flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access); + angle::Result onResourceAccess(const vk::CommandResources &resources); + angle::Result flushCommandBuffersIfNecessary(const vk::CommandResources &resources); bool renderPassUsesStorageResources() const; angle::Result pushDebugGroupImpl(GLenum source, GLuint id, const char *message); @@ -1437,9 +1411,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // avoided however, as on the affected driver that would disable certain optimizations. void updateStencilWriteWorkaround(); - void updateShaderResourcesWithSharedCacheKey( - const vk::SharedDescriptorSetCacheKey &sharedCacheKey); - angle::Result createGraphicsPipeline(); angle::Result allocateQueueSerialIndex(); @@ -1448,7 +1419,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText void generateOutsideRenderPassCommandsQueueSerial(); void generateRenderPassCommandsQueueSerial(QueueSerial *queueSerialOut); - angle::Result ensureInterfacePipelineCache(); + angle::Result finalizeImagesWithTileMemory(); angle::ImageLoadContext mImageLoadContext; @@ -1459,8 +1430,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText vk::PipelineHelper *mCurrentGraphicsPipeline; vk::PipelineHelper *mCurrentGraphicsPipelineShaders; - vk::PipelineHelper *mCurrentGraphicsPipelineVertexInput; - vk::PipelineHelper *mCurrentGraphicsPipelineFragmentOutput; vk::PipelineHelper *mCurrentComputePipeline; gl::PrimitiveMode mCurrentDrawMode; @@ -1510,6 +1479,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // - Occlusion queries // - Transform feedback queries, if not emulated gl::QueryTypeMap mActiveRenderPassQueries; + gl::QueryTypeBitSet mActiveRenderPassQueryBitmask; // Dirty bits. DirtyBits mGraphicsDirtyBits; @@ -1561,6 +1531,10 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText IncompleteTextureSet mIncompleteTextures; + // Track sample shading state, this helps avoid redundant work by + // conditionally dirtying DIRTY_BIT_SAMPLE_SHADING bit + bool mSampleShadingEnabled; + // If the current surface bound to this context wants to have all rendering flipped vertically. // Updated on calls to onMakeCurrent. bool mFlipYForCurrentSurface; @@ -1574,10 +1548,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // This info is used in the descriptor update step. gl::ActiveTextureArray mActiveTextures; - vk::DescriptorSetDescBuilder mShaderBuffersDescriptorDesc; - // The WriteDescriptorDescs from ProgramExecutableVk with InputAttachment update. - vk::WriteDescriptorDescs mShaderBufferWriteDescriptorDescs; - gl::ActiveTextureArray mActiveImages; // "Current Value" aka default vertex attribute state. @@ -1589,6 +1559,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText gl::AttribArray mStreamedVertexBuffers; gl::AttributesMask mHasInFlightStreamedVertexBuffers; + std::vector mImagesWithTileMemory; + // We use a single pool for recording commands. We also keep a free list for pool recycling. vk::SecondaryCommandPools mCommandPools; @@ -1601,6 +1573,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // Current active transform feedback buffer queue serial. Invalid if TF not active. QueueSerial mCurrentTransformFeedbackQueueSerial; + egl::ContextPriority mInitialContextPriority; + // The garbage list for single context use objects. The list will be GPU tracked by next // submission queueSerial. Note: Resource based shared object should always be added to // renderer's mSharedGarbageList. @@ -1610,14 +1584,12 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // Used with dynamic rendering as it doesn't use render passes. vk::RenderPass mNullRenderPass; + // vulkan primary command buffer + vk::CommandsState mCommandState; + vk::OutsideRenderPassCommandBufferHelper *mOutsideRenderPassCommands; vk::RenderPassCommandBufferHelper *mRenderPassCommands; - // Allocators for the render pass command buffers. They are utilized only when shared ring - // buffer allocators are being used. - vk::SecondaryCommandMemoryAllocator mOutsideRenderPassCommandsAllocator; - vk::SecondaryCommandMemoryAllocator mRenderPassCommandsAllocator; - // The following is used when creating debug-util markers for graphics debuggers (e.g. AGI). A // given gl{Begin|End}Query command may result in commands being submitted to the outside or // render-pass command buffer. The ContextVk::handleGraphicsEventLog() method records the @@ -1633,13 +1605,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText vk::ShaderLibrary mShaderLibrary; UtilsVk mUtils; - bool mGpuEventsEnabled; - vk::DynamicQueryPool mGpuEventQueryPool; - // A list of queries that have yet to be turned into an event (their result is not yet - // available). - std::vector mInFlightGpuEventQueries; - // A list of gpu events since the last clock sync. - std::vector mGpuEvents; // The current frame index, used to generate a submission-encompassing event tagged with it. uint32_t mPrimaryBufferEventCounter; @@ -1677,35 +1642,23 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // True if current started render pass is allowed to reactivate. bool mAllowRenderPassToReactivate; + // This flag indicates whether size pointer should be used as arg for binding vertex buffers. + bool mUseSizePointerForBindingVertexBuffers; + // The size of copy commands issued between buffers and images. Used to submit the command // buffer for the outside render pass. VkDeviceSize mTotalBufferToImageCopySize; VkDeviceSize mEstimatedPendingImageGarbageSize; - // Semaphores that must be flushed before the current commands. Flushed semaphores will be - // waited on in the next submission. - std::vector mWaitSemaphores; - std::vector mWaitSemaphoreStageMasks; - // Whether this context has wait semaphores (flushed and unflushed) that must be submitted. - bool mHasWaitSemaphoresPendingSubmission; - - // Hold information from the last gpu clock sync for future gpu-to-cpu timestamp conversions. - GpuClockSyncInfo mGpuClockSync; - - // The very first timestamp queried for a GPU event is used as origin, so event timestamps would - // have a value close to zero, to avoid losing 12 bits when converting these 64 bit values to - // double. - uint64_t mGpuEventTimestampOrigin; + // The number of render passes since the last submission of all commands. + VkDeviceSize mRenderPassCountSinceSubmit; // A mix of per-frame and per-run counters. + angle::PerfMonitorCounterGroupsInfo mPerfMonitorCountersInfo; angle::PerfMonitorCounterGroups mPerfMonitorCounters; gl::state::DirtyBits mPipelineDirtyBitsMask; - egl::ContextPriority mInitialContextPriority; - egl::ContextPriority mContextPriority; - vk::ProtectionType mProtectionType; - ShareGroupVk *mShareGroupVk; // This is a special "empty" placeholder buffer for use when we just need a placeholder buffer @@ -1729,6 +1682,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText VulkanCacheStats mVulkanCacheStats; RangedSerialFactory mOutsideRenderPassSerialFactory; + + uint32_t mCommandsPendingSubmissionCount; }; ANGLE_INLINE angle::Result ContextVk::endRenderPassIfTransformFeedbackBuffer( @@ -1751,36 +1706,6 @@ ANGLE_INLINE angle::Result ContextVk::onIndexBufferChange( return endRenderPassIfTransformFeedbackBuffer(currentIndexBuffer); } -ANGLE_INLINE angle::Result ContextVk::onVertexBufferChange(const vk::BufferHelper *vertexBuffer) -{ - mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS); - return endRenderPassIfTransformFeedbackBuffer(vertexBuffer); -} - -ANGLE_INLINE angle::Result ContextVk::onVertexAttributeChange(size_t attribIndex, - GLuint stride, - GLuint divisor, - angle::FormatID format, - bool compressed, - GLuint relativeOffset, - const vk::BufferHelper *vertexBuffer) -{ - const GLuint staticStride = - mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled ? 0 : stride; - - if (!getFeatures().supportsVertexInputDynamicState.enabled) - { - invalidateCurrentGraphicsPipeline(); - - // Set divisor to 1 for attribs with emulated divisor - mGraphicsPipelineDesc->updateVertexInput( - this, &mGraphicsPipelineTransition, static_cast(attribIndex), staticStride, - divisor > mRenderer->getMaxVertexAttribDivisor() ? 1 : divisor, format, compressed, - relativeOffset); - } - return onVertexBufferChange(vertexBuffer); -} - ANGLE_INLINE bool ContextVk::hasUnsubmittedUse(const vk::ResourceUse &use) const { return mCurrentQueueSerialIndex != kInvalidQueueSerialIndex && diff --git a/src/libANGLE/renderer/vulkan/DeviceVk.cpp b/src/libANGLE/renderer/vulkan/DeviceVk.cpp index 9196874089b..96cfe95de03 100644 --- a/src/libANGLE/renderer/vulkan/DeviceVk.cpp +++ b/src/libANGLE/renderer/vulkan/DeviceVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for DeviceVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/DeviceVk.h" #include diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/src/libANGLE/renderer/vulkan/DisplayVk.cpp index b24d1ce2cd3..49a93515ab8 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.cpp +++ b/src/libANGLE/renderer/vulkan/DisplayVk.cpp @@ -261,8 +261,7 @@ egl::Error DisplayVk::waitClient(const gl::Context *context) { ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient"); ContextVk *contextVk = vk::GetImpl(context); - return angle::ToEGL(contextVk->finishImpl(RenderPassClosureReason::EGLWaitClient), - EGL_BAD_ACCESS); + return angle::ToEGL(contextVk->finishImpl(QueueSubmitReason::EGLWaitClient), EGL_BAD_ACCESS); } egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine) @@ -559,8 +558,8 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const // also be exposed. The Vulkan extensions that support these EGL extensions are not split in // the same way; both Vulkan extensions are needed for EGL_EXT_image_dma_buf_import, and with // both Vulkan extensions, EGL_EXT_image_dma_buf_import_modifiers is also supportable. - outExtensions->imageDmaBufImportEXT = - getFeatures().supportsExternalMemoryDmaBufAndModifiers.enabled; + outExtensions->imageDmaBufImportEXT = getFeatures().supportsExternalMemoryDmaBuf.enabled && + getFeatures().supportsImageDrmFormatModifier.enabled; outExtensions->imageDmaBufImportModifiersEXT = outExtensions->imageDmaBufImportEXT; // Disable context priority when non-zero memory init is enabled. This enforces a queue order. @@ -571,13 +570,9 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const outExtensions->nativeFenceSyncANDROID = getFeatures().supportsAndroidNativeFenceSync.enabled; #endif // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX) -#if defined(ANGLE_PLATFORM_GGP) - outExtensions->ggpStreamDescriptor = true; - outExtensions->swapWithFrameToken = getFeatures().supportsGGPFrameToken.enabled; -#endif // defined(ANGLE_PLATFORM_GGP) - outExtensions->bufferAgeEXT = true; + outExtensions->presentationTime = getFeatures().supportsTimestampSurfaceAttribute.enabled; outExtensions->protectedContentEXT = (getFeatures().supportsProtectedMemory.enabled && getFeatures().supportsSurfaceProtectedSwapchains.enabled); @@ -623,6 +618,9 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const outExtensions->surfaceCompressionEXT = getFeatures().supportsImageCompressionControlSwapchain.enabled; + + outExtensions->contextPriorityRealtimeNV = (getFeatures().supportsGlobalPriority.enabled && + getFeatures().supportsGlobalPriorityQuery.enabled); } void DisplayVk::generateCaps(egl::Caps *outCaps) const @@ -729,8 +727,8 @@ egl::Error DisplayVk::querySupportedCompressionRates(const egl::Config *configur vk::GetVkFormatFromFormatID(mRenderer, format.getActualRenderableImageFormatID()); imageFormatInfo.type = VK_IMAGE_TYPE_2D; imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageFormatInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + imageFormatInfo.usage = vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; VkImageCompressionPropertiesEXT compressionProperties = {}; diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.h b/src/libANGLE/renderer/vulkan/DisplayVk.h index 365a4e28647..4f018d3dc00 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.h +++ b/src/libANGLE/renderer/vulkan/DisplayVk.h @@ -138,6 +138,7 @@ class DisplayVk : public DisplayImpl, public vk::ErrorContext, public vk::Global std::shared_ptr postMultiThreadWorkerTask( const std::shared_ptr &task) override; void notifyDeviceLost() override; + GlobalOps::Api getFrontendApi() const override { return GlobalOps::Api::Egl; } angle::ScratchBuffer mScratchBuffer; diff --git a/src/libANGLE/renderer/vulkan/DisplayVk_api.h b/src/libANGLE/renderer/vulkan/DisplayVk_api.h index 459dfc298ca..56a818c8ee6 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk_api.h +++ b/src/libANGLE/renderer/vulkan/DisplayVk_api.h @@ -53,11 +53,6 @@ bool IsVulkanFuchsiaDisplayAvailable(); DisplayImpl *CreateVulkanFuchsiaDisplay(const egl::DisplayState &state); #endif // defined(ANGLE_PLATFORM_FUCHSIA) -#if defined(ANGLE_PLATFORM_GGP) -bool IsVulkanGGPDisplayAvailable(); -DisplayImpl *CreateVulkanGGPDisplay(const egl::DisplayState &state); -#endif // defined(ANGLE_PLATFORM_GGP) - #if defined(ANGLE_PLATFORM_APPLE) bool IsVulkanMacDisplayAvailable(); DisplayImpl *CreateVulkanMacDisplay(const egl::DisplayState &state); diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp index cf370a5da78..88e4a1c1a6d 100644 --- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for FramebufferVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/FramebufferVk.h" #include @@ -43,13 +47,15 @@ constexpr unsigned int kEmulatedAlphaValue = 1; bool HasSrcBlitFeature(vk::Renderer *renderer, RenderTargetVk *srcRenderTarget) { angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID(); - return renderer->hasImageFormatFeatureBits(srcFormatID, VK_FORMAT_FEATURE_BLIT_SRC_BIT); + return renderer->hasImageFormatFeatureBits(srcFormatID, VK_FORMAT_FEATURE_BLIT_SRC_BIT) && + srcRenderTarget->getImageForCopy().canTransferFrom(); } bool HasDstBlitFeature(vk::Renderer *renderer, RenderTargetVk *dstRenderTarget) { angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID(); - return renderer->hasImageFormatFeatureBits(dstFormatID, VK_FORMAT_FEATURE_BLIT_DST_BIT); + return renderer->hasImageFormatFeatureBits(dstFormatID, VK_FORMAT_FEATURE_BLIT_DST_BIT) && + dstRenderTarget->getImageForWrite().canTransferTo(); } // Returns false if destination has any channel the source doesn't. This means that channel was @@ -257,6 +263,88 @@ void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle, } } +void AdjustBlitAreas(RenderTargetVk *readRenderTarget, + gl::Rectangle *sourceArea, + gl::Rectangle *destArea, + gl::Rectangle *srcFramebufferDimensions, + const gl::Rectangle &dstFramebufferDimensions, + SurfaceRotation srcFramebufferRotation, + SurfaceRotation *dstFramebufferRotation, + SurfaceRotation rotation, + bool srcFramebufferFlippedY, + bool dstFramebufferFlippedY, + const bool isResolve, + bool *flipX, + bool *flipY, + const bool isDefault, + UtilsVk::BlitResolveParameters *params) +{ + const gl::Extents readExtent = readRenderTarget->getExtents(); + gl::Rectangle srcAttachmentDimensions = + gl::Rectangle(0, 0, readExtent.width, readExtent.height); + if (isDefault) + { + // The readExtent size of the default framebuffer is the same as the window size. Choose + // to use the framebuffer size instead. + srcAttachmentDimensions = *srcFramebufferDimensions; + } + // If framebuffers are flipped in Y, flip the source and destination area (which define the + // transformation regardless of clipping), as well as the blit area (which is the clipped + // destination area). + if (srcFramebufferFlippedY) + { + sourceArea->y = srcAttachmentDimensions.height - sourceArea->y; + sourceArea->height = -sourceArea->height; + } + + *flipX = sourceArea->isReversedX() != destArea->isReversedX(); + *flipY = sourceArea->isReversedY() != destArea->isReversedY(); + + // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve. + ASSERT(!isResolve || + (*flipX == false && *flipY == (srcFramebufferFlippedY != dstFramebufferFlippedY))); + + // Again, transfer the destination flip to source, so destination is unflipped. Note that + // destArea was not reversed until the final possible Y-flip. + ASSERT(!destArea->isReversedX()); + *sourceArea = sourceArea->flip(false, destArea->isReversedY()); + *destArea = destArea->removeReversal(); + + // Now that clipping and flipping is done, rotate certain values that will be used for + // UtilsVk::BlitResolveParameters + gl::Rectangle sourceAreaOld = *sourceArea; + gl::Rectangle destAreaOld = *destArea; + if (srcFramebufferRotation == rotation) + { + AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld, srcAttachmentDimensions, + sourceArea); + AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcAttachmentDimensions, + flipX, flipY); + } + SurfaceRotation rememberDestFramebufferRotation = *dstFramebufferRotation; + if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees) + { + *dstFramebufferRotation = rotation; + } + AdjustBlitAreaForPreRotation(*dstFramebufferRotation, destAreaOld, dstFramebufferDimensions, + destArea); + *dstFramebufferRotation = rememberDestFramebufferRotation; + + params->srcOffset[0] = sourceArea->x; + params->srcOffset[1] = sourceArea->y; + params->dstOffset[0] = destArea->x; + params->dstOffset[1] = destArea->y; + params->rotatedOffsetFactor[0] = std::abs(sourceArea->width); + params->rotatedOffsetFactor[1] = std::abs(sourceArea->height); + params->srcExtents[0] = srcAttachmentDimensions.width; + params->srcExtents[1] = srcAttachmentDimensions.height; + params->flipX = *flipX; + params->flipY = *flipY; + params->srcMip = + readRenderTarget->getImageForCopy().toVkLevel(readRenderTarget->getLevelIndex()); + params->srcLayer = readRenderTarget->getLayerIndex(); +} + vk::FramebufferNonResolveAttachmentMask MakeUnresolveAttachmentMask(const vk::RenderPassDesc &desc) { vk::FramebufferNonResolveAttachmentMask unresolveMask( @@ -327,6 +415,38 @@ bool AllowAddingResolveAttachmentsToSubpass(const vk::RenderPassDesc &desc) // For the same reason, adding resolve attachments after the fact is disabled with YUV resolve. return !desc.isRenderToTexture() && !desc.hasYUVResolveAttachment(); } + +angle::Result UnresolveYuvImage(ContextVk *contextVk, + RenderTargetVk *colorRenderTarget, + const gl::Rectangle &renderArea) +{ + vk::ImageHelper *dst = &colorRenderTarget->getImageForRenderPass(); + vk::ImageHelper *src = &colorRenderTarget->getResolveImageForRenderPass(); + + // The Y2Y sampler is used for the source image in the unresolve copy. + vk::DeviceScoped srcViewY2Y(contextVk->getDevice()); + ANGLE_TRY(src->initLayerImageViewWithYuvModeOverride( + contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), + &srcViewY2Y.get(), vk::LevelIndex(0), 1, 0, 1, gl::YuvSamplingMode::Y2Y, + VK_IMAGE_USAGE_SAMPLED_BIT, GL_NONE)); + const vk::ImageView *dstView = nullptr; + ANGLE_TRY(colorRenderTarget->getImageView(contextVk, &dstView)); + + UtilsVk::CopyImageParameters params = {}; + params.srcOffset[0] = renderArea.x; + params.srcOffset[1] = renderArea.y; + params.srcExtents[0] = renderArea.width; + params.srcExtents[1] = renderArea.height; + params.copyYuvWithoutColorConversion = true; + + ANGLE_TRY( + contextVk->getUtils().copyImage(contextVk, dst, dstView, src, &srcViewY2Y.get(), params)); + + // Mark our temp view as garbage immediately + vk::ImageView srcViewObject = srcViewY2Y.release(); + contextVk->addGarbage(&srcViewObject); + return angle::Result::Continue; +} } // anonymous namespace FramebufferVk::FramebufferVk(vk::Renderer *renderer, const gl::FramebufferState &state) @@ -341,6 +461,7 @@ FramebufferVk::FramebufferVk(vk::Renderer *renderer, const gl::FramebufferState mIsCurrentFramebufferCached = !renderer->getFeatures().supportsImagelessFramebuffer.enabled; mIsYUVResolve = false; + mRasterizationSamples = -1; } FramebufferVk::~FramebufferVk() = default; @@ -927,6 +1048,8 @@ angle::Result FramebufferVk::readPixels(const gl::Context *context, gl::Buffer *packBuffer, void *pixels) { + ASSERT(mDeferredClears.empty()); + // Clip read area to framebuffer. const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize(); const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height); @@ -939,9 +1062,6 @@ angle::Result FramebufferVk::readPixels(const gl::Context *context, return angle::Result::Continue; } - // Flush any deferred clears. - ANGLE_TRY(flushDeferredClears(contextVk)); - GLuint outputSkipBytes = 0; PackPixelsParams params; ANGLE_TRY(vk::ImageHelper::GetReadPixelsParams(contextVk, pack, packBuffer, format, type, area, @@ -1046,6 +1166,8 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk, bool flipX, bool flipY) { + vk::Renderer *renderer = contextVk->getRenderer(); + // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, // it should never be the case that both color and depth/stencil need to be blitted at // at the same time. @@ -1067,12 +1189,24 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk, blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT; } - vk::CommandBufferAccess access; - access.onImageTransferRead(imageAspectMask, srcImage); - access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1, - drawRenderTarget->getLayerIndex(), 1, imageAspectMask, dstImage); + vk::CommandResources resources; + if (srcImage != dstImage) + { + resources.onImageTransferRead(imageAspectMask, srcImage); + resources.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1, + drawRenderTarget->getLayerIndex(), 1, imageAspectMask, + dstImage); + } + else + { + resources.onImageSelfCopy(readRenderTarget->getLevelIndex(), 1, + readRenderTarget->getLayerIndex(), 1, + drawRenderTarget->getLevelIndex(), 1, + drawRenderTarget->getLayerIndex(), 1, imageAspectMask, srcImage); + } + vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); VkImageBlit blit = {}; blit.srcSubresource.aspectMask = blitAspectMask; @@ -1105,8 +1239,8 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk, &blit.dstOffsets[1]); } - commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, + commandBuffer->blitImage(srcImage->getImage(), srcImage->getCurrentLayout(renderer), + dstImage->getImage(), dstImage->getCurrentLayout(renderer), 1, &blit, gl_vk::GetFilter(filter)); return angle::Result::Continue; @@ -1134,14 +1268,36 @@ angle::Result FramebufferVk::blit(const gl::Context *context, srcFramebufferVk->restageDeferredClearsForReadFramebuffer(contextVk); } - // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands - // are issued before we issue the blit command. - ANGLE_TRY(flushDeferredClears(contextVk)); - const bool blitColorBuffer = (mask & GL_COLOR_BUFFER_BIT) != 0; const bool blitDepthBuffer = (mask & GL_DEPTH_BUFFER_BIT) != 0; const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0; + if (blitDepthBuffer || blitStencilBuffer) + { + RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget(); + RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil(); + vk::ImageHelper &readImage = readRenderTarget->getImageForCopy(); + vk::ImageHelper &drawImage = drawRenderTarget->getImageForWrite(); + + if (!readImage.canTransferFrom()) + { + ASSERT(readImage.useTileMemory()); + readImage.finalizeImageLayoutInShareContexts(renderer, contextVk, {}); + ANGLE_TRY(readImage.fallbackFromTileMemory(contextVk)); + } + + if (!drawImage.canTransferTo()) + { + ASSERT(drawImage.useTileMemory()); + drawImage.finalizeImageLayoutInShareContexts(renderer, contextVk, {}); + ANGLE_TRY(drawImage.fallbackFromTileMemory(contextVk)); + } + } + + // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands + // are issued before we issue the blit command. + ANGLE_TRY(flushDeferredClears(contextVk)); + // If a framebuffer contains a mixture of multisampled and multisampled-render-to-texture // attachments, this function could be simultaneously doing a blit on one attachment and resolve // on another. For the most part, this means resolve semantics apply. However, as the resolve @@ -1261,14 +1417,6 @@ angle::Result FramebufferVk::blit(const gl::Context *context, } } - // If framebuffers are flipped in Y, flip the source and destination area (which define the - // transformation regardless of clipping), as well as the blit area (which is the clipped - // destination area). - if (srcFramebufferFlippedY) - { - sourceArea.y = srcFramebufferDimensions.height - sourceArea.y; - sourceArea.height = -sourceArea.height; - } if (dstFramebufferFlippedY) { destArea.y = dstFramebufferDimensions.height - destArea.y; @@ -1278,75 +1426,43 @@ angle::Result FramebufferVk::blit(const gl::Context *context, dstFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height; } - bool flipX = sourceArea.isReversedX() != destArea.isReversedX(); - bool flipY = sourceArea.isReversedY() != destArea.isReversedY(); - - // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve. - ASSERT(!isResolve || - (flipX == false && flipY == (srcFramebufferFlippedY != dstFramebufferFlippedY))); - - // Again, transfer the destination flip to source, so destination is unflipped. Note that - // destArea was not reversed until the final possible Y-flip. - ASSERT(!destArea.isReversedX()); - sourceArea = sourceArea.flip(false, destArea.isReversedY()); - destArea = destArea.removeReversal(); - - // Now that clipping and flipping is done, rotate certain values that will be used for - // UtilsVk::BlitResolveParameters - gl::Rectangle sourceAreaOld = sourceArea; - gl::Rectangle destAreaOld = destArea; - if (srcFramebufferRotation == rotation) - { - AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld, - srcFramebufferDimensions, &sourceArea); - AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcFramebufferDimensions, - &flipX, &flipY); - } - SurfaceRotation rememberDestFramebufferRotation = dstFramebufferRotation; - if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees) - { - dstFramebufferRotation = rotation; - } - AdjustBlitAreaForPreRotation(dstFramebufferRotation, destAreaOld, dstFramebufferDimensions, - &destArea); - dstFramebufferRotation = rememberDestFramebufferRotation; - // Clip the destination area to the framebuffer size and scissor. Note that we don't care - // about the source area anymore. The offset translation is done based on the original source - // and destination rectangles. The stretch factor is already calculated as well. + // about the source area anymore. The offset translation is done based on the original + // source and destination rectangles. The stretch factor is already calculated as well. gl::Rectangle blitArea; if (!gl::ClipRectangle(getRotatedScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea)) { return angle::Result::Continue; } - bool noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f; - bool noFlip = !flipX && !flipY; - bool disableFlippingBlitWithCommand = - renderer->getFeatures().disableFlippingBlitWithCommand.enabled; - - UtilsVk::BlitResolveParameters commonParams; - commonParams.srcOffset[0] = sourceArea.x; - commonParams.srcOffset[1] = sourceArea.y; - commonParams.dstOffset[0] = destArea.x; - commonParams.dstOffset[1] = destArea.y; - commonParams.rotatedOffsetFactor[0] = std::abs(sourceArea.width); - commonParams.rotatedOffsetFactor[1] = std::abs(sourceArea.height); - commonParams.stretch[0] = static_cast(stretch[0]); - commonParams.stretch[1] = static_cast(stretch[1]); - commonParams.srcExtents[0] = srcFramebufferDimensions.width; - commonParams.srcExtents[1] = srcFramebufferDimensions.height; - commonParams.blitArea = blitArea; - commonParams.linear = filter == GL_LINEAR && !isResolve; - commonParams.flipX = flipX; - commonParams.flipY = flipY; - commonParams.rotation = rotation; + // In case that color attachment has different size from depth attachment, need to calculate + // blit parameters for each. + bool isDefault = srcFramebuffer->isDefault(); + bool flipX = false; + bool flipY = false; + bool noClip = false; + + UtilsVk::BlitResolveParameters params; + params.stretch[0] = static_cast(stretch[0]); + params.stretch[1] = static_cast(stretch[1]); + params.renderArea = getRotatedCompleteRenderArea(contextVk); + params.blitArea = blitArea; + params.linear = filter == GL_LINEAR && !isResolve; + params.rotation = rotation; if (blitColorBuffer) { - RenderTargetVk *readRenderTarget = srcFramebufferVk->getColorReadRenderTarget(); - UtilsVk::BlitResolveParameters params = commonParams; - params.srcLayer = readRenderTarget->getLayerIndex(); + RenderTargetVk *readRenderTarget = srcFramebufferVk->getColorReadRenderTarget(); + + gl::Rectangle sourceColorArea = sourceArea; + gl::Rectangle destColorArea = destArea; + SurfaceRotation dstColorFramebufferRotation = dstFramebufferRotation; + AdjustBlitAreas(readRenderTarget, &sourceColorArea, &destColorArea, + &srcFramebufferDimensions, dstFramebufferDimensions, srcFramebufferRotation, + &dstColorFramebufferRotation, rotation, srcFramebufferFlippedY, + dstFramebufferFlippedY, isResolve, &flipX, &flipY, isDefault, ¶ms); + + noClip = blitArea == destColorArea && stretch[0] == 1.0f && stretch[1] == 1.0f; // Multisampled images are not allowed to have mips. ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0)); @@ -1361,9 +1477,9 @@ angle::Result FramebufferVk::blit(const gl::Context *context, // https://gitlab.khronos.org/vulkan/vulkan/-/issues/3490) // // For simplicity, we either blit all render targets with a Vulkan command, or none. - bool canBlitWithCommand = - !isColorResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) && - HasSrcBlitFeature(renderer, readRenderTarget) && rotation == SurfaceRotation::Identity; + bool canBlitWithCommand = !isColorResolve && noClip && + HasSrcBlitFeature(renderer, readRenderTarget) && + rotation == SurfaceRotation::Identity; // If we need to reinterpret the colorspace of the read RenderTarget then the blit must be // done through a shader @@ -1397,7 +1513,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context, // Now that all flipping is done, adjust the offsets for resolve and prerotation if (isColorResolve) { - AdjustBlitResolveParametersForResolve(sourceArea, destArea, ¶ms); + AdjustBlitResolveParametersForResolve(sourceColorArea, destColorArea, ¶ms); } AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, ¶ms); @@ -1406,9 +1522,9 @@ angle::Result FramebufferVk::blit(const gl::Context *context, for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) { RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL]; - ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget, - drawRenderTarget, filter, true, false, false, flipX, - flipY)); + ANGLE_TRY(blitWithCommand(contextVk, sourceColorArea, destColorArea, + readRenderTarget, drawRenderTarget, filter, true, false, + false, flipX, flipY)); } } // If we're not flipping or rotating, use Vulkan's builtin resolve. @@ -1490,142 +1606,170 @@ angle::Result FramebufferVk::blit(const gl::Context *context, { RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget(); RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil(); - UtilsVk::BlitResolveParameters params = commonParams; - params.srcLayer = readRenderTarget->getLayerIndex(); + // glBlitFramebuffer requires that depth/stencil blits have matching formats. + ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget)); // Multisampled images are not allowed to have mips. ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0)); - // Similarly, only blit if there's been no clipping or rotating. - bool canBlitWithCommand = - !isDepthStencilResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) && - HasSrcBlitFeature(renderer, readRenderTarget) && - HasDstBlitFeature(renderer, drawRenderTarget) && rotation == SurfaceRotation::Identity; - bool areChannelsBlitCompatible = - AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget); + vk::ImageHelper *srcImage = &readRenderTarget->getImageForCopy(); + vk::ImageHelper *dstImage = &drawRenderTarget->getImageForWrite(); - // glBlitFramebuffer requires that depth/stencil blits have matching formats. - ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget)); + AdjustBlitAreas(readRenderTarget, &sourceArea, &destArea, &srcFramebufferDimensions, + dstFramebufferDimensions, srcFramebufferRotation, &dstFramebufferRotation, + rotation, srcFramebufferFlippedY, dstFramebufferFlippedY, isResolve, &flipX, + &flipY, isDefault, ¶ms); - if (canBlitWithCommand && areChannelsBlitCompatible) - { - ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget, - drawRenderTarget, filter, false, blitDepthBuffer, - blitStencilBuffer, flipX, flipY)); - } - else - { - vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy(); + noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f; + const bool noFlip = !flipX && !flipY; - VkImageAspectFlags resolveAspects = 0; - if (blitDepthBuffer) - { - resolveAspects |= VK_IMAGE_ASPECT_DEPTH_BIT; - } - if (blitStencilBuffer) - { - resolveAspects |= VK_IMAGE_ASPECT_STENCIL_BIT; - } + const vk::ImageView *dstDepthStencilView = nullptr; + ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &dstDepthStencilView)); - // See comment on canResolveWithSubpass for the color path. - bool canResolveWithSubpass = - isDepthStencilResolve && - !renderer->getFeatures().disableDepthStencilResolveThroughAttachment.enabled && - areChannelsBlitCompatible && mCurrentFramebufferDesc.getLayerCount() == 1 && - contextVk->hasStartedRenderPassWithQueueSerial( - srcFramebufferVk->getLastRenderPassQueueSerial()) && - !contextVk->isRenderPassStartedAndUsesImage( - drawRenderTarget->getImageForRenderPass()) && - noFlip && rotation == SurfaceRotation::Identity; + gl::LevelIndex dstLevelIndex = drawRenderTarget->getLevelIndex(); + uint32_t dstLayerIndex = drawRenderTarget->getLayerIndex(); - if (canResolveWithSubpass) - { - const vk::RenderPassCommandBufferHelper &renderPassCommands = - contextVk->getStartedRenderPassCommands(); - const vk::RenderPassDesc &renderPassDesc = renderPassCommands.getRenderPassDesc(); + // Get depth- and stencil-only views for reading. + const vk::ImageView *srcDepthView = nullptr; + if (blitDepthBuffer) + { + ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy( + contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &srcDepthView)); + } - const VkImageAspectFlags depthStencilImageAspects = - depthStencilImage->getAspectFlags(); - const bool resolvesAllAspects = - (resolveAspects & depthStencilImageAspects) == depthStencilImageAspects; + const vk::ImageView *srcStencilView = nullptr; + if (blitStencilBuffer) + { + ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy( + contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &srcStencilView)); + } - // Make sure that: - // - The blit and render areas are identical - // - There is no resolve attachment already - // Additionally, disable the optimization for a few corner cases that are - // unrealistic and inconvenient. - // - // Note: currently, if two separate `glBlitFramebuffer` calls are made for each - // aspect, only the first one is optimized as a resolve attachment. Applications - // should use one `glBlitFramebuffer` call with both aspects if they want to resolve - // both. - canResolveWithSubpass = - blitArea == renderPassCommands.getRenderArea() && - (resolvesAllAspects || - renderer->getFeatures().supportsDepthStencilIndependentResolveNone.enabled) && - !renderPassDesc.hasDepthStencilResolveAttachment() && - AllowAddingResolveAttachmentsToSubpass(renderPassDesc); - } + // If shader stencil export is not possible, defer stencil blit/resolve to another pass. + const bool hasShaderStencilExport = + renderer->getFeatures().supportsShaderStencilExport.enabled; + + // When possible try to use mid render pass blit to avoid breaking current renderPass. + bool canBlitWithMidRenderPassDraw = + !isDepthStencilResolve && dstImage != srcImage && + contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial) && + (!blitStencilBuffer || hasShaderStencilExport) && + !contextVk->getState().isTransformFeedbackActiveUnpaused() && + !contextVk->hasActiveRenderPassQuery(); + if (canBlitWithMidRenderPassDraw) + { + // All deferred clear must have been flushed, otherwise it will conflict with + // params.blitArea. + ASSERT(!hasDeferredClears()); + // If we have to use standalone renderPass for stencil, then no need for depth to use + // midRenderPass. + ASSERT(!blitStencilBuffer || hasShaderStencilExport); + ASSERT(blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport)); + ASSERT(!isDepthStencilResolve); + + AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, ¶ms); + + ANGLE_TRY(utilsVk.depthStencilBlitResolve( + contextVk, &contextVk->getStartedRenderPassCommands(), dstImage, + *dstDepthStencilView, dstLevelIndex, dstLayerIndex, srcImage, srcDepthView, + srcStencilView, params)); - if (canResolveWithSubpass) - { - ANGLE_TRY(resolveDepthStencilWithSubpass(contextVk, params, resolveAspects)); - } - else - { - // See comment for the draw-based color blit. The render pass must be flushed - // before creating the views. - ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass( - RenderPassClosureReason::PrepareForBlit)); + return angle::Result::Continue; + } - // Now that all flipping is done, adjust the offsets for resolve and prerotation - if (isDepthStencilResolve) - { - AdjustBlitResolveParametersForResolve(sourceArea, destArea, ¶ms); - } - AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, - ¶ms); + bool areChannelsBlitCompatible = + AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget); - // Get depth- and stencil-only views for reading. - const vk::ImageView *depthView = nullptr; - const vk::ImageView *stencilView = nullptr; + // Similarly, only blit if there's been no clipping or rotating. + bool canBlitWithCommand = areChannelsBlitCompatible && !isDepthStencilResolve && noClip && + HasSrcBlitFeature(renderer, readRenderTarget) && + HasDstBlitFeature(renderer, drawRenderTarget) && + rotation == SurfaceRotation::Identity; + if (canBlitWithCommand) + { + return blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget, + drawRenderTarget, filter, false, blitDepthBuffer, + blitStencilBuffer, flipX, flipY); + } - if (blitDepthBuffer) - { - ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy( - contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &depthView)); - } + VkImageAspectFlags resolveAspects = 0; + if (blitDepthBuffer) + { + resolveAspects |= VK_IMAGE_ASPECT_DEPTH_BIT; + } + if (blitStencilBuffer) + { + resolveAspects |= VK_IMAGE_ASPECT_STENCIL_BIT; + } - if (blitStencilBuffer) - { - ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy( - contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &stencilView)); - } + // See comment on canResolveWithSubpass for the color path. + bool canResolveWithSubpass = + isDepthStencilResolve && + !renderer->getFeatures().disableDepthStencilResolveThroughAttachment.enabled && + areChannelsBlitCompatible && mCurrentFramebufferDesc.getLayerCount() == 1 && + contextVk->hasStartedRenderPassWithQueueSerial( + srcFramebufferVk->getLastRenderPassQueueSerial()) && + !contextVk->isRenderPassStartedAndUsesImage( + drawRenderTarget->getImageForRenderPass()) && + noFlip && rotation == SurfaceRotation::Identity; + if (canResolveWithSubpass) + { + const vk::RenderPassCommandBufferHelper &renderPassCommands = + contextVk->getStartedRenderPassCommands(); + const vk::RenderPassDesc &renderPassDesc = renderPassCommands.getRenderPassDesc(); + + const VkImageAspectFlags srcImageAspects = srcImage->getAspectFlags(); + const bool resolvesAllAspects = (resolveAspects & srcImageAspects) == srcImageAspects; + + // Make sure that: + // - The blit and render areas are identical + // - There is no resolve attachment already + // Additionally, disable the optimization for a few corner cases that are + // unrealistic and inconvenient. + // + // Note: currently, if two separate `glBlitFramebuffer` calls are made for each + // aspect, only the first one is optimized as a resolve attachment. Applications + // should use one `glBlitFramebuffer` call with both aspects if they want to resolve + // both. + canResolveWithSubpass = + blitArea == renderPassCommands.getRenderArea() && + (resolvesAllAspects || + renderer->getFeatures().supportsDepthStencilIndependentResolveNone.enabled) && + !renderPassDesc.hasDepthStencilResolveAttachment() && + AllowAddingResolveAttachmentsToSubpass(renderPassDesc); + } + if (canResolveWithSubpass) + { + return resolveDepthStencilWithSubpass(contextVk, params, resolveAspects); + } - // If shader stencil export is not possible, defer stencil blit/resolve to another - // pass. - const bool hasShaderStencilExport = - renderer->getFeatures().supportsShaderStencilExport.enabled; + // Now that all flipping is done, adjust the offsets for resolve and prerotation + if (isDepthStencilResolve) + { + AdjustBlitResolveParametersForResolve(sourceArea, destArea, ¶ms); + } + AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, ¶ms); - // Blit depth. If shader stencil export is present, blit stencil as well. - if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport)) - { - ANGLE_TRY(utilsVk.depthStencilBlitResolve( - contextVk, this, depthStencilImage, depthView, - hasShaderStencilExport ? stencilView : nullptr, params)); - } + // Blit depth. If shader stencil export is present, blit stencil as well. + if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport)) + { + // All deferred clear must have been flushed, otherwise it will conflict with + // params.blitArea. + ASSERT(!hasDeferredClears()); - // If shader stencil export is not present, blit stencil through a different path. - if (blitStencilBuffer && !hasShaderStencilExport) - { - ANGLE_VK_PERF_WARNING( - contextVk, GL_DEBUG_SEVERITY_LOW, - "Inefficient BlitFramebuffer operation on the stencil aspect " - "due to lack of shader stencil export support"); - ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport( - contextVk, this, depthStencilImage, stencilView, params)); - } - } + ANGLE_TRY(utilsVk.depthStencilBlitResolve( + contextVk, nullptr, dstImage, *dstDepthStencilView, dstLevelIndex, dstLayerIndex, + srcImage, srcDepthView, hasShaderStencilExport ? srcStencilView : nullptr, params)); + } + + // If shader stencil export is not present, blit stencil through a different path. + if (blitStencilBuffer && !hasShaderStencilExport) + { + ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW, + "Inefficient BlitFramebuffer operation on the stencil aspect " + "due to lack of shader stencil export support"); + ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(contextVk, dstImage, dstLevelIndex, + dstLayerIndex, srcImage, + srcStencilView, params)); } } @@ -1713,11 +1857,12 @@ angle::Result FramebufferVk::ensureFragmentShadingRateImageAndViewInitialized( contextVk, gl::TextureType::_2D, VkExtent3D{fragmentShadingRateAttachmentWidth, fragmentShadingRateAttachmentHeight, 1}, renderer->getFormat(angle::FormatID::R8_UINT), 1, imageUsageFlags, gl::LevelIndex(0), 1, - 1, false, contextVk->getProtectionType() == vk::ProtectionType::Protected)); + 1, false, contextVk->getProtectionType() == vk::ProtectionType::Protected, + vk::TileMemory::Prohibited)); - ANGLE_TRY(contextVk->initImageAllocation( - &mFragmentShadingRateImage, false, renderer->getMemoryProperties(), - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vk::MemoryAllocationType::TextureImage)); + ANGLE_TRY(contextVk->initImageAllocation(&mFragmentShadingRateImage, false, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + vk::MemoryAllocationType::TextureImage)); mFragmentShadingRateImageView.init(renderer); ANGLE_TRY(mFragmentShadingRateImageView.initFragmentShadingRateView( @@ -1737,16 +1882,21 @@ angle::Result FramebufferVk::generateFragmentShadingRateWithCPU( const uint32_t foveatedAttachmentHeight, const std::vector &activeFocalPoints) { + vk::Renderer *renderer = contextVk->getRenderer(); + // Fill in image with fragment shading rate data - size_t bufferSize = fragmentShadingRateWidth * fragmentShadingRateHeight; + const size_t bufferSize = fragmentShadingRateWidth * fragmentShadingRateHeight; + VkBufferCreateInfo bufferCreateInfo = {}; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.size = bufferSize; bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vk::RendererScoped stagingBuffer(contextVk->getRenderer()); vk::BufferHelper *buffer = &stagingBuffer.get(); ANGLE_TRY(buffer->init(contextVk, bufferCreateInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + uint8_t *mappedBuffer; ANGLE_TRY(buffer->map(contextVk, &mappedBuffer)); uint8_t val = 0; @@ -1825,12 +1975,12 @@ angle::Result FramebufferVk::generateFragmentShadingRateWithCPU( ANGLE_TRY(buffer->flush(contextVk->getRenderer(), 0, buffer->getSize())); buffer->unmap(contextVk->getRenderer()); // copy data from staging buffer to image - vk::CommandBufferAccess access; - access.onBufferTransferRead(buffer); - access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, - &mFragmentShadingRateImage); + vk::CommandResources resources; + resources.onBufferTransferRead(buffer); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, + &mFragmentShadingRateImage); vk::OutsideRenderPassCommandBuffer *dataUpload; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &dataUpload)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &dataUpload)); VkBufferImageCopy copy = {}; copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copy.imageSubresource.layerCount = 1; @@ -1839,7 +1989,7 @@ angle::Result FramebufferVk::generateFragmentShadingRateWithCPU( copy.imageExtent.height = fragmentShadingRateHeight; dataUpload->copyBufferToImage(buffer->getBuffer().getHandle(), mFragmentShadingRateImage.getImage(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); + mFragmentShadingRateImage.getCurrentLayout(renderer), 1, ©); return angle::Result::Continue; } @@ -2005,21 +2155,23 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk, const UtilsVk::BlitResolveParameters ¶ms, vk::ImageHelper *srcImage) { - vk::CommandBufferAccess access; - access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage); + vk::Renderer *renderer = contextVk->getRenderer(); + + vk::CommandResources resources; + resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage); for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) { RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL]; vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite(); - access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1, - drawRenderTarget->getLayerIndex(), 1, VK_IMAGE_ASPECT_COLOR_BIT, - &dstImage); + resources.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1, + drawRenderTarget->getLayerIndex(), 1, + VK_IMAGE_ASPECT_COLOR_BIT, &dstImage); } vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); VkImageResolve resolveRegion = {}; resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -2048,7 +2200,7 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk, resolveRegion.dstSubresource.mipLevel = levelVk.get(); resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex(); - srcImage->resolve(&dstImage, resolveRegion, commandBuffer); + srcImage->resolve(renderer, &dstImage, resolveRegion, commandBuffer); perfCounters.resolveImageCommands++; } @@ -2111,23 +2263,26 @@ angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk, // Shouldn't try to issue deferred clears if invalidating sub framebuffer. ASSERT(mDeferredClears.empty() || !isSubInvalidate); - // Remove deferred clears for the invalidated attachments. - if (invalidateDepthBuffer) + if (contextVk->getFeatures().dropDepthStencilClearOnInvalidate.enabled) { - mDeferredClears.reset(vk::kUnpackedDepthIndex); - } - if (invalidateStencilBuffer) - { - mDeferredClears.reset(vk::kUnpackedStencilIndex); - } - for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) - { - if (invalidateColorBuffers.test(colorIndexGL)) + // Remove deferred clears for the invalidated attachments. + if (invalidateDepthBuffer) { - mDeferredClears.reset(colorIndexGL); + mDeferredClears.reset(vk::kUnpackedDepthIndex); + } + if (invalidateStencilBuffer) + { + mDeferredClears.reset(vk::kUnpackedStencilIndex); } } + // Limit invalidateColorBuffers to enabled draw buffers + invalidateColorBuffers &= mState.getEnabledDrawBuffers(); + for (size_t colorIndexGL : invalidateColorBuffers) + { + mDeferredClears.reset(colorIndexGL); + } + // If there are still deferred clears, restage them. See relevant comment in invalidateSub. restageDeferredClears(contextVk); @@ -2138,19 +2293,16 @@ angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk, // so their loadOp can be set to DONT_CARE in the following render pass. if (!isSubInvalidate) { - for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) + for (size_t colorIndexGL : invalidateColorBuffers) { - if (invalidateColorBuffers.test(colorIndexGL)) - { - RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL]; - ASSERT(colorRenderTarget); + RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL]; + ASSERT(colorRenderTarget); - bool preferToKeepContentsDefined = false; - colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined); - if (preferToKeepContentsDefined) - { - invalidateColorBuffers.reset(colorIndexGL); - } + bool preferToKeepContentsDefined = false; + colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined); + if (preferToKeepContentsDefined) + { + invalidateColorBuffers.reset(colorIndexGL); } } @@ -2195,8 +2347,7 @@ angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk, vk::PackedAttachmentIndex colorIndexVk(0); for (size_t colorIndexGL : mState.getColorAttachmentsMask()) { - if (mState.getEnabledDrawBuffers()[colorIndexGL] && - invalidateColorBuffers.test(colorIndexGL)) + if (invalidateColorBuffers.test(colorIndexGL)) { contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment( contextVk->getState(), colorIndexGL, colorIndexVk, invalidateArea); @@ -2533,7 +2684,11 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, } } - // A shared attachment's colospace could have been modified in another context, update + // Update cached value of samples. Always ensure we have at least one sample since + // GraphicsPipelineDesc can't handle 0 samples. + mRasterizationSamples = std::max(getSamplesImpl(), 1); + + // A shared attachment's colorspace could have been modified in another context, update // colorspace of all attachments to reflect current context's colorspace. gl::SrgbWriteControlMode srgbWriteControlMode = mState.getWriteControlMode(); updateColorAttachmentColorspace(srgbWriteControlMode); @@ -2556,53 +2711,87 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, ANGLE_TRY(updateFoveationState(contextVk, *newFoveationState, foveatedAttachmentSize)); } - // Defer clears for draw framebuffer ops. Note that this will result in a render area that - // completely covers the framebuffer, even if the operation that follows is scissored. - // - // Additionally, defer clears for read framebuffer attachments that are not taking part in a - // blit operation. - const bool isBlitCommand = command >= gl::Command::Blit && command <= gl::Command::BlitAll; + // Note that deferring clears may result in a render area that completely covers the + // framebuffer, even if the operation that follows is scissored. + bool deferColorClears, deferDepthStencilClears; - bool deferColorClears = binding == GL_DRAW_FRAMEBUFFER; - bool deferDepthStencilClears = binding == GL_DRAW_FRAMEBUFFER; - if (binding == GL_READ_FRAMEBUFFER && isBlitCommand) + switch (command) { - uint32_t blitMask = - static_cast(command) - static_cast(gl::Command::Blit); - if ((blitMask & gl::CommandBlitBufferColor) == 0) - { - deferColorClears = true; - } - if ((blitMask & (gl::CommandBlitBufferDepth | gl::CommandBlitBufferStencil)) == 0) - { + // These commands always expect deferred clears (to perform potential optimization). + case gl::Command::Clear: + case gl::Command::Draw: + ASSERT(binding == GL_DRAW_FRAMEBUFFER); + deferColorClears = true; deferDepthStencilClears = true; - } + break; + // Defer clears only for draw framebuffer attachments for the invalidate operation. + case gl::Command::Invalidate: + ASSERT(binding == GL_DRAW_FRAMEBUFFER || binding == GL_READ_FRAMEBUFFER); + deferColorClears = (binding == GL_DRAW_FRAMEBUFFER); + deferDepthStencilClears = (binding == GL_DRAW_FRAMEBUFFER); + break; + // These commands do not expect (handle) deferred clears. There is no reason to defer + // clears for CopyImage and ReadPixels, as they need to read from the image right away. + // GetMultisample does not access attachments at all and clears are flushed for simplicity. + // Other enum may be used for different cases, where deferred clears may be handled or not. + // Clears are not deferred to avoid bugs. If clears need to be deferred, operation must not + // use the Command::Other enumeration. + case gl::Command::CopyImage: + case gl::Command::ReadPixels: + case gl::Command::GetMultisample: + case gl::Command::Other: + // Binding for Command::Other reflects current code and may be updated as necessary. + ASSERT(((command == gl::Command::CopyImage || command == gl::Command::ReadPixels) && + binding == GL_READ_FRAMEBUFFER) || + (command == gl::Command::GetMultisample && binding == GL_DRAW_FRAMEBUFFER) || + (command == gl::Command::Other && binding == GL_FRAMEBUFFER)); + deferColorClears = false; + deferDepthStencilClears = false; + break; + // Defer clears for read framebuffer attachments that are not taking part in a blit + // operation in order to restage them and possibly use as clear op in a future render pass. + default: + ASSERT(command >= gl::Command::Blit && command <= gl::Command::BlitAll); + if (binding == GL_READ_FRAMEBUFFER) + { + const uint32_t blitMask = + static_cast(command) - static_cast(gl::Command::Blit); + deferColorClears = ((blitMask & gl::CommandBlitBufferColor) == 0); + deferDepthStencilClears = ((blitMask & gl::CommandBlitBufferDepthStencil) == 0); + } + else + { + ASSERT(binding == GL_DRAW_FRAMEBUFFER); + deferColorClears = true; + deferDepthStencilClears = true; + } + break; } - // If we are notified that any attachment is dirty, but we have deferred clears for them, a - // flushDeferredClears() call is missing somewhere. ASSERT this to catch these bugs. - vk::ClearValuesArray previousDeferredClears = mDeferredClears; + // If we have deferred clears, a flushDeferredClears() or restageDeferredClears() call is + // missing somewhere. ASSERT this to catch these bugs. + ASSERT(mDeferredClears.empty()); for (size_t colorIndexGL : dirtyColorAttachments) { - ASSERT(!previousDeferredClears.test(colorIndexGL)); ANGLE_TRY(flushColorAttachmentUpdates(context, deferColorClears, static_cast(colorIndexGL))); } if (dirtyDepthStencilAttachment) { - ASSERT(!previousDeferredClears.testDepth()); - ASSERT(!previousDeferredClears.testStencil()); ANGLE_TRY(flushDepthStencilAttachmentUpdates(context, deferDepthStencilClears)); } // No-op redundant changes to prevent closing the RenderPass. if (mCurrentFramebufferDesc == priorFramebufferDesc && - mCurrentFramebufferDesc.attachmentCount() > 0) + mCurrentFramebufferDesc.attachmentCount() > 0 && mRenderPassDesc.samples() == getSamples()) { return angle::Result::Continue; } + // The cached attachment information is cleared here. + mCachedAttachmentsInfo.clear(); + // ContextVk::onFramebufferChange will end up calling onRenderPassFinished if necessary, // which will trigger ending of current render pass. |mLastRenderPassQueueSerial| is reset // so that the render pass will not get reactivated, since |mCurrentFramebufferDesc| has @@ -2700,6 +2889,10 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk) if (color->isRenderToTexture()) { + ASSERT( + !contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled || + (colorRenderTargets[colorIndexGL]->getImageForRenderPass().getCreateFlags() & + VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) != 0); isRenderToTexture = true; break; } @@ -2707,6 +2900,9 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk) const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment(); if (depthStencil && depthStencil->isRenderToTexture()) { + ASSERT(!contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled || + (depthStencilRenderTarget->getImageForRenderPass().getCreateFlags() & + VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) != 0); isRenderToTexture = true; } @@ -2722,11 +2918,16 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk) updateLegacyDither(contextVk); } -angle::Result FramebufferVk::getAttachmentsAndRenderTargets( - vk::ErrorContext *context, - vk::FramebufferAttachmentsVector *unpackedAttachments, - vk::FramebufferAttachmentsVector *packedRenderTargetsInfoOut) +angle::Result FramebufferVk::updateAttachmentsAndRenderTargets(ContextVk *contextVk) { + // If the cached attachment info is unchanged, it can be reused. + if (!mCachedAttachmentsInfo.unpackedAttachments.empty()) + { + return angle::Result::Continue; + } + + bool anyResolveAttachments = false; + // Color attachments. mIsYUVResolve = false; const auto &colorRenderTargets = mRenderTargetCache.getColors(); @@ -2738,17 +2939,27 @@ angle::Result FramebufferVk::getAttachmentsAndRenderTargets( if (colorRenderTarget->isYuvResolve()) { mIsYUVResolve = true; - if (context->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) + if (contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) { + // Because the color attachment will be null if + // nullColorAttachmentWithExternalFormatResolve is VK_TRUE, push YUV resolve as + // color attachment to ensure the coherency of other attachment information, like + // ops and clearValues. + const vk::ImageView *resolveImageView = nullptr; + ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView)); + mCachedAttachmentsInfo.unpackedAttachments.push_back(resolveImageView->getHandle()); + mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back( + RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve)); + + anyResolveAttachments = true; continue; } } const vk::ImageView *imageView = nullptr; ANGLE_TRY(colorRenderTarget->getImageViewWithColorspace( - context, mCurrentFramebufferDesc.getWriteControlMode(), &imageView)); - unpackedAttachments->push_back(imageView->getHandle()); - - packedRenderTargetsInfoOut->emplace_back( + contextVk, mCurrentFramebufferDesc.getWriteControlMode(), &imageView)); + mCachedAttachmentsInfo.unpackedAttachments.push_back(imageView->getHandle()); + mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back( RenderTargetInfo(colorRenderTarget, RenderTargetImage::Attachment)); } @@ -2757,10 +2968,10 @@ angle::Result FramebufferVk::getAttachmentsAndRenderTargets( if (depthStencilRenderTarget) { const vk::ImageView *imageView = nullptr; - ANGLE_TRY(depthStencilRenderTarget->getImageView(context, &imageView)); + ANGLE_TRY(depthStencilRenderTarget->getImageView(contextVk, &imageView)); - unpackedAttachments->push_back(imageView->getHandle()); - packedRenderTargetsInfoOut->emplace_back( + mCachedAttachmentsInfo.unpackedAttachments.push_back(imageView->getHandle()); + mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back( RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::Attachment)); } @@ -2768,21 +2979,21 @@ angle::Result FramebufferVk::getAttachmentsAndRenderTargets( if (mCurrentFramebufferDesc.hasFragmentShadingRateAttachment()) { const vk::ImageViewHelper *imageViewHelper = &mFragmentShadingRateImageView; - unpackedAttachments->push_back( + mCachedAttachmentsInfo.unpackedAttachments.push_back( imageViewHelper->getFragmentShadingRateImageView().getHandle()); - packedRenderTargetsInfoOut->emplace_back(nullptr, RenderTargetImage::FragmentShadingRate); + mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back( + nullptr, RenderTargetImage::FragmentShadingRate); } // Color resolve attachments. From here on, the views are placed at sparse indices because of // |RenderPassFramebuffer|. That allows more resolve attachments to be added later. - unpackedAttachments->resize(vk::kMaxFramebufferAttachments, VK_NULL_HANDLE); + mCachedAttachmentsInfo.unpackedAttachments.resize(vk::kMaxFramebufferAttachments, + VK_NULL_HANDLE); static_assert(vk::RenderPassFramebuffer::kColorResolveAttachmentBegin < vk::kMaxFramebufferAttachments); static_assert(vk::RenderPassFramebuffer::kDepthStencilResolveAttachment < vk::kMaxFramebufferAttachments); - bool anyResolveAttachments = false; - for (size_t colorIndexGL : mState.getColorAttachmentsMask()) { RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL]; @@ -2790,12 +3001,19 @@ angle::Result FramebufferVk::getAttachmentsAndRenderTargets( if (colorRenderTarget->hasResolveAttachment()) { + if (colorRenderTarget->isYuvResolve() && + contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) + { + continue; + } + const vk::ImageView *resolveImageView = nullptr; - ANGLE_TRY(colorRenderTarget->getResolveImageView(context, &resolveImageView)); + ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView)); constexpr size_t kBaseIndex = vk::RenderPassFramebuffer::kColorResolveAttachmentBegin; - (*unpackedAttachments)[kBaseIndex + colorIndexGL] = resolveImageView->getHandle(); - packedRenderTargetsInfoOut->emplace_back( + mCachedAttachmentsInfo.unpackedAttachments[kBaseIndex + colorIndexGL] = + resolveImageView->getHandle(); + mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back( RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve)); anyResolveAttachments = true; @@ -2806,11 +3024,12 @@ angle::Result FramebufferVk::getAttachmentsAndRenderTargets( if (depthStencilRenderTarget && depthStencilRenderTarget->hasResolveAttachment()) { const vk::ImageView *imageView = nullptr; - ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(context, &imageView)); + ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(contextVk, &imageView)); - (*unpackedAttachments)[vk::RenderPassFramebuffer::kDepthStencilResolveAttachment] = + mCachedAttachmentsInfo + .unpackedAttachments[vk::RenderPassFramebuffer::kDepthStencilResolveAttachment] = imageView->getHandle(); - packedRenderTargetsInfoOut->emplace_back( + mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back( RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::Resolve)); anyResolveAttachments = true; @@ -2826,13 +3045,10 @@ angle::Result FramebufferVk::getAttachmentsAndRenderTargets( return angle::Result::Continue; } -angle::Result FramebufferVk::createNewFramebuffer( - ContextVk *contextVk, - uint32_t framebufferWidth, - const uint32_t framebufferHeight, - const uint32_t framebufferLayers, - const vk::FramebufferAttachmentsVector &unpackedAttachments, - const vk::FramebufferAttachmentsVector &renderTargetsInfo) +angle::Result FramebufferVk::createNewFramebuffer(ContextVk *contextVk, + uint32_t framebufferWidth, + const uint32_t framebufferHeight, + const uint32_t framebufferLayers) { ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled); @@ -2858,13 +3074,15 @@ angle::Result FramebufferVk::createNewFramebuffer( ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass)); // Create a new framebuffer. + uint32_t currentAttachmentCount = + static_cast(mCachedAttachmentsInfo.packedRenderTargetsInfo.size()); vk::FramebufferHelper newFramebuffer; VkFramebufferCreateInfo framebufferInfo = {}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.flags = 0; framebufferInfo.renderPass = compatibleRenderPass->getHandle(); - framebufferInfo.attachmentCount = static_cast(renderTargetsInfo.size()); + framebufferInfo.attachmentCount = currentAttachmentCount; framebufferInfo.width = framebufferWidth; framebufferInfo.height = framebufferHeight; framebufferInfo.layers = framebufferLayers; @@ -2872,15 +3090,15 @@ angle::Result FramebufferVk::createNewFramebuffer( // Check that our description matches our attachments. Can catch implementation bugs. ASSERT((mIsYUVResolve && contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) || - static_cast(renderTargetsInfo.size()) == - mCurrentFramebufferDesc.attachmentCount()); + currentAttachmentCount == mCurrentFramebufferDesc.attachmentCount()); if (!useImagelessFramebuffer) { - vk::FramebufferAttachmentsVector packedAttachments = unpackedAttachments; + vk::FramebufferAttachmentsVector packedAttachments = + mCachedAttachmentsInfo.unpackedAttachments; vk::RenderPassFramebuffer::PackViews(&packedAttachments); - ASSERT(renderTargetsInfo.size() == packedAttachments.size()); + ASSERT(currentAttachmentCount == packedAttachments.size()); framebufferInfo.pAttachments = packedAttachments.data(); // The cache key (|FramebufferDesc|) can't distinguish between two framebuffers with 0 @@ -2908,11 +3126,11 @@ angle::Result FramebufferVk::createNewFramebuffer( // For imageless framebuffers, attachment image and create info objects should be defined // when creating the new framebuffer. vk::FramebufferAttachmentsVector attachmentImageInfos( - renderTargetsInfo.size(), {}); + currentAttachmentCount, {}); - for (size_t index = 0; index < renderTargetsInfo.size(); ++index) + for (size_t index = 0; index < currentAttachmentCount; ++index) { - const RenderTargetInfo &info = renderTargetsInfo[index]; + const RenderTargetInfo &info = mCachedAttachmentsInfo.packedRenderTargetsInfo[index]; VkFramebufferAttachmentImageInfo &attachmentInfo = attachmentImageInfos[index]; attachmentInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO; @@ -2933,8 +3151,15 @@ angle::Result FramebufferVk::createNewFramebuffer( continue; } + // Use the resolve image for both draw and resolve attachments when rendering to YUV + // with the nullColorAttachmentWithExternalFormatResolve feature enabled. + // If nullColorAttachmentWithExternalFormatResolve is not supported, follow default + // behaviour. + const bool overrideDrawAttachmentWithResolveAttachment = + info.renderTarget->isYuvResolve() && + contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve(); vk::ImageHelper *image = (info.renderTargetImage == RenderTargetImage::Resolve || - info.renderTarget->isYuvResolve()) + overrideDrawAttachmentWithResolveAttachment) ? &info.renderTarget->getResolveImageForRenderPass() : &info.renderTarget->getImageForRenderPass(); @@ -2984,9 +3209,9 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, ? std::max(mCurrentFramebufferDesc.getLayerCount(), 1u) : 1; - vk::FramebufferAttachmentsVector unpackedAttachments; - vk::FramebufferAttachmentsVector renderTargetsInfo; - ANGLE_TRY(getAttachmentsAndRenderTargets(contextVk, &unpackedAttachments, &renderTargetsInfo)); + ANGLE_TRY(updateAttachmentsAndRenderTargets(contextVk)); + vk::FramebufferAttachmentsVector unpackedAttachments = + mCachedAttachmentsInfo.unpackedAttachments; vk::Framebuffer framebufferHandle; if (contextVk->getFeatures().preferDynamicRendering.enabled) @@ -3011,8 +3236,7 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, { // Create a new framebuffer ANGLE_TRY(createNewFramebuffer(contextVk, framebufferWidth, framebufferHeight, - framebufferLayers, unpackedAttachments, - renderTargetsInfo)); + framebufferLayers)); ASSERT(mCurrentFramebuffer.valid()); framebufferHandle.setHandle(mCurrentFramebuffer.getHandle()); } @@ -3033,8 +3257,12 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, if (mBackbuffer != nullptr) { // Account for swapchain pre-rotation - framebufferWidth = renderTargetsInfo[0].renderTarget->getRotatedExtents().width; - framebufferHeight = renderTargetsInfo[0].renderTarget->getRotatedExtents().height; + framebufferWidth = mCachedAttachmentsInfo.packedRenderTargetsInfo[0] + .renderTarget->getRotatedExtents() + .width; + framebufferHeight = mCachedAttachmentsInfo.packedRenderTargetsInfo[0] + .renderTarget->getRotatedExtents() + .height; } const vk::ImagelessFramebuffer imagelessFramebuffer = @@ -3202,6 +3430,11 @@ void FramebufferVk::restageDeferredClearsForReadFramebuffer(ContextVk *contextVk restageDeferredClearsImpl(contextVk); } +void FramebufferVk::restageDeferredClearsAfterNoopDraw(ContextVk *contextVk) +{ + restageDeferredClearsImpl(contextVk); +} + void FramebufferVk::restageDeferredClearsImpl(ContextVk *contextVk) { // Set the appropriate aspect and clear values for depth and stencil. @@ -3491,10 +3724,20 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, { if (renderPassAttachmentOps[colorIndexVk].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) { - renderPassAttachmentOps[colorIndexVk].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + // Unresolve for YUV render targets is done using a separate renderpass + if (colorRenderTarget->isYuvResolve()) + { + ASSERT(!mRenderPassDesc.getColorUnresolveAttachmentMask().test(colorIndexGL)); + ANGLE_TRY(UnresolveYuvImage(contextVk, colorRenderTarget, renderArea)); + } + else + { + renderPassAttachmentOps[colorIndexVk].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - // Update the render pass desc to specify that this attachment should be unresolved. - mRenderPassDesc.packColorUnresolveAttachment(colorIndexGL); + // Update the render pass desc to specify that this attachment should be + // unresolved. + mRenderPassDesc.packColorUnresolveAttachment(colorIndexGL); + } } else { @@ -3614,20 +3857,21 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, } } - if (unresolveDepth || unresolveStencil) + if (unresolveDepth) { - if (unresolveDepth) - { - mRenderPassDesc.packDepthUnresolveAttachment(); - } - if (unresolveStencil) - { - mRenderPassDesc.packStencilUnresolveAttachment(); - } + mRenderPassDesc.packDepthUnresolveAttachment(); + } + else + { + mRenderPassDesc.removeDepthUnresolveAttachment(); + } + if (unresolveStencil) + { + mRenderPassDesc.packStencilUnresolveAttachment(); } else { - mRenderPassDesc.removeDepthStencilUnresolveAttachment(); + mRenderPassDesc.removeStencilUnresolveAttachment(); } } @@ -3793,7 +4037,7 @@ gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk) return rotatedScissoredArea; } -GLint FramebufferVk::getSamples() const +GLint FramebufferVk::getSamplesImpl() const { const gl::FramebufferAttachment *lastAttachment = nullptr; @@ -3821,7 +4065,7 @@ GLint FramebufferVk::getSamples() const // If none of the attachments are multisampled-render-to-texture, take the sample count from the // last attachment (any would have worked, as they would all have the same sample count). - return std::max(lastAttachment ? lastAttachment->getSamples() : 1, 1); + return lastAttachment ? lastAttachment->getSamples() : 1; } angle::Result FramebufferVk::flushDepthStencilDeferredClear(ContextVk *contextVk, @@ -3842,11 +4086,11 @@ angle::Result FramebufferVk::flushDepthStencilDeferredClear(ContextVk *contextVk // Depth/stencil attachments cannot be 3D. ASSERT(!renderTarget->is3DImage()); - vk::CommandBufferAccess access; - access.onImageTransferWrite(renderTarget->getLevelIndex(), 1, renderTarget->getLayerIndex(), 1, - image.getAspectFlags(), &image); + vk::CommandResources resources; + resources.onImageTransferWrite(renderTarget->getLevelIndex(), 1, renderTarget->getLayerIndex(), + 1, image.getAspectFlags(), &image); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); VkImageSubresourceRange range = {}; range.aspectMask = aspect; diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h index fd16765d90b..f59cce0e2fb 100644 --- a/src/libANGLE/renderer/vulkan/FramebufferVk.h +++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h @@ -125,7 +125,11 @@ class FramebufferVk : public FramebufferImpl vk::RenderPassCommandBuffer **commandBufferOut, bool *renderPassDescChangedOut); - GLint getSamples() const; + GLint getSamples() const + { + ASSERT(mRasterizationSamples > 0); + return mRasterizationSamples; + } const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; } @@ -136,6 +140,7 @@ class FramebufferVk : public FramebufferImpl bool hasDeferredStencilClear() const { return mDeferredClears.testStencil(); } angle::Result flushDepthStencilDeferredClear(ContextVk *contextVk, VkImageAspectFlagBits aspect); + void restageDeferredClearsAfterNoopDraw(ContextVk *contextVk); void switchToColorFramebufferFetchMode(ContextVk *contextVk, bool hasColorFramebufferFetch); @@ -182,23 +187,28 @@ class FramebufferVk : public FramebufferImpl RenderTargetImage renderTargetImage; }; + struct CachedAttachmentsInfo + { + void clear() + { + unpackedAttachments.clear(); + packedRenderTargetsInfo.clear(); + } + vk::FramebufferAttachmentsVector unpackedAttachments; + vk::FramebufferAttachmentsVector packedRenderTargetsInfo; + }; + // Returns the attachments to be used to create a framebuffer. The views returned in // |unpackedAttachments| are not necessarily packed, but the render targets in // |packedRenderTargetsInfoOut| are. In particular, the resolve attachment views need to stay // sparse to be placed in |RenderPassFramebuffer|, but the calling function will have to pack // them to match the render buffers before creating a framebuffer. - angle::Result getAttachmentsAndRenderTargets( - vk::ErrorContext *context, - vk::FramebufferAttachmentsVector *unpackedAttachments, - vk::FramebufferAttachmentsVector *packedRenderTargetsInfoOut); + angle::Result updateAttachmentsAndRenderTargets(ContextVk *contextVk); - angle::Result createNewFramebuffer( - ContextVk *contextVk, - uint32_t framebufferWidth, - const uint32_t framebufferHeight, - const uint32_t framebufferLayers, - const vk::FramebufferAttachmentsVector &unpackedAttachments, - const vk::FramebufferAttachmentsVector &renderTargetsInfo); + angle::Result createNewFramebuffer(ContextVk *contextVk, + uint32_t framebufferWidth, + const uint32_t framebufferHeight, + const uint32_t framebufferLayers); // The 'in' rectangles must be clipped to the scissor and FBO. The clipping is done in 'blit'. angle::Result blitWithCommand(ContextVk *contextVk, @@ -310,6 +320,7 @@ class FramebufferVk : public FramebufferImpl angle::Result updateFoveationState(ContextVk *contextVk, const gl::FoveationState &newFoveationState, const gl::Extents &foveatedAttachmentSize); + GLint getSamplesImpl() const; void insertCache(ContextVk *contextVk, const vk::FramebufferDesc &desc, @@ -355,6 +366,12 @@ class FramebufferVk : public FramebufferImpl // Serial of the render pass this framebuffer has opened, if any. QueueSerial mLastRenderPassQueueSerial; + + // Cached value of rasterization samples + GLint mRasterizationSamples; + + // Cached values of unpacked attachments and render target info for the framebuffer. + CachedAttachmentsInfo mCachedAttachmentsInfo; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp b/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp index fc19c5a7901..b15bb9f0351 100644 --- a/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp +++ b/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp @@ -198,10 +198,10 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk, bool hasProtectedContent = mProtectedMemory; ANGLE_TRY(image->initExternal( contextVk, type, vkExtents, vkFormat.getIntendedFormatID(), actualFormatID, 1, usageFlags, - createFlags, vk::ImageLayout::ExternalPreInitialized, &externalMemoryImageCreateInfo, + createFlags, vk::ImageAccess::ExternalPreInitialized, &externalMemoryImageCreateInfo, gl::LevelIndex(0), static_cast(levels), layerCount, - contextVk->isRobustResourceInitEnabled(), hasProtectedContent, vk::YcbcrConversionDesc{}, - nullptr)); + contextVk->isRobustResourceInitEnabled(), hasProtectedContent, vk::TileMemory::Prohibited, + vk::YcbcrConversionDesc{}, nullptr)); VkMemoryRequirements externalMemoryRequirements; image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements); diff --git a/src/libANGLE/renderer/vulkan/MemoryTracking.cpp b/src/libANGLE/renderer/vulkan/MemoryTracking.cpp index 8e07640136a..2e1e74ec03f 100644 --- a/src/libANGLE/renderer/vulkan/MemoryTracking.cpp +++ b/src/libANGLE/renderer/vulkan/MemoryTracking.cpp @@ -7,6 +7,10 @@ // Implements the class methods in MemoryTracking.h. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/MemoryTracking.h" #include "common/debug.h" diff --git a/src/libANGLE/renderer/vulkan/MemoryTracking.h b/src/libANGLE/renderer/vulkan/MemoryTracking.h index d0a85108675..0c05c1fc27d 100644 --- a/src/libANGLE/renderer/vulkan/MemoryTracking.h +++ b/src/libANGLE/renderer/vulkan/MemoryTracking.h @@ -40,8 +40,9 @@ enum class MemoryAllocationType RenderBufferStorageImage = 9, Buffer = 10, BufferExternal = 11, + ImplicitYuvTargetImage = 12, - InvalidEnum = 12, + InvalidEnum = 13, EnumCount = InvalidEnum, }; @@ -58,6 +59,7 @@ constexpr const char *kMemoryAllocationTypeMessage[] = { "RenderBufferStorageImage", "Buffer", "BufferExternal", + "ImplicitYuvTargetImage", "Invalid", }; constexpr const uint32_t kMemoryAllocationTypeCount = diff --git a/src/libANGLE/renderer/vulkan/OverlayVk.cpp b/src/libANGLE/renderer/vulkan/OverlayVk.cpp index 565ee57ca7b..9063a4bb579 100644 --- a/src/libANGLE/renderer/vulkan/OverlayVk.cpp +++ b/src/libANGLE/renderer/vulkan/OverlayVk.cpp @@ -7,6 +7,10 @@ // Implements the OverlayVk class. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/OverlayVk.h" #include "common/system_utils.h" @@ -59,14 +63,15 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk) constexpr bool kNoRobustInit = false; // Create the font image. - ANGLE_TRY(mFontImage.init( - contextVk, gl::TextureType::_2D, - VkExtent3D{gl::overlay::kFontGlyphWidth, gl::overlay::kFontGlyphHeight, 1}, - renderer->getFormat(angle::FormatID::R8_UNORM), 1, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, gl::LevelIndex(0), - gl::overlay::kFontMipCount, gl::overlay::kFontCharacters, kNoRobustInit, false)); - - ANGLE_TRY(contextVk->initImageAllocation(&mFontImage, false, renderer->getMemoryProperties(), + ANGLE_TRY( + mFontImage.init(contextVk, gl::TextureType::_2D, + VkExtent3D{gl::overlay::kFontGlyphWidth, gl::overlay::kFontGlyphHeight, 1}, + renderer->getFormat(angle::FormatID::R8_UNORM), 1, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + gl::LevelIndex(0), gl::overlay::kFontMipCount, gl::overlay::kFontCharacters, + kNoRobustInit, false, vk::TileMemory::Prohibited)); + + ANGLE_TRY(contextVk->initImageAllocation(&mFontImage, false, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vk::MemoryAllocationType::FontImage)); @@ -76,13 +81,13 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk) mFontImage.getLayerCount())); // Copy font data from staging buffer. - vk::CommandBufferAccess access; - access.onBufferTransferRead(&fontDataBuffer.get()); - access.onImageTransferWrite(gl::LevelIndex(0), gl::overlay::kFontMipCount, 0, - gl::overlay::kFontCharacters, VK_IMAGE_ASPECT_COLOR_BIT, - &mFontImage); + vk::CommandResources resources; + resources.onBufferTransferRead(&fontDataBuffer.get()); + resources.onImageTransferWrite(gl::LevelIndex(0), gl::overlay::kFontMipCount, 0, + gl::overlay::kFontCharacters, VK_IMAGE_ASPECT_COLOR_BIT, + &mFontImage); vk::OutsideRenderPassCommandBuffer *fontDataUpload; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &fontDataUpload)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &fontDataUpload)); VkBufferImageCopy copy = {}; copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -100,7 +105,7 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk) fontDataUpload->copyBufferToImage(fontDataBuffer.get().getBuffer().getHandle(), mFontImage.getImage(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); + mFontImage.getCurrentLayout(renderer), 1, ©); } return angle::Result::Continue; diff --git a/src/libANGLE/renderer/vulkan/PersistentCommandPool.cpp b/src/libANGLE/renderer/vulkan/PersistentCommandPool.cpp index 7ba51882344..2b9b0de2969 100644 --- a/src/libANGLE/renderer/vulkan/PersistentCommandPool.cpp +++ b/src/libANGLE/renderer/vulkan/PersistentCommandPool.cpp @@ -19,7 +19,7 @@ PersistentCommandPool::PersistentCommandPool() {} PersistentCommandPool::~PersistentCommandPool() { - ASSERT(!mCommandPool.valid() && mFreeBuffers.empty()); + ASSERT(!mCommandPool.valid() && mFreeBuffers.empty() && mFreeBuffersNeedReset.empty()); } angle::Result PersistentCommandPool::init(ErrorContext *context, @@ -66,12 +66,25 @@ void PersistentCommandPool::destroy(VkDevice device) mFreeBuffers.pop_back(); } + while (!mFreeBuffersNeedReset.empty()) + { + mFreeBuffersNeedReset.back().destroy(device, mCommandPool); + mFreeBuffersNeedReset.pop_back(); + } + mCommandPool.destroy(device); } angle::Result PersistentCommandPool::allocate(ErrorContext *context, PrimaryCommandBuffer *commandBufferOut) { + while (!mFreeBuffersNeedReset.empty()) + { + mFreeBuffersNeedReset.front().reset(); + mFreeBuffers.emplace_back(std::move(mFreeBuffersNeedReset.front())); + mFreeBuffersNeedReset.pop_front(); + } + if (mFreeBuffers.empty()) { ANGLE_TRY(allocateCommandBuffer(context)); @@ -84,13 +97,21 @@ angle::Result PersistentCommandPool::allocate(ErrorContext *context, return angle::Result::Continue; } -angle::Result PersistentCommandPool::collect(ErrorContext *context, PrimaryCommandBuffer &&buffer) +angle::Result PersistentCommandPool::collect(ErrorContext *context, + PrimaryCommandBuffer &&buffer, + WhenToResetCommandBuffer whenToReset) { - // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT NOT set, The CommandBuffer - // can still hold the memory resource - ANGLE_VK_TRY(context, buffer.reset()); - - mFreeBuffers.emplace_back(std::move(buffer)); + if (whenToReset == WhenToResetCommandBuffer::Now) + { + // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT NOT set, The CommandBuffer + // can still hold the memory resource + ANGLE_VK_TRY(context, buffer.reset()); + mFreeBuffers.emplace_back(std::move(buffer)); + } + else + { + mFreeBuffersNeedReset.emplace_back(std::move(buffer)); + } return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/PersistentCommandPool.h b/src/libANGLE/renderer/vulkan/PersistentCommandPool.h index 2f3c11d230a..a505659b933 100644 --- a/src/libANGLE/renderer/vulkan/PersistentCommandPool.h +++ b/src/libANGLE/renderer/vulkan/PersistentCommandPool.h @@ -21,6 +21,14 @@ namespace rx namespace vk { +// When command buffer gets collected, we have the option to call reset right away, or we can defer +// the reset call until the command buffer is going to be recycled for use again by allocate call. +enum class WhenToResetCommandBuffer +{ + Now, + Defer, +}; + class PersistentCommandPool final { public: @@ -33,14 +41,19 @@ class PersistentCommandPool final uint32_t queueFamilyIndex); angle::Result allocate(ErrorContext *context, PrimaryCommandBuffer *commandBufferOut); - angle::Result collect(ErrorContext *context, PrimaryCommandBuffer &&buffer); + angle::Result collect(ErrorContext *context, + PrimaryCommandBuffer &&buffer, + WhenToResetCommandBuffer whenToReset); bool valid() const { return mCommandPool.valid(); } private: angle::Result allocateCommandBuffer(ErrorContext *context); + // command buffers that are free and ready to use std::deque mFreeBuffers; + // command buffers that are free but needs reset before use + std::deque mFreeBuffersNeedReset; CommandPool mCommandPool; diff --git a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp index cfd386f5da2..74152512957 100644 --- a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp +++ b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp @@ -5,6 +5,11 @@ // // ProgramExecutableVk.cpp: Collects the information and interfaces common to both ProgramVks and // ProgramPipelineVks in order to execute/draw with either. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/vulkan/ProgramExecutableVk.h" @@ -181,9 +186,8 @@ void GetPipelineCacheData(ContextVk *contextVk, { ASSERT(pipelineCache.valid() || contextVk->getState().isGLES1() || !contextVk->getFeatures().warmUpPipelineCacheAtLink.enabled || - !contextVk->getFeatures().hasEffectivePipelineCacheSerialization.enabled); - if (!pipelineCache.valid() || - !contextVk->getFeatures().hasEffectivePipelineCacheSerialization.enabled) + contextVk->getFeatures().skipPipelineCacheSerialization.enabled); + if (!pipelineCache.valid() || contextVk->getFeatures().skipPipelineCacheSerialization.enabled) { return; } @@ -233,10 +237,7 @@ vk::SpecializationConstants MakeSpecConsts(ProgramTransformOptions transformOpti const vk::GraphicsPipelineDesc &desc) { vk::SpecializationConstants specConsts; - - specConsts.surfaceRotation = transformOptions.surfaceRotation; specConsts.dither = desc.getEmulatedDitherControl(); - return specConsts; } @@ -257,7 +258,8 @@ angle::Result UpdateFullTexturesDescriptorSet(vk::ErrorContext *context, const gl::SamplerBindingVector &samplers, VkDescriptorSet descriptorSet) { - vk::Renderer *renderer = context->getRenderer(); + vk::Renderer *renderer = context->getRenderer(); + const std::vector &samplerBindings = executable.getSamplerBindings(); const std::vector &samplerBoundTextureUnits = executable.getSamplerBoundTextureUnits(); const std::vector &uniforms = executable.getUniforms(); @@ -316,8 +318,8 @@ angle::Result UpdateFullTexturesDescriptorSet(vk::ErrorContext *context, { ASSERT(writeSet.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); const vk::BufferView *view = nullptr; - ANGLE_TRY( - textureVk->getBufferView(context, nullptr, &samplerBinding, false, &view)); + ANGLE_TRY(textureVk->getBufferView(context, nullptr, &samplerBinding, false, &view, + nullptr)); VkBufferView &bufferView = updateBuilder->allocBufferView(); bufferView = view->getHandle(); @@ -336,14 +338,14 @@ angle::Result UpdateFullTexturesDescriptorSet(vk::ErrorContext *context, const gl::SamplerState &samplerState = sampler ? sampler->getSamplerState() : textureVk->getState().getSamplerState(); - vk::ImageLayout imageLayout = textureVk->getImage().getCurrentImageLayout(); + vk::ImageAccess imageAccess = textureVk->getImage().getCurrentImageAccess(); const vk::ImageView &imageView = textureVk->getReadImageView( samplerState.getSRGBDecode(), samplerUniform.isTexelFetchStaticUse(), isSamplerExternalY2Y); VkDescriptorImageInfo *imageInfo = const_cast( &writeSet.pImageInfo[arrayElement + samplerUniform.getOuterArrayOffset()]); - imageInfo->imageLayout = ConvertImageLayoutToVkImageLayout(renderer, imageLayout); + imageInfo->imageLayout = renderer->getVkImageLayout(imageAccess); imageInfo->imageView = imageView.getHandle(); imageInfo->sampler = samplerHelper.get().getHandle(); } @@ -352,6 +354,20 @@ angle::Result UpdateFullTexturesDescriptorSet(vk::ErrorContext *context, return angle::Result::Continue; } + +void UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer &bufferBinding, + const vk::SharedDescriptorSetCacheKey &sharedCacheKey) +{ + if (bufferBinding.get() != nullptr) + { + // For simplicity, we do not check if uniform is active or duplicate. The worst case is + // we unnecessarily delete the cache entry when buffer bound to inactive uniform is + // destroyed. + BufferVk *bufferVk = vk::GetImpl(bufferBinding.get()); + vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); + bufferHelper.onNewDescriptorSet(sharedCacheKey); + } +} } // namespace class ProgramExecutableVk::WarmUpTaskCommon : public vk::ErrorContext, public LinkSubTask @@ -469,13 +485,11 @@ class ProgramExecutableVk::WarmUpGraphicsTask : public WarmUpTaskCommon vk::PipelineRobustness pipelineRobustness, vk::PipelineProtectedAccess pipelineProtectedAccess, vk::GraphicsPipelineSubset subset, - const bool isSurfaceRotated, const vk::GraphicsPipelineDesc &graphicsPipelineDesc, SharedRenderPass *compatibleRenderPass, vk::PipelineHelper *placeholderPipelineHelper) : WarmUpTaskCommon(renderer, executableVk, pipelineRobustness, pipelineProtectedAccess), mPipelineSubset(subset), - mIsSurfaceRotated(isSurfaceRotated), mGraphicsPipelineDesc(graphicsPipelineDesc), mWarmUpPipelineHelper(placeholderPipelineHelper), mCompatibleRenderPass(compatibleRenderPass) @@ -488,7 +502,7 @@ class ProgramExecutableVk::WarmUpGraphicsTask : public WarmUpTaskCommon void operator()() override { angle::Result result = mExecutableVk->warmUpGraphicsPipelineCache( - this, mPipelineRobustness, mPipelineProtectedAccess, mPipelineSubset, mIsSurfaceRotated, + this, mPipelineRobustness, mPipelineProtectedAccess, mPipelineSubset, mGraphicsPipelineDesc, mCompatibleRenderPass->get(), mWarmUpPipelineHelper); ASSERT((result == angle::Result::Continue) == (mErrorCode == VK_SUCCESS)); @@ -510,7 +524,6 @@ class ProgramExecutableVk::WarmUpGraphicsTask : public WarmUpTaskCommon private: vk::GraphicsPipelineSubset mPipelineSubset; - bool mIsSurfaceRotated; vk::GraphicsPipelineDesc mGraphicsPipelineDesc; vk::PipelineHelper *mWarmUpPipelineHelper; @@ -648,7 +661,7 @@ ProgramExecutableVk::ProgramExecutableVk(const gl::ProgramExecutable *executable : ProgramExecutableImpl(executable), mImmutableSamplersMaxDescriptorCount(1), mUniformBufferDescriptorType(VK_DESCRIPTOR_TYPE_MAX_ENUM), - mDynamicUniformDescriptorOffsets{}, + mDefaultUniformDynamicDescriptorOffsets{}, mValidGraphicsPermutations{}, mValidComputePermutations{} { @@ -690,6 +703,7 @@ void ProgramExecutableVk::resetLayout(ContextVk *contextVk) { descriptorSet.reset(); } + mValidDescriptorSetIndices.reset(); for (vk::DynamicDescriptorPoolPointer &pool : mDynamicDescriptorPools) { @@ -797,7 +811,7 @@ angle::Result ProgramExecutableVk::load(ContextVk *contextVk, gl::ShaderMap requiredBufferSize; stream->readPackedEnumMap(&requiredBufferSize); - if (!isSeparable) + if (!isSeparable && !contextVk->getFeatures().preferGlobalPipelineCache.enabled) { size_t compressedPipelineDataSize = 0; stream->readInt(&compressedPipelineDataSize); @@ -807,7 +821,7 @@ angle::Result ProgramExecutableVk::load(ContextVk *contextVk, { bool compressedData = false; stream->readBool(&compressedData); - stream->readBytes(compressedPipelineData.data(), compressedPipelineDataSize); + stream->readBytes(compressedPipelineData); // Initialize the pipeline cache based on cached data. ANGLE_TRY(initializePipelineCache(contextVk, compressedData, compressedPipelineData)); } @@ -855,7 +869,7 @@ void ProgramExecutableVk::save(ContextVk *contextVk, // pipelines do. However, currently ANGLE doesn't sync program pipelines to cache. ANGLE could // potentially use VK_EXT_graphics_pipeline_library to create separate pipelines for // pre-rasterization and fragment subsets, but currently those subsets are bundled together. - if (!isSeparable) + if (!isSeparable && !contextVk->getFeatures().preferGlobalPipelineCache.enabled) { angle::MemoryBuffer cacheData; @@ -864,7 +878,7 @@ void ProgramExecutableVk::save(ContextVk *contextVk, if (cacheData.size() > 0) { stream->writeBool(contextVk->getFeatures().enablePipelineCacheDataCompression.enabled); - stream->writeBytes(cacheData.data(), cacheData.size()); + stream->writeBytes(cacheData); } } } @@ -885,14 +899,13 @@ angle::Result ProgramExecutableVk::getPipelineCacheWarmUpTasks( const vk::GraphicsPipelineSubset subset = GetWarmUpSubset(renderer->getFeatures()); bool isCompute = false; - angle::FixedVector surfaceRotationVariations = {false}; vk::GraphicsPipelineDesc *graphicsPipelineDesc = nullptr; vk::RenderPass compatibleRenderPass; WarmUpTaskCommon prepForWarmUpContext(renderer); - ANGLE_TRY(prepareForWarmUpPipelineCache( - &prepForWarmUpContext, pipelineRobustness, pipelineProtectedAccess, subset, &isCompute, - &surfaceRotationVariations, &graphicsPipelineDesc, &compatibleRenderPass)); + ANGLE_TRY(preparePipelineCacheForWarmUp(&prepForWarmUpContext, pipelineRobustness, + pipelineProtectedAccess, subset, &isCompute, + &graphicsPipelineDesc, &compatibleRenderPass)); std::vector> warmUpSubTasks; if (isCompute) @@ -906,28 +919,25 @@ angle::Result ProgramExecutableVk::getPipelineCacheWarmUpTasks( { ProgramTransformOptions transformOptions = {}; SharedRenderPass *sharedRenderPass = new SharedRenderPass(std::move(compatibleRenderPass)); - for (bool surfaceRotation : surfaceRotationVariations) - { - // Add a placeholder entry in GraphicsPipelineCache - transformOptions.surfaceRotation = surfaceRotation; - const uint8_t programIndex = transformOptions.permutationIndex; - vk::PipelineHelper *pipelineHelper = nullptr; - if (subset == vk::GraphicsPipelineSubset::Complete) - { - CompleteGraphicsPipelineCache &pipelines = mCompleteGraphicsPipelines[programIndex]; - pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper); - } - else - { - ASSERT(subset == vk::GraphicsPipelineSubset::Shaders); - ShadersGraphicsPipelineCache &pipelines = mShadersGraphicsPipelines[programIndex]; - pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper); - } - warmUpSubTasks.push_back(std::make_shared( - renderer, this, pipelineRobustness, pipelineProtectedAccess, subset, - surfaceRotation, *graphicsPipelineDesc, sharedRenderPass, pipelineHelper)); + // Add a placeholder entry in GraphicsPipelineCache + const uint8_t programIndex = transformOptions.permutationIndex; + vk::PipelineHelper *pipelineHelper = nullptr; + if (subset == vk::GraphicsPipelineSubset::Complete) + { + CompleteGraphicsPipelineCache &pipelines = mCompleteGraphicsPipelines[programIndex]; + pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper); } + else + { + ASSERT(subset == vk::GraphicsPipelineSubset::Shaders); + ShadersGraphicsPipelineCache &pipelines = mShadersGraphicsPipelines[programIndex]; + pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper); + } + + warmUpSubTasks.push_back(std::make_shared( + renderer, this, pipelineRobustness, pipelineProtectedAccess, subset, + *graphicsPipelineDesc, sharedRenderPass, pipelineHelper)); } // If the caller hasn't provided a valid async task container, inline the warmUp tasks. @@ -949,23 +959,32 @@ angle::Result ProgramExecutableVk::getPipelineCacheWarmUpTasks( return angle::Result::Continue; } -angle::Result ProgramExecutableVk::prepareForWarmUpPipelineCache( +angle::Result ProgramExecutableVk::preparePipelineCacheForWarmUp( vk::ErrorContext *context, vk::PipelineRobustness pipelineRobustness, vk::PipelineProtectedAccess pipelineProtectedAccess, vk::GraphicsPipelineSubset subset, bool *isComputeOut, - angle::FixedVector *surfaceRotationVariationsOut, vk::GraphicsPipelineDesc **graphicsPipelineDescOut, vk::RenderPass *renderPassOut) { ASSERT(isComputeOut); - ASSERT(surfaceRotationVariationsOut); ASSERT(graphicsPipelineDescOut); ASSERT(renderPassOut); ASSERT(context->getFeatures().warmUpPipelineCacheAtLink.enabled); - ANGLE_TRY(ensurePipelineCacheInitialized(context)); + // Ensure pipeline cache is initialized + if (context->getFeatures().preferGlobalPipelineCache.enabled) + { + // Make sure Renderer's pipeline cache is initialized + vk::PipelineCacheAccess unused; + ANGLE_TRY(context->getRenderer()->getPipelineCache(context, &unused)); + } + else + { + // Make sure ProgramExecutableVk's pipeline cache is initialized + ANGLE_TRY(ensurePipelineCacheInitialized(context)); + } *isComputeOut = false; const bool isCompute = mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute); @@ -987,7 +1006,9 @@ angle::Result ProgramExecutableVk::prepareForWarmUpPipelineCache( gl::PrimitiveMode mode = (mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) || mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation)) ? gl::PrimitiveMode::Patches - : gl::PrimitiveMode::TriangleStrip; + : mExecutable->hasLinkedShaderStage(gl::ShaderType::Geometry) + ? mExecutable->getGeometryShaderInputPrimitiveType() + : gl::PrimitiveMode::Triangles; SetupDefaultPipelineState(context, *mExecutable, mode, pipelineRobustness, pipelineProtectedAccess, subset, &mWarmUpGraphicsPipelineDesc); @@ -1004,31 +1025,12 @@ angle::Result ProgramExecutableVk::prepareForWarmUpPipelineCache( *graphicsPipelineDescOut = &mWarmUpGraphicsPipelineDesc; - // Variations that definitely matter: - // - // - PreRotation: It's a boolean specialization constant - // - Depth correction: It's a SPIR-V transformation - // // There are a number of states that are not currently dynamic (and may never be, such as sample // shading), but pre-creating shaders for them is impractical. Most such state is likely unused // by most applications, but variations can be added here for certain apps that are known to // benefit from it. - *surfaceRotationVariationsOut = {false}; - if (context->getFeatures().enablePreRotateSurfaces.enabled && - !context->getFeatures().preferDriverUniformOverSpecConst.enabled) - { - surfaceRotationVariationsOut->push_back(true); - } - ProgramTransformOptions transformOptions = {}; - for (bool rotation : *surfaceRotationVariationsOut) - { - // Initialize graphics programs. - transformOptions.surfaceRotation = rotation; - ANGLE_TRY(initGraphicsShaderPrograms(context, transformOptions)); - } - - return angle::Result::Continue; + return initGraphicsShaderPrograms(context, transformOptions); } angle::Result ProgramExecutableVk::warmUpComputePipelineCache( @@ -1045,9 +1047,16 @@ angle::Result ProgramExecutableVk::warmUpComputePipelineCache( // Make sure the shader module for compute shader stage is valid. ASSERT(mComputeProgramInfo.valid(gl::ShaderType::Compute)); - // No synchronization necessary since mPipelineCache is internally synchronized. vk::PipelineCacheAccess pipelineCache; - pipelineCache.init(&mPipelineCache, nullptr); + if (context->getFeatures().preferGlobalPipelineCache.enabled) + { + ANGLE_TRY(context->getRenderer()->getPipelineCache(context, &pipelineCache)); + } + else + { + // No synchronization necessary since mPipelineCache is internally synchronized. + pipelineCache.init(&mPipelineCache, nullptr); + } // There is no state associated with compute programs, so only one pipeline needs creation // to warm up the cache. @@ -1063,7 +1072,6 @@ angle::Result ProgramExecutableVk::warmUpGraphicsPipelineCache( vk::PipelineRobustness pipelineRobustness, vk::PipelineProtectedAccess pipelineProtectedAccess, vk::GraphicsPipelineSubset subset, - const bool isSurfaceRotated, const vk::GraphicsPipelineDesc &graphicsPipelineDesc, const vk::RenderPass &renderPass, vk::PipelineHelper *placeholderPipelineHelper) @@ -1072,13 +1080,20 @@ angle::Result ProgramExecutableVk::warmUpGraphicsPipelineCache( ASSERT(placeholderPipelineHelper && !placeholderPipelineHelper->valid()); - // No synchronization necessary since mPipelineCache is internally synchronized. vk::PipelineCacheAccess pipelineCache; - pipelineCache.init(&mPipelineCache, nullptr); + + if (context->getFeatures().preferGlobalPipelineCache.enabled) + { + ANGLE_TRY(context->getRenderer()->getPipelineCache(context, &pipelineCache)); + } + else + { + // No synchronization necessary since mPipelineCache is internally synchronized. + pipelineCache.init(&mPipelineCache, nullptr); + } const vk::GraphicsPipelineDesc *descPtr = nullptr; ProgramTransformOptions transformOptions = {}; - transformOptions.surfaceRotation = isSurfaceRotated; ANGLE_TRY(createGraphicsPipelineImpl(context, transformOptions, subset, &pipelineCache, PipelineSource::WarmUp, graphicsPipelineDesc, renderPass, @@ -1408,35 +1423,38 @@ void ProgramExecutableVk::initializeWriteDescriptorDesc(vk::ErrorContext *contex { const gl::ShaderBitSet &linkedShaderStages = mExecutable->getLinkedShaderStages(); - // Update mShaderResourceWriteDescriptorDescBuilder - mShaderResourceWriteDescriptorDescs.reset(); - mShaderResourceWriteDescriptorDescs.updateShaderBuffers( + // Update mUniformBuffersWriteDescriptorDescs and its builder + mUniformBuffersWriteDescriptorDescs.reset(); + mUniformBuffersWriteDescriptorDescs.updateShaderBuffers( mVariableInfoMap, mExecutable->getUniformBlocks(), getUniformBufferDescriptorType()); + mUniformBuffersWriteDescriptorDescs.updateDynamicDescriptorsCount(); + mUniformBuffersDescriptorDescBuilder.resize( + mUniformBuffersWriteDescriptorDescs.getTotalDescriptorCount()); + + // Update mShaderResourceWriteDescriptorDescs and its builder + mShaderResourceWriteDescriptorDescs.reset(); mShaderResourceWriteDescriptorDescs.updateShaderBuffers( mVariableInfoMap, mExecutable->getShaderStorageBlocks(), getStorageBufferDescriptorType()); mShaderResourceWriteDescriptorDescs.updateAtomicCounters( mVariableInfoMap, mExecutable->getAtomicCounterBuffers()); mShaderResourceWriteDescriptorDescs.updateImages(*mExecutable, mVariableInfoMap); - mShaderResourceWriteDescriptorDescs.updateDynamicDescriptorsCount(); + mShaderResourceDescriptorDescBuilder.resize( + mShaderResourceWriteDescriptorDescs.getTotalDescriptorCount()); - // Update mTextureWriteDescriptors + // Update mTextureWriteDescriptors and its builder mTextureWriteDescriptorDescs.reset(); mTextureWriteDescriptorDescs.updateExecutableActiveTextures(mVariableInfoMap, *mExecutable); mTextureWriteDescriptorDescs.updateDynamicDescriptorsCount(); + mTextureDescriptorDescBuilder.resize(mTextureWriteDescriptorDescs.getTotalDescriptorCount()); - // Update mDefaultUniformWriteDescriptors - mDefaultUniformWriteDescriptorDescs.reset(); - mDefaultUniformWriteDescriptorDescs.updateDefaultUniform(linkedShaderStages, mVariableInfoMap, - *mExecutable); - mDefaultUniformWriteDescriptorDescs.updateDynamicDescriptorsCount(); - + // Update mDefaultUniformAndXfbWriteDescriptorDescs and its builder mDefaultUniformAndXfbWriteDescriptorDescs.reset(); + mDefaultUniformAndXfbWriteDescriptorDescs.updateDefaultUniform(linkedShaderStages, + mVariableInfoMap, *mExecutable); if (mExecutable->hasTransformFeedbackOutput() && context->getFeatures().emulateTransformFeedback.enabled) { // Update mDefaultUniformAndXfbWriteDescriptorDescs for the emulation code path. - mDefaultUniformAndXfbWriteDescriptorDescs.updateDefaultUniform( - linkedShaderStages, mVariableInfoMap, *mExecutable); if (linkedShaderStages[gl::ShaderType::Vertex]) { mDefaultUniformAndXfbWriteDescriptorDescs.updateTransformFeedbackWrite(mVariableInfoMap, @@ -1444,11 +1462,8 @@ void ProgramExecutableVk::initializeWriteDescriptorDesc(vk::ErrorContext *contex } mDefaultUniformAndXfbWriteDescriptorDescs.updateDynamicDescriptorsCount(); } - else - { - // Otherwise it will be the same as default uniform - mDefaultUniformAndXfbWriteDescriptorDescs = mDefaultUniformWriteDescriptorDescs; - } + mDefaultUniformAndXfbDescriptorDescBuilder.resize( + mDefaultUniformAndXfbWriteDescriptorDescs.getTotalDescriptorCount()); } ProgramTransformOptions ProgramExecutableVk::getTransformOptions( @@ -1457,7 +1472,6 @@ ProgramTransformOptions ProgramExecutableVk::getTransformOptions( { ProgramTransformOptions transformOptions = {}; - transformOptions.surfaceRotation = desc.getSurfaceRotation(); transformOptions.removeTransformFeedbackEmulation = contextVk->getFeatures().emulateTransformFeedback.enabled && !contextVk->getState().isTransformFeedbackActiveUnpaused(); @@ -1611,9 +1625,12 @@ angle::Result ProgramExecutableVk::createGraphicsPipeline( ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc); // When creating monolithic pipelines, the renderer's pipeline cache is used as passed in. - // When creating the shaders subset of pipelines, the program's own pipeline cache is used. + // When creating the shaders subset of pipelines, the program's own pipeline cache is used, + // unless the renderer's pipeline cache is preferred. vk::PipelineCacheAccess perProgramPipelineCache; - const bool useProgramPipelineCache = pipelineSubset == vk::GraphicsPipelineSubset::Shaders; + const bool useProgramPipelineCache = + !contextVk->getFeatures().preferGlobalPipelineCache.enabled && + pipelineSubset == vk::GraphicsPipelineSubset::Shaders; if (useProgramPipelineCache) { ANGLE_TRY(ensurePipelineCacheInitialized(contextVk)); @@ -1639,22 +1656,36 @@ angle::Result ProgramExecutableVk::createGraphicsPipeline( return angle::Result::Continue; } -angle::Result ProgramExecutableVk::linkGraphicsPipelineLibraries( +angle::Result ProgramExecutableVk::createLinkedGraphicsPipeline( ContextVk *contextVk, vk::PipelineCacheAccess *pipelineCache, const vk::GraphicsPipelineDesc &desc, - vk::PipelineHelper *vertexInputPipeline, vk::PipelineHelper *shadersPipeline, - vk::PipelineHelper *fragmentOutputPipeline, const vk::GraphicsPipelineDesc **descPtrOut, vk::PipelineHelper **pipelineOut) { ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc); const uint8_t programIndex = transformOptions.permutationIndex; - ANGLE_TRY(mCompleteGraphicsPipelines[programIndex].linkLibraries( - contextVk, pipelineCache, desc, getPipelineLayout(), vertexInputPipeline, shadersPipeline, - fragmentOutputPipeline, descPtrOut, pipelineOut)); + // When linking libraries, use the program's own pipeline cache if monolithic pipelines are not + // to be created, otherwise there is effectively a merge to global pipeline cache happening. + vk::PipelineCacheAccess programPipelineCache; + vk::PipelineCacheAccess *linkPipelineCache = pipelineCache; + if (!contextVk->getFeatures().preferGlobalPipelineCache.enabled && + !contextVk->getFeatures().preferMonolithicPipelinesOverLibraries.enabled) + { + // No synchronization necessary since mPipelineCache is internally synchronized. + programPipelineCache.init(&mPipelineCache, nullptr); + linkPipelineCache = &programPipelineCache; + } + + // Pull in a compatible RenderPass. + const vk::RenderPass *compatibleRenderPass = nullptr; + ANGLE_TRY(contextVk->getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass)); + + ANGLE_TRY(mCompleteGraphicsPipelines[programIndex].createPipeline( + contextVk, linkPipelineCache, *compatibleRenderPass, getPipelineLayout(), {shadersPipeline}, + PipelineSource::DrawLinked, desc, descPtrOut, pipelineOut)); // If monolithic pipelines are preferred over libraries, create a task so that it can be created // asynchronously. @@ -1735,8 +1766,8 @@ angle::Result ProgramExecutableVk::createPipelineLayout( context, mDefaultUniformAndXfbSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::UniformsAndXfb])); - // Uniform and storage buffers, atomic counter buffers and images: - mShaderResourceSetDesc = {}; + // Uniform buffers: + mUniformBuffersSetDesc = {}; // Count the number of active uniform buffer descriptors. uint32_t numActiveUniformBufferDescriptors = 0; @@ -1767,7 +1798,15 @@ angle::Result ProgramExecutableVk::createPipelineLayout( } addInterfaceBlockDescriptorSetDesc(mExecutable->getUniformBlocks(), linkedShaderStages, - mUniformBufferDescriptorType, &mShaderResourceSetDesc); + mUniformBufferDescriptorType, &mUniformBuffersSetDesc); + + ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout( + context, mUniformBuffersSetDesc, + &mDescriptorSetLayouts[DescriptorSetIndex::UniformBuffers])); + + // Storage buffers, atomic counter buffers and images: + mShaderResourceSetDesc = {}; + addInterfaceBlockDescriptorSetDesc(mExecutable->getShaderStorageBlocks(), linkedShaderStages, vk::kStorageBufferDescriptorType, &mShaderResourceSetDesc); addAtomicCounterBufferDescriptorSetDesc(mExecutable->getAtomicCounterBuffers(), @@ -1786,10 +1825,12 @@ angle::Result ProgramExecutableVk::createPipelineLayout( ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout( context, mTextureSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::Texture])); - // Create pipeline layout with these 3 descriptor sets. + // Create pipeline layout with these 4 descriptor sets. vk::PipelineLayoutDesc pipelineLayoutDesc; pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::UniformsAndXfb, mDefaultUniformAndXfbSetDesc); + pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::UniformBuffers, + mUniformBuffersSetDesc); pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::ShaderResource, mShaderResourceSetDesc); pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Texture, mTextureSetDesc); @@ -1806,8 +1847,8 @@ angle::Result ProgramExecutableVk::createPipelineLayout( ANGLE_TRY(pipelineLayoutCache->getPipelineLayout(context, pipelineLayoutDesc, mDescriptorSetLayouts, &mPipelineLayout)); - mDynamicUniformDescriptorOffsets.clear(); - mDynamicUniformDescriptorOffsets.resize(mExecutable->getLinkedShaderStageCount(), 0); + mDefaultUniformDynamicDescriptorOffsets.clear(); + mDefaultUniformDynamicDescriptorOffsets.resize(mExecutable->getLinkedShaderStageCount(), 0); initializeWriteDescriptorDesc(context); @@ -1825,6 +1866,9 @@ angle::Result ProgramExecutableVk::initializeDescriptorPools( ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::Texture].bindCachedDescriptorPool( context, mTextureSetDesc, mImmutableSamplersMaxDescriptorCount, descriptorSetLayoutCache, &mDynamicDescriptorPools[DescriptorSetIndex::Texture])); + ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::UniformBuffers].bindCachedDescriptorPool( + context, mUniformBuffersSetDesc, 1, descriptorSetLayoutCache, + &mDynamicDescriptorPools[DescriptorSetIndex::UniformBuffers])); return (*metaDescriptorPools)[DescriptorSetIndex::ShaderResource].bindCachedDescriptorPool( context, mShaderResourceSetDesc, 1, descriptorSetLayoutCache, &mDynamicDescriptorPools[DescriptorSetIndex::ShaderResource]); @@ -1856,11 +1900,44 @@ void ProgramExecutableVk::resolvePrecisionMismatch(const gl::ProgramMergedVaryin if (frontPrecision > backPrecision) { - // The output is higher precision than the input - ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable( - mergedVarying.frontShaderStage, mergedVarying.frontShader->id); - info.varyingIsOutput = true; - info.useRelaxedPrecision = true; + // The output is higher precision than the input. + if (mergedVarying.frontShaderStage == gl::ShaderType::TessControl && + mergedVarying.frontShader->isArray()) + { + // b/42266751 + // if the frontShader output belongs to TCS, and it is an array + // do not adjust its' precision, as this would result reading output from other + // invocations not working properly. Adjust the input precision instead. + + // For example, in below test case, TCS output is highp float, assume TES input is + // lowp float, If we adjust TCS output precision, we will truncate the write result + // to tc_out[1] to lowp, and get incorrect tc_out[1] > 10000000 comparison result. + // #extension GL_OES_tessellation_shader : require + // layout(vertices = 3) out; + // in highp float tc_in[]; + // out highp float tc_out[]; + // void main() + // { + // tc_out[gl_InvocationID] = tc_in[gl_InvocationID]; + // barrier(); + // if (gl_InvocationID == 0) + // { + // tc_out[gl_InvocationID] = tc_out[1] > 10000000 ? 1.0 : 0.0; + // } + // barrier(); + // } + ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable( + mergedVarying.backShaderStage, mergedVarying.backShader->id); + info.varyingIsInput = true; + SetBitField(info.useRelaxedPrecision, PrecisionAdjustmentEnum::kUpperPrecision); + } + else + { + ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable( + mergedVarying.frontShaderStage, mergedVarying.frontShader->id); + info.varyingIsOutput = true; + SetBitField(info.useRelaxedPrecision, PrecisionAdjustmentEnum::kLowerPrecision); + } } else { @@ -1869,7 +1946,7 @@ void ProgramExecutableVk::resolvePrecisionMismatch(const gl::ProgramMergedVaryin ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable( mergedVarying.backShaderStage, mergedVarying.backShader->id); info.varyingIsInput = true; - info.useRelaxedPrecision = true; + SetBitField(info.useRelaxedPrecision, PrecisionAdjustmentEnum::kLowerPrecision); } } } @@ -1896,8 +1973,9 @@ angle::Result ProgramExecutableVk::getOrAllocateDescriptorSet( { ASSERT((*newSharedCacheKeyOut)->valid()); // Cache miss. A new cache entry has been created. - descriptorSetDesc.updateDescriptorSet(renderer, writeDescriptorDescs, updateBuilder, - mDescriptorSets[setIndex]->getDescriptorSet()); + updateBuilder->updateWriteDescriptorSet(renderer, descriptorSetDesc, + writeDescriptorDescs, + mDescriptorSets[setIndex]->getDescriptorSet()); } } else @@ -1906,57 +1984,47 @@ angle::Result ProgramExecutableVk::getOrAllocateDescriptorSet( context, *mDescriptorSetLayouts[setIndex], &mDescriptorSets[setIndex])); ASSERT(mDescriptorSets[setIndex]); - descriptorSetDesc.updateDescriptorSet(renderer, writeDescriptorDescs, updateBuilder, - mDescriptorSets[setIndex]->getDescriptorSet()); + updateBuilder->updateWriteDescriptorSet(renderer, descriptorSetDesc, writeDescriptorDescs, + mDescriptorSets[setIndex]->getDescriptorSet()); } + mValidDescriptorSetIndices.set(setIndex); return angle::Result::Continue; } -angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet( +angle::Result ProgramExecutableVk::updateBuffersDescriptorSet( vk::Context *context, - uint32_t currentFrame, - UpdateDescriptorSetsBuilder *updateBuilder, + const uint32_t currentFrame, + const vk::DescriptorSetDescBuilder &descriptorSetDesc, const vk::WriteDescriptorDescs &writeDescriptorDescs, - const vk::DescriptorSetDescBuilder &shaderResourcesDesc, + const DescriptorSetIndex setIndex, + UpdateDescriptorSetsBuilder *updateBuilder, vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut) { - if (!mDynamicDescriptorPools[DescriptorSetIndex::ShaderResource]) + if (!mDynamicDescriptorPools[setIndex]) { (*newSharedCacheKeyOut).reset(); return angle::Result::Continue; } - ANGLE_TRY(getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, shaderResourcesDesc, - writeDescriptorDescs, DescriptorSetIndex::ShaderResource, - newSharedCacheKeyOut)); - - size_t numOffsets = writeDescriptorDescs.getDynamicDescriptorSetCount(); - mDynamicShaderResourceDescriptorOffsets.resize(numOffsets); - if (numOffsets > 0) - { - memcpy(mDynamicShaderResourceDescriptorOffsets.data(), - shaderResourcesDesc.getDynamicOffsets(), numOffsets * sizeof(uint32_t)); - } - - return angle::Result::Continue; + return getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, descriptorSetDesc, + writeDescriptorDescs, setIndex, newSharedCacheKeyOut); } angle::Result ProgramExecutableVk::updateUniformsAndXfbDescriptorSet( vk::Context *context, uint32_t currentFrame, UpdateDescriptorSetsBuilder *updateBuilder, - const vk::WriteDescriptorDescs &writeDescriptorDescs, - vk::BufferHelper *defaultUniformBuffer, - vk::DescriptorSetDescBuilder *uniformsAndXfbDesc, + const vk::BufferHelper *defaultUniformBuffer, vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut) { mCurrentDefaultUniformBufferSerial = defaultUniformBuffer ? defaultUniformBuffer->getBufferSerial() : vk::kInvalidBufferSerial; - return getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, *uniformsAndXfbDesc, - writeDescriptorDescs, DescriptorSetIndex::UniformsAndXfb, - sharedCacheKeyOut); + return getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, + mDefaultUniformAndXfbDescriptorDescBuilder, + mDefaultUniformAndXfbWriteDescriptorDescs, + DescriptorSetIndex::UniformsAndXfb, sharedCacheKeyOut); } angle::Result ProgramExecutableVk::updateTexturesDescriptorSet( @@ -1975,11 +2043,11 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet( // {VkImage/VkSampler} generates a unique serial. These object ids are combined to form a // unique signature for each descriptor set. This allows us to keep a cache of descriptor // sets and avoid calling vkAllocateDesctiporSets each texture update. - vk::DescriptorSetDescBuilder descriptorBuilder; - descriptorBuilder.updatePreCacheActiveTextures(context, *mExecutable, textures, samplers); + mTextureDescriptorDescBuilder.updatePreCacheActiveTextures( + context, *mExecutable, textures, samplers, mTextureWriteDescriptorDescs); ANGLE_TRY(mDynamicDescriptorPools[DescriptorSetIndex::Texture]->getOrAllocateDescriptorSet( - context, currentFrame, descriptorBuilder.getDesc(), + context, currentFrame, mTextureDescriptorDescBuilder.getDesc(), *mDescriptorSetLayouts[DescriptorSetIndex::Texture], &mDescriptorSets[DescriptorSetIndex::Texture], &newSharedCacheKey)); ASSERT(mDescriptorSets[DescriptorSetIndex::Texture]); @@ -2012,71 +2080,275 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet( textures, samplers, mDescriptorSets[DescriptorSetIndex::Texture]->getDescriptorSet())); } + mValidDescriptorSetIndices.set(DescriptorSetIndex::Texture); return angle::Result::Continue; } -template -angle::Result ProgramExecutableVk::bindDescriptorSets( - vk::ErrorContext *context, - uint32_t currentFrame, +angle::Result ProgramExecutableVk::updateUniformsAndXfbDescInfo( + vk::Context *context, + const vk::BufferHelper *currentUniformBuffer, + const vk::BufferHelper &emptyBuffer, + uint32_t currentFrameCount, + UpdateDescriptorSetsBuilder *updateBuilder, + bool activeUnpaused, + TransformFeedbackVk *transformFeedbackVk) +{ + mDefaultUniformAndXfbDescriptorDescBuilder.updateUniformsAndXfb( + context, *getExecutable(), mDefaultUniformAndXfbWriteDescriptorDescs, currentUniformBuffer, + emptyBuffer, activeUnpaused, transformFeedbackVk); + + vk::SharedDescriptorSetCacheKey newSharedCacheKey; + ANGLE_TRY(updateUniformsAndXfbDescriptorSet(context, currentFrameCount, updateBuilder, + currentUniformBuffer, &newSharedCacheKey)); + + if (newSharedCacheKey) + { + transformFeedbackVk->onNewDescriptorSet(*getExecutable(), newSharedCacheKey); + } + + return angle::Result::Continue; +} + +angle::Result ProgramExecutableVk::updateUniformBuffersDescInfo( + vk::Context *context, vk::CommandBufferHelperCommon *commandBufferHelper, - CommandBufferT *commandBuffer, - PipelineType pipelineType) + const gl::BufferVector &bufferBindings, + VkDeviceSize maxBoundBufferRange, + const vk::BufferHelper &emptyBuffer, + uint32_t currentFrameCount, + UpdateDescriptorSetsBuilder *updateBuilder) { - // Can probably use better dirty bits here. + const gl::ProgramExecutable *executable = getExecutable(); + for (size_t blockIndex : executable->getActiveUniformBufferBlocks()) + { + const GLuint binding = executable->getUniformBlockBinding(blockIndex); + mUniformBuffersDescriptorDescBuilder.updateOneUniformBuffer( + context, commandBufferHelper, blockIndex, executable->getUniformBlocks()[blockIndex], + bufferBindings[binding], getUniformBufferDescriptorType(), maxBoundBufferRange, + emptyBuffer, mUniformBuffersWriteDescriptorDescs); + } + + vk::SharedDescriptorSetCacheKey newSharedCacheKey; + ANGLE_TRY(updateBuffersDescriptorSet( + context, currentFrameCount, mUniformBuffersDescriptorDescBuilder, + mUniformBuffersWriteDescriptorDescs, DescriptorSetIndex::UniformBuffers, updateBuilder, + &newSharedCacheKey)); - // Find the maximum non-null descriptor set. This is used in conjunction with a driver - // workaround to bind empty descriptor sets only for gaps in between 0 and max and avoid - // binding unnecessary empty descriptor sets for the sets beyond max. - DescriptorSetIndex lastNonNullDescriptorSetIndex = DescriptorSetIndex::InvalidEnum; - for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums()) + if (newSharedCacheKey && !usesDynamicUniformBufferDescriptors()) { - if (mDescriptorSets[descriptorSetIndex]) + // A new cache entry has been created. We record this cache key in the images and + // buffers so that the descriptorSet cache can be destroyed when buffer/image is + // destroyed. + // + // Dynamic descriptor type uses the underlying BufferBlock in the descriptorSet. + // There could be many BufferHelper objects sub-allocated from the same BufferBlock. And + // each BufferHelper could combine with other buffers to form a descriptorSet. This means + // the descriptorSet numbers for BufferBlock could potentially very large, in thousands with + // some app traces like seeing in honkai_star_rail. The overhead of maintaining + // mDescriptorSetCacheManager for BufferBlock could be too big. We chose to not maintain + // mDescriptorSetCacheManager in this case. The only downside is that when BufferBlock gets + // destroyed, we will not able to immediately destroy all cached descriptorSets that it is + // part of. They will still gets evicted later on if needed. + for (size_t blockIndex : executable->getActiveUniformBufferBlocks()) { - lastNonNullDescriptorSetIndex = descriptorSetIndex; + const GLuint binding = executable->getUniformBlockBinding(blockIndex); + const gl::OffsetBindingPointer &bufferBinding = bufferBindings[binding]; + UpdateBufferWithSharedCacheKey(bufferBinding, newSharedCacheKey); } } - const VkPipelineBindPoint pipelineBindPoint = pipelineType == PipelineType::Compute - ? VK_PIPELINE_BIND_POINT_COMPUTE - : VK_PIPELINE_BIND_POINT_GRAPHICS; + return angle::Result::Continue; +} + +void ProgramExecutableVk::updateShaderResourcesWithSharedCacheKey( + const gl::BufferVector &shaderStorageBufferBindings, + const gl::BufferVector &atomicCounterBufferBindings, + const gl::ActiveTextureArray &activeImages, + const vk::SharedDescriptorSetCacheKey &newSharedCacheKey) +{ + const gl::ProgramExecutable *executable = getExecutable(); + ASSERT(!usesDynamicShaderStorageBufferDescriptors()); + ASSERT(!usesDynamicAtomicCounterBufferDescriptors()); - for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums()) + // Update shader storage buffers with new shared key + for (size_t blockIndex : executable->getActiveStorageBufferBlocks()) { - if (ToUnderlying(descriptorSetIndex) > ToUnderlying(lastNonNullDescriptorSetIndex)) - { - continue; - } + const GLuint binding = executable->getShaderStorageBlockBinding(blockIndex); + const gl::OffsetBindingPointer &bufferBinding = + shaderStorageBufferBindings[binding]; + UpdateBufferWithSharedCacheKey(bufferBinding, newSharedCacheKey); + } + + // Update atomic counter buffers with new shared key + const std::vector &blocks = executable->getAtomicCounterBuffers(); + for (uint32_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex) + { + const GLuint binding = executable->getAtomicCounterBufferBinding(blockIndex); + const gl::OffsetBindingPointer &bufferBinding = + atomicCounterBufferBindings[binding]; + UpdateBufferWithSharedCacheKey(bufferBinding, newSharedCacheKey); + } - if (!mDescriptorSets[descriptorSetIndex]) + for (const gl::ImageBinding &imageBinding : executable->getImageBindings()) + { + uint32_t arraySize = static_cast(imageBinding.boundImageUnits.size()); + for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement) { - continue; + GLuint imageUnit = imageBinding.boundImageUnits[arrayElement]; + // For simplicity, we do not check if uniform is active or duplicate. The worst case is + // we unnecessarily delete the cache entry when image bound to inactive uniform is + // destroyed. + TextureVk *textureVk = activeImages[imageUnit]; + if (!textureVk) + { + continue; + } + textureVk->onNewDescriptorSet(newSharedCacheKey); } + } +} +angle::Result ProgramExecutableVk::updateShaderResourcesDescInfo( + ContextVk *contextVk, + vk::CommandBufferHelperCommon *commandBufferHelper, + const FramebufferVk *framebufferVk, + const gl::BufferVector &shaderStorageBufferBindings, + const gl::BufferVector &atomicCounterBufferBindings, + const VkPhysicalDeviceLimits &limits, + const vk::BufferHelper &emptyBuffer, + const GLbitfield memoryBarrierBits, + const gl::ActiveTextureArray &activeImages, + const std::vector &imageUnits, + uint32_t currentFrameCount, + UpdateDescriptorSetsBuilder *updateBuilder) +{ + const gl::ProgramExecutable *executable = getExecutable(); + + const bool hasImages = executable->hasImages(); + const bool hasStorageBuffers = executable->hasStorageBuffers(); + const bool hasAtomicCounterBuffers = executable->hasAtomicCounterBuffers(); + const bool hasFramebufferFetch = executable->usesColorFramebufferFetch() || + executable->usesDepthFramebufferFetch() || + executable->usesStencilFramebufferFetch(); + + if (!hasStorageBuffers && !hasAtomicCounterBuffers && !hasImages && !hasFramebufferFetch) + { + return angle::Result::Continue; + } + + // Update input attachments first since it could change descriptor counts + if (hasFramebufferFetch) + { + // Update writeDescriptorDescs with inputAttachments + mShaderResourceWriteDescriptorDescs.updateInputAttachments(*executable, mVariableInfoMap, + framebufferVk); + + // Total descriptor count could have changed, resize DescriptorSetDescBuilder + mShaderResourceDescriptorDescBuilder.resize( + mShaderResourceWriteDescriptorDescs.getTotalDescriptorCount()); + + // Update DescriptorSetDescBuilder with inputAttachments + ANGLE_TRY(mShaderResourceDescriptorDescBuilder.updateInputAttachments( + contextVk, *executable, mVariableInfoMap, framebufferVk, + mShaderResourceWriteDescriptorDescs)); + } + + if (hasStorageBuffers) + { + mShaderResourceDescriptorDescBuilder.updateStorageBuffers( + contextVk, commandBufferHelper, *executable, shaderStorageBufferBindings, + executable->getShaderStorageBlocks(), getStorageBufferDescriptorType(), + limits.maxStorageBufferRange, emptyBuffer, mShaderResourceWriteDescriptorDescs, + memoryBarrierBits); + } + + if (hasAtomicCounterBuffers) + { + mShaderResourceDescriptorDescBuilder.updateAtomicCounters( + contextVk, commandBufferHelper, *executable, mVariableInfoMap, + atomicCounterBufferBindings, executable->getAtomicCounterBuffers(), + limits.minStorageBufferOffsetAlignment, emptyBuffer, + mShaderResourceWriteDescriptorDescs); + } + + if (hasImages) + { + ANGLE_TRY(mShaderResourceDescriptorDescBuilder.updateImages( + contextVk, *executable, mVariableInfoMap, activeImages, imageUnits, + mShaderResourceWriteDescriptorDescs)); + } + + // Record usage of storage buffers and images in the command buffer to aid handling of + // glMemoryBarrier. + if (hasImages || hasStorageBuffers || hasAtomicCounterBuffers) + { + commandBufferHelper->setHasShaderStorageOutput(); + } + + vk::SharedDescriptorSetCacheKey newSharedCacheKey; + ANGLE_TRY(updateBuffersDescriptorSet( + contextVk, currentFrameCount, mShaderResourceDescriptorDescBuilder, + mShaderResourceWriteDescriptorDescs, DescriptorSetIndex::ShaderResource, updateBuilder, + &newSharedCacheKey)); + + if (newSharedCacheKey) + { + // A new cache entry has been created. We record this cache key in the images and buffers so + // that the descriptorSet cache can be destroyed when buffer/image is destroyed. + updateShaderResourcesWithSharedCacheKey(shaderStorageBufferBindings, + atomicCounterBufferBindings, activeImages, + newSharedCacheKey); + } + + return angle::Result::Continue; +} + +template +angle::Result ProgramExecutableVk::bindDescriptorSets( + vk::ErrorContext *context, + uint32_t currentFrame, + vk::CommandBufferHelperCommon *commandBufferHelper, + CommandBufferT *commandBuffer, + PipelineType pipelineType) +{ + const VkPipelineBindPoint pipelineBindPoint = pipelineType == PipelineType::Compute + ? VK_PIPELINE_BIND_POINT_COMPUTE + : VK_PIPELINE_BIND_POINT_GRAPHICS; + + for (DescriptorSetIndex descriptorSetIndex : mValidDescriptorSetIndices) + { + ASSERT(mDescriptorSets[descriptorSetIndex]); VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex]->getDescriptorSet(); ASSERT(descSet != VK_NULL_HANDLE); - // Default uniforms are encompassed in a block per shader stage, and they are assigned - // through dynamic uniform buffers (requiring dynamic offsets). No other descriptor - // requires a dynamic offset. - if (descriptorSetIndex == DescriptorSetIndex::UniformsAndXfb) - { - commandBuffer->bindDescriptorSets( - getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet, - static_cast(mDynamicUniformDescriptorOffsets.size()), - mDynamicUniformDescriptorOffsets.data()); - } - else if (descriptorSetIndex == DescriptorSetIndex::ShaderResource) - { - commandBuffer->bindDescriptorSets( - getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet, - static_cast(mDynamicShaderResourceDescriptorOffsets.size()), - mDynamicShaderResourceDescriptorOffsets.data()); - } - else + switch (descriptorSetIndex) { - commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint, - descriptorSetIndex, 1, &descSet, 0, nullptr); + case DescriptorSetIndex::UniformsAndXfb: + // Default uniforms are encompassed in a block per shader stage, and they are + // assigned through dynamic uniform buffers (requiring dynamic offsets). + commandBuffer->bindDescriptorSets( + getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet, + static_cast(mDefaultUniformDynamicDescriptorOffsets.size()), + mDefaultUniformDynamicDescriptorOffsets.data()); + break; + case DescriptorSetIndex::UniformBuffers: + commandBuffer->bindDescriptorSets( + getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet, + static_cast( + mUniformBuffersWriteDescriptorDescs.getDynamicDescriptorSetCount()), + mUniformBuffersDescriptorDescBuilder.getDynamicOffsets()); + break; + case DescriptorSetIndex::ShaderResource: + commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint, + descriptorSetIndex, 1, &descSet, 0, nullptr); + break; + case DescriptorSetIndex::Texture: + commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint, + descriptorSetIndex, 1, &descSet, 0, nullptr); + break; + default: + UNREACHABLE(); + break; } commandBufferHelper->retainResource(mDescriptorSets[descriptorSetIndex].get()); @@ -2155,7 +2427,7 @@ angle::Result ProgramExecutableVk::updateUniforms(vk::Context *context, { const angle::MemoryBuffer &uniformData = mDefaultUniformBlocks[shaderType]->uniformData; memcpy(&bufferData[offsets[shaderType]], uniformData.data(), uniformData.size()); - mDynamicUniformDescriptorOffsets[offsetIndex] = + mDefaultUniformDynamicDescriptorOffsets[offsetIndex] = static_cast(bufferOffset + offsets[shaderType]); mDefaultUniformBlocksDirty.reset(shaderType); } @@ -2174,23 +2446,16 @@ angle::Result ProgramExecutableVk::updateUniforms(vk::Context *context, { // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't // modify the descriptor sets once initialized. - const vk::WriteDescriptorDescs &writeDescriptorDescs = - getDefaultUniformWriteDescriptorDescs(transformFeedbackVk); - - vk::DescriptorSetDescBuilder uniformsAndXfbDesc( - writeDescriptorDescs.getTotalDescriptorCount()); - uniformsAndXfbDesc.updateUniformsAndXfb( - context, *mExecutable, writeDescriptorDescs, defaultUniformBuffer, *emptyBuffer, - isTransformFeedbackActiveUnpaused, + mDefaultUniformAndXfbDescriptorDescBuilder.updateUniformsAndXfb( + context, *mExecutable, mDefaultUniformAndXfbWriteDescriptorDescs, defaultUniformBuffer, + *emptyBuffer, isTransformFeedbackActiveUnpaused, mExecutable->hasTransformFeedbackOutput() ? transformFeedbackVk : nullptr); vk::SharedDescriptorSetCacheKey newSharedCacheKey; ANGLE_TRY(updateUniformsAndXfbDescriptorSet(context, currentFrame, updateBuilder, - writeDescriptorDescs, defaultUniformBuffer, - &uniformsAndXfbDesc, &newSharedCacheKey)); + defaultUniformBuffer, &newSharedCacheKey)); if (newSharedCacheKey) { - defaultUniformBuffer->getBufferBlock()->onNewDescriptorSet(newSharedCacheKey); if (mExecutable->hasTransformFeedbackOutput() && context->getFeatures().emulateTransformFeedback.enabled) { diff --git a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h index 71b89971cff..3af13d2188c 100644 --- a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h +++ b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h @@ -57,15 +57,14 @@ union ProgramTransformOptions final { struct { - uint8_t surfaceRotation : 1; uint8_t removeTransformFeedbackEmulation : 1; uint8_t multiSampleFramebufferFetch : 1; uint8_t enableSampleShading : 1; uint8_t removeDepthStencilInput : 1; - uint8_t reserved : 3; // must initialize to zero + uint8_t reserved : 4; // must initialize to zero }; uint8_t permutationIndex; - static constexpr uint32_t kPermutationCount = 0x1 << 5; + static constexpr uint32_t kPermutationCount = 0x1 << 4; }; static_assert(sizeof(ProgramTransformOptions) == 1, "Size check failed"); static_assert(static_cast(SurfaceRotation::EnumCount) <= 8, "Size check failed"); @@ -188,14 +187,12 @@ class ProgramExecutableVk : public ProgramExecutableImpl const vk::GraphicsPipelineDesc **descPtrOut, vk::PipelineHelper **pipelineOut); - angle::Result linkGraphicsPipelineLibraries(ContextVk *contextVk, - vk::PipelineCacheAccess *pipelineCache, - const vk::GraphicsPipelineDesc &desc, - vk::PipelineHelper *vertexInputPipeline, - vk::PipelineHelper *shadersPipeline, - vk::PipelineHelper *fragmentOutputPipeline, - const vk::GraphicsPipelineDesc **descPtrOut, - vk::PipelineHelper **pipelineOut); + angle::Result createLinkedGraphicsPipeline(ContextVk *contextVk, + vk::PipelineCacheAccess *pipelineCache, + const vk::GraphicsPipelineDesc &desc, + vk::PipelineHelper *shadersPipeline, + const vk::GraphicsPipelineDesc **descPtrOut, + vk::PipelineHelper **pipelineOut); angle::Result getOrCreateComputePipeline(vk::ErrorContext *context, vk::PipelineCacheAccess *pipelineCache, @@ -222,23 +219,6 @@ class ProgramExecutableVk : public ProgramExecutableImpl PipelineType pipelineType, UpdateDescriptorSetsBuilder *updateBuilder); - angle::Result updateShaderResourcesDescriptorSet( - vk::Context *context, - uint32_t currentFrame, - UpdateDescriptorSetsBuilder *updateBuilder, - const vk::WriteDescriptorDescs &writeDescriptorDescs, - const vk::DescriptorSetDescBuilder &shaderResourcesDesc, - vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut); - - angle::Result updateUniformsAndXfbDescriptorSet( - vk::Context *context, - uint32_t currentFrame, - UpdateDescriptorSetsBuilder *updateBuilder, - const vk::WriteDescriptorDescs &writeDescriptorDescs, - vk::BufferHelper *defaultUniformBuffer, - vk::DescriptorSetDescBuilder *uniformsAndXfbDesc, - vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut); - template angle::Result bindDescriptorSets(vk::ErrorContext *context, uint32_t currentFrame, @@ -343,21 +323,43 @@ class ProgramExecutableVk : public ProgramExecutableImpl angle::Result mergePipelineCacheToRenderer(vk::ErrorContext *context) const; - const vk::WriteDescriptorDescs &getShaderResourceWriteDescriptorDescs() const - { - return mShaderResourceWriteDescriptorDescs; - } - const vk::WriteDescriptorDescs &getDefaultUniformWriteDescriptorDescs( - TransformFeedbackVk *transformFeedbackVk) const + angle::Result updateUniformsAndXfbDescInfo(vk::Context *context, + const vk::BufferHelper *currentUniformBuffer, + const vk::BufferHelper &emptyBuffer, + uint32_t currentFrameCount, + UpdateDescriptorSetsBuilder *updateBuilder, + bool activeUnpaused, + TransformFeedbackVk *transformFeedbackVk); + + angle::Result updateUniformBuffersDescInfo(vk::Context *context, + vk::CommandBufferHelperCommon *commandBufferHelper, + const gl::BufferVector &bufferBindings, + VkDeviceSize maxBoundBufferRange, + const vk::BufferHelper &emptyBuffer, + uint32_t currentFrameCount, + UpdateDescriptorSetsBuilder *updateBuilder); + + void updateOneUniformBufferOffset(const size_t blockIndex, + const gl::OffsetBindingPointer &bufferBinding) { - return transformFeedbackVk == nullptr ? mDefaultUniformWriteDescriptorDescs - : mDefaultUniformAndXfbWriteDescriptorDescs; + mUniformBuffersDescriptorDescBuilder.updateOneUniformBufferOffset( + blockIndex, bufferBinding, mUniformBuffersWriteDescriptorDescs); } - const vk::WriteDescriptorDescs &getTextureWriteDescriptorDescs() const - { - return mTextureWriteDescriptorDescs; - } + angle::Result updateShaderResourcesDescInfo( + ContextVk *contextVk, + vk::CommandBufferHelperCommon *commandBufferHelper, + const FramebufferVk *framebufferVk, + const gl::BufferVector &shaderStorageBufferBindings, + const gl::BufferVector &atomicCounterBufferBindings, + const VkPhysicalDeviceLimits &limits, + const vk::BufferHelper &emptyBuffer, + const GLbitfield memoryBarrierBits, + const gl::ActiveTextureArray &activeImages, + const std::vector &imageUnits, + uint32_t currentFrameCount, + UpdateDescriptorSetsBuilder *updateBuilder); + // The following functions are for internal use of programs, including from a threaded link job: angle::Result resizeUniformBlockMemory(vk::ErrorContext *context, const gl::ShaderMap &requiredBufferSize); @@ -478,15 +480,13 @@ class ProgramExecutableVk : public ProgramExecutableImpl const vk::RenderPass &compatibleRenderPass, const vk::GraphicsPipelineDesc **descPtrOut, vk::PipelineHelper **pipelineOut); - angle::Result prepareForWarmUpPipelineCache( - vk::ErrorContext *context, - vk::PipelineRobustness pipelineRobustness, - vk::PipelineProtectedAccess pipelineProtectedAccess, - vk::GraphicsPipelineSubset subset, - bool *isComputeOut, - angle::FixedVector *surfaceRotationVariationsOut, - vk::GraphicsPipelineDesc **graphicsPipelineDescOut, - vk::RenderPass *renderPassOut); + angle::Result preparePipelineCacheForWarmUp(vk::ErrorContext *context, + vk::PipelineRobustness pipelineRobustness, + vk::PipelineProtectedAccess pipelineProtectedAccess, + vk::GraphicsPipelineSubset subset, + bool *isComputeOut, + vk::GraphicsPipelineDesc **graphicsPipelineDescOut, + vk::RenderPass *renderPassOut); angle::Result warmUpComputePipelineCache(vk::ErrorContext *context, vk::PipelineRobustness pipelineRobustness, vk::PipelineProtectedAccess pipelineProtectedAccess); @@ -494,7 +494,6 @@ class ProgramExecutableVk : public ProgramExecutableImpl vk::PipelineRobustness pipelineRobustness, vk::PipelineProtectedAccess pipelineProtectedAccess, vk::GraphicsPipelineSubset subset, - const bool isSurfaceRotated, const vk::GraphicsPipelineDesc &graphicsPipelineDesc, const vk::RenderPass &renderPass, vk::PipelineHelper *placeholderPipelineHelper); @@ -517,7 +516,29 @@ class ProgramExecutableVk : public ProgramExecutableImpl void initializeWriteDescriptorDesc(vk::ErrorContext *context); + void updateShaderResourcesWithSharedCacheKey( + const gl::BufferVector &shaderStorageBufferBindings, + const gl::BufferVector &atomicCounterBufferBindings, + const gl::ActiveTextureArray &activeImages, + const vk::SharedDescriptorSetCacheKey &newSharedCacheKey); + + angle::Result updateUniformsAndXfbDescriptorSet( + vk::Context *context, + uint32_t currentFrame, + UpdateDescriptorSetsBuilder *updateBuilder, + const vk::BufferHelper *defaultUniformBuffer, + vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut); + + angle::Result updateBuffersDescriptorSet(vk::Context *context, + const uint32_t currentFrame, + const vk::DescriptorSetDescBuilder &descriptorSetDesc, + const vk::WriteDescriptorDescs &writeDescriptorDescs, + const DescriptorSetIndex setIndex, + UpdateDescriptorSetsBuilder *updateBuilder, + vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut); + // Descriptor sets and pools for shader resources for this program. + angle::PackedEnumBitSet mValidDescriptorSetIndices; vk::DescriptorSetArray mDescriptorSets; vk::DescriptorSetArray mDynamicDescriptorPools; vk::BufferSerial mCurrentDefaultUniformBufferSerial; @@ -531,13 +552,12 @@ class ProgramExecutableVk : public ProgramExecutableImpl // A set of dynamic offsets used with vkCmdBindDescriptorSets for the default uniform buffers. VkDescriptorType mUniformBufferDescriptorType; - gl::ShaderVector mDynamicUniformDescriptorOffsets; - std::vector mDynamicShaderResourceDescriptorOffsets; + gl::ShaderVector mDefaultUniformDynamicDescriptorOffsets; ShaderInterfaceVariableInfoMap mVariableInfoMap; - static_assert((ProgramTransformOptions::kPermutationCount == 32), - "ProgramTransformOptions::kPermutationCount must be 32."); + static_assert((ProgramTransformOptions::kPermutationCount == 16), + "ProgramTransformOptions::kPermutationCount must be 16."); angle::BitSet32 mValidGraphicsPermutations; static_assert((vk::ComputePipelineOptions::kPermutationCount == 4), @@ -583,11 +603,18 @@ class ProgramExecutableVk : public ProgramExecutableImpl vk::GraphicsPipelineDesc mWarmUpGraphicsPipelineDesc; // The "layout" information for descriptorSets + vk::WriteDescriptorDescs mUniformBuffersWriteDescriptorDescs; vk::WriteDescriptorDescs mShaderResourceWriteDescriptorDescs; vk::WriteDescriptorDescs mTextureWriteDescriptorDescs; - vk::WriteDescriptorDescs mDefaultUniformWriteDescriptorDescs; vk::WriteDescriptorDescs mDefaultUniformAndXfbWriteDescriptorDescs; + // The DescriptorSetDescBuilder for descriptorSets + vk::DescriptorSetDescBuilder mUniformBuffersDescriptorDescBuilder; + vk::DescriptorSetDescBuilder mShaderResourceDescriptorDescBuilder; + vk::DescriptorSetDescBuilder mTextureDescriptorDescBuilder; + vk::DescriptorSetDescBuilder mDefaultUniformAndXfbDescriptorDescBuilder; + + vk::DescriptorSetLayoutDesc mUniformBuffersSetDesc; vk::DescriptorSetLayoutDesc mShaderResourceSetDesc; vk::DescriptorSetLayoutDesc mTextureSetDesc; vk::DescriptorSetLayoutDesc mDefaultUniformAndXfbSetDesc; diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp index 095616f75e5..675f89948f7 100644 --- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp +++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp @@ -13,8 +13,6 @@ #include "common/utilities.h" #include "libANGLE/Context.h" #include "libANGLE/ProgramLinkedResources.h" -#include "libANGLE/renderer/renderer_utils.h" -#include "libANGLE/renderer/vulkan/BufferVk.h" #include "libANGLE/renderer/vulkan/TextureVk.h" namespace rx @@ -25,8 +23,9 @@ namespace // Identical to Std140 encoder in all aspects, except it ignores opaque uniform types. class VulkanDefaultBlockEncoder : public sh::Std140BlockEncoder { - public: + protected: void advanceOffset(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, @@ -37,8 +36,29 @@ class VulkanDefaultBlockEncoder : public sh::Std140BlockEncoder return; } - sh::Std140BlockEncoder::advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, - matrixStride); + sh::Std140BlockEncoder::advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, + arrayStride, matrixStride); + } +}; +// Identical to PackedSPIRVBlockEncoder encoder in all aspects, except it ignores opaque uniform +// types. +class VulkanDefaultBlockPackedEncoder : public sh::PackedSPIRVBlockEncoder +{ + protected: + void advanceOffset(GLenum type, + const size_t bytesPerComponent, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) override + { + if (gl::IsOpaqueType(type)) + { + return; + } + + sh::PackedSPIRVBlockEncoder::advanceOffset(type, bytesPerComponent, arraySizes, + isRowMajorMatrix, arrayStride, matrixStride); } }; @@ -128,17 +148,6 @@ class LinkTaskVk final : public vk::ErrorContext, public LinkTask return angle::Result::Stop; } - // Accumulate relevant perf counters - const angle::VulkanPerfCounters &from = getPerfCounters(); - angle::VulkanPerfCounters &to = contextVk->getPerfCounters(); - - to.pipelineCreationCacheHits += from.pipelineCreationCacheHits; - to.pipelineCreationCacheMisses += from.pipelineCreationCacheMisses; - to.pipelineCreationTotalCacheHitsDurationNs += - from.pipelineCreationTotalCacheHitsDurationNs; - to.pipelineCreationTotalCacheMissesDurationNs += - from.pipelineCreationTotalCacheMissesDurationNs; - return angle::Result::Continue; } @@ -148,9 +157,10 @@ class LinkTaskVk final : public vk::ErrorContext, public LinkTask std::vector> *postLinkSubTasksOut); void linkResources(const gl::ProgramLinkedResources &resources); - angle::Result initDefaultUniformBlocks(); + angle::Result initDefaultUniformBlocks(bool usePackedLayoutForDefaultUniform); void generateUniformLayoutMapping(gl::ShaderMap *layoutMapOut, - gl::ShaderMap *requiredBufferSizeOut); + gl::ShaderMap *requiredBufferSizeOut, + const bool usePackedLayoutForDefaultUniform); void initDefaultUniformLayoutMapping(gl::ShaderMap *layoutMapOut); // The front-end ensures that the program is not accessed while linking, so it is safe to @@ -201,7 +211,8 @@ angle::Result LinkTaskVk::linkImpl(const gl::ProgramLinkedResources &resources, ANGLE_TRY(executableVk->initShaders(this, mExecutable->getLinkedShaderStages(), spirvBlobs, mIsGLES1)); - ANGLE_TRY(initDefaultUniformBlocks()); + ANGLE_TRY( + initDefaultUniformBlocks(getFeatures().convertLowpAndMediumpFloatUniformsTo16Bits.enabled)); ANGLE_TRY(executableVk->createPipelineLayout(this, &mPipelineLayoutCache, &mDescriptorSetLayoutCache, nullptr)); @@ -233,7 +244,7 @@ void LinkTaskVk::linkResources(const gl::ProgramLinkedResources &resources) linker.linkResources(mState, resources); } -angle::Result LinkTaskVk::initDefaultUniformBlocks() +angle::Result LinkTaskVk::initDefaultUniformBlocks(const bool usePackedLayoutForDefaultUniform) { ProgramExecutableVk *executableVk = vk::GetImpl(mExecutable); @@ -242,7 +253,7 @@ angle::Result LinkTaskVk::initDefaultUniformBlocks() gl::ShaderMap requiredBufferSize; requiredBufferSize.fill(0); - generateUniformLayoutMapping(&layoutMap, &requiredBufferSize); + generateUniformLayoutMapping(&layoutMap, &requiredBufferSize, usePackedLayoutForDefaultUniform); initDefaultUniformLayoutMapping(&layoutMap); // All uniform initializations are complete, now resize the buffers accordingly and return @@ -251,7 +262,8 @@ angle::Result LinkTaskVk::initDefaultUniformBlocks() void InitDefaultUniformBlock(const std::vector &uniforms, sh::BlockLayoutMap *blockLayoutMapOut, - size_t *blockSizeOut) + size_t *blockSizeOut, + const bool usePackedLayoutForDefaultUniform) { if (uniforms.empty()) { @@ -259,15 +271,24 @@ void InitDefaultUniformBlock(const std::vector &uniforms, return; } - VulkanDefaultBlockEncoder blockEncoder; - sh::GetActiveUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut); - - *blockSizeOut = blockEncoder.getCurrentOffset(); + if (usePackedLayoutForDefaultUniform) + { + VulkanDefaultBlockPackedEncoder packedBlockEncoder; + sh::GetActiveUniformBlockInfo(uniforms, "", &packedBlockEncoder, blockLayoutMapOut); + *blockSizeOut = packedBlockEncoder.getCurrentOffset(); + } + else + { + VulkanDefaultBlockEncoder blockEncoder; + sh::GetActiveUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut); + *blockSizeOut = blockEncoder.getCurrentOffset(); + } return; } void LinkTaskVk::generateUniformLayoutMapping(gl::ShaderMap *layoutMapOut, - gl::ShaderMap *requiredBufferSizeOut) + gl::ShaderMap *requiredBufferSizeOut, + const bool usePackedLayoutForDefaultUniform) { for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages()) { @@ -277,7 +298,8 @@ void LinkTaskVk::generateUniformLayoutMapping(gl::ShaderMap { const std::vector &uniforms = shader->uniforms; InitDefaultUniformBlock(uniforms, &(*layoutMapOut)[shaderType], - &(*requiredBufferSizeOut)[shaderType]); + &(*requiredBufferSizeOut)[shaderType], + usePackedLayoutForDefaultUniform); } } } @@ -288,6 +310,13 @@ void LinkTaskVk::initDefaultUniformLayoutMapping(gl::ShaderMapgetUniforms(); + // Reserve enough storage for the layoutInfo. + for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages()) + { + executableVk->getSharedDefaultUniformBlock(shaderType) + ->uniformLayout.reserve(mExecutable->getUniformLocations().size()); + } + for (const gl::VariableLocation &location : mExecutable->getUniformLocations()) { gl::ShaderMap layoutInfo; @@ -318,7 +347,6 @@ void LinkTaskVk::initDefaultUniformLayoutMapping(gl::ShaderMapsecond; } } - ASSERT(found); } } diff --git a/src/libANGLE/renderer/vulkan/QueryVk.cpp b/src/libANGLE/renderer/vulkan/QueryVk.cpp index 0b1d8704037..deb58472f15 100644 --- a/src/libANGLE/renderer/vulkan/QueryVk.cpp +++ b/src/libANGLE/renderer/vulkan/QueryVk.cpp @@ -492,8 +492,8 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait) // We only need to check mQueryHelper, not mStashedQueryHelper, since they are always in order. if (contextVk->hasUnsubmittedUse(mQueryHelper.get())) { - ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, nullptr, - RenderPassClosureReason::GetQueryResult)); + ANGLE_TRY( + contextVk->flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::GetQueryResult)); ASSERT(contextVk->getRenderer()->hasResourceUseSubmitted( mQueryHelperTimeElapsedBegin.getResourceUse())); diff --git a/src/libANGLE/renderer/vulkan/README.md b/src/libANGLE/renderer/vulkan/README.md index d11bee4f341..803a12f3848 100644 --- a/src/libANGLE/renderer/vulkan/README.md +++ b/src/libANGLE/renderer/vulkan/README.md @@ -39,7 +39,7 @@ optimization internally. command buffer into vulkan's primary command buffer, puts secondary command buffer back to unstarted state and then goes into recycler for reuse. -The back-end (mostly) records Image and Buffer barriers through additional `CommandBufferAccess` +The back-end (mostly) records Image and Buffer barriers through additional `CommandResources` APIs, the result of which is passed to `getOutsideRenderPassCommandBuffer`. Note that the barriers are not actually recorded until `getOutsideRenderPassCommandBuffer` is called: @@ -62,13 +62,13 @@ In this example we'll be recording a buffer copy command: ``` // Ensure that ANGLE sets proper read and write barriers for the Buffers. - vk::CommandBufferAccess access; - access.onBufferTransferWrite(dstBuffer); - access.onBufferTransferRead(srcBuffer); + vk::CommandResources resources; + resources.onBufferTransferWrite(dstBuffer); + resources.onBufferTransferRead(srcBuffer); // Get a pointer to a secondary command buffer for command recording. vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Record the copy command into the secondary buffer. We're done! commandBuffer->copyBuffer(srcBuffer->getBuffer(), dstBuffer->getBuffer(), copyCount, copies); diff --git a/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp b/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp index 9c85cd85525..fcccec54674 100644 --- a/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp +++ b/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp @@ -52,6 +52,10 @@ void RenderTargetVk::init(vk::ImageHelper *image, uint32_t layerCount, RenderTargetTransience transience) { + // If this comes from SurfaceVk, the usage bit will be 0 (image init are deferred). + ASSERT(image->getUsage() == 0 || + (image->getUsage() & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) != 0); mImage = image; mImageViews = imageViews; mResolveImage = resolveImage; @@ -64,17 +68,12 @@ void RenderTargetVk::init(vk::ImageHelper *image, mTransience = transience; } -void RenderTargetVk::invalidateImageAndViews() -{ - mImage = nullptr; - mImageViews = nullptr; - mResolveImage = nullptr; - mResolveImageViews = nullptr; -} - void RenderTargetVk::reset() { - invalidateImageAndViews(); + mImage = nullptr; + mImageViews = nullptr; + mResolveImage = nullptr; + mResolveImageViews = nullptr; mImageSiblingSerial = {}; mLevelIndexGL = gl::LevelIndex(0); mLayerIndex = 0; @@ -181,7 +180,7 @@ const vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass() const return *mResolveImage; } -angle::Result RenderTargetVk::getImageViewImpl(vk::ErrorContext *context, +angle::Result RenderTargetVk::getImageViewImpl(ContextVk *contextVk, const vk::ImageHelper &image, vk::ImageViewHelper *imageViews, const vk::ImageView **imageViewOut) const @@ -190,68 +189,68 @@ angle::Result RenderTargetVk::getImageViewImpl(vk::ErrorContext *context, vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image)); if (mLayerCount == 1) { - return imageViews->getLevelLayerDrawImageView(context, image, levelVk, mLayerIndex, + return imageViews->getLevelLayerDrawImageView(contextVk, image, levelVk, mLayerIndex, imageViewOut); } // Layered render targets view the whole level or a handful of layers in case of multiview. - return imageViews->getLevelDrawImageView(context, image, levelVk, mLayerIndex, mLayerCount, + return imageViews->getLevelDrawImageView(contextVk, image, levelVk, mLayerIndex, mLayerCount, imageViewOut); } -angle::Result RenderTargetVk::getImageView(vk::ErrorContext *context, +angle::Result RenderTargetVk::getImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const { ASSERT(mImage); - return getImageViewImpl(context, *mImage, mImageViews, imageViewOut); + return getImageViewImpl(contextVk, *mImage, mImageViews, imageViewOut); } -angle::Result RenderTargetVk::getImageViewWithColorspace(vk::ErrorContext *context, +angle::Result RenderTargetVk::getImageViewWithColorspace(ContextVk *contextVk, gl::SrgbWriteControlMode mode, const vk::ImageView **imageViewOut) const { ASSERT(mImage); mImageViews->updateSrgbWiteControlMode(*mImage, mode); - return getImageViewImpl(context, *mImage, mImageViews, imageViewOut); + return getImageViewImpl(contextVk, *mImage, mImageViews, imageViewOut); } -angle::Result RenderTargetVk::getResolveImageView(vk::ErrorContext *context, +angle::Result RenderTargetVk::getResolveImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const { ASSERT(mResolveImage); - return getImageViewImpl(context, *mResolveImage, mResolveImageViews, imageViewOut); + return getImageViewImpl(contextVk, *mResolveImage, mResolveImageViews, imageViewOut); } -angle::Result RenderTargetVk::getDepthOrStencilImageView(vk::ErrorContext *context, +angle::Result RenderTargetVk::getDepthOrStencilImageView(ContextVk *contextVk, VkImageAspectFlagBits aspect, const vk::ImageView **imageViewOut) const { ASSERT(mImage); - return getDepthOrStencilImageViewImpl(context, *mImage, mImageViews, aspect, imageViewOut); + return getDepthOrStencilImageViewImpl(contextVk, *mImage, mImageViews, aspect, imageViewOut); } angle::Result RenderTargetVk::getDepthOrStencilImageViewForCopy( - vk::ErrorContext *context, + ContextVk *contextVk, VkImageAspectFlagBits aspect, const vk::ImageView **imageViewOut) const { return isResolveImageOwnerOfData() - ? getResolveDepthOrStencilImageView(context, aspect, imageViewOut) - : getDepthOrStencilImageView(context, aspect, imageViewOut); + ? getResolveDepthOrStencilImageView(contextVk, aspect, imageViewOut) + : getDepthOrStencilImageView(contextVk, aspect, imageViewOut); } angle::Result RenderTargetVk::getResolveDepthOrStencilImageView( - vk::ErrorContext *context, + ContextVk *contextVk, VkImageAspectFlagBits aspect, const vk::ImageView **imageViewOut) const { ASSERT(mResolveImage); - return getDepthOrStencilImageViewImpl(context, *mResolveImage, mResolveImageViews, aspect, + return getDepthOrStencilImageViewImpl(contextVk, *mResolveImage, mResolveImageViews, aspect, imageViewOut); } angle::Result RenderTargetVk::getDepthOrStencilImageViewImpl( - vk::ErrorContext *context, + ContextVk *contextVk, const vk::ImageHelper &image, vk::ImageViewHelper *imageViews, VkImageAspectFlagBits aspect, @@ -260,7 +259,7 @@ angle::Result RenderTargetVk::getDepthOrStencilImageViewImpl( // If the image has only one aspect, the usual view is sufficient. if (image.getAspectFlags() == aspect) { - return getImageViewImpl(context, image, imageViews, imageViewOut); + return getImageViewImpl(contextVk, image, imageViews, imageViewOut); } // Otherwise, for images with both the depth and stencil aspects, need to create special views @@ -269,12 +268,12 @@ angle::Result RenderTargetVk::getDepthOrStencilImageViewImpl( vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image)); if (mLayerCount == 1) { - return imageViews->getLevelLayerDepthOrStencilImageView(context, image, levelVk, + return imageViews->getLevelLayerDepthOrStencilImageView(contextVk, image, levelVk, mLayerIndex, aspect, imageViewOut); } // Layered render targets view the whole level or a handful of layers in case of multiview. - return imageViews->getLevelDepthOrStencilImageView(context, image, levelVk, mLayerIndex, + return imageViews->getLevelDepthOrStencilImageView(contextVk, image, levelVk, mLayerIndex, mLayerCount, aspect, imageViewOut); } @@ -291,7 +290,7 @@ vk::ImageHelper *RenderTargetVk::getOwnerOfData() const return isResolveImageOwnerOfData() ? mResolveImage : mImage; } -angle::Result RenderTargetVk::getCopyImageView(vk::ErrorContext *context, +angle::Result RenderTargetVk::getCopyImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const { const vk::ImageViewHelper *imageViews = @@ -308,8 +307,8 @@ angle::Result RenderTargetVk::getCopyImageView(vk::ErrorContext *context, // Otherwise, this must come from the surface, in which case the image is 2D, so the image view // used to draw is just as good for fetching. If resolve attachment is present, fetching is // done from that. - return isResolveImageOwnerOfData() ? getResolveImageView(context, imageViewOut) - : getImageView(context, imageViewOut); + return isResolveImageOwnerOfData() ? getResolveImageView(contextVk, imageViewOut) + : getImageView(contextVk, imageViewOut); } angle::FormatID RenderTargetVk::getImageActualFormatID() const @@ -362,10 +361,14 @@ void RenderTargetVk::updateSwapchainImage(vk::ImageHelper *image, vk::ImageViewHelper *resolveImageViews) { ASSERT(image && image->valid() && imageViews); + ASSERT(!mImageSiblingSerial.valid()); + ASSERT(mLevelIndexGL == gl::LevelIndex(0)); + ASSERT(mLayerIndex == 0); mImage = image; mImageViews = imageViews; mResolveImage = resolveImage; mResolveImageViews = resolveImageViews; + mLayerCount = 1; } vk::ImageHelper &RenderTargetVk::getImageForCopy() const diff --git a/src/libANGLE/renderer/vulkan/RenderTargetVk.h b/src/libANGLE/renderer/vulkan/RenderTargetVk.h index e9df6d17ab6..5642b19e752 100644 --- a/src/libANGLE/renderer/vulkan/RenderTargetVk.h +++ b/src/libANGLE/renderer/vulkan/RenderTargetVk.h @@ -92,26 +92,25 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget vk::ImageHelper &getImageForWrite() const; // For cube maps we use single-level single-layer 2D array views. - angle::Result getImageView(vk::ErrorContext *context, const vk::ImageView **imageViewOut) const; - angle::Result getImageViewWithColorspace(vk::ErrorContext *context, + angle::Result getImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const; + angle::Result getImageViewWithColorspace(ContextVk *contextVk, gl::SrgbWriteControlMode srgbWriteContrlMode, const vk::ImageView **imageViewOut) const; - angle::Result getResolveImageView(vk::ErrorContext *context, + angle::Result getResolveImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const; - angle::Result getDepthOrStencilImageView(vk::ErrorContext *context, + angle::Result getDepthOrStencilImageView(ContextVk *contextVk, VkImageAspectFlagBits aspect, const vk::ImageView **imageViewOut) const; - angle::Result getDepthOrStencilImageViewForCopy(vk::ErrorContext *context, + angle::Result getDepthOrStencilImageViewForCopy(ContextVk *contextVk, VkImageAspectFlagBits aspect, const vk::ImageView **imageViewOut) const; - angle::Result getResolveDepthOrStencilImageView(vk::ErrorContext *context, + angle::Result getResolveDepthOrStencilImageView(ContextVk *contextVk, VkImageAspectFlagBits aspect, const vk::ImageView **imageViewOut) const; // For 3D textures, the 2D view created for render target is invalid to read from. The // following will return a view to the whole image (for all types, including 3D and 2DArray). - angle::Result getCopyImageView(vk::ErrorContext *context, - const vk::ImageView **imageViewOut) const; + angle::Result getCopyImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const; angle::FormatID getImageActualFormatID() const; const angle::Format &getImageActualFormat() const; @@ -158,7 +157,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget } bool isYuvResolve() const { - return mResolveImage != nullptr ? mResolveImage->isYuvResolve() : false; + return mResolveImage != nullptr ? mResolveImage->isYuvExternalFormat() : false; } void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey) @@ -169,14 +168,16 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget { mFramebufferCacheManager.releaseKeys(contextVk); } - // Releases framebuffers and resets Image and ImageView pointers, while keeping other - // members intact, in order to allow |updateSwapchainImage| call later. - void releaseImageAndViews(ContextVk *contextVk) + // Resets all members to the initial state without releasing framebuffers since Window Surface + // framebuffers are not managed by the cache. + void releaseSwapchainImage() { reset(); } + // Releases framebuffers and resets all members to the initial state. + void release(ContextVk *contextVk) { releaseFramebuffers(contextVk); - invalidateImageAndViews(); + reset(); } - // Releases framebuffers and resets all members to the initial state. + // Destroys framebuffers and resets all members to the initial state. void destroy(vk::Renderer *renderer) { mFramebufferCacheManager.destroyKeys(renderer); @@ -206,14 +207,13 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget } private: - void invalidateImageAndViews(); void reset(); - angle::Result getImageViewImpl(vk::ErrorContext *context, + angle::Result getImageViewImpl(ContextVk *contextVk, const vk::ImageHelper &image, vk::ImageViewHelper *imageViews, const vk::ImageView **imageViewOut) const; - angle::Result getDepthOrStencilImageViewImpl(vk::ErrorContext *context, + angle::Result getDepthOrStencilImageViewImpl(ContextVk *contextVk, const vk::ImageHelper &image, vk::ImageViewHelper *imageViews, VkImageAspectFlagBits aspect, diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp index 41e1f2aff51..574091a5b96 100644 --- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp @@ -27,7 +27,8 @@ RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state) : RenderbufferImpl(state), mOwnsImage(false), mImage(nullptr), - mImageObserverBinding(this, kRenderbufferImageSubjectIndex) + mImageObserverBinding(this, kRenderbufferImageSubjectIndex), + mRenderer(nullptr) {} RenderbufferVk::~RenderbufferVk() {} @@ -46,8 +47,8 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, gl::MultisamplingMode mode) { ContextVk *contextVk = vk::GetImpl(context); - vk::Renderer *renderer = contextVk->getRenderer(); - const vk::Format &format = renderer->getFormat(internalformat); + mRenderer = contextVk->getRenderer(); + const vk::Format &format = mRenderer->getFormat(internalformat); angle::FormatID textureFormatID = format.getActualRenderableImageFormatID(); if (!mOwnsImage) @@ -77,7 +78,7 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, mOwnsImage = true; mImageSiblingSerial = {}; mImageObserverBinding.bind(mImage); - mImageViews.init(renderer); + mImageViews.init(mRenderer); } const angle::Format &textureFormat = format.getActualRenderableImageFormat(); @@ -86,7 +87,7 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, const bool isRenderToTexture = mode == gl::MultisamplingMode::MultisampledRenderToTexture; const bool hasRenderToTextureEXT = - renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled; + mRenderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled; // Transfer and sampled usage are used for various utilities such as readback or blit. VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | @@ -105,14 +106,14 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, // For framebuffer fetch and advanced blend emulation, color will be read as input attachment. // For depth/stencil framebuffer fetch, depth/stencil will also be read as input attachment. if (!isDepthStencilFormat || - renderer->getFeatures().supportsShaderFramebufferFetchDepthStencil.enabled) + mRenderer->getFeatures().supportsShaderFramebufferFetchDepthStencil.enabled) { usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } VkImageCreateFlags createFlags = vk::kVkImageCreateFlagsNone; if (isRenderToTexture && - renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled) + mRenderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled) { createFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT; } @@ -125,15 +126,17 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, const uint32_t imageSamples = isRenderToTexture ? 1 : samples; bool robustInit = contextVk->isRobustResourceInitEnabled(); + vk::TileMemory tileMemoryPreference = + isDepthStencilFormat ? vk::TileMemory::Preferred : vk::TileMemory::Prohibited; VkExtent3D extents = {static_cast(width), static_cast(height), 1u}; ANGLE_TRY(mImage->initExternal( contextVk, gl::TextureType::_2D, extents, format.getIntendedFormatID(), textureFormatID, - imageSamples, usage, createFlags, vk::ImageLayout::Undefined, nullptr, gl::LevelIndex(0), 1, - 1, robustInit, false, vk::YcbcrConversionDesc{}, nullptr)); + imageSamples, usage, createFlags, vk::ImageAccess::Undefined, nullptr, gl::LevelIndex(0), 1, + 1, robustInit, false, tileMemoryPreference, vk::YcbcrConversionDesc{}, nullptr)); VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - ANGLE_TRY(contextVk->initImageAllocation(mImage, false, renderer->getMemoryProperties(), flags, + ANGLE_TRY(contextVk->initImageAllocation(mImage, false, flags, vk::MemoryAllocationType::RenderBufferStorageImage)); // If multisampled render to texture, an implicit multisampled image is created which is used as @@ -141,11 +144,11 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, // automatically resolved into |mImage| and its contents are discarded. if (isRenderToTexture && !hasRenderToTextureEXT) { - mMultisampledImageViews.init(renderer); + mMultisampledImageViews.init(mRenderer); ANGLE_TRY(mMultisampledImage.initImplicitMultisampledRenderToTexture( - contextVk, false, renderer->getMemoryProperties(), gl::TextureType::_2D, samples, - *mImage, mImage->getExtents(), robustInit)); + contextVk, false, gl::TextureType::_2D, samples, *mImage, mImage->getExtents(), + robustInit)); mRenderTarget.init(&mMultisampledImage, &mMultisampledImageViews, mImage, &mImageViews, mImageSiblingSerial, gl::LevelIndex(0), 0, 1, @@ -185,7 +188,7 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex egl::Image *image) { ContextVk *contextVk = vk::GetImpl(context); - vk::Renderer *renderer = contextVk->getRenderer(); + mRenderer = contextVk->getRenderer(); ANGLE_TRY(contextVk->getShareGroup()->lockDefaultContextsPriority(contextVk)); @@ -196,7 +199,7 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex mOwnsImage = false; mImageSiblingSerial = imageVk->generateSiblingSerial(); mImageObserverBinding.bind(mImage); - mImageViews.init(renderer); + mImageViews.init(mRenderer); // Update ImageViewHelper's colorspace related state EGLenum imageColorspaceAttribute = image->getColorspaceAttribute(); @@ -314,7 +317,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk) } else { - mRenderTarget.releaseImageAndViews(contextVk); + mRenderTarget.release(contextVk); mImageViews.release(renderer, mImage->getResourceUse()); mMultisampledImageViews.release(renderer, mImage->getResourceUse()); } @@ -393,10 +396,17 @@ void RenderbufferVk::onSubjectStateChange(angle::SubjectIndex index, angle::Subj { ASSERT(index == kRenderbufferImageSubjectIndex && (message == angle::SubjectMessage::SubjectChanged || - message == angle::SubjectMessage::InitializationComplete)); + message == angle::SubjectMessage::InitializationComplete || + message == angle::SubjectMessage::VkImageChanged)); + + if (message == angle::SubjectMessage::VkImageChanged) + { + mImageViews.release(mRenderer, mImage->getResourceUse()); + } // Forward the notification to the parent class that the staging buffer changed. - if (message == angle::SubjectMessage::SubjectChanged) + if (message == angle::SubjectMessage::SubjectChanged || + message == angle::SubjectMessage::VkImageChanged) { onStateChange(angle::SubjectMessage::SubjectChanged); } diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/src/libANGLE/renderer/vulkan/RenderbufferVk.h index b66c341ef10..0e208e98f82 100644 --- a/src/libANGLE/renderer/vulkan/RenderbufferVk.h +++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.h @@ -127,6 +127,8 @@ class RenderbufferVk : public RenderbufferImpl, public angle::ObserverInterface RenderTargetVk mRenderTarget; angle::ObserverBinding mImageObserverBinding; + + vk::Renderer *mRenderer; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/SamplerVk.cpp b/src/libANGLE/renderer/vulkan/SamplerVk.cpp index 1cdc667fd41..f15b039fd70 100644 --- a/src/libANGLE/renderer/vulkan/SamplerVk.cpp +++ b/src/libANGLE/renderer/vulkan/SamplerVk.cpp @@ -11,6 +11,7 @@ #include "common/debug.h" #include "libANGLE/Context.h" +#include "libANGLE/renderer/vulkan/ShareGroupVk.h" #include "libANGLE/renderer/vulkan/vk_utils.h" namespace rx @@ -29,7 +30,6 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty) { ContextVk *contextVk = vk::GetImpl(context); - vk::Renderer *renderer = contextVk->getRenderer(); if (mSampler) { if (!dirty) @@ -40,7 +40,7 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty) } vk::SamplerDesc desc(contextVk, mState, false, nullptr, static_cast(0)); - ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, desc, &mSampler)); + ANGLE_TRY(contextVk->getShareGroup()->getSamplerCache().getSampler(contextVk, desc, &mSampler)); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp index dcc8cd5697e..de768da05d4 100644 --- a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp +++ b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp @@ -7,6 +7,10 @@ // CPU-side storage of commands to delay GPU-side allocation until commands are submitted. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/SecondaryCommandBuffer.h" #include "common/debug.h" #include "libANGLE/renderer/vulkan/vk_utils.h" @@ -40,12 +44,22 @@ const char *GetCommandString(CommandID id) return "BindGraphicsPipeline"; case CommandID::BindIndexBuffer: return "BindIndexBuffer"; + case CommandID::BindIndexBuffer2: + return "BindIndexBuffer2"; + case CommandID::BindTileMemory: + return "BindTileMemory"; case CommandID::BindTransformFeedbackBuffers: return "BindTransformFeedbackBuffers"; case CommandID::BindVertexBuffers: return "BindVertexBuffers"; case CommandID::BindVertexBuffers2: return "BindVertexBuffers2"; + case CommandID::BindVertexBuffers2NoSize: + return "BindVertexBuffers2NoSize"; + case CommandID::BindVertexBuffers2NoSizeNoStride: + return "BindVertexBuffers2NoSizeNoStride"; + case CommandID::BindVertexBuffers2NoStride: + return "BindVertexBuffers2NoStride"; case CommandID::BlitImage: return "BlitImage"; case CommandID::BufferBarrier: @@ -142,6 +156,8 @@ const char *GetCommandString(CommandID id) return "SetLogicOp"; case CommandID::SetPrimitiveRestartEnable: return "SetPrimitiveRestartEnable"; + case CommandID::SetPrimitiveTopology: + return "SetPrimitiveTopology"; case CommandID::SetRasterizerDiscardEnable: return "SetRasterizerDiscardEnable"; case CommandID::SetScissor: @@ -202,9 +218,6 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) ANGLE_TRACE_EVENT0("gpu.angle", "SecondaryCommandBuffer::executeCommands"); - // Used for ring buffer allocators only. - mCommandAllocator.terminateLastCommandBlock(); - for (const CommandHeader *command : mCommands) { for (const CommandHeader *currentCommand = command; @@ -259,7 +272,9 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) GetFirstArrayParameter(params); const uint32_t *dynamicOffsets = GetNextArrayParameter(descriptorSets, params->descriptorSetCount); - vkCmdBindDescriptorSets(cmdBuffer, params->pipelineBindPoint, params->layout, + const VkPipelineBindPoint pipelineBindPoint = + static_cast(params->pipelineBindPoint); + vkCmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, params->layout, params->firstSet, params->descriptorSetCount, descriptorSets, params->dynamicOffsetCount, dynamicOffsets); @@ -280,6 +295,23 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) params->indexType); break; } + case CommandID::BindIndexBuffer2: + { + const BindIndexBuffer2Params *params = + getParamPtr(currentCommand); + vkCmdBindIndexBuffer2KHR(cmdBuffer, params->buffer, params->offset, + params->size, params->indexType); + break; + } + case CommandID::BindTileMemory: + { + const BindTileMemoryParams *params = + getParamPtr(currentCommand); + const VkTileMemoryBindInfoQCOM tileMemoryBindInfo = { + VK_STRUCTURE_TYPE_TILE_MEMORY_BIND_INFO_QCOM, nullptr, params->tileMemory}; + vkCmdBindTileMemoryQCOM(cmdBuffer, &tileMemoryBindInfo); + break; + } case CommandID::BindTransformFeedbackBuffers: { const BindTransformFeedbackBuffersParams *params = @@ -308,6 +340,21 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) const BindVertexBuffers2Params *params = getParamPtr(currentCommand); const VkBuffer *buffers = GetFirstArrayParameter(params); + const VkDeviceSize *offsets = + GetNextArrayParameter(buffers, params->bindingCount); + const VkDeviceSize *sizes = + GetNextArrayParameter(offsets, params->bindingCount); + const VkDeviceSize *strides = + GetNextArrayParameter(sizes, params->bindingCount); + vkCmdBindVertexBuffers2EXT(cmdBuffer, 0, params->bindingCount, buffers, offsets, + sizes, strides); + break; + } + case CommandID::BindVertexBuffers2NoSize: + { + const BindVertexBuffers2NoSizeParams *params = + getParamPtr(currentCommand); + const VkBuffer *buffers = GetFirstArrayParameter(params); const VkDeviceSize *offsets = GetNextArrayParameter(buffers, params->bindingCount); const VkDeviceSize *strides = @@ -316,12 +363,35 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) nullptr, strides); break; } + case CommandID::BindVertexBuffers2NoSizeNoStride: + { + const BindVertexBuffers2NoSizeNoStrideParams *params = + getParamPtr(currentCommand); + const VkBuffer *buffers = GetFirstArrayParameter(params); + const VkDeviceSize *offsets = + GetNextArrayParameter(buffers, params->bindingCount); + vkCmdBindVertexBuffers2EXT(cmdBuffer, 0, params->bindingCount, buffers, offsets, + nullptr, nullptr); + break; + } + case CommandID::BindVertexBuffers2NoStride: + { + const BindVertexBuffers2NoStrideParams *params = + getParamPtr(currentCommand); + const VkBuffer *buffers = GetFirstArrayParameter(params); + const VkDeviceSize *offsets = + GetNextArrayParameter(buffers, params->bindingCount); + const VkDeviceSize *sizes = + GetNextArrayParameter(offsets, params->bindingCount); + vkCmdBindVertexBuffers2EXT(cmdBuffer, 0, params->bindingCount, buffers, offsets, + sizes, nullptr); + break; + } case CommandID::BlitImage: { const BlitImageParams *params = getParamPtr(currentCommand); - vkCmdBlitImage(cmdBuffer, params->srcImage, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, params->dstImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ¶ms->region, + vkCmdBlitImage(cmdBuffer, params->srcImage, params->srcImageLayout, + params->dstImage, params->dstImageLayout, 1, ¶ms->region, params->filter); break; } @@ -675,9 +745,8 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) { const ResolveImageParams *params = getParamPtr(currentCommand); - vkCmdResolveImage(cmdBuffer, params->srcImage, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, params->dstImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ¶ms->region); + vkCmdResolveImage(cmdBuffer, params->srcImage, params->srcImageLayout, + params->dstImage, params->dstImageLayout, 1, ¶ms->region); break; } case CommandID::SetBlendConstants: @@ -742,7 +811,8 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) getParamPtr(currentCommand); const VkExtent2D fragmentSize = {params->fragmentWidth, params->fragmentHeight}; const VkFragmentShadingRateCombinerOpKHR ops[2] = { - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, + static_cast( + params->vkFragmentShadingRateCombinerOp0), static_cast( params->vkFragmentShadingRateCombinerOp1)}; vkCmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, ops); @@ -775,6 +845,13 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) vkCmdSetPrimitiveRestartEnableEXT(cmdBuffer, params->primitiveRestartEnable); break; } + case CommandID::SetPrimitiveTopology: + { + const SetPrimitiveTopologyParams *params = + getParamPtr(currentCommand); + vkCmdSetPrimitiveTopologyEXT(cmdBuffer, params->primitiveTopology); + break; + } case CommandID::SetRasterizerDiscardEnable: { const SetRasterizerDiscardEnableParams *params = @@ -879,7 +956,7 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) { const WriteTimestampParams *params = getParamPtr(currentCommand); - vkCmdWriteTimestamp(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + vkCmdWriteTimestamp(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, params->queryPool, params->query); break; } @@ -887,7 +964,7 @@ void SecondaryCommandBuffer::executeCommands(PrimaryCommandBuffer *primary) { const WriteTimestampParams *params = getParamPtr(currentCommand); - vkCmdWriteTimestamp2KHR(cmdBuffer, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, + vkCmdWriteTimestamp2KHR(cmdBuffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, params->queryPool, params->query); break; } diff --git a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h index e316a1d9af1..3f52e13fe44 100644 --- a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h +++ b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h @@ -11,16 +11,15 @@ #ifndef LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_ #define LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/vulkan/vk_headers.h" +#include "libANGLE/renderer/vulkan/AllocatorHelperPool.h" #include "libANGLE/renderer/vulkan/vk_command_buffer_utils.h" #include "libANGLE/renderer/vulkan/vk_wrapper.h" -#if ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC -# include "libANGLE/renderer/vulkan/AllocatorHelperRing.h" -#else -# include "libANGLE/renderer/vulkan/AllocatorHelperPool.h" -#endif - namespace rx { class ContextVk; @@ -31,15 +30,9 @@ class ErrorContext; class RenderPassDesc; class SecondaryCommandPool; -#if ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC -using SecondaryCommandMemoryAllocator = SharedCommandMemoryAllocator; -using SecondaryCommandBlockPool = SharedCommandBlockPool; -using SecondaryCommandBlockAllocator = SharedCommandBlockAllocator; -#else using SecondaryCommandMemoryAllocator = DedicatedCommandMemoryAllocator; using SecondaryCommandBlockPool = DedicatedCommandBlockPool; using SecondaryCommandBlockAllocator = DedicatedCommandBlockAllocator; -#endif namespace priv { @@ -58,9 +51,14 @@ enum class CommandID : uint16_t BindDescriptorSets, BindGraphicsPipeline, BindIndexBuffer, + BindIndexBuffer2, + BindTileMemory, BindTransformFeedbackBuffers, BindVertexBuffers, BindVertexBuffers2, + BindVertexBuffers2NoSize, + BindVertexBuffers2NoSizeNoStride, + BindVertexBuffers2NoStride, BlitImage, BufferBarrier, BufferBarrier2, @@ -113,6 +111,7 @@ enum class CommandID : uint16_t SetLineWidth, SetLogicOp, SetPrimitiveRestartEnable, + SetPrimitiveTopology, SetRasterizerDiscardEnable, SetScissor, SetStencilCompareMask, @@ -164,7 +163,8 @@ struct BindDescriptorSetParams { CommandHeader header; - VkPipelineBindPoint pipelineBindPoint : 8; + // Actually a VkPipelineBindPoint; valid values are GRAPHICS or COMPUTE. + uint32_t pipelineBindPoint : 8; uint32_t firstSet : 8; uint32_t descriptorSetCount : 8; uint32_t dynamicOffsetCount : 8; @@ -183,6 +183,17 @@ struct BindIndexBufferParams }; VERIFY_8_BYTE_ALIGNMENT(BindIndexBufferParams) +struct BindIndexBuffer2Params +{ + CommandHeader header; + + VkIndexType indexType; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +}; +VERIFY_8_BYTE_ALIGNMENT(BindIndexBuffer2Params) + struct BindPipelineParams { CommandHeader header; @@ -202,7 +213,10 @@ struct BindTransformFeedbackBuffersParams VERIFY_8_BYTE_ALIGNMENT(BindTransformFeedbackBuffersParams) using BindVertexBuffersParams = BindTransformFeedbackBuffersParams; -using BindVertexBuffers2Params = BindVertexBuffersParams; +using BindVertexBuffers2Params = BindVertexBuffersParams; +using BindVertexBuffers2NoSizeParams = BindVertexBuffers2Params; +using BindVertexBuffers2NoSizeNoStrideParams = BindVertexBuffers2Params; +using BindVertexBuffers2NoStrideParams = BindVertexBuffers2Params; struct BlitImageParams { @@ -212,6 +226,8 @@ struct BlitImageParams VkImage srcImage; VkImage dstImage; VkImageBlit region; + VkImageLayout srcImageLayout; + VkImageLayout dstImageLayout; }; VERIFY_8_BYTE_ALIGNMENT(BlitImageParams) @@ -232,6 +248,14 @@ struct BufferBarrier2Params }; VERIFY_8_BYTE_ALIGNMENT(BufferBarrier2Params) +struct BindTileMemoryParams +{ + CommandHeader header; + uint32_t padding; + VkDeviceMemory tileMemory; +}; +VERIFY_8_BYTE_ALIGNMENT(BindTileMemoryParams) + struct ClearAttachmentsParams { CommandHeader header; @@ -586,6 +610,8 @@ struct ResolveImageParams VkImageResolve region; VkImage srcImage; VkImage dstImage; + VkImageLayout srcImageLayout; + VkImageLayout dstImageLayout; }; VERIFY_8_BYTE_ALIGNMENT(ResolveImageParams) @@ -663,7 +689,8 @@ struct SetFragmentShadingRateParams uint32_t fragmentWidth : 8; uint32_t fragmentHeight : 8; - uint32_t vkFragmentShadingRateCombinerOp1 : 16; + uint32_t vkFragmentShadingRateCombinerOp0 : 8; + uint32_t vkFragmentShadingRateCombinerOp1 : 8; }; VERIFY_8_BYTE_ALIGNMENT(SetFragmentShadingRateParams) @@ -699,6 +726,14 @@ struct SetPrimitiveRestartEnableParams }; VERIFY_8_BYTE_ALIGNMENT(SetPrimitiveRestartEnableParams) +struct SetPrimitiveTopologyParams +{ + CommandHeader header; + + VkPrimitiveTopology primitiveTopology; +}; +VERIFY_8_BYTE_ALIGNMENT(SetPrimitiveTopologyParams) + struct SetRasterizerDiscardEnableParams { CommandHeader header; @@ -873,6 +908,12 @@ class SecondaryCommandBuffer final : angle::NonCopyable void bindGraphicsPipeline(const Pipeline &pipeline); void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType); + void bindIndexBuffer2(const Buffer &buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType); + + void bindTileMemory(const DeviceMemory &tileMemory); void bindTransformFeedbackBuffers(uint32_t firstBinding, uint32_t bindingCount, @@ -892,6 +933,23 @@ class SecondaryCommandBuffer final : angle::NonCopyable const VkDeviceSize *sizes, const VkDeviceSize *strides); + void bindVertexBuffers2NoSize(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *strides); + + void bindVertexBuffers2NoSizeNoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets); + + void bindVertexBuffers2NoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *sizes); + void blitImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, @@ -1067,6 +1125,7 @@ class SecondaryCommandBuffer final : angle::NonCopyable void setLineWidth(float lineWidth); void setLogicOp(VkLogicOp logicOp); void setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable); + void setPrimitiveTopology(VkPrimitiveTopology primitiveTopology); void setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable); void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors); void setStencilCompareMask(uint32_t compareFrontMask, uint32_t compareBackMask); @@ -1127,16 +1186,6 @@ class SecondaryCommandBuffer final : angle::NonCopyable return mCommandAllocator.initialize(allocator); } - void attachAllocator(vk::SecondaryCommandMemoryAllocator *source) - { - mCommandAllocator.attachAllocator(source); - } - - void detachAllocator(vk::SecondaryCommandMemoryAllocator *destination) - { - mCommandAllocator.detachAllocator(destination); - } - angle::Result begin(ErrorContext *context, const VkCommandBufferInheritanceInfo &inheritanceInfo) { @@ -1348,6 +1397,9 @@ ANGLE_INLINE void SecondaryCommandBuffer::bindDescriptorSets(const PipelineLayou uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) { + // Only GRAPHICS and COMPUTE pipeline bind points are valid here. + ASSERT(pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS || + pipelineBindPoint == VK_PIPELINE_BIND_POINT_COMPUTE); const ArrayParamSize descSize = calculateArrayParameterSize(descriptorSetCount); const ArrayParamSize offsetSize = calculateArrayParameterSize(dynamicOffsetCount); @@ -1387,6 +1439,26 @@ ANGLE_INLINE void SecondaryCommandBuffer::bindIndexBuffer(const Buffer &buffer, paramStruct->indexType = indexType; } +ANGLE_INLINE void SecondaryCommandBuffer::bindIndexBuffer2(const Buffer &buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType) +{ + BindIndexBuffer2Params *paramStruct = + initCommand(CommandID::BindIndexBuffer2); + paramStruct->buffer = buffer.getHandle(); + paramStruct->offset = offset; + paramStruct->size = size; + paramStruct->indexType = indexType; +} + +ANGLE_INLINE void SecondaryCommandBuffer::bindTileMemory(const DeviceMemory &tileMemory) +{ + BindTileMemoryParams *paramStruct = + initCommand(CommandID::BindTileMemory); + paramStruct->tileMemory = tileMemory.getHandle(); +} + ANGLE_INLINE void SecondaryCommandBuffer::bindTransformFeedbackBuffers(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, @@ -1436,13 +1508,37 @@ ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers2(uint32_t firstBindi const VkDeviceSize *strides) { ASSERT(firstBinding == 0); - ASSERT(sizes == nullptr); uint8_t *writePtr; const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); + const ArrayParamSize sizesSize = offsetsSize; const ArrayParamSize stridesSize = offsetsSize; BindVertexBuffers2Params *paramStruct = initCommand( CommandID::BindVertexBuffers2, + buffersSize.allocateBytes + offsetsSize.allocateBytes + sizesSize.allocateBytes + + stridesSize.allocateBytes, + &writePtr); + // Copy params + paramStruct->bindingCount = bindingCount; + writePtr = storeArrayParameter(writePtr, buffers, buffersSize); + writePtr = storeArrayParameter(writePtr, offsets, offsetsSize); + writePtr = storeArrayParameter(writePtr, sizes, sizesSize); + storeArrayParameter(writePtr, strides, stridesSize); +} + +ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers2NoSize(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *strides) +{ + ASSERT(firstBinding == 0); + uint8_t *writePtr; + const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); + const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); + const ArrayParamSize stridesSize = offsetsSize; + BindVertexBuffers2NoSizeParams *paramStruct = initCommand( + CommandID::BindVertexBuffers2NoSize, buffersSize.allocateBytes + offsetsSize.allocateBytes + stridesSize.allocateBytes, &writePtr); // Copy params @@ -1452,6 +1548,47 @@ ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers2(uint32_t firstBindi storeArrayParameter(writePtr, strides, stridesSize); } +ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers2NoSizeNoStride( + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets) +{ + ASSERT(firstBinding == 0); + uint8_t *writePtr; + const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); + const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); + BindVertexBuffers2NoSizeNoStrideParams *paramStruct = + initCommand( + CommandID::BindVertexBuffers2NoSizeNoStride, + buffersSize.allocateBytes + offsetsSize.allocateBytes, &writePtr); + // Copy params + paramStruct->bindingCount = bindingCount; + writePtr = storeArrayParameter(writePtr, buffers, buffersSize); + storeArrayParameter(writePtr, offsets, offsetsSize); +} + +ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers2NoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *sizes) +{ + ASSERT(firstBinding == 0); + uint8_t *writePtr; + const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); + const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); + const ArrayParamSize sizesSize = offsetsSize; + BindVertexBuffers2NoStrideParams *paramStruct = initCommand( + CommandID::BindVertexBuffers2NoStride, + buffersSize.allocateBytes + offsetsSize.allocateBytes + sizesSize.allocateBytes, &writePtr); + // Copy params + paramStruct->bindingCount = bindingCount; + writePtr = storeArrayParameter(writePtr, buffers, buffersSize); + writePtr = storeArrayParameter(writePtr, offsets, offsetsSize); + storeArrayParameter(writePtr, sizes, sizesSize); +} + ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, @@ -1461,14 +1598,14 @@ ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage, VkFilter filter) { // Currently ANGLE uses limited params so verify those assumptions and update if they change - ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ASSERT(regionCount == 1); BlitImageParams *paramStruct = initCommand(CommandID::BlitImage); paramStruct->srcImage = srcImage.getHandle(); paramStruct->dstImage = dstImage.getHandle(); paramStruct->filter = filter; paramStruct->region = regions[0]; + paramStruct->srcImageLayout = srcImageLayout; + paramStruct->dstImageLayout = dstImageLayout; } ANGLE_INLINE void SecondaryCommandBuffer::bufferBarrier( @@ -2005,13 +2142,13 @@ ANGLE_INLINE void SecondaryCommandBuffer::resolveImage(const Image &srcImage, const VkImageResolve *regions) { // Currently ANGLE uses limited params so verify those assumptions and update if they change. - ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ASSERT(regionCount == 1); ResolveImageParams *paramStruct = initCommand(CommandID::ResolveImage); paramStruct->srcImage = srcImage.getHandle(); paramStruct->dstImage = dstImage.getHandle(); paramStruct->region = regions[0]; + paramStruct->srcImageLayout = srcImageLayout; + paramStruct->dstImageLayout = dstImageLayout; } ANGLE_INLINE void SecondaryCommandBuffer::setBlendConstants(const float blendConstants[4]) @@ -2082,18 +2219,16 @@ ANGLE_INLINE void SecondaryCommandBuffer::setFragmentShadingRate( ASSERT(fragmentSize != nullptr); // Supported parameter values - - // 1. CombinerOp for ops[0] needs to be VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR - // as there are no current usecases in ANGLE to use primitive fragment shading rates - // 2. The largest fragment size supported is 4x4 - ASSERT(ops[0] == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR); + // The largest fragment size supported is 4x4 ASSERT(fragmentSize->width <= 4); ASSERT(fragmentSize->height <= 4); SetFragmentShadingRateParams *paramStruct = initCommand(CommandID::SetFragmentShadingRate); - paramStruct->fragmentWidth = static_cast(fragmentSize->width); - paramStruct->fragmentHeight = static_cast(fragmentSize->height); - paramStruct->vkFragmentShadingRateCombinerOp1 = static_cast(ops[1]); + SetBitField(paramStruct->fragmentWidth, fragmentSize->width); + SetBitField(paramStruct->fragmentHeight, fragmentSize->height); + SetBitField(paramStruct->vkFragmentShadingRateCombinerOp0, ops[0]); + SetBitField(paramStruct->vkFragmentShadingRateCombinerOp1, ops[1]); } ANGLE_INLINE void SecondaryCommandBuffer::setFrontFace(VkFrontFace frontFace) @@ -2121,6 +2256,14 @@ ANGLE_INLINE void SecondaryCommandBuffer::setPrimitiveRestartEnable(VkBool32 pri paramStruct->primitiveRestartEnable = primitiveRestartEnable; } +ANGLE_INLINE void SecondaryCommandBuffer::setPrimitiveTopology( + VkPrimitiveTopology primitiveTopology) +{ + SetPrimitiveTopologyParams *paramStruct = + initCommand(CommandID::SetPrimitiveTopology); + paramStruct->primitiveTopology = primitiveTopology; +} + ANGLE_INLINE void SecondaryCommandBuffer::setRasterizerDiscardEnable( VkBool32 rasterizerDiscardEnable) { @@ -2275,7 +2418,7 @@ ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits const QueryPool &queryPool, uint32_t query) { - ASSERT(pipelineStage == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); + ASSERT(pipelineStage == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); WriteTimestampParams *paramStruct = initCommand(CommandID::WriteTimestamp); @@ -2287,7 +2430,7 @@ ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp2(VkPipelineStageFlagBit const QueryPool &queryPool, uint32_t query) { - ASSERT(pipelineStage == VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); + ASSERT(pipelineStage == VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT); WriteTimestampParams *paramStruct = initCommand(CommandID::WriteTimestamp2); diff --git a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp index 6af08555772..8a3ac9bb9bf 100644 --- a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp +++ b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp @@ -79,10 +79,10 @@ angle::Result SemaphoreVk::wait(gl::Context *context, BufferVk *bufferVk = vk::GetImpl(buffer); vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); - vk::CommandBufferAccess access; + vk::CommandResources resources; vk::OutsideRenderPassCommandBuffer *commandBuffer; - access.onBufferExternalAcquireRelease(&bufferHelper); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + resources.onBufferExternalAcquireRelease(&bufferHelper); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Queue ownership transfer. bufferHelper.acquireFromExternal(vk::kExternalDeviceQueueIndex, @@ -99,13 +99,13 @@ angle::Result SemaphoreVk::wait(gl::Context *context, { TextureVk *textureVk = vk::GetImpl(textureBarrier.texture); vk::ImageHelper &image = textureVk->getImage(); - vk::ImageLayout layout = - vk::GetImageLayoutFromGLImageLayout(contextVk, textureBarrier.layout); + vk::ImageAccess imageAccess = + vk::GetImageAccessFromGLImageLayout(contextVk, textureBarrier.layout); - vk::CommandBufferAccess access; + vk::CommandResources resources; vk::OutsideRenderPassCommandBuffer *commandBuffer; - access.onExternalAcquireRelease(&image); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + resources.onExternalAcquireRelease(&image); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Image should not be accessed while unowned. Emulated formats may have staged updates // to clear the image after initialization. @@ -113,7 +113,7 @@ angle::Result SemaphoreVk::wait(gl::Context *context, // Queue ownership transfer and layout transition. image.acquireFromExternal(contextVk, vk::kExternalDeviceQueueIndex, - contextVk->getDeviceQueueIndex(), layout, commandBuffer); + contextVk->getDeviceQueueIndex(), imageAccess, commandBuffer); } } @@ -136,10 +136,10 @@ angle::Result SemaphoreVk::signal(gl::Context *context, vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); ANGLE_TRY(contextVk->onBufferReleaseToExternal(bufferHelper)); - vk::CommandBufferAccess access; + vk::CommandResources resources; vk::OutsideRenderPassCommandBuffer *commandBuffer; - access.onBufferExternalAcquireRelease(&bufferHelper); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + resources.onBufferExternalAcquireRelease(&bufferHelper); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Queue ownership transfer. bufferHelper.releaseToExternal(vk::kExternalDeviceQueueIndex, commandBuffer); @@ -154,27 +154,27 @@ angle::Result SemaphoreVk::signal(gl::Context *context, { TextureVk *textureVk = vk::GetImpl(textureBarrier.texture); vk::ImageHelper &image = textureVk->getImage(); - vk::ImageLayout layout = - vk::GetImageLayoutFromGLImageLayout(contextVk, textureBarrier.layout); + vk::ImageAccess imageAccess = + vk::GetImageAccessFromGLImageLayout(contextVk, textureBarrier.layout); // Don't transition to Undefined layout. If external wants to transition the image away // from Undefined after this operation, it's perfectly fine to keep the layout as is in // ANGLE. Note that vk::ImageHelper doesn't expect transitions to Undefined. - if (layout == vk::ImageLayout::Undefined) + if (imageAccess == vk::ImageAccess::Undefined) { - layout = image.getCurrentImageLayout(); + imageAccess = image.getCurrentImageAccess(); } ANGLE_TRY(textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); ANGLE_TRY(contextVk->onImageReleaseToExternal(image)); - vk::CommandBufferAccess access; + vk::CommandResources resources; vk::OutsideRenderPassCommandBuffer *commandBuffer; - access.onExternalAcquireRelease(&image); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + resources.onExternalAcquireRelease(&image); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Queue ownership transfer and layout transition. - image.releaseToExternal(contextVk, vk::kExternalDeviceQueueIndex, layout, + image.releaseToExternal(contextVk, vk::kExternalDeviceQueueIndex, imageAccess, commandBuffer); } } @@ -186,7 +186,7 @@ angle::Result SemaphoreVk::signal(gl::Context *context, } return contextVk->flushAndSubmitCommands(&mSemaphore, nullptr, - RenderPassClosureReason::ExternalSemaphoreSignal); + QueueSubmitReason::ExternalSemaphoreSignal); } angle::Result SemaphoreVk::importOpaqueFd(ContextVk *contextVk, GLint fd) @@ -195,7 +195,7 @@ angle::Result SemaphoreVk::importOpaqueFd(ContextVk *contextVk, GLint fd) if (!mSemaphore.valid()) { - mSemaphore.init(renderer->getDevice()); + mSemaphore.init(renderer->getDevice(), VK_SEMAPHORE_TYPE_BINARY); } ASSERT(mSemaphore.valid()); @@ -218,7 +218,7 @@ angle::Result SemaphoreVk::importZirconEvent(ContextVk *contextVk, GLuint handle if (!mSemaphore.valid()) { - mSemaphore.init(renderer->getDevice()); + mSemaphore.init(renderer->getDevice(), VK_SEMAPHORE_TYPE_BINARY); } ASSERT(mSemaphore.valid()); diff --git a/src/libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.cpp b/src/libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.cpp index a75db3420a5..f297d46e856 100644 --- a/src/libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.cpp +++ b/src/libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.cpp @@ -7,6 +7,10 @@ // mapping. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.h" namespace rx @@ -72,8 +76,7 @@ void ShaderInterfaceVariableInfoMap::save(gl::BinaryOutputStream *stream) stream->writeInt(idToIndexMap.size()); if (idToIndexMap.size() > 0) { - stream->writeBytes(reinterpret_cast(idToIndexMap.data()), - idToIndexMap.size() * sizeof(*idToIndexMap.data())); + stream->writeBytes(angle::as_byte_span(idToIndexMap)); } } @@ -110,8 +113,8 @@ void ShaderInterfaceVariableInfoMap::load(gl::BinaryInputStream *stream) size_t count = stream->readInt(); if (count > 0) { - idToIndexMap.resetWithRawData(count, - stream->getBytes(count * sizeof(*idToIndexMap.data()))); + idToIndexMap.resetWithRawData(count, stream->remainingSpan().data()); + stream->skip(count * sizeof(*idToIndexMap.data())); } } diff --git a/src/libANGLE/renderer/vulkan/ShaderVk.cpp b/src/libANGLE/renderer/vulkan/ShaderVk.cpp index 4d19bd38091..b977a2b034f 100644 --- a/src/libANGLE/renderer/vulkan/ShaderVk.cpp +++ b/src/libANGLE/renderer/vulkan/ShaderVk.cpp @@ -75,17 +75,6 @@ std::shared_ptr ShaderVk::compile(const gl::Context *contex options->ignorePrecisionQualifiers = true; } - if (contextVk->getFeatures().forceFragmentShaderPrecisionHighpToMediump.enabled) - { - options->forceShaderPrecisionHighpToMediump = true; - } - - // Let compiler use specialized constant for pre-rotation. - if (!contextVk->getFeatures().preferDriverUniformOverSpecConst.enabled) - { - options->useSpecializationConstant = true; - } - if (contextVk->getFeatures().clampFragDepth.enabled) { options->clampFragDepth = true; @@ -106,6 +95,11 @@ std::shared_ptr ShaderVk::compile(const gl::Context *contex options->addVulkanXfbEmulationSupportCode = true; } + if (contextVk->getFeatures().emulateDithering.enabled) + { + options->emulateDithering = true; + } + if (contextVk->getFeatures().roundOutputAfterDithering.enabled) { options->roundOutputAfterDithering = true; @@ -141,6 +135,17 @@ std::shared_ptr ShaderVk::compile(const gl::Context *contex options->emulateR32fImageAtomicExchange = true; } + // https://issuetracker.google.com/406827038 + // Unconditionally set this option to true for the Vulkan backend + options->preserveDenorms = true; + + options->removeInactiveVariables = true; + + if (contextVk->getFeatures().convertLowpAndMediumpFloatUniformsTo16Bits.enabled) + { + options->transformFloatUniformTo16Bits = true; + } + // The Vulkan backend needs no post-processing of the translated shader. return std::shared_ptr(new ShaderTranslateTask); } diff --git a/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp b/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp index 1363516d505..1ae69af1337 100644 --- a/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp +++ b/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp @@ -158,33 +158,34 @@ angle::Result ShareGroupVk::updateContextsPriority(ContextVk *contextVk, void ShareGroupVk::onDestroy(const egl::Display *display) { - DisplayVk *displayVk = vk::GetImpl(display); - mRefCountedEventsGarbageRecycler.destroy(mRenderer); + // If any context uses display texture share group, it is expected that a + // BufferBlock may still in used by textures that outlive ShareGroup. The + // non-empty BufferBlock will be put into Renderer's orphan list instead. + // Same with samplers in the sampler cache. + const bool hasDisplayTextureShareGroup = mState.hasAnyContextWithDisplayTextureShareGroup(); for (std::unique_ptr &pool : mDefaultBufferPools) { if (pool) { - // If any context uses display texture share group, it is expected that a - // BufferBlock may still in used by textures that outlived ShareGroup. The - // non-empty BufferBlock will be put into Renderer's orphan list instead. - pool->destroy(mRenderer, mState.hasAnyContextWithDisplayTextureShareGroup()); + pool->destroy(mRenderer, hasDisplayTextureShareGroup); } } mPipelineLayoutCache.destroy(mRenderer); mDescriptorSetLayoutCache.destroy(mRenderer); + mSamplerCache.destroy(mRenderer, hasDisplayTextureShareGroup); + mYuvConversionCache.destroy(mRenderer, hasDisplayTextureShareGroup); + mMetaDescriptorPools[DescriptorSetIndex::UniformsAndXfb].destroy(mRenderer); mMetaDescriptorPools[DescriptorSetIndex::Texture].destroy(mRenderer); + mMetaDescriptorPools[DescriptorSetIndex::UniformBuffers].destroy(mRenderer); mMetaDescriptorPools[DescriptorSetIndex::ShaderResource].destroy(mRenderer); mFramebufferCache.destroy(mRenderer); resetPrevTexture(); - - mVertexInputGraphicsPipelineCache.destroy(displayVk); - mFragmentOutputGraphicsPipelineCache.destroy(displayVk); } angle::Result ShareGroupVk::onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture) @@ -287,7 +288,7 @@ void TextureUpload::onTextureRelease(TextureVk *textureVk) } } -void ShareGroupVk::onFramebufferBoundary() +void ShareGroupVk::onFrameBoundary() { if (isDueForBufferPoolPrune()) { @@ -314,8 +315,7 @@ vk::BufferPool *ShareGroupVk::getDefaultBufferPool(VkDeviceSize size, std::unique_ptr pool = std::make_unique(); vma::VirtualBlockCreateFlags vmaFlags = vma::VirtualBlockCreateFlagBits::GENERAL; - pool->initWithFlags(mRenderer, vmaFlags, usageFlags, 0, memoryTypeIndex, - memoryPropertyFlags); + pool->initWithFlags(mRenderer, vmaFlags, usageFlags, memoryTypeIndex, memoryPropertyFlags); mDefaultBufferPools[memoryTypeIndex] = std::move(pool); } diff --git a/src/libANGLE/renderer/vulkan/ShareGroupVk.h b/src/libANGLE/renderer/vulkan/ShareGroupVk.h index db189ebb6d6..76926284c62 100644 --- a/src/libANGLE/renderer/vulkan/ShareGroupVk.h +++ b/src/libANGLE/renderer/vulkan/ShareGroupVk.h @@ -43,6 +43,8 @@ class ShareGroupVk : public ShareGroupImpl void onContextAdd() override; FramebufferCache &getFramebufferCache() { return mFramebufferCache; } + SamplerCache &getSamplerCache() { return mSamplerCache; } + SamplerYcbcrConversionCache &getYuvConversionCache() { return mYuvConversionCache; } bool hasAnyContextWithRobustness() const { return mState.hasAnyContextWithRobustness(); } @@ -81,15 +83,6 @@ class ShareGroupVk : public ShareGroupImpl void onTextureRelease(TextureVk *textureVk); - VertexInputGraphicsPipelineCache *getVertexInputGraphicsPipelineCache() - { - return &mVertexInputGraphicsPipelineCache; - } - FragmentOutputGraphicsPipelineCache *getFragmentOutputGraphicsPipelineCache() - { - return &mFragmentOutputGraphicsPipelineCache; - } - angle::Result scheduleMonolithicPipelineCreationTask( ContextVk *contextVk, vk::WaitableMonolithicPipelineCreationTask *taskOut); @@ -110,7 +103,7 @@ class ShareGroupVk : public ShareGroupImpl } } - void onFramebufferBoundary(); + void onFrameBoundary(); uint32_t getCurrentFrameCount() const { return mCurrentFrameCount; } private: @@ -126,6 +119,10 @@ class ShareGroupVk : public ShareGroupImpl // VkFramebuffer caches FramebufferCache mFramebufferCache; + // VkSampler and VkSamplerYcbcrConversion caches + SamplerCache mSamplerCache; + SamplerYcbcrConversionCache mYuvConversionCache; + void resetPrevTexture() { mTextureUpload.resetPrevTexture(); } // ANGLE uses a PipelineLayout cache to store compatible pipeline layouts. @@ -150,13 +147,6 @@ class ShareGroupVk : public ShareGroupImpl // The system time when last pruneEmptyBuffer gets called. double mLastPruneTime; - // Used when VK_EXT_graphics_pipeline_library is available, the vertex input and fragment output - // partial pipelines are created in the following caches. These caches are in the share group - // because linked pipelines using these pipeline libraries are referenced from - // ProgramExecutableVk, and as such must stay alive as long as the program may be alive. - VertexInputGraphicsPipelineCache mVertexInputGraphicsPipelineCache; - FragmentOutputGraphicsPipelineCache mFragmentOutputGraphicsPipelineCache; - // The system time when the last monolithic pipeline creation job was launched. This is // rate-limited to avoid hogging all cores and interfering with the application threads. A // single pipeline creation job is currently supported. diff --git a/src/libANGLE/renderer/vulkan/Suballocation.cpp b/src/libANGLE/renderer/vulkan/Suballocation.cpp index 6d0b85bdb75..637af47e76c 100644 --- a/src/libANGLE/renderer/vulkan/Suballocation.cpp +++ b/src/libANGLE/renderer/vulkan/Suballocation.cpp @@ -63,14 +63,12 @@ BufferBlock::~BufferBlock() ASSERT(!mVirtualBlock.valid()); ASSERT(!mBuffer.valid()); ASSERT(!mDeviceMemory.valid()); - ASSERT(mDescriptorSetCacheManager.empty()); } void BufferBlock::destroy(Renderer *renderer) { VkDevice device = renderer->getDevice(); - mDescriptorSetCacheManager.destroyKeys(renderer); if (mMappedMemory) { unmap(device); diff --git a/src/libANGLE/renderer/vulkan/Suballocation.h b/src/libANGLE/renderer/vulkan/Suballocation.h index 47be5c92060..212ab9e4ceb 100644 --- a/src/libANGLE/renderer/vulkan/Suballocation.h +++ b/src/libANGLE/renderer/vulkan/Suballocation.h @@ -10,6 +10,10 @@ #ifndef LIBANGLE_RENDERER_VULKAN_SUBALLOCATION_H_ #define LIBANGLE_RENDERER_VULKAN_SUBALLOCATION_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/SimpleMutex.h" #include "common/debug.h" #include "libANGLE/angletypes.h" @@ -84,18 +88,6 @@ class BufferBlock final : angle::NonCopyable int32_t getAndIncrementEmptyCounter(); void calculateStats(vma::StatInfo *pStatInfo) const; - void onNewDescriptorSet(const SharedDescriptorSetCacheKey &sharedCacheKey) - { - mDescriptorSetCacheManager.addKey(sharedCacheKey); - } - void releaseAllCachedDescriptorSetCacheKeys(Renderer *renderer) - { - if (!mDescriptorSetCacheManager.empty()) - { - mDescriptorSetCacheManager.releaseKeys(renderer); - } - } - private: mutable angle::SimpleMutex mVirtualBlockMutex; VirtualBlock mVirtualBlock; @@ -119,8 +111,6 @@ class BufferBlock final : angle::NonCopyable // buffer block is found to be empty when pruneEmptyBuffer is called. This gets reset whenever // it becomes non-empty. int32_t mCountRemainsEmpty; - // Manages the descriptorSet cache that created with this BufferBlock. - DescriptorSetCacheManager mDescriptorSetCacheManager; }; using BufferBlockPointer = std::unique_ptr; using BufferBlockPointerVector = std::vector; diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp index ad27e97ea46..5d4f7a93a70 100644 --- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp +++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for SurfaceVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/SurfaceVk.h" #include "common/debug.h" @@ -171,6 +175,22 @@ bool DepthStencilNeedsInputAttachmentUsage(const angle::FeaturesVk &features) return features.supportsShaderFramebufferFetchDepthStencil.enabled; } +bool IsKnownAnglePresentMode(VkPresentModeKHR mode) +{ + switch (vk::ConvertVkPresentModeToPresentMode(mode)) + { + case vk::PresentMode::ImmediateKHR: + case vk::PresentMode::MailboxKHR: + case vk::PresentMode::FifoKHR: + case vk::PresentMode::FifoRelaxedKHR: + case vk::PresentMode::SharedDemandRefreshKHR: + case vk::PresentMode::SharedContinuousRefreshKHR: + return true; + default: + return false; + } +} + angle::Result InitImageHelper(DisplayVk *displayVk, EGLint width, EGLint height, @@ -211,9 +231,9 @@ angle::Result InitImageHelper(DisplayVk *displayVk, hasProtectedContent ? VK_IMAGE_CREATE_PROTECTED_BIT : vk::kVkImageCreateFlagsNone; ANGLE_TRY(imageHelper->initExternal( displayVk, gl::TextureType::_2D, extents, vkFormat.getIntendedFormatID(), - renderableFormatId, samples, usage, imageCreateFlags, vk::ImageLayout::Undefined, nullptr, + renderableFormatId, samples, usage, imageCreateFlags, vk::ImageAccess::Undefined, nullptr, gl::LevelIndex(0), 1, 1, isRobustResourceInitEnabled, hasProtectedContent, - vk::YcbcrConversionDesc{}, nullptr)); + vk::TileMemory::Prohibited, vk::YcbcrConversionDesc{}, nullptr)); return angle::Result::Continue; } @@ -398,7 +418,7 @@ angle::Result NewSemaphore(vk::ErrorContext *context, { if (semaphoreRecycler->empty()) { - ANGLE_VK_TRY(context, semaphoreOut->init(context->getDevice())); + ANGLE_VK_TRY(context, semaphoreOut->init(context->getDevice(), VK_SEMAPHORE_TYPE_BINARY)); } else { @@ -478,6 +498,23 @@ bool HasAnyOldSwapchains(const std::deque &presentH return false; } +void DestroyPresentHistory(vk::Renderer *renderer, + std::deque *presentHistory, + vk::Recycler *fenceRecycler, + vk::Recycler *semaphoreRecycler) +{ + VkDevice device = renderer->getDevice(); + for (impl::ImagePresentOperation &presentOperation : *presentHistory) + { + if (presentOperation.fence.valid()) + { + (void)presentOperation.fence.wait(device, renderer->getMaxFenceWaitTimeNs()); + } + presentOperation.destroy(device, fenceRecycler, semaphoreRecycler); + } + presentHistory->clear(); +} + bool IsCompatiblePresentMode(vk::PresentMode mode, VkPresentModeKHR *compatibleModes, size_t compatibleModesCount) @@ -487,12 +524,30 @@ bool IsCompatiblePresentMode(vk::PresentMode mode, return std::find(compatibleModes, compatibleModesEnd, vkMode) != compatibleModesEnd; } +impl::SurfaceSizeState GetSizeState(const std::atomic &sizeState) +{ + return sizeState.load(std::memory_order_relaxed); +} + +void SetSizeState(std::atomic *sizeState, impl::SurfaceSizeState value) +{ + sizeState->store(value, std::memory_order_relaxed); +} + +// VK_SUBOPTIMAL_KHR is ok since we still have an Image that can be presented successfully +bool IsImageAcquireFailed(VkResult result) +{ + return ANGLE_UNLIKELY(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR); +} + // This function MUST only be called from a thread where Surface is current. void AcquireNextImageUnlocked(VkDevice device, VkSwapchainKHR swapchain, - impl::ImageAcquireOperation *acquire) + impl::ImageAcquireOperation *acquire, + std::atomic *sizeState) { - ASSERT(acquire->state == impl::ImageAcquireState::NeedToAcquire); + ASSERT(acquire->state == impl::ImageAcquireState::Unacquired); + ASSERT(*sizeState == impl::SurfaceSizeState::Unresolved); ASSERT(swapchain != VK_NULL_HANDLE); impl::UnlockedAcquireData *data = &acquire->unlockedAcquireData; @@ -507,6 +562,11 @@ void AcquireNextImageUnlocked(VkDevice device, result->result = vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, result->acquireSemaphore, VK_NULL_HANDLE, &result->imageIndex); + if (!IsImageAcquireFailed(result->result)) + { + SetSizeState(sizeState, impl::SurfaceSizeState::Resolved); + } + // Result processing will be done later in the same thread. acquire->state = impl::ImageAcquireState::NeedToProcessResult; } @@ -568,14 +628,9 @@ void SurfaceVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMe onStateChange(angle::SubjectMessage::SubjectChanged); } -EGLint SurfaceVk::getWidth() const +gl::Extents SurfaceVk::getSize() const { - return mWidth; -} - -EGLint SurfaceVk::getHeight() const -{ - return mHeight; + return gl::Extents(mWidth, mHeight, 1); } OffscreenSurfaceVk::AttachmentImage::AttachmentImage(SurfaceVk *surfaceVk) @@ -604,7 +659,7 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT; } ANGLE_TRY(image.initMemoryAndNonZeroFillIfNeeded( - displayVk, hasProtectedContent, renderer->getMemoryProperties(), flags, + displayVk, hasProtectedContent, flags, vk::MemoryAllocationType::OffscreenSurfaceAttachmentImage)); imageViews.init(renderer); @@ -654,6 +709,20 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk) bool robustInit = mState.isRobustResourceInitEnabled(); + EGLBoolean isLargestPbuffer = + static_cast(mState.attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE)); + if (isLargestPbuffer) + { + mWidth = std::min(mWidth, config->maxPBufferWidth); + + mHeight = std::min(mHeight, config->maxPBufferHeight); + + if (mWidth * mHeight > config->maxPBufferPixels) + { + mHeight = config->maxPBufferPixels / mWidth; + } + } + if (config->renderTargetFormat != GL_NONE) { ANGLE_TRY(mColorAttachment.initialize(displayVk, mWidth, mHeight, @@ -700,7 +769,7 @@ egl::Error OffscreenSurfaceVk::unMakeCurrent(const gl::Context *context) return angle::ToEGL(result, EGL_BAD_CURRENT_SURFACE); } -egl::Error OffscreenSurfaceVk::swap(const gl::Context *context) +egl::Error OffscreenSurfaceVk::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return egl::NoError(); } @@ -803,8 +872,8 @@ egl::Error OffscreenSurfaceVk::lockSurface(const egl::Display *display, ASSERT(image->valid()); angle::Result result = - LockSurfaceImpl(vk::GetImpl(display), image, mLockBufferHelper, getWidth(), getHeight(), - usageHint, preservePixels, bufferPtrOut, bufferPitchOut); + LockSurfaceImpl(vk::GetImpl(display), image, mLockBufferHelper, mWidth, mHeight, usageHint, + preservePixels, bufferPtrOut, bufferPitchOut); return angle::ToEGL(result, EGL_BAD_ACCESS); } @@ -814,8 +883,8 @@ egl::Error OffscreenSurfaceVk::unlockSurface(const egl::Display *display, bool p ASSERT(image->valid()); ASSERT(mLockBufferHelper.valid()); - return angle::ToEGL(UnlockSurfaceImpl(vk::GetImpl(display), image, mLockBufferHelper, - getWidth(), getHeight(), preservePixels), + return angle::ToEGL(UnlockSurfaceImpl(vk::GetImpl(display), image, mLockBufferHelper, mWidth, + mHeight, preservePixels), EGL_BAD_ACCESS); } @@ -963,6 +1032,8 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ mNativeWindowType(window), mSurface(VK_NULL_HANDLE), mSupportsProtectedSwapchain(false), + mIsSurfaceSizedBySwapchain(false), + mSizeState(SurfaceSizeState::InvalidSwapchain), mSwapchain(VK_NULL_HANDLE), mLastSwapchain(VK_NULL_HANDLE), mSwapchainPresentMode(vk::PresentMode::FifoKHR), @@ -976,7 +1047,9 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ mDepthStencilImageBinding(this, kAnySurfaceImageSubjectIndex), mColorImageMSBinding(this, kAnySurfaceImageSubjectIndex), mFrameCount(1), - mBufferAgeQueryFrameNumber(0) + mPresentID(0), + mIsBufferAgeQueried(false), + mRenderer(nullptr) { // Initialize the color render target with the multisampled targets. If not multisampled, the // render target will be updated to refer to a swapchain image on every acquire. @@ -1008,7 +1081,7 @@ void WindowSurfaceVk::destroy(const egl::Display *display) // flush the pipe. (void)finish(displayVk); - if (mAcquireOperation.state == impl::ImageAcquireState::Ready) + if (mAcquireOperation.state == ImageAcquireState::Ready) { // swapchain image doesn't own ANI semaphore. Release ANI semaphore from image so that it // can destroy cleanly without hitting assertion.. @@ -1023,15 +1096,8 @@ void WindowSurfaceVk::destroy(const egl::Display *display) mLockBufferHelper.destroy(renderer); } - for (impl::ImagePresentOperation &presentOperation : mPresentHistory) - { - if (presentOperation.fence.valid()) - { - (void)presentOperation.fence.wait(device, renderer->getMaxFenceWaitTimeNs()); - } - presentOperation.destroy(device, &mPresentFenceRecycler, &mPresentSemaphoreRecycler); - } - mPresentHistory.clear(); + DestroyPresentHistory(renderer, &mPresentHistory, &mPresentFenceRecycler, + &mPresentSemaphoreRecycler); destroySwapChainImages(displayVk); @@ -1102,15 +1168,31 @@ egl::Error WindowSurfaceVk::initialize(const egl::Display *display) return angle::ToEGL(result, EGL_BAD_SURFACE); } +egl::Error WindowSurfaceVk::makeCurrent(const gl::Context *context) +{ + ContextVk *contextVk = vk::GetImpl(context); + // mDepthStencilImage is initialized at surface create time where there is no context + // information. So tileMemoryImages will not propagate to the rendering context. In order for + // tests to work, we need to propagate it to rendering context. + if (mDepthStencilImage.useTileMemory()) + { + contextVk->getPerfCounters().tileMemoryImages++; + } + return egl::NoError(); +} + egl::Error WindowSurfaceVk::unMakeCurrent(const gl::Context *context) { ContextVk *contextVk = vk::GetImpl(context); angle::Result result = contextVk->onSurfaceUnMakeCurrent(this); - // Even though all swap chain images are tracked individually, the semaphores are not - // tracked by ResourceUse. This propagates context's queue serial to surface when it - // detaches from context so that surface will always wait until context is finished. - mUse.merge(contextVk->getSubmittedResourceUse()); + if (mDepthStencilImage.useTileMemory()) + { + contextVk->getPerfCounters().tileMemoryImages--; + // ContextVk::onSurfaceUnMakeCurrent must have submitted everything which means all tile + // images mus have been finalized + ASSERT(contextVk->isImageWithTileMemoryFinalized(&mDepthStencilImage)); + } return angle::ToEGL(result, EGL_BAD_CURRENT_SURFACE); } @@ -1136,6 +1218,14 @@ angle::FormatID WindowSurfaceVk::getActualFormatID(vk::Renderer *renderer) { actualFormatID = angle::FormatID::R8G8B8A8_UNORM; } + + // For the devices that prefer using BGR565 instead of RGB565, the swapchain images should + // remain as RGB565, since creating BGR565 surfaces is currently not supported. + if (renderer->getFeatures().preferBGR565ToRGB565.enabled && + intendedFormatID == angle::FormatID::R5G6B5_UNORM) + { + actualFormatID = angle::FormatID::R5G6B5_UNORM; + } return actualFormatID; } @@ -1165,27 +1255,28 @@ bool WindowSurfaceVk::updateColorSpace(DisplayVk *displayVk) angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMatchesOut) { - vk::Renderer *renderer = displayVk->getRenderer(); + mRenderer = displayVk->getRenderer(); - mColorImageMSViews.init(renderer); - mDepthStencilImageViews.init(renderer); + mColorImageMSViews.init(mRenderer); + mDepthStencilImageViews.init(mRenderer); - renderer->reloadVolkIfNeeded(); + mRenderer->reloadVolkIfNeeded(); - gl::Extents windowSize; - ANGLE_TRY(createSurfaceVk(displayVk, &windowSize)); + ANGLE_TRY(createSurfaceVk(displayVk)); // Check if the selected queue created supports present to this surface. bool presentSupported = false; - ANGLE_TRY(renderer->checkQueueForSurfacePresent(displayVk, mSurface, &presentSupported)); + ANGLE_TRY(mRenderer->checkQueueForSurfacePresent(displayVk, mSurface, &presentSupported)); if (!presentSupported) { return angle::Result::Continue; } - const VkPhysicalDevice &physicalDevice = renderer->getPhysicalDevice(); + const VkPhysicalDevice &physicalDevice = mRenderer->getPhysicalDevice(); - if (renderer->getFeatures().supportsSurfaceCapabilities2Extension.enabled) + VkSurfaceCapabilitiesKHR surfaceCaps; + + if (mRenderer->getFeatures().supportsSurfaceCapabilities2Extension.enabled) { VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2 = {}; surfaceInfo2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; @@ -1195,7 +1286,7 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat surfaceCaps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR; VkSharedPresentSurfaceCapabilitiesKHR sharedPresentSurfaceCaps = {}; - if (renderer->getFeatures().supportsSharedPresentableImageExtension.enabled) + if (mRenderer->getFeatures().supportsSharedPresentableImageExtension.enabled) { sharedPresentSurfaceCaps.sType = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR; @@ -1206,7 +1297,7 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat } VkSurfaceProtectedCapabilitiesKHR surfaceProtectedCaps = {}; - if (renderer->getFeatures().supportsSurfaceProtectedCapabilitiesExtension.enabled) + if (mRenderer->getFeatures().supportsSurfaceProtectedCapabilitiesExtension.enabled) { surfaceProtectedCaps.sType = VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR; @@ -1216,13 +1307,13 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfaceCapabilities2KHR( physicalDevice, &surfaceInfo2, &surfaceCaps2)); - mSurfaceCaps = surfaceCaps2.surfaceCapabilities; + surfaceCaps = surfaceCaps2.surfaceCapabilities; mSupportsProtectedSwapchain = surfaceProtectedCaps.supportsProtected; } else { ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, - &mSurfaceCaps)); + &surfaceCaps)); } if (IsAndroid()) @@ -1233,28 +1324,19 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat ANGLE_VK_CHECK(displayVk, (mState.hasProtectedContent() ? mSupportsProtectedSwapchain : true), VK_ERROR_FEATURE_NOT_PRESENT); - // Adjust width and height to the swapchain if necessary. - uint32_t width = mSurfaceCaps.currentExtent.width; - uint32_t height = mSurfaceCaps.currentExtent.height; - ANGLE_VK_CHECK(displayVk, - (mSurfaceCaps.supportedUsageFlags & kSurfaceVkColorImageUsageFlags) == + (surfaceCaps.supportedUsageFlags & kSurfaceVkColorImageUsageFlags) == kSurfaceVkColorImageUsageFlags, VK_ERROR_INITIALIZATION_FAILED); - EGLAttrib attribWidth = mState.attributes.get(EGL_WIDTH, 0); - EGLAttrib attribHeight = mState.attributes.get(EGL_HEIGHT, 0); - - if (mSurfaceCaps.currentExtent.width == kSurfaceSizedBySwapchain) + if (surfaceCaps.currentExtent.width == kSurfaceSizedBySwapchain) { - ASSERT(mSurfaceCaps.currentExtent.height == kSurfaceSizedBySwapchain); + ASSERT(surfaceCaps.currentExtent.height == kSurfaceSizedBySwapchain); + ASSERT(!IsAndroid()); - width = (attribWidth != 0) ? static_cast(attribWidth) : windowSize.width; - height = (attribHeight != 0) ? static_cast(attribHeight) : windowSize.height; + mIsSurfaceSizedBySwapchain = true; } - gl::Extents extents(static_cast(width), static_cast(height), 1); - // Introduction to Android rotation and pre-rotation: // // Android devices have one native orientation, but a window may be displayed in a different @@ -1284,62 +1366,31 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat // and scissor calculations are done with non-rotated values; and then the final values are // rotated. // - // ANGLE learns about the window's rotation from mSurfaceCaps.currentTransform. If + // ANGLE learns about the window's rotation from surfaceCaps.currentTransform. If // currentTransform is non-IDENTITY, ANGLE must "pre-rotate" various aspects of its work // (e.g. rotate vertices in the vertex shaders, change scissor, viewport, and render-pass - // renderArea). The swapchain's transform is given the value of mSurfaceCaps.currentTransform. + // renderArea). The swapchain's transform is given the value of surfaceCaps.currentTransform. // That prevents SurfaceFlinger from doing a rotation blit for every frame (which is costly in // terms of performance and power). // // When a window is rotated 90 or 270 degrees, the aspect ratio changes. The width and height // are swapped. The x/y and width/height of various values in ANGLE must also be swapped // before communicating the values to Vulkan. - if (renderer->getFeatures().enablePreRotateSurfaces.enabled) - { - // Use the surface's transform. For many platforms, this will always be identity (ANGLE - // does not need to do any pre-rotation). However, when mSurfaceCaps.currentTransform is - // not identity, the device has been rotated away from its natural orientation. In such a - // case, ANGLE must rotate all rendering in order to avoid the compositor - // (e.g. SurfaceFlinger on Android) performing an additional rotation blit. In addition, - // ANGLE must create the swapchain with VkSwapchainCreateInfoKHR::preTransform set to the - // value of mSurfaceCaps.currentTransform. - mPreTransform = mSurfaceCaps.currentTransform; - } - else - { - // Default to identity transform. - mPreTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - - if ((mSurfaceCaps.supportedTransforms & mPreTransform) == 0) - { - mPreTransform = mSurfaceCaps.currentTransform; - } - } // Set emulated pre-transform if any emulated prerotation features are set. - if (renderer->getFeatures().emulatedPrerotation90.enabled) + if (mRenderer->getFeatures().emulatedPrerotation90.enabled) { mEmulatedPreTransform = VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR; } - else if (renderer->getFeatures().emulatedPrerotation180.enabled) + else if (mRenderer->getFeatures().emulatedPrerotation180.enabled) { mEmulatedPreTransform = VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR; } - else if (renderer->getFeatures().emulatedPrerotation270.enabled) + else if (mRenderer->getFeatures().emulatedPrerotation270.enabled) { mEmulatedPreTransform = VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR; } - // If prerotation is emulated, the window is physically rotated. With real prerotation, the - // surface reports the rotated sizes. With emulated prerotation however, the surface reports - // the actual window sizes. Adjust the window extents to match what real prerotation would have - // reported. - if (Is90DegreeRotation(mEmulatedPreTransform)) - { - ASSERT(mPreTransform == VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR); - std::swap(extents.width, extents.height); - } - ANGLE_TRY(GetPresentModes(displayVk, physicalDevice, mSurface, &mPresentModes)); // Select appropriate present mode based on vsync parameter. Default to 1 (FIFO), though it @@ -1360,23 +1411,30 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat mCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; } - if ((mSurfaceCaps.supportedCompositeAlpha & mCompositeAlpha) == 0) + if ((surfaceCaps.supportedCompositeAlpha & mCompositeAlpha) == 0) { mCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; } - ANGLE_VK_CHECK(displayVk, (mSurfaceCaps.supportedCompositeAlpha & mCompositeAlpha) != 0, + ANGLE_VK_CHECK(displayVk, (surfaceCaps.supportedCompositeAlpha & mCompositeAlpha) != 0, VK_ERROR_INITIALIZATION_FAILED); // Single buffer, if supported - if ((mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER) == EGL_SINGLE_BUFFER) && - supportsPresentMode(vk::PresentMode::SharedDemandRefreshKHR)) + if (mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER) == EGL_SINGLE_BUFFER) { - setDesiredSwapchainPresentMode(vk::PresentMode::SharedDemandRefreshKHR); + if (supportsPresentMode(vk::PresentMode::SharedDemandRefreshKHR)) + { + mSwapchainPresentMode = vk::PresentMode::SharedDemandRefreshKHR; + setDesiredSwapchainPresentMode(vk::PresentMode::SharedDemandRefreshKHR); + } + else + { + WARN() << "Shared presentation mode requested, but not supported"; + } } mCompressionFlags = VK_IMAGE_COMPRESSION_DISABLED_EXT; mFixedRateFlags = 0; - VkFormat imageFormat = vk::GetVkFormatFromFormatID(renderer, getActualFormatID(renderer)); + VkFormat imageFormat = vk::GetVkFormatFromFormatID(mRenderer, getActualFormatID(mRenderer)); EGLenum surfaceCompressionRate = static_cast(mState.attributes.get( EGL_SURFACE_COMPRESSION_EXT, EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)); bool useFixedRateCompression = @@ -1385,8 +1443,8 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat (surfaceCompressionRate == EGL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT); if (useFixedRateCompression) { - ASSERT(renderer->getFeatures().supportsImageCompressionControl.enabled); - ASSERT(renderer->getFeatures().supportsImageCompressionControlSwapchain.enabled); + ASSERT(mRenderer->getFeatures().supportsImageCompressionControl.enabled); + ASSERT(mRenderer->getFeatures().supportsImageCompressionControlSwapchain.enabled); if (imageFormat == VK_FORMAT_R8G8B8A8_UNORM || imageFormat == VK_FORMAT_R8_UNORM || imageFormat == VK_FORMAT_R5G6B5_UNORM_PACK16 || imageFormat == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16) @@ -1394,21 +1452,22 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat mCompressionFlags = fixedRateDefault ? VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT : VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT; mFixedRateFlags = gl_vk::ConvertEGLFixedRateToVkFixedRate(surfaceCompressionRate, - getActualFormatID(renderer)); + getActualFormatID(mRenderer)); } } - ANGLE_TRY(createSwapChain(displayVk, extents)); + ANGLE_TRY(prepareSwapchainForAcquireNextImage(displayVk)); + ASSERT(mSwapchain != VK_NULL_HANDLE); // Create the semaphores that will be used for vkAcquireNextImageKHR. for (vk::Semaphore &semaphore : mAcquireOperation.unlockedAcquireData.acquireImageSemaphores) { - ANGLE_VK_TRY(displayVk, semaphore.init(displayVk->getDevice())); + ANGLE_VK_TRY(displayVk, semaphore.init(displayVk->getDevice(), VK_SEMAPHORE_TYPE_BINARY)); } // Keep the image acquire deferred. |mColorRenderTarget| will not be accessed until update in - // the |postProcessUnlockedAcquire| call. - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire); + // the |acquireNextSwapchainImage| call. + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired); *anyMatchesOut = true; return angle::Result::Continue; @@ -1420,17 +1479,18 @@ angle::Result WindowSurfaceVk::getAttachmentRenderTarget(const gl::Context *cont GLsizei samples, FramebufferAttachmentRenderTarget **rtOut) { - if (mAcquireOperation.state != impl::ImageAcquireState::Ready) + if (mAcquireOperation.state != ImageAcquireState::Ready) { // Acquire the next image (previously deferred) before it is drawn to or read from. ContextVk *contextVk = vk::GetImpl(context); ANGLE_VK_TRACE_EVENT_AND_MARKER(contextVk, "First Swap Image Use"); - ANGLE_TRY(doDeferredAcquireNextImage(context, false)); + ANGLE_TRY(doDeferredAcquireNextImage(contextVk)); } return SurfaceVk::getAttachmentRenderTarget(context, binding, imageIndex, samples, rtOut); } -angle::Result WindowSurfaceVk::collectOldSwapchain(ContextVk *contextVk, VkSwapchainKHR swapchain) +angle::Result WindowSurfaceVk::collectOldSwapchain(vk::ErrorContext *context, + VkSwapchainKHR swapchain) { ASSERT(swapchain != VK_NULL_HANDLE); ASSERT(swapchain != mLastSwapchain); @@ -1447,7 +1507,7 @@ angle::Result WindowSurfaceVk::collectOldSwapchain(ContextVk *contextVk, VkSwapc if (mPresentHistory.empty()) { // Destroy the current (never-used) swapchain. - vkDestroySwapchainKHR(contextVk->getDevice(), swapchain, nullptr); + vkDestroySwapchainKHR(context->getDevice(), swapchain, nullptr); return angle::Result::Continue; } @@ -1459,7 +1519,7 @@ angle::Result WindowSurfaceVk::collectOldSwapchain(ContextVk *contextVk, VkSwapc // Schedule the swapchain for destruction. cleanupData.swapchain = swapchain; - for (impl::ImagePresentOperation &presentOperation : mPresentHistory) + for (ImagePresentOperation &presentOperation : mPresentHistory) { // fence is only used when VK_EXT_swapchain_maintenance1 is supported. if (presentOperation.fence.valid()) @@ -1483,9 +1543,9 @@ angle::Result WindowSurfaceVk::collectOldSwapchain(ContextVk *contextVk, VkSwapc mOldSwapchains.emplace_back(std::move(cleanupData)); // Try to cleanup old swapchains first, before checking the kMaxOldSwapchains limit. - if (contextVk->getFeatures().supportsSwapchainMaintenance1.enabled) + if (context->getFeatures().supportsSwapchainMaintenance1.enabled) { - ANGLE_TRY(cleanUpOldSwapchains(contextVk)); + ANGLE_TRY(cleanUpOldSwapchains(context)); } // If too many old swapchains have accumulated, wait idle and destroy them. This is to prevent @@ -1496,13 +1556,12 @@ angle::Result WindowSurfaceVk::collectOldSwapchain(ContextVk *contextVk, VkSwapc static constexpr size_t kMaxOldSwapchains = 5; if (mOldSwapchains.size() > kMaxOldSwapchains) { - mUse.merge(contextVk->getSubmittedResourceUse()); - ANGLE_TRY(finish(contextVk)); + ANGLE_TRY(finish(context)); for (SwapchainCleanupData &oldSwapchain : mOldSwapchains) { - oldSwapchain.waitFences(contextVk->getDevice(), - contextVk->getRenderer()->getMaxFenceWaitTimeNs()); - oldSwapchain.destroy(contextVk->getDevice(), &mPresentFenceRecycler, + oldSwapchain.waitFences(context->getDevice(), + context->getRenderer()->getMaxFenceWaitTimeNs()); + oldSwapchain.destroy(context->getDevice(), &mPresentFenceRecycler, &mPresentSemaphoreRecycler); } mOldSwapchains.clear(); @@ -1511,92 +1570,107 @@ angle::Result WindowSurfaceVk::collectOldSwapchain(ContextVk *contextVk, VkSwapc return angle::Result::Continue; } -angle::Result WindowSurfaceVk::recreateSwapchain(ContextVk *contextVk, const gl::Extents &extents) +void WindowSurfaceVk::invalidateSwapchain(vk::Renderer *renderer) { - ASSERT(mAcquireOperation.state != impl::ImageAcquireState::Ready); + ASSERT(mSizeState != SurfaceSizeState::InvalidSwapchain); + ASSERT(mSwapchain != VK_NULL_HANDLE); + ASSERT(!mSwapchainImages[mCurrentSwapchainImageIndex] + .image->getAcquireNextImageSemaphore() + .valid()); // Invalidate the current swapchain while keep the last handle to create the new swapchain. - // mSwapchain may be already NULL if this is a repeated call (after a previous failure). - ASSERT(mSwapchain == mLastSwapchain || mSwapchain == VK_NULL_HANDLE); + ASSERT(mSwapchain == mLastSwapchain); mSwapchain = VK_NULL_HANDLE; - releaseSwapchainImages(contextVk); + mAcquireOperation.state = ImageAcquireState::Unacquired; - // If prerotation is emulated, adjust the window extents to match what real prerotation would - // have reported. - gl::Extents swapchainExtents = extents; - if (Is90DegreeRotation(mEmulatedPreTransform)) + // Surface size is unresolved since new swapchain may have new size. + setSizeState(SurfaceSizeState::InvalidSwapchain); + + releaseSwapchainImages(renderer); + + // Notify the parent classes of the surface's new state. + onStateChange(angle::SubjectMessage::SurfaceChanged); +} + +angle::Result WindowSurfaceVk::recreateSwapchain(vk::ErrorContext *context) +{ + // Swapchain must be already invalidated. + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired); + ASSERT(mSwapchain == VK_NULL_HANDLE); + + // May happen in case if it is recreate after a previous failure. + if (!mSwapchainImages.empty() || mDepthStencilImage.valid() || mColorImageMS.valid()) { - ASSERT(mPreTransform == VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR); - std::swap(swapchainExtents.width, swapchainExtents.height); + releaseSwapchainImages(context->getRenderer()); } - // On Android, vkCreateSwapchainKHR destroys mLastSwapchain, which is incorrect. Wait idle in - // that case as a workaround. - if (mLastSwapchain != VK_NULL_HANDLE && - contextVk->getFeatures().waitIdleBeforeSwapchainRecreation.enabled) + if (mLastSwapchain != VK_NULL_HANDLE) { - mUse.merge(contextVk->getSubmittedResourceUse()); - ANGLE_TRY(finish(contextVk)); + // On Android, vkCreateSwapchainKHR may return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR if use + // mLastSwapchain as an oldSwapchain when in shared present mode. Destroy the swapchain + // now as a workaround. + if (isSharedPresentMode() && + context->getFeatures().destroyOldSwapchainInSharedPresentMode.enabled) + { + ANGLE_TRY(finish(context)); + DestroyPresentHistory(context->getRenderer(), &mPresentHistory, &mPresentFenceRecycler, + &mPresentSemaphoreRecycler); + vkDestroySwapchainKHR(context->getDevice(), mLastSwapchain, nullptr); + mLastSwapchain = VK_NULL_HANDLE; + } } // Save the handle since it is going to be updated in the createSwapChain call below. VkSwapchainKHR oldSwapchain = mLastSwapchain; - angle::Result result = createSwapChain(contextVk, swapchainExtents); - - // Notify the parent classes of the surface's new state. - onStateChange(angle::SubjectMessage::SurfaceChanged); + angle::Result result = createSwapChain(context); // oldSwapchain was retired in the createSwapChain call above and can be collected. if (oldSwapchain != VK_NULL_HANDLE && oldSwapchain != mLastSwapchain) { - ANGLE_TRY(collectOldSwapchain(contextVk, oldSwapchain)); + ANGLE_TRY(collectOldSwapchain(context, oldSwapchain)); } return result; } -angle::Result WindowSurfaceVk::resizeSwapchainImages(vk::ErrorContext *context, uint32_t imageCount) +void WindowSurfaceVk::createSwapchainImages(uint32_t imageCount) { - if (static_cast(imageCount) != mSwapchainImages.size()) - { - mSwapchainImageBindings.clear(); - mSwapchainImages.resize(imageCount); + ASSERT(mSwapchainImages.empty()); + ASSERT(mSwapchainImageBindings.empty()); - // Update the image bindings. Because the observer binding class uses raw pointers we - // need to first ensure the entire image vector is fully allocated before binding the - // subject and observer together. - for (uint32_t index = 0; index < imageCount; ++index) - { - mSwapchainImageBindings.push_back( - angle::ObserverBinding(this, kAnySurfaceImageSubjectIndex)); - } + // Because the observer binding class uses raw pointers we need to first ensure the entire image + // vector is fully allocated before binding the subject and observer together. + mSwapchainImages.resize(imageCount); + mSwapchainImageBindings.resize(imageCount); - for (uint32_t index = 0; index < imageCount; ++index) - { - mSwapchainImages[index].image = std::make_unique(); - mSwapchainImageBindings[index].bind(mSwapchainImages[index].image.get()); - } + for (uint32_t index = 0; index < imageCount; ++index) + { + mSwapchainImages[index].image = std::make_unique(); + mSwapchainImageBindings[index] = angle::ObserverBinding(this, kAnySurfaceImageSubjectIndex); + mSwapchainImageBindings[index].bind(mSwapchainImages[index].image.get()); } - - return angle::Result::Continue; } -angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, - const gl::Extents &extents) +angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context) { ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::createSwapchain"); - ASSERT(mAcquireOperation.state != impl::ImageAcquireState::Ready); + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired); + ASSERT(mSizeState == SurfaceSizeState::InvalidSwapchain); ASSERT(mSwapchain == VK_NULL_HANDLE); vk::Renderer *renderer = context->getRenderer(); VkDevice device = renderer->getDevice(); - const vk::Format &format = renderer->getFormat(mState.config->renderTargetFormat); + const angle::FormatID actualFormatID = getActualFormatID(renderer); + const angle::FormatID intendedFormatID = getIntendedFormatID(renderer); - gl::Extents rotatedExtents = extents; + // Note: Vulkan doesn't allow 0-width/height swapchains and images. + const gl::Extents nonZeroSurfaceExtents(std::max(mWidth, 1), std::max(mHeight, 1), 1); + + gl::Extents swapchainExtents = nonZeroSurfaceExtents; if (Is90DegreeRotation(getPreTransform())) { // The Surface is oriented such that its aspect ratio no longer matches that of the @@ -1606,7 +1680,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, // scissor, and render-pass render area must also be swapped. Then, when ANGLE rotates // gl_Position in the vertex shader, the rendering will look the same as if no // pre-rotation had been done. - std::swap(rotatedExtents.width, rotatedExtents.height); + std::swap(swapchainExtents.width, swapchainExtents.height); } // We need transfer src for reading back from the backbuffer. @@ -1618,19 +1692,15 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, imageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } - mSwapchainPresentMode = getDesiredSwapchainPresentMode(); - mWidth = extents.width; - mHeight = extents.height; - VkSwapchainCreateInfoKHR swapchainInfo = {}; swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainInfo.flags = mState.hasProtectedContent() ? VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR : 0; - swapchainInfo.surface = mSurface; - swapchainInfo.imageFormat = vk::GetVkFormatFromFormatID(renderer, getActualFormatID(renderer)); - swapchainInfo.imageColorSpace = mSurfaceColorSpace; - // Note: Vulkan doesn't allow 0-width/height swapchains. - swapchainInfo.imageExtent.width = std::max(rotatedExtents.width, 1); - swapchainInfo.imageExtent.height = std::max(rotatedExtents.height, 1); + swapchainInfo.surface = mSurface; + swapchainInfo.minImageCount = mMinImageCount; + swapchainInfo.imageFormat = vk::GetVkFormatFromFormatID(renderer, actualFormatID); + swapchainInfo.imageColorSpace = mSurfaceColorSpace; + swapchainInfo.imageExtent.width = swapchainExtents.width; + swapchainInfo.imageExtent.height = swapchainExtents.height; swapchainInfo.imageArrayLayers = 1; swapchainInfo.imageUsage = imageUsageFlags; swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -1672,71 +1742,12 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, } #endif - if (context->getFeatures().supportsSwapchainMaintenance1.enabled) + if (renderer->getFeatures().supportsSwapchainMaintenance1.enabled) { swapchainInfo.flags |= VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT; } - // Get the list of compatible present modes to avoid unnecessary swapchain recreation. - if (renderer->getFeatures().supportsSurfaceMaintenance1.enabled) - { - VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2 = {}; - surfaceInfo2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; - surfaceInfo2.surface = mSurface; - - VkSurfacePresentModeEXT surfacePresentMode = {}; - surfacePresentMode.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT; - surfacePresentMode.presentMode = swapchainInfo.presentMode; - vk::AddToPNextChain(&surfaceInfo2, &surfacePresentMode); - - VkSurfaceCapabilities2KHR surfaceCaps2 = {}; - surfaceCaps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR; - - mCompatiblePresentModes.resize(kCompatiblePresentModesSize); - - VkSurfacePresentModeCompatibilityEXT compatibleModes = {}; - compatibleModes.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT; - compatibleModes.presentModeCount = kCompatiblePresentModesSize; - compatibleModes.pPresentModes = mCompatiblePresentModes.data(); - vk::AddToPNextChain(&surfaceCaps2, &compatibleModes); - - ANGLE_VK_TRY(context, vkGetPhysicalDeviceSurfaceCapabilities2KHR( - renderer->getPhysicalDevice(), &surfaceInfo2, &surfaceCaps2)); - - mCompatiblePresentModes.resize(compatibleModes.presentModeCount); - - // http://anglebug.com/368647924: in case of multiple drivers vulkan loader causes extension - // to be listed when not actually supported. kCompatiblePresentModesSize is above max count - // to catch this case and work around. - if (compatibleModes.presentModeCount == kCompatiblePresentModesSize) - { - mCompatiblePresentModes.resize(1); - mCompatiblePresentModes[0] = swapchainInfo.presentMode; - } - - // The implementation must always return the given present mode as compatible with itself. - ASSERT(IsCompatiblePresentMode(mSwapchainPresentMode, mCompatiblePresentModes.data(), - mCompatiblePresentModes.size())); - - // On Android we expect VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and - // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR to be compatible. - ASSERT(!IsAndroid() || !isSharedPresentMode() || - IsCompatiblePresentMode( - mSwapchainPresentMode == vk::PresentMode::SharedDemandRefreshKHR - ? vk::PresentMode::SharedContinuousRefreshKHR - : vk::PresentMode::SharedDemandRefreshKHR, - mCompatiblePresentModes.data(), mCompatiblePresentModes.size())); - - // Vulkan spec says "The per-present mode image counts may be less-than or greater-than the - // image counts returned when VkSurfacePresentModeEXT is not provided.". Use the per present - // mode imageCount here. Otherwise we may get into - // VUID-VkSwapchainCreateInfoKHR-presentMode-02839. - mSurfaceCaps = surfaceCaps2.surfaceCapabilities; - } - - mMinImageCount = GetMinImageCount(renderer, mSurfaceCaps, mSwapchainPresentMode); - swapchainInfo.minImageCount = mMinImageCount; - + ASSERT(!mCompatiblePresentModes.empty()); VkSwapchainPresentModesCreateInfoEXT compatibleModesInfo = {}; if (renderer->getFeatures().supportsSwapchainMaintenance1.enabled && mCompatiblePresentModes.size() > 1) @@ -1748,13 +1759,6 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, vk::AddToPNextChain(&swapchainInfo, &compatibleModesInfo); } - else - { - // Without VK_EXT_swapchain_maintenance1, each present mode can be considered only - // compatible with itself. - mCompatiblePresentModes.resize(1); - mCompatiblePresentModes[0] = swapchainInfo.presentMode; - } if (isSharedPresentMode()) { @@ -1775,7 +1779,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, // need to carry over to the new one. http://anglebug.com/42261637 VkSwapchainKHR newSwapChain = VK_NULL_HANDLE; ANGLE_VK_TRY(context, vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &newSwapChain)); - mLastSwapchain = newSwapChain; + mLastSwapchain = newSwapChain; // If frame timestamp was enabled for the surface, [re]enable it when [re]creating the swapchain if (renderer->getFeatures().supportsTimestampSurfaceAttribute.enabled && @@ -1802,7 +1806,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, ANGLE_VK_CHECK(context, samples > 0, VK_ERROR_INITIALIZATION_FAILED); VkExtent3D vkExtents; - gl_vk::GetExtent(rotatedExtents, &vkExtents); + gl_vk::GetExtent(swapchainExtents, &vkExtents); bool robustInit = mState.isRobustResourceInitEnabled(); @@ -1820,11 +1824,12 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, // with the rest of ANGLE, (e.g. which calculates the Vulkan scissor with non-rotated // values and then rotates the final rectangle). ANGLE_TRY(mColorImageMS.initMSAASwapchain( - context, gl::TextureType::_2D, vkExtents, Is90DegreeRotation(getPreTransform()), format, - samples, usage, gl::LevelIndex(0), 1, 1, robustInit, mState.hasProtectedContent())); + context, gl::TextureType::_2D, vkExtents, Is90DegreeRotation(getPreTransform()), + intendedFormatID, actualFormatID, samples, usage, gl::LevelIndex(0), 1, 1, robustInit, + mState.hasProtectedContent())); ANGLE_TRY(mColorImageMS.initMemoryAndNonZeroFillIfNeeded( - context, mState.hasProtectedContent(), renderer->getMemoryProperties(), - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vk::MemoryAllocationType::SwapchainMSAAImage)); + context, mState.hasProtectedContent(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + vk::MemoryAllocationType::SwapchainMSAAImage)); // Initialize the color render target with the multisampled targets. If not multisampled, // the render target will be updated to refer to a swapchain image on every acquire. @@ -1832,7 +1837,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, gl::LevelIndex(0), 0, 1, RenderTargetTransience::Default); } - ANGLE_TRY(resizeSwapchainImages(context, imageCount)); + createSwapchainImages(imageCount); for (uint32_t imageIndex = 0; imageIndex < imageCount; ++imageIndex) { @@ -1846,8 +1851,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, ASSERT(member.image); member.image->init2DWeakReference( - context, swapchainImages[imageIndex], extents, Is90DegreeRotation(getPreTransform()), - getIntendedFormatID(renderer), getActualFormatID(renderer), createFlags, + context, swapchainImages[imageIndex], nonZeroSurfaceExtents, + Is90DegreeRotation(getPreTransform()), intendedFormatID, actualFormatID, createFlags, imageUsageFlags, 1, robustInit); member.imageViews.init(renderer); member.frameNumber = 0; @@ -1864,12 +1869,16 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, dsUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } + // Try use tile memory for depth buffer since its content will be + // invalidated after swap. + vk::TileMemory tileMemoryPreference = + isSharedPresentMode() ? vk::TileMemory::Prohibited : vk::TileMemory::Preferred; + ANGLE_TRY(mDepthStencilImage.init(context, gl::TextureType::_2D, vkExtents, dsFormat, samples, dsUsage, gl::LevelIndex(0), 1, 1, robustInit, - mState.hasProtectedContent())); + mState.hasProtectedContent(), tileMemoryPreference)); ANGLE_TRY(mDepthStencilImage.initMemoryAndNonZeroFillIfNeeded( - context, mState.hasProtectedContent(), renderer->getMemoryProperties(), - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + context, mState.hasProtectedContent(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vk::MemoryAllocationType::SwapchainDepthStencilImage)); mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, nullptr, @@ -1881,8 +1890,9 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::ErrorContext *context, // Assign swapchain after all initialization is finished. mSwapchain = newSwapChain; - // Need to acquire a new image before the swapchain can be used. - mAcquireOperation.state = impl::ImageAcquireState::NeedToAcquire; + + // Swapchain is now valid, but size is still unresolved until acquire next image. + setSizeState(SurfaceSizeState::Unresolved); context->getPerfCounters().swapchainCreate++; @@ -1894,10 +1904,17 @@ bool WindowSurfaceVk::isMultiSampled() const return mColorImageMS.valid(); } -angle::Result WindowSurfaceVk::queryAndAdjustSurfaceCaps(ContextVk *contextVk, - VkSurfaceCapabilitiesKHR *surfaceCaps) +angle::Result WindowSurfaceVk::queryAndAdjustSurfaceCaps( + vk::ErrorContext *context, + vk::PresentMode presentMode, + VkSurfaceCapabilitiesKHR *surfaceCapsOut, + CompatiblePresentModes *compatiblePresentModesOut) const { - vk::Renderer *renderer = contextVk->getRenderer(); + // We must not query compatible present modes while swapchain is valid, but must query otherwise + ASSERT((compatiblePresentModesOut == nullptr && mSwapchain != VK_NULL_HANDLE) || + (compatiblePresentModesOut != nullptr && mSwapchain == VK_NULL_HANDLE)); + + vk::Renderer *renderer = context->getRenderer(); const VkPhysicalDevice &physicalDevice = renderer->getPhysicalDevice(); if (renderer->getFeatures().supportsSurfaceMaintenance1.enabled) @@ -1908,123 +1925,223 @@ angle::Result WindowSurfaceVk::queryAndAdjustSurfaceCaps(ContextVk *contextVk, VkSurfacePresentModeEXT surfacePresentMode = {}; surfacePresentMode.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT; - surfacePresentMode.presentMode = - vk::ConvertPresentModeToVkPresentMode(getDesiredSwapchainPresentMode()); + surfacePresentMode.presentMode = vk::ConvertPresentModeToVkPresentMode(presentMode); vk::AddToPNextChain(&surfaceInfo2, &surfacePresentMode); VkSurfaceCapabilities2KHR surfaceCaps2 = {}; surfaceCaps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR; - ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilities2KHR( - renderer->getPhysicalDevice(), &surfaceInfo2, &surfaceCaps2)); - *surfaceCaps = surfaceCaps2.surfaceCapabilities; + VkSurfacePresentModeCompatibilityEXT compatibleModes = {}; + if (compatiblePresentModesOut != nullptr) + { + // Skip the query if VK_EXT_swapchain_maintenance1 is not supported since compatible + // modes can't be used. + if (renderer->getFeatures().supportsSwapchainMaintenance1.enabled) + { + compatiblePresentModesOut->resize(kCompatiblePresentModesSize); + + compatibleModes.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT; + compatibleModes.presentModeCount = kCompatiblePresentModesSize; + compatibleModes.pPresentModes = compatiblePresentModesOut->data(); + vk::AddToPNextChain(&surfaceCaps2, &compatibleModes); + } + else + { + compatiblePresentModesOut->resize(1); + (*compatiblePresentModesOut)[0] = surfacePresentMode.presentMode; + } + } + + ANGLE_VK_TRY(context, vkGetPhysicalDeviceSurfaceCapabilities2KHR( + physicalDevice, &surfaceInfo2, &surfaceCaps2)); + + if (compatibleModes.pPresentModes != nullptr) + { + // http://anglebug.com/368647924: in case of multiple drivers vulkan loader causes + // extension to be listed when not actually supported. kCompatiblePresentModesSize is + // above max count to catch this case and work around. + if (compatibleModes.presentModeCount == kCompatiblePresentModesSize) + { + compatiblePresentModesOut->resize(1); + (*compatiblePresentModesOut)[0] = surfacePresentMode.presentMode; + } + else + { + compatiblePresentModesOut->resize(compatibleModes.presentModeCount); + + // Drop anything ANGLE can't handle. + std::erase_if(*compatiblePresentModesOut, + [](VkPresentModeKHR mode) { return !IsKnownAnglePresentMode(mode); }); + + // Ensure at least one mode remains. + ASSERT(!compatiblePresentModesOut->empty()); + + // The implementation must always return the given present mode as compatible with + // itself. + ASSERT(IsCompatiblePresentMode(presentMode, compatiblePresentModesOut->data(), + compatiblePresentModesOut->size())); + + // On Android we expect VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and + // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR to be compatible. + ASSERT(!IsAndroid() || !IsSharedPresentMode(presentMode) || + IsCompatiblePresentMode( + presentMode == vk::PresentMode::SharedDemandRefreshKHR + ? vk::PresentMode::SharedContinuousRefreshKHR + : vk::PresentMode::SharedDemandRefreshKHR, + compatiblePresentModesOut->data(), compatiblePresentModesOut->size())); + } + } + + *surfaceCapsOut = surfaceCaps2.surfaceCapabilities; } else { - ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, - surfaceCaps)); + ANGLE_VK_TRY(context, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, + surfaceCapsOut)); + if (compatiblePresentModesOut != nullptr) + { + // Without VK_EXT_surface_maintenance1, each present mode can be considered only + // compatible with itself. + compatiblePresentModesOut->resize(1); + (*compatiblePresentModesOut)[0] = vk::ConvertPresentModeToVkPresentMode(presentMode); + } } - if (surfaceCaps->currentExtent.width == kSurfaceSizedBySwapchain) + if (mIsSurfaceSizedBySwapchain) { - ASSERT(surfaceCaps->currentExtent.height == kSurfaceSizedBySwapchain); - ASSERT(!IsAndroid()); - // vkGetPhysicalDeviceSurfaceCapabilitiesKHR does not provide useful extents for some - // platforms (e.g. Fuschia). Therefore, we must query the window size via a - // platform-specific mechanism. Add those extents to the surfaceCaps - gl::Extents currentExtents; - ANGLE_TRY(getCurrentWindowSize(contextVk, ¤tExtents)); - surfaceCaps->currentExtent.width = currentExtents.width; - surfaceCaps->currentExtent.height = currentExtents.height; + // platforms (e.g. Fuchsia). Therefore, we must query the window size via a + // platform-specific mechanism. Add those extents to the surfaceCapsOut + gl::Extents windowExtents; + ANGLE_TRY(getCurrentWindowSize(context, &windowExtents)); + surfaceCapsOut->currentExtent.width = windowExtents.width; + surfaceCapsOut->currentExtent.height = windowExtents.height; } + adjustSurfaceExtent(&surfaceCapsOut->currentExtent); + return angle::Result::Continue; } -angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk, bool forceRecreate) +void WindowSurfaceVk::adjustSurfaceExtent(VkExtent2D *extent) const { - ASSERT(mAcquireOperation.state != impl::ImageAcquireState::Ready); + ASSERT(extent->width != kSurfaceSizedBySwapchain); + ASSERT(extent->height != kSurfaceSizedBySwapchain); - vk::PresentMode desiredSwapchainPresentMode = getDesiredSwapchainPresentMode(); - - bool presentModeIncompatible = - !IsCompatiblePresentMode(desiredSwapchainPresentMode, mCompatiblePresentModes.data(), - mCompatiblePresentModes.size()); - bool swapchainMissing = (mSwapchain == VK_NULL_HANDLE); - bool needRecreate = forceRecreate || presentModeIncompatible || swapchainMissing; - - // If there's no change, early out. - if (!contextVk->getFeatures().perFrameWindowSizeQuery.enabled && !needRecreate) + // When screen is physically rotated and prerotation is emulated, the window is rotated along + // with it. With real prerotation, the window preserves the upright orientation, by counter + // rotating relative to the screen physical rotation. In both cases, surface reports the window + // sizes. Because with emulated prerotation window is physically rotated, the surface will + // also report rotated sizes (relative to the upright orientation). Adjust the window extents + // to match what real prerotation would have reported. + if (Is90DegreeRotation(mEmulatedPreTransform)) { - return angle::Result::Continue; + ASSERT(mPreTransform == VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR); + std::swap(extent->width, extent->height); } +} + +angle::Result WindowSurfaceVk::prepareSwapchainForAcquireNextImage(vk::ErrorContext *context) +{ + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired); + ASSERT(mSizeState != SurfaceSizeState::Resolved); - // Get the latest surface capabilities. - ANGLE_TRY(queryAndAdjustSurfaceCaps(contextVk, &mSurfaceCaps)); + vk::Renderer *renderer = context->getRenderer(); + + const bool isSwapchainValid = (mSwapchain != VK_NULL_HANDLE); + ASSERT(!isSwapchainValid || !skipAcquireNextSwapchainImageForSharedPresentMode()); + + // Get the latest surface capabilities. Also update the compatible present modes if recreate + // was probably caused by the incompatible desired present mode. Note, that we must not update + // compatible present modes while swapchain is still valid, but must do it otherwise. + VkSurfaceCapabilitiesKHR surfaceCaps; + ANGLE_TRY(queryAndAdjustSurfaceCaps(context, mSwapchainPresentMode, &surfaceCaps, + isSwapchainValid ? nullptr : &mCompatiblePresentModes)); - if (contextVk->getFeatures().perFrameWindowSizeQuery.enabled && !needRecreate) + const uint32_t minImageCount = GetMinImageCount(renderer, surfaceCaps, mSwapchainPresentMode); + + if (isSwapchainValid) { // This device generates neither VK_ERROR_OUT_OF_DATE_KHR nor VK_SUBOPTIMAL_KHR. Check for // whether the size and/or rotation have changed since the swapchain was created. - uint32_t swapchainWidth = getWidth(); - uint32_t swapchainHeight = getHeight(); + uint32_t curSurfaceWidth = mWidth; + uint32_t curSurfaceHeight = mHeight; - // getWidth() and getHeight() are swapped for 90 degree and 270 degree emulated - // preTransform, we should swap them back before comparing with surface properties to avoid - // a size mismatch and unnecessary swapchain recreation + // On Android, rotation can cause the minImageCount to change + if (surfaceCaps.currentTransform == mPreTransform && + surfaceCaps.currentExtent.width == curSurfaceWidth && + surfaceCaps.currentExtent.height == curSurfaceHeight && minImageCount == mMinImageCount) + { + return angle::Result::Continue; + } - if (Is90DegreeRotation(mEmulatedPreTransform)) + if (renderer->getFeatures().avoidInvisibleWindowSwapchainRecreate.enabled) { - std::swap(swapchainWidth, swapchainHeight); + bool isWindowVisible = false; + ANGLE_TRY(getWindowVisibility(context, &isWindowVisible)); + if (!isWindowVisible) + { + return angle::Result::Continue; + } } - // On Android, rotation can cause the minImageCount to change - needRecreate = mSurfaceCaps.currentTransform != mPreTransform || - mSurfaceCaps.currentExtent.width != swapchainWidth || - mSurfaceCaps.currentExtent.height != swapchainHeight || - GetMinImageCount(contextVk->getRenderer(), mSurfaceCaps, - desiredSwapchainPresentMode) != mMinImageCount; + invalidateSwapchain(renderer); } + ASSERT(mSwapchain == VK_NULL_HANDLE); - // If anything has changed, recreate the swapchain. - if (!needRecreate) { - return angle::Result::Continue; + // Lock protects individual |mWidth| and |mHeight| writes from this thread and reads from + // other threads. The acquire memory order of the mutex lock will prevent |mSizeState| + // relaxed atomic assignment to be moved before the lock. When other thread reads that + // |mSizeState| is resolved, the mutex will be already locked, preventing reading old + // |mWidth| and |mHeight| values. Similar goal may be archived by using atomics instead of + // the mutex. The mutex is used for code simplicity and to avoid non relaxed atomic stores + // on each frame. + std::lock_guard lock(mSizeMutex); + mWidth = surfaceCaps.currentExtent.width; + mHeight = surfaceCaps.currentExtent.height; } - gl::Extents newSwapchainExtents(mSurfaceCaps.currentExtent.width, - mSurfaceCaps.currentExtent.height, 1); + mMinImageCount = minImageCount; - if (contextVk->getFeatures().enablePreRotateSurfaces.enabled) - { - // Update the surface's transform, which can change even if the window size does not. - mPreTransform = mSurfaceCaps.currentTransform; - } + // Use the surface's transform. For many platforms, this will always be identity (ANGLE does + // not need to do any pre-rotation). However, when surfaceCaps.currentTransform is not + // identity, the device has been rotated away from its natural orientation. In such a case, + // ANGLE must rotate all rendering in order to avoid the compositor (e.g. SurfaceFlinger on + // Android) performing an additional rotation blit. In addition, ANGLE must create the + // swapchain with VkSwapchainCreateInfoKHR::preTransform set to the value of + // surfaceCaps.currentTransform. + mPreTransform = surfaceCaps.currentTransform; - return recreateSwapchain(contextVk, newSwapchainExtents); + return recreateSwapchain(context); } -void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk) +void WindowSurfaceVk::releaseSwapchainImages(vk::Renderer *renderer) { - vk::Renderer *renderer = contextVk->getRenderer(); + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired); + ASSERT(mSwapchain == VK_NULL_HANDLE); - mColorRenderTarget.releaseImageAndViews(contextVk); - mDepthStencilRenderTarget.releaseImageAndViews(contextVk); + // This is the last chance when resource uses may be merged. + mergeImageResourceUses(); + + mColorRenderTarget.releaseSwapchainImage(); + mDepthStencilRenderTarget.releaseSwapchainImage(); if (mDepthStencilImage.valid()) { + ASSERT(!mDepthStencilImage.hasAnyRenderPassUsageFlags()); mDepthStencilImageViews.release(renderer, mDepthStencilImage.getResourceUse()); - mDepthStencilImage.releaseImageFromShareContexts(renderer, contextVk, {}); + mDepthStencilImage.releaseImage(renderer); mDepthStencilImage.releaseStagedUpdates(renderer); } if (mColorImageMS.valid()) { + ASSERT(!mColorImageMS.hasAnyRenderPassUsageFlags()); + renderer->collectGarbage(mColorImageMS.getResourceUse(), &mFramebufferMS); mColorImageMSViews.release(renderer, mColorImageMS.getResourceUse()); - mColorImageMS.releaseImageFromShareContexts(renderer, contextVk, {}); + mColorImageMS.releaseImage(renderer); mColorImageMS.releaseStagedUpdates(renderer); - contextVk->addGarbage(&mFramebufferMS); } mSwapchainImageBindings.clear(); @@ -2032,32 +2149,41 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk) for (SwapchainImage &swapchainImage : mSwapchainImages) { ASSERT(swapchainImage.image); + ASSERT(!swapchainImage.image->hasAnyRenderPassUsageFlags()); + + renderer->collectGarbage(swapchainImage.image->getResourceUse(), + &swapchainImage.framebuffer); + renderer->collectGarbage(swapchainImage.image->getResourceUse(), + &swapchainImage.fetchFramebuffer); + swapchainImage.imageViews.release(renderer, swapchainImage.image->getResourceUse()); // swapchain image must not have ANI semaphore assigned here, since acquired image must be // presented before swapchain recreation. swapchainImage.image->resetImageWeakReference(); swapchainImage.image->destroy(renderer); - - contextVk->addGarbage(&swapchainImage.framebuffer); - if (swapchainImage.fetchFramebuffer.valid()) - { - contextVk->addGarbage(&swapchainImage.fetchFramebuffer); - } } mSwapchainImages.clear(); } -angle::Result WindowSurfaceVk::finish(vk::ErrorContext *context) +void WindowSurfaceVk::mergeImageResourceUses() { - vk::Renderer *renderer = context->getRenderer(); - mUse.merge(mDepthStencilImage.getResourceUse()); mUse.merge(mColorImageMS.getResourceUse()); for (SwapchainImage &swapchainImage : mSwapchainImages) { mUse.merge(swapchainImage.image->getResourceUse()); } +} + +angle::Result WindowSurfaceVk::finish(vk::ErrorContext *context) +{ + vk::Renderer *renderer = context->getRenderer(); + + // Image acquire semaphores are tracked by the ResourceUse of the corresponding swapchain images + // (waiting for image will also wait for the semaphore). Present semaphores are tracked + // explicitly after pre-present submission. + mergeImageResourceUses(); return renderer->finishResourceUse(context, mUse); } @@ -2096,31 +2222,25 @@ egl::Error WindowSurfaceVk::prepareSwap(const gl::Context *context) { // Image is only required to be acquired here in case of a blocking present modes (FIFO). // However, we will acquire the image in any case, for simplicity and possibly for performance. - if (mAcquireOperation.state != impl::ImageAcquireState::NeedToAcquire) + if (mAcquireOperation.state != ImageAcquireState::Unacquired) { return egl::NoError(); } - vk::Renderer *renderer = vk::GetImpl(context)->getRenderer(); + ContextVk *contextVk = vk::GetImpl(context); - angle::Result result = prepareForAcquireNextSwapchainImage(context, false); + angle::Result result = prepareSwapchainForAcquireNextImage(contextVk); if (result != angle::Result::Continue) { return angle::ToEGL(result, EGL_BAD_SURFACE); } // |mColorRenderTarget| may be invalid at this point (in case of swapchain recreate above), - // however it will not be accessed until update in the |postProcessUnlockedAcquire| call. + // however it will not be accessed until update in the |acquireNextSwapchainImage| call. // Must check present mode after the above prepare (in case of swapchain recreate). - if (isSharedPresentMode()) - { - // Shared present mode requires special handling, because it requires use of - // |skipAcquireNextSwapchainImageForSharedPresentMode| method. - // Below call is not going to block. - result = doDeferredAcquireNextImageWithUsableSwapchain(context); - return angle::ToEGL(result, EGL_BAD_SURFACE); - } + ASSERT(mSwapchain != VK_NULL_HANDLE); + ASSERT(!skipAcquireNextSwapchainImageForSharedPresentMode()); // Call vkAcquireNextImageKHR without holding the share group and global locks. // The following are accessed by this function: @@ -2128,8 +2248,9 @@ egl::Error WindowSurfaceVk::prepareSwap(const gl::Context *context) // - mAcquireOperation.state // - Contents of mAcquireOperation.unlockedAcquireData and // mAcquireOperation.unlockedAcquireResult - // - context->getDevice(), which doesn't need external synchronization + // - contextVk->getDevice(), which doesn't need external synchronization // - mSwapchain + // - mSizeState, which is atomic // // All these members MUST only be accessed from a thread where Surface is current. // The |AcquireNextImageUnlocked| itself is also possible only from this thread, therefore there @@ -2139,11 +2260,11 @@ egl::Error WindowSurfaceVk::prepareSwap(const gl::Context *context) // calling it (likely the eglSwapBuffers call that follows) egl::Display::GetCurrentThreadUnlockedTailCall()->add( - [device = renderer->getDevice(), swapchain = mSwapchain, - acquire = &mAcquireOperation](void *resultOut) { + [device = contextVk->getDevice(), swapchain = mSwapchain, acquire = &mAcquireOperation, + surfaceSizeState = &mSizeState](void *resultOut) { ANGLE_TRACE_EVENT0("gpu.angle", "Acquire Swap Image Before Swap"); ANGLE_UNUSED_VARIABLE(resultOut); - AcquireNextImageUnlocked(device, swapchain, acquire); + AcquireNextImageUnlocked(device, swapchain, acquire, surfaceSizeState); }); return egl::NoError(); @@ -2151,20 +2272,23 @@ egl::Error WindowSurfaceVk::prepareSwap(const gl::Context *context) egl::Error WindowSurfaceVk::swapWithDamage(const gl::Context *context, const EGLint *rects, - EGLint n_rects) + EGLint n_rects, + SurfaceSwapFeedback *feedback) { - angle::Result result = swapImpl(context, rects, n_rects, nullptr); + ContextVk *contextVk = vk::GetImpl(context); + angle::Result result = swapImpl(contextVk, rects, n_rects, nullptr, feedback); if (result == angle::Result::Continue) { - ContextVk *contextVk = vk::GetImpl(context); - result = contextVk->onFramebufferBoundary(context); + result = contextVk->onFrameBoundary(context); } return angle::ToEGL(result, EGL_BAD_SURFACE); } -egl::Error WindowSurfaceVk::swap(const gl::Context *context) +egl::Error WindowSurfaceVk::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { + ContextVk *contextVk = vk::GetImpl(context); + // When in shared present mode, eglSwapBuffers is unnecessary except for mode change. When mode // change is not expected, the eglSwapBuffers call is forwarded to the context as a glFlush. // This allows the context to skip it if there's nothing to flush. Otherwise control is bounced @@ -2174,31 +2298,79 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context) // effectively wait for the just submitted commands. if (isSharedPresentMode() && mSwapchainPresentMode == getDesiredSwapchainPresentMode()) { - const angle::Result result = vk::GetImpl(context)->flush(context); + const angle::Result result = contextVk->flush(context); return angle::ToEGL(result, EGL_BAD_SURFACE); } - angle::Result result = swapImpl(context, nullptr, 0, nullptr); + angle::Result result = swapImpl(contextVk, nullptr, 0, nullptr, feedback); if (result == angle::Result::Continue) { - ContextVk *contextVk = vk::GetImpl(context); - result = contextVk->onFramebufferBoundary(context); + result = contextVk->onFrameBoundary(context); } return angle::ToEGL(result, EGL_BAD_SURFACE); } -angle::Result WindowSurfaceVk::computePresentOutOfDate(vk::ErrorContext *context, - VkResult result, - bool *presentOutOfDate) +angle::Result WindowSurfaceVk::checkSwapchainOutOfDate(vk::ErrorContext *context, + VkResult presentResult) { + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired || + (mAcquireOperation.state == ImageAcquireState::Ready && + skipAcquireNextSwapchainImageForSharedPresentMode())); + ASSERT(mSwapchain != VK_NULL_HANDLE); + + bool presentOutOfDate = false; + bool isFailure = false; + // If OUT_OF_DATE is returned, it's ok, we just need to recreate the swapchain before // continuing. We do the same when VK_SUBOPTIMAL_KHR is returned to avoid visual degradation - // and handle device rotation / screen resize. - *presentOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR; - if (!*presentOutOfDate) + // (except when in shared present mode). + switch (presentResult) { - ANGLE_VK_TRY(context, result); + case VK_SUCCESS: + break; + case VK_SUBOPTIMAL_KHR: + presentOutOfDate = !isSharedPresentMode(); + break; + case VK_ERROR_OUT_OF_DATE_KHR: + presentOutOfDate = true; + break; + case VK_ERROR_SURFACE_LOST_KHR: + // Handle SURFACE_LOST_KHR the same way as OUT_OF_DATE when in shared present mode, + // because on some platforms (observed on Android) swapchain recreate still succeeds + // making this error behave the same as OUT_OF_DATE. In case of a real surface lost, + // following swapchain recreate will also fail, effectively deferring the failure. + if (isSharedPresentMode()) + { + presentOutOfDate = true; + } + else + { + isFailure = true; + } + break; + default: + isFailure = true; + break; } + + const vk::PresentMode desiredSwapchainPresentMode = getDesiredSwapchainPresentMode(); + + // Invalidate the swapchain on failure to avoid repeated swapchain use and to be able to recover + // from the error. + if (presentOutOfDate || isFailure || + !IsCompatiblePresentMode(desiredSwapchainPresentMode, mCompatiblePresentModes.data(), + mCompatiblePresentModes.size())) + { + invalidateSwapchain(context->getRenderer()); + mSwapchainPresentMode = desiredSwapchainPresentMode; + if (isFailure) + { + ANGLE_VK_TRY(context, presentResult); + UNREACHABLE(); + } + } + + ASSERT(!isFailure); return angle::Result::Continue; } @@ -2226,25 +2398,24 @@ angle::Result WindowSurfaceVk::prePresentSubmit(ContextVk *contextVk, // Make sure deferred clears are applied, if any. if (mColorImageMS.valid()) { - // anglebug:382006939 + ASSERT(mColorImageMS.areStagedUpdatesClearOnly()); + // http://anglebug.com/382006939 // If app calls: - // glClear(GL_COLOR_BUFFER_BIT); - // eglSwapBuffers(); + // glClear(GL_COLOR_BUFFER_BIT); + // eglSwapBuffers(); // As an optimization, deferred clear could skip msaa buffer and applied to back buffer // directly instead of clearing msaa buffer and then resolve. // The exception is that when we back buffer data has to be preserved under // certain situations, we must also ensure msaa buffer contains the right content. // Under that situation, this optimization will not apply. - vk::ClearValuesArray deferredClearValues; - ANGLE_TRY(mColorImageMS.flushSingleSubresourceStagedUpdates(contextVk, gl::LevelIndex(0), 0, - 1, &deferredClearValues, 0)); - if (deferredClearValues.any()) + if (!isSharedPresentMode() && + (mState.swapBehavior == EGL_BUFFER_DESTROYED && !mIsBufferAgeQueried)) { - // Apply clear color directly to the single sampled image if the EGL surface is - // double buffered or when EGL_SWAP_BEHAVIOR is EGL_BUFFER_DESTROYED - if (!isSharedPresentMode() && - (mState.swapBehavior == EGL_BUFFER_DESTROYED && mBufferAgeQueryFrameNumber == 0)) + vk::ClearValuesArray deferredClearValues; + ANGLE_TRY(mColorImageMS.flushSingleSubresourceStagedUpdates( + contextVk, gl::LevelIndex(0), 0, 1, &deferredClearValues, 0)); + if (deferredClearValues.any()) { // Apply clear color directly to the single sampled image if the EGL surface is // double buffered and when EGL_SWAP_BEHAVIOR is EGL_BUFFER_DESTROYED @@ -2255,14 +2426,14 @@ angle::Result WindowSurfaceVk::prePresentSubmit(ContextVk *contextVk, gl::LevelIndex(1), 0, 1, {})); imageResolved = true; } - else - { - // Apply clear value to multisampled mColorImageMS and then resolve to single - // sampled image later if EGL surface is single buffered or when EGL_SWAP_BEHAVIOR - // is EGL_BUFFER_PRESERVED - ANGLE_TRY(mColorImageMS.flushStagedUpdates(contextVk, gl::LevelIndex(0), - gl::LevelIndex(1), 0, 1, {})); - } + } + else + { + // Apply clear value to multisampled mColorImageMS and then resolve to single sampled + // image later if EGL surface is single buffered or when EGL_SWAP_BEHAVIOR is + // EGL_BUFFER_PRESERVED + ANGLE_TRY(mColorImageMS.flushStagedUpdates(contextVk, gl::LevelIndex(0), + gl::LevelIndex(1), 0, 1, {})); } } else @@ -2278,8 +2449,8 @@ angle::Result WindowSurfaceVk::prePresentSubmit(ContextVk *contextVk, if (image.image->getAcquireNextImageSemaphore().valid()) { ASSERT(!renderer->getFeatures().supportsPresentation.enabled || - image.image->getCurrentImageLayout() == vk::ImageLayout::Present || - image.image->getCurrentImageLayout() == vk::ImageLayout::Undefined); + image.image->getCurrentImageAccess() == vk::ImageAccess::Present || + image.image->getCurrentImageAccess() == vk::ImageAccess::Undefined); contextVk->addWaitSemaphore(image.image->getAcquireNextImageSemaphore().getHandle(), vk::kSwapchainAcquireImageWaitStageFlags); image.image->resetAcquireNextImageSemaphore(); @@ -2294,28 +2465,21 @@ angle::Result WindowSurfaceVk::prePresentSubmit(ContextVk *contextVk, ASSERT(!imageResolved); ANGLE_TRY(contextVk->optimizeRenderPassForPresent(&image.imageViews, image.image.get(), - &mColorImageMS, mSwapchainPresentMode, + &mColorImageMS, isSharedPresentMode(), &imageResolved)); } - // Because the color attachment defers layout changes until endRenderPass time, we must call - // finalize the layout transition in the renderpass before we insert layout change to - // ImageLayout::Present bellow. - contextVk->finalizeImageLayout(image.image.get(), {}); - contextVk->finalizeImageLayout(&mColorImageMS, {}); - - vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper)); - if (mColorImageMS.valid() && !imageResolved) { // Transition the multisampled image to TRANSFER_SRC for resolve. - vk::CommandBufferAccess access; - access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, &mColorImageMS); - access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, - image.image.get()); + vk::CommandResources resources; + resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, &mColorImageMS); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, + image.image.get()); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; + ANGLE_TRY( + contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); VkImageResolve resolveRegion = {}; resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -2327,7 +2491,7 @@ angle::Result WindowSurfaceVk::prePresentSubmit(ContextVk *contextVk, resolveRegion.dstOffset = {}; resolveRegion.extent = image.image->getRotatedExtents(); - mColorImageMS.resolve(image.image.get(), resolveRegion, + mColorImageMS.resolve(renderer, image.image.get(), resolveRegion, &commandBufferHelper->getCommandBuffer()); contextVk->getPerfCounters().swapchainResolveOutsideSubpass++; @@ -2337,30 +2501,67 @@ angle::Result WindowSurfaceVk::prePresentSubmit(ContextVk *contextVk, // with other functionality, especially counters used to validate said functionality. const bool shouldDrawOverlay = overlayHasEnabledWidget(contextVk); - if (renderer->getFeatures().supportsPresentation.enabled && !shouldDrawOverlay) + if (!shouldDrawOverlay) + { + ANGLE_TRY(recordPresentLayoutBarrierIfNecessary(contextVk)); + } + + if (mDepthStencilImage.valid()) { - // This does nothing if it's already in the requested layout - image.image->recordReadBarrier(contextVk, VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::Present, commandBufferHelper); + // EGL specification says depth/stencil buffer data is no longer valid after swap. Set their + // content invalid right before last submission so that we dont need to store. + mDepthStencilImage.invalidateEntireLevelContent(contextVk, gl::LevelIndex(0)); + mDepthStencilImage.invalidateEntireLevelStencilContent(contextVk, gl::LevelIndex(0)); } ANGLE_TRY(contextVk->flushAndSubmitCommands(shouldDrawOverlay ? nullptr : &presentSemaphore, - nullptr, RenderPassClosureReason::EGLSwapBuffers)); + nullptr, QueueSubmitReason::EGLSwapBuffers)); if (shouldDrawOverlay) { updateOverlay(contextVk); ANGLE_TRY(drawOverlay(contextVk, &image)); - if (renderer->getFeatures().supportsPresentation.enabled) - { - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper)); - image.image->recordReadBarrier(contextVk, VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::Present, commandBufferHelper); - } + ANGLE_TRY(recordPresentLayoutBarrierIfNecessary(contextVk)); + + ANGLE_TRY(contextVk->flushAndSubmitCommands(&presentSemaphore, nullptr, + QueueSubmitReason::DrawOverlay)); + } + + ASSERT(image.image->getCurrentImageAccess() == + (isSharedPresentMode() ? vk::ImageAccess::SharedPresent : vk::ImageAccess::Present)); + + // This is to track |presentSemaphore| submission. + mUse.setQueueSerial(contextVk->getLastSubmittedQueueSerial()); + + return angle::Result::Continue; +} + +angle::Result WindowSurfaceVk::recordPresentLayoutBarrierIfNecessary(ContextVk *contextVk) +{ + if (!contextVk->getFeatures().supportsPresentation.enabled || isSharedPresentMode()) + { + return angle::Result::Continue; + } + vk::ImageHelper *image = mSwapchainImages[mCurrentSwapchainImageIndex].image.get(); - ANGLE_TRY(contextVk->flushAndSubmitCommands( - &presentSemaphore, nullptr, RenderPassClosureReason::AlreadySpecifiedElsewhere)); + // Note that renderpass will be automatically closed in case of outside renderpass resolve. + if (contextVk->hasStartedRenderPassWithDefaultFramebuffer()) + { + // When we have a renderpass with default framebuffer it must be optimized for present. + ASSERT(contextVk->getStartedRenderPassCommands().isImageOptimizedForPresent(image)); + return angle::Result::Continue; + } + + // Image may be already in Present layout if swap without any draw. + if (image->getCurrentImageAccess() != vk::ImageAccess::Present) + { + vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper)); + + image->recordReadBarrier(contextVk, VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageAccess::Present, + commandBufferHelper); + commandBufferHelper->retainImage(contextVk->getRenderer(), image); } return angle::Result::Continue; @@ -2370,9 +2571,10 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, const EGLint *rects, EGLint n_rects, const void *pNextChain, - bool *presentOutOfDate) + SurfaceSwapFeedback *feedback) { - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::Ready); + ASSERT(mAcquireOperation.state == ImageAcquireState::Ready); + ASSERT(mSizeState == SurfaceSizeState::Resolved); ASSERT(mSwapchain != VK_NULL_HANDLE); ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::present"); @@ -2416,8 +2618,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, std::vector vkRects; if (contextVk->getFeatures().supportsIncrementalPresent.enabled && (n_rects > 0)) { - EGLint width = getWidth(); - EGLint height = getHeight(); + EGLint width = mWidth; + EGLint height = mHeight; const EGLint *eglRects = rects; presentRegion.rectangleCount = n_rects; @@ -2475,12 +2677,26 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, .image->getAcquireNextImageSemaphore() .valid()); + // EGL_ANDROID_presentation_time: set the desired presentation time for the frame. + VkPresentTimesInfoGOOGLE presentTimesInfo = {}; + VkPresentTimeGOOGLE presentTime = {}; + if (mDesiredPresentTime.has_value()) + { + ASSERT(contextVk->getFeatures().supportsTimestampSurfaceAttribute.enabled); + presentTime.presentID = mPresentID++; + presentTime.desiredPresentTime = mDesiredPresentTime.value(); + mDesiredPresentTime.reset(); + + presentTimesInfo.sType = VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE; + presentTimesInfo.swapchainCount = 1; + presentTimesInfo.pTimes = &presentTime; + + vk::AddToPNextChain(&presentInfo, &presentTimesInfo); + } + VkResult presentResult = renderer->queuePresent(contextVk, contextVk->getPriority(), presentInfo); - // Update cached surface capabilities. - ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(renderer->getPhysicalDevice(), - mSurface, &mSurfaceCaps)); // EGL_EXT_buffer_age // 4) What is the buffer age of a single buffered surface? // RESOLVED: 0. This falls out implicitly from the buffer age @@ -2492,6 +2708,13 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, { // Set FrameNumber for the presented image. mSwapchainImages[mCurrentSwapchainImageIndex].frameNumber = mFrameCount++; + // Always defer acquiring the next swapchain image, except when in shared present mode. + // Note, if desired present mode is not compatible with the current mode or present is + // out-of-date, swapchain will be invalidated in |checkSwapchainOutOfDate| call below. + deferAcquireNextImage(); + // Tell front end that swapChain image changed so that it could dirty default framebuffer. + ASSERT(feedback != nullptr); + feedback->swapChainImageChanged = true; } // Place the semaphore in the present history. Schedule pending old swapchains to be destroyed @@ -2511,7 +2734,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, mPresentHistory.back().oldSwapchains = std::move(mOldSwapchains); } - ANGLE_TRY(computePresentOutOfDate(contextVk, presentResult, presentOutOfDate)); + // Check for out of date swapchain. Note, possible swapchain invalidate will also defer ANI. + ANGLE_TRY(checkSwapchainOutOfDate(contextVk, presentResult)); // Now apply CPU throttle if needed ANGLE_TRY(throttleCPU(contextVk, swapSerial)); @@ -2556,7 +2780,7 @@ angle::Result WindowSurfaceVk::cleanUpPresentHistory(vk::ErrorContext *context) while (!mPresentHistory.empty()) { - impl::ImagePresentOperation &presentOperation = mPresentHistory.front(); + ImagePresentOperation &presentOperation = mPresentHistory.front(); // If there is no fence associated with the history, check queueSerial. if (!presentOperation.fence.valid()) @@ -2596,7 +2820,7 @@ angle::Result WindowSurfaceVk::cleanUpPresentHistory(vk::ErrorContext *context) if (mPresentHistory.size() > mSwapchainImages.size() * 2 && !mPresentHistory.front().fence.valid() && !mPresentHistory.front().queueSerial.valid()) { - impl::ImagePresentOperation presentOperation = std::move(mPresentHistory.front()); + ImagePresentOperation presentOperation = std::move(mPresentHistory.front()); mPresentHistory.pop_front(); // |kInvalidImageIndex| is only possible when |VkSwapchainPresentFenceInfoEXT| is used, in @@ -2625,8 +2849,8 @@ angle::Result WindowSurfaceVk::cleanUpOldSwapchains(vk::ErrorContext *context) while (!mOldSwapchains.empty()) { - impl::SwapchainCleanupData &oldSwapchain = mOldSwapchains.front(); - VkResult result = oldSwapchain.getFencesStatus(device); + SwapchainCleanupData &oldSwapchain = mOldSwapchains.front(); + VkResult result = oldSwapchain.getFencesStatus(device); if (result == VK_NOT_READY) { break; @@ -2639,57 +2863,46 @@ angle::Result WindowSurfaceVk::cleanUpOldSwapchains(vk::ErrorContext *context) return angle::Result::Continue; } -angle::Result WindowSurfaceVk::swapImpl(const gl::Context *context, +angle::Result WindowSurfaceVk::swapImpl(ContextVk *contextVk, const EGLint *rects, EGLint n_rects, - const void *pNextChain) + const void *pNextChain, + SurfaceSwapFeedback *feedback) { ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::swapImpl"); - ContextVk *contextVk = vk::GetImpl(context); - // prepareSwap() has already called vkAcquireNextImageKHR if necessary, but its results need to // be processed now if not already. doDeferredAcquireNextImage() will - // automatically skip the prepareForAcquireNextSwapchainImage() and vkAcquireNextImageKHR calls - // in that case. The swapchain recreation path in - // doDeferredAcquireNextImageWithUsableSwapchain() is acceptable because it only happens if - // previous vkAcquireNextImageKHR failed. + // automatically skip the prepareSwapchainForAcquireNextImage() and vkAcquireNextImageKHR calls + // in that case. The swapchain recreation path in doDeferredAcquireNextImage() is acceptable + // because it only happens if previous vkAcquireNextImageKHR failed. // Note: this method may be called from |onSharedPresentContextFlush|, therefore can't assume // that image is always acquired at this point. - if (mAcquireOperation.state != impl::ImageAcquireState::Ready) + if (mAcquireOperation.state != ImageAcquireState::Ready) { - ANGLE_TRY(doDeferredAcquireNextImage(context, false)); + ANGLE_TRY(doDeferredAcquireNextImage(contextVk)); } - bool presentOutOfDate = false; - ANGLE_TRY(present(contextVk, rects, n_rects, pNextChain, &presentOutOfDate)); - - // Defer acquiring the next swapchain image regardless if the swapchain is out-of-date or not. - deferAcquireNextImage(); - - if (presentOutOfDate) - { - // Immediately recreate out of date swapchain, while keeping image acquire deferred. - ANGLE_VK_TRACE_EVENT_AND_MARKER(contextVk, "Out-of-Date Swapbuffer"); - ANGLE_TRY(checkForOutOfDateSwapchain(contextVk, true)); - } + ANGLE_TRY(present(contextVk, rects, n_rects, pNextChain, feedback)); // |mColorRenderTarget| may be invalid at this point (in case of swapchain recreate above), - // however it will not be accessed until update in the |postProcessUnlockedAcquire| call. - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire); + // however it will not be accessed until update in the |acquireNextSwapchainImage| call. + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired || + (mAcquireOperation.state == ImageAcquireState::Ready && + skipAcquireNextSwapchainImageForSharedPresentMode())); return angle::Result::Continue; } -angle::Result WindowSurfaceVk::onSharedPresentContextFlush(const gl::Context *context) +angle::Result WindowSurfaceVk::onSharedPresentContextFlush(ContextVk *contextVk) { - return swapImpl(context, nullptr, 0, nullptr); + return swapImpl(contextVk, nullptr, 0, nullptr, nullptr); } bool WindowSurfaceVk::hasStagedUpdates() const { - return mAcquireOperation.state == impl::ImageAcquireState::Ready && - mSwapchainImages[mCurrentSwapchainImageIndex].image->hasStagedUpdatesInAllocatedLevels(); + return mAcquireOperation.state == ImageAcquireState::Ready && + mColorRenderTarget.getImageForRenderPass().hasStagedUpdatesInAllocatedLevels(); } void WindowSurfaceVk::setTimestampsEnabled(bool enabled) @@ -2698,103 +2911,71 @@ void WindowSurfaceVk::setTimestampsEnabled(bool enabled) ASSERT(IsAndroid()); } -void WindowSurfaceVk::deferAcquireNextImage() +egl::Error WindowSurfaceVk::setPresentationTime(EGLnsecsANDROID time) { - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::Ready); - - mAcquireOperation.state = impl::ImageAcquireState::NeedToAcquire; - - // Set gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 via subject-observer message-passing - // to the front-end Surface, Framebuffer, and Context classes. The DIRTY_BIT_COLOR_ATTACHMENT_0 - // is processed before all other dirty bits. However, since the attachments of the default - // framebuffer cannot change, this bit will be processed before all others. It will cause - // WindowSurfaceVk::getAttachmentRenderTarget() to be called (which will acquire the next image) - // before any RenderTargetVk accesses. The processing of other dirty bits as well as other - // setup for draws and reads will then access a properly-updated RenderTargetVk. - onStateChange(angle::SubjectMessage::SwapchainImageChanged); + mDesiredPresentTime = time; + return egl::NoError(); } -angle::Result WindowSurfaceVk::prepareForAcquireNextSwapchainImage(const gl::Context *context, - bool forceSwapchainRecreate) +void WindowSurfaceVk::deferAcquireNextImage() { - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire); + ASSERT(mAcquireOperation.state == ImageAcquireState::Ready); + ASSERT(mSizeState == SurfaceSizeState::Resolved); + ASSERT(mSwapchain != VK_NULL_HANDLE); + ASSERT(!mSwapchainImages[mCurrentSwapchainImageIndex] + .image->getAcquireNextImageSemaphore() + .valid()); + ASSERT(!isSharedPresentMode()); - ContextVk *contextVk = vk::GetImpl(context); - return checkForOutOfDateSwapchain(contextVk, forceSwapchainRecreate); + mAcquireOperation.state = ImageAcquireState::Unacquired; + + // Swapchain may be recreated in prepareSwapchainForAcquireNextImage() call. + setSizeState(SurfaceSizeState::Unresolved); } -angle::Result WindowSurfaceVk::doDeferredAcquireNextImage(const gl::Context *context, - bool forceSwapchainRecreate) +angle::Result WindowSurfaceVk::doDeferredAcquireNextImage(vk::ErrorContext *context) { - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire || - (mAcquireOperation.state == impl::ImageAcquireState::NeedToProcessResult && - !forceSwapchainRecreate)); - // prepareForAcquireNextSwapchainImage() may recreate Swapchain even if there is an image + ASSERT(mAcquireOperation.state != ImageAcquireState::Ready); + // prepareSwapchainForAcquireNextImage() may recreate Swapchain even if there is an image // acquired. Avoid this, by skipping the prepare call. - if (mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire) + if (mAcquireOperation.state == ImageAcquireState::Unacquired) { - ANGLE_TRY(prepareForAcquireNextSwapchainImage(context, forceSwapchainRecreate)); + ANGLE_TRY(prepareSwapchainForAcquireNextImage(context)); } - return doDeferredAcquireNextImageWithUsableSwapchain(context); -} - -angle::Result WindowSurfaceVk::doDeferredAcquireNextImageWithUsableSwapchain( - const gl::Context *context) -{ - ASSERT(mAcquireOperation.state != impl::ImageAcquireState::Ready); + ASSERT(mSwapchain != VK_NULL_HANDLE); - ContextVk *contextVk = vk::GetImpl(context); + VkResult result = VK_ERROR_UNKNOWN; + constexpr uint32_t kMaxAttempts = 2; + for (uint32_t attempt = 1; attempt <= kMaxAttempts; ++attempt) { - // Note: TRACE_EVENT0 is put here instead of inside the function to workaround this issue: - // http://anglebug.com/42261625 - ANGLE_TRACE_EVENT0("gpu.angle", "acquireNextSwapchainImage"); - // Get the next available swapchain image. - VkResult result = acquireNextSwapchainImage(contextVk); + result = acquireNextSwapchainImage(context); + if (result == VK_SUCCESS) + { + break; + } + + // Always invalidate the swapchain in case of the failure. + invalidateSwapchain(context->getRenderer()); ASSERT(result != VK_SUBOPTIMAL_KHR); // If OUT_OF_DATE is returned, it's ok, we just need to recreate the swapchain before // continuing. - if (ANGLE_UNLIKELY(result == VK_ERROR_OUT_OF_DATE_KHR)) + if (ANGLE_UNLIKELY(result != VK_ERROR_OUT_OF_DATE_KHR)) { - ANGLE_TRY(checkForOutOfDateSwapchain(contextVk, true)); - // Try one more time and bail if we fail - result = acquireNextSwapchainImage(contextVk); + break; } - ANGLE_VK_TRY(contextVk, result); - } - // Auto-invalidate the contents of the surface. According to EGL, on swap: - // - // - When EGL_BUFFER_DESTROYED is specified, the contents of the color image can be - // invalidated. - // * This is disabled when buffer age has been queried to work around a dEQP test bug. - // - Depth/Stencil can always be invalidated - // - // In all cases, when in shared present mode, swap is implicit and the swap behavior - // doesn't apply so no invalidation is done. - if (!isSharedPresentMode()) - { - if (mState.swapBehavior == EGL_BUFFER_DESTROYED && mBufferAgeQueryFrameNumber == 0) - { - mSwapchainImages[mCurrentSwapchainImageIndex].image->invalidateSubresourceContent( - contextVk, gl::LevelIndex(0), 0, 1, nullptr); - if (mColorImageMS.valid()) - { - mColorImageMS.invalidateSubresourceContent(contextVk, gl::LevelIndex(0), 0, 1, - nullptr); - } - } - if (mDepthStencilImage.valid()) + // Do not recreate the swapchain if it's the last attempt. + if (attempt < kMaxAttempts) { - mDepthStencilImage.invalidateSubresourceContent(contextVk, gl::LevelIndex(0), 0, 1, - nullptr); - mDepthStencilImage.invalidateSubresourceStencilContent(contextVk, gl::LevelIndex(0), 0, - 1, nullptr); + ANGLE_TRY(prepareSwapchainForAcquireNextImage(context)); } } + ANGLE_VK_TRY(context, result); + return angle::Result::Continue; } @@ -2805,7 +2986,7 @@ bool WindowSurfaceVk::skipAcquireNextSwapchainImageForSharedPresentMode() const ASSERT(mSwapchainImages.size()); const SwapchainImage &image = mSwapchainImages[0]; ASSERT(image.image->valid()); - if (image.image->getCurrentImageLayout() == vk::ImageLayout::SharedPresent) + if (image.image->getCurrentImageAccess() == vk::ImageAccess::SharedPresent) { return true; } @@ -2818,57 +2999,31 @@ bool WindowSurfaceVk::skipAcquireNextSwapchainImageForSharedPresentMode() const // the return value won't be VK_SUBOPTIMAL_KHR. VkResult WindowSurfaceVk::acquireNextSwapchainImage(vk::ErrorContext *context) { - ASSERT(mAcquireOperation.state != impl::ImageAcquireState::Ready); - - // |mSwapchain| may be invalid in case if previous recreate attempt failed. - if (mSwapchain == VK_NULL_HANDLE) - { - return VK_ERROR_OUT_OF_DATE_KHR; - } - - VkDevice device = context->getDevice(); + ANGLE_TRACE_EVENT0("gpu.angle", "acquireNextSwapchainImage"); + ASSERT(mAcquireOperation.state != ImageAcquireState::Ready); + ASSERT(mSwapchain != VK_NULL_HANDLE); + ASSERT(!skipAcquireNextSwapchainImageForSharedPresentMode()); - if (skipAcquireNextSwapchainImageForSharedPresentMode()) - { - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire); - // This will check for OUT_OF_DATE when in single image mode. and prevent - // re-AcquireNextImage. - VkResult result = vkGetSwapchainStatusKHR(device, mSwapchain); - if (ANGLE_UNLIKELY(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)) - { - return result; - } - // Note that an acquire and result processing is no longer needed. - mAcquireOperation.state = impl::ImageAcquireState::Ready; - return VK_SUCCESS; - } + vk::Renderer *renderer = context->getRenderer(); + VkDevice device = renderer->getDevice(); // If calling vkAcquireNextImageKHR is necessary, do so first. - if (mAcquireOperation.state == impl::ImageAcquireState::NeedToAcquire) + if (mAcquireOperation.state == ImageAcquireState::Unacquired) { - AcquireNextImageUnlocked(device, mSwapchain, &mAcquireOperation); + AcquireNextImageUnlocked(device, mSwapchain, &mAcquireOperation, &mSizeState); } // After the above call result is always ready for processing. - return postProcessUnlockedAcquire(context); -} - -VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::ErrorContext *context) -{ - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::NeedToProcessResult); - ASSERT(mSwapchain != VK_NULL_HANDLE); + ASSERT(mAcquireOperation.state == ImageAcquireState::NeedToProcessResult); const VkResult result = mAcquireOperation.unlockedAcquireResult.result; - // VK_SUBOPTIMAL_KHR is ok since we still have an Image that can be presented successfully - if (ANGLE_UNLIKELY(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)) + if (IsImageAcquireFailed(result)) { - // Skip processing the result on failure. Acquire operation will be allowed again after - // possible swapchain recreation caused by this failure. In case if there will be no - // recreation, error will be returned to an app and result will be processed again in the - // possible next EGL/GLES call (where swapchain will be recreated). + ASSERT(mSizeState == SurfaceSizeState::Unresolved); return result; } + ASSERT(mSizeState == SurfaceSizeState::Resolved); mCurrentSwapchainImageIndex = mAcquireOperation.unlockedAcquireResult.imageIndex; ASSERT(!isSharedPresentMode() || mCurrentSwapchainImageIndex == 0); @@ -2890,9 +3045,8 @@ VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::ErrorContext *context) if (isSharedPresentMode()) { ASSERT(image.image->valid() && - image.image->getCurrentImageLayout() != vk::ImageLayout::SharedPresent); - vk::Renderer *renderer = context->getRenderer(); - vk::ScopedPrimaryCommandBuffer scopedCommandBuffer(renderer->getDevice()); + image.image->getCurrentImageAccess() != vk::ImageAccess::SharedPresent); + vk::ScopedPrimaryCommandBuffer scopedCommandBuffer(device); auto protectionType = vk::ConvertProtectionBoolToType(mState.hasProtectedContent()); if (renderer->getCommandBufferOneOff(context, protectionType, &scopedCommandBuffer) == angle::Result::Continue) @@ -2900,9 +3054,12 @@ VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::ErrorContext *context) vk::PrimaryCommandBuffer &primaryCommandBuffer = scopedCommandBuffer.get(); VkSemaphore semaphore; // Note return errors is early exit may leave new Image and Swapchain in unknown state. - image.image->recordWriteBarrierOneOff(renderer, vk::ImageLayout::SharedPresent, + image.image->recordWriteBarrierOneOff(renderer, vk::ImageAccess::SharedPresent, &primaryCommandBuffer, &semaphore); ASSERT(semaphore == acquireImageSemaphore); + + renderer->insertSubmitDebugMarkerInCommandBuffer(primaryCommandBuffer, + QueueSubmitReason::AcquireNextImage); if (primaryCommandBuffer.end() != VK_SUCCESS) { setDesiredSwapInterval(mState.swapInterval); @@ -2917,10 +3074,12 @@ VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::ErrorContext *context) setDesiredSwapInterval(mState.swapInterval); return VK_ERROR_OUT_OF_DATE_KHR; } - mUse.setQueueSerial(queueSerial); + image.image->setQueueSerial(queueSerial); } } + // Note, please add new code that may fail before this comment. + // The semaphore will be waited on in the next flush. mAcquireOperation.unlockedAcquireData.acquireImageSemaphores.next(); @@ -2933,14 +3092,32 @@ VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::ErrorContext *context) nullptr); } - // Notify the owning framebuffer there may be staged updates. - if (image.image->hasStagedUpdatesInAllocatedLevels()) + // Auto-invalidate the contents of the surface. According to EGL, on swap: + // + // - When EGL_BUFFER_DESTROYED is specified, the contents of the color image can be + // invalidated. + // * This is disabled when buffer age has been queried to work around a dEQP test bug. + // - Depth/Stencil is always invalidated before last submission. + // + // In all cases, when in shared present mode, swap is implicit and the swap behavior + // doesn't apply so no invalidation is done. + if (!isSharedPresentMode()) { - onStateChange(angle::SubjectMessage::SwapchainImageChanged); + if (mState.swapBehavior == EGL_BUFFER_DESTROYED && !mIsBufferAgeQueried) + { + image.image->invalidateEntireLevelContent(context, gl::LevelIndex(0)); + if (mColorImageMS.valid()) + { + mColorImageMS.invalidateEntireLevelContent(context, gl::LevelIndex(0)); + } + } } + // Depth buffer (excluding emulated channel) should have been invalidated before the last + // submission of previous frame + ASSERT(!mDepthStencilImage.valid() || !mDepthStencilImage.isVkImageContentDefined()); // Note that an acquire and result processing is no longer needed. - mAcquireOperation.state = impl::ImageAcquireState::Ready; + mAcquireOperation.state = ImageAcquireState::Ready; return VK_SUCCESS; } @@ -3021,60 +3198,120 @@ void WindowSurfaceVk::setSwapInterval(const egl::Display *display, EGLint interv } } -egl::Error WindowSurfaceVk::getUserWidth(const egl::Display *display, EGLint *value) const +angle::Result WindowSurfaceVk::getWindowVisibility(vk::ErrorContext *context, + bool *isVisibleOut) const { - DisplayVk *displayVk = vk::GetImpl(display); + UNIMPLEMENTED(); + return angle::Result::Stop; +} - if (mSurfaceCaps.currentExtent.width == kSurfaceSizedBySwapchain) - { - // Surface has no intrinsic size; use current size. - *value = getWidth(); - return egl::NoError(); - } +SurfaceSizeState WindowSurfaceVk::getSizeState() const +{ + return GetSizeState(mSizeState); +} - VkSurfaceCapabilitiesKHR surfaceCaps; - angle::Result result = getUserExtentsImpl(displayVk, &surfaceCaps); - if (result == angle::Result::Continue) +void WindowSurfaceVk::setSizeState(SurfaceSizeState sizeState) +{ + SetSizeState(&mSizeState, sizeState); +} + +angle::Result WindowSurfaceVk::ensureSizeResolved(const gl::Context *context) +{ + if (getSizeState() == SurfaceSizeState::Resolved) { - // The EGL spec states that value is not written if there is an error - ASSERT(surfaceCaps.currentExtent.width != kSurfaceSizedBySwapchain); - *value = static_cast(surfaceCaps.currentExtent.width); + return angle::Result::Continue; } - return angle::ToEGL(result, EGL_BAD_SURFACE); + ASSERT(mAcquireOperation.state == ImageAcquireState::Unacquired); + + ANGLE_TRY(doDeferredAcquireNextImage(vk::GetImpl(context))); + + ASSERT(mSizeState == SurfaceSizeState::Resolved); + return angle::Result::Continue; } -egl::Error WindowSurfaceVk::getUserHeight(const egl::Display *display, EGLint *value) const +gl::Extents WindowSurfaceVk::getSize() const { - DisplayVk *displayVk = vk::GetImpl(display); + ASSERT(mSizeState == SurfaceSizeState::Resolved); + return gl::Extents(mWidth, mHeight, 1); +} - if (mSurfaceCaps.currentExtent.height == kSurfaceSizedBySwapchain) +egl::Error WindowSurfaceVk::getUserSize(const egl::Display *display, + EGLint *width, + EGLint *height) const +{ + if (getSizeState() == SurfaceSizeState::Resolved) { - // Surface has no intrinsic size; use current size. - *value = getHeight(); + std::lock_guard lock(mSizeMutex); + // Surface size is resolved; use current size. + if (width != nullptr) + { + *width = mWidth; + } + if (height != nullptr) + { + *height = mHeight; + } return egl::NoError(); } - VkSurfaceCapabilitiesKHR surfaceCaps; - angle::Result result = getUserExtentsImpl(displayVk, &surfaceCaps); + VkExtent2D extent; + angle::Result result = getUserExtentsImpl(vk::GetImpl(display), &extent); if (result == angle::Result::Continue) { // The EGL spec states that value is not written if there is an error - ASSERT(surfaceCaps.currentExtent.height != kSurfaceSizedBySwapchain); - *value = static_cast(surfaceCaps.currentExtent.height); + if (width != nullptr) + { + *width = static_cast(extent.width); + } + if (height != nullptr) + { + *height = static_cast(extent.height); + } + return egl::NoError(); } + return angle::ToEGL(result, EGL_BAD_SURFACE); } -angle::Result WindowSurfaceVk::getUserExtentsImpl(DisplayVk *displayVk, - VkSurfaceCapabilitiesKHR *surfaceCaps) const +angle::Result WindowSurfaceVk::getUserExtentsImpl(vk::ErrorContext *context, + VkExtent2D *extentOut) const { - *surfaceCaps = mSurfaceCaps; + if (mIsSurfaceSizedBySwapchain) + { + gl::Extents windowExtents; + ANGLE_TRY(getCurrentWindowSize(context, &windowExtents)); + extentOut->width = windowExtents.width; + extentOut->height = windowExtents.height; + } + else + { + VkSurfaceCapabilitiesKHR surfaceCaps; + ANGLE_VK_TRY(context, + vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + context->getRenderer()->getPhysicalDevice(), mSurface, &surfaceCaps)); + *extentOut = surfaceCaps.currentExtent; + } - // With real prerotation, the surface reports the rotated sizes. With emulated prerotation, - // adjust the window extents to match what real pre-rotation would have reported. - if (Is90DegreeRotation(mEmulatedPreTransform)) + adjustSurfaceExtent(extentOut); + + // Must return current surface size if swapchain recreate will be skipped in the future + // |prepareSwapchainForAcquireNextImage| call. Can't skip recreate if swapchain is already + // invalid. Avoid unnecessary |getWindowVisibility| call if window and surface sizes match. + if (context->getFeatures().avoidInvisibleWindowSwapchainRecreate.enabled && + getSizeState() == SurfaceSizeState::Unresolved) { - std::swap(surfaceCaps->currentExtent.width, surfaceCaps->currentExtent.height); + std::lock_guard lock(mSizeMutex); + if (extentOut->width != static_cast(mWidth) || + extentOut->height != static_cast(mHeight)) + { + bool isWindowVisible = false; + ANGLE_TRY(getWindowVisibility(context, &isWindowVisible)); + if (!isWindowVisible) + { + extentOut->width = mWidth; + extentOut->height = mHeight; + } + } } return angle::Result::Continue; @@ -3100,7 +3337,9 @@ angle::Result WindowSurfaceVk::getCurrentFramebuffer(ContextVk *contextVk, ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled); // FramebufferVk dirty-bit processing should ensure that a new image was acquired. - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::Ready); + ASSERT(mAcquireOperation.state == ImageAcquireState::Ready); + ASSERT(mSizeState == SurfaceSizeState::Resolved); + ASSERT(mSwapchain != VK_NULL_HANDLE); // Track the new fetch mode mFramebufferFetchMode = fetchMode; @@ -3162,13 +3401,13 @@ angle::Result WindowSurfaceVk::initializeContents(const gl::Context *context, { ContextVk *contextVk = vk::GetImpl(context); - if (mAcquireOperation.state != impl::ImageAcquireState::Ready) + if (mAcquireOperation.state != ImageAcquireState::Ready) { // Acquire the next image (previously deferred). Some tests (e.g. // GenerateMipmapWithRedefineBenchmark.Run/vulkan_webgl) cause this path to be taken, // because of dirty-object processing. ANGLE_VK_TRACE_EVENT_AND_MARKER(contextVk, "Initialize Swap Image"); - ANGLE_TRY(doDeferredAcquireNextImage(context, false)); + ANGLE_TRY(doDeferredAcquireNextImage(contextVk)); } ASSERT(mSwapchainImages.size() > 0); @@ -3241,8 +3480,11 @@ angle::Result WindowSurfaceVk::drawOverlay(ContextVk *contextVk, SwapchainImage const vk::ImageView *imageView = nullptr; ANGLE_TRY(image->imageViews.getLevelLayerDrawImageView(contextVk, *image->image, vk::LevelIndex(0), 0, &imageView)); - ANGLE_TRY(overlayVk->onPresent(contextVk, image->image.get(), imageView, - Is90DegreeRotation(getPreTransform()))); + if (overlayVk) + { + ANGLE_TRY(overlayVk->onPresent(contextVk, image->image.get(), imageView, + Is90DegreeRotation(getPreTransform()))); + } return angle::Result::Continue; } @@ -3262,8 +3504,8 @@ egl::Error WindowSurfaceVk::setAutoRefreshEnabled(bool enabled) // We only expose EGL_ANDROID_front_buffer_auto_refresh extension on Android with supported // VK_EXT_swapchain_maintenance1 extension, where current and new present modes expected to be // compatible. Can't use |mCompatiblePresentModes| here to check if this is true because it is - // not thread safe. Instead of the check, ASSERT is added to the |createSwapChain| method where - // |mCompatiblePresentModes| are queried. + // not thread safe. Instead of the check, ASSERT is added to the |queryAndAdjustSurfaceCaps| + // method where |mCompatiblePresentModes| are queried. // Simply change mDesiredSwapchainPresentMode regardless if we are already in single buffer mode // or not, since compatible present modes does not require swapchain recreation. @@ -3286,32 +3528,30 @@ egl::Error WindowSurfaceVk::getBufferAge(const gl::Context *context, EGLint *age } // Image must be already acquired in the |prepareSwap| call. - ASSERT(mAcquireOperation.state != impl::ImageAcquireState::NeedToAcquire); + ASSERT(mAcquireOperation.state != ImageAcquireState::Unacquired); + + if (!mIsBufferAgeQueried) + { + // When the buffer age is queried, we assume the application benefits from the contents + // of the swapchain images staying valid. + // Set a flag in that case before doDeferredAcquireNextImage, which invalidates the + // contents. + ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW, + "Querying age of a surface will make it retain its content"); + + mIsBufferAgeQueried = true; + } // If the result of vkAcquireNextImageKHR is not yet processed, do so now. - if (mAcquireOperation.state == impl::ImageAcquireState::NeedToProcessResult) - { - // In case of shared present mode |doDeferredAcquireNextImageWithUsableSwapchain| must be - // already called in the |prepareSwap| call. - ASSERT(!isSharedPresentMode()); - // Using this method and not |postProcessUnlockedAcquire|, in order to handle possible - // VK_ERROR_OUT_OF_DATE_KHR error and recreate the swapchain, instead of failing. - egl::Error result = - angle::ToEGL(doDeferredAcquireNextImageWithUsableSwapchain(context), EGL_BAD_SURFACE); + if (mAcquireOperation.state == ImageAcquireState::NeedToProcessResult) + { + egl::Error result = angle::ToEGL(doDeferredAcquireNextImage(contextVk), EGL_BAD_SURFACE); if (result.isError()) { return result; } } - if (mBufferAgeQueryFrameNumber == 0) - { - ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW, - "Querying age of a surface will make it retain its content"); - - mBufferAgeQueryFrameNumber = mFrameCount; - } - if (age != nullptr) { if (mState.swapBehavior == EGL_BUFFER_PRESERVED) @@ -3367,6 +3607,11 @@ egl::Error WindowSurfaceVk::setRenderBuffer(EGLint renderBuffer) return egl::NoError(); } +bool WindowSurfaceVk::supportsSingleRenderBuffer() const +{ + return supportsPresentMode(vk::PresentMode::SharedDemandRefreshKHR); +} + egl::Error WindowSurfaceVk::lockSurface(const egl::Display *display, EGLint usageHint, bool preservePixels, @@ -3377,34 +3622,33 @@ egl::Error WindowSurfaceVk::lockSurface(const egl::Display *display, DisplayVk *displayVk = vk::GetImpl(display); - if (mAcquireOperation.state != impl::ImageAcquireState::Ready) + if (mAcquireOperation.state != ImageAcquireState::Ready) { - VkResult result = acquireNextSwapchainImage(displayVk); - if (result != VK_SUCCESS) + angle::Result result = doDeferredAcquireNextImage(displayVk); + if (result != angle::Result::Continue) { - return angle::ToEGL(angle::Result::Stop, EGL_BAD_ACCESS); + return angle::ToEGL(result, EGL_BAD_ACCESS); } } vk::ImageHelper *image = mSwapchainImages[mCurrentSwapchainImageIndex].image.get(); ASSERT(image->valid()); - angle::Result result = - LockSurfaceImpl(displayVk, image, mLockBufferHelper, getWidth(), getHeight(), usageHint, - preservePixels, bufferPtrOut, bufferPitchOut); + angle::Result result = LockSurfaceImpl(displayVk, image, mLockBufferHelper, mWidth, mHeight, + usageHint, preservePixels, bufferPtrOut, bufferPitchOut); return angle::ToEGL(result, EGL_BAD_ACCESS); } egl::Error WindowSurfaceVk::unlockSurface(const egl::Display *display, bool preservePixels) { - ASSERT(mAcquireOperation.state == impl::ImageAcquireState::Ready); + ASSERT(mAcquireOperation.state == ImageAcquireState::Ready); vk::ImageHelper *image = mSwapchainImages[mCurrentSwapchainImageIndex].image.get(); ASSERT(image->valid()); ASSERT(mLockBufferHelper.valid()); - return angle::ToEGL(UnlockSurfaceImpl(vk::GetImpl(display), image, mLockBufferHelper, - getWidth(), getHeight(), preservePixels), + return angle::ToEGL(UnlockSurfaceImpl(vk::GetImpl(display), image, mLockBufferHelper, mWidth, + mHeight, preservePixels), EGL_BAD_ACCESS); } @@ -3431,16 +3675,35 @@ egl::Error WindowSurfaceVk::detachFromFramebuffer(const gl::Context *context, return egl::NoError(); } -EGLint WindowSurfaceVk::getCompressionRate(const egl::Display *display) const +egl::Error WindowSurfaceVk::getCompressionRate(const egl::Display *display, + const gl::Context *context, + EGLint *rate) { + ASSERT(mSwapchain != VK_NULL_HANDLE); ASSERT(!mSwapchainImages.empty()); DisplayVk *displayVk = vk::GetImpl(display); + ContextVk *contextVk = vk::GetImpl(context); vk::Renderer *renderer = displayVk->getRenderer(); + ANGLE_TRACE_EVENT0("gpu.angle", "getCompressionRate"); + ASSERT(renderer->getFeatures().supportsImageCompressionControl.enabled); ASSERT(renderer->getFeatures().supportsImageCompressionControlSwapchain.enabled); + // Image must be already acquired in the |prepareSwap| call. + ASSERT(mAcquireOperation.state != ImageAcquireState::Unacquired); + + // If the result of vkAcquireNextImageKHR is not yet processed, do so now. + if (mAcquireOperation.state == ImageAcquireState::NeedToProcessResult) + { + egl::Error result = angle::ToEGL(doDeferredAcquireNextImage(contextVk), EGL_BAD_SURFACE); + if (result.isError()) + { + return result; + } + } + VkImageSubresource2EXT imageSubresource2 = {}; imageSubresource2.sType = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT; imageSubresource2.imageSubresource.aspectMask = mSwapchainImages[0].image->getAspectFlags(); @@ -3457,7 +3720,41 @@ EGLint WindowSurfaceVk::getCompressionRate(const egl::Display *display) const std::vector eglFixedRates = vk_gl::ConvertCompressionFlagsToEGLFixedRate( compressionProperties.imageCompressionFixedRateFlags, 1); - return eglFixedRates.empty() ? EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT : eglFixedRates[0]; + *rate = + (eglFixedRates.empty() ? EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT : eglFixedRates[0]); + + return egl::NoError(); } +void WindowSurfaceVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) +{ + if (message == angle::SubjectMessage::VkImageChanged) + { + const vk::ResourceUse &use = mDepthStencilImage.getResourceUse(); + + // Free all cached VkFramebuffers + if (isMultiSampled()) + { + mRenderer->collectGarbage(use, &mFramebufferMS); + } + + for (auto &image : mSwapchainImages) + { + if (mFramebufferFetchMode == vk::FramebufferFetchMode::Color) + { + mRenderer->collectGarbage(use, &image.fetchFramebuffer); + } + else + { + mRenderer->collectGarbage(use, &image.framebuffer); + } + } + + // Release ImageViews + mDepthStencilImageViews.release(mRenderer, use); + } + + // Forward the notification to observing class that the staging buffer changed. + onStateChange(angle::SubjectMessage::SubjectChanged); +} } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.h b/src/libANGLE/renderer/vulkan/SurfaceVk.h index a044fce0dcf..a48f1d348ca 100644 --- a/src/libANGLE/renderer/vulkan/SurfaceVk.h +++ b/src/libANGLE/renderer/vulkan/SurfaceVk.h @@ -10,6 +10,7 @@ #ifndef LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_ #define LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_ +#include #include "common/CircularBuffer.h" #include "common/SimpleMutex.h" #include "common/vulkan/vk_headers.h" @@ -34,11 +35,11 @@ class SurfaceVk : public SurfaceImpl, public angle::ObserverInterface, public vk void destroy(const egl::Display *display) override; // We monitor the staging buffer for changes. This handles staged data from outside this class. - void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + virtual void onSubjectStateChange(angle::SubjectIndex index, + angle::SubjectMessage message) override; - // width and height can change with client window resizing - EGLint getWidth() const override; - EGLint getHeight() const override; + // size can change with client window resizing + gl::Extents getSize() const override; EGLint mWidth; EGLint mHeight; @@ -59,7 +60,7 @@ class OffscreenSurfaceVk : public SurfaceVk egl::Error unMakeCurrent(const gl::Context *context) override; const vk::ImageHelper *getColorImage() const { return &mColorAttachment.image; } - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -204,9 +205,9 @@ struct SwapchainImage : angle::NonCopyable enum class ImageAcquireState { - Ready, - NeedToAcquire, + Unacquired, NeedToProcessResult, + Ready, }; // Associated data for a call to vkAcquireNextImageKHR without necessarily holding the share group @@ -252,13 +253,20 @@ struct UnlockedAcquireResult : angle::NonCopyable struct ImageAcquireOperation : angle::NonCopyable { // Initially image needs to be acquired. - ImageAcquireState state = ImageAcquireState::NeedToAcquire; + ImageAcquireState state = ImageAcquireState::Unacquired; // No synchronization is necessary when making the vkAcquireNextImageKHR call since it is ONLY // possible on a thread where Surface is current. UnlockedAcquireData unlockedAcquireData; UnlockedAcquireResult unlockedAcquireResult; }; + +enum class SurfaceSizeState +{ + InvalidSwapchain, + Unresolved, + Resolved, +}; } // namespace impl class WindowSurfaceVk : public SurfaceVk @@ -271,6 +279,7 @@ class WindowSurfaceVk : public SurfaceVk egl::Error initialize(const egl::Display *display) override; + egl::Error makeCurrent(const gl::Context *context) override; egl::Error unMakeCurrent(const gl::Context *context) override; angle::Result getAttachmentRenderTarget(const gl::Context *context, @@ -279,10 +288,11 @@ class WindowSurfaceVk : public SurfaceVk GLsizei samples, FramebufferAttachmentRenderTarget **rtOut) override; egl::Error prepareSwap(const gl::Context *context) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error swapWithDamage(const gl::Context *context, const EGLint *rects, - EGLint n_rects) override; + EGLint n_rects, + SurfaceSwapFeedback *feedback) override; egl::Error postSubBuffer(const gl::Context *context, EGLint x, EGLint y, @@ -297,17 +307,12 @@ class WindowSurfaceVk : public SurfaceVk egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - // Note: windows cannot be resized on Android. The approach requires - // calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR. However, that is - // expensive; and there are troublesome timing issues for other parts of - // ANGLE (which cause test failures and crashes). Therefore, a - // special-Android-only path is created just for the querying of EGL_WIDTH - // and EGL_HEIGHT. - // https://issuetracker.google.com/issues/153329980 - egl::Error getUserWidth(const egl::Display *display, EGLint *value) const override; - egl::Error getUserHeight(const egl::Display *display, EGLint *value) const override; - angle::Result getUserExtentsImpl(DisplayVk *displayVk, - VkSurfaceCapabilitiesKHR *surfaceCaps) const; + // Explicitly resolves surface size to use before state synchronization (e.g. validation). + angle::Result ensureSizeResolved(const gl::Context *context) final; + gl::Extents getSize() const final; + + // Unresolved Surface size until render target is first accessed (e.g. after draw). + egl::Error getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const final; EGLint isPostSubBufferSupported() const override; EGLint getSwapBehavior() const override; @@ -337,18 +342,13 @@ class WindowSurfaceVk : public SurfaceVk egl::Error getBufferAge(const gl::Context *context, EGLint *age) override; egl::Error setRenderBuffer(EGLint renderBuffer) override; + bool supportsSingleRenderBuffer() const override; - bool isSharedPresentMode() const - { - return (mSwapchainPresentMode == vk::PresentMode::SharedDemandRefreshKHR || - mSwapchainPresentMode == vk::PresentMode::SharedContinuousRefreshKHR); - } + bool isSharedPresentMode() const { return IsSharedPresentMode(mSwapchainPresentMode); } bool isSharedPresentModeDesired() const { - vk::PresentMode desiredSwapchainPresentMode = getDesiredSwapchainPresentMode(); - return (desiredSwapchainPresentMode == vk::PresentMode::SharedDemandRefreshKHR || - desiredSwapchainPresentMode == vk::PresentMode::SharedContinuousRefreshKHR); + return IsSharedPresentMode(getDesiredSwapchainPresentMode()); } egl::Error lockSurface(const egl::Display *display, @@ -364,77 +364,96 @@ class WindowSurfaceVk : public SurfaceVk egl::Error detachFromFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) override; - angle::Result onSharedPresentContextFlush(const gl::Context *context); + angle::Result onSharedPresentContextFlush(ContextVk *contextVk); bool hasStagedUpdates() const; void setTimestampsEnabled(bool enabled) override; + egl::Error setPresentationTime(EGLnsecsANDROID time) override; - EGLint getCompressionRate(const egl::Display *display) const override; + egl::Error getCompressionRate(const egl::Display *display, + const gl::Context *context, + EGLint *rate) override; protected: - angle::Result swapImpl(const gl::Context *context, + angle::Result swapImpl(ContextVk *contextVk, const EGLint *rects, EGLint n_rects, - const void *pNextChain); + const void *pNextChain, + SurfaceSwapFeedback *feedback); EGLNativeWindowType mNativeWindowType; VkSurfaceKHR mSurface; - VkSurfaceCapabilitiesKHR mSurfaceCaps; VkBool32 mSupportsProtectedSwapchain; private: - virtual angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) = 0; + // Present modes that are compatible with the current mode. If mDesiredSwapchainPresentMode is + // in this list, mode switch can happen without the need to recreate the swapchain. + // There are currently only 6 possible present modes but vector is bigger for a workaround. + static constexpr uint32_t kCompatiblePresentModesSize = 10; + using CompatiblePresentModes = + angle::FixedVector; + + static bool IsSharedPresentMode(vk::PresentMode presentMode) + { + return (presentMode == vk::PresentMode::SharedDemandRefreshKHR || + presentMode == vk::PresentMode::SharedContinuousRefreshKHR); + } + + virtual angle::Result createSurfaceVk(vk::ErrorContext *context) = 0; virtual angle::Result getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) = 0; + gl::Extents *extentsOut) const = 0; + virtual angle::Result getWindowVisibility(vk::ErrorContext *context, bool *isVisibleOut) const; + + impl::SurfaceSizeState getSizeState() const; + void setSizeState(impl::SurfaceSizeState sizeState); + angle::Result getUserExtentsImpl(vk::ErrorContext *context, VkExtent2D *extentOut) const; vk::PresentMode getDesiredSwapchainPresentMode() const; void setDesiredSwapchainPresentMode(vk::PresentMode presentMode); void setDesiredSwapInterval(EGLint interval); angle::Result initializeImpl(DisplayVk *displayVk, bool *anyMatchesOut); - angle::Result recreateSwapchain(ContextVk *contextVk, const gl::Extents &extents); - angle::Result createSwapChain(vk::ErrorContext *context, const gl::Extents &extents); - angle::Result collectOldSwapchain(ContextVk *contextVk, VkSwapchainKHR swapchain); - angle::Result queryAndAdjustSurfaceCaps(ContextVk *contextVk, - VkSurfaceCapabilitiesKHR *surfaceCaps); - angle::Result checkForOutOfDateSwapchain(ContextVk *contextVk, bool forceRecreate); - angle::Result resizeSwapchainImages(vk::ErrorContext *context, uint32_t imageCount); - void releaseSwapchainImages(ContextVk *contextVk); + // Invalidates the swapchain pointer, releases images, and defers acquire next swapchain image. + void invalidateSwapchain(vk::Renderer *renderer); + angle::Result recreateSwapchain(vk::ErrorContext *context); + angle::Result createSwapChain(vk::ErrorContext *context); + angle::Result collectOldSwapchain(vk::ErrorContext *context, VkSwapchainKHR swapchain); + angle::Result queryAndAdjustSurfaceCaps( + vk::ErrorContext *context, + vk::PresentMode presentMode, + VkSurfaceCapabilitiesKHR *surfaceCapsOut, + CompatiblePresentModes *compatiblePresentModesOut) const; + void adjustSurfaceExtent(VkExtent2D *extent) const; + // This method will invalidate the swapchain (if needed due to present returning OUT_OF_DATE, or + // swap interval changing). Updates the current swapchain present mode. + angle::Result prepareSwapchainForAcquireNextImage(vk::ErrorContext *context); + void createSwapchainImages(uint32_t imageCount); + void releaseSwapchainImages(vk::Renderer *renderer); void destroySwapChainImages(DisplayVk *displayVk); - angle::Result prepareForAcquireNextSwapchainImage(const gl::Context *context, - bool forceSwapchainRecreate); - // Called when a swapchain image whose acquisition was deferred must be acquired. This method - // will recreate the swapchain (if needed due to present returning OUT_OF_DATE, swap interval - // changing, surface size changing etc, by calling prepareForAcquireNextSwapchainImage()) and - // call the doDeferredAcquireNextImageWithUsableSwapchain() method. - angle::Result doDeferredAcquireNextImage(const gl::Context *context, - bool forceSwapchainRecreate); - // Calls acquireNextSwapchainImage() and sets up the acquired image. On some platforms, - // vkAcquireNextImageKHR returns OUT_OF_DATE instead of present, so this function may still - // recreate the swapchain. The main difference with doDeferredAcquireNextImage is that it does - // not check for surface property changes for the purposes of swapchain recreation (because - // that's already done by prepareForAcquireNextSwapchainImage. - angle::Result doDeferredAcquireNextImageWithUsableSwapchain(const gl::Context *context); - // This method calls vkAcquireNextImageKHR() to acquire the next swapchain image or to process - // unlocked ANI result. It is scheduled to be called later by deferAcquireNextImage(). + // Called when a swapchain image whose acquisition was deferred must be acquired or unlocked + // ANI result processed. This method will recreate the swapchain (if needed due to surface size + // changing etc, by calling prepareSwapchainForAcquireNextImage()) and call the + // acquireNextSwapchainImage(). On some platforms, vkAcquireNextImageKHR() returns OUT_OF_DATE + // instead of present, which is also recreates the swapchain. It is scheduled to be called + // later by deferAcquireNextImage(). + angle::Result doDeferredAcquireNextImage(vk::ErrorContext *context); + // This method calls vkAcquireNextImageKHR() to acquire the next swapchain image or processes + // unlocked ANI result, then sets up the acquired image. VkResult acquireNextSwapchainImage(vk::ErrorContext *context); - // Process the result of vkAcquireNextImageKHR. - VkResult postProcessUnlockedAcquire(vk::ErrorContext *context); // This method is called when a swapchain image is presented. It schedules - // acquireNextSwapchainImage() to be called later. + // doDeferredAcquireNextImage() to be called later. void deferAcquireNextImage(); bool skipAcquireNextSwapchainImageForSharedPresentMode() const; - angle::Result computePresentOutOfDate(vk::ErrorContext *context, - VkResult result, - bool *presentOutOfDate); + angle::Result checkSwapchainOutOfDate(vk::ErrorContext *context, VkResult presentResult); angle::Result prePresentSubmit(ContextVk *contextVk, const vk::Semaphore &presentSemaphore); + angle::Result recordPresentLayoutBarrierIfNecessary(ContextVk *contextVk); angle::Result present(ContextVk *contextVk, const EGLint *rects, EGLint n_rects, const void *pNextChain, - bool *presentOutOfDate); + SurfaceSwapFeedback *feedback); angle::Result cleanUpPresentHistory(vk::ErrorContext *context); angle::Result cleanUpOldSwapchains(vk::ErrorContext *context); @@ -445,6 +464,7 @@ class WindowSurfaceVk : public SurfaceVk // not ahead of the frame being rendered by *one* frame. angle::Result throttleCPU(vk::ErrorContext *context, const QueueSerial ¤tSubmitSerial); + void mergeImageResourceUses(); // Finish all GPU operations on the surface angle::Result finish(vk::ErrorContext *context); @@ -461,6 +481,15 @@ class WindowSurfaceVk : public SurfaceVk angle::FormatID getIntendedFormatID(vk::Renderer *renderer); angle::FormatID getActualFormatID(vk::Renderer *renderer); + void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + + bool mIsSurfaceSizedBySwapchain; + + // Atomic is to allow update state without necessarily locking the mSizeMutex. + std::atomic mSizeState; + // Protects mWidth and mHeight against getUserSize() call. + mutable angle::SimpleMutex mSizeMutex; + std::vector mPresentModes; VkSwapchainKHR mSwapchain; // Current swapchain (same as last created or NULL) @@ -476,11 +505,7 @@ class WindowSurfaceVk : public SurfaceVk VkImageCompressionFlagBitsEXT mCompressionFlags; VkImageCompressionFixedRateFlagsEXT mFixedRateFlags; - // Present modes that are compatible with the current mode. If mDesiredSwapchainPresentMode is - // in this list, mode switch can happen without the need to recreate the swapchain. - // There are currently only 6 possible present modes but vector is bigger for a workaround. - static constexpr uint32_t kCompatiblePresentModesSize = 10; - angle::FixedVector mCompatiblePresentModes; + CompatiblePresentModes mCompatiblePresentModes; // A circular buffer that stores the serial of the submission fence of the context on every // swap. The CPU is throttled by waiting for the 2nd previous serial to finish. This should @@ -528,15 +553,21 @@ class WindowSurfaceVk : public SurfaceVk // EGL_EXT_buffer_age: Track frame count. uint64_t mFrameCount; + // EGL_ANDROID_presentation_time: Next frame's id and presentation time + // used for VK_GOOGLE_display_timing. + uint32_t mPresentID; + std::optional mDesiredPresentTime; // EGL_KHR_lock_surface3 vk::BufferHelper mLockBufferHelper; // EGL_KHR_partial_update - uint64_t mBufferAgeQueryFrameNumber; + bool mIsBufferAgeQueried; // GL_EXT_shader_framebuffer_fetch vk::FramebufferFetchMode mFramebufferFetchMode = vk::FramebufferFetchMode::None; + + vk::Renderer *mRenderer; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/SyncVk.cpp b/src/libANGLE/renderer/vulkan/SyncVk.cpp index 0dee4398660..0b59cd6cf11 100644 --- a/src/libANGLE/renderer/vulkan/SyncVk.cpp +++ b/src/libANGLE/renderer/vulkan/SyncVk.cpp @@ -268,7 +268,7 @@ angle::Result SyncHelper::getStatus(ErrorContext *context, ContextVk *contextVk, // be blocked by command buffer recording if another thread calls // CommandPoolAccess::flushRenderPassCommands(), which is against EGL spec where // eglClientWaitSync() should return immediately with timeout == 0. - if (renderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled()) + if (renderer->getFeatures().asyncGarbageCleanup.enabled) { ANGLE_TRY(renderer->checkCompletedCommandsAndCleanup(context)); } @@ -356,6 +356,10 @@ VkResult ExternalFence::getStatus(VkDevice device) const { if (mFenceFdStatus == VK_SUCCESS) { + if (mFenceFd == kInvalidFenceFd) + { + return VK_SUCCESS; + } return SyncWaitFd(mFenceFd, 0, VK_NOT_READY); } return mFence.getStatus(device); @@ -365,6 +369,10 @@ VkResult ExternalFence::wait(VkDevice device, uint64_t timeout) const { if (mFenceFdStatus == VK_SUCCESS) { + if (mFenceFd == kInvalidFenceFd) + { + return VK_SUCCESS; + } return SyncWaitFd(mFenceFd, timeout); } return mFence.wait(device, timeout); @@ -433,7 +441,7 @@ angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int */ // Flush current pending set of commands providing the fence... ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, &mExternalFence, - RenderPassClosureReason::SyncObjectWithFdInit)); + QueueSubmitReason::SyncObjectWithFdInit)); ANGLE_VK_TRY(contextVk, mExternalFence->getFenceFdStatus()); @@ -465,7 +473,7 @@ angle::Result SyncHelperNativeFence::prepareForClientWait(ErrorContext *context, if (flushCommands && contextVk) { ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, nullptr, - RenderPassClosureReason::SyncObjectClientWait)); + QueueSubmitReason::SyncObjectClientWait)); } *resultOut = VK_INCOMPLETE; @@ -521,7 +529,7 @@ angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk) DeviceScoped waitSemaphore(device); // Wait semaphore for next vkQueueSubmit(). // Create a Semaphore with imported fenceFd. - ANGLE_VK_TRY(contextVk, waitSemaphore.get().init(device)); + ANGLE_VK_TRY(contextVk, waitSemaphore.get().init(device, VK_SEMAPHORE_TYPE_BINARY)); VkImportSemaphoreFdInfoKHR importFdInfo = {}; importFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR; diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp index d82335d8586..ae8f8e1f439 100644 --- a/src/libANGLE/renderer/vulkan/TextureVk.cpp +++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for TextureVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/TextureVk.h" #include @@ -34,14 +38,11 @@ namespace rx { namespace { -constexpr VkImageUsageFlags kTransferImageFlags = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - constexpr VkImageUsageFlags kColorAttachmentImageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; constexpr VkImageUsageFlags kDrawStagingImageFlags = - kTransferImageFlags | kColorAttachmentImageFlags; + vk::kImageUsageTransferBits | kColorAttachmentImageFlags; constexpr VkFormatFeatureFlags kBlitFeatureFlags = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; @@ -285,11 +286,11 @@ void Set3DBaseArrayLayerAndLayerCount(VkImageSubresourceLayers *Subresource) const vk::Format *AdjustStorageViewFormatPerWorkarounds(vk::Renderer *renderer, const vk::Format *intended, - vk::ImageAccess access) + vk::ImageFormatSupport formatSupport) { // r32f images are emulated with r32ui. if (renderer->getFeatures().emulateR32fImageAtomicExchange.enabled && - intended->getActualImageFormatID(access) == angle::FormatID::R32_FLOAT) + intended->getActualImageFormatID(formatSupport) == angle::FormatID::R32_FLOAT) { return &renderer->getFormat(angle::FormatID::R32_UINT); } @@ -501,8 +502,8 @@ GLint GetFormatSupportedCompressionRates(vk::Renderer *renderer, renderer, vk::GetVkFormatFromFormatID(renderer, format.getActualRenderableImageFormatID()), VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &compressionInfo, &compressionProp, vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess)) { @@ -557,7 +558,7 @@ TextureVk::TextureVk(const gl::TextureState &state, vk::Renderer *renderer) : TextureImpl(state), mOwnsImage(false), mRequiresMutableStorage(false), - mRequiredImageAccess(vk::ImageAccess::SampleOnly), + mRequiredFormatSupport(vk::ImageFormatSupport::SampleOnly), mImmutableSamplerDirty(false), mEGLImageNativeType(gl::TextureType::InvalidEnum), mEGLImageLayerOffset(0), @@ -711,9 +712,13 @@ angle::Result TextureVk::setImageImpl(const gl::Context *context, unpackBuffer, pixels, vkFormat); } -bool TextureVk::isFastUnpackPossible(const vk::Format &vkFormat, +bool TextureVk::isFastUnpackPossible(const gl::Box &area, + GLuint rowLengthPixels, + GLuint imageHeightPixels, + const vk::Format &vkFormat, size_t offset, - const vk::Format &bufferVkFormat) const + const vk::Format &bufferVkFormat, + GLenum type) const { // Conditions to determine if fast unpacking is possible // 1. Image must be well defined to unpack directly to it @@ -725,21 +730,34 @@ bool TextureVk::isFastUnpackPossible(const vk::Format &vkFormat, // to emulated depth/stencil. // 4. vkCmdCopyBufferToImage requires byte offset to be a multiple of 4. // 5. Actual texture format and intended buffer format must match for color formats - const angle::Format &bufferFormat = vkFormat.getActualBufferFormat(false); + // 6. rowLengthPixels must not smaller than the width of the copy area. + // 7. imageHeight must not smaller than the height of the copy area. + // 8. Don't need conversion to load Texture. + + if (!mImage->valid()) + { + return false; + } + const angle::Format &bufferFormat = vkFormat.getActualBufferFormat(); const bool isCombinedDepthStencil = bufferFormat.hasDepthAndStencilBits(); const bool isDepthXorStencil = bufferFormat.hasDepthOrStencilBits() && !isCombinedDepthStencil; const bool isCompatibleDepth = vkFormat.getIntendedFormat().depthBits == bufferFormat.depthBits; const VkDeviceSize imageCopyAlignment = vk::GetImageCopyBufferAlignment(mImage->getActualFormatID()); const bool formatsMatch = bufferFormat.hasDepthOrStencilBits() || - (vkFormat.getActualImageFormatID(getRequiredImageAccess()) == + (vkFormat.getActualImageFormatID(getRequiredFormatSupport()) == bufferVkFormat.getIntendedFormatID()); + const bool overlapRow = rowLengthPixels < static_cast(area.width); + const bool overlapImage = imageHeightPixels < static_cast(area.height); + const bool needConversion = + vkFormat.getTextureLoadFunction(getRequiredFormatSupport(), type).requiresConversion; - return mImage->valid() && !isCombinedDepthStencil && + return !isCombinedDepthStencil && (vkFormat.getIntendedFormatID() == - vkFormat.getActualImageFormatID(getRequiredImageAccess()) || + vkFormat.getActualImageFormatID(getRequiredFormatSupport()) || (isDepthXorStencil && isCompatibleDepth)) && - (offset % imageCopyAlignment) == 0 && formatsMatch; + (offset % imageCopyAlignment) == 0 && formatsMatch && !overlapRow && !overlapImage && + !needConversion; } bool TextureVk::isMipImageDescDefined(gl::TextureTarget textureTarget, size_t level) @@ -975,18 +993,26 @@ angle::Result TextureVk::clearSubImageImpl(const gl::Context *context, bool usesBufferForClear = false; - VkFormatFeatureFlags renderableCheckFlag = + const VkFormatFeatureFlags clearUpdateRequiredFeature = clearMode == vk::ClearTextureMode::FullClear ? VK_FORMAT_FEATURE_TRANSFER_DST_BIT : outputFormatInfo.isDepthOrStencil() ? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - if (vk::FormatHasNecessaryFeature(contextVk->getRenderer(), outputActualFormatID, - getTilingMode(), renderableCheckFlag)) + const VkImageUsageFlags clearUpdateRequiredUsage = + clearMode == vk::ClearTextureMode::FullClear ? VK_IMAGE_USAGE_TRANSFER_DST_BIT + : outputFormatInfo.isDepthOrStencil() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + const bool formatFeaturesAllowClearUpdate = + vk::FormatHasNecessaryFeature(contextVk->getRenderer(), outputActualFormatID, + getTilingMode(), clearUpdateRequiredFeature); + const bool imageUsageAllowsClearUpdate = + (mImageUsageFlags & clearUpdateRequiredUsage) == clearUpdateRequiredUsage; + if (formatFeaturesAllowClearUpdate && imageUsageAllowsClearUpdate) { uint32_t baseLayer = useLayerAsDepth ? clearArea.z : 0; uint32_t layerCount = useLayerAsDepth ? clearArea.depth : 1; ANGLE_TRY(mImage->stagePartialClear(contextVk, clearArea, clearMode, mState.getType(), level, baseLayer, layerCount, type, inputFormatInfo, - inputVkFormat, getRequiredImageAccess(), data)); + inputVkFormat, getRequiredFormatSupport(), data)); } else { @@ -1035,7 +1061,7 @@ angle::Result TextureVk::clearSubImageImpl(const gl::Context *context, contextVk, getNativeImageIndex(index), gl::Extents(clearArea.width, clearArea.height, 1), gl::Offset(clearArea.x, clearArea.y, 0), inputFormatInfo, pixelUnpackState, - type, clearBuffer.data(), outputVkFormat, getRequiredImageAccess(), + type, clearBuffer.data(), outputVkFormat, getRequiredFormatSupport(), vk::ApplyImageUpdate::Defer, &updateAppliedImmediately)); ASSERT(!updateAppliedImmediately); } @@ -1052,7 +1078,8 @@ angle::Result TextureVk::clearSubImageImpl(const gl::Context *context, gl::Extents(clearArea.width, clearArea.height, clearArea.depth), gl::Offset(clearArea.x, clearArea.y, clearArea.z), inputFormatInfo, pixelUnpackState, type, clearBuffer.data(), outputVkFormat, - getRequiredImageAccess(), vk::ApplyImageUpdate::Defer, &updateAppliedImmediately)); + getRequiredFormatSupport(), vk::ApplyImageUpdate::Defer, + &updateAppliedImmediately)); ASSERT(!updateAppliedImmediately); } } @@ -1072,20 +1099,27 @@ angle::Result TextureVk::ensureImageInitializedIfUpdatesNeedStageOrFlush( bool usesBufferForUpdate) { bool mustFlush = - updateMustBeFlushed(level, vkFormat.getActualImageFormatID(getRequiredImageAccess())); + updateMustBeFlushed(level, vkFormat.getActualImageFormatID(getRequiredFormatSupport())); bool mustStage = applyUpdate == vk::ApplyImageUpdate::Defer; + const bool canFlushStagedUpdates = + !mustStage && mImage->valid() && mImage->hasBufferSourcedStagedUpdatesInAllLevels(); + // If texture has all levels being specified, then do the flush immediately. This tries to avoid // issue flush as each level is being provided which may end up flushing out the staged clear // that otherwise might able to be removed. It also helps tracking all updates with just one // VkEvent instead of one for each level. - if (mustFlush || - (!mustStage && mImage->valid() && mImage->hasBufferSourcedStagedUpdatesInAllLevels())) + if (mustFlush || canFlushStagedUpdates) { ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); - // If forceSubmitImmutableTextureUpdates is enabled, submit the staged updates as well. - if (contextVk->getFeatures().forceSubmitImmutableTextureUpdates.enabled) + // To handle use cases where shared resources are not properly synchronized between multiple + // contexts, forceSubmitImmutableTextureUpdates submits the staged updates to force + // synchronization. This is limited to cases where the resource is an immutable texture and + // there are multiple active shared contexts. + if (canFlushStagedUpdates && contextVk->getShareGroup()->getContexts().size() > 1 && + mState.getImmutableFormat() && + contextVk->getFeatures().forceSubmitImmutableTextureUpdates.enabled) { ANGLE_TRY(contextVk->submitStagedTextureUpdates()); } @@ -1100,6 +1134,78 @@ angle::Result TextureVk::ensureImageInitializedIfUpdatesNeedStageOrFlush( return angle::Result::Continue; } +angle::Result TextureVk::ghostOnOverwrite(ContextVk *contextVk, + const gl::ImageIndex &index, + const gl::Box &area) +{ + // If the texture's image is in use by the GPU but is overwritten completely, release the old + // image and create a fresh one. If the texture was used in a render pass, this avoids breaking + // the render pass. Otherwise, it allows the new image to be initialized with + // VK_EXT_host_image_copy functionality. In the very least, an unnecessary ?->Transfer barrier + // is avoided. + + // Can't ghost the image if it's not owned by this texture. For simplicity, also don't ghost + // images if it's the target of an EGL image; this avoids the need to have to get the image + // siblings to sync their ImageHelper pointers (http://anglebug.com/410584007). This limitation + // can likely be more easily lifted once http://anglebug.com/352005188 is implemented. + // + // If the allocateNonZeroMemory feature is enabled, the image's memory is going to be + // initialized which puts the image back in GPU use so there's no point in ghosting the image + // either. + vk::Renderer *renderer = contextVk->getRenderer(); + if (!mOwnsImage || mImage == nullptr || !mImage->valid() || mImage->isForeignImage() || + mState.hasBeenBoundAsSourceOfEglImage() || mState.isExternalMemoryTexture() || + renderer->getFeatures().allocateNonZeroMemory.enabled) + { + return angle::Result::Continue; + } + + // Only ghost the image if it's in use by the GPU. + if (renderer->hasResourceUseFinished(mImage->getResourceUse())) + { + return angle::Result::Continue; + } + + // Size check: Can only ghost the image if the area being overwritten covers the entire image. + // + // As a targeted optimization, only limit to non-array 2D color textures. Other texture types + // can be very easily added if need, but need additional tests similar to those that have landed + // in http://anglebug.com/42265356 for 2D textures. + const gl::LevelIndex overwriteLevel = gl::LevelIndex(index.getLevelIndex()); + const gl::LevelIndex imageLevel = mImage->getFirstAllocatedLevel(); + + const bool is2DImage = mImage->getLevelCount() == 1 && mImage->getLayerCount() == 1 && + mImage->getType() == VK_IMAGE_TYPE_2D; + const bool is2DUpdate = mState.getType() == gl::TextureType::_2D && index.getLayerCount() == 1; + const bool isWholeArea = area.x == 0 && area.y == 0 && area.z == 0 && + mImage->getExtents().width == static_cast(area.width) && + mImage->getExtents().height == static_cast(area.height) && + mImage->getExtents().depth == static_cast(area.depth); + const bool isColor = mImage->getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT; + + if (!is2DImage || !is2DUpdate || overwriteLevel != imageLevel || !isWholeArea || !isColor) + { + return angle::Result::Continue; + } + + const vk::Format &format = getBaseLevelFormat(renderer); + + // Since the entire image is being overwritten, there's no reason to keep the previous contents + // of the image around. Just start over with a completely new image; data is about to be + // uploaded to it. + releaseImage(contextVk); + ANGLE_TRY(ensureImageAllocated(contextVk, format)); + ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(), + format.getActualImageFormatID(getRequiredFormatSupport()), + ImageMipLevels::EnabledLevels)); + + // The new image is now ready to be used with no dependency to the texture's previous use. Note + // that |releaseimage| already includes a notification to observers that the image has changed. + ASSERT(renderer->hasResourceUseFinished(mImage->getResourceUse())); + + return angle::Result::Continue; +} + angle::Result TextureVk::setSubImageImpl(const gl::Context *context, const gl::ImageIndex &index, const gl::Box &area, @@ -1112,8 +1218,11 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context, { ContextVk *contextVk = vk::GetImpl(context); - bool mustStage = updateMustBeStaged(gl::LevelIndex(index.getLevelIndex()), - vkFormat.getActualImageFormatID(getRequiredImageAccess())); + ANGLE_TRY(ghostOnOverwrite(contextVk, index, area)); + + bool mustStage = + updateMustBeStaged(gl::LevelIndex(index.getLevelIndex()), + vkFormat.getActualImageFormatID(getRequiredFormatSupport())); vk::ApplyImageUpdate applyUpdate; if (mustStage) @@ -1162,24 +1271,25 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context, const vk::Format &bufferVkFormat = contextVk->getRenderer()->getFormat(formatInfo.sizedInternalFormat); - if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), - vkFormat.getActualImageFormatID(getRequiredImageAccess())) && - isFastUnpackPossible(vkFormat, offsetBytes, bufferVkFormat)) + GLuint pixelSize = formatInfo.pixelBytes; + GLuint blockWidth = formatInfo.compressedBlockWidth; + GLuint blockHeight = formatInfo.compressedBlockHeight; + if (!formatInfo.compressed) { - GLuint pixelSize = formatInfo.pixelBytes; - GLuint blockWidth = formatInfo.compressedBlockWidth; - GLuint blockHeight = formatInfo.compressedBlockHeight; - if (!formatInfo.compressed) - { - pixelSize = formatInfo.computePixelBytes(type); - blockWidth = 1; - blockHeight = 1; - } - ASSERT(pixelSize != 0 && inputRowPitch != 0 && blockWidth != 0 && blockHeight != 0); + pixelSize = formatInfo.computePixelBytes(type); + blockWidth = 1; + blockHeight = 1; + } + ASSERT(pixelSize != 0 && inputRowPitch != 0 && blockWidth != 0 && blockHeight != 0); - GLuint rowLengthPixels = inputRowPitch / pixelSize * blockWidth; - GLuint imageHeightPixels = inputDepthPitch / inputRowPitch * blockHeight; + GLuint rowLengthPixels = inputRowPitch / pixelSize * blockWidth; + GLuint imageHeightPixels = inputDepthPitch / inputRowPitch * blockHeight; + if ((shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), + vkFormat.getActualImageFormatID(getRequiredFormatSupport()))) && + isFastUnpackPossible(area, rowLengthPixels, imageHeightPixels, vkFormat, offsetBytes, + bufferVkFormat, type)) + { ANGLE_TRY(copyBufferDataToImage(contextVk, &bufferHelper, index, rowLengthPixels, imageHeightPixels, area, offsetBytes, aspectFlags)); } @@ -1192,7 +1302,7 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context, void *mapPtr = nullptr; - ANGLE_TRY(unpackBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &mapPtr)); + ANGLE_TRY(unpackBufferVk->mapForReadAccessOnly(contextVk, &mapPtr)); const uint8_t *source = static_cast(mapPtr) + reinterpret_cast(pixels); @@ -1201,10 +1311,10 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context, contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth), gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, source, vkFormat, - getRequiredImageAccess(), inputRowPitch, inputDepthPitch, inputSkipBytes, + getRequiredFormatSupport(), inputRowPitch, inputDepthPitch, inputSkipBytes, applyUpdate, &updateAppliedImmediately)); - ANGLE_TRY(unpackBufferVk->unmapImpl(contextVk)); + ANGLE_TRY(unpackBufferVk->unmapReadAccessOnly(contextVk)); } } else if (pixels) @@ -1212,7 +1322,7 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context, ANGLE_TRY(mImage->stageSubresourceUpdate( contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth), gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels, vkFormat, - getRequiredImageAccess(), applyUpdate, &updateAppliedImmediately)); + getRequiredFormatSupport(), applyUpdate, &updateAppliedImmediately)); } if (updateAppliedImmediately) @@ -1245,9 +1355,6 @@ angle::Result TextureVk::copyImage(const gl::Context *context, // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|). ANGLE_TRY(ensureRenderableIfCopyTexImageCannotTransfer(contextVk, internalFormatInfo, source)); - // The texture level being redefined might be the same as the one bound to the framebuffer. - // This _could_ be supported by using a temp image before redefining the level (and potentially - // discarding the image). However, this is currently unimplemented. FramebufferVk *framebufferVk = vk::GetImpl(source); RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget(); vk::ImageHelper *srcImage = &colorReadRT->getImageForCopy(); @@ -1259,11 +1366,97 @@ angle::Result TextureVk::copyImage(const gl::Context *context, const bool isSelfCopy = mImage == srcImage && levelIndex == colorReadRT->getLevelIndex() && redefinedFace == sourceFace; + // The texture level being redefined might be the same as the one bound to the framebuffer. + // In that case, snapshot the source image first, then redefine, then copy from the snapshot. + vk::RendererScoped sourceImageCopy(renderer); + gl::Rectangle clippedSourceArea; + gl::Offset modifiedDestOffset(0, 0, 0); + bool hasCopyArea = false; + + if (isSelfCopy) + { + gl::Extents fbSize = source->getReadColorAttachment()->getSize(); + hasCopyArea = ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &clippedSourceArea); + + if (hasCopyArea) + { + modifiedDestOffset = gl::Offset(clippedSourceArea.x - sourceArea.x, + clippedSourceArea.y - sourceArea.y, 0); + + // Make sure the source image exists and any updates are already flushed. + ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); + + ANGLE_TRY(sourceImageCopy.get().init2DStaging( + contextVk, mState.hasProtectedContent(), + gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), + srcImage->getIntendedFormatID(), srcImage->getActualFormatID(), + vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT, 1)); + + vk::CommandResources resources; + resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, + &sourceImageCopy.get()); + + vk::OutsideRenderPassCommandBuffer *commandBuffer; + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); + + gl::Offset srcOffset(clippedSourceArea.x, clippedSourceArea.y, 0); + gl::Extents copyExtents(clippedSourceArea.width, clippedSourceArea.height, 1); + + VkImageSubresourceLayers srcSubresource = {}; + srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srcSubresource.mipLevel = srcImage->toVkLevel(colorReadRT->getLevelIndex()).get(); + srcSubresource.baseArrayLayer = sourceFace; + srcSubresource.layerCount = 1; + + if (srcImage->getExtents().depth > 1) + { + Set3DBaseArrayLayerAndLayerCount(&srcSubresource); + srcOffset.z = static_cast(colorReadRT->getLayerIndex()); + } + + VkImageSubresourceLayers destSubresource = {}; + destSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + destSubresource.mipLevel = 0; + destSubresource.baseArrayLayer = 0; + destSubresource.layerCount = 1; + + vk::ImageHelper::Copy(renderer, srcImage, &sourceImageCopy.get(), srcOffset, + gl::kOffsetZero, copyExtents, srcSubresource, destSubresource, + commandBuffer); + } + } + ANGLE_TRY(redefineLevel(context, index, vkFormat, newImageSize)); if (isSelfCopy) { - UNIMPLEMENTED(); + if (!hasCopyArea) + { + return angle::Result::Continue; + } + + // Use a draw copy for format conversion. + ANGLE_TRY( + contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy)); + + vk::DeviceScoped sourceCopyView(contextVk->getDevice()); + gl::TextureType sourceCopyTextureType = + vk::Get2DTextureType(1, sourceImageCopy.get().getSamples()); + ANGLE_TRY(sourceImageCopy.get().initLayerImageView( + contextVk, sourceCopyTextureType, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), + &sourceCopyView.get(), vk::LevelIndex(0), 1, 0, 1)); + + ANGLE_TRY(copySubImageImplWithDraw( + contextVk, index, modifiedDestOffset, vkFormat, gl::LevelIndex(0), + gl::Box(gl::kOffsetZero, + gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1)), + false, false, false, false, &sourceImageCopy.get(), &sourceCopyView.get(), + SurfaceRotation::Identity)); + + vk::ImageView sourceCopyViewObject = sourceCopyView.release(); + contextVk->addGarbage(&sourceCopyViewObject); return angle::Result::Continue; } @@ -1465,7 +1658,8 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, const vk::Format &dstFormat = renderer->getFormat(internalFormat.sizedInternalFormat); angle::FormatID dstIntendedFormatID = dstFormat.getIntendedFormatID(); - angle::FormatID dstActualFormatID = dstFormat.getActualImageFormatID(getRequiredImageAccess()); + angle::FormatID dstActualFormatID = + dstFormat.getActualImageFormatID(getRequiredFormatSupport()); VkImageTiling destTilingMode = getTilingMode(); bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO(); @@ -1514,7 +1708,7 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, ANGLE_TRY(mImage->stageSubresourceUpdateFromFramebuffer( context, offsetImageIndex, clippedSourceArea, modifiedDestOffset, gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat, - getRequiredImageAccess(), framebufferVk)); + getRequiredFormatSupport(), framebufferVk)); // Flush out staged update if possible if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstActualFormatID)) @@ -1540,7 +1734,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, const angle::Format &srcIntendedFormat = source->getImage().getIntendedFormat(); const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat); - angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredImageAccess()); + angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredFormatSupport()); VkImageTiling dstTilingMode = getTilingMode(); const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index); @@ -1577,12 +1771,12 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, vk::RendererScoped bufferHelper(renderer); uint8_t *sourceData = nullptr; ANGLE_TRY(source->copyImageDataToBufferAndGetData( - contextVk, sourceLevelGL, sourceBox.depth, sourceBox, - RenderPassClosureReason::CopyTextureOnCPU, &bufferHelper.get(), &sourceData)); + contextVk, sourceLevelGL, sourceBox.depth, sourceBox, QueueSubmitReason::CopyTextureOnCPU, + &bufferHelper.get(), &sourceData)); const angle::Format &srcTextureFormat = source->getImage().getActualFormat(); const angle::Format &dstTextureFormat = - dstVkFormat.getActualImageFormat(getRequiredImageAccess()); + dstVkFormat.getActualImageFormat(getRequiredFormatSupport()); size_t destinationAllocationSize = sourceBox.width * sourceBox.height * sourceBox.depth * dstTextureFormat.pixelBytes; @@ -1668,8 +1862,8 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, gl::Extents extents = {sourceBox.width, sourceBox.height, sourceBox.depth}; // Change source layout if necessary - vk::CommandBufferAccess access; - access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage); + vk::CommandResources resources; + resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage); VkImageSubresourceLayers srcSubresource = {}; srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -1702,17 +1896,18 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, bool isSelfCopy = mImage == srcImage; // If destination is valid, copy the source directly into it. - if (shouldUpdateBeFlushed(level, dstFormat.getActualImageFormatID(getRequiredImageAccess())) && + if (shouldUpdateBeFlushed(level, + dstFormat.getActualImageFormatID(getRequiredFormatSupport())) && !isSelfCopy) { // Make sure any updates to the image are already flushed. ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); - access.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT, - mImage); + resources.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT, + mImage); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); VkImageSubresourceLayers destSubresource = srcSubresource; destSubresource.mipLevel = mImage->toVkLevel(level).get(); @@ -1740,16 +1935,16 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, stagingImage = std::make_unique>(); ANGLE_TRY(stagingImage->get().init2DStaging( - contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(), + contextVk, mState.hasProtectedContent(), gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(), - dstFormat.getActualImageFormatID(getRequiredImageAccess()), kTransferImageFlags, - layerCount)); + dstFormat.getActualImageFormatID(getRequiredFormatSupport()), + vk::kImageUsageTransferBits, layerCount)); - access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, VK_IMAGE_ASPECT_COLOR_BIT, - &stagingImage->get()); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, + VK_IMAGE_ASPECT_COLOR_BIT, &stagingImage->get()); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); VkImageSubresourceLayers destSubresource = srcSubresource; destSubresource.mipLevel = 0; @@ -1792,7 +1987,6 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, const vk::ImageView *srcView, SurfaceRotation srcFramebufferRotation) { - vk::Renderer *renderer = contextVk->getRenderer(); UtilsVk &utilsVk = contextVk->getUtils(); // Potentially make adjustments for pre-rotation. @@ -1837,14 +2031,14 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, gl::LevelIndex level(index.getLevelIndex()); - UtilsVk::CopyImageParameters params; + UtilsVk::CopyImageParameters params = {}; params.srcOffset[0] = rotatedSourceBox.x; params.srcOffset[1] = rotatedSourceBox.y; params.srcExtents[0] = rotatedSourceBox.width; params.srcExtents[1] = rotatedSourceBox.height; params.dstOffset[0] = dstOffset.x; params.dstOffset[1] = dstOffset.y; - params.srcMip = srcImage->toVkLevel(sourceLevelGL).get(); + params.srcMip = srcImage->toVkLevel(sourceLevelGL); params.srcSampleCount = srcImage->getSamples(); params.srcHeight = srcExtents.height; params.dstMip = level; @@ -1873,7 +2067,8 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, .colorEncoding; // If destination is valid, copy the source directly into it. - if (shouldUpdateBeFlushed(level, dstFormat.getActualImageFormatID(getRequiredImageAccess())) && + if (shouldUpdateBeFlushed(level, + dstFormat.getActualImageFormatID(getRequiredFormatSupport())) && !isSelfCopy) { // Make sure any updates to the image are already flushed. @@ -1900,9 +2095,9 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, stagingImage = std::make_unique>(); ANGLE_TRY(stagingImage->get().init2DStaging( - contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(), + contextVk, mState.hasProtectedContent(), gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(), - dstFormat.getActualImageFormatID(getRequiredImageAccess()), kDrawStagingImageFlags, + dstFormat.getActualImageFormatID(getRequiredFormatSupport()), kDrawStagingImageFlags, layerCount)); params.dstOffset[0] = 0; @@ -1992,7 +2187,7 @@ angle::Result TextureVk::setStorageImpl(ContextVk *contextVk, ASSERT(mState.getImmutableFormat()); ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels)); ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(), - format.getActualImageFormatID(getRequiredImageAccess()), + format.getActualImageFormatID(getRequiredFormatSupport()), ImageMipLevels::FullMipChainForGenerateMipmap)); return angle::Result::Continue; @@ -2066,7 +2261,7 @@ angle::Result TextureVk::setStorageExternalMemory(const gl::Context *context, kColorAttachmentImageFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; if ((usageFlags & kRenderableUsageFlags) != 0) { - mRequiredImageAccess = vk::ImageAccess::Renderable; + mRequiredFormatSupport = vk::ImageFormatSupport::Renderable; } ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount())); @@ -2100,7 +2295,7 @@ GLint TextureVk::getImageCompressionRate(const gl::Context *context) if (!mOwnsImage) { - return 0; + return GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT; } VkImageSubresource2EXT imageSubresource2 = {}; @@ -2266,7 +2461,7 @@ void TextureVk::releaseAndDeleteImageAndViews(ContextVk *contextVk) releaseImage(contextVk); mImageObserverBinding.bind(nullptr); mRequiresMutableStorage = false; - mRequiredImageAccess = vk::ImageAccess::SampleOnly; + mRequiredFormatSupport = vk::ImageFormatSupport::SampleOnly; mImageCreateFlags = 0; SafeDelete(mImage); } @@ -2287,14 +2482,18 @@ void TextureVk::releaseAndDeleteImageAndViews(ContextVk *contextVk) onStateChange(angle::SubjectMessage::SubjectChanged); } mRedefinedLevels = {}; + + ASSERT(mDescriptorSetCacheManager.allValidEntriesAreCached(contextVk)); mDescriptorSetCacheManager.releaseKeys(contextVk->getRenderer()); } -void TextureVk::initImageUsageFlags(ContextVk *contextVk, angle::FormatID actualFormatID) +void TextureVk::initImageUsageFlags(ContextVk *contextVk, + const angle::Format &intendedFormat, + angle::FormatID actualFormatID) { ASSERT(actualFormatID != angle::FormatID::NONE); - mImageUsageFlags = kTransferImageFlags | VK_IMAGE_USAGE_SAMPLED_BIT; + mImageUsageFlags = vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT; // If the image has depth/stencil support, add those as possible usage. vk::Renderer *renderer = contextVk->getRenderer(); @@ -2316,7 +2515,14 @@ void TextureVk::initImageUsageFlags(ContextVk *contextVk, angle::FormatID actual else if (renderer->hasImageFormatFeatureBits(actualFormatID, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) { - mImageUsageFlags |= kColorAttachmentImageFlags; + // If the intended format is not renderable, don't add color attachment flags even if the + // fallback format is. This way, the image is more likely to be usable with + // VK_EXT_host_image_copy. + if (!intendedFormat.isLUMA() || + mRequiredFormatSupport == vk::ImageFormatSupport::Renderable) + { + mImageUsageFlags |= kColorAttachmentImageFlags; + } } } @@ -2328,7 +2534,8 @@ angle::Result TextureVk::ensureImageAllocated(ContextVk *contextVk, const vk::Fo {}); } - initImageUsageFlags(contextVk, format.getActualImageFormatID(getRequiredImageAccess())); + initImageUsageFlags(contextVk, format.getIntendedFormat(), + format.getActualImageFormatID(getRequiredFormatSupport())); return angle::Result::Continue; } @@ -2352,7 +2559,7 @@ void TextureVk::setImageHelper(ContextVk *contextVk, // don't know if other container object will render or not. if (!mOwnsImage && !imageHelper->isBackedByExternalMemory()) { - mRequiredImageAccess = vk::ImageAccess::Renderable; + mRequiredFormatSupport = vk::ImageFormatSupport::Renderable; } mEGLImageNativeType = eglImageNativeType; mEGLImageLevelOffset = imageLevelOffset; @@ -2423,7 +2630,7 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context, TextureLevelDefinition levelDefinition = IsTextureLevelDefinitionCompatibleWithImage( *mImage, levelIndexGL, size, format.getIntendedFormatID(), - format.getActualImageFormatID(getRequiredImageAccess())) + format.getActualImageFormatID(getRequiredFormatSupport())) ? TextureLevelDefinition::Compatible : TextureLevelDefinition::Incompatible; if (TextureRedefineLevel(levelAllocation, levelDefinition, mState.getImmutableFormat(), @@ -2448,7 +2655,7 @@ angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk, gl::LevelIndex sourceLevelGL, uint32_t layerCount, const gl::Box &sourceArea, - RenderPassClosureReason reason, + QueueSubmitReason reason, vk::BufferHelper *copyBuffer, uint8_t **outDataPtr) { @@ -2531,12 +2738,13 @@ angle::Result TextureVk::copyBufferDataToImage(ContextVk *contextVk, // Make sure the source is initialized and its images are flushed. ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); - vk::CommandBufferAccess access; - access.onBufferTransferRead(srcBuffer); - access.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(), mImage); + vk::CommandResources resources; + resources.onBufferTransferRead(srcBuffer); + resources.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(), + mImage); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); commandBuffer->copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(), mImage->getCurrentLayout(contextVk->getRenderer()), 1, @@ -2547,8 +2755,6 @@ angle::Result TextureVk::copyBufferDataToImage(ContextVk *contextVk, angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) { - vk::Renderer *renderer = contextVk->getRenderer(); - // Requires that the image: // // - is not sRGB @@ -2578,7 +2784,8 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) vk::SharedSamplerPtr sampler; vk::SamplerDesc samplerDesc(contextVk, samplerState, false, nullptr, static_cast(0)); - ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler)); + ANGLE_TRY( + contextVk->getShareGroup()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler)); // If the image has more levels than supported, generate as many mips as possible at a time. const vk::LevelIndex maxGenerateLevels(UtilsVk::GetGenerateMipmapMaxLevels(contextVk)); @@ -2587,7 +2794,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel() + 1)); dstBaseLevelVk <= dstMaxLevelVk; dstBaseLevelVk = dstBaseLevelVk + maxGenerateLevels.get()) { - vk::CommandBufferAccess access; + vk::CommandResources resources; // For mipmap generation, we should make sure that there is no pending write for the source // mip level. If there is, a barrier should be inserted before the source mip being used. @@ -2595,15 +2802,15 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) uint32_t writeLevelCount = std::min(maxGenerateLevels.get(), dstMaxLevelVk.get() + 1 - dstBaseLevelVk.get()); - access.onImageComputeMipmapGenerationRead(mImage->toGLLevel(srcLevelVk), 1, 0, - mImage->getLayerCount(), - VK_IMAGE_ASPECT_COLOR_BIT, mImage); - access.onImageComputeShaderWrite(mImage->toGLLevel(dstBaseLevelVk), writeLevelCount, 0, - mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT, - mImage); + resources.onImageComputeMipmapGenerationRead(mImage->toGLLevel(srcLevelVk), 1, 0, + mImage->getLayerCount(), + VK_IMAGE_ASPECT_COLOR_BIT, mImage); + resources.onImageComputeShaderWrite(mImage->toGLLevel(dstBaseLevelVk), writeLevelCount, 0, + mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT, + mImage); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Generate mipmaps for every layer separately. for (uint32_t layer = 0; layer < mImage->getLayerCount(); ++layer) @@ -2669,7 +2876,7 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context) vk::RendererScoped bufferHelper(contextVk->getRenderer()); ANGLE_TRY(copyImageDataToBufferAndGetData(contextVk, baseLevelGL, imageLayerCount, imageArea, - RenderPassClosureReason::GenerateMipmapOnCPU, + QueueSubmitReason::GenerateMipmapOnCPU, &bufferHelper.get(), &imageData)); const angle::Format &angleFormat = mImage->getActualFormat(); @@ -2714,10 +2921,16 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) vk::LevelIndex maxLevel = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel())); ASSERT(maxLevel != vk::LevelIndex(0)); - if (getImageViews().hasColorspaceOverrideForWrite(*mImage)) + const bool colorspaceOverrideForRead = getImageViews().hasColorspaceOverrideForRead(*mImage); + const bool colorspaceOverrideForWrite = getImageViews().hasColorspaceOverrideForWrite(*mImage); + + if (colorspaceOverrideForRead || colorspaceOverrideForWrite) { angle::FormatID actualFormatID = - getImageViews().getColorspaceOverrideFormatForWrite(mImage->getActualFormatID()); + colorspaceOverrideForRead + ? getImageViews().getColorspaceOverrideFormatForRead(mImage->getActualFormatID()) + : getImageViews().getColorspaceOverrideFormatForWrite(mImage->getActualFormatID()); + return contextVk->getUtils().generateMipmapWithDraw( contextVk, mImage, actualFormatID, gl::IsMipmapFiltered(mState.getSamplerState().getMinFilter())); @@ -2766,7 +2979,9 @@ angle::Result TextureVk::maybeUpdateBaseMaxLevels(ContextVk *contextVk, } gl::LevelIndex newBaseLevel = gl::LevelIndex(mState.getEffectiveBaseLevel()); - gl::LevelIndex newMaxLevel = gl::LevelIndex(mState.getEffectiveMaxLevel()); + // In edge case where base level > max level, clamp up to base level. + gl::LevelIndex newMaxLevel = + std::max(gl::LevelIndex(mState.getEffectiveMaxLevel()), newBaseLevel); ASSERT(newBaseLevel <= newMaxLevel); if (!mImage->valid()) @@ -2827,21 +3042,20 @@ angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk, const uint32_t layerCount = srcImage->getLayerCount(); ANGLE_TRY(stagingImage->get().initStaging( - contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(), - srcImage->getType(), srcImage->getExtents(), srcImage->getIntendedFormatID(), - srcImage->getActualFormatID(), srcImage->getSamples(), kTransferImageFlags, levelCount, - layerCount)); + contextVk, mState.hasProtectedContent(), srcImage->getType(), srcImage->getExtents(), + srcImage->getIntendedFormatID(), srcImage->getActualFormatID(), srcImage->getSamples(), + vk::kImageUsageTransferBits, levelCount, layerCount)); // Copy the src image wholly into the staging image const VkImageAspectFlags aspectFlags = srcImage->getAspectFlags(); - vk::CommandBufferAccess access; - access.onImageTransferWrite(gl::LevelIndex(0), levelCount, 0, layerCount, aspectFlags, - &stagingImage->get()); - access.onImageTransferRead(aspectFlags, srcImage); + vk::CommandResources resources; + resources.onImageTransferWrite(gl::LevelIndex(0), levelCount, 0, layerCount, aspectFlags, + &stagingImage->get()); + resources.onImageTransferRead(aspectFlags, srcImage); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); VkImageCopy copyRegion = {}; copyRegion.srcSubresource.aspectMask = aspectFlags; @@ -2880,7 +3094,7 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk: ANGLE_TRY(flushImageStagedUpdates(contextVk)); const angle::Format &srcFormat = mImage->getActualFormat(); - const angle::Format &dstFormat = format.getActualImageFormat(getRequiredImageAccess()); + const angle::Format &dstFormat = format.getActualImageFormat(getRequiredFormatSupport()); // If layerCount or levelCount is bigger than 1, we go for the slow path for now. The problem // with draw path is that in the multiple level/layer case, we have to do copy in a loop. @@ -2894,7 +3108,7 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk: "Copying image data due to texture format fallback"); ASSERT(CanCopyWithDraw(renderer, mImage->getUsage(), - format.getActualImageFormatID(getRequiredImageAccess()), + format.getActualImageFormatID(getRequiredFormatSupport()), getTilingMode())); vk::LevelIndex levelVk(0); gl::LevelIndex sourceLevelGL = mImage->toGLLevel(levelVk); @@ -2938,7 +3152,7 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk: // Explicitly finish. If new use cases arise where we don't want to block we can change // this. - ANGLE_TRY(contextVk->finishImpl(RenderPassClosureReason::TextureReformatToRenderable)); + ANGLE_TRY(contextVk->finishImpl(QueueSubmitReason::TextureReformatToRenderable)); // invalidate must be called after wait for finish. ANGLE_TRY(srcBuffer->invalidate(renderer)); @@ -3007,14 +3221,20 @@ angle::Result TextureVk::respecifyImageStorage(ContextVk *contextVk) // Save previousFirstAllocateLevel before mImage becomes invalid gl::LevelIndex previousFirstAllocateLevel = mImage->getFirstAllocatedLevel(); + // If the current level is less than levelCount, Angle needs to generate the required + // levelCount for it. + const bool levelIncomplete = + mImage->getLevelCount() < + getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap); + // If we didn't own the image, release the current and create a new one releaseImage(contextVk); // Create the image helper ANGLE_TRY(ensureImageAllocated(contextVk, format)); ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(), - format.getActualImageFormatID(getRequiredImageAccess()), - mState.getImmutableFormat() + format.getActualImageFormatID(getRequiredFormatSupport()), + mState.getImmutableFormat() || levelIncomplete ? ImageMipLevels::FullMipChainForGenerateMipmap : ImageMipLevels::EnabledLevels)); @@ -3025,7 +3245,9 @@ angle::Result TextureVk::respecifyImageStorage(ContextVk *contextVk) else { const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer()); - if (mImage->getActualFormatID() != format.getActualImageFormatID(getRequiredImageAccess())) + if (mImage->getActualFormatID() != + format.getActualImageFormatID(getRequiredFormatSupport()) && + mImage->getLevelCount() == getMipLevelCount(ImageMipLevels::EnabledLevels)) { ANGLE_TRY(reinitImageAsRenderable(contextVk, format)); } @@ -3087,7 +3309,7 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context, { const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer()); ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(), - format.getActualImageFormatID(getRequiredImageAccess()), + format.getActualImageFormatID(getRequiredFormatSupport()), ImageMipLevels::EnabledLevels)); } @@ -3133,11 +3355,30 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context, // Create the implicit multisampled image. ANGLE_TRY(multisampledImage.initImplicitMultisampledRenderToTexture( - contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(), - mState.getType(), samples, *mImage, extents, useRobustInit)); + contextVk, mState.hasProtectedContent(), mState.getType(), samples, *mImage, + extents, useRobustInit)); } } + // If rendering to a YUV image and nullColorAttachmentWithExternalFormatResolve is not supported + // create an RGB image that is otherwise identical to the YUV image. This new RGB image + // will be used as the draw attachment, while the original YUV image is used as the resolve + // attachment. + if (mImage->isYuvExternalFormat() && mRgbDrawImageForYuvResolve == nullptr && + !contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) + { + vk::Renderer *renderer = contextVk->getRenderer(); + + // Allocate implicit RGB image and image view + mRgbDrawImageForYuvResolve = std::make_unique(); + mRgbDrawImageViewsForYuvResolve = std::make_unique(); + + // Initialize implicit RGB image and image view + ANGLE_TRY(mRgbDrawImageForYuvResolve->initRgbDrawImageForYuvResolve( + contextVk, *mImage, contextVk->isRobustResourceInitEnabled())); + mRgbDrawImageViewsForYuvResolve->init(renderer); + } + GLuint layerIndex = 0, layerCount = 0, imageLayerCount = 0; GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerIndex, &layerCount, &imageLayerCount); @@ -3179,7 +3420,7 @@ angle::Result TextureVk::ensureImageInitialized(ContextVk *contextVk, ImageMipLe const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer()); ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(), - format.getActualImageFormatID(getRequiredImageAccess()), mipLevels)); + format.getActualImageFormatID(getRequiredFormatSupport()), mipLevels)); if (mipLevels == ImageMipLevels::FullMipChainForGenerateMipmap) { // Remove staged updates to non-base mips when generating mipmaps. These can only be @@ -3245,7 +3486,7 @@ void TextureVk::initSingleLayerRenderTargets(ContextVk *contextVk, if (isMultisampledRenderToTexture) { ASSERT(mMultisampledImages->at(renderToTextureIndex)[requestedLevel].valid()); - ASSERT(!mImage->isYuvResolve()); + ASSERT(!mImage->isYuvExternalFormat()); resolveImage = drawImage; resolveImageViews = drawImageViews; @@ -3264,7 +3505,7 @@ void TextureVk::initSingleLayerRenderTargets(ContextVk *contextVk, transience = RenderTargetTransience::MultisampledTransient; } } - else if (mImage->isYuvResolve()) + else if (mImage->isYuvExternalFormat()) { // If rendering to YUV, similar to multisampled render to texture resolveImage = drawImage; @@ -3279,11 +3520,9 @@ void TextureVk::initSingleLayerRenderTargets(ContextVk *contextVk, } else { - transience = RenderTargetTransience::YuvResolveTransient; - // Need to populate drawImage here; either abuse mMultisampledImages etc - // or build something parallel to it. we don't have a vulkan implementation which - // wants this path yet, though. - UNREACHABLE(); + transience = RenderTargetTransience::YuvResolveTransient; + drawImage = mRgbDrawImageForYuvResolve.get(); + drawImageViews = mRgbDrawImageViewsForYuvResolve.get(); } } @@ -3352,7 +3591,7 @@ void TextureVk::prepareForGenerateMipmap(ContextVk *contextVk) // If the compute path is to be used to generate mipmaps, add the STORAGE usage. if (CanGenerateMipmapWithCompute(contextVk->getRenderer(), imageType, - format.getActualImageFormatID(getRequiredImageAccess()), + format.getActualImageFormatID(getRequiredFormatSupport()), samples, mOwnsImage)) { mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT; @@ -3457,34 +3696,21 @@ angle::Result TextureVk::respecifyImageStorageIfNecessary(ContextVk *contextVk, // If generating mipmaps and the image needs to be recreated (not full-mip already, or changed // usage flags), make sure it's recreated. - if (isGenerateMipmap && mImage && mImage->valid() && + const bool isMipmapEnabledByGenerateMipmap = + isGenerateMipmap && mImage && mImage->valid() && (oldUsageFlags != mImageUsageFlags || (!mState.getImmutableFormat() && mImage->getLevelCount() != - getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap)))) - { - ASSERT(mOwnsImage); - // Immutable texture is not expected to reach here. The usage flag change should have - // been handled earlier and level count change should not need to reallocate - ASSERT(!mState.getImmutableFormat()); + getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap))); - // Flush staged updates to the base level of the image. Note that updates to the rest of - // the levels have already been discarded through the |removeStagedUpdates| call above. - ANGLE_TRY(flushImageStagedUpdates(contextVk)); - - stageSelfAsSubresourceUpdates(contextVk); - - // Release the mImage without collecting garbage from image views. - releaseImage(contextVk); - } - - // Respecify the image if it's changed in usage, or if any of its levels are redefined and no - // update to base/max levels were done (otherwise the above call would have already taken care - // of this). Note that if both base/max and image usage are changed, the image is recreated - // twice, which incurs unnecessary copies. This is not expected to be happening in real - // applications. + // Respecify the image if it's changed in usage, not full-mip, or if any of its levels are + // redefined and no update to base/max levels were done (otherwise the above call would have + // already taken care of this). Note that if both base/max and image usage are changed, the + // image is recreated twice, which incurs unnecessary copies. This is not expected to be + // happening in real applications. if (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags || - TextureHasAnyRedefinedLevels(mRedefinedLevels) || isMipmapEnabledByMinFilter) + TextureHasAnyRedefinedLevels(mRedefinedLevels) || isMipmapEnabledByMinFilter || + isMipmapEnabledByGenerateMipmap) { ANGLE_TRY(respecifyImageStorage(contextVk)); } @@ -3644,7 +3870,8 @@ angle::Result TextureVk::syncState(const gl::Context *context, if (localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) || localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN) || localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE) || - localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA)) + localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA) || + localBits.test(gl::Texture::DIRTY_BIT_ASTC_DECODE_PRECISION)) { ANGLE_TRY(refreshImageViews(contextVk)); } @@ -3671,9 +3898,10 @@ angle::Result TextureVk::syncState(const gl::Context *context, vk::SamplerDesc samplerDescSamplerExternal2DY2YEXT(contextVk, mState.getSamplerState(), mState.isStencilMode(), &y2yConversionDesc, mImage->getIntendedFormatID()); - ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &mSampler)); - ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDescSamplerExternal2DY2YEXT, - &mY2YSampler)); + ANGLE_TRY(contextVk->getShareGroup()->getSamplerCache().getSampler(contextVk, samplerDesc, + &mSampler)); + ANGLE_TRY(contextVk->getShareGroup()->getSamplerCache().getSampler( + contextVk, samplerDescSamplerExternal2DY2YEXT, &mY2YSampler)); updateCachedImageViewSerials(); @@ -3694,7 +3922,7 @@ angle::Result TextureVk::initializeContents(const gl::Context *context, // on a non-complete cube map. return mImage->stageRobustResourceClearWithFormat( contextVk, imageIndex, desc.size, format.getIntendedFormat(), - format.getActualImageFormat(getRequiredImageAccess())); + format.getActualImageFormat(getRequiredFormatSupport())); } angle::Result TextureVk::initializeContentsWithBlack(const gl::Context *context, @@ -3714,7 +3942,7 @@ angle::Result TextureVk::initializeContentsWithBlack(const gl::Context *context, // on a non-complete cube map. return mImage->stageResourceClearWithFormat( contextVk, imageIndex, desc.size, format.getIntendedFormat(), - format.getActualImageFormat(getRequiredImageAccess()), clearValue); + format.getActualImageFormat(getRequiredFormatSupport()), clearValue); } void TextureVk::releaseOwnershipOfImage(const gl::Context *context) @@ -3772,7 +4000,7 @@ const vk::ImageView &TextureVk::getCopyImageView() const return imageViews.getLinearCopyImageView(); } -angle::Result TextureVk::getLevelLayerImageView(vk::ErrorContext *context, +angle::Result TextureVk::getLevelLayerImageView(ContextVk *contextVk, gl::LevelIndex level, size_t layer, const vk::ImageView **imageViewOut) @@ -3783,20 +4011,20 @@ angle::Result TextureVk::getLevelLayerImageView(vk::ErrorContext *context, vk::LevelIndex levelVk = mImage->toVkLevel(levelGL); uint32_t nativeLayer = getNativeImageLayer(static_cast(layer)); - return getImageViews().getLevelLayerDrawImageView(context, *mImage, levelVk, nativeLayer, + return getImageViews().getLevelLayerDrawImageView(contextVk, *mImage, levelVk, nativeLayer, imageViewOut); } -angle::Result TextureVk::getStorageImageView(vk::ErrorContext *context, +angle::Result TextureVk::getStorageImageView(ContextVk *contextVk, const gl::ImageUnit &binding, const vk::ImageView **imageViewOut) { - vk::Renderer *renderer = context->getRenderer(); + vk::Renderer *renderer = contextVk->getRenderer(); angle::FormatID formatID = angle::Format::InternalFormatToID(binding.format); const vk::Format *format = &renderer->getFormat(formatID); - format = AdjustStorageViewFormatPerWorkarounds(renderer, format, getRequiredImageAccess()); + format = AdjustStorageViewFormatPerWorkarounds(renderer, format, getRequiredFormatSupport()); gl::LevelIndex nativeLevelGL = getNativeImageLevel(gl::LevelIndex(static_cast(binding.level))); @@ -3809,17 +4037,17 @@ angle::Result TextureVk::getStorageImageView(vk::ErrorContext *context, uint32_t nativeLayer = getNativeImageLayer(static_cast(binding.layer)); return getImageViews().getLevelLayerStorageImageView( - context, *mImage, nativeLevelVk, nativeLayer, + contextVk, *mImage, nativeLevelVk, nativeLayer, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, - format->getActualImageFormatID(getRequiredImageAccess()), imageViewOut); + format->getActualImageFormatID(getRequiredFormatSupport()), imageViewOut); } uint32_t nativeLayer = getNativeImageLayer(0); return getImageViews().getLevelStorageImageView( - context, mState.getType(), *mImage, nativeLevelVk, nativeLayer, + contextVk, mState.getType(), *mImage, nativeLevelVk, nativeLayer, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, - format->getActualImageFormatID(getRequiredImageAccess()), imageViewOut); + format->getActualImageFormatID(getRequiredFormatSupport()), imageViewOut); } vk::BufferHelper *TextureVk::getPossiblyEmulatedTextureBuffer(vk::ErrorContext *context) const @@ -3840,7 +4068,8 @@ angle::Result TextureVk::getBufferView(vk::ErrorContext *context, const vk::Format *imageUniformFormat, const gl::SamplerBinding *samplerBinding, bool isImage, - const vk::BufferView **viewOut) + const vk::BufferView **viewOut, + VkFormat *viewVkFormatOut) { vk::Renderer *renderer = context->getRenderer(); @@ -3855,7 +4084,7 @@ angle::Result TextureVk::getBufferView(vk::ErrorContext *context, if (isImage) { imageUniformFormat = AdjustStorageViewFormatPerWorkarounds(renderer, imageUniformFormat, - getRequiredImageAccess()); + getRequiredFormatSupport()); } const vk::BufferHelper *buffer = &vk::GetImpl(mState.getBuffer().get())->getBuffer(); @@ -3874,8 +4103,8 @@ angle::Result TextureVk::getBufferView(vk::ErrorContext *context, } // Create a view for the required format. - return mBufferViews.getView(context, *buffer, buffer->getOffset(), *imageUniformFormat, - viewOut); + return mBufferViews.getView(context, *buffer, buffer->getOffset(), *imageUniformFormat, viewOut, + viewVkFormatOut); } angle::Result TextureVk::initImage(ContextVk *contextVk, @@ -3927,14 +4156,20 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT; } - mImageCreateFlags |= - vk::GetMinimalImageCreateFlags(renderer, mState.getType(), mImageUsageFlags); - const VkFormat actualImageFormat = rx::vk::GetVkFormatFromFormatID(renderer, actualImageFormatID); const VkImageType imageType = gl_vk::GetImageType(mState.getType()); const VkImageTiling imageTiling = mImage->getTilingMode(); + if (mipLevels == ImageMipLevels::FullMipChainForGenerateMipmap && + CanGenerateMipmapWithCompute(renderer, imageType, actualImageFormatID, samples, mOwnsImage)) + { + mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT; + } + + mImageCreateFlags |= + vk::GetMinimalImageCreateFlags(renderer, mState.getType(), mImageUsageFlags); + // The MSRTSS bit is included in the create flag for all textures if the feature flag // corresponding to its preference is enabled. Otherwise, it is enabled for a texture if it is // bound to an MSRTT framebuffer. @@ -4007,10 +4242,13 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, &perfQuery, vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess)) { // Only enable it if it has no performance impact whatsoever (or impact is tiny, given - // feature). + // feature). For luminance/alpha formats, on some platforms it's known to be an overall + // win despite non-optimal layout. + const bool isLUMA = angle::Format::Get(intendedImageFormatID).isLUMA(); if (perfQuery.identicalMemoryLayout || (perfQuery.optimalDeviceAccess && - renderer->getFeatures().allowHostImageCopyDespiteNonIdenticalLayout.enabled)) + renderer->getFeatures().allowHostImageCopyDespiteNonIdenticalLayout.enabled) || + (isLUMA && renderer->getFeatures().forceHostImageCopyForLuma.enabled)) { mImageUsageFlags |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT; } @@ -4018,8 +4256,9 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, } // Fixed rate compression - VkImageCompressionControlEXT *compressionInfo = nullptr; - VkImageCompressionControlEXT compressionInfoVar = {}; + VkImageCompressionControlEXT *compressionInfo = nullptr; + VkImageCompressionControlEXT compressionInfoVar = {}; + VkImageCompressionFixedRateFlagsEXT compressionRates = VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT; if (renderer->getFeatures().supportsImageCompressionControl.enabled && mOwnsImage && mState.getSurfaceCompressionFixedRate() != GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT) { @@ -4027,30 +4266,26 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, // Use default compression control flag for query compressionInfoVar.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT; - VkImageCompressionPropertiesEXT compressionProp = {}; - compressionProp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT; - // If fixed rate compression is supported by this type, not support YUV now. const vk::Format &format = renderer->getFormat(intendedImageFormatID); - if (!mImage->isYuvResolve() && + if (!mImage->isYuvExternalFormat() && (GetFormatSupportedCompressionRates(renderer, format, 0, nullptr) != 0)) { - VkImageCompressionFixedRateFlagsEXT compressionRates = - VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT; GetCompressionFixedRate(&compressionInfoVar, &compressionRates, mState.getSurfaceCompressionFixedRate()); compressionInfo = &compressionInfoVar; } } - ANGLE_TRY(mImage->initExternal( - contextVk, mState.getType(), vkExtent, intendedImageFormatID, actualImageFormatID, samples, - mImageUsageFlags, mImageCreateFlags, vk::ImageLayout::Undefined, nullptr, - gl::LevelIndex(firstLevel), levelCount, layerCount, - contextVk->isRobustResourceInitEnabled(), mState.hasProtectedContent(), - vk::ImageHelper::deriveConversionDesc(contextVk, actualImageFormatID, - intendedImageFormatID), - compressionInfo)); + ANGLE_TRY(mImage->initExternal(contextVk, mState.getType(), vkExtent, intendedImageFormatID, + actualImageFormatID, samples, mImageUsageFlags, + mImageCreateFlags, vk::ImageAccess::Undefined, nullptr, + gl::LevelIndex(firstLevel), levelCount, layerCount, + contextVk->isRobustResourceInitEnabled(), + mState.hasProtectedContent(), vk::TileMemory::Prohibited, + vk::ImageHelper::deriveConversionDesc( + contextVk, actualImageFormatID, intendedImageFormatID), + compressionInfo)); ANGLE_TRY(updateTextureLabel(contextVk)); @@ -4064,8 +4299,7 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT; } - ANGLE_TRY(contextVk->initImageAllocation(mImage, mState.hasProtectedContent(), - renderer->getMemoryProperties(), flags, + ANGLE_TRY(contextVk->initImageAllocation(mImage, mState.hasProtectedContent(), flags, vk::MemoryAllocationType::TextureImage)); const uint32_t viewLevelCount = @@ -4073,7 +4307,8 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, ANGLE_TRY(initImageViews(contextVk, viewLevelCount)); mCurrentBaseLevel = gl::LevelIndex(mState.getBaseLevel()); - mCurrentMaxLevel = gl::LevelIndex(mState.getMaxLevel()); + // In edge case where base level > max level, clamp up to base level. + mCurrentMaxLevel = std::max(gl::LevelIndex(mState.getMaxLevel()), mCurrentBaseLevel); return angle::Result::Continue; } @@ -4097,13 +4332,20 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk, uint32_t levelCoun // Use this as a proxy for the SRGB override & skip decode settings. bool createExtraSRGBViews = mRequiresMutableStorage; + GLenum astcDecodePrecision = GL_NONE; + vk::Renderer *renderer = contextVk->getRenderer(); + if (renderer->getFeatures().supportsAstcDecodeMode.enabled) + { + astcDecodePrecision = mState.getASTCDecodePrecision(); + } + const VkImageUsageFlags kDisallowedSwizzledUsage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; - ANGLE_TRY(getImageViews().initReadViews(contextVk, mState.getType(), *mImage, formatSwizzle, - readSwizzle, baseLevelVk, levelCount, baseLayer, - getImageViewLayerCount(), createExtraSRGBViews, - getImage().getUsage() & ~kDisallowedSwizzledUsage)); + ANGLE_TRY(getImageViews().initReadViews( + contextVk, mState.getType(), *mImage, formatSwizzle, readSwizzle, baseLevelVk, levelCount, + baseLayer, getImageViewLayerCount(), createExtraSRGBViews, + getImage().getUsage() & ~kDisallowedSwizzledUsage, astcDecodePrecision)); updateCachedImageViewSerials(); @@ -4145,6 +4387,13 @@ void TextureVk::releaseImage(ContextVk *contextVk) mMultisampledImages.reset(); } + if (mRgbDrawImageForYuvResolve) + { + mRgbDrawImageForYuvResolve->releaseImageFromShareContexts(renderer, contextVk, + mImageSiblingSerial); + mRgbDrawImageForYuvResolve.reset(); + } + onStateChange(angle::SubjectMessage::SubjectChanged); mRedefinedLevels = {}; } @@ -4191,6 +4440,12 @@ void TextureVk::releaseImageViews(ContextVk *contextVk) mMultisampledImageViews.reset(); } + if (mRgbDrawImageViewsForYuvResolve) + { + mRgbDrawImageViewsForYuvResolve->release(renderer, mImage->getResourceUse()); + mRgbDrawImageViewsForYuvResolve.reset(); + } + for (auto &renderTargets : mSingleLayerRenderTargets) { for (RenderTargetVector &renderTargetLevels : renderTargets) @@ -4315,7 +4570,7 @@ const gl::InternalFormat &TextureVk::getImplementationSizedFormat(const gl::Cont { ContextVk *contextVk = vk::GetImpl(context); const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer()); - sizedFormat = format.getActualImageFormat(getRequiredImageAccess()).glInternalFormat; + sizedFormat = format.getActualImageFormat(getRequiredFormatSupport()).glInternalFormat; } return gl::GetSizedInternalFormatInfo(sizedFormat); @@ -4551,12 +4806,12 @@ angle::Result TextureVk::ensureRenderableWithFormat(ContextVk *contextVk, const vk::Format &format, TextureUpdateResult *updateResultOut) { - if (mRequiredImageAccess == vk::ImageAccess::Renderable) + if (mRequiredFormatSupport == vk::ImageFormatSupport::Renderable) { return angle::Result::Continue; } - mRequiredImageAccess = vk::ImageAccess::Renderable; + mRequiredFormatSupport = vk::ImageFormatSupport::Renderable; if (!mImage) { // Later on when ensureImageAllocated() is called, it will ensure a renderable format is @@ -4570,13 +4825,18 @@ angle::Result TextureVk::ensureRenderableWithFormat(ContextVk *contextVk, return angle::Result::Continue; } - // luminance/alpha format never fallback for rendering and if we ever do fallback, the - // following code may not handle it properly. - ASSERT(!format.getIntendedFormat().isLUMA()); + // If luminance/alpha formats ever fall back for rendering, it would only be because the + // color attachment usage isn't specified by default. The following wouldn't actually change + // the format of the LUMA image because it's always emulated with a renderable format. If + // Vulkan ever introduces a LUMA format that ANGLE uses, the following code may not handle it + // properly. + ASSERT(!format.getIntendedFormat().isLUMA() || + (mImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0); angle::FormatID previousActualFormatID = - format.getActualImageFormatID(vk::ImageAccess::SampleOnly); - angle::FormatID actualFormatID = format.getActualImageFormatID(vk::ImageAccess::Renderable); + format.getActualImageFormatID(vk::ImageFormatSupport::SampleOnly); + angle::FormatID actualFormatID = + format.getActualImageFormatID(vk::ImageFormatSupport::Renderable); if (!mImage->valid()) { @@ -4607,7 +4867,7 @@ angle::Result TextureVk::ensureRenderableWithFormat(ContextVk *contextVk, actualFormatID)) { angle::FormatID sampleOnlyFormatID = - format.getActualImageFormatID(vk::ImageAccess::SampleOnly); + format.getActualImageFormatID(vk::ImageFormatSupport::SampleOnly); ANGLE_TRY(initImage(contextVk, intendedFormatID, sampleOnlyFormatID, mipLevels)); } @@ -4649,7 +4909,7 @@ angle::Result TextureVk::ensureRenderableIfCopyTextureCannotTransfer( vk::Renderer *renderer = contextVk->getRenderer(); const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat); - angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredImageAccess()); + angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredFormatSupport()); VkImageTiling dstTilingMode = getTilingMode(); if (!CanCopyWithTransferForCopyTexture( @@ -4675,7 +4935,7 @@ angle::Result TextureVk::ensureRenderableIfCopyTexImageCannotTransfer( const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat); angle::FormatID dstIntendedFormatID = dstVkFormat.getIntendedFormatID(); angle::FormatID dstActualFormatID = - dstVkFormat.getActualImageFormatID(getRequiredImageAccess()); + dstVkFormat.getActualImageFormatID(getRequiredFormatSupport()); VkImageTiling destTilingMode = getTilingMode(); bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO(); diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h index 9138127fa50..5fdf1e1e361 100644 --- a/src/libANGLE/renderer/vulkan/TextureVk.h +++ b/src/libANGLE/renderer/vulkan/TextureVk.h @@ -243,11 +243,12 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface const vk::Format *imageUniformFormat, const gl::SamplerBinding *samplerBinding, bool isImage, - const vk::BufferView **viewOut); + const vk::BufferView **viewOut, + VkFormat *viewVkFormatOut); // A special view used for texture copies that shouldn't perform swizzle. const vk::ImageView &getCopyImageView() const; - angle::Result getStorageImageView(vk::ErrorContext *context, + angle::Result getStorageImageView(ContextVk *contextVk, const gl::ImageUnit &binding, const vk::ImageView **imageViewOut); @@ -422,6 +423,12 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface const vk::Format &format, const gl::Extents &size); + // If an image is in use by the GPU but is overwritten completely, a new VkImage can be created + // instead to avoid creating an unnecessary dependency. + angle::Result ghostOnOverwrite(ContextVk *contextVk, + const gl::ImageIndex &index, + const gl::Box &area); + angle::Result setImageImpl(const gl::Context *context, const gl::ImageIndex &index, const gl::InternalFormat &formatInfo, @@ -459,7 +466,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface gl::LevelIndex sourceLevelGL, uint32_t layerCount, const gl::Box &sourceArea, - RenderPassClosureReason reason, + QueueSubmitReason reason, vk::BufferHelper *copyBuffer, uint8_t **outDataPtr); @@ -557,7 +564,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface gl::LevelIndex level, GLuint layerIndex, GLuint layerCount); - angle::Result getLevelLayerImageView(vk::ErrorContext *context, + angle::Result getLevelLayerImageView(ContextVk *contextVk, gl::LevelIndex levelGL, size_t layer, const vk::ImageView **imageViewOut); @@ -583,9 +590,13 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface angle::Result maybeUpdateBaseMaxLevels(ContextVk *contextVk, TextureUpdateResult *changeResultOut); - bool isFastUnpackPossible(const vk::Format &vkFormat, + bool isFastUnpackPossible(const gl::Box &area, + GLuint rowLengthPixels, + GLuint imageHeightPixels, + const vk::Format &vkFormat, size_t offset, - const vk::Format &bufferVkFormat) const; + const vk::Format &bufferVkFormat, + GLenum type) const; bool updateMustBeStaged(gl::LevelIndex textureLevelIndexGL, angle::FormatID dstFormatID) const; bool updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL, angle::FormatID dstFormatID) const; @@ -608,11 +619,13 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface angle::Result ensureMutable(ContextVk *contextVk); angle::Result refreshImageViews(ContextVk *contextVk); - void initImageUsageFlags(ContextVk *contextVk, angle::FormatID actualFormatID); + void initImageUsageFlags(ContextVk *contextVk, + const angle::Format &intendedFormat, + angle::FormatID actualFormatID); void handleImmutableSamplerTransition(const vk::ImageHelper *previousImage, const vk::ImageHelper *nextImage); - vk::ImageAccess getRequiredImageAccess() const { return mRequiredImageAccess; } + vk::ImageFormatSupport getRequiredFormatSupport() const { return mRequiredFormatSupport; } void stageSelfAsSubresourceUpdates(ContextVk *contextVk); @@ -639,7 +652,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface UniqueSerial mImageSiblingSerial; bool mRequiresMutableStorage; - vk::ImageAccess mRequiredImageAccess; + vk::ImageFormatSupport mRequiredFormatSupport; bool mImmutableSamplerDirty; // Only valid if this texture is an "EGLImage target" and the associated EGL Image was @@ -673,6 +686,11 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface gl::RenderToTextureImageMap>; std::unique_ptr mMultisampledImageViews; + // Implicit RGB image to be used in YUV rendering when + // nullColorAttachmentWithExternalFormatResolve is not supported. + std::unique_ptr mRgbDrawImageForYuvResolve; + std::unique_ptr mRgbDrawImageViewsForYuvResolve; + // Texture buffers create texel buffer views instead. |BufferViewHelper| contains the views // corresponding to the attached buffer range. vk::BufferViewHelper mBufferViews; diff --git a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp index f52e26366b1..201ea0d94a0 100644 --- a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp +++ b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for TransformFeedbackVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h" #include "libANGLE/Context.h" diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp index 38544c8e6e6..505e5afea40 100644 --- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp +++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp @@ -7,6 +7,10 @@ // Implements the UtilsVk class. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/UtilsVk.h" #include "common/spirv/spirv_instruction_builder_autogen.h" @@ -236,17 +240,14 @@ uint32_t GetCopyImageToBufferFlags(const angle::Format &srcFormat) return CopyImageToBuffer_comp::kSrcIsFloat; } -uint32_t GetBlitResolveFlags(bool blitColor, - bool blitDepth, - bool blitStencil, - const angle::Format &intendedFormat) +uint32_t GetColorBlitResolveFlags(const angle::Format &intendedFormat) { - if (blitColor) - { - return GetFormatFlags(intendedFormat, BlitResolve_frag::kBlitColorInt, - BlitResolve_frag::kBlitColorUint, BlitResolve_frag::kBlitColorFloat); - } + return GetFormatFlags(intendedFormat, BlitResolve_frag::kBlitColorInt, + BlitResolve_frag::kBlitColorUint, BlitResolve_frag::kBlitColorFloat); +} +uint32_t GetDepthStencilBlitResolveFlags(bool blitDepth, bool blitStencil) +{ if (blitDepth) { if (blitStencil) @@ -520,35 +521,6 @@ void SetStencilDynamicStateForUnused(vk::Renderer *renderer, commandBuffer->setStencilReference(0x00, 0x00); } -void HandlePrimitiveRestart(ContextVk *contextVk, - gl::DrawElementsType glIndexType, - GLsizei indexCount, - const uint8_t *srcPtr, - uint8_t *outPtr) -{ - switch (glIndexType) - { - case gl::DrawElementsType::UnsignedByte: - if (contextVk->getFeatures().supportsIndexTypeUint8.enabled) - { - CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); - } - else - { - CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); - } - break; - case gl::DrawElementsType::UnsignedShort: - CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); - break; - case gl::DrawElementsType::UnsignedInt: - CopyLineLoopIndicesWithRestart(indexCount, srcPtr, outPtr); - break; - default: - UNREACHABLE(); - } -} - namespace unresolve { // The unresolve shader looks like the following, based on the number and types of unresolve @@ -1236,7 +1208,8 @@ void ResetDynamicState(ContextVk *contextVk, vk::RenderPassCommandBuffer *comman vk::Renderer *renderer = contextVk->getRenderer(); - // Reset all other dynamic state, since it can affect UtilsVk functions: + // Reset all other dynamic state, since it can affect UtilsVk functions. Values reflect common + // UtilsVk setting. if (renderer->getFeatures().useCullModeDynamicState.enabled) { commandBuffer->setCullMode(VK_CULL_MODE_NONE); @@ -1245,6 +1218,10 @@ void ResetDynamicState(ContextVk *contextVk, vk::RenderPassCommandBuffer *comman { commandBuffer->setFrontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE); } + if (renderer->getFeatures().usePrimitiveTopologyDynamicState.enabled) + { + commandBuffer->setPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); + } if (renderer->getFeatures().useDepthTestEnableDynamicState.enabled) { commandBuffer->setDepthTestEnable(VK_FALSE); @@ -1623,7 +1600,7 @@ angle::Result UtilsVk::ensureImageCopyResourcesInitializedWithSampler( vk::SharedSamplerPtr sampler; ANGLE_TRY( - contextVk->getRenderer()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler)); + contextVk->getShareGroup()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler)); vk::DescriptorSetLayoutDesc descriptorSetDesc; descriptorSetDesc.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, @@ -1804,7 +1781,7 @@ angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk) samplerInfo.compareEnable = VK_FALSE; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.minLod = 0; - samplerInfo.maxLod = 0; + samplerInfo.maxLod = gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS - 1; samplerInfo.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; samplerInfo.unnormalizedCoordinates = VK_FALSE; @@ -1984,13 +1961,13 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk, { ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk)); - vk::CommandBufferAccess access; - access.onBufferComputeShaderRead(src); - access.onBufferComputeShaderWrite(dst); + vk::CommandResources resources; + resources.onBufferComputeShaderRead(src); + resources.onBufferComputeShaderWrite(dst); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); commandBuffer = &commandBufferHelper->getCommandBuffer(); VkDescriptorSet descriptorSet; @@ -2047,15 +2024,15 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk, { ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk)); - vk::CommandBufferAccess access; - access.onBufferComputeShaderRead(srcIndirectBuf); - access.onBufferComputeShaderRead(srcIndexBuf); - access.onBufferComputeShaderWrite(dstIndirectBuf); - access.onBufferComputeShaderWrite(dstIndexBuf); + vk::CommandResources resources; + resources.onBufferComputeShaderRead(srcIndirectBuf); + resources.onBufferComputeShaderRead(srcIndexBuf); + resources.onBufferComputeShaderWrite(dstIndirectBuf); + resources.onBufferComputeShaderWrite(dstIndexBuf); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); commandBuffer = &commandBufferHelper->getCommandBuffer(); VkDescriptorSet descriptorSet; @@ -2118,15 +2095,15 @@ angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer( { ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk)); - vk::CommandBufferAccess access; - access.onBufferComputeShaderRead(srcIndirectBuffer); - access.onBufferComputeShaderRead(srcIndexBuffer); - access.onBufferComputeShaderWrite(dstIndirectBuffer); - access.onBufferComputeShaderWrite(dstIndexBuffer); + vk::CommandResources resources; + resources.onBufferComputeShaderRead(srcIndirectBuffer); + resources.onBufferComputeShaderRead(srcIndexBuffer); + resources.onBufferComputeShaderWrite(dstIndirectBuffer); + resources.onBufferComputeShaderWrite(dstIndexBuffer); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); commandBuffer = &commandBufferHelper->getCommandBuffer(); VkDescriptorSet descriptorSet; @@ -2184,14 +2161,14 @@ angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer( { ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk)); - vk::CommandBufferAccess access; - access.onBufferComputeShaderRead(srcIndirectBuffer); - access.onBufferComputeShaderWrite(dstIndirectBuffer); - access.onBufferComputeShaderWrite(dstIndexBuffer); + vk::CommandResources resources; + resources.onBufferComputeShaderRead(srcIndirectBuffer); + resources.onBufferComputeShaderWrite(dstIndirectBuffer); + resources.onBufferComputeShaderWrite(dstIndexBuffer); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); commandBuffer = &commandBufferHelper->getCommandBuffer(); VkDescriptorSet descriptorSet; @@ -2240,11 +2217,24 @@ angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer( // Used to clear a layer of a renderable texture in part or whole (EXT_clear_texture). angle::Result UtilsVk::clearTexture(ContextVk *contextVk, vk::ImageHelper *dst, - ClearTextureParameters ¶ms) + const ClearTextureParameters ¶ms) +{ + ANGLE_TRY(clearTextureNoFlush(contextVk, dst, params)); + + // Close the render pass for this temporary framebuffer. If the render pass is not immediately + // closed and the render area grows due to scissor change, the clear area unexpectedly changes. + // This can be avoided if the scissor code takes LOAD_OP_CLEAR into account before deciding to + // grow the render pass's render area. + return contextVk->flushCommandsAndEndRenderPass( + RenderPassClosureReason::TemporaryForClearTexture); +} + +angle::Result UtilsVk::clearTextureNoFlush(ContextVk *contextVk, + vk::ImageHelper *dst, + const ClearTextureParameters ¶ms) { const angle::Format &dstActualFormat = dst->getActualFormat(); bool isDepthOrStencil = dstActualFormat.hasDepthOrStencilBits(); - bool isFormatDS = dstActualFormat.hasDepthAndStencilBits(); vk::DeviceScoped destView(contextVk->getDevice()); const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples()); @@ -2262,38 +2252,36 @@ angle::Result UtilsVk::clearTexture(ContextVk *contextVk, vk::RenderPassDesc renderPassDesc; renderPassDesc.setSamples(dst->getSamples()); - if (!isDepthOrStencil) + if (isDepthOrStencil) { - renderPassDesc.packColorAttachment(0, dstActualFormat.id); + renderPassDesc.packDepthStencilAttachment(dstActualFormat.id); } else { - renderPassDesc.packDepthStencilAttachment(dstActualFormat.id); + renderPassDesc.packColorAttachment(0, dstActualFormat.id); } + vk::RenderPassCommandBuffer *commandBuffer; - vk::ImageLayout imageLayout = - isDepthOrStencil ? vk::ImageLayout::DepthWriteStencilWrite : vk::ImageLayout::ColorWrite; - ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea, + ANGLE_TRY(startRenderPass(contextVk, &destView.get(), renderPassDesc, renderArea, params.aspectFlags, ¶ms.clearValue, vk::RenderPassSource::InternalUtils, &commandBuffer)); - // If the format contains both depth and stencil, the barrier aspect mask for the image should - // include both bits. - contextVk->onImageRenderPassWrite( - dst->toGLLevel(params.level), params.layer, 1, - isFormatDS ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : params.aspectFlags, - imageLayout, dst); + if (isDepthOrStencil) + { + contextVk->onDepthStencilDraw(dst->toGLLevel(params.level), params.layer, 1, dst, nullptr, + {}); + } + else + { + contextVk->onColorDraw(dst->toGLLevel(params.level), params.layer, 1, dst, nullptr, {}, + vk::PackedAttachmentIndex(0)); + } vk::ImageView destViewObject = destView.release(); contextVk->addGarbage(&destViewObject); - // Close the render pass for this temporary framebuffer. If the render pass is not immediately - // closed and the render area grows due to scissor change, the clear area unexpectedly changes. - // This can be avoided if the scissor code takes LOAD_OP_CLEAR into account before deciding to - // grow the render pass's render area. - return contextVk->flushCommandsAndEndRenderPass( - RenderPassClosureReason::TemporaryForClearTexture); + return angle::Result::Continue; } angle::Result UtilsVk::convertVertexBuffer( @@ -2303,12 +2291,12 @@ angle::Result UtilsVk::convertVertexBuffer( const ConvertVertexParameters ¶ms, const OffsetAndVertexCounts &additionalOffsetVertexCounts) { - vk::CommandBufferAccess access; - access.onBufferComputeShaderRead(src); - access.onBufferComputeShaderWrite(dst); + vk::CommandResources resources; + resources.onBufferComputeShaderRead(src); + resources.onBufferComputeShaderWrite(dst); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); ConvertVertexShaderParams shaderParams; shaderParams.Ns = params.srcFormat->channelCount; @@ -2488,7 +2476,6 @@ angle::Result UtilsVk::convertVertexBufferImpl( } angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, - vk::ImageHelper *image, const vk::ImageView *imageView, const vk::RenderPassDesc &renderPassDesc, const gl::Rectangle &renderArea, @@ -2499,9 +2486,9 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, { ASSERT(aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT || (aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0); - vk::ImageLayout imageLayout = aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT - ? vk::ImageLayout::ColorWrite - : vk::ImageLayout::DepthWriteStencilWrite; + vk::ImageAccess imageAccess = aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT + ? vk::ImageAccess::ColorWrite + : vk::ImageAccess::DepthWriteStencilWrite; vk::Framebuffer framebuffer; vk::Framebuffer framebufferHandle; vk::RenderPassFramebuffer renderPassFramebuffer; @@ -2546,13 +2533,13 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, if (clearValue == nullptr) { - renderPassAttachmentOps.initWithLoadStore(vk::kAttachmentIndexZero, imageLayout, - imageLayout); + renderPassAttachmentOps.initWithLoadStore(vk::kAttachmentIndexZero, imageAccess, + imageAccess); } else { attachmentClearValue = *clearValue; - renderPassAttachmentOps.setLayouts(vk::kAttachmentIndexZero, imageLayout, imageLayout); + renderPassAttachmentOps.setLayouts(vk::kAttachmentIndexZero, imageAccess, imageAccess); renderPassAttachmentOps.setClearOp(vk::kAttachmentIndexZero); renderPassAttachmentOps.setClearStencilOp(vk::kAttachmentIndexZero); } @@ -2560,16 +2547,19 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, if (aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT) { clearValues.storeColor(vk::kAttachmentIndexZero, attachmentClearValue); + ANGLE_TRY(contextVk->beginNewRenderPass( + std::move(renderPassFramebuffer), renderArea, renderPassDesc, renderPassAttachmentOps, + vk::PackedAttachmentCount(1), vk::kAttachmentIndexInvalid, clearValues, + commandBufferOut)); } else { clearValues.storeDepthStencil(vk::kAttachmentIndexZero, attachmentClearValue); + ANGLE_TRY(contextVk->beginNewRenderPass( + std::move(renderPassFramebuffer), renderArea, renderPassDesc, renderPassAttachmentOps, + vk::PackedAttachmentCount(0), vk::kAttachmentIndexZero, clearValues, commandBufferOut)); } - ANGLE_TRY(contextVk->beginNewRenderPass( - std::move(renderPassFramebuffer), renderArea, renderPassDesc, renderPassAttachmentOps, - vk::PackedAttachmentCount(1), vk::kAttachmentIndexInvalid, clearValues, commandBufferOut)); - contextVk->addGarbage(&framebuffer); return angle::Result::Continue; @@ -2786,14 +2776,14 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk, pipelineDesc.setRenderPassDesc(renderPassDesc); vk::RenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea, + ANGLE_TRY(startRenderPass(contextVk, &destView.get(), renderPassDesc, renderArea, VK_IMAGE_ASPECT_COLOR_BIT, nullptr, vk::RenderPassSource::InternalUtils, &commandBuffer)); UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0)); contextVk->onImageRenderPassWrite(dst->toGLLevel(params.dstMip), params.dstLayer, 1, - VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorWrite, dst); + VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageAccess::ColorWrite, dst); const uint32_t flags = GetImageClearFlags(dstActualFormat, 0, false); @@ -2830,84 +2820,33 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk, RenderPassClosureReason::TemporaryForImageClear); } -angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, - const vk::ImageView *srcView, - const BlitResolveParameters ¶ms) -{ - // The views passed to this function are already retained, so a render pass cannot be already - // open. Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and - // then the views are used in a new command buffer without having been retained for it. - // http://crbug.com/1272266#c22 - // - // Note that depth/stencil views for blit are not derived from a |Resource| class and are - // retained differently. - ASSERT(!contextVk->hasActiveRenderPass()); - - return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params); -} - -angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, - const vk::ImageView *srcDepthView, - const vk::ImageView *srcStencilView, - const BlitResolveParameters ¶ms) -{ - return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView, - params); -} - -angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, - const vk::ImageView *srcColorView, - const vk::ImageView *srcDepthView, - const vk::ImageView *srcStencilView, - const BlitResolveParameters ¶ms) +angle::Result UtilsVk::setupBlitResolveGraphicsProgram(ContextVk *contextVk, + const vk::ImageHelper &srcImage, + const vk::ImageView *srcColorView, + const vk::ImageView *srcDepthView, + const vk::ImageView *srcStencilView, + const vk::GraphicsPipelineDesc &pipelineDesc, + uint32_t flags, + uint32_t outputMask, + const BlitResolveParameters ¶ms, + vk::RenderPassCommandBuffer *commandBuffer, + bool blitColor, + bool blitDepth, + bool blitStencil) { - // Possible ways to resolve color are: - // - // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip - // images during resolve. - // - Manual resolve: A shader can read all samples from input, average them and output. - // - Using subpass resolve attachment: A shader can transform the sample colors from source to - // destination coordinates and the subpass resolve would finish the job. - // - // The first method is unable to handle flipping, so it's not generally applicable. The last - // method would have been great were we able to modify the last render pass that rendered into - // source, but still wouldn't be able to handle flipping. The second method is implemented in - // this function for complete control. - - // Possible ways to resolve depth/stencil are: - // - // - Manual resolve: A shader can read a samples from input and choose that for output. - // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This - // requires an extension that's not very well supported. - // - // The first method is implemented in this function. - - // Possible ways to blit color, depth or stencil are: - // - // - vkCmdBlitImage: This function works if the source and destination formats have the blit - // feature. - // - Manual blit: A shader can sample from the source image and write it to the destination. - // - // The first method has a serious shortcoming. GLES allows blit parameters to exceed the - // source or destination boundaries. The actual blit is clipped to these limits, but the - // scaling applied is determined solely by the input areas. Vulkan requires the blit parameters - // to be within the source and destination bounds. This makes it hard to keep the scaling - // constant. - // - // The second method is implemented in this function, which shares code with the resolve method. + // Either color is blitted/resolved or depth/stencil, but not both. + ASSERT(blitColor != (blitDepth || blitStencil)); vk::Renderer *renderer = contextVk->getRenderer(); - ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk)); - - bool isResolve = src->getSamples() > 1; + // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters + // etc are identical. + const bool isSrc3D = srcImage.getType() == VK_IMAGE_TYPE_3D; + ASSERT(!isSrc3D || (blitColor && srcImage.getSamples() == 1)); BlitResolveShaderParams shaderParams; + bool isResolve = srcImage.getSamples() > 1; + bool isDepthOrStencil = srcImage.isDepthOrStencil(); + // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these // Calculate*Offset() functions. if (isResolve) @@ -2922,13 +2861,15 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, shaderParams.stretch[1] = params.stretch[1]; shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0]; shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1]; - shaderParams.srcLayer = params.srcLayer; - shaderParams.samples = src->getSamples(); - shaderParams.invSamples = 1.0f / shaderParams.samples; - shaderParams.outputMask = framebuffer->getState().getEnabledDrawBuffers().bits(); - shaderParams.flipX = params.flipX; - shaderParams.flipY = params.flipY; - shaderParams.rotateXY = 0; + // Depth/stencil copy views are specific to the level/layer, so no need to offset them further. + shaderParams.srcMip = isDepthOrStencil ? 0 : params.srcMip.get(); + shaderParams.srcLayer = isDepthOrStencil ? 0 : params.srcLayer; + shaderParams.samples = srcImage.getSamples(); + shaderParams.invSamples = 1.0f / shaderParams.samples; + shaderParams.outputMask = outputMask; + shaderParams.flipX = params.flipX; + shaderParams.flipY = params.flipY; + shaderParams.rotateXY = 0; // Potentially make adjustments for pre-rotation. Depending on the angle some of the // shaderParams need to be adjusted. @@ -2959,98 +2900,26 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation); - bool blitColor = srcColorView != nullptr; - bool blitDepth = srcDepthView != nullptr; - bool blitStencil = srcStencilView != nullptr; - - // Either color is blitted/resolved or depth/stencil, but not both. - ASSERT(blitColor != (blitDepth || blitStencil)); - - // Linear sampling is only valid with color blitting. - ASSERT((blitColor && !isResolve) || !params.linear); - - uint32_t flags = - GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getIntendedFormat()); - flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0; - flags |= isResolve ? BlitResolve_frag::kIsResolve : 0; - Function function = Function::BlitResolve; - - // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters - // etc are identical. - const bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D; - ASSERT(!isSrc3D || (blitColor && !isResolve)); - if (isSrc3D) - { - flags = GetFormatFlags(src->getIntendedFormat(), Blit3DSrc_frag::kBlitInt, - Blit3DSrc_frag::kBlitUint, Blit3DSrc_frag::kBlitFloat); - } - - vk::GraphicsPipelineDesc pipelineDesc; - pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete, - contextVk->pipelineRobustness(), - contextVk->pipelineProtectedAccess()); - if (blitColor) - { - constexpr VkColorComponentFlags kAllColorComponents = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT; - - pipelineDesc.setColorWriteMasks( - gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue( - kAllColorComponents, gl::BlendStateExt::ColorMaskStorage::GetMask( - framebuffer->getRenderPassDesc().colorAttachmentRange())), - framebuffer->getEmulatedAlphaAttachmentMask(), ~gl::DrawBufferMask()); - } - else - { - pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask()); - } - pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc()); - if (blitDepth) - { - SetDepthStateForWrite(renderer, &pipelineDesc); - } - - if (blitStencil) - { - SetStencilStateForWrite(renderer, &pipelineDesc); - } - - // All deferred clear must have been flushed, otherwise it will conflict with params.blitArea. - ASSERT(!framebuffer->hasDeferredClears()); - vk::RenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr)); - VkDescriptorSet descriptorSet; ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(), Function::BlitResolve, &descriptorSet)); - // Pick layout consistent with GetImageReadLayout() to avoid unnecessary layout change. - vk::ImageLayout srcImagelayout = src->isDepthOrStencil() - ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead - : vk::ImageLayout::FragmentShaderReadOnly; - contextVk->onImageRenderPassRead(src->getAspectFlags(), srcImagelayout, src); - - UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(), - framebuffer->getState().getEnabledDrawBuffers()); - UpdateDepthStencilAccess(contextVk, blitDepth, blitStencil); - VkDescriptorImageInfo imageInfos[2] = {}; if (blitColor) { imageInfos[0].imageView = srcColorView->getHandle(); - imageInfos[0].imageLayout = src->getCurrentLayout(renderer); + imageInfos[0].imageLayout = srcImage.getCurrentLayout(renderer); } if (blitDepth) { imageInfos[0].imageView = srcDepthView->getHandle(); - imageInfos[0].imageLayout = src->getCurrentLayout(renderer); + imageInfos[0].imageLayout = srcImage.getCurrentLayout(renderer); } if (blitStencil) { imageInfos[1].imageView = srcStencilView->getHandle(); - imageInfos[1].imageLayout = src->getCurrentLayout(renderer); + imageInfos[1].imageLayout = srcImage.getCurrentLayout(renderer); } VkDescriptorImageInfo samplerInfo = {}; @@ -3100,15 +2969,284 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader)); } + Function function = Function::BlitResolve; + ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader, isSrc3D ? &mBlit3DSrc[flags] : &mBlitResolve[flags], &pipelineDesc, descriptorSet, &shaderParams, sizeof(shaderParams), commandBuffer)); + return angle::Result::Continue; +} + +angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk, + FramebufferVk *framebuffer, + vk::ImageHelper *srcImage, + const vk::ImageView *srcView, + const BlitResolveParameters ¶ms) +{ + // The views passed to this function are already retained, so a render pass cannot be already + // open. Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and + // then the views are used in a new command buffer without having been retained for it. + // http://crbug.com/1272266#c22 + ASSERT(!contextVk->hasActiveRenderPass()); + vk::Renderer *renderer = contextVk->getRenderer(); + + // Possible ways to resolve color are: + // + // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip + // images during resolve. + // - Manual resolve: A shader can read all samples from input, average them and output. + // - Using subpass resolve attachment: A shader can transform the sample colors from source to + // destination coordinates and the subpass resolve would finish the job. + // + // The first method is unable to handle flipping, so it's not generally applicable. The last + // method would have been great were we able to modify the last render pass that rendered into + // source, but still wouldn't be able to handle flipping. The second method is implemented in + // this function for complete control. + + // Possible ways to blit color, depth or stencil are: + // + // - vkCmdBlitImage: This function works if the source and destination formats have the blit + // feature. + // - Manual blit: A shader can sample from the source image and write it to the destination. + // + // The first method has a serious shortcoming. GLES allows blit parameters to exceed the + // source or destination boundaries. The actual blit is clipped to these limits, but the + // scaling applied is determined solely by the input areas. Vulkan requires the blit parameters + // to be within the source and destination bounds. This makes it hard to keep the scaling + // constant. + // + // The second method is implemented in this function, which shares code with the resolve method. + + ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk)); + + bool isResolve = srcImage->getSamples() > 1; + + ASSERT(srcView != nullptr); + // Linear sampling is only valid with color blitting. + ASSERT(!isResolve || !params.linear); + + uint32_t flags = GetColorBlitResolveFlags(srcImage->getIntendedFormat()); + flags |= srcImage->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0; + flags |= isResolve ? BlitResolve_frag::kIsResolve : 0; + + // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters + // etc are identical. + const bool isSrc3D = srcImage->getType() == VK_IMAGE_TYPE_3D; + ASSERT(!isSrc3D || !isResolve); + if (isSrc3D) + { + flags = GetFormatFlags(srcImage->getIntendedFormat(), Blit3DSrc_frag::kBlitInt, + Blit3DSrc_frag::kBlitUint, Blit3DSrc_frag::kBlitFloat); + } + + vk::GraphicsPipelineDesc pipelineDesc; + pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete, + contextVk->pipelineRobustness(), + contextVk->pipelineProtectedAccess()); + + vk::ImageAccess srcImagelayout = srcImage->isDepthOrStencil() + ? vk::ImageAccess::DepthReadStencilReadFragmentShaderRead + : vk::ImageAccess::FragmentShaderReadOnly; + + constexpr VkColorComponentFlags kAllColorComponents = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT; + + pipelineDesc.setColorWriteMasks( + gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue( + kAllColorComponents, gl::BlendStateExt::ColorMaskStorage::GetMask( + framebuffer->getRenderPassDesc().colorAttachmentRange())), + framebuffer->getEmulatedAlphaAttachmentMask(), ~gl::DrawBufferMask()); + + for (size_t colorIndexGL : framebuffer->getState().getEnabledDrawBuffers()) + { + if (&framebuffer->getColorDrawRenderTarget(colorIndexGL)->getImageForWrite() == srcImage) + { + srcImagelayout = vk::ImageAccess::ColorWriteFragmentShaderFeedback; + break; + } + } + + pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc()); + + // All deferred clear must have been flushed, otherwise it will conflict with + // params.blitArea. + ASSERT(!framebuffer->hasDeferredClears()); + vk::RenderPassCommandBuffer *commandBuffer; + ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr)); + + // Pick layout consistent with GetImageReadAccess() to avoid unnecessary layout change. + contextVk->onImageRenderPassRead(srcImage->getAspectFlags(), srcImagelayout, srcImage); + + UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(), + framebuffer->getState().getEnabledDrawBuffers()); + + if (srcImagelayout == vk::ImageAccess::ColorWriteFragmentShaderFeedback) + { + srcImage->setRenderPassUsageFlag(vk::RenderPassUsage::ColorTextureSampler); + } + + ANGLE_TRY(setupBlitResolveGraphicsProgram( + contextVk, *srcImage, srcView, nullptr, nullptr, pipelineDesc, flags, + framebuffer->getState().getEnabledDrawBuffers().bits(), params, commandBuffer, true, false, + false)); + // Set dynamic state VkViewport viewport; - gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk); - gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, false, completeRenderArea.height, + gl_vk::GetViewport(params.renderArea, 0.0f, 1.0f, false, false, params.renderArea.height, + &viewport); + commandBuffer->setViewport(0, 1, &viewport); + + VkRect2D scissor = gl_vk::GetRect(params.blitArea); + commandBuffer->setScissor(0, 1, &scissor); + + SetDepthDynamicStateForUnused(renderer, commandBuffer); + SetStencilDynamicStateForUnused(renderer, commandBuffer); + + // Note: this utility starts the render pass directly, thus bypassing + // ContextVk::startRenderPass. As such, occlusion queries are not enabled. + commandBuffer->draw(3, 0); + + // The renderPass stared by UtilsVk may not exact the same as FramebufferVk's. So dont try to + // reactivate. + contextVk->disableRenderPassReactivation(); + + return angle::Result::Continue; +} + +angle::Result UtilsVk::depthStencilBlitResolve( + ContextVk *contextVk, + vk::RenderPassCommandBufferHelper *renderPassCommands, + vk::ImageHelper *dstImage, + const vk::ImageView &dstImageView, + gl::LevelIndex dstImageLevel, + uint32_t dstImageLayer, + vk::ImageHelper *srcImage, + const vk::ImageView *srcDepthView, + const vk::ImageView *srcStencilView, + const BlitResolveParameters ¶ms) +{ + // Possible ways to resolve depth/stencil are: + // + // - Manual resolve: A shader can read a samples from input and choose that for output. + // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This + // requires an extension that's not very well supported. + // + // The first method is implemented in this function. + + // Possible ways to blit color, depth or stencil are: + // + // - vkCmdBlitImage: This function works if the source and destination formats have the blit + // feature. + // - Manual blit: A shader can sample from the source image and write it to the destination. + // + // The first method has a serious shortcoming. GLES allows blit parameters to exceed the + // source or destination boundaries. The actual blit is clipped to these limits, but the + // scaling applied is determined solely by the input areas. Vulkan requires the blit parameters + // to be within the source and destination bounds. This makes it hard to keep the scaling + // constant. + // + // The second method is implemented in this function, which shares code with the resolve method. + vk::Renderer *renderer = contextVk->getRenderer(); + ASSERT(renderPassCommands == nullptr || renderPassCommands->started()); + + ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk)); + + bool isResolve = srcImage->getSamples() > 1; + bool blitDepth = srcDepthView != nullptr; + bool blitStencil = srcStencilView != nullptr; + + ASSERT(blitDepth || blitStencil); + // Linear sampling is only valid with color blitting. + ASSERT(!params.linear); + + uint32_t flags = GetDepthStencilBlitResolveFlags(blitDepth, blitStencil); + flags |= isResolve ? BlitResolve_frag::kIsResolve : 0; + + // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters + // etc are identical. + ASSERT(srcImage->getType() != VK_IMAGE_TYPE_3D); + + const vk::RenderPassDesc *renderPassDesc; + vk::RenderPassDesc standaloneRenderPassDesc; + if (renderPassCommands != nullptr) + { + renderPassCommands->growRenderArea(contextVk, params.renderArea); + // If renderPassCommands is not null, use it instead of create a new one. + renderPassDesc = &renderPassCommands->getRenderPassDesc(); + } + else + { + standaloneRenderPassDesc.setSamples(dstImage->getSamples()); + standaloneRenderPassDesc.packDepthStencilAttachment(dstImage->getActualFormatID()); + renderPassDesc = &standaloneRenderPassDesc; + } + + vk::GraphicsPipelineDesc pipelineDesc; + pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete, + contextVk->pipelineRobustness(), + contextVk->pipelineProtectedAccess()); + + vk::ImageAccess srcImagelayout = vk::ImageAccess::DepthReadStencilReadFragmentShaderRead; + + pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask()); + pipelineDesc.setRenderPassDesc(*renderPassDesc); + if (blitDepth) + { + SetDepthStateForWrite(renderer, &pipelineDesc); + } + + if (blitStencil) + { + SetStencilStateForWrite(renderer, &pipelineDesc); + } + + if (dstImage == srcImage) + { + srcImagelayout = vk::ImageAccess::DepthStencilFragmentShaderFeedback; + } + + vk::RenderPassCommandBuffer *commandBuffer; + if (renderPassCommands != nullptr) + { + commandBuffer = &renderPassCommands->getCommandBuffer(); + } + else + { + ANGLE_TRY(startRenderPass(contextVk, &dstImageView, *renderPassDesc, params.renderArea, + dstImage->getAspectFlags(), nullptr, + vk::RenderPassSource::InternalUtils, &commandBuffer)); + ASSERT(commandBuffer != nullptr); + + contextVk->onDepthStencilDraw(dstImageLevel, dstImageLayer, 1, dstImage, nullptr, {}); + } + + // Pick layout consistent with GetImageReadAccess() to avoid unnecessary layout change. + contextVk->onImageRenderPassRead(srcImage->getAspectFlags(), srcImagelayout, srcImage); + + UpdateDepthStencilAccess(contextVk, blitDepth, blitStencil); + + if (srcImagelayout == vk::ImageAccess::DepthStencilFragmentShaderFeedback) + { + if (blitDepth) + { + srcImage->setRenderPassUsageFlag(vk::RenderPassUsage::DepthTextureSampler); + } + if (blitStencil) + { + srcImage->setRenderPassUsageFlag(vk::RenderPassUsage::StencilTextureSampler); + } + } + + ANGLE_TRY(setupBlitResolveGraphicsProgram(contextVk, *srcImage, nullptr, srcDepthView, + srcStencilView, pipelineDesc, flags, 0, params, + commandBuffer, false, blitDepth, blitStencil)); + + // Set dynamic state + VkViewport viewport; + gl_vk::GetViewport(params.renderArea, 0.0f, 1.0f, false, false, params.renderArea.height, &viewport); commandBuffer->setViewport(0, 1, &viewport); @@ -3144,26 +3282,36 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, // ContextVk::startRenderPass. As such, occlusion queries are not enabled. commandBuffer->draw(3, 0); - // Don't allow this render pass to be reactivated by the user's draw call due to test flakiness - // on win/intel bot. - contextVk->disableRenderPassReactivation(); + if (renderPassCommands != nullptr) + { + contextVk->restoreAllGraphicsState(); + } + else + { + // The renderPass stared by UtilsVk may not exact the same as FramebufferVk's. So dont try + // to reactivate. + contextVk->disableRenderPassReactivation(); + } return angle::Result::Continue; } angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, + vk::ImageHelper *dstImage, + gl::LevelIndex dstLevelIndex, + uint32_t dstLayerIndex, + vk::ImageHelper *srcImage, const vk::ImageView *srcStencilView, const BlitResolveParameters ¶ms) { + ASSERT((dstImage->getAspectFlags() & VK_IMAGE_ASPECT_STENCIL_BIT) != 0); vk::Renderer *renderer = contextVk->getRenderer(); // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a // temporary buffer which is then copied into the stencil aspect of the image. ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk)); - bool isResolve = src->getSamples() > 1; + bool isResolve = srcImage->getSamples() > 1; // Create a temporary buffer to blit/resolve stencil into. vk::RendererScoped blitBuffer(renderer); @@ -3191,8 +3339,10 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, shaderParams.stretch[1] = params.stretch[1]; shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0]; shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1]; - shaderParams.srcLayer = params.srcLayer; + // Depth/stencil copy views are specific to the layer, so no need to offset it further. + shaderParams.srcLayer = 0; shaderParams.srcWidth = params.srcExtents[0]; + shaderParams.srcHeight = params.srcExtents[1]; shaderParams.dstPitch = bufferRowLengthInUints; shaderParams.blitArea[0] = params.blitArea.x; shaderParams.blitArea[1] = params.blitArea.y; @@ -3234,25 +3384,27 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, // Linear sampling is only valid with color blitting. ASSERT(!params.linear); - uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0; - flags |= isResolve ? BlitResolve_frag::kIsResolve : 0; - - RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget(); - ASSERT(depthStencilRenderTarget != nullptr); - vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImageForWrite(); + uint32_t flags = isResolve ? BlitResolveStencilNoExport_comp::kIsResolve : 0; // Change layouts prior to computation. - vk::CommandBufferAccess access; - access.onImageComputeShaderRead(src->getAspectFlags(), src); - access.onImageTransferWrite(depthStencilRenderTarget->getLevelIndex(), 1, - depthStencilRenderTarget->getLayerIndex(), 1, - depthStencilImage->getAspectFlags(), depthStencilImage); - access.onBufferComputeShaderWrite(&blitBuffer.get()); + vk::CommandResources resources; + if (dstImage != srcImage) + { + resources.onImageComputeShaderRead(srcImage->getAspectFlags(), srcImage); + resources.onImageTransferWrite(dstLevelIndex, 1, dstLayerIndex, 1, + dstImage->getAspectFlags(), dstImage); + } + else + { + resources.onImageSelfCopy(dstLevelIndex, 1, dstLayerIndex, 1, dstLevelIndex, 1, + params.srcLayer, 1, srcImage->getAspectFlags(), srcImage); + } + resources.onBufferComputeShaderWrite(&blitBuffer.get()); VkDescriptorSet descriptorSet; vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); commandBuffer = &commandBufferHelper->getCommandBuffer(); ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::BlitResolveStencilNoExport, &descriptorSet)); @@ -3260,7 +3412,7 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, // Blit/resolve stencil into the buffer. VkDescriptorImageInfo imageInfo = {}; imageInfo.imageView = srcStencilView->getHandle(); - imageInfo.imageLayout = src->getCurrentLayout(renderer); + imageInfo.imageLayout = srcImage->getCurrentLayout(renderer); VkDescriptorBufferInfo bufferInfo = {}; bufferInfo.buffer = blitBuffer.get().getBuffer().getHandle(); @@ -3319,9 +3471,8 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t); region.bufferImageHeight = params.blitArea.height; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - region.imageSubresource.mipLevel = - depthStencilImage->toVkLevel(depthStencilRenderTarget->getLevelIndex()).get(); - region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex(); + region.imageSubresource.mipLevel = dstImage->toVkLevel(dstLevelIndex).get(); + region.imageSubresource.baseArrayLayer = dstLayerIndex; region.imageSubresource.layerCount = 1; region.imageOffset.x = params.blitArea.x; region.imageOffset.y = params.blitArea.y; @@ -3330,9 +3481,101 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, region.imageExtent.height = params.blitArea.height; region.imageExtent.depth = 1; - commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(), - depthStencilImage->getImage(), - depthStencilImage->getCurrentLayout(renderer), 1, ®ion); + commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(), dstImage->getImage(), + dstImage->getCurrentLayout(renderer), 1, ®ion); + + return angle::Result::Continue; +} + +angle::Result UtilsVk::copyImageFromTileMemory(ContextVk *contextVk, + const VkImageAspectFlags aspectFlags, + vk::ImageHelper *dstImage, + vk::ImageHelper *srcImage) +{ + ASSERT(srcImage->useTileMemory()); + ASSERT(!dstImage->useTileMemory()); + // tile memory image are simple 2D single sampled depth stencil image + ASSERT(srcImage->getSamples() == 1 && dstImage->getSamples() == 1); + ASSERT(srcImage->getLayerCount() == 1 && dstImage->getLayerCount() == 1); + ASSERT(srcImage->getLevelCount() == 1 && dstImage->getLevelCount() == 1); + ASSERT(srcImage->getActualFormatID() == dstImage->getActualFormatID()); + ASSERT(srcImage->getActualFormat().hasDepthOrStencilBits()); + ASSERT(srcImage->isVkImageContentDefined()); + + const angle::FormatID formatID = srcImage->getActualFormatID(); + const bool blitDepthBuffer = (aspectFlags & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; + const bool blitStencilBuffer = (aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; + + const int width = static_cast(dstImage->getExtents().width); + const int height = static_cast(dstImage->getExtents().height); + const gl::Rectangle renderArea = {0, 0, width, height}; + + UtilsVk::BlitResolveParameters params = {}; + params.stretch[0] = 1.0f; + params.stretch[1] = 1.0f; + params.srcExtents[0] = width; + params.srcExtents[1] = height; + params.renderArea.width = width; + params.renderArea.height = height; + params.blitArea.width = width; + params.blitArea.height = height; + params.rotation = SurfaceRotation::Identity; + + const bool hasShaderStencilExport = + contextVk->getFeatures().supportsShaderStencilExport.enabled; + + vk::DeviceScoped srcDepthView(contextVk->getDevice()); + vk::DeviceScoped srcStencilView(contextVk->getDevice()); + + if (blitDepthBuffer) + { + ANGLE_TRY(srcImage->initReinterpretedLayerImageView( + contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_DEPTH_BIT, gl::SwizzleState(), + &srcDepthView.get(), vk::LevelIndex(0), 1, 0, 1, + vk::ImageHelper::kDefaultImageViewUsageFlags, formatID, GL_NONE)); + } + + if (blitStencilBuffer) + { + ANGLE_TRY(srcImage->initReinterpretedLayerImageView( + contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_STENCIL_BIT, gl::SwizzleState(), + &srcStencilView.get(), vk::LevelIndex(0), 1, 0, 1, + vk::ImageHelper::kDefaultImageViewUsageFlags, formatID, GL_NONE)); + } + + if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport)) + { + vk::DeviceScoped dstDepthStencilImageView(contextVk->getDevice()); + ANGLE_TRY(dstImage->initReinterpretedLayerImageView( + contextVk, gl::TextureType::_2D, aspectFlags, gl::SwizzleState(), + &dstDepthStencilImageView.get(), vk::LevelIndex(0), 1, 0, 1, + vk::ImageHelper::kDefaultImageViewUsageFlags, formatID, GL_NONE)); + + ANGLE_TRY(depthStencilBlitResolve( + contextVk, nullptr, dstImage, dstDepthStencilImageView.get(), gl::LevelIndex(0), 0, + srcImage, blitDepthBuffer ? &srcDepthView.get() : nullptr, + (blitStencilBuffer && hasShaderStencilExport) ? &srcStencilView.get() : nullptr, + params)); + + vk::ImageView dstDepthViewObject = dstDepthStencilImageView.release(); + contextVk->addGarbage(&dstDepthViewObject); + } + + // If shader stencil export is not present, blit stencil through a different path. + if (blitStencilBuffer && !hasShaderStencilExport) + { + ANGLE_TRY(stencilBlitResolveNoShaderExport(contextVk, dstImage, gl::LevelIndex(0), 0, + srcImage, &srcStencilView.get(), params)); + } + + vk::ImageView srcDepthViewObject = srcDepthView.release(); + contextVk->addGarbage(&srcDepthViewObject); + + vk::ImageView stencilViewObject = srcStencilView.release(); + contextVk->addGarbage(&stencilViewObject); + + ANGLE_TRY(contextVk->flushCommandsAndEndRenderPassWithoutSubmit( + RenderPassClosureReason::TileMemorySimulatedClear)); return angle::Result::Continue; } @@ -3361,8 +3604,13 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, vk::SamplerDesc samplerDesc; if (isYUV) { - samplerDesc = vk::SamplerDesc(contextVk, gl::SamplerState(), false, - &src->getYcbcrConversionDesc(), srcIntendedFormat.id); + // copyYuvWithoutColorConversion indicates whether we need to perform the copy + // with or without color conversion + const vk::YcbcrConversionDesc ycbcrConversionDesc = params.copyYuvWithoutColorConversion + ? src->getY2YConversionDesc() + : src->getYcbcrConversionDesc(); + samplerDesc = vk::SamplerDesc(contextVk, gl::SamplerState(), false, &ycbcrConversionDesc, + srcIntendedFormat.id); ANGLE_TRY(ensureImageCopyResourcesInitializedWithSampler(contextVk, samplerDesc)); } @@ -3380,7 +3628,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, shaderParams.dstIsAlpha = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0; shaderParams.dstDefaultChannelsMask = GetFormatDefaultChannelMask(dst->getIntendedFormat(), dst->getActualFormat()); - shaderParams.srcMip = params.srcMip; + shaderParams.srcMip = params.srcMip.get(); shaderParams.srcLayer = params.srcLayer; shaderParams.srcSampleCount = params.srcSampleCount; shaderParams.srcOffset[0] = params.srcOffset[0]; @@ -3466,7 +3714,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, } vk::RenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea, + ANGLE_TRY(startRenderPass(contextVk, destView, renderPassDesc, renderArea, VK_IMAGE_ASPECT_COLOR_BIT, nullptr, vk::RenderPassSource::InternalUtils, &commandBuffer)); @@ -3486,9 +3734,9 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, // Change source layout inside render pass. contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::FragmentShaderReadOnly, src); + vk::ImageAccess::FragmentShaderReadOnly, src); contextVk->onImageRenderPassWrite(params.dstMip, params.dstLayer, 1, VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::ColorWrite, dst); + vk::ImageAccess::ColorWrite, dst); VkDescriptorImageInfo imageInfo = {}; imageInfo.imageView = srcView->getHandle(); @@ -3643,19 +3891,19 @@ angle::Result UtilsVk::copyImageBits(ContextVk *contextVk, bool isDst3D = dst->getType() == VK_IMAGE_TYPE_3D; // Change layouts prior to computation. - vk::CommandBufferAccess access; - access.onImageTransferRead(src->getAspectFlags(), src); - access.onImageTransferWrite(params.dstLevel, 1, isDst3D ? 0 : params.dstOffset[2], - isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT, - dst); + vk::CommandResources resources; + resources.onImageTransferRead(src->getAspectFlags(), src); + resources.onImageTransferWrite(params.dstLevel, 1, isDst3D ? 0 : params.dstOffset[2], + isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT, + dst); // srcBuffer is the destination of copyImageToBuffer() below. - access.onBufferTransferWrite(&srcBuffer.get()); - access.onBufferComputeShaderWrite(&dstBuffer.get()); + resources.onBufferTransferWrite(&srcBuffer.get()); + resources.onBufferComputeShaderWrite(&dstBuffer.get()); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); commandBuffer = &commandBufferHelper->getCommandBuffer(); // Copy src into buffer, completely packed. @@ -3807,6 +4055,7 @@ angle::Result UtilsVk::copyImageToBuffer(ContextVk *contextVk, const CopyImageToBufferParameters ¶ms) { vk::Renderer *renderer = contextVk->getRenderer(); + ANGLE_TRY(ensureCopyImageToBufferResourcesInitialized(contextVk)); const angle::Format &srcFormat = src->getActualFormat(); @@ -3855,14 +4104,14 @@ angle::Result UtilsVk::copyImageToBuffer(ContextVk *contextVk, ANGLE_TRY(src->initReinterpretedLayerImageView( contextVk, textureType, src->getAspectFlags(), swizzle, &srcView.get(), params.srcMip, 1, textureType == gl::TextureType::_2D ? params.srcLayer : 0, 1, VK_IMAGE_USAGE_SAMPLED_BIT, - linearFormat)); + linearFormat, GL_NONE)); - vk::CommandBufferAccess access; - access.onImageComputeShaderRead(src->getAspectFlags(), src); - access.onBufferComputeShaderWrite(dst); + vk::CommandResources resources; + resources.onImageComputeShaderRead(src->getAspectFlags(), src); + resources.onBufferComputeShaderWrite(dst); vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); vk::OutsideRenderPassCommandBuffer *commandBuffer; commandBuffer = &commandBufferHelper->getCommandBuffer(); @@ -3923,11 +4172,11 @@ angle::Result UtilsVk::copyRgbToRgba(ContextVk *contextVk, { vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; - vk::CommandBufferAccess access; - access.onBufferComputeShaderRead(srcBuffer); - access.onBufferComputeShaderWrite(dstBuffer); + vk::CommandResources resources; + resources.onBufferComputeShaderRead(srcBuffer); + resources.onBufferComputeShaderWrite(dstBuffer); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); rx::UtilsVk::ConvertVertexShaderParams shaderParams; shaderParams.Ns = 3; // src channels @@ -4008,8 +4257,10 @@ angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk, vk::ImageHelper *dstImage, const VkBufferImageCopy *copyRegion) { + vk::Renderer *renderer = contextVk->getRenderer(); + ANGLE_TRY(ensureTransCodeEtcToBcResourcesInitialized(contextVk)); - vk::Renderer *renderer = contextVk->getRenderer(); + const angle::Format &intendedFormat = dstImage->getIntendedFormat(); vk::ContextScoped bufferViewHelper(contextVk); const gl::InternalFormat &info = @@ -4036,7 +4287,7 @@ angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk, bufferViewHelper.get().init(renderer, 0, texBufferSize); ANGLE_TRY(bufferViewHelper.get().getView( contextVk, *srcBuffer, copyRegion->bufferOffset, - renderer->getFormat(GetCompactibleUINTFormat(intendedFormat)), &srcBufferView)); + renderer->getFormat(GetCompactibleUINTFormat(intendedFormat)), &srcBufferView, nullptr)); vk::LevelIndex dstLevel = gl::LevelIndexWrapper(copyRegion->imageSubresource.mipLevel); @@ -4076,7 +4327,7 @@ angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk, writeDescriptorSet[0].pTexelBufferView = &bufferView; VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + imageInfo.imageLayout = dstImage->getCurrentLayout(renderer); writeDescriptorSet[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeDescriptorSet[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; writeDescriptorSet[1].dstBinding = 1; @@ -4089,7 +4340,7 @@ angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk, ANGLE_TRY(dstImage->initReinterpretedLayerImageView( contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), &scopedImageView.get(), dstLevel, 1, copyRegion->imageSubresource.baseArrayLayer + i, 1, - VK_IMAGE_USAGE_STORAGE_BIT, GetCompactibleUINTFormat(intendedFormat))); + VK_IMAGE_USAGE_STORAGE_BIT, GetCompactibleUINTFormat(intendedFormat), GL_NONE)); imageInfo.imageView = scopedImageView.get().getHandle(); VkDescriptorSet descriptorSet; @@ -4226,18 +4477,18 @@ angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk, vk::LevelIndex maxLevelVK = baseLevelVK + (levelCount - 1); // Transition entire image to color attachment layout - vk::CommandBufferAccess access; - access.onImageDrawMipmapGenerationWrite(baseLevelGL, levelCount, 0, layerCount, - VK_IMAGE_ASPECT_COLOR_BIT, image); + vk::CommandResources resources; + resources.onImageDrawMipmapGenerationWrite(baseLevelGL, levelCount, 0, layerCount, + VK_IMAGE_ASPECT_COLOR_BIT, image); vk::OutsideRenderPassCommandBuffer *outsideCommandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &outsideCommandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &outsideCommandBuffer)); gl::TextureType textureType = vk::Get2DTextureType(layerCount, sampleCount); gl::SwizzleState swizzle = {}; VkImageUsageFlags imageUsageFlags = image->getUsage(); // Setup shaders for draw - uint32_t flags = GetBlitResolveFlags(true, false, false, actualFormat); + uint32_t flags = GetColorBlitResolveFlags(actualFormat); flags |= layerCount > 1 ? BlitResolve_frag::kSrcIsArray : 0; Function function = Function::BlitResolve; @@ -4276,9 +4527,13 @@ angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk, pipelineDesc.setRasterizationSamples(sampleCount); pipelineDesc.setRenderPassDesc(renderPassDesc); + const VkImageLayout drawLayout = image->getCurrentLayout(renderer); + const VkImageLayout readLayout = + renderer->getVkImageLayout(vk::ImageAccess::FragmentShaderReadOnly); + // Setup write descriptors VkDescriptorImageInfo imageInfos = {}; - imageInfos.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfos.imageLayout = readLayout; VkDescriptorImageInfo samplerInfo = {}; samplerInfo.sampler = isMipmapFiltered ? mLinearSampler.getHandle() : mPointSampler.getHandle(); @@ -4307,9 +4562,9 @@ angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk, barrier.subresourceRange.layerCount = layerCount; barrier.subresourceRange.baseMipLevel = baseLevelVK.get(); barrier.subresourceRange.levelCount = 1; - barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barrier.oldLayout = drawLayout; barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.newLayout = readLayout; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; // Sample from mipLevel N and draw to mipLevel N+1 @@ -4342,15 +4597,15 @@ angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk, vk::ImageView srcImageView; ANGLE_TRY(image->initReinterpretedLayerImageView( contextVk, textureType, image->getAspectFlags(), swizzle, &srcImageView, srcLevelVk, - 1, currentLayer, 1, imageUsageFlags, actualFormatID)); + 1, currentLayer, 1, imageUsageFlags, actualFormatID, GL_NONE)); vk::ImageView dstImageView; ANGLE_TRY(image->initReinterpretedLayerImageView( contextVk, textureType, image->getAspectFlags(), swizzle, &dstImageView, dstLevelVk, - 1, currentLayer, 1, imageUsageFlags, actualFormatID)); + 1, currentLayer, 1, imageUsageFlags, actualFormatID, GL_NONE)); vk::RenderPassCommandBuffer *commandBuffer = nullptr; - ANGLE_TRY(startRenderPass(contextVk, image, &dstImageView, renderPassDesc, renderArea, + ANGLE_TRY(startRenderPass(contextVk, &dstImageView, renderPassDesc, renderArea, VK_IMAGE_ASPECT_COLOR_BIT, nullptr, vk::RenderPassSource::InternalUtils, &commandBuffer)); @@ -4402,7 +4657,7 @@ angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier); // Update image's layout related state to shader read only optimal layout - image->setCurrentImageLayout(renderer, vk::ImageLayout::FragmentShaderReadOnly); + image->setCurrentImageAccess(renderer, vk::ImageAccess::FragmentShaderReadOnly); return angle::Result::Continue; } @@ -4496,6 +4751,9 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk, (params.unresolveDepth ? 1 : 0) + (unresolveStencilWithShaderExport ? 1 : 0); const uint32_t totalBindingCount = colorAttachmentCount + depthStencilBindingCount; + const VkImageLayout readLayout = + renderer->getVkImageLayout(vk::ImageAccess::FragmentShaderReadOnly); + if (totalBindingCount > 0) { const Function function = static_cast( @@ -4523,15 +4781,13 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk, if (unresolveStencilWithShaderExport) { inputImageInfo[inputBindingIndex].imageView = stencilSrcView->getHandle(); - inputImageInfo[inputBindingIndex].imageLayout = - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + inputImageInfo[inputBindingIndex].imageLayout = readLayout; ++inputBindingIndex; } if (params.unresolveDepth) { inputImageInfo[inputBindingIndex].imageView = depthSrcView->getHandle(); - inputImageInfo[inputBindingIndex].imageLayout = - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + inputImageInfo[inputBindingIndex].imageLayout = readLayout; ++inputBindingIndex; } @@ -4540,8 +4796,7 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk, { inputImageInfo[inputBindingIndex].imageView = colorSrcView[attachmentIndex]->getHandle(); - inputImageInfo[inputBindingIndex].imageLayout = - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + inputImageInfo[inputBindingIndex].imageLayout = readLayout; ++inputBindingIndex; } @@ -4621,7 +4876,7 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk, VkDescriptorImageInfo stencilImageInfo = {}; stencilImageInfo.imageView = stencilSrcView->getHandle(); - stencilImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + stencilImageInfo.imageLayout = readLayout; VkWriteDescriptorSet stencilWriteInfo = {}; stencilWriteInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -4715,7 +4970,7 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk, // A potential optimization is to reuse the already open render pass if it belongs to the // swapchain. vk::RenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea, + ANGLE_TRY(startRenderPass(contextVk, destView, renderPassDesc, renderArea, VK_IMAGE_ASPECT_COLOR_BIT, nullptr, vk::RenderPassSource::DefaultFramebuffer, &commandBuffer)); @@ -4731,9 +4986,9 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk, commandBufferHelper->retainResource(textWidgetsBuffer); commandBufferHelper->retainResource(graphWidgetsBuffer); contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::FragmentShaderReadOnly, font); + vk::ImageAccess::FragmentShaderReadOnly, font); contextVk->onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, - vk::ImageLayout::ColorWrite, dst); + vk::ImageAccess::ColorWrite, dst); VkDescriptorImageInfo imageInfo = {}; imageInfo.imageView = fontView->getHandle(); @@ -4830,6 +5085,8 @@ angle::Result UtilsVk::generateFragmentShadingRate( vk::ImageViewHelper *shadingRateAttachmentImageViewHelper, const GenerateFragmentShadingRateParameters &shadingRateParameters) { + vk::Renderer *renderer = contextVk->getRenderer(); + ANGLE_TRY(ensureGenerateFragmentShadingRateResourcesInitialized(contextVk)); // Each workgroup processes an 8x8 tile of the image. @@ -4841,23 +5098,22 @@ angle::Result UtilsVk::generateFragmentShadingRate( // Setup compute shader vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper; - vk::CommandBufferAccess access = {}; + vk::CommandResources resources = {}; // Fragment shading rate image will always have 1 layer. - access.onImageComputeShaderWrite(shadingRateAttachmentImageHelper->getFirstAllocatedLevel(), - shadingRateAttachmentImageHelper->getLevelCount(), 0, - shadingRateAttachmentImageHelper->getLayerCount(), - shadingRateAttachmentImageHelper->getAspectFlags(), - shadingRateAttachmentImageHelper); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper)); + resources.onImageComputeShaderWrite(shadingRateAttachmentImageHelper->getFirstAllocatedLevel(), + shadingRateAttachmentImageHelper->getLevelCount(), 0, + shadingRateAttachmentImageHelper->getLayerCount(), + shadingRateAttachmentImageHelper->getAspectFlags(), + shadingRateAttachmentImageHelper); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(resources, &commandBufferHelper)); VkDescriptorSet descriptorSet; ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::GenerateFragmentShadingRate, &descriptorSet)); VkDescriptorImageInfo destShadingRateImage = {}; destShadingRateImage.imageView = shadingRateAttachmentImageViewHelper->getFragmentShadingRateImageView().getHandle(); - destShadingRateImage.imageLayout = - shadingRateAttachmentImageHelper->getCurrentLayout(contextVk->getRenderer()); + destShadingRateImage.imageLayout = shadingRateAttachmentImageHelper->getCurrentLayout(renderer); destShadingRateImage.sampler = mPointSampler.getHandle(); VkWriteDescriptorSet writeInfos[1] = {}; writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -4985,11 +5241,11 @@ angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *con ANGLE_TRACE_EVENT0("gpu.angle", "LineLoopHelper::getIndexBufferForElementArrayBuffer"); void *srcDataMapping = nullptr; - ANGLE_TRY(elementArrayBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &srcDataMapping)); + ANGLE_TRY(elementArrayBufferVk->mapForReadAccessOnly(contextVk, &srcDataMapping)); ANGLE_TRY(streamIndices(contextVk, glIndexType, indexCount, static_cast(srcDataMapping) + elementArrayOffset, bufferOut, indexCountOut)); - ANGLE_TRY(elementArrayBufferVk->unmapImpl(contextVk)); + ANGLE_TRY(elementArrayBufferVk->unmapReadAccessOnly(contextVk)); return angle::Result::Continue; } @@ -5011,12 +5267,12 @@ angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *con {sourceOffset, indexBuffer->getOffset() + unitCount * unitSize, unitSize}, }; - vk::CommandBufferAccess access; - access.onBufferTransferWrite(indexBuffer); - access.onBufferTransferRead(sourceBuffer); + vk::CommandResources resources; + resources.onBufferTransferWrite(indexBuffer); + resources.onBufferTransferRead(sourceBuffer); vk::OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); commandBuffer->copyBuffer(sourceBuffer->getBuffer(), indexBuffer->getBuffer(), static_cast(copies.size()), copies.data()); @@ -5044,14 +5300,18 @@ angle::Result LineLoopHelper::streamIndices(ContextVk *contextVk, } *indexCountOut = numOutIndices; - ANGLE_TRY(contextVk->initBufferForVertexConversion( - &mDynamicIndexBuffer, unitSize * numOutIndices, vk::MemoryHostVisibility::Visible)); + // Make sure indexBufferSize not zero, otherwise VMA may hit assertion. + size_t indexBufferSize = numOutIndices > 0 ? unitSize * numOutIndices : unitSize; + + ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, indexBufferSize, + vk::MemoryHostVisibility::Visible)); vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer(); uint8_t *indices = indexBuffer->getMappedMemory(); if (contextVk->getState().isPrimitiveRestartEnabled()) { - HandlePrimitiveRestart(contextVk, glIndexType, indexCount, srcPtr, indices); + rx::StreamEmulatedLineLoopIndices(glIndexType, indexCount, srcPtr, indices, + !contextVk->getFeatures().supportsIndexTypeUint8.enabled); } else { diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.h b/src/libANGLE/renderer/vulkan/UtilsVk.h index 47a1a981b99..5c7ec307a5b 100644 --- a/src/libANGLE/renderer/vulkan/UtilsVk.h +++ b/src/libANGLE/renderer/vulkan/UtilsVk.h @@ -135,9 +135,12 @@ class UtilsVk : angle::NonCopyable float stretch[2]; // |srcExtents| is used to normalize source coordinates for sampling. int srcExtents[2]; + // render area, which maps to VkViewport + gl::Rectangle renderArea; // |blitArea| is the area in destination where blit happens. It's expected that scissor // and source clipping effects have already been applied to it. gl::Rectangle blitArea; + vk::LevelIndex srcMip; int srcLayer; // Whether linear or point sampling should be used. bool linear; @@ -162,7 +165,7 @@ class UtilsVk : angle::NonCopyable int srcOffset[2]; int srcExtents[2]; int dstOffset[2]; - int srcMip; + vk::LevelIndex srcMip; int srcLayer; int srcSampleCount; int srcHeight; @@ -175,6 +178,7 @@ class UtilsVk : angle::NonCopyable SurfaceRotation srcRotation; GLenum srcColorEncoding; GLenum dstColorEncoding; + bool copyYuvWithoutColorConversion; }; struct CopyImageBitsParameters @@ -266,10 +270,15 @@ class UtilsVk : angle::NonCopyable const ConvertVertexParameters ¶ms, const OffsetAndVertexCounts &additionalOffsetVertexCounts); + // For VK_QCOM_tile_memory_heap + angle::Result clearTextureNoFlush(ContextVk *contextVk, + vk::ImageHelper *dst, + const ClearTextureParameters ¶ms); + // EXT_clear_texture angle::Result clearTexture(ContextVk *contextVk, vk::ImageHelper *dst, - ClearTextureParameters ¶ms); + const ClearTextureParameters ¶ms); angle::Result clearFramebuffer(ContextVk *contextVk, FramebufferVk *framebuffer, @@ -278,18 +287,26 @@ class UtilsVk : angle::NonCopyable // Resolve images if multisampled. Blit otherwise. angle::Result colorBlitResolve(ContextVk *contextVk, FramebufferVk *framebuffer, - vk::ImageHelper *src, + vk::ImageHelper *srcImage, const vk::ImageView *srcView, const BlitResolveParameters ¶ms); + angle::Result depthStencilBlitResolve(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, + vk::RenderPassCommandBufferHelper *renderPassCommands, + vk::ImageHelper *dstImage, + const vk::ImageView &dstImageView, + gl::LevelIndex dstImageLevel, + uint32_t dstImageLayer, + vk::ImageHelper *srcImage, const vk::ImageView *srcDepthView, const vk::ImageView *srcStencilView, const BlitResolveParameters ¶ms); + angle::Result stencilBlitResolveNoShaderExport(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, + vk::ImageHelper *dstImage, + gl::LevelIndex dstLevelIndex, + uint32_t dstLayerIndex, + vk::ImageHelper *srcImage, const vk::ImageView *srcStencilView, const BlitResolveParameters ¶ms); @@ -297,6 +314,11 @@ class UtilsVk : angle::NonCopyable vk::ImageHelper *dst, const ClearImageParameters ¶ms); + angle::Result copyImageFromTileMemory(ContextVk *contextVk, + const VkImageAspectFlags aspectFlags, + vk::ImageHelper *dstImage, + vk::ImageHelper *srcImage); + angle::Result copyImage(ContextVk *contextVk, vk::ImageHelper *dst, const vk::ImageView *dstView, @@ -473,6 +495,7 @@ class UtilsVk : angle::NonCopyable BlitResolveOffset offset = {}; float stretch[2] = {}; float invSrcExtent[2] = {}; + int32_t srcMip = 0; int32_t srcLayer = 0; int32_t samples = 0; float invSamples = 0; @@ -490,11 +513,12 @@ class UtilsVk : angle::NonCopyable float invSrcExtent[2] = {}; int32_t srcLayer = 0; int32_t srcWidth = 0; - int32_t blitArea[4] = {}; - int32_t dstPitch = 0; + int32_t srcHeight = 0; uint32_t flipX = 0; uint32_t flipY = 0; uint32_t rotateXY = 0; + int32_t blitArea[4] = {}; + int32_t dstPitch = 0; }; struct ExportStencilShaderParams @@ -656,7 +680,6 @@ class UtilsVk : angle::NonCopyable angle::Result ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk *contextVk); angle::Result startRenderPass(ContextVk *contextVk, - vk::ImageHelper *image, const vk::ImageView *imageView, const vk::RenderPassDesc &renderPassDesc, const gl::Rectangle &renderArea, @@ -675,15 +698,6 @@ class UtilsVk : angle::NonCopyable const ConvertVertexShaderParams &shaderParams, const OffsetAndVertexCounts &additionalOffsetVertexCounts); - // Blits or resolves either color or depth/stencil, based on which view is given. - angle::Result blitResolveImpl(ContextVk *contextVk, - FramebufferVk *framebuffer, - vk::ImageHelper *src, - const vk::ImageView *srcColorView, - const vk::ImageView *srcDepthView, - const vk::ImageView *srcStencilView, - const BlitResolveParameters ¶ms); - // Allocates a single descriptor set. angle::Result allocateDescriptorSetWithLayout( ContextVk *contextVk, @@ -703,6 +717,20 @@ class UtilsVk : angle::NonCopyable const vk::SamplerDesc &samplerDesc, VkDescriptorSet *descriptorSetOut); + angle::Result setupBlitResolveGraphicsProgram(ContextVk *contextVk, + const vk::ImageHelper &srcImage, + const vk::ImageView *srcColorView, + const vk::ImageView *srcDepthView, + const vk::ImageView *srcStencilView, + const vk::GraphicsPipelineDesc &pipelineDesc, + uint32_t flags, + uint32_t outputMask, + const BlitResolveParameters ¶ms, + vk::RenderPassCommandBuffer *commandBuffer, + bool blitColor, + bool blitDepth, + bool blitStencil); + angle::PackedEnumMap mDescriptorSetLayouts; angle::PackedEnumMap mPipelineLayouts; angle::PackedEnumMap mDescriptorPools; diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp index 9e999dbf18b..1a5abec308f 100644 --- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp +++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp @@ -7,6 +7,10 @@ // Implements the class methods for VertexArrayVk. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/VertexArrayVk.h" #include "common/debug.h" @@ -26,6 +30,10 @@ namespace constexpr int kStreamIndexBufferCachedIndexCount = 6; constexpr int kMaxCachedStreamIndexBuffers = 4; constexpr size_t kDefaultValueSize = sizeof(gl::VertexAttribCurrentValueData::Values); +constexpr gl::VertexArray::DirtyAttribBits kDirtyFormatAttribBits = + gl::VertexArray::DirtyAttribBits({gl::VertexArray::DIRTY_ATTRIB_ENABLED, + gl::VertexArray::DIRTY_ATTRIB_POINTER, + gl::VertexArray::DIRTY_ATTRIB_FORMAT}); ANGLE_INLINE bool BindingIsAligned(const angle::Format &angleFormat, VkDeviceSize offset, @@ -63,17 +71,14 @@ bool ShouldCombineAttributes(vk::Renderer *renderer, return false; } const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); - return !vertexFormat.getVertexLoadRequiresConversion(false) && binding.getDivisor() == 0 && + return !vertexFormat.getVertexLoadRequiresConversion() && binding.getDivisor() == 0 && ClientBindingAligned(attrib, binding.getStride(), - vertexFormat.getVertexInputAlignment(false)); + vertexFormat.getVertexInputAlignment()); } -void WarnOnVertexFormatConversion(ContextVk *contextVk, - const vk::Format &vertexFormat, - bool compressed, - bool insertEventMarker) +void WarnOnVertexFormatConversion(ContextVk *contextVk, const vk::Format &vertexFormat) { - if (!vertexFormat.getVertexLoadRequiresConversion(compressed)) + if (!vertexFormat.getVertexLoadRequiresConversion()) { return; } @@ -82,7 +87,7 @@ void WarnOnVertexFormatConversion(ContextVk *contextVk, contextVk, GL_DEBUG_SEVERITY_LOW, "The Vulkan driver does not support vertex attribute format 0x%04X, emulating with 0x%04X", vertexFormat.getIntendedFormat().glInternalFormat, - vertexFormat.getActualBufferFormat(compressed).glInternalFormat); + vertexFormat.getActualBufferFormat().glInternalFormat); } angle::Result StreamVertexData(ContextVk *contextVk, @@ -204,8 +209,8 @@ angle::Result CalculateMaxVertexCountForConversion(ContextVk *contextVk, // Initialize numVertices to 0 *maxNumVerticesOut = 0; - unsigned srcFormatSize = srcFormat.pixelBytes; - unsigned dstFormatSize = dstFormat.pixelBytes; + uint32_t srcFormatSize = srcFormat.pixelBytes; + uint32_t dstFormatSize = dstFormat.pixelBytes; uint32_t srcStride = conversion->getCacheKey().stride; uint32_t dstStride = dstFormatSize; @@ -213,10 +218,11 @@ angle::Result CalculateMaxVertexCountForConversion(ContextVk *contextVk, ASSERT(srcStride != 0); ASSERT(conversion->dirty()); - // Start the range with the range from the the beginning of the buffer to the end of - // buffer. Then scissor it with the dirtyRange. + // Start the range from the beginning of the buffer to the end of the buffer. Then scissor it + // with the dirtyRange. + VkDeviceSize srcBufferSize = srcBuffer->getSize(); size_t srcOffset = conversion->getCacheKey().offset; - GLint64 srcLength = srcBuffer->getSize() - srcOffset; + GLint64 srcLength = static_cast(srcBufferSize) - srcOffset; // The max number of vertices from binding to the end of the buffer size_t maxNumVertices = GetVertexCountForRange(srcLength, srcFormatSize, srcStride); @@ -225,6 +231,16 @@ angle::Result CalculateMaxVertexCountForConversion(ContextVk *contextVk, return angle::Result::Continue; } + // The intended data size does not include the entire stride from the last vertex, but only the + // format size. The data size must be within the source buffer's limit. + VkDeviceSize intendedSrcDataSize = + static_cast((maxNumVertices - 1) * srcStride) + srcFormatSize; + if (intendedSrcDataSize > srcBufferSize) + { + maxNumVertices = static_cast(srcBufferSize / srcStride); + ASSERT(maxNumVertices != 0); + } + // Allocate buffer for results vk::MemoryHostVisibility hostVisible = conversion->getCacheKey().hostVisible ? vk::MemoryHostVisibility::Visible @@ -233,7 +249,7 @@ angle::Result CalculateMaxVertexCountForConversion(ContextVk *contextVk, hostVisible)); // Calculate numVertices to convert - *maxNumVerticesOut = GetVertexCountForRange(srcLength, srcFormatSize, srcStride); + *maxNumVerticesOut = maxNumVertices; return angle::Result::Continue; } @@ -300,14 +316,17 @@ void CalculateOffsetAndVertexCountForDirtyRange(BufferVk *bufferVk, } } // anonymous namespace -VertexArrayVk::VertexArrayVk(ContextVk *contextVk, const gl::VertexArrayState &state) - : VertexArrayImpl(state), +VertexArrayVk::VertexArrayVk(ContextVk *contextVk, + const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers) + : VertexArrayImpl(state, vertexArrayBuffers), mCurrentArrayBufferHandles{}, mCurrentArrayBufferOffsets{}, - mCurrentArrayBufferRelativeOffsets{}, + mCurrentArrayBufferSizes{}, mCurrentArrayBuffers{}, - mCurrentArrayBufferStrides{}, - mCurrentArrayBufferDivisors{}, + mDefaultAttribFormatIDs{}, + mVertexInputBindingDescs{}, + mVertexInputAttribDescs{}, mCurrentElementArrayBuffer(nullptr), mLineLoopHelper(contextVk->getRenderer()), mDirtyLineLoopTranslation(true) @@ -316,22 +335,35 @@ VertexArrayVk::VertexArrayVk(ContextVk *contextVk, const gl::VertexArrayState &s mCurrentArrayBufferHandles.fill(emptyBuffer.getBuffer().getHandle()); mCurrentArrayBufferOffsets.fill(0); - mCurrentArrayBufferRelativeOffsets.fill(0); + mCurrentArrayBufferSizes.fill(0); mCurrentArrayBuffers.fill(&emptyBuffer); - mCurrentArrayBufferStrides.fill(0); - mCurrentArrayBufferDivisors.fill(0); - mBindingDirtyBitsRequiresPipelineUpdate.set(gl::VertexArray::DIRTY_BINDING_DIVISOR); - if (!contextVk->getFeatures().useVertexInputBindingStrideDynamicState.enabled) + // Divisor value is ignored by the implementation when using VK_VERTEX_INPUT_RATE_VERTEX, but it + // is set to 1 to avoid a validation error due to a validation layer issue. + mZeroDivisor = + contextVk->getRenderer()->isVertexAttributeInstanceRateZeroDivisorAllowed() ? 0 : 1; + + for (uint32_t attribIndex = 0; attribIndex < mVertexInputBindingDescs.size(); attribIndex++) { - mBindingDirtyBitsRequiresPipelineUpdate.set(gl::VertexArray::DIRTY_BINDING_STRIDE); + mVertexInputBindingDescs[attribIndex] = VkVertexInputBindingDescription2EXT{ + VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, + nullptr, + attribIndex, + 0, + static_cast(VK_VERTEX_INPUT_RATE_VERTEX), + mZeroDivisor}; } - // All but DIRTY_ATTRIB_POINTER_BUFFER requires graphics pipeline update - mAttribDirtyBitsRequiresPipelineUpdate.set(gl::VertexArray::DIRTY_ATTRIB_ENABLED); - mAttribDirtyBitsRequiresPipelineUpdate.set(gl::VertexArray::DIRTY_ATTRIB_POINTER); - mAttribDirtyBitsRequiresPipelineUpdate.set(gl::VertexArray::DIRTY_ATTRIB_FORMAT); - mAttribDirtyBitsRequiresPipelineUpdate.set(gl::VertexArray::DIRTY_ATTRIB_BINDING); + for (uint32_t attribIndex = 0; attribIndex < mVertexInputAttribDescs.size(); attribIndex++) + { + mVertexInputAttribDescs[attribIndex] = VkVertexInputAttributeDescription2EXT{ + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, + nullptr, + attribIndex, + attribIndex, + VK_FORMAT_R8G8B8A8_UNORM, + 0}; + } } VertexArrayVk::~VertexArrayVk() {} @@ -386,8 +418,7 @@ angle::Result VertexArrayVk::convertIndexBufferIndirectGPU(ContextVk *contextVk, vk::BufferHelper **indirectBufferVkOut) { size_t srcDataSize = static_cast(mCurrentElementArrayBuffer->getSize()); - ASSERT(mCurrentElementArrayBuffer == - &vk::GetImpl(getState().getElementArrayBuffer())->getBuffer()); + ASSERT(mCurrentElementArrayBuffer == &vk::GetImpl(getElementArrayBuffer())->getBuffer()); vk::BufferHelper *srcIndexBuf = mCurrentElementArrayBuffer; @@ -446,8 +477,7 @@ angle::Result VertexArrayVk::handleLineLoopIndirectDraw(const gl::Context *conte { size_t maxVertexCount = 0; ContextVk *contextVk = vk::GetImpl(context); - const gl::AttributesMask activeAttribs = - context->getStateCache().getActiveBufferedAttribsMask(); + const gl::AttributesMask activeAttribs = context->getActiveBufferedAttribsMask(); const auto &attribs = mState.getVertexAttributes(); const auto &bindings = mState.getVertexBindings(); @@ -478,7 +508,7 @@ angle::Result VertexArrayVk::convertIndexBufferCPU(ContextVk *contextVk, const void *sourcePointer, BufferBindingDirty *bindingDirty) { - ASSERT(!mState.getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte); + ASSERT(!getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte); vk::Renderer *renderer = contextVk->getRenderer(); size_t elementSize = contextVk->getVkIndexTypeSize(indexType); const size_t amount = elementSize * indexCount; @@ -673,7 +703,7 @@ angle::Result VertexArrayVk::convertVertexBufferCPU(ContextVk *contextVk, } uint8_t *src = nullptr; - ANGLE_TRY(srcBuffer->mapImpl(contextVk, GL_MAP_READ_BIT, reinterpret_cast(&src))); + ANGLE_TRY(srcBuffer->mapForReadAccessOnly(contextVk, reinterpret_cast(&src))); uint32_t srcStride = conversion->getCacheKey().stride; if (conversion->isEntireBufferDirty()) @@ -717,20 +747,64 @@ angle::Result VertexArrayVk::convertVertexBufferCPU(ContextVk *contextVk, } conversion->clearDirty(); - ANGLE_TRY(srcBuffer->unmapImpl(contextVk)); + ANGLE_TRY(srcBuffer->unmapReadAccessOnly(contextVk)); return angle::Result::Continue; } void VertexArrayVk::updateCurrentElementArrayBuffer() { - ASSERT(mState.getElementArrayBuffer() != nullptr); - ASSERT(mState.getElementArrayBuffer()->getSize() > 0); + ASSERT(getElementArrayBuffer() != nullptr); + ASSERT(getElementArrayBuffer()->getSize() > 0); - BufferVk *bufferVk = vk::GetImpl(mState.getElementArrayBuffer()); + BufferVk *bufferVk = vk::GetImpl(getElementArrayBuffer()); mCurrentElementArrayBuffer = &bufferVk->getBuffer(); } +gl::VertexArray::DirtyBits VertexArrayVk::checkBufferForDirtyBits( + const gl::Context *context, + const gl::VertexArrayBufferBindingMask bufferBindingMask) +{ + gl::VertexArray::DirtyBits dirtyBits; + + const std::vector &attribs = mState.getVertexAttributes(); + const std::vector &bindings = mState.getVertexBindings(); + + // Element buffer is not in bindings yet, has to handle separately. + dirtyBits.set(gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER); + + gl::VertexArrayBufferBindingMask bindingMask = bufferBindingMask; + bindingMask.reset(gl::kElementArrayBufferIndex); + + for (size_t bindingIndex : bindingMask) + { + const gl::Buffer *bufferGL = getVertexArrayBuffer(bindingIndex); + vk::BufferSerial bufferSerial = vk::GetImpl(bufferGL)->getBufferSerial(); + gl::AttributesMask enabledAttributeMask = + bindings[bindingIndex].getBoundAttributesMask() & mState.getEnabledAttributesMask(); + for (size_t attribIndex : enabledAttributeMask) + { + ASSERT(attribs[attribIndex].enabled); + if (!bufferSerial.valid() || bufferSerial != mCurrentArrayBufferSerial[attribIndex]) + { + dirtyBits.set(gl::VertexArray::DIRTY_BIT_BINDING_0 + bindingIndex); + break; + } + } + } + + // buffer content may have changed when it became non-current. In that case we always assume + // buffer data has changed. + if (mContentsObserverBindingsMask.any()) + { + uint64_t bits = mContentsObserverBindingsMask.bits(); + bits <<= gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0; + dirtyBits |= gl::VertexArray::DirtyBits(bits); + } + + return dirtyBits; +} + angle::Result VertexArrayVk::syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, gl::VertexArray::DirtyAttribBitsArray *attribBits, @@ -739,399 +813,425 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ASSERT(dirtyBits.any()); ContextVk *contextVk = vk::GetImpl(context); + vk::Renderer *renderer = contextVk->getRenderer(); contextVk->getPerfCounters().vertexArraySyncStateCalls++; const std::vector &attribs = mState.getVertexAttributes(); const std::vector &bindings = mState.getVertexBindings(); - for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter) + // Split out dirtyBits into bindingBits and attributeBits + gl::BufferBindingMask bufferBindingDirtyBits( + static_cast(dirtyBits.bits() >> gl::VertexArray::DIRTY_BIT_BINDING_0)); + gl::BufferBindingMask bufferDataDirtyBits( + static_cast(dirtyBits.bits() >> gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0)); + gl::AttributesMask attribDirtyBits( + static_cast(dirtyBits.bits() >> gl::VertexArray::DIRTY_BIT_ATTRIB_0)); + + // Fold DIRTY_BIT_BINDING_n into DIRTY_BIT_ATTRIB_n + if (bufferBindingDirtyBits.any()) { - size_t dirtyBit = *iter; - switch (dirtyBit) + for (size_t bindingIndex : bufferBindingDirtyBits) { - case gl::VertexArray::DIRTY_BIT_LOST_OBSERVATION: - { - // If vertex array was not observing while unbound, we need to check buffer's - // internal storage and take action if buffer storage has changed while not - // observing. - if (contextVk->getFeatures().compressVertexData.enabled || - mContentsObservers->any()) - { - // We may have lost buffer content change when it became non-current. In that - // case we always assume buffer has changed. If compressVertexData.enabled is - // true, it also depends on buffer usage which may have changed. - iter.setLaterBits( - gl::VertexArray::DirtyBits(mState.getBufferBindingMask().to_ulong() - << gl::VertexArray::DIRTY_BIT_BINDING_0)); - } - else - { - for (size_t bindingIndex : mState.getBufferBindingMask()) - { - const gl::Buffer *bufferGL = bindings[bindingIndex].getBuffer().get(); - vk::BufferSerial bufferSerial = vk::GetImpl(bufferGL)->getBufferSerial(); - for (size_t attribIndex : bindings[bindingIndex].getBoundAttributesMask()) - { - if (attribs[attribIndex].enabled && - (!bufferSerial.valid() || - bufferSerial != mCurrentArrayBufferSerial[attribIndex])) - { - iter.setLaterBit(gl::VertexArray::DIRTY_BIT_BINDING_0 + - bindingIndex); - break; - } - } - } - } - break; - } + attribDirtyBits |= bindings[bindingIndex].getBoundAttributesMask(); + mDivisorExceedMaxSupportedValueBindingMask.set( + bindingIndex, + bindings[bindingIndex].getDivisor() > renderer->getMaxVertexAttribDivisor()); + } + } - case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER: - case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA: - { - gl::Buffer *bufferGL = mState.getElementArrayBuffer(); - if (bufferGL && bufferGL->getSize() > 0) - { - // Note that just updating buffer data may still result in a new - // vk::BufferHelper allocation. - updateCurrentElementArrayBuffer(); - } - else - { - mCurrentElementArrayBuffer = nullptr; - } + bool elementBufferDirty = dirtyBits[gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER] || + dirtyBits[gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA]; + if (elementBufferDirty) + { + gl::Buffer *bufferGL = getElementArrayBuffer(); + if (bufferGL && bufferGL->getSize() > 0) + { + // Note that just updating buffer data may still result in a new + // vk::BufferHelper allocation. + updateCurrentElementArrayBuffer(); + } + else + { + mCurrentElementArrayBuffer = nullptr; + } - mLineLoopBufferFirstIndex.reset(); - mLineLoopBufferLastIndex.reset(); - ANGLE_TRY(contextVk->onIndexBufferChange(mCurrentElementArrayBuffer)); - mDirtyLineLoopTranslation = true; - break; - } + mLineLoopBufferFirstIndex.reset(); + mLineLoopBufferLastIndex.reset(); + ANGLE_TRY(contextVk->onIndexBufferChange(mCurrentElementArrayBuffer)); + mDirtyLineLoopTranslation = true; + } + + // Update mStreamingVertexAttribsMask + mStreamingVertexAttribsMask = mState.getClientMemoryAttribsMask(); + if (ANGLE_UNLIKELY(mDivisorExceedMaxSupportedValueBindingMask.any())) + { + for (size_t bindingIndex : mDivisorExceedMaxSupportedValueBindingMask) + { + mStreamingVertexAttribsMask |= bindings[bindingIndex].getBoundAttributesMask(); + } + } + mStreamingVertexAttribsMask &= mState.getEnabledAttributesMask(); + + // All enabled attributes that are dirty + gl::AttributesMask enabledAttribDirtyBits = attribDirtyBits & mState.getEnabledAttributesMask(); -#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \ - case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \ - { \ - gl::VertexArray::DirtyAttribBits dirtyAttribBitsRequiresPipelineUpdate = \ - (*attribBits)[INDEX] & mAttribDirtyBitsRequiresPipelineUpdate; \ - const bool bufferOnly = dirtyAttribBitsRequiresPipelineUpdate.none(); \ - ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \ - bindings[attribs[INDEX].bindingIndex], INDEX, bufferOnly)); \ - (*attribBits)[INDEX].reset(); \ - break; \ + // We are going to re-evaluate mNeedsConversionAttribsMask inside syncDirtyEnabledAttrib + mNeedsConversionAttribsMask &= ~enabledAttribDirtyBits; + + // Sync all enabled non-streaming attributes that are dirty + const gl::AttributesMask enabledNonStreamAttribDirtyBits = + enabledAttribDirtyBits & ~mStreamingVertexAttribsMask; + for (size_t attribIndex : enabledNonStreamAttribDirtyBits) + { + // This will also update mNeedsConversionAttribMask + ANGLE_TRY(syncDirtyEnabledNonStreamingAttrib(contextVk, attribs[attribIndex], + bindings[attribs[attribIndex].bindingIndex], + attribIndex, (*attribBits)[attribIndex])); } - ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC) - -// Since BINDING already implies DATA and ATTRIB change, we remove these here to avoid redundant -// processing. -#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \ - case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \ - { \ - gl::VertexArray::DirtyBindingBits dirtyBindingBitsRequirePipelineUpdate = \ - (*bindingBits)[INDEX] & mBindingDirtyBitsRequiresPipelineUpdate; \ - \ - for (size_t attribIndex : bindings[INDEX].getBoundAttributesMask()) \ - { \ - gl::VertexArray::DirtyAttribBits dirtyAttribBitsRequiresPipelineUpdate = \ - (*attribBits)[attribIndex] & mAttribDirtyBitsRequiresPipelineUpdate; \ - const bool bufferOnly = dirtyBindingBitsRequirePipelineUpdate.none() && \ - dirtyAttribBitsRequiresPipelineUpdate.none(); \ - ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[attribIndex], bindings[INDEX], \ - attribIndex, bufferOnly)); \ - iter.resetLaterBit(gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + attribIndex); \ - iter.resetLaterBit(gl::VertexArray::DIRTY_BIT_ATTRIB_0 + attribIndex); \ - (*attribBits)[attribIndex].reset(); \ - } \ - (*bindingBits)[INDEX].reset(); \ - break; \ + // Sync all enabled and streaming attributes that are dirty + const gl::AttributesMask enabledStreamAttribDirtyBits = + enabledAttribDirtyBits & mStreamingVertexAttribsMask; + for (size_t attribIndex : enabledStreamAttribDirtyBits) + { + // This will also update mNeedsConversionAttribMask + ANGLE_TRY(syncDirtyEnabledStreamingAttrib(contextVk, attribs[attribIndex], + bindings[attribs[attribIndex].bindingIndex], + attribIndex, (*attribBits)[attribIndex])); } - ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC) + // Sync all enabled attributes that needs data conversion. + if (ANGLE_UNLIKELY(mNeedsConversionAttribsMask.any())) + { + // Update mContentsObserverBindingsMask + mContentsObserverBindingsMask.reset(); + mContentsObserverBindingsMask.set(gl::kElementArrayBufferIndex); + for (size_t attribIndex : mNeedsConversionAttribsMask) + { + mContentsObserverBindingsMask.set(attribs[attribIndex].bindingIndex); + } -#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \ - case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \ - ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \ - bindings[attribs[INDEX].bindingIndex], INDEX, false)); \ - iter.resetLaterBit(gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX); \ - (*attribBits)[INDEX].reset(); \ - break; + // As long as attribute has changed or data has changed, we need to reprocess it. + gl::AttributesMask needsConversionAttribDirtyBits = attribDirtyBits; + for (size_t bindingIndex : bufferDataDirtyBits) + { + needsConversionAttribDirtyBits |= bindings[bindingIndex].getBoundAttributesMask(); + } - ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC) + needsConversionAttribDirtyBits &= mNeedsConversionAttribsMask; + needsConversionAttribDirtyBits &= mState.getEnabledAttributesMask(); - default: - UNREACHABLE(); - break; + for (size_t attribIndex : needsConversionAttribDirtyBits) + { + ANGLE_TRY(syncNeedsConversionAttrib(contextVk, attribs[attribIndex], + bindings[attribs[attribIndex].bindingIndex], + attribIndex)); } } - return angle::Result::Continue; -} // namespace rx + // Sync all disabled attributes that are dirty. We only need to handle attributes that was + // changed from enabled to disabled. + const gl::AttributesMask previouslyEnabledAttribDirtyBits = + mCurrentEnabledAttribsMask & ~mState.getEnabledAttributesMask(); + const gl::AttributesMask disabledAttribDirtyBits = + previouslyEnabledAttribDirtyBits & attribDirtyBits; + for (size_t attribIndex : disabledAttribDirtyBits) + { + ANGLE_TRY(syncDirtyDisabledAttrib(contextVk, attribs[attribIndex], attribIndex)); + } -#undef ANGLE_VERTEX_DIRTY_ATTRIB_FUNC -#undef ANGLE_VERTEX_DIRTY_BINDING_FUNC -#undef ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC + if (ANGLE_UNLIKELY(mDivisorExceedMaxSupportedValueBindingMask.any())) + { + gl::AttributesMask divisorExceedMaxSupportedValueAttribMask; + for (size_t bindingIndex : mDivisorExceedMaxSupportedValueBindingMask) + { + divisorExceedMaxSupportedValueAttribMask |= + bindings[bindingIndex].getBoundAttributesMask(); + } + // Set divisor to 1 for attribs with emulated divisor, since we always go down the stream + // code path + divisorExceedMaxSupportedValueAttribMask &= mCurrentEnabledAttribsMask; + for (size_t attribIndex : divisorExceedMaxSupportedValueAttribMask) + { + ASSERT(mStreamingVertexAttribsMask.test(attribIndex)); + mVertexInputBindingDescs[attribIndex].divisor = 1; + } + } -ANGLE_INLINE angle::Result VertexArrayVk::setDefaultPackedInput(ContextVk *contextVk, - size_t attribIndex, - angle::FormatID *formatOut) + ANGLE_TRY(contextVk->onVertexArrayChange(enabledAttribDirtyBits)); + + attribBits->fill(gl::VertexArray::DirtyAttribBits()); + bindingBits->fill(gl::VertexArray::DirtyBindingBits()); + + return angle::Result::Continue; +} + +ANGLE_INLINE void VertexArrayVk::setDefaultPackedInput(ContextVk *contextVk, + size_t attribIndex, + angle::FormatID *formatOut) { const gl::State &glState = contextVk->getState(); const gl::VertexAttribCurrentValueData &defaultValue = glState.getVertexAttribCurrentValues()[attribIndex]; *formatOut = GetCurrentValueFormatID(defaultValue.Type); - - return contextVk->onVertexAttributeChange(attribIndex, 0, 0, *formatOut, false, 0, nullptr); } -angle::Result VertexArrayVk::updateActiveAttribInfo(ContextVk *contextVk) +ANGLE_INLINE angle::Result VertexArrayVk::syncDirtyEnabledNonStreamingAttrib( + ContextVk *contextVk, + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + size_t attribIndex, + const gl::VertexArray::DirtyAttribBits &dirtyAttribBits) { - const std::vector &attribs = mState.getVertexAttributes(); - const std::vector &bindings = mState.getVertexBindings(); + vk::Renderer *renderer = contextVk->getRenderer(); + ASSERT(attrib.enabled); + ASSERT(!mStreamingVertexAttribsMask.test(attribIndex)); + ASSERT(!mNeedsConversionAttribsMask[attribIndex]); + + const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); + + // Init attribute offset to the front-end value + mVertexInputAttribDescs[attribIndex].offset = attrib.relativeOffset; + gl::Buffer *bufferGL = getVertexArrayBuffer(attrib.bindingIndex); + const angle::Format &srcFormat = vertexFormat.getIntendedFormat(); + unsigned srcFormatSize = srcFormat.pixelBytes; + bool hasAtLeastOneVertex = (bufferGL->getSize() - binding.getOffset()) >= srcFormatSize; + // If buffer size is 0, hasAtLeastOneVertex must be false + ASSERT(bufferGL->getSize() > 0 || !hasAtLeastOneVertex); - // Update pipeline cache with current active attribute info - for (size_t attribIndex : mState.getEnabledAttributesMask()) + if (ANGLE_LIKELY(hasAtLeastOneVertex)) { - const gl::VertexAttribute &attrib = attribs[attribIndex]; - const gl::VertexBinding &binding = bindings[attribs[attribIndex].bindingIndex]; - const angle::FormatID format = attrib.format->id; + BufferVk *bufferVk = vk::GetImpl(bufferGL); + uint32_t srcStride = binding.getStride() == 0 ? srcFormatSize : binding.getStride(); + bool bindingIsAligned = + BindingIsAligned(srcFormat, binding.getOffset() + attrib.relativeOffset, srcStride); + bool needsConversion = + (vertexFormat.getVertexLoadRequiresConversion() || !bindingIsAligned); + + if (ANGLE_UNLIKELY(needsConversion)) + { + // Early out if needs conversion. We will handle these attributes last. + mNeedsConversionAttribsMask.set(attribIndex); + return angle::Result::Continue; + } + + vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); + mCurrentArrayBuffers[attribIndex] = &bufferHelper; + mCurrentArrayBufferSerial[attribIndex] = bufferHelper.getBufferSerial(); + VkDeviceSize bufferSize = renderer->padVertexAttribBufferSizeIfNeeded(bufferVk->getSize()); - ANGLE_TRY(contextVk->onVertexAttributeChange( - attribIndex, mCurrentArrayBufferStrides[attribIndex], binding.getDivisor(), format, - mCurrentArrayBufferCompressed.test(attribIndex), - mCurrentArrayBufferRelativeOffsets[attribIndex], mCurrentArrayBuffers[attribIndex])); + VkDeviceSize bufferOffset; + if (contextVk->getFeatures().supportsBindVertexBuffers2.enabled) + { + mCurrentArrayBufferHandles[attribIndex] = bufferHelper.getBuffer().getHandle(); + bufferOffset = bufferHelper.getOffset(); + } + else + { + mCurrentArrayBufferHandles[attribIndex] = + bufferHelper.getBufferForVertexArray(contextVk, bufferSize, &bufferOffset) + .getHandle(); + } + + // Vulkan requires the offset is within the buffer. We use robust access + // behaviour to reset the offset if it starts outside the buffer. + ASSERT(binding.getOffset() < static_cast(bufferSize)); + mCurrentArrayBufferOffsets[attribIndex] = bufferOffset + binding.getOffset(); + mCurrentArrayBufferSizes[attribIndex] = bufferSize - binding.getOffset(); + mVertexInputBindingDescs[attribIndex].stride = binding.getStride(); + } + else + { + vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); + + mCurrentArrayBuffers[attribIndex] = &emptyBuffer; + mCurrentArrayBufferSerial[attribIndex] = emptyBuffer.getBufferSerial(); + mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); + mCurrentArrayBufferOffsets[attribIndex] = emptyBuffer.getOffset(); + mCurrentArrayBufferSizes[attribIndex] = emptyBuffer.getSize(); + mVertexInputBindingDescs[attribIndex].stride = 0; + } - mCurrentArrayBufferFormats[attribIndex] = format; + if ((dirtyAttribBits & kDirtyFormatAttribBits).any()) + { + setVertexInputAttribDescFormat(renderer, attribIndex, attrib.format->id); } + setVertexInputBindingDescDivisor(renderer, attribIndex, binding.getDivisor()); + mCurrentEnabledAttribsMask.set(attribIndex); return angle::Result::Continue; } -angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, - const gl::VertexAttribute &attrib, - const gl::VertexBinding &binding, - size_t attribIndex, - bool bufferOnly) +ANGLE_INLINE angle::Result VertexArrayVk::syncDirtyEnabledStreamingAttrib( + ContextVk *contextVk, + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + size_t attribIndex, + const gl::VertexArray::DirtyAttribBits &dirtyAttribBits) { vk::Renderer *renderer = contextVk->getRenderer(); - if (attrib.enabled) - { - const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); + ASSERT(attrib.enabled); + ASSERT(mStreamingVertexAttribsMask.test(attribIndex)); + ASSERT(!mNeedsConversionAttribsMask[attribIndex]); - // Init attribute offset to the front-end value - mCurrentArrayBufferRelativeOffsets[attribIndex] = attrib.relativeOffset; - gl::Buffer *bufferGL = binding.getBuffer().get(); - // Emulated and/or client-side attribs will be streamed - bool isStreamingVertexAttrib = - (binding.getDivisor() > renderer->getMaxVertexAttribDivisor()) || (bufferGL == nullptr); - // If we sre switching between streaming and buffer mode, set bufferOnly to false since we - // are actually changing the buffer. - if (bufferOnly && isStreamingVertexAttrib != mStreamingVertexAttribsMask.test(attribIndex)) - { - bufferOnly = false; - } - mStreamingVertexAttribsMask.set(attribIndex, isStreamingVertexAttrib); - bool compressed = false; - - if (bufferGL) - { - mContentsObservers->disableForBuffer(bufferGL, static_cast(attribIndex)); - } - - if (!isStreamingVertexAttrib && bufferGL->getSize() > 0) - { - BufferVk *bufferVk = vk::GetImpl(bufferGL); - const angle::Format &srcFormat = vertexFormat.getIntendedFormat(); - unsigned srcFormatSize = srcFormat.pixelBytes; - uint32_t srcStride = binding.getStride() == 0 ? srcFormatSize : binding.getStride(); - size_t numVertices = GetVertexCount(bufferVk, binding, srcFormatSize); - bool bindingIsAligned = - BindingIsAligned(srcFormat, binding.getOffset() + attrib.relativeOffset, srcStride); - - if (renderer->getFeatures().compressVertexData.enabled && - gl::IsStaticBufferUsage(bufferGL->getUsage()) && - vertexFormat.canCompressBufferData()) - { - compressed = true; - } + const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); - bool needsConversion = - numVertices > 0 && - (vertexFormat.getVertexLoadRequiresConversion(compressed) || !bindingIsAligned); + vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); + mCurrentArrayBuffers[attribIndex] = &emptyBuffer; + mCurrentArrayBufferSerial[attribIndex] = emptyBuffer.getBufferSerial(); + mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); + mCurrentArrayBufferOffsets[attribIndex] = emptyBuffer.getOffset(); + mCurrentArrayBufferSizes[attribIndex] = emptyBuffer.getSize(); - if (needsConversion) - { - const angle::Format &dstFormat = vertexFormat.getActualBufferFormat(compressed); - // Converted buffer is tightly packed - uint32_t dstStride = dstFormat.pixelBytes; - - ASSERT(vertexFormat.getVertexInputAlignment(compressed) <= - vk::kVertexBufferAlignment); - - mContentsObservers->enableForBuffer(bufferGL, static_cast(attribIndex)); - - WarnOnVertexFormatConversion(contextVk, vertexFormat, compressed, true); - - const VertexConversionBuffer::CacheKey cacheKey{ - srcFormat.id, srcStride, - static_cast(binding.getOffset()) + attrib.relativeOffset, - !bindingIsAligned, false}; - - VertexConversionBuffer *conversion = - bufferVk->getVertexConversionBuffer(renderer, cacheKey); - - // Converted attribs are packed in their own VK buffer so offset is relative to the - // binding and coversion's offset. The conversion buffer try to reuse the existing - // buffer as much as possible to reduce the amount of data that has to be converted. - // When binding's offset changes, it will check if new offset and existing buffer's - // offset are multiple of strides apart. It yes it will reuse. If new offset is - // larger, all existing data are still valid. If the new offset is smaller it will - // mark the newly exposed range dirty and then rely on - // ContextVk::initBufferForVertexConversion to decide buffer's size is big enough or - // not and reallocate (and mark entire buffer dirty) if needed. - // - // bufferVk:----------------------------------------------------------------------- - // | | - // | bingding.offset + attrib.relativeOffset. - // conversion->getCacheKey().offset - // - // conversion.buffer: -------------------------------------------------------------- - // | - // dstRelativeOffset - size_t srcRelativeOffset = - binding.getOffset() + attrib.relativeOffset - conversion->getCacheKey().offset; - size_t numberOfVerticesToSkip = srcRelativeOffset / srcStride; - size_t dstRelativeOffset = numberOfVerticesToSkip * dstStride; - - if (conversion->dirty()) - { - if (compressed) - { - INFO() << "Compressing vertex data in buffer " << bufferGL->id().value - << " from " << ToUnderlying(srcFormat.id) << " to " - << ToUnderlying(dstFormat.id) << "."; - } + bool combined = ShouldCombineAttributes(renderer, attrib, binding); + mVertexInputBindingDescs[attribIndex].stride = + combined ? binding.getStride() : vertexFormat.getActualBufferFormat().pixelBytes; + // Init attribute offset to the front-end value + mVertexInputAttribDescs[attribIndex].offset = attrib.relativeOffset; - if (bindingIsAligned) - { - ANGLE_TRY(convertVertexBufferGPU(contextVk, bufferVk, conversion, srcFormat, - dstFormat)); - } - else - { - ANGLE_VK_PERF_WARNING( - contextVk, GL_DEBUG_SEVERITY_HIGH, - "GPU stall due to vertex format conversion of unaligned data"); + if ((dirtyAttribBits & kDirtyFormatAttribBits).any()) + { + setVertexInputAttribDescFormat(renderer, attribIndex, attrib.format->id); + } + setVertexInputBindingDescDivisor(renderer, attribIndex, binding.getDivisor()); - ANGLE_TRY(convertVertexBufferCPU( - contextVk, bufferVk, conversion, srcFormat, dstFormat, - vertexFormat.getVertexLoadFunction(compressed))); - } + mCurrentEnabledAttribsMask.set(attribIndex); + return angle::Result::Continue; +} - // If conversion happens, the destination buffer stride may be changed, - // therefore an attribute change needs to be called. Note that it may trigger - // unnecessary vulkan PSO update when the destination buffer stride does not - // change, but for simplicity just make it conservative - bufferOnly = false; - } +ANGLE_INLINE angle::Result VertexArrayVk::syncDirtyDisabledAttrib(ContextVk *contextVk, + const gl::VertexAttribute &attrib, + size_t attribIndex) +{ + ASSERT(!attrib.enabled); + ASSERT(mCurrentEnabledAttribsMask.test(attribIndex)); + contextVk->invalidateDefaultAttribute(attribIndex); + + // These will be filled out by the ContextVk. + vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); + mCurrentArrayBuffers[attribIndex] = &emptyBuffer; + mCurrentArrayBufferSerial[attribIndex] = emptyBuffer.getBufferSerial(); + mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); + mCurrentArrayBufferOffsets[attribIndex] = emptyBuffer.getOffset(); + mCurrentArrayBufferSizes[attribIndex] = emptyBuffer.getSize(); + mVertexInputBindingDescs[attribIndex].stride = 0; + setVertexInputBindingDescDivisor(contextVk->getRenderer(), attribIndex, 0); + mVertexInputAttribDescs[attribIndex].offset = 0; + + mCurrentEnabledAttribsMask.reset(attribIndex); + return angle::Result::Continue; +} - vk::BufferHelper *bufferHelper = conversion->getBuffer(); - mCurrentArrayBuffers[attribIndex] = bufferHelper; - mCurrentArrayBufferSerial[attribIndex] = bufferHelper->getBufferSerial(); - VkDeviceSize bufferOffset; - mCurrentArrayBufferHandles[attribIndex] = - bufferHelper - ->getBufferForVertexArray(contextVk, bufferHelper->getSize(), &bufferOffset) - .getHandle(); - ASSERT(BindingIsAligned(dstFormat, bufferOffset + dstRelativeOffset, dstStride)); - mCurrentArrayBufferOffsets[attribIndex] = bufferOffset + dstRelativeOffset; - mCurrentArrayBufferRelativeOffsets[attribIndex] = 0; - mCurrentArrayBufferStrides[attribIndex] = dstStride; - } - else - { - if (numVertices == 0) - { - vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); +angle::Result VertexArrayVk::syncNeedsConversionAttrib(ContextVk *contextVk, + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + size_t attribIndex) +{ + vk::Renderer *renderer = contextVk->getRenderer(); + ASSERT(attrib.enabled); + ASSERT(mNeedsConversionAttribsMask.test(attribIndex)); + ASSERT(!mStreamingVertexAttribsMask.test(attribIndex)); + ASSERT(mVertexInputAttribDescs[attribIndex].offset == attrib.relativeOffset); + ASSERT(mContentsObserverBindingsMask.test(attrib.bindingIndex)); - mCurrentArrayBuffers[attribIndex] = &emptyBuffer; - mCurrentArrayBufferSerial[attribIndex] = emptyBuffer.getBufferSerial(); - mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); - mCurrentArrayBufferOffsets[attribIndex] = emptyBuffer.getOffset(); - mCurrentArrayBufferStrides[attribIndex] = 0; - } - else - { - vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); - mCurrentArrayBuffers[attribIndex] = &bufferHelper; - mCurrentArrayBufferSerial[attribIndex] = bufferHelper.getBufferSerial(); - VkDeviceSize bufferOffset; - mCurrentArrayBufferHandles[attribIndex] = - bufferHelper - .getBufferForVertexArray(contextVk, bufferVk->getSize(), &bufferOffset) - .getHandle(); - - // Vulkan requires the offset is within the buffer. We use robust access - // behaviour to reset the offset if it starts outside the buffer. - mCurrentArrayBufferOffsets[attribIndex] = - binding.getOffset() < static_cast(bufferVk->getSize()) - ? binding.getOffset() + bufferOffset - : bufferOffset; - - mCurrentArrayBufferStrides[attribIndex] = binding.getStride(); - } - } - } - else - { - vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); - mCurrentArrayBuffers[attribIndex] = &emptyBuffer; - mCurrentArrayBufferSerial[attribIndex] = emptyBuffer.getBufferSerial(); - mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); - mCurrentArrayBufferOffsets[attribIndex] = emptyBuffer.getOffset(); - - bool combined = ShouldCombineAttributes(renderer, attrib, binding); - mCurrentArrayBufferStrides[attribIndex] = - combined ? binding.getStride() - : vertexFormat.getActualBufferFormat(compressed).pixelBytes; - } + const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); - if (bufferOnly) + gl::Buffer *bufferGL = getVertexArrayBuffer(attrib.bindingIndex); + ASSERT(bufferGL); + ASSERT(bufferGL->getSize() > 0); + BufferVk *bufferVk = vk::GetImpl(bufferGL); + + const angle::Format &srcFormat = vertexFormat.getIntendedFormat(); + unsigned srcFormatSize = srcFormat.pixelBytes; + uint32_t srcStride = binding.getStride() == 0 ? srcFormatSize : binding.getStride(); + bool bindingIsAligned = + BindingIsAligned(srcFormat, binding.getOffset() + attrib.relativeOffset, srcStride); + + const angle::Format &dstFormat = vertexFormat.getActualBufferFormat(); + // Converted buffer is tightly packed + uint32_t dstStride = dstFormat.pixelBytes; + + ASSERT(vertexFormat.getVertexInputAlignment() <= vk::kVertexBufferAlignment); + + WarnOnVertexFormatConversion(contextVk, vertexFormat); + + const VertexConversionBuffer::CacheKey cacheKey{ + srcFormat.id, srcStride, static_cast(binding.getOffset()) + attrib.relativeOffset, + !bindingIsAligned, false}; + + VertexConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey); + + // Converted attribs are packed in their own VK buffer so offset is relative to the + // binding and coversion's offset. The conversion buffer try to reuse the existing + // buffer as much as possible to reduce the amount of data that has to be converted. + // When binding's offset changes, it will check if new offset and existing buffer's + // offset are multiple of strides apart. It yes it will reuse. If new offset is + // larger, all existing data are still valid. If the new offset is smaller it will + // mark the newly exposed range dirty and then rely on + // ContextVk::initBufferForVertexConversion to decide buffer's size is big enough or + // not and reallocate (and mark entire buffer dirty) if needed. + // + // bufferVk:----------------------------------------------------------------------- + // | | + // | bingding.offset + attrib.relativeOffset. + // conversion->getCacheKey().offset + // + // conversion.buffer: -------------------------------------------------------------- + // | + // dstRelativeOffset + size_t srcRelativeOffset = + binding.getOffset() + attrib.relativeOffset - conversion->getCacheKey().offset; + size_t numberOfVerticesToSkip = srcRelativeOffset / srcStride; + size_t dstRelativeOffset = numberOfVerticesToSkip * dstStride; + + if (conversion->dirty()) + { + if (bindingIsAligned) { - ANGLE_TRY(contextVk->onVertexBufferChange(mCurrentArrayBuffers[attribIndex])); + ANGLE_TRY( + convertVertexBufferGPU(contextVk, bufferVk, conversion, srcFormat, dstFormat)); } else { - const angle::FormatID format = attrib.format->id; - ANGLE_TRY(contextVk->onVertexAttributeChange( - attribIndex, mCurrentArrayBufferStrides[attribIndex], binding.getDivisor(), format, - compressed, mCurrentArrayBufferRelativeOffsets[attribIndex], - mCurrentArrayBuffers[attribIndex])); - - mCurrentArrayBufferFormats[attribIndex] = format; - mCurrentArrayBufferCompressed[attribIndex] = compressed; - mCurrentArrayBufferDivisors[attribIndex] = binding.getDivisor(); + ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH, + "GPU stall due to vertex format conversion of unaligned data"); + + ANGLE_TRY(convertVertexBufferCPU(contextVk, bufferVk, conversion, srcFormat, dstFormat, + vertexFormat.getVertexLoadFunction())); } + + // If conversion happens, the destination buffer stride may be changed, + // therefore an attribute change needs to be called. Note that it may trigger + // unnecessary vulkan PSO update when the destination buffer stride does not + // change, but for simplicity just make it conservative + } + + vk::BufferHelper *bufferHelper = conversion->getBuffer(); + mCurrentArrayBuffers[attribIndex] = bufferHelper; + mCurrentArrayBufferSerial[attribIndex] = bufferHelper->getBufferSerial(); + VkDeviceSize bufferSize = bufferHelper->getSize(); + + VkDeviceSize bufferOffset; + if (contextVk->getFeatures().supportsBindVertexBuffers2.enabled) + { + mCurrentArrayBufferHandles[attribIndex] = bufferHelper->getBuffer().getHandle(); + bufferOffset = bufferHelper->getOffset(); } else { - contextVk->invalidateDefaultAttribute(attribIndex); - - // These will be filled out by the ContextVk. - vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); - mCurrentArrayBuffers[attribIndex] = &emptyBuffer; - mCurrentArrayBufferSerial[attribIndex] = emptyBuffer.getBufferSerial(); - mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); - mCurrentArrayBufferOffsets[attribIndex] = emptyBuffer.getOffset(); - mCurrentArrayBufferStrides[attribIndex] = 0; - mCurrentArrayBufferDivisors[attribIndex] = 0; - mCurrentArrayBufferCompressed[attribIndex] = false; - mCurrentArrayBufferRelativeOffsets[attribIndex] = 0; - - ANGLE_TRY(setDefaultPackedInput(contextVk, attribIndex, - &mCurrentArrayBufferFormats[attribIndex])); + mCurrentArrayBufferHandles[attribIndex] = + bufferHelper->getBufferForVertexArray(contextVk, bufferSize, &bufferOffset).getHandle(); } - + ASSERT(BindingIsAligned(dstFormat, bufferOffset + dstRelativeOffset, dstStride)); + mCurrentArrayBufferOffsets[attribIndex] = bufferOffset + dstRelativeOffset; + mCurrentArrayBufferSizes[attribIndex] = bufferSize - dstRelativeOffset; + mVertexInputAttribDescs[attribIndex].offset = 0; + mVertexInputBindingDescs[attribIndex].stride = dstStride; + setVertexInputAttribDescFormat(renderer, attribIndex, attrib.format->id); + setVertexInputBindingDescDivisor(renderer, attribIndex, binding.getDivisor()); + + mCurrentEnabledAttribsMask.set(attribIndex); return angle::Result::Continue; } @@ -1159,7 +1259,7 @@ gl::AttributesMask VertexArrayVk::mergeClientAttribsRange( { combinedIndexes.push_back(attribIndex); } - GLuint pixelBytes = vertexFormat.getActualBufferFormat(false).pixelBytes; + GLuint pixelBytes = vertexFormat.getActualBufferFormat().pixelBytes; size_t destStride = combined ? binding.getStride() : pixelBytes; uintptr_t startAddress = reinterpret_cast(attrib.pointer); mergeRangesOut[attribIndex].startAddr = startAddress; @@ -1223,8 +1323,7 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, vk::Renderer *renderer = contextVk->getRenderer(); const gl::AttributesMask activeAttribs = - context->getStateCache().getActiveClientAttribsMask() | - context->getStateCache().getActiveBufferedAttribsMask(); + context->getActiveClientAttribsMask() | context->getActiveBufferedAttribsMask(); const gl::AttributesMask activeStreamedAttribs = mStreamingVertexAttribsMask & activeAttribs; // Early return for corner case where emulated buffered attribs are not active @@ -1256,15 +1355,14 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); - const angle::Format &dstFormat = vertexFormat.getActualBufferFormat(false); + const angle::Format &dstFormat = vertexFormat.getActualBufferFormat(); GLuint pixelBytes = dstFormat.pixelBytes; - const bool compressed = false; - ASSERT(vertexFormat.getVertexInputAlignment(false) <= vk::kVertexBufferAlignment); + ASSERT(vertexFormat.getVertexInputAlignment() <= vk::kVertexBufferAlignment); vk::BufferHelper *vertexDataBuffer = nullptr; const uint8_t *src = static_cast(attrib.pointer); - const uint32_t divisor = binding.getDivisor(); + uint32_t divisor = binding.getDivisor(); bool combined = mergeAttribMask.test(attribIndex); GLuint stride = combined ? binding.getStride() : pixelBytes; @@ -1274,23 +1372,25 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, // Instanced attrib if (divisor > renderer->getMaxVertexAttribDivisor()) { - // Divisor will be set to 1 & so update buffer to have 1 attrib per instance - size_t bytesToAllocate = instanceCount * stride; + // Divisor will be set to 1 & so update buffer to have 1 attrib per instance. Make + // sure we do multiplication with uint64_t in case the result is more than 32 bit. + // We will let buffer allocation code handle the failure if needed. + size_t bytesToAllocate = static_cast(instanceCount) * stride; // Allocate buffer for results ANGLE_TRY(contextVk->allocateStreamedVertexBuffer(attribIndex, bytesToAllocate, &vertexDataBuffer)); - gl::Buffer *bufferGL = binding.getBuffer().get(); + gl::Buffer *bufferGL = getVertexArrayBuffer(attrib.bindingIndex); if (bufferGL != nullptr) { // Only do the data copy if src buffer is valid. if (bufferGL->getSize() > 0) { // Map buffer to expand attribs for divisor emulation - BufferVk *bufferVk = vk::GetImpl(binding.getBuffer().get()); + BufferVk *bufferVk = vk::GetImpl(bufferGL); void *buffSrc = nullptr; - ANGLE_TRY(bufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &buffSrc)); + ANGLE_TRY(bufferVk->mapForReadAccessOnly(contextVk, &buffSrc)); src = reinterpret_cast(buffSrc) + binding.getOffset(); uint32_t srcAttributeSize = @@ -1300,10 +1400,9 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, ANGLE_TRY(StreamVertexDataWithDivisor( contextVk, vertexDataBuffer, src, bytesToAllocate, binding.getStride(), - stride, vertexFormat.getVertexLoadFunction(compressed), divisor, - numVertices)); + stride, vertexFormat.getVertexLoadFunction(), divisor, numVertices)); - ANGLE_TRY(bufferVk->unmapImpl(contextVk)); + ANGLE_TRY(bufferVk->unmapReadAccessOnly(contextVk)); } else if (contextVk->getExtensions().robustnessAny()) { @@ -1317,13 +1416,14 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, size_t numVertices = instanceCount; ANGLE_TRY(StreamVertexDataWithDivisor( contextVk, vertexDataBuffer, src, bytesToAllocate, binding.getStride(), - stride, vertexFormat.getVertexLoadFunction(compressed), divisor, - numVertices)); + stride, vertexFormat.getVertexLoadFunction(), divisor, numVertices)); } + + divisor = 1; } else { - ASSERT(binding.getBuffer().get() == nullptr); + ASSERT(getVertexArrayBuffer(attrib.bindingIndex) == nullptr); size_t count = UnsignedCeilDivide(instanceCount, divisor); size_t bytesToAllocate = count * stride; @@ -1333,12 +1433,24 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, ANGLE_TRY(StreamVertexData(contextVk, vertexDataBuffer, src, bytesToAllocate, 0, count, binding.getStride(), - vertexFormat.getVertexLoadFunction(compressed))); + vertexFormat.getVertexLoadFunction())); } } + else if (attrib.pointer == nullptr) + { + // Set them to the initial value. + vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer(); + mCurrentArrayBuffers[attribIndex] = &emptyBuffer; + mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle(); + mCurrentArrayBufferOffsets[attribIndex] = 0; + mCurrentArrayBufferSizes[attribIndex] = 0; + mVertexInputBindingDescs[attribIndex].stride = 0; + setVertexInputBindingDescDivisor(renderer, attribIndex, 0); + continue; + } else { - ASSERT(binding.getBuffer().get() == nullptr); + ASSERT(getVertexArrayBuffer(attrib.bindingIndex) == nullptr); size_t mergedAttribIdx = mergedIndexes[attribIndex]; const AttributeRange &range = mergeRanges[attribIndex]; if (attribBufferHelper[mergedAttribIdx] == nullptr) @@ -1352,7 +1464,7 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, contextVk, attribBufferHelper[mergedAttribIdx], (const uint8_t *)range.copyStartAddr, bytesToAllocate - destOffset, destOffset, vertexCount, binding.getStride(), - combined ? nullptr : vertexFormat.getVertexLoadFunction(compressed))); + combined ? nullptr : vertexFormat.getVertexLoadFunction())); } vertexDataBuffer = attribBufferHelper[mergedAttribIdx]; startOffset = combined ? (uintptr_t)attrib.pointer - range.startAddr : 0; @@ -1360,16 +1472,26 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context, ASSERT(vertexDataBuffer != nullptr); mCurrentArrayBuffers[attribIndex] = vertexDataBuffer; mCurrentArrayBufferSerial[attribIndex] = vertexDataBuffer->getBufferSerial(); + VkDeviceSize bufferSize = vertexDataBuffer->getSize(); + VkDeviceSize bufferOffset; - mCurrentArrayBufferHandles[attribIndex] = - vertexDataBuffer - ->getBufferForVertexArray(contextVk, vertexDataBuffer->getSize(), &bufferOffset) - .getHandle(); + if (contextVk->getFeatures().supportsBindVertexBuffers2.enabled) + { + mCurrentArrayBufferHandles[attribIndex] = vertexDataBuffer->getBuffer().getHandle(); + bufferOffset = vertexDataBuffer->getOffset(); + } + else + { + mCurrentArrayBufferHandles[attribIndex] = + vertexDataBuffer->getBufferForVertexArray(contextVk, bufferSize, &bufferOffset) + .getHandle(); + } mCurrentArrayBufferOffsets[attribIndex] = bufferOffset + startOffset; - mCurrentArrayBufferStrides[attribIndex] = stride; - mCurrentArrayBufferDivisors[attribIndex] = divisor; + mCurrentArrayBufferSizes[attribIndex] = bufferSize - startOffset; + mVertexInputBindingDescs[attribIndex].stride = stride; + setVertexInputBindingDescDivisor(renderer, attribIndex, divisor); ASSERT(BindingIsAligned(dstFormat, mCurrentArrayBufferOffsets[attribIndex], - mCurrentArrayBufferStrides[attribIndex])); + mVertexInputBindingDescs[attribIndex].stride)); } return angle::Result::Continue; @@ -1388,7 +1510,7 @@ angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk, // Handle GL_LINE_LOOP drawElements. if (mDirtyLineLoopTranslation) { - gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer(); + gl::Buffer *elementArrayBuffer = getElementArrayBuffer(); if (!elementArrayBuffer) { @@ -1440,32 +1562,71 @@ angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk, angle::Result VertexArrayVk::updateDefaultAttrib(ContextVk *contextVk, size_t attribIndex) { - if (!mState.getEnabledAttributesMask().test(attribIndex)) - { - vk::BufferHelper *bufferHelper; - ANGLE_TRY( - contextVk->allocateStreamedVertexBuffer(attribIndex, kDefaultValueSize, &bufferHelper)); + ASSERT(!mState.getEnabledAttributesMask().test(attribIndex)); + vk::Renderer *renderer = contextVk->getRenderer(); + vk::BufferHelper *bufferHelper; + ANGLE_TRY( + contextVk->allocateStreamedVertexBuffer(attribIndex, kDefaultValueSize, &bufferHelper)); - const gl::VertexAttribCurrentValueData &defaultValue = - contextVk->getState().getVertexAttribCurrentValues()[attribIndex]; - uint8_t *ptr = bufferHelper->getMappedMemory(); - memcpy(ptr, &defaultValue.Values, kDefaultValueSize); - ANGLE_TRY(bufferHelper->flush(contextVk->getRenderer())); + const gl::VertexAttribCurrentValueData &defaultValue = + contextVk->getState().getVertexAttribCurrentValues()[attribIndex]; + uint8_t *ptr = bufferHelper->getMappedMemory(); + memcpy(ptr, &defaultValue.Values, kDefaultValueSize); + ANGLE_TRY(bufferHelper->flush(contextVk->getRenderer())); - VkDeviceSize bufferOffset; + VkDeviceSize bufferOffset; + if (contextVk->getFeatures().supportsBindVertexBuffers2.enabled) + { + mCurrentArrayBufferHandles[attribIndex] = bufferHelper->getBuffer().getHandle(); + bufferOffset = bufferHelper->getOffset(); + } + else + { mCurrentArrayBufferHandles[attribIndex] = bufferHelper->getBufferForVertexArray(contextVk, kDefaultValueSize, &bufferOffset) .getHandle(); - mCurrentArrayBufferOffsets[attribIndex] = bufferOffset; - mCurrentArrayBuffers[attribIndex] = bufferHelper; - mCurrentArrayBufferSerial[attribIndex] = bufferHelper->getBufferSerial(); - mCurrentArrayBufferStrides[attribIndex] = 0; - mCurrentArrayBufferDivisors[attribIndex] = 0; - - ANGLE_TRY(setDefaultPackedInput(contextVk, attribIndex, - &mCurrentArrayBufferFormats[attribIndex])); } + mCurrentArrayBufferOffsets[attribIndex] = bufferOffset; + mCurrentArrayBufferSizes[attribIndex] = kDefaultValueSize; + mCurrentArrayBuffers[attribIndex] = bufferHelper; + mCurrentArrayBufferSerial[attribIndex] = bufferHelper->getBufferSerial(); + mVertexInputBindingDescs[attribIndex].stride = 0; + setVertexInputBindingDescDivisor(renderer, attribIndex, 0); + + setDefaultPackedInput(contextVk, attribIndex, &mDefaultAttribFormatIDs[attribIndex]); + setVertexInputAttribDescFormat(renderer, attribIndex, mDefaultAttribFormatIDs[attribIndex]); return angle::Result::Continue; } + +ANGLE_INLINE void VertexArrayVk::setVertexInputAttribDescFormat(vk::Renderer *renderer, + size_t attribIndex, + angle::FormatID formatID) +{ + const vk::Format &format = renderer->getFormat(formatID); + mVertexInputAttribDescs[attribIndex].format = format.getActualBufferVkFormat(renderer); + + const angle::Format &intendedFormat = format.getIntendedFormat(); + gl::ComponentType componentType = GetVertexAttributeComponentType( + intendedFormat.isPureInt(), intendedFormat.vertexAttribType); + gl::SetComponentTypeMask(componentType, attribIndex, &mCurrentVertexAttributesTypeMask); +} + +ANGLE_INLINE void VertexArrayVk::setVertexInputBindingDescDivisor(vk::Renderer *renderer, + size_t attribIndex, + GLuint divisor) +{ + if (divisor != 0) + { + mVertexInputBindingDescs[attribIndex].inputRate = + static_cast(VK_VERTEX_INPUT_RATE_INSTANCE); + mVertexInputBindingDescs[attribIndex].divisor = divisor; + } + else + { + mVertexInputBindingDescs[attribIndex].inputRate = + static_cast(VK_VERTEX_INPUT_RATE_VERTEX); + mVertexInputBindingDescs[attribIndex].divisor = mZeroDivisor; + } +} } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h index 0e61ac507a5..407273147d9 100644 --- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h +++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h @@ -46,18 +46,22 @@ ANGLE_INLINE bool operator<(const AttributeRange &a, const AttributeRange &b) class VertexArrayVk : public VertexArrayImpl { public: - VertexArrayVk(ContextVk *contextVk, const gl::VertexArrayState &state); + VertexArrayVk(ContextVk *contextVk, + const gl::VertexArrayState &state, + const gl::VertexArrayBuffers &vertexArrayBuffers); ~VertexArrayVk() override; void destroy(const gl::Context *context) override; + gl::VertexArray::DirtyBits checkBufferForDirtyBits( + const gl::Context *context, + const gl::VertexArrayBufferBindingMask bufferBindingMask) override; + angle::Result syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, gl::VertexArray::DirtyAttribBitsArray *attribBits, gl::VertexArray::DirtyBindingBitsArray *bindingBits) override; - angle::Result updateActiveAttribInfo(ContextVk *contextVk); - angle::Result updateDefaultAttrib(ContextVk *contextVk, size_t attribIndex); angle::Result updateStreamedAttribs(const gl::Context *context, @@ -99,34 +103,46 @@ class VertexArrayVk : public VertexArrayImpl return mCurrentArrayBufferOffsets; } - const gl::AttribArray &getCurrentArrayBufferRelativeOffsets() const + const gl::AttribArray &getCurrentArrayBufferSizes() const { - return mCurrentArrayBufferRelativeOffsets; + return mCurrentArrayBufferSizes; } - const gl::AttribArray &getCurrentArrayBuffers() const + const gl::AttribArray &getVertexInputBindingDescs() const { - return mCurrentArrayBuffers; + return mVertexInputBindingDescs; + } + + const gl::AttribArray &getVertexInputAttribDescs() const + { + return mVertexInputAttribDescs; + } + + GLuint getCurrentArrayBufferRelativeOffset(size_t attribIndex) const + { + return mVertexInputAttribDescs[attribIndex].offset; } - const gl::AttribArray &getCurrentArrayBufferFormats() const + VkFormat getCurrentArrayBufferVkFormat(size_t attribIndex) const { - return mCurrentArrayBufferFormats; + return mVertexInputAttribDescs[attribIndex].format; } - const gl::AttribArray &getCurrentArrayBufferStrides() const + angle::FormatID getCurrentArrayBufferFormatID(size_t attribIndex) const { - return mCurrentArrayBufferStrides; + return mCurrentEnabledAttribsMask.test(attribIndex) + ? mState.getVertexAttribute(attribIndex).format->id + : mDefaultAttribFormatIDs[attribIndex]; } - const gl::AttribArray &getCurrentArrayBufferDivisors() const + GLuint getCurrentArrayBufferStride(size_t attribIndex) const { - return mCurrentArrayBufferDivisors; + return mVertexInputBindingDescs[attribIndex].stride; } - const gl::AttributesMask &getCurrentArrayBufferCompressed() const + GLuint getCurrentArrayBufferDivisor(size_t attribIndex) const { - return mCurrentArrayBufferCompressed; + return mVertexInputBindingDescs[attribIndex].divisor; } // Update mCurrentElementArrayBuffer based on the vertex array state @@ -134,6 +150,11 @@ class VertexArrayVk : public VertexArrayImpl vk::BufferHelper *getCurrentElementArrayBuffer() const { return mCurrentElementArrayBuffer; } + const gl::AttribArray &getCurrentArrayBuffers() const + { + return mCurrentArrayBuffers; + } + angle::Result convertIndexBufferGPU(ContextVk *contextVk, BufferVk *bufferVk, const void *indices); @@ -149,11 +170,15 @@ class VertexArrayVk : public VertexArrayImpl const void *sourcePointer, BufferBindingDirty *bufferBindingDirty); - const gl::AttributesMask &getStreamingVertexAttribsMask() const + gl::AttributesMask getStreamingVertexAttribsMask() const { return mStreamingVertexAttribsMask; } + + gl::ComponentTypeMask getCurrentVertexAttributesTypeMask() const { - return mStreamingVertexAttribsMask; + return mCurrentVertexAttributesTypeMask; } + gl::AttributesMask getCurrentEnabledAttribsMask() const { return mCurrentEnabledAttribsMask; } + private: gl::AttributesMask mergeClientAttribsRange( vk::Renderer *renderer, @@ -163,9 +188,9 @@ class VertexArrayVk : public VertexArrayImpl std::array &mergeRangesOut, std::array &mergedIndexesOut) const; - angle::Result setDefaultPackedInput(ContextVk *contextVk, - size_t attribIndex, - angle::FormatID *formatOut); + void setDefaultPackedInput(ContextVk *contextVk, + size_t attribIndex, + angle::FormatID *formatOut); angle::Result convertVertexBufferGPU(ContextVk *contextVk, BufferVk *srcBuffer, @@ -179,24 +204,51 @@ class VertexArrayVk : public VertexArrayImpl const angle::Format &dstFormat, const VertexCopyFunction vertexLoadFunction); - angle::Result syncDirtyAttrib(ContextVk *contextVk, - const gl::VertexAttribute &attrib, - const gl::VertexBinding &binding, - size_t attribIndex, - bool bufferOnly); + angle::Result syncDirtyEnabledNonStreamingAttrib( + ContextVk *contextVk, + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + size_t attribIndex, + const gl::VertexArray::DirtyAttribBits &dirtyAttribBits); + + angle::Result syncDirtyEnabledStreamingAttrib( + ContextVk *contextVk, + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + size_t attribIndex, + const gl::VertexArray::DirtyAttribBits &dirtyAttribBits); + + angle::Result syncDirtyDisabledAttrib(ContextVk *contextVk, + const gl::VertexAttribute &attrib, + size_t attribIndex); + + angle::Result syncNeedsConversionAttrib(ContextVk *contextVk, + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + size_t attribIndex); + + void setVertexInputAttribDescFormat(vk::Renderer *renderer, + size_t attribIndex, + angle::FormatID formatID); + + void setVertexInputBindingDescDivisor(vk::Renderer *renderer, + size_t attribIndex, + GLuint divisor); gl::AttribArray mCurrentArrayBufferHandles; gl::AttribArray mCurrentArrayBufferOffsets; - // The offset into the buffer to the first attrib - gl::AttribArray mCurrentArrayBufferRelativeOffsets; + gl::AttribArray mCurrentArrayBufferSizes; gl::AttribArray mCurrentArrayBuffers; // Tracks BufferSerial of mCurrentArrayBuffers since they are always valid to access. gl::AttribArray mCurrentArrayBufferSerial; - // Cache strides of attributes for a fast pipeline cache update when VAOs are changed - gl::AttribArray mCurrentArrayBufferFormats; - gl::AttribArray mCurrentArrayBufferStrides; - gl::AttribArray mCurrentArrayBufferDivisors; - gl::AttributesMask mCurrentArrayBufferCompressed; + // Tracks the default attribute format ID + gl::AttribArray mDefaultAttribFormatIDs; + + // These struct are defined by VK_EXT_vertex_input_dynamic_state, for convenience, we these to + // store offset/divisor even when vertexInputDynamicState not supported. + gl::AttribArray mVertexInputBindingDescs; + gl::AttribArray mVertexInputAttribDescs; + vk::BufferHelper *mCurrentElementArrayBuffer; // Cached element array buffers for improving performance. @@ -211,12 +263,17 @@ class VertexArrayVk : public VertexArrayImpl Optional mLineLoopBufferLastIndex; bool mDirtyLineLoopTranslation; + gl::BufferBindingMask mDivisorExceedMaxSupportedValueBindingMask; + + gl::AttributesMask mCurrentEnabledAttribsMask; // Track client and/or emulated attribs that we have to stream their buffer contents gl::AttributesMask mStreamingVertexAttribsMask; + gl::AttributesMask mNeedsConversionAttribsMask; + + gl::ComponentTypeMask mCurrentVertexAttributesTypeMask; - // The attrib/binding dirty bits that requires graphics pipeline update - gl::VertexArray::DirtyBindingBits mBindingDirtyBitsRequiresPipelineUpdate; - gl::VertexArray::DirtyAttribBits mAttribDirtyBitsRequiresPipelineUpdate; + // This maybe 0 or 1 depends on feature bit + uint32_t mZeroDivisor; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/VkImageImageSiblingVk.cpp b/src/libANGLE/renderer/vulkan/VkImageImageSiblingVk.cpp index 6984909c779..b61e3cc5d6f 100644 --- a/src/libANGLE/renderer/vulkan/VkImageImageSiblingVk.cpp +++ b/src/libANGLE/renderer/vulkan/VkImageImageSiblingVk.cpp @@ -49,9 +49,10 @@ angle::Result VkImageImageSiblingVk::initImpl(DisplayVk *displayVk) ANGLE_VK_CHECK(displayVk, formatID != angle::FormatID::NONE, VK_ERROR_FORMAT_NOT_SUPPORTED); const vk::Format &vkFormat = renderer->getFormat(formatID); - const vk::ImageAccess imageAccess = - isRenderable(nullptr) ? vk::ImageAccess::Renderable : vk::ImageAccess::SampleOnly; - const angle::FormatID actualImageFormatID = vkFormat.getActualImageFormatID(imageAccess); + const vk::ImageFormatSupport formatSupport = isRenderable(nullptr) + ? vk::ImageFormatSupport::Renderable + : vk::ImageFormatSupport::SampleOnly; + const angle::FormatID actualImageFormatID = vkFormat.getActualImageFormatID(formatSupport); const angle::Format &format = angle::Format::Get(actualImageFormatID); angle::FormatID intendedFormatID; diff --git a/src/libANGLE/renderer/vulkan/VulkanSecondaryCommandBuffer.h b/src/libANGLE/renderer/vulkan/VulkanSecondaryCommandBuffer.h index 0d2a16ed019..4e05603cdc3 100644 --- a/src/libANGLE/renderer/vulkan/VulkanSecondaryCommandBuffer.h +++ b/src/libANGLE/renderer/vulkan/VulkanSecondaryCommandBuffer.h @@ -20,11 +20,7 @@ class PoolAllocator; class SharedRingBufferAllocator; } // namespace angle -#if ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC -using SecondaryCommandMemoryAllocator = angle::SharedRingBufferAllocator; -#else using SecondaryCommandMemoryAllocator = angle::PoolAllocator; -#endif namespace rx { @@ -60,10 +56,6 @@ class VulkanSecondaryCommandBuffer : public priv::CommandBuffer void destroy(); - void attachAllocator(SecondaryCommandMemoryAllocator *source) {} - - void detachAllocator(SecondaryCommandMemoryAllocator *destination) {} - angle::Result begin(ErrorContext *context, const VkCommandBufferInheritanceInfo &inheritanceInfo); angle::Result end(ErrorContext *context); diff --git a/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp b/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp index 24117003eb1..bfd66559bba 100644 --- a/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp +++ b/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp @@ -7,6 +7,10 @@ // Implements the class methods for DisplayVkAndroid. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h" #include @@ -79,6 +83,13 @@ egl::ConfigSet DisplayVkAndroid::generateConfigs() { VkFormat vkFormat = mRenderer->getFormat(glFormat).getActualRenderableImageVkFormat(mRenderer); + // The config for display format should remain as R5G6B5, since creating B5G6R5 surfaces + // is currently not supported. + if (getFeatures().preferBGR565ToRGB565.enabled && + vkFormat == VK_FORMAT_B5G6R5_UNORM_PACK16) + { + vkFormat = VK_FORMAT_R5G6B5_UNORM_PACK16; + } ASSERT(vkFormat != VK_FORMAT_UNDEFINED); if (isConfigFormatSupported(vkFormat)) { diff --git a/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp b/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp index d473715486b..2a09ec53345 100644 --- a/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp +++ b/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp @@ -155,6 +155,36 @@ HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClie HardwareBufferImageSiblingVkAndroid::~HardwareBufferImageSiblingVkAndroid() {} +void CheckFormatSupport( + vk::Renderer *renderer, + const VkAndroidHardwareBufferFormatPropertiesANDROID &bufferFormatProperties, + const uint64_t ahbUsage, + bool *externalFormatHasNecessaryFormatSupport, + bool *formatHasNecessaryFormatSupport) +{ + *externalFormatHasNecessaryFormatSupport = + ((bufferFormatProperties.formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0); + + if (((ahbUsage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0) && + (bufferFormatProperties.formatFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0) + { + *externalFormatHasNecessaryFormatSupport = false; + } + + if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED) + { + *formatHasNecessaryFormatSupport = false; + } + else + { + angle::FormatID formatID = vk::GetFormatIDFromVkFormat(bufferFormatProperties.format); + *formatHasNecessaryFormatSupport = + (ahbUsage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0 + ? HasFullTextureFormatSupport(renderer, formatID) + : HasNonRenderableTextureFormatSupport(renderer, formatID); + } +} + // Static egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer( vk::Renderer *renderer, @@ -209,32 +239,31 @@ egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer( angle::android::GetANativeWindowBufferProperties(windowBuffer, &width, &height, &depth, &pixelFormat, &usage); - if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED) + // https://registry.khronos.org/vulkan/specs/latest/man/html/VkAndroidHardwareBufferFormatPropertiesANDROID.html + // "externalFormat [...] must not be zero." + ASSERT(bufferFormatProperties.externalFormat != 0); + + bool externalFormatHasNecessaryFormatSupport; + bool formatHasNecessaryFormatSupport; + + CheckFormatSupport(renderer, bufferFormatProperties, usage, + &externalFormatHasNecessaryFormatSupport, &formatHasNecessaryFormatSupport); + + if (!externalFormatHasNecessaryFormatSupport && + (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)) { - ASSERT(bufferFormatProperties.externalFormat != 0); - // We must have an external format, check that it supports texture sampling - if (!(bufferFormatProperties.formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) - { - std::ostringstream err; - err << "Sampling from AHardwareBuffer externalFormat 0x" << std::hex - << bufferFormatProperties.externalFormat << " is unsupported."; - return egl::Error(EGL_BAD_PARAMETER, err.str()); - } + std::ostringstream err; + err << "Sampling from AHardwareBuffer externalFormat 0x" << std::hex + << bufferFormatProperties.externalFormat << " is unsupported."; + return egl::Error(EGL_BAD_PARAMETER, err.str()); } - else + + if (!externalFormatHasNecessaryFormatSupport && !formatHasNecessaryFormatSupport) { - angle::FormatID formatID = vk::GetFormatIDFromVkFormat(bufferFormatProperties.format); - const bool hasNecessaryFormatSupport = - (usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0 - ? HasFullTextureFormatSupport(renderer, formatID) - : HasNonRenderableTextureFormatSupport(renderer, formatID); - if (!hasNecessaryFormatSupport) - { - std::ostringstream err; - err << "AHardwareBuffer format " << bufferFormatProperties.format - << " does not support enough features to use as a texture."; - return egl::Error(EGL_BAD_PARAMETER, err.str()); - } + std::ostringstream err; + err << "AHardwareBuffer format " << bufferFormatProperties.format + << " does not support enough features to use as a texture."; + return egl::Error(EGL_BAD_PARAMETER, err.str()); } if (attribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE) @@ -298,7 +327,19 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk ANGLE_VK_TRY(displayVk, vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer, &bufferProperties)); - const bool isExternal = bufferFormatProperties.format == VK_FORMAT_UNDEFINED; + bool externalFormatHasNecessaryFormatSupport; + bool formatHasNecessaryFormatSupport; + + CheckFormatSupport(renderer, bufferFormatProperties, mUsage, + &externalFormatHasNecessaryFormatSupport, &formatHasNecessaryFormatSupport); + + ASSERT(formatHasNecessaryFormatSupport || externalFormatHasNecessaryFormatSupport); + + const bool isExternal = + externalFormatHasNecessaryFormatSupport && !formatHasNecessaryFormatSupport; + + ANGLE_VK_CHECK(displayVk, isExternal || bufferFormatProperties.format != VK_FORMAT_UNDEFINED, + VK_ERROR_INITIALIZATION_FAILED); VkExternalFormatANDROID externalFormat = {}; externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; @@ -349,15 +390,19 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk { ANGLE_VK_CHECK(displayVk, bufferFormatProperties.externalFormat != 0, VK_ERROR_UNKNOWN); externalFormat.externalFormat = bufferFormatProperties.externalFormat; + ASSERT(externalFormat.externalFormat != 0); - // VkImageCreateInfo struct: If the pNext chain includes a VkExternalFormatANDROID structure - // whose externalFormat member is not 0, usage must not include any usages except - // VK_IMAGE_USAGE_SAMPLED_BIT - if (externalFormat.externalFormat != 0 && !externalRenderTargetSupported) - { - // Clear all other bits except sampled - usage &= VK_IMAGE_USAGE_SAMPLED_BIT; - } + // VUID-VkImageCreateInfo-pNext-02397 states - + // If the pNext chain includes a VkExternalFormatANDROID structure whose externalFormat + // member is not 0, usage must not include any usages except + // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, or + // VK_IMAGE_USAGE_SAMPLED_BIT + const VkImageUsageFlags allowedUsage = + VK_IMAGE_USAGE_SAMPLED_BIT | + (externalRenderTargetSupported ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0); + + // Clear all other usage bits + usage &= allowedUsage; // If the pNext chain includes a VkExternalFormatANDROID structure whose externalFormat // member is not 0, tiling must be VK_IMAGE_TILING_OPTIMAL @@ -399,12 +444,21 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk bool robustInitEnabled = false; mImage->setTilingMode(imageTilingMode); + VkImageCreateFlags imageCreateFlags = AhbDescUsageToVkImageCreateFlags(ahbDescription); + if (renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled && + (usage & + (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) != 0) + { + // We don't know if it will be used for MSRTSS or not, so always create with the bit + imageCreateFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT; + } + vk::YcbcrConversionDesc conversionDesc{}; if (isExternal) { - if (externalRenderTargetSupported) + if ((usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) { angle::FormatID externalFormatID = renderer->getExternalFormatTable()->getOrAllocExternalFormatID( @@ -461,10 +515,10 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk ANGLE_TRY(mImage->initExternal(displayVk, textureType, vkExtents, vkFormat->getIntendedFormatID(), actualRenderableFormatID, 1, - usage, imageCreateFlags, vk::ImageLayout::ExternalPreInitialized, + usage, imageCreateFlags, vk::ImageAccess::ExternalPreInitialized, imageCreateInfoPNext, gl::LevelIndex(0), mLevelCount, layerCount, - robustInitEnabled, hasProtectedContent(), conversionDesc, - nullptr)); + robustInitEnabled, hasProtectedContent(), + vk::TileMemory::Prohibited, conversionDesc, nullptr)); VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {}; importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; diff --git a/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp b/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp index 61fe2023a9a..afe6dc503b4 100644 --- a/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp +++ b/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp @@ -21,8 +21,7 @@ WindowSurfaceVkAndroid::WindowSurfaceVkAndroid(const egl::SurfaceState &surfaceS : WindowSurfaceVk(surfaceState, window) {} -angle::Result WindowSurfaceVkAndroid::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkAndroid::createSurfaceVk(vk::ErrorContext *context) { VkAndroidSurfaceCreateInfoKHR createInfo = {}; @@ -32,11 +31,11 @@ angle::Result WindowSurfaceVkAndroid::createSurfaceVk(vk::ErrorContext *context, ANGLE_VK_TRY(context, vkCreateAndroidSurfaceKHR(context->getRenderer()->getInstance(), &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkAndroid::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { vk::Renderer *renderer = context->getRenderer(); const VkPhysicalDevice &physicalDevice = renderer->getPhysicalDevice(); diff --git a/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h b/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h index 69157e2fde8..6ab0bb563a6 100644 --- a/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h +++ b/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h @@ -21,8 +21,9 @@ class WindowSurfaceVkAndroid : public WindowSurfaceVk WindowSurfaceVkAndroid(const egl::SurfaceState &surfaceState, EGLNativeWindowType window); private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/clspv_utils.cpp b/src/libANGLE/renderer/vulkan/clspv_utils.cpp index e7570157b4b..ebd05060c86 100644 --- a/src/libANGLE/renderer/vulkan/clspv_utils.cpp +++ b/src/libANGLE/renderer/vulkan/clspv_utils.cpp @@ -6,6 +6,10 @@ // Utilities to map clspv interface variables to OpenCL and Vulkan mappings. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/clspv_utils.h" #include "common/log_utils.h" #include "libANGLE/renderer/vulkan/CLDeviceVk.h" @@ -23,6 +27,12 @@ #include "spirv-tools/libspirv.h" #include "spirv-tools/libspirv.hpp" +#if defined(ANGLE_ENABLE_ASSERTS) +constexpr bool kAngleDebug = true; +#else +constexpr bool kAngleDebug = false; +#endif + namespace rx { constexpr std::string_view kPrintfConversionSpecifiers = "diouxXfFeEgGaAcsp"; @@ -94,30 +104,44 @@ std::string PrintFormattedString(const std::string &formatString, { // all floats with same convention as snprintf if (size == 2) + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), cl_half_to_float(ReadPtrAs(data))); + } else if (size == 4) + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), ReadPtrAs(data)); + } else + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), ReadPtrAs(data)); + } break; } default: { if (size == 1) + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), ReadPtrAs(data)); + } else if (size == 2) + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), ReadPtrAs(data)); + } else if (size == 4) + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), ReadPtrAs(data)); + } else + { bytesWritten = snprintf(out.data(), outSize, formatString.c_str(), ReadPtrAs(data)); + } break; } } @@ -288,6 +312,11 @@ void ProcessPrintfStatement(unsigned char *&data, } std::printf("%s", printfOutput.c_str()); + + if (kAngleDebug) + { + INFO() << "ANGLE-CL.Kernel: " << printfOutput.c_str(); + } } std::string GetSpvVersionAsClspvString(spv_target_env spvVersion) @@ -319,6 +348,61 @@ std::vector GetNativeBuiltins(const vk::Renderer *renderer) } } // anonymous namespace +namespace clspv_cl +{ + +cl::AddressingMode GetAddressingMode(uint32_t mask) +{ + cl::AddressingMode addressingMode = cl::AddressingMode::Clamp; + + switch (mask & clspv::kSamplerAddressMask) + { + case clspv::CLK_ADDRESS_NONE: + default: + addressingMode = + cl::FromCLenum(static_cast(CL_ADDRESS_NONE)); + break; + case clspv::CLK_ADDRESS_CLAMP_TO_EDGE: + addressingMode = + cl::FromCLenum(static_cast(CL_ADDRESS_CLAMP_TO_EDGE)); + break; + case clspv::CLK_ADDRESS_CLAMP: + addressingMode = + cl::FromCLenum(static_cast(CL_ADDRESS_CLAMP)); + break; + case clspv::CLK_ADDRESS_MIRRORED_REPEAT: + addressingMode = + cl::FromCLenum(static_cast(CL_ADDRESS_MIRRORED_REPEAT)); + break; + case clspv::CLK_ADDRESS_REPEAT: + addressingMode = + cl::FromCLenum(static_cast(CL_ADDRESS_REPEAT)); + break; + } + + return addressingMode; +} + +cl::FilterMode GetFilterMode(uint32_t mask) +{ + cl::FilterMode filterMode = cl::FilterMode::Nearest; + + switch (mask & clspv::kSamplerFilterMask) + { + case clspv::CLK_FILTER_NEAREST: + default: + filterMode = cl::FromCLenum(static_cast(CL_FILTER_NEAREST)); + break; + case clspv::CLK_FILTER_LINEAR: + filterMode = cl::FromCLenum(static_cast(CL_FILTER_LINEAR)); + break; + } + + return filterMode; +} + +} // namespace clspv_cl + // Process the data recorded into printf storage buffer along with the info in printfino descriptor // and write it to stdout. angle::Result ClspvProcessPrintfBuffer(unsigned char *buffer, @@ -362,6 +446,11 @@ std::string ClspvGetCompilerOptions(const CLDeviceVk *device) ASSERT(false); } options += addressBits == 64 ? " -arch=spir64" : " -arch=spir"; + if (rendererVk->getFeatures().supportsBufferDeviceAddress.enabled) + { + ASSERT(addressBits == 64); + options += " -physical-storage-buffers "; + } // select SPIR-V version target options += " --spv-version=" + GetSpvVersionAsClspvString(device->getSpirvVersion()); @@ -399,6 +488,17 @@ std::string ClspvGetCompilerOptions(const CLDeviceVk *device) options += " --enable-printf"; options += " --cl-kernel-arg-info"; + // add opencl atomic feature macros + featureMacros.push_back("__opencl_c_atomic_order_acq_rel"); + featureMacros.push_back("__opencl_c_atomic_order_seq_cst"); + featureMacros.push_back("__opencl_c_atomic_scope_device"); + + // check for int8 support + if (rendererVk->getFeatures().supportsShaderInt8.enabled) + { + options += " --int8 --rewrite-packed-structs"; + } + // 8 bit storage buffer support if (!rendererVk->getFeatures().supports8BitStorageBuffer.enabled) { @@ -472,11 +572,27 @@ std::string ClspvGetCompilerOptions(const CLDeviceVk *device) featureMacros.push_back("__opencl_c_read_write_images"); } + if (rendererVk->getFeatures().supportsBufferDeviceAddress.enabled) + { + // It is for generating ConstantDataStorageBuffer without -physical-storage-buffers, + // ConstantDataPointerPushConstant with -physical-storage-buffers + // TODO: this flag is only on in case of supportsBufferDeviceAddress.enabled + // until ConstantDataStorageBuffer will be implemented. + // http://anglebug.com/442950569 + options += " -module-constants-in-storage-buffer"; + } + if (rendererVk->getEnabledFeatures().features.shaderInt64) { featureMacros.push_back("__opencl_c_int64"); } + if (rendererVk->getFeatures().supportsShaderIntegerDotProduct.enabled) + { + featureMacros.push_back("__opencl_c_integer_dot_product_input_4x8bit"); + featureMacros.push_back("__opencl_c_integer_dot_product_input_4x8bit_packed"); + } + if (!rteModes.empty()) { options += " --rounding-mode-rte="; diff --git a/src/libANGLE/renderer/vulkan/clspv_utils.h b/src/libANGLE/renderer/vulkan/clspv_utils.h index 9adeac7c1c5..f20c0d37e88 100644 --- a/src/libANGLE/renderer/vulkan/clspv_utils.h +++ b/src/libANGLE/renderer/vulkan/clspv_utils.h @@ -15,6 +15,7 @@ #include #include "clspv/Compiler.h" +#include "clspv/Sampler.h" #include "spirv-tools/libspirv.h" namespace rx @@ -34,6 +35,37 @@ struct ClspvPrintfInfo std::vector argSizes; }; +struct ClspvLiteralSampler +{ + uint32_t descriptorSet; + uint32_t binding; + cl_bool normalizedCoords; + cl::AddressingMode addressingMode; + cl::FilterMode filterMode; +}; + +struct ClspvConstantDataBufferInfo +{ + uint32_t set; + uint32_t binding; + uint32_t pcOffset; + std::vector bufferData; +}; + +namespace clspv_cl +{ + +cl::AddressingMode GetAddressingMode(uint32_t mask); + +cl::FilterMode GetFilterMode(uint32_t mask); + +inline bool IsNormalizedCoords(uint32_t mask) +{ + return (mask & clspv::kSamplerNormalizedCoordsMask) == clspv::CLK_NORMALIZED_COORDS_TRUE; +} + +} // namespace clspv_cl + angle::Result ClspvProcessPrintfBuffer(unsigned char *buffer, const size_t bufferSize, const angle::HashMap *infoMap); diff --git a/src/libANGLE/renderer/vulkan/doc/Allocators.md b/src/libANGLE/renderer/vulkan/doc/Allocators.md index 92ea50b93a5..bf6ed976653 100644 --- a/src/libANGLE/renderer/vulkan/doc/Allocators.md +++ b/src/libANGLE/renderer/vulkan/doc/Allocators.md @@ -1,21 +1,7 @@ # Allocators Allocator helpers are used in the command buffer objects as a means to allocate memory for the -latter. Regardless of the inner workings of the allocation method they use, they use the same -interface in the ANGLE code. - -## Allocator types - -There are currently two types of allocators defined in ANGLE: - -* Pool allocators; and - -* Ring buffer allocators. - -**ANGLE uses pool allocators by default.** To switch to ring buffer allocators, the flag -`angle_enable_vulkan_shared_ring_buffer_cmd_alloc` should be enabled in GN args. This flag appears -as `ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC` in the code, which is used to select the -allocator type. +latter. Currently, only a pool allocator is implemented. ### Common interface @@ -24,8 +10,8 @@ aliased as the following: * `SecondaryCommandMemoryAllocator` - * This is the main allocator object used in the allocator helper classes. It is used as a type - for some of the allocator helpers' public functions. + * This is the main allocator object used in the allocator helper class. It is used as a type + for some of the allocator helper's public functions. * `SecondaryCommandBlockPool` @@ -47,39 +33,3 @@ _Files: `AllocatorHelperPool.cpp` and `AllocatorHelperPool.h`_ - `SecondaryCommandBlockAllocator` -> `DedicatedCommandBlockAllocator` -#### Notes - -* `attachAllocator()` and `detachAllocator()` functions are no-ops for the pool allocators. - -* Regarding `SecondaryCommandBlockAllocator` in pool allocators: - - * `init()` works only with pool allocators. - - * `hasAllocatorLinks()` always returns `false`. - - * `terminateLastCommandBlock()` is no-op. - -### Ring buffer allocator helpers - -_Files: `AllocatorHelperRing.cpp` and `AllocatorHelperRing.h`_ - -- `SecondaryCommandMemoryAllocator` -> `SharedCommandMemoryAllocator` -> `angle::SharedRingBufferAllocator` - -- `SecondaryCommandBlockPool` -> `SharedCommandBlockPool` - -- `SecondaryCommandBlockAllocator` -> `SharedCommandBlockAllocator` - -#### Notes - -* It can be seen that in the context's initialization and destruction, and flushing the command - processor's commands, there are calls to attach and detach an allocator (via `attachAllocator()` - and `detachAllocator()`). Please note that **these functions are only defined for ring buffer - allocators**. - -* Regarding `SecondaryCommandBlockAllocator` in ring buffer allocators: - - * `init()` is no-op. - - * `hasAllocatorLinks()` checks the allocator and the shared checkpoint. - - * `terminateLastCommandBlock()` is only used in ring buffer allocators. diff --git a/src/libANGLE/renderer/vulkan/doc/PresentSemaphores.md b/src/libANGLE/renderer/vulkan/doc/PresentSemaphores.md index bf6bac0c97b..c8dbbc432c3 100644 --- a/src/libANGLE/renderer/vulkan/doc/PresentSemaphores.md +++ b/src/libANGLE/renderer/vulkan/doc/PresentSemaphores.md @@ -94,8 +94,9 @@ old swapchains must now be deferred to when the first QP of the new swapchain ha If an application resizes the window constantly and at a high rate, ANGLE would keep accumulating old swapchains and not free them until it stops. -## VK_EXT_swapchain_maintenance1 +## VK_KHR_swapchain_maintenance1 / VK_EXT_swapchain_maintenance1 -With the VK_EXT_swapchain_maintenance1, all the above is unnecessary. Each QP operation can have an -associated fence, which can be used to know when the semaphore associated with it can be recycled. -The old swapchains are destroyed when QP fences are signaled. +With the VK_KHR_swapchain_maintenance1 or VK_EXT_swapchain_maintenance1 extension, all the above is +unnecessary. Each QP operation can have an associated fence, which can be used to know when the +semaphore associated with it can be recycled. The old swapchains are destroyed when QP fences are +signaled. diff --git a/src/libANGLE/renderer/vulkan/doc/ShaderModuleCompilation.md b/src/libANGLE/renderer/vulkan/doc/ShaderModuleCompilation.md index 771f738f550..bab615a77fe 100644 --- a/src/libANGLE/renderer/vulkan/doc/ShaderModuleCompilation.md +++ b/src/libANGLE/renderer/vulkan/doc/ShaderModuleCompilation.md @@ -5,16 +5,17 @@ of steps: 1. **ANGLE Internal Translation**: The initial calls to `glCompileShader` are passed to the [ANGLE shader translator][translator]. The translator compiles application shaders into SPIR-V, after -transforming GLSL to conform to the [GL_KHR_vulkan_glsl][GL_KHR_vulkan_glsl] extension spec with -some additional workarounds and emulation. We emulate OpenGL's different depth range, viewport y -flipping, default uniforms, and emulate a number of extensions among others. For more info see +transforming it with SPIR-V's restrictions in mind (which are similar to those in the +[GL_KHR_vulkan_glsl][GL_KHR_vulkan_glsl] extension spec) with some additional workarounds and +emulation. We emulate OpenGL's different depth range, viewport y flipping, default uniforms, and +emulate a number of extensions among others. For more info see [TranslatorVulkan.cpp][TranslatorVulkan.cpp]. After initial compilation, the SPIR-V blobs are not complete. The translator initially assigns resources and in/out variables arbitrary descriptor set, binding and location indices. The correct values are determined at link time. For the sake of transform feedback, some additional code is generated to be removed or modified during SPIR-V transformation. - The translator outputs some feature code conditional to Vulkan specialization constants, which are +The translator outputs some feature code conditional to Vulkan specialization constants, which are resolved at draw-time. For example, for emulating Dithering and Android surface rotation. 1. **Link Time**: During a call to `glLinkProgram` the Vulkan back-end can know the necessary @@ -81,6 +82,6 @@ Note right of "Vulkan Back-end": We init VkShaderModules\nand VkPipeline then\nr [GL_KHR_vulkan_glsl]: https://github.com/KhronosGroup/GLSL/blob/main/extensions/khr/GL_KHR_vulkan_glsl.txt [SPIRV-Tools]: https://github.com/KhronosGroup/SPIRV-Tools [translator]: https://chromium.googlesource.com/angle/angle/+/refs/heads/main/src/compiler/translator/ -[TranslatorVulkan.cpp]: https://chromium.googlesource.com/angle/angle/+/refs/heads/main/src/compiler/translator/TranslatorVulkan.cpp +[TranslatorVulkan.cpp]: https://chromium.googlesource.com/angle/angle/+/refs/heads/main/src/compiler/translator/spirv/TranslatorVulkan.cpp [VkShaderModule]: https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkShaderModule.html [PipelineCreation]: PipelineCreation.md diff --git a/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp b/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp index 534ec10a411..8acf5264ab4 100644 --- a/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp +++ b/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp @@ -34,8 +34,7 @@ bool WindowSurfaceVkFuchsia::isValidNativeWindow(EGLNativeWindowType window) return fuchsia_egl_window_get_width(egl_window) >= 0; } -angle::Result WindowSurfaceVkFuchsia::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkFuchsia::createSurfaceVk(vk::ErrorContext *context) { #if !defined(ANGLE_SHARED_LIBVULKAN) InitImagePipeSurfaceFUCHSIAFunctions(context->getRenderer()->getInstance()); @@ -48,11 +47,11 @@ angle::Result WindowSurfaceVkFuchsia::createSurfaceVk(vk::ErrorContext *context, ANGLE_VK_TRY(context, vkCreateImagePipeSurfaceFUCHSIA(context->getRenderer()->getInstance(), &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkFuchsia::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { fuchsia_egl_window *egl_window = reinterpret_cast(mNativeWindowType); diff --git a/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h b/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h index b6aaac77d10..cb04307715b 100644 --- a/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h +++ b/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h @@ -24,8 +24,9 @@ class WindowSurfaceVkFuchsia : public WindowSurfaceVk static bool isValidNativeWindow(EGLNativeWindowType window); private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/gen_vk_format_table.py b/src/libANGLE/renderer/vulkan/gen_vk_format_table.py index e8311efa9d2..716520394f6 100644 --- a/src/libANGLE/renderer/vulkan/gen_vk_format_table.py +++ b/src/libANGLE/renderer/vulkan/gen_vk_format_table.py @@ -92,7 +92,7 @@ mActualRenderableImageFormatID = {image}; mImageInitializerFunction = {image_initializer};""" -image_struct_template = "{{{image}, {image_initializer}}}" +image_struct_template = "{cond_begin}{{{image}, {image_initializer}}},{cond_end}" image_fallback_template = """{{ static constexpr ImageFormatInitInfo kInfo[] = {{{image_list}}}; @@ -187,10 +187,13 @@ def get_formats(format, type): return (fallbacks, len(fallbacks) - len(compressed)) def image_args(format): + is_astc_fallback = angle.startswith("ASTC") and not format.startswith("ASTC") return dict( image="angle::FormatID::" + format, image_initializer=angle_format.get_internal_format_initializer( - internal_format, format)) + internal_format, format), + cond_begin="#ifdef ANGLE_HAS_ASTCENC\n" if is_astc_fallback else "", + cond_end="\n#endif\n" if is_astc_fallback else "") def buffer_args(format): vk_buffer_format = vk_map[format] @@ -211,7 +214,7 @@ def buffer_args(format): elif len(images) > 1: args.update( image_template=image_fallback_template, - image_list=", ".join(image_struct_template.format(**image_args(i)) for i in images)) + image_list="\n".join(image_struct_template.format(**image_args(i)) for i in images)) buffers, buffers_compressed_offset = get_formats(angle, "buffer") if len(buffers) == 1: diff --git a/src/libANGLE/renderer/vulkan/ggp/DisplayVkGGP.cpp b/src/libANGLE/renderer/vulkan/ggp/DisplayVkGGP.cpp deleted file mode 100644 index 031f07dab3e..00000000000 --- a/src/libANGLE/renderer/vulkan/ggp/DisplayVkGGP.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2019 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. -// -// DisplayVkGGP.cpp: -// Implements the class methods for DisplayVkGGP. -// - -#include "libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h" - -#include "libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.h" -#include "libANGLE/renderer/vulkan/vk_caps_utils.h" - -namespace rx -{ -DisplayVkGGP::DisplayVkGGP(const egl::DisplayState &state) : DisplayVk(state) {} - -bool DisplayVkGGP::isValidNativeWindow(EGLNativeWindowType window) const -{ - // GGP doesn't use window handles. - return true; -} - -SurfaceImpl *DisplayVkGGP::createWindowSurfaceVk(const egl::SurfaceState &state, - EGLNativeWindowType window) -{ - return new WindowSurfaceVkGGP(state, window); -} - -egl::ConfigSet DisplayVkGGP::generateConfigs() -{ - // Not entirely sure what backbuffer formats GGP supports. - constexpr GLenum kColorFormats[] = {GL_BGRA8_EXT, GL_BGRX8_ANGLEX}; - return egl_vk::GenerateConfigs(kColorFormats, egl_vk::kConfigDepthStencilFormats, this); -} - -void DisplayVkGGP::checkConfigSupport(egl::Config *config) {} - -const char *DisplayVkGGP::getWSIExtension() const -{ - return VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME; -} - -bool IsVulkanGGPDisplayAvailable() -{ - return true; -} - -DisplayImpl *CreateVulkanGGPDisplay(const egl::DisplayState &state) -{ - return new DisplayVkGGP(state); -} -} // namespace rx diff --git a/src/libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h b/src/libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h deleted file mode 100644 index 4625f9de633..00000000000 --- a/src/libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright 2019 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. -// -// DisplayVkGGP.h: -// Google Game Platform implementation of DisplayVk. -// - -#ifndef LIBANGLE_RENDERER_VULKAN_GGP_DISPLAYVKGGP_H_ -#define LIBANGLE_RENDERER_VULKAN_GGP_DISPLAYVKGGP_H_ - -#include "libANGLE/renderer/vulkan/DisplayVk.h" - -namespace rx -{ -class DisplayVkGGP : public DisplayVk -{ - public: - DisplayVkGGP(const egl::DisplayState &state); - - bool isValidNativeWindow(EGLNativeWindowType window) const override; - - SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state, - EGLNativeWindowType window) override; - - egl::ConfigSet generateConfigs() override; - void checkConfigSupport(egl::Config *config) override; - - const char *getWSIExtension() const override; -}; -} // namespace rx - -#endif // LIBANGLE_RENDERER_VULKAN_GGP_DISPLAYVKGGP_H_ diff --git a/src/libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.cpp b/src/libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.cpp deleted file mode 100644 index 6e1cb8a9310..00000000000 --- a/src/libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright 2019 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. -// -// WindowSurfaceVkGGP.cpp: -// Implements the class methods for WindowSurfaceVkGGP. -// - -#include "libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.h" - -#include "libANGLE/Context.h" -#include "libANGLE/Display.h" -#include "libANGLE/Surface.h" -#include "libANGLE/renderer/vulkan/DisplayVk.h" -#include "libANGLE/renderer/vulkan/vk_renderer.h" - -namespace rx -{ -namespace -{ -constexpr EGLAttrib kDefaultStreamDescriptor = static_cast(kGgpPrimaryStreamDescriptor); -} // namespace - -WindowSurfaceVkGGP::WindowSurfaceVkGGP(const egl::SurfaceState &surfaceState, - EGLNativeWindowType window) - : WindowSurfaceVk(surfaceState, window) -{} - -angle::Result WindowSurfaceVkGGP::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) -{ - vk::Renderer *renderer = context->getRenderer(); - - // Get the stream descriptor if specified. Default is kGgpPrimaryStreamDescriptor. - EGLAttrib streamDescriptor = - mState.attributes.get(EGL_GGP_STREAM_DESCRIPTOR_ANGLE, kDefaultStreamDescriptor); - - VkStreamDescriptorSurfaceCreateInfoGGP createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP; - createInfo.streamDescriptor = static_cast(streamDescriptor); - - ANGLE_VK_TRY(context, vkCreateStreamDescriptorSurfaceGGP(renderer->getInstance(), &createInfo, - nullptr, &mSurface)); - - return getCurrentWindowSize(context, extentsOut); -} - -angle::Result WindowSurfaceVkGGP::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) -{ - vk::Renderer *renderer = context->getRenderer(); - const VkPhysicalDevice &physicalDevice = renderer->getPhysicalDevice(); - - ANGLE_VK_TRY(context, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, - &mSurfaceCaps)); - - *extentsOut = - gl::Extents(mSurfaceCaps.currentExtent.width, mSurfaceCaps.currentExtent.height, 1); - return angle::Result::Continue; -} - -egl::Error WindowSurfaceVkGGP::swapWithFrameToken(const gl::Context *context, - EGLFrameTokenANGLE frameToken) -{ - VkPresentFrameTokenGGP frameTokenData = {}; - frameTokenData.sType = VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP; - frameTokenData.frameToken = static_cast(frameToken); - - angle::Result result = swapImpl(context, nullptr, 0, &frameTokenData); - return angle::ToEGL(result, EGL_BAD_SURFACE); -} -} // namespace rx diff --git a/src/libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.h b/src/libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.h deleted file mode 100644 index 5bfe8651917..00000000000 --- a/src/libANGLE/renderer/vulkan/ggp/WindowSurfaceVkGGP.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2019 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. -// -// WindowSurfaceVkGGP.h: -// Google Game Platform implementation of WindowSurfaceVk. -// - -#ifndef LIBANGLE_RENDERER_VULKAN_GGP_WINDOWSURFACEVKGGP_H_ -#define LIBANGLE_RENDERER_VULKAN_GGP_WINDOWSURFACEVKGGP_H_ - -#include "libANGLE/renderer/vulkan/SurfaceVk.h" - -namespace rx -{ - -class WindowSurfaceVkGGP : public WindowSurfaceVk -{ - public: - WindowSurfaceVkGGP(const egl::SurfaceState &surfaceState, EGLNativeWindowType window); - - private: - egl::Error swapWithFrameToken(const gl::Context *context, - EGLFrameTokenANGLE frameToken) override; - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; -}; - -} // namespace rx - -#endif // LIBANGLE_RENDERER_VULKAN_GGP_WINDOWSURFACEVKGGP_H_ diff --git a/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.cpp b/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.cpp index 51f093c6cf8..a2d1e95c5b8 100644 --- a/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.cpp +++ b/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.cpp @@ -7,6 +7,10 @@ // Implements the class methods for DisplayVkLinux. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/vulkan/linux/DisplayVkLinux.h" #include "common/linux/dma_buf_utils.h" @@ -17,9 +21,7 @@ namespace rx { -DisplayVkLinux::DisplayVkLinux(const egl::DisplayState &state) - : DisplayVk(state), mDrmFormatsInitialized(false) -{} +DisplayVkLinux::DisplayVkLinux(const egl::DisplayState &state) : DisplayVk(state) {} DeviceImpl *DisplayVkLinux::createDevice() { @@ -45,7 +47,7 @@ ExternalImageSiblingImpl *DisplayVkLinux::createExternalImageSibling( } // Returns the list of DRM modifiers that a VkFormat supports -std::vector DisplayVkLinux::GetDrmModifiers( +std::vector DisplayVkLinux::getDrmModifiers( const DisplayVk *displayVk, VkFormat vkFormat) { @@ -74,7 +76,7 @@ std::vector DisplayVkLinux::GetDrmModifiers( } // Returns true if that VkFormat has at least on format modifier in its properties -bool DisplayVkLinux::SupportsDrmModifiers(VkPhysicalDevice device, VkFormat vkFormat) +bool DisplayVkLinux::supportsDrmModifiers(VkPhysicalDevice device, VkFormat vkFormat) { // Query list of drm format modifiers compatible with VkFormat. VkDrmFormatModifierPropertiesListEXT formatModifierPropertiesList = {}; @@ -92,17 +94,17 @@ bool DisplayVkLinux::SupportsDrmModifiers(VkPhysicalDevice device, VkFormat vkFo } // Returns a list of VkFormats supporting at least one DRM format modifier -std::vector DisplayVkLinux::GetVkFormatsWithDrmModifiers(const vk::Renderer *renderer) +std::vector DisplayVkLinux::getVkFormatsWithDrmModifiers(const vk::Renderer *renderer) { std::vector vkFormats; for (size_t formatIndex = 1; formatIndex < angle::kNumANGLEFormats; ++formatIndex) { const vk::Format &format = renderer->getFormat(angle::FormatID(formatIndex)); VkFormat vkFormat = - format.getActualImageVkFormat(renderer, rx::vk::ImageAccess::Renderable); + format.getActualImageVkFormat(renderer, rx::vk::ImageFormatSupport::Renderable); if (vkFormat != VK_FORMAT_UNDEFINED && - SupportsDrmModifiers(renderer->getPhysicalDevice(), vkFormat)) + supportsDrmModifiers(renderer->getPhysicalDevice(), vkFormat)) { vkFormats.push_back(vkFormat); } @@ -112,38 +114,37 @@ std::vector DisplayVkLinux::GetVkFormatsWithDrmModifiers(const vk::Ren } // Returns a list of supported DRM formats -std::vector DisplayVkLinux::GetDrmFormats(const vk::Renderer *renderer) +std::unordered_set DisplayVkLinux::getDrmFormats(const vk::Renderer *renderer) { std::unordered_set drmFormatsSet; - for (VkFormat vkFormat : GetVkFormatsWithDrmModifiers(renderer)) + for (VkFormat vkFormat : getVkFormatsWithDrmModifiers(renderer)) { std::vector drmFormats = angle::VkFormatToDrmFourCCFormat(vkFormat); - for (EGLint drmFormat : drmFormats) - { - drmFormatsSet.insert(drmFormat); - } + drmFormatsSet.insert(drmFormats.begin(), drmFormats.end()); } + // Ensure that default DRM_FORMAT_XRGB8888 is supported. + ASSERT(drmFormatsSet.count(DRM_FORMAT_XRGB8888) == 1); - std::vector drmFormats; - std::copy(std::begin(drmFormatsSet), std::end(drmFormatsSet), std::back_inserter(drmFormats)); - - return drmFormats; + return drmFormatsSet; } -bool DisplayVkLinux::supportsDmaBufFormat(EGLint format) const +bool DisplayVkLinux::supportsDmaBufFormat(EGLint format) { - return std::find(std::begin(mDrmFormats), std::end(mDrmFormats), format) != - std::end(mDrmFormats); + if (mDrmFormats.empty()) + { + mDrmFormats = getDrmFormats(getRenderer()); + } + + return (mDrmFormats.count(format) == 1); } egl::Error DisplayVkLinux::queryDmaBufFormats(EGLint maxFormats, EGLint *formats, EGLint *numFormats) { - if (!mDrmFormatsInitialized) + if (mDrmFormats.empty()) { - mDrmFormats = GetDrmFormats(getRenderer()); - mDrmFormatsInitialized = true; + mDrmFormats = getDrmFormats(getRenderer()); } EGLint formatsSize = static_cast(mDrmFormats.size()); @@ -152,7 +153,7 @@ egl::Error DisplayVkLinux::queryDmaBufFormats(EGLint maxFormats, { // Do not copy data beyond the limits of the vector maxFormats = std::min(maxFormats, formatsSize); - std::memcpy(formats, mDrmFormats.data(), maxFormats * sizeof(EGLint)); + std::copy_n(mDrmFormats.begin(), maxFormats, formats); } return egl::NoError(); @@ -177,7 +178,7 @@ egl::Error DisplayVkLinux::queryDmaBufModifiers(EGLint drmFormat, { VkFormat vkFmt = vkFormats[i]; - std::vector vkDrmMods = GetDrmModifiers(this, vkFmt); + std::vector vkDrmMods = getDrmModifiers(this, vkFmt); std::vector drmMods(vkDrmMods.size()); std::transform(std::begin(vkDrmMods), std::end(vkDrmMods), std::begin(drmMods), diff --git a/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.h b/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.h index 92512e074d8..b83a57a983c 100644 --- a/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.h +++ b/src/libANGLE/renderer/vulkan/linux/DisplayVkLinux.h @@ -27,12 +27,7 @@ class DisplayVkLinux : public DisplayVk EGLenum target, EGLClientBuffer buffer, const egl::AttributeMap &attribs) override; - std::vector GetDrmModifiers(const DisplayVk *displayVk, - VkFormat vkFormat); - bool SupportsDrmModifiers(VkPhysicalDevice device, VkFormat vkFormat); - std::vector GetVkFormatsWithDrmModifiers(const vk::Renderer *renderer); - std::vector GetDrmFormats(const vk::Renderer *renderer); - bool supportsDmaBufFormat(EGLint format) const override; + bool supportsDmaBufFormat(EGLint format) override; egl::Error queryDmaBufFormats(EGLint maxFormats, EGLint *formats, EGLint *numFormats) override; egl::Error queryDmaBufModifiers(EGLint format, EGLint maxModifiers, @@ -41,10 +36,14 @@ class DisplayVkLinux : public DisplayVk EGLint *numModifiers) override; private: - // Supported DRM formats - std::vector mDrmFormats; + std::vector getDrmModifiers(const DisplayVk *displayVk, + VkFormat vkFormat); + bool supportsDrmModifiers(VkPhysicalDevice device, VkFormat vkFormat); + std::vector getVkFormatsWithDrmModifiers(const vk::Renderer *renderer); + std::unordered_set getDrmFormats(const vk::Renderer *renderer); - bool mDrmFormatsInitialized; + // Supported DRM formats + std::unordered_set mDrmFormats; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp b/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp index cb49ac3c913..c5d78865745 100644 --- a/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp +++ b/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp @@ -6,9 +6,14 @@ // DmaBufImageSiblingVkLinux.cpp: Implements DmaBufImageSiblingVkLinux. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.h" #include "common/linux/dma_buf_utils.h" +#include "common/system_utils.h" #include "libANGLE/Display.h" #include "libANGLE/renderer/vulkan/DisplayVk.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" @@ -282,7 +287,8 @@ angle::Result GetAllocateInfo(const egl::AttributeMap &attribs, bool areFdsIdentical = true; for (uint32_t plane = 1; plane < planeCount; ++plane) { - if (attribs.getAsInt(kFds[plane]) != attribs.getAsInt(kFds[0])) + if (!angle::IsSameFileDescriptor(attribs.getAsInt(kFds[plane]), + attribs.getAsInt(kFds[0]))) { areFdsIdentical = false; break; @@ -551,11 +557,11 @@ angle::Result DmaBufImageSiblingVkLinux::initWithFormat(DisplayVk *displayVk, linearFilterSupported); } - ANGLE_TRY(mImage->initExternal(displayVk, gl::TextureType::_2D, vkExtents, intendedFormatID, - actualImageFormatID, 1, usageFlags, createFlags, - vk::ImageLayout::ExternalPreInitialized, imageCreateInfoPNext, - gl::LevelIndex(0), 1, 1, kIsRobustInitEnabled, - hasProtectedContent(), conversionDesc, nullptr)); + ANGLE_TRY(mImage->initExternal( + displayVk, gl::TextureType::_2D, vkExtents, intendedFormatID, actualImageFormatID, 1, + usageFlags, createFlags, vk::ImageAccess::ExternalPreInitialized, imageCreateInfoPNext, + gl::LevelIndex(0), 1, 1, kIsRobustInitEnabled, hasProtectedContent(), + vk::TileMemory::Prohibited, conversionDesc, nullptr)); VkMemoryRequirements externalMemoryRequirements; mImage->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements); @@ -578,8 +584,9 @@ angle::Result DmaBufImageSiblingVkLinux::initImpl(DisplayVk *displayVk) { vk::Renderer *renderer = displayVk->getRenderer(); - const vk::Format &vkFormat = renderer->getFormat(mFormat.info->sizedInternalFormat); - const angle::Format &format = vkFormat.getActualImageFormat(rx::vk::ImageAccess::SampleOnly); + const vk::Format &vkFormat = renderer->getFormat(mFormat.info->sizedInternalFormat); + const angle::Format &format = + vkFormat.getActualImageFormat(rx::vk::ImageFormatSupport::SampleOnly); InitResult initResult; diff --git a/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.cpp b/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.cpp index 16e1ae63cec..9ff2bb0dae4 100644 --- a/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.cpp +++ b/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.cpp @@ -20,8 +20,7 @@ WindowSurfaceVkSimple::WindowSurfaceVkSimple(const egl::SurfaceState &surfaceSta WindowSurfaceVkSimple::~WindowSurfaceVkSimple() {} -angle::Result WindowSurfaceVkSimple::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkSimple::createSurfaceVk(vk::ErrorContext *context) { vk::Renderer *renderer = context->getRenderer(); ASSERT(renderer != nullptr); @@ -63,20 +62,20 @@ angle::Result WindowSurfaceVkSimple::createSurfaceVk(vk::ErrorContext *context, ANGLE_VK_TRY(context, vkCreateDisplayPlaneSurfaceKHR(instance, &info, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkSimple::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { vk::Renderer *renderer = context->getRenderer(); const VkPhysicalDevice &physicalDevice = renderer->getPhysicalDevice(); - ANGLE_VK_TRY(context, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, - &mSurfaceCaps)); + VkSurfaceCapabilitiesKHR surfaceCaps; + ANGLE_VK_TRY(context, + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, &surfaceCaps)); - *extentsOut = - gl::Extents(mSurfaceCaps.currentExtent.width, mSurfaceCaps.currentExtent.height, 1); + *extentsOut = gl::Extents(surfaceCaps.currentExtent.width, surfaceCaps.currentExtent.height, 1); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.h b/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.h index 2a03b1ce5e9..473a876ac37 100644 --- a/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.h +++ b/src/libANGLE/renderer/vulkan/linux/display/WindowSurfaceVkSimple.h @@ -22,8 +22,9 @@ class WindowSurfaceVkSimple final : public WindowSurfaceVk ~WindowSurfaceVkSimple() final; private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/linux/gbm/DisplayVkGbm.cpp b/src/libANGLE/renderer/vulkan/linux/gbm/DisplayVkGbm.cpp index eaa5ad06f62..25a1f2da1f4 100644 --- a/src/libANGLE/renderer/vulkan/linux/gbm/DisplayVkGbm.cpp +++ b/src/libANGLE/renderer/vulkan/linux/gbm/DisplayVkGbm.cpp @@ -71,7 +71,20 @@ egl::ConfigSet DisplayVkGbm::generateConfigs() return cfgSet; } -void DisplayVkGbm::checkConfigSupport(egl::Config *config) {} +void DisplayVkGbm::checkConfigSupport(egl::Config *config) +{ + ASSERT(mGbmDevice); + uint32_t format = angle::GLInternalFormatToDrmFourCCFormat(config->renderTargetFormat); + uint32_t flags = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT; + + if (!gbm_device_is_format_supported(mGbmDevice, format, flags)) + { + config->surfaceType &= ~EGL_WINDOW_BIT; + return; + } + + config->nativeVisualID = format; +} const char *DisplayVkGbm::getWSIExtension() const { diff --git a/src/libANGLE/renderer/vulkan/linux/headless/DisplayVkHeadless.cpp b/src/libANGLE/renderer/vulkan/linux/headless/DisplayVkHeadless.cpp index c56977c6b5a..7aa46c7c667 100644 --- a/src/libANGLE/renderer/vulkan/linux/headless/DisplayVkHeadless.cpp +++ b/src/libANGLE/renderer/vulkan/linux/headless/DisplayVkHeadless.cpp @@ -38,8 +38,8 @@ SurfaceImpl *DisplayVkHeadless::createWindowSurfaceVk(const egl::SurfaceState &s egl::ConfigSet DisplayVkHeadless::generateConfigs() { std::vector kColorFormats; - std::vector kDesiredColorFormats = {GL_RGBA8, GL_BGRA8_EXT, GL_RGB565, GL_RGB8, - GL_RGB10_A2}; + std::vector kDesiredColorFormats = {GL_RGBA8, GL_BGRA8_EXT, GL_RGB565, + GL_RGB8, GL_RGB10_A2, GL_RGBA16F}; for (GLenum glFormat : kDesiredColorFormats) { diff --git a/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.cpp b/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.cpp index 7c9a155106f..ee69c1c1a07 100644 --- a/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.cpp +++ b/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.cpp @@ -20,8 +20,7 @@ WindowSurfaceVkHeadless::WindowSurfaceVkHeadless(const egl::SurfaceState &surfac WindowSurfaceVkHeadless::~WindowSurfaceVkHeadless() {} -angle::Result WindowSurfaceVkHeadless::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkHeadless::createSurfaceVk(vk::ErrorContext *context) { vk::Renderer *renderer = context->getRenderer(); ASSERT(renderer != nullptr); @@ -32,16 +31,12 @@ angle::Result WindowSurfaceVkHeadless::createSurfaceVk(vk::ErrorContext *context ANGLE_VK_TRY(context, vkCreateHeadlessSurfaceEXT(instance, &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkHeadless::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { - const VkPhysicalDevice &physicalDevice = context->getRenderer()->getPhysicalDevice(); - ANGLE_VK_TRY(context, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, - &mSurfaceCaps)); - // Spec: "For headless surfaces, currentExtent is the reserved value (0xFFFFFFFF, 0xFFFFFFFF). // Whatever the application sets a swapchain's imageExtent to will be the size of the surface, // after the first image is presented." @@ -50,12 +45,7 @@ angle::Result WindowSurfaceVkHeadless::getCurrentWindowSize(vk::ErrorContext *co angle::vk::SimpleDisplayWindow *simpleWindow = reinterpret_cast(mNativeWindowType); - // Update surface extent before output the new extent. - mSurfaceCaps.currentExtent.width = simpleWindow->width; - mSurfaceCaps.currentExtent.height = simpleWindow->height; - - *extentsOut = - gl::Extents(mSurfaceCaps.currentExtent.width, mSurfaceCaps.currentExtent.height, 1); + *extentsOut = gl::Extents(simpleWindow->width, simpleWindow->height, 1); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.h b/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.h index 081d3ec7e78..3247d8105db 100644 --- a/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.h +++ b/src/libANGLE/renderer/vulkan/linux/headless/WindowSurfaceVkHeadless.h @@ -22,8 +22,9 @@ class WindowSurfaceVkHeadless final : public WindowSurfaceVk ~WindowSurfaceVkHeadless() final; private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/linux/wayland/DisplayVkWayland.cpp b/src/libANGLE/renderer/vulkan/linux/wayland/DisplayVkWayland.cpp index 68cec5b4e15..a53475fe64f 100644 --- a/src/libANGLE/renderer/vulkan/linux/wayland/DisplayVkWayland.cpp +++ b/src/libANGLE/renderer/vulkan/linux/wayland/DisplayVkWayland.cpp @@ -7,6 +7,10 @@ // Implements the class methods for DisplayVkWayland. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/linux/wayland/DisplayVkWayland.h" #include diff --git a/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.cpp b/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.cpp index eb4b6b14130..58124fc0dd1 100644 --- a/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.cpp +++ b/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.cpp @@ -36,8 +36,7 @@ WindowSurfaceVkWayland::WindowSurfaceVkWayland(const egl::SurfaceState &surfaceS mExtents = gl::Extents(eglWindow->width, eglWindow->height, 1); } -angle::Result WindowSurfaceVkWayland::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkWayland::createSurfaceVk(vk::ErrorContext *context) { ANGLE_VK_CHECK(context, vkGetPhysicalDeviceWaylandPresentationSupportKHR( @@ -56,26 +55,14 @@ angle::Result WindowSurfaceVkWayland::createSurfaceVk(vk::ErrorContext *context, ANGLE_VK_TRY(context, vkCreateWaylandSurfaceKHR(context->getRenderer()->getInstance(), &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkWayland::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { *extentsOut = mExtents; return angle::Result::Continue; } -egl::Error WindowSurfaceVkWayland::getUserWidth(const egl::Display *display, EGLint *value) const -{ - *value = getWidth(); - return egl::NoError(); -} - -egl::Error WindowSurfaceVkWayland::getUserHeight(const egl::Display *display, EGLint *value) const -{ - *value = getHeight(); - return egl::NoError(); -} - } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.h b/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.h index b8a81adb5de..8a41862df7d 100644 --- a/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.h +++ b/src/libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.h @@ -29,15 +29,10 @@ class WindowSurfaceVkWayland : public WindowSurfaceVk EGLNativeWindowType window, wl_display *display); - // On Wayland, currentExtent is undefined (0xFFFFFFFF, 0xFFFFFFFF). - // Whatever the application sets a swapchain's imageExtent to will be the size of the window, - // after the first image is presented - egl::Error getUserWidth(const egl::Display *display, EGLint *value) const override; - egl::Error getUserHeight(const egl::Display *display, EGLint *value) const override; - private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; wl_display *mWaylandDisplay; gl::Extents mExtents; diff --git a/src/libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.cpp b/src/libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.cpp index 3ced7b97f6d..3abc1a41bb6 100644 --- a/src/libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.cpp +++ b/src/libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.cpp @@ -7,6 +7,10 @@ // Implements the class methods for DisplayVkXcb. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.h" #include diff --git a/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.cpp b/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.cpp index 303ba1273b6..52a6bc99202 100644 --- a/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.cpp +++ b/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.cpp @@ -20,8 +20,7 @@ WindowSurfaceVkXcb::WindowSurfaceVkXcb(const egl::SurfaceState &surfaceState, : WindowSurfaceVk(surfaceState, window), mXcbConnection(conn) {} -angle::Result WindowSurfaceVkXcb::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkXcb::createSurfaceVk(vk::ErrorContext *context) { VkXcbSurfaceCreateInfoKHR createInfo = {}; @@ -32,11 +31,11 @@ angle::Result WindowSurfaceVkXcb::createSurfaceVk(vk::ErrorContext *context, ANGLE_VK_TRY(context, vkCreateXcbSurfaceKHR(context->getRenderer()->getInstance(), &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkXcb::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { xcb_get_geometry_cookie_t cookie = xcb_get_geometry(mXcbConnection, static_cast(mNativeWindowType)); @@ -53,4 +52,22 @@ angle::Result WindowSurfaceVkXcb::getCurrentWindowSize(vk::ErrorContext *context return angle::Result::Continue; } +angle::Result WindowSurfaceVkXcb::getWindowVisibility(vk::ErrorContext *context, + bool *isVisibleOut) const +{ + xcb_get_window_attributes_cookie_t cookie = + xcb_get_window_attributes(mXcbConnection, static_cast(mNativeWindowType)); + xcb_generic_error_t *error = nullptr; + xcb_get_window_attributes_reply_t *reply = + xcb_get_window_attributes_reply(mXcbConnection, cookie, &error); + if (error) + { + free(reply); + ANGLE_VK_CHECK(context, false, VK_ERROR_INITIALIZATION_FAILED); + } + *isVisibleOut = (reply->map_state == XCB_MAP_STATE_VIEWABLE); + free(reply); + return angle::Result::Continue; +} + } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h b/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h index 725d21e9268..4165c6aa06b 100644 --- a/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h +++ b/src/libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h @@ -25,8 +25,10 @@ class WindowSurfaceVkXcb : public WindowSurfaceVk xcb_connection_t *conn); private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; + angle::Result getWindowVisibility(vk::ErrorContext *context, bool *isVisibleOut) const override; xcb_connection_t *mXcbConnection; }; diff --git a/src/libANGLE/renderer/vulkan/mac/IOSurfaceSurfaceVkMac.mm b/src/libANGLE/renderer/vulkan/mac/IOSurfaceSurfaceVkMac.mm index 71ffbd6238b..1a71338e46d 100644 --- a/src/libANGLE/renderer/vulkan/mac/IOSurfaceSurfaceVkMac.mm +++ b/src/libANGLE/renderer/vulkan/mac/IOSurfaceSurfaceVkMac.mm @@ -134,7 +134,7 @@ int FindIOSurfaceFormatIndex(GLenum internalFormat, GLenum type) ASSERT(context != nullptr); ContextVk *contextVk = vk::GetImpl(context); angle::Result result = - contextVk->flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::ContextChange); + contextVk->flushAndSubmitCommands(nullptr, nullptr, QueueSubmitReason::ContextChange); return angle::ToEGL(result, EGL_BAD_SURFACE); } @@ -185,7 +185,7 @@ int FindIOSurfaceFormatIndex(GLenum internalFormat, GLenum type) contextVk, gl::ImageIndex::Make2D(0), gl::Extents(static_cast(width), pixelUnpack.imageHeight, 1), gl::Offset(), internalFormatInfo, pixelUnpack, kIOSurfaceFormats[mFormatIndex].type, - reinterpret_cast(source), format, vk::ImageAccess::Renderable, + reinterpret_cast(source), format, vk::ImageFormatSupport::Renderable, vk::ApplyImageUpdate::Defer, &updateAppliedImmediately); IOSurfaceUnlock(mIOSurface, 0, nullptr); diff --git a/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h b/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h index bb3e4d592f0..0525b4105dc 100644 --- a/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h +++ b/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h @@ -24,8 +24,9 @@ class WindowSurfaceVkMac : public WindowSurfaceVk ~WindowSurfaceVkMac() override; private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; CAMetalLayer *mMetalLayer; id mMetalDevice; diff --git a/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.mm b/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.mm index 07e87533569..1f99df27767 100644 --- a/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.mm +++ b/src/libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.mm @@ -29,9 +29,7 @@ [mMetalLayer release]; } -angle::Result WindowSurfaceVkMac::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) - API_AVAILABLE(macosx(10.11)) +angle::Result WindowSurfaceVkMac::createSurfaceVk(vk::ErrorContext *context) { mMetalDevice = MTLCreateSystemDefaultDevice(); @@ -57,12 +55,11 @@ ANGLE_VK_TRY(context, vkCreateMetalSurfaceEXT(context->getRenderer()->getInstance(), &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkMac::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) - API_AVAILABLE(macosx(10.11)) + gl::Extents *extentsOut) const { ANGLE_VK_CHECK(context, (mMetalLayer != nullptr), VK_ERROR_INITIALIZATION_FAILED); diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000000.inc b/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000000.inc index 432e3b01433..23da7599ff4 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000000.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000000.inc @@ -10,76 +10,77 @@ #pragma once constexpr uint8_t kBlit3DSrc_frag_00000000[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4d,0x68,0x5d,0x65, - 0x10,0x86,0xbf,0x73,0xef,0xcd,0xbd,0x89,0x91,0x36,0xc6,0xb4,0x31,0xff,0xd1,0x1a, - 0x69,0x13,0x89,0x5d,0xa8,0x04,0x44,0x51,0xba,0xd0,0x45,0x69,0xfd,0x81,0x64,0x91, - 0x4d,0x84,0x6c,0xb2,0x50,0x09,0xda,0x4d,0x16,0x55,0x08,0xd2,0x4d,0x16,0xdd,0x64, - 0xe1,0xa2,0xfe,0xb4,0xd4,0x5a,0x53,0x45,0xeb,0xc2,0xd6,0x9d,0xf8,0x13,0xb4,0xa8, - 0x0d,0x4a,0xd4,0xa0,0x44,0x2d,0x06,0xac,0x4a,0x40,0x6b,0xb4,0x2d,0x01,0xe7,0x3d, - 0xe7,0x99,0x76,0xb8,0x17,0xe6,0x9e,0x33,0xef,0x3b,0xdf,0xbc,0x33,0xf3,0x7d,0xdf, - 0x29,0x97,0x76,0xd4,0x52,0xca,0xd2,0x0d,0xa9,0x31,0x0d,0x65,0x29,0xff,0xdd,0x94, - 0x4a,0x49,0xaf,0xcd,0xa9,0x9a,0x3f,0x1f,0xde,0xfb,0xc4,0xde,0xe1,0x67,0x9f,0x9b, - 0x1c,0xbe,0xfb,0x9e,0xdd,0xe2,0xb7,0xa4,0x72,0x1e,0x27,0x6e,0xab,0x79,0x15,0x7b, - 0xca,0x9e,0x7a,0x72,0xea,0x69,0xe1,0x6d,0x66,0x63,0x66,0x13,0x66,0x53,0x66,0xd3, - 0x66,0x33,0x66,0xb3,0x66,0x73,0x66,0xf3,0x66,0x2d,0x96,0x43,0x6b,0x6a,0xca,0x6f, - 0x6f,0x6d,0xb9,0x9e,0xf2,0xa5,0xf4,0x48,0x6a,0x48,0xdd,0x45,0x29,0x69,0x07,0x4f, - 0xc7,0x32,0xb0,0xc6,0x80,0x95,0xc0,0x5a,0x02,0x56,0x06,0xbb,0x25,0x60,0x15,0xb0, - 0xee,0x80,0x35,0x80,0xf5,0x07,0xac,0x0a,0x76,0x7b,0xc0,0x6a,0x60,0x3b,0x03,0xd6, - 0x08,0x76,0x67,0xc0,0x9a,0xc0,0x76,0xe7,0x7d,0x95,0xaf,0xd5,0xa7,0x1e,0x35,0x93, - 0x5e,0xfa,0x91,0x3f,0x81,0x9f,0xe1,0x4f,0xe1,0x7b,0xfc,0x34,0x7e,0x19,0x7f,0x06, - 0xbf,0x82,0x3f,0x8b,0xdf,0x80,0x3f,0x87,0x5f,0xc5,0x9f,0xc7,0xf7,0x19,0x9f,0xb0, - 0xe7,0x6d,0x41,0x5f,0xfe,0xad,0xc1,0x5f,0xa8,0xe3,0x17,0xe0,0x55,0xcf,0xcd,0xf6, - 0x5f,0xca,0xfd,0x72,0x5e,0x8f,0xde,0xb7,0xdb,0x5b,0x95,0xd9,0xb5,0x5b,0x7c,0x0d, - 0xed,0x12,0x7e,0x33,0x7e,0x25,0x8f,0xa9,0x58,0x8e,0xc4,0xb9,0x4a,0xe9,0x3e,0xfc, - 0x36,0xb0,0x6d,0xe6,0x77,0x92,0xcb,0xfd,0x2e,0xfc,0x94,0xf7,0x71,0xe3,0xb5,0x7d, - 0x70,0xeb,0xc4,0xaa,0x3c,0xbb,0x82,0x49,0xaf,0x87,0xfd,0xe8,0x46,0xaf,0x87,0x79, - 0x08,0x1b,0x42,0xaf,0x0f,0x3d,0xc5,0xf7,0xc3,0xd5,0x02,0x3f,0x80,0xbe,0xfb,0x83, - 0xf0,0x8a,0x1f,0x22,0xbe,0x2b,0xef,0xa3,0x94,0x86,0x89,0x93,0x7f,0x57,0xdd,0xba, - 0x11,0xce,0x8b,0xfb,0x7b,0xea,0xea,0xd8,0x47,0x1f,0xca,0xbb,0x1f,0xae,0x13,0x7f, - 0x94,0x33,0xe0,0x73,0x1b,0xe5,0x7e,0x95,0xc3,0xfa,0x71,0xe6,0xee,0xfc,0x44,0x1d, - 0x3f,0xc9,0x3e,0x38,0x3f,0x05,0xef,0xfe,0x74,0x5d,0xfc,0x01,0xee,0x93,0xf3,0x33, - 0x75,0xfc,0x41,0xf6,0xc6,0xf9,0xd9,0x3a,0xfe,0x90,0xd9,0x83,0x81,0x9f,0xab,0xe3, - 0x0f,0x9b,0xbd,0x10,0xf8,0x79,0x78,0x9d,0x9b,0x97,0x98,0x45,0x8c,0x3f,0x82,0xdf, - 0x61,0x93,0x39,0x1e,0xce,0x59,0xfc,0xf1,0xf9,0xca,0x67,0xf6,0x3a,0xef,0xc7,0xd1, - 0x90,0x7f,0x02,0xac,0xd3,0x56,0x9e,0x24,0xee,0x4d,0xb0,0x93,0xc4,0xc9,0x5f,0x00, - 0xeb,0x32,0xc5,0xb7,0xc8,0x71,0xaf,0xdd,0xb2,0x12,0x33,0x4c,0xd4,0xf2,0x9f,0x21, - 0xba,0x7b,0xf7,0x73,0xd6,0x3f,0xe4,0x3c,0x3f,0x66,0xa8,0xea,0xfb,0x08,0x2c,0x05, - 0xec,0x63,0x30,0xd5,0xfa,0xa8,0x61,0x3a,0x4b,0x9f,0x10,0x2b,0xee,0x21,0xc3,0x34, - 0xd7,0x4f,0x39,0xab,0x7d,0xe4,0x57,0xdc,0x22,0xf8,0x8b,0xac,0xfb,0x8c,0xb5,0x8b, - 0x61,0xdd,0xe7,0xac,0x1b,0x08,0xeb,0xce,0x81,0xcf,0xb2,0xee,0x0b,0xd6,0x9e,0x63, - 0x9d,0xce,0xf1,0x97,0xac,0x1b,0x64,0x9d,0xce,0xf0,0x57,0xe0,0x0b,0x16,0xa3,0xb3, - 0x7d,0x1e,0x4c,0x67,0xfb,0x5f,0x9b,0xc0,0x32,0xbd,0x5d,0xb1,0x78,0x71,0x4b,0x66, - 0xcb,0xcc,0x65,0x29,0xf4,0xfc,0x35,0x9a,0xfa,0x3d,0x6f,0xb1,0xc2,0xbe,0x01,0x7f, - 0xdc,0xbc,0xfc,0xdb,0x9a,0x15,0x98,0xc7,0x5d,0xb6,0x1c,0x9e,0x4b,0xcf,0x7f,0x2c, - 0x4a,0x71,0x3b,0xb3,0x22,0xa6,0x81,0x35,0x4b,0xa1,0x87,0x6f,0xe9,0x61,0x24,0xf4, - 0xf0,0x1d,0xb8,0xf7,0xf0,0x3d,0x98,0xf7,0xb0,0x1a,0x7a,0x10,0xb7,0x62,0xb6,0x8a, - 0xee,0x4a,0xe8,0xe1,0x07,0xb4,0xb3,0xd0,0xc3,0x8f,0xe0,0xde,0xc3,0x1d,0x59,0x81, - 0x79,0x9c,0x7a,0xf0,0x5c,0xab,0xa1,0x87,0x5d,0x59,0x11,0xb3,0xcc,0x9a,0x95,0xd0, - 0xc3,0x4f,0xf4,0xb0,0x27,0xf4,0xf0,0x33,0xb8,0xf7,0xf0,0x0b,0x98,0xf7,0xb0,0x16, - 0x7a,0x10,0x77,0xc1,0x6c,0x0d,0x5d,0xbd,0xef,0x47,0xf7,0x57,0xb4,0x77,0x65,0xd7, - 0xef,0x8a,0x6a,0xf4,0xd8,0xb5,0x50,0xe3,0x20,0x71,0xab,0xac,0xbb,0x40,0x8d,0xfa, - 0x36,0xbd,0x4c,0x8d,0x47,0xa8,0x51,0xf7,0xf3,0x15,0xf0,0x67,0x98,0xcd,0xab,0x60, - 0x3e,0xbf,0xd7,0xc8,0x19,0xef,0xc2,0x51,0xb0,0xe2,0x2e,0x54,0xf3,0x7b,0x7f,0x8c, - 0xd8,0xa3,0xe4,0x50,0x7e,0xdd,0xbf,0x37,0xb8,0xbf,0xf2,0x75,0x57,0x4f,0x71,0x4f, - 0x47,0x2d,0x97,0xee,0xe8,0xdb,0xc4,0x9c,0x0a,0xfd,0xbe,0x43,0xbe,0x63,0xe1,0xfb, - 0xe0,0xf7,0xe4,0x5d,0x7a,0x18,0x0f,0xf7,0xe4,0x34,0xb8,0xdf,0xaf,0xf7,0xc8,0x71, - 0x3a,0xd4,0xfc,0x3e,0x78,0xec,0xe3,0x0c,0x58,0xec,0xe3,0x2c,0xb1,0x67,0xe8,0x63, - 0xcc,0x62,0xf5,0x8d,0xf8,0x80,0x5a,0xcf,0x86,0x79,0xfe,0x46,0x2d,0xfb,0xc2,0x3c, - 0x2f,0x82,0x2f,0x5a,0x8c,0xfc,0xdf,0xc1,0xfa,0xc2,0x39,0xf8,0x03,0x7c,0x80,0x73, - 0xb0,0x1e,0xce,0x81,0xb8,0x3f,0xcd,0xd6,0xd9,0x5b,0xbd,0x3f,0x60,0x31,0x63,0xd4, - 0xa0,0x7d,0x77,0x6e,0x3d,0xe8,0xfc,0x85,0xce,0x78,0xd0,0xf9,0x1b,0xdc,0x75,0x36, - 0x82,0x8e,0xb8,0x4b,0x66,0x1b,0xe4,0xba,0x84,0xce,0x44,0xd0,0x71,0x6e,0x23,0xe8, - 0x5c,0x46,0x67,0x32,0xe8,0x5c,0x01,0x77,0x9d,0xcd,0xa0,0x23,0xee,0xaa,0xd9,0x26, - 0xb9,0xae,0xa2,0x33,0x15,0x74,0x9c,0xdb,0x0c,0x3a,0xda,0x94,0x8b,0x7c,0x13,0x5c, - 0x27,0xcb,0x0a,0xdc,0x75,0x2a,0xd9,0x75,0x1d,0x71,0x25,0x33,0x61,0xca,0xa5,0x77, - 0xe9,0x4c,0x07,0x1d,0xe7,0xf4,0x74,0x9d,0x1a,0x3a,0x07,0x82,0x4e,0x63,0x56,0xe0, - 0xae,0xd3,0x1c,0x74,0xc4,0x35,0x99,0x35,0x93,0xab,0x09,0x9d,0x99,0xa0,0xe3,0x5c, - 0x73,0xd0,0xd9,0x82,0xce,0xc1,0xa0,0xb3,0x35,0x2b,0x70,0xd7,0x69,0x0d,0x3a,0xe2, - 0x5a,0xcc,0x5a,0xc9,0xd5,0x82,0xce,0x6c,0xd0,0x71,0xae,0x35,0xe8,0x6c,0x43,0xe7, - 0x50,0xd0,0xd9,0x9e,0x15,0xb8,0xeb,0x74,0x04,0x1d,0x71,0xed,0x66,0x1d,0xe4,0x6a, - 0x47,0x67,0x2e,0xe8,0x38,0xd7,0x11,0x74,0xba,0xd1,0x39,0x1c,0x74,0x7a,0xb2,0x02, - 0x77,0x9d,0xfe,0xa0,0x23,0xae,0xd7,0xac,0x9f,0x5c,0xbd,0xe8,0xcc,0x07,0x1d,0xe7, - 0xf4,0xdc,0xb4,0x8d,0x1e,0x31,0xfb,0x1f,0xb7,0xf0,0x33,0x52,0xe8,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4b,0x68,0x9d,0x55, + 0x10,0xc7,0xcf,0x77,0xef,0xcd,0xbd,0xf1,0x96,0x36,0x0d,0xa6,0x31,0xe6,0x61,0x6a, + 0x6b,0x30,0xa6,0x12,0xbb,0xa8,0x12,0x10,0x45,0xe9,0x42,0x17,0xa5,0xf5,0x01,0xc9, + 0x22,0x9b,0x08,0xd9,0xdc,0x85,0x4a,0xd0,0x6e,0xb2,0xa8,0x42,0x90,0x6e,0xb2,0xe8, + 0x26,0x0b,0x17,0x3e,0x5a,0x6a,0x8d,0xa9,0xa2,0x75,0x61,0xeb,0x4e,0x7c,0x54,0x2d, + 0x3e,0x42,0x25,0x6a,0x50,0xa2,0x16,0x03,0xbe,0x08,0x68,0x09,0x36,0xa5,0x52,0xe7, + 0xff,0x7d,0xbf,0x69,0x87,0x1b,0x98,0x9c,0x6f,0xfe,0xff,0x39,0xf3,0x9f,0x39,0x67, + 0xce,0x2d,0x97,0x76,0xd6,0x52,0xca,0x52,0x3d,0xb5,0xa6,0xa1,0x2c,0xe5,0x7f,0xed, + 0xa9,0x94,0xf4,0xb9,0x29,0x55,0xf3,0xf5,0xa1,0x7d,0x8f,0xef,0x1b,0x7e,0xe6,0xd9, + 0xc9,0xe1,0x3d,0x77,0xef,0x16,0xbf,0x25,0x95,0xf3,0x38,0x71,0x6d,0xe6,0x55,0x6c, + 0x95,0x3d,0xf9,0x44,0xe3,0x29,0xe1,0x1d,0x66,0x63,0x66,0x13,0x66,0x0d,0xb3,0x29, + 0xb3,0x69,0xb3,0x19,0xb3,0x59,0xb3,0x39,0xb3,0xad,0x96,0x43,0x7b,0x6a,0xca,0x6f, + 0x5f,0x1d,0xb9,0x9e,0xf2,0xa5,0xf4,0x70,0x6a,0x49,0xbd,0x45,0x29,0x69,0x27,0xab, + 0x63,0x19,0x58,0x6b,0xc0,0x4a,0x60,0x5b,0x03,0x56,0x06,0xeb,0x0a,0x58,0x05,0xac, + 0x37,0x60,0x2d,0x60,0xdb,0x03,0x56,0x05,0xbb,0x2d,0x60,0x35,0xb0,0xc1,0x80,0xb5, + 0x82,0xdd,0x19,0xb0,0x1b,0xc0,0x76,0x07,0xac,0x0e,0xb6,0x27,0xef,0xb5,0x7c,0xad, + 0x66,0xf5,0xad,0x73,0xba,0x85,0x1e,0xe5,0x4f,0xe0,0x67,0xf8,0x0d,0x7c,0x8f,0x9f, + 0xc2,0x2f,0xe3,0x4f,0xe3,0x57,0xf0,0x67,0xf0,0x5b,0xf0,0x67,0xf1,0xab,0xf8,0x73, + 0xf8,0x7e,0xee,0x27,0x6c,0xdd,0x11,0xf4,0xe5,0xdf,0x1a,0xfc,0x85,0x26,0x7e,0x01, + 0x5e,0xf5,0xdc,0x68,0xff,0x4b,0xb9,0x5f,0xce,0xeb,0xd1,0x77,0xa7,0x7d,0x55,0x39, + 0xcf,0x9b,0x2c,0xbe,0x86,0x76,0x09,0x7f,0x13,0x7e,0x25,0x8f,0xa9,0x58,0x8e,0xc4, + 0xac,0xa5,0x74,0x2f,0x7e,0x07,0xd8,0x36,0xf3,0xbb,0xc9,0xe5,0x7e,0x0f,0x7e,0xca, + 0xfb,0xd8,0x7c,0xed,0x6e,0xdc,0xba,0x83,0x55,0x59,0x7b,0x82,0x49,0xb3,0x8f,0x7b, + 0xea,0x45,0xb3,0x8f,0x33,0x11,0xb6,0x0b,0xcd,0x7e,0x34,0x15,0xbf,0x1d,0xae,0x16, + 0xf8,0x01,0x6a,0x70,0x7f,0x88,0x79,0x50,0xfc,0x2e,0xe2,0x7b,0xf2,0x5e,0x4a,0x69, + 0x98,0x38,0xf9,0x77,0x35,0xed,0x1b,0x69,0xd2,0xdd,0xcb,0xbc,0xb8,0xbf,0x1f,0x5d, + 0xe5,0x3d,0x40,0x6c,0x37,0xfe,0x28,0x73,0xe0,0x67,0x37,0xca,0xbb,0x2b,0x87,0xfd, + 0xe3,0x9c,0xbd,0xf3,0x13,0x4d,0xfc,0x24,0x77,0xe1,0x7c,0x03,0xde,0xfd,0xa9,0xa6, + 0xf8,0x83,0xbc,0x33,0xe7,0xa7,0x9b,0xf8,0x43,0xdc,0x8f,0xf3,0x33,0x4d,0xfc,0x61, + 0xb3,0x07,0x02,0x3f,0xdb,0xc4,0x1f,0x31,0x7b,0x3e,0xf0,0x73,0xf0,0x9a,0x9d,0x17, + 0xb9,0x53,0xf9,0x37,0xdb,0x49,0x1c,0x0f,0xb3,0x15,0xff,0xf8,0x19,0xcb,0xcf,0xe8, + 0x35,0xbe,0x8f,0x93,0x53,0xfe,0x09,0xb0,0x6e,0xdb,0x39,0x4f,0xdc,0x1b,0x60,0xf3, + 0xc4,0xc9,0x5f,0x00,0xeb,0x31,0xc5,0x37,0xc9,0x71,0x8f,0xbd,0xac,0x12,0x67,0x96, + 0xa8,0xe5,0x92,0x21,0x7a,0x6f,0xf7,0x31,0xdf,0x1f,0x30,0xc3,0x8f,0x1a,0xaa,0xfa, + 0x3e,0x04,0x4b,0x01,0xfb,0x08,0x4c,0xb5,0x3e,0x62,0x98,0xee,0xf8,0x63,0x62,0xc5, + 0x3d,0x68,0x98,0xce,0xf1,0x13,0x66,0xb3,0x9f,0xfc,0x8a,0x3b,0x0b,0xfe,0x02,0xfb, + 0x3e,0x63,0xef,0xd9,0xb0,0xef,0x73,0xf6,0x0d,0x84,0x7d,0xe7,0xc0,0x67,0xd8,0xf7, + 0x05,0x7b,0xcf,0xb1,0x4f,0x73,0xfb,0x25,0xfb,0x86,0xd8,0xa7,0x99,0xfd,0x0a,0xfc, + 0xa4,0xc5,0x68,0x96,0xbf,0x06,0xd3,0x2c,0xff,0x6b,0x27,0xb0,0x44,0x6f,0x97,0x2d, + 0x5e,0xdc,0xa2,0xd9,0x12,0xe7,0xb2,0x18,0x7a,0x3e,0x8f,0xa6,0xfe,0x9e,0xb3,0x58, + 0x61,0xdf,0x80,0x3f,0x66,0x9e,0x6a,0xda,0x91,0x15,0x98,0xc7,0x6d,0x58,0x0e,0xcf, + 0xa5,0x75,0xdd,0xa2,0x14,0x77,0x7b,0x56,0xc4,0xb4,0xb0,0x67,0x31,0xf4,0xf0,0x2d, + 0x3d,0x8c,0x84,0x1e,0xbe,0x03,0xf7,0x1e,0xbe,0x07,0xf3,0x1e,0x56,0x42,0x0f,0xe2, + 0x96,0xcd,0x56,0xd0,0x5d,0x0e,0x3d,0xfc,0x80,0x76,0x16,0x7a,0xf8,0x11,0xdc,0x7b, + 0x18,0xc8,0x0a,0xcc,0xe3,0xd4,0x83,0xe7,0x5a,0x09,0x3d,0x0c,0x66,0x45,0xcc,0x12, + 0x7b,0x96,0x43,0x0f,0x3f,0xd1,0xc3,0xde,0xd0,0xc3,0xcf,0xe0,0xde,0xc3,0x2f,0x60, + 0xde,0xc3,0x6a,0xe8,0x41,0xdc,0x05,0xb3,0x55,0x74,0xf5,0x7d,0x00,0xdd,0x5f,0xd1, + 0x1e,0xcc,0xae,0xbf,0x15,0xd5,0xe8,0xb1,0xab,0xa1,0xc6,0x3b,0x88,0x5b,0x61,0xdf, + 0x05,0x6a,0xd4,0x6f,0xd1,0x4b,0xd4,0x38,0x49,0x8d,0x7a,0xbf,0x2f,0x83,0x3f,0xcd, + 0xd9,0xbc,0x02,0xe6,0xe7,0xf7,0x2a,0x39,0xe3,0x5b,0x38,0x0a,0x56,0xbc,0x85,0x6a, + 0xfe,0xce,0x8f,0x11,0x7b,0x94,0x1c,0xca,0xaf,0xf7,0xf7,0x3a,0xef,0x57,0xfe,0x7c, + 0x7e,0x16,0xc5,0x3b,0x1d,0xb5,0x5c,0x7a,0xa3,0x6f,0x11,0x73,0x32,0xf4,0xfb,0x36, + 0xf9,0x8e,0x85,0xdf,0x07,0x7f,0x27,0xef,0xd0,0xc3,0x78,0x78,0x27,0xa7,0xc0,0xfd, + 0x7d,0xbd,0x4b,0x8e,0x53,0xa1,0xe6,0xf7,0xc0,0x63,0x1f,0xa7,0xc1,0x62,0x1f,0x67, + 0x88,0x3d,0x4d,0x1f,0x63,0x16,0xab,0xdf,0x88,0xf7,0xa9,0xf5,0x4c,0x38,0xcf,0xdf, + 0xa8,0x65,0x7f,0x38,0xcf,0xdf,0xc1,0x3f,0xb5,0x18,0xf9,0x7f,0x80,0xf5,0x87,0x39, + 0xf8,0x13,0x7c,0x80,0x39,0x58,0x0b,0x73,0x20,0xee,0x2f,0xb3,0x35,0xee,0x56,0xdf, + 0xf7,0x5b,0xcc,0x18,0x35,0xe8,0xde,0x9d,0x5b,0x0b,0x3a,0x7f,0xa3,0x33,0x1e,0x74, + 0xfe,0x01,0x77,0x9d,0xf5,0xa0,0x23,0xee,0x62,0x3e,0x37,0x45,0xae,0x8b,0xe8,0x4c, + 0x04,0x1d,0xe7,0xd6,0x83,0xce,0x25,0x74,0x26,0x83,0xce,0x06,0xb8,0xeb,0x5c,0x09, + 0x3a,0x1b,0xf9,0x9a,0x72,0x4c,0xb9,0x2e,0xa3,0xd3,0x08,0x3a,0xce,0x5d,0x09,0x3a, + 0x57,0xd1,0x19,0x0a,0x3a,0xba,0xa8,0xab,0x41,0xa7,0x9c,0x5d,0xd7,0x11,0x97,0x99, + 0x09,0x53,0x2e,0x7d,0x4b,0x67,0x2a,0xe8,0x38,0xa7,0xd5,0x75,0xaa,0x59,0xa1,0x73, + 0x30,0xe8,0xd4,0xb2,0x02,0x77,0x9d,0x7a,0xd0,0x11,0xd7,0x6a,0x56,0x27,0x57,0x2b, + 0x3a,0xd3,0x41,0xc7,0xb9,0x7a,0xd0,0xd9,0x8c,0xce,0xa1,0xa0,0xb3,0x25,0x2b,0x70, + 0xd7,0x69,0x0f,0x3a,0xe2,0xda,0xcc,0xda,0xc9,0xd5,0x86,0xce,0x4c,0xd0,0x71,0xae, + 0x3d,0xe8,0x74,0xa0,0x73,0x38,0xe8,0x6c,0xcb,0x0a,0xdc,0x75,0xba,0x82,0x8e,0xb8, + 0x4e,0xb3,0x2e,0x72,0x75,0xa2,0x33,0x1b,0x74,0x9c,0xeb,0x0a,0x3a,0x3d,0xe8,0x1c, + 0x09,0x3a,0xbd,0x59,0x81,0xbb,0x4e,0x7f,0xd0,0x11,0xd7,0x67,0xd6,0x4f,0xae,0x3e, + 0x74,0xe6,0x82,0x8e,0x73,0x5a,0xff,0xb3,0x0b,0x1d,0x31,0xfb,0x1f,0x0b,0x1a,0xdd, + 0x4a,0xf0,0x0c,0x00,0x00 }; // Generated from: @@ -108,6 +109,7 @@ constexpr uint8_t kBlit3DSrc_frag_00000000[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000001.inc b/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000001.inc index cab679add79..a5ce7b93d6e 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000001.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000001.inc @@ -10,77 +10,77 @@ #pragma once constexpr uint8_t kBlit3DSrc_frag_00000001[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4b,0x68,0x5d,0x65, - 0x10,0xc7,0xbf,0xef,0x9c,0xfb,0x48,0x93,0x8b,0x4d,0x88,0xa6,0x31,0xde,0xbc,0xda, - 0x12,0xb5,0x09,0xb5,0x0b,0x15,0x83,0x28,0x0a,0x05,0x5d,0x14,0x5a,0x15,0x4c,0x17, - 0xd9,0x5c,0xb0,0x0b,0x03,0x2a,0x44,0xe9,0x26,0x8b,0x0a,0x46,0xe8,0x26,0x8b,0x6e, - 0xb2,0x70,0x51,0x1f,0x2d,0xb5,0xb6,0xa9,0xa2,0x75,0x61,0xeb,0x4e,0xd4,0x16,0x2d, - 0x3e,0x82,0x12,0x6d,0x50,0xa2,0x06,0x03,0xbe,0x08,0xd8,0x12,0xad,0x35,0x38,0xf3, - 0x9d,0xdf,0xb4,0xe3,0x0d,0x4c,0xce,0x9d,0xff,0x7f,0xbe,0xf9,0xcf,0x7c,0x67,0xe6, - 0xe4,0xd9,0x96,0x6a,0x08,0x31,0xb4,0x86,0x96,0x30,0x12,0x43,0xfa,0xeb,0x08,0x59, - 0xd0,0x9f,0x6d,0xa1,0x92,0x9e,0x0f,0xed,0x7a,0x6c,0xd7,0xf6,0x67,0x9f,0x7b,0x62, - 0xfb,0x9d,0x77,0xed,0x50,0xfe,0x86,0x90,0xa7,0x38,0xe5,0x36,0x8a,0x57,0x92,0xa7, - 0xda,0x53,0x8d,0x27,0x9f,0x56,0xbc,0x4b,0x6c,0xaf,0x58,0x43,0x6c,0x42,0x6c,0x52, - 0x6c,0x4a,0x6c,0x5a,0x6c,0x46,0x6c,0x56,0xac,0x5d,0x72,0xe8,0x99,0xaa,0xe6,0x97, - 0x5f,0x5d,0x49,0x4f,0xf3,0x85,0xf0,0x70,0x28,0x87,0xde,0xa2,0x94,0xb0,0x85,0xa7, - 0x61,0x11,0xac,0xc5,0x61,0x19,0x58,0xbb,0xc3,0x72,0xb0,0x6e,0x87,0x95,0xc0,0xea, - 0x0e,0x2b,0x83,0x0d,0x38,0xac,0x02,0xb6,0xd5,0x61,0x55,0xb0,0xdb,0x1c,0xd6,0x02, - 0x36,0xe2,0xb0,0x0d,0x60,0x3b,0x52,0x5f,0xf9,0xb5,0xfa,0xb4,0x47,0xbd,0x93,0x3e, - 0xfa,0x51,0xbf,0x81,0x1f,0xf1,0x27,0xf0,0x2d,0x7e,0x12,0x3f,0xc7,0x9f,0xc2,0x2f, - 0xe1,0x4f,0xe3,0x97,0xf1,0x67,0xf0,0x2b,0xf8,0xb3,0xf8,0x76,0xc7,0xc7,0xe5,0xb9, - 0xd9,0xe9,0xab,0x3f,0xe8,0xfc,0xb9,0x26,0x7e,0x0e,0x5e,0xeb,0xe9,0x94,0xff,0x59, - 0xf2,0xf3,0x54,0x4f,0x96,0xde,0x73,0x9e,0xb4,0xf4,0xee,0x36,0x49,0x7c,0x15,0x6d, - 0xe5,0x6e,0x12,0xbf,0x0d,0x2e,0xc2,0xd7,0x78,0xc7,0x25,0xfc,0x1b,0x89,0x2f,0xa5, - 0xb8,0x92,0x9c,0x29,0x62,0x15,0xbf,0x17,0xbf,0x0b,0x4c,0xf3,0xd5,0xc9,0x17,0x52, - 0x5f,0xb5,0x6b,0xef,0xc5,0xac,0x0d,0xab,0xf0,0xac,0x3b,0xd3,0xfc,0x7d,0xbc,0x9f, - 0x5e,0xf2,0xab,0xdf,0x0f,0x36,0xdc,0x54,0xaf,0xc6,0x0f,0xc2,0x55,0x1d,0x3f,0x84, - 0xbe,0xf9,0xc3,0xf0,0x1a,0x3f,0x42,0x7c,0x3d,0xf5,0x90,0x85,0x3b,0x88,0xab,0x33, - 0x0f,0xfe,0xdc,0x28,0xf3,0x63,0xfe,0xce,0xa6,0x3a,0x76,0xd3,0x87,0xe6,0xdd,0x03, - 0xd7,0x86,0x3f,0xc6,0x4c,0xd4,0xe8,0x63,0x8c,0x7d,0xcb,0xdd,0xf9,0x71,0xde,0x83, - 0xf1,0x8d,0x26,0x7e,0x1f,0xf7,0x6e,0xfc,0x04,0xbc,0xf9,0x93,0x4d,0xf1,0xfb,0xd9, - 0x2f,0xe3,0xa7,0x9a,0xf8,0x03,0xdc,0x9d,0xf1,0xd3,0x4d,0xfc,0x41,0xb1,0x07,0x1c, - 0x3f,0xd3,0xc4,0x1f,0x12,0x7b,0xde,0xf1,0xb3,0xf0,0x3a,0x27,0x2f,0x71,0x17,0x3e, - 0xfe,0x30,0xfe,0xcd,0x72,0x33,0xc7,0xb8,0x9b,0x2c,0xfc,0xff,0x8f,0xcf,0x59,0xba, - 0xb3,0xd7,0xf9,0x7d,0x0c,0x0d,0xf5,0x8f,0x83,0xf5,0xc8,0xc9,0x13,0xc4,0x9d,0x04, - 0x3b,0x41,0x9c,0xfa,0x73,0x60,0xb7,0x88,0xe2,0x9b,0xe4,0xb8,0x5b,0xb6,0x2e,0xe3, - 0x0e,0x03,0xb5,0xfc,0x25,0x88,0xee,0xe2,0x7d,0xcc,0xf6,0x07,0xcc,0xef,0x23,0x82, - 0x6a,0xfd,0x1f,0x82,0x05,0x87,0x7d,0x04,0xa6,0xb5,0xee,0x11,0x4c,0x67,0xe9,0x63, - 0x62,0x95,0x7b,0x50,0x30,0x9d,0xc3,0x73,0xcc,0xea,0x00,0xf9,0x35,0xee,0x3c,0xf8, - 0x8b,0x9c,0xfb,0x84,0xb3,0xe7,0xdd,0xb9,0x4f,0x39,0x37,0xe4,0xce,0x5d,0x00,0x7f, - 0x81,0x73,0x9f,0x71,0xf6,0x02,0xe7,0x74,0x8e,0x3f,0xe7,0xdc,0x30,0xe7,0x74,0x86, - 0xbf,0x00,0x3f,0x29,0x31,0x3a,0xdb,0x5f,0x82,0xe9,0x6c,0xaf,0xc9,0x0d,0x2c,0xd0, - 0xdb,0x15,0x89,0x57,0x6e,0x5e,0x6c,0x81,0x7b,0x99,0x77,0x3d,0x7f,0x85,0x66,0x48, - 0x73,0x53,0x4a,0xd8,0xd7,0xe0,0x8f,0x8a,0xa7,0x35,0x6d,0x8d,0x05,0x66,0x71,0x7f, - 0x4b,0x0e,0xcb,0xa5,0xcf,0xcb,0x12,0xa5,0x71,0xb7,0xc7,0x22,0xa6,0xcc,0x99,0x79, - 0xd7,0xc3,0x37,0xf4,0x30,0xea,0x7a,0xf8,0x16,0xdc,0x7a,0xb8,0x08,0x66,0x3d,0x2c, - 0xb9,0x1e,0x94,0x5b,0x14,0x5b,0x42,0x77,0xd1,0xf5,0xf0,0x1d,0xda,0xd1,0xf5,0xf0, - 0x3d,0xb8,0xf5,0x70,0x6b,0x2c,0x30,0x8b,0xd3,0x1e,0x2c,0xd7,0x92,0xeb,0x61,0x5b, - 0x2c,0x62,0x16,0x38,0xb3,0xe8,0x7a,0xf8,0x81,0x1e,0x76,0xba,0x1e,0x7e,0x04,0xb7, - 0x1e,0x7e,0x02,0xb3,0x1e,0x56,0x5c,0x0f,0xca,0x2d,0x8b,0xad,0xa0,0xbb,0x9c,0xbe, - 0x2d,0x85,0xee,0xcf,0x68,0x6f,0x8b,0xd7,0x77,0x45,0x6b,0xb4,0xd8,0x15,0x57,0xe3, - 0x30,0x71,0x4b,0x9c,0x5b,0xa6,0x46,0xfd,0x36,0xbd,0x4c,0x8d,0x87,0xa9,0x51,0x77, - 0xf1,0x15,0xf0,0x67,0xb8,0x9b,0x57,0xc1,0xec,0xfe,0x5e,0x23,0xa7,0xdf,0x85,0x23, - 0x60,0xc5,0x2e,0x54,0xd2,0xde,0x1f,0x25,0xf6,0x08,0x39,0x34,0xbf,0xee,0xdf,0x1b, - 0xec,0xaf,0xfa,0xba,0xab,0xa7,0xd8,0xd3,0xc7,0x25,0x97,0xee,0xe8,0x5b,0xc4,0x9c, - 0x72,0xfd,0xbe,0x4d,0xbe,0xa3,0xee,0xfb,0x60,0x7b,0xf2,0x0e,0x3d,0x8c,0xbb,0x3d, - 0x39,0x0d,0x6e,0xfb,0xf5,0x2e,0x39,0x4e,0xbb,0x9a,0xdf,0x03,0xf7,0x7d,0x9c,0x01, - 0xf3,0x7d,0x9c,0x25,0xf6,0x0c,0x7d,0x8c,0x49,0xac,0x7e,0xbf,0xdf,0xa7,0xd6,0xb3, - 0xee,0x3e,0x7f,0xa1,0x96,0xdd,0xee,0x3e,0x7f,0x05,0x3f,0x27,0x31,0xea,0xff,0x06, - 0x36,0xe0,0xe6,0xe0,0x77,0xf0,0x21,0xe6,0x60,0xd5,0xcd,0x81,0x72,0x7f,0x88,0xad, - 0xf2,0x6e,0xf5,0xf7,0xfd,0x12,0xb3,0x97,0x1a,0xf4,0xbd,0x1b,0xb7,0xea,0x74,0xfe, - 0x44,0x67,0xdc,0xe9,0x5c,0x02,0x37,0x9d,0x35,0xa7,0x73,0x29,0xcd,0x4c,0x48,0x98, - 0xe6,0xba,0x8c,0x4e,0xc3,0xe9,0x18,0xb7,0xe6,0x74,0xae,0xa0,0xb3,0xcf,0xe9,0xfc, - 0x03,0x6e,0x3a,0xeb,0x4e,0x47,0xb9,0xab,0x62,0xeb,0xe4,0xba,0x8a,0xce,0x84,0xd3, - 0x31,0x6e,0xdd,0xe9,0xc4,0x58,0xe8,0x8c,0x3a,0x9d,0x2c,0x16,0xb8,0xe9,0x94,0xe3, - 0x75,0x1d,0xe5,0x72,0x31,0xc5,0x34,0x97,0xfe,0x56,0x9d,0x49,0xa7,0x63,0x9c,0x3e, - 0x4d,0xa7,0x05,0x9d,0xfd,0x4e,0x67,0x43,0x2c,0x70,0xd3,0xa9,0x39,0x1d,0xe5,0x5a, - 0xc5,0x6a,0xe4,0x6a,0x45,0x67,0xca,0xe9,0x18,0x57,0x73,0x3a,0x1b,0xd1,0x39,0xe0, - 0x74,0xda,0x63,0x81,0x9b,0x4e,0xa7,0xd3,0x51,0xae,0x43,0xac,0x93,0x5c,0x1d,0xe8, - 0x4c,0x3b,0x1d,0xe3,0x3a,0x9d,0x4e,0x17,0x3a,0x07,0x9d,0xce,0xa6,0x58,0xe0,0xa6, - 0xd3,0xe3,0x74,0x94,0xeb,0x16,0xeb,0x21,0x57,0x37,0x3a,0x33,0x4e,0xc7,0xb8,0x1e, - 0xa7,0xd3,0x8b,0xce,0x21,0xa7,0xd3,0x17,0x0b,0xdc,0x74,0x06,0x9d,0x8e,0x72,0xfd, - 0x62,0x83,0xe4,0xea,0x47,0x67,0xd6,0xe9,0x18,0xa7,0xcf,0x7f,0x65,0x2b,0xef,0x11, - 0xfb,0x0f,0x22,0xd8,0x03,0x22,0xf8,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4d,0x6c,0x94,0x65, + 0x10,0xc7,0x9f,0xe7,0xdd,0xed,0x6e,0xcb,0x22,0xd4,0x0a,0xad,0xd5,0x6d,0x5d,0xc0, + 0x34,0x60,0x09,0x72,0x40,0x23,0x31,0x1a,0x4d,0x48,0xe4,0x40,0x02,0x68,0x62,0x39, + 0xf4,0xb2,0x09,0x3d,0xd0,0x44,0x4d,0xaa,0xe1,0xd2,0x03,0x26,0x94,0x84,0x4b,0x0f, + 0x5c,0x7a,0xf0,0xe0,0x07,0x04,0x11,0x8b,0x46,0xf1,0x20,0x78,0x33,0xa2,0x8d,0x10, + 0x3e,0x1a,0x4d,0xd5,0x46,0x52,0xb4,0xa1,0x09,0xa0,0x69,0xa2,0x58,0x05,0xd2,0xc4, + 0x99,0xe7,0xfd,0x0d,0x0c,0xbb,0xc9,0xec,0xfb,0xce,0xff,0x3f,0x33,0xff,0x99,0xe7, + 0xe3,0x2d,0x64,0x6b,0xca,0x21,0xc4,0xb0,0x24,0x34,0x87,0xde,0x18,0xd2,0xef,0xc1, + 0x90,0x05,0x7d,0xad,0x84,0x52,0x7a,0xbe,0xb4,0xed,0x95,0x6d,0x1b,0xde,0x7c,0x6b, + 0xf7,0x86,0x4d,0x4f,0x6d,0x54,0x7e,0x59,0x28,0xa4,0x38,0xe5,0x96,0x8b,0x57,0x94, + 0xa7,0xda,0x6b,0xf5,0x3d,0xaf,0x2b,0xde,0x2e,0xb6,0x4b,0xac,0x2e,0x36,0x28,0x36, + 0x24,0x36,0x2c,0x36,0x22,0x36,0x2a,0x36,0x26,0xd6,0x2a,0x35,0x34,0xa7,0xac,0xf5, + 0xe5,0xad,0x3d,0xe9,0x69,0xbd,0x10,0xb6,0x86,0xa6,0xd0,0x95,0xb7,0x12,0xd6,0xf0, + 0x34,0x2c,0x82,0x35,0x3b,0x2c,0x03,0x6b,0x75,0x58,0x01,0xec,0x61,0x87,0x15,0xc1, + 0xaa,0x0e,0x6b,0x02,0xab,0x39,0xac,0x04,0xf6,0xb8,0xc3,0xca,0x60,0x6b,0x1d,0xd6, + 0x0c,0xb6,0xde,0x61,0x2d,0x60,0x1b,0x1d,0xb6,0x04,0x6c,0x53,0x9a,0xb5,0x70,0xb7, + 0x67,0x9d,0x5b,0xd7,0xa9,0x9b,0x19,0xd5,0xaf,0xe3,0x47,0xfc,0x41,0x7c,0x8b,0x1f, + 0xc2,0x2f,0xe0,0x0f,0xe3,0x17,0xf1,0x47,0xf0,0x9b,0xf0,0x47,0xf1,0x4b,0xf8,0x63, + 0xf8,0xb6,0xee,0xc7,0xe4,0xb9,0xda,0xe9,0xab,0xbf,0xca,0xf9,0xe3,0x0d,0xfc,0x38, + 0xbc,0xf6,0xf3,0x90,0xfc,0x67,0xc9,0x2f,0xa4,0x7e,0xb2,0xb4,0xf7,0x85,0xa4,0xa5, + 0xeb,0xd9,0x21,0xf1,0x65,0xb4,0x95,0x5b,0x29,0x7e,0x05,0x2e,0xc2,0x2f,0x65,0xdf, + 0x8b,0xf8,0x2b,0x88,0x2f,0xa6,0xb8,0xa2,0xe4,0xe4,0xb1,0x8a,0x3f,0x8b,0xdf,0x0e, + 0xa6,0xf5,0xaa,0xd4,0x0b,0x69,0xae,0x07,0xee,0xee,0x95,0x59,0xc5,0x59,0x89,0x67, + 0xd5,0x99,0x6a,0x74,0xb3,0x6f,0x5d,0x68,0xa8,0xff,0x18,0x58,0x6f,0x43,0xcf,0x1a, + 0xbf,0x0a,0xae,0xec,0xf8,0x1e,0x7a,0x30,0xbf,0x97,0xf3,0xa1,0xf1,0xeb,0x89,0xaf, + 0xa6,0x39,0xb2,0xf0,0x24,0x71,0x55,0xce,0x89,0xcf,0xdb,0xdc,0xa0,0xbb,0x85,0xf3, + 0x63,0xfe,0x76,0x74,0xb5,0xee,0x0e,0x62,0x2b,0xf8,0x7d,0x9c,0x8b,0xa5,0xcc,0xd1, + 0xc7,0x3d,0x2c,0xb8,0xfc,0x7e,0xf6,0xc2,0xf8,0x7a,0x03,0x3f,0xc0,0xda,0x1b,0x3f, + 0x08,0x6f,0xfe,0x50,0x43,0xfc,0x5e,0xee,0x9d,0xf1,0xc3,0x0d,0xfc,0x3e,0xd6,0xce, + 0xf8,0x91,0x06,0xfe,0xa0,0xd8,0x0b,0x8e,0x1f,0x6d,0xe0,0x0f,0x89,0xbd,0xed,0xf8, + 0x31,0x78,0x3d,0x2b,0xef,0xb0,0xa7,0xea,0x77,0xca,0x4a,0x1c,0x65,0x2d,0xb2,0x70, + 0xff,0x8f,0xcf,0x5a,0x5a,0xa3,0x0f,0x79,0x3f,0x4a,0x4d,0xf5,0x8f,0x81,0x3d,0x22, + 0x99,0xc7,0x89,0xfb,0x18,0xec,0x38,0x71,0xea,0x8f,0x83,0x3d,0x2a,0x8a,0x9f,0x50, + 0xe3,0x69,0xb9,0x69,0x19,0x6b,0x16,0xe8,0xe5,0x3f,0x41,0xf4,0xfe,0x3d,0xc7,0x79, + 0xfe,0x9a,0x33,0xbb,0x53,0x50,0xed,0xf7,0x1b,0xb0,0xe0,0xb0,0x33,0x60,0xda,0xeb, + 0x0e,0xc1,0x74,0x8f,0xbf,0x25,0x56,0xb9,0x17,0x05,0xd3,0x73,0xf7,0x1d,0x67,0xb3, + 0x46,0x7d,0x8d,0x9b,0x00,0x3f,0x40,0xde,0xf7,0xe4,0x4e,0xb8,0xbc,0xb3,0xe4,0xf5, + 0xb8,0xbc,0x73,0xe0,0xfb,0xc9,0x3b,0x4f,0xee,0x39,0xf2,0xf4,0xdc,0x5e,0x20,0xaf, + 0x97,0x3c,0x3d,0xb3,0x17,0xc1,0xc7,0x25,0x46,0xcf,0xf2,0x25,0x30,0x3d,0xcb,0xff, + 0xca,0x0a,0x4c,0x31,0xdb,0x6d,0x89,0x57,0x6e,0x52,0x6c,0x8a,0x75,0x99,0x74,0x33, + 0xff,0x80,0x66,0x48,0xe7,0xa4,0x98,0xb0,0x1f,0xc1,0x5f,0x16,0x2f,0x7d,0x73,0x63, + 0x8e,0x59,0xdc,0x2d,0xa9,0x61,0xb5,0xf4,0xf9,0x8f,0x44,0x69,0xdc,0xda,0x98,0xc7, + 0x34,0x91,0x33,0xe9,0x66,0xf8,0x89,0x19,0x36,0xbb,0x19,0x7e,0x06,0xb7,0x19,0x7e, + 0x01,0xb3,0x19,0x66,0xdc,0x0c,0xca,0x4d,0x8b,0xcd,0xa0,0x3b,0xed,0x66,0xf8,0x15, + 0xed,0xe8,0x66,0xb8,0x0c,0x6e,0x33,0xf4,0xc4,0x1c,0xb3,0x38,0x9d,0xc1,0x6a,0xcd, + 0xb8,0x19,0xd6,0xc5,0x3c,0x66,0x8a,0x9c,0x69,0x37,0xc3,0x15,0x66,0xd8,0xe2,0x66, + 0xf8,0x0d,0xdc,0x66,0xf8,0x1d,0xcc,0x66,0x98,0x73,0x33,0x28,0x37,0x2b,0x36,0x87, + 0xee,0x6c,0xfa,0x96,0xe4,0xba,0x57,0xd1,0x5e,0x17,0xef,0xdd,0x15,0xed,0xd1,0x62, + 0xe7,0x5c,0x8f,0x4f,0x10,0x37,0x43,0xde,0x2c,0x3d,0xea,0xb7,0xe8,0x5d,0x7a,0x1c, + 0xa0,0x47,0xbd,0x8b,0xef,0x81,0xbf,0xc1,0xda,0xbc,0x0f,0x66,0xeb,0xf7,0x01,0x35, + 0xfd,0x5d,0x38,0x0c,0x96,0xdf,0x85,0x52,0xba,0xe7,0x47,0x88,0x3d,0x4c,0x0d,0xad, + 0xaf,0xf7,0xef,0x23,0xee,0xaf,0xfa,0x7a,0x57,0x4f,0x70,0x4f,0x5f,0x95,0x5a,0x7a, + 0x47,0x3f,0x25,0xe6,0x84,0x9b,0xf7,0x33,0xea,0x1d,0x71,0xdf,0x07,0xbb,0x27,0x9f, + 0x33,0x43,0xbf,0xbb,0x27,0x27,0xc1,0xed,0x7e,0x7d,0x41,0x8d,0x93,0xae,0xe7,0x2f, + 0xc1,0xfd,0x1c,0xa7,0xc0,0xfc,0x1c,0xa7,0x89,0x3d,0xc5,0x1c,0x7d,0x12,0xab,0xdf, + 0xeb,0xaf,0xe8,0xf5,0xb4,0x5b,0xcf,0x6b,0xf4,0xb2,0xdd,0xad,0xe7,0x75,0xf0,0x09, + 0x89,0x51,0xff,0x06,0x58,0xcd,0x9d,0x83,0x3f,0xc0,0x7b,0x38,0x07,0xf3,0xee,0x1c, + 0x28,0xf7,0xa7,0xd8,0x3c,0x7b,0xab,0xef,0xcf,0x4b,0xcc,0x2e,0x7a,0xd0,0x7d,0x37, + 0x6e,0xde,0xe9,0xfc,0x85,0x4e,0xbf,0xd3,0xf9,0x1b,0xdc,0x74,0x16,0x9c,0x8e,0x72, + 0x37,0xc5,0x16,0xa8,0x75,0x13,0x9d,0xba,0xd3,0x31,0x6e,0xc1,0xe9,0xdc,0x42,0x67, + 0xc0,0xe9,0xdc,0x06,0x37,0x9d,0x45,0xa7,0xa3,0xdc,0x1d,0xb1,0x45,0x6a,0xdd,0x41, + 0x67,0xd0,0xe9,0x18,0xb7,0xe8,0x74,0x74,0x53,0xae,0xf3,0x5d,0x33,0x9d,0x18,0x73, + 0xdc,0x74,0x8a,0xf1,0x9e,0x8e,0x72,0x99,0x98,0x62,0x5a,0x4b,0xdf,0x55,0x67,0xc8, + 0xe9,0x18,0xa7,0x4f,0xd3,0x29,0xa3,0xb3,0xd7,0xe9,0x34,0xc7,0x1c,0x37,0x9d,0x8a, + 0xd3,0x51,0xae,0x45,0xac,0x42,0xad,0x16,0x74,0x86,0x9d,0x8e,0x71,0x15,0xa7,0xb3, + 0x0c,0x9d,0x7d,0x4e,0x67,0x79,0xcc,0x71,0xd3,0x69,0x73,0x3a,0xca,0xb5,0x8a,0xb5, + 0x51,0xab,0x15,0x9d,0x11,0xa7,0x63,0x5c,0x9b,0xd3,0x59,0x89,0xce,0x41,0xa7,0xd3, + 0x1e,0x73,0xdc,0x74,0x3a,0x9d,0x8e,0x72,0x1d,0x62,0x9d,0xd4,0xea,0x40,0x67,0xd4, + 0xe9,0x18,0xd7,0xe9,0x74,0xaa,0xe8,0x1c,0x72,0x3a,0x5d,0x31,0xc7,0x4d,0xa7,0xe6, + 0x74,0x94,0xeb,0x16,0xab,0x51,0xab,0x1b,0x9d,0x31,0xa7,0x63,0x9c,0x3e,0x17,0x65, + 0xa3,0x9f,0x11,0xfb,0x1f,0x90,0x8a,0xcf,0x21,0x00,0x0d,0x00,0x00 }; // Generated from: @@ -109,6 +109,7 @@ constexpr uint8_t kBlit3DSrc_frag_00000001[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000002.inc b/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000002.inc index 31b587831ab..38ef96aa1a2 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000002.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/Blit3DSrc.frag.00000002.inc @@ -10,77 +10,77 @@ #pragma once constexpr uint8_t kBlit3DSrc_frag_00000002[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4b,0x68,0x5d,0x65, - 0x10,0xc7,0xbf,0xef,0x9c,0xfb,0x48,0x73,0x2f,0x36,0x21,0x9a,0xc6,0x98,0x67,0x5b, - 0xa2,0x36,0xa1,0x76,0xa1,0x62,0x10,0x45,0xa1,0xa0,0x8b,0x42,0xab,0x82,0xe9,0x22, - 0x9b,0x0b,0x76,0x61,0x40,0x85,0x28,0xdd,0x64,0x51,0xc1,0x08,0xdd,0x64,0xd1,0x4d, - 0x16,0x2e,0xea,0xa3,0xa5,0xd6,0x36,0x55,0xb4,0x2e,0x6c,0xdd,0x89,0xda,0xa2,0xc5, - 0x47,0x50,0xa2,0x0d,0x4a,0xd4,0x60,0xc0,0x17,0x01,0x5b,0xa2,0xb5,0x06,0x67,0xbe, - 0xf3,0x9b,0x76,0xbc,0x81,0xc9,0xb9,0xf3,0xff,0xcf,0xcc,0x7f,0xe6,0x3b,0xdf,0x9c, - 0x3c,0xdb,0x52,0x0d,0x21,0x86,0xd6,0xd0,0x12,0x46,0x62,0x48,0x7f,0xed,0x21,0x0b, - 0xfa,0xb3,0x16,0x2a,0xe9,0xf9,0xd0,0xae,0xc7,0x76,0x6d,0x7f,0xf6,0xb9,0x27,0xb6, - 0xdf,0x79,0xd7,0x0e,0xe5,0x6f,0x08,0x79,0x8a,0x53,0x6e,0xa3,0x78,0x25,0x79,0xaa, - 0x3d,0xd5,0x78,0xf2,0x69,0xc5,0x3b,0xc5,0xf6,0x8a,0x35,0xc4,0x26,0xc4,0x26,0xc5, - 0xa6,0xc4,0xa6,0xc5,0x66,0xc4,0x66,0xc5,0xda,0xa4,0x86,0xe6,0x54,0xb5,0xbe,0xfc, - 0xea,0x4c,0x7a,0x5a,0x2f,0x84,0x87,0x43,0x39,0xf4,0x16,0xad,0x84,0x2d,0x3c,0x0d, - 0x8b,0x60,0x2d,0x0e,0xcb,0xc0,0xda,0x1c,0x96,0x83,0x75,0x39,0xac,0x04,0xd6,0xe3, - 0xb0,0x32,0xd8,0x80,0xc3,0x2a,0x60,0x5b,0x1d,0x56,0x05,0xbb,0xcd,0x61,0x2d,0x60, - 0x23,0x0e,0xdb,0x00,0xb6,0x23,0xcd,0x95,0x5f,0xeb,0x4f,0x67,0xd4,0x33,0xe9,0x63, - 0x1e,0xf5,0x1b,0xf8,0x11,0x7f,0x02,0xdf,0xe2,0x27,0xf1,0x73,0xfc,0x29,0xfc,0x12, - 0xfe,0x34,0x7e,0x19,0x7f,0x06,0xbf,0x82,0x3f,0x8b,0x6f,0x67,0x7c,0x5c,0x9e,0x9b, - 0x9d,0xbe,0xfa,0x83,0xce,0x9f,0x6b,0xe2,0xe7,0xe0,0xb5,0x9f,0x0e,0xf9,0x9f,0x25, - 0x3f,0x4f,0xfd,0x64,0xe9,0x3d,0xe7,0x49,0x4b,0xcf,0x6e,0x93,0xc4,0x57,0xd1,0x56, - 0xee,0x26,0xf1,0x6b,0x70,0x01,0xbe,0xce,0x3b,0x2e,0xe1,0xdf,0x48,0x7c,0x29,0xc5, - 0x95,0x24,0xa7,0x38,0x0b,0xc5,0xef,0xc5,0xef,0x04,0xd3,0x7a,0x3d,0xd4,0x8b,0x69, - 0xae,0xfa,0xb5,0xf7,0x62,0xd6,0x83,0x55,0x78,0xd6,0x9c,0x69,0xfd,0x3e,0xde,0x4f, - 0x2f,0xf5,0xd5,0xef,0x07,0x1b,0x6e,0xaa,0xaf,0xf1,0x83,0x70,0x55,0xc7,0x0f,0x31, - 0x8f,0xf9,0xc3,0xf0,0x1a,0x3f,0x42,0x7c,0x2d,0xcd,0x90,0x85,0x3b,0x88,0xab,0x71, - 0x1f,0x7c,0xde,0x28,0xf7,0xc7,0xfc,0x9d,0x4d,0x7d,0xec,0x66,0x0e,0xad,0xbb,0x07, - 0xae,0x07,0x7f,0x8c,0x3b,0x51,0x67,0x8e,0x31,0xf6,0x2d,0x77,0xf9,0xe3,0xbc,0x07, - 0xe3,0x1b,0x4d,0xfc,0x3e,0xce,0xdd,0xf8,0x09,0x78,0xf3,0x27,0x9b,0xe2,0xf7,0xb3, - 0x5f,0xc6,0x4f,0x35,0xf1,0x07,0x38,0x3b,0xe3,0xa7,0x9b,0xf8,0x83,0x62,0x0f,0x38, - 0x7e,0xa6,0x89,0x3f,0x24,0xf6,0xbc,0xe3,0x67,0xe1,0xf5,0x9e,0xbc,0xc4,0x59,0xf8, - 0xf8,0xc3,0xf8,0x37,0xcb,0xc9,0x1c,0xe3,0xcc,0xb3,0xf0,0xff,0x3f,0x3e,0x67,0xe9, - 0xcc,0x5e,0xe7,0xf7,0x31,0x34,0xd4,0x3f,0x0e,0xd6,0x2d,0x99,0x27,0x88,0x3b,0x09, - 0x76,0x82,0x38,0xf5,0xe7,0xc0,0x6e,0x11,0xc5,0x37,0xa9,0x71,0xb7,0x6c,0x5d,0xc6, - 0x19,0x06,0x7a,0xf9,0x4b,0x10,0xdd,0xc5,0xfb,0xb8,0xdb,0x1f,0x70,0x7f,0x1f,0x11, - 0x54,0xfb,0xff,0x10,0x2c,0x38,0xec,0x23,0x30,0xed,0x75,0x8f,0x60,0x7a,0x97,0x3e, - 0x26,0x56,0xb9,0x07,0x05,0xd3,0x7b,0x78,0x8e,0xbb,0x3a,0x40,0x7d,0x8d,0x3b,0x0f, - 0xfe,0x22,0x79,0x9f,0x90,0x7b,0xde,0xe5,0x7d,0x4a,0xde,0x90,0xcb,0xbb,0x00,0xfe, - 0x02,0x79,0x9f,0x91,0x7b,0x81,0x3c,0xbd,0xc7,0x9f,0x93,0x37,0x4c,0x9e,0x9e,0xef, - 0x17,0xe0,0x27,0x25,0x46,0xef,0xf6,0x97,0x60,0x7a,0xb7,0xd7,0xe4,0x04,0x16,0x98, - 0xed,0x8a,0xc4,0x2b,0x37,0x2f,0xb6,0xc0,0xb9,0xcc,0xbb,0x99,0xbf,0x42,0x33,0xa4, - 0x7b,0x53,0x4a,0xd8,0xd7,0xe0,0x8f,0x8a,0xa7,0x3d,0x6d,0x8d,0x05,0x66,0x71,0x7f, - 0x4b,0x0d,0xab,0xa5,0xcf,0xcb,0x12,0xa5,0x71,0xb7,0xc7,0x22,0xa6,0x4c,0xce,0xbc, - 0x9b,0xe1,0x1b,0x66,0x18,0x75,0x33,0x7c,0x0b,0x6e,0x33,0x5c,0x04,0xb3,0x19,0x96, - 0xdc,0x0c,0xca,0x2d,0x8a,0x2d,0xa1,0xbb,0xe8,0x66,0xf8,0x0e,0xed,0xe8,0x66,0xf8, - 0x1e,0xdc,0x66,0xb8,0x35,0x16,0x98,0xc5,0xe9,0x0c,0x56,0x6b,0xc9,0xcd,0xb0,0x2d, - 0x16,0x31,0x0b,0xe4,0x2c,0xba,0x19,0x7e,0x60,0x86,0x9d,0x6e,0x86,0x1f,0xc1,0x6d, - 0x86,0x9f,0xc0,0x6c,0x86,0x15,0x37,0x83,0x72,0xcb,0x62,0x2b,0xe8,0x2e,0xa7,0x6f, - 0x4b,0xa1,0xfb,0x33,0xda,0xdb,0xe2,0xf5,0x5d,0xd1,0x1e,0x2d,0x76,0xc5,0xf5,0x38, - 0x4c,0xdc,0x12,0x79,0xcb,0xf4,0xa8,0xdf,0xa6,0x97,0xe9,0xf1,0x30,0x3d,0xea,0x7e, - 0xbe,0x02,0xfe,0x0c,0x67,0xf3,0x2a,0x98,0x9d,0xdf,0x6b,0xd4,0xf4,0xbb,0x70,0x04, - 0xac,0xd8,0x85,0x4a,0xda,0xfb,0xa3,0xc4,0x1e,0xa1,0x86,0xd6,0xd7,0xfd,0x7b,0x83, - 0xfd,0x55,0x5f,0x77,0xf5,0x14,0x7b,0xfa,0xb8,0xd4,0xd2,0x1d,0x7d,0x8b,0x98,0x53, - 0x6e,0xde,0xb7,0xa9,0x77,0xd4,0x7d,0x1f,0x6c,0x4f,0xde,0x61,0x86,0x71,0xb7,0x27, - 0xa7,0xc1,0x6d,0xbf,0xde,0xa5,0xc6,0x69,0xd7,0xf3,0x7b,0xe0,0x7e,0x8e,0x33,0x60, - 0x7e,0x8e,0xb3,0xc4,0x9e,0x61,0x8e,0x31,0x89,0xd5,0xef,0xf7,0xfb,0xf4,0x7a,0xd6, - 0x9d,0xe7,0x2f,0xf4,0xb2,0xdb,0x9d,0xe7,0xaf,0xe0,0xe7,0x24,0x46,0xfd,0xdf,0xc0, - 0x06,0xdc,0x3d,0xf8,0x1d,0x7c,0x88,0x7b,0xb0,0xea,0xee,0x81,0x72,0x7f,0x88,0xad, - 0xf2,0x6e,0xf5,0xf7,0xfd,0x12,0xb3,0x97,0x1e,0xf4,0xbd,0x1b,0xb7,0xea,0x74,0xfe, - 0x44,0x67,0xdc,0xe9,0x5c,0x02,0x37,0x9d,0x35,0xa7,0x73,0x29,0xdd,0x99,0x90,0x30, - 0xad,0x75,0x19,0x9d,0x86,0xd3,0x31,0x6e,0xcd,0xe9,0x5c,0x41,0x67,0x9f,0xd3,0xf9, - 0x07,0xdc,0x74,0xd6,0x9d,0x8e,0x72,0x57,0xc5,0xd6,0xa9,0x75,0x15,0x9d,0x09,0xa7, - 0x63,0xdc,0xba,0xd3,0x89,0xb1,0xd0,0x19,0x75,0x3a,0x59,0x2c,0x70,0xd3,0x29,0xc7, - 0xeb,0x3a,0xca,0xe5,0x62,0x8a,0x69,0x2d,0xfd,0xad,0x3a,0x93,0x4e,0xc7,0x38,0x7d, - 0x9a,0x4e,0x0b,0x3a,0xfb,0x9d,0xce,0x86,0x58,0xe0,0xa6,0x53,0x77,0x3a,0xca,0xb5, - 0x8a,0xd5,0xa9,0xd5,0x8a,0xce,0x94,0xd3,0x31,0xae,0xee,0x74,0x36,0xa2,0x73,0xc0, - 0xe9,0xb4,0xc5,0x02,0x37,0x9d,0x0e,0xa7,0xa3,0x5c,0xbb,0x58,0x07,0xb5,0xda,0xd1, - 0x99,0x76,0x3a,0xc6,0x75,0x38,0x9d,0x4e,0x74,0x0e,0x3a,0x9d,0x4d,0xb1,0xc0,0x4d, - 0xa7,0xdb,0xe9,0x28,0xd7,0x25,0xd6,0x4d,0xad,0x2e,0x74,0x66,0x9c,0x8e,0x71,0xdd, - 0x4e,0xa7,0x17,0x9d,0x43,0x4e,0xa7,0x2f,0x16,0xb8,0xe9,0x0c,0x3a,0x1d,0xe5,0xfa, - 0xc5,0x06,0xa9,0xd5,0x8f,0xce,0xac,0xd3,0x31,0x4e,0x9f,0xff,0xca,0x56,0xde,0x23, - 0xf6,0x1f,0x52,0xc4,0x1f,0x8c,0xf8,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4d,0x6c,0x55,0x55, + 0x10,0xc7,0xcf,0xb9,0xef,0xf5,0xbd,0x96,0x87,0x50,0x2a,0xb4,0x56,0x5f,0xcb,0x03, + 0x4c,0x03,0x96,0x20,0x0b,0x34,0x12,0xa3,0xd1,0x84,0x44,0x17,0x24,0xa0,0x24,0x96, + 0x45,0x37,0x2f,0xa1,0x0b,0x9a,0x08,0x49,0x35,0x6c,0xba,0xc0,0x84,0x92,0xb0,0xe9, + 0x82,0x4d,0x17,0x2e,0xfc,0x80,0x20,0x62,0xd1,0x28,0x2e,0x04,0x77,0xc6,0x8f,0x46, + 0x89,0x1f,0x8d,0xa6,0x6a,0x23,0x29,0xd0,0xd0,0x04,0xd0,0x34,0x11,0xac,0x02,0x69, + 0xe2,0xcc,0xb9,0xbf,0x81,0xe1,0xbd,0x64,0xde,0xbd,0xf3,0xff,0xcf,0xcc,0xff,0xcc, + 0x39,0x67,0x6e,0x21,0x5b,0x57,0x0e,0x21,0x86,0x25,0xa1,0x39,0xf4,0xc6,0x90,0x7e, + 0x2b,0x42,0x16,0xf4,0xb5,0x12,0x4a,0xe9,0xf9,0xc2,0xf6,0x5d,0xdb,0x37,0xbd,0xf6, + 0xfa,0x9e,0x4d,0x5b,0x9e,0xd8,0xac,0xfc,0xb2,0x50,0x48,0x71,0xca,0x2d,0x17,0xaf, + 0x28,0x4f,0xb5,0x57,0xeb,0x7b,0xf7,0x29,0xde,0x2e,0xb6,0x5b,0xac,0x2e,0x36,0x28, + 0x36,0x24,0x36,0x2c,0x36,0x22,0x36,0x2a,0x36,0x26,0xd6,0x2a,0x35,0x34,0xa7,0xac, + 0xf5,0xe5,0xad,0x3d,0xe9,0x69,0xbd,0x10,0x5e,0x0c,0x4d,0xa1,0x2b,0x5f,0x4a,0x58, + 0xc7,0xd3,0xb0,0x08,0xd6,0xec,0xb0,0x0c,0xac,0xd5,0x61,0x05,0xb0,0x87,0x1c,0x56, + 0x04,0xab,0x3a,0xac,0x09,0xac,0xe6,0xb0,0x12,0xd8,0xa3,0x0e,0x2b,0x83,0xad,0x77, + 0x58,0x33,0xd8,0x46,0x87,0xb5,0x80,0x6d,0x76,0xd8,0x12,0xb0,0x2d,0xa9,0xd7,0xc2, + 0xdd,0x35,0x6b,0xdf,0xba,0x4f,0xdd,0xf4,0xa8,0x7e,0x1d,0x3f,0xe2,0x0f,0xe2,0x5b, + 0xfc,0x10,0x7e,0x01,0x7f,0x18,0xbf,0x88,0x3f,0x82,0xdf,0x84,0x3f,0x8a,0x5f,0xc2, + 0x1f,0xc3,0xb7,0x7d,0x3f,0x29,0xcf,0xb5,0x4e,0x5f,0xfd,0x35,0xce,0x1f,0x6f,0xe0, + 0xc7,0xe1,0x75,0x3d,0x0f,0xca,0x7f,0x96,0xfc,0x42,0x5a,0x4f,0x96,0xce,0xbe,0x90, + 0xb4,0x74,0x3f,0x3b,0x24,0xbe,0x8c,0xb6,0x72,0xab,0xc4,0xaf,0xc0,0x05,0xf8,0xa5, + 0x9c,0x7b,0x11,0x7f,0x25,0xf1,0xc5,0x14,0x57,0x94,0x9c,0x7c,0x2f,0x14,0x7f,0x1a, + 0xbf,0x1d,0x4c,0xeb,0x55,0xa9,0x17,0x53,0x5f,0x0f,0xdc,0x3d,0x2b,0xb3,0xaa,0xb3, + 0x12,0xcf,0x8a,0x33,0xd5,0xe8,0xe6,0xdc,0xba,0xd0,0x50,0x7f,0x35,0x58,0x6f,0x83, + 0x86,0xc6,0xaf,0x81,0x2b,0x3b,0xbe,0x87,0x9e,0xcc,0xef,0xe5,0x7e,0x68,0xfc,0x46, + 0xe2,0x2b,0xa9,0x8f,0x2c,0x3c,0x4e,0x5c,0x85,0x7b,0xe2,0xf3,0xb6,0x36,0xe8,0x6e, + 0xe3,0xfe,0x98,0xbf,0x03,0x5d,0xad,0xbb,0x93,0xd8,0x2a,0x7e,0x1f,0xf7,0x62,0x29, + 0x7d,0xf4,0x31,0x87,0x05,0x97,0xdf,0xcf,0x59,0x18,0x5f,0x6f,0xe0,0x07,0xd8,0x7b, + 0xe3,0x07,0xe1,0xcd,0x1f,0x6a,0x88,0x3f,0xc0,0xdc,0x19,0x3f,0xdc,0xc0,0x1f,0x64, + 0xef,0x8c,0x1f,0x69,0xe0,0x8f,0x88,0x3d,0xe7,0xf8,0xd1,0x06,0xfe,0xa8,0xd8,0x1b, + 0x8e,0x1f,0x83,0xd7,0xbb,0xf2,0x26,0x67,0xaa,0x7e,0xa7,0xec,0xc4,0x09,0xf6,0x38, + 0x0b,0xf7,0xff,0xf8,0xac,0xa5,0x3d,0x7a,0x8f,0xf7,0x13,0xd4,0x54,0xff,0x24,0xd8, + 0xc3,0x92,0x79,0x8a,0xb8,0x0f,0xc0,0x4e,0x11,0xa7,0xfe,0x38,0xd8,0x23,0xa2,0xf8, + 0x21,0x35,0x9e,0x94,0x49,0xcb,0xd8,0xb3,0xc0,0x5a,0xfe,0x13,0x44,0xe7,0xef,0x19, + 0xee,0xf3,0x17,0xdc,0xd9,0x97,0x04,0xd5,0xf5,0x7e,0x09,0x16,0x1c,0xf6,0x15,0x98, + 0xae,0x75,0xa7,0x60,0x7a,0xc6,0x5f,0x13,0xab,0xdc,0xf3,0x82,0xe9,0xbd,0xfb,0x86, + 0xbb,0x59,0xa3,0xbe,0xc6,0x4d,0x80,0x1f,0x26,0xef,0x5b,0x72,0x27,0x5c,0xde,0x77, + 0xe4,0xf5,0xb8,0xbc,0xf3,0xe0,0x87,0xc8,0xfb,0x9e,0xdc,0xf3,0xe4,0xe9,0xbd,0xfd, + 0x81,0xbc,0x5e,0xf2,0x74,0x7f,0x7f,0x04,0x1f,0x97,0x18,0xbd,0xcb,0x3f,0x81,0xe9, + 0x5d,0xfe,0x57,0x76,0x60,0x8a,0xde,0x6e,0x4b,0xbc,0x72,0x93,0x62,0x53,0xec,0xcb, + 0xa4,0xeb,0xf9,0x67,0x34,0x43,0xba,0x27,0xc5,0x84,0xfd,0x02,0xfe,0xb2,0x78,0xe9, + 0x9b,0x1b,0x73,0xcc,0xe2,0x6e,0x49,0x0d,0xab,0xa5,0xcf,0x7f,0x24,0x4a,0xe3,0xd6, + 0xc7,0x3c,0xa6,0x89,0x9c,0x49,0xd7,0xc3,0xaf,0xf4,0xb0,0xd5,0xf5,0xf0,0x1b,0xb8, + 0xf5,0xf0,0x3b,0x98,0xf5,0x30,0xe3,0x7a,0x50,0x6e,0x5a,0x6c,0x06,0xdd,0x69,0xd7, + 0xc3,0x1f,0x68,0x47,0xd7,0xc3,0x05,0x70,0xeb,0xa1,0x27,0xe6,0x98,0xc5,0x69,0x0f, + 0x56,0x6b,0xc6,0xf5,0xb0,0x21,0xe6,0x31,0x53,0xe4,0x4c,0xbb,0x1e,0x2e,0xd2,0xc3, + 0x36,0xd7,0xc3,0x25,0x70,0xeb,0xe1,0x32,0x98,0xf5,0x30,0xe7,0x7a,0x50,0x6e,0x56, + 0x6c,0x0e,0xdd,0xd9,0xf4,0x2d,0xc9,0x75,0xaf,0xa0,0xbd,0x21,0xde,0x9b,0x15,0x5d, + 0xa3,0xc5,0xce,0xb9,0x35,0x3e,0x46,0xdc,0x0c,0x79,0xb3,0xac,0x51,0xbf,0x45,0x6f, + 0xb1,0xc6,0x01,0xd6,0xa8,0xf3,0xfb,0x36,0xf8,0x7e,0xf6,0xe6,0x1d,0x30,0xdb,0xbf, + 0x77,0xa9,0xe9,0x67,0xe1,0x18,0x58,0x3e,0x0b,0xa5,0x34,0xe7,0xc7,0x89,0x3d,0x46, + 0x0d,0xad,0xaf,0xf3,0xf7,0x3e,0xf3,0xab,0xbe,0xce,0xea,0x69,0xe6,0xf4,0x15,0xa9, + 0xa5,0x33,0xfa,0x11,0x31,0xa7,0x5d,0xbf,0x1f,0x53,0xef,0xb8,0xfb,0x3e,0xd8,0x9c, + 0x7c,0x42,0x0f,0xfd,0x6e,0x4e,0xce,0x80,0xdb,0x7c,0x7d,0x4a,0x8d,0x33,0x6e,0xcd, + 0x9f,0x81,0xfb,0x3e,0xce,0x82,0xf9,0x3e,0xce,0x11,0x7b,0x96,0x3e,0xfa,0x24,0x56, + 0xbf,0xd7,0x9f,0xb3,0xd6,0x73,0x6e,0x3f,0xaf,0xb2,0x96,0x1d,0x6e,0x3f,0xaf,0x81, + 0x4f,0x48,0x8c,0xfa,0xd7,0xc1,0x6a,0xee,0x1e,0xfc,0x09,0xde,0xc3,0x3d,0x98,0x77, + 0xf7,0x40,0xb9,0xbf,0xc4,0xe6,0x39,0x5b,0x7d,0x7f,0x56,0x62,0x76,0xb3,0x06,0x3d, + 0x77,0xe3,0xe6,0x9d,0xce,0xdf,0xe8,0xf4,0x3b,0x9d,0x1b,0xe0,0xa6,0xb3,0xe0,0x74, + 0x94,0xbb,0x29,0xb6,0x40,0xad,0x9b,0xe8,0xd4,0x9d,0x8e,0x71,0x0b,0x4e,0xe7,0x16, + 0x3a,0x03,0x4e,0xe7,0x36,0xb8,0xe9,0x2c,0x3a,0x1d,0xe5,0xee,0x88,0x2d,0x52,0xeb, + 0x0e,0x3a,0x83,0x4e,0xc7,0xb8,0x45,0xa7,0xa3,0x87,0x72,0x8d,0xef,0x9a,0xe9,0xc4, + 0x98,0xe3,0xa6,0x53,0x8c,0xf7,0x74,0x94,0xcb,0xc4,0x14,0xd3,0x5a,0xfa,0xae,0x3a, + 0x43,0x4e,0xc7,0x38,0x7d,0x9a,0x4e,0x19,0x9d,0x03,0x4e,0xa7,0x39,0xe6,0xb8,0xe9, + 0x54,0x9c,0x8e,0x72,0x2d,0x62,0x15,0x6a,0xb5,0xa0,0x33,0xec,0x74,0x8c,0xab,0x38, + 0x9d,0x65,0xe8,0x1c,0x74,0x3a,0xcb,0x63,0x8e,0x9b,0x4e,0x9b,0xd3,0x51,0xae,0x55, + 0xac,0x8d,0x5a,0xad,0xe8,0x8c,0x38,0x1d,0xe3,0xda,0x9c,0xce,0x2a,0x74,0x8e,0x38, + 0x9d,0xf6,0x98,0xe3,0xa6,0xd3,0xe9,0x74,0x94,0xeb,0x10,0xeb,0xa4,0x56,0x07,0x3a, + 0xa3,0x4e,0xc7,0xb8,0x4e,0xa7,0x53,0x45,0xe7,0xa8,0xd3,0xe9,0x8a,0x39,0x6e,0x3a, + 0x35,0xa7,0xa3,0x5c,0xb7,0x58,0x8d,0x5a,0xdd,0xe8,0x8c,0x39,0x1d,0xe3,0xf4,0xb9, + 0x28,0x07,0xfd,0x94,0xd8,0xff,0xc0,0x97,0xe4,0x26,0x00,0x0d,0x00,0x00 }; // Generated from: @@ -109,6 +109,7 @@ constexpr uint8_t kBlit3DSrc_frag_00000002[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000000.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000000.inc index 00e2a996328..c38b827e485 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000000.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000000.inc @@ -10,72 +10,74 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000000[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x5f,0x68,0xd6,0x65, - 0x14,0xc7,0x9f,0xdf,0xfb,0x77,0xb9,0xb1,0x94,0xe6,0xd4,0x6d,0x3a,0xcd,0x06,0xa1, - 0xb1,0xbc,0xb0,0x18,0x84,0x61,0x78,0x61,0x17,0xa2,0x59,0x30,0x2f,0x76,0xb3,0x60, - 0x37,0xef,0x45,0xc1,0x28,0x6f,0x76,0x61,0xc1,0x4b,0x78,0xb3,0x0b,0x6f,0x76,0x63, - 0x6a,0xb3,0x48,0x83,0x2e,0x22,0x4b,0x52,0x2a,0x87,0xb1,0x72,0x14,0xab,0xc4,0x81, - 0x56,0x0c,0x4a,0x06,0x25,0x83,0x92,0x81,0xda,0x22,0xa5,0xf3,0xfd,0xbd,0x9f,0xb3, - 0x0e,0xef,0x0b,0x67,0xbf,0xdf,0xf7,0xfb,0x3d,0xcf,0xf9,0x3e,0xe7,0xbc,0xcf,0xf3, - 0xae,0x58,0xd8,0x5a,0x4d,0x29,0x4b,0xab,0x52,0x4b,0x5a,0x9f,0xa5,0xfc,0xb3,0x26, - 0x15,0x92,0x5e,0x5b,0x53,0x25,0x7f,0xee,0xdd,0xf7,0xd2,0xbe,0xfe,0xd7,0x5e,0x1f, - 0xe9,0xdf,0xf9,0xd4,0x0e,0xe9,0xed,0xa9,0x98,0xe7,0x49,0x7b,0xd8,0x50,0xc9,0x9e, - 0x8a,0x57,0x5e,0xae,0xbd,0x2a,0xbe,0xc3,0xe2,0x90,0xc5,0xb0,0x45,0xcd,0x62,0xd4, - 0x62,0xcc,0xa2,0x6e,0x31,0x6e,0x31,0x61,0xb1,0xda,0x6a,0x68,0x4d,0x55,0xf5,0xed, - 0xad,0x23,0xf7,0x53,0xbd,0x94,0x9e,0x4f,0xe5,0xd4,0xd3,0xd8,0x4a,0xda,0xca,0xd3, - 0xb9,0x0c,0xae,0x25,0x70,0x05,0xb8,0xd5,0x81,0x2b,0xc2,0xad,0x0f,0x5c,0x09,0xae, - 0x27,0x70,0x65,0xb8,0xcd,0x81,0xab,0xc0,0x3d,0x16,0xb8,0x2a,0xdc,0xe3,0x81,0x6b, - 0x81,0x7b,0x22,0x70,0x0f,0xc1,0xed,0xc8,0xfb,0x2a,0xae,0xec,0x4f,0x3d,0x6a,0x26, - 0x9b,0xe8,0x47,0x78,0x18,0x9c,0x81,0x6b,0x60,0xcf,0x1f,0x05,0x17,0xc1,0x63,0xe0, - 0x12,0xb8,0x0e,0x2e,0x83,0xc7,0xc1,0x15,0xf0,0x04,0xd8,0x67,0x7c,0xc2,0x9e,0x8f, - 0x06,0x7f,0xe1,0x2d,0x01,0x4f,0x36,0xe9,0x93,0xe8,0xda,0xcf,0x23,0xf6,0xb7,0x90, - 0xe3,0x62,0xbe,0x1f,0xbd,0x77,0xda,0x5b,0x85,0xd9,0xad,0xb3,0xfc,0x2a,0xde,0x05, - 0x70,0x2b,0xb8,0x94,0xe7,0x94,0xac,0x46,0xe2,0x5c,0xa5,0xf4,0x0c,0xb8,0x03,0x6e, - 0xad,0xe1,0x2e,0x6a,0x39,0xee,0x06,0xa7,0xbc,0x8f,0xb6,0x95,0xef,0xc1,0xa3,0x8b, - 0xa8,0xf0,0xec,0x0e,0x21,0xbf,0x8d,0x7c,0x1f,0x3d,0xf8,0x6d,0x64,0x1e,0xe2,0xb6, - 0xe3,0xd7,0x8b,0x9f,0xf2,0x37,0xa3,0x55,0x83,0xde,0x87,0xbf,0xe3,0x6d,0xe8,0xca, - 0xdf,0x4e,0x7e,0x77,0xde,0x47,0x21,0xf5,0x93,0x27,0xfc,0x64,0xd3,0xba,0x01,0xce, - 0x8b,0xe3,0x3d,0x4d,0xfb,0xd8,0x4f,0x1f,0xaa,0x7b,0x00,0xad,0x0b,0x3c,0xc8,0x19, - 0xf0,0xb9,0x0d,0x72,0xbf,0x8a,0x61,0xfd,0x10,0x73,0x77,0x7d,0xb8,0x49,0x1f,0xe1, - 0x7b,0x70,0xbd,0x86,0xee,0x78,0xb4,0x29,0xff,0x30,0xf7,0xc9,0xf5,0xb1,0x26,0xfd, - 0x08,0xdf,0x8d,0xeb,0xf5,0x26,0xfd,0xa8,0xc5,0xee,0xa0,0x8f,0x37,0xe9,0xc7,0x2c, - 0xde,0x0c,0xfa,0x04,0xfa,0x06,0xeb,0xfc,0x38,0xb3,0xe0,0xe7,0x68,0xe5,0xe3,0x58, - 0x33,0x79,0x9b,0xf7,0xe3,0xd4,0x10,0x3e,0x01,0xd7,0x65,0x93,0x38,0x45,0xde,0x3b, - 0x70,0xa7,0xc8,0x13,0x9e,0x84,0xeb,0x36,0xc7,0x77,0xa9,0xf1,0xb4,0xdd,0xa2,0x02, - 0x33,0x4a,0xec,0xe5,0x6f,0x63,0x74,0xb7,0x76,0x71,0x96,0x3f,0xe2,0xbc,0x1e,0x34, - 0x56,0xfb,0xfb,0x18,0x2e,0x05,0xee,0x1c,0x9c,0xf6,0xfa,0x82,0x71,0x3a,0x2b,0x9f, - 0x90,0x2b,0xed,0x39,0xe3,0x34,0xb7,0x4f,0x39,0x8b,0xbd,0xd4,0x57,0xde,0x79,0xf8, - 0xb7,0x58,0xf7,0x19,0x6b,0xcf,0x87,0x75,0x17,0x58,0xd7,0x17,0xd6,0x5d,0x84,0xaf, - 0xb3,0xee,0x73,0xd6,0x5e,0x64,0x9d,0xce,0xe9,0x17,0xac,0xdb,0xc6,0x3a,0x9d,0xd1, - 0x2f,0xe1,0x3f,0xb4,0x1c,0x9d,0xdd,0x4b,0x70,0x3a,0xbb,0xf7,0x6c,0x02,0xd3,0xf4, - 0xf6,0x8f,0xe5,0x4b,0x9b,0xb2,0x98,0x66,0x2e,0x53,0xa1,0xe7,0xcb,0x78,0xea,0xf3, - 0x86,0xe5,0x8a,0xfb,0x0a,0xfe,0x45,0x43,0xda,0xd3,0x9a,0xac,0xc1,0x79,0xde,0xb2, - 0xd5,0xf0,0x5a,0x7a,0xde,0xb1,0x2c,0xe5,0xad,0xcd,0x1a,0x39,0x65,0xd6,0x4c,0x85, - 0x1e,0xbe,0xa6,0x87,0x81,0xd0,0xc3,0x37,0xf0,0xde,0xc3,0x15,0x38,0xef,0x61,0x36, - 0xf4,0x20,0x6d,0xc6,0x62,0x16,0xdf,0x99,0xd0,0xc3,0xb7,0x78,0x67,0xa1,0x87,0xef, - 0xe0,0xbd,0x87,0x8e,0xac,0xc1,0x79,0x9e,0x7a,0xf0,0x5a,0xb3,0xa1,0x87,0xce,0xac, - 0x91,0x33,0xcd,0x9a,0x99,0xd0,0xc3,0xf7,0xf4,0xb0,0x27,0xf4,0xf0,0x03,0xbc,0xf7, - 0xf0,0x23,0x9c,0xf7,0x30,0x17,0x7a,0x90,0x76,0xd5,0x62,0x0e,0x5f,0xbd,0x1f,0xc0, - 0xf7,0x1a,0xde,0x9d,0xd9,0xff,0x77,0x45,0x7b,0xf4,0xdc,0xb9,0xb0,0xc7,0x75,0xe4, - 0xcd,0xb2,0xee,0x2a,0xfb,0xd1,0x5d,0x38,0xc9,0x5d,0x12,0xd6,0xbd,0x39,0xcd,0x9d, - 0x19,0xb4,0xfd,0xe9,0xbe,0xbc,0x47,0xce,0xe9,0x70,0x2e,0xdf,0xa7,0xaf,0xa1,0x70, - 0x2e,0xcf,0xc0,0xfb,0x79,0x3e,0x8b,0xef,0x99,0xfc,0xf7,0xab,0x9c,0xdf,0xa9,0x0f, - 0xa8,0x77,0x96,0x5a,0xfa,0xed,0xbb,0x4e,0xad,0xfd,0xd4,0xd2,0xef,0xc5,0x0d,0xf8, - 0x2b,0x96,0x23,0xfc,0x13,0x5c,0x6f,0x98,0xdb,0xcf,0xf0,0x7d,0xcc,0x6d,0x3e,0xcc, - 0x4d,0xda,0x2f,0x16,0xf3,0xcc,0x42,0xef,0xcf,0x5a,0xce,0x21,0xf6,0xa0,0x39,0xb9, - 0x36,0x1f,0x7c,0x7e,0xc5,0x67,0x28,0xf8,0xfc,0x06,0xef,0x3e,0x0b,0xc1,0x47,0xda, - 0x4d,0x8b,0x05,0x6a,0xdd,0xc4,0x67,0x38,0xf8,0xb8,0xb6,0x10,0x7c,0x7e,0xc7,0x67, - 0x24,0xf8,0xfc,0x01,0xef,0x3e,0x8b,0xc1,0x47,0xda,0x2d,0x8b,0x45,0x6a,0xdd,0xc2, - 0xa7,0x16,0x7c,0x5c,0x5b,0x0c,0x3e,0x7f,0xe2,0x33,0x10,0x7c,0xfe,0x82,0x77,0x9f, - 0xa5,0xe0,0x23,0xed,0xb6,0xc5,0x12,0xb5,0x6e,0xe3,0x33,0x1a,0x7c,0x5c,0x5b,0x0a, - 0x3e,0x77,0xf0,0x39,0x1c,0x7c,0xee,0xc2,0xbb,0xcf,0x72,0xf0,0xb9,0x9b,0x73,0x29, - 0xe7,0x54,0xeb,0x1e,0x3e,0x63,0xc1,0xc7,0xb5,0xe5,0xe0,0xf3,0x2f,0x3e,0x47,0x82, - 0xcf,0x7d,0x78,0xf7,0xf1,0xcb,0x20,0x1f,0x69,0x0f,0xf8,0x67,0xa2,0x5a,0x0f,0xf0, - 0xa9,0x07,0x1f,0xd7,0xf4,0x74,0x9f,0x62,0xd6,0xf0,0x39,0x1a,0x7c,0x4a,0x59,0x83, - 0x77,0x9f,0x6a,0xf0,0x91,0x56,0xb6,0xa8,0x52,0x4b,0xef,0xf2,0x19,0x0f,0x3e,0xae, - 0x55,0x83,0xcf,0x2a,0x7c,0x8e,0x05,0x9f,0xd6,0xac,0xc1,0xbb,0x4f,0x7b,0xf0,0x91, - 0xd6,0x66,0xd1,0x4e,0xad,0x36,0x7c,0x26,0x82,0x8f,0x6b,0x7a,0xde,0xb7,0xa6,0x06, - 0x2c,0xfe,0x03,0xad,0x5f,0xf0,0xc4,0xf8,0x0b,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4f,0x68,0x5c,0x55, + 0x14,0xc6,0xef,0x9b,0x99,0xcc,0x24,0x1d,0x6c,0x63,0x4d,0xb5,0x9d,0x49,0x4d,0xb5, + 0x06,0x24,0x95,0xd8,0x45,0x95,0x80,0x28,0x4a,0x17,0xba,0x28,0xad,0x7f,0x20,0x15, + 0xb2,0x89,0x90,0xcd,0x2c,0x54,0x82,0x76,0x93,0x85,0x0a,0x83,0x74,0x93,0x45,0x37, + 0xd9,0xd4,0x5a,0x53,0xc5,0xb6,0x1a,0x77,0xe2,0x9f,0xa2,0xc5,0x3f,0x41,0x8d,0x1a, + 0x94,0xa8,0xc5,0x80,0x55,0x09,0x68,0x09,0x68,0x09,0x68,0x8d,0xb6,0x25,0xe0,0xf9, + 0xde,0xfc,0x4e,0x7a,0x98,0x81,0x93,0xfb,0xce,0xf7,0x9d,0x73,0xbe,0x7b,0xce,0xbb, + 0xf7,0xa5,0x58,0xd8,0x59,0x49,0x29,0x4b,0x1b,0x52,0x67,0xea,0xcd,0x52,0xfe,0xbb, + 0x3e,0x15,0x92,0x1e,0xab,0xa9,0x9c,0xaf,0x0f,0xee,0x7b,0x6c,0xdf,0xe0,0x33,0xcf, + 0x8e,0x0d,0xee,0xb9,0x6b,0xb7,0xf8,0x8d,0xa9,0x98,0xc7,0x89,0xdb,0x64,0x5e,0xc9, + 0x56,0xd9,0x93,0x4f,0x34,0x9e,0x12,0xde,0x63,0x76,0xd0,0x6c,0xd4,0xac,0x61,0x36, + 0x6e,0x36,0x61,0xd6,0x34,0x9b,0x34,0x9b,0x32,0xeb,0xb6,0x1a,0xca,0xa9,0xa8,0xbe, + 0x3d,0xf5,0xe4,0x7a,0xaa,0x97,0xd2,0x43,0xa9,0x23,0xf5,0xb6,0xb6,0x92,0x76,0xb2, + 0x3a,0x96,0x81,0x75,0x06,0xac,0x00,0xd6,0x1d,0xb0,0x22,0xd8,0xd6,0x80,0x95,0xc0, + 0x7a,0x03,0xd6,0x01,0xb6,0x23,0x60,0x65,0xb0,0xdb,0x02,0x56,0x01,0xbb,0x3d,0x60, + 0x9d,0x60,0x77,0x04,0xac,0x0b,0x6c,0x77,0xc0,0x36,0x80,0xed,0xc9,0x7b,0x2d,0xae, + 0xef,0x59,0x7d,0x6b,0x4e,0x37,0xd3,0xa3,0xfc,0x51,0xfc,0x0c,0xbf,0x81,0xef,0xf1, + 0xe3,0xf8,0x45,0xfc,0x09,0xfc,0x12,0x7e,0x13,0xbf,0x03,0x7f,0x12,0xbf,0x8c,0x3f, + 0x85,0xef,0x73,0x3f,0x66,0xeb,0xad,0x41,0x5f,0xfe,0x2d,0xc1,0x9f,0x6e,0xe3,0xa7, + 0xe1,0xb5,0x9f,0x1b,0xec,0x6f,0x21,0xf7,0x8b,0xf9,0x7e,0xf4,0x7c,0xa3,0x3d,0x95, + 0x99,0xe7,0x4d,0x16,0x5f,0x41,0xbb,0x80,0x5f,0xc5,0x2f,0xe5,0x31,0x25,0xab,0x91, + 0x38,0x6b,0x29,0xdd,0x83,0xdf,0x03,0xb6,0xc5,0xfc,0x1a,0xb5,0xdc,0xaf,0xe3,0xa7, + 0xbc,0x8f,0xeb,0xd6,0xdf,0x8d,0x5b,0x2d,0x58,0x99,0xb5,0x1e,0x4c,0x9a,0xdb,0x79, + 0x4f,0xbd,0x68,0x6e,0x67,0x26,0xc2,0x76,0xa1,0xd9,0x87,0xa6,0xe2,0x77,0xc0,0x55, + 0x02,0xdf,0xcf,0x1e,0xdc,0x1f,0xe0,0x3c,0x28,0x7e,0x17,0xf1,0xf5,0xbc,0x97,0x42, + 0x1a,0x24,0x4e,0xfe,0x9d,0x6d,0x79,0x43,0x6d,0xba,0x7b,0x39,0x2f,0xee,0xef,0x47, + 0x57,0x75,0x0f,0x10,0x5b,0xc3,0x1f,0xe6,0x1c,0xf8,0xec,0x86,0xb9,0x77,0xc5,0x90, + 0x3f,0xc2,0xec,0x9d,0x1f,0x6d,0xe3,0xc7,0x78,0x17,0xce,0x37,0xe0,0xdd,0x1f,0x6f, + 0x8b,0x3f,0xc4,0x3d,0x73,0x7e,0xa2,0x8d,0x7f,0x8e,0xf7,0xe3,0x7c,0xb3,0x8d,0x3f, + 0x6c,0x76,0x7f,0xe0,0x27,0xdb,0xf8,0x23,0x66,0x2f,0x04,0x7e,0x0a,0x7e,0x9b,0x75, + 0x7e,0x94,0x77,0xca,0x67,0x6a,0xfd,0xe7,0xbe,0x66,0xf2,0x12,0xcf,0x47,0xa9,0x21, + 0xff,0x18,0x58,0xcd,0x26,0x71,0x9c,0xb8,0x57,0xc0,0x8e,0x13,0x27,0x7f,0x1a,0xac, + 0x6e,0x8a,0xaf,0x52,0xc3,0xf7,0x75,0x9a,0x7d,0xdc,0x6d,0x37,0xab,0xc0,0xcc,0x12, + 0xd8,0x7f,0x86,0xe8,0xbe,0xdd,0xcb,0xf9,0x7e,0x9b,0x33,0xfc,0x88,0xa1,0xda,0xef, + 0x3b,0x60,0x29,0x60,0xef,0x82,0x69,0xef,0x0f,0x1b,0xa6,0x77,0xfc,0x1e,0xb1,0xe2, + 0x1e,0x30,0x4c,0x73,0x7c,0x9f,0xb3,0xd9,0x47,0x7d,0xc5,0x9d,0x01,0x7f,0x91,0xbc, + 0x0f,0xc8,0x3d,0x13,0xf2,0x3e,0x24,0xaf,0x3f,0xe4,0x9d,0x05,0x6f,0x92,0xf7,0x11, + 0xb9,0x67,0xc9,0xd3,0xb9,0xfd,0x98,0xbc,0x01,0xf2,0x74,0x66,0x3f,0x01,0x9f,0xb1, + 0x18,0x9d,0xe5,0x4f,0xc1,0x74,0x96,0xff,0xb5,0x09,0xcc,0xd1,0xdb,0x15,0x8b,0x17, + 0x37,0x6b,0x36,0xc7,0x5c,0x66,0x43,0xcf,0x9f,0xa1,0xa9,0xdf,0xf3,0x16,0x2b,0xec, + 0x73,0xf0,0x47,0xcd,0xd3,0x9e,0xb6,0x64,0x2d,0xcc,0xe3,0x2e,0x5b,0x0d,0xaf,0xa5, + 0xf5,0x1f,0x8b,0x52,0xdc,0xb6,0xac,0x15,0xd3,0x41,0xce,0x6c,0xe8,0xe1,0x4b,0x7a, + 0x18,0x0a,0x3d,0x7c,0x05,0xee,0x3d,0x7c,0x0d,0xe6,0x3d,0x2c,0x84,0x1e,0xc4,0xcd, + 0x9b,0x2d,0xa0,0x3b,0x1f,0x7a,0xf8,0x06,0xed,0x2c,0xf4,0xf0,0x2d,0xb8,0xf7,0xb0, + 0x35,0x6b,0x61,0x1e,0xa7,0x1e,0xbc,0xd6,0x42,0xe8,0xa1,0x96,0xb5,0x62,0xe6,0xc8, + 0x99,0x0f,0x3d,0x7c,0x47,0x0f,0x7b,0x43,0x0f,0xdf,0x83,0x7b,0x0f,0x3f,0x80,0x79, + 0x0f,0x8b,0xa1,0x07,0x71,0xe7,0xcc,0x16,0xd1,0xd5,0xf3,0x01,0x74,0x7f,0x44,0xbb, + 0x96,0x5d,0xbb,0x3b,0xda,0xa3,0xc7,0x2e,0x86,0x3d,0xd6,0x89,0x5b,0x20,0xef,0x1c, + 0xfb,0xd1,0xdd,0x78,0x99,0xbb,0x25,0x5f,0xf7,0xe8,0x04,0x77,0x68,0xd8,0xf6,0xa7, + 0xfb,0xf3,0x1a,0x31,0x27,0xc2,0xb9,0x7c,0x9d,0xbe,0x46,0xc2,0xb9,0x3c,0x09,0xee, + 0xe7,0xf9,0x14,0xba,0x27,0xc9,0xd3,0x77,0xef,0x0d,0xf2,0x4e,0x93,0xa7,0x3b,0xf9, + 0x26,0xf8,0xd3,0xbc,0x87,0x19,0xb0,0xc7,0xad,0x8a,0xee,0xe1,0x5b,0xec,0xe1,0x14, + 0xdf,0xc0,0x99,0x50,0xef,0x27,0xea,0xed,0x0f,0xf5,0xce,0x83,0x7f,0x61,0x31,0xf2, + 0x7f,0x06,0xeb,0x0b,0x33,0xff,0x05,0xbc,0x9f,0x99,0x2f,0x85,0x99,0x8b,0xfb,0xd5, + 0x6c,0x89,0x39,0xea,0xf9,0x3e,0x8b,0x39,0xc8,0x5e,0x34,0x63,0xe7,0x96,0x82,0xce, + 0x6f,0xe8,0x8c,0x04,0x9d,0xdf,0xc1,0x5d,0x67,0x39,0xe8,0x88,0xbb,0x60,0xb6,0x4c, + 0xad,0x0b,0xe8,0x8c,0x06,0x1d,0xe7,0x96,0x83,0xce,0x1f,0xe8,0x8c,0x05,0x9d,0x3f, + 0xc1,0x5d,0x67,0x25,0xe8,0x88,0xbb,0x68,0xb6,0x42,0xad,0x8b,0xe8,0x34,0x82,0x8e, + 0x73,0x2b,0x41,0xe7,0x2f,0x74,0x06,0x82,0xce,0xdf,0xe0,0xae,0xb3,0x1a,0x74,0xc4, + 0x5d,0x32,0x5b,0xa5,0xd6,0x25,0x74,0xc6,0x83,0x8e,0x73,0xab,0x41,0xe7,0x32,0x3a, + 0x87,0x82,0xce,0x15,0x70,0xd7,0x59,0x0b,0x3a,0xe2,0xae,0x9a,0xad,0x51,0xeb,0x2a, + 0x3a,0x13,0x41,0xc7,0xb9,0xb5,0xa0,0xa3,0x4b,0x72,0x9e,0xff,0x6d,0xae,0x93,0x65, + 0x2d,0xdc,0x75,0x4a,0xd9,0x35,0x1d,0x71,0x05,0x33,0x61,0xaa,0xa5,0x67,0xe9,0x34, + 0x83,0x8e,0x73,0x5a,0x5d,0xa7,0x82,0xce,0xe1,0xa0,0xd3,0x99,0xb5,0x70,0xd7,0xa9, + 0x06,0x1d,0x71,0x5d,0x66,0x55,0x6a,0x75,0xa1,0x33,0x19,0x74,0x9c,0xab,0x06,0x9d, + 0x8d,0xe8,0x1c,0x09,0x3a,0x9b,0xb2,0x16,0xee,0x3a,0x9b,0x83,0x8e,0xb8,0x6e,0xb3, + 0xcd,0xd4,0xea,0x46,0x67,0x2a,0xe8,0x38,0xa7,0x75,0xcd,0x06,0x33,0x64,0xf6,0x3f, + 0x95,0x73,0xe7,0x94,0x5c,0x0c,0x00,0x00 }; // Generated from: @@ -104,6 +106,7 @@ constexpr uint8_t kBlitResolve_frag_00000000[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -177,7 +180,7 @@ constexpr uint8_t kBlitResolve_frag_00000000[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// vec4 colorValue = texture(sampler2D(color, blitSampler), srcImageCoords * params . invSrcExtent); +// vec4 colorValue = textureLod(sampler2D(color, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip); // // broadcastColor(colorValue); // diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000001.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000001.inc index ea82223c7f7..b5fd524cc46 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000001.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000001.inc @@ -10,75 +10,76 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000001[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x65,0x94,0x4b,0x6c,0x95,0x65, - 0x10,0x86,0xbf,0xef,0xdc,0xb5,0x40,0x41,0x8e,0x55,0x7a,0x57,0x6c,0x62,0xc0,0x54, - 0x16,0x6a,0x9a,0x18,0x0d,0x84,0x05,0x2c,0x08,0xd7,0xa4,0x5d,0x74,0x53,0x93,0x6e, - 0xce,0x42,0x48,0xa3,0xdd,0x74,0x01,0x26,0x27,0x86,0x4d,0x17,0x6c,0xba,0x41,0xc4, - 0x22,0x01,0x51,0x14,0xdc,0x19,0x05,0xa2,0x44,0xa1,0x81,0x14,0x68,0x34,0x05,0x1a, - 0x9a,0xa8,0x98,0x26,0x4a,0x9a,0x28,0x69,0xb4,0xb5,0x09,0xc2,0xcc,0xff,0x3f,0x43, - 0x27,0xc7,0x26,0xd3,0xef,0x9f,0xf7,0x9d,0x99,0x77,0xe6,0xbb,0x9c,0x6c,0x66,0x6d, - 0x31,0x84,0x18,0x9e,0x0c,0xa5,0xd0,0x1e,0x43,0xf2,0xb7,0x2a,0x64,0x82,0x7e,0xd6, - 0x85,0x42,0xb2,0x6e,0xd9,0xb6,0x67,0x5b,0xe7,0x3b,0xef,0xf6,0x77,0xbe,0xf2,0xea, - 0x06,0xe5,0x57,0x84,0x6c,0x12,0xa7,0x5c,0xbd,0x78,0x39,0x59,0xd5,0xde,0x7e,0xab, - 0xb2,0x57,0xf1,0xb2,0x58,0x8f,0x58,0x9f,0x58,0x45,0x6c,0x40,0x6c,0x48,0xac,0x2a, - 0x36,0x2c,0x36,0x22,0xb6,0x52,0x6a,0x68,0x4e,0x51,0xeb,0xcb,0x57,0x39,0xd1,0xd3, - 0x7a,0x21,0x6c,0x0d,0xf9,0xd0,0x9c,0xb6,0x12,0xd6,0xb2,0x1a,0x16,0xc1,0x4a,0x0e, - 0xcb,0x80,0xad,0x74,0x58,0x16,0xec,0x59,0x87,0xe5,0xc0,0x9a,0x1d,0x96,0x07,0x6b, - 0x77,0x58,0x01,0xec,0x05,0x87,0x15,0xc1,0x5e,0x74,0x58,0x09,0xec,0x25,0x87,0x3d, - 0x01,0xb6,0x21,0x99,0x2b,0xfb,0xb8,0x3f,0x9d,0x51,0xf7,0xa4,0x95,0x79,0xd4,0xef, - 0xc3,0x8f,0xf8,0x15,0x7c,0x8b,0x1f,0xc0,0xcf,0xe2,0x0f,0xe1,0xe7,0xf0,0xab,0xf8, - 0x79,0xfc,0x61,0xfc,0x02,0xfe,0x08,0xbe,0xed,0xf1,0x11,0x59,0x9f,0x77,0xfa,0xea, - 0x3f,0xe7,0xfc,0xd1,0x1a,0x7e,0x14,0x5e,0xfb,0x59,0x2d,0xff,0x33,0x89,0x9f,0x4d, - 0xfa,0xd1,0xef,0x06,0xf9,0x2a,0xb0,0x77,0xcf,0x48,0x7c,0x11,0xed,0x0c,0x7e,0x1d, - 0x7e,0x2e,0x89,0xc9,0x49,0x8d,0xc0,0xbd,0x0a,0xe1,0x75,0xfc,0x32,0xd8,0xd3,0xe2, - 0x37,0x52,0xcb,0xfc,0x26,0xfc,0x90,0xcc,0xb1,0xec,0xf1,0x39,0x98,0x35,0x62,0x05, - 0xd6,0x26,0x67,0xaa,0xd7,0xc2,0x79,0x34,0xa3,0xd7,0xc2,0x7e,0x28,0xb6,0x1e,0xbd, - 0x36,0xf4,0x34,0xbe,0x1d,0xae,0xe8,0xf8,0x0e,0xf4,0xcd,0x5f,0x07,0xaf,0xf1,0xeb, - 0x89,0x6f,0x4a,0xe6,0xc8,0x84,0x4e,0xe2,0xd4,0x7f,0xb9,0x26,0xaf,0x8b,0xfb,0x62, - 0xfe,0xe6,0x9a,0x3e,0xb6,0x33,0x87,0xd6,0xdd,0x01,0xd7,0x88,0xdf,0xcd,0x1d,0xb0, - 0x7d,0xeb,0xe6,0x7d,0x65,0x5d,0x7e,0x2f,0xfb,0x6e,0x7c,0x5f,0x0d,0xdf,0xcf,0x39, - 0x18,0x5f,0x81,0x37,0x7f,0xa0,0x26,0x7e,0x90,0xf7,0x64,0xfc,0x50,0x0d,0xbf,0x9f, - 0xb3,0x31,0xbe,0x5a,0xc3,0x1f,0x14,0xdb,0xe8,0xf8,0xe1,0x1a,0xfe,0x90,0xd8,0x7b, - 0x8e,0x1f,0x81,0x5f,0x23,0x93,0x1f,0x66,0x2f,0xf8,0x39,0xfa,0xdf,0xaa,0x7b,0xf2, - 0x01,0xdf,0x87,0xa9,0xa1,0xfe,0x11,0xb0,0x46,0xd9,0x89,0xa3,0xc4,0x7d,0x04,0x76, - 0x94,0x38,0xf5,0x47,0xc1,0x9a,0x44,0xf1,0x63,0x6a,0x58,0x5f,0xa7,0xe8,0x43,0xef, - 0xef,0xe7,0xf4,0xa1,0xfe,0x6b,0xf2,0xca,0x32,0xec,0x61,0x00,0x5b,0x10,0x44,0xdf, - 0xde,0x1b,0xdc,0xf5,0xaf,0xb8,0xcf,0xbb,0x04,0xd5,0xbc,0xaf,0xc1,0x82,0xc3,0xbe, - 0x01,0xd3,0x59,0x76,0x0a,0xa6,0x77,0xe9,0x1c,0xb1,0xca,0x6d,0x12,0x4c,0xf7,0xf5, - 0x3c,0x77,0xb5,0x8d,0xfa,0x1a,0x77,0x01,0xfc,0x7d,0xf2,0xbe,0x25,0xf7,0x82,0xcb, - 0xfb,0x8e,0xbc,0x0e,0x97,0x77,0x11,0xbc,0x4a,0xde,0xf7,0xe4,0x5e,0x24,0x4f,0xef, - 0xf1,0x0f,0xe4,0xad,0x23,0x4f,0xef,0xf0,0x25,0xf0,0xd3,0x12,0xa3,0x77,0xfb,0x32, - 0x98,0xde,0xed,0x79,0xd9,0x81,0x71,0x66,0x5b,0x94,0x78,0xe5,0xc6,0xc4,0xc6,0xd9, - 0x97,0x31,0x37,0xf3,0x15,0x34,0xf5,0xef,0x80,0xc4,0x2a,0x76,0x15,0x7c,0xb7,0x78, - 0xda,0xd3,0x9a,0x98,0x62,0x16,0xf7,0xaf,0xd4,0xb0,0x5a,0xba,0xfe,0x2d,0x51,0x1a, - 0xd7,0x12,0xd3,0x98,0x3c,0x39,0x63,0x6e,0x86,0x6b,0xcc,0xd0,0xe5,0x66,0xb8,0x0e, - 0x6e,0x33,0xdc,0x00,0xb3,0x19,0x26,0xdd,0x0c,0xca,0x4d,0x88,0x4d,0xa2,0x3b,0xe1, - 0x66,0xf8,0x11,0xed,0xe8,0x66,0xf8,0x09,0xdc,0x66,0x68,0x8e,0x29,0x66,0x71,0x3a, - 0x83,0xd5,0x9a,0x74,0x33,0xb4,0xc6,0x34,0x66,0x9c,0x9c,0x09,0x37,0xc3,0x4d,0x66, - 0xd8,0xec,0x66,0xb8,0x05,0x6e,0x33,0xdc,0x06,0xb3,0x19,0xa6,0xdd,0x0c,0xca,0x4d, - 0x89,0x4d,0xa3,0xab,0xdf,0x3b,0xd0,0xbd,0x83,0x76,0x6b,0x5c,0x7a,0x4b,0xda,0xa3, - 0xc5,0x4e,0xbb,0x1e,0xdb,0x88,0x9b,0x24,0x6f,0x8a,0x7e,0xf4,0xad,0x7c,0xc8,0x5b, - 0x53,0x5f,0xdf,0xd5,0x31,0xde,0x54,0xb7,0xf4,0xa7,0xef,0xe9,0x38,0x31,0xc7,0xdc, - 0xbd,0x3c,0xc1,0x5c,0xbd,0xee,0x5e,0x9e,0x04,0xb7,0xfb,0xfc,0x09,0xba,0x27,0xc9, - 0xd3,0xdf,0xc1,0x4f,0xc9,0x3b,0x45,0x9e,0xbe,0xd1,0xcf,0xc0,0xf7,0x71,0x0e,0xa7, - 0xc1,0xec,0xac,0xbe,0xa0,0x96,0x7f,0x77,0x67,0xc0,0xd2,0x77,0x57,0x48,0xde,0xf6, - 0x59,0x62,0xcf,0x50,0xa3,0x47,0x62,0xf5,0x1d,0x7f,0xc9,0x0c,0x67,0x5d,0x1f,0x3f, - 0xd3,0xc7,0x76,0xd7,0xc7,0x2f,0xe0,0x63,0x12,0xa3,0xfe,0xaf,0x60,0x6d,0xee,0xac, - 0xee,0x82,0x77,0x70,0x56,0x33,0xee,0xac,0x94,0xfb,0x4d,0x6c,0x86,0xfd,0xd7,0xef, - 0x37,0x25,0xa6,0x87,0x1e,0xf4,0x6c,0x8c,0x9b,0x71,0x3a,0xbf,0xa3,0xd3,0xeb,0x74, - 0xfe,0x00,0x37,0x9d,0x59,0xa7,0xa3,0xdc,0x3d,0xb1,0x59,0x6a,0xdd,0x43,0xa7,0xcf, - 0xe9,0x18,0x37,0xeb,0x74,0xfe,0x44,0xa7,0xdf,0xe9,0xfc,0x05,0x6e,0x3a,0x73,0x4e, - 0x47,0xb9,0xfb,0x62,0x73,0xd4,0xba,0x8f,0x4e,0xc5,0xe9,0x18,0x37,0xe7,0x74,0xfe, - 0x41,0xa7,0xcb,0xe9,0xcc,0x83,0x9b,0xce,0xa2,0xd3,0x99,0x4f,0x6a,0x84,0x04,0xd3, - 0x5a,0x0b,0xe8,0x0c,0x38,0x1d,0xe3,0x16,0x9d,0xce,0x03,0x74,0x06,0x9d,0xce,0x7f, - 0xe0,0xa6,0x13,0xe3,0x92,0x8e,0x72,0x0f,0xf5,0xce,0xc4,0xb4,0xd6,0x43,0x74,0x86, - 0x9c,0x8e,0x71,0x31,0x2e,0xe9,0xe4,0x62,0xaa,0xb3,0xdf,0xe9,0xe4,0x63,0x8a,0x9b, - 0x4e,0xc9,0xe9,0x28,0x57,0x10,0x2b,0x51,0x4b,0xbf,0x55,0xa7,0xea,0x74,0x8c,0x2b, - 0x39,0x9d,0x3a,0x74,0x0e,0x3a,0x9d,0x65,0x31,0xc5,0x4d,0xa7,0xde,0xe9,0x28,0xb7, - 0x5c,0xac,0x9e,0x5a,0xcb,0xd1,0x19,0x76,0x3a,0xc6,0xd5,0x3b,0x9d,0xa7,0xd0,0x39, - 0xe4,0x74,0x56,0xc7,0x14,0x37,0x9d,0x06,0xa7,0xa3,0x5c,0x59,0xac,0x81,0x5a,0x65, - 0x74,0x46,0x9c,0x8e,0x71,0xba,0x3e,0x90,0x57,0xd9,0x25,0xf6,0x08,0x97,0x53,0x2f, - 0x72,0x8c,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x65,0x95,0x4d,0x68,0x9d,0x55, + 0x10,0x86,0xcf,0x77,0xef,0xcd,0xbd,0x49,0x2f,0xb6,0x31,0xa6,0x8d,0xf9,0xa9,0x69, + 0x1a,0x03,0x92,0x4a,0xec,0xa2,0x4a,0x40,0x14,0xa5,0x0b,0x5d,0x94,0xd6,0x1f,0x48, + 0x85,0x6c,0x22,0x64,0x93,0x85,0x4a,0x50,0x37,0x59,0x54,0xe1,0x22,0xdd,0x64,0xd1, + 0x4d,0x36,0xb5,0xd6,0x54,0xb1,0xfe,0xd4,0xb6,0x5a,0x77,0xe2,0x4f,0xd1,0x62,0x35, + 0x54,0xa2,0x06,0x25,0x6a,0x31,0x60,0x55,0x02,0x5a,0x02,0x5a,0xa3,0x6d,0x09,0x38, + 0xef,0x77,0x9f,0x69,0x87,0x6b,0x60,0x7a,0xbe,0x79,0xdf,0x99,0x79,0xcf,0x9c,0x33, + 0xe7,0xb6,0x58,0xe8,0xaf,0xa4,0x94,0xa5,0x75,0xa9,0x39,0xf5,0x67,0x29,0xff,0xbb, + 0x31,0x15,0x92,0x3e,0xab,0xa9,0x9c,0xaf,0x0f,0xec,0x7a,0x74,0xd7,0xd0,0xd3,0xcf, + 0x8c,0x0f,0xed,0xb8,0x73,0xbb,0xf8,0xf5,0xa9,0x98,0xc7,0x89,0xdb,0x60,0x5e,0xc9, + 0x56,0xd9,0x13,0x8f,0x4f,0x3c,0x29,0xbc,0xdd,0x6c,0xaf,0xd9,0x98,0xd9,0x84,0xd9, + 0xa4,0xd9,0x94,0x59,0xcd,0x6c,0xda,0x6c,0xc6,0xac,0xd5,0x6a,0x28,0xa7,0xa2,0xfa, + 0xf6,0xd5,0x9e,0xeb,0xa9,0x5e,0x4a,0x0f,0xa6,0xa6,0xd4,0x53,0xdf,0x4a,0xea,0x67, + 0x75,0x2c,0x03,0x6b,0x0e,0x58,0x01,0xac,0x35,0x60,0x45,0xb0,0x9b,0x03,0x56,0x02, + 0xeb,0x09,0x58,0x13,0xd8,0x96,0x80,0x95,0xc1,0x6e,0x0d,0x58,0x05,0xec,0xb6,0x80, + 0x35,0x83,0xdd,0x1e,0xb0,0x16,0xb0,0xed,0x01,0x5b,0x07,0xb6,0x23,0xef,0xb5,0x78, + 0x6d,0xcf,0xea,0x5b,0xe7,0x74,0x0b,0x3d,0xca,0x1f,0xc3,0xcf,0xf0,0x27,0xf0,0x3d, + 0x7e,0x12,0xbf,0x88,0x3f,0x85,0x5f,0xc2,0xaf,0xe1,0x37,0xe1,0x4f,0xe3,0x97,0xf1, + 0x67,0xf0,0xfd,0xdc,0x0f,0xd9,0xba,0x35,0xe8,0xcb,0xef,0x0b,0xfe,0x6c,0x03,0x3f, + 0x0b,0xaf,0xfd,0xdc,0x64,0xff,0x16,0x72,0xbf,0x98,0xef,0x47,0xdf,0x9b,0xec,0xab, + 0xcc,0x79,0x76,0x58,0x7c,0x05,0xed,0x02,0x7e,0x15,0xbf,0x94,0xc7,0x94,0xac,0x46, + 0x62,0xd6,0x52,0xba,0x1b,0xbf,0x1d,0x6c,0xa3,0xf9,0x5d,0xd4,0x72,0xbf,0x1b,0x3f, + 0xe5,0x7d,0xdc,0x70,0xed,0x6e,0xdc,0xba,0x82,0x95,0x59,0xbb,0x83,0x49,0x73,0x33, + 0xf7,0xd4,0x83,0xe6,0x66,0xce,0x44,0xd8,0x36,0x34,0x7b,0xd1,0x54,0xfc,0x16,0xb8, + 0x4a,0xe0,0x07,0xd8,0x83,0xfb,0x83,0xcc,0x83,0xe2,0xb7,0x11,0xdf,0x9d,0xf7,0x52, + 0x48,0x43,0xc4,0xc9,0xbf,0xa3,0x21,0x6f,0xb8,0x41,0x77,0x27,0xf3,0xe2,0xfe,0x6e, + 0x74,0x55,0x77,0x0f,0xb1,0x5d,0xf8,0x23,0xcc,0x81,0x9f,0xdd,0x08,0xef,0xae,0x18, + 0xf2,0x47,0x39,0x7b,0xe7,0xc7,0x1a,0xf8,0x71,0xee,0xc2,0xf9,0x09,0x78,0xf7,0x27, + 0x1b,0xe2,0x9f,0xe5,0x9d,0x39,0x3f,0xd5,0xc0,0xef,0xe3,0x7e,0x9c,0xaf,0x35,0xf0, + 0xfb,0xcd,0xee,0x0b,0xfc,0x74,0x03,0x7f,0xc0,0xec,0xf9,0xc0,0xcf,0xc0,0x77,0x5a, + 0xe7,0x07,0xb9,0x53,0x7e,0xa6,0xfe,0xb7,0xea,0x4c,0x5e,0xe4,0xfb,0x20,0x35,0xe4, + 0x1f,0x02,0xeb,0xb2,0x93,0x38,0x4c,0xdc,0xcb,0x60,0x87,0x89,0x93,0x3f,0x0b,0xd6, + 0x6d,0x8a,0xaf,0x50,0x43,0x33,0x7b,0x0c,0xdd,0xb8,0xcf,0x93,0xf8,0x77,0xd9,0x4b, + 0x2b,0x70,0x86,0x09,0xec,0x5f,0x43,0xf4,0xfe,0xee,0x61,0xde,0xdf,0x67,0xa6,0x1f, + 0x36,0x54,0x75,0x3e,0x00,0x4b,0x01,0xfb,0x10,0x4c,0xbd,0x3c,0x64,0x98,0xee,0xfc, + 0x23,0x62,0xc5,0xdd,0x6f,0x98,0xce,0xf5,0x63,0x66,0xb5,0x97,0xfa,0x8a,0x3b,0x0d, + 0xfe,0x02,0x79,0x9f,0x90,0x7b,0x3a,0xe4,0x7d,0x4a,0xde,0x40,0xc8,0x3b,0x03,0x5e, + 0x23,0xef,0x33,0x72,0xcf,0x90,0xa7,0x39,0x3e,0x4b,0xde,0x20,0x79,0x9a,0xe1,0xcf, + 0xc1,0x8f,0x59,0x8c,0x66,0xfb,0x0b,0x30,0xcd,0xf6,0x3f,0x76,0x02,0xf3,0xf4,0x76, + 0xc5,0xe2,0xc5,0xcd,0x99,0xcd,0x73,0x2e,0x73,0xa1,0xe7,0x73,0x68,0xea,0xef,0x39, + 0x8b,0x15,0xf6,0x25,0xf8,0x23,0xe6,0x69,0x4f,0x3d,0x59,0x1d,0xf3,0xb8,0xcb,0x56, + 0xc3,0x6b,0x69,0xfd,0xdb,0xa2,0xf2,0xf7,0x91,0xd5,0x63,0x9a,0xc8,0x99,0x0b,0x3d, + 0x7c,0x45,0x0f,0xc3,0xa1,0x87,0xaf,0xc1,0xbd,0x87,0x6f,0xc0,0xbc,0x87,0xc5,0xd0, + 0x83,0xb8,0x05,0xb3,0x45,0x74,0x17,0x42,0x0f,0xdf,0xa2,0x9d,0x85,0x1e,0xbe,0x03, + 0xf7,0x1e,0x7a,0xb3,0x3a,0xe6,0x71,0xea,0xc1,0x6b,0x2d,0x86,0x1e,0xfa,0xb2,0x7a, + 0xcc,0x3c,0x39,0x0b,0xa1,0x87,0xef,0xe9,0x61,0x67,0xe8,0xe1,0x07,0x70,0xef,0xe1, + 0x47,0x30,0xef,0x61,0x29,0xf4,0x20,0xee,0xbc,0xd9,0x12,0xba,0xfa,0xde,0x83,0xee, + 0x4f,0x68,0xf7,0x65,0xd7,0xdf,0x92,0xf6,0xe8,0xb1,0x4b,0x61,0x8f,0x5b,0x89,0x5b, + 0x24,0xef,0x3c,0xfb,0xd1,0x5b,0x79,0x89,0xb7,0x26,0x5f,0xef,0xea,0x08,0x6f,0x6a, + 0xc4,0xf6,0xa7,0xf7,0xf4,0x2a,0x31,0x47,0xc2,0x5c,0xbe,0x46,0x5f,0xa3,0x61,0x2e, + 0x8f,0x82,0xfb,0x3c,0xbf,0x8e,0xee,0x51,0xf2,0xf4,0x3b,0xf8,0x06,0x79,0xe3,0xe4, + 0xe9,0x4d,0xbe,0x09,0xfe,0x14,0xf7,0xf0,0x16,0x98,0xdf,0xd5,0xdb,0xd4,0x8a,0xef, + 0xee,0x38,0x58,0xfd,0xdd,0x95,0xf3,0xb7,0x7e,0x82,0xd8,0xe3,0xd4,0x70,0xcd,0x77, + 0xd0,0x3c,0x19,0x34,0xdf,0x05,0x77,0xcd,0x53,0x60,0x8f,0xd9,0xce,0xf5,0xf6,0xdf, + 0xa3,0xef,0x13,0xfc,0x0e,0x9f,0x0a,0xf5,0x7e,0xa6,0xde,0xee,0x50,0xef,0x02,0xf8, + 0x59,0x8b,0x91,0xff,0x0b,0x58,0x6f,0xb8,0xe7,0x5f,0xc1,0x07,0xb8,0xe7,0xe5,0x70, + 0xcf,0xe2,0x7e,0x33,0x5b,0xe6,0xee,0xf4,0x7d,0xaf,0xc5,0xec,0x65,0x2f,0xba,0x57, + 0xe7,0x96,0x83,0xce,0xef,0xe8,0x8c,0x06,0x9d,0x3f,0xc0,0x5d,0x67,0x25,0xe8,0x88, + 0xbb,0x68,0xb6,0x42,0xad,0x8b,0xe8,0x8c,0x05,0x1d,0xe7,0x56,0x82,0xce,0x9f,0xe8, + 0x8c,0x07,0x9d,0xbf,0xc0,0x5d,0x67,0x35,0xe8,0x88,0xbb,0x64,0xb6,0x4a,0xad,0x4b, + 0xe8,0x4c,0x04,0x1d,0xe7,0x56,0x83,0xce,0x65,0x74,0x06,0x83,0xce,0x15,0x70,0xd7, + 0x59,0x0b,0x3a,0xe2,0xae,0x9a,0xad,0x51,0xeb,0x2a,0x3a,0x93,0x41,0xc7,0xb9,0xb5, + 0xa0,0xa3,0xc1,0xb9,0xc0,0xff,0x8b,0xae,0x93,0x65,0x75,0xdc,0x75,0x4a,0xd9,0x75, + 0x1d,0x71,0x05,0x33,0x61,0xaa,0xa5,0x6f,0xe9,0x4c,0x05,0x1d,0xe7,0xb4,0xba,0x4e, + 0x05,0x9d,0x7d,0x41,0xa7,0x39,0xab,0xe3,0xae,0x53,0x0d,0x3a,0xe2,0x5a,0xcc,0xaa, + 0xd4,0x6a,0x41,0xa7,0x16,0x74,0x9c,0xab,0x06,0x9d,0xf5,0xe8,0xec,0x0f,0x3a,0x1b, + 0xb2,0x3a,0xee,0x3a,0x6d,0x41,0x47,0x5c,0xab,0x59,0x1b,0xb5,0x5a,0xd1,0x99,0x0e, + 0x3a,0xce,0xb5,0x05,0x9d,0x8d,0xe8,0x1c,0x08,0x3a,0x9b,0xb2,0x3a,0xee,0x3a,0x9d, + 0x41,0x47,0x5c,0x87,0x59,0x27,0xb5,0x3a,0xd0,0x99,0x09,0x3a,0xce,0x69,0x5d,0xb3, + 0x0b,0x18,0x36,0xfb,0x0f,0xed,0xcb,0xaf,0x20,0xe0,0x0c,0x00,0x00 }; // Generated from: @@ -107,6 +108,7 @@ constexpr uint8_t kBlitResolve_frag_00000001[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -180,7 +182,7 @@ constexpr uint8_t kBlitResolve_frag_00000001[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// vec4 colorValue = texture(sampler2DArray(color, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)); +// vec4 colorValue = textureLod(sampler2DArray(color, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip); // // broadcastColor(colorValue); // diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000002.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000002.inc index 2a4eaabc6c8..60622985575 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000002.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000002.inc @@ -10,75 +10,76 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000002[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4d,0x68,0x5d,0x55, - 0x14,0x85,0xcf,0x79,0xff,0x26,0xb1,0x69,0x30,0x49,0x9b,0x9f,0xc6,0x6a,0x23,0x54, - 0x2c,0xa5,0x04,0x15,0x41,0x2a,0x75,0x64,0x84,0x07,0x92,0x08,0x9d,0x64,0x10,0x84, - 0x37,0x29,0xc4,0x52,0xd0,0x0c,0x3a,0x09,0x9a,0x49,0x06,0x05,0xc9,0x44,0x69,0x33, - 0xd0,0xd6,0x0a,0x45,0x5a,0x2d,0x9d,0x55,0x2d,0xfe,0x14,0x25,0x6a,0x50,0xa2,0x06, - 0x03,0xfe,0x94,0x80,0x96,0x80,0x96,0x80,0x96,0x68,0x53,0x2a,0x75,0xaf,0x7b,0xbf, - 0x93,0x6c,0xde,0x83,0xcd,0xbd,0x7b,0xad,0x7d,0xf6,0xda,0xeb,0x9c,0x73,0x5f,0xb1, - 0xb0,0xa7,0x1a,0x42,0x0c,0x2d,0xa1,0x16,0x76,0xc5,0x90,0xfd,0x3a,0x42,0x21,0xe8, - 0xb5,0x35,0x54,0xb2,0xe7,0x33,0xf5,0xe7,0xeb,0xfb,0x5f,0x7a,0xb9,0xb1,0xff,0xd1, - 0xc7,0x0e,0x88,0xdf,0x16,0x8a,0x59,0x9d,0xb8,0x76,0xcb,0x4a,0xf6,0x54,0xbc,0xf8, - 0xc2,0x91,0xa3,0xc2,0xbb,0x2c,0x46,0x2d,0xc6,0x2c,0x1a,0x16,0x13,0x16,0x93,0x16, - 0x53,0x16,0x33,0x16,0xb3,0x16,0xdb,0xad,0x87,0xd6,0x54,0xd5,0xdf,0xde,0xba,0x32, - 0x3d,0xf5,0x0b,0x61,0x38,0x94,0x43,0x5f,0x3e,0x4a,0xd8,0xc3,0x33,0x61,0x11,0xac, - 0xe6,0xb0,0x02,0xd8,0x76,0x87,0x15,0xc1,0x76,0x3a,0xac,0x04,0xd6,0xef,0xb0,0x32, - 0xd8,0x6e,0x87,0x55,0xc0,0x06,0x1d,0x56,0x05,0xdb,0xeb,0xb0,0x1a,0xd8,0x3e,0x87, - 0xdd,0x03,0x76,0x20,0xf3,0x55,0xdc,0x9c,0x4f,0x1e,0xb5,0x27,0x03,0xf8,0x51,0x3e, - 0x46,0x1e,0xc9,0x1b,0xe4,0xa9,0x7e,0x82,0xbc,0x48,0x3e,0x49,0x5e,0x22,0x9f,0x22, - 0x2f,0x93,0xcf,0x90,0x57,0xc8,0x67,0xc9,0xd3,0x1e,0x9f,0xb5,0xe7,0x83,0x4e,0x5f, - 0xf9,0x03,0xe4,0xf7,0x99,0x6a,0x21,0xcb,0x8b,0x99,0x5e,0x21,0x3b,0xc7,0x52,0xd6, - 0x6b,0x37,0x33,0xee,0xb0,0xbc,0x4a,0x7f,0xf1,0xdd,0x56,0xd9,0x0a,0x2f,0xae,0x8d, - 0x33,0x2c,0x65,0x58,0x29,0x74,0xb2,0x4e,0xf8,0x93,0xe4,0x5d,0xae,0x57,0x37,0xf5, - 0x49,0xab,0x97,0x5e,0x21,0x9b,0xbb,0x6d,0x73,0xdf,0xbb,0x89,0x0a,0xd1,0xca,0xb3, - 0xd7,0x85,0xf4,0xfa,0xd9,0xff,0x3e,0xf4,0x94,0xef,0x02,0x7b,0x04,0x2f,0x69,0xff, - 0x55,0x7f,0x3f,0x5c,0xd5,0xf1,0x83,0xe4,0xe2,0x1f,0x82,0x57,0xff,0x4e,0x9b,0x72, - 0x2f,0x75,0xca,0x1f,0xa6,0x4f,0x5a,0x37,0xc4,0x7d,0x48,0xf9,0xc1,0x26,0xdd,0x61, - 0x66,0x56,0xdf,0x67,0xe1,0x2a,0x8e,0xaf,0xb3,0x2f,0xe2,0x47,0x38,0xf3,0xb4,0x6f, - 0x23,0x7c,0x4f,0x45,0x57,0x7f,0x98,0x7d,0x4b,0xfc,0x58,0x13,0x3f,0xce,0x39,0x24, - 0xbe,0x01,0x9f,0xf2,0x89,0xa6,0xfa,0x63,0x7c,0x3f,0x89,0x9f,0x6c,0xe2,0x8f,0x73, - 0x36,0x89,0x9f,0x6a,0xe2,0xa7,0x2d,0x0e,0x39,0x7e,0xa6,0x89,0x3f,0x61,0xf1,0x8a, - 0xe3,0x67,0x1d,0xaf,0xf3,0x7c,0x9d,0xfd,0xdc,0x67,0xbb,0x2f,0xdf,0x6f,0x80,0xf9, - 0xe8,0xb1,0x5d,0x3b,0xc3,0xf9,0xf3,0x57,0xb5,0xf9,0x3f,0x14,0xdd,0xb9,0xbe,0xcd, - 0xfb,0x19,0xf4,0x94,0x9f,0x6d,0x3a,0xaf,0x0b,0x7c,0x37,0xaa,0x7f,0x8f,0xf3,0x50, - 0xdf,0xc7,0x0d,0x2d,0xb0,0x77,0x81,0x19,0x6f,0x19,0x52,0xce,0xce,0x34,0xbf,0xe3, - 0x97,0xb9,0xc7,0xcf,0xd9,0xac,0xba,0x97,0x1f,0x80,0x5d,0x76,0xf3,0x1c,0xe5,0x5b, - 0xf9,0x10,0xfe,0x69,0xeb,0xa0,0xfb,0xf6,0x11,0x77,0x72,0x80,0x7e,0xaa,0xb9,0x02, - 0x3e,0x6d,0x35,0xca,0x3f,0x66,0xdd,0x15,0xd6,0xe9,0x1e,0x7e,0xc2,0xba,0x41,0xd6, - 0xe9,0x0e,0x7e,0x0a,0x7e,0xde,0x6a,0x74,0x37,0x3f,0x03,0xd3,0xdd,0xfc,0xd7,0x26, - 0x9f,0x67,0x9e,0xdb,0x56,0x2f,0xee,0xaa,0xc5,0x3c,0x7e,0xf4,0x3e,0x62,0xeb,0xb4, - 0x17,0x9f,0xa3,0x19,0xb2,0x73,0xcd,0xf7,0xe7,0x0b,0xf0,0x51,0xcb,0x34,0x53,0x67, - 0xcc,0xb1,0x54,0xb7,0x61,0x3d,0x52,0x2f,0x3d,0xd7,0xad,0x4a,0x75,0x3b,0x63,0x5e, - 0x53,0x66,0xcd,0x55,0xe7,0xe1,0x4b,0x3c,0x0c,0x39,0x0f,0x5f,0x81,0x27,0x0f,0x5f, - 0x83,0x25,0x0f,0x8b,0xce,0x83,0xb8,0x05,0x8b,0x45,0x74,0x17,0x9c,0x87,0x6f,0xd0, - 0x8e,0xce,0xc3,0xb7,0xe0,0xc9,0xc3,0x8e,0x98,0x63,0xa9,0x4e,0x1e,0x52,0xaf,0x45, - 0xe7,0xa1,0x27,0xe6,0x35,0xf3,0xac,0x59,0x70,0x1e,0xbe,0xc3,0xc3,0x41,0xe7,0xe1, - 0x7b,0xf0,0xe4,0xe1,0x07,0xb0,0xe4,0x61,0xd9,0x79,0x10,0xb7,0x64,0xb1,0x8c,0xee, - 0x12,0xf7,0x48,0xba,0x3f,0xa2,0xdd,0x13,0xb7,0xee,0xb3,0x66,0x4c,0xb5,0xcb,0x6e, - 0xc6,0x5e,0xea,0x16,0x59,0xb7,0x44,0xed,0x49,0x6a,0x4f,0x52,0xab,0xfb,0xda,0x1f, - 0xf3,0xef,0x49,0xeb,0xdf,0xb5,0x38,0x05,0xa7,0x3d,0xea,0x8b,0xf9,0x5d,0x5c,0xce, - 0xe6,0xcf,0x39,0x79,0xd5,0x7f,0xd4,0x9b,0x78,0x1d,0xc7,0xab,0xea,0xdf,0x02,0xbf, - 0x84,0xd7,0xd3,0xf4,0x10,0xfe,0x8f,0xd5,0xcc,0xd1,0x23,0xf9,0x3d,0x4d,0x3e,0xc7, - 0x5c,0xa7,0xe8,0xa5,0x6f,0xf3,0x1d,0xbe,0xcb,0x71,0xe6,0x3c,0x07,0x26,0x6f,0x87, - 0xe8,0xfb,0xaa,0xe9,0xb4,0x31,0xb7,0x7c,0x9c,0xcb,0xfe,0x47,0xf2,0x33,0x3f,0x4f, - 0x4d,0xbd,0xc9,0xfb,0x1c,0x1e,0xf4,0x5d,0xbf,0x8f,0x87,0x0b,0xe8,0xea,0x1b,0xbf, - 0x08,0xfe,0x1a,0xbd,0x2f,0xd1,0xfb,0xa2,0xf3,0xfe,0x13,0xeb,0x86,0x9d,0xf7,0x9f, - 0xc1,0xe7,0xd1,0xff,0x05,0xac,0xee,0xce,0xfe,0x57,0xf0,0x01,0xce,0x7e,0xc5,0xed, - 0x85,0xb8,0x6b,0x16,0x2b,0xcc,0xa9,0xf7,0xa7,0xac,0x66,0x94,0x19,0xe4,0x21,0x71, - 0x2b,0x4e,0xe7,0x37,0x74,0x0e,0x3b,0x9d,0xdf,0xc1,0x93,0xce,0xaa,0xd3,0x11,0x77, - 0xdd,0x62,0x95,0x5e,0xd7,0xd1,0x19,0x73,0x3a,0x89,0x5b,0x75,0x3a,0x7f,0xa0,0x33, - 0xee,0x74,0xfe,0x04,0x4f,0x3a,0x6b,0x4e,0x47,0xdc,0x0d,0x8b,0x35,0x7a,0xdd,0x40, - 0xa7,0xe1,0x74,0x12,0xb7,0xe6,0x74,0xfe,0x42,0x67,0xc8,0xe9,0xfc,0x0d,0x9e,0x74, - 0xd6,0x9d,0x8e,0xb8,0x9b,0xd9,0x9d,0xcd,0x7b,0xdd,0x44,0x67,0xc2,0xe9,0x24,0x6e, - 0xdd,0xe9,0xdc,0x42,0xe7,0x98,0xd3,0xd9,0x00,0x4f,0x3a,0x77,0x9c,0xce,0x46,0xf6, - 0x0c,0x19,0xa6,0x5e,0xb7,0xd1,0x99,0x74,0x3a,0x89,0xbb,0xe3,0x74,0xee,0xa2,0x73, - 0xdc,0xe9,0xe8,0x03,0xbe,0xeb,0x74,0x8a,0x71,0x4b,0x47,0x5c,0xb4,0x10,0xa6,0x5e, - 0x7a,0x97,0xce,0x94,0xd3,0x49,0x5c,0x31,0x6e,0xe9,0x54,0x62,0xae,0x33,0xed,0x74, - 0xaa,0x31,0xc7,0x93,0x4e,0x8b,0xd3,0x11,0x57,0xb3,0x68,0xa1,0x57,0x0d,0x9d,0x19, - 0xa7,0x93,0xb8,0x16,0xa7,0x73,0x2f,0x3a,0x27,0x9c,0xce,0xb6,0x98,0xe3,0x49,0xa7, - 0xc3,0xe9,0x88,0x6b,0xb7,0xe8,0xa0,0x57,0x3b,0x3a,0xb3,0x4e,0x27,0x71,0x7a,0xfe, - 0x67,0x1b,0xf0,0x84,0xc5,0xff,0xae,0xde,0xc7,0xe7,0x7c,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x5f,0x68,0x97,0x65, + 0x14,0xc7,0x9f,0xf7,0xf7,0x77,0xf3,0x67,0xba,0xcc,0x2d,0xdd,0xe6,0xb2,0x5c,0x60, + 0x24,0x22,0x62,0x11,0x84,0x61,0x57,0x2d,0x18,0xc4,0x16,0x78,0xb3,0x8b,0x11,0xec, + 0x26,0x58,0x22,0xd4,0x2e,0xba,0x19,0xb5,0x9b,0x5d,0x08,0xb1,0x9b,0x42,0x77,0x61, + 0x69,0x06,0x52,0x5a,0xd6,0x9d,0x95,0xf4,0x47,0xaa,0x55,0xa3,0x58,0x35,0x1a,0xa8, + 0xc5,0xa0,0x64,0x50,0x32,0x28,0x5b,0xa9,0x0c,0x3a,0xdf,0xf7,0xfd,0x9c,0x79,0xf8, + 0x0d,0x0e,0xef,0x7b,0xbe,0xdf,0xf3,0x9c,0xef,0xf3,0x7d,0xce,0xf3,0xfe,0x56,0x2e, + 0xed,0xa8,0xa7,0x94,0xa5,0x75,0xa9,0x25,0xf5,0x64,0x29,0xff,0xbb,0x33,0x95,0x92, + 0x5e,0x1b,0xa9,0x96,0x3f,0x9f,0xe8,0x7f,0xba,0x7f,0xf7,0xf3,0x2f,0x8c,0xec,0xde, + 0xf7,0xd0,0x1e,0xf1,0x1b,0x52,0x39,0xaf,0x13,0xb7,0xd1,0xb2,0x8a,0x3d,0x15,0xcf, + 0x3d,0xf3,0xec,0x21,0xe1,0xed,0x16,0x83,0x16,0x43,0x16,0x23,0x16,0xa3,0x16,0x63, + 0x16,0xe3,0x16,0x93,0x16,0x53,0x16,0x6d,0xd6,0x43,0x6b,0xea,0xea,0x6f,0x6f,0xed, + 0xb9,0x9e,0xfa,0xa5,0xd4,0x97,0xaa,0xa9,0xab,0xd8,0x4a,0xda,0xc1,0xd3,0xb1,0x0c, + 0xac,0x25,0x60,0x25,0xb0,0xb6,0x80,0x95,0xc1,0xb6,0x04,0xac,0x02,0xd6,0x1d,0xb0, + 0x2a,0xd8,0xf6,0x80,0xd5,0xc0,0x7a,0x03,0x56,0x07,0xdb,0x19,0xb0,0x16,0xb0,0x5d, + 0x01,0x6b,0x05,0xdb,0x13,0xb0,0x75,0x60,0xfb,0x72,0xaf,0xe5,0xb5,0x3d,0xcb,0xb7, + 0xce,0xa9,0x07,0x8f,0xca,0x87,0xc8,0x33,0xf2,0x11,0x72,0xaf,0x1f,0x25,0x2f,0x93, + 0x8f,0x91,0x57,0xc8,0xc7,0xc9,0xab,0xe4,0x93,0xe4,0x35,0xf2,0x29,0x72,0x3f,0xf7, + 0x53,0xf6,0xbc,0x2f,0xe8,0x2b,0xbf,0x97,0xfc,0x2e,0x53,0x2d,0xe5,0x79,0x39,0xd7, + 0x2b,0xe5,0xb3,0xad,0xe4,0xbd,0xb6,0xb3,0xc7,0xbb,0x2d,0xaf,0xd3,0x5f,0x7c,0x87, + 0x55,0x36,0xe0,0xc5,0xad,0x67,0xae,0x95,0x1c,0xab,0xa4,0xcd,0xac,0x13,0xfe,0x28, + 0x79,0x7b,0xe8,0xd5,0x41,0xbd,0x6b,0x75,0xd2,0x2b,0xe5,0xfb,0xbe,0x63,0x6d,0x16, + 0x1d,0x44,0x2d,0x44,0x83,0x67,0x67,0x08,0x69,0x76,0x33,0x97,0x2e,0x34,0x95,0x6f, + 0x03,0x7b,0x10,0x3f,0x3e,0x03,0xd5,0xdf,0x03,0x57,0x0f,0x7c,0x2f,0xf3,0x16,0x7f, + 0x3f,0xbc,0xfa,0x6f,0xb6,0x9d,0xee,0xa4,0x4e,0xf9,0x03,0xf4,0xf1,0x75,0x7b,0x9b, + 0x74,0xf6,0x73,0x1f,0x3c,0xef,0x43,0x47,0x7d,0x9f,0xa4,0xb6,0x16,0xf8,0x7e,0xce, + 0x46,0xfc,0x00,0x73,0xf7,0xb3,0x1b,0xe0,0x3b,0x2b,0x87,0xfa,0x83,0x9c,0x9d,0xf3, + 0x43,0x4d,0xfc,0x30,0xb3,0x70,0x7e,0x04,0xde,0xf3,0xd1,0xa6,0xfa,0xc3,0x7c,0x57, + 0xce,0x8f,0x35,0xf1,0x2f,0x32,0x1f,0xe7,0xc7,0x9b,0xf8,0x09,0x8b,0x03,0x81,0x9f, + 0x6c,0xe2,0x8f,0x58,0xbc,0x14,0xf8,0xa9,0xc0,0x6b,0x9e,0xaf,0x72,0x9e,0xbb,0xec, + 0x94,0xe4,0xfb,0x35,0xb0,0x18,0xde,0xeb,0x38,0xf7,0x7e,0xab,0x9d,0xe2,0x49,0xee, + 0x03,0x3f,0x69,0x6b,0xbf,0x57,0x59,0x98,0xf3,0x9b,0xbc,0x9f,0x44,0x5f,0xf9,0xa9, + 0xa6,0xf9,0x9d,0x65,0x1e,0xaa,0x7f,0x97,0xf9,0xa8,0xef,0xc3,0xa6,0x54,0xe2,0x2c, + 0x13,0x7b,0xfe,0xcf,0x90,0x6a,0x3e,0xe3,0xe2,0xde,0x9f,0xe7,0x6e,0x3f,0x65,0x7b, + 0xd7,0x5d,0xfd,0x10,0xec,0x7c,0xd8,0xcf,0x21,0xbe,0x9f,0x8f,0xe0,0x1f,0xb7,0x0e, + 0xba,0x7f,0x1f,0x73,0x47,0x7b,0xe8,0xa7,0x9a,0x0b,0xe0,0x13,0x56,0xa3,0xfc,0x13, + 0xd6,0x5d,0x60,0x9d,0xee,0xe5,0xa7,0xac,0xeb,0x65,0x9d,0xee,0xe4,0x67,0xe0,0xef, + 0x58,0x8d,0xee,0xea,0xe7,0x60,0xba,0xab,0xff,0xda,0xce,0x67,0xd8,0xcf,0x4d,0xab, + 0x17,0x77,0xd1,0x62,0x06,0x3f,0x7a,0x1f,0xb0,0x75,0x3a,0x83,0x2f,0xd0,0x4c,0xf9, + 0x9c,0x8b,0xf3,0xf9,0x12,0x7c,0xd0,0x32,0xed,0xa9,0x3d,0x2b,0x30,0xaf,0xbb,0x61, + 0x3d,0xbc,0x97,0x9e,0xff,0x58,0x95,0xea,0xb6,0x66,0x45,0x4d,0x95,0x35,0x17,0x83, + 0x87,0xaf,0xf1,0xb0,0x37,0x78,0xf8,0x06,0xdc,0x3d,0x7c,0x0b,0xe6,0x1e,0xe6,0x82, + 0x07,0x71,0xb3,0x16,0x73,0xe8,0xce,0x06,0x0f,0xdf,0xa1,0x9d,0x05,0x0f,0xdf,0x83, + 0xbb,0x87,0x2d,0x59,0x81,0x79,0x9d,0x3c,0x78,0xaf,0xb9,0xe0,0xa1,0x33,0x2b,0x6a, + 0x66,0x58,0x33,0x1b,0x3c,0xfc,0x80,0x87,0xfd,0xc1,0xc3,0x8f,0xe0,0xee,0xe1,0x27, + 0x30,0xf7,0xb0,0x10,0x3c,0x88,0x9b,0xb7,0x58,0x40,0x77,0x9e,0x7b,0x24,0xdd,0x9f, + 0xd1,0xee,0xcc,0x6e,0xdf,0x67,0xed,0xd1,0x6b,0x17,0xc2,0x1e,0xbb,0xa8,0x9b,0x63, + 0xdd,0x3c,0xb5,0x47,0xa9,0x3d,0x4a,0xad,0xee,0xeb,0xb6,0xac,0xf8,0xbe,0xb4,0xfe, + 0x6d,0x8b,0x63,0x70,0x3a,0xa3,0xee,0xac,0xb8,0x8b,0xe2,0xce,0xc0,0xc9,0xab,0x7e, + 0xb3,0x5e,0xc7,0xeb,0x71,0xbc,0xaa,0xfe,0x0d,0xf0,0xf7,0xf1,0x7a,0x82,0x1e,0xc2, + 0x57,0xac,0x66,0x9a,0x1e,0xee,0xf7,0x04,0xf9,0x34,0xfb,0x3a,0x46,0x2f,0x7d,0x9b, + 0x6f,0xf1,0x5d,0x0e,0xb3,0xcf,0xd3,0x60,0xf2,0x76,0x80,0xbe,0x2f,0x9b,0xce,0x7a, + 0xf6,0x2d,0x1f,0xa7,0xf3,0xdf,0x95,0x62,0xe6,0x67,0xa8,0xe9,0x6f,0xf2,0x3e,0x8d, + 0x07,0x7d,0xd7,0xef,0xe1,0xe1,0x2c,0xba,0xfa,0xc6,0xcf,0x81,0xbf,0x42,0xef,0x0f, + 0xe8,0x7d,0x2e,0x78,0xbf,0xc4,0xba,0xbe,0xe0,0xfd,0x32,0xf8,0x57,0xe8,0x5f,0x01, + 0xeb,0x0f,0xb3,0xff,0x05,0xbc,0x87,0xd9,0x2f,0x86,0xb3,0x10,0xf7,0xab,0xc5,0x22, + 0xfb,0xd4,0xfb,0x63,0x56,0x33,0xc8,0x1e,0xe4,0xc1,0xb9,0xc5,0xa0,0xf3,0x1b,0x3a, + 0x07,0x83,0xce,0xef,0xe0,0xae,0xb3,0x14,0x74,0xc4,0x5d,0xb5,0x58,0xa2,0xd7,0x55, + 0x74,0x86,0x82,0x8e,0x73,0x4b,0x41,0xe7,0x0f,0x74,0x86,0x83,0xce,0x9f,0xe0,0xae, + 0xb3,0x1c,0x74,0xc4,0x5d,0xb3,0x58,0xa6,0xd7,0x35,0x74,0x46,0x82,0x8e,0x73,0xcb, + 0x41,0xe7,0x2f,0x74,0x7a,0x83,0xce,0xdf,0xe0,0xae,0xb3,0x12,0x74,0xc4,0x5d,0xcf, + 0xef,0x57,0xd1,0xeb,0x3a,0x3a,0xa3,0x41,0xc7,0xb9,0x95,0xa0,0x73,0x03,0x9d,0xc3, + 0x41,0xe7,0x26,0xb8,0xeb,0xac,0x06,0x1d,0x71,0xb7,0x2c,0x56,0xe9,0x75,0x0b,0x9d, + 0xb1,0xa0,0xe3,0xdc,0x6a,0xd0,0xd1,0xc7,0x7a,0x99,0xff,0x99,0xae,0x93,0xf1,0x4f, + 0xc9,0x75,0x2a,0xd9,0x6d,0x1d,0x71,0x25,0x0b,0x61,0xea,0xa5,0x77,0xe9,0x8c,0x07, + 0x1d,0xe7,0xf4,0x74,0x9d,0x3a,0x3a,0x13,0x41,0xa7,0x25,0x2b,0x70,0xd7,0x69,0x04, + 0x1d,0x71,0xad,0x16,0x0d,0x7a,0xb5,0xa2,0x33,0x19,0x74,0x9c,0x6b,0x04,0x9d,0x0d, + 0xe8,0x1c,0x09,0x3a,0x1b,0xb3,0x02,0x77,0x9d,0x4d,0x41,0x47,0x5c,0x9b,0xc5,0x26, + 0x7a,0xb5,0xa1,0x33,0x15,0x74,0x9c,0xd3,0x73,0xd5,0x0e,0xe6,0x11,0x8b,0xff,0x01, + 0xe2,0xad,0xd4,0xd6,0xa4,0x0c,0x00,0x00 }; // Generated from: @@ -107,6 +108,7 @@ constexpr uint8_t kBlitResolve_frag_00000002[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000003.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000003.inc index a02ec85bde8..77061c35599 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000003.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000003.inc @@ -10,78 +10,78 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000003[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4f,0x68,0x5d,0x55, - 0x10,0xc6,0xcf,0x7d,0xef,0xe5,0xbd,0x98,0xc4,0xa6,0xc1,0x24,0xc6,0xa6,0xa6,0x69, - 0x13,0xa1,0x62,0x29,0x25,0xa8,0x08,0x52,0xd1,0x95,0x11,0x02,0x9a,0x08,0xdd,0x64, - 0x11,0x84,0x6c,0x84,0x58,0x0a,0x9a,0x45,0x37,0x41,0xb3,0xc9,0xa2,0x20,0xd9,0x28, - 0x6d,0x16,0xda,0x5a,0xa9,0x7f,0x52,0x8a,0xb6,0x5a,0xdc,0x55,0x2d,0x5a,0x8b,0x12, - 0x6d,0x50,0xa2,0x06,0x03,0xfe,0x23,0xa0,0x25,0xa0,0x25,0xda,0x94,0x4a,0x9d,0xef, - 0xde,0xdf,0xb4,0xc3,0x7b,0x30,0x9c,0x37,0xdf,0x37,0x67,0xbe,0x99,0x39,0xe7,0xdc, - 0x72,0xa9,0xaf,0x96,0x52,0x96,0x9a,0x52,0x63,0xea,0xcf,0x52,0xfe,0x6b,0x4b,0xa5, - 0xa4,0xbf,0xcd,0xa9,0x9a,0xaf,0x8f,0x0f,0x3d,0x3d,0xb4,0xfb,0xf9,0x17,0xc6,0x77, - 0xdf,0xff,0xc0,0x1e,0xf1,0x9b,0x52,0x39,0x8f,0x13,0xd7,0x6a,0x5e,0xc5,0x56,0xd9, - 0x73,0xcf,0x3c,0xbb,0x5f,0x78,0x87,0xd9,0x88,0xd9,0xa8,0xd9,0xb8,0xd9,0x84,0xd9, - 0xa4,0xd9,0x94,0xd9,0x8c,0xd9,0xac,0xd9,0x66,0xcb,0xa1,0x3d,0x35,0xe5,0xb7,0x7f, - 0x1d,0xb9,0x9e,0xf2,0xa5,0x34,0x98,0x1a,0x52,0x77,0x51,0x4a,0xea,0x63,0x75,0x2c, - 0x03,0x6b,0x0c,0x58,0x09,0x6c,0x73,0xc0,0xca,0x60,0x5d,0x01,0xab,0x80,0x6d,0x0d, - 0x58,0x03,0x58,0x6f,0xc0,0xaa,0x60,0xfd,0x01,0xab,0x81,0xed,0x0c,0x58,0x23,0xd8, - 0xae,0x80,0xdd,0x06,0xb6,0x27,0xef,0xab,0x7c,0xb3,0x3e,0xf5,0xa8,0x99,0xf4,0xd0, - 0x8f,0xfc,0x51,0xfc,0x0c,0x7f,0x1c,0xdf,0xe3,0x27,0xf0,0xcb,0xf8,0x93,0xf8,0x15, - 0xfc,0x29,0xfc,0x06,0xfc,0x19,0xfc,0x2a,0xfe,0x2c,0xbe,0xcf,0xf8,0xb8,0xad,0x3b, - 0x82,0xbe,0xfc,0xed,0xf8,0x77,0x98,0x6a,0x29,0xf7,0xcb,0xb9,0x5e,0x29,0x3f,0xc7, - 0x4a,0x9e,0xab,0x97,0x1a,0xef,0x34,0xbf,0x46,0x7e,0xf1,0x9d,0x16,0xd9,0x0c,0x2f, - 0xae,0x85,0x33,0xac,0xe4,0x58,0x25,0xb5,0xb3,0x4f,0xf8,0xc3,0xf8,0x1d,0x21,0x57, - 0x27,0xf1,0xae,0xb5,0x85,0x5c,0x29,0xaf,0xbb,0xe5,0xe6,0xdc,0x3b,0xb1,0x2a,0xd6, - 0xcc,0xba,0x25,0x98,0xf4,0xb6,0x32,0xff,0x6e,0xf4,0xe4,0xdf,0x0d,0x76,0x1f,0xbd, - 0xf8,0xfc,0x15,0xbf,0x0d,0xae,0x16,0xf8,0x7e,0x7c,0xf1,0xf7,0xc0,0x2b,0x7f,0xbb, - 0x55,0xb9,0x93,0x38,0xf9,0xf7,0x92,0xc7,0xf7,0x0d,0x70,0x1f,0xdc,0xdf,0x5b,0xa7, - 0x3b,0x48,0xcd,0xca,0xfb,0x04,0x5c,0x35,0xf0,0x43,0xcc,0x45,0xfc,0x30,0x67,0xee, - 0x73,0x1b,0xe6,0x3d,0x95,0x43,0xfc,0x3e,0xe6,0xe6,0xfc,0x68,0x1d,0x3f,0xc6,0x39, - 0x38,0x3f,0x0e,0xef,0xfe,0x44,0x5d,0xfc,0x01,0xde,0x8f,0xf3,0x93,0x75,0xfc,0x41, - 0xce,0xc6,0xf9,0xa9,0x3a,0x7e,0xda,0xec,0xd1,0xc0,0xcf,0xd4,0xf1,0x87,0xcc,0x5e, - 0x0c,0xfc,0x6c,0xe0,0x75,0x9e,0xaf,0x30,0xcf,0x5d,0x36,0x7d,0xf5,0xfd,0x2a,0x58, - 0xb4,0xbb,0x6c,0x6a,0xc7,0x38,0x7f,0x3e,0x55,0xf9,0x9a,0x05,0x5f,0xf3,0x7b,0x83, - 0xff,0xc7,0xd0,0x93,0x7f,0xbc,0xee,0xbc,0x4e,0xa0,0xaf,0x7b,0xf8,0x0e,0x67,0x11, - 0xeb,0x3d,0xc3,0xbb,0x52,0xbe,0x0f,0x38,0x2f,0xe9,0x3e,0x68,0x68,0x89,0xd9,0x26, - 0xf6,0x5c,0x35,0xa4,0x21,0x3f,0xf3,0xe2,0x0d,0x9c,0xe3,0x9e,0x3f,0x69,0xbd,0xe8, - 0xde,0x7e,0x0c,0x76,0x2e,0xd4,0xbc,0x9f,0xb7,0xf4,0x09,0xfc,0x63,0x96,0x41,0xf7, - 0xf1,0x53,0xee,0x6c,0x0f,0xf9,0x14,0x73,0x1e,0x7c,0xda,0x62,0xe4,0x7f,0xc6,0xbe, - 0xf3,0xec,0xd3,0x3d,0xfd,0x9c,0x7d,0xfd,0xec,0xd3,0x1d,0xbd,0x00,0x3e,0x6f,0x31, - 0xba,0xbb,0x5f,0x80,0xe9,0xee,0xfe,0x6b,0x95,0x2f,0x50,0xcf,0x35,0x8b,0x17,0x77, - 0xd1,0x6c,0x81,0x7e,0xf4,0x7f,0xd8,0xf6,0x69,0x16,0x5f,0xa2,0x99,0xf2,0x73,0x2f, - 0xe6,0xf3,0x15,0xf8,0x88,0x79,0xaa,0xa9,0x3b,0x2b,0x30,0x8f,0xdb,0xb0,0x1c,0x9e, - 0x4b,0xeb,0xba,0x45,0x29,0x6e,0x5b,0x56,0xc4,0x34,0xb0,0xe7,0x62,0xe8,0xe1,0x6b, - 0x7a,0x18,0x08,0x3d,0x7c,0x03,0xee,0x3d,0x5c,0x02,0xf3,0x1e,0x96,0x42,0x0f,0xe2, - 0x16,0xcd,0x96,0xd0,0x5d,0x0c,0x3d,0x7c,0x8b,0x76,0x16,0x7a,0xf8,0x0e,0xdc,0x7b, - 0xe8,0xc9,0x0a,0xcc,0xe3,0xd4,0x83,0xe7,0x5a,0x0a,0x3d,0xf4,0x66,0x45,0xcc,0x02, - 0x7b,0x16,0x43,0x0f,0xdf,0xd3,0xc3,0xde,0xd0,0xc3,0x0f,0xe0,0xde,0xc3,0x8f,0x60, - 0xde,0xc3,0x4a,0xe8,0x41,0xdc,0xb2,0xd9,0x0a,0xba,0xcb,0xdc,0x23,0xe9,0xfe,0x84, - 0x76,0x6f,0x76,0xeb,0xbe,0xab,0x46,0x8f,0x5d,0x09,0x35,0x6e,0x27,0x6e,0x89,0x7d, - 0xcb,0xc4,0x1e,0x26,0xf6,0x30,0xb1,0xba,0xaf,0x7d,0x59,0xf1,0xde,0xb4,0xff,0x3d, - 0xb3,0x23,0x70,0x9a,0xd1,0x8e,0xac,0xb8,0x8b,0xe2,0x4e,0xc3,0xa9,0x57,0x7d,0xc3, - 0x5e,0xa3,0xd7,0x31,0x7a,0x55,0xfc,0xeb,0xe0,0xef,0xd3,0xeb,0x51,0x72,0x08,0xff, - 0xc7,0x62,0xe6,0xc8,0xe1,0xfd,0x1e,0xc5,0x9f,0xa3,0xae,0x23,0xe4,0xd2,0xdb,0x7d, - 0x93,0x77,0xeb,0x7a,0x6f,0xa1,0x77,0x22,0xe8,0xbd,0x0d,0xee,0xe7,0xfc,0x2e,0xbd, - 0xa7,0x80,0xcd,0x83,0x09,0x7e,0xca,0x10,0xbd,0xf7,0x93,0xc4,0xce,0x93,0x63,0x8c, - 0x59,0x9c,0x42,0xf7,0x24,0xdf,0x33,0xd5,0xfe,0x92,0xe5,0x69,0x61,0x36,0x9a,0xd5, - 0xa9,0xfc,0x5b,0x56,0xe4,0x3e,0x4d,0xcc,0x50,0xdd,0x7c,0xe7,0xa8,0x5b,0xdf,0x8e, - 0x0f,0xa9,0xfb,0x0c,0x75,0xeb,0x3b,0x72,0x16,0xfc,0x65,0x72,0x7f,0x44,0xee,0xb3, - 0xa1,0xdf,0x9f,0xd9,0x37,0x18,0xfa,0xfd,0x05,0xfc,0x02,0xfa,0xbf,0x82,0x0d,0x85, - 0xfb,0xf5,0x1b,0x78,0x0f,0xf7,0x6b,0x35,0xcc,0x5b,0xdc,0xef,0x66,0xab,0xd4,0xa9, - 0xff,0x8f,0x58,0xcc,0x08,0x35,0xa8,0x07,0xe7,0x56,0x83,0xce,0x1f,0xe8,0xec,0x0b, - 0x3a,0x7f,0x82,0xbb,0xce,0x5a,0xd0,0x11,0x77,0xd9,0x6c,0x8d,0x5c,0x97,0xd1,0x19, - 0x0d,0x3a,0xce,0xad,0x05,0x9d,0xbf,0xd0,0x19,0x0b,0x3a,0x7f,0x83,0xbb,0xce,0x7a, - 0xd0,0x11,0x77,0x25,0xbf,0xaf,0x45,0xae,0x2b,0xe8,0x8c,0x07,0x1d,0xe7,0xd6,0x83, - 0xce,0x55,0x74,0x06,0x82,0xce,0x06,0xb8,0xeb,0x5c,0x0f,0x3a,0x1b,0xf9,0x9a,0x72, - 0x4c,0xb9,0xae,0xa1,0x33,0x11,0x74,0x9c,0xbb,0x1e,0x74,0x6e,0xa0,0x73,0x20,0xe8, - 0xe8,0x22,0xde,0x08,0x3a,0xe5,0xec,0x96,0x8e,0xb8,0xcc,0x4c,0x98,0x72,0xe9,0xbf, - 0x74,0x26,0x83,0x8e,0x73,0x5a,0x5d,0xa7,0x9a,0x15,0x3a,0x07,0x83,0x4e,0x2d,0x2b, - 0x70,0xd7,0x69,0x0a,0x3a,0xe2,0x1a,0xcd,0x9a,0xc8,0xd5,0x88,0xce,0x54,0xd0,0x71, - 0xae,0x29,0xe8,0xdc,0x8e,0xce,0x74,0xd0,0xd9,0x94,0x15,0xb8,0xeb,0xb4,0x05,0x1d, - 0x71,0xad,0x66,0x6d,0xe4,0x6a,0x45,0x67,0x26,0xe8,0x38,0xd7,0x16,0x74,0xda,0xd1, - 0x39,0x14,0x74,0x3a,0xb2,0x02,0x77,0x9d,0xae,0xa0,0x23,0xae,0xd3,0xac,0x8b,0x5c, - 0x9d,0xe8,0xcc,0x06,0x1d,0xe7,0xb4,0xfe,0x67,0x83,0x7e,0xc8,0xec,0x7f,0x79,0xd8, - 0x48,0xef,0x00,0x0d,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x5f,0x68,0x96,0x75, + 0x14,0xc7,0x7f,0xcf,0xfb,0xbe,0x7b,0xdf,0xb5,0xa9,0x73,0xb4,0xad,0xe5,0x6c,0x4e, + 0xb7,0xc0,0x48,0x44,0xc4,0x22,0x08,0xa3,0xae,0x5a,0x30,0xa8,0x2d,0xf0,0x66,0x17, + 0x23,0xd8,0x8d,0xb0,0x44,0xa8,0x5d,0x78,0x33,0x6a,0x37,0xbb,0x10,0x62,0x37,0x85, + 0xee,0xc2,0xd2,0x8c,0xfe,0x4c,0xa4,0xb4,0xa4,0x3b,0x2b,0x29,0x93,0x62,0xe5,0x28, + 0x56,0x0d,0x07,0xfd,0x63,0x50,0x32,0x28,0x59,0x39,0x31,0xec,0x7c,0x9f,0xe7,0x73, + 0xf4,0xf0,0xbe,0x70,0x78,0xde,0xf3,0xfd,0x9e,0xdf,0xf9,0x9e,0x73,0x7e,0xe7,0x79, + 0xca,0xa5,0xde,0x5a,0x4a,0x59,0x6a,0x4a,0x8d,0xa9,0x2f,0x4b,0xf9,0xaf,0x35,0x95, + 0x92,0xfe,0x36,0xa7,0x6a,0xfe,0x7c,0x72,0xe0,0xd9,0x81,0x9d,0x2f,0xbc,0x38,0xba, + 0x73,0xcf,0x43,0xbb,0xc4,0x6f,0x48,0xe5,0x3c,0x4e,0x5c,0x8b,0x79,0x15,0x7b,0xca, + 0x9e,0x7f,0x6e,0xff,0x01,0xe1,0xed,0x66,0x43,0x66,0xc3,0x66,0xa3,0x66,0x63,0x66, + 0xe3,0x66,0x13,0x66,0x53,0x66,0xd3,0x66,0x1b,0x2d,0x87,0xce,0xd4,0x94,0xdf,0xfe, + 0xb5,0xe7,0x7a,0xca,0x97,0x52,0x7f,0x6a,0x48,0x5d,0x45,0x29,0xa9,0x97,0xa7,0x63, + 0x19,0x58,0x63,0xc0,0x4a,0x60,0x1b,0x03,0x56,0x06,0xeb,0x0c,0x58,0x05,0x6c,0x73, + 0xc0,0x1a,0xc0,0x7a,0x02,0x56,0x05,0xeb,0x0b,0x58,0x0d,0x6c,0x7b,0xc0,0x1a,0xc1, + 0x76,0x04,0xec,0x2e,0xb0,0x5d,0x01,0x6b,0x02,0xdb,0x93,0xf7,0x5a,0xbe,0x5d,0xb3, + 0xfa,0xd6,0x9c,0xba,0xe9,0x51,0xfe,0x30,0x7e,0x86,0x3f,0x8a,0xef,0xf1,0x63,0xf8, + 0x65,0xfc,0x71,0xfc,0x0a,0xfe,0x04,0x7e,0x03,0xfe,0x14,0x7e,0x15,0x7f,0x1a,0xdf, + 0xe7,0x7e,0xd2,0x9e,0xdb,0x82,0xbe,0xfc,0xad,0xf8,0x77,0x9b,0x6a,0x29,0xf7,0xcb, + 0xb9,0x5e,0x29,0xbf,0xdb,0x4a,0x9e,0xab,0x87,0x1a,0xef,0x31,0xbf,0x46,0x7e,0xf1, + 0x1d,0x16,0xd9,0x0c,0x2f,0x6e,0x1d,0xf7,0x5a,0xc9,0xb1,0x4a,0x6a,0xe3,0x9c,0xf0, + 0x47,0xf1,0xdb,0x43,0xae,0x0e,0xe2,0x5d,0x6b,0x13,0xb9,0x52,0x5e,0xf7,0xfa,0xdb, + 0x77,0xd1,0x81,0x55,0x83,0x35,0xf3,0xdc,0x14,0x4c,0x9a,0x9b,0xb9,0x97,0x2e,0x34, + 0xe5,0xdf,0x07,0xf6,0x20,0xfd,0xf8,0x1d,0x28,0x7e,0x0b,0x5c,0x2d,0xf0,0x7d,0xdc, + 0xb7,0xf8,0xfb,0xe1,0x95,0xbf,0xcd,0x2a,0xdd,0x4e,0x9c,0xfc,0x07,0xc8,0xe3,0xe7, + 0x76,0xd7,0xe9,0xec,0x65,0x1f,0xdc,0xef,0x47,0x47,0x79,0x9f,0x22,0xb6,0x1a,0xf8, + 0x01,0x66,0x23,0x7e,0x90,0x7b,0xf7,0xd9,0x0d,0xf2,0x9e,0x95,0x43,0xfc,0x3e,0x66, + 0xe7,0xfc,0x70,0x1d,0x3f,0xc2,0x5d,0x38,0x3f,0x0a,0xef,0xfe,0x58,0x5d,0xfc,0x41, + 0xde,0x2b,0xe7,0xc7,0xeb,0xf8,0x43,0xdc,0x8f,0xf3,0x13,0x75,0xfc,0xa4,0xd9,0xe3, + 0x81,0x9f,0xaa,0xe3,0x0f,0x9b,0xbd,0x14,0xf8,0xe9,0xc0,0xeb,0x3e,0x5f,0x65,0x9e, + 0x3b,0x6c,0x4a,0xea,0xfb,0x35,0xb0,0x68,0x9e,0xeb,0x18,0x7b,0x7f,0xaf,0x4d,0xf1, + 0x04,0xfb,0xc0,0x27,0x2d,0x7f,0x66,0xc1,0xd7,0x3c,0xdf,0xe4,0xff,0x09,0xf4,0xe5, + 0x9f,0x04,0xd3,0x2e,0xbe,0xcb,0x5d,0xc4,0x7a,0xcf,0x82,0xe9,0xfc,0x87,0xdc,0x97, + 0x74,0x1e,0x36,0xe5,0x12,0xb3,0x4d,0x9c,0xb9,0x6e,0x48,0x43,0x7e,0xe7,0xc5,0x7b, + 0x70,0x9e,0x5d,0x7f,0xda,0x7a,0xd1,0xee,0x7e,0x02,0x76,0x3e,0xd4,0x78,0x80,0xf7, + 0xe9,0x53,0xf8,0x27,0x2c,0x83,0xf6,0xf1,0x33,0x76,0xb6,0x9b,0x7c,0x8a,0xb9,0x00, + 0x3e,0x69,0x31,0xf2,0x3f,0xe7,0xdc,0x05,0xce,0x69,0x4f,0xbf,0xe0,0x5c,0x1f,0xe7, + 0xb4,0xa3,0x17,0xc1,0x67,0x2d,0x46,0xbb,0xfb,0x25,0x98,0x76,0xf7,0x5f,0xab,0x7c, + 0x8e,0x7a,0x6e,0x58,0xbc,0xb8,0x4b,0x66,0x73,0xf4,0xa3,0xff,0x83,0x76,0x4e,0x33, + 0xf8,0x0a,0xcd,0x94,0xdf,0x7b,0x31,0x9f,0xaf,0xc1,0x87,0xcc,0x53,0x4d,0x5d,0x59, + 0x81,0x79,0xdc,0x9a,0xe5,0xf0,0x5c,0x7a,0xae,0x5a,0x94,0xe2,0xb6,0x64,0x45,0x4c, + 0x03,0x67,0x2e,0x85,0x1e,0xbe,0xa1,0x87,0xdd,0xa1,0x87,0x6f,0xc1,0xbd,0x87,0xcb, + 0x60,0xde,0xc3,0x42,0xe8,0x41,0xdc,0xbc,0xd9,0x02,0xba,0xf3,0xa1,0x87,0xef,0xd0, + 0xce,0x42,0x0f,0xdf,0x83,0x7b,0x0f,0xdd,0x59,0x81,0x79,0x9c,0x7a,0xf0,0x5c,0x0b, + 0xa1,0x87,0x9e,0xac,0x88,0x99,0xe3,0xcc,0x7c,0xe8,0xe1,0x07,0x7a,0xd8,0x1b,0x7a, + 0xf8,0x11,0xdc,0x7b,0xf8,0x09,0xcc,0x7b,0x58,0x0a,0x3d,0x88,0x5b,0x34,0x5b,0x42, + 0x77,0x91,0x3d,0x92,0xee,0x15,0xb4,0x7b,0xb2,0x3b,0xfb,0xad,0x1a,0x3d,0x76,0x29, + 0xd4,0xb8,0x95,0xb8,0x05,0xce,0x2d,0x12,0x7b,0x84,0xd8,0x23,0xc4,0x6a,0x5f,0x7b, + 0xb3,0xe2,0x7d,0xd3,0xf9,0xf7,0xcd,0x8e,0xc2,0x69,0x46,0xdb,0xb2,0x62,0x17,0xc5, + 0x9d,0x81,0x53,0xaf,0xfa,0x86,0xbd,0x4e,0xaf,0xc7,0xe8,0x55,0xf1,0x6f,0x80,0x7f, + 0x40,0xaf,0xc7,0xc9,0x21,0xfc,0x1f,0x8b,0x99,0x21,0x87,0xf7,0x7b,0x1c,0x7f,0x86, + 0xba,0x8e,0x92,0x4b,0xef,0xea,0x5b,0xbc,0xa7,0xae,0xf7,0x36,0x7a,0x23,0x41,0xef, + 0x1d,0x70,0xbf,0xe7,0xf7,0xe8,0x3d,0x05,0x6c,0x16,0x4c,0xf0,0x33,0x86,0xe8,0x7d, + 0x3f,0x45,0xec,0x2c,0x39,0x46,0x98,0xc5,0x69,0x74,0x4f,0xf1,0x3d,0x53,0xed,0x2f, + 0x5b,0x9e,0x75,0xcc,0x46,0xb3,0x3a,0x9d,0x7f,0xcb,0x8a,0xdc,0x67,0x88,0x19,0xa8, + 0x9b,0xef,0x0c,0x75,0xeb,0xdb,0xf1,0x11,0x75,0x9f,0xa5,0x6e,0x7d,0x47,0xce,0x81, + 0xbf,0x42,0xee,0x8f,0xc9,0x7d,0x2e,0xf4,0xfb,0x33,0xe7,0xfa,0x43,0xbf,0xbf,0x80, + 0x5f,0x44,0xff,0x57,0xb0,0x81,0xb0,0x5f,0xbf,0x81,0x77,0xb3,0x5f,0xcb,0x61,0xde, + 0xe2,0x7e,0x37,0x5b,0xa6,0x4e,0xfd,0x7f,0xcc,0x62,0x86,0xa8,0x41,0x3d,0x38,0xb7, + 0x1c,0x74,0xfe,0x40,0x67,0x5f,0xd0,0xf9,0x13,0xdc,0x75,0x56,0x82,0x8e,0xb8,0xab, + 0x66,0x2b,0xe4,0xba,0x8a,0xce,0x70,0xd0,0x71,0x6e,0x25,0xe8,0xfc,0x85,0xce,0x48, + 0xd0,0xf9,0x1b,0xdc,0x75,0x56,0x83,0x8e,0xb8,0x6b,0xf9,0xbe,0x16,0xb9,0xae,0xa1, + 0x33,0x1a,0x74,0x9c,0x5b,0x0d,0x3a,0xd7,0xd1,0xe9,0x0b,0x3a,0x6b,0xe0,0xae,0x73, + 0x33,0xe8,0xac,0xe5,0xcf,0x94,0x63,0xca,0x75,0x03,0x9d,0xb1,0xa0,0xe3,0xdc,0xcd, + 0xa0,0x73,0x0b,0x9d,0x83,0x41,0x47,0x8b,0x78,0x2b,0xe8,0x94,0xb3,0x3b,0x3a,0xe2, + 0x32,0x33,0x61,0xca,0xa5,0xff,0xd2,0x19,0x0f,0x3a,0xce,0xe9,0xe9,0x3a,0xd5,0xac, + 0xd0,0x39,0x14,0x74,0x6a,0x59,0x81,0xbb,0x4e,0x53,0xd0,0x11,0xd7,0x68,0xd6,0x44, + 0xae,0x46,0x74,0x26,0x82,0x8e,0x73,0x4d,0x41,0x67,0x3d,0x3a,0x93,0x41,0x67,0x43, + 0x56,0xe0,0xae,0xd3,0x1a,0x74,0xc4,0xb5,0x98,0xb5,0x92,0xab,0x05,0x9d,0xa9,0xa0, + 0xe3,0x5c,0x6b,0xd0,0x69,0x43,0xe7,0x70,0xd0,0x69,0xcf,0x0a,0xdc,0x75,0x3a,0x83, + 0x8e,0xb8,0x0e,0xb3,0x4e,0x72,0x75,0xa0,0x33,0x1d,0x74,0x9c,0xd3,0xf3,0x3f,0x1b, + 0xf4,0x23,0x66,0xff,0x03,0x6b,0xc6,0x33,0x26,0x18,0x0d,0x00,0x00 }; // Generated from: @@ -110,6 +110,7 @@ constexpr uint8_t kBlitResolve_frag_00000003[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000004.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000004.inc index 47d0ca213cd..706a836935c 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000004.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000004.inc @@ -10,73 +10,75 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000004[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4d,0x68,0x5d,0x65, - 0x10,0x86,0xbf,0x73,0xff,0xf5,0xa6,0xa6,0xfe,0x34,0x69,0xf5,0xb6,0xa6,0x56,0x82, - 0x90,0x52,0xbb,0x50,0x31,0x88,0xa2,0x50,0xd0,0x45,0xa1,0x55,0xc1,0x74,0x91,0xcd, - 0x05,0xbb,0x30,0xa0,0x8b,0x28,0xdd,0x64,0x51,0xc1,0x08,0xdd,0x64,0xd1,0x4d,0x36, - 0xb5,0xd6,0x54,0xd1,0x8a,0x1b,0xf1,0xa7,0x68,0xf1,0x27,0x28,0xb1,0x06,0x25,0x6a, - 0x30,0xa0,0xad,0x04,0xb4,0x04,0xb4,0x04,0xb4,0x04,0x4d,0x0d,0xd4,0x3a,0xef,0x39, - 0xcf,0xa4,0xc3,0xbd,0x30,0xf7,0x3b,0xf3,0xbe,0x33,0xf3,0x7e,0xf3,0x9d,0xf9,0x4e, - 0xb9,0xb4,0xa3,0x9e,0x52,0x96,0xae,0x4f,0x8d,0xb4,0x25,0x4b,0xf9,0xef,0xc6,0x54, - 0x4a,0x7a,0x6c,0xa6,0x5a,0xbe,0x3e,0xba,0xf7,0xc9,0xbd,0xbb,0x9e,0x7f,0xe1,0xe9, - 0x5d,0xf7,0xdc,0xbb,0x5b,0xfc,0x0d,0xa9,0x9c,0xc7,0x89,0xeb,0x36,0xaf,0x62,0xab, - 0xec,0xd9,0xf6,0x33,0xcf,0x09,0xef,0x31,0x3b,0x60,0xd6,0x36,0x1b,0x31,0x1b,0x35, - 0x1b,0x33,0x1b,0x37,0x9b,0x30,0x9b,0x34,0xdb,0x68,0x35,0x94,0x53,0x57,0x7d,0x7b, - 0xea,0xc9,0xf5,0x54,0x2f,0xa5,0xc7,0x52,0x35,0x6d,0x2d,0xb6,0x92,0x76,0xb0,0x3a, - 0x96,0x81,0x35,0x02,0x56,0x02,0xdb,0x18,0xb0,0x32,0xd8,0xe6,0x80,0x55,0xc0,0x5a, - 0x01,0xab,0x82,0xf5,0x05,0xac,0x06,0x76,0x67,0xc0,0xea,0x60,0x77,0x05,0xac,0x01, - 0xb6,0x33,0x60,0xd7,0x81,0xed,0xce,0xfb,0x2a,0xaf,0xef,0x4f,0x3d,0xea,0x4c,0xb6, - 0xd1,0x8f,0xfc,0x36,0x7e,0x86,0x3f,0x82,0xef,0xf1,0xa3,0xf8,0x65,0xfc,0x31,0xfc, - 0x0a,0xfe,0x38,0x7e,0x15,0x7f,0x02,0xbf,0x86,0x3f,0x89,0xef,0x67,0x7c,0xdc,0xd6, - 0x3b,0x82,0xbe,0xfc,0xed,0xc1,0x9f,0xea,0xe0,0xa7,0xe0,0xb5,0x9f,0x9b,0xed,0xbf, - 0x94,0xfb,0xe5,0x7c,0x3f,0xa5,0xfc,0x3d,0x97,0x73,0x2d,0x9d,0x5d,0xaf,0xc5,0xd7, - 0xd1,0x16,0xb7,0xc9,0xfc,0x26,0x5c,0x06,0xdf,0xc5,0x3b,0xae,0xe0,0xdf,0x42,0x7c, - 0x25,0x8f,0xab,0x58,0x4e,0x11,0x2b,0xfc,0x01,0xfc,0x1e,0x30,0xd5,0x6b,0x51,0x2f, - 0xe5,0x7d,0x75,0xad,0xbf,0x17,0xb7,0x26,0x56,0x63,0x6d,0x05,0x53,0xfd,0x6d,0xbc, - 0x9f,0xad,0xd4,0x97,0x7f,0x3b,0xd8,0x40,0xc7,0x7e,0x15,0xbf,0x1d,0xae,0x1e,0xf8, - 0x7e,0xf4,0xdd,0x1f,0x80,0x57,0xfc,0x4e,0xe2,0x5b,0x79,0x0f,0xa5,0x74,0x37,0x71, - 0x2d,0xe6,0x21,0xe6,0x0d,0x32,0x3f,0xee,0xef,0xe9,0xd8,0xc7,0x3e,0xfa,0x50,0xdd, - 0xfd,0x70,0x4d,0xfc,0x21,0x66,0xa2,0x8b,0x3e,0x86,0xb8,0x6f,0xe5,0x90,0x3f,0xcc, - 0x7b,0x70,0xbe,0xdd,0xc1,0x1f,0xe4,0xdc,0x9d,0x1f,0x81,0x77,0x7f,0xb4,0x23,0xfe, - 0x10,0xf7,0xcb,0xf9,0xb1,0x0e,0xfe,0x30,0x67,0xe7,0xfc,0x78,0x07,0x7f,0xc4,0xec, - 0xe1,0xc0,0x4f,0x74,0xf0,0x47,0xcd,0x5e,0x0c,0xfc,0x24,0xfc,0x16,0xeb,0xfc,0x18, - 0xbd,0xf3,0x79,0x5a,0xff,0xb9,0xaf,0x33,0x79,0x85,0xe7,0x63,0xd4,0x90,0x7f,0x1c, - 0xec,0x56,0x3b,0x89,0x13,0xc4,0xbd,0x06,0x76,0x82,0x38,0xf9,0x53,0x60,0xb7,0x99, - 0xe2,0xeb,0xd4,0xb8,0xcf,0x6e,0x55,0x89,0x33,0x4a,0xec,0xe5,0xb2,0x21,0xba,0x6b, - 0x0f,0x32,0xbb,0xef,0x32,0x9f,0x8f,0x1b,0xaa,0x77,0xf5,0x1e,0x58,0x0a,0xd8,0xfb, - 0x60,0xda,0xeb,0x7e,0xc3,0x34,0x2b,0x1f,0x10,0x2b,0xee,0x11,0xc3,0x34,0x67,0x1f, - 0x32,0x8b,0x7d,0xd4,0x57,0xdc,0x69,0xf0,0x97,0xc9,0xfb,0x88,0xdc,0xd3,0x21,0xef, - 0x63,0xf2,0xfa,0x43,0xde,0x19,0xf0,0x97,0xc8,0xfb,0x84,0xdc,0x33,0xe4,0x69,0x4e, - 0x3f,0x25,0x6f,0x80,0x3c,0xcd,0xe8,0x67,0xe0,0xef,0x58,0x8c,0x66,0xf7,0x73,0x30, - 0xcd,0xee,0xaa,0x9d,0xc0,0x0c,0xbd,0xad,0x59,0xbc,0xb8,0x69,0xb3,0x19,0xce,0x65, - 0x3a,0xf4,0xfc,0x05,0x9a,0x29,0x9f,0x8b,0x4a,0x8e,0x7d,0x09,0xfe,0x84,0x79,0xda, - 0xd3,0x4d,0x59,0x81,0x79,0xdc,0xbf,0x56,0xc3,0x6b,0x69,0xfd,0xdb,0xa2,0x14,0xd7, - 0x93,0x15,0x31,0x55,0x72,0xa6,0x43,0x0f,0x5f,0xd1,0xc3,0x60,0xe8,0xe1,0x2c,0xb8, - 0xf7,0xf0,0x35,0x98,0xf7,0x30,0x17,0x7a,0x10,0x37,0x6b,0x36,0x87,0xee,0x6c,0xe8, - 0xe1,0x1b,0xb4,0xb3,0xd0,0xc3,0xb7,0xe0,0xde,0xc3,0xa6,0xac,0xc0,0x3c,0x4e,0x3d, - 0x78,0xad,0xb9,0xd0,0x43,0x6f,0x56,0xc4,0xcc,0x90,0x33,0x1b,0x7a,0xf8,0x8e,0x1e, - 0xf6,0x84,0x1e,0xbe,0x07,0xf7,0x1e,0x7e,0x00,0xf3,0x1e,0x16,0x42,0x0f,0xe2,0xe6, - 0xcd,0x16,0xd0,0x9d,0xcf,0xbf,0x1d,0x85,0xee,0x8f,0x68,0xf7,0x66,0xd7,0xee,0x8a, - 0xf6,0xe8,0xb1,0x0b,0x61,0x8f,0x9b,0x89,0x9b,0x23,0x6f,0x9e,0xfd,0xe8,0x2e,0xbc, - 0xca,0x5d,0x92,0xaf,0x7b,0x73,0x92,0x3b,0xf3,0x94,0xed,0x4f,0xf7,0xe5,0x0d,0x62, - 0x4e,0x86,0xb9,0x7c,0x93,0xbe,0x86,0xc3,0x5c,0xbe,0x05,0xee,0xf3,0x7c,0x0a,0x5d, - 0xe1,0x43,0x86,0xe9,0x7b,0xf6,0x36,0xf5,0x4e,0x51,0x4b,0xdf,0xbe,0x9f,0xa8,0xb5, - 0x8f,0x5a,0xfa,0x16,0xfc,0x0c,0x7e,0xd6,0x62,0xe4,0x9f,0x03,0xeb,0x0b,0xe7,0x76, - 0x1e,0xbc,0x9f,0x73,0x5b,0x0c,0xe7,0x26,0xee,0x17,0xb3,0x45,0xce,0x42,0xcf,0x0f, - 0x59,0xcc,0x01,0xf6,0xa0,0x73,0x72,0x6e,0x31,0xe8,0xfc,0x8a,0xce,0x70,0xd0,0xf9, - 0x0d,0xdc,0x75,0x96,0x82,0x8e,0xb8,0x0b,0x66,0x4b,0xd4,0xba,0x80,0x4e,0x3b,0xe8, - 0x38,0xb7,0x14,0x74,0x7e,0x47,0xe7,0x60,0xd0,0xf9,0x03,0xdc,0x75,0x96,0x83,0x8e, - 0xb8,0x8b,0x66,0xcb,0xd4,0xba,0x88,0xce,0x48,0xd0,0x71,0x6e,0x39,0xe8,0xfc,0x89, - 0xce,0x60,0xd0,0xf9,0x0b,0xdc,0x75,0x56,0x82,0x8e,0xb8,0x4b,0x66,0x2b,0xd4,0xba, - 0x84,0xce,0x68,0xd0,0x71,0x6e,0x25,0xe8,0xfc,0x83,0xce,0xa1,0xa0,0xb3,0x0a,0xee, - 0x3a,0x6b,0x41,0x67,0x35,0xaf,0x91,0x72,0x4c,0xb5,0x2e,0xa3,0x33,0x16,0x74,0x9c, - 0x5b,0x0b,0x3a,0x57,0xd0,0x39,0x1c,0x74,0xfe,0x03,0x77,0x9d,0x2c,0xbb,0xa6,0x23, - 0xee,0xaa,0xbe,0xcf,0x59,0x51,0xeb,0x2a,0x3a,0xe3,0x41,0xc7,0x39,0xad,0xae,0x53, - 0xc9,0x0a,0x9d,0x23,0x41,0xa7,0x9a,0x15,0xb8,0xeb,0x34,0x82,0x8e,0xb8,0x9a,0x59, - 0x83,0x5a,0x7a,0x96,0xce,0x44,0xd0,0x71,0xae,0x11,0x74,0x9a,0xe8,0x1c,0x0d,0x3a, - 0x5d,0x59,0x81,0xbb,0x4e,0x77,0xd0,0x11,0xb7,0xc1,0xac,0x9b,0x5a,0x1b,0xd0,0x99, - 0x0c,0x3a,0xce,0x69,0xbd,0x62,0x5f,0x86,0xfb,0xcd,0xfe,0x07,0x64,0x0e,0xf1,0x49, - 0x08,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x5f,0x68,0xd6,0x65, + 0x14,0xc7,0x9f,0xe7,0xfd,0xbd,0xef,0xde,0xb9,0xf7,0x2d,0x37,0xa6,0xf3,0xcf,0xde, + 0xd9,0xcc,0x18,0xc1,0xc4,0xbc,0xb0,0x50,0xc2,0x30,0x10,0xea,0x42,0xd0,0x0a,0x72, + 0x17,0xbb,0x79,0x41,0x2f,0x1a,0x54,0xb0,0xc2,0x9b,0x5d,0x28,0xb8,0xc0,0x9b,0x5d, + 0x78,0xb3,0x1b,0x35,0x9b,0x45,0x6a,0xda,0x5d,0xf4,0x47,0x4a,0xfa,0x33,0x92,0x55, + 0xa3,0x98,0x36,0x1a,0xd8,0x1f,0x06,0x25,0x03,0x93,0x41,0xca,0xca,0x74,0x78,0xce, + 0xf3,0xfb,0x9c,0xed,0xf0,0x0e,0xce,0x7e,0xef,0xf9,0x7e,0xcf,0x39,0xdf,0x73,0x9e, + 0xdf,0x79,0x7e,0x59,0x61,0x53,0x39,0x84,0x18,0x5a,0x42,0x73,0xe8,0x8a,0x21,0xfd, + 0xb5,0x85,0x42,0xd0,0x9f,0x95,0xd0,0x94,0x9e,0xcf,0xed,0x79,0x69,0xcf,0x96,0x37, + 0xde,0x3c,0xb0,0x65,0xdb,0x93,0x5b,0x95,0x7f,0x38,0x64,0x29,0x4e,0xb9,0x95,0xe2, + 0x15,0xe5,0xa9,0xf6,0x6a,0xfd,0x95,0xd7,0x14,0xef,0x10,0xeb,0x13,0xab,0x8b,0x0d, + 0x88,0x0d,0x8a,0x0d,0x89,0x0d,0x8b,0x8d,0x88,0x8d,0x8a,0xb5,0x4a,0x0d,0xcd,0x29, + 0x6b,0x7d,0xf9,0xd5,0x91,0xf4,0xb4,0x5e,0x08,0xcf,0x87,0x52,0xe8,0xca,0x5b,0x09, + 0x9b,0x78,0x1a,0x16,0xc1,0x9a,0x1d,0x56,0x00,0x6b,0x75,0x58,0x06,0xb6,0xd6,0x61, + 0x45,0xb0,0x9a,0xc3,0x4a,0x60,0xdd,0x0e,0x6b,0x02,0x7b,0xcc,0x61,0x65,0xb0,0xc7, + 0x1d,0xd6,0x0c,0xb6,0xd9,0x61,0x2b,0xc0,0xb6,0x3a,0xac,0x05,0x6c,0x5b,0x9a,0x35, + 0x5b,0xea,0x59,0xe7,0xd6,0x73,0xda,0xc0,0x8c,0xea,0xd7,0xf1,0x23,0xfe,0x00,0xbe, + 0xc5,0x0f,0xe2,0x67,0xf8,0x43,0xf8,0x45,0xfc,0x61,0xfc,0x12,0xfe,0x08,0x7e,0x13, + 0xfe,0x28,0xbe,0x9d,0xfb,0x29,0x79,0x3e,0xea,0xf4,0xd5,0xdf,0xe8,0xfc,0xb1,0x06, + 0x7e,0x0c,0x5e,0xfb,0x69,0x97,0xff,0x85,0xe4,0x67,0xa9,0x9f,0x42,0x7a,0xf7,0x59, + 0xd2,0xd2,0xf3,0x5c,0x23,0xf1,0x65,0xb4,0x95,0x5b,0x2d,0x7e,0x05,0x2e,0xc2,0x57, + 0x79,0xef,0x45,0xfc,0x55,0xc4,0x17,0x53,0x5c,0x51,0x72,0xf2,0x58,0xc5,0x9f,0xc6, + 0xef,0x00,0xd3,0x7a,0x35,0xea,0x85,0x34,0xd7,0x43,0x4b,0xef,0xca,0xac,0xe2,0xac, + 0x89,0x67,0xcd,0x99,0x6a,0x6c,0xe0,0xbd,0x75,0xa1,0xa1,0xfe,0x23,0x60,0xbd,0x0d, + 0x3d,0x6b,0xfc,0x46,0xb8,0xb2,0xe3,0x7b,0xe8,0xc1,0xfc,0x5e,0xf6,0x43,0xe3,0x37, + 0x13,0x5f,0x4b,0x73,0x14,0xc2,0x13,0xc4,0xd5,0xd8,0x13,0x9f,0xb7,0xa3,0x41,0x77, + 0x37,0xfb,0x63,0xfe,0x5e,0x74,0xb5,0xee,0x3e,0x62,0x2b,0xf8,0xfb,0xd9,0x8b,0x2a, + 0x73,0xec,0xe7,0x1e,0x66,0x2e,0xbf,0x9f,0x77,0x61,0x7c,0xbd,0x81,0x3f,0xc8,0xd9, + 0x1b,0x3f,0x00,0x6f,0xfe,0x60,0x43,0xfc,0x21,0xee,0x9d,0xf1,0x43,0x0d,0xfc,0x61, + 0xce,0xce,0xf8,0xe1,0x06,0xfe,0x98,0xd8,0x2e,0xc7,0x8f,0x34,0xf0,0xc7,0xc5,0x8e, + 0x38,0x7e,0x14,0x7e,0x9d,0x4c,0x7e,0x82,0xd9,0xf9,0x6c,0x2d,0xfd,0x99,0xaf,0x67, + 0x72,0x92,0xdf,0x27,0xa8,0xa1,0xfe,0x29,0xb0,0xf5,0x72,0x12,0xa7,0x89,0x7b,0x07, + 0xec,0x34,0x71,0xea,0x8f,0x81,0x75,0x8a,0xe2,0xbb,0xd4,0xb0,0xbe,0xce,0xd3,0xc7, + 0x53,0x72,0xd3,0x0a,0x9c,0x59,0x00,0xfb,0x57,0x10,0xbd,0x7f,0x3b,0xd9,0xe7,0x8f, + 0xd8,0xd9,0x17,0x04,0xd5,0x1d,0xfc,0x18,0x2c,0x38,0xec,0x13,0x30,0xed,0x7d,0x9f, + 0x60,0xfa,0x8e,0x3f,0x25,0x56,0xb9,0x67,0x05,0xd3,0xbd,0xfb,0x8c,0xdd,0xec,0xa6, + 0xbe,0xc6,0x5d,0x02,0x7f,0x8b,0xbc,0xcf,0xc9,0xbd,0xe4,0xf2,0xbe,0x20,0xaf,0xc7, + 0xe5,0x5d,0x06,0x3f,0x4a,0xde,0x97,0xe4,0x5e,0x26,0x4f,0xf7,0xf6,0x2b,0xf2,0x7a, + 0xc9,0xd3,0x9d,0xfd,0x1a,0xfc,0x82,0xc4,0xe8,0x2e,0x7f,0x03,0xa6,0xbb,0xbc,0x20, + 0x27,0x30,0xc1,0x6c,0x77,0x25,0x5e,0xb9,0x71,0xb1,0x09,0xce,0x65,0xdc,0xcd,0xfc, + 0x2d,0x9a,0x21,0xed,0x49,0x31,0x61,0x57,0xc0,0x5f,0x14,0x4f,0x7b,0xea,0x88,0x39, + 0x66,0x71,0xff,0x49,0x0d,0xab,0xa5,0xcf,0x3b,0x12,0xa5,0x71,0xeb,0x63,0x1e,0x53, + 0x22,0x67,0xdc,0xcd,0xf0,0x1d,0x33,0xec,0x70,0x33,0x7c,0x0f,0x6e,0x33,0xfc,0x00, + 0x66,0x33,0x4c,0xb9,0x19,0x94,0x9b,0x14,0x9b,0x42,0x77,0xd2,0xcd,0xf0,0x23,0xda, + 0xd1,0xcd,0xf0,0x13,0xb8,0xcd,0xb0,0x2e,0xe6,0x98,0xc5,0xe9,0x0c,0x56,0x6b,0xca, + 0xcd,0xd0,0x19,0xf3,0x98,0x09,0x72,0x26,0xdd,0x0c,0x57,0x99,0x61,0xb7,0x9b,0xe1, + 0x1a,0xb8,0xcd,0xf0,0x33,0x98,0xcd,0x30,0xe3,0x66,0x50,0x6e,0x5a,0x6c,0x06,0xdd, + 0xe9,0xf4,0x2d,0xc9,0x75,0x7f,0x41,0xbb,0x33,0x2e,0xdf,0x1d,0xed,0xd1,0x62,0x67, + 0x5c,0x8f,0x35,0xe2,0xa6,0xc8,0x9b,0xa6,0x1f,0xbd,0x1b,0x6f,0x73,0xb7,0xd4,0xd7, + 0x7b,0x74,0x86,0x3b,0xf4,0xb2,0xf4,0xa7,0xf7,0xe7,0x3d,0x62,0xce,0xb8,0xbd,0x7c, + 0x9f,0xb9,0xfa,0xdd,0x5e,0x9e,0x05,0xb7,0x7d,0x3e,0x87,0xee,0x59,0xf2,0xf4,0xbb, + 0xf7,0x01,0x79,0xe7,0xc9,0xab,0xa4,0x73,0xc8,0xf1,0xd7,0x79,0x0f,0x17,0xc1,0xfa, + 0xa4,0x8a,0x7e,0x13,0x3f,0xa4,0x87,0x73,0x7c,0x03,0x2f,0xba,0x7a,0xd7,0xa9,0xb7, + 0xd7,0xd5,0xfb,0x15,0xfc,0x8a,0xc4,0xa8,0xff,0x1b,0x58,0xb7,0x3b,0xf3,0xdf,0xc1, + 0x7b,0x38,0xf3,0x59,0x77,0xe6,0xca,0xfd,0x21,0x36,0xcb,0x39,0xea,0xef,0x67,0x24, + 0xa6,0x8f,0x5e,0xf4,0x8c,0x8d,0x9b,0x75,0x3a,0x7f,0xa2,0xd3,0xef,0x74,0xfe,0x02, + 0x37,0x9d,0x39,0xa7,0xa3,0xdc,0x0d,0xb1,0x39,0x6a,0xdd,0x40,0xa7,0xee,0x74,0x8c, + 0x9b,0x73,0x3a,0x37,0xd1,0x39,0xe8,0x74,0xfe,0x06,0x37,0x9d,0x79,0xa7,0xa3,0xdc, + 0x2d,0xb1,0x79,0x6a,0xdd,0x42,0x67,0xc0,0xe9,0x18,0x37,0xef,0x74,0xfe,0x41,0xa7, + 0xd7,0xe9,0xdc,0x06,0x37,0x9d,0x05,0xa7,0x73,0x3b,0xed,0x5b,0x48,0x98,0xd6,0xba, + 0x83,0xce,0xa0,0xd3,0x31,0x6e,0xc1,0xe9,0xdc,0x45,0xe7,0x90,0xd3,0xf9,0x1f,0xdc, + 0x74,0x16,0x9d,0x8e,0x72,0xf7,0xc4,0x16,0xa9,0x75,0x0f,0x9d,0x21,0xa7,0x63,0xdc, + 0xa2,0xd3,0x89,0x31,0xd7,0x39,0xec,0x74,0x0a,0x31,0xc7,0x4d,0xa7,0x14,0x97,0x75, + 0x94,0xcb,0xc4,0x14,0xd3,0x5a,0xfa,0x5b,0x75,0x86,0x9d,0x8e,0x71,0xa5,0xb8,0xac, + 0xd3,0x8c,0xce,0x31,0xa7,0xb3,0x22,0xe6,0xb8,0xe9,0x54,0x9d,0x8e,0x72,0x2d,0x62, + 0x55,0x6a,0xb5,0xa0,0x33,0xe2,0x74,0x8c,0xab,0x3a,0x9d,0x95,0xe8,0x1c,0x77,0x3a, + 0xad,0x31,0xc7,0x4d,0xa7,0xdd,0xe9,0x28,0xd7,0x26,0xd6,0x4e,0xad,0x36,0x74,0x46, + 0x9d,0x8e,0x71,0xfa,0xbc,0x2f,0x5f,0x95,0xed,0x62,0x0f,0x00,0xb3,0x2b,0x01,0xe5, + 0x6c,0x0c,0x00,0x00 }; // Generated from: @@ -105,6 +107,7 @@ constexpr uint8_t kBlitResolve_frag_00000004[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -178,7 +181,7 @@ constexpr uint8_t kBlitResolve_frag_00000004[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// ivec4 colorValue = texture(isampler2D(color, blitSampler), srcImageCoords * params . invSrcExtent); +// ivec4 colorValue = textureLod(isampler2D(color, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip); // // broadcastColor(colorValue); // diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000005.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000005.inc index 2fe92df934f..a381873b90d 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000005.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000005.inc @@ -10,75 +10,77 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000005[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x65,0x95,0x5f,0x68,0xd6,0x65, - 0x14,0xc7,0x9f,0xdf,0xfb,0x77,0xeb,0x5d,0xeb,0x15,0xdd,0x56,0xf6,0xee,0x5f,0xca, - 0x10,0x26,0xba,0x0b,0x8b,0x46,0x14,0x05,0x42,0x5d,0x08,0xfe,0x09,0xda,0x2e,0x76, - 0xf3,0x42,0x5e,0x34,0x28,0x61,0x89,0x37,0xbb,0x30,0x68,0x81,0x37,0xbb,0xd8,0xcd, - 0x6e,0xd6,0xb2,0x59,0x64,0xf6,0x4f,0xbb,0x8b,0x52,0x29,0x49,0x1d,0xc5,0xac,0x51, - 0x2c,0x1d,0x0d,0xfa,0xc7,0x40,0x65,0xa0,0x32,0x71,0x2a,0x6a,0xe7,0x3c,0xbf,0xcf, - 0xd1,0xc3,0xab,0x70,0x7c,0x7e,0xe7,0xfb,0x3d,0xe7,0x7c,0x9f,0xf3,0x3c,0xe7,0x79, - 0x97,0xcd,0xac,0x2b,0x86,0x90,0x84,0x47,0x42,0x5d,0xe8,0x4c,0x42,0xfc,0xb7,0x2a, - 0x64,0x82,0x7e,0x96,0x42,0x21,0xae,0x2f,0x6f,0x7b,0x75,0xdb,0xa6,0xb7,0xf7,0xbe, - 0xbe,0x69,0xcb,0xd3,0x3d,0xca,0x37,0x86,0x6c,0x8c,0x53,0xee,0x31,0xf1,0x72,0xb2, - 0xaa,0xbd,0x59,0x7d,0xe3,0x2d,0xc5,0x9b,0xc5,0xfa,0xc5,0xaa,0x62,0x83,0x62,0x43, - 0x62,0xc3,0x62,0x23,0x62,0xa3,0x62,0xe3,0x62,0x65,0xa9,0xa1,0x39,0x45,0xad,0x2f, - 0x5f,0xcd,0x51,0x4f,0xeb,0x85,0xf0,0x4a,0xc8,0x87,0xd6,0x74,0x2b,0x61,0x1d,0xab, - 0x61,0x09,0x58,0x9d,0xc3,0x32,0x60,0x65,0x87,0x65,0xc1,0x1e,0x77,0x58,0x0e,0xac, - 0xe2,0xb0,0x3c,0x58,0x87,0xc3,0x0a,0x60,0xeb,0x1d,0x56,0x04,0xdb,0xe0,0xb0,0x3a, - 0xb0,0x8d,0x0e,0xab,0x07,0xeb,0x89,0x7d,0x65,0xef,0xef,0x4f,0x7b,0xd4,0x33,0x69, - 0xa3,0x1f,0xf5,0xab,0xf8,0x09,0xfe,0x20,0xbe,0xc5,0x0f,0xe1,0x67,0xf1,0x87,0xf1, - 0x73,0xf8,0x23,0xf8,0x79,0xfc,0x51,0xfc,0x02,0xfe,0x38,0xbe,0x9d,0xf1,0xa4,0xac, - 0x4f,0x39,0x7d,0xf5,0x3b,0x9d,0x3f,0x55,0xc3,0x4f,0xc1,0xeb,0x7e,0x56,0xcb,0xff, - 0x99,0xe8,0x67,0xe3,0x7e,0x32,0xf1,0x9e,0xb3,0x51,0x4b,0xcf,0xae,0x45,0xe2,0x8b, - 0x68,0x2b,0xd7,0x24,0x7e,0x09,0x2e,0x81,0x6f,0xe0,0x8e,0x73,0xf8,0x6b,0x88,0xcf, - 0xc5,0xb8,0x9c,0xe4,0xa4,0xb1,0x8a,0x3f,0x87,0xdf,0x0c,0xa6,0xf5,0x2a,0xd4,0x0b, - 0xb1,0xaf,0x86,0xfb,0xf7,0x62,0x56,0xc2,0x0a,0xac,0x15,0x67,0x5a,0xbf,0x8d,0xfb, - 0x69,0xa5,0xbe,0xfa,0xed,0x60,0xdd,0x35,0xfb,0xd5,0xf8,0x4e,0xb8,0xa2,0xe3,0xbb, - 0xd0,0x37,0xbf,0x1b,0x5e,0xe3,0x37,0x12,0x5f,0x89,0x3d,0x64,0xc2,0x66,0xe2,0x2a, - 0xcc,0x83,0xcf,0xeb,0x65,0x7e,0xcc,0xdf,0x5a,0xb3,0x8f,0xed,0xf4,0xa1,0x75,0x77, - 0xc0,0x95,0xf0,0xfb,0x98,0x89,0x06,0xfa,0xe8,0xe3,0xbd,0x65,0x5d,0xfe,0x00,0xf7, - 0x60,0x7c,0xb5,0x86,0xdf,0xcd,0xb9,0x1b,0x3f,0x08,0x6f,0xfe,0x50,0x4d,0xfc,0x3e, - 0xde,0x97,0xf1,0xc3,0x35,0xfc,0x7e,0xce,0xce,0xf8,0x91,0x1a,0xfe,0x80,0xd8,0x8b, - 0x8e,0x1f,0xad,0xe1,0xc7,0xc4,0xde,0x71,0xfc,0x38,0xfc,0x13,0xd2,0xf9,0x04,0xbd, - 0xf3,0xf3,0xf4,0xd0,0xaa,0x67,0xf2,0x3e,0xdf,0x13,0xd4,0x50,0x7f,0x12,0x6c,0xad, - 0x9c,0xc4,0x41,0xe2,0x3e,0x04,0x3b,0x48,0x9c,0xfa,0x53,0x60,0x4f,0x8a,0xe2,0x47, - 0xd4,0xb0,0x7d,0x1d,0x61,0x1f,0x3a,0xaf,0x5f,0x72,0x27,0xea,0x3f,0x23,0xaf,0x2e, - 0xc3,0x19,0x06,0xb0,0x15,0x41,0xf4,0x2d,0x3e,0xcf,0x6c,0x7f,0xc3,0xfc,0xee,0x14, - 0x54,0xf3,0xbe,0x05,0x0b,0x0e,0xfb,0x0e,0x4c,0x7b,0xd9,0x21,0x98,0xce,0xd2,0x71, - 0x62,0x95,0x7b,0x49,0x30,0x9d,0xc3,0x13,0xcc,0x6a,0x07,0xf5,0x35,0xee,0x24,0xf8, - 0x7b,0xe4,0x7d,0x4f,0xee,0x49,0x97,0xf7,0x03,0x79,0x5d,0x2e,0xef,0x14,0xf8,0xbb, - 0xe4,0xfd,0x48,0xee,0x29,0xf2,0x74,0x8e,0x4f,0x93,0xd7,0x4d,0x9e,0xce,0xf0,0x19, - 0xf0,0xcf,0x25,0x46,0x67,0xfb,0x2c,0x98,0xce,0xf6,0x0d,0x39,0x81,0x19,0x7a,0xbb, - 0x25,0xf1,0xca,0x4d,0x8b,0xcd,0x70,0x2e,0xd3,0xae,0xe7,0x9f,0xd0,0x0c,0x71,0x6e, - 0x72,0x11,0xfb,0x19,0x7c,0x97,0x78,0xba,0xa7,0xb5,0x49,0x8a,0x59,0xdc,0x4d,0xa9, - 0x61,0xb5,0x74,0xbd,0x2e,0x51,0x1a,0xd7,0x96,0xa4,0x31,0x79,0x72,0xa6,0x5d,0x0f, - 0xe7,0xe8,0xa1,0xd7,0xf5,0xf0,0x0b,0xb8,0xf5,0xf0,0x2b,0x98,0xf5,0x30,0xe7,0x7a, - 0x50,0x6e,0x56,0x6c,0x0e,0xdd,0x59,0xd7,0xc3,0x6f,0x68,0x27,0xae,0x87,0xdf,0xc1, - 0xad,0x87,0xd6,0x24,0xc5,0x2c,0x4e,0x7b,0xb0,0x5a,0x73,0xae,0x87,0xf6,0x24,0x8d, - 0x99,0x21,0x67,0xd6,0xf5,0xf0,0x07,0x3d,0x6c,0x75,0x3d,0x9c,0x07,0xb7,0x1e,0x2e, - 0x80,0x59,0x0f,0x0b,0xae,0x07,0xe5,0xe6,0xc5,0x16,0xd0,0x9d,0x8f,0xbf,0x2d,0xa9, - 0xee,0x9f,0x68,0xb7,0x27,0x0f,0xde,0x92,0xee,0xd1,0x62,0x17,0xdc,0x1e,0x3b,0x88, - 0x9b,0x23,0x6f,0x9e,0xfd,0xe8,0x5b,0xf9,0x80,0xb7,0xa6,0xbe,0xbe,0xab,0x43,0xbc, - 0xa9,0xd7,0x64,0x7f,0xfa,0x9e,0x3e,0x26,0xe6,0x90,0x9b,0xcb,0x4f,0xe8,0x6b,0xc0, - 0xcd,0xe5,0x61,0x70,0x9b,0xe7,0x4f,0xd1,0x3d,0x4c,0x9e,0xfe,0x0e,0x7e,0x46,0xde, - 0x11,0xf2,0x4a,0xf1,0x1c,0x52,0x7c,0x0f,0xf7,0xf0,0x05,0x98,0xdd,0xd5,0x57,0xd4, - 0xf2,0xef,0xee,0x28,0x58,0xfa,0xee,0x0a,0xf1,0x6d,0x1f,0x23,0xf6,0x28,0x35,0xfa, - 0x24,0x56,0x7f,0x63,0xbf,0xa6,0x87,0x63,0x6e,0x1f,0x7f,0xb1,0x8f,0xed,0x6e,0x1f, - 0x7f,0x83,0x9f,0x95,0x18,0xf5,0xff,0x01,0xeb,0x70,0x77,0xf5,0x2f,0x78,0x17,0x77, - 0xb5,0xe8,0xee,0x4a,0xb9,0xff,0xc4,0x16,0x39,0x7f,0xfd,0x7e,0x41,0x62,0xfa,0xd9, - 0x83,0xde,0x8d,0x71,0x8b,0x4e,0xe7,0x22,0x3a,0x03,0x4e,0xe7,0x12,0xb8,0xe9,0x2c, - 0x39,0x1d,0xe5,0x2e,0x8b,0x2d,0x51,0xeb,0x32,0x3a,0x55,0xa7,0x63,0xdc,0x92,0xd3, - 0xb9,0x82,0xce,0x6e,0xa7,0x73,0x15,0xdc,0x74,0x96,0x9d,0x8e,0x72,0xd7,0xc4,0x96, - 0xa9,0x75,0x0d,0x9d,0x41,0xa7,0x63,0xdc,0xb2,0xd3,0xb9,0x81,0x4e,0xaf,0xd3,0x59, - 0x01,0x37,0x9d,0xdb,0x4e,0x67,0x25,0xd6,0x0a,0x11,0xd3,0x5a,0x37,0xd1,0x19,0x72, - 0x3a,0xc6,0xdd,0x76,0x3a,0x77,0xd1,0xd9,0xe7,0x74,0xee,0x81,0x9b,0x4e,0x26,0x79, - 0xa0,0x73,0x8f,0x3f,0x3a,0x8a,0x69,0x2d,0xfd,0x56,0x9d,0x61,0xa7,0x63,0x9c,0xae, - 0xa6,0x93,0x4f,0x52,0x9d,0xfd,0x4e,0xa7,0x90,0xa4,0xb8,0xe9,0xd4,0x3b,0x1d,0xe5, - 0x8a,0x62,0xf5,0xd4,0x2a,0xa2,0x33,0xe2,0x74,0x8c,0xab,0x77,0x3a,0x0d,0xe8,0x1c, - 0x70,0x3a,0x8f,0x26,0x29,0x6e,0x3a,0x65,0xa7,0xa3,0x5c,0xa3,0x58,0x99,0x5a,0x8d, - 0xe8,0x8c,0x3a,0x1d,0xe3,0xca,0x4e,0x67,0x35,0x3a,0x63,0x4e,0x67,0x4d,0x92,0xe2, - 0xa6,0xd3,0xe2,0x74,0x94,0x6b,0x12,0x6b,0xa1,0x56,0x13,0x3a,0xe3,0x4e,0xc7,0x38, - 0x5d,0xef,0xc8,0xc1,0x3e,0x2b,0xf6,0x3f,0x63,0xd5,0xbd,0xf8,0x9c,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x65,0x94,0x4d,0x68,0x9d,0x55, + 0x10,0x86,0xcf,0xb9,0xdf,0xfd,0x49,0x93,0xab,0x4d,0x88,0xa6,0x31,0xde,0xd4,0xfc, + 0x94,0x20,0xa4,0xd4,0x2e,0xaa,0x58,0xa4,0x45,0xa1,0xa0,0x8b,0x42,0xab,0x82,0xcd, + 0x22,0x9b,0x0b,0xcd,0xc2,0x80,0x0a,0x51,0xba,0xc9,0xa2,0x82,0x11,0xba,0xc9,0xa2, + 0x9b,0x6c,0x6a,0xad,0xa9,0x62,0x6d,0xab,0x6d,0xb5,0xee,0xc4,0x9f,0xa2,0xa5,0x6a, + 0x50,0xa2,0x06,0x4b,0xd4,0x60,0xc0,0x3f,0x02,0x5a,0x02,0xb6,0x44,0x6b,0x0d,0xce, + 0x9c,0xef,0x99,0x66,0xb8,0x06,0x26,0xe7,0xce,0xfb,0xce,0xcc,0x7b,0xe6,0x9c,0x39, + 0x5f,0x56,0xe8,0xaf,0x84,0x10,0x43,0x73,0x68,0x0a,0x9b,0x62,0x48,0x7f,0x6d,0xa1, + 0x10,0xf4,0x67,0x4b,0x28,0xa7,0xf5,0xe1,0xdd,0x8f,0xef,0xde,0xf2,0xec,0x73,0xfb, + 0xb7,0x6c,0xbb,0x77,0xab,0xf2,0xb7,0x86,0x2c,0xc5,0x29,0xb7,0x5e,0xbc,0xa2,0xac, + 0x6a,0x4f,0xd5,0x9f,0x7c,0x5a,0xf1,0x0e,0xb1,0x21,0xb1,0xba,0xd8,0xa8,0xd8,0x98, + 0xd8,0xb8,0xd8,0x84,0xd8,0xa4,0xd8,0x94,0x58,0xab,0xd4,0xd0,0x9c,0x8a,0xd6,0x97, + 0x5f,0x1d,0x49,0x4f,0xeb,0x85,0xf0,0x48,0x28,0x85,0xee,0x7c,0x2b,0xa1,0x9f,0xd5, + 0xb0,0x08,0xd6,0xe4,0xb0,0x02,0x58,0xab,0xc3,0x32,0xb0,0x4e,0x87,0x15,0xc1,0x6a, + 0x0e,0x2b,0x81,0xf5,0x38,0xac,0x0c,0xb6,0xc9,0x61,0x15,0xb0,0xbb,0x1d,0xd6,0x04, + 0xb6,0xd9,0x61,0xeb,0xc0,0xb6,0x3a,0xac,0x19,0x6c,0x5b,0xea,0x35,0xbb,0xb9,0x67, + 0xed,0x5b,0xcf,0x69,0x23,0x3d,0xaa,0x5f,0xc7,0x8f,0xf8,0xa3,0xf8,0x16,0x3f,0x86, + 0x9f,0xe1,0x8f,0xe3,0x17,0xf1,0x27,0xf0,0x4b,0xf8,0x93,0xf8,0x65,0xfc,0x29,0x7c, + 0x3b,0xf7,0xa3,0xb2,0xf6,0x39,0x7d,0xf5,0x7b,0x9d,0x3f,0xdd,0xc0,0x4f,0xc3,0xeb, + 0x7e,0xda,0xe5,0x7f,0x21,0xf9,0x59,0xda,0x4f,0x21,0xdd,0x7d,0x96,0xb4,0xf4,0x3c, + 0x37,0x48,0x7c,0x05,0x6d,0xe5,0x6e,0x17,0xbf,0x05,0x2e,0xc2,0x57,0xb9,0xf7,0x22, + 0xfe,0x6d,0xc4,0x17,0x53,0x5c,0x51,0x72,0xf2,0x58,0xc5,0x1f,0xc0,0xef,0x00,0xd3, + 0x7a,0x35,0xea,0x85,0xd4,0xd7,0x2d,0x37,0xef,0xca,0xac,0xc5,0x59,0x99,0xb5,0xe6, + 0x4c,0x35,0x36,0x72,0x6f,0xdd,0x68,0xa8,0x7f,0x17,0xd8,0x60,0xc3,0x9e,0x35,0xbe, + 0x17,0xae,0xe2,0xf8,0x01,0xf6,0x60,0xfe,0x20,0xf3,0xa1,0xf1,0x9b,0x89,0xaf,0xa5, + 0x3e,0x0a,0xe1,0x1e,0xe2,0x6a,0xcc,0x89,0xcf,0xdb,0xde,0xa0,0xbb,0x8b,0xf9,0x31, + 0x7f,0x0f,0xba,0x5a,0x77,0x2f,0xb1,0x2d,0xf8,0xfb,0x98,0x8b,0x2a,0x7d,0xec,0xe3, + 0x1d,0x66,0x2e,0x7f,0x98,0xbb,0x30,0xbe,0xde,0xc0,0x8f,0x70,0xf6,0xc6,0x8f,0xc2, + 0x9b,0x3f,0xd6,0x10,0x7f,0x80,0x77,0x67,0xfc,0x78,0x03,0x7f,0x90,0xb3,0x33,0x7e, + 0xa2,0x81,0x3f,0x24,0xf6,0xa0,0xe3,0x27,0x1b,0xf8,0xc3,0x62,0xcf,0x3b,0x7e,0x0a, + 0xfe,0x0e,0xe9,0xfc,0x08,0xbd,0xf3,0xd9,0xfa,0xdf,0xaa,0x67,0xf2,0x12,0xbf,0x8f, + 0x50,0x43,0xfd,0xa3,0x60,0x5d,0x72,0x12,0xc7,0x88,0x7b,0x05,0xec,0x18,0x71,0xea, + 0x4f,0x83,0xdd,0x29,0x8a,0xaf,0x52,0x43,0x67,0xf4,0x4d,0x66,0xc9,0xef,0xf3,0x1c, + 0xfe,0x7d,0xf2,0xf2,0x0a,0x9c,0x61,0x00,0xfb,0x4b,0x10,0x7d,0x8f,0x3b,0x98,0xef, + 0xf7,0x98,0xe1,0x47,0x05,0xd5,0x3a,0xef,0x83,0x05,0x87,0x7d,0x00,0xa6,0xbd,0xec, + 0x15,0x4c,0xef,0xfc,0x43,0x62,0x95,0x7b,0x48,0x30,0x9d,0xc3,0x8f,0x98,0xd5,0x1e, + 0xea,0x6b,0xdc,0x05,0xf0,0x17,0xc9,0xfb,0x98,0xdc,0x0b,0x2e,0xef,0x13,0xf2,0x06, + 0x5c,0xde,0x45,0xf0,0x17,0xc8,0xbb,0x44,0xee,0x45,0xf2,0x74,0x8e,0x3f,0x25,0x6f, + 0x90,0x3c,0x9d,0xe1,0xcf,0xc0,0x4f,0x4b,0x8c,0xce,0xf6,0xe7,0x60,0x3a,0xdb,0x2b, + 0x72,0x02,0xb3,0xf4,0x76,0x5d,0xe2,0x95,0x9b,0x11,0x9b,0xe5,0x5c,0x66,0x5c,0xcf, + 0x5f,0xa0,0x19,0xd2,0xdc,0x14,0x13,0xf6,0x25,0xf8,0x63,0xe2,0xe9,0x9e,0xba,0x63, + 0x8e,0x59,0xdc,0xdf,0x52,0xc3,0x6a,0xe9,0x7a,0x4d,0xa2,0x34,0xae,0x37,0xe6,0x31, + 0x25,0x72,0x66,0x5c,0x0f,0x5f,0xd1,0xc3,0x76,0xd7,0xc3,0xd7,0xe0,0xd6,0xc3,0x37, + 0x60,0xd6,0xc3,0xbc,0xeb,0x41,0xb9,0x39,0xb1,0x79,0x74,0xe7,0x5c,0x0f,0xdf,0xa2, + 0x1d,0x5d,0x0f,0x97,0xc1,0xad,0x87,0x9e,0x98,0x63,0x16,0xa7,0x3d,0x58,0xad,0x79, + 0xd7,0x43,0x5f,0xcc,0x63,0x66,0xc9,0x99,0x73,0x3d,0x7c,0x47,0x0f,0xbb,0x5c,0x0f, + 0xdf,0x83,0x5b,0x0f,0x3f,0x80,0x59,0x0f,0x8b,0xae,0x07,0xe5,0x16,0xc4,0x16,0xd1, + 0x5d,0x48,0xdf,0x96,0x5c,0xf7,0x47,0xb4,0xfb,0xe2,0xda,0x5b,0xd2,0x3d,0x5a,0xec, + 0xa2,0xdb,0x63,0x3f,0x71,0xf3,0xe4,0x2d,0xb0,0x1f,0x7d,0x2b,0x2f,0xf3,0xd6,0xd4, + 0xd7,0x77,0x75,0x9c,0x37,0xf5,0x84,0xec,0x4f,0xdf,0xd3,0x6b,0xc4,0x1c,0x77,0x73, + 0xf9,0x3a,0x7d,0x0d,0xbb,0xb9,0x3c,0x01,0x6e,0xf3,0xfc,0x06,0xba,0x27,0xc8,0xd3, + 0xef,0xe0,0x49,0xf2,0x46,0xc8,0xd3,0x37,0x79,0x0a,0xfc,0x19,0xee,0xe1,0x34,0x98, + 0xdd,0xd5,0x5b,0xd4,0xf2,0xef,0xee,0x0c,0x58,0xfe,0xee,0xca,0xe9,0xad,0x9f,0x25, + 0xf6,0x0c,0x35,0x4c,0xf3,0x6d,0x34,0xcf,0x39,0xcd,0x77,0xc0,0x4d,0xf3,0x3c,0xd8, + 0x90,0xec,0x5c,0xbf,0xcb,0xef,0xd2,0xf7,0x59,0xbe,0xc3,0xe7,0x5d,0xbd,0x9f,0xa8, + 0xb7,0xc7,0xd5,0xfb,0x19,0xfc,0x92,0xc4,0xa8,0xff,0x0b,0x58,0x8f,0xbb,0xe7,0x5f, + 0xc1,0x07,0xb8,0xe7,0x25,0x77,0xcf,0xca,0xfd,0x26,0xb6,0xc4,0xdd,0xe9,0xef,0x9d, + 0x12,0x33,0xc4,0x5e,0xf4,0x5e,0x8d,0x5b,0x72,0x3a,0xbf,0xa3,0x33,0xec,0x74,0xfe, + 0x00,0x37,0x9d,0x65,0xa7,0xa3,0xdc,0x15,0xb1,0x65,0x6a,0x5d,0x41,0xa7,0xee,0x74, + 0x8c,0x5b,0x76,0x3a,0x7f,0xa2,0x33,0xe2,0x74,0xae,0x82,0x9b,0xce,0x8a,0xd3,0xb9, + 0x9a,0x66,0x2f,0x24,0x4c,0x6b,0x5d,0x43,0x67,0xd4,0xe9,0x18,0xb7,0xe2,0x74,0xae, + 0xa3,0x33,0xe8,0x74,0xfe,0x01,0x37,0x9d,0x55,0xa7,0xa3,0xdc,0x0d,0xb1,0x55,0x6a, + 0xdd,0x40,0x67,0xcc,0xe9,0x18,0xb7,0xea,0x74,0x62,0xcc,0x75,0x0e,0x38,0x9d,0x42, + 0xcc,0x71,0xd3,0x29,0xc5,0x35,0x1d,0xe5,0x32,0x31,0xc5,0xb4,0x96,0xfe,0x56,0x9d, + 0x71,0xa7,0x63,0x5c,0x29,0xae,0xe9,0x34,0xa1,0x73,0xd0,0xe9,0xac,0x8b,0x39,0x6e, + 0x3a,0x55,0xa7,0xa3,0x5c,0xb3,0x58,0x95,0x5a,0xcd,0xe8,0x4c,0x38,0x1d,0xe3,0xaa, + 0x4e,0x67,0x3d,0x3a,0x87,0x9c,0x4e,0x6b,0xcc,0x71,0xd3,0x69,0x77,0x3a,0xca,0xb5, + 0x89,0xb5,0x53,0xab,0x0d,0x9d,0x49,0xa7,0x63,0x5c,0xbb,0xd3,0xe9,0x40,0xe7,0xb0, + 0xd3,0xd9,0x10,0x73,0xdc,0x74,0xba,0x9c,0x8e,0x72,0x9d,0x62,0x5d,0xd4,0xea,0x44, + 0x67,0xca,0xe9,0x18,0xa7,0xeb,0xbf,0xf2,0xa2,0xef,0x17,0xfb,0x0f,0x34,0xc7,0xaf, + 0x2a,0xf0,0x0c,0x00,0x00 }; // Generated from: @@ -107,6 +109,7 @@ constexpr uint8_t kBlitResolve_frag_00000005[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -180,7 +183,7 @@ constexpr uint8_t kBlitResolve_frag_00000005[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// ivec4 colorValue = texture(isampler2DArray(color, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)); +// ivec4 colorValue = textureLod(isampler2DArray(color, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip); // // broadcastColor(colorValue); // diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000006.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000006.inc index a42ca7110b3..b53092e8e7e 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000006.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000006.inc @@ -10,77 +10,78 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000006[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4b,0x68,0x5d,0x65, - 0x14,0x85,0xcf,0xb9,0xe7,0xe6,0xde,0xb4,0xb7,0xb1,0x69,0x93,0x26,0x6a,0x6e,0x9a, - 0x68,0xad,0xf8,0x28,0xa5,0x10,0x15,0x41,0x2c,0x75,0xa4,0x95,0x06,0x31,0x1d,0x74, - 0x12,0x30,0x82,0x19,0x38,0x48,0xa5,0x28,0x19,0x74,0x60,0x8a,0x9d,0x64,0x50,0x84, - 0x4c,0xa4,0xed,0x40,0x5b,0x2b,0x14,0x11,0xab,0xd6,0xce,0xaa,0x16,0x1f,0xa5,0x12, - 0x6b,0x50,0xa2,0x0d,0x06,0x7c,0x94,0x80,0x96,0x80,0x96,0x80,0xa9,0xf1,0x11,0xe2, - 0x5e,0xe7,0x7c,0x3b,0xdd,0xdc,0xc0,0xee,0x39,0x7b,0xad,0xfd,0xef,0xb5,0xd7,0x7f, - 0xfe,0xff,0x36,0x2b,0x6d,0xa9,0x26,0x49,0x9a,0xac,0x4d,0x9a,0x93,0xde,0x34,0xc9, - 0xff,0x36,0x24,0xa5,0x44,0xaf,0xb5,0xa4,0x92,0x3f,0x1f,0xdf,0xb3,0x77,0xcf,0xf6, - 0x17,0x5f,0x7a,0x6e,0xfb,0x03,0x0f,0xee,0x10,0x7f,0x4b,0x92,0xe5,0x75,0xe2,0xd6, - 0x5b,0x56,0xb6,0xa7,0x62,0xe4,0xd9,0xe7,0xf7,0x0b,0xef,0xb0,0xd8,0x6b,0x31,0x68, - 0x31,0x2c,0xdc,0x62,0xd4,0x62,0xcc,0x62,0xdc,0x62,0xc2,0xa2,0xd5,0x7a,0x68,0x4d, - 0x55,0xfd,0xed,0xad,0x23,0xd7,0x53,0xbf,0x24,0x79,0x22,0x69,0x4a,0xea,0xc5,0x28, - 0xc9,0x16,0x9e,0x8e,0xa5,0x60,0xcd,0x01,0x2b,0x81,0xb5,0x06,0x2c,0x03,0xbb,0x35, - 0x60,0x65,0xb0,0x7a,0xc0,0x9a,0xc0,0x7a,0x03,0x56,0x01,0xbb,0x2b,0x60,0x55,0xb0, - 0x7b,0x02,0xd6,0x0c,0xb6,0x2d,0x60,0x6b,0xc0,0x76,0xe4,0xbe,0xb2,0xd5,0xf9,0xe4, - 0x51,0x7b,0xb2,0x19,0x3f,0xca,0x07,0xc9,0x53,0xf2,0x61,0x72,0xaf,0x1f,0x21,0xcf, - 0xc8,0x47,0xc9,0xcb,0xe4,0x63,0xe4,0x4d,0xe4,0xe3,0xe4,0x15,0xf2,0x09,0x72,0xdf, - 0xe3,0x53,0xf6,0xbc,0x33,0xe8,0x2b,0xbf,0x83,0xbc,0xcd,0x54,0x4b,0x79,0x9e,0xe5, - 0x7a,0x7a,0xdf,0x64,0x35,0x15,0xf6,0x46,0x33,0x76,0x5a,0x5e,0xa5,0x7f,0x89,0xbc, - 0x46,0x5e,0xce,0xbf,0x7b,0x66,0x7d,0x8a,0x7a,0x71,0xed,0x79,0xdf,0x82,0xeb,0xb5, - 0x7f,0x37,0xd1,0x47,0xf8,0x23,0xe4,0x1d,0xa1,0x77,0x27,0xf5,0xae,0xdd,0x45,0xaf, - 0x24,0xf7,0xb1,0x6e,0xf5,0x3b,0x74,0x12,0x15,0xa2,0x8d,0x67,0x57,0x08,0xe9,0x75, - 0xf3,0x3d,0xea,0xe8,0x75,0xb3,0x1f,0xc2,0xee,0xc7,0x5b,0x0f,0xfd,0x55,0xdf,0x0b, - 0x57,0x0d,0xfc,0x56,0x72,0xf1,0x77,0xc3,0x77,0xe5,0x1e,0x4a,0xc9,0xbd,0xd4,0x29, - 0xbf,0x8f,0x3e,0xbe,0xae,0x8f,0xf3,0xe1,0xf9,0xce,0x06,0xdd,0xdd,0xcc,0xac,0xbe, - 0x4f,0xc2,0x55,0x02,0xdf,0xcf,0xbe,0x88,0x1f,0xe0,0x0c,0xd4,0xf0,0x31,0xc0,0xfd, - 0xca,0x42,0xfd,0x3e,0xf6,0xcd,0xf9,0xc1,0x06,0x7e,0x88,0xef,0xe0,0xfc,0x30,0xbc, - 0xe7,0x23,0x0d,0xf5,0x07,0xb8,0x4f,0xce,0x8f,0x36,0xf0,0x07,0xf9,0x36,0xce,0x8f, - 0x35,0xf0,0x87,0x2d,0x76,0x05,0x7e,0xbc,0x81,0x3f,0x62,0x71,0x28,0xf0,0x13,0xf0, - 0xdb,0x6c,0xb7,0xe5,0xf3,0x35,0xbe,0x4d,0x8c,0xdb,0x6c,0x97,0x4e,0xb2,0x4f,0xfc, - 0x54,0xad,0xfe,0x0e,0xa5,0xe1,0x3b,0xbe,0xc9,0xfb,0x49,0xfa,0x2b,0x3f,0xd5,0xf0, - 0x7d,0xce,0x70,0x6f,0x54,0xff,0x1e,0xfb,0xaf,0x73,0xf4,0x90,0xa1,0x25,0xf6,0x2a, - 0x61,0xa6,0x25,0x43,0x54,0xfb,0x28,0x67,0xfa,0x3c,0xe7,0xf6,0x29,0x9b,0x55,0xe7, - 0xf0,0x23,0xb0,0xf3,0x61,0x9e,0xfd,0xdc,0x95,0x8f,0xe1,0x1f,0xb3,0x0e,0xda,0xaf, - 0x4f,0x38,0x83,0x3d,0xf4,0x53,0xcd,0x05,0xf0,0x57,0xac,0x46,0xf9,0xa7,0xac,0xbb, - 0xc0,0x3a,0x9d,0xbb,0xcf,0x58,0xb7,0x95,0x75,0x3a,0x73,0x9f,0x83,0xbf,0x63,0x35, - 0x3a,0x8b,0x5f,0x80,0xe9,0x2c,0xfe,0x65,0x93,0x4f,0x32,0xcf,0x3f,0x56,0x2f,0xee, - 0xa2,0xc5,0x24,0x7e,0xf4,0xfe,0xb4,0xad,0xd3,0x5e,0x5c,0x42,0x53,0x7f,0x2f,0xb3, - 0x3f,0x5f,0x82,0x0f,0x58,0x96,0xdf,0xb9,0xb4,0xc0,0xbc,0xee,0x6f,0xeb,0xe1,0xbd, - 0xf4,0x5c,0xb4,0x2a,0xd5,0x75,0xa5,0x45,0x4d,0x13,0x6b,0x2e,0x06,0x0f,0x5f,0xe1, - 0xa1,0x2f,0x78,0xb8,0x0c,0xee,0x1e,0xbe,0x06,0x73,0x0f,0xd3,0xc1,0x83,0xb8,0x29, - 0x8b,0x69,0x74,0xa7,0x82,0x87,0x6f,0xd0,0x4e,0x83,0x87,0x6f,0xc1,0xdd,0xc3,0xed, - 0x69,0x81,0x79,0x9d,0x3c,0x78,0xaf,0xe9,0xe0,0xa1,0x9e,0x16,0x35,0x93,0xac,0x99, - 0x0a,0x1e,0xbe,0xc3,0xc3,0xce,0xe0,0xe1,0x7b,0x70,0xf7,0x70,0x05,0xcc,0x3d,0xcc, - 0x06,0x0f,0xe2,0x66,0x2c,0x66,0xd1,0x9d,0xe1,0x1c,0x49,0xf7,0x07,0xb4,0xeb,0xe9, - 0xcd,0xf3,0xac,0x19,0xbd,0x76,0x36,0xcc,0xd8,0x4d,0xdd,0x34,0xeb,0x66,0xa8,0x3d, - 0x4a,0xed,0x51,0x6a,0x75,0x97,0x7a,0xd2,0xe2,0x3e,0x69,0xfd,0xdb,0x16,0xc7,0xe0, - 0xb4,0x47,0x9b,0xd3,0xe2,0x2c,0xce,0xe6,0xf3,0x17,0x9c,0xbc,0xea,0x37,0xe9,0x75, - 0xbc,0x0e,0xe1,0x55,0xf5,0x6f,0x80,0x7f,0x80,0xd7,0x13,0xf4,0x10,0x7e,0xc3,0x6a, - 0x8e,0xd3,0xc3,0xfd,0x9e,0x20,0x3f,0xce,0x5c,0xc7,0xe8,0xa5,0xbb,0xf9,0x16,0xf7, - 0xf2,0x19,0xe6,0x3c,0x0d,0x26,0x6f,0xbb,0xe8,0x7b,0xc8,0x74,0x6a,0xcc,0x2d,0x1f, - 0xa7,0x93,0x02,0xab,0x30,0xaf,0x6a,0xfa,0x1b,0xbc,0x4b,0xeb,0x05,0xee,0xea,0xbb, - 0xac,0x93,0x27,0xdd,0xf3,0xf7,0xf1,0x74,0x86,0x39,0xda,0x72,0x2f,0x05,0xfe,0xaa, - 0xd5,0x68,0xcd,0x59,0xd6,0x09,0x5f,0x67,0x4a,0xc2,0x3e,0x0c,0xbf,0x33,0x67,0xb9, - 0xdf,0x9a,0xeb,0x1c,0x9c,0xef,0xd9,0x8f,0xf4,0xdf,0x1d,0xf6,0xec,0x27,0xf0,0x4b, - 0xcc,0xfd,0x33,0x58,0x7f,0x38,0x33,0xbf,0x80,0xf7,0x70,0x66,0xe6,0xc2,0x1e,0x8a, - 0xbb,0x6a,0x31,0x87,0xbf,0xab,0xf9,0xf9,0xcb,0xf2,0xff,0x03,0xce,0xe1,0xdd,0xb9, - 0xb9,0xa0,0xf3,0x2b,0x3a,0xfb,0x82,0xce,0x6f,0xe0,0xae,0x33,0x1f,0x74,0xc4,0x5d, - 0xb3,0x98,0xa7,0xd7,0x35,0x74,0x06,0x83,0x8e,0x73,0xf3,0x41,0xe7,0x77,0x74,0x86, - 0x82,0xce,0x1f,0xe0,0xae,0xb3,0x10,0x74,0xc4,0x5d,0xb7,0x58,0xa0,0xd7,0x75,0x74, - 0x86,0x83,0x8e,0x73,0x0b,0x41,0xe7,0x4f,0x74,0xfa,0x82,0xce,0x22,0xb8,0xeb,0x2c, - 0x05,0x9d,0xc5,0xfc,0x4c,0x26,0x39,0xa6,0x5e,0x37,0xd0,0x19,0x09,0x3a,0xce,0x2d, - 0x05,0x9d,0x7f,0xd1,0x39,0x10,0x74,0xfe,0x03,0x77,0x9d,0x95,0xa0,0x23,0x6e,0xd9, - 0x62,0x85,0x5e,0xcb,0xe8,0x8c,0x06,0x1d,0xe7,0x56,0x82,0x4e,0x29,0x2d,0x74,0x0e, - 0x06,0x9d,0x2c,0x2d,0x70,0xd7,0xa9,0xa4,0x37,0x75,0xc4,0x95,0x2d,0x84,0xa9,0x97, - 0xde,0xa5,0x33,0x16,0x74,0x9c,0xd3,0xd3,0x75,0xd6,0xa0,0x73,0x38,0xe8,0xac,0x4d, - 0x0b,0xdc,0x75,0x5a,0x82,0x8e,0xb8,0x9a,0x45,0x0b,0xbd,0x6a,0xe8,0x8c,0x07,0x1d, - 0xe7,0x5a,0x82,0x4e,0x2b,0x3a,0x47,0x82,0xce,0x86,0xb4,0xc0,0x5d,0xa7,0x3d,0xe8, - 0x88,0xdb,0x68,0xd1,0x4e,0xaf,0x8d,0xe8,0x4c,0x04,0x1d,0xe7,0xf4,0x5c,0xb6,0xdb, - 0xf7,0xb0,0xc5,0xff,0x7c,0x50,0x47,0x18,0xb4,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x5f,0x68,0x97,0x65, + 0x14,0xc7,0x9f,0xf7,0xf7,0x77,0x6d,0x6b,0x69,0x6b,0x9b,0xb1,0xcd,0xcd,0x6c,0xd1, + 0x1f,0x11,0x41,0x8b,0x20,0x12,0xbb,0x2a,0xc3,0x11,0xcd,0x0b,0x6f,0x06,0x19,0xb4, + 0x8b,0x2e,0x66,0x48,0xb1,0x0b,0x2f,0x9a,0xe4,0xcd,0x2e,0x24,0xd8,0x4d,0xa8,0x17, + 0x96,0x66,0x20,0x15,0x69,0x99,0x77,0x56,0xd2,0x1f,0x2b,0x56,0x8d,0x62,0xda,0x68, + 0xd0,0x1f,0x19,0x94,0x0c,0x4a,0x06,0xce,0x16,0x29,0x9d,0xef,0xfb,0x7e,0xce,0x3a, + 0xfc,0x7e,0x70,0xf6,0xbe,0xe7,0xfb,0x3d,0xcf,0xf9,0x9e,0xf3,0x3c,0xe7,0x79,0x57, + 0x2e,0xad,0xaf,0xa7,0x94,0xa5,0xe6,0xd4,0x94,0xd6,0x65,0x29,0xff,0xad,0x4e,0xa5, + 0xa4,0xd7,0x96,0x54,0xcb,0x9f,0x8f,0xef,0xd8,0xb9,0x63,0xe3,0x8b,0x2f,0x3d,0xb7, + 0x71,0xcb,0x83,0x9b,0xc4,0xb7,0xa5,0x72,0x1e,0x27,0xee,0x36,0xf3,0x2a,0xf6,0x94, + 0x8d,0x3e,0xfb,0xfc,0x1e,0xe1,0x9d,0x66,0x3b,0xcd,0x86,0xcd,0x46,0x84,0x9b,0x8d, + 0x99,0x8d,0x9b,0x4d,0x98,0x4d,0x9a,0xad,0xb2,0x1c,0x5a,0x53,0x57,0x7e,0x7b,0xeb, + 0xcc,0xf5,0x94,0x2f,0xa5,0x27,0x52,0x35,0xf5,0x14,0xa5,0xa4,0xf5,0x3c,0x1d,0xcb, + 0xc0,0x9a,0x02,0x56,0x02,0x5b,0x15,0xb0,0x32,0xd8,0x9a,0x80,0x55,0xc0,0x7a,0x02, + 0x56,0x05,0xeb,0x0f,0x58,0x0d,0xec,0xee,0x80,0xd5,0xc1,0xee,0x0d,0x58,0x13,0xd8, + 0x86,0x80,0xdd,0x02,0xb6,0x29,0x60,0xcd,0x60,0x5b,0xf2,0x5e,0xcb,0x2b,0x35,0xab, + 0x6f,0xed,0xd3,0x5a,0x7a,0x94,0x3f,0x8c,0x9f,0xe1,0x8f,0xe0,0x7b,0xfc,0x28,0x7e, + 0x19,0x7f,0x0c,0xbf,0x82,0x3f,0x8e,0x5f,0xc5,0x9f,0xc0,0xaf,0xe1,0x4f,0xe2,0xfb, + 0xbe,0x9f,0xb0,0xe7,0x5d,0x41,0x5f,0xfe,0x3a,0xfc,0x76,0x53,0x2d,0xe5,0x7e,0x39, + 0xd7,0xd3,0x7b,0x87,0xc5,0xd4,0xd8,0x2f,0xd5,0xd8,0x65,0x7e,0x9d,0xfc,0x25,0xfc, + 0x16,0xfc,0x4a,0x3e,0x0b,0x65,0xcb,0x53,0xc4,0x8b,0xbb,0x23,0xcf,0x5b,0x70,0xfd, + 0xf6,0xb7,0x83,0x3c,0xc2,0x1f,0xc1,0xef,0x0c,0xb9,0xbb,0x88,0x77,0xed,0x6e,0x72, + 0xa5,0xbc,0x8f,0x5b,0x57,0xce,0xa6,0x0b,0xab,0x05,0x6b,0xe7,0xd9,0x1d,0x4c,0x9a, + 0xbd,0x9c,0x53,0x0f,0x9a,0xbd,0xec,0x89,0xb0,0x07,0xe8,0xaf,0x0f,0x0d,0xc5,0xf7, + 0xc3,0xd5,0x03,0x3f,0xc0,0xf9,0x8b,0xbf,0x07,0xbe,0x3b,0xef,0xa3,0x94,0xee,0x23, + 0x4e,0xfe,0xfd,0xe4,0xf1,0x75,0x9b,0x1b,0x74,0xb6,0x32,0x1f,0xee,0x6f,0x47,0x47, + 0x79,0x9f,0x24,0xb6,0x16,0xf8,0x41,0xf6,0x46,0xfc,0x10,0x73,0xd0,0x42,0x1f,0x43, + 0xdc,0xbb,0x72,0x88,0xdf,0xc5,0xde,0x39,0x3f,0xdc,0xc0,0xef,0xe6,0x2c,0x9c,0x1f, + 0x81,0x77,0x7f,0xb4,0x21,0x7e,0x2f,0xf7,0xcc,0xf9,0xb1,0x06,0x7e,0x1f,0xe7,0xe3, + 0xfc,0x78,0x03,0x7f,0xc0,0x6c,0x5b,0xe0,0x27,0x1a,0xf8,0x83,0x66,0xfb,0x03,0x3f, + 0x09,0xbf,0xc1,0x76,0x45,0x7d,0xbe,0xc6,0xd9,0x44,0xf3,0xb5,0x47,0x99,0xfb,0x3b, + 0x6d,0xd7,0x8e,0xb3,0x6f,0x7c,0xd2,0x56,0xbe,0x57,0x59,0x38,0xd7,0x37,0x79,0x3f, + 0x8e,0x9e,0xfc,0x13,0x0d,0xe7,0x75,0x8a,0x3c,0x8a,0x3f,0xcd,0x79,0x68,0xae,0x1e, + 0x32,0xa5,0x12,0x7b,0x97,0xa8,0xf1,0x6f,0x43,0xa4,0xff,0x28,0x73,0x7e,0x8e,0x59, + 0x7e,0xca,0x6a,0xd7,0x6c,0x7e,0x04,0x76,0x2e,0xd4,0xb3,0x87,0xfb,0xf3,0x31,0xfc, + 0x63,0x96,0x41,0xfb,0xf7,0x09,0x33,0xd9,0x47,0x3e,0xc5,0x9c,0x07,0x7f,0xc5,0x62, + 0xe4,0x7f,0xca,0xba,0xf3,0xac,0xd3,0x1c,0x7e,0xc6,0xba,0x01,0xd6,0x69,0x06,0x3f, + 0x07,0x7f,0xc7,0x62,0x34,0x9b,0x5f,0x80,0x69,0x36,0xaf,0x5b,0xe5,0x53,0xd4,0xf3, + 0x8f,0xc5,0x8b,0xbb,0x60,0x36,0x45,0x3f,0x7a,0x7f,0xda,0xd6,0x69,0x0f,0xbe,0x42, + 0x53,0xbf,0x97,0xd9,0x9f,0xaf,0xc1,0x87,0xcc,0x53,0x4d,0x6b,0xb2,0x02,0xf3,0xb8, + 0x65,0xcb,0xe1,0xb9,0xf4,0xbc,0x66,0x51,0x8a,0xeb,0xc9,0x8a,0x98,0x2a,0x6b,0x2e, + 0x84,0x1e,0xbe,0xa1,0x87,0xcd,0xa1,0x87,0x6f,0xc1,0xbd,0x87,0xef,0xc0,0xbc,0x87, + 0x99,0xd0,0x83,0xb8,0x69,0xb3,0x19,0x74,0xa7,0x43,0x0f,0xdf,0xa3,0x9d,0x85,0x1e, + 0x7e,0x00,0xf7,0x1e,0xba,0xb3,0x02,0xf3,0x38,0xf5,0xe0,0xb9,0x66,0x42,0x0f,0xbd, + 0x59,0x11,0x33,0xc5,0x9a,0xe9,0xd0,0xc3,0x45,0x7a,0xd8,0x1a,0x7a,0xb8,0x04,0xee, + 0x3d,0xfc,0x08,0xe6,0x3d,0xcc,0x85,0x1e,0xc4,0xcd,0x9a,0xcd,0xa1,0x3b,0xcb,0x1c, + 0x49,0xf7,0x27,0xb4,0x7b,0xb3,0xff,0xe7,0x59,0x35,0x7a,0xec,0x5c,0xa8,0x71,0x2d, + 0x71,0x33,0xac,0x9b,0x25,0xf6,0x10,0xb1,0x87,0x88,0xd5,0xdd,0xea,0xcf,0x8a,0xfb, + 0xa5,0xf5,0x6f,0x9b,0x1d,0x86,0xcb,0xbf,0x87,0x59,0x31,0x8b,0xe2,0xde,0x85,0x53, + 0xaf,0xfa,0x46,0xbd,0x4e,0xaf,0x47,0xe9,0x55,0xf1,0x6f,0x80,0xbf,0x4f,0xaf,0xc7, + 0xc8,0x21,0x7c,0xc9,0x62,0x8e,0x90,0xc3,0xfb,0x3d,0x86,0x7f,0x84,0xba,0x0e,0x93, + 0x4b,0x77,0xf3,0x2d,0xee,0xe5,0x33,0xd4,0x79,0x12,0x4c,0xbd,0x6d,0x23,0xef,0x7e, + 0xd3,0x69,0xa1,0x6e,0xf5,0x71,0x32,0x15,0x58,0x8d,0x7a,0x15,0x33,0xd8,0xd0,0xbb, + 0xb4,0x5e,0xe0,0xae,0xbe,0xc7,0x3a,0xf5,0x74,0x3a,0xaf,0xbb,0xe8,0xe9,0x14,0x75, + 0xe8,0xce,0x7f,0x00,0xfe,0xaa,0xc5,0x68,0xcd,0x19,0xd6,0x09,0x6f,0x35,0x25,0x61, + 0x1f,0x86,0xef,0xcc,0x19,0xee,0xb7,0xea,0x3a,0x0b,0xe7,0x7b,0xf6,0x33,0xf9,0xb7, + 0x87,0x3d,0xfb,0x05,0xfc,0x4b,0xea,0xfe,0x15,0x6c,0x30,0xcc,0xcc,0x6f,0xe0,0x7d, + 0xcc,0xcc,0x7c,0xd8,0x43,0x71,0x97,0xcd,0xe6,0xe9,0xef,0x72,0x3e,0x7f,0xe5,0xfc, + 0x7f,0xc2,0x59,0x7a,0x77,0x6e,0x3e,0xe8,0xfc,0x8e,0xce,0xae,0xa0,0xf3,0x07,0xb8, + 0xeb,0x2c,0x04,0x1d,0x71,0x57,0xcc,0x16,0xc8,0x75,0x05,0x9d,0xe1,0xa0,0xe3,0xdc, + 0x42,0xd0,0xf9,0x13,0x9d,0xdd,0x41,0xe7,0x2f,0x70,0xd7,0x59,0x0c,0x3a,0xe2,0xae, + 0x9a,0x2d,0x92,0xeb,0x2a,0x3a,0x23,0x41,0xc7,0xb9,0xc5,0xa0,0x73,0x0d,0x9d,0x81, + 0xa0,0xb3,0x04,0xee,0x3a,0xcb,0x41,0x67,0x29,0xc7,0x52,0x8e,0x29,0xd7,0x75,0x74, + 0x46,0x83,0x8e,0x73,0xcb,0x41,0xe7,0x5f,0x74,0xf6,0x06,0x9d,0x1b,0xe0,0xae,0xe3, + 0x17,0x54,0x3a,0xe2,0x6e,0xf2,0xe1,0x57,0xae,0x9b,0xe8,0x8c,0x05,0x1d,0xe7,0xf4, + 0x74,0x9d,0x72,0x56,0xe8,0xec,0x0b,0x3a,0x95,0xac,0xc0,0x5d,0xa7,0x1e,0x74,0xc4, + 0x55,0xcd,0xea,0xe4,0xd2,0xbb,0x74,0xc6,0x83,0x8e,0x73,0xf5,0xa0,0xd3,0x8c,0xce, + 0x81,0xa0,0xd3,0x92,0x15,0xb8,0xeb,0xb4,0x05,0x1d,0x71,0xad,0x66,0x6d,0xe4,0x6a, + 0x45,0x67,0x22,0xe8,0x38,0xd7,0x16,0x74,0x56,0xa3,0x73,0x30,0xe8,0xdc,0x9e,0x15, + 0xb8,0xeb,0x74,0x04,0x1d,0x71,0xed,0x66,0x1d,0xe4,0x6a,0x47,0x67,0x32,0xe8,0x38, + 0xa7,0xe7,0x0d,0xdb,0xbc,0x87,0xcd,0xfe,0x03,0xd4,0xba,0x0e,0x01,0xdc,0x0c,0x00, + 0x00 }; // Generated from: @@ -109,6 +110,7 @@ constexpr uint8_t kBlitResolve_frag_00000006[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000007.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000007.inc index ab5bff5420a..c6b8ff52fd6 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000007.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000007.inc @@ -10,80 +10,80 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000007[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4b,0x6c,0x55,0x55, - 0x14,0x86,0xf7,0xb9,0xb7,0xbd,0x2d,0x5c,0xaa,0x05,0x4a,0x4b,0xd3,0x42,0x0b,0x05, - 0x7c,0x11,0x42,0x52,0x35,0x26,0x46,0xa2,0x23,0xc5,0xd0,0xa8,0x65,0xc0,0xa4,0x89, - 0x35,0xb1,0x03,0x07,0xc5,0x10,0x4d,0x07,0x0c,0x2c,0x91,0x49,0x07,0xc4,0xa4,0x13, - 0x03,0x0c,0x14,0xc4,0xe0,0xa3,0x84,0xa8,0x11,0x15,0x99,0xa1,0xe2,0x8b,0x68,0xaa, - 0x12,0x4d,0xd5,0xc6,0x26,0x3e,0x48,0x13,0x25,0x4d,0x2c,0xd6,0x47,0x53,0xd7,0x7f, - 0xce,0xb7,0x60,0xe5,0xde,0x64,0xf5,0x9c,0xf5,0xff,0x6b,0xaf,0x7f,0xaf,0xb5,0xd7, - 0x3e,0x2d,0x97,0x7a,0x1a,0x52,0xca,0xd2,0xf2,0xd4,0x98,0x6e,0xca,0x52,0xfe,0x5b, - 0x99,0x4a,0x49,0xaf,0xd5,0x54,0xc9,0x9f,0xf7,0xef,0xda,0xbd,0x6b,0xdb,0x53,0x4f, - 0x3f,0xbe,0xed,0xf6,0x3b,0xb6,0x8b,0xbf,0x21,0x95,0xf3,0x38,0x71,0x37,0x9a,0x57, - 0x67,0x4f,0xd9,0xf0,0x63,0x4f,0xec,0x15,0xde,0x6a,0xb6,0xdb,0x6c,0xc0,0x6c,0x48, - 0xb8,0xd9,0x88,0xd9,0xa8,0xd9,0x98,0xd9,0xb8,0x59,0xb3,0xe5,0xd0,0x9a,0x06,0xe5, - 0xb7,0xb7,0xd6,0x5c,0x4f,0xf9,0x52,0x7a,0x20,0xd5,0xa7,0xce,0x62,0x2b,0xa9,0x87, - 0xa7,0x63,0x19,0x58,0x63,0xc0,0x4a,0x60,0xcd,0x01,0x2b,0x83,0xad,0x0d,0x58,0x1d, - 0x58,0x67,0xc0,0xea,0xc1,0xba,0x03,0x56,0x01,0xdb,0x14,0xb0,0x06,0xb0,0x9b,0x03, - 0xd6,0x08,0xb6,0x35,0x60,0xcb,0xc0,0xb6,0xe7,0x75,0x95,0xaf,0xed,0x4f,0x35,0xaa, - 0x27,0xeb,0xa9,0x47,0xfe,0x00,0x7e,0x86,0x3f,0x84,0xef,0xf1,0xc3,0xf8,0x65,0xfc, - 0x11,0xfc,0x3a,0xfc,0x51,0xfc,0x7a,0xfc,0x31,0xfc,0x0a,0xfe,0x38,0xbe,0xf7,0xf8, - 0x84,0x3d,0x37,0x06,0x7d,0xf9,0x1b,0xf0,0x57,0x9b,0x6a,0x29,0xf7,0xcb,0xb9,0x9e, - 0xde,0xd7,0x58,0x4c,0x85,0xde,0x68,0x8f,0x6d,0xe6,0x37,0x90,0xbf,0x84,0x5f,0xc5, - 0xaf,0xcb,0xcf,0xbd,0x6c,0x79,0x8a,0x78,0x71,0x2d,0x79,0xde,0x82,0xeb,0xb6,0xbf, - 0x6b,0xc8,0x23,0xfc,0x6e,0xfc,0xd6,0x90,0xbb,0x8d,0x78,0xd7,0xee,0x20,0x57,0xca, - 0xeb,0x58,0x71,0xed,0x1c,0xda,0xb0,0x0a,0xb6,0x9a,0x67,0x47,0x30,0xe9,0xad,0xe3, - 0x3c,0x3a,0xd1,0x5b,0x47,0x3f,0x84,0xdd,0x46,0x6d,0x5d,0xe4,0x57,0x7c,0x37,0x5c, - 0x43,0xe0,0x37,0xe3,0x8b,0xdf,0x02,0xdf,0x91,0xd7,0x50,0x4a,0xb7,0x10,0x27,0xff, - 0x56,0xf2,0xf8,0xba,0x5e,0xe6,0xc3,0xfd,0x1d,0x35,0xba,0x3b,0xd9,0xb3,0xf2,0x3e, - 0x08,0x57,0x09,0x7c,0x1f,0x7d,0x11,0xdf,0xcf,0x0c,0x54,0xa9,0xa3,0x9f,0xfb,0x55, - 0x0e,0xf1,0x7b,0xe8,0x9b,0xf3,0x03,0x35,0xfc,0x20,0xe7,0xe0,0xfc,0x10,0xbc,0xfb, - 0xc3,0x35,0xf1,0xfb,0xb8,0x4f,0xce,0x8f,0xd4,0xf0,0xfb,0x39,0x1b,0xe7,0x47,0x6b, - 0xf8,0x83,0x66,0xf7,0x06,0x7e,0xac,0x86,0x3f,0x64,0x76,0x20,0xf0,0xe3,0xf0,0x5b, - 0xad,0xdb,0xaa,0xf3,0x79,0xce,0x26,0x5a,0xbb,0x75,0xe9,0x38,0x7d,0xe2,0x53,0x95, - 0x3f,0xb3,0xe0,0xab,0x5f,0x2f,0xf1,0x7e,0x9c,0xfc,0xf2,0x4f,0xd4,0x9c,0xcf,0x49, - 0xf4,0x34,0x77,0xaf,0x91,0x33,0xee,0xef,0x0c,0xf7,0x4a,0xf9,0xde,0xe1,0x7c,0x34, - 0x67,0x77,0x1a,0x5a,0xa2,0x97,0x89,0x35,0x0b,0x86,0x28,0xf6,0x1e,0x66,0xfe,0x3c, - 0x73,0xfd,0x90,0xd5,0xa2,0x39,0xfd,0x00,0xec,0x7c,0xd8,0xf3,0x5e,0xee,0xd2,0x87, - 0xf0,0xf7,0x59,0x06,0xf5,0xf3,0x23,0x66,0xb4,0x8b,0x7c,0x8a,0xb9,0x00,0xfe,0xac, - 0xc5,0xc8,0xff,0x84,0x75,0x17,0x58,0xa7,0xb9,0xfc,0x94,0x75,0x9b,0x59,0xa7,0x99, - 0xfc,0x0c,0x7c,0xc2,0x62,0x34,0xab,0x9f,0x83,0x69,0x56,0xff,0xb2,0x9d,0x4f,0xb2, - 0x9f,0x7f,0x2c,0x5e,0xdc,0x45,0xb3,0x49,0xea,0xd1,0xfb,0x23,0xb6,0x4e,0xbd,0xf8, - 0x02,0x4d,0xfd,0x9e,0xa1,0x3f,0x5f,0x82,0xf7,0x9b,0xa7,0x3d,0xad,0xcf,0x0a,0xcc, - 0xe3,0xfe,0xb6,0x1c,0x9e,0x4b,0xcf,0x79,0x8b,0x52,0xdc,0xc6,0xac,0x88,0xa9,0x67, - 0xcd,0xc5,0x50,0xc3,0x57,0xd4,0xd0,0x1b,0x6a,0xf8,0x1a,0xdc,0x6b,0xf8,0x06,0xcc, - 0x6b,0x98,0x0a,0x35,0x88,0xbb,0x64,0x36,0x85,0xee,0xa5,0x50,0xc3,0xb7,0x68,0x67, - 0xa1,0x86,0xef,0xc0,0xbd,0x86,0x0d,0x59,0x81,0x79,0x9c,0x6a,0xf0,0x5c,0x53,0xa1, - 0x86,0x9e,0xac,0x88,0x99,0x64,0xcd,0xa5,0x50,0xc3,0xf7,0xd4,0xb0,0x23,0xd4,0xf0, - 0x03,0xb8,0xd7,0xf0,0x23,0x98,0xd7,0x30,0x13,0x6a,0x10,0x37,0x6d,0x36,0x83,0xee, - 0x34,0x73,0x24,0xdd,0x9f,0xd0,0xee,0xc9,0xae,0xcf,0xbb,0xf6,0xe8,0xb1,0x33,0x61, - 0x8f,0x9b,0x88,0x9b,0x62,0xdd,0x34,0xb1,0x87,0x89,0x3d,0x4c,0xac,0xee,0xda,0x96, - 0xac,0xb8,0x6f,0x5a,0xff,0x86,0xd9,0x11,0xb8,0xfc,0xfb,0x97,0x15,0xb3,0x28,0xee, - 0x2d,0x38,0xd5,0xaa,0x6f,0xd6,0x0b,0xd4,0x3a,0x48,0xad,0x8a,0x7f,0x11,0xfc,0x4d, - 0x6a,0x3d,0x46,0x0e,0xe1,0x57,0x2d,0xe6,0x28,0x39,0xbc,0xde,0x63,0xf8,0x47,0xd9, - 0xd7,0x11,0x72,0xe9,0xee,0xbe,0xcc,0xbd,0x75,0xbd,0x57,0xd0,0x3b,0x19,0xf4,0x5e, - 0x05,0xf7,0x73,0x7e,0x9d,0xda,0x53,0xc0,0x26,0xc0,0x04,0x3f,0x6c,0x88,0xee,0xfb, - 0x29,0x62,0x27,0xc8,0xf1,0x28,0xbd,0x38,0x8d,0xee,0x29,0xbe,0x5f,0xda,0xfb,0x01, - 0xcb,0x53,0xa5,0x37,0xea,0xd5,0xe9,0x54,0x60,0x15,0x7a,0xa2,0x98,0xbe,0x9a,0xfe, - 0xaa,0x9e,0x27,0xf9,0x1e,0xbc,0xcd,0x3a,0xd5,0xa1,0x6f,0xc9,0xbb,0xd4,0x71,0x86, - 0x3a,0xf4,0x5d,0x79,0x0f,0xfc,0x39,0x8b,0xd1,0x9a,0xb3,0xac,0x13,0xbe,0xc2,0x94, - 0x84,0xbd,0x1f,0xbe,0x75,0x67,0xf9,0x86,0x68,0x5f,0xe7,0xe0,0xbc,0x4f,0x3f,0x93, - 0x7f,0x67,0xe8,0xd3,0x2f,0xe0,0x1f,0xb3,0xef,0x5f,0xc1,0xfa,0xc2,0x5c,0xfe,0x06, - 0xde,0xc5,0x5c,0xce,0x86,0x73,0x12,0x77,0xd9,0x6c,0x96,0xfa,0x2e,0xe7,0x33,0x5e, - 0xce,0xff,0x0f,0x9d,0xa3,0x76,0xe7,0x66,0x83,0xce,0xef,0xe8,0xec,0x09,0x3a,0x7f, - 0x80,0xbb,0xce,0x5c,0xd0,0x11,0x77,0xc5,0x6c,0x8e,0x5c,0x57,0xd0,0x19,0x08,0x3a, - 0xce,0xcd,0x05,0x9d,0x3f,0xd1,0x19,0x0c,0x3a,0xf3,0xe0,0xae,0xb3,0x10,0x74,0xe6, - 0xf3,0x79,0x4c,0x39,0xa6,0x5c,0x57,0xd1,0x19,0x0a,0x3a,0xce,0x2d,0x04,0x9d,0x7f, - 0xd1,0xe9,0x0d,0x3a,0xff,0x81,0xbb,0xce,0x52,0xd0,0x11,0xb7,0x68,0xb6,0x44,0xae, - 0x45,0x74,0x86,0x83,0x8e,0x73,0x4b,0x41,0xa7,0x94,0x15,0x3a,0xfb,0x82,0x4e,0x39, - 0x2b,0x70,0xd7,0xa9,0x64,0xd7,0x75,0xc4,0xd5,0x99,0x09,0x53,0x2e,0xbd,0x4b,0x67, - 0x24,0xe8,0x38,0xa7,0xa7,0xeb,0x2c,0x43,0x67,0x7f,0xd0,0x59,0x9e,0x15,0xb8,0xeb, - 0x34,0x05,0x1d,0x71,0x55,0xb3,0x26,0x72,0x55,0xd1,0x19,0x0d,0x3a,0xce,0x35,0x05, - 0x9d,0x66,0x74,0x0e,0x06,0x9d,0x95,0x59,0x81,0xbb,0x4e,0x4b,0xd0,0x11,0xb7,0xca, - 0xac,0x85,0x5c,0xab,0xd0,0x19,0x0b,0x3a,0xce,0xb5,0x04,0x9d,0x36,0x74,0x0e,0x05, - 0x9d,0xb5,0x59,0x81,0xbb,0x4e,0x47,0xd0,0x11,0xd7,0x6e,0xd6,0x41,0xae,0x76,0x74, - 0xc6,0x83,0x8e,0x73,0x7a,0x2e,0xda,0xed,0xbb,0xcb,0xec,0x7f,0xc3,0x14,0x97,0x77, - 0x38,0x0d,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4d,0x6c,0x55,0x65, + 0x10,0x86,0xcf,0xb9,0xf7,0xf6,0xde,0xd2,0x6b,0xb5,0x40,0x69,0x69,0x6e,0xa1,0x85, + 0x52,0xfc,0x23,0x84,0x04,0x34,0x26,0x46,0xa2,0x2b,0xc5,0xd0,0xa8,0x65,0xc1,0xa6, + 0x89,0x35,0xb1,0x0b,0x17,0xc5,0x10,0x4d,0x17,0x2c,0x2c,0x91,0x4d,0x17,0xc4,0xa4, + 0x1b,0x03,0x2c,0x50,0x10,0xe3,0x4f,0x09,0x51,0x23,0x2a,0xb2,0x43,0xc5,0x3f,0xa2, + 0xa9,0xda,0x68,0xaa,0x36,0x36,0xf1,0x87,0x34,0x51,0xd2,0xc4,0x62,0xfd,0x69,0xea, + 0xbc,0xe7,0x3c,0x03,0x93,0x7b,0x93,0xe9,0x77,0xe6,0x7d,0xe7,0x9b,0xf7,0x9b,0x39, + 0xf3,0x9d,0x16,0x0b,0x3d,0x95,0x24,0x49,0x93,0xa6,0xa4,0x31,0xb9,0x39,0x4d,0xb2, + 0xdf,0xca,0xa4,0x90,0xe8,0xb1,0x9a,0x94,0xb3,0xf5,0xfe,0xdd,0x7b,0x76,0x6f,0x7d, + 0xea,0xe9,0xc7,0xb7,0xee,0xb8,0x63,0x9b,0xf8,0x1b,0x93,0x62,0x16,0x27,0xee,0x26, + 0xf3,0x4a,0xb6,0xca,0x86,0x1f,0x7b,0x62,0x9f,0xf0,0x36,0xb3,0x3d,0x66,0x03,0x66, + 0x43,0xc2,0xcd,0x46,0xcc,0x46,0xcd,0xc6,0xcc,0xc6,0xcd,0x5a,0x2c,0x87,0xf6,0x54, + 0x94,0xdf,0x9e,0xda,0x32,0x3d,0xe5,0x4b,0x92,0x07,0x92,0x86,0xa4,0x33,0x3f,0x4a, + 0xd2,0xc3,0xea,0x58,0x0a,0xd6,0x18,0xb0,0x02,0x58,0x4b,0xc0,0x8a,0x60,0x6b,0x03, + 0x56,0x02,0xeb,0x0c,0x58,0x03,0x58,0x77,0xc0,0xca,0x60,0x9b,0x02,0x56,0x01,0xbb, + 0x25,0x60,0x8d,0x60,0x5b,0x02,0xb6,0x02,0x6c,0x5b,0xc0,0x9a,0xc0,0x76,0x64,0xb5, + 0x16,0xaf,0x9d,0x59,0x75,0xab,0x4f,0xeb,0xa9,0x51,0xfe,0x00,0x7e,0x8a,0x3f,0x84, + 0xef,0xf1,0xc3,0xf8,0x45,0xfc,0x11,0xfc,0x12,0xfe,0x28,0x7e,0x03,0xfe,0x18,0x7e, + 0x19,0x7f,0x1c,0xdf,0xfb,0x7e,0xca,0xd6,0x8d,0x41,0x5f,0xfe,0x06,0xfc,0xd5,0xa6, + 0x5a,0xc8,0xfc,0x62,0xa6,0xa7,0xe7,0x35,0x16,0x53,0xa6,0x5f,0x3a,0x63,0xbb,0xf9, + 0x15,0xf2,0x17,0xf0,0xab,0xf8,0xa5,0x6c,0x16,0x8a,0x96,0x27,0x8f,0x17,0xd7,0x9a, + 0xe5,0xcd,0xb9,0x6e,0xfb,0xbb,0x86,0x3c,0xc2,0xef,0xc6,0x6f,0x0b,0xb9,0xdb,0x89, + 0x77,0xed,0x1a,0xb9,0x92,0xac,0x8e,0xe6,0x6b,0xef,0xa6,0x1d,0x2b,0x07,0x5b,0xcd, + 0x5a,0x0b,0x26,0xcd,0x75,0xbc,0xa7,0x4e,0x34,0xd7,0xd1,0x13,0x61,0xb7,0x53,0x5f, + 0x17,0x1a,0x8a,0xef,0x86,0xab,0x04,0xbe,0x97,0xf7,0x2f,0x7e,0x33,0x7c,0x2d,0xab, + 0xa3,0x90,0xdc,0x4a,0x9c,0xfc,0xdb,0xc8,0xe3,0xfb,0xb6,0xd7,0xe9,0xec,0x64,0x3e, + 0xdc,0xdf,0x85,0x8e,0xf2,0x3e,0x48,0x6c,0x39,0xf0,0x7d,0xf4,0x46,0x7c,0x3f,0x73, + 0x50,0xa5,0x8e,0x7e,0xee,0x5d,0x31,0xc4,0xef,0xa5,0x77,0xce,0x0f,0xd4,0xf1,0x83, + 0xbc,0x0b,0xe7,0x87,0xe0,0xdd,0x1f,0xae,0x8b,0xdf,0xcf,0x3d,0x73,0x7e,0xa4,0x8e, + 0x3f,0xc0,0xfb,0x71,0x7e,0xb4,0x8e,0x3f,0x64,0x76,0x6f,0xe0,0xc7,0xea,0xf8,0xc3, + 0x66,0x07,0x03,0x3f,0x0e,0xbf,0xc5,0xba,0xa2,0x3a,0x9f,0xe7,0xdd,0x44,0xf3,0xbd, + 0xc7,0x99,0xfb,0x0e,0xeb,0xda,0x49,0xfa,0xc6,0x27,0x2d,0x5b,0xd3,0xe0,0xab,0x7f, + 0x2f,0xf1,0x7c,0x12,0x3d,0xf9,0xa7,0xc0,0x34,0x7b,0xaf,0x91,0x23,0x9e,0xef,0x2c, + 0x98,0xf6,0xbf,0xc3,0xfb,0xd1,0x9c,0xdd,0x69,0xca,0x05,0x7a,0x99,0xb0,0x67,0xd1, + 0x10,0x9d,0xe7,0x1e,0xe6,0xfe,0x02,0xb3,0xfd,0x90,0xd5,0xa2,0x59,0xfd,0x00,0xec, + 0x42,0x38,0xe3,0x3e,0xee,0xd3,0x87,0xf0,0xf7,0x59,0x06,0xf5,0xf3,0x23,0x66,0xb4, + 0x8b,0x7c,0x8a,0xb9,0x08,0xfe,0xac,0xc5,0xc8,0xff,0x84,0x7d,0x17,0xd9,0xa7,0xb9, + 0xfc,0x94,0x7d,0xbd,0xec,0xd3,0x4c,0x7e,0x06,0x3e,0x61,0x31,0x9a,0xd5,0xcf,0xc1, + 0x34,0xab,0x7f,0xd9,0xc9,0x27,0x39,0xcf,0x3f,0x16,0x2f,0xee,0x92,0xd9,0x24,0xf5, + 0xe8,0xf9,0x11,0xdb,0xa7,0x1e,0x7c,0x81,0xa6,0x7e,0xcf,0xd0,0x9f,0x2f,0xc1,0xfb, + 0xcd,0xd3,0x99,0xd6,0xa7,0x39,0xe6,0x71,0x7f,0x5b,0x0e,0xcf,0xa5,0x75,0xc1,0xa2, + 0x14,0xb7,0x31,0xcd,0x63,0x1a,0xd8,0x73,0x29,0xd4,0xf0,0x15,0x35,0x6c,0x0f,0x35, + 0x7c,0x0d,0xee,0x35,0x7c,0x03,0xe6,0x35,0x4c,0x87,0x1a,0xc4,0x4d,0x99,0x4d,0xa3, + 0x3b,0x15,0x6a,0xf8,0x16,0xed,0x34,0xd4,0xf0,0x1d,0xb8,0xd7,0xb0,0x21,0xcd,0x31, + 0x8f,0x53,0x0d,0x9e,0x6b,0x3a,0xd4,0xd0,0x93,0xe6,0x31,0x93,0xec,0x99,0x0a,0x35, + 0x7c,0x4f,0x0d,0x3b,0x43,0x0d,0x3f,0x80,0x7b,0x0d,0x3f,0x82,0x79,0x0d,0xb3,0xa1, + 0x06,0x71,0x33,0x66,0xb3,0xe8,0xce,0x30,0x47,0xd2,0xfd,0x09,0xed,0x9e,0xf4,0xfa, + 0x7c,0xeb,0x8c,0x1e,0x3b,0x1b,0xce,0xb8,0x89,0xb8,0x69,0xf6,0xcd,0x10,0x7b,0x84, + 0xd8,0x23,0xc4,0xea,0xae,0x6d,0x4e,0xf3,0xfb,0xa6,0xfd,0x6f,0x98,0x1d,0x85,0xcb, + 0xbe,0x7f,0x69,0x3e,0x8b,0xe2,0xde,0x82,0x53,0xad,0xfa,0x66,0xbd,0x40,0xad,0xc7, + 0xa9,0x55,0xf1,0x2f,0x82,0xbf,0x49,0xad,0x27,0xc8,0x21,0xfc,0xaa,0xc5,0x1c,0x23, + 0x87,0xd7,0x7b,0x02,0xff,0x18,0xe7,0x3a,0x4a,0x2e,0xdd,0xd5,0x97,0xb9,0xa7,0xae, + 0xf7,0x0a,0x7a,0x83,0x41,0xef,0x55,0x70,0x7f,0xcf,0xaf,0x53,0x7b,0x12,0xb0,0x09, + 0x30,0xc1,0x0f,0x1b,0xa2,0xfb,0x7e,0x9a,0xd8,0x09,0x72,0x3c,0x4a,0x2f,0xce,0xa0, + 0x7b,0x9a,0xef,0x97,0xce,0x7e,0xd0,0xf2,0x54,0xe9,0x8d,0x7a,0x75,0x26,0xc9,0xb1, + 0x32,0x3d,0x51,0x4c,0x5f,0x5d,0x7f,0x55,0xcf,0x93,0x7c,0x0f,0xde,0x66,0x9f,0xea, + 0xd0,0xb7,0xe4,0x5d,0xea,0x38,0x4b,0x1d,0xfa,0xae,0xbc,0x07,0xfe,0x9c,0xc5,0x68, + 0xcf,0x39,0xf6,0x09,0xbf,0xc1,0x94,0x84,0xbd,0x1f,0xbe,0x6d,0xe7,0xf8,0x86,0xe8, + 0x5c,0xe7,0xe1,0xbc,0x4f,0x3f,0x93,0x7f,0x57,0xe8,0xd3,0x2f,0xe0,0x1f,0x73,0xee, + 0x5f,0xc1,0xfa,0xc2,0x5c,0xfe,0x06,0xde,0xc5,0x5c,0xce,0x85,0xf7,0x24,0xee,0xb2, + 0xd9,0x1c,0xf5,0x5d,0xce,0x66,0xbc,0x98,0xfd,0x1f,0x3a,0x4f,0xed,0xce,0xcd,0x05, + 0x9d,0xdf,0xd1,0xd9,0x1b,0x74,0xfe,0x00,0x77,0x9d,0xf9,0xa0,0x23,0xee,0x8a,0xd9, + 0x3c,0xb9,0xae,0xa0,0x33,0x10,0x74,0x9c,0x9b,0x0f,0x3a,0x7f,0xa2,0x33,0x18,0x74, + 0x16,0xc0,0x5d,0x67,0x31,0xe8,0x2c,0x64,0xf3,0x98,0x64,0x98,0x72,0x5d,0x45,0x67, + 0x28,0xe8,0x38,0xb7,0x18,0x74,0xfe,0x45,0xa7,0x37,0xe8,0xfc,0x07,0xee,0x3a,0xcb, + 0x41,0x47,0xdc,0x92,0xd9,0x32,0xb9,0x96,0xd0,0x19,0x0e,0x3a,0xce,0x2d,0x07,0x9d, + 0x42,0x9a,0xeb,0xec,0x0f,0x3a,0xc5,0x34,0xc7,0x5d,0xa7,0x9c,0x5e,0xd7,0x11,0x57, + 0x32,0x13,0xa6,0x5c,0x7a,0x96,0xce,0x48,0xd0,0x71,0x4e,0xab,0xeb,0xac,0x40,0xe7, + 0x40,0xd0,0x69,0x4a,0x73,0xdc,0x75,0x9a,0x83,0x8e,0xb8,0xaa,0x59,0x33,0xb9,0xaa, + 0xe8,0x8c,0x06,0x1d,0xe7,0x9a,0x83,0x4e,0x0b,0x3a,0x87,0x82,0xce,0xca,0x34,0xc7, + 0x5d,0xa7,0x35,0xe8,0x88,0x5b,0x65,0xd6,0x4a,0xae,0x55,0xe8,0x8c,0x05,0x1d,0xe7, + 0x5a,0x83,0x4e,0x3b,0x3a,0x87,0x83,0xce,0xda,0x34,0xc7,0x5d,0xa7,0x16,0x74,0xc4, + 0x75,0x98,0xd5,0xc8,0xd5,0x81,0xce,0x78,0xd0,0x71,0x4e,0xeb,0x92,0xdd,0xbe,0xbb, + 0xcc,0xfe,0x07,0x45,0x1b,0x13,0x71,0x50,0x0d,0x00,0x00 }; // Generated from: @@ -112,6 +112,7 @@ constexpr uint8_t kBlitResolve_frag_00000007[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000008.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000008.inc index 1e245254116..c3bb3af79c6 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000008.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000008.inc @@ -10,73 +10,75 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000008[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x4d,0x68,0x5d,0x65, - 0x10,0x86,0xbf,0x73,0xff,0xf5,0xa6,0xa6,0xfe,0x34,0x69,0x35,0xad,0xa9,0x2d,0x41, - 0x48,0xa9,0x5d,0xa8,0x18,0x44,0x51,0x28,0xe8,0xa2,0xd0,0xaa,0x60,0xba,0xc8,0xe6, - 0x82,0x5d,0x18,0x68,0x17,0x51,0xba,0xc9,0xa2,0x82,0x11,0xba,0xc9,0xa2,0x9b,0x6c, - 0x6a,0xad,0xa9,0xa2,0x15,0x37,0xe2,0x4f,0xd1,0xe2,0x4f,0x50,0x62,0x0d,0x4a,0xd4, - 0x60,0x40,0x5b,0x09,0x68,0x09,0xd8,0x12,0xd0,0x12,0x34,0x35,0x50,0xeb,0xbc,0xe7, - 0x3c,0x93,0x0e,0xf7,0xc2,0xdc,0xef,0xcc,0xfb,0xce,0xcc,0xfb,0xcd,0x9c,0xef,0x3b, - 0xe5,0xd2,0xb6,0x7a,0x4a,0x59,0xba,0x39,0x35,0xd2,0xa6,0x2c,0xe5,0xbf,0x5b,0x53, - 0x29,0xe9,0xb1,0x99,0x6a,0xf9,0xfa,0xc4,0x9e,0x67,0xf6,0xec,0x7c,0xe1,0xc5,0xe7, - 0x76,0xde,0xff,0xc0,0x2e,0xf1,0xb7,0xa4,0x72,0x1e,0x27,0xae,0xd3,0xbc,0x8a,0xad, - 0xb2,0x83,0xad,0xe7,0x0f,0x09,0xef,0x32,0xdb,0x6f,0xd6,0x32,0x1b,0x36,0x1b,0x31, - 0x1b,0x35,0x1b,0x33,0x1b,0x37,0x9b,0x30,0x5b,0x6f,0x35,0x94,0x53,0x57,0x7d,0x7b, - 0xea,0xca,0xf5,0x54,0x2f,0xa5,0x27,0x53,0x35,0x6d,0x2e,0xb6,0x92,0xb6,0xb1,0x3a, - 0x96,0x81,0x35,0x02,0x56,0x02,0x5b,0x1f,0xb0,0x32,0xd8,0xc6,0x80,0x55,0xc0,0x7a, - 0x02,0x56,0x05,0xeb,0x0d,0x58,0x0d,0x6c,0x7b,0xc0,0xea,0x60,0xf7,0x06,0xac,0x01, - 0xb6,0x23,0x60,0x37,0x81,0xed,0xca,0xfb,0x2a,0xaf,0xed,0x4f,0x3d,0x6a,0x26,0x5b, - 0xe8,0x47,0x7e,0x0b,0x3f,0xc3,0x1f,0xc6,0xf7,0xf8,0x11,0xfc,0x32,0xfe,0x28,0x7e, - 0x05,0x7f,0x0c,0xbf,0x8a,0x3f,0x8e,0x5f,0xc3,0x9f,0xc0,0xf7,0x19,0x9f,0xb0,0xf5, - 0x9e,0xa0,0x2f,0x7f,0x6b,0xf0,0x27,0xdb,0xf8,0x49,0x78,0xed,0xe7,0x76,0xfb,0x2f, - 0xe5,0x7e,0x39,0xdf,0x4f,0x29,0x7f,0xcf,0xe5,0x5c,0x4b,0xb3,0xeb,0xb6,0xf8,0x3a, - 0xda,0xe2,0x36,0x98,0xdf,0x84,0x4b,0xf0,0x1d,0xbc,0xe3,0x0a,0xfe,0x1d,0xc4,0x57, - 0xf2,0xb8,0x8a,0xe5,0x14,0xb3,0x10,0xfe,0x30,0x7e,0x17,0x98,0xea,0xf5,0x50,0x2f, - 0xcb,0xfb,0xea,0x58,0x7b,0x2f,0x6e,0x3d,0x58,0x8d,0xb5,0x19,0x4c,0xf5,0xb7,0xf0, - 0x7e,0x36,0x53,0x5f,0xfe,0xdd,0x60,0xfd,0x6d,0xf5,0x15,0xbf,0x15,0xae,0x1e,0xf8, - 0x3e,0xfa,0x71,0xbf,0x1f,0x5e,0xf1,0x3b,0x88,0x6f,0xe6,0x3d,0x94,0xd2,0x7d,0xc4, - 0x35,0x39,0x0f,0x31,0x6f,0x80,0xf3,0xe3,0xfe,0xee,0xb6,0x7d,0xec,0xa5,0x0f,0xd5, - 0xdd,0x07,0xd7,0x83,0x3f,0xc8,0x99,0xe8,0xa0,0x8f,0x41,0xee,0x5b,0x39,0xe4,0x0f, - 0xf1,0x1e,0x9c,0x6f,0xb5,0xf1,0x07,0x98,0xbb,0xf3,0xc3,0xf0,0xee,0x8f,0xb4,0xc5, - 0x1f,0xe6,0x7e,0x39,0x3f,0xda,0xc6,0x1f,0x61,0x76,0xce,0x8f,0xb5,0xf1,0x47,0xcd, - 0x1e,0x0b,0xfc,0x78,0x1b,0x7f,0xcc,0xec,0xa5,0xc0,0x4f,0xc0,0x6f,0xb2,0xce,0x8f, - 0x33,0x53,0x3e,0x4f,0x6b,0x3f,0xf7,0x35,0x93,0x57,0x79,0x3e,0x4e,0x0d,0xf9,0x27, - 0xc0,0xee,0xb4,0x49,0x9c,0x24,0xee,0x75,0xb0,0x93,0xc4,0xc9,0x9f,0x04,0xbb,0xcb, - 0x14,0xdf,0xa0,0xc6,0x83,0x76,0xab,0x4a,0xcc,0x28,0xb1,0x97,0xab,0x86,0xe8,0xae, - 0x3d,0xc2,0xd9,0x7d,0x8f,0xf3,0xf9,0x94,0xa1,0x7a,0x57,0xef,0x83,0xa5,0x80,0x7d, - 0x00,0xa6,0xbd,0xee,0x33,0x4c,0x67,0xe5,0x43,0x62,0xc5,0x3d,0x6e,0x98,0xce,0xd9, - 0x47,0x9c,0xc5,0x5e,0xea,0x2b,0xee,0x0c,0xf8,0x2b,0xe4,0x7d,0x4c,0xee,0x99,0x90, - 0xf7,0x09,0x79,0x7d,0x21,0xef,0x2c,0xf8,0xcb,0xe4,0x7d,0x4a,0xee,0x59,0xf2,0x74, - 0x4e,0x3f,0x23,0xaf,0x9f,0x3c,0xcd,0xf7,0x73,0xf0,0x77,0x2d,0x46,0x67,0xf7,0x0b, - 0x30,0x9d,0xdd,0x15,0x9b,0xc0,0x34,0xbd,0xad,0x5a,0xbc,0xb8,0x29,0xb3,0x69,0xe6, - 0x32,0x15,0x7a,0xfe,0x12,0xcd,0x94,0x9f,0x8b,0x4a,0x8e,0x7d,0x05,0xfe,0xb4,0x79, - 0xda,0xd3,0x6d,0x59,0x81,0x79,0xdc,0xbf,0x56,0xc3,0x6b,0x69,0xfd,0xdb,0xa2,0x14, - 0xd7,0x95,0x15,0x31,0x55,0x72,0xa6,0x42,0x0f,0x5f,0xd3,0xc3,0x40,0xe8,0xe1,0x1c, - 0xb8,0xf7,0xf0,0x0d,0x98,0xf7,0x30,0x1b,0x7a,0x10,0x37,0x63,0x36,0x8b,0xee,0x4c, - 0xe8,0xe1,0x5b,0xb4,0xb3,0xd0,0xc3,0x77,0xe0,0xde,0xc3,0x86,0xac,0xc0,0x3c,0x4e, - 0x3d,0x78,0xad,0xd9,0xd0,0x43,0x77,0x56,0xc4,0x4c,0x93,0x33,0x13,0x7a,0xf8,0x9e, - 0x1e,0x76,0x87,0x1e,0x7e,0x00,0xf7,0x1e,0x7e,0x04,0xf3,0x1e,0xe6,0x43,0x0f,0xe2, - 0xe6,0xcc,0xe6,0xd1,0x9d,0xcb,0xbf,0x1d,0x85,0xee,0x4f,0x68,0x77,0x67,0x37,0xee, - 0x8a,0xf6,0xe8,0xb1,0xf3,0x61,0x8f,0x1b,0x89,0x9b,0x25,0x6f,0x8e,0xfd,0xe8,0x2e, - 0xbc,0xc6,0x5d,0x92,0xaf,0x7b,0x73,0x8a,0x3b,0xf3,0xac,0xed,0x4f,0xf7,0xe5,0x4d, - 0x62,0x4e,0x85,0x73,0xf9,0x16,0x7d,0x0d,0x85,0x73,0xf9,0x36,0xb8,0x9f,0xe7,0xd3, - 0xe8,0x0a,0x1f,0x34,0x4c,0xdf,0xb3,0x77,0xa8,0x77,0x9a,0x5a,0xfa,0xf6,0xfd,0x4c, - 0xad,0xbd,0xd4,0xd2,0xf7,0xe2,0x17,0xf0,0x73,0x16,0x23,0xff,0x3c,0x58,0x6f,0x98, - 0xdb,0x05,0xf0,0x3e,0xe6,0xb6,0x10,0xe6,0x26,0xee,0x57,0xb3,0x05,0x66,0xa1,0xe7, - 0x47,0x2d,0x66,0x3f,0x7b,0xd0,0x9c,0x9c,0x5b,0x08,0x3a,0xbf,0xa1,0x33,0x14,0x74, - 0x7e,0x07,0x77,0x9d,0xc5,0xa0,0x23,0xee,0xa2,0xd9,0x22,0xb5,0x2e,0xa2,0xd3,0x0a, - 0x3a,0xce,0x2d,0x06,0x9d,0x3f,0xd0,0x39,0x10,0x74,0x2e,0x81,0xbb,0xce,0x52,0xd0, - 0x11,0x77,0xd9,0x6c,0x89,0x5a,0x97,0xd1,0x19,0x0e,0x3a,0xce,0x2d,0x05,0x9d,0x3f, - 0xd1,0x19,0x08,0x3a,0x7f,0x81,0xbb,0xce,0x72,0xd0,0x11,0x77,0xc5,0x6c,0x99,0x5a, - 0x57,0xd0,0x19,0x09,0x3a,0xce,0x2d,0x07,0x9d,0x7f,0xd0,0x39,0x1c,0x74,0x56,0xc0, - 0x5d,0x67,0x35,0xe8,0xac,0xe4,0x35,0x52,0x8e,0xa9,0xd6,0x55,0x74,0x46,0x83,0x8e, - 0x73,0xab,0x41,0xe7,0x1a,0x3a,0x47,0x82,0xce,0x7f,0xe0,0xae,0x93,0x65,0x37,0x74, - 0xc4,0x5d,0xd7,0xf7,0x39,0x2b,0x6a,0x5d,0x47,0x67,0x2c,0xe8,0x38,0xa7,0xd5,0x75, - 0x2a,0x59,0xa1,0x73,0x34,0xe8,0x54,0xb3,0x02,0x77,0x9d,0x46,0xd0,0x11,0x57,0x33, - 0x6b,0x50,0x4b,0xcf,0xd2,0x19,0x0f,0x3a,0xce,0x35,0x82,0x4e,0x13,0x9d,0x63,0x41, - 0xa7,0x23,0x2b,0x70,0xd7,0xe9,0x0c,0x3a,0xe2,0xd6,0x99,0x75,0x52,0x6b,0x1d,0x3a, - 0x13,0x41,0xc7,0x39,0xad,0xd7,0xec,0xcb,0xf0,0x90,0xd9,0xff,0x0b,0x92,0x24,0xe7, - 0x08,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x5f,0x68,0xd6,0x65, + 0x14,0xc7,0x9f,0xe7,0xfd,0xbd,0xef,0xde,0xb9,0xf7,0x2d,0x37,0xa6,0xf3,0xcf,0xde, + 0xd9,0xcc,0x18,0xc1,0xc4,0xbc,0xb0,0x50,0xc2,0x30,0x10,0xea,0x42,0xd0,0x0a,0x72, + 0x17,0xbb,0x79,0x41,0x2f,0x1a,0x54,0xb0,0xc2,0x9b,0x5d,0x28,0xb8,0xc0,0x9b,0x5d, + 0x78,0xb3,0x1b,0x35,0x9b,0x45,0x6a,0xda,0x5d,0xf4,0x47,0x4a,0xfa,0x33,0x92,0x55, + 0xa3,0x98,0x36,0x1a,0xd8,0x1f,0x06,0x25,0x03,0x93,0x41,0xca,0xca,0x74,0x78,0xce, + 0xf3,0xfb,0x9c,0xed,0xf0,0x0e,0xce,0x7e,0xef,0xf9,0x7e,0xcf,0x39,0xdf,0xe7,0x9c, + 0xdf,0x79,0x7e,0x59,0x61,0x53,0x39,0x84,0x18,0x5a,0x42,0x73,0xe8,0x8a,0x21,0xfd, + 0xb5,0x85,0x42,0xd0,0x9f,0x95,0xd0,0x94,0x9e,0xcf,0xed,0x79,0x69,0xcf,0x96,0x37, + 0xde,0x3c,0xb0,0x65,0xdb,0x93,0x5b,0x95,0x7f,0x38,0x64,0x29,0x4e,0xb9,0x95,0xe2, + 0x15,0xe5,0xa9,0xf6,0x6a,0xfd,0x95,0xd7,0x14,0xef,0x10,0xeb,0x13,0xab,0x8b,0x0d, + 0x88,0x0d,0x8a,0x0d,0x89,0x0d,0x8b,0x8d,0x88,0x8d,0x8a,0xb5,0x4a,0x0d,0xcd,0x29, + 0x6b,0x7d,0xf9,0xd5,0x91,0xf4,0xb4,0x5e,0x08,0xcf,0x87,0x52,0xe8,0xca,0x8f,0x12, + 0x36,0xf1,0x34,0x2c,0x82,0x35,0x3b,0xac,0x00,0xd6,0xea,0xb0,0x0c,0x6c,0xad,0xc3, + 0x8a,0x60,0x35,0x87,0x95,0xc0,0xba,0x1d,0xd6,0x04,0xf6,0x98,0xc3,0xca,0x60,0x8f, + 0x3b,0xac,0x19,0x6c,0xb3,0xc3,0x56,0x80,0x6d,0x75,0x58,0x0b,0xd8,0xb6,0xd4,0x6b, + 0xb6,0x74,0x66,0xed,0x5b,0xe7,0xb4,0x81,0x1e,0xd5,0xaf,0xe3,0x47,0xfc,0x01,0x7c, + 0x8b,0x1f,0xc4,0xcf,0xf0,0x87,0xf0,0x8b,0xf8,0xc3,0xf8,0x25,0xfc,0x11,0xfc,0x26, + 0xfc,0x51,0x7c,0x9b,0xfb,0x29,0x79,0x3e,0xea,0xf4,0xd5,0xdf,0xe8,0xfc,0xb1,0x06, + 0x7e,0x0c,0x5e,0xcf,0xd3,0x2e,0xff,0x0b,0xc9,0xcf,0xd2,0x79,0x0a,0xe9,0xdd,0x67, + 0x49,0x4b,0xe7,0xb9,0x46,0xe2,0xcb,0x68,0x2b,0xb7,0x5a,0xfc,0x0a,0x5c,0x80,0xaf, + 0xf2,0xde,0x8b,0xf8,0xab,0x88,0x2f,0xa6,0xb8,0xa2,0xe4,0xe4,0xb3,0x50,0xfc,0x69, + 0xfc,0x0e,0x30,0xad,0x57,0xa3,0x5e,0x4c,0x7d,0x3d,0xb4,0xf4,0xae,0xcc,0x6a,0xce, + 0x9a,0x78,0x56,0x9c,0xa9,0xc6,0x06,0xde,0x5b,0x17,0x1a,0xea,0x3f,0x02,0xd6,0xdb, + 0xa0,0xa1,0xf1,0x1b,0xe1,0xca,0x8e,0xef,0xa1,0x27,0xf3,0x7b,0xd9,0x0f,0x8d,0xdf, + 0x4c,0x7c,0x25,0xf5,0x51,0x08,0x4f,0x10,0x57,0x61,0x4f,0x7c,0xde,0x8e,0x06,0xdd, + 0xdd,0xec,0x8f,0xf9,0x7b,0xd1,0xd5,0xba,0xfb,0x88,0xad,0xe1,0xef,0x67,0x2f,0xaa, + 0xf4,0xb1,0x9f,0x7b,0x98,0xb9,0xfc,0x7e,0xde,0x85,0xf1,0xf5,0x06,0xfe,0x20,0xb3, + 0x37,0x7e,0x00,0xde,0xfc,0xc1,0x86,0xf8,0x43,0xdc,0x3b,0xe3,0x87,0x1a,0xf8,0xc3, + 0xcc,0xce,0xf8,0xe1,0x06,0xfe,0x98,0xd8,0x2e,0xc7,0x8f,0x34,0xf0,0xc7,0xc5,0x8e, + 0x38,0x7e,0x14,0x7e,0x9d,0x74,0x7e,0x82,0x99,0xf2,0xd9,0x5a,0xfa,0x33,0x5f,0x67, + 0x72,0x92,0xdf,0x27,0xa8,0xa1,0xfe,0x29,0xb0,0xf5,0x32,0x89,0xd3,0xc4,0xbd,0x03, + 0x76,0x9a,0x38,0xf5,0xc7,0xc0,0x3a,0x45,0xf1,0x5d,0x6a,0xd8,0xb9,0xce,0x73,0x8e, + 0xa7,0xe4,0xa6,0x15,0x98,0x59,0x00,0xfb,0x57,0x10,0xbd,0x7f,0x3b,0xd9,0xe7,0x8f, + 0xd8,0xd9,0x17,0x04,0xd5,0x1d,0xfc,0x18,0x2c,0x38,0xec,0x13,0x30,0x3d,0xfb,0x3e, + 0xc1,0xf4,0x1d,0x7f,0x4a,0xac,0x72,0xcf,0x0a,0xa6,0x7b,0xf7,0x19,0xbb,0xd9,0x4d, + 0x7d,0x8d,0xbb,0x04,0xfe,0x16,0x79,0x9f,0x93,0x7b,0xc9,0xe5,0x7d,0x41,0x5e,0x8f, + 0xcb,0xbb,0x0c,0x7e,0x94,0xbc,0x2f,0xc9,0xbd,0x4c,0x9e,0xee,0xed,0x57,0xe4,0xf5, + 0x92,0xa7,0xf3,0xfe,0x1a,0xfc,0x82,0xc4,0xe8,0x2e,0x7f,0x03,0xa6,0xbb,0xbc,0x20, + 0x13,0x98,0xa0,0xb7,0xbb,0x12,0xaf,0xdc,0xb8,0xd8,0x04,0x73,0x19,0x77,0x3d,0x7f, + 0x8b,0x66,0x48,0x7b,0x52,0x4c,0xd8,0x15,0xf0,0x17,0xc5,0xd3,0x33,0x75,0xc4,0x1c, + 0xb3,0xb8,0xff,0xa4,0x86,0xd5,0xd2,0xe7,0x1d,0x89,0xd2,0xb8,0xf5,0x31,0x8f,0x29, + 0x91,0x33,0xee,0x7a,0xf8,0x8e,0x1e,0x76,0xb8,0x1e,0xbe,0x07,0xb7,0x1e,0x7e,0x00, + 0xb3,0x1e,0xa6,0x5c,0x0f,0xca,0x4d,0x8a,0x4d,0xa1,0x3b,0xe9,0x7a,0xf8,0x11,0xed, + 0xe8,0x7a,0xf8,0x09,0xdc,0x7a,0x58,0x17,0x73,0xcc,0xe2,0xb4,0x07,0xab,0x35,0xe5, + 0x7a,0xe8,0x8c,0x79,0xcc,0x04,0x39,0x93,0xae,0x87,0xab,0xf4,0xb0,0xdb,0xf5,0x70, + 0x0d,0xdc,0x7a,0xf8,0x19,0xcc,0x7a,0x98,0x71,0x3d,0x28,0x37,0x2d,0x36,0x83,0xee, + 0x74,0xfa,0x96,0xe4,0xba,0xbf,0xa0,0xdd,0x19,0x97,0xef,0x8e,0x9e,0xd1,0x62,0x67, + 0xdc,0x19,0x6b,0xc4,0x4d,0x91,0x37,0xcd,0x79,0xf4,0x6e,0xbc,0xcd,0xdd,0x52,0x5f, + 0xef,0xd1,0x19,0xee,0xd0,0xcb,0x72,0x3e,0xbd,0x3f,0xef,0x11,0x73,0xc6,0xed,0xe5, + 0xfb,0xf4,0xd5,0xef,0xf6,0xf2,0x2c,0xb8,0xed,0xf3,0x39,0x74,0xcf,0x92,0xa7,0xdf, + 0xbd,0x0f,0xc8,0x3b,0x4f,0x5e,0x2d,0xcd,0x21,0xc7,0x5f,0xe7,0x3d,0x5c,0x04,0xeb, + 0x93,0x2a,0xfa,0x4d,0xfc,0x90,0x33,0x9c,0xe3,0x1b,0x78,0xd1,0xd5,0xbb,0x4e,0xbd, + 0xbd,0xae,0xde,0xaf,0xe0,0x57,0x24,0x46,0xfd,0xdf,0xc0,0xba,0xdd,0xcc,0x7f,0x07, + 0xef,0x61,0xe6,0xb3,0x6e,0xe6,0xca,0xfd,0x21,0x36,0xcb,0x1c,0xf5,0xf7,0x33,0x12, + 0xd3,0xc7,0x59,0x74,0xc6,0xc6,0xcd,0x3a,0x9d,0x3f,0xd1,0xe9,0x77,0x3a,0x7f,0x81, + 0x9b,0xce,0x9c,0xd3,0x51,0xee,0x86,0xd8,0x1c,0xb5,0x6e,0xa0,0x53,0x77,0x3a,0xc6, + 0xcd,0x39,0x9d,0x9b,0xe8,0x1c,0x74,0x3a,0x7f,0x83,0x9b,0xce,0xbc,0xd3,0x51,0xee, + 0x96,0xd8,0x3c,0xb5,0x6e,0xa1,0x33,0xe0,0x74,0x8c,0x9b,0x77,0x3a,0xff,0xa0,0xd3, + 0xeb,0x74,0x6e,0x83,0x9b,0xce,0x82,0xd3,0xb9,0x9d,0xf6,0x2d,0x24,0x4c,0x6b,0xdd, + 0x41,0x67,0xd0,0xe9,0x18,0xb7,0xe0,0x74,0xee,0xa2,0x73,0xc8,0xe9,0xfc,0x0f,0x6e, + 0x3a,0x8b,0x4e,0x47,0xb9,0x7b,0x62,0x8b,0xd4,0xba,0x87,0xce,0x90,0xd3,0x31,0x6e, + 0xd1,0xe9,0xc4,0x98,0xeb,0x1c,0x76,0x3a,0x85,0x98,0xe3,0xa6,0x53,0x8a,0xcb,0x3a, + 0xca,0x65,0x62,0x8a,0x69,0x2d,0xfd,0xad,0x3a,0xc3,0x4e,0xc7,0xb8,0x52,0x5c,0xd6, + 0x69,0x46,0xe7,0x98,0xd3,0x59,0x11,0x73,0xdc,0x74,0xaa,0x4e,0x47,0xb9,0x16,0xb1, + 0x2a,0xb5,0x5a,0xd0,0x19,0x71,0x3a,0xc6,0x55,0x9d,0xce,0x4a,0x74,0x8e,0x3b,0x9d, + 0xd6,0x98,0xe3,0xa6,0xd3,0xee,0x74,0x94,0x6b,0x13,0x6b,0xa7,0x56,0x1b,0x3a,0xa3, + 0x4e,0xc7,0x38,0x7d,0xde,0x97,0xaf,0xca,0x76,0xb1,0x07,0x9c,0x82,0x63,0xd8,0x6c, + 0x0c,0x00,0x00 }; // Generated from: @@ -105,6 +107,7 @@ constexpr uint8_t kBlitResolve_frag_00000008[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -178,7 +181,7 @@ constexpr uint8_t kBlitResolve_frag_00000008[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// uvec4 colorValue = texture(usampler2D(color, blitSampler), srcImageCoords * params . invSrcExtent); +// uvec4 colorValue = textureLod(usampler2D(color, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip); // // broadcastColor(colorValue); // diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000009.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000009.inc index e255eb9c042..9f11f39e057 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000009.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000009.inc @@ -10,76 +10,77 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000009[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x65,0x95,0x5f,0x68,0xd6,0x65, - 0x14,0xc7,0x9f,0xdf,0xfb,0x77,0xeb,0x5d,0xeb,0x15,0xdd,0x56,0xf6,0xee,0x5f,0xca, - 0x10,0x26,0xba,0x0b,0x8b,0x46,0x14,0x05,0x42,0x5d,0x08,0xfe,0x09,0xda,0x2e,0x76, - 0xf3,0x42,0x5e,0x34,0x28,0x61,0x89,0x37,0xbb,0x30,0x68,0x81,0x37,0xbb,0xd8,0xcd, - 0x6e,0xd6,0xb2,0x59,0x64,0xf6,0x4f,0xbb,0x8b,0x52,0x29,0x49,0x1d,0xc5,0xac,0x51, - 0x2c,0x1d,0x0d,0xfa,0xc7,0x40,0x65,0xa0,0x32,0x71,0x2a,0x6a,0xe7,0x3c,0xbf,0xcf, - 0xd1,0xc3,0xab,0x70,0x7c,0x7e,0xe7,0xfb,0x3d,0xe7,0x7c,0x9f,0xf3,0x3c,0xe7,0x79, - 0x97,0xcd,0xac,0x2b,0x86,0x90,0x84,0x47,0x42,0x5d,0xe8,0x4c,0x42,0xfc,0xb7,0x2a, - 0x64,0x82,0x7e,0x96,0x42,0x21,0xae,0x2f,0x6f,0x7b,0x75,0xdb,0xa6,0xb7,0xf7,0xbe, - 0xbe,0x69,0xcb,0xd3,0x3d,0xca,0x37,0x86,0x6c,0x8c,0x53,0xee,0x31,0xf1,0x72,0xb2, - 0xaa,0xbd,0x59,0x7d,0xe3,0x2d,0xc5,0x9b,0xc5,0xfa,0xc5,0xaa,0x62,0x83,0x62,0x43, - 0x62,0xc3,0x62,0x23,0x62,0xa3,0x62,0xe3,0x62,0x65,0xa9,0xa1,0x39,0x45,0xad,0x2f, - 0x5f,0xcd,0x51,0x4f,0xeb,0x85,0xf0,0x4a,0xc8,0x87,0xd6,0x74,0x2b,0x61,0x1d,0xab, - 0x61,0x09,0x58,0x9d,0xc3,0x32,0x60,0x65,0x87,0x65,0xc1,0x1e,0x77,0x58,0x0e,0xac, - 0xe2,0xb0,0x3c,0x58,0x87,0xc3,0x0a,0x60,0xeb,0x1d,0x56,0x04,0xdb,0xe0,0xb0,0x3a, - 0xb0,0x8d,0x0e,0xab,0x07,0xeb,0x89,0x7d,0x65,0xef,0xef,0x4f,0x7b,0xd4,0x33,0x69, - 0xa3,0x1f,0xf5,0xab,0xf8,0x09,0xfe,0x20,0xbe,0xc5,0x0f,0xe1,0x67,0xf1,0x87,0xf1, - 0x73,0xf8,0x23,0xf8,0x79,0xfc,0x51,0xfc,0x02,0xfe,0x38,0xbe,0x9d,0xf1,0xa4,0xac, - 0x4f,0x39,0x7d,0xf5,0x3b,0x9d,0x3f,0x55,0xc3,0x4f,0xc1,0xeb,0x7e,0x56,0xcb,0xff, - 0x99,0xe8,0x67,0xe3,0x7e,0x32,0xf1,0x9e,0xb3,0x51,0x4b,0xcf,0xae,0x45,0xe2,0x8b, - 0x68,0x2b,0xd7,0x24,0x7e,0x09,0x2e,0xc0,0x37,0x70,0xc7,0x39,0xfc,0x35,0xc4,0xe7, - 0x62,0x5c,0x4e,0x72,0xd2,0xb3,0x50,0xfc,0x39,0xfc,0x66,0x30,0xad,0x57,0xa1,0x5e, - 0x12,0xfb,0x6a,0xb8,0x7f,0x2f,0x66,0x15,0xac,0xc0,0x5a,0x72,0xa6,0xf5,0xdb,0xb8, - 0x9f,0x56,0xea,0xab,0xdf,0x0e,0xd6,0x5d,0x53,0x5f,0xe3,0x3b,0xe1,0x8a,0x8e,0xef, - 0xa2,0x1f,0xf3,0xbb,0xe1,0x35,0x7e,0x23,0xf1,0xa5,0xd8,0x43,0x26,0x6c,0x26,0xae, - 0xc4,0x3c,0xf8,0xbc,0x5e,0xe6,0xc7,0xfc,0xad,0x35,0xfb,0xd8,0x4e,0x1f,0x5a,0x77, - 0x07,0x5c,0x05,0xbf,0x8f,0x99,0x68,0xa0,0x8f,0x3e,0xde,0x5b,0xd6,0xe5,0x0f,0x70, - 0x0f,0xc6,0x57,0x6b,0xf8,0xdd,0x9c,0xbb,0xf1,0x83,0xf0,0xe6,0x0f,0xd5,0xc4,0xef, - 0xe3,0x7d,0x19,0x3f,0x5c,0xc3,0xef,0xe7,0xec,0x8c,0x1f,0xa9,0xe1,0x0f,0x88,0xbd, - 0xe8,0xf8,0xd1,0x1a,0x7e,0x4c,0xec,0x1d,0xc7,0x8f,0xc3,0x3f,0x21,0x9d,0x4f,0x70, - 0xa6,0xfc,0x3c,0x3d,0xb4,0xea,0x99,0xbc,0xcf,0xf7,0x04,0x35,0xd4,0x9f,0x04,0x5b, - 0x2b,0x27,0x71,0x90,0xb8,0x0f,0xc1,0x0e,0x12,0xa7,0xfe,0x14,0xd8,0x93,0xa2,0xf8, - 0x11,0x35,0x6c,0x5f,0x47,0xd8,0x87,0xce,0xeb,0x97,0xdc,0x89,0xfa,0xcf,0xc8,0xab, - 0xcb,0x70,0x86,0x01,0x6c,0x45,0x10,0x7d,0x8b,0xcf,0x33,0xdb,0xdf,0x30,0xbf,0x3b, - 0x05,0xd5,0xbc,0x6f,0xc1,0x82,0xc3,0xbe,0x03,0xd3,0x5e,0x76,0x08,0xa6,0xb3,0x74, - 0x9c,0x58,0xe5,0x5e,0x12,0x4c,0xe7,0xf0,0x04,0xb3,0xda,0x41,0x7d,0x8d,0x3b,0x09, - 0xfe,0x1e,0x79,0xdf,0x93,0x7b,0xd2,0xe5,0xfd,0x40,0x5e,0x97,0xcb,0x3b,0x05,0xfe, - 0x2e,0x79,0x3f,0x92,0x7b,0x8a,0x3c,0x9d,0xe3,0xd3,0xe4,0x75,0x93,0xa7,0xe7,0x7f, - 0x06,0xfc,0x73,0x89,0xd1,0xd9,0x3e,0x0b,0xa6,0xb3,0x7d,0x43,0x4e,0x60,0x86,0xde, - 0x6e,0x49,0xbc,0x72,0xd3,0x62,0x33,0x9c,0xcb,0xb4,0xeb,0xf9,0x27,0x34,0x43,0x9c, - 0x9b,0x5c,0xc4,0x7e,0x06,0xdf,0x25,0x9e,0xee,0x69,0x6d,0x92,0x62,0x16,0x77,0x53, - 0x6a,0x58,0x2d,0x5d,0xaf,0x4b,0x94,0xc6,0xb5,0x25,0x69,0x4c,0x9e,0x9c,0x69,0xd7, - 0xc3,0x39,0x7a,0xe8,0x75,0x3d,0xfc,0x02,0x6e,0x3d,0xfc,0x0a,0x66,0x3d,0xcc,0xb9, - 0x1e,0x94,0x9b,0x15,0x9b,0x43,0x77,0xd6,0xf5,0xf0,0x1b,0xda,0x89,0xeb,0xe1,0x77, - 0x70,0xeb,0xa1,0x35,0x49,0x31,0x8b,0xd3,0x1e,0xac,0xd6,0x9c,0xeb,0xa1,0x3d,0x49, - 0x63,0x66,0xc8,0x99,0x75,0x3d,0xfc,0x41,0x0f,0x5b,0x5d,0x0f,0xe7,0xc1,0xad,0x87, - 0x0b,0x60,0xd6,0xc3,0x82,0xeb,0x41,0xb9,0x79,0xb1,0x05,0x74,0xe7,0xe3,0x6f,0x4b, - 0xaa,0xfb,0x27,0xda,0xed,0xc9,0x83,0xb7,0xa4,0x7b,0xb4,0xd8,0x05,0xb7,0xc7,0x0e, - 0xe2,0xe6,0xc8,0x9b,0x67,0x3f,0xfa,0x56,0x3e,0xe0,0xad,0xa9,0xaf,0xef,0xea,0x10, - 0x6f,0xea,0x35,0xd9,0x9f,0xbe,0xa7,0x8f,0x89,0x39,0xe4,0xe6,0xf2,0x13,0xfa,0x1a, - 0x70,0x73,0x79,0x18,0xdc,0xe6,0xf9,0x53,0x74,0x0f,0x93,0xa7,0xbf,0x83,0x9f,0x91, - 0x77,0x84,0xbc,0x4a,0x3c,0x87,0x14,0xdf,0xc3,0x3d,0x7c,0x01,0x66,0x77,0xf5,0x15, - 0xb5,0xfc,0xbb,0x3b,0x0a,0x96,0xbe,0xbb,0x42,0x7c,0xdb,0xc7,0x88,0x3d,0x4a,0x8d, - 0x3e,0x89,0xd5,0xdf,0xd8,0xaf,0xe9,0xe1,0x98,0xdb,0xc7,0x5f,0xec,0x63,0xbb,0xdb, - 0xc7,0xdf,0xe0,0x67,0x25,0x46,0xfd,0x7f,0xc0,0x3a,0xdc,0x5d,0xfd,0x0b,0xde,0xc5, - 0x5d,0x2d,0xba,0xbb,0x52,0xee,0x3f,0xb1,0x45,0xce,0x5f,0xbf,0x5f,0x90,0x98,0x7e, - 0xf6,0xa0,0x77,0x63,0xdc,0xa2,0xd3,0xb9,0x88,0xce,0x80,0xd3,0xb9,0x04,0x6e,0x3a, - 0x4b,0x4e,0x47,0xb9,0xcb,0x62,0x4b,0xd4,0xba,0x8c,0x4e,0xd5,0xe9,0x18,0xb7,0xe4, - 0x74,0xae,0xa0,0xb3,0xdb,0xe9,0x5c,0x05,0x37,0x9d,0x65,0xa7,0xa3,0xdc,0x35,0xb1, - 0x65,0x6a,0x5d,0x43,0x67,0xd0,0xe9,0x18,0xb7,0xec,0x74,0x6e,0xa0,0xd3,0xeb,0x74, - 0x56,0xc0,0x4d,0xe7,0xb6,0xd3,0x59,0x89,0xb5,0x42,0xc4,0xb4,0xd6,0x4d,0x74,0x86, - 0x9c,0x8e,0x71,0xb7,0x9d,0xce,0x5d,0x74,0xf6,0x39,0x9d,0x7b,0xe0,0xa6,0x93,0x49, - 0x1e,0xe8,0xdc,0xe3,0x8f,0x8e,0x62,0x5a,0x4b,0xbf,0x55,0x67,0xd8,0xe9,0x18,0xa7, - 0xab,0xe9,0xe4,0x93,0x54,0x67,0xbf,0xd3,0x29,0x24,0x29,0x6e,0x3a,0xf5,0x4e,0x47, - 0xb9,0xa2,0x58,0x3d,0xb5,0x8a,0xe8,0x8c,0x38,0x1d,0xe3,0xea,0x9d,0x4e,0x03,0x3a, - 0x07,0x9c,0xce,0xa3,0x49,0x8a,0x9b,0x4e,0xd9,0xe9,0x28,0xd7,0x28,0x56,0xa6,0x56, - 0x23,0x3a,0xa3,0x4e,0xc7,0xb8,0xb2,0xd3,0x59,0x8d,0xce,0x98,0xd3,0x59,0x93,0xa4, - 0xb8,0xe9,0xb4,0x38,0x1d,0xe5,0x9a,0xc4,0x5a,0xa8,0xd5,0x84,0xce,0xb8,0xd3,0x31, - 0x4e,0xd7,0x3b,0x72,0xb0,0xcf,0x8a,0xfd,0x0f,0x66,0x63,0x86,0x6f,0x9c,0x0c,0x00, - 0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x65,0x94,0x4d,0x68,0x9d,0x55, + 0x10,0x86,0xcf,0xb9,0xdf,0xfd,0x49,0x73,0xaf,0x36,0x21,0x9a,0xc6,0x98,0xd4,0xfc, + 0x94,0x20,0xa4,0xd4,0x2e,0xaa,0x58,0xa4,0x45,0xa1,0xa0,0x8b,0x42,0xab,0x82,0xcd, + 0x22,0x9b,0x0b,0xcd,0xc2,0x80,0x0a,0x51,0xba,0xc9,0xa2,0x82,0x11,0xba,0xc9,0xa2, + 0x9b,0x6c,0x6a,0xad,0xa9,0x62,0x6d,0xab,0x6d,0xb5,0xee,0xc4,0x9f,0xa2,0xa5,0x6a, + 0x50,0xa2,0x06,0x4b,0xd4,0x60,0xc0,0x3f,0x02,0x5a,0x02,0xb6,0x44,0x6b,0x0d,0xce, + 0x9c,0xef,0x99,0x66,0xb8,0x06,0x26,0xe7,0xce,0xfb,0xce,0xcc,0x7b,0xe6,0x9c,0x39, + 0x5f,0x56,0xe8,0xaf,0x84,0x10,0x43,0x73,0x68,0x0a,0x9b,0x62,0x48,0x7f,0xad,0xa1, + 0x10,0xf4,0x67,0x35,0x94,0xd3,0xfa,0xf0,0xee,0xc7,0x77,0x6f,0x79,0xf6,0xb9,0xfd, + 0x5b,0xb6,0xdd,0xbb,0x55,0xf9,0x5b,0x43,0x96,0xe2,0x94,0x5b,0x2f,0x5e,0x51,0x56, + 0xb5,0xa7,0xea,0x4f,0x3e,0xad,0x78,0xbb,0xd8,0x90,0x58,0x5d,0x6c,0x54,0x6c,0x4c, + 0x6c,0x5c,0x6c,0x42,0x6c,0x52,0x6c,0x4a,0xac,0x45,0x6a,0x68,0x4e,0x45,0xeb,0xcb, + 0xaf,0xf6,0xa4,0xa7,0xf5,0x42,0x78,0x24,0x94,0x42,0x77,0xbe,0x95,0xd0,0xcf,0x6a, + 0x58,0x04,0x6b,0x72,0x58,0x01,0xac,0xc5,0x61,0x19,0x58,0x87,0xc3,0x8a,0x60,0x5d, + 0x0e,0x2b,0x81,0xf5,0x38,0xac,0x0c,0xb6,0xc9,0x61,0x15,0xb0,0xbb,0x1d,0xd6,0x04, + 0xb6,0xd9,0x61,0xeb,0xc0,0xb6,0x3a,0xac,0x19,0x6c,0x5b,0xea,0x35,0xbb,0xb9,0x67, + 0xed,0x5b,0xcf,0x69,0x23,0x3d,0xaa,0x5f,0xc7,0x8f,0xf8,0xa3,0xf8,0x16,0x3f,0x86, + 0x9f,0xe1,0x8f,0xe3,0x17,0xf1,0x27,0xf0,0x4b,0xf8,0x93,0xf8,0x65,0xfc,0x29,0x7c, + 0x3b,0xf7,0xa3,0xb2,0xf6,0x39,0x7d,0xf5,0x7b,0x9d,0x3f,0xdd,0xc0,0x4f,0xc3,0xeb, + 0x7e,0xda,0xe4,0x7f,0x21,0xf9,0x59,0xda,0x4f,0x21,0xdd,0x7d,0x96,0xb4,0xf4,0x3c, + 0x37,0x48,0x7c,0x05,0x6d,0xe5,0x6e,0x17,0xbf,0x0a,0x17,0xe0,0x6b,0xdc,0x7b,0x11, + 0xff,0x36,0xe2,0x8b,0x29,0xae,0x28,0x39,0xf9,0x59,0x28,0xfe,0x00,0x7e,0x3b,0x98, + 0xd6,0xeb,0xa2,0x5e,0x4c,0x7d,0xdd,0x72,0xf3,0xae,0xcc,0xba,0x9c,0x95,0x59,0xab, + 0xce,0x54,0x63,0x23,0xf7,0xd6,0x8d,0x86,0xfa,0x77,0x81,0x0d,0x36,0x68,0x68,0x7c, + 0x2f,0x5c,0xc5,0xf1,0x03,0xf4,0x64,0xfe,0x20,0xf3,0xa1,0xf1,0x9b,0x89,0xaf,0xa6, + 0x3e,0x0a,0xe1,0x1e,0xe2,0xaa,0xcc,0x89,0xcf,0xdb,0xde,0xa0,0xbb,0x8b,0xf9,0x31, + 0x7f,0x0f,0xba,0x5a,0x77,0x2f,0xb1,0x5d,0xf8,0xfb,0x98,0x8b,0x1a,0x7d,0xec,0xe3, + 0x1d,0x66,0x2e,0x7f,0x98,0xbb,0x30,0xbe,0xde,0xc0,0x8f,0x70,0xf6,0xc6,0x8f,0xc2, + 0x9b,0x3f,0xd6,0x10,0x7f,0x80,0x77,0x67,0xfc,0x78,0x03,0x7f,0x90,0xb3,0x33,0x7e, + 0xa2,0x81,0x3f,0x24,0xf6,0xa0,0xe3,0x27,0x1b,0xf8,0xc3,0x62,0xcf,0x3b,0x7e,0x0a, + 0xfe,0x0e,0xe9,0xfc,0x08,0x67,0xca,0x67,0xeb,0x7f,0xab,0x9e,0xc9,0x4b,0xfc,0x3e, + 0x42,0x0d,0xf5,0x8f,0x82,0x75,0xca,0x49,0x1c,0x23,0xee,0x15,0xb0,0x63,0xc4,0xa9, + 0x3f,0x0d,0x76,0xa7,0x28,0xbe,0x4a,0x0d,0x9d,0xd1,0x37,0x99,0x25,0xbf,0xcf,0x73, + 0xf8,0xf7,0xc9,0xcb,0x2b,0x70,0x86,0x01,0xec,0x2f,0x41,0xf4,0x3d,0xee,0x60,0xbe, + 0xdf,0x63,0x86,0x1f,0x15,0x54,0xeb,0xbc,0x0f,0x16,0x1c,0xf6,0x01,0x98,0xf6,0xb2, + 0x57,0x30,0xbd,0xf3,0x0f,0x89,0x55,0xee,0x21,0xc1,0x74,0x0e,0x3f,0x62,0x56,0x7b, + 0xa8,0xaf,0x71,0x17,0xc0,0x5f,0x24,0xef,0x63,0x72,0x2f,0xb8,0xbc,0x4f,0xc8,0x1b, + 0x70,0x79,0x17,0xc1,0x5f,0x20,0xef,0x12,0xb9,0x17,0xc9,0xd3,0x39,0xfe,0x94,0xbc, + 0x41,0xf2,0xf4,0xfc,0x3f,0x03,0x3f,0x2d,0x31,0x3a,0xdb,0x9f,0x83,0xe9,0x6c,0xaf, + 0xc8,0x09,0xcc,0xd2,0xdb,0x75,0x89,0x57,0x6e,0x46,0x6c,0x96,0x73,0x99,0x71,0x3d, + 0x7f,0x81,0x66,0x48,0x73,0x53,0x4c,0xd8,0x97,0xe0,0x8f,0x89,0xa7,0x7b,0xea,0x8e, + 0x39,0x66,0x71,0x7f,0x4b,0x0d,0xab,0xa5,0xeb,0x35,0x89,0xd2,0xb8,0xde,0x98,0xc7, + 0x94,0xc8,0x99,0x71,0x3d,0x7c,0x45,0x0f,0xdb,0x5d,0x0f,0x5f,0x83,0x5b,0x0f,0xdf, + 0x80,0x59,0x0f,0xf3,0xae,0x07,0xe5,0xe6,0xc4,0xe6,0xd1,0x9d,0x73,0x3d,0x7c,0x8b, + 0x76,0x74,0x3d,0x5c,0x06,0xb7,0x1e,0x7a,0x62,0x8e,0x59,0x9c,0xf6,0x60,0xb5,0xe6, + 0x5d,0x0f,0x7d,0x31,0x8f,0x99,0x25,0x67,0xce,0xf5,0xf0,0x1d,0x3d,0xec,0x72,0x3d, + 0x7c,0x0f,0x6e,0x3d,0xfc,0x00,0x66,0x3d,0x2c,0xba,0x1e,0x94,0x5b,0x10,0x5b,0x44, + 0x77,0x21,0x7d,0x5b,0x72,0xdd,0x1f,0xd1,0xee,0x8b,0x6b,0x6f,0x49,0xf7,0x68,0xb1, + 0x8b,0x6e,0x8f,0xfd,0xc4,0xcd,0x93,0xb7,0xc0,0x7e,0xf4,0xad,0xbc,0xcc,0x5b,0x53, + 0x5f,0xdf,0xd5,0x71,0xde,0xd4,0x13,0xb2,0x3f,0x7d,0x4f,0xaf,0x11,0x73,0xdc,0xcd, + 0xe5,0xeb,0xf4,0x35,0xec,0xe6,0xf2,0x04,0xb8,0xcd,0xf3,0x1b,0xe8,0x9e,0x20,0x4f, + 0xbf,0x83,0x27,0xc9,0x1b,0x21,0x4f,0xdf,0xe4,0x29,0xf0,0x67,0xb8,0x87,0xd3,0x60, + 0x76,0x57,0x6f,0x51,0xcb,0xbf,0xbb,0x33,0x60,0xf9,0xbb,0x2b,0xa7,0xb7,0x7e,0x96, + 0xd8,0x33,0xd4,0x30,0xcd,0xb7,0xd1,0x3c,0xe7,0x34,0xdf,0x01,0x37,0xcd,0xf3,0x60, + 0x43,0xb2,0x73,0xfd,0x2e,0xbf,0x4b,0xdf,0x67,0xf9,0x0e,0x9f,0x77,0xf5,0x7e,0xa2, + 0xde,0x1e,0x57,0xef,0x67,0xf0,0x4b,0x12,0xa3,0xfe,0x2f,0x60,0x3d,0xee,0x9e,0x7f, + 0x05,0x1f,0xe0,0x9e,0x97,0xdc,0x3d,0x2b,0xf7,0x9b,0xd8,0x12,0x77,0xa7,0xbf,0x77, + 0x4a,0xcc,0x10,0x7b,0xd1,0x7b,0x35,0x6e,0xc9,0xe9,0xfc,0x8e,0xce,0xb0,0xd3,0xf9, + 0x03,0xdc,0x74,0x96,0x9d,0x8e,0x72,0x57,0xc4,0x96,0xa9,0x75,0x05,0x9d,0xba,0xd3, + 0x31,0x6e,0xd9,0xe9,0xfc,0x89,0xce,0x88,0xd3,0xb9,0x0a,0x6e,0x3a,0x2b,0x4e,0xe7, + 0x6a,0x9a,0xbd,0x90,0x30,0xad,0x75,0x0d,0x9d,0x51,0xa7,0x63,0xdc,0x8a,0xd3,0xb9, + 0x8e,0xce,0xa0,0xd3,0xf9,0x07,0xdc,0x74,0x56,0x9d,0x8e,0x72,0x37,0xc4,0x56,0xa9, + 0x75,0x03,0x9d,0x31,0xa7,0x63,0xdc,0xaa,0xd3,0x89,0x31,0xd7,0x39,0xe0,0x74,0x0a, + 0x31,0xc7,0x4d,0xa7,0x14,0xd7,0x74,0x94,0xcb,0xc4,0x14,0xd3,0x5a,0xfa,0x5b,0x75, + 0xc6,0x9d,0x8e,0x71,0xa5,0xb8,0xa6,0xd3,0x84,0xce,0x41,0xa7,0xb3,0x2e,0xe6,0xb8, + 0xe9,0xd4,0x9c,0x8e,0x72,0xcd,0x62,0x35,0x6a,0x35,0xa3,0x33,0xe1,0x74,0x8c,0xab, + 0x39,0x9d,0xf5,0xe8,0x1c,0x72,0x3a,0x2d,0x31,0xc7,0x4d,0xa7,0xcd,0xe9,0x28,0xd7, + 0x2a,0xd6,0x46,0xad,0x56,0x74,0x26,0x9d,0x8e,0x71,0x6d,0x4e,0xa7,0x1d,0x9d,0xc3, + 0x4e,0x67,0x43,0xcc,0x71,0xd3,0xe9,0x74,0x3a,0xca,0x75,0x88,0x75,0x52,0xab,0x03, + 0x9d,0x29,0xa7,0x63,0x9c,0xae,0xff,0xca,0x8b,0xbe,0x5f,0xec,0x3f,0xf9,0xf0,0x26, + 0xef,0xf0,0x0c,0x00,0x00 }; // Generated from: @@ -108,6 +109,7 @@ constexpr uint8_t kBlitResolve_frag_00000009[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -181,7 +183,7 @@ constexpr uint8_t kBlitResolve_frag_00000009[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// uvec4 colorValue = texture(usampler2DArray(color, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)); +// uvec4 colorValue = textureLod(usampler2DArray(color, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip); // // broadcastColor(colorValue); // diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000A.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000A.inc index e85ba35ae75..ac6bb17caa2 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000A.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000A.inc @@ -10,77 +10,78 @@ #pragma once constexpr uint8_t kBlitResolve_frag_0000000A[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4b,0x68,0x5d,0x55, - 0x14,0x86,0xf7,0xb9,0xf7,0xe6,0x24,0xed,0x4d,0x34,0xad,0xb7,0x4d,0xac,0x37,0x4d, - 0xb4,0x56,0x7c,0x94,0x52,0x88,0x8a,0x20,0x96,0x3a,0xd2,0x4a,0x83,0x98,0x0e,0x3a, - 0x09,0x18,0xc1,0x0c,0x1c,0xa4,0x58,0x94,0x0c,0x3a,0x30,0xc5,0x4e,0x32,0x28,0x42, - 0x26,0xd2,0x76,0xa0,0xad,0x15,0x8a,0x88,0x7d,0xcf,0xaa,0x16,0x1f,0xa5,0x12,0x6b, - 0x50,0xa2,0x06,0x03,0x3e,0x4a,0x40,0x4b,0x40,0x4b,0xc0,0xd4,0xf8,0x08,0x71,0xfd, - 0xfb,0x7c,0x3b,0x5d,0xdc,0xc0,0xca,0x3e,0xeb,0xff,0xd7,0x5e,0xff,0x5a,0xeb,0xec, - 0x7d,0x6e,0xb9,0xb4,0xa9,0x39,0x84,0x2c,0xac,0x0e,0x2d,0xa1,0x27,0x0b,0xf1,0x6f, - 0x4d,0x28,0x05,0x3d,0x56,0x43,0x1e,0xd7,0xa7,0x76,0xed,0xde,0xb5,0xf5,0x95,0x57, - 0x5f,0xdc,0xfa,0xf0,0x23,0xdb,0xc4,0xdf,0x16,0xca,0x31,0x4e,0xdc,0xed,0xe6,0x55, - 0x6c,0x95,0x0d,0xbf,0xf0,0xd2,0x5e,0xe1,0x1d,0x66,0xbb,0xcd,0x06,0xcc,0x86,0x84, - 0x9b,0x8d,0x98,0x8d,0x9a,0x8d,0x99,0x8d,0x9b,0xb5,0x5b,0x0e,0xed,0x69,0x56,0x7e, - 0x7b,0xea,0x88,0x7a,0xca,0x17,0xc2,0xd3,0xa1,0x29,0xd4,0x8b,0x52,0xc2,0x26,0xd6, - 0x84,0x65,0x60,0x2d,0x0e,0x2b,0x81,0xb5,0x3b,0xac,0x0c,0xd6,0xe9,0xb0,0x0a,0x58, - 0xdd,0x61,0x4d,0x60,0x3d,0x0e,0xcb,0xc1,0xee,0x75,0x58,0x33,0xd8,0xfd,0x0e,0x6b, - 0x01,0xdb,0xe2,0xb0,0x55,0x60,0xdb,0x62,0x5f,0xe5,0x95,0xfa,0xd4,0xa3,0x66,0xb2, - 0x91,0x7e,0xe4,0x0f,0xe0,0x67,0xf8,0x43,0xf8,0x29,0x7e,0x18,0xbf,0x8c,0x3f,0x82, - 0x5f,0xc1,0x1f,0xc5,0x6f,0xc2,0x1f,0xc3,0xcf,0xf1,0xc7,0xf1,0xd3,0x8c,0x4f,0xd8, - 0x7a,0x8f,0xd3,0x97,0x7f,0x37,0xfe,0x1d,0xa6,0x5a,0x8a,0x7e,0x39,0xea,0xe9,0x79, - 0x9d,0xc5,0xe4,0xcc,0x26,0x8b,0xef,0xb5,0x12,0x73,0xe5,0x8e,0xaf,0xc2,0x07,0xf8, - 0x56,0xde,0xa3,0x6a,0x5c,0x6f,0x99,0x6a,0xf0,0xe2,0xd6,0xd9,0x5a,0x83,0xeb,0xb1, - 0xff,0xeb,0xc9,0x2b,0xfc,0x71,0xfc,0x0e,0xa7,0xd5,0x49,0x7c,0x29,0xf6,0xd1,0xba, - 0xf2,0x1e,0x3a,0xb1,0x1c,0xab,0xb1,0x56,0x9d,0x29,0x7f,0x17,0xef,0xa3,0x4e,0xfe, - 0x2e,0xe6,0x21,0xec,0x21,0x7a,0xeb,0xa6,0x76,0xc5,0xf7,0xc0,0x35,0x3b,0x7e,0x33, - 0xbe,0xf8,0xfb,0xe0,0xab,0x51,0xb3,0x14,0x1e,0x20,0x4e,0xfe,0x83,0xe4,0x49,0xfb, - 0x7a,0x39,0x1f,0xc9,0xdf,0xde,0xa0,0xbb,0x93,0x9a,0x95,0xf7,0x19,0xb8,0xdc,0xf1, - 0x7d,0xcc,0x41,0x7c,0x3f,0x67,0xa0,0x95,0x3e,0xfa,0xb9,0x5f,0x65,0x17,0xbf,0x87, - 0x39,0x25,0x7e,0xa0,0x81,0x1f,0x64,0xee,0x89,0x1f,0x82,0x4f,0xfe,0x70,0x43,0xfc, - 0x3e,0xee,0x53,0xe2,0x47,0x1a,0xf8,0xfd,0xbc,0xd7,0xc4,0x8f,0x36,0xf0,0x07,0xcd, - 0x76,0x38,0x7e,0xac,0x81,0x3f,0x64,0x76,0xc0,0xf1,0xe3,0xf0,0x5b,0x6c,0xda,0xea, - 0xf3,0x4d,0x66,0xea,0xed,0x4e,0x9b,0xd2,0x71,0xe6,0xcf,0xa7,0x6a,0xe5,0x3b,0x94, - 0xb9,0xf7,0xf8,0x0e,0xcf,0xc7,0xc9,0x2f,0xff,0x44,0xc3,0xfb,0x39,0xc5,0xbd,0x51, - 0xfc,0x69,0xe6,0xaf,0x73,0xf4,0xa8,0xa1,0x25,0x66,0x15,0xa8,0x69,0xd1,0x10,0xc5, - 0x3e,0xc1,0x19,0xbe,0xc8,0x39,0x7d,0xd6,0x6a,0xd5,0x39,0xfc,0x10,0xec,0xa2,0xab, - 0x67,0x2f,0x77,0xe5,0x23,0xf8,0x27,0x2d,0x83,0xe6,0xf5,0x31,0x67,0xb0,0x9b,0x7c, - 0x8a,0xb9,0x04,0xfe,0xba,0xc5,0xc8,0xff,0x84,0x7d,0x97,0xd8,0xa7,0x73,0xf7,0x29, - 0xfb,0x36,0xb3,0x4f,0x33,0xf8,0x0c,0xfc,0x7d,0x8b,0xd1,0x59,0xfc,0x1c,0x4c,0xb3, - 0xfa,0xcb,0x2a,0x9f,0xa0,0x9e,0x7f,0x2c,0x5e,0xdc,0x65,0xb3,0x09,0xfa,0xd1,0xf3, - 0x73,0xb6,0x4f,0xb3,0xb8,0x82,0xa6,0xfe,0x5e,0x63,0x3e,0x5f,0x80,0xf7,0x9b,0xa7, - 0x9a,0x3a,0xb2,0x02,0x4b,0x71,0x7f,0x5b,0x8e,0x94,0x4b,0xeb,0x82,0x45,0x29,0xee, - 0xae,0xac,0x88,0x69,0x62,0xcf,0x65,0xd7,0xc3,0x97,0xf4,0xd0,0xeb,0x7a,0xb8,0x0a, - 0x9e,0x7a,0xf8,0x0a,0x2c,0xf5,0x30,0xe5,0x7a,0x10,0x37,0x69,0x36,0x85,0xee,0xa4, - 0xeb,0xe1,0x6b,0xb4,0x33,0xd7,0xc3,0x37,0xe0,0xa9,0x87,0x0d,0x59,0x81,0xa5,0x38, - 0xf5,0x90,0x72,0x4d,0xb9,0x1e,0xea,0x59,0x11,0x33,0xc1,0x9e,0x49,0xd7,0xc3,0xb7, - 0xf4,0xb0,0xdd,0xf5,0xf0,0x1d,0x78,0xea,0xe1,0x7b,0xb0,0xd4,0xc3,0x8c,0xeb,0x41, - 0xdc,0xb4,0xd9,0x0c,0xba,0xd3,0x9c,0x23,0xe9,0xfe,0x80,0x76,0x3d,0xbb,0x75,0x9e, - 0x55,0x63,0x8a,0x9d,0x71,0x35,0x76,0x11,0x37,0xc5,0xbe,0x69,0x62,0x0f,0x13,0x7b, - 0x98,0x58,0xdd,0xa5,0xee,0xac,0xb8,0x4f,0xda,0xff,0x9e,0xd9,0x11,0x38,0xcd,0x68, - 0x63,0x56,0x9c,0xc5,0x99,0x58,0x7f,0xc1,0xa9,0x57,0x7d,0x93,0xde,0xa2,0xd7,0x41, - 0x7a,0x55,0xfc,0xdb,0xe0,0x67,0xe9,0xf5,0x18,0x39,0x84,0xdf,0xb4,0x98,0xa3,0xe4, - 0x48,0xfd,0x1e,0xc3,0x3f,0x4a,0x5d,0x47,0xc8,0xa5,0xbb,0xf9,0x2e,0xf7,0xf2,0x79, - 0xea,0x3c,0x09,0xa6,0xde,0x76,0x90,0xf7,0x80,0xe9,0xb4,0x52,0xb7,0xfa,0x38,0x19, - 0x0a,0x2c,0xa7,0x5e,0xc5,0xf4,0x35,0xf4,0x2e,0xad,0x97,0xb9,0xab,0x1f,0xb0,0x4f, - 0x3d,0xe9,0x9e,0x9f,0xa1,0xa7,0x53,0xd4,0x51,0x8b,0xbd,0x14,0xf8,0x1b,0x16,0xa3, - 0x3d,0xe7,0xd8,0x77,0x36,0x7e,0x73,0xf3,0x88,0x9d,0x77,0xdf,0x99,0x73,0xf1,0x7b, - 0x59,0xfc,0xd6,0x5d,0x80,0x4b,0x33,0xfb,0x91,0xfc,0x3b,0xdd,0xcc,0x7e,0x02,0xbf, - 0x42,0xdd,0x3f,0x83,0xf5,0xb9,0x33,0xf3,0x0b,0x78,0x37,0x67,0x66,0xd6,0xcd,0x50, - 0xdc,0x35,0xb3,0x59,0xfa,0xbb,0x16,0xcf,0x5f,0x39,0xfe,0x06,0x5c,0xa0,0xf7,0xc4, - 0xcd,0x3a,0x9d,0x5f,0xd1,0xd9,0xe3,0x74,0x7e,0x03,0x4f,0x3a,0x73,0x4e,0x47,0xdc, - 0x75,0xb3,0x39,0x72,0x5d,0x47,0x67,0xc0,0xe9,0x24,0x6e,0xce,0xe9,0xfc,0x8e,0xce, - 0xa0,0xd3,0xf9,0x03,0x3c,0xe9,0xcc,0x3b,0x1d,0x71,0x37,0xcc,0xe6,0xc9,0x75,0x03, - 0x9d,0x21,0xa7,0x93,0xb8,0x79,0xa7,0xf3,0x27,0x3a,0xbd,0x4e,0x67,0x01,0x3c,0xe9, - 0x2c,0x3a,0x9d,0x85,0x78,0x26,0x43,0xc4,0x94,0xeb,0x26,0x3a,0xc3,0x4e,0x27,0x71, - 0x8b,0x4e,0xe7,0x5f,0x74,0xf6,0x39,0x9d,0xff,0xc0,0x93,0xce,0xb2,0xd3,0x11,0xb7, - 0x64,0xb6,0x4c,0xae,0x25,0x74,0x46,0x9c,0x4e,0xe2,0x96,0x9d,0x4e,0x29,0x2b,0x74, - 0xf6,0x3b,0x9d,0x72,0x56,0xe0,0x49,0x27,0xcf,0x6e,0xe9,0x88,0xab,0x98,0x09,0x53, - 0x2e,0x3d,0x4b,0x67,0xd4,0xe9,0x24,0x4e,0x6b,0xd2,0x59,0x85,0xce,0x41,0xa7,0xb3, - 0x3a,0x2b,0xf0,0xa4,0xd3,0xe6,0x74,0xc4,0x55,0xcd,0xda,0xc8,0x55,0x45,0x67,0xcc, - 0xe9,0x24,0xae,0xcd,0xe9,0xb4,0xa3,0x73,0xc8,0xe9,0xac,0xc9,0x0a,0x3c,0xe9,0xd4, - 0x9c,0x8e,0xb8,0xb5,0x66,0x35,0x72,0xad,0x45,0x67,0xdc,0xe9,0x24,0x4e,0xeb,0x92, - 0xdd,0xbe,0xc7,0xcc,0xfe,0x07,0x7d,0xe5,0xad,0x67,0xb4,0x0c,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x5f,0x68,0x97,0x65, + 0x14,0xc7,0xdf,0xf7,0xf7,0x77,0x6d,0x6b,0x69,0xdb,0xdc,0xa2,0xcd,0xcd,0x6c,0xd1, + 0x1f,0x11,0x41,0x8b,0x20,0x12,0xbb,0x2a,0xc3,0x11,0xcd,0x0b,0x6f,0x06,0x19,0xb4, + 0x8b,0x2e,0x26,0x49,0xb1,0x0b,0x2f,0x9a,0xe4,0xcd,0x2e,0x24,0xd8,0x4d,0xa8,0x17, + 0x96,0x66,0x20,0x15,0x69,0x9a,0x77,0x56,0xd2,0x1f,0x2b,0x66,0x8d,0x62,0xd5,0x68, + 0xd0,0x1f,0x19,0x94,0x0c,0x4a,0x06,0xce,0x16,0x29,0x9d,0xef,0xf3,0x7e,0xce,0x3a, + 0xfc,0x06,0x67,0xef,0x7b,0xbe,0xdf,0xf3,0x9c,0xef,0x39,0xe7,0x79,0x9e,0xf7,0x57, + 0x2e,0xad,0xaf,0x67,0x59,0x9e,0x35,0x67,0x4d,0xd9,0xba,0x3c,0x4b,0x7f,0xab,0xb3, + 0x52,0xa6,0xd7,0x96,0xac,0x96,0x9e,0x8f,0xef,0xd8,0xb9,0x63,0xe3,0x8b,0x2f,0x3d, + 0xb7,0x71,0xcb,0x83,0x9b,0xc4,0xb7,0x65,0xe5,0x14,0x27,0xee,0x36,0xf3,0x2a,0xf6, + 0x94,0x8d,0x3e,0xfb,0xfc,0x1e,0xe1,0x5d,0x66,0x3b,0xcd,0x86,0xcd,0x46,0x84,0x9b, + 0x8d,0x99,0x8d,0x9b,0x4d,0x98,0x4d,0x9a,0xad,0xb2,0x1c,0x5a,0x53,0x57,0x7e,0x7b, + 0xeb,0x4a,0x7a,0xca,0x97,0x65,0x4f,0x64,0xd5,0xac,0xa7,0x28,0x25,0x5b,0xcf,0xd3, + 0xb1,0x1c,0xac,0x29,0x60,0x25,0xb0,0x55,0x01,0x2b,0x83,0x75,0x07,0xac,0x02,0xd6, + 0x13,0xb0,0x2a,0x58,0x7f,0xc0,0x6a,0x60,0x77,0x07,0xac,0x0e,0x76,0x6f,0xc0,0x9a, + 0xc0,0x36,0x04,0xec,0x16,0xb0,0x4d,0x01,0x6b,0x06,0xdb,0x92,0x7a,0x2d,0xaf,0xd4, + 0xac,0xbe,0x35,0xa7,0xb5,0xf4,0x28,0x7f,0x18,0x3f,0xc7,0x1f,0xc1,0xf7,0xf8,0x51, + 0xfc,0x32,0xfe,0x18,0x7e,0x05,0x7f,0x1c,0xbf,0x8a,0x3f,0x81,0x5f,0xc3,0x9f,0xc4, + 0xf7,0xb9,0x9f,0xb0,0xe7,0x5d,0x41,0x5f,0xfe,0x3a,0xfc,0x76,0x53,0x2d,0x25,0xbf, + 0x9c,0xf4,0xf4,0xde,0x69,0x31,0x35,0xe6,0x95,0xa7,0xbd,0xae,0xa4,0x5c,0xb5,0xc0, + 0xb7,0xc0,0x67,0xf0,0xad,0xec,0xad,0x6a,0x5c,0x63,0x99,0x3a,0xe0,0xc5,0x75,0xda, + 0xb3,0x03,0xae,0xdf,0xfe,0xaf,0x21,0xaf,0xf0,0x47,0xf0,0xbb,0x82,0x56,0x37,0xf1, + 0xa5,0xd4,0xc7,0xad,0x2b,0x7b,0xd3,0x8d,0xd5,0x82,0x75,0xf0,0x6c,0x09,0x26,0x8d, + 0x5e,0xf6,0xa9,0x07,0x8d,0x5e,0x66,0x22,0xec,0x01,0xfa,0xeb,0xa3,0x7e,0xc5,0xf7, + 0xc3,0xd5,0x03,0x3f,0xc0,0xfe,0x8b,0xbf,0x07,0xbe,0x25,0x69,0x96,0xb2,0xfb,0x88, + 0x93,0x7f,0x3f,0x79,0x7c,0xdd,0xe6,0x06,0x9d,0xad,0x9c,0x0f,0xf7,0xb7,0xa3,0xa3, + 0xbc,0x4f,0x12,0x5b,0x0b,0xfc,0x20,0xb3,0x10,0x3f,0xc4,0x39,0x68,0xa5,0x8f,0x21, + 0xee,0x5d,0x39,0xc4,0xef,0x62,0x56,0xce,0x0f,0x37,0xf0,0xbb,0x99,0xbd,0xf3,0x23, + 0xf0,0xee,0x8f,0x36,0xc4,0xef,0xe5,0x9e,0x39,0x3f,0xd6,0xc0,0xef,0x63,0x6f,0x9d, + 0x1f,0x6f,0xe0,0x0f,0x98,0x6d,0x0b,0xfc,0x44,0x03,0x7f,0xd0,0x6c,0x7f,0xe0,0x27, + 0xe1,0x37,0xd8,0x54,0xd4,0xe7,0x6b,0xcc,0x34,0x9a,0xaf,0x3d,0xca,0xb9,0xbf,0xc3, + 0xa6,0x76,0x9c,0xfd,0xe0,0x93,0xb6,0xf2,0xbd,0xca,0xc3,0xbe,0xbe,0xc9,0xfb,0x71, + 0xf4,0xe4,0x9f,0x68,0xd8,0xaf,0x53,0xcc,0x5f,0xf1,0xa7,0xd9,0x0f,0x9d,0xab,0x87, + 0x4c,0xa9,0xc4,0xec,0x32,0x6a,0xfc,0xdb,0x10,0xe9,0x3f,0xca,0xb9,0x3e,0xcf,0xd9, + 0x7d,0xca,0x6a,0xd7,0xd9,0xfc,0x10,0xec,0x7c,0xa8,0x67,0x0f,0xf7,0xe7,0x23,0xf8, + 0xc7,0x2c,0x83,0xe6,0xf7,0x31,0x67,0xb2,0x8f,0x7c,0x8a,0xb9,0x00,0xfe,0x8a,0xc5, + 0xc8,0xff,0x84,0x75,0x17,0x58,0xa7,0x73,0xf8,0x29,0xeb,0x06,0x58,0xa7,0x19,0x7c, + 0x06,0xfe,0x8e,0xc5,0xe8,0x6c,0x7e,0x0e,0xa6,0xd9,0x5d,0xb7,0xca,0xa7,0xa8,0xe7, + 0x1f,0x8b,0x17,0x77,0xd1,0x6c,0x8a,0x7e,0xf4,0xfe,0xb4,0xad,0xd3,0x0c,0xbe,0x44, + 0x53,0x7f,0x2f,0x33,0x9f,0xaf,0xc0,0x87,0xcc,0x4b,0xf7,0x30,0x2f,0x30,0x8f,0x5b, + 0xb6,0x1c,0x9e,0x4b,0xcf,0x6b,0x16,0xa5,0xb8,0x9e,0xbc,0x88,0xa9,0xb2,0xe6,0x62, + 0xe8,0xe1,0x12,0x3d,0x6c,0x0e,0x3d,0x7c,0x0d,0xee,0x3d,0x7c,0x03,0xe6,0x3d,0xcc, + 0x84,0x1e,0xc4,0x4d,0x9b,0xcd,0xa0,0x3b,0x1d,0x7a,0xf8,0x16,0xed,0x3c,0xf4,0xf0, + 0x1d,0xb8,0xf7,0x70,0x67,0x5e,0x60,0x1e,0xa7,0x1e,0x3c,0xd7,0x4c,0xe8,0xa1,0x37, + 0x2f,0x62,0xa6,0x58,0x33,0x1d,0x7a,0xf8,0x9e,0x1e,0xb6,0x86,0x1e,0x7e,0x00,0xf7, + 0x1e,0x7e,0x04,0xf3,0x1e,0xe6,0x42,0x0f,0xe2,0x66,0xcd,0xe6,0xd0,0x9d,0xe5,0x1c, + 0x49,0xf7,0x27,0xb4,0x7b,0xf3,0xff,0xcf,0xb3,0x6a,0xf4,0xd8,0xb9,0x50,0xe3,0x5a, + 0xe2,0x66,0x58,0x37,0x4b,0xec,0x21,0x62,0x0f,0x11,0xab,0xbb,0xd5,0x9f,0x17,0xf7, + 0x4b,0xeb,0xdf,0x36,0x3b,0x0c,0x97,0xbe,0x87,0x79,0x71,0x16,0xc5,0xbd,0x0b,0xa7, + 0x5e,0xf5,0x8d,0x7a,0x9d,0x5e,0x8f,0xd2,0xab,0xe2,0xdf,0x00,0x7f,0x9f,0x5e,0x8f, + 0x91,0x43,0xf8,0x92,0xc5,0x1c,0x21,0x87,0xf7,0x7b,0x0c,0xff,0x08,0x75,0x1d,0x26, + 0x97,0xee,0xe6,0x5b,0xdc,0xcb,0x67,0xa8,0xf3,0x24,0x98,0x7a,0xdb,0x46,0xde,0xfd, + 0xa6,0xd3,0x4a,0xdd,0xea,0xe3,0x64,0x56,0x60,0x35,0xea,0x55,0xcc,0x60,0x43,0xef, + 0xd2,0x7a,0x81,0xbb,0xfa,0x1e,0xeb,0xd4,0xd3,0xe9,0x54,0x77,0xd1,0xd3,0x29,0xea, + 0xd0,0x9d,0x3f,0x03,0xfe,0xaa,0xc5,0x68,0xcd,0x59,0xd6,0x9d,0x49,0xdf,0xe0,0x5a, + 0xc2,0x3e,0x08,0xdf,0x99,0xb3,0xe9,0xfb,0x59,0xfc,0xfe,0x9d,0x83,0xf3,0x99,0xfd, + 0x4c,0xfe,0xed,0x61,0x66,0xbf,0x80,0x7f,0x41,0xdd,0xbf,0x82,0x0d,0x86,0x33,0xf3, + 0x1b,0x78,0x1f,0x67,0x66,0x3e,0xcc,0x50,0xdc,0x65,0xb3,0x79,0xfa,0xbb,0x9c,0xce, + 0x5f,0x39,0xfd,0x26,0x9c,0xa3,0x77,0xe7,0xe6,0x83,0xce,0xef,0xe8,0xec,0x0a,0x3a, + 0x7f,0x80,0xbb,0xce,0x42,0xd0,0x11,0x77,0xc5,0x6c,0x81,0x5c,0x57,0xd0,0x19,0x0e, + 0x3a,0xce,0x2d,0x04,0x9d,0x3f,0xd1,0xd9,0x1d,0x74,0xfe,0x02,0x77,0x9d,0xc5,0xa0, + 0x23,0xee,0xaa,0xd9,0x22,0xb9,0xae,0xa2,0x33,0x12,0x74,0x9c,0x5b,0x0c,0x3a,0xd7, + 0xd0,0x19,0x08,0x3a,0x4b,0xe0,0xae,0xb3,0x1c,0x74,0x96,0x12,0x96,0x25,0x4c,0xb9, + 0xae,0xa3,0x33,0x1a,0x74,0x9c,0x5b,0x0e,0x3a,0xff,0xa2,0xb3,0x37,0xe8,0xdc,0x00, + 0x77,0x1d,0xbf,0xa0,0xd2,0x11,0x77,0x93,0x0f,0xbf,0x72,0xdd,0x44,0x67,0x2c,0xe8, + 0x38,0xa7,0xa7,0xeb,0x94,0xf3,0x42,0x67,0x5f,0xd0,0xa9,0xe4,0x05,0xee,0x3a,0xf5, + 0xa0,0x23,0xae,0x6a,0x56,0x27,0x97,0xde,0xa5,0x33,0x1e,0x74,0x9c,0xab,0x07,0x9d, + 0x66,0x74,0x0e,0x04,0x9d,0x96,0xbc,0xc0,0x5d,0xa7,0x2d,0xe8,0x88,0x6b,0x35,0x6b, + 0x23,0x57,0x2b,0x3a,0x13,0x41,0xc7,0xb9,0xb6,0xa0,0xb3,0x1a,0x9d,0x83,0x41,0xe7, + 0xf6,0xbc,0xc0,0x5d,0xa7,0x33,0xe8,0x88,0x6b,0x37,0xeb,0x24,0x57,0x3b,0x3a,0x93, + 0x41,0xc7,0x39,0x3d,0x6f,0xd8,0xf0,0x1e,0x36,0xfb,0x0f,0x8c,0xca,0xb9,0x26,0xdc, + 0x0c,0x00,0x00 }; // Generated from: @@ -109,6 +110,7 @@ constexpr uint8_t kBlitResolve_frag_0000000A[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000B.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000B.inc index 3cf96d6500a..212dfb3039d 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000B.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000B.inc @@ -10,80 +10,80 @@ #pragma once constexpr uint8_t kBlitResolve_frag_0000000B[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4b,0x6c,0x55,0x55, - 0x14,0x86,0xf7,0xbe,0xb7,0x3d,0x2d,0xdc,0x56,0x0b,0x5e,0x68,0x1b,0x0a,0x2d,0x14, - 0xf0,0x45,0x08,0x49,0xd5,0x98,0x18,0x89,0x8e,0x14,0x43,0xa3,0x96,0x01,0x93,0x26, - 0xd6,0xc4,0x0e,0x1c,0x94,0x48,0x34,0x1d,0x30,0xb0,0x44,0x26,0x1d,0x10,0x93,0x4e, - 0x0c,0x30,0x50,0x10,0x83,0x8f,0x12,0xa2,0x46,0x14,0x64,0x86,0x8a,0x0f,0x08,0xa6, - 0x6a,0xa3,0xa9,0xda,0xd8,0xc4,0x07,0x69,0xa2,0xa4,0x89,0xc5,0xfa,0x68,0xea,0xfa, - 0xcf,0xf9,0x36,0xac,0xdc,0x26,0xab,0xfb,0xac,0xff,0x5f,0x7b,0xfd,0x7b,0xad,0xfd, - 0xb8,0xe5,0x52,0x77,0x43,0x08,0x31,0x2c,0x0f,0x8d,0xe1,0xd6,0x18,0xf2,0xbf,0x15, - 0xa1,0x14,0xf4,0x59,0x09,0x59,0x3e,0x3e,0xb4,0x73,0xd7,0xce,0xad,0xcf,0x3e,0xf7, - 0xd4,0xd6,0xbb,0xee,0xde,0x26,0xfe,0xa6,0x50,0xce,0xe3,0xc4,0xdd,0x6c,0x5e,0x9d, - 0x8d,0xb2,0xa1,0x27,0x9f,0xde,0x23,0xbc,0xd5,0x6c,0x97,0x59,0xbf,0xd9,0xa0,0x70, - 0xb3,0x61,0xb3,0x11,0xb3,0x51,0xb3,0x31,0xb3,0x16,0xcb,0xa1,0x39,0x0d,0xca,0x6f, - 0x5f,0xad,0xb9,0x9e,0xf2,0x85,0xf0,0x70,0xa8,0x0f,0x1d,0xc5,0x52,0x42,0x37,0x63, - 0xc2,0x22,0x58,0xa3,0xc3,0x4a,0x60,0x2d,0x0e,0x2b,0x83,0xb5,0x39,0xac,0x0e,0xac, - 0xc3,0x61,0xf5,0x60,0x5d,0x0e,0xcb,0xc0,0x36,0x3a,0xac,0x01,0xec,0x36,0x87,0x35, - 0x82,0x6d,0x71,0xd8,0x32,0xb0,0x6d,0x79,0x5d,0xe5,0xeb,0xeb,0x53,0x8d,0xea,0xc9, - 0x3a,0xea,0x91,0xdf,0x8f,0x1f,0xf1,0x07,0xf1,0x53,0xfc,0x10,0x7e,0x19,0x7f,0x18, - 0xbf,0x0e,0x7f,0x04,0xbf,0x1e,0x7f,0x14,0x3f,0xc3,0x1f,0xc3,0x4f,0x3d,0x3e,0x6e, - 0xe3,0x06,0xa7,0x2f,0x7f,0x3d,0xfe,0x2d,0xa6,0x5a,0xca,0xfd,0x72,0xae,0xa7,0xef, - 0x55,0x16,0x93,0xd1,0x9b,0x98,0xef,0x6b,0x5d,0x9e,0x2b,0x73,0x7c,0x05,0x3e,0xc0, - 0x37,0xb1,0x8f,0x5a,0xe3,0x6a,0xcb,0x54,0x85,0x17,0xb7,0xca,0xc6,0x2a,0x5c,0x97, - 0xfd,0x5f,0x4d,0x5e,0xe1,0xf7,0xe1,0xb7,0x3a,0xad,0x36,0xe2,0x4b,0x79,0x1d,0x4d, - 0xd7,0xf7,0xa1,0x0d,0xcb,0xb0,0x2a,0x63,0xc5,0x99,0xf2,0xaf,0x65,0x3f,0x3a,0xc8, - 0xbf,0x96,0x7e,0x08,0xbb,0x93,0xda,0x3a,0x59,0xbb,0xe2,0xbb,0xe0,0x1a,0x1c,0xbf, - 0x09,0x5f,0xfc,0x66,0xf8,0x4a,0xae,0x59,0x0a,0xb7,0x13,0x27,0xff,0x0e,0xf2,0xa4, - 0x79,0x3d,0x9c,0x8f,0xe4,0x6f,0xaf,0xd1,0xdd,0xc1,0x9a,0x95,0xf7,0x11,0xb8,0xcc, - 0xf1,0xbd,0xf4,0x41,0x7c,0x1f,0x67,0xa0,0x89,0x3a,0xfa,0xb8,0x5f,0x65,0x17,0xbf, - 0x9b,0x3e,0x25,0xbe,0xbf,0x86,0x1f,0xa0,0xef,0x89,0x1f,0x84,0x4f,0xfe,0x50,0x4d, - 0xfc,0x5e,0xee,0x53,0xe2,0x87,0x6b,0xf8,0x7d,0xec,0x6b,0xe2,0x47,0x6a,0xf8,0x03, - 0x66,0x0f,0x38,0x7e,0xb4,0x86,0x3f,0x68,0xb6,0xdf,0xf1,0x63,0xf0,0x5b,0xac,0xdb, - 0xaa,0xf3,0x25,0x7a,0xea,0xad,0xdd,0xba,0x74,0x8c,0xfe,0xf3,0x54,0xe5,0x63,0x74, - 0xbe,0xfa,0xf5,0x2a,0xdf,0xc7,0xc8,0x2f,0xff,0x78,0xcd,0xfe,0x9c,0x40,0x4f,0xe7, - 0xec,0x4d,0x7a,0xef,0xd7,0x77,0x9a,0x7b,0xa5,0x7c,0xef,0xb3,0x3f,0x3a,0x67,0xf7, - 0x18,0x5a,0xa2,0x97,0x81,0x39,0x0b,0x86,0x28,0xf6,0x7e,0xce,0xf8,0x79,0xce,0xf1, - 0xa3,0x56,0x8b,0xce,0xe9,0x47,0x60,0xe7,0xdd,0x9a,0xf7,0x70,0x97,0x3e,0x86,0x7f, - 0xd0,0x32,0xa8,0x9f,0x9f,0x70,0x46,0x3b,0xc9,0xa7,0x98,0x0b,0xe0,0x2f,0x58,0x8c, - 0xfc,0xcf,0x98,0x77,0x81,0x79,0x3a,0x97,0x9f,0x33,0x6f,0x13,0xf3,0xd4,0xa3,0x2f, - 0xc0,0xc7,0x2d,0x46,0x67,0xf5,0x22,0x98,0x7a,0xf9,0x97,0xad,0x7c,0x82,0xf5,0xfc, - 0x63,0xf1,0xe2,0x2e,0x99,0x4d,0x50,0x8f,0xbe,0x1f,0xb7,0x79,0xea,0xc5,0x65,0x34, - 0xf5,0xf7,0x3c,0xfd,0xf9,0x12,0xbc,0xcf,0x3c,0xad,0x69,0x5d,0x2c,0xb0,0x14,0xf7, - 0xb7,0xe5,0x48,0xb9,0x34,0xce,0x5b,0x94,0xe2,0x36,0xc4,0x22,0xa6,0x9e,0x39,0x97, - 0x5c,0x0d,0x5f,0x51,0x43,0x8f,0xab,0xe1,0x6b,0xf0,0x54,0xc3,0x37,0x60,0xa9,0x86, - 0x29,0x57,0x83,0xb8,0x49,0xb3,0x29,0x74,0x27,0x5d,0x0d,0xdf,0xa2,0x1d,0x5d,0x0d, - 0xdf,0x81,0xa7,0x1a,0xd6,0xc7,0x02,0x4b,0x71,0xaa,0x21,0xe5,0x9a,0x72,0x35,0x74, - 0xc7,0x22,0x66,0x82,0x39,0x93,0xae,0x86,0xef,0xa9,0x61,0xbb,0xab,0xe1,0x07,0xf0, - 0x54,0xc3,0x8f,0x60,0xa9,0x86,0x19,0x57,0x83,0xb8,0x69,0xb3,0x19,0x74,0xa7,0x39, - 0x47,0xd2,0xfd,0x09,0xed,0xee,0x78,0xe3,0xbc,0x6b,0x8d,0x29,0x76,0xc6,0xad,0x71, - 0x23,0x71,0x53,0xcc,0x9b,0x26,0xf6,0x10,0xb1,0x87,0x88,0xd5,0x5d,0xdb,0x1c,0x8b, - 0xfb,0xa6,0xf9,0x6f,0x9b,0x1d,0x86,0xcb,0xdf,0xbf,0x58,0x9c,0x45,0x71,0xef,0xc2, - 0xa9,0x56,0xbd,0x59,0x2f,0x53,0xeb,0x00,0xb5,0x2a,0xfe,0x15,0xf0,0x77,0xa8,0xf5, - 0x28,0x39,0x84,0x5f,0xb3,0x98,0x23,0xe4,0x48,0xf5,0x1e,0xc5,0x3f,0xc2,0xba,0x0e, - 0x93,0x4b,0x77,0xf7,0x35,0xee,0x6d,0xd2,0x7b,0x1d,0xbd,0x13,0x4e,0xef,0x0d,0xf0, - 0xb4,0xcf,0x6f,0x51,0x7b,0x70,0xd8,0x38,0x98,0xe0,0xc7,0x0c,0xd1,0x7d,0x3f,0x49, - 0xec,0x38,0x39,0x9e,0xa0,0x17,0xa7,0xd0,0x3d,0xc9,0xfb,0xa5,0xb5,0xef,0xb7,0x3c, - 0x4d,0xf4,0x46,0xbd,0x3a,0x15,0x0a,0x2c,0xa3,0x27,0x8a,0xe9,0xad,0xe9,0xaf,0xea, - 0x79,0x86,0xf7,0xe0,0x3d,0xe6,0xa9,0x0e,0xbd,0x25,0x1f,0x50,0xc7,0x69,0xea,0xd0, - 0xbb,0x72,0x06,0xfc,0x45,0x8b,0xd1,0x9c,0xb3,0xcc,0x3b,0x93,0xbf,0xfb,0x59,0x8e, - 0x7d,0xe8,0xde,0xba,0xb3,0xf9,0x9b,0x5d,0xfc,0xde,0x9e,0x83,0x4b,0x7d,0xfa,0x99, - 0xfc,0x3b,0x5c,0x9f,0x7e,0x01,0xff,0x94,0x75,0xff,0x0a,0xd6,0xeb,0xce,0xe5,0x6f, - 0xe0,0x9d,0x9c,0xcb,0x59,0xb7,0x4f,0xe2,0xae,0x98,0xcd,0x52,0xdf,0x95,0xfc,0x8c, - 0x97,0xf3,0xdf,0xa1,0x73,0xd4,0x9e,0xb8,0x59,0xa7,0xf3,0x3b,0x3a,0xbb,0x9d,0xce, - 0x1f,0xe0,0x49,0x67,0xce,0xe9,0x88,0xbb,0x6a,0x36,0x47,0xae,0xab,0xe8,0xf4,0x3b, - 0x9d,0xc4,0xcd,0x39,0x9d,0x3f,0xd1,0x19,0x70,0x3a,0xf3,0xe0,0x49,0x67,0xc1,0xe9, - 0xcc,0xe7,0xe7,0x31,0xe4,0x98,0x72,0x5d,0x43,0x67,0xd0,0xe9,0x24,0x6e,0xc1,0xe9, - 0xfc,0x8b,0x4e,0x8f,0xd3,0xf9,0x0f,0x3c,0xe9,0x2c,0x39,0x1d,0x71,0x8b,0x66,0x4b, - 0xe4,0x5a,0x44,0x67,0xc8,0xe9,0x24,0x6e,0xc9,0xe9,0x94,0x62,0xa1,0xb3,0xd7,0xe9, - 0x94,0x63,0x81,0x27,0x9d,0x2c,0xde,0xd0,0x11,0x57,0x67,0x26,0x4c,0xb9,0xf4,0x2d, - 0x9d,0x61,0xa7,0x93,0x38,0x8d,0x49,0x67,0x19,0x3a,0xfb,0x9c,0xce,0xf2,0x58,0xe0, - 0x49,0xa7,0xd9,0xe9,0x88,0xab,0x98,0x35,0x93,0xab,0x82,0xce,0x88,0xd3,0x49,0x5c, - 0xb3,0xd3,0x69,0x41,0xe7,0x80,0xd3,0x59,0x11,0x0b,0x3c,0xe9,0x54,0x9d,0x8e,0xb8, - 0x95,0x66,0x55,0x72,0xad,0x44,0x67,0xd4,0xe9,0x24,0xae,0xea,0x74,0x5a,0xd1,0x39, - 0xe8,0x74,0xda,0x62,0x81,0x27,0x9d,0x35,0x4e,0x47,0x5c,0xbb,0xd9,0x1a,0x72,0xb5, - 0xa3,0x33,0xe6,0x74,0x12,0xa7,0x71,0xd1,0x6e,0xdf,0xbd,0x66,0xff,0x03,0xae,0xea, - 0x9c,0x7a,0x38,0x0d,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0x4b,0x6c,0x95,0x55, + 0x14,0x85,0xcf,0xb9,0xf7,0xf6,0xb6,0xf4,0xb6,0x5a,0xf0,0x42,0xdb,0x50,0x68,0xa1, + 0x14,0x5f,0x84,0x90,0x80,0xc6,0xc4,0x48,0x74,0xa4,0x18,0x1a,0xb5,0x0c,0x98,0x34, + 0xb1,0x26,0x76,0xe0,0xa0,0x44,0xa2,0xe9,0x80,0x81,0x25,0x32,0xe9,0x80,0x98,0x74, + 0x62,0x80,0x01,0x0a,0x62,0x7c,0x94,0x10,0x35,0xa2,0x20,0x33,0x54,0xf0,0x41,0x34, + 0x55,0x1b,0x4d,0xd5,0xc6,0x26,0x0a,0xa4,0x89,0x92,0x26,0x16,0xeb,0xa3,0xa9,0x7b, + 0xfd,0xff,0x77,0x60,0xe7,0x36,0xd9,0x3d,0xff,0x5e,0x6b,0x9f,0xbd,0xce,0xde,0xe7, + 0x71,0x8b,0x85,0xee,0xfa,0x10,0x62,0x68,0x0c,0x0d,0xe1,0xf6,0x18,0xb2,0xbf,0xe5, + 0xa1,0x10,0xf4,0x59,0x09,0xe5,0x6c,0x7c,0x78,0xe7,0xae,0x9d,0x9b,0x9f,0x7b,0xfe, + 0xe9,0xcd,0xdb,0xee,0xd9,0x22,0xfe,0x96,0x50,0xcc,0xe2,0xc4,0xdd,0x6a,0x5e,0xc9, + 0x46,0xd9,0xd0,0x53,0xcf,0xec,0x11,0xde,0x6a,0xb6,0xcb,0xac,0xdf,0x6c,0x50,0xb8, + 0xd9,0xb0,0xd9,0x88,0xd9,0xa8,0xd9,0x98,0x59,0x8b,0xe5,0xd0,0x9c,0x7a,0xe5,0xb7, + 0xaf,0xd6,0x4c,0x4f,0xf9,0x42,0x78,0x24,0xd4,0x85,0x8e,0x7c,0x29,0xa1,0x9b,0x31, + 0x61,0x11,0xac,0xc1,0x61,0x05,0xb0,0x16,0x87,0x15,0xc1,0xda,0x1c,0x56,0x02,0xeb, + 0x70,0x58,0x1d,0x58,0x97,0xc3,0xca,0x60,0x1b,0x1c,0x56,0x0f,0x76,0x87,0xc3,0x1a, + 0xc0,0x36,0x39,0x6c,0x19,0xd8,0x16,0x87,0x35,0x82,0x6d,0xcb,0x6a,0x2d,0xde,0x58, + 0xb3,0xea,0x56,0x9f,0xd6,0x52,0xa3,0xfc,0x7e,0xfc,0x88,0x3f,0x88,0x9f,0xe2,0x87, + 0xf0,0x8b,0xf8,0xc3,0xf8,0x25,0xfc,0x11,0xfc,0x3a,0xfc,0x51,0xfc,0x32,0xfe,0x18, + 0x7e,0xea,0xfb,0x09,0x1b,0xd7,0x3b,0x7d,0xf9,0xeb,0xf0,0x6f,0x33,0xd5,0x42,0xe6, + 0x17,0x33,0x3d,0x7d,0xaf,0xb4,0x98,0x32,0xfd,0x8a,0xd9,0x5e,0x97,0xb2,0x5c,0x65, + 0xc7,0x57,0xe0,0x03,0x7c,0x13,0x7b,0xab,0x35,0xae,0xb2,0x4c,0x55,0x78,0x71,0x2b, + 0x6d,0xac,0xc2,0x75,0xd9,0xff,0x55,0xe4,0x15,0x7e,0x3f,0x7e,0xab,0xd3,0x6a,0x23, + 0xbe,0x90,0xd5,0xd1,0x7c,0x63,0x6f,0xda,0xb0,0xb2,0xb3,0x2a,0x63,0xc5,0x99,0x34, + 0xd6,0xb0,0x4f,0x1d,0x68,0xac,0xa1,0x27,0xc2,0xee,0xa6,0xbe,0x4e,0xd6,0xaf,0xf8, + 0x2e,0xb8,0x7a,0xc7,0xf7,0xb0,0xff,0xe2,0x37,0xc2,0x57,0x32,0xcd,0x42,0xb8,0x93, + 0x38,0xf9,0x77,0x91,0x27,0xcd,0xdb,0x5a,0xa3,0xb3,0x9d,0xf3,0x91,0xfc,0x1d,0xe8, + 0x28,0xef,0xa3,0xc4,0x96,0x1d,0xdf,0x4b,0x2f,0xc4,0xf7,0x71,0x0e,0x9a,0xa8,0xa3, + 0x8f,0x7b,0x57,0x74,0xf1,0xbb,0xe9,0x55,0xe2,0xfb,0x6b,0xf8,0x01,0x7a,0x9f,0xf8, + 0x41,0xf8,0xe4,0x0f,0xd5,0xc4,0xef,0xe5,0x9e,0x25,0x7e,0xb8,0x86,0xdf,0xc7,0xde, + 0x26,0x7e,0xa4,0x86,0x3f,0x60,0xf6,0xa0,0xe3,0x47,0x6b,0xf8,0x83,0x66,0xfb,0x1d, + 0x3f,0x06,0xbf,0xc9,0xba,0xa2,0x3a,0x5f,0xa6,0xa7,0xde,0xd2,0xdc,0xa3,0x9c,0xfb, + 0x76,0xeb,0xda,0x71,0xf6,0x83,0x27,0x2d,0x1b,0xa3,0xf3,0xd5,0xbf,0xd7,0xf8,0x3e, + 0x8e,0x9e,0xfc,0x13,0xee,0xdc,0xbe,0x45,0xef,0xfd,0xfa,0x4e,0x83,0x69,0xfe,0x07, + 0xec,0x8f,0xce,0xd9,0xbd,0xa6,0x5c,0xa0,0x97,0x81,0x39,0x0b,0x86,0x68,0x3d,0x0f, + 0x70,0xce,0xcf,0x73,0x96,0x1f,0xb3,0x5a,0x74,0x56,0x3f,0x06,0x3b,0xef,0xd6,0xb8, + 0x87,0xfb,0xf4,0x09,0xfc,0x43,0x96,0x41,0xfd,0xfc,0x94,0x33,0xda,0x49,0x3e,0xc5, + 0x5c,0x00,0x7f,0xd1,0x62,0xe4,0x7f,0xc6,0xbc,0x0b,0xcc,0xd3,0xb9,0xfc,0x9c,0x79, + 0x3d,0xcc,0x53,0x4f,0xbe,0x00,0x1f,0xb7,0x18,0x9d,0xd5,0x2f,0xc1,0xd4,0xcb,0xbf, + 0x6c,0xe5,0x13,0xac,0xe7,0x1f,0x8b,0x17,0x77,0xc9,0x6c,0x82,0x7a,0xf4,0xfd,0x84, + 0xcd,0x53,0x0f,0xbe,0x42,0x53,0x7f,0x2f,0xd0,0x9f,0xaf,0xc1,0xfb,0xcc,0xd3,0x9a, + 0xd6,0xc6,0x1c,0x4b,0x71,0x7f,0x5b,0x8e,0x94,0x4b,0xe3,0xbc,0x45,0x29,0x6e,0x7d, + 0xcc,0x63,0xea,0x98,0x73,0xc9,0xd5,0xf0,0x0d,0x35,0x6c,0x75,0x35,0x7c,0x0b,0x9e, + 0x6a,0xf8,0x0e,0x2c,0xd5,0x30,0xe5,0x6a,0x10,0x37,0x69,0x36,0x85,0xee,0xa4,0xab, + 0xe1,0x7b,0xb4,0xa3,0xab,0xe1,0x07,0xf0,0x54,0xc3,0xba,0x98,0x63,0x29,0x4e,0x35, + 0xa4,0x5c,0x53,0xae,0x86,0xee,0x98,0xc7,0x4c,0x30,0x67,0xd2,0xd5,0xf0,0x23,0x35, + 0x6c,0x77,0x35,0xfc,0x04,0x9e,0x6a,0xf8,0x19,0x2c,0xd5,0x30,0xe3,0x6a,0x10,0x37, + 0x6d,0x36,0x83,0xee,0x34,0xe7,0x48,0xba,0xbf,0xa0,0xdd,0x1d,0x6f,0x9e,0x6f,0xad, + 0x31,0xc5,0xce,0xb8,0x35,0x6e,0x20,0x6e,0x8a,0x79,0xd3,0xc4,0x1e,0x22,0xf6,0x10, + 0xb1,0xba,0x6b,0x1b,0x63,0x7e,0xdf,0x34,0xff,0x1d,0xb3,0xc3,0x70,0xd9,0xfb,0x17, + 0xf3,0xb3,0x28,0xee,0x3d,0x38,0xd5,0xaa,0x37,0xeb,0x15,0x6a,0x3d,0x4a,0xad,0x8a, + 0x7f,0x15,0xfc,0x5d,0x6a,0x3d,0x46,0x0e,0xe1,0xd7,0x2d,0xe6,0x08,0x39,0x52,0xbd, + 0xc7,0xf0,0x8f,0xb0,0xae,0xc3,0xe4,0xd2,0x5d,0x7d,0x9d,0x7b,0x9a,0xf4,0xde,0x40, + 0x6f,0xc0,0xe9,0xbd,0x09,0x9e,0xf6,0xf9,0x6d,0x6a,0x0f,0x0e,0x1b,0x07,0x13,0xfc, + 0xb8,0x21,0xba,0xef,0x27,0x89,0x1d,0x27,0xc7,0x93,0xf4,0xe2,0x14,0xba,0x27,0x79, + 0xbf,0xb4,0xf6,0xfd,0x96,0xa7,0x89,0xde,0xa8,0x57,0xa7,0x42,0x8e,0x95,0xe9,0x89, + 0x62,0x7a,0x6b,0xfa,0xab,0x7a,0x9e,0xe5,0x3d,0x78,0x9f,0x79,0xaa,0x43,0x6f,0xc9, + 0x87,0xd4,0x71,0x9a,0x3a,0xf4,0xae,0x9c,0x01,0x7f,0xc9,0x62,0x34,0xe7,0x2c,0xf3, + 0xce,0x64,0xef,0x7e,0x39,0xc3,0x3e,0x72,0x6f,0xdb,0xd9,0xec,0xcd,0xce,0x7f,0x73, + 0xcf,0xc1,0xa5,0x3e,0xfd,0x4a,0xfe,0x1d,0xae,0x4f,0xbf,0x81,0x5f,0x64,0xdd,0x97, + 0xc1,0x7a,0xdd,0xb9,0xbc,0x02,0xde,0xc9,0xb9,0x9c,0x75,0xfb,0x24,0xee,0xaa,0xd9, + 0x2c,0xf5,0x5d,0xcd,0xce,0x78,0x31,0xfb,0x1d,0x3a,0x47,0xed,0x89,0x9b,0x75,0x3a, + 0xbf,0xa3,0xb3,0xdb,0xe9,0xfc,0x01,0x9e,0x74,0xe6,0x9c,0x8e,0xb8,0x6b,0x66,0x73, + 0xe4,0xba,0x86,0x4e,0xbf,0xd3,0x49,0xdc,0x9c,0xd3,0xf9,0x13,0x9d,0x01,0xa7,0x33, + 0x0f,0x9e,0x74,0x16,0x9c,0xce,0x7c,0x76,0x1e,0x43,0x86,0x29,0xd7,0x75,0x74,0x06, + 0x9d,0x4e,0xe2,0x16,0x9c,0xce,0xbf,0xe8,0xf4,0x38,0x9d,0xff,0xc0,0x93,0xce,0x92, + 0xd3,0x11,0xb7,0x68,0xb6,0x44,0xae,0x45,0x74,0x86,0x9c,0x4e,0xe2,0x96,0x9c,0x4e, + 0x21,0xe6,0x3a,0x7b,0x9d,0x4e,0x31,0xe6,0x78,0xd2,0x29,0xc7,0x9b,0x3a,0xe2,0x4a, + 0x66,0xc2,0x94,0x4b,0xdf,0xd2,0x19,0x76,0x3a,0x89,0xd3,0x98,0x74,0x96,0xa1,0xb3, + 0xcf,0xe9,0x34,0xc6,0x1c,0x4f,0x3a,0xcd,0x4e,0x47,0x5c,0xc5,0xac,0x99,0x5c,0x15, + 0x74,0x46,0x9c,0x4e,0xe2,0x9a,0x9d,0x4e,0x0b,0x3a,0x07,0x9c,0xce,0xf2,0x98,0xe3, + 0x49,0xa7,0xea,0x74,0xc4,0xad,0x30,0xab,0x92,0x6b,0x05,0x3a,0xa3,0x4e,0x27,0x71, + 0x55,0xa7,0xd3,0x8a,0xce,0x41,0xa7,0xd3,0x16,0x73,0x3c,0xe9,0xac,0x76,0x3a,0xe2, + 0xda,0xcd,0x56,0x93,0xab,0x1d,0x9d,0x31,0xa7,0x93,0x38,0x8d,0x8b,0x76,0xfb,0xee, + 0x33,0xfb,0x1f,0xb0,0xa7,0xb8,0xae,0x50,0x0d,0x00,0x00 }; // Generated from: @@ -112,6 +112,7 @@ constexpr uint8_t kBlitResolve_frag_0000000B[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000C.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000C.inc index 2d8200a5c8b..9ed24ffff93 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000C.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000C.inc @@ -10,49 +10,51 @@ #pragma once constexpr uint8_t kBlitResolve_frag_0000000C[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0x6b,0x4b,0x54,0x51, - 0x14,0x86,0xd7,0x9c,0x33,0xce,0x8c,0xdd,0x34,0xca,0x19,0x1b,0x23,0x4c,0x33,0xba, - 0x21,0x82,0x15,0x41,0x24,0xf4,0xa9,0xc0,0x99,0x6c,0x1c,0x2d,0xcb,0xfa,0x20,0x59, - 0x62,0xa2,0x35,0x28,0x56,0x52,0x4c,0x39,0xe8,0x87,0xa0,0xac,0xdf,0xd1,0xef,0x8b, - 0x2e,0x10,0xb4,0xd6,0x3e,0xcf,0x8e,0x95,0x07,0xb6,0x7b,0xd6,0xb3,0xd7,0xed,0x3d, - 0x6b,0x1f,0xd3,0x64,0xb8,0x28,0x92,0x93,0x03,0x52,0x92,0xaf,0x92,0x3d,0x47,0x25, - 0x51,0x22,0x72,0x50,0x0a,0x61,0xbf,0x55,0x6b,0xd6,0x46,0xd7,0x37,0x16,0x47,0x2f, - 0x5f,0x19,0xb3,0xf3,0x23,0x92,0x06,0x3f,0x3b,0xeb,0x91,0xa2,0xe4,0x75,0xb7,0xb5, - 0xba,0xb0,0xbc,0x26,0x81,0x89,0xd4,0x74,0xf5,0xaa,0x9f,0xf1,0xa2,0xfb,0x7d,0xc8, - 0xf2,0xe9,0xaf,0x9e,0x90,0x3f,0xf3,0xbd,0x2d,0x5d,0x52,0xa1,0xf6,0x30,0x7b,0x64, - 0x39,0x58,0xc9,0xb1,0x04,0xd6,0xeb,0x58,0x0a,0xeb,0x77,0x2c,0x0f,0x3b,0xe9,0x58, - 0x17,0x6c,0xd0,0xb1,0x02,0xec,0x8c,0x63,0x45,0xd8,0x39,0xc7,0x4a,0xb0,0x4b,0x8e, - 0x75,0xc3,0xc6,0x82,0xae,0xf4,0x5f,0x7f,0xa6,0xb1,0x86,0xc6,0x32,0xf6,0x94,0xee, - 0x43,0xe8,0x8b,0xf6,0x69,0x67,0x37,0xf7,0x9d,0x37,0x39,0xb7,0x7c,0xc7,0xf4,0x6f, - 0x12,0xec,0x34,0x68,0x4d,0x42,0xde,0x34,0xf4,0x6e,0x5a,0x2a,0xea,0x5f,0x44,0x4b, - 0x82,0x7d,0x18,0x3b,0x1f,0x7c,0xf2,0x3a,0xb7,0xec,0x7d,0x1a,0xbf,0x8e,0xdd,0x03, - 0xeb,0x53,0xbb,0x8f,0x5c,0xd1,0x2e,0x63,0xdb,0x73,0x4a,0x27,0x17,0xdf,0x4b,0x5c, - 0x7d,0xac,0x02,0x7b,0xd9,0x2d,0xab,0xd7,0xcf,0xfb,0xa9,0x50,0xcf,0xec,0x13,0xb0, - 0x8b,0xd4,0xab,0x52,0xcf,0xfc,0x07,0x38,0x2b,0xba,0xf3,0x58,0x3f,0xda,0x23,0x9c, - 0x9b,0xff,0x59,0xfc,0xad,0xde,0x71,0x55,0x7d,0x1e,0x3f,0xb3,0x2f,0xec,0x8b,0x1b, - 0x67,0x7e,0xd1,0x9e,0x20,0xd6,0xf2,0x4c,0x72,0x7f,0x0a,0xf4,0x39,0xc9,0xfd,0x4d, - 0x43,0xbf,0xdd,0x52,0xe7,0x2c,0x27,0xff,0x3f,0xd1,0xb6,0x1c,0x77,0xf8,0x5d,0x27, - 0x87,0xd9,0x53,0xb0,0xaa,0xf6,0xd6,0xc0,0x6f,0x1a,0xd6,0xc0,0xcf,0xec,0x26,0x6c, - 0x40,0x2b,0xce,0x92,0x23,0xf6,0x39,0xc7,0x3c,0xaf,0xea,0x7d,0x4b,0x98,0xa5,0xd0, - 0xdb,0x4f,0x25,0x76,0x9f,0x6f,0x30,0xeb,0x05,0xe6,0xd9,0x50,0x6a,0xfd,0x3e,0x81, - 0x89,0x63,0x8b,0x30,0xeb,0xfd,0xae,0x32,0x7b,0x97,0x4f,0xf1,0xb5,0xb3,0x9b,0xca, - 0x6c,0x0e,0xcf,0x98,0x55,0x95,0xfc,0xe6,0xb7,0x04,0xdf,0x21,0x6e,0x99,0xd8,0x25, - 0x17,0xf7,0x9c,0xb8,0x41,0x17,0xb7,0x02,0xef,0x10,0xb7,0x4a,0xec,0x0a,0x71,0x36, - 0xc7,0x35,0xe2,0x46,0x88,0xb3,0x19,0xbe,0x80,0x7f,0x53,0x1f,0x9b,0xed,0x4b,0x98, - 0xcd,0xf6,0x87,0xbe,0x81,0x4d,0xb4,0xfd,0x56,0x7f,0x3b,0x6b,0xe9,0xda,0xe4,0xbd, - 0xb4,0x9c,0xe6,0x75,0x6a,0xda,0xd3,0x56,0x5f,0x63,0x1b,0xf0,0x69,0xb5,0xac,0xa7, - 0x8f,0xb0,0xe8,0xf7,0x4b,0x73,0xc4,0x5c,0xb6,0x7f,0x57,0x2f,0xf3,0xfb,0x8c,0x4f, - 0x17,0x31,0x2d,0xa7,0xe1,0x15,0x1a,0xc6,0x9d,0x86,0xd7,0xf0,0xa8,0xe1,0x0d,0x2c, - 0x6a,0x68,0x3b,0x0d,0x76,0xb6,0x15,0x7a,0xcc,0xea,0x6e,0x39,0x0d,0x6f,0xa9,0x9d, - 0x73,0x1a,0xde,0xc1,0xa3,0x86,0x4f,0xb0,0xe8,0x67,0x1a,0x62,0xae,0xb6,0xd3,0xb0, - 0x87,0xcf,0x26,0x31,0x5b,0x4e,0xc3,0x7b,0x34,0x4c,0x38,0x0d,0x1f,0xe0,0x51,0xc3, - 0x36,0x2c,0x6a,0xd8,0x75,0x1a,0xb6,0xc3,0x9c,0x25,0x30,0xab,0xdb,0x09,0xdf,0x41, - 0x56,0x77,0x87,0xda,0x7b,0xee,0xdb,0xb1,0x1e,0xa3,0xef,0xae,0xeb,0xf1,0x0b,0x7e, - 0x6d,0xe2,0x3a,0xf4,0x53,0x0f,0xf7,0x36,0xfb,0xb6,0xcc,0xb6,0xef,0x68,0x86,0x6f, - 0xe8,0x9e,0xf6,0x37,0x1b,0xf6,0xcc,0x67,0xc6,0xdd,0xcb,0x07,0xe8,0x9a,0x73,0xf7, - 0xf2,0x21,0x3c,0xde,0xe7,0x79,0xea,0x1a,0xbf,0xaf,0xcc,0xbe,0xa9,0x47,0xe4,0x9b, - 0x77,0xb3,0x78,0x0c,0x97,0xf0,0x9e,0xd2,0xf0,0xbf,0xc2,0xd8,0x1f,0x55,0x75,0x4d, - 0xd7,0x5f,0x4f,0xda,0x98,0xde,0x54,0x07,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0xfd,0x4b,0x93,0x51, + 0x14,0xc7,0xef,0x9e,0x67,0xdb,0x33,0xed,0x65,0x46,0x6d,0xb3,0x19,0x61,0x99,0xd1, + 0x1b,0x22,0x68,0x11,0x44,0x42,0x3f,0x15,0x38,0x33,0x9d,0xc6,0x52,0x2b,0x8d,0x88, + 0x2c,0x53,0x49,0x93,0xc2,0x72,0x54,0xb3,0xa4,0xfd,0x10,0x94,0xf5,0x4f,0xf4,0xf7, + 0x45,0x2f,0x10,0x74,0xce,0xdd,0xe7,0xc6,0x69,0x0f,0x5c,0xef,0xce,0xe7,0x9e,0x97, + 0xfb,0xbd,0xe7,0x5e,0xe3,0xa8,0x2f,0x71,0x2e,0xe5,0x3a,0x5d,0xce,0x7d,0x75,0xad, + 0xef,0x80,0x8b,0x84,0x38,0xb7,0xc7,0x65,0xfd,0x7c,0xb5,0x52,0xad,0x0c,0xac,0xad, + 0xdf,0x1f,0x18,0x3e,0x3f,0xa8,0xeb,0xfb,0x5d,0xec,0xfd,0x74,0x2d,0xef,0x12,0x97, + 0x96,0x59,0xc7,0x93,0x85,0xc5,0x65,0xe7,0x99,0x73,0x15,0x19,0x5d,0xe2,0xa7,0x3c, + 0x31,0xbf,0xf7,0x6a,0x3e,0xf9,0x95,0xf7,0xf9,0x5b,0xbe,0xd7,0x5c,0xc6,0x95,0xa8, + 0xdd,0xc7,0x1c,0x58,0x0a,0x96,0x33,0x2c,0x82,0x75,0x19,0x16,0xc3,0xba,0x0d,0x4b, + 0xc3,0x8e,0x18,0x96,0x81,0xf5,0x1a,0x96,0x85,0x9d,0x30,0x2c,0x81,0x9d,0x32,0x2c, + 0x07,0x3b,0x67,0x58,0x07,0x6c,0xd0,0xb0,0x4e,0xd8,0xb0,0xd7,0x1a,0xff,0xdb,0xb3, + 0xea,0xae,0xa0,0xbb,0x88,0x3d,0x2e,0xf3,0x71,0x34,0x07,0xfb,0x98,0xb1,0xab,0x6d, + 0xeb,0x55,0xd6,0x35,0xdf,0x41,0xf9,0x1b,0x79,0x3b,0xf6,0xfa,0x23,0x9f,0x37,0xf6, + 0x7a,0x54,0x5f,0x49,0xfc,0x13,0xf4,0x45,0xd8,0xfb,0xb0,0xd3,0xde,0x27,0x2d,0xbd, + 0x6c,0x9d,0xb1,0xf2,0x4b,0xd8,0x79,0x58,0x41,0xec,0x02,0xb9,0x82,0x5d,0xc4,0xd6, + 0xef,0xa8,0x44,0x85,0xb3,0x0a,0xa3,0x60,0x46,0x96,0xb9,0x68,0x86,0xd6,0xec,0xe6, + 0xdc,0x4a,0xd4,0x54,0xfb,0x30,0xec,0x2c,0x35,0xcb,0xd4,0x54,0xff,0x1e,0xd6,0x12, + 0xb3,0x1e,0xf6,0x10,0xec,0x7e,0xfa,0xa3,0xfe,0x27,0xf1,0xd7,0x7a,0x87,0x44,0xf9, + 0x69,0xfc,0xd4,0x3e,0xd3,0x16,0x37,0xd4,0x56,0x77,0x84,0xfe,0x69,0x9e,0x51,0xee, + 0x55,0x96,0x7d,0x8e,0x72,0xaf,0x63,0xbf,0xdf,0x0e,0x37,0xc6,0x5a,0xca,0xfd,0xff, + 0x05,0x5b,0x73,0x5c,0xe7,0xf7,0x18,0x39,0xd4,0x1e,0x87,0x95,0x65,0x6f,0x13,0xf8, + 0x4d,0xc2,0x26,0xf0,0x53,0xbb,0x0a,0xeb,0x91,0x8a,0xd3,0xe4,0x08,0xfb,0xac,0xd1, + 0xd3,0x60,0xcf,0xb1,0x2f,0xcd,0x75,0x1b,0x4d,0xca,0x2f,0xc8,0x9d,0x8c,0xe8,0xb7, + 0xc3,0xe7,0xa7,0x10,0x7d,0x07,0x97,0xb9,0x0f,0x0f,0xe8,0xf9,0x84,0x50,0xd5,0xf3, + 0x10,0xe6,0x0c,0x5b,0x84,0xa9,0xb6,0x1b,0xc2,0xb4,0x17,0x8f,0xf0,0xd5,0xb5,0x2b, + 0xc2,0xb4,0x4f,0x8f,0xe9,0x65,0x99,0xfc,0xea,0xb7,0x04,0xdf,0x26,0x6e,0x99,0xd8, + 0x25,0x13,0xb7,0x42,0x5c,0xaf,0x89,0x5b,0x85,0xbf,0x25,0xee,0x29,0xb1,0xab,0xc4, + 0x69,0x9f,0xd7,0x88,0xeb,0x27,0x4e,0x7b,0xbc,0x0e,0xff,0x26,0x3e,0xda,0xfb,0x67, + 0x30,0xed,0xfd,0x0f,0x39,0x81,0x4d,0xb4,0xfd,0x16,0x7f,0x5d,0xdb,0x90,0xb1,0xc9, + 0xb9,0x6c,0x18,0xcd,0xcf,0xa9,0xa9,0x5f,0x5d,0x7c,0x95,0xbd,0x80,0x4f,0x8a,0xa5, + 0x7b,0xfa,0x08,0x0b,0x7e,0xbf,0x24,0x47,0xc8,0xa5,0xf3,0x77,0xf1,0x52,0xbf,0xcf, + 0xf8,0x64,0x88,0xd9,0x30,0x1a,0x5e,0xa2,0x61,0xc8,0x68,0x78,0x05,0x0f,0x1a,0xb6, + 0x60,0x41,0x43,0xc3,0x68,0xd8,0xf2,0xfb,0x73,0x9e,0x69,0xdd,0xba,0xd1,0xf0,0x9a, + 0xda,0x29,0xa3,0xe1,0x0d,0x3c,0x68,0xf8,0x04,0x0b,0x7e,0xaa,0x21,0xe4,0x6a,0x18, + 0x0d,0xbb,0xf8,0x6c,0x12,0x53,0x37,0x1a,0xb6,0xd1,0x30,0x62,0x34,0xbc,0x83,0x07, + 0x0d,0xef,0x61,0x41,0x43,0xd3,0x68,0xd0,0xb5,0x1d,0x19,0x4d,0xea,0xee,0xf8,0x77, + 0xd2,0xaa,0xfb,0x81,0xda,0xbb,0xe6,0x6d,0xe9,0x1e,0x83,0x6f,0xd3,0xec,0xf1,0x0b, + 0x7e,0x0d,0xe2,0x76,0xd8,0xcf,0x98,0xbf,0xb7,0xad,0xb7,0xa7,0xb6,0xbe,0xb3,0x29, + 0xde,0xd8,0x4d,0xd9,0xdf,0xb4,0x9f,0x5b,0x3e,0x53,0xe6,0x5e,0xde,0x42,0x57,0xcd, + 0xdc,0xcb,0x19,0x78,0xb8,0xcf,0xb3,0xd4,0x9d,0x21,0x4e,0xdf,0xdf,0x1d,0xe2,0xe6, + 0x88,0xd3,0xb7,0x78,0x17,0xbe,0x42,0x1f,0xe6,0x61,0x35,0xc9,0xa2,0xef,0x70,0x81, + 0x3d,0xcc,0xf2,0xb6,0xe7,0x4d,0x1f,0xef,0xb1,0xee,0xfc,0x19,0xc7,0xfe,0xff,0x90, + 0xb2,0x3f,0x72,0x22,0x17,0x65,0xfc,0x05,0xa3,0xd4,0x0a,0x18,0xc8,0x07,0x00,0x00 }; // Generated from: @@ -72,6 +74,7 @@ constexpr uint8_t kBlitResolve_frag_0000000C[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -108,6 +111,6 @@ constexpr uint8_t kBlitResolve_frag_0000000C[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// gl_FragDepth = texture(sampler2D(depth, blitSampler), srcImageCoords * params . invSrcExtent). x; +// gl_FragDepth = textureLod(sampler2D(depth, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip). x; // // } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000D.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000D.inc index 8326bd6b8e7..9f319be86ec 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000D.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000D.inc @@ -11,51 +11,53 @@ #pragma once constexpr uint8_t kBlitResolve_frag_0000000D[] = { 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0xfb,0x4b,0x54,0x41, - 0x14,0xc7,0x67,0xef,0xdd,0xdd,0xbb,0xf6,0xd2,0xa8,0x55,0xd3,0x08,0xd3,0x8c,0x5e, - 0x88,0x60,0x45,0x10,0x09,0xfd,0x54,0xe0,0x9a,0xad,0xab,0x65,0x66,0x0f,0x73,0x0b, - 0x8a,0x7c,0x90,0xd2,0x43,0x8a,0x2d,0x17,0xc3,0x6a,0x69,0x7f,0x08,0xca,0xfa,0x17, - 0xfa,0xfb,0xa2,0x07,0x04,0x9d,0x33,0xf7,0x33,0x71,0xd8,0x85,0x71,0xee,0xf9,0xcc, - 0x79,0xcc,0x77,0xce,0x8c,0x71,0x34,0x90,0x38,0x97,0x71,0x3b,0x5c,0xc1,0x7d,0x73, - 0xe9,0x6f,0xaf,0x8b,0x84,0x38,0xb7,0xd3,0xe5,0xfd,0x7c,0xa9,0x54,0x29,0x0d,0xad, - 0xae,0x55,0x87,0x4e,0x9f,0x19,0xd6,0xf5,0x3d,0x2e,0xf6,0x7e,0xba,0xd6,0xee,0x12, - 0x97,0x95,0x59,0xc7,0xe2,0xfc,0xc3,0x25,0xe7,0x99,0x73,0x25,0x19,0x1d,0xe2,0xa7, - 0x3c,0x31,0xdf,0xbb,0x34,0x9f,0x7c,0xb5,0xfb,0xfc,0xa9,0xef,0x65,0x97,0x73,0x5d, - 0xd4,0x1e,0x60,0x0e,0x2c,0x03,0x2b,0x18,0x16,0xc1,0x3a,0x0c,0x8b,0x61,0xdd,0x86, - 0x65,0x61,0x07,0x0d,0xcb,0xc1,0xfa,0x0c,0xcb,0xc3,0x8e,0x18,0x96,0xc0,0x8e,0x19, - 0x56,0x80,0x9d,0x32,0xac,0x0d,0x36,0xec,0x75,0xc5,0xff,0xf7,0xa7,0x1a,0x4b,0x68, - 0xec,0xc4,0x9e,0x90,0xb9,0x1f,0x7d,0xc1,0x3e,0x6c,0xec,0x4a,0xcb,0x7a,0x85,0x75, - 0xcd,0xb7,0x4f,0xfe,0x46,0xde,0x8e,0xbd,0xd6,0xc8,0xe7,0x8d,0xfd,0xde,0x55,0x4b, - 0x97,0xf8,0x27,0x68,0x89,0xb0,0x77,0x63,0x67,0xbd,0x4f,0x56,0xfa,0x96,0x9e,0xa7, - 0xf2,0xf3,0xd8,0xed,0xb0,0xa2,0xd8,0x45,0x72,0x05,0xbb,0x13,0x5b,0x7f,0x87,0xa4, - 0x73,0xe1,0x5c,0xc2,0x28,0x32,0xf2,0xcc,0x9d,0x66,0x68,0xbd,0x6e,0xce,0xa7,0x8b, - 0x7a,0x6a,0x1f,0x80,0x9d,0xa4,0x5e,0x0f,0xf5,0xd4,0xbf,0x97,0xb5,0xc4,0xac,0x87, - 0xfa,0xc1,0x1e,0x64,0x5d,0xfd,0x8f,0xe2,0xaf,0xf5,0xf6,0x8b,0xea,0xe3,0xf8,0xa9, - 0x7d,0xa2,0x25,0x6e,0x84,0xfe,0x05,0x7b,0x94,0x58,0xcd,0x33,0xc6,0xfd,0xc9,0xb3, - 0xcf,0x31,0xee,0x6f,0xec,0xf7,0xdb,0xe6,0xc6,0x59,0xcb,0x90,0xb3,0x75,0xd6,0x1c, - 0x57,0xf8,0x1e,0x27,0x87,0xda,0x13,0xb0,0x1e,0xd9,0x5b,0x19,0xbf,0x49,0x58,0x19, - 0x3f,0xb5,0x2b,0xb0,0x5e,0xa9,0x38,0x4d,0x8e,0xb0,0xcf,0x19,0xfa,0x19,0xec,0x39, - 0xf6,0xa5,0xb9,0x6e,0xa1,0xa1,0x48,0xbf,0xe7,0xd9,0xa7,0xae,0x9f,0x95,0xfb,0x19, - 0xd1,0x7b,0x07,0xfb,0x25,0x44,0xef,0xff,0x05,0xee,0xc6,0x23,0xfa,0x5f,0x16,0xaa, - 0x71,0x8f,0x61,0xce,0xb0,0x45,0x98,0x6a,0xbd,0x2a,0x4c,0xcf,0x7e,0x09,0x5f,0x5d, - 0xbb,0x28,0x4c,0xfb,0xb6,0x4c,0x6f,0x7b,0xc8,0xaf,0x7e,0x2b,0xf0,0x4d,0xe2,0x9e, - 0x10,0xbb,0x62,0xe2,0x56,0x89,0xeb,0x33,0x71,0x6b,0xf0,0x3a,0x71,0x4f,0x89,0x5d, - 0x23,0x4e,0xfb,0xfe,0x8c,0xb8,0x41,0xe2,0xb4,0xe7,0xcf,0xe1,0xdf,0xc5,0x47,0xef, - 0xc2,0x0b,0x98,0xde,0x85,0x9f,0x72,0x02,0x35,0xb4,0xfd,0x11,0x7f,0x5d,0x5b,0x97, - 0x51,0xe3,0x5c,0xd6,0x8d,0xe6,0x97,0xd4,0x74,0x7e,0x3d,0xeb,0xd9,0x2b,0xf8,0xa4, - 0x58,0xba,0xa7,0x4f,0xb0,0xe0,0xf7,0x5b,0x72,0x84,0x5c,0x3a,0xff,0x10,0x2f,0xf5, - 0xfb,0x82,0x4f,0x8e,0x98,0x75,0xa3,0xe1,0x35,0x1a,0x46,0x8c,0x86,0x37,0xf0,0xa0, - 0x61,0x03,0x16,0x34,0x6c,0x19,0x0d,0x1b,0xfe,0x8c,0x9c,0x67,0x5a,0xb7,0x6e,0x34, - 0x6c,0x52,0x3b,0x63,0x34,0xbc,0x85,0x07,0x0d,0x9f,0x61,0xc1,0x4f,0x35,0x84,0x5c, - 0x5b,0x46,0xc3,0x36,0x3e,0x35,0x62,0xea,0x46,0xc3,0x3b,0x34,0x8c,0x1a,0x0d,0xef, - 0xe1,0x41,0xc3,0x07,0x58,0xd0,0xd0,0x34,0x1a,0x74,0xad,0x21,0xa3,0x49,0xdd,0x86, - 0x7f,0x37,0x69,0xdd,0x8f,0xd4,0xde,0x36,0x6f,0x4d,0xf7,0x18,0x7c,0x9b,0x66,0x8f, - 0x5f,0xf1,0xdb,0x22,0xae,0xc1,0x7e,0xc6,0xfd,0xbd,0x4d,0xdf,0xa2,0xda,0xfa,0xee, - 0xa6,0x78,0x73,0xd7,0x64,0x7f,0xd3,0x7e,0x4e,0x7d,0xa6,0xcc,0xbd,0xbc,0x81,0xae, - 0x19,0x73,0x2f,0x67,0xe1,0xe1,0x3e,0xdf,0xa4,0xee,0x2c,0x71,0xfa,0x1e,0x6f,0x13, - 0x37,0x47,0x9c,0xbe,0xcd,0x3b,0xf0,0x65,0xfa,0x70,0x17,0x16,0x7a,0x75,0x8f,0x5c, - 0xf6,0xdd,0x2d,0xc0,0xd2,0x77,0x97,0xf7,0x6f,0xbb,0x8a,0xef,0x02,0x39,0xae,0x8b, - 0xaf,0xbe,0xe3,0xfb,0x68,0xa8,0x9a,0xf8,0x07,0x70,0xe7,0x7b,0x13,0xfb,0xff,0x67, - 0xca,0xfe,0x4a,0xc6,0x73,0x32,0xfe,0x01,0xec,0x21,0xc7,0xe5,0xf8,0x07,0x00,0x00 + 0x14,0xc7,0x67,0xef,0xdd,0x97,0xf6,0x58,0xa3,0x76,0x35,0x8d,0xb0,0xcc,0xe8,0x85, + 0x08,0x5a,0x04,0x91,0xd0,0x4f,0x05,0xae,0x99,0xae,0x86,0x99,0x3d,0xcc,0xb5,0x34, + 0xc8,0x1e,0x4a,0x49,0x0f,0x2b,0xcc,0xa4,0xd8,0x4a,0xda,0x1f,0x82,0xb2,0xfe,0x81, + 0xfe,0xbe,0xe8,0x01,0x41,0xe7,0xcc,0xfd,0x4c,0x1c,0xf6,0xc2,0xec,0xdc,0xf3,0x99, + 0xf3,0xfa,0xde,0x99,0xd9,0x38,0xea,0xca,0x39,0x97,0x72,0xcd,0x2e,0xef,0xbe,0xb9, + 0xe4,0xd9,0xe1,0x22,0x21,0xce,0x6d,0x71,0x59,0x3f,0x9f,0x2d,0x57,0xca,0x3d,0x8b, + 0x4b,0xd5,0x9e,0xfe,0xe3,0xbd,0xba,0xbe,0xdd,0xc5,0xde,0x4f,0xd7,0x0a,0x2e,0xe7, + 0xd2,0x32,0xeb,0xb8,0x33,0x3d,0xbf,0xe0,0x3c,0x73,0xae,0x2c,0xa3,0x45,0xfc,0x94, + 0xe7,0xcc,0xfb,0x56,0xcd,0x27,0x6f,0x05,0x9f,0x3f,0xf1,0x3d,0xe7,0x32,0xae,0x95, + 0xda,0x5d,0xcc,0x81,0xa5,0x60,0x79,0xc3,0x22,0x58,0x8b,0x61,0x31,0xac,0xcd,0xb0, + 0x34,0x6c,0x8f,0x61,0x19,0x58,0xa7,0x61,0x59,0xd8,0x01,0xc3,0x72,0xb0,0x43,0x86, + 0xe5,0x61,0xc7,0x0c,0x6b,0x82,0xf5,0x1a,0xd6,0x0c,0xeb,0xf7,0x5a,0xe3,0xff,0x3d, + 0xab,0xee,0x32,0xba,0x4b,0xd8,0xc3,0x32,0xef,0x47,0x73,0xb0,0xf7,0x19,0xbb,0xd2, + 0xb0,0x5e,0x61,0x5d,0xf3,0xed,0x94,0xdf,0xc8,0xdb,0xb1,0xd7,0x1f,0xf9,0xbc,0xb1, + 0xd7,0xa3,0xfa,0x5a,0xc5,0x3f,0x87,0xbe,0x08,0x7b,0x1b,0x76,0xda,0xfb,0xa4,0x65, + 0x2f,0x93,0x6f,0xac,0xfc,0x14,0x76,0x01,0x56,0x14,0xbb,0x48,0xae,0x60,0x97,0xb0, + 0xf5,0xd9,0x2b,0x51,0xe1,0x5b,0x85,0x51,0x34,0x23,0xcb,0x5c,0x32,0x43,0x6b,0xb6, + 0xf1,0xdd,0x5a,0xa9,0xa9,0xf6,0x6e,0xd8,0x51,0x6a,0xb6,0x53,0x53,0xfd,0x3b,0x58, + 0xcb,0x99,0xf5,0xd0,0x43,0xb0,0xbb,0xd9,0x1f,0xf5,0x3f,0x88,0xbf,0xd6,0xdb,0x25, + 0xca,0x0f,0xe3,0xa7,0xf6,0x91,0x86,0xb8,0xbe,0x86,0xba,0x03,0xec,0x9f,0xe6,0x19, + 0xe4,0x5c,0x65,0xe9,0x73,0x90,0x73,0x1d,0xfb,0x7e,0x9b,0xdc,0x10,0x6b,0x29,0x72, + 0x36,0xce,0x9a,0xe3,0x3c,0xef,0x43,0xe4,0x50,0x7b,0x18,0xd6,0x2e,0xbd,0x8d,0xe0, + 0x37,0x0a,0x1b,0xc1,0x4f,0xed,0x0a,0xac,0x43,0x2a,0x8e,0x93,0x23,0xf4,0x39,0xc1, + 0x9e,0x06,0x7b,0xca,0xec,0xe9,0x15,0x34,0x15,0xd9,0xf3,0x69,0xfa,0x8c,0x8d,0xff, + 0x2c,0xf6,0x09,0x39,0xb3,0x11,0xb1,0x0e,0xf6,0x4b,0x88,0xde,0x93,0xd3,0x9c,0x97, + 0x05,0xce,0xc4,0x88,0x50,0xcd,0x73,0x0f,0xe6,0x0c,0xbb,0x0f,0x53,0xed,0x17,0x84, + 0xe9,0x5e,0x3d,0xc0,0x57,0xd7,0xce,0x08,0xd3,0x7d,0x5c,0x64,0xaf,0xdb,0xc9,0xaf, + 0x7e,0x4b,0xf0,0x35,0xe2,0x1e,0x12,0xbb,0x64,0xe2,0x1e,0x11,0xd7,0x69,0xe2,0x96, + 0xe1,0xab,0xc4,0x3d,0x26,0x76,0x99,0x38,0x3d,0x07,0x4f,0x88,0xeb,0x26,0x4e,0xcf, + 0xc0,0x53,0xf8,0x77,0xf1,0xd1,0xb3,0xf1,0x0c,0xa6,0x67,0xe3,0xa7,0x7c,0x81,0x55, + 0xb4,0xfd,0x11,0x7f,0x5d,0x5b,0xf1,0x35,0x92,0xef,0xb2,0x62,0x34,0xbf,0xa0,0xa6, + 0x3e,0xcf,0xc5,0x57,0xd9,0x4b,0xf8,0xa8,0x58,0xda,0xd3,0x27,0x58,0xf0,0xfb,0x2d, + 0x39,0x42,0x2e,0x9d,0x7f,0x88,0x97,0xfa,0x7d,0xc1,0x27,0x43,0xcc,0x8a,0xd1,0xf0, + 0x0a,0x0d,0x7d,0x46,0xc3,0x1a,0x3c,0x68,0x78,0x0d,0x0b,0x1a,0x6a,0x46,0x83,0xae, + 0xad,0xcb,0xa8,0x51,0x77,0xdd,0x68,0x78,0x43,0xed,0x94,0xd1,0xf0,0x16,0x1e,0x34, + 0x7c,0x86,0x05,0x3f,0xd5,0x10,0x72,0xd5,0x8c,0x86,0x4d,0x7c,0x56,0x89,0x59,0x37, + 0x1a,0xde,0xa1,0x61,0xc0,0x68,0x78,0x0f,0x0f,0x1a,0x3e,0xc0,0x82,0x86,0xba,0xd1, + 0xa0,0x6b,0x1b,0x32,0xea,0xd4,0xdd,0xf0,0xf7,0x28,0xa9,0xfb,0x91,0xda,0x9b,0xe6, + 0xee,0x69,0x8f,0xc1,0xb7,0x6e,0x7a,0xfc,0x8a,0x5f,0x8d,0xb8,0x0d,0xfa,0x19,0xf2, + 0xe7,0x36,0xb9,0x9b,0x6a,0xeb,0x3d,0x1c,0xe3,0x0e,0x5e,0x94,0xfe,0xc6,0xfd,0x9c, + 0xf8,0x8c,0x99,0x73,0x79,0x09,0x5d,0x13,0xe6,0x5c,0x4e,0xc2,0xc3,0x79,0xbe,0x4c, + 0xdd,0x49,0xe2,0xf4,0x7e,0x5e,0x25,0x6e,0x8a,0x38,0xbd,0x93,0xd7,0xe0,0x77,0xd9, + 0x87,0xeb,0xb0,0xb0,0x57,0x37,0xc8,0x65,0xef,0xdd,0x0c,0x2c,0xb9,0x77,0x59,0x7f, + 0xd7,0xab,0xf8,0xce,0x90,0x23,0xd4,0xbc,0x49,0xcd,0x59,0x53,0xf3,0x16,0x3c,0xd4, + 0x9c,0x83,0x4d,0x48,0xe7,0x7a,0xf7,0xe7,0xd1,0x5d,0xe5,0xff,0x66,0xce,0xd4,0xbe, + 0xcd,0xba,0xf3,0xfb,0x1a,0xfb,0xff,0x46,0x65,0x7f,0xa5,0x9b,0x93,0x32,0xfe,0x01, + 0xd1,0xf0,0xb6,0x4b,0x5c,0x08,0x00,0x00 }; // Generated from: @@ -75,6 +77,7 @@ constexpr uint8_t kBlitResolve_frag_0000000D[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -111,6 +114,6 @@ constexpr uint8_t kBlitResolve_frag_0000000D[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// gl_FragDepth = texture(sampler2DArray(depth, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)). x; +// gl_FragDepth = textureLod(sampler2DArray(depth, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip). x; // // } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000E.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000E.inc index cf7b58209d0..ebed00a4e34 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000E.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000E.inc @@ -10,44 +10,45 @@ #pragma once constexpr uint8_t kBlitResolve_frag_0000000E[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x4d,0x93,0x5b,0x6b,0x53,0x51, - 0x10,0x85,0x77,0xce,0x69,0x2e,0x55,0xd3,0x26,0x68,0x12,0x2b,0x62,0xa3,0xf1,0x41, - 0xd0,0x96,0x3e,0xa8,0x04,0x44,0xd1,0x87,0xc6,0x56,0x22,0xd2,0xd6,0x52,0xb5,0xa8, - 0xa9,0x06,0x25,0x6a,0x6a,0xc0,0x82,0x56,0xc1,0x07,0xff,0x8e,0xbf,0x4f,0xbc,0x80, - 0xe0,0xac,0x9d,0x6f,0xd7,0xd9,0x30,0xd9,0x67,0xd6,0x5c,0xd7,0xec,0x49,0x9e,0x75, - 0xca,0x21,0x14,0xc2,0xb1,0x50,0x09,0x5f,0xc2,0xf4,0xd4,0x43,0x66,0x48,0x08,0xc7, - 0x43,0x29,0xde,0x77,0xfb,0x5b,0xfd,0xe5,0x0f,0x07,0xc3,0xe5,0xab,0xd7,0x56,0x64, - 0x9f,0x0b,0x79,0xf4,0x93,0x6d,0x3e,0x94,0xc3,0x8c,0xdd,0x92,0xf1,0xde,0x68,0x5f, - 0x78,0xcd,0xa4,0x17,0xef,0x3c,0xe2,0x65,0xf7,0x7d,0x42,0xf9,0xec,0xab,0x16,0xf3, - 0x2b,0x3e,0x84,0xb5,0x50,0x0c,0x4d,0x6a,0x77,0xb8,0x13,0x56,0x00,0xab,0x38,0x2c, - 0x03,0xab,0x39,0x2c,0x07,0x3b,0xed,0xb0,0x19,0xb0,0xb3,0x0e,0x2b,0x82,0xb5,0x1d, - 0x56,0x02,0xbb,0xe8,0xb0,0x32,0xd8,0x25,0x87,0x55,0xc0,0xae,0x38,0x6c,0x16,0x6c, - 0x25,0xf2,0xca,0x8f,0xfa,0x13,0xc7,0x1e,0x1c,0x9b,0xe8,0xeb,0x76,0x5f,0x80,0x5f, - 0xd2,0xcf,0xa3,0x9f,0xb4,0xa8,0x2c,0xea,0x79,0xe4,0xa2,0xef,0x86,0xf9,0x94,0xe8, - 0x55,0x73,0x68,0x99,0x5e,0xa6,0xdf,0x2c,0xe6,0xcd,0x43,0x15,0xbb,0x6c,0x73,0x76, - 0x57,0xe1,0xdd,0xb6,0xdf,0x79,0xe2,0x84,0xdf,0x40,0xaf,0xb9,0x5c,0x75,0xfc,0x53, - 0xad,0x06,0xb9,0x74,0xce,0xd9,0x4b,0xa5,0x39,0xd4,0x91,0x12,0x52,0xe5,0x6e,0x38, - 0x51,0xbd,0x16,0xf3,0x68,0x52,0xaf,0xc5,0x7b,0x08,0xbb,0x0c,0x97,0x05,0xf2,0xcb, - 0xff,0x0c,0xb6,0xb2,0xb3,0x2f,0xa2,0xcb,0xde,0xc6,0xae,0xfc,0xa7,0xac,0xcb,0x0e, - 0x7e,0x0d,0xde,0x2a,0xb8,0xb8,0x25,0xde,0x27,0xe9,0x5d,0x62,0x95,0x67,0x95,0xfd, - 0xa8,0xd2,0xd7,0x2a,0xfb,0x99,0xc7,0x7e,0x66,0xed,0x2d,0xa6,0xb6,0x42,0xf8,0x7f, - 0x0a,0x4e,0x57,0x8e,0xb5,0xa3,0x77,0x9b,0xe6,0x90,0xbe,0x0e,0x76,0xdd,0x76,0x21, - 0x63,0xee,0x81,0xbc,0xbf,0x0c,0xd1,0xae,0xdd,0xe4,0x5d,0x36,0x98,0xfd,0x03,0x63, - 0xa7,0x59,0x6e,0x82,0x6d,0xb8,0x7a,0xfb,0xbc,0xef,0x16,0xf6,0x3b,0x96,0x41,0x33, - 0x7a,0xc8,0x1c,0x17,0xc8,0x27,0x9f,0x6d,0xf0,0x6f,0xe6,0x23,0x7d,0x87,0xb8,0x6d, - 0xe2,0x34,0xbb,0x47,0xc4,0x2d,0x12,0xa7,0xb9,0x3d,0x06,0xff,0x6e,0x3e,0x9a,0xe7, - 0x13,0x30,0xcd,0xf3,0xa7,0x75,0x3e,0xa0,0x9f,0x3f,0xe6,0x2f,0xdb,0xae,0xc9,0x00, - 0x3e,0xbb,0xb1,0xdf,0x62,0x9c,0xef,0x53,0x6a,0xea,0x7c,0x65,0xe6,0xcf,0xc0,0x37, - 0x4d,0x53,0x4f,0x07,0x60,0xc9,0xef,0xb7,0xe5,0x48,0xb9,0x74,0xff,0x30,0x2f,0xf9, - 0x7d,0xc2,0xa7,0x48,0xcc,0xae,0xe3,0xb0,0x07,0x87,0x25,0xc7,0xe1,0x05,0x78,0xe2, - 0xf0,0x12,0x2c,0x71,0x18,0x39,0x0e,0xb2,0x0d,0x4d,0x46,0xd4,0x1d,0x3a,0x0e,0xaf, - 0xa8,0x5d,0x70,0x1c,0x5e,0x83,0x27,0x0e,0x1f,0xc1,0x92,0x9f,0x38,0xa4,0x5c,0x23, - 0xc7,0xe1,0x10,0x9f,0x01,0x31,0x43,0xc7,0xe1,0x0d,0x1c,0xba,0x8e,0xc3,0x5b,0xf0, - 0xc4,0xe1,0x1d,0x58,0xe2,0x30,0x71,0x1c,0x64,0x1b,0x9b,0x4c,0xa8,0x3b,0x66,0x8f, - 0x54,0xf7,0x3d,0xb5,0x0f,0xdd,0xbe,0xaa,0xc7,0xe4,0x3b,0x71,0x3d,0x7e,0xc6,0x6f, - 0x44,0xdc,0x98,0x7e,0xb4,0xd3,0xf7,0xd8,0xe7,0xe7,0xe6,0xa9,0x7d,0xed,0x83,0x29, - 0xe6,0x36,0xbb,0xa7,0xb9,0xe9,0x7f,0x72,0x1f,0xbb,0xce,0x2d,0xeb,0xb5,0x07,0xf6, - 0xd7,0x3a,0xe8,0x9a,0xfc,0x03,0x52,0x53,0x8a,0x15,0x54,0x06,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0x5b,0x6b,0x53,0x41, + 0x14,0x46,0x27,0xe7,0x34,0x39,0x69,0x35,0x6d,0x82,0x26,0xb1,0x22,0x36,0x1a,0x1f, + 0x04,0x6d,0xe9,0x43,0x95,0x80,0x28,0xfa,0xd0,0xd8,0x4a,0x44,0xda,0x5a,0xbc,0x04, + 0x35,0xd5,0xa0,0x44,0x4d,0x0d,0x58,0xd0,0x2a,0xf8,0xe0,0xdf,0xf1,0xf7,0x89,0x17, + 0x10,0xdc,0xdf,0xc9,0x9a,0xba,0xf1,0xc0,0x74,0x32,0x6b,0x5f,0xbf,0x3d,0xd3,0x34, + 0x69,0x67,0x21,0x14,0xc2,0x5c,0x28,0x87,0xcf,0x61,0xfa,0xd5,0x42,0x62,0x24,0x84, + 0x63,0xa1,0x94,0xef,0xb7,0x7b,0x3b,0xbd,0x95,0xf7,0x07,0xc3,0x95,0xb5,0x2b,0xab, + 0xb2,0xcf,0x87,0x34,0xf7,0x93,0x6d,0x21,0x64,0x61,0xc6,0x76,0xad,0xf1,0xde,0x68, + 0x5f,0xbc,0x6a,0xab,0x9b,0xef,0x69,0xce,0x33,0xf7,0xfb,0xb8,0xf2,0xd9,0xaf,0x6a, + 0x9e,0x5f,0xf1,0x21,0x6c,0x84,0x62,0x68,0x50,0xbb,0xcd,0x1e,0x59,0x01,0x56,0x76, + 0x2c,0x81,0x55,0x1d,0x4b,0x61,0xa7,0x1c,0x9b,0x81,0x9d,0x71,0xac,0x08,0x6b,0x39, + 0x56,0x82,0x5d,0x70,0x2c,0x83,0x5d,0x74,0xac,0x0c,0xbb,0xec,0xd8,0x2c,0x6c,0xd5, + 0xb1,0x39,0xd8,0x5a,0xae,0x35,0x3d,0xea,0x59,0xba,0xbb,0xe8,0x6e,0x70,0xde,0xb4, + 0xfd,0x3c,0x9a,0xe3,0xf9,0x1c,0xe7,0x13,0x16,0x95,0xe4,0xe7,0x34,0xd7,0xa7,0xdf, + 0x75,0xf3,0x29,0xd1,0xbf,0x66,0xd3,0xb4,0x73,0x86,0x86,0x24,0xcf,0x9b,0x86,0x0a, + 0x76,0xd9,0xe6,0x6d,0xaf,0x30,0x8b,0x96,0xfd,0x5d,0x20,0x4e,0xfc,0x1a,0xe7,0xaa, + 0xcb,0x55,0xc3,0x3f,0xd6,0xaa,0x93,0x4b,0xdf,0x59,0xb3,0xc4,0xd9,0xd4,0x58,0x25, + 0xb7,0x2a,0xec,0x75,0xb7,0x54,0xb3,0xc9,0x9c,0x1a,0xd4,0x6c,0x72,0x4f,0x62,0x97, + 0xd0,0xb3,0x48,0x0d,0xf9,0x9f,0xc6,0x96,0x39,0xfb,0x12,0xf3,0x97,0xbd,0x85,0x5d, + 0xf9,0x4f,0x5a,0xa7,0x6d,0xfc,0xea,0xdc,0x61,0x70,0x71,0xcb,0xff,0xd5,0xe9,0x70, + 0x3f,0xca,0xb3,0xce,0xbb,0xa9,0xd0,0xd7,0x3a,0xef,0x36,0xcd,0xfb,0x99,0xb5,0xfb, + 0x98,0xda,0x0a,0xe1,0xdf,0x57,0x70,0x67,0xe5,0xd8,0x38,0xba,0xbb,0x69,0x0e,0x9d, + 0x37,0x61,0x57,0xed,0x3d,0x24,0xcc,0x3e,0x90,0xf7,0xa7,0x11,0xbd,0xc1,0xeb,0xdc, + 0xcd,0x16,0xf3,0xbf,0x67,0x6a,0x35,0xcf,0x6d,0xd8,0x96,0xab,0xb7,0xcf,0x1d,0xef, + 0x60,0xbf,0x65,0x19,0x34,0xa3,0xfb,0xcc,0x71,0x91,0x7c,0xf2,0xd9,0x85,0x7f,0x35, + 0x1f,0x9d,0x1f,0x10,0xb7,0x4b,0x9c,0x66,0xf7,0x90,0xb8,0x25,0xe2,0x34,0xb7,0x47, + 0xf0,0x6f,0xe6,0xa3,0x79,0x3e,0x86,0x69,0x9e,0x3f,0xac,0xf3,0x01,0xfd,0xfc,0x36, + 0x7f,0xd9,0xfa,0xb6,0x06,0xe8,0xe9,0xe7,0xfd,0x16,0xf3,0xf9,0x3e,0xa1,0xa6,0xbe, + 0x2f,0xcc,0xfc,0x29,0x7c,0xdb,0x4e,0xea,0xe9,0x00,0x16,0xfd,0x7e,0x59,0x8e,0x98, + 0x4b,0xfb,0x77,0xf3,0x92,0xdf,0x47,0x7c,0x8a,0xc4,0xf4,0x9d,0x86,0x3d,0x34,0x2c, + 0x3b,0x0d,0xcf,0xe1,0x51,0xc3,0x0b,0x58,0xd4,0x30,0x72,0x1a,0x64,0x1b,0xda,0x1a, + 0x51,0x77,0xe8,0x34,0xbc,0xa4,0x76,0xc1,0x69,0x78,0x05,0x8f,0x1a,0x3e,0xc0,0xa2, + 0x9f,0x34,0xc4,0x5c,0x23,0xa7,0xe1,0x10,0x9f,0x01,0x31,0x43,0xa7,0xe1,0x35,0x1a, + 0x3a,0x4e,0xc3,0x1b,0x78,0xd4,0xf0,0x16,0x16,0x35,0x4c,0x9c,0x06,0xd9,0xc6,0xb6, + 0x26,0xd4,0x1d,0xf3,0x8e,0x54,0xf7,0x1d,0xb5,0x0f,0xdd,0x7b,0x55,0x8f,0xd1,0x77, + 0xe2,0x7a,0xfc,0x84,0xdf,0x88,0xb8,0x31,0xfd,0xe8,0x4d,0xdf,0xe1,0x3d,0x3f,0x33, + 0x4f,0xbd,0xd7,0x1e,0x4c,0x31,0x37,0x79,0x7b,0x9a,0x9b,0xfe,0x4f,0xee,0x62,0xd7, + 0x77,0xc3,0x7a,0xed,0xc2,0xfe,0x58,0x07,0x1d,0x5b,0x7f,0x01,0x02,0x9b,0x31,0x90, + 0x6c,0x06,0x00,0x00 }; // Generated from: @@ -67,6 +68,7 @@ constexpr uint8_t kBlitResolve_frag_0000000E[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000F.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000F.inc index e0f7543fb3e..d6ca10c7ab0 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000F.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.0000000F.inc @@ -10,47 +10,48 @@ #pragma once constexpr uint8_t kBlitResolve_frag_0000000F[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0x5b,0x4f,0x53,0x51, - 0x10,0x85,0x77,0x7b,0xe8,0x05,0xb5,0xd0,0x46,0xdb,0x8a,0x31,0x52,0xad,0x0f,0x26, - 0x0a,0xe1,0x41,0x4d,0x13,0xa3,0xd1,0x07,0x2a,0x98,0xaa,0x50,0xf4,0x01,0x95,0x20, - 0xa2,0xa6,0x28,0xd6,0x54,0x68,0xec,0x83,0x51,0xc1,0x9f,0xe3,0xef,0x33,0x5e,0x12, - 0x13,0x67,0x9d,0x7e,0x9b,0x4c,0x3c,0xc9,0x9c,0x7d,0x66,0xcd,0x75,0xcd,0x9e,0x93, - 0x64,0x9b,0x85,0x10,0x32,0xe1,0x58,0x28,0x86,0x6f,0x61,0xfc,0x54,0x42,0xd6,0x90, - 0x10,0x8e,0x87,0x7c,0x7a,0xde,0xed,0xac,0x75,0xe6,0xf7,0xf6,0x5f,0xce,0x5f,0xbd, - 0xb6,0x20,0xfb,0x54,0x48,0x52,0x3f,0xd9,0xa6,0x43,0x21,0x4c,0xd8,0x29,0x79,0xb7, - 0xb5,0xd3,0x17,0x5e,0x36,0x69,0xa7,0x67,0x92,0xe2,0x05,0xf7,0x7d,0x42,0xf9,0xec, - 0xab,0x9c,0xe6,0x57,0x7c,0x08,0x4b,0x21,0x17,0x6a,0xd4,0x6e,0x72,0x46,0x2c,0x03, - 0x56,0x74,0x58,0x16,0xac,0xec,0xb0,0x04,0xec,0xb4,0xc3,0x26,0xc0,0xce,0x3a,0x2c, - 0x07,0xd6,0x70,0x58,0x1e,0xec,0xa2,0xc3,0x0a,0x60,0x97,0x1c,0x56,0x04,0xbb,0xe2, - 0xb0,0x49,0xb0,0x85,0x94,0x57,0x72,0xd4,0x9f,0x38,0xb6,0xe1,0x58,0x43,0x5f,0xb6, - 0xf3,0x02,0xfc,0xa2,0x7e,0x1e,0xfd,0xa4,0x45,0x65,0x53,0x3d,0x49,0xb9,0xe8,0xbb, - 0x6a,0x3e,0x79,0x7a,0xd5,0x1c,0xea,0xa6,0x17,0xe8,0x37,0x9b,0xe6,0x4d,0x42,0x09, - 0xbb,0x6c,0x53,0x76,0x96,0xe0,0xdd,0xb0,0xf7,0x34,0x71,0xc2,0x6f,0xa0,0x97,0x5d, - 0xae,0x0a,0xfe,0xb1,0x56,0x95,0x5c,0x7a,0xce,0xd9,0x4d,0xc5,0x39,0x54,0x90,0x3c, - 0x52,0xe2,0xac,0x3a,0x51,0xbd,0x3a,0xf3,0xa8,0x51,0xaf,0xce,0x7d,0x08,0xbb,0x0c, - 0x97,0x19,0xf2,0xcb,0xff,0x0c,0xb6,0x82,0xb3,0xcf,0xa2,0xcb,0xde,0xc0,0xae,0xfc, - 0xa7,0xac,0xcb,0x26,0x7e,0x55,0xee,0x2a,0xb8,0xb8,0x39,0xee,0x27,0xea,0x2d,0x62, - 0x95,0x67,0x91,0xfd,0x28,0xd1,0xd7,0x22,0xfb,0x99,0xa4,0xfd,0x4c,0xda,0x5d,0x8c, - 0x6d,0x19,0x72,0x66,0x9c,0xc4,0x5e,0x97,0x8e,0xee,0x6d,0x9c,0x43,0xfa,0xf2,0x7f, - 0x3d,0x74,0xc8,0x29,0xff,0xfb,0xd4,0xcf,0x33,0xeb,0x15,0xbe,0x65,0xbf,0x6e,0xbb, - 0x93,0xe5,0x9e,0x02,0xd8,0x2f,0x43,0xb4,0x9b,0x37,0xb9,0xc7,0x75,0xee,0xea,0xa1, - 0x4d,0x43,0xb3,0x7f,0x02,0xb6,0xee,0x7a,0xec,0xb3,0x0f,0x4f,0xb1,0xdf,0xb1,0x0c, - 0x9a,0xe9,0x33,0xe6,0x3e,0x43,0x3e,0xf9,0x6c,0x80,0x1f,0x9a,0x8f,0xf4,0x4d,0xe2, - 0x36,0x88,0xd3,0xac,0x9f,0x13,0x37,0x4b,0x9c,0xe6,0xbc,0x05,0xfe,0xdd,0x7c,0x34, - 0xff,0x17,0x60,0x9a,0xff,0x4f,0xeb,0xbc,0x47,0x3f,0x7f,0xcc,0x5f,0xb6,0x6d,0x93, - 0x1e,0x7c,0xf4,0xbd,0x6a,0x71,0xe2,0xfd,0x8a,0x9a,0x7a,0x3e,0x33,0xaf,0xd7,0xe0, - 0x5d,0xd3,0xd4,0xd3,0x27,0xb0,0xe8,0xf7,0xdb,0x72,0xc4,0x5c,0x3a,0x7f,0x98,0x97, - 0xfc,0xbe,0xe2,0x93,0x23,0x66,0xdb,0x71,0xd8,0x81,0xc3,0x9c,0xe3,0xf0,0x06,0x3c, - 0x72,0x78,0x0b,0x16,0x39,0x0c,0x1c,0x07,0xd9,0x76,0x4d,0x06,0xd4,0xdd,0x75,0x1c, - 0xfa,0xd4,0xce,0x38,0x0e,0xef,0xc1,0x23,0x87,0x2f,0x60,0xd1,0x4f,0x1c,0x62,0xae, - 0x81,0xe3,0x70,0x80,0x4f,0x8f,0x98,0x5d,0xc7,0xe1,0x03,0x1c,0x5a,0x8e,0xc3,0x1e, - 0x78,0xe4,0xb0,0x0f,0x16,0x39,0x8c,0x1c,0x07,0xd9,0x86,0x26,0x23,0xea,0x0e,0xd9, - 0x23,0xd5,0xfd,0x48,0xed,0x03,0xb7,0xdf,0xea,0x31,0xfa,0x8e,0x5c,0x8f,0x87,0xf8, - 0x0d,0x88,0x1b,0xd2,0x8f,0xfe,0x81,0x7b,0xec,0xbf,0x7a,0xd6,0xae,0x3f,0xa0,0xe7, - 0x0e,0x3e,0xf9,0xb4,0xe6,0x18,0x8f,0xf3,0x5b,0x25,0x67,0x70,0x58,0x17,0x4c,0xbd, - 0xac,0x18,0xa2,0xff,0x64,0x0d,0xdf,0x2e,0x39,0x36,0xad,0x1b,0xfd,0x13,0x8f,0xa8, - 0x2b,0xfb,0x6d,0xf6,0x5b,0x79,0xf4,0xef,0x3e,0xc6,0xae,0xe7,0x96,0xcd,0xa3,0x0d, - 0xf6,0xd7,0x32,0xb7,0x4c,0xfe,0x01,0x76,0x5f,0xe7,0xdd,0xe8,0x06,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0x5d,0x4f,0x53,0x41, + 0x10,0x86,0xb7,0x3d,0xb4,0xa7,0xa0,0x85,0x12,0x6d,0x2b,0xc6,0x48,0xb5,0x5e,0x98, + 0x28,0x84,0x0b,0x34,0x4d,0x8c,0x46,0x2f,0x40,0x30,0x55,0xf9,0xf2,0x02,0x95,0x20, + 0xa2,0x06,0xb4,0xd6,0x54,0x20,0xf6,0xc2,0xa8,0xe0,0xcf,0xf1,0xf7,0x19,0x3f,0x12, + 0x13,0xe7,0x3d,0x7d,0x96,0x4c,0x38,0xc9,0x9e,0x3d,0xfb,0xcc,0xec,0xcc,0xbc,0xb3, + 0x7b,0x92,0x7c,0x33,0x0d,0x21,0x17,0x46,0x42,0x29,0x7c,0x0f,0x83,0x67,0x3c,0xe4, + 0x8d,0x84,0x70,0x2a,0x14,0xb3,0xf9,0x7e,0x7b,0xb5,0x3d,0xbd,0xb7,0xff,0x6a,0x7a, + 0xf6,0xc6,0x8c,0xec,0xa3,0x21,0xc9,0xfc,0x64,0x1b,0x0b,0x69,0x18,0xb2,0x59,0xe3, + 0xfd,0xd6,0x6e,0x57,0xbc,0x62,0x63,0x3e,0x9b,0x93,0x8c,0xa7,0xee,0xfb,0xb4,0xe2, + 0xd9,0x57,0x25,0x8b,0xaf,0xfd,0x21,0x2c,0x84,0x42,0xa8,0x91,0xbb,0xc9,0x1c,0x59, + 0x0e,0x56,0x72,0x2c,0x0f,0xab,0x38,0x96,0xc0,0xce,0x39,0x36,0x04,0xbb,0xe0,0x58, + 0x01,0xd6,0x70,0xac,0x08,0xbb,0xe2,0x58,0x0a,0xbb,0xea,0x58,0x09,0x76,0xdd,0xb1, + 0x61,0xd8,0x8c,0x63,0x23,0xb0,0xd9,0x4c,0x6b,0x72,0x5c,0xb3,0x74,0xcf,0xa3,0xbb, + 0xc6,0x7a,0xd1,0xe6,0xcb,0x68,0x8e,0xeb,0x4b,0xac,0xcf,0xd8,0xae,0x7c,0xb6,0x4e, + 0x32,0x7d,0xfa,0xae,0x9a,0x4f,0x91,0xfa,0xd5,0x9b,0xba,0xad,0x53,0x34,0xe4,0xb3, + 0xb8,0x49,0x28,0x63,0x97,0x6d,0xd4,0xe6,0x32,0xbd,0x68,0xd8,0x7b,0x8c,0x7d,0xe2, + 0xb7,0x58,0x57,0x5c,0xac,0x71,0xfc,0x63,0xae,0x2a,0xb1,0xf4,0x5c,0x34,0x4b,0xec, + 0xcd,0x38,0xa3,0xe8,0x46,0x99,0xb9,0xea,0x86,0x72,0xd6,0xe9,0x53,0x8d,0x9c,0x75, + 0xce,0x49,0xec,0x1a,0x7a,0x26,0xc8,0x21,0xff,0xf3,0xd8,0x52,0x67,0x9f,0xa4,0xff, + 0xb2,0x37,0xb0,0x2b,0xfe,0x59,0xab,0xb4,0x89,0x5f,0x95,0x33,0x0c,0x6e,0xdf,0xd4, + 0x89,0x3c,0x2d,0xce,0x47,0x71,0xe6,0xb8,0x37,0x65,0xea,0x9a,0xe3,0xde,0x26,0x59, + 0x3d,0xc3,0x76,0x1e,0x03,0x5b,0x8e,0x98,0x39,0x37,0x62,0xad,0x0b,0xc7,0x67,0x37, + 0x88,0xa1,0xf5,0xe2,0x89,0x1a,0xda,0xae,0xff,0x0f,0xa9,0xa7,0x48,0xbf,0x97,0xf8, + 0x56,0xce,0x9b,0x76,0x7f,0xf2,0xf8,0x06,0xd8,0x6f,0x23,0xba,0xb3,0xb7,0x39,0xcb, + 0x75,0xce,0xeb,0xb1,0x75,0x47,0xfd,0x7f,0x0a,0x5b,0x77,0x35,0x76,0xb9,0x13,0xcf, + 0xb0,0xdf,0xb3,0x08,0xea,0xe9,0x73,0xfa,0x3e,0x41,0x3c,0xf9,0x6c,0xc0,0x8f,0xcc, + 0x47,0xeb,0x4d,0xf6,0x6d,0xb0,0x4f,0xbd,0x7e,0xc1,0xbe,0x49,0xf6,0xa9,0xcf,0x5b, + 0xf0,0x1f,0xe6,0xa3,0xfe,0xbf,0x84,0xa9,0xff,0xbf,0xac,0xf2,0x1d,0xea,0xf9,0x6b, + 0xfe,0xb2,0x6d,0xdb,0xd8,0x41,0x8f,0xbe,0x97,0x6d,0x9f,0x74,0xbf,0x26,0xa7,0x9e, + 0x2f,0xf4,0xeb,0x0d,0x7c,0xc5,0x56,0xaa,0xe9,0x33,0x2c,0xfa,0xfd,0xb1,0x18,0x31, + 0x96,0xe6,0x9f,0xe6,0x25,0xbf,0x6f,0xf8,0x14,0xd8,0xb3,0xed,0x34,0xec,0xa2,0x61, + 0xca,0x69,0x78,0x0b,0x8f,0x1a,0xde,0xc1,0xa2,0x86,0x9e,0xd3,0x20,0x5b,0xc7,0x46, + 0x8f,0xbc,0x1d,0xa7,0xa1,0x4b,0xee,0x9c,0xd3,0xf0,0x01,0x1e,0x35,0x7c,0x85,0x45, + 0x3f,0x69,0x88,0xb1,0x7a,0x4e,0xc3,0x21,0x3e,0x3b,0xec,0xe9,0x38,0x0d,0x1f,0xd1, + 0xd0,0x72,0x1a,0xf6,0xe0,0x51,0xc3,0x3e,0x2c,0x6a,0xe8,0x3b,0x0d,0xb2,0x1d,0xd8, + 0xe8,0x93,0xf7,0x80,0x7b,0xa4,0xbc,0x9f,0xc8,0x7d,0xe8,0xee,0xb7,0x6a,0x8c,0xbe, + 0x7d,0x57,0xe3,0x11,0x7e,0x3d,0xf6,0x1d,0x50,0x8f,0xfe,0x81,0x07,0xdc,0x7f,0xd5, + 0xac,0xbb,0xfe,0x88,0x9a,0xdb,0xf8,0x14,0xb3,0x9c,0x03,0x1e,0xfb,0xb7,0x4c,0xcc, + 0xe0,0xd8,0x0a,0x4c,0xb5,0x2c,0x19,0xd1,0x7f,0xb2,0x8a,0xef,0x0a,0x31,0x36,0xad, + 0x1a,0xfd,0x13,0x6b,0xe4,0x95,0xfd,0x2e,0xf7,0x5b,0x71,0xf4,0xef,0x3e,0xc1,0xae, + 0xe7,0x8e,0xf5,0x63,0x1e,0xf6,0xcf,0x22,0xb7,0x6c,0xfc,0x07,0x35,0xd9,0x9f,0xfa, + 0x00,0x07,0x00,0x00 }; // Generated from: @@ -70,6 +71,7 @@ constexpr uint8_t kBlitResolve_frag_0000000F[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000010.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000010.inc index 737767ff47f..2a3dc421ee2 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000010.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000010.inc @@ -10,52 +10,54 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000010[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0x6b,0x4b,0xd4,0x41, - 0x14,0x87,0x67,0xef,0x6b,0x37,0x8d,0x6d,0xd5,0x34,0xc2,0x32,0xa3,0x1b,0x22,0x58, - 0x11,0x44,0x42,0x2f,0xa2,0xc0,0x35,0x5d,0x77,0x35,0xcb,0x6a,0x11,0xdd,0x72,0xc9, - 0x5b,0xae,0xc5,0x56,0x92,0x6c,0x2a,0xf9,0x22,0x28,0x8b,0xfa,0x12,0x7d,0xbe,0xe8, - 0x02,0x41,0xe7,0xcc,0xff,0x19,0x39,0xb9,0x30,0x3b,0xff,0xf3,0xcc,0xb9,0xcc,0x6f, - 0xce,0x4c,0x22,0xde,0x9b,0x71,0x2e,0xe6,0x0e,0xb8,0xac,0xfb,0xe2,0xa2,0xdf,0x51, - 0x17,0x17,0x12,0xcd,0x5f,0x73,0x4e,0xd6,0x5a,0x5c,0x69,0x6c,0xb2,0x72,0x6b,0xaa, - 0x5c,0xa9,0xcf,0xcf,0xcc,0x55,0x57,0x2b,0xf5,0xb5,0xea,0xd2,0x6c,0x6d,0xa1,0x52, - 0x6d,0xac,0x2c,0xaf,0xae,0x89,0xef,0x41,0x97,0xf6,0x31,0xb7,0x0b,0xa5,0x42,0x7f, - 0x7d,0x6d,0xae,0xff,0xf2,0x95,0x01,0xcd,0x75,0xc4,0x25,0x7c,0x4e,0x5d,0x6b,0x75, - 0x19,0x97,0x94,0x59,0xc7,0xe2,0x4c,0x6d,0xc9,0x79,0xe6,0x5c,0x41,0x46,0x9b,0xf8, - 0x29,0xcf,0x68,0x0e,0xf9,0x6a,0xf5,0x39,0xa3,0xf5,0x3b,0x2e,0xe5,0x3a,0xd8,0x5b, - 0x2f,0x73,0x60,0x31,0x58,0xd6,0xb0,0x38,0xac,0xcd,0xb0,0x04,0xac,0xd3,0xb0,0x24, - 0xec,0x84,0x61,0x29,0x58,0x8f,0x61,0x69,0xd8,0x19,0xc3,0x32,0xb0,0x73,0x86,0x65, - 0x61,0x97,0x0c,0x6b,0x81,0x0d,0x78,0x5d,0x89,0xbd,0xfd,0xa9,0xc6,0x02,0x1a,0xbf, - 0xe5,0x22,0x7b,0x54,0xbe,0x4f,0xa3,0x2f,0xd8,0xa7,0xd0,0xa8,0x76,0x69,0xdf,0x7a, - 0x89,0x75,0xcd,0x97,0x93,0xff,0xb8,0xb7,0x13,0x5e,0xab,0x7e,0xb7,0xcb,0x57,0x1a, - 0x2d,0x1d,0xe2,0x9f,0x41,0x4b,0x1c,0xfb,0x30,0x76,0xd2,0xfb,0x24,0xa5,0x57,0x51, - 0x2d,0xe5,0xd7,0xb1,0x5b,0x61,0x79,0xb1,0xf3,0xe4,0x0a,0x76,0x3b,0xb6,0xfe,0x4e, - 0xba,0x43,0x7b,0xe7,0x12,0x46,0x9e,0x91,0x66,0x6e,0x37,0x43,0xeb,0x75,0x72,0x3e, - 0x1d,0xd4,0x53,0xfb,0x38,0xec,0x22,0xf5,0xba,0xa8,0xa7,0xfe,0xdd,0xac,0x65,0xcc, - 0x7a,0xa8,0x1f,0xec,0x3e,0xd6,0xd5,0xff,0x2c,0xfe,0x5a,0xef,0x98,0xa8,0x3e,0x8f, - 0x9f,0xda,0x17,0xf6,0xc5,0x0d,0xd2,0xbf,0x60,0x0f,0x11,0xab,0x79,0x86,0xb9,0x3f, - 0x79,0xf6,0x39,0xcc,0x9d,0x4d,0xf8,0xfd,0xb6,0xb8,0x11,0x6a,0xc4,0xdc,0xff,0xbf, - 0x60,0x6b,0x8e,0xbb,0x7c,0x8f,0x90,0x43,0xed,0x51,0x58,0x97,0xec,0xad,0x88,0xdf, - 0x38,0xac,0x88,0x9f,0xda,0x25,0x58,0xb7,0x54,0x9c,0x20,0x47,0xd8,0xe7,0x94,0xe9, - 0xe7,0x43,0xf6,0xa1,0xfd,0xbc,0x2a,0xf7,0x2f,0xce,0xb7,0x63,0xaf,0xbf,0x84,0xe8, - 0xfd,0xbe,0x41,0xef,0x67,0xe9,0x6f,0x51,0xa8,0xf6,0xa8,0x0a,0x73,0x86,0x3d,0x81, - 0xa9,0x96,0x31,0x61,0x7a,0xb6,0x4f,0xf1,0xd5,0xb5,0x9b,0xc2,0xb4,0x2f,0xf3,0xf4, - 0xae,0x8b,0xfc,0xea,0x57,0x83,0x6f,0x13,0xf7,0x8c,0xd8,0x9a,0x89,0x5b,0x20,0xae, - 0xc7,0xc4,0x2d,0xc2,0x37,0x89,0x5b,0x26,0x76,0x91,0x38,0xed,0xeb,0x0a,0x71,0x7d, - 0xc4,0xa9,0xee,0xe7,0xf0,0xef,0xe2,0xa3,0xbd,0x5e,0x85,0x69,0xaf,0x7f,0xca,0x09, - 0x34,0xd0,0xf6,0x47,0xfc,0x75,0xad,0x2e,0xa3,0xc1,0xb9,0xd4,0x8d,0xe6,0x17,0xd4, - 0xd4,0xdf,0x86,0xf8,0x2a,0x7b,0x09,0x1f,0x17,0x4b,0xf7,0xf4,0x01,0x16,0xfc,0x7e, - 0x4b,0x8e,0x90,0x4b,0xe7,0x1f,0xe2,0xa5,0x7e,0x9f,0xf0,0x49,0x11,0x53,0x37,0x1a, - 0x5e,0xa1,0x61,0xd0,0x68,0x78,0x0d,0x0f,0x1a,0xde,0xc0,0x82,0x86,0xa6,0xd1,0xa0, - 0x6b,0xeb,0x32,0x9a,0xd4,0x5d,0x37,0x1a,0xde,0x52,0x3b,0x66,0x34,0x6c,0xc0,0x83, - 0x86,0x8f,0xb0,0xe0,0xa7,0x1a,0x42,0xae,0xa6,0xd1,0xb0,0x8b,0x4f,0x83,0x98,0x75, - 0xa3,0xe1,0x1d,0x1a,0x86,0x8c,0x86,0x4d,0x78,0xd0,0xb0,0x05,0x0b,0x1a,0x76,0x8c, - 0x86,0x2d,0x7f,0x3f,0x9c,0x67,0x5a,0x77,0xdb,0xbf,0x8b,0xa8,0xee,0x7b,0x6a,0xef, - 0x9a,0xb7,0xa4,0x7b,0x0c,0xbe,0x3b,0x66,0x8f,0x9f,0xf1,0x6b,0x12,0xb7,0xcd,0x7e, - 0x46,0xfc,0xbd,0x8d,0xde,0x9a,0xda,0xfa,0xae,0xca,0xbc,0xa9,0x49,0xd9,0xdf,0x84, - 0x9f,0x23,0x9f,0xb2,0xb9,0x97,0xf7,0xd1,0x35,0x65,0xee,0xe5,0x03,0x78,0xb8,0xcf, - 0xd3,0xd4,0x55,0x7e,0x4f,0x98,0xbe,0xbf,0x47,0xe4,0x9b,0xa6,0x17,0x7a,0x1e,0x8f, - 0xe1,0xce,0x9f,0x5d,0xf4,0x6e,0x2b,0xf0,0x21,0x39,0x8f,0x02,0xf6,0x5f,0x51,0x79, - 0x4d,0xc6,0x3f,0xb4,0x82,0xd4,0xb9,0x94,0x07,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0x6b,0x4b,0x54,0x51, + 0x14,0x86,0xf7,0x5c,0x9c,0x19,0x8d,0xd2,0xb0,0x19,0x4d,0x23,0x2c,0x33,0xba,0x21, + 0x82,0x16,0x41,0x34,0xd0,0x87,0x28,0x70,0xcc,0xcb,0xa8,0x4c,0x6a,0x8d,0x93,0x0a, + 0x5a,0x3a,0xda,0x38,0xd5,0x50,0x99,0x89,0x35,0x95,0xe4,0x87,0x20,0xad,0xff,0xd0, + 0xef,0x8b,0x2e,0x10,0xb4,0xd6,0x39,0xcf,0x8e,0x95,0x07,0xf6,0x39,0x67,0x3d,0x7b, + 0xdd,0xde,0x7d,0x89,0x45,0xbb,0x93,0xce,0x45,0x5c,0x93,0x4b,0xb9,0xaf,0x2e,0x7c, + 0x8e,0xba,0xa8,0x90,0xf0,0xbb,0xd7,0xea,0x64,0xae,0xd1,0xe5,0x47,0x26,0x8b,0x37, + 0x0b,0xe3,0xc5,0xf5,0xc5,0xd2,0xfc,0x42,0xa5,0xb8,0x5e,0x5d,0x28,0xcf,0x2d,0x2d, + 0x17,0x17,0x6a,0x6b,0xab,0x95,0xaa,0xf8,0x1e,0x72,0x89,0x20,0xe6,0x56,0x2e,0x9f, + 0xeb,0x5d,0xaf,0xce,0xf7,0x0e,0x5c,0xee,0xd3,0x5c,0x47,0x5c,0x2c,0xc8,0xa9,0x73, + 0xcd,0x2e,0xe9,0xe2,0xf2,0xd5,0xb1,0x52,0x5a,0x2a,0xbb,0x80,0x39,0x97,0x93,0xd1, + 0x22,0x7e,0xca,0x93,0x9a,0x43,0xfe,0x9a,0x83,0x9c,0xe1,0xfc,0x6d,0xd7,0xe0,0xda, + 0xe8,0xad,0x9b,0xaf,0x67,0x11,0x58,0xca,0xb0,0x28,0xac,0xc5,0xb0,0x18,0xac,0xdd, + 0xb0,0x38,0xec,0x84,0x61,0x0d,0xb0,0x2e,0xc3,0x12,0xb0,0x33,0x86,0x25,0x61,0xe7, + 0x0c,0x4b,0xc1,0x2e,0x19,0xd6,0x08,0xeb,0x33,0xac,0x09,0x36,0x10,0x68,0x8d,0xfd, + 0xeb,0x59,0x75,0xe7,0xd0,0xbd,0xdf,0x1a,0xda,0xc3,0xf2,0x7f,0x1a,0xcd,0xde,0x3e, + 0x85,0x6e,0xb5,0xf3,0x07,0xe6,0xf3,0xcc,0x6b,0xbe,0x56,0x79,0x47,0x03,0x3b,0x16, + 0xe8,0xd7,0xff,0x8c,0xfc,0x25,0xd0,0xd7,0x26,0xfe,0x49,0xf4,0x45,0xb1,0x0f,0x63, + 0xc7,0x03,0x9f,0xb8,0xec,0x5f,0x58,0x4b,0xf9,0x35,0xec,0x66,0x58,0x5a,0xec,0x34, + 0xb9,0xbc,0x9d,0xc1,0xd6,0xe7,0xa4,0x44,0xf9,0xb5,0xf2,0x23,0x6d,0x46,0x82,0x6f, + 0xc6,0x0c,0xad,0xd9,0xce,0xba,0xb5,0x51,0x53,0xed,0xe3,0xb0,0x8b,0xd4,0xec,0xa0, + 0xa6,0xfa,0x77,0x32,0x97,0x34,0xf3,0xbe,0x07,0x6f,0xf7,0xb0,0x3f,0xea,0x7f,0x16, + 0x7f,0xad,0x77,0x4c,0x94,0x9f,0xc7,0x4f,0xed,0x0b,0x07,0xe2,0xfa,0x0f,0xd4,0xcd, + 0xb2,0x7f,0x9a,0x67,0x90,0x73,0x95,0xa6,0xcf,0x41,0xce,0x72,0x2c,0xe8,0xb7,0xd1, + 0x0d,0x51,0x23,0xe2,0xfe,0x7f,0xbc,0xad,0x39,0xee,0xf0,0x3f,0x44,0x0e,0xb5,0x87, + 0x61,0x1d,0xd2,0xdb,0x28,0x7e,0x63,0xb0,0x51,0xfc,0xd4,0xce,0xc3,0x3a,0xa5,0xe2, + 0x04,0x39,0x7c,0x9f,0x05,0xf6,0xd4,0xdb,0x33,0xf4,0xa5,0xb9,0xee,0xa1,0x29,0xcd, + 0x9e,0x97,0xe8,0x53,0xf7,0xfc,0x8a,0x9c,0xd1,0x28,0xff,0x8e,0x98,0x9f,0x42,0xf4, + 0x5e,0x5c,0xe7,0x7c,0x2c,0x72,0x06,0x46,0x85,0xea,0x1e,0x3e,0x84,0x39,0xc3,0x1e, + 0xc1,0x54,0xeb,0x88,0x30,0xdd,0x9b,0x65,0x7c,0x75,0xee,0x86,0x30,0xdd,0xb7,0x15, + 0xf6,0xb6,0x83,0xfc,0xea,0x57,0x86,0xbf,0x25,0x6e,0x8d,0xd8,0xb2,0x89,0x7b,0x4c, + 0x5c,0x97,0x89,0xab,0xc0,0xb7,0x89,0xab,0x12,0x5b,0x21,0x4e,0xf7,0xfd,0x09,0x71, + 0x3d,0xc4,0xa9,0xee,0xa7,0xf0,0x6f,0xe2,0xa3,0x67,0xe1,0x19,0x4c,0xcf,0xc2,0x0f, + 0x59,0x81,0x0d,0xb4,0xfd,0x16,0x7f,0x9d,0xab,0xc9,0xd8,0x60,0x5d,0x6a,0x46,0xf3, + 0x73,0x6a,0xea,0xb3,0x29,0xbe,0xca,0x5e,0xc0,0xc7,0xc4,0xd2,0x9e,0x3e,0xc1,0xbc, + 0xdf,0x2f,0xc9,0xe1,0x73,0xe9,0xf7,0xbb,0x78,0xa9,0xdf,0x1e,0x3e,0x0d,0xc4,0xd4, + 0x8c,0x86,0x57,0x68,0xe8,0x37,0x1a,0x36,0xe1,0x5e,0xc3,0x6b,0x98,0xd7,0x50,0x37, + 0x1a,0x74,0x6e,0x4b,0x46,0x9d,0xba,0x5b,0x46,0xc3,0x36,0xb5,0x23,0x46,0xc3,0x1b, + 0xb8,0xd7,0xf0,0x19,0xe6,0xfd,0x54,0x83,0xcf,0x55,0x37,0x1a,0xf6,0xf1,0xd9,0x20, + 0x66,0xcb,0x68,0x78,0x87,0x86,0xac,0xd1,0xf0,0x1e,0xee,0x35,0x7c,0x80,0x79,0x0d, + 0xbb,0x46,0x83,0xce,0xed,0xc8,0xd8,0xa5,0xee,0x4e,0x70,0x6f,0xc2,0xba,0x1f,0xa9, + 0xbd,0x6f,0xee,0x9a,0xf6,0xe8,0x7d,0x77,0x4d,0x8f,0x5f,0xf0,0xab,0x13,0xb7,0x43, + 0x3f,0x43,0xc1,0xb9,0x0d,0xef,0xa2,0xda,0x7a,0xef,0xc6,0xb9,0x73,0x93,0xd2,0xdf, + 0x44,0xf0,0x0d,0x7d,0xc6,0xcd,0xb9,0xbc,0x8b,0xae,0x82,0x39,0x97,0x53,0x70,0x7f, + 0x9e,0xa7,0xa9,0x3b,0x45,0x9c,0xde,0xc7,0xfb,0xc4,0xcd,0x10,0xa7,0x77,0xb3,0x08, + 0x5f,0x65,0x1f,0x66,0x61,0x05,0xc9,0xa2,0x77,0xf6,0x01,0x3d,0x4c,0x73,0xd7,0x67, + 0xd9,0x47,0x5d,0xcb,0x39,0xe6,0xf5,0x79,0x49,0xbe,0x79,0x78,0x56,0xd6,0x32,0x87, + 0xfd,0x47,0x56,0xe8,0xaa,0x8c,0xbf,0xd0,0xcc,0x9b,0x6d,0x08,0x08,0x00,0x00 }; // Generated from: @@ -77,6 +79,7 @@ constexpr uint8_t kBlitResolve_frag_00000010[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -113,6 +116,6 @@ constexpr uint8_t kBlitResolve_frag_00000010[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// gl_FragStencilRefARB = int(texture(usampler2D(stencil, blitSampler), srcImageCoords * params . invSrcExtent). x); +// gl_FragStencilRefARB = int(textureLod(usampler2D(stencil, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip). x); // // } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000011.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000011.inc index acfd755536d..da5c1855395 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000011.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000011.inc @@ -10,56 +10,57 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000011[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0xeb,0x4b,0x94,0x41, - 0x14,0xc6,0x67,0xf7,0x5d,0x77,0xb5,0x9b,0x86,0xad,0x9a,0x46,0x58,0x66,0x74,0x43, - 0x04,0x2b,0x82,0x48,0xe8,0x43,0x14,0xb8,0xa6,0xb6,0x6a,0x66,0xd6,0x66,0xee,0x96, - 0x82,0xa9,0xad,0x9b,0x58,0x49,0x61,0x2a,0x85,0x95,0xe4,0x07,0xa3,0xac,0xff,0xa0, - 0xbf,0x2f,0xba,0x40,0xd0,0x39,0xf3,0xfe,0x46,0x0e,0x2e,0xcc,0xce,0x9c,0x67,0x9e, - 0x73,0x79,0xde,0x73,0x26,0x4a,0xb6,0x65,0x9c,0x4b,0xb8,0x3d,0xae,0xda,0x7d,0x77, - 0xf1,0xef,0xa0,0x4b,0x0a,0x12,0xef,0x5b,0xf5,0x4e,0xee,0x6a,0x5c,0xbe,0x7f,0xb8, - 0x70,0x6d,0x64,0xb0,0x30,0x3f,0x39,0x5e,0x2c,0x95,0x0b,0xf3,0x95,0xd2,0xcc,0xc4, - 0xd4,0x74,0xa1,0xb4,0x38,0x37,0x5b,0xae,0x08,0x77,0xaf,0x4b,0x7b,0x9f,0xeb,0xb9, - 0x7c,0xae,0x63,0xbe,0x52,0xec,0x38,0x7f,0xa1,0x53,0x63,0x1d,0x70,0x91,0x8f,0xa9, - 0x77,0xb5,0x2e,0xe3,0x52,0xb2,0xeb,0x7a,0x32,0x3e,0x35,0xe3,0x3c,0xe6,0x5c,0x4e, - 0x56,0x9d,0xf0,0x14,0xcf,0x68,0x0c,0x39,0xd5,0xfa,0x98,0xf1,0xfd,0x0d,0x57,0xe5, - 0x1a,0xa9,0xad,0x8d,0x3d,0x60,0x09,0xb0,0x6a,0x83,0x25,0xc1,0xea,0x0c,0x16,0x81, - 0x35,0x19,0x2c,0x05,0x76,0xc4,0x60,0x55,0x60,0xad,0x06,0x4b,0x83,0x9d,0x30,0x58, - 0x06,0xec,0x94,0xc1,0xaa,0xc1,0xce,0x19,0xac,0x06,0xac,0xd3,0xeb,0x8a,0x76,0xea, - 0x53,0x8d,0x39,0x34,0x7e,0xae,0x8f,0xed,0x3e,0x39,0x1f,0x47,0x5f,0xb0,0x8f,0xa1, - 0x51,0xed,0xfc,0xae,0xfb,0x3c,0xf7,0x1a,0xaf,0x5e,0xfe,0x93,0xde,0x8e,0xbc,0x56, - 0x3d,0x37,0xc8,0x29,0x8d,0x96,0x46,0xe1,0x67,0xd0,0x92,0xc4,0xde,0x8f,0x9d,0xf2, - 0x9c,0x94,0xf4,0x2a,0xce,0xa5,0xf8,0x65,0xec,0x5a,0xb0,0xac,0xd8,0x59,0x62,0x05, - 0xbb,0x01,0x5b,0x7f,0x47,0xdd,0xbe,0x9d,0xef,0x12,0x56,0x96,0x95,0x66,0x6f,0x30, - 0x4b,0xf3,0x35,0xf1,0x7d,0x1a,0xc9,0xa7,0xf6,0x61,0xb0,0xb3,0xe4,0x6b,0x26,0x9f, - 0xf2,0x5b,0xb8,0xcb,0x98,0xfb,0x90,0x3f,0xd8,0xed,0xdc,0x2b,0xff,0x24,0x7c,0xcd, - 0x77,0x48,0x54,0x9f,0x86,0xa7,0xf6,0x99,0x5d,0x7e,0x5d,0xf4,0x2f,0xd8,0xdd,0xf8, - 0x6a,0x9c,0x1e,0xe6,0x27,0x4b,0x9d,0x3d,0xcc,0x6c,0xe4,0xeb,0xad,0x71,0xbd,0xe4, - 0x48,0x10,0x73,0xf7,0xae,0x31,0x6e,0x72,0xee,0x25,0x86,0xda,0x7d,0x60,0xcd,0x52, - 0xdb,0x00,0xbc,0x5b,0x60,0x03,0xf0,0xd4,0xce,0x83,0xb5,0x48,0xc6,0x21,0x62,0x84, - 0x3a,0x47,0xe8,0x67,0xb0,0xc7,0xa8,0x4b,0x63,0xdd,0x43,0x43,0x96,0x7e,0x8f,0xd3, - 0x8b,0x08,0xbb,0x44,0xdd,0xda,0xff,0x8b,0x32,0xaf,0x49,0xce,0x0e,0xce,0x6f,0x41, - 0xf4,0x3d,0x5c,0x61,0x56,0xa6,0x99,0x87,0x01,0x41,0x35,0xce,0x0c,0x98,0x33,0xd8, - 0x2c,0x98,0x6a,0xef,0x17,0x4c,0x7b,0x31,0x07,0x57,0xef,0xae,0x0a,0xa6,0x7d,0x7c, - 0x4a,0xaf,0x9b,0x89,0xaf,0xbc,0x32,0xf8,0x1a,0x7e,0x15,0x7c,0xcb,0xc6,0xef,0x19, - 0x7e,0xad,0xc6,0x6f,0x01,0x7c,0x05,0xbf,0x45,0x7c,0x17,0xf0,0xd3,0x39,0x78,0x8e, - 0x5f,0x3b,0x7e,0xaa,0xfb,0x05,0xf8,0x0f,0xe1,0xe8,0x6c,0xbc,0x04,0xd3,0xd9,0xf8, - 0x25,0x5f,0x60,0x19,0x6d,0x7f,0x85,0xaf,0x77,0x4b,0xb2,0x96,0xf9,0x2e,0x4b,0x46, - 0xf3,0x2b,0x72,0xea,0xef,0xb5,0x70,0xd3,0x7e,0x8f,0xf1,0x5b,0x62,0x69,0x4d,0x5b, - 0x60,0x81,0xf7,0x47,0x62,0x84,0x58,0xba,0xff,0x14,0x96,0xf2,0xbe,0xc2,0xa9,0xc2, - 0x67,0xc9,0x68,0x78,0x83,0x86,0x2e,0xa3,0x61,0x05,0x3c,0x68,0x58,0x05,0x0b,0x1a, - 0xd6,0x8d,0x86,0x55,0xff,0x6d,0x9d,0xc7,0x34,0xef,0x9a,0xd1,0xf0,0x96,0xdc,0x09, - 0xa3,0xe1,0x1d,0x78,0xd0,0xf0,0x05,0x2c,0xf0,0x54,0x43,0x88,0xb5,0x6e,0x34,0x6c, - 0xc3,0x59,0xc6,0x67,0xcd,0x68,0x78,0x8f,0x86,0x6e,0xa3,0xe1,0x03,0x78,0xd0,0xf0, - 0x11,0x2c,0x68,0xd8,0x34,0x1a,0xf4,0x6e,0x43,0xd6,0x26,0x79,0x37,0xfc,0x3b,0x8a, - 0xf3,0x7e,0x22,0xf7,0xb6,0x79,0x7b,0x5a,0x63,0xe0,0x6e,0x9a,0x1a,0xbf,0xc1,0x5b, - 0xc7,0x6f,0x83,0x7a,0x7a,0xfd,0xdc,0xc6,0x6f,0x53,0x6d,0x7d,0x87,0x83,0xbc,0xc1, - 0x61,0xa9,0x6f,0xc8,0xef,0x31,0x67,0xd0,0xcc,0xe5,0x1d,0x74,0x8d,0x98,0xb9,0x1c, - 0x05,0x0f,0xf3,0x7c,0x97,0xbc,0xa3,0xf8,0xe9,0xfb,0xbc,0x8f,0xdf,0x18,0x7e,0xfa, - 0x56,0x0b,0xe0,0xb3,0xf4,0xe1,0x01,0x58,0xe8,0xd5,0x43,0x62,0xd9,0x77,0x37,0x01, - 0x16,0xbf,0xbb,0xb4,0x7f,0xeb,0x45,0xb8,0x13,0xc4,0xb8,0x2d,0x5c,0x7d,0xf3,0x8f, - 0xd0,0x50,0xc4,0x5f,0x7b,0xf0,0x18,0xdc,0xf9,0x99,0x8b,0xeb,0x98,0x04,0xef,0x96, - 0x1e,0xe4,0xb0,0xff,0x49,0x86,0x4b,0xb2,0xfe,0x03,0xfe,0xcd,0x99,0xae,0x38,0x08, - 0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x94,0xeb,0x4b,0x94,0x41, + 0x14,0x87,0x67,0x2f,0xee,0xaa,0x51,0x1a,0xb6,0x6a,0x1a,0x61,0x99,0xd1,0x0d,0x11, + 0xb4,0x08,0x22,0xa1,0x0f,0x51,0xe0,0x9a,0x97,0x55,0x31,0xb3,0x36,0x73,0xb7,0xb4, + 0x4c,0xc5,0x35,0x31,0xe9,0x22,0x89,0x95,0x14,0x5b,0x49,0x06,0x41,0xb7,0xef,0xfd, + 0x7d,0xd1,0x05,0x82,0xce,0x99,0xf7,0x99,0x38,0xac,0x30,0xbe,0xef,0x79,0xe6,0xdc, + 0x7e,0xef,0x99,0xd9,0x44,0xbc,0x3d,0xed,0x5c,0xcc,0xd5,0xba,0x6a,0xf7,0xcd,0x45, + 0x7f,0x7b,0x5d,0x5c,0x48,0xf4,0xdc,0x69,0x70,0xb2,0x57,0xe3,0x72,0x83,0x63,0xf9, + 0x8b,0xe3,0x23,0xf9,0xd2,0xcc,0x54,0xa1,0xb8,0x94,0x2f,0x2d,0x17,0xe7,0xa7,0x67, + 0xe7,0xf2,0xc5,0xd5,0xc5,0x85,0xa5,0x65,0xf1,0xdd,0xe5,0x52,0x3e,0xe6,0x52,0x36, + 0x97,0xed,0x2c,0x2d,0x17,0x3a,0x7b,0x4e,0x77,0x69,0xae,0x3d,0x2e,0xe1,0x73,0xea, + 0x5e,0x9d,0x4b,0xbb,0xa4,0x3c,0x75,0xdd,0x9f,0x9a,0x9d,0x77,0x9e,0x39,0x97,0x95, + 0x55,0x2f,0x7e,0xca,0xd3,0x9a,0x43,0xde,0xea,0x7c,0xce,0x68,0xff,0xb2,0xab,0x72, + 0x4d,0xf4,0xd6,0xce,0x33,0xb0,0x18,0xac,0xda,0xb0,0x38,0xac,0xde,0xb0,0x04,0xac, + 0xd9,0xb0,0x24,0xec,0x80,0x61,0x55,0xb0,0x36,0xc3,0x52,0xb0,0x23,0x86,0xa5,0x61, + 0xc7,0x0c,0xab,0x86,0x9d,0x32,0xac,0x06,0xd6,0x65,0x58,0x2d,0xac,0xc7,0x6b,0x4d, + 0xfc,0xef,0x59,0x75,0x67,0xd1,0xfd,0xa1,0x21,0xb2,0x07,0xe4,0xfd,0x30,0x9a,0x83, + 0x7d,0x08,0xdd,0x6a,0xe7,0x2a,0xf6,0x73,0xec,0x6b,0xbe,0x06,0xf9,0x1f,0xf7,0x76, + 0xc2,0xeb,0xd7,0xf7,0x46,0x79,0x4b,0xa1,0xaf,0x49,0xfc,0xd3,0xe8,0x8b,0x63,0xef, + 0xc6,0x4e,0x7a,0x9f,0xa4,0xcc,0x2f,0xaa,0xa5,0xfc,0x1c,0x76,0x1d,0x2c,0x23,0x76, + 0x86,0x5c,0xc1,0x6e,0xc4,0xd6,0xbf,0x83,0x12,0x15,0xbe,0x55,0x58,0x19,0xb3,0x52, + 0x3c,0x1b,0xcd,0xd2,0x9a,0xcd,0x7c,0xb7,0x26,0x6a,0xaa,0xbd,0x1f,0x76,0x92,0x9a, + 0x2d,0xd4,0x54,0xff,0x56,0xf6,0xd2,0x66,0x3f,0xf4,0x10,0xec,0x0e,0xe6,0xa3,0xfe, + 0x47,0xf1,0xd7,0x7a,0xfb,0x44,0xf9,0x71,0xfc,0xd4,0x3e,0x51,0x11,0xd7,0x5d,0x51, + 0xb7,0x97,0xf9,0x69,0x9e,0x3e,0xce,0x55,0x86,0x3e,0xfb,0x38,0xcb,0x09,0xdf,0x6f, + 0x8d,0xeb,0xa7,0x46,0x8c,0x9c,0x95,0x4f,0xcd,0x71,0x85,0xf7,0x7e,0x72,0xa8,0x3d, + 0x00,0x6b,0x91,0xde,0x86,0xf0,0x1b,0x86,0x0d,0xe1,0xa7,0x76,0x0e,0xd6,0x2a,0x15, + 0x47,0xc9,0x11,0xfa,0x1c,0x67,0xa6,0xc1,0x9e,0x34,0x33,0xbd,0x8e,0xa6,0x0c,0x33, + 0x9f,0x62,0x16,0x09,0xe3,0x5f,0xc4,0xd6,0xfd,0x59,0x74,0x68,0xfc,0x19,0x39,0xc3, + 0x71,0xde,0x1d,0x3e,0xbf,0x84,0xe8,0xbd,0x39,0xcf,0xf9,0x59,0xe4,0x8c,0x0c,0x09, + 0xd5,0xbc,0x4b,0x30,0x67,0x58,0x09,0xa6,0xdf,0x62,0x50,0x98,0xce,0x6e,0x19,0x5f, + 0xdd,0xbb,0x20,0x4c,0xe7,0xfa,0x80,0xd9,0xb7,0x90,0x5f,0xfd,0x56,0xe0,0x9b,0xc4, + 0xad,0x12,0xbb,0x62,0xe2,0x1e,0x12,0xd7,0x66,0xe2,0xd6,0xe0,0x1b,0xc4,0x3d,0x22, + 0x76,0x8d,0x38,0x3d,0x17,0x8f,0x89,0xeb,0x20,0x4e,0x75,0x3f,0x81,0x7f,0x17,0x1f, + 0x3d,0x2b,0x4f,0x61,0x7a,0x56,0x7e,0xca,0x17,0xd8,0x44,0xdb,0x1f,0xf1,0xd7,0xbd, + 0x75,0xdf,0x5b,0xf4,0x5d,0xd6,0x8d,0xe6,0x67,0xd4,0x74,0x3e,0x47,0xd2,0xb3,0x0d, + 0xf8,0xb0,0x58,0xda,0xd3,0x47,0x58,0xf0,0xfb,0x2d,0x39,0x42,0x2e,0x7d,0xfe,0x10, + 0x2f,0xf5,0xfb,0x8c,0x4f,0x15,0x31,0xeb,0x46,0xc3,0x73,0x34,0x74,0x1b,0x0d,0x2f, + 0xe0,0x41,0xc3,0x4b,0x58,0xd0,0x50,0x36,0x1a,0x74,0x6f,0x4b,0x56,0x99,0xba,0x5b, + 0x46,0xc3,0x2b,0x6a,0xc7,0x8c,0x86,0xd7,0xf0,0xa0,0xe1,0x13,0x2c,0xf8,0xa9,0x86, + 0x90,0xab,0x6c,0x34,0x7c,0xc1,0x67,0x93,0x98,0x2d,0xa3,0xe1,0x0d,0x1a,0x7a,0x8d, + 0x86,0xb7,0xf0,0xa0,0xe1,0x1d,0x2c,0x68,0xd8,0x31,0x1a,0x74,0x6f,0x5b,0xd6,0x0e, + 0x75,0xb7,0xfd,0xbd,0x8a,0xea,0xbe,0xa7,0xf6,0x17,0x73,0x17,0xb5,0xc7,0xe0,0xbb, + 0x63,0x7a,0xfc,0x8a,0x5f,0x99,0xb8,0x6d,0xfa,0xe9,0xf7,0xe7,0x36,0xba,0xab,0x6a, + 0xeb,0xbd,0x1c,0xe1,0x4e,0x8e,0x49,0x7f,0xa3,0xfe,0x19,0xf9,0x8c,0x98,0x73,0x79, + 0x15,0x5d,0xe3,0xe6,0x5c,0x4e,0xc0,0xc3,0x79,0xbe,0x46,0xdd,0x09,0xe2,0xf4,0xbe, + 0xde,0x20,0x6e,0x92,0x38,0xbd,0xa3,0x79,0xf8,0x02,0x73,0xb8,0x09,0x0b,0xb3,0xba, + 0x45,0x2e,0x7b,0xef,0xa6,0x61,0xd1,0xbd,0x4b,0xf9,0xbb,0x5f,0xc0,0x77,0x9a,0x1c, + 0xa1,0xe6,0x6d,0x6a,0x16,0x4d,0xcd,0x3b,0xf0,0x50,0x73,0x06,0x36,0x2e,0x9d,0xeb, + 0xef,0xc4,0x5d,0x74,0x17,0xf8,0xfd,0x99,0xa1,0xb6,0xce,0xef,0x1e,0xfb,0xce,0x9f, + 0xdd,0x28,0xdf,0x1c,0xbc,0x57,0xe6,0x97,0xc5,0xfe,0x2b,0xdd,0x9d,0x95,0xf5,0x0f, + 0xf2,0x78,0x8d,0x50,0x9c,0x08,0x00,0x00 }; // Generated from: @@ -81,6 +82,7 @@ constexpr uint8_t kBlitResolve_frag_00000011[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -117,6 +119,6 @@ constexpr uint8_t kBlitResolve_frag_00000011[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// gl_FragStencilRefARB = int(texture(usampler2DArray(stencil, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)). x); +// gl_FragStencilRefARB = int(textureLod(usampler2DArray(stencil, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip). x); // // } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000012.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000012.inc index 81b66b26d4a..008c232d286 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000012.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000012.inc @@ -10,48 +10,48 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000012[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x4d,0x52,0xdb,0x6e,0x12,0x51, - 0x14,0xdd,0xcc,0x14,0x06,0x54,0x5a,0x08,0x02,0xd6,0x18,0x8b,0xe2,0x83,0x89,0xb6, - 0xe9,0x83,0x1a,0x12,0xa3,0xd1,0x07,0xb0,0x35,0x68,0x55,0x7a,0xf1,0xd6,0x8c,0xa5, - 0x40,0x4a,0x68,0x41,0x81,0x18,0xb5,0xea,0x83,0xff,0xa0,0x3f,0xe1,0xf7,0x19,0x2f, - 0x89,0x89,0x7b,0xcd,0xac,0x83,0x7b,0x92,0x33,0xe7,0xec,0xb5,0xd7,0xbe,0xac,0x7d, - 0x8e,0xef,0x55,0x03,0x91,0x84,0x9c,0x90,0xb4,0x7c,0x92,0xf8,0xcb,0x8b,0xa7,0x48, - 0xbc,0x7f,0x2d,0x88,0xfa,0x32,0xd2,0x7a,0xb4,0x1d,0xd6,0x9f,0x6e,0x86,0x93,0x83, - 0xbd,0x4e,0x77,0x1c,0x4e,0xa6,0xdd,0xe1,0x7e,0xff,0x30,0xec,0xbe,0x7b,0x3d,0x1a, - 0x4f,0x95,0x7b,0x52,0x52,0x51,0xcc,0xbd,0x66,0xab,0xb9,0x32,0x99,0x76,0x56,0xae, - 0x5d,0x5f,0x45,0xae,0x79,0xf1,0xa3,0x9c,0xf0,0x2d,0x48,0x20,0x73,0xba,0x63,0x1d, - 0xed,0xf5,0x87,0xc0,0x73,0xba,0x1a,0xd1,0xee,0x47,0x78,0x80,0x1c,0x7a,0xca,0x45, - 0x39,0x11,0x23,0xb2,0x26,0x49,0x29,0xb1,0xb7,0x2a,0x77,0x87,0x25,0x88,0xa5,0x0d, - 0xe6,0x11,0xcb,0x19,0xcc,0x27,0x76,0xc6,0x60,0x73,0xc4,0xce,0x19,0x2c,0x49,0xac, - 0x62,0xb0,0x14,0xb1,0x4b,0x06,0x0b,0x88,0x5d,0x36,0x58,0x9a,0xd8,0x55,0x83,0x65, - 0x88,0xad,0x46,0xba,0xfc,0x59,0x7f,0xd0,0xd8,0xa0,0xc6,0x6f,0x85,0xd8,0x5e,0xd7, - 0xf3,0x45,0xea,0x73,0xf6,0x05,0x6a,0x2c,0x68,0x94,0x17,0xd9,0x7e,0xa4,0x05,0xe7, - 0xa2,0x72,0x52,0xec,0x15,0x9c,0xb2,0xda,0x01,0xfb,0x85,0xbf,0xa4,0xcc,0x2c,0xfd, - 0xf0,0xcd,0xeb,0x9e,0xa5,0xee,0x8a,0xfe,0x17,0x18,0x07,0xfc,0x26,0xed,0x9c,0xc9, - 0x95,0x27,0xdf,0xd5,0x2a,0x32,0x17,0xbe,0xf3,0x72,0x6a,0x36,0x87,0x3c,0x57,0x8a, - 0x2b,0xcb,0xbd,0x68,0x16,0xea,0x95,0x39,0x8f,0x12,0xeb,0x95,0x79,0x1f,0xc0,0xae, - 0x50,0xcb,0x22,0xf3,0x83,0x7f,0x96,0xbe,0xc0,0xf8,0x97,0x68,0xc3,0x5f,0xa1,0x1f, - 0xf9,0x4f,0x6b,0x97,0x55,0xf2,0x8a,0xbc,0x2b,0x31,0x71,0xcb,0xbc,0x1f,0x67,0xd7, - 0x18,0x8b,0x3c,0x75,0xbe,0x8f,0x14,0xfb,0xaa,0xf3,0x4d,0xfa,0x51,0x3f,0x19,0xbd, - 0x8b,0xb8,0x46,0x42,0xfe,0x7f,0x09,0x63,0x23,0xc7,0xda,0xec,0xde,0xe2,0x1c,0xb0, - 0xd7,0x89,0x61,0x96,0x4d,0xe6,0xc0,0xec,0x6f,0xe8,0xdb,0xf0,0x78,0x16,0xd6,0xf9, - 0xa5,0x08,0xde,0xde,0x2d,0xde,0x53,0x8b,0x77,0xb1,0xa1,0x6a,0x31,0xdb,0x4d,0x62, - 0x2d,0x53,0x7f,0xc8,0xfb,0xde,0xa2,0xff,0xae,0x66,0xc0,0xcc,0xb6,0x39,0xd7,0x45, - 0xe6,0x03,0x67,0x87,0xf8,0x17,0xe5,0xc0,0x7e,0xc6,0xb8,0x1d,0xc6,0x61,0x96,0xcf, - 0x19,0xb7,0xc4,0x38,0xf4,0xfb,0x82,0xf8,0x77,0xe5,0x60,0xbe,0x2f,0x89,0x61,0xbe, - 0x3f,0xb5,0xf3,0x36,0xfb,0xf9,0xa3,0x7c,0xf8,0x76,0x75,0xb5,0xa9,0x07,0xe7,0xc7, - 0x1a,0x87,0xb9,0x86,0xac,0x89,0xef,0x33,0xef,0xe0,0x15,0xf1,0x27,0x6a,0xa1,0xa7, - 0xb7,0xc4,0x1c,0xef,0xb7,0xe6,0x70,0xb9,0xb0,0xff,0x50,0x16,0x78,0x1f,0xc8,0x49, - 0x32,0x66,0xd7,0x68,0xd8,0xa7,0x86,0x65,0xa3,0xa1,0x43,0xdc,0x69,0xe8,0x12,0x73, - 0x1a,0x06,0x46,0x03,0x7c,0x3d,0x5d,0x03,0xd6,0xed,0x19,0x0d,0x07,0xac,0x9d,0x30, - 0x1a,0xfa,0xc4,0x9d,0x86,0xf7,0xc4,0x1c,0x0f,0x1a,0x5c,0xae,0x81,0xd1,0x70,0x4c, - 0x4e,0x9b,0x31,0x3d,0xa3,0xe1,0x90,0x1a,0x6a,0x46,0xc3,0x11,0x71,0xa7,0x61,0x48, - 0xcc,0x69,0x18,0x1b,0x0d,0xf0,0x8d,0x74,0x8d,0x59,0x77,0xc4,0x77,0x84,0xba,0x6f, - 0x58,0xfb,0xd8,0xbc,0x5f,0xf4,0xe8,0xb8,0x63,0xd3,0xe3,0x47,0xf2,0x06,0x8c,0x1b, - 0xb1,0x1f,0xbc,0xf1,0xfb,0x7c,0xdf,0xa1,0x32,0xf1,0xb6,0x1f,0x10,0x43,0xcc,0x1d, - 0xbe,0x3d,0xcc,0x0d,0xbd,0x3f,0xa4,0x5f,0x22,0x7f,0x3c,0xb7,0x0d,0xe2,0xb7,0xb5, - 0xf7,0x06,0xed,0xbf,0xda,0x51,0x4d,0xd7,0x3f,0x2c,0xe3,0xe1,0x28,0x94,0x06,0x00, - 0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x92,0xdb,0x6e,0x12,0x51, + 0x14,0x86,0x17,0x33,0x85,0x81,0x1a,0x5a,0x08,0x02,0xd6,0x18,0x8b,0xe2,0x85,0x89, + 0xb6,0xe9,0x45,0x35,0x24,0x46,0xa3,0x17,0x60,0x6b,0xd0,0xaa,0xf4,0xe0,0xa9,0x19, + 0x4b,0x81,0x94,0xd0,0x82,0x02,0x31,0x6a,0xd5,0x0b,0xdf,0x41,0x5f,0xc2,0xe7,0x33, + 0x1e,0x12,0x13,0xd7,0x3f,0xf3,0xef,0xba,0x22,0xc9,0x66,0xcf,0xfe,0xd6,0xf1,0x5f, + 0x7b,0xfb,0x5e,0x35,0x10,0x49,0xc8,0xac,0xa4,0xe5,0xa3,0xc4,0xbf,0xbc,0x78,0x4a, + 0xe2,0xfd,0x4b,0x41,0xd4,0x96,0x91,0xd6,0xc3,0xed,0xb0,0xfe,0x64,0x33,0x9c,0x1c, + 0xec,0x75,0xba,0xe3,0x70,0x32,0xed,0x0e,0xf7,0xfb,0x87,0x61,0xf7,0xed,0xab,0xd1, + 0x78,0xaa,0xbe,0xa7,0x24,0x15,0xc5,0xdc,0x6d,0xb6,0x9a,0xcb,0x93,0x69,0x67,0x79, + 0xf5,0xda,0x0a,0x72,0xcd,0x89,0x1f,0xe5,0x84,0x6d,0x5e,0x02,0x99,0xd1,0x1d,0xeb, + 0x68,0xaf,0x3f,0x04,0xcf,0xe9,0x6a,0x44,0xbb,0x1f,0xf1,0x00,0x39,0xf4,0x2b,0x17, + 0xe5,0x44,0x8c,0xc8,0x9a,0x24,0xa5,0xc4,0xde,0xaa,0xdc,0x1d,0x4b,0x90,0xa5,0x0d, + 0xf3,0xc8,0x72,0x86,0xf9,0x64,0x67,0x0c,0x9b,0x21,0x3b,0x67,0x58,0x92,0xac,0x62, + 0x58,0x8a,0xec,0x92,0x61,0x01,0xd9,0x65,0xc3,0xd2,0x64,0x57,0x0d,0xcb,0x90,0xad, + 0x18,0x36,0x4b,0xb6,0x1a,0x69,0xf5,0x4f,0x7a,0x86,0xee,0x06,0x75,0x7f,0x2d,0xc4, + 0xe7,0x75,0xfd,0xbe,0x48,0xcd,0xee,0x7c,0x81,0xba,0x0b,0x1a,0xe5,0x45,0x67,0x3f, + 0xd2,0x87,0xef,0xa2,0xfa,0xa4,0xd8,0x3f,0x7c,0xca,0x7a,0x0e,0xa8,0x01,0xf6,0x92, + 0x7a,0x66,0x69,0x87,0x6d,0x4e,0xf7,0x2c,0x67,0x51,0xd1,0xff,0x79,0xc6,0x81,0xdf, + 0xe0,0x39,0x67,0x72,0xe5,0xe9,0xef,0x6a,0x15,0x99,0x0b,0xbf,0xf3,0x6a,0x71,0xb3, + 0xc9,0x73,0xa5,0xcc,0xca,0x72,0x2f,0x9a,0x85,0x9a,0x65,0xce,0xa9,0xc4,0x9a,0x65, + 0xde,0x13,0xd8,0x15,0xea,0x59,0x60,0x0d,0xf8,0x9f,0xa5,0x2d,0x30,0xf6,0x45,0xce, + 0x1f,0xf6,0x0a,0xed,0xc8,0x7f,0x5a,0x3b,0xad,0xd2,0xaf,0xc8,0x3b,0x14,0x13,0xb7, + 0xf4,0x5f,0x9d,0x1a,0xef,0x07,0x79,0xea,0x7c,0x37,0x29,0xf6,0x55,0xe7,0x5b,0xf5, + 0xa3,0x7e,0x32,0x7a,0x1f,0x71,0x8d,0x84,0xfc,0xfb,0x25,0xcc,0x19,0x39,0xd6,0x4e, + 0xee,0x2e,0xce,0x81,0xf3,0x3a,0x19,0xe6,0xd9,0x64,0x0e,0xcc,0xff,0xba,0xbe,0x0f, + 0x8f,0xdf,0xc2,0x3a,0x3f,0x95,0xe0,0x4d,0xde,0xe4,0x5d,0xb5,0x78,0x1f,0x1b,0xaa, + 0x1e,0xf3,0xdd,0x24,0x6b,0x99,0xfa,0x43,0xde,0xf9,0x16,0xed,0x77,0x34,0x03,0x66, + 0xb6,0xcd,0xb9,0x2e,0x30,0x1f,0x7c,0x76,0xc8,0x3f,0xab,0x0f,0xce,0x4f,0x19,0xb7, + 0xc3,0x38,0xcc,0xf2,0x19,0xe3,0x16,0x19,0x87,0x7e,0x9f,0x93,0x7f,0x53,0x1f,0xcc, + 0xf7,0x05,0x19,0xe6,0xfb,0x43,0x3b,0x6f,0xb3,0x9f,0xdf,0xea,0x0f,0xdb,0xae,0xae, + 0x36,0xf5,0xe0,0xfb,0x91,0xc6,0x61,0xae,0x21,0x6b,0xe2,0xf7,0x89,0x77,0xf0,0x92, + 0xfc,0xb1,0x9e,0xd0,0xd3,0x1b,0x32,0xe7,0xf7,0x4b,0x73,0xb8,0x5c,0xd8,0xbf,0xab, + 0x17,0xfc,0xde,0xd3,0x27,0xc9,0x98,0x5d,0xa3,0x61,0x9f,0x1a,0x96,0x8c,0x86,0x0e, + 0xb9,0xd3,0xd0,0x25,0x73,0x1a,0x06,0x46,0x03,0x6c,0x3d,0x5d,0x03,0xd6,0xed,0x19, + 0x0d,0x07,0xac,0x9d,0x30,0x1a,0xfa,0xe4,0x4e,0xc3,0x3b,0x32,0xe7,0x07,0x0d,0x2e, + 0xd7,0xc0,0x68,0x38,0xa6,0x4f,0x9b,0x31,0x3d,0xa3,0xe1,0x90,0x1a,0x6a,0x46,0xc3, + 0x11,0xb9,0xd3,0x30,0x24,0x73,0x1a,0xc6,0x46,0x03,0x6c,0x23,0x5d,0x63,0xd6,0x1d, + 0xf1,0x1d,0xa1,0xee,0x6b,0xd6,0x3e,0x36,0xef,0x17,0x3d,0x3a,0xdf,0xb1,0xe9,0xf1, + 0x03,0xfd,0x06,0x8c,0x1b,0xb1,0x1f,0xbc,0xf1,0x7b,0x7c,0xdf,0xa1,0x7a,0xe2,0x6d, + 0xdf,0x27,0x43,0xcc,0x6d,0xbe,0x3d,0xcc,0x0d,0xbd,0x3f,0xa0,0x5d,0x22,0x7b,0x3c, + 0xb7,0x0d,0xf2,0x5b,0xda,0x7b,0x83,0xe7,0x3f,0xda,0x51,0x4d,0xd7,0x5f,0x58,0x8f, + 0x8f,0xad,0xac,0x06,0x00,0x00 }; // Generated from: @@ -73,6 +73,7 @@ constexpr uint8_t kBlitResolve_frag_00000012[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000013.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000013.inc index bb3b13bdcf7..de10efd8066 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000013.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000013.inc @@ -10,51 +10,51 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000013[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x93,0xed,0x4b,0x54,0x41, - 0x14,0xc6,0x67,0xf7,0xea,0xbd,0x5a,0xa9,0x2b,0xb6,0x9a,0x11,0x69,0xd9,0x87,0xa0, - 0x14,0x3f,0x54,0x08,0x51,0xd4,0x07,0x4d,0x63,0x2b,0xdf,0x0b,0xac,0x2e,0xa6,0x4b, - 0x6a,0xba,0x99,0xbb,0x65,0x49,0x04,0x65,0xfd,0x09,0xf5,0x4f,0xf4,0xf7,0x45,0x2f, - 0x10,0x74,0x9e,0xb9,0xbf,0x91,0xa1,0x85,0xd9,0x99,0xf3,0x9c,0xe7,0xbc,0x3c,0x73, - 0xe6,0x26,0xe5,0x91,0xcc,0xb9,0x92,0x3b,0xe6,0x3a,0xdc,0x17,0x57,0xfc,0x7a,0x5d, - 0xd9,0x90,0x62,0xff,0xda,0xe7,0xcc,0xd7,0xe9,0x16,0x66,0x97,0xf3,0xc9,0x47,0x8b, - 0x79,0x73,0x63,0x75,0xbd,0xbe,0x97,0x37,0x5b,0xf5,0xc6,0xda,0xe6,0x76,0x5e,0x7f, - 0xbb,0xfb,0x72,0xaf,0x65,0xdc,0xe3,0x2e,0xf5,0x31,0x77,0x6a,0x0b,0xb5,0xb1,0x66, - 0x6b,0x7d,0xec,0xca,0xd5,0x71,0xe5,0xea,0x76,0x89,0xcf,0x29,0x5f,0x8f,0xcb,0x5c, - 0x9b,0xed,0x5a,0x3b,0xab,0x9b,0x0d,0xe1,0x15,0x5b,0x53,0x7e,0x4f,0x3c,0x9e,0x29, - 0x87,0x9d,0x2a,0x3e,0xa7,0x62,0x9c,0x9b,0x76,0xed,0xae,0x9f,0xde,0x46,0xd8,0x03, - 0x56,0x02,0xeb,0x88,0xb0,0x32,0x58,0x25,0xc2,0x12,0xb0,0x53,0x11,0xd6,0x06,0x76, - 0x26,0xc2,0xda,0xc1,0x86,0x23,0x2c,0x05,0xbb,0x10,0x61,0x19,0xd8,0xc5,0x08,0xeb, - 0x00,0xbb,0x1c,0x61,0x9d,0x60,0xe3,0x5e,0x57,0x72,0xd4,0x9f,0x34,0x4e,0xa1,0xf1, - 0x5b,0x5f,0x61,0xcf,0xd8,0xf9,0x3c,0xfa,0x82,0x7d,0x0e,0x8d,0x7d,0x16,0x55,0xf6, - 0x76,0xe2,0xb5,0xe8,0x5c,0x35,0x4e,0x4a,0xaf,0xe2,0x0c,0x98,0x9d,0xd1,0xaf,0xfc, - 0xfd,0xc6,0xec,0xc2,0x2f,0x5f,0xb7,0xed,0x5d,0xe8,0x1e,0xb6,0xff,0x1e,0xe2,0x84, - 0x5f,0xc7,0xae,0x44,0xb9,0x7a,0xe1,0x87,0x5a,0x55,0x72,0xe9,0x77,0xd6,0x9d,0x38, - 0xba,0x87,0x5e,0x56,0xca,0xea,0x62,0xaf,0x46,0x4b,0xf5,0x06,0xb8,0x8f,0x7e,0xea, - 0x0d,0x30,0x0f,0x61,0x97,0xd0,0x32,0x48,0x7e,0xf1,0x4f,0xe3,0xcb,0x22,0xff,0x10, - 0xb6,0xfc,0xc3,0xf8,0x95,0xff,0xa4,0x75,0x39,0x02,0xaf,0xca,0xac,0x5c,0x14,0x37, - 0xca,0x7c,0x82,0x3d,0x41,0xac,0xf2,0x4c,0xf2,0x3e,0x52,0xfa,0x9a,0xe4,0x4d,0x26, - 0xbe,0x9f,0x4e,0x9b,0x45,0x51,0xa3,0x44,0xce,0x52,0xb4,0x42,0xaf,0xd3,0x47,0x73, - 0x2b,0x72,0xc8,0x9e,0xf9,0xaf,0x87,0x1a,0x39,0xc5,0xbf,0x47,0xfd,0x94,0xbb,0x9e, - 0xe5,0x9c,0x60,0x2f,0x52,0x53,0xb3,0xba,0x66,0x6f,0xa9,0xcc,0xd9,0xc1,0xf9,0x65, - 0x88,0xde,0xea,0x0d,0xe6,0xba,0xc2,0xec,0x1e,0xd8,0xed,0x68,0x16,0x8f,0xc1,0x56, - 0xa2,0x9e,0x1b,0xbc,0x8f,0x27,0xf8,0x6f,0x5b,0x06,0xdd,0xf1,0x53,0xe6,0x30,0x48, - 0x3e,0x71,0x72,0xf0,0x4f,0xc6,0x91,0xbd,0x4a,0x5c,0x4e,0x9c,0xee,0xfe,0x19,0x71, - 0x43,0xc4,0xa9,0xdf,0x35,0xf0,0xef,0xc6,0xd1,0x3c,0xd6,0xc1,0x34,0x8f,0x9f,0xd6, - 0xf9,0x16,0xfd,0xfc,0x31,0xbe,0x7c,0x75,0x5b,0x5b,0xe8,0xd1,0x79,0xce,0xe2,0x74, - 0x0f,0xcf,0xa9,0xa9,0xdf,0x07,0xee,0x6f,0x03,0x7c,0xde,0xac,0xcc,0xe3,0x05,0x16, - 0x78,0xbf,0x2d,0x47,0xc8,0xa5,0xfd,0x87,0xb1,0x32,0xaf,0xa1,0xe0,0xb4,0x13,0x53, - 0x8f,0x34,0xbc,0x40,0xc3,0x68,0xa4,0x61,0x1b,0x3c,0x68,0xd8,0x01,0x0b,0x1a,0x9a, - 0x91,0x86,0x1d,0x7f,0xaf,0xce,0x63,0xaa,0xdb,0x88,0x34,0xec,0x52,0xbb,0x14,0x69, - 0x78,0x05,0x1e,0x34,0x7c,0x04,0x0b,0x3c,0x69,0x08,0xb9,0x9a,0x91,0x86,0x43,0x38, - 0x5b,0xc4,0x34,0x22,0x0d,0x2d,0x34,0x4c,0x44,0x1a,0x5e,0x83,0x07,0x0d,0x6f,0xc0, - 0x82,0x86,0x83,0x48,0x83,0x7c,0xfb,0xb6,0x0e,0xa8,0xbb,0xcf,0x3b,0x52,0xdd,0x77, - 0xd4,0x3e,0x8c,0xde,0xbb,0x7a,0x0c,0xdc,0x83,0xa8,0xc7,0xcf,0xf0,0x9a,0xc4,0xed, - 0xd3,0x8f,0xbe,0x89,0xbb,0x7c,0x0f,0xea,0x59,0x6f,0xff,0x3e,0x3d,0xd7,0xe0,0xa4, - 0xbe,0x66,0x81,0x87,0xfb,0x9b,0x23,0xa7,0x8b,0xb0,0x79,0x30,0xf5,0x32,0x6b,0x88, - 0xbe,0x9b,0x05,0xb8,0xf3,0xe4,0xc8,0xad,0x1b,0x7d,0x3f,0x4b,0xd4,0x95,0xff,0x16, - 0xef,0x5b,0x79,0x74,0x3f,0xcb,0xf8,0xf5,0x7b,0x4f,0xfd,0x87,0xe0,0x37,0xed,0x7e, - 0xa6,0xb0,0xff,0x5a,0xa5,0x09,0x5b,0xff,0x00,0xd5,0xcc,0x3b,0x94,0x28,0x07,0x00, - 0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x53,0x6b,0x6f,0x12,0x41, + 0x14,0x1d,0xd8,0xb2,0x0b,0x35,0xb4,0x10,0x04,0xac,0x31,0x16,0xc5,0x0f,0x26,0xda, + 0xa6,0x1f,0xaa,0x21,0x31,0x1a,0xfd,0x00,0xb6,0x06,0x95,0xd2,0x87,0x26,0x55,0x37, + 0x58,0x88,0x2d,0x16,0xac,0x5d,0x14,0x25,0xc6,0x44,0xab,0x3f,0x41,0xff,0x84,0xbf, + 0xcf,0xf8,0x48,0x4c,0xbc,0x67,0xf6,0x4c,0x73,0x53,0x92,0x61,0x66,0xce,0x3d,0xf7, + 0x71,0xee,0x9d,0xf5,0x92,0xd5,0xc0,0x98,0x84,0x99,0x36,0x69,0xf3,0xd5,0xc4,0xbf, + 0xbc,0x49,0x0a,0x12,0xef,0xdf,0x0a,0x46,0x6c,0x19,0xb3,0xde,0xda,0x0a,0xeb,0x8f, + 0x37,0xc2,0x68,0xb7,0xd3,0xed,0x1d,0x86,0xd1,0xa8,0x37,0xdc,0xd9,0xdb,0x0f,0x7b, + 0xef,0x0e,0x5e,0x1d,0x8e,0x84,0x7b,0xca,0xf8,0xd6,0xe7,0x6e,0x73,0xbd,0xb9,0x18, + 0x8d,0xba,0x8b,0xcb,0xd7,0x96,0x10,0x6b,0xc6,0x78,0x36,0x26,0x6c,0xb3,0x26,0x30, + 0x53,0xb2,0x63,0x0d,0x3a,0x7b,0x43,0xe0,0x39,0x59,0x0d,0xbb,0x7b,0x16,0x0f,0x10, + 0x43,0x4e,0x39,0x1b,0x13,0x3e,0xc6,0xac,0x98,0x94,0x29,0xb1,0xb6,0x2a,0x77,0x87, + 0x25,0x88,0xa5,0x15,0x96,0x24,0x96,0x53,0x98,0x47,0xec,0x8c,0xc2,0xa6,0x88,0x9d, + 0x53,0x58,0x8a,0x58,0x45,0x61,0x3e,0xb1,0x4b,0x0a,0x0b,0x88,0x5d,0x56,0x58,0x9a, + 0xd8,0x55,0x85,0x65,0x88,0x2d,0x29,0x6c,0x9a,0xd8,0xb2,0xd5,0xea,0x1d,0xd7,0x0c, + 0xdd,0x0d,0xea,0xfe,0x5e,0x88,0xef,0xab,0x72,0xbe,0x48,0xcd,0xee,0x7e,0x81,0xba, + 0x0b,0xe2,0x95,0xb4,0x77,0xcf,0xea,0xc3,0xb9,0x28,0x1c,0x9f,0xf5,0x83,0x53,0x96, + 0x7b,0x40,0x0d,0xb0,0x97,0x84,0x99,0xa5,0x1d,0xb6,0x19,0xd9,0xb3,0xec,0x45,0x45, + 0xfe,0x67,0xe9,0x07,0xfc,0x06,0xef,0x39,0x15,0x2b,0x4f,0xbe,0xcb,0x55,0x64,0x2c, + 0xfc,0xce,0x8b,0xc5,0xf5,0x26,0xcf,0xe5,0xab,0x95,0xe5,0x5e,0x54,0x0b,0x39,0xcb, + 0xec,0x53,0x89,0x39,0xcb,0x9c,0x13,0xb0,0x2b,0xd4,0x33,0xc7,0x1c,0xe0,0x9f,0xa5, + 0x2d,0x50,0xf6,0x79,0xf6,0x1f,0xf6,0x0a,0xed,0x88,0x7f,0x5a,0x2a,0xad,0x92,0x57, + 0xe4,0x0c,0x8d,0xf2,0x5b,0x38,0x91,0xa7,0xc6,0xf9,0x20,0x4e,0x9d,0xef,0xc6,0x67, + 0x5d,0x75,0xbe,0x55,0xcf,0xd6,0x93,0x91,0x79,0xc4,0x39,0x12,0x8c,0x99,0x50,0xcb, + 0xd5,0xba,0x72,0x3c,0xbb,0x38,0x06,0xee,0xab,0x27,0x6a,0x68,0xaa,0xfe,0xdf,0x67, + 0x3d,0x3e,0xfb,0xdd,0xe2,0xd9,0xe3,0x7d,0x83,0x39,0xc1,0xbf,0x2e,0xef,0x29,0xc9, + 0xb3,0x21,0xe7,0xb7,0x20,0x78,0xc3,0x37,0x39,0xdb,0x6d,0xce,0xef,0xa1,0x74,0x0b, + 0xf3,0x78,0x42,0x6c,0x5b,0xd5,0x3c,0xe4,0x1b,0x79,0x4a,0xfb,0x1d,0x89,0x80,0x1e, + 0x3f,0xe3,0x1c,0xe6,0x18,0x0f,0x9c,0x90,0xf8,0x67,0xe1,0xe0,0xde,0xa1,0x5f,0x48, + 0x3f,0xf4,0xfe,0x39,0xfd,0xe6,0xe9,0x87,0x7a,0x77,0x88,0xff,0x10,0x0e,0xe6,0xd1, + 0x25,0x86,0x79,0xfc,0x92,0xca,0xfb,0xac,0xe7,0xaf,0xf0,0x61,0xeb,0xc9,0xea,0x53, + 0x0f,0xce,0x6b,0xe2,0x87,0x3e,0xbc,0x60,0x4e,0xfc,0x3e,0xb2,0x7f,0xbb,0xc4,0xdb, + 0x72,0x0b,0x2c,0x1e,0x63,0x8e,0xf7,0x47,0x62,0xb8,0x58,0xd8,0x7f,0x0a,0x2b,0xb0, + 0x1a,0x62,0x4e,0x8a,0x3e,0x3d,0xa5,0xe1,0x25,0x35,0x2c,0x28,0x0d,0xfb,0xc4,0x9d, + 0x86,0x01,0x31,0xa7,0x21,0x52,0x1a,0x06,0xb6,0xaf,0xc6,0x62,0xc8,0x3b,0x54,0x1a, + 0x0e,0x98,0x3b,0xa1,0x34,0xbc,0x26,0xee,0x34,0x7c,0x22,0xe6,0x78,0xd0,0xe0,0x62, + 0x45,0x4a,0xc3,0x11,0x39,0x7d,0xfa,0x0c,0x95,0x86,0x11,0x35,0xd4,0x94,0x86,0x37, + 0xc4,0x9d,0x86,0xb7,0xc4,0x9c,0x86,0x89,0xd2,0x00,0xdb,0x58,0xd6,0x84,0x79,0xc7, + 0x7c,0x47,0xc8,0xfb,0x9e,0xb9,0x8f,0xd4,0x7b,0x47,0x8d,0x8e,0x3b,0x51,0x35,0x7e, + 0x21,0x2f,0xa2,0xdf,0x98,0xf5,0xe0,0x9b,0xb8,0xc7,0xef,0x01,0x35,0xe3,0xed,0x3f, + 0x60,0xcd,0x4d,0x72,0x7c,0x9b,0x33,0xc6,0x5d,0xff,0xd6,0x18,0xd3,0x28,0xac,0x4d, + 0x0c,0xb5,0xb4,0x04,0xc1,0x77,0xb3,0x4e,0x6e,0x9b,0x31,0x42,0xa9,0x06,0xdf,0xcf, + 0x26,0xf3,0xc2,0x7e,0x9b,0xef,0x1b,0x71,0xd0,0x9f,0x2d,0xda,0xf1,0xfb,0xc0,0xfc, + 0x8f,0x88,0xdf,0x92,0xfe,0x34,0x78,0xff,0x27,0x99,0x6a,0xb2,0xfe,0x03,0xe0,0x23, + 0x39,0x7d,0x40,0x07,0x00,0x00 }; // Generated from: @@ -76,6 +76,7 @@ constexpr uint8_t kBlitResolve_frag_00000013[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000014.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000014.inc index c42cd066e0c..4f30383cc6a 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000014.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000014.inc @@ -10,57 +10,60 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000014[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x94,0xdb,0x4b,0x54,0x51, - 0x14,0xc6,0xf7,0x5c,0x9c,0xd1,0x6e,0x1a,0x36,0x6a,0x1a,0x61,0x99,0xd1,0x0d,0x11, - 0xac,0x08,0x22,0xa1,0x87,0x28,0x70,0xcc,0xcb,0xa8,0x59,0x96,0xe3,0x6d,0x22,0x49, - 0x2d,0x74,0x2a,0x29,0xe9,0x62,0x89,0x95,0x14,0x53,0x99,0x3e,0x04,0x65,0xbd,0xf6, - 0xf7,0x45,0x17,0x08,0x5a,0x6b,0x9f,0xdf,0x8e,0x95,0x0f,0x0d,0x6c,0xce,0x59,0xdf, - 0xfa,0xd6,0xe5,0xdb,0x67,0xad,0x49,0xc4,0x9b,0xd2,0xce,0xc5,0xdc,0x16,0x57,0xee, - 0xbe,0xb8,0xe8,0xb7,0xd3,0xc5,0x05,0x89,0x9e,0xef,0xab,0x9d,0xf8,0x2a,0x5c,0xae, - 0x7b,0x20,0x7f,0x6e,0xb0,0x2f,0x3f,0x77,0x63,0x74,0xa2,0x30,0x9b,0x9f,0x2b,0x16, - 0x66,0xc6,0x27,0xa7,0xf2,0x85,0xf9,0xdb,0xb7,0x66,0x8b,0xc2,0xdd,0xea,0x52,0x3e, - 0xe6,0x7c,0x36,0x97,0x6d,0x99,0x2b,0x4e,0xb4,0x1c,0x3f,0xd1,0xaa,0xb9,0x76,0xb8, - 0x84,0xcf,0xa9,0xbe,0x4a,0xa9,0x91,0x94,0xa7,0x9e,0xe9,0xd1,0xc9,0x19,0xe7,0x31, - 0xe7,0xb2,0x72,0xf2,0x72,0xaa,0x84,0xab,0xbe,0xb4,0x79,0xdf,0xa6,0x39,0xe5,0xad, - 0xd2,0xd7,0x88,0xf8,0x17,0x5c,0x99,0xab,0xa5,0xd7,0x26,0x9e,0x01,0x8b,0x81,0x95, - 0x1b,0x2c,0x0e,0x56,0x65,0xb0,0x04,0x58,0x9d,0xc1,0x92,0x60,0x7b,0x0c,0x56,0x06, - 0xd6,0x68,0xb0,0x14,0xd8,0x01,0x83,0xa5,0xc1,0x0e,0x19,0xac,0x1c,0xec,0x98,0xc1, - 0x2a,0xc0,0x5a,0xbd,0xae,0xc4,0xdf,0xfe,0x54,0x63,0x16,0x8d,0x35,0xd8,0x5d,0xf2, - 0xdc,0x8f,0xbe,0x60,0xef,0x33,0x76,0x6e,0x93,0x3f,0x87,0x3f,0xe4,0xcb,0x93,0x6f, - 0xad,0x3a,0xb2,0xc7,0x36,0xf1,0xc7,0xe0,0xeb,0x9d,0x55,0x4b,0x54,0xdc,0xdb,0x09, - 0x7f,0x37,0x71,0xdf,0x47,0xc2,0x6b,0x55,0xed,0xb5,0xc2,0x4f,0xa3,0x3d,0x8e,0xbd, - 0x1d,0x3b,0xe9,0x39,0x49,0xf9,0xd6,0x51,0x2e,0xc5,0x4f,0x63,0x57,0x82,0x65,0xc4, - 0xce,0x90,0x2b,0xd8,0x35,0xd8,0xfa,0xdb,0x2b,0x5f,0x3a,0xdc,0x63,0x38,0x19,0x4e, - 0x8a,0x67,0x8d,0x39,0x5a,0xaf,0x8e,0xfb,0xac,0xa5,0x9e,0xda,0xbb,0xc1,0x8e,0x52, - 0xaf,0x9e,0x7a,0xca,0x6f,0xc0,0x97,0x36,0xfe,0x50,0x3f,0xd8,0xcd,0xf8,0x95,0x7f, - 0x10,0xbe,0xd6,0xdb,0x25,0xaa,0x0f,0xc3,0x53,0xfb,0xc8,0xa6,0xb8,0x36,0xbe,0x77, - 0xb0,0xdb,0x89,0xd5,0x3c,0x1d,0xcc,0x5b,0x8a,0x3e,0x3b,0x98,0xf9,0x84,0xef,0xb7, - 0xc2,0x75,0xe2,0x8b,0xb9,0x7f,0x7f,0xc1,0xd6,0x1c,0x17,0x79,0xef,0x24,0x87,0xda, - 0x5d,0x60,0xf5,0xd2,0x5b,0x0f,0xbc,0x5e,0xb0,0x1e,0x78,0x6a,0xe7,0xc0,0x1a,0xa4, - 0x62,0x3f,0x39,0x42,0x9f,0x83,0x7c,0x4f,0x8d,0x1d,0xa6,0xa7,0x0c,0xb1,0xc3,0xec, - 0x65,0xe8,0x73,0x84,0xbb,0xf8,0x5f,0x9f,0xa3,0xbc,0x8f,0x90,0x43,0xed,0x31,0x53, - 0xbf,0x80,0x4f,0xe7,0xe7,0x26,0xf9,0x74,0x7e,0x4e,0xca,0x7e,0xc4,0x79,0x77,0xd4, - 0xfc,0x21,0x88,0xee,0xdf,0x19,0x66,0x6d,0x96,0x79,0xea,0x11,0x54,0xef,0xab,0x08, - 0xe6,0x0c,0x76,0x07,0x4c,0x7b,0xea,0x16,0x4c,0xbf,0xe5,0x5d,0xb8,0xea,0x3b,0x2b, - 0x98,0xce,0xc1,0x3d,0x66,0xa5,0x9e,0xfc,0xca,0x9b,0x07,0x5f,0x22,0xee,0x3e,0xb1, - 0xf3,0x26,0xee,0x01,0x71,0x8d,0x26,0x6e,0x01,0xfc,0x29,0x71,0x0f,0x89,0x5d,0x20, - 0x4e,0xe7,0xe8,0x11,0x71,0xcd,0xc4,0xa9,0xee,0xc7,0xe0,0x5f,0x85,0xa3,0xb3,0xf5, - 0x04,0x4c,0x67,0xeb,0xbb,0xdc,0xc0,0x32,0xda,0x7e,0x09,0x5f,0x7d,0x8b,0x72,0x96, - 0xb9,0x97,0x45,0xa3,0xf9,0x19,0x35,0x9d,0xcf,0x97,0xf4,0xd8,0x12,0x78,0xaf,0x58, - 0xda,0xd3,0x07,0xb0,0xc0,0xfb,0x29,0x39,0x42,0x2e,0x7d,0x7e,0x13,0x96,0xf2,0x3e, - 0xc1,0x29,0x23,0x66,0xd1,0x68,0x78,0x8e,0x86,0x36,0xa3,0xe1,0x05,0x78,0xd0,0xf0, - 0x12,0x2c,0x68,0x28,0x19,0x0d,0xea,0x5b,0x91,0x53,0xa2,0xee,0x8a,0xd1,0xf0,0x8a, - 0xda,0x31,0xa3,0xe1,0x35,0x78,0xd0,0xf0,0x11,0x2c,0xf0,0x54,0x43,0xc8,0x55,0x32, - 0x1a,0x36,0xe0,0x2c,0x13,0xb3,0x62,0x34,0xbc,0x41,0x43,0xbb,0xd1,0xf0,0x16,0x3c, - 0x68,0x78,0x07,0x16,0x34,0xac,0x1b,0x0d,0xea,0x5b,0x95,0xb3,0x4e,0xdd,0x55,0xbf, - 0x87,0x51,0xdd,0x35,0x6a,0x6f,0x98,0x9d,0xd0,0x1e,0x03,0x77,0xdd,0xf4,0xf8,0x19, - 0x5e,0x89,0xb8,0x55,0xfa,0xe9,0xf4,0x73,0x1b,0xed,0xb6,0xda,0xba,0xc7,0x7d,0xec, - 0xf0,0x80,0xf4,0xd7,0xef,0x9f,0x11,0xa7,0xcf,0xcc,0xe5,0x65,0x74,0x0d,0x9a,0xb9, - 0xbc,0x02,0x1e,0xe6,0x79,0x88,0xba,0x8a,0x5f,0x12,0x4c,0x77,0xea,0x2a,0xf9,0x86, - 0xcc,0xb7,0xb8,0x06,0xee,0xfc,0x3d,0x25,0xfc,0x7f,0xd5,0x35,0xf2,0xea,0xee,0x8e, - 0xb3,0xd3,0xda,0x8f,0xee,0xf3,0x75,0xb0,0x3e,0xf2,0xea,0x5e,0x4f,0x81,0x87,0xbc, - 0x7a,0xcf,0xd3,0xe0,0xce,0xef,0x46,0xf4,0xff,0x33,0x03,0xae,0x75,0xf2,0xd8,0xbf, - 0xe5,0xf6,0x4e,0xc9,0xf9,0x03,0xab,0x2c,0x84,0x1c,0x9c,0x08,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x94,0xe9,0x4b,0x94,0x51, + 0x14,0xc6,0xaf,0x33,0xe3,0x8c,0xb6,0x69,0xd8,0xa8,0x59,0x84,0x2d,0x46,0x1b,0x22, + 0x68,0x11,0x44,0x41,0x1f,0xa2,0x40,0xcd,0x65,0x54,0xcc,0xac,0x71,0x99,0x49,0x6d, + 0x33,0xd2,0x22,0xa2,0x45,0xb2,0x55,0x0a,0x2b,0x51,0xa6,0x92,0xfc,0x10,0x94,0xd5, + 0xdf,0x17,0x2d,0x10,0x74,0xce,0x7d,0x7f,0x37,0x4e,0xf3,0xa1,0x17,0x2e,0xf7,0x3d, + 0xcf,0x59,0x9f,0x7b,0xcf,0xb9,0xf1,0xd8,0xce,0x94,0x73,0x25,0x6e,0x8d,0x2b,0x73, + 0x5f,0x5c,0xf4,0x6d,0x74,0x31,0x41,0xa2,0x7d,0xb1,0xca,0x89,0xae,0xdc,0x65,0x3a, + 0xfb,0xb2,0x27,0xfa,0x7b,0xb2,0x53,0xe3,0xc3,0xb9,0xfc,0xf5,0xec,0xd4,0x74,0xfe, + 0xea,0xe8,0xc4,0xe5,0x6c,0xfe,0xd6,0xb5,0xc9,0xeb,0xd3,0x62,0xbb,0xd6,0x25,0xbd, + 0xcf,0xc9,0xb6,0x4c,0x5b,0xe3,0xd4,0x74,0xae,0xb1,0xe5,0x60,0x93,0xc6,0xda,0xe0, + 0xe2,0x3e,0xa6,0xea,0x2a,0x24,0x47,0x42,0x76,0x5d,0x57,0x86,0x27,0xae,0x3a,0x8f, + 0x39,0xd7,0x26,0x2b,0x27,0xab,0x52,0x6c,0x55,0x97,0x32,0xff,0xeb,0x34,0xa6,0xfc, + 0x55,0xf8,0x1c,0x91,0xfd,0x29,0x57,0xea,0x6a,0xa8,0x75,0x27,0x7b,0xc0,0x4a,0xc0, + 0xca,0x0c,0x16,0x03,0xab,0x34,0x58,0x1c,0xac,0xd6,0x60,0x09,0xb0,0xad,0x06,0x2b, + 0x05,0xab,0x37,0x58,0x12,0x6c,0x97,0xc1,0x52,0x60,0x7b,0x0c,0x56,0x06,0x76,0xc0, + 0x60,0xe5,0x60,0x4d,0x06,0x5b,0x03,0xd6,0xe2,0xb9,0xc6,0xff,0xd6,0xac,0xbc,0xdb, + 0xe0,0x5d,0x8d,0xdc,0x21,0xfb,0x0e,0x38,0x07,0x79,0xbb,0x91,0x33,0x45,0xfa,0x0c, + 0xfa,0x10,0x2f,0x47,0xbc,0xa5,0xaa,0x48,0x1e,0x2b,0xb2,0x1f,0xc3,0x5e,0xcf,0xb1, + 0x4a,0xbc,0x62,0x5e,0x8e,0xfb,0xf3,0x8a,0xf9,0x3a,0xe2,0x9e,0xbf,0x9e,0x47,0x8d, + 0xd8,0xa7,0x38,0x8f,0x18,0xf2,0x7a,0xe4,0x84,0xb7,0x49,0xc8,0xfd,0x47,0xb1,0x14, + 0x3f,0x82,0x5c,0x01,0x96,0x16,0x39,0x4d,0xac,0x20,0x57,0x23,0xeb,0xb7,0x4d,0xbc, + 0xc2,0xd9,0x86,0x95,0x36,0x2b,0xc9,0x5e,0x6d,0x96,0xe6,0xac,0xe5,0x9c,0x6b,0xc8, + 0xa9,0xf2,0x66,0xb0,0xfd,0xe4,0xac,0x23,0xa7,0xda,0x6f,0x41,0x97,0x32,0xfa,0x50, + 0x43,0x90,0x1b,0xb8,0x4f,0xb5,0xdf,0x8d,0xbd,0xe6,0xdb,0x24,0xcc,0xf7,0x62,0xa7, + 0xf2,0xbe,0x22,0xbf,0xe6,0xa2,0xbc,0xc7,0xb8,0x6f,0x8d,0xd3,0x4a,0x1f,0x26,0xa9, + 0xb3,0x95,0x59,0x88,0xfb,0x7a,0xcb,0x5d,0x3b,0xba,0x12,0xf7,0xef,0x17,0x64,0x8d, + 0x71,0x9a,0xff,0x76,0x62,0xa8,0xdc,0x01,0x56,0x27,0xb5,0x75,0x61,0xd7,0x0d,0xd6, + 0x85,0x9d,0xca,0x19,0xb0,0x2d,0x92,0xb1,0x97,0x18,0xa1,0xce,0x7e,0xee,0x34,0xc8, + 0x83,0xd4,0xa5,0xb1,0xce,0xc1,0x29,0x8d,0x3c,0x8a,0x2e,0x4d,0xec,0x51,0xe6,0x39, + 0xf0,0xc8,0x73,0x56,0xff,0xe3,0x71,0x81,0xff,0x3c,0x31,0x54,0x1e,0x33,0xf5,0x5d, + 0x44,0xa7,0x3d,0x36,0x45,0x3c,0xed,0xb1,0x43,0x32,0x43,0x31,0xfe,0x1d,0x39,0x7f, + 0x08,0xa2,0x73,0x7b,0x94,0x7e,0xbc,0x4d,0xcf,0x75,0x09,0xaa,0xe7,0x79,0x07,0xcc, + 0x19,0xec,0x2e,0x98,0xd6,0xd4,0x29,0x98,0xf6,0xc2,0x3d,0x6c,0x55,0x77,0x5c,0x30, + 0xed,0x93,0xfb,0xf4,0x52,0x1d,0xf1,0xd5,0x6e,0x06,0xfc,0x11,0x7e,0x0f,0xf0,0x9d, + 0x31,0x7e,0xb3,0xf8,0xd5,0x1b,0xbf,0x87,0xe0,0xb3,0xf8,0x3d,0xc6,0xf7,0x21,0x7e, + 0xda,0x67,0x4f,0xf0,0x6b,0xc0,0x4f,0x79,0x3f,0x05,0xff,0x2a,0x36,0xda,0x7b,0xcf, + 0xc0,0xb4,0xf7,0xbe,0xcb,0x09,0xcc,0xc3,0xed,0x97,0xd8,0xab,0x6e,0x4e,0xd6,0x3c, + 0xe7,0x32,0x67,0x38,0x3f,0x27,0xa7,0xf3,0xf5,0x27,0x3c,0xf6,0x02,0xbc,0x5b,0x24, + 0xad,0xe9,0x03,0x58,0xb0,0xfb,0x29,0x31,0x42,0x2c,0xdd,0xbf,0x89,0x95,0xda,0x7d, + 0xc2,0xa6,0x14,0x9f,0x39,0xc3,0xe1,0x25,0x1c,0x9a,0x0d,0x87,0x57,0xe0,0x81,0xc3, + 0x6b,0xb0,0xc0,0xa1,0x60,0x38,0xa8,0x6e,0x41,0x56,0x81,0xbc,0x0b,0x86,0xc3,0x22, + 0xb9,0x4b,0x0c,0x87,0x25,0xf0,0xc0,0xe1,0x23,0x58,0xb0,0x53,0x0e,0x21,0x56,0xc1, + 0x70,0x58,0xc5,0x66,0x1e,0x9f,0x05,0xc3,0xe1,0x0d,0x1c,0x8e,0x19,0x0e,0x6f,0xc1, + 0x03,0x87,0x77,0x60,0x81,0xc3,0x8a,0xe1,0xa0,0xba,0x65,0x59,0x2b,0xe4,0x5d,0xf6, + 0x73,0x1a,0xe5,0x7d,0x4f,0xee,0x55,0x33,0x13,0x5a,0x63,0xb0,0x5d,0x31,0x35,0x7e, + 0xc6,0xae,0x80,0xdf,0x32,0xf5,0xb4,0xfb,0xbe,0x8d,0x66,0x5f,0x65,0x9d,0xf3,0x1e, + 0x66,0xbc,0x4f,0xea,0xeb,0xf5,0x7b,0x64,0xd3,0x63,0xfa,0xf2,0x0c,0xbc,0xfa,0x4d, + 0x5f,0x0e,0x80,0x87,0x7e,0x3e,0x4b,0xde,0x01,0xfc,0x74,0xfe,0xcf,0xe3,0x37,0x88, + 0x9f,0xce,0x7e,0x16,0x7c,0x92,0x7b,0x18,0x02,0xeb,0x97,0x28,0x3a,0x87,0xc3,0xd4, + 0x70,0x96,0xb7,0x65,0xc8,0xdc,0xe3,0x08,0x7a,0xe7,0xcf,0x38,0xee,0xdf,0xc1,0x11, + 0x62,0xeb,0xdc,0x8f,0xf3,0x1e,0x28,0x17,0x7d,0x0b,0x2e,0x81,0xf5,0x10,0x5f,0xdf, + 0x84,0x69,0xf0,0xe2,0xf8,0x7a,0x57,0x37,0xd0,0x3b,0x3f,0xd3,0x51,0xbd,0x37,0xc1, + 0x35,0x5f,0x0e,0xf9,0xb7,0xdc,0xc0,0x61,0x59,0x7f,0x00,0x8c,0xe1,0x21,0x31,0x18, + 0x09,0x00,0x00 }; // Generated from: @@ -84,6 +87,7 @@ constexpr uint8_t kBlitResolve_frag_00000014[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -120,8 +124,8 @@ constexpr uint8_t kBlitResolve_frag_00000014[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// gl_FragDepth = texture(sampler2D(depth, blitSampler), srcImageCoords * params . invSrcExtent). x; +// gl_FragDepth = textureLod(sampler2D(depth, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip). x; // -// gl_FragStencilRefARB = int(texture(usampler2D(stencil, blitSampler), srcImageCoords * params . invSrcExtent). x); +// gl_FragStencilRefARB = int(textureLod(usampler2D(stencil, blitSampler), srcImageCoords * params . invSrcExtent, params . srcMip). x); // // } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000015.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000015.inc index 6aa9d00e978..740214ca5cc 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000015.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000015.inc @@ -11,60 +11,61 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000015[] = { 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x94,0xdb,0x4b,0x54,0x51, - 0x14,0xc6,0xb7,0x73,0x74,0x46,0xbb,0x69,0xd8,0xa8,0x69,0x84,0x65,0x46,0x37,0x44, - 0xb0,0x22,0x88,0x84,0x1e,0xa2,0xc0,0x31,0x2f,0x33,0x9a,0x99,0x35,0x99,0x33,0x3a, - 0xa6,0x69,0xa8,0x0f,0xd1,0x85,0x08,0x33,0x29,0xe9,0x22,0x95,0x95,0x14,0x53,0x49, - 0x3e,0x14,0x65,0xfd,0x71,0xd1,0x05,0x82,0xd6,0xda,0xe7,0xb7,0x63,0x33,0x0f,0x1d, - 0xd8,0xec,0xb3,0xbe,0xf5,0xad,0xcb,0xb7,0x6f,0x41,0xa4,0x21,0x66,0x4c,0x91,0x59, - 0x67,0x4a,0xcd,0x37,0x13,0x7e,0x9b,0x4d,0x44,0x90,0x70,0x7e,0x5e,0x69,0xc4,0x57, - 0x66,0x92,0x9d,0xbd,0xe9,0x13,0x7d,0xa9,0xf4,0x74,0x6e,0x30,0x93,0x9d,0x4a,0x4f, - 0xcf,0x64,0x27,0x86,0x46,0xc7,0xd3,0xd9,0x6b,0x57,0x27,0xa7,0x66,0x84,0xbb,0xde, - 0x44,0x6d,0xcc,0xc9,0x44,0x32,0xd1,0x34,0x3d,0x93,0x69,0x3a,0x78,0xa8,0x59,0x73, - 0x6d,0x32,0x81,0xcd,0xa9,0xbe,0x72,0xa9,0x51,0x2c,0xb3,0x8e,0x2b,0x83,0xa3,0x13, - 0xc6,0x62,0xc6,0x24,0x64,0xe4,0x64,0x54,0x08,0x57,0x7d,0x31,0xef,0x7f,0x83,0xe6, - 0x94,0xbf,0x72,0x5b,0x23,0xe4,0x9f,0x32,0x25,0xa6,0x9a,0x5e,0x1b,0x98,0x1d,0x56, - 0x04,0x56,0xea,0x61,0x11,0xb0,0x0a,0x0f,0x0b,0xc0,0x6a,0x3c,0xac,0x18,0x6c,0x9b, - 0x87,0x95,0x80,0xd5,0x7b,0x58,0x14,0x6c,0x97,0x87,0xc5,0xc0,0xf6,0x78,0x58,0x29, - 0xd8,0x01,0x0f,0x2b,0x03,0x6b,0xb6,0xba,0x82,0x7f,0xfd,0xa9,0xc6,0x04,0x1a,0xab, - 0xb0,0x3b,0x64,0xde,0x89,0x3e,0x67,0xef,0xf0,0xec,0x64,0x81,0x3f,0x89,0xdf,0xe5, - 0xcb,0x91,0x6f,0xa9,0x32,0xb4,0xc7,0x0a,0xf8,0x63,0xf0,0x75,0xcd,0x2a,0x25,0x2a, - 0x62,0xed,0xc0,0xae,0x4d,0xc4,0xf6,0x11,0x58,0xad,0xaa,0xbd,0x5a,0xf8,0x31,0xb4, - 0x47,0xb0,0x37,0x62,0x17,0x5b,0x4e,0xb1,0xec,0x75,0x98,0x4b,0xf1,0xa3,0xd8,0xe5, - 0x60,0x71,0xb1,0xe3,0xe4,0x72,0x76,0x15,0xb6,0x7e,0xdb,0x65,0xa7,0xdd,0x3a,0xba, - 0x11,0x67,0x44,0x99,0xab,0xbc,0xa1,0xf5,0x6a,0x58,0xcf,0x6a,0xea,0xa9,0xbd,0x15, - 0x6c,0x3f,0xf5,0x6a,0xa9,0xa7,0xfc,0x3a,0x7c,0x31,0xcf,0xef,0xea,0x3b,0xbb,0x11, - 0xbf,0xf2,0x77,0xc3,0xd7,0x7a,0x5b,0x44,0xf5,0x5e,0x78,0x6a,0xef,0x2b,0x88,0x6b, - 0x61,0xbf,0x9d,0xdd,0x4a,0xac,0xe6,0x69,0xe3,0xbc,0x45,0xe9,0xb3,0x8d,0x33,0x1f, - 0xd8,0x7e,0xcb,0x4c,0x3b,0xbe,0x22,0x72,0x16,0xce,0x9a,0xe3,0x34,0xff,0xed,0xe4, - 0x50,0xbb,0x03,0xac,0x56,0x7a,0xeb,0x82,0xd7,0x0d,0xd6,0x05,0x4f,0xed,0x24,0x58, - 0x9d,0x54,0xec,0x21,0x87,0xeb,0xb3,0x8f,0xfd,0x74,0xf6,0x00,0x7d,0x69,0xae,0xf3, - 0x68,0x88,0xb3,0xdf,0x83,0xf4,0xe9,0xfc,0x23,0xfc,0xc7,0xa9,0x35,0xc2,0x3d,0x76, - 0xba,0x46,0x59,0xbb,0xff,0xe9,0xba,0xcc,0xff,0x28,0x39,0xd4,0x1e,0xf3,0xfa,0x9d, - 0xc0,0xa7,0xf5,0xaf,0x93,0x4f,0xcf,0xdb,0x61,0xb9,0x4f,0x11,0xfe,0x0d,0x35,0x7f, - 0x0a,0xa2,0xf7,0xf5,0x18,0x67,0xf3,0x0e,0xe7,0xaf,0x4b,0x50,0xed,0x7b,0x16,0xcc, - 0x78,0xd8,0x5d,0x30,0xed,0xa9,0x53,0x30,0xdd,0xfb,0x39,0xb8,0xea,0x3b,0x2e,0x98, - 0x9e,0x9b,0x7b,0x9c,0xad,0x5a,0xf2,0x2b,0x6f,0x1e,0x7c,0x8e,0xb8,0xfb,0xc4,0xce, - 0x7b,0x71,0x0f,0x88,0xab,0xf7,0xe2,0x16,0xc0,0x67,0x89,0x7b,0x48,0xec,0x02,0x71, - 0x7a,0xee,0x1e,0x11,0xd7,0x48,0x9c,0xea,0x7e,0x0c,0xfe,0x49,0x38,0x7a,0x16,0x9f, - 0x80,0xe9,0x59,0xfc,0x21,0x2b,0xb0,0x84,0xb6,0xdf,0xc2,0x57,0xdf,0xa2,0xde,0x7d, - 0xd6,0x65,0xd1,0xd3,0xfc,0x94,0x9a,0xfa,0xdd,0x16,0xae,0x62,0xcf,0xc0,0xbb,0xc5, - 0xd2,0x9e,0x3e,0x82,0x39,0xde,0x2f,0xc9,0xe1,0x72,0xe9,0xfc,0x5d,0x58,0xca,0xfb, - 0x02,0xa7,0x84,0x98,0x45,0x4f,0xc3,0x0b,0x34,0xb4,0x78,0x1a,0x5e,0x82,0x3b,0x0d, - 0xaf,0xc0,0x9c,0x86,0xbc,0xa7,0x41,0x7d,0xcb,0x32,0xf2,0xd4,0x5d,0xf6,0x34,0xbc, - 0xa6,0x76,0x91,0xa7,0xe1,0x0d,0xb8,0xd3,0xf0,0x19,0xcc,0xf1,0x54,0x83,0xcb,0x95, - 0xf7,0x34,0xac,0xc1,0x59,0x22,0x66,0xd9,0xd3,0xf0,0x16,0x0d,0xad,0x9e,0x86,0x77, - 0xe0,0x4e,0xc3,0x7b,0x30,0xa7,0x61,0xd5,0xd3,0xa0,0xbe,0x15,0x19,0xab,0xd4,0x5d, - 0xb1,0xf7,0x36,0xac,0xfb,0x81,0xda,0x6b,0xde,0x9d,0xd0,0x1e,0x1d,0x77,0xd5,0xeb, - 0xf1,0x2b,0xbc,0x3c,0x71,0x2b,0xf4,0xd3,0x6e,0xcf,0x6d,0xf8,0x16,0xa8,0xad,0xf7, - 0x3e,0xc5,0x9d,0xef,0x95,0xfe,0x7a,0xec,0x1c,0x72,0x52,0xde,0xb9,0x3c,0x8b,0xae, - 0x3e,0xef,0x5c,0xf6,0x83,0xbb,0xf3,0x7c,0x8e,0xba,0xfd,0xc4,0xe9,0x7b,0x70,0x81, - 0xb8,0x01,0xe2,0xf4,0xee,0xa7,0xc1,0x27,0xd9,0x87,0x8b,0x60,0x6e,0xaf,0x2e,0x91, - 0xcb,0xbf,0x77,0x43,0x60,0xe1,0xbd,0x8b,0xda,0xb7,0x25,0x03,0x77,0x88,0x1c,0x67, - 0x84,0xab,0xf7,0x38,0x8b,0x86,0x8c,0x17,0x3f,0x0c,0x6e,0xec,0xde,0x04,0xf6,0x3d, - 0x1d,0xa6,0x27,0x7d,0x2f,0xc6,0x79,0x47,0x74,0x0d,0x26,0x6c,0x6f,0x21,0x96,0x22, - 0xaf,0xbe,0x25,0x37,0xc0,0x5d,0x5e,0xdd,0xdb,0x9b,0xe0,0xc6,0xfe,0x87,0xfa,0x6e, - 0x81,0x6b,0x9d,0x1c,0xf6,0x1f,0xe9,0xfc,0x88,0x8c,0xbf,0x4c,0x21,0xcd,0x12,0x40, - 0x09,0x00,0x00 + 0x14,0xc6,0xb7,0x73,0x74,0x46,0xed,0xa2,0x61,0x33,0x96,0x45,0x54,0x56,0x74,0x23, + 0x04,0x2d,0x82,0x48,0xe8,0x21,0x0a,0xd2,0xca,0xc6,0xc2,0xae,0x93,0x39,0x53,0x9a, + 0xa3,0x23,0xea,0x43,0x0f,0x41,0x74,0x83,0xe8,0x46,0x45,0x9a,0x14,0x56,0x52,0x58, + 0x59,0x3e,0x04,0xdd,0xfe,0xb1,0xe8,0x02,0x41,0x6b,0xed,0xf3,0xdb,0xb1,0x98,0x87, + 0x0e,0x6c,0xf6,0x59,0xdf,0xfa,0xd6,0xe5,0xdb,0xb7,0x28,0xd1,0x9c,0x72,0xae,0xc2, + 0xd5,0xba,0x6a,0xf7,0xcd,0xc5,0xdf,0x12,0x97,0x10,0x24,0x9e,0x27,0x1a,0x9c,0xf8, + 0x6a,0x5c,0xf6,0xf0,0xb1,0xdc,0xde,0x9e,0xee,0xdc,0x58,0x7f,0x6f,0xbe,0x30,0x9a, + 0x1b,0x1b,0x2f,0x0c,0xf7,0x0d,0x14,0x73,0x85,0x4b,0x23,0xa5,0xd1,0x71,0xe1,0x2e, + 0x70,0x49,0x1f,0xb3,0xaf,0x23,0xdb,0xb1,0x6d,0x6c,0x3c,0xbf,0xad,0x6d,0x7b,0x8b, + 0xe6,0x5a,0xec,0x22,0x9f,0x53,0x7d,0x75,0x52,0xa3,0x52,0x66,0x1d,0x43,0xbd,0x03, + 0xc3,0xce,0x63,0xce,0x75,0xc8,0x28,0xca,0xa8,0x17,0xae,0xfa,0x52,0xe6,0x7f,0xa1, + 0xe6,0x94,0xbf,0x3a,0x5f,0x23,0xe6,0xef,0x77,0x55,0xae,0x91,0x5e,0x9b,0x99,0x03, + 0x56,0x01,0x56,0x6d,0xb0,0x04,0x58,0xbd,0xc1,0x22,0xb0,0x65,0x06,0xab,0x04,0x5b, + 0x69,0xb0,0x2a,0xb0,0xd5,0x06,0x4b,0x82,0xad,0x33,0x58,0x0a,0x6c,0xa3,0xc1,0xaa, + 0xc1,0xb6,0x1a,0xac,0x06,0xac,0xc5,0x60,0xb5,0x60,0x6d,0x5e,0x6b,0xf4,0xaf,0x67, + 0xd5,0xdd,0x81,0xee,0x0c,0xf6,0x21,0x99,0xd7,0xa2,0x39,0xd8,0x6b,0x8c,0x9d,0x2d, + 0xf3,0x67,0xf1,0x87,0x7c,0x45,0xf2,0x4d,0x36,0xc4,0x76,0xa9,0x8c,0x5f,0x82,0xaf, + 0xeb,0xd8,0x20,0x51,0x09,0x6f,0x47,0x7e,0xbd,0x12,0xbe,0x8f,0xc8,0xeb,0xd7,0xf5, + 0x68,0x14,0x7e,0x8a,0xf5,0x48,0x60,0x2f,0xc2,0xae,0xf4,0x9c,0x4a,0xd9,0xff,0x38, + 0x97,0xe2,0xbb,0xb0,0xeb,0xc0,0xd2,0x62,0xa7,0xc9,0x15,0xec,0x0c,0xb6,0x7e,0xab, + 0x24,0x2a,0xac,0x6d,0x18,0x69,0x33,0x92,0xcc,0x19,0x33,0xb4,0xe6,0x32,0xd6,0xb9, + 0x91,0x9a,0x6a,0x2f,0x07,0xdb,0x42,0xcd,0x26,0x6a,0x2a,0x7f,0x05,0xbe,0x94,0xf1, + 0x87,0x1e,0x82,0xbd,0x9e,0xfd,0x54,0xfe,0x06,0xf8,0x5a,0x6f,0xa9,0x28,0xdf,0x04, + 0x4f,0xed,0xcd,0x65,0x71,0xad,0x65,0x75,0xdb,0xd9,0x6f,0xcd,0x73,0x80,0x73,0x98, + 0xa4,0xcf,0x03,0xdc,0x85,0xc8,0xf7,0x5b,0xe3,0x3a,0xf1,0x55,0x90,0xb3,0x7c,0xd6, + 0x1c,0x07,0xf9,0xef,0x24,0x87,0xda,0x87,0xc0,0x9a,0xa4,0xb7,0x2e,0x78,0x47,0xc0, + 0xba,0xe0,0xa9,0x9d,0x05,0x5b,0x21,0x15,0x8f,0x92,0x23,0xf4,0xd9,0xc3,0x9e,0x06, + 0xfb,0x94,0xd9,0xd3,0xd3,0x68,0x4a,0xb3,0xe7,0xbd,0xf4,0x19,0x19,0x7e,0x01,0x5b, + 0xf9,0x83,0xfc,0xa7,0xa9,0x3d,0xc8,0x7d,0x0f,0x3a,0x87,0x58,0xcb,0xff,0xe9,0x1c, + 0xe6,0x7f,0x88,0x1c,0x6a,0x97,0x4c,0xff,0xa3,0xf8,0xb4,0x9f,0xab,0xe4,0xd3,0x7e, + 0x77,0xc8,0x1d,0x4b,0xf0,0xef,0xa8,0xf9,0x53,0x10,0xbd,0xd7,0xbb,0x39,0xaf,0xb7, + 0x38,0x93,0x5d,0x82,0xaa,0x8e,0xdb,0x60,0xce,0x60,0x77,0xc0,0xb4,0xa7,0xc3,0x82, + 0xe9,0x59,0xb9,0x0b,0x57,0x7d,0x7b,0x04,0xd3,0x73,0x74,0x8f,0xb3,0xd6,0x44,0x7e, + 0xe5,0xdd,0x07,0xbf,0x49,0xdc,0x03,0x62,0xef,0x9b,0xb8,0x87,0xc4,0xad,0x36,0x71, + 0x8f,0xc0,0xaf,0x13,0xf7,0x98,0xd8,0x47,0xc4,0xe9,0x39,0x9c,0x20,0x6e,0x3d,0x71, + 0xaa,0x7b,0x12,0xfc,0xbd,0x70,0xf4,0x6c,0x3e,0x01,0xd3,0xb3,0xf9,0x43,0x56,0x60, + 0x1a,0x6d,0xbf,0x85,0xaf,0xbe,0x29,0x19,0xd3,0xac,0xcb,0x94,0xd1,0xfc,0x94,0x9a, + 0xfa,0x5d,0x11,0xae,0x62,0xcf,0xc0,0x8f,0x88,0xa5,0x3d,0x7d,0x04,0x0b,0xbc,0x5f, + 0x92,0x23,0xe4,0xd2,0xf9,0xbb,0xb0,0x94,0xf7,0x19,0x4e,0x15,0x31,0x53,0x46,0xc3, + 0x73,0x34,0xb4,0x1a,0x0d,0x2f,0xc0,0x83,0x86,0x97,0x60,0x41,0xc3,0xac,0xd1,0xa0, + 0xbe,0x19,0x19,0xb3,0xd4,0x9d,0x31,0x1a,0x5e,0x51,0xbb,0xc2,0x68,0x78,0x0d,0x1e, + 0x34,0x7c,0x02,0x0b,0x3c,0xd5,0x10,0x72,0xcd,0x1a,0x0d,0x5f,0xe0,0x4c,0x13,0x33, + 0x63,0x34,0xbc,0x41,0x43,0xbb,0xd1,0xf0,0x16,0x3c,0x68,0x78,0x07,0x16,0x34,0xcc, + 0x1b,0x0d,0xea,0x9b,0x93,0x31,0x4f,0xdd,0x39,0x7f,0x8f,0xe3,0xba,0x1f,0xa8,0xfd, + 0xc5,0xdc,0x09,0xed,0x31,0x70,0xe7,0x4d,0x8f,0x5f,0xe1,0xcd,0x12,0x37,0x47,0x3f, + 0x9d,0xfe,0xdc,0xc6,0x6f,0x83,0xda,0xfa,0x0e,0x74,0xf3,0x06,0x1c,0x93,0xfe,0x8e, + 0xfa,0x39,0xe6,0x74,0x9b,0x73,0x79,0x1c,0x5d,0x3d,0xe6,0x5c,0x9e,0x00,0x0f,0xe7, + 0xf9,0x24,0x75,0x4f,0x10,0xa7,0xef,0xc3,0x19,0xe2,0x4e,0x11,0xa7,0x77,0x3f,0x07, + 0x5e,0x62,0x1f,0xce,0x82,0x85,0xbd,0x3a,0x47,0x2e,0x7b,0xef,0xfa,0xc0,0xe2,0x7b, + 0x97,0xf4,0x6f,0x4d,0x1e,0x6e,0x1f,0x39,0x42,0xcd,0xf3,0xd4,0x2c,0x98,0x9a,0x17, + 0xc0,0x43,0xcd,0x7e,0xb0,0x1e,0xe9,0x5c,0xef,0xfe,0x00,0xba,0xf3,0xbc,0x77,0xfd, + 0xa6,0xf6,0x45,0xfc,0xce,0xef,0x6b,0xe4,0xdf,0xe6,0x8b,0xe4,0xd6,0xb7,0x66,0x84, + 0x37,0x48,0xd7,0x4f,0xdf,0x9f,0x31,0xb0,0x6e,0xf2,0xeb,0x3b,0x74,0x0d,0xbc,0x3c, + 0x7f,0xc6,0xdf,0xeb,0xd8,0xaf,0xdf,0x65,0xfa,0xbd,0x01,0xae,0xf5,0x8a,0xd8,0x7f, + 0x44,0xfd,0x4e,0x19,0x7f,0x01,0x13,0xdc,0xc2,0xdb,0xac,0x09,0x00,0x00 }; // Generated from: @@ -88,6 +89,7 @@ constexpr uint8_t kBlitResolve_frag_00000015[] = { // vec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; @@ -124,8 +126,8 @@ constexpr uint8_t kBlitResolve_frag_00000015[] = { // { // vec2 srcImageCoords = getSrcImageCoords(); // -// gl_FragDepth = texture(sampler2DArray(depth, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)). x; +// gl_FragDepth = textureLod(sampler2DArray(depth, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip). x; // -// gl_FragStencilRefARB = int(texture(usampler2DArray(stencil, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)). x); +// gl_FragStencilRefARB = int(textureLod(usampler2DArray(stencil, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer), params . srcMip). x); // // } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000016.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000016.inc index 6d8e374fa05..1401e943c64 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000016.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000016.inc @@ -10,52 +10,52 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000016[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x93,0xdd,0x4e,0x53,0x41, - 0x14,0x85,0xa7,0x2d,0xb4,0xa0,0x56,0x4a,0xb0,0x20,0xc6,0x08,0x8a,0x17,0x26,0x0a, - 0xe1,0x42,0x0d,0x89,0xd1,0xe8,0x05,0x08,0x06,0x29,0x14,0x45,0x2e,0xd0,0x82,0x50, - 0x02,0x01,0x5a,0x85,0xaa,0x8d,0x18,0x4d,0x10,0x7d,0x03,0x7d,0x09,0x9f,0xcf,0xf8, - 0x93,0x98,0xb8,0xd7,0xe9,0x37,0xb8,0xc3,0x85,0x27,0xd9,0x67,0x66,0xaf,0xfd,0xbb, - 0x66,0xcf,0x64,0xd2,0x43,0xb9,0x10,0x52,0xe1,0x44,0xe8,0x08,0x9f,0x43,0xeb,0xeb, - 0x0e,0x69,0x43,0x5a,0xeb,0x97,0x9e,0x60,0xb6,0xce,0x30,0x3f,0xbb,0x50,0x19,0x5f, - 0x7c,0x54,0xd9,0xdb,0x58,0x59,0xab,0xee,0x56,0xf6,0x1a,0xd5,0xda,0xea,0xe6,0x76, - 0xa5,0xda,0x7c,0x51,0xdf,0x6d,0x98,0xef,0xc9,0x90,0x4d,0x62,0xee,0x4f,0xcf,0x4f, - 0x8f,0xec,0x35,0xd6,0x46,0xae,0xdf,0x18,0x55,0xae,0xd3,0x21,0x93,0xe4,0x94,0xad, - 0xcb,0x6a,0xb4,0xd9,0x2a,0xd9,0x59,0xd9,0xac,0x09,0x2f,0x98,0x4c,0x98,0x94,0x92, - 0x7d,0x26,0xb1,0xe5,0xdc,0xfe,0x94,0x72,0xda,0xae,0x90,0xd4,0x50,0x8e,0x10,0x26, - 0x43,0x7b,0xe8,0xa5,0xd7,0x21,0xd6,0x88,0xa5,0xc0,0x3a,0x1c,0x96,0x06,0x2b,0x38, - 0x2c,0x03,0x76,0xd6,0x61,0x6d,0x60,0xe7,0x1d,0xd6,0x0e,0x36,0xe8,0xb0,0x2c,0xd8, - 0x65,0x87,0xe5,0xc0,0xae,0x38,0xac,0x03,0xec,0x9a,0xc3,0x3a,0xc1,0x46,0x13,0x5e, - 0x99,0xa3,0xfe,0xc4,0x71,0x02,0x8e,0xbd,0xe8,0x53,0xb6,0x5e,0x82,0x5f,0xd4,0x2f, - 0x3a,0xbd,0x84,0xff,0xd7,0x9e,0x96,0x5e,0x3e,0xe6,0x5f,0xc6,0x5f,0x67,0xd2,0x63, - 0x55,0xd2,0x89,0x9e,0x49,0xb8,0x6b,0x5f,0x34,0x9f,0x2c,0xdc,0xe4,0xd3,0x67,0x7a, - 0x0e,0x7e,0xe9,0xa4,0x8f,0x4c,0xc8,0x63,0x97,0xed,0xb4,0xad,0x79,0xce,0x69,0xd0, - 0xfe,0x5d,0xc4,0x09,0xbf,0x85,0x5e,0x70,0xb9,0xba,0xf1,0x8f,0xb5,0x8a,0xe4,0xd2, - 0x77,0xc1,0x26,0x1b,0xcf,0xad,0x1b,0xc9,0x22,0x79,0xd6,0xa2,0x13,0xd5,0xeb,0xe3, - 0xfc,0x7a,0xa9,0xd7,0xc7,0xfc,0x84,0x5d,0x85,0x4b,0x3f,0xf9,0xe5,0x7f,0x0e,0x5b, - 0xce,0xd9,0x07,0xd0,0x65,0x1f,0xc4,0xae,0xfc,0x67,0xac,0xcb,0x21,0xfc,0x8a,0xcc, - 0x36,0xb8,0xb8,0x61,0xe6,0x19,0xf5,0x31,0x62,0x95,0x67,0x9c,0xfb,0x94,0xa7,0xaf, - 0x71,0xee,0x74,0x26,0xe9,0xa7,0xd3,0x66,0xd1,0xb2,0xa5,0xc2,0xbf,0x2f,0xe5,0x74, - 0xe5,0x98,0x3c,0x9a,0x5b,0x2b,0x87,0xf4,0x29,0x67,0x9f,0x21,0x5f,0x16,0xfb,0x0c, - 0x6f,0x26,0xd6,0x98,0x85,0xc7,0xff,0x6a,0xcc,0xb1,0x9f,0x25,0x87,0xf4,0x32,0x98, - 0xe6,0xf5,0x98,0x1c,0x9a,0xef,0x4d,0xbb,0xaf,0x69,0xf6,0x81,0x3a,0x3f,0x0d,0xd1, - 0x7b,0xb8,0xcd,0x5d,0x58,0x62,0xde,0x25,0x3b,0x51,0xcd,0xef,0x29,0xd8,0x92,0xab, - 0x5f,0xe3,0x4e,0x3d,0xc3,0x7e,0xcf,0x32,0x68,0x2e,0x15,0x66,0xd7,0x4f,0x3e,0xf9, - 0x2c,0x83,0x1f,0x98,0x8f,0xf4,0xe7,0xc4,0x2d,0x13,0xa7,0x79,0xad,0x12,0x37,0x40, - 0x9c,0xfa,0x5d,0x03,0xff,0x66,0x3e,0x9a,0x61,0x15,0x4c,0x33,0xfc,0x61,0x9d,0x6f, - 0xd1,0xcf,0x6f,0xf3,0x97,0x6d,0xdd,0x64,0x0b,0x3e,0xda,0xcf,0x59,0x9c,0xce,0x75, - 0x83,0x9a,0xfa,0xde,0x33,0xe7,0x4d,0xf0,0xb2,0x69,0xea,0xe9,0x03,0x58,0xf4,0xfb, - 0x65,0x39,0x62,0x2e,0xad,0xdf,0xcd,0x4b,0x7e,0x1f,0xf1,0x69,0x27,0x66,0xdd,0x71, - 0xd8,0x86,0xc3,0xb0,0xe3,0xb0,0x03,0x1e,0x39,0xd4,0xc0,0x22,0x87,0x86,0xe3,0x20, - 0x5b,0xdd,0xa4,0x41,0xdd,0xba,0xe3,0xf0,0x92,0xda,0x29,0xc7,0x61,0x17,0x3c,0x72, - 0x38,0x00,0x8b,0x7e,0xe2,0x10,0x73,0x35,0x1c,0x87,0x43,0x7c,0xb6,0x88,0xa9,0x3b, - 0x0e,0xaf,0xe0,0x30,0xe6,0x38,0xbc,0x06,0x8f,0x1c,0xde,0x80,0x45,0x0e,0xfb,0x8e, - 0x83,0x6c,0x4d,0x93,0x7d,0xea,0x36,0xb9,0x47,0xaa,0xfb,0x96,0xda,0x87,0xee,0xfe, - 0xaa,0xc7,0xe8,0xbb,0xef,0x7a,0xfc,0x84,0x5f,0x83,0xb8,0x26,0xfd,0xe8,0x1d,0x3d, - 0xe0,0x0d,0x55,0xcc,0x53,0xf7,0x75,0x1a,0x4c,0x31,0x77,0xb9,0x7b,0x3a,0x37,0xbd, - 0xcd,0x87,0xd8,0xf5,0xdd,0xb1,0x5e,0x27,0xc0,0x94,0x4b,0xef,0x65,0x9e,0xb7,0xa2, - 0x5c,0x7a,0x27,0x0b,0x60,0xc7,0x73,0xe9,0x1c,0x9e,0x60,0xd7,0xf7,0x8e,0x19,0x2c, - 0x82,0x2b,0x77,0x09,0xfd,0x8f,0xb1,0x1b,0x33,0xf9,0x0b,0x5e,0x1d,0x06,0x2b,0x84, - 0x07,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x93,0xdd,0x4e,0x53,0x51, + 0x10,0x85,0x77,0x7b,0xa0,0x05,0xb4,0x50,0x82,0x05,0x31,0x46,0x50,0xbc,0x30,0x51, + 0x08,0x17,0x68,0x48,0x8c,0x46,0x2f,0x40,0x30,0x48,0xa1,0x20,0x72,0x81,0x16,0x84, + 0x12,0x08,0xd0,0x2a,0x54,0x6d,0xc4,0x68,0x82,0xe8,0x1b,0xe8,0x4b,0xf8,0x7c,0xc6, + 0x9f,0xc4,0xc4,0x59,0xa7,0xdf,0xc1,0x09,0x17,0x9e,0x64,0xce,0xde,0xb3,0xe6,0x77, + 0xed,0xd9,0x3b,0x4a,0x0f,0x65,0x43,0x48,0x85,0x8e,0xd0,0x16,0x3e,0x87,0xe6,0xd7, + 0x1d,0xd2,0x86,0x34,0xd7,0x2f,0x3d,0xc1,0x6c,0xed,0x61,0x61,0x6e,0xa9,0x3c,0xb1, + 0xbc,0x58,0x3e,0xd8,0x5a,0xdb,0xa8,0xec,0x97,0x0f,0xea,0x95,0xea,0xfa,0xf6,0x6e, + 0xb9,0xd2,0x78,0x51,0xdb,0xaf,0x9b,0xef,0x99,0x90,0x89,0x63,0x1e,0xcc,0x2c,0xcc, + 0x8c,0x1c,0xd4,0x37,0x46,0xc6,0x6e,0x8e,0x2a,0x57,0x67,0x88,0xe2,0x9c,0xb2,0x75, + 0x59,0x8d,0x16,0x5b,0x25,0x7b,0x6b,0xdb,0x55,0xe1,0x79,0x93,0x49,0x93,0x62,0xbc, + 0x8f,0x62,0x5b,0xd6,0xed,0xcf,0x2a,0xa7,0xed,0xf2,0x71,0x0d,0xe5,0x08,0x61,0x2a, + 0xb4,0x86,0x5e,0x7a,0x1d,0x62,0x4d,0xb0,0x14,0x58,0x9b,0xc3,0xd2,0x60,0x79,0x87, + 0x45,0x60,0xe7,0x1d,0xd6,0x02,0x76,0xd1,0x61,0xad,0x60,0x83,0x0e,0xcb,0x80,0x5d, + 0x75,0x58,0x16,0xec,0x9a,0xc3,0xda,0xc0,0x6e,0x38,0xac,0x1d,0x6c,0xd4,0x61,0x1d, + 0x60,0x63,0x31,0xd7,0xe8,0xa4,0x67,0xf1,0x9e,0x84,0x77,0x2f,0xfa,0xb4,0xad,0x57, + 0xe0,0x9c,0xe8,0x97,0x9d,0x5e,0xc4,0xff,0x6b,0x4f,0x53,0x2f,0x9d,0xf2,0x2f,0xe1, + 0xaf,0x73,0xea,0xb1,0x2a,0xe9,0x58,0x8f,0xe2,0xf3,0xd0,0xbe,0x60,0x3e,0x19,0xf8, + 0xca,0xa7,0xcf,0xf4,0x2c,0x9c,0xd3,0x71,0x1f,0x51,0xc8,0x61,0x97,0xad,0xd3,0xd6, + 0x1c,0x67,0x37,0x68,0xff,0x2e,0xe2,0x84,0xdf,0x46,0xcf,0xbb,0x5c,0xdd,0xf8,0x27, + 0xb5,0x0a,0xe4,0xd2,0x77,0xc9,0x2c,0xc9,0x59,0x76,0x23,0x19,0x27,0x39,0xd6,0x82, + 0x13,0xd5,0xec,0xe3,0x5c,0x7b,0xa9,0xd9,0xc7,0x5c,0x85,0x5d,0x87,0x4f,0x3f,0x35, + 0xe4,0x7f,0x01,0x5b,0xd6,0xd9,0x07,0x98,0x97,0xec,0x83,0xd8,0x95,0xff,0x9c,0x75, + 0x3a,0x84,0x5f,0x81,0x99,0x07,0x17,0x37,0x7c,0xaa,0xce,0x38,0xf3,0x54,0x9e,0x09, + 0xee,0x59,0x8e,0xbe,0x26,0xb8,0xeb,0x51,0xdc,0x4f,0xbb,0xcd,0xa3,0x69,0x4b,0x85, + 0x7f,0x5f,0xca,0xe9,0xca,0x31,0x75,0x32,0xbb,0x66,0x0e,0xe9,0xd3,0xce,0x3e,0x4b, + 0xbe,0x0c,0xf6,0x59,0xde,0x52,0x52,0x63,0x0e,0x1e,0xff,0xab,0x31,0xcf,0x7e,0x8e, + 0x1c,0xd2,0x4b,0x60,0x9a,0xd9,0x63,0x72,0x68,0xc6,0xb7,0xec,0xce,0xa6,0xd9,0x07, + 0xea,0xfc,0x34,0x44,0xef,0xe4,0x0e,0xf7,0x61,0x85,0x99,0x17,0xed,0x84,0x35,0xc3, + 0xa7,0x60,0x2b,0xae,0x7e,0x95,0x7b,0xf5,0x0c,0xfb,0x7d,0xcb,0xa0,0xb9,0x94,0x99, + 0x5d,0x3f,0xf9,0xe4,0xb3,0x0a,0x7e,0x64,0x3e,0xd2,0x9f,0x13,0xb7,0x4a,0x9c,0xe6, + 0xb5,0x4e,0xdc,0x00,0x71,0xea,0x77,0x03,0xfc,0x9b,0xf9,0x68,0x86,0x15,0x30,0xcd, + 0xf0,0x87,0x75,0xbe,0x43,0x3f,0xbf,0xcd,0x5f,0xb6,0x4d,0x93,0x1d,0xf8,0x68,0x3f, + 0x6f,0x71,0x3a,0xd7,0x2d,0x6a,0xea,0x7b,0xcf,0x9c,0xb7,0xc1,0x4b,0xa6,0xa9,0xa7, + 0x0f,0x60,0x89,0xdf,0x2f,0xcb,0x91,0xe4,0xd2,0xfa,0xdd,0xbc,0xe4,0xf7,0x11,0x9f, + 0x56,0x62,0x36,0x1d,0x87,0x5d,0x38,0x0c,0x3b,0x0e,0x7b,0xe0,0x09,0x87,0x2a,0x58, + 0xc2,0xa1,0xee,0x38,0xc8,0x56,0x33,0xa9,0x53,0xb7,0xe6,0x38,0xbc,0xa4,0x76,0xca, + 0x71,0xd8,0x07,0x4f,0x38,0x1c,0x81,0x25,0x7e,0xe2,0x90,0xe4,0xaa,0x3b,0x0e,0xc7, + 0xf8,0xec,0x10,0x53,0x73,0x1c,0x5e,0xc1,0x61,0xdc,0x71,0x78,0x0d,0x9e,0x70,0x78, + 0x03,0x96,0x70,0x38,0x74,0x1c,0x64,0x6b,0x98,0x1c,0x52,0xb7,0xc1,0x3d,0x52,0xdd, + 0xb7,0xd4,0x3e,0x76,0xf7,0x57,0x3d,0x26,0xbe,0x87,0xae,0xc7,0x4f,0xf8,0xd5,0x89, + 0x6b,0xd0,0x8f,0xde,0xd1,0x43,0xde,0x50,0xd9,0x3c,0x75,0x5f,0x67,0xc0,0x14,0x73, + 0x8f,0xbb,0xa7,0x73,0xd3,0xdb,0x7c,0x84,0x5d,0xdf,0x5d,0xeb,0x75,0x12,0x4c,0xb9, + 0xf4,0x5e,0x16,0x78,0x2b,0xca,0xa5,0x77,0xb2,0x04,0x76,0x3a,0x97,0xce,0xe1,0x09, + 0x76,0x7d,0xef,0x98,0xc1,0x32,0xb8,0x72,0x17,0xd1,0xff,0x18,0xbb,0x71,0x93,0xbf, + 0x2c,0x5d,0x24,0xfc,0x9c,0x07,0x00,0x00 }; // Generated from: @@ -79,6 +79,7 @@ constexpr uint8_t kBlitResolve_frag_00000016[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000017.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000017.inc index 2fb392df3d0..4420eb78a23 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000017.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000017.inc @@ -10,55 +10,55 @@ #pragma once constexpr uint8_t kBlitResolve_frag_00000017[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x94,0xdd,0x4f,0x53,0x41, - 0x10,0xc5,0xb7,0xbd,0xd0,0x82,0x5a,0x28,0xc1,0x82,0x18,0x23,0x28,0x3e,0x98,0x28, - 0x84,0x07,0x35,0x24,0x46,0xa3,0x0f,0x20,0x98,0xaa,0x7c,0x09,0x88,0x0f,0x0d,0x42, - 0x13,0xab,0x7c,0x49,0xd1,0x54,0x25,0x98,0xa2,0x8d,0x3c,0x98,0x28,0x1a,0xfd,0x27, - 0xfc,0xfb,0x8c,0x1f,0x89,0x89,0x73,0xee,0xfd,0x2d,0xd9,0xf0,0xe0,0x4d,0xb6,0xbb, - 0x73,0x66,0xf6,0xcc,0x9c,0x9d,0xdd,0x46,0xe9,0xfe,0xac,0x73,0x29,0x77,0xc4,0xb5, - 0xb8,0x2f,0x2e,0xf9,0x3a,0x5c,0xda,0x90,0x64,0xfe,0xda,0xe9,0xcc,0xd7,0xea,0xa6, - 0x27,0x66,0x4b,0x23,0xf3,0x33,0xa5,0xea,0xe3,0xc5,0xe5,0xf2,0x66,0xa9,0xba,0x55, - 0x5e,0x5b,0xaa,0xac,0x94,0xca,0xb5,0x8d,0xf5,0xcd,0x2d,0x8b,0x3d,0xea,0x32,0xf1, - 0x9e,0x5b,0xc5,0xe9,0xe2,0x60,0x75,0x6b,0x79,0xf0,0xd2,0xe5,0x21,0x71,0xb5,0xb9, - 0x28,0xe6,0x94,0xaf,0xdd,0x72,0x34,0xd9,0xac,0xb1,0xba,0x58,0x59,0x13,0x9e,0xb7, - 0x31,0x6a,0x63,0x2e,0x5e,0x47,0xb1,0x2f,0x1b,0xac,0x8f,0x89,0xd3,0x56,0xf9,0x38, - 0x87,0x38,0x9c,0x1b,0x73,0xcd,0xae,0x8b,0x5a,0xfb,0x99,0x3d,0x96,0x02,0x6b,0x09, - 0xb0,0x34,0x58,0x3e,0xc0,0x22,0xb0,0x13,0x01,0xd6,0x04,0x76,0x2a,0xc0,0x9a,0xc1, - 0xfa,0x02,0x2c,0x03,0x76,0x2e,0xc0,0xb2,0x60,0xe7,0x03,0xac,0x05,0xec,0x62,0x80, - 0xb5,0x82,0x0d,0xc5,0xba,0xa2,0x83,0xfa,0xa4,0x71,0x14,0x8d,0x5d,0xd8,0xe3,0x36, - 0x9f,0x45,0x9f,0xb7,0xcf,0x04,0xf6,0x1c,0xf1,0xdf,0x3a,0x13,0x7b,0xe1,0x50,0xfc, - 0x02,0xf1,0x3a,0x93,0x4e,0xcb,0x92,0x8e,0xed,0x28,0xd6,0xae,0x75,0xc1,0x62,0x32, - 0x68,0x53,0x4c,0xb7,0xd9,0x59,0xf4,0xa5,0xe3,0x3a,0x22,0x97,0xc3,0x2f,0x5f,0x9b, - 0xcd,0x39,0xce,0xa9,0xcf,0x7e,0xdb,0xd9,0x27,0xfc,0x2a,0x76,0x3e,0xe0,0xea,0x20, - 0xde,0xe7,0x2a,0xc0,0xa5,0xef,0xb4,0x75,0xd6,0x9f,0x5b,0x07,0x23,0xc3,0xc8,0x31, - 0x17,0x82,0xa1,0x7c,0xdd,0x9c,0x5f,0x17,0xf9,0xba,0xe9,0x9f,0xb0,0x0b,0x68,0xe9, - 0x81,0x5f,0xf1,0x27,0xf1,0x65,0x03,0x7f,0x2f,0xb6,0xfc,0x7d,0xf8,0xc5,0x7f,0xdc, - 0xaa,0xec,0x27,0xae,0x40,0x6f,0x5d,0xb0,0x6f,0x80,0x7e,0x7a,0x7b,0x98,0xbd,0xe2, - 0x19,0xe1,0x3e,0xe5,0xa8,0x6b,0x84,0x3b,0x1d,0xc5,0xf5,0xb4,0x5a,0x2f,0x12,0x5f, - 0x0a,0xce,0x54,0x30,0x7c,0xad,0x63,0x07,0x7d,0x4b,0x38,0x64,0x8f,0x1f,0xaa,0xa1, - 0x08,0xa7,0xe2,0xef,0x90,0x3f,0xc3,0x59,0x4f,0xb0,0xf6,0xfe,0x59,0xd6,0x19,0xf8, - 0x66,0x79,0x63,0xbe,0xa6,0x79,0x74,0xff,0xaf,0xa6,0x07,0xac,0xe7,0xe1,0x90,0xbd, - 0x00,0xa6,0x9c,0x8f,0xe0,0xd0,0x7d,0xb8,0x62,0xf7,0x3b,0xcd,0xda,0x91,0xe7,0x97, - 0x21,0x7a,0x3f,0xd7,0xb8,0x3b,0x15,0xee,0xc7,0x3d,0xeb,0x80,0xfa,0xfd,0x04,0xac, - 0x12,0xd4,0xb0,0xc6,0x1d,0x7c,0x8a,0xff,0xa6,0x31,0xa8,0x8f,0x2b,0xf4,0xba,0x07, - 0x3e,0xc5,0xac,0x82,0xef,0x5a,0x8c,0xec,0x75,0xf6,0xad,0xb2,0x4f,0xfd,0xdd,0x60, - 0x5f,0x2f,0xfb,0x54,0xef,0x33,0xf0,0xef,0x16,0xa3,0x9e,0x6f,0x82,0xa9,0xe7,0x3f, - 0xad,0xf2,0x1a,0xf5,0xfc,0xb1,0x78,0xf9,0xaa,0x36,0x6a,0xe8,0xd1,0x7a,0xd2,0xf6, - 0xe9,0x5c,0x9f,0x93,0x53,0xdf,0x0e,0x3d,0x7a,0x01,0x3e,0x65,0x96,0x6a,0xfa,0x00, - 0xe6,0xe3,0x7e,0x1b,0x87,0xe7,0xd2,0xfc,0xc3,0xa2,0x14,0xf7,0x89,0x98,0x66,0xf6, - 0x54,0x03,0x0d,0x2f,0xd1,0x30,0x10,0x68,0x78,0x05,0xee,0x35,0xbc,0x06,0xf3,0x1a, - 0xea,0x81,0x06,0xf9,0xb6,0x6d,0xd4,0xc9,0xbb,0x1d,0x68,0xd8,0x21,0x77,0x2a,0xd0, - 0xf0,0x06,0xdc,0x6b,0xf8,0x08,0xe6,0xe3,0xa4,0xc1,0x73,0xd5,0x03,0x0d,0xfb,0xc4, - 0xd4,0xd8,0xb3,0x1d,0x68,0xd8,0x45,0xc3,0x70,0xa0,0xe1,0x2d,0xb8,0xd7,0xf0,0x0e, - 0xcc,0x6b,0xd8,0x0b,0x34,0xc8,0xd7,0xb0,0xb1,0x47,0xde,0x06,0xf7,0x48,0x79,0xdf, - 0x93,0x7b,0x3f,0xb8,0xbf,0xaa,0xd1,0xc7,0xee,0x05,0x35,0x7e,0x26,0xae,0xce,0xbe, - 0x06,0xf5,0xe8,0xdd,0xdd,0xe6,0xcd,0xa9,0x66,0xbd,0xaf,0xbb,0xd4,0x5c,0x24,0x26, - 0x13,0xe7,0x4c,0x70,0x7f,0x7e,0x93,0x70,0xba,0x00,0x9b,0x02,0x53,0x2d,0x13,0x86, - 0xe8,0x6d,0x4e,0x13,0x3b,0x05,0x47,0xc9,0xaa,0xd1,0x9b,0x98,0x21,0xaf,0xfc,0x37, - 0xb8,0xdf,0xe2,0xd1,0xff,0xc5,0x7d,0xfc,0xfa,0xae,0xdb,0x79,0x8c,0x82,0xa9,0x16, - 0xbd,0xc9,0x87,0xbc,0x47,0x71,0xe9,0x2d,0x2e,0x81,0x1d,0xe6,0xd2,0x59,0x2f,0xe3, - 0x77,0x71,0x5f,0x12,0x2d,0x65,0x70,0x71,0xcf,0x61,0xff,0xb5,0xaa,0x87,0x6d,0xfc, - 0x03,0x12,0x2d,0xde,0x48,0x18,0x08,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x7d,0x94,0x5d,0x4f,0x93,0x41, + 0x10,0x85,0xb7,0x7d,0xa1,0x05,0xb4,0x50,0x82,0x05,0x31,0x46,0x50,0xbc,0x30,0x51, + 0x08,0x17,0x68,0x48,0x8c,0x46,0x2f,0x40,0x30,0x55,0xf9,0x12,0x10,0x2f,0x1a,0x84, + 0x26,0x56,0xf9,0x92,0xa2,0xa9,0x4a,0x30,0x45,0x89,0xbd,0x30,0x51,0x34,0xfa,0x27, + 0xfc,0x7d,0xc6,0x8f,0xc4,0xc4,0x39,0x6f,0x9f,0x25,0x9b,0x5e,0xf8,0x26,0xdb,0xdd, + 0x39,0x33,0x3b,0x73,0xce,0xce,0x6e,0xa3,0xe4,0x40,0xda,0xb9,0x84,0x6b,0x73,0x2d, + 0xee,0x8b,0xab,0x7f,0x9d,0x2e,0x69,0x48,0x7d,0xfe,0xda,0xe5,0xcc,0xd7,0xea,0x66, + 0xa7,0xe6,0x0b,0x63,0x8b,0x73,0x85,0xf2,0xe3,0xe5,0xd5,0xe2,0x76,0xa1,0xbc,0x53, + 0xdc,0x58,0x29,0xad,0x15,0x8a,0x95,0xad,0xcd,0xed,0x1d,0x8b,0x3d,0xe6,0x52,0xf1, + 0x9e,0x5b,0xf9,0xd9,0xfc,0x50,0x79,0x67,0x75,0x68,0xe4,0xf2,0xb0,0x72,0xb5,0xbb, + 0x28,0xce,0x29,0x5f,0x87,0xd5,0x68,0xb2,0x59,0x63,0x7d,0xb9,0xb4,0x21,0x3c,0x6b, + 0x63,0xdc,0xc6,0x42,0xbc,0x8e,0x62,0x5f,0x3a,0x58,0x1f,0x57,0x4e,0x5b,0x65,0xe3, + 0x1a,0xca,0xe1,0xdc,0x84,0x6b,0x76,0xdd,0x70,0x1d,0x60,0xf6,0x58,0x02,0xac,0x25, + 0xc0,0x92,0x60,0xd9,0x00,0x8b,0xc0,0x4e,0x06,0x58,0x13,0xd8,0xe9,0x00,0x6b,0x06, + 0xeb,0x0f,0xb0,0x14,0xd8,0xf9,0x00,0x4b,0x83,0x5d,0x08,0xb0,0x16,0xb0,0x4b,0x01, + 0xd6,0x0a,0x36,0x1c,0x60,0x6d,0x60,0x23,0xb1,0xd6,0xe8,0x88,0xb3,0x74,0x8f,0xa3, + 0xbb,0x1b,0x7b,0xd2,0xe6,0x73,0x68,0xf6,0xf6,0xd9,0xc0,0x5e,0x20,0xfe,0x5b,0x57, + 0xdd,0x5e,0x6a,0x88,0x5f,0x22,0x5e,0xe7,0xd4,0x65,0x55,0x92,0xb1,0x1d,0xc5,0xe7, + 0xa1,0x75,0xce,0x62,0x52,0xe8,0x55,0x4c,0x8f,0xd9,0x69,0x34,0x27,0x63,0x1e,0x91, + 0xcb,0xe0,0x97,0xaf,0xdd,0xe6,0x0c,0x67,0xd7,0x6f,0xbf,0x1d,0xec,0x13,0x7e,0x15, + 0x3b,0x1b,0xe4,0xea,0x24,0xde,0xd7,0xca,0x91,0x4b,0xdf,0x19,0xf3,0xf8,0xb3,0xec, + 0x64,0xa4,0x82,0x91,0x61,0xce,0x05,0x43,0x35,0x7b,0x38,0xd7,0x6e,0x6a,0xf6,0xd0, + 0x57,0x61,0x17,0xd1,0xd3,0x4b,0x0d,0xc5,0x9f,0xc2,0x97,0x0e,0xfc,0x7d,0xf4,0x4b, + 0xfe,0x7e,0xfc,0xca,0x7f,0xc2,0x98,0x0e,0x10,0x97,0xa3,0xe7,0x2e,0xd8,0x37,0xd8, + 0x50,0x67,0x94,0x7e,0x2a,0xcf,0x18,0xf7,0x2c,0x03,0xaf,0x31,0xee,0x7a,0x14,0xf3, + 0x69,0xb5,0x7e,0xd4,0x7d,0x09,0x72,0x26,0x82,0xe1,0xb9,0x4e,0x1c,0xf5,0xae,0x9e, + 0x43,0xf6,0x64,0x03,0x87,0x7c,0x70,0xfe,0x77,0xe0,0x93,0xe2,0xbc,0xa7,0x58,0x47, + 0xf8,0xe7,0x59,0xa7,0xc8,0x37,0xcf,0xdb,0xf3,0x9c,0x16,0xd1,0xfd,0x3f,0x4e,0x0f, + 0x58,0x2f,0x92,0x43,0xf6,0x12,0x98,0x6a,0x3e,0x22,0x87,0x38,0x5d,0xb1,0x3b,0x9e, + 0x64,0xed,0xa8,0xf3,0xcb,0x10,0xbd,0xab,0x6b,0xdc,0x9f,0x12,0x77,0xe4,0x9e,0x75, + 0x44,0x3d,0x7f,0x02,0x56,0x0a,0x38,0x6c,0x70,0x0f,0x9f,0xe2,0xbf,0x69,0x19,0xd4, + 0xc7,0x35,0x7a,0xdd,0x4b,0x3e,0xc5,0xac,0x83,0xef,0x5b,0x8c,0xec,0x4d,0xf6,0xad, + 0xb3,0x4f,0xfd,0xdd,0x62,0x5f,0x1f,0xfb,0xc4,0xf7,0x19,0xf8,0x77,0x8b,0x51,0xcf, + 0xb7,0xc1,0xd4,0xf3,0x9f,0xc6,0xbc,0x02,0x9f,0x3f,0x16,0x2f,0x5f,0xd9,0x46,0x05, + 0x3d,0x5a,0x4f,0xdb,0x3e,0x9d,0xeb,0x73,0x6a,0xea,0xdb,0xa3,0x47,0x2f,0xc0,0x67, + 0xcc,0x12,0xa7,0x0f,0x60,0x3e,0xee,0xb7,0xe5,0xf0,0xb9,0x34,0xff,0xb0,0x28,0xc5, + 0x7d,0x22,0xa6,0x99,0x3d,0xe5,0x40,0xc3,0x4b,0x34,0x0c,0x06,0x1a,0x5e,0x81,0x7b, + 0x0d,0xaf,0xc1,0xbc,0x86,0x6a,0xa0,0x41,0xbe,0x5d,0x1b,0x55,0xea,0xee,0x06,0x1a, + 0xf6,0xa8,0x9d,0x08,0x34,0xbc,0x01,0xf7,0x1a,0x3e,0x82,0xf9,0x38,0x69,0xf0,0xb9, + 0xaa,0x81,0x86,0x43,0x62,0x2a,0xec,0xd9,0x0d,0x34,0xec,0xa3,0x61,0x34,0xd0,0xf0, + 0x16,0xdc,0x6b,0x78,0x07,0xe6,0x35,0xd4,0x02,0x0d,0xf2,0x1d,0xd8,0xa8,0x51,0xf7, + 0x80,0x7b,0xa4,0xba,0xef,0xa9,0x7d,0x18,0xdc,0x5f,0x71,0xf4,0xb1,0xb5,0x80,0xe3, + 0x67,0xe2,0xaa,0xec,0x3b,0x80,0x8f,0xde,0xdd,0x6d,0xde,0x9c,0x38,0xeb,0x7d,0xdd, + 0x85,0x73,0x9e,0x98,0x54,0x5c,0xb3,0x8e,0xfb,0xf3,0x9b,0x26,0xa7,0x0b,0xb0,0x19, + 0x30,0x71,0x99,0x32,0x44,0x6f,0x73,0x96,0xd8,0x19,0x72,0x14,0x8c,0x8d,0xde,0xc4, + 0x1c,0x75,0xe5,0xbf,0xc1,0xfd,0x56,0x1e,0xfd,0x5f,0xdc,0xc7,0xaf,0xef,0xba,0x9d, + 0xc7,0x38,0x98,0xb8,0xe8,0x4d,0x3e,0xe4,0x3d,0x2a,0x97,0xde,0xe2,0x0a,0x58,0x63, + 0x2e,0x9d,0xf5,0x2a,0x7e,0x17,0xf7,0xa5,0xae,0xa5,0x08,0xae,0xdc,0x0b,0xd8,0x7f, + 0x8d,0xf5,0xa8,0x8d,0x7f,0x03,0x23,0x4c,0x84,0x30,0x08,0x00,0x00 }; // Generated from: @@ -82,6 +82,7 @@ constexpr uint8_t kBlitResolve_frag_00000017[] = { // ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; +// int srcMip; // int srcLayer; // int samples; // float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc index 03d219611c2..cfcbc40a413 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc @@ -10,83 +10,96 @@ #pragma once constexpr uint8_t kBlitResolveStencilNoExport_comp_00000000[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x6d,0x96,0xdb,0x6f,0x94,0x45, - 0x18,0xc6,0xbf,0xdd,0x6d,0x77,0xcb,0x6a,0x5b,0xaa,0x2d,0x60,0x0b,0x94,0x5a,0x83, - 0x87,0x25,0x88,0x09,0x27,0x03,0x2b,0x85,0x08,0x62,0x4b,0x44,0xc0,0x6e,0x34,0xa8, - 0xad,0xc6,0x0b,0xb8,0xe8,0x21,0x29,0xb1,0xb6,0x41,0x6d,0x69,0x45,0xc4,0xa2,0x41, - 0x40,0x03,0x91,0x18,0x12,0x13,0xa9,0x4d,0xd0,0x6a,0x8c,0x05,0x8c,0x37,0x9e,0x2e, - 0x10,0xc4,0x2b,0xfc,0x47,0x3c,0xc7,0xe8,0xfb,0xcc,0xfe,0xc6,0xbc,0x6e,0xfc,0x92, - 0xc9,0xec,0x3c,0xef,0xf9,0x34,0xb3,0x99,0x74,0x7b,0x2e,0x49,0x52,0x49,0x3e,0xa9, - 0x49,0x7e,0x4a,0xca,0x5f,0x43,0x92,0x36,0x24,0x49,0x6e,0x4a,0xb2,0x61,0x7f,0x68, - 0xc7,0x9e,0x1d,0x2b,0x87,0x0e,0x3c,0xb7,0x72,0xf5,0x9a,0x55,0xa2,0xd7,0x25,0x99, - 0xc0,0x27,0x5a,0xbd,0xf1,0x54,0xdb,0x5e,0x65,0xab,0xef,0x99,0xfd,0xfd,0xc2,0x6b, - 0x6d,0xcd,0x37,0xbc,0x2a,0xe8,0x4a,0x4c,0x73,0x79,0x05,0x5d,0x86,0xd6,0x06,0xdd, - 0x49,0xb2,0xd8,0xd6,0x76,0x93,0x5e,0x82,0xdd,0x76,0xf6,0x88,0xa5,0xc0,0x6a,0x1c, - 0x96,0x06,0x9b,0xef,0xb0,0x0c,0xd8,0x22,0x87,0x55,0x81,0x79,0x1b,0xd5,0x60,0xcb, - 0x1c,0x96,0x05,0x5b,0xe5,0xb0,0x1c,0xd8,0x6a,0x87,0xd5,0x80,0xad,0x77,0xd8,0x3c, - 0xb0,0x8d,0x21,0xae,0xcc,0xbf,0xfe,0x29,0xc6,0x23,0xb6,0xdf,0x4e,0x3c,0xf1,0xdc, - 0xe6,0x72,0x30,0x55,0x41,0x9f,0x82,0x1e,0xe5,0xcf,0xe3,0x5b,0x15,0xf6,0xa6,0x2b, - 0x72,0x24,0x7b,0xd3,0xc4,0x2e,0xfe,0x99,0x0a,0x7d,0x33,0xe8,0x8b,0xe7,0x4b,0xe4, - 0xfc,0x36,0x5b,0xb7,0x9a,0x95,0x74,0xa0,0x67,0x82,0xbc,0x7e,0x37,0x19,0x4f,0x96, - 0xdc,0xc8,0xc7,0x85,0x76,0xce,0xe1,0x43,0xa4,0xe7,0xa1,0x27,0xd0,0xa5,0x2f,0x8f, - 0x0f,0xcb,0xec,0x7c,0x33,0xb2,0xc2,0x37,0x70,0xae,0x05,0x2b,0x20,0x5f,0x87,0xbc, - 0xf8,0xeb,0xa1,0xe5,0x1d,0xfd,0x16,0x62,0x8e,0xe7,0x26,0x78,0x16,0x98,0x95,0x66, - 0xec,0xcb,0x76,0x8b,0xed,0xcd,0xf8,0xa6,0xf3,0x62,0x97,0xaf,0xa5,0x66,0x59,0xb5, - 0x68,0x71,0x2b,0xcb,0x8a,0x7c,0x79,0xb7,0xe4,0xcb,0x52,0xea,0xb9,0x04,0xdf,0x75, - 0x6e,0x05,0x2b,0xb8,0xdc,0x54,0xc3,0xdf,0x06,0x4d,0xfa,0x1a,0xcd,0x8b,0xe5,0xf8, - 0x71,0xa7,0xed,0xcb,0xf1,0x2b,0xca,0xad,0x25,0x06,0xc9,0xad,0x43,0xae,0x05,0x7a, - 0x33,0xfd,0x63,0xdf,0xa6,0x15,0xa6,0x5d,0x78,0x11,0x6c,0xa3,0xd3,0xd1,0x41,0xde, - 0xe2,0x79,0x2b,0x7d,0x2a,0x9d,0xdb,0xd0,0x99,0x77,0xf4,0x5d,0xf4,0x6c,0x3c,0xef, - 0xad,0x88,0x65,0x9f,0xad,0xbf,0xed,0x8b,0xe7,0x21,0x97,0x77,0xf9,0x34,0xec,0xea, - 0xf4,0x22,0xb2,0xd9,0xd0,0x3f,0xf3,0x92,0xc3,0xd8,0x4a,0x25,0xff,0xfd,0x52,0x4e, - 0xe6,0x55,0x7e,0x1f,0x26,0x9f,0x3a,0x1f,0x01,0x6b,0xb6,0xec,0x1c,0x85,0xef,0x75, - 0xb0,0xa3,0xf0,0xe9,0x3c,0x05,0xd6,0x62,0x35,0x7f,0x03,0x1d,0xd1,0xcf,0xe3,0xae, - 0xe6,0xa7,0xf0,0xc3,0xf7,0xcb,0x69,0xc5,0x15,0xea,0x98,0x09,0x33,0x94,0x0f,0xfd, - 0x50,0x9e,0x95,0xf3,0xd8,0xfc,0x10,0x1d,0xd3,0xd8,0xd4,0x79,0xa6,0xa2,0x66,0x17, - 0x88,0x57,0xfc,0x9f,0x43,0xf3,0x7d,0x7a,0x91,0xfc,0xae,0x30,0x2e,0xf5,0xfb,0x25, - 0xb0,0x8b,0xf4,0xec,0x5a,0xab,0x65,0x1a,0xdf,0x12,0x66,0xe4,0x37,0x43,0xd4,0x3f, - 0xbf,0xda,0xe9,0x32,0xf8,0x9f,0xf6,0x5b,0x33,0xf1,0x05,0x74,0xed,0x9b,0x8d,0xab, - 0x9e,0x3b,0xae,0x96,0x99,0x29,0x62,0xb7,0x01,0x7c,0xd2,0x78,0xf2,0x61,0x96,0xcb, - 0x98,0xe6,0xe6,0x20,0xbe,0x37,0x82,0x47,0x3d,0x0b,0xd0,0xd3,0xe4,0xf4,0x2c,0x04, - 0x8f,0x32,0x8b,0xc0,0x1e,0x35,0x99,0x1c,0xf7,0x44,0x23,0xb8,0xf4,0xb4,0x71,0xbf, - 0xb4,0x32,0x07,0x45,0x66,0xae,0x1d,0x7c,0xa7,0x49,0x49,0xee,0x0e,0xb0,0x76,0x72, - 0xa6,0xb8,0x3f,0x35,0x79,0xcd,0xc5,0x5d,0xd0,0xa5,0xfb,0x8c,0xc9,0x6b,0x4e,0xee, - 0x06,0x57,0x4e,0x0a,0xe4,0xe4,0x0f,0xa3,0x09,0xbf,0x27,0xe4,0xbb,0x9c,0x17,0xfd, - 0xfe,0xdd,0xf6,0xcb,0x9c,0x0b,0xce,0xe6,0xbd,0xce,0x66,0xec,0xc3,0x31,0xe2,0xb8, - 0x0f,0x7b,0xe2,0x19,0xe0,0xde,0x58,0x03,0xae,0xb8,0xd6,0x71,0xa7,0xb7,0x32,0xa7, - 0x45,0x78,0xee,0x07,0x7f,0x85,0x99,0xdc,0x80,0x9c,0xf0,0x71,0xb0,0x4d,0xe0,0x45, - 0xa7,0x6b,0x33,0xba,0x3a,0x9c,0xae,0x2d,0xe0,0x13,0xc8,0x3d,0x88,0xec,0x16,0xe4, - 0xb6,0x85,0x3b,0xba,0x2c,0xb7,0xd5,0xd5,0x68,0x3b,0xf8,0x8c,0xf1,0x28,0x57,0x0f, - 0x83,0xd5,0x91,0xaf,0x2e,0x97,0x2f,0xd1,0x3a,0x6d,0x75,0x91,0x9f,0xce,0x70,0x07, - 0x54,0x87,0x59,0x7e,0x04,0x9b,0xfa,0x5e,0x66,0xbe,0x77,0x82,0xef,0xb6,0xea,0xcb, - 0xa7,0xaf,0xc0,0x22,0x9f,0x72,0x1d,0x75,0x69,0xff,0xd9,0xb2,0x29,0xbe,0xef,0xe1, - 0x29,0x20,0xd3,0xe9,0x62,0xd8,0x4d,0x0c,0xbb,0x5c,0x0c,0x7b,0xc0,0x63,0x0c,0x8f, - 0x81,0xc5,0x18,0x4a,0x2e,0x06,0xd1,0xba,0x6d,0x95,0xb0,0xdb,0xed,0x62,0x78,0x1c, - 0xdb,0x29,0x17,0xc3,0x13,0xe0,0x31,0x86,0x6f,0xc1,0x22,0x9f,0x62,0x88,0xba,0x4a, - 0x2e,0x86,0xab,0xf0,0x74,0x21,0xd3,0xed,0x62,0x78,0x92,0x18,0xf6,0xba,0x18,0x9e, - 0x02,0x8f,0x31,0x3c,0x0d,0x16,0x63,0xe8,0x75,0x31,0x88,0xd6,0x63,0xab,0x17,0xbb, - 0x3d,0xf4,0xa9,0xec,0x3e,0x8b,0xed,0xab,0xee,0xae,0x94,0x8f,0x91,0xb7,0xd7,0xf9, - 0xf8,0x23,0x7c,0x25,0xe4,0x7a,0xc2,0x7d,0x95,0x0d,0xb3,0xba,0x9f,0x5e,0xd8,0x47, - 0xcf,0x4a,0x47,0x1f,0x3a,0xfa,0x9c,0x8e,0xeb,0xe8,0x91,0xde,0x2b,0xb6,0x06,0xa1, - 0x29,0xa6,0x1f,0xf0,0x5f,0xb4,0x1b,0x8e,0x26,0xfd,0xd7,0xe8,0x5f,0xd1,0x3e,0x80, - 0x36,0x4b,0xec,0x07,0xa0,0xeb,0xbd,0xf8,0xc5,0xe2,0x1d,0x80,0x1e,0xe3,0x17,0xbd, - 0x3f,0xcc,0x5a,0xd9,0x9f,0x7e,0x57,0xc3,0xe7,0xf1,0x49,0xdf,0x97,0xe8,0x7b,0x01, - 0x7c,0x98,0x5c,0x8e,0x3a,0x5d,0xa2,0x8d,0xd8,0x1a,0x45,0xd7,0x08,0x75,0xd2,0x7b, - 0xf4,0x12,0x75,0x1a,0xa2,0x4e,0xd9,0xd0,0x17,0x65,0x7c,0x80,0xfe,0x18,0x03,0x9b, - 0xc3,0xd6,0x38,0xb6,0xc6,0xc8,0x59,0xd4,0x3b,0x4a,0xec,0xe2,0x39,0x84,0x4f,0xfd, - 0xf0,0x8f,0xe0,0xd7,0xa4,0xf3,0xeb,0x50,0x98,0xe5,0x24,0x60,0x92,0x9f,0xc0,0x07, - 0xbd,0x53,0xaf,0xf1,0xce,0xe9,0xac,0x37,0xed,0x18,0xef,0x59,0xc9,0x7c,0xd0,0x5b, - 0xf6,0x26,0x3c,0xc7,0xdc,0x9d,0xf1,0x16,0xb1,0x1c,0x77,0x77,0xc6,0x09,0xf0,0x78, - 0xff,0x9c,0x24,0x77,0x27,0x42,0xcf,0xe7,0xc2,0xdb,0xf7,0x36,0xfa,0x4e,0x72,0xd7, - 0x0e,0x93,0x6b,0xd5,0xf7,0x1d,0xe8,0xfa,0xbe,0x03,0x3b,0x03,0x7e,0x9a,0xf7,0x43, - 0x39,0x7b,0x97,0x7a,0x6a,0x66,0xbf,0x86,0xef,0x2c,0xbc,0xa2,0x7d,0x03,0xf6,0x1e, - 0x3d,0x73,0x96,0xdc,0xc5,0xd8,0x27,0x5d,0x4f,0xdd,0x80,0x67,0x14,0xfe,0x09,0x57, - 0x8b,0x73,0xf4,0xed,0x38,0xbd,0xf0,0x3e,0xb5,0x38,0xe7,0xe6,0xf7,0x0a,0xf8,0x75, - 0x37,0x1b,0x83,0xd8,0x19,0xe4,0x4e,0xcf,0xd2,0x93,0xd7,0xfe,0xa7,0xf7,0x07,0x5c, - 0x7f,0x7c,0x44,0x4e,0x2f,0xb8,0xfe,0xf8,0x18,0xfc,0x20,0x73,0x3d,0x0b,0x16,0xdf, - 0xd2,0x4f,0x78,0x03,0x67,0xb1,0x25,0xec,0x33,0xf0,0x86,0xa0,0x3b,0x1b,0xfe,0x0b, - 0xcc,0xf1,0x7f,0xa1,0x03,0xfa,0x03,0xd6,0x1f,0x73,0xc4,0xee,0xdf,0x28,0xed,0x7f, - 0xd9,0xa4,0xaf,0xb7,0xf5,0x0f,0x1b,0x39,0x83,0xf3,0x68,0x0d,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x6d,0x96,0x6d,0x4c,0x95,0x65, + 0x18,0xc7,0x9f,0x73,0x0e,0x9c,0x83,0x47,0x01,0x49,0x50,0x5e,0x7c,0x89,0x70,0x5a, + 0x1d,0x66,0xb6,0x25,0xd9,0x94,0x44,0x97,0xa6,0xe0,0x32,0x35,0x58,0xcd,0x0a,0x6a, + 0x7d,0x81,0x2d,0x65,0xcb,0x0f,0x02,0x4e,0xe3,0x6d,0xab,0x2c,0x58,0xc1,0x66,0x51, + 0xc9,0x4c,0x0d,0x2d,0xd3,0x2c,0x5b,0xcc,0x0f,0x30,0x97,0x99,0x5b,0x5b,0x12,0x9b, + 0x65,0x5b,0xcb,0x97,0xbe,0xb5,0xf5,0xcd,0x22,0x94,0x5e,0xae,0xeb,0x7e,0x7e,0xb7, + 0xbb,0x76,0xd6,0xd9,0xee,0x3d,0xcf,0xfd,0xbf,0x5e,0xff,0xd7,0x7d,0xdd,0xd7,0x79, + 0x62,0xd1,0xb2,0x44,0x10,0x44,0x82,0x64,0x90,0x15,0x14,0x47,0x02,0xf7,0xcb,0x0b, + 0xa2,0x81,0xbe,0x4e,0x0f,0xe2,0xee,0xf9,0xe8,0xc6,0xad,0x1b,0x97,0xbc,0xb4,0xf3, + 0x85,0x25,0x0f,0x2c,0x5b,0xaa,0xf2,0x9c,0x20,0xe6,0xf4,0x54,0x96,0x2b,0x3a,0x99, + 0xf2,0xcc,0x90,0xf5,0xe2,0x73,0x8d,0xdb,0x15,0xcf,0x96,0x35,0x53,0xf0,0x0c,0xe7, + 0x2b,0x10,0xcf,0xe1,0x72,0xbe,0x04,0xcd,0x76,0xbe,0x83,0x60,0xae,0xac,0xf5,0x62, + 0x3d,0x2f,0x0c,0x1b,0x94,0xf1,0xf4,0x58,0x04,0x2c,0xcb,0x60,0x51,0xb0,0x99,0x06, + 0x8b,0x81,0x15,0x1a,0x2c,0x03,0xcc,0xc6,0xc8,0x04,0xbb,0xd3,0x60,0x71,0xb0,0x85, + 0x06,0x4b,0x80,0xdd,0x6d,0xb0,0x2c,0xb0,0x72,0x83,0x4d,0x03,0x5b,0x6a,0xb0,0x24, + 0x58,0x95,0xe3,0x1a,0xbb,0x9d,0xb3,0xf2,0x3e,0x24,0xcf,0xbb,0xe0,0xe8,0xf7,0xa5, + 0xa6,0x2e,0x43,0x69,0xf2,0x21,0xe4,0xde,0xfe,0x22,0xf9,0x66,0x10,0x6f,0x2c,0xad, + 0x6e,0x1a,0x6f,0x8c,0x7a,0xa8,0xfe,0x78,0x9a,0xbf,0x71,0xfc,0xf9,0xfd,0x35,0xce, + 0xa1,0x48,0xd6,0x2c,0x89,0x12,0x75,0xf2,0x98,0xb3,0xd7,0xf7,0x02,0xd1,0x89,0x53, + 0x2f,0xcd,0x71,0x8e,0xec,0x13,0xe4,0xe0,0xe5,0x49,0xe4,0x01,0xf2,0xe9,0xd4,0x20, + 0xe6,0xf0,0x8c,0x60,0x06,0xb6,0x8a,0xaf,0x60,0x9f,0x0d,0x96,0xc2,0x3e,0x07,0x7b, + 0xd5,0xcf,0x45,0x96,0x34,0xf2,0x3b,0xe0,0xec,0xf7,0x05,0xe8,0xcc,0x96,0x28,0xc5, + 0xc4,0xd7,0xd8,0x25,0xf2,0x2c,0x26,0x37,0xdd,0xcf,0x35,0xf5,0x9a,0x2f,0x51,0xf5, + 0x2c,0x4a,0xcc,0x8a,0x9b,0x95,0x34,0xcb,0xdb,0x69,0x3e,0xf3,0x39,0xe7,0x79,0xe4, + 0xaf,0xfb,0x05,0x60,0x29,0x53,0x9f,0x69,0xe8,0x97,0xf2,0xae,0x3e,0xf2,0x25,0x93, + 0x45,0xe4,0xb2,0x58,0x9e,0x8b,0xc8,0xcd,0xdb,0x55,0xc0,0x43,0xed,0x1e,0xc4,0xae, + 0x04,0xb9,0xf2,0x58,0x19,0x96,0x65,0x55,0xb9,0x9c,0xb5,0xe2,0x95,0x60,0x2b,0x8d, + 0x8f,0x2a,0x6a,0xe7,0xf7,0x6b,0x4d,0xee,0xeb,0xf0,0x99,0x34,0xf2,0xcd,0xf4,0xb7, + 0xdf,0x6f,0xa3,0xb7,0xfd,0x5e,0x2f,0xf0,0xbf,0xf2,0xf3,0xfb,0x3d,0xa6,0xf6,0x9a, + 0x53,0x87,0x39,0xab,0x57,0xf0,0x1f,0x37,0xf6,0xfb,0xb9,0x67,0x45,0x22,0x39,0x48, + 0x6c,0xc6,0xca,0xed,0x5f,0xc4,0xf8,0xf8,0x80,0xf7,0x83,0xd4,0x57,0xf7,0x87,0xc0, + 0x8a,0xa5,0x5a,0x47,0xd0,0xfb,0x10,0xec,0x08,0x7a,0xba,0x1f,0x02,0x2b,0x91,0x3e, + 0x38,0x86,0x0f,0x9f,0xc7,0x71,0xd3,0x07,0x9f,0x92,0x87,0xed,0xa1,0xd3,0xca,0xd3, + 0x9d,0x6b,0xcc,0xdd,0xab,0xa4,0xeb,0x91,0xf0,0xfe,0x5c,0x24,0xe6,0xf7,0xf8,0x18, + 0x23,0xa6,0xee,0xc7,0xd3,0xce,0xf0,0x12,0xb6,0xaa,0xff,0x0b,0x32,0xdb,0xbb,0x57, + 0xa9,0x6f,0xb9,0x68,0xeb,0x1d,0xb8,0x06,0x76,0x95,0x3e,0xae,0x90,0x6a,0x45,0xc9, + 0x2d,0xe0,0xde,0xfc,0x25,0x88,0xd6,0x70,0x42,0x76,0xd7,0xc1,0x6f,0xc9,0xbb,0xde, + 0x93,0x5f,0x91,0xeb,0x73,0xb5,0x68,0xe5,0x32,0x0b,0xb3,0xb9,0x47,0x95,0xc4,0xcd, + 0x03,0xef,0x12,0x9d,0xa4,0xbb,0xdf,0x21,0xa6,0x77,0x69,0x37,0xb9,0xe7,0x83,0x7b, + 0x3f,0xb3,0xf1,0x53,0x60,0xfc,0xcc,0x01,0xf7,0x36,0x85,0x60,0x8f,0x8b,0x4d,0x82, + 0xd9,0x91,0x0f,0xae,0x7e,0x4a,0x99,0x39,0x0b,0xb8,0x17,0x95,0xdc,0xc3,0x32,0xf0, + 0x4d,0x62,0x95,0x60,0xde,0x96,0xb1,0xa2,0xf0,0xfe,0x5c,0xec,0x17,0x33,0x77,0x17, + 0xe2,0x7b,0x40,0xec,0xf5,0xde,0xdc,0x03,0xae,0x35,0x49,0x51,0x93,0x9b,0x22,0x53, + 0xfc,0x5e,0x57,0xef,0xb0,0x2e,0xfa,0x3e,0x29,0xcf,0xeb,0xec,0x53,0x26,0xe6,0x7d, + 0x26,0xa6,0xef,0xc3,0x97,0xe1,0x71,0x3f,0xf1,0x54,0x67,0x07,0xb3,0x64,0x19,0xb8, + 0xf2,0xd2,0xfb,0xb9,0x1c,0x5e,0x15,0xf0,0x52,0x9d,0x87,0xc0,0xbb,0xb9,0xa3,0x2b, + 0xb0,0x53,0xbc,0x1d,0x6c,0x15,0x78,0xa5,0xf1,0xb5,0x1a,0x5f,0x55,0xc6,0xd7,0x1a, + 0xf0,0x4e,0xec,0x1e,0xc1,0x76,0x0d,0x76,0xeb,0xdc,0xdc,0x0e,0xed,0xd6,0x9a,0x33, + 0x5a,0x0f,0xfe,0xb1,0xe8,0x68,0xad,0x36,0x80,0xe5,0x50,0xaf,0x1a,0x53,0x2f,0x95, + 0x55,0xcb,0xaa,0xa1,0x3e,0xd5,0x6e,0x26,0x64,0xba,0xbb,0xfd,0x18,0x31,0xf5,0xb7, + 0x97,0xfb,0xbe,0x09,0x7c,0x8b,0x9c,0xbe,0xe6,0xf4,0x1b,0x98,0xd7,0xd3,0x5a,0x7b, + 0x5f,0xfa,0xfc,0x43,0xaa,0x59,0xe2,0xf6,0xa1,0x4e,0x0a,0x9b,0x6a,0xc3,0x61,0x0b, + 0x1c,0x36,0x1b,0x0e,0x5b,0xc1,0x3d,0x87,0x27,0xc0,0x3c,0x87,0x3a,0xc3,0x41,0x65, + 0xb5,0xb2,0xea,0x88,0x5b,0x6b,0x38,0x3c,0x49,0xec,0x88,0xe1,0xf0,0x14,0xb8,0xe7, + 0xf0,0x3b,0x98,0xd7,0x53,0x0e,0xde,0x57,0x9d,0xe1,0x30,0x89,0x4e,0x0d,0x36,0xb5, + 0x86,0xc3,0xd3,0x70,0xd8,0x66,0x38,0x3c,0x03,0xee,0x39,0x3c,0x0b,0xe6,0x39,0x34, + 0x18,0x0e,0x2a,0xab,0x97,0xd5,0x40,0xdc,0x7a,0xfa,0x54,0xe3,0x3e,0x4f,0xec,0x49, + 0x33,0x2b,0x35,0x47,0xaf,0xdb,0x60,0x72,0xfc,0x07,0xbd,0x3a,0xec,0xea,0x89,0xd5, + 0x94,0x16,0xab,0x51,0x56,0x33,0xf6,0xfa,0x7e,0x4c,0x6a,0x11,0x77,0xbd,0x1e,0xd6, + 0x7a,0x3b,0x7d,0xad,0x71,0x9a,0xd0,0x6b,0x36,0x7a,0x3b,0xe9,0xab,0xff,0xd3,0x6b, + 0x22,0x1f,0xd5,0x9b,0x15,0x09,0x7d,0x36,0xd2,0xdb,0xcd,0x46,0x36,0x23,0x12,0x62, + 0x8d,0xf8,0x6b,0xc6,0xcf,0x2e,0xfc,0xec,0x32,0xbc,0xa6,0xe0,0xa6,0xbe,0x8b,0xc4, + 0xae,0x0d,0x59,0xd2,0xcd,0xc2,0xb0,0xa6,0x2a,0x2b,0x34,0xb2,0xb8,0xe3,0x1b,0xc6, + 0x50,0xd9,0x77,0x41,0x28,0x3b,0xc5,0x79,0xec,0x45,0xae,0xff,0x69,0x7f,0x4a,0x5d, + 0x5a,0x91,0xfb,0x3a,0xa9,0xbc,0x45,0x56,0x2b,0xf9,0xb4,0x98,0xbe,0x6a,0x27,0x27, + 0xfd,0x8d,0xe0,0xaf,0x13,0xbc,0x83,0x9a,0x77,0x1b,0x5f,0x9d,0x6e,0xf6,0x06,0x0e, + 0x53,0x5f,0x5d,0xf4,0x8e,0xfe,0x67,0xbe,0x4a,0xef,0xec,0xa1,0x77,0x34,0xef,0xd7, + 0xc0,0x77,0xd0,0xb3,0xfb,0xc0,0x86,0x89,0xf5,0x3a,0xb1,0xf6,0x51,0x33,0xef,0xb7, + 0x1b,0xee,0xaa,0xf3,0x06,0x39,0xb5,0xa0,0xdf,0x45,0x5e,0xbd,0x26,0x2f,0xd5,0xe9, + 0x91,0xd5,0x8b,0x7d,0x8f,0xe1,0xf8,0x26,0x1c,0x23,0x86,0xe3,0x5b,0xe0,0x9e,0x63, + 0xbf,0xf1,0xa5,0xb2,0x3e,0x59,0xfd,0xf8,0xea,0x33,0x1c,0xdf,0x86,0xe3,0x7e,0xc3, + 0xf1,0x1d,0x70,0xcf,0x71,0x00,0xcc,0x73,0x7c,0x97,0x58,0x03,0x70,0xf4,0x7e,0xfb, + 0x0d,0xc7,0xf7,0xc8,0xa9,0x07,0xfd,0x3e,0x74,0x3d,0x9f,0x5e,0xa3,0xfb,0x3e,0x35, + 0xe9,0xc6,0xae,0x1f,0x0e,0x83,0x86,0x83,0xea,0x1c,0x90,0x35,0x88,0xfd,0x01,0xf2, + 0xd5,0x6f,0x89,0xc3,0x7c,0x8b,0xe8,0x5e,0xbf,0x3b,0x8e,0xf2,0xcd,0x51,0x27,0xf9, + 0xea,0xf7,0xc6,0x47,0xe8,0x1c,0x35,0x73,0xfd,0x13,0x78,0x1f,0x37,0x73,0xfd,0x04, + 0xb8,0xff,0x8f,0x38,0x49,0x9d,0x4f,0xb8,0xb9,0x94,0x70,0xdf,0x27,0xa7,0xf0,0x77, + 0x92,0xff,0xc3,0x0e,0xce,0x45,0xfb,0xfd,0x33,0xe4,0xfa,0xfb,0x06,0xec,0x0b,0xf0, + 0xd3,0xfc,0xc7,0x6b,0x7d,0xbf,0xa4,0xbf,0x75,0x26,0x9d,0x43,0x6f,0x18,0x5d,0x95, + 0x7d,0x0d,0x76,0x86,0x3b,0x34,0x4c,0xed,0x3c,0xf7,0x41,0x73,0xc7,0xf4,0x5e,0xdd, + 0xa2,0x4f,0xce,0x50,0x23,0xad,0xdd,0x68,0xda,0x5c,0x19,0x91,0x75,0x1e,0xfb,0x11, + 0x73,0xb6,0x67,0x99,0x05,0xbe,0xb7,0xbe,0x32,0xbd,0xd5,0x0e,0x76,0x0e,0xfc,0xac, + 0x99,0xcd,0x37,0xc0,0xa7,0xcc,0x6c,0x1e,0xc5,0xff,0x79,0xe3,0xff,0x02,0xf3,0xc4, + 0xfb,0xfa,0x96,0xfb,0x71,0xc1,0xf8,0x9a,0x00,0x9f,0x32,0x33,0xd4,0xfb,0x1a,0x35, + 0xb3,0x46,0xe7,0xcb,0x0d,0xb8,0x4c,0xc0,0x47,0x75,0xdb,0xd0,0x6d,0xe3,0x3b,0x21, + 0xce,0x4c,0xb9,0x69,0x66,0xa0,0x9f,0x5d,0xad,0xa6,0xf7,0x7f,0xa0,0x07,0x2e,0x99, + 0xde,0xff,0x11,0x7c,0x37,0xff,0x15,0x97,0xc1,0xfc,0xf7,0xd9,0x4f,0x7c,0x57,0x5d, + 0x26,0x96,0x62,0x3f,0x83,0xe7,0x39,0xdf,0x71,0xf7,0x7d,0x79,0x85,0x6f,0xd0,0x2a, + 0xe4,0x0f,0xcb,0x99,0x5c,0xe1,0x3c,0xed,0x77,0x8f,0x3e,0xff,0x96,0x0a,0x2e,0x97, + 0xf5,0x1f,0x73,0x58,0x0a,0xd2,0xe4,0x0f,0x00,0x00 }; // Generated from: @@ -102,13 +115,14 @@ constexpr uint8_t kBlitResolveStencilNoExport_comp_00000000[] = { // vec2 invSrcExtent; // int srcLayer; // int srcWidth; -// -// ivec4 blitArea; -// int destPitch; +// int srcHeight; // // bool flipX; // bool flipY; // bool rotateXY; +// +// ivec4 blitArea; +// int destPitch; // } params; // // layout(set = 0, binding = 0)buffer dst @@ -144,14 +158,23 @@ constexpr uint8_t kBlitResolveStencilNoExport_comp_00000000[] = { // if(params . rotateXY) // srcImageCoords . xy = srcImageCoords . yx; // -// int xDir = params . flipX ? - 1 : 1; +// int xDir = 0, yDir = 0; +// if(params . rotateXY) +// { +// yDir = params . flipY ? - 1 : 1; +// } +// else +// { +// xDir = params . flipX ? - 1 : 1; +// } // // uint outStencils = 0; // // for(int i = 0;i < 4;++ i) // { // -// if(srcImageCoords . x >= 0 && srcImageCoords . x < params . srcWidth) +// if((srcImageCoords . x >= 0 && srcImageCoords . x < params . srcWidth)&& +// (srcImageCoords . y >= 0 && srcImageCoords . y < params . srcHeight)) // { // // uint stencilValue = texture(usampler2D(stencil, blitSampler), srcImageCoords * params . invSrcExtent). x; @@ -160,7 +183,14 @@ constexpr uint8_t kBlitResolveStencilNoExport_comp_00000000[] = { // // } // -// srcImageCoords . x += xDir; +// if(params . rotateXY) +// { +// srcImageCoords . y += yDir; +// } +// else +// { +// srcImageCoords . x += xDir; +// } // } // // destData[gl_GlobalInvocationID . y * params . destPitch + gl_GlobalInvocationID . x]= outStencils; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc index 0ce02280dff..cda247a97a4 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc @@ -10,108 +10,112 @@ #pragma once constexpr uint8_t kBlitResolveStencilNoExport_comp_00000001[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x6d,0x96,0xd9,0x6f,0x94,0x55, - 0x18,0xc6,0xbf,0x99,0x69,0xa7,0x65,0xb4,0x2d,0xd5,0x16,0xb0,0x05,0x4a,0xad,0xc1, - 0xa5,0x04,0x31,0x61,0x33,0x30,0x52,0x88,0x20,0xb6,0x44,0x2c,0xd8,0x09,0x06,0x95, - 0x6a,0xbc,0x80,0x8b,0x2e,0x49,0x89,0xb5,0x0d,0x6a,0x4b,0x2b,0x22,0x16,0x0d,0x02, - 0x2e,0x80,0x1a,0x8c,0xc4,0x34,0x9a,0x48,0x6d,0x82,0x60,0xa2,0xb2,0x68,0xbc,0x30, - 0xf1,0x06,0x41,0xbc,0xc2,0x7f,0xc2,0x3d,0x46,0xdf,0xe7,0xcc,0xef,0x98,0x37,0x13, - 0xbf,0xe4,0xe4,0xcc,0x79,0xde,0x7d,0x3b,0x67,0x32,0xe9,0x96,0x8a,0x24,0x49,0x25, - 0xb9,0xa4,0x32,0xf9,0x39,0x29,0x7e,0xb5,0x49,0xda,0x90,0x24,0xb9,0x21,0xc9,0x86, - 0xfd,0x81,0x4d,0x5b,0x37,0x2d,0x1e,0xd8,0xfd,0xf4,0xe2,0xa5,0xcb,0x96,0x88,0x5e, - 0x9d,0x64,0x02,0x9f,0x68,0x35,0xc6,0x53,0x6e,0x7b,0x99,0xad,0x9e,0x27,0x77,0xf5, - 0x0a,0xaf,0xb2,0x35,0xd3,0xf0,0xb2,0xa0,0x2b,0x31,0xcd,0xc5,0x15,0x74,0x19,0x5a, - 0x15,0x74,0x27,0xc9,0x5c,0x5b,0x1b,0x4d,0x7a,0x1e,0x76,0x5b,0xd8,0x23,0x96,0x02, - 0xab,0x74,0x58,0x1a,0x6c,0xa6,0xc3,0x32,0x60,0x73,0x1c,0x56,0x06,0xe6,0x6d,0x94, - 0x83,0x2d,0x70,0x58,0x16,0x6c,0x89,0xc3,0x2a,0xc0,0x96,0x3a,0xac,0x12,0x6c,0xa5, - 0xc3,0x66,0x80,0xad,0x0e,0x71,0x65,0xfe,0xf3,0x4f,0x31,0xee,0xb7,0xfd,0x56,0xe2, - 0x89,0xe7,0x66,0x97,0x83,0x89,0x12,0xfa,0x04,0xf4,0x28,0x7f,0x1a,0xdf,0xca,0xb0, - 0x37,0x55,0x92,0x23,0xd9,0x9b,0x22,0x76,0xf1,0x4f,0x97,0xe8,0x9b,0x46,0x5f,0x3c, - 0x5f,0x24,0xe7,0xb7,0xd8,0xba,0xd9,0xac,0xa4,0x03,0x3d,0x13,0xe4,0xf5,0xbb,0xde, - 0x78,0xb2,0xe4,0x46,0x3e,0xce,0xb6,0x73,0x05,0x3e,0x44,0x7a,0x0e,0x7a,0x02,0x5d, - 0xfa,0x72,0xf8,0xb0,0xc0,0xce,0x37,0x22,0x2b,0x7c,0x15,0xe7,0x2a,0xb0,0x56,0xe4, - 0xab,0x91,0x17,0x7f,0x0d,0xb4,0x9c,0xa3,0xdf,0x44,0xcc,0xf1,0x5c,0x0f,0xcf,0x2c, - 0xb3,0xd2,0x80,0x7d,0xd9,0x6e,0xb4,0xbd,0x01,0xdf,0x74,0x9e,0xeb,0xf2,0x35,0xdf, - 0x2c,0xab,0x16,0x8d,0x6e,0x65,0x59,0x91,0x2f,0xe7,0x96,0x7c,0x99,0x4f,0x3d,0xe7, - 0xe1,0xbb,0xce,0x4d,0x60,0xad,0x2e,0x37,0xe5,0xf0,0x37,0x43,0x93,0xbe,0x3a,0xf3, - 0x62,0x21,0x7e,0xdc,0x6e,0xfb,0x42,0xfc,0x8a,0x72,0xcb,0x89,0x41,0x72,0x2b,0x90, - 0x6b,0x84,0xde,0x40,0xff,0xd8,0xb7,0x66,0x91,0x69,0x17,0x9e,0x07,0x5b,0xed,0x74, - 0xb4,0x91,0xb7,0x78,0x5e,0x4f,0x9f,0x4a,0xe7,0x06,0x74,0xe6,0x1c,0xbd,0x93,0x9e, - 0x8d,0xe7,0xed,0x25,0xb1,0xec,0xb4,0xf5,0x8f,0x7d,0xf1,0x3c,0xe0,0xf2,0x2e,0x9f, - 0x06,0x5d,0x9d,0x9e,0x43,0x36,0x1b,0xfa,0x67,0x46,0xb2,0x0f,0x5b,0x29,0x78,0x4a, - 0x77,0xc9,0xbc,0xc4,0xef,0x7d,0xe4,0x53,0xe7,0xfd,0x60,0x0d,0x96,0x9d,0x03,0xf0, - 0xbd,0x02,0x76,0x00,0x3e,0x9d,0x27,0xc0,0x1a,0xad,0xe6,0xaf,0xa2,0x23,0xfa,0x79, - 0xa8,0x24,0xb7,0x47,0xe9,0x3f,0xe5,0xfe,0x6d,0x7a,0x22,0x9e,0xdf,0xc1,0x4f,0xdf, - 0x4f,0x27,0x15,0x77,0xa8,0x73,0x26,0xcc,0x58,0x2e,0xf4,0x4b,0x71,0x96,0x4e,0xe3, - 0xd3,0xa7,0xd8,0x98,0xc2,0x27,0x9d,0xa7,0x4b,0xec,0x9e,0x21,0x1f,0xe2,0xff,0x0a, - 0x9a,0xef,0xe3,0x0b,0xe4,0x7f,0x91,0x71,0x69,0x1e,0x2e,0x82,0x5d,0xa0,0xa7,0x97, - 0x5b,0xad,0xd3,0xf8,0x96,0xe0,0xf3,0xef,0x86,0xa8,0xbf,0x7e,0xb3,0xd3,0x25,0xf0, - 0xbf,0xec,0xb7,0x66,0xe6,0x6b,0xe8,0xda,0xd7,0x1a,0x57,0x0d,0x77,0x60,0x15,0x33, - 0x95,0xc7,0x6e,0x2d,0xf8,0xb8,0xf1,0xe4,0xc2,0xac,0x17,0x31,0xcd,0xd5,0x1e,0x7c, - 0xaf,0x03,0x8f,0x7a,0x66,0xa1,0xa7,0xde,0xe9,0x99,0x0d,0x1e,0x65,0xe6,0x80,0x3d, - 0x6c,0x32,0x15,0xdc,0x23,0x75,0xe0,0xd2,0xd3,0xcc,0xfd,0xd3,0xc4,0x9c,0xe4,0x99, - 0xc9,0x16,0xf0,0xcd,0x26,0x25,0xb9,0xdb,0xc0,0x5a,0xc8,0x59,0x26,0xe4,0xb6,0x3c, - 0xcc,0xcd,0x1d,0xd0,0xa5,0xfb,0x98,0xc9,0x6b,0x8e,0xee,0x04,0x57,0x4e,0x5a,0xc9, - 0xc9,0x9f,0x46,0x13,0x7e,0x57,0xc8,0x77,0x31,0x2f,0xfa,0xfd,0x87,0xed,0x97,0x38, - 0xb7,0x3a,0x9b,0x77,0x3b,0x9b,0xb1,0x4f,0x47,0x88,0xe3,0x1e,0xec,0x89,0xa7,0x8f, - 0x7b,0x65,0x19,0xb8,0xe2,0x5a,0xc1,0x9d,0xdf,0xc4,0x1c,0xe7,0xe1,0xb9,0x17,0xfc, - 0x45,0x66,0x76,0x15,0x72,0xc2,0x47,0xc1,0xd6,0x80,0xe7,0x9d,0xae,0xb5,0xe8,0x6a, - 0x73,0xba,0xd6,0x81,0x8f,0x21,0x77,0x3f,0xb2,0xeb,0x90,0xdb,0x10,0xee,0xf0,0xa2, - 0xdc,0x7a,0x57,0xa3,0x8d,0xe0,0x1f,0x19,0x8f,0x72,0xf5,0x20,0x58,0x35,0xf9,0xea, - 0x70,0xf9,0x12,0xad,0xdd,0x56,0x07,0xf9,0x69,0x0f,0x77,0x44,0x79,0x98,0x97,0x87, - 0xb0,0xa9,0xef,0x05,0xe6,0x7f,0x33,0xf8,0x16,0xab,0xbe,0x7c,0xfa,0x0e,0x2c,0xf2, - 0x29,0xd7,0x51,0x97,0xf6,0x5f,0x2c,0x9b,0xe2,0xfb,0x01,0x9e,0x56,0x64,0xda,0x5d, - 0x0c,0x5b,0x88,0xa1,0xd3,0xc5,0xb0,0x15,0x3c,0xc6,0xf0,0x08,0x58,0x8c,0xa1,0xe0, - 0x62,0x10,0xad,0xcb,0x56,0x01,0xbb,0x5d,0x2e,0x86,0x6d,0xd8,0x4e,0xb9,0x18,0x1e, - 0x05,0x8f,0x31,0x7c,0x0f,0x16,0xf9,0x14,0x43,0xd4,0x55,0x70,0x31,0x5c,0x81,0xa7, - 0x03,0x99,0x2e,0x17,0xc3,0x63,0xc4,0xb0,0xdd,0xc5,0xf0,0x38,0x78,0x8c,0xe1,0x09, - 0xb0,0x18,0x43,0xb7,0x8b,0x41,0xb4,0x1d,0xb6,0xba,0xb1,0xbb,0x83,0x3e,0x95,0xdd, - 0xa7,0xb0,0x7d,0xc5,0xdd,0xa5,0xf2,0x31,0xf2,0x76,0x3b,0x1f,0x7f,0x82,0xaf,0x80, - 0x9c,0xf4,0x4c,0x5a,0x9c,0x9a,0xd5,0x5d,0xf4,0xc2,0x4e,0x7a,0x56,0x3a,0x7a,0xd0, - 0xd1,0xe3,0x74,0x5c,0x43,0x8f,0xf4,0x5e,0xb6,0xd5,0x0f,0x4d,0x31,0xfd,0x88,0xff, - 0xa2,0x5d,0x77,0x34,0xe9,0xbf,0x4a,0xff,0x8a,0xf6,0x09,0xb4,0x29,0x62,0xdf,0x0d, - 0x5d,0xef,0xc9,0xaf,0x16,0x6f,0x1f,0xf4,0x18,0xbf,0xe8,0xbd,0x61,0xd6,0x8a,0xfe, - 0xf4,0xba,0x1a,0x3e,0x83,0x4f,0xfa,0xbe,0x44,0xdf,0xb3,0xe0,0x83,0xe4,0x72,0xd8, - 0xe9,0x12,0x6d,0xc8,0xd6,0x30,0xba,0x86,0xa8,0x93,0xde,0xab,0xe7,0xa9,0xd3,0x00, - 0x75,0xca,0x86,0xbe,0x28,0xe2,0x7d,0xf4,0xc7,0x08,0xd8,0x59,0x6c,0x8d,0x62,0x6b, - 0x84,0x9c,0x45,0xbd,0xc3,0xc4,0x2e,0x9e,0xbd,0xf8,0xd4,0x0b,0xff,0x10,0x7e,0x8d, - 0x3b,0xbf,0xf6,0x86,0x59,0x4e,0x02,0x26,0xf9,0x31,0x7c,0xd0,0x3b,0xf6,0x32,0xef, - 0xa0,0xce,0x7a,0xf3,0x0e,0xf2,0xde,0x15,0xcc,0x07,0xbd,0x75,0xaf,0xc1,0x73,0xd0, - 0xdd,0x19,0xaf,0x13,0xcb,0x21,0x77,0x67,0x1c,0x06,0x8f,0xf7,0xcf,0x11,0x72,0x77, - 0xd8,0xe5,0xe0,0x0d,0xe4,0x8e,0xba,0x1c,0xbc,0x09,0x1e,0x73,0xf0,0x16,0x58,0xac, - 0xc1,0x31,0x74,0x25,0x0e,0x3b,0x0e,0x96,0x0a,0xf7,0x7f,0x36,0xbc,0xb3,0x27,0xe0, - 0x3d,0x8e,0x8e,0x6d,0x96,0x1f,0xbd,0xb7,0xef,0x12,0xc3,0x09,0xee,0xf7,0x41,0xf4, - 0xa8,0xa7,0xde,0x83,0xae,0xef,0x5b,0xb0,0xf7,0xc1,0x4f,0xf2,0x66,0xc9,0xc7,0x0f, - 0xe8,0xa1,0xce,0xf0,0xee,0x15,0xf9,0x4e,0xc1,0x2b,0xda,0x37,0x60,0x1f,0xd2,0xa7, - 0xa7,0xa8,0x57,0xcc,0xf7,0xb8,0xeb,0xe3,0xeb,0xf0,0x0c,0xc3,0x3f,0xe6,0x62,0x9f, - 0x64,0x56,0x46,0x89,0xf3,0x63,0xea,0x3f,0xe9,0xee,0x8c,0xcb,0xe0,0xd7,0xdc,0x3c, - 0xf6,0x63,0xa7,0x9f,0x77,0x24,0xcb,0x1c,0x5c,0xfd,0x9f,0x79,0xeb,0x73,0xf5,0xf8, - 0x8c,0x7a,0x9c,0x71,0xf5,0x38,0x0b,0xbe,0x87,0xbb,0xe4,0x1c,0x58,0x7c,0xbf,0x3f, - 0xe7,0xdd,0x3d,0x87,0x2d,0x61,0x5f,0x80,0xd7,0x06,0xdd,0xd9,0xf0,0xff,0xe3,0x3c, - 0xff,0x51,0xda,0xa0,0xdf,0x67,0x3d,0x79,0x9e,0xd8,0xfd,0xbb,0xa8,0xfd,0x6f,0xab, - 0xe4,0x4a,0x5b,0xff,0x02,0x8d,0xed,0x49,0xea,0xfc,0x0d,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x6d,0x96,0xfb,0x6b,0x96,0x65, + 0x18,0xc7,0x9f,0xf7,0xe0,0xfb,0xce,0xd7,0xb6,0xb9,0xda,0x3c,0x1f,0x5a,0x93,0x59, + 0x4d,0xd4,0xa0,0x9a,0x59,0x33,0x73,0x90,0x59,0xdb,0xd2,0x56,0x6d,0xf4,0x4b,0x1b, + 0xa4,0x2d,0xa8,0x70,0x5b,0x18,0xb5,0x91,0xa7,0x49,0x6d,0x60,0x56,0x0e,0xb3,0x13, + 0x46,0xe2,0x0f,0x5b,0x54,0x46,0x81,0xae,0x81,0x65,0x14,0x9e,0xfa,0x2d,0xe8,0x37, + 0xc1,0xcc,0xd1,0x5f,0xb0,0x8e,0x46,0x5d,0xdf,0xfb,0xfd,0xdc,0x72,0xf1,0xd2,0x03, + 0x37,0xf7,0x73,0x7f,0xaf,0xe3,0xf7,0xba,0xaf,0xfb,0x7e,0x9e,0x4c,0xba,0x2e,0x9f, + 0x24,0xa9,0xa4,0x90,0x94,0x25,0x99,0x54,0x12,0x9e,0xaa,0x24,0x9d,0xe8,0x75,0x56, + 0x92,0x0b,0xf3,0xc6,0x96,0xf6,0x96,0x95,0xfd,0x2f,0x3c,0xb5,0xf2,0xf6,0x3b,0x56, + 0x4b,0x5e,0x91,0x64,0x82,0x9e,0x64,0x95,0xa6,0x33,0xc3,0xe6,0xac,0x8d,0xe7,0xba, + 0x9f,0x79,0x5e,0x78,0xb9,0x8d,0xd9,0x86,0x67,0x83,0xaf,0xc4,0x3c,0x17,0x47,0xf0, + 0x65,0x68,0x79,0xf0,0x9d,0x24,0x8b,0x6c,0x3c,0x60,0xd6,0x8b,0x8b,0x61,0x93,0x3a, + 0xe6,0x88,0xa5,0xc0,0xca,0x1c,0x96,0x06,0x9b,0xed,0xb0,0x0c,0xd8,0x3c,0x87,0x65, + 0xc1,0x7c,0x8c,0x19,0x60,0x37,0x3a,0x2c,0x07,0xb6,0xcc,0x61,0x79,0xb0,0x9b,0x1d, + 0x56,0x06,0xb6,0xc2,0x61,0x33,0xc1,0x56,0x3b,0xac,0x00,0xb6,0x3e,0x70,0xcd,0x5c, + 0xcb,0x59,0xbc,0x0f,0xdb,0x7c,0x13,0x1c,0xe3,0xba,0xd6,0xd5,0xe5,0x24,0xf9,0x64, + 0xf1,0x37,0x51,0x52,0x17,0xf9,0x9b,0x80,0xaf,0xf4,0x27,0x4b,0xfc,0x4d,0xe2,0x2f, + 0xae,0xcf,0x53,0xe7,0xf9,0x36,0x6e,0xb0,0x2c,0xd2,0x41,0x9e,0x09,0xf6,0x7a,0xaf, + 0x31,0x9d,0x1c,0xf5,0x50,0x0e,0x73,0x6d,0x9d,0x27,0x87,0x28,0x2f,0x20,0x4f,0x90, + 0xcf,0x82,0x63,0x26,0xe0,0xd9,0xe4,0x3a,0x6c,0x85,0xdf,0xcd,0xba,0x1c,0xac,0x01, + 0xfb,0x0a,0xec,0xa5,0x5f,0x89,0xac,0xe0,0xe4,0xd7,0xc3,0x39,0xae,0x6b,0xd0,0x99, + 0x63,0x51,0x16,0x10,0x5f,0xb1,0x17,0xda,0xbc,0x80,0xdc,0xb4,0x5e,0xe4,0xea,0xb5, + 0xc4,0xa2,0xc6,0xbd,0x5b,0xc8,0xc8,0xb9,0x51,0x70,0x23,0xda,0x29,0x9f,0x25,0xec, + 0xe3,0x62,0xf2,0xd7,0x7a,0x29,0x58,0x83,0xab,0xcf,0x4c,0xf4,0x6b,0x79,0x97,0x8f, + 0x6a,0xcb,0xa4,0x9e,0x5c,0x96,0xdb,0x5c,0x4f,0x6e,0xd1,0xae,0xd1,0xf1,0x5e,0x83, + 0x5d,0xde,0xc9,0x9b,0x5c,0x1e,0xeb,0x90,0x17,0x9c,0x7c,0x53,0x89,0x7e,0x3b,0x7d, + 0x18,0xd7,0x5b,0x6d,0xfc,0x6b,0x4f,0x5c,0x6f,0x73,0x75,0xd7,0x7a,0x07,0xb5,0x91, + 0xff,0x9d,0xf8,0xcf,0x39,0xf9,0x7e,0xce,0xc4,0x7c,0x93,0x1c,0x22,0x36,0x57,0xc0, + 0xb5,0xf3,0x9d,0x72,0x1c,0xde,0xe6,0xfd,0x10,0xb5,0xd2,0xfa,0xb0,0xeb,0x8d,0xf7, + 0xf0,0xe1,0xf7,0xf2,0x88,0x72,0x0c,0xf5,0xcd,0x84,0xfe,0x2e,0x84,0xbd,0x2a,0xf6, + 0xf1,0x49,0xfc,0x7e,0x45,0xdd,0x26,0xf0,0xab,0xf5,0x64,0x49,0x2d,0x4f,0x61,0x2b, + 0xfd,0x33,0xc8,0x7c,0x0f,0x9d,0xa3,0x36,0x2b,0x4c,0x5b,0xbd,0x78,0x1e,0xec,0x1c, + 0xfd,0x74,0xa7,0x31,0x4d,0x93,0x5b,0x42,0xff,0xfe,0x61,0x88,0xf8,0xff,0x6e,0xab, + 0x0b,0xe0,0x7f,0xdb,0xbb,0xfa,0xf5,0x07,0xe4,0x9a,0xef,0x33,0xad,0x4a,0xee,0x9c, + 0x72,0xfa,0xb9,0x89,0xb8,0x55,0xe0,0x43,0xa6,0x53,0x08,0xe7,0xac,0x88,0xa9,0xa7, + 0x07,0xc9,0xbd,0x1a,0x3c,0xfa,0x99,0x83,0x9f,0x1a,0xe7,0x67,0x2e,0x78,0xb4,0x99, + 0x07,0xb6,0xd9,0x6c,0xf2,0x9c,0xe1,0x6a,0x70,0xf9,0xa9,0xe5,0xec,0x2f,0xa5,0x3f, + 0x9b,0x38,0x0f,0x75,0xe0,0x0f,0x9b,0x55,0x9e,0x7b,0xad,0x8e,0x91,0x86,0xf7,0x17, + 0x66,0xbf,0x9c,0xfb,0x6d,0x19,0xbe,0xdf,0x35,0x7b,0xf5,0xef,0x2d,0xe0,0xaa,0x49, + 0x03,0x35,0xf9,0xcb,0x64,0xc2,0x6f,0x0d,0xf5,0x2e,0xd6,0x45,0xef,0x7f,0xda,0x7c, + 0x81,0x75,0x83,0x8b,0xb9,0xca,0xc5,0x8c,0x7d,0xb4,0x0b,0x1e,0xb7,0x11,0x6f,0x15, + 0x3c,0x74,0x2e,0xee,0x82,0x47,0x23,0x3c,0xa4,0xb7,0x16,0x7c,0x0f,0x76,0xf7,0x60, + 0xbb,0x16,0x3b,0x9d,0x97,0x7b,0xb1,0x6b,0x72,0x75,0x5c,0x0f,0xfe,0xb1,0xe9,0xd4, + 0x07,0xdd,0x22,0x56,0x01,0xa7,0x66,0xc7,0x49,0xb2,0x0d,0x36,0x9a,0xe1,0xa0,0xf7, + 0x2d,0x66,0xa7,0xfa,0xdf,0x4f,0x4c,0x3d,0xaf,0xb0,0x27,0x1b,0xc1,0x1f,0xb1,0x95, + 0x72,0xfa,0x11,0x2c,0xea,0xa9,0x1e,0xd1,0x97,0xe6,0x69,0xea,0xf1,0x33,0x3a,0x0d, + 0xd8,0x6c,0x70,0x1c,0x1e,0x84,0xc3,0x26,0xc7,0xe1,0x21,0xf0,0xc8,0xa1,0x05,0x2c, + 0x72,0x68,0x73,0x1c,0x24,0x6b,0xb5,0xd1,0x46,0xdc,0x56,0xc7,0x61,0x33,0xb1,0x53, + 0x8e,0xc3,0x16,0xf0,0xc8,0xe1,0x27,0xb0,0xa8,0x27,0x0e,0xd1,0x57,0x9b,0xe3,0x70, + 0x19,0x9d,0x66,0x6c,0x5a,0x1d,0x87,0x47,0xe1,0xd0,0xee,0x38,0x3c,0x06,0x1e,0x39, + 0x3c,0x0e,0x16,0x39,0x74,0x3a,0x0e,0x92,0x75,0xd8,0xe8,0x24,0x6e,0x87,0xeb,0xa5, + 0x27,0x88,0x7d,0xd9,0xdd,0x45,0xca,0x31,0xea,0x76,0xba,0x1c,0x7f,0x45,0xaf,0x0d, + 0xbb,0x0e,0x62,0x75,0x97,0xc4,0xea,0xb2,0xd1,0x83,0xbd,0xde,0xc7,0xac,0x16,0xaa, + 0xcd,0xd3,0xd4,0x7a,0x2b,0x77,0xa9,0xe2,0x74,0xa3,0xd7,0xe3,0xf4,0x9e,0xa5,0xaf, + 0xfe,0x4f,0xaf,0x9b,0x7c,0xa4,0x77,0x15,0x9f,0x5d,0xf4,0x76,0x8f,0x93,0x4d,0x83, + 0x75,0xe1,0xaf,0x07,0x3f,0xdb,0xf1,0xb3,0xdd,0xf1,0x9a,0x82,0x9b,0x7c,0xa7,0xad, + 0x08,0xfd,0xc8,0x54,0xe7,0x2b,0xd4,0x54,0xb2,0x94,0x93,0x29,0xc6,0x2f,0xc4,0x90, + 0xec,0x44,0x52,0x94,0x7d,0xce,0x7e,0xbc,0x88,0x5c,0xdf,0x88,0xdf,0xac,0x2e,0x7d, + 0xc8,0x63,0x9d,0x24,0xef,0xb5,0xd1,0x47,0x3e,0xbd,0xae,0xaf,0x5e,0x22,0x27,0x3d, + 0x9f,0xe1,0xef,0x65,0xf0,0x46,0x6a,0x3e,0xe8,0x7c,0x49,0x36,0x10,0xee,0xb6,0xa2, + 0xaf,0x01,0x7a,0x67,0x67,0xb8,0x17,0x8a,0xbd,0xb3,0x83,0xde,0x91,0xff,0xdd,0xe0, + 0x31,0xd7,0x3d,0xf8,0xde,0x4d,0x8d,0xa2,0x9f,0x41,0xb8,0x4a,0x67,0x2f,0x39,0xf4, + 0xa2,0x3f,0x40,0x1e,0xfb,0x5c,0x1e,0x7b,0xc3,0x3d,0x9d,0x04,0x4c,0xf6,0x43,0x8e, + 0xd3,0xab,0x70,0x4a,0x39,0x4e,0xaf,0x81,0x47,0x4e,0x23,0xce,0x97,0x64,0xc3,0x36, + 0x46,0xf0,0x35,0xec,0x38,0xbd,0x0e,0xa7,0xfd,0x8e,0xd3,0x01,0xf0,0xc8,0xe9,0x0d, + 0x7c,0x1f,0x80,0x53,0xf4,0x33,0xe2,0x38,0xbd,0x49,0x0e,0x43,0xe8,0x0f,0xa3,0x1b, + 0xf3,0xdf,0xe7,0x74,0xdf,0xa2,0x06,0x83,0xd8,0x8d,0x90,0xf3,0xa8,0xcb,0x59,0x3a, + 0x07,0x6d,0x8c,0x62,0x7f,0x90,0xfc,0xf4,0x3d,0x7f,0x87,0x6f,0xf9,0x93,0xe6,0x4f, + 0xdf,0xf1,0xf7,0xc1,0xa6,0xb8,0x3f,0x1b,0xa9,0x95,0x7a,0xee,0x03,0xe4,0x7a,0xce, + 0x80,0x7d,0x08,0x7e,0x84,0x6f,0xa1,0x38,0x7f,0x44,0x8f,0xe9,0x5e,0xf8,0x0e,0xbd, + 0xa3,0xe8,0x4a,0xf6,0x3d,0xd8,0x31,0xfa,0xf8,0x28,0xfc,0x62,0x7e,0xa3,0xae,0xcf, + 0xd5,0xdb,0x57,0xd8,0xbb,0x63,0xf0,0x10,0xbf,0xf1,0x92,0xb3,0x3d,0x66,0xe3,0x38, + 0xf6,0x63,0x6e,0x7f,0x3f,0x71,0xfb,0xbb,0x0b,0xec,0x53,0xf0,0xab,0xee,0x3e,0xbc, + 0x08,0x3e,0xe5,0xee,0xc3,0x71,0xfc,0x1d,0x77,0xb6,0x5f,0xd2,0x93,0xd3,0xce,0xf6, + 0x12,0xf8,0x94,0xbb,0xa7,0xa2,0xed,0xb8,0x3b,0xcf,0x3a,0xc3,0x17,0xc9,0xf5,0x12, + 0xf9,0x4a,0xb7,0x1f,0xdd,0x7e,0x17,0xe7,0x04,0x35,0xdc,0x56,0x72,0x3f,0xf4,0xb9, + 0x7e,0xfb,0x9a,0x7e,0x3b,0xe5,0xfa,0xed,0x1b,0xf0,0x41,0xee,0xe3,0xd3,0x60,0xf1, + 0x3f,0xe5,0x5b,0xfe,0x2f,0x4e,0x13,0xab,0x10,0xf6,0xa3,0x88,0x57,0x05,0xdf,0xb9, + 0xf0,0x9f,0x75,0x96,0x7f,0xb1,0x46,0xe4,0xeb,0xac,0xe6,0x67,0xd9,0x2f,0xff,0xfd, + 0xd7,0xfc,0x8f,0x55,0x6c,0x8d,0x8d,0xff,0x00,0xf2,0xa0,0xf8,0x24,0x54,0x0e,0x00, + 0x00 }; // Generated from: // // #version 450 core // +// #extension GL_EXT_samplerless_texture_functions : require +// // layout(local_size_x = 8, local_size_y = 8, local_size_z = 1)in; // // layout(push_constant)uniform PushConstants { // -// vec2 offset; +// ivec2 offset; // vec2 stretch; // vec2 invSrcExtent; // int srcLayer; // int srcWidth; -// -// ivec4 blitArea; -// int destPitch; +// int srcHeight; // // bool flipX; // bool flipY; // bool rotateXY; +// +// ivec4 blitArea; +// int destPitch; // } params; // // layout(set = 0, binding = 0)buffer dst @@ -120,9 +124,7 @@ constexpr uint8_t kBlitResolveStencilNoExport_comp_00000001[] = { // uint destData[]; // }; // -// layout(set = 0, binding = 1)uniform utexture2DArray stencil; -// -// layout(set = 0, binding = 2)uniform sampler blitSampler; +// layout(set = 0, binding = 1)uniform utexture2DMS stencil; // // void main() // { @@ -133,10 +135,7 @@ constexpr uint8_t kBlitResolveStencilNoExport_comp_00000001[] = { // } // // destSubImageCoords += params . blitArea . xy; -// vec2 srcImageCoords = vec2(destSubImageCoords); -// -// srcImageCoords *= params . stretch; -// srcImageCoords += vec2(0.5); +// ivec2 srcImageCoords = ivec2(destSubImageCoords); // // srcImageCoords -= params . offset; // @@ -147,23 +146,39 @@ constexpr uint8_t kBlitResolveStencilNoExport_comp_00000001[] = { // if(params . rotateXY) // srcImageCoords . xy = srcImageCoords . yx; // -// int xDir = params . flipX ? - 1 : 1; +// int xDir = 0, yDir = 0; +// if(params . rotateXY) +// { +// yDir = params . flipY ? - 1 : 1; +// } +// else +// { +// xDir = params . flipX ? - 1 : 1; +// } // // uint outStencils = 0; // // for(int i = 0;i < 4;++ i) // { // -// if(srcImageCoords . x >= 0 && srcImageCoords . x < params . srcWidth) +// if((srcImageCoords . x >= 0 && srcImageCoords . x < params . srcWidth)&& +// (srcImageCoords . y >= 0 && srcImageCoords . y < params . srcHeight)) // { // -// uint stencilValue = texture(usampler2DArray(stencil, blitSampler), vec3(srcImageCoords * params . invSrcExtent, params . srcLayer)). x; +// uint stencilValue = texelFetch(stencil, srcImageCoords, 0). x; // // outStencils |=(stencilValue & 0xFF)<<(i * 8); // // } // -// srcImageCoords . x += xDir; +// if(params . rotateXY) +// { +// srcImageCoords . y += yDir; +// } +// else +// { +// srcImageCoords . x += xDir; +// } // } // // destData[gl_GlobalInvocationID . y * params . destPitch + gl_GlobalInvocationID . x]= outStencils; diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc deleted file mode 100644 index ef33fb50443..00000000000 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc +++ /dev/null @@ -1,156 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_vk_internal_shaders.py. -// -// Copyright 2018 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. -// -// shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc: -// Pre-generated shader for the ANGLE Vulkan back-end. - -#pragma once -constexpr uint8_t kBlitResolveStencilNoExport_comp_00000002[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0xdb,0x6f,0x54,0x55, - 0x14,0xc6,0xf7,0xcc,0xb4,0x33,0x65,0xa4,0x2d,0xc5,0x16,0x90,0x7b,0xad,0x29,0xe8, - 0x18,0xc0,0x04,0x99,0x8a,0x14,0x95,0x26,0x22,0xd8,0x56,0xb0,0x28,0x8d,0x2f,0xb5, - 0x09,0xb4,0x35,0x08,0xb6,0x11,0xd0,0x36,0xe5,0xa6,0x42,0x20,0x3e,0x98,0x40,0x6d, - 0x02,0x42,0x42,0xe4,0x16,0x63,0xa2,0x21,0x26,0x88,0xd6,0x27,0xd4,0xf8,0x17,0x79, - 0x41,0x62,0x74,0x7d,0xfb,0xfc,0xb6,0xac,0xcc,0x49,0x76,0xf6,0x59,0xdf,0xba,0x7e, - 0x6b,0xaf,0x7d,0x4e,0x21,0xdf,0x51,0x0a,0x21,0x17,0xca,0xa1,0x21,0xfc,0x1c,0xb2, - 0xa7,0x25,0xe4,0x0d,0x09,0xe1,0x91,0x50,0x8c,0xfb,0xf6,0xde,0x81,0xde,0x75,0xef, - 0x1f,0xde,0xb7,0x6e,0xe3,0xb3,0x1b,0xa4,0x6f,0x0a,0x85,0x68,0x27,0x5d,0xb3,0xd9, - 0xd4,0xdb,0x5e,0x67,0xeb,0xe0,0xf0,0x3b,0x87,0x84,0x37,0xda,0x5a,0x60,0x78,0x5d, - 0x8c,0x15,0x2c,0x72,0xb6,0x62,0x2c,0x43,0x1b,0x63,0xec,0x10,0x96,0xdb,0x7a,0xc5, - 0xbc,0x57,0x90,0xb7,0x83,0x3d,0x61,0x39,0xb0,0x06,0x87,0xe5,0xc1,0x16,0x38,0xac, - 0x00,0xb6,0xc4,0x61,0x75,0x60,0x3e,0x47,0x3d,0xd8,0x6a,0x87,0x15,0xc1,0x36,0x38, - 0xac,0x04,0xb6,0xd1,0x61,0x0d,0x60,0x5d,0x0e,0x9b,0x07,0xb6,0x25,0xf2,0x2a,0xfc, - 0x5f,0x9f,0x38,0x1e,0xb7,0xfd,0x71,0xf8,0x24,0xb9,0xdd,0xf5,0xe0,0x02,0xb9,0xeb, - 0x88,0x37,0x53,0xd3,0x03,0xc5,0x9b,0x81,0x9b,0xec,0x67,0x6b,0xe2,0xcd,0x12,0x2f, - 0xc9,0x37,0xe8,0xe9,0x63,0xb6,0x1e,0xb5,0x2a,0xf2,0x51,0x5f,0x88,0xfe,0x7a,0x6f, - 0x33,0x9b,0x22,0xdc,0x55,0xc3,0x62,0x93,0x4b,0xd4,0x90,0xf4,0x65,0xf4,0x01,0xbd, - 0xe2,0x95,0xa9,0x61,0xb5,0xc9,0xf3,0xf1,0x15,0xfe,0x3c,0x72,0x23,0x58,0x05,0xff, - 0x26,0xfc,0x65,0xdf,0x8c,0xae,0xec,0xf4,0x0b,0xe1,0x9c,0xe4,0x36,0x6c,0x16,0x59, - 0x96,0xa5,0xe4,0x57,0xee,0x65,0xb6,0x2f,0xa5,0x36,0xc9,0xcb,0x5d,0xbf,0x56,0x5a, - 0xe6,0x74,0x4e,0xcb,0x58,0x45,0x56,0xb2,0x2b,0xbb,0xa5,0x5a,0x56,0x72,0x5e,0x2b, - 0xa8,0x5d,0xf2,0x2a,0xb0,0x8a,0xeb,0x4d,0x3d,0xf6,0xed,0xe8,0x14,0xaf,0xd5,0xaa, - 0xe8,0xa4,0x8e,0x35,0xb6,0x77,0x52,0x57,0xf2,0xab,0x3a,0xce,0x5d,0xf8,0x95,0x9c, - 0xbe,0x1b,0x59,0xfa,0xad,0xe8,0xcb,0x4e,0xbf,0x83,0xf9,0x4a,0xf2,0x40,0x4d,0x5d, - 0x43,0xb6,0xfe,0xb5,0x27,0xc9,0x6f,0xbb,0x9e,0x4b,0x3e,0x40,0x5f,0x14,0xff,0x30, - 0xbe,0xc5,0x38,0x0b,0xf3,0xc2,0x34,0xb9,0x72,0xe1,0xe1,0x93,0x73,0xb2,0x7c,0x8e, - 0xf1,0x3e,0x4d,0x6f,0x24,0x1f,0x77,0x73,0x70,0x8a,0x18,0xfe,0xdc,0x4e,0xab,0xa6, - 0xd8,0xcf,0x42,0x9c,0xe5,0x72,0x3c,0x97,0x6c,0x66,0x2f,0x10,0xf7,0x73,0xfa,0x34, - 0x43,0x5c,0xc9,0xb3,0x35,0xbd,0xbb,0x48,0xad,0xb2,0xff,0x12,0x9d,0x9f,0x97,0xeb, - 0xf4,0xe6,0x69,0xb3,0xd2,0xdc,0xdd,0x00,0xbb,0xce,0xec,0x6c,0xb2,0x13,0xcb,0x53, - 0x5b,0x60,0x56,0xff,0x32,0x44,0xe7,0xf8,0xa7,0x49,0x37,0xc1,0x1f,0xd8,0xbb,0x66, - 0xf3,0x16,0x7a,0xed,0x2f,0x99,0x55,0x33,0xdf,0x92,0x46,0x66,0xb7,0x9b,0xbc,0x2d, - 0xe0,0x9f,0x98,0x4d,0x39,0xde,0xa9,0x0c,0x5b,0x18,0xfb,0x94,0xd5,0xde,0x0a,0x9e, - 0xe2,0x2c,0x22,0x4e,0x9b,0x8b,0xb3,0x18,0x3c,0xf9,0x2c,0x01,0xdb,0x65,0x3e,0x25, - 0xee,0x6b,0x2b,0xb8,0xe2,0xb4,0x73,0xcf,0x57,0x31,0x8f,0xdd,0xcc,0x7e,0x07,0xf8, - 0x6b,0xe6,0x25,0xbf,0x27,0xc0,0x3a,0xe8,0x99,0x78,0x7f,0x67,0xfe,0x9a,0xcf,0xb5, - 0xe8,0x15,0xfb,0x92,0xf9,0x6b,0x5e,0x9f,0x04,0x57,0x4f,0x2a,0xf4,0xe4,0x6f,0xd3, - 0x09,0x7f,0x2a,0xf6,0x3b,0xeb,0x8b,0xde,0xef,0xdb,0x7e,0x13,0xb9,0xe2,0x72,0xae, - 0x77,0x39,0xd3,0x1c,0x9d,0x84,0xc7,0x33,0xe4,0x5b,0x0f,0x0f,0xdd,0x83,0xe7,0xe0, - 0x51,0x85,0x87,0xec,0x36,0x83,0x7f,0x84,0xdf,0x16,0x7c,0x37,0xe3,0xa7,0xfb,0xf1, - 0x02,0x7e,0xdd,0xae,0x8f,0x2f,0x82,0x7f,0x6d,0x36,0x9d,0xd1,0x36,0xc3,0x9a,0xe0, - 0xd4,0xe3,0x38,0x49,0xb7,0xcd,0x56,0x0f,0x1c,0xf4,0xbe,0xdb,0xfc,0xd4,0xff,0x97, - 0xc9,0x19,0xe2,0x8c,0x67,0x67,0xb2,0x1d,0xfc,0x75,0x93,0x54,0xd3,0x37,0x60,0xc9, - 0x4e,0xfd,0x48,0xb1,0xb4,0xff,0x4e,0x3f,0xbe,0xc7,0xa6,0x82,0xcf,0x36,0xc7,0x61, - 0x27,0x1c,0x76,0x38,0x0e,0xaf,0x82,0x27,0x0e,0xbd,0x60,0x89,0x43,0xbf,0xe3,0x20, - 0x5d,0x9f,0xad,0x7e,0xf2,0xf6,0x39,0x0e,0xbb,0xc8,0x9d,0x73,0x1c,0x76,0x83,0x27, - 0x0e,0xb7,0xc1,0x92,0x9d,0x38,0xa4,0x58,0xfd,0x8e,0xc3,0x5d,0x6c,0x7a,0xf0,0xe9, - 0x73,0x1c,0xf6,0xc0,0x61,0xc0,0x71,0x78,0x03,0x3c,0x71,0x78,0x13,0x2c,0x71,0x18, - 0x74,0x1c,0xa4,0xdb,0x6b,0x6b,0x90,0xbc,0x7b,0xdd,0x2c,0xbd,0x45,0xee,0xbb,0xee, - 0x5b,0xa4,0x1a,0x93,0xed,0xa0,0xab,0xf1,0x27,0xec,0xfa,0xf1,0x53,0x9c,0xaf,0x8c, - 0xa7,0x78,0x0f,0x33,0x0b,0x43,0x7c,0x17,0x15,0x63,0x3f,0x31,0xf6,0xbb,0x18,0x73, - 0xc4,0x51,0xdc,0x3b,0xb6,0xc6,0xd0,0x89,0xd3,0x8f,0xd4,0x2f,0xdd,0x3d,0xa7,0x53, - 0xfc,0x1f,0x98,0x5f,0xe9,0xce,0xa3,0xbb,0x0d,0xf7,0x77,0xd1,0xeb,0xfb,0xfb,0x87, - 0xf1,0x1d,0x45,0x9f,0xf8,0x4b,0x3f,0x62,0x6b,0x94,0x7a,0x46,0xdc,0x19,0x1e,0xa2, - 0x26,0x3d,0xdf,0x12,0xef,0x3d,0xf0,0x2a,0xbd,0x9c,0x70,0xb1,0xa4,0x1b,0xb7,0x35, - 0x41,0xac,0x71,0xce,0x49,0xdf,0xfb,0x23,0x9c,0xd3,0x01,0xce,0x49,0xf1,0x8f,0x82, - 0xa7,0x5a,0x3f,0x20,0xf6,0x51,0x7a,0x94,0xe2,0x4c,0xc0,0x55,0x36,0x1f,0x52,0xc3, - 0x08,0xf6,0xe3,0xd4,0x31,0xe5,0xea,0x90,0xcd,0xa4,0xad,0x29,0xfc,0x27,0xc9,0xa9, - 0x7f,0xc7,0x09,0xfe,0x1b,0x43,0x16,0xef,0x54,0xbc,0xe3,0x19,0x36,0xc7,0x5d,0xad, - 0xc2,0x5f,0x3d,0xff,0x18,0xbd,0x9e,0xdf,0xc0,0xce,0x80,0x9f,0xe6,0xbb,0x2b,0x1e, - 0x67,0xe9,0xb1,0xee,0xd1,0x2f,0xd8,0x9d,0xc3,0x56,0xba,0x5f,0xc1,0x3e,0xe5,0x1c, - 0xcf,0xc1,0x2f,0xd5,0x37,0xe5,0xce,0xf9,0x1e,0x36,0x13,0xd8,0x4f,0xf2,0xfd,0x52, - 0x9e,0xcf,0xe8,0xcf,0xb0,0xbb,0x43,0x77,0xc0,0xe7,0xdc,0x7c,0x8e,0x11,0x77,0xcc, - 0xf9,0x9e,0xa7,0xc6,0xda,0xf9,0x1b,0x75,0x67,0x74,0x89,0x33,0xba,0xe8,0xce,0xe8, - 0x0b,0xf0,0x69,0xee,0xd6,0x65,0xb0,0xf4,0xcf,0xb9,0xc2,0xbf,0xe2,0x32,0xb9,0x84, - 0x5d,0x05,0x6f,0x89,0xb1,0x8b,0xf1,0x9f,0x79,0x8d,0xff,0x6a,0x15,0xfd,0x56,0x3b, - 0xb3,0x6b,0x70,0xf5,0xdf,0x72,0xed,0xff,0xd8,0x6d,0xeb,0xb2,0xf5,0x1f,0x9d,0xad, - 0x56,0x74,0xf8,0x0b,0x00,0x00 -}; - -// Generated from: -// -// #version 450 core -// -// #extension GL_EXT_samplerless_texture_functions : require -// -// layout(local_size_x = 8, local_size_y = 8, local_size_z = 1)in; -// -// layout(push_constant)uniform PushConstants { -// -// ivec2 offset; -// vec2 stretch; -// vec2 invSrcExtent; -// int srcLayer; -// int srcWidth; -// -// ivec4 blitArea; -// int destPitch; -// -// bool flipX; -// bool flipY; -// bool rotateXY; -// } params; -// -// layout(set = 0, binding = 0)buffer dst -// { -// -// uint destData[]; -// }; -// -// layout(set = 0, binding = 1)uniform utexture2DMS stencil; -// -// void main() -// { -// ivec2 destSubImageCoords = ivec2(gl_GlobalInvocationID . x * 4, gl_GlobalInvocationID . y); -// if(any(lessThanEqual(params . blitArea . zw, destSubImageCoords))) -// { -// return; -// } -// -// destSubImageCoords += params . blitArea . xy; -// ivec2 srcImageCoords = ivec2(destSubImageCoords); -// -// srcImageCoords -= params . offset; -// -// if(params . flipX) -// srcImageCoords . x = - srcImageCoords . x; -// if(params . flipY) -// srcImageCoords . y = - srcImageCoords . y; -// if(params . rotateXY) -// srcImageCoords . xy = srcImageCoords . yx; -// -// int xDir = params . flipX ? - 1 : 1; -// -// uint outStencils = 0; -// -// for(int i = 0;i < 4;++ i) -// { -// -// if(srcImageCoords . x >= 0 && srcImageCoords . x < params . srcWidth) -// { -// -// uint stencilValue = texelFetch(stencil, srcImageCoords, 0). x; -// -// outStencils |=(stencilValue & 0xFF)<<(i * 8); -// -// } -// -// srcImageCoords . x += xDir; -// } -// -// destData[gl_GlobalInvocationID . y * params . destPitch + gl_GlobalInvocationID . x]= outStencils; -// } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc b/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc deleted file mode 100644 index e347861145a..00000000000 --- a/src/libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc +++ /dev/null @@ -1,158 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_vk_internal_shaders.py. -// -// Copyright 2018 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. -// -// shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc: -// Pre-generated shader for the ANGLE Vulkan back-end. - -#pragma once -constexpr uint8_t kBlitResolveStencilNoExport_comp_00000003[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x5d,0x95,0xeb,0x6f,0xd4,0x45, - 0x14,0x86,0x67,0x2f,0xdd,0x2d,0xab,0x6d,0x29,0xb4,0xdc,0x6f,0xb5,0xa6,0x8a,0x4b, - 0x00,0x13,0x74,0x2b,0x52,0x54,0x9a,0x88,0x68,0x5b,0xc1,0xaa,0x34,0x7c,0x29,0x4d, - 0xa0,0x2d,0x41,0xb1,0x8d,0x88,0xb6,0xa9,0x28,0x48,0x40,0x0d,0x46,0xe2,0x07,0x12, - 0xa8,0x4d,0x10,0x48,0x0c,0x14,0x34,0xc6,0x98,0xf8,0x05,0x51,0xd4,0x10,0xfc,0x7f, - 0xb8,0x69,0x8c,0x9e,0x77,0xf6,0x19,0x72,0xb2,0x9b,0x9c,0xcc,0xce,0x7b,0xae,0xef, - 0x99,0x33,0xbf,0xc9,0x65,0xdb,0x8b,0x21,0x64,0x42,0x29,0xd4,0x87,0xbf,0x42,0xf5, - 0xd7,0x1c,0xb2,0x86,0x84,0xf0,0x50,0x28,0xc4,0x75,0x6b,0x4f,0x7f,0xcf,0xda,0x77, - 0x0f,0xee,0x59,0xbb,0xe1,0xa9,0xf5,0xd2,0x37,0x86,0x5c,0xb4,0x93,0xae,0xc9,0x6c, - 0xea,0x6c,0xcd,0x9b,0xbc,0x3d,0xb4,0xef,0x80,0xf0,0x06,0x93,0xb9,0x86,0xe7,0x63, - 0xac,0x60,0x91,0xab,0x12,0x63,0x19,0xda,0x10,0x63,0x87,0xb0,0xcc,0xe4,0x25,0xf3, - 0x5e,0x4e,0xde,0x76,0xd6,0x84,0x65,0xc0,0xea,0x1d,0x96,0x05,0x9b,0xeb,0xb0,0x1c, - 0xd8,0x22,0x87,0xe5,0xc1,0x7c,0x8e,0x3a,0xb0,0x55,0x0e,0x2b,0x80,0xad,0x77,0x58, - 0x11,0x6c,0x83,0xc3,0xea,0xc1,0x3a,0x1d,0x36,0x07,0x6c,0x53,0xe4,0x95,0x7b,0x50, - 0x9f,0x38,0x1e,0xb6,0xf5,0x11,0xf8,0xa4,0x7d,0x9b,0xeb,0xc1,0x59,0x72,0xe7,0x89, - 0x37,0x5d,0xd3,0x03,0xc5,0x9b,0x86,0x9b,0xec,0x67,0x6a,0xe2,0xcd,0x10,0x2f,0xed, - 0xaf,0xd0,0xd3,0xc5,0x26,0xf3,0xad,0x8a,0x6c,0xd4,0xe7,0xa2,0xbf,0xfe,0xb7,0x9a, - 0x4d,0x01,0xee,0xaa,0x61,0xa1,0xed,0x8b,0xd4,0x90,0xf4,0x25,0xf4,0x01,0xbd,0xe2, - 0x95,0xa8,0x61,0x95,0xed,0x1f,0xc6,0x57,0xf8,0xb3,0xec,0x1b,0xc0,0xca,0xf8,0x37, - 0xe2,0x2f,0xfb,0x26,0x74,0x25,0xa7,0x9f,0x07,0xe7,0xb4,0x6f,0xc5,0x66,0x81,0x65, - 0x59,0x42,0x7e,0xe5,0x5e,0x6a,0xeb,0x12,0x6a,0xd3,0x7e,0x99,0xeb,0xd7,0x0a,0xcb, - 0x9c,0xce,0x69,0x29,0x52,0x40,0x92,0x5d,0xc9,0x89,0x6a,0x59,0xc1,0x79,0x2d,0xa7, - 0x76,0xed,0x57,0x82,0x95,0x5d,0x6f,0xea,0xb0,0x6f,0x43,0xa7,0x78,0x2d,0x56,0x45, - 0x07,0x75,0x3c,0x66,0x6b,0x07,0x75,0x25,0xbf,0x8a,0xe3,0xdc,0x89,0x5f,0xd1,0xe9, - 0xbb,0xd8,0x4b,0xbf,0x19,0x7d,0xc9,0xe9,0xb7,0x31,0x5f,0x69,0xdf,0x5f,0x53,0xd7, - 0xa0,0xc9,0x7f,0xf6,0x4b,0xfb,0xdd,0xae,0xe7,0xda,0xef,0xa7,0x2f,0x8a,0x7f,0x10, - 0xdf,0x42,0x9c,0x85,0x39,0x61,0x8a,0x5c,0x19,0x6a,0xcc,0x38,0x49,0x35,0x7f,0xc8, - 0xff,0x29,0x7a,0xa3,0xfd,0x61,0xb0,0x94,0xe3,0x08,0x73,0xa0,0x1e,0x1c,0x23,0x7e, - 0xda,0x7f,0x4a,0x0e,0x7f,0xae,0x27,0x55,0x73,0xec,0x77,0x2e,0xce,0x7a,0x29,0x9e, - 0x5b,0x75,0xa6,0xcf,0x92,0xf7,0x6b,0xfa,0x38,0x4d,0x5e,0xed,0x67,0x6a,0x7a,0x7b, - 0x8e,0x5c,0xb2,0xbf,0x84,0xce,0xcf,0xd3,0x2c,0xbd,0x5b,0x63,0x56,0x9a,0xcb,0x2b, - 0x60,0xb3,0xcc,0xd6,0xd3,0x76,0xa2,0x59,0x6a,0x0b,0xd4,0x7c,0xcf,0x10,0x9d,0xf3, - 0x5d,0xdb,0x5d,0x05,0xff,0xc7,0xfe,0x6b,0x76,0xbf,0x43,0xaf,0xf5,0x05,0xb3,0x6a, - 0xe2,0x5b,0xd3,0xc0,0x6c,0x77,0x91,0xb7,0x19,0xfc,0x98,0xd9,0x94,0xe2,0x9d,0xab, - 0x62,0xf3,0x62,0x1f,0xab,0xb5,0xb7,0x80,0xa7,0x38,0x0b,0x88,0xd3,0xea,0xe2,0x2c, - 0x04,0x4f,0x3e,0x8b,0xc0,0xb6,0x9b,0x4f,0x91,0xfb,0xdc,0x02,0xae,0x38,0x6d,0x7c, - 0x07,0x56,0x32,0xaf,0x5d,0xdc,0x8d,0x76,0xf0,0x57,0xcd,0x4b,0x7e,0x8f,0x82,0xb5, - 0xd3,0x33,0xf1,0xfe,0xd1,0xfc,0x35,0xbf,0x8f,0xa3,0x5f,0x1c,0xcf,0x22,0x1f,0xe7, - 0x79,0x35,0xb8,0x7a,0x52,0xa6,0x27,0x7f,0x9b,0x4e,0xf8,0x13,0xb1,0xdf,0xd5,0xbe, - 0xe8,0xff,0x7d,0x5b,0xaf,0xb2,0x2f,0xbb,0x9c,0xeb,0x5c,0xce,0x34,0x6b,0x1f,0xc3, - 0xe3,0x49,0xf2,0xad,0x83,0x87,0xee,0xc9,0x33,0xf0,0xa8,0xc0,0x43,0x76,0x1b,0xc1, - 0x8f,0xe2,0xb7,0x09,0xdf,0x8d,0xf8,0xe9,0xfe,0x3c,0x87,0x5f,0x97,0xeb,0xe3,0xf3, - 0xe0,0xb3,0x66,0xd3,0x11,0x6d,0xab,0x58,0x23,0x9c,0xba,0x1d,0x27,0xe9,0xb6,0x98, - 0x74,0xc3,0x41,0xff,0x77,0x98,0x9f,0xfa,0xff,0x22,0x39,0x43,0xbc,0x03,0xd5,0x33, - 0xd9,0x0a,0xfe,0x9a,0xed,0x54,0xd3,0x4f,0x60,0xc9,0x4e,0xfd,0x48,0xb1,0xb4,0xde, - 0xa6,0x1f,0xbf,0x60,0x53,0xc6,0x67,0x8b,0xe3,0xf0,0x32,0x1c,0xb6,0x39,0x0e,0xaf, - 0x80,0x27,0x0e,0x3d,0x60,0x89,0x43,0x9f,0xe3,0x20,0x5d,0xaf,0x49,0x1f,0x79,0x7b, - 0x1d,0x87,0xed,0xe4,0xce,0x38,0x0e,0x3b,0xc0,0x13,0x87,0x9f,0xc1,0x92,0x9d,0x38, - 0xa4,0x58,0x7d,0x8e,0xc3,0x75,0x6c,0xba,0xf1,0xe9,0x75,0x1c,0x5e,0x87,0x43,0xbf, - 0xe3,0xf0,0x06,0x78,0xe2,0xf0,0x26,0x58,0xe2,0x30,0xe0,0x38,0x48,0xb7,0xd3,0x64, - 0x80,0xbc,0x3b,0xdd,0x2c,0xed,0x22,0xf7,0x75,0xf7,0xad,0x52,0x8d,0xc9,0x76,0xc0, - 0xd5,0xf8,0x3b,0x76,0x7d,0xf8,0x29,0xce,0x25,0xe3,0x29,0xde,0x43,0xcc,0xc2,0x20, - 0xdf,0x4d,0xc5,0xd8,0x4b,0x8c,0xbd,0x2e,0xc6,0x0d,0xe2,0x28,0xee,0x35,0x93,0x51, - 0x74,0xe2,0xf4,0x1b,0xf5,0x4b,0x77,0xcb,0xe9,0x14,0xff,0x57,0xe6,0x57,0xba,0x33, - 0xe8,0x7e,0x80,0xfb,0x5b,0xe8,0xf5,0x7d,0xbe,0x63,0x7c,0x47,0xd0,0x27,0xfe,0xd2, - 0x0f,0x9b,0x8c,0x50,0xcf,0xb0,0x3b,0xc3,0x03,0xd4,0xa4,0xdf,0xf7,0xc4,0x7b,0x07, - 0xbc,0x42,0x2f,0xc7,0x5d,0x2c,0xe9,0xc6,0x4c,0xc6,0x89,0x35,0xc6,0x39,0xe9,0x3d, - 0x78,0x8f,0x73,0xda,0xcf,0x39,0x29,0xfe,0x21,0xf0,0x54,0xeb,0xfb,0xc4,0x3e,0x44, - 0x8f,0x52,0x9c,0x71,0xb8,0xca,0xe6,0x03,0x6a,0x18,0xc6,0x7e,0x8c,0x3a,0x26,0x5d, - 0x1d,0xb2,0x99,0x30,0x99,0xc4,0x7f,0x82,0x9c,0x7a,0x5b,0x3e,0xe2,0x5d,0x49,0x75, - 0x1d,0xa5,0xae,0x23,0xae,0xae,0x4f,0xc0,0x53,0x1f,0x8e,0xd3,0x87,0x4c,0x9c,0xdf, - 0x42,0x7c,0x7b,0x4e,0x50,0xeb,0x71,0xec,0x07,0xad,0x3e,0xbd,0x41,0x9f,0x91,0xe3, - 0x04,0x77,0xbf,0x42,0x1c,0x9d,0xe1,0xe7,0xe8,0xf5,0xbb,0x09,0xf6,0x05,0xf8,0x49, - 0xbe,0xe3,0xca,0xf7,0x25,0x67,0xa6,0x7b,0xf9,0x07,0x76,0xa7,0xb0,0x95,0xee,0x4f, - 0xb0,0xaf,0x98,0x8b,0x53,0xf4,0x2b,0xf1,0x9d,0x74,0x73,0x73,0x0b,0x9b,0x71,0xec, - 0x27,0xf8,0x1e,0x2a,0xcf,0x69,0x38,0x0c,0xb9,0x3b,0x79,0x0d,0xfc,0x86,0x9b,0xf7, - 0x51,0xe2,0x8e,0x3a,0xdf,0x33,0xd4,0x58,0x3b,0xcf,0x23,0xae,0xb7,0xdf,0xd0,0xdb, - 0x73,0xae,0xb7,0xe7,0xc1,0xa7,0xb8,0xab,0x17,0xc0,0xd2,0x1b,0x76,0x91,0xb7,0xe7, - 0x02,0xb9,0x84,0x7d,0x0b,0xde,0x1c,0x63,0x17,0xe2,0x1b,0x7c,0x99,0x77,0xba,0x82, - 0x7e,0xb3,0xcd,0xc0,0x65,0xb8,0xfa,0xb7,0x41,0xeb,0xbf,0x76,0x72,0x9d,0x26,0xff, - 0x03,0xd9,0xf4,0x6d,0x73,0x68,0x0c,0x00,0x00 -}; - -// Generated from: -// -// #version 450 core -// -// #extension GL_EXT_samplerless_texture_functions : require -// -// layout(local_size_x = 8, local_size_y = 8, local_size_z = 1)in; -// -// layout(push_constant)uniform PushConstants { -// -// ivec2 offset; -// vec2 stretch; -// vec2 invSrcExtent; -// int srcLayer; -// int srcWidth; -// -// ivec4 blitArea; -// int destPitch; -// -// bool flipX; -// bool flipY; -// bool rotateXY; -// } params; -// -// layout(set = 0, binding = 0)buffer dst -// { -// -// uint destData[]; -// }; -// -// layout(set = 0, binding = 1)uniform utexture2DMSArray stencil; -// -// void main() -// { -// ivec2 destSubImageCoords = ivec2(gl_GlobalInvocationID . x * 4, gl_GlobalInvocationID . y); -// if(any(lessThanEqual(params . blitArea . zw, destSubImageCoords))) -// { -// return; -// } -// -// destSubImageCoords += params . blitArea . xy; -// ivec2 srcImageCoords = ivec2(destSubImageCoords); -// -// srcImageCoords -= params . offset; -// -// if(params . flipX) -// srcImageCoords . x = - srcImageCoords . x; -// if(params . flipY) -// srcImageCoords . y = - srcImageCoords . y; -// if(params . rotateXY) -// srcImageCoords . xy = srcImageCoords . yx; -// -// int xDir = params . flipX ? - 1 : 1; -// -// uint outStencils = 0; -// -// for(int i = 0;i < 4;++ i) -// { -// -// if(srcImageCoords . x >= 0 && srcImageCoords . x < params . srcWidth) -// { -// -// uint stencilValue = texelFetch(stencil, ivec3(srcImageCoords, params . srcLayer), 0). x; -// -// outStencils |=(stencilValue & 0xFF)<<(i * 8); -// -// } -// -// srcImageCoords . x += xDir; -// } -// -// destData[gl_GlobalInvocationID . y * params . destPitch + gl_GlobalInvocationID . x]= outStencils; -// } diff --git a/src/libANGLE/renderer/vulkan/shaders/gen/ImageCopyFloat.frag.00000000.inc b/src/libANGLE/renderer/vulkan/shaders/gen/ImageCopyFloat.frag.00000000.inc index 392ac52844f..4255bc75068 100644 --- a/src/libANGLE/renderer/vulkan/shaders/gen/ImageCopyFloat.frag.00000000.inc +++ b/src/libANGLE/renderer/vulkan/shaders/gen/ImageCopyFloat.frag.00000000.inc @@ -10,131 +10,133 @@ #pragma once constexpr uint8_t kImageCopyFloat_frag_00000000[] = { - 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x85,0x58,0x7b,0x68,0x97,0x65, - 0x14,0xfe,0xce,0xbb,0xab,0x5a,0x6e,0xe6,0x9c,0x97,0x4a,0xd4,0x65,0x94,0x5b,0xa6, - 0x69,0x66,0xea,0x9a,0xce,0x36,0x03,0x35,0x6b,0xb6,0x34,0x24,0x4c,0xa7,0x79,0xcb, - 0xad,0x4c,0x2d,0xa2,0x42,0xad,0xe8,0x66,0x42,0x21,0x81,0x66,0x81,0x56,0x16,0x1a, - 0x36,0xa4,0x44,0x4a,0xd4,0x7f,0xec,0x82,0x51,0x19,0x04,0x52,0x29,0xd9,0x24,0x50, - 0x8a,0xa2,0xd2,0x4a,0x2d,0x3b,0xcf,0xce,0x73,0xdc,0xf1,0x47,0xd1,0xe0,0xdd,0xef, - 0xf7,0x3e,0xe7,0xf6,0x9c,0xe7,0xbd,0x7c,0xdf,0x96,0x97,0x2a,0x8a,0xb2,0x4c,0xb2, - 0xce,0x59,0x71,0xb6,0x38,0x65,0xed,0x3f,0xdd,0xb2,0xa4,0x88,0x7d,0x5e,0xa3,0x9f, - 0x5d,0xb2,0xc2,0xf6,0xf9,0x84,0x49,0x53,0x27,0x0d,0xbe,0x7f,0xe9,0x9c,0xc1,0xc3, - 0xaf,0x1d,0x02,0xbf,0xae,0x59,0x5e,0xbb,0x3f,0x6c,0x25,0x59,0x51,0x96,0xaf,0x9f, - 0x18,0x8b,0x67,0x2d,0x68,0x06,0x7e,0x5a,0x47,0xb9,0x1a,0x4b,0xd5,0x0f,0xb8,0x16, - 0xca,0x6e,0xca,0x0a,0xb2,0xf1,0x56,0x26,0xab,0xe0,0xa7,0x63,0x42,0xac,0x38,0x60, - 0x89,0x58,0x69,0xc0,0xf2,0x88,0x95,0x05,0x2c,0x9f,0x58,0xaf,0x80,0x15,0x10,0xbb, - 0x24,0x60,0x85,0xc4,0xfa,0x05,0xac,0x88,0xd8,0x65,0x01,0x2b,0x26,0x76,0x45,0xc0, - 0x3a,0x11,0xab,0x0a,0x58,0x67,0x62,0x43,0x02,0xd6,0x85,0xd8,0xf0,0x80,0x5d,0x40, - 0x6c,0x64,0xc0,0x2e,0x24,0x36,0x26,0x60,0x5d,0x89,0x8d,0x85,0xde,0xda,0xa9,0x6b, - 0x30,0x41,0x3b,0x3c,0xcd,0xdc,0x25,0x9c,0x17,0xa8,0x60,0x03,0xa8,0xa1,0xcf,0xfb, - 0x87,0x39,0xb4,0xef,0xcb,0x79,0x77,0xcd,0x82,0x3c,0xfd,0x35,0x67,0x1e,0x73,0x96, - 0xeb,0xb7,0x42,0x6a,0xd1,0x43,0xfd,0x4b,0xf8,0x1d,0xeb,0xd0,0x53,0xe7,0xa5,0xac, - 0x95,0x38,0x2f,0xa7,0x7e,0xd0,0xba,0x52,0x7f,0xe3,0xfb,0xa5,0xd0,0x77,0xf0,0xe4, - 0xd1,0x65,0xea,0xd5,0x37,0xe0,0xe8,0xa1,0x61,0xe7,0xcd,0xe3,0x7c,0x0e,0x1d,0x1b, - 0x1b,0xbf,0xbc,0xc1,0xe7,0x83,0x74,0x54,0x77,0x7e,0xb2,0xc6,0xe7,0xd0,0x74,0xdb, - 0x84,0x59,0xd5,0x3e,0x1f,0xaa,0xe3,0xfb,0x6d,0x03,0xcf,0xcd,0xa1,0xd1,0xfa,0x75, - 0xbd,0xc7,0x82,0x67,0x2d,0x79,0xe2,0xa7,0xaf,0xee,0xd2,0xf1,0xdc,0x1f,0xce,0xd7, - 0x47,0xed,0xff,0x0c,0xf7,0xe9,0xa7,0x39,0x6f,0xe4,0xfa,0x22,0xd7,0x68,0xce,0xeb, - 0x88,0x55,0x52,0x9b,0x7a,0x6a,0x03,0xff,0x09,0xb4,0x95,0x06,0xfb,0x44,0xee,0x39, - 0xd8,0x27,0xd1,0x5e,0x4b,0x3b,0x3e,0xa7,0x90,0xb3,0xfb,0x4f,0xa7,0x9e,0x3e,0x6f, - 0xe2,0xfa,0xfb,0xbc,0x99,0xeb,0xed,0xf3,0xc7,0xb9,0x57,0xb1,0x16,0xcf,0x31,0x36, - 0x2f,0xd8,0xd7,0x72,0xdf,0xba,0x66,0x1b,0x72,0xea,0xb5,0x72,0x1f,0xfa,0x7c,0x1f, - 0x39,0x22,0xdf,0x7e,0xe6,0x4b,0xc1,0x7e,0x80,0xfb,0xdb,0xe7,0xdf,0x70,0xcf,0xa2, - 0xbf,0x43,0x8c,0x2d,0x09,0xf6,0x23,0x39,0xf1,0x6d,0x39,0xf5,0x8f,0xe5,0xec,0x9d, - 0xdf,0xda,0xad,0x2b,0x6a,0x90,0xef,0x14,0xb5,0x2d,0xa7,0xfe,0xa7,0x78,0x7f,0x00, - 0xeb,0xad,0x95,0x92,0x18,0x3f,0xc9,0xce,0xff,0xf1,0xf9,0xc5,0xd8,0xd7,0x3a,0x81, - 0x1f,0xf2,0xe5,0xd3,0x00,0x6c,0x34,0xe7,0x05,0xc4,0x60,0xef,0x21,0xa6,0x9d,0xd7, - 0xc3,0xbc,0x5c,0x3a,0xf4,0x44,0xad,0x06,0x6d,0xa6,0xe5,0x8d,0x25,0xe7,0xf6,0xe8, - 0x54,0x9d,0x3f,0xff,0xd8,0x2b,0xd5,0x23,0x74,0x95,0x13,0x7b,0xc9,0xb8,0x06,0x7f, - 0x28,0x82,0xb5,0xaf,0xe6,0x39,0x39,0x43,0xfe,0x53,0x74,0xc5,0xa0,0xed,0x5f,0xc4, - 0xce,0x04,0xde,0xcd,0x3c,0x63,0x7f,0xd3,0x3e,0x4e,0x33,0x60,0x5f,0x55,0x8a,0xed, - 0xbd,0x7a,0xe6,0x83,0x4f,0x95,0x18,0xbe,0x4a,0x7d,0x30,0xbf,0x4a,0x2c,0x0e,0x38, - 0xe2,0xb0,0xdf,0x06,0x33,0x6e,0x22,0xe3,0xb0,0xe7,0xae,0x16,0xc3,0xb7,0xaa,0x0f, - 0xce,0xe7,0x10,0x31,0x0c,0x7b,0xf1,0x77,0x65,0x3e,0x82,0x9a,0x9c,0x52,0x7f,0xd8, - 0x86,0xea,0x00,0x86,0x7e,0xf0,0xfd,0x56,0x8d,0xc3,0xda,0x0d,0x13,0xab,0x89,0x9f, - 0x47,0xb9,0x9e,0xc3,0xc5,0xf0,0x06,0x55,0x07,0x9c,0x86,0x24,0xc3,0xdc,0xef,0x4f, - 0xcd,0xe1,0xb9,0xf0,0x79,0x42,0xb5,0x80,0xdf,0x6d,0xc9,0x7c,0x0a,0x18,0x33,0x34, - 0xf4,0x70,0x1d,0x7b,0x98,0x1e,0x7a,0x18,0x29,0x86,0x7b,0x0f,0xd7,0x8b,0x61,0xde, - 0x43,0x4d,0xe8,0x01,0xb6,0x51,0x3a,0x6a,0x58,0x77,0x54,0xe8,0x61,0x8c,0x58,0x6d, - 0x09,0x3d,0x54,0x8b,0xe1,0xde,0xc3,0xb0,0x64,0x98,0xfb,0xa1,0x07,0xcf,0x55,0x13, - 0x7a,0x68,0x4c,0xe6,0x83,0xbe,0x10,0x33,0x2a,0xf4,0x30,0x96,0x3d,0x34,0x85,0x1e, - 0xc6,0x89,0xe1,0xde,0x43,0xad,0x18,0xe6,0x3d,0xd4,0x87,0x1e,0x60,0x1b,0xaf,0xa3, - 0x9e,0x75,0xc7,0x8b,0xed,0x23,0xd4,0xad,0x13,0xab,0xdd,0x98,0x3a,0xf6,0x3e,0x38, - 0xba,0x6f,0x7d,0xe0,0x78,0x3b,0xfd,0xc0,0xbb,0x8e,0x39,0xc1,0x07,0x67,0xa2,0x90, - 0xe7,0xc1,0xf7,0x5c,0x11,0x39,0xb7,0x85,0x3d,0x57,0x2c,0x86,0xaf,0xe0,0x9e,0xeb, - 0x2c,0x86,0x21,0x6f,0x0b,0xef,0x8c,0x2e,0x62,0xf8,0x1c,0x9d,0xe3,0xec,0x5d,0xc8, - 0xdc,0xf3,0x18,0xd3,0x95,0x18,0xf2,0x7a,0x4c,0x89,0x18,0xfe,0x94,0xfa,0x60,0x5e, - 0x2a,0x96,0xa7,0x84,0x7c,0x70,0xb7,0x74,0x23,0x9f,0x23,0xe4,0x83,0xb5,0xba,0x48, - 0x0c,0x6f,0xe1,0x79,0xec,0x2e,0x86,0x4d,0xd3,0x7e,0x71,0xe6,0xca,0x58,0x1b,0xf9, - 0x84,0x76,0x5f,0x93,0x06,0xe6,0x6b,0x0e,0x6b,0x32,0x55,0x0c,0xf7,0x35,0xb9,0x4d, - 0x0c,0xf3,0x35,0x99,0x1d,0xd6,0x04,0xb6,0x46,0x1d,0xb3,0xa9,0x73,0x23,0xf7,0x15, - 0x78,0x4c,0x13,0xab,0x9d,0x31,0xee,0x0b,0x7e,0x3f,0xad,0xdf,0x91,0xeb,0x03,0xc6, - 0xe0,0x73,0x17,0x6b,0x7d,0x24,0x16,0x77,0x29,0x63,0x0e,0x84,0x5a,0xb0,0x7d,0xac, - 0xe3,0x13,0xc6,0xe1,0xf3,0x02,0xed,0x11,0xb5,0x3e,0x65,0x6f,0x7d,0x58,0x17,0xcf, - 0xd5,0x27,0xc8,0xe3,0x33,0x31,0x3b,0x9e,0xad,0x8f,0x11,0xfb,0x5c,0x0c,0xaf,0xe2, - 0x3e,0xf9,0x82,0x39,0x91,0xdf,0xe3,0xf6,0x93,0x4b,0x45,0x8e,0x0f,0x38,0x9d,0xd5, - 0x6a,0x7f,0x10,0x3b,0x41,0x0e,0xd3,0x92,0xe5,0x05,0xaf,0xfd,0xe4,0x8a,0xf3,0x83, - 0x35,0x18,0x91,0xcc,0xee,0x7a,0xb8,0x46,0x33,0xa8,0x91,0xb0,0xdf,0xa3,0x39,0x1a, - 0x1d,0x64,0xcd,0x83,0x41,0xa3,0xaf,0xc4,0xe2,0x5c,0xa3,0xb6,0xa0,0x11,0x6c,0x5f, - 0xeb,0x38,0xcc,0xb8,0xc3,0x41,0xa3,0x6f,0x83,0x46,0x33,0x72,0x34,0x3a,0x22,0x66, - 0x8f,0x1a,0x7d,0x27,0x86,0xbb,0x46,0x47,0x99,0xf3,0xeb,0xa0,0xd1,0x21,0x72,0xa9, - 0xc8,0xf1,0x69,0x0b,0x1a,0x1d,0x0d,0x1a,0xdd,0x91,0x2c,0x2f,0x78,0x1d,0x22,0x57, - 0xd7,0xe8,0xfa,0x64,0xf6,0x11,0x3c,0xc3,0xae,0xd1,0x4c,0x6a,0x94,0xd8,0xef,0xc9, - 0x1c,0x8d,0x8e,0xb3,0xe6,0xf1,0xa0,0xd1,0x0f,0x62,0x71,0xae,0xd1,0x89,0xa0,0x11, - 0x6c,0x3f,0xea,0xf8,0x99,0x71,0x3f,0x07,0x8d,0x7e,0x09,0x1a,0xcd,0xcc,0xd1,0xe8, - 0x57,0x31,0x7b,0xd4,0xe8,0x37,0x31,0xdc,0x35,0x3a,0xc9,0x9c,0x3f,0x06,0x8d,0x7e, - 0x22,0x97,0x8a,0x1c,0x9f,0x13,0x41,0xa3,0x93,0x41,0xa3,0x19,0xc9,0xf2,0x82,0xd7, - 0x4f,0xe4,0xea,0x1a,0x8d,0x49,0x66,0x87,0x56,0x89,0xf9,0xfc,0xec,0xcd,0x66,0x0e, - 0xf8,0xdd,0xc9,0xbd,0x86,0x7b,0x0f,0x31,0x27,0xc3,0x99,0x6f,0xe2,0x99,0x7f,0x3c, - 0x9c,0xf9,0x39,0x62,0xb8,0x9f,0xf9,0xb9,0x62,0x98,0x9f,0xf9,0x55,0x41,0x3f,0xd8, - 0xee,0xd6,0xd1,0xcc,0xba,0xcd,0x21,0x77,0x0b,0x73,0xaf,0x0d,0xb9,0xef,0x15,0xc3, - 0x3d,0xf7,0x7d,0x62,0x98,0xe7,0x5e,0x1e,0x72,0xc3,0xb6,0x44,0xc7,0x72,0xe6,0x5e, - 0x12,0xee,0x93,0xa5,0x62,0x7d,0xe1,0xbd,0xe2,0x3d,0xe6,0x5a,0x26,0x86,0x6f,0xa0, - 0x16,0x1e,0xb7,0x9c,0x5a,0xc0,0xe7,0x01,0xb1,0x9a,0xe0,0xb9,0x8c,0xf9,0x51,0x77, - 0x65,0xa8,0x0b,0x9f,0x07,0x75,0xac,0x64,0xfc,0x83,0xa1,0xee,0x43,0xa1,0xee,0x14, - 0x7d,0x93,0xc4,0x3b,0xe6,0xc3,0xc4,0xee,0x4c,0x1d,0xef,0x2d,0xf8,0x7a,0x8b,0x46, - 0xc0,0xfe,0x88,0x58,0x9c,0x0f,0xdc,0xe9,0xc0,0x1f,0x15,0x8b,0x7d,0xa4,0xbd,0xff, - 0x4e,0xed,0x6b,0xb5,0x82,0xb9,0x60,0xcb,0xe7,0xbb,0xb2,0xbf,0xc3,0xa2,0x27,0xe7, - 0xb4,0x32,0xac,0xef,0x5d,0xac,0x8d,0x3e,0x57,0x90,0x3b,0x7c,0x57,0xd1,0xf7,0xee, - 0xc0,0x7f,0xfe,0xbf,0xf0,0x5f,0xf8,0x1f,0xfc,0xd7,0x90,0xe7,0x22,0x31,0x9f,0xf9, - 0x81,0xe7,0x62,0xc6,0x2c,0xfa,0x0f,0x9e,0x5e,0x7b,0x55,0xe0,0x39,0x33,0x19,0x57, - 0x70,0x5f,0xcc,0x7d,0xe3,0x7b,0xe5,0x69,0xee,0x95,0xd6,0xb0,0x57,0x9e,0x11,0xc3, - 0x7d,0xaf,0x3c,0x2b,0x86,0xf9,0x5e,0x59,0x17,0xd6,0x0c,0xb6,0xd5,0x3a,0xd6,0xb1, - 0xee,0xea,0xd0,0xf3,0x1a,0xb1,0xda,0xfe,0xec,0x29,0x4e,0xe7,0xdf,0x19,0x67,0x18, - 0x73,0x26,0xdc,0x19,0x7f,0x8b,0xc5,0x0d,0x65,0x4c,0x51,0xea,0xa8,0x05,0xdb,0x59, - 0xdc,0x41,0xc9,0xe2,0xf0,0xb9,0x92,0xb5,0xf2,0x93,0xc5,0x55,0x85,0xbb,0xa2,0x20, - 0x19,0x8e,0x77,0x65,0xbf,0x5b,0x0a,0x53,0xc7,0xdd,0x02,0xfb,0x18,0xea,0x56,0xcc, - 0x9c,0x67,0xc3,0x9d,0x21,0xcc,0x89,0x77,0xeb,0xe8,0x03,0x4e,0x7e,0x67,0x00,0xf3, - 0x3b,0x63,0x56,0xb2,0xfc,0xe0,0x85,0xd8,0xb3,0xe1,0xce,0xa8,0x4d,0x66,0x77,0x3d, - 0x5c,0xa3,0x17,0xa8,0x91,0x3f,0x7b,0xfa,0xe4,0x68,0xd4,0x95,0x35,0xf1,0xe9,0x1a, - 0x95,0x26,0x8b,0x73,0x8d,0x7a,0x07,0x8d,0x60,0xeb,0x86,0x7b,0x87,0x71,0x65,0x41, - 0xa3,0x72,0xc6,0x45,0x8d,0x7a,0x26,0xc3,0xa3,0x46,0xbd,0x82,0x46,0x3d,0x83,0x46, - 0x7d,0x98,0x13,0xf9,0x3d,0xbe,0x3b,0x73,0xba,0x46,0xee,0xd3,0x3b,0x68,0xd4,0x27, - 0x68,0xd4,0x94,0x2c,0x3f,0x78,0x75,0x27,0x57,0xd7,0xa8,0x2e,0x99,0xbd,0x36,0xe7, - 0xd9,0xf3,0x22,0x35,0xf2,0x67,0x4f,0x55,0x8e,0x46,0xfd,0x58,0xb3,0x5f,0xd0,0x68, - 0x40,0xb2,0x38,0xd7,0xa8,0x32,0x68,0x04,0x5b,0x85,0x8e,0xcb,0x19,0x77,0x79,0xd0, - 0xe8,0x0a,0xc6,0x45,0x8d,0xae,0x4c,0x86,0x47,0x8d,0x06,0x05,0x8d,0xae,0x0c,0x1a, - 0x55,0x31,0x67,0x45,0xd0,0x68,0x20,0x73,0xba,0x46,0xee,0x53,0x19,0x34,0xaa,0x0a, - 0x1a,0xcd,0x4d,0x96,0x1f,0xbc,0x06,0x92,0xab,0x6b,0x74,0x53,0x32,0x7b,0x5d,0x78, - 0xf6,0xf8,0xd9,0x5b,0x17,0xce,0xfc,0x3c,0xee,0x35,0xdc,0x03,0x88,0x41,0x7e,0x3f, - 0xf3,0xeb,0x79,0xe6,0xf7,0x85,0x33,0xff,0x92,0x18,0xee,0x67,0x7e,0x83,0x18,0xe6, - 0x67,0x7e,0x6f,0x38,0xf3,0xb0,0xbd,0xac,0x63,0x13,0xeb,0x6e,0x0a,0xf7,0xc9,0xab, - 0xcc,0x7d,0x20,0xe4,0x7e,0x4d,0x0c,0xf7,0xdc,0xaf,0x8b,0x61,0x9e,0x7b,0x4f,0xc8, - 0x0d,0xdb,0x66,0x1d,0x5b,0x98,0x7b,0x4b,0x78,0xef,0xde,0xca,0xdc,0xdf,0x84,0xf7, - 0xee,0xb7,0xc4,0xf0,0x0f,0xf9,0x77,0xd4,0x36,0x31,0x0c,0xef,0xe6,0x5e,0xef,0x6d, - 0x31,0xbc,0x8d,0xf5,0xb6,0x87,0x7a,0xb0,0xb5,0xea,0xd8,0xce,0x7a,0xad,0xe1,0xcc, - 0x4e,0x4e,0xf6,0x4c,0x9b,0x17,0xfe,0xde,0x72,0xbf,0xed,0x41,0xeb,0xf9,0xc9,0x7c, - 0xc0,0x15,0x31,0xad,0x81,0xcf,0x3b,0xe4,0x73,0x2c,0xf0,0x79,0x57,0x0c,0x77,0x3e, - 0x3b,0x03,0x1f,0xd8,0x76,0xe8,0xd8,0xc9,0x3a,0x3b,0x02,0x9f,0x29,0xe4,0x33,0x3f, - 0xac,0xbd,0xfb,0xed,0x0c,0x7c,0x16,0x24,0xf3,0x01,0x47,0xc4,0xec,0x08,0x7c,0xde, - 0x23,0x9f,0xb5,0x81,0xcf,0xfb,0x62,0xb8,0xf3,0xd9,0x1d,0xf8,0xc0,0xb6,0x4b,0xc7, - 0x6e,0xd6,0xd9,0x15,0xf8,0xdc,0x9a,0xec,0xff,0x24,0x0b,0x52,0xc7,0xf3,0xc7,0xfd, - 0x76,0x07,0x3e,0xf7,0x24,0xf3,0x01,0x47,0xc4,0xec,0xe2,0x73,0x72,0x0f,0x7d,0x37, - 0x87,0x67,0xc6,0x9b,0x62,0x5a,0x22,0x9f,0xd7,0x99,0x98,0x3a,0x70,0xff,0x9b,0xd2, - 0x63,0xf7,0x84,0x3a,0x8b,0x92,0xd5,0x42,0x6d,0xc4,0x6c,0x66,0x9d,0xbd,0xf4,0x7d, - 0x39,0x3c,0x47,0x37,0x32,0x1f,0x86,0xff,0xff,0x37,0x85,0xe7,0xa8,0xc7,0xec,0x0d, - 0xf9,0x17,0x26,0xab,0x81,0x9a,0x1b,0x79,0x06,0x6e,0xd0,0x08,0xfc,0x6f,0x06,0xb6, - 0xbf,0x74,0x97,0x8c,0xd4,0xf1,0x0f,0x32,0x90,0xe5,0x21,0xb8,0x16,0x00,0x00 + 0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x85,0x58,0x59,0x6c,0x56,0x55, + 0x10,0xbe,0x73,0xda,0xd2,0x5a,0x4a,0xc1,0x50,0x8a,0x45,0x96,0x6a,0xd5,0xa0,0x34, + 0x48,0x2b,0xe2,0x42,0x4b,0x4b,0x11,0x5a,0xd3,0x2a,0x2e,0x21,0xa2,0x68,0x4c,0x83, + 0x28,0x88,0xb4,0x22,0xb8,0x44,0x90,0xb0,0x09,0xbc,0xb8,0x40,0xfa,0xa0,0x86,0x88, + 0xcb,0x03,0x2e,0x84,0xa0,0x51,0x42,0x94,0x10,0x25,0x14,0x1f,0x34,0x1a,0x8c,0x0b, + 0x0f,0x68,0x24,0x35,0x2a,0x3c,0x19,0xb5,0x88,0xb4,0x2e,0xf3,0x75,0xbe,0xb1,0xe3, + 0x1f,0x8d,0x7f,0x72,0x7a,0xff,0xf3,0xcd,0xcc,0x37,0x33,0xdf,0x39,0xe7,0xde,0xfb, + 0x37,0x2f,0x55,0x15,0x66,0x99,0x64,0xc5,0x59,0x51,0xb6,0x22,0x65,0x03,0x9f,0xb3, + 0xb3,0xa4,0x88,0x5d,0x6b,0xf5,0x3a,0x34,0x1b,0x32,0x30,0x6f,0x6e,0xbb,0xb9,0x6d, + 0xf2,0x8a,0x95,0x77,0x4d,0x9e,0x7a,0xf9,0x14,0xf8,0x95,0x66,0x79,0x03,0xfe,0xb0, + 0x0d,0xcf,0x0a,0xb3,0x7c,0xbd,0x62,0x2c,0x6b,0x5f,0xd2,0x01,0xbc,0x4f,0xc7,0x58, + 0x35,0x8e,0x50,0x3f,0xe0,0x9a,0x28,0x6b,0xc9,0x0a,0xb2,0x59,0x96,0x26,0xab,0xe2, + 0xd5,0x31,0x21,0x56,0x14,0xb0,0x44,0x6c,0x44,0xc0,0xf2,0x88,0x95,0x05,0x2c,0x9f, + 0xd8,0x39,0x01,0x2b,0x20,0x36,0x36,0x60,0x43,0x88,0x55,0x06,0xac,0x90,0xd8,0x05, + 0x01,0x2b,0x22,0x36,0x31,0x60,0x67,0x11,0xab,0x0e,0x58,0x31,0xb1,0x29,0x01,0x1b, + 0x4a,0x6c,0x6a,0xc0,0x4a,0x88,0x5d,0x19,0xb0,0x61,0xc4,0xea,0x02,0x56,0x4a,0xac, + 0x11,0x7a,0x6b,0xa7,0xae,0x41,0xb3,0x76,0xd8,0x47,0xee,0xe1,0x9c,0x17,0xa8,0x60, + 0xe7,0x53,0x43,0x9f,0x9f,0x17,0xe6,0xd0,0x7e,0x3c,0xe7,0x23,0x95,0x05,0x3c,0xe7, + 0x29,0x67,0x1e,0x39,0xcb,0xf5,0xdb,0x10,0x6a,0x31,0x4a,0xfd,0x87,0xf3,0x3b,0xd6, + 0x61,0xb4,0xce,0x47,0x30,0x57,0xe2,0xbc,0x9c,0xfa,0x41,0xeb,0x49,0xfa,0x17,0xdf, + 0xc7,0x41,0xdf,0xc9,0xd7,0x4d,0x2f,0x53,0xaf,0xf1,0x01,0x47,0x0f,0x37,0xed,0xbb, + 0x7e,0xa6,0xcf,0xa1,0xe3,0xbc,0x79,0x9f,0xcf,0xf0,0xf9,0x25,0x3a,0xea,0x8b,0x37, + 0x37,0xf8,0x1c,0x9a,0xee,0x6e,0x6e,0xaf,0xf7,0x79,0x8d,0x8e,0xef,0x76,0x5f,0xf8, + 0xf7,0x1c,0x1a,0x3d,0xf7,0x6c,0x45,0x23,0xea,0x6c,0x62,0x9d,0xf8,0x8c,0xd7,0x5d, + 0x3a,0x8b,0xfb,0xc3,0xeb,0xf5,0xd1,0xf4,0x3f,0xc3,0x7d,0x2a,0x95,0xf3,0x1a,0xae, + 0x2f,0xb8,0xa6,0x73,0x3e,0x9b,0xd8,0x24,0x6a,0x33,0x87,0xda,0xc0,0xbf,0x99,0xb6, + 0x11,0xc1,0xde,0xca,0x3d,0x07,0x7b,0x1b,0xed,0x4d,0xb4,0xe3,0x3a,0x97,0x35,0xbb, + 0xff,0x7c,0xea,0xe9,0xf3,0x85,0x5c,0x7f,0x9f,0x77,0x70,0xbd,0x7d,0xbe,0x91,0x7b, + 0x15,0x6b,0xf1,0x04,0x63,0xf3,0x82,0xbd,0x8b,0xfb,0xd6,0x35,0xdb,0x9e,0x93,0x6f, + 0x0f,0xf7,0xa1,0xcf,0xbb,0x59,0x23,0xf8,0x3e,0x24,0x5f,0x0a,0xf6,0x23,0xdc,0xdf, + 0x3e,0x3f,0xc6,0x3d,0x8b,0xfe,0xbe,0x62,0xec,0xf0,0x60,0x3f,0x9e,0x13,0xdf,0x93, + 0x93,0xff,0x44,0xce,0xde,0xf9,0x65,0xc0,0xba,0xb6,0x01,0x7c,0x67,0xa8,0x6d,0x39, + 0xf5,0x3f,0xc3,0xfb,0x07,0xb0,0x0a,0xcd,0x94,0xc4,0xea,0x93,0xec,0x9f,0x1f,0x9f, + 0x9f,0x8b,0x7d,0xad,0x13,0xf8,0x81,0x2f,0x9f,0x06,0x60,0xd3,0x39,0x2f,0x90,0xc1, + 0x7a,0xc0,0x55,0x62,0xf3,0x86,0x6a,0x5d,0x35,0xf4,0x3f,0x4c,0x0c,0x2b,0x21,0xc7, + 0xb9,0x62,0xfa,0x7a,0x4d,0x98,0x8f,0x95,0x41,0xcd,0xc1,0x31,0x5f,0x1b,0xee,0xdc, + 0xf9,0xc0,0xdf,0xfb,0xf8,0x56,0x9d,0x6f,0xdd,0xf0,0x7c,0xfd,0x34,0xe5,0x4c,0xec, + 0x37,0xe3,0x3a,0x9d,0x56,0x04,0xfb,0xa3,0x9e,0x67,0xa9,0x9f,0x3d,0xce,0xd5,0x55, + 0x45,0xfe,0xdf,0x89,0xf5,0x87,0xde,0x3a,0x78,0x0e,0xff,0xa0,0x7d,0xa6,0x32,0x60, + 0xef,0xd5,0x88,0xed,0xcf,0x39,0xe4,0x83,0x4f,0xad,0x18,0xbe,0x5e,0x7d,0x30,0xbf, + 0x4c,0x2c,0x0e,0x38,0xe2,0xb0,0x27,0xa7,0x32,0xae,0x95,0x71,0xd8,0x97,0x97,0x8b, + 0xe1,0xaf,0xab,0x0f,0xce,0xf0,0x34,0x31,0x0c,0xfb,0xf5,0x57,0xad,0xbc,0x8e,0xba, + 0x9d,0x51,0x7f,0xd8,0xae,0xd0,0x01,0x0c,0xfd,0xe0,0xfb,0x8d,0x1a,0x87,0xf5,0xbd, + 0x4a,0x2c,0x27,0x3e,0x6b,0xb8,0xe6,0x57,0x8b,0xe1,0x37,0xa9,0x3a,0xa8,0x69,0x5a, + 0x32,0xcc,0xfd,0x7e,0x53,0x0e,0xe7,0xc2,0xb5,0x57,0xb5,0x80,0xdf,0x6d,0xc9,0x7c, + 0x0a,0x18,0x73,0x45,0xe8,0xa1,0x9e,0x3d,0xcc,0x0f,0x3d,0xcc,0x10,0xc3,0xbd,0x87, + 0x06,0x31,0xcc,0x7b,0x98,0x1d,0x7a,0x80,0xad,0x11,0x1c,0xcc,0xdb,0x18,0x7a,0x68, + 0x12,0xcb,0x2d,0xa1,0x87,0x59,0x62,0xb8,0xf7,0x70,0x55,0x32,0xcc,0xfd,0xd0,0x83, + 0x73,0xcd,0x0e,0x3d,0x2c,0x48,0xe6,0x83,0xbe,0x10,0xd3,0x18,0x7a,0x98,0xc3,0x1e, + 0x16,0x86,0x1e,0x9a,0xc5,0x70,0xef,0xa1,0x45,0x0c,0xf3,0x1e,0xda,0x42,0x0f,0xb0, + 0x5d,0xab,0xa3,0x8d,0x79,0xaf,0x15,0xdb,0x47,0xc8,0xdb,0x2a,0x96,0x7b,0x41,0x1a, + 0x3c,0x1f,0xa8,0xd1,0x7d,0xdb,0x42,0x8d,0xb7,0xd3,0x0f,0x75,0xb7,0x92,0x13,0xf5, + 0xe0,0xdc,0x0c,0xe1,0x99,0xf1,0x3d,0x57,0xc8,0x9a,0x7b,0xc2,0x9e,0x2b,0x12,0xc3, + 0xd7,0x72,0xcf,0x15,0x8b,0x61,0xe0,0xed,0xe4,0x7d,0x65,0xa8,0x18,0xbe,0x8e,0xe7, + 0xac,0x54,0x0c,0xc3,0x79,0xbb,0x4b,0x7d,0x70,0x66,0x47,0x32,0xdf,0x3d,0xe4,0x29, + 0x23,0x86,0x5c,0xce,0x33,0x4a,0x0c,0xdf,0x42,0x9e,0x72,0x31,0xae,0x51,0xac,0x11, + 0xf7,0xa4,0xd1,0xac,0xf1,0x38,0x6b,0xc4,0xfa,0x9d,0x23,0x86,0x77,0xf2,0x8c,0x56, + 0x88,0x61,0xb7,0xa8,0x06,0x38,0x87,0x63,0x98,0x1b,0x7c,0x42,0xbb,0xaf,0xd3,0x7c, + 0xf2,0x75,0x84,0x75,0xba,0x55,0x0c,0xf7,0x75,0xba,0x4d,0x0c,0xf3,0x75,0x5a,0x1c, + 0xd6,0x09,0xb6,0x05,0x3a,0x16,0x53,0xfb,0x05,0xdc,0x6b,0xa8,0xe3,0x0e,0xb1,0xdc, + 0x19,0xe3,0x8e,0xf2,0x7b,0x9f,0x7e,0x07,0xd7,0x47,0x8c,0xc1,0x75,0x3f,0x73,0x7d, + 0x2c,0x16,0x37,0x8e,0x31,0x5f,0x86,0x5c,0xb0,0x7d,0xa2,0xe3,0x53,0xc6,0xe1,0x5a, + 0xa2,0x3d,0x22,0xd7,0x67,0xec,0x6d,0x0c,0xf3,0xe2,0x79,0xfc,0x38,0xeb,0xf8,0x5c, + 0xcc,0x8e,0x67,0xf2,0x06,0x62,0x5f,0x88,0xe1,0xd5,0xdc,0x3b,0x47,0xc9,0x09,0x7e, + 0x8f,0x3b,0xc2,0x5a,0xaa,0x72,0x7c,0x50,0xd3,0x9f,0x9a,0xed,0x34,0xb1,0x5e,0xd6, + 0x70,0x47,0x32,0x5e,0xd4,0x75,0x84,0xb5,0xe2,0x4c,0x61,0x0d,0xea,0x92,0xd9,0x5d, + 0x0f,0xd7,0xa8,0x9d,0x1a,0x09,0xfb,0x3d,0x99,0xa3,0xd1,0xd7,0xcc,0xf9,0x75,0xd0, + 0xe8,0x1b,0xb1,0x38,0xd7,0xe8,0x44,0xd0,0x08,0xb6,0xe3,0x3a,0xbe,0x65,0xdc,0xb7, + 0x41,0xa3,0xef,0x82,0x46,0xed,0x39,0x1a,0x7d,0x2f,0x66,0x8f,0x1a,0xfd,0x20,0x86, + 0xbb,0x46,0x27,0xc9,0x79,0x3c,0x68,0xd4,0xc3,0x5a,0xaa,0x72,0x7c,0x4e,0x04,0x8d, + 0x4e,0x06,0x8d,0xee,0x4c,0xc6,0x8b,0xba,0x7a,0x58,0xab,0x6b,0xd4,0x90,0xcc,0x5e, + 0xc7,0x73,0xed,0x1a,0x2d,0xa2,0x46,0x89,0xfd,0xf6,0xe7,0x68,0xf4,0x23,0x73,0xfe, + 0x18,0x34,0xfa,0x49,0x2c,0xce,0x35,0xea,0x0b,0x1a,0xc1,0xf6,0xb3,0x8e,0x53,0x8c, + 0x3b,0x15,0x34,0x3a,0x1d,0x34,0x5a,0x94,0xa3,0xd1,0x6f,0x62,0xf6,0xa8,0xd1,0x19, + 0x31,0xdc,0x35,0xea,0x27,0xe7,0xcf,0x41,0xa3,0x5e,0xd6,0x52,0x95,0xe3,0xd3,0x17, + 0x34,0xea,0x0f,0x1a,0xb5,0x27,0xe3,0x45,0x5d,0xbd,0xac,0xd5,0x35,0x6a,0x4a,0x66, + 0x87,0x56,0x89,0x7c,0x7e,0xf6,0x16,0x93,0x03,0x7e,0x0b,0xb9,0xd7,0x70,0x2f,0x44, + 0x4c,0x7f,0x38,0xf3,0x4b,0x78,0xe6,0x37,0x86,0x33,0x7f,0xaf,0x18,0xee,0x67,0x7e, + 0xa9,0x18,0xe6,0x67,0x7e,0x4b,0xd0,0x0f,0xb6,0xfb,0x74,0xac,0x64,0xde,0x95,0x81, + 0xfb,0x41,0x72,0x77,0x05,0xee,0x87,0xc4,0x70,0xe7,0x7e,0x58,0x0c,0x73,0xee,0xd5, + 0x81,0x1b,0xb6,0x47,0x74,0xac,0x26,0xf7,0x23,0xe1,0x7e,0xf2,0xa8,0x58,0x5f,0x78, + 0xd7,0x78,0x87,0x5c,0xab,0xc4,0xf0,0xed,0xd4,0xc2,0xe3,0x56,0x53,0x0b,0xf8,0x3c, + 0x26,0x96,0x13,0x75,0xae,0x22,0x3f,0xf2,0x6e,0x0e,0x79,0xe1,0xb3,0x46,0xc7,0x66, + 0xc6,0xaf,0x09,0x79,0xd7,0x86,0xbc,0x73,0xf5,0x0d,0x14,0xef,0xa6,0xeb,0x89,0x2d, + 0x4c,0x83,0xef,0x32,0xf8,0x7a,0x83,0x46,0xc0,0xbe,0x41,0x2c,0xce,0x07,0xee,0xe9, + 0xc0,0x37,0x8a,0xc5,0x6e,0x18,0xe8,0xff,0xac,0x81,0xb5,0xda,0x44,0x2e,0xd8,0xf2, + 0xf9,0x8e,0xed,0xef,0xbe,0xe8,0xc9,0x6b,0xda,0x1c,0xd6,0xf7,0x6e,0xe6,0x46,0x9f, + 0x9b,0x58,0x3b,0x7c,0xb7,0xd0,0xf7,0xbe,0x50,0x7f,0xc7,0xbf,0xd4,0x7f,0xff,0x7f, + 0xd4,0xff,0x24,0xeb,0x5c,0x2e,0xe6,0xd3,0x11,0xea,0x5c,0xc1,0x98,0xe5,0xff,0x51, + 0xa7,0xe7,0xde,0x12,0xea,0x5c,0x94,0xac,0x56,0xd4,0xbe,0x82,0xfb,0xc6,0xf7,0xca, + 0x53,0xdc,0x2b,0x7b,0xc2,0x5e,0x79,0x5a,0x0c,0xf7,0xbd,0xb2,0x55,0x0c,0xf3,0xbd, + 0xb2,0x23,0xac,0x19,0x6c,0xdb,0x74,0xec,0x60,0xde,0x6d,0xa1,0xe7,0x2e,0xb1,0xdc, + 0xfe,0xec,0x29,0x4d,0xff,0xbc,0x67,0xa4,0x64,0x31,0xb8,0xfa,0x3d,0x23,0x3f,0x59, + 0x5c,0x0d,0x63,0x86,0xa5,0xc1,0x5c,0xb0,0x15,0xe8,0x28,0x62,0x1c,0xae,0xeb,0x98, + 0xab,0x98,0x71,0xd5,0xe1,0x5e,0x31,0x34,0x19,0x8e,0xf7,0x67,0xbf,0xb7,0x94,0xa4, + 0xc1,0x7b,0x0b,0xec,0x75,0xd4,0xad,0x94,0x9c,0xe0,0xf7,0xf8,0x42,0x72,0xe2,0x7d, + 0x3b,0xfa,0xa0,0x26,0xbf,0x67,0x00,0xf3,0x7b,0xc6,0x3d,0xc9,0xf8,0x51,0x57,0x21, + 0x6b,0xf5,0x7b,0x46,0x4b,0x32,0xbb,0xeb,0xe1,0x1a,0x3d,0x43,0x8d,0xfc,0xd9,0x53, + 0x99,0xa3,0x51,0x19,0x73,0x96,0x05,0x8d,0xca,0x93,0xc5,0xb9,0x46,0x13,0x82,0x46, + 0xb0,0x8d,0xc6,0x7d,0x87,0x71,0x63,0x82,0x46,0x63,0x19,0x17,0x35,0x1a,0x97,0x0c, + 0x8f,0x1a,0x8d,0x0f,0x1a,0x8d,0x0b,0x1a,0x55,0x92,0x73,0x74,0xd0,0xa8,0x82,0x9c, + 0xae,0x91,0xfb,0x4c,0x08,0x1a,0x55,0x06,0x8d,0x96,0x24,0xe3,0x47,0x5d,0x15,0xac, + 0xd5,0x35,0x6a,0x4d,0x66,0x6f,0xc9,0x79,0xf6,0x6c,0xa7,0x46,0xfe,0xec,0xa9,0xcd, + 0xd1,0xe8,0x22,0xe6,0xbc,0x28,0x68,0x34,0x31,0x59,0x9c,0x6b,0x54,0x13,0x34,0x82, + 0xed,0x62,0x1d,0xd5,0x8c,0xab,0x0e,0x1a,0x4d,0x66,0x5c,0xd4,0xe8,0xd2,0x64,0x78, + 0xd4,0x68,0x4a,0xd0,0xe8,0xd2,0xa0,0x51,0x2d,0x39,0x2f,0x0e,0x1a,0x4d,0x22,0xa7, + 0x6b,0xe4,0x3e,0x35,0x41,0xa3,0xda,0xa0,0xd1,0xd2,0x64,0xfc,0xa8,0x6b,0x12,0x6b, + 0x75,0x8d,0xae,0x4f,0x66,0x6f,0x0d,0xcf,0x1e,0x3f,0x7b,0x3b,0xc2,0x99,0x5f,0xc6, + 0xbd,0x86,0xfb,0x00,0x62,0xc0,0xef,0x67,0xfe,0x05,0x9e,0xf9,0xee,0x70,0xe6,0x5f, + 0x14,0xc3,0xfd,0xcc,0xbf,0x24,0x86,0xf9,0x99,0x3f,0x1c,0xce,0x3c,0x6c,0x2f,0xeb, + 0x78,0x85,0x79,0x5f,0x09,0xf7,0x93,0x57,0xc9,0x7d,0x24,0x70,0xbf,0x26,0x86,0x3b, + 0xf7,0xeb,0x62,0x98,0x73,0x77,0x07,0x6e,0xd8,0x76,0xe9,0xd8,0x43,0xee,0x3d,0xe1, + 0xbd,0xfb,0x0d,0x72,0x1f,0x0b,0xef,0xdd,0x6f,0x8a,0xe1,0x1f,0xf0,0xb7,0xd5,0x5b, + 0x62,0x18,0xde,0xcd,0x3d,0xdf,0xdb,0x62,0x78,0x0f,0xf3,0xed,0x0b,0xf9,0x60,0xdb, + 0xab,0x63,0x1f,0xf3,0xed,0x0d,0xcf,0xf9,0x9b,0x93,0x3d,0xd3,0x96,0x85,0xdf,0x60, + 0xee,0xb7,0x2f,0x68,0xdd,0x91,0xcc,0x07,0xb5,0x22,0x66,0x6f,0xa8,0xe7,0x1d,0xd6, + 0x73,0x22,0xd4,0xf3,0xae,0x18,0xee,0xf5,0x1c,0x08,0xf5,0xc0,0xb6,0x5f,0xc7,0x01, + 0xe6,0xd9,0x1f,0xea,0x99,0xc7,0x7a,0x3a,0xc2,0xda,0xbb,0xdf,0x81,0x50,0x4f,0x67, + 0x32,0x1f,0xd4,0x88,0x98,0xfd,0xa1,0x9e,0xf7,0x58,0x4f,0x57,0xa8,0xe7,0x7d,0x31, + 0xdc,0xeb,0x39,0x14,0xea,0x81,0xed,0xa0,0x8e,0x43,0xcc,0x73,0x30,0xd4,0x73,0x4b, + 0xb2,0xff,0xaf,0x74,0xa6,0xc1,0xe7,0x8f,0xfb,0x1d,0x0a,0xf5,0x3c,0x90,0xcc,0x07, + 0x35,0x22,0xe6,0x20,0x9f,0x93,0xdd,0xf4,0xdd,0x15,0x9e,0x19,0xbb,0xc5,0xb4,0x04, + 0x9f,0xe7,0xb9,0x31,0x0d,0xe2,0xfe,0x3b,0xd3,0x63,0xbb,0x43,0x9e,0xe5,0xc9,0x72, + 0x21,0x37,0x62,0x76,0x31,0xcf,0x61,0xfa,0xbe,0x1c,0x9e,0xa3,0x3b,0xc9,0x87,0xe1, + 0xff,0x37,0x4e,0xe1,0x39,0xea,0x31,0x87,0x03,0xff,0xfd,0xc9,0x72,0x20,0xe7,0x4e, + 0x9e,0x81,0x19,0x1a,0x81,0xff,0xd7,0xc0,0xf6,0xbb,0xee,0x92,0x2b,0x75,0xfc,0x05, + 0xf3,0x4b,0xb5,0x25,0xf0,0x16,0x00,0x00 }; // Generated from: @@ -283,7 +285,7 @@ constexpr uint8_t kImageCopyFloat_frag_00000000[] = { // ivec2 srcSubImageCoords = transformImageCoords(ivec2(gl_FragCoord . xy)); // // vec4 srcValue = texture( -// src, vec2(params . srcOffset + srcSubImageCoords)/ textureSize(src, 0), params . srcMip); +// src, vec2((params . srcOffset + srcSubImageCoords)+ vec2(0.5))/ textureSize(src, 0), params . srcMip); // // dst = transformSrcValue(srcValue); // } diff --git a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.frag b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.frag index 66e44599db0..c9fab5848f7 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.frag +++ b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.frag @@ -83,11 +83,11 @@ #if SrcIsArray #define SRC_RESOURCE_NAME texture2DArray #define SRC_SAMPLER_NAME sampler2DArray -#define TEXEL_FETCH(src, coord, sample) texture(src, vec3(coord * params.invSrcExtent, params.srcLayer)) +#define TEXEL_FETCH(src, coord, sample) textureLod(src, vec3(coord * params.invSrcExtent, params.srcLayer), params.srcMip) #else #define SRC_RESOURCE_NAME texture2D #define SRC_SAMPLER_NAME sampler2D -#define TEXEL_FETCH(src, coord, sample) texture(src, coord * params.invSrcExtent) +#define TEXEL_FETCH(src, coord, sample) textureLod(src, coord * params.invSrcExtent, params.srcMip) #endif #define COLOR_TEXEL_FETCH(src, coord, sample) TEXEL_FETCH(COLOR_SRC_RESOURCE(SRC_SAMPLER_NAME)(src, blitSampler), coord, sample) diff --git a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.inc b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.inc index ec3324f5f80..477eaaaf612 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.inc +++ b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolve.inc @@ -9,6 +9,7 @@ layout(push_constant) uniform PushConstants { CoordType offset; vec2 stretch; vec2 invSrcExtent; + int srcMip; int srcLayer; int samples; float invSamples; diff --git a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp index 74665ce80ce..d6e960592d8 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp +++ b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp @@ -18,24 +18,14 @@ #if IsResolve #define CoordType ivec2 -#if SrcIsArray -#define SRC_RESOURCE utexture2DMSArray -#define TEXEL_FETCH(src, coord, sample) texelFetch(src, ivec3(coord, params.srcLayer), sample) -#else #define SRC_RESOURCE utexture2DMS #define TEXEL_FETCH(src, coord, sample) texelFetch(src, coord, sample) -#endif #else #define CoordType vec2 -#if SrcIsArray -#define SRC_RESOURCE utexture2DArray -#define TEXEL_FETCH(src, coord, sample) texture(usampler2DArray(src, blitSampler), vec3(coord * params.invSrcExtent, params.srcLayer)) -#else #define SRC_RESOURCE utexture2D #define TEXEL_FETCH(src, coord, sample) texture(usampler2D(src, blitSampler), coord * params.invSrcExtent) -#endif #endif // IsResolve @@ -48,13 +38,14 @@ layout(push_constant) uniform PushConstants { vec2 invSrcExtent; int srcLayer; int srcWidth; - // Output. - ivec4 blitArea; - int destPitch; + int srcHeight; // Flip control. bool flipX; bool flipY; bool rotateXY; + // Output. + ivec4 blitArea; + int destPitch; } params; layout (set = 0, binding = 0) buffer dst @@ -103,14 +94,23 @@ void main() if (params.rotateXY) srcImageCoords.xy = srcImageCoords.yx; - int xDir = params.flipX ? -1 : 1; + int xDir = 0, yDir = 0; + if (params.rotateXY) + { + yDir = params.flipY ? -1 : 1; + } + else + { + xDir = params.flipX ? -1 : 1; + } uint outStencils = 0; for (int i = 0; i < 4; ++i) { - // Bounds check on X: - if (srcImageCoords.x >= 0 && srcImageCoords.x < params.srcWidth) + // Bounds check on X and Y: + if ((srcImageCoords.x >= 0 && srcImageCoords.x < params.srcWidth) && + (srcImageCoords.y >= 0 && srcImageCoords.y < params.srcHeight)) { // Note: always resolve using sample 0. GLES3 gives us freedom in choosing how // to resolve depth/stencil images. @@ -123,7 +123,14 @@ void main() #endif } - srcImageCoords.x += xDir; + if (params.rotateXY) + { + srcImageCoords.y += yDir; + } + else + { + srcImageCoords.x += xDir; + } } destData[gl_GlobalInvocationID.y * params.destPitch + gl_GlobalInvocationID.x] = outStencils; diff --git a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp.json b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp.json index 6da94f6b043..85899b70f4b 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp.json +++ b/src/libANGLE/renderer/vulkan/shaders/src/BlitResolveStencilNoExport.comp.json @@ -7,7 +7,6 @@ "BlitResolveStencilNoExport.frag.comp: Build parameters for BlitResolveStencilNoExport.comp." ], "Flags": [ - "SrcIsArray", "IsResolve" ] } diff --git a/src/libANGLE/renderer/vulkan/shaders/src/ImageCopyFloat.frag b/src/libANGLE/renderer/vulkan/shaders/src/ImageCopyFloat.frag index e9400915ae5..3669ad51fc9 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/ImageCopyFloat.frag +++ b/src/libANGLE/renderer/vulkan/shaders/src/ImageCopyFloat.frag @@ -34,7 +34,7 @@ void main() #if SrcIsYUV SrcType srcValue = texture( - src, vec2(params.srcOffset + srcSubImageCoords) / textureSize(src, 0), params.srcMip); + src, vec2((params.srcOffset + srcSubImageCoords) + vec2(0.5)) / textureSize(src, 0), params.srcMip); #elif SrcIs2DMS SrcType srcValue = SrcType(0); for (int i = 0; i < params.srcSampleCount; i++) diff --git a/src/libANGLE/renderer/vulkan/shaders/src/third_party/etc_decoder/README.chromium b/src/libANGLE/renderer/vulkan/shaders/src/third_party/etc_decoder/README.chromium index f3b7fd86921..b7372ee39ce 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/third_party/etc_decoder/README.chromium +++ b/src/libANGLE/renderer/vulkan/shaders/src/third_party/etc_decoder/README.chromium @@ -3,6 +3,7 @@ Short Name: Granite URL: https://github.com/Themaister/Granite Version: N/A Revision: cbc9cc966d2b3cae8906d2d30e761904342b5aba +Update Mechanism: Manual License: MIT License File: LICENSE Security Critical: No @@ -16,4 +17,3 @@ Local Modifications: add punchthrough parameter for DecodeRGB. add R11 macro for EAC_R11 decode. rename ALPHA_BITS to alphaBits. - diff --git a/src/libANGLE/renderer/vulkan/shaders/src/third_party/ffx_spd/README.chromium b/src/libANGLE/renderer/vulkan/shaders/src/third_party/ffx_spd/README.chromium index 3ee417ee165..6197078e2be 100644 --- a/src/libANGLE/renderer/vulkan/shaders/src/third_party/ffx_spd/README.chromium +++ b/src/libANGLE/renderer/vulkan/shaders/src/third_party/ffx_spd/README.chromium @@ -4,6 +4,7 @@ URL: https://github.com/GPUOpen-Effects/FidelityFX-SPD Version: 1.0 Date: 2019-05-31 Revision: 0e82a6f4f491aa18adde62edc3f5c4ed20d92627 +Update Mechanism: Manual License: MIT License File: LICENSE Security Critical: No diff --git a/src/libANGLE/renderer/vulkan/spv_utils.cpp b/src/libANGLE/renderer/vulkan/spv_utils.cpp index b096c144d02..de282912dd4 100644 --- a/src/libANGLE/renderer/vulkan/spv_utils.cpp +++ b/src/libANGLE/renderer/vulkan/spv_utils.cpp @@ -7,6 +7,10 @@ // accordingly. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/spv_utils.h" #include @@ -622,7 +626,7 @@ void AssignTransformFeedbackQualifiers(const gl::ProgramExecutable &programExecu std::string fieldName = pos == std::string::npos ? tfVarying.name : tfVarying.name.substr(pos + 1); - if (fieldName == varying->frontVarying.varying->name.c_str()) + if (fieldName == varying->frontVarying.varying->name) { originalVarying = varying; break; @@ -737,7 +741,7 @@ void AssignInputAttachmentBindings(const SpvSourceOptions &options, void AssignInterfaceBlockBindings(const SpvSourceOptions &options, const gl::ProgramExecutable &programExecutable, const std::vector &blocks, - + const DescriptorSetIndex descriptorSetIndex, SpvProgramInterfaceInfo *programInterfaceInfo, ShaderInterfaceVariableInfoMap *variableInfoMapOut) { @@ -760,7 +764,7 @@ void AssignInterfaceBlockBindings(const SpvSourceOptions &options, } variableInfoMapOut->addResource(activeShaders, block.getIds(), - ToUnderlying(DescriptorSetIndex::ShaderResource), + ToUnderlying(descriptorSetIndex), programInterfaceInfo->currentShaderResourceBindingIndex++); } } @@ -833,12 +837,14 @@ void AssignNonTextureBindings(const SpvSourceOptions &options, variableInfoMapOut); const std::vector &uniformBlocks = programExecutable.getUniformBlocks(); - AssignInterfaceBlockBindings(options, programExecutable, uniformBlocks, programInterfaceInfo, + AssignInterfaceBlockBindings(options, programExecutable, uniformBlocks, + DescriptorSetIndex::UniformBuffers, programInterfaceInfo, variableInfoMapOut); const std::vector &storageBlocks = programExecutable.getShaderStorageBlocks(); - AssignInterfaceBlockBindings(options, programExecutable, storageBlocks, programInterfaceInfo, + AssignInterfaceBlockBindings(options, programExecutable, storageBlocks, + DescriptorSetIndex::ShaderResource, programInterfaceInfo, variableInfoMapOut); AssignAtomicCounterBufferBindings(options, programExecutable, programInterfaceInfo, @@ -1551,7 +1557,8 @@ void SpirvVaryingPrecisionFixer::visitVariable(const ShaderInterfaceVariableInfo spv::StorageClass storageClass, spirv::Blob *blobOut) { - if (info.useRelaxedPrecision && info.activeStages[shaderType] && !mFixedVaryingId[id].valid()) + if (info.useRelaxedPrecision != PrecisionAdjustmentEnum::kUnchanged && + info.activeStages[shaderType] && !mFixedVaryingId[id].valid()) { mFixedVaryingId[id] = SpirvTransformerBase::GetNewId(blobOut); mFixedVaryingTypeId[id] = typeId; @@ -1565,7 +1572,7 @@ TransformationState SpirvVaryingPrecisionFixer::transformVariable( spv::StorageClass storageClass, spirv::Blob *blobOut) { - if (info.useRelaxedPrecision && + if (info.useRelaxedPrecision != PrecisionAdjustmentEnum::kUnchanged && (storageClass == spv::StorageClassOutput || storageClass == spv::StorageClassInput)) { // Change existing OpVariable to use fixedVaryingId @@ -1592,8 +1599,8 @@ void SpirvVaryingPrecisionFixer::writeInputPreamble( { const spirv::IdRef id(idIndex); const ShaderInterfaceVariableInfo *info = variableInfoById[id]; - if (info && info->useRelaxedPrecision && info->activeStages[shaderType] && - info->varyingIsInput) + if (info && info->useRelaxedPrecision != PrecisionAdjustmentEnum::kUnchanged && + info->activeStages[shaderType] && info->varyingIsInput) { // This is an input varying, need to cast the mediump value that came from // the previous stage into a highp value that the code wants to work with. @@ -1663,10 +1670,18 @@ void SpirvVaryingPrecisionFixer::writeOutputPrologue( { const spirv::IdRef id(idIndex); const ShaderInterfaceVariableInfo *info = variableInfoById[id]; - if (info && info->useRelaxedPrecision && info->activeStages[shaderType] && - info->varyingIsOutput) + if (info && info->useRelaxedPrecision != PrecisionAdjustmentEnum::kUnchanged && + info->activeStages[shaderType] && info->varyingIsOutput) { ASSERT(mFixedVaryingTypeId[id].valid()); + // b/42266751 + // Make sure we are not trying to copy the entire tessellation control shader output + // array from the temp global variables to the corrected varyings. + // According to spec + // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_tessellation_shader.txt, + // each tessellation control shader invocation may only write to per vertex output + // variables corresponding to its own output patch vertex. + ASSERT(shaderType != gl::ShaderType::TessControl); // Build OpLoad instruction to load the highp value into a temporary const spirv::IdRef tempVar(SpirvTransformerBase::GetNewId(blobOut)); @@ -4051,7 +4066,8 @@ TransformationState SpirvTransformer::transformDecorate(const uint32_t *instruct case spv::DecorationNoPerspective: case spv::DecorationCentroid: case spv::DecorationSample: - if (mOptions.useSpirvVaryingPrecisionFixer && info->useRelaxedPrecision) + if (mOptions.useSpirvVaryingPrecisionFixer && + info->useRelaxedPrecision != PrecisionAdjustmentEnum::kUnchanged) { // Change the id to replacement variable spirv::WriteDecorate(mSpirvBlobOut, replacementId, decoration, decorationValues); @@ -4093,9 +4109,10 @@ TransformationState SpirvTransformer::transformDecorate(const uint32_t *instruct return TransformationState::Transformed; } - // If any, the replacement variable is always reduced precision so add that decoration to - // fixedVaryingId. - if (mOptions.useSpirvVaryingPrecisionFixer && info->useRelaxedPrecision) + // If we are lowering the precision of original variable, the replacement variable is reduced + // precision so add that decoration to fixedVaryingId. + if (mOptions.useSpirvVaryingPrecisionFixer && + info->useRelaxedPrecision == PrecisionAdjustmentEnum::kLowerPrecision) { mVaryingPrecisionFixer.addDecorate(replacementId, mSpirvBlobOut); } @@ -4470,7 +4487,8 @@ TransformationState SpirvTransformer::transformAccessChain(const uint32_t *instr if (mOptions.useSpirvVaryingPrecisionFixer) { - if (info->activeStages[mOptions.shaderType] && !info->useRelaxedPrecision) + if (info->activeStages[mOptions.shaderType] && + info->useRelaxedPrecision == PrecisionAdjustmentEnum::kUnchanged) { return TransformationState::Unchanged; } diff --git a/src/libANGLE/renderer/vulkan/spv_utils.h b/src/libANGLE/renderer/vulkan/spv_utils.h index c0f100179df..3b483565c11 100644 --- a/src/libANGLE/renderer/vulkan/spv_utils.h +++ b/src/libANGLE/renderer/vulkan/spv_utils.h @@ -79,6 +79,13 @@ struct ShaderInterfaceVariableXfbInfo std::vector arrayElements; }; +enum class PrecisionAdjustmentEnum : uint8_t +{ + kUnchanged, + kLowerPrecision, + kUpperPrecision, +}; + // Information for each shader interface variable. Not all fields are relevant to each shader // interface variable. For example opaque uniforms require a set and binding index, while vertex // attributes require a location. @@ -91,7 +98,6 @@ struct ShaderInterfaceVariableInfo location(kInvalid), component(kInvalid), index(kInvalid), - useRelaxedPrecision(false), varyingIsInput(false), varyingIsOutput(false), hasTransformFeedback(false), @@ -99,7 +105,9 @@ struct ShaderInterfaceVariableInfo padding(0), attributeComponentCount(0), attributeLocationCount(0) - {} + { + SetBitField(useRelaxedPrecision, PrecisionAdjustmentEnum::kUnchanged); + } static constexpr uint32_t kInvalid = std::numeric_limits::max(); @@ -118,17 +126,17 @@ struct ShaderInterfaceVariableInfo gl::ShaderBitSet activeStages; // Indicates that the precision needs to be modified in the generated SPIR-V - // to support only transferring medium precision data when there's a precision + // to support only transferring same precision data when there's a precision // mismatch between the shaders. For example, either the VS casts highp->mediump // or the FS casts mediump->highp. - uint8_t useRelaxedPrecision : 1; + PrecisionAdjustmentEnum useRelaxedPrecision : 2; // Indicate if varying is input or output, or both (in case of for example gl_Position in a // geometry shader) uint8_t varyingIsInput : 1; uint8_t varyingIsOutput : 1; uint8_t hasTransformFeedback : 1; uint8_t isArray : 1; - uint8_t padding : 3; + uint8_t padding : 2; // For vertex attributes, this is the number of components / locations. These are used by the // vertex attribute aliasing transformation only. diff --git a/src/libANGLE/renderer/vulkan/vk_barrier_data.cpp b/src/libANGLE/renderer/vulkan/vk_barrier_data.cpp new file mode 100644 index 00000000000..145e7866d5c --- /dev/null +++ b/src/libANGLE/renderer/vulkan/vk_barrier_data.cpp @@ -0,0 +1,894 @@ +// +// Copyright 2025 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. +// + +#include "libANGLE/renderer/vulkan/vk_barrier_data.h" +#include "libANGLE/renderer/vulkan/vk_renderer.h" + +namespace rx +{ +namespace vk +{ +namespace +{ +// clang-format off +constexpr angle::PackedEnumMap kBufferMemoryBarrierData = { + {PipelineStage::TopOfPipe, {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, EventStage::InvalidEnum}}, + {PipelineStage::DrawIndirect, {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, EventStage::VertexInput}}, + {PipelineStage::VertexInput, {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, EventStage::VertexInput}}, + {PipelineStage::VertexShader, {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, EventStage::VertexShader}}, + {PipelineStage::TessellationControl, {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, EventStage::InvalidEnum}}, + {PipelineStage::TessellationEvaluation, {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, EventStage::InvalidEnum}}, + {PipelineStage::GeometryShader, {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, EventStage::InvalidEnum}}, + {PipelineStage::TransformFeedback, {VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, EventStage::TransformFeedbackWrite}}, + {PipelineStage::FragmentShadingRate, {0, EventStage::InvalidEnum}}, + {PipelineStage::EarlyFragmentTest, {0, EventStage::InvalidEnum}}, + {PipelineStage::FragmentShader, {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, EventStage::FragmentShader}}, + {PipelineStage::LateFragmentTest, {0, EventStage::InvalidEnum}}, + {PipelineStage::ColorAttachmentOutput, {0, EventStage::InvalidEnum}}, + {PipelineStage::ComputeShader, {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, EventStage::ComputeShader}}, + {PipelineStage::Transfer, {VK_PIPELINE_STAGE_TRANSFER_BIT, EventStage::InvalidEnum}}, + {PipelineStage::BottomOfPipe, BufferMemoryBarrierData{VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, EventStage::InvalidEnum}}, + {PipelineStage::Host, {VK_PIPELINE_STAGE_HOST_BIT, EventStage::InvalidEnum}}, +}; + +constexpr ImageAccessToMemoryBarrierDataMap kImageMemoryBarrierData = { + { + ImageAccess::Undefined, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_UNDEFINED, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + // Transition to: we don't expect to transition into Undefined. + 0, + // Transition from: there's no data in the image to care about. + 0, + ResourceAccess::ReadOnly, + PipelineStage::InvalidEnum, + // We do not directly use this layout in SetEvent. We transit to other layout before using + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::ColorWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::ColorAttachmentOutput, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::ColorWriteAndInput, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::ColorAttachmentOutput, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::MSRTTEmulationColorUnresolveAndResolve, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::FragmentShader, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthWriteStencilWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + kAllDepthStencilPipelineStageFlags, + kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::EarlyFragmentTest, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthStencilWriteAndInput, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ, + kAllDepthStencilPipelineStageFlags, + kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::EarlyFragmentTest, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthWriteStencilRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + kAllDepthStencilPipelineStageFlags, + kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::EarlyFragmentTest, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthWriteStencilReadFragmentShaderStencilRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::EarlyFragmentTest, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthWriteStencilReadAllShadersStencilRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, + kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::VertexShader, + EventStage::AttachmentAndAllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::DepthReadStencilWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + kAllDepthStencilPipelineStageFlags, + kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::EarlyFragmentTest, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthReadStencilWriteFragmentShaderDepthRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::EarlyFragmentTest, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthReadStencilWriteAllShadersDepthRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, + kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::VertexShader, + EventStage::AttachmentAndAllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::DepthReadStencilRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, + kAllDepthStencilPipelineStageFlags, + kAllDepthStencilPipelineStageFlags, + // Transition to: all reads must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::EarlyFragmentTest, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + + { + ImageAccess::DepthReadStencilReadFragmentShaderRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::EarlyFragmentTest, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthReadStencilReadAllShadersRead, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, + kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, + kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::VertexShader, + EventStage::AttachmentAndAllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::ColorWriteFragmentShaderFeedback, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::FragmentShader, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::ColorWriteAllShadersFeedback, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::VertexShader, + EventStage::AttachmentAndAllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::DepthStencilFragmentShaderFeedback, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::FragmentShader, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::DepthStencilAllShadersFeedback, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags, + kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::VertexShader, + EventStage::AttachmentAndAllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::DepthStencilResolve, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + // Note: depth/stencil resolve uses color output stage and mask! + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::ColorAttachmentOutput, + EventStage::Attachment, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::MSRTTEmulationDepthStencilUnresolveAndResolve, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + // Note: depth/stencil resolve uses color output stage and mask! + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::FragmentShader, + EventStage::AttachmentAndFragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::Present, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + // Transition to: do not delay execution of commands in the second synchronization + // scope. Allow layout transition to be delayed until present semaphore is signaled. + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + // Transition from: use same stages as in Acquire Image Semaphore stage mask in order to + // build a dependency chain from the Acquire Image Semaphore to the layout transition's + // first synchronization scope. + kSwapchainAcquireImageWaitStageFlags, + // Transition to: vkQueuePresentKHR automatically performs the appropriate memory barriers: + // + // > Any writes to memory backing the images referenced by the pImageIndices and + // > pSwapchains members of pPresentInfo, that are available before vkQueuePresentKHR + // > is executed, are automatically made visible to the read access performed by the + // > presentation engine. + 0, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::BottomOfPipe, + // We do not directly use this layout in SetEvent. + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::SharedPresent, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, + // All currently possible stages for SharedPresent + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_MEMORY_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::BottomOfPipe, + EventStage::AttachmentAndFragmentShaderAndTransfer, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::ExternalPreInitialized, + ImageMemoryBarrierData{ + // Binding a VkImage with an initial layout of VK_IMAGE_LAYOUT_UNDEFINED to external + // memory whose content has already been defined does not make the content undefined + // (see 12.8.1. External Resource Sharing). + // + // Note that for external memory objects, if the content is already defined, the + // ownership rules imply that the first operation on the texture must be a call to + // glWaitSemaphoreEXT that grants ownership of the image and informs us of the true + // layout. If the content is not already defined, the first operation may not be a + // glWaitSemaphore, but in this case undefined layout is appropriate. + VK_IMAGE_LAYOUT_UNDEFINED, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + // Transition to: we don't expect to transition into PreInitialized. + 0, + // Transition from: all writes must finish before barrier. + VK_ACCESS_MEMORY_WRITE_BIT, + ResourceAccess::ReadOnly, + PipelineStage::InvalidEnum, + // We do not directly use this layout in SetEvent. We transit to internal layout before using + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::ExternalShadersReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::TopOfPipe, + // We do not directly use this layout in SetEvent. We transit to internal layout before using + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::ExternalShadersWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::TopOfPipe, + // We do not directly use this layout in SetEvent. We transit to internal layout before using + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::ForeignAccess, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + // Transition to: we don't expect to transition into ForeignAccess, that's done at + // submission time by the CommandQueue; the following value doesn't matter. + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + // Transition to: see dstStageMask + 0, + // Transition from: all writes must finish before barrier; it is unknown how the foreign + // entity has access the memory. + VK_ACCESS_MEMORY_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::TopOfPipe, + // We do not directly use this layout in SetEvent. We transit to internal layout before using + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::TransferSrc, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + // Transition to: all reads must happen after barrier. + VK_ACCESS_TRANSFER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::Transfer, + EventStage::Transfer, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::TransferDst, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + // Transition to: all writes must happen after barrier. + VK_ACCESS_TRANSFER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_TRANSFER_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::Transfer, + EventStage::Transfer, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::TransferSrcDst, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_TRANSFER_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::Transfer, + EventStage::Transfer, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::HostCopy, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + // Transition to: we don't expect to transition into HostCopy on the GPU. + 0, + // Transition from: the data was initialized in the image by the host. Note that we + // only transition to this layout if the image was previously in UNDEFINED, in which + // case it didn't contain any data prior to the host copy either. + 0, + ResourceAccess::ReadOnly, + PipelineStage::InvalidEnum, + // We do not directly use this layout in SetEvent. + EventStage::InvalidEnum, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::VertexShaderReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::VertexShader, + EventStage::VertexShader, + PipelineStageGroup::PreFragmentOnly, + }, + }, + { + ImageAccess::VertexShaderWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::VertexShader, + EventStage::VertexShader, + PipelineStageGroup::PreFragmentOnly, + }, + }, + { + ImageAccess::PreFragmentShadersReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + kPreFragmentStageFlags, + kPreFragmentStageFlags, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::VertexShader, + EventStage::PreFragmentShaders, + PipelineStageGroup::PreFragmentOnly, + }, + }, + { + ImageAccess::PreFragmentShadersWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + kPreFragmentStageFlags, + kPreFragmentStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::VertexShader, + EventStage::PreFragmentShaders, + PipelineStageGroup::PreFragmentOnly, + }, + }, + { + ImageAccess::FragmentShadingRateAttachmentReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + // Transition to: all reads must happen after barrier. + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::FragmentShadingRate, + EventStage::FragmentShadingRate, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::FragmentShaderReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::FragmentShader, + EventStage::FragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::FragmentShaderWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::FragmentShader, + EventStage::FragmentShader, + PipelineStageGroup::FragmentOnly, + }, + }, + { + ImageAccess::ComputeShaderReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + PipelineStage::ComputeShader, + EventStage::ComputeShader, + PipelineStageGroup::ComputeOnly, + }, + }, + { + ImageAccess::ComputeShaderWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT, + ResourceAccess::ReadWrite, + PipelineStage::ComputeShader, + EventStage::ComputeShader, + PipelineStageGroup::ComputeOnly, + }, + }, + { + ImageAccess::AllGraphicsShadersReadOnly, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + kAllShadersPipelineStageFlags, + kAllShadersPipelineStageFlags, + // Transition to: all reads must happen after barrier. + VK_ACCESS_SHADER_READ_BIT, + // Transition from: RAR and WAR don't need memory barrier. + 0, + ResourceAccess::ReadOnly, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::VertexShader, + EventStage::AllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::AllGraphicsShadersWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + kAllShadersPipelineStageFlags, + kAllShadersPipelineStageFlags, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::VertexShader, + EventStage::AllShaders, + PipelineStageGroup::Other, + }, + }, + { + ImageAccess::TransferDstAndComputeWrite, + ImageMemoryBarrierData{ + VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, + // Transition to: all reads and writes must happen after barrier. + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT, + // Transition from: all writes must finish before barrier. + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, + ResourceAccess::ReadWrite, + // In case of multiple destination stages, We barrier the earliest stage + PipelineStage::ComputeShader, + EventStage::TransferAndComputeShader, + PipelineStageGroup::Other, + }, + }, +}; +// clang-format on + +PipelineStageGroup GetPipelineStageGroupFromStageFlags(VkPipelineStageFlags dstStageMask) +{ + if ((dstStageMask & ~kFragmentAndAttachmentPipelineStageFlags) == 0) + { + return PipelineStageGroup::FragmentOnly; + } + else if (dstStageMask == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) + { + return PipelineStageGroup::ComputeOnly; + } + else if ((dstStageMask & ~kPreFragmentStageFlags) == 0) + { + return PipelineStageGroup::PreFragmentOnly; + } + return PipelineStageGroup::Other; +} +} // namespace + +const BufferMemoryBarrierData &GetBufferMemoryBarrierData(PipelineStage stage) +{ + return kBufferMemoryBarrierData[stage]; +} + +ImageAccess GetImageAccessFromGLImageLayout(ErrorContext *context, GLenum layout) +{ + switch (layout) + { + case GL_NONE: + return ImageAccess::Undefined; + case GL_LAYOUT_GENERAL_EXT: + return ImageAccess::ExternalShadersWrite; + case GL_LAYOUT_COLOR_ATTACHMENT_EXT: + return ImageAccess::ColorWrite; + case GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT: + return ImageAccess::DepthWriteStencilWrite; + case GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT: + return ImageAccess::DepthReadStencilRead; + case GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT: + return ImageAccess::DepthReadStencilWrite; + case GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT: + return ImageAccess::DepthWriteStencilRead; + case GL_LAYOUT_SHADER_READ_ONLY_EXT: + return ImageAccess::ExternalShadersReadOnly; + case GL_LAYOUT_TRANSFER_SRC_EXT: + return ImageAccess::TransferSrc; + case GL_LAYOUT_TRANSFER_DST_EXT: + return ImageAccess::TransferDst; + default: + UNREACHABLE(); + return vk::ImageAccess::Undefined; + } +} + +void InitializeEventStageToVkPipelineStageFlagsMap( + EventStageToVkPipelineStageFlagsMap *map, + VkPipelineStageFlags supportedVulkanPipelineStageMask) +{ + map->fill(0); + + for (const BufferMemoryBarrierData &bufferBarrierData : kBufferMemoryBarrierData) + { + const EventStage eventStage = bufferBarrierData.eventStage; + if (eventStage != EventStage::InvalidEnum) + { + (*map)[eventStage] |= + bufferBarrierData.pipelineStageFlags & supportedVulkanPipelineStageMask; + } + } + + for (const ImageMemoryBarrierData &imageBarrierData : kImageMemoryBarrierData) + { + const EventStage eventStage = imageBarrierData.eventStage; + if (eventStage != EventStage::InvalidEnum) + { + (*map)[eventStage] |= imageBarrierData.dstStageMask & supportedVulkanPipelineStageMask; + } + } +} + +void InitializeImageLayoutAndMemoryBarrierDataMap( + const angle::FeaturesVk &features, + ImageAccessToMemoryBarrierDataMap *map, + VkPipelineStageFlags supportedVulkanPipelineStageMask) +{ + *map = kImageMemoryBarrierData; + for (ImageMemoryBarrierData &barrierData : *map) + { + barrierData.srcStageMask &= supportedVulkanPipelineStageMask; + barrierData.dstStageMask &= supportedVulkanPipelineStageMask; + ASSERT(barrierData.pipelineStageGroup == + GetPipelineStageGroupFromStageFlags(barrierData.dstStageMask)); + } + + // Use the GENERAL layout if possible and efficient. By removing image layout transitions, + // we're able to issue more efficient synchronization. + if (features.supportsUnifiedImageLayouts.enabled) + { + for (ImageMemoryBarrierData &barrierData : *map) + { + if (barrierData.layout != VK_IMAGE_LAYOUT_UNDEFINED && + barrierData.layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && + barrierData.layout != VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR) + { + ASSERT(barrierData.layout != VK_IMAGE_LAYOUT_PREINITIALIZED); + barrierData.layout = VK_IMAGE_LAYOUT_GENERAL; + } + } + } + + // When dynamic rendering is not enabled, input attachments should use the GENERAL layout. + if (!features.preferDynamicRendering.enabled) + { + (*map)[ImageAccess::ColorWriteAndInput].layout = VK_IMAGE_LAYOUT_GENERAL; + (*map)[ImageAccess::DepthStencilWriteAndInput].layout = VK_IMAGE_LAYOUT_GENERAL; + } +} + +} // namespace vk +} // namespace rx diff --git a/src/libANGLE/renderer/vulkan/vk_barrier_data.h b/src/libANGLE/renderer/vulkan/vk_barrier_data.h new file mode 100644 index 00000000000..aa8801ea96b --- /dev/null +++ b/src/libANGLE/renderer/vulkan/vk_barrier_data.h @@ -0,0 +1,191 @@ +// +// Copyright 2025 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. +// + +#ifndef LIBANGLE_RENDERER_VULKAN_VK_BARRIER_DATA_H_ +#define LIBANGLE_RENDERER_VULKAN_VK_BARRIER_DATA_H_ + +#include +#include +#include + +#include "libANGLE/renderer/vulkan/vk_cache_utils.h" +#include "libANGLE/renderer/vulkan/vk_ref_counted_event.h" + +namespace angle +{ +struct FeaturesVk; +} + +namespace rx +{ +namespace vk +{ +class Renderer; + +// Information useful for buffer-related barriers +struct BufferMemoryBarrierData +{ + VkPipelineStageFlags pipelineStageFlags; + // EventStage::InvalidEnum indicates don't use VkEvent for barrier(i.e., use pipelineBarrier + // instead) + EventStage eventStage; +}; + +const BufferMemoryBarrierData &GetBufferMemoryBarrierData(PipelineStage stage); + +// Imagine an image going through a few layout transitions: +// +// srcStage 1 dstStage 2 srcStage 2 dstStage 3 +// Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3 +// srcAccess 1 dstAccess 2 srcAccess 2 dstAccess 3 +// \_________________ ___________________/ +// \/ +// A transition +// +// Every transition requires 6 pieces of information: from/to layouts, src/dst stage masks and +// src/dst access masks. At the moment we decide to transition the image to Layout 2 (i.e. +// Transition 1), we need to have Layout 1, srcStage 1 and srcAccess 1 stored as history of the +// image. To perform the transition, we need to know Layout 2, dstStage 2 and dstAccess 2. +// Additionally, we need to know srcStage 2 and srcAccess 2 to retain them for the next transition. +// +// That is, with the history kept, on every new transition we need 5 pieces of new information: +// layout/dstStage/dstAccess to transition into the layout, and srcStage/srcAccess for the future +// transition out from it. Given the small number of possible combinations of these values, an +// enum is used were each value encapsulates these 5 pieces of information: +// +// +--------------------------------+ +// srcStage 1 | dstStage 2 srcStage 2 | dstStage 3 +// Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3 +// srcAccess 1 |dstAccess 2 srcAccess 2| dstAccess 3 +// +--------------- ---------------+ +// \/ +// One enum value +// +// Note that, while generally dstStage for the to-transition and srcStage for the from-transition +// are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively. +enum class ImageAccess +{ + Undefined = 0, + // Framebuffer attachment accesses are placed first, so they can fit in fewer bits in + // PackedAttachmentOpsDesc. + + // Color (Write): + ColorWrite, + // Used only with dynamic rendering, because it needs a different VkImageLayout + ColorWriteAndInput, + MSRTTEmulationColorUnresolveAndResolve, + + // Depth (Write), Stencil (Write) + DepthWriteStencilWrite, + // Used only with dynamic rendering, because it needs a different VkImageLayout. For + // simplicity, depth/stencil attachments when used as input attachments don't attempt to + // distinguish read-only aspects. That's only useful for supporting feedback loops, but if an + // application is reading depth or stencil through an input attachment, it's safe to assume they + // wouldn't be accessing the other aspect through a sampler! + DepthStencilWriteAndInput, + + // Depth (Write), Stencil (Read) + DepthWriteStencilRead, + DepthWriteStencilReadFragmentShaderStencilRead, + DepthWriteStencilReadAllShadersStencilRead, + + // Depth (Read), Stencil (Write) + DepthReadStencilWrite, + DepthReadStencilWriteFragmentShaderDepthRead, + DepthReadStencilWriteAllShadersDepthRead, + + // Depth (Read), Stencil (Read) + DepthReadStencilRead, + DepthReadStencilReadFragmentShaderRead, + DepthReadStencilReadAllShadersRead, + + // The GENERAL layout is used when there's a feedback loop. For depth/stencil it doesn't matter + // which aspect is participating in feedback and whether the other aspect is read-only. + ColorWriteFragmentShaderFeedback, + ColorWriteAllShadersFeedback, + DepthStencilFragmentShaderFeedback, + DepthStencilAllShadersFeedback, + + // Depth/stencil resolve is special because it uses the _color_ output stage and mask + DepthStencilResolve, + MSRTTEmulationDepthStencilUnresolveAndResolve, + + Present, + SharedPresent, + // The rest of the accesses. + ExternalPreInitialized, + ExternalShadersReadOnly, + ExternalShadersWrite, + ForeignAccess, + TransferSrc, + TransferDst, + TransferSrcDst, + // Used when the image is transitioned on the host for use by host image copy + HostCopy, + VertexShaderReadOnly, + VertexShaderWrite, + // PreFragment == Vertex, Tessellation and Geometry stages + PreFragmentShadersReadOnly, + PreFragmentShadersWrite, + FragmentShadingRateAttachmentReadOnly, + FragmentShaderReadOnly, + FragmentShaderWrite, + ComputeShaderReadOnly, + ComputeShaderWrite, + AllGraphicsShadersReadOnly, + AllGraphicsShadersWrite, + TransferDstAndComputeWrite, + + InvalidEnum, + EnumCount = InvalidEnum, +}; + +ImageAccess GetImageAccessFromGLImageLayout(ErrorContext *context, GLenum layout); + +// Information useful for image-related barriers +struct ImageMemoryBarrierData +{ + // The Vk layout corresponding to the ImageAccess key. + VkImageLayout layout; + + // The stage in which the image is used (or Bottom/Top if not using any specific stage). Unless + // Bottom/Top (Bottom used for transition to and Top used for transition from), the two values + // should match. + VkPipelineStageFlags dstStageMask; + VkPipelineStageFlags srcStageMask; + // Access mask when transitioning into this layout. + VkAccessFlags dstAccessMask; + // Access mask when transitioning out from this layout. Note that source access mask never + // needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers). + VkAccessFlags srcAccessMask; + // Read or write. + ResourceAccess type; + // *CommandBufferHelper track an array of PipelineBarriers. This indicates which array element + // this should be merged into. Right now we track individual barrier for every PipelineStage. If + // layout has a single stage mask bit, we use that stage as index. If layout has multiple stage + // mask bits, we pick the lowest stage as the index since it is the first stage that needs + // barrier. + PipelineStage barrierIndex; + EventStage eventStage; + // The pipeline stage flags group that used for heuristic. + PipelineStageGroup pipelineStageGroup; +}; +using ImageAccessToMemoryBarrierDataMap = angle::PackedEnumMap; + +// Initialize EventStage to VkPipelineStageFlags mapping table. +void InitializeEventStageToVkPipelineStageFlagsMap( + EventStageToVkPipelineStageFlagsMap *map, + VkPipelineStageFlags supportedVulkanPipelineStageMask); + +// Initialize ImageAccess to ImageMemoryBarrierData mapping table. +void InitializeImageLayoutAndMemoryBarrierDataMap( + const angle::FeaturesVk &features, + ImageAccessToMemoryBarrierDataMap *mapping, + VkPipelineStageFlags supportedVulkanPipelineStageMask); + +} // namespace vk +} // namespace rx +#endif // LIBANGLE_RENDERER_VULKAN_VK_BARRIER_DATA_H_ diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp index 96dfe510159..616aec3f64f 100644 --- a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp @@ -8,9 +8,14 @@ // Also contains the structures for the packed descriptions for the RenderPass and Pipeline. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "common/aligned_memory.h" +#include "common/span.h" #include "common/system_utils.h" #include "libANGLE/BlobCache.h" #include "libANGLE/VertexAttribute.h" @@ -112,20 +117,9 @@ constexpr GraphicsPipelineTransitionBits kPipelineShadersTransitionBitsMask = TransitionBits(kPipelineShadersDescOffset)) & ~GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineShadersDescOffset)); -constexpr GraphicsPipelineTransitionBits kPipelineFragmentOutputTransitionBitsMask = - GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineFragmentOutputDescSize) + - TransitionBits(kPipelineFragmentOutputDescOffset)) & - ~GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineFragmentOutputDescOffset)); - -constexpr GraphicsPipelineTransitionBits kPipelineVertexInputTransitionBitsMask = - GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineVertexInputDescSize) + - TransitionBits(kPipelineVertexInputDescOffset)) & - ~GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineVertexInputDescOffset)); - bool GraphicsPipelineHasVertexInput(GraphicsPipelineSubset subset) { - return subset == GraphicsPipelineSubset::Complete || - subset == GraphicsPipelineSubset::VertexInput; + return subset == GraphicsPipelineSubset::Complete; } bool GraphicsPipelineHasShaders(GraphicsPipelineSubset subset) @@ -135,13 +129,12 @@ bool GraphicsPipelineHasShaders(GraphicsPipelineSubset subset) bool GraphicsPipelineHasShadersOrFragmentOutput(GraphicsPipelineSubset subset) { - return subset != GraphicsPipelineSubset::VertexInput; + return true; } bool GraphicsPipelineHasFragmentOutput(GraphicsPipelineSubset subset) { - return subset == GraphicsPipelineSubset::Complete || - subset == GraphicsPipelineSubset::FragmentOutput; + return subset == GraphicsPipelineSubset::Complete; } uint8_t PackGLBlendOp(gl::BlendEquationType blendOp) @@ -311,6 +304,19 @@ enum class DynamicRenderingInfoSubset Pipeline, }; +bool IsReadOnlyDepthStencilAccess(ImageAccess imageAccess) +{ + switch (imageAccess) + { + case ImageAccess::DepthReadStencilRead: + case ImageAccess::DepthReadStencilReadFragmentShaderRead: + case ImageAccess::DepthReadStencilReadAllShadersRead: + return true; + default: + return false; + } +} + void DeriveRenderingInfo(Renderer *renderer, const RenderPassDesc &desc, DynamicRenderingInfoSubset subset, @@ -320,7 +326,8 @@ void DeriveRenderingInfo(Renderer *renderer, const vk::AttachmentOpsArray &ops, const PackedClearValuesArray &clearValues, uint32_t layerCount, - DynamicRenderingInfo *infoOut) + DynamicRenderingInfo *infoOut, + bool *isReadOnlyDepthStencilOut) { ASSERT(renderer->getFeatures().preferDynamicRendering.enabled); // MSRTT cannot be emulated over dynamic rendering. @@ -393,13 +400,22 @@ void DeriveRenderingInfo(Renderer *renderer, if (subset == DynamicRenderingInfoSubset::Full) { - const VkImageLayout layout = vk::ConvertImageLayoutToVkImageLayout( - renderer, static_cast(ops[attachmentCount].initialLayout)); - const VkImageLayout resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ASSERT(static_cast(ops[attachmentCount].initialLayout) != + vk::ImageAccess::SharedPresent || + static_cast(ops[attachmentCount].finalLayout) == + vk::ImageAccess::SharedPresent); + const VkImageLayout layout = renderer->getVkImageLayout( + static_cast(ops[attachmentCount].initialLayout)); + const VkImageLayout resolveImageLayout = renderer->getVkImageLayout( + static_cast(ops[attachmentCount].finalResolveLayout)); + const bool hasColorResolveAttachment = desc.hasColorResolveAttachment(colorIndexGL); + const bool isIntegerFormat = angle::Format::Get(attachmentFormatID).isInt(); const VkResolveModeFlagBits resolveMode = isYUVExternalFormat ? VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID - : desc.hasColorResolveAttachment(colorIndexGL) ? VK_RESOLVE_MODE_AVERAGE_BIT - : VK_RESOLVE_MODE_NONE; + : hasColorResolveAttachment || desc.isRenderToTexture() + ? isIntegerFormat ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT + : VK_RESOLVE_MODE_AVERAGE_BIT + : VK_RESOLVE_MODE_NONE; const RenderPassLoadOp loadOp = static_cast(ops[attachmentCount].loadOp); const RenderPassStoreOp storeOp = @@ -411,9 +427,22 @@ void DeriveRenderingInfo(Renderer *renderer, // See description of RenderPassFramebuffer::mImageViews regarding the layout of the // attachmentViews. In short, the draw attachments are packed, while the resolve // attachments are not. + if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve()) + { + // If nullColorAttachmentWithExternalFormatResolve is VK_TRUE, attachmentViews has + // no color attachment imageView and only has resolveImageView. + infoOut->colorAttachmentInfo[attachmentCount.get()].imageView = VK_NULL_HANDLE; + infoOut->colorAttachmentInfo[attachmentCount.get()].resolveImageView = + attachmentViews[attachmentCount.get()]; + infoOut->colorAttachmentInfo[attachmentCount.get()].clearValue = + clearValues[attachmentCount]; + + ++attachmentCount; + continue; + } infoOut->colorAttachmentInfo[attachmentCount.get()].imageView = attachmentViews[attachmentCount.get()]; - if (resolveMode != VK_RESOLVE_MODE_NONE) + if (resolveMode != VK_RESOLVE_MODE_NONE && !desc.isRenderToTexture()) { infoOut->colorAttachmentInfo[attachmentCount.get()].resolveImageView = attachmentViews[RenderPassFramebuffer::kColorResolveAttachmentBegin + @@ -455,10 +484,11 @@ void DeriveRenderingInfo(Renderer *renderer, const bool resolveStencil = angleFormat.stencilBits != 0 && desc.hasStencilResolveAttachment(); - const VkImageLayout layout = ConvertImageLayoutToVkImageLayout( - renderer, static_cast(ops[attachmentCount].initialLayout)); + const ImageAccess imageAccess = + static_cast(ops[attachmentCount].initialLayout); + const VkImageLayout layout = renderer->getVkImageLayout(imageAccess); const VkImageLayout resolveImageLayout = - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + renderer->getVkImageLayout(ImageAccess::DepthWriteStencilWrite); const VkResolveModeFlagBits depthResolveMode = resolveDepth ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_NONE; const VkResolveModeFlagBits stencilResolveMode = @@ -497,6 +527,11 @@ void DeriveRenderingInfo(Renderer *renderer, angleFormat.depthBits == 0 ? nullptr : &infoOut->depthAttachmentInfo; infoOut->renderingInfo.pStencilAttachment = angleFormat.stencilBits == 0 ? nullptr : &infoOut->stencilAttachmentInfo; + + if (isReadOnlyDepthStencilOut != nullptr) + { + *isReadOnlyDepthStencilOut = IsReadOnlyDepthStencilAccess(imageAccess); + } } ++attachmentCount; @@ -531,7 +566,7 @@ void DeriveRenderingInfo(Renderer *renderer, VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR; infoOut->fragmentShadingRateInfo.imageView = attachmentViews[attachmentCount.get()]; infoOut->fragmentShadingRateInfo.imageLayout = - VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; + renderer->getVkImageLayout(vk::ImageAccess::FragmentShadingRateAttachmentReadOnly); infoOut->fragmentShadingRateInfo.shadingRateAttachmentTexelSize = renderer->getMaxFragmentShadingRateAttachmentTexelSize(); @@ -540,10 +575,17 @@ void DeriveRenderingInfo(Renderer *renderer, } } +enum class ShadersStateSource +{ + ThisPipeline, + PipelineLibrary, +}; + void AttachPipelineRenderingInfo(ErrorContext *context, const RenderPassDesc &desc, const DynamicRenderingInfo &renderingInfo, GraphicsPipelineSubset subset, + ShadersStateSource shadersSource, VkPipelineRenderingCreateInfoKHR *pipelineRenderingInfoOut, VkRenderingAttachmentLocationInfoKHR *attachmentLocationsOut, VkRenderingInputAttachmentIndexInfoKHR *inputLocationsOut, @@ -572,8 +614,11 @@ void AttachPipelineRenderingInfo(ErrorContext *context, renderingInfo.colorAttachmentLocations.data(); AddToPNextChain(createInfoOut, attachmentLocationsOut); - // Note: VkRenderingInputAttachmentIndexInfoKHR only affects the fragment stage subset. - if (desc.hasColorFramebufferFetch() && GraphicsPipelineHasShaders(subset)) + // Note: VkRenderingInputAttachmentIndexInfoKHR only affects the fragment stage subset, and is + // needed only when the shaders stage is not coming from a pipeline library (where this mapping + // is already specified). + if (desc.hasColorFramebufferFetch() && shadersSource == ShadersStateSource::ThisPipeline && + GraphicsPipelineHasShaders(subset)) { *inputLocationsOut = {}; inputLocationsOut->sType = VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR; @@ -630,10 +675,8 @@ void UnpackAttachmentDesc(Renderer *renderer, ConvertRenderPassLoadOpToVkLoadOp(static_cast(ops.stencilLoadOp)); desc->stencilStoreOp = ConvertRenderPassStoreOpToVkStoreOp(static_cast(ops.stencilStoreOp)); - desc->initialLayout = - ConvertImageLayoutToVkImageLayout(renderer, static_cast(ops.initialLayout)); - desc->finalLayout = - ConvertImageLayoutToVkImageLayout(renderer, static_cast(ops.finalLayout)); + desc->initialLayout = renderer->getVkImageLayout(static_cast(ops.initialLayout)); + desc->finalLayout = renderer->getVkImageLayout(static_cast(ops.finalLayout)); } struct AttachmentInfo @@ -649,7 +692,8 @@ void UnpackColorResolveAttachmentDesc(Renderer *renderer, VkAttachmentDescription2 *desc, angle::FormatID formatID, const AttachmentInfo &info, - ImageLayout finalLayout) + VkImageLayout initialLayout, + VkImageLayout finalLayout) { *desc = {}; desc->sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; @@ -673,8 +717,8 @@ void UnpackColorResolveAttachmentDesc(Renderer *renderer, info.isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - desc->initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - desc->finalLayout = ConvertImageLayoutToVkImageLayout(renderer, finalLayout); + desc->initialLayout = initialLayout; + desc->finalLayout = finalLayout; } void UnpackDepthStencilResolveAttachmentDesc(vk::ErrorContext *context, @@ -734,11 +778,11 @@ void UnpackDepthStencilResolveAttachmentDesc(vk::ErrorContext *context, desc->stencilStoreOp = stencilInfo.isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; } - desc->initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - desc->finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + desc->initialLayout = desc->finalLayout = + renderer->getVkImageLayout(vk::ImageAccess::DepthWriteStencilWrite); } -void UnpackFragmentShadingRateAttachmentDesc(VkAttachmentDescription2 *desc) +void UnpackFragmentShadingRateAttachmentDesc(Renderer *renderer, VkAttachmentDescription2 *desc) { *desc = {}; desc->sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; @@ -749,8 +793,8 @@ void UnpackFragmentShadingRateAttachmentDesc(VkAttachmentDescription2 *desc) desc->storeOp = VK_ATTACHMENT_STORE_OP_NONE; desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - desc->initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - desc->finalLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; + desc->initialLayout = desc->finalLayout = + renderer->getVkImageLayout(vk::ImageAccess::FragmentShadingRateAttachmentReadOnly); } void UnpackStencilState(const PackedStencilOpState &packedState, @@ -800,6 +844,7 @@ void SetPipelineShaderStageInfo(const VkStructureType type, // subpass will only contain the attachments that need to be unresolved to simplify the shader that // performs the operations. void InitializeUnresolveSubpass( + Renderer *renderer, const RenderPassDesc &desc, const gl::DrawBuffersVector &drawSubpassColorAttachmentRefs, const gl::DrawBuffersVector &drawSubpassResolveAttachmentRefs, @@ -903,6 +948,8 @@ void InitializeUnresolveSubpass( // // Again, the color attachment refs already created for the application draw subpass can be used // indexed with colorIndexGL. + const VkImageLayout readLayout = + renderer->getVkImageLayout(vk::ImageAccess::FragmentShaderReadOnly); if (desc.hasDepthStencilUnresolveAttachment()) { ASSERT(desc.hasDepthStencilAttachment()); @@ -914,7 +961,7 @@ void InitializeUnresolveSubpass( unresolveDepthStencilInputAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; unresolveDepthStencilInputAttachmentRef.attachment = depthStencilResolveAttachmentRef.attachment; - unresolveDepthStencilInputAttachmentRef.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + unresolveDepthStencilInputAttachmentRef.layout = readLayout; unresolveDepthStencilInputAttachmentRef.aspectMask = 0; if (desc.hasDepthUnresolveAttachment()) @@ -957,7 +1004,7 @@ void InitializeUnresolveSubpass( // Note the input attachment layout should be shader read-only. The subpass dependency // will take care of transitioning the layout of the resolve attachment to color attachment // automatically. - unresolveInputAttachmentRefs->back().layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + unresolveInputAttachmentRefs->back().layout = readLayout; } ASSERT(!unresolveColorAttachmentRefs->empty() || @@ -1433,6 +1480,7 @@ void UpdateSubpassColorPerfCounters(const VkRenderPassCreateInfo2 &createInfo, void UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo2 &createInfo, size_t renderPassIndex, + ImageAccess depthStencilImageAccess, RenderPassPerfCounters *countersOut) { ASSERT(renderPassIndex != VK_ATTACHMENT_UNUSED); @@ -1455,7 +1503,7 @@ void UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo2 &cre // Depth/stencil read-only mode. countersOut->readOnlyDepthStencil += - ds.finalLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ? 1 : 0; + IsReadOnlyDepthStencilAccess(depthStencilImageAccess) ? 1 : 0; } void UpdateRenderPassDepthStencilResolvePerfCounters( @@ -1502,6 +1550,7 @@ void UpdateRenderPassPerfCounters( const RenderPassDesc &desc, const VkRenderPassCreateInfo2 &createInfo, const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve, + ImageAccess depthStencilImageAccess, RenderPassPerfCounters *countersOut) { // Accumulate depth/stencil attachment indices in all subpasses to avoid double-counting @@ -1535,7 +1584,7 @@ void UpdateRenderPassPerfCounters( for (size_t attachmentRenderPassIndex : depthStencilAttachmentIndices) { UpdateRenderPassDepthStencilPerfCounters(createInfo, attachmentRenderPassIndex, - countersOut); + depthStencilImageAccess, countersOut); } UpdateRenderPassDepthStencilResolvePerfCounters(createInfo, depthStencilResolve, countersOut); @@ -1595,11 +1644,6 @@ void InitializeSpecializationInfo( (*specializationEntriesOut)[id].constantID = static_cast(id); switch (id) { - case sh::vk::SpecializationConstantId::SurfaceRotation: - (*specializationEntriesOut)[id].offset = - offsetof(SpecializationConstants, surfaceRotation); - (*specializationEntriesOut)[id].size = sizeof(specConsts.surfaceRotation); - break; case sh::vk::SpecializationConstantId::Dither: (*specializationEntriesOut)[id].offset = offsetof(vk::SpecializationConstants, dither); @@ -1717,7 +1761,6 @@ enum class PipelineState PolygonMode, CullMode, FrontFace, - SurfaceRotation, ViewportNegativeOneToOne, SampleShadingEnable, RasterizationSamples, @@ -1781,7 +1824,6 @@ using PipelineStateBitSet = angle::BitSetArray( uint32_t *vaDivisors = &(*valuesOut)[PipelineState::VertexAttribDivisor]; uint32_t *vaOffsets = &(*valuesOut)[PipelineState::VertexAttribOffset]; uint32_t *vaStrides = &(*valuesOut)[PipelineState::VertexAttribStride]; - uint32_t *vaCompressed = &(*valuesOut)[PipelineState::VertexAttribCompressed]; uint32_t *vaShaderComponentType = &(*valuesOut)[PipelineState::VertexAttribShaderComponentType]; for (uint32_t attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; ++attribIndex) @@ -1790,7 +1832,6 @@ using PipelineStateBitSet = angle::BitSetArray( vaDivisors[attribIndex] = vertex.attribs[attribIndex].divisor; vaOffsets[attribIndex] = vertex.attribs[attribIndex].offset; vaStrides[attribIndex] = vertex.strides[attribIndex]; - vaCompressed[attribIndex] = vertex.attribs[attribIndex].compressed; gl::ComponentType componentType = gl::GetComponentTypeMask( gl::ComponentTypeMask(vertex.shaderAttribComponentType), attribIndex); @@ -1824,7 +1865,6 @@ using PipelineStateBitSet = angle::BitSetArray( (*valuesOut)[PipelineState::DepthWrite] = shaders.bits.depthWrite; (*valuesOut)[PipelineState::StencilTest] = shaders.bits.stencilTest; (*valuesOut)[PipelineState::DepthCompareOp] = shaders.bits.depthCompareOp; - (*valuesOut)[PipelineState::SurfaceRotation] = shaders.bits.surfaceRotation; (*valuesOut)[PipelineState::EmulatedDitherControl] = shaders.emulatedDitherControl; (*valuesOut)[PipelineState::StencilOpFailFront] = shaders.front.fail; (*valuesOut)[PipelineState::StencilOpPassFront] = shaders.front.pass; @@ -2034,7 +2074,6 @@ PipelineState GetPipelineState(size_t stateIndex, bool *isRangedOut, size_t *sub {PipelineState::PolygonMode, "polygon_mode"}, {PipelineState::CullMode, "cull_mode"}, {PipelineState::FrontFace, "front_face"}, - {PipelineState::SurfaceRotation, "rotated_surface"}, {PipelineState::ViewportNegativeOneToOne, "viewport_depth_[-1,1]"}, {PipelineState::SampleShadingEnable, "sample_shading"}, {PipelineState::RasterizationSamples, "rasterization_samples"}, @@ -2092,7 +2131,6 @@ PipelineState GetPipelineState(size_t stateIndex, bool *isRangedOut, size_t *sub case PipelineState::RenderPassUnresolveDepth: case PipelineState::RenderPassUnresolveStencil: case PipelineState::PrimitiveRestartEnable: - case PipelineState::SurfaceRotation: case PipelineState::ViewportNegativeOneToOne: case PipelineState::SampleShadingEnable: case PipelineState::AlphaToCoverageEnable: @@ -2483,7 +2521,6 @@ PipelineState GetPipelineState(size_t stateIndex, bool *isRangedOut, size_t *sub {PipelineState::DepthWrite, 0}, {PipelineState::StencilTest, 0}, {PipelineState::DepthCompareOp, hasShaders ? VK_COMPARE_OP_LESS : 0}, - {PipelineState::SurfaceRotation, 0}, {PipelineState::EmulatedDitherControl, 0}, {PipelineState::StencilOpFailFront, hasShaders ? VK_STENCIL_OP_KEEP : 0}, {PipelineState::StencilOpPassFront, hasShaders ? VK_STENCIL_OP_KEEP : 0}, @@ -2589,18 +2626,10 @@ void DumpPipelineCacheGraph( const char *subsetTag = ""; switch (kSubset) { - case GraphicsPipelineSubset::VertexInput: - subsetDescription = "(vertex input)\\n"; - subsetTag = "VI_"; - break; case GraphicsPipelineSubset::Shaders: subsetDescription = "(shaders)\\n"; subsetTag = "S_"; break; - case GraphicsPipelineSubset::FragmentOutput: - subsetDescription = "(fragment output)\\n"; - subsetTag = "FO_"; - break; default: break; } @@ -2701,68 +2730,6 @@ void MakeInvalidCachedObject(SharedDescriptorSetCacheKey *cacheKeyOut) *cacheKeyOut = SharedDescriptorSetCacheKey::MakeShared(VK_NULL_HANDLE); } -angle::Result InitializePipelineFromLibraries(ErrorContext *context, - PipelineCacheAccess *pipelineCache, - const vk::PipelineLayout &pipelineLayout, - const vk::PipelineHelper &vertexInputPipeline, - const vk::PipelineHelper &shadersPipeline, - const vk::PipelineHelper &fragmentOutputPipeline, - const vk::GraphicsPipelineDesc &desc, - Pipeline *pipelineOut, - CacheLookUpFeedback *feedbackOut) -{ - // Nothing in the create info, everything comes from the libraries. - VkGraphicsPipelineCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - createInfo.layout = pipelineLayout.getHandle(); - - if (context->getFeatures().preferDynamicRendering.enabled && desc.getRenderPassFoveation()) - { - createInfo.flags |= VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; - } - - const std::array pipelines = { - vertexInputPipeline.getPipeline().getHandle(), - shadersPipeline.getPipeline().getHandle(), - fragmentOutputPipeline.getPipeline().getHandle(), - }; - - // Specify the three subsets as input libraries. - VkPipelineLibraryCreateInfoKHR libraryInfo = {}; - libraryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; - libraryInfo.libraryCount = 3; - libraryInfo.pLibraries = pipelines.data(); - - AddToPNextChain(&createInfo, &libraryInfo); - - // If supported, get feedback. - VkPipelineCreationFeedback feedback = {}; - VkPipelineCreationFeedbackCreateInfo feedbackInfo = {}; - feedbackInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO; - - const bool supportsFeedback = context->getFeatures().supportsPipelineCreationFeedback.enabled; - if (supportsFeedback) - { - feedbackInfo.pPipelineCreationFeedback = &feedback; - AddToPNextChain(&createInfo, &feedbackInfo); - } - - // Create the pipeline - ANGLE_VK_TRY(context, pipelineCache->createGraphicsPipeline(context, createInfo, pipelineOut)); - - if (supportsFeedback) - { - const bool cacheHit = - (feedback.flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT) != - 0; - - *feedbackOut = cacheHit ? CacheLookUpFeedback::Hit : CacheLookUpFeedback::Miss; - ApplyPipelineCreationFeedback(context, feedback); - } - - return angle::Result::Continue; -} - bool ShouldDumpPipelineCacheGraph(ErrorContext *context) { return kDumpPipelineCacheGraph && context->getRenderer()->isPipelineCacheGraphDumpEnabled(); @@ -2793,16 +2760,9 @@ FramebufferFetchMode GetProgramFramebufferFetchMode(const gl::ProgramExecutable GraphicsPipelineTransitionBits GetGraphicsPipelineTransitionBitsMask(GraphicsPipelineSubset subset) { - switch (subset) + if (subset == GraphicsPipelineSubset::Shaders) { - case GraphicsPipelineSubset::VertexInput: - return kPipelineVertexInputTransitionBitsMask; - case GraphicsPipelineSubset::Shaders: - return kPipelineShadersTransitionBitsMask; - case GraphicsPipelineSubset::FragmentOutput: - return kPipelineFragmentOutputTransitionBitsMask; - default: - break; + return kPipelineShadersTransitionBitsMask; } ASSERT(subset == GraphicsPipelineSubset::Complete); @@ -2930,9 +2890,13 @@ void RenderPassDesc::packStencilUnresolveAttachment() mUnresolveStencil = true; } -void RenderPassDesc::removeDepthStencilUnresolveAttachment() +void RenderPassDesc::removeDepthUnresolveAttachment() +{ + mUnresolveDepth = false; +} + +void RenderPassDesc::removeStencilUnresolveAttachment() { - mUnresolveDepth = false; mUnresolveStencil = false; } @@ -2966,7 +2930,7 @@ void RenderPassDesc::setWriteControlMode(gl::SrgbWriteControlMode mode) size_t RenderPassDesc::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const @@ -3044,7 +3008,8 @@ void RenderPassDesc::beginRendering( { DynamicRenderingInfo info; DeriveRenderingInfo(context->getRenderer(), *this, DynamicRenderingInfoSubset::Full, renderArea, - subpassContents, attachmentViews, ops, clearValues, layerCount, &info); + subpassContents, attachmentViews, ops, clearValues, layerCount, &info, + nullptr); primary->beginRendering(info.renderingInfo); @@ -3074,7 +3039,7 @@ void RenderPassDesc::populateRenderingInheritanceInfo( DynamicRenderingInfo renderingInfo; DeriveRenderingInfo(renderer, *this, DynamicRenderingInfoSubset::Pipeline, {}, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, {}, {}, {}, 0, - &renderingInfo); + &renderingInfo, nullptr); *colorFormatStorageOut = renderingInfo.colorAttachmentFormats; *infoOut = {}; @@ -3101,9 +3066,10 @@ void RenderPassDesc::updatePerfCounters( angle::VulkanPerfCounters *countersOut) { DynamicRenderingInfo info; + bool isReadOnlyDepthStencil = false; DeriveRenderingInfo(context->getRenderer(), *this, DynamicRenderingInfoSubset::Full, {}, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, attachmentViews, ops, {}, 0, - &info); + &info, &isReadOnlyDepthStencil); // Note: resolve attachments don't have ops with dynamic rendering and they are implicit. // Counter-tests should take the |preferDynamicRendering| flag into account. For color, it's @@ -3174,21 +3140,7 @@ void RenderPassDesc::updatePerfCounters( } } - if (info.renderingInfo.pDepthAttachment != nullptr || - info.renderingInfo.pStencilAttachment != nullptr) - { - ASSERT(info.renderingInfo.pDepthAttachment == nullptr || - info.renderingInfo.pStencilAttachment == nullptr || - info.renderingInfo.pDepthAttachment->imageLayout == - info.renderingInfo.pStencilAttachment->imageLayout); - - const VkImageLayout layout = info.renderingInfo.pDepthAttachment != nullptr - ? info.renderingInfo.pDepthAttachment->imageLayout - : info.renderingInfo.pStencilAttachment->imageLayout; - - countersOut->readOnlyDepthStencilRenderPasses += - layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ? 1 : 0; - } + countersOut->readOnlyDepthStencilRenderPasses += isReadOnlyDepthStencil ? 1 : 0; } bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs) @@ -3258,20 +3210,19 @@ size_t ComputePipelineDesc::hash() const size_t paddedPipelineOptions = mPipelineOptions.permutationIndex; size_t pipelineOptionsHash = - angle::ComputeGenericHash(&paddedPipelineOptions, sizeof(paddedPipelineOptions)); + angle::ComputeGenericHash(angle::byte_span_from_ref(paddedPipelineOptions)); size_t specializationConstantIDsHash = 0; if (!mConstantIds.empty()) { specializationConstantIDsHash = - angle::ComputeGenericHash(mConstantIds.data(), mConstantIds.size() * sizeof(uint32_t)); + angle::ComputeGenericHash(angle::as_byte_span(mConstantIds)); } size_t specializationConstantsHash = 0; if (!mConstants.empty()) { - specializationConstantsHash = - angle::ComputeGenericHash(mConstants.data(), mConstants.size() * sizeof(uint32_t)); + specializationConstantsHash = angle::ComputeGenericHash(angle::as_byte_span(mConstants)); } return pipelineOptionsHash ^ specializationConstantIDsHash ^ specializationConstantsHash; @@ -3345,30 +3296,26 @@ const void *GraphicsPipelineDesc::getPipelineSubsetMemory(GraphicsPipelineSubset sizeof(PackedVertexInputAttributes) == sizeof(GraphicsPipelineDesc)); + // Vertex input dynamic state and vertex input binding stride should not be enabled at the same + // time. It is preferable to use vertex input over binding stride. + ASSERT(!mVertexInput.inputAssembly.bits.useVertexInputBindingStrideDynamicState || + !mVertexInput.inputAssembly.bits.useVertexInputDynamicState); size_t vertexInputReduceSize = 0; - if (mVertexInput.inputAssembly.bits.useVertexInputBindingStrideDynamicState) + if (mVertexInput.inputAssembly.bits.useVertexInputDynamicState) { - vertexInputReduceSize = sizeof(PackedVertexInputAttributes::strides); + vertexInputReduceSize = sizeof(PackedVertexInputAttributes); } - else if (mVertexInput.inputAssembly.bits.useVertexInputDynamicState) + else if (mVertexInput.inputAssembly.bits.useVertexInputBindingStrideDynamicState) { - vertexInputReduceSize = sizeof(PackedVertexInputAttributes); + vertexInputReduceSize = sizeof(PackedVertexInputAttributes::strides); } switch (subset) { - case GraphicsPipelineSubset::VertexInput: - *sizeOut = kPipelineVertexInputDescSize - vertexInputReduceSize; - return &mVertexInput; - case GraphicsPipelineSubset::Shaders: *sizeOut = kPipelineShadersDescSize; return &mShaders; - case GraphicsPipelineSubset::FragmentOutput: - *sizeOut = kPipelineFragmentOutputDescSize; - return &mSharedNonVertexInput; - case GraphicsPipelineSubset::Complete: default: *sizeOut = sizeof(*this) - vertexInputReduceSize; @@ -3381,7 +3328,7 @@ size_t GraphicsPipelineDesc::hash(GraphicsPipelineSubset subset) const size_t keySize = 0; const void *key = getPipelineSubsetMemory(subset, &keySize); - return angle::ComputeGenericHash(key, keySize); + return angle::ComputeGenericHash(angle::Span(static_cast(key), keySize)); } bool GraphicsPipelineDesc::keyEqual(const GraphicsPipelineDesc &other, @@ -3420,7 +3367,6 @@ void GraphicsPipelineDesc::initDefaults(const ErrorContext *context, { SetBitField(packedAttrib.divisor, 0); SetBitField(packedAttrib.format, defaultFormat); - SetBitField(packedAttrib.compressed, 0); SetBitField(packedAttrib.offset, 0); } mVertexInput.vertex.shaderAttribComponentType = 0; @@ -3451,8 +3397,8 @@ void GraphicsPipelineDesc::initDefaults(const ErrorContext *context, mShaders.shaders.bits.depthWrite = 0; mShaders.shaders.bits.stencilTest = 0; mShaders.shaders.bits.nonZeroStencilWriteMaskWorkaround = 0; + mShaders.shaders.bits.padding = 0; SetBitField(mShaders.shaders.bits.depthCompareOp, VK_COMPARE_OP_LESS); - mShaders.shaders.bits.surfaceRotation = 0; mShaders.shaders.emulatedDitherControl = 0; mShaders.shaders.padding = 0; SetBitField(mShaders.shaders.front.fail, VK_STENCIL_OP_KEEP); @@ -3520,8 +3466,7 @@ VkResult GraphicsPipelineDesc::initializePipeline(ErrorContext *context, GraphicsPipelineSubset subset, const RenderPass &compatibleRenderPass, const PipelineLayout &pipelineLayout, - const ShaderModuleMap &shaders, - const SpecializationConstants &specConsts, + const GraphicsPipelineShadersInfo &shaders, Pipeline *pipelineOut, CacheLookUpFeedback *feedbackOut) const { @@ -3549,21 +3494,44 @@ VkResult GraphicsPipelineDesc::initializePipeline(ErrorContext *context, { initializePipelineVertexInputState(context, &vertexInputState, &dynamicStateList); - createInfo.pVertexInputState = &vertexInputState.vertexInputState; + if (!context->getFeatures().supportsVertexInputDynamicState.enabled) + { + // Note: If vertex input state is dynamic, no need to set pVertexInputState; + // vertexInputState is not initialized either. + createInfo.pVertexInputState = &vertexInputState.vertexInputState; + } createInfo.pInputAssemblyState = &vertexInputState.inputAssemblyState; } + VkPipeline shadersPipeline = VK_NULL_HANDLE; + VkPipelineLibraryCreateInfoKHR shadersLibraryInfo = {}; + shadersLibraryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; + if (hasShaders) { - initializePipelineShadersState(context, shaders, specConsts, &shadersState, - &dynamicStateList); + // If the shaders state comes from a library, use the library instead. + if (shaders.usePipelineLibrary()) + { + shadersPipeline = shaders.mPipelineLibrary->getPipeline().getHandle(); + + shadersLibraryInfo.libraryCount = 1; + shadersLibraryInfo.pLibraries = &shadersPipeline; + + AddToPNextChain(&createInfo, &shadersLibraryInfo); + } + else + { + initializePipelineShadersState(context, *shaders.mShaders, *shaders.mSpecConsts, + &shadersState, &dynamicStateList); + + createInfo.stageCount = static_cast(shadersState.shaderStages.size()); + createInfo.pStages = shadersState.shaderStages.data(); + createInfo.pTessellationState = &shadersState.tessellationState; + createInfo.pViewportState = &shadersState.viewportState; + createInfo.pRasterizationState = &shadersState.rasterState; + createInfo.pDepthStencilState = &shadersState.depthStencilState; + } - createInfo.stageCount = static_cast(shadersState.shaderStages.size()); - createInfo.pStages = shadersState.shaderStages.data(); - createInfo.pTessellationState = &shadersState.tessellationState; - createInfo.pViewportState = &shadersState.viewportState; - createInfo.pRasterizationState = &shadersState.rasterState; - createInfo.pDepthStencilState = &shadersState.depthStencilState; createInfo.layout = pipelineLayout.getHandle(); } @@ -3592,29 +3560,22 @@ VkResult GraphicsPipelineDesc::initializePipeline(ErrorContext *context, VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo = {}; libraryInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; - if (subset != GraphicsPipelineSubset::Complete) + if (subset == GraphicsPipelineSubset::Shaders) { - switch (subset) - { - case GraphicsPipelineSubset::VertexInput: - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT; - break; - case GraphicsPipelineSubset::Shaders: - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT | - VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT; - break; - case GraphicsPipelineSubset::FragmentOutput: - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT; - break; - default: - UNREACHABLE(); - break; - } + libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT | + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT; createInfo.flags |= VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; AddToPNextChain(&createInfo, &libraryInfo); } + else if (hasShaders && shaders.usePipelineLibrary()) + { + libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT | + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT; + + AddToPNextChain(&createInfo, &libraryInfo); + } VkPipelineRobustnessCreateInfoEXT robustness = {}; robustness.sType = VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT; @@ -3678,8 +3639,11 @@ VkResult GraphicsPipelineDesc::initializePipeline(ErrorContext *context, { DeriveRenderingInfo(context->getRenderer(), getRenderPassDesc(), DynamicRenderingInfoSubset::Pipeline, {}, VK_SUBPASS_CONTENTS_INLINE, - {}, {}, {}, 0, &renderingInfo); + {}, {}, {}, 0, &renderingInfo, nullptr); AttachPipelineRenderingInfo(context, getRenderPassDesc(), renderingInfo, subset, + shaders.usePipelineLibrary() + ? ShadersStateSource::PipelineLibrary + : ShadersStateSource::ThisPipeline, &pipelineRenderingInfo, &attachmentLocations, &inputLocations, &createFlags2, &createInfo); } @@ -3699,7 +3663,7 @@ VkResult GraphicsPipelineDesc::initializePipeline(ErrorContext *context, return result; } -angle::FormatID patchVertexAttribComponentType(angle::FormatID format, +angle::FormatID PatchVertexAttribComponentType(angle::FormatID format, gl::ComponentType vsInputType) { const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(format); @@ -3762,7 +3726,6 @@ angle::FormatID patchVertexAttribComponentType(angle::FormatID format, VkFormat GraphicsPipelineDesc::getPipelineVertexInputStateFormat( ErrorContext *context, angle::FormatID formatID, - bool compressed, const gl::ComponentType programAttribType, uint32_t attribIndex) { @@ -3770,7 +3733,7 @@ VkFormat GraphicsPipelineDesc::getPipelineVertexInputStateFormat( // Get the corresponding VkFormat for the attrib's format. const Format &format = renderer->getFormat(formatID); const angle::Format &intendedFormat = format.getIntendedFormat(); - VkFormat vkFormat = format.getActualBufferVkFormat(renderer, compressed); + VkFormat vkFormat = format.getActualBufferVkFormat(renderer); const gl::ComponentType attribType = GetVertexAttributeComponentType( intendedFormat.isPureInt(), intendedFormat.vertexAttribType); @@ -3781,9 +3744,8 @@ VkFormat GraphicsPipelineDesc::getPipelineVertexInputStateFormat( if (attribType == gl::ComponentType::Float || programAttribType == gl::ComponentType::Float) { angle::FormatID patchFormatID = - patchVertexAttribComponentType(formatID, programAttribType); - vkFormat = - renderer->getFormat(patchFormatID).getActualBufferVkFormat(renderer, compressed); + PatchVertexAttribComponentType(formatID, programAttribType); + vkFormat = renderer->getFormat(patchFormatID).getActualBufferVkFormat(renderer); } else { @@ -3797,7 +3759,7 @@ VkFormat GraphicsPipelineDesc::getPipelineVertexInputStateFormat( ASSERT(intendedFormat.blueBits == convertedFormat.getIntendedFormat().blueBits); ASSERT(intendedFormat.alphaBits == convertedFormat.getIntendedFormat().alphaBits); - vkFormat = convertedFormat.getActualBufferVkFormat(renderer, compressed); + vkFormat = convertedFormat.getActualBufferVkFormat(renderer); } const Format &origFormat = renderer->getFormat(GetFormatIDFromVkFormat(origVkFormat)); const Format &patchFormat = renderer->getFormat(GetFormatIDFromVkFormat(vkFormat)); @@ -3815,66 +3777,75 @@ void GraphicsPipelineDesc::initializePipelineVertexInputState( GraphicsPipelineDynamicStateList *dynamicStateListOut) const { // TODO(jmadill): Possibly use different path for ES 3.1 split bindings/attribs. - uint32_t vertexAttribCount = 0; - - stateOut->divisorState.sType = - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; - stateOut->divisorState.pVertexBindingDivisors = stateOut->divisorDesc.data(); - for (size_t attribIndexSizeT : - gl::AttributesMask(mVertexInput.inputAssembly.bits.programActiveAttributeLocations)) + const gl::AttributesMask &activeAttributeLocationsMask = + gl::AttributesMask(mVertexInput.inputAssembly.bits.programActiveAttributeLocations); + if (!context->getFeatures().supportsVertexInputDynamicState.enabled) { - const uint32_t attribIndex = static_cast(attribIndexSizeT); + stateOut->divisorState.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; + stateOut->divisorState.pVertexBindingDivisors = stateOut->divisorDesc.data(); - VkVertexInputBindingDescription &bindingDesc = stateOut->bindingDescs[vertexAttribCount]; - VkVertexInputAttributeDescription &attribDesc = stateOut->attributeDescs[vertexAttribCount]; - const PackedAttribDesc &packedAttrib = mVertexInput.vertex.attribs[attribIndex]; - - bindingDesc.binding = attribIndex; - bindingDesc.stride = static_cast(mVertexInput.vertex.strides[attribIndex]); - if (packedAttrib.divisor != 0) - { - bindingDesc.inputRate = static_cast(VK_VERTEX_INPUT_RATE_INSTANCE); - stateOut->divisorDesc[stateOut->divisorState.vertexBindingDivisorCount].binding = - bindingDesc.binding; - stateOut->divisorDesc[stateOut->divisorState.vertexBindingDivisorCount].divisor = - packedAttrib.divisor; - ++stateOut->divisorState.vertexBindingDivisorCount; - } - else + uint32_t vertexAttribCount = 0; + for (size_t attribIndexSizeT : activeAttributeLocationsMask) { - bindingDesc.inputRate = static_cast(VK_VERTEX_INPUT_RATE_VERTEX); - } + const uint32_t attribIndex = static_cast(attribIndexSizeT); + + VkVertexInputBindingDescription &bindingDesc = + stateOut->bindingDescs[vertexAttribCount]; + VkVertexInputAttributeDescription &attribDesc = + stateOut->attributeDescs[vertexAttribCount]; + const PackedAttribDesc &packedAttrib = mVertexInput.vertex.attribs[attribIndex]; - // If using dynamic state for stride, the value for stride is unconditionally 0 here. - // |ContextVk::handleDirtyGraphicsVertexBuffers| implements the same fix when setting stride - // dynamically. - ASSERT(!context->getFeatures().useVertexInputBindingStrideDynamicState.enabled || - bindingDesc.stride == 0); + bindingDesc.binding = attribIndex; + bindingDesc.stride = static_cast(mVertexInput.vertex.strides[attribIndex]); + if (packedAttrib.divisor != 0) + { + bindingDesc.inputRate = + static_cast(VK_VERTEX_INPUT_RATE_INSTANCE); + stateOut->divisorDesc[stateOut->divisorState.vertexBindingDivisorCount].binding = + bindingDesc.binding; + stateOut->divisorDesc[stateOut->divisorState.vertexBindingDivisorCount].divisor = + packedAttrib.divisor; + ++stateOut->divisorState.vertexBindingDivisorCount; + } + else + { + bindingDesc.inputRate = static_cast(VK_VERTEX_INPUT_RATE_VERTEX); + } - // Get the corresponding VkFormat for the attrib's format. - angle::FormatID formatID = static_cast(packedAttrib.format); - const gl::ComponentType programAttribType = gl::GetComponentTypeMask( - gl::ComponentTypeMask(mVertexInput.vertex.shaderAttribComponentType), attribIndex); + // If using dynamic state for stride, the value for stride is unconditionally 0 here. + // |ContextVk::handleDirtyGraphicsVertexBuffers| implements the same fix when setting + // stride dynamically. + ASSERT(!context->getFeatures().useVertexInputBindingStrideDynamicState.enabled || + bindingDesc.stride == 0); - attribDesc.binding = attribIndex; - attribDesc.format = getPipelineVertexInputStateFormat( - context, formatID, packedAttrib.compressed, programAttribType, attribIndex); - attribDesc.location = static_cast(attribIndex); - attribDesc.offset = packedAttrib.offset; + // Get the corresponding VkFormat for the attrib's format. + angle::FormatID formatID = static_cast(packedAttrib.format); + const gl::ComponentType programAttribType = gl::GetComponentTypeMask( + gl::ComponentTypeMask(mVertexInput.vertex.shaderAttribComponentType), attribIndex); - vertexAttribCount++; - } + attribDesc.binding = attribIndex; + attribDesc.format = getPipelineVertexInputStateFormat(context, formatID, + programAttribType, attribIndex); + attribDesc.location = static_cast(attribIndex); + attribDesc.offset = packedAttrib.offset; - // The binding descriptions are filled in at draw time. - stateOut->vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - stateOut->vertexInputState.flags = 0; - stateOut->vertexInputState.vertexBindingDescriptionCount = vertexAttribCount; - stateOut->vertexInputState.pVertexBindingDescriptions = stateOut->bindingDescs.data(); - stateOut->vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount; - stateOut->vertexInputState.pVertexAttributeDescriptions = stateOut->attributeDescs.data(); - if (stateOut->divisorState.vertexBindingDivisorCount) - { - stateOut->vertexInputState.pNext = &stateOut->divisorState; + vertexAttribCount++; + } + ASSERT(vertexAttribCount == static_cast(activeAttributeLocationsMask.count())); + + // The binding descriptions are filled in at draw time. + stateOut->vertexInputState.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + stateOut->vertexInputState.flags = 0; + stateOut->vertexInputState.vertexBindingDescriptionCount = vertexAttribCount; + stateOut->vertexInputState.pVertexBindingDescriptions = stateOut->bindingDescs.data(); + stateOut->vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount; + stateOut->vertexInputState.pVertexAttributeDescriptions = stateOut->attributeDescs.data(); + if (stateOut->divisorState.vertexBindingDivisorCount) + { + stateOut->vertexInputState.pNext = &stateOut->divisorState; + } } const PackedInputAssemblyState &inputAssembly = mVertexInput.inputAssembly; @@ -3890,10 +3861,14 @@ void GraphicsPipelineDesc::initializePipelineVertexInputState( // Dynamic state if (context->getFeatures().useVertexInputBindingStrideDynamicState.enabled && - vertexAttribCount > 0) + activeAttributeLocationsMask.any()) { dynamicStateListOut->push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE); } + if (context->getFeatures().usePrimitiveTopologyDynamicState.enabled) + { + dynamicStateListOut->push_back(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT); + } if (context->getFeatures().usePrimitiveRestartEnableDynamicState.enabled) { dynamicStateListOut->push_back(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE); @@ -4281,7 +4256,6 @@ void GraphicsPipelineDesc::updateVertexInput(ContextVk *contextVk, GLuint stride, GLuint divisor, angle::FormatID format, - bool compressed, GLuint relativeOffset) { PackedAttribDesc &packedAttrib = mVertexInput.vertex.attribs[attribIndex]; @@ -4294,7 +4268,6 @@ void GraphicsPipelineDesc::updateVertexInput(ContextVk *contextVk, } SetBitField(packedAttrib.format, format); - SetBitField(packedAttrib.compressed, compressed); SetBitField(packedAttrib.offset, relativeOffset); constexpr size_t kAttribBits = kPackedAttribDescSize * kBitsPerByte; @@ -4718,13 +4691,6 @@ void GraphicsPipelineDesc::updateDepthClampEnabled(GraphicsPipelineTransitionBit transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits)); } -void GraphicsPipelineDesc::updateSurfaceRotation(GraphicsPipelineTransitionBits *transition, - bool isRotatedAspectRatio) -{ - SetBitField(mShaders.shaders.bits.surfaceRotation, isRotatedAspectRatio); - transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits)); -} - void GraphicsPipelineDesc::updateDepthWriteEnabled(GraphicsPipelineTransitionBits *transition, const gl::DepthStencilState &depthStencilState, const gl::Framebuffer *drawFramebuffer) @@ -4915,8 +4881,8 @@ AttachmentOpsArray &AttachmentOpsArray::operator=(const AttachmentOpsArray &othe } void AttachmentOpsArray::initWithLoadStore(PackedAttachmentIndex index, - ImageLayout initialLayout, - ImageLayout finalLayout) + ImageAccess initialLayout, + ImageAccess finalLayout) { setLayouts(index, initialLayout, finalLayout); setOps(index, RenderPassLoadOp::Load, RenderPassStoreOp::Store); @@ -4924,8 +4890,8 @@ void AttachmentOpsArray::initWithLoadStore(PackedAttachmentIndex index, } void AttachmentOpsArray::setLayouts(PackedAttachmentIndex index, - ImageLayout initialLayout, - ImageLayout finalLayout) + ImageAccess initialLayout, + ImageAccess finalLayout) { PackedAttachmentOpsDesc &ops = mOps[index.get()]; SetBitField(ops.initialLayout, initialLayout); @@ -4967,7 +4933,7 @@ void AttachmentOpsArray::setClearStencilOp(PackedAttachmentIndex index) size_t AttachmentOpsArray::hash() const { - return angle::ComputeGenericHash(mOps); + return angle::ComputeGenericHash(angle::byte_span_from_ref(mOps)); } bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs) @@ -4989,23 +4955,17 @@ DescriptorSetLayoutDesc &DescriptorSetLayoutDesc::operator=(const DescriptorSetL size_t DescriptorSetLayoutDesc::hash() const { - size_t validDescriptorSetLayoutBindingsCount = mDescriptorSetLayoutBindings.size(); - size_t validImmutableSamplersCount = mImmutableSamplers.size(); - - ASSERT(validDescriptorSetLayoutBindingsCount != 0 || validImmutableSamplersCount == 0); + ASSERT(!mDescriptorSetLayoutBindings.empty() || mImmutableSamplers.empty()); size_t genericHash = 0; - if (validDescriptorSetLayoutBindingsCount > 0) + if (!mDescriptorSetLayoutBindings.empty()) { - genericHash = angle::ComputeGenericHash( - mDescriptorSetLayoutBindings.data(), - validDescriptorSetLayoutBindingsCount * sizeof(PackedDescriptorSetBinding)); + genericHash = angle::ComputeGenericHash(angle::as_byte_span(mDescriptorSetLayoutBindings)); } - if (validImmutableSamplersCount > 0) + if (!mImmutableSamplers.empty()) { - genericHash ^= angle::ComputeGenericHash(mImmutableSamplers.data(), - validImmutableSamplersCount * sizeof(VkSampler)); + genericHash ^= angle::ComputeGenericHash(angle::as_byte_span(mImmutableSamplers)); } return genericHash; @@ -5104,7 +5064,7 @@ PipelineLayoutDesc &PipelineLayoutDesc::operator=(const PipelineLayoutDesc &rhs) size_t PipelineLayoutDesc::hash() const { - size_t genericHash = angle::ComputeGenericHash(mPushConstantRange); + size_t genericHash = angle::ComputeGenericHash(angle::byte_span_from_ref(mPushConstantRange)); for (const DescriptorSetLayoutDesc &descriptorSetLayoutDesc : mDescriptorSetLayouts) { genericHash ^= descriptorSetLayoutDesc.hash(); @@ -5165,8 +5125,8 @@ void CreateMonolithicPipelineTask::operator()() ANGLE_TRACE_EVENT0("gpu.angle", "CreateMonolithicPipelineTask"); mResult = mDesc.initializePipeline(this, &mPipelineCache, vk::GraphicsPipelineSubset::Complete, - *compatibleRenderPass, mPipelineLayout, mShaders, - mSpecConsts, &mPipeline, &mFeedback); + *compatibleRenderPass, mPipelineLayout, + {&mShaders, &mSpecConsts}, &mPipeline, &mFeedback); if (mRenderer->getFeatures().slowDownMonolithicPipelineCreationForTesting.enabled) { @@ -5196,7 +5156,10 @@ WaitableMonolithicPipelineCreationTask::~WaitableMonolithicPipelineCreationTask( } // PipelineHelper implementation. -PipelineHelper::PipelineHelper() = default; +PipelineHelper::PipelineHelper() +{ + mTransitions.reserve(8); +} PipelineHelper::~PipelineHelper() = default; @@ -5354,9 +5317,7 @@ size_t DescriptorSetDesc::hash() const { return 0; } - - return angle::ComputeGenericHash(mDescriptorInfos.data(), - sizeof(mDescriptorInfos[0]) * mDescriptorInfos.size()); + return angle::ComputeGenericHash(angle::as_byte_span(mDescriptorInfos)); } // FramebufferDesc implementation. @@ -5419,7 +5380,7 @@ bool FramebufferDesc::hasFragmentShadingRateAttachment() const size_t FramebufferDesc::hash() const { - return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^ + return angle::ComputeGenericHash(angle::as_bytes(angle::Span(mSerials).first(mMaxIndex))) ^ mHasColorFramebufferFetch << 26 ^ mIsRenderToTexture << 25 ^ mLayerCount << 16 ^ mUnresolveAttachmentMask; } @@ -5501,6 +5462,13 @@ void FramebufferDesc::releaseCachedObject(ContextVk *contextVk) SetBitField(mIsValid, 0); } +bool FramebufferDesc::hasValidCachedObject(ContextVk *contextVk) const +{ + ASSERT(valid()); + Framebuffer framebuffer; + return contextVk->getShareGroup()->getFramebufferCache().get(contextVk, *this, framebuffer); +} + // YcbcrConversionDesc implementation YcbcrConversionDesc::YcbcrConversionDesc() { @@ -5515,7 +5483,7 @@ YcbcrConversionDesc &YcbcrConversionDesc::operator=(const YcbcrConversionDesc &r size_t YcbcrConversionDesc::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } bool YcbcrConversionDesc::operator==(const YcbcrConversionDesc &other) const @@ -5558,9 +5526,9 @@ void YcbcrConversionDesc::update(Renderer *renderer, SetBitField(mIsExternalFormat, (externalFormat) ? 1 : 0); SetBitField(mLinearFilterSupported, linearFilterSupported == YcbcrLinearFilterSupport::Supported); - mExternalOrVkFormat = - (externalFormat) ? externalFormat - : vkFormat.getActualImageVkFormat(renderer, vk::ImageAccess::SampleOnly); + mExternalOrVkFormat = (externalFormat) ? externalFormat + : vkFormat.getActualImageVkFormat( + renderer, vk::ImageFormatSupport::SampleOnly); updateChromaFilter(renderer, chromaFilter); @@ -5687,6 +5655,7 @@ void SamplerDesc::reset() mBorderColor.blue = 0.0f; mBorderColor.alpha = 0.0f; mReserved = 0; + mUsesSecondComponentForStencil = 0; } void SamplerDesc::update(Renderer *renderer, @@ -5799,6 +5768,15 @@ void SamplerDesc::update(Renderer *renderer, const vk::Format &vkFormat = renderer->getFormat(intendedFormatID); gl::ColorGeneric adjustedBorderColor = AdjustBorderColor(samplerState.getBorderColor(), vkFormat.getIntendedFormat(), stencilMode); + + // As per the spec, for custom borders for textures with a stencil component, the implementation + // is required to use either the first or the second component of the border color. Although it + // is recommended to use the first, using the second is also valid. + mUsesSecondComponentForStencil = + vkFormat.getIntendedFormat().hasDepthOrStencilBits() && stencilMode && + renderer->getFeatures().usesSecondComponentForStencilBorderColor.enabled + ? 1 + : 0; mBorderColor = adjustedBorderColor.colorF; mReserved = 0; @@ -5835,7 +5813,7 @@ angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const ASSERT((contextVk->getFeatures().supportsYUVSamplerConversion.enabled)); samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO; samplerYcbcrConversionInfo.pNext = nullptr; - ANGLE_TRY(contextVk->getRenderer()->getYuvConversionCache().getSamplerYcbcrConversion( + ANGLE_TRY(contextVk->getShareGroup()->getYuvConversionCache().getSamplerYcbcrConversion( contextVk, mYcbcrConversionDesc, &samplerYcbcrConversionInfo.conversion)); AddToPNextChain(&createInfo, &samplerYcbcrConversionInfo); @@ -5852,14 +5830,13 @@ angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const createInfo.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || createInfo.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) { - ASSERT((contextVk->getFeatures().supportsCustomBorderColor.enabled)); + ASSERT(contextVk->getFeatures().supportsCustomBorderColor.enabled); customBorderColorInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; - customBorderColorInfo.customBorderColor.float32[0] = mBorderColor.red; - customBorderColorInfo.customBorderColor.float32[1] = mBorderColor.green; - customBorderColorInfo.customBorderColor.float32[2] = mBorderColor.blue; - customBorderColorInfo.customBorderColor.float32[3] = mBorderColor.alpha; - + // Currently it is not required to set the format in customBorderColorInfo, because the + // feature supportsCustomBorderColor currently requires customBorderColorWithoutFormat to + // be enabled. + angle::ColorF customColor = mBorderColor; if (mBorderColorType == static_cast(angle::ColorGeneric::Type::Float)) { createInfo.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT; @@ -5867,8 +5844,17 @@ angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const else { createInfo.borderColor = VK_BORDER_COLOR_INT_CUSTOM_EXT; + if (mUsesSecondComponentForStencil) + { + customColor.green = customColor.red; + } } + customBorderColorInfo.customBorderColor.float32[0] = customColor.red; + customBorderColorInfo.customBorderColor.float32[1] = customColor.green; + customBorderColorInfo.customBorderColor.float32[2] = customColor.blue; + customBorderColorInfo.customBorderColor.float32[3] = customColor.alpha; + vk::AddToPNextChain(&createInfo, &customBorderColorInfo); } ANGLE_VK_TRY(contextVk, sampler->init(contextVk->getDevice(), createInfo)); @@ -5878,7 +5864,7 @@ angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const size_t SamplerDesc::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } bool SamplerDesc::operator==(const SamplerDesc &other) const @@ -5992,6 +5978,13 @@ void WriteDescriptorDescs::updateShaderBuffers( const std::vector &blocks, VkDescriptorType descriptorType) { + std::vector *blockIndexToDescriptorDescIndexMap = + IsUniformBuffer(descriptorType) ? &mUniformBlockIndexToDescriptorDescIndex + : &mStorageBlockIndexToDescriptorDescIndex; + ASSERT(blockIndexToDescriptorDescIndexMap != nullptr); + ASSERT(blockIndexToDescriptorDescIndexMap->empty()); + blockIndexToDescriptorDescIndexMap->resize(blocks.size(), kInvalidDescriptorDescIndex); + // Initialize the descriptor writes in a first pass. This ensures we can pack the structures // corresponding to array elements tightly. for (uint32_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex) @@ -6006,8 +5999,9 @@ void WriteDescriptorDescs::updateShaderBuffers( const gl::ShaderType firstShaderType = block.getFirstActiveShaderType(); const ShaderInterfaceVariableInfo &info = variableInfoMap.getVariableById(firstShaderType, block.getId(firstShaderType)); + uint32_t arrayElement = block.pod.isArray ? block.pod.arrayElement : 0; - if (block.pod.isArray && block.pod.arrayElement > 0) + if (arrayElement > 0) { incrementDescriptorCount(info.binding, 1); mCurrentInfoIndex++; @@ -6016,6 +6010,10 @@ void WriteDescriptorDescs::updateShaderBuffers( { updateWriteDesc(info.binding, descriptorType, 1); } + + // Cache DescriptorDesc index + blockIndexToDescriptorDescIndexMap->at(blockIndex) = + mDescs[info.binding].descriptorInfoIndex + arrayElement; } } @@ -6077,7 +6075,7 @@ void WriteDescriptorDescs::updateImages(const gl::ProgramExecutable &executable, void WriteDescriptorDescs::updateInputAttachments( const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, - FramebufferVk *framebufferVk) + const FramebufferVk *framebufferVk) { if (framebufferVk->getDepthStencilRenderTarget() != nullptr) { @@ -6203,99 +6201,6 @@ std::ostream &operator<<(std::ostream &os, const WriteDescriptorDescs &desc) } // DescriptorSetDesc implementation. -void DescriptorSetDesc::updateDescriptorSet(Renderer *renderer, - const WriteDescriptorDescs &writeDescriptorDescs, - UpdateDescriptorSetsBuilder *updateBuilder, - const DescriptorDescHandles *handles, - VkDescriptorSet descriptorSet) const -{ - for (uint32_t writeIndex = 0; writeIndex < writeDescriptorDescs.size(); ++writeIndex) - { - const WriteDescriptorDesc &writeDesc = writeDescriptorDescs[writeIndex]; - - if (writeDesc.descriptorCount == 0) - { - continue; - } - - VkWriteDescriptorSet &writeSet = updateBuilder->allocWriteDescriptorSet(); - - writeSet.descriptorCount = writeDesc.descriptorCount; - writeSet.descriptorType = static_cast(writeDesc.descriptorType); - writeSet.dstArrayElement = 0; - writeSet.dstBinding = writeIndex; - writeSet.dstSet = descriptorSet; - writeSet.pBufferInfo = nullptr; - writeSet.pImageInfo = nullptr; - writeSet.pNext = nullptr; - writeSet.pTexelBufferView = nullptr; - writeSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - - uint32_t infoDescIndex = writeDesc.descriptorInfoIndex; - - switch (writeSet.descriptorType) - { - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - { - ASSERT(writeDesc.descriptorCount == 1); - VkBufferView &bufferView = updateBuilder->allocBufferView(); - bufferView = handles[infoDescIndex].bufferView; - writeSet.pTexelBufferView = &bufferView; - break; - } - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: - { - VkDescriptorBufferInfo *writeBuffers = - updateBuilder->allocDescriptorBufferInfos(writeSet.descriptorCount); - for (uint32_t arrayElement = 0; arrayElement < writeSet.descriptorCount; - ++arrayElement) - { - const DescriptorInfoDesc &infoDesc = - mDescriptorInfos[infoDescIndex + arrayElement]; - VkDescriptorBufferInfo &bufferInfo = writeBuffers[arrayElement]; - bufferInfo.buffer = handles[infoDescIndex + arrayElement].buffer; - bufferInfo.offset = infoDesc.imageViewSerialOrOffset; - bufferInfo.range = infoDesc.imageLayoutOrRange; - } - writeSet.pBufferInfo = writeBuffers; - break; - } - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - { - VkDescriptorImageInfo *writeImages = - updateBuilder->allocDescriptorImageInfos(writeSet.descriptorCount); - for (uint32_t arrayElement = 0; arrayElement < writeSet.descriptorCount; - ++arrayElement) - { - const DescriptorInfoDesc &infoDesc = - mDescriptorInfos[infoDescIndex + arrayElement]; - VkDescriptorImageInfo &imageInfo = writeImages[arrayElement]; - - ImageLayout imageLayout = static_cast(infoDesc.imageLayoutOrRange); - - imageInfo.imageLayout = - ConvertImageLayoutToVkImageLayout(renderer, imageLayout); - imageInfo.imageView = handles[infoDescIndex + arrayElement].imageView; - imageInfo.sampler = handles[infoDescIndex + arrayElement].sampler; - } - writeSet.pImageInfo = writeImages; - break; - } - - default: - UNREACHABLE(); - break; - } - } -} - std::ostream &operator<<(std::ostream &os, const DescriptorSetDesc &desc) { os << " desc[" << desc.size() << "]:"; @@ -6323,6 +6228,12 @@ void DescriptorSetDescAndPool::releaseCachedObject(Renderer *renderer) mPool = nullptr; } +bool DescriptorSetDescAndPool::hasValidCachedObject(ContextVk *contextVk) const +{ + ASSERT(valid()); + return mPool->hasCachedDescriptorSet(mDesc); +} + // DescriptorSetDescBuilder implementation. DescriptorSetDescBuilder::DescriptorSetDescBuilder() = default; DescriptorSetDescBuilder::DescriptorSetDescBuilder(size_t descriptorCount) @@ -6430,15 +6341,15 @@ void DescriptorSetDescBuilder::updatePreCacheActiveTextures( Context *context, const gl::ProgramExecutable &executable, const gl::ActiveTextureArray &textures, - const gl::SamplerBindingVector &samplers) + const gl::SamplerBindingVector &samplers, + const WriteDescriptorDescs &writeDescriptorDescs) { + Renderer *renderer = context->getRenderer(); const std::vector &samplerBindings = executable.getSamplerBindings(); const gl::ActiveTextureMask &activeTextures = executable.getActiveSamplersMask(); const ProgramExecutableVk *executableVk = vk::GetImpl(&executable); - resize(executableVk->getTextureWriteDescriptorDescs().getTotalDescriptorCount()); - const WriteDescriptorDescs &writeDescriptorDescs = - executableVk->getTextureWriteDescriptorDescs(); + ASSERT(writeDescriptorDescs.getTotalDescriptorCount() == mDesc.size()); const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap(); const std::vector &uniforms = executable.getUniforms(); @@ -6497,7 +6408,7 @@ void DescriptorSetDescBuilder::updatePreCacheActiveTextures( textureVk->getImageViewSubresourceSerial( samplerState, samplerUniform.isTexelFetchStaticUse()); - ImageLayout imageLayout = textureVk->getImage().getCurrentImageLayout(); + VkImageLayout imageLayout = textureVk->getImage().getCurrentLayout(renderer); SetBitField(infoDesc.imageLayoutOrRange, imageLayout); infoDesc.imageViewSerialOrOffset = imageViewSerial.viewSerial.getValue(); infoDesc.samplerOrBufferSerial = samplerHelper.getSamplerSerial().getValue(); @@ -6525,39 +6436,17 @@ void DescriptorSetDescBuilder::setEmptyBuffer(uint32_t infoDescIndex, } } -template void DescriptorSetDescBuilder::updateOneShaderBuffer( Context *context, - CommandBufferT *commandBufferHelper, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, + CommandBufferHelperCommon *commandBufferHelper, + const uint32_t infoDescIndex, const gl::InterfaceBlock &block, - uint32_t bufferIndex, + const gl::OffsetBindingPointer &bufferBinding, VkDescriptorType descriptorType, VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits) + const BufferHelper &emptyBuffer) { - if (block.activeShaders().none()) - { - return; - } - - const gl::ShaderType firstShaderType = block.getFirstActiveShaderType(); - const ShaderInterfaceVariableInfo &info = - variableInfoMap.getVariableById(firstShaderType, block.getId(firstShaderType)); - - uint32_t binding = info.binding; - uint32_t arrayElement = block.pod.isArray ? block.pod.arrayElement : 0; - uint32_t infoDescIndex = writeDescriptorDescs[binding].descriptorInfoIndex + arrayElement; - - const gl::OffsetBindingPointer &bufferBinding = buffers[bufferIndex]; - if (bufferBinding.get() == nullptr) - { - setEmptyBuffer(infoDescIndex, descriptorType, emptyBuffer); - return; - } + ASSERT(infoDescIndex != kInvalidDescriptorDescIndex && infoDescIndex < mDesc.size()); // Limit bound buffer size to maximum resource binding size. GLsizeiptr boundBufferSize = gl::GetBoundBufferAvailableSize(bufferBinding); @@ -6570,51 +6459,7 @@ void DescriptorSetDescBuilder::updateOneShaderBuffer( BufferVk *bufferVk = vk::GetImpl(bufferBinding.get()); BufferHelper &bufferHelper = bufferVk->getBuffer(); - - const bool isUniformBuffer = descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || - descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - if (isUniformBuffer) - { - commandBufferHelper->bufferRead(context, VK_ACCESS_UNIFORM_READ_BIT, block.activeShaders(), - &bufferHelper); - } - else - { - ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || - descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); - if (block.pod.isReadOnly) - { - // Avoid unnecessary barriers for readonly SSBOs by making sure the buffers are - // marked read-only. This also helps BufferVk make better decisions during - // buffer data uploads and copies by knowing that the buffers are not actually - // being written to. - commandBufferHelper->bufferRead(context, VK_ACCESS_SHADER_READ_BIT, - block.activeShaders(), &bufferHelper); - } - else if ((bufferHelper.getCurrentWriteAccess() & VK_ACCESS_SHADER_WRITE_BIT) != 0 && - (memoryBarrierBits & kBufferMemoryBarrierBits) == 0) - { - // Buffer is already in shader write access, and this is not from memoryBarrier call, - // then skip the WAW barrier since GL spec says driver is not required to insert barrier - // here. We still need to maintain object life time tracking here. - // Based on discussion here https://gitlab.khronos.org/opengl/API/-/issues/144, the - // above check of VK_ACCESS_SHADER_WRITE_BIT bit can be removed and instead rely on app - // issue glMemoryBarrier. But almost all usage I am seeing does not issue - // glMemoryBarrier before SSBO write. They only issue glMemoryBarrier after the SSBO - // write. This is to ensure we do not break the existing usage even if we think they are - // out of spec. - commandBufferHelper->retainResourceForWrite(&bufferHelper); - } - else - { - // We set the SHADER_READ_BIT to be conservative. - VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; - commandBufferHelper->bufferWrite(context, accessFlags, block.activeShaders(), - &bufferHelper); - } - } - - VkDeviceSize offset = bufferBinding.getOffset() + bufferHelper.getOffset(); + VkDeviceSize offset = bufferBinding.getOffset() + bufferHelper.getOffset(); DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoDescIndex); infoDesc.samplerOrBufferSerial = bufferHelper.getBlockSerial().getValue(); @@ -6633,39 +6478,145 @@ void DescriptorSetDescBuilder::updateOneShaderBuffer( mHandles[infoDescIndex].buffer = bufferHelper.getBuffer().getHandle(); } -template -void DescriptorSetDescBuilder::updateShaderBuffers( +void DescriptorSetDescBuilder::updateOneUniformBuffer( Context *context, - CommandBufferT *commandBufferHelper, - const gl::ProgramExecutable &executable, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const std::vector &blocks, + CommandBufferHelperCommon *commandBufferHelper, + const size_t blockIndex, + const gl::InterfaceBlock &block, + const gl::OffsetBindingPointer &bufferBinding, + VkDescriptorType descriptorType, + VkDeviceSize maxBoundBufferRange, + const BufferHelper &emptyBuffer, + const WriteDescriptorDescs &writeDescriptorDescs) +{ + ASSERT(IsUniformBuffer(descriptorType)); + + uint32_t infoDescIndex = + writeDescriptorDescs.getDescriptorDescIndexForUniformBufferBlockIndex(blockIndex); + + // Early return if empty buffer + if (bufferBinding.get() == nullptr) + { + setEmptyBuffer(infoDescIndex, descriptorType, emptyBuffer); + return; + } + + updateOneShaderBuffer(context, commandBufferHelper, infoDescIndex, block, bufferBinding, + descriptorType, maxBoundBufferRange, emptyBuffer); + + // Insert necessary barriers + commandBufferHelper->bufferRead(context, VK_ACCESS_UNIFORM_READ_BIT, block.activeShaders(), + &vk::GetImpl(bufferBinding.get())->getBuffer()); +} + +void DescriptorSetDescBuilder::updateOneUniformBufferOffset( + const size_t blockIndex, + const gl::OffsetBindingPointer &bufferBinding, + const WriteDescriptorDescs &writeDescriptorDescs) +{ + uint32_t infoDescIndex = + writeDescriptorDescs.getDescriptorDescIndexForUniformBufferBlockIndex(blockIndex); + ASSERT(infoDescIndex != kInvalidDescriptorDescIndex && infoDescIndex < mDesc.size()); + ASSERT(bufferBinding.get() != nullptr); + + DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoDescIndex); + BufferHelper &bufferHelper = vk::GetImpl(bufferBinding.get())->getBuffer(); + ASSERT(infoDesc.samplerOrBufferSerial == bufferHelper.getBlockSerial().getValue()); + // Reachable only by program executables with dynamic descriptor type + ASSERT(infoDesc.imageViewSerialOrOffset == 0); + + VkDeviceSize newOffset = bufferBinding.getOffset() + bufferHelper.getOffset(); + ASSERT(infoDescIndex < mDynamicOffsets.size()); + SetBitField(mDynamicOffsets[infoDescIndex], newOffset); +} + +void DescriptorSetDescBuilder::updateOneStorageBuffer( + Context *context, + CommandBufferHelperCommon *commandBufferHelper, + const size_t blockIndex, + const gl::InterfaceBlock &block, + const gl::OffsetBindingPointer &bufferBinding, VkDescriptorType descriptorType, VkDeviceSize maxBoundBufferRange, const BufferHelper &emptyBuffer, const WriteDescriptorDescs &writeDescriptorDescs, const GLbitfield memoryBarrierBits) { - const bool isUniformBuffer = descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || - descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + ASSERT(IsStorageBuffer(descriptorType)); + + uint32_t infoDescIndex = + writeDescriptorDescs.getDescriptorDescIndexForStorageBufferBlockIndex(blockIndex); + // Early return if empty buffer + if (bufferBinding.get() == nullptr) + { + setEmptyBuffer(infoDescIndex, descriptorType, emptyBuffer); + return; + } + + updateOneShaderBuffer(context, commandBufferHelper, infoDescIndex, block, bufferBinding, + descriptorType, maxBoundBufferRange, emptyBuffer); + + // Insert necessary barriers + BufferHelper &bufferHelper = vk::GetImpl(bufferBinding.get())->getBuffer(); + if (block.pod.isReadOnly) + { + // Avoid unnecessary barriers for readonly SSBOs by making sure the buffers are + // marked read-only. This also helps BufferVk make better decisions during + // buffer data uploads and copies by knowing that the buffers are not actually + // being written to. + commandBufferHelper->bufferRead(context, VK_ACCESS_SHADER_READ_BIT, block.activeShaders(), + &bufferHelper); + } + else if (bufferHelper.isLastAccessShaderWriteOnly() && + (memoryBarrierBits & kBufferMemoryBarrierBits) == 0) + { + // Buffer is already in shader write access, and this is not from memoryBarrier call, + // then skip the WAW barrier since GL spec says driver is not required to insert barrier + // here. We still need to maintain object life time tracking here. + // Based on discussion here https://gitlab.khronos.org/opengl/API/-/issues/144, the + // above check of VK_ACCESS_SHADER_WRITE_BIT bit can be removed and instead rely on app + // issue glMemoryBarrier. But almost all usage I am seeing does not issue + // glMemoryBarrier before SSBO write. They only issue glMemoryBarrier after the SSBO + // write. This is to ensure we do not break the existing usage even if we think they are + // out of spec. + commandBufferHelper->retainResourceForWrite(&bufferHelper); + } + else + { + // We set the SHADER_READ_BIT to be conservative. + VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + commandBufferHelper->bufferWrite(context, accessFlags, block.activeShaders(), + &bufferHelper); + } +} + +void DescriptorSetDescBuilder::updateStorageBuffers( + Context *context, + CommandBufferHelperCommon *commandBufferHelper, + const gl::ProgramExecutable &executable, + const gl::BufferVector &buffers, + const std::vector &blocks, + VkDescriptorType descriptorType, + VkDeviceSize maxBoundBufferRange, + const BufferHelper &emptyBuffer, + const WriteDescriptorDescs &writeDescriptorDescs, + const GLbitfield memoryBarrierBits) +{ // Now that we have the proper array elements counts, initialize the info structures. - for (uint32_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex) + for (size_t blockIndex : executable.getActiveStorageBufferBlocks()) { - const GLuint binding = isUniformBuffer - ? executable.getUniformBlockBinding(blockIndex) - : executable.getShaderStorageBlockBinding(blockIndex); - updateOneShaderBuffer(context, commandBufferHelper, variableInfoMap, buffers, - blocks[blockIndex], binding, descriptorType, maxBoundBufferRange, - emptyBuffer, writeDescriptorDescs, memoryBarrierBits); + const GLuint binding = executable.getShaderStorageBlockBinding(blockIndex); + + updateOneStorageBuffer(context, commandBufferHelper, blockIndex, blocks[blockIndex], + buffers[binding], descriptorType, maxBoundBufferRange, emptyBuffer, + writeDescriptorDescs, memoryBarrierBits); } } -template void DescriptorSetDescBuilder::updateAtomicCounters( Context *context, - CommandBufferT *commandBufferHelper, + CommandBufferHelperCommon *commandBufferHelper, const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, const gl::BufferVector &buffers, @@ -6735,90 +6686,15 @@ void DescriptorSetDescBuilder::updateAtomicCounters( } } -// Explicit instantiation -template void DescriptorSetDescBuilder::updateOneShaderBuffer( - Context *context, - RenderPassCommandBufferHelper *commandBufferHelper, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const gl::InterfaceBlock &block, - uint32_t bufferIndex, - VkDescriptorType descriptorType, - VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits); - -template void DescriptorSetDescBuilder::updateOneShaderBuffer( - Context *context, - OutsideRenderPassCommandBufferHelper *commandBufferHelper, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const gl::InterfaceBlock &block, - uint32_t bufferIndex, - VkDescriptorType descriptorType, - VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits); - -template void DescriptorSetDescBuilder::updateShaderBuffers( - Context *context, - OutsideRenderPassCommandBufferHelper *commandBufferHelper, - const gl::ProgramExecutable &executable, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const std::vector &blocks, - VkDescriptorType descriptorType, - VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits); - -template void DescriptorSetDescBuilder::updateShaderBuffers( - Context *context, - RenderPassCommandBufferHelper *commandBufferHelper, - const gl::ProgramExecutable &executable, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const std::vector &blocks, - VkDescriptorType descriptorType, - VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits); - -template void DescriptorSetDescBuilder::updateAtomicCounters( - Context *context, - OutsideRenderPassCommandBufferHelper *commandBufferHelper, - const gl::ProgramExecutable &executable, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const std::vector &atomicCounterBuffers, - const VkDeviceSize requiredOffsetAlignment, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs); - -template void DescriptorSetDescBuilder::updateAtomicCounters( - Context *context, - RenderPassCommandBufferHelper *commandBufferHelper, - const gl::ProgramExecutable &executable, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const std::vector &atomicCounterBuffers, - const VkDeviceSize requiredOffsetAlignment, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs); - angle::Result DescriptorSetDescBuilder::updateImages( - Context *context, + ContextVk *contextVk, const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, const gl::ActiveTextureArray &activeImages, const std::vector &imageUnits, const WriteDescriptorDescs &writeDescriptorDescs) { - Renderer *renderer = context->getRenderer(); + Renderer *renderer = contextVk->getRenderer(); const std::vector &imageBindings = executable.getImageBindings(); const std::vector &uniforms = executable.getUniforms(); @@ -6859,18 +6735,26 @@ angle::Result DescriptorSetDescBuilder::updateImages( { GLuint imageUnit = imageBinding.boundImageUnits[arrayElement]; TextureVk *textureVk = activeImages[imageUnit]; + if (!textureVk) + { + continue; + } uint32_t infoIndex = writeDescriptorDescs[info.binding].descriptorInfoIndex + arrayElement + imageUniform.getOuterArrayOffset(); const vk::BufferView *view = nullptr; - ANGLE_TRY(textureVk->getBufferView(context, format, nullptr, true, &view)); + VkFormat viewFormat; + ANGLE_TRY( + textureVk->getBufferView(contextVk, format, nullptr, true, &view, &viewFormat)); DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex); infoDesc.imageViewSerialOrOffset = textureVk->getBufferViewSerial().viewSerial.getValue(); infoDesc.imageLayoutOrRange = 0; - infoDesc.imageSubresourceRange = 0; + // special handling for texture buffer to store the VK format here. + infoDesc.imageSubresourceRange = static_cast(viewFormat); + infoDesc.samplerOrBufferSerial = 0; mHandles[infoIndex].bufferView = view->getHandle(); @@ -6883,6 +6767,10 @@ angle::Result DescriptorSetDescBuilder::updateImages( GLuint imageUnit = imageBinding.boundImageUnits[arrayElement]; const gl::ImageUnit &binding = imageUnits[imageUnit]; TextureVk *textureVk = activeImages[imageUnit]; + if (!textureVk) + { + continue; + } vk::ImageHelper *image = &textureVk->getImage(); const vk::ImageView *imageView = nullptr; @@ -6890,7 +6778,7 @@ angle::Result DescriptorSetDescBuilder::updateImages( vk::ImageOrBufferViewSubresourceSerial serial = textureVk->getStorageImageViewSerial(binding); - ANGLE_TRY(textureVk->getStorageImageView(context, binding, &imageView)); + ANGLE_TRY(textureVk->getStorageImageView(contextVk, binding, &imageView)); uint32_t infoIndex = writeDescriptorDescs[info.binding].descriptorInfoIndex + arrayElement + imageUniform.getOuterArrayOffset(); @@ -6898,7 +6786,7 @@ angle::Result DescriptorSetDescBuilder::updateImages( // Note: binding.access is unused because it is implied by the shader. DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex); - SetBitField(infoDesc.imageLayoutOrRange, image->getCurrentImageLayout()); + SetBitField(infoDesc.imageLayoutOrRange, image->getCurrentLayout(renderer)); memcpy(&infoDesc.imageSubresourceRange, &serial.subresource, sizeof(uint32_t)); infoDesc.imageViewSerialOrOffset = serial.viewSerial.getValue(); infoDesc.samplerOrBufferSerial = 0; @@ -6912,19 +6800,21 @@ angle::Result DescriptorSetDescBuilder::updateImages( } angle::Result DescriptorSetDescBuilder::updateInputAttachments( - vk::Context *context, + ContextVk *contextVk, const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, - FramebufferVk *framebufferVk, + const FramebufferVk *framebufferVk, const WriteDescriptorDescs &writeDescriptorDescs) { + vk::Renderer *renderer = contextVk->getRenderer(); + // Note: Depth/stencil input attachments are only supported in ANGLE when using // VK_KHR_dynamic_rendering_local_read, so the layout is chosen to be the one specifically made // for that extension. if (executable.usesDepthFramebufferFetch() || executable.usesStencilFramebufferFetch()) { RenderTargetVk *renderTargetVk = framebufferVk->getDepthStencilRenderTarget(); - ASSERT(context->getFeatures().preferDynamicRendering.enabled); + ASSERT(contextVk->getFeatures().preferDynamicRendering.enabled); if (renderTargetVk != nullptr) { @@ -6932,21 +6822,23 @@ angle::Result DescriptorSetDescBuilder::updateInputAttachments( renderTargetVk->getDrawSubresourceSerial(); const VkImageAspectFlags aspects = renderTargetVk->getImageForRenderPass().getAspectFlags(); + const VkImageLayout inputAttachmentLayout = + renderer->getVkImageLayout(ImageAccess::DepthStencilWriteAndInput); if (executable.usesDepthFramebufferFetch() && (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) { const vk::ImageView *imageView = nullptr; ANGLE_TRY(renderTargetVk->getDepthOrStencilImageView( - context, VK_IMAGE_ASPECT_DEPTH_BIT, &imageView)); + contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &imageView)); const uint32_t depthBinding = variableInfoMap .getVariableById(gl::ShaderType::Fragment, sh::vk::spirv::kIdDepthInputAttachment) .binding; - updateInputAttachment(context, depthBinding, ImageLayout::DepthStencilWriteAndInput, - imageView, serial, writeDescriptorDescs); + updateInputAttachment(contextVk, depthBinding, inputAttachmentLayout, imageView, + serial, writeDescriptorDescs); } if (executable.usesStencilFramebufferFetch() && @@ -6954,16 +6846,15 @@ angle::Result DescriptorSetDescBuilder::updateInputAttachments( { const vk::ImageView *imageView = nullptr; ANGLE_TRY(renderTargetVk->getDepthOrStencilImageView( - context, VK_IMAGE_ASPECT_STENCIL_BIT, &imageView)); + contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &imageView)); const uint32_t stencilBinding = variableInfoMap .getVariableById(gl::ShaderType::Fragment, sh::vk::spirv::kIdStencilInputAttachment) .binding; - updateInputAttachment(context, stencilBinding, - ImageLayout::DepthStencilWriteAndInput, imageView, serial, - writeDescriptorDescs); + updateInputAttachment(contextVk, stencilBinding, inputAttachmentLayout, imageView, + serial, writeDescriptorDescs); } } } @@ -6980,6 +6871,8 @@ angle::Result DescriptorSetDescBuilder::updateInputAttachments( gl::ShaderType::Fragment, sh::vk::spirv::kIdInputAttachment0 + firstColorInputAttachment); const uint32_t baseColorBinding = baseColorInfo.binding - firstColorInputAttachment; + const VkImageLayout inputAttachmentLayout = + renderer->getVkImageLayout(ImageAccess::ColorWriteAndInput); for (size_t colorIndex : framebufferVk->getState().getColorAttachmentsMask()) { @@ -6987,17 +6880,14 @@ angle::Result DescriptorSetDescBuilder::updateInputAttachments( RenderTargetVk *renderTargetVk = framebufferVk->getColorDrawRenderTarget(colorIndex); const vk::ImageView *imageView = nullptr; - ANGLE_TRY(renderTargetVk->getImageView(context, &imageView)); + ANGLE_TRY(renderTargetVk->getImageView(contextVk, &imageView)); const ImageOrBufferViewSubresourceSerial serial = renderTargetVk->getDrawSubresourceSerial(); // We just need any layout that represents GENERAL for render pass objects. With dynamic // rendering, there's a specific layout. - updateInputAttachment(context, binding, - context->getFeatures().preferDynamicRendering.enabled - ? ImageLayout::ColorWriteAndInput - : ImageLayout::FragmentShaderWrite, - imageView, serial, writeDescriptorDescs); + updateInputAttachment(contextVk, binding, inputAttachmentLayout, imageView, serial, + writeDescriptorDescs); } return angle::Result::Continue; @@ -7006,7 +6896,7 @@ angle::Result DescriptorSetDescBuilder::updateInputAttachments( void DescriptorSetDescBuilder::updateInputAttachment( Context *context, uint32_t binding, - ImageLayout layout, + VkImageLayout layout, const vk::ImageView *imageView, ImageOrBufferViewSubresourceSerial serial, const WriteDescriptorDescs &writeDescriptorDescs) @@ -7024,35 +6914,9 @@ void DescriptorSetDescBuilder::updateInputAttachment( mHandles[infoIndex].imageView = imageView->getHandle(); } -void DescriptorSetDescBuilder::updateDescriptorSet(Renderer *renderer, - const WriteDescriptorDescs &writeDescriptorDescs, - UpdateDescriptorSetsBuilder *updateBuilder, - VkDescriptorSet descriptorSet) const -{ - mDesc.updateDescriptorSet(renderer, writeDescriptorDescs, updateBuilder, mHandles.data(), - descriptorSet); -} - // SharedCacheKeyManager implementation. template -size_t SharedCacheKeyManager::updateEmptySlotBits() -{ - ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount); - size_t emptySlot = kInvalidSlot; - for (size_t slot = 0; slot < mSharedCacheKeys.size(); ++slot) - { - SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys[slot]; - if (!sharedCacheKey->valid()) - { - mEmptySlotBits[slot / kSlotBitCount].set(slot % kSlotBitCount); - emptySlot = slot; - } - } - return emptySlot; -} - -template -void SharedCacheKeyManager::addKey(const SharedCacheKeyT &key) +bool SharedCacheKeyManager::addKeyToEmptySlot(const SharedCacheKeyT &key) { // Search for available slots and use that if any size_t slot = 0; @@ -7065,32 +6929,48 @@ void SharedCacheKeyManager::addKey(const SharedCacheKeyT &key) ASSERT(!sharedCacheKey->valid()); sharedCacheKey = key; emptyBits.reset(slot % kSlotBitCount); - return; + return true; } slot += kSlotBitCount; } + return false; +} - // Some cached entries may have been released. Try to update and use any available slot if any. - slot = updateEmptySlotBits(); - if (slot != kInvalidSlot) +template +bool SharedCacheKeyManager::releaseUnusedKeysAndReplaceWithKey( + const SharedCacheKeyT &key) +{ + ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount); + size_t emptySlot = kInvalidSlot; + + for (size_t slot = 0; slot < mSharedCacheKeys.size(); ++slot) { SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys[slot]; + if (!sharedCacheKey->valid()) + { + mEmptySlotBits[slot / kSlotBitCount].set(slot % kSlotBitCount); + emptySlot = slot; + } + } + + if (emptySlot != kInvalidSlot) + { + SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys[emptySlot]; ASSERT(!sharedCacheKey->valid()); sharedCacheKey = key; - SlotBitMask &emptyBits = mEmptySlotBits[slot / kSlotBitCount]; - emptyBits.reset(slot % kSlotBitCount); - return; + SlotBitMask &emptyBits = mEmptySlotBits[emptySlot / kSlotBitCount]; + emptyBits.reset(emptySlot % kSlotBitCount); + return true; } + return false; +} + +template +void SharedCacheKeyManager::addKeyToNewSlot(const SharedCacheKeyT &key) +{ // No slot available, expand mSharedCacheKeys ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount); - if (!mEmptySlotBits.empty()) - { - // On first insertion, let std::vector allocate a single entry for minimal memory overhead, - // since this is the most common usage case. If that exceeds, reserve a larger chunk to - // avoid storage reallocation for efficiency (enough storage enough for 512 cache entries). - mEmptySlotBits.reserve(8); - } mEmptySlotBits.emplace_back(0xFFFFFFFE); mSharedCacheKeys.emplace_back(key); while (mSharedCacheKeys.size() < mEmptySlotBits.size() * kSlotBitCount) @@ -7164,11 +7044,12 @@ void SharedCacheKeyManager::clear() } template -bool SharedCacheKeyManager::containsKey(const SharedCacheKeyT &key) const +bool SharedCacheKeyManager::containsKeyWithOwnerEqual( + const SharedCacheKeyT &key) const { for (const SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys) { - if (*key == *sharedCacheKey) + if (key.owner_equal(sharedCacheKey)) { return true; } @@ -7177,19 +7058,92 @@ bool SharedCacheKeyManager::containsKey(const SharedCacheKeyT & } template -void SharedCacheKeyManager::assertAllEntriesDestroyed() +void SharedCacheKeyManager::assertAllEntriesDestroyed() const { // Caller must have already freed all caches - for (SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys) + for (const SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys) { ASSERT(!sharedCacheKey->valid()); } } +template +bool SharedCacheKeyManager::allValidEntriesAreCached(ContextVk *contextVk) const +{ + for (const SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys) + { + if (sharedCacheKey->valid() && !sharedCacheKey->hasValidCachedObject(contextVk)) + { + return false; + } + } + return true; +} + // Explict instantiate for FramebufferCacheManager template class SharedCacheKeyManager; +template <> +void SharedCacheKeyManager::addKey(const SharedFramebufferCacheKey &key) +{ + if (addKeyToEmptySlot(key)) + { + return; + } + + // Some cached entries may have been released. Try to update and use any available slot if + // any. + if (releaseUnusedKeysAndReplaceWithKey(key)) + { + return; + } + + // No slot available, expand mSharedCacheKeys + if (!mEmptySlotBits.empty()) + { + // On first insertion, let std::vector allocate a single entry for minimal memory overhead, + // since this is the most common usage case. If that exceeds, reserve a larger chunk to + // avoid storage reallocation for efficiency (enough storage enough for 512 cache entries). + mEmptySlotBits.reserve(8); + } + addKeyToNewSlot(key); +} + // Explict instantiate for DescriptorSetCacheManager template class SharedCacheKeyManager; +template <> +void SharedCacheKeyManager::addKey( + const SharedDescriptorSetCacheKey &key) +{ + // There are cases that same texture or buffer are bound in multiple binding point. When we have + // a cache miss, we end up looping binding point and calling addKey which may end up adding same + // key multiple times. This is a quick way to avoid that. + if (mLastAddedSharedCacheKey.owner_equal(key)) + { + return; + } + + // In case of the texture or buffer is part of many descriptorSets, lets not track it any more + // to alleviate the overhead associated with this. We will rely on eviction to free the + // descriptorSets when needed. + static constexpr size_t kMaxEmptySlots = 1; + static constexpr size_t kMaxSharedCacheKeyTracked = kSlotBitCount * kMaxEmptySlots; + if (mSharedCacheKeys.size() >= kMaxSharedCacheKeyTracked) + { + return; + } + + mLastAddedSharedCacheKey = key; + ASSERT(!containsKeyWithOwnerEqual(key)); + + if (addKeyToEmptySlot(key)) + { + return; + } + + // No slot available, expand mSharedCacheKeys + addKeyToNewSlot(key); + ASSERT(mEmptySlotBits.size() <= kMaxEmptySlots); +} // PipelineCacheAccess implementation. std::unique_lock PipelineCacheAccess::getLock() @@ -7317,6 +7271,100 @@ uint32_t UpdateDescriptorSetsBuilder::flushDescriptorSetUpdates(VkDevice device) return totalSize; } +void UpdateDescriptorSetsBuilder::updateWriteDescriptorSet( + vk::Renderer *renderer, + const vk::DescriptorSetDescBuilder &descriptorSetDescBuilder, + const vk::WriteDescriptorDescs &writeDescriptorDescs, + const VkDescriptorSet descriptorSet) +{ + const vk::DescriptorInfoDesc *descriptorSetDescs = + descriptorSetDescBuilder.getDesc().getInfoDescs(); + const vk::DescriptorDescHandles *handles = descriptorSetDescBuilder.getHandles(); + + for (uint32_t writeIndex = 0; writeIndex < writeDescriptorDescs.size(); ++writeIndex) + { + const vk::WriteDescriptorDesc &writeDesc = writeDescriptorDescs[writeIndex]; + + if (writeDesc.descriptorCount == 0) + { + continue; + } + + VkWriteDescriptorSet &writeSet = allocWriteDescriptorSet(); + + writeSet.descriptorCount = writeDesc.descriptorCount; + writeSet.descriptorType = static_cast(writeDesc.descriptorType); + writeSet.dstArrayElement = 0; + writeSet.dstBinding = writeIndex; + writeSet.dstSet = descriptorSet; + writeSet.pBufferInfo = nullptr; + writeSet.pImageInfo = nullptr; + writeSet.pNext = nullptr; + writeSet.pTexelBufferView = nullptr; + writeSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + + uint32_t infoDescIndex = writeDesc.descriptorInfoIndex; + + switch (writeSet.descriptorType) + { + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + { + ASSERT(writeDesc.descriptorCount == 1); + VkBufferView &bufferView = allocBufferView(); + bufferView = handles[infoDescIndex].bufferView; + writeSet.pTexelBufferView = &bufferView; + break; + } + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + { + VkDescriptorBufferInfo *writeBuffers = + allocDescriptorBufferInfos(writeSet.descriptorCount); + for (uint32_t arrayElement = 0; arrayElement < writeSet.descriptorCount; + ++arrayElement) + { + const vk::DescriptorInfoDesc &infoDesc = + descriptorSetDescs[infoDescIndex + arrayElement]; + VkDescriptorBufferInfo &bufferInfo = writeBuffers[arrayElement]; + bufferInfo.buffer = handles[infoDescIndex + arrayElement].buffer; + bufferInfo.offset = infoDesc.imageViewSerialOrOffset; + bufferInfo.range = infoDesc.imageLayoutOrRange; + } + writeSet.pBufferInfo = writeBuffers; + break; + } + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + { + VkDescriptorImageInfo *writeImages = + allocDescriptorImageInfos(writeSet.descriptorCount); + for (uint32_t arrayElement = 0; arrayElement < writeSet.descriptorCount; + ++arrayElement) + { + const vk::DescriptorInfoDesc &infoDesc = + descriptorSetDescs[infoDescIndex + arrayElement]; + VkDescriptorImageInfo &imageInfo = writeImages[arrayElement]; + + imageInfo.imageLayout = static_cast(infoDesc.imageLayoutOrRange); + imageInfo.imageView = handles[infoDescIndex + arrayElement].imageView; + imageInfo.sampler = handles[infoDescIndex + arrayElement].sampler; + } + writeSet.pImageInfo = writeImages; + break; + } + + default: + UNREACHABLE(); + break; + } + } +} + // FramebufferCache implementation. void FramebufferCache::destroy(vk::Renderer *renderer) { @@ -7437,15 +7485,15 @@ void RenderPassCache::InitializeOpsForCompatibleRenderPass(const vk::RenderPassD continue; } - const vk::ImageLayout imageLayout = vk::ImageLayout::ColorWrite; - opsOut->initWithLoadStore(colorIndexVk, imageLayout, imageLayout); + const vk::ImageAccess imageAccess = vk::ImageAccess::ColorWrite; + opsOut->initWithLoadStore(colorIndexVk, imageAccess, imageAccess); ++colorIndexVk; } if (desc.hasDepthStencilAttachment()) { - const vk::ImageLayout imageLayout = vk::ImageLayout::DepthWriteStencilWrite; - opsOut->initWithLoadStore(colorIndexVk, imageLayout, imageLayout); + const vk::ImageAccess imageAccess = vk::ImageAccess::DepthWriteStencilWrite; + opsOut->initWithLoadStore(colorIndexVk, imageAccess, imageAccess); } } @@ -7563,7 +7611,10 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, 0}; #endif - gl::DrawBuffersArray colorResolveImageLayout = {}; + gl::DrawBuffersArray colorResolveImageLayout = {}; + + const VkImageLayout defaultColorAttachmentLayout = + renderer->getVkImageLayout(vk::ImageAccess::ColorWrite); // Pack color attachments vk::PackedAttachmentIndex attachmentCount(0); @@ -7588,30 +7639,59 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, ASSERT(attachmentFormatID != angle::FormatID::NONE); bool isYUVExternalFormat = vk::IsYUVExternalFormat(attachmentFormatID); + + // If nullColorAttachmentWithExternalFormatResolve is VK_TRUE, pack YUV resolve first as if + // it is the color attachment. if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve()) { colorAttachmentRefs.push_back(kUnusedAttachment); // temporary workaround for ARM driver assertion. Will remove once driver fix lands - colorAttachmentRefs.back().layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAttachmentRefs.back().layout = defaultColorAttachmentLayout; colorAttachmentRefs.back().aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + VkAttachmentReference2 colorRef = {}; + colorRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + colorRef.attachment = attachmentCount.get(); + colorRef.layout = defaultColorAttachmentLayout; + colorRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + colorResolveAttachmentRefs.push_back(colorRef); + vk::UnpackAttachmentDesc(renderer, &attachmentDescs[attachmentCount.get()], + attachmentFormatID, attachmentSamples, ops[attachmentCount]); + +#if defined(ANGLE_PLATFORM_ANDROID) + // For rendering to YUV, chain on the external format info to the resolve + // attachment + const vk::ExternalYuvFormatInfo &externalFormatInfo = + renderer->getExternalFormatTable()->getExternalFormatInfo(attachmentFormatID); + externalFormat.externalFormat = externalFormatInfo.externalFormat; + VkAttachmentDescription2 &attachment = attachmentDescs[attachmentCount.get()]; + attachment.pNext = &externalFormat; + ASSERT(attachment.format == VK_FORMAT_UNDEFINED); +#endif + ++attachmentCount; continue; } + ASSERT(static_cast(ops[attachmentCount].initialLayout) != + vk::ImageAccess::SharedPresent || + static_cast(ops[attachmentCount].finalLayout) == + vk::ImageAccess::SharedPresent); + VkAttachmentReference2 colorRef = {}; colorRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; colorRef.attachment = attachmentCount.get(); - colorRef.layout = - needInputAttachments - ? VK_IMAGE_LAYOUT_GENERAL - : vk::ConvertImageLayoutToVkImageLayout( - renderer, static_cast(ops[attachmentCount].initialLayout)); + colorRef.layout = needInputAttachments + ? renderer->getVkImageLayout(vk::ImageAccess::ColorWriteAndInput) + : renderer->getVkImageLayout(static_cast( + ops[attachmentCount].initialLayout)); colorRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorAttachmentRefs.push_back(colorRef); vk::UnpackAttachmentDesc(renderer, &attachmentDescs[attachmentCount.get()], attachmentFormatID, attachmentSamples, ops[attachmentCount]); colorResolveImageLayout[colorIndexGL] = - static_cast(ops[attachmentCount].finalResolveLayout); + static_cast(ops[attachmentCount].finalResolveLayout); if (isYUVExternalFormat) { @@ -7640,6 +7720,7 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, } // Pack depth/stencil attachment, if any + vk::ImageAccess depthStencilImageAccess = vk::ImageAccess::Undefined; if (desc.hasDepthStencilAttachment()) { uint32_t depthStencilIndexGL = static_cast(desc.depthStencilAttachmentIndex()); @@ -7647,10 +7728,11 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, angle::FormatID attachmentFormatID = desc[depthStencilIndexGL]; ASSERT(attachmentFormatID != angle::FormatID::NONE); + depthStencilImageAccess = static_cast(ops[attachmentCount].initialLayout); + depthStencilAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; depthStencilAttachmentRef.attachment = attachmentCount.get(); - depthStencilAttachmentRef.layout = ConvertImageLayoutToVkImageLayout( - renderer, static_cast(ops[attachmentCount].initialLayout)); + depthStencilAttachmentRef.layout = renderer->getVkImageLayout(depthStencilImageAccess); depthStencilAttachmentRef.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; @@ -7669,18 +7751,19 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, // Pack fragment shading rate attachment, if any if (desc.hasFragmentShadingAttachment()) { - vk::UnpackFragmentShadingRateAttachmentDesc(&attachmentDescs[attachmentCount.get()]); + vk::UnpackFragmentShadingRateAttachmentDesc(renderer, + &attachmentDescs[attachmentCount.get()]); fragmentShadingRateAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; fragmentShadingRateAttachmentRef.attachment = attachmentCount.get(); fragmentShadingRateAttachmentRef.layout = - VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; + renderer->getVkImageLayout(vk::ImageAccess::FragmentShadingRateAttachmentReadOnly); ++attachmentCount; } // Pack color resolve attachments - const uint32_t nonResolveAttachmentCount = attachmentCount.get(); + uint32_t nonResolveAttachmentCount = attachmentCount.get(); for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL) { if (!desc.hasColorResolveAttachment(colorIndexGL)) @@ -7694,10 +7777,23 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, angle::FormatID attachmentFormatID = desc[colorIndexGL]; bool isYUVExternalFormat = vk::IsYUVExternalFormat(attachmentFormatID); + if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve()) + { + // attachmentCount counts the YUV resolve, so decrease nonResolveAttachmentCount here. + --nonResolveAttachmentCount; + continue; + } + + const VkImageLayout finalLayout = + renderer->getVkImageLayout(colorResolveImageLayout[colorIndexGL]); + const VkImageLayout initialLayout = + (finalLayout == VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR ? VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR + : defaultColorAttachmentLayout); + VkAttachmentReference2 colorRef = {}; colorRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; colorRef.attachment = attachmentCount.get(); - colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorRef.layout = initialLayout; colorRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // If color attachment is invalidated, try to remove its resolve attachment altogether. @@ -7712,18 +7808,10 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, const bool isInvalidated = isMSRTTEmulationColorInvalidated.test(colorIndexGL); - if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve()) - { - vk::UnpackAttachmentDesc(renderer, &attachmentDescs[attachmentCount.get()], - attachmentFormatID, attachmentSamples, ops[attachmentCount]); - } - else - { - vk::UnpackColorResolveAttachmentDesc( - renderer, &attachmentDescs[attachmentCount.get()], attachmentFormatID, - {desc.hasColorUnresolveAttachment(colorIndexGL), isInvalidated, false}, - colorResolveImageLayout[colorIndexGL]); - } + vk::UnpackColorResolveAttachmentDesc( + renderer, &attachmentDescs[attachmentCount.get()], attachmentFormatID, + {desc.hasColorUnresolveAttachment(colorIndexGL), isInvalidated, false}, initialLayout, + finalLayout); #if defined(ANGLE_PLATFORM_ANDROID) // For rendering to YUV, chain on the external format info to the resolve attachment @@ -7773,7 +7861,8 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, } depthStencilResolveAttachmentRef.attachment = attachmentCount.get(); - depthStencilResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthStencilResolveAttachmentRef.layout = + renderer->getVkImageLayout(vk::ImageAccess::DepthWriteStencilWrite); depthStencilResolveAttachmentRef.aspectMask = 0; if (!isMSRTTEmulationDepthInvalidated && !isDepthUnused) @@ -7808,10 +7897,10 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, { subpassDesc.push_back({}); vk::InitializeUnresolveSubpass( - desc, colorAttachmentRefs, colorResolveAttachmentRefs, depthStencilAttachmentRef, - depthStencilResolveAttachmentRef, &unresolveColorAttachmentRefs, - &unresolveDepthStencilAttachmentRef, &unresolveInputAttachmentRefs, - &unresolvePreserveAttachmentRefs, &subpassDesc.back()); + renderer, desc, colorAttachmentRefs, colorResolveAttachmentRefs, + depthStencilAttachmentRef, depthStencilResolveAttachmentRef, + &unresolveColorAttachmentRefs, &unresolveDepthStencilAttachmentRef, + &unresolveInputAttachmentRefs, &unresolvePreserveAttachmentRefs, &subpassDesc.back()); } subpassDesc.push_back({}); @@ -7946,6 +8035,13 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, createInfo.pDependencies = subpassDependencies.data(); } + if (desc.viewCount() && desc.isRenderToTexture()) + { + // GL_OVR_multiview_multisampled_render_to_texture is only implemented + // through the VK_EXT_multisampled_render_to_single_sampled extension, and not emulated. + ASSERT(isRenderToTextureThroughExtension); + } + const uint32_t viewMask = angle::BitMask(desc.viewCount()); if (desc.viewCount() > 0) { @@ -7970,7 +8066,8 @@ angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context, // unresolve and resolve operations etc. This information is taken out of the render pass // create info. Depth/stencil resolve attachment uses RenderPass2 structures, so it's // passed in separately. - vk::UpdateRenderPassPerfCounters(desc, createInfo, depthStencilResolve, renderPassCounters); + vk::UpdateRenderPassPerfCounters(desc, createInfo, depthStencilResolve, + depthStencilImageAccess, renderPassCounters); } return angle::Result::Continue; @@ -8169,8 +8266,7 @@ angle::Result GraphicsPipelineCache::createPipeline( vk::PipelineCacheAccess *pipelineCache, const vk::RenderPass &compatibleRenderPass, const vk::PipelineLayout &pipelineLayout, - const vk::ShaderModuleMap &shaders, - const vk::SpecializationConstants &specConsts, + const vk::GraphicsPipelineShadersInfo &shaders, PipelineSource source, const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc **descPtrOut, @@ -8185,9 +8281,9 @@ angle::Result GraphicsPipelineCache::createPipeline( constexpr vk::GraphicsPipelineSubset kSubset = GraphicsPipelineCacheTypeHelper::kSubset; - ANGLE_VK_TRY(context, desc.initializePipeline(context, pipelineCache, kSubset, - compatibleRenderPass, pipelineLayout, shaders, - specConsts, &newPipeline, &feedback)); + ANGLE_VK_TRY(context, + desc.initializePipeline(context, pipelineCache, kSubset, compatibleRenderPass, + pipelineLayout, shaders, &newPipeline, &feedback)); } if (source == PipelineSource::WarmUp) @@ -8197,40 +8293,19 @@ angle::Result GraphicsPipelineCache::createPipeline( // pipeline. **pipelineOut = vk::PipelineHelper(std::move(newPipeline), vk::CacheLookUpFeedback::WarmUpMiss); + ASSERT(!shaders.usePipelineLibrary()); } else { addToCache(source, desc, std::move(newPipeline), feedback, descPtrOut, pipelineOut); + if (shaders.usePipelineLibrary()) + { + (*pipelineOut)->setLinkedLibraryReferences(shaders.pipelineLibrary()); + } } return angle::Result::Continue; } -template -angle::Result GraphicsPipelineCache::linkLibraries( - vk::ErrorContext *context, - vk::PipelineCacheAccess *pipelineCache, - const vk::GraphicsPipelineDesc &desc, - const vk::PipelineLayout &pipelineLayout, - vk::PipelineHelper *vertexInputPipeline, - vk::PipelineHelper *shadersPipeline, - vk::PipelineHelper *fragmentOutputPipeline, - const vk::GraphicsPipelineDesc **descPtrOut, - vk::PipelineHelper **pipelineOut) -{ - vk::Pipeline newPipeline; - vk::CacheLookUpFeedback feedback = vk::CacheLookUpFeedback::None; - - ANGLE_TRY(vk::InitializePipelineFromLibraries( - context, pipelineCache, pipelineLayout, *vertexInputPipeline, *shadersPipeline, - *fragmentOutputPipeline, desc, &newPipeline, &feedback)); - - addToCache(PipelineSource::DrawLinked, desc, std::move(newPipeline), feedback, descPtrOut, - pipelineOut); - (*pipelineOut)->setLinkedLibraryReferences(shadersPipeline); - - return angle::Result::Continue; -} - template void GraphicsPipelineCache::addToCache(PipelineSource source, const vk::GraphicsPipelineDesc &desc, @@ -8305,47 +8380,16 @@ template angle::Result GraphicsPipelineCache:: vk::PipelineCacheAccess *pipelineCache, const vk::RenderPass &compatibleRenderPass, const vk::PipelineLayout &pipelineLayout, - const vk::ShaderModuleMap &shaders, - const vk::SpecializationConstants &specConsts, + const vk::GraphicsPipelineShadersInfo &shaders, PipelineSource source, const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc **descPtrOut, vk::PipelineHelper **pipelineOut); -template angle::Result GraphicsPipelineCache::linkLibraries( - vk::ErrorContext *context, - vk::PipelineCacheAccess *pipelineCache, - const vk::GraphicsPipelineDesc &desc, - const vk::PipelineLayout &pipelineLayout, - vk::PipelineHelper *vertexInputPipeline, - vk::PipelineHelper *shadersPipeline, - vk::PipelineHelper *fragmentOutputPipeline, - const vk::GraphicsPipelineDesc **descPtrOut, - vk::PipelineHelper **pipelineOut); template void GraphicsPipelineCache::populate( const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline, vk::PipelineHelper **pipelineHelperOut); -template void GraphicsPipelineCache::destroy( - vk::ErrorContext *context); -template void GraphicsPipelineCache::release( - vk::ErrorContext *context); -template angle::Result GraphicsPipelineCache::createPipeline( - vk::ErrorContext *context, - vk::PipelineCacheAccess *pipelineCache, - const vk::RenderPass &compatibleRenderPass, - const vk::PipelineLayout &pipelineLayout, - const vk::ShaderModuleMap &shaders, - const vk::SpecializationConstants &specConsts, - PipelineSource source, - const vk::GraphicsPipelineDesc &desc, - const vk::GraphicsPipelineDesc **descPtrOut, - vk::PipelineHelper **pipelineOut); -template void GraphicsPipelineCache::populate( - const vk::GraphicsPipelineDesc &desc, - vk::Pipeline &&pipeline, - vk::PipelineHelper **pipelineHelperOut); - template void GraphicsPipelineCache::destroy( vk::ErrorContext *context); template void GraphicsPipelineCache::release( @@ -8355,8 +8399,7 @@ template angle::Result GraphicsPipelineCache::c vk::PipelineCacheAccess *pipelineCache, const vk::RenderPass &compatibleRenderPass, const vk::PipelineLayout &pipelineLayout, - const vk::ShaderModuleMap &shaders, - const vk::SpecializationConstants &specConsts, + const vk::GraphicsPipelineShadersInfo &shaders, PipelineSource source, const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc **descPtrOut, @@ -8366,27 +8409,6 @@ template void GraphicsPipelineCache::populate( vk::Pipeline &&pipeline, vk::PipelineHelper **pipelineHelperOut); -template void GraphicsPipelineCache::destroy( - vk::ErrorContext *context); -template void GraphicsPipelineCache::release( - vk::ErrorContext *context); -template angle::Result -GraphicsPipelineCache::createPipeline( - vk::ErrorContext *context, - vk::PipelineCacheAccess *pipelineCache, - const vk::RenderPass &compatibleRenderPass, - const vk::PipelineLayout &pipelineLayout, - const vk::ShaderModuleMap &shaders, - const vk::SpecializationConstants &specConsts, - PipelineSource source, - const vk::GraphicsPipelineDesc &desc, - const vk::GraphicsPipelineDesc **descPtrOut, - vk::PipelineHelper **pipelineOut); -template void GraphicsPipelineCache::populate( - const vk::GraphicsPipelineDesc &desc, - vk::Pipeline &&pipeline, - vk::PipelineHelper **pipelineHelperOut); - // DescriptorSetLayoutCache implementation. DescriptorSetLayoutCache::DescriptorSetLayoutCache() = default; @@ -8526,27 +8548,44 @@ SamplerYcbcrConversionCache::~SamplerYcbcrConversionCache() ASSERT(mExternalFormatPayload.empty() && mVkFormatPayload.empty()); } -void SamplerYcbcrConversionCache::destroy(vk::Renderer *renderer) +void SamplerYcbcrConversionCache::destroy(vk::Renderer *renderer, bool orphanConversionInfo) { renderer->accumulateCacheStats(VulkanCacheType::SamplerYcbcrConversion, mCacheStats); - VkDevice device = renderer->getDevice(); - - uint32_t count = static_cast(mExternalFormatPayload.size()); - for (auto &iter : mExternalFormatPayload) + // If the EGL_ANGLE_display_texture_share_group extension is causing some samplers to + // stay alive, there is no way to know which conversion info object needs to stay alive. + // stash them all in the renderer to be destroyed when possible. + if (orphanConversionInfo) { - vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter.second; - samplerYcbcrConversion.destroy(device); + for (auto &iter : mExternalFormatPayload) + { + renderer->addSamplerYcbcrConversionToOrphanList(iter.second.release()); + } + for (auto &iter : mVkFormatPayload) + { + renderer->addSamplerYcbcrConversionToOrphanList(iter.second.release()); + } } - renderer->onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, count); - - count = static_cast(mExternalFormatPayload.size()); - for (auto &iter : mVkFormatPayload) + else { - vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter.second; - samplerYcbcrConversion.destroy(device); + VkDevice device = renderer->getDevice(); + + uint32_t count = static_cast(mExternalFormatPayload.size()); + for (auto &iter : mExternalFormatPayload) + { + vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter.second; + samplerYcbcrConversion.destroy(device); + } + renderer->onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, count); + + count = static_cast(mExternalFormatPayload.size()); + for (auto &iter : mVkFormatPayload) + { + vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter.second; + samplerYcbcrConversion.destroy(device); + } + renderer->onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, count); } - renderer->onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, count); mExternalFormatPayload.clear(); mVkFormatPayload.clear(); @@ -8595,14 +8634,34 @@ SamplerCache::~SamplerCache() ASSERT(mPayload.empty()); } -void SamplerCache::destroy(vk::Renderer *renderer) +void SamplerCache::destroy(vk::Renderer *renderer, bool orphanReferencedSamplers) { renderer->accumulateCacheStats(VulkanCacheType::Sampler, mCacheStats); uint32_t count = static_cast(mPayload.size()); - ASSERT(AllCacheEntriesHaveUniqueReference(mPayload)); + + if (orphanReferencedSamplers) + { + for (auto &iter : mPayload) + { + // If the EGL_ANGLE_display_texture_share_group extension is causing some samplers to + // stay alive, stash them in the renderer to be destroyed when possible. + if (!iter.second.unique()) + { + renderer->addSamplerToOrphanList(iter.second); + } + else + { + renderer->onDeallocateHandle(vk::HandleType::Sampler, 1); + } + } + } + else + { + ASSERT(AllCacheEntriesHaveUniqueReference(mPayload)); + renderer->onDeallocateHandle(vk::HandleType::Sampler, count); + } mPayload.clear(); - renderer->onDeallocateHandle(vk::HandleType::Sampler, count); } angle::Result SamplerCache::getSampler(ContextVk *contextVk, diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.h b/src/libANGLE/renderer/vulkan/vk_cache_utils.h index 8ccb3c6af73..3721889248c 100644 --- a/src/libANGLE/renderer/vulkan/vk_cache_utils.h +++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.h @@ -11,6 +11,10 @@ #ifndef LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_ #define LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/Color.h" @@ -34,22 +38,23 @@ class UpdateDescriptorSetsBuilder; // Some descriptor set and pipeline layout constants. // -// The set/binding assignment is done as following: +// The set/binding assignment is done as follows: // // - Set 0 contains uniform blocks created to encompass default uniforms. 1 binding is used per // pipeline stage. Additionally, transform feedback buffers are bound from binding 2 and up. // For internal shaders, set 0 is used for all the needed resources. // - Set 1 contains all textures (including texture buffers). -// - Set 2 contains all other shader resources, such as uniform and storage blocks, atomic counter +// - Set 2 contains all uniform buffers +// - Set 3 contains all other shader resources, such as storage buffers, atomic counter // buffers, images and image buffers. -// - Set 3 reserved for OpenCL enum class DescriptorSetIndex : uint32_t { Internal = 0, // Internal shaders UniformsAndXfb = Internal, // Uniforms set index Texture = 1, // Textures set index - ShaderResource = 2, // Other shader resources set index + UniformBuffers = 2, // Uniform buffers set index + ShaderResource = 3, // Other shader resources set index // CL specific naming for set indices LiteralSampler = 0, @@ -67,11 +72,12 @@ class Context; class BufferHelper; class DynamicDescriptorPool; class SamplerHelper; -enum class ImageLayout; +enum class ImageAccess; class PipelineCacheAccess; class RenderPassCommandBufferHelper; class PackedClearValuesArray; class AttachmentOpsArray; +class CommandBufferHelperCommon; using PipelineLayoutPtr = AtomicSharedPtr; using DescriptorSetLayoutPtr = AtomicSharedPtr; @@ -214,7 +220,8 @@ class alignas(4) RenderPassDesc final // initially. void packDepthUnresolveAttachment(); void packStencilUnresolveAttachment(); - void removeDepthStencilUnresolveAttachment(); + void removeDepthUnresolveAttachment(); + void removeStencilUnresolveAttachment(); PackedAttachmentIndex getPackedColorAttachmentIndex(size_t colorIndexGL); @@ -411,10 +418,8 @@ static_assert(kRenderPassDescSize == 16, "Size check failed"); enum class GraphicsPipelineSubset { - Complete, // Including all subsets - VertexInput, - Shaders, - FragmentOutput, + Complete, // Include all subsets + Shaders, // Include only the shader subsets, excluding vertex input and fragment output state. }; enum class CacheLookUpFeedback @@ -447,7 +452,7 @@ struct PackedAttachmentOpsDesc final uint16_t isStencilInvalidated : 1; uint16_t padding1 : 6; - // Layouts take values from ImageLayout, so they are small. Layouts that are possible here are + // Layouts take values from ImageAccess, so they are small. Layouts that are possible here are // placed at the beginning of that enum. uint16_t initialLayout : 5; uint16_t finalLayout : 5; @@ -473,12 +478,12 @@ class AttachmentOpsArray final // Initialize an attachment op with all load and store operations. void initWithLoadStore(PackedAttachmentIndex index, - ImageLayout initialLayout, - ImageLayout finalLayout); + ImageAccess initialLayout, + ImageAccess finalLayout); void setLayouts(PackedAttachmentIndex index, - ImageLayout initialLayout, - ImageLayout finalLayout); + ImageAccess initialLayout, + ImageAccess finalLayout); void setOps(PackedAttachmentIndex index, RenderPassLoadOp loadOp, RenderPassStoreOp storeOp); void setStencilOps(PackedAttachmentIndex index, RenderPassLoadOp loadOp, @@ -502,8 +507,8 @@ struct PackedAttribDesc final uint8_t format; uint8_t divisor; uint16_t offset : kAttributeOffsetMaxBits; - uint16_t compressed : 1; }; +static_assert(kAttributeOffsetMaxBits == 16, "Keep PackedAttribDesc struct tightly packed"); constexpr size_t kPackedAttribDescSize = sizeof(PackedAttribDesc); static_assert(kPackedAttribDescSize == 4, "Size mismatch"); @@ -600,13 +605,12 @@ struct PackedPreRasterizationAndFragmentStates final // Dynamic in VK_EXT_extended_dynamic_state2 uint32_t depthCompareOp : 4; - // Affecting specialization constants - uint32_t surfaceRotation : 1; - // Whether the pipeline is robust (shader stages copy) uint32_t isRobustContext : 1; // Whether the pipeline needs access to protected content (shader stages copy) uint32_t isProtectedContext : 1; + + uint32_t padding : 1; } bits; // Affecting specialization constants @@ -799,7 +803,7 @@ struct GraphicsPipelineFragmentOutputVulkanStructs ANGLE_ENABLE_STRUCT_PADDING_WARNINGS -using GraphicsPipelineDynamicStateList = angle::FixedVector; +using GraphicsPipelineDynamicStateList = angle::FixedVector; enum class PipelineRobustness { @@ -869,6 +873,38 @@ class ComputePipelineDesc final char mPadding[7] = {}; }; +class PipelineHelper; + +// When a graphics pipeline is created, the shaders state is either directly specified (monolithic +// pipeline) or is specified in a pipeline library. This struct encapsulates the choices. +struct GraphicsPipelineShadersInfo final +{ + public: + GraphicsPipelineShadersInfo(const ShaderModuleMap *shaders, + const SpecializationConstants *specConsts) + : mShaders(shaders), mSpecConsts(specConsts) + {} + GraphicsPipelineShadersInfo(vk::PipelineHelper *pipelineLibrary) + : mPipelineLibrary(pipelineLibrary) + {} + + vk::PipelineHelper *pipelineLibrary() const { return mPipelineLibrary; } + bool usePipelineLibrary() const { return mPipelineLibrary != nullptr; } + + private: + // If the shaders state should be directly specified in the final pipeline. + const ShaderModuleMap *mShaders = nullptr; + const SpecializationConstants *mSpecConsts = nullptr; + + // If the shaders state is provided via a pipeline library. + vk::PipelineHelper *mPipelineLibrary = nullptr; + + friend class GraphicsPipelineDesc; +}; + +angle::FormatID PatchVertexAttribComponentType(angle::FormatID format, + gl::ComponentType vsInputType); + // State changes are applied through the update methods. Each update method can also have a // sibling method that applies the update without marking a state transition. The non-transition // update methods are used for internal shader pipelines. Not every non-transition update method @@ -905,8 +941,7 @@ class GraphicsPipelineDesc final GraphicsPipelineSubset subset, const RenderPass &compatibleRenderPass, const PipelineLayout &pipelineLayout, - const ShaderModuleMap &shaders, - const SpecializationConstants &specConsts, + const GraphicsPipelineShadersInfo &shaders, Pipeline *pipelineOut, CacheLookUpFeedback *feedbackOut) const; @@ -917,7 +952,6 @@ class GraphicsPipelineDesc final GLuint stride, GLuint divisor, angle::FormatID format, - bool compressed, GLuint relativeOffset); void setVertexShaderComponentTypes(gl::AttributesMask activeAttribLocations, gl::ComponentTypeMask componentTypeMask); @@ -1062,10 +1096,6 @@ class GraphicsPipelineDesc final void setSubpass(uint32_t subpass); uint32_t getSubpass() const; - void updateSurfaceRotation(GraphicsPipelineTransitionBits *transition, - bool isRotatedAspectRatio); - bool getSurfaceRotation() const { return mShaders.shaders.bits.surfaceRotation; } - void updateEmulatedDitherControl(GraphicsPipelineTransitionBits *transition, uint16_t value); uint32_t getEmulatedDitherControl() const { return mShaders.shaders.emulatedDitherControl; } @@ -1085,7 +1115,6 @@ class GraphicsPipelineDesc final static VkFormat getPipelineVertexInputStateFormat(ErrorContext *context, angle::FormatID formatID, - bool compressed, const gl::ComponentType programAttribType, uint32_t attribIndex); @@ -1101,6 +1130,16 @@ class GraphicsPipelineDesc final return mFragmentOutput; } + bool hasPipelineProtectedAccess() const + { + ASSERT(mShaders.shaders.bits.isProtectedContext == + mVertexInput.inputAssembly.bits.isProtectedContext); + ASSERT(mShaders.shaders.bits.isProtectedContext == + mFragmentOutput.blendMaskAndLogic.bits.isProtectedContext); + + return mShaders.shaders.bits.isProtectedContext; + } + private: void updateSubpass(GraphicsPipelineTransitionBits *transition, uint32_t subpass); @@ -1206,7 +1245,7 @@ class DescriptorSetLayoutDesc final #endif }; -// The following are for caching descriptor set layouts. Limited to max three descriptor set +// The following are for caching descriptor set layouts. Limited to max four descriptor set // layouts. This can be extended in the future. constexpr size_t kMaxDescriptorSetLayouts = ToUnderlying(DescriptorSetIndex::EnumCount); @@ -1390,7 +1429,9 @@ class SamplerDesc final // Values from angle::ColorGeneric::Type. Float is 0 and others are 1. uint16_t mBorderColorType : 1; - uint16_t mPadding : 15; + uint16_t mUsesSecondComponentForStencil : 1; + + uint16_t mPadding : 14; // 16*8 bits for BorderColor angle::ColorF mBorderColor; @@ -1404,8 +1445,6 @@ static_assert(sizeof(SamplerDesc) == 56, "Unexpected SamplerDesc size"); // Disable warnings about struct padding. ANGLE_DISABLE_STRUCT_PADDING_WARNINGS -class PipelineHelper; - struct GraphicsPipelineTransition { GraphicsPipelineTransition(); @@ -1613,7 +1652,7 @@ class PipelineHelper final : public Resource const GraphicsPipelineDesc *desc, PipelineHelper *pipeline); - const std::vector getTransitions() const { return mTransitions; } + const std::vector &getTransitions() const { return mTransitions; } void setComputePipeline(Pipeline &&pipeline, CacheLookUpFeedback feedback) { @@ -1644,8 +1683,7 @@ class PipelineHelper final : public Resource // The list of pipeline helpers that were referenced when creating a linked pipeline. These // pipelines must be kept alive, so their serial is updated at the same time as this object. - // Not necessary for vertex input and fragment output as they stay alive until context's - // destruction. + // The shaders pipeline is the only library so far. PipelineHelper *mLinkedShaders = nullptr; // If pipeline libraries are used and monolithic pipelines are created in parallel, this is the @@ -1773,7 +1811,7 @@ struct DescriptorInfoDesc { uint32_t samplerOrBufferSerial; uint32_t imageViewSerialOrOffset; - uint32_t imageLayoutOrRange; // Packed VkImageLayout + uint32_t imageLayoutOrRange; uint32_t imageSubresourceRange; }; @@ -1794,6 +1832,7 @@ struct DescriptorDescHandles VkBufferView bufferView; }; +constexpr uint32_t kInvalidDescriptorDescIndex = static_cast(-1); class WriteDescriptorDescs { public: @@ -1802,6 +1841,8 @@ class WriteDescriptorDescs mDescs.clear(); mDynamicDescriptorSetCount = 0; mCurrentInfoIndex = 0; + mUniformBlockIndexToDescriptorDescIndex.clear(); + mStorageBlockIndexToDescriptorDescIndex.clear(); } void updateShaderBuffers(const ShaderInterfaceVariableInfoMap &variableInfoMap, @@ -1816,7 +1857,7 @@ class WriteDescriptorDescs void updateInputAttachments(const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, - FramebufferVk *framebufferVk); + const FramebufferVk *framebufferVk); void updateExecutableActiveTextures(const ShaderInterfaceVariableInfoMap &variableInfoMap, const gl::ProgramExecutable &executable); @@ -1841,6 +1882,20 @@ class WriteDescriptorDescs size_t getTotalDescriptorCount() const { return mCurrentInfoIndex; } size_t getDynamicDescriptorSetCount() const { return mDynamicDescriptorSetCount; } + uint32_t getDescriptorDescIndexForUniformBufferBlockIndex(size_t bindingIndex) const + { + ASSERT(bindingIndex < mUniformBlockIndexToDescriptorDescIndex.size()); + + return mUniformBlockIndexToDescriptorDescIndex[bindingIndex]; + } + + uint32_t getDescriptorDescIndexForStorageBufferBlockIndex(size_t bindingIndex) const + { + ASSERT(bindingIndex < mStorageBlockIndexToDescriptorDescIndex.size()); + + return mStorageBlockIndexToDescriptorDescIndex[bindingIndex]; + } + private: bool hasWriteDescAtIndex(uint32_t bindingIndex) const { @@ -1858,14 +1913,15 @@ class WriteDescriptorDescs VkDescriptorType descriptorType, uint32_t descriptorCount); - void updateInputAttachment(uint32_t binding, - ImageLayout layout, - RenderTargetVk *renderTargetVk); - // After a preliminary minimum size, use heap memory. angle::FastMap mDescs; size_t mDynamicDescriptorSetCount = 0; uint32_t mCurrentInfoIndex = 0; + + // A map of { uniform block index, mDescs index } + std::vector mUniformBlockIndexToDescriptorDescIndex; + // A map of { storage block index, mDescs index } + std::vector mStorageBlockIndexToDescriptorDescIndex; }; std::ostream &operator<<(std::ostream &os, const WriteDescriptorDescs &desc); @@ -1907,11 +1963,7 @@ class DescriptorSetDesc return mDescriptorInfos[infoDescIndex]; } - void updateDescriptorSet(Renderer *renderer, - const WriteDescriptorDescs &writeDescriptorDescs, - UpdateDescriptorSetsBuilder *updateBuilder, - const DescriptorDescHandles *handles, - VkDescriptorSet descriptorSet) const; + const DescriptorInfoDesc *getInfoDescs() const { return mDescriptorInfos.data(); } private: // After a preliminary minimum size, use heap memory. @@ -1952,6 +2004,9 @@ class DescriptorSetDescAndPool final return mDesc == other.mDesc && mPool == other.mPool; } + // Returns true if the key/value can be found in the cache. + bool hasValidCachedObject(ContextVk *contextVk) const; + private: DescriptorSetDesc mDesc; DynamicDescriptorPool *mPool; @@ -2008,33 +2063,45 @@ class DescriptorSetDescBuilder final TransformFeedbackVk *transformFeedbackVk); // Specific helpers for shader resource descriptors. - template + void updateOneUniformBuffer(Context *context, + CommandBufferHelperCommon *commandBufferHelper, + const size_t blockIndex, + const gl::InterfaceBlock &block, + const gl::OffsetBindingPointer &bufferBinding, + VkDescriptorType descriptorType, + VkDeviceSize maxBoundBufferRange, + const BufferHelper &emptyBuffer, + const WriteDescriptorDescs &writeDescriptorDescs); + void updateOneStorageBuffer(Context *context, + CommandBufferHelperCommon *commandBufferHelper, + const size_t blockIndex, + const gl::InterfaceBlock &block, + const gl::OffsetBindingPointer &bufferBinding, + VkDescriptorType descriptorType, + VkDeviceSize maxBoundBufferRange, + const BufferHelper &emptyBuffer, + const WriteDescriptorDescs &writeDescriptorDescs, + const GLbitfield memoryBarrierBits); void updateOneShaderBuffer(Context *context, - CommandBufferT *commandBufferHelper, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, + CommandBufferHelperCommon *commandBufferHelper, + const uint32_t infoDescIndex, const gl::InterfaceBlock &block, - uint32_t bufferIndex, + const gl::OffsetBindingPointer &bufferBinding, VkDescriptorType descriptorType, VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits); - template - void updateShaderBuffers(Context *context, - CommandBufferT *commandBufferHelper, - const gl::ProgramExecutable &executable, - const ShaderInterfaceVariableInfoMap &variableInfoMap, - const gl::BufferVector &buffers, - const std::vector &blocks, - VkDescriptorType descriptorType, - VkDeviceSize maxBoundBufferRange, - const BufferHelper &emptyBuffer, - const WriteDescriptorDescs &writeDescriptorDescs, - const GLbitfield memoryBarrierBits); - template + const BufferHelper &emptyBuffer); + void updateStorageBuffers(Context *context, + CommandBufferHelperCommon *commandBufferHelper, + const gl::ProgramExecutable &executable, + const gl::BufferVector &buffers, + const std::vector &blocks, + VkDescriptorType descriptorType, + VkDeviceSize maxBoundBufferRange, + const BufferHelper &emptyBuffer, + const WriteDescriptorDescs &writeDescriptorDescs, + const GLbitfield memoryBarrierBits); void updateAtomicCounters(Context *context, - CommandBufferT *commandBufferHelper, + CommandBufferHelperCommon *commandBufferHelper, const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, const gl::BufferVector &buffers, @@ -2042,36 +2109,37 @@ class DescriptorSetDescBuilder final const VkDeviceSize requiredOffsetAlignment, const BufferHelper &emptyBuffer, const WriteDescriptorDescs &writeDescriptorDescs); - angle::Result updateImages(Context *context, + void updateOneUniformBufferOffset(const size_t blockIndex, + const gl::OffsetBindingPointer &bufferBinding, + const WriteDescriptorDescs &writeDescriptorDescs); + angle::Result updateImages(ContextVk *contextVk, const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, const gl::ActiveTextureArray &activeImages, const std::vector &imageUnits, const WriteDescriptorDescs &writeDescriptorDescs); - angle::Result updateInputAttachments(vk::Context *context, + angle::Result updateInputAttachments(ContextVk *contextVk, const gl::ProgramExecutable &executable, const ShaderInterfaceVariableInfoMap &variableInfoMap, - FramebufferVk *framebufferVk, + const FramebufferVk *framebufferVk, const WriteDescriptorDescs &writeDescriptorDescs); // Specialized update for textures. void updatePreCacheActiveTextures(Context *context, const gl::ProgramExecutable &executable, const gl::ActiveTextureArray &textures, - const gl::SamplerBindingVector &samplers); - - void updateDescriptorSet(Renderer *renderer, - const WriteDescriptorDescs &writeDescriptorDescs, - UpdateDescriptorSetsBuilder *updateBuilder, - VkDescriptorSet descriptorSet) const; + const gl::SamplerBindingVector &samplers, + const WriteDescriptorDescs &writeDescriptorDescs); const uint32_t *getDynamicOffsets() const { return mDynamicOffsets.data(); } size_t getDynamicOffsetsSize() const { return mDynamicOffsets.size(); } + const DescriptorDescHandles *getHandles() const { return mHandles.data(); } + private: void updateInputAttachment(Context *context, uint32_t binding, - ImageLayout layout, + VkImageLayout layout, const vk::ImageView *imageView, ImageOrBufferViewSubresourceSerial serial, const WriteDescriptorDescs &writeDescriptorDescs); @@ -2161,6 +2229,7 @@ class FramebufferDesc void releaseCachedObject(Renderer *renderer) { UNREACHABLE(); } void releaseCachedObject(ContextVk *contextVk); bool valid() const { return mIsValid; } + bool hasValidCachedObject(ContextVk *contextVk) const; private: void reset(); @@ -2277,16 +2346,21 @@ class SharedCacheKeyManager void clear(); // The following APIs are expected to be used for assertion only - bool containsKey(const SharedCacheKeyT &key) const; bool empty() const { return mSharedCacheKeys.empty(); } - void assertAllEntriesDestroyed(); + bool allValidEntriesAreCached(ContextVk *contextVk) const; private: - size_t updateEmptySlotBits(); + bool addKeyToEmptySlot(const SharedCacheKeyT &key); + bool releaseUnusedKeysAndReplaceWithKey(const SharedCacheKeyT &key); + void addKeyToNewSlot(const SharedCacheKeyT &key); + + bool containsKeyWithOwnerEqual(const SharedCacheKeyT &key) const; + void assertAllEntriesDestroyed() const; // Tracks an array of cache keys with refcounting. Note this owns one refcount of // SharedCacheKeyT object. std::deque mSharedCacheKeys; + SharedCacheKeyT mLastAddedSharedCacheKey; // To speed up searching for available slot in the mSharedCacheKeys, we use bitset to track // available (i.e, empty) slot @@ -2297,7 +2371,12 @@ class SharedCacheKeyManager }; using FramebufferCacheManager = SharedCacheKeyManager; +template <> +void FramebufferCacheManager::addKey(const SharedFramebufferCacheKey &key); + using DescriptorSetCacheManager = SharedCacheKeyManager; +template <> +void DescriptorSetCacheManager::addKey(const SharedDescriptorSetCacheKey &key); } // namespace vk } // namespace rx @@ -2389,9 +2468,9 @@ enum class VulkanCacheType Sampler, SamplerYcbcrConversion, DescriptorSetLayout, - DriverUniformsDescriptors, - TextureDescriptors, UniformsAndXfbDescriptors, + TextureDescriptors, + UniformBuffersDescriptors, ShaderResourcesDescriptors, Framebuffer, DescriptorMetaCache, @@ -2611,13 +2690,6 @@ struct GraphicsPipelineDescCompleteHash return key.hash(vk::GraphicsPipelineSubset::Complete); } }; -struct GraphicsPipelineDescVertexInputHash -{ - size_t operator()(const rx::vk::GraphicsPipelineDesc &key) const - { - return key.hash(vk::GraphicsPipelineSubset::VertexInput); - } -}; struct GraphicsPipelineDescShadersHash { size_t operator()(const rx::vk::GraphicsPipelineDesc &key) const @@ -2625,13 +2697,6 @@ struct GraphicsPipelineDescShadersHash return key.hash(vk::GraphicsPipelineSubset::Shaders); } }; -struct GraphicsPipelineDescFragmentOutputHash -{ - size_t operator()(const rx::vk::GraphicsPipelineDesc &key) const - { - return key.hash(vk::GraphicsPipelineSubset::FragmentOutput); - } -}; struct ComputePipelineDescKeyEqual { @@ -2649,14 +2714,6 @@ struct GraphicsPipelineDescCompleteKeyEqual return first.keyEqual(second, vk::GraphicsPipelineSubset::Complete); } }; -struct GraphicsPipelineDescVertexInputKeyEqual -{ - size_t operator()(const rx::vk::GraphicsPipelineDesc &first, - const rx::vk::GraphicsPipelineDesc &second) const - { - return first.keyEqual(second, vk::GraphicsPipelineSubset::VertexInput); - } -}; struct GraphicsPipelineDescShadersKeyEqual { size_t operator()(const rx::vk::GraphicsPipelineDesc &first, @@ -2665,14 +2722,6 @@ struct GraphicsPipelineDescShadersKeyEqual return first.keyEqual(second, vk::GraphicsPipelineSubset::Shaders); } }; -struct GraphicsPipelineDescFragmentOutputKeyEqual -{ - size_t operator()(const rx::vk::GraphicsPipelineDesc &first, - const rx::vk::GraphicsPipelineDesc &second) const - { - return first.keyEqual(second, vk::GraphicsPipelineSubset::FragmentOutput); - } -}; // Derive the KeyEqual and GraphicsPipelineSubset enum from the Hash struct template @@ -2682,25 +2731,12 @@ struct GraphicsPipelineCacheTypeHelper static constexpr vk::GraphicsPipelineSubset kSubset = vk::GraphicsPipelineSubset::Complete; }; -template <> -struct GraphicsPipelineCacheTypeHelper -{ - using KeyEqual = GraphicsPipelineDescVertexInputKeyEqual; - static constexpr vk::GraphicsPipelineSubset kSubset = vk::GraphicsPipelineSubset::VertexInput; -}; template <> struct GraphicsPipelineCacheTypeHelper { using KeyEqual = GraphicsPipelineDescShadersKeyEqual; static constexpr vk::GraphicsPipelineSubset kSubset = vk::GraphicsPipelineSubset::Shaders; }; -template <> -struct GraphicsPipelineCacheTypeHelper -{ - using KeyEqual = GraphicsPipelineDescFragmentOutputKeyEqual; - static constexpr vk::GraphicsPipelineSubset kSubset = - vk::GraphicsPipelineSubset::FragmentOutput; -}; // Compute Pipeline Cache implementation // TODO(aannestrand): Add cache trimming/eviction. @@ -2781,23 +2817,12 @@ class GraphicsPipelineCache final : public HasCacheStats; -using VertexInputGraphicsPipelineCache = GraphicsPipelineCache; using ShadersGraphicsPipelineCache = GraphicsPipelineCache; -using FragmentOutputGraphicsPipelineCache = - GraphicsPipelineCache; class DescriptorSetLayoutCache final : angle::NonCopyable { @@ -2865,7 +2887,7 @@ class SamplerCache final : public HasCacheStats SamplerCache(); ~SamplerCache() override; - void destroy(vk::Renderer *renderer); + void destroy(vk::Renderer *renderer, bool orphanReferencedSamplers); angle::Result getSampler(ContextVk *contextVk, const vk::SamplerDesc &desc, @@ -2883,7 +2905,7 @@ class SamplerYcbcrConversionCache final SamplerYcbcrConversionCache(); ~SamplerYcbcrConversionCache() override; - void destroy(vk::Renderer *renderer); + void destroy(vk::Renderer *renderer, bool orphanConversionInfo); angle::Result getSamplerYcbcrConversion(vk::ErrorContext *context, const vk::YcbcrConversionDesc &ycbcrConversionDesc, @@ -2917,7 +2939,7 @@ class DescriptorSetCache final : angle::NonCopyable void clear() { mPayload.clear(); } - bool getDescriptorSet(const vk::DescriptorSetDesc &desc, T *descriptorSetOut) + bool getDescriptorSet(const vk::DescriptorSetDesc &desc, T *descriptorSetOut) const { auto iter = mPayload.find(desc); if (iter != mPayload.end()) @@ -3005,6 +3027,11 @@ class UpdateDescriptorSetsBuilder final : angle::NonCopyable // Returns the number of written descriptor sets. uint32_t flushDescriptorSetUpdates(VkDevice device); + void updateWriteDescriptorSet(vk::Renderer *renderer, + const vk::DescriptorSetDescBuilder &descriptorSetDescBuilder, + const vk::WriteDescriptorDescs &writeDescriptorDescs, + const VkDescriptorSet descriptorSet); + private: // Manage the storage for VkDescriptorBufferInfo and VkDescriptorImageInfo. The storage is not // required to be continuous, but the requested allocation from allocate() call must be diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp index ea96d53be9a..4102464caaa 100644 --- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp @@ -7,6 +7,10 @@ // Helper functions for the Vulkan Caps. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/vk_caps_utils.h" #include @@ -186,12 +190,12 @@ bool CanSupportYuvInternalFormat(const Renderer *renderer) const Format &twoPlane8bitYuvFormat = renderer->getFormat(GL_G8_B8R8_2PLANE_420_UNORM_ANGLE); bool twoPlane8bitYuvFormatSupported = renderer->hasImageFormatFeatureBits( - twoPlane8bitYuvFormat.getActualImageFormatID(vk::ImageAccess::SampleOnly), + twoPlane8bitYuvFormat.getActualImageFormatID(vk::ImageFormatSupport::SampleOnly), VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); const Format &threePlane8bitYuvFormat = renderer->getFormat(GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE); bool threePlane8bitYuvFormatSupported = renderer->hasImageFormatFeatureBits( - threePlane8bitYuvFormat.getActualImageFormatID(vk::ImageAccess::SampleOnly), + threePlane8bitYuvFormat.getActualImageFormatID(vk::ImageFormatSupport::SampleOnly), VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); return twoPlane8bitYuvFormatSupported && threePlane8bitYuvFormatSupported; @@ -352,9 +356,6 @@ void Renderer::ensureCapsInitialized() const mNativeLimitations.emulatedAstc = true; } - // Vulkan doesn't support ASTC 3D block textures, which are required by - // GL_OES_texture_compression_astc. - mNativeExtensions.textureCompressionAstcOES = false; // Enable KHR_texture_compression_astc_sliced_3d mNativeExtensions.textureCompressionAstcSliced3dKHR = mNativeExtensions.textureCompressionAstcLdrKHR && @@ -362,8 +363,12 @@ void Renderer::ensureCapsInitialized() const // Enable KHR_texture_compression_astc_hdr mNativeExtensions.textureCompressionAstcHdrKHR = - mNativeExtensions.textureCompressionAstcLdrKHR && - getFeatures().supportsTextureCompressionAstcHdr.enabled; + mNativeExtensions.textureCompressionAstcLdrKHR && supportsAstcHdr(); + + // Enable GL_OES_texture_compression_astc + mNativeExtensions.textureCompressionAstcOES = getFeatures().supportsAstc3d.enabled && + mNativeExtensions.textureCompressionAstcHdrKHR && + mNativeExtensions.textureCompressionAstcLdrKHR; // Enable EXT_compressed_ETC1_RGB8_sub_texture mNativeExtensions.compressedETC1RGB8SubTextureEXT = @@ -385,6 +390,8 @@ void Renderer::ensureCapsInitialized() const getFeatures().enableMultisampledRenderToTexture.enabled; mNativeExtensions.multisampledRenderToTexture2EXT = getFeatures().enableMultisampledRenderToTexture.enabled; + mNativeExtensions.multiviewMultisampledRenderToTextureOVR = + getFeatures().supportsMultiviewMultisampleRenderToTexture.enabled; mNativeExtensions.textureStorageMultisample2dArrayOES = (limitsVk.standardSampleLocations == VK_TRUE); mNativeExtensions.copyTextureCHROMIUM = true; @@ -418,8 +425,7 @@ void Renderer::ensureCapsInitialized() const mNativeLimitations.multidrawEmulated = false; // Enable EXT_base_instance - mNativeExtensions.baseInstanceEXT = true; - mNativeLimitations.baseInstanceEmulated = false; + mNativeExtensions.baseInstanceEXT = true; // Enable ANGLE_base_vertex_base_instance mNativeExtensions.baseVertexBaseInstanceANGLE = true; @@ -637,8 +643,20 @@ void Renderer::ensureCapsInitialized() const // Always enable ANGLE_rgbx_internal_format to expose GL_RGBX8_ANGLE except for Samsung. mNativeExtensions.rgbxInternalFormatANGLE = mFeatures.supportsAngleRgbxInternalFormat.enabled; - // https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html - mNativeCaps.maxElementIndex = std::numeric_limits::max() - 1; + // Enable EXT_texture_compression_astc_decode_mode + mNativeExtensions.textureCompressionAstcDecodeModeEXT = + mNativeExtensions.textureCompressionAstcLdrKHR && + getFeatures().supportsAstcDecodeMode.enabled; + mNativeExtensions.textureCompressionAstcDecodeModeRgb9e5EXT = + mNativeExtensions.textureCompressionAstcLdrKHR && + getFeatures().supportsAstcDecodeModeRgb9e5.enabled; + + // The Vulkan limit maxDrawIndexedIndexValue has a minimum required value of 2^32-1. + // OpenGL ES 3.2 requires a minimum value of 2^24-1 for GL_MAX_ELEMENT_INDEX. + // 2^30-1 is chosen as an arbitrary value larger than the minimum requirement, but + // avoiding integer limits and overflows in math. + mNativeCaps.maxElementIndex = (1 << 30) - 1; + mNativeCaps.max3DTextureSize = rx::LimitToInt(limitsVk.maxImageDimension3D); mNativeCaps.max2DTextureSize = std::min(limitsVk.maxFramebufferWidth, limitsVk.maxImageDimension2D); @@ -721,11 +739,9 @@ void Renderer::ensureCapsInitialized() const rx::LimitToInt(limitsVk.maxComputeWorkGroupInvocations); mNativeCaps.maxComputeSharedMemorySize = rx::LimitToInt(limitsVk.maxComputeSharedMemorySize); - GLuint maxUniformBlockSize = limitsVk.maxUniformBufferRange; - - // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size - // currently), on AMD the maxUniformBufferRange is near uint32_t max. - maxUniformBlockSize = std::min(0x10000u, maxUniformBlockSize); + const GLuint maxUniformBlockSize = std::min( + rx::LimitToIntAnd(limitsVk.maxUniformBufferRange, mMaxBufferMemorySizeLimit), + gl::IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE); const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * kComponentsPerVector); const GLuint maxUniformComponents = maxUniformVectors * kComponentsPerVector; @@ -738,7 +754,6 @@ void Renderer::ensureCapsInitialized() const { mNativeCaps.maxShaderUniformComponents[shaderType] = maxUniformComponents; } - mNativeCaps.maxUniformLocations = maxUniformVectors; const int32_t maxPerStageUniformBuffers = rx::LimitToInt( limitsVk.maxPerStageDescriptorUniformBuffers - kReservedPerStageDefaultUniformBindingCount); @@ -759,8 +774,18 @@ void Renderer::ensureCapsInitialized() const // Note that Vulkan currently implements textures as combined image+samplers, so the limit is // the minimum of supported samplers and sampled images. - const uint32_t maxPerStageTextures = std::min(limitsVk.maxPerStageDescriptorSamplers, - limitsVk.maxPerStageDescriptorSampledImages); + uint32_t maxPerStageTextures = std::min(limitsVk.maxPerStageDescriptorSamplers, + limitsVk.maxPerStageDescriptorSampledImages); + + // Many devices support a huge number of samplers (millions) and every one needs a uniform + // location, either generated by ANGLE or assigned by the user. Limit the number of samplers per + // stage to something reasonable, which in turn also lowers the number of uniform locations. + // This isn't expected to have any practical effect on real apps/users, but is instead to keep + // tests for these limits (e.g., dEQP, end2end) within reason in terms of shader program sizes + // and compilation times. + constexpr uint32_t kMaximumSamplersPerStage = 4096; + maxPerStageTextures = std::min(kMaximumSamplersPerStage, maxPerStageTextures); + const uint32_t maxCombinedTextures = std::min(limitsVk.maxDescriptorSetSamplers, limitsVk.maxDescriptorSetSampledImages); for (gl::ShaderType shaderType : gl::AllShaderTypes()) @@ -769,6 +794,10 @@ void Renderer::ensureCapsInitialized() const } mNativeCaps.maxCombinedTextureImageUnits = rx::LimitToInt(maxCombinedTextures); + // All uniforms (variables + samplers) consume a location when a shader is linked. + mNativeCaps.maxUniformLocations = + LimitToInt(maxUniformVectors + LimitToInt(maxPerStageTextures)); + uint32_t maxPerStageStorageBuffers = limitsVk.maxPerStageDescriptorStorageBuffers; uint32_t maxVertexStageStorageBuffers = maxPerStageStorageBuffers; uint32_t maxCombinedStorageBuffers = limitsVk.maxDescriptorSetStorageBuffers; @@ -843,7 +872,8 @@ void Renderer::ensureCapsInitialized() const // Emulated as storage buffers, atomic counter buffers have the same size limit. However, the // limit is a signed integer and values above int max will end up as a negative size. The // storage buffer size is just capped to int unconditionally. - uint32_t maxStorageBufferRange = rx::LimitToInt(limitsVk.maxStorageBufferRange); + uint32_t maxStorageBufferRange = + rx::LimitToIntAnd(limitsVk.maxStorageBufferRange, mMaxBufferMemorySizeLimit); if (mFeatures.limitMaxStorageBufferSize.enabled) { constexpr uint32_t kStorageBufferLimit = 256 * 1024 * 1024; @@ -871,9 +901,10 @@ void Renderer::ensureCapsInitialized() const mNativeCaps.maxAtomicCounterBufferSize = maxStorageBufferRange; // There is no particular limit to how many atomic counters there can be, other than the size of - // a storage buffer. We nevertheless limit this to something reasonable (4096 arbitrarily). + // a storage buffer. We nevertheless limit this to something reasonable; 32 arbitrarily, which + // is more than what most GLES drivers support (8, the minimum required value). const int32_t maxAtomicCounters = - std::min(4096, maxStorageBufferRange / sizeof(uint32_t)); + std::min(32, maxStorageBufferRange / sizeof(uint32_t)); for (gl::ShaderType shaderType : gl::AllShaderTypes()) { mNativeCaps.maxShaderAtomicCounters[shaderType] = maxAtomicCounters; @@ -1088,12 +1119,26 @@ void Renderer::ensureCapsInitialized() const // GL_RGBA32UI Y Y mNativeExtensions.textureBufferOES = true; mNativeExtensions.textureBufferEXT = true; - mNativeCaps.maxTextureBufferSize = rx::LimitToInt(limitsVk.maxTexelBufferElements); - if (getFeatures().padBuffersToMaxVertexAttribStride.enabled) + { - // Account for buffer padding - mNativeCaps.maxTextureBufferSize -= getMaxVertexAttribStride(); + // GLES 3.2's limit for GL_MAX_TEXTURE_BUFFER_SIZE is 65536. Note that this limit is about + // how many texels are addressable by the texture buffer. + // + // Aiming for 256MB of memory (see https://gitlab.freedesktop.org/mesa/mesa/-/issues/9862), + // a buffer of RGBA32 values would need 16 million elements, which is chosen by ANGLE. This + // is far above the minimum requirement. Note also that it could correspond to a 4k*4k 2D + // texture. + // + // Note additionally that mMaxBufferMemorySizeLimit is a value in bytes, so it's divided by + // 16 (for RGBA32) too to get to the maximum texel count that is allowed. Vulkan's required + // limit for maxMemoryAllocationSize is 2^30 for this value, which divided by 16 is 64 + // million, which is always higher than the desired value of 16 million. + constexpr uint32_t kTextureBufferLimit = 16 * 1024 * 1024; + ASSERT(kTextureBufferLimit < mMaxBufferMemorySizeLimit); + mNativeCaps.maxTextureBufferSize = + std::min(limitsVk.maxTexelBufferElements, kTextureBufferLimit); } + mNativeCaps.textureBufferOffsetAlignment = rx::LimitToInt(limitsVk.minTexelBufferOffsetAlignment); @@ -1142,6 +1187,7 @@ void Renderer::ensureCapsInitialized() const bool tessellationShaderEnabled = mFeatures.supportsTransformFeedbackExtension.enabled && (mFeatures.supportsPrimitivesGeneratedQuery.enabled || + mFeatures.allowPipelineStatisticsForPrimitivesGeneratedQuery.enabled || mFeatures.exposeNonConformantExtensionsAndVersions.enabled); mNativeExtensions.tessellationShaderEXT = tessellationShaderEnabled; mNativeExtensions.tessellationShaderOES = tessellationShaderEnabled; @@ -1194,9 +1240,11 @@ void Renderer::ensureCapsInitialized() const // Geometry shaders are required for ES 3.2. if (mPhysicalDeviceFeatures.geometryShader) { - bool geometryShaderEnabled = mFeatures.supportsTransformFeedbackExtension.enabled && - (mFeatures.supportsPrimitivesGeneratedQuery.enabled || - mFeatures.exposeNonConformantExtensionsAndVersions.enabled); + bool geometryShaderEnabled = + mFeatures.supportsTransformFeedbackExtension.enabled && + (mFeatures.supportsPrimitivesGeneratedQuery.enabled || + mFeatures.allowPipelineStatisticsForPrimitivesGeneratedQuery.enabled || + mFeatures.exposeNonConformantExtensionsAndVersions.enabled); mNativeExtensions.geometryShaderEXT = geometryShaderEnabled; mNativeExtensions.geometryShaderOES = geometryShaderEnabled; mNativeCaps.maxFramebufferLayers = rx::LimitToInt(limitsVk.maxFramebufferLayers); @@ -1255,7 +1303,9 @@ void Renderer::ensureCapsInitialized() const // After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally // implemented to support the geometry shader. Until then, EXT_clip_cull_distance is enabled // only in the experimental cases. - if (mPhysicalDeviceFeatures.shaderClipDistance && + if ((mFeatures.supportsClipCullDistanceInGSAndTS.enabled || + (!mNativeExtensions.geometryShaderAny() && !mNativeExtensions.tessellationShaderAny())) && + mPhysicalDeviceFeatures.shaderClipDistance && limitsVk.maxClipDistances >= kMaxClipDistancePerSpec) { // Do not enable GL_APPLE_clip_distance for Samsung devices. @@ -1323,34 +1373,70 @@ void Renderer::ensureCapsInitialized() const // GL_QCOM_shading_rate mNativeExtensions.shadingRateQCOM = mFeatures.supportsFragmentShadingRate.enabled; + // GL_EXT_fragment_shading_rate + if (mFeatures.supportFragmentShadingRateExtExtensions.enabled) + { + mNativeExtensions.fragmentShadingRateEXT = mFeatures.supportsFragmentShadingRate.enabled; + mNativeExtensions.fragmentShadingRatePrimitiveEXT = + mFeatures.supportsPrimitiveFragmentShadingRate.enabled; + } + // GL_QCOM_framebuffer_foveated mNativeExtensions.framebufferFoveatedQCOM = mFeatures.supportsFoveatedRendering.enabled; // GL_QCOM_texture_foveated mNativeExtensions.textureFoveatedQCOM = mFeatures.supportsFoveatedRendering.enabled; // GL_ANGLE_shader_pixel_local_storage - mNativeExtensions.shaderPixelLocalStorageANGLE = true; - if (getFeatures().supportsShaderFramebufferFetch.enabled && mIsColorFramebufferFetchCoherent) - { - mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = true; - mNativePLSOptions.type = ShPixelLocalStorageType::FramebufferFetch; - mNativePLSOptions.fragmentSyncType = ShFragmentSynchronizationType::Automatic; - } - else if (getFeatures().supportsFragmentShaderPixelInterlock.enabled) - { - // Use shader images with VK_EXT_fragment_shader_interlock, instead of attachments, if - // they're our only option to be coherent. - mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = true; - mNativePLSOptions.type = ShPixelLocalStorageType::ImageLoadStore; - // GL_ARB_fragment_shader_interlock compiles to SPV_EXT_fragment_shader_interlock. - mNativePLSOptions.fragmentSyncType = - ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL; - mNativePLSOptions.supportsNativeRGBA8ImageFormats = true; - } - else + // + // NOTE: + // * The Vulkan backend limits the ES version to 2.0 when drawBuffersIndexed is not supported. + // * The frontend disables all ES 3.x extensions when the context version is too low for them. + // * This means it is impossible on Vulkan to have pixel local storage without DBI. + if (mFeatures.supportShaderPixelLocalStorageAngle.enabled && + mNativeExtensions.drawBuffersIndexedAny()) { - mNativePLSOptions.type = ShPixelLocalStorageType::FramebufferFetch; - ASSERT(mNativePLSOptions.fragmentSyncType == ShFragmentSynchronizationType::NotSupported); + mNativeExtensions.shaderPixelLocalStorageANGLE = true; + + // Prefer framebuffer fetch in almost all cases if it's available, except if framebuffer + // fetch isn't coherent *and* fragment shader pixel interlock is available. This is the case + // on many desktop GPUs. Fall back to using shader images with interlock to provide coherent + // PLS in this case. + bool fetchIsNonCoherentButHasInterlock = + !mIsColorFramebufferFetchCoherent && + getFeatures().supportsFragmentShaderPixelInterlock.enabled; + + if (getFeatures().supportsShaderFramebufferFetch.enabled && + !fetchIsNonCoherentButHasInterlock) + { + // Input attachments are the preferred implementation for PLS on Vulkan. + mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = + mIsColorFramebufferFetchCoherent; + mNativePLSOptions.type = ShPixelLocalStorageType::FramebufferFetch; + mNativePLSOptions.fragmentSyncType = mIsColorFramebufferFetchCoherent + ? ShFragmentSynchronizationType::Automatic + : ShFragmentSynchronizationType::NotSupported; + } + else + { + mNativePLSOptions.type = ShPixelLocalStorageType::ImageLoadStore; + mNativePLSOptions.supportsNativeRGBA8ImageFormats = true; + + if (getFeatures().supportsFragmentShaderPixelInterlock.enabled) + { + // Use shader images with VK_EXT_fragment_shader_interlock, instead of input + // attachments, if they're our only option to be coherent. + mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = true; + // GL_ARB_fragment_shader_interlock compiles to SPV_EXT_fragment_shader_interlock. + mNativePLSOptions.fragmentSyncType = + ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL; + } + else + { + // If fragment shader pixel interlock isn't supported, then only non-coherent PLS is + // supported. + mNativePLSOptions.fragmentSyncType = ShFragmentSynchronizationType::NotSupported; + } + } } // If framebuffer fetch is to be enabled/used, cap maxColorAttachments/maxDrawBuffers to @@ -1412,13 +1498,23 @@ void Renderer::ensureCapsInitialized() const mNativeExtensions.logicOpANGLE = mPhysicalDeviceFeatures.logicOp == VK_TRUE; - mNativeExtensions.YUVTargetEXT = mFeatures.supportsExternalFormatResolve.enabled; + mNativeExtensions.YUVTargetEXT = mFeatures.supportsYuvTarget.enabled; mNativeExtensions.textureStorageCompressionEXT = mFeatures.supportsImageCompressionControl.enabled; mNativeExtensions.EGLImageStorageCompressionEXT = mFeatures.supportsImageCompressionControl.enabled; + if (mFeatures.supportsFragmentShadingRate.enabled) + { + mNativeCaps.fragmentShadingRateProperties + .fragmentShadingRateWithShaderDepthStencilWritesSupport = static_cast( + mFragmentShadingRateProperties.fragmentShadingRateNonTrivialCombinerOps); + } + + // GL_OES_compressed_paletted_texture + mNativeExtensions.compressedPalettedTextureOES = true; + // Log any missing extensions required for GLES 3.2. LogMissingExtensionsForGLES32(mNativeExtensions); } @@ -1511,9 +1607,9 @@ egl::Config GenerateDefaultConfig(DisplayVk *display, gl::Version maxSupportedESVersion = renderer->getMaxSupportedESVersion(); // ES3 features are required to emulate ES1 - EGLint es1Support = (maxSupportedESVersion.major >= 3 ? EGL_OPENGL_ES_BIT : 0); - EGLint es2Support = (maxSupportedESVersion.major >= 2 ? EGL_OPENGL_ES2_BIT : 0); - EGLint es3Support = (maxSupportedESVersion.major >= 3 ? EGL_OPENGL_ES3_BIT : 0); + EGLint es1Support = (maxSupportedESVersion >= gl::ES_3_0 ? EGL_OPENGL_ES_BIT : 0); + EGLint es2Support = (maxSupportedESVersion >= gl::ES_2_0 ? EGL_OPENGL_ES2_BIT : 0); + EGLint es3Support = (maxSupportedESVersion >= gl::ES_3_0 ? EGL_OPENGL_ES3_BIT : 0); egl::Config config; @@ -1587,7 +1683,6 @@ egl::ConfigSet GenerateConfigs(const GLenum *colorFormats, gl::SupportedSampleSet colorSampleCounts; gl::SupportedSampleSet depthStencilSampleCounts; - gl::SupportedSampleSet sampleCounts; const VkPhysicalDeviceLimits &limits = display->getRenderer()->getPhysicalDeviceProperties().limits; @@ -1603,9 +1698,7 @@ egl::ConfigSet GenerateConfigs(const GLenum *colorFormats, colorSampleCounts.insert(0); depthStencilSampleCounts.insert(0); - std::set_intersection(colorSampleCounts.begin(), colorSampleCounts.end(), - depthStencilSampleCounts.begin(), depthStencilSampleCounts.end(), - std::inserter(sampleCounts, sampleCounts.begin())); + gl::SupportedSampleSet sampleCounts = colorSampleCounts & depthStencilSampleCounts; egl::ConfigSet configSet; @@ -1635,7 +1728,7 @@ egl::ConfigSet GenerateConfigs(const GLenum *colorFormats, configSampleCounts = &depthStencilSampleCounts; } - for (EGLint sampleCount : *configSampleCounts) + for (EGLint sampleCount : configSampleCounts->sampleCounts()) { egl::Config config = GenerateDefaultConfig(display, colorFormatInfo, depthStencilFormatInfo, sampleCount); diff --git a/src/libANGLE/renderer/vulkan/vk_cl_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cl_utils.cpp index 1704aae922d..6c3c800505c 100644 --- a/src/libANGLE/renderer/vulkan/vk_cl_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_cl_utils.cpp @@ -15,6 +15,29 @@ namespace rx namespace cl_vk { +// Give two cl::BufferRect regions, calculate a series of the buffer copy regions that can be used +// in vulkan copy buffer command. +std::vector CalculateRectCopyRegions(const cl::BufferRect &srcRect, + const cl::BufferRect &dstRect) +{ + // For copying the buffer rect region should be the same + ASSERT(srcRect.getExtents() == dstRect.getExtents()); + std::vector copyRegions; + + for (size_t slice = 0; slice < srcRect.mSize.depth; slice++) + { + for (size_t row = 0; row < srcRect.mSize.height; row++) + { + VkBufferCopy copyRegion = {}; + copyRegion.size = srcRect.mSize.width * srcRect.mElementSize; + copyRegion.srcOffset = srcRect.getRowOffset(slice, row); + copyRegion.dstOffset = dstRect.getRowOffset(slice, row); + copyRegions.push_back(copyRegion); + } + } + return copyRegions; +} + VkExtent3D GetExtent(const cl::Extents &extent) { VkExtent3D vkExtent{}; @@ -83,9 +106,13 @@ VkImageViewType GetImageViewType(cl::MemObjectType memObjectType) VkMemoryPropertyFlags GetMemoryPropertyFlags(cl::MemFlags memFlags) { - // TODO: http://anglebug.com/42267018 VkMemoryPropertyFlags propFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + if (memFlags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR)) + { + propFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + } + if (memFlags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR)) { propFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; @@ -94,13 +121,24 @@ VkMemoryPropertyFlags GetMemoryPropertyFlags(cl::MemFlags memFlags) return propFlags; } -VkBufferUsageFlags GetBufferUsageFlags(cl::MemFlags memFlags) +VkBufferUsageFlags GetBufferUsageFlags(cl::MemFlags memFlags, bool physicalAddressing) { // The buffer usage flags don't particularly affect the buffer in any known drivers, use all the // bits that ANGLE needs. - return VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | - VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; + VkBufferUsageFlags usageFlags = + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; + + if (physicalAddressing) + { + // VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT specifies that the buffer can be used to + // retrieve a buffer device address via vkGetBufferDeviceAddress and use that address to + // access the buffer's memory from a shader. + usageFlags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + } + + return usageFlags; } } // namespace cl_vk diff --git a/src/libANGLE/renderer/vulkan/vk_cl_utils.h b/src/libANGLE/renderer/vulkan/vk_cl_utils.h index b201a4218a0..6dee6a40891 100644 --- a/src/libANGLE/renderer/vulkan/vk_cl_utils.h +++ b/src/libANGLE/renderer/vulkan/vk_cl_utils.h @@ -21,12 +21,15 @@ namespace rx { namespace cl_vk { +std::vector CalculateRectCopyRegions(const cl::BufferRect &srcRect, + const cl::BufferRect &dstRect); + VkExtent3D GetExtent(const cl::Extents &extent); VkOffset3D GetOffset(const cl::Offset &offset); VkImageType GetImageType(cl::MemObjectType memObjectType); VkImageViewType GetImageViewType(cl::MemObjectType memObjectType); VkMemoryPropertyFlags GetMemoryPropertyFlags(cl::MemFlags memFlags); -VkBufferUsageFlags GetBufferUsageFlags(cl::MemFlags memFlags); +VkBufferUsageFlags GetBufferUsageFlags(cl::MemFlags memFlags, bool physicalAddressing); } // namespace cl_vk } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/vk_format_map.json b/src/libANGLE/renderer/vulkan/vk_format_map.json index b0bbf2a28e3..c9066959343 100644 --- a/src/libANGLE/renderer/vulkan/vk_format_map.json +++ b/src/libANGLE/renderer/vulkan/vk_format_map.json @@ -167,8 +167,30 @@ "ASTC_12x10_SRGB_BLOCK": "VK_FORMAT_ASTC_12x10_SRGB_BLOCK", "ASTC_12x12_UNORM_BLOCK": "VK_FORMAT_ASTC_12x12_UNORM_BLOCK", "ASTC_12x12_SRGB_BLOCK": "VK_FORMAT_ASTC_12x12_SRGB_BLOCK", + "ASTC_3x3x3_UNORM_BLOCK": "VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT", + "ASTC_4x3x3_UNORM_BLOCK": "VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT", + "ASTC_4x4x3_UNORM_BLOCK": "VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT", + "ASTC_4x4x4_UNORM_BLOCK": "VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT", + "ASTC_5x4x4_UNORM_BLOCK": "VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT", + "ASTC_5x5x4_UNORM_BLOCK": "VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT", + "ASTC_5x5x5_UNORM_BLOCK": "VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT", + "ASTC_6x5x5_UNORM_BLOCK": "VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT", + "ASTC_6x6x5_UNORM_BLOCK": "VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT", + "ASTC_6x6x6_UNORM_BLOCK": "VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT", + "ASTC_3x3x3_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT", + "ASTC_4x3x3_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT", + "ASTC_4x4x3_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT", + "ASTC_4x4x4_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT", + "ASTC_5x4x4_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT", + "ASTC_5x5x4_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT", + "ASTC_5x5x5_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT", + "ASTC_6x5x5_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT", + "ASTC_6x6x5_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT", + "ASTC_6x6x6_UNORM_SRGB_BLOCK": "VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT", "G8_B8_R8_3PLANE_420_UNORM": "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM", "G8_B8R8_2PLANE_420_UNORM": "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM", + "R10X6G10X6B10X6A10X6_UNORM": "VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16", + "G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16": "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16", "EXTERNAL0": "VK_FORMAT_UNDEFINED", "EXTERNAL1": "VK_FORMAT_UNDEFINED", "EXTERNAL2": "VK_FORMAT_UNDEFINED", @@ -209,6 +231,9 @@ "L4A4_UNORM": { "image": "R8G8_UNORM" }, + "R5G6B5_UNORM": { + "image": "B5G6R5_UNORM" + }, "R4G4B4A4_UNORM": { "image": "R8G8B8A8_UNORM" }, @@ -235,7 +260,7 @@ "image": "R8G8B8A8_UNORM_SRGB" }, "D24_UNORM_X8_UINT": { - "image": ["D24_UNORM_S8_UINT", "D32_FLOAT_S8X24_UINT"] + "image": ["D24_UNORM_S8_UINT", "D32_FLOAT", "D32_FLOAT_S8X24_UINT"] }, "D32_UNORM": { "buffer": "NONE", @@ -611,6 +636,66 @@ "ASTC_12x12_SRGB_BLOCK": { "image": "R8G8B8A8_UNORM_SRGB" }, + "ASTC_3x3x3_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_4x3x3_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_4x4x3_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_4x4x4_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_5x4x4_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_5x5x4_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_5x5x5_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_6x5x5_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_6x6x5_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_6x6x6_UNORM_BLOCK": { + "image": "R8G8B8A8_UNORM" + }, + "ASTC_3x3x3_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_4x3x3_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_4x4x3_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_4x4x4_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_5x4x4_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_5x5x4_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_5x5x5_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_6x5x5_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_6x6x5_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, + "ASTC_6x6x6_UNORM_SRGB_BLOCK": { + "image": "R8G8B8A8_UNORM_SRGB" + }, "PALETTE4_R8G8B8_UNORM": { "image": "R8G8B8A8_UNORM" diff --git a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp index 8152fa93d9a..24f270253d2 100644 --- a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp +++ b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp @@ -119,7 +119,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x10_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x10_SRGB_BLOCK; @@ -133,7 +136,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x10_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x10_UNORM_BLOCK; @@ -147,7 +153,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x5_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x5_SRGB_BLOCK; @@ -161,7 +170,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x5_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x5_UNORM_BLOCK; @@ -175,7 +187,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x6_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x6_SRGB_BLOCK; @@ -189,7 +204,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x6_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x6_UNORM_BLOCK; @@ -203,7 +221,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x8_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x8_SRGB_BLOCK; @@ -217,7 +238,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_10x8_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_10x8_UNORM_BLOCK; @@ -231,7 +255,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_12x10_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_12x10_SRGB_BLOCK; @@ -245,7 +272,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_12x10_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_12x10_UNORM_BLOCK; @@ -259,7 +289,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_12x12_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_12x12_SRGB_BLOCK; @@ -273,7 +306,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_12x12_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_12x12_UNORM_BLOCK; @@ -283,19 +319,71 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::ASTC_3x3x3_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_3x3x3_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_3x3x3_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_3x3x3_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_4x3x3_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_4x3x3_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_4x3x3_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_4x3x3_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_4x4_SRGB_BLOCK: @@ -303,7 +391,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_4x4_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_4x4_SRGB_BLOCK; @@ -317,7 +408,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_4x4_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_4x4_UNORM_BLOCK; @@ -327,19 +421,71 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::ASTC_4x4x3_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_4x4x3_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_4x4x3_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_4x4x3_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_4x4x4_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_4x4x4_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_4x4x4_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_4x4x4_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_5x4_SRGB_BLOCK: @@ -347,7 +493,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_5x4_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_5x4_SRGB_BLOCK; @@ -361,7 +510,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_5x4_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_5x4_UNORM_BLOCK; @@ -371,11 +523,37 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::ASTC_5x4x4_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_5x4x4_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_5x4x4_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_5x4x4_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_5x5_SRGB_BLOCK: @@ -383,7 +561,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_5x5_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_5x5_SRGB_BLOCK; @@ -397,7 +578,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_5x5_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_5x5_UNORM_BLOCK; @@ -407,19 +591,71 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::ASTC_5x5x4_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_5x5x4_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_5x5x4_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_5x5x4_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_5x5x5_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_5x5x5_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_5x5x5_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_5x5x5_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_6x5_SRGB_BLOCK: @@ -427,7 +663,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_6x5_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_6x5_SRGB_BLOCK; @@ -441,7 +680,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_6x5_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_6x5_UNORM_BLOCK; @@ -451,11 +693,37 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::ASTC_6x5x5_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_6x5x5_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_6x5x5_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_6x5x5_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_6x6_SRGB_BLOCK: @@ -463,7 +731,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_6x6_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_6x6_SRGB_BLOCK; @@ -477,7 +748,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_6x6_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_6x6_UNORM_BLOCK; @@ -487,19 +761,71 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::ASTC_6x6x5_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_6x6x5_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_6x6x5_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_6x6x5_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_6x6x6_UNORM_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_RGBA_ASTC_6x6x6_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_6x6x6_UNORM_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_6x6x6_UNORM_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK: - // This format is not implemented in Vulkan. + mIntendedGLFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK, nullptr}, +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::ASTC_8x5_SRGB_BLOCK: @@ -507,7 +833,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_8x5_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_8x5_SRGB_BLOCK; @@ -521,7 +850,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_8x5_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_8x5_UNORM_BLOCK; @@ -535,7 +867,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_8x6_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_8x6_SRGB_BLOCK; @@ -549,7 +884,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_8x6_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_8x6_UNORM_BLOCK; @@ -563,7 +901,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_8x8_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_8x8_SRGB_BLOCK; @@ -577,7 +918,10 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ASTC_8x8_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; +#ifdef ANGLE_HAS_ASTCENC + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, +#endif + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ASTC_8x8_UNORM_BLOCK; @@ -849,7 +1193,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::D24_UNORM_S8_UINT, nullptr}, - {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}}; + {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::D24_UNORM_S8_UINT; @@ -864,7 +1209,9 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::D24_UNORM_X8_UINT, nullptr}, {angle::FormatID::D24_UNORM_S8_UINT, nullptr}, - {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}}; + {angle::FormatID::D32_FLOAT, nullptr}, + {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::D24_UNORM_X8_UINT; @@ -888,7 +1235,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}, - {angle::FormatID::D24_UNORM_S8_UINT, nullptr}}; + {angle::FormatID::D24_UNORM_S8_UINT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::D32_FLOAT_S8X24_UINT; @@ -903,7 +1251,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::D24_UNORM_X8_UINT, nullptr}, {angle::FormatID::D24_UNORM_S8_UINT, nullptr}, - {angle::FormatID::D32_FLOAT, nullptr}}; + {angle::FormatID::D32_FLOAT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::NONE; @@ -918,7 +1267,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::EAC_R11G11_SNORM_BLOCK, nullptr}, {angle::FormatID::R16G16_SNORM, nullptr}, - {angle::FormatID::R16G16_FLOAT, nullptr}}; + {angle::FormatID::R16G16_FLOAT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::EAC_R11G11_SNORM_BLOCK; @@ -933,7 +1283,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::EAC_R11G11_UNORM_BLOCK, nullptr}, {angle::FormatID::R16G16_UNORM, nullptr}, - {angle::FormatID::R16G16_FLOAT, nullptr}}; + {angle::FormatID::R16G16_FLOAT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::EAC_R11G11_UNORM_BLOCK; @@ -948,7 +1299,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::EAC_R11_SNORM_BLOCK, nullptr}, {angle::FormatID::R16_SNORM, nullptr}, - {angle::FormatID::R16_FLOAT, nullptr}}; + {angle::FormatID::R16_FLOAT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::EAC_R11_SNORM_BLOCK; @@ -963,7 +1315,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::EAC_R11_UNORM_BLOCK, nullptr}, {angle::FormatID::R16_UNORM, nullptr}, - {angle::FormatID::R16_FLOAT, nullptr}}; + {angle::FormatID::R16_FLOAT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::EAC_R11_UNORM_BLOCK; @@ -982,7 +1335,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK, nullptr}, {angle::FormatID::R8G8B8A8_UNORM, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::NONE; @@ -997,7 +1351,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK, nullptr}, {angle::FormatID::R8G8B8A8_UNORM_SRGB, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK; @@ -1012,7 +1367,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK, nullptr}, {angle::FormatID::R8G8B8A8_UNORM, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK; @@ -1026,7 +1382,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}}; + {angle::FormatID::R8G8B8A8_UNORM_SRGB, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK; @@ -1040,7 +1397,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK; @@ -1055,7 +1413,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK, nullptr}, {angle::FormatID::R8G8B8A8_UNORM_SRGB, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK; @@ -1070,7 +1429,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK, nullptr}, {angle::FormatID::R8G8B8A8_UNORM, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK; @@ -1167,6 +1527,17 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) mVertexLoadRequiresConversion = false; break; + case angle::FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + mIntendedGLFormat = GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE; + mActualSampleOnlyImageFormatID = + angle::FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16; + mImageInitializerFunction = nullptr; + mActualBufferFormatID = angle::FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; + break; + case angle::FormatID::G8_B8R8_2PLANE_420_UNORM: mIntendedGLFormat = GL_G8_B8R8_2PLANE_420_UNORM_ANGLE; mActualSampleOnlyImageFormatID = angle::FormatID::G8_B8R8_2PLANE_420_UNORM; @@ -1438,6 +1809,16 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) mVertexLoadRequiresConversion = true; break; + case angle::FormatID::R10X6G10X6B10X6A10X6_UNORM: + mIntendedGLFormat = GL_R10X6G10X6B10X6A10X6_UNORM_ANGLEX; + mActualSampleOnlyImageFormatID = angle::FormatID::R10X6G10X6B10X6A10X6_UNORM; + mImageInitializerFunction = nullptr; + mActualBufferFormatID = angle::FormatID::R10X6G10X6B10X6A10X6_UNORM; + mVkBufferFormatIsPacked = false; + mVertexLoadFunction = nullptr; + mVertexLoadRequiresConversion = false; + break; + case angle::FormatID::R11G11B10_FLOAT: mIntendedGLFormat = GL_R11F_G11F_B10F; mActualSampleOnlyImageFormatID = angle::FormatID::R11G11B10_FLOAT; @@ -1536,7 +1917,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R16G16B16_FLOAT, nullptr}, {angle::FormatID::R16G16B16A16_FLOAT, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -1555,7 +1937,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R16G16B16_SINT, nullptr}, {angle::FormatID::R16G16B16A16_SINT, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -1578,7 +1961,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) {angle::FormatID::R32G32B32_FLOAT, nullptr}, {angle::FormatID::R32G32B32A32_FLOAT, Initialize4ComponentData}}; + gl::Float32One>}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -1624,7 +2008,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R16G16B16_UINT, nullptr}, {angle::FormatID::R16G16B16A16_UINT, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -1647,7 +2032,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) {angle::FormatID::R32G32B32_FLOAT, nullptr}, {angle::FormatID::R32G32B32A32_FLOAT, Initialize4ComponentData}}; + gl::Float32One>}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -1950,7 +2336,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) {angle::FormatID::R32G32B32_FLOAT, nullptr}, {angle::FormatID::R32G32B32A32_FLOAT, Initialize4ComponentData}}; + gl::Float32One>}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -1972,7 +2359,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) {angle::FormatID::R32G32B32_SINT, nullptr}, {angle::FormatID::R32G32B32A32_SINT, Initialize4ComponentData}}; + 0x00000001>}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::R32G32B32_SINT; @@ -2006,7 +2394,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) {angle::FormatID::R32G32B32_UINT, nullptr}, {angle::FormatID::R32G32B32A32_UINT, Initialize4ComponentData}}; + 0x00000001>}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::R32G32B32_UINT; @@ -2196,7 +2585,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R4G4B4A4_UNORM, nullptr}, - {angle::FormatID::R8G8B8A8_UNORM, nullptr}}; + {angle::FormatID::R8G8B8A8_UNORM, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::R4G4B4A4_UNORM; @@ -2210,7 +2600,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) { static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R5G5B5A1_UNORM, nullptr}, - {angle::FormatID::A1R5G5B5_UNORM, nullptr}}; + {angle::FormatID::A1R5G5B5_UNORM, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::R5G5B5A1_UNORM; @@ -2220,13 +2611,18 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) break; case angle::FormatID::R5G6B5_UNORM: - mIntendedGLFormat = GL_RGB565; - mActualSampleOnlyImageFormatID = angle::FormatID::R5G6B5_UNORM; - mImageInitializerFunction = nullptr; - mActualBufferFormatID = angle::FormatID::R5G6B5_UNORM; - mVkBufferFormatIsPacked = true; - mVertexLoadFunction = CopyNativeVertexData; - mVertexLoadRequiresConversion = false; + mIntendedGLFormat = GL_RGB565; + { + static constexpr ImageFormatInitInfo kInfo[] = { + {angle::FormatID::R5G6B5_UNORM, nullptr}, + {angle::FormatID::B5G6R5_UNORM, nullptr}, + }; + initImageFallback(renderer, kInfo, ArraySize(kInfo)); + } + mActualBufferFormatID = angle::FormatID::R5G6B5_UNORM; + mVkBufferFormatIsPacked = true; + mVertexLoadFunction = CopyNativeVertexData; + mVertexLoadRequiresConversion = false; break; case angle::FormatID::R8G8B8A8_SINT: @@ -2341,7 +2737,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R8G8B8_SINT, nullptr}, {angle::FormatID::R8G8B8A8_SINT, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -2360,7 +2757,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R8G8B8_SNORM, nullptr}, {angle::FormatID::R8G8B8A8_SNORM, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -2397,7 +2795,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R8G8B8_UINT, nullptr}, {angle::FormatID::R8G8B8A8_UINT, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -2416,7 +2815,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R8G8B8_UNORM, nullptr}, {angle::FormatID::R8G8B8A8_UNORM, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } { @@ -2436,7 +2836,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::R8G8B8_UNORM_SRGB, nullptr}, {angle::FormatID::R8G8B8A8_UNORM_SRGB, - Initialize4ComponentData}}; + Initialize4ComponentData}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::R8G8B8_UNORM_SRGB; @@ -2639,7 +3040,8 @@ void Format::initialize(Renderer *renderer, const angle::Format &angleFormat) static constexpr ImageFormatInitInfo kInfo[] = { {angle::FormatID::S8_UINT, nullptr}, {angle::FormatID::D24_UNORM_S8_UINT, nullptr}, - {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}}; + {angle::FormatID::D32_FLOAT_S8X24_UINT, nullptr}, + }; initImageFallback(renderer, kInfo, ArraySize(kInfo)); } mActualBufferFormatID = angle::FormatID::S8_UINT; @@ -2730,16 +3132,36 @@ VkFormat GetVkFormatFromFormatID(const Renderer *renderer, angle::FormatID forma {angle::FormatID::ASTC_12x10_UNORM_BLOCK, VK_FORMAT_ASTC_12x10_UNORM_BLOCK}, {angle::FormatID::ASTC_12x12_SRGB_BLOCK, VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, {angle::FormatID::ASTC_12x12_UNORM_BLOCK, VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, + {angle::FormatID::ASTC_3x3x3_UNORM_BLOCK, VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT}, + {angle::FormatID::ASTC_4x3x3_UNORM_BLOCK, VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT}, {angle::FormatID::ASTC_4x4_SRGB_BLOCK, VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, {angle::FormatID::ASTC_4x4_UNORM_BLOCK, VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, + {angle::FormatID::ASTC_4x4x3_UNORM_BLOCK, VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT}, + {angle::FormatID::ASTC_4x4x4_UNORM_BLOCK, VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT}, {angle::FormatID::ASTC_5x4_SRGB_BLOCK, VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, {angle::FormatID::ASTC_5x4_UNORM_BLOCK, VK_FORMAT_ASTC_5x4_UNORM_BLOCK}, + {angle::FormatID::ASTC_5x4x4_UNORM_BLOCK, VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT}, {angle::FormatID::ASTC_5x5_SRGB_BLOCK, VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, {angle::FormatID::ASTC_5x5_UNORM_BLOCK, VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, + {angle::FormatID::ASTC_5x5x4_UNORM_BLOCK, VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT}, + {angle::FormatID::ASTC_5x5x5_UNORM_BLOCK, VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT}, {angle::FormatID::ASTC_6x5_SRGB_BLOCK, VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, {angle::FormatID::ASTC_6x5_UNORM_BLOCK, VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, + {angle::FormatID::ASTC_6x5x5_UNORM_BLOCK, VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT}, {angle::FormatID::ASTC_6x6_SRGB_BLOCK, VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, {angle::FormatID::ASTC_6x6_UNORM_BLOCK, VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, + {angle::FormatID::ASTC_6x6x5_UNORM_BLOCK, VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT}, + {angle::FormatID::ASTC_6x6x6_UNORM_BLOCK, VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT}, + {angle::FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK, VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT}, {angle::FormatID::ASTC_8x5_SRGB_BLOCK, VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, {angle::FormatID::ASTC_8x5_UNORM_BLOCK, VK_FORMAT_ASTC_8x5_UNORM_BLOCK}, {angle::FormatID::ASTC_8x6_SRGB_BLOCK, VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, @@ -2791,6 +3213,8 @@ VkFormat GetVkFormatFromFormatID(const Renderer *renderer, angle::FormatID forma {angle::FormatID::EXTERNAL5, VK_FORMAT_UNDEFINED}, {angle::FormatID::EXTERNAL6, VK_FORMAT_UNDEFINED}, {angle::FormatID::EXTERNAL7, VK_FORMAT_UNDEFINED}, + {angle::FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16}, {angle::FormatID::G8_B8R8_2PLANE_420_UNORM, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM}, {angle::FormatID::G8_B8_R8_3PLANE_420_UNORM, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM}, {angle::FormatID::NONE, VK_FORMAT_UNDEFINED}, @@ -2800,6 +3224,7 @@ VkFormat GetVkFormatFromFormatID(const Renderer *renderer, angle::FormatID forma {angle::FormatID::R10G10B10A2_UINT, VK_FORMAT_A2B10G10R10_UINT_PACK32}, {angle::FormatID::R10G10B10A2_UNORM, VK_FORMAT_A2B10G10R10_UNORM_PACK32}, {angle::FormatID::R10G10B10A2_USCALED, VK_FORMAT_A2B10G10R10_USCALED_PACK32}, + {angle::FormatID::R10X6G10X6B10X6A10X6_UNORM, VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16}, {angle::FormatID::R11G11B10_FLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32}, {angle::FormatID::R16G16B16A16_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT}, {angle::FormatID::R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT}, @@ -2908,26 +3333,66 @@ angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat) return angle::FormatID::ASTC_12x12_SRGB_BLOCK; case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return angle::FormatID::ASTC_12x12_UNORM_BLOCK; + case VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_3x3x3_UNORM_BLOCK; + case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK; + case VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_4x3x3_UNORM_BLOCK; + case VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK; case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return angle::FormatID::ASTC_4x4_SRGB_BLOCK; case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return angle::FormatID::ASTC_4x4_UNORM_BLOCK; + case VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_4x4x3_UNORM_BLOCK; + case VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK; + case VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_4x4x4_UNORM_BLOCK; + case VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK; case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return angle::FormatID::ASTC_5x4_SRGB_BLOCK; case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return angle::FormatID::ASTC_5x4_UNORM_BLOCK; + case VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_5x4x4_UNORM_BLOCK; + case VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK; case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return angle::FormatID::ASTC_5x5_SRGB_BLOCK; case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return angle::FormatID::ASTC_5x5_UNORM_BLOCK; + case VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_5x5x4_UNORM_BLOCK; + case VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK; + case VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_5x5x5_UNORM_BLOCK; + case VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK; case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return angle::FormatID::ASTC_6x5_SRGB_BLOCK; case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return angle::FormatID::ASTC_6x5_UNORM_BLOCK; + case VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_6x5x5_UNORM_BLOCK; + case VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK; case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return angle::FormatID::ASTC_6x6_SRGB_BLOCK; case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return angle::FormatID::ASTC_6x6_UNORM_BLOCK; + case VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_6x6x5_UNORM_BLOCK; + case VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK; + case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT: + return angle::FormatID::ASTC_6x6x6_UNORM_BLOCK; + case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT: + return angle::FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK; case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return angle::FormatID::ASTC_8x5_SRGB_BLOCK; case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: @@ -3014,6 +3479,8 @@ angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat) return angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK; case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + return angle::FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16; case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: return angle::FormatID::G8_B8R8_2PLANE_420_UNORM; case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: @@ -3032,6 +3499,8 @@ angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat) return angle::FormatID::R10G10B10A2_UNORM; case VK_FORMAT_A2B10G10R10_USCALED_PACK32: return angle::FormatID::R10G10B10A2_USCALED; + case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: + return angle::FormatID::R10X6G10X6B10X6A10X6_UNORM; case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return angle::FormatID::R11G11B10_FLOAT; case VK_FORMAT_R16G16B16A16_SFLOAT: diff --git a/src/libANGLE/renderer/vulkan/vk_format_utils.cpp b/src/libANGLE/renderer/vulkan/vk_format_utils.cpp index 28a4e28c418..1525f198f0b 100644 --- a/src/libANGLE/renderer/vulkan/vk_format_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_format_utils.cpp @@ -6,6 +6,10 @@ // vk_format_utils: // Helper for Vulkan format code. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "image_util/loadimage.h" @@ -48,19 +52,43 @@ void FillTextureFormatCaps(vk::Renderer *renderer, if (outTextureCaps->renderbuffer) { + VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {}; + imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; + imageFormatInfo.format = GetVkFormatFromFormatID(renderer, formatID); + imageFormatInfo.type = VK_IMAGE_TYPE_2D; + imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageFormatInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; if (hasColorAttachmentFeatureBit) { - vk_gl::AddSampleCounts(physicalDeviceLimits.framebufferColorSampleCounts, - &outTextureCaps->sampleCounts); + imageFormatInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } if (hasDepthAttachmentFeatureBit) { - // Some drivers report different depth and stencil sample counts. We'll AND those - // counts together, limiting all depth and/or stencil formats to the lower number of - // sample counts. - vk_gl::AddSampleCounts((physicalDeviceLimits.framebufferDepthSampleCounts & - physicalDeviceLimits.framebufferStencilSampleCounts), - &outTextureCaps->sampleCounts); + imageFormatInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + } + + VkImageFormatProperties2 imageFormatProperties2 = {}; + imageFormatProperties2.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; + VkResult result = vkGetPhysicalDeviceImageFormatProperties2( + renderer->getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties2); + if (result == VK_SUCCESS) + { + if (hasColorAttachmentFeatureBit) + { + vk_gl::AddSampleCounts(imageFormatProperties2.imageFormatProperties.sampleCounts & + physicalDeviceLimits.framebufferColorSampleCounts, + &outTextureCaps->sampleCounts); + } + if (hasDepthAttachmentFeatureBit) + { + // Some drivers report different depth and stencil sample counts. We'll AND those + // counts together, limiting all depth and/or stencil formats to the lower number of + // sample counts. + vk_gl::AddSampleCounts((imageFormatProperties2.imageFormatProperties.sampleCounts & + physicalDeviceLimits.framebufferDepthSampleCounts & + physicalDeviceLimits.framebufferStencilSampleCounts), + &outTextureCaps->sampleCounts); + } } } } @@ -120,7 +148,6 @@ Format::Format() mActualSampleOnlyImageFormatID(angle::FormatID::NONE), mActualRenderableImageFormatID(angle::FormatID::NONE), mActualBufferFormatID(angle::FormatID::NONE), - mActualCompressedBufferFormatID(angle::FormatID::NONE), mImageInitializerFunction(nullptr), mTextureLoadFunctions(), mRenderableTextureLoadFunctions(), @@ -136,6 +163,15 @@ Format::Format() void Format::initImageFallback(Renderer *renderer, const ImageFormatInitInfo *info, int numInfo) { size_t skip = renderer->getFeatures().forceFallbackFormat.enabled ? 1 : 0; + + // For R5G6B5, the fallback B5G6R5 is for performance reasons, and only used for some + // platforms by enabling the proper feature flag. Therefore, forcing format fallback should + // not apply to R5G6B5. + skip += (info[0].format == angle::FormatID::R5G6B5_UNORM && + renderer->getFeatures().preferBGR565ToRGB565.enabled) + ? 1 + : 0; + SupportTest testFunction = HasNonRenderableTextureFormatSupport; const angle::Format &format = angle::Format::Get(info[0].format); if (format.isInt() || (format.isFloat() && format.redBits >= 32)) @@ -178,22 +214,11 @@ void Format::initBufferFallback(Renderer *renderer, mVertexLoadFunction = info[i].vertexLoadFunction; mVertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion; } - - if (renderer->getFeatures().compressVertexData.enabled && compressedStartIndex < numInfo) - { - int i = FindSupportedFormat(renderer, info, compressedStartIndex, numInfo, - HasFullBufferFormatSupport); - - mActualCompressedBufferFormatID = info[i].format; - mVkCompressedBufferFormatIsPacked = info[i].vkFormatIsPacked; - mCompressedVertexLoadFunction = info[i].vertexLoadFunction; - mCompressedVertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion; - } } -size_t Format::getVertexInputAlignment(bool compressed) const +size_t Format::getVertexInputAlignment() const { - const angle::Format &bufferFormat = getActualBufferFormat(compressed); + const angle::Format &bufferFormat = getActualBufferFormat(); size_t pixelBytes = bufferFormat.pixelBytes; return mVkBufferFormatIsPacked ? pixelBytes : (pixelBytes / bufferFormat.channelCount); } @@ -236,6 +261,14 @@ void FormatTable::initialize(Renderer *renderer, gl::TextureCapsMap *outTextureC const auto intendedFormatID = static_cast(formatIndex); const angle::Format &intendedAngleFormat = angle::Format::Get(intendedFormatID); + // Skip querying device caps for ASTC 3D formats if VK_EXT_texture_compression_astc_3d is + // not enabled + if (renderer->getFeatures().supportsAstc3d.enabled == false && + IsASTC3DFormat(intendedFormatID)) + { + continue; + } + format.initialize(renderer, intendedAngleFormat); format.mIntendedFormatID = intendedFormatID; @@ -319,6 +352,7 @@ angle::FormatID ExternalFormatTable::getOrAllocExternalFormatID(uint64_t externa { ERR() << "ANGLE only suports maximum " << kMaxExternalFormatCountSupported << " external renderable formats"; + ASSERT(false); return angle::FormatID::NONE; } @@ -467,7 +501,12 @@ bool HasFullTextureFormatSupport(vk::Renderer *renderer, angle::FormatID formatI case angle::FormatID::R32G32B32A32_FLOAT: break; default: - kBitsColorFull |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; + const angle::Format &format = angle::Format::Get(formatID); + if (!format.isYUV) + { + // EXT_yuv_target does not support blend anyway, so no need to ask for blend bit. + kBitsColorFull |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; + } break; } @@ -493,6 +532,39 @@ bool IsETCFormat(angle::FormatID formatID) return formatID >= angle::FormatID::EAC_R11G11_SNORM_BLOCK && formatID <= angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK; } + +// Checks if it is an ASTC 3D texture format +bool IsASTC3DFormat(angle::FormatID formatID) +{ + switch (formatID) + { + case angle::FormatID::ASTC_3x3x3_UNORM_BLOCK: + case angle::FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_4x3x3_UNORM_BLOCK: + case angle::FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_4x4x3_UNORM_BLOCK: + case angle::FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_4x4x4_UNORM_BLOCK: + case angle::FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_5x4x4_UNORM_BLOCK: + case angle::FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_5x5x4_UNORM_BLOCK: + case angle::FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_5x5x5_UNORM_BLOCK: + case angle::FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_6x5x5_UNORM_BLOCK: + case angle::FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_6x6x5_UNORM_BLOCK: + case angle::FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK: + case angle::FormatID::ASTC_6x6x6_UNORM_BLOCK: + case angle::FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK: + return true; + + default: + return false; + } +} + // Checks if it is a BC texture format bool IsBCFormat(angle::FormatID formatID) { @@ -575,8 +647,7 @@ angle::FormatID GetTranscodeBCFormatID(angle::FormatID formatID) VkFormat AdjustASTCFormatForHDR(const vk::Renderer *renderer, VkFormat vkFormat) { ASSERT(renderer != nullptr); - const bool hdrEnabled = renderer->getFeatures().supportsTextureCompressionAstcHdr.enabled; - + const bool hdrEnabled = renderer->supportsAstcHdr(); if (hdrEnabled == false) { return vkFormat; diff --git a/src/libANGLE/renderer/vulkan/vk_format_utils.h b/src/libANGLE/renderer/vulkan/vk_format_utils.h index e6826325dff..3db4abc8797 100644 --- a/src/libANGLE/renderer/vulkan/vk_format_utils.h +++ b/src/libANGLE/renderer/vulkan/vk_format_utils.h @@ -36,7 +36,7 @@ class Renderer; // VkFormat values in range [0, kNumVkFormats) are used as indices in various tables. constexpr uint32_t kNumVkFormats = 185; -enum ImageAccess +enum ImageFormatSupport { SampleOnly, Renderable, @@ -85,9 +85,9 @@ class Format final : private angle::NonCopyable const angle::Format &getIntendedFormat() const { return angle::Format::Get(mIntendedFormatID); } // The actual Image format is used to implement the front-end format for Texture/Renderbuffers. - const angle::Format &getActualImageFormat(ImageAccess access) const + const angle::Format &getActualImageFormat(ImageFormatSupport support) const { - return angle::Format::Get(getActualImageFormatID(access)); + return angle::Format::Get(getActualImageFormatID(support)); } angle::FormatID getActualRenderableImageFormatID() const @@ -103,47 +103,39 @@ class Format final : private angle::NonCopyable return GetVkFormatFromFormatID(renderer, mActualRenderableImageFormatID); } - angle::FormatID getActualImageFormatID(ImageAccess access) const + angle::FormatID getActualImageFormatID(ImageFormatSupport support) const { - return ImageAccess::Renderable == access ? mActualRenderableImageFormatID - : mActualSampleOnlyImageFormatID; + return support == ImageFormatSupport::Renderable ? mActualRenderableImageFormatID + : mActualSampleOnlyImageFormatID; } - VkFormat getActualImageVkFormat(const Renderer *renderer, ImageAccess access) const + VkFormat getActualImageVkFormat(const Renderer *renderer, ImageFormatSupport support) const { - return GetVkFormatFromFormatID(renderer, getActualImageFormatID(access)); + return GetVkFormatFromFormatID(renderer, getActualImageFormatID(support)); } - LoadImageFunctionInfo getTextureLoadFunction(ImageAccess access, GLenum type) const + LoadImageFunctionInfo getTextureLoadFunction(ImageFormatSupport support, GLenum type) const { - return ImageAccess::Renderable == access ? mRenderableTextureLoadFunctions(type) - : mTextureLoadFunctions(type); + return support == ImageFormatSupport::Renderable ? mRenderableTextureLoadFunctions(type) + : mTextureLoadFunctions(type); } // The actual Buffer format is used to implement the front-end format for Buffers. This format // is used by vertex buffers as well as texture buffers. Note that all formats required for // GL_EXT_texture_buffer have mandatory support for vertex buffers in Vulkan, so they won't be // using an emulated format. - const angle::Format &getActualBufferFormat(bool compressed) const + const angle::Format &getActualBufferFormat() const { - return angle::Format::Get(compressed ? mActualCompressedBufferFormatID - : mActualBufferFormatID); + return angle::Format::Get(mActualBufferFormatID); } - VkFormat getActualBufferVkFormat(const Renderer *renderer, bool compressed) const + VkFormat getActualBufferVkFormat(const Renderer *renderer) const { - return GetVkFormatFromFormatID( - renderer, compressed ? mActualCompressedBufferFormatID : mActualBufferFormatID); + return GetVkFormatFromFormatID(renderer, mActualBufferFormatID); } - VertexCopyFunction getVertexLoadFunction(bool compressed) const - { - return compressed ? mCompressedVertexLoadFunction : mVertexLoadFunction; - } + VertexCopyFunction getVertexLoadFunction() const { return mVertexLoadFunction; } - bool getVertexLoadRequiresConversion(bool compressed) const - { - return compressed ? mCompressedVertexLoadRequiresConversion : mVertexLoadRequiresConversion; - } + bool getVertexLoadRequiresConversion() const { return mVertexLoadRequiresConversion; } // |intendedGLFormat| always correponds to a valid GLenum type. For types that don't have a // corresponding GLenum we do our best to specify a GLenum that is "close". @@ -157,16 +149,10 @@ class Format final : private angle::NonCopyable return mActualSampleOnlyImageFormatID != mActualRenderableImageFormatID; } - bool canCompressBufferData() const - { - return mActualCompressedBufferFormatID != angle::FormatID::NONE && - mActualBufferFormatID != mActualCompressedBufferFormatID; - } - // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input // Description'. - size_t getVertexInputAlignment(bool compressed) const; + size_t getVertexInputAlignment() const; private: friend class FormatTable; @@ -186,7 +172,6 @@ class Format final : private angle::NonCopyable angle::FormatID mActualSampleOnlyImageFormatID; angle::FormatID mActualRenderableImageFormatID; angle::FormatID mActualBufferFormatID; - angle::FormatID mActualCompressedBufferFormatID; InitializeTextureDataFunction mImageInitializerFunction; LoadFunctionMap mTextureLoadFunctions; @@ -282,6 +267,8 @@ bool HasFullTextureFormatSupport(vk::Renderer *renderer, angle::FormatID formatI bool HasNonRenderableTextureFormatSupport(vk::Renderer *renderer, angle::FormatID formatID); // Checks if it is a ETC texture format bool IsETCFormat(angle::FormatID formatID); +// Checks if it is an ASTC texture format +bool IsASTC3DFormat(angle::FormatID formatID); // Checks if it is a BC texture format bool IsBCFormat(angle::FormatID formatID); diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp index 046fe6f6df7..a5bc94a5f39 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp +++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp @@ -6,6 +6,10 @@ // vk_helpers: // Helper utility classes that manage Vulkan resources. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/vk_helpers.h" #include "common/aligned_memory.h" @@ -47,827 +51,15 @@ constexpr VkClearDepthStencilValue kRobustInitDepthStencilValue = {1.0f, 0}; constexpr VkImageAspectFlags kDepthStencilAspects = VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; -// Information useful for buffer related barriers -struct BufferMemoryBarrierData -{ - VkPipelineStageFlags pipelineStageFlags; - // EventStage::InvalidEnum indicates don't use VkEvent for barrier(i.e., use pipelineBarrier - // instead) - EventStage eventStage; -}; -// clang-format off -constexpr angle::PackedEnumMap kBufferMemoryBarrierData = { - {PipelineStage::TopOfPipe, {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, EventStage::InvalidEnum}}, - {PipelineStage::DrawIndirect, {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, EventStage::VertexInput}}, - {PipelineStage::VertexInput, {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, EventStage::VertexInput}}, - {PipelineStage::VertexShader, {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, EventStage::VertexShader}}, - {PipelineStage::TessellationControl, {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, EventStage::InvalidEnum}}, - {PipelineStage::TessellationEvaluation, {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, EventStage::InvalidEnum}}, - {PipelineStage::GeometryShader, {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, EventStage::InvalidEnum}}, - {PipelineStage::TransformFeedback, {VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, EventStage::TransformFeedbackWrite}}, - {PipelineStage::FragmentShadingRate, {0, EventStage::InvalidEnum}}, - {PipelineStage::EarlyFragmentTest, {0, EventStage::InvalidEnum}}, - {PipelineStage::FragmentShader, {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, EventStage::FragmentShader}}, - {PipelineStage::LateFragmentTest, {0, EventStage::InvalidEnum}}, - {PipelineStage::ColorAttachmentOutput, {0, EventStage::InvalidEnum}}, - {PipelineStage::ComputeShader, {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, EventStage::ComputeShader}}, - {PipelineStage::Transfer, {VK_PIPELINE_STAGE_TRANSFER_BIT, EventStage::InvalidEnum}}, - {PipelineStage::BottomOfPipe, BufferMemoryBarrierData{VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, EventStage::InvalidEnum}}, - {PipelineStage::Host, {VK_PIPELINE_STAGE_HOST_BIT, EventStage::InvalidEnum}}, -}; - -constexpr gl::ShaderMap kPipelineStageShaderMap = { - {gl::ShaderType::Vertex, PipelineStage::VertexShader}, - {gl::ShaderType::TessControl, PipelineStage::TessellationControl}, - {gl::ShaderType::TessEvaluation, PipelineStage::TessellationEvaluation}, - {gl::ShaderType::Geometry, PipelineStage::GeometryShader}, - {gl::ShaderType::Fragment, PipelineStage::FragmentShader}, - {gl::ShaderType::Compute, PipelineStage::ComputeShader}, -}; - -constexpr ImageLayoutToMemoryBarrierDataMap kImageMemoryBarrierData = { - { - ImageLayout::Undefined, - ImageMemoryBarrierData{ - "Undefined", - VK_IMAGE_LAYOUT_UNDEFINED, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - // Transition to: we don't expect to transition into Undefined. - 0, - // Transition from: there's no data in the image to care about. - 0, - ResourceAccess::ReadOnly, - PipelineStage::InvalidEnum, - // We do not directly use this layout in SetEvent. We transit to other layout before using - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::ColorWrite, - ImageMemoryBarrierData{ - "ColorWrite", - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::ColorAttachmentOutput, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::ColorWriteAndInput, - ImageMemoryBarrierData{ - "ColorWriteAndInput", - VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::ColorAttachmentOutput, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::MSRTTEmulationColorUnresolveAndResolve, - ImageMemoryBarrierData{ - "MSRTTEmulationColorUnresolveAndResolve", - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::FragmentShader, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthWriteStencilWrite, - ImageMemoryBarrierData{ - "DepthWriteStencilWrite", - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - kAllDepthStencilPipelineStageFlags, - kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::EarlyFragmentTest, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthStencilWriteAndInput, - ImageMemoryBarrierData{ - "DepthStencilWriteAndInput", - VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, - kAllDepthStencilPipelineStageFlags, - kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::EarlyFragmentTest, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthWriteStencilRead, - ImageMemoryBarrierData{ - "DepthWriteStencilRead", - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - kAllDepthStencilPipelineStageFlags, - kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::EarlyFragmentTest, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthWriteStencilReadFragmentShaderStencilRead, - ImageMemoryBarrierData{ - "DepthWriteStencilReadFragmentShaderStencilRead", - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::EarlyFragmentTest, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthWriteStencilReadAllShadersStencilRead, - ImageMemoryBarrierData{ - "DepthWriteStencilReadAllShadersStencilRead", - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, - kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::VertexShader, - EventStage::AttachmentAndAllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::DepthReadStencilWrite, - ImageMemoryBarrierData{ - "DepthReadStencilWrite", - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - kAllDepthStencilPipelineStageFlags, - kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::EarlyFragmentTest, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthReadStencilWriteFragmentShaderDepthRead, - ImageMemoryBarrierData{ - "DepthReadStencilWriteFragmentShaderDepthRead", - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::EarlyFragmentTest, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthReadStencilWriteAllShadersDepthRead, - ImageMemoryBarrierData{ - "DepthReadStencilWriteAllShadersDepthRead", - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, - kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::VertexShader, - EventStage::AttachmentAndAllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::DepthReadStencilRead, - ImageMemoryBarrierData{ - "DepthReadStencilRead", - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, - kAllDepthStencilPipelineStageFlags, - kAllDepthStencilPipelineStageFlags, - // Transition to: all reads must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::EarlyFragmentTest, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - - { - ImageLayout::DepthReadStencilReadFragmentShaderRead, - ImageMemoryBarrierData{ - "DepthReadStencilReadFragmentShaderRead", - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::EarlyFragmentTest, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthReadStencilReadAllShadersRead, - ImageMemoryBarrierData{ - "DepthReadStencilReadAllShadersRead", - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, - kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, - kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::VertexShader, - EventStage::AttachmentAndAllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::ColorWriteFragmentShaderFeedback, - ImageMemoryBarrierData{ - "ColorWriteFragmentShaderFeedback", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::FragmentShader, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::ColorWriteAllShadersFeedback, - ImageMemoryBarrierData{ - "ColorWriteAllShadersFeedback", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::VertexShader, - EventStage::AttachmentAndAllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::DepthStencilFragmentShaderFeedback, - ImageMemoryBarrierData{ - "DepthStencilFragmentShaderFeedback", - VK_IMAGE_LAYOUT_GENERAL, - kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::FragmentShader, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::DepthStencilAllShadersFeedback, - ImageMemoryBarrierData{ - "DepthStencilAllShadersFeedback", - VK_IMAGE_LAYOUT_GENERAL, - kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags, - kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::VertexShader, - EventStage::AttachmentAndAllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::DepthStencilResolve, - ImageMemoryBarrierData{ - "DepthStencilResolve", - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - // Note: depth/stencil resolve uses color output stage and mask! - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::ColorAttachmentOutput, - EventStage::Attachment, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::MSRTTEmulationDepthStencilUnresolveAndResolve, - ImageMemoryBarrierData{ - "MSRTTEmulationDepthStencilUnresolveAndResolve", - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - // Note: depth/stencil resolve uses color output stage and mask! - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::FragmentShader, - EventStage::AttachmentAndFragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::Present, - ImageMemoryBarrierData{ - "Present", - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - // Transition to: do not delay execution of commands in the second synchronization - // scope. Allow layout transition to be delayed until present semaphore is signaled. - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - // Transition from: use same stages as in Acquire Image Semaphore stage mask in order to - // build a dependency chain from the Acquire Image Semaphore to the layout transition's - // first synchronization scope. - kSwapchainAcquireImageWaitStageFlags, - // Transition to: vkQueuePresentKHR automatically performs the appropriate memory barriers: - // - // > Any writes to memory backing the images referenced by the pImageIndices and - // > pSwapchains members of pPresentInfo, that are available before vkQueuePresentKHR - // > is executed, are automatically made visible to the read access performed by the - // > presentation engine. - 0, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::BottomOfPipe, - // We do not directly use this layout in SetEvent. - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::SharedPresent, - ImageMemoryBarrierData{ - "SharedPresent", - VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, - // All currently possible stages for SharedPresent - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_MEMORY_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::BottomOfPipe, - EventStage::AttachmentAndFragmentShaderAndTransfer, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::ExternalPreInitialized, - ImageMemoryBarrierData{ - "ExternalPreInitialized", - // Binding a VkImage with an initial layout of VK_IMAGE_LAYOUT_UNDEFINED to external - // memory whose content has already been defined does not make the content undefined - // (see 12.8.1. External Resource Sharing). - // - // Note that for external memory objects, if the content is already defined, the - // ownership rules imply that the first operation on the texture must be a call to - // glWaitSemaphoreEXT that grants ownership of the image and informs us of the true - // layout. If the content is not already defined, the first operation may not be a - // glWaitSemaphore, but in this case undefined layout is appropriate. - VK_IMAGE_LAYOUT_UNDEFINED, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - // Transition to: we don't expect to transition into PreInitialized. - 0, - // Transition from: all writes must finish before barrier. - VK_ACCESS_MEMORY_WRITE_BIT, - ResourceAccess::ReadOnly, - PipelineStage::InvalidEnum, - // We do not directly use this layout in SetEvent. We transit to internal layout before using - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::ExternalShadersReadOnly, - ImageMemoryBarrierData{ - "ExternalShadersReadOnly", - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::TopOfPipe, - // We do not directly use this layout in SetEvent. We transit to internal layout before using - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::ExternalShadersWrite, - ImageMemoryBarrierData{ - "ExternalShadersWrite", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::TopOfPipe, - // We do not directly use this layout in SetEvent. We transit to internal layout before using - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::ForeignAccess, - ImageMemoryBarrierData{ - "ForeignAccess", - VK_IMAGE_LAYOUT_GENERAL, - // Transition to: we don't expect to transition into ForeignAccess, that's done at - // submission time by the CommandQueue; the following value doesn't matter. - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - // Transition to: see dstStageMask - 0, - // Transition from: all writes must finish before barrier; it is unknown how the foreign - // entity has access the memory. - VK_ACCESS_MEMORY_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::TopOfPipe, - // We do not directly use this layout in SetEvent. We transit to internal layout before using - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::TransferSrc, - ImageMemoryBarrierData{ - "TransferSrc", - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - // Transition to: all reads must happen after barrier. - VK_ACCESS_TRANSFER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::Transfer, - EventStage::Transfer, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::TransferDst, - ImageMemoryBarrierData{ - "TransferDst", - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - // Transition to: all writes must happen after barrier. - VK_ACCESS_TRANSFER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_TRANSFER_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::Transfer, - EventStage::Transfer, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::TransferSrcDst, - ImageMemoryBarrierData{ - "TransferSrcDst", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_TRANSFER_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::Transfer, - EventStage::Transfer, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::HostCopy, - ImageMemoryBarrierData{ - "HostCopy", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - // Transition to: we don't expect to transition into HostCopy on the GPU. - 0, - // Transition from: the data was initialized in the image by the host. Note that we - // only transition to this layout if the image was previously in UNDEFINED, in which - // case it didn't contain any data prior to the host copy either. - 0, - ResourceAccess::ReadOnly, - PipelineStage::InvalidEnum, - // We do not directly use this layout in SetEvent. - EventStage::InvalidEnum, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::VertexShaderReadOnly, - ImageMemoryBarrierData{ - "VertexShaderReadOnly", - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::VertexShader, - EventStage::VertexShader, - PipelineStageGroup::PreFragmentOnly, - }, - }, - { - ImageLayout::VertexShaderWrite, - ImageMemoryBarrierData{ - "VertexShaderWrite", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::VertexShader, - EventStage::VertexShader, - PipelineStageGroup::PreFragmentOnly, - }, - }, - { - ImageLayout::PreFragmentShadersReadOnly, - ImageMemoryBarrierData{ - "PreFragmentShadersReadOnly", - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - kPreFragmentStageFlags, - kPreFragmentStageFlags, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::VertexShader, - EventStage::PreFragmentShaders, - PipelineStageGroup::PreFragmentOnly, - }, - }, - { - ImageLayout::PreFragmentShadersWrite, - ImageMemoryBarrierData{ - "PreFragmentShadersWrite", - VK_IMAGE_LAYOUT_GENERAL, - kPreFragmentStageFlags, - kPreFragmentStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::VertexShader, - EventStage::PreFragmentShaders, - PipelineStageGroup::PreFragmentOnly, - }, - }, - { - ImageLayout::FragmentShadingRateAttachmentReadOnly, - ImageMemoryBarrierData{ - "FragmentShadingRateAttachmentReadOnly", - VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, - VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, - VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, - // Transition to: all reads must happen after barrier. - VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::FragmentShadingRate, - EventStage::FragmentShadingRate, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::FragmentShaderReadOnly, - ImageMemoryBarrierData{ - "FragmentShaderReadOnly", - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::FragmentShader, - EventStage::FragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::FragmentShaderWrite, - ImageMemoryBarrierData{ - "FragmentShaderWrite", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::FragmentShader, - EventStage::FragmentShader, - PipelineStageGroup::FragmentOnly, - }, - }, - { - ImageLayout::ComputeShaderReadOnly, - ImageMemoryBarrierData{ - "ComputeShaderReadOnly", - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - PipelineStage::ComputeShader, - EventStage::ComputeShader, - PipelineStageGroup::ComputeOnly, - }, - }, - { - ImageLayout::ComputeShaderWrite, - ImageMemoryBarrierData{ - "ComputeShaderWrite", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT, - ResourceAccess::ReadWrite, - PipelineStage::ComputeShader, - EventStage::ComputeShader, - PipelineStageGroup::ComputeOnly, - }, - }, - { - ImageLayout::AllGraphicsShadersReadOnly, - ImageMemoryBarrierData{ - "AllGraphicsShadersReadOnly", - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - kAllShadersPipelineStageFlags, - kAllShadersPipelineStageFlags, - // Transition to: all reads must happen after barrier. - VK_ACCESS_SHADER_READ_BIT, - // Transition from: RAR and WAR don't need memory barrier. - 0, - ResourceAccess::ReadOnly, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::VertexShader, - EventStage::AllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::AllGraphicsShadersWrite, - ImageMemoryBarrierData{ - "AllGraphicsShadersWrite", - VK_IMAGE_LAYOUT_GENERAL, - kAllShadersPipelineStageFlags, - kAllShadersPipelineStageFlags, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::VertexShader, - EventStage::AllShaders, - PipelineStageGroup::Other, - }, - }, - { - ImageLayout::TransferDstAndComputeWrite, - ImageMemoryBarrierData{ - "TransferDstAndComputeWrite", - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, - // Transition to: all reads and writes must happen after barrier. - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT, - // Transition from: all writes must finish before barrier. - VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, - ResourceAccess::ReadWrite, - // In case of multiple destination stages, We barrier the earliest stage - PipelineStage::ComputeShader, - EventStage::TransferAndComputeShader, - PipelineStageGroup::Other, - }, - }, -}; -// clang-format on +// A flag that is used to allow to fetch raw GPU pointer to a buffer and can be used when +// supportsBufferDeviceAddress is enabled +constexpr VkMemoryAllocateFlagsInfo kMemoryAllocateDeviceAddressFlags = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, nullptr, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, + 0}; -EventStage GetImageLayoutEventStage(ImageLayout layout) +EventStage GetImageAccessEventStage(Renderer *renderer, ImageAccess imageAccess) { - const ImageMemoryBarrierData &barrierData = kImageMemoryBarrierData[layout]; + const ImageMemoryBarrierData &barrierData = renderer->getImageMemoryBarrierData(imageAccess); return barrierData.eventStage; } @@ -1048,12 +240,25 @@ VkClearValue GetRobustResourceClearValue(const angle::Format &intendedFormat, return clearValue; } -bool IsShaderReadOnlyLayout(const ImageMemoryBarrierData &imageLayout) +bool IsShaderReadOnlyAccess(ImageAccess imageAccess) { - // We also use VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL for texture sample from depth - // texture. See GetImageReadLayout() for detail. - return imageLayout.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL || - imageLayout.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + switch (imageAccess) + { + case ImageAccess::ExternalShadersReadOnly: + case ImageAccess::VertexShaderReadOnly: + case ImageAccess::PreFragmentShadersReadOnly: + case ImageAccess::FragmentShaderReadOnly: + case ImageAccess::ComputeShaderReadOnly: + case ImageAccess::AllGraphicsShadersReadOnly: + // We also use read-only depth/stencil for texture sample from depth texture. See + // GetImageReadAccess() for details. + case ImageAccess::DepthReadStencilRead: + case ImageAccess::DepthReadStencilReadFragmentShaderRead: + case ImageAccess::DepthReadStencilReadAllShadersRead: + return true; + default: + return false; + } } bool IsAnySubresourceContentDefined(const gl::TexLevelArray> &contentDefined) @@ -1159,6 +364,21 @@ bool IsClearOfAllChannels(UpdateSource updateSource) updateSource == UpdateSource::ClearAfterInvalidate; } +template +gl::Box MakeUpdateBoundingBox(const Offset &offset, + const Extent &extents, + uint32_t layerIndex, + uint32_t layerCount) +{ + gl::Box updateBoundingBox = {offset, extents}; + if (layerIndex > 0 || layerCount > 1) + { + updateBoundingBox.z = layerIndex; + updateBoundingBox.depth = layerCount; + } + return updateBoundingBox; +} + angle::Result InitDynamicDescriptorPool(ErrorContext *context, const DescriptorSetLayoutDesc &descriptorSetLayoutDesc, const DescriptorSetLayout &descriptorSetLayout, @@ -1168,6 +388,7 @@ angle::Result InitDynamicDescriptorPool(ErrorContext *context, std::vector descriptorPoolSizes; DescriptorSetLayoutBindingVector bindingVector; descriptorSetLayoutDesc.unpackBindings(&bindingVector); + descriptorPoolSizes.reserve(bindingVector.size()); for (const VkDescriptorSetLayoutBinding &binding : bindingVector) { @@ -1189,15 +410,6 @@ angle::Result InitDynamicDescriptorPool(ErrorContext *context, return angle::Result::Continue; } -bool CheckSubpassCommandBufferCount(uint32_t count) -{ - // When using angle::SharedRingBufferAllocator we must ensure that allocator is attached and - // detached from the same priv::SecondaryCommandBuffer instance. - // Custom command buffer (priv::SecondaryCommandBuffer) may contain commands for multiple - // subpasses, therefore we do not need multiple buffers. - return (count == 1 || !RenderPassCommandBuffer::ExecutesInline()); -} - bool IsAnyLayout(VkImageLayout needle, const VkImageLayout *haystack, uint32_t haystackCount) { const VkImageLayout *haystackEnd = haystack + haystackCount; @@ -1297,139 +509,70 @@ VkPipelineStageFlags ConvertShaderBitSetToVkPipelineStageFlags( for (gl::ShaderType shaderType : writeShaderStages) { const PipelineStage stage = GetPipelineStage(shaderType); - pipelineStageFlags |= kBufferMemoryBarrierData[stage].pipelineStageFlags; + pipelineStageFlags |= GetBufferMemoryBarrierData(stage).pipelineStageFlags; } return pipelineStageFlags; } -} // anonymous namespace - -// This is an arbitrary max. We can change this later if necessary. -uint32_t DynamicDescriptorPool::mMaxSetsPerPool = 16; -uint32_t DynamicDescriptorPool::mMaxSetsPerPoolMultiplier = 2; - -ImageLayout GetImageLayoutFromGLImageLayout(ErrorContext *context, GLenum layout) -{ - const bool supportsMixedReadWriteDepthStencilLayouts = - context->getFeatures().supportsMixedReadWriteDepthStencilLayouts.enabled; - switch (layout) - { - case GL_NONE: - return ImageLayout::Undefined; - case GL_LAYOUT_GENERAL_EXT: - return ImageLayout::ExternalShadersWrite; - case GL_LAYOUT_COLOR_ATTACHMENT_EXT: - return ImageLayout::ColorWrite; - case GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT: - return ImageLayout::DepthWriteStencilWrite; - case GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT: - return ImageLayout::DepthReadStencilRead; - case GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT: - return supportsMixedReadWriteDepthStencilLayouts ? ImageLayout::DepthReadStencilWrite - : ImageLayout::DepthWriteStencilWrite; - case GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT: - return supportsMixedReadWriteDepthStencilLayouts ? ImageLayout::DepthWriteStencilRead - : ImageLayout::DepthWriteStencilWrite; - case GL_LAYOUT_SHADER_READ_ONLY_EXT: - return ImageLayout::ExternalShadersReadOnly; - case GL_LAYOUT_TRANSFER_SRC_EXT: - return ImageLayout::TransferSrc; - case GL_LAYOUT_TRANSFER_DST_EXT: - return ImageLayout::TransferDst; - default: - UNREACHABLE(); - return vk::ImageLayout::Undefined; - } -} - -GLenum ConvertImageLayoutToGLImageLayout(ImageLayout layout) -{ - switch (kImageMemoryBarrierData[layout].layout) - { - case VK_IMAGE_LAYOUT_UNDEFINED: - return GL_NONE; - case VK_IMAGE_LAYOUT_GENERAL: - return GL_LAYOUT_GENERAL_EXT; - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - return GL_LAYOUT_COLOR_ATTACHMENT_EXT; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - return GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: - return GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT; - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - return GL_LAYOUT_SHADER_READ_ONLY_EXT; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - return GL_LAYOUT_TRANSFER_SRC_EXT; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - return GL_LAYOUT_TRANSFER_DST_EXT; - case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: - return GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT; - case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: - return GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT; - default: - break; - } - UNREACHABLE(); - return GL_NONE; -} -VkImageLayout ConvertImageLayoutToVkImageLayout(Renderer *renderer, ImageLayout imageLayout) +// Temporarily updating an image's chromaFilter and restore it at the end. +class [[nodiscard]] ScopedOverrideYCbCrFilter final { - const ImageMemoryBarrierData &transition = renderer->getImageMemoryBarrierData(imageLayout); - VkImageLayout layout = transition.layout; - - if (ANGLE_LIKELY(renderer->getFeatures().supportsMixedReadWriteDepthStencilLayouts.enabled)) + public: + ScopedOverrideYCbCrFilter(Renderer *renderer, ImageHelper *img, const VkFilter &filter) + : mRenderer(renderer), + mImage(img), + mOriginalFilter(img->getYcbcrConversionDesc().getChromaFilter()) { - return layout; + img->updateChromaFilter(renderer, filter); } - // If the layouts are not supported, substitute them with what's available. This may be - // less optimal and/or introduce synchronization hazards. - if (layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL || - layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) + ~ScopedOverrideYCbCrFilter() { - layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - // If the replacement layout causes a feedback loop, use the GENERAL layout - if ((transition.dstStageMask & - (VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)) != 0) - { - layout = VK_IMAGE_LAYOUT_GENERAL; - } + mImage->updateChromaFilter(mRenderer, mOriginalFilter); + mRenderer = nullptr; + mImage = nullptr; } - return layout; -} + private: + Renderer *mRenderer; + ImageHelper *mImage; + VkFilter mOriginalFilter; +}; -PipelineStageGroup GetPipelineStageGroupFromStageFlags(VkPipelineStageFlags dstStageMask) -{ - if ((dstStageMask & ~kFragmentAndAttachmentPipelineStageFlags) == 0) - { - return PipelineStageGroup::FragmentOnly; - } - else if (dstStageMask == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) - { - return PipelineStageGroup::ComputeOnly; - } - else if ((dstStageMask & ~kPreFragmentStageFlags) == 0) - { - return PipelineStageGroup::PreFragmentOnly; - } - return PipelineStageGroup::Other; -} +// image usage flags that allowed for VK_QCOM_tile_memory_heap +constexpr VkImageUsageFlags kQCOMTileMemoryAllowedImageUsageBits = + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; -void InitializeImageLayoutAndMemoryBarrierDataMap( - ImageLayoutToMemoryBarrierDataMap *map, - VkPipelineStageFlags supportedVulkanPipelineStageMask) +// Returns true if it is compatible with VK_QCOM_tile_memory_heap +bool IsTileMemoryCompatible(const vk::Renderer *renderer, const VkImageCreateInfo &createInfo) { - *map = kImageMemoryBarrierData; - for (ImageMemoryBarrierData &barrierData : *map) + // First check general conditions specified in + // https://github.com/KhronosGroup/Vulkan-Docs/blob/main/proposals/VK_QCOM_tile_memory_heap.adoc + bool compatible = createInfo.imageType == VK_IMAGE_TYPE_2D && + createInfo.tiling == VK_IMAGE_TILING_OPTIMAL && createInfo.flags == 0 && + createInfo.mipLevels == 1 && createInfo.arrayLayers == 1 && + createInfo.samples == VK_SAMPLE_COUNT_1_BIT && + (createInfo.usage & ~kQCOMTileMemoryAllowedImageUsageBits) == 0; + + // If the driver actually supports VK_QCOM_tile_memory_heap, we must also check the format with + // vulkan driver. Otherwise we just skip format check for simulation. + if (renderer->getFeatures().supportsTileMemoryHeap.enabled && compatible) { - barrierData.srcStageMask &= supportedVulkanPipelineStageMask; - barrierData.dstStageMask &= supportedVulkanPipelineStageMask; - ASSERT(barrierData.pipelineStageGroup == - GetPipelineStageGroupFromStageFlags(barrierData.dstStageMask)); + VkImageUsageFlags usage = createInfo.usage | VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM; + compatible = vk::ImageHelper::FormatSupportsUsage( + renderer, createInfo.format, createInfo.imageType, createInfo.tiling, usage, + createInfo.flags, nullptr, nullptr, + vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess); } + + return compatible; } +} // anonymous namespace + +// This is an arbitrary max. We can change this later if necessary. +uint32_t DynamicDescriptorPool::mMaxSetsPerPool = 16; +uint32_t DynamicDescriptorPool::mMaxSetsPerPoolMultiplier = 2; bool FormatHasNecessaryFeature(Renderer *renderer, angle::FormatID formatID, @@ -1454,32 +597,6 @@ bool CanCopyWithTransfer(Renderer *renderer, return srcFormatHasNecessaryFeature && dstFormatHasNecessaryFeature; } -void InitializeEventStageToVkPipelineStageFlagsMap( - EventStageToVkPipelineStageFlagsMap *map, - VkPipelineStageFlags supportedVulkanPipelineStageMask) -{ - map->fill(0); - - for (const BufferMemoryBarrierData &bufferBarrierData : kBufferMemoryBarrierData) - { - const EventStage eventStage = bufferBarrierData.eventStage; - if (eventStage != EventStage::InvalidEnum) - { - (*map)[eventStage] |= - bufferBarrierData.pipelineStageFlags & supportedVulkanPipelineStageMask; - } - } - - for (const ImageMemoryBarrierData &imageBarrierData : kImageMemoryBarrierData) - { - const EventStage eventStage = imageBarrierData.eventStage; - if (eventStage != EventStage::InvalidEnum) - { - (*map)[eventStage] |= imageBarrierData.dstStageMask & supportedVulkanPipelineStageMask; - } - } -} - // Context implementation Context::Context(Renderer *renderer) : ErrorContext(renderer), mShareGroupRefCountedEventsGarbageRecycler(nullptr) @@ -1774,8 +891,8 @@ bool RenderPassAttachment::onAccessImpl(ResourceAccess access, uint32_t currentC // invalidated. mInvalidatedCmdCount = kInfiniteCmdCount; mDisabledCmdCount = kInfiniteCmdCount; - // Return true to indicate that the store op should remain STORE and that mContentDefined - // should be set to true; + // Return true to indicate that the store op should remain STORE and that + // mVkImageContentDefined should be set to true; return true; } // Drawing to this attachment is being disabled. @@ -1784,8 +901,8 @@ bool RenderPassAttachment::onAccessImpl(ResourceAccess access, uint32_t currentC // The attachment was previously drawn while enabled, and so is no longer invalidated. mInvalidatedCmdCount = kInfiniteCmdCount; mDisabledCmdCount = kInfiniteCmdCount; - // Return true to indicate that the store op should remain STORE and that mContentDefined - // should be set to true; + // Return true to indicate that the store op should remain STORE and that + // mVkImageContentDefined should be set to true; return true; } @@ -1805,7 +922,6 @@ CommandBufferHelperCommon::~CommandBufferHelperCommon() {} void CommandBufferHelperCommon::initializeImpl() { - mCommandAllocator.init(); } void CommandBufferHelperCommon::resetImpl(ErrorContext *context) @@ -1879,36 +995,11 @@ void CommandBufferHelperCommon::releaseCommandPoolImpl() ASSERT(mCommandPool == nullptr); } -template -void CommandBufferHelperCommon::attachAllocatorImpl(SecondaryCommandMemoryAllocator *allocator) -{ - if constexpr (DerivedT::ExecutesInline()) - { - auto &commandBuffer = static_cast(this)->getCommandBuffer(); - mCommandAllocator.attachAllocator(allocator); - commandBuffer.attachAllocator(mCommandAllocator.getAllocator()); - } -} - -template -SecondaryCommandMemoryAllocator *CommandBufferHelperCommon::detachAllocatorImpl() -{ - SecondaryCommandMemoryAllocator *result = nullptr; - if constexpr (DerivedT::ExecutesInline()) - { - auto &commandBuffer = static_cast(this)->getCommandBuffer(); - commandBuffer.detachAllocator(mCommandAllocator.getAllocator()); - result = mCommandAllocator.detachAllocator(commandBuffer.empty()); - } - return result; -} - template void CommandBufferHelperCommon::assertCanBeRecycledImpl() { DerivedT *derived = static_cast(this); ASSERT(mCommandPool == nullptr); - ASSERT(!mCommandAllocator.hasAllocatorLinks()); // Vulkan secondary command buffers must be invalid (collected). ASSERT(DerivedT::ExecutesInline() || !derived->getCommandBuffer().valid()); // ANGLEs Custom secondary command buffers must be empty (reset). @@ -1921,7 +1012,7 @@ void CommandBufferHelperCommon::bufferWrite(Context *context, BufferHelper *buffer) { VkPipelineStageFlags writePipelineStageFlags = - kBufferMemoryBarrierData[writeStage].pipelineStageFlags; + GetBufferMemoryBarrierData(writeStage).pipelineStageFlags; bufferWriteImpl(context, writeAccessType, writePipelineStageFlags, writeStage, buffer); } @@ -1942,7 +1033,7 @@ void CommandBufferHelperCommon::bufferRead(Context *context, BufferHelper *buffer) { VkPipelineStageFlags readPipelineStageFlags = - kBufferMemoryBarrierData[readStage].pipelineStageFlags; + GetBufferMemoryBarrierData(readStage).pipelineStageFlags; bufferReadImpl(context, readAccessType, readPipelineStageFlags, readStage, buffer); } @@ -1955,7 +1046,7 @@ void CommandBufferHelperCommon::bufferRead(Context *context, { PipelineStage readStage = GetPipelineStage(shaderType); VkPipelineStageFlags readPipelineStageFlags = - kBufferMemoryBarrierData[readStage].pipelineStageFlags; + GetBufferMemoryBarrierData(readStage).pipelineStageFlags; bufferReadImpl(context, readAccessType, readPipelineStageFlags, readStage, buffer); } } @@ -1993,19 +1084,19 @@ void CommandBufferHelperCommon::bufferReadImpl(Context *context, ASSERT(!usesBufferForWrite(*buffer)); buffer->recordReadEvent(context, readAccessType, readPipelineStageFlags, readStage, - mQueueSerial, kBufferMemoryBarrierData[readStage].eventStage, + mQueueSerial, GetBufferMemoryBarrierData(readStage).eventStage, &mRefCountedEvents); } void CommandBufferHelperCommon::imageReadImpl(Context *context, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, BarrierType barrierType, ImageHelper *image) { - if (image->isReadBarrierNecessary(context->getRenderer(), imageLayout)) + if (image->isReadBarrierNecessary(context->getRenderer(), imageAccess)) { - updateImageLayoutAndBarrier(context, image, aspectFlags, imageLayout, barrierType); + updateImageLayoutAndBarrier(context, image, aspectFlags, imageAccess, barrierType); } } @@ -2014,25 +1105,25 @@ void CommandBufferHelperCommon::imageWriteImpl(Context *context, uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, BarrierType barrierType, ImageHelper *image) { image->onWrite(level, 1, layerStart, layerCount, aspectFlags); - if (image->isWriteBarrierNecessary(imageLayout, level, 1, layerStart, layerCount)) + if (image->isWriteBarrierNecessary(imageAccess, level, 1, layerStart, layerCount)) { - updateImageLayoutAndBarrier(context, image, aspectFlags, imageLayout, barrierType); + updateImageLayoutAndBarrier(context, image, aspectFlags, imageAccess, barrierType); } } void CommandBufferHelperCommon::updateImageLayoutAndBarrier(Context *context, ImageHelper *image, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, BarrierType barrierType) { VkSemaphore semaphore = VK_NULL_HANDLE; - image->updateLayoutAndBarrier(context, aspectFlags, imageLayout, barrierType, mQueueSerial, + image->updateLayoutAndBarrier(context, aspectFlags, imageAccess, barrierType, mQueueSerial, &mPipelineBarriers, &mEventBarriers, &mRefCountedEventCollector, &semaphore); // If image has an ANI semaphore, move it to command buffer so that we can wait for it in @@ -2047,7 +1138,7 @@ void CommandBufferHelperCommon::updateImageLayoutAndBarrier(Context *context, void CommandBufferHelperCommon::retainImageWithEvent(Context *context, ImageHelper *image) { image->setQueueSerial(mQueueSerial); - image->updatePipelineStageAccessHistory(); + image->updatePipelineStageAccessHistory(context->getRenderer()); if (context->getFeatures().useVkEventForImageBarrier.enabled) { @@ -2076,17 +1167,19 @@ template void CommandBufferHelperCommon::flushSetEventsImplwaitSemaphores.emplace_back(mAcquireNextImageSemaphore.release()); - commandsState->waitSemaphoreStageMasks.emplace_back(kSwapchainAcquireImageWaitStageFlags); + commandsState->addWaitSemaphore(mAcquireNextImageSemaphore.release(), + kSwapchainAcquireImageWaitStageFlags); } - mPipelineBarriers.execute(renderer, &commandsState->primaryCommands); - mEventBarriers.execute(renderer, &commandsState->primaryCommands); + mPipelineBarriers.execute(renderer, primaryCommands); + mEventBarriers.execute(renderer, primaryCommands); } void CommandBufferHelperCommon::addCommandDiagnosticsCommon(std::ostringstream *out) @@ -2134,7 +1227,7 @@ angle::Result OutsideRenderPassCommandBufferHelper::reset( void OutsideRenderPassCommandBufferHelper::imageRead(Context *context, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image) { if (image->getResourceUse() >= mQueueSerial) @@ -2142,11 +1235,11 @@ void OutsideRenderPassCommandBufferHelper::imageRead(Context *context, // If image is already used by renderPass, it may already set the event to renderPass's // event. In this case we already lost the previous event to wait for, thus use pipeline // barrier instead of event - imageReadImpl(context, aspectFlags, imageLayout, BarrierType::Pipeline, image); + imageReadImpl(context, aspectFlags, imageAccess, BarrierType::Pipeline, image); } else { - imageReadImpl(context, aspectFlags, imageLayout, BarrierType::Event, image); + imageReadImpl(context, aspectFlags, imageAccess, BarrierType::Event, image); // Usually an image can only used by a RenderPassCommands or OutsideRenderPassCommands // because the layout will be different, except with image sampled from compute shader. In // this case, the renderPassCommands' read will override the outsideRenderPassCommands' @@ -2159,20 +1252,20 @@ void OutsideRenderPassCommandBufferHelper::imageWrite(Context *context, uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image) { - imageWriteImpl(context, level, layerStart, layerCount, aspectFlags, imageLayout, + imageWriteImpl(context, level, layerStart, layerCount, aspectFlags, imageAccess, BarrierType::Event, image); retainImageWithEvent(context, image); } -void OutsideRenderPassCommandBufferHelper::retainImage(ImageHelper *image) +void OutsideRenderPassCommandBufferHelper::retainImage(Renderer *renderer, ImageHelper *image) { // We want explicit control on when VkEvent is used for outsideRPCommands to minimize the // overhead, so do not setEvent here. image->setQueueSerial(mQueueSerial); - image->updatePipelineStageAccessHistory(); + image->updatePipelineStageAccessHistory(renderer); } void OutsideRenderPassCommandBufferHelper::trackImageWithEvent(Context *context, ImageHelper *image) @@ -2191,8 +1284,10 @@ void OutsideRenderPassCommandBufferHelper::collectRefCountedEventsGarbage( } } -angle::Result OutsideRenderPassCommandBufferHelper::flushToPrimary(Context *context, - CommandsState *commandsState) +angle::Result OutsideRenderPassCommandBufferHelper::flushToPrimary( + Context *context, + CommandsState *commandsState, + PrimaryCommandBuffer *primaryCommands) { ANGLE_TRACE_EVENT0("gpu.angle", "OutsideRenderPassCommandBufferHelper::flushToPrimary"); ASSERT(!empty()); @@ -2200,21 +1295,20 @@ angle::Result OutsideRenderPassCommandBufferHelper::flushToPrimary(Context *cont Renderer *renderer = context->getRenderer(); // Commands that are added to primary before beginRenderPass command - executeBarriers(renderer, commandsState); + executeBarriers(renderer, commandsState, primaryCommands); ANGLE_TRY(endCommandBuffer(context)); ASSERT(mIsCommandBufferEnded); - mCommandBuffer.executeCommands(&commandsState->primaryCommands); + mCommandBuffer.executeCommands(primaryCommands); // Call VkCmdSetEvent to track the completion of this renderPass. - flushSetEventsImpl(context, &commandsState->primaryCommands); + flushSetEventsImpl(context, primaryCommands); // Proactively reset all released events before ending command buffer. - context->getRenderer()->getRefCountedEventRecycler()->resetEvents( - context, mQueueSerial, &commandsState->primaryCommands); + context->getRenderer()->getRefCountedEventRecycler()->resetEvents(context, mQueueSerial, + primaryCommands); - // Restart the command buffer. - return reset(context, &commandsState->secondaryCommands); + return angle::Result::Continue; } angle::Result OutsideRenderPassCommandBufferHelper::endCommandBuffer(ErrorContext *context) @@ -2249,17 +1343,6 @@ void OutsideRenderPassCommandBufferHelper::releaseCommandPool() releaseCommandPoolImpl(); } -void OutsideRenderPassCommandBufferHelper::attachAllocator( - SecondaryCommandMemoryAllocator *allocator) -{ - attachAllocatorImpl(allocator); -} - -SecondaryCommandMemoryAllocator *OutsideRenderPassCommandBufferHelper::detachAllocator() -{ - return detachAllocatorImpl(); -} - void OutsideRenderPassCommandBufferHelper::assertCanBeRecycled() { assertCanBeRecycledImpl(); @@ -2371,7 +1454,7 @@ RenderPassCommandBufferHelper::RenderPassCommandBufferHelper() mDepthStencilAttachmentIndex(kAttachmentIndexInvalid), mColorAttachmentsCount(0), mImageOptimizeForPresent(nullptr), - mImageOptimizeForPresentOriginalLayout(ImageLayout::Undefined) + mImageOptimizeForPresentOriginalLayout(ImageAccess::Undefined) {} RenderPassCommandBufferHelper::~RenderPassCommandBufferHelper() {} @@ -2421,9 +1504,7 @@ angle::Result RenderPassCommandBufferHelper::reset( mColorAttachmentsCount = PackedAttachmentCount(0); mDepthStencilAttachmentIndex = kAttachmentIndexInvalid; mImageOptimizeForPresent = nullptr; - mImageOptimizeForPresentOriginalLayout = ImageLayout::Undefined; - - ASSERT(CheckSubpassCommandBufferCount(getSubpassCommandBufferCount())); + mImageOptimizeForPresentOriginalLayout = ImageAccess::Undefined; // Collect/Reset the command buffers for (uint32_t subpass = 0; subpass < getSubpassCommandBufferCount(); ++subpass) @@ -2444,10 +1525,10 @@ angle::Result RenderPassCommandBufferHelper::reset( void RenderPassCommandBufferHelper::imageRead(ContextVk *contextVk, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image) { - imageReadImpl(contextVk, aspectFlags, imageLayout, BarrierType::Event, image); + imageReadImpl(contextVk, aspectFlags, imageAccess, BarrierType::Event, image); // As noted in the header we don't support multiple read layouts for Images. // We allow duplicate uses in the RP to accommodate for normal GL sampler usage. retainImageWithEvent(contextVk, image); @@ -2458,10 +1539,10 @@ void RenderPassCommandBufferHelper::imageWrite(ContextVk *contextVk, uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image) { - imageWriteImpl(contextVk, level, layerStart, layerCount, aspectFlags, imageLayout, + imageWriteImpl(contextVk, level, layerStart, layerCount, aspectFlags, imageAccess, BarrierType::Event, image); retainImageWithEvent(contextVk, image); } @@ -2634,13 +1715,13 @@ void RenderPassCommandBufferHelper::finalizeColorImageLayout( ASSERT(image != nullptr); // Do layout change. - ImageLayout imageLayout; + ImageAccess imageAccess; if (image->usedByCurrentRenderPassAsAttachmentAndSampler(RenderPassUsage::ColorTextureSampler)) { // texture code already picked layout and inserted barrier - imageLayout = image->getCurrentImageLayout(); - ASSERT(imageLayout == ImageLayout::ColorWriteFragmentShaderFeedback || - imageLayout == ImageLayout::ColorWriteAllShadersFeedback); + imageAccess = image->getCurrentImageAccess(); + ASSERT(imageAccess == ImageAccess::ColorWriteFragmentShaderFeedback || + imageAccess == ImageAccess::ColorWriteAllShadersFeedback); } else { @@ -2650,29 +1731,33 @@ void RenderPassCommandBufferHelper::finalizeColorImageLayout( // but that is needed to query whether the attachment is unresolved or not. const bool hasUnresolve = isResolveImage && mRenderPassDesc.getColorUnresolveAttachmentMask().any(); - imageLayout = hasUnresolve ? ImageLayout::MSRTTEmulationColorUnresolveAndResolve - : ImageLayout::ColorWrite; + imageAccess = hasUnresolve ? ImageAccess::MSRTTEmulationColorUnresolveAndResolve + : ImageAccess::ColorWrite; if (context->getFeatures().preferDynamicRendering.enabled && mRenderPassDesc.hasColorFramebufferFetch()) { // Note MSRTT emulation is not implemented with dynamic rendering. - ASSERT(imageLayout == ImageLayout::ColorWrite); - imageLayout = ImageLayout::ColorWriteAndInput; + ASSERT(imageAccess == ImageAccess::ColorWrite); + imageAccess = ImageAccess::ColorWriteAndInput; } - else if (image->getCurrentImageLayout() == ImageLayout::SharedPresent) + else if (image->getCurrentImageAccess() == ImageAccess::SharedPresent) { - // Once you transition to ImageLayout::SharedPresent, you never transition out of it. - ASSERT(imageLayout == ImageLayout::ColorWrite); - imageLayout = ImageLayout::SharedPresent; + // Once you transition to ImageAccess::SharedPresent, you never transition out of it. + ASSERT(imageAccess == ImageAccess::ColorWrite); + imageAccess = ImageAccess::SharedPresent; } - updateImageLayoutAndBarrier(context, image, VK_IMAGE_ASPECT_COLOR_BIT, imageLayout, + updateImageLayoutAndBarrier(context, image, VK_IMAGE_ASPECT_COLOR_BIT, imageAccess, BarrierType::Event); } if (!isResolveImage) { - mAttachmentOps.setLayouts(packedAttachmentIndex, imageLayout, imageLayout); + mAttachmentOps.setLayouts(packedAttachmentIndex, imageAccess, imageAccess); + } + else + { + SetBitField(mAttachmentOps[packedAttachmentIndex].finalResolveLayout, imageAccess); } // Dynamic rendering does not have implicit layout transitions at render pass boundaries. This @@ -2683,29 +1768,31 @@ void RenderPassCommandBufferHelper::finalizeColorImageLayout( ASSERT(isDefault()); ASSERT(context->getFeatures().supportsPresentation.enabled); ASSERT(packedAttachmentIndex == kAttachmentIndexZero); + // Shared present mode must not change layout + ASSERT(imageAccess != ImageAccess::SharedPresent); // Use finalLayout instead of extra barrier for layout change to present. For dynamic // rendering, this is not possible and is done when the render pass is flushed. However, // because this function is expected to finalize the image layout, we still have to pretend // the image is in the present layout already. - mImageOptimizeForPresentOriginalLayout = mImageOptimizeForPresent->getCurrentImageLayout(); - mImageOptimizeForPresent->setCurrentImageLayout(context->getRenderer(), - ImageLayout::Present); + mImageOptimizeForPresentOriginalLayout = mImageOptimizeForPresent->getCurrentImageAccess(); + mImageOptimizeForPresent->setCurrentImageAccess(context->getRenderer(), + ImageAccess::Present); if (!context->getFeatures().preferDynamicRendering.enabled) { if (isResolveImage) { SetBitField(mAttachmentOps[packedAttachmentIndex].finalResolveLayout, - mImageOptimizeForPresent->getCurrentImageLayout()); + mImageOptimizeForPresent->getCurrentImageAccess()); } else { SetBitField(mAttachmentOps[packedAttachmentIndex].finalLayout, - mImageOptimizeForPresent->getCurrentImageLayout()); + mImageOptimizeForPresent->getCurrentImageAccess()); } mImageOptimizeForPresent = nullptr; - mImageOptimizeForPresentOriginalLayout = ImageLayout::Undefined; + mImageOptimizeForPresentOriginalLayout = ImageAccess::Undefined; } } @@ -2725,7 +1812,7 @@ void RenderPassCommandBufferHelper::finalizeColorImageLoadStore( RenderPassStoreOp storeOp = static_cast(ops.storeOp); // This has to be called after layout been finalized - ASSERT(ops.initialLayout != static_cast(ImageLayout::Undefined)); + ASSERT(ops.initialLayout != static_cast(ImageAccess::Undefined)); uint32_t currentCmdCount = getRenderPassWriteCommandCount(); bool isInvalidated = false; @@ -2764,7 +1851,7 @@ void RenderPassCommandBufferHelper::finalizeDepthStencilImageLayout(Context *con ImageHelper *depthStencilImage = mDepthAttachment.getImage(); // Do depth stencil layout change. - ImageLayout imageLayout; + ImageAccess imageAccess; bool barrierRequired; const bool isDepthAttachmentAndSampler = @@ -2782,57 +1869,57 @@ void RenderPassCommandBufferHelper::finalizeDepthStencilImageLayout(Context *con if (isDepthAttachmentAndSampler || isStencilAttachmentAndSampler) { // texture code already picked layout and inserted barrier - imageLayout = depthStencilImage->getCurrentImageLayout(); + imageAccess = depthStencilImage->getCurrentImageAccess(); if ((isDepthAttachmentAndSampler && !isReadOnlyDepth) || (isStencilAttachmentAndSampler && !isReadOnlyStencil)) { - ASSERT(imageLayout == ImageLayout::DepthStencilFragmentShaderFeedback || - imageLayout == ImageLayout::DepthStencilAllShadersFeedback); + ASSERT(imageAccess == ImageAccess::DepthStencilFragmentShaderFeedback || + imageAccess == ImageAccess::DepthStencilAllShadersFeedback); barrierRequired = true; } else { - ASSERT(imageLayout == ImageLayout::DepthWriteStencilReadFragmentShaderStencilRead || - imageLayout == ImageLayout::DepthWriteStencilReadAllShadersStencilRead || - imageLayout == ImageLayout::DepthReadStencilWriteFragmentShaderDepthRead || - imageLayout == ImageLayout::DepthReadStencilWriteAllShadersDepthRead || - imageLayout == ImageLayout::DepthReadStencilReadFragmentShaderRead || - imageLayout == ImageLayout::DepthReadStencilReadAllShadersRead); + ASSERT(imageAccess == ImageAccess::DepthWriteStencilReadFragmentShaderStencilRead || + imageAccess == ImageAccess::DepthWriteStencilReadAllShadersStencilRead || + imageAccess == ImageAccess::DepthReadStencilWriteFragmentShaderDepthRead || + imageAccess == ImageAccess::DepthReadStencilWriteAllShadersDepthRead || + imageAccess == ImageAccess::DepthReadStencilReadFragmentShaderRead || + imageAccess == ImageAccess::DepthReadStencilReadAllShadersRead); barrierRequired = - depthStencilImage->isReadBarrierNecessary(context->getRenderer(), imageLayout); + depthStencilImage->isReadBarrierNecessary(context->getRenderer(), imageAccess); } } else { if (mRenderPassDesc.hasDepthStencilFramebufferFetch()) { - imageLayout = ImageLayout::DepthStencilWriteAndInput; + imageAccess = ImageAccess::DepthStencilWriteAndInput; } else if (isReadOnlyDepth) { - imageLayout = isReadOnlyStencil ? ImageLayout::DepthReadStencilRead - : ImageLayout::DepthReadStencilWrite; + imageAccess = isReadOnlyStencil ? ImageAccess::DepthReadStencilRead + : ImageAccess::DepthReadStencilWrite; } else { - imageLayout = isReadOnlyStencil ? ImageLayout::DepthWriteStencilRead - : ImageLayout::DepthWriteStencilWrite; + imageAccess = isReadOnlyStencil ? ImageAccess::DepthWriteStencilRead + : ImageAccess::DepthWriteStencilWrite; } barrierRequired = !isReadOnlyDepth || !isReadOnlyStencil || - depthStencilImage->isReadBarrierNecessary(context->getRenderer(), imageLayout); + depthStencilImage->isReadBarrierNecessary(context->getRenderer(), imageAccess); } - mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, imageLayout, imageLayout); + mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, imageAccess, imageAccess); if (barrierRequired) { const angle::Format &format = depthStencilImage->getActualFormat(); ASSERT(format.hasDepthOrStencilBits()); VkImageAspectFlags aspectFlags = GetDepthStencilAspectFlags(format); - updateImageLayoutAndBarrier(context, depthStencilImage, aspectFlags, imageLayout, + updateImageLayoutAndBarrier(context, depthStencilImage, aspectFlags, imageAccess, barrierType); } } @@ -2845,14 +1932,14 @@ void RenderPassCommandBufferHelper::finalizeDepthStencilResolveImageLayout(Conte ImageHelper *depthStencilResolveImage = mDepthResolveAttachment.getImage(); // When depth/stencil is unresolved, use a layout that includes fragment shader reads. - ImageLayout imageLayout = mRenderPassDesc.hasDepthStencilUnresolveAttachment() - ? ImageLayout::MSRTTEmulationDepthStencilUnresolveAndResolve - : ImageLayout::DepthStencilResolve; + ImageAccess imageAccess = mRenderPassDesc.hasDepthStencilUnresolveAttachment() + ? ImageAccess::MSRTTEmulationDepthStencilUnresolveAndResolve + : ImageAccess::DepthStencilResolve; const angle::Format &format = depthStencilResolveImage->getActualFormat(); ASSERT(format.hasDepthOrStencilBits()); VkImageAspectFlags aspectFlags = GetDepthStencilAspectFlags(format); - updateImageLayoutAndBarrier(context, depthStencilResolveImage, aspectFlags, imageLayout, + updateImageLayoutAndBarrier(context, depthStencilResolveImage, aspectFlags, imageAccess, BarrierType::Event); // The resolve image can never be read-only. @@ -2879,11 +1966,11 @@ void RenderPassCommandBufferHelper::finalizeDepthStencilResolveImageLayout(Conte void RenderPassCommandBufferHelper::finalizeFragmentShadingRateImageLayout(Context *context) { ImageHelper *image = mFragmentShadingRateAtachment.getImage(); - ImageLayout imageLayout = ImageLayout::FragmentShadingRateAttachmentReadOnly; + ImageAccess imageAccess = ImageAccess::FragmentShadingRateAttachmentReadOnly; ASSERT(image && image->valid()); - if (image->isReadBarrierNecessary(context->getRenderer(), imageLayout)) + if (image->isReadBarrierNecessary(context->getRenderer(), imageAccess)) { - updateImageLayoutAndBarrier(context, image, VK_IMAGE_ASPECT_COLOR_BIT, imageLayout, + updateImageLayoutAndBarrier(context, image, VK_IMAGE_ASPECT_COLOR_BIT, imageAccess, BarrierType::Event); } image->resetRenderPassUsageFlags(); @@ -2944,7 +2031,7 @@ void RenderPassCommandBufferHelper::finalizeDepthStencilLoadStore(Context *conte RenderPassStoreOp stencilStoreOp = static_cast(dsOps.stencilStoreOp); // This has to be called after layout been finalized - ASSERT(dsOps.initialLayout != static_cast(ImageLayout::Undefined)); + ASSERT(dsOps.initialLayout != static_cast(ImageAccess::Undefined)); uint32_t currentCmdCount = getRenderPassWriteCommandCount(); bool isDepthInvalidated = false; @@ -3268,6 +2355,7 @@ void RenderPassCommandBufferHelper::invalidateRenderPassStencilAttachment( angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context, CommandsState *commandsState, + PrimaryCommandBuffer *primaryCommands, const RenderPass &renderPass, VkFramebuffer framebufferOverride) { @@ -3282,10 +2370,9 @@ angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context, ANGLE_TRACE_EVENT0("gpu.angle", "RenderPassCommandBufferHelper::flushToPrimary"); ASSERT(mRenderPassStarted); - PrimaryCommandBuffer &primary = commandsState->primaryCommands; // Commands that are added to primary before beginRenderPass command - executeBarriers(renderer, commandsState); + executeBarriers(renderer, commandsState, primaryCommands); constexpr VkSubpassContents kSubpassContents = ExecutesInline() ? VK_SUBPASS_CONTENTS_INLINE @@ -3293,7 +2380,7 @@ angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context, if (!renderPass.valid()) { - mRenderPassDesc.beginRendering(context, &primary, mRenderArea, kSubpassContents, + mRenderPassDesc.beginRendering(context, primaryCommands, mRenderArea, kSubpassContents, mFramebuffer.getUnpackedImageViews(), mAttachmentOps, mClearValues, mFramebuffer.getLayers()); } @@ -3313,7 +2400,7 @@ angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context, } mRenderPassDesc.beginRenderPass( - context, &primary, renderPass, + context, primaryCommands, renderPass, framebufferOverride ? framebufferOverride : mFramebuffer.getFramebuffer().getHandle(), mRenderArea, kSubpassContents, mClearValues, mFramebuffer.isImageless() ? &attachmentBeginInfo : nullptr); @@ -3325,42 +2412,41 @@ angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context, if (subpass > 0) { ASSERT(!context->getFeatures().preferDynamicRendering.enabled); - primary.nextSubpass(kSubpassContents); + primaryCommands->nextSubpass(kSubpassContents); } - mCommandBuffers[subpass].executeCommands(&primary); + mCommandBuffers[subpass].executeCommands(primaryCommands); } if (!renderPass.valid()) { - primary.endRendering(); + primaryCommands->endRendering(); if (mImageOptimizeForPresent != nullptr) { // finalizeColorImageLayout forces layout to Present. If this is not the case, that // code was not run (so mImageOptimizeForPresentOriginalLayout is invalid). - ASSERT(mImageOptimizeForPresent->getCurrentImageLayout() == ImageLayout::Present); + ASSERT(mImageOptimizeForPresent->getCurrentImageAccess() == ImageAccess::Present); // Restore the original layout of the image and do the real transition after the render // pass ends. - mImageOptimizeForPresent->setCurrentImageLayout(renderer, + mImageOptimizeForPresent->setCurrentImageAccess(renderer, mImageOptimizeForPresentOriginalLayout); - mImageOptimizeForPresent->recordWriteBarrierOneOff(renderer, ImageLayout::Present, - &primary, nullptr); + mImageOptimizeForPresent->recordWriteBarrierOneOff(renderer, ImageAccess::Present, + primaryCommands, nullptr); mImageOptimizeForPresent = nullptr; - mImageOptimizeForPresentOriginalLayout = ImageLayout::Undefined; + mImageOptimizeForPresentOriginalLayout = ImageAccess::Undefined; } } else { - primary.endRenderPass(); + primaryCommands->endRenderPass(); } // Now issue VkCmdSetEvents to primary command buffer ASSERT(mRefCountedEvents.empty()); - mVkEventArray.flushSetEvents(&primary); + mVkEventArray.flushSetEvents(primaryCommands); - // Restart the command buffer. - return reset(context, &commandsState->secondaryCommands); + return angle::Result::Continue; } void RenderPassCommandBufferHelper::addColorResolveAttachment(size_t colorIndexGL, @@ -3497,18 +2583,6 @@ void RenderPassCommandBufferHelper::releaseCommandPool() releaseCommandPoolImpl(); } -void RenderPassCommandBufferHelper::attachAllocator(SecondaryCommandMemoryAllocator *allocator) -{ - ASSERT(CheckSubpassCommandBufferCount(getSubpassCommandBufferCount())); - attachAllocatorImpl(allocator); -} - -SecondaryCommandMemoryAllocator *RenderPassCommandBufferHelper::detachAllocator() -{ - ASSERT(CheckSubpassCommandBufferCount(getSubpassCommandBufferCount())); - return detachAllocatorImpl(); -} - void RenderPassCommandBufferHelper::assertCanBeRecycled() { ASSERT(!mRenderPassStarted); @@ -3598,7 +2672,6 @@ template angle::Result CommandBufferRecycler::getCommandBufferHelper( ErrorContext *context, SecondaryCommandPool *commandPool, - SecondaryCommandMemoryAllocator *commandsAllocator, CommandBufferHelperT **commandBufferHelperOut) { std::unique_lock lock(mMutex); @@ -3617,9 +2690,6 @@ angle::Result CommandBufferRecycler::getCommandBufferHelpe ANGLE_TRY((*commandBufferHelperOut)->attachCommandPool(context, commandPool)); - // Attach functions are only used for ring buffer allocators. - (*commandBufferHelperOut)->attachAllocator(commandsAllocator); - return angle::Result::Continue; } @@ -3627,12 +2697,10 @@ template angle::Result CommandBufferRecycler::getCommandBufferHelper( ErrorContext *, SecondaryCommandPool *, - SecondaryCommandMemoryAllocator *, OutsideRenderPassCommandBufferHelper **); template angle::Result CommandBufferRecycler::getCommandBufferHelper( ErrorContext *, SecondaryCommandPool *, - SecondaryCommandMemoryAllocator *, RenderPassCommandBufferHelper **); template @@ -3798,6 +2866,7 @@ angle::Result DynamicBuffer::allocate(Context *context, BufferHelper **bufferHelperOut, bool *newBufferAllocatedOut) { + ASSERT(sizeInBytes != 0); bool newBuffer = !allocateFromCurrentBuffer(sizeInBytes, bufferHelperOut); if (newBufferAllocatedOut) { @@ -3983,6 +3052,8 @@ BufferPool::BufferPool() mUsage(0), mHostVisible(false), mSize(0), + mInitialSize(0), + mPreferredSize(0), mMemoryTypeIndex(0), mTotalMemorySize(0), mNumberOfNewBuffersNeededSinceLastPrune(0) @@ -3993,30 +3064,25 @@ BufferPool::BufferPool(BufferPool &&other) mUsage(other.mUsage), mHostVisible(other.mHostVisible), mSize(other.mSize), + mInitialSize(other.mInitialSize), + mPreferredSize(other.mPreferredSize), mMemoryTypeIndex(other.mMemoryTypeIndex) {} void BufferPool::initWithFlags(Renderer *renderer, vma::VirtualBlockCreateFlags flags, VkBufferUsageFlags usage, - VkDeviceSize initialSize, uint32_t memoryTypeIndex, VkMemoryPropertyFlags memoryPropertyFlags) { mVirtualBlockCreateFlags = flags; mUsage = usage; mMemoryTypeIndex = memoryTypeIndex; - if (initialSize) - { - // Should be power of two - ASSERT(gl::isPow2(initialSize)); - mSize = initialSize; - } - else - { - mSize = renderer->getPreferedBufferBlockSize(memoryTypeIndex); - } + mInitialSize = renderer->getPreferredInitialBufferBlockSize(memoryTypeIndex); + mPreferredSize = renderer->getPreferredLargeBufferBlockSize(memoryTypeIndex); + mSize = mInitialSize; mHostVisible = ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0); + mBufferBlocks.reserve(32); } BufferPool::~BufferPool() @@ -4027,10 +3093,10 @@ BufferPool::~BufferPool() void BufferPool::pruneEmptyBuffers(Renderer *renderer) { - // First try to walk through mBuffers and move empty buffers to mEmptyBuffer and remove null + // Walk through mBuffers and move empty buffers to mEmptyBuffer and remove null // pointers for allocation performance. - // The expectation is that we will find none needs to be compacted in most calls. bool needsCompact = false; + size_t nonEmptyBufferCount = 0; for (std::unique_ptr &block : mBufferBlocks) { if (block->isEmpty()) @@ -4050,20 +3116,19 @@ void BufferPool::pruneEmptyBuffers(Renderer *renderer) } needsCompact = true; } - } - - // Now remove the null pointers that left by empty buffers all at once, if any. - if (needsCompact) - { - BufferBlockPointerVector compactedBlocks; - for (std::unique_ptr &block : mBufferBlocks) + else { - if (block) + if (needsCompact) { - compactedBlocks.push_back(std::move(block)); + mBufferBlocks[nonEmptyBufferCount] = std::move(block); } + nonEmptyBufferCount++; } - mBufferBlocks = std::move(compactedBlocks); + } + + if (needsCompact) + { + mBufferBlocks.resize(nonEmptyBufferCount); } // Decide how many empty buffers to keep around and trim down the excessive empty buffers. We @@ -4097,9 +3162,12 @@ VkResult BufferPool::allocateNewBuffer(ErrorContext *context, VkDeviceSize sizeI // First ensure we are not exceeding the heapSize to avoid the validation error. VK_RESULT_CHECK(sizeInBytes <= heapSize, VK_ERROR_OUT_OF_DEVICE_MEMORY); - // Double the size until meet the requirement. This also helps reducing the fragmentation. Since + // Double the size until the requirement is met. This also helps reduce fragmentation. Since // this is global pool, we have less worry about memory waste. - VkDeviceSize newSize = mSize; + // If this is the first buffer block allocation from an empty pool, the initial size is used. + // However, the preferred size will be used for future blocks in the same pool. + ASSERT(mInitialSize <= mPreferredSize); + VkDeviceSize newSize = mBufferBlocks.empty() ? mInitialSize : mPreferredSize; while (newSize < sizeInBytes) { newSize <<= 1; @@ -4126,9 +3194,14 @@ VkResult BufferPool::allocateNewBuffer(ErrorContext *context, VkDeviceSize sizeI VkMemoryPropertyFlags memoryPropertyFlagsOut; VkDeviceSize sizeOut; uint32_t memoryTypeIndex; - VK_RESULT_TRY(AllocateBufferMemory(context, MemoryAllocationType::Buffer, memoryPropertyFlags, - &memoryPropertyFlagsOut, nullptr, &buffer.get(), - &memoryTypeIndex, &deviceMemory.get(), &sizeOut)); + + const void *extraAllocationInfoPtr = context->getFeatures().supportsBufferDeviceAddress.enabled + ? &kMemoryAllocateDeviceAddressFlags + : nullptr; + + VK_RESULT_TRY(AllocateBufferMemory( + context, MemoryAllocationType::Buffer, memoryPropertyFlags, &memoryPropertyFlagsOut, + extraAllocationInfoPtr, &buffer.get(), &memoryTypeIndex, &deviceMemory.get(), &sizeOut)); ASSERT(sizeOut >= mSize); // Allocate bufferBlock @@ -4188,9 +3261,16 @@ VkResult BufferPool::allocateBuffer(ErrorContext *context, VkMemoryPropertyFlags memoryPropertyFlagsOut; VkDeviceSize sizeOut; uint32_t memoryTypeIndex; - VK_RESULT_TRY(AllocateBufferMemory( - context, MemoryAllocationType::Buffer, memoryPropertyFlags, &memoryPropertyFlagsOut, - nullptr, &buffer.get(), &memoryTypeIndex, &deviceMemory.get(), &sizeOut)); + + const void *extraAllocationInfoPtr = + context->getFeatures().supportsBufferDeviceAddress.enabled + ? &kMemoryAllocateDeviceAddressFlags + : nullptr; + + VK_RESULT_TRY(AllocateBufferMemory(context, MemoryAllocationType::Buffer, + memoryPropertyFlags, &memoryPropertyFlagsOut, + extraAllocationInfoPtr, &buffer.get(), &memoryTypeIndex, + &deviceMemory.get(), &sizeOut)); ASSERT(sizeOut >= alignedSize); suballocation->initWithEntireBuffer(context, buffer.get(), MemoryAllocationType::Buffer, @@ -4229,7 +3309,7 @@ VkResult BufferPool::allocateBuffer(ErrorContext *context, while (!mEmptyBufferBlocks.empty()) { std::unique_ptr &block = mEmptyBufferBlocks.back(); - if (block->getMemorySize() < mSize) + if (block->getMemorySize() < mSize || block->getMemorySize() < alignedSize) { mTotalMemorySize -= block->getMemorySize(); block->destroy(context->getRenderer()); @@ -4270,7 +3350,9 @@ void BufferPool::destroy(Renderer *renderer, bool orphanNonEmptyBufferBlock) else { // When orphan is not allowed, all BufferBlocks must be empty. - ASSERT(orphanNonEmptyBufferBlock); + // If Device is lost due to errors then add non-empty BufferBlocks + // to the orphan list to be freed towards end. + ASSERT(renderer->isDeviceLost() || orphanNonEmptyBufferBlock); renderer->addBufferBlockToOrphanList(block.release()); } } @@ -4496,7 +3578,10 @@ void DescriptorPoolHelper::destroyGarbage() } // DynamicDescriptorPool implementation. -DynamicDescriptorPool::DynamicDescriptorPool() : mCachedDescriptorSetLayout(VK_NULL_HANDLE) {} +DynamicDescriptorPool::DynamicDescriptorPool() : mCachedDescriptorSetLayout(VK_NULL_HANDLE) +{ + mDescriptorPools.reserve(32); +} DynamicDescriptorPool::~DynamicDescriptorPool() { @@ -4530,7 +3615,7 @@ angle::Result DynamicDescriptorPool::init(ErrorContext *context, ASSERT(setSizeCount); ASSERT(mDescriptorPools.empty()); ASSERT(mCachedDescriptorSetLayout == VK_NULL_HANDLE); - + mPoolSizes.reserve(setSizeCount); mPoolSizes.assign(setSizes, setSizes + setSizeCount); mCachedDescriptorSetLayout = descriptorSetLayout.getHandle(); @@ -4625,6 +3710,9 @@ bool DynamicDescriptorPool::evictStaleDescriptorSets(Renderer *renderer, // Evict it from the cache and remove it from LRU list. bool removed = mDescriptorSetCache.eraseDescriptorSet(it->sharedCacheKey->getDesc()); ASSERT(removed); + // Invalidate the sharedCacheKey so that they could be reused. + it->sharedCacheKey->destroy(renderer->getDevice()); + ASSERT(!it->sharedCacheKey->valid()); // Note that erase it from LRU list will "destroy" descriptorSet. Since we // never actually destroy descriptorSet, it will just add to the garbage list. Here we @@ -4873,6 +3961,13 @@ void DynamicDescriptorPool::checkAndDestroyUnusedPool(Renderer *renderer) } } +// For ASSERT only +bool DynamicDescriptorPool::hasCachedDescriptorSet(const DescriptorSetDesc &desc) const +{ + DescriptorSetLRUListIterator listIterator; + return mDescriptorSetCache.getDescriptorSet(desc, &listIterator); +} + // For testing only! uint32_t DynamicDescriptorPool::GetMaxSetsPerPoolForTesting() { @@ -4901,7 +3996,9 @@ void DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(uint32_t maxSe template DynamicallyGrowingPool::DynamicallyGrowingPool() : mPoolSize(0), mCurrentPool(0), mCurrentFreeEntry(0) -{} +{ + mPools.reserve(64); +} template DynamicallyGrowingPool::~DynamicallyGrowingPool() = default; @@ -5178,7 +4275,7 @@ void QueryHelper::endQueryImpl(ContextVk *contextVk, CommandBufferT *commandBuff angle::Result QueryHelper::beginQuery(ContextVk *contextVk) { - if (contextVk->hasActiveRenderPass()) + if (contextVk->hasStartedRenderPass()) { ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass( RenderPassClosureReason::BeginNonRenderPassQuery)); @@ -5196,16 +4293,16 @@ angle::Result QueryHelper::beginQuery(ContextVk *contextVk) angle::Result QueryHelper::endQuery(ContextVk *contextVk) { - if (contextVk->hasActiveRenderPass()) + if (contextVk->hasStartedRenderPass()) { ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass( RenderPassClosureReason::EndNonRenderPassQuery)); } - CommandBufferAccess access; + CommandResources resources; OutsideRenderPassCommandBuffer *commandBuffer; - access.onQueryAccess(this); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + resources.onQueryAccess(this); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); ANGLE_TRY(contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd)); @@ -5254,16 +4351,16 @@ void QueryHelper::endRenderPassQuery(ContextVk *contextVk) angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk) { - if (contextVk->hasActiveRenderPass()) + if (contextVk->hasStartedRenderPass()) { ANGLE_TRY( contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TimestampQuery)); } - CommandBufferAccess access; + CommandResources resources; OutsideRenderPassCommandBuffer *commandBuffer; - access.onQueryAccess(this); - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + resources.onQueryAccess(this); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); writeTimestamp(contextVk, commandBuffer); return angle::Result::Continue; } @@ -5274,7 +4371,7 @@ void QueryHelper::writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBu const QueryPool &queryPool = getQueryPool(); resetQueryPoolImpl(contextVk, queryPool, primary); - primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery); + primary->writeTimestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, queryPool, mQuery); } void QueryHelper::writeTimestamp(ContextVk *contextVk, @@ -5282,7 +4379,7 @@ void QueryHelper::writeTimestamp(ContextVk *contextVk, { const QueryPool &queryPool = getQueryPool(); resetQueryPoolImpl(contextVk, queryPool, commandBuffer); - commandBuffer->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery); + commandBuffer->writeTimestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, queryPool, mQuery); } bool QueryHelper::hasSubmittedCommands() const @@ -5386,18 +4483,6 @@ void SemaphoreHelper::deinit() mSemaphore = nullptr; } -PipelineStage GetPipelineStage(gl::ShaderType stage) -{ - const PipelineStage pipelineStage = kPipelineStageShaderMap[stage]; - ASSERT(pipelineStage == PipelineStage::VertexShader || - pipelineStage == PipelineStage::TessellationControl || - pipelineStage == PipelineStage::TessellationEvaluation || - pipelineStage == PipelineStage::GeometryShader || - pipelineStage == PipelineStage::FragmentShader || - pipelineStage == PipelineStage::ComputeShader); - return pipelineStage; -} - // PipelineBarrier implementation. void PipelineBarrier::addDiagnosticsString(std::ostringstream &out) const { @@ -5441,16 +4526,22 @@ void PipelineBarrierArray::execute(Renderer *renderer, PrimaryCommandBuffer *pri void PipelineBarrierArray::addDiagnosticsString(std::ostringstream &out) const { - out << "Memory Barrier: "; + std::ostringstream barrierStream; + barrierStream << "Memory Barrier: "; + bool haveBarrierLog = false; for (PipelineStage pipelineStage : mBarrierMask) { const PipelineBarrier &barrier = mBarriers[pipelineStage]; if (!barrier.isEmpty()) { - barrier.addDiagnosticsString(out); + haveBarrierLog = true; + barrier.addDiagnosticsString(barrierStream); } } - out << "\\l"; + if (haveBarrierLog) + { + out << barrierStream.str() << "\\l"; + } } // BufferHelper implementation. @@ -5496,9 +4587,14 @@ BufferHelper &BufferHelper::operator=(BufferHelper &&other) { mCurrentReadEvents = std::move(other.mCurrentReadEvents); } - mTransformFeedbackWriteHeuristicBits = std::move(other.mTransformFeedbackWriteHeuristicBits); + mXFBOrComputeWriteHeuristicBits = std::move(other.mXFBOrComputeWriteHeuristicBits); mSerial = other.mSerial; - mClientBuffer = std::move(other.mClientBuffer); + + // BufferHelper is usually std::move()'ed when the GL buffer backing is internally recreated as + // an optimization, or for other internal buffer allocation reasons. It should never happen for + // buffers that are backed by external memory. + ASSERT(other.mClientBuffer == nullptr); + mClientBuffer = nullptr; return *this; } @@ -5515,14 +4611,9 @@ angle::Result BufferHelper::init(ErrorContext *context, VkBufferCreateInfo modifiedCreateInfo; const VkBufferCreateInfo *createInfo = &requestedCreateInfo; - if (renderer->getFeatures().padBuffersToMaxVertexAttribStride.enabled) - { - const VkDeviceSize maxVertexAttribStride = renderer->getMaxVertexAttribStride(); - ASSERT(maxVertexAttribStride); - modifiedCreateInfo = requestedCreateInfo; - modifiedCreateInfo.size += maxVertexAttribStride; - createInfo = &modifiedCreateInfo; - } + modifiedCreateInfo = requestedCreateInfo; + modifiedCreateInfo.size = renderer->padVertexAttribBufferSizeIfNeeded(requestedCreateInfo.size); + createInfo = &modifiedCreateInfo; VkMemoryPropertyFlags requiredFlags = (memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); @@ -5551,10 +4642,16 @@ angle::Result BufferHelper::init(ErrorContext *context, DeviceScoped deviceMemory(renderer->getDevice()); VkDeviceSize sizeOut; uint32_t bufferMemoryTypeIndex; - ANGLE_VK_TRY(context, - AllocateBufferMemory(context, MemoryAllocationType::Buffer, memoryPropertyFlagsOut, - &memoryPropertyFlagsOut, nullptr, &buffer.get(), - &bufferMemoryTypeIndex, &deviceMemory.get(), &sizeOut)); + + const void *extraAllocationInfoPtr = context->getFeatures().supportsBufferDeviceAddress.enabled + ? &kMemoryAllocateDeviceAddressFlags + : nullptr; + + ANGLE_VK_TRY(context, AllocateBufferMemory( + context, MemoryAllocationType::Buffer, memoryPropertyFlagsOut, + &memoryPropertyFlagsOut, extraAllocationInfoPtr, &buffer.get(), + &bufferMemoryTypeIndex, &deviceMemory.get(), &sizeOut)); + ASSERT(sizeOut >= createInfo->size); mSuballocation.initWithEntireBuffer(context, buffer.get(), MemoryAllocationType::Buffer, @@ -5616,6 +4713,82 @@ angle::Result BufferHelper::initExternal(ErrorContext *context, return angle::Result::Continue; } +angle::Result BufferHelper::initAndAcquireFromExternalMemory( + Context *context, + VkMemoryPropertyFlags memoryProperties, + const VkBufferCreateInfo &requestedCreateInfo, + const VkExternalMemoryHandleTypeFlagBits externalMemoryHandleType, + const int32_t sharedBufferFD) +{ + Renderer *renderer = context->getRenderer(); + ASSERT(renderer); + + initializeBarrierTracker(context); + + VkBufferCreateInfo modifiedCreateInfo = requestedCreateInfo; + VkExternalMemoryBufferCreateInfo externCreateInfo = {}; + externCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; + externCreateInfo.handleTypes = externalMemoryHandleType; + externCreateInfo.pNext = nullptr; + modifiedCreateInfo.pNext = &externCreateInfo; + + DeviceScoped buffer(renderer->getDevice()); + ANGLE_VK_TRY(context, buffer.get().init(renderer->getDevice(), modifiedCreateInfo)); + + DeviceScoped deviceMemory(renderer->getDevice()); + VkMemoryPropertyFlags memoryPropertyFlagsOut; + VkDeviceSize allocatedSize = 0; + uint32_t memoryTypeIndex; + ANGLE_TRY(InitExternalSharedFDMemory(context, externalMemoryHandleType, sharedBufferFD, + memoryProperties, &buffer.get(), &memoryPropertyFlagsOut, + &memoryTypeIndex, &deviceMemory.get(), &allocatedSize)); + + mSuballocation.initWithEntireBuffer(context, buffer.get(), MemoryAllocationType::BufferExternal, + memoryTypeIndex, deviceMemory.get(), memoryPropertyFlagsOut, + requestedCreateInfo.size, allocatedSize); + if (isHostVisible()) + { + uint8_t *ptrOut; + ANGLE_TRY(map(context, &ptrOut)); + } + return angle::Result::Continue; +} + +angle::Result BufferHelper::initHostExternal(ErrorContext *context, + VkMemoryPropertyFlags memoryProperties, + const VkBufferCreateInfo &requestedCreateInfo, + void *hostPtr) +{ + Renderer *renderer = context->getRenderer(); + + initializeBarrierTracker(context); + + VkBufferCreateInfo modifiedCreateInfo = requestedCreateInfo; + VkExternalMemoryBufferCreateInfo externCreateInfo = {}; + externCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; + externCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + externCreateInfo.pNext = nullptr; + modifiedCreateInfo.pNext = &externCreateInfo; + + DeviceScoped buffer(renderer->getDevice()); + ANGLE_VK_TRY(context, buffer.get().init(renderer->getDevice(), modifiedCreateInfo)); + + DeviceScoped deviceMemory(renderer->getDevice()); + VkMemoryPropertyFlags memoryPropertyFlagsOut; + VkDeviceSize allocatedSize = 0; + uint32_t memoryTypeIndex = UINT32_MAX; + + ANGLE_TRY(InitExternalHostMemory(context, hostPtr, memoryProperties, &buffer.get(), + &memoryPropertyFlagsOut, &memoryTypeIndex, &deviceMemory.get(), + &allocatedSize)); + + mSuballocation.initWithEntireBuffer(context, buffer.get(), MemoryAllocationType::BufferExternal, + memoryTypeIndex, deviceMemory.get(), memoryPropertyFlagsOut, + requestedCreateInfo.size, allocatedSize); + + return angle::Result::Continue; +} + VkResult BufferHelper::initSuballocation(Context *context, uint32_t memoryTypeIndex, size_t size, @@ -5624,19 +4797,14 @@ VkResult BufferHelper::initSuballocation(Context *context, BufferPool *pool) { ASSERT(pool != nullptr); + ASSERT(size != 0); Renderer *renderer = context->getRenderer(); // We should reset these in case the BufferHelper object has been released and called // initSuballocation again. initializeBarrierTracker(context); - if (renderer->getFeatures().padBuffersToMaxVertexAttribStride.enabled) - { - const VkDeviceSize maxVertexAttribStride = renderer->getMaxVertexAttribStride(); - ASSERT(maxVertexAttribStride); - size += maxVertexAttribStride; - } - + size = static_cast(renderer->padVertexAttribBufferSizeIfNeeded(size)); VK_RESULT_TRY(pool->allocateBuffer(context, size, alignment, &mSuballocation)); context->getPerfCounters().bufferSuballocationCalls++; @@ -5687,6 +4855,8 @@ angle::Result BufferHelper::initializeNonZeroMemory(ErrorContext *context, commandBuffer.copyBuffer(stagingBuffer.getBuffer(), getBuffer(), 1, ©Region); + renderer->insertSubmitDebugMarkerInCommandBuffer(commandBuffer, + QueueSubmitReason::InitNonZeroMemory); ANGLE_VK_TRY(context, commandBuffer.end()); QueueSerial queueSerial; @@ -5718,6 +4888,22 @@ angle::Result BufferHelper::initializeNonZeroMemory(ErrorContext *context, const Buffer &BufferHelper::getBufferForVertexArray(ContextVk *contextVk, VkDeviceSize actualDataSize, VkDeviceSize *offsetOut) +{ + ASSERT(!contextVk->getFeatures().supportsBindVertexBuffers2.enabled); + return getBufferForVertexArrayImpl(contextVk, actualDataSize, offsetOut); +} + +const Buffer &BufferHelper::getIndexBufferForVertexArray(ContextVk *contextVk, + VkDeviceSize actualDataSize, + VkDeviceSize *offsetOut) +{ + ASSERT(!contextVk->getFeatures().supportsMaintenance5.enabled); + return getBufferForVertexArrayImpl(contextVk, actualDataSize, offsetOut); +} + +const Buffer &BufferHelper::getBufferForVertexArrayImpl(ContextVk *contextVk, + VkDeviceSize actualDataSize, + VkDeviceSize *offsetOut) { ASSERT(mSuballocation.valid()); ASSERT(actualDataSize <= mSuballocation.getSize()); @@ -5779,6 +4965,7 @@ void BufferHelper::destroy(Renderer *renderer) { mCurrentWriteEvent.release(renderer); mCurrentReadEvents.release(renderer); + ASSERT(mDescriptorSetCacheManager.allValidEntriesAreCached(nullptr)); mDescriptorSetCacheManager.destroyKeys(renderer); unmap(renderer); mBufferWithUserSize.destroy(renderer->getDevice()); @@ -5811,12 +4998,6 @@ void BufferHelper::releaseImpl(Renderer *renderer) if (mSuballocation.valid()) { - if (!mSuballocation.isSuballocated()) - { - // Destroy cacheKeys now to avoid getting into situation that having to destroy - // descriptorSet from garbage collection thread. - mSuballocation.getBufferBlock()->releaseAllCachedDescriptorSetCacheKeys(renderer); - } renderer->collectSuballocationGarbage(mUse, std::move(mSuballocation), std::move(mBufferWithUserSize)); } @@ -5831,9 +5012,11 @@ void BufferHelper::releaseImpl(Renderer *renderer) } } -void BufferHelper::releaseBufferAndDescriptorSetCache(Context *context) +void BufferHelper::releaseBufferAndDescriptorSetCache(ContextVk *contextVk) { - Renderer *renderer = context->getRenderer(); + Renderer *renderer = contextVk->getRenderer(); + + ASSERT(mDescriptorSetCacheManager.allValidEntriesAreCached(contextVk)); if (renderer->hasResourceUseFinished(getResourceUse())) { mDescriptorSetCacheManager.destroyKeys(renderer); @@ -5843,7 +5026,7 @@ void BufferHelper::releaseBufferAndDescriptorSetCache(Context *context) mDescriptorSetCacheManager.releaseKeys(renderer); } - release(context); + release(contextVk); } angle::Result BufferHelper::map(ErrorContext *context, uint8_t **ptrOut) @@ -5934,7 +5117,7 @@ void BufferHelper::recordReadBarrier(Context *context, { // If the type of read already tracked by mCurrentReadEvents, it means we must already inserted // the barrier when mCurrentReadEvents is set. No new barrier is needed. - EventStage eventStage = kBufferMemoryBarrierData[stageIndex].eventStage; + EventStage eventStage = GetBufferMemoryBarrierData(stageIndex).eventStage; if (mCurrentReadEvents.hasEventAndAccess(eventStage, readAccessType)) { ASSERT((context->getRenderer()->getPipelineStageMask(eventStage) & @@ -5984,7 +5167,7 @@ void BufferHelper::recordReadEvent(Context *context, // dependency between fragment and vertex/transfer/compute stages. But it also comes with // higher overhead. In order to strike the balance, right now we only track it with VkEvent // if it ever written by transform feedback. - useVkEvent = mTransformFeedbackWriteHeuristicBits.any(); + useVkEvent = mXFBOrComputeWriteHeuristicBits.any(); } if (useVkEvent && refCountedEventArray->initEventAtStage(context, eventStage)) @@ -6027,6 +5210,8 @@ void BufferHelper::recordWriteBarrier(Context *context, { Renderer *renderer = context->getRenderer(); + updatePipelineStageWriteHistory(context, stageIndex); + // Barrier against prior read VkEvents. if (!mCurrentReadEvents.empty()) { @@ -6112,20 +5297,19 @@ void BufferHelper::recordWriteEvent(Context *context, PipelineStage writeStage, RefCountedEventArray *refCountedEventArray) { - EventStage eventStage = kBufferMemoryBarrierData[writeStage].eventStage; + EventStage eventStage = GetBufferMemoryBarrierData(writeStage).eventStage; bool useVkEvent = false; if (context->getFeatures().useVkEventForBufferBarrier.enabled && eventStage != EventStage::InvalidEnum) { ASSERT(mCurrentReadEvents.empty()); - updatePipelineStageWriteHistory(writeStage); // VkCmdSetEvent can remove the unnecessary GPU pipeline bubble that comes from false // dependency between fragment and vertex/transfer/compute stages. But it also comes with // higher overhead. In order to strike the balance, right now we only track it with VkEvent // if it ever written by transform feedback. - useVkEvent = mTransformFeedbackWriteHeuristicBits.any(); + useVkEvent = mXFBOrComputeWriteHeuristicBits.any(); // We only track one write event. In case of multiple writes like write from different // shader stages in the same render pass, only the first write is tracked by event, @@ -6221,6 +5405,20 @@ void BufferHelper::fillWithPattern(const void *pattern, return; } +VkDeviceAddress BufferHelper::getDeviceAddress(Context *context) +{ + ASSERT(context->getFeatures().supportsBufferDeviceAddress.enabled); + ASSERT(valid()); + + VkBufferDeviceAddressInfo info{}; + info.buffer = getBuffer().getHandle(); + info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + info.pNext = NULL; + VkDevice device = context->getDevice(); + + return vkGetBufferDeviceAddressKHR(device, &info); +} + // Used for ImageHelper non-zero memory allocation when useVmaForImageSuballocation is disabled. angle::Result InitMappableDeviceMemory(ErrorContext *context, DeviceMemory *deviceMemory, @@ -6269,18 +5467,18 @@ void ImageHelper::resetCachedProperties() mImageType = VK_IMAGE_TYPE_2D; mTilingMode = VK_IMAGE_TILING_OPTIMAL; mCreateFlags = kVkImageCreateFlagsNone; - mUsage = 0; + mRequestedUsage = 0; mExtents = {}; mRotatedAspectRatio = false; mIntendedFormatID = angle::FormatID::NONE; mActualFormatID = angle::FormatID::NONE; mSamples = 1; mImageSerial = kInvalidImageSerial; - mCurrentLayout = ImageLayout::Undefined; + mCurrentAccess = ImageAccess::Undefined; mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; mIsReleasedToExternal = false; mIsForeignImage = false; - mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; + mLastNonShaderReadOnlyAccess = ImageAccess::Undefined; mCurrentShaderReadStageMask = 0; mFirstAllocatedLevel = gl::LevelIndex(0); mLayerCount = 0; @@ -6289,34 +5487,37 @@ void ImageHelper::resetCachedProperties() mAllocationSize = 0; mMemoryAllocationType = MemoryAllocationType::InvalidEnum; mMemoryTypeIndex = kInvalidMemoryTypeIndex; + mTileMemoryCompatible = false; + mUseTileMemory = false; std::fill(mViewFormats.begin(), mViewFormats.begin() + mViewFormats.max_size(), VK_FORMAT_UNDEFINED); mYcbcrConversionDesc.reset(); mCurrentSingleClearValue.reset(); mRenderPassUsageFlags.reset(); + mVkImageCreateInfo = {}; setEntireContentUndefined(); } -void ImageHelper::setEntireContentDefined() +ANGLE_INLINE void ImageHelper::setEntireContentDefined() { - for (LevelContentDefinedMask &levelContentDefined : mContentDefined) + for (LevelContentDefinedMask &levelContentDefined : mVkImageContentDefined) { levelContentDefined.set(); } - for (LevelContentDefinedMask &levelContentDefined : mStencilContentDefined) + for (LevelContentDefinedMask &levelContentDefined : mVkImageStencilContentDefined) { levelContentDefined.set(); } } -void ImageHelper::setEntireContentUndefined() +ANGLE_INLINE void ImageHelper::setEntireContentUndefined() { - for (LevelContentDefinedMask &levelContentDefined : mContentDefined) + for (LevelContentDefinedMask &levelContentDefined : mVkImageContentDefined) { levelContentDefined.reset(); } - for (LevelContentDefinedMask &levelContentDefined : mStencilContentDefined) + for (LevelContentDefinedMask &levelContentDefined : mVkImageStencilContentDefined) { levelContentDefined.reset(); } @@ -6326,11 +5527,11 @@ void ImageHelper::setEntireContentUndefined() // emulated formats have a clear staged. } -void ImageHelper::setContentDefined(LevelIndex levelStart, - uint32_t levelCount, - uint32_t layerStart, - uint32_t layerCount, - VkImageAspectFlags aspectFlags) +ANGLE_INLINE void ImageHelper::setContentDefined(LevelIndex levelStart, + uint32_t levelCount, + uint32_t layerStart, + uint32_t layerCount, + VkImageAspectFlags aspectFlags) { // Mark the range as defined. Layers above 8 are discarded, and are always assumed to have // defined contents. @@ -6348,35 +5549,49 @@ void ImageHelper::setContentDefined(LevelIndex levelStart, if ((aspectFlags & ~VK_IMAGE_ASPECT_STENCIL_BIT) != 0) { - getLevelContentDefined(level) |= layerRangeBits; + setLevelContentDefined(level, layerRangeBits); } if ((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) != 0) { - getLevelStencilContentDefined(level) |= layerRangeBits; + setLevelStencilContentDefined(level, layerRangeBits); } } } -ImageHelper::LevelContentDefinedMask &ImageHelper::getLevelContentDefined(LevelIndex level) +ANGLE_INLINE void ImageHelper::setLevelContentDefined(LevelIndex level, + const uint8_t layerRangeBits) +{ + mVkImageContentDefined[level.get()] |= layerRangeBits; +} + +ANGLE_INLINE void ImageHelper::clearLevelContentDefined(LevelIndex level, + const uint8_t layerRangeBits) +{ + mVkImageContentDefined[level.get()] &= ~layerRangeBits; +} + +ANGLE_INLINE void ImageHelper::setLevelStencilContentDefined(LevelIndex level, + const uint8_t layerRangeBits) { - return mContentDefined[level.get()]; + mVkImageStencilContentDefined[level.get()] |= layerRangeBits; } -ImageHelper::LevelContentDefinedMask &ImageHelper::getLevelStencilContentDefined(LevelIndex level) +ANGLE_INLINE void ImageHelper::clearLevelStencilContentDefined(LevelIndex level, + const uint8_t layerRangeBits) { - return mStencilContentDefined[level.get()]; + mVkImageStencilContentDefined[level.get()] &= ~layerRangeBits; } -const ImageHelper::LevelContentDefinedMask &ImageHelper::getLevelContentDefined( +ANGLE_INLINE const ImageHelper::LevelContentDefinedMask &ImageHelper::getLevelContentDefined( LevelIndex level) const { - return mContentDefined[level.get()]; + return mVkImageContentDefined[level.get()]; } -const ImageHelper::LevelContentDefinedMask &ImageHelper::getLevelStencilContentDefined( +ANGLE_INLINE const ImageHelper::LevelContentDefinedMask &ImageHelper::getLevelStencilContentDefined( LevelIndex level) const { - return mStencilContentDefined[level.get()]; + return mVkImageStencilContentDefined[level.get()]; } YcbcrConversionDesc ImageHelper::deriveConversionDesc(ErrorContext *context, @@ -6441,54 +5656,19 @@ angle::Result ImageHelper::init(ErrorContext *context, uint32_t mipLevels, uint32_t layerCount, bool isRobustResourceInitEnabled, - bool hasProtectedContent) + bool hasProtectedContent, + TileMemory tileMemoryPreference) { return initExternal(context, textureType, extents, format.getIntendedFormatID(), format.getActualRenderableImageFormatID(), samples, usage, - kVkImageCreateFlagsNone, ImageLayout::Undefined, nullptr, firstLevel, + kVkImageCreateFlagsNone, ImageAccess::Undefined, nullptr, firstLevel, mipLevels, layerCount, isRobustResourceInitEnabled, hasProtectedContent, + tileMemoryPreference, deriveConversionDesc(context, format.getActualRenderableImageFormatID(), format.getIntendedFormatID()), nullptr); } -angle::Result ImageHelper::initFromCreateInfo(ErrorContext *context, - const VkImageCreateInfo &requestedCreateInfo, - VkMemoryPropertyFlags memoryPropertyFlags) -{ - ASSERT(!valid()); - ASSERT(!IsAnySubresourceContentDefined(mContentDefined)); - ASSERT(!IsAnySubresourceContentDefined(mStencilContentDefined)); - - mImageType = requestedCreateInfo.imageType; - mExtents = requestedCreateInfo.extent; - mRotatedAspectRatio = false; - mSamples = std::max((int)requestedCreateInfo.samples, 1); - mImageSerial = context->getRenderer()->getResourceSerialFactory().generateImageSerial(); - mLayerCount = requestedCreateInfo.arrayLayers; - mLevelCount = requestedCreateInfo.mipLevels; - mUsage = requestedCreateInfo.usage; - - // Validate that mLayerCount is compatible with the image type - ASSERT(requestedCreateInfo.imageType != VK_IMAGE_TYPE_3D || mLayerCount == 1); - ASSERT(requestedCreateInfo.imageType != VK_IMAGE_TYPE_2D || mExtents.depth == 1); - - mCurrentLayout = ImageLayout::Undefined; - - ANGLE_VK_TRY(context, mImage.init(context->getDevice(), requestedCreateInfo)); - - mVkImageCreateInfo = requestedCreateInfo; - mVkImageCreateInfo.pNext = nullptr; - mVkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - MemoryProperties memoryProperties = {}; - - ANGLE_TRY(initMemoryAndNonZeroFillIfNeeded(context, false, memoryProperties, - memoryPropertyFlags, - vk::MemoryAllocationType::StagingImage)); - return angle::Result::Continue; -} - angle::Result ImageHelper::copyToBufferOneOff(ErrorContext *context, BufferHelper *stagingBuffer, VkBufferImageCopy copyRegion) @@ -6500,11 +5680,14 @@ angle::Result ImageHelper::copyToBufferOneOff(ErrorContext *context, PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get(); VkSemaphore acquireNextImageSemaphore; - recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageLayout::TransferDst, + recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageAccess::TransferDst, renderer->getQueueFamilyIndex(), &commandBuffer, &acquireNextImageSemaphore); commandBuffer.copyBufferToImage(stagingBuffer->getBuffer().getHandle(), getImage(), getCurrentLayout(renderer), 1, ©Region); + + renderer->insertSubmitDebugMarkerInCommandBuffer(commandBuffer, + QueueSubmitReason::CopyBufferToImageOneOff); ANGLE_VK_TRY(context, commandBuffer.end()); QueueSerial submitQueueSerial; @@ -6520,7 +5703,8 @@ angle::Result ImageHelper::initMSAASwapchain(ErrorContext *context, gl::TextureType textureType, const VkExtent3D &extents, bool rotatedAspectRatio, - const Format &format, + angle::FormatID intendedFormatID, + angle::FormatID actualFormatID, GLint samples, VkImageUsageFlags usage, gl::LevelIndex firstLevel, @@ -6529,11 +5713,11 @@ angle::Result ImageHelper::initMSAASwapchain(ErrorContext *context, bool isRobustResourceInitEnabled, bool hasProtectedContent) { - ANGLE_TRY(initExternal(context, textureType, extents, format.getIntendedFormatID(), - format.getActualRenderableImageFormatID(), samples, usage, - kVkImageCreateFlagsNone, ImageLayout::Undefined, nullptr, firstLevel, - mipLevels, layerCount, isRobustResourceInitEnabled, hasProtectedContent, - YcbcrConversionDesc{}, nullptr)); + ANGLE_TRY(initExternal(context, textureType, extents, intendedFormatID, actualFormatID, samples, + usage, kVkImageCreateFlagsNone, ImageAccess::Undefined, nullptr, + firstLevel, mipLevels, layerCount, isRobustResourceInitEnabled, + hasProtectedContent, TileMemory::Prohibited, YcbcrConversionDesc{}, + nullptr)); if (rotatedAspectRatio) { std::swap(mExtents.width, mExtents.height); @@ -6550,19 +5734,20 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, GLint samples, VkImageUsageFlags usage, VkImageCreateFlags additionalCreateFlags, - ImageLayout initialLayout, + ImageAccess initialAccess, const void *externalImageCreateInfo, gl::LevelIndex firstLevel, uint32_t mipLevels, uint32_t layerCount, bool isRobustResourceInitEnabled, bool hasProtectedContent, + TileMemory tileMemoryPreference, YcbcrConversionDesc conversionDesc, const void *compressionControl) { ASSERT(!valid()); - ASSERT(!IsAnySubresourceContentDefined(mContentDefined)); - ASSERT(!IsAnySubresourceContentDefined(mStencilContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageStencilContentDefined)); Renderer *renderer = context->getRenderer(); @@ -6578,7 +5763,7 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, mLayerCount = layerCount; mCreateFlags = vk::GetMinimalImageCreateFlags(renderer, textureType, usage) | additionalCreateFlags; - mUsage = usage; + mRequestedUsage = usage; // Validate that mLayerCount is compatible with the texture type ASSERT(textureType != gl::TextureType::_3D || mLayerCount == 1); @@ -6597,7 +5782,7 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, if (externalImageCreateInfo == nullptr) { imageCreateInfoPNext = DeriveCreateInfoPNext( - context, mUsage, actualFormatID, compressionControl, &imageFormatListInfoStorage, + context, usage, actualFormatID, compressionControl, &imageFormatListInfoStorage, &imageListFormatsStorage, &mCreateFlags); } else @@ -6609,13 +5794,12 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, mYcbcrConversionDesc = conversionDesc; const angle::Format &actualFormat = angle::Format::Get(actualFormatID); - const angle::Format &intendedFormat = angle::Format::Get(intendedFormatID); VkFormat actualVkFormat = GetVkFormatFromFormatID(renderer, actualFormatID); - ANGLE_TRACE_EVENT_INSTANT("gpu.angle.texture_metrics", "ImageHelper::initExternal", - "intended_format", intendedFormat.glInternalFormat, "actual_format", - actualFormat.glInternalFormat, "width", extents.width, "height", - extents.height); + ANGLE_TRACE_EVENT_INSTANT( + "gpu.angle.texture_metrics", "ImageHelper::initExternal", "intended_format", + angle::Format::Get(intendedFormatID).glInternalFormat, "actual_format", + actualFormat.glInternalFormat, "width", extents.width, "height", extents.height); if (actualFormat.isYUV) { @@ -6638,6 +5822,9 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, mCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT; } + VkSampleCountFlagBits sampleCountFlagBits = + gl_vk::GetSamples(mSamples, context->getFeatures().limitSampleCountTo2.enabled); + VkImageCreateInfo imageInfo = {}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.pNext = imageCreateInfoPNext; @@ -6647,20 +5834,50 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, imageInfo.extent = mExtents; imageInfo.mipLevels = mLevelCount; imageInfo.arrayLayers = mLayerCount; - imageInfo.samples = - gl_vk::GetSamples(mSamples, context->getFeatures().limitSampleCountTo2.enabled); + imageInfo.samples = sampleCountFlagBits; imageInfo.tiling = mTilingMode; - imageInfo.usage = mUsage; + imageInfo.usage = mRequestedUsage; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.queueFamilyIndexCount = 0; imageInfo.pQueueFamilyIndices = nullptr; - imageInfo.initialLayout = ConvertImageLayoutToVkImageLayout(renderer, initialLayout); + imageInfo.initialLayout = renderer->getVkImageLayout(initialAccess); + + // DepthStencil format that has emulated channels needs re-stage emulated channel clear after + // reallocate, for now just disable the tile memory for that. + if (tileMemoryPreference == TileMemory::Preferred && + (renderer->getFeatures().simulateTileMemoryForTesting.enabled || + renderer->getFeatures().supportsTileMemoryHeap.enabled) && + !HasEmulatedImageChannels(angle::Format::Get(mIntendedFormatID), + angle::Format::Get(mActualFormatID))) + { + ASSERT(initialAccess == ImageAccess::Undefined); + ASSERT(angle::Format::Get(actualFormatID).hasDepthOrStencilBits()); + ASSERT(imageCreateInfoPNext == nullptr); + + // Remove transfer bits when determining tile memory compatible or not, since tile memory + // does not support transfers. + imageInfo.usage &= ~kImageUsageTransferBits; + mTileMemoryCompatible = IsTileMemoryCompatible(renderer, imageInfo); + if (mTileMemoryCompatible) + { + if (renderer->getFeatures().supportsTileMemoryHeap.enabled) + { + imageInfo.usage |= VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM; + } + mUseTileMemory = true; + } + else + { + // Restore usage bits + imageInfo.usage = mRequestedUsage; + } + } - mCurrentLayout = initialLayout; + mCurrentAccess = initialAccess; mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; mIsReleasedToExternal = false; mIsForeignImage = false; - mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; + mLastNonShaderReadOnlyAccess = ImageAccess::Undefined; mCurrentShaderReadStageMask = 0; ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo)); @@ -6676,7 +5893,7 @@ angle::Result ImageHelper::initExternal(ErrorContext *context, // Consider the contents defined for any image that has the PREINITIALIZED layout, or is // imported from external. - if (initialLayout != ImageLayout::Undefined || externalImageCreateInfo != nullptr) + if (initialAccess != ImageAccess::Undefined || externalImageCreateInfo != nullptr) { setEntireContentDefined(); } @@ -6728,7 +5945,7 @@ const void *ImageHelper::DeriveCreateInfoPNext( } // static -bool ImageHelper::FormatSupportsUsage(Renderer *renderer, +bool ImageHelper::FormatSupportsUsage(const Renderer *renderer, VkFormat format, VkImageType imageType, VkImageTiling tilingMode, @@ -6769,7 +5986,7 @@ void ImageHelper::setImageFormatsFromActualFormat(VkFormat actualFormat, imageFormatsOut.push_back(actualFormat); } -void ImageHelper::deriveImageViewFormatFromCreateInfoPNext(VkImageCreateInfo &imageInfo, +void ImageHelper::deriveImageViewFormatFromCreateInfoPNext(const VkImageCreateInfo &imageInfo, ImageFormats &formatOut) { const VkBaseInStructure *pNextChain = @@ -6817,21 +6034,36 @@ void ImageHelper::deriveExternalImageTiling(const void *createInfoChain) void ImageHelper::releaseImage(Renderer *renderer) { - // mDeviceMemory and mVmaAllocation should not be valid at the same time. - ASSERT(!mDeviceMemory.valid() || !mVmaAllocation.valid()); - if (mDeviceMemory.valid()) + if (mImage.valid()) { - renderer->onMemoryDealloc(mMemoryAllocationType, mAllocationSize, mMemoryTypeIndex, - mDeviceMemory.getHandle()); + GarbageObjects garbageObjects; + garbageObjects.reserve(2); + garbageObjects.emplace_back(GarbageObject::Get(&mImage)); + + // mDeviceMemory and mVmaAllocation should not be valid at the same time. + ASSERT(!mDeviceMemory.valid() || !mVmaAllocation.valid()); + if (mDeviceMemory.valid()) + { + renderer->onMemoryDealloc(mMemoryAllocationType, mAllocationSize, mMemoryTypeIndex, + mDeviceMemory.getHandle()); + garbageObjects.emplace_back(GarbageObject::Get(&mDeviceMemory)); + } + if (mVmaAllocation.valid()) + { + renderer->onMemoryDealloc(mMemoryAllocationType, mAllocationSize, mMemoryTypeIndex, + mVmaAllocation.getHandle()); + garbageObjects.emplace_back(GarbageObject::Get(&mVmaAllocation)); + } + renderer->collectGarbage(mUse, std::move(garbageObjects)); } - if (mVmaAllocation.valid()) + else { - renderer->onMemoryDealloc(mMemoryAllocationType, mAllocationSize, mMemoryTypeIndex, - mVmaAllocation.getHandle()); + ASSERT(!mDeviceMemory.valid()); + ASSERT(!mVmaAllocation.valid()); } + mCurrentEvent.release(renderer); mLastNonShaderReadOnlyEvent.release(renderer); - renderer->collectGarbage(mUse, &mImage, &mDeviceMemory, &mVmaAllocation); mViewFormats.clear(); mUse.reset(); mImageSerial = kInvalidImageSerial; @@ -6858,6 +6090,13 @@ void ImageHelper::finalizeImageLayoutInShareContexts(Renderer *renderer, { vk::GetImpl(context.second)->finalizeImageLayout(this, imageSiblingSerial); } + if (mUseTileMemory) + { + for (auto context : contextVk->getShareGroup()->getContexts()) + { + vk::GetImpl(context.second)->removeImageWithTileMemory(this); + } + } } } @@ -6866,11 +6105,12 @@ void ImageHelper::releaseStagedUpdates(Renderer *renderer) ASSERT(validateSubresourceUpdateRefCountsConsistent()); // Remove updates that never made it to the texture. - for (std::vector &levelUpdates : mSubresourceUpdates) + for (SubresourceUpdates &levelUpdates : mSubresourceUpdates) { - for (SubresourceUpdate &update : levelUpdates) + while (!levelUpdates.empty()) { - update.release(renderer); + levelUpdates.front().release(renderer); + levelUpdates.pop_front(); } } @@ -6941,7 +6181,7 @@ angle::Result ImageHelper::initializeNonZeroMemory(ErrorContext *context, // Queue a DMA copy. VkSemaphore acquireNextImageSemaphore; - recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageLayout::TransferDst, + recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageAccess::TransferDst, context->getDeviceQueueIndex(), &commandBuffer, &acquireNextImageSemaphore); // SwapChain image should not come here @@ -6972,15 +6212,14 @@ angle::Result ImageHelper::initializeNonZeroMemory(ErrorContext *context, } commandBuffer.copyBufferToImage(stagingBuffer.getBuffer().getHandle(), mImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); + getCurrentLayout(renderer), 1, ©Region); if (hasBothDepthAndStencil) { copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; commandBuffer.copyBufferToImage(stagingBuffer.getBuffer().getHandle(), mImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); + getCurrentLayout(renderer), 1, ©Region); } } } @@ -7021,6 +6260,8 @@ angle::Result ImageHelper::initializeNonZeroMemory(ErrorContext *context, } } + renderer->insertSubmitDebugMarkerInCommandBuffer(commandBuffer, + QueueSubmitReason::InitNonZeroMemory); ANGLE_VK_TRY(context, commandBuffer.end()); QueueSerial queueSerial; @@ -7039,7 +6280,6 @@ angle::Result ImageHelper::initializeNonZeroMemory(ErrorContext *context, } VkResult ImageHelper::initMemory(ErrorContext *context, - const MemoryProperties &memoryProperties, VkMemoryPropertyFlags flags, VkMemoryPropertyFlags excludedFlags, const VkMemoryRequirements *memoryRequirements, @@ -7053,7 +6293,35 @@ VkResult ImageHelper::initMemory(ErrorContext *context, // To allocate memory here, if possible, we use the image memory suballocator which uses VMA. ASSERT(excludedFlags < VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM); Renderer *renderer = context->getRenderer(); - if (renderer->getFeatures().useVmaForImageSuballocation.enabled) + + // First try allocate tile memory if requested + ASSERT(!mDeviceMemory.valid()); + if (mUseTileMemory) + { + if (renderer->getFeatures().supportsTileMemoryHeap.enabled) + { + AllocateImageMemoryFromTileHeap(context, mMemoryAllocationType, flags, flagsOut, + &mImage, &mMemoryTypeIndex, &mDeviceMemory, + &mAllocationSize); + } + else + { + ASSERT(renderer->getFeatures().simulateTileMemoryForTesting.enabled); + AllocateImageMemory(context, mMemoryAllocationType, flags, flagsOut, nullptr, &mImage, + &mMemoryTypeIndex, &mDeviceMemory, &mAllocationSize); + } + + if (mDeviceMemory.valid()) + { + context->getPerfCounters().tileMemoryImages++; + } + else + { + mUseTileMemory = false; + } + } + + if (!mDeviceMemory.valid() && renderer->getFeatures().useVmaForImageSuballocation.enabled) { // While it may be preferable to allocate the image on the device, it should also be // possible to allocate on other memory types if the device is out of memory. @@ -7064,11 +6332,16 @@ VkResult ImageHelper::initMemory(ErrorContext *context, memoryRequirements, allocateDedicatedMemory, mMemoryAllocationType, &mVmaAllocation, flagsOut, &mMemoryTypeIndex, &mAllocationSize)); } - else + else if (!mDeviceMemory.valid()) { - VK_RESULT_TRY(AllocateImageMemory(context, mMemoryAllocationType, flags, flagsOut, nullptr, - &mImage, &mMemoryTypeIndex, &mDeviceMemory, - &mAllocationSize)); + const void *extraAllocationInfoPtr = + context->getFeatures().supportsBufferDeviceAddress.enabled + ? &kMemoryAllocateDeviceAddressFlags + : nullptr; + + VK_RESULT_TRY(AllocateImageMemory(context, mMemoryAllocationType, flags, flagsOut, + extraAllocationInfoPtr, &mImage, &mMemoryTypeIndex, + &mDeviceMemory, &mAllocationSize)); } mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); @@ -7082,7 +6355,6 @@ VkResult ImageHelper::initMemory(ErrorContext *context, angle::Result ImageHelper::initMemoryAndNonZeroFillIfNeeded( ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, VkMemoryPropertyFlags flags, MemoryAllocationType allocationType) { @@ -7102,14 +6374,14 @@ angle::Result ImageHelper::initMemoryAndNonZeroFillIfNeeded( renderer->getImageMemorySuballocator().needsDedicatedMemory(memoryRequirements.size); ANGLE_VK_TRY(context, - initMemory(context, memoryProperties, flags, 0, &memoryRequirements, - allocateDedicatedMemory, allocationType, &outputFlags, &outputSize)); + initMemory(context, flags, 0, &memoryRequirements, allocateDedicatedMemory, + allocationType, &outputFlags, &outputSize)); // Memory can only be non-zero initialized if the TRANSFER_DST usage is set. This is normally // the case, but not with |initImplicitMultisampledRenderToTexture| which creates a // lazy-allocated transient image. if (renderer->getFeatures().allocateNonZeroMemory.enabled && - (mUsage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0) + (mVkImageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0) { ANGLE_TRY(initializeNonZeroMemory(context, hasProtectedContent, outputFlags, outputSize)); } @@ -7159,7 +6431,60 @@ angle::Result ImageHelper::initExternalMemory(ErrorContext *context, return angle::Result::Continue; } -angle::Result ImageHelper::initLayerImageView(ErrorContext *context, +angle::Result ImageHelper::fallbackFromTileMemory(ContextVk *contextVk) +{ + ASSERT(mUseTileMemory); + ANGLE_TRACE_EVENT0("gpu.angle", "ImageHelper::fallbackFromTileMemory"); + Renderer *renderer = contextVk->getRenderer(); + UtilsVk &utilsVk = contextVk->getUtils(); + MemoryAllocationType allocationType = mMemoryAllocationType; + + ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW, + "The Vulkan driver has to copy from tile memory to regular memory. " + "Consider calling glInvalidateFramebuffer"); + + // Move the necessary information from this ImageHelper to prevImage + std::unique_ptr prevImage = std::make_unique(); + // Move storage from this object to prevImage + prevImage->copyStateAndMoveStorageFrom(this); + + // Recreate VkImage with original usage bits + mImageSerial = renderer->getResourceSerialFactory().generateImageSerial(); + mVkImageCreateInfo.usage = mRequestedUsage; + ANGLE_VK_TRY(contextVk, mImage.init(contextVk->getDevice(), mVkImageCreateInfo)); + contextVk->getPerfCounters().tileMemoryImages--; + contextVk->getPerfCounters().fallbackFromTileMemory++; + + // reallocate device memory. + VkMemoryRequirements memoryRequirements; + mImage.getMemoryRequirements(renderer->getDevice(), &memoryRequirements); + bool allocateDedicatedMemory = + renderer->getImageMemorySuballocator().needsDedicatedMemory(memoryRequirements.size); + VkMemoryPropertyFlags memoryPropertyFlagsOut; + VkDeviceSize deviceMemorySizeOut; + ANGLE_VK_TRY(contextVk, initMemory(contextVk, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0x0, + &memoryRequirements, allocateDedicatedMemory, allocationType, + &memoryPropertyFlagsOut, &deviceMemorySizeOut)); + + // Copy data from the previous image. + if (prevImage->isVkImageContentDefined()) + { + ANGLE_TRY( + utilsVk.copyImageFromTileMemory(contextVk, getAspectFlags(), this, prevImage.get())); + ASSERT(isVkImageContentDefined()); + } + + prevImage->releaseImage(renderer); + prevImage.release(); + + // Notify RenderBufferVk/SurfaceVk so that they can free all cached objects like ImageViews and + // VkFramebuffers. + onStateChange(angle::SubjectMessage::VkImageChanged); + + return angle::Result::Continue; +} + +angle::Result ImageHelper::initLayerImageView(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -7169,13 +6494,14 @@ angle::Result ImageHelper::initLayerImageView(ErrorContext *context, uint32_t baseArrayLayer, uint32_t layerCount) const { - return initLayerImageViewImpl(context, textureType, aspectMask, swizzleMap, imageViewOut, - baseMipLevelVk, levelCount, baseArrayLayer, layerCount, - GetVkFormatFromFormatID(context->getRenderer(), mActualFormatID), - kDefaultImageViewUsageFlags, gl::YuvSamplingMode::Default); + return initLayerImageViewImpl( + contextVk, textureType, aspectMask, swizzleMap, imageViewOut, baseMipLevelVk, levelCount, + baseArrayLayer, layerCount, + GetVkFormatFromFormatID(contextVk->getRenderer(), mActualFormatID), + kDefaultImageViewUsageFlags, gl::YuvSamplingMode::Default, GL_NONE); } -angle::Result ImageHelper::initLayerImageViewWithUsage(ErrorContext *context, +angle::Result ImageHelper::initLayerImageViewWithUsage(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -7184,16 +6510,18 @@ angle::Result ImageHelper::initLayerImageViewWithUsage(ErrorContext *context, uint32_t levelCount, uint32_t baseArrayLayer, uint32_t layerCount, - VkImageUsageFlags imageUsageFlags) const + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) const { - return initLayerImageViewImpl(context, textureType, aspectMask, swizzleMap, imageViewOut, - baseMipLevelVk, levelCount, baseArrayLayer, layerCount, - GetVkFormatFromFormatID(context->getRenderer(), mActualFormatID), - imageUsageFlags, gl::YuvSamplingMode::Default); + return initLayerImageViewImpl( + contextVk, textureType, aspectMask, swizzleMap, imageViewOut, baseMipLevelVk, levelCount, + baseArrayLayer, layerCount, + GetVkFormatFromFormatID(contextVk->getRenderer(), mActualFormatID), imageUsageFlags, + gl::YuvSamplingMode::Default, astcDecodePrecision); } angle::Result ImageHelper::initLayerImageViewWithYuvModeOverride( - ErrorContext *context, + ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -7203,15 +6531,17 @@ angle::Result ImageHelper::initLayerImageViewWithYuvModeOverride( uint32_t baseArrayLayer, uint32_t layerCount, gl::YuvSamplingMode yuvSamplingMode, - VkImageUsageFlags imageUsageFlags) const + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) const { - return initLayerImageViewImpl(context, textureType, aspectMask, swizzleMap, imageViewOut, - baseMipLevelVk, levelCount, baseArrayLayer, layerCount, - GetVkFormatFromFormatID(context->getRenderer(), mActualFormatID), - imageUsageFlags, yuvSamplingMode); + return initLayerImageViewImpl( + contextVk, textureType, aspectMask, swizzleMap, imageViewOut, baseMipLevelVk, levelCount, + baseArrayLayer, layerCount, + GetVkFormatFromFormatID(contextVk->getRenderer(), mActualFormatID), imageUsageFlags, + yuvSamplingMode, astcDecodePrecision); } -angle::Result ImageHelper::initLayerImageViewImpl(ErrorContext *context, +angle::Result ImageHelper::initLayerImageViewImpl(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -7222,7 +6552,8 @@ angle::Result ImageHelper::initLayerImageViewImpl(ErrorContext *context, uint32_t layerCount, VkFormat imageFormat, VkImageUsageFlags usageFlags, - gl::YuvSamplingMode yuvSamplingMode) const + gl::YuvSamplingMode yuvSamplingMode, + GLenum astcDecodePrecision) const { VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -7260,6 +6591,18 @@ angle::Result ImageHelper::initLayerImageViewImpl(ErrorContext *context, viewInfo.pNext = &imageViewUsageCreateInfo; } + const angle::Format &angleFormat = getActualFormat(); + GLenum glFormat = angleFormat.glInternalFormat; + VkImageViewASTCDecodeModeEXT astcDecodeModeEXT = {}; + if (astcDecodePrecision != GL_NONE && gl::IsASTC2DFormat(glFormat)) + { + astcDecodeModeEXT.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT; + astcDecodeModeEXT.pNext = nullptr; + astcDecodeModeEXT.decodeMode = gl_vk::GetAstcDecodeMode(astcDecodePrecision); + + AddToPNextChain(&viewInfo, &astcDecodeModeEXT); + } + VkSamplerYcbcrConversionInfo yuvConversionInfo = {}; auto conversionDesc = @@ -7267,11 +6610,11 @@ angle::Result ImageHelper::initLayerImageViewImpl(ErrorContext *context, if (conversionDesc.valid()) { - ASSERT((context->getFeatures().supportsYUVSamplerConversion.enabled)); + ASSERT((contextVk->getFeatures().supportsYUVSamplerConversion.enabled)); yuvConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO; yuvConversionInfo.pNext = nullptr; - ANGLE_TRY(context->getRenderer()->getYuvConversionCache().getSamplerYcbcrConversion( - context, conversionDesc, &yuvConversionInfo.conversion)); + ANGLE_TRY(contextVk->getShareGroup()->getYuvConversionCache().getSamplerYcbcrConversion( + contextVk, conversionDesc, &yuvConversionInfo.conversion)); AddToPNextChain(&viewInfo, &yuvConversionInfo); // VUID-VkImageViewCreateInfo-image-02399 @@ -7281,11 +6624,11 @@ angle::Result ImageHelper::initLayerImageViewImpl(ErrorContext *context, viewInfo.format = VK_FORMAT_UNDEFINED; } } - ANGLE_VK_TRY(context, imageViewOut->init(context->getDevice(), viewInfo)); + ANGLE_VK_TRY(contextVk, imageViewOut->init(contextVk->getDevice(), viewInfo)); return angle::Result::Continue; } -angle::Result ImageHelper::initReinterpretedLayerImageView(ErrorContext *context, +angle::Result ImageHelper::initReinterpretedLayerImageView(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -7295,16 +6638,17 @@ angle::Result ImageHelper::initReinterpretedLayerImageView(ErrorContext *context uint32_t baseArrayLayer, uint32_t layerCount, VkImageUsageFlags imageUsageFlags, - angle::FormatID imageViewFormat) const + angle::FormatID imageViewFormat, + GLenum astcDecodePrecision) const { VkImageUsageFlags usageFlags = - imageUsageFlags & GetMaximalImageUsageFlags(context->getRenderer(), imageViewFormat); + imageUsageFlags & GetMaximalImageUsageFlags(contextVk->getRenderer(), imageViewFormat); return initLayerImageViewImpl( - context, textureType, aspectMask, swizzleMap, imageViewOut, baseMipLevelVk, levelCount, + contextVk, textureType, aspectMask, swizzleMap, imageViewOut, baseMipLevelVk, levelCount, baseArrayLayer, layerCount, - vk::GetVkFormatFromFormatID(context->getRenderer(), imageViewFormat), usageFlags, - gl::YuvSamplingMode::Default); + vk::GetVkFormatFromFormatID(contextVk->getRenderer(), imageViewFormat), usageFlags, + gl::YuvSamplingMode::Default, astcDecodePrecision); } void ImageHelper::destroy(Renderer *renderer) @@ -7329,7 +6673,7 @@ void ImageHelper::destroy(Renderer *renderer) mImage.destroy(device); mDeviceMemory.destroy(device); mVmaAllocation.destroy(renderer->getAllocator()); - mCurrentLayout = ImageLayout::Undefined; + mCurrentAccess = ImageAccess::Undefined; mImageType = VK_IMAGE_TYPE_2D; mLayerCount = 0; mLevelCount = 0; @@ -7350,8 +6694,8 @@ void ImageHelper::init2DWeakReference(ErrorContext *context, bool isRobustResourceInitEnabled) { ASSERT(!valid()); - ASSERT(!IsAnySubresourceContentDefined(mContentDefined)); - ASSERT(!IsAnySubresourceContentDefined(mStencilContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageStencilContentDefined)); vk::Renderer *renderer = context->getRenderer(); gl_vk::GetExtent(glExtents, &mExtents); @@ -7359,13 +6703,13 @@ void ImageHelper::init2DWeakReference(ErrorContext *context, mIntendedFormatID = intendedFormatID; mActualFormatID = actualFormatID; mCreateFlags = createFlags; - mUsage = usage; + mRequestedUsage = usage; mSamples = std::max(samples, 1); mImageSerial = renderer->getResourceSerialFactory().generateImageSerial(); mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); mIsReleasedToExternal = false; mIsForeignImage = false; - mCurrentLayout = ImageLayout::Undefined; + mCurrentAccess = ImageAccess::Undefined; mLayerCount = 1; mLevelCount = 1; @@ -7376,13 +6720,15 @@ void ImageHelper::init2DWeakReference(ErrorContext *context, mViewFormats); mImage.setHandle(handle); + // Even though we did not use mVkImageCreateInfo to create mImage, mVkImageCreateInfo.usage is + // being used for actual usage of mImage, so we always keep it updated. + mVkImageCreateInfo.usage = mRequestedUsage; stageClearIfEmulatedFormat(isRobustResourceInitEnabled, false); } angle::Result ImageHelper::init2DStaging(ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, const gl::Extents &glExtents, angle::FormatID intendedFormatID, angle::FormatID actualFormatID, @@ -7391,13 +6737,12 @@ angle::Result ImageHelper::init2DStaging(ErrorContext *context, { gl_vk::GetExtent(glExtents, &mExtents); - return initStaging(context, hasProtectedContent, memoryProperties, VK_IMAGE_TYPE_2D, mExtents, - intendedFormatID, actualFormatID, 1, usage, 1, layerCount); + return initStaging(context, hasProtectedContent, VK_IMAGE_TYPE_2D, mExtents, intendedFormatID, + actualFormatID, 1, usage, 1, layerCount); } angle::Result ImageHelper::initStaging(ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, VkImageType imageType, const VkExtent3D &extents, angle::FormatID intendedFormatID, @@ -7408,8 +6753,8 @@ angle::Result ImageHelper::initStaging(ErrorContext *context, uint32_t layerCount) { ASSERT(!valid()); - ASSERT(!IsAnySubresourceContentDefined(mContentDefined)); - ASSERT(!IsAnySubresourceContentDefined(mStencilContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageStencilContentDefined)); vk::Renderer *renderer = context->getRenderer(); mImageType = imageType; @@ -7421,13 +6766,13 @@ angle::Result ImageHelper::initStaging(ErrorContext *context, mImageSerial = renderer->getResourceSerialFactory().generateImageSerial(); mLayerCount = layerCount; mLevelCount = mipLevels; - mUsage = usage; + mRequestedUsage = usage; // Validate that mLayerCount is compatible with the image type ASSERT(imageType != VK_IMAGE_TYPE_3D || mLayerCount == 1); ASSERT(imageType != VK_IMAGE_TYPE_2D || mExtents.depth == 1); - mCurrentLayout = ImageLayout::Undefined; + mCurrentAccess = ImageAccess::Undefined; VkImageCreateInfo imageInfo = {}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -7444,7 +6789,7 @@ angle::Result ImageHelper::initStaging(ErrorContext *context, imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.queueFamilyIndexCount = 0; imageInfo.pQueueFamilyIndices = nullptr; - imageInfo.initialLayout = getCurrentLayout(context->getRenderer()); + imageInfo.initialLayout = getCurrentLayout(renderer); ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo)); @@ -7459,8 +6804,7 @@ angle::Result ImageHelper::initStaging(ErrorContext *context, memoryPropertyFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT; } - ANGLE_TRY(initMemoryAndNonZeroFillIfNeeded(context, hasProtectedContent, memoryProperties, - memoryPropertyFlags, + ANGLE_TRY(initMemoryAndNonZeroFillIfNeeded(context, hasProtectedContent, memoryPropertyFlags, vk::MemoryAllocationType::StagingImage)); return angle::Result::Continue; } @@ -7468,7 +6812,6 @@ angle::Result ImageHelper::initStaging(ErrorContext *context, angle::Result ImageHelper::initImplicitMultisampledRenderToTexture( ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, gl::TextureType textureType, GLint samples, const ImageHelper &resolveImage, @@ -7477,8 +6820,8 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture( { ASSERT(!valid()); ASSERT(samples > 1); - ASSERT(!IsAnySubresourceContentDefined(mContentDefined)); - ASSERT(!IsAnySubresourceContentDefined(mStencilContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageContentDefined)); + ASSERT(!IsAnySubresourceContentDefined(mVkImageStencilContentDefined)); // The image is used as either color or depth/stencil attachment. Additionally, its memory is // lazily allocated as the contents are discarded at the end of the renderpass and with tiling @@ -7490,7 +6833,8 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture( // supports LAZILY_ALLOCATED. However, based on actual image requirements, such a memory may // not be suitable for the image. We don't support such a case, which will result in the // |initMemory| call below failing. - const bool hasLazilyAllocatedMemory = memoryProperties.hasLazilyAllocatedMemory(); + const bool hasLazilyAllocatedMemory = + context->getRenderer()->getMemoryProperties().hasLazilyAllocatedMemory(); const VkImageUsageFlags kLazyFlags = hasLazilyAllocatedMemory ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : 0; @@ -7517,9 +6861,10 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture( ANGLE_TRY(initExternal(context, textureType, multisampleImageExtents, resolveImage.getIntendedFormatID(), resolveImage.getActualFormatID(), samples, kMultisampledUsageFlags, kMultisampledCreateFlags, - ImageLayout::Undefined, nullptr, resolveImage.getFirstAllocatedLevel(), + ImageAccess::Undefined, nullptr, resolveImage.getFirstAllocatedLevel(), kLevelCount, resolveImage.getLayerCount(), isRobustResourceInitEnabled, - hasProtectedContent, YcbcrConversionDesc{}, nullptr)); + hasProtectedContent, TileMemory::Prohibited, YcbcrConversionDesc{}, + nullptr)); // Remove the emulated format clear from the multisampled image if any. There is one already // staged on the resolve image if needed. @@ -7534,11 +6879,53 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture( // still fail), but ideally that means GL_EXT_multisampled_render_to_texture should not be // advertised on this platform in the first place. ANGLE_TRY(initMemoryAndNonZeroFillIfNeeded( - context, hasProtectedContent, memoryProperties, kMultisampledMemoryFlags, + context, hasProtectedContent, kMultisampledMemoryFlags, vk::MemoryAllocationType::ImplicitMultisampledRenderToTextureImage)); return angle::Result::Continue; } +angle::Result ImageHelper::initRgbDrawImageForYuvResolve(ErrorContext *context, + const ImageHelper &resolveImage, + bool isRobustResourceInitEnabled) +{ + // Find the RGB format corresponding to the YUV format + const vk::ExternalYuvFormatInfo &externalFormatInfo = + context->getRenderer()->getExternalFormatTable()->getExternalFormatInfo( + resolveImage.getActualFormatID()); + const angle::FormatID formatID = + vk::GetFormatIDFromVkFormat(externalFormatInfo.colorAttachmentFormat); + + // Create RGB draw image + const VkImageUsageFlags usageFlags = + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + + const bool hasProtectedContent = + (resolveImage.getCreateFlags() & VK_IMAGE_CREATE_PROTECTED_BIT) != 0; + const VkImageCreateFlags createFlags = hasProtectedContent ? VK_IMAGE_CREATE_PROTECTED_BIT : 0; + + ANGLE_TRY(initExternal( + context, gl::TextureType::_2D, resolveImage.getExtents(), formatID, formatID, 1, usageFlags, + createFlags, ImageAccess::Undefined, nullptr, resolveImage.getFirstAllocatedLevel(), + resolveImage.getLevelCount(), resolveImage.getLayerCount(), isRobustResourceInitEnabled, + hasProtectedContent, TileMemory::Prohibited, YcbcrConversionDesc{}, nullptr)); + + ASSERT(!hasEmulatedImageChannels()); + + const VkMemoryPropertyFlags yuvMemoryFlags = + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + (hasProtectedContent ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0); + + ANGLE_TRY(initMemoryAndNonZeroFillIfNeeded(context, hasProtectedContent, yuvMemoryFlags, + vk::MemoryAllocationType::ImplicitYuvTargetImage)); + + return angle::Result::Continue; +} + +VkImageAspectFlags ImageHelper::getIntendedAspectFlags() const +{ + return GetFormatAspectFlags(angle::Format::Get(mIntendedFormatID)); +} + VkImageAspectFlags ImageHelper::getAspectFlags() const { return GetFormatAspectFlags(angle::Format::Get(mActualFormatID)); @@ -7549,29 +6936,27 @@ bool ImageHelper::isCombinedDepthStencilFormat() const return (getAspectFlags() & kDepthStencilAspects) == kDepthStencilAspects; } -void ImageHelper::setCurrentImageLayout(Renderer *renderer, ImageLayout newLayout) +void ImageHelper::setCurrentImageAccess(Renderer *renderer, ImageAccess newAccess) { - // Once you transition to ImageLayout::SharedPresent, you never transition out of it. - if (mCurrentLayout == ImageLayout::SharedPresent) + // Once you transition to ImageAccess::SharedPresent, you never transition out of it. + if (mCurrentAccess == ImageAccess::SharedPresent) { return; } - const ImageMemoryBarrierData &transitionFrom = - renderer->getImageMemoryBarrierData(mCurrentLayout); - const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newLayout); - mLastNonShaderReadOnlyLayout = - !IsShaderReadOnlyLayout(transitionFrom) ? mCurrentLayout : mLastNonShaderReadOnlyLayout; + mLastNonShaderReadOnlyAccess = + !IsShaderReadOnlyAccess(mCurrentAccess) ? mCurrentAccess : mLastNonShaderReadOnlyAccess; // Force the use of BarrierType::Pipeline in the next barrierImpl call mLastNonShaderReadOnlyEvent.release(renderer); - mCurrentShaderReadStageMask = - IsShaderReadOnlyLayout(transitionTo) ? transitionTo.dstStageMask : 0; - mCurrentLayout = newLayout; + mCurrentShaderReadStageMask = IsShaderReadOnlyAccess(newAccess) + ? renderer->getImageMemoryBarrierData(newAccess).dstStageMask + : 0; + mCurrentAccess = newAccess; } VkImageLayout ImageHelper::getCurrentLayout(Renderer *renderer) const { - return ConvertImageLayoutToVkImageLayout(renderer, mCurrentLayout); + return renderer->getVkImageLayout(mCurrentAccess); } gl::Extents ImageHelper::getLevelExtents(LevelIndex levelVk) const @@ -7637,6 +7022,11 @@ bool ImageHelper::hasRenderPassUsageFlag(RenderPassUsage flag) const return mRenderPassUsageFlags.test(flag); } +bool ImageHelper::hasAnyRenderPassUsageFlags() const +{ + return mRenderPassUsageFlags.any(); +} + bool ImageHelper::usedByCurrentRenderPassAsAttachmentAndSampler( RenderPassUsage textureSamplerUsage) const { @@ -7644,10 +7034,10 @@ bool ImageHelper::usedByCurrentRenderPassAsAttachmentAndSampler( mRenderPassUsageFlags[textureSamplerUsage]; } -bool ImageHelper::isReadBarrierNecessary(Renderer *renderer, ImageLayout newLayout) const +bool ImageHelper::isReadBarrierNecessary(Renderer *renderer, ImageAccess newAccess) const { // If transitioning to a different layout, we need always need a barrier. - if (mCurrentLayout != newLayout) + if (mCurrentAccess != newAccess) { return true; } @@ -7657,11 +7047,11 @@ bool ImageHelper::isReadBarrierNecessary(Renderer *renderer, ImageLayout newLayo // RAW (read-after-write) hazards always require a memory barrier. This can only happen if the // layout (same as new layout) is writable which in turn is only possible if the image is // simultaneously bound for shader write (i.e. the layout is GENERAL or SHARED_PRESENT). - const ImageMemoryBarrierData &layoutData = renderer->getImageMemoryBarrierData(mCurrentLayout); + const ImageMemoryBarrierData &layoutData = renderer->getImageMemoryBarrierData(mCurrentAccess); return HasResourceWriteAccess(layoutData.type); } -bool ImageHelper::isReadSubresourceBarrierNecessary(ImageLayout newLayout, +bool ImageHelper::isReadSubresourceBarrierNecessary(ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, @@ -7670,7 +7060,7 @@ bool ImageHelper::isReadSubresourceBarrierNecessary(ImageLayout newLayout, // In case an image has both read and write permissions, the written subresources since the last // barrier should be checked to avoid RAW and WAR hazards. However, if a layout change is // necessary regardless, there is no need to check the written subresources. - if (mCurrentLayout != newLayout) + if (mCurrentAccess != newAccess) { return true; } @@ -7688,14 +7078,14 @@ bool ImageHelper::isReadSubresourceBarrierNecessary(ImageLayout newLayout, return false; } -bool ImageHelper::isWriteBarrierNecessary(ImageLayout newLayout, +bool ImageHelper::isWriteBarrierNecessary(ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, uint32_t layerCount) const { // If transitioning to a different layout, we need always need a barrier. - if (mCurrentLayout != newLayout) + if (mCurrentAccess != newAccess) { return true; } @@ -7722,7 +7112,7 @@ bool ImageHelper::isWriteBarrierNecessary(ImageLayout newLayout, void ImageHelper::changeLayoutAndQueue(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer) { @@ -7732,7 +7122,7 @@ void ImageHelper::changeLayoutAndQueue(Context *context, VkSemaphore acquireNextImageSemaphore; // recordBarrierImpl should detect there is queue switch and fall back to pipelineBarrier // properly. - recordBarrierImpl(context, aspectMask, newLayout, newDeviceQueueIndex, nullptr, commandBuffer, + recordBarrierImpl(context, aspectMask, newAccess, newDeviceQueueIndex, nullptr, commandBuffer, &acquireNextImageSemaphore); // SwapChain image should not get here. ASSERT(acquireNextImageSemaphore == VK_NULL_HANDLE); @@ -7741,30 +7131,30 @@ void ImageHelper::changeLayoutAndQueue(Context *context, void ImageHelper::acquireFromExternal(Context *context, DeviceQueueIndex externalQueueIndex, DeviceQueueIndex newDeviceQueueIndex, - ImageLayout currentLayout, + ImageAccess currentAccess, OutsideRenderPassCommandBuffer *commandBuffer) { // The image must be newly allocated or have been released to the external // 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 || + ASSERT(mCurrentAccess == ImageAccess::ExternalPreInitialized || mCurrentDeviceQueueIndex.familyIndex() == externalQueueIndex.familyIndex()); - mCurrentLayout = currentLayout; + mCurrentAccess = currentAccess; 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) + if (currentAccess != ImageAccess::Undefined) { - changeLayoutAndQueue(context, getAspectFlags(), mCurrentLayout, newDeviceQueueIndex, + changeLayoutAndQueue(context, getAspectFlags(), mCurrentAccess, newDeviceQueueIndex, commandBuffer); } // It is unknown how the external has modified the image, so assume every subresource has // defined content. That is unless the layout is Undefined. - if (currentLayout == ImageLayout::Undefined) + if (currentAccess == ImageAccess::Undefined) { setEntireContentUndefined(); } @@ -7776,7 +7166,7 @@ void ImageHelper::acquireFromExternal(Context *context, void ImageHelper::releaseToExternal(Context *context, DeviceQueueIndex externalQueueIndex, - ImageLayout desiredLayout, + ImageAccess expectedAccess, OutsideRenderPassCommandBuffer *commandBuffer) { ASSERT(!mIsReleasedToExternal); @@ -7784,9 +7174,9 @@ void ImageHelper::releaseToExternal(Context *context, // A layout change is unnecessary if the image that was previously acquired was never used by // GL! if (mCurrentDeviceQueueIndex.familyIndex() != externalQueueIndex.familyIndex() || - mCurrentLayout != desiredLayout) + mCurrentAccess != expectedAccess) { - changeLayoutAndQueue(context, getAspectFlags(), desiredLayout, externalQueueIndex, + changeLayoutAndQueue(context, getAspectFlags(), expectedAccess, externalQueueIndex, commandBuffer); } @@ -7797,7 +7187,7 @@ VkImageMemoryBarrier ImageHelper::releaseToForeign(Renderer *renderer) { ASSERT(mIsForeignImage); - const ImageMemoryBarrierData barrierData = renderer->getImageMemoryBarrierData(mCurrentLayout); + const ImageMemoryBarrierData barrierData = renderer->getImageMemoryBarrierData(mCurrentAccess); VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -7812,9 +7202,9 @@ VkImageMemoryBarrier ImageHelper::releaseToForeign(Renderer *renderer) barrier.subresourceRange.levelCount = mLevelCount; barrier.subresourceRange.layerCount = mLayerCount; - mCurrentLayout = ImageLayout::ForeignAccess; + mCurrentAccess = ImageAccess::ForeignAccess; mCurrentDeviceQueueIndex = kForeignDeviceQueueIndex; - mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; + mLastNonShaderReadOnlyAccess = ImageAccess::Undefined; mCurrentShaderReadStageMask = 0; return barrier; @@ -7833,7 +7223,7 @@ gl::LevelIndex ImageHelper::toGLLevel(LevelIndex levelIndexVk) const ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct( Renderer *renderer, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, uint32_t newQueueFamilyIndex, VkImageMemoryBarrier *imageMemoryBarrier) const { @@ -7841,14 +7231,14 @@ ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct( ASSERT(newQueueFamilyIndex != QueueFamily::kInvalidIndex); const ImageMemoryBarrierData &transitionFrom = - renderer->getImageMemoryBarrierData(mCurrentLayout); - const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newLayout); + renderer->getImageMemoryBarrierData(mCurrentAccess); + const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newAccess); imageMemoryBarrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier->srcAccessMask = transitionFrom.srcAccessMask; imageMemoryBarrier->dstAccessMask = transitionTo.dstAccessMask; - imageMemoryBarrier->oldLayout = ConvertImageLayoutToVkImageLayout(renderer, mCurrentLayout); - imageMemoryBarrier->newLayout = ConvertImageLayoutToVkImageLayout(renderer, newLayout); + imageMemoryBarrier->oldLayout = renderer->getVkImageLayout(mCurrentAccess); + imageMemoryBarrier->newLayout = renderer->getVkImageLayout(newAccess); imageMemoryBarrier->srcQueueFamilyIndex = mCurrentDeviceQueueIndex.familyIndex(); imageMemoryBarrier->dstQueueFamilyIndex = newQueueFamilyIndex; imageMemoryBarrier->image = mImage.getHandle(); @@ -7865,7 +7255,7 @@ ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct( template void ImageHelper::barrierImpl(Renderer *renderer, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, CommandBufferT *commandBuffer, @@ -7878,10 +7268,10 @@ void ImageHelper::barrierImpl(Renderer *renderer, *acquireNextImageSemaphoreOut = mAcquireNextImageSemaphore.release(); } - if (mCurrentLayout == ImageLayout::SharedPresent) + if (mCurrentAccess == ImageAccess::SharedPresent) { const ImageMemoryBarrierData &transition = - renderer->getImageMemoryBarrierData(mCurrentLayout); + renderer->getImageMemoryBarrierData(mCurrentAccess); VkMemoryBarrier memoryBarrier = {}; memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; memoryBarrier.srcAccessMask = transition.srcAccessMask; @@ -7893,14 +7283,14 @@ void ImageHelper::barrierImpl(Renderer *renderer, } // Make sure we never transition out of SharedPresent - ASSERT(mCurrentLayout != ImageLayout::SharedPresent || newLayout == ImageLayout::SharedPresent); + ASSERT(mCurrentAccess != ImageAccess::SharedPresent || newAccess == ImageAccess::SharedPresent); const ImageMemoryBarrierData &transitionFrom = - renderer->getImageMemoryBarrierData(mCurrentLayout); - const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newLayout); + renderer->getImageMemoryBarrierData(mCurrentAccess); + const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newAccess); VkImageMemoryBarrier imageMemoryBarrier = {}; - initImageMemoryBarrierStruct(renderer, aspectMask, newLayout, newDeviceQueueIndex.familyIndex(), + initImageMemoryBarrierStruct(renderer, aspectMask, newAccess, newDeviceQueueIndex.familyIndex(), &imageMemoryBarrier); VkPipelineStageFlags dstStageMask = transitionTo.dstStageMask; @@ -7934,12 +7324,12 @@ void ImageHelper::barrierImpl(Renderer *renderer, { srcStageMask |= mCurrentShaderReadStageMask; mCurrentShaderReadStageMask = 0; - mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; + mLastNonShaderReadOnlyAccess = ImageAccess::Undefined; } commandBuffer->imageBarrier(srcStageMask, dstStageMask, imageMemoryBarrier); } - mCurrentLayout = newLayout; + mCurrentAccess = newAccess; mCurrentDeviceQueueIndex = newDeviceQueueIndex; resetSubresourcesWrittenSinceBarrier(); } @@ -7947,7 +7337,7 @@ void ImageHelper::barrierImpl(Renderer *renderer, template void ImageHelper::recordBarrierImpl(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, CommandBufferT *commandBuffer, @@ -7957,7 +7347,7 @@ void ImageHelper::recordBarrierImpl(Context *context, // mCurrentEvent must be invalid if useVkEventForImageBarrieris disabled. ASSERT(renderer->getFeatures().useVkEventForImageBarrier.enabled || !mCurrentEvent.valid()); - if (mCurrentLayout == ImageLayout::SharedPresent) + if (mCurrentAccess == ImageAccess::SharedPresent) { // For now we always use pipelineBarrier for singlebuffer mode. We could use event here in // future. @@ -7971,7 +7361,7 @@ void ImageHelper::recordBarrierImpl(Context *context, context->onForeignImageUse(this); } - barrierImpl(renderer, aspectMask, newLayout, newDeviceQueueIndex, eventCollector, commandBuffer, + barrierImpl(renderer, aspectMask, newAccess, newDeviceQueueIndex, eventCollector, commandBuffer, acquireNextImageSemaphoreOut); // We must release the event so that new event will be created and added. If we did not add new @@ -7983,7 +7373,7 @@ void ImageHelper::recordBarrierImpl(Context *context, void ImageHelper::recordBarrierOneOffImpl(Renderer *renderer, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, PrimaryCommandBuffer *commandBuffer, VkSemaphore *acquireNextImageSemaphoreOut) @@ -7992,7 +7382,7 @@ void ImageHelper::recordBarrierOneOffImpl(Renderer *renderer, mCurrentEvent.release(renderer); ASSERT(mCurrentDeviceQueueIndex != kForeignDeviceQueueIndex); - barrierImpl(renderer, aspectMask, newLayout, newDeviceQueueIndex, nullptr, commandBuffer, + barrierImpl(renderer, aspectMask, newAccess, newDeviceQueueIndex, nullptr, commandBuffer, acquireNextImageSemaphoreOut); } @@ -8026,18 +7416,18 @@ void ImageHelper::resetSubresourcesWrittenSinceBarrier() void ImageHelper::recordWriteBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, uint32_t layerCount, OutsideRenderPassCommandBufferHelper *commands) { - if (isWriteBarrierNecessary(newLayout, levelStart, levelCount, layerStart, layerCount)) + if (isWriteBarrierNecessary(newAccess, levelStart, levelCount, layerStart, layerCount)) { ASSERT(!mCurrentEvent.valid() || !commands->hasSetEventPendingFlush(mCurrentEvent)); VkSemaphore acquireNextImageSemaphore; - recordBarrierImpl(context, aspectMask, newLayout, context->getDeviceQueueIndex(), + recordBarrierImpl(context, aspectMask, newAccess, context->getDeviceQueueIndex(), commands->getRefCountedEventCollector(), &commands->getCommandBuffer(), &acquireNextImageSemaphore); @@ -8052,7 +7442,7 @@ void ImageHelper::recordWriteBarrier(Context *context, void ImageHelper::recordReadSubresourceBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, @@ -8061,12 +7451,12 @@ void ImageHelper::recordReadSubresourceBarrier(Context *context, { // This barrier is used for an image with both read/write permissions, including during mipmap // generation and self-copy. - if (isReadSubresourceBarrierNecessary(newLayout, levelStart, levelCount, layerStart, + if (isReadSubresourceBarrierNecessary(newAccess, levelStart, levelCount, layerStart, layerCount)) { ASSERT(!mCurrentEvent.valid() || !commands->hasSetEventPendingFlush(mCurrentEvent)); VkSemaphore acquireNextImageSemaphore; - recordBarrierImpl(context, aspectMask, newLayout, context->getDeviceQueueIndex(), + recordBarrierImpl(context, aspectMask, newAccess, context->getDeviceQueueIndex(), commands->getRefCountedEventCollector(), &commands->getCommandBuffer(), &acquireNextImageSemaphore); @@ -8082,17 +7472,17 @@ void ImageHelper::recordReadSubresourceBarrier(Context *context, void ImageHelper::recordReadBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, OutsideRenderPassCommandBufferHelper *commands) { - if (!isReadBarrierNecessary(context->getRenderer(), newLayout)) + if (!isReadBarrierNecessary(context->getRenderer(), newAccess)) { return; } ASSERT(!mCurrentEvent.valid() || !commands->hasSetEventPendingFlush(mCurrentEvent)); VkSemaphore acquireNextImageSemaphore; - recordBarrierImpl(context, aspectMask, newLayout, context->getDeviceQueueIndex(), + recordBarrierImpl(context, aspectMask, newAccess, context->getDeviceQueueIndex(), commands->getRefCountedEventCollector(), &commands->getCommandBuffer(), &acquireNextImageSemaphore); @@ -8104,7 +7494,7 @@ void ImageHelper::recordReadBarrier(Context *context, void ImageHelper::updateLayoutAndBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, BarrierType barrierType, const QueueSerial &queueSerial, PipelineBarrierArray *pipelineBarriers, @@ -8117,7 +7507,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, ASSERT(!mBarrierQueueSerial.valid() || mBarrierQueueSerial.getIndex() != queueSerial.getIndex() || mBarrierQueueSerial.getSerial() <= queueSerial.getSerial()); - ASSERT(renderer->getImageMemoryBarrierData(newLayout).barrierIndex != + ASSERT(renderer->getImageMemoryBarrierData(newAccess).barrierIndex != PipelineStage::InvalidEnum); // mCurrentEvent must be invalid if useVkEventForImageBarrieris disabled. ASSERT(renderer->getFeatures().useVkEventForImageBarrier.enabled || !mCurrentEvent.valid()); @@ -8138,13 +7528,13 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, barrierType = BarrierType::Pipeline; } - // Once you transition to ImageLayout::SharedPresent, you never transition out of it. - if (mCurrentLayout == ImageLayout::SharedPresent) + // Once you transition to ImageAccess::SharedPresent, you never transition out of it. + if (mCurrentAccess == ImageAccess::SharedPresent) { - newLayout = ImageLayout::SharedPresent; + newAccess = ImageAccess::SharedPresent; } - if (newLayout == mCurrentLayout && !hasQueueChange) + if (newAccess == mCurrentAccess && !hasQueueChange) { if (mBarrierQueueSerial == queueSerial) { @@ -8156,7 +7546,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, } const ImageMemoryBarrierData &layoutData = - renderer->getImageMemoryBarrierData(mCurrentLayout); + renderer->getImageMemoryBarrierData(mCurrentAccess); // RAR is not a hazard and doesn't require a barrier, especially as the image layout hasn't // changed. The following asserts that such a barrier is not attempted. ASSERT(HasResourceWriteAccess(layoutData.type)); @@ -8184,12 +7574,13 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, else { const ImageMemoryBarrierData &transitionFrom = - renderer->getImageMemoryBarrierData(mCurrentLayout); - const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newLayout); + renderer->getImageMemoryBarrierData(mCurrentAccess); + const ImageMemoryBarrierData &transitionTo = renderer->getImageMemoryBarrierData(newAccess); VkPipelineStageFlags srcStageMask = transitionFrom.srcStageMask; VkPipelineStageFlags dstStageMask = transitionTo.dstStageMask; + const bool isNewAccessShaderReadOnly = IsShaderReadOnlyAccess(newAccess); - if (transitionFrom.layout == transitionTo.layout && IsShaderReadOnlyLayout(transitionTo) && + if (transitionFrom.layout == transitionTo.layout && isNewAccessShaderReadOnly && mBarrierQueueSerial == queueSerial && !hasQueueChange) { // If we are switching between different shader stage reads of the same render pass, @@ -8206,7 +7597,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, ASSERT(!mLastNonShaderReadOnlyEvent.valid() || mLastNonShaderReadOnlyEvent.getEventStage() == - GetImageLayoutEventStage(mLastNonShaderReadOnlyLayout)); + GetImageAccessEventStage(renderer, mLastNonShaderReadOnlyAccess)); if (!mLastNonShaderReadOnlyEvent.valid()) { barrierType = BarrierType::Pipeline; @@ -8214,7 +7605,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, if (barrierType == BarrierType::Event) { - // If we already inserted a barrier in the same renderPass, we has to add + // If we already inserted a barrier in the same renderPass, we have to add // the new stage mask to the existing VkCmdWaitEvent call, otherwise VVL will // complain. eventBarriers->addAdditionalStageAccess(mLastNonShaderReadOnlyEvent, dstStageMask, @@ -8224,7 +7615,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, else { const ImageMemoryBarrierData &layoutData = - renderer->getImageMemoryBarrierData(mLastNonShaderReadOnlyLayout); + renderer->getImageMemoryBarrierData(mLastNonShaderReadOnlyAccess); pipelineBarriers->mergeMemoryBarrier( transitionTo.barrierIndex, layoutData.srcStageMask, dstStageMask, layoutData.srcAccessMask, transitionTo.dstAccessMask); @@ -8244,12 +7635,11 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, else { VkImageMemoryBarrier imageMemoryBarrier = {}; - initImageMemoryBarrierStruct(renderer, aspectMask, newLayout, + initImageMemoryBarrierStruct(renderer, aspectMask, newAccess, context->getDeviceQueueIndex().familyIndex(), &imageMemoryBarrier); - if (transitionFrom.layout == transitionTo.layout && - IsShaderReadOnlyLayout(transitionTo)) + if (transitionFrom.layout == transitionTo.layout && isNewAccessShaderReadOnly) { // If we are transiting within shaderReadOnly layout, i.e. reading from different // shader stages, VkEvent can't handle this right now. In order for VkEvent to @@ -8277,9 +7667,9 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, { // mCurrentShaderReadStageMask has more bits than srcStageMask. This means it // has been used by more than one shader stage in the same render pass. These - // two usages are tracked by two different ImageLayout, even though underline + // two usages are tracked by two different ImageAccess, even though underlying // VkImageLayout is the same. This means two different RefCountedEvents since - // each RefCountedEvent is associated with one ImageLayout. When we transit out + // each RefCountedEvent is associated with one ImageAccess. When we transit out // of this layout, we must wait for all reads to finish. But Right now // ImageHelper only keep track of the last read. To workaround this problem we // use pipelineBarrier in this case. @@ -8287,20 +7677,20 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, srcStageMask |= mCurrentShaderReadStageMask; } mCurrentShaderReadStageMask = 0; - mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; + mLastNonShaderReadOnlyAccess = ImageAccess::Undefined; if (mLastNonShaderReadOnlyEvent.valid()) { mLastNonShaderReadOnlyEvent.release(context); } } - // If we are transition into shaderRead layout, remember the last - // non-shaderRead layout here. - const bool isShaderReadOnly = IsShaderReadOnlyLayout(transitionTo); - if (isShaderReadOnly) + // If we are transition into shaderRead layout, remember the last non-shaderRead layout + // here. + const bool isCurrentAccessShaderReadOnly = IsShaderReadOnlyAccess(mCurrentAccess); + if (isNewAccessShaderReadOnly && !isCurrentAccessShaderReadOnly) { mLastNonShaderReadOnlyEvent.release(context); - mLastNonShaderReadOnlyLayout = mCurrentLayout; + mLastNonShaderReadOnlyAccess = mCurrentAccess; mCurrentShaderReadStageMask = dstStageMask; } @@ -8308,7 +7698,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, { eventBarriers->addEventImageBarrier(renderer, mCurrentEvent, dstStageMask, imageMemoryBarrier); - if (isShaderReadOnly) + if (isNewAccessShaderReadOnly && !isCurrentAccessShaderReadOnly) { mLastNonShaderReadOnlyEvent = mCurrentEvent; } @@ -8323,7 +7713,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, mBarrierQueueSerial = queueSerial; } - mCurrentLayout = newLayout; + mCurrentAccess = newAccess; } mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); @@ -8334,6 +7724,8 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, // pipelineBarrier. Otherwise if we keep mCurrentEvent here we may accidentally end up waiting // for an old event which creates sync hazard. ASSERT(!mCurrentEvent.valid()); + + ASSERT(!IsShaderReadOnlyAccess(mLastNonShaderReadOnlyAccess)); } void ImageHelper::setCurrentRefCountedEvent(Context *context, @@ -8360,7 +7752,7 @@ void ImageHelper::setCurrentRefCountedEvent(Context *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. - EventStage eventStage = GetImageLayoutEventStage(mCurrentLayout); + EventStage eventStage = GetImageAccessEventStage(context->getRenderer(), mCurrentAccess); if (!refCountedEventArray->getEvent(eventStage).valid() && !refCountedEventArray->initEventAtStage(context, eventStage)) { @@ -8373,12 +7765,27 @@ void ImageHelper::setCurrentRefCountedEvent(Context *context, mCurrentEvent = refCountedEventArray->getEvent(eventStage); } -void ImageHelper::updatePipelineStageAccessHistory() +void ImageHelper::updatePipelineStageAccessHistory(Renderer *renderer) { - const ImageMemoryBarrierData &barrierData = kImageMemoryBarrierData[mCurrentLayout]; + const ImageMemoryBarrierData &barrierData = renderer->getImageMemoryBarrierData(mCurrentAccess); mPipelineStageAccessHeuristic.onAccess(barrierData.pipelineStageGroup); } +bool ImageHelper::areStagedUpdatesClearOnly() +{ + for (SubresourceUpdates &levelUpdates : mSubresourceUpdates) + { + for (SubresourceUpdate &update : levelUpdates) + { + if (!IsClear(update.updateSource)) + { + return false; + } + } + } + return true; +} + void ImageHelper::clearColor(Renderer *renderer, const VkClearColorValue &color, LevelIndex baseMipLevelVk, @@ -8389,8 +7796,8 @@ void ImageHelper::clearColor(Renderer *renderer, { ASSERT(valid()); - ASSERT(mCurrentLayout == ImageLayout::TransferDst || - mCurrentLayout == ImageLayout::SharedPresent); + ASSERT(mCurrentAccess == ImageAccess::TransferDst || + mCurrentAccess == ImageAccess::SharedPresent); VkImageSubresourceRange range = {}; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -8421,7 +7828,7 @@ void ImageHelper::clearDepthStencil(Renderer *renderer, { ASSERT(valid()); - ASSERT(mCurrentLayout == ImageLayout::TransferDst); + ASSERT(mCurrentAccess == ImageAccess::TransferDst); VkImageSubresourceRange range = {}; range.aspectMask = clearAspectFlags; @@ -8511,8 +7918,8 @@ void ImageHelper::Copy(Renderer *renderer, { ASSERT(commandBuffer->valid() && srcImage->valid() && dstImage->valid()); - ASSERT(srcImage->getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - ASSERT(dstImage->getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + ASSERT(srcImage->getCurrentImageAccess() == ImageAccess::TransferSrc); + ASSERT(dstImage->getCurrentImageAccess() == ImageAccess::TransferDst); VkImageCopy region = {}; region.srcSubresource = srcSubresource; @@ -8584,29 +7991,29 @@ angle::Result ImageHelper::CopyImageSubData(const gl::Context *context, region.extent.height = srcHeight; region.extent.depth = (isSrc3D || isDst3D) ? srcDepth : 1; - CommandBufferAccess access; + CommandResources resources; if (srcImage == dstImage) { - access.onImageSelfCopy(srcLevelGL, 1, region.srcSubresource.baseArrayLayer, - region.srcSubresource.layerCount, dstLevelGL, 1, - region.dstSubresource.baseArrayLayer, - region.dstSubresource.layerCount, aspectFlags, srcImage); + resources.onImageSelfCopy(srcLevelGL, 1, region.srcSubresource.baseArrayLayer, + region.srcSubresource.layerCount, dstLevelGL, 1, + region.dstSubresource.baseArrayLayer, + region.dstSubresource.layerCount, aspectFlags, srcImage); } else { - access.onImageTransferRead(aspectFlags, srcImage); - access.onImageTransferWrite(dstLevelGL, 1, region.dstSubresource.baseArrayLayer, - region.dstSubresource.layerCount, aspectFlags, dstImage); + resources.onImageTransferRead(aspectFlags, srcImage); + resources.onImageTransferWrite(dstLevelGL, 1, region.dstSubresource.baseArrayLayer, + region.dstSubresource.layerCount, aspectFlags, dstImage); } OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); ASSERT(srcImage->valid() && dstImage->valid()); - ASSERT(srcImage->getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL || - srcImage->getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_GENERAL); - ASSERT(dstImage->getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || - dstImage->getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_GENERAL); + ASSERT(srcImage->getCurrentImageAccess() == ImageAccess::TransferSrc || + srcImage->getCurrentImageAccess() == ImageAccess::TransferSrcDst); + ASSERT(dstImage->getCurrentImageAccess() == ImageAccess::TransferDst || + dstImage->getCurrentImageAccess() == ImageAccess::TransferSrcDst); commandBuffer->copyImage(srcImage->getImage(), srcImage->getCurrentLayout(renderer), dstImage->getImage(), dstImage->getCurrentLayout(renderer), 1, @@ -8649,13 +8056,13 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, { Renderer *renderer = contextVk->getRenderer(); - CommandBufferAccess access; + CommandResources resources; gl::LevelIndex baseLevelGL = toGLLevel(baseLevel); - access.onImageTransferWrite(baseLevelGL + 1, maxLevel.get(), 0, mLayerCount, - VK_IMAGE_ASPECT_COLOR_BIT, this); + resources.onImageTransferWrite(baseLevelGL + 1, maxLevel.get(), 0, mLayerCount, + VK_IMAGE_ASPECT_COLOR_BIT, this); OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // We are able to use blitImage since the image format we are using supports it. int32_t mipWidth = mExtents.width; @@ -8667,6 +8074,10 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.image = mImage.getHandle(); + barrier.oldLayout = getCurrentLayout(renderer); + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -8674,6 +8085,17 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, barrier.subresourceRange.layerCount = mLayerCount; barrier.subresourceRange.levelCount = 1; + // The barriers can be simplified if the image layout does not need to change. + const bool isGeneralLayout = getCurrentLayout(renderer) == VK_IMAGE_LAYOUT_GENERAL; + VkMemoryBarrier globalBarrier = {}; + globalBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + globalBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + globalBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + const VkImageLayout blitSrcLayout = + isGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL : barrier.newLayout; + const VkImageLayout blitDstLayout = barrier.oldLayout; + const VkFilter filter = gl_vk::GetFilter(CalculateGenerateMipmapFilter(contextVk, getActualFormatID())); @@ -8685,15 +8107,20 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, if (mipLevel > baseLevel && mipLevel <= maxLevel) { - barrier.subresourceRange.baseMipLevel = mipLevel.get() - 1; - barrier.oldLayout = getCurrentLayout(renderer); - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + if (isGeneralLayout) + { + commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, globalBarrier); + } + else + { + barrier.subresourceRange.baseMipLevel = mipLevel.get() - 1; + + commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, barrier); + } // We can do it for all layers at once. - commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, barrier); VkImageBlit blit = {}; blit.srcOffsets[0] = {0, 0, 0}; blit.srcOffsets[1] = {mipWidth, mipHeight, mipDepth}; @@ -8708,62 +8135,77 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, blit.dstSubresource.baseArrayLayer = 0; blit.dstSubresource.layerCount = mLayerCount; - commandBuffer->blitImage(mImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, filter); + commandBuffer->blitImage(mImage, blitSrcLayout, mImage, blitDstLayout, 1, &blit, + filter); } mipWidth = nextMipWidth; mipHeight = nextMipHeight; mipDepth = nextMipDepth; } - // Transition all mip level to the same layout so we can declare our whole image layout to one - // ImageLayout. FragmentShaderReadOnly is picked here since this is the most reasonable usage - // after glGenerateMipmap call. - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - if (baseLevel.get() > 0) + // If the GENERAL layout is not used, the layout of the mips need to be unified because we + // really only track one layout for the whole image. + if (!isGeneralLayout) { - // [0:baseLevel-1] from TRANSFER_DST to SHADER_READ - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = baseLevel.get(); + // Transition all mip level to the same layout so we can declare our whole image layout to + // one ImageAccess. FragmentShaderReadOnly is picked here since this is the most reasonable + // usage after glGenerateMipmap call. + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + if (baseLevel.get() > 0) + { + // [0:baseLevel-1] from TRANSFER_DST to SHADER_READ + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = baseLevel.get(); + commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier); + } + // [maxLevel:mLevelCount-1] from TRANSFER_DST to SHADER_READ + ASSERT(mLevelCount > maxLevel.get()); + barrier.subresourceRange.baseMipLevel = maxLevel.get(); + barrier.subresourceRange.levelCount = mLevelCount - maxLevel.get(); commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier); + // [baseLevel:maxLevel-1] from TRANSFER_SRC to SHADER_READ + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.subresourceRange.baseMipLevel = baseLevel.get(); + barrier.subresourceRange.levelCount = maxLevel.get() - baseLevel.get(); + commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier); + + // This is just changing the internal state of the image helper so that the next call + // to changeLayout will use this layout as the "oldLayout" argument. + // mLastNonShaderReadOnlyAccess is used to ensure previous write are made visible to reads, + // since the only write here is transfer, hence mLastNonShaderReadOnlyAccess is set to + // ImageAccess::TransferDst. + setCurrentImageAccess(renderer, ImageAccess::FragmentShaderReadOnly); + } + else + { + // Make sure the following commands know a transfer operation has happened since the last + // barrier, and what subresource it has affected. + setCurrentImageAccess(renderer, ImageAccess::TransferSrcDst); + onWrite(baseLevelGL + 1, mLevelCount - 1, 0, mLayerCount, VK_IMAGE_ASPECT_COLOR_BIT); } - // [maxLevel:mLevelCount-1] from TRANSFER_DST to SHADER_READ - ASSERT(mLevelCount > maxLevel.get()); - barrier.subresourceRange.baseMipLevel = maxLevel.get(); - barrier.subresourceRange.levelCount = mLevelCount - maxLevel.get(); - commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier); - // [baseLevel:maxLevel-1] from TRANSFER_SRC to SHADER_READ - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.subresourceRange.baseMipLevel = baseLevel.get(); - barrier.subresourceRange.levelCount = maxLevel.get() - baseLevel.get(); - commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier); - - // This is just changing the internal state of the image helper so that the next call - // to changeLayout will use this layout as the "oldLayout" argument. - // mLastNonShaderReadOnlyLayout is used to ensure previous write are made visible to reads, - // since the only write here is transfer, hence mLastNonShaderReadOnlyLayout is set to - // ImageLayout::TransferDst. - setCurrentImageLayout(renderer, ImageLayout::FragmentShaderReadOnly); contextVk->trackImageWithOutsideRenderPassEvent(this); return angle::Result::Continue; } -void ImageHelper::resolve(ImageHelper *dst, +void ImageHelper::resolve(Renderer *renderer, + ImageHelper *dst, const VkImageResolve ®ion, OutsideRenderPassCommandBuffer *commandBuffer) { - ASSERT(mCurrentLayout == ImageLayout::TransferSrc || - mCurrentLayout == ImageLayout::SharedPresent); - commandBuffer->resolveImage(getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst->getImage(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + ASSERT(mCurrentAccess == ImageAccess::TransferSrc || + mCurrentAccess == ImageAccess::SharedPresent); + ASSERT(dst->getCurrentImageAccess() == ImageAccess::TransferDst || + dst->getCurrentImageAccess() == ImageAccess::SharedPresent); + commandBuffer->resolveImage(getImage(), getCurrentLayout(renderer), dst->getImage(), + dst->getCurrentLayout(renderer), 1, ®ion); } void ImageHelper::removeSingleSubresourceStagedUpdates(ContextVk *contextVk, @@ -8774,7 +8216,7 @@ void ImageHelper::removeSingleSubresourceStagedUpdates(ContextVk *contextVk, mCurrentSingleClearValue.reset(); // Find any staged updates for this index and remove them from the pending list. - std::vector *levelUpdates = getLevelUpdates(levelIndexGL); + SubresourceUpdates *levelUpdates = getLevelUpdates(levelIndexGL); if (levelUpdates == nullptr) { return; @@ -8807,7 +8249,7 @@ void ImageHelper::removeSingleStagedClearAfterInvalidate(gl::LevelIndex levelInd // ClearAfterInvalidate update pending to this subresource, and that's a color clear due to // emulated channels after invalidate. This function removes that update. - std::vector *levelUpdates = getLevelUpdates(levelIndexGL); + SubresourceUpdates *levelUpdates = getLevelUpdates(levelIndexGL); if (levelUpdates == nullptr) { return; @@ -8836,7 +8278,7 @@ void ImageHelper::removeStagedUpdates(ErrorContext *context, // Remove all updates to levels [start, end]. for (gl::LevelIndex level = levelGLStart; level <= levelGLEnd; ++level) { - std::vector *levelUpdates = getLevelUpdates(level); + SubresourceUpdates *levelUpdates = getLevelUpdates(level); if (levelUpdates == nullptr) { ASSERT(static_cast(level.get()) >= mSubresourceUpdates.size()); @@ -8867,7 +8309,7 @@ angle::Result ImageHelper::stageSubresourceUpdateImpl(ContextVk *contextVk, GLenum type, const uint8_t *pixels, const Format &vkFormat, - ImageAccess access, + ImageFormatSupport formatSupport, const GLuint inputRowPitch, const GLuint inputDepthPitch, const GLuint inputSkipBytes, @@ -8876,7 +8318,7 @@ angle::Result ImageHelper::stageSubresourceUpdateImpl(ContextVk *contextVk, { *updateAppliedImmediatelyOut = false; - const angle::Format &storageFormat = vkFormat.getActualImageFormat(access); + const angle::Format &storageFormat = vkFormat.getActualImageFormat(formatSupport); size_t outputRowPitch; size_t outputDepthPitch; @@ -8885,7 +8327,7 @@ angle::Result ImageHelper::stageSubresourceUpdateImpl(ContextVk *contextVk, uint32_t bufferImageHeight; size_t allocationSize; - LoadImageFunctionInfo loadFunctionInfo = vkFormat.getTextureLoadFunction(access, type); + LoadImageFunctionInfo loadFunctionInfo = vkFormat.getTextureLoadFunction(formatSupport, type); LoadImageFunction stencilLoadFunction = nullptr; bool useComputeTransCoding = false; @@ -9151,7 +8593,7 @@ angle::Result ImageHelper::stageSubresourceUpdateImpl(ContextVk *contextVk, return angle::Result::Continue; } -angle::Result ImageHelper::updateSubresourceOnHost(ErrorContext *context, +angle::Result ImageHelper::updateSubresourceOnHost(ContextVk *contextVk, ApplyImageUpdate applyUpdate, const gl::ImageIndex &index, const gl::Extents &glExtents, @@ -9162,34 +8604,39 @@ angle::Result ImageHelper::updateSubresourceOnHost(ErrorContext *context, bool *copiedOut) { // If the image is not set up for host copy, it can't be done. - if (!valid() || (mUsage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) == 0) + if (!valid() || (mVkImageCreateInfo.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) == 0) { return angle::Result::Continue; } - Renderer *renderer = context->getRenderer(); + Renderer *renderer = contextVk->getRenderer(); const VkPhysicalDeviceHostImageCopyPropertiesEXT &hostImageCopyProperties = renderer->getPhysicalDeviceHostImageCopyProperties(); // The image should be unused by the GPU. if (!renderer->hasResourceUseFinished(getResourceUse())) { - ANGLE_TRY(renderer->checkCompletedCommandsAndCleanup(context)); + ANGLE_TRY(renderer->checkCompletedCommandsAndCleanup(contextVk)); if (!renderer->hasResourceUseFinished(getResourceUse())) { return angle::Result::Continue; } } - // The image should not have any pending updates to this subresource. - // - // TODO: if there are any pending updates, see if they can be pruned given the incoming update. - // This would most likely be the case where a clear is automatically staged for robustness or - // other reasons, which would now be superseded by the data upload. http://anglebug.com/42266771 + // If there are staged updates that will be completely overwritten, try to drop them. In + // particular, this commonly happens where a clear is automatically staged for robustness or + // other reasons, which would now be superseded by the data upload. const gl::LevelIndex updateLevelGL(index.getLevelIndex()); const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0; const uint32_t layerCount = index.getLayerCount(); - if (hasStagedUpdatesForSubresource(updateLevelGL, layerIndex, layerCount)) + const bool isArray = gl::IsArrayTextureType(index.getType()); + const uint32_t baseArrayLayer = isArray ? offset.z : layerIndex; + const gl::Box updateBoundingBox = + MakeUpdateBoundingBox(offset, glExtents, baseArrayLayer, layerCount); + pruneSupersededUpdatesForLevelImpl(contextVk, updateLevelGL, updateBoundingBox); + + // If there are still pending updates to this subresource, cannot overwrite it. + if (hasStagedUpdatesForSubresource(updateLevelGL, baseArrayLayer, layerCount)) { return angle::Result::Continue; } @@ -9197,7 +8644,7 @@ angle::Result ImageHelper::updateSubresourceOnHost(ErrorContext *context, // The image should be in a layout this is copiable. If UNDEFINED, it can be transitioned to a // layout that is copyable. const VkImageAspectFlags aspectMask = getAspectFlags(); - if (mCurrentLayout == ImageLayout::Undefined) + if (mCurrentAccess == ImageAccess::Undefined) { VkHostImageLayoutTransitionInfoEXT transition = {}; transition.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT; @@ -9205,25 +8652,34 @@ angle::Result ImageHelper::updateSubresourceOnHost(ErrorContext *context, transition.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // The GENERAL layout is always guaranteed to be in // VkPhysicalDeviceHostImageCopyPropertiesEXT::pCopyDstLayouts - transition.newLayout = VK_IMAGE_LAYOUT_GENERAL; + transition.newLayout = renderer->getVkImageLayout(ImageAccess::HostCopy); transition.subresourceRange.aspectMask = aspectMask; transition.subresourceRange.baseMipLevel = 0; transition.subresourceRange.levelCount = mLevelCount; transition.subresourceRange.baseArrayLayer = 0; transition.subresourceRange.layerCount = mLayerCount; - ANGLE_VK_TRY(context, vkTransitionImageLayoutEXT(renderer->getDevice(), 1, &transition)); - mCurrentLayout = ImageLayout::HostCopy; + ANGLE_VK_TRY(contextVk, vkTransitionImageLayoutEXT(renderer->getDevice(), 1, &transition)); + mCurrentAccess = ImageAccess::HostCopy; } - else if (mCurrentLayout != ImageLayout::HostCopy && - !IsAnyLayout(getCurrentLayout(renderer), hostImageCopyProperties.pCopyDstLayouts, - hostImageCopyProperties.copyDstLayoutCount)) + else if (mCurrentAccess == ImageAccess::HostCopy) { - return angle::Result::Continue; + // If last access to the image was a host-copy, continue to copy to it on the host; this + // frequently happens because uploads to mips or layers can be done by separate calls. + } + else + { + // If host-copy is disallowed post-initialization, or if the layout is not supported for + // host-copy, fall back to the buffer-copy path. + const bool canHostCopyAfterGpuUse = + renderer->getFeatures().allowHostImageCopyAfterInitialUpload.enabled && + IsAnyLayout(getCurrentLayout(renderer), hostImageCopyProperties.pCopyDstLayouts, + hostImageCopyProperties.copyDstLayoutCount); + if (!canHostCopyAfterGpuUse) + { + return angle::Result::Continue; + } } - - const bool isArray = gl::IsArrayTextureType(index.getType()); - const uint32_t baseArrayLayer = isArray ? offset.z : layerIndex; onWrite(updateLevelGL, 1, baseArrayLayer, layerCount, aspectMask); *copiedOut = true; @@ -9234,9 +8690,9 @@ angle::Result ImageHelper::updateSubresourceOnHost(ErrorContext *context, // appropriate synchronization (such as through glFenceSync), and because the copy is happening // in this call (just without holding the lock), the sync function won't be called until the // copy is done. - auto doCopy = [context, image = mImage.getHandle(), source, memoryRowLength, memoryImageHeight, - aspectMask, levelVk = toVkLevel(updateLevelGL), isArray, baseArrayLayer, - layerCount, offset, glExtents, + auto doCopy = [contextVk, image = mImage.getHandle(), source, memoryRowLength, + memoryImageHeight, aspectMask, levelVk = toVkLevel(updateLevelGL), isArray, + baseArrayLayer, layerCount, offset, glExtents, layout = getCurrentLayout(renderer)](void *resultOut) { ANGLE_TRACE_EVENT0("gpu.angle", "Upload image data on host"); ANGLE_UNUSED_VARIABLE(resultOut); @@ -9266,10 +8722,10 @@ angle::Result ImageHelper::updateSubresourceOnHost(ErrorContext *context, copyInfo.regionCount = 1; copyInfo.pRegions = ©Region; - VkResult result = vkCopyMemoryToImageEXT(context->getDevice(), ©Info); + VkResult result = vkCopyMemoryToImageEXT(contextVk->getDevice(), ©Info); if (result != VK_SUCCESS) { - context->handleError(result, __FILE__, ANGLE_FUNCTION, __LINE__); + contextVk->handleError(result, __FILE__, ANGLE_FUNCTION, __LINE__); } }; @@ -9306,7 +8762,7 @@ angle::Result ImageHelper::reformatStagedBufferUpdates(ContextVk *contextVk, const gl::InternalFormat &dstFormatInfo = gl::GetSizedInternalFormatInfo(dstFormat.glInternalFormat); - for (std::vector &levelUpdates : mSubresourceUpdates) + for (SubresourceUpdates &levelUpdates : mSubresourceUpdates) { for (SubresourceUpdate &update : levelUpdates) { @@ -9425,7 +8881,7 @@ angle::Result ImageHelper::calculateBufferInfo(ContextVk *contextVk, void ImageHelper::onRenderPassAttach(const QueueSerial &queueSerial) { setQueueSerial(queueSerial); - // updatePipelineStageAccessHistory uses mCurrentLayout which we dont know yet (deferred until + // updatePipelineStageAccessHistory uses mCurrentAccess which we dont know yet (deferred until // endRenderPass time). So update it directly since we know attachment will be accessed by // fragment and attachment stages. mPipelineStageAccessHeuristic.onAccess(PipelineStageGroup::FragmentOnly); @@ -9476,16 +8932,42 @@ bool ImageHelper::hasSubresourceDefinedStencilContent(gl::LevelIndex level, .any(); } +void ImageHelper::invalidateEntireLevelContent(vk::ErrorContext *context, gl::LevelIndex level) +{ + invalidateSubresourceContentImpl( + context, level, 0, mLayerCount, + static_cast(getIntendedAspectFlags() & ~VK_IMAGE_ASPECT_STENCIL_BIT), + nullptr, nullptr); +} + void ImageHelper::invalidateSubresourceContent(ContextVk *contextVk, gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount, bool *preferToKeepContentsDefinedOut) { - invalidateSubresourceContentImpl( - contextVk, level, layerIndex, layerCount, - static_cast(getAspectFlags() & ~VK_IMAGE_ASPECT_STENCIL_BIT), - &getLevelContentDefined(toVkLevel(level)), preferToKeepContentsDefinedOut); + const VkImageAspectFlagBits aspect = + static_cast(getAspectFlags() & ~VK_IMAGE_ASPECT_STENCIL_BIT); + bool layerLimitReached = false; + invalidateSubresourceContentImpl(contextVk, level, layerIndex, layerCount, aspect, + preferToKeepContentsDefinedOut, &layerLimitReached); + if (layerLimitReached) + { + const char *aspectName = (aspect == VK_IMAGE_ASPECT_DEPTH_BIT ? "depth" : "color"); + ANGLE_VK_PERF_WARNING( + contextVk, GL_DEBUG_SEVERITY_LOW, + "glInvalidateFramebuffer (%s) ineffective on attachments with layer >= 8", aspectName); + } +} + +void ImageHelper::invalidateEntireLevelStencilContent(vk::ErrorContext *context, + gl::LevelIndex level) +{ + if (getIntendedFormat().stencilBits > 0) + { + invalidateSubresourceContentImpl(context, level, 0, mLayerCount, + VK_IMAGE_ASPECT_STENCIL_BIT, nullptr, nullptr); + } } void ImageHelper::invalidateSubresourceStencilContent(ContextVk *contextVk, @@ -9494,18 +8976,25 @@ void ImageHelper::invalidateSubresourceStencilContent(ContextVk *contextVk, uint32_t layerCount, bool *preferToKeepContentsDefinedOut) { - invalidateSubresourceContentImpl( - contextVk, level, layerIndex, layerCount, VK_IMAGE_ASPECT_STENCIL_BIT, - &getLevelStencilContentDefined(toVkLevel(level)), preferToKeepContentsDefinedOut); + bool layerLimitReached = false; + invalidateSubresourceContentImpl(contextVk, level, layerIndex, layerCount, + VK_IMAGE_ASPECT_STENCIL_BIT, + preferToKeepContentsDefinedOut, &layerLimitReached); + if (layerLimitReached) + { + ANGLE_VK_PERF_WARNING( + contextVk, GL_DEBUG_SEVERITY_LOW, + "glInvalidateFramebuffer (stencil) ineffective on attachments with layer >= 8"); + } } -void ImageHelper::invalidateSubresourceContentImpl(ContextVk *contextVk, +void ImageHelper::invalidateSubresourceContentImpl(vk::ErrorContext *context, gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount, VkImageAspectFlagBits aspect, - LevelContentDefinedMask *contentDefinedMask, - bool *preferToKeepContentsDefinedOut) + bool *preferToKeepContentsDefinedOut, + bool *layerLimitReachedOut) { // If the aspect being invalidated doesn't exist, skip invalidation altogether. if ((getAspectFlags() & aspect) == 0) @@ -9536,7 +9025,7 @@ void ImageHelper::invalidateSubresourceContentImpl(ContextVk *contextVk, break; case VK_IMAGE_ASPECT_COLOR_BIT: skip = hasEmulatedChannels && - contextVk->getFeatures().preferSkippingInvalidateForEmulatedFormats.enabled; + context->getFeatures().preferSkippingInvalidateForEmulatedFormats.enabled; break; default: UNREACHABLE(); @@ -9554,24 +9043,27 @@ void ImageHelper::invalidateSubresourceContentImpl(ContextVk *contextVk, if (layerIndex >= kMaxContentDefinedLayerCount) { - const char *aspectName = "color"; - if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) - { - aspectName = "depth"; - } - else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) - { - aspectName = "stencil"; - } - ANGLE_VK_PERF_WARNING( - contextVk, GL_DEBUG_SEVERITY_LOW, - "glInvalidateFramebuffer (%s) ineffective on attachments with layer >= 8", aspectName); + ASSERT(layerLimitReachedOut != nullptr); + *layerLimitReachedOut = true; return; } uint8_t layerRangeBits = GetContentDefinedLayerRangeBits(layerIndex, layerCount, kMaxContentDefinedLayerCount); - *contentDefinedMask &= static_cast(~layerRangeBits); + LevelIndex levelVk = toVkLevel(level); + if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) + { + clearLevelStencilContentDefined(levelVk, layerRangeBits); + } + else + { + clearLevelContentDefined(levelVk, layerRangeBits); + } + + // The VkImage data has been invalidated, the previous storeOp maybe turned into DontCare, which + // means there is no grantee that it still contains mCurrentSingleClearValue data. THis is also + // consistent with mVkImageContentDefined since we have just cleared the bits. + mCurrentSingleClearValue.reset(); // If there are emulated channels, stage a clear to make sure those channels continue to contain // valid values. @@ -9592,72 +9084,73 @@ void ImageHelper::restoreSubresourceContent(gl::LevelIndex level, { restoreSubresourceContentImpl( level, layerIndex, layerCount, - static_cast(getAspectFlags() & ~VK_IMAGE_ASPECT_STENCIL_BIT), - &getLevelContentDefined(toVkLevel(level))); + static_cast(getAspectFlags() & ~VK_IMAGE_ASPECT_STENCIL_BIT)); } void ImageHelper::restoreSubresourceStencilContent(gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount) { - restoreSubresourceContentImpl(level, layerIndex, layerCount, VK_IMAGE_ASPECT_STENCIL_BIT, - &getLevelStencilContentDefined(toVkLevel(level))); + restoreSubresourceContentImpl(level, layerIndex, layerCount, VK_IMAGE_ASPECT_STENCIL_BIT); } void ImageHelper::restoreSubresourceContentImpl(gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount, - VkImageAspectFlagBits aspect, - LevelContentDefinedMask *contentDefinedMask) + VkImageAspectFlagBits aspect) { if (layerIndex >= kMaxContentDefinedLayerCount) { return; } + // This function is called on attachments during a render pass when it's determined that + // they should no longer be considered invalidated. For an attachment with emulated + // format that has extra channels, invalidateSubresourceContentImpl may have proactively + // inserted a clear so that the extra channels continue to have defined values. + // |FramebufferVk::invalidateImpl| closes the render pass right away however in that + // case, so it should be impossible for the contents of such formats to need to be + // restored. + const bool hasClearAfterInvalidateUpdate = + getLevelUpdates(level) != nullptr && getLevelUpdates(level)->size() != 0 && + getLevelUpdates(level)->at(0).updateSource == UpdateSource::ClearAfterInvalidate; + ASSERT(!hasEmulatedImageChannels() || !hasClearAfterInvalidateUpdate); + + // Additionally, as the resource has been rewritten to in the render pass, its no longer cleared + // to the cached value. + mCurrentSingleClearValue.reset(); + uint8_t layerRangeBits = GetContentDefinedLayerRangeBits(layerIndex, layerCount, kMaxContentDefinedLayerCount); + LevelIndex levelVk = toVkLevel(level); - switch (aspect) + if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) { - case VK_IMAGE_ASPECT_DEPTH_BIT: - // Emulated depth channel should never have been marked invalid, so it can retain its - // cleared value. - ASSERT(!hasEmulatedDepthChannel() || - (contentDefinedMask->bits() & layerRangeBits) == layerRangeBits); - break; - case VK_IMAGE_ASPECT_STENCIL_BIT: - // Emulated stencil channel should never have been marked invalid, so it can retain its - // cleared value. - ASSERT(!hasEmulatedStencilChannel() || - (contentDefinedMask->bits() & layerRangeBits) == layerRangeBits); - break; - case VK_IMAGE_ASPECT_COLOR_BIT: - { - // This function is called on attachments during a render pass when it's determined that - // they should no longer be considered invalidated. For an attachment with emulated - // format that has extra channels, invalidateSubresourceContentImpl may have proactively - // inserted a clear so that the extra channels continue to have defined values. - // |FramebufferVk::invalidateImpl| closes the render pass right away however in that - // case, so it should be impossible for the contents of such formats to need to be - // restored. - const bool hasClearAfterInvalidateUpdate = - getLevelUpdates(level) != nullptr && getLevelUpdates(level)->size() != 0 && - getLevelUpdates(level)->at(0).updateSource == UpdateSource::ClearAfterInvalidate; - ASSERT(!hasEmulatedImageChannels() || !hasClearAfterInvalidateUpdate); - - break; - } - default: - UNREACHABLE(); - break; + setLevelStencilContentDefined(levelVk, layerRangeBits); } + else + { + setLevelContentDefined(levelVk, layerRangeBits); + } +} - // Additionally, as the resource has been rewritten to in the render pass, its no longer cleared - // to the cached value. - mCurrentSingleClearValue.reset(); - - *contentDefinedMask |= layerRangeBits; +// Returns true if we have valid data in any non-emulated channel. +bool ImageHelper::isVkImageContentDefined() const +{ + if (isDepthOrStencil()) + { + // The emulated channel will always have valid content since we stage clear for emulated + // channel. When we query if VkImage has defined content or not, we only care about user + // content. So ignore the emulated channel when checking content defined. + return (getIntendedFormat().depthBits > 0 && + IsAnySubresourceContentDefined(mVkImageContentDefined)) || + (getIntendedFormat().stencilBits > 0 && + IsAnySubresourceContentDefined(mVkImageStencilContentDefined)); + } + else + { + return IsAnySubresourceContentDefined(mVkImageContentDefined); + } } angle::Result ImageHelper::stagePartialClear(ContextVk *contextVk, @@ -9670,12 +9163,12 @@ angle::Result ImageHelper::stagePartialClear(ContextVk *contextVk, GLenum type, const gl::InternalFormat &formatInfo, const Format &vkFormat, - ImageAccess access, + ImageFormatSupport formatSupport, const uint8_t *data) { // If the input data pointer is null, the texture is filled with zeros. const angle::Format &intendedFormat = vkFormat.getIntendedFormat(); - const angle::Format &actualFormat = vkFormat.getActualImageFormat(access); + const angle::Format &actualFormat = vkFormat.getActualImageFormat(formatSupport); auto intendedPixelSize = static_cast(intendedFormat.pixelBytes); auto actualPixelSize = static_cast(actualFormat.pixelBytes); @@ -9688,7 +9181,7 @@ angle::Result ImageHelper::stagePartialClear(ContextVk *contextVk, // The appropriate loading function is used to take the original value as a single pixel and // convert it into the format actually used for this image. std::vector actualData(actualPixelSize, 0); - LoadImageFunctionInfo loadFunctionInfo = vkFormat.getTextureLoadFunction(access, type); + LoadImageFunctionInfo loadFunctionInfo = vkFormat.getTextureLoadFunction(formatSupport, type); bool stencilOnly = formatInfo.sizedInternalFormat == GL_STENCIL_INDEX8; if (stencilOnly) @@ -9756,7 +9249,7 @@ angle::Result ImageHelper::stageSubresourceUpdate(ContextVk *contextVk, GLenum type, const uint8_t *pixels, const Format &vkFormat, - ImageAccess access, + ImageFormatSupport formatSupport, ApplyImageUpdate applyUpdate, bool *updateAppliedImmediatelyOut) { @@ -9766,9 +9259,10 @@ angle::Result ImageHelper::stageSubresourceUpdate(ContextVk *contextVk, ANGLE_TRY(calculateBufferInfo(contextVk, glExtents, formatInfo, unpack, type, index.usesTex3D(), &inputRowPitch, &inputDepthPitch, &inputSkipBytes)); - ANGLE_TRY(stageSubresourceUpdateImpl( - contextVk, index, glExtents, offset, formatInfo, unpack, type, pixels, vkFormat, access, - inputRowPitch, inputDepthPitch, inputSkipBytes, applyUpdate, updateAppliedImmediatelyOut)); + ANGLE_TRY(stageSubresourceUpdateImpl(contextVk, index, glExtents, offset, formatInfo, unpack, + type, pixels, vkFormat, formatSupport, inputRowPitch, + inputDepthPitch, inputSkipBytes, applyUpdate, + updateAppliedImmediatelyOut)); return angle::Result::Continue; } @@ -9820,7 +9314,7 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer( const gl::Offset &dstOffset, const gl::Extents &dstExtent, const gl::InternalFormat &formatInfo, - ImageAccess access, + ImageFormatSupport formatSupport, FramebufferVk *framebufferVk) { ContextVk *contextVk = GetImpl(context); @@ -9845,8 +9339,9 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer( Renderer *renderer = contextVk->getRenderer(); const Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat); - const angle::Format &storageFormat = vkFormat.getActualImageFormat(access); - LoadImageFunctionInfo loadFunction = vkFormat.getTextureLoadFunction(access, formatInfo.type); + const angle::Format &storageFormat = vkFormat.getActualImageFormat(formatSupport); + LoadImageFunctionInfo loadFunction = + vkFormat.getTextureLoadFunction(formatSupport, formatInfo.type); size_t outputRowPitch = storageFormat.pixelBytes * clippedRectangle.width; size_t outputDepthPitch = outputRowPitch * clippedRectangle.height; @@ -10139,8 +9634,7 @@ void ImageHelper::stageClearIfEmulatedFormat(bool isRobustResourceInitEnabled, b } } -bool ImageHelper::verifyEmulatedClearsAreBeforeOtherUpdates( - const std::vector &updates) +bool ImageHelper::verifyEmulatedClearsAreBeforeOtherUpdates(const SubresourceUpdates &updates) { bool isIteratingEmulatedClears = true; @@ -10168,12 +9662,81 @@ bool ImageHelper::verifyEmulatedClearsAreBeforeOtherUpdates( return true; } +void ImageHelper::copyStateAndMoveStorageFrom(ImageHelper *other) +{ + // move these vulkan objects + mImage = std::move(other->mImage); + mDeviceMemory = std::move(other->mDeviceMemory); + mVmaAllocation = std::move(other->mVmaAllocation); + if (other->mCurrentEvent.valid()) + { + mCurrentEvent = std::move(other->mCurrentEvent); + } + if (other->mLastNonShaderReadOnlyEvent.valid()) + { + mLastNonShaderReadOnlyEvent = std::move(other->mLastNonShaderReadOnlyEvent); + } + + // Copy over state + mUse = other->mUse; + + mVkImageCreateInfo = other->mVkImageCreateInfo; + mImageType = other->mImageType; + mTilingMode = other->mTilingMode; + mCreateFlags = other->mCreateFlags; + mRequestedUsage = other->mRequestedUsage; + mExtents = other->mExtents; + mRotatedAspectRatio = other->mRotatedAspectRatio; + mIntendedFormatID = other->mIntendedFormatID; + mActualFormatID = other->mActualFormatID; + mSamples = other->mSamples; + mImageSerial = other->mImageSerial; + + mCurrentAccess = other->mCurrentAccess; + mCurrentDeviceQueueIndex = other->mCurrentDeviceQueueIndex; + mLastNonShaderReadOnlyAccess = other->mLastNonShaderReadOnlyAccess; + mCurrentShaderReadStageMask = other->mCurrentShaderReadStageMask; + mRenderPassUsageFlags = other->mRenderPassUsageFlags; + mBarrierQueueSerial = other->mBarrierQueueSerial; + mPipelineStageAccessHeuristic = other->mPipelineStageAccessHeuristic; + + mIsReleasedToExternal = other->mIsReleasedToExternal; + mIsForeignImage = other->mIsForeignImage; + mYcbcrConversionDesc = other->mYcbcrConversionDesc; + + mFirstAllocatedLevel = other->mFirstAllocatedLevel; + mLayerCount = other->mLayerCount; + mLevelCount = other->mLevelCount; + mVkImageContentDefined = other->mVkImageContentDefined; + mVkImageStencilContentDefined = other->mVkImageStencilContentDefined; + + mAllocationSize = other->mAllocationSize; + mMemoryAllocationType = other->mMemoryAllocationType; + mMemoryTypeIndex = other->mMemoryTypeIndex; + mTileMemoryCompatible = other->mTileMemoryCompatible; + mUseTileMemory = other->mUseTileMemory; + + mSubresourcesWrittenSinceBarrier = other->mSubresourcesWrittenSinceBarrier; + + // Reset information for other (invalid) image. + other->mCurrentAccess = ImageAccess::Undefined; + other->mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; + other->mIsReleasedToExternal = false; + other->mIsForeignImage = false; + other->mLastNonShaderReadOnlyAccess = ImageAccess::Undefined; + other->mCurrentShaderReadStageMask = 0; + other->mImageSerial = kInvalidImageSerial; + other->mMemoryAllocationType = MemoryAllocationType::InvalidEnum; + other->setEntireContentUndefined(); + other->mTileMemoryCompatible = false; + other->mUseTileMemory = false; +} + void ImageHelper::stageSelfAsSubresourceUpdates( ContextVk *contextVk, uint32_t levelCount, gl::TextureType textureType, const gl::CubeFaceArray &skipLevels) - { // Nothing to do if every level must be skipped const gl::TexLevelMask levelsMask(angle::BitMask(levelCount) @@ -10193,43 +9756,8 @@ void ImageHelper::stageSelfAsSubresourceUpdates( std::unique_ptr> prevImage = std::make_unique>(); - // Move the necessary information for staged update to work, and keep the rest as part of this - // object. - - // Usage info - prevImage->get().Resource::operator=(std::move(*this)); - - // Vulkan objects - prevImage->get().mImage = std::move(mImage); - prevImage->get().mDeviceMemory = std::move(mDeviceMemory); - prevImage->get().mVmaAllocation = std::move(mVmaAllocation); - - // Barrier information. Note: mLevelCount is set to levelCount so that only the necessary - // levels are transitioned when flushing the update. - prevImage->get().mIntendedFormatID = mIntendedFormatID; - prevImage->get().mActualFormatID = mActualFormatID; - prevImage->get().mCurrentLayout = mCurrentLayout; - prevImage->get().mCurrentDeviceQueueIndex = mCurrentDeviceQueueIndex; - prevImage->get().mLastNonShaderReadOnlyLayout = mLastNonShaderReadOnlyLayout; - prevImage->get().mCurrentShaderReadStageMask = mCurrentShaderReadStageMask; - prevImage->get().mLevelCount = levelCount; - prevImage->get().mLayerCount = mLayerCount; - prevImage->get().mImageSerial = mImageSerial; - prevImage->get().mAllocationSize = mAllocationSize; - prevImage->get().mMemoryAllocationType = mMemoryAllocationType; - prevImage->get().mMemoryTypeIndex = mMemoryTypeIndex; - - // Reset information for current (invalid) image. - mCurrentLayout = ImageLayout::Undefined; - mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; - mIsReleasedToExternal = false; - mIsForeignImage = false; - mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; - mCurrentShaderReadStageMask = 0; - mImageSerial = kInvalidImageSerial; - mMemoryAllocationType = MemoryAllocationType::InvalidEnum; - - setEntireContentUndefined(); + // Move storage from this object to prevImage + prevImage->get().copyStateAndMoveStorageFrom(this); // Stage updates from the previous image. for (LevelIndex levelVk(0); levelVk < LevelIndex(levelCount); ++levelVk) @@ -10271,7 +9799,7 @@ angle::Result ImageHelper::flushSingleSubresourceStagedUpdates(ContextVk *contex ClearValuesArray *deferredClears, uint32_t deferredClearIndex) { - std::vector *levelUpdates = getLevelUpdates(levelGL); + SubresourceUpdates *levelUpdates = getLevelUpdates(levelGL); if (levelUpdates == nullptr || levelUpdates->empty()) { return angle::Result::Continue; @@ -10312,10 +9840,6 @@ angle::Result ImageHelper::flushSingleSubresourceStagedUpdates(ContextVk *contex // Note that this set command handles combined or separate depth/stencil clears. deferredClears->store(deferredClearIndex, update.aspectFlags, update.value); - // Do not call onWrite as it removes mCurrentSingleClearValue, but instead call - // setContentDefined directly. - setContentDefined(toVkLevel(levelGL), 1, layer, layerCount, update.aspectFlags); - // We process the updates again to erase any clears for this level. removeSingleSubresourceStagedUpdates(contextVk, levelGL, layer, layerCount); return angle::Result::Continue; @@ -10338,7 +9862,7 @@ angle::Result ImageHelper::flushStagedClearEmulatedChannelsUpdates(ContextVk *co { // It is expected that the checked mip levels in this loop do not surpass the size of // mSubresourceUpdates. - std::vector *levelUpdates = getLevelUpdates(updateMipLevelGL); + SubresourceUpdates *levelUpdates = getLevelUpdates(updateMipLevelGL); ASSERT(levelUpdates != nullptr); // The levels with no updates should be skipped. @@ -10351,7 +9875,7 @@ angle::Result ImageHelper::flushStagedClearEmulatedChannelsUpdates(ContextVk *co // than one such update type, we can process the first update and move on if there is // another update type in the list. ASSERT(verifyEmulatedClearsAreBeforeOtherUpdates(*levelUpdates)); - std::vector::iterator update = (*levelUpdates).begin(); + SubresourceUpdate *update = &(*levelUpdates).front(); if (update->updateSource != UpdateSource::ClearEmulatedChannelsOnly) { @@ -10375,7 +9899,7 @@ angle::Result ImageHelper::flushStagedClearEmulatedChannelsUpdates(ContextVk *co // superseded by Clears, |mCurrentSingleClearValue| is irrelevant and can't have a value. ASSERT(!mCurrentSingleClearValue.valid()); - levelUpdates->erase(update); + levelUpdates->pop_front(); if (!levelUpdates->empty()) { ASSERT(levelUpdates->begin()->updateSource != UpdateSource::ClearEmulatedChannelsOnly); @@ -10404,7 +9928,7 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, // done with fine granularity as updates are applied. This is achieved by specifying a layer // that is outside the tracking range. Under some circumstances, ComputeWrite is also required. // This need not be applied if the only updates are ClearEmulatedChannels. - CommandBufferAccess transferAccess; + CommandResources transferAccess; OutsideRenderPassCommandBufferHelper *commandBuffer = nullptr; bool transCoding = renderer->getFeatures().supportsComputeTranscodeEtcToBc.enabled && IsETCFormat(intendedFormat) && IsBCFormat(actualformat); @@ -10414,6 +9938,10 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, transferAccess.onImageTransferDstAndComputeWrite( levelGLStart, 1, kMaxContentDefinedLayerCount, 0, aspectFlags, this); } + else if (mUseTileMemory) + { + ASSERT(areStagedUpdatesClearOnly()); + } else { transferAccess.onImageTransferWrite(levelGLStart, 1, kMaxContentDefinedLayerCount, 0, @@ -10436,8 +9964,8 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, // It is expected that the checked mip levels in this loop do not surpass the size of // mSubresourceUpdates. - std::vector *levelUpdates = getLevelUpdates(updateMipLevelGL); - std::vector updatesToKeep; + SubresourceUpdates *levelUpdates = getLevelUpdates(updateMipLevelGL); + SubresourceUpdates updatesToKeep; ASSERT(levelUpdates != nullptr); // Because updates may have overlapping layer ranges, we must first figure out the actual @@ -10532,12 +10060,12 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, // a single barrier can be issued and we could continue with the rest of the updates // from the first level. In case of multiple layer updates within the same level, a // barrier might be needed if there are multiple updates in the same parts of the image. - ImageLayout barrierLayout = - transCoding ? ImageLayout::TransferDstAndComputeWrite : ImageLayout::TransferDst; + ImageAccess barrierAccess = + transCoding ? ImageAccess::TransferDstAndComputeWrite : ImageAccess::TransferDst; if (updateLayerCount >= kMaxParallelLayerWrites) { // If there are more subresources than bits we can track, always insert a barrier. - recordWriteBarrier(contextVk, aspectFlags, barrierLayout, updateMipLevelGL, 1, + recordWriteBarrier(contextVk, aspectFlags, barrierAccess, updateMipLevelGL, 1, updateBaseLayer, updateLayerCount, commandBuffer); mSubresourcesWrittenSinceBarrier[updateMipLevelGL.get()].set(); } @@ -10550,7 +10078,7 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, subresourceHash)) { // If there's overlap in subresource upload, issue a barrier. - recordWriteBarrier(contextVk, aspectFlags, barrierLayout, updateMipLevelGL, 1, + recordWriteBarrier(contextVk, aspectFlags, barrierAccess, updateMipLevelGL, 1, updateBaseLayer, updateLayerCount, commandBuffer); mSubresourcesWrittenSinceBarrier[updateMipLevelGL.get()].reset(); } @@ -10563,9 +10091,23 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, case UpdateSource::Clear: case UpdateSource::ClearAfterInvalidate: { - clear(renderer, update.data.clear.aspectFlags, update.data.clear.value, - updateMipLevelVk, updateBaseLayer, updateLayerCount, - &commandBuffer->getCommandBuffer()); + if (canTransferTo()) + { + clear(renderer, update.data.clear.aspectFlags, update.data.clear.value, + updateMipLevelVk, updateBaseLayer, updateLayerCount, + &commandBuffer->getCommandBuffer()); + } + else + { + ASSERT(mUseTileMemory); + UtilsVk::ClearTextureParameters params = {}; + params.aspectFlags = getAspectFlags(); + params.level = updateMipLevelVk; + params.clearArea = gl::Box(0, 0, 0, mExtents.width, mExtents.height, 1); + params.clearValue = update.data.clear.value; + params.layer = updateBaseLayer; + ANGLE_TRY(contextVk->getUtils().clearTexture(contextVk, this, params)); + } contextVk->getPerfCounters().fullImageClears++; // Remember the latest operation is a clear call. mCurrentSingleClearValue = update.data.clear; @@ -10622,7 +10164,7 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, ASSERT(currentBuffer && currentBuffer->valid()); ANGLE_TRY(currentBuffer->flush(renderer)); - CommandBufferAccess bufferAccess; + CommandResources bufferAccess; VkBufferImageCopy *copyRegion = &update.data.buffer.copyRegion; if (transCoding && update.data.buffer.formatID != actualformat) @@ -10660,7 +10202,7 @@ angle::Result ImageHelper::flushStagedUpdatesImpl(ContextVk *contextVk, } case UpdateSource::Image: { - CommandBufferAccess imageAccess; + CommandResources imageAccess; imageAccess.onImageTransferRead(aspectFlags, &update.refCounted.image->get()); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(imageAccess, &commandBuffer)); @@ -10721,7 +10263,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk, // the clear. if (mCurrentSingleClearValue.valid()) { - std::vector *levelUpdates = + SubresourceUpdates *levelUpdates = getLevelUpdates(gl::LevelIndex(mCurrentSingleClearValue.value().levelIndex)); if (levelUpdates && levelUpdates->size() == 1) { @@ -10730,8 +10272,6 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk, mCurrentSingleClearValue.value() == update.data.clear) { ASSERT(levelGLStart + 1 == levelGLEnd); - setContentDefined(toVkLevel(levelGLStart), 1, layerStart, layerEnd - layerStart, - update.data.clear.aspectFlags); ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW, "Repeated Clear on framebuffer attachment dropped"); update.release(renderer); @@ -10794,7 +10334,7 @@ bool ImageHelper::hasStagedUpdatesForSubresource(gl::LevelIndex levelGL, { // Check to see if any updates are staged for the given level and layer - const std::vector *levelUpdates = getLevelUpdates(levelGL); + const SubresourceUpdates *levelUpdates = getLevelUpdates(levelGL); if (levelUpdates == nullptr || levelUpdates->empty()) { return false; @@ -10822,7 +10362,7 @@ bool ImageHelper::hasStagedUpdatesForSubresource(gl::LevelIndex levelGL, bool ImageHelper::removeStagedClearUpdatesAndReturnColor(gl::LevelIndex levelGL, const VkClearColorValue **color) { - std::vector *levelUpdates = getLevelUpdates(levelGL); + SubresourceUpdates *levelUpdates = getLevelUpdates(levelGL); if (levelUpdates == nullptr || levelUpdates->empty()) { return false; @@ -10847,7 +10387,7 @@ bool ImageHelper::removeStagedClearUpdatesAndReturnColor(gl::LevelIndex levelGL, return result; } -void ImageHelper::adjustLayerRange(const std::vector &levelUpdates, +void ImageHelper::adjustLayerRange(const SubresourceUpdates &levelUpdates, uint32_t *layerStart, uint32_t *layerEnd) { @@ -10884,7 +10424,7 @@ bool ImageHelper::hasStagedUpdatesInLevels(gl::LevelIndex levelStart, gl::LevelI { for (gl::LevelIndex level = levelStart; level < levelEnd; ++level) { - const std::vector *levelUpdates = getLevelUpdates(level); + const SubresourceUpdates *levelUpdates = getLevelUpdates(level); if (levelUpdates == nullptr) { ASSERT(static_cast(level.get()) >= mSubresourceUpdates.size()); @@ -10905,7 +10445,7 @@ bool ImageHelper::hasStagedImageUpdatesWithMismatchedFormat(gl::LevelIndex level { for (gl::LevelIndex level = levelStart; level < levelEnd; ++level) { - const std::vector *levelUpdates = getLevelUpdates(level); + const SubresourceUpdates *levelUpdates = getLevelUpdates(level); if (levelUpdates == nullptr) { continue; @@ -10927,7 +10467,7 @@ bool ImageHelper::hasBufferSourcedStagedUpdatesInAllLevels() const { for (gl::LevelIndex level = mFirstAllocatedLevel; level <= getLastAllocatedLevel(); ++level) { - const std::vector *levelUpdates = getLevelUpdates(level); + const SubresourceUpdates *levelUpdates = getLevelUpdates(level); if (levelUpdates == nullptr || levelUpdates->empty()) { return false; @@ -10961,7 +10501,7 @@ bool ImageHelper::validateSubresourceUpdateBufferRefConsistent( uint32_t refs = 0; - for (const std::vector &levelUpdates : mSubresourceUpdates) + for (const SubresourceUpdates &levelUpdates : mSubresourceUpdates) { for (const SubresourceUpdate &update : levelUpdates) { @@ -10984,7 +10524,7 @@ bool ImageHelper::validateSubresourceUpdateImageRefConsistent(RefCounted &levelUpdates : mSubresourceUpdates) + for (const SubresourceUpdates &levelUpdates : mSubresourceUpdates) { for (const SubresourceUpdate &update : levelUpdates) { @@ -11000,7 +10540,7 @@ bool ImageHelper::validateSubresourceUpdateImageRefConsistent(RefCounted &levelUpdates : mSubresourceUpdates) + for (const SubresourceUpdates &levelUpdates : mSubresourceUpdates) { for (const SubresourceUpdate &update : levelUpdates) { @@ -11030,7 +10570,7 @@ void ImageHelper::pruneSupersededUpdatesForLevel(ContextVk *contextVk, { constexpr VkDeviceSize kSubresourceUpdateSizeBeforePruning = 16 * 1024 * 1024; // 16 MB constexpr int kUpdateCountThreshold = 1024; - std::vector *levelUpdates = getLevelUpdates(level); + SubresourceUpdates *levelUpdates = getLevelUpdates(level); // If we are below pruning threshold, nothing to do. const int updateCount = static_cast(levelUpdates->size()); @@ -11041,20 +10581,39 @@ void ImageHelper::pruneSupersededUpdatesForLevel(ContextVk *contextVk, return; } + pruneSupersededUpdatesForLevelImpl(contextVk, level, {}); +} + +void ImageHelper::pruneSupersededUpdatesForLevelImpl(ContextVk *contextVk, + const gl::LevelIndex level, + const gl::Box &upcomingUpdateBoundingBox) +{ + SubresourceUpdates *levelUpdates = getLevelUpdates(level); + if (levelUpdates == nullptr || levelUpdates->size() == 0) + { + return; + } + + // ClearEmulatedChannelsOnly updates can only be in the beginning of the list of updates. + // They don't entirely clear the image, so they cannot supersede any update. + ASSERT(verifyEmulatedClearsAreBeforeOtherUpdates(*levelUpdates)); + // Start from the most recent update and define a boundingBox that covers the region to be // updated. Walk through all earlier updates and if its update region is contained within the // boundingBox, mark it as superseded, otherwise reset the boundingBox and continue. // // Color, depth and stencil are the only types supported for now. The boundingBox for color and // depth types is at index 0 and index 1 has the boundingBox for stencil type. + // + // |upcomingUpdateBoundingBox| is non-empty in case an update is about to happen but is not + // staged. In that case, that unstaged update can also supersede the staged updates. VkDeviceSize supersededUpdateSize = 0; - std::array boundingBox = {gl::Box(gl::kOffsetZero, gl::Extents())}; + std::array boundingBox = {upcomingUpdateBoundingBox, upcomingUpdateBoundingBox}; auto canDropUpdate = [this, contextVk, level, &supersededUpdateSize, &boundingBox](SubresourceUpdate &update) { VkDeviceSize updateSize = 0; VkImageAspectFlags aspectMask = update.getDestAspectFlags(); - gl::Box currentUpdateBox(gl::kOffsetZero, gl::Extents()); const bool isColor = (aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_PLANE_0_BIT | @@ -11064,45 +10623,48 @@ void ImageHelper::pruneSupersededUpdatesForLevel(ContextVk *contextVk, ASSERT(isColor || isDepth || isStencil); int aspectIndex = (isColor || isDepth) ? 0 : 1; + uint32_t layerIndex = 0; + uint32_t layerCount = 0; + update.getDestSubresource(mLayerCount, &layerIndex, &layerCount); + + gl::Box currentUpdateBox(gl::kOffsetZero, gl::Extents()); if (update.updateSource == UpdateSource::Buffer) { - currentUpdateBox = gl::Box(update.data.buffer.copyRegion.imageOffset, - update.data.buffer.copyRegion.imageExtent); + currentUpdateBox = MakeUpdateBoundingBox(update.data.buffer.copyRegion.imageOffset, + update.data.buffer.copyRegion.imageExtent, + layerIndex, layerCount); updateSize = update.data.buffer.bufferHelper->getSize(); } else if (update.updateSource == UpdateSource::Image) { - currentUpdateBox = gl::Box(update.data.image.copyRegion.dstOffset, - update.data.image.copyRegion.extent); + currentUpdateBox = + MakeUpdateBoundingBox(update.data.image.copyRegion.dstOffset, + update.data.image.copyRegion.extent, layerIndex, layerCount); } else if (update.updateSource == UpdateSource::ClearPartial) { - currentUpdateBox = gl::Box( - update.data.clearPartial.offset.x, update.data.clearPartial.offset.z, - update.data.clearPartial.offset.z, update.data.clearPartial.extent.width, - update.data.clearPartial.extent.height, update.data.clearPartial.extent.depth); + currentUpdateBox = + MakeUpdateBoundingBox(update.data.clearPartial.offset, + update.data.clearPartial.extent, layerIndex, layerCount); } else { ASSERT(IsClear(update.updateSource)); - currentUpdateBox = gl::Box(gl::kOffsetZero, getLevelExtents(toVkLevel(level))); - } - - // Account for updates to layered images - uint32_t layerIndex = 0; - uint32_t layerCount = 0; - update.getDestSubresource(mLayerCount, &layerIndex, &layerCount); - if (layerIndex > 0 || layerCount > 1) - { - currentUpdateBox.z = layerIndex; - currentUpdateBox.depth = layerCount; + currentUpdateBox = MakeUpdateBoundingBox( + gl::kOffsetZero, getLevelExtents(toVkLevel(level)), layerIndex, layerCount); } // Check if current update region is superseded by the accumulated update region if (boundingBox[aspectIndex].contains(currentUpdateBox)) { - ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW, - "Dropped texture update that is superseded by a more recent one"); + // Warn that the app did something useless. In case of ClearEmulatedChannelsOnly, a + // clear is staged by ANGLE not the app, so no need to warn in that case. + if (update.updateSource != UpdateSource::ClearEmulatedChannelsOnly) + { + ANGLE_VK_PERF_WARNING( + contextVk, GL_DEBUG_SEVERITY_LOW, + "Dropped texture update that is superseded by a more recent one"); + } // Release the superseded update update.release(contextVk->getRenderer()); @@ -11132,6 +10694,8 @@ void ImageHelper::pruneSupersededUpdatesForLevel(ContextVk *contextVk, // Update total staging buffer size mTotalStagedBufferUpdateSize -= supersededUpdateSize; + + ASSERT(validateSubresourceUpdateRefCountsConsistent()); } void ImageHelper::removeSupersededUpdates(ContextVk *contextVk, @@ -11142,7 +10706,7 @@ void ImageHelper::removeSupersededUpdates(ContextVk *contextVk, for (LevelIndex levelVk(0); levelVk < LevelIndex(mLevelCount); ++levelVk) { gl::LevelIndex levelGL = toGLLevel(levelVk); - std::vector *levelUpdates = getLevelUpdates(levelGL); + SubresourceUpdates *levelUpdates = getLevelUpdates(levelGL); if (levelUpdates == nullptr || levelUpdates->size() == 0 || skipLevelsAllFaces.test(levelGL.get())) { @@ -11150,14 +10714,8 @@ void ImageHelper::removeSupersededUpdates(ContextVk *contextVk, continue; } - // ClearEmulatedChannelsOnly updates can only be in the beginning of the list of updates. - // They don't entirely clear the image, so they cannot supersede any update. - ASSERT(verifyEmulatedClearsAreBeforeOtherUpdates(*levelUpdates)); - pruneSupersededUpdatesForLevel(contextVk, levelGL, PruneReason::MinimizeWorkBeforeFlush); } - - ASSERT(validateSubresourceUpdateRefCountsConsistent()); } angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk, @@ -11169,8 +10727,7 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk, uint8_t **outDataPtr) { ANGLE_TRACE_EVENT0("gpu.angle", "ImageHelper::copyImageDataToBuffer"); - Renderer *renderer = contextVk->getRenderer(); - + Renderer *renderer = contextVk->getRenderer(); const angle::Format &imageFormat = getActualFormat(); // As noted in the OpenGL ES 3.2 specs, table 8.13, CopyTexImage cannot @@ -11190,7 +10747,7 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk, ANGLE_TRY(contextVk->initBufferForImageCopy(dstBuffer, bufferSize, MemoryCoherency::CachedPreferCoherent, imageFormat.id, &dstOffset, outDataPtr)); - ANGLE_TRY(dstBuffer->flush(contextVk->getRenderer())); + ANGLE_TRY(dstBuffer->flush(renderer)); VkBuffer bufferHandle = dstBuffer->getBuffer().getHandle(); @@ -11213,12 +10770,12 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk, regions.imageSubresource.layerCount = layerCount; regions.imageSubresource.mipLevel = sourceLevelVk.get(); - CommandBufferAccess access; - access.onBufferTransferWrite(dstBuffer); - access.onImageTransferRead(aspectFlags, this); + CommandResources resources; + resources.onBufferTransferWrite(dstBuffer); + resources.onImageTransferRead(aspectFlags, this); OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); commandBuffer->copyImageToBuffer(mImage, getCurrentLayout(renderer), bufferHandle, regionCount, ®ions); @@ -11258,12 +10815,14 @@ angle::Result ImageHelper::copySurfaceImageToBuffer(DisplayVk *displayVk, PrimaryCommandBuffer &primaryCommandBuffer = scopedCommandBuffer.get(); VkSemaphore acquireNextImageSemaphore; - recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageLayout::TransferSrc, + recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageAccess::TransferSrc, displayVk->getDeviceQueueIndex(), &primaryCommandBuffer, &acquireNextImageSemaphore); primaryCommandBuffer.copyImageToBuffer(mImage, getCurrentLayout(renderer), bufferHelper->getBuffer().getHandle(), 1, ®ion); + renderer->insertSubmitDebugMarkerInCommandBuffer(primaryCommandBuffer, + QueueSubmitReason::CopySurfaceImageToBuffer); ANGLE_VK_TRY(displayVk, primaryCommandBuffer.end()); QueueSerial submitQueueSerial; @@ -11307,12 +10866,14 @@ angle::Result ImageHelper::copyBufferToSurfaceImage(DisplayVk *displayVk, PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get(); VkSemaphore acquireNextImageSemaphore; - recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageLayout::TransferDst, + recordBarrierOneOffImpl(renderer, getAspectFlags(), ImageAccess::TransferDst, displayVk->getDeviceQueueIndex(), &commandBuffer, &acquireNextImageSemaphore); commandBuffer.copyBufferToImage(bufferHelper->getBuffer().getHandle(), mImage, getCurrentLayout(renderer), 1, ®ion); + renderer->insertSubmitDebugMarkerInCommandBuffer(commandBuffer, + QueueSubmitReason::CopyBufferToSurfaceImage); ANGLE_VK_TRY(displayVk, commandBuffer.end()); QueueSerial submitQueueSerial; @@ -11531,7 +11092,8 @@ bool ImageHelper::canCopyWithTransformForReadPixels(const PackPixelsParams &pack // Don't allow copies from emulated formats for simplicity. return !hasEmulatedImageFormat() && isSameFormatCopy && !needsTransformation && - isPitchMultipleOfTexelSize && isOffsetMultipleOfTexelSize && isRowLengthEnough; + isPitchMultipleOfTexelSize && isOffsetMultipleOfTexelSize && isRowLengthEnough && + canTransferFrom(); } bool ImageHelper::canCopyWithComputeForReadPixels(const PackPixelsParams &packPixelsParams, @@ -11695,20 +11257,18 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, if (isMultisampled) { ANGLE_TRY(resolvedImage.get().init2DStaging( - contextVk, contextVk->getState().hasProtectedContent(), renderer->getMemoryProperties(), + contextVk, contextVk->getState().hasProtectedContent(), gl::Extents(area.width, area.height, 1), mIntendedFormatID, mActualFormatID, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT, - 1)); + vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT, 1)); } else if (isExternalFormat) { ANGLE_TRY(resolvedImage.get().init2DStaging( - contextVk, contextVk->getState().hasProtectedContent(), renderer->getMemoryProperties(), + contextVk, contextVk->getState().hasProtectedContent(), gl::Extents(area.width, area.height, 1), angle::FormatID::R8G8B8A8_UNORM, angle::FormatID::R8G8B8A8_UNORM, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + vk::kImageUsageTransferBits | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT, 1)); } @@ -11749,13 +11309,15 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, ANGLE_TRY( contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy)); - CommandBufferAccess access; + CommandResources resources; OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Create some temp views because copyImage works in terms of them gl::TextureType textureType = Get2DTextureType(1, resolvedImage.get().getSamples()); + ScopedOverrideYCbCrFilter scopedOverrideYCbCrFilter(renderer, src, VK_FILTER_NEAREST); + // Surely we have a view of this already! vk::ImageView srcView; ANGLE_TRY(src->initLayerImageView(contextVk, textureType, VK_IMAGE_ASPECT_COLOR_BIT, @@ -11775,7 +11337,7 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, ANGLE_TRY(contextVk->getUtils().copyImage(contextVk, &resolvedImage.get(), &stagingView, src, &srcView, params)); - CommandBufferAccess readAccess; + CommandResources readAccess; readAccess.onImageTransferRead(layoutChangeAspectFlags, &resolvedImage.get()); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(readAccess, &commandBuffer)); @@ -11793,13 +11355,13 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, if (isMultisampled) { - CommandBufferAccess access; - access.onImageTransferRead(layoutChangeAspectFlags, this); - access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, layoutChangeAspectFlags, - &resolvedImage.get()); + CommandResources resources; + resources.onImageTransferRead(layoutChangeAspectFlags, this); + resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, layoutChangeAspectFlags, + &resolvedImage.get()); OutsideRenderPassCommandBuffer *commandBuffer; - ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); + ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer)); // Note: resolve only works on color images (not depth/stencil). ASSERT(copyAspectFlags == VK_IMAGE_ASPECT_COLOR_BIT); @@ -11814,7 +11376,7 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, resolveRegion.dstOffset = {}; resolveRegion.extent = srcExtent; - resolve(&resolvedImage.get(), resolveRegion, commandBuffer); + resolve(renderer, &resolvedImage.get(), resolveRegion, commandBuffer); // Make the resolved image the target of buffer copy. src = &resolvedImage.get(); @@ -11824,6 +11386,16 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, srcSubresource.mipLevel = 0; } + if (!src->canTransferFrom()) + { + ASSERT(src->useTileMemory()); + if (src->useTileMemory()) + { + ANGLE_TRY(src->fallbackFromTileMemory(contextVk)); + ASSERT(src->canTransferFrom()); + } + } + // If PBO and if possible, copy directly on the GPU. if (packPixelsParams.packBuffer) { @@ -11836,7 +11408,7 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, BufferHelper &packBuffer = GetImpl(packPixelsParams.packBuffer)->getBuffer(); VkDeviceSize packBufferOffset = packBuffer.getOffset(); - CommandBufferAccess copyAccess; + CommandResources copyAccess; copyAccess.onBufferTransferWrite(&packBuffer); copyAccess.onImageTransferRead(layoutChangeAspectFlags, src); @@ -11898,7 +11470,7 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, roundUp(region.bufferImageHeight, storageFormatInfo.compressedBlockHeight); } - CommandBufferAccess readbackAccess; + CommandResources readbackAccess; readbackAccess.onBufferTransferWrite(stagingBuffer); readbackAccess.onImageTransferRead(layoutChangeAspectFlags, src); @@ -11911,7 +11483,7 @@ angle::Result ImageHelper::readPixelsImpl(ContextVk *contextVk, ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH, "GPU stall due to ReadPixels"); // Triggers a full finish. - ANGLE_TRY(contextVk->finishImpl(RenderPassClosureReason::GLReadPixels)); + ANGLE_TRY(contextVk->finishImpl(QueueSubmitReason::GLReadPixels)); // invalidate must be called after wait for finish. ANGLE_TRY(stagingBuffer->invalidate(renderer)); @@ -11955,11 +11527,14 @@ angle::Result ImageHelper::packReadPixelBuffer(ContextVk *contextVk, // Must map the PBO in order to read its contents (and then unmap it later) BufferVk *packBufferVk = GetImpl(packPixelsParams.packBuffer); void *mapPtr = nullptr; - ANGLE_TRY(packBufferVk->mapImpl(contextVk, GL_MAP_WRITE_BIT, &mapPtr)); + BufferFeedback feedback; + ANGLE_TRY(packBufferVk->mapImpl(contextVk, GL_MAP_WRITE_BIT, &mapPtr, &feedback)); + ASSERT(!feedback.hasFeedback()); uint8_t *dst = static_cast(mapPtr) + reinterpret_cast(pixels); PackPixels(packPixelsParams, aspectFormat, area.width * aspectFormat.pixelBytes, readPixelBuffer, dst); - ANGLE_TRY(packBufferVk->unmapImpl(contextVk)); + ANGLE_TRY(packBufferVk->unmapImpl(contextVk, &feedback)); + ASSERT(!feedback.hasFeedback()); } else { @@ -12069,6 +11644,33 @@ ImageHelper::SubresourceUpdate::SubresourceUpdate(VkColorComponentFlags colorMas data.clear.colorMaskFlags = colorMaskFlags; } +ImageHelper::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other) + : updateSource(other.updateSource) +{ + switch (updateSource) + { + case UpdateSource::Clear: + case UpdateSource::ClearEmulatedChannelsOnly: + case UpdateSource::ClearAfterInvalidate: + data.clear = other.data.clear; + refCounted.buffer = nullptr; + break; + case UpdateSource::ClearPartial: + data.clearPartial = other.data.clearPartial; + break; + case UpdateSource::Buffer: + data.buffer = other.data.buffer; + refCounted.buffer = other.refCounted.buffer; + break; + case UpdateSource::Image: + data.image = other.data.image; + refCounted.image = other.refCounted.image; + break; + default: + UNREACHABLE(); + } +} + ImageHelper::SubresourceUpdate::SubresourceUpdate(SubresourceUpdate &&other) : updateSource(other.updateSource) { @@ -12240,15 +11842,14 @@ void ImageHelper::clipLevelToUpdateListUpperLimit(gl::LevelIndex *level) const *level = std::min(*level, levelLimit); } -std::vector *ImageHelper::getLevelUpdates(gl::LevelIndex level) +ImageHelper::SubresourceUpdates *ImageHelper::getLevelUpdates(gl::LevelIndex level) { return static_cast(level.get()) < mSubresourceUpdates.size() ? &mSubresourceUpdates[level.get()] : nullptr; } -const std::vector *ImageHelper::getLevelUpdates( - gl::LevelIndex level) const +const ImageHelper::SubresourceUpdates *ImageHelper::getLevelUpdates(gl::LevelIndex level) const { return static_cast(level.get()) < mSubresourceUpdates.size() ? &mSubresourceUpdates[level.get()] @@ -12280,8 +11881,7 @@ void ImageHelper::prependSubresourceUpdate(gl::LevelIndex level, SubresourceUpda mTotalStagedBufferUpdateSize += update.updateSource == UpdateSource::Buffer ? update.data.buffer.bufferHelper->getSize() : 0; - mSubresourceUpdates[level.get()].insert(mSubresourceUpdates[level.get()].begin(), - std::move(update)); + mSubresourceUpdates[level.get()].emplace_front(std::move(update)); onStateChange(angle::SubjectMessage::SubjectChanged); } @@ -12386,7 +11986,6 @@ ComputePipelineOptions GetComputePipelineOptions(vk::PipelineRobustness robustne // ImageViewHelper implementation. ImageViewHelper::ImageViewHelper() : mCurrentBaseMaxLevelHash(0), - mIsCopyImageViewShared(false), mReadColorspace(ImageViewColorspace::Invalid), mWriteColorspace(ImageViewColorspace::Invalid) {} @@ -12400,13 +11999,13 @@ ImageViewHelper::ImageViewHelper(ImageViewHelper &&other) std::swap(mPerLevelRangeLinearReadImageViews, other.mPerLevelRangeLinearReadImageViews); std::swap(mPerLevelRangeSRGBReadImageViews, other.mPerLevelRangeSRGBReadImageViews); - std::swap(mPerLevelRangeLinearCopyImageViews, other.mPerLevelRangeLinearCopyImageViews); - std::swap(mPerLevelRangeSRGBCopyImageViews, other.mPerLevelRangeSRGBCopyImageViews); - std::swap(mIsCopyImageViewShared, other.mIsCopyImageViewShared); std::swap(mPerLevelRangeStencilReadImageViews, other.mPerLevelRangeStencilReadImageViews); std::swap(mPerLevelRangeSamplerExternal2DY2YEXTImageViews, other.mPerLevelRangeSamplerExternal2DY2YEXTImageViews); + std::swap(mLinearCopyImageView, other.mLinearCopyImageView); + std::swap(mSRGBCopyImageView, other.mSRGBCopyImageView); + std::swap(mLayerLevelDrawImageViews, other.mLayerLevelDrawImageViews); std::swap(mLayerLevelDrawImageViewsLinear, other.mLayerLevelDrawImageViewsLinear); std::swap(mSubresourceDrawImageViews, other.mSubresourceDrawImageViews); @@ -12438,7 +12037,6 @@ void ImageViewHelper::release(Renderer *renderer, const ResourceUse &use) mReadColorspace = ImageViewColorspace::Invalid; mWriteColorspace = ImageViewColorspace::Invalid; // Clear shared flag - mIsCopyImageViewShared = false; mColorspaceState.reset(); GarbageObjects garbage; @@ -12448,11 +12046,19 @@ void ImageViewHelper::release(Renderer *renderer, const ResourceUse &use) // Release the read views ReleaseImageViews(&mPerLevelRangeLinearReadImageViews, &garbage); ReleaseImageViews(&mPerLevelRangeSRGBReadImageViews, &garbage); - ReleaseImageViews(&mPerLevelRangeLinearCopyImageViews, &garbage); - ReleaseImageViews(&mPerLevelRangeSRGBCopyImageViews, &garbage); ReleaseImageViews(&mPerLevelRangeStencilReadImageViews, &garbage); ReleaseImageViews(&mPerLevelRangeSamplerExternal2DY2YEXTImageViews, &garbage); + // Release the copy views + if (mLinearCopyImageView.valid()) + { + garbage.emplace_back(GetGarbage(&mLinearCopyImageView)); + } + if (mSRGBCopyImageView.valid()) + { + garbage.emplace_back(GetGarbage(&mSRGBCopyImageView)); + } + // Release the draw views ReleaseLayerLevelImageViews(&mLayerLevelDrawImageViews, &garbage); ReleaseLayerLevelImageViews(&mLayerLevelDrawImageViewsLinear, &garbage); @@ -12485,15 +12091,15 @@ void ImageViewHelper::release(Renderer *renderer, const ResourceUse &use) bool ImageViewHelper::isImageViewGarbageEmpty() const { - return mPerLevelRangeLinearReadImageViews.empty() && - mPerLevelRangeLinearCopyImageViews.empty() && mPerLevelRangeSRGBReadImageViews.empty() && - mPerLevelRangeSRGBCopyImageViews.empty() && + return mPerLevelRangeLinearReadImageViews.empty() && !mLinearCopyImageView.valid() && + mPerLevelRangeSRGBReadImageViews.empty() && !mSRGBCopyImageView.valid() && mPerLevelRangeStencilReadImageViews.empty() && mPerLevelRangeSamplerExternal2DY2YEXTImageViews.empty() && mLayerLevelDrawImageViews.empty() && mLayerLevelDrawImageViewsLinear.empty() && mSubresourceDrawImageViews.empty() && mLayerLevelDepthOnlyImageViews.empty() && mLayerLevelStencilOnlyImageViews.empty() && mSubresourceDepthOnlyImageViews.empty() && - mSubresourceStencilOnlyImageViews.empty() && mLayerLevelStorageImageViews.empty(); + mSubresourceStencilOnlyImageViews.empty() && mLayerLevelStorageImageViews.empty() && + !mFragmentShadingRateImageView.valid(); } void ImageViewHelper::destroy(VkDevice device) @@ -12506,11 +12112,13 @@ void ImageViewHelper::destroy(VkDevice device) // Release the read views DestroyImageViews(&mPerLevelRangeLinearReadImageViews, device); DestroyImageViews(&mPerLevelRangeSRGBReadImageViews, device); - DestroyImageViews(&mPerLevelRangeLinearCopyImageViews, device); - DestroyImageViews(&mPerLevelRangeSRGBCopyImageViews, device); DestroyImageViews(&mPerLevelRangeStencilReadImageViews, device); DestroyImageViews(&mPerLevelRangeSamplerExternal2DY2YEXTImageViews, device); + // Release the copy views + mLinearCopyImageView.destroy(device); + mSRGBCopyImageView.destroy(device); + // Release the draw views DestroyLayerLevelImageViews(&mLayerLevelDrawImageViews, device); DestroyLayerLevelImageViews(&mLayerLevelDrawImageViewsLinear, device); @@ -12542,7 +12150,8 @@ angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk, uint32_t baseLayer, uint32_t layerCount, bool requiresSRGBViews, - VkImageUsageFlags imageUsageFlags) + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) { ASSERT(levelCount > 0); @@ -12558,8 +12167,6 @@ angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk, mPerLevelRangeLinearReadImageViews.resize(maxViewCount); mPerLevelRangeSRGBReadImageViews.resize(maxViewCount); - mPerLevelRangeLinearCopyImageViews.resize(maxViewCount); - mPerLevelRangeSRGBCopyImageViews.resize(maxViewCount); mPerLevelRangeStencilReadImageViews.resize(maxViewCount); mPerLevelRangeSamplerExternal2DY2YEXTImageViews.resize(maxViewCount); } @@ -12576,13 +12183,14 @@ angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk, // Initialize image views for both linear and srgb colorspaces ANGLE_TRY(initLinearAndSrgbReadViewsImpl(contextVk, viewType, image, formatSwizzle, readSwizzle, baseLevel, levelCount, baseLayer, - layerCount, imageUsageFlags)); + layerCount, imageUsageFlags, astcDecodePrecision)); } else { // Initialize image view for image's format's colorspace ANGLE_TRY(initReadViewsImpl(contextVk, viewType, image, formatSwizzle, readSwizzle, - baseLevel, levelCount, baseLayer, layerCount, imageUsageFlags)); + baseLevel, levelCount, baseLayer, layerCount, imageUsageFlags, + astcDecodePrecision)); } return angle::Result::Continue; @@ -12597,7 +12205,8 @@ angle::Result ImageViewHelper::initReadViewsImpl(ContextVk *contextVk, uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount, - VkImageUsageFlags imageUsageFlags) + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) { ASSERT(mImageViewSerial.valid()); ASSERT(mReadColorspace != ImageViewColorspace::Invalid); @@ -12608,24 +12217,24 @@ angle::Result ImageViewHelper::initReadViewsImpl(ContextVk *contextVk, { ANGLE_TRY(image.initLayerImageViewWithUsage( contextVk, viewType, VK_IMAGE_ASPECT_DEPTH_BIT, readSwizzle, &getReadImageView(), - baseLevel, levelCount, baseLayer, layerCount, imageUsageFlags)); + baseLevel, levelCount, baseLayer, layerCount, imageUsageFlags, astcDecodePrecision)); ANGLE_TRY(image.initLayerImageViewWithUsage( contextVk, viewType, VK_IMAGE_ASPECT_STENCIL_BIT, readSwizzle, &mPerLevelRangeStencilReadImageViews[mCurrentBaseMaxLevelHash], baseLevel, levelCount, - baseLayer, layerCount, imageUsageFlags)); + baseLayer, layerCount, imageUsageFlags, astcDecodePrecision)); } else { - ANGLE_TRY(image.initLayerImageViewWithUsage(contextVk, viewType, aspectFlags, readSwizzle, - &getReadImageView(), baseLevel, levelCount, - baseLayer, layerCount, imageUsageFlags)); + ANGLE_TRY(image.initLayerImageViewWithUsage( + contextVk, viewType, aspectFlags, readSwizzle, &getReadImageView(), baseLevel, + levelCount, baseLayer, layerCount, imageUsageFlags, astcDecodePrecision)); - if (image.getActualFormat().isYUV) + if (image.hasImmutableSampler()) { ANGLE_TRY(image.initLayerImageViewWithYuvModeOverride( contextVk, viewType, aspectFlags, readSwizzle, &getSamplerExternal2DY2YEXTImageView(), baseLevel, levelCount, baseLayer, - layerCount, gl::YuvSamplingMode::Y2Y, imageUsageFlags)); + layerCount, gl::YuvSamplingMode::Y2Y, imageUsageFlags, astcDecodePrecision)); } } @@ -12636,19 +12245,11 @@ angle::Result ImageViewHelper::initReadViewsImpl(ContextVk *contextVk, fetchType = Get2DTextureType(layerCount, image.getSamples()); } - if (!image.getActualFormat().isBlock) + if (!image.getActualFormat().isBlock && !getCopyImageView().valid()) { - if (fetchType != viewType || readSwizzle != formatSwizzle || - HasBothDepthAndStencilAspects(aspectFlags)) - { - ANGLE_TRY(image.initLayerImageViewWithUsage( - contextVk, fetchType, aspectFlags, formatSwizzle, &getCopyImageViewStorage(), - baseLevel, levelCount, baseLayer, layerCount, imageUsageFlags)); - } - else - { - mIsCopyImageViewShared = true; - } + ANGLE_TRY(image.initLayerImageViewWithUsage( + contextVk, fetchType, aspectFlags, formatSwizzle, &getCopyImageView(), LevelIndex(0), + image.getLevelCount(), baseLayer, layerCount, imageUsageFlags, astcDecodePrecision)); } return angle::Result::Continue; } @@ -12662,7 +12263,8 @@ angle::Result ImageViewHelper::initLinearAndSrgbReadViewsImpl(ContextVk *context uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount, - VkImageUsageFlags imageUsageFlags) + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) { ASSERT(mReadColorspace != ImageViewColorspace::Invalid); @@ -12688,12 +12290,12 @@ angle::Result ImageViewHelper::initLinearAndSrgbReadViewsImpl(ContextVk *context ANGLE_TRY(image.initReinterpretedLayerImageView( contextVk, viewType, VK_IMAGE_ASPECT_DEPTH_BIT, readSwizzle, &mPerLevelRangeLinearReadImageViews[mCurrentBaseMaxLevelHash], baseLevel, levelCount, - baseLayer, layerCount, imageUsageFlags, linearFormat)); + baseLayer, layerCount, imageUsageFlags, linearFormat, astcDecodePrecision)); ANGLE_TRY(image.initReinterpretedLayerImageView( contextVk, viewType, VK_IMAGE_ASPECT_STENCIL_BIT, readSwizzle, &mPerLevelRangeStencilReadImageViews[mCurrentBaseMaxLevelHash], baseLevel, levelCount, - baseLayer, layerCount, imageUsageFlags, linearFormat)); + baseLayer, layerCount, imageUsageFlags, linearFormat, astcDecodePrecision)); } else { @@ -12702,7 +12304,8 @@ angle::Result ImageViewHelper::initLinearAndSrgbReadViewsImpl(ContextVk *context ANGLE_TRY(image.initReinterpretedLayerImageView( contextVk, viewType, aspectFlags, readSwizzle, &mPerLevelRangeLinearReadImageViews[mCurrentBaseMaxLevelHash], baseLevel, - levelCount, baseLayer, layerCount, imageUsageFlags, linearFormat)); + levelCount, baseLayer, layerCount, imageUsageFlags, linearFormat, + astcDecodePrecision)); } if (srgbFormat != angle::FormatID::NONE && @@ -12711,15 +12314,15 @@ angle::Result ImageViewHelper::initLinearAndSrgbReadViewsImpl(ContextVk *context ANGLE_TRY(image.initReinterpretedLayerImageView( contextVk, viewType, aspectFlags, readSwizzle, &mPerLevelRangeSRGBReadImageViews[mCurrentBaseMaxLevelHash], baseLevel, levelCount, - baseLayer, layerCount, imageUsageFlags, srgbFormat)); + baseLayer, layerCount, imageUsageFlags, srgbFormat, astcDecodePrecision)); } - if (image.getActualFormat().isYUV) + if (image.hasImmutableSampler()) { ANGLE_TRY(image.initLayerImageViewWithYuvModeOverride( contextVk, viewType, aspectFlags, readSwizzle, &getSamplerExternal2DY2YEXTImageView(), baseLevel, levelCount, baseLayer, - layerCount, gl::YuvSamplingMode::Y2Y, imageUsageFlags)); + layerCount, gl::YuvSamplingMode::Y2Y, imageUsageFlags, astcDecodePrecision)); } } @@ -12733,35 +12336,26 @@ angle::Result ImageViewHelper::initLinearAndSrgbReadViewsImpl(ContextVk *context if (!image.getActualFormat().isBlock) { - if (fetchType != viewType || formatSwizzle != readSwizzle || - HasBothDepthAndStencilAspects(aspectFlags)) + if (!mLinearCopyImageView.valid()) { - if (!mPerLevelRangeLinearCopyImageViews[mCurrentBaseMaxLevelHash].valid()) - { - ANGLE_TRY(image.initReinterpretedLayerImageView( - contextVk, fetchType, aspectFlags, formatSwizzle, - &mPerLevelRangeLinearCopyImageViews[mCurrentBaseMaxLevelHash], baseLevel, - levelCount, baseLayer, layerCount, imageUsageFlags, linearFormat)); - } - if (srgbFormat != angle::FormatID::NONE && - !mPerLevelRangeSRGBCopyImageViews[mCurrentBaseMaxLevelHash].valid()) - { - ANGLE_TRY(image.initReinterpretedLayerImageView( - contextVk, fetchType, aspectFlags, formatSwizzle, - &mPerLevelRangeSRGBCopyImageViews[mCurrentBaseMaxLevelHash], baseLevel, - levelCount, baseLayer, layerCount, imageUsageFlags, srgbFormat)); - } + ANGLE_TRY(image.initReinterpretedLayerImageView( + contextVk, fetchType, aspectFlags, formatSwizzle, &mLinearCopyImageView, + LevelIndex(0), image.getLevelCount(), baseLayer, layerCount, imageUsageFlags, + linearFormat, astcDecodePrecision)); } - else + if (srgbFormat != angle::FormatID::NONE && !mSRGBCopyImageView.valid()) { - mIsCopyImageViewShared = true; + ANGLE_TRY(image.initReinterpretedLayerImageView( + contextVk, fetchType, aspectFlags, formatSwizzle, &mSRGBCopyImageView, + LevelIndex(0), image.getLevelCount(), baseLayer, layerCount, imageUsageFlags, + srgbFormat, astcDecodePrecision)); } } return angle::Result::Continue; } -angle::Result ImageViewHelper::getLevelStorageImageView(ErrorContext *context, +angle::Result ImageViewHelper::getLevelStorageImageView(ContextVk *contextVk, gl::TextureType viewType, const ImageHelper &image, LevelIndex levelVk, @@ -12782,12 +12376,12 @@ angle::Result ImageViewHelper::getLevelStorageImageView(ErrorContext *context, } // Create the view. Note that storage images are not affected by swizzle parameters. - return image.initReinterpretedLayerImageView(context, viewType, image.getAspectFlags(), - gl::SwizzleState(), imageView, levelVk, 1, layer, - image.getLayerCount(), imageUsageFlags, formatID); + return image.initReinterpretedLayerImageView( + contextVk, viewType, image.getAspectFlags(), gl::SwizzleState(), imageView, levelVk, 1, + layer, image.getLayerCount(), imageUsageFlags, formatID, GL_NONE); } -angle::Result ImageViewHelper::getLevelLayerStorageImageView(ErrorContext *contextVk, +angle::Result ImageViewHelper::getLevelLayerStorageImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12813,10 +12407,10 @@ angle::Result ImageViewHelper::getLevelLayerStorageImageView(ErrorContext *conte gl::TextureType viewType = Get2DTextureType(1, image.getSamples()); return image.initReinterpretedLayerImageView(contextVk, viewType, image.getAspectFlags(), gl::SwizzleState(), imageView, levelVk, 1, layer, - 1, imageUsageFlags, formatID); + 1, imageUsageFlags, formatID, GL_NONE); } -angle::Result ImageViewHelper::getLevelLayerDrawImageViewImpl(ErrorContext *context, +angle::Result ImageViewHelper::getLevelLayerDrawImageViewImpl(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12843,12 +12437,12 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageViewImpl(ErrorContext *cont // Note that these views are specifically made to be used as framebuffer attachments, and // therefore don't have swizzle. return image.initReinterpretedLayerImageView( - context, Get2DTextureType(layerCount, image.getSamples()), image.getAspectFlags(), + contextVk, Get2DTextureType(layerCount, image.getSamples()), image.getAspectFlags(), gl::SwizzleState(), imageViewOut, levelVk, 1, layer, layerCount, - vk::ImageHelper::kDefaultImageViewUsageFlags, actualFormat); + vk::ImageHelper::kDefaultImageViewUsageFlags, actualFormat, GL_NONE); } -angle::Result ImageViewHelper::getLevelDrawImageView(ErrorContext *context, +angle::Result ImageViewHelper::getLevelDrawImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12879,10 +12473,10 @@ angle::Result ImageViewHelper::getLevelDrawImageView(ErrorContext *context, view = std::make_unique(); *imageViewOut = view.get(); - return getLevelLayerDrawImageViewImpl(context, image, levelVk, layer, layerCount, view.get()); + return getLevelLayerDrawImageViewImpl(contextVk, image, levelVk, layer, layerCount, view.get()); } -angle::Result ImageViewHelper::getLevelLayerDrawImageView(ErrorContext *context, +angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12912,10 +12506,10 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ErrorContext *context, return angle::Result::Continue; } - return getLevelLayerDrawImageViewImpl(context, image, levelVk, layer, 1, imageView); + return getLevelLayerDrawImageViewImpl(contextVk, image, levelVk, layer, 1, imageView); } -angle::Result ImageViewHelper::getLevelDepthOrStencilImageView(ErrorContext *context, +angle::Result ImageViewHelper::getLevelDepthOrStencilImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12945,11 +12539,11 @@ angle::Result ImageViewHelper::getLevelDepthOrStencilImageView(ErrorContext *con view = std::make_unique(); *imageViewOut = view.get(); - return getLevelLayerDepthOrStencilImageViewImpl(context, image, levelVk, layer, layerCount, + return getLevelLayerDepthOrStencilImageViewImpl(contextVk, image, levelVk, layer, layerCount, aspect, view.get()); } -angle::Result ImageViewHelper::getLevelLayerDepthOrStencilImageView(ErrorContext *context, +angle::Result ImageViewHelper::getLevelLayerDepthOrStencilImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12974,12 +12568,12 @@ angle::Result ImageViewHelper::getLevelLayerDepthOrStencilImageView(ErrorContext return angle::Result::Continue; } - return getLevelLayerDepthOrStencilImageViewImpl(context, image, levelVk, layer, 1, aspect, + return getLevelLayerDepthOrStencilImageViewImpl(contextVk, image, levelVk, layer, 1, aspect, imageView); } angle::Result ImageViewHelper::getLevelLayerDepthOrStencilImageViewImpl( - ErrorContext *context, + ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -12990,9 +12584,9 @@ angle::Result ImageViewHelper::getLevelLayerDepthOrStencilImageViewImpl( // Note that these views are specifically made to be used as input attachments, and // therefore don't have swizzle. return image.initReinterpretedLayerImageView( - context, Get2DTextureType(layerCount, image.getSamples()), aspect, gl::SwizzleState(), + contextVk, Get2DTextureType(layerCount, image.getSamples()), aspect, gl::SwizzleState(), imageViewOut, levelVk, 1, layer, layerCount, vk::ImageHelper::kDefaultImageViewUsageFlags, - image.getActualFormatID()); + image.getActualFormatID(), GL_NONE); } angle::Result ImageViewHelper::initFragmentShadingRateView(ContextVk *contextVk, ImageHelper *image) @@ -13016,21 +12610,22 @@ angle::Result ImageViewHelper::initFragmentShadingRateView(ContextVk *contextVk, // - layerCount == 1 return image->initLayerImageViewWithUsage( contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), - &mFragmentShadingRateImageView, vk::LevelIndex(0), 1, 0, 1, image->getUsage()); + &mFragmentShadingRateImageView, vk::LevelIndex(0), 1, 0, 1, image->getUsage(), GL_NONE); } -angle::FormatID ImageViewHelper::getColorspaceOverrideFormatForWrite(angle::FormatID format) const +angle::FormatID ImageViewHelper::getColorspaceOverrideFormatImpl(ImageViewColorspace colorspace, + angle::FormatID format) const { - ASSERT(mWriteColorspace != ImageViewColorspace::Invalid); + ASSERT(colorspace != ImageViewColorspace::Invalid); angle::FormatID colorspaceOverrideFormat = format; angle::FormatID linearFormat = ConvertToLinear(format); angle::FormatID sRGBFormat = ConvertToSRGB(format); - if (mWriteColorspace == ImageViewColorspace::Linear && linearFormat != angle::FormatID::NONE) + if (colorspace == ImageViewColorspace::Linear && linearFormat != angle::FormatID::NONE) { colorspaceOverrideFormat = linearFormat; } - else if (mWriteColorspace == ImageViewColorspace::SRGB && sRGBFormat != angle::FormatID::NONE) + else if (colorspace == ImageViewColorspace::SRGB && sRGBFormat != angle::FormatID::NONE) { colorspaceOverrideFormat = sRGBFormat; } @@ -13220,12 +12815,17 @@ angle::Result BufferViewHelper::getView(ErrorContext *context, const BufferHelper &buffer, VkDeviceSize bufferOffset, const Format &format, - const BufferView **viewOut) + const BufferView **viewOut, + VkFormat *viewVkFormatOut) { ASSERT(format.valid()); vk::Renderer *renderer = context->getRenderer(); - VkFormat viewVkFormat = format.getActualBufferVkFormat(renderer, false); + VkFormat viewVkFormat = format.getActualBufferVkFormat(renderer); + if (viewVkFormatOut != nullptr) + { + *viewVkFormatOut = viewVkFormat; + } auto iter = mViews.find(viewVkFormat); if (iter != mViews.end()) @@ -13237,7 +12837,7 @@ angle::Result BufferViewHelper::getView(ErrorContext *context, // If the size is not a multiple of pixelBytes, remove the extra bytes. The last element cannot // be read anyway, and this is a requirement of Vulkan (for size to be a multiple of format // texel block size). - const angle::Format &bufferFormat = format.getActualBufferFormat(false); + const angle::Format &bufferFormat = format.getActualBufferFormat(); const GLuint pixelBytes = bufferFormat.pixelBytes; VkDeviceSize size = mSize - mSize % pixelBytes; @@ -13248,6 +12848,31 @@ angle::Result BufferViewHelper::getView(ErrorContext *context, viewCreateInfo.offset = mOffset + bufferOffset; viewCreateInfo.range = size; + VkBufferUsageFlags2CreateInfoKHR usageFlagsCreateInfo = {}; + if (renderer->getFeatures().supportsMaintenance5.enabled) + { + // The usage for bufferview should only contain the uniform texel and storage texel bits. + usageFlagsCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR; + constexpr VkFormatFeatureFlags kViewUsageFormatFeatureMask = + VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT; + VkBufferUsageFlags2KHR viewUsage = 0; + + VkFormatFeatureFlags bufferFormatFeatureBits = + renderer->getBufferFormatFeatureBits(bufferFormat.id, kViewUsageFormatFeatureMask); + if ((bufferFormatFeatureBits & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) != 0) + { + viewUsage |= VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR; + } + if ((bufferFormatFeatureBits & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) != 0) + { + viewUsage |= VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR; + } + + ASSERT(viewUsage != 0); + usageFlagsCreateInfo.usage = viewUsage; + AddToPNextChain(&viewCreateInfo, &usageFlagsCreateInfo); + } + BufferView view; ANGLE_VK_TRY(context, view.init(context->getDevice(), viewCreateInfo)); @@ -13337,71 +12962,72 @@ ActiveHandleCounter::ActiveHandleCounter() : mActiveCounts{}, mAllocatedCounts{} ActiveHandleCounter::~ActiveHandleCounter() = default; -// CommandBufferAccess implementation. -CommandBufferAccess::CommandBufferAccess() = default; -CommandBufferAccess::~CommandBufferAccess() = default; +// CommandResources implementation. +CommandResources::CommandResources() = default; +CommandResources::~CommandResources() = default; -void CommandBufferAccess::onBufferRead(VkAccessFlags readAccessType, - PipelineStage readStage, - BufferHelper *buffer) +void CommandResources::onBufferRead(VkAccessFlags readAccessType, + PipelineStage readStage, + BufferHelper *buffer) { ASSERT(!buffer->isReleasedToExternal()); mReadBuffers.emplace_back(buffer, readAccessType, readStage); } -void CommandBufferAccess::onBufferWrite(VkAccessFlags writeAccessType, - PipelineStage writeStage, - BufferHelper *buffer) +void CommandResources::onBufferWrite(VkAccessFlags writeAccessType, + PipelineStage writeStage, + BufferHelper *buffer) { ASSERT(!buffer->isReleasedToExternal()); mWriteBuffers.emplace_back(buffer, writeAccessType, writeStage); } -void CommandBufferAccess::onImageRead(VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, - ImageHelper *image) +void CommandResources::onImageRead(VkImageAspectFlags aspectFlags, + ImageAccess imageAccess, + ImageHelper *image) { ASSERT(!image->isReleasedToExternal()); ASSERT(image->getImageSerial().valid()); - mReadImages.emplace_back(image, aspectFlags, imageLayout); + mReadImages.emplace_back(image, aspectFlags, imageAccess); } -void CommandBufferAccess::onImageWrite(gl::LevelIndex levelStart, - uint32_t levelCount, - uint32_t layerStart, - uint32_t layerCount, - VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, - ImageHelper *image) +void CommandResources::onImageWrite(gl::LevelIndex levelStart, + uint32_t levelCount, + uint32_t layerStart, + uint32_t layerCount, + VkImageAspectFlags aspectFlags, + ImageAccess imageAccess, + ImageHelper *image) { ASSERT(!image->isReleasedToExternal()); ASSERT(image->getImageSerial().valid()); - mWriteImages.emplace_back(CommandBufferImageAccess{image, aspectFlags, imageLayout}, levelStart, + mWriteImages.emplace_back(CommandResourceImage{image, aspectFlags, imageAccess}, levelStart, levelCount, layerStart, layerCount); } -void CommandBufferAccess::onImageReadSubresources(gl::LevelIndex levelStart, - uint32_t levelCount, - uint32_t layerStart, - uint32_t layerCount, - VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, - ImageHelper *image) +void CommandResources::onImageReadSubresources(gl::LevelIndex levelStart, + uint32_t levelCount, + uint32_t layerStart, + uint32_t layerCount, + VkImageAspectFlags aspectFlags, + ImageAccess imageAccess, + ImageHelper *image) { ASSERT(!image->isReleasedToExternal()); ASSERT(image->getImageSerial().valid()); - mReadImageSubresources.emplace_back(CommandBufferImageAccess{image, aspectFlags, imageLayout}, + mReadImageSubresources.emplace_back(CommandResourceImage{image, aspectFlags, imageAccess}, levelStart, levelCount, layerStart, layerCount); } -void CommandBufferAccess::onBufferExternalAcquireRelease(BufferHelper *buffer) +void CommandResources::onBufferExternalAcquireRelease(BufferHelper *buffer) { - mExternalAcquireReleaseBuffers.emplace_back(CommandBufferBufferExternalAcquireRelease{buffer}); + mExternalAcquireReleaseBuffers.emplace_back( + CommandResourceBufferExternalAcquireRelease{buffer}); } -void CommandBufferAccess::onResourceAccess(Resource *resource) +void CommandResources::onResourceAccess(Resource *resource) { - mAccessResources.emplace_back(CommandBufferResourceAccess{resource}); + mGenericResources.emplace_back(CommandResourceGeneric{resource}); } // DescriptorMetaCache implementation. diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h index e8eebad7ef5..af5edd79f83 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.h +++ b/src/libANGLE/renderer/vulkan/vk_helpers.h @@ -9,10 +9,15 @@ #ifndef LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_ #define LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "common/MemoryBuffer.h" #include "common/SimpleMutex.h" #include "libANGLE/renderer/vulkan/MemoryTracking.h" #include "libANGLE/renderer/vulkan/Suballocation.h" +#include "libANGLE/renderer/vulkan/vk_barrier_data.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "libANGLE/renderer/vulkan/vk_ref_counted_event.h" @@ -63,122 +68,10 @@ using ImageLayerWriteMask = std::bitset; -// Imagine an image going through a few layout transitions: -// -// srcStage 1 dstStage 2 srcStage 2 dstStage 3 -// Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3 -// srcAccess 1 dstAccess 2 srcAccess 2 dstAccess 3 -// \_________________ ___________________/ -// \/ -// A transition -// -// Every transition requires 6 pieces of information: from/to layouts, src/dst stage masks and -// src/dst access masks. At the moment we decide to transition the image to Layout 2 (i.e. -// Transition 1), we need to have Layout 1, srcStage 1 and srcAccess 1 stored as history of the -// image. To perform the transition, we need to know Layout 2, dstStage 2 and dstAccess 2. -// Additionally, we need to know srcStage 2 and srcAccess 2 to retain them for the next transition. -// -// That is, with the history kept, on every new transition we need 5 pieces of new information: -// layout/dstStage/dstAccess to transition into the layout, and srcStage/srcAccess for the future -// transition out from it. Given the small number of possible combinations of these values, an -// enum is used were each value encapsulates these 5 pieces of information: -// -// +--------------------------------+ -// srcStage 1 | dstStage 2 srcStage 2 | dstStage 3 -// Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3 -// srcAccess 1 |dstAccess 2 srcAccess 2| dstAccess 3 -// +--------------- ---------------+ -// \/ -// One enum value -// -// Note that, while generally dstStage for the to-transition and srcStage for the from-transition -// are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively. -enum class ImageLayout -{ - Undefined = 0, - // Framebuffer attachment layouts are placed first, so they can fit in fewer bits in - // PackedAttachmentOpsDesc. - - // Color (Write): - ColorWrite, - // Used only with dynamic rendering, because it needs a different VkImageLayout - ColorWriteAndInput, - MSRTTEmulationColorUnresolveAndResolve, - - // Depth (Write), Stencil (Write) - DepthWriteStencilWrite, - // Used only with dynamic rendering, because it needs a different VkImageLayout. For - // simplicity, depth/stencil attachments when used as input attachments don't attempt to - // distinguish read-only aspects. That's only useful for supporting feedback loops, but if an - // application is reading depth or stencil through an input attachment, it's safe to assume they - // wouldn't be accessing the other aspect through a sampler! - DepthStencilWriteAndInput, - - // Depth (Write), Stencil (Read) - DepthWriteStencilRead, - DepthWriteStencilReadFragmentShaderStencilRead, - DepthWriteStencilReadAllShadersStencilRead, - - // Depth (Read), Stencil (Write) - DepthReadStencilWrite, - DepthReadStencilWriteFragmentShaderDepthRead, - DepthReadStencilWriteAllShadersDepthRead, - - // Depth (Read), Stencil (Read) - DepthReadStencilRead, - DepthReadStencilReadFragmentShaderRead, - DepthReadStencilReadAllShadersRead, - - // The GENERAL layout is used when there's a feedback loop. For depth/stencil it doesn't matter - // which aspect is participating in feedback and whether the other aspect is read-only. - ColorWriteFragmentShaderFeedback, - ColorWriteAllShadersFeedback, - DepthStencilFragmentShaderFeedback, - DepthStencilAllShadersFeedback, - - // Depth/stencil resolve is special because it uses the _color_ output stage and mask - DepthStencilResolve, - MSRTTEmulationDepthStencilUnresolveAndResolve, - - Present, - SharedPresent, - // The rest of the layouts. - ExternalPreInitialized, - ExternalShadersReadOnly, - ExternalShadersWrite, - ForeignAccess, - TransferSrc, - TransferDst, - TransferSrcDst, - // Used when the image is transitioned on the host for use by host image copy - HostCopy, - VertexShaderReadOnly, - VertexShaderWrite, - // PreFragment == Vertex, Tessellation and Geometry stages - PreFragmentShadersReadOnly, - PreFragmentShadersWrite, - FragmentShadingRateAttachmentReadOnly, - FragmentShaderReadOnly, - FragmentShaderWrite, - ComputeShaderReadOnly, - ComputeShaderWrite, - AllGraphicsShadersReadOnly, - AllGraphicsShadersWrite, - TransferDstAndComputeWrite, - - InvalidEnum, - EnumCount = InvalidEnum, -}; - VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType); -ImageLayout GetImageLayoutFromGLImageLayout(ErrorContext *context, GLenum layout); - -GLenum ConvertImageLayoutToGLImageLayout(ImageLayout imageLayout); - -VkImageLayout ConvertImageLayoutToVkImageLayout(Renderer *renderer, ImageLayout imageLayout); - class ImageHelper; +class CommandsState; // Abstracts contexts where command recording is done in response to API calls, and includes // data structures that are Vulkan-related, need to be accessed by the internals of |namespace vk| @@ -199,6 +92,11 @@ class Context : public ErrorContext void finalizeAllForeignImages(); protected: + bool hasForeignImagesToTransition() const + { + return !mForeignImagesInUse.empty() || !mImagesToTransitionToForeign.empty(); + } + // Stash the ShareGroupVk's RefCountedEventRecycler here ImageHelper to conveniently access RefCountedEventsGarbageRecycler *mShareGroupRefCountedEventsGarbageRecycler; // List of foreign images that are currently used in recorded commands but haven't been @@ -480,6 +378,8 @@ class DynamicDescriptorPool final : angle::NonCopyable void destroyUnusedPool(Renderer *renderer, const DescriptorPoolWeakPointer &pool); void checkAndDestroyUnusedPool(Renderer *renderer); + // For ASSERT use only. Return true if mDescriptorSetCache contains DescriptorSet for desc. + bool hasCachedDescriptorSet(const DescriptorSetDesc &desc) const; // For testing only! static uint32_t GetMaxSetsPerPoolForTesting(); static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool); @@ -822,78 +722,6 @@ class SemaphoreHelper final : angle::NonCopyable const Semaphore *mSemaphore; }; -// This defines enum for VkPipelineStageFlagBits so that we can use it to compare and index into -// array. -enum class PipelineStage : uint32_t -{ - // Bellow are ordered based on Graphics Pipeline Stages - TopOfPipe = 0, - DrawIndirect = 1, - VertexInput = 2, - VertexShader = 3, - TessellationControl = 4, - TessellationEvaluation = 5, - GeometryShader = 6, - TransformFeedback = 7, - FragmentShadingRate = 8, - EarlyFragmentTest = 9, - FragmentShader = 10, - LateFragmentTest = 11, - ColorAttachmentOutput = 12, - - // Compute specific pipeline Stage - ComputeShader = 13, - - // Transfer specific pipeline Stage - Transfer = 14, - BottomOfPipe = 15, - - // Host specific pipeline stage - Host = 16, - - InvalidEnum = 17, - EnumCount = InvalidEnum, -}; -using PipelineStagesMask = angle::PackedEnumBitSet; - -PipelineStage GetPipelineStage(gl::ShaderType stage); - -struct ImageMemoryBarrierData -{ - const char *name; - - // The Vk layout corresponding to the ImageLayout key. - VkImageLayout layout; - - // The stage in which the image is used (or Bottom/Top if not using any specific stage). Unless - // Bottom/Top (Bottom used for transition to and Top used for transition from), the two values - // should match. - VkPipelineStageFlags dstStageMask; - VkPipelineStageFlags srcStageMask; - // Access mask when transitioning into this layout. - VkAccessFlags dstAccessMask; - // Access mask when transitioning out from this layout. Note that source access mask never - // needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers). - VkAccessFlags srcAccessMask; - // Read or write. - ResourceAccess type; - // *CommandBufferHelper track an array of PipelineBarriers. This indicates which array element - // this should be merged into. Right now we track individual barrier for every PipelineStage. If - // layout has a single stage mask bit, we use that stage as index. If layout has multiple stage - // mask bits, we pick the lowest stage as the index since it is the first stage that needs - // barrier. - PipelineStage barrierIndex; - EventStage eventStage; - // The pipeline stage flags group that used for heuristic. - PipelineStageGroup pipelineStageGroup; -}; -using ImageLayoutToMemoryBarrierDataMap = angle::PackedEnumMap; - -// Initialize ImageLayout to ImageMemoryBarrierData mapping table. -void InitializeImageLayoutAndMemoryBarrierDataMap( - ImageLayoutToMemoryBarrierDataMap *mapping, - VkPipelineStageFlags supportedVulkanPipelineStageMask); - // This wraps data and API for vkCmdPipelineBarrier call class PipelineBarrier : angle::NonCopyable { @@ -1049,6 +877,16 @@ class BufferHelper : public ReadWriteResource VkMemoryPropertyFlags memoryProperties, const VkBufferCreateInfo &requestedCreateInfo, GLeglClientBufferEXT clientBuffer); + angle::Result initAndAcquireFromExternalMemory( + Context *context, + VkMemoryPropertyFlags memoryProperties, + const VkBufferCreateInfo &requestedCreateInfo, + const VkExternalMemoryHandleTypeFlagBits externalMemoryHandleType, + const int32_t sharedBufferFD); + angle::Result initHostExternal(ErrorContext *context, + VkMemoryPropertyFlags memoryProperties, + const VkBufferCreateInfo &requestedCreateInfo, + void *hostPtr); VkResult initSuballocation(Context *context, uint32_t memoryTypeIndex, size_t size, @@ -1059,7 +897,7 @@ class BufferHelper : public ReadWriteResource void destroy(Renderer *renderer); void release(Renderer *renderer); void release(Context *context); - void releaseBufferAndDescriptorSetCache(Context *context); + void releaseBufferAndDescriptorSetCache(ContextVk *contextVk); BufferSerial getBufferSerial() const { return mSerial; } BufferSerial getBlockSerial() const @@ -1084,6 +922,7 @@ class BufferHelper : public ReadWriteResource // Returns the main buffer block's pointer. uint8_t *getBlockMemory() const { return mSuballocation.getBlockMemory(); } VkDeviceSize getBlockMemorySize() const { return mSuballocation.getBlockMemorySize(); } + VkDeviceMemory getDeviceMemory() const { return mSuballocation.getDeviceMemory().getHandle(); } bool isHostVisible() const { return mSuballocation.isHostVisible(); } bool isCoherent() const { return mSuballocation.isCoherent(); } bool isCached() const { return mSuballocation.isCached(); } @@ -1152,12 +991,17 @@ class BufferHelper : public ReadWriteResource void fillWithPattern(const void *pattern, size_t patternSize, size_t offset, size_t size); + VkDeviceAddress getDeviceAddress(Context *context); + // Special handling for VertexArray code so that we can create a dedicated VkBuffer for the // sub-range of memory of the actual buffer data size that user requested (i.e, excluding extra // paddings that we added for alignment, which will not get zero filled). const Buffer &getBufferForVertexArray(ContextVk *contextVk, VkDeviceSize actualDataSize, VkDeviceSize *offsetOut); + const Buffer &getIndexBufferForVertexArray(ContextVk *contextVk, + VkDeviceSize actualDataSize, + VkDeviceSize *offsetOut); void onNewDescriptorSet(const SharedDescriptorSetCacheKey &sharedCacheKey) { @@ -1177,8 +1021,10 @@ class BufferHelper : public ReadWriteResource void initializeBarrierTracker(ErrorContext *context); - // Returns the current VkAccessFlags bits - VkAccessFlags getCurrentWriteAccess() const { return mCurrentWriteAccess; } + bool isLastAccessShaderWriteOnly() const + { + return mCurrentReadAccess == 0 && (mCurrentWriteAccess & VK_ACCESS_SHADER_WRITE_BIT) != 0; + } private: // Only called by DynamicBuffer. @@ -1190,15 +1036,29 @@ class BufferHelper : public ReadWriteResource void releaseImpl(Renderer *renderer); - void updatePipelineStageWriteHistory(PipelineStage writeStage) + void updatePipelineStageWriteHistory(Context *context, PipelineStage writeStage) { - mTransformFeedbackWriteHeuristicBits <<= 1; + mXFBOrComputeWriteHeuristicBits <<= 1; + if (writeStage == PipelineStage::TransformFeedback) { - mTransformFeedbackWriteHeuristicBits |= 1; + mXFBOrComputeWriteHeuristicBits |= 1; + } + else if ((writeStage == PipelineStage::ComputeShader) && + (mCurrentReadStages & VK_PIPELINE_STAGE_VERTEX_INPUT_BIT) != 0 && + context->getFeatures().isVertexSyncDeferred.enabled) + { + // When a buffer is written in compute after read in vertex stage, using vkEvent + // for synchronization is generally more performance-friendly than a pipeline barrier, + // especially on deferred rendering GPUs. + mXFBOrComputeWriteHeuristicBits |= 1; } } + const Buffer &getBufferForVertexArrayImpl(ContextVk *contextVk, + VkDeviceSize actualDataSize, + VkDeviceSize *offsetOut); + // Suballocation object. BufferSuballocation mSuballocation; // This normally is invalid. We always use the BufferBlock's buffer and offset combination. But @@ -1222,9 +1082,8 @@ class BufferHelper : public ReadWriteResource // Track history of pipeline stages being used. This information provides // heuristic for making decisions if a VkEvent should be used to track the operation. - static constexpr uint32_t kTransformFeedbackWriteHeuristicWindowSize = 16; - angle::BitSet16 - mTransformFeedbackWriteHeuristicBits; + static constexpr uint32_t kXFBOrComputeWriteHeuristicWindowSize = 16; + angle::BitSet16 mXFBOrComputeWriteHeuristicBits; BufferSerial mSerial; // Manages the descriptorSet cache that created with this BufferHelper object. @@ -1247,7 +1106,6 @@ class BufferPool : angle::NonCopyable void initWithFlags(Renderer *renderer, vma::VirtualBlockCreateFlags flags, VkBufferUsageFlags usage, - VkDeviceSize initialSize, uint32_t memoryTypeIndex, VkMemoryPropertyFlags memoryProperty); @@ -1258,7 +1116,7 @@ class BufferPool : angle::NonCopyable // Frees resources immediately, or orphan the non-empty BufferBlocks if allowed. If orphan is // not allowed, it will assert if BufferBlock is still not empty. - void destroy(Renderer *renderer, bool orphanAllowed); + void destroy(Renderer *renderer, bool orphanNonEmptyBufferBlock); // Remove and destroy empty BufferBlocks void pruneEmptyBuffers(Renderer *renderer); @@ -1275,17 +1133,24 @@ class BufferPool : angle::NonCopyable vma::VirtualBlockCreateFlags mVirtualBlockCreateFlags; VkBufferUsageFlags mUsage; bool mHostVisible; + // Size used to create the last allocated buffer block from the pool to suballocate from. VkDeviceSize mSize; + // Size used to allocate a new buffer block from an empty pool. + VkDeviceSize mInitialSize; + // Size used to allocate a new buffer block from a non-empty pool. + VkDeviceSize mPreferredSize; + // Intended memory type index used for the buffer allocation. uint32_t mMemoryTypeIndex; + // Total allocated buffer block size from the pool. VkDeviceSize mTotalMemorySize; BufferBlockPointerVector mBufferBlocks; - BufferBlockPointerVector mEmptyBufferBlocks; + std::deque mEmptyBufferBlocks; // Tracks the number of new buffers needed for suballocation since last pruneEmptyBuffers call. // We will use this heuristic information to decide how many empty buffers to keep around. size_t mNumberOfNewBuffersNeededSinceLastPrune; // max size to go down the suballocation code path. Any allocation greater or equal this size // will call into vulkan directly to allocate a dedicated VkDeviceMemory. - static constexpr size_t kMaxBufferSizeForSuballocation = 4 * 1024 * 1024; + static constexpr size_t kMaxBufferSizeForSuballocation = 8 * 1024 * 1024; }; using BufferPoolPointerArray = std::array, VK_MAX_MEMORY_TYPES>; @@ -1422,14 +1287,6 @@ class SecondaryCommandBufferCollector final std::vector mCollectedCommandBuffers; }; -struct CommandsState -{ - std::vector waitSemaphores; - std::vector waitSemaphoreStageMasks; - PrimaryCommandBuffer primaryCommands; - SecondaryCommandBufferCollector secondaryCommands; -}; - // How the ImageHelper object is being used by the renderpass enum class RenderPassUsage { @@ -1508,7 +1365,9 @@ class CommandBufferHelperCommon : angle::NonCopyable return hostBufferWrite; } - void executeBarriers(Renderer *renderer, CommandsState *commandsState); + void executeBarriers(Renderer *renderer, + CommandsState *commandsState, + PrimaryCommandBuffer *primaryCommands); // The markOpen and markClosed functions are to aid in proper use of the *CommandBufferHelper. // saw invalid use due to threading issues that can be easily caught by marking when it's safe @@ -1570,11 +1429,6 @@ class CommandBufferHelperCommon : angle::NonCopyable template void releaseCommandPoolImpl(); - template - void attachAllocatorImpl(SecondaryCommandMemoryAllocator *allocator); - template - SecondaryCommandMemoryAllocator *detachAllocatorImpl(); - template void assertCanBeRecycledImpl(); @@ -1592,7 +1446,7 @@ class CommandBufferHelperCommon : angle::NonCopyable void imageReadImpl(Context *context, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, BarrierType barrierType, ImageHelper *image); @@ -1601,14 +1455,14 @@ class CommandBufferHelperCommon : angle::NonCopyable uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, BarrierType barrierType, ImageHelper *image); void updateImageLayoutAndBarrier(Context *context, ImageHelper *image, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, BarrierType barrierType); void addCommandDiagnosticsCommon(std::ostringstream *out); @@ -1674,9 +1528,6 @@ class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCom angle::Result detachCommandPool(ErrorContext *context, SecondaryCommandPool **commandPoolOut); void releaseCommandPool(); - void attachAllocator(SecondaryCommandMemoryAllocator *allocator); - SecondaryCommandMemoryAllocator *detachAllocator(); - void assertCanBeRecycled(); #if defined(ANGLE_ENABLE_ASSERTS) @@ -1686,7 +1537,7 @@ class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCom void imageRead(Context *context, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image); void imageWrite(Context *context, @@ -1694,11 +1545,11 @@ class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCom uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image); // Update image with this command buffer's queueSerial. - void retainImage(ImageHelper *image); + void retainImage(Renderer *renderer, ImageHelper *image); // Call SetEvent and have image's current event pointing to it. void trackImageWithEvent(Context *context, ImageHelper *image); @@ -1711,7 +1562,9 @@ class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCom RefCountedEventCollector *getRefCountedEventCollector() { return &mRefCountedEventCollector; } - angle::Result flushToPrimary(Context *context, CommandsState *commandsState); + angle::Result flushToPrimary(Context *context, + CommandsState *commandsState, + PrimaryCommandBuffer *primaryCommands); void setGLMemoryBarrierIssued() { @@ -1910,9 +1763,6 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon void detachCommandPool(SecondaryCommandPool **commandPoolOut); void releaseCommandPool(); - void attachAllocator(SecondaryCommandMemoryAllocator *allocator); - SecondaryCommandMemoryAllocator *detachAllocator(); - void assertCanBeRecycled(); #if defined(ANGLE_ENABLE_ASSERTS) @@ -1920,9 +1770,22 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon void markClosed() { getCommandBuffer().close(); } #endif + void buffersVertexAttribRead(Context *context, + const gl::AttribArray &buffers, + uint32_t maxAttrib) + { + for (uint32_t attribIndex = 0; attribIndex < maxAttrib; ++attribIndex) + { + vk::BufferHelper *arrayBuffer = buffers[attribIndex]; + ASSERT(arrayBuffer != nullptr); + bufferRead(context, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, PipelineStage::VertexInput, + arrayBuffer); + } + } + void imageRead(ContextVk *contextVk, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image); void imageWrite(ContextVk *contextVk, @@ -1930,7 +1793,7 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image); void colorImagesDraw(gl::LevelIndex level, @@ -1953,6 +1816,7 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon angle::Result flushToPrimary(Context *context, CommandsState *commandsState, + PrimaryCommandBuffer *primaryCommands, const RenderPass &renderPass, VkFramebuffer framebufferOverride); @@ -2070,6 +1934,10 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon } void setImageOptimizeForPresent(ImageHelper *image) { mImageOptimizeForPresent = image; } + bool isImageOptimizedForPresent(const ImageHelper *image) const + { + return mImageOptimizeForPresent == image; + } void setGLMemoryBarrierIssued() { @@ -2177,7 +2045,7 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon // rendering, the barrier is recorded after the pass without needing an outside render pass // command buffer. ImageHelper *mImageOptimizeForPresent; - ImageLayout mImageOptimizeForPresentOriginalLayout; + ImageAccess mImageOptimizeForPresentOriginalLayout; // The list of VkEvents copied from RefCountedEventArray EventArray mVkEventArray; @@ -2191,14 +2059,13 @@ template class CommandBufferRecycler { public: - CommandBufferRecycler() = default; + CommandBufferRecycler() { mCommandBufferHelperFreeList.reserve(8); } ~CommandBufferRecycler() = default; void onDestroy(); angle::Result getCommandBufferHelper(ErrorContext *context, SecondaryCommandPool *commandPool, - SecondaryCommandMemoryAllocator *commandsAllocator, CommandBufferHelperT **commandBufferHelperOut); void recycleCommandBufferHelper(CommandBufferHelperT **commandBuffer); @@ -2238,6 +2105,12 @@ enum class ApplyImageUpdate Defer, }; +enum class TileMemory +{ + Preferred, + Prohibited, +}; + constexpr VkImageAspectFlagBits IMAGE_ASPECT_DEPTH_STENCIL = static_cast(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); @@ -2268,10 +2141,9 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t mipLevels, uint32_t layerCount, bool isRobustResourceInitEnabled, - bool hasProtectedContent); - angle::Result initFromCreateInfo(ErrorContext *context, - const VkImageCreateInfo &requestedCreateInfo, - VkMemoryPropertyFlags memoryPropertyFlags); + bool hasProtectedContent, + TileMemory tileMemoryPreference); + angle::Result copyToBufferOneOff(ErrorContext *context, BufferHelper *stagingBuffer, VkBufferImageCopy copyRegion); @@ -2279,7 +2151,8 @@ class ImageHelper final : public Resource, public angle::Subject gl::TextureType textureType, const VkExtent3D &extents, bool rotatedAspectRatio, - const Format &format, + angle::FormatID intendedFormatID, + angle::FormatID actualFormatID, GLint samples, VkImageUsageFlags usage, gl::LevelIndex firstLevel, @@ -2295,17 +2168,17 @@ class ImageHelper final : public Resource, public angle::Subject GLint samples, VkImageUsageFlags usage, VkImageCreateFlags additionalCreateFlags, - ImageLayout initialLayout, + ImageAccess initialAccess, const void *externalImageCreateInfo, gl::LevelIndex firstLevel, uint32_t mipLevels, uint32_t layerCount, bool isRobustResourceInitEnabled, bool hasProtectedContent, + TileMemory tileMemoryPreference, YcbcrConversionDesc conversionDesc, const void *compressionControl); VkResult initMemory(ErrorContext *context, - const MemoryProperties &memoryProperties, VkMemoryPropertyFlags flags, VkMemoryPropertyFlags excludedFlags, const VkMemoryRequirements *memoryRequirements, @@ -2315,7 +2188,6 @@ class ImageHelper final : public Resource, public angle::Subject VkDeviceSize *sizeOut); angle::Result initMemoryAndNonZeroFillIfNeeded(ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, VkMemoryPropertyFlags flags, MemoryAllocationType allocationType); angle::Result initExternalMemory(ErrorContext *context, @@ -2327,7 +2199,7 @@ class ImageHelper final : public Resource, public angle::Subject VkMemoryPropertyFlags flags); static constexpr VkImageUsageFlags kDefaultImageViewUsageFlags = 0; - angle::Result initLayerImageView(ErrorContext *context, + angle::Result initLayerImageView(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -2336,7 +2208,7 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t levelCount, uint32_t baseArrayLayer, uint32_t layerCount) const; - angle::Result initLayerImageViewWithUsage(ErrorContext *context, + angle::Result initLayerImageViewWithUsage(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -2345,8 +2217,9 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t levelCount, uint32_t baseArrayLayer, uint32_t layerCount, - VkImageUsageFlags imageUsageFlags) const; - angle::Result initLayerImageViewWithYuvModeOverride(ErrorContext *context, + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) const; + angle::Result initLayerImageViewWithYuvModeOverride(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -2356,8 +2229,9 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t baseArrayLayer, uint32_t layerCount, gl::YuvSamplingMode yuvSamplingMode, - VkImageUsageFlags imageUsageFlags) const; - angle::Result initReinterpretedLayerImageView(ErrorContext *context, + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision) const; + angle::Result initReinterpretedLayerImageView(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -2367,7 +2241,8 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t baseArrayLayer, uint32_t layerCount, VkImageUsageFlags imageUsageFlags, - angle::FormatID imageViewFormat) const; + angle::FormatID imageViewFormat, + GLenum astcDecodePrecision) const; // Create a 2D[Array] for staging purposes. Used by: // // - TextureVk::copySubImageImplWithDraw @@ -2375,7 +2250,6 @@ class ImageHelper final : public Resource, public angle::Subject // angle::Result init2DStaging(ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, const gl::Extents &glExtents, angle::FormatID intendedFormatID, angle::FormatID actualFormatID, @@ -2387,7 +2261,6 @@ class ImageHelper final : public Resource, public angle::Subject // angle::Result initStaging(ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, VkImageType imageType, const VkExtent3D &extents, angle::FormatID intendedFormatID, @@ -2400,12 +2273,15 @@ class ImageHelper final : public Resource, public angle::Subject // rendering. If LAZILY_ALLOCATED memory is available, it will prefer that. angle::Result initImplicitMultisampledRenderToTexture(ErrorContext *context, bool hasProtectedContent, - const MemoryProperties &memoryProperties, gl::TextureType textureType, GLint samples, const ImageHelper &resolveImage, const VkExtent3D &multisampleImageExtents, bool isRobustResourceInitEnabled); + // Create a 2d image for use as the implicit RGB draw image in YUV rendering. + angle::Result initRgbDrawImageForYuvResolve(ErrorContext *context, + const ImageHelper &resolveImage, + bool isRobustResourceInitEnabled); // Helper for initExternal and users to automatically derive the appropriate VkImageCreateInfo // pNext chain based on the given parameters, and adjust create flags. In some cases, these @@ -2428,7 +2304,7 @@ class ImageHelper final : public Resource, public angle::Subject OnlyQuerySuccess, RequireMultisampling }; - static bool FormatSupportsUsage(Renderer *renderer, + static bool FormatSupportsUsage(const Renderer *renderer, VkFormat format, VkImageType imageType, VkImageTiling tilingMode, @@ -2445,7 +2321,7 @@ class ImageHelper final : public Resource, public angle::Subject // Helper for initExternal and users to extract the view formats of the image from the pNext // chain in VkImageCreateInfo. - void deriveImageViewFormatFromCreateInfoPNext(VkImageCreateInfo &imageInfo, + void deriveImageViewFormatFromCreateInfoPNext(const VkImageCreateInfo &imageInfo, ImageFormats &formatOut); // Release the underlying VkImage object for garbage collection. @@ -2463,6 +2339,7 @@ class ImageHelper final : public Resource, public angle::Subject bool valid() const { return mImage.valid(); } + VkImageAspectFlags getIntendedAspectFlags() const; VkImageAspectFlags getAspectFlags() const; // True if image contains both depth & stencil aspects bool isCombinedDepthStencilFormat() const; @@ -2489,7 +2366,14 @@ class ImageHelper final : public Resource, public angle::Subject void setTilingMode(VkImageTiling tilingMode) { mTilingMode = tilingMode; } VkImageTiling getTilingMode() const { return mTilingMode; } VkImageCreateFlags getCreateFlags() const { return mCreateFlags; } - VkImageUsageFlags getUsage() const { return mUsage; } + VkImageUsageFlags getUsage() const + { + // The only difference between mRequestedUsage and mVkImageCreateInfo.usage should be + // VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM and kImageUsageTransferBits. + ASSERT(((mVkImageCreateInfo.usage ^ mRequestedUsage) & + ~(VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM | kImageUsageTransferBits)) == 0); + return mVkImageCreateInfo.usage; + } VkImageType getType() const { return mImageType; } const VkExtent3D &getExtents() const { return mExtents; } const VkExtent3D getRotatedExtents() const; @@ -2541,8 +2425,8 @@ class ImageHelper final : public Resource, public angle::Subject return mImageSerial; } - void setCurrentImageLayout(Renderer *renderer, ImageLayout newLayout); - ImageLayout getCurrentImageLayout() const { return mCurrentLayout; } + void setCurrentImageAccess(Renderer *renderer, ImageAccess newAccess); + ImageAccess getCurrentImageAccess() const { return mCurrentAccess; } VkImageLayout getCurrentLayout(Renderer *renderer) const; const QueueSerial &getBarrierQueueSerial() const { return mBarrierQueueSerial; } @@ -2558,6 +2442,7 @@ class ImageHelper final : public Resource, public angle::Subject void clearRenderPassUsageFlag(RenderPassUsage flag); void resetRenderPassUsageFlags(); bool hasRenderPassUsageFlag(RenderPassUsage flag) const; + bool hasAnyRenderPassUsageFlags() const; bool usedByCurrentRenderPassAsAttachmentAndSampler(RenderPassUsage textureSamplerUsage) const; static void Copy(Renderer *renderer, @@ -2591,8 +2476,9 @@ class ImageHelper final : public Resource, public angle::Subject LevelIndex maxLevel); // Resolve this image into a destination image. This image should be in the TransferSrc layout. - // The destination image is automatically transitioned into TransferDst. - void resolve(ImageHelper *dst, + // The destination image should be in the TransferDst layout. + void resolve(Renderer *renderer, + ImageHelper *dst, const VkImageResolve ®ion, OutsideRenderPassCommandBuffer *commandBuffer); @@ -2618,7 +2504,7 @@ class ImageHelper final : public Resource, public angle::Subject GLenum type, const gl::InternalFormat &formatInfo, const Format &vkFormat, - ImageAccess access, + ImageFormatSupport formatSupport, const uint8_t *data); angle::Result stageSubresourceUpdateImpl(ContextVk *contextVk, @@ -2630,7 +2516,7 @@ class ImageHelper final : public Resource, public angle::Subject GLenum type, const uint8_t *pixels, const Format &vkFormat, - ImageAccess access, + ImageFormatSupport formatSupport, const GLuint inputRowPitch, const GLuint inputDepthPitch, const GLuint inputSkipBytes, @@ -2646,7 +2532,7 @@ class ImageHelper final : public Resource, public angle::Subject GLenum type, const uint8_t *pixels, const Format &vkFormat, - ImageAccess access, + ImageFormatSupport formatSupport, ApplyImageUpdate applyUpdate, bool *updateAppliedImmediatelyOut); @@ -2664,7 +2550,7 @@ class ImageHelper final : public Resource, public angle::Subject const gl::Offset &dstOffset, const gl::Extents &dstExtent, const gl::InternalFormat &formatInfo, - ImageAccess access, + ImageFormatSupport formatSupport, FramebufferVk *framebufferVk); void stageSubresourceUpdateFromImage(RefCounted *image, @@ -2733,6 +2619,8 @@ class ImageHelper final : public Resource, public angle::Subject // as with renderbuffers or surface images. angle::Result flushAllStagedUpdates(ContextVk *contextVk); + // Returns true if any subresource within {levelGL, [layer, layer+layerCount)} has a staged + // update bool hasStagedUpdatesForSubresource(gl::LevelIndex levelGL, uint32_t layer, uint32_t layerCount) const; @@ -2744,7 +2632,7 @@ class ImageHelper final : public Resource, public angle::Subject void recordWriteBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, @@ -2753,7 +2641,7 @@ class ImageHelper final : public Resource, public angle::Subject void recordReadSubresourceBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, @@ -2761,22 +2649,22 @@ class ImageHelper final : public Resource, public angle::Subject OutsideRenderPassCommandBufferHelper *commands); void recordWriteBarrierOneOff(Renderer *renderer, - ImageLayout newLayout, + ImageAccess newAccess, PrimaryCommandBuffer *commandBuffer, VkSemaphore *acquireNextImageSemaphoreOut) { - recordBarrierOneOffImpl(renderer, getAspectFlags(), newLayout, mCurrentDeviceQueueIndex, + recordBarrierOneOffImpl(renderer, getAspectFlags(), newAccess, mCurrentDeviceQueueIndex, commandBuffer, acquireNextImageSemaphoreOut); } // This function can be used to prevent issuing redundant layout transition commands. - bool isReadBarrierNecessary(Renderer *renderer, ImageLayout newLayout) const; - bool isReadSubresourceBarrierNecessary(ImageLayout newLayout, + bool isReadBarrierNecessary(Renderer *renderer, ImageAccess newAccess) const; + bool isReadSubresourceBarrierNecessary(ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, uint32_t layerCount) const; - bool isWriteBarrierNecessary(ImageLayout newLayout, + bool isWriteBarrierNecessary(ImageAccess newAccess, gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, @@ -2784,7 +2672,7 @@ class ImageHelper final : public Resource, public angle::Subject void recordReadBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, OutsideRenderPassCommandBufferHelper *commands); bool isQueueFamilyChangeNeccesary(DeviceQueueIndex newDeviceQueueIndex) const @@ -2794,14 +2682,14 @@ class ImageHelper final : public Resource, public angle::Subject void changeLayoutAndQueue(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer); // Returns true if barrier has been generated void updateLayoutAndBarrier(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, BarrierType barrierType, const QueueSerial &queueSerial, PipelineBarrierArray *pipelineBarriers, @@ -2813,13 +2701,13 @@ class ImageHelper final : public Resource, public angle::Subject void acquireFromExternal(Context *context, DeviceQueueIndex externalQueueIndex, DeviceQueueIndex newDeviceQueueIndex, - ImageLayout currentLayout, + ImageAccess currentAccess, OutsideRenderPassCommandBuffer *commandBuffer); // Performs an ownership transfer to an external instance or API. void releaseToExternal(Context *context, DeviceQueueIndex externalQueueIndex, - ImageLayout desiredLayout, + ImageAccess expectedAccess, OutsideRenderPassCommandBuffer *commandBuffer); // Returns true if the image is owned by an external API or instance. @@ -2932,7 +2820,7 @@ class ImageHelper final : public Resource, public angle::Subject VkImageAspectFlags aspectFlags); bool hasImmutableSampler() const { return mYcbcrConversionDesc.valid(); } uint64_t getExternalFormat() const { return mYcbcrConversionDesc.getExternalFormat(); } - bool isYuvResolve() const { return mYcbcrConversionDesc.getExternalFormat() != 0; } + bool isYuvExternalFormat() const { return mYcbcrConversionDesc.getExternalFormat() != 0; } bool updateChromaFilter(Renderer *renderer, VkFilter filter) { return mYcbcrConversionDesc.updateChromaFilter(renderer, filter); @@ -2957,11 +2845,17 @@ class ImageHelper final : public Resource, public angle::Subject bool hasSubresourceDefinedStencilContent(gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount) const; + + // Returns true if VkImage has valid user content at any level/layer/aspect (emulated channel is + // ignored). + bool isVkImageContentDefined() const; + void invalidateEntireLevelContent(vk::ErrorContext *context, gl::LevelIndex level); void invalidateSubresourceContent(ContextVk *contextVk, gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount, bool *preferToKeepContentsDefinedOut); + void invalidateEntireLevelStencilContent(vk::ErrorContext *context, gl::LevelIndex level); void invalidateSubresourceStencilContent(ContextVk *contextVk, gl::LevelIndex level, uint32_t layerIndex, @@ -3006,7 +2900,23 @@ class ImageHelper final : public Resource, public angle::Subject mCurrentEvent.release(context); mLastNonShaderReadOnlyEvent.release(context); } - void updatePipelineStageAccessHistory(); + void updatePipelineStageAccessHistory(Renderer *renderer); + + bool areStagedUpdatesClearOnly(); + + bool canTransferFrom() const + { + return (mVkImageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0; + } + bool canTransferTo() const + { + return (mVkImageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0; + } + + // VK_QCOM_tile_memory_heap + bool isTileMemoryCompatible() const { return mTileMemoryCompatible; } + bool useTileMemory() const { return mUseTileMemory; } + angle::Result fallbackFromTileMemory(ContextVk *contextVk); private: ANGLE_ENABLE_STRUCT_PADDING_WARNINGS @@ -3084,6 +2994,8 @@ class ImageHelper final : public Resource, public angle::Subject SubresourceUpdate(VkColorComponentFlags colorMaskFlags, const VkClearColorValue &clearValue, const gl::ImageIndex &imageIndex); + + SubresourceUpdate(const SubresourceUpdate &other); SubresourceUpdate(SubresourceUpdate &&other); SubresourceUpdate &operator=(SubresourceUpdate &&other); @@ -3115,6 +3027,7 @@ class ImageHelper final : public Resource, public angle::Subject RefCounted *buffer; } refCounted; }; + using SubresourceUpdates = std::deque; // Up to 8 layers are tracked per level for whether contents are defined, above which the // contents are considered unconditionally defined. This handles the more likely scenarios of: @@ -3142,7 +3055,7 @@ class ImageHelper final : public Resource, public angle::Subject void initImageMemoryBarrierStruct(Renderer *renderer, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, uint32_t newQueueFamilyIndex, VkImageMemoryBarrier *imageMemoryBarrier) const; @@ -3150,7 +3063,7 @@ class ImageHelper final : public Resource, public angle::Subject template void barrierImpl(Renderer *renderer, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, CommandBufferT *commandBuffer, @@ -3159,7 +3072,7 @@ class ImageHelper final : public Resource, public angle::Subject template void recordBarrierImpl(Context *context, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, CommandBufferT *commandBuffer, @@ -3167,7 +3080,7 @@ class ImageHelper final : public Resource, public angle::Subject void recordBarrierOneOffImpl(Renderer *renderer, VkImageAspectFlags aspectMask, - ImageLayout newLayout, + ImageAccess newAccess, DeviceQueueIndex newDeviceQueueIndex, PrimaryCommandBuffer *commandBuffer, VkSemaphore *acquireNextImageSemaphoreOut); @@ -3188,7 +3101,7 @@ class ImageHelper final : public Resource, public angle::Subject // channels. VkColorComponentFlags getEmulatedChannelsMask() const; void stageClearIfEmulatedFormat(bool isRobustResourceInitEnabled, bool isExternalImage); - bool verifyEmulatedClearsAreBeforeOtherUpdates(const std::vector &updates); + bool verifyEmulatedClearsAreBeforeOtherUpdates(const SubresourceUpdates &updates); // Clear either color or depth/stencil based on image format. void clear(Renderer *renderer, @@ -3223,7 +3136,7 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t baseArrayLayer, uint32_t layerCount); - angle::Result updateSubresourceOnHost(ErrorContext *context, + angle::Result updateSubresourceOnHost(ContextVk *contextVk, ApplyImageUpdate applyUpdate, const gl::ImageIndex &index, const gl::Extents &glExtents, @@ -3253,8 +3166,8 @@ class ImageHelper final : public Resource, public angle::Subject // Limit the input level to the number of levels in subresource update list. void clipLevelToUpdateListUpperLimit(gl::LevelIndex *level) const; - std::vector *getLevelUpdates(gl::LevelIndex level); - const std::vector *getLevelUpdates(gl::LevelIndex level) const; + SubresourceUpdates *getLevelUpdates(gl::LevelIndex level); + const SubresourceUpdates *getLevelUpdates(gl::LevelIndex level) const; void appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update); void prependSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update); @@ -3267,6 +3180,9 @@ class ImageHelper final : public Resource, public angle::Subject void pruneSupersededUpdatesForLevel(ContextVk *contextVk, const gl::LevelIndex level, const PruneReason reason); + void pruneSupersededUpdatesForLevelImpl(ContextVk *contextVk, + const gl::LevelIndex level, + const gl::Box &upcomingUpdateBoundingBox); // Whether there are any updates in [start, end). bool hasStagedUpdatesInLevels(gl::LevelIndex levelStart, gl::LevelIndex levelEnd) const; @@ -3286,27 +3202,28 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags); - void invalidateSubresourceContentImpl(ContextVk *contextVk, + void invalidateSubresourceContentImpl(vk::ErrorContext *context, gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount, VkImageAspectFlagBits aspect, - LevelContentDefinedMask *contentDefinedMask, - bool *preferToKeepContentsDefinedOut); + bool *preferToKeepContentsDefinedOut, + bool *layerLimitReachedOut); void restoreSubresourceContentImpl(gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount, - VkImageAspectFlagBits aspect, - LevelContentDefinedMask *contentDefinedMask); + VkImageAspectFlagBits aspect); // Use the following functions to access m*ContentDefined to make sure the correct level index // is used (i.e. vk::LevelIndex and not gl::LevelIndex). - LevelContentDefinedMask &getLevelContentDefined(LevelIndex level); - LevelContentDefinedMask &getLevelStencilContentDefined(LevelIndex level); + void setLevelContentDefined(LevelIndex level, const uint8_t layerRangeBits); + void clearLevelContentDefined(LevelIndex level, const uint8_t layerRangeBits); + void setLevelStencilContentDefined(LevelIndex level, const uint8_t layerRangeBits); + void clearLevelStencilContentDefined(LevelIndex level, const uint8_t layerRangeBits); const LevelContentDefinedMask &getLevelContentDefined(LevelIndex level) const; const LevelContentDefinedMask &getLevelStencilContentDefined(LevelIndex level) const; - angle::Result initLayerImageViewImpl(ErrorContext *context, + angle::Result initLayerImageViewImpl(ContextVk *contextVk, gl::TextureType textureType, VkImageAspectFlags aspectMask, const gl::SwizzleState &swizzleMap, @@ -3317,7 +3234,8 @@ class ImageHelper final : public Resource, public angle::Subject uint32_t layerCount, VkFormat imageFormat, VkImageUsageFlags usageFlags, - gl::YuvSamplingMode yuvSamplingMode) const; + gl::YuvSamplingMode yuvSamplingMode, + GLenum astcDecodePrecision) const; angle::Result readPixelsImpl(ContextVk *contextVk, const gl::Rectangle &area, @@ -3368,10 +3286,16 @@ class ImageHelper final : public Resource, public angle::Subject return ext.width * ext.height > kThreadholdForComputeTransCoding; } - void adjustLayerRange(const std::vector &levelUpdates, + void adjustLayerRange(const SubresourceUpdates &levelUpdates, uint32_t *layerStart, uint32_t *layerEnd); + // Copy most of state and move VkImage/VkDeviceMemory from other ImageHelper. This should not be + // used for general usage. It is specifically for stageSelfUpdate and falling back from tile + // memory where the VkImage and storage will be reallocated but most of ImageHelper property + // will keep the same. + void copyStateAndMoveStorageFrom(ImageHelper *other); + // Vulkan objects. Image mImage; DeviceMemory mDeviceMemory; @@ -3382,7 +3306,7 @@ class ImageHelper final : public Resource, public angle::Subject VkImageType mImageType; VkImageTiling mTilingMode; VkImageCreateFlags mCreateFlags; - VkImageUsageFlags mUsage; + VkImageUsageFlags mRequestedUsage; // For Android swapchain images, the Vulkan VkImage must be "rotated". However, most of ANGLE // uses non-rotated extents (i.e. the way the application views the extents--see "Introduction // to Android rotation and pre-rotation" in "SurfaceVk.cpp"). Thus, mExtents are non-rotated. @@ -3396,10 +3320,10 @@ class ImageHelper final : public Resource, public angle::Subject ImageSerial mImageSerial; // Current state. - ImageLayout mCurrentLayout; DeviceQueueIndex mCurrentDeviceQueueIndex; + ImageAccess mCurrentAccess; // For optimizing transition between different shader readonly layouts - ImageLayout mLastNonShaderReadOnlyLayout; + ImageAccess mLastNonShaderReadOnlyAccess; VkPipelineStageFlags mCurrentShaderReadStageMask; // Track how it is being used by current open renderpass. RenderPassUsageFlags mRenderPassUsageFlags; @@ -3440,7 +3364,7 @@ class ImageHelper final : public Resource, public angle::Subject // Image formats used for imageless framebuffers. ImageFormats mViewFormats; - std::vector> mSubresourceUpdates; + std::vector mSubresourceUpdates; VkDeviceSize mTotalStagedBufferUpdateSize; // Optimization for repeated clear with the same value. If this pointer is not null, the entire @@ -3448,10 +3372,11 @@ class ImageHelper final : public Resource, public angle::Subject // the exact same clear value, we will detect and skip the clear call. Optional mCurrentSingleClearValue; - // Track whether each subresource has defined contents. Up to 8 layers are tracked per level, - // above which the contents are considered unconditionally defined. - gl::TexLevelArray mContentDefined; - gl::TexLevelArray mStencilContentDefined; + // Track whether each subresource of VkImage has defined contents. Up to 8 layers are tracked + // per level, above which the contents are considered unconditionally defined. Note that this is + // only tracking VkImage. Staged update will not set this bit until it is flushed. + gl::TexLevelArray mVkImageContentDefined; + gl::TexLevelArray mVkImageStencilContentDefined; // Used for memory allocation tracking. // Memory size allocated for the image in the memory during the initialization. @@ -3461,6 +3386,11 @@ class ImageHelper final : public Resource, public angle::Subject // Memory type index used for the allocation. It can be used to determine the heap index. uint32_t mMemoryTypeIndex; + // True if image is compatible with tile memory + bool mTileMemoryCompatible; + // True if it actually uses tile memory. + bool mUseTileMemory; + // Only used for swapChain images. This is set when an image is acquired and is waited on // by the next submission (which uses this image), at which point it is released. Semaphore mAcquireNextImageSemaphore; @@ -3533,13 +3463,13 @@ class ImageViewHelper final : angle::NonCopyable } const ImageView &getLinearCopyImageView() const { - return mIsCopyImageViewShared ? getValidReadViewImpl(mPerLevelRangeLinearReadImageViews) - : getValidReadViewImpl(mPerLevelRangeLinearCopyImageViews); + ASSERT(mLinearCopyImageView.valid()); + return mLinearCopyImageView; } const ImageView &getSRGBCopyImageView() const { - return mIsCopyImageViewShared ? getValidReadViewImpl(mPerLevelRangeSRGBReadImageViews) - : getValidReadViewImpl(mPerLevelRangeSRGBCopyImageViews); + ASSERT(mSRGBCopyImageView.valid()); + return mSRGBCopyImageView; } const ImageView &getStencilReadImageView() const { @@ -3584,17 +3514,8 @@ class ImageViewHelper final : angle::NonCopyable bool hasCopyImageView() const { - if ((mReadColorspace == ImageViewColorspace::Linear && - mCurrentBaseMaxLevelHash < mPerLevelRangeLinearCopyImageViews.size()) || - (mReadColorspace == ImageViewColorspace::SRGB && - mCurrentBaseMaxLevelHash < mPerLevelRangeSRGBCopyImageViews.size())) - { - return getCopyImageView().valid(); - } - else - { - return false; - } + return (mReadColorspace == ImageViewColorspace::Linear && mLinearCopyImageView.valid()) || + (mReadColorspace == ImageViewColorspace::SRGB && mSRGBCopyImageView.valid()); } // For applications that frequently switch a texture's max level, and make no other changes to @@ -3610,10 +3531,11 @@ class ImageViewHelper final : angle::NonCopyable uint32_t baseLayer, uint32_t layerCount, bool requiresSRGBViews, - VkImageUsageFlags imageUsageFlags); + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision); // Creates a storage view with all layers of the level. - angle::Result getLevelStorageImageView(ErrorContext *context, + angle::Result getLevelStorageImageView(ContextVk *contextVk, gl::TextureType viewType, const ImageHelper &image, LevelIndex levelVk, @@ -3623,7 +3545,7 @@ class ImageViewHelper final : angle::NonCopyable const ImageView **imageViewOut); // Creates a storage view with a single layer of the level. - angle::Result getLevelLayerStorageImageView(ErrorContext *context, + angle::Result getLevelLayerStorageImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -3632,7 +3554,7 @@ class ImageViewHelper final : angle::NonCopyable const ImageView **imageViewOut); // Creates a draw view with a range of layers of the level. - angle::Result getLevelDrawImageView(ErrorContext *context, + angle::Result getLevelDrawImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -3640,14 +3562,14 @@ class ImageViewHelper final : angle::NonCopyable const ImageView **imageViewOut); // Creates a draw view with a single layer of the level. - angle::Result getLevelLayerDrawImageView(ErrorContext *context, + angle::Result getLevelLayerDrawImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, const ImageView **imageViewOut); // Creates a depth-xor-stencil view with a range of layers of the level. - angle::Result getLevelDepthOrStencilImageView(ErrorContext *context, + angle::Result getLevelDepthOrStencilImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -3656,7 +3578,7 @@ class ImageViewHelper final : angle::NonCopyable const ImageView **imageViewOut); // Creates a depth-xor-stencil view with a single layer of the level. - angle::Result getLevelLayerDepthOrStencilImageView(ErrorContext *context, + angle::Result getLevelLayerDepthOrStencilImageView(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -3690,6 +3612,7 @@ class ImageViewHelper final : angle::NonCopyable // Helpers for colorspace state ImageViewColorspace getColorspaceForRead() const { return mReadColorspace; } + bool hasColorspaceOverrideForRead(const ImageHelper &image) const { ASSERT(image.valid()); @@ -3707,7 +3630,7 @@ class ImageViewHelper final : angle::NonCopyable (image.getActualFormat().isSRGB && mWriteColorspace == vk::ImageViewColorspace::Linear); } - angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const; + void updateStaticTexelFetch(const ImageHelper &image, bool staticTexelFetchAccess) const { if (mColorspaceState.hasStaticTexelFetchAccess != staticTexelFetchAccess) @@ -3751,6 +3674,16 @@ class ImageViewHelper final : angle::NonCopyable } } + angle::FormatID getColorspaceOverrideFormatForRead(angle::FormatID format) const + { + return getColorspaceOverrideFormatImpl(mReadColorspace, format); + } + + angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const + { + return getColorspaceOverrideFormatImpl(mWriteColorspace, format); + } + private: ImageView &getReadImageView() { @@ -3760,20 +3693,8 @@ class ImageViewHelper final : angle::NonCopyable } ImageView &getCopyImageView() { - if (mReadColorspace == ImageViewColorspace::Linear) - { - return mIsCopyImageViewShared ? getReadViewImpl(mPerLevelRangeLinearReadImageViews) - : getReadViewImpl(mPerLevelRangeLinearCopyImageViews); - } - - return mIsCopyImageViewShared ? getReadViewImpl(mPerLevelRangeSRGBReadImageViews) - : getReadViewImpl(mPerLevelRangeSRGBCopyImageViews); - } - ImageView &getCopyImageViewStorage() - { - return mReadColorspace == ImageViewColorspace::Linear - ? getReadViewImpl(mPerLevelRangeLinearCopyImageViews) - : getReadViewImpl(mPerLevelRangeSRGBCopyImageViews); + return mReadColorspace == ImageViewColorspace::Linear ? mLinearCopyImageView + : mSRGBCopyImageView; } // Used by public get*ImageView() methods to do proper assert based on vector size and validity @@ -3798,13 +3719,13 @@ class ImageViewHelper final : angle::NonCopyable return imageViewVector[mCurrentBaseMaxLevelHash]; } - angle::Result getLevelLayerDrawImageViewImpl(ErrorContext *context, + angle::Result getLevelLayerDrawImageViewImpl(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, uint32_t layerCount, ImageView *imageViewOut); - angle::Result getLevelLayerDepthOrStencilImageViewImpl(ErrorContext *context, + angle::Result getLevelLayerDepthOrStencilImageViewImpl(ContextVk *contextVk, const ImageHelper &image, LevelIndex levelVk, uint32_t layer, @@ -3822,7 +3743,8 @@ class ImageViewHelper final : angle::NonCopyable uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount, - VkImageUsageFlags imageUsageFlags); + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision); // Create linear and srgb read views angle::Result initLinearAndSrgbReadViewsImpl(ContextVk *contextVk, @@ -3834,10 +3756,14 @@ class ImageViewHelper final : angle::NonCopyable uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount, - VkImageUsageFlags imageUsageFlags); + VkImageUsageFlags imageUsageFlags, + GLenum astcDecodePrecision); void updateColorspace(const ImageHelper &image) const; + angle::FormatID getColorspaceOverrideFormatImpl(ImageViewColorspace colorspace, + angle::FormatID format) const; + // For applications that frequently switch a texture's base/max level, and make no other changes // to the texture, keep track of the currently-used base and max levels, and keep one "read // view" per each combination. The value stored here is base<<4|max, used to look up the view @@ -3846,10 +3772,6 @@ class ImageViewHelper final : angle::NonCopyable "Not enough bits in mCurrentBaseMaxLevelHash"); uint8_t mCurrentBaseMaxLevelHash; - // This flag is set when copy views are identical to read views, and we share the views instead - // of creating new ones. - bool mIsCopyImageViewShared; - mutable ImageViewColorspace mReadColorspace; mutable ImageViewColorspace mWriteColorspace; mutable angle::ColorspaceState mColorspaceState; @@ -3857,11 +3779,15 @@ class ImageViewHelper final : angle::NonCopyable // Read views (one per [base, max] level range) ImageViewVector mPerLevelRangeLinearReadImageViews; ImageViewVector mPerLevelRangeSRGBReadImageViews; - ImageViewVector mPerLevelRangeLinearCopyImageViews; - ImageViewVector mPerLevelRangeSRGBCopyImageViews; ImageViewVector mPerLevelRangeStencilReadImageViews; ImageViewVector mPerLevelRangeSamplerExternal2DY2YEXTImageViews; + // Copy views always view the whole image, because the shaders directly access the mips and they + // don't need to take the base level into account (because it pertains only to textures, and + // it's a detail that's not propagated to the render target). + ImageView mLinearCopyImageView; + ImageView mSRGBCopyImageView; + // Draw views LayerLevelImageViewVector mLayerLevelDrawImageViews; LayerLevelImageViewVector mLayerLevelDrawImageViewsLinear; @@ -3901,7 +3827,8 @@ class BufferViewHelper final : public Resource const BufferHelper &buffer, VkDeviceSize bufferOffset, const Format &format, - const BufferView **viewOut); + const BufferView **viewOut, + VkFormat *viewVkFormatOut); // Return unique Serial for a bufferView. ImageOrBufferViewSubresourceSerial getSerial() const; @@ -3952,9 +3879,10 @@ class ShaderProgramHelper : angle::NonCopyable const GraphicsPipelineDesc **descPtrOut, PipelineHelper **pipelineOut) const { - return graphicsPipelines->createPipeline(context, pipelineCache, compatibleRenderPass, - pipelineLayout, mShaders, specConsts, source, - pipelineDesc, descPtrOut, pipelineOut); + return graphicsPipelines->createPipeline( + context, pipelineCache, compatibleRenderPass, pipelineLayout, + GraphicsPipelineShadersInfo(&mShaders, &specConsts), source, pipelineDesc, descPtrOut, + pipelineOut); } void createMonolithicPipelineCreationTask(vk::ErrorContext *context, @@ -4006,39 +3934,39 @@ class ActiveHandleCounter final : angle::NonCopyable // directly correspond to the application draw/dispatch call. Before the command is recorded in the // command buffer, the render pass may need to be broken and/or appropriate barriers may need to be // inserted. The following struct aggregates all resources that such internal commands need. -struct CommandBufferBufferAccess +struct CommandResourceBuffer { BufferHelper *buffer; VkAccessFlags accessType; PipelineStage stage; }; -struct CommandBufferImageAccess +struct CommandResourceImage { ImageHelper *image; VkImageAspectFlags aspectFlags; - ImageLayout imageLayout; + ImageAccess imageAccess; }; -struct CommandBufferImageSubresourceAccess +struct CommandResourceImageSubresource { - CommandBufferImageAccess access; + CommandResourceImage image; gl::LevelIndex levelStart; uint32_t levelCount; uint32_t layerStart; uint32_t layerCount; }; -struct CommandBufferBufferExternalAcquireRelease +struct CommandResourceBufferExternalAcquireRelease { BufferHelper *buffer; }; -struct CommandBufferResourceAccess +struct CommandResourceGeneric { Resource *resource; }; -class CommandBufferAccess : angle::NonCopyable +class CommandResources : angle::NonCopyable { public: - CommandBufferAccess(); - ~CommandBufferAccess(); + CommandResources(); + ~CommandResources(); void onBufferTransferRead(BufferHelper *buffer) { @@ -4065,7 +3993,8 @@ class CommandBufferAccess : angle::NonCopyable void onImageTransferRead(VkImageAspectFlags aspectFlags, ImageHelper *image) { - onImageRead(aspectFlags, ImageLayout::TransferSrc, image); + ASSERT(image->canTransferFrom()); + onImageRead(aspectFlags, ImageAccess::TransferSrc, image); } void onImageTransferWrite(gl::LevelIndex levelStart, uint32_t levelCount, @@ -4074,8 +4003,9 @@ class CommandBufferAccess : angle::NonCopyable VkImageAspectFlags aspectFlags, ImageHelper *image) { + ASSERT(image->canTransferTo()); onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags, - ImageLayout::TransferDst, image); + ImageAccess::TransferDst, image); } void onImageSelfCopy(gl::LevelIndex readLevelStart, uint32_t readLevelCount, @@ -4088,10 +4018,11 @@ class CommandBufferAccess : angle::NonCopyable VkImageAspectFlags aspectFlags, ImageHelper *image) { + ASSERT(image->canTransferFrom() && image->canTransferTo()); onImageReadSubresources(readLevelStart, readLevelCount, readLayerStart, readLayerCount, - aspectFlags, ImageLayout::TransferSrcDst, image); + aspectFlags, ImageAccess::TransferSrcDst, image); onImageWrite(writeLevelStart, writeLevelCount, writeLayerStart, writeLayerCount, - aspectFlags, ImageLayout::TransferSrcDst, image); + aspectFlags, ImageAccess::TransferSrcDst, image); } void onImageDrawMipmapGenerationWrite(gl::LevelIndex levelStart, uint32_t levelCount, @@ -4101,11 +4032,11 @@ class CommandBufferAccess : angle::NonCopyable ImageHelper *image) { onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags, - ImageLayout::ColorWrite, image); + ImageAccess::ColorWrite, image); } void onImageComputeShaderRead(VkImageAspectFlags aspectFlags, ImageHelper *image) { - onImageRead(aspectFlags, ImageLayout::ComputeShaderReadOnly, image); + onImageRead(aspectFlags, ImageAccess::ComputeShaderReadOnly, image); } void onImageComputeMipmapGenerationRead(gl::LevelIndex levelStart, uint32_t levelCount, @@ -4115,7 +4046,7 @@ class CommandBufferAccess : angle::NonCopyable ImageHelper *image) { onImageReadSubresources(levelStart, levelCount, layerStart, layerCount, aspectFlags, - ImageLayout::ComputeShaderWrite, image); + ImageAccess::ComputeShaderWrite, image); } void onImageComputeShaderWrite(gl::LevelIndex levelStart, uint32_t levelCount, @@ -4125,7 +4056,7 @@ class CommandBufferAccess : angle::NonCopyable ImageHelper *image) { onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags, - ImageLayout::ComputeShaderWrite, image); + ImageAccess::ComputeShaderWrite, image); } void onImageTransferDstAndComputeWrite(gl::LevelIndex levelStart, uint32_t levelCount, @@ -4134,8 +4065,9 @@ class CommandBufferAccess : angle::NonCopyable VkImageAspectFlags aspectFlags, ImageHelper *image) { + ASSERT(image->canTransferTo()); onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags, - ImageLayout::TransferDstAndComputeWrite, image); + ImageAccess::TransferDstAndComputeWrite, image); } void onExternalAcquireRelease(ImageHelper *image) { onResourceAccess(image); } void onQueryAccess(QueryHelper *query) { onResourceAccess(query); } @@ -4143,16 +4075,16 @@ class CommandBufferAccess : angle::NonCopyable // The limits reflect the current maximum concurrent usage of each resource type. ASSERTs will // fire if this limit is exceeded in the future. - using ReadBuffers = angle::FixedVector; - using WriteBuffers = angle::FixedVector; - using ReadImages = angle::FixedVector; - using WriteImages = angle::FixedVector; - using ReadImageSubresources = angle::FixedVector; + using ReadBuffers = angle::FixedVector; + using WriteBuffers = angle::FixedVector; + using ReadImages = angle::FixedVector; + using WriteImages = + angle::FixedVector; + using ReadImageSubresources = angle::FixedVector; using ExternalAcquireReleaseBuffers = - angle::FixedVector; - using AccessResources = angle::FixedVector; + angle::FixedVector; + using GenericResources = angle::FixedVector; const ReadBuffers &getReadBuffers() const { return mReadBuffers; } const WriteBuffers &getWriteBuffers() const { return mWriteBuffers; } @@ -4163,7 +4095,7 @@ class CommandBufferAccess : angle::NonCopyable { return mExternalAcquireReleaseBuffers; } - const AccessResources &getAccessResources() const { return mAccessResources; } + const GenericResources &getGenericResources() const { return mGenericResources; } private: void onBufferRead(VkAccessFlags readAccessType, PipelineStage readStage, BufferHelper *buffer); @@ -4171,13 +4103,13 @@ class CommandBufferAccess : angle::NonCopyable PipelineStage writeStage, BufferHelper *buffer); - void onImageRead(VkImageAspectFlags aspectFlags, ImageLayout imageLayout, ImageHelper *image); + void onImageRead(VkImageAspectFlags aspectFlags, ImageAccess imageAccess, ImageHelper *image); void onImageWrite(gl::LevelIndex levelStart, uint32_t levelCount, uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image); void onImageReadSubresources(gl::LevelIndex levelStart, @@ -4185,7 +4117,7 @@ class CommandBufferAccess : angle::NonCopyable uint32_t layerStart, uint32_t layerCount, VkImageAspectFlags aspectFlags, - ImageLayout imageLayout, + ImageAccess imageAccess, ImageHelper *image); void onResourceAccess(Resource *resource); @@ -4196,7 +4128,7 @@ class CommandBufferAccess : angle::NonCopyable WriteImages mWriteImages; ReadImageSubresources mReadImageSubresources; ExternalAcquireReleaseBuffers mExternalAcquireReleaseBuffers; - AccessResources mAccessResources; + GenericResources mGenericResources; }; enum class PresentMode diff --git a/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp b/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp index ad106ebb178..7b54f01c1c3 100644 --- a/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp +++ b/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp @@ -48,8 +48,6 @@ namespace #include "libANGLE/renderer/vulkan/shaders/gen/BlitResolve.frag.00000017.inc" #include "libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc" #include "libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc" -#include "libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc" -#include "libANGLE/renderer/vulkan/shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc" @@ -204,8 +202,6 @@ constexpr CompressedShaderBlob kBlitResolve_frag_shaders[] = { constexpr CompressedShaderBlob kBlitResolveStencilNoExport_comp_shaders[] = { {kBlitResolveStencilNoExport_comp_00000000, sizeof(kBlitResolveStencilNoExport_comp_00000000)}, {kBlitResolveStencilNoExport_comp_00000001, sizeof(kBlitResolveStencilNoExport_comp_00000001)}, - {kBlitResolveStencilNoExport_comp_00000002, sizeof(kBlitResolveStencilNoExport_comp_00000002)}, - {kBlitResolveStencilNoExport_comp_00000003, sizeof(kBlitResolveStencilNoExport_comp_00000003)}, }; constexpr CompressedShaderBlob kConvertIndex_comp_shaders[] = { {kConvertIndex_comp_00000000, sizeof(kConvertIndex_comp_00000000)}, diff --git a/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.gni b/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.gni index e61956b4ca2..c6865214235 100644 --- a/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.gni +++ b/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.gni @@ -38,8 +38,6 @@ angle_vulkan_internal_shaders = [ "shaders/gen/BlitResolve.frag.00000017.inc", "shaders/gen/BlitResolveStencilNoExport.comp.00000000.inc", "shaders/gen/BlitResolveStencilNoExport.comp.00000001.inc", - "shaders/gen/BlitResolveStencilNoExport.comp.00000002.inc", - "shaders/gen/BlitResolveStencilNoExport.comp.00000003.inc", "shaders/gen/ConvertIndex.comp.00000000.inc", "shaders/gen/ConvertIndex.comp.00000001.inc", "shaders/gen/ConvertIndex.comp.00000002.inc", diff --git a/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h b/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h index 0db110cb2d7..a14f9ce2f5d 100644 --- a/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h +++ b/src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h @@ -53,10 +53,9 @@ namespace BlitResolveStencilNoExport_comp { enum flags { - kSrcIsArray = 0x00000001, - kIsResolve = 0x00000002, + kIsResolve = 0x00000001, }; -constexpr size_t kArrayLen = 0x00000004; +constexpr size_t kArrayLen = 0x00000002; } // namespace BlitResolveStencilNoExport_comp namespace ConvertIndex_comp diff --git a/src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp b/src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp index 5dc649bed2e..9d732296b24 100644 --- a/src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp +++ b/src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp @@ -58,16 +58,36 @@ constexpr FormatMap kFormatProperties = { {FormatID::ASTC_12x10_UNORM_BLOCK, {0, 0, 0}}, {FormatID::ASTC_12x12_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_12x12_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_3x3x3_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_4x3x3_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_4x4_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_4x4_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_4x4x3_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_4x4x4_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_5x4_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_5x4_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_5x4x4_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_5x5_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_5x5_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_5x5x4_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_5x5x5_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_6x5_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_6x5_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_6x5x5_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_6x6_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_6x6_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_6x6x5_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_6x6x6_UNORM_BLOCK, {0, 0, 0}}, + {FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_8x5_SRGB_BLOCK, {0, 0, 0}}, {FormatID::ASTC_8x5_UNORM_BLOCK, {0, 0, 0}}, {FormatID::ASTC_8x6_SRGB_BLOCK, {0, 0, 0}}, @@ -127,6 +147,7 @@ constexpr FormatMap kFormatProperties = { {FormatID::EXTERNAL5, {0, 0, 0}}, {FormatID::EXTERNAL6, {0, 0, 0}}, {FormatID::EXTERNAL7, {0, 0, 0}}, + {FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, {0, 0, 0}}, {FormatID::G8_B8R8_2PLANE_420_UNORM, {0, 0, 0}}, {FormatID::G8_B8_R8_3PLANE_420_UNORM, {0, 0, 0}}, {FormatID::NONE, {0, 0, 0}}, @@ -141,6 +162,7 @@ constexpr FormatMap kFormatProperties = { SAMPLED_IMAGE_FILTER_LINEAR, UNIFORM_TEXEL_BUFFER | VERTEX_BUFFER}}, {FormatID::R10G10B10A2_USCALED, {0, 0, 0}}, + {FormatID::R10X6G10X6B10X6A10X6_UNORM, {0, 0, 0}}, {FormatID::R11G11B10_FLOAT, {0, BLIT_SRC | SAMPLED_IMAGE | SAMPLED_IMAGE_FILTER_LINEAR, UNIFORM_TEXEL_BUFFER}}, {FormatID::R16G16B16A16_FLOAT, diff --git a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp index d5d44228a40..126bd67373f 100644 --- a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp +++ b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp @@ -102,7 +102,14 @@ void RefCountedEvent::releaseImpl(Renderer *renderer, RecyclerT *recycler) if (isLastReference) { ASSERT(recycler != nullptr); - recycler->recycle(std::move(*this)); + if (renderer->getFeatures().recycleVkEvent.enabled) + { + recycler->recycle(std::move(*this), renderer->getDevice()); + } + else + { + destroy(renderer->getDevice()); + } ASSERT(mHandle == nullptr); } else @@ -335,6 +342,24 @@ bool RefCountedEventRecycler::fetchEventsToReuse(RefCountedEventCollector *event return true; } +void RefCountedEventRecycler::recycle(RefCountedEventCollector &&garbageObjects, VkDevice device) +{ + ASSERT(!garbageObjects.empty()); + for (const RefCountedEvent &event : garbageObjects) + { + ASSERT(event.validAndNoReference()); + } + std::lock_guard lock(mMutex); + if (mEventsToReset.size() >= kMaxEventToKeepCount) + { + DestroyRefCountedEvents(device, garbageObjects); + } + else + { + mEventsToReset.emplace_back(std::move(garbageObjects)); + } +} + // RefCountedEventsGarbageRecycler implementation. RefCountedEventsGarbageRecycler::~RefCountedEventsGarbageRecycler() { @@ -374,7 +399,8 @@ void RefCountedEventsGarbageRecycler::cleanup(Renderer *renderer) // Move mEventsToReset to the renderer so that it can be reset. if (!mEventsToReset.empty()) { - renderer->getRefCountedEventRecycler()->recycle(std::move(mEventsToReset)); + renderer->getRefCountedEventRecycler()->recycle(std::move(mEventsToReset), + renderer->getDevice()); } } @@ -477,12 +503,16 @@ void EventBarrierArray::execute(Renderer *renderer, PrimaryCommandBuffer *primar void EventBarrierArray::addDiagnosticsString(std::ostringstream &out) const { - out << "Event Barrier: "; + std::ostringstream eventStream; + eventStream << "Event Barrier: "; for (const EventBarrier &barrier : mBarriers) { - barrier.addDiagnosticsString(out); + barrier.addDiagnosticsString(eventStream); + } + if (!mBarriers.empty()) + { + out << eventStream.str() << "\\l"; } - out << "\\l"; } } // namespace vk } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h index efecf9b3bb2..fdf6eec3349 100644 --- a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h +++ b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h @@ -27,7 +27,7 @@ namespace rx namespace vk { class Context; -enum class ImageLayout; +enum class ImageAccess; // There are two ways to implement a barrier: Using VkCmdPipelineBarrier or VkCmdWaitEvents. The // BarrierType enum will be passed around to indicate which barrier caller want to use. @@ -131,16 +131,12 @@ enum class EventStage : uint32_t using EventStageBitMask = typename angle::PackedEnumBitSet; using EventStageToVkPipelineStageFlagsMap = angle::PackedEnumMap; -// Initialize EventStage to VkPipelineStageFlags mapping table. -void InitializeEventStageToVkPipelineStageFlagsMap( - EventStageToVkPipelineStageFlagsMap *map, - VkPipelineStageFlags supportedVulkanPipelineStageMask); // VkCmdWaitEvents requires srcStageMask must be the bitwise OR of the stageMask parameter used in // previous calls to vkCmdSetEvent (See VUID-vkCmdWaitEvents-srcStageMask-01158). This mean we must // keep the record of what stageMask each event has been used in VkCmdSetEvent call so that we can // retrieve that information when we need to wait for the event. Instead of keeping just stageMask -// here, we keep the ImageLayout for now which gives us more information for debugging. +// here, we keep the ImageAccess for now which gives us more information for debugging. struct EventAndStage { bool valid() const { return event.valid(); } @@ -415,20 +411,21 @@ class RefCountedEventsGarbage final }; // Two levels of RefCountedEvents recycle system: For the performance reason, we have two levels of -// events recycler system. The first level is per ShareGroupVk, which owns RefCountedEventRecycler. -// RefCountedEvent garbage is added to it without any lock. Once GPU complete, the refCount is -// decremented. When the last refCount goes away, it goes into mEventsToReset. Note that since -// ShareGroupVk access is already protected by context share lock at the API level, so no lock is -// taken and reference counting is not atomic. At RefCountedEventsGarbageRecycler::cleanup time, the -// entire mEventsToReset is added into renderer's list. The renderer owns RefCountedEventRecycler -// list, and all access to it is protected with simple mutex lock. When any context calls -// OutsideRenderPassCommandBufferHelper::flushToPrimary, mEventsToReset is retrieved from renderer -// and the reset commands is added to the command buffer. The events are then moved to the -// renderer's garbage list. They are checked and along with renderer's garbage cleanup and if -// completed, they get moved to renderer's mEventsToReuse list. When a RefCountedEvent is needed, we -// always dip into ShareGroupVk's mEventsToReuse list. If its empty, it then dip into renderer's -// mEventsToReuse and grab a collector of events and try to reuse. That way the traffic into -// renderer is minimized as most of calls will be contained in SHareGroupVk. +// events recycler system. The first level is per ShareGroupVk, which owns +// RefCountedEventsGarbageRecycler. RefCountedEvent garbage is added to it without any lock. Once +// GPU complete, the refCount is decremented. When the last refCount goes away, it goes into +// mEventsToReset. Note that since ShareGroupVk access is already protected by context share lock at +// the API level, so no lock is taken and reference counting is not atomic. At +// RefCountedEventsGarbageRecycler::cleanup time, the entire mEventsToReset is added into renderer's +// list. The renderer owns RefCountedEventRecycler list, and all access to it is protected with +// simple mutex lock. When any context calls OutsideRenderPassCommandBufferHelper::flushToPrimary, +// mEventsToReset is retrieved from renderer and the reset commands is added to the command buffer. +// The events are then moved to the renderer's garbage list. They are checked and along with +// renderer's garbage cleanup and if completed, they get moved to renderer's mEventsToReuse list. +// When a RefCountedEvent is needed, we always dip into ShareGroupVk's mEventsToReuse list. If its +// empty, it then dip into renderer's mEventsToReuse and grab a collector of events and try to +// reuse. That way the traffic into renderer is minimized as most of calls will be contained in +// ShareGroupVk. // Thread safe event recycler, protected by its own lock. class RefCountedEventRecycler final @@ -445,29 +442,27 @@ class RefCountedEventRecycler final void destroy(VkDevice device); // Add single event to the toReset list - void recycle(RefCountedEvent &&garbageObject) + void recycle(RefCountedEvent &&garbageObject, VkDevice device) { ASSERT(garbageObject.validAndNoReference()); std::lock_guard lock(mMutex); - if (mEventsToReset.empty()) + if (mEventsToReset.size() >= kMaxEventToKeepCount) { - mEventsToReset.emplace_back(); + garbageObject.destroy(device); } - mEventsToReset.back().emplace_back(std::move(garbageObject)); - } - - // Add a list of events to the toReset list - void recycle(RefCountedEventCollector &&garbageObjects) - { - ASSERT(!garbageObjects.empty()); - for (const RefCountedEvent &event : garbageObjects) + else { - ASSERT(event.validAndNoReference()); + if (mEventsToReset.empty()) + { + mEventsToReset.emplace_back(); + } + mEventsToReset.back().emplace_back(std::move(garbageObject)); } - std::lock_guard lock(mMutex); - mEventsToReset.emplace_back(std::move(garbageObjects)); } + // Add a list of events to the toReset list + void recycle(RefCountedEventCollector &&garbageObjects, VkDevice device); + // Reset all events in the toReset list and move them to the toReuse list void resetEvents(ErrorContext *context, const QueueSerial queueSerial, @@ -482,6 +477,10 @@ class RefCountedEventRecycler final bool fetchEventsToReuse(RefCountedEventCollector *eventsToReuseOut); private: + // Maximum number of RefCountedEventCollector we will keep in mEventsToReset. + // When mEventsToReset size reaches kMaxEventToKeepCount, any extra used VkEvent items will be + // destroyed immediately. + static constexpr size_t kMaxEventToKeepCount = 16; angle::SimpleMutex mMutex; // RefCountedEvent list that has been released, needs to be reset. std::deque mEventsToReset; @@ -512,7 +511,7 @@ class RefCountedEventsGarbageRecycler final mGarbageQueue.emplace(queueSerial, std::move(refCountedEvents)); } - void recycle(RefCountedEvent &&garbageObject) + void recycle(RefCountedEvent &&garbageObject, VkDevice device) { ASSERT(garbageObject.validAndNoReference()); mEventsToReset.emplace_back(std::move(garbageObject)); diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.cpp b/src/libANGLE/renderer/vulkan/vk_renderer.cpp index 933bf898130..62ad1614760 100644 --- a/src/libANGLE/renderer/vulkan/vk_renderer.cpp +++ b/src/libANGLE/renderer/vulkan/vk_renderer.cpp @@ -7,9 +7,14 @@ // Implements the class methods for Renderer. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/vk_renderer.h" // Placing this first seems to solve an intellisense bug. +#include "libANGLE/angletypes.h" #include "libANGLE/renderer/vulkan/vk_utils.h" #include @@ -36,6 +41,7 @@ #include "libANGLE/renderer/vulkan/vk_resource.h" #include "libANGLE/trace.h" #include "platform/PlatformMethods.h" +#include "vulkan/vulkan_core.h" // Consts namespace @@ -69,6 +75,75 @@ constexpr bool kEnableVulkanAPIDumpLayer = false; namespace rx { +namespace +{ +constexpr angle::PackedEnumMap kQueueSubmitReason = {{ + {QueueSubmitReason::EGLSwapBuffers, "Queue submission imminent due to eglSwapBuffers()"}, + {QueueSubmitReason::EGLWaitClient, "Queue submission imminent due to eglWaitClient()"}, + {QueueSubmitReason::DeferredFlush, "Queue submission imminent due to deferred flushing"}, + {QueueSubmitReason::GLFinish, "Queue submission imminent due to glFinish()"}, + {QueueSubmitReason::GLFlush, "Queue submission imminent due to glFlush()"}, + {QueueSubmitReason::GLReadPixels, "Queue submission imminent due to glReadPixels()"}, + {QueueSubmitReason::AcquireNextImage, "Queue submission imminent due to acquiring next image"}, + {QueueSubmitReason::ContextChange, "Queue submission imminent due to context change"}, + {QueueSubmitReason::ContextDestruction, "Queue submission imminent due to context destruction"}, + {QueueSubmitReason::ContextPriorityChange, + "Queue submission imminent due to context priority change"}, + {QueueSubmitReason::SurfaceUnMakeCurrent, + "Queue submission imminent due to unmaking current on surface"}, + {QueueSubmitReason::CopyBufferToImageOneOff, + "Queue submission imminent after one-off copying buffer to image"}, + {QueueSubmitReason::CopyBufferToSurfaceImage, + "Queue submission imminent after copying buffer to surface image"}, + {QueueSubmitReason::CopySurfaceImageToBuffer, + "Queue submission imminent after copying surface image to buffer"}, + {QueueSubmitReason::ForeignImageRelease, + "Queue submission imminent due to releasing foreign image"}, + {QueueSubmitReason::ImageUseThenReleaseToExternal, + "Queue submission imminent due to image used in render pass being released"}, + {QueueSubmitReason::TextureReformatToRenderable, + "Queue submission imminent due to reformatting texture to a renderable fallback"}, + {QueueSubmitReason::CopyTextureOnCPU, + "Queue submission imminent due to fallback to CPU when copying texture"}, + {QueueSubmitReason::GenerateMipmapOnCPU, + "Queue submission imminent due to fallback to CPU when generating mipmaps"}, + {QueueSubmitReason::ExternalSemaphoreSignal, + "Queue submission imminent due to external semaphore signal"}, + {QueueSubmitReason::GetQueryResult, "Queue submission imminent after getting query result"}, + {QueueSubmitReason::GetTimestamp, "Queue submission imminent after getting the timestamp"}, + {QueueSubmitReason::SyncCPUGPUTime, + "Queue submission imminent due to synchronizing CPU and GPU time"}, + {QueueSubmitReason::SyncObjectInit, "Queue submission imminent after initializing sync object"}, + {QueueSubmitReason::SyncObjectClientWait, + "Queue submission imminent due to sync object client wait"}, + {QueueSubmitReason::SyncObjectWithFdInit, + "Queue submission imminent due to inserting sync object with file descriptor"}, + {QueueSubmitReason::DeviceLocalBufferMap, + "Queue submission imminent due to mapping device local buffer"}, + {QueueSubmitReason::BufferWriteThenMap, + "Queue submission imminent due to mapping buffer being written to by render pass"}, + {QueueSubmitReason::BufferInUseWhenSynchronizedMap, + "Queue submission imminent due to mapping buffer in use by GPU without " + "GL_MAP_UNSYNCHRONIZED_BIT"}, + {QueueSubmitReason::WaitSemaphore, "Queue submission imminent after waiting for semaphore"}, + {QueueSubmitReason::ExcessivePendingGarbage, + "Queue submission imminent due to exceeding pending garbage memory size threshold"}, + {QueueSubmitReason::OutOfMemory, + "Queue submission imminent due to context finish to mitigate running out of device memory"}, + {QueueSubmitReason::RenderPassCountLimitReached, + "Queue submission imminent due to exceeding the threshold for render pass command count"}, + {QueueSubmitReason::RenderPassCommandLimitReached, + "Queue submission imminent due to exceeding write command limit at draw time"}, + {QueueSubmitReason::BufferToImageUpdateLimitReached, + "Queue submission imminent due to exceeding buffer-to-image update size limit"}, + {QueueSubmitReason::ForceSubmitStagedTexture, + "Queue submission imminent due to staged texture updates"}, + {QueueSubmitReason::DrawOverlay, "Queue submission imminent due to drawing overlay"}, + {QueueSubmitReason::InitNonZeroMemory, + "Queue submission imminent due to initializing non-zero memory"}, +}}; +} // namespace + namespace vk { namespace @@ -83,7 +158,7 @@ constexpr uint32_t kPreferredDefaultUniformBufferSize = 64 * 1024u; // Maximum size to use VMA image suballocation. Any allocation greater than or equal to this // value will use a dedicated VkDeviceMemory. -constexpr size_t kImageSizeThresholdForDedicatedMemoryAllocation = 4 * 1024 * 1024; +constexpr size_t kImageSizeThresholdForDedicatedMemoryAllocation = 8 * 1024 * 1024; // Pipeline cache header version. It should be incremented any time there is an update to the cache // header or data structure. @@ -102,9 +177,6 @@ constexpr uint32_t kPipelineCacheVkUpdatePeriod = 60; // initialization logic simpler. constexpr uint32_t kPreferredVulkanAPIVersion = VK_API_VERSION_1_1; -// Development flag for transition period when both old and new syncval fitlers are used -constexpr bool kSyncValCheckExtraProperties = false; - bool IsVulkan11(uint32_t apiVersion) { return apiVersion >= VK_API_VERSION_1_1; @@ -123,6 +195,12 @@ bool IsRADV(uint32_t vendorId, uint32_t driverId, const char *deviceName) return IsAMD(vendorId) && strstr(deviceName, "RADV") != nullptr; } +bool IsMesaPanVK(uint32_t driverId) +{ + // rely on VkDriverId alone to identify MESA PanVK driver + return driverId == VK_DRIVER_ID_MESA_PANVK; +} + bool IsQualcommOpenSource(uint32_t vendorId, uint32_t driverId, const char *deviceName) { if (!IsQualcomm(vendorId)) @@ -206,12 +284,6 @@ constexpr const char *kSkippedMessages[] = { // http://anglebug.com/42266199 "VUID-vkDestroySemaphore-semaphore-01137", "VUID-vkDestroySemaphore-semaphore-05149", - // https://issuetracker.google.com/303219657 - "VUID-VkGraphicsPipelineCreateInfo-pStages-00738", - // http://anglebug.com/42266334 - "VUID-vkCmdDraw-None-06887", - "VUID-vkCmdDraw-None-06886", - "VUID-vkCmdDrawIndexed-None-06887", // http://anglebug.com/42266819 "VUID-vkCmdDraw-None-09000", "VUID-vkCmdDrawIndexed-None-09002", @@ -226,13 +298,9 @@ constexpr const char *kSkippedMessages[] = { "VUID-vkCmdDrawIndexed-None-07835", "VUID-VkGraphicsPipelineCreateInfo-Input-08733", "VUID-vkCmdDraw-Input-08734", - // https://anglebug.com/42266575#comment4 - "VUID-VkBufferViewCreateInfo-format-08779", // https://anglebug.com/42266639 "VUID-VkVertexInputBindingDivisorDescriptionKHR-divisor-01870", "VUID-VkVertexInputBindingDivisorDescription-divisor-01870", - // https://anglebug.com/42266675 - "VUID-VkGraphicsPipelineCreateInfo-topology-08773", // https://anglebug.com/42265766 "VUID-vkCmdBlitImage-srcImage-00240", // https://anglebug.com/42266678 @@ -265,8 +333,6 @@ constexpr const char *kSkippedMessages[] = { "VUID-VkImportMemoryFdInfoKHR-handleType-00667", // http://anglebug.com/42266904 "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00658", - // https://anglebug.com/42266920 - "VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01912", // https://anglebug.com/42266947 "VUID-VkPipelineVertexInputStateCreateInfo-pNext-pNext", // https://issuetracker.google.com/319228278 @@ -284,6 +350,12 @@ constexpr const char *kSkippedMessages[] = { "VUID-vkCmdDraw-None-09462", // https://anglebug.com/394598758 "VUID-vkBindBufferMemory-size-01037", + // https://anglebug.com/443133082 + "VUID-vkCmdDraw-None-09549", + // https://anglebug.com/470128354 + "VUID-vkCmdEndQuery-None-07007", + // https://anglebug.com/475549551 + "VUID-VkGraphicsPipelineCreateInfo-renderPass-09652", }; // Validation messages that should be ignored only when VK_EXT_primitive_topology_list_restart is @@ -293,6 +365,30 @@ constexpr const char *kNoListRestartSkippedMessages[] = { "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252", }; +// Validation messages that should be ignored only when VK_KHR_maintenance5 is not present. +constexpr const char *kNoMaintenance5SkippedMessages[] = { + // https://anglebug.com/42266575#comment4 + "VUID-VkBufferViewCreateInfo-format-08779", + // https://anglebug.com/42266675 + "VUID-VkGraphicsPipelineCreateInfo-topology-08773", + "VUID-vkCmdDraw-primitiveTopology-10748", + "VUID-vkCmdDrawIndexed-primitiveTopology-10748", + "VUID-vkCmdDrawIndirect-primitiveTopology-10748", + "VUID-vkCmdDrawIndexedIndirect-primitiveTopology-10748", +}; + +// Validation messages that should be ignored only when VK_KHR_maintenance9 is not present. +constexpr const char *kNoMaintenance9SkippedMessages[] = { + // http://issuetracker.google.com/429339330 + "WARNING-VkImageSubresourceRange-layerCount-compatibility", +}; + +// Validation messages that should be ignored only when preferBGR565ToRGB565 is enabled. +constexpr const char *kPreferBGR565SkippedMessages[] = { + // http://anglebug.com/42264464 + "VUID-VkSamplerCustomBorderColorCreateInfoEXT-format-04015", +}; + // Validation messages that should be ignored only when exposeNonConformantExtensionsAndVersions is // enabled on certain test platforms. constexpr const char *kExposeNonConformantSkippedMessages[] = { @@ -349,262 +445,185 @@ constexpr const char *kSkippedMessagesWithDynamicRendering[] = { // 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. constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessages[] = { - // http://anglebug.com/42264929 - // http://anglebug.com/42264934 - { - "SYNC-HAZARD-WRITE-AFTER-WRITE", - "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: " - "SYNC_IMAGE_LAYOUT_TRANSITION, " - "write_barriers: 0", - }, - // These errors are caused by a feedback loop tests that don't produce correct Vulkan to begin - // with. - // http://anglebug.com/42264930 - // http://anglebug.com/42265542 - // - // Occasionally, this is due to VVL's lack of support for some extensions. For example, - // syncval doesn't properly account for VK_EXT_fragment_shader_interlock, which gives - // synchronization guarantees without the need for an image barrier. - // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4387 - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "imageLayout: VK_IMAGE_LAYOUT_GENERAL", - "usage: SYNC_FRAGMENT_SHADER_SHADER_", - }, - // http://anglebug.com/42265049 - { - "SYNC-HAZARD-WRITE-AFTER-WRITE", - "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: " - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, write_barriers: " - "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_" - "STENCIL_ATTACHMENT_WRITE|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_LATE_" - "FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_" - "ATTACHMENT_" - "READ|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE", - }, - {"SYNC-HAZARD-WRITE-AFTER-WRITE", - "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: " - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, write_barriers: " - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_" - "ATTACHMENT_WRITE", - "", - false, - { - "message_type = RenderPassLayoutTransitionError", - "access = SYNC_IMAGE_LAYOUT_TRANSITION", // probably not needed, message_type implies this - "prior_access = " - "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", - "write_barriers = " - "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT|VK_" - "ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", - }}, - // From: TraceTest.manhattan_31 with SwiftShader and - // VulkanPerformanceCounterTest.NewTextureDoesNotBreakRenderPass for both depth and stencil - // aspect. http://anglebug.com/42265196. - // Additionally hit in the asphalt_9 trace // https://issuetracker.google.com/316337308 + // DifferentStencilMasksTest.DrawWithSameEffectiveMask/ES2_Vulkan_SwiftShader + // VulkanPerformanceCounterTest.NewTextureDoesNotBreakRenderPass for both depth and stencil + // Hit in the asphalt_9 + // http://anglebug.com/42265363 + // dead_by_daylight + // From: TraceTest.diablo_immortal http://anglebug.com/42266309 (Linux AMD) {"SYNC-HAZARD-WRITE-AFTER-WRITE", - "with loadOp VK_ATTACHMENT_LOAD_OP_DONT_CARE. Access info (usage: " - "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: " - "SYNC_IMAGE_LAYOUT_TRANSITION", - "", false, { - "message_type = RenderPassLoadOpError", - "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE", + "message_type = BeginRenderingError", "access = " "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" "BIT)", "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", + "command = vkCmdBeginRenderingKHR", + "prior_command = vkCmdPipelineBarrier", + "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE", }}, - // DifferentStencilMasksTest.DrawWithSameEffectiveMask/ES2_Vulkan_SwiftShader - // Also other errors with similar message structure. {"SYNC-HAZARD-WRITE-AFTER-WRITE", - "with loadOp VK_ATTACHMENT_LOAD_OP_DONT_CARE. Access info (usage: " - "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: " - "SYNC_IMAGE_LAYOUT_TRANSITION", - "", false, { - "message_type = BeginRenderingError", - "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE", + "message_type = RenderPassLoadOpError", "access = " "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" "BIT)", "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", + "command = vkCmdBeginRenderPass", + "prior_command = vkCmdPipelineBarrier", + "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE", }}, - // From various tests. The validation layer does not calculate the exact vertexCounts that's - // being accessed. http://anglebug.com/42265220 - {"SYNC-HAZARD-READ-AFTER-WRITE", - "Hazard READ_AFTER_WRITE for vertex", - "usage: SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ", - false, - { - "message_type = DrawVertexBufferError", - "access = " - "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", - }}, - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "Hazard READ_AFTER_WRITE for index", - "usage: SYNC_INDEX_INPUT_INDEX_READ", - }, - { - "SYNC-HAZARD-WRITE-AFTER-READ", - "Hazard WRITE_AFTER_READ for", - "Access info (usage: SYNC_VERTEX_SHADER_SHADER_STORAGE_WRITE, prior_usage: " - "SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ", - }, - {"SYNC-HAZARD-WRITE-AFTER-READ", - "Hazard WRITE_AFTER_READ for dstBuffer VkBuffer", - "Access info (usage: SYNC_COPY_TRANSFER_WRITE, prior_usage: " - "SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ", - false, - {"message_type = BufferRegionError", "resource_parameter = dstBuffer", - "access = VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)", - "prior_access = " - "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)"}}, - { - "SYNC-HAZARD-WRITE-AFTER-READ", - "Hazard WRITE_AFTER_READ for VkBuffer", - "Access info (usage: SYNC_COMPUTE_SHADER_SHADER_STORAGE_WRITE, prior_usage: " - "SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ", - }, - // http://anglebug.com/42266506 (VkNonDispatchableHandle on x86 bots) - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "Hazard READ_AFTER_WRITE for VkBuffer", - "usage: SYNC_VERTEX_SHADER_SHADER_STORAGE_READ", - }, - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "Hazard READ_AFTER_WRITE for VkNonDispatchableHandle", - "usage: SYNC_VERTEX_SHADER_SHADER_STORAGE_READ", - }, - // Coherent framebuffer fetch is enabled on some platforms that are known a priori to have the - // needed behavior, even though this is not specified in the Vulkan spec. These generate - // syncval errors that are benign on those platforms. - // http://anglebug.com/42265363 - // From: TraceTest.dead_by_daylight - // From: TraceTest.genshin_impact + // http://anglebug.com/42265427 + // From: TraceTest.blade_and_soul_revolution + // FramebufferFetchES31.ReopenRenderPass/ES3_1_Vulkan {"SYNC-HAZARD-READ-AFTER-WRITE", - "with loadOp VK_ATTACHMENT_LOAD_OP_LOAD. Access info (usage: " - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ, prior_usage: " - "SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: 0", - "", true, { "message_type = RenderPassLoadOpError", - "load_op = VK_ATTACHMENT_LOAD_OP_LOAD", "access = " "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT)", "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", - "write_barriers = 0", + "command = vkCmdBeginRenderPass", + "prior_command = vkCmdEndRenderPass", + "load_op = VK_ATTACHMENT_LOAD_OP_LOAD", }}, + // http://anglebug.com/42265363 + // http://anglebug.com/415382790 {"SYNC-HAZARD-WRITE-AFTER-WRITE", - "image layout transition (old_layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, " - "new_layout: " - "VK_IMAGE_LAYOUT_GENERAL). Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: " - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, write_barriers:", - "", true, { "message_type = RenderPassLayoutTransitionError", + "access = SYNC_IMAGE_LAYOUT_TRANSITION", + "prior_access = " + "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", + "command = vkCmdBeginRenderPass", + "prior_command = vkCmdEndRenderPass", "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL", "new_layout = VK_IMAGE_LAYOUT_GENERAL", - "access = SYNC_IMAGE_LAYOUT_TRANSITION", // probably not needed, message_type implies this + }}, + // http://anglebug.com/415383266 + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + true, + { + "message_type = RenderPassLayoutTransitionError", + "access = SYNC_IMAGE_LAYOUT_TRANSITION", "prior_access = " "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", + "command = vkCmdBeginRenderPass", + "prior_command = vkCmdDrawIndexed", + "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL", + "new_layout = VK_IMAGE_LAYOUT_GENERAL", }}, + // http://anglebug.com/399191283 + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + {"message_type = BeginRenderingError", + "access = " + "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "prior_command = vkCmdPipelineBarrier", + "command = vkCmdBeginRenderingKHR", "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE"}}, + // https://anglebug.com/400789178, prior_command could be vkCmdEndRenderPass or + // vkCmdEndRenderingKHR + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + {"message_type = ImageBarrierError", "hazard_type = WRITE_AFTER_WRITE", + "access = SYNC_IMAGE_LAYOUT_TRANSITION", + "prior_access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)", + "command = vkCmdPipelineBarrier", "prior_command = vkCmdEndRender"}}, + // https://anglebug.com/400789178 + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + {"message_type = RenderPassAttachmentError", "hazard_type = WRITE_AFTER_WRITE", + "access = " + "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", + "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "command = vkCmdDrawIndexed", + "prior_command = vkCmdEndRenderPass"}}, + // False positive: https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/10667 + {"SYNC-HAZARD-WRITE-AFTER-READ", + false, + {"message_type = DynamicRenderingAttachmentError", "hazard_type = WRITE_AFTER_READ", + "access = " + "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", + "prior_access = VK_PIPELINE_STAGE_2_BLIT_BIT(VK_ACCESS_2_TRANSFER_READ_BIT)", + "command = vkCmdDraw", "prior_command = vkCmdBlitImage"}}, + // https://anglebug.com/456785955 + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + {"hazard_type = WRITE_AFTER_WRITE", + "access = " + "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "prior_access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)", + "command = vkCmdBeginRender", "prior_command = vkCmdEndRender", + "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE"}}, + {"SYNC-HAZARD-READ-AFTER-WRITE", + false, + {"message_type = RenderPassLoadOpError", "hazard_type = READ_AFTER_WRITE", + "access = " + "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT)", + "prior_access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)", + "command = vkCmdBeginRenderPass", "prior_command = vkCmdEndRenderPass", + "load_op = VK_ATTACHMENT_LOAD_OP_LOAD"}}}; + +// Messages that should not be generated if the feature to force-enable providing the size pointer +// to vkCmdBindVertexBuffers2() is disabled. +constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithoutForcedSizePointer[] = { // From: TraceTest.special_forces_group_2 http://anglebug.com/42264123 - { - "SYNC-HAZARD-WRITE-AFTER-READ", - "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: " - "SYNC_FRAGMENT_SHADER_SHADER_", - }, - // http://anglebug.com/42265504 + // http://anglebug.com/397775556 + // From: TraceTest.life_is_strange http://anglebug.com/42266180 (Linux AMD) + // From: TraceTest.diablo_immortal http://anglebug.com/42266309 (Linux AMD) {"SYNC-HAZARD-READ-AFTER-WRITE", - "type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageLayout: " - "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, binding #0, index 0. Access info (usage: " - "SYNC_COMPUTE_SHADER_SHADER_", - "", false}, - // http://anglebug.com/42265925 - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, " - "imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL", - "Access info (usage: SYNC_FRAGMENT_SHADER_SHADER_", - }, - // From: TraceTest.life_is_strange http://anglebug.com/42266180 + false, + { + "message_type = BufferError", + "access = " + "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", + "prior_access = " + "VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)", + "command = vkCmdDrawIndexed", + "prior_command = vkCmdCopyBuffer", + }}, + // http://anglebug.com/394598470 {"SYNC-HAZARD-WRITE-AFTER-READ", - "with storeOp VK_ATTACHMENT_STORE_OP_DONT_CARE. " - "Access info (usage: SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, " - "prior_usage: SYNC_FRAGMENT_SHADER_SHADER_"}, - // From: TraceTest.life_is_strange http://anglebug.com/42266180 - {"SYNC-HAZARD-READ-AFTER-WRITE", - "type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, " - "imageLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL", - "usage: SYNC_FRAGMENT_SHADER_SHADER_"}, - // From: TraceTest.diablo_immortal http://anglebug.com/42266309 - {"SYNC-HAZARD-WRITE-AFTER-WRITE", - "Access info (usage: " - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, prior_usage: " - "SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: 0"}, - // From: TraceTest.diablo_immortal http://anglebug.com/42266309 + false, + { + "message_type = BufferCopyError", + "access = VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)", + "prior_access = " + "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", + "command = vkCmdCopyBuffer", + "prior_command = vkCmdDrawIndexed", + }}, + // https://anglebug.com/443095908 {"SYNC-HAZARD-WRITE-AFTER-READ", - "with loadOp VK_ATTACHMENT_LOAD_OP_DONT_CARE. Access info (usage: " - "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: " - "SYNC_FRAGMENT_SHADER_SHADER_"}, - // From: TraceTest.catalyst_black http://anglebug.com/42266390 + false, + {"message_type = BufferCopyError", "hazard_type = WRITE_AFTER_READ", + "access = " + "VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)", + "prior_access = " + "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", + "command = vkCmdCopyImageToBuffer", "prior_command = vkCmdDraw"}}, {"SYNC-HAZARD-WRITE-AFTER-READ", - "with storeOp VK_ATTACHMENT_STORE_OP_STORE. Access info (usage: " - "SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: " - "SYNC_FRAGMENT_SHADER_SHADER_"}, - // http://anglebug.com/352094384 - { - "SYNC-HAZARD-WRITE-AFTER-WRITE", - "Hazard WRITE_AFTER_WRITE for VkImageView", - "Access info (usage: SYNC_ACCESS_INDEX_NONE, prior_usage: SYNC_IMAGE_LAYOUT_TRANSITION, ", - }, - // http://anglebug.com/394598470 - { - "SYNC-HAZARD-WRITE-AFTER-READ", - "access = VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)", - "prior_access = " - "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", - }, -}; - -// Messages that shouldn't be generated if storeOp=NONE is supported, otherwise they are expected. -constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithoutStoreOpNone[] = { - // These errors are generated when simultaneously using a read-only depth/stencil attachment as - // sampler. This is valid Vulkan. - // - // When storeOp=NONE is not present, ANGLE uses storeOp=STORE, but considers the image read-only - // and produces a hazard. ANGLE relies on storeOp=NONE and so this is not expected to be worked - // around. - // - // With storeOp=NONE, there is another bug where a depth/stencil attachment may use storeOp=NONE - // for depth while storeOp=DONT_CARE for stencil, and the latter causes a synchronization error - // (similarly to the previous case as DONT_CARE is also a write operation). - // http://anglebug.com/42264496 - { - "SYNC-HAZARD-WRITE-AFTER-READ", - "VK_ATTACHMENT_STORE_OP_STORE. Access info (usage: " - "SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE", - "usage: SYNC_FRAGMENT_SHADER_SHADER_", - }, - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "imageLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL", - "usage: SYNC_FRAGMENT_SHADER_SHADER_", - }, - // From: TraceTest.antutu_refinery http://anglebug.com/42265159 - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "imageLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL", - "usage: SYNC_COMPUTE_SHADER_SHADER_SAMPLED_READ", - }, + false, + {"message_type = BufferCopyError", "hazard_type = WRITE_AFTER_READ", + "access = " + "VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)", + "prior_access = " + "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", + "command = vkCmdCopyImageToBuffer", "prior_command = vkCmdDrawIndexed"}}, + {"SYNC-HAZARD-WRITE-AFTER-READ", + false, + {"message_type = SubmitTimeError", "hazard_type = WRITE_AFTER_READ", + "prior_access = " + "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)", + "read_barriers = 0", "command = vkCmdCopyImageToBuffer", "prior_command = vkCmdDrawIndexed"}}, }; // Messages that shouldn't be generated if both loadOp=NONE and storeOp=NONE are supported, @@ -613,47 +632,127 @@ constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithoutLoadStoreOpNon // This error is generated for multiple reasons: // // - http://anglebug.com/42264926 - // - http://anglebug.com/42263911: This is resolved with storeOp=NONE - { - "SYNC-HAZARD-WRITE-AFTER-WRITE", - "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: " - "SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, write_barriers: 0", - }, - // http://anglebug.com/42264926 - // http://anglebug.com/42265079 - // http://anglebug.com/42264496 - { - "SYNC-HAZARD-WRITE-AFTER-WRITE", - "with loadOp VK_ATTACHMENT_LOAD_OP_DONT_CARE. Access info " - "(usage: " - "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE", - }, + // + // Observed on AMD when running the following test: + // + // dEQP-GLES2.functional.shaders.builtin_variable.pointcoord + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + { + "message_type = BeginRenderingError", + "hazard_type = WRITE_AFTER_WRITE", + "access = " + "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", + "write_barriers = " + "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT|VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(" + "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT)", + "command = vkCmdBeginRenderingKHR", + "prior_command = vkCmdPipelineBarrier", + "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE", + }}, + // Observed on SwiftShader when running the following tests: + // + // dEQP-GLES3.functional.fbo.blit.default_framebuffer.rgb8 + // TraceTest.life_is_strange + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + { + "message_type = ImageBarrierError", + "hazard_type = WRITE_AFTER_WRITE", + "access = SYNC_IMAGE_LAYOUT_TRANSITION", + "prior_access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "write_barriers = 0", + "command = vkCmdPipelineBarrier", + "prior_command = vkCmdEndRenderingKHR", + }}, + // Observed on SwiftShader when running the following tests: + // + // ReadOnlyFeedbackLoopTest.ReadOnlyDepthFeedbackLoopDrawThenDepthStencilClear/ES3_Vulkan_SwiftShader + // VulkanPerformanceCounterTest.ClearColorBufferAndReadOnlyDepthStencilUsesSingleRenderPass* + // VulkanPerformanceCounterTest.ReadOnlyDepthStencilFeedbackLoopUsesSingleRenderPass/ES3_Vulkan_SwiftShader_PreferMonolithicPipelinesOverLibraries_NoMergeProgramPipelineCachesToGlobalCache + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + { + "message_type = ImageBarrierError", + "hazard_type = WRITE_AFTER_WRITE", + "access = SYNC_IMAGE_LAYOUT_TRANSITION", + "prior_access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "write_barriers = 0", + "command = vkCmdWaitEvents", + "prior_command = vkCmdEndRenderingKHR", + }}, + // Observed on old drivers without dynamic rendering and no support for the S8 format when + // running the following test: + // + // ClearTextureEXTTest.StencilTexture/ES3_Vulkan + // + // In this case ANGLE uses LOAD_OP_DONT_CARE and STORE_OP_DONT_CARE for the emulated depth + // channel. + // + // Similarly, in the following test: + // + // TraceTest.scary_teacher_3d + // + // LOAD_OP_LOAD and STORE_OP_STORE are used to preserve the depth channel without the NONE ops. + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + { + "message_type = RenderPassStoreOpError", + "hazard_type = WRITE_AFTER_WRITE", + "access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", + "write_barriers = " + "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT|VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(" + "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT)", + "command = vkCmdEndRenderPass", + "prior_command = vkCmdPipelineBarrier", + "store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE", + }}, + {"SYNC-HAZARD-WRITE-AFTER-WRITE", + false, + { + "message_type = RenderPassStoreOpError", + "hazard_type = WRITE_AFTER_WRITE", + "access = " + "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_" + "BIT)", + "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", + "write_barriers = " + "VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT|VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT|VK_" + "PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT)", + "command = vkCmdEndRenderPass", + "prior_command = vkCmdPipelineBarrier", + "store_op = VK_ATTACHMENT_STORE_OP_STORE", + }}, }; // Messages that are only generated with MSRTT emulation. Some of these are syncval bugs (discussed // in https://gitlab.khronos.org/vulkan/vulkan/-/issues/3840) constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithMSRTTEmulation[] = { - // False positive: https://gitlab.khronos.org/vulkan/vulkan/-/issues/3840 - { - "SYNC-HAZARD-READ-AFTER-WRITE", - "during depth/stencil resolve read", - "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ", - }, // Unknown whether ANGLE or syncval bug. + // To repro: see http://anglebug.com/40644740#comment69 {"SYNC-HAZARD-WRITE-AFTER-WRITE", - "image layout transition (old_layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, " - "new_layout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL). Access info (usage: " - "SYNC_IMAGE_LAYOUT_TRANSITION", - "", false, // TODO: it seems if this filter is removed then the error will be // intersepted by a different filter. Investigate the nature of the // error if necessary how to improve its detection. { "message_type = RenderPassLayoutTransitionError", + "access = SYNC_IMAGE_LAYOUT_TRANSITION", + "prior_access = " + "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)", + "command = vkCmdBeginRenderPass", + "prior_command = vkCmdEndRenderPass", "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL", "new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL", - "access = SYNC_IMAGE_LAYOUT_TRANSITION", // probably not needed, message_type implies this }}, }; @@ -663,12 +762,17 @@ enum class DebugMessageReport Print, }; -bool IsMessageInSkipList(const char *message, +bool IsMessageInSkipList(const char *messageId, + const char *message, const char *const skippedList[], size_t skippedListSize) { for (size_t index = 0; index < skippedListSize; ++index) { + if (strstr(messageId, skippedList[index]) != nullptr) + { + return true; + } if (strstr(message, skippedList[index]) != nullptr) { return true; @@ -678,6 +782,35 @@ bool IsMessageInSkipList(const char *message, return false; } +bool SyncvalMessageMatchesSkip(const char *messageId, + const char *message, + const vk::SkippedSyncvalMessage &skip) +{ + // TODO(http://anglebug.com/391284743): Ongoing transition: textual matches -> extraProperties. + // The skip should include at least one extraProperty + ASSERT(skip.extraProperties[0]); + + if (strstr(messageId, skip.messageId) == nullptr) + { + return false; + } + // Check that all extraProperties entries are present in the message + bool mismatch = false; + for (uint32_t i = 0; i < kMaxSyncValExtraProperties; i++) + { + if (skip.extraProperties[i] == nullptr) + { + break; + } + if (strstr(message, skip.extraProperties[i]) == nullptr) + { + mismatch = true; + break; + } + } + return !mismatch; +} + // Suppress validation errors that are known. Returns DebugMessageReport::Ignore in that case. DebugMessageReport ShouldReportDebugMessage(Renderer *renderer, const char *messageId, @@ -690,7 +823,7 @@ DebugMessageReport ShouldReportDebugMessage(Renderer *renderer, // Check with non-syncval messages: const std::vector &skippedMessages = renderer->getSkippedValidationMessages(); - if (IsMessageInSkipList(message, skippedMessages.data(), skippedMessages.size())) + if (IsMessageInSkipList(messageId, message, skippedMessages.data(), skippedMessages.size())) { return DebugMessageReport::Ignore; } @@ -698,63 +831,37 @@ DebugMessageReport ShouldReportDebugMessage(Renderer *renderer, // Then check with syncval messages: const bool isColorFramebufferFetchUsed = renderer->isColorFramebufferFetchUsed(); - for (const vk::SkippedSyncvalMessage &msg : renderer->getSkippedSyncvalMessages()) + for (const vk::SkippedSyncvalMessage &skip : renderer->getSkippedSyncvalMessages()) { - if (kSyncValCheckExtraProperties && msg.extraProperties[0]) + if (!SyncvalMessageMatchesSkip(messageId, message, skip)) { - if (strstr(messageId, msg.messageId) == nullptr) - { - continue; - } - bool mismatch = false; - for (uint32_t i = 0; i < kMaxSyncValExtraProperties; i++) - { - if (msg.extraProperties[i] == nullptr) - { - break; - } - if (strstr(message, msg.extraProperties[i]) == nullptr) - { - mismatch = true; - break; - } - } - if (mismatch) - { - continue; - } + continue; } - else + + if (skip.isDueToNonConformantCoherentColorFramebufferFetch) { - if (strstr(messageId, msg.messageId) == nullptr || - strstr(message, msg.messageContents1) == nullptr || - strstr(message, msg.messageContents2) == nullptr) + // If the error is due to exposing coherent framebuffer fetch (without + // VK_EXT_rasterization_order_attachment_access), but framebuffer fetch has not been + // used by the application, report it. + // + // Note that currently syncval doesn't support the + // VK_EXT_rasterization_order_attachment_access extension, so the syncval messages would + // continue to be produced despite the extension. + constexpr bool kSyncValSupportsRasterizationOrderExtension = false; + const bool hasRasterizationOrderExtension = + renderer->getFeatures().supportsRasterizationOrderAttachmentAccess.enabled && + kSyncValSupportsRasterizationOrderExtension; + if (!isColorFramebufferFetchUsed || hasRasterizationOrderExtension) { - continue; + return DebugMessageReport::Print; } } - // If the error is due to exposing coherent framebuffer fetch (without - // VK_EXT_rasterization_order_attachment_access), but framebuffer fetch has not been used by - // the application, report it. - // - // Note that currently syncval doesn't support the - // VK_EXT_rasterization_order_attachment_access extension, so the syncval messages would - // continue to be produced despite the extension. - constexpr bool kSyncValSupportsRasterizationOrderExtension = false; - const bool hasRasterizationOrderExtension = - renderer->getFeatures().supportsRasterizationOrderAttachmentAccess.enabled && - kSyncValSupportsRasterizationOrderExtension; - if (msg.isDueToNonConformantCoherentColorFramebufferFetch && - (!isColorFramebufferFetchUsed || hasRasterizationOrderExtension)) - { - return DebugMessageReport::Print; - } - - // Otherwise ignore the message + // Ignore the message as it matched one the the skips return DebugMessageReport::Ignore; } + // Message didn't match any skips, report return DebugMessageReport::Print; } @@ -1655,7 +1762,7 @@ angle::Result GetAndDecompressPipelineCacheVk(vk::ErrorContext *context, constexpr char kEnableDebugMarkersVarName[] = "ANGLE_ENABLE_DEBUG_MARKERS"; constexpr char kEnableDebugMarkersPropertyName[] = "debug.angle.markers"; -ANGLE_INLINE gl::ShadingRate GetShadingRateFromVkExtent(const VkExtent2D &extent) +ANGLE_INLINE gl::ShadingRate GetShadingRateEXTFromVkExtent(const VkExtent2D &extent) { if (extent.width == 1) { @@ -1667,6 +1774,10 @@ ANGLE_INLINE gl::ShadingRate GetShadingRateFromVkExtent(const VkExtent2D &extent { return gl::ShadingRate::_1x2; } + else if (extent.height == 4) + { + return gl::ShadingRate::_1x4; + } } else if (extent.width == 2) { @@ -1678,10 +1789,18 @@ ANGLE_INLINE gl::ShadingRate GetShadingRateFromVkExtent(const VkExtent2D &extent { return gl::ShadingRate::_2x2; } + else if (extent.height == 4) + { + return gl::ShadingRate::_2x4; + } } else if (extent.width == 4) { - if (extent.height == 2) + if (extent.height == 1) + { + return gl::ShadingRate::_4x1; + } + else if (extent.height == 2) { return gl::ShadingRate::_4x2; } @@ -1731,9 +1850,9 @@ void DumpPipelineCacheGraph(Renderer *renderer, const std::ostringstream &graph) bool CanSupportMSRTSSForRGBA8(Renderer *renderer) { // The support is checked for a basic 2D texture. - constexpr VkImageUsageFlags kImageUsageFlags = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + constexpr VkImageUsageFlags kImageUsageFlags = vk::kImageUsageTransferBits | + VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; VkImageCreateFlags imageCreateFlags = GetMinimalImageCreateFlags(renderer, gl::TextureType::_2D, kImageUsageFlags) | VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT; @@ -1749,6 +1868,104 @@ bool CanSupportMSRTSSForRGBA8(Renderer *renderer) return supportsMSRTTUsageRGBA8 && supportsMSRTTUsageRGBA8SRGB; } + +VkResult RetrieveDeviceLostInfoFromDevice(VkDevice device, + VkPhysicalDeviceFaultFeaturesEXT faultFeatures) +{ + // For VkDeviceFaultAddressTypeEXT in VK_EXT_device_fault + constexpr const char *kDeviceFaultAddressTypeMessage[] = { + "None", + "InvalidRead", + "InvalidWrite", + "InvalidExecute", + "InstructionPointerUnknown", + "InstructionPointerInvalid", + "InstructionPointerFault", + }; + + // At first, the data regarding the number of faults is collected, so the proper allocations can + // be made to store the incoming data. + VkDeviceFaultCountsEXT faultCounts = {}; + faultCounts.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT; + + VkResult result = vkGetDeviceFaultInfoEXT(device, &faultCounts, nullptr); + if (result != VK_SUCCESS) + { + return result; + } + + VkDeviceFaultInfoEXT faultInfos = {}; + faultInfos.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT; + + std::vector addressInfos(faultCounts.addressInfoCount); + faultInfos.pAddressInfos = addressInfos.data(); + + std::vector vendorInfos(faultCounts.vendorInfoCount); + faultInfos.pVendorInfos = vendorInfos.data(); + + // The vendor binary data will be logged in chunks of 4 bytes. + uint32_t vendorBinaryDataChunkCount = + (static_cast(faultCounts.vendorBinarySize) + 3) / 4; + std::vector vendorBinaryDataChunks(vendorBinaryDataChunkCount, 0); + faultInfos.pVendorBinaryData = vendorBinaryDataChunks.data(); + + result = vkGetDeviceFaultInfoEXT(device, &faultCounts, &faultInfos); + if (result != VK_SUCCESS) + { + return result; + } + + // Collect the fault information from the device. + std::stringstream faultString; + faultString << "Fault description: <" << faultInfos.description << ">" << std::endl; + + for (auto &addressFault : addressInfos) + { + // Based on the spec, The address precision is a power of two, and shows the lower and upper + // address ranges where the error could be: + // - lowerAddress = (reportedAddress & ~(addressPrecision - 1)) + // - upperAddress = (reportedAddress | (addressPrecision - 1)) + // For example, if the reported address is 0x12345 and the precision is 16, it shows that + // the address could be between 0x12340 and 0x1234F. + faultString << "--> Address fault reported at 0x" << std::hex + << addressFault.reportedAddress << " | Precision range: 0x" + << addressFault.addressPrecision << " (" << std::dec + << std::log2(addressFault.addressPrecision) << " bits) | Operation: " + << kDeviceFaultAddressTypeMessage[addressFault.addressType] << std::endl; + } + + for (auto &vendorFault : vendorInfos) + { + faultString << "--> Vendor-specific fault reported (Code " << std::dec + << vendorFault.vendorFaultCode << "): <" << vendorFault.description + << "> | Fault Data: 0x" << std::hex << vendorFault.vendorFaultData << std::endl; + } + + if (faultFeatures.deviceFaultVendorBinary) + { + // The binary data must start with the header in the format of the following type: + // - VkDeviceFaultVendorBinaryHeaderVersionOneEXT (56 bytes) + faultString << "--> Vendor-specific binary crash dump (" << faultCounts.vendorBinarySize + << " bytes, in hex):" << std::endl; + + constexpr uint32_t kVendorBinaryDataChunksPerLine = 8; + for (uint32_t i = 0; i < vendorBinaryDataChunkCount; i++) + { + faultString << "0x" << std::hex << std::setw(8) << std::setfill('0') + << vendorBinaryDataChunks[i] + << ((i + 1) % kVendorBinaryDataChunksPerLine != 0 ? " " : "\n"); + } + faultString << std::endl; + } + else + { + faultString << "--> Vendor-specific binary crash dump not available." << std::endl; + } + + // Output the log stream. + WARN() << faultString.str(); + return VK_SUCCESS; +} } // namespace // OneOffCommandPool implementation. @@ -1867,7 +2084,13 @@ Renderer::Renderer() mCleanUpThread(this, &mCommandQueue), mSupportedBufferWritePipelineStageMask(0), mSupportedVulkanShaderStageMask(0), - mMemoryAllocationTracker(MemoryAllocationTracker(this)) + mMemoryAllocationTracker(MemoryAllocationTracker(this)), + mMaxBufferMemorySizeLimit(0), + mNativeVectorWidthDouble(0), + mNativeVectorWidthHalf(0), + mPreferredVectorWidthDouble(0), + mPreferredVectorWidthHalf(0), + mMinRPWriteCommandCountToEarlySubmit(UINT32_MAX) { VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags}; mFormatProperties.fill(invalid); @@ -1904,6 +2127,8 @@ void Renderer::onDestroy(vk::ErrorContext *context) handleDeviceLost(); } + (void)(finishResourceUse(context, mSubmittedResourceUse)); + if (mPlaceHolderDescriptorSetLayout) { ASSERT(mPlaceHolderDescriptorSetLayout.unique()); @@ -1917,6 +2142,8 @@ void Renderer::onDestroy(vk::ErrorContext *context) cleanupGarbage(nullptr); ASSERT(!hasSharedGarbage()); ASSERT(mOrphanedBufferBlockList.empty()); + ASSERT(mOrphanedSamplers.empty()); + ASSERT(mOrphanedSamplerYcbcrConversions.empty()); mRefCountedEventRecycler.destroy(mDevice); @@ -1928,8 +2155,6 @@ void Renderer::onDestroy(vk::ErrorContext *context) mPipelineCacheInitialized = false; mPipelineCache.destroy(mDevice); - mSamplerCache.destroy(this); - mYuvConversionCache.destroy(this); mVkFormatDescriptorCountMap.clear(); mOutsideRenderPassCommandBufferRecycler.onDestroy(); @@ -1987,6 +2212,15 @@ void Renderer::onDestroy(vk::ErrorContext *context) } } +VkResult Renderer::retrieveDeviceLostDetails() const +{ + if (!getFeatures().supportsDeviceFault.enabled) + { + return VK_SUCCESS; + } + return RetrieveDeviceLostInfoFromDevice(mDevice, mFaultFeatures); +} + void Renderer::notifyDeviceLost() { mDeviceLost = true; @@ -2103,14 +2337,25 @@ angle::Result Renderer::enableInstanceExtensions(vk::ErrorContext *context, mEnabledInstanceExtensions.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); } + const bool hasSurfaceMaintenance1EXT = + ExtensionFound(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME, instanceExtensionNames); + const bool hasSurfaceMaintenance1KHR = + ExtensionFound(VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME, instanceExtensionNames); + ANGLE_FEATURE_CONDITION( &mFeatures, supportsSurfaceMaintenance1, - !isMockICDEnabled() && ExtensionFound(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME, - instanceExtensionNames)); + !isMockICDEnabled() && (hasSurfaceMaintenance1KHR || hasSurfaceMaintenance1EXT)); if (mFeatures.supportsSurfaceMaintenance1.enabled) { - mEnabledInstanceExtensions.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME); + if (hasSurfaceMaintenance1KHR) + { + mEnabledInstanceExtensions.push_back(VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME); + } + if (hasSurfaceMaintenance1EXT) + { + mEnabledInstanceExtensions.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME); + } } } @@ -2184,7 +2429,7 @@ angle::Result Renderer::initialize(vk::ErrorContext *context, volkInitializeCustom(vulkanLoaderGetInstanceProcAddr); uint32_t ver = volkGetInstanceVersion(); - if (!IsAndroid() && ver < VK_MAKE_VERSION(1, 1, 91)) + if (!IsAndroid() && ver < VK_MAKE_API_VERSION(0, 1, 1, 91)) { // http://crbug.com/1205999 - non-Android Vulkan Loader versions before 1.1.91 have a // bug which prevents loading VK_EXT_debug_utils function pointers. @@ -2421,19 +2666,27 @@ angle::Result Renderer::initialize(vk::ErrorContext *context, mQueueFamilyProperties.data()); uint32_t queueFamilyMatchCount = 0; - // Try first for a protected graphics queue family - uint32_t firstGraphicsQueueFamily = vk::QueueFamily::FindIndex( - mQueueFamilyProperties, - (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_PROTECTED_BIT), 0, - &queueFamilyMatchCount); - // else just a graphics queue family + + VkQueueFlags queueFamilyBits = VK_QUEUE_FLAG_BITS_MAX_ENUM; + uint32_t firstQueueFamily = QueueFamily::kInvalidIndex; + if (nativeWindowSystem == angle::NativeWindowSystem::NullCompute) + { + queueFamilyBits = VK_QUEUE_COMPUTE_BIT; + firstQueueFamily = + QueueFamily::FindIndex(mQueueFamilyProperties, queueFamilyBits, VK_QUEUE_PROTECTED_BIT, + VK_QUEUE_GRAPHICS_BIT, &queueFamilyMatchCount); + } if (queueFamilyMatchCount == 0) { - firstGraphicsQueueFamily = vk::QueueFamily::FindIndex( - mQueueFamilyProperties, (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT), 0, - &queueFamilyMatchCount); + queueFamilyBits = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT; + firstQueueFamily = + QueueFamily::FindIndex(mQueueFamilyProperties, queueFamilyBits, VK_QUEUE_PROTECTED_BIT, + 0, &queueFamilyMatchCount); } - ANGLE_VK_CHECK(context, queueFamilyMatchCount > 0, VK_ERROR_INITIALIZATION_FAILED); + + ANGLE_VK_CHECK(context, + queueFamilyMatchCount > 0 && firstQueueFamily != QueueFamily::kInvalidIndex, + VK_ERROR_INITIALIZATION_FAILED); // Store the physical device memory properties so we can find the right memory pools. mMemoryProperties.init(mPhysicalDevice); @@ -2457,7 +2710,7 @@ angle::Result Renderer::initialize(vk::ErrorContext *context, // for the best. We cannot wait for a window surface to know which supports present because of // EGL_KHR_surfaceless_context or simply pbuffers. So far, only MoltenVk seems to expose // multiple queue families, and using the first queue family is fine with it. - ANGLE_TRY(createDeviceAndQueue(context, firstGraphicsQueueFamily)); + ANGLE_TRY(createDeviceAndQueue(context, firstQueueFamily)); // Initialize the format table. mFormatTable.initialize(this, &mNativeTextureCaps); @@ -2487,10 +2740,22 @@ angle::Result Renderer::initialize(vk::ErrorContext *context, angle::Result Renderer::initializeMemoryAllocator(vk::ErrorContext *context) { - // This number matches Chromium and was picked by looking at memory usage of + mTileMemoyTypeIndex = kInvalidMemoryTypeIndex; + if (mFeatures.supportsTileMemoryHeap.enabled) + { + mTileMemoyTypeIndex = mMemoryProperties.findTileMemoryTypeIndex(); + ASSERT(mTileMemoyTypeIndex != kInvalidMemoryTypeIndex); + } + + // The preferred heap block size was picked by looking at memory usage of // Android apps. The allocator will start making blocks at 1/8 the max size // and builds up block size as needed before capping at the max set here. - mPreferredLargeHeapBlockSize = 4 * 1024 * 1024; + mPreferredLargeHeapBlockSize = 8 * 1024 * 1024; + + // The first allocated buffer block from an empty buffer pool has a smaller size in order to + // reduce the memory footprint. + mPreferredInitialBufferBlockSize = 1 * 1024 * 1024; + ASSERT(mPreferredInitialBufferBlockSize <= mPreferredLargeHeapBlockSize); // Create VMA allocator ANGLE_VK_TRY(context, @@ -2656,7 +2921,8 @@ angle::Result Renderer::initializeMemoryAllocator(vk::ErrorContext *context) // (feature) // rasterizationOrderStencilAttachmentAccess // (feature) -// - VK_EXT_swapchain_maintenance1: swapchainMaintenance1 (feature) +// - VK_KHR_swapchain_maintenance1 or +// VK_EXT_swapchain_maintenance1: swapchainMaintenance1 (feature) // - VK_EXT_legacy_dithering: supportsLegacyDithering (feature) // - VK_EXT_physical_device_drm: hasPrimary (property), // hasRender (property) @@ -2670,7 +2936,17 @@ angle::Result Renderer::initializeMemoryAllocator(vk::ErrorContext *context) // - VK_EXT_shader_atomic_float shaderImageFloat32Atomics (feature) // - VK_EXT_image_compression_control imageCompressionControl (feature) // - VK_EXT_image_compression_control_swapchain imageCompressionControlSwapchain (feature) +// - VK_EXT_device_fault deviceFault (feature), +// deviceFaultVendorBinary (feature) +// - VK_EXT_astc_decode_mode decodeModeSharedExponent (feature) +// - VK_KHR_unified_image_layouts unifiedImageLayouts (feature) +// - VK_EXT_global_priority_query globalPriorityQuery (feature) +// - VK_EXT_external_memory_host minImportedHostPointerAlignment (property) +// - VK_QCOM_tile_memory_heap tileMemoryHeapFeatures (feature) +// tileMemoryHeapProperties (property) +// - VK_EXT_texture_compression_astc_3d textureCompressionASTC_3D (feature) // + void Renderer::appendDeviceExtensionFeaturesNotPromoted( const vk::ExtensionNameList &deviceExtensionNames, VkPhysicalDeviceFeatures2KHR *deviceFeatures, @@ -2787,7 +3063,8 @@ void Renderer::appendDeviceExtensionFeaturesNotPromoted( vk::AddToPNextChain(deviceFeatures, &mShaderAtomicFloatFeatures); } - if (ExtensionFound(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, deviceExtensionNames)) + if (ExtensionFound(VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, deviceExtensionNames) || + ExtensionFound(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, deviceExtensionNames)) { vk::AddToPNextChain(deviceFeatures, &mSwapchainMaintenance1Features); } @@ -2839,6 +3116,11 @@ void Renderer::appendDeviceExtensionFeaturesNotPromoted( vk::AddToPNextChain(deviceFeatures, &mDynamicRenderingLocalReadFeatures); } + if (ExtensionFound(VK_KHR_UNIFIED_IMAGE_LAYOUTS_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mUnifiedImageLayoutsFeatures); + } + if (ExtensionFound(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, deviceExtensionNames)) { vk::AddToPNextChain(deviceFeatures, &mBlendOperationAdvancedFeatures); @@ -2853,6 +3135,32 @@ void Renderer::appendDeviceExtensionFeaturesNotPromoted( { vk::AddToPNextChain(deviceFeatures, &mImageCompressionControlSwapchainFeatures); } + if (ExtensionFound(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mFaultFeatures); + } + if (ExtensionFound(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mPhysicalDeviceAstcDecodeFeatures); + } + if (ExtensionFound(VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mPhysicalDeviceGlobalPriorityQueryFeatures); + } + if (ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceProperties, &mExternalMemoryHostProperties); + } + if (ExtensionFound(VK_EXT_TEXTURE_COMPRESSION_ASTC_3D_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mTextureCompressionASTC3DFeatures); + } + + if (ExtensionFound(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mTileMemoryHeapFeatures); + vk::AddToPNextChain(deviceProperties, &mTileMemoryHeapProperties); + } } // The following features and properties used by ANGLE have been promoted to Vulkan 1.1: @@ -2920,6 +3228,9 @@ void Renderer::appendDeviceExtensionFeaturesPromotedTo11( // shaderSignedZeroInfNanPreserveFloat32 (property) // shaderSignedZeroInfNanPreserveFloat64 (property) // - VK_KHR_uniform_buffer_standard_layout: uniformBufferStandardLayout (feature) +// - VK_KHR_buffer_device_address: bufferDeviceAddress (feature) +// - VK_KHR_shader_atomic_int64: shaderBufferInt64Atomics (feature) +// shaderSharedInt64Atomics (feature) // // Note that supportedDepthResolveModes is used just to check if the property struct is populated. // ANGLE always uses VK_RESOLVE_MODE_SAMPLE_ZERO_BIT for both depth and stencil, and support for @@ -2979,6 +3290,16 @@ void Renderer::appendDeviceExtensionFeaturesPromotedTo12( { vk::AddToPNextChain(deviceFeatures, &mUniformBufferStandardLayoutFeatures); } + + if (ExtensionFound(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mBufferDeviceAddressFeatures); + } + + if (ExtensionFound(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mShaderAtomicInt64Features); + } } // The following features and properties used by ANGLE have been promoted to Vulkan 1.3: @@ -2990,6 +3311,7 @@ void Renderer::appendDeviceExtensionFeaturesPromotedTo12( // - VK_KHR_dynamic_rendering: dynamicRendering (feature) // - VK_KHR_maintenance5: maintenance5 (feature) // - VK_EXT_texture_compression_astc_hdr: textureCompressionASTC_HDR(feature) +// - VK_KHR_shader_integer_dot_product: shaderIntegerDotProduct (feature) // // Note that VK_EXT_extended_dynamic_state2 is partially promoted to Vulkan 1.3. If ANGLE creates a // Vulkan 1.3 device, it would still need to enable this extension separately for @@ -3029,6 +3351,12 @@ void Renderer::appendDeviceExtensionFeaturesPromotedTo13( { vk::AddToPNextChain(deviceFeatures, &mTextureCompressionASTCHDRFeatures); } + + if (ExtensionFound(VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME, deviceExtensionNames)) + { + vk::AddToPNextChain(deviceFeatures, &mShaderIntegerDotProductFeatures); + vk::AddToPNextChain(deviceProperties, &mShaderIntegerDotProductProperties); + } } void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames) @@ -3097,6 +3425,9 @@ void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceE mMaintenance3Properties = {}; mMaintenance3Properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; + mFaultFeatures = {}; + mFaultFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT; + mDriverProperties = {}; mDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; @@ -3191,7 +3522,7 @@ void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceE mSwapchainMaintenance1Features = {}; mSwapchainMaintenance1Features.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT; + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR; mDitheringFeatures = {}; mDitheringFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT; @@ -3247,6 +3578,42 @@ void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceE mUniformBufferStandardLayoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES; + mPhysicalDeviceAstcDecodeFeatures = {}; + mPhysicalDeviceAstcDecodeFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT; + + mUnifiedImageLayoutsFeatures = {}; + mUnifiedImageLayoutsFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR; + + mShaderIntegerDotProductFeatures = {}; + mShaderIntegerDotProductFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES; + + mShaderIntegerDotProductProperties = {}; + mShaderIntegerDotProductProperties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES; + + mPhysicalDeviceGlobalPriorityQueryFeatures = {}; + mPhysicalDeviceGlobalPriorityQueryFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT; + + mExternalMemoryHostProperties = {}; + mExternalMemoryHostProperties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT; + + mBufferDeviceAddressFeatures = {}; + mBufferDeviceAddressFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; + + mShaderAtomicInt64Features = {}; + mShaderAtomicInt64Features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES; + + mTextureCompressionASTC3DFeatures = {}; + mTextureCompressionASTC3DFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_3D_FEATURES_EXT; + #if defined(ANGLE_PLATFORM_ANDROID) mExternalFormatResolveFeatures = {}; mExternalFormatResolveFeatures.sType = @@ -3257,6 +3624,13 @@ void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceE VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID; #endif + mTileMemoryHeapFeatures = {}; + mTileMemoryHeapFeatures.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_MEMORY_HEAP_FEATURES_QCOM; + mTileMemoryHeapProperties = {}; + mTileMemoryHeapProperties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_MEMORY_HEAP_PROPERTIES_QCOM; + // Query features and properties. VkPhysicalDeviceFeatures2KHR deviceFeatures = {}; deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; @@ -3333,21 +3707,33 @@ void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceE mTextureCompressionASTCHDRFeatures.pNext = nullptr; mUniformBufferStandardLayoutFeatures.pNext = nullptr; mMaintenance3Properties.pNext = nullptr; + mFaultFeatures.pNext = nullptr; + mPhysicalDeviceAstcDecodeFeatures.pNext = nullptr; + mUnifiedImageLayoutsFeatures.pNext = nullptr; + mShaderIntegerDotProductFeatures.pNext = nullptr; + mShaderIntegerDotProductProperties.pNext = nullptr; + mPhysicalDeviceGlobalPriorityQueryFeatures.pNext = nullptr; + mExternalMemoryHostProperties.pNext = nullptr; + mBufferDeviceAddressFeatures.pNext = nullptr; + mShaderAtomicInt64Features.pNext = nullptr; + mTextureCompressionASTC3DFeatures.pNext = nullptr; #if defined(ANGLE_PLATFORM_ANDROID) mExternalFormatResolveFeatures.pNext = nullptr; mExternalFormatResolveProperties.pNext = nullptr; #endif + mTileMemoryHeapFeatures.pNext = nullptr; + mTileMemoryHeapProperties.pNext = nullptr; } // See comment above appendDeviceExtensionFeaturesNotPromoted. Additional extensions are enabled // here which don't have feature structs: // // - VK_KHR_shared_presentable_image +// - VK_EXT_device_memory_report // - VK_EXT_memory_budget // - VK_KHR_incremental_present // - VK_EXT_queue_family_foreign // - VK_ANDROID_external_memory_android_hardware_buffer -// - VK_GGP_frame_token // - VK_KHR_external_memory_fd // - VK_KHR_external_memory_fuchsia // - VK_KHR_external_semaphore_fd @@ -3398,15 +3784,6 @@ void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &de ASSERT(!mFeatures.supportsAndroidHardwareBuffer.enabled); #endif -#if defined(ANGLE_PLATFORM_GGP) - if (mFeatures.supportsGGPFrameToken.enabled) - { - mEnabledDeviceExtensions.push_back(VK_GGP_FRAME_TOKEN_EXTENSION_NAME); - } -#else - ASSERT(!mFeatures.supportsGGPFrameToken.enabled); -#endif - if (mFeatures.supportsExternalMemoryFd.enabled) { mEnabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); @@ -3504,11 +3881,16 @@ void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &de { ASSERT(mMemoryReportFeatures.deviceMemoryReport); mEnabledDeviceExtensions.push_back(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mMemoryReportFeatures); } - if (mFeatures.supportsExternalMemoryDmaBufAndModifiers.enabled) + if (mFeatures.supportsExternalMemoryDmaBuf.enabled) { mEnabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME); + } + + if (mFeatures.supportsImageDrmFormatModifier.enabled) + { mEnabledDeviceExtensions.push_back(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME); } @@ -3608,7 +3990,11 @@ void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &de if (mFeatures.supportsSwapchainMaintenance1.enabled) { - mEnabledDeviceExtensions.push_back(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME); + const bool hasSwapchainMaintenance1KHR = + ExtensionFound(VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, deviceExtensionNames); + mEnabledDeviceExtensions.push_back(hasSwapchainMaintenance1KHR + ? VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME + : VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME); vk::AddToPNextChain(&mEnabledFeatures, &mSwapchainMaintenance1Features); } @@ -3647,6 +4033,12 @@ void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &de vk::AddToPNextChain(&mEnabledFeatures, &mDynamicRenderingLocalReadFeatures); } + if (getFeatures().supportsUnifiedImageLayouts.enabled) + { + mEnabledDeviceExtensions.push_back(VK_KHR_UNIFIED_IMAGE_LAYOUTS_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mUnifiedImageLayoutsFeatures); + } + if (getFeatures().supportsImageCompressionControl.enabled) { mEnabledDeviceExtensions.push_back(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME); @@ -3660,6 +4052,29 @@ void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &de vk::AddToPNextChain(&mEnabledFeatures, &mImageCompressionControlSwapchainFeatures); } + if (mFeatures.supportsSwapchainMutableFormat.enabled) + { + mEnabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME); + } + + if (mFeatures.supportsDeviceFault.enabled) + { + mEnabledDeviceExtensions.push_back(VK_EXT_DEVICE_FAULT_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mFaultFeatures); + } + + if (mFeatures.supportsAstcDecodeMode.enabled) + { + mEnabledDeviceExtensions.push_back(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mPhysicalDeviceAstcDecodeFeatures); + } + + if (mFeatures.supportsAstc3d.enabled) + { + mEnabledDeviceExtensions.push_back(VK_EXT_TEXTURE_COMPRESSION_ASTC_3D_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mTextureCompressionASTC3DFeatures); + } + #if defined(ANGLE_PLATFORM_WINDOWS) // We only need the VK_EXT_full_screen_exclusive extension if we are opting // out of it via VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT (i.e. working @@ -3678,18 +4093,26 @@ void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &de vk::AddToPNextChain(&mEnabledFeatures, &mExternalFormatResolveFeatures); } #endif + + if (mFeatures.supportsGlobalPriority.enabled) + { + mEnabledDeviceExtensions.push_back(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME); + } + + if (mFeatures.supportsGlobalPriorityQuery.enabled) + { + mEnabledDeviceExtensions.push_back(VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mPhysicalDeviceGlobalPriorityQueryFeatures); + } + + if (getFeatures().supportsTileMemoryHeap.enabled) + { + mEnabledDeviceExtensions.push_back(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mTileMemoryHeapFeatures); + } } -// See comment above appendDeviceExtensionFeaturesPromotedTo11. Additional extensions are enabled -// here which don't have feature structs: -// -// - VK_KHR_get_memory_requirements2 -// - VK_KHR_bind_memory2 -// - VK_KHR_maintenance1 -// - VK_KHR_external_memory -// - VK_KHR_external_semaphore -// - VK_KHR_external_fence -// +// See comment above appendDeviceExtensionFeaturesPromotedTo11. void Renderer::enableDeviceExtensionsPromotedTo11(const vk::ExtensionNameList &deviceExtensionNames) { // OVR_multiview disallows multiview with geometry and tessellation, so don't request these @@ -3731,6 +4154,7 @@ void Renderer::enableDeviceExtensionsPromotedTo11(const vk::ExtensionNameList &d // - VK_KHR_spirv_1_4 // - VK_KHR_sampler_mirror_clamp_to_edge // - VK_KHR_depth_stencil_resolve +// - VK_KHR_buffer_device_address // void Renderer::enableDeviceExtensionsPromotedTo12(const vk::ExtensionNameList &deviceExtensionNames) { @@ -3809,6 +4233,16 @@ void Renderer::enableDeviceExtensionsPromotedTo12(const vk::ExtensionNameList &d mEnabledDeviceExtensions.push_back(VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME); vk::AddToPNextChain(&mEnabledFeatures, &mUniformBufferStandardLayoutFeatures); } + if (mFeatures.supportsBufferDeviceAddress.enabled) + { + mEnabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mBufferDeviceAddressFeatures); + } + if (mFeatures.supportsShaderAtomicInt64.enabled) + { + mEnabledDeviceExtensions.push_back(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mShaderAtomicInt64Features); + } } // See comment above appendDeviceExtensionFeaturesPromotedTo13. @@ -3854,6 +4288,12 @@ void Renderer::enableDeviceExtensionsPromotedTo13(const vk::ExtensionNameList &d mEnabledDeviceExtensions.push_back(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME); vk::AddToPNextChain(&mEnabledFeatures, &mTextureCompressionASTCHDRFeatures); } + + if (mFeatures.supportsShaderIntegerDotProduct.enabled) + { + mEnabledDeviceExtensions.push_back(VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME); + vk::AddToPNextChain(&mEnabledFeatures, &mShaderIntegerDotProductFeatures); + } } angle::Result Renderer::enableDeviceExtensions(vk::ErrorContext *context, @@ -3967,6 +4407,10 @@ void Renderer::initDeviceExtensionEntryPoints() { InitHostImageCopyFunctions(mDevice); } + if (mFeatures.supportsImageCompressionControl.enabled) + { + InitImageCompressionControlFunctions(mDevice); + } if (mFeatures.supportsVertexInputDynamicState.enabled) { InitVertexInputDynamicStateEXTFunctions(mDevice); @@ -3994,7 +4438,19 @@ void Renderer::initDeviceExtensionEntryPoints() # endif if (mFeatures.supportsSynchronization2.enabled) { - InitSynchronization2Functions(mDevice); + InitSynchronization2Functions(mDevice); + } + if (mFeatures.supportsDeviceFault.enabled) + { + InitDeviceFaultFunctions(mDevice); + } + if (mFeatures.supportsMaintenance5.enabled) + { + InitMaintenance5Functions(mDevice); + } + if (mFeatures.supportsTileMemoryHeap.enabled) + { + InitTileMemoryHeapFunctions(mDevice); } // Extensions promoted to Vulkan 1.2 { @@ -4006,6 +4462,10 @@ void Renderer::initDeviceExtensionEntryPoints() { InitRenderPass2KHRFunctions(mDevice); } + if (mFeatures.supportsBufferDeviceAddress.enabled) + { + InitBufferDeviceAddressFunctions(mDevice); + } } // Extensions promoted to Vulkan 1.3 { @@ -4123,7 +4583,7 @@ angle::Result Renderer::setupDevice(vk::ErrorContext *context, mEnabledFeatures.features.shaderInt64 = mPhysicalDeviceFeatures.shaderInt64; // Used to support 64bit-floats in shader code mEnabledFeatures.features.shaderFloat64 = - mFeatures.supportsShaderFloat64.enabled && mPhysicalDeviceFeatures.shaderFloat64; + mFeatures.supportsShaderFloat64.enabled && mPhysicalDeviceFeatures.shaderFloat64 == VK_TRUE; if (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() || !vk::RenderPassCommandBuffer::ExecutesInline()) @@ -4159,6 +4619,41 @@ angle::Result Renderer::createDeviceAndQueue(vk::ErrorContext *context, uint32_t queueCreateInfo[0].queueCount = queueCount; queueCreateInfo[0].pQueuePriorities = vk::QueueFamily::kQueuePriorities; + VkDeviceQueueGlobalPriorityCreateInfo queueGlobalPriorityCreateInfo = {}; + queueGlobalPriorityCreateInfo.sType = + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO; + if (mFeatures.supportsGlobalPriorityQuery.enabled) + { + // Query all supported global priorities. + uint32_t queueFamilyPropertiesCount = static_cast(mQueueFamilyProperties.size()); + std::vector queueFamilyProperties2(queueFamilyPropertiesCount); + std::vector globalPriorityProperties( + queueFamilyPropertiesCount); + + for (uint32_t i = 0; i < queueFamilyPropertiesCount; i++) + { + globalPriorityProperties[i] = {}; + globalPriorityProperties[i].sType = + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT; + + queueFamilyProperties2[i] = {}; + queueFamilyProperties2[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + vk::AddToPNextChain(&queueFamilyProperties2[i], &globalPriorityProperties[i]); + } + + vkGetPhysicalDeviceQueueFamilyProperties2(mPhysicalDevice, &queueFamilyPropertiesCount, + queueFamilyProperties2.data()); + + if (HasRequiredGlobalPriority(globalPriorityProperties, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT)) + { + // Realtime global priority is supported, so we can use it in + // queueGlobalPriorityCreateInfo + queueGlobalPriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT; + vk::AddToPNextChain(&queueCreateInfo, &queueGlobalPriorityCreateInfo); + } + } + // Setup device initialization struct VkDeviceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -4261,14 +4756,20 @@ angle::Result Renderer::createDeviceAndQueue(vk::ErrorContext *context, uint32_t // Initialize the barrierData tables by removing unsupported pipeline stage bits InitializeEventStageToVkPipelineStageFlagsMap(&mEventStageToPipelineStageFlagsMap, ~unsupportedStages); - InitializeImageLayoutAndMemoryBarrierDataMap(&mImageLayoutAndMemoryBarrierDataMap, - ~unsupportedStages); + InitializeImageLayoutAndMemoryBarrierDataMap( + getFeatures(), &mImageLayoutAndMemoryBarrierDataMap, ~unsupportedStages); ANGLE_TRY(initializeMemoryAllocator(context)); // Log the memory heap stats when the device has been initialized (when debugging). mMemoryAllocationTracker.onDeviceInit(); + // Synchronize the Vulkan pipeline cache to the blob cache every frame + if (mFeatures.syncPipelineCacheToBlobCacheEveryFrame.enabled) + { + mPipelineCacheVkUpdateTimeout = 1; + } + return angle::Result::Continue; } @@ -4314,6 +4815,27 @@ void Renderer::initializeValidationMessageSuppressions() kExposeNonConformantSkippedMessages + ArraySize(kExposeNonConformantSkippedMessages)); } + if (!getFeatures().supportsMaintenance5.enabled) + { + mSkippedValidationMessages.insert( + mSkippedValidationMessages.end(), kNoMaintenance5SkippedMessages, + kNoMaintenance5SkippedMessages + ArraySize(kNoMaintenance5SkippedMessages)); + } + + if (!getFeatures().supportsMaintenance9.enabled) + { + mSkippedValidationMessages.insert( + mSkippedValidationMessages.end(), kNoMaintenance9SkippedMessages, + kNoMaintenance9SkippedMessages + ArraySize(kNoMaintenance9SkippedMessages)); + } + + if (getFeatures().preferBGR565ToRGB565.enabled) + { + mSkippedValidationMessages.insert( + mSkippedValidationMessages.end(), kPreferBGR565SkippedMessages, + kPreferBGR565SkippedMessages + ArraySize(kPreferBGR565SkippedMessages)); + } + if (getFeatures().useVkEventForImageBarrier.enabled && (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() || !vk::RenderPassCommandBuffer::ExecutesInline())) @@ -4343,13 +4865,12 @@ void Renderer::initializeValidationMessageSuppressions() // Build the list of syncval errors that are currently expected and should be skipped. mSkippedSyncvalMessages.insert(mSkippedSyncvalMessages.end(), kSkippedSyncvalMessages, kSkippedSyncvalMessages + ArraySize(kSkippedSyncvalMessages)); - if (!getFeatures().supportsRenderPassStoreOpNone.enabled && - !getFeatures().supportsRenderPassLoadStoreOpNone.enabled) + if (!getFeatures().forceSizePointerForBoundVertexBuffers.enabled) { - mSkippedSyncvalMessages.insert(mSkippedSyncvalMessages.end(), - kSkippedSyncvalMessagesWithoutStoreOpNone, - kSkippedSyncvalMessagesWithoutStoreOpNone + - ArraySize(kSkippedSyncvalMessagesWithoutStoreOpNone)); + mSkippedSyncvalMessages.insert( + mSkippedSyncvalMessages.end(), kSkippedSyncvalMessagesWithoutForcedSizePointer, + kSkippedSyncvalMessagesWithoutForcedSizePointer + + ArraySize(kSkippedSyncvalMessagesWithoutForcedSizePointer)); } if (!getFeatures().supportsRenderPassLoadStoreOpNone.enabled) { @@ -4402,9 +4923,9 @@ std::string Renderer::getRendererDescription() const uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion; strstr << "Vulkan "; - strstr << VK_VERSION_MAJOR(apiVersion) << "."; - strstr << VK_VERSION_MINOR(apiVersion) << "."; - strstr << VK_VERSION_PATCH(apiVersion); + strstr << VK_API_VERSION_MAJOR(apiVersion) << "."; + strstr << VK_API_VERSION_MINOR(apiVersion) << "."; + strstr << VK_API_VERSION_PATCH(apiVersion); strstr << " ("; @@ -4457,12 +4978,21 @@ std::string Renderer::getVersionString(bool includeFullVersion) const strstr << ANGLE_VK_VERSION_MAJOR_WIN_INTEL(driverVersion) << "."; strstr << ANGLE_VK_VERSION_MINOR_WIN_INTEL(driverVersion); } + // The major version for the new QCOM drivers seems to be 512, which results in a major + // version of 0 and a non-zero variant field when using the VK_API_VERSION_x macros. + // Therefore, the version string is updated to show the correct major version. + else if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_QUALCOMM) + { + strstr << (512 | VK_API_VERSION_MAJOR(driverVersion)) << "."; + strstr << VK_API_VERSION_MINOR(driverVersion) << "."; + strstr << VK_API_VERSION_PATCH(driverVersion); + } // All other drivers use the Vulkan standard else { - strstr << VK_VERSION_MAJOR(driverVersion) << "."; - strstr << VK_VERSION_MINOR(driverVersion) << "."; - strstr << VK_VERSION_PATCH(driverVersion); + strstr << VK_API_VERSION_MAJOR(driverVersion) << "."; + strstr << VK_API_VERSION_MINOR(driverVersion) << "."; + strstr << VK_API_VERSION_PATCH(driverVersion); } } @@ -4523,7 +5053,12 @@ gl::Version Renderer::getMaxSupportedESVersion() const } // Limit to ES2.0 if there are any blockers for 3.0. - // TODO: http://anglebug.com/42262611 Limit to GLES 2.0 if flat shading can't be emulated + + // VK_EXT_provoking_vertex is required for flat shading. + if (!mFeatures.provokingVertex.enabled) + { + maxVersion = LimitVersionTo(maxVersion, {2, 0}); + } // Multisample textures (ES3.1) and multisample renderbuffers (ES3.0) require the Vulkan driver // to support the standard sample locations (in order to pass dEQP tests that check these @@ -4612,17 +5147,18 @@ void Renderer::queryAndCacheFragmentShadingRates() ASSERT(result == VK_SUCCESS); // Cache supported fragment shading rates - mSupportedFragmentShadingRates.reset(); - mSupportedFragmentShadingRateSampleCounts.fill(0u); + mSupportedFragmentShadingRatesEXT.reset(); + mSupportedFragmentShadingRateEXTSampleCounts.fill(0u); for (const VkPhysicalDeviceFragmentShadingRateKHR &shadingRate : shadingRates) { if (shadingRate.sampleCounts == 0) { continue; } - const gl::ShadingRate rate = GetShadingRateFromVkExtent(shadingRate.fragmentSize); - mSupportedFragmentShadingRates.set(rate); - mSupportedFragmentShadingRateSampleCounts[rate] = shadingRate.sampleCounts; + const gl::ShadingRate rate = GetShadingRateEXTFromVkExtent(shadingRate.fragmentSize); + mSupportedFragmentShadingRatesEXT.set(rate); + mSupportedFragmentShadingRateEXTSampleCounts[rate] = + static_cast(shadingRate.sampleCounts); } } @@ -4641,18 +5177,25 @@ bool Renderer::canSupportFragmentShadingRate() const return false; } - ASSERT(mSupportedFragmentShadingRates.any()); + ASSERT(mSupportedFragmentShadingRatesEXT.any()); - // To implement GL_QCOM_shading_rate extension the Vulkan ICD needs to support at least the - // following shading rates - - // {1, 1} - // {1, 2} - // {2, 1} - // {2, 2} - return mSupportedFragmentShadingRates.test(gl::ShadingRate::_1x1) && - mSupportedFragmentShadingRates.test(gl::ShadingRate::_1x2) && - mSupportedFragmentShadingRates.test(gl::ShadingRate::_2x1) && - mSupportedFragmentShadingRates.test(gl::ShadingRate::_2x2); + // To implement GL_EXT_fragment_shading_rate and GL_QCOM_shading_rate extension + // the Vulkan ICD needs to support at least the following shading rates + // VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT {1, 1} + // VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT {1, 2} + // VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT {2, 1} + // VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT {2, 2} + constexpr VkSampleCountFlags krequiredSampleCounts = + VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT; + + return (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_1x1] & + krequiredSampleCounts) == krequiredSampleCounts && + (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_1x2] & + krequiredSampleCounts) == krequiredSampleCounts && + (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_2x1] & + krequiredSampleCounts) == krequiredSampleCounts && + (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_2x2] & + krequiredSampleCounts) == krequiredSampleCounts; } bool Renderer::canSupportFoveatedRendering() const @@ -4663,8 +5206,8 @@ bool Renderer::canSupportFoveatedRendering() const return false; } - ASSERT(mSupportedFragmentShadingRates.any()); - ASSERT(!mSupportedFragmentShadingRateSampleCounts.empty()); + ASSERT(mSupportedFragmentShadingRatesEXT.any()); + ASSERT(!mSupportedFragmentShadingRateEXTSampleCounts.empty()); // To implement QCOM foveated rendering extensions the Vulkan ICD needs to support all sample // count bits listed in VkPhysicalDeviceLimits::framebufferColorSampleCounts for these shading @@ -4677,16 +5220,52 @@ bool Renderer::canSupportFoveatedRendering() const getPhysicalDeviceProperties().limits.framebufferColorSampleCounts & vk_gl::kSupportedSampleCounts; - return (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_1x1] & + return (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_1x1] & framebufferSampleCounts) == framebufferSampleCounts && - (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_1x2] & + (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_1x2] & framebufferSampleCounts) == framebufferSampleCounts && - (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_2x1] & + (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_2x1] & framebufferSampleCounts) == framebufferSampleCounts && - (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_2x2] & + (mSupportedFragmentShadingRateEXTSampleCounts[gl::ShadingRate::_2x2] & framebufferSampleCounts) == framebufferSampleCounts; } +bool CanSupportAstcHdr3D(const Renderer *renderer) +{ + // New formats added in VK_EXT_texture_compression_astc_hdr + std::vector astcHdrFormats = { + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT}; + + for (VkFormat format : astcHdrFormats) + { + // If any ASTC HDR format does not support 3D, return false + if (false == vk::ImageHelper::FormatSupportsUsage( + renderer, format, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_SAMPLED_BIT, 0, nullptr, nullptr, + vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess)) + { + return false; + } + } + + return true; +} + +bool Renderer::supportsAstcHdr() const +{ + // When determining whether we support this, have to check for both the Vulkan + // feaure and explicity check for 3D texture types. The latter could be emulated + // in the future. (http://anglebug.com/416095435) + return getFeatures().supportsTextureCompressionAstcHdr.enabled && + getFeatures().supportsAstcHdr3dTextures.enabled; +} + bool Renderer::canPreferDeviceLocalMemoryHostVisible(VkPhysicalDeviceType deviceType) { if (deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) @@ -4742,6 +5321,9 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, const bool isSamsung = IsSamsung(mPhysicalDeviceProperties.vendorID); const bool isSwiftShader = IsSwiftshader(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID); + const bool isLavapipe = + IsLavapipe(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID); + const bool isSoftwareRenderer = isSwiftShader || isLavapipe; const bool isGalaxyS23 = IsGalaxyS23(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID); @@ -4752,6 +5334,10 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, mPhysicalDeviceProperties.deviceName); const bool isQualcommProprietary = isQualcomm && !isQualcommOpenSource; + // Distinguish between the ARM proprietary driver and the Mesa open source driver + const bool isMesaPanVK = IsMesaPanVK(mDriverProperties.driverID); + const bool isARMProprietary = isARM && !isMesaPanVK; + // Lacking other explicit ways to tell if mali GPU is job manager based or command stream front // end based, we use maxDrawIndirectCount as equivalent since all JM based has // maxDrawIndirectCount==1 and all CSF based has maxDrawIndirectCount>1. @@ -4763,7 +5349,7 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, mPhysicalDeviceProperties.deviceName); angle::VersionInfo driverVersion = {}; - if (isARM) + if (isARMProprietary) { driverVersion = angle::ParseArmVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion); } @@ -4807,8 +5393,9 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Due to these key architectural differences, some operations improve performance on one while // deteriorating performance on the other. ANGLE will accordingly make some decisions based on // the device architecture for optimal performance on both. - const bool isImmediateModeRenderer = isNvidia || isAMD || isIntel || isSamsung || isSwiftShader; - const bool isTileBasedRenderer = isARM || isPowerVR || isQualcomm || isBroadcom || isApple; + const bool isImmediateModeRenderer = + isNvidia || isAMD || isIntel || isSamsung || isSoftwareRenderer; + const bool isTileBasedRenderer = isARM || isPowerVR || isQualcomm || isBroadcom || isApple; // Make sure all known architectures are accounted for. if (!isImmediateModeRenderer && !isTileBasedRenderer && !isMockICDEnabled()) @@ -4832,9 +5419,9 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, provokingVertex, mProvokingVertexFeatures.provokingVertexLast == VK_TRUE); - // http://b/208458772. ARM driver supports this protected memory extension but we are seeing - // excessive load/store unit activity when this extension is enabled, even if not been used. - // Disable this extension on older ARM platforms that don't support + // http://b/208458772. ARM proprietary driver supports this protected memory extension but we + // are seeing excessive load/store unit activity when this extension is enabled, even if not + // been used. Disable this extension on older ARM platforms that don't support // VK_EXT_pipeline_protected_access. // http://anglebug.com/42266183 // @@ -4843,7 +5430,8 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION( &mFeatures, supportsProtectedMemory, mProtectedMemoryFeatures.protectedMemory == VK_TRUE && - (!isARM || mPipelineProtectedAccessFeatures.pipelineProtectedAccess == VK_TRUE) && + (!isARMProprietary || + mPipelineProtectedAccessFeatures.pipelineProtectedAccess == VK_TRUE) && !isIntel); ANGLE_FEATURE_CONDITION(&mFeatures, supportsHostQueryReset, @@ -4854,10 +5442,12 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // VkHostImageCopyDevicePerformanceQueryEXT::identicalMemoryLayout. ANGLE_FEATURE_CONDITION(&mFeatures, allowHostImageCopyDespiteNonIdenticalLayout, false); - // VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL and - // VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL are introduced by - // VK_KHR_maintenance2 and promoted to Vulkan 1.1. - ANGLE_FEATURE_CONDITION(&mFeatures, supportsMixedReadWriteDepthStencilLayouts, true); + // Force host image copy for textures with luminance/alpha formats. This disables framebuffer + // compression (but these formats are not renderable), and the benefits of host image copy + // outweigh framebuffer compression on sampled textures on the following GPUs: + // + // - ARM + ANGLE_FEATURE_CONDITION(&mFeatures, forceHostImageCopyForLuma, isARM); // VK_EXT_pipeline_creation_feedback is promoted to core in Vulkan 1.3. ANGLE_FEATURE_CONDITION( @@ -4910,12 +5500,6 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ExtensionFound(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, deviceExtensionNames)); #endif -#if defined(ANGLE_PLATFORM_GGP) - ANGLE_FEATURE_CONDITION( - &mFeatures, supportsGGPFrameToken, - ExtensionFound(VK_GGP_FRAME_TOKEN_EXTENSION_NAME, deviceExtensionNames)); -#endif - ANGLE_FEATURE_CONDITION( &mFeatures, supportsExternalMemoryFd, ExtensionFound(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, deviceExtensionNames)); @@ -5002,7 +5586,7 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ExtensionFound(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME, deviceExtensionNames)); ANGLE_FEATURE_CONDITION(&mFeatures, disallowMixedDepthStencilLoadOpNoneAndLoad, - isARM && driverVersion < angle::VersionTriple(38, 1, 0)); + isARMProprietary && driverVersion < angle::VersionTriple(38, 1, 0)); ANGLE_FEATURE_CONDITION( &mFeatures, supportsRenderPassStoreOpNone, @@ -5059,17 +5643,23 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // MSRTSS is disabled if the driver does not support it for RGBA8 and RGBA8_SRGB. // This is used to filter out known drivers where support for sRGB formats are missing. + // + // Qualcomm driver 512.821 is known to have rendering bugs with this extension. + // http://crbug.com/413427770 ANGLE_FEATURE_CONDITION( &mFeatures, supportsMultisampledRenderToSingleSampled, mMultisampledRenderToSingleSampledFeatures.multisampledRenderToSingleSampled == VK_TRUE && mFeatures.supportsRenderpass2.enabled && - mFeatures.supportsDepthStencilResolve.enabled && CanSupportMSRTSSForRGBA8(this)); + mFeatures.supportsDepthStencilResolve.enabled && CanSupportMSRTSSForRGBA8(this) && + !(isQualcommProprietary && driverVersion < angle::VersionTriple(512, 822, 0))); // Preferring the MSRTSS flag is for texture initialization. If the MSRTSS is not used at first, // it will be used (if available) when recreating the image if it is bound to an MSRTT // framebuffer. - ANGLE_FEATURE_CONDITION(&mFeatures, preferMSRTSSFlagByDefault, - mFeatures.supportsMultisampledRenderToSingleSampled.enabled && isARM); + ANGLE_FEATURE_CONDITION( + &mFeatures, preferMSRTSSFlagByDefault, + mFeatures.supportsMultisampledRenderToSingleSampled.enabled && !isMesaPanVK && + !(isQualcommProprietary && driverVersion < angle::VersionTriple(512, 777, 0))); ANGLE_FEATURE_CONDITION(&mFeatures, supportsImage2dViewOf3d, mImage2dViewOf3dFeatures.image2DViewOf3D == VK_TRUE); @@ -5084,37 +5674,62 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsMultiview, mMultiviewFeatures.multiview == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsMultiviewMultisampleRenderToTexture, + mFeatures.supportsMultisampledRenderToSingleSampled.enabled && + mFeatures.supportsMultiview.enabled); + + // VK_EXT_device_fault can provide more information when the device is lost. + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsDeviceFault, + ExtensionFound(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, deviceExtensionNames) && + mFaultFeatures.deviceFault == VK_TRUE); + // TODO: http://anglebug.com/42264464 - drop dependency on customBorderColorWithoutFormat. ANGLE_FEATURE_CONDITION( &mFeatures, supportsCustomBorderColor, mCustomBorderColorFeatures.customBorderColors == VK_TRUE && mCustomBorderColorFeatures.customBorderColorWithoutFormat == VK_TRUE); + // If format is undefined, the borderColor is VK_BORDER_COLOR_INT_CUSTOM_EXT, and the sampler is + // used with an image with a stencil format, then the implementation must source the custom + // border color from either the first or second components of the borderColor, although it is + // recommended to source it from the first component. + ANGLE_FEATURE_CONDITION(&mFeatures, usesSecondComponentForStencilBorderColor, + mFeatures.supportsCustomBorderColor.enabled && isQualcommProprietary); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsMultiDrawIndirect, mPhysicalDeviceFeatures.multiDrawIndirect == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, perFrameWindowSizeQuery, - IsAndroid() || isIntel || (IsWindows() && (isAMD || isNvidia)) || - IsFuchsia() || isSamsung || - nativeWindowSystem == angle::NativeWindowSystem::Wayland); + // The |WindowSurfaceVk::getWindowVisibility| method must be implemented. + // When enabled, surface will be resized only if window is visible. + // Notes: + // - Enable for NVIDIA on Linux X11 because of the possible driver bug, when acquire next image + // continuously returns OUT_OF_DATE if recreate the swapchain while window is not visible + // (http://anglebug.com/397848903). + ANGLE_FEATURE_CONDITION(&mFeatures, avoidInvisibleWindowSwapchainRecreate, + (isNvidia && nativeWindowSystem == angle::NativeWindowSystem::X11)); ANGLE_FEATURE_CONDITION(&mFeatures, padBuffersToMaxVertexAttribStride, isAMD || isSamsung); - mMaxVertexAttribStride = std::min(static_cast(gl::limits::kMaxVertexAttribStride), - mPhysicalDeviceProperties.limits.maxVertexInputBindingStride); + mMaxVertexAttribStride = + mFeatures.padBuffersToMaxVertexAttribStride.enabled + ? std::min(static_cast(gl::limits::kMaxVertexAttribStride), + mPhysicalDeviceProperties.limits.maxVertexInputBindingStride) + : 0; - ANGLE_FEATURE_CONDITION(&mFeatures, forceD16TexFilter, IsAndroid() && isQualcommProprietary); + // The limits related to buffer size should also take the max memory allocation size and padding + // (if applicable) into account. + mMaxBufferMemorySizeLimit = getMaxMemoryAllocationSize() - mMaxVertexAttribStride; - ANGLE_FEATURE_CONDITION(&mFeatures, disableFlippingBlitWithCommand, - IsAndroid() && isQualcommProprietary); + ANGLE_FEATURE_CONDITION(&mFeatures, forceD16TexFilter, IsAndroid() && isQualcommProprietary); // Allocation sanitization disabled by default because of a heaveyweight implementation // that can cause OOM and timeouts. ANGLE_FEATURE_CONDITION(&mFeatures, allocateNonZeroMemory, false); - // ARM does buffer copy on geometry pipeline, which may create a GPU pipeline bubble that - // prevents vertex shader to overlap with fragment shader on job manager based architecture. For - // now we always choose CPU to do copy on ARM job manager based GPU. - ANGLE_FEATURE_CONDITION(&mFeatures, preferCPUForBufferSubData, isARM); + // ARM proprietary driver does buffer copy on geometry pipeline, which may create a GPU pipeline + // bubble that prevents vertex shader to overlap with fragment shader on job manager based + // architecture. For now we always choose CPU to do copy on ARM job manager based GPU. + ANGLE_FEATURE_CONDITION(&mFeatures, preferCPUForBufferSubData, isARMProprietary); // On android, we usually are GPU limited, we try to use CPU to do data copy when other // conditions are the same. Set to zero will use GPU to do copy. This is subject to further @@ -5128,27 +5743,26 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportStats, false); ANGLE_FEATURE_CONDITION( - &mFeatures, supportsExternalMemoryDmaBufAndModifiers, - ExtensionFound(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, deviceExtensionNames) && - ExtensionFound(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, deviceExtensionNames)); + &mFeatures, supportsExternalMemoryDmaBuf, + ExtensionFound(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, deviceExtensionNames)); ANGLE_FEATURE_CONDITION( - &mFeatures, supportsExternalMemoryHost, - ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames)); - - // Android pre-rotation support can be disabled. - ANGLE_FEATURE_CONDITION(&mFeatures, enablePreRotateSurfaces, IsAndroid()); + &mFeatures, supportsImageDrmFormatModifier, + ExtensionFound(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, deviceExtensionNames)); // http://anglebug.com/42261756 // Precision qualifiers are disabled for Pixel 2 before the driver included relaxed precision. + const bool isPixel4 = + IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID); ANGLE_FEATURE_CONDITION( &mFeatures, enablePrecisionQualifiers, !(IsPixel2(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) && (driverVersion < angle::VersionTriple(512, 490, 0))) && - !IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID)); + !isPixel4); // http://anglebug.com/42265957 - ANGLE_FEATURE_CONDITION(&mFeatures, varyingsRequireMatchingPrecisionInSpirv, isPowerVR); + ANGLE_FEATURE_CONDITION(&mFeatures, varyingsRequireMatchingPrecisionInSpirv, + isPowerVR || isSamsung); // IMR devices are less sensitive to the src/dst stage masks in barriers, and behave more // efficiently when all barriers are aggregated, rather than individually and precisely @@ -5161,33 +5775,16 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, preferSkippingInvalidateForEmulatedFormats, isImmediateModeRenderer); - ANGLE_FEATURE_CONDITION(&mFeatures, asyncCommandBufferResetAndGarbageCleanup, true); + ANGLE_FEATURE_CONDITION(&mFeatures, asyncGarbageCleanup, true); + // reset sometimes gets blocked by mutex lock inside vulkan driver and runs in small core while + // main thread gets blocked by command pool lock. FOr now dont call reset in garbage clean up + // thread on ARM proprietary driver. + ANGLE_FEATURE_CONDITION(&mFeatures, asyncCommandBufferReset, + mFeatures.asyncGarbageCleanup.enabled && !isARMProprietary); ANGLE_FEATURE_CONDITION(&mFeatures, supportsYUVSamplerConversion, mSamplerYcbcrConversionFeatures.samplerYcbcrConversion != VK_FALSE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat16, - mShaderFloat16Int8Features.shaderFloat16 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderInt8, - mShaderFloat16Int8Features.shaderInt8 == VK_TRUE); - - ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat64, - mPhysicalDeviceFeatures.shaderFloat64 == VK_TRUE); - - // Prefer driver uniforms over specialization constants in the following: - // - // - Older Qualcomm drivers where specialization constants severely degrade the performance of - // pipeline creation. http://issuetracker.google.com/173636783 - // - ARM hardware - // - Imagination hardware - // - Samsung hardware - // - SwiftShader - // - ANGLE_FEATURE_CONDITION( - &mFeatures, preferDriverUniformOverSpecConst, - (isQualcommProprietary && driverVersion < angle::VersionTriple(512, 513, 0)) || isARM || - isPowerVR || isSamsung || isSwiftShader); - ANGLE_FEATURE_CONDITION(&mFeatures, preferCachedNoncoherentForDynamicStreamBufferUsage, IsMeteorLake(mPhysicalDeviceProperties.deviceID)); @@ -5242,11 +5839,11 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // * OOM: http://crbug.com/1263046 // - Intel on windows: http://anglebug.com/42263602 // - AMD on windows: http://crbug.com/1132366 - // - Old ARM drivers on Android fail multiple tests, though newer drivers don't (although they - // support MSRTSS and emulation is unnecessary) + // - Old ARM proprietary drivers on Android fail multiple tests, though newer drivers don't + // (although they support MSRTSS and emulation is unnecessary) // ANGLE_FEATURE_CONDITION(&mFeatures, allowMultisampledRenderToTextureEmulation, - (isTileBasedRenderer && !isARM) || isSamsung); + (isTileBasedRenderer && !isARMProprietary) || isSamsung); ANGLE_FEATURE_CONDITION(&mFeatures, enableMultisampledRenderToTexture, mFeatures.supportsMultisampledRenderToSingleSampled.enabled || (mFeatures.supportsDepthStencilResolve.enabled && @@ -5260,8 +5857,11 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsPipelineStatisticsQuery, mPhysicalDeviceFeatures.pipelineStatisticsQuery == VK_TRUE); - // Android mistakenly destroys the old swapchain when creating a new one. - ANGLE_FEATURE_CONDITION(&mFeatures, waitIdleBeforeSwapchainRecreation, IsAndroid() && isARM); + ANGLE_FEATURE_CONDITION( + &mFeatures, allowPipelineStatisticsForPrimitivesGeneratedQuery, + mFeatures.supportsPipelineStatisticsQuery.enabled && (isSamsung || isQualcommProprietary)); + + ANGLE_FEATURE_CONDITION(&mFeatures, destroyOldSwapchainInSharedPresentMode, IsAndroid()); // vkCmdClearAttachments races with draw calls on Qualcomm hardware as observed on Pixel2 and // Pixel4. https://issuetracker.google.com/issues/166809097 @@ -5283,27 +5883,31 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // or extensions. For the purpose of testing coverage, we would still enable ES 3.2 on these // platforms. However, once a listed test platform is updated to a version that does support // ES 3.2, it should be unlisted. - ANGLE_FEATURE_CONDITION( - &mFeatures, exposeES32ForTesting, - mFeatures.exposeNonConformantExtensionsAndVersions.enabled && - (isSwiftShader || - IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) || - (IsLinux() && isNvidia && driverVersion < angle::VersionTriple(441, 0, 0)) || - (IsWindows() && isIntel))); + ANGLE_FEATURE_CONDITION(&mFeatures, exposeES32ForTesting, + mFeatures.exposeNonConformantExtensionsAndVersions.enabled && + (isSoftwareRenderer || isPixel4 || (IsWindows() && isIntel))); ANGLE_FEATURE_CONDITION( &mFeatures, supportsMemoryBudget, ExtensionFound(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, deviceExtensionNames)); - // Disabled by default. Only enable it for experimental purpose, as this will cause various - // tests to fail. - ANGLE_FEATURE_CONDITION(&mFeatures, forceFragmentShaderPrecisionHighpToMediump, false); + // TODO: Delete these two feature flags (https://issuetracker.google.com/422507974). More + // frequent submission may help benchmark score improvement, and in certain cases helps real + // performance as well (for things like bufferSubData able to go down faster path), but it + // increases power consumption by keeping GPU powered up longer for real world applications that + // runs in vsync mode. For now the feature is just disabled so that people can still do + // comparison if needed. They should be deleted in future. + ANGLE_FEATURE_CONDITION(&mFeatures, preferSubmitAtFBOBoundary, false); + // This is relevant only if preferSubmitAtFBOBoundary is enabled + ANGLE_FEATURE_CONDITION(&mFeatures, forceSubmitExceptionsAtFBOBoundary, + mFeatures.preferSubmitAtFBOBoundary.enabled && !isQualcommProprietary); - // Testing shows that on ARM and Qualcomm GPU, doing implicit flush at framebuffer boundary - // improves performance. Most app traces shows frame time reduced and manhattan 3.1 offscreen - // score improves 7%. - ANGLE_FEATURE_CONDITION(&mFeatures, preferSubmitAtFBOBoundary, - isTileBasedRenderer || isSwiftShader); + // The number of minimum write commands in the command buffer to trigger one submission of + // pending commands at draw call time + if (isARMProprietary) + { + mMinRPWriteCommandCountToEarlySubmit = 128; + } // In order to support immutable samplers tied to external formats, we need to overallocate // descriptor counts for such immutable samplers @@ -5362,9 +5966,12 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, emulateDithering, IsAndroid() && !mFeatures.supportsLegacyDithering.enabled); + // Enable additional blend factors when dithering for Samsung + ANGLE_FEATURE_CONDITION(&mFeatures, enableAdditionalBlendFactorsForDithering, isSamsung); + ANGLE_FEATURE_CONDITION(&mFeatures, adjustClearColorPrecision, - IsAndroid() && mFeatures.supportsLegacyDithering.enabled && isARM && - driverVersion < angle::VersionTriple(50, 0, 0)); + IsAndroid() && mFeatures.supportsLegacyDithering.enabled && + isARMProprietary && driverVersion < angle::VersionTriple(50, 0, 0)); // ANGLE always exposes framebuffer fetch because too many apps assume it's there. See comments // on |mIsColorFramebufferFetchCoherent| for details. Non-coherent framebuffer fetch is always @@ -5383,10 +5990,15 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, (isIntel && IsLinux() && driverVersion >= angle::VersionTriple(22, 0, 0)) || mFeatures.exposeNonConformantExtensionsAndVersions.enabled; - ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetch, - supportsFramebufferFetchInSurface); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetchNonCoherent, - supportsFramebufferFetchInSurface); + // Emulating framebuffer fetch causes significant perf regressions on samsung + const bool framebufferFetchEmulationCausesPerfRegression = isSamsung; + + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsShaderFramebufferFetch, + (supportsFramebufferFetchInSurface && !framebufferFetchEmulationCausesPerfRegression)); + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsShaderFramebufferFetchNonCoherent, + (supportsFramebufferFetchInSurface && !framebufferFetchEmulationCausesPerfRegression)); // On ARM hardware, framebuffer-fetch-like behavior on Vulkan is known to be coherent even // without the Vulkan extension. @@ -5431,54 +6043,27 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Use VMA for image suballocation. ANGLE_FEATURE_CONDITION(&mFeatures, useVmaForImageSuballocation, true); + // Some platforms perform better using BGR565 than RGB565. + bool isBGR565Renderable = hasImageFormatFeatureBits(angle::FormatID::B5G6R5_UNORM, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); + ANGLE_FEATURE_CONDITION(&mFeatures, preferBGR565ToRGB565, + isBGR565Renderable && isQualcomm && !isPixel4); + // Emit SPIR-V 1.4 when supported. The following old drivers have various bugs with SPIR-V 1.4: // // - Nvidia drivers - Crashes when creating pipelines, not using any SPIR-V 1.4 features. Known // good since at least version 525. http://anglebug.com/343249127 // - Qualcomm drivers - Crashes when creating pipelines in the presence of OpCopyLogical with // some types. http://anglebug.com/343218484 - // - ARM drivers - Fail tests when OpSelect uses a scalar to select between vectors. Known good - // since at least version 47. http://anglebug.com/343218491 - ANGLE_FEATURE_CONDITION(&mFeatures, supportsSPIRV14, - ExtensionFound(VK_KHR_SPIRV_1_4_EXTENSION_NAME, deviceExtensionNames) && - !(isNvidia && driverVersion < angle::VersionTriple(525, 0, 0)) && - !isQualcommProprietary && - !(isARM && driverVersion < angle::VersionTriple(47, 0, 0))); - - // Rounding features from VK_KHR_float_controls extension - ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp16, - mFloatControlProperties.shaderDenormFlushToZeroFloat16 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp32, - mFloatControlProperties.shaderDenormFlushToZeroFloat32 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp64, - mFloatControlProperties.shaderDenormFlushToZeroFloat64 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp16, - mFloatControlProperties.shaderDenormPreserveFloat16 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp32, - mFloatControlProperties.shaderDenormPreserveFloat32 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp64, - mFloatControlProperties.shaderDenormPreserveFloat64 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp16, - mFloatControlProperties.shaderRoundingModeRTEFloat16 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp32, - mFloatControlProperties.shaderRoundingModeRTEFloat32 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp64, - mFloatControlProperties.shaderRoundingModeRTEFloat64 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp16, - mFloatControlProperties.shaderRoundingModeRTZFloat16 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp32, - mFloatControlProperties.shaderRoundingModeRTZFloat32 == VK_TRUE); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp64, - mFloatControlProperties.shaderRoundingModeRTZFloat64 == VK_TRUE); - ANGLE_FEATURE_CONDITION( - &mFeatures, supportsSignedZeroInfNanPreserveFp16, - mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat16 == VK_TRUE); + // - ARM proprietary drivers - Fail tests when OpSelect uses a scalar to select between vectors. + // Known good since at least version 47. + // http://anglebug.com/343218491 ANGLE_FEATURE_CONDITION( - &mFeatures, supportsSignedZeroInfNanPreserveFp32, - mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat32 == VK_TRUE); - ANGLE_FEATURE_CONDITION( - &mFeatures, supportsSignedZeroInfNanPreserveFp64, - mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat64 == VK_TRUE); + &mFeatures, supportsSPIRV14, + ExtensionFound(VK_KHR_SPIRV_1_4_EXTENSION_NAME, deviceExtensionNames) && + !(isNvidia && driverVersion < angle::VersionTriple(525, 0, 0)) && + !isQualcommProprietary && + !(isARMProprietary && driverVersion < angle::VersionTriple(47, 0, 0))); // Retain debug info in SPIR-V blob. ANGLE_FEATURE_CONDITION(&mFeatures, retainSPIRVDebugInfo, getEnableValidationLayers()); @@ -5499,9 +6084,10 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // // Regressions have been detected using r46 on older architectures though // http://issuetracker.google.com/336411904 - const bool isExtendedDynamicStateBuggy = - (isARM && driverVersion < angle::VersionTriple(44, 1, 0)) || - (isMaliJobManagerBasedGPU && driverVersion >= angle::VersionTriple(46, 0, 0)); + const bool isARMExtendedDynamicStateBuggy = + isARMProprietary && + (driverVersion < angle::VersionTriple(44, 1, 0) || + (isMaliJobManagerBasedGPU && driverVersion >= angle::VersionTriple(46, 0, 0))); // Vertex input binding stride is buggy for Windows/Intel drivers before 100.9684. const bool isVertexInputBindingStrideBuggy = @@ -5510,21 +6096,26 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Intel driver has issues with VK_EXT_vertex_input_dynamic_state // http://anglebug.com/42265637#comment9 // - // On ARM drivers prior to r48, |vkCmdBindVertexBuffers2| applies strides to the wrong index, - // according to the errata: https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en + // On ARM proprietary drivers prior to r48, |vkCmdBindVertexBuffers2| applies strides to the + // wrong index, according to the errata: + // https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en // // On Qualcomm drivers prior to 777, this feature had a bug. // http://anglebug.com/381384988 + // + // Use of vertexInputDynamicState on PowerVR devices is disabled for performance reasons + // (http://issuetracker.google.com/469320616). ANGLE_FEATURE_CONDITION( &mFeatures, supportsVertexInputDynamicState, mVertexInputDynamicStateFeatures.vertexInputDynamicState == VK_TRUE && !(IsWindows() && isIntel) && - !(isARM && driverVersion < angle::VersionTriple(48, 0, 0)) && - !(isQualcommProprietary && driverVersion < angle::VersionTriple(512, 777, 0))); + !(isARMProprietary && driverVersion < angle::VersionTriple(48, 0, 0)) && + !(isQualcommProprietary && driverVersion < angle::VersionTriple(512, 777, 0)) && + !isPowerVR); ANGLE_FEATURE_CONDITION(&mFeatures, supportsExtendedDynamicState, mExtendedDynamicStateFeatures.extendedDynamicState == VK_TRUE && - !isExtendedDynamicStateBuggy); + !isARMExtendedDynamicStateBuggy); // VK_EXT_vertex_input_dynamic_state enables dynamic state for the full vertex input state. As // such, when available use supportsVertexInputDynamicState instead of @@ -5532,34 +6123,56 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, useVertexInputBindingStrideDynamicState, mFeatures.supportsExtendedDynamicState.enabled && !mFeatures.supportsVertexInputDynamicState.enabled && - !isExtendedDynamicStateBuggy && !isVertexInputBindingStrideBuggy); - // On ARM drivers prior to r52, |vkCmdSetCullMode| incorrectly culls non-triangle topologies, - // according to the errata: https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en - ANGLE_FEATURE_CONDITION(&mFeatures, useCullModeDynamicState, - mFeatures.supportsExtendedDynamicState.enabled && - !isExtendedDynamicStateBuggy && - !(isARM && driverVersion < angle::VersionTriple(52, 0, 0))); + !isVertexInputBindingStrideBuggy); + // On ARM proprietary drivers prior to r52, |vkCmdSetCullMode| incorrectly culls non-triangle + // topologies, according to the errata: + // https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en + ANGLE_FEATURE_CONDITION( + &mFeatures, useCullModeDynamicState, + mFeatures.supportsExtendedDynamicState.enabled && !isARMExtendedDynamicStateBuggy && + !(isARMProprietary && driverVersion < angle::VersionTriple(52, 0, 0))); ANGLE_FEATURE_CONDITION(&mFeatures, useDepthCompareOpDynamicState, mFeatures.supportsExtendedDynamicState.enabled); ANGLE_FEATURE_CONDITION(&mFeatures, useDepthTestEnableDynamicState, mFeatures.supportsExtendedDynamicState.enabled); ANGLE_FEATURE_CONDITION( &mFeatures, useDepthWriteEnableDynamicState, - mFeatures.supportsExtendedDynamicState.enabled && !isExtendedDynamicStateBuggy); + mFeatures.supportsExtendedDynamicState.enabled && !isARMExtendedDynamicStateBuggy); ANGLE_FEATURE_CONDITION(&mFeatures, useFrontFaceDynamicState, mFeatures.supportsExtendedDynamicState.enabled); + // On ARM proprietary drivers, there seems to be a bug with primitive topology dynamic state in + // combination with geometry shaders. + // + // On Samsung, it was observed that the combination of primitive topology dynamic state + // _enabled_ and primitive restart dynamic state _disabled_ is buggy. However, the feature is + // not disabled because primitive restart is not disabled outside tests. + // + // Also seeing rendering issues on PowerVR (http://b/472763050) + ANGLE_FEATURE_CONDITION( + &mFeatures, usePrimitiveTopologyDynamicState, + mFeatures.supportsExtendedDynamicState.enabled && !isARMProprietary && !isPowerVR); ANGLE_FEATURE_CONDITION(&mFeatures, useStencilOpDynamicState, mFeatures.supportsExtendedDynamicState.enabled); ANGLE_FEATURE_CONDITION(&mFeatures, useStencilTestEnableDynamicState, mFeatures.supportsExtendedDynamicState.enabled); + // vkCmdBindVertexBuffers2EXT() requires extended dynamic state. + ANGLE_FEATURE_CONDITION(&mFeatures, supportsBindVertexBuffers2, + mFeatures.supportsExtendedDynamicState.enabled); + + // Providing vkCmdBindVertexBuffers2() with a pointer to the sizes of the bound buffers can help + // with syncval issues and robustness. + ANGLE_FEATURE_CONDITION( + &mFeatures, forceSizePointerForBoundVertexBuffers, + mEnableValidationLayers && mFeatures.supportsBindVertexBuffers2.enabled); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsExtendedDynamicState2, mExtendedDynamicState2Features.extendedDynamicState2 == VK_TRUE && - !isExtendedDynamicStateBuggy); + !isARMExtendedDynamicStateBuggy); ANGLE_FEATURE_CONDITION( &mFeatures, usePrimitiveRestartEnableDynamicState, - mFeatures.supportsExtendedDynamicState2.enabled && !isExtendedDynamicStateBuggy); + mFeatures.supportsExtendedDynamicState2.enabled && !isARMExtendedDynamicStateBuggy); ANGLE_FEATURE_CONDITION(&mFeatures, useRasterizerDiscardEnableDynamicState, mFeatures.supportsExtendedDynamicState2.enabled); ANGLE_FEATURE_CONDITION(&mFeatures, useDepthBiasEnableDynamicState, @@ -5577,10 +6190,18 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Older Samsung drivers with version < 24.0.0 have a bug in imageless framebuffer support. const bool isSamsungDriverWithImagelessFramebufferBug = isSamsung && driverVersion < angle::VersionTriple(24, 0, 0); - // Qualcomm with imageless framebuffers, vkCreateFramebuffer loops forever. + // Qualcomm with imageless framebuffers, vkCreateFramebuffer loops forever (512.801). // http://issuetracker.google.com/369693310 + // + // On some devices, crashes are seen with vkCmdBeginRenderPass, likely due to imageless + // framebuffers (512.805). http://crbug.com/415968761 const bool isQualcommWithImagelessFramebufferBug = - isQualcommProprietary && driverVersion < angle::VersionTriple(512, 802, 0); + isQualcommProprietary && driverVersion < angle::VersionTriple(512, 806, 0); + // Some ARM-based phones with the 38.0 and 38.1 ARM proprietary driver crash when creating + // imageless framebuffers. + const bool isARMProprietaryWithImagelessFramebufferBug = + isARMProprietary && driverVersion >= angle::VersionTriple(38, 0, 0) && + driverVersion < angle::VersionTriple(38, 2, 0); // PowerVR with imageless framebuffer spends enormous amounts of time in framebuffer destruction // and creation. ANGLE doesn't cache imageless framebuffers, instead adding them to garbage // collection, expecting them to be lightweight. @@ -5588,6 +6209,7 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsImagelessFramebuffer, mImagelessFramebufferFeatures.imagelessFramebuffer == VK_TRUE && !isSamsungDriverWithImagelessFramebufferBug && + !isARMProprietaryWithImagelessFramebufferBug && !isQualcommWithImagelessFramebufferBug && !isPowerVR); if (ExtensionFound(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, deviceExtensionNames)) @@ -5599,6 +6221,9 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsFragmentShadingRate, canSupportFragmentShadingRate()); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsPrimitiveFragmentShadingRate, + mFragmentShadingRateFeatures.primitiveFragmentShadingRate == VK_TRUE); + // Support QCOM foveated rendering extensions. // Gated on supportsImagelessFramebuffer and supportsRenderPassLoadStoreOpNone // to reduce code complexity. @@ -5633,70 +6258,108 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // on those earlier versions. http://anglebug.com/42266655 // // On RADV, creating graphics pipeline can crash in the driver. http://crbug.com/1497512 + // + // Some unacceptable performance degradation has been observed on device with ARM proprietary + // driver when graphics pipeline is enabled, therefore it's recommended to disable it until the + // problematic area gets addressed and fixed. http://anglebug.com/404581992 ANGLE_FEATURE_CONDITION(&mFeatures, supportsGraphicsPipelineLibrary, mGraphicsPipelineLibraryFeatures.graphicsPipelineLibrary == VK_TRUE && (!isNvidia || driverVersion >= angle::VersionTriple(531, 0, 0)) && - !isRADV); + !isRADV && !isARMProprietary); - // The following drivers are known to key the pipeline cache blobs with vertex input and - // fragment output state, causing draw-time pipeline creation to miss the cache regardless of - // warm up: + // When VK_EXT_graphics_pipeline_library is not used: + // + // The following drivers are known to key the pipeline cache blobs with vertex input and + // fragment output state, causing draw-time pipeline creation to miss the cache regardless of + // warm up: // - // - ARM drivers - // - Imagination drivers + // - ARM proprietary drivers + // - Imagination drivers // - // The following drivers are instead known to _not_ include said state, and hit the cache at - // draw time. + // The following drivers are instead known to _not_ include said state, and hit the cache at + // draw time. // - // - SwiftShader - // - Open source Qualcomm drivers + // - SwiftShader + // - Open source Qualcomm drivers // - // The situation is unknown for other drivers. + // The situation is unknown for other drivers. // - // Additionally, numerous tests that previously never created a Vulkan pipeline fail or crash on - // proprietary Qualcomm drivers when they do during cache warm up. On Intel/Linux, one trace - // shows flakiness with this. - const bool libraryBlobsAreReusedByMonolithicPipelines = !isARM && !isPowerVR; - ANGLE_FEATURE_CONDITION(&mFeatures, warmUpPipelineCacheAtLink, - libraryBlobsAreReusedByMonolithicPipelines && !isQualcommProprietary && - !(IsLinux() && isIntel) && !(IsChromeOS() && isSwiftShader)); + // Additionally, numerous tests that previously never created a Vulkan pipeline fail or crash + // on proprietary Qualcomm drivers when they do during cache warm up. On Intel/Linux, one + // trace shows flakiness with this. + // + // When VK_EXT_graphics_pipeline_library is used, warm up is always enabled as the chances of + // blobs being reused is very high. + const bool libraryBlobsAreReusedByMonolithicPipelines = !isARMProprietary && !isPowerVR; + ANGLE_FEATURE_CONDITION( + &mFeatures, warmUpPipelineCacheAtLink, + mFeatures.supportsGraphicsPipelineLibrary.enabled || + (libraryBlobsAreReusedByMonolithicPipelines && !isQualcommProprietary && + !(IsLinux() && isIntel) && !(IsChromeOS() && isSwiftShader))); // On SwiftShader, no data is retrieved from the pipeline cache, so there is no reason to // serialize it or put it in the blob cache. - // For Windows Nvidia Vulkan driver older than 520, Vulkan pipeline cache will only generate one - // single huge cache for one process shared by all graphics pipelines in the same process, which - // can be huge. - const bool nvVersionLessThan520 = isNvidia && driverVersion < angle::VersionTriple(520, 0, 0); - ANGLE_FEATURE_CONDITION(&mFeatures, hasEffectivePipelineCacheSerialization, - !isSwiftShader && !nvVersionLessThan520); + // For Windows NVIDIA Vulkan driver, Vulkan pipeline cache will only generate one + // single huge cache for one process shared by all graphics pipelines in the same process, + // which can be huge. zlib take long time to compress it. + ANGLE_FEATURE_CONDITION(&mFeatures, skipPipelineCacheSerialization, isSwiftShader || isNvidia); // Practically all drivers still prefer to do cross-stage linking. // graphicsPipelineLibraryFastLinking allows them to quickly produce working pipelines, but it // is typically not as efficient as complete pipelines. // - // This optimization is disabled on the Intel/windows driver before 31.0.101.5379 due to driver - // bugs. - // This optimization is disabled for Samsung. - ANGLE_FEATURE_CONDITION( - &mFeatures, preferMonolithicPipelinesOverLibraries, - mFeatures.supportsGraphicsPipelineLibrary.enabled && - !(IsWindows() && isIntel && driverVersion < angle::VersionTriple(101, 5379, 0)) && - !isSamsung); + // Unfortunately, the monolithic pipeline is not required to produce the exact same output as + // linked-pipelines, which violates OpenGL ES rules: + // + // Rule 4 The same vertex or fragment shader will produce the same result when run multiple + // times with the same input. The wording 'the same shader' means a program object that is + // populated with the same source strings, which are compiled and then linked, possibly + // multiple times, and which program object is then executed using the same GL state vector. + // Invariance is relaxed for shaders with side effects, such as image stores, image atomic + // operations, or accessing atomic counters (see section A.5) + // + // For that reason, this feature is disabled by default. An application that does not rely on + // the above rule and would like to benefit from the gains may override this. + ANGLE_FEATURE_CONDITION(&mFeatures, preferMonolithicPipelinesOverLibraries, + mFeatures.supportsGraphicsPipelineLibrary.enabled && false); + + // To avoid memory bloating due to using pipeline caches per program, the pipeline cache in the + // renderer can be used. + ANGLE_FEATURE_CONDITION(&mFeatures, preferGlobalPipelineCache, + isNvidia || (isAMD && !isRADV) || isSamsung || isQualcommProprietary); // Whether the pipeline caches should merge into the global pipeline cache. This should only be // enabled on platforms if: // + // - preferGlobalPipelineCache is not enabled // - VK_EXT_graphics_pipeline_library is not supported. In that case, only the program's cache // used during warm up is merged into the global cache for later monolithic pipeline creation. // - VK_EXT_graphics_pipeline_library is supported, monolithic pipelines are preferred, and the // driver is able to reuse blobs from partial pipelines when creating monolithic pipelines. ANGLE_FEATURE_CONDITION(&mFeatures, mergeProgramPipelineCachesToGlobalCache, - !mFeatures.supportsGraphicsPipelineLibrary.enabled || - (mFeatures.preferMonolithicPipelinesOverLibraries.enabled && - libraryBlobsAreReusedByMonolithicPipelines)); + !mFeatures.preferGlobalPipelineCache.enabled && + (!mFeatures.supportsGraphicsPipelineLibrary.enabled || + (mFeatures.preferMonolithicPipelinesOverLibraries.enabled && + libraryBlobsAreReusedByMonolithicPipelines))); + + // Whether all accesses to pipeline cache need to be externally synchronized. This should only + // be enabled on platforms if: + // + // - mergeProgramPipelineCachesToGlobalCache is enabled + // - preferMonolithicPipelinesOverLibraries is enabled + // - stale nvidia drivers + ANGLE_FEATURE_CONDITION(&mFeatures, externallySynchronizePipelineCacheAccess, + mFeatures.mergeProgramPipelineCachesToGlobalCache.enabled || + mFeatures.preferMonolithicPipelinesOverLibraries.enabled || + (isNvidia && driverVersion < angle::VersionTriple(441, 0, 0))); ANGLE_FEATURE_CONDITION(&mFeatures, enableAsyncPipelineCacheCompression, true); + // Enable using an extra submit fence for the command batches. In case there is an external + // fence during the main submission, this extra fence will be used for an empty submission right + // after it. + ANGLE_FEATURE_CONDITION(&mFeatures, enableExtraSubmitFence, false); + // Sync monolithic pipelines to the blob cache occasionally on platforms that would benefit from // it: // @@ -5714,7 +6377,7 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, mFeatures.preferMonolithicPipelinesOverLibraries.enabled && (!IsAndroid() || mFeatures.enableAsyncPipelineCacheCompression.enabled); ANGLE_FEATURE_CONDITION(&mFeatures, syncMonolithicPipelinesToBlobCache, - mFeatures.hasEffectivePipelineCacheSerialization.enabled && + !mFeatures.skipPipelineCacheSerialization.enabled && (hasNoPipelineWarmUp || canSyncLargeMonolithicCache)); // Enable the feature on Samsung by default, because it has big blob cache. @@ -5731,18 +6394,18 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, verifyPipelineCacheInBlobCache, !mFeatures.hasBlobCacheThatEvictsOldItemsFirst.enabled); - // On ARM, dynamic state for stencil write mask doesn't work correctly in the presence of - // discard or alpha to coverage, if the static state provided when creating the pipeline has a - // value of 0. + // On ARM proprietary driver, dynamic state for stencil write mask doesn't work correctly in the + // presence of discard or alpha to coverage, if the static state provided when creating the + // pipeline has a value of 0. Fixed in r43p0 release. ANGLE_FEATURE_CONDITION(&mFeatures, useNonZeroStencilWriteMaskStaticState, - isARM && driverVersion < angle::VersionTriple(43, 0, 0)); + isARMProprietary && driverVersion < angle::VersionTriple(43, 0, 0)); // On some vendors per-sample shading is not enabled despite the presence of a Sample // decoration. Guard against this by parsing shader for "sample" decoration and explicitly // enabling per-sample shading pipeline state. ANGLE_FEATURE_CONDITION(&mFeatures, explicitlyEnablePerSampleShading, !isQualcommProprietary); - ANGLE_FEATURE_CONDITION(&mFeatures, explicitlyCastMediumpFloatTo16Bit, isARM); + ANGLE_FEATURE_CONDITION(&mFeatures, explicitlyCastMediumpFloatTo16Bit, isARMProprietary); // Force to create swapchain with continuous refresh on shared present. Disabled by default. // Only enable it on integrations without EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID passthrough. @@ -5758,12 +6421,11 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Only enable VK_EXT_host_image_copy on hardware where identicalMemoryTypeRequirements is set. // That lets ANGLE avoid having to fallback to non-host-copyable image allocations if the // host-copyable one fails due to out-of-that-specific-kind-of-memory. - // - // Disabled on Fuchsia until they upgrade their version of VVL. ANGLE_FEATURE_CONDITION(&mFeatures, supportsHostImageCopy, mHostImageCopyFeatures.hostImageCopy == VK_TRUE && - mHostImageCopyProperties.identicalMemoryTypeRequirements && - !IsFuchsia()); + mHostImageCopyProperties.identicalMemoryTypeRequirements); + // Software renderers always benefit from host-image-copy, because that's just memcpy. + ANGLE_FEATURE_CONDITION(&mFeatures, allowHostImageCopyAfterInitialUpload, isSoftwareRenderer); // 1) host vk driver does not natively support ETC format. // 2) host vk driver supports BC format. @@ -5814,23 +6476,25 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, preferSubmitOnAnySamplesPassedQueryEnd, isTileBasedRenderer); - // ARM driver appears having a bug that if we did not wait for submission to complete, but call - // vkGetQueryPoolResults(VK_QUERY_RESULT_WAIT_BIT), it may result VK_NOT_READY. - // https://issuetracker.google.com/253522366 + // ARM proprietary driver appears having a bug that if we did not wait for submission to + // complete, but call vkGetQueryPoolResults(VK_QUERY_RESULT_WAIT_BIT), it may result + // VK_NOT_READY. https://issuetracker.google.com/253522366 // // Workaround for nvidia earlier version driver which appears having a bug that On older nvidia // driver, vkGetQueryPoolResult() with VK_QUERY_RESULT_WAIT_BIT may result in incorrect result. // In that case we force into CPU wait for submission to complete. http://anglebug.com/42265186 - ANGLE_FEATURE_CONDITION(&mFeatures, forceWaitForSubmissionToCompleteForQueryResult, - isARM || (isNvidia && driverVersion < angle::VersionTriple(470, 0, 0))); + ANGLE_FEATURE_CONDITION( + &mFeatures, forceWaitForSubmissionToCompleteForQueryResult, + isARMProprietary || (isNvidia && driverVersion < angle::VersionTriple(470, 0, 0))); - // Some ARM drivers may not free memory in "vkFreeCommandBuffers()" without + // Some ARM proprietary drivers may not free memory in "vkFreeCommandBuffers()" without // VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT flag. - ANGLE_FEATURE_CONDITION(&mFeatures, useResetCommandBufferBitForSecondaryPools, isARM); + ANGLE_FEATURE_CONDITION(&mFeatures, useResetCommandBufferBitForSecondaryPools, + isARMProprietary); - // Intel and AMD mesa drivers need depthBiasConstantFactor to be doubled to align with GL. + // Intel, Mali and AMD mesa drivers need depthBiasConstantFactor to be doubled to align with GL. ANGLE_FEATURE_CONDITION(&mFeatures, doubleDepthBiasConstantFactor, - (isIntel && !IsWindows()) || isRADV || isNvidia); + (isIntel && !IsWindows()) || isMesaPanVK || isRADV || isNvidia); // Required to pass android.media.codec.cts.EncodeDecodeTest // https://issuetracker.google.com/246218584 @@ -5843,54 +6507,54 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsTimelineSemaphore, mTimelineSemaphoreFeatures.timelineSemaphore == VK_TRUE); - // 8bit storage features - ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitStorageBuffer, - m8BitStorageFeatures.storageBuffer8BitAccess == VK_TRUE); - - ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitUniformAndStorageBuffer, - m8BitStorageFeatures.uniformAndStorageBuffer8BitAccess == VK_TRUE); - - ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitPushConstant, - m8BitStorageFeatures.storagePushConstant8 == VK_TRUE); - - // 16bit storage features - ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitStorageBuffer, - m16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE); - - ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitUniformAndStorageBuffer, - m16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE); - - ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitPushConstant, - m16BitStorageFeatures.storagePushConstant16 == VK_TRUE); - - ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitInputOutput, - m16BitStorageFeatures.storageInputOutput16 == VK_TRUE); - #if defined(ANGLE_PLATFORM_ANDROID) ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalFormatResolve, mExternalFormatResolveFeatures.externalFormatResolve == VK_TRUE); + + // We can fully support GL_EXT_YUV_target iff we have support for + // VK_ANDROID_external_format_resolve. + ANGLE_FEATURE_CONDITION(&mFeatures, supportsYuvTarget, + mFeatures.supportsExternalFormatResolve.enabled); + #else ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalFormatResolve, false); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsYuvTarget, false); #endif // VkEvent has much bigger overhead. Until we know that it helps desktop GPUs, we restrict it to - // TBRs. Also enabled for SwiftShader so that we get more test coverage in bots. + // TBRs. Also enabled for testing drivers to get more test coverage in bots. ANGLE_FEATURE_CONDITION(&mFeatures, useVkEventForImageBarrier, - isTileBasedRenderer || isSwiftShader); + isTileBasedRenderer || isSoftwareRenderer); ANGLE_FEATURE_CONDITION(&mFeatures, useVkEventForBufferBarrier, - isTileBasedRenderer || isSwiftShader); + isTileBasedRenderer || isSoftwareRenderer); - ANGLE_FEATURE_CONDITION(&mFeatures, supportsMaintenance5, - mMaintenance5Features.maintenance5 == VK_TRUE); + // VkEvent is better than pipeline barriers on Mali GPUs with vertex sync deferred mode enabled. + // Be unable to query GPU features currently, we restrict it to Mali non-JobManagerBased GPUs. + ANGLE_FEATURE_CONDITION( + &mFeatures, isVertexSyncDeferred, + mFeatures.useVkEventForBufferBarrier.enabled && isARM && !isMaliJobManagerBasedGPU); + // vkCmdResetEvent adds extra GPU overhead and ARM prefers CPU overhead of creating/destroying + // VkEvent instead of GPU overhead associated with vkCmdResetEvent. + ANGLE_FEATURE_CONDITION(&mFeatures, recycleVkEvent, isSwiftShader); + + // Disable for Samsung, details here -> http://anglebug.com/386749841#comment21 ANGLE_FEATURE_CONDITION(&mFeatures, supportsDynamicRendering, - mDynamicRenderingFeatures.dynamicRendering == VK_TRUE); + mDynamicRenderingFeatures.dynamicRendering == VK_TRUE && !isSamsung); + + // Don't enable VK_KHR_maintenance5 without VK_KHR_dynamic_rendering + ANGLE_FEATURE_CONDITION(&mFeatures, supportsMaintenance5, + mFeatures.supportsDynamicRendering.enabled && + mMaintenance5Features.maintenance5 == VK_TRUE); // Disabled on Nvidia driver due to a bug with attachment location mapping, resulting in // incorrect rendering in the presence of gaps in locations. http://anglebug.com/372883691. + // + // Disable for Samsung, details here -> http://anglebug.com/386749841#comment21 ANGLE_FEATURE_CONDITION( &mFeatures, supportsDynamicRenderingLocalRead, - mDynamicRenderingLocalReadFeatures.dynamicRenderingLocalRead == VK_TRUE && !isNvidia); + mDynamicRenderingLocalReadFeatures.dynamicRenderingLocalRead == VK_TRUE && + !(isNvidia || isSamsung)); // Using dynamic rendering when VK_KHR_dynamic_rendering_local_read is available, because that's // needed for framebuffer fetch, MSRTT and advanced blend emulation. @@ -5902,9 +6566,12 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Emulation of GL_EXT_multisampled_render_to_texture is not possible with dynamic rendering. // That support is also not sacrificed for dynamic rendering. // - // Use of dynamic rendering is disabled on older ARM drivers due to driver bugs + // Use of dynamic rendering is disabled on older ARM proprietary drivers due to driver bugs // (http://issuetracker.google.com/356051947). // + // Use of dynamic rendering is disabled on older Qualcomm drivers due to driver bugs + // (http://crbug.com/415738891). + // // Use of dynamic rendering on PowerVR devices is disabled for performance reasons // (http://issuetracker.google.com/372273294). const bool hasLegacyDitheringV1 = @@ -5913,12 +6580,14 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, const bool emulatesMultisampledRenderToTexture = mFeatures.enableMultisampledRenderToTexture.enabled && !mFeatures.supportsMultisampledRenderToSingleSampled.enabled; - ANGLE_FEATURE_CONDITION(&mFeatures, preferDynamicRendering, - mFeatures.supportsDynamicRendering.enabled && - mFeatures.supportsDynamicRenderingLocalRead.enabled && - !hasLegacyDitheringV1 && !emulatesMultisampledRenderToTexture && - !(isARM && driverVersion < angle::VersionTriple(52, 0, 0)) && - !isPowerVR); + ANGLE_FEATURE_CONDITION( + &mFeatures, preferDynamicRendering, + mFeatures.supportsDynamicRendering.enabled && + mFeatures.supportsDynamicRenderingLocalRead.enabled && !hasLegacyDitheringV1 && + !emulatesMultisampledRenderToTexture && + !(isARMProprietary && driverVersion < angle::VersionTriple(52, 0, 0)) && + !(isQualcommProprietary && driverVersion < angle::VersionTriple(512, 801, 0)) && + !isPowerVR); // 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 @@ -5948,8 +6617,8 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsSynchronization2, mSynchronization2Features.synchronization2 == VK_TRUE); - // Disable descriptorSet cache for SwiftShader to ensure the code path gets tested. - ANGLE_FEATURE_CONDITION(&mFeatures, descriptorSetCache, !isSwiftShader); + // Disable descriptorSet cache for testing drivers to ensure the code path gets tested. + ANGLE_FEATURE_CONDITION(&mFeatures, descriptorSetCache, !isSoftwareRenderer); ANGLE_FEATURE_CONDITION(&mFeatures, supportsImageCompressionControl, mImageCompressionControlFeatures.imageCompressionControl == VK_TRUE); @@ -5964,9 +6633,20 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, &mFeatures, supportsTextureCompressionAstcHdr, mTextureCompressionASTCHDRFeatures.textureCompressionASTC_HDR == VK_TRUE); + // Not all hardware can support 3D textures with ASTC HDR (http://anglebug.com/416095435) ANGLE_FEATURE_CONDITION( - &mFeatures, supportsUniformBufferStandardLayout, - mUniformBufferStandardLayoutFeatures.uniformBufferStandardLayout == VK_TRUE); + &mFeatures, supportsAstcHdr3dTextures, + mFeatures.supportsTextureCompressionAstcHdr.enabled && CanSupportAstcHdr3D(this)); + + // http://anglebug.com/42264006 + // GL_EXT_clip_cull_distance also adds features to geometry and tessellation shaders, which are + // currently disabled. + ANGLE_FEATURE_CONDITION(&mFeatures, supportsClipCullDistanceInGSAndTS, false); + + // http://anglebug.com/442950569 + // feature is currently experimental (i.e. dont default enable even if device supports it) + // keep it as an opt-in override instead + ANGLE_FEATURE_CONDITION(&mFeatures, supportsBufferDeviceAddress, false); // Disable memory report feature overrides if extension is not supported. if ((mFeatures.logMemoryReportCallbacks.enabled || mFeatures.logMemoryReportStats.enabled) && @@ -5996,10 +6676,189 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsAngleRgbxInternalFormat, !isSamsung); ANGLE_FEATURE_CONDITION(&mFeatures, supportsAppleClipDistance, !isSamsung); - // Enable the use of below native kernels - // Each builtin kernel gets its own feature and condition, for now a single feature condition is - // setup - ANGLE_FEATURE_CONDITION(&mFeatures, usesNativeBuiltinClKernel, isSamsung); + // Force enable sample usage for AHB images for Samsung + ANGLE_FEATURE_CONDITION(&mFeatures, forceSampleUsageForAhbBackedImages, isSamsung); + + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsAstcDecodeMode, + ExtensionFound(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, deviceExtensionNames)); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsAstcDecodeModeRgb9e5, + mPhysicalDeviceAstcDecodeFeatures.decodeModeSharedExponent == VK_TRUE && + mFeatures.supportsAstcDecodeMode.enabled); + + // Disable uniformAndStorageBuffer16BitAccess and supportsShaderFloat16 on Samsung devices + ANGLE_FEATURE_CONDITION( + &mFeatures, supports16BitUniformAndStorageBuffer, + m16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE && !isSamsung); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat16, + mShaderFloat16Int8Features.shaderFloat16 == VK_TRUE && !isSamsung); + + // http://anglebug.com/440941211: + // Disable the feature on Windows Intel because some shaders using 16-bit floats crash + // http://anglebug.com/443302350 + // http://anglebug.com/443302625 + // Temporarily disable the feature on PowerVR while the above 2 bugs are under investigations + // http://anglebug.com/446159597 + // Disable the feature on Samsung devices + // https://b.corp.google.com/issues/446844410 + // Disable on driver implementations other than ARM proprietary until the performance impact on + // them is verified. + ANGLE_FEATURE_CONDITION(&mFeatures, convertLowpAndMediumpFloatUniformsTo16Bits, + mFeatures.supports16BitUniformAndStorageBuffer.enabled && + mFeatures.supportsShaderFloat16.enabled && isARMProprietary); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsUnifiedImageLayouts, + mUnifiedImageLayoutsFeatures.unifiedImageLayouts == VK_TRUE); + + // Disable the feature on Samsung devices - http://anglebug.com/467875813 + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsGlobalPriority, + ExtensionFound(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, deviceExtensionNames) && !isSamsung); + + // REALTIME priority is not permitted on most operating systems. This feature is limited to + // Android for now. + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsGlobalPriorityQuery, + mFeatures.supportsGlobalPriority.enabled && + mPhysicalDeviceGlobalPriorityQueryFeatures.globalPriorityQuery == VK_TRUE && + IsAndroid()); + + // There are use cases where synchronization is not performed properly when texture is modified + // between different contexts. To avoid rendering artifacts, force submit staged updates for + // Samsung. + ANGLE_FEATURE_CONDITION(&mFeatures, forceSubmitImmutableTextureUpdates, isSamsung); + + // Don't expose these 2 extensions on Samsung devices - + // 1. GL_ANGLE_shader_pixel_local_storage + // 2. GL_ANGLE_shader_pixel_local_storage_coherent + ANGLE_FEATURE_CONDITION(&mFeatures, supportShaderPixelLocalStorageAngle, !isSamsung); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportFragmentShadingRateExtExtensions, + mFeatures.supportsFragmentShadingRate.enabled && !isSamsung); + + // http://issuetracker.google.com/372273294 + // Older Unity titles are calling glClear on depth/stencil followed by a call to + // glInvalidateFramebuffer, but expect the contents of the framebuffer to still be valid. + // In this case, we can't drop the clears that we've deferred. + ANGLE_FEATURE_CONDITION(&mFeatures, dropDepthStencilClearOnInvalidate, false); + + // VK_QCOM_tile_memory_heap is available + ANGLE_FEATURE_CONDITION(&mFeatures, supportsTileMemoryHeap, + /*mTileMemoryHeapFeatures.tileMemoryHeap == VK_TRUE*/ false); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsAstc3d, + mTextureCompressionASTC3DFeatures.textureCompressionASTC_3D == VK_TRUE); + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Features specific to OpenCL backend + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + if (mGlobalOps->getFrontendApi() == GlobalOps::Api::OpenCL) + { + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsExternalMemoryHost, + ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames)); + + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsUniformBufferStandardLayout, + mUniformBufferStandardLayoutFeatures.uniformBufferStandardLayout == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat16, + mShaderFloat16Int8Features.shaderFloat16 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderInt8, + mShaderFloat16Int8Features.shaderInt8 == VK_TRUE); + + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsShaderIntegerDotProduct, + mShaderIntegerDotProductFeatures.shaderIntegerDotProduct == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat64, + mPhysicalDeviceFeatures.shaderFloat64 == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderAtomicInt64, + mShaderAtomicInt64Features.shaderBufferInt64Atomics == VK_TRUE && + mShaderAtomicInt64Features.shaderSharedInt64Atomics == VK_TRUE); + + // Rounding features from VK_KHR_float_controls extension + ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp16, + mFloatControlProperties.shaderDenormFlushToZeroFloat16 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp32, + mFloatControlProperties.shaderDenormFlushToZeroFloat32 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp64, + mFloatControlProperties.shaderDenormFlushToZeroFloat64 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp16, + mFloatControlProperties.shaderDenormPreserveFloat16 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp32, + mFloatControlProperties.shaderDenormPreserveFloat32 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp64, + mFloatControlProperties.shaderDenormPreserveFloat64 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp16, + mFloatControlProperties.shaderRoundingModeRTEFloat16 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp32, + mFloatControlProperties.shaderRoundingModeRTEFloat32 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp64, + mFloatControlProperties.shaderRoundingModeRTEFloat64 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp16, + mFloatControlProperties.shaderRoundingModeRTZFloat16 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp32, + mFloatControlProperties.shaderRoundingModeRTZFloat32 == VK_TRUE); + ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp64, + mFloatControlProperties.shaderRoundingModeRTZFloat64 == VK_TRUE); + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsSignedZeroInfNanPreserveFp16, + mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat16 == VK_TRUE); + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsSignedZeroInfNanPreserveFp32, + mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat32 == VK_TRUE); + ANGLE_FEATURE_CONDITION( + &mFeatures, supportsSignedZeroInfNanPreserveFp64, + mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat64 == VK_TRUE); + + // 8bit storage features + ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitStorageBuffer, + m8BitStorageFeatures.storageBuffer8BitAccess == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitUniformAndStorageBuffer, + m8BitStorageFeatures.uniformAndStorageBuffer8BitAccess == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitPushConstant, + m8BitStorageFeatures.storagePushConstant8 == VK_TRUE); + + // 16bit storage features + ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitStorageBuffer, + m16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE); + + ANGLE_FEATURE_CONDITION( + &mFeatures, supports16BitUniformAndStorageBuffer, + m16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitPushConstant, + m16BitStorageFeatures.storagePushConstant16 == VK_TRUE); + + ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitInputOutput, + m16BitStorageFeatures.storageInputOutput16 == VK_TRUE); + + // Enable the use of below native kernels + // Each builtin kernel gets its own feature and condition, for now a single feature + // condition is setup + ANGLE_FEATURE_CONDITION(&mFeatures, usesNativeBuiltinClKernel, isSamsung); + + ANGLE_FEATURE_CONDITION(&mFeatures, debugClDumpCommandStream, false); + + // Set limits to expose to OpenCL. + // This information cannot yet be queried from the Vulkan device. + if (isSamsung && mFeatures.supportsShaderFloat64.enabled) + { + mNativeVectorWidthDouble = 1; + mPreferredVectorWidthDouble = 1; + } + if (isSamsung && mFeatures.supportsShaderFloat16.enabled) + { + mNativeVectorWidthHalf = 2; + mPreferredVectorWidthHalf = 8; + } + } } void Renderer::appBasedFeatureOverrides(const vk::ExtensionNameList &extensions) {} @@ -6082,8 +6941,7 @@ angle::Result Renderer::getPipelineCache(vk::ErrorContext *context, ANGLE_TRY(ensurePipelineCacheInitialized(context)); angle::SimpleMutex *pipelineCacheMutex = - context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled || - context->getFeatures().preferMonolithicPipelinesOverLibraries.enabled + context->getFeatures().externallySynchronizePipelineCacheAccess.enabled ? &mPipelineCacheMutex : nullptr; @@ -6208,9 +7066,7 @@ angle::Result Renderer::getLockedPipelineCacheDataIfNew(vk::ErrorContext *contex return angle::Result::Continue; } -angle::Result Renderer::syncPipelineCacheVk(vk::ErrorContext *context, - vk::GlobalOps *globalOps, - const gl::Context *contextGL) +angle::Result Renderer::syncPipelineCacheVk(const gl::Context *contextGL) { // Skip syncing until pipeline cache is initialized. if (!mPipelineCacheInitialized) @@ -6229,7 +7085,8 @@ angle::Result Renderer::syncPipelineCacheVk(vk::ErrorContext *context, return angle::Result::Continue; } - mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod; + mPipelineCacheVkUpdateTimeout = + mFeatures.syncPipelineCacheToBlobCacheEveryFrame.enabled ? 1 : kPipelineCacheVkUpdatePeriod; ContextVk *contextVk = vk::GetImpl(contextGL); @@ -6247,7 +7104,7 @@ angle::Result Renderer::syncPipelineCacheVk(vk::ErrorContext *context, { std::unique_lock lock(mPipelineCacheMutex); ANGLE_TRY(getLockedPipelineCacheDataIfNew( - context, &pipelineCacheSize, mPipelineCacheSizeAtLastSync, &pipelineCacheData)); + contextVk, &pipelineCacheSize, mPipelineCacheSizeAtLastSync, &pipelineCacheData)); } if (pipelineCacheData.empty()) { @@ -6255,6 +7112,8 @@ angle::Result Renderer::syncPipelineCacheVk(vk::ErrorContext *context, } mPipelineCacheSizeAtLastSync = pipelineCacheSize; + vk::GlobalOps *globalOps = getGlobalOps(); + ASSERT(globalOps); if (mFeatures.enableAsyncPipelineCacheCompression.enabled) { // zlib compression ratio normally ranges from 2:1 to 5:1. Set kMaxTotalSize to 64M to @@ -6277,6 +7136,12 @@ angle::Result Renderer::syncPipelineCacheVk(vk::ErrorContext *context, return angle::Result::Continue; } +angle::Result Renderer::onFrameBoundary(const gl::Context *contextGL) +{ + ASSERT(contextGL); + return syncPipelineCacheVk(contextGL); +} + // These functions look at the mandatory format for support, and fallback to querying the device (if // necessary) to test the availability of the bits. bool Renderer::hasLinearImageFormatFeatureBits(angle::FormatID formatID, @@ -6299,6 +7164,13 @@ VkFormatFeatureFlags Renderer::getImageFormatFeatureBits( return getFormatFeatureBits<&VkFormatProperties::optimalTilingFeatures>(formatID, featureBits); } +VkFormatFeatureFlags Renderer::getBufferFormatFeatureBits( + angle::FormatID formatID, + const VkFormatFeatureFlags featureBits) const +{ + return getFormatFeatureBits<&VkFormatProperties::bufferFeatures>(formatID, featureBits); +} + bool Renderer::hasImageFormatFeatureBits(angle::FormatID formatID, const VkFormatFeatureFlags featureBits) const { @@ -6344,6 +7216,7 @@ angle::Result Renderer::queueSubmitOneOff(vk::ErrorContext *context, primary.getHandle(), waitSemaphore, waitSemaphoreStageMasks, submitQueueSerial)); + mSubmittedResourceUse.setQueueSerial(submitQueueSerial); *queueSerialOut = submitQueueSerial; if (primary.valid()) { @@ -6362,9 +7235,11 @@ angle::Result Renderer::queueSubmitWaitSemaphore(vk::ErrorContext *context, VkPipelineStageFlags waitSemaphoreStageMasks, QueueSerial submitQueueSerial) { - return mCommandQueue.queueSubmitOneOff(context, vk::ProtectionType::Unprotected, priority, - VK_NULL_HANDLE, waitSemaphore.getHandle(), - waitSemaphoreStageMasks, submitQueueSerial); + ANGLE_TRY(mCommandQueue.queueSubmitOneOff(context, vk::ProtectionType::Unprotected, priority, + VK_NULL_HANDLE, waitSemaphore.getHandle(), + waitSemaphoreStageMasks, submitQueueSerial)); + mSubmittedResourceUse.setQueueSerial(submitQueueSerial); + return angle::Result::Continue; } template @@ -6441,17 +7316,20 @@ void Renderer::cleanupGarbage(bool *anyGarbageCleanedOut) bool anyCleaned = false; // Clean up general garbage - anyCleaned = (mSharedGarbageList.cleanupSubmittedGarbage(this) > 0) || anyCleaned; + anyCleaned = mSharedGarbageList.cleanupSubmittedGarbage(this) > 0 || anyCleaned; // Clean up suballocation garbages - anyCleaned = (mSuballocationGarbageList.cleanupSubmittedGarbage(this) > 0) || anyCleaned; + anyCleaned = mSuballocationGarbageList.cleanupSubmittedGarbage(this) > 0 || anyCleaned; // Note: do this after clean up mSuballocationGarbageList so that we will have more chances to // find orphaned blocks being empty. - anyCleaned = (mOrphanedBufferBlockList.pruneEmptyBufferBlocks(this) > 0) || anyCleaned; + anyCleaned = mOrphanedBufferBlockList.pruneEmptyBufferBlocks(this) > 0 || anyCleaned; // Clean up RefCountedEvent that are done resetting - anyCleaned = (mRefCountedEventRecycler.cleanupResettingEvents(this) > 0) || anyCleaned; + anyCleaned = mRefCountedEventRecycler.cleanupResettingEvents(this) > 0 || anyCleaned; + + // Clean up samplers that couldn't be destroyed when the share group was. + anyCleaned = cleanupOrphanedSamplers() || anyCleaned; if (anyGarbageCleanedOut != nullptr) { @@ -6459,6 +7337,50 @@ void Renderer::cleanupGarbage(bool *anyGarbageCleanedOut) } } +bool Renderer::cleanupOrphanedSamplers() +{ + std::unique_lock lock(mOrphanedSamplerMutex); + + if (mOrphanedSamplers.empty() && mOrphanedSamplerYcbcrConversions.empty()) + { + return false; + } + + // Destroy any sampler that is no longer referenced. + std::vector remainingSamplers; + for (SharedSamplerPtr &sampler : mOrphanedSamplers) + { + if (!sampler.unique()) + { + remainingSamplers.push_back(sampler); + } + } + const uint32_t destroyedSamplerCount = + static_cast(mOrphanedSamplers.size() - remainingSamplers.size()); + onDeallocateHandle(vk::HandleType::Sampler, destroyedSamplerCount); + mOrphanedSamplers = std::move(remainingSamplers); + + bool anyCleaned = destroyedSamplerCount > 0; + + // If all samplers are gone, destroy all the ycbcr conversion objects too. We don't track which + // samplers use which ycbcr conversion objects, so they are destroyed conservatively. + if (remainingSamplers.empty()) + { + anyCleaned = anyCleaned || !mOrphanedSamplerYcbcrConversions.empty(); + for (VkSamplerYcbcrConversion handle : mOrphanedSamplerYcbcrConversions) + { + vk::SamplerYcbcrConversion conversion; + conversion.setHandle(handle); + conversion.destroy(mDevice); + } + onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, + static_cast(mOrphanedSamplerYcbcrConversions.size())); + mOrphanedSamplerYcbcrConversions.clear(); + } + + return anyCleaned; +} + void Renderer::cleanupPendingSubmissionGarbage() { // Check if pending garbage is still pending. If not, move them to the garbage list. @@ -6487,6 +7409,13 @@ uint64_t Renderer::getMaxFenceWaitTimeNs() const return kMaxFenceWaitTimeNs; } +VkDeviceSize Renderer::padVertexAttribBufferSizeIfNeeded(VkDeviceSize bufferSize) +{ + // When the padding feature is disabled, the max attribute stride should remain 0. + ASSERT(mFeatures.padBuffersToMaxVertexAttribStride.enabled ^ (mMaxVertexAttribStride == 0)); + return bufferSize + mMaxVertexAttribStride; +} + void Renderer::setGlobalDebugAnnotator(bool *installedAnnotatorOut) { // Install one of two DebugAnnotator classes: @@ -6582,14 +7511,11 @@ void Renderer::initializeDeviceExtensionEntryPointsFromCore() const } } -angle::Result Renderer::submitCommands( - vk::ErrorContext *context, - vk::ProtectionType protectionType, - egl::ContextPriority contextPriority, - const vk::Semaphore *signalSemaphore, - const vk::SharedExternalFence *externalFence, - std::vector &&imagesToTransitionToForeign, - const QueueSerial &submitQueueSerial) +angle::Result Renderer::submitCommands(vk::ErrorContext *context, + const vk::Semaphore *signalSemaphore, + const vk::SharedExternalFence *externalFence, + const QueueSerial &submitQueueSerial, + CommandsState &&commandsState) { ASSERT(signalSemaphore == nullptr || signalSemaphore->valid()); const VkSemaphore signalVkSemaphore = @@ -6601,15 +7527,48 @@ angle::Result Renderer::submitCommands( externalFenceCopy = *externalFence; } - ANGLE_TRY(mCommandQueue.submitCommands( - context, protectionType, contextPriority, signalVkSemaphore, std::move(externalFenceCopy), - std::move(imagesToTransitionToForeign), submitQueueSerial)); + ANGLE_TRY(mCommandQueue.submitCommands(context, signalVkSemaphore, std::move(externalFenceCopy), + submitQueueSerial, std::move(commandsState))); ANGLE_TRY(mCommandQueue.postSubmitCheck(context)); return angle::Result::Continue; } +angle::Result Renderer::insertOneOffSubmitDebugMarker(vk::ErrorContext *context, + vk::ProtectionType protectionType, + egl::ContextPriority priority, + QueueSubmitReason reason) +{ + if (!enableDebugUtils() && !angleDebuggerMode()) + { + return angle::Result::Continue; + } + + ScopedPrimaryCommandBuffer scopedCommandBuffer(getDevice()); + ANGLE_TRY(getCommandBufferOneOff(context, protectionType, &scopedCommandBuffer)); + PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get(); + insertSubmitDebugMarkerInCommandBuffer(commandBuffer, reason); + ANGLE_VK_TRY(context, commandBuffer.end()); + + QueueSerial queueSerial; + return queueSubmitOneOff(context, std::move(scopedCommandBuffer), protectionType, priority, + VK_NULL_HANDLE, 0, &queueSerial); +} + +void Renderer::insertSubmitDebugMarkerInCommandBuffer(PrimaryCommandBuffer &commandBuffer, + QueueSubmitReason reason) +{ + if (!enableDebugUtils() && !angleDebuggerMode()) + { + return; + } + + VkDebugUtilsLabelEXT labelInfo; + vk::MakeDebugUtilsLabel(GL_DEBUG_SOURCE_API, kQueueSubmitReason[reason], &labelInfo); + commandBuffer.insertDebugUtilsLabelEXT(labelInfo); +} + angle::Result Renderer::submitPriorityDependency(vk::ErrorContext *context, vk::ProtectionTypes protectionTypes, egl::ContextPriority srcContextPriority, @@ -6617,7 +7576,7 @@ angle::Result Renderer::submitPriorityDependency(vk::ErrorContext *context, SerialIndex index) { RendererScoped> semaphore(this); - ANGLE_VK_TRY(context, semaphore.get().get().init(mDevice)); + ANGLE_VK_TRY(context, semaphore.get().get().init(mDevice, VK_SEMAPHORE_TYPE_BINARY)); // First, submit already flushed commands / wait semaphores into the source Priority VkQueue. // Commands that are in the Secondary Command Buffers will be flushed into the new VkQueue. @@ -6628,6 +7587,7 @@ angle::Result Renderer::submitPriorityDependency(vk::ErrorContext *context, { vk::ProtectionType protectionType = protectionTypes.first(); protectionTypes.reset(protectionType); + CommandsState commandsState(this, protectionType, srcContextPriority); QueueSerial queueSerial(index, generateQueueSerial(index)); // Submit semaphore only if this is the last submission (all into the same VkQueue). @@ -6638,13 +7598,20 @@ angle::Result Renderer::submitPriorityDependency(vk::ErrorContext *context, semaphore.get().setQueueSerial(queueSerial); signalSemaphore = &semaphore.get().get(); } - ANGLE_TRY(submitCommands(context, protectionType, srcContextPriority, signalSemaphore, - nullptr, {}, queueSerial)); + + ANGLE_TRY(insertOneOffSubmitDebugMarker(context, protectionType, srcContextPriority, + QueueSubmitReason::ContextPriorityChange)); + ANGLE_TRY(submitCommands(context, signalSemaphore, nullptr, queueSerial, + std::move(commandsState))); + mSubmittedResourceUse.setQueueSerial(queueSerial); } // Submit only Wait Semaphore into the destination Priority (VkQueue). QueueSerial queueSerial(index, generateQueueSerial(index)); semaphore.get().setQueueSerial(queueSerial); + + ANGLE_TRY(insertOneOffSubmitDebugMarker(context, ProtectionType::Unprotected, + dstContextPriority, QueueSubmitReason::WaitSemaphore)); ANGLE_TRY(queueSubmitWaitSemaphore(context, dstContextPriority, semaphore.get().get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, queueSerial)); @@ -6676,43 +7643,6 @@ angle::Result Renderer::waitForResourceUseToFinishWithUserTimeout(vk::ErrorConte return mCommandQueue.waitForResourceUseToFinishWithUserTimeout(context, use, timeout, result); } -angle::Result Renderer::flushWaitSemaphores( - vk::ProtectionType protectionType, - egl::ContextPriority priority, - std::vector &&waitSemaphores, - std::vector &&waitSemaphoreStageMasks) -{ - ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::flushWaitSemaphores"); - mCommandQueue.flushWaitSemaphores(protectionType, priority, std::move(waitSemaphores), - std::move(waitSemaphoreStageMasks)); - - return angle::Result::Continue; -} - -angle::Result Renderer::flushRenderPassCommands( - vk::Context *context, - vk::ProtectionType protectionType, - egl::ContextPriority priority, - const vk::RenderPass &renderPass, - VkFramebuffer framebufferOverride, - vk::RenderPassCommandBufferHelper **renderPassCommands) -{ - ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::flushRenderPassCommands"); - return mCommandQueue.flushRenderPassCommands(context, protectionType, priority, renderPass, - framebufferOverride, renderPassCommands); -} - -angle::Result Renderer::flushOutsideRPCommands( - vk::Context *context, - vk::ProtectionType protectionType, - egl::ContextPriority priority, - vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands) -{ - ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::flushOutsideRPCommands"); - return mCommandQueue.flushOutsideRPCommands(context, protectionType, priority, - outsideRPCommands); -} - VkResult Renderer::queuePresent(vk::ErrorContext *context, egl::ContextPriority priority, const VkPresentInfoKHR &presentInfo) @@ -6730,34 +7660,30 @@ VkResult Renderer::queuePresent(vk::ErrorContext *context, template angle::Result Renderer::getCommandBufferImpl(vk::ErrorContext *context, vk::SecondaryCommandPool *commandPool, - vk::SecondaryCommandMemoryAllocator *commandsAllocator, RecyclerT *recycler, CommandBufferHelperT **commandBufferHelperOut) { - return recycler->getCommandBufferHelper(context, commandPool, commandsAllocator, - commandBufferHelperOut); + return recycler->getCommandBufferHelper(context, commandPool, commandBufferHelperOut); } angle::Result Renderer::getOutsideRenderPassCommandBufferHelper( vk::ErrorContext *context, vk::SecondaryCommandPool *commandPool, - vk::SecondaryCommandMemoryAllocator *commandsAllocator, vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut) { ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::getOutsideRenderPassCommandBufferHelper"); - return getCommandBufferImpl(context, commandPool, commandsAllocator, - &mOutsideRenderPassCommandBufferRecycler, commandBufferHelperOut); + return getCommandBufferImpl(context, commandPool, &mOutsideRenderPassCommandBufferRecycler, + commandBufferHelperOut); } angle::Result Renderer::getRenderPassCommandBufferHelper( vk::ErrorContext *context, vk::SecondaryCommandPool *commandPool, - vk::SecondaryCommandMemoryAllocator *commandsAllocator, vk::RenderPassCommandBufferHelper **commandBufferHelperOut) { ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::getRenderPassCommandBufferHelper"); - return getCommandBufferImpl(context, commandPool, commandsAllocator, - &mRenderPassCommandBufferRecycler, commandBufferHelperOut); + return getCommandBufferImpl(context, commandPool, &mRenderPassCommandBufferRecycler, + commandBufferHelperOut); } void Renderer::recycleOutsideRenderPassCommandBufferHelper( @@ -6859,7 +7785,14 @@ void Renderer::onDeallocateHandle(vk::HandleType handleType, uint32_t count) mActiveHandleCounts.onDeallocate(handleType, count); } -VkDeviceSize Renderer::getPreferedBufferBlockSize(uint32_t memoryTypeIndex) const +VkDeviceSize Renderer::getPreferredInitialBufferBlockSize(uint32_t memoryTypeIndex) const +{ + // Try not to exceed 1/64 of heap size to begin with. + const VkDeviceSize heapSize = getMemoryProperties().getHeapSizeForMemoryType(memoryTypeIndex); + return std::min(heapSize / 64, mPreferredInitialBufferBlockSize); +} + +VkDeviceSize Renderer::getPreferredLargeBufferBlockSize(uint32_t memoryTypeIndex) const { // Try not to exceed 1/64 of heap size to begin with. const VkDeviceSize heapSize = getMemoryProperties().getHeapSizeForMemoryType(memoryTypeIndex); @@ -6894,6 +7827,18 @@ angle::Result Renderer::cleanupSomeGarbage(ErrorContext *context, bool *anyGarba return mCommandQueue.cleanupSomeGarbage(context, 0, anyGarbageCleanedOut); } +void Renderer::addSamplerToOrphanList(SharedSamplerPtr sampler) +{ + std::unique_lock lock(mOrphanedSamplerMutex); + mOrphanedSamplers.push_back(sampler); +} + +void Renderer::addSamplerYcbcrConversionToOrphanList(VkSamplerYcbcrConversion conversion) +{ + std::unique_lock lock(mOrphanedSamplerMutex); + mOrphanedSamplerYcbcrConversions.push_back(conversion); +} + // static const char *Renderer::GetVulkanObjectTypeName(VkObjectType type) { diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.h b/src/libANGLE/renderer/vulkan/vk_renderer.h index 360d44fd7d8..c09ec75d806 100644 --- a/src/libANGLE/renderer/vulkan/vk_renderer.h +++ b/src/libANGLE/renderer/vulkan/vk_renderer.h @@ -52,15 +52,11 @@ class Format; static constexpr size_t kMaxExtensionNames = 400; using ExtensionNameList = angle::FixedVector; -static constexpr size_t kMaxSyncValExtraProperties = 5; +static constexpr size_t kMaxSyncValExtraProperties = 9; // Information used to accurately skip known synchronization issues in ANGLE. -// TODO: remove messageContents1 and messageContents2 fields after all -// supressions have transitioned to using extraProperties. struct SkippedSyncvalMessage { const char *messageId; - const char *messageContents1; - const char *messageContents2 = ""; bool isDueToNonConformantCoherentColorFramebufferFetch = false; const char *extraProperties[kMaxSyncValExtraProperties] = {}; }; @@ -102,21 +98,6 @@ class ImageMemorySuballocator : angle::NonCopyable // glSignalSemaphoreEXT. using SignalSemaphoreVector = angle::FixedVector; -// Recursive function to process variable arguments for garbage collection -inline void CollectGarbage(std::vector *garbageOut) {} -template -void CollectGarbage(std::vector *garbageOut, ArgT object, ArgsT... objectsIn) -{ - if (object->valid()) - { - garbageOut->emplace_back(vk::GarbageObject::Get(object)); - } - CollectGarbage(garbageOut, objectsIn...); -} - -// Recursive function to process variable arguments for garbage destroy -inline void DestroyGarbage(vk::Renderer *renderer) {} - class OneOffCommandPool : angle::NonCopyable { public: @@ -213,6 +194,12 @@ class Renderer : angle::NonCopyable { return mPhysicalDeviceFeatures; } + const VkPhysicalDeviceShaderIntegerDotProductProperties & + getPhysicalDeviceShaderIntegerDotProductProperties() const + { + return mShaderIntegerDotProductProperties; + } + const VkPhysicalDeviceFeatures2KHR &getEnabledFeatures() const { return mEnabledFeatures; } VkDevice getDevice() const { return mDevice; } @@ -223,6 +210,12 @@ class Renderer : angle::NonCopyable VkSurfaceKHR surface, bool *supportedOut); + const VkPhysicalDeviceExternalMemoryHostPropertiesEXT & + getPhysicalDeviceExternalMemoryHostProperties() const + { + return mExternalMemoryHostProperties; + } + const gl::Caps &getNativeCaps() const; const gl::TextureCapsMap &getNativeTextureCaps() const; const gl::Extensions &getNativeExtensions() const; @@ -261,14 +254,15 @@ class Renderer : angle::NonCopyable size_t *pipelineCacheSizeOut, size_t lastSyncSize, std::vector *pipelineCacheDataOut); - angle::Result syncPipelineCacheVk(vk::ErrorContext *context, - vk::GlobalOps *globalOps, - const gl::Context *contextGL); const angle::FeaturesVk &getFeatures() const { return mFeatures; } uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; } - VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; } + VkDeviceSize padVertexAttribBufferSizeIfNeeded(VkDeviceSize bufferSize); uint32_t getMaxColorInputAttachmentCount() const { return mMaxColorInputAttachmentCount; } + ANGLE_INLINE bool isInFlightCommandsEmpty() const + { + return mCommandQueue.isInFlightCommandsEmpty(); + } uint32_t getDefaultUniformBufferSize() const { return mDefaultUniformBufferSize; } @@ -285,16 +279,13 @@ class Renderer : angle::NonCopyable const VkFormatFeatureFlags featureBits) const; VkFormatFeatureFlags getImageFormatFeatureBits(angle::FormatID format, const VkFormatFeatureFlags featureBits) const; + VkFormatFeatureFlags getBufferFormatFeatureBits(angle::FormatID format, + const VkFormatFeatureFlags featureBits) const; bool hasImageFormatFeatureBits(angle::FormatID format, const VkFormatFeatureFlags featureBits) const; bool hasBufferFormatFeatureBits(angle::FormatID format, const VkFormatFeatureFlags featureBits) const; - bool isAsyncCommandBufferResetAndGarbageCleanupEnabled() const - { - return mFeatures.asyncCommandBufferResetAndGarbageCleanup.enabled; - } - ANGLE_INLINE egl::ContextPriority getDriverPriority(egl::ContextPriority priority) { return mCommandQueue.getDriverPriority(priority); @@ -332,29 +323,42 @@ class Renderer : angle::NonCopyable VkPipelineStageFlags waitSemaphoreStageMasks, QueueSerial submitQueueSerial); - template - void collectGarbage(const vk::ResourceUse &use, ArgsT... garbageIn) + template + void collectGarbage(const vk::ResourceUse &use, ArgT garbageIn) { + if (!garbageIn->valid()) + { + return; + } + if (hasResourceUseFinished(use)) { - DestroyGarbage(this, garbageIn...); + garbageIn->destroy(mDevice); } else { std::vector sharedGarbage; - CollectGarbage(&sharedGarbage, garbageIn...); - if (!sharedGarbage.empty()) - { - collectGarbage(use, std::move(sharedGarbage)); - } + sharedGarbage.emplace_back(vk::GarbageObject::Get(garbageIn)); + collectGarbage(use, std::move(sharedGarbage)); } } void collectGarbage(const vk::ResourceUse &use, vk::GarbageObjects &&sharedGarbage) { ASSERT(!sharedGarbage.empty()); - vk::SharedGarbage garbage(use, std::move(sharedGarbage)); - mSharedGarbageList.add(this, std::move(garbage)); + if (hasResourceUseFinished(use)) + { + for (auto &garbage : sharedGarbage) + { + garbage.destroy(this); + } + sharedGarbage.clear(); + } + else + { + vk::SharedGarbage garbage(use, std::move(sharedGarbage)); + mSharedGarbageList.add(this, std::move(garbage)); + } } void collectSuballocationGarbage(const vk::ResourceUse &use, @@ -408,9 +412,6 @@ class Renderer : angle::NonCopyable bool enableDebugUtils() const { return mEnableDebugUtils; } bool angleDebuggerMode() const { return mAngleDebuggerMode; } - SamplerCache &getSamplerCache() { return mSamplerCache; } - SamplerYcbcrConversionCache &getYuvConversionCache() { return mYuvConversionCache; } - void onAllocateHandle(vk::HandleType handleType); void onDeallocateHandle(vk::HandleType handleType, uint32_t count); @@ -428,12 +429,10 @@ class Renderer : angle::NonCopyable void cleanupPendingSubmissionGarbage(); angle::Result submitCommands(vk::ErrorContext *context, - vk::ProtectionType protectionType, - egl::ContextPriority contextPriority, const vk::Semaphore *signalSemaphore, const vk::SharedExternalFence *externalFence, - std::vector &&imagesToTransitionToForeign, - const QueueSerial &submitQueueSerial); + const QueueSerial &submitQueueSerial, + CommandsState &&commandsState); angle::Result submitPriorityDependency(vk::ErrorContext *context, vk::ProtectionTypes protectionTypes, @@ -441,6 +440,13 @@ class Renderer : angle::NonCopyable egl::ContextPriority dstContextPriority, SerialIndex index); + angle::Result insertOneOffSubmitDebugMarker(vk::ErrorContext *context, + vk::ProtectionType protectionType, + egl::ContextPriority priority, + QueueSubmitReason reason); + void insertSubmitDebugMarkerInCommandBuffer(PrimaryCommandBuffer &commandBuffer, + QueueSubmitReason reason); + void handleDeviceLost(); angle::Result finishResourceUse(vk::ErrorContext *context, const vk::ResourceUse &use); angle::Result finishQueueSerial(vk::ErrorContext *context, const QueueSerial &queueSerial); @@ -453,22 +459,6 @@ class Renderer : angle::NonCopyable angle::Result checkCompletedCommandsAndCleanup(vk::ErrorContext *context); angle::Result releaseFinishedCommands(vk::ErrorContext *context); - angle::Result flushWaitSemaphores(vk::ProtectionType protectionType, - egl::ContextPriority priority, - std::vector &&waitSemaphores, - std::vector &&waitSemaphoreStageMasks); - angle::Result flushRenderPassCommands(vk::Context *context, - vk::ProtectionType protectionType, - egl::ContextPriority priority, - const vk::RenderPass &renderPass, - VkFramebuffer framebufferOverride, - vk::RenderPassCommandBufferHelper **renderPassCommands); - angle::Result flushOutsideRPCommands( - vk::Context *context, - vk::ProtectionType protectionType, - egl::ContextPriority priority, - vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands); - VkResult queuePresent(vk::ErrorContext *context, egl::ContextPriority priority, const VkPresentInfoKHR &presentInfo); @@ -476,18 +466,18 @@ class Renderer : angle::NonCopyable angle::Result getOutsideRenderPassCommandBufferHelper( vk::ErrorContext *context, vk::SecondaryCommandPool *commandPool, - vk::SecondaryCommandMemoryAllocator *commandsAllocator, vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut); angle::Result getRenderPassCommandBufferHelper( vk::ErrorContext *context, vk::SecondaryCommandPool *commandPool, - vk::SecondaryCommandMemoryAllocator *commandsAllocator, vk::RenderPassCommandBufferHelper **commandBufferHelperOut); void recycleOutsideRenderPassCommandBufferHelper( vk::OutsideRenderPassCommandBufferHelper **commandBuffer); void recycleRenderPassCommandBufferHelper(vk::RenderPassCommandBufferHelper **commandBuffer); + CommandPoolAccess &getCommandPoolAccess() { return mCommandQueue.getCommandPoolAccess(); } + // Process GPU memory reports void processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData) { @@ -514,9 +504,13 @@ class Renderer : angle::NonCopyable return mEventStageToPipelineStageFlagsMap[eventStage]; } - const ImageMemoryBarrierData &getImageMemoryBarrierData(ImageLayout layout) const + const ImageMemoryBarrierData &getImageMemoryBarrierData(ImageAccess imageAccess) const { - return mImageLayoutAndMemoryBarrierDataMap[layout]; + return mImageLayoutAndMemoryBarrierDataMap[imageAccess]; + } + VkImageLayout getVkImageLayout(ImageAccess imageAccess) const + { + return getImageMemoryBarrierData(imageAccess).layout; } VkShaderStageFlags getSupportedVulkanShaderStageMask() const @@ -547,7 +541,8 @@ class Renderer : angle::NonCopyable return mEnabledDeviceExtensions; } - VkDeviceSize getPreferedBufferBlockSize(uint32_t memoryTypeIndex) const; + VkDeviceSize getPreferredInitialBufferBlockSize(uint32_t memoryTypeIndex) const; + VkDeviceSize getPreferredLargeBufferBlockSize(uint32_t memoryTypeIndex) const; size_t getDefaultBufferAlignment() const { return mDefaultBufferAlignment; } @@ -557,6 +552,8 @@ class Renderer : angle::NonCopyable } size_t getStagingBufferAlignment() const { return mStagingBufferAlignment; } + uint32_t getTileMemoyTypeIndex() const { return mTileMemoyTypeIndex; } + uint32_t getVertexConversionBufferMemoryTypeIndex(MemoryHostVisibility hostVisibility) const { return hostVisibility == MemoryHostVisibility::Visible @@ -572,7 +569,13 @@ class Renderer : angle::NonCopyable bool isShadingRateSupported(gl::ShadingRate shadingRate) const { - return mSupportedFragmentShadingRates.test(shadingRate); + return mSupportedFragmentShadingRatesEXT.test(shadingRate); + } + + const angle::ShadingRateMap &getSupportedFragmentShadingRateEXTSampleCounts() const + { + ASSERT(mFeatures.supportsFragmentShadingRate.enabled); + return mSupportedFragmentShadingRateEXTSampleCounts; } VkExtent2D getMaxFragmentShadingRateAttachmentTexelSize() const @@ -582,6 +585,8 @@ class Renderer : angle::NonCopyable } void addBufferBlockToOrphanList(vk::BufferBlock *block) { mOrphanedBufferBlockList.add(block); } + void addSamplerToOrphanList(SharedSamplerPtr sampler); + void addSamplerYcbcrConversionToOrphanList(VkSamplerYcbcrConversion conversion); VkDeviceSize getSuballocationDestroyedSize() const { @@ -654,7 +659,7 @@ class Renderer : angle::NonCopyable void requestAsyncCommandsAndGarbageCleanup(vk::ErrorContext *context); - VkDeviceSize getMaxMemoryAllocationSize() + VkDeviceSize getMaxMemoryAllocationSize() const { return mMaintenance3Properties.maxMemoryAllocationSize; } @@ -696,6 +701,29 @@ class Renderer : angle::NonCopyable return mPlaceHolderDescriptorSetLayout; } + // VK_EXT_device_fault allows gathering more info if the device is lost. + VkResult retrieveDeviceLostDetails() const; + + bool supportsAstcHdr() const; + + uint32_t getNativeVectorWidthDouble() const { return mNativeVectorWidthDouble; } + uint32_t getNativeVectorWidthHalf() const { return mNativeVectorWidthHalf; } + uint32_t getPreferredVectorWidthDouble() const { return mPreferredVectorWidthDouble; } + uint32_t getPreferredVectorWidthHalf() const { return mPreferredVectorWidthHalf; } + + bool isVertexAttributeInstanceRateZeroDivisorAllowed() const + { + return !mFeatures.supportsVertexInputDynamicState.enabled || + mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateZeroDivisor == VK_TRUE; + } + + angle::Result onFrameBoundary(const gl::Context *contextGL); + + uint32_t getMinRenderPassWriteCommandCountToEarlySubmit() const + { + return mMinRPWriteCommandCountToEarlySubmit; + } + private: angle::Result setupDevice(vk::ErrorContext *context, const angle::FeatureOverrides &featureOverrides, @@ -752,6 +780,7 @@ class Renderer : angle::NonCopyable vk::PipelineCache *pipelineCache, bool *success); angle::Result ensurePipelineCacheInitialized(vk::ErrorContext *context); + angle::Result syncPipelineCacheVk(const gl::Context *contextGL); template VkFormatFeatureFlags getFormatFeatureBits(angle::FormatID formatID, @@ -777,10 +806,11 @@ class Renderer : angle::NonCopyable // should be flushed. void calculatePendingGarbageSizeLimit(); + bool cleanupOrphanedSamplers(); + template angle::Result getCommandBufferImpl(vk::ErrorContext *context, vk::SecondaryCommandPool *commandPool, - vk::SecondaryCommandMemoryAllocator *commandsAllocator, RecyclerT *recycler, CommandBufferHelperT **commandBufferHelperOut); @@ -871,7 +901,7 @@ class Renderer : angle::NonCopyable mRasterizationOrderAttachmentAccessFeatures; VkPhysicalDeviceShaderAtomicFloatFeaturesEXT mShaderAtomicFloatFeatures; VkPhysicalDeviceMaintenance5FeaturesKHR mMaintenance5Features; - VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT mSwapchainMaintenance1Features; + VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR mSwapchainMaintenance1Features; VkPhysicalDeviceLegacyDitheringFeaturesEXT mDitheringFeatures; VkPhysicalDeviceDrmPropertiesEXT mDrmProperties; VkPhysicalDeviceTimelineSemaphoreFeaturesKHR mTimelineSemaphoreFeatures; @@ -894,12 +924,25 @@ class Renderer : angle::NonCopyable VkPhysicalDeviceFloatControlsProperties mFloatControlProperties; VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR mUniformBufferStandardLayoutFeatures; VkPhysicalDeviceMaintenance3Properties mMaintenance3Properties; + VkPhysicalDeviceFaultFeaturesEXT mFaultFeatures; + VkPhysicalDeviceASTCDecodeFeaturesEXT mPhysicalDeviceAstcDecodeFeatures; + VkPhysicalDeviceUnifiedImageLayoutsFeaturesKHR mUnifiedImageLayoutsFeatures; + VkPhysicalDeviceShaderIntegerDotProductFeatures mShaderIntegerDotProductFeatures; + VkPhysicalDeviceShaderIntegerDotProductProperties mShaderIntegerDotProductProperties; + VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT mPhysicalDeviceGlobalPriorityQueryFeatures; + VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties; + VkPhysicalDeviceBufferDeviceAddressFeaturesKHR mBufferDeviceAddressFeatures; + VkPhysicalDeviceShaderAtomicInt64Features mShaderAtomicInt64Features; + VkPhysicalDeviceTileMemoryHeapFeaturesQCOM mTileMemoryHeapFeatures; + VkPhysicalDeviceTileMemoryHeapPropertiesQCOM mTileMemoryHeapProperties; + VkPhysicalDeviceTextureCompressionASTC3DFeaturesEXT mTextureCompressionASTC3DFeatures; uint32_t mLegacyDitheringVersion = 0; - angle::PackedEnumBitSet mSupportedFragmentShadingRates; - angle::PackedEnumMap - mSupportedFragmentShadingRateSampleCounts; + // EXT_fragment_shading_rate + angle::ShadingRateSet mSupportedFragmentShadingRatesEXT; + angle::ShadingRateMap mSupportedFragmentShadingRateEXTSampleCounts; + std::vector mQueueFamilyProperties; uint32_t mCurrentQueueFamilyIndex; uint32_t mMaxVertexAttribDivisor; @@ -920,6 +963,11 @@ class Renderer : angle::NonCopyable // Holds RefCountedEvent that are free and ready to reuse vk::RefCountedEventRecycler mRefCountedEventRecycler; + // Holds orphaned VkSampler and VkSamplerYcbcrConversion objects when ShareGroup gets destroyed + angle::SimpleMutex mOrphanedSamplerMutex; + std::vector mOrphanedSamplers; + std::vector mOrphanedSamplerYcbcrConversions; + VkDeviceSize mPendingGarbageSizeLimit; vk::FormatTable mFormatTable; @@ -932,6 +980,8 @@ class Renderer : angle::NonCopyable vk::ImageMemorySuballocator mImageMemorySuballocator; vk::MemoryProperties mMemoryProperties; + uint32_t mTileMemoyTypeIndex; + VkDeviceSize mPreferredInitialBufferBlockSize; VkDeviceSize mPreferredLargeHeapBlockSize; // The default alignment for BufferVk object @@ -946,10 +996,10 @@ class Renderer : angle::NonCopyable // The mutex protects - // 1. initialization of the cache - // 2. Vulkan driver guarantess synchronization for read and write operations but the spec + // 2. Vulkan driver guarantees synchronization for read and write operations but the spec // requires external synchronization when mPipelineCache is the dstCache of - // vkMergePipelineCaches. Lock the mutex if mergeProgramPipelineCachesToGlobalCache is - // enabled + // vkMergePipelineCaches. Though some buggy vulkan drivers need external synchronization + // for all access. Lock the mutex if externallySynchronizePipelineCacheAccess is enabled angle::SimpleMutex mPipelineCacheMutex; vk::PipelineCache mPipelineCache; size_t mCurrentPipelineCacheBlobCacheSlotIndex; @@ -1007,8 +1057,6 @@ class Renderer : angle::NonCopyable mOutsideRenderPassCommandBufferRecycler; vk::CommandBufferRecycler mRenderPassCommandBufferRecycler; - SamplerCache mSamplerCache; - SamplerYcbcrConversionCache mYuvConversionCache; angle::HashMap mVkFormatDescriptorCountMap; vk::ActiveHandleCounter mActiveHandleCounts; angle::SimpleMutex mActiveHandleCountsMutex; @@ -1046,7 +1094,7 @@ class Renderer : angle::NonCopyable VkShaderStageFlags mSupportedVulkanShaderStageMask; // The 1:1 mapping between EventStage and VkPipelineStageFlags EventStageToVkPipelineStageFlagsMap mEventStageToPipelineStageFlagsMap; - ImageLayoutToMemoryBarrierDataMap mImageLayoutAndMemoryBarrierDataMap; + ImageAccessToMemoryBarrierDataMap mImageLayoutAndMemoryBarrierDataMap; // Use thread pool to compress cache data. std::shared_ptr mCompressEvent; @@ -1068,6 +1116,22 @@ class Renderer : angle::NonCopyable // A placeholder descriptor set layout handle for layouts with no bindings. vk::DescriptorSetLayoutPtr mPlaceHolderDescriptorSetLayout; + + // Cached value for the buffer memory size limit. + VkDeviceSize mMaxBufferMemorySizeLimit; + + // Record submitted queue serials not belongs to any context. + vk::ResourceUse mSubmittedResourceUse; + + // Potentially vendor & feature-specific device info. + uint32_t mNativeVectorWidthDouble; + uint32_t mNativeVectorWidthHalf; + uint32_t mPreferredVectorWidthDouble; + uint32_t mPreferredVectorWidthHalf; + + // The number of minimum write commands in the command buffer to trigger one submission of + // pending commands at draw call time + uint32_t mMinRPWriteCommandCountToEarlySubmit; }; ANGLE_INLINE Serial Renderer::generateQueueSerial(SerialIndex index) @@ -1124,27 +1188,7 @@ ANGLE_INLINE angle::Result Renderer::checkCompletedCommandsAndCleanup(vk::ErrorC ANGLE_INLINE angle::Result Renderer::releaseFinishedCommands(vk::ErrorContext *context) { - return mCommandQueue.releaseFinishedCommands(context); -} - -template -void DestroyGarbage(Renderer *renderer, ArgT object, ArgsT... objectsIn) -{ - if (object->valid()) - { - object->destroy(renderer->getDevice()); - } - DestroyGarbage(renderer, objectsIn...); -} - -template -void DestroyGarbage(Renderer *renderer, vk::Allocation *object, ArgsT... objectsIn) -{ - if (object->valid()) - { - object->destroy(renderer->getAllocator()); - } - DestroyGarbage(renderer, objectsIn...); + return mCommandQueue.releaseFinishedCommands(context, WhenToResetCommandBuffer::Now); } } // namespace vk } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/vk_resource.cpp b/src/libANGLE/renderer/vulkan/vk_resource.cpp index 85e13f751fe..5c174770b1d 100644 --- a/src/libANGLE/renderer/vulkan/vk_resource.cpp +++ b/src/libANGLE/renderer/vulkan/vk_resource.cpp @@ -7,6 +7,10 @@ // Resource lifetime tracking in the Vulkan back-end. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/vulkan/vk_resource.h" #include "libANGLE/renderer/vulkan/ContextVk.h" @@ -18,7 +22,7 @@ namespace vk // Resource implementation. angle::Result Resource::waitForIdle(ContextVk *contextVk, const char *debugMessage, - RenderPassClosureReason reason) + QueueSubmitReason reason) { // If there are pending commands for the resource, flush them. if (contextVk->hasUnsubmittedUse(mUse)) diff --git a/src/libANGLE/renderer/vulkan/vk_resource.h b/src/libANGLE/renderer/vulkan/vk_resource.h index d5c0dc1b124..f8bde088bb7 100644 --- a/src/libANGLE/renderer/vulkan/vk_resource.h +++ b/src/libANGLE/renderer/vulkan/vk_resource.h @@ -327,7 +327,7 @@ class Resource : angle::NonCopyable // Complete all recorded and in-flight commands involving this resource angle::Result waitForIdle(ContextVk *contextVk, const char *debugMessage, - RenderPassClosureReason reason); + QueueSubmitReason reason); void setSerial(SerialIndex index, Serial serial) { mUse.setSerial(index, serial); } @@ -369,7 +369,7 @@ class ReadWriteResource : public Resource // Complete all recorded and in-flight commands involving this resource angle::Result waitForIdle(ContextVk *contextVk, const char *debugMessage, - RenderPassClosureReason reason) + QueueSubmitReason reason) { return Resource::waitForIdle(contextVk, debugMessage, reason); } diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp index e9f0f6158d0..f73e2906ca0 100644 --- a/src/libANGLE/renderer/vulkan/vk_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp @@ -7,8 +7,13 @@ // Helper functions for the Vulkan Renderer. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/vk_utils.h" +#include "common/span.h" #include "libANGLE/Context.h" #include "libANGLE/Display.h" #include "libANGLE/renderer/vulkan/BufferVk.h" @@ -120,29 +125,16 @@ VkResult FindAndAllocateCompatibleMemory(vk::ErrorContext *context, return result; } -template -VkResult AllocateAndBindBufferOrImageMemory(vk::ErrorContext *context, - vk::MemoryAllocationType memoryAllocationType, - VkMemoryPropertyFlags requestedMemoryPropertyFlags, - VkMemoryPropertyFlags *memoryPropertyFlagsOut, - const VkMemoryRequirements &memoryRequirements, - const void *extraAllocationInfo, - const VkBindImagePlaneMemoryInfoKHR *extraBindInfo, - T *bufferOrImage, - uint32_t *memoryTypeIndexOut, - vk::DeviceMemory *deviceMemoryOut); - -template <> -VkResult AllocateAndBindBufferOrImageMemory(vk::ErrorContext *context, - vk::MemoryAllocationType memoryAllocationType, - VkMemoryPropertyFlags requestedMemoryPropertyFlags, - VkMemoryPropertyFlags *memoryPropertyFlagsOut, - const VkMemoryRequirements &memoryRequirements, - const void *extraAllocationInfo, - const VkBindImagePlaneMemoryInfoKHR *extraBindInfo, - vk::Image *image, - uint32_t *memoryTypeIndexOut, - vk::DeviceMemory *deviceMemoryOut) +VkResult AllocateAndBindImageMemory(vk::ErrorContext *context, + vk::MemoryAllocationType memoryAllocationType, + VkMemoryPropertyFlags requestedMemoryPropertyFlags, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + const VkMemoryRequirements &memoryRequirements, + const void *extraAllocationInfo, + const VkBindImagePlaneMemoryInfoKHR *extraBindInfo, + vk::Image *image, + uint32_t *memoryTypeIndexOut, + vk::DeviceMemory *deviceMemoryOut) { const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties(); @@ -170,53 +162,24 @@ VkResult AllocateAndBindBufferOrImageMemory(vk::ErrorContext *context, return VK_SUCCESS; } -template <> -VkResult AllocateAndBindBufferOrImageMemory(vk::ErrorContext *context, - vk::MemoryAllocationType memoryAllocationType, - VkMemoryPropertyFlags requestedMemoryPropertyFlags, - VkMemoryPropertyFlags *memoryPropertyFlagsOut, - const VkMemoryRequirements &memoryRequirements, - const void *extraAllocationInfo, - const VkBindImagePlaneMemoryInfoKHR *extraBindInfo, - vk::Buffer *buffer, - uint32_t *memoryTypeIndexOut, - vk::DeviceMemory *deviceMemoryOut) -{ - ASSERT(extraBindInfo == nullptr); - - const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties(); - - VK_RESULT_TRY(FindAndAllocateCompatibleMemory( - context, memoryAllocationType, memoryProperties, requestedMemoryPropertyFlags, - memoryPropertyFlagsOut, memoryRequirements, extraAllocationInfo, memoryTypeIndexOut, - deviceMemoryOut)); - - VK_RESULT_TRY(buffer->bindMemory(context->getDevice(), *deviceMemoryOut, 0)); - return VK_SUCCESS; -} - -template -VkResult AllocateBufferOrImageMemory(vk::ErrorContext *context, +VkResult AllocateAndBindBufferMemory(vk::ErrorContext *context, vk::MemoryAllocationType memoryAllocationType, VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags *memoryPropertyFlagsOut, + const VkMemoryRequirements &memoryRequirements, const void *extraAllocationInfo, - T *bufferOrImage, + vk::Buffer *buffer, uint32_t *memoryTypeIndexOut, - vk::DeviceMemory *deviceMemoryOut, - VkDeviceSize *sizeOut) + vk::DeviceMemory *deviceMemoryOut) { - // Call driver to determine memory requirements. - VkMemoryRequirements memoryRequirements; - bufferOrImage->getMemoryRequirements(context->getDevice(), &memoryRequirements); + const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties(); - VK_RESULT_TRY(AllocateAndBindBufferOrImageMemory( - context, memoryAllocationType, requestedMemoryPropertyFlags, memoryPropertyFlagsOut, - memoryRequirements, extraAllocationInfo, nullptr, bufferOrImage, memoryTypeIndexOut, + VK_RESULT_TRY(FindAndAllocateCompatibleMemory( + context, memoryAllocationType, memoryProperties, requestedMemoryPropertyFlags, + memoryPropertyFlagsOut, memoryRequirements, extraAllocationInfo, memoryTypeIndexOut, deviceMemoryOut)); - *sizeOut = memoryRequirements.size; - + VK_RESULT_TRY(buffer->bindMemory(context->getDevice(), *deviceMemoryOut, 0)); return VK_SUCCESS; } @@ -227,7 +190,6 @@ const char *kVkValidationLayerNames[] = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects"}; - } // anonymous namespace const char *VulkanResultString(VkResult result) @@ -351,8 +313,17 @@ bool GetAvailableValidationLayers(const std::vector &layerPro namespace vk { -const char *gLoaderLayersPathEnv = "VK_LAYER_PATH"; -const char *gLoaderICDFilenamesEnv = "VK_ICD_FILENAMES"; +namespace +{ +constexpr gl::ShaderMap kPipelineStageShaderMap = { + {gl::ShaderType::Vertex, PipelineStage::VertexShader}, + {gl::ShaderType::TessControl, PipelineStage::TessellationControl}, + {gl::ShaderType::TessEvaluation, PipelineStage::TessellationEvaluation}, + {gl::ShaderType::Geometry, PipelineStage::GeometryShader}, + {gl::ShaderType::Fragment, PipelineStage::FragmentShader}, + {gl::ShaderType::Compute, PipelineStage::ComputeShader}, +}; +} // anonymous namespace VkImageAspectFlags GetDepthStencilAspectFlags(const angle::Format &format) { @@ -474,6 +445,69 @@ VkResult MemoryProperties::findCompatibleMemoryIndex( return VK_ERROR_INCOMPATIBLE_DRIVER; } +uint32_t MemoryProperties::findTileMemoryTypeIndex() const +{ + uint32_t tileMemoryHeapIndex = kInvalidMemoryHeapIndex; + for (uint32_t heapIndex = 0; heapIndex < mMemoryProperties.memoryTypeCount; heapIndex++) + { + if (mMemoryProperties.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM) + { + // There should be only one tile memory heap + ASSERT(tileMemoryHeapIndex == kInvalidMemoryHeapIndex); + tileMemoryHeapIndex = heapIndex; + } + } + + uint32_t tileMemoryTypeIndex = kInvalidMemoryTypeIndex; + if (tileMemoryHeapIndex != kInvalidMemoryHeapIndex) + { + for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < mMemoryProperties.memoryTypeCount; + memoryTypeIndex++) + { + if (mMemoryProperties.memoryTypes[memoryTypeIndex].heapIndex == tileMemoryHeapIndex) + { + // There should be only one memoryTypeIndex that matches the tile memory heap + ASSERT(tileMemoryTypeIndex == kInvalidMemoryTypeIndex); + tileMemoryTypeIndex = memoryTypeIndex; + } + } + } + return tileMemoryTypeIndex; +} + +void MemoryProperties::log(std::ostringstream &out) const +{ + out << "\nmMemoryProperties.memoryHeaps[" << mMemoryProperties.memoryHeapCount << "] = {\n" + << std::hex; + for (uint32_t heapIndex = 0; heapIndex < mMemoryProperties.memoryHeapCount; heapIndex++) + { + out << "\t{ .size=0x" << mMemoryProperties.memoryHeaps[heapIndex].size; + out << " .flags=0x" << mMemoryProperties.memoryHeaps[heapIndex].flags << " }"; + + if (heapIndex < mMemoryProperties.memoryHeapCount - 1) + { + out << "\n"; + } + } + out << " \n}"; + + out << "\nmMemoryProperties.memoryTypes[" << mMemoryProperties.memoryTypeCount << "] = {\n" + << std::hex; + for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < mMemoryProperties.memoryTypeCount; + memoryTypeIndex++) + { + out << "\t{ .heapIndex=0x" << mMemoryProperties.memoryTypes[memoryTypeIndex].heapIndex; + out << " .propertyFlags=0x" << mMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags + << " }"; + + if (memoryTypeIndex < mMemoryProperties.memoryTypeCount - 1) + { + out << "\n"; + } + } + out << " \n}"; +} + // StagingBuffer implementation. StagingBuffer::StagingBuffer() : mSize(0) {} @@ -559,7 +593,7 @@ angle::Result InitMappableAllocation(ErrorContext *context, } VkResult AllocateBufferMemory(ErrorContext *context, - vk::MemoryAllocationType memoryAllocationType, + MemoryAllocationType memoryAllocationType, VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags *memoryPropertyFlagsOut, const void *extraAllocationInfo, @@ -568,14 +602,20 @@ VkResult AllocateBufferMemory(ErrorContext *context, DeviceMemory *deviceMemoryOut, VkDeviceSize *sizeOut) { - return AllocateBufferOrImageMemory(context, memoryAllocationType, requestedMemoryPropertyFlags, - memoryPropertyFlagsOut, extraAllocationInfo, buffer, - memoryTypeIndexOut, deviceMemoryOut, sizeOut); + VkMemoryRequirements memoryRequirements; + buffer->getMemoryRequirements(context->getDevice(), &memoryRequirements); + + VK_RESULT_TRY(AllocateAndBindBufferMemory( + context, memoryAllocationType, requestedMemoryPropertyFlags, memoryPropertyFlagsOut, + memoryRequirements, extraAllocationInfo, buffer, memoryTypeIndexOut, deviceMemoryOut)); + + *sizeOut = memoryRequirements.size; + return VK_SUCCESS; } VkResult AllocateImageMemory(ErrorContext *context, - vk::MemoryAllocationType memoryAllocationType, - VkMemoryPropertyFlags memoryPropertyFlags, + MemoryAllocationType memoryAllocationType, + VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags *memoryPropertyFlagsOut, const void *extraAllocationInfo, Image *image, @@ -583,9 +623,15 @@ VkResult AllocateImageMemory(ErrorContext *context, DeviceMemory *deviceMemoryOut, VkDeviceSize *sizeOut) { - return AllocateBufferOrImageMemory(context, memoryAllocationType, memoryPropertyFlags, - memoryPropertyFlagsOut, extraAllocationInfo, image, - memoryTypeIndexOut, deviceMemoryOut, sizeOut); + VkMemoryRequirements memoryRequirements; + image->getMemoryRequirements(context->getDevice(), &memoryRequirements); + + VK_RESULT_TRY(AllocateAndBindImageMemory(context, memoryAllocationType, + requestedMemoryPropertyFlags, memoryPropertyFlagsOut, + memoryRequirements, extraAllocationInfo, nullptr, + image, memoryTypeIndexOut, deviceMemoryOut)); + *sizeOut = memoryRequirements.size; + return VK_SUCCESS; } VkResult AllocateImageMemoryWithRequirements(ErrorContext *context, @@ -599,10 +645,70 @@ VkResult AllocateImageMemoryWithRequirements(ErrorContext *context, DeviceMemory *deviceMemoryOut) { VkMemoryPropertyFlags memoryPropertyFlagsOut = 0; - return AllocateAndBindBufferOrImageMemory(context, memoryAllocationType, memoryPropertyFlags, - &memoryPropertyFlagsOut, memoryRequirements, - extraAllocationInfo, extraBindInfo, image, - memoryTypeIndexOut, deviceMemoryOut); + return AllocateAndBindImageMemory(context, memoryAllocationType, memoryPropertyFlags, + &memoryPropertyFlagsOut, memoryRequirements, + extraAllocationInfo, extraBindInfo, image, memoryTypeIndexOut, + deviceMemoryOut); +} + +VkResult AllocateImageMemoryFromTileHeap(ErrorContext *context, + MemoryAllocationType memoryAllocationType, + VkMemoryPropertyFlags requestedMemoryPropertyFlags, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + Image *image, + uint32_t *memoryTypeIndexOut, + DeviceMemory *deviceMemoryOut, + VkDeviceSize *sizeOut) +{ + vk::Renderer *renderer = context->getRenderer(); + VkDevice device = renderer->getDevice(); + + VkImageMemoryRequirementsInfo2 info = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + nullptr, image->getHandle()}; + VkTileMemoryRequirementsQCOM tileMemReqs = {VK_STRUCTURE_TYPE_TILE_MEMORY_REQUIREMENTS_QCOM, + nullptr, 0, 0}; + VkMemoryRequirements2 memoryRequirements2 = { + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &tileMemReqs, {}}; + image->getMemoryRequirements2(device, info, &memoryRequirements2); + + if (tileMemReqs.size == 0) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + + uint32_t tileMemoryTypeIndex = renderer->getTileMemoyTypeIndex(); + ASSERT(tileMemoryTypeIndex != kInvalidMemoryTypeIndex); + + VkMemoryAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.pNext = nullptr; + allocInfo.memoryTypeIndex = tileMemoryTypeIndex; + allocInfo.allocationSize = tileMemReqs.size; + + // Add the new allocation for tracking. + renderer->getMemoryAllocationTracker()->setPendingMemoryAlloc( + memoryAllocationType, allocInfo.allocationSize, tileMemoryTypeIndex); + + DeviceScoped deviceMemory(device); + VK_RESULT_TRY(deviceMemory.get().allocate(device, allocInfo)); + + VK_RESULT_TRY(image->bindMemory(device, deviceMemory.get())); + + renderer->onMemoryAlloc(memoryAllocationType, allocInfo.allocationSize, tileMemoryTypeIndex, + deviceMemoryOut->getHandle()); + + *deviceMemoryOut = deviceMemory.release(); + *memoryTypeIndexOut = tileMemoryTypeIndex; + *memoryPropertyFlagsOut = + renderer->getMemoryProperties().getMemoryType(tileMemoryTypeIndex).propertyFlags; + *sizeOut = tileMemReqs.size; + + // The tile memory are lazily allocated at vkCmdBindTileMemoryQCOM() time. + requestedMemoryPropertyFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; + ASSERT((*memoryPropertyFlagsOut & requestedMemoryPropertyFlags) == + requestedMemoryPropertyFlags); + + return VK_SUCCESS; } VkResult AllocateBufferMemoryWithRequirements(ErrorContext *context, @@ -615,10 +721,102 @@ VkResult AllocateBufferMemoryWithRequirements(ErrorContext *context, uint32_t *memoryTypeIndexOut, DeviceMemory *deviceMemoryOut) { - return AllocateAndBindBufferOrImageMemory(context, memoryAllocationType, memoryPropertyFlags, - memoryPropertyFlagsOut, memoryRequirements, - extraAllocationInfo, nullptr, buffer, - memoryTypeIndexOut, deviceMemoryOut); + return AllocateAndBindBufferMemory( + context, memoryAllocationType, memoryPropertyFlags, memoryPropertyFlagsOut, + memoryRequirements, extraAllocationInfo, buffer, memoryTypeIndexOut, deviceMemoryOut); +} + +angle::Result InitExternalSharedFDMemory( + ErrorContext *context, + const VkExternalMemoryHandleTypeFlagBits externalMemoryHandleType, + const int32_t sharedBufferFD, + VkMemoryPropertyFlags memoryProperties, + Buffer *buffer, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + uint32_t *memoryTypeIndexOut, + DeviceMemory *deviceMemoryOut, + VkDeviceSize *sizeOut) +{ + VkDevice device = context->getRenderer()->getDevice(); + VkMemoryRequirements externalMemoryRequirements; + buffer->getMemoryRequirements(device, &externalMemoryRequirements); + + VkMemoryFdPropertiesKHR memoryFdProperties = {}; + vkGetMemoryFdPropertiesKHR(device, externalMemoryHandleType, sharedBufferFD, + &memoryFdProperties); + externalMemoryRequirements.memoryTypeBits = memoryFdProperties.memoryTypeBits; + + VkImportMemoryFdInfoKHR importMemoryFdInfo = {}; + importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR; + importMemoryFdInfo.handleType = externalMemoryHandleType; + importMemoryFdInfo.fd = sharedBufferFD; + + ANGLE_VK_TRY(context, AllocateBufferMemoryWithRequirements( + context, MemoryAllocationType::BufferExternal, memoryProperties, + externalMemoryRequirements, &importMemoryFdInfo, buffer, + memoryPropertyFlagsOut, memoryTypeIndexOut, deviceMemoryOut)); + *sizeOut = externalMemoryRequirements.size; + + return angle::Result::Continue; +} + +angle::Result GetHostPointerMemoryRequirements(ErrorContext *context, + void *hostPtr, + VkMemoryRequirements &memRequirements, + Buffer *buffer) +{ + VkDevice device = context->getRenderer()->getDevice(); + buffer->getMemoryRequirements(device, &memRequirements); + + VkMemoryHostPointerPropertiesEXT externalMemoryHostProperties = {}; + externalMemoryHostProperties.sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT; + externalMemoryHostProperties.pNext = nullptr; + + // Get properties for external memory host pointer + vkGetMemoryHostPointerPropertiesEXT(device, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, + hostPtr, &externalMemoryHostProperties); + + // Buffer memory type bits should be compatible with host pointer memory type bits + memRequirements.memoryTypeBits = + externalMemoryHostProperties.memoryTypeBits & memRequirements.memoryTypeBits; + if (memRequirements.memoryTypeBits == 0) + { + ERR() << "Buffer memoryTypeBits are not compatible with hostPtr memoryTypeBits:" + << externalMemoryHostProperties.memoryTypeBits; + return angle::Result::Stop; + } + + return angle::Result::Continue; +} + +angle::Result InitExternalHostMemory(ErrorContext *context, + void *hostPtr, + VkMemoryPropertyFlags memoryProperties, + Buffer *buffer, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + uint32_t *memoryTypeIndexOut, + DeviceMemory *deviceMemoryOut, + VkDeviceSize *sizeOut) +{ + VkMemoryRequirements externalMemoryRequirements = {}; + ANGLE_TRY( + GetHostPointerMemoryRequirements(context, hostPtr, externalMemoryRequirements, buffer)); + + // Import memory from a host pointer by using VK_EXT_external_memory_host extension + VkImportMemoryHostPointerInfoEXT importInfo = {}; + importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT; + importInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + importInfo.pHostPointer = hostPtr; + + ANGLE_VK_TRY(context, AllocateBufferMemoryWithRequirements( + context, MemoryAllocationType::BufferExternal, memoryProperties, + externalMemoryRequirements, &importInfo, buffer, + memoryPropertyFlagsOut, memoryTypeIndexOut, deviceMemoryOut)); + + *sizeOut = externalMemoryRequirements.size; + + return angle::Result::Continue; } angle::Result InitShaderModule(ErrorContext *context, @@ -903,7 +1101,19 @@ void ApplyPipelineCreationFeedback(ErrorContext *context, size_t MemoryAllocInfoMapKey::hash() const { - return angle::ComputeGenericHash(*this); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); +} + +PipelineStage GetPipelineStage(gl::ShaderType stage) +{ + const PipelineStage pipelineStage = kPipelineStageShaderMap[stage]; + ASSERT(pipelineStage == PipelineStage::VertexShader || + pipelineStage == PipelineStage::TessellationControl || + pipelineStage == PipelineStage::TessellationEvaluation || + pipelineStage == PipelineStage::GeometryShader || + pipelineStage == PipelineStage::FragmentShader || + pipelineStage == PipelineStage::ComputeShader); + return pipelineStage; } } // namespace vk @@ -924,6 +1134,9 @@ PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2 // VK_KHR_external_semaphore_fd PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr; +// VK_EXT_device_fault +PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT = nullptr; + // VK_EXT_host_query_reset PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT = nullptr; @@ -943,6 +1156,12 @@ PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR = nullpt PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR = nullptr; PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR = nullptr; +// VK_KHR_maintenance5 +PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR = nullptr; + +// VK_QCOM_tile_memory_heap +PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM = nullptr; + // VK_KHR_external_fence_capabilities PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR = nullptr; @@ -973,10 +1192,6 @@ PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferProper PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = nullptr; # endif -# if defined(ANGLE_PLATFORM_GGP) -PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP = nullptr; -# endif - # define GET_INSTANCE_FUNC(vkName) \ do \ { \ @@ -1044,6 +1259,16 @@ PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT = nullptr; PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR = nullptr; PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR = nullptr; +// VK_KHR_external_memory_fd +PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR = nullptr; +PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR = nullptr; + +// VK_EXT_external_memory_host +PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT = nullptr; + +// VK_KHR_buffer_device_address +PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR = nullptr; + void InitDebugUtilsEXTFunctions(VkInstance instance) { GET_INSTANCE_FUNC(vkCreateDebugUtilsMessengerEXT); @@ -1085,16 +1310,14 @@ void InitExternalMemoryHardwareBufferANDROIDFunctions(VkDevice device) } # endif -# if defined(ANGLE_PLATFORM_GGP) -void InitGGPStreamDescriptorSurfaceFunctions(VkInstance instance) +void InitExternalSemaphoreFdFunctions(VkDevice device) { - GET_INSTANCE_FUNC(vkCreateStreamDescriptorSurfaceGGP); + GET_DEVICE_FUNC(vkImportSemaphoreFdKHR); } -# endif // defined(ANGLE_PLATFORM_GGP) -void InitExternalSemaphoreFdFunctions(VkDevice device) +void InitDeviceFaultFunctions(VkDevice device) { - GET_DEVICE_FUNC(vkImportSemaphoreFdKHR); + GET_DEVICE_FUNC(vkGetDeviceFaultInfoEXT); } void InitHostQueryResetFunctions(VkDevice device) @@ -1173,6 +1396,18 @@ void InitFragmentShadingRateKHRDeviceFunction(VkDevice device) GET_DEVICE_FUNC(vkCmdSetFragmentShadingRateKHR); } +// VK_KHR_maintenance5 +void InitMaintenance5Functions(VkDevice device) +{ + GET_DEVICE_FUNC(vkCmdBindIndexBuffer2KHR); +} + +// VK_QCOM_tile_memory_heap +void InitTileMemoryHeapFunctions(VkDevice device) +{ + GET_DEVICE_FUNC(vkCmdBindTileMemoryQCOM); +} + // VK_GOOGLE_display_timing void InitGetPastPresentationTimingGoogleFunction(VkDevice device) { @@ -1189,12 +1424,34 @@ void InitHostImageCopyFunctions(VkDevice device) GET_DEVICE_FUNC(vkTransitionImageLayoutEXT); } +// VK_EXT_image_compression_control +void InitImageCompressionControlFunctions(VkDevice device) +{ + GET_DEVICE_FUNC(vkGetImageSubresourceLayout2EXT); +} + void InitSynchronization2Functions(VkDevice device) { GET_DEVICE_FUNC(vkCmdPipelineBarrier2KHR); GET_DEVICE_FUNC(vkCmdWriteTimestamp2KHR); } +void InitExternalMemoryFdFunctions(VkDevice device) +{ + GET_DEVICE_FUNC(vkGetMemoryFdKHR); + GET_DEVICE_FUNC(vkGetMemoryFdPropertiesKHR); +} + +void InitExternalMemoryHostFunctions(VkDevice device) +{ + GET_DEVICE_FUNC(vkGetMemoryHostPointerPropertiesEXT); +} + +void InitBufferDeviceAddressFunctions(VkDevice device) +{ + GET_DEVICE_FUNC(vkGetBufferDeviceAddressKHR); +} + # undef GET_INSTANCE_FUNC # undef GET_DEVICE_FUNC @@ -1254,6 +1511,24 @@ GLenum CalculateGenerateMipmapFilter(ContextVk *contextVk, angle::FormatID forma return formatSupportsLinearFiltering && !hintFastest ? GL_LINEAR : GL_NEAREST; } +bool HasRequiredGlobalPriority( + const std::vector &globalPriorityProperties, + VkQueueGlobalPriorityEXT requiredGlobalPriority) +{ + for (const auto &globalPriorityProperty : globalPriorityProperties) + { + for (uint32_t i = 0; i < globalPriorityProperty.priorityCount; i++) + { + if (globalPriorityProperty.priorities[i] == requiredGlobalPriority) + { + return true; + } + } + } + + return false; +} + namespace gl_vk { @@ -1709,6 +1984,22 @@ VkImageTiling GetTilingMode(gl::TilingMode tilingMode) } } +VkFormat GetAstcDecodeMode(const GLenum astcDecodePrecision) +{ + switch (astcDecodePrecision) + { + case GL_RGBA16F: + return VK_FORMAT_R16G16B16A16_SFLOAT; + case GL_RGBA8: + return VK_FORMAT_R8G8B8A8_UNORM; + case GL_RGB9_E5: + return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; + default: + UNREACHABLE(); + return VK_FORMAT_R16G16B16A16_SFLOAT; + } +} + VkImageCompressionFixedRateFlagsEXT ConvertEGLFixedRateToVkFixedRate( const EGLenum eglCompressionRate, const angle::FormatID actualFormatID) diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h index 1ae0e3b7e5f..0a3819e574a 100644 --- a/src/libANGLE/renderer/vulkan/vk_utils.h +++ b/src/libANGLE/renderer/vulkan/vk_utils.h @@ -10,6 +10,10 @@ #ifndef LIBANGLE_RENDERER_VULKAN_VK_UTILS_H_ #define LIBANGLE_RENDERER_VULKAN_VK_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include @@ -121,7 +125,7 @@ enum class BufferUsageType // A maximum offset of 4096 covers almost every Vulkan driver on desktop (80%) and mobile (99%). The // next highest values to meet native drivers are 16 bits or 32 bits. -constexpr uint32_t kAttributeOffsetMaxBits = 15; +constexpr uint32_t kAttributeOffsetMaxBits = 16; constexpr uint32_t kInvalidMemoryTypeIndex = UINT32_MAX; constexpr uint32_t kInvalidMemoryHeapIndex = UINT32_MAX; @@ -129,6 +133,9 @@ namespace vk { class Renderer; +constexpr VkImageUsageFlags kImageUsageTransferBits = + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + // Used for memory allocation tracking. enum class MemoryAllocationType; @@ -374,6 +381,15 @@ class ErrorContext : angle::NonCopyable class GlobalOps : angle::NonCopyable { public: + enum class Api : uint8_t + { + Egl = 0, + OpenCL = 1, + + InvalidEnum = 2, + EnumCount = InvalidEnum, + }; + virtual ~GlobalOps() = default; virtual void putBlob(const angle::BlobCacheKey &key, const angle::MemoryBuffer &value) = 0; @@ -383,6 +399,8 @@ class GlobalOps : angle::NonCopyable const std::shared_ptr &task) = 0; virtual void notifyDeviceLost() = 0; + + virtual GlobalOps::Api getFrontendApi() const = 0; }; class RenderPassDesc; @@ -536,11 +554,18 @@ class MemoryProperties final : angle::NonCopyable return mMemoryProperties.memoryHeaps[heapIndex].size; } - const VkMemoryType &getMemoryType(uint32_t i) const { return mMemoryProperties.memoryTypes[i]; } + const VkMemoryType &getMemoryType(uint32_t memoryTypeIndex) const + { + return mMemoryProperties.memoryTypes[memoryTypeIndex]; + } uint32_t getMemoryHeapCount() const { return mMemoryProperties.memoryHeapCount; } uint32_t getMemoryTypeCount() const { return mMemoryProperties.memoryTypeCount; } + uint32_t findTileMemoryTypeIndex() const; + + void log(std::ostringstream &out) const; + private: VkPhysicalDeviceMemoryProperties mMemoryProperties; }; @@ -603,6 +628,15 @@ VkResult AllocateImageMemoryWithRequirements(ErrorContext *context, uint32_t *memoryTypeIndexOut, DeviceMemory *deviceMemoryOut); +VkResult AllocateImageMemoryFromTileHeap(ErrorContext *context, + MemoryAllocationType memoryAllocationType, + VkMemoryPropertyFlags requestedMemoryPropertyFlags, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + Image *image, + uint32_t *memoryTypeIndexOut, + DeviceMemory *deviceMemoryOut, + VkDeviceSize *sizeOut); + VkResult AllocateBufferMemoryWithRequirements(ErrorContext *context, MemoryAllocationType memoryAllocationType, VkMemoryPropertyFlags memoryPropertyFlags, @@ -613,6 +647,31 @@ VkResult AllocateBufferMemoryWithRequirements(ErrorContext *context, uint32_t *memoryTypeIndexOut, DeviceMemory *deviceMemoryOut); +angle::Result InitExternalSharedFDMemory( + ErrorContext *context, + const VkExternalMemoryHandleTypeFlagBits externalMemoryHandleType, + const int32_t sharedBufferFD, + VkMemoryPropertyFlags memoryProperties, + Buffer *buffer, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + uint32_t *memoryTypeIndexOut, + DeviceMemory *deviceMemoryOut, + VkDeviceSize *sizeOut); + +angle::Result GetHostPointerMemoryRequirements(ErrorContext *context, + void *hostPtr, + VkMemoryRequirements &memRequirements, + Buffer *buffer); + +angle::Result InitExternalHostMemory(ErrorContext *context, + void *hostPtr, + VkMemoryPropertyFlags memoryProperties, + Buffer *buffer, + VkMemoryPropertyFlags *memoryPropertyFlagsOut, + uint32_t *memoryTypeIndexOut, + DeviceMemory *deviceMemoryOut, + VkDeviceSize *sizeOut); + gl::TextureType Get2DTextureType(uint32_t layerCount, GLint samples); enum class RecordingMode @@ -1347,6 +1406,18 @@ constexpr bool IsDynamicDescriptor(VkDescriptorType descriptorType) } } +constexpr bool IsUniformBuffer(const VkDescriptorType descriptorType) +{ + return descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || + descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; +} + +constexpr bool IsStorageBuffer(const VkDescriptorType descriptorType) +{ + return descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || + descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; +} + void ApplyPipelineCreationFeedback(ErrorContext *context, const VkPipelineCreationFeedback &feedback); @@ -1355,6 +1426,41 @@ angle::Result SetDebugUtilsObjectName(ContextVk *contextVk, uint64_t handle, const std::string &label); +// This defines enum for VkPipelineStageFlagBits so that we can use it to compare and index into +// array. +enum class PipelineStage : uint32_t +{ + // Bellow are ordered based on Graphics Pipeline Stages + TopOfPipe = 0, + DrawIndirect = 1, + VertexInput = 2, + VertexShader = 3, + TessellationControl = 4, + TessellationEvaluation = 5, + GeometryShader = 6, + TransformFeedback = 7, + FragmentShadingRate = 8, + EarlyFragmentTest = 9, + FragmentShader = 10, + LateFragmentTest = 11, + ColorAttachmentOutput = 12, + + // Compute specific pipeline Stage + ComputeShader = 13, + + // Transfer specific pipeline Stage + Transfer = 14, + BottomOfPipe = 15, + + // Host specific pipeline stage + Host = 16, + + InvalidEnum = 17, + EnumCount = InvalidEnum, +}; +using PipelineStagesMask = angle::PackedEnumBitSet; + +PipelineStage GetPipelineStage(gl::ShaderType stage); } // namespace vk #if !defined(ANGLE_SHARED_LIBVULKAN) @@ -1373,14 +1479,12 @@ void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance); void InitExternalMemoryHardwareBufferANDROIDFunctions(VkDevice device); # endif -# if defined(ANGLE_PLATFORM_GGP) -// VK_GGP_stream_descriptor_surface -void InitGGPStreamDescriptorSurfaceFunctions(VkInstance instance); -# endif // defined(ANGLE_PLATFORM_GGP) - // VK_KHR_external_semaphore_fd void InitExternalSemaphoreFdFunctions(VkDevice device); +// VK_EXT_device_fault +void InitDeviceFaultFunctions(VkDevice device); + // VK_EXT_host_query_reset void InitHostQueryResetFunctions(VkDevice device); @@ -1409,15 +1513,33 @@ void InitDynamicRenderingLocalReadFunctions(VkDevice device); void InitFragmentShadingRateKHRInstanceFunction(VkInstance instance); void InitFragmentShadingRateKHRDeviceFunction(VkDevice device); +// VK_KHR_maintenance5 +void InitMaintenance5Functions(VkDevice device); + +// VK_QCOM_tile_memory_heap +void InitTileMemoryHeapFunctions(VkDevice device); + // VK_GOOGLE_display_timing void InitGetPastPresentationTimingGoogleFunction(VkDevice device); // VK_EXT_host_image_copy void InitHostImageCopyFunctions(VkDevice device); +// VK_EXT_image_compression_control +void InitImageCompressionControlFunctions(VkDevice device); + // VK_KHR_Synchronization2 void InitSynchronization2Functions(VkDevice device); +// VK_KHR_external_memory_fd +void InitExternalMemoryFdFunctions(VkDevice device); + +// VK_EXT_external_memory_host +void InitExternalMemoryHostFunctions(VkDevice device); + +// VK_KHR_buffer_device_address +void InitBufferDeviceAddressFunctions(VkDevice device); + #endif // !defined(ANGLE_SHARED_LIBVULKAN) // Promoted to Vulkan 1.1 @@ -1430,6 +1552,10 @@ void InitBindMemory2KHRFunctionsFromCore(); GLenum CalculateGenerateMipmapFilter(ContextVk *contextVk, angle::FormatID formatID); +bool HasRequiredGlobalPriority( + const std::vector &globalPriorityProperties, + VkQueueGlobalPriorityEXT requiredGlobalPriority); + namespace gl_vk { inline VkRect2D GetRect(const gl::Rectangle &source) @@ -1483,6 +1609,8 @@ vk::LevelIndex GetLevelIndex(gl::LevelIndex levelGL, gl::LevelIndex baseLevel); VkImageTiling GetTilingMode(gl::TilingMode tilingMode); +VkFormat GetAstcDecodeMode(const GLenum astcDecodePrecision); + VkImageCompressionFixedRateFlagsEXT ConvertEGLFixedRateToVkFixedRate( const EGLenum eglCompressionRate, const angle::FormatID actualFormatID); @@ -1532,12 +1660,6 @@ enum class RenderPassClosureReason AlreadySpecifiedElsewhere, // Implicit closures due to flush/wait/etc. - ContextDestruction, - ContextChange, - GLFlush, - GLFinish, - EGLSwapBuffers, - EGLWaitClient, SurfaceUnMakeCurrent, // Closure due to switching rendering to another framebuffer. @@ -1553,36 +1675,30 @@ enum class RenderPassClosureReason DepthStencilUseInFeedbackLoop, DepthStencilWriteAfterFeedbackLoop, PipelineBindWhileXfbActive, + XfbWriteThenTextureBuffer, // Use of resource after render pass - BufferWriteThenMap, BufferWriteThenOutOfRPRead, BufferUseThenOutOfRPWrite, ImageUseThenOutOfRPRead, ImageUseThenOutOfRPWrite, - XfbWriteThenComputeRead, + XfbWriteThenUniformBufferRead, XfbWriteThenIndirectDispatchBuffer, ImageAttachmentThenComputeRead, GraphicsTextureImageAccessThenComputeAccess, - GetQueryResult, BeginNonRenderPassQuery, EndNonRenderPassQuery, TimestampQuery, EndRenderPassQuery, - GLReadPixels, // Synchronization BufferUseThenReleaseToExternal, ImageUseThenReleaseToExternal, - BufferInUseWhenSynchronizedMap, GLMemoryBarrierThenStorageResource, StorageResourceUseThenGLMemoryBarrier, - ExternalSemaphoreSignal, SyncObjectInit, - SyncObjectWithFdInit, SyncObjectClientWait, - SyncObjectServerWait, - SyncObjectGetStatus, + ForeignImageRelease, // Closures that ANGLE could have avoided, but doesn't for simplicity or optimization of more // common cases. @@ -1592,9 +1708,11 @@ enum class RenderPassClosureReason GenerateMipmapOnCPU, CopyTextureOnCPU, TextureReformatToRenderable, - DeviceLocalBufferMap, OutOfReservedQueueSerialForOutsideCommands, + // VK_QCOM_tile_memory_heap + TileMemorySimulatedClear, + // UtilsVk GenerateMipmapWithDraw, PrepareForBlit, @@ -1607,10 +1725,69 @@ enum class RenderPassClosureReason // LegacyDithering requires updating the render pass LegacyDithering, + // Flushing and submitting the command buffer requires render pass closure. + SubmitCommands, + + InvalidEnum, + EnumCount = InvalidEnum, +}; + +enum class QueueSubmitReason +{ + // Flush/Finish/Wait + EGLSwapBuffers, + EGLWaitClient, + GLFinish, + GLFlush, + GLReadPixels, + + // Context/Surface + AcquireNextImage, + ContextChange, + ContextDestruction, + ContextPriorityChange, + SurfaceUnMakeCurrent, + + // Buffer/Image + CopyBufferToImageOneOff, + CopyBufferToSurfaceImage, + CopySurfaceImageToBuffer, + ForeignImageRelease, + ImageUseThenReleaseToExternal, + InitNonZeroMemory, + TextureReformatToRenderable, + CopyTextureOnCPU, + GenerateMipmapOnCPU, + + // Sync/Query/Timestamp + ExternalSemaphoreSignal, + GetQueryResult, + GetTimestamp, + SyncCPUGPUTime, + SyncObjectInit, + SyncObjectClientWait, + SyncObjectWithFdInit, + DeviceLocalBufferMap, + BufferWriteThenMap, + BufferInUseWhenSynchronizedMap, + WaitSemaphore, + // In case of memory budget issues, pending garbage needs to be freed. ExcessivePendingGarbage, OutOfMemory, + // In case of reaching the render pass limit in the command buffer, it should be submitted. + RenderPassCountLimitReached, + RenderPassCommandLimitReached, + + // Outside command buffer submission + BufferToImageUpdateLimitReached, + ForceSubmitStagedTexture, + + // Others + DeferredFlush, + DrawOverlay, + InvalidEnum, EnumCount = InvalidEnum, }; diff --git a/src/libANGLE/renderer/vulkan/vk_wrapper.h b/src/libANGLE/renderer/vulkan/vk_wrapper.h index ce8a638a9ce..925ce998c5e 100644 --- a/src/libANGLE/renderer/vulkan/vk_wrapper.h +++ b/src/libANGLE/renderer/vulkan/vk_wrapper.h @@ -210,6 +210,10 @@ class CommandBuffer : public WrappedObject void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline); void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType); + void bindIndexBuffer2(const Buffer &buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType); void bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, @@ -220,6 +224,22 @@ class CommandBuffer : public WrappedObject const VkDeviceSize *offsets, const VkDeviceSize *sizes, const VkDeviceSize *strides); + void bindVertexBuffers2NoSize(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *strides); + void bindVertexBuffers2NoSizeNoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets); + void bindVertexBuffers2NoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *sizes); + + void bindTileMemory(const DeviceMemory &tileMemory); void blitImage(const Image &srcImage, VkImageLayout srcImageLayout, @@ -360,6 +380,7 @@ class CommandBuffer : public WrappedObject void setLineWidth(float lineWidth); void setLogicOp(VkLogicOp logicOp); void setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable); + void setPrimitiveTopology(VkPrimitiveTopology primitiveTopology); void setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable); void setRenderingAttachmentLocations(const VkRenderingAttachmentLocationInfoKHR *info); void setRenderingInputAttachmentIndicates(const VkRenderingInputAttachmentIndexInfoKHR *info); @@ -447,6 +468,9 @@ class Image final : public WrappedObject VkResult init(VkDevice device, const VkImageCreateInfo &createInfo); void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const; + void getMemoryRequirements2(VkDevice device, + const VkImageMemoryRequirementsInfo2 &info, + VkMemoryRequirements2 *requirements2Out) const; VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory); VkResult bindMemory2(VkDevice device, const VkBindImageMemoryInfoKHR &bindInfo); @@ -475,7 +499,7 @@ class Semaphore final : public WrappedObject Semaphore() = default; void destroy(VkDevice device); - VkResult init(VkDevice device); + VkResult init(VkDevice device, VkSemaphoreType semaphoreType); VkResult importFd(VkDevice device, const VkImportSemaphoreFdInfoKHR &importFdInfo) const; }; @@ -1037,6 +1061,15 @@ ANGLE_INLINE void CommandBuffer::bindIndexBuffer(const Buffer &buffer, vkCmdBindIndexBuffer(mHandle, buffer.getHandle(), offset, indexType); } +ANGLE_INLINE void CommandBuffer::bindIndexBuffer2(const Buffer &buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType) +{ + ASSERT(valid()); + vkCmdBindIndexBuffer2KHR(mHandle, buffer.getHandle(), offset, size, indexType); +} + ANGLE_INLINE void CommandBuffer::bindDescriptorSets(const PipelineLayout &layout, VkPipelineBindPoint pipelineBindPoint, DescriptorSetIndex firstSet, @@ -1167,6 +1200,12 @@ ANGLE_INLINE void CommandBuffer::setPrimitiveRestartEnable(VkBool32 primitiveRes vkCmdSetPrimitiveRestartEnableEXT(mHandle, primitiveRestartEnable); } +ANGLE_INLINE void CommandBuffer::setPrimitiveTopology(VkPrimitiveTopology primitiveTopology) +{ + ASSERT(valid()); + vkCmdSetPrimitiveTopologyEXT(mHandle, primitiveTopology); +} + ANGLE_INLINE void CommandBuffer::setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable) { ASSERT(valid()); @@ -1418,6 +1457,41 @@ ANGLE_INLINE void CommandBuffer::bindVertexBuffers2(uint32_t firstBinding, strides); } +ANGLE_INLINE void CommandBuffer::bindVertexBuffers2NoSize(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *strides) +{ + bindVertexBuffers2(firstBinding, bindingCount, buffers, offsets, nullptr, strides); +} + +ANGLE_INLINE void CommandBuffer::bindVertexBuffers2NoSizeNoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets) +{ + bindVertexBuffers2(firstBinding, bindingCount, buffers, offsets, nullptr, nullptr); +} + +ANGLE_INLINE void CommandBuffer::bindVertexBuffers2NoStride(uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *buffers, + const VkDeviceSize *offsets, + const VkDeviceSize *sizes) +{ + bindVertexBuffers2(firstBinding, bindingCount, buffers, offsets, sizes, nullptr); +} + +ANGLE_INLINE void CommandBuffer::bindTileMemory(const DeviceMemory &tileMemory) +{ + ASSERT(valid()); + ASSERT(tileMemory.valid()); + const VkTileMemoryBindInfoQCOM tileMemoryBindInfo = { + VK_STRUCTURE_TYPE_TILE_MEMORY_BIND_INFO_QCOM, nullptr, tileMemory.getHandle()}; + vkCmdBindTileMemoryQCOM(mHandle, &tileMemoryBindInfo); +} + ANGLE_INLINE void CommandBuffer::beginTransformFeedback(uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer *counterBuffers, @@ -1515,6 +1589,14 @@ ANGLE_INLINE void Image::getMemoryRequirements(VkDevice device, vkGetImageMemoryRequirements(device, mHandle, requirementsOut); } +ANGLE_INLINE void Image::getMemoryRequirements2(VkDevice device, + const VkImageMemoryRequirementsInfo2 &info, + VkMemoryRequirements2 *requirements2Out) const +{ + ASSERT(valid()); + vkGetImageMemoryRequirements2(device, &info, requirements2Out); +} + ANGLE_INLINE VkResult Image::bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory) { ASSERT(valid() && deviceMemory.valid()); @@ -1566,7 +1648,7 @@ ANGLE_INLINE void Semaphore::destroy(VkDevice device) } } -ANGLE_INLINE VkResult Semaphore::init(VkDevice device) +ANGLE_INLINE VkResult Semaphore::init(VkDevice device, VkSemaphoreType semaphoreType) { ASSERT(!valid()); @@ -1574,6 +1656,16 @@ ANGLE_INLINE VkResult Semaphore::init(VkDevice device) semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.flags = 0; + VkSemaphoreTypeCreateInfoKHR semaphoreTypeInfo = {}; + if (semaphoreType != VK_SEMAPHORE_TYPE_BINARY) + { + semaphoreTypeInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR; + semaphoreTypeInfo.semaphoreType = semaphoreType; + + // vk::AddToPNextChain is not available in this header. + semaphoreInfo.pNext = &semaphoreTypeInfo; + } + return vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle); } diff --git a/src/libANGLE/renderer/vulkan/vulkan_backend.gni b/src/libANGLE/renderer/vulkan/vulkan_backend.gni index 851944d8329..bf35eedc0b2 100644 --- a/src/libANGLE/renderer/vulkan/vulkan_backend.gni +++ b/src/libANGLE/renderer/vulkan/vulkan_backend.gni @@ -6,8 +6,6 @@ import("../../../../gni/angle.gni") vulkan_backend_sources = [ "AllocatorHelperPool.cpp", "AllocatorHelperPool.h", - "AllocatorHelperRing.cpp", - "AllocatorHelperRing.h", "BufferVk.cpp", "BufferVk.h", "CommandQueue.cpp", @@ -85,6 +83,8 @@ vulkan_backend_sources = [ "android/vk_android_utils.h", "spv_utils.cpp", "spv_utils.h", + "vk_barrier_data.cpp", + "vk_barrier_data.h", "vk_cache_utils.cpp", "vk_cache_utils.h", "vk_caps_utils.cpp", @@ -223,15 +223,6 @@ if (is_fuchsia) { ] } -if (is_ggp) { - vulkan_backend_sources += [ - "ggp/DisplayVkGGP.cpp", - "ggp/DisplayVkGGP.h", - "ggp/WindowSurfaceVkGGP.cpp", - "ggp/WindowSurfaceVkGGP.h", - ] -} - if (is_mac) { vulkan_backend_sources += [ "mac/DisplayVkMac.h", diff --git a/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp b/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp index 728cd1b03f0..fd2aacab38f 100644 --- a/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp +++ b/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp @@ -7,6 +7,10 @@ // Implements the class methods for DisplayVkWin32. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/vulkan/win32/DisplayVkWin32.h" #include "libANGLE/renderer/vulkan/DisplayVk.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" diff --git a/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp b/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp index d6c509c0c6a..14ffe319fcc 100644 --- a/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp +++ b/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp @@ -19,8 +19,7 @@ WindowSurfaceVkWin32::WindowSurfaceVkWin32(const egl::SurfaceState &surfaceState : WindowSurfaceVk(surfaceState, window) {} -angle::Result WindowSurfaceVkWin32::createSurfaceVk(vk::ErrorContext *context, - gl::Extents *extentsOut) +angle::Result WindowSurfaceVkWin32::createSurfaceVk(vk::ErrorContext *context) { VkWin32SurfaceCreateInfoKHR createInfo = {}; @@ -31,11 +30,11 @@ angle::Result WindowSurfaceVkWin32::createSurfaceVk(vk::ErrorContext *context, ANGLE_VK_TRY(context, vkCreateWin32SurfaceKHR(context->getRenderer()->getInstance(), &createInfo, nullptr, &mSurface)); - return getCurrentWindowSize(context, extentsOut); + return angle::Result::Continue; } angle::Result WindowSurfaceVkWin32::getCurrentWindowSize(vk::ErrorContext *context, - gl::Extents *extentsOut) + gl::Extents *extentsOut) const { RECT rect; ANGLE_VK_CHECK(context, GetClientRect(mNativeWindowType, &rect) == TRUE, diff --git a/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h b/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h index 60cba81380c..cb4efc7f738 100644 --- a/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h +++ b/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h @@ -21,8 +21,9 @@ class WindowSurfaceVkWin32 : public WindowSurfaceVk WindowSurfaceVkWin32(const egl::SurfaceState &surfaceState, EGLNativeWindowType window); private: - angle::Result createSurfaceVk(vk::ErrorContext *context, gl::Extents *extentsOut) override; - angle::Result getCurrentWindowSize(vk::ErrorContext *context, gl::Extents *extentsOut) override; + angle::Result createSurfaceVk(vk::ErrorContext *context) override; + angle::Result getCurrentWindowSize(vk::ErrorContext *context, + gl::Extents *extentsOut) const override; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/BUILD.gn b/src/libANGLE/renderer/wgpu/BUILD.gn index abc7d6157f8..6a739bf9763 100644 --- a/src/libANGLE/renderer/wgpu/BUILD.gn +++ b/src/libANGLE/renderer/wgpu/BUILD.gn @@ -19,12 +19,11 @@ angle_source_set("angle_wgpu_backend") { sources = wgpu_backend_sources public_deps = [ "$angle_root:libANGLE_headers" ] + defines = [ "WGPU_SKIP_DECLARATIONS" ] deps = [ "$angle_root:angle_image_util", - "${angle_dawn_dir}/include/dawn:cpp_headers", "${angle_dawn_dir}/include/dawn:headers", - "${angle_dawn_dir}/src/dawn:cpp", "${angle_dawn_dir}/src/dawn:proc", "${angle_dawn_dir}/src/dawn/native", "${angle_root}:translator", diff --git a/src/libANGLE/renderer/wgpu/BufferWgpu.cpp b/src/libANGLE/renderer/wgpu/BufferWgpu.cpp index 47b61df21c3..ab3409ba2d5 100644 --- a/src/libANGLE/renderer/wgpu/BufferWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/BufferWgpu.cpp @@ -7,6 +7,10 @@ // Implements the class methods for BufferWgpu. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/wgpu/BufferWgpu.h" #include "common/debug.h" @@ -23,24 +27,23 @@ namespace { // Based on a buffer binding target, compute the default wgpu usage flags. More can be added if the // buffer is used in new ways. -wgpu::BufferUsage GetDefaultWGPUBufferUsageForBinding(gl::BufferBinding binding) +WGPUBufferUsage GetDefaultWGPUBufferUsageForBinding(gl::BufferBinding binding) { switch (binding) { case gl::BufferBinding::Array: case gl::BufferBinding::ElementArray: - return wgpu::BufferUsage::Vertex | wgpu::BufferUsage::Index | - wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; + return WGPUBufferUsage_Vertex | WGPUBufferUsage_Index | WGPUBufferUsage_CopySrc | + WGPUBufferUsage_CopyDst; case gl::BufferBinding::Uniform: - return wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopySrc | - wgpu::BufferUsage::CopyDst; + return WGPUBufferUsage_Uniform | WGPUBufferUsage_CopySrc | WGPUBufferUsage_CopyDst; case gl::BufferBinding::PixelPack: - return wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst; + return WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst; case gl::BufferBinding::PixelUnpack: - return wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc; + return WGPUBufferUsage_MapWrite | WGPUBufferUsage_CopySrc; case gl::BufferBinding::CopyRead: case gl::BufferBinding::CopyWrite: @@ -51,11 +54,11 @@ wgpu::BufferUsage GetDefaultWGPUBufferUsageForBinding(gl::BufferBinding binding) case gl::BufferBinding::DrawIndirect: case gl::BufferBinding::AtomicCounter: UNIMPLEMENTED(); - return wgpu::BufferUsage::None; + return WGPUBufferUsage_None; default: UNREACHABLE(); - return wgpu::BufferUsage::None; + return WGPUBufferUsage_None; } } @@ -69,10 +72,12 @@ angle::Result BufferWgpu::setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) + gl::BufferUsage usage, + BufferFeedback *feedback) { ContextWgpu *contextWgpu = webgpu::GetImpl(context); - wgpu::Device device = webgpu::GetDevice(context); + const DawnProcTable *wgpu = webgpu::GetProcs(contextWgpu); + webgpu::DeviceHandle device = webgpu::GetDevice(context); bool hasData = data && size > 0; @@ -82,7 +87,8 @@ angle::Result BufferWgpu::setData(const gl::Context *context, (hasData && !mBuffer.canMapForWrite())) { // Allocate a new buffer - ANGLE_TRY(mBuffer.initBuffer(device, size, GetDefaultWGPUBufferUsageForBinding(target), + ANGLE_TRY(mBuffer.initBuffer(wgpu, device, size, + GetDefaultWGPUBufferUsageForBinding(target), webgpu::MapAtCreation::Yes)); } @@ -92,7 +98,7 @@ angle::Result BufferWgpu::setData(const gl::Context *context, if (!mBuffer.getMappedState().has_value()) { - ANGLE_TRY(mBuffer.mapImmediate(contextWgpu, wgpu::MapMode::Write, 0, size)); + ANGLE_TRY(mBuffer.mapImmediate(contextWgpu, WGPUMapMode_Write, 0, size)); } uint8_t *mappedData = mBuffer.getMapWritePointer(0, size); @@ -106,17 +112,17 @@ angle::Result BufferWgpu::setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) + size_t offset, + BufferFeedback *feedback) { ContextWgpu *contextWgpu = webgpu::GetImpl(context); - wgpu::Device device = webgpu::GetDevice(context); ASSERT(mBuffer.valid()); if (mBuffer.canMapForWrite()) { if (!mBuffer.getMappedState().has_value()) { - ANGLE_TRY(mBuffer.mapImmediate(contextWgpu, wgpu::MapMode::Write, offset, size)); + ANGLE_TRY(mBuffer.mapImmediate(contextWgpu, WGPUMapMode_Write, offset, size)); } uint8_t *mappedData = mBuffer.getMapWritePointer(offset, size); @@ -124,10 +130,11 @@ angle::Result BufferWgpu::setSubData(const gl::Context *context, } else { + const DawnProcTable *wgpu = webgpu::GetProcs(context); // TODO: Upload into a staging buffer and copy to the destination buffer so that the copy // happens at the right point in time for command buffer recording. - wgpu::Queue &queue = contextWgpu->getQueue(); - queue.WriteBuffer(mBuffer.getBuffer(), offset, data, size); + webgpu::QueueHandle queue = contextWgpu->getQueue(); + wgpu->queueWriteBuffer(queue.get(), mBuffer.getBuffer().get(), offset, data, size); } return angle::Result::Continue; @@ -137,12 +144,16 @@ angle::Result BufferWgpu::copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) + GLsizeiptr size, + BufferFeedback *feedback) { return angle::Result::Continue; } -angle::Result BufferWgpu::map(const gl::Context *context, GLenum access, void **mapPtr) +angle::Result BufferWgpu::map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) { return angle::Result::Continue; } @@ -151,12 +162,15 @@ angle::Result BufferWgpu::mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) + void **mapPtr, + BufferFeedback *feedback) { return angle::Result::Continue; } -angle::Result BufferWgpu::unmap(const gl::Context *context, GLboolean *result) +angle::Result BufferWgpu::unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) { *result = GL_TRUE; return angle::Result::Continue; diff --git a/src/libANGLE/renderer/wgpu/BufferWgpu.h b/src/libANGLE/renderer/wgpu/BufferWgpu.h index 9738e81629a..d2c952af304 100644 --- a/src/libANGLE/renderer/wgpu/BufferWgpu.h +++ b/src/libANGLE/renderer/wgpu/BufferWgpu.h @@ -14,7 +14,7 @@ #include "libANGLE/renderer/wgpu/wgpu_helpers.h" -#include +#include namespace rx { @@ -29,24 +29,33 @@ class BufferWgpu : public BufferImpl gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage usage) override; + gl::BufferUsage usage, + BufferFeedback *feedback) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, - size_t offset) override; + size_t offset, + BufferFeedback *feedback) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, - GLsizeiptr size) override; - angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; + GLsizeiptr size, + BufferFeedback *feedback) override; + angle::Result map(const gl::Context *context, + GLenum access, + void **mapPtr, + BufferFeedback *feedback) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, - void **mapPtr) override; - angle::Result unmap(const gl::Context *context, GLboolean *result) override; + void **mapPtr, + BufferFeedback *feedback) override; + angle::Result unmap(const gl::Context *context, + GLboolean *result, + BufferFeedback *feedback) override; angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, diff --git a/src/libANGLE/renderer/wgpu/ContextWgpu.cpp b/src/libANGLE/renderer/wgpu/ContextWgpu.cpp index cc543859b10..18b27a2592c 100644 --- a/src/libANGLE/renderer/wgpu/ContextWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ContextWgpu.cpp @@ -7,12 +7,18 @@ // Implements the class methods for ContextWgpu. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "libANGLE/renderer/wgpu/ContextWgpu.h" +#include "common/PackedEnums.h" #include "common/debug.h" #include "compiler/translator/wgsl/OutputUniformBlocks.h" #include "libANGLE/Context.h" +#include "libANGLE/Error.h" #include "libANGLE/renderer/OverlayImpl.h" #include "libANGLE/renderer/wgpu/BufferWgpu.h" #include "libANGLE/renderer/wgpu/CompilerWgpu.h" @@ -59,6 +65,11 @@ constexpr angle::PackedEnumMap "Render pass closed for uploading streamed client data"}, {webgpu::RenderPassClosureReason::VertexArrayLineLoop, "Render pass closed for line loop emulation"}, + {webgpu::RenderPassClosureReason::CopyBufferToTexture, + "Render pass closed to update texture"}, + {webgpu::RenderPassClosureReason::CopyTextureToTexture, + "Render pass closed to copy texture"}, + {webgpu::RenderPassClosureReason::CopyImage, "Render pass closed to copy image"}, }}; } // namespace @@ -73,6 +84,7 @@ ContextWgpu::ContextWgpu(const gl::State &state, gl::ErrorSet *errorSet, Display DIRTY_BIT_BLEND_CONSTANT, DIRTY_BIT_VERTEX_BUFFERS, DIRTY_BIT_INDEX_BUFFER, + DIRTY_BIT_DRIVER_UNIFORMS, DIRTY_BIT_BIND_GROUPS, }; } @@ -86,14 +98,41 @@ void ContextWgpu::onDestroy(const gl::Context *context) angle::Result ContextWgpu::initialize(const angle::ImageLoadContext &imageLoadContext) { + const DawnProcTable *wgpu = webgpu::GetProcs(this); + mImageLoadContext = imageLoadContext; + // Create the driver uniform bind group layout, which won't ever change. + WGPUBindGroupLayoutEntry driverUniformBindGroupEntry = WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT; + driverUniformBindGroupEntry.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; + driverUniformBindGroupEntry.binding = sh::kDriverUniformBlockBinding; + driverUniformBindGroupEntry.buffer.type = WGPUBufferBindingType_Uniform; + driverUniformBindGroupEntry.buffer.minBindingSize = kDriverUniformSize; + driverUniformBindGroupEntry.texture.sampleType = WGPUTextureSampleType_BindingNotUsed; + driverUniformBindGroupEntry.sampler.type = WGPUSamplerBindingType_BindingNotUsed; + driverUniformBindGroupEntry.storageTexture.access = WGPUStorageTextureAccess_BindingNotUsed; + // Create a bind group layout with these entries. + WGPUBindGroupLayoutDescriptor driverUniformsBindGroupLayoutDesc = + WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT; + driverUniformsBindGroupLayoutDesc.entryCount = 1; + driverUniformsBindGroupLayoutDesc.entries = &driverUniformBindGroupEntry; + mDriverUniformsBindGroupLayout = webgpu::BindGroupLayoutHandle::Acquire( + wgpu, + wgpu->deviceCreateBindGroupLayout(getDevice().get(), &driverUniformsBindGroupLayoutDesc)); + + // Driver uniforms should be set to 0 for later memcmp. + memset(&mDriverUniforms, 0, sizeof(mDriverUniforms)); + return angle::Result::Continue; } angle::Result ContextWgpu::onFramebufferChange(FramebufferWgpu *framebufferWgpu, gl::Command command) { + // May modify framebuffer size, so invalidate driver uniforms which contain the framebuffer + // size. + invalidateDriverUniforms(); + // If internal framebuffer state changes, always end the render pass ANGLE_TRY(endRenderPass(webgpu::RenderPassClosureReason::FramebufferInternalChange)); @@ -111,16 +150,18 @@ angle::Result ContextWgpu::flush(webgpu::RenderPassClosureReason closureReason) if (mCurrentCommandEncoder) { - wgpu::CommandBuffer commandBuffer = mCurrentCommandEncoder.Finish(); + const DawnProcTable *wgpu = webgpu::GetProcs(this); + webgpu::CommandBufferHandle commandBuffer = webgpu::CommandBufferHandle::Acquire( + wgpu, wgpu->commandEncoderFinish(mCurrentCommandEncoder.get(), nullptr)); mCurrentCommandEncoder = nullptr; - getQueue().Submit(1, &commandBuffer); + wgpu->queueSubmit(getQueue().get(), 1, &commandBuffer.get()); } return angle::Result::Continue; } -void ContextWgpu::setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format) +void ContextWgpu::setColorAttachmentFormat(size_t colorIndex, WGPUTextureFormat format) { if (mRenderPipelineDesc.setColorAttachmentFormat(colorIndex, format)) { @@ -128,8 +169,7 @@ void ContextWgpu::setColorAttachmentFormat(size_t colorIndex, wgpu::TextureForma } } -void ContextWgpu::setColorAttachmentFormats( - const gl::DrawBuffersArray &formats) +void ContextWgpu::setColorAttachmentFormats(const gl::DrawBuffersArray &formats) { for (size_t i = 0; i < formats.size(); i++) { @@ -137,7 +177,7 @@ void ContextWgpu::setColorAttachmentFormats( } } -void ContextWgpu::setDepthStencilFormat(wgpu::TextureFormat format) +void ContextWgpu::setDepthStencilFormat(WGPUTextureFormat format) { if (mRenderPipelineDesc.setDepthStencilAttachmentFormat(format)) { @@ -173,26 +213,60 @@ void ContextWgpu::invalidateIndexBuffer() mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER); } +void ContextWgpu::invalidateCurrentTextures() +{ + ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable()); + executableWgpu->markSamplerBindingsDirty(); + mDirtyBits.set(DIRTY_BIT_BIND_GROUPS); +} + +void ContextWgpu::invalidateDriverUniforms() +{ + mDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); +} + void ContextWgpu::ensureCommandEncoderCreated() { if (!mCurrentCommandEncoder) { - mCurrentCommandEncoder = getDevice().CreateCommandEncoder(nullptr); + const DawnProcTable *wgpu = webgpu::GetProcs(this); + mCurrentCommandEncoder = webgpu::CommandEncoderHandle::Acquire( + wgpu, wgpu->deviceCreateCommandEncoder(getDevice().get(), nullptr)); } } -wgpu::CommandEncoder &ContextWgpu::getCurrentCommandEncoder() +angle::Result ContextWgpu::getCurrentCommandEncoder(webgpu::RenderPassClosureReason closureReason, + webgpu::CommandEncoderHandle *outHandle) { - return mCurrentCommandEncoder; + if (hasActiveRenderPass()) + { + ANGLE_TRY(endRenderPass(closureReason)); + } + ensureCommandEncoderCreated(); + *outHandle = mCurrentCommandEncoder; + return angle::Result::Continue; } angle::Result ContextWgpu::finish(const gl::Context *context) { + const DawnProcTable *wgpu = webgpu::GetProcs(this); + ANGLE_TRY(flush(webgpu::RenderPassClosureReason::GLFinish)); - wgpu::Future onWorkSubmittedFuture = getQueue().OnSubmittedWorkDone( - wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus status) {}); - wgpu::WaitStatus status = getInstance().WaitAny(onWorkSubmittedFuture, -1); + WGPUQueueWorkDoneCallbackInfo callback = WGPU_QUEUE_WORK_DONE_CALLBACK_INFO_INIT; + callback.mode = WGPUCallbackMode_WaitAnyOnly; + callback.callback = [](WGPUQueueWorkDoneStatus status, + WGPUStringView message, + void *userdata1, void *userdata2) { + ASSERT(userdata1 == nullptr); + ASSERT(userdata2 == nullptr); + }; + + WGPUFutureWaitInfo onWorkSubmittedFuture = WGPU_FUTURE_WAIT_INFO_INIT; + onWorkSubmittedFuture.future = wgpu->queueOnSubmittedWorkDone(getQueue().get(), callback); + + WGPUWaitStatus status = + wgpu->instanceWaitAny(getInstance().get(), 1, &onWorkSubmittedFuture, -1); ASSERT(!webgpu::IsWgpuError(status)); return angle::Result::Continue; @@ -203,20 +277,24 @@ angle::Result ContextWgpu::drawArrays(const gl::Context *context, GLint first, GLsizei count) { - if (mode == gl::PrimitiveMode::LineLoop) - { - UNIMPLEMENTED(); - return angle::Result::Continue; - } - else if (mode == gl::PrimitiveMode::TriangleFan) + if (mode == gl::PrimitiveMode::TriangleFan) { UNIMPLEMENTED(); return angle::Result::Continue; } + uint32_t firstIndex = 0; + uint32_t indexCount = static_cast(count); ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, nullptr, - 0, nullptr, nullptr)); - mCommandBuffer.draw(static_cast(count), 1, static_cast(first), 0); + 0, &firstIndex, &indexCount)); + if (mode == gl::PrimitiveMode::LineLoop) + { + mCommandBuffer.drawIndexed(indexCount, 1, firstIndex, 0, 0); + } + else + { + mCommandBuffer.draw(static_cast(count), 1, static_cast(first), 0); + } return angle::Result::Continue; } @@ -226,21 +304,26 @@ angle::Result ContextWgpu::drawArraysInstanced(const gl::Context *context, GLsizei count, GLsizei instanceCount) { - if (mode == gl::PrimitiveMode::LineLoop) - { - UNIMPLEMENTED(); - return angle::Result::Continue; - } - else if (mode == gl::PrimitiveMode::TriangleFan) + if (mode == gl::PrimitiveMode::TriangleFan) { UNIMPLEMENTED(); return angle::Result::Continue; } + uint32_t firstIndex = 0; + uint32_t indexCount = static_cast(count); ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount, - gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr, nullptr)); - mCommandBuffer.draw(static_cast(count), static_cast(instanceCount), - static_cast(first), 0); + gl::DrawElementsType::InvalidEnum, nullptr, 0, &firstIndex, &indexCount)); + if (mode == gl::PrimitiveMode::LineLoop) + { + mCommandBuffer.drawIndexed(indexCount, static_cast(instanceCount), firstIndex, 0, + 0); + } + else + { + mCommandBuffer.draw(indexCount, static_cast(instanceCount), + static_cast(first), 0); + } return angle::Result::Continue; } @@ -251,21 +334,26 @@ angle::Result ContextWgpu::drawArraysInstancedBaseInstance(const gl::Context *co GLsizei instanceCount, GLuint baseInstance) { - if (mode == gl::PrimitiveMode::LineLoop) - { - UNIMPLEMENTED(); - return angle::Result::Continue; - } - else if (mode == gl::PrimitiveMode::TriangleFan) + if (mode == gl::PrimitiveMode::TriangleFan) { UNIMPLEMENTED(); return angle::Result::Continue; } + uint32_t firstIndex = 0; + uint32_t indexCount = static_cast(count); ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount, - gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr, nullptr)); - mCommandBuffer.draw(static_cast(count), static_cast(instanceCount), - static_cast(first), baseInstance); + gl::DrawElementsType::InvalidEnum, nullptr, 0, &firstIndex, &indexCount)); + if (mode == gl::PrimitiveMode::LineLoop) + { + mCommandBuffer.drawIndexed(indexCount, static_cast(instanceCount), firstIndex, 0, + baseInstance); + } + else + { + mCommandBuffer.draw(static_cast(count), static_cast(instanceCount), + static_cast(first), baseInstance); + } return angle::Result::Continue; } @@ -564,6 +652,9 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, setColorAttachmentFormats(framebufferWgpu->getCurrentColorAttachmentFormats()); setDepthStencilFormat(framebufferWgpu->getCurrentDepthStencilAttachmentFormat()); + // May modify framebuffer size, so invalidate driver uniforms which contain the + // framebuffer size. + invalidateDriverUniforms(); ANGLE_TRY(endRenderPass(webgpu::RenderPassClosureReason::FramebufferBindingChange)); } break; @@ -580,6 +671,8 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, break; case gl::state::DIRTY_BIT_DEPTH_RANGE: mDirtyBits.set(DIRTY_BIT_VIEWPORT); + // Driver uniforms include the depth range, which has now changed. + invalidateDriverUniforms(); break; case gl::state::DIRTY_BIT_BLEND_ENABLED: { @@ -640,6 +733,8 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, } break; case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + // Driver uniforms include the sample alpha to coverage state. + invalidateDriverUniforms(); break; case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED: break; @@ -686,12 +781,12 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, break; case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT: { - wgpu::StencilOperation failOp = - gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilFail); - wgpu::StencilOperation depthFailOp = - gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilPassDepthFail); - wgpu::StencilOperation passOp = - gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilPassDepthPass); + WGPUStencilOperation failOp = + gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilFail); + WGPUStencilOperation depthFailOp = + gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilPassDepthFail); + WGPUStencilOperation passOp = + gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilPassDepthPass); if (mRenderPipelineDesc.setStencilFrontOps(failOp, depthFailOp, passOp)) { invalidateCurrentRenderPipeline(); @@ -700,12 +795,12 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, break; case gl::state::DIRTY_BIT_STENCIL_OPS_BACK: { - wgpu::StencilOperation failOp = - gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilBackFail); - wgpu::StencilOperation depthFailOp = - gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilBackPassDepthFail); - wgpu::StencilOperation passOp = - gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilBackPassDepthPass); + WGPUStencilOperation failOp = + gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilBackFail); + WGPUStencilOperation depthFailOp = + gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilBackPassDepthFail); + WGPUStencilOperation passOp = + gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilBackPassDepthPass); if (mRenderPipelineDesc.setStencilBackOps(failOp, depthFailOp, passOp)) { invalidateCurrentRenderPipeline(); @@ -769,12 +864,16 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, case gl::state::DIRTY_BIT_PROGRAM_BINDING: case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE: invalidateCurrentRenderPipeline(); + iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS); break; case gl::state::DIRTY_BIT_SAMPLER_BINDINGS: + invalidateCurrentTextures(); break; case gl::state::DIRTY_BIT_TEXTURE_BINDINGS: + invalidateCurrentTextures(); break; case gl::state::DIRTY_BIT_IMAGE_BINDINGS: + invalidateCurrentTextures(); break; case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING: break; @@ -810,8 +909,12 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, switch (extendedDirtyBit) { case gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL: + // Driver uniforms are calculated using the clip control state. + invalidateDriverUniforms(); break; case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES: + // Driver uniforms include the clip distances. + invalidateDriverUniforms(); break; case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED: break; @@ -825,7 +928,9 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, break; case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT: break; - case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE: + case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM: + break; + case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT: break; case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED: break; @@ -833,6 +938,8 @@ angle::Result ContextWgpu::syncState(const gl::Context *context, break; case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT: break; + case gl::state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED: + break; default: UNREACHABLE(); } @@ -929,9 +1036,10 @@ BufferImpl *ContextWgpu::createBuffer(const gl::BufferState &state) return new BufferWgpu(state); } -VertexArrayImpl *ContextWgpu::createVertexArray(const gl::VertexArrayState &data) +VertexArrayImpl *ContextWgpu::createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) { - return new VertexArrayWgpu(data); + return new VertexArrayWgpu(data, vertexArrayBuffers); } QueryImpl *ContextWgpu::createQuery(gl::QueryType type) @@ -1015,11 +1123,13 @@ void ContextWgpu::handleError(GLenum errorCode, mErrors->handleError(errorCode, errorStream.str().c_str(), file, function, line); } -angle::Result ContextWgpu::startRenderPass(const wgpu::RenderPassDescriptor &desc) +angle::Result ContextWgpu::startRenderPass(const webgpu::PackedRenderPassDescriptor &desc) { + const DawnProcTable *wgpu = webgpu::GetProcs(this); + ensureCommandEncoderCreated(); - mCurrentRenderPass = mCurrentCommandEncoder.BeginRenderPass(&desc); + mCurrentRenderPass = webgpu::CreateRenderPass(wgpu, mCurrentCommandEncoder, desc); mDirtyBits |= mNewRenderPassDirtyBits; return angle::Result::Continue; @@ -1029,16 +1139,19 @@ angle::Result ContextWgpu::endRenderPass(webgpu::RenderPassClosureReason closure { if (mCurrentRenderPass) { + const DawnProcTable *wgpu = webgpu::GetProcs(this); + const char *reasonText = kRenderPassClosureReason[closureReason]; ASSERT(reasonText); if (mCommandBuffer.hasCommands()) { - ANGLE_WGPU_SCOPED_DEBUG_TRY(this, mCommandBuffer.recordCommands(mCurrentRenderPass)); + ANGLE_WGPU_SCOPED_DEBUG_TRY(this, + mCommandBuffer.recordCommands(wgpu, mCurrentRenderPass)); mCommandBuffer.clear(); } - mCurrentRenderPass.End(); + wgpu->renderPassEncoderEnd(mCurrentRenderPass.get()); mCurrentRenderPass = nullptr; } @@ -1058,13 +1171,27 @@ angle::Result ContextWgpu::setupDraw(const gl::Context *context, uint32_t *outFirstIndex, uint32_t *indexCountOut) { - if (mRenderPipelineDesc.setPrimitiveMode(mode, indexTypeOrInvalid)) + gl::DrawElementsType dstIndexTypeOrInvalid = indexTypeOrInvalid; + if (mode == gl::PrimitiveMode::LineLoop && + dstIndexTypeOrInvalid == gl::DrawElementsType::InvalidEnum) + { + if (vertexOrIndexCount >= std::numeric_limits::max()) + { + dstIndexTypeOrInvalid = gl::DrawElementsType::UnsignedInt; + } + else + { + dstIndexTypeOrInvalid = gl::DrawElementsType::UnsignedShort; + } + } + + if (mRenderPipelineDesc.setPrimitiveMode(mode, dstIndexTypeOrInvalid)) { invalidateCurrentRenderPipeline(); } ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable()); - if (executableWgpu->checkDirtyUniforms()) + if (executableWgpu->checkDirtyUniforms() || executableWgpu->hasDirtySamplerBindings()) { mDirtyBits.set(DIRTY_BIT_BIND_GROUPS); } @@ -1073,6 +1200,8 @@ angle::Result ContextWgpu::setupDraw(const gl::Context *context, if (mState.areClientArraysEnabled()) { VertexArrayWgpu *vertexArrayWgpu = GetImplAs(mState.getVertexArray()); + // Pass in original indexTypeOrInvalid into syncClientArrays because the method will need to + // determine if the original draw call was a DrawElements or DrawArrays call. ANGLE_TRY(vertexArrayWgpu->syncClientArrays( context, mState.getProgramExecutable()->getActiveAttribLocationsMask(), mode, firstVertexOrInvalid, vertexOrIndexCount, instanceCount, indexTypeOrInvalid, indices, @@ -1080,18 +1209,15 @@ angle::Result ContextWgpu::setupDraw(const gl::Context *context, } bool reAddDirtyIndexBufferBit = false; - if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum) + if (dstIndexTypeOrInvalid != gl::DrawElementsType::InvalidEnum) { - *outFirstIndex = gl_wgpu::GetFirstIndexForDrawCall(indexTypeOrInvalid, adjustedIndicesPtr); - if (mCurrentIndexBufferType != indexTypeOrInvalid) + *outFirstIndex = + gl_wgpu::GetFirstIndexForDrawCall(dstIndexTypeOrInvalid, adjustedIndicesPtr); + if (mCurrentIndexBufferType != dstIndexTypeOrInvalid) { invalidateIndexBuffer(); } } - else - { - ASSERT(outFirstIndex == nullptr); - } if (mDirtyBits.any()) { @@ -1131,9 +1257,9 @@ angle::Result ContextWgpu::setupDraw(const gl::Context *context, break; case DIRTY_BIT_INDEX_BUFFER: - if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum) + if (dstIndexTypeOrInvalid != gl::DrawElementsType::InvalidEnum) { - ANGLE_TRY(handleDirtyIndexBuffer(indexTypeOrInvalid, &dirtyBitIter)); + ANGLE_TRY(handleDirtyIndexBuffer(dstIndexTypeOrInvalid, &dirtyBitIter)); } else { @@ -1142,6 +1268,9 @@ angle::Result ContextWgpu::setupDraw(const gl::Context *context, reAddDirtyIndexBufferBit = true; } break; + case DIRTY_BIT_DRIVER_UNIFORMS: + ANGLE_TRY(handleDirtyDriverUniforms(&dirtyBitIter)); + break; case DIRTY_BIT_BIND_GROUPS: ANGLE_TRY(handleDirtyBindGroups(&dirtyBitIter)); break; @@ -1169,7 +1298,7 @@ angle::Result ContextWgpu::handleDirtyRenderPipelineDesc(DirtyBits::Iterator *di ProgramExecutableWgpu *executable = webgpu::GetImpl(mState.getProgramExecutable()); ASSERT(executable); - wgpu::RenderPipeline previousPipeline = std::move(mCurrentGraphicsPipeline); + webgpu::RenderPipelineHandle previousPipeline = std::move(mCurrentGraphicsPipeline); ANGLE_TRY(executable->getRenderPipeline(this, mRenderPipelineDesc, &mCurrentGraphicsPipeline)); if (mCurrentGraphicsPipeline != previousPipeline) { @@ -1222,9 +1351,17 @@ angle::Result ContextWgpu::handleDirtyViewport(DirtyBits::Iterator *dirtyBitsIte return angle::Result::Continue; } + FramebufferWgpu *drawFramebufferWgpu = webgpu::GetImpl(mState.getDrawFramebuffer()); + if (drawFramebufferWgpu->flipY()) + { + clampedViewport.y = + drawFramebufferWgpu->getState().getDimensions().height - clampedViewport.y1(); + } + ASSERT(mCurrentGraphicsPipeline); mCommandBuffer.setViewport(clampedViewport.x, clampedViewport.y, clampedViewport.width, clampedViewport.height, depthMin, depthMax); + return angle::Result::Continue; } @@ -1253,6 +1390,13 @@ angle::Result ContextWgpu::handleDirtyScissor(DirtyBits::Iterator *dirtyBitsIter return angle::Result::Continue; } + FramebufferWgpu *framebufferWgpu = webgpu::GetImpl(framebuffer); + if (framebufferWgpu->flipY()) + { + clampedScissor.y = framebufferWgpu->getState().getDimensions().height - clampedScissor.y - + clampedScissor.height; + } + ASSERT(mCurrentGraphicsPipeline); mCommandBuffer.setScissorRect(clampedScissor.x, clampedScissor.y, clampedScissor.width, clampedScissor.height); @@ -1320,7 +1464,9 @@ angle::Result ContextWgpu::handleDirtyIndexBuffer(gl::DrawElementsType indexType { ANGLE_TRY(buffer->unmap()); } - mCommandBuffer.setIndexBuffer(buffer->getBuffer(), gl_wgpu::GetIndexFormat(indexType), 0, -1); + mCommandBuffer.setIndexBuffer(buffer->getBuffer(), + static_cast(gl_wgpu::GetIndexFormat(indexType)), + 0, -1); mCurrentIndexBufferType = indexType; return angle::Result::Continue; } @@ -1328,10 +1474,96 @@ angle::Result ContextWgpu::handleDirtyIndexBuffer(gl::DrawElementsType indexType angle::Result ContextWgpu::handleDirtyBindGroups(DirtyBits::Iterator *dirtyBitsIterator) { ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable()); - wgpu::BindGroup bindGroup; - ANGLE_TRY(executableWgpu->updateUniformsAndGetBindGroup(this, &bindGroup)); - // TODO(anglebug.com/376553328): need to set up every bind group here. - mCommandBuffer.setBindGroup(sh::kDefaultUniformBlockBindGroup, bindGroup); + webgpu::BindGroupHandle defaultUniformBindGroup; + ANGLE_TRY(executableWgpu->updateUniformsAndGetBindGroup(this, &defaultUniformBindGroup)); + mCommandBuffer.setBindGroup(sh::kDefaultUniformBlockBindGroup, defaultUniformBindGroup); + + webgpu::BindGroupHandle samplerAndTextureBindGroup; + ANGLE_TRY(executableWgpu->getSamplerAndTextureBindGroup(this, &samplerAndTextureBindGroup)); + mCommandBuffer.setBindGroup(sh::kTextureAndSamplerBindGroup, samplerAndTextureBindGroup); + + // Creating the driver uniform bind group is handled by handleDirtyDriverUniforms(). + mCommandBuffer.setBindGroup(sh::kDriverUniformBindGroup, mDriverUniformsBindGroup); + + return angle::Result::Continue; +} + +angle::Result ContextWgpu::handleDirtyDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator) +{ + const DawnProcTable *wgpu = webgpu::GetProcs(this); + + DriverUniforms newDriverUniforms; + memset(&newDriverUniforms, 0, sizeof(newDriverUniforms)); + + newDriverUniforms.depthRange[0] = mState.getNearPlane(); + newDriverUniforms.depthRange[1] = mState.getFarPlane(); + + FramebufferWgpu *drawFramebufferWgpu = webgpu::GetImpl(mState.getDrawFramebuffer()); + + newDriverUniforms.renderArea = drawFramebufferWgpu->getState().getDimensions().height << 16 | + drawFramebufferWgpu->getState().getDimensions().width; + + const float flipX = 1.0f; + const float flipY = drawFramebufferWgpu->flipY() ? -1.0f : 1.0f; + newDriverUniforms.flipXY = gl::PackSnorm4x8( + flipX, flipY, flipX, mState.getClipOrigin() == gl::ClipOrigin::LowerLeft ? -flipY : flipY); + + // gl_ClipDistance + const uint32_t enabledClipDistances = mState.getEnabledClipDistances().bits(); + ASSERT((enabledClipDistances & ~sh::vk::kDriverUniformsMiscEnabledClipPlanesMask) == 0); + + // GL_CLIP_DEPTH_MODE_EXT + const uint32_t transformDepth = !mState.isClipDepthModeZeroToOne(); + ASSERT((transformDepth & ~sh::vk::kDriverUniformsMiscTransformDepthMask) == 0); + + // GL_SAMPLE_ALPHA_TO_COVERAGE + const uint32_t alphaToCoverage = mState.isSampleAlphaToCoverageEnabled(); + ASSERT((alphaToCoverage & ~sh::vk::kDriverUniformsMiscAlphaToCoverageMask) == 0); + + newDriverUniforms.misc = + (enabledClipDistances << sh::vk::kDriverUniformsMiscEnabledClipPlanesOffset) | + (transformDepth << sh::vk::kDriverUniformsMiscTransformDepthOffset) | + (alphaToCoverage << sh::vk::kDriverUniformsMiscAlphaToCoverageOffset); + + // If no change to driver uniforms, return early. + if (memcmp(&newDriverUniforms, &mDriverUniforms, sizeof(DriverUniforms)) == 0) + { + return angle::Result::Continue; + } + + // Cache the uniforms so we can check for changes later. + memcpy(&mDriverUniforms, &newDriverUniforms, sizeof(DriverUniforms)); + + // Upload the new driver uniforms to a new GPU buffer. + webgpu::BufferHelper driverUniformBuffer; + + ANGLE_TRY(driverUniformBuffer.initBuffer(wgpu, getDevice(), sizeof(DriverUniforms), + WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, + webgpu::MapAtCreation::Yes)); + + ASSERT(driverUniformBuffer.valid()); + + uint8_t *bufferData = driverUniformBuffer.getMapWritePointer(0, sizeof(DriverUniforms)); + memcpy(bufferData, &mDriverUniforms, sizeof(DriverUniforms)); + + ANGLE_TRY(driverUniformBuffer.unmap()); + + // Now create the bind group containing the driver uniform buffer. + WGPUBindGroupEntry bindGroupEntry = WGPU_BIND_GROUP_ENTRY_INIT; + bindGroupEntry.binding = sh::kDriverUniformBlockBinding; + bindGroupEntry.buffer = driverUniformBuffer.getBuffer().get(); + bindGroupEntry.offset = 0; + bindGroupEntry.size = sizeof(DriverUniforms); + + WGPUBindGroupDescriptor bindGroupDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT; + bindGroupDesc.layout = mDriverUniformsBindGroupLayout.get(); + bindGroupDesc.entryCount = 1; + bindGroupDesc.entries = &bindGroupEntry; + mDriverUniformsBindGroup = webgpu::BindGroupHandle::Acquire( + wgpu, wgpu->deviceCreateBindGroup(getDevice().get(), &bindGroupDesc)); + + // This bind group needs to be updated on the same draw call as the driver uniforms are updated. + dirtyBitsIterator->setLaterBit(DIRTY_BIT_BIND_GROUPS); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/wgpu/ContextWgpu.h b/src/libANGLE/renderer/wgpu/ContextWgpu.h index b00a27d62ee..a39caeba4a6 100644 --- a/src/libANGLE/renderer/wgpu/ContextWgpu.h +++ b/src/libANGLE/renderer/wgpu/ContextWgpu.h @@ -10,11 +10,12 @@ #ifndef LIBANGLE_RENDERER_WGPU_CONTEXTWGPU_H_ #define LIBANGLE_RENDERER_WGPU_CONTEXTWGPU_H_ -#include +#include #include "image_util/loadimage.h" #include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/wgpu/DisplayWgpu.h" +#include "libANGLE/renderer/wgpu/UtilsWgpu.h" #include "libANGLE/renderer/wgpu/wgpu_command_buffer.h" #include "libANGLE/renderer/wgpu/wgpu_format_utils.h" #include "libANGLE/renderer/wgpu/wgpu_helpers.h" @@ -26,7 +27,42 @@ namespace rx class ContextWgpu : public ContextImpl { + private: + // Must keep this in sync with DriverUniform::createUniformFields in: + // src/compiler/translator/tree_util/DriverUniform.cpp + // For shader uniforms such as gl_DepthRange and the viewport size. + // + // Note: this struct was originally for Vulkan, but may be able to be pared down for WGSL. + struct DriverUniforms + { + std::array acbBufferOffsets; + + // .x is near, .y is far + std::array depthRange; + + // Used to flip gl_FragCoord. Packed uvec2 + uint32_t renderArea; + + // Packed vec4 of snorm8 + uint32_t flipXY; + + // Only the lower 16 bits used + uint32_t dither; + + // Various bits of state: + // - Surface rotation + // - Advanced blend equation + // - Sample count + // - Enabled clip planes + // - Depth transformation + // - layered FBO + uint32_t misc; + }; + static_assert(sizeof(DriverUniforms) % (sizeof(uint32_t) * 4) == 0, + "DriverUniforms should be 16 bytes aligned"); + public: + static constexpr size_t kDriverUniformSize = sizeof(DriverUniforms); ContextWgpu(const gl::State &state, gl::ErrorSet *errorSet, DisplayWgpu *display); ~ContextWgpu() override; @@ -219,7 +255,8 @@ class ContextWgpu : public ContextImpl BufferImpl *createBuffer(const gl::BufferState &state) override; // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) override; // Query and Fence creation QueryImpl *createQuery(gl::QueryType type) override; @@ -262,16 +299,18 @@ class ContextWgpu : public ContextImpl const angle::ImageLoadContext &getImageLoadContext() const { return mImageLoadContext; } - DisplayWgpu *getDisplay() { return mDisplay; } - wgpu::Device &getDevice() { return mDisplay->getDevice(); } - wgpu::Queue &getQueue() { return mDisplay->getQueue(); } - wgpu::Instance &getInstance() { return mDisplay->getInstance(); } + DisplayWgpu *getDisplay() const { return mDisplay; } + const angle::FeaturesWgpu &getFeatures() const { return mDisplay->getFeatures(); } + const DawnProcTable *getProcs() const { return mDisplay->getProcs(); } + webgpu::DeviceHandle getDevice() const { return mDisplay->getDevice(); } + webgpu::QueueHandle getQueue() const { return mDisplay->getQueue(); } + webgpu::InstanceHandle getInstance() const { return mDisplay->getInstance(); } angle::ImageLoadContext &getImageLoadContext() { return mImageLoadContext; } const webgpu::Format &getFormat(GLenum internalFormat) const { return mDisplay->getFormat(internalFormat); } - angle::Result startRenderPass(const wgpu::RenderPassDescriptor &desc); + angle::Result startRenderPass(const webgpu::PackedRenderPassDescriptor &desc); angle::Result endRenderPass(webgpu::RenderPassClosureReason closureReason); bool hasActiveRenderPass() { return mCurrentRenderPass != nullptr; } @@ -280,17 +319,30 @@ class ContextWgpu : public ContextImpl angle::Result flush(webgpu::RenderPassClosureReason); - void setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format); - void setColorAttachmentFormats(const gl::DrawBuffersArray &formats); - void setDepthStencilFormat(wgpu::TextureFormat format); + void setColorAttachmentFormat(size_t colorIndex, WGPUTextureFormat format); + void setColorAttachmentFormats(const gl::DrawBuffersArray &formats); + void setDepthStencilFormat(WGPUTextureFormat format); void setVertexAttribute(size_t attribIndex, webgpu::PackedVertexAttribute newAttrib); void invalidateVertexBuffer(size_t slot); void invalidateVertexBuffers(); void invalidateIndexBuffer(); + void invalidateCurrentTextures(); + void invalidateDriverUniforms(); void ensureCommandEncoderCreated(); - wgpu::CommandEncoder &getCurrentCommandEncoder(); + angle::Result getCurrentCommandEncoder(webgpu::RenderPassClosureReason closureReason, + webgpu::CommandEncoderHandle *outHandle); + + // Driver uniforms are managed by ContextWgpu. + webgpu::BindGroupLayoutHandle getDriverUniformBindGroupLayout() + { + ASSERT(mDriverUniformsBindGroupLayout); + return mDriverUniformsBindGroupLayout; + } + + webgpu::UtilsWgpu *getUtils() { return &mUtils; } + webgpu::CommandBuffer &getCommandBuffer() { return mCommandBuffer; } private: // Dirty bits. @@ -309,6 +361,7 @@ class ContextWgpu : public ContextImpl DIRTY_BIT_VERTEX_BUFFERS, DIRTY_BIT_INDEX_BUFFER, + DIRTY_BIT_DRIVER_UNIFORMS, DIRTY_BIT_BIND_GROUPS, DIRTY_BIT_MAX, @@ -322,6 +375,9 @@ class ContextWgpu : public ContextImpl static_assert(DIRTY_BIT_RENDER_PIPELINE_BINDING > DIRTY_BIT_RENDER_PASS, "Render pass using dirty bit must be handled after the render pass dirty bit"); + static_assert(DIRTY_BIT_BIND_GROUPS > DIRTY_BIT_DRIVER_UNIFORMS, + "Bind group creation must be handled after editing driver uniforms"); + using DirtyBits = angle::BitSet; DirtyBits mDirtyBits; @@ -355,6 +411,7 @@ class ContextWgpu : public ContextImpl angle::Result handleDirtyIndexBuffer(gl::DrawElementsType indexType, DirtyBits::Iterator *dirtyBitsIterator); angle::Result handleDirtyBindGroups(DirtyBits::Iterator *dirtyBitsIterator); + angle::Result handleDirtyDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator); angle::Result handleDirtyRenderPass(DirtyBits::Iterator *dirtyBitsIterator); @@ -362,16 +419,27 @@ class ContextWgpu : public ContextImpl DisplayWgpu *mDisplay; - wgpu::CommandEncoder mCurrentCommandEncoder; - wgpu::RenderPassEncoder mCurrentRenderPass; + webgpu::CommandEncoderHandle mCurrentCommandEncoder; + webgpu::RenderPassEncoderHandle mCurrentRenderPass; webgpu::CommandBuffer mCommandBuffer; webgpu::RenderPipelineDesc mRenderPipelineDesc; - wgpu::RenderPipeline mCurrentGraphicsPipeline; + webgpu::RenderPipelineHandle mCurrentGraphicsPipeline; gl::AttributesMask mCurrentRenderPipelineAllAttributes; gl::DrawElementsType mCurrentIndexBufferType = gl::DrawElementsType::InvalidEnum; + + // Actual struct of driver uniforms that is copied to the GPU. Only stored to check if the next + // set of driver uniforms has changed. + DriverUniforms mDriverUniforms; + // Holds the binding group layout for the driver uniforms. + webgpu::BindGroupLayoutHandle mDriverUniformsBindGroupLayout; + // Holds the most recent driver uniforms BindGroup. Note there may be others in the + // command buffer. + webgpu::BindGroupHandle mDriverUniformsBindGroup; + + webgpu::UtilsWgpu mUtils; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp b/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp index c76b2f76b49..2fc9c0e9ded 100644 --- a/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp @@ -10,6 +10,8 @@ #include "libANGLE/renderer/wgpu/DeviceWgpu.h" #include "common/debug.h" +#include "libANGLE/Display.h" +#include "libANGLE/renderer/wgpu/DisplayWgpu.h" namespace rx { @@ -25,10 +27,35 @@ egl::Error DeviceWgpu::initialize() egl::Error DeviceWgpu::getAttribute(const egl::Display *display, EGLint attribute, void **outValue) { - UNIMPLEMENTED(); - return egl::Error(EGL_BAD_ACCESS); + DisplayWgpu *displayWgpu = webgpu::GetImpl(display); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + + switch (attribute) + { + case EGL_WEBGPU_DEVICE_ANGLE: + { + webgpu::DeviceHandle device = displayWgpu->getDevice(); + wgpu->deviceAddRef(device.get()); + *outValue = device.get(); + break; + } + case EGL_WEBGPU_ADAPTER_ANGLE: + { + webgpu::AdapterHandle adapater = displayWgpu->getAdapter(); + wgpu->adapterAddRef(adapater.get()); + *outValue = adapater.get(); + break; + } + default: + return egl::Error(EGL_BAD_ATTRIBUTE); + } + + return egl::NoError(); } -void DeviceWgpu::generateExtensions(egl::DeviceExtensions *outExtensions) const {} +void DeviceWgpu::generateExtensions(egl::DeviceExtensions *outExtensions) const +{ + outExtensions->deviceWebGPU = true; +} } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/DisplayWgpu.cpp b/src/libANGLE/renderer/wgpu/DisplayWgpu.cpp index 501b0afd9d7..b7271732a52 100644 --- a/src/libANGLE/renderer/wgpu/DisplayWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/DisplayWgpu.cpp @@ -20,24 +20,84 @@ #include "libANGLE/renderer/wgpu/DisplayWgpu_api.h" #include "libANGLE/renderer/wgpu/ImageWgpu.h" #include "libANGLE/renderer/wgpu/SurfaceWgpu.h" +#include "libANGLE/renderer/wgpu/wgpu_proc_utils.h" + +#if defined(ANGLE_PLATFORM_LINUX) +# if defined(ANGLE_USE_X11) +# define ANGLE_WEBGPU_HAS_WINDOW_SURFACE_TYPE 1 +# define ANGLE_WEBGPU_WINDOW_SYSTEM angle::NativeWindowSystem::X11 +# elif defined(ANGLE_USE_WAYLAND) +# define ANGLE_WEBGPU_HAS_WINDOW_SURFACE_TYPE 1 +# define ANGLE_WEBGPU_WINDOW_SYSTEM angle::NativeWindowSystem::Wayland +# else +# define ANGLE_WEBGPU_HAS_WINDOW_SURFACE_TYPE 0 +# define ANGLE_WEBGPU_WINDOW_SYSTEM angle::NativeWindowSystem::Other +# endif +#else +# define ANGLE_WEBGPU_HAS_WINDOW_SURFACE_TYPE 1 +# define ANGLE_WEBGPU_WINDOW_SYSTEM angle::NativeWindowSystem::Other +#endif namespace rx { +#if !ANGLE_WEBGPU_HAS_WINDOW_SURFACE_TYPE +WindowSurfaceWgpu *CreateWgpuWindowSurface(const egl::SurfaceState &surfaceState, + EGLNativeWindowType window) +{ + UNIMPLEMENTED(); + return nullptr; +} +#endif + DisplayWgpu::DisplayWgpu(const egl::DisplayState &state) : DisplayImpl(state) {} DisplayWgpu::~DisplayWgpu() {} egl::Error DisplayWgpu::initialize(egl::Display *display) { - ANGLE_TRY(createWgpuDevice()); + const egl::AttributeMap &attribs = display->getAttributeMap(); + mProcTable = *reinterpret_cast( + attribs.get(EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE, + reinterpret_cast(&webgpu::GetDefaultProcTable()))); + + WGPUInstance providedInstance = + reinterpret_cast(attribs.get(EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE, 0)); + if (providedInstance) + { + mProcTable.instanceAddRef(providedInstance); + mInstance = webgpu::InstanceHandle::Acquire(&mProcTable, providedInstance); + } + + WGPUDevice providedDevice = + reinterpret_cast(attribs.get(EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE, 0)); + if (providedDevice) + { + mProcTable.deviceAddRef(providedDevice); + mDevice = webgpu::DeviceHandle::Acquire(&mProcTable, providedDevice); + + mAdapter = + webgpu::AdapterHandle::Acquire(&mProcTable, mProcTable.deviceGetAdapter(mDevice.get())); + + if (!mInstance) + { + mInstance = webgpu::InstanceHandle::Acquire( + &mProcTable, mProcTable.adapterGetInstance(mAdapter.get())); + } + } + else + { + ANGLE_TRY(createWgpuDevice()); + } + + mQueue = webgpu::QueueHandle::Acquire(&mProcTable, mProcTable.deviceGetQueue(mDevice.get())); - mQueue = mDevice.GetQueue(); mFormatTable.initialize(); - wgpu::SupportedLimits supportedLimits; - mDevice.GetLimits(&supportedLimits); - mLimitsWgpu = supportedLimits.limits; + mLimitsWgpu = WGPU_LIMITS_INIT; + mProcTable.deviceGetLimits(mDevice.get(), &mLimitsWgpu); + + initializeFeatures(); webgpu::GenerateCaps(mLimitsWgpu, &mGLCaps, &mGLTextureCaps, &mGLExtensions, &mGLLimitations, &mEGLCaps, &mEGLExtensions, &mMaxSupportedClientVersion); @@ -45,7 +105,13 @@ egl::Error DisplayWgpu::initialize(egl::Display *display) return egl::NoError(); } -void DisplayWgpu::terminate() {} +void DisplayWgpu::terminate() +{ + mAdapter = nullptr; + mInstance = nullptr; + mDevice = nullptr; + mQueue = nullptr; +} egl::Error DisplayWgpu::makeCurrent(egl::Display *display, egl::Surface *drawSurface, @@ -70,8 +136,8 @@ egl::ConfigSet DisplayWgpu::generateConfigs() config.blueSize = 8; config.alphaSize = 8; config.alphaMaskSize = 0; - config.bindToTextureRGB = EGL_TRUE; - config.bindToTextureRGBA = EGL_TRUE; + config.bindToTextureRGB = EGL_FALSE; + config.bindToTextureRGBA = EGL_FALSE; config.colorBufferType = EGL_RGB_BUFFER; config.configCaveat = EGL_NONE; config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT; @@ -90,7 +156,10 @@ egl::ConfigSet DisplayWgpu::generateConfigs() config.sampleBuffers = 0; config.samples = 0; config.stencilSize = 8; - config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + config.surfaceType = EGL_PBUFFER_BIT; +#if ANGLE_WEBGPU_HAS_WINDOW_SURFACE_TYPE + config.surfaceType |= EGL_WINDOW_BIT; +#endif config.optimalOrientation = 0; config.transparentType = EGL_NONE; config.transparentRedValue = 0; @@ -112,6 +181,54 @@ egl::Error DisplayWgpu::restoreLostDevice(const egl::Display *display) return egl::NoError(); } +egl::Error DisplayWgpu::validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const +{ + switch (buftype) + { + case EGL_WEBGPU_TEXTURE_ANGLE: + return validateExternalWebGPUTexture(clientBuffer, attribs); + default: + return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs); + } +} + +egl::Error DisplayWgpu::validateImageClientBuffer(const gl::Context *context, + EGLenum target, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const +{ + switch (target) + { + case EGL_WEBGPU_TEXTURE_ANGLE: + return validateExternalWebGPUTexture(clientBuffer, attribs); + default: + return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs); + } +} + +egl::Error DisplayWgpu::validateExternalWebGPUTexture(EGLClientBuffer buffer, + const egl::AttributeMap &attribs) const +{ + WGPUTexture externalTexture = reinterpret_cast(buffer); + if (externalTexture == nullptr) + { + return egl::Error(EGL_BAD_PARAMETER, "NULL Buffer"); + } + + WGPUTextureFormat externalTextureFormat = mProcTable.textureGetFormat(externalTexture); + const webgpu::Format *webgpuFormat = + getFormatForImportedTexture(attribs, externalTextureFormat); + if (webgpuFormat == nullptr) + { + return egl::Error(EGL_BAD_PARAMETER, "Invalid format."); + } + + return egl::NoError(); +} + bool DisplayWgpu::isValidNativeWindow(EGLNativeWindowType window) const { return true; @@ -119,12 +236,12 @@ bool DisplayWgpu::isValidNativeWindow(EGLNativeWindowType window) const std::string DisplayWgpu::getRendererDescription() { - return "Wgpu"; + return "WebGPU"; } std::string DisplayWgpu::getVendorString() { - return "Wgpu"; + return "WebGPU"; } std::string DisplayWgpu::getVersionString(bool includeFullVersion) @@ -167,7 +284,7 @@ SurfaceImpl *DisplayWgpu::createWindowSurface(const egl::SurfaceState &state, SurfaceImpl *DisplayWgpu::createPbufferSurface(const egl::SurfaceState &state, const egl::AttributeMap &attribs) { - return new OffscreenSurfaceWgpu(state); + return new OffscreenSurfaceWgpu(state, EGL_NONE, nullptr); } SurfaceImpl *DisplayWgpu::createPbufferFromClientBuffer(const egl::SurfaceState &state, @@ -175,8 +292,7 @@ SurfaceImpl *DisplayWgpu::createPbufferFromClientBuffer(const egl::SurfaceState EGLClientBuffer buffer, const egl::AttributeMap &attribs) { - UNIMPLEMENTED(); - return nullptr; + return new OffscreenSurfaceWgpu(state, buftype, buffer); } SurfaceImpl *DisplayWgpu::createPixmapSurface(const egl::SurfaceState &state, @@ -192,7 +308,21 @@ ImageImpl *DisplayWgpu::createImage(const egl::ImageState &state, EGLenum target, const egl::AttributeMap &attribs) { - return new ImageWgpu(state); + return new ImageWgpu(state, context); +} + +ExternalImageSiblingImpl *DisplayWgpu::createExternalImageSibling(const gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const egl::AttributeMap &attribs) +{ + switch (target) + { + case EGL_WEBGPU_TEXTURE_ANGLE: + return new WebGPUTextureImageSiblingWgpu(buffer, attribs); + default: + return DisplayImpl::createExternalImageSibling(context, target, buffer, attribs); + } } rx::ContextImpl *DisplayWgpu::createContext(const gl::State &state, @@ -217,17 +347,43 @@ ShareGroupImpl *DisplayWgpu::createShareGroup(const egl::ShareGroupState &state) return new ShareGroupWgpu(state); } +void DisplayWgpu::populateFeatureList(angle::FeatureList *features) +{ + mFeatures.populateFeatureList(features); +} + angle::NativeWindowSystem DisplayWgpu::getWindowSystem() const { -#if defined(ANGLE_PLATFORM_LINUX) -# if defined(ANGLE_USE_X11) - return angle::NativeWindowSystem::X11; -# elif defined(ANGLE_USE_WAYLAND) - return angle::NativeWindowSystem::Wayland; -# endif -#else - return angle::NativeWindowSystem::Other; -#endif + return ANGLE_WEBGPU_WINDOW_SYSTEM; +} + +const webgpu::Format *DisplayWgpu::getFormatForImportedTexture(const egl::AttributeMap &attribs, + WGPUTextureFormat wgpuFormat) const +{ + GLenum requestedGLFormat = attribs.getAsInt(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_NONE); + GLenum requestedGLType = attribs.getAsInt(EGL_TEXTURE_TYPE_ANGLE, GL_NONE); + + if (requestedGLFormat != GL_NONE) + { + const gl::InternalFormat &internalFormat = + gl::GetInternalFormatInfo(requestedGLFormat, requestedGLType); + if (internalFormat.internalFormat == GL_NONE) + { + return nullptr; + } + + const webgpu::Format &format = mFormatTable[internalFormat.sizedInternalFormat]; + if (format.getActualWgpuTextureFormat() != wgpuFormat) + { + return nullptr; + } + + return &format; + } + else + { + return mFormatTable.findClosestTextureFormat(wgpuFormat); + } } void DisplayWgpu::generateExtensions(egl::DisplayExtensions *outExtensions) const @@ -240,42 +396,60 @@ void DisplayWgpu::generateCaps(egl::Caps *outCaps) const *outCaps = mEGLCaps; } -egl::Error DisplayWgpu::createWgpuDevice() +void DisplayWgpu::initializeFeatures() { - dawnProcSetProcs(&dawn::native::GetProcs()); + ApplyFeatureOverrides(&mFeatures, getState().featureOverrides); + if (mState.featureOverrides.allDisabled) + { + return; + } - dawn::native::DawnInstanceDescriptor dawnInstanceDescriptor; + // Disabled by default. Gets explicitly enabled by ANGLE embedders. + ANGLE_FEATURE_CONDITION((&mFeatures), avoidWaitAny, false); +} - wgpu::InstanceDescriptor instanceDescriptor; - instanceDescriptor.features.timedWaitAnyEnable = true; - instanceDescriptor.nextInChain = &dawnInstanceDescriptor; - mInstance = wgpu::CreateInstance(&instanceDescriptor); +egl::Error DisplayWgpu::createWgpuDevice() +{ + if (!mInstance) + { + WGPUInstanceDescriptor instanceDescriptor = WGPU_INSTANCE_DESCRIPTOR_INIT; + static constexpr auto kTimedWaitAny = WGPUInstanceFeatureName_TimedWaitAny; + instanceDescriptor.requiredFeatureCount = 1; + instanceDescriptor.requiredFeatures = &kTimedWaitAny; + mInstance = webgpu::InstanceHandle::Acquire(&mProcTable, + mProcTable.createInstance(&instanceDescriptor)); + } struct RequestAdapterResult { WGPURequestAdapterStatus status; - wgpu::Adapter adapter; + webgpu::AdapterHandle adapter; std::string message; }; RequestAdapterResult adapterResult; - wgpu::RequestAdapterOptions requestAdapterOptions; + WGPURequestAdapterOptions requestAdapterOptions = WGPU_REQUEST_ADAPTER_OPTIONS_INIT; + + WGPURequestAdapterCallbackInfo requestAdapterCallback = WGPU_REQUEST_ADAPTER_CALLBACK_INFO_INIT; + requestAdapterCallback.mode = WGPUCallbackMode_WaitAnyOnly; + requestAdapterCallback.callback = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, + struct WGPUStringView message, void *userdata1, + void *userdata2) { + RequestAdapterResult *result = reinterpret_cast(userdata1); + const DawnProcTable *wgpu = reinterpret_cast(userdata2); - wgpu::RequestAdapterCallbackInfo callbackInfo; - callbackInfo.mode = wgpu::CallbackMode::WaitAnyOnly; - callbackInfo.callback = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, - char const *message, void *userdata) { - RequestAdapterResult *result = reinterpret_cast(userdata); - result->status = status; - result->adapter = wgpu::Adapter::Acquire(adapter); - result->message = message ? message : ""; + result->status = status; + result->adapter = webgpu::AdapterHandle::Acquire(wgpu, adapter); + result->message = std::string(message.data, message.length); }; - callbackInfo.userdata = &adapterResult; + requestAdapterCallback.userdata1 = &adapterResult; + requestAdapterCallback.userdata2 = &mProcTable; - wgpu::FutureWaitInfo futureWaitInfo; - futureWaitInfo.future = mInstance.RequestAdapter(&requestAdapterOptions, callbackInfo); + WGPUFutureWaitInfo futureWaitInfo; + futureWaitInfo.future = mProcTable.instanceRequestAdapter( + mInstance.get(), &requestAdapterOptions, requestAdapterCallback); - wgpu::WaitStatus status = mInstance.WaitAny(1, &futureWaitInfo, -1); + WGPUWaitStatus status = mProcTable.instanceWaitAny(mInstance.get(), 1, &futureWaitInfo, -1); if (webgpu::IsWgpuError(status)) { std::ostringstream err; @@ -285,18 +459,56 @@ egl::Error DisplayWgpu::createWgpuDevice() mAdapter = adapterResult.adapter; - std::vector requiredFeatures; // empty for now + std::vector requiredFeatures; // empty for now - wgpu::DeviceDescriptor deviceDesc; + WGPUDeviceDescriptor deviceDesc = WGPU_DEVICE_DESCRIPTOR_INIT; deviceDesc.requiredFeatureCount = requiredFeatures.size(); deviceDesc.requiredFeatures = requiredFeatures.data(); + deviceDesc.uncapturedErrorCallbackInfo.callback = + [](WGPUDevice const *device, WGPUErrorType type, struct WGPUStringView message, + void *userdata1, void *userdata2) { + ASSERT(userdata1 == nullptr); + ASSERT(userdata2 == nullptr); + ERR() << "Error: " << static_cast::type>(type) + << " - message: " << std::string(message.data, message.length); + }; + + struct RequestDeviceResult + { + WGPURequestDeviceStatus status; + webgpu::DeviceHandle device; + std::string message; + }; + RequestDeviceResult deviceResult; + + WGPURequestDeviceCallbackInfo requestDeviceCallback = WGPU_REQUEST_DEVICE_CALLBACK_INFO_INIT; + requestDeviceCallback.mode = WGPUCallbackMode_WaitAnyOnly; + requestDeviceCallback.callback = [](WGPURequestDeviceStatus status, WGPUDevice device, + struct WGPUStringView message, void *userdata1, + void *userdata2) { + RequestDeviceResult *result = reinterpret_cast(userdata1); + const DawnProcTable *wgpu = reinterpret_cast(userdata2); + + result->status = status; + result->device = webgpu::DeviceHandle::Acquire(wgpu, device); + result->message = std::string(message.data, message.length); + }; + requestDeviceCallback.userdata1 = &deviceResult; + requestDeviceCallback.userdata2 = &mProcTable; + + futureWaitInfo.future = + mProcTable.adapterRequestDevice(mAdapter.get(), &deviceDesc, requestDeviceCallback); + + status = mProcTable.instanceWaitAny(mInstance.get(), 1, &futureWaitInfo, -1); + if (webgpu::IsWgpuError(status)) + { + std::ostringstream err; + err << "Failed to get WebGPU device: " << deviceResult.message; + return egl::Error(EGL_BAD_ALLOC, err.str()); + } + + mDevice = deviceResult.device; - mDevice = mAdapter.CreateDevice(&deviceDesc); - mDevice.SetUncapturedErrorCallback( - [](WGPUErrorType type, const char *message, void *userdata) { - ERR() << "Error: " << type << " - message: " << message; - }, - nullptr); return egl::NoError(); } diff --git a/src/libANGLE/renderer/wgpu/DisplayWgpu.h b/src/libANGLE/renderer/wgpu/DisplayWgpu.h index ab622272617..3db3b6361aa 100644 --- a/src/libANGLE/renderer/wgpu/DisplayWgpu.h +++ b/src/libANGLE/renderer/wgpu/DisplayWgpu.h @@ -10,12 +10,13 @@ #ifndef LIBANGLE_RENDERER_WGPU_DISPLAYWGPU_H_ #define LIBANGLE_RENDERER_WGPU_DISPLAYWGPU_H_ -#include -#include +#include #include "libANGLE/renderer/DisplayImpl.h" #include "libANGLE/renderer/ShareGroupImpl.h" #include "libANGLE/renderer/wgpu/wgpu_format_utils.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" +#include "platform/autogen/FeaturesWgpu_autogen.h" namespace rx { @@ -46,6 +47,15 @@ class DisplayWgpu : public DisplayImpl bool testDeviceLost() override; egl::Error restoreLostDevice(const egl::Display *display) override; + egl::Error validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const override; + egl::Error validateImageClientBuffer(const gl::Context *context, + EGLenum target, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const override; + bool isValidNativeWindow(EGLNativeWindowType window) const override; std::string getRendererDescription() override; @@ -76,6 +86,10 @@ class DisplayWgpu : public DisplayImpl const gl::Context *context, EGLenum target, const egl::AttributeMap &attribs) override; + ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const egl::AttributeMap &attribs) override; ContextImpl *createContext(const gl::State &state, gl::ErrorSet *errorSet, @@ -88,16 +102,18 @@ class DisplayWgpu : public DisplayImpl ShareGroupImpl *createShareGroup(const egl::ShareGroupState &state) override; - void populateFeatureList(angle::FeatureList *features) override {} + void populateFeatureList(angle::FeatureList *features) override; angle::NativeWindowSystem getWindowSystem() const override; - wgpu::Adapter &getAdapter() { return mAdapter; } - wgpu::Device &getDevice() { return mDevice; } - wgpu::Queue &getQueue() { return mQueue; } - wgpu::Instance &getInstance() { return mInstance; } + const DawnProcTable *getProcs() const { return &mProcTable; } + const angle::FeaturesWgpu &getFeatures() const { return mFeatures; } + webgpu::AdapterHandle getAdapter() { return mAdapter; } + webgpu::DeviceHandle getDevice() { return mDevice; } + webgpu::QueueHandle getQueue() { return mQueue; } + webgpu::InstanceHandle getInstance() { return mInstance; } - const wgpu::Limits getLimitsWgpu() const { return mLimitsWgpu; } + const WGPULimits &getLimitsWgpu() const { return mLimitsWgpu; } const gl::Caps &getGLCaps() const { return mGLCaps; } const gl::TextureCapsMap &getGLTextureCaps() const { return mGLTextureCaps; } @@ -105,25 +121,33 @@ class DisplayWgpu : public DisplayImpl const gl::Limitations &getGLLimitations() const { return mGLLimitations; } const ShPixelLocalStorageOptions &getPLSOptions() const { return mPLSOptions; } - std::map &getSurfaceCache() { return mSurfaceCache; } - const webgpu::Format &getFormat(GLenum internalFormat) const { return mFormatTable[internalFormat]; } + const webgpu::Format *getFormatForImportedTexture(const egl::AttributeMap &attribs, + WGPUTextureFormat wgpuFormat) const; + private: + egl::Error validateExternalWebGPUTexture(EGLClientBuffer buffer, + const egl::AttributeMap &attribs) const; + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateCaps(egl::Caps *outCaps) const override; + void initializeFeatures(); + egl::Error createWgpuDevice(); - wgpu::Adapter mAdapter; - wgpu::Instance mInstance; - wgpu::Device mDevice; - wgpu::Queue mQueue; + DawnProcTable mProcTable; + + webgpu::AdapterHandle mAdapter; + webgpu::InstanceHandle mInstance; + webgpu::DeviceHandle mDevice; + webgpu::QueueHandle mQueue; - wgpu::Limits mLimitsWgpu; + WGPULimits mLimitsWgpu; gl::Caps mGLCaps; gl::TextureCapsMap mGLTextureCaps; @@ -134,14 +158,9 @@ class DisplayWgpu : public DisplayImpl gl::Version mMaxSupportedClientVersion; ShPixelLocalStorageOptions mPLSOptions; - // http://anglebug.com/342213844 - // Dawn currently holds references to the internal swap chains for an unknown amount of time - // after destroying a surface and can fail to create a new swap chain for the same window. - // ANGLE tests re-create EGL surfaces for the same window each test. As a workaround, cache the - // wgpu::Surface created for each window for the lifetime of the display. - std::map mSurfaceCache; - webgpu::FormatTable mFormatTable; + + angle::FeaturesWgpu mFeatures; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/FramebufferWgpu.cpp b/src/libANGLE/renderer/wgpu/FramebufferWgpu.cpp index 2794d8f296f..f01ec5933d9 100644 --- a/src/libANGLE/renderer/wgpu/FramebufferWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/FramebufferWgpu.cpp @@ -7,6 +7,10 @@ // Implements the class methods for FramebufferWgpu. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/FramebufferWgpu.h" #include <__config> @@ -17,69 +21,14 @@ #include "libANGLE/renderer/wgpu/ContextWgpu.h" #include "libANGLE/renderer/wgpu/RenderTargetWgpu.h" #include "libANGLE/renderer/wgpu/wgpu_utils.h" +#include "webgpu/webgpu.h" namespace rx { -namespace -{ -bool CompareColorRenderPassAttachments(const wgpu::RenderPassColorAttachment &attachment1, - const wgpu::RenderPassColorAttachment &attachment2) -{ - - if (attachment1.nextInChain != nullptr || attachment2.nextInChain != nullptr) - { - return false; - } - - return attachment1.view.Get() == attachment2.view.Get() && - attachment1.depthSlice == attachment2.depthSlice && - attachment1.resolveTarget.Get() == attachment2.resolveTarget.Get() && - attachment1.loadOp == attachment2.loadOp && attachment1.storeOp == attachment2.storeOp && - attachment1.clearValue.r == attachment2.clearValue.r && - attachment1.clearValue.g == attachment2.clearValue.g && - attachment1.clearValue.b == attachment2.clearValue.b && - attachment1.clearValue.a == attachment2.clearValue.a; -} - -bool CompareColorRenderPassAttachmentVectors( - const std::vector &attachments1, - const std::vector &attachments2) -{ - if (attachments1.size() != attachments2.size()) - { - return false; - } - - for (uint32_t i = 0; i < attachments1.size(); ++i) - { - if (!CompareColorRenderPassAttachments(attachments1[i], attachments2[i])) - { - return false; - } - } - - return true; -} - -bool CompareDepthStencilRenderPassAttachments( - const wgpu::RenderPassDepthStencilAttachment &attachment1, - const wgpu::RenderPassDepthStencilAttachment &attachment2) -{ - return attachment1.view.Get() == attachment2.view.Get() && - attachment1.depthLoadOp == attachment2.depthLoadOp && - attachment1.depthStoreOp == attachment2.depthStoreOp && - attachment1.depthClearValue == attachment2.depthClearValue && - attachment1.stencilLoadOp == attachment2.stencilLoadOp && - attachment1.stencilStoreOp == attachment2.stencilStoreOp && - attachment1.stencilClearValue == attachment2.stencilClearValue && - attachment1.stencilReadOnly == attachment2.stencilReadOnly; -} -} // namespace - FramebufferWgpu::FramebufferWgpu(const gl::FramebufferState &state) : FramebufferImpl(state) { - mCurrentColorAttachmentFormats.fill(wgpu::TextureFormat::Undefined); + mCurrentColorAttachmentFormats.fill(WGPUTextureFormat_Undefined); } FramebufferWgpu::~FramebufferWgpu() {} @@ -116,43 +65,32 @@ angle::Result FramebufferWgpu::clear(const gl::Context *context, GLbitfield mask ContextWgpu *contextWgpu = GetImplAs(context); - gl::ColorF colorClearValue = context->getState().getColorClearValue(); + webgpu::PackedRenderPassDescriptor clearRenderPassDesc; + + gl::ColorF clearValue = context->getState().getColorClearValue(); gl::DrawBufferMask clearColorBuffers = mState.getEnabledDrawBuffers(); - wgpu::Color clearValue; - clearValue.r = colorClearValue.red; - clearValue.g = colorClearValue.green; - clearValue.b = colorClearValue.blue; - clearValue.a = colorClearValue.alpha; - std::vector colorAttachments; - wgpu::RenderPassDepthStencilAttachment depthStencilAttachment; float depthValue = 1; uint32_t stencilValue = 0; for (size_t enabledDrawBuffer : clearColorBuffers) { - colorAttachments.push_back(webgpu::CreateNewClearColorAttachment( - clearValue, wgpu::kDepthSliceUndefined, + clearRenderPassDesc.colorAttachments.push_back(webgpu::CreateNewClearColorAttachment( + clearValue, WGPU_DEPTH_SLICE_UNDEFINED, mRenderTargetCache.getColorDraw(mState, enabledDrawBuffer)->getTextureView())); } - // Attempt to end a render pass if one has already been started. - bool isActiveRenderPass = - !CompareColorRenderPassAttachmentVectors(mCurrentColorAttachments, colorAttachments) || - contextWgpu->hasActiveRenderPass(); - if (clearDepth || clearStencil) { - depthValue = context->getState().getDepthClearValue(); stencilValue = static_cast(context->getState().getStencilClearValue()); - depthStencilAttachment = webgpu::CreateNewDepthStencilAttachment( + clearRenderPassDesc.depthStencilAttachment = webgpu::CreateNewClearDepthStencilAttachment( depthValue, stencilValue, mRenderTargetCache.getDepthStencil()->getTextureView(), clearDepth, clearStencil); - - isActiveRenderPass = - isActiveRenderPass || !CompareDepthStencilRenderPassAttachments( - depthStencilAttachment, mCurrentDepthStencilAttachment); } + // Attempt to end a render pass if one has already been started. + bool isActiveRenderPass = + mCurrentRenderPassDesc != clearRenderPassDesc || contextWgpu->hasActiveRenderPass(); + if (mDeferredClears.any()) { // Merge the current clear command with any deferred clears. This is to keep the clear paths @@ -179,9 +117,8 @@ angle::Result FramebufferWgpu::clear(const gl::Context *context, GLbitfield mask { deferredClearValue.stencilValue = mDeferredClears.getStencilValue(); } - renderTarget->getImage()->stageClear( - renderTarget->getImage()->toGlLevel(renderTarget->getLevelIndex()), - deferredClearValue, false, false); + renderTarget->getImage()->stageClear(renderTarget->getGlLevel(), deferredClearValue, + false, false); } if (mDeferredClears.hasDepth() || mDeferredClears.hasStencil()) { @@ -189,9 +126,9 @@ angle::Result FramebufferWgpu::clear(const gl::Context *context, GLbitfield mask dsClearValue.depthValue = mDeferredClears.getDepthValue(); dsClearValue.stencilValue = mDeferredClears.getStencilValue(); RenderTargetWgpu *renderTarget = mRenderTargetCache.getDepthStencil(); - renderTarget->getImage()->stageClear( - renderTarget->getImage()->toGlLevel(renderTarget->getLevelIndex()), - dsClearValue, mDeferredClears.hasDepth(), mDeferredClears.hasStencil()); + renderTarget->getImage()->stageClear(renderTarget->getGlLevel(), dsClearValue, + mDeferredClears.hasDepth(), + mDeferredClears.hasStencil()); } mDeferredClears.reset(); } @@ -203,8 +140,7 @@ angle::Result FramebufferWgpu::clear(const gl::Context *context, GLbitfield mask ANGLE_TRY(contextWgpu->endRenderPass(webgpu::RenderPassClosureReason::NewRenderPass)); } - setUpForRenderPass(contextWgpu, (clearDepth || clearStencil), std::move(colorAttachments), - depthStencilAttachment); + mCurrentRenderPassDesc = std::move(clearRenderPassDesc); ANGLE_TRY(contextWgpu->startRenderPass(mCurrentRenderPassDesc)); ANGLE_TRY(contextWgpu->endRenderPass(webgpu::RenderPassClosureReason::NewRenderPass)); return angle::Result::Continue; @@ -271,23 +207,32 @@ angle::Result FramebufferWgpu::readPixels(const gl::Context *context, // nothing to read return angle::Result::Continue; } + gl::Rectangle flippedArea = getReadArea(context, clippedArea); ContextWgpu *contextWgpu = GetImplAs(context); ANGLE_TRY(flushDeferredClears(contextWgpu)); - ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::GLReadPixels)); - GLuint outputSkipBytes = 0; PackPixelsParams params; ANGLE_TRY(webgpu::ImageHelper::getReadPixelsParams(contextWgpu, pack, packBuffer, format, type, origArea, clippedArea, ¶ms, &outputSkipBytes)); - params.reverseRowOrder = !params.reverseRowOrder; + if (mFlipY) + { + params.reverseRowOrder = !params.reverseRowOrder; + } + + // Does not handle reading from depth/stencil buffer(s). + ASSERT(format != GL_DEPTH_COMPONENT && format != GL_STENCIL_INDEX); + + RenderTargetWgpu *readRT = getReadPixelsRenderTarget(); + uint32_t layer = readRT->getLayer(); - webgpu::ImageHelper *sourceImageHelper = getReadPixelsRenderTarget()->getImage(); - ANGLE_TRY(sourceImageHelper->readPixels(contextWgpu, params.area, params, + webgpu::ImageHelper *sourceImageHelper = readRT->getImage(); + ANGLE_TRY(sourceImageHelper->readPixels(contextWgpu, flippedArea, params, + readRT->getLevelIndex(), layer, static_cast(pixels) + outputSkipBytes)); return angle::Result::Continue; @@ -333,7 +278,7 @@ angle::Result FramebufferWgpu::syncState(const gl::Context *context, RenderTargetWgpu *rt = mRenderTargetCache.getDepthStencil(); mCurrentDepthStencilFormat = (rt && rt->getImage()) ? rt->getImage()->toWgpuTextureFormat() - : wgpu::TextureFormat::Undefined; + : WGPUTextureFormat_Undefined; if (binding == GL_DRAW_FRAMEBUFFER) { contextWgpu->setDepthStencilFormat(mCurrentDepthStencilFormat); @@ -379,7 +324,7 @@ angle::Result FramebufferWgpu::syncState(const gl::Context *context, RenderTargetWgpu *rt = mRenderTargetCache.getColorDraw(mState, colorIndexGL); mCurrentColorAttachmentFormats[colorIndexGL] = (rt && rt->getImage()) ? rt->getImage()->toWgpuTextureFormat() - : wgpu::TextureFormat::Undefined; + : WGPUTextureFormat_Undefined; if (binding == GL_DRAW_FRAMEBUFFER) { contextWgpu->setColorAttachmentFormat( @@ -394,6 +339,8 @@ angle::Result FramebufferWgpu::syncState(const gl::Context *context, // Like in Vulkan, defer clears for draw framebuffer ops as well as clears to read framebuffer // attachments that are not taking part in a blit operation. + ASSERT(mDeferredClears.empty()); + const bool isBlitCommand = command >= gl::Command::Blit && command <= gl::Command::BlitAll; bool deferColorClears = binding == GL_DRAW_FRAMEBUFFER; bool deferDepthStencilClears = binding == GL_DRAW_FRAMEBUFFER; @@ -433,17 +380,27 @@ RenderTargetWgpu *FramebufferWgpu::getReadPixelsRenderTarget() const } void FramebufferWgpu::addNewColorAttachments( - std::vector newColorAttachments) + std::vector newColorAttachments) { - mNewColorAttachments.insert(mCurrentColorAttachments.end(), newColorAttachments.begin(), - newColorAttachments.end()); + if (!mNewRenderPassDesc.has_value()) + { + mNewRenderPassDesc = webgpu::PackedRenderPassDescriptor(); + } + + for (webgpu::PackedRenderPassColorAttachment &colorAttachment : newColorAttachments) + { + mNewRenderPassDesc->colorAttachments.push_back(colorAttachment); + } } void FramebufferWgpu::updateDepthStencilAttachment( - wgpu::RenderPassDepthStencilAttachment newRenderPassDepthStencilAttachment) + webgpu::PackedRenderPassDepthStencilAttachment newRenderPassDepthStencilAttachment) { - mNewDepthStencilAttachment = std::move(newRenderPassDepthStencilAttachment); - mAddedNewDepthStencilAttachment = true; + if (!mNewRenderPassDesc.has_value()) + { + mNewRenderPassDesc = webgpu::PackedRenderPassDescriptor(); + } + mNewRenderPassDesc->depthStencilAttachment = std::move(newRenderPassDepthStencilAttachment); } angle::Result FramebufferWgpu::flushOneColorAttachmentUpdate(const gl::Context *context, @@ -511,9 +468,7 @@ angle::Result FramebufferWgpu::flushAttachmentUpdates(const gl::Context *context } // If we added any new attachments, we start a render pass to fully flush the updates. - if ((!mNewColorAttachments.empty() && - mNewColorAttachments.size() != mCurrentColorAttachments.size()) || - mAddedNewDepthStencilAttachment) + if (mNewRenderPassDesc.has_value()) { ANGLE_TRY(startRenderPassNewAttachments(contextWgpu)); } @@ -527,35 +482,33 @@ angle::Result FramebufferWgpu::flushDeferredClears(ContextWgpu *contextWgpu) return angle::Result::Continue; } ANGLE_TRY(contextWgpu->endRenderPass(webgpu::RenderPassClosureReason::NewRenderPass)); - mCurrentColorAttachments.clear(); + + webgpu::PackedRenderPassDescriptor clearRenderPassDesc; for (size_t colorIndexGL : mState.getColorAttachmentsMask()) { if (!mDeferredClears.test(colorIndexGL)) { continue; } - mCurrentColorAttachments.push_back(webgpu::CreateNewClearColorAttachment( + clearRenderPassDesc.colorAttachments.push_back(webgpu::CreateNewClearColorAttachment( mDeferredClears[colorIndexGL].clearColor, mDeferredClears[colorIndexGL].depthSlice, mRenderTargetCache.getColorDraw(mState, colorIndexGL)->getTextureView())); } if (mRenderTargetCache.getDepthStencil() && (mDeferredClears.hasDepth() || mDeferredClears.hasStencil())) { - mCurrentDepthStencilAttachment = webgpu::CreateNewDepthStencilAttachment( + clearRenderPassDesc.depthStencilAttachment = webgpu::CreateNewClearDepthStencilAttachment( mDeferredClears.getDepthValue(), mDeferredClears.getStencilValue(), mRenderTargetCache.getDepthStencil()->getTextureView(), !mDeferredClears.hasDepth(), !mDeferredClears.hasStencil()); - mCurrentRenderPassDesc.depthStencilAttachment = &mCurrentDepthStencilAttachment; } - else - { - mCurrentRenderPassDesc.depthStencilAttachment = nullptr; - } - mCurrentRenderPassDesc.colorAttachmentCount = mCurrentColorAttachments.size(); - mCurrentRenderPassDesc.colorAttachments = mCurrentColorAttachments.data(); + + mCurrentRenderPassDesc = std::move(clearRenderPassDesc); ANGLE_TRY(contextWgpu->startRenderPass(mCurrentRenderPassDesc)); ANGLE_TRY(contextWgpu->endRenderPass(webgpu::RenderPassClosureReason::NewRenderPass)); + mDeferredClears.reset(); + return angle::Result::Continue; } @@ -564,10 +517,10 @@ angle::Result FramebufferWgpu::startRenderPassNewAttachments(ContextWgpu *contex // Flush out a render pass if there is an active one. ANGLE_TRY(contextWgpu->endRenderPass(webgpu::RenderPassClosureReason::NewRenderPass)); - setUpForRenderPass(contextWgpu, mAddedNewDepthStencilAttachment, mNewColorAttachments, - mNewDepthStencilAttachment); - mNewColorAttachments.clear(); - mAddedNewDepthStencilAttachment = false; + ASSERT(mNewRenderPassDesc.has_value()); + mCurrentRenderPassDesc = std::move(mNewRenderPassDesc.value()); + mNewRenderPassDesc.reset(); + ANGLE_TRY(contextWgpu->startRenderPass(mCurrentRenderPassDesc)); return angle::Result::Continue; } @@ -576,60 +529,58 @@ angle::Result FramebufferWgpu::startNewRenderPass(ContextWgpu *contextWgpu) { ANGLE_TRY(contextWgpu->endRenderPass(webgpu::RenderPassClosureReason::NewRenderPass)); - mCurrentColorAttachments.clear(); + webgpu::PackedRenderPassDescriptor newRenderPass; for (size_t colorIndexGL : mState.getColorAttachmentsMask()) { - wgpu::RenderPassColorAttachment colorAttachment; + webgpu::PackedRenderPassColorAttachment colorAttachment; colorAttachment.view = mRenderTargetCache.getColorDraw(mState, colorIndexGL)->getTextureView(); - colorAttachment.depthSlice = wgpu::kDepthSliceUndefined; - colorAttachment.loadOp = wgpu::LoadOp::Load; - colorAttachment.storeOp = wgpu::StoreOp::Store; + colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; + colorAttachment.storeOp = WGPUStoreOp_Store; - mCurrentColorAttachments.push_back(colorAttachment); + if (mDeferredClears.test(colorIndexGL)) + { + colorAttachment.loadOp = WGPULoadOp_Clear; + colorAttachment.clearValue = mDeferredClears[colorIndexGL].clearColor; + mDeferredClears.reset(colorIndexGL); + } + else + { + colorAttachment.loadOp = WGPULoadOp_Load; + } + + newRenderPass.colorAttachments.push_back(colorAttachment); } if (mRenderTargetCache.getDepthStencil()) { - mCurrentDepthStencilAttachment = webgpu::CreateNewDepthStencilAttachment( - contextWgpu->getState().getDepthClearValue(), - static_cast(contextWgpu->getState().getStencilClearValue()), - mRenderTargetCache.getDepthStencil()->getTextureView(), mState.hasDepth(), - mState.hasStencil()); - mCurrentRenderPassDesc.depthStencilAttachment = &mCurrentDepthStencilAttachment; - } - else - { - mCurrentRenderPassDesc.depthStencilAttachment = nullptr; + webgpu::PackedRenderPassDepthStencilAttachment dsAttachment = + webgpu::CreateNewDepthStencilAttachment( + mRenderTargetCache.getDepthStencil()->getTextureView(), mState.hasDepth(), + mState.hasStencil()); + + if (mDeferredClears.hasDepth()) + { + dsAttachment.depthLoadOp = WGPULoadOp_Clear; + dsAttachment.depthClearValue = mDeferredClears.getDepthValue(); + mDeferredClears.reset(webgpu::kUnpackedDepthIndex); + } + if (mDeferredClears.hasStencil()) + { + dsAttachment.stencilLoadOp = WGPULoadOp_Clear; + dsAttachment.stencilClearValue = mDeferredClears.getStencilValue(); + mDeferredClears.reset(webgpu::kUnpackedStencilIndex); + } + + newRenderPass.depthStencilAttachment = dsAttachment; } - mCurrentRenderPassDesc.colorAttachmentCount = mCurrentColorAttachments.size(); - mCurrentRenderPassDesc.colorAttachments = mCurrentColorAttachments.data(); + mCurrentRenderPassDesc = std::move(newRenderPass); ANGLE_TRY(contextWgpu->startRenderPass(mCurrentRenderPassDesc)); return angle::Result::Continue; } -void FramebufferWgpu::setUpForRenderPass( - ContextWgpu *contextWgpu, - bool depthOrStencil, - std::vector colorAttachments, - wgpu::RenderPassDepthStencilAttachment depthStencilAttachment) -{ - if (depthOrStencil) - { - mCurrentDepthStencilAttachment = std::move(depthStencilAttachment); - mCurrentRenderPassDesc.depthStencilAttachment = &mCurrentDepthStencilAttachment; - } - else - { - mCurrentRenderPassDesc.depthStencilAttachment = nullptr; - } - mCurrentColorAttachments = std::move(colorAttachments); - mCurrentRenderPassDesc.colorAttachmentCount = mCurrentColorAttachments.size(); - mCurrentRenderPassDesc.colorAttachments = mCurrentColorAttachments.data(); -} - -void FramebufferWgpu::mergeClearWithDeferredClears(wgpu::Color clearValue, +void FramebufferWgpu::mergeClearWithDeferredClears(const gl::ColorF &clearValue, gl::DrawBufferMask clearColorBuffers, float depthValue, uint32_t stencilValue, @@ -640,18 +591,37 @@ void FramebufferWgpu::mergeClearWithDeferredClears(wgpu::Color clearValue, for (size_t enabledDrawBuffer : clearColorBuffers) { mDeferredClears.store(static_cast(enabledDrawBuffer), - {clearValue, wgpu::kDepthSliceUndefined, 0, 0}); + {clearValue, WGPU_DEPTH_SLICE_UNDEFINED, 0, 0}); } if (clearDepth) { mDeferredClears.store(webgpu::kUnpackedDepthIndex, - {clearValue, wgpu::kDepthSliceUndefined, depthValue, 0}); + {clearValue, WGPU_DEPTH_SLICE_UNDEFINED, depthValue, 0}); } if (clearStencil) { mDeferredClears.store(webgpu::kUnpackedStencilIndex, - {clearValue, wgpu::kDepthSliceUndefined, 0, stencilValue}); + {clearValue, WGPU_DEPTH_SLICE_UNDEFINED, 0, stencilValue}); + } +} + +gl::Rectangle FramebufferWgpu::getReadArea(const gl::Context *context, + const gl::Rectangle &glArea) const +{ + RenderTargetWgpu *readRT = getReadPixelsRenderTarget(); + if (!readRT) + { + readRT = mRenderTargetCache.getDepthStencil(); } + ASSERT(readRT); + gl::Rectangle flippedArea = glArea; + if (mFlipY) + { + flippedArea.y = readRT->getImage()->getLevelSize(readRT->getLevelIndex()).height - + flippedArea.y - flippedArea.height; + } + + return flippedArea; } } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/FramebufferWgpu.h b/src/libANGLE/renderer/wgpu/FramebufferWgpu.h index 98c38a929ad..5fd6f38a59e 100644 --- a/src/libANGLE/renderer/wgpu/FramebufferWgpu.h +++ b/src/libANGLE/renderer/wgpu/FramebufferWgpu.h @@ -13,6 +13,7 @@ #include "libANGLE/renderer/FramebufferImpl.h" #include "libANGLE/renderer/RenderTargetCache.h" #include "libANGLE/renderer/wgpu/RenderTargetWgpu.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" namespace rx { @@ -80,10 +81,11 @@ class FramebufferWgpu : public FramebufferImpl RenderTargetWgpu *getReadPixelsRenderTarget() const; - void addNewColorAttachments(std::vector newColorAttachments); + void addNewColorAttachments( + std::vector newColorAttachments); void updateDepthStencilAttachment( - wgpu::RenderPassDepthStencilAttachment newRenderPassDepthStencilAttachment); + webgpu::PackedRenderPassDepthStencilAttachment newRenderPassDepthStencilAttachment); angle::Result flushOneColorAttachmentUpdate(const gl::Context *context, bool deferClears, @@ -102,23 +104,25 @@ class FramebufferWgpu : public FramebufferImpl angle::Result startNewRenderPass(ContextWgpu *contextWgpu); - void setUpForRenderPass(ContextWgpu *contextWgpu, - bool depthOrStencil, - std::vector colorAttachments, - wgpu::RenderPassDepthStencilAttachment depthStencilAttachment); + // WGPU's Framebuffer coordinates are Y down. OpenGL's are Y up. This corrects the coordinates + // of the read area based on the currently active RenderTarget. + gl::Rectangle getReadArea(const gl::Context *context, const gl::Rectangle &glArea) const; - const gl::DrawBuffersArray &getCurrentColorAttachmentFormats() const + const gl::DrawBuffersArray &getCurrentColorAttachmentFormats() const { return mCurrentColorAttachmentFormats; } - wgpu::TextureFormat getCurrentDepthStencilAttachmentFormat() const + WGPUTextureFormat getCurrentDepthStencilAttachmentFormat() const { return mCurrentDepthStencilFormat; } + void setFlipY(bool flipY) { mFlipY = flipY; } + bool flipY() const { return mFlipY; } + private: - void mergeClearWithDeferredClears(wgpu::Color clearValue, + void mergeClearWithDeferredClears(const gl::ColorF &clearValue, gl::DrawBufferMask clearColorBuffers, float depthValue, uint32_t stencilValue, @@ -127,19 +131,19 @@ class FramebufferWgpu : public FramebufferImpl bool clearStencil); RenderTargetCache mRenderTargetCache; - wgpu::RenderPassDescriptor mCurrentRenderPassDesc; - wgpu::RenderPassDepthStencilAttachment mCurrentDepthStencilAttachment; - std::vector mCurrentColorAttachments; - gl::DrawBuffersArray mCurrentColorAttachmentFormats; - wgpu::TextureFormat mCurrentDepthStencilFormat = wgpu::TextureFormat::Undefined; - - // Secondary vector to track new clears that are added and should be run in a new render pass - // during flushColorAttachmentUpdates. - std::vector mNewColorAttachments; - wgpu::RenderPassDepthStencilAttachment mNewDepthStencilAttachment; - bool mAddedNewDepthStencilAttachment = false; + webgpu::PackedRenderPassDescriptor mCurrentRenderPassDesc; + + gl::DrawBuffersArray mCurrentColorAttachmentFormats; + WGPUTextureFormat mCurrentDepthStencilFormat = WGPUTextureFormat_Undefined; + + // Secondary descriptor to track new clears that are added and should be run in a new render + // pass during flushColorAttachmentUpdates. + std::optional mNewRenderPassDesc; webgpu::ClearValuesArray mDeferredClears; + + // Whether this framebuffer should be rendered to with a negated y coordinate. + bool mFlipY = false; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ImageWgpu.cpp b/src/libANGLE/renderer/wgpu/ImageWgpu.cpp index 4683aba8070..a40d89f7db3 100644 --- a/src/libANGLE/renderer/wgpu/ImageWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ImageWgpu.cpp @@ -8,23 +8,203 @@ // #include "libANGLE/renderer/wgpu/ImageWgpu.h" +#include "libANGLE/Display.h" +#include "libANGLE/renderer/wgpu/DisplayWgpu.h" +#include "libANGLE/renderer/wgpu/RenderbufferWgpu.h" +#include "libANGLE/renderer/wgpu/TextureWgpu.h" #include "common/debug.h" namespace rx { +WebGPUTextureImageSiblingWgpu::WebGPUTextureImageSiblingWgpu(EGLClientBuffer buffer, + const egl::AttributeMap &attribs) + : mBuffer(buffer), mAttribs(attribs) +{} +WebGPUTextureImageSiblingWgpu::~WebGPUTextureImageSiblingWgpu() {} -ImageWgpu::ImageWgpu(const egl::ImageState &state) : ImageImpl(state) {} +egl::Error WebGPUTextureImageSiblingWgpu::initialize(const egl::Display *display) +{ + return angle::ResultToEGL(initializeImpl(display)); +} + +angle::Result WebGPUTextureImageSiblingWgpu::initializeImpl(const egl::Display *display) +{ + DisplayWgpu *displayWgpu = webgpu::GetImpl(display); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + + webgpu::TextureHandle externalTexture = + webgpu::TextureHandle::Acquire(wgpu, reinterpret_cast(mBuffer)); + ASSERT(externalTexture != nullptr); + + // Explicitly add-ref to hold on to the external reference + wgpu->textureAddRef(externalTexture.get()); + + const webgpu::Format *webgpuFormat = displayWgpu->getFormatForImportedTexture( + mAttribs, wgpu->textureGetFormat(externalTexture.get())); + ASSERT(webgpuFormat != nullptr); + ANGLE_TRY(mImage.initExternal(wgpu, webgpuFormat->getIntendedFormatID(), + webgpuFormat->getActualImageFormatID(), externalTexture)); + return angle::Result::Continue; +} + +void WebGPUTextureImageSiblingWgpu::onDestroy(const egl::Display *display) +{ + mImage.resetImage(); +} + +gl::Format WebGPUTextureImageSiblingWgpu::getFormat() const +{ + const angle::Format &angleFormat = angle::Format::Get(mImage.getIntendedFormatID()); + return gl::Format(angleFormat.glInternalFormat); +} + +bool WebGPUTextureImageSiblingWgpu::isRenderable(const gl::Context *context) const +{ + constexpr WGPUTextureUsage kRenderableRequiredUsages = + WGPUTextureUsage_CopySrc | WGPUTextureUsage_RenderAttachment; + return (mImage.getUsage() & kRenderableRequiredUsages) == kRenderableRequiredUsages; +} + +bool WebGPUTextureImageSiblingWgpu::isTexturable(const gl::Context *context) const +{ + constexpr WGPUTextureUsage kTexturableRequiredUsages = + WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding; + return (mImage.getUsage() & kTexturableRequiredUsages) == kTexturableRequiredUsages; +} + +bool WebGPUTextureImageSiblingWgpu::isYUV() const +{ + const angle::Format &actualFormat = angle::Format::Get(mImage.getActualFormatID()); + return actualFormat.isYUV; +} + +bool WebGPUTextureImageSiblingWgpu::hasFrontBufferUsage() const +{ + return false; +} + +bool WebGPUTextureImageSiblingWgpu::isCubeMap() const +{ + return false; +} + +bool WebGPUTextureImageSiblingWgpu::hasProtectedContent() const +{ + return false; +} + +gl::Extents WebGPUTextureImageSiblingWgpu::getSize() const +{ + return wgpu_gl::GetExtents(mImage.getSize()); +} + +size_t WebGPUTextureImageSiblingWgpu::getSamples() const +{ + // GL treats a sample count of 1 as multisampled. When the WebGPU texture has a sample count of + // 1, force it to 0. + uint32_t samples = mImage.getSamples(); + return samples > 1 ? samples : 0; +} + +uint32_t WebGPUTextureImageSiblingWgpu::getLevelCount() const +{ + return mImage.getLevelCount(); +} + +webgpu::ImageHelper *WebGPUTextureImageSiblingWgpu::getImage() const +{ + return const_cast(&mImage); +} + +ImageWgpu::ImageWgpu(const egl::ImageState &state, const gl::Context *context) + : ImageImpl(state), mContext(context) +{} ImageWgpu::~ImageWgpu() {} egl::Error ImageWgpu::initialize(const egl::Display *display) { + if (egl::IsTextureTarget(mState.target)) + { + if (mState.imageIndex.getLevelIndex() != 0) + { + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_ACCESS, + "Creation of EGLImages from non-zero mip levels is unimplemented."); + } + if (mState.imageIndex.getType() != gl::TextureType::_2D) + { + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_ACCESS, + "Creation of EGLImages from non-2D textures is unimplemented."); + } + + TextureWgpu *textureWgpu = webgpu::GetImpl(GetAs(mState.source)); + + ASSERT(mContext != nullptr); + angle::Result initResult = textureWgpu->ensureImageInitialized(mContext); + if (initResult != angle::Result::Continue) + { + return egl::Error(EGL_BAD_ACCESS, "Failed to initialize source texture."); + } + + mImage = textureWgpu->getImage(); + } + else if (egl::IsRenderbufferTarget(mState.target)) + { + RenderbufferWgpu *renderbufferWgpu = + webgpu::GetImpl(GetAs(mState.source)); + mImage = renderbufferWgpu->getImage(); + + ASSERT(mContext != nullptr); + } + else if (egl::IsExternalImageTarget(mState.target)) + { + const ExternalImageSiblingWgpu *externalImageSibling = + webgpu::GetImpl(GetAs(mState.source)); + mImage = externalImageSibling->getImage(); + + ASSERT(mContext == nullptr); + } + else + { + UNREACHABLE(); + return egl::Error(EGL_BAD_ACCESS); + } + + ASSERT(mImage->isInitialized()); + mOwnsImage = false; + return egl::NoError(); } angle::Result ImageWgpu::orphan(const gl::Context *context, egl::ImageSibling *sibling) { + if (sibling == mState.source) + { + if (egl::IsTextureTarget(mState.target)) + { + TextureWgpu *textureWgpu = webgpu::GetImpl(GetAs(mState.source)); + ASSERT(mImage == textureWgpu->getImage()); + textureWgpu->releaseOwnershipOfImage(context); + } + else if (egl::IsRenderbufferTarget(mState.target)) + { + RenderbufferWgpu *renderbufferWgpu = + webgpu::GetImpl(GetAs(mState.source)); + ASSERT(mImage == renderbufferWgpu->getImage()); + renderbufferWgpu->releaseOwnershipOfImage(context); + } + else + { + UNREACHABLE(); + return angle::Result::Stop; + } + + mOwnsImage = true; + } + return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/wgpu/ImageWgpu.h b/src/libANGLE/renderer/wgpu/ImageWgpu.h index ff7581d1044..71a815ed208 100644 --- a/src/libANGLE/renderer/wgpu/ImageWgpu.h +++ b/src/libANGLE/renderer/wgpu/ImageWgpu.h @@ -10,19 +10,68 @@ #ifndef LIBANGLE_RENDERER_WGPU_IMAGEWGPU_H_ #define LIBANGLE_RENDERER_WGPU_IMAGEWGPU_H_ +#include "libANGLE/AttributeMap.h" #include "libANGLE/renderer/ImageImpl.h" +#include "libANGLE/renderer/wgpu/wgpu_helpers.h" namespace rx { +class ExternalImageSiblingWgpu : public ExternalImageSiblingImpl +{ + public: + ExternalImageSiblingWgpu() {} + ~ExternalImageSiblingWgpu() override {} + + virtual webgpu::ImageHelper *getImage() const = 0; +}; + +class WebGPUTextureImageSiblingWgpu : public ExternalImageSiblingWgpu +{ + public: + WebGPUTextureImageSiblingWgpu(EGLClientBuffer buffer, const egl::AttributeMap &attribs); + ~WebGPUTextureImageSiblingWgpu() override; + + egl::Error initialize(const egl::Display *display) override; + void onDestroy(const egl::Display *display) override; + + // ExternalImageSiblingImpl interface + gl::Format getFormat() const override; + bool isRenderable(const gl::Context *context) const override; + bool isTexturable(const gl::Context *context) const override; + bool isYUV() const override; + bool hasFrontBufferUsage() const override; + bool isCubeMap() const override; + bool hasProtectedContent() const override; + gl::Extents getSize() const override; + size_t getSamples() const override; + uint32_t getLevelCount() const override; + + webgpu::ImageHelper *getImage() const override; + + private: + angle::Result initializeImpl(const egl::Display *display); + + EGLClientBuffer mBuffer = nullptr; + egl::AttributeMap mAttribs; + webgpu::ImageHelper mImage; +}; class ImageWgpu : public ImageImpl { public: - ImageWgpu(const egl::ImageState &state); + ImageWgpu(const egl::ImageState &state, const gl::Context *context); ~ImageWgpu() override; egl::Error initialize(const egl::Display *display) override; angle::Result orphan(const gl::Context *context, egl::ImageSibling *sibling) override; + + webgpu::ImageHelper *getImage() const { return mImage; } + + private: + bool mOwnsImage = false; + webgpu::ImageHelper *mImage = nullptr; + + const gl::Context *mContext = nullptr; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/OWNERS b/src/libANGLE/renderer/wgpu/OWNERS new file mode 100644 index 00000000000..2eeefba59a6 --- /dev/null +++ b/src/libANGLE/renderer/wgpu/OWNERS @@ -0,0 +1,2 @@ +liza@chromium.org +mpdenton@chromium.org diff --git a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp index f6e64e2e988..3ee409c3cb5 100644 --- a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // ProgramExecutableWgpu.cpp: Implementation of ProgramExecutableWgpu. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/renderer/wgpu/ProgramExecutableWgpu.h" @@ -12,13 +17,19 @@ #include "angle_gl.h" #include "anglebase/numerics/safe_conversions.h" #include "common/PackedGLEnums_autogen.h" +#include "common/log_utils.h" +#include "common/mathutil.h" +#include "common/utilities.h" #include "compiler/translator/wgsl/OutputUniformBlocks.h" #include "libANGLE/Error.h" #include "libANGLE/Program.h" +#include "libANGLE/ProgramExecutable.h" #include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/wgpu/ContextWgpu.h" +#include "libANGLE/renderer/wgpu/TextureWgpu.h" #include "libANGLE/renderer/wgpu/wgpu_helpers.h" #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" namespace rx { @@ -36,11 +47,14 @@ ProgramExecutableWgpu::~ProgramExecutableWgpu() = default; void ProgramExecutableWgpu::destroy(const gl::Context *context) {} -angle::Result ProgramExecutableWgpu::updateUniformsAndGetBindGroup(ContextWgpu *contextWgpu, - wgpu::BindGroup *outBindGroup) +angle::Result ProgramExecutableWgpu::updateUniformsAndGetBindGroup( + ContextWgpu *contextWgpu, + webgpu::BindGroupHandle *outBindGroup) { if (mDefaultUniformBlocksDirty.any()) { + const DawnProcTable *wgpu = webgpu::GetProcs(contextWgpu); + // TODO(anglebug.com/376553328): this creates an entire new buffer every time a single // uniform changes, and the old ones are just garbage collected. This should be optimized. webgpu::BufferHelper defaultUniformBuffer; @@ -56,9 +70,9 @@ angle::Result ProgramExecutableWgpu::updateUniformsAndGetBindGroup(ContextWgpu * return angle::Result::Stop; } - ANGLE_TRY(defaultUniformBuffer.initBuffer( - contextWgpu->getDevice(), requiredSpace, - wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst, webgpu::MapAtCreation::Yes)); + ANGLE_TRY(defaultUniformBuffer.initBuffer(wgpu, contextWgpu->getDevice(), requiredSpace, + WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, + webgpu::MapAtCreation::Yes)); ASSERT(defaultUniformBuffer.valid()); @@ -74,13 +88,13 @@ angle::Result ProgramExecutableWgpu::updateUniformsAndGetBindGroup(ContextWgpu * ANGLE_TRY(defaultUniformBuffer.unmap()); // Create the BindGroupEntries - std::vector bindings; + std::vector bindings; auto addBindingToGroupIfNecessary = [&](uint32_t bindingIndex, gl::ShaderType shaderType) { if (mDefaultUniformBlocks[shaderType]->uniformData.size() != 0) { - wgpu::BindGroupEntry bindGroupEntry; + WGPUBindGroupEntry bindGroupEntry = WGPU_BIND_GROUP_ENTRY_INIT; bindGroupEntry.binding = bindingIndex; - bindGroupEntry.buffer = defaultUniformBuffer.getBuffer(); + bindGroupEntry.buffer = defaultUniformBuffer.getBuffer().get(); bindGroupEntry.offset = offsets[shaderType]; bindGroupEntry.size = mDefaultUniformBlocks[shaderType]->uniformData.size(); bindings.push_back(bindGroupEntry); @@ -93,13 +107,13 @@ angle::Result ProgramExecutableWgpu::updateUniformsAndGetBindGroup(ContextWgpu * addBindingToGroupIfNecessary(sh::kDefaultFragmentUniformBlockBinding, gl::ShaderType::Fragment); - // A bind group contains one or multiple bindings - wgpu::BindGroupDescriptor bindGroupDesc{}; - bindGroupDesc.layout = mDefaultBindGroupLayout; + WGPUBindGroupDescriptor bindGroupDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT; + bindGroupDesc.layout = mDefaultBindGroupLayout.get(); // There must be as many bindings as declared in the layout! bindGroupDesc.entryCount = bindings.size(); bindGroupDesc.entries = bindings.data(); - mDefaultBindGroup = contextWgpu->getDevice().CreateBindGroup(&bindGroupDesc); + mDefaultBindGroup = webgpu::BindGroupHandle::Acquire( + wgpu, wgpu->deviceCreateBindGroup(contextWgpu->getDevice().get(), &bindGroupDesc)); } ASSERT(mDefaultBindGroup); @@ -108,6 +122,111 @@ angle::Result ProgramExecutableWgpu::updateUniformsAndGetBindGroup(ContextWgpu * return angle::Result::Continue; } +angle::Result ProgramExecutableWgpu::getSamplerAndTextureBindGroup( + ContextWgpu *contextWgpu, + webgpu::BindGroupHandle *outBindGroup) +{ + if (mSamplerBindingsDirty) + { + const DawnProcTable *wgpu = webgpu::GetProcs(contextWgpu); + + const gl::ActiveTexturesCache &completeTextures = + contextWgpu->getState().getActiveTexturesCache(); + + std::vector bindings; + bindings.reserve(mExecutable->getSamplerBindings().size() * 2); + + // Hold refs to samplers and texture views created in this function until the bind group is + // created + std::vector samplers; + samplers.reserve(mExecutable->getSamplerBindings().size()); + + std::vector textureViews; + textureViews.reserve(mExecutable->getSamplerBindings().size()); + + for (uint32_t textureIndex = 0; textureIndex < mExecutable->getSamplerBindings().size(); + ++textureIndex) + { + const gl::SamplerBinding &samplerBinding = + mExecutable->getSamplerBindings()[textureIndex]; + + if (samplerBinding.textureUnitsCount != 1) + { + // TODO(anglebug.com/389145696): arrays of samplers not yet supported + UNIMPLEMENTED(); + return angle::Result::Stop; + } + for (uint32_t arrayElement = 0; arrayElement < samplerBinding.textureUnitsCount; + ++arrayElement) + { + GLuint textureUnit = samplerBinding.getTextureUnit( + mExecutable->getSamplerBoundTextureUnits(), arrayElement); + gl::Texture *texture = completeTextures[textureUnit]; + gl::Sampler *sampler = contextWgpu->getState().getSampler(textureUnit); + uint32_t samplerSlot = (textureIndex + arrayElement) * 2; + uint32_t textureSlot = samplerSlot + 1; + if (!texture) + { + // TODO(anglebug.com/389145696): no support for incomplete textures. + UNIMPLEMENTED(); + return angle::Result::Stop; + } + const gl::SamplerState *samplerState = + sampler ? &sampler->getSamplerState() : &texture->getSamplerState(); + if (samplerBinding.format == gl::SamplerFormat::Shadow) + { + // TODO(anglebug.com/389145696): no support for shadow samplers yet. + UNIMPLEMENTED(); + return angle::Result::Stop; + } + TextureWgpu *textureWgpu = webgpu::GetImpl(texture); + + // TODO(anglebug.com/389145696): potentially cache sampler. + WGPUSamplerDescriptor sampleDesc = gl_wgpu::GetWgpuSamplerDesc(samplerState); + webgpu::SamplerHandle wgpuSampler = webgpu::SamplerHandle::Acquire( + wgpu, wgpu->deviceCreateSampler(contextWgpu->getDevice().get(), &sampleDesc)); + samplers.push_back(wgpuSampler); + + WGPUBindGroupEntry samplerBindGroupEntry = WGPU_BIND_GROUP_ENTRY_INIT; + samplerBindGroupEntry.binding = samplerSlot; + samplerBindGroupEntry.sampler = wgpuSampler.get(); + + bindings.push_back(samplerBindGroupEntry); + + WGPUBindGroupEntry textureBindGroupEntry = WGPU_BIND_GROUP_ENTRY_INIT; + textureBindGroupEntry.binding = textureSlot; + + webgpu::TextureViewHandle textureView; + ANGLE_TRY(textureWgpu->getImage()->createFullTextureView( + textureView, + /*desiredViewDimension=*/gl_wgpu::GetWgpuTextureViewDimension( + samplerBinding.textureType))); + textureViews.push_back(textureView); + textureBindGroupEntry.textureView = textureView.get(); + bindings.push_back(textureBindGroupEntry); + + } // for array elements + } // for sampler bindings + + // A bind group contains one or multiple bindings + WGPUBindGroupDescriptor bindGroupDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT; + ASSERT(mSamplersAndTexturesBindGroupLayout); + bindGroupDesc.layout = mSamplersAndTexturesBindGroupLayout.get(); + // There must be as many bindings as declared in the layout! + bindGroupDesc.entryCount = bindings.size(); + bindGroupDesc.entries = bindings.data(); + mSamplersAndTexturesBindGroup = webgpu::BindGroupHandle::Acquire( + wgpu, wgpu->deviceCreateBindGroup(contextWgpu->getDevice().get(), &bindGroupDesc)); + + mSamplerBindingsDirty = false; + } + + ASSERT(mSamplersAndTexturesBindGroup); + *outBindGroup = mSamplersAndTexturesBindGroup; + + return angle::Result::Continue; +} + angle::CheckedNumeric ProgramExecutableWgpu::getDefaultUniformAlignedSize( ContextWgpu *context, gl::ShaderType shaderType) const @@ -192,7 +311,7 @@ void ProgramExecutableWgpu::setUniform1iv(GLint location, GLsizei count, const G const gl::LinkedUniform &linkedUniform = mExecutable->getUniforms()[locationInfo.index]; if (linkedUniform.isSampler()) { - // TODO(anglebug.com/42267100): handle samplers. + mSamplerBindingsDirty = true; return; } @@ -351,9 +470,9 @@ TranslatedWGPUShaderModule &ProgramExecutableWgpu::getShaderModule(gl::ShaderTyp angle::Result ProgramExecutableWgpu::getRenderPipeline(ContextWgpu *context, const webgpu::RenderPipelineDesc &desc, - wgpu::RenderPipeline *pipelineOut) + webgpu::RenderPipelineHandle *pipelineOut) { - gl::ShaderMap shaders; + gl::ShaderMap shaders; for (gl::ShaderType shaderType : gl::AllShaderTypes()) { shaders[shaderType] = mShaderModules[shaderType].module; @@ -370,44 +489,123 @@ void ProgramExecutableWgpu::genBindingLayoutIfNecessary(ContextWgpu *context) { return; } + + const DawnProcTable *wgpu = webgpu::GetProcs(context); + // TODO(anglebug.com/42267100): for now, only create a wgpu::PipelineLayout with the default - // uniform block. Will need to be extended for driver uniforms, UBOs, and textures/samplers. - // Also, possibly provide this layout as a compilation hint to createShaderModule(). + // uniform block, driver uniform block, and textures/samplers. Will need to be extended for + // UBOs. Also, possibly provide this layout as a compilation hint to createShaderModule(). - std::vector bindGroupLayoutEntries; - auto addBindGroupLayoutEntryIfNecessary = [&](uint32_t bindingIndex, gl::ShaderType shaderType, - wgpu::ShaderStage wgpuVisibility) { + std::vector defaultBindGroupLayoutEntries; + auto addDefaultBindGroupLayoutEntryIfNecessary = [&](uint32_t bindingIndex, + gl::ShaderType shaderType, + WGPUShaderStage wgpuVisibility) { if (mDefaultUniformBlocks[shaderType]->uniformData.size() != 0) { - wgpu::BindGroupLayoutEntry bindGroupLayoutEntry; - bindGroupLayoutEntry.visibility = wgpuVisibility; - bindGroupLayoutEntry.binding = bindingIndex; - bindGroupLayoutEntry.buffer.type = wgpu::BufferBindingType::Uniform; + WGPUBindGroupLayoutEntry bindGroupLayoutEntry = WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT; + bindGroupLayoutEntry.visibility = wgpuVisibility; + bindGroupLayoutEntry.binding = bindingIndex; + bindGroupLayoutEntry.buffer.type = WGPUBufferBindingType_Uniform; // By setting a `minBindingSize`, some validation is pushed from every draw call to // pipeline creation time. bindGroupLayoutEntry.buffer.minBindingSize = mDefaultUniformBlocks[shaderType]->uniformData.size(); - bindGroupLayoutEntries.push_back(bindGroupLayoutEntry); + bindGroupLayoutEntry.texture.sampleType = WGPUTextureSampleType_BindingNotUsed; + bindGroupLayoutEntry.sampler.type = WGPUSamplerBindingType_BindingNotUsed; + bindGroupLayoutEntry.storageTexture.access = WGPUStorageTextureAccess_BindingNotUsed; + defaultBindGroupLayoutEntries.push_back(bindGroupLayoutEntry); } }; // Default uniform blocks for each of the vertex shader and the fragment shader. - addBindGroupLayoutEntryIfNecessary(sh::kDefaultVertexUniformBlockBinding, - gl::ShaderType::Vertex, wgpu::ShaderStage::Vertex); - addBindGroupLayoutEntryIfNecessary(sh::kDefaultFragmentUniformBlockBinding, - gl::ShaderType::Fragment, wgpu::ShaderStage::Fragment); + addDefaultBindGroupLayoutEntryIfNecessary(sh::kDefaultVertexUniformBlockBinding, + gl::ShaderType::Vertex, WGPUShaderStage_Vertex); + addDefaultBindGroupLayoutEntryIfNecessary(sh::kDefaultFragmentUniformBlockBinding, + gl::ShaderType::Fragment, WGPUShaderStage_Fragment); + + // Create a bind group layout with these entries. + WGPUBindGroupLayoutDescriptor defaultBindGroupLayoutDesc = + WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT; + defaultBindGroupLayoutDesc.entryCount = defaultBindGroupLayoutEntries.size(); + defaultBindGroupLayoutDesc.entries = defaultBindGroupLayoutEntries.data(); + mDefaultBindGroupLayout = webgpu::BindGroupLayoutHandle::Acquire( + wgpu, + wgpu->deviceCreateBindGroupLayout(context->getDevice().get(), &defaultBindGroupLayoutDesc)); + + // Add the textures/samplers to the second bind group. + std::vector samplersAndTexturesBindGroupLayoutEntries; + + // For each sampler binding, the translator should have generated 2 WGSL bindings, a sampler and + // a texture, with incrementing binding numbers starting from 0. + for (size_t i = 0; i < mExecutable->getSamplerBindings().size(); i++) + { + const gl::SamplerBinding &samplerBinding = mExecutable->getSamplerBindings()[i]; + + { + WGPUBindGroupLayoutEntry samplerBindGroupLayoutEntry = + WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT; + samplerBindGroupLayoutEntry.visibility = + WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; + samplerBindGroupLayoutEntry.binding = angle::base::checked_cast(i * 2); + samplerBindGroupLayoutEntry.buffer.type = WGPUBufferBindingType_BindingNotUsed; + samplerBindGroupLayoutEntry.texture.sampleType = WGPUTextureSampleType_BindingNotUsed; + samplerBindGroupLayoutEntry.sampler.type = + samplerBinding.format == gl::SamplerFormat::Shadow + ? WGPUSamplerBindingType_Comparison + : WGPUSamplerBindingType_Filtering; + samplerBindGroupLayoutEntry.storageTexture.access = + WGPUStorageTextureAccess_BindingNotUsed; + + samplersAndTexturesBindGroupLayoutEntries.push_back(samplerBindGroupLayoutEntry); + } + + { + WGPUBindGroupLayoutEntry textureBindGroupLayoutEntry = + WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT; + textureBindGroupLayoutEntry.visibility = + WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; + textureBindGroupLayoutEntry.binding = angle::base::checked_cast(i * 2 + 1); + textureBindGroupLayoutEntry.buffer.type = WGPUBufferBindingType_BindingNotUsed; + textureBindGroupLayoutEntry.texture.sampleType = + gl_wgpu::GetTextureSampleType(samplerBinding.format); + textureBindGroupLayoutEntry.texture.viewDimension = + gl_wgpu::GetWgpuTextureViewDimension(samplerBinding.textureType); + textureBindGroupLayoutEntry.sampler.type = WGPUSamplerBindingType_BindingNotUsed; + textureBindGroupLayoutEntry.storageTexture.access = + WGPUStorageTextureAccess_BindingNotUsed; + samplersAndTexturesBindGroupLayoutEntries.push_back(textureBindGroupLayoutEntry); + } + } // Create a bind group layout with these entries. - wgpu::BindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.entryCount = bindGroupLayoutEntries.size(); - bindGroupLayoutDesc.entries = bindGroupLayoutEntries.data(); - mDefaultBindGroupLayout = context->getDevice().CreateBindGroupLayout(&bindGroupLayoutDesc); - - // Create the pipeline layout. This is a list where each element N corresponds to the @group(N) - // in the compiled shaders. - wgpu::PipelineLayoutDescriptor layoutDesc{}; - layoutDesc.bindGroupLayoutCount = 1; - layoutDesc.bindGroupLayouts = &mDefaultBindGroupLayout; - mPipelineLayout = context->getDevice().CreatePipelineLayout(&layoutDesc); + WGPUBindGroupLayoutDescriptor texturesAndSamplersBindGroupLayoutDesc = + WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT; + texturesAndSamplersBindGroupLayoutDesc.entryCount = + samplersAndTexturesBindGroupLayoutEntries.size(); + texturesAndSamplersBindGroupLayoutDesc.entries = + samplersAndTexturesBindGroupLayoutEntries.data(); + mSamplersAndTexturesBindGroupLayout = webgpu::BindGroupLayoutHandle::Acquire( + wgpu, wgpu->deviceCreateBindGroupLayout(context->getDevice().get(), + &texturesAndSamplersBindGroupLayoutDesc)); + + // Driver uniforms bind groups are handled by ContextWgpu. + + // TODO(anglebug.com/376553328): now add UBO bindings. + + // Create the pipeline layout. This is a list where each element N corresponds to the + // @group(N) in the compiled shaders. + std::array groupLayouts = {}; + + groupLayouts[sh::kDefaultUniformBlockBindGroup] = mDefaultBindGroupLayout.get(); + groupLayouts[sh::kTextureAndSamplerBindGroup] = mSamplersAndTexturesBindGroupLayout.get(); + groupLayouts[sh::kDriverUniformBindGroup] = context->getDriverUniformBindGroupLayout().get(); + static_assert(sh::kDriverUniformBindGroup == sh::kMaxBindGroup, + "More bind groups added without changing the layout"); + + WGPUPipelineLayoutDescriptor layoutDesc = WGPU_PIPELINE_LAYOUT_DESCRIPTOR_INIT; + layoutDesc.bindGroupLayoutCount = groupLayouts.size(); + layoutDesc.bindGroupLayouts = groupLayouts.data(); + mPipelineLayout = webgpu::PipelineLayoutHandle::Acquire( + wgpu, wgpu->deviceCreatePipelineLayout(context->getDevice().get(), &layoutDesc)); } } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h index a2ff0d2de5c..e9b139febdb 100644 --- a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h +++ b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h @@ -14,13 +14,13 @@ #include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h" -#include +#include namespace rx { struct TranslatedWGPUShaderModule { - wgpu::ShaderModule module; + webgpu::ShaderModuleHandle module; }; class ProgramExecutableWgpu : public ProgramExecutableImpl @@ -32,7 +32,9 @@ class ProgramExecutableWgpu : public ProgramExecutableImpl void destroy(const gl::Context *context) override; angle::Result updateUniformsAndGetBindGroup(ContextWgpu *context, - wgpu::BindGroup *outBindGroup); + webgpu::BindGroupHandle *outBindGroup); + angle::Result getSamplerAndTextureBindGroup(ContextWgpu *contextWgpu, + webgpu::BindGroupHandle *outBindGroup); angle::Result resizeUniformBlockMemory(const gl::ShaderMap &requiredBufferSize); @@ -43,6 +45,8 @@ class ProgramExecutableWgpu : public ProgramExecutableImpl void markDefaultUniformsDirty(); bool checkDirtyUniforms() { return mDefaultUniformBlocksDirty.any(); } + void markSamplerBindingsDirty() { mSamplerBindingsDirty = true; } + bool hasDirtySamplerBindings() { return mSamplerBindingsDirty; } void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; @@ -101,7 +105,7 @@ class ProgramExecutableWgpu : public ProgramExecutableImpl angle::Result getRenderPipeline(ContextWgpu *context, const webgpu::RenderPipelineDesc &desc, - wgpu::RenderPipeline *pipelineOut); + webgpu::RenderPipelineHandle *pipelineOut); private: angle::CheckedNumeric getDefaultUniformAlignedSize(ContextWgpu *context, @@ -118,16 +122,25 @@ class ProgramExecutableWgpu : public ProgramExecutableImpl webgpu::PipelineCache mPipelineCache; // Holds the binding layout of resources (buffers, textures, samplers) required by the linked // shaders. - wgpu::PipelineLayout mPipelineLayout; + webgpu::PipelineLayoutHandle mPipelineLayout; // Holds the binding group layout for the default bind group. - wgpu::BindGroupLayout mDefaultBindGroupLayout; + webgpu::BindGroupLayoutHandle mDefaultBindGroupLayout; // Holds the most recent BindGroup. Note there may be others in the command buffer. - wgpu::BindGroup mDefaultBindGroup; + webgpu::BindGroupHandle mDefaultBindGroup; // Holds layout info for basic GL uniforms, which needs to be laid out in a buffer for WGSL // similarly to a UBO. DefaultUniformBlockMap mDefaultUniformBlocks; gl::ShaderBitSet mDefaultUniformBlocksDirty; + + // Tracks when a sampler binding has been changed with glUniform1i(). Starts true to ensure the + // bind group is created the first time around. + bool mSamplerBindingsDirty = true; + // Holds the binding group layout for the samplers and textures. + webgpu::BindGroupLayoutHandle mSamplersAndTexturesBindGroupLayout; + // Holds the most recent samplers and textures BindGroup. Note there may be others in the + // command buffer. + webgpu::BindGroupHandle mSamplersAndTexturesBindGroup; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp b/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp index 107d1750981..e0e27e503ea 100644 --- a/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp @@ -7,6 +7,10 @@ // Implements the class methods for ProgramWgpu. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/ProgramWgpu.h" #include "GLES2/gl2.h" @@ -20,8 +24,7 @@ #include "libANGLE/renderer/wgpu/wgpu_utils.h" #include "libANGLE/renderer/wgpu/wgpu_wgsl_util.h" #include "libANGLE/trace.h" - -#include +#include "platform/autogen/FeaturesWgpu_autogen.h" namespace rx { @@ -34,6 +37,7 @@ class WgpuDefaultBlockEncoder : public sh::Std140BlockEncoder { public: void advanceOffset(GLenum type, + const size_t bytesPerComponent, const std::vector &arraySizes, bool isRowMajorMatrix, int arrayStride, @@ -44,39 +48,64 @@ class WgpuDefaultBlockEncoder : public sh::Std140BlockEncoder return; } - sh::Std140BlockEncoder::advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, - matrixStride); + sh::Std140BlockEncoder::advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, + arrayStride, matrixStride); } }; -void InitDefaultUniformBlock(const std::vector &uniforms, - sh::BlockLayoutMap *blockLayoutMapOut, - size_t *blockSizeOut) +angle::Result InitDefaultUniformBlock(const std::vector &uniforms, + sh::BlockLayoutMap *blockLayoutMapOut, + size_t *blockSizeOut) { if (uniforms.empty()) { *blockSizeOut = 0; - return; + return angle::Result::Continue; } WgpuDefaultBlockEncoder blockEncoder; sh::GetActiveUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut); - *blockSizeOut = blockEncoder.getCurrentOffset(); - return; + // The default uniforms are packed into a struct, and so the size of the struct must be aligned + // to kUniformStructAlignment; + angle::CheckedNumeric blockSize = + CheckedRoundUp(blockEncoder.getCurrentOffset(), webgpu::kUniformStructAlignment); + if (!blockSize.IsValid()) + { + ERR() << "Packing the default uniforms into a struct results in a struct that is too " + "large. Unaligned size = " + << blockEncoder.getCurrentOffset() + << ", alignment = " << webgpu::kUniformStructAlignment; + return angle::Result::Stop; + } + + *blockSizeOut = blockSize.ValueOrDie(); + return angle::Result::Continue; +} + +std::string FormatWGPUCompilationMessage(const WGPUCompilationMessage &message) +{ + std::ostringstream oss; + oss << message.lineNum << ":" << message.linePos << ": " + << std::string(message.message.data, message.message.length); + return oss.str(); } class CreateWGPUShaderModuleTask : public LinkSubTask { public: - CreateWGPUShaderModuleTask(wgpu::Instance instance, - wgpu::Device device, + CreateWGPUShaderModuleTask(const DawnProcTable *wgpu, + webgpu::InstanceHandle instance, + webgpu::DeviceHandle device, + const angle::FeaturesWgpu &features, const gl::SharedCompiledShaderState &compiledShaderState, const gl::ProgramExecutable &executable, gl::ProgramMergedVaryings mergedVaryings, TranslatedWGPUShaderModule &resultShaderModule) - : mInstance(instance), + : mProcTable(wgpu), + mInstance(instance), mDevice(device), + mFeatures(features), mCompiledShaderState(compiledShaderState), mExecutable(executable), mMergedVaryings(std::move(mergedVaryings)), @@ -101,15 +130,15 @@ class CreateWGPUShaderModuleTask : public LinkSubTask std::string finalShaderSource; if (shaderType == gl::ShaderType::Vertex) { - finalShaderSource = webgpu::WgslAssignLocations(mCompiledShaderState->translatedSource, - mExecutable.getProgramInputs(), - mMergedVaryings, shaderType); + finalShaderSource = webgpu::WgslAssignLocationsAndSamplerBindings( + mExecutable, *mCompiledShaderState->translatedSource, + mExecutable.getProgramInputs(), mMergedVaryings, shaderType); } else if (shaderType == gl::ShaderType::Fragment) { - finalShaderSource = webgpu::WgslAssignLocations(mCompiledShaderState->translatedSource, - mExecutable.getOutputVariables(), - mMergedVaryings, shaderType); + finalShaderSource = webgpu::WgslAssignLocationsAndSamplerBindings( + mExecutable, *mCompiledShaderState->translatedSource, + mExecutable.getOutputVariables(), mMergedVaryings, shaderType); } else { @@ -120,63 +149,110 @@ class CreateWGPUShaderModuleTask : public LinkSubTask std::cout << finalShaderSource; } - wgpu::ShaderModuleWGSLDescriptor shaderModuleWGSLDescriptor; - shaderModuleWGSLDescriptor.code = finalShaderSource.c_str(); + WGPUShaderSourceWGSL shaderModuleWGSLDescriptor = WGPU_SHADER_SOURCE_WGSL_INIT; + shaderModuleWGSLDescriptor.code = {finalShaderSource.c_str(), finalShaderSource.length()}; - wgpu::ShaderModuleDescriptor shaderModuleDescriptor; - shaderModuleDescriptor.nextInChain = &shaderModuleWGSLDescriptor; + WGPUShaderModuleDescriptor shaderModuleDescriptor = WGPU_SHADER_MODULE_DESCRIPTOR_INIT; + shaderModuleDescriptor.nextInChain = &shaderModuleWGSLDescriptor.chain; - mShaderModule.module = mDevice.CreateShaderModule(&shaderModuleDescriptor); + mShaderModule.module = webgpu::ShaderModuleHandle::Acquire( + mProcTable, + mProcTable->deviceCreateShaderModule(mDevice.get(), &shaderModuleDescriptor)); - wgpu::CompilationInfoCallbackInfo callbackInfo; - callbackInfo.mode = wgpu::CallbackMode::WaitAnyOnly; - callbackInfo.callback = [](WGPUCompilationInfoRequestStatus status, - struct WGPUCompilationInfo const *compilationInfo, - void *userdata) { - CreateWGPUShaderModuleTask *task = static_cast(userdata); + if (mFeatures.avoidWaitAny.enabled) + { + WGPUCompilationInfoCallbackInfo getCompilationInfoCallback = + WGPU_COMPILATION_INFO_CALLBACK_INFO_INIT; + getCompilationInfoCallback.mode = WGPUCallbackMode_AllowSpontaneous; + getCompilationInfoCallback.callback = + [](WGPUCompilationInfoRequestStatus status, + struct WGPUCompilationInfo const *compilationInfo, void *userdata1, + void *userdata2) { + ASSERT(userdata1 == nullptr); + ASSERT(userdata2 == nullptr); + for (size_t msgIdx = 0; + compilationInfo && msgIdx < compilationInfo->messageCount; ++msgIdx) + { + const WGPUCompilationMessage &message = compilationInfo->messages[msgIdx]; + switch (message.type) + { + case WGPUCompilationMessageType_Error: + ERR() << FormatWGPUCompilationMessage(message); + break; + case WGPUCompilationMessageType_Warning: + WARN() << FormatWGPUCompilationMessage(message); + break; + case WGPUCompilationMessageType_Info: + INFO() << FormatWGPUCompilationMessage(message); + break; + default: + UNIMPLEMENTED(); + break; + } + } + }; - if (status != WGPUCompilationInfoRequestStatus_Success) - { - task->mResult = angle::Result::Stop; - } + mProcTable->shaderModuleGetCompilationInfo(mShaderModule.module.get(), + getCompilationInfoCallback); + } + else + { + WGPUCompilationInfoCallbackInfo getCompilationInfoCallback = + WGPU_COMPILATION_INFO_CALLBACK_INFO_INIT; + getCompilationInfoCallback.mode = WGPUCallbackMode_WaitAnyOnly; + getCompilationInfoCallback.callback = + [](WGPUCompilationInfoRequestStatus status, + struct WGPUCompilationInfo const *compilationInfo, void *userdata1, + void *userdata2) { + CreateWGPUShaderModuleTask *task = + reinterpret_cast(userdata1); + ASSERT(userdata2 == nullptr); + if (status != WGPUCompilationInfoRequestStatus_Success) + { + task->mResult = angle::Result::Stop; + } - for (size_t msgIdx = 0; msgIdx < compilationInfo->messageCount; ++msgIdx) + for (size_t msgIdx = 0; + compilationInfo && msgIdx < compilationInfo->messageCount; ++msgIdx) + { + const WGPUCompilationMessage &message = compilationInfo->messages[msgIdx]; + switch (message.type) + { + case WGPUCompilationMessageType_Error: + task->mLog << "Error: "; + break; + case WGPUCompilationMessageType_Warning: + task->mLog << "Warning: "; + break; + case WGPUCompilationMessageType_Info: + task->mLog << "Info: "; + break; + default: + task->mLog << "Unknown: "; + break; + } + task->mLog << FormatWGPUCompilationMessage(message) << std::endl; + } + }; + getCompilationInfoCallback.userdata1 = this; + + WGPUFutureWaitInfo waitInfo = WGPU_FUTURE_WAIT_INFO_INIT; + waitInfo.future = mProcTable->shaderModuleGetCompilationInfo( + mShaderModule.module.get(), getCompilationInfoCallback); + WGPUWaitStatus waitStatus = + mProcTable->instanceWaitAny(mInstance.get(), 1, &waitInfo, -1); + if (waitStatus != WGPUWaitStatus_Success) { - const WGPUCompilationMessage &message = compilationInfo->messages[msgIdx]; - switch (message.type) - { - case WGPUCompilationMessageType_Error: - task->mLog << "Error: "; - break; - case WGPUCompilationMessageType_Warning: - task->mLog << "Warning: "; - break; - case WGPUCompilationMessageType_Info: - task->mLog << "Info: "; - break; - default: - task->mLog << "Unknown: "; - break; - } - task->mLog << message.lineNum << ":" << message.linePos << ": " << message.message - << std::endl; + mResult = angle::Result::Stop; } - }; - callbackInfo.userdata = this; - - wgpu::FutureWaitInfo waitInfo; - waitInfo.future = mShaderModule.module.GetCompilationInfo(callbackInfo); - - wgpu::WaitStatus waitStatus = mInstance.WaitAny(1, &waitInfo, -1); - if (waitStatus != wgpu::WaitStatus::Success) - { - mResult = angle::Result::Stop; } } private: - wgpu::Instance mInstance; - wgpu::Device mDevice; + const DawnProcTable *mProcTable = nullptr; + webgpu::InstanceHandle mInstance; + webgpu::DeviceHandle mDevice; + const angle::FeaturesWgpu &mFeatures; gl::SharedCompiledShaderState mCompiledShaderState; const gl::ProgramExecutable &mExecutable; gl::ProgramMergedVaryings mMergedVaryings; @@ -190,9 +266,15 @@ class CreateWGPUShaderModuleTask : public LinkSubTask class LinkTaskWgpu : public LinkTask { public: - LinkTaskWgpu(wgpu::Instance instance, wgpu::Device device, ProgramWgpu *program) - : mInstance(instance), + LinkTaskWgpu(const DawnProcTable *wgpu, + webgpu::InstanceHandle instance, + webgpu::DeviceHandle device, + const angle::FeaturesWgpu &features, + ProgramWgpu *program) + : mProcTable(wgpu), + mInstance(instance), mDevice(device), + mFeatures(features), mProgram(program), mExecutable(&mProgram->getState().getExecutable()) {} @@ -216,8 +298,9 @@ class LinkTaskWgpu : public LinkTask if (shaders[shaderType]) { auto task = std::make_shared( - mInstance, mDevice, shaders[shaderType], *executable->getExecutable(), - mergedVaryings, executable->getShaderModule(shaderType)); + mProcTable, mInstance, mDevice, mFeatures, shaders[shaderType], + *executable->getExecutable(), mergedVaryings, + executable->getShaderModule(shaderType)); linkSubTasksOut->push_back(task); } } @@ -249,7 +332,7 @@ class LinkTaskWgpu : public LinkTask gl::ShaderMap requiredBufferSize; requiredBufferSize.fill(0); - generateUniformLayoutMapping(&layoutMap, &requiredBufferSize); + ANGLE_TRY(generateUniformLayoutMapping(&layoutMap, &requiredBufferSize)); initDefaultUniformLayoutMapping(&layoutMap); // All uniform initializations are complete, now resize the buffers accordingly and return @@ -260,8 +343,8 @@ class LinkTaskWgpu : public LinkTask return angle::Result::Continue; } - void generateUniformLayoutMapping(gl::ShaderMap *layoutMapOut, - gl::ShaderMap *requiredBufferSizeOut) + angle::Result generateUniformLayoutMapping(gl::ShaderMap *layoutMapOut, + gl::ShaderMap *requiredBufferSizeOut) { for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages()) { @@ -271,10 +354,12 @@ class LinkTaskWgpu : public LinkTask if (shader) { const std::vector &uniforms = shader->uniforms; - InitDefaultUniformBlock(uniforms, &(*layoutMapOut)[shaderType], - &(*requiredBufferSizeOut)[shaderType]); + ANGLE_TRY(InitDefaultUniformBlock(uniforms, &(*layoutMapOut)[shaderType], + &(*requiredBufferSizeOut)[shaderType])); } } + + return angle::Result::Continue; } void initDefaultUniformLayoutMapping(gl::ShaderMap *layoutMapOut) @@ -326,8 +411,10 @@ class LinkTaskWgpu : public LinkTask } } - wgpu::Instance mInstance; - wgpu::Device mDevice; + const DawnProcTable *mProcTable = nullptr; + webgpu::InstanceHandle mInstance; + webgpu::DeviceHandle mDevice; + const angle::FeaturesWgpu &mFeatures; ProgramWgpu *mProgram = nullptr; const gl::ProgramExecutable *mExecutable; angle::Result mLinkResult = angle::Result::Stop; @@ -356,10 +443,13 @@ void ProgramWgpu::setSeparable(bool separable) {} angle::Result ProgramWgpu::link(const gl::Context *context, std::shared_ptr *linkTaskOut) { - wgpu::Device device = webgpu::GetDevice(context); - wgpu::Instance instance = webgpu::GetInstance(context); + const DawnProcTable *wgpu = webgpu::GetProcs(context); + const angle::FeaturesWgpu &features = webgpu::GetFeatures(context); + webgpu::DeviceHandle device = webgpu::GetDevice(context); + webgpu::InstanceHandle instance = webgpu::GetInstance(context); - *linkTaskOut = std::shared_ptr(new LinkTaskWgpu(instance, device, this)); + *linkTaskOut = + std::shared_ptr(new LinkTaskWgpu(wgpu, instance, device, features, this)); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/wgpu/RenderTargetWgpu.cpp b/src/libANGLE/renderer/wgpu/RenderTargetWgpu.cpp index cbc6dfbae2f..eed32ceffa5 100644 --- a/src/libANGLE/renderer/wgpu/RenderTargetWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/RenderTargetWgpu.cpp @@ -27,10 +27,10 @@ RenderTargetWgpu::RenderTargetWgpu(RenderTargetWgpu &&other) {} void RenderTargetWgpu::set(webgpu::ImageHelper *image, - const wgpu::TextureView &texture, + const webgpu::TextureViewHandle &texture, const webgpu::LevelIndex level, uint32_t layer, - const wgpu::TextureFormat &format) + WGPUTextureFormat format) { mImage = image; mTextureView = texture; diff --git a/src/libANGLE/renderer/wgpu/RenderTargetWgpu.h b/src/libANGLE/renderer/wgpu/RenderTargetWgpu.h index 45386f0ab3c..f1e71168f34 100644 --- a/src/libANGLE/renderer/wgpu/RenderTargetWgpu.h +++ b/src/libANGLE/renderer/wgpu/RenderTargetWgpu.h @@ -10,10 +10,11 @@ #ifndef LIBANGLE_RENDERER_WGPU_RENDERTARGETWGPU_H_ #define LIBANGLE_RENDERER_WGPU_RENDERTARGETWGPU_H_ -#include #include +#include #include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/angletypes.h" #include "libANGLE/renderer/wgpu/wgpu_helpers.h" #include "libANGLE/renderer/wgpu/wgpu_utils.h" @@ -29,27 +30,29 @@ class RenderTargetWgpu final : public FramebufferAttachmentRenderTarget RenderTargetWgpu(RenderTargetWgpu &&other); void set(webgpu::ImageHelper *image, - const wgpu::TextureView &texture, + const webgpu::TextureViewHandle &texture, const webgpu::LevelIndex level, uint32_t layer, - const wgpu::TextureFormat &format); + WGPUTextureFormat format); void reset(); angle::Result flushImageStagedUpdates(ContextWgpu *contextWgpu, webgpu::ClearValuesArray *deferredClears, uint32_t deferredClearIndex); - wgpu::TextureView getTextureView() { return mTextureView; } + webgpu::TextureViewHandle getTextureView() { return mTextureView; } webgpu::ImageHelper *getImage() { return mImage; } webgpu::LevelIndex getLevelIndex() const { return mLevelIndex; } + uint32_t getLayer() const { return mLayerIndex; } + gl::LevelIndex getGlLevel() const { return mImage->toGlLevel(mLevelIndex); } private: webgpu::ImageHelper *mImage = nullptr; // TODO(liza): move TextureView into ImageHelper. - wgpu::TextureView mTextureView; + webgpu::TextureViewHandle mTextureView; webgpu::LevelIndex mLevelIndex{0}; uint32_t mLayerIndex = 0; - const wgpu::TextureFormat *mFormat = nullptr; + const WGPUTextureFormat *mFormat = nullptr; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/RenderbufferWgpu.cpp b/src/libANGLE/renderer/wgpu/RenderbufferWgpu.cpp index 4cb5b446728..82bc8192d04 100644 --- a/src/libANGLE/renderer/wgpu/RenderbufferWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/RenderbufferWgpu.cpp @@ -10,20 +10,35 @@ #include "libANGLE/renderer/wgpu/RenderbufferWgpu.h" #include "common/debug.h" +#include "libANGLE/renderer/wgpu/ImageWgpu.h" namespace rx { +namespace +{ +constexpr angle::SubjectIndex kRenderbufferImageSubjectIndex = 0; +} -RenderbufferWgpu::RenderbufferWgpu(const gl::RenderbufferState &state) : RenderbufferImpl(state) {} +RenderbufferWgpu::RenderbufferWgpu(const gl::RenderbufferState &state) + : RenderbufferImpl(state), mImageObserverBinding(this, kRenderbufferImageSubjectIndex) +{ + setImageHelper(new webgpu::ImageHelper(), true); +} RenderbufferWgpu::~RenderbufferWgpu() {} +void RenderbufferWgpu::onDestroy(const gl::Context *context) +{ + setImageHelper(nullptr, true); +} + angle::Result RenderbufferWgpu::setStorage(const gl::Context *context, GLenum internalformat, GLsizei width, GLsizei height) { - return angle::Result::Continue; + return setStorageMultisample(context, 1, internalformat, width, height, + gl::MultisamplingMode::Regular); } angle::Result RenderbufferWgpu::setStorageMultisample(const gl::Context *context, @@ -33,12 +48,40 @@ angle::Result RenderbufferWgpu::setStorageMultisample(const gl::Context *context GLsizei height, gl::MultisamplingMode mode) { + ASSERT(mode == gl::MultisamplingMode::Regular); + + if (width == 0 || height == 0) + { + mImage->resetImage(); + return angle::Result::Continue; + } + + const DawnProcTable *wgpu = webgpu::GetProcs(context); + ContextWgpu *contextWgpu = webgpu::GetImpl(context); + const webgpu::Format &webgpuFormat = contextWgpu->getFormat(internalformat); + + constexpr WGPUTextureUsage kUsage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | + WGPUTextureUsage_RenderAttachment | + WGPUTextureUsage_TextureBinding; + + WGPUTextureDescriptor desc = mImage->createTextureDescriptor( + kUsage, WGPUTextureDimension_2D, gl_wgpu::GetExtent3D(gl::Extents(width, height, 1)), + webgpuFormat.getActualWgpuTextureFormat(), /*mipLevelCount*/ 1, samples); + + ANGLE_TRY(mImage->initImage(wgpu, webgpuFormat.getIntendedFormatID(), + webgpuFormat.getActualImageFormatID(), contextWgpu->getDevice(), + gl::LevelIndex(0), desc)); + return angle::Result::Continue; } angle::Result RenderbufferWgpu::setStorageEGLImageTarget(const gl::Context *context, egl::Image *image) { + ImageWgpu *imageWgpu = webgpu::GetImpl(image); + setImageHelper(imageWgpu->getImage(), false); + ASSERT(mImage->isInitialized()); + return angle::Result::Continue; } @@ -46,7 +89,61 @@ angle::Result RenderbufferWgpu::initializeContents(const gl::Context *context, GLenum binding, const gl::ImageIndex &imageIndex) { + UNIMPLEMENTED(); + return angle::Result::Continue; +} + +angle::Result RenderbufferWgpu::getAttachmentRenderTarget(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex, + GLsizei samples, + FramebufferAttachmentRenderTarget **rtOut) +{ + gl::LevelIndex level(0); + + webgpu::TextureViewHandle textureView; + ANGLE_TRY(mImage->createTextureViewSingleLevel(level, 0, textureView)); + + mRenderTarget.set(mImage, textureView, mImage->toWgpuLevel(level), 0, + mImage->toWgpuTextureFormat()); + + *rtOut = &mRenderTarget; return angle::Result::Continue; } +void RenderbufferWgpu::releaseOwnershipOfImage(const gl::Context *context) +{ + mOwnsImage = false; + setImageHelper(nullptr, true); +} + +void RenderbufferWgpu::onSubjectStateChange(angle::SubjectIndex index, + angle::SubjectMessage message) +{ + ASSERT(index == kRenderbufferImageSubjectIndex && + (message == angle::SubjectMessage::SubjectChanged || + message == angle::SubjectMessage::InitializationComplete)); + + // Forward the notification to the parent that the internal storage changed. + onStateChange(message); +} + +void RenderbufferWgpu::setImageHelper(webgpu::ImageHelper *imageHelper, bool ownsImageHelper) +{ + if (mOwnsImage && mImage) + { + mImageObserverBinding.bind(nullptr); + SafeDelete(mImage); + } + + mImage = imageHelper; + mOwnsImage = ownsImageHelper; + + if (mImage) + { + mImageObserverBinding.bind(mImage); + } + + onStateChange(angle::SubjectMessage::SubjectChanged); +} } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/RenderbufferWgpu.h b/src/libANGLE/renderer/wgpu/RenderbufferWgpu.h index 8e45a9a2014..24ebacf1d72 100644 --- a/src/libANGLE/renderer/wgpu/RenderbufferWgpu.h +++ b/src/libANGLE/renderer/wgpu/RenderbufferWgpu.h @@ -11,16 +11,20 @@ #define LIBANGLE_RENDERER_WGPU_RENDERBUFFERWGPU_H_ #include "libANGLE/renderer/RenderbufferImpl.h" +#include "libANGLE/renderer/wgpu/RenderTargetWgpu.h" +#include "libANGLE/renderer/wgpu/wgpu_helpers.h" namespace rx { -class RenderbufferWgpu : public RenderbufferImpl +class RenderbufferWgpu : public RenderbufferImpl, public angle::ObserverInterface { public: RenderbufferWgpu(const gl::RenderbufferState &state); ~RenderbufferWgpu() override; + void onDestroy(const gl::Context *context) override; + angle::Result setStorage(const gl::Context *context, GLenum internalformat, GLsizei width, @@ -37,6 +41,28 @@ class RenderbufferWgpu : public RenderbufferImpl angle::Result initializeContents(const gl::Context *context, GLenum binding, const gl::ImageIndex &imageIndex) override; + + angle::Result getAttachmentRenderTarget(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex, + GLsizei samples, + FramebufferAttachmentRenderTarget **rtOut) override; + + void releaseOwnershipOfImage(const gl::Context *context); + webgpu::ImageHelper *getImage() const { return mImage; } + + // We monitor the ImageHelper and set dirty bits if the ImageHelper changes. This can + // support changes in the ImageHelper even outside the RenderbufferWgpu class. + void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + + private: + void setImageHelper(webgpu::ImageHelper *imageHelper, bool ownsImageHelper); + + bool mOwnsImage = false; + webgpu::ImageHelper *mImage = nullptr; + RenderTargetWgpu mRenderTarget; + + angle::ObserverBinding mImageObserverBinding; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp b/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp index c8fa632a1f1..f24f8744793 100644 --- a/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp @@ -51,6 +51,7 @@ std::shared_ptr ShaderWgpu::compile(const gl::Context *cont options->validateAST = true; options->separateCompoundStructDeclarations = true; + options->scalarizeVecAndMatConstructorArgs = true; return std::shared_ptr(new ShaderTranslateTaskWgpu); } diff --git a/src/libANGLE/renderer/wgpu/SurfaceWgpu.cpp b/src/libANGLE/renderer/wgpu/SurfaceWgpu.cpp index 5a08d369aef..61f385349eb 100644 --- a/src/libANGLE/renderer/wgpu/SurfaceWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/SurfaceWgpu.cpp @@ -7,6 +7,10 @@ // Implements the class methods for SurfaceWgpu. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/SurfaceWgpu.h" #include "common/debug.h" @@ -19,44 +23,52 @@ namespace rx { -constexpr wgpu::TextureUsage kSurfaceTextureUsage = - wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment | - wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst; +constexpr WGPUTextureUsage kSurfaceTextureUsage = + WGPUTextureUsage_TextureBinding | WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc | + WGPUTextureUsage_CopyDst; SurfaceWgpu::SurfaceWgpu(const egl::SurfaceState &surfaceState) : SurfaceImpl(surfaceState) {} SurfaceWgpu::~SurfaceWgpu() {} -angle::Result SurfaceWgpu::createDepthStencilAttachment(uint32_t width, +angle::Result SurfaceWgpu::createDepthStencilAttachment(const egl::Display *display, + uint32_t width, uint32_t height, const webgpu::Format &webgpuFormat, - wgpu::Device &device, + webgpu::DeviceHandle device, AttachmentImage *outDepthStencilAttachment) { - wgpu::TextureDescriptor desc = outDepthStencilAttachment->texture.createTextureDescriptor( - kSurfaceTextureUsage, wgpu::TextureDimension::e2D, {width, height, 1}, + const DisplayWgpu *displayWgpu = webgpu::GetImpl(display); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + + WGPUTextureDescriptor desc = outDepthStencilAttachment->texture.createTextureDescriptor( + kSurfaceTextureUsage, WGPUTextureDimension_2D, {width, height, 1}, webgpuFormat.getActualWgpuTextureFormat(), 1, 1); constexpr uint32_t level = 0; constexpr uint32_t layer = 0; - ANGLE_TRY(outDepthStencilAttachment->texture.initImage(webgpuFormat.getIntendedFormatID(), + ANGLE_TRY(outDepthStencilAttachment->texture.initImage(wgpu, webgpuFormat.getIntendedFormatID(), webgpuFormat.getActualImageFormatID(), device, gl::LevelIndex(level), desc)); - wgpu::TextureView view; - ANGLE_TRY( - outDepthStencilAttachment->texture.createTextureView(gl::LevelIndex(level), layer, view)); + webgpu::TextureViewHandle view; + ANGLE_TRY(outDepthStencilAttachment->texture.createTextureViewSingleLevel(gl::LevelIndex(level), + layer, view)); outDepthStencilAttachment->renderTarget.set( &outDepthStencilAttachment->texture, view, webgpu::LevelIndex(level), layer, outDepthStencilAttachment->texture.toWgpuTextureFormat()); return angle::Result::Continue; } -OffscreenSurfaceWgpu::OffscreenSurfaceWgpu(const egl::SurfaceState &surfaceState) +OffscreenSurfaceWgpu::OffscreenSurfaceWgpu(const egl::SurfaceState &surfaceState, + EGLenum clientBufferType, + EGLClientBuffer clientBuffer) : SurfaceWgpu(surfaceState), mWidth(surfaceState.attributes.getAsInt(EGL_WIDTH, 0)), - mHeight(surfaceState.attributes.getAsInt(EGL_HEIGHT, 0)) + mHeight(surfaceState.attributes.getAsInt(EGL_HEIGHT, 0)), + mClientBufferType(clientBufferType), + mClientBuffer(clientBuffer) {} OffscreenSurfaceWgpu::~OffscreenSurfaceWgpu() {} @@ -66,7 +78,7 @@ egl::Error OffscreenSurfaceWgpu::initialize(const egl::Display *display) return angle::ResultToEGL(initializeImpl(display)); } -egl::Error OffscreenSurfaceWgpu::swap(const gl::Context *context) +egl::Error OffscreenSurfaceWgpu::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { UNREACHABLE(); return egl::NoError(); @@ -88,15 +100,11 @@ egl::Error OffscreenSurfaceWgpu::releaseTexImage(const gl::Context *context, EGL void OffscreenSurfaceWgpu::setSwapInterval(const egl::Display *display, EGLint interval) {} -EGLint OffscreenSurfaceWgpu::getWidth() const +gl::Extents OffscreenSurfaceWgpu::getSize() const { - return mWidth; + return gl::Extents(mWidth, mHeight, 1); } -EGLint OffscreenSurfaceWgpu::getHeight() const -{ - return mHeight; -} EGLint OffscreenSurfaceWgpu::getSwapBehavior() const { @@ -148,38 +156,69 @@ angle::Result OffscreenSurfaceWgpu::getAttachmentRenderTarget( angle::Result OffscreenSurfaceWgpu::initializeImpl(const egl::Display *display) { DisplayWgpu *displayWgpu = webgpu::GetImpl(display); - wgpu::Device &device = displayWgpu->getDevice(); - - const egl::Config *config = mState.config; + const DawnProcTable *wgpu = displayWgpu->getProcs(); + webgpu::DeviceHandle device = displayWgpu->getDevice(); - if (config->renderTargetFormat != GL_NONE) + if (mClientBufferType == EGL_WEBGPU_TEXTURE_ANGLE) { - const webgpu::Format &webgpuFormat = displayWgpu->getFormat(config->renderTargetFormat); - wgpu::TextureDescriptor desc = mColorAttachment.texture.createTextureDescriptor( - kSurfaceTextureUsage, wgpu::TextureDimension::e2D, - {static_cast(mWidth), static_cast(mHeight), 1}, - webgpuFormat.getActualWgpuTextureFormat(), 1, 1); - - constexpr uint32_t level = 0; - constexpr uint32_t layer = 0; - - ANGLE_TRY(mColorAttachment.texture.initImage(webgpuFormat.getIntendedFormatID(), - webgpuFormat.getActualImageFormatID(), device, - gl::LevelIndex(level), desc)); - - wgpu::TextureView view; - ANGLE_TRY(mColorAttachment.texture.createTextureView(gl::LevelIndex(level), layer, view)); - mColorAttachment.renderTarget.set(&mColorAttachment.texture, view, - webgpu::LevelIndex(level), layer, + webgpu::TextureHandle externalTexture = + webgpu::TextureHandle::Acquire(wgpu, reinterpret_cast(mClientBuffer)); + ASSERT(externalTexture != nullptr); + + // Explicitly add-ref to hold on to the external reference + wgpu->textureAddRef(externalTexture.get()); + + const webgpu::Format *webgpuFormat = displayWgpu->getFormatForImportedTexture( + mState.attributes, wgpu->textureGetFormat(externalTexture.get())); + ASSERT(webgpuFormat); + ANGLE_TRY(mColorAttachment.texture.initExternal(wgpu, webgpuFormat->getIntendedFormatID(), + webgpuFormat->getActualImageFormatID(), + externalTexture)); + + webgpu::TextureViewHandle view; + ANGLE_TRY( + mColorAttachment.texture.createTextureViewSingleLevel(gl::LevelIndex(0), 0, view)); + + mColorAttachment.renderTarget.set(&mColorAttachment.texture, view, webgpu::LevelIndex(0), 0, mColorAttachment.texture.toWgpuTextureFormat()); - } - if (config->depthStencilFormat != GL_NONE) + mWidth = mColorAttachment.texture.getSize().width; + mHeight = mColorAttachment.texture.getSize().height; + } + else { - const webgpu::Format &webgpuFormat = displayWgpu->getFormat(config->depthStencilFormat); - ANGLE_TRY(createDepthStencilAttachment(static_cast(mWidth), - static_cast(mHeight), webgpuFormat, device, - &mDepthStencilAttachment)); + const egl::Config *config = mState.config; + + if (config->renderTargetFormat != GL_NONE) + { + const webgpu::Format &webgpuFormat = displayWgpu->getFormat(config->renderTargetFormat); + WGPUTextureDescriptor desc = mColorAttachment.texture.createTextureDescriptor( + kSurfaceTextureUsage, WGPUTextureDimension_2D, + {static_cast(mWidth), static_cast(mHeight), 1}, + webgpuFormat.getActualWgpuTextureFormat(), 1, 1); + + constexpr uint32_t level = 0; + constexpr uint32_t layer = 0; + + ANGLE_TRY(mColorAttachment.texture.initImage(wgpu, webgpuFormat.getIntendedFormatID(), + webgpuFormat.getActualImageFormatID(), + device, gl::LevelIndex(level), desc)); + + webgpu::TextureViewHandle view; + ANGLE_TRY(mColorAttachment.texture.createTextureViewSingleLevel(gl::LevelIndex(level), + layer, view)); + mColorAttachment.renderTarget.set(&mColorAttachment.texture, view, + webgpu::LevelIndex(level), layer, + mColorAttachment.texture.toWgpuTextureFormat()); + } + + if (config->depthStencilFormat != GL_NONE) + { + const webgpu::Format &webgpuFormat = displayWgpu->getFormat(config->depthStencilFormat); + ANGLE_TRY(createDepthStencilAttachment(display, static_cast(mWidth), + static_cast(mHeight), webgpuFormat, + device, &mDepthStencilAttachment)); + } } return angle::Result::Continue; @@ -206,7 +245,7 @@ void WindowSurfaceWgpu::destroy(const egl::Display *display) mDepthStencilAttachment.texture.resetImage(); } -egl::Error WindowSurfaceWgpu::swap(const gl::Context *context) +egl::Error WindowSurfaceWgpu::swap(const gl::Context *context, SurfaceSwapFeedback *feedback) { return angle::ResultToEGL(swapImpl(context)); } @@ -230,14 +269,9 @@ void WindowSurfaceWgpu::setSwapInterval(const egl::Display *display, EGLint inte UNIMPLEMENTED(); } -EGLint WindowSurfaceWgpu::getWidth() const -{ - return mCurrentSurfaceSize.width; -} - -EGLint WindowSurfaceWgpu::getHeight() const +gl::Extents WindowSurfaceWgpu::getSize() const { - return mCurrentSurfaceSize.height; + return mCurrentSurfaceSize; } EGLint WindowSurfaceWgpu::getSwapBehavior() const @@ -257,12 +291,16 @@ angle::Result WindowSurfaceWgpu::initializeContents(const gl::Context *context, egl::Error WindowSurfaceWgpu::attachToFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) { + FramebufferWgpu *framebufferWgpu = GetImplAs(framebuffer); + framebufferWgpu->setFlipY(true); return egl::NoError(); } egl::Error WindowSurfaceWgpu::detachFromFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) { + FramebufferWgpu *framebufferWgpu = GetImplAs(framebuffer); + framebufferWgpu->setFlipY(false); return egl::NoError(); } @@ -289,18 +327,20 @@ angle::Result WindowSurfaceWgpu::getAttachmentRenderTarget( angle::Result WindowSurfaceWgpu::initializeImpl(const egl::Display *display) { DisplayWgpu *displayWgpu = webgpu::GetImpl(display); - wgpu::Adapter &adapter = displayWgpu->getAdapter(); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + webgpu::AdapterHandle adapter = displayWgpu->getAdapter(); ANGLE_TRY(createWgpuSurface(display, &mSurface)); gl::Extents size; ANGLE_TRY(getCurrentWindowSize(display, &size)); - wgpu::SurfaceCapabilities surfaceCapabilities; - wgpu::Status getCapabilitiesStatus = mSurface.GetCapabilities(adapter, &surfaceCapabilities); - if (getCapabilitiesStatus != wgpu::Status::Success) + WGPUSurfaceCapabilities surfaceCapabilities = WGPU_SURFACE_CAPABILITIES_INIT; + WGPUStatus getCapabilitiesStatus = + wgpu->surfaceGetCapabilities(mSurface.get(), adapter.get(), &surfaceCapabilities); + if (getCapabilitiesStatus != WGPUStatus_Success) { - ERR() << "wgpu::Surface::GetCapabilities failed: " + ERR() << "wgpuSurfaceGetCapabilities failed: " << gl::FmtHex(static_cast(getCapabilitiesStatus)); return angle::Result::Stop; } @@ -313,17 +353,17 @@ angle::Result WindowSurfaceWgpu::initializeImpl(const egl::Display *display) mSurfaceTextureFormat->getActualWgpuTextureFormat()) != (surfaceCapabilities.formats + surfaceCapabilities.formatCount)); - mSurfaceTextureUsage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc | - wgpu::TextureUsage::CopyDst; + mSurfaceTextureUsage = + WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst; ASSERT((surfaceCapabilities.usages & mSurfaceTextureUsage) == mSurfaceTextureUsage); // Default to the always supported Fifo present mode. Use Mailbox if it's available. - mPresentMode = wgpu::PresentMode::Fifo; + mPresentMode = WGPUPresentMode_Fifo; for (size_t i = 0; i < surfaceCapabilities.presentModeCount; i++) { - if (surfaceCapabilities.presentModes[i] == wgpu::PresentMode::Mailbox) + if (surfaceCapabilities.presentModes[i] == WGPUPresentMode_Mailbox) { - mPresentMode = wgpu::PresentMode::Mailbox; + mPresentMode = WGPUPresentMode_Mailbox; } } @@ -346,10 +386,11 @@ angle::Result WindowSurfaceWgpu::swapImpl(const gl::Context *context) { const egl::Display *display = context->getDisplay(); ContextWgpu *contextWgpu = webgpu::GetImpl(context); + const DawnProcTable *wgpu = webgpu::GetProcs(contextWgpu); ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::EGLSwapBuffers)); - mSurface.Present(); + wgpu->surfacePresent(mSurface.get()); gl::Extents size; ANGLE_TRY(getCurrentWindowSize(display, &size)); @@ -367,24 +408,25 @@ angle::Result WindowSurfaceWgpu::configureSurface(const egl::Display *display, const gl::Extents &size) { DisplayWgpu *displayWgpu = webgpu::GetImpl(display); - wgpu::Device &device = displayWgpu->getDevice(); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + webgpu::DeviceHandle device = displayWgpu->getDevice(); ASSERT(mSurfaceTextureFormat != nullptr); - wgpu::SurfaceConfiguration surfaceConfig = {}; - surfaceConfig.device = device; + WGPUSurfaceConfiguration surfaceConfig = WGPU_SURFACE_CONFIGURATION_INIT; + surfaceConfig.device = device.get(); surfaceConfig.format = mSurfaceTextureFormat->getActualWgpuTextureFormat(); surfaceConfig.usage = mSurfaceTextureUsage; surfaceConfig.width = size.width; surfaceConfig.height = size.height; surfaceConfig.presentMode = mPresentMode; - mSurface.Configure(&surfaceConfig); + wgpu->surfaceConfigure(mSurface.get(), &surfaceConfig); if (mDepthStencilFormat) { ANGLE_TRY(createDepthStencilAttachment( - static_cast(size.width), static_cast(size.height), + display, static_cast(size.width), static_cast(size.height), *mDepthStencilFormat, device, &mDepthStencilAttachment)); } @@ -394,22 +436,27 @@ angle::Result WindowSurfaceWgpu::configureSurface(const egl::Display *display, angle::Result WindowSurfaceWgpu::updateCurrentTexture(const egl::Display *display) { - wgpu::SurfaceTexture texture; - mSurface.GetCurrentTexture(&texture); - if (texture.status != wgpu::SurfaceGetCurrentTextureStatus::Success) + DisplayWgpu *displayWgpu = webgpu::GetImpl(display); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + + WGPUSurfaceTexture surfaceTexture = WGPU_SURFACE_TEXTURE_INIT; + wgpu->surfaceGetCurrentTexture(mSurface.get(), &surfaceTexture); + webgpu::TextureHandle texture = webgpu::TextureHandle::Acquire(wgpu, surfaceTexture.texture); + if (surfaceTexture.status != WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal && + surfaceTexture.status != WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal) { - ERR() << "wgpu::Surface::GetCurrentTexture failed: " - << gl::FmtHex(static_cast(texture.status)); + ERR() << "wgpuSurfaceGetCurrentTexture failed: " + << gl::FmtHex(static_cast(surfaceTexture.status)); return angle::Result::Stop; } - wgpu::TextureFormat wgpuFormat = texture.texture.GetFormat(); + WGPUTextureFormat wgpuFormat = wgpu->textureGetFormat(texture.get()); angle::FormatID angleFormat = webgpu::GetFormatIDFromWgpuTextureFormat(wgpuFormat); - ANGLE_TRY(mColorAttachment.texture.initExternal(angleFormat, angleFormat, texture.texture)); + ANGLE_TRY(mColorAttachment.texture.initExternal(wgpu, angleFormat, angleFormat, texture)); - wgpu::TextureView view; - ANGLE_TRY(mColorAttachment.texture.createTextureView(gl::LevelIndex(0), 0, view)); + webgpu::TextureViewHandle view; + ANGLE_TRY(mColorAttachment.texture.createTextureViewSingleLevel(gl::LevelIndex(0), 0, view)); mColorAttachment.renderTarget.set(&mColorAttachment.texture, view, webgpu::LevelIndex(0), 0, wgpuFormat); diff --git a/src/libANGLE/renderer/wgpu/SurfaceWgpu.h b/src/libANGLE/renderer/wgpu/SurfaceWgpu.h index 3003b53c2ba..8da4ca2026b 100644 --- a/src/libANGLE/renderer/wgpu/SurfaceWgpu.h +++ b/src/libANGLE/renderer/wgpu/SurfaceWgpu.h @@ -15,7 +15,7 @@ #include "libANGLE/renderer/wgpu/RenderTargetWgpu.h" #include "libANGLE/renderer/wgpu/wgpu_helpers.h" -#include +#include namespace rx { @@ -32,30 +32,32 @@ class SurfaceWgpu : public SurfaceImpl webgpu::ImageHelper texture; RenderTargetWgpu renderTarget; }; - angle::Result createDepthStencilAttachment(uint32_t width, + angle::Result createDepthStencilAttachment(const egl::Display *display, + uint32_t width, uint32_t height, const webgpu::Format &webgpuFormat, - wgpu::Device &device, + webgpu::DeviceHandle device, AttachmentImage *outDepthStencilAttachment); }; class OffscreenSurfaceWgpu : public SurfaceWgpu { public: - OffscreenSurfaceWgpu(const egl::SurfaceState &surfaceState); + OffscreenSurfaceWgpu(const egl::SurfaceState &surfaceState, + EGLenum clientBufferType, + EGLClientBuffer clientBuffer); ~OffscreenSurfaceWgpu() override; egl::Error initialize(const egl::Display *display) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - // width and height can change with client window resizing - EGLint getWidth() const override; - EGLint getHeight() const override; + // size can change with client window resizing + gl::Extents getSize() const override; EGLint getSwapBehavior() const override; @@ -80,6 +82,9 @@ class OffscreenSurfaceWgpu : public SurfaceWgpu EGLint mWidth; EGLint mHeight; + EGLenum mClientBufferType = EGL_NONE; + EGLClientBuffer mClientBuffer = nullptr; + AttachmentImage mColorAttachment; AttachmentImage mDepthStencilAttachment; }; @@ -92,16 +97,15 @@ class WindowSurfaceWgpu : public SurfaceWgpu egl::Error initialize(const egl::Display *display) override; void destroy(const egl::Display *display) override; - egl::Error swap(const gl::Context *context) override; + egl::Error swap(const gl::Context *context, SurfaceSwapFeedback *feedback) override; egl::Error bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; void setSwapInterval(const egl::Display *display, EGLint interval) override; - // width and height can change with client window resizing - EGLint getWidth() const override; - EGLint getHeight() const override; + // size can change with client window resizing + gl::Extents getSize() const override; EGLint getSwapBehavior() const override; @@ -132,16 +136,16 @@ class WindowSurfaceWgpu : public SurfaceWgpu angle::Result updateCurrentTexture(const egl::Display *display); virtual angle::Result createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) = 0; + webgpu::SurfaceHandle *outSurface) = 0; virtual angle::Result getCurrentWindowSize(const egl::Display *display, gl::Extents *outSize) = 0; EGLNativeWindowType mNativeWindow; - wgpu::Surface mSurface; + webgpu::SurfaceHandle mSurface; const webgpu::Format *mSurfaceTextureFormat = nullptr; - wgpu::TextureUsage mSurfaceTextureUsage; - wgpu::PresentMode mPresentMode; + WGPUTextureUsage mSurfaceTextureUsage; + WGPUPresentMode mPresentMode; const webgpu::Format *mDepthStencilFormat = nullptr; diff --git a/src/libANGLE/renderer/wgpu/TextureWgpu.cpp b/src/libANGLE/renderer/wgpu/TextureWgpu.cpp index 7cc4e96566f..86425acc902 100644 --- a/src/libANGLE/renderer/wgpu/TextureWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/TextureWgpu.cpp @@ -9,12 +9,17 @@ #include "libANGLE/renderer/wgpu/TextureWgpu.h" +#include "common/PackedGLEnums_autogen.h" #include "common/debug.h" #include "libANGLE/Error.h" #include "libANGLE/angletypes.h" #include "libANGLE/renderer/wgpu/ContextWgpu.h" #include "libANGLE/renderer/wgpu/DisplayWgpu.h" +#include "libANGLE/renderer/wgpu/FramebufferWgpu.h" +#include "libANGLE/renderer/wgpu/ImageWgpu.h" #include "libANGLE/renderer/wgpu/RenderTargetWgpu.h" +#include "libANGLE/renderer/wgpu/UtilsWgpu.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" namespace rx { @@ -22,6 +27,8 @@ namespace rx namespace { +constexpr angle::SubjectIndex kTextureImageSubjectIndex = 0; + void GetRenderTargetLayerCountAndIndex(webgpu::ImageHelper *image, const gl::ImageIndex &index, GLuint *layerIndex, @@ -77,22 +84,75 @@ bool IsTextureLevelDefinitionCompatibleWithImage(webgpu::ImageHelper *image, const gl::Extents &size, const webgpu::Format &format) { - return size == wgpu_gl::getExtents(image->getSize()) && + return size == wgpu_gl::GetExtents(image->getSize()) && image->getIntendedFormatID() == format.getIntendedFormatID() && image->getActualFormatID() == format.getActualImageFormatID(); } +bool CanCopyWithTransferForTexImage(const webgpu::ImageHelper &srcImage, + angle::FormatID dstIntendedFormatID, + angle::FormatID dstActualFormatID, + WGPUTextureUsage dstUsage, + bool isViewportFlipY) +{ + // For glTex[Sub]Image, only accept same-format transfers. + // There are cases that two images' actual format is the same, but intended formats are + // different due to one is using the fallback format (for example, RGB fallback to RGBA). In + // these situations CanCopyWithTransfer will say yes. But if we use transfer to do copy, the + // alpha channel will be also be copied with source data which is wrong. + bool isFormatCompatible = srcImage.getIntendedFormatID() == dstIntendedFormatID && + srcImage.getActualFormatID() == dstActualFormatID; + + return !isViewportFlipY && isFormatCompatible && + (srcImage.getUsage() & WGPUTextureUsage_CopySrc) != 0 && + (dstUsage & WGPUTextureUsage_CopyDst) != 0; +} + +bool CanCopyWithDraw(const webgpu::ImageHelper &srcImage, WGPUTextureUsage dstUsage) +{ + return (srcImage.getUsage() & WGPUTextureUsage_TextureBinding) != 0 && + (dstUsage & WGPUTextureUsage_RenderAttachment) != 0; +} + +bool CanCopyWithTransferForCopyTexture(ContextWgpu *contextWgpu, + const webgpu::ImageHelper &srcImage, + angle::FormatID destIntendedFormatID, + angle::FormatID destActualFormatID, + WGPUTextureUsage destUsage, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + if (unpackFlipY || unpackPremultiplyAlpha != unpackUnmultiplyAlpha) + { + return false; + } + + bool isFormatCompatible = srcImage.getIntendedFormatID() == destIntendedFormatID && + srcImage.getActualFormatID() == destActualFormatID; + + return isFormatCompatible && (srcImage.getUsage() & WGPUTextureUsage_CopySrc) != 0 && + (destUsage & WGPUTextureUsage_CopyDst) != 0; +} + } // namespace TextureWgpu::TextureWgpu(const gl::TextureState &state) : TextureImpl(state), - mImage(new webgpu::ImageHelper()), mCurrentBaseLevel(state.getBaseLevel()), - mCurrentMaxLevel(state.getMaxLevel()) -{} + mCurrentMaxLevel(state.getMaxLevel()), + mImageObserverBinding(this, kTextureImageSubjectIndex) +{ + setImageHelper(new webgpu::ImageHelper(), true); +} TextureWgpu::~TextureWgpu() {} +void TextureWgpu::onDestroy(const gl::Context *context) +{ + setImageHelper(nullptr, true); +} + angle::Result TextureWgpu::setImage(const gl::Context *context, const gl::ImageIndex &index, GLenum internalFormat, @@ -149,7 +209,51 @@ angle::Result TextureWgpu::copyImage(const gl::Context *context, GLenum internalFormat, gl::Framebuffer *source) { - return angle::Result::Continue; + ContextWgpu *contextWgpu = GetImplAs(context); + + gl::Extents newImageSize(sourceArea.width, sourceArea.height, 1); + + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE); + + const webgpu::Format &webgpuFormat = + contextWgpu->getFormat(internalFormatInfo.sizedInternalFormat); + + // The texture level being redefined might be the same as the one bound to the framebuffer. + // This _could_ be supported by using a temp image before redefining the level (and potentially + // discarding the image). However, this is currently unimplemented. + FramebufferWgpu *framebufferWgpu = GetImplAs(source); + RenderTargetWgpu *colorReadRT = framebufferWgpu->getReadPixelsRenderTarget(); + webgpu::ImageHelper *srcImage = colorReadRT->getImage(); + const bool isCubeMap = index.getType() == gl::TextureType::CubeMap; + gl::LevelIndex levelIndex(index.getLevelIndex()); + const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0; + + const uint32_t redefinedFace = isCubeMap ? layerIndex : 0; + const uint32_t sourceFace = isCubeMap ? colorReadRT->getLayer() : 0; + const bool isSelfCopy = mImage->getTexture().get() == srcImage->getTexture().get() && + levelIndex == colorReadRT->getGlLevel() && redefinedFace == sourceFace; + + // TODO(anglebug.com/438268609): handle copying a texture when it needs to be redefined. + ANGLE_TRY(redefineLevel(context, webgpuFormat, index, newImageSize)); + + // TODO(crbug.com/438268609): Remove this and implement path to initialize the destination image + // then stage a copy update. + if (!mImage->isInitialized()) + { + ANGLE_TRY(initializeImageImpl(contextWgpu, webgpuFormat, index.getLevelIndex() + 1, + gl::LevelIndex(mState.getEffectiveBaseLevel()), + newImageSize)); + } + + if (isSelfCopy) + { + UNIMPLEMENTED(); + return angle::Result::Continue; + } + + return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo, + source); } angle::Result TextureWgpu::copySubImage(const gl::Context *context, @@ -158,7 +262,98 @@ angle::Result TextureWgpu::copySubImage(const gl::Context *context, const gl::Rectangle &sourceArea, gl::Framebuffer *source) { - return angle::Result::Continue; + ContextWgpu *contextWgpu = GetImplAs(context); + const gl::InternalFormat &internalFormat = *mState.getImageDesc(index).format.info; + const webgpu::Format &webgpuFormat = contextWgpu->getFormat(internalFormat.sizedInternalFormat); + + // TODO(crbug.com/438268609): Remove this and implement path to initialize the destination image + // then stage a copy update. + if (!mImage->isInitialized()) + { + ANGLE_TRY(initializeImageImpl(contextWgpu, webgpuFormat, index.getLevelIndex() + 1, + gl::LevelIndex(mState.getEffectiveBaseLevel()), + mState.getBaseLevelDesc().size)); + } + + return copySubImageImpl(context, index, destOffset, sourceArea, internalFormat, source); +} + +angle::Result TextureWgpu::copySubImageImpl(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::InternalFormat &internalFormat, + gl::Framebuffer *source) +{ + gl::Extents fbSize = source->getReadColorAttachment()->getSize(); + gl::Rectangle clippedSourceArea; + if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &clippedSourceArea)) + { + return angle::Result::Continue; + } + + ContextWgpu *contextWgpu = GetImplAs(context); + FramebufferWgpu *framebufferWgpu = GetImplAs(source); + + // If negative offsets are given, clippedSourceArea ensures we don't read from those offsets. + // However, that changes the sourceOffset->destOffset mapping. Here, destOffset is shifted by + // the same amount as clipped to correct the error. + WGPUTextureDimension imageType = gl_wgpu::GetWgpuTextureDimension(mState.getType()); + int zOffset = (imageType == WGPUTextureDimension_3D) ? destOffset.z : 0; + const gl::Offset modifiedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x, + destOffset.y + clippedSourceArea.y - sourceArea.y, zOffset); + + RenderTargetWgpu *colorReadRT = framebufferWgpu->getReadPixelsRenderTarget(); + if (!colorReadRT || !colorReadRT->getImage()) + { + UNIMPLEMENTED(); + return angle::Result::Continue; + } + + const webgpu::Format &dstFormat = contextWgpu->getFormat(internalFormat.sizedInternalFormat); + angle::FormatID dstIntendedFormatID = dstFormat.getIntendedFormatID(); + angle::FormatID dstActualFormatID = dstFormat.getActualImageFormatID(); + + bool isViewportFlipY = framebufferWgpu->flipY(); + + gl::Box clippedSourceBox(clippedSourceArea.x, clippedSourceArea.y, colorReadRT->getLayer(), + clippedSourceArea.width, clippedSourceArea.height, 1); + + // If it's possible to perform the copy with a transfer, that's the best option. + if (CanCopyWithTransferForTexImage(*colorReadRT->getImage(), dstIntendedFormatID, + dstActualFormatID, mImage->getUsage(), isViewportFlipY)) + { + return mImage->CopyImage(contextWgpu, colorReadRT->getImage(), index, modifiedDestOffset, + colorReadRT->getGlLevel(), colorReadRT->getLayer(), + clippedSourceBox); + } + + // If it's possible to perform the copy with a draw call, do that. + if (CanCopyWithDraw(*colorReadRT->getImage(), mImage->getUsage())) + { + webgpu::TextureViewHandle dstView; + ANGLE_TRY(mImage->createTextureViewSingleLevel(gl::LevelIndex(index.getLevelIndex()), + index.hasLayer() ? index.getLayerIndex() : 0, + dstView)); + + WGPUExtent3D srcSize = colorReadRT->getImage()->getTextureDescriptor().size; + WGPUExtent3D dstSize = mImage->getTextureDescriptor().size; + const angle::Format &srcFormat = + angle::Format::Get(colorReadRT->getImage()->getIntendedFormatID()); + const angle::Format &dstAngleFormat = dstFormat.getIntendedFormat(); + gl::Rectangle finalSourceArea = clippedSourceArea; + + return contextWgpu->getUtils()->copyImage( + contextWgpu, colorReadRT->getTextureView(), dstView, finalSourceArea, + modifiedDestOffset, srcSize, dstSize, false, false, isViewportFlipY, false, srcFormat, + dstAngleFormat.id, dstActualFormatID); + } + + return getImage()->copyImageCpuReadback( + context, index, clippedSourceArea, modifiedDestOffset, + gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat, + colorReadRT->getImage(), source->getExtents()); } angle::Result TextureWgpu::copyTexture(const gl::Context *context, @@ -171,7 +366,29 @@ angle::Result TextureWgpu::copyTexture(const gl::Context *context, bool unpackUnmultiplyAlpha, const gl::Texture *source) { - return angle::Result::Continue; + ContextWgpu *contextWgpu = webgpu::GetImpl(context); + TextureWgpu *sourceTextureWgpu = webgpu::GetImpl(source); + + const gl::ImageDesc &srcImageDesc = sourceTextureWgpu->mState.getImageDesc( + NonCubeTextureTypeToTarget(source->getType()), sourceLevel); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); + const webgpu::Format &dstWebgpuFormat = + contextWgpu->getFormat(internalFormatInfo.sizedInternalFormat); + ANGLE_TRY(redefineLevel(context, dstWebgpuFormat, index, srcImageDesc.size)); + + // TODO(crbug.com/438268609): Remove this and implement path to initialize the destination image + // then stage a copy update. + if (!mImage->isInitialized()) + { + ANGLE_TRY(initializeImageImpl(contextWgpu, dstWebgpuFormat, index.getLevelIndex() + 1, + gl::LevelIndex(sourceLevel), srcImageDesc.size)); + } + + return copySubTextureImpl(context, index, gl::kOffsetZero, sourceLevel, + gl::Box(gl::kOffsetZero, srcImageDesc.size), unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha, dstWebgpuFormat, + internalFormatInfo, sourceTextureWgpu); } angle::Result TextureWgpu::copySubTexture(const gl::Context *context, @@ -184,7 +401,86 @@ angle::Result TextureWgpu::copySubTexture(const gl::Context *context, bool unpackUnmultiplyAlpha, const gl::Texture *source) { - return angle::Result::Continue; + ContextWgpu *contextWgpu = webgpu::GetImpl(context); + TextureWgpu *sourceTextureWgpu = webgpu::GetImpl(source); + gl::TextureTarget target = index.getTarget(); + gl::LevelIndex dstLevelGL(index.getLevelIndex()); + const gl::InternalFormat &internalFormat = + *mState.getImageDesc(target, dstLevelGL.get()).format.info; + const webgpu::Format &dstWebgpuFormat = + contextWgpu->getFormat(internalFormat.sizedInternalFormat); + const gl::ImageDesc &srcImageDesc = sourceTextureWgpu->mState.getImageDesc( + NonCubeTextureTypeToTarget(source->getType()), sourceLevel); + + // TODO(crbug.com/438268609): Remove this and implement path to initialize the destination image + // then stage a copy update. + if (!mImage->isInitialized()) + { + ANGLE_TRY(initializeImageImpl(contextWgpu, dstWebgpuFormat, index.getLevelIndex() + 1, + gl::LevelIndex(sourceLevel), srcImageDesc.size)); + mImage->removeStagedUpdates(dstLevelGL); + } + return copySubTextureImpl(context, index, destOffset, sourceLevel, sourceBox, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha, dstWebgpuFormat, + internalFormat, sourceTextureWgpu); +} + +angle::Result TextureWgpu::copySubTextureImpl(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Offset &destOffset, + GLint sourceLevel, + const gl::Box &sourceBox, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const webgpu::Format &dstWebgpuFormat, + const gl::InternalFormat &internalFormat, + TextureWgpu *sourceTextureWgpu) +{ + ContextWgpu *contextWgpu = webgpu::GetImpl(context); + // We need to ensure both that the source texture is initialized and any updates to it are + // staged so we are not copying from a blank texture. + ANGLE_TRY(sourceTextureWgpu->ensureImageInitialized(context)); + ANGLE_TRY(sourceTextureWgpu->getImage()->flushStagedUpdates(contextWgpu)); + if (CanCopyWithTransferForCopyTexture( + contextWgpu, *sourceTextureWgpu->getImage(), dstWebgpuFormat.getIntendedFormatID(), + dstWebgpuFormat.getActualImageFormatID(), mImage->getUsage(), unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha)) + { + return mImage->CopyImage(contextWgpu, sourceTextureWgpu->getImage(), index, destOffset, + gl::LevelIndex(sourceLevel), static_cast(sourceBox.z), + sourceBox); + } + + if (CanCopyWithDraw(*sourceTextureWgpu->getImage(), mImage->getUsage())) + { + webgpu::TextureViewHandle srcView; + ANGLE_TRY(sourceTextureWgpu->getImage()->createTextureViewSingleLevel( + gl::LevelIndex(sourceLevel), 0, srcView)); + webgpu::TextureViewHandle dstView; + ANGLE_TRY(mImage->createTextureViewSingleLevel(gl::LevelIndex(index.getLevelIndex()), 0, + dstView)); + + WGPUExtent3D srcSize = sourceTextureWgpu->getImage()->getTextureDescriptor().size; + WGPUExtent3D dstSize = mImage->getTextureDescriptor().size; + const angle::Format &srcFormat = + sourceTextureWgpu->getBaseLevelFormat(contextWgpu).getIntendedFormat(); + + gl::Rectangle sourceRect(sourceBox.x, sourceBox.y, sourceBox.width, sourceBox.height); + + return contextWgpu->getUtils()->copyImage( + contextWgpu, srcView, dstView, sourceRect, destOffset, srcSize, dstSize, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha, false, unpackFlipY, srcFormat, + dstWebgpuFormat.getIntendedFormatID(), dstWebgpuFormat.getActualImageFormatID()); + } + + const gl::ImageDesc &srcImageDesc = sourceTextureWgpu->mState.getImageDesc( + NonCubeTextureTypeToTarget(sourceTextureWgpu->mState.getType()), + gl::LevelIndex(sourceLevel).get()); + return mImage->copyImageCpuReadback( + context, index, gl::Rectangle(sourceBox.x, sourceBox.y, sourceBox.width, sourceBox.height), + destOffset, gl::Extents(sourceBox.width, sourceBox.height, sourceBox.depth), internalFormat, + sourceTextureWgpu->getImage(), srcImageDesc.size); } angle::Result TextureWgpu::copyRenderbufferSubData(const gl::Context *context, @@ -254,6 +550,10 @@ angle::Result TextureWgpu::setEGLImageTarget(const gl::Context *context, gl::TextureType type, egl::Image *image) { + ImageWgpu *imageWgpu = webgpu::GetImpl(image); + setImageHelper(imageWgpu->getImage(), false); + ASSERT(mImage->isInitialized()); + return angle::Result::Continue; } @@ -363,6 +663,27 @@ angle::Result TextureWgpu::getAttachmentRenderTarget(const gl::Context *context, return angle::Result::Continue; } +void TextureWgpu::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) +{ + ASSERT(index == kTextureImageSubjectIndex && + (message == angle::SubjectMessage::SubjectChanged || + message == angle::SubjectMessage::InitializationComplete)); + + // Forward the notification to the parent that the staging buffer changed. + onStateChange(message); +} + +angle::Result TextureWgpu::ensureImageInitialized(const gl::Context *context) +{ + return initializeImage(webgpu::GetImpl(context), ImageMipLevels::EnabledLevels); +} + +void TextureWgpu::releaseOwnershipOfImage(const gl::Context *context) +{ + mOwnsImage = false; + setImageHelper(nullptr, true); +} + angle::Result TextureWgpu::setImageImpl(const gl::Context *context, GLenum internalFormat, GLenum type, @@ -415,6 +736,7 @@ angle::Result TextureWgpu::setSubImageImpl(const gl::Context *context, uint32_t outputDepthPitch = outputRowPitch * glExtents.height; uint32_t allocationSize = outputDepthPitch * glExtents.depth; + // TODO(anglebug.com/389145696): ignores area.x|y|z ANGLE_TRY(mImage->stageTextureUpload(contextWgpu, webgpuFormat, type, glExtents, inputRowPitch, inputDepthPitch, outputRowPitch, outputDepthPitch, allocationSize, index, pixels)); @@ -427,21 +749,43 @@ angle::Result TextureWgpu::initializeImage(ContextWgpu *contextWgpu, ImageMipLev { return angle::Result::Continue; } - const webgpu::Format &webgpuFormat = getBaseLevelFormat(contextWgpu); - DisplayWgpu *displayWgpu = contextWgpu->getDisplay(); - const gl::ImageDesc *firstLevelDesc = &mState.getBaseLevelDesc(); - uint32_t levelCount = getMipLevelCount(mipLevels); - gl::LevelIndex firstLevel = gl::LevelIndex(mState.getEffectiveBaseLevel()); - const gl::Extents &firstLevelExtents = firstLevelDesc->size; - wgpu::TextureDimension textureDimension = gl_wgpu::getWgpuTextureDimension(mState.getType()); - wgpu::TextureUsage textureUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst | - wgpu::TextureUsage::RenderAttachment | - wgpu::TextureUsage::TextureBinding; + + const gl::ImageDesc *firstLevelDesc = &mState.getBaseLevelDesc(); + uint32_t levelCount = getMipLevelCount(mipLevels); + gl::LevelIndex firstLevel = gl::LevelIndex(mState.getEffectiveBaseLevel()); + + const webgpu::Format &webgpuFormat = getBaseLevelFormat(contextWgpu); + return initializeImageImpl(contextWgpu, webgpuFormat, levelCount, firstLevel, + firstLevelDesc->size); +} + +angle::Result TextureWgpu::initializeImageImpl(ContextWgpu *contextWgpu, + const webgpu::Format &webgpuFormat, + uint32_t levelCount, + gl::LevelIndex firstLevel, + const gl::Extents &size) +{ + const DawnProcTable *wgpu = webgpu::GetProcs(contextWgpu); + + DisplayWgpu *displayWgpu = contextWgpu->getDisplay(); + WGPUExtent3D wgpuExtents = gl_wgpu::GetExtent3D(size); + WGPUTextureDimension textureDimension = gl_wgpu::GetWgpuTextureDimension(mState.getType()); + WGPUTextureUsage textureUsage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | + WGPUTextureUsage_RenderAttachment | + WGPUTextureUsage_TextureBinding; + + if (mState.getType() == gl::TextureType::CubeMap) + { + ASSERT(wgpuExtents.depthOrArrayLayers == 1); + ASSERT(wgpuExtents.width == wgpuExtents.height); + wgpuExtents.depthOrArrayLayers = 6; + } + return mImage->initImage( - webgpuFormat.getIntendedFormatID(), webgpuFormat.getActualImageFormatID(), + wgpu, webgpuFormat.getIntendedFormatID(), webgpuFormat.getActualImageFormatID(), displayWgpu->getDevice(), firstLevel, mImage->createTextureDescriptor( - textureUsage, textureDimension, gl_wgpu::getExtent3D(firstLevelExtents), + textureUsage, textureDimension, wgpuExtents, webgpu::GetWgpuTextureFormatFromFormatID(webgpuFormat.getActualImageFormatID()), levelCount, 1)); } @@ -451,14 +795,23 @@ angle::Result TextureWgpu::redefineLevel(const gl::Context *context, const gl::ImageIndex &index, const gl::Extents &size) { - if (mImage != nullptr) + + if (mImage != nullptr && mOwnsImage) { - // If there are any staged changes for this index, we can remove them since we're going to - // override them with this call. + // If there are any staged changes for this index, we can remove them since we're going + // to override them with this call. gl::LevelIndex levelIndexGL(index.getLevelIndex()); - // Multilayer images are not yet supported. - const uint32_t layerIndex = 0; - mImage->removeStagedUpdates(levelIndexGL); + const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0; + + if (index.hasLayer()) + { + mImage->removeSingleSubresourceStagedUpdates(levelIndexGL, layerIndex, + index.getLayerCount()); + } + else + { + mImage->removeStagedUpdates(levelIndexGL); + } if (mImage->isInitialized()) { @@ -474,13 +827,13 @@ angle::Result TextureWgpu::redefineLevel(const gl::Context *context, mImage->getLevelCount(), layerIndex, index, mImage->getFirstAllocatedLevel(), &mRedefinedLevels)) { - mImage->resetImage(); + resetImageAndReleaseViews(); } } } else { - mImage = new webgpu::ImageHelper; + setImageHelper(new webgpu::ImageHelper, true); } return angle::Result::Continue; @@ -546,7 +899,7 @@ angle::Result TextureWgpu::respecifyImageStorageIfNecessary(ContextWgpu *context { ANGLE_TRY(mImage->flushStagedUpdates(contextWgpu)); - mImage->resetImage(); + resetImageAndReleaseViews(); } // Also recreate the image if it's changed in usage, or if any of its levels are redefined and @@ -557,7 +910,7 @@ angle::Result TextureWgpu::respecifyImageStorageIfNecessary(ContextWgpu *context { ANGLE_TRY(mImage->flushStagedUpdates(contextWgpu)); - mImage->resetImage(); + resetImageAndReleaseViews(); } return angle::Result::Continue; @@ -585,7 +938,7 @@ void TextureWgpu::prepareForGenerateMipmap(ContextWgpu *contextWgpu) if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), baseLevel)) { ASSERT(!mState.getImmutableFormat()); - mImage->resetImage(); + resetImageAndReleaseViews(); } } @@ -624,7 +977,7 @@ angle::Result TextureWgpu::maybeUpdateBaseMaxLevels(ContextWgpu *contextWgpu) else { // TODO(liza): Respecify the image once copying images is supported. - mImage->resetImage(); + resetImageAndReleaseViews(); return angle::Result::Continue; } @@ -661,8 +1014,8 @@ angle::Result TextureWgpu::initSingleLayerRenderTargets( for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) { - wgpu::TextureView textureView; - ANGLE_TRY(mImage->createTextureView(levelIndex, layerIndex, textureView)); + webgpu::TextureViewHandle textureView; + ANGLE_TRY(mImage->createTextureViewSingleLevel(levelIndex, layerIndex, textureView)); renderTargets[layerIndex].set(mImage, textureView, mImage->toWgpuLevel(levelIndex), layerIndex, mImage->toWgpuTextureFormat()); @@ -677,4 +1030,36 @@ const webgpu::Format &TextureWgpu::getBaseLevelFormat(ContextWgpu *contextWgpu) return contextWgpu->getFormat(baseLevelDesc.format.info->sizedInternalFormat); } +void TextureWgpu::setImageHelper(webgpu::ImageHelper *imageHelper, bool ownsImageHelper) +{ + if (mOwnsImage && mImage) + { + mImageObserverBinding.bind(nullptr); + SafeDelete(mImage); + } + + mImage = imageHelper; + mOwnsImage = ownsImageHelper; + + if (mImage) + { + mImageObserverBinding.bind(mImage); + } + + onStateChange(angle::SubjectMessage::SubjectChanged); +} + +void TextureWgpu::resetImageAndReleaseViews() +{ + for (auto &renderTargets : mSingleLayerRenderTargets) + { + for (auto &levelRenderTargets : renderTargets) + { + levelRenderTargets.clear(); + } + renderTargets.clear(); + } + mImage->resetImage(); +} + } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/TextureWgpu.h b/src/libANGLE/renderer/wgpu/TextureWgpu.h index 9424d7e5672..d8658d53351 100644 --- a/src/libANGLE/renderer/wgpu/TextureWgpu.h +++ b/src/libANGLE/renderer/wgpu/TextureWgpu.h @@ -17,12 +17,15 @@ namespace rx { -class TextureWgpu : public TextureImpl + +class TextureWgpu : public TextureImpl, public angle::ObserverInterface { public: TextureWgpu(const gl::TextureState &state); ~TextureWgpu() override; + void onDestroy(const gl::Context *context) override; + angle::Result setImage(const gl::Context *context, const gl::ImageIndex &index, GLenum internalFormat, @@ -171,7 +174,14 @@ class TextureWgpu : public TextureImpl GLsizei samples, FramebufferAttachmentRenderTarget **rtOut) override; - webgpu::ImageHelper *getImage() { return mImage; } + angle::Result ensureImageInitialized(const gl::Context *context); + + void releaseOwnershipOfImage(const gl::Context *context); + webgpu::ImageHelper *getImage() const { return mImage; } + + // We monitor the ImageHelper and set dirty bits if the ImageHelper changes. This can + // support changes in the ImageHelper even outside the TextureWgpu class. + void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; private: angle::Result setImageImpl(const gl::Context *context, @@ -190,7 +200,31 @@ class TextureWgpu : public TextureImpl const gl::PixelUnpackState &unpack, const uint8_t *pixels); + angle::Result copySubImageImpl(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::InternalFormat &internalFormat, + gl::Framebuffer *source); + + angle::Result copySubTextureImpl(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Offset &destOffset, + GLint sourceLevel, + const gl::Box &sourceBox, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const webgpu::Format &dstWebgpuFormat, + const gl::InternalFormat &internalFormat, + TextureWgpu *sourceTextureWgpu); + angle::Result initializeImage(ContextWgpu *contextWgpu, ImageMipLevels mipLevels); + angle::Result initializeImageImpl(ContextWgpu *contextWgpu, + const webgpu::Format &webgpuFormat, + uint32_t levelCount, + gl::LevelIndex firstLevel, + const gl::Extents &size); angle::Result redefineLevel(const gl::Context *context, const webgpu::Format &webgpuFormat, @@ -209,11 +243,17 @@ class TextureWgpu : public TextureImpl gl::RenderToTextureImageIndex renderToTextureIndex); const webgpu::Format &getBaseLevelFormat(ContextWgpu *contextWgpu) const; - webgpu::ImageHelper *mImage; + void setImageHelper(webgpu::ImageHelper *imageHelper, bool ownsImageHelper); + + void resetImageAndReleaseViews(); + bool mOwnsImage = false; + webgpu::ImageHelper *mImage = nullptr; gl::LevelIndex mCurrentBaseLevel; gl::LevelIndex mCurrentMaxLevel; gl::CubeFaceArray mRedefinedLevels; + angle::ObserverBinding mImageObserverBinding; + // Render targets stored as array of vector of vectors // // - First dimension: only RenderToTextureImageIndex::Default for now. diff --git a/src/libANGLE/renderer/wgpu/UtilsWgpu.cpp b/src/libANGLE/renderer/wgpu/UtilsWgpu.cpp new file mode 100644 index 00000000000..36c8ec3aa75 --- /dev/null +++ b/src/libANGLE/renderer/wgpu/UtilsWgpu.cpp @@ -0,0 +1,316 @@ +// Copyright 2025 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. +// +// UtilsWgpu.cpp: +// Helper methods for the WebGPU backend. +// + +#include "libANGLE/renderer/wgpu/UtilsWgpu.h" + +#include +#include "libANGLE/renderer/wgpu/ContextWgpu.h" + +namespace rx +{ +namespace +{ +constexpr char kVertexEntryPoint[] = "vs_main"; +constexpr char kFragmentEntryPoint[] = "fs_main"; + +constexpr char kVertexMain[] = R"( +struct VertexInput { + @location(0) pos: vec2, + @location(1) texCoord: vec2, +}; + +struct VertexOutput { + @builtin(position) position: vec4, + @location(0) texCoord: vec2, +}; + +@vertex +fn vs_main(in: VertexInput) -> VertexOutput { + var out: VertexOutput; + out.position = vec4(in.pos, 0.0, 1.0); + out.texCoord = in.texCoord; + return out; +} +)"; + +const char *GetWgslTextureComponentTypeFromGlComponent(GLenum componentType) +{ + if (componentType == GL_INT) + { + return "i32"; + } + if (componentType == GL_UNSIGNED_INT) + { + return "u32"; + } + + return "f32"; +} + +const char *GetWgslTextureComponentTypeFromFormat(const angle::Format &format) +{ + return GetWgslTextureComponentTypeFromGlComponent(format.componentType); +} + +} // namespace + +namespace webgpu +{ + +UtilsWgpu::UtilsWgpu() = default; + +UtilsWgpu::~UtilsWgpu() = default; + +webgpu::ShaderModuleHandle UtilsWgpu::getCopyShaderModule(ContextWgpu *context, const CopyKey &key) +{ + std::stringstream ss; + + const angle::Format &dstFormat = angle::Format::Get(key.dstActualFormatID); + + ss << kVertexMain; + ss << "@group(0) @binding(0)\n var t_source: texture_2d<" + << GetWgslTextureComponentTypeFromGlComponent(key.srcComponentType) << ">;\n"; + + ss << "@fragment\nfn " << kFragmentEntryPoint + << "(in: VertexOutput) -> @location(0) " + "vec4<" + << GetWgslTextureComponentTypeFromFormat(dstFormat) << "> {\n"; + ss << " var srcValue = textureLoad(t_source, vec2(floor(in.texCoord)), 0);\n"; + ss << " var out_rgb = srcValue.rgb;\n"; + if (key.premultiplyAlpha && !key.unmultiplyAlpha) + { + ss << " out_rgb = out_rgb * srcValue.a;\n"; + } + else if (key.unmultiplyAlpha && !key.premultiplyAlpha) + { + ss << " if (srcValue.a > 0.0) {\n"; + ss << " out_rgb = out_rgb / srcValue.a;\n"; + ss << " }\n"; + } + ss << " var out_a = srcValue.a;\n"; + if (!key.dstIntentedFormatHasAlphaBits) + { + ss << " out_a = 1.0;\n"; + } + ss << " return vec4<" << GetWgslTextureComponentTypeFromFormat(dstFormat) + << ">(out_rgb, out_a);\n"; + ss << "}\n"; + return getShaderModule(context, ss.str()); +} + +webgpu::ShaderModuleHandle UtilsWgpu::getShaderModule(ContextWgpu *context, + const std::string &shaderSource) +{ + WGPUShaderSourceWGSL wgslDesc = WGPU_SHADER_SOURCE_WGSL_INIT; + wgslDesc.code = {shaderSource.c_str(), shaderSource.length()}; + + WGPUShaderModuleDescriptor shaderModuleDescriptor = WGPU_SHADER_MODULE_DESCRIPTOR_INIT; + shaderModuleDescriptor.nextInChain = &wgslDesc.chain; + + const DawnProcTable *wgpu = webgpu::GetProcs(context); + return webgpu::ShaderModuleHandle::Acquire( + wgpu, wgpu->deviceCreateShaderModule(context->getDevice().get(), &shaderModuleDescriptor)); +} + +angle::Result UtilsWgpu::getPipeline(ContextWgpu *context, + const CopyKey &key, + const webgpu::ShaderModuleHandle &shader, + CachedPipeline *cachedPipelineOut) +{ + webgpu::ShaderModuleHandle shaderModule = shader; + + WGPURenderPipelineDescriptor pipelineDesc = WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT; + pipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleStrip; + pipelineDesc.multisample.count = 1; + + WGPUVertexAttribute attributes[2] = {}; + attributes[0].format = WGPUVertexFormat_Float32x2; + attributes[0].offset = offsetof(CopyVertex, position); + attributes[0].shaderLocation = 0; + attributes[1].format = WGPUVertexFormat_Float32x2; + attributes[1].offset = offsetof(CopyVertex, texCoord); + attributes[1].shaderLocation = 1; + + WGPUVertexBufferLayout vertexBufferLayout = {}; + vertexBufferLayout.arrayStride = sizeof(CopyVertex); + vertexBufferLayout.attributeCount = 2; + vertexBufferLayout.attributes = attributes; + + pipelineDesc.vertex.bufferCount = 1; + pipelineDesc.vertex.buffers = &vertexBufferLayout; + pipelineDesc.vertex.module = shaderModule.get(); + pipelineDesc.vertex.entryPoint = {kVertexEntryPoint, sizeof(kVertexEntryPoint) - 1}; + + WGPUFragmentState fragmentState = WGPU_FRAGMENT_STATE_INIT; + fragmentState.module = shaderModule.get(); + fragmentState.entryPoint = {kFragmentEntryPoint, sizeof(kFragmentEntryPoint) - 1}; + WGPUColorTargetState colorTargetState = WGPU_COLOR_TARGET_STATE_INIT; + colorTargetState.format = webgpu::GetWgpuTextureFormatFromFormatID(key.dstActualFormatID); + fragmentState.targetCount = 1; + fragmentState.targets = &colorTargetState; + pipelineDesc.fragment = &fragmentState; + + WGPUBindGroupLayoutEntry bglEntry = WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT; + bglEntry.binding = 0; + bglEntry.visibility = WGPUShaderStage_Fragment; + bglEntry.texture.viewDimension = WGPUTextureViewDimension_2D; + + if (key.srcComponentType == GL_INT) + { + bglEntry.texture.sampleType = WGPUTextureSampleType_Sint; + } + else if (key.srcComponentType == GL_UNSIGNED_INT) + { + bglEntry.texture.sampleType = WGPUTextureSampleType_Uint; + } + else + { + bglEntry.texture.sampleType = WGPUTextureSampleType_Float; + } + + WGPUBindGroupLayoutDescriptor bglDesc = WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT; + bglDesc.entryCount = 1; + bglDesc.entries = &bglEntry; + + WGPUDevice device = context->getDevice().get(); + const DawnProcTable *wgpu = webgpu::GetProcs(context); + webgpu::BindGroupLayoutHandle bindGroupLayout; + bindGroupLayout = webgpu::BindGroupLayoutHandle::Acquire( + wgpu, wgpu->deviceCreateBindGroupLayout(device, &bglDesc)); + + WGPUPipelineLayoutDescriptor plDesc = WGPU_PIPELINE_LAYOUT_DESCRIPTOR_INIT; + plDesc.bindGroupLayoutCount = 1; + plDesc.bindGroupLayouts = &bindGroupLayout.get(); + webgpu::PipelineLayoutHandle pipelineLayout; + pipelineLayout = webgpu::PipelineLayoutHandle::Acquire( + wgpu, wgpu->deviceCreatePipelineLayout(device, &plDesc)); + pipelineDesc.layout = pipelineLayout.get(); + + cachedPipelineOut->pipeline = webgpu::RenderPipelineHandle::Acquire( + wgpu, wgpu->deviceCreateRenderPipeline(device, &pipelineDesc)); + cachedPipelineOut->bindGroupLayout = std::move(bindGroupLayout); + + return angle::Result::Continue; +} + +angle::Result UtilsWgpu::copyImage(ContextWgpu *context, + webgpu::TextureViewHandle src, + webgpu::TextureViewHandle dst, + const gl::Rectangle &sourceArea, + const gl::Offset &destOffset, + const WGPUExtent3D &srcSize, + const WGPUExtent3D &dstSize, + bool premultiplyAlpha, + bool unmultiplyAlpha, + bool srcFlipY, + bool dstFlipY, + const angle::Format &srcFormat, + angle::FormatID dstIntendedFormatID, + angle::FormatID dstActualFormatID) +{ + const DawnProcTable *wgpu = webgpu::GetProcs(context); + const angle::Format &dstIntendedFormat = angle::Format::Get(dstIntendedFormatID); + CopyKey key = {}; + key.op = WgpuPipelineOp::ImageCopy; + key.srcComponentType = srcFormat.componentType; + key.dstActualFormatID = dstActualFormatID; + key.dstIntentedFormatHasAlphaBits = dstIntendedFormat.alphaBits != 0; + key.premultiplyAlpha = premultiplyAlpha; + key.unmultiplyAlpha = unmultiplyAlpha; + key.srcFlipY = srcFlipY; + key.dstFlipY = dstFlipY; + + const CachedPipeline *cachedPipeline = nullptr; + auto it = mCopyPipelineCache.find(key); + if (it != mCopyPipelineCache.end()) + { + cachedPipeline = &it->second; + } + else + { + webgpu::ShaderModuleHandle shaderModule = getCopyShaderModule(context, key); + CachedPipeline newCachedPipeline; + ANGLE_TRY(getPipeline(context, key, shaderModule, &newCachedPipeline)); + auto inserted = mCopyPipelineCache.emplace(key, std::move(newCachedPipeline)); + cachedPipeline = &inserted.first->second; + } + + WGPUBindGroupDescriptor bgDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT; + WGPUBindGroupEntry bgEntry = WGPU_BIND_GROUP_ENTRY_INIT; + bgEntry.binding = 0; + bgEntry.textureView = src.get(); + bgDesc.entryCount = 1; + bgDesc.entries = &bgEntry; + bgDesc.layout = cachedPipeline->bindGroupLayout.get(); + + webgpu::BindGroupHandle bindGroup; + bindGroup = webgpu::BindGroupHandle::Acquire( + wgpu, wgpu->deviceCreateBindGroup(context->getDevice().get(), &bgDesc)); + + webgpu::PackedRenderPassDescriptor renderPassDesc; + webgpu::PackedRenderPassColorAttachment colorAttachment; + colorAttachment.view = dst; + colorAttachment.loadOp = WGPULoadOp_Load; + colorAttachment.storeOp = WGPUStoreOp_Store; + colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; + renderPassDesc.colorAttachments.push_back(colorAttachment); + ANGLE_TRY(context->endRenderPass(webgpu::RenderPassClosureReason::CopyImage)); + ANGLE_TRY(context->startRenderPass(renderPassDesc)); + + float dstX1 = destOffset.x; + float dstY1 = destOffset.y; + float dstX2 = destOffset.x + sourceArea.width; + float dstY2 = destOffset.y + sourceArea.height; + + float srcX1 = sourceArea.x; + float srcY1 = sourceArea.y; + float srcX2 = sourceArea.x + sourceArea.width; + float srcY2 = sourceArea.y + sourceArea.height; + + if (srcFlipY != dstFlipY) + { + std::swap(srcY1, srcY2); + } + + // WebGPU's texture coordinate system has (0,0) in the top-left corner. + // Normalized device coordinates (NDC) has y pointing up. + // The following vertex positions are in NDC. The viewport is not flipped. + float dstNormX1 = dstX1 / dstSize.width * 2.0f - 1.0f; + float dstNormY1 = -(dstY1 / dstSize.height * 2.0f - 1.0f); + float dstNormX2 = dstX2 / dstSize.width * 2.0f - 1.0f; + float dstNormY2 = -(dstY2 / dstSize.height * 2.0f - 1.0f); + + webgpu::CommandBuffer &commandBuffer = context->getCommandBuffer(); + commandBuffer.setPipeline(cachedPipeline->pipeline); + commandBuffer.setBindGroup(0, bindGroup); + CopyVertex vertices[4] = { + {{dstNormX1, dstNormY2}, {srcX1, srcY2}}, + {{dstNormX2, dstNormY2}, {srcX2, srcY2}}, + {{dstNormX1, dstNormY1}, {srcX1, srcY1}}, + {{dstNormX2, dstNormY1}, {srcX2, srcY1}}, + }; + + WGPUBufferDescriptor bufferDesc = {}; + bufferDesc.size = sizeof(vertices); + bufferDesc.usage = WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst; + webgpu::BufferHandle vertexBuffer = webgpu::BufferHandle::Acquire( + wgpu, wgpu->deviceCreateBuffer(context->getDevice().get(), &bufferDesc)); + + wgpu->queueWriteBuffer(context->getQueue().get(), vertexBuffer.get(), 0, vertices, + sizeof(vertices)); + commandBuffer.setVertexBuffer(0, vertexBuffer, 0, sizeof(vertices)); + + commandBuffer.draw(4, 1, 0, 0); + + ANGLE_TRY(context->endRenderPass(webgpu::RenderPassClosureReason::CopyImage)); + + return angle::Result::Continue; +} + +} // namespace webgpu +} // namespace rx diff --git a/src/libANGLE/renderer/wgpu/UtilsWgpu.h b/src/libANGLE/renderer/wgpu/UtilsWgpu.h new file mode 100644 index 00000000000..78d57a55bc5 --- /dev/null +++ b/src/libANGLE/renderer/wgpu/UtilsWgpu.h @@ -0,0 +1,96 @@ +// Copyright 2025 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. +// +// UtilsWgpu.h: +// Defines the UtilsWgpu class, a helper class for image copies with a draw. + +#ifndef LIBANGLE_RENDERER_WGPU_UTILSWGPU_H_ +#define LIBANGLE_RENDERER_WGPU_UTILSWGPU_H_ + +#include +#include +#include "libANGLE/renderer/Format.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" + +namespace rx +{ +class ContextWgpu; +namespace webgpu +{ + +enum class WgpuPipelineOp : uint8_t +{ + ImageCopy, +}; + +struct CopyVertex +{ + float position[2]; + float texCoord[2]; +}; + +struct CopyKey +{ + GLenum srcComponentType; + angle::FormatID dstActualFormatID; + WgpuPipelineOp op; + bool dstIntentedFormatHasAlphaBits; + bool premultiplyAlpha; + bool unmultiplyAlpha; + bool srcFlipY; + bool dstFlipY; + + bool operator<(const CopyKey &other) const + { + return std::tie(op, srcComponentType, dstActualFormatID, dstIntentedFormatHasAlphaBits, + premultiplyAlpha, unmultiplyAlpha, srcFlipY, dstFlipY) < + std::tie(other.op, other.srcComponentType, other.dstActualFormatID, + other.dstIntentedFormatHasAlphaBits, other.premultiplyAlpha, + other.unmultiplyAlpha, other.srcFlipY, other.dstFlipY); + } +}; + +struct CachedPipeline +{ + webgpu::RenderPipelineHandle pipeline; + webgpu::BindGroupLayoutHandle bindGroupLayout; +}; + +class UtilsWgpu : angle::NonCopyable +{ + public: + UtilsWgpu(); + ~UtilsWgpu(); + + angle::Result copyImage(ContextWgpu *context, + webgpu::TextureViewHandle src, + webgpu::TextureViewHandle dst, + const gl::Rectangle &sourceArea, + const gl::Offset &destOffset, + const WGPUExtent3D &srcSize, + const WGPUExtent3D &dstSize, + bool premultiplyAlpha, + bool unmultiplyAlpha, + bool srcFlipY, + bool dstFlipY, + const angle::Format &srcFormat, + angle::FormatID dstIntendedFormatID, + angle::FormatID dstActualFormatID); + + private: + webgpu::ShaderModuleHandle getCopyShaderModule(ContextWgpu *context, const CopyKey &key); + webgpu::ShaderModuleHandle getShaderModule(ContextWgpu *context, const std::string &shader); + + angle::Result getPipeline(ContextWgpu *context, + const CopyKey &key, + const webgpu::ShaderModuleHandle &shader, + CachedPipeline *cachedPipelineOut); + + std::map mCopyPipelineCache; +}; + +} // namespace webgpu +} // namespace rx + +#endif // LIBANGLE_RENDERER_WGPU_UTILSWGPU_H_ diff --git a/src/libANGLE/renderer/wgpu/VertexArrayWgpu.cpp b/src/libANGLE/renderer/wgpu/VertexArrayWgpu.cpp index bc4fedc822c..33773e0c9e1 100644 --- a/src/libANGLE/renderer/wgpu/VertexArrayWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/VertexArrayWgpu.cpp @@ -7,10 +7,17 @@ // Implements the class methods for VertexArrayWgpu. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/VertexArrayWgpu.h" +#include "common/PackedEnums.h" #include "common/debug.h" +#include "libANGLE/Error.h" #include "libANGLE/renderer/wgpu/ContextWgpu.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" namespace rx { @@ -19,7 +26,8 @@ namespace { bool AttributeNeedsStreaming(ContextWgpu *context, const gl::VertexAttribute &attrib, - const gl::VertexBinding &binding) + const gl::VertexBinding &binding, + const gl::Buffer *bufferGl) { const size_t stride = ComputeVertexAttributeStride(attrib, binding); if (stride % 4 != 0) @@ -39,7 +47,6 @@ bool AttributeNeedsStreaming(ContextWgpu *context, return true; } - gl::Buffer *bufferGl = binding.getBuffer().get(); if (!bufferGl || bufferGl->getSize() == 0) { return true; @@ -104,7 +111,9 @@ CopyIndexFunction GetCopyIndexFunction(gl::DrawElementsType sourceType, } // namespace -VertexArrayWgpu::VertexArrayWgpu(const gl::VertexArrayState &data) : VertexArrayImpl(data) +VertexArrayWgpu::VertexArrayWgpu(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) + : VertexArrayImpl(data, vertexArrayBuffers) { // Pre-initialize mCurrentIndexBuffer to a streaming buffer because no index buffer dirty bit is // triggered if our first draw call has no buffer bound. @@ -130,9 +139,6 @@ angle::Result VertexArrayWgpu::syncState(const gl::Context *context, size_t dirtyBit = *iter; switch (dirtyBit) { - case gl::VertexArray::DIRTY_BIT_LOST_OBSERVATION: - break; - case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER: case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA: ANGLE_TRY(syncDirtyElementArrayBuffer(contextWgpu)); @@ -194,6 +200,8 @@ angle::Result VertexArrayWgpu::syncClientArrays( const void **adjustedIndicesPtr, uint32_t *indexCountOut) { + const DawnProcTable *wgpu = webgpu::GetProcs(context); + *adjustedIndicesPtr = indices; gl::AttributesMask clientAttributesToSync = @@ -202,46 +210,51 @@ angle::Result VertexArrayWgpu::syncClientArrays( gl::DrawElementsType destDrawElementsTypeOrInvalid = sourceDrawElementsTypeOrInvalid; - IndexDataNeedsStreaming indexDataNeedsStreaming = IndexDataNeedsStreaming::No; - if (sourceDrawElementsTypeOrInvalid == gl::DrawElementsType::UnsignedByte) - { - // Promote 8-bit indices to 16-bit indices - indexDataNeedsStreaming = IndexDataNeedsStreaming::Yes; - destDrawElementsTypeOrInvalid = gl::DrawElementsType::UnsignedShort; - } - else if (mode == gl::PrimitiveMode::LineLoop) - { - // Index data will always need streaming for line loop mode regardless of what type of draw - // call it is. - indexDataNeedsStreaming = IndexDataNeedsStreaming::Yes; - } - else if (sourceDrawElementsTypeOrInvalid != gl::DrawElementsType::InvalidEnum && - !mState.getElementArrayBuffer()) - { - // Index data needs to be uploaded to the GPU - indexDataNeedsStreaming = IndexDataNeedsStreaming::Yes; - } + IndexDataNeedsStreaming indexDataNeedsStreaming = determineIndexDataNeedsStreaming( + sourceDrawElementsTypeOrInvalid, count, mode, &destDrawElementsTypeOrInvalid); - if (!clientAttributesToSync.any() && indexDataNeedsStreaming == IndexDataNeedsStreaming::No) + if (!clientAttributesToSync.any() && indexDataNeedsStreaming == IndexDataNeedsStreaming::None) { return angle::Result::Continue; } - GLsizei adjustedCount = count; - if (mode == gl::PrimitiveMode::LineLoop) + gl::Buffer *elementArrayBuffer = getElementArrayBuffer(); + ContextWgpu *contextWgpu = webgpu::GetImpl(context); + webgpu::DeviceHandle device = webgpu::GetDevice(context); + const uint8_t *srcIndexData = static_cast(indices); + if (elementArrayBuffer) { - adjustedCount++; + BufferWgpu *elementArrayBufferWgpu = GetImplAs(elementArrayBuffer); + size_t sourceOffset = + rx::roundDownPow2(reinterpret_cast(indices), webgpu::kBufferMapOffsetAlignment); + ASSERT(sourceOffset < elementArrayBufferWgpu->getBuffer().actualSize()); + size_t mapReadSize = rx::roundUpPow2( + static_cast(elementArrayBufferWgpu->getBuffer().actualSize()) - sourceOffset, + webgpu::kBufferCopyToBufferAlignment); + if (!elementArrayBufferWgpu->getBuffer().isMappedForRead()) + { + ANGLE_TRY(elementArrayBufferWgpu->getBuffer().mapImmediate( + contextWgpu, WGPUMapMode_Read, sourceOffset, mapReadSize)); + } + srcIndexData = + elementArrayBufferWgpu->getBuffer().getMapReadPointer(sourceOffset, mapReadSize); } + uint32_t adjustedCount = calculateAdjustedIndexCount( + mode, primitiveRestartEnabled, destDrawElementsTypeOrInvalid, count, srcIndexData); + // If there aren't any client attributes to sync but the adjusted count is 0, that means + // there no indices outside the primitive restart index, so this is a no-op. + if (!clientAttributesToSync.any() && adjustedCount == 0) + { + return angle::Result::Continue; + } if (indexCountOut) { *indexCountOut = adjustedCount; } - ContextWgpu *contextWgpu = webgpu::GetImpl(context); - wgpu::Device device = webgpu::GetDevice(context); - - // If any attributes need to be streamed, we need to know the index range. + // If any attributes need to be streamed, we need to know the index range. We also need to know + // the index range if there is a draw arrays call and we have to stream the index data for it. std::optional indexRange; if (clientAttributesToSync.any()) { @@ -249,183 +262,102 @@ angle::Result VertexArrayWgpu::syncClientArrays( size_t vertexCount = 0; ANGLE_TRY(GetVertexRangeInfo(context, first, count, sourceDrawElementsTypeOrInvalid, indices, baseVertex, &startVertex, &vertexCount)); - indexRange = gl::IndexRange(startVertex, startVertex + vertexCount - 1, 0); + indexRange = + gl::IndexRange(startVertex, static_cast(startVertex + vertexCount - 1)); + } + else if (indexDataNeedsStreaming != IndexDataNeedsStreaming::None && + sourceDrawElementsTypeOrInvalid == gl::DrawElementsType::InvalidEnum) + { + indexRange = gl::IndexRange(first, first + count - 1); } // Pre-compute the total size of all streamed vertex and index data so a single staging buffer // can be used size_t stagingBufferSize = 0; - std::optional destIndexDataSize; - std::optional destIndexUnitSize; - gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer(); - if (indexDataNeedsStreaming == IndexDataNeedsStreaming::Yes) - { - destIndexUnitSize = - static_cast(gl::GetDrawElementsTypeSize(destDrawElementsTypeOrInvalid)); - destIndexDataSize = destIndexUnitSize.value() * adjustedCount; - - // Allocating staging buffer space for indices is only needed when there is no source index - // buffer or index data conversion is needed - if (!elementArrayBuffer || sourceDrawElementsTypeOrInvalid != destDrawElementsTypeOrInvalid) - { - stagingBufferSize += - rx::roundUpPow2(destIndexDataSize.value(), webgpu::kBufferCopyToBufferAlignment); - } - } - - const std::vector &attribs = mState.getVertexAttributes(); - const std::vector &bindings = mState.getVertexBindings(); - - if (clientAttributesToSync.any()) - { - for (size_t attribIndex : clientAttributesToSync) - { - const gl::VertexAttribute &attrib = attribs[attribIndex]; - const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; - - size_t elementCount = gl::ComputeVertexBindingElementCount( - binding.getDivisor(), indexRange->vertexCount(), instanceCount); - - const webgpu::Format &vertexFormat = - contextWgpu->getFormat(attrib.format->glInternalFormat); - size_t destTypeSize = vertexFormat.getActualBufferFormat().pixelBytes; - ASSERT(destTypeSize > 0); - - size_t attribSize = destTypeSize * elementCount; - stagingBufferSize += rx::roundUpPow2(attribSize, webgpu::kBufferCopyToBufferAlignment); - } - } + ANGLE_TRY(calculateStagingBufferSize( + contextWgpu, sourceDrawElementsTypeOrInvalid == destDrawElementsTypeOrInvalid, + primitiveRestartEnabled, indexDataNeedsStreaming, destDrawElementsTypeOrInvalid, + adjustedCount, clientAttributesToSync, instanceCount, indexRange, &stagingBufferSize)); + ASSERT(stagingBufferSize % webgpu::kBufferSizeAlignment == 0); webgpu::BufferHelper stagingBuffer; uint8_t *stagingData = nullptr; size_t currentStagingDataPosition = 0; if (stagingBufferSize > 0) { - ASSERT(stagingBufferSize > 0); ASSERT(stagingBufferSize % webgpu::kBufferSizeAlignment == 0); - ANGLE_TRY(stagingBuffer.initBuffer(device, stagingBufferSize, - wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite, + ANGLE_TRY(stagingBuffer.initBuffer(wgpu, device, stagingBufferSize, + WGPUBufferUsage_CopySrc | WGPUBufferUsage_MapWrite, webgpu::MapAtCreation::Yes)); stagingData = stagingBuffer.getMapWritePointer(0, stagingBufferSize); } - struct BufferCopy - { - uint64_t sourceOffset; - webgpu::BufferHelper *src; - webgpu::BufferHelper *dest; - uint64_t destOffset; - uint64_t size; - }; std::vector stagingUploads; - if (indexDataNeedsStreaming == IndexDataNeedsStreaming::Yes) + if (indexDataNeedsStreaming != IndexDataNeedsStreaming::None) { // Indices are streamed to the start of the buffer. Tell the draw call command to use 0 for // firstIndex. *adjustedIndicesPtr = 0; - ASSERT(destIndexDataSize.has_value()); - ASSERT(destIndexUnitSize.has_value()); - + size_t destIndexDataSize = + static_cast(gl::GetDrawElementsTypeSize(destDrawElementsTypeOrInvalid)) * + adjustedCount; size_t destIndexBufferSize = - rx::roundUpPow2(destIndexDataSize.value(), webgpu::kBufferCopyToBufferAlignment); + rx::roundUpPow2(destIndexDataSize, webgpu::kBufferCopyToBufferAlignment); ANGLE_TRY(ensureBufferCreated(context, mStreamingIndexBuffer, destIndexBufferSize, 0, - wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Index, + WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index, BufferType::IndexBuffer)); - if (sourceDrawElementsTypeOrInvalid == destDrawElementsTypeOrInvalid && elementArrayBuffer) - { - // Use the element array buffer as the source for the new streaming index buffer. This - // condition is only hit when an indexed draw call has an element array buffer and is - // trying to draw line loops. - - // When using an element array buffer, 'indices' is an offset to the first element. - size_t sourceOffset = reinterpret_cast(indices); - BufferWgpu *elementArrayBufferWgpu = GetImplAs(elementArrayBuffer); - webgpu::BufferHelper *sourceBuffer = &elementArrayBufferWgpu->getBuffer(); - - size_t copySize = rx::roundUpPow2(destIndexUnitSize.value() * count, - webgpu::kBufferCopyToBufferAlignment); - stagingUploads.push_back( - {sourceOffset, sourceBuffer, &mStreamingIndexBuffer, 0, copySize}); - - if (mode == gl::PrimitiveMode::LineLoop) - { - // Emulate line loops with an additional copy of the first index at the end of the - // buffer - size_t lastOffset = copySize; - stagingUploads.push_back({sourceOffset, sourceBuffer, &mStreamingIndexBuffer, - lastOffset, - rx::roundUpPow2(destIndexUnitSize.value(), - webgpu::kBufferCopyToBufferAlignment)}); - } - } - else + switch (indexDataNeedsStreaming) { - const uint8_t *srcIndexData = static_cast(indices); - - webgpu::BufferReadback readbackBuffer; - if (mState.getElementArrayBuffer()) - { - webgpu::BufferHelper &srcBuffer = - webgpu::GetImpl(mState.getElementArrayBuffer())->getBuffer(); - - const GLuint srcIndexTypeSize = - gl::GetDrawElementsTypeSize(sourceDrawElementsTypeOrInvalid); - const size_t srcIndexOffset = reinterpret_cast(indices); - - ANGLE_TRY(srcBuffer.readDataImmediate( - contextWgpu, srcIndexOffset, count * srcIndexTypeSize, - webgpu::RenderPassClosureReason::IndexRangeReadback, &readbackBuffer)); - srcIndexData = readbackBuffer.data; - } - - CopyIndexFunction indexCopyFunction = GetCopyIndexFunction( - sourceDrawElementsTypeOrInvalid, destDrawElementsTypeOrInvalid); - ASSERT(stagingData != nullptr); - indexCopyFunction(srcIndexData, count, stagingData + currentStagingDataPosition); - - if (mode == gl::PrimitiveMode::LineLoop) - { - indexCopyFunction( - srcIndexData, count, - stagingData + currentStagingDataPosition + (destIndexUnitSize.value() * count)); - } - - size_t copySize = destIndexBufferSize; - stagingUploads.push_back( - {currentStagingDataPosition, &stagingBuffer, &mStreamingIndexBuffer, 0, copySize}); - currentStagingDataPosition += copySize; + case IndexDataNeedsStreaming::LineLoopStreaming: + ANGLE_TRY(streamIndicesLineLoop( + contextWgpu, sourceDrawElementsTypeOrInvalid, destDrawElementsTypeOrInvalid, + count, adjustedCount, indices, primitiveRestartEnabled, stagingData, + destIndexBufferSize, indexRange, srcIndexData, &stagingBuffer, &stagingUploads, + ¤tStagingDataPosition)); + break; + case IndexDataNeedsStreaming::TriangleFanStreaming: + UNIMPLEMENTED(); + break; + case IndexDataNeedsStreaming::NonEmulatedStreaming: + ANGLE_TRY(streamIndicesDefault(contextWgpu, sourceDrawElementsTypeOrInvalid, + destDrawElementsTypeOrInvalid, mode, count, indices, + stagingData, destIndexBufferSize, &stagingBuffer, + &stagingUploads, ¤tStagingDataPosition)); + break; + default: + NOTREACHED(); + break; } - // TODO(anglebug.com/383356846): add support for primitive restarts and line loop draw - // arrays. } + const std::vector &attribs = mState.getVertexAttributes(); + const std::vector &bindings = mState.getVertexBindings(); for (size_t attribIndex : clientAttributesToSync) { const gl::VertexAttribute &attrib = attribs[attribIndex]; const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; + const gl::Buffer *buffer = getVertexArrayBuffer(attrib.bindingIndex); size_t streamedVertexCount = gl::ComputeVertexBindingElementCount( binding.getDivisor(), indexRange->vertexCount(), instanceCount); - const size_t sourceStride = ComputeVertexAttributeStride(attrib, binding); + const size_t sourceStride = ComputeVertexAttributeStride(attrib, binding); const size_t sourceTypeSize = gl::ComputeVertexAttributeTypeSize(attrib); // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing // a non-instanced draw call - const size_t firstIndex = (binding.getDivisor() == 0) ? indexRange->start : 0; + const size_t firstIndex = (binding.getDivisor() == 0) ? indexRange->start() : 0; // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state. // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt const uint8_t *inputPointer = static_cast(attrib.pointer); webgpu::BufferReadback readbackBuffer; - if (binding.getBuffer().get()) + if (buffer) { - webgpu::BufferHelper &srcBuffer = - webgpu::GetImpl(binding.getBuffer().get())->getBuffer(); - + webgpu::BufferHelper &srcBuffer = webgpu::GetImpl(buffer)->getBuffer(); size_t sourceVertexDataSize = sourceStride * (firstIndex + streamedVertexCount - 1) + sourceTypeSize; @@ -453,7 +385,7 @@ angle::Result VertexArrayWgpu::syncClientArrays( ANGLE_TRY(ensureBufferCreated( context, mStreamingArrayBuffers[attribIndex], destCopyOffset + copySize, attribIndex, - wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Vertex, BufferType::ArrayBuffer)); + WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex, BufferType::ArrayBuffer)); stagingUploads.push_back({currentStagingDataPosition, &stagingBuffer, &mStreamingArrayBuffers[attribIndex], destCopyOffset, copySize}); @@ -465,15 +397,15 @@ angle::Result VertexArrayWgpu::syncClientArrays( { ANGLE_TRY(stagingBuffer.unmap()); } - ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::VertexArrayStreaming)); - - contextWgpu->ensureCommandEncoderCreated(); - wgpu::CommandEncoder &commandEncoder = contextWgpu->getCurrentCommandEncoder(); + webgpu::CommandEncoderHandle commandEncoder; + ANGLE_TRY(contextWgpu->getCurrentCommandEncoder( + webgpu::RenderPassClosureReason::VertexArrayStreaming, &commandEncoder)); for (const BufferCopy © : stagingUploads) { - commandEncoder.CopyBufferToBuffer(copy.src->getBuffer(), copy.sourceOffset, - copy.dest->getBuffer(), copy.destOffset, copy.size); + wgpu->commandEncoderCopyBufferToBuffer(commandEncoder.get(), copy.src->getBuffer().get(), + copy.sourceOffset, copy.dest->getBuffer().get(), + copy.destOffset, copy.size); } return angle::Result::Continue; @@ -484,7 +416,9 @@ angle::Result VertexArrayWgpu::syncDirtyAttrib(ContextWgpu *contextWgpu, const gl::VertexBinding &binding, size_t attribIndex) { - mForcedStreamingAttributes[attribIndex] = AttributeNeedsStreaming(contextWgpu, attrib, binding); + gl::Buffer *bufferGl = getVertexArrayBuffer(attrib.bindingIndex); + mForcedStreamingAttributes[attribIndex] = + AttributeNeedsStreaming(contextWgpu, attrib, binding, bufferGl); if (attrib.enabled) { @@ -500,9 +434,8 @@ angle::Result VertexArrayWgpu::syncDirtyAttrib(ContextWgpu *contextWgpu, SetBitField(mCurrentAttribs[attribIndex].offset, 0); SetBitField(mCurrentAttribs[attribIndex].stride, binding.getStride()); - gl::Buffer *bufferGl = binding.getBuffer().get(); ASSERT(bufferGl); - BufferWgpu *bufferWgpu = webgpu::GetImpl(bufferGl); + BufferWgpu *bufferWgpu = webgpu::GetImpl(bufferGl); mCurrentArrayBuffers[attribIndex].buffer = &(bufferWgpu->getBuffer()); mCurrentArrayBuffers[attribIndex].offset = reinterpret_cast(attrib.pointer); } @@ -527,7 +460,7 @@ angle::Result VertexArrayWgpu::syncDirtyAttrib(ContextWgpu *contextWgpu, angle::Result VertexArrayWgpu::syncDirtyElementArrayBuffer(ContextWgpu *contextWgpu) { - gl::Buffer *bufferGl = mState.getElementArrayBuffer(); + gl::Buffer *bufferGl = getElementArrayBuffer(); if (bufferGl) { BufferWgpu *buffer = webgpu::GetImpl(bufferGl); @@ -545,14 +478,16 @@ angle::Result VertexArrayWgpu::ensureBufferCreated(const gl::Context *context, webgpu::BufferHelper &buffer, size_t size, size_t attribIndex, - wgpu::BufferUsage usage, + WGPUBufferUsage usage, BufferType bufferType) { ContextWgpu *contextWgpu = webgpu::GetImpl(context); - if (!buffer.valid() || buffer.requestedSize() < size || buffer.getBuffer().GetUsage() != usage) + const DawnProcTable *wgpu = webgpu::GetProcs(contextWgpu); + if (!buffer.valid() || buffer.requestedSize() < size || + wgpu->bufferGetUsage(buffer.getBuffer().get()) != usage) { - wgpu::Device device = webgpu::GetDevice(context); - ANGLE_TRY(buffer.initBuffer(device, size, usage, webgpu::MapAtCreation::No)); + webgpu::DeviceHandle device = webgpu::GetDevice(context); + ANGLE_TRY(buffer.initBuffer(wgpu, device, size, usage, webgpu::MapAtCreation::No)); if (bufferType == BufferType::IndexBuffer) { @@ -572,4 +507,287 @@ angle::Result VertexArrayWgpu::ensureBufferCreated(const gl::Context *context, return angle::Result::Continue; } +IndexDataNeedsStreaming VertexArrayWgpu::determineIndexDataNeedsStreaming( + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + GLsizei count, + gl::PrimitiveMode mode, + gl::DrawElementsType *destDrawElementsTypeOrInvalidOut) +{ + if (mode == gl::PrimitiveMode::LineLoop) + { + // Promote 8-bit indices to 16-bit indices + *destDrawElementsTypeOrInvalidOut = + calculateDrawElementsType(sourceDrawElementsTypeOrInvalid, count); + return IndexDataNeedsStreaming::LineLoopStreaming; + } + else if (mode == gl::PrimitiveMode::TriangleFan) + { + *destDrawElementsTypeOrInvalidOut = + calculateDrawElementsType(sourceDrawElementsTypeOrInvalid, count); + return IndexDataNeedsStreaming::TriangleFanStreaming; + } + else if (sourceDrawElementsTypeOrInvalid != gl::DrawElementsType::InvalidEnum && + !getElementArrayBuffer()) + { + // Index data needs to be uploaded to the GPU + *destDrawElementsTypeOrInvalidOut = + calculateDrawElementsType(sourceDrawElementsTypeOrInvalid, count); + return IndexDataNeedsStreaming::NonEmulatedStreaming; + } + return IndexDataNeedsStreaming::None; +} + +uint32_t VertexArrayWgpu::calculateAdjustedIndexCount( + gl::PrimitiveMode mode, + bool primitiveRestartEnabled, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + GLsizei count, + const uint8_t *srcIndexData) +{ + if (mode == gl::PrimitiveMode::LineLoop) + { + if (primitiveRestartEnabled) + { + return GetLineLoopWithRestartIndexCount(destDrawElementsTypeOrInvalid, count, + srcIndexData); + } + return count + 1; + } + else if (mode == gl::PrimitiveMode::TriangleFan) + { + // TODO(crbug.com/401499251): implement helper to calculate the primitive restart count for + // triangle fans emulation. + if (primitiveRestartEnabled) + { + UNIMPLEMENTED(); + return count; + } + return 3 * (count - 2); + } + return count; +} + +angle::Result VertexArrayWgpu::calculateStagingBufferSize( + ContextWgpu *contextWgpu, + bool srcDestDrawElementsTypeEqual, + bool primitiveRestartEnabled, + IndexDataNeedsStreaming indexDataNeedsStreaming, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + GLsizei adjustedCountForStreamedIndices, + gl::AttributesMask clientAttributesToSync, + GLsizei instanceCount, + std::optional indexRange, + size_t *stagingBufferSizeOut) +{ + if (indexDataNeedsStreaming != IndexDataNeedsStreaming::None) + { + size_t destIndexUnitSize = + static_cast(gl::GetDrawElementsTypeSize(destDrawElementsTypeOrInvalid)); + size_t destIndexDataSize = destIndexUnitSize * adjustedCountForStreamedIndices; + // Allocating staging buffer space for indices is only needed when there is no source index + // buffer or index data conversion is needed + if (primitiveRestartEnabled || !getElementArrayBuffer() || !srcDestDrawElementsTypeEqual) + { + *stagingBufferSizeOut += + rx::roundUpPow2(destIndexDataSize, webgpu::kBufferCopyToBufferAlignment); + } + } + + const std::vector &attribs = mState.getVertexAttributes(); + const std::vector &bindings = mState.getVertexBindings(); + + if (clientAttributesToSync.any()) + { + for (size_t attribIndex : clientAttributesToSync) + { + const gl::VertexAttribute &attrib = attribs[attribIndex]; + const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; + + size_t elementCount = gl::ComputeVertexBindingElementCount( + binding.getDivisor(), indexRange->vertexCount(), instanceCount); + + const webgpu::Format &vertexFormat = + contextWgpu->getFormat(attrib.format->glInternalFormat); + size_t destTypeSize = vertexFormat.getActualBufferFormat().pixelBytes; + ASSERT(destTypeSize > 0); + + size_t attribSize = destTypeSize * elementCount; + *stagingBufferSizeOut += + rx::roundUpPow2(attribSize, webgpu::kBufferCopyToBufferAlignment); + } + } + + if (*stagingBufferSizeOut > contextWgpu->getDisplay()->getLimitsWgpu().maxBufferSize) + { + ERR() << "Staging buffer size of " << stagingBufferSizeOut + << " in sync client arrays is larger than the max buffer size " + << contextWgpu->getDisplay()->getLimitsWgpu().maxBufferSize; + return angle::Result::Stop; + } + return angle::Result::Continue; +} + +gl::DrawElementsType VertexArrayWgpu::calculateDrawElementsType( + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + GLsizei count) +{ + if (sourceDrawElementsTypeOrInvalid == gl::DrawElementsType::UnsignedByte) + { + // Promote 8-bit indices to 16-bit indices + return gl::DrawElementsType::UnsignedShort; + } + // Index data will always need streaming for line loop mode regardless of what type of draw + // call it is. + else if (sourceDrawElementsTypeOrInvalid == gl::DrawElementsType::InvalidEnum) + { + // Line loop draw array calls are emulated via indexed draw calls, so an index type must + // be set. + if (count >= std::numeric_limits::max()) + { + return gl::DrawElementsType::UnsignedInt; + } + return gl::DrawElementsType::UnsignedShort; + } + return sourceDrawElementsTypeOrInvalid; +} + +angle::Result VertexArrayWgpu::streamIndicesLineLoop( + ContextWgpu *contextWgpu, + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + GLsizei count, + GLsizei adjustedCount, + const void *indices, + bool primitiveRestartEnabled, + uint8_t *stagingData, + size_t destIndexBufferSize, + std::optional indexRange, + const uint8_t *srcIndexData, + webgpu::BufferHelper *stagingBufferPtr, + std::vector *stagingUploadsOut, + size_t *currentStagingDataPositionOut) +{ + size_t destIndexUnitSize = + static_cast(gl::GetDrawElementsTypeSize(destDrawElementsTypeOrInvalid)); + gl::Buffer *elementArrayBuffer = getElementArrayBuffer(); + // TODO(anglebug.com/401226623): Don't use the staging buffer when the adjustedCount for + // primitive restarts is count + 1. + if (primitiveRestartEnabled) + { + rx::StreamEmulatedLineLoopIndices(destDrawElementsTypeOrInvalid, count, srcIndexData, + stagingData, + /* shouldConvertUint8= */ true); + if (elementArrayBuffer) + { + BufferWgpu *elementArrayBufferWgpu = GetImplAs(elementArrayBuffer); + ANGLE_TRY(elementArrayBufferWgpu->getBuffer().unmap()); + } + stagingUploadsOut->push_back({*currentStagingDataPositionOut, stagingBufferPtr, + &mStreamingIndexBuffer, 0, destIndexBufferSize}); + } + else if (sourceDrawElementsTypeOrInvalid == destDrawElementsTypeOrInvalid && elementArrayBuffer) + { + // Use the element array buffer as the source for the new streaming index buffer. This + // condition is only hit when an indexed draw call has an element array buffer and is + // trying to draw line loops. + + // When using an element array buffer, 'indices' is an offset to the first element. + size_t sourceOffset = reinterpret_cast(indices); + BufferWgpu *elementArrayBufferWgpu = GetImplAs(elementArrayBuffer); + webgpu::BufferHelper *sourceBuffer = &elementArrayBufferWgpu->getBuffer(); + + size_t copySize = + rx::roundUpPow2(destIndexUnitSize * count, webgpu::kBufferCopyToBufferAlignment); + stagingUploadsOut->push_back( + {sourceOffset, sourceBuffer, &mStreamingIndexBuffer, 0, copySize}); + + // Emulate line loops with an additional copy of the first index at the end of the + // buffer + size_t lastOffset = copySize; + stagingUploadsOut->push_back( + {sourceOffset, sourceBuffer, &mStreamingIndexBuffer, lastOffset, + rx::roundUpPow2(destIndexUnitSize, webgpu::kBufferCopyToBufferAlignment)}); + } + // Handle emulating line loop for draw arrays calls. + else if (sourceDrawElementsTypeOrInvalid == gl::DrawElementsType::InvalidEnum) + { + ASSERT(destDrawElementsTypeOrInvalid != gl::DrawElementsType::InvalidEnum); + uint32_t clampedVertexCount = gl::clampCast(indexRange->vertexCount()); + uint32_t startVertex = static_cast(indexRange->start()); + size_t index = *currentStagingDataPositionOut; + for (uint32_t i = 0; i < clampedVertexCount; i++) + { + uint32_t copyData = startVertex + i; + memcpy(stagingData + index, ©Data, destIndexUnitSize); + index += destIndexUnitSize; + } + memcpy(stagingData + *currentStagingDataPositionOut + destIndexUnitSize * count, + &startVertex, destIndexUnitSize); + + size_t copySize = destIndexBufferSize; + stagingUploadsOut->push_back({*currentStagingDataPositionOut, stagingBufferPtr, + &mStreamingIndexBuffer, 0, copySize}); + *currentStagingDataPositionOut += copySize; + } + else + { + ANGLE_TRY(streamIndicesDefault( + contextWgpu, sourceDrawElementsTypeOrInvalid, destDrawElementsTypeOrInvalid, + gl::PrimitiveMode::LineLoop, count, indices, stagingData, destIndexBufferSize, + stagingBufferPtr, stagingUploadsOut, currentStagingDataPositionOut)); + } + return angle::Result::Continue; +} + +angle::Result VertexArrayWgpu::streamIndicesDefault( + ContextWgpu *contextWgpu, + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + gl::PrimitiveMode mode, + GLsizei count, + const void *indices, + uint8_t *stagingData, + size_t destIndexBufferSize, + webgpu::BufferHelper *stagingBufferPtr, + std::vector *stagingUploadsOut, + size_t *currentStagingDataPositionOut) +{ + size_t destIndexUnitSize = + static_cast(gl::GetDrawElementsTypeSize(destDrawElementsTypeOrInvalid)); + + webgpu::BufferReadback readbackBuffer; + const uint8_t *srcIndexData = static_cast(indices); + if (getElementArrayBuffer()) + { + webgpu::BufferHelper &srcBuffer = webgpu::GetImpl(getElementArrayBuffer())->getBuffer(); + + const GLuint srcIndexTypeSize = + gl::GetDrawElementsTypeSize(sourceDrawElementsTypeOrInvalid); + const size_t srcIndexOffset = reinterpret_cast(indices); + + ANGLE_TRY(srcBuffer.readDataImmediate(contextWgpu, srcIndexOffset, count * srcIndexTypeSize, + webgpu::RenderPassClosureReason::IndexRangeReadback, + &readbackBuffer)); + srcIndexData = readbackBuffer.data; + } + + CopyIndexFunction indexCopyFunction = + GetCopyIndexFunction(sourceDrawElementsTypeOrInvalid, destDrawElementsTypeOrInvalid); + ASSERT(stagingData != nullptr); + indexCopyFunction(srcIndexData, count, stagingData + *currentStagingDataPositionOut); + + if (mode == gl::PrimitiveMode::LineLoop) + { + indexCopyFunction( + srcIndexData, count, + stagingData + *currentStagingDataPositionOut + (destIndexUnitSize * count)); + } + + size_t copySize = destIndexBufferSize; + stagingUploadsOut->push_back( + {*currentStagingDataPositionOut, stagingBufferPtr, &mStreamingIndexBuffer, 0, copySize}); + *currentStagingDataPositionOut += copySize; + return angle::Result::Continue; +} + } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/VertexArrayWgpu.h b/src/libANGLE/renderer/wgpu/VertexArrayWgpu.h index 26bd2d21b87..db6352ff297 100644 --- a/src/libANGLE/renderer/wgpu/VertexArrayWgpu.h +++ b/src/libANGLE/renderer/wgpu/VertexArrayWgpu.h @@ -13,6 +13,7 @@ #include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/wgpu/BufferWgpu.h" #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" namespace rx { @@ -25,8 +26,10 @@ enum class BufferType enum class IndexDataNeedsStreaming { - Yes, - No, + LineLoopStreaming, + TriangleFanStreaming, + NonEmulatedStreaming, + None, }; struct VertexBufferWithOffset @@ -38,7 +41,8 @@ struct VertexBufferWithOffset class VertexArrayWgpu : public VertexArrayImpl { public: - VertexArrayWgpu(const gl::VertexArrayState &data); + VertexArrayWgpu(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers); angle::Result syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits, @@ -65,6 +69,15 @@ class VertexArrayWgpu : public VertexArrayImpl uint32_t *indexCountOut); private: + struct BufferCopy + { + uint64_t sourceOffset; + webgpu::BufferHelper *src; + webgpu::BufferHelper *dest; + uint64_t destOffset; + uint64_t size; + }; + angle::Result syncDirtyAttrib(ContextWgpu *contextWgpu, const gl::VertexAttribute &attrib, const gl::VertexBinding &binding, @@ -75,9 +88,63 @@ class VertexArrayWgpu : public VertexArrayImpl webgpu::BufferHelper &buffer, size_t size, size_t attribIndex, - wgpu::BufferUsage usage, + WGPUBufferUsage usage, BufferType bufferType); + IndexDataNeedsStreaming determineIndexDataNeedsStreaming( + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + GLsizei count, + gl::PrimitiveMode mode, + gl::DrawElementsType *destDrawElementsTypeOrInvalidOut); + + uint32_t calculateAdjustedIndexCount(gl::PrimitiveMode mode, + bool primitiveRestartEnabled, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + GLsizei count, + const uint8_t *srcIndexData); + + angle::Result calculateStagingBufferSize(ContextWgpu *contextWgpu, + bool srcDestDrawElementsTypeEqual, + bool primitiveRestartEnabled, + IndexDataNeedsStreaming indexDataNeedsStreaming, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + GLsizei adjustedCountForStreamedIndices, + gl::AttributesMask clientAttributesToSync, + GLsizei instanceCount, + std::optional indexRange, + size_t *stagingBufferSizeOut); + + gl::DrawElementsType calculateDrawElementsType( + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + GLsizei count); + + angle::Result streamIndicesLineLoop(ContextWgpu *contextWgpu, + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + GLsizei count, + GLsizei adjustedCount, + const void *indices, + bool primitiveRestartEnabled, + uint8_t *stagingData, + size_t destIndexBufferSize, + std::optional indexRange, + const uint8_t *srcIndexData, + webgpu::BufferHelper *stagingBufferPtr, + std::vector *stagingUploadsOut, + size_t *currentStagingDataPositionOut); + + angle::Result streamIndicesDefault(ContextWgpu *contextWgpu, + gl::DrawElementsType sourceDrawElementsTypeOrInvalid, + gl::DrawElementsType destDrawElementsTypeOrInvalid, + gl::PrimitiveMode mode, + GLsizei count, + const void *indices, + uint8_t *stagingData, + size_t destIndexBufferSize, + webgpu::BufferHelper *stagingBufferPtr, + std::vector *stagingUploadsOut, + size_t *currentStagingDataPositionOut); + gl::AttribArray mCurrentAttribs; gl::AttribArray mStreamingArrayBuffers; gl::AttribArray mCurrentArrayBuffers; diff --git a/src/libANGLE/renderer/wgpu/gen_wgpu_format_table.py b/src/libANGLE/renderer/wgpu/gen_wgpu_format_table.py index ce8dd2fe8b7..12ddb360256 100644 --- a/src/libANGLE/renderer/wgpu/gen_wgpu_format_table.py +++ b/src/libANGLE/renderer/wgpu/gen_wgpu_format_table.py @@ -49,16 +49,16 @@ }} }} -wgpu::TextureFormat GetWgpuTextureFormatFromFormatID(angle::FormatID formatID) +WGPUTextureFormat GetWgpuTextureFormatFromFormatID(angle::FormatID formatID) {{ - static constexpr angle::FormatMap kMap = {{ + static constexpr angle::FormatMap kMap = {{ {image_format_id_cases} }}; return kMap[formatID]; }} -angle::FormatID GetFormatIDFromWgpuTextureFormat(wgpu::TextureFormat wgpuFormat) +angle::FormatID GetFormatIDFromWgpuTextureFormat(WGPUTextureFormat wgpuFormat) {{ switch (wgpuFormat) {{ @@ -69,16 +69,16 @@ }} }} -wgpu::VertexFormat GetWgpuVertexFormatFromFormatID(angle::FormatID formatID) +WGPUVertexFormat GetWgpuVertexFormatFromFormatID(angle::FormatID formatID) {{ - static constexpr angle::FormatMap kMap = {{ + static constexpr angle::FormatMap kMap = {{ {buffer_format_id_cases} }}; return kMap[formatID]; }} -angle::FormatID GetFormatIDFromWgpuBufferFormat(wgpu::VertexFormat wgpuFormat) +angle::FormatID GetFormatIDFromWgpuBufferFormat(WGPUVertexFormat wgpuFormat) {{ switch (wgpuFormat) {{ @@ -225,15 +225,15 @@ def buffer_args(format): def get_format_id_case(format_id, format_type, wgpu_format): - # wgpu::VertexFormat::Undefined was replaced with wgpu::VertexFormat(0u) + # WGPUVertexFormat_Undefined was replaced with WGPUVertexFormat(0u) # in https://dawn-review.googlesource.com/c/dawn/+/193360 if 'Undefined' in wgpu_format and 'VertexFormat' in format_type: - return "{angle::FormatID::%s, wgpu::%s(0u)}" % (format_id, format_type) - return "{angle::FormatID::%s, wgpu::%s::%s}" % (format_id, format_type, wgpu_format) + return "{angle::FormatID::%s, WGPU%s(0u)}" % (format_id, format_type) + return "{angle::FormatID::%s, WGPU%s_%s}" % (format_id, format_type, wgpu_format) def get_wgpu_format_case(format_type, format_id, wgpu_format): - # wgpu::VertexFormat::Undefined was replaced with wgpu::VertexFormat(0u) + # WGPUVertexFormat_Undefined was replaced with WGPUVertexFormat(0u) # in https://dawn-review.googlesource.com/c/dawn/+/193360 # so there is no 'case' needed for it. if 'Undefined' in wgpu_format and 'VertexFormat' in format_type: @@ -243,7 +243,7 @@ def get_wgpu_format_case(format_type, format_id, wgpu_format): if 'EXTERNAL' in format_id: return '' return """\ - case wgpu::%s::%s: + case WGPU%s_%s: return angle::FormatID::%s; """ % (format_type, wgpu_format, format_id) diff --git a/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.cpp b/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.cpp index 2a539bad2c8..cb1ef355ebc 100644 --- a/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.cpp +++ b/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.cpp @@ -26,22 +26,24 @@ WindowSurfaceWgpuX11::WindowSurfaceWgpuX11(const egl::SurfaceState &surfaceState {} angle::Result WindowSurfaceWgpuX11::createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) + webgpu::SurfaceHandle *outSurface) { DisplayWgpu *displayWgpu = webgpu::GetImpl(display); + const DawnProcTable *wgpu = displayWgpu->getProcs(); EGLNativeWindowType window = getNativeWindow(); - wgpu::Instance instance = displayWgpu->getInstance(); + webgpu::InstanceHandle instance = displayWgpu->getInstance(); - wgpu::SurfaceDescriptorFromXlibWindow x11Desc; + WGPUSurfaceSourceXlibWindow x11Desc = WGPU_SURFACE_SOURCE_XLIB_WINDOW_INIT; x11Desc.display = reinterpret_cast(display->getNativeDisplayId()); x11Desc.window = window; - wgpu::SurfaceDescriptor surfaceDesc; - surfaceDesc.nextInChain = &x11Desc; + WGPUSurfaceDescriptor surfaceDesc = WGPU_SURFACE_DESCRIPTOR_INIT; + surfaceDesc.nextInChain = &x11Desc.chain; - wgpu::Surface surface = instance.CreateSurface(&surfaceDesc); + webgpu::SurfaceHandle surface = webgpu::SurfaceHandle::Acquire( + wgpu, wgpu->instanceCreateSurface(instance.get(), &surfaceDesc)); *outSurface = surface; return angle::Result::Continue; diff --git a/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.h b/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.h index 21e8592c3d2..dc7df15f82f 100644 --- a/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.h +++ b/src/libANGLE/renderer/wgpu/linux/x11/WindowSurfaceWgpuX11.h @@ -21,7 +21,7 @@ class WindowSurfaceWgpuX11 : public WindowSurfaceWgpu private: angle::Result createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) override; + webgpu::SurfaceHandle *outSurface) override; angle::Result getCurrentWindowSize(const egl::Display *display, gl::Extents *outSize) override; }; diff --git a/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.h b/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.h index 043cb399289..5895efd459f 100644 --- a/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.h +++ b/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.h @@ -27,7 +27,7 @@ class WindowSurfaceWgpuMetalLayer : public WindowSurfaceWgpu private: angle::Result createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) override; + webgpu::SurfaceHandle *outSurface) override; angle::Result getCurrentWindowSize(const egl::Display *display, gl::Extents *outSize) override; id mMetalDevice; diff --git a/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.mm b/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.mm index 548cc2f8558..99d614fe8ef 100644 --- a/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.mm +++ b/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.mm @@ -44,7 +44,7 @@ } angle::Result WindowSurfaceWgpuMetalLayer::createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) + webgpu::SurfaceHandle *outSurface) API_AVAILABLE(macosx(10.11)) { CALayer *layer = reinterpret_cast(getNativeWindow()); @@ -56,21 +56,25 @@ CGSizeMake(mMetalLayer.bounds.size.width * mMetalLayer.contentsScale, mMetalLayer.bounds.size.height * mMetalLayer.contentsScale); mMetalLayer.framebufferOnly = NO; +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST mMetalLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; +#endif mMetalLayer.contentsScale = layer.contentsScale; [layer addSublayer:mMetalLayer]; - wgpu::SurfaceDescriptorFromMetalLayer metalLayerDesc; + WGPUSurfaceSourceMetalLayer metalLayerDesc = WGPU_SURFACE_SOURCE_METAL_LAYER_INIT; metalLayerDesc.layer = mMetalLayer; - wgpu::SurfaceDescriptor surfaceDesc; - surfaceDesc.nextInChain = &metalLayerDesc; + WGPUSurfaceDescriptor surfaceDesc = WGPU_SURFACE_DESCRIPTOR_INIT; + surfaceDesc.nextInChain = &metalLayerDesc.chain; DisplayWgpu *displayWgpu = webgpu::GetImpl(display); - wgpu::Instance instance = displayWgpu->getInstance(); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + webgpu::InstanceHandle instance = displayWgpu->getInstance(); - wgpu::Surface surface = instance.CreateSurface(&surfaceDesc); + webgpu::SurfaceHandle surface = webgpu::SurfaceHandle::Acquire( + wgpu, wgpu->instanceCreateSurface(instance.get(), &surfaceDesc)); *outSurface = surface; return angle::Result::Continue; diff --git a/src/libANGLE/renderer/wgpu/wgpu_command_buffer.cpp b/src/libANGLE/renderer/wgpu/wgpu_command_buffer.cpp index 183031e3073..0280fb0f4e4 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_command_buffer.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_command_buffer.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/wgpu_command_buffer.h" namespace rx @@ -13,10 +17,10 @@ namespace webgpu namespace { template -const T *GetReferencedObject(std::unordered_set &referenceList, const T &item) +T::ObjectType GetReferencedObject(std::unordered_set &referenceList, const T &item) { auto iter = referenceList.insert(item).first; - return &(*iter); + return (*iter).get(); } // Get the packed command ID from the current command data @@ -66,11 +70,11 @@ void CommandBuffer::drawIndexed(uint32_t indexCount, drawIndexedCommand->firstInstance = firstInstance; } -void CommandBuffer::setBindGroup(uint32_t groupIndex, wgpu::BindGroup bindGroup) +void CommandBuffer::setBindGroup(uint32_t groupIndex, BindGroupHandle bindGroup) { SetBindGroupCommand *setBindGroupCommand = initCommand(); setBindGroupCommand->groupIndex = groupIndex; - setBindGroupCommand->bindGroup = GetReferencedObject(mReferencedBindGroups, bindGroup); + setBindGroupCommand->bindGroup = GetReferencedObject(mState.referencedBindGroups, bindGroup); } void CommandBuffer::setBlendConstant(float r, float g, float b, float a) @@ -81,13 +85,13 @@ void CommandBuffer::setBlendConstant(float r, float g, float b, float a) setBlendConstantCommand->b = b; setBlendConstantCommand->a = a; - mHasSetBlendConstantCommand = true; + mState.hasSetBlendConstantCommand = true; } -void CommandBuffer::setPipeline(wgpu::RenderPipeline pipeline) +void CommandBuffer::setPipeline(RenderPipelineHandle pipeline) { SetPipelineCommand *setPiplelineCommand = initCommand(); - setPiplelineCommand->pipeline = GetReferencedObject(mReferencedRenderPipelines, pipeline); + setPiplelineCommand->pipeline = GetReferencedObject(mState.referencedRenderPipelines, pipeline); } void CommandBuffer::setScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) @@ -98,7 +102,7 @@ void CommandBuffer::setScissorRect(uint32_t x, uint32_t y, uint32_t width, uint3 setScissorRectCommand->width = width; setScissorRectCommand->height = height; - mHasSetScissorCommand = true; + mState.hasSetScissorCommand = true; } void CommandBuffer::setViewport(float x, @@ -116,64 +120,55 @@ void CommandBuffer::setViewport(float x, setViewportCommand->minDepth = minDepth; setViewportCommand->maxDepth = maxDepth; - mHasSetViewportCommand = true; + mState.hasSetViewportCommand = true; } -void CommandBuffer::setIndexBuffer(wgpu::Buffer buffer, - wgpu::IndexFormat format, +void CommandBuffer::setIndexBuffer(BufferHandle buffer, + WGPUIndexFormat format, uint64_t offset, uint64_t size) { SetIndexBufferCommand *setIndexBufferCommand = initCommand(); - setIndexBufferCommand->buffer = GetReferencedObject(mReferencedBuffers, buffer); + setIndexBufferCommand->buffer = GetReferencedObject(mState.referencedBuffers, buffer); setIndexBufferCommand->format = format; setIndexBufferCommand->offset = offset; setIndexBufferCommand->size = size; } void CommandBuffer::setVertexBuffer(uint32_t slot, - wgpu::Buffer buffer, + BufferHandle buffer, uint64_t offset, uint64_t size) { SetVertexBufferCommand *setVertexBufferCommand = initCommand(); setVertexBufferCommand->slot = slot; - setVertexBufferCommand->buffer = GetReferencedObject(mReferencedBuffers, buffer); + setVertexBufferCommand->buffer = GetReferencedObject(mState.referencedBuffers, buffer); setVertexBufferCommand->offset = offset; setVertexBufferCommand->size = size; } void CommandBuffer::clear() { - mCommandCount = 0; - - mHasSetScissorCommand = false; - mHasSetViewportCommand = false; - mHasSetBlendConstantCommand = false; - if (!mCommandBlocks.empty()) { // Only clear the command blocks that have been used - for (size_t cmdBlockIdx = 0; cmdBlockIdx <= mCurrentCommandBlock; cmdBlockIdx++) + for (size_t cmdBlockIdx = 0; cmdBlockIdx <= mState.currentCommandBlock; cmdBlockIdx++) { mCommandBlocks[cmdBlockIdx]->clear(); } } - mCurrentCommandBlock = 0; - - mReferencedRenderPipelines.clear(); - mReferencedBuffers.clear(); + mState = PerSubmissionData(); } -void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) +void CommandBuffer::recordCommands(const DawnProcTable *wgpu, RenderPassEncoderHandle encoder) { ASSERT(hasCommands()); ASSERT(!mCommandBlocks.empty()); // Make sure the last block is finalized - mCommandBlocks[mCurrentCommandBlock]->finalize(); + mCommandBlocks[mState.currentCommandBlock]->finalize(); - for (size_t cmdBlockIdx = 0; cmdBlockIdx <= mCurrentCommandBlock; cmdBlockIdx++) + for (size_t cmdBlockIdx = 0; cmdBlockIdx <= mState.currentCommandBlock; cmdBlockIdx++) { const CommandBlock *commandBlock = mCommandBlocks[cmdBlockIdx].get(); @@ -190,8 +185,9 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const DrawCommand &drawCommand = GetCommandAndIterate(¤tCommand); - encoder.Draw(drawCommand.vertexCount, drawCommand.instanceCount, - drawCommand.firstVertex, drawCommand.firstInstance); + wgpu->renderPassEncoderDraw(encoder.get(), drawCommand.vertexCount, + drawCommand.instanceCount, drawCommand.firstVertex, + drawCommand.firstInstance); break; } @@ -199,10 +195,10 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const DrawIndexedCommand &drawIndexedCommand = GetCommandAndIterate(¤tCommand); - encoder.DrawIndexed( - drawIndexedCommand.indexCount, drawIndexedCommand.instanceCount, - drawIndexedCommand.firstIndex, drawIndexedCommand.baseVertex, - drawIndexedCommand.firstInstance); + wgpu->renderPassEncoderDrawIndexed( + encoder.get(), drawIndexedCommand.indexCount, + drawIndexedCommand.instanceCount, drawIndexedCommand.firstIndex, + drawIndexedCommand.baseVertex, drawIndexedCommand.firstInstance); break; } @@ -210,8 +206,9 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetBindGroupCommand &setBindGroupCommand = GetCommandAndIterate(¤tCommand); - encoder.SetBindGroup(setBindGroupCommand.groupIndex, - *setBindGroupCommand.bindGroup); + wgpu->renderPassEncoderSetBindGroup(encoder.get(), + setBindGroupCommand.groupIndex, + setBindGroupCommand.bindGroup, 0, nullptr); break; } @@ -219,9 +216,9 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetBlendConstantCommand &setBlendConstantCommand = GetCommandAndIterate(¤tCommand); - wgpu::Color color{setBlendConstantCommand.r, setBlendConstantCommand.g, - setBlendConstantCommand.b, setBlendConstantCommand.a}; - encoder.SetBlendConstant(&color); + WGPUColor color{setBlendConstantCommand.r, setBlendConstantCommand.g, + setBlendConstantCommand.b, setBlendConstantCommand.a}; + wgpu->renderPassEncoderSetBlendConstant(encoder.get(), &color); break; } @@ -229,8 +226,8 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetIndexBufferCommand &setIndexBufferCommand = GetCommandAndIterate(¤tCommand); - encoder.SetIndexBuffer( - *setIndexBufferCommand.buffer, setIndexBufferCommand.format, + wgpu->renderPassEncoderSetIndexBuffer( + encoder.get(), setIndexBufferCommand.buffer, setIndexBufferCommand.format, setIndexBufferCommand.offset, setIndexBufferCommand.size); break; } @@ -239,7 +236,7 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetPipelineCommand &setPiplelineCommand = GetCommandAndIterate(¤tCommand); - encoder.SetPipeline(*setPiplelineCommand.pipeline); + wgpu->renderPassEncoderSetPipeline(encoder.get(), setPiplelineCommand.pipeline); break; } @@ -247,9 +244,9 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetScissorRectCommand &setScissorRectCommand = GetCommandAndIterate(¤tCommand); - encoder.SetScissorRect(setScissorRectCommand.x, setScissorRectCommand.y, - setScissorRectCommand.width, - setScissorRectCommand.height); + wgpu->renderPassEncoderSetScissorRect( + encoder.get(), setScissorRectCommand.x, setScissorRectCommand.y, + setScissorRectCommand.width, setScissorRectCommand.height); break; } @@ -257,9 +254,10 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetViewportCommand &setViewportCommand = GetCommandAndIterate(¤tCommand); - encoder.SetViewport(setViewportCommand.x, setViewportCommand.y, - setViewportCommand.width, setViewportCommand.height, - setViewportCommand.minDepth, setViewportCommand.maxDepth); + wgpu->renderPassEncoderSetViewport( + encoder.get(), setViewportCommand.x, setViewportCommand.y, + setViewportCommand.width, setViewportCommand.height, + setViewportCommand.minDepth, setViewportCommand.maxDepth); break; } @@ -267,8 +265,8 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) { const SetVertexBufferCommand &setVertexBufferCommand = GetCommandAndIterate(¤tCommand); - encoder.SetVertexBuffer( - setVertexBufferCommand.slot, *setVertexBufferCommand.buffer, + wgpu->renderPassEncoderSetVertexBuffer( + encoder.get(), setVertexBufferCommand.slot, setVertexBufferCommand.buffer, setVertexBufferCommand.offset, setVertexBufferCommand.size); break; } @@ -283,18 +281,26 @@ void CommandBuffer::recordCommands(wgpu::RenderPassEncoder encoder) void CommandBuffer::nextCommandBlock() { - if (mCurrentCommandBlock + 1 < mCommandBlocks.size()) + if (!mCommandBlocks.empty()) + { + ASSERT(mState.currentCommandBlock < mCommandBlocks.size()); + + // Finish the current command block before moving to a new one + mCommandBlocks[mState.currentCommandBlock]->finalize(); + } + + if (mState.currentCommandBlock + 1 < mCommandBlocks.size()) { // There is already a command block allocated. Make sure it's been cleared and use it. - mCurrentCommandBlock++; - ASSERT(mCommandBlocks[mCurrentCommandBlock]->mCurrentPosition == 0); - ASSERT(mCommandBlocks[mCurrentCommandBlock]->mRemainingSize > 0); + mState.currentCommandBlock++; + ASSERT(mCommandBlocks[mState.currentCommandBlock]->mCurrentPosition == 0); + ASSERT(mCommandBlocks[mState.currentCommandBlock]->mRemainingSize > 0); } else { std::unique_ptr newBlock = std::make_unique(); mCommandBlocks.push_back(std::move(newBlock)); - mCurrentCommandBlock = mCommandBlocks.size() - 1; + mState.currentCommandBlock = mCommandBlocks.size() - 1; } } diff --git a/src/libANGLE/renderer/wgpu/wgpu_command_buffer.h b/src/libANGLE/renderer/wgpu/wgpu_command_buffer.h index 16d8e32d07d..7bf96c231cc 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_command_buffer.h +++ b/src/libANGLE/renderer/wgpu/wgpu_command_buffer.h @@ -7,10 +7,14 @@ #ifndef LIBANGLE_RENDERER_WGPU_WGPU_COMMAND_BUFFER_H_ #define LIBANGLE_RENDERER_WGPU_WGPU_COMMAND_BUFFER_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/debug.h" #include "libANGLE/renderer/wgpu/wgpu_utils.h" -#include +#include #include namespace rx @@ -126,7 +130,7 @@ struct SetBindGroupCommand uint32_t pad0; union { - const wgpu::BindGroup *bindGroup; + WGPUBindGroup bindGroup; uint64_t pad1; // Pad to 64 bits on 32-bit systems }; }; @@ -143,10 +147,10 @@ struct SetIndexBufferCommand { union { - const wgpu::Buffer *buffer; + WGPUBuffer buffer; uint64_t pad0; // Pad to 64 bits on 32-bit systems }; - wgpu::IndexFormat format; + WGPUIndexFormat format; uint32_t pad1; uint64_t offset; uint64_t size; @@ -161,7 +165,7 @@ struct SetPipelineCommand { union { - const wgpu::RenderPipeline *pipeline; + WGPURenderPipeline pipeline; uint64_t padding; // Pad to 64 bits on 32-bit systems }; }; @@ -185,7 +189,7 @@ struct SetVertexBufferCommand uint32_t pad0; union { - const wgpu::Buffer *buffer; + WGPUBuffer buffer; uint64_t pad1; // Pad to 64 bits on 32-bit systems }; uint64_t offset; @@ -242,25 +246,25 @@ class CommandBuffer uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance); - void setBindGroup(uint32_t groupIndex, wgpu::BindGroup bindGroup); + void setBindGroup(uint32_t groupIndex, BindGroupHandle bindGroup); void setBlendConstant(float r, float g, float b, float a); - void setPipeline(wgpu::RenderPipeline pipeline); + void setPipeline(RenderPipelineHandle pipeline); void setScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height); void setViewport(float x, float y, float width, float height, float minDepth, float maxDepth); - void setIndexBuffer(wgpu::Buffer buffer, - wgpu::IndexFormat format, + void setIndexBuffer(BufferHandle buffer, + WGPUIndexFormat format, uint64_t offset, uint64_t size); - void setVertexBuffer(uint32_t slot, wgpu::Buffer buffer, uint64_t offset, uint64_t size); + void setVertexBuffer(uint32_t slot, BufferHandle buffer, uint64_t offset, uint64_t size); void clear(); - bool hasCommands() const { return mCommandCount > 0; } - bool hasSetScissorCommand() const { return mHasSetScissorCommand; } - bool hasSetViewportCommand() const { return mHasSetViewportCommand; } - bool hasSetBlendConstantCommand() const { return mHasSetBlendConstantCommand; } + bool hasCommands() const { return mState.commandCount > 0; } + bool hasSetScissorCommand() const { return mState.hasSetScissorCommand; } + bool hasSetViewportCommand() const { return mState.hasSetViewportCommand; } + bool hasSetBlendConstantCommand() const { return mState.hasSetBlendConstantCommand; } - void recordCommands(wgpu::RenderPassEncoder encoder); + void recordCommands(const DawnProcTable *wgpu, RenderPassEncoderHandle encoder); private: struct CommandBlock @@ -295,24 +299,32 @@ class CommandBuffer static_assert(kCommandBlockStructSize == kCommandBlockSize, "Size mismatch"); std::vector> mCommandBlocks; - size_t mCurrentCommandBlock = 0; - - size_t mCommandCount = 0; - bool mHasSetScissorCommand = false; - bool mHasSetViewportCommand = false; - bool mHasSetBlendConstantCommand = false; - // std::unordered_set required because it does not move elements and stored command reference - // addresses in the set - std::unordered_set mReferencedRenderPipelines; - std::unordered_set mReferencedBuffers; - std::unordered_set mReferencedBindGroups; + // State for the current commands held in mCommandBlocks. In a structure so that it can be + // easily reset by calling the constructor. + struct PerSubmissionData + { + size_t currentCommandBlock = 0; + + size_t commandCount = 0; + bool hasSetScissorCommand = false; + bool hasSetViewportCommand = false; + bool hasSetBlendConstantCommand = false; + + // std::unordered_set required because it does not move elements and stored command + // reference addresses in the set + std::unordered_set referencedRenderPipelines; + std::unordered_set referencedBuffers; + std::unordered_set referencedBindGroups; + }; + PerSubmissionData mState; void nextCommandBlock(); void ensureCommandSpace(size_t space) { - if (mCommandBlocks.empty() || mCommandBlocks[mCurrentCommandBlock]->mRemainingSize < space) + if (mCommandBlocks.empty() || + mCommandBlocks[mState.currentCommandBlock]->mRemainingSize < space) { nextCommandBlock(); } @@ -323,7 +335,7 @@ class CommandBuffer { constexpr size_t allocationSize = sizeof(CommandID) + sizeof(CommandType); ensureCommandSpace(allocationSize); - CommandBlock *commandBlock = mCommandBlocks[mCurrentCommandBlock].get(); + CommandBlock *commandBlock = mCommandBlocks[mState.currentCommandBlock].get(); uint8_t *idAndCommandStorage = commandBlock->getDataAtCurrentPositionAndReserveSpace(allocationSize); @@ -334,7 +346,7 @@ class CommandBuffer CommandType *commandStruct = reinterpret_cast(idAndCommandStorage + sizeof(CommandID)); - mCommandCount++; + mState.commandCount++; return commandStruct; } diff --git a/src/libANGLE/renderer/wgpu/wgpu_format_map.json b/src/libANGLE/renderer/wgpu/wgpu_format_map.json index 7032cd0762d..45dfc08425a 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_format_map.json +++ b/src/libANGLE/renderer/wgpu/wgpu_format_map.json @@ -492,7 +492,13 @@ "R32G32B32A32_USCALED": { "buffer": "R32G32B32A32_FLOAT" }, - "R4G4B4A4_UNORM": { + "R5G6B5_UNORM": { + "image": "R8G8B8A8_UNORM" + }, + "R4G4B4A4_UNORM": { + "image": "R8G8B8A8_UNORM" + }, + "R5G5B5A1_UNORM": { "image": "R8G8B8A8_UNORM" }, "R8_SSCALED": { @@ -546,6 +552,9 @@ "image": "R8G8B8A8_UNORM", "buffer": "NONE" }, + "D24_UNORM_X8_UINT": { + "image": "D24_UNORM_S8_UINT" + }, "X2R10G10B10_SINT_VERTEX": { "image": "NONE", "buffer": "R16G16B16A16_SINT" @@ -572,4 +581,3 @@ } } } - \ No newline at end of file diff --git a/src/libANGLE/renderer/wgpu/wgpu_format_table_autogen.cpp b/src/libANGLE/renderer/wgpu/wgpu_format_table_autogen.cpp index eae3a2102d7..06b14bcb470 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_format_table_autogen.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_format_table_autogen.cpp @@ -709,7 +709,11 @@ void Format::initialize(const angle::Format &angleFormat) break; case angle::FormatID::D24_UNORM_X8_UINT: - // This format is not implemented in WebGPU. + mIntendedGLFormat = GL_DEPTH_COMPONENT24; + mActualImageFormatID = angle::FormatID::D24_UNORM_S8_UINT; + mImageInitializerFunction = nullptr; + mIsRenderable = true; + break; case angle::FormatID::D32_FLOAT: @@ -909,6 +913,10 @@ void Format::initialize(const angle::Format &angleFormat) mVertexLoadRequiresConversion = false; break; + case angle::FormatID::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + // This format is not implemented in WebGPU. + break; + case angle::FormatID::G8_B8R8_2PLANE_420_UNORM: // This format is not implemented in WebGPU. break; @@ -1151,6 +1159,10 @@ void Format::initialize(const angle::Format &angleFormat) mVertexLoadRequiresConversion = true; break; + case angle::FormatID::R10X6G10X6B10X6A10X6_UNORM: + // This format is not implemented in WebGPU. + break; + case angle::FormatID::R11G11B10_FLOAT: mIntendedGLFormat = GL_R11F_G11F_B10F; mActualImageFormatID = angle::FormatID::R11G11B10_FLOAT; @@ -1702,11 +1714,19 @@ void Format::initialize(const angle::Format &angleFormat) break; case angle::FormatID::R5G5B5A1_UNORM: - // This format is not implemented in WebGPU. + mIntendedGLFormat = GL_RGB5_A1; + mActualImageFormatID = angle::FormatID::R8G8B8A8_UNORM; + mImageInitializerFunction = nullptr; + mIsRenderable = true; + break; case angle::FormatID::R5G6B5_UNORM: - // This format is not implemented in WebGPU. + mIntendedGLFormat = GL_RGB565; + mActualImageFormatID = angle::FormatID::R8G8B8A8_UNORM; + mImageInitializerFunction = Initialize4ComponentData; + mIsRenderable = true; + break; case angle::FormatID::R8G8B8A8_SINT: @@ -2073,324 +2093,324 @@ void Format::initialize(const angle::Format &angleFormat) } } -wgpu::TextureFormat GetWgpuTextureFormatFromFormatID(angle::FormatID formatID) +WGPUTextureFormat GetWgpuTextureFormatFromFormatID(angle::FormatID formatID) { - static constexpr angle::FormatMap kMap = { - {angle::FormatID::ASTC_10x10_SRGB_BLOCK, wgpu::TextureFormat::ASTC10x10UnormSrgb}, - {angle::FormatID::ASTC_10x10_UNORM_BLOCK, wgpu::TextureFormat::ASTC10x10Unorm}, - {angle::FormatID::ASTC_10x5_SRGB_BLOCK, wgpu::TextureFormat::ASTC10x5UnormSrgb}, - {angle::FormatID::ASTC_10x5_UNORM_BLOCK, wgpu::TextureFormat::ASTC10x5Unorm}, - {angle::FormatID::ASTC_10x6_SRGB_BLOCK, wgpu::TextureFormat::ASTC10x6UnormSrgb}, - {angle::FormatID::ASTC_10x6_UNORM_BLOCK, wgpu::TextureFormat::ASTC10x6Unorm}, - {angle::FormatID::ASTC_10x8_SRGB_BLOCK, wgpu::TextureFormat::ASTC10x8UnormSrgb}, - {angle::FormatID::ASTC_10x8_UNORM_BLOCK, wgpu::TextureFormat::ASTC10x8Unorm}, - {angle::FormatID::ASTC_12x10_SRGB_BLOCK, wgpu::TextureFormat::ASTC12x10UnormSrgb}, - {angle::FormatID::ASTC_12x10_UNORM_BLOCK, wgpu::TextureFormat::ASTC12x10Unorm}, - {angle::FormatID::ASTC_12x12_SRGB_BLOCK, wgpu::TextureFormat::ASTC12x12UnormSrgb}, - {angle::FormatID::ASTC_12x12_UNORM_BLOCK, wgpu::TextureFormat::ASTC12x12Unorm}, - {angle::FormatID::ASTC_4x4_SRGB_BLOCK, wgpu::TextureFormat::ASTC4x4UnormSrgb}, - {angle::FormatID::ASTC_4x4_UNORM_BLOCK, wgpu::TextureFormat::ASTC4x4Unorm}, - {angle::FormatID::ASTC_5x4_SRGB_BLOCK, wgpu::TextureFormat::ASTC5x4UnormSrgb}, - {angle::FormatID::ASTC_5x4_UNORM_BLOCK, wgpu::TextureFormat::ASTC5x4Unorm}, - {angle::FormatID::ASTC_5x5_SRGB_BLOCK, wgpu::TextureFormat::ASTC5x5UnormSrgb}, - {angle::FormatID::ASTC_5x5_UNORM_BLOCK, wgpu::TextureFormat::ASTC5x5Unorm}, - {angle::FormatID::ASTC_6x5_SRGB_BLOCK, wgpu::TextureFormat::ASTC6x5UnormSrgb}, - {angle::FormatID::ASTC_6x5_UNORM_BLOCK, wgpu::TextureFormat::ASTC6x5Unorm}, - {angle::FormatID::ASTC_6x6_SRGB_BLOCK, wgpu::TextureFormat::ASTC6x6UnormSrgb}, - {angle::FormatID::ASTC_6x6_UNORM_BLOCK, wgpu::TextureFormat::ASTC6x6Unorm}, - {angle::FormatID::ASTC_8x5_SRGB_BLOCK, wgpu::TextureFormat::ASTC8x5UnormSrgb}, - {angle::FormatID::ASTC_8x5_UNORM_BLOCK, wgpu::TextureFormat::ASTC8x5Unorm}, - {angle::FormatID::ASTC_8x6_SRGB_BLOCK, wgpu::TextureFormat::ASTC8x6UnormSrgb}, - {angle::FormatID::ASTC_8x6_UNORM_BLOCK, wgpu::TextureFormat::ASTC8x6Unorm}, - {angle::FormatID::ASTC_8x8_SRGB_BLOCK, wgpu::TextureFormat::ASTC8x8UnormSrgb}, - {angle::FormatID::ASTC_8x8_UNORM_BLOCK, wgpu::TextureFormat::ASTC8x8Unorm}, - {angle::FormatID::B8G8R8A8_UNORM, wgpu::TextureFormat::BGRA8Unorm}, - {angle::FormatID::B8G8R8A8_UNORM_SRGB, wgpu::TextureFormat::BGRA8UnormSrgb}, - {angle::FormatID::BC1_RGBA_UNORM_BLOCK, wgpu::TextureFormat::BC1RGBAUnorm}, - {angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK, wgpu::TextureFormat::BC1RGBAUnormSrgb}, - {angle::FormatID::BC2_RGBA_UNORM_BLOCK, wgpu::TextureFormat::BC2RGBAUnorm}, - {angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK, wgpu::TextureFormat::BC2RGBAUnormSrgb}, - {angle::FormatID::BC3_RGBA_UNORM_BLOCK, wgpu::TextureFormat::BC3RGBAUnorm}, - {angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK, wgpu::TextureFormat::BC3RGBAUnormSrgb}, - {angle::FormatID::BC4_RED_SNORM_BLOCK, wgpu::TextureFormat::BC4RSnorm}, - {angle::FormatID::BC4_RED_UNORM_BLOCK, wgpu::TextureFormat::BC4RUnorm}, - {angle::FormatID::BC5_RG_SNORM_BLOCK, wgpu::TextureFormat::BC5RGSnorm}, - {angle::FormatID::BC5_RG_UNORM_BLOCK, wgpu::TextureFormat::BC5RGUnorm}, - {angle::FormatID::BC6H_RGB_SFLOAT_BLOCK, wgpu::TextureFormat::BC6HRGBFloat}, - {angle::FormatID::BC6H_RGB_UFLOAT_BLOCK, wgpu::TextureFormat::BC6HRGBUfloat}, - {angle::FormatID::BC7_RGBA_UNORM_BLOCK, wgpu::TextureFormat::BC7RGBAUnorm}, - {angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK, wgpu::TextureFormat::BC7RGBAUnormSrgb}, - {angle::FormatID::D16_UNORM, wgpu::TextureFormat::Depth16Unorm}, - {angle::FormatID::D24_UNORM_S8_UINT, wgpu::TextureFormat::Depth24PlusStencil8}, - {angle::FormatID::D32_FLOAT, wgpu::TextureFormat::Depth32Float}, - {angle::FormatID::EAC_R11G11_SNORM_BLOCK, wgpu::TextureFormat::EACRG11Snorm}, - {angle::FormatID::EAC_R11G11_UNORM_BLOCK, wgpu::TextureFormat::EACRG11Unorm}, - {angle::FormatID::EAC_R11_SNORM_BLOCK, wgpu::TextureFormat::EACR11Snorm}, - {angle::FormatID::EAC_R11_UNORM_BLOCK, wgpu::TextureFormat::EACR11Unorm}, - {angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK, wgpu::TextureFormat::ETC2RGB8A1UnormSrgb}, - {angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK, wgpu::TextureFormat::ETC2RGB8A1Unorm}, - {angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK, wgpu::TextureFormat::ETC2RGBA8UnormSrgb}, - {angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, wgpu::TextureFormat::ETC2RGBA8Unorm}, - {angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK, wgpu::TextureFormat::ETC2RGB8UnormSrgb}, - {angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK, wgpu::TextureFormat::ETC2RGB8Unorm}, - {angle::FormatID::EXTERNAL0, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL1, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL2, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL3, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL4, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL5, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL6, wgpu::TextureFormat::Undefined}, - {angle::FormatID::EXTERNAL7, wgpu::TextureFormat::Undefined}, - {angle::FormatID::NONE, wgpu::TextureFormat::Undefined}, - {angle::FormatID::R10G10B10A2_SINT, wgpu::TextureFormat::RGB10A2Uint}, - {angle::FormatID::R10G10B10A2_UNORM, wgpu::TextureFormat::RGB10A2Unorm}, - {angle::FormatID::R11G11B10_FLOAT, wgpu::TextureFormat::RG11B10Ufloat}, - {angle::FormatID::R16G16B16A16_FLOAT, wgpu::TextureFormat::RGBA16Float}, - {angle::FormatID::R16G16B16A16_SINT, wgpu::TextureFormat::RGBA16Sint}, - {angle::FormatID::R16G16B16A16_SNORM, wgpu::TextureFormat::RGBA16Snorm}, - {angle::FormatID::R16G16B16A16_UINT, wgpu::TextureFormat::RGBA16Uint}, - {angle::FormatID::R16G16B16A16_UNORM, wgpu::TextureFormat::RGBA16Unorm}, - {angle::FormatID::R16G16_FLOAT, wgpu::TextureFormat::RG16Float}, - {angle::FormatID::R16G16_SINT, wgpu::TextureFormat::RG16Sint}, - {angle::FormatID::R16G16_SNORM, wgpu::TextureFormat::RG16Snorm}, - {angle::FormatID::R16G16_UINT, wgpu::TextureFormat::RG16Uint}, - {angle::FormatID::R16G16_UNORM, wgpu::TextureFormat::RG16Unorm}, - {angle::FormatID::R16_FLOAT, wgpu::TextureFormat::R16Float}, - {angle::FormatID::R16_SINT, wgpu::TextureFormat::R16Sint}, - {angle::FormatID::R16_SNORM, wgpu::TextureFormat::R16Snorm}, - {angle::FormatID::R16_UINT, wgpu::TextureFormat::R16Uint}, - {angle::FormatID::R16_UNORM, wgpu::TextureFormat::R16Unorm}, - {angle::FormatID::R32G32B32A32_FLOAT, wgpu::TextureFormat::RGBA32Float}, - {angle::FormatID::R32G32B32A32_SINT, wgpu::TextureFormat::RGBA32Sint}, - {angle::FormatID::R32G32B32A32_UINT, wgpu::TextureFormat::RGBA32Uint}, - {angle::FormatID::R32G32_FLOAT, wgpu::TextureFormat::RG32Float}, - {angle::FormatID::R32G32_SINT, wgpu::TextureFormat::RG32Sint}, - {angle::FormatID::R32G32_UINT, wgpu::TextureFormat::RG32Uint}, - {angle::FormatID::R32_FLOAT, wgpu::TextureFormat::R32Float}, - {angle::FormatID::R32_SINT, wgpu::TextureFormat::R32Sint}, - {angle::FormatID::R32_UINT, wgpu::TextureFormat::R32Uint}, - {angle::FormatID::R8G8B8A8_SINT, wgpu::TextureFormat::RGBA8Sint}, - {angle::FormatID::R8G8B8A8_SNORM, wgpu::TextureFormat::RGBA8Snorm}, - {angle::FormatID::R8G8B8A8_UINT, wgpu::TextureFormat::RGBA8Uint}, - {angle::FormatID::R8G8B8A8_UNORM, wgpu::TextureFormat::RGBA8Unorm}, - {angle::FormatID::R8G8B8A8_UNORM_SRGB, wgpu::TextureFormat::RGBA8UnormSrgb}, - {angle::FormatID::R8G8_SINT, wgpu::TextureFormat::RG8Sint}, - {angle::FormatID::R8G8_SNORM, wgpu::TextureFormat::RG8Snorm}, - {angle::FormatID::R8G8_UINT, wgpu::TextureFormat::RG8Uint}, - {angle::FormatID::R8G8_UNORM, wgpu::TextureFormat::RG8Unorm}, - {angle::FormatID::R8_SINT, wgpu::TextureFormat::R8Sint}, - {angle::FormatID::R8_SNORM, wgpu::TextureFormat::R8Snorm}, - {angle::FormatID::R8_UINT, wgpu::TextureFormat::R8Uint}, - {angle::FormatID::R8_UNORM, wgpu::TextureFormat::R8Unorm}, - {angle::FormatID::R9G9B9E5_SHAREDEXP, wgpu::TextureFormat::RGB9E5Ufloat}, - {angle::FormatID::S8_UINT, wgpu::TextureFormat::Stencil8}}; + static constexpr angle::FormatMap kMap = { + {angle::FormatID::ASTC_10x10_SRGB_BLOCK, WGPUTextureFormat_ASTC10x10UnormSrgb}, + {angle::FormatID::ASTC_10x10_UNORM_BLOCK, WGPUTextureFormat_ASTC10x10Unorm}, + {angle::FormatID::ASTC_10x5_SRGB_BLOCK, WGPUTextureFormat_ASTC10x5UnormSrgb}, + {angle::FormatID::ASTC_10x5_UNORM_BLOCK, WGPUTextureFormat_ASTC10x5Unorm}, + {angle::FormatID::ASTC_10x6_SRGB_BLOCK, WGPUTextureFormat_ASTC10x6UnormSrgb}, + {angle::FormatID::ASTC_10x6_UNORM_BLOCK, WGPUTextureFormat_ASTC10x6Unorm}, + {angle::FormatID::ASTC_10x8_SRGB_BLOCK, WGPUTextureFormat_ASTC10x8UnormSrgb}, + {angle::FormatID::ASTC_10x8_UNORM_BLOCK, WGPUTextureFormat_ASTC10x8Unorm}, + {angle::FormatID::ASTC_12x10_SRGB_BLOCK, WGPUTextureFormat_ASTC12x10UnormSrgb}, + {angle::FormatID::ASTC_12x10_UNORM_BLOCK, WGPUTextureFormat_ASTC12x10Unorm}, + {angle::FormatID::ASTC_12x12_SRGB_BLOCK, WGPUTextureFormat_ASTC12x12UnormSrgb}, + {angle::FormatID::ASTC_12x12_UNORM_BLOCK, WGPUTextureFormat_ASTC12x12Unorm}, + {angle::FormatID::ASTC_4x4_SRGB_BLOCK, WGPUTextureFormat_ASTC4x4UnormSrgb}, + {angle::FormatID::ASTC_4x4_UNORM_BLOCK, WGPUTextureFormat_ASTC4x4Unorm}, + {angle::FormatID::ASTC_5x4_SRGB_BLOCK, WGPUTextureFormat_ASTC5x4UnormSrgb}, + {angle::FormatID::ASTC_5x4_UNORM_BLOCK, WGPUTextureFormat_ASTC5x4Unorm}, + {angle::FormatID::ASTC_5x5_SRGB_BLOCK, WGPUTextureFormat_ASTC5x5UnormSrgb}, + {angle::FormatID::ASTC_5x5_UNORM_BLOCK, WGPUTextureFormat_ASTC5x5Unorm}, + {angle::FormatID::ASTC_6x5_SRGB_BLOCK, WGPUTextureFormat_ASTC6x5UnormSrgb}, + {angle::FormatID::ASTC_6x5_UNORM_BLOCK, WGPUTextureFormat_ASTC6x5Unorm}, + {angle::FormatID::ASTC_6x6_SRGB_BLOCK, WGPUTextureFormat_ASTC6x6UnormSrgb}, + {angle::FormatID::ASTC_6x6_UNORM_BLOCK, WGPUTextureFormat_ASTC6x6Unorm}, + {angle::FormatID::ASTC_8x5_SRGB_BLOCK, WGPUTextureFormat_ASTC8x5UnormSrgb}, + {angle::FormatID::ASTC_8x5_UNORM_BLOCK, WGPUTextureFormat_ASTC8x5Unorm}, + {angle::FormatID::ASTC_8x6_SRGB_BLOCK, WGPUTextureFormat_ASTC8x6UnormSrgb}, + {angle::FormatID::ASTC_8x6_UNORM_BLOCK, WGPUTextureFormat_ASTC8x6Unorm}, + {angle::FormatID::ASTC_8x8_SRGB_BLOCK, WGPUTextureFormat_ASTC8x8UnormSrgb}, + {angle::FormatID::ASTC_8x8_UNORM_BLOCK, WGPUTextureFormat_ASTC8x8Unorm}, + {angle::FormatID::B8G8R8A8_UNORM, WGPUTextureFormat_BGRA8Unorm}, + {angle::FormatID::B8G8R8A8_UNORM_SRGB, WGPUTextureFormat_BGRA8UnormSrgb}, + {angle::FormatID::BC1_RGBA_UNORM_BLOCK, WGPUTextureFormat_BC1RGBAUnorm}, + {angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK, WGPUTextureFormat_BC1RGBAUnormSrgb}, + {angle::FormatID::BC2_RGBA_UNORM_BLOCK, WGPUTextureFormat_BC2RGBAUnorm}, + {angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK, WGPUTextureFormat_BC2RGBAUnormSrgb}, + {angle::FormatID::BC3_RGBA_UNORM_BLOCK, WGPUTextureFormat_BC3RGBAUnorm}, + {angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK, WGPUTextureFormat_BC3RGBAUnormSrgb}, + {angle::FormatID::BC4_RED_SNORM_BLOCK, WGPUTextureFormat_BC4RSnorm}, + {angle::FormatID::BC4_RED_UNORM_BLOCK, WGPUTextureFormat_BC4RUnorm}, + {angle::FormatID::BC5_RG_SNORM_BLOCK, WGPUTextureFormat_BC5RGSnorm}, + {angle::FormatID::BC5_RG_UNORM_BLOCK, WGPUTextureFormat_BC5RGUnorm}, + {angle::FormatID::BC6H_RGB_SFLOAT_BLOCK, WGPUTextureFormat_BC6HRGBFloat}, + {angle::FormatID::BC6H_RGB_UFLOAT_BLOCK, WGPUTextureFormat_BC6HRGBUfloat}, + {angle::FormatID::BC7_RGBA_UNORM_BLOCK, WGPUTextureFormat_BC7RGBAUnorm}, + {angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK, WGPUTextureFormat_BC7RGBAUnormSrgb}, + {angle::FormatID::D16_UNORM, WGPUTextureFormat_Depth16Unorm}, + {angle::FormatID::D24_UNORM_S8_UINT, WGPUTextureFormat_Depth24PlusStencil8}, + {angle::FormatID::D32_FLOAT, WGPUTextureFormat_Depth32Float}, + {angle::FormatID::EAC_R11G11_SNORM_BLOCK, WGPUTextureFormat_EACRG11Snorm}, + {angle::FormatID::EAC_R11G11_UNORM_BLOCK, WGPUTextureFormat_EACRG11Unorm}, + {angle::FormatID::EAC_R11_SNORM_BLOCK, WGPUTextureFormat_EACR11Snorm}, + {angle::FormatID::EAC_R11_UNORM_BLOCK, WGPUTextureFormat_EACR11Unorm}, + {angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK, WGPUTextureFormat_ETC2RGB8A1UnormSrgb}, + {angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK, WGPUTextureFormat_ETC2RGB8A1Unorm}, + {angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK, WGPUTextureFormat_ETC2RGBA8UnormSrgb}, + {angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, WGPUTextureFormat_ETC2RGBA8Unorm}, + {angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK, WGPUTextureFormat_ETC2RGB8UnormSrgb}, + {angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK, WGPUTextureFormat_ETC2RGB8Unorm}, + {angle::FormatID::EXTERNAL0, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL1, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL2, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL3, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL4, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL5, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL6, WGPUTextureFormat_Undefined}, + {angle::FormatID::EXTERNAL7, WGPUTextureFormat_Undefined}, + {angle::FormatID::NONE, WGPUTextureFormat_Undefined}, + {angle::FormatID::R10G10B10A2_SINT, WGPUTextureFormat_RGB10A2Uint}, + {angle::FormatID::R10G10B10A2_UNORM, WGPUTextureFormat_RGB10A2Unorm}, + {angle::FormatID::R11G11B10_FLOAT, WGPUTextureFormat_RG11B10Ufloat}, + {angle::FormatID::R16G16B16A16_FLOAT, WGPUTextureFormat_RGBA16Float}, + {angle::FormatID::R16G16B16A16_SINT, WGPUTextureFormat_RGBA16Sint}, + {angle::FormatID::R16G16B16A16_SNORM, WGPUTextureFormat_RGBA16Snorm}, + {angle::FormatID::R16G16B16A16_UINT, WGPUTextureFormat_RGBA16Uint}, + {angle::FormatID::R16G16B16A16_UNORM, WGPUTextureFormat_RGBA16Unorm}, + {angle::FormatID::R16G16_FLOAT, WGPUTextureFormat_RG16Float}, + {angle::FormatID::R16G16_SINT, WGPUTextureFormat_RG16Sint}, + {angle::FormatID::R16G16_SNORM, WGPUTextureFormat_RG16Snorm}, + {angle::FormatID::R16G16_UINT, WGPUTextureFormat_RG16Uint}, + {angle::FormatID::R16G16_UNORM, WGPUTextureFormat_RG16Unorm}, + {angle::FormatID::R16_FLOAT, WGPUTextureFormat_R16Float}, + {angle::FormatID::R16_SINT, WGPUTextureFormat_R16Sint}, + {angle::FormatID::R16_SNORM, WGPUTextureFormat_R16Snorm}, + {angle::FormatID::R16_UINT, WGPUTextureFormat_R16Uint}, + {angle::FormatID::R16_UNORM, WGPUTextureFormat_R16Unorm}, + {angle::FormatID::R32G32B32A32_FLOAT, WGPUTextureFormat_RGBA32Float}, + {angle::FormatID::R32G32B32A32_SINT, WGPUTextureFormat_RGBA32Sint}, + {angle::FormatID::R32G32B32A32_UINT, WGPUTextureFormat_RGBA32Uint}, + {angle::FormatID::R32G32_FLOAT, WGPUTextureFormat_RG32Float}, + {angle::FormatID::R32G32_SINT, WGPUTextureFormat_RG32Sint}, + {angle::FormatID::R32G32_UINT, WGPUTextureFormat_RG32Uint}, + {angle::FormatID::R32_FLOAT, WGPUTextureFormat_R32Float}, + {angle::FormatID::R32_SINT, WGPUTextureFormat_R32Sint}, + {angle::FormatID::R32_UINT, WGPUTextureFormat_R32Uint}, + {angle::FormatID::R8G8B8A8_SINT, WGPUTextureFormat_RGBA8Sint}, + {angle::FormatID::R8G8B8A8_SNORM, WGPUTextureFormat_RGBA8Snorm}, + {angle::FormatID::R8G8B8A8_UINT, WGPUTextureFormat_RGBA8Uint}, + {angle::FormatID::R8G8B8A8_UNORM, WGPUTextureFormat_RGBA8Unorm}, + {angle::FormatID::R8G8B8A8_UNORM_SRGB, WGPUTextureFormat_RGBA8UnormSrgb}, + {angle::FormatID::R8G8_SINT, WGPUTextureFormat_RG8Sint}, + {angle::FormatID::R8G8_SNORM, WGPUTextureFormat_RG8Snorm}, + {angle::FormatID::R8G8_UINT, WGPUTextureFormat_RG8Uint}, + {angle::FormatID::R8G8_UNORM, WGPUTextureFormat_RG8Unorm}, + {angle::FormatID::R8_SINT, WGPUTextureFormat_R8Sint}, + {angle::FormatID::R8_SNORM, WGPUTextureFormat_R8Snorm}, + {angle::FormatID::R8_UINT, WGPUTextureFormat_R8Uint}, + {angle::FormatID::R8_UNORM, WGPUTextureFormat_R8Unorm}, + {angle::FormatID::R9G9B9E5_SHAREDEXP, WGPUTextureFormat_RGB9E5Ufloat}, + {angle::FormatID::S8_UINT, WGPUTextureFormat_Stencil8}}; return kMap[formatID]; } -angle::FormatID GetFormatIDFromWgpuTextureFormat(wgpu::TextureFormat wgpuFormat) +angle::FormatID GetFormatIDFromWgpuTextureFormat(WGPUTextureFormat wgpuFormat) { switch (wgpuFormat) { - case wgpu::TextureFormat::ASTC10x10UnormSrgb: + case WGPUTextureFormat_ASTC10x10UnormSrgb: return angle::FormatID::ASTC_10x10_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC10x10Unorm: + case WGPUTextureFormat_ASTC10x10Unorm: return angle::FormatID::ASTC_10x10_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC10x5UnormSrgb: + case WGPUTextureFormat_ASTC10x5UnormSrgb: return angle::FormatID::ASTC_10x5_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC10x5Unorm: + case WGPUTextureFormat_ASTC10x5Unorm: return angle::FormatID::ASTC_10x5_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC10x6UnormSrgb: + case WGPUTextureFormat_ASTC10x6UnormSrgb: return angle::FormatID::ASTC_10x6_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC10x6Unorm: + case WGPUTextureFormat_ASTC10x6Unorm: return angle::FormatID::ASTC_10x6_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC10x8UnormSrgb: + case WGPUTextureFormat_ASTC10x8UnormSrgb: return angle::FormatID::ASTC_10x8_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC10x8Unorm: + case WGPUTextureFormat_ASTC10x8Unorm: return angle::FormatID::ASTC_10x8_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC12x10UnormSrgb: + case WGPUTextureFormat_ASTC12x10UnormSrgb: return angle::FormatID::ASTC_12x10_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC12x10Unorm: + case WGPUTextureFormat_ASTC12x10Unorm: return angle::FormatID::ASTC_12x10_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC12x12UnormSrgb: + case WGPUTextureFormat_ASTC12x12UnormSrgb: return angle::FormatID::ASTC_12x12_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC12x12Unorm: + case WGPUTextureFormat_ASTC12x12Unorm: return angle::FormatID::ASTC_12x12_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC4x4UnormSrgb: + case WGPUTextureFormat_ASTC4x4UnormSrgb: return angle::FormatID::ASTC_4x4_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC4x4Unorm: + case WGPUTextureFormat_ASTC4x4Unorm: return angle::FormatID::ASTC_4x4_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC5x4UnormSrgb: + case WGPUTextureFormat_ASTC5x4UnormSrgb: return angle::FormatID::ASTC_5x4_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC5x4Unorm: + case WGPUTextureFormat_ASTC5x4Unorm: return angle::FormatID::ASTC_5x4_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC5x5UnormSrgb: + case WGPUTextureFormat_ASTC5x5UnormSrgb: return angle::FormatID::ASTC_5x5_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC5x5Unorm: + case WGPUTextureFormat_ASTC5x5Unorm: return angle::FormatID::ASTC_5x5_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC6x5UnormSrgb: + case WGPUTextureFormat_ASTC6x5UnormSrgb: return angle::FormatID::ASTC_6x5_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC6x5Unorm: + case WGPUTextureFormat_ASTC6x5Unorm: return angle::FormatID::ASTC_6x5_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC6x6UnormSrgb: + case WGPUTextureFormat_ASTC6x6UnormSrgb: return angle::FormatID::ASTC_6x6_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC6x6Unorm: + case WGPUTextureFormat_ASTC6x6Unorm: return angle::FormatID::ASTC_6x6_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC8x5UnormSrgb: + case WGPUTextureFormat_ASTC8x5UnormSrgb: return angle::FormatID::ASTC_8x5_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC8x5Unorm: + case WGPUTextureFormat_ASTC8x5Unorm: return angle::FormatID::ASTC_8x5_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC8x6UnormSrgb: + case WGPUTextureFormat_ASTC8x6UnormSrgb: return angle::FormatID::ASTC_8x6_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC8x6Unorm: + case WGPUTextureFormat_ASTC8x6Unorm: return angle::FormatID::ASTC_8x6_UNORM_BLOCK; - case wgpu::TextureFormat::ASTC8x8UnormSrgb: + case WGPUTextureFormat_ASTC8x8UnormSrgb: return angle::FormatID::ASTC_8x8_SRGB_BLOCK; - case wgpu::TextureFormat::ASTC8x8Unorm: + case WGPUTextureFormat_ASTC8x8Unorm: return angle::FormatID::ASTC_8x8_UNORM_BLOCK; - case wgpu::TextureFormat::BGRA8Unorm: + case WGPUTextureFormat_BGRA8Unorm: return angle::FormatID::B8G8R8A8_UNORM; - case wgpu::TextureFormat::BGRA8UnormSrgb: + case WGPUTextureFormat_BGRA8UnormSrgb: return angle::FormatID::B8G8R8A8_UNORM_SRGB; - case wgpu::TextureFormat::BC1RGBAUnorm: + case WGPUTextureFormat_BC1RGBAUnorm: return angle::FormatID::BC1_RGBA_UNORM_BLOCK; - case wgpu::TextureFormat::BC1RGBAUnormSrgb: + case WGPUTextureFormat_BC1RGBAUnormSrgb: return angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK; - case wgpu::TextureFormat::BC2RGBAUnorm: + case WGPUTextureFormat_BC2RGBAUnorm: return angle::FormatID::BC2_RGBA_UNORM_BLOCK; - case wgpu::TextureFormat::BC2RGBAUnormSrgb: + case WGPUTextureFormat_BC2RGBAUnormSrgb: return angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK; - case wgpu::TextureFormat::BC3RGBAUnorm: + case WGPUTextureFormat_BC3RGBAUnorm: return angle::FormatID::BC3_RGBA_UNORM_BLOCK; - case wgpu::TextureFormat::BC3RGBAUnormSrgb: + case WGPUTextureFormat_BC3RGBAUnormSrgb: return angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK; - case wgpu::TextureFormat::BC4RSnorm: + case WGPUTextureFormat_BC4RSnorm: return angle::FormatID::BC4_RED_SNORM_BLOCK; - case wgpu::TextureFormat::BC4RUnorm: + case WGPUTextureFormat_BC4RUnorm: return angle::FormatID::BC4_RED_UNORM_BLOCK; - case wgpu::TextureFormat::BC5RGSnorm: + case WGPUTextureFormat_BC5RGSnorm: return angle::FormatID::BC5_RG_SNORM_BLOCK; - case wgpu::TextureFormat::BC5RGUnorm: + case WGPUTextureFormat_BC5RGUnorm: return angle::FormatID::BC5_RG_UNORM_BLOCK; - case wgpu::TextureFormat::BC6HRGBFloat: + case WGPUTextureFormat_BC6HRGBFloat: return angle::FormatID::BC6H_RGB_SFLOAT_BLOCK; - case wgpu::TextureFormat::BC6HRGBUfloat: + case WGPUTextureFormat_BC6HRGBUfloat: return angle::FormatID::BC6H_RGB_UFLOAT_BLOCK; - case wgpu::TextureFormat::BC7RGBAUnorm: + case WGPUTextureFormat_BC7RGBAUnorm: return angle::FormatID::BC7_RGBA_UNORM_BLOCK; - case wgpu::TextureFormat::BC7RGBAUnormSrgb: + case WGPUTextureFormat_BC7RGBAUnormSrgb: return angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK; - case wgpu::TextureFormat::Depth16Unorm: + case WGPUTextureFormat_Depth16Unorm: return angle::FormatID::D16_UNORM; - case wgpu::TextureFormat::Depth24PlusStencil8: + case WGPUTextureFormat_Depth24PlusStencil8: return angle::FormatID::D24_UNORM_S8_UINT; - case wgpu::TextureFormat::Depth32Float: + case WGPUTextureFormat_Depth32Float: return angle::FormatID::D32_FLOAT; - case wgpu::TextureFormat::EACRG11Snorm: + case WGPUTextureFormat_EACRG11Snorm: return angle::FormatID::EAC_R11G11_SNORM_BLOCK; - case wgpu::TextureFormat::EACRG11Unorm: + case WGPUTextureFormat_EACRG11Unorm: return angle::FormatID::EAC_R11G11_UNORM_BLOCK; - case wgpu::TextureFormat::EACR11Snorm: + case WGPUTextureFormat_EACR11Snorm: return angle::FormatID::EAC_R11_SNORM_BLOCK; - case wgpu::TextureFormat::EACR11Unorm: + case WGPUTextureFormat_EACR11Unorm: return angle::FormatID::EAC_R11_UNORM_BLOCK; - case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb: + case WGPUTextureFormat_ETC2RGB8A1UnormSrgb: return angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK; - case wgpu::TextureFormat::ETC2RGB8A1Unorm: + case WGPUTextureFormat_ETC2RGB8A1Unorm: return angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK; - case wgpu::TextureFormat::ETC2RGBA8UnormSrgb: + case WGPUTextureFormat_ETC2RGBA8UnormSrgb: return angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK; - case wgpu::TextureFormat::ETC2RGBA8Unorm: + case WGPUTextureFormat_ETC2RGBA8Unorm: return angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK; - case wgpu::TextureFormat::ETC2RGB8UnormSrgb: + case WGPUTextureFormat_ETC2RGB8UnormSrgb: return angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK; - case wgpu::TextureFormat::ETC2RGB8Unorm: + case WGPUTextureFormat_ETC2RGB8Unorm: return angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK; - case wgpu::TextureFormat::Undefined: + case WGPUTextureFormat_Undefined: return angle::FormatID::NONE; - case wgpu::TextureFormat::RGB10A2Uint: + case WGPUTextureFormat_RGB10A2Uint: return angle::FormatID::R10G10B10A2_SINT; - case wgpu::TextureFormat::RGB10A2Unorm: + case WGPUTextureFormat_RGB10A2Unorm: return angle::FormatID::R10G10B10A2_UNORM; - case wgpu::TextureFormat::RG11B10Ufloat: + case WGPUTextureFormat_RG11B10Ufloat: return angle::FormatID::R11G11B10_FLOAT; - case wgpu::TextureFormat::RGBA16Float: + case WGPUTextureFormat_RGBA16Float: return angle::FormatID::R16G16B16A16_FLOAT; - case wgpu::TextureFormat::RGBA16Sint: + case WGPUTextureFormat_RGBA16Sint: return angle::FormatID::R16G16B16A16_SINT; - case wgpu::TextureFormat::RGBA16Snorm: + case WGPUTextureFormat_RGBA16Snorm: return angle::FormatID::R16G16B16A16_SNORM; - case wgpu::TextureFormat::RGBA16Uint: + case WGPUTextureFormat_RGBA16Uint: return angle::FormatID::R16G16B16A16_UINT; - case wgpu::TextureFormat::RGBA16Unorm: + case WGPUTextureFormat_RGBA16Unorm: return angle::FormatID::R16G16B16A16_UNORM; - case wgpu::TextureFormat::RG16Float: + case WGPUTextureFormat_RG16Float: return angle::FormatID::R16G16_FLOAT; - case wgpu::TextureFormat::RG16Sint: + case WGPUTextureFormat_RG16Sint: return angle::FormatID::R16G16_SINT; - case wgpu::TextureFormat::RG16Snorm: + case WGPUTextureFormat_RG16Snorm: return angle::FormatID::R16G16_SNORM; - case wgpu::TextureFormat::RG16Uint: + case WGPUTextureFormat_RG16Uint: return angle::FormatID::R16G16_UINT; - case wgpu::TextureFormat::RG16Unorm: + case WGPUTextureFormat_RG16Unorm: return angle::FormatID::R16G16_UNORM; - case wgpu::TextureFormat::R16Float: + case WGPUTextureFormat_R16Float: return angle::FormatID::R16_FLOAT; - case wgpu::TextureFormat::R16Sint: + case WGPUTextureFormat_R16Sint: return angle::FormatID::R16_SINT; - case wgpu::TextureFormat::R16Snorm: + case WGPUTextureFormat_R16Snorm: return angle::FormatID::R16_SNORM; - case wgpu::TextureFormat::R16Uint: + case WGPUTextureFormat_R16Uint: return angle::FormatID::R16_UINT; - case wgpu::TextureFormat::R16Unorm: + case WGPUTextureFormat_R16Unorm: return angle::FormatID::R16_UNORM; - case wgpu::TextureFormat::RGBA32Float: + case WGPUTextureFormat_RGBA32Float: return angle::FormatID::R32G32B32A32_FLOAT; - case wgpu::TextureFormat::RGBA32Sint: + case WGPUTextureFormat_RGBA32Sint: return angle::FormatID::R32G32B32A32_SINT; - case wgpu::TextureFormat::RGBA32Uint: + case WGPUTextureFormat_RGBA32Uint: return angle::FormatID::R32G32B32A32_UINT; - case wgpu::TextureFormat::RG32Float: + case WGPUTextureFormat_RG32Float: return angle::FormatID::R32G32_FLOAT; - case wgpu::TextureFormat::RG32Sint: + case WGPUTextureFormat_RG32Sint: return angle::FormatID::R32G32_SINT; - case wgpu::TextureFormat::RG32Uint: + case WGPUTextureFormat_RG32Uint: return angle::FormatID::R32G32_UINT; - case wgpu::TextureFormat::R32Float: + case WGPUTextureFormat_R32Float: return angle::FormatID::R32_FLOAT; - case wgpu::TextureFormat::R32Sint: + case WGPUTextureFormat_R32Sint: return angle::FormatID::R32_SINT; - case wgpu::TextureFormat::R32Uint: + case WGPUTextureFormat_R32Uint: return angle::FormatID::R32_UINT; - case wgpu::TextureFormat::RGBA8Sint: + case WGPUTextureFormat_RGBA8Sint: return angle::FormatID::R8G8B8A8_SINT; - case wgpu::TextureFormat::RGBA8Snorm: + case WGPUTextureFormat_RGBA8Snorm: return angle::FormatID::R8G8B8A8_SNORM; - case wgpu::TextureFormat::RGBA8Uint: + case WGPUTextureFormat_RGBA8Uint: return angle::FormatID::R8G8B8A8_UINT; - case wgpu::TextureFormat::RGBA8Unorm: + case WGPUTextureFormat_RGBA8Unorm: return angle::FormatID::R8G8B8A8_UNORM; - case wgpu::TextureFormat::RGBA8UnormSrgb: + case WGPUTextureFormat_RGBA8UnormSrgb: return angle::FormatID::R8G8B8A8_UNORM_SRGB; - case wgpu::TextureFormat::RG8Sint: + case WGPUTextureFormat_RG8Sint: return angle::FormatID::R8G8_SINT; - case wgpu::TextureFormat::RG8Snorm: + case WGPUTextureFormat_RG8Snorm: return angle::FormatID::R8G8_SNORM; - case wgpu::TextureFormat::RG8Uint: + case WGPUTextureFormat_RG8Uint: return angle::FormatID::R8G8_UINT; - case wgpu::TextureFormat::RG8Unorm: + case WGPUTextureFormat_RG8Unorm: return angle::FormatID::R8G8_UNORM; - case wgpu::TextureFormat::R8Sint: + case WGPUTextureFormat_R8Sint: return angle::FormatID::R8_SINT; - case wgpu::TextureFormat::R8Snorm: + case WGPUTextureFormat_R8Snorm: return angle::FormatID::R8_SNORM; - case wgpu::TextureFormat::R8Uint: + case WGPUTextureFormat_R8Uint: return angle::FormatID::R8_UINT; - case wgpu::TextureFormat::R8Unorm: + case WGPUTextureFormat_R8Unorm: return angle::FormatID::R8_UNORM; - case wgpu::TextureFormat::RGB9E5Ufloat: + case WGPUTextureFormat_RGB9E5Ufloat: return angle::FormatID::R9G9B9E5_SHAREDEXP; - case wgpu::TextureFormat::Stencil8: + case WGPUTextureFormat_Stencil8: return angle::FormatID::S8_UINT; default: @@ -2399,106 +2419,106 @@ angle::FormatID GetFormatIDFromWgpuTextureFormat(wgpu::TextureFormat wgpuFormat) } } -wgpu::VertexFormat GetWgpuVertexFormatFromFormatID(angle::FormatID formatID) +WGPUVertexFormat GetWgpuVertexFormatFromFormatID(angle::FormatID formatID) { - static constexpr angle::FormatMap kMap = { - {angle::FormatID::EXTERNAL0, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL1, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL2, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL3, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL4, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL5, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL6, wgpu::VertexFormat(0u)}, - {angle::FormatID::EXTERNAL7, wgpu::VertexFormat(0u)}, - {angle::FormatID::NONE, wgpu::VertexFormat(0u)}, - {angle::FormatID::R10G10B10A2_UNORM, wgpu::VertexFormat::Unorm10_10_10_2}, - {angle::FormatID::R16G16B16A16_FLOAT, wgpu::VertexFormat::Float16x4}, - {angle::FormatID::R16G16B16A16_SINT, wgpu::VertexFormat::Sint16x4}, - {angle::FormatID::R16G16B16A16_SNORM, wgpu::VertexFormat::Snorm16x4}, - {angle::FormatID::R16G16B16A16_UINT, wgpu::VertexFormat::Uint16x4}, - {angle::FormatID::R16G16B16A16_UNORM, wgpu::VertexFormat::Unorm16x4}, - {angle::FormatID::R16G16_FLOAT, wgpu::VertexFormat::Float16x2}, - {angle::FormatID::R16G16_SINT, wgpu::VertexFormat::Sint16x2}, - {angle::FormatID::R16G16_SNORM, wgpu::VertexFormat::Snorm16x2}, - {angle::FormatID::R16G16_UINT, wgpu::VertexFormat::Uint16x2}, - {angle::FormatID::R16G16_UNORM, wgpu::VertexFormat::Unorm16x2}, - {angle::FormatID::R32G32B32A32_FLOAT, wgpu::VertexFormat::Float32x4}, - {angle::FormatID::R32G32B32A32_SINT, wgpu::VertexFormat::Sint32x4}, - {angle::FormatID::R32G32B32A32_UINT, wgpu::VertexFormat::Uint32x4}, - {angle::FormatID::R32G32B32_FLOAT, wgpu::VertexFormat::Float32x3}, - {angle::FormatID::R32G32B32_SINT, wgpu::VertexFormat::Sint32x3}, - {angle::FormatID::R32G32B32_UINT, wgpu::VertexFormat::Uint32x3}, - {angle::FormatID::R32G32_FLOAT, wgpu::VertexFormat::Float32x2}, - {angle::FormatID::R32G32_SINT, wgpu::VertexFormat::Sint32x2}, - {angle::FormatID::R32G32_UINT, wgpu::VertexFormat::Uint32x2}, - {angle::FormatID::R32_FLOAT, wgpu::VertexFormat::Float32}, - {angle::FormatID::R32_SINT, wgpu::VertexFormat::Sint32}, - {angle::FormatID::R32_UINT, wgpu::VertexFormat::Uint32}, - {angle::FormatID::R8G8B8A8_SINT, wgpu::VertexFormat::Sint8x4}, - {angle::FormatID::R8G8B8A8_SNORM, wgpu::VertexFormat::Snorm8x4}, - {angle::FormatID::R8G8B8A8_UINT, wgpu::VertexFormat::Uint8x4}, - {angle::FormatID::R8G8B8A8_UNORM, wgpu::VertexFormat::Unorm8x4}}; + static constexpr angle::FormatMap kMap = { + {angle::FormatID::EXTERNAL0, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL1, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL2, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL3, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL4, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL5, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL6, WGPUVertexFormat(0u)}, + {angle::FormatID::EXTERNAL7, WGPUVertexFormat(0u)}, + {angle::FormatID::NONE, WGPUVertexFormat(0u)}, + {angle::FormatID::R10G10B10A2_UNORM, WGPUVertexFormat_Unorm10_10_10_2}, + {angle::FormatID::R16G16B16A16_FLOAT, WGPUVertexFormat_Float16x4}, + {angle::FormatID::R16G16B16A16_SINT, WGPUVertexFormat_Sint16x4}, + {angle::FormatID::R16G16B16A16_SNORM, WGPUVertexFormat_Snorm16x4}, + {angle::FormatID::R16G16B16A16_UINT, WGPUVertexFormat_Uint16x4}, + {angle::FormatID::R16G16B16A16_UNORM, WGPUVertexFormat_Unorm16x4}, + {angle::FormatID::R16G16_FLOAT, WGPUVertexFormat_Float16x2}, + {angle::FormatID::R16G16_SINT, WGPUVertexFormat_Sint16x2}, + {angle::FormatID::R16G16_SNORM, WGPUVertexFormat_Snorm16x2}, + {angle::FormatID::R16G16_UINT, WGPUVertexFormat_Uint16x2}, + {angle::FormatID::R16G16_UNORM, WGPUVertexFormat_Unorm16x2}, + {angle::FormatID::R32G32B32A32_FLOAT, WGPUVertexFormat_Float32x4}, + {angle::FormatID::R32G32B32A32_SINT, WGPUVertexFormat_Sint32x4}, + {angle::FormatID::R32G32B32A32_UINT, WGPUVertexFormat_Uint32x4}, + {angle::FormatID::R32G32B32_FLOAT, WGPUVertexFormat_Float32x3}, + {angle::FormatID::R32G32B32_SINT, WGPUVertexFormat_Sint32x3}, + {angle::FormatID::R32G32B32_UINT, WGPUVertexFormat_Uint32x3}, + {angle::FormatID::R32G32_FLOAT, WGPUVertexFormat_Float32x2}, + {angle::FormatID::R32G32_SINT, WGPUVertexFormat_Sint32x2}, + {angle::FormatID::R32G32_UINT, WGPUVertexFormat_Uint32x2}, + {angle::FormatID::R32_FLOAT, WGPUVertexFormat_Float32}, + {angle::FormatID::R32_SINT, WGPUVertexFormat_Sint32}, + {angle::FormatID::R32_UINT, WGPUVertexFormat_Uint32}, + {angle::FormatID::R8G8B8A8_SINT, WGPUVertexFormat_Sint8x4}, + {angle::FormatID::R8G8B8A8_SNORM, WGPUVertexFormat_Snorm8x4}, + {angle::FormatID::R8G8B8A8_UINT, WGPUVertexFormat_Uint8x4}, + {angle::FormatID::R8G8B8A8_UNORM, WGPUVertexFormat_Unorm8x4}}; return kMap[formatID]; } -angle::FormatID GetFormatIDFromWgpuBufferFormat(wgpu::VertexFormat wgpuFormat) +angle::FormatID GetFormatIDFromWgpuBufferFormat(WGPUVertexFormat wgpuFormat) { switch (wgpuFormat) { - case wgpu::VertexFormat::Unorm10_10_10_2: + case WGPUVertexFormat_Unorm10_10_10_2: return angle::FormatID::R10G10B10A2_UNORM; - case wgpu::VertexFormat::Float16x4: + case WGPUVertexFormat_Float16x4: return angle::FormatID::R16G16B16A16_FLOAT; - case wgpu::VertexFormat::Sint16x4: + case WGPUVertexFormat_Sint16x4: return angle::FormatID::R16G16B16A16_SINT; - case wgpu::VertexFormat::Snorm16x4: + case WGPUVertexFormat_Snorm16x4: return angle::FormatID::R16G16B16A16_SNORM; - case wgpu::VertexFormat::Uint16x4: + case WGPUVertexFormat_Uint16x4: return angle::FormatID::R16G16B16A16_UINT; - case wgpu::VertexFormat::Unorm16x4: + case WGPUVertexFormat_Unorm16x4: return angle::FormatID::R16G16B16A16_UNORM; - case wgpu::VertexFormat::Float16x2: + case WGPUVertexFormat_Float16x2: return angle::FormatID::R16G16_FLOAT; - case wgpu::VertexFormat::Sint16x2: + case WGPUVertexFormat_Sint16x2: return angle::FormatID::R16G16_SINT; - case wgpu::VertexFormat::Snorm16x2: + case WGPUVertexFormat_Snorm16x2: return angle::FormatID::R16G16_SNORM; - case wgpu::VertexFormat::Uint16x2: + case WGPUVertexFormat_Uint16x2: return angle::FormatID::R16G16_UINT; - case wgpu::VertexFormat::Unorm16x2: + case WGPUVertexFormat_Unorm16x2: return angle::FormatID::R16G16_UNORM; - case wgpu::VertexFormat::Float32x4: + case WGPUVertexFormat_Float32x4: return angle::FormatID::R32G32B32A32_FLOAT; - case wgpu::VertexFormat::Sint32x4: + case WGPUVertexFormat_Sint32x4: return angle::FormatID::R32G32B32A32_SINT; - case wgpu::VertexFormat::Uint32x4: + case WGPUVertexFormat_Uint32x4: return angle::FormatID::R32G32B32A32_UINT; - case wgpu::VertexFormat::Float32x3: + case WGPUVertexFormat_Float32x3: return angle::FormatID::R32G32B32_FLOAT; - case wgpu::VertexFormat::Sint32x3: + case WGPUVertexFormat_Sint32x3: return angle::FormatID::R32G32B32_SINT; - case wgpu::VertexFormat::Uint32x3: + case WGPUVertexFormat_Uint32x3: return angle::FormatID::R32G32B32_UINT; - case wgpu::VertexFormat::Float32x2: + case WGPUVertexFormat_Float32x2: return angle::FormatID::R32G32_FLOAT; - case wgpu::VertexFormat::Sint32x2: + case WGPUVertexFormat_Sint32x2: return angle::FormatID::R32G32_SINT; - case wgpu::VertexFormat::Uint32x2: + case WGPUVertexFormat_Uint32x2: return angle::FormatID::R32G32_UINT; - case wgpu::VertexFormat::Float32: + case WGPUVertexFormat_Float32: return angle::FormatID::R32_FLOAT; - case wgpu::VertexFormat::Sint32: + case WGPUVertexFormat_Sint32: return angle::FormatID::R32_SINT; - case wgpu::VertexFormat::Uint32: + case WGPUVertexFormat_Uint32: return angle::FormatID::R32_UINT; - case wgpu::VertexFormat::Sint8x4: + case WGPUVertexFormat_Sint8x4: return angle::FormatID::R8G8B8A8_SINT; - case wgpu::VertexFormat::Snorm8x4: + case WGPUVertexFormat_Snorm8x4: return angle::FormatID::R8G8B8A8_SNORM; - case wgpu::VertexFormat::Uint8x4: + case WGPUVertexFormat_Uint8x4: return angle::FormatID::R8G8B8A8_UINT; - case wgpu::VertexFormat::Unorm8x4: + case WGPUVertexFormat_Unorm8x4: return angle::FormatID::R8G8B8A8_UNORM; default: diff --git a/src/libANGLE/renderer/wgpu/wgpu_format_utils.cpp b/src/libANGLE/renderer/wgpu/wgpu_format_utils.cpp index 1a1420a647f..332d15c0dd7 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_format_utils.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_format_utils.cpp @@ -67,5 +67,22 @@ void FormatTable::initialize() } } } + +const Format *FormatTable::findClosestTextureFormat(WGPUTextureFormat wgpuFormat) const +{ + for (const Format &format : mFormatData) + { + // Accept formats with WGPUTextureFormats that match the request and are 1:1 with their + // intended format (not a fallback for something else) + if (format.getActualWgpuTextureFormat() == wgpuFormat && + format.getIntendedFormatID() == format.getActualImageFormatID()) + { + return &format; + } + } + + return nullptr; +} + } // namespace webgpu } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/wgpu_format_utils.h b/src/libANGLE/renderer/wgpu/wgpu_format_utils.h index 7454ebf74e9..cddc8faa62d 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_format_utils.h +++ b/src/libANGLE/renderer/wgpu/wgpu_format_utils.h @@ -9,7 +9,7 @@ #ifndef LIBANGLE_RENDERER_WGPU_WGPU_FORMAT_UTILS_H_ #define LIBANGLE_RENDERER_WGPU_WGPU_FORMAT_UTILS_H_ -#include +#include #include "libANGLE/formatutils.h" #include "libANGLE/renderer/Format.h" @@ -33,10 +33,10 @@ struct BufferFormatInitInfo final bool VertexLoadRequiresConversion; }; -wgpu::TextureFormat GetWgpuTextureFormatFromFormatID(angle::FormatID formatID); -angle::FormatID GetFormatIDFromWgpuTextureFormat(wgpu::TextureFormat wgpuFormat); -wgpu::VertexFormat GetWgpuVertexFormatFromFormatID(angle::FormatID formatID); -angle::FormatID GetFormatIDFromWgpuBufferFormat(wgpu::VertexFormat wgpuFormat); +WGPUTextureFormat GetWgpuTextureFormatFromFormatID(angle::FormatID formatID); +angle::FormatID GetFormatIDFromWgpuTextureFormat(WGPUTextureFormat wgpuFormat); +WGPUVertexFormat GetWgpuVertexFormatFromFormatID(angle::FormatID formatID); +angle::FormatID GetFormatIDFromWgpuBufferFormat(WGPUVertexFormat wgpuFormat); // Describes a WebGPU format. WebGPU has separate formats for images and vertex buffers, this class // describes both. @@ -64,13 +64,13 @@ class Format final : private angle::NonCopyable return mTextureLoadFunctions(type); } - wgpu::TextureFormat getActualWgpuTextureFormat() const + WGPUTextureFormat getActualWgpuTextureFormat() const { return GetWgpuTextureFormatFromFormatID(mActualImageFormatID); } angle::FormatID getActualImageFormatID() const { return mActualImageFormatID; } - wgpu::VertexFormat getActualWgpuVertexFormat() const + WGPUVertexFormat getActualWgpuVertexFormat() const { return GetWgpuVertexFormatFromFormatID(mActualBufferFormatID); } @@ -138,6 +138,8 @@ class FormatTable final : angle::NonCopyable return mFormatData[static_cast(formatID)]; } + const Format *findClosestTextureFormat(WGPUTextureFormat wgpuFormat) const; + private: // The table data is indexed by angle::FormatID. std::array mFormatData; diff --git a/src/libANGLE/renderer/wgpu/wgpu_helpers.cpp b/src/libANGLE/renderer/wgpu/wgpu_helpers.cpp index 0a056285269..b700fa6d2b5 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_helpers.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_helpers.cpp @@ -4,13 +4,22 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/wgpu_helpers.h" -#include "libANGLE/formatutils.h" +#include + +#include "common/PackedGLEnums_autogen.h" +#include "dawn/dawn_proc_table.h" +#include "libANGLE/formatutils.h" #include "libANGLE/renderer/wgpu/ContextWgpu.h" #include "libANGLE/renderer/wgpu/DisplayWgpu.h" #include "libANGLE/renderer/wgpu/FramebufferWgpu.h" -#include "wgpu_helpers.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" +#include "webgpu/webgpu.h" namespace rx { @@ -18,15 +27,17 @@ namespace webgpu { namespace { -wgpu::TextureDescriptor TextureDescriptorFromTexture(const wgpu::Texture &texture) -{ - wgpu::TextureDescriptor descriptor = {}; - descriptor.usage = texture.GetUsage(); - descriptor.dimension = texture.GetDimension(); - descriptor.size = {texture.GetWidth(), texture.GetHeight(), texture.GetDepthOrArrayLayers()}; - descriptor.format = texture.GetFormat(); - descriptor.mipLevelCount = texture.GetMipLevelCount(); - descriptor.sampleCount = texture.GetSampleCount(); +WGPUTextureDescriptor TextureDescriptorFromTexture(const DawnProcTable *wgpu, + const webgpu::TextureHandle &texture) +{ + WGPUTextureDescriptor descriptor = WGPU_TEXTURE_DESCRIPTOR_INIT; + descriptor.usage = wgpu->textureGetUsage(texture.get()); + descriptor.dimension = wgpu->textureGetDimension(texture.get()); + descriptor.size = {wgpu->textureGetWidth(texture.get()), wgpu->textureGetHeight(texture.get()), + wgpu->textureGetDepthOrArrayLayers(texture.get())}; + descriptor.format = wgpu->textureGetFormat(texture.get()); + descriptor.mipLevelCount = wgpu->textureGetMipLevelCount(texture.get()); + descriptor.sampleCount = wgpu->textureGetSampleCount(texture.get()); descriptor.viewFormatCount = 0; return descriptor; } @@ -58,35 +69,64 @@ const uint8_t *AdjustMapPointerForOffset(const uint8_t *mapPtr, size_t offset) return AdjustMapPointerForOffset(const_cast(mapPtr), offset); } +angle::Result GetCheckedAllocationSizeAndRowPitch(uint32_t rowBytes, + uint32_t width, + uint32_t height, + uint32_t *outputRowPitchOut, + uint32_t *allocationSizeOut) +{ + angle::CheckedNumeric checkedOutputRowPitch = rx::CheckedRoundUp( + static_cast(angle::base::CheckMul(rowBytes, width).ValueOrDie()), + static_cast(webgpu::kTextureRowSizeAlignment)); + + angle::CheckedNumeric checkedAllocationSize = rx::CheckedRoundUpPow2( + static_cast(angle::base::CheckMul(checkedOutputRowPitch, height).ValueOrDie()), + static_cast(kBufferSizeAlignment)); + + if (!checkedAllocationSize.AssignIfValid(allocationSizeOut) || + !checkedOutputRowPitch.AssignIfValid(outputRowPitchOut)) + { + ERR() << "Calculating allocation size and output row pitch for an image copy failed."; + return angle::Result::Stop; + } + + return angle::Result::Continue; +} + } // namespace ImageHelper::ImageHelper() {} ImageHelper::~ImageHelper() {} -angle::Result ImageHelper::initImage(angle::FormatID intendedFormatID, +angle::Result ImageHelper::initImage(const DawnProcTable *wgpu, + angle::FormatID intendedFormatID, angle::FormatID actualFormatID, - wgpu::Device &device, + DeviceHandle device, gl::LevelIndex firstAllocatedLevel, - wgpu::TextureDescriptor textureDescriptor) + WGPUTextureDescriptor textureDescriptor) { + mProcTable = wgpu; mIntendedFormatID = intendedFormatID; mActualFormatID = actualFormatID; mTextureDescriptor = textureDescriptor; mFirstAllocatedLevel = firstAllocatedLevel; - mTexture = device.CreateTexture(&mTextureDescriptor); + mTexture = + TextureHandle::Acquire(wgpu, wgpu->deviceCreateTexture(device.get(), &mTextureDescriptor)); mInitialized = true; return angle::Result::Continue; } -angle::Result ImageHelper::initExternal(angle::FormatID intendedFormatID, +angle::Result ImageHelper::initExternal(const DawnProcTable *wgpu, + angle::FormatID intendedFormatID, angle::FormatID actualFormatID, - wgpu::Texture externalTexture) + webgpu::TextureHandle externalTexture) { + mProcTable = wgpu; mIntendedFormatID = intendedFormatID; mActualFormatID = actualFormatID; - mTextureDescriptor = TextureDescriptorFromTexture(externalTexture); + mTextureDescriptor = TextureDescriptorFromTexture(wgpu, externalTexture); mFirstAllocatedLevel = gl::LevelIndex(0); mTexture = externalTexture; mInitialized = true; @@ -118,14 +158,22 @@ angle::Result ImageHelper::flushSingleLevelUpdates(ContextWgpu *contextWgpu, { return angle::Result::Continue; } - wgpu::Device device = contextWgpu->getDevice(); - wgpu::Queue queue = contextWgpu->getQueue(); - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - wgpu::ImageCopyTexture dst; - dst.texture = mTexture; - std::vector colorAttachments; - wgpu::TextureView textureView; - ANGLE_TRY(createTextureView(levelGL, 0, textureView)); + + std::optional encoder; + auto ensureEncoder = [&]() -> angle::Result { + ANGLE_TRY(contextWgpu->getCurrentCommandEncoder( + webgpu::RenderPassClosureReason::CopyBufferToTexture, &encoder.emplace())); + return angle::Result::Continue; + }; + + WGPUTexelCopyTextureInfo dst = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT; + dst.texture = mTexture.get(); + std::vector colorAttachments; + TextureViewHandle textureView; + // Create a texture view of the entire level, layers and all. + ANGLE_TRY(createTextureView(levelGL, /*levelCount=*/1, /*layerIndex*/ 0, + mTextureDescriptor.size.depthOrArrayLayers, textureView, + WGPUTextureViewDimension_Undefined)); bool updateDepth = false; bool updateStencil = false; float depthValue = 1; @@ -139,9 +187,31 @@ angle::Result ImageHelper::flushSingleLevelUpdates(ContextWgpu *contextWgpu, switch (srcUpdate.updateSource) { case UpdateSource::Texture: - dst.mipLevel = toWgpuLevel(srcUpdate.targetLevel).get(); - encoder.CopyBufferToTexture(&srcUpdate.textureData, &dst, &mTextureDescriptor.size); - break; + { + LevelIndex wgpuLevel = toWgpuLevel(srcUpdate.targetLevel); + dst.mipLevel = wgpuLevel.get(); + WGPUExtent3D copyExtent = getLevelSize(wgpuLevel); + + // TODO(anglebug.com/389145696): copyExtent just always copies to the whole level. + // Should support smaller regions. + dst.origin = WGPUOrigin3D{0, 0, srcUpdate.layerIndex}; + // Updating multiple layers at once maybe not currently supported. + ASSERT(srcUpdate.layerCount == 1); + copyExtent.depthOrArrayLayers = srcUpdate.layerCount; + + if (!encoder.has_value()) + { + ANGLE_TRY(ensureEncoder()); + } + + WGPUTexelCopyBufferInfo copyInfo = WGPU_TEXEL_COPY_BUFFER_INFO_INIT; + copyInfo.layout = srcUpdate.textureDataLayout; + copyInfo.buffer = srcUpdate.textureData.get(); + mProcTable->commandEncoderCopyBufferToTexture(encoder.value().get(), ©Info, + &dst, ©Extent); + } + break; + case UpdateSource::Clear: if (deferredClears) { @@ -187,25 +257,22 @@ angle::Result ImageHelper::flushSingleLevelUpdates(ContextWgpu *contextWgpu, } if (updateDepth || updateStencil) { - frameBuffer->updateDepthStencilAttachment(CreateNewDepthStencilAttachment( + frameBuffer->updateDepthStencilAttachment(CreateNewClearDepthStencilAttachment( depthValue, stencilValue, textureView, updateDepth, updateStencil)); } - wgpu::CommandBuffer commandBuffer = encoder.Finish(); - queue.Submit(1, &commandBuffer); - encoder = nullptr; currentLevelQueue->clear(); return angle::Result::Continue; } -wgpu::TextureDescriptor ImageHelper::createTextureDescriptor(wgpu::TextureUsage usage, - wgpu::TextureDimension dimension, - wgpu::Extent3D size, - wgpu::TextureFormat format, - std::uint32_t mipLevelCount, - std::uint32_t sampleCount) +WGPUTextureDescriptor ImageHelper::createTextureDescriptor(WGPUTextureUsage usage, + WGPUTextureDimension dimension, + WGPUExtent3D size, + WGPUTextureFormat format, + std::uint32_t mipLevelCount, + std::uint32_t sampleCount) { - wgpu::TextureDescriptor textureDescriptor = {}; + WGPUTextureDescriptor textureDescriptor = WGPU_TEXTURE_DESCRIPTOR_INIT; textureDescriptor.usage = usage; textureDescriptor.dimension = dimension; textureDescriptor.size = size; @@ -232,12 +299,13 @@ angle::Result ImageHelper::stageTextureUpload(ContextWgpu *contextWgpu, { return angle::Result::Continue; } - wgpu::Device device = contextWgpu->getDevice(); - wgpu::Queue queue = contextWgpu->getQueue(); + mProcTable = webgpu::GetProcs(contextWgpu); + webgpu::DeviceHandle device = contextWgpu->getDevice(); gl::LevelIndex levelGL(index.getLevelIndex()); BufferHelper bufferHelper; - wgpu::BufferUsage usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; - ANGLE_TRY(bufferHelper.initBuffer(device, allocationSize, usage, MapAtCreation::Yes)); + WGPUBufferUsage usage = WGPUBufferUsage_CopySrc | WGPUBufferUsage_CopyDst; + ANGLE_TRY( + bufferHelper.initBuffer(mProcTable, device, allocationSize, usage, MapAtCreation::Yes)); LoadImageFunctionInfo loadFunctionInfo = webgpuFormat.getTextureLoadFunction(type); uint8_t *data = bufferHelper.getMapWritePointer(0, allocationSize); loadFunctionInfo.loadFunction(contextWgpu->getImageLoadContext(), glExtents.width, @@ -245,14 +313,16 @@ angle::Result ImageHelper::stageTextureUpload(ContextWgpu *contextWgpu, inputDepthPitch, data, outputRowPitch, outputDepthPitch); ANGLE_TRY(bufferHelper.unmap()); - wgpu::TextureDataLayout textureDataLayout = {}; + WGPUTexelCopyBufferLayout textureDataLayout = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT; textureDataLayout.bytesPerRow = outputRowPitch; textureDataLayout.rowsPerImage = outputDepthPitch; - wgpu::ImageCopyBuffer imageCopyBuffer; - imageCopyBuffer.layout = textureDataLayout; - imageCopyBuffer.buffer = bufferHelper.getBuffer(); - appendSubresourceUpdate(levelGL, - SubresourceUpdate(UpdateSource::Texture, levelGL, imageCopyBuffer)); + + GLint layerIndex = index.hasLayer() ? index.getLayerIndex() : 0; + + appendSubresourceUpdate( + levelGL, + SubresourceUpdate(UpdateSource::Texture, levelGL, layerIndex, index.getLayerCount(), + bufferHelper.getBuffer(), textureDataLayout)); return angle::Result::Continue; } @@ -265,6 +335,28 @@ void ImageHelper::stageClear(gl::LevelIndex targetLevel, clearValues, hasDepth, hasStencil)); } +void ImageHelper::removeSingleSubresourceStagedUpdates(gl::LevelIndex levelToRemove, + uint32_t layerIndex, + uint32_t layerCount) +{ + std::vector *updatesToClear = getLevelUpdates(levelToRemove); + if (!updatesToClear || updatesToClear->size() == 0) + { + return; + } + + for (int64_t i = updatesToClear->size() - 1; i >= 0; i--) + { + size_t index = static_cast(i); + // TODO(anglebug.com/420782526): maybe clear partial matches here. Vulkan backend does not. + if ((*updatesToClear)[index].layerIndex == layerIndex && + (*updatesToClear)[index].layerCount == layerCount) + { + updatesToClear->erase(updatesToClear->begin() + index); + } + } +} + void ImageHelper::removeStagedUpdates(gl::LevelIndex levelToRemove) { std::vector *updateToClear = getLevelUpdates(levelToRemove); @@ -276,11 +368,136 @@ void ImageHelper::removeStagedUpdates(gl::LevelIndex levelToRemove) void ImageHelper::resetImage() { - mTexture.Destroy(); - mTextureDescriptor = {}; + if (mTexture) + { + mProcTable->textureDestroy(mTexture.get()); + } + mProcTable = nullptr; + mTexture = nullptr; + mTextureDescriptor = WGPU_TEXTURE_DESCRIPTOR_INIT; mInitialized = false; mFirstAllocatedLevel = gl::LevelIndex(0); } + +angle::Result ImageHelper::CopyImage(ContextWgpu *contextWgpu, + ImageHelper *srcImage, + const gl::ImageIndex &dstIndex, + const gl::Offset &dstOffset, + gl::LevelIndex sourceLevelGL, + uint32_t sourceLayer, + const gl::Box &sourceBox) +{ + gl::LevelIndex dstLevel(dstIndex.getLevelIndex()); + uint32_t dstLayerOrZOffset = dstIndex.hasLayer() ? dstIndex.getLayerIndex() : dstOffset.z; + + WGPUTexelCopyTextureInfo src = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT; + src.texture = srcImage->getTexture().get(); + src.mipLevel = srcImage->toWgpuLevel(sourceLevelGL).get(); + src.origin.x = static_cast(sourceBox.x); + src.origin.y = static_cast(sourceBox.y); + src.origin.z = sourceLayer; + + WGPUTexelCopyTextureInfo dst = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT; + dst.texture = mTexture.get(); + dst.mipLevel = toWgpuLevel(dstLevel).get(); + dst.origin.x = static_cast(dstOffset.x); + dst.origin.y = static_cast(dstOffset.y); + dst.origin.z = dstLayerOrZOffset; + + WGPUExtent3D copySize = {static_cast(sourceBox.width), + static_cast(sourceBox.height), + static_cast(sourceBox.depth)}; + + webgpu::CommandEncoderHandle encoder; + ANGLE_TRY(contextWgpu->getCurrentCommandEncoder( + webgpu::RenderPassClosureReason::CopyTextureToTexture, &encoder)); + mProcTable->commandEncoderCopyTextureToTexture(encoder.get(), &src, &dst, ©Size); + + return angle::Result::Continue; +} + +angle::Result ImageHelper::copyImageCpuReadback(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Rectangle &sourceArea, + const gl::Offset &dstOffset, + const gl::Extents &dstExtent, + const gl::InternalFormat &formatInfo, + ImageHelper *srcImage, + const gl::Extents &srcExtents) +{ + ContextWgpu *contextWgpu = GetImpl(context); + mProcTable = webgpu::GetProcs(contextWgpu); + + const webgpu::Format &dstWebgpuFormat = contextWgpu->getFormat(formatInfo.sizedInternalFormat); + const angle::Format &storageFormat = dstWebgpuFormat.getActualImageFormat(); + LoadImageFunctionInfo loadFunctionInfo = + dstWebgpuFormat.getTextureLoadFunction(formatInfo.type); + + uint32_t allocationSize; + uint32_t outputRowPitch; + ANGLE_TRY(GetCheckedAllocationSizeAndRowPitch(storageFormat.pixelBytes, sourceArea.width, + sourceArea.height, &outputRowPitch, + &allocationSize)); + + BufferHelper stagingBuffer; + ANGLE_TRY(stagingBuffer.initBuffer(mProcTable, contextWgpu->getDevice(), allocationSize, + WGPUBufferUsage_CopySrc | WGPUBufferUsage_CopyDst, + MapAtCreation::Yes)); + + uint8_t *stagingPointer = stagingBuffer.getMapWritePointer(0, allocationSize); + const angle::Format ©Format = + GetFormatFromFormatType(formatInfo.internalFormat, formatInfo.type); + PackPixelsParams packPixelsParams(sourceArea, copyFormat, static_cast(outputRowPitch), + false, nullptr, 0); + + if (loadFunctionInfo.requiresConversion) + { + // When a conversion is required, we need to use the loadFunction to read from a temporary + // buffer instead so its an even slower path. + angle::MemoryBuffer memoryBuffer; + if (!memoryBuffer.resize(allocationSize)) + { + return angle::Result::Stop; + } + + // Read into the scratch buffer + ANGLE_TRY(srcImage->readPixels(contextWgpu, sourceArea, packPixelsParams, + srcImage->toWgpuLevel(gl::LevelIndex(0)), 0, + memoryBuffer.data())); + + // Load from scratch buffer to our pixel buffer + loadFunctionInfo.loadFunction(contextWgpu->getImageLoadContext(), sourceArea.width, + sourceArea.height, 1, memoryBuffer.data(), + packPixelsParams.outputPitch, 0, stagingPointer, + outputRowPitch, 0); + } + else + { + // We read directly from the framebuffer into our pixel buffer. + ANGLE_TRY(srcImage->readPixels(contextWgpu, sourceArea, packPixelsParams, + srcImage->toWgpuLevel(gl::LevelIndex(0)), 0, + stagingPointer)); + } + + ANGLE_TRY(stagingBuffer.unmap()); + + WGPUTexelCopyBufferLayout textureDataLayout = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT; + textureDataLayout.bytesPerRow = outputRowPitch; + textureDataLayout.rowsPerImage = sourceArea.height; + textureDataLayout.offset = + dstOffset.x * storageFormat.pixelBytes + dstOffset.y * outputRowPitch; + + gl::LevelIndex levelGL(index.getLevelIndex()); + GLint layerIndex = index.hasLayer() ? index.getLayerIndex() : 0; + + appendSubresourceUpdate( + levelGL, + SubresourceUpdate(UpdateSource::Texture, levelGL, layerIndex, index.getLayerCount(), + stagingBuffer.getBuffer(), textureDataLayout)); + + return angle::Result::Continue; +} + // static angle::Result ImageHelper::getReadPixelsParams(rx::ContextWgpu *contextWgpu, const gl::PixelPackState &packState, @@ -309,6 +526,8 @@ angle::Result ImageHelper::getReadPixelsParams(rx::ContextWgpu *contextWgpu, angle::Result ImageHelper::readPixels(rx::ContextWgpu *contextWgpu, const gl::Rectangle &area, const rx::PackPixelsParams &packPixelsParams, + webgpu::LevelIndex level, + uint32_t layer, void *pixels) { if (mActualFormatID == angle::FormatID::NONE) @@ -318,86 +537,116 @@ angle::Result ImageHelper::readPixels(rx::ContextWgpu *contextWgpu, return angle::Result::Stop; } - wgpu::Device device = contextWgpu->getDisplay()->getDevice(); - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - wgpu::Queue queue = contextWgpu->getDisplay()->getQueue(); + DeviceHandle device = contextWgpu->getDisplay()->getDevice(); + webgpu::CommandEncoderHandle encoder; + ANGLE_TRY(contextWgpu->getCurrentCommandEncoder( + webgpu::RenderPassClosureReason::CopyBufferToTexture, &encoder)); const angle::Format &actualFormat = angle::Format::Get(mActualFormatID); uint32_t textureBytesPerRow = roundUp(actualFormat.pixelBytes * area.width, kCopyBufferAlignment); - wgpu::TextureDataLayout textureDataLayout; + WGPUTexelCopyBufferLayout textureDataLayout = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT; textureDataLayout.bytesPerRow = textureBytesPerRow; textureDataLayout.rowsPerImage = area.height; size_t allocationSize = textureBytesPerRow * area.height; BufferHelper bufferHelper; - ANGLE_TRY(bufferHelper.initBuffer(device, allocationSize, - wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst, + ANGLE_TRY(bufferHelper.initBuffer(mProcTable, device, allocationSize, + WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, MapAtCreation::No)); - wgpu::ImageCopyBuffer copyBuffer; - copyBuffer.buffer = bufferHelper.getBuffer(); + WGPUTexelCopyBufferInfo copyBuffer = WGPU_TEXEL_COPY_BUFFER_INFO_INIT; + copyBuffer.buffer = bufferHelper.getBuffer().get(); copyBuffer.layout = textureDataLayout; - wgpu::ImageCopyTexture copyTexture; - wgpu::Origin3D textureOrigin; - textureOrigin.x = area.x; - textureOrigin.y = area.y; - copyTexture.origin = textureOrigin; - copyTexture.texture = mTexture; - copyTexture.mipLevel = toWgpuLevel(mFirstAllocatedLevel).get(); + WGPUTexelCopyTextureInfo copyTexture WGPU_TEXEL_COPY_TEXTURE_INFO_INIT; + copyTexture.origin.x = area.x; + copyTexture.origin.y = area.y; + copyTexture.origin.z = layer; + copyTexture.texture = mTexture.get(); + copyTexture.mipLevel = level.get(); - wgpu::Extent3D copySize; + WGPUExtent3D copySize = WGPU_EXTENT_3D_INIT; copySize.width = area.width; copySize.height = area.height; - encoder.CopyTextureToBuffer(©Texture, ©Buffer, ©Size); + mProcTable->commandEncoderCopyTextureToBuffer(encoder.get(), ©Texture, ©Buffer, + ©Size); - wgpu::CommandBuffer commandBuffer = encoder.Finish(); - queue.Submit(1, &commandBuffer); - encoder = nullptr; + ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::GLReadPixels)); - ANGLE_TRY(bufferHelper.mapImmediate(contextWgpu, wgpu::MapMode::Read, 0, allocationSize)); + ANGLE_TRY(bufferHelper.mapImmediate(contextWgpu, WGPUMapMode_Read, 0, allocationSize)); const uint8_t *readPixelBuffer = bufferHelper.getMapReadPointer(0, allocationSize); PackPixels(packPixelsParams, actualFormat, textureBytesPerRow, readPixelBuffer, static_cast(pixels)); return angle::Result::Continue; } -angle::Result ImageHelper::createTextureView(gl::LevelIndex targetLevel, - uint32_t layerIndex, - wgpu::TextureView &textureViewOut) +angle::Result ImageHelper::createTextureViewSingleLevel(gl::LevelIndex targetLevel, + uint32_t layerIndex, + TextureViewHandle &textureViewOut) +{ + return createTextureView(targetLevel, /*levelCount=*/1, layerIndex, /*arrayLayerCount=*/1, + textureViewOut, WGPUTextureViewDimension_Undefined); +} + +angle::Result ImageHelper::createFullTextureView(TextureViewHandle &textureViewOut, + WGPUTextureViewDimension desiredViewDimension) +{ + return createTextureView(mFirstAllocatedLevel, mTextureDescriptor.mipLevelCount, 0, + mTextureDescriptor.size.depthOrArrayLayers, textureViewOut, + desiredViewDimension); +} + +angle::Result ImageHelper::createTextureView( + gl::LevelIndex targetLevel, + uint32_t levelCount, + uint32_t layerIndex, + uint32_t arrayLayerCount, + TextureViewHandle &textureViewOut, + Optional desiredViewDimension) { if (!isTextureLevelInAllocatedImage(targetLevel)) { return angle::Result::Stop; } - wgpu::TextureViewDescriptor textureViewDesc; - textureViewDesc.aspect = wgpu::TextureAspect::All; + WGPUTextureViewDescriptor textureViewDesc = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT; + textureViewDesc.aspect = WGPUTextureAspect_All; textureViewDesc.baseArrayLayer = layerIndex; - textureViewDesc.arrayLayerCount = 1; + textureViewDesc.arrayLayerCount = arrayLayerCount; textureViewDesc.baseMipLevel = toWgpuLevel(targetLevel).get(); - textureViewDesc.mipLevelCount = 1; - switch (mTextureDescriptor.dimension) + textureViewDesc.mipLevelCount = levelCount; + if (!desiredViewDimension.valid()) { - case wgpu::TextureDimension::Undefined: - textureViewDesc.dimension = wgpu::TextureViewDimension::Undefined; - break; - case wgpu::TextureDimension::e1D: - textureViewDesc.dimension = wgpu::TextureViewDimension::e1D; - break; - case wgpu::TextureDimension::e2D: - textureViewDesc.dimension = wgpu::TextureViewDimension::e2D; - break; - case wgpu::TextureDimension::e3D: - textureViewDesc.dimension = wgpu::TextureViewDimension::e3D; - break; + switch (mTextureDescriptor.dimension) + { + case WGPUTextureDimension_Undefined: + textureViewDesc.dimension = WGPUTextureViewDimension_Undefined; + break; + case WGPUTextureDimension_1D: + textureViewDesc.dimension = WGPUTextureViewDimension_1D; + break; + case WGPUTextureDimension_2D: + textureViewDesc.dimension = WGPUTextureViewDimension_2D; + break; + case WGPUTextureDimension_3D: + textureViewDesc.dimension = WGPUTextureViewDimension_3D; + break; + default: + UNIMPLEMENTED(); + return angle::Result::Stop; + } + } + else + { + textureViewDesc.dimension = desiredViewDimension.value(); } textureViewDesc.format = mTextureDescriptor.format; - textureViewOut = mTexture.CreateView(&textureViewDesc); + textureViewOut = TextureViewHandle::Acquire( + mProcTable, mProcTable->textureCreateView(mTexture.get(), &textureViewDesc)); return angle::Result::Continue; } -gl::LevelIndex ImageHelper::getLastAllocatedLevel() +gl::LevelIndex ImageHelper::getLastAllocatedLevel() const { return mFirstAllocatedLevel + mTextureDescriptor.mipLevelCount - 1; } @@ -409,10 +658,10 @@ LevelIndex ImageHelper::toWgpuLevel(gl::LevelIndex levelIndexGl) const gl::LevelIndex ImageHelper::toGlLevel(LevelIndex levelIndexWgpu) const { - return wgpu_gl::getLevelIndex(levelIndexWgpu, mFirstAllocatedLevel); + return wgpu_gl::GetLevelIndex(levelIndexWgpu, mFirstAllocatedLevel); } -bool ImageHelper::isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel) +bool ImageHelper::isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel) const { if (!mInitialized || textureLevel < mFirstAllocatedLevel) { @@ -422,6 +671,20 @@ bool ImageHelper::isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel) return wgpuTextureLevel < LevelIndex(mTextureDescriptor.mipLevelCount); } +WGPUExtent3D ImageHelper::getLevelSize(LevelIndex wgpuLevel) const +{ + WGPUExtent3D copyExtent = mTextureDescriptor.size; + // https://www.w3.org/TR/webgpu/#abstract-opdef-logical-miplevel-specific-texture-extent + copyExtent.width = std::max(1u, copyExtent.width >> wgpuLevel.get()); + copyExtent.height = std::max(1u, copyExtent.height >> wgpuLevel.get()); + if (mTextureDescriptor.dimension == WGPUTextureDimension_3D) + { + copyExtent.depthOrArrayLayers = + std::max(1u, copyExtent.depthOrArrayLayers >> wgpuLevel.get()); + } + return copyExtent; +} + void ImageHelper::appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update) { if (mSubresourceQueue.size() <= static_cast(level.get())) @@ -429,6 +692,7 @@ void ImageHelper::appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdat mSubresourceQueue.resize(level.get() + 1); } mSubresourceQueue[level.get()].emplace_back(std::move(update)); + onStateChange(angle::SubjectMessage::SubjectChanged); } std::vector *ImageHelper::getLevelUpdates(gl::LevelIndex level) @@ -444,25 +708,31 @@ BufferHelper::~BufferHelper() {} void BufferHelper::reset() { + mProcTable = nullptr; mBuffer = nullptr; mMappedState.reset(); } -angle::Result BufferHelper::initBuffer(wgpu::Device device, +angle::Result BufferHelper::initBuffer(const DawnProcTable *wgpu, + webgpu::DeviceHandle device, size_t size, - wgpu::BufferUsage usage, + WGPUBufferUsage usage, MapAtCreation mappedAtCreation) { - wgpu::BufferDescriptor descriptor; - descriptor.size = roundUp(size, kBufferSizeAlignment); + mProcTable = wgpu; + + size_t safeBufferSize = rx::roundUpPow2(size, kBufferSizeAlignment); + WGPUBufferDescriptor descriptor = WGPU_BUFFER_DESCRIPTOR_INIT; + descriptor.size = safeBufferSize; descriptor.usage = usage; descriptor.mappedAtCreation = mappedAtCreation == MapAtCreation::Yes; - mBuffer = device.CreateBuffer(&descriptor); + mBuffer = webgpu::BufferHandle::Acquire( + mProcTable, mProcTable->deviceCreateBuffer(device.get(), &descriptor)); if (mappedAtCreation == MapAtCreation::Yes) { - mMappedState = {wgpu::MapMode::Read | wgpu::MapMode::Write, 0, size}; + mMappedState = {WGPUMapMode_Read | WGPUMapMode_Write, 0, safeBufferSize}; } else { @@ -475,53 +745,60 @@ angle::Result BufferHelper::initBuffer(wgpu::Device device, } angle::Result BufferHelper::mapImmediate(ContextWgpu *context, - wgpu::MapMode mode, + WGPUMapMode mode, size_t offset, size_t size) { ASSERT(!mMappedState.has_value()); - WGPUBufferMapAsyncStatus mapResult = WGPUBufferMapAsyncStatus_Unknown; + WGPUMapAsyncStatus mapResult = WGPUMapAsyncStatus_Error; + WGPUBufferMapCallbackInfo mapAsyncCallback = WGPU_BUFFER_MAP_CALLBACK_INFO_INIT; + mapAsyncCallback.mode = WGPUCallbackMode_WaitAnyOnly; + mapAsyncCallback.callback = [](WGPUMapAsyncStatus status, struct WGPUStringView message, + void *userdata1, void *userdata2) { + WGPUMapAsyncStatus *pStatus = reinterpret_cast(userdata1); + ASSERT(userdata2 == nullptr); - wgpu::BufferMapCallbackInfo callbackInfo; - callbackInfo.mode = wgpu::CallbackMode::WaitAnyOnly; - callbackInfo.callback = [](WGPUBufferMapAsyncStatus status, void *userdata) { - *static_cast(userdata) = status; + *pStatus = status; }; - callbackInfo.userdata = &mapResult; + mapAsyncCallback.userdata1 = &mapResult; - wgpu::FutureWaitInfo waitInfo; - waitInfo.future = mBuffer.MapAsync(mode, GetSafeBufferMapOffset(offset), - GetSafeBufferMapSize(offset, size), callbackInfo); + size_t safeBufferMapOffset = GetSafeBufferMapOffset(offset); + size_t safeBufferMapSize = GetSafeBufferMapSize(offset, size); + WGPUFutureWaitInfo waitInfo; + waitInfo.future = mProcTable->bufferMapAsync(mBuffer.get(), mode, safeBufferMapOffset, + safeBufferMapSize, mapAsyncCallback); - wgpu::Instance instance = context->getDisplay()->getInstance(); - ANGLE_WGPU_TRY(context, instance.WaitAny(1, &waitInfo, -1)); + webgpu::InstanceHandle instance = context->getDisplay()->getInstance(); + ANGLE_WGPU_TRY(context, mProcTable->instanceWaitAny(instance.get(), 1, &waitInfo, -1)); ANGLE_WGPU_TRY(context, mapResult); ASSERT(waitInfo.completed); - mMappedState = {mode, offset, size}; + mMappedState = {mode, safeBufferMapOffset, safeBufferMapSize}; return angle::Result::Continue; } angle::Result BufferHelper::unmap() { - ASSERT(mMappedState.has_value()); - mBuffer.Unmap(); - mMappedState.reset(); + if (mMappedState.has_value()) + { + mProcTable->bufferUnmap(mBuffer.get()); + mMappedState.reset(); + } return angle::Result::Continue; } uint8_t *BufferHelper::getMapWritePointer(size_t offset, size_t size) const { - ASSERT(mBuffer.GetMapState() == wgpu::BufferMapState::Mapped); + ASSERT(mProcTable->bufferGetMapState(mBuffer.get()) == WGPUBufferMapState_Mapped); ASSERT(mMappedState.has_value()); ASSERT(mMappedState->offset <= offset); ASSERT(mMappedState->offset + mMappedState->size >= offset + size); - void *mapPtr = - mBuffer.GetMappedRange(GetSafeBufferMapOffset(offset), GetSafeBufferMapSize(offset, size)); + void *mapPtr = mProcTable->bufferGetMappedRange(mBuffer.get(), GetSafeBufferMapOffset(offset), + GetSafeBufferMapSize(offset, size)); ASSERT(mapPtr); return AdjustMapPointerForOffset(static_cast(mapPtr), offset); @@ -529,14 +806,15 @@ uint8_t *BufferHelper::getMapWritePointer(size_t offset, size_t size) const const uint8_t *BufferHelper::getMapReadPointer(size_t offset, size_t size) const { - ASSERT(mBuffer.GetMapState() == wgpu::BufferMapState::Mapped); + ASSERT(mProcTable->bufferGetMapState(mBuffer.get()) == WGPUBufferMapState_Mapped); ASSERT(mMappedState.has_value()); ASSERT(mMappedState->offset <= offset); ASSERT(mMappedState->offset + mMappedState->size >= offset + size); - // GetConstMappedRange is used for reads whereas GetMappedRange is only used for writes. - const void *mapPtr = mBuffer.GetConstMappedRange(GetSafeBufferMapOffset(offset), - GetSafeBufferMapSize(offset, size)); + // wgpuBufferGetConstMappedRange is used for reads whereas wgpuBufferGetMappedRange is only used + // for writes. + const void *mapPtr = mProcTable->bufferGetConstMappedRange( + mBuffer.get(), GetSafeBufferMapOffset(offset), GetSafeBufferMapSize(offset, size)); ASSERT(mapPtr); return AdjustMapPointerForOffset(static_cast(mapPtr), offset); @@ -549,17 +827,26 @@ const std::optional &BufferHelper::getMappedState() const bool BufferHelper::canMapForRead() const { - return (mMappedState.has_value() && (mMappedState->mode & wgpu::MapMode::Read)) || - (mBuffer && (mBuffer.GetUsage() & wgpu::BufferUsage::MapRead)); + return (mMappedState.has_value() && (mMappedState->mode & WGPUMapMode_Read)) || + (mBuffer && (mProcTable->bufferGetUsage(mBuffer.get()) & WGPUBufferUsage_MapRead)); } bool BufferHelper::canMapForWrite() const { - return (mMappedState.has_value() && (mMappedState->mode & wgpu::MapMode::Write)) || - (mBuffer && (mBuffer.GetUsage() & wgpu::BufferUsage::MapWrite)); + return (mMappedState.has_value() && (mMappedState->mode & WGPUMapMode_Write)) || + (mBuffer && (mProcTable->bufferGetUsage(mBuffer.get()) & WGPUBufferUsage_MapWrite)); +} + +bool BufferHelper::isMappedForRead() const +{ + return mMappedState.has_value() && (mMappedState->mode & WGPUMapMode_Read); +} +bool BufferHelper::isMappedForWrite() const +{ + return mMappedState.has_value() && (mMappedState->mode & WGPUMapMode_Write); } -wgpu::Buffer &BufferHelper::getBuffer() +webgpu::BufferHandle BufferHelper::getBuffer() const { return mBuffer; } @@ -571,7 +858,7 @@ uint64_t BufferHelper::requestedSize() const uint64_t BufferHelper::actualSize() const { - return mBuffer ? mBuffer.GetSize() : 0; + return mBuffer ? mProcTable->bufferGetSize(mBuffer.get()) : 0; } angle::Result BufferHelper::readDataImmediate(ContextWgpu *context, @@ -592,23 +879,24 @@ angle::Result BufferHelper::readDataImmediate(ContextWgpu *context, const size_t stagingBufferSize = roundUpPow2( size, std::max(webgpu::kBufferCopyToBufferAlignment, webgpu::kBufferMapOffsetAlignment)); - ANGLE_TRY(result->buffer.initBuffer(context->getDisplay()->getDevice(), stagingBufferSize, - wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead, - webgpu::MapAtCreation::No)); + ANGLE_TRY(result->buffer.initBuffer( + mProcTable, context->getDisplay()->getDevice(), stagingBufferSize, + WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead, webgpu::MapAtCreation::No)); // Copy the source buffer to staging and flush the commands - context->ensureCommandEncoderCreated(); - wgpu::CommandEncoder &commandEncoder = context->getCurrentCommandEncoder(); + webgpu::CommandEncoderHandle commandEncoder; + ANGLE_TRY(context->getCurrentCommandEncoder(reason, &commandEncoder)); size_t safeCopyOffset = rx::roundDownPow2(offset, webgpu::kBufferCopyToBufferAlignment); size_t offsetAdjustment = offset - safeCopyOffset; size_t copySize = roundUpPow2(size + offsetAdjustment, webgpu::kBufferCopyToBufferAlignment); - commandEncoder.CopyBufferToBuffer(getBuffer(), safeCopyOffset, result->buffer.getBuffer(), 0, - copySize); + mProcTable->commandEncoderCopyBufferToBuffer(commandEncoder.get(), mBuffer.get(), + safeCopyOffset, result->buffer.getBuffer().get(), + 0, copySize); ANGLE_TRY(context->flush(reason)); // Read back from the staging buffer and compute the index range - ANGLE_TRY(result->buffer.mapImmediate(context, wgpu::MapMode::Read, offsetAdjustment, size)); + ANGLE_TRY(result->buffer.mapImmediate(context, WGPUMapMode_Read, offsetAdjustment, size)); result->data = result->buffer.getMapReadPointer(offsetAdjustment, size); return angle::Result::Continue; diff --git a/src/libANGLE/renderer/wgpu/wgpu_helpers.h b/src/libANGLE/renderer/wgpu/wgpu_helpers.h index 98c0c8c3031..2b01e03e55c 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_helpers.h +++ b/src/libANGLE/renderer/wgpu/wgpu_helpers.h @@ -7,8 +7,8 @@ #ifndef LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_ #define LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_ -#include #include +#include #include #include "libANGLE/Error.h" @@ -26,7 +26,7 @@ namespace webgpu { // WebGPU requires copy buffers bytesPerRow to be aligned to 256. -// https://www.w3.org/TR/webgpu/#abstract-opdef-validating-gpuimagecopybuffer +// https://www.w3.org/TR/webgpu/#abstract-opdef-validating-gputexelcopybufferinfo static const GLuint kCopyBufferAlignment = 256; enum class UpdateSource @@ -49,11 +49,28 @@ struct SubresourceUpdate SubresourceUpdate(UpdateSource targetUpdateSource, gl::LevelIndex newTargetLevel, - wgpu::ImageCopyBuffer targetBuffer) + BufferHandle targetBuffer, + const WGPUTexelCopyBufferLayout &targetBufferLayout) { - updateSource = targetUpdateSource; - textureData = targetBuffer; - targetLevel = newTargetLevel; + updateSource = targetUpdateSource; + textureData = targetBuffer; + textureDataLayout = targetBufferLayout; + targetLevel = newTargetLevel; + } + + SubresourceUpdate(UpdateSource targetUpdateSource, + gl::LevelIndex newTargetLevel, + uint32_t newLayerIndex, + uint32_t newLayerCount, + BufferHandle targetBuffer, + const WGPUTexelCopyBufferLayout &targetBufferLayout) + { + updateSource = targetUpdateSource; + textureData = targetBuffer; + textureDataLayout = targetBufferLayout; + targetLevel = newTargetLevel; + layerIndex = newLayerIndex; + layerCount = newLayerCount; } SubresourceUpdate(UpdateSource targetUpdateSource, @@ -62,8 +79,8 @@ struct SubresourceUpdate bool hasDepth, bool hasStencil) { - updateSource = targetUpdateSource; - targetLevel = newTargetLevel; + updateSource = targetUpdateSource; + targetLevel = newTargetLevel; clearData.clearValues = clearValues; clearData.hasDepth = hasDepth; clearData.hasStencil = hasStencil; @@ -71,27 +88,32 @@ struct SubresourceUpdate UpdateSource updateSource; ClearUpdate clearData; - wgpu::ImageCopyBuffer textureData; + BufferHandle textureData; + WGPUTexelCopyBufferLayout textureDataLayout; gl::LevelIndex targetLevel; + uint32_t layerIndex = 0; + uint32_t layerCount = 1; }; -wgpu::TextureDimension toWgpuTextureDimension(gl::TextureType glTextureType); +WGPUTextureDimension ToWgpuTextureDimension(gl::TextureType glTextureType); -class ImageHelper +class ImageHelper : public angle::Subject { public: ImageHelper(); - ~ImageHelper(); + ~ImageHelper() override; - angle::Result initImage(angle::FormatID intendedFormatID, + angle::Result initImage(const DawnProcTable *wgpu, + angle::FormatID intendedFormatID, angle::FormatID actualFormatID, - wgpu::Device &device, + DeviceHandle device, gl::LevelIndex firstAllocatedLevel, - wgpu::TextureDescriptor textureDescriptor); - angle::Result initExternal(angle::FormatID intendedFormatID, + WGPUTextureDescriptor textureDescriptor); + angle::Result initExternal(const DawnProcTable *wgpu, + angle::FormatID intendedFormatID, angle::FormatID actualFormatID, - wgpu::Texture externalTexture); + webgpu::TextureHandle externalTexture); angle::Result flushStagedUpdates(ContextWgpu *contextWgpu); angle::Result flushSingleLevelUpdates(ContextWgpu *contextWgpu, @@ -99,12 +121,12 @@ class ImageHelper ClearValuesArray *deferredClears, uint32_t deferredClearIndex); - wgpu::TextureDescriptor createTextureDescriptor(wgpu::TextureUsage usage, - wgpu::TextureDimension dimension, - wgpu::Extent3D size, - wgpu::TextureFormat format, - std::uint32_t mipLevelCount, - std::uint32_t sampleCount); + WGPUTextureDescriptor createTextureDescriptor(WGPUTextureUsage usage, + WGPUTextureDimension dimension, + WGPUExtent3D size, + WGPUTextureFormat format, + std::uint32_t mipLevelCount, + std::uint32_t sampleCount); angle::Result stageTextureUpload(ContextWgpu *contextWgpu, const webgpu::Format &webgpuFormat, @@ -124,9 +146,29 @@ class ImageHelper bool hasStencil); void removeStagedUpdates(gl::LevelIndex levelToRemove); + void removeSingleSubresourceStagedUpdates(gl::LevelIndex levelToRemove, + uint32_t layerIndex, + uint32_t layerCount); void resetImage(); + angle::Result CopyImage(ContextWgpu *contextWgpu, + ImageHelper *srcImage, + const gl::ImageIndex &dstIndex, + const gl::Offset &dstOffset, + gl::LevelIndex sourceLevelGL, + uint32_t sourceLayer, + const gl::Box &sourceBox); + + angle::Result copyImageCpuReadback(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Rectangle &sourceArea, + const gl::Offset &dstOffset, + const gl::Extents &dstExtent, + const gl::InternalFormat &formatInfo, + ImageHelper *srcImage, + const gl::Extents &srcExtents); + static angle::Result getReadPixelsParams(rx::ContextWgpu *contextWgpu, const gl::PixelPackState &packState, gl::Buffer *packBuffer, @@ -140,31 +182,45 @@ class ImageHelper angle::Result readPixels(rx::ContextWgpu *contextWgpu, const gl::Rectangle &area, const rx::PackPixelsParams &packPixelsParams, + webgpu::LevelIndex level, + uint32_t layer, void *pixels); + angle::Result createTextureViewSingleLevel(gl::LevelIndex targetLevel, + uint32_t layerIndex, + TextureViewHandle &textureViewOut); + angle::Result createFullTextureView(TextureViewHandle &textureViewOut, + WGPUTextureViewDimension desiredViewDimension); angle::Result createTextureView(gl::LevelIndex targetLevel, + uint32_t levelCount, uint32_t layerIndex, - wgpu::TextureView &textureViewOut); + uint32_t arrayLayerCount, + TextureViewHandle &textureViewOut, + Optional desiredViewDimension); LevelIndex toWgpuLevel(gl::LevelIndex levelIndexGl) const; gl::LevelIndex toGlLevel(LevelIndex levelIndexWgpu) const; - bool isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel); - wgpu::Texture &getTexture() { return mTexture; } - wgpu::TextureFormat toWgpuTextureFormat() const { return mTextureDescriptor.format; } - angle::FormatID getIntendedFormatID() { return mIntendedFormatID; } - angle::FormatID getActualFormatID() { return mActualFormatID; } - const wgpu::TextureDescriptor &getTextureDescriptor() const { return mTextureDescriptor; } - gl::LevelIndex getFirstAllocatedLevel() { return mFirstAllocatedLevel; } - gl::LevelIndex getLastAllocatedLevel(); - uint32_t getLevelCount() { return mTextureDescriptor.mipLevelCount; } - wgpu::Extent3D getSize() { return mTextureDescriptor.size; } - bool isInitialized() { return mInitialized; } + bool isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel) const; + TextureHandle &getTexture() { return mTexture; } + WGPUTextureFormat toWgpuTextureFormat() const { return mTextureDescriptor.format; } + angle::FormatID getIntendedFormatID() const { return mIntendedFormatID; } + angle::FormatID getActualFormatID() const { return mActualFormatID; } + const WGPUTextureDescriptor &getTextureDescriptor() const { return mTextureDescriptor; } + gl::LevelIndex getFirstAllocatedLevel() const { return mFirstAllocatedLevel; } + gl::LevelIndex getLastAllocatedLevel() const; + uint32_t getLevelCount() const { return mTextureDescriptor.mipLevelCount; } + WGPUExtent3D getSize() const { return mTextureDescriptor.size; } + WGPUExtent3D getLevelSize(LevelIndex wgpuLevel) const; + uint32_t getSamples() const { return mTextureDescriptor.sampleCount; } + WGPUTextureUsage getUsage() const { return mTextureDescriptor.usage; } + bool isInitialized() const { return mInitialized; } private: void appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update); std::vector *getLevelUpdates(gl::LevelIndex level); - wgpu::Texture mTexture; - wgpu::TextureDescriptor mTextureDescriptor = {}; + const DawnProcTable *mProcTable = nullptr; + TextureHandle mTexture; + WGPUTextureDescriptor mTextureDescriptor = {}; bool mInitialized = false; gl::LevelIndex mFirstAllocatedLevel = gl::LevelIndex(0); @@ -175,7 +231,7 @@ class ImageHelper }; struct BufferMapState { - wgpu::MapMode mode; + WGPUMapMode mode; size_t offset; size_t size; }; @@ -197,15 +253,13 @@ class BufferHelper : public angle::NonCopyable bool valid() const { return mBuffer.operator bool(); } void reset(); - angle::Result initBuffer(wgpu::Device device, + angle::Result initBuffer(const DawnProcTable *wgpu, + webgpu::DeviceHandle device, size_t size, - wgpu::BufferUsage usage, + WGPUBufferUsage usage, MapAtCreation mappedAtCreation); - angle::Result mapImmediate(ContextWgpu *context, - wgpu::MapMode mode, - size_t offset, - size_t size); + angle::Result mapImmediate(ContextWgpu *context, WGPUMapMode mode, size_t offset, size_t size); angle::Result unmap(); uint8_t *getMapWritePointer(size_t offset, size_t size) const; @@ -216,7 +270,10 @@ class BufferHelper : public angle::NonCopyable bool canMapForRead() const; bool canMapForWrite() const; - wgpu::Buffer &getBuffer(); + bool isMappedForRead() const; + bool isMappedForWrite() const; + + webgpu::BufferHandle getBuffer() const; uint64_t requestedSize() const; uint64_t actualSize() const; @@ -229,7 +286,8 @@ class BufferHelper : public angle::NonCopyable BufferReadback *result); private: - wgpu::Buffer mBuffer; + const DawnProcTable *mProcTable = nullptr; + webgpu::BufferHandle mBuffer; size_t mRequestedSize = 0; std::optional mMappedState; diff --git a/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.cpp b/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.cpp index 1002e3466d4..d38b9a8ed71 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.cpp @@ -4,47 +4,50 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h" #include "common/aligned_memory.h" #include "common/hash_utils.h" +#include "common/span.h" #include "libANGLE/Error.h" #include "libANGLE/renderer/wgpu/ContextWgpu.h" -#include "libANGLE/renderer/wgpu/wgpu_utils.h" namespace rx { namespace webgpu { // Can pack the index format into 1 bit since it has 2 values and Undefined is not used. -static_assert(static_cast(wgpu::IndexFormat::Uint32) == 2U, - "Max wgpu::IndexFormat is not 2"); -static_assert(static_cast(wgpu::IndexFormat::Undefined) == 0, - "wgpu::IndexFormat::Undefined unexpected value"); -constexpr uint32_t PackIndexFormat(wgpu::IndexFormat unpackedFormat) +static_assert(static_cast(WGPUIndexFormat_Uint32) == 2U, "Max WGPUIndexFormat is not 2"); +static_assert(static_cast(WGPUIndexFormat_Undefined) == 0, + "WGPUIndexFormat::Undefined unexpected value"); +constexpr uint32_t PackIndexFormat(WGPUIndexFormat unpackedFormat) { ASSERT(static_cast(unpackedFormat) > 0); return static_cast(unpackedFormat) - 1; } -constexpr wgpu::IndexFormat UnpackIndexFormat(uint32_t packedIndexFormat) +constexpr WGPUIndexFormat UnpackIndexFormat(uint32_t packedIndexFormat) { - return static_cast(packedIndexFormat + 1); + return static_cast(packedIndexFormat + 1); } // Can pack the front face into 1 bit since it has 2 values and Undefined is not used. -static_assert(static_cast(wgpu::FrontFace::CW) == 2U, "Max wgpu::FrontFace is not 2"); -static_assert(static_cast(wgpu::FrontFace::Undefined) == 0, - "wgpu::FrontFace::Undefined unexpected value"); -constexpr uint32_t PackFrontFace(wgpu::FrontFace unpackedFrontFace) +static_assert(static_cast(WGPUFrontFace_CW) == 2U, "Max WGPUFrontFace is not 2"); +static_assert(static_cast(WGPUFrontFace_Undefined) == 0, + "WGPUFrontFace_Undefined unexpected value"); +constexpr uint32_t PackFrontFace(WGPUFrontFace unpackedFrontFace) { ASSERT(static_cast(unpackedFrontFace) > 0); return static_cast(unpackedFrontFace) - 1; } -constexpr wgpu::FrontFace UnpackFrontFace(uint32_t packedFrontFace) +constexpr WGPUFrontFace UnpackFrontFace(uint32_t packedFrontFace) { - return static_cast(packedFrontFace + 1); + return static_cast(packedFrontFace + 1); } PackedVertexAttribute::PackedVertexAttribute() @@ -77,7 +80,7 @@ bool RenderPipelineDesc::setPrimitiveMode(gl::PrimitiveMode primitiveMode, { bool changed = false; - wgpu::PrimitiveTopology topology = gl_wgpu::GetPrimitiveTopology(primitiveMode); + WGPUPrimitiveTopology topology = gl_wgpu::GetPrimitiveTopology(primitiveMode); if (mPrimitiveState.topology != static_cast(topology)) { SetBitField(mPrimitiveState.topology, topology); @@ -110,10 +113,10 @@ bool RenderPipelineDesc::setBlendEnabled(size_t colorIndex, bool enabled) } bool RenderPipelineDesc::setBlendFuncs(size_t colorIndex, - wgpu::BlendFactor srcRGB, - wgpu::BlendFactor dstRGB, - wgpu::BlendFactor srcAlpha, - wgpu::BlendFactor dstAlpha) + WGPUBlendFactor srcRGB, + WGPUBlendFactor dstRGB, + WGPUBlendFactor srcAlpha, + WGPUBlendFactor dstAlpha) { bool changed = false; PackedColorTargetState &colorTarget = mColorTargetStates[colorIndex]; @@ -146,8 +149,8 @@ bool RenderPipelineDesc::setBlendFuncs(size_t colorIndex, } bool RenderPipelineDesc::setBlendEquations(size_t colorIndex, - wgpu::BlendOperation rgb, - wgpu::BlendOperation alpha) + WGPUBlendOperation rgb, + WGPUBlendOperation alpha) { bool changed = false; PackedColorTargetState &colorTarget = mColorTargetStates[colorIndex]; @@ -195,7 +198,7 @@ bool RenderPipelineDesc::setVertexAttribute(size_t attribIndex, PackedVertexAttr return true; } -bool RenderPipelineDesc::setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format) +bool RenderPipelineDesc::setColorAttachmentFormat(size_t colorIndex, WGPUTextureFormat format) { if (mColorTargetStates[colorIndex].format == static_cast(format)) { @@ -206,7 +209,7 @@ bool RenderPipelineDesc::setColorAttachmentFormat(size_t colorIndex, wgpu::Textu return true; } -bool RenderPipelineDesc::setDepthStencilAttachmentFormat(wgpu::TextureFormat format) +bool RenderPipelineDesc::setDepthStencilAttachmentFormat(WGPUTextureFormat format) { if (mDepthStencilState.format == static_cast(format)) { @@ -217,7 +220,7 @@ bool RenderPipelineDesc::setDepthStencilAttachmentFormat(wgpu::TextureFormat for return true; } -bool RenderPipelineDesc::setDepthFunc(wgpu::CompareFunction compareFunc) +bool RenderPipelineDesc::setDepthFunc(WGPUCompareFunction compareFunc) { if (mDepthStencilState.depthCompare == static_cast(compareFunc)) { @@ -227,7 +230,7 @@ bool RenderPipelineDesc::setDepthFunc(wgpu::CompareFunction compareFunc) return true; } -bool RenderPipelineDesc::setStencilFrontFunc(wgpu::CompareFunction compareFunc) +bool RenderPipelineDesc::setStencilFrontFunc(WGPUCompareFunction compareFunc) { if (mDepthStencilState.stencilFrontCompare == static_cast(compareFunc)) { @@ -237,9 +240,9 @@ bool RenderPipelineDesc::setStencilFrontFunc(wgpu::CompareFunction compareFunc) return true; } -bool RenderPipelineDesc::setStencilFrontOps(wgpu::StencilOperation failOp, - wgpu::StencilOperation depthFailOp, - wgpu::StencilOperation passOp) +bool RenderPipelineDesc::setStencilFrontOps(WGPUStencilOperation failOp, + WGPUStencilOperation depthFailOp, + WGPUStencilOperation passOp) { if (mDepthStencilState.stencilFrontFailOp == static_cast(failOp) && mDepthStencilState.stencilFrontDepthFailOp == static_cast(depthFailOp) && @@ -253,7 +256,7 @@ bool RenderPipelineDesc::setStencilFrontOps(wgpu::StencilOperation failOp, return true; } -bool RenderPipelineDesc::setStencilBackFunc(wgpu::CompareFunction compareFunc) +bool RenderPipelineDesc::setStencilBackFunc(WGPUCompareFunction compareFunc) { if (mDepthStencilState.stencilBackCompare == static_cast(compareFunc)) { @@ -263,9 +266,9 @@ bool RenderPipelineDesc::setStencilBackFunc(wgpu::CompareFunction compareFunc) return true; } -bool RenderPipelineDesc::setStencilBackOps(wgpu::StencilOperation failOp, - wgpu::StencilOperation depthFailOp, - wgpu::StencilOperation passOp) +bool RenderPipelineDesc::setStencilBackOps(WGPUStencilOperation failOp, + WGPUStencilOperation depthFailOp, + WGPUStencilOperation passOp) { if (mDepthStencilState.stencilBackFailOp == static_cast(failOp) && mDepthStencilState.stencilBackDepthFailOp == static_cast(depthFailOp) && @@ -302,26 +305,29 @@ bool RenderPipelineDesc::setStencilWriteMask(uint8_t writeMask) size_t RenderPipelineDesc::hash() const { - return angle::ComputeGenericHash(this, sizeof(*this)); + return angle::ComputeGenericHash(angle::byte_span_from_ref(*this)); } angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, - const wgpu::PipelineLayout &pipelineLayout, - const gl::ShaderMap &shaders, - wgpu::RenderPipeline *pipelineOut) const + const PipelineLayoutHandle &pipelineLayout, + const gl::ShaderMap &shaders, + RenderPipelineHandle *pipelineOut) const { - wgpu::RenderPipelineDescriptor pipelineDesc; - pipelineDesc.layout = pipelineLayout; + const DawnProcTable *wgpu = webgpu::GetProcs(context); + + constexpr const char *kShaderEntryPoint = "wgslMain"; + + WGPURenderPipelineDescriptor pipelineDesc = WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT; + pipelineDesc.layout = pipelineLayout.get(); - pipelineDesc.vertex.module = shaders[gl::ShaderType::Vertex]; - pipelineDesc.vertex.entryPoint = "wgslMain"; + pipelineDesc.vertex.module = shaders[gl::ShaderType::Vertex].get(); + pipelineDesc.vertex.entryPoint = {kShaderEntryPoint, std::strlen(kShaderEntryPoint)}; pipelineDesc.vertex.constantCount = 0; pipelineDesc.vertex.constants = nullptr; pipelineDesc.vertex.bufferCount = 0; pipelineDesc.vertex.buffers = nullptr; - pipelineDesc.primitive.topology = - static_cast(mPrimitiveState.topology); + pipelineDesc.primitive.topology = static_cast(mPrimitiveState.topology); if (webgpu::IsStripPrimitiveTopology(pipelineDesc.primitive.topology)) { pipelineDesc.primitive.stripIndexFormat = @@ -329,14 +335,14 @@ angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, } else { - pipelineDesc.primitive.stripIndexFormat = wgpu::IndexFormat::Undefined; + pipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; } pipelineDesc.primitive.frontFace = UnpackFrontFace(mPrimitiveState.frontFace); - pipelineDesc.primitive.cullMode = static_cast(mPrimitiveState.cullMode); + pipelineDesc.primitive.cullMode = static_cast(mPrimitiveState.cullMode); size_t attribCount = 0; - gl::AttribArray vertexBuffers; - gl::AttribArray vertexAttribs; + gl::AttribArray vertexBuffers; + gl::AttribArray vertexAttribs; for (PackedVertexAttribute packedAttrib : mVertexAttributes) { @@ -345,13 +351,16 @@ angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, continue; } - wgpu::VertexAttribute &newAttribute = vertexAttribs[attribCount]; - newAttribute.format = static_cast(packedAttrib.format); + WGPUVertexAttribute &newAttribute = vertexAttribs[attribCount]; + newAttribute = WGPU_VERTEX_ATTRIBUTE_INIT; + newAttribute.format = static_cast(packedAttrib.format); newAttribute.offset = packedAttrib.offset; newAttribute.shaderLocation = packedAttrib.shaderLocation; - wgpu::VertexBufferLayout &newBufferLayout = vertexBuffers[attribCount]; + WGPUVertexBufferLayout &newBufferLayout = vertexBuffers[attribCount]; + newBufferLayout = WGPU_VERTEX_BUFFER_LAYOUT_INIT; newBufferLayout.arrayStride = packedAttrib.stride; + newBufferLayout.stepMode = WGPUVertexStepMode_Undefined; newBufferLayout.attributeCount = 1; newBufferLayout.attributes = &newAttribute; @@ -361,13 +370,13 @@ angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, pipelineDesc.vertex.bufferCount = attribCount; pipelineDesc.vertex.buffers = vertexBuffers.data(); - wgpu::FragmentState fragmentState; - std::array colorTargets; - std::array blendStates; + WGPUFragmentState fragmentState = WGPU_FRAGMENT_STATE_INIT; + std::array colorTargets; + std::array blendStates; if (shaders[gl::ShaderType::Fragment]) { - fragmentState.module = shaders[gl::ShaderType::Fragment]; - fragmentState.entryPoint = "wgslMain"; + fragmentState.module = shaders[gl::ShaderType::Fragment].get(); + fragmentState.entryPoint = {kShaderEntryPoint, std::strlen(kShaderEntryPoint)}; fragmentState.constantCount = 0; fragmentState.constants = nullptr; @@ -377,32 +386,34 @@ angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, { const webgpu::PackedColorTargetState &packedColorTarget = mColorTargetStates[colorTargetIndex]; - wgpu::ColorTargetState &outputColorTarget = colorTargets[colorTargetIndex]; + WGPUColorTargetState &outputColorTarget = colorTargets[colorTargetIndex]; + outputColorTarget = WGPU_COLOR_TARGET_STATE_INIT; - outputColorTarget.format = static_cast(packedColorTarget.format); + outputColorTarget.format = static_cast(packedColorTarget.format); if (packedColorTarget.blendEnabled) { + blendStates[colorTargetIndex] = WGPU_BLEND_STATE_INIT; blendStates[colorTargetIndex].color.srcFactor = - static_cast(packedColorTarget.colorBlendSrcFactor); + static_cast(packedColorTarget.colorBlendSrcFactor); blendStates[colorTargetIndex].color.dstFactor = - static_cast(packedColorTarget.colorBlendDstFactor); + static_cast(packedColorTarget.colorBlendDstFactor); blendStates[colorTargetIndex].color.operation = - static_cast(packedColorTarget.colorBlendOp); + static_cast(packedColorTarget.colorBlendOp); blendStates[colorTargetIndex].alpha.srcFactor = - static_cast(packedColorTarget.alphaBlendSrcFactor); + static_cast(packedColorTarget.alphaBlendSrcFactor); blendStates[colorTargetIndex].alpha.dstFactor = - static_cast(packedColorTarget.alphaBlendDstFactor); + static_cast(packedColorTarget.alphaBlendDstFactor); blendStates[colorTargetIndex].alpha.operation = - static_cast(packedColorTarget.alphaBlendOp); + static_cast(packedColorTarget.alphaBlendOp); outputColorTarget.blend = &blendStates[colorTargetIndex]; } outputColorTarget.writeMask = - static_cast(packedColorTarget.writeMask); + static_cast(packedColorTarget.writeMask); - if (outputColorTarget.format != wgpu::TextureFormat::Undefined) + if (outputColorTarget.format != WGPUTextureFormat_Undefined) { colorTargetCount = colorTargetIndex + 1; } @@ -413,35 +424,34 @@ angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, pipelineDesc.fragment = &fragmentState; } - wgpu::DepthStencilState depthStencilState; - if (static_cast(mDepthStencilState.format) != - wgpu::TextureFormat::Undefined) + WGPUDepthStencilState depthStencilState = WGPU_DEPTH_STENCIL_STATE_INIT; + if (static_cast(mDepthStencilState.format) != WGPUTextureFormat_Undefined) { - const webgpu::PackedDepthStencilState &packedDepthStencilState = mDepthStencilState; + const PackedDepthStencilState &packedDepthStencilState = mDepthStencilState; - depthStencilState.format = static_cast(packedDepthStencilState.format); + depthStencilState.format = static_cast(packedDepthStencilState.format); depthStencilState.depthWriteEnabled = - static_cast(packedDepthStencilState.depthWriteEnabled); + static_cast(packedDepthStencilState.depthWriteEnabled); depthStencilState.depthCompare = - static_cast(packedDepthStencilState.depthCompare); + static_cast(packedDepthStencilState.depthCompare); depthStencilState.stencilFront.compare = - static_cast(packedDepthStencilState.stencilFrontCompare); + static_cast(packedDepthStencilState.stencilFrontCompare); depthStencilState.stencilFront.failOp = - static_cast(packedDepthStencilState.stencilFrontFailOp); + static_cast(packedDepthStencilState.stencilFrontFailOp); depthStencilState.stencilFront.depthFailOp = - static_cast(packedDepthStencilState.stencilFrontDepthFailOp); + static_cast(packedDepthStencilState.stencilFrontDepthFailOp); depthStencilState.stencilFront.passOp = - static_cast(packedDepthStencilState.stencilFrontPassOp); + static_cast(packedDepthStencilState.stencilFrontPassOp); depthStencilState.stencilBack.compare = - static_cast(packedDepthStencilState.stencilBackCompare); + static_cast(packedDepthStencilState.stencilBackCompare); depthStencilState.stencilBack.failOp = - static_cast(packedDepthStencilState.stencilBackFailOp); + static_cast(packedDepthStencilState.stencilBackFailOp); depthStencilState.stencilBack.depthFailOp = - static_cast(packedDepthStencilState.stencilBackDepthFailOp); + static_cast(packedDepthStencilState.stencilBackDepthFailOp); depthStencilState.stencilBack.passOp = - static_cast(packedDepthStencilState.stencilBackPassOp); + static_cast(packedDepthStencilState.stencilBackPassOp); depthStencilState.stencilReadMask = packedDepthStencilState.stencilReadMask; depthStencilState.stencilWriteMask = packedDepthStencilState.stencilWriteMask; @@ -453,8 +463,10 @@ angle::Result RenderPipelineDesc::createPipeline(ContextWgpu *context, pipelineDesc.depthStencil = &depthStencilState; } - wgpu::Device device = context->getDevice(); - ANGLE_WGPU_SCOPED_DEBUG_TRY(context, *pipelineOut = device.CreateRenderPipeline(&pipelineDesc)); + DeviceHandle device = context->getDevice(); + ANGLE_WGPU_SCOPED_DEBUG_TRY( + context, *pipelineOut = RenderPipelineHandle::Acquire( + wgpu, wgpu->deviceCreateRenderPipeline(device.get(), &pipelineDesc))); return angle::Result::Continue; } @@ -470,9 +482,9 @@ PipelineCache::~PipelineCache() = default; angle::Result PipelineCache::getRenderPipeline(ContextWgpu *context, const RenderPipelineDesc &desc, - const wgpu::PipelineLayout &pipelineLayout, - const gl::ShaderMap &shaders, - wgpu::RenderPipeline *pipelineOut) + const PipelineLayoutHandle &pipelineLayout, + const gl::ShaderMap &shaders, + RenderPipelineHandle *pipelineOut) { auto iter = mRenderPipelines.find(desc); if (iter != mRenderPipelines.end()) diff --git a/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.h b/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.h index 03fad4bc0c0..5be13743185 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.h +++ b/src/libANGLE/renderer/wgpu/wgpu_pipeline_state.h @@ -7,13 +7,14 @@ #ifndef LIBANGLE_RENDERER_WGPU_PIPELINE_STATE_H_ #define LIBANGLE_RENDERER_WGPU_PIPELINE_STATE_H_ -#include #include +#include #include #include "libANGLE/Constants.h" #include "libANGLE/Error.h" #include "libANGLE/angletypes.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" #include "common/PackedEnums.h" @@ -142,24 +143,24 @@ class RenderPipelineDesc final bool setBlendEnabled(size_t colorIndex, bool enabled); bool setBlendFuncs(size_t colorIndex, - wgpu::BlendFactor srcRGB, - wgpu::BlendFactor dstRGB, - wgpu::BlendFactor srcAlpha, - wgpu::BlendFactor dstAlpha); - bool setBlendEquations(size_t colorIndex, wgpu::BlendOperation rgb, wgpu::BlendOperation alpha); + WGPUBlendFactor srcRGB, + WGPUBlendFactor dstRGB, + WGPUBlendFactor srcAlpha, + WGPUBlendFactor dstAlpha); + bool setBlendEquations(size_t colorIndex, WGPUBlendOperation rgb, WGPUBlendOperation alpha); bool setVertexAttribute(size_t attribIndex, PackedVertexAttribute &newAttrib); - bool setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format); - bool setDepthStencilAttachmentFormat(wgpu::TextureFormat format); - bool setDepthFunc(wgpu::CompareFunction compareFunc); - bool setStencilFrontFunc(wgpu::CompareFunction compareFunc); - bool setStencilFrontOps(wgpu::StencilOperation failOp, - wgpu::StencilOperation depthFailOp, - wgpu::StencilOperation passOp); - bool setStencilBackFunc(wgpu::CompareFunction compareFunc); - bool setStencilBackOps(wgpu::StencilOperation failOp, - wgpu::StencilOperation depthFailOp, - wgpu::StencilOperation passOp); + bool setColorAttachmentFormat(size_t colorIndex, WGPUTextureFormat format); + bool setDepthStencilAttachmentFormat(WGPUTextureFormat format); + bool setDepthFunc(WGPUCompareFunction compareFunc); + bool setStencilFrontFunc(WGPUCompareFunction compareFunc); + bool setStencilFrontOps(WGPUStencilOperation failOp, + WGPUStencilOperation depthFailOp, + WGPUStencilOperation passOp); + bool setStencilBackFunc(WGPUCompareFunction compareFunc); + bool setStencilBackOps(WGPUStencilOperation failOp, + WGPUStencilOperation depthFailOp, + WGPUStencilOperation passOp); bool setStencilReadMask(uint8_t readeMask); bool setStencilWriteMask(uint8_t writeMask); @@ -167,9 +168,9 @@ class RenderPipelineDesc final size_t hash() const; angle::Result createPipeline(ContextWgpu *context, - const wgpu::PipelineLayout &pipelineLayout, - const gl::ShaderMap &shaders, - wgpu::RenderPipeline *pipelineOut) const; + const PipelineLayoutHandle &pipelineLayout, + const gl::ShaderMap &shaders, + RenderPipelineHandle *pipelineOut) const; private: PackedVertexAttribute mVertexAttributes[gl::MAX_VERTEX_ATTRIBS]; @@ -213,12 +214,12 @@ class PipelineCache final angle::Result getRenderPipeline(ContextWgpu *context, const RenderPipelineDesc &desc, - const wgpu::PipelineLayout &pipelineLayout, - const gl::ShaderMap &shaders, - wgpu::RenderPipeline *pipelineOut); + const PipelineLayoutHandle &pipelineLayout, + const gl::ShaderMap &shaders, + RenderPipelineHandle *pipelineOut); private: - std::unordered_map mRenderPipelines; + std::unordered_map mRenderPipelines; }; } // namespace webgpu diff --git a/src/libANGLE/renderer/wgpu/wgpu_proc_utils.cpp b/src/libANGLE/renderer/wgpu/wgpu_proc_utils.cpp new file mode 100644 index 00000000000..fd4e1e1bb02 --- /dev/null +++ b/src/libANGLE/renderer/wgpu/wgpu_proc_utils.cpp @@ -0,0 +1,23 @@ +// +// Copyright 2025 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. +// + +#include "libANGLE/renderer/wgpu/wgpu_proc_utils.h" + +// DawnNative.h includes the webgpu cpp API which depends on wgpu function declarations. To hide the +// declarations from the rest of the ANGLE WebGPU backend, only enable them in this file. +#undef WGPU_SKIP_DECLARATIONS +#include + +namespace rx +{ +namespace webgpu +{ +const DawnProcTable &GetDefaultProcTable() +{ + return dawn::native::GetProcs(); +} +} // namespace webgpu +} // namespace rx diff --git a/src/libANGLE/renderer/wgpu/wgpu_proc_utils.h b/src/libANGLE/renderer/wgpu/wgpu_proc_utils.h new file mode 100644 index 00000000000..ab6d3b0ad5f --- /dev/null +++ b/src/libANGLE/renderer/wgpu/wgpu_proc_utils.h @@ -0,0 +1,20 @@ +// +// Copyright 2025 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. +// + +#ifndef LIBANGLE_RENDERER_WGPU_WGPU_PROC_UTILS_H_ +#define LIBANGLE_RENDERER_WGPU_WGPU_PROC_UTILS_H_ + +struct DawnProcTable; + +namespace rx +{ +namespace webgpu +{ +const DawnProcTable &GetDefaultProcTable(); +} +} // namespace rx + +#endif // LIBANGLE_RENDERER_WGPU_WGPU_PROC_UTILS_H diff --git a/src/libANGLE/renderer/wgpu/wgpu_sources.gni b/src/libANGLE/renderer/wgpu/wgpu_sources.gni index fc877419fc4..cabd6a813c3 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_sources.gni +++ b/src/libANGLE/renderer/wgpu/wgpu_sources.gni @@ -46,6 +46,8 @@ wgpu_backend_sources = [ "TextureWgpu.h", "TransformFeedbackWgpu.cpp", "TransformFeedbackWgpu.h", + "UtilsWgpu.cpp", + "UtilsWgpu.h", "VertexArrayWgpu.cpp", "VertexArrayWgpu.h", "wgpu_command_buffer.cpp", @@ -57,6 +59,8 @@ wgpu_backend_sources = [ "wgpu_helpers.h", "wgpu_pipeline_state.cpp", "wgpu_pipeline_state.h", + "wgpu_proc_utils.cpp", + "wgpu_proc_utils.h", "wgpu_utils.cpp", "wgpu_utils.h", "wgpu_wgsl_util.cpp", @@ -70,7 +74,7 @@ if (is_win) { ] } -if (is_mac) { +if (is_mac || is_ios) { wgpu_backend_sources += [ "mac/WindowSurfaceWgpuMetalLayer.h", "mac/WindowSurfaceWgpuMetalLayer.mm", diff --git a/src/libANGLE/renderer/wgpu/wgpu_utils.cpp b/src/libANGLE/renderer/wgpu/wgpu_utils.cpp index 1515cbd2d17..355ea946f0c 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_utils.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_utils.cpp @@ -6,10 +6,12 @@ #include "libANGLE/renderer/wgpu/wgpu_utils.h" +#include "common/log_utils.h" #include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/wgpu/ContextWgpu.h" #include "libANGLE/renderer/wgpu/DisplayWgpu.h" #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h" +#include "webgpu/webgpu.h" namespace rx { @@ -22,40 +24,64 @@ DisplayWgpu *GetDisplay(const gl::Context *context) return contextWgpu->getDisplay(); } -wgpu::Device GetDevice(const gl::Context *context) +const DawnProcTable *GetProcs(const gl::Context *context) +{ + DisplayWgpu *display = GetDisplay(context); + return display->getProcs(); +} + +const DawnProcTable *GetProcs(const ContextWgpu *context) +{ + DisplayWgpu *display = context->getDisplay(); + return display->getProcs(); +} + +const angle::FeaturesWgpu &GetFeatures(const gl::Context *context) +{ + DisplayWgpu *display = GetDisplay(context); + return display->getFeatures(); +} + +const angle::FeaturesWgpu &GetFeatures(const ContextWgpu *context) +{ + DisplayWgpu *display = context->getDisplay(); + return display->getFeatures(); +} + +webgpu::DeviceHandle GetDevice(const gl::Context *context) { DisplayWgpu *display = GetDisplay(context); return display->getDevice(); } -wgpu::Instance GetInstance(const gl::Context *context) +webgpu::InstanceHandle GetInstance(const gl::Context *context) { DisplayWgpu *display = GetDisplay(context); return display->getInstance(); } -wgpu::RenderPassColorAttachment CreateNewClearColorAttachment(wgpu::Color clearValue, +PackedRenderPassColorAttachment CreateNewClearColorAttachment(const gl::ColorF &clearValue, uint32_t depthSlice, - wgpu::TextureView textureView) + TextureViewHandle textureView) { - wgpu::RenderPassColorAttachment colorAttachment; + PackedRenderPassColorAttachment colorAttachment; colorAttachment.view = textureView; colorAttachment.depthSlice = depthSlice; - colorAttachment.loadOp = wgpu::LoadOp::Clear; - colorAttachment.storeOp = wgpu::StoreOp::Store; + colorAttachment.loadOp = WGPULoadOp_Clear; + colorAttachment.storeOp = WGPUStoreOp_Store; colorAttachment.clearValue = clearValue; return colorAttachment; } -wgpu::RenderPassDepthStencilAttachment CreateNewDepthStencilAttachment( +PackedRenderPassDepthStencilAttachment CreateNewClearDepthStencilAttachment( float depthClearValue, uint32_t stencilClearValue, - wgpu::TextureView textureView, + TextureViewHandle textureView, bool hasDepthValue, bool hasStencilValue) { - wgpu::RenderPassDepthStencilAttachment depthStencilAttachment; + PackedRenderPassDepthStencilAttachment depthStencilAttachment; depthStencilAttachment.view = textureView; // WebGPU requires that depth/stencil attachments have a load op if the correlated ReadOnly // value is set to false, so we make sure to set the value here to to support cases where only a @@ -64,28 +90,52 @@ wgpu::RenderPassDepthStencilAttachment CreateNewDepthStencilAttachment( depthStencilAttachment.stencilReadOnly = !hasStencilValue; if (hasDepthValue) { - depthStencilAttachment.depthLoadOp = wgpu::LoadOp::Clear; - depthStencilAttachment.depthStoreOp = wgpu::StoreOp::Store; + depthStencilAttachment.depthLoadOp = WGPULoadOp_Clear; + depthStencilAttachment.depthStoreOp = WGPUStoreOp_Store; depthStencilAttachment.depthClearValue = depthClearValue; } if (hasStencilValue) { - depthStencilAttachment.stencilLoadOp = wgpu::LoadOp::Clear; - depthStencilAttachment.stencilStoreOp = wgpu::StoreOp::Store; + depthStencilAttachment.stencilLoadOp = WGPULoadOp_Clear; + depthStencilAttachment.stencilStoreOp = WGPUStoreOp_Store; depthStencilAttachment.stencilClearValue = stencilClearValue; } return depthStencilAttachment; } -bool IsWgpuError(wgpu::WaitStatus waitStatus) +PackedRenderPassDepthStencilAttachment +CreateNewDepthStencilAttachment(TextureViewHandle textureView, bool hasDepth, bool hasStencilValue) +{ + PackedRenderPassDepthStencilAttachment depthStencilAttachment; + depthStencilAttachment.view = textureView; + // WebGPU requires that depth/stencil attachments have a load op if the correlated ReadOnly + // value is set to false, so we make sure to set the value here to to support cases where only a + // depth or stencil mask is set. + depthStencilAttachment.depthReadOnly = !hasDepth; + depthStencilAttachment.stencilReadOnly = !hasStencilValue; + if (hasDepth) + { + depthStencilAttachment.depthLoadOp = WGPULoadOp_Load; + depthStencilAttachment.depthStoreOp = WGPUStoreOp_Store; + } + if (hasStencilValue) + { + depthStencilAttachment.stencilLoadOp = WGPULoadOp_Load; + depthStencilAttachment.stencilStoreOp = WGPUStoreOp_Store; + } + + return depthStencilAttachment; +} + +bool IsWgpuError(WGPUWaitStatus waitStatus) { - return waitStatus != wgpu::WaitStatus::Success; + return waitStatus != WGPUWaitStatus_Success; } -bool IsWgpuError(WGPUBufferMapAsyncStatus mapBufferStatus) +bool IsWgpuError(WGPUMapAsyncStatus mapAsyncStatus) { - return mapBufferStatus != WGPUBufferMapAsyncStatus_Success; + return mapAsyncStatus != WGPUMapAsyncStatus_Success; } ClearValuesArray::ClearValuesArray() : mValues{}, mEnabled{} {} @@ -105,7 +155,85 @@ gl::DrawBufferMask ClearValuesArray::getColorMask() const return gl::DrawBufferMask(mEnabled.bits() & kUnpackedColorBuffersMask); } -void GenerateCaps(const wgpu::Limits &limitsWgpu, +bool operator==(const PackedRenderPassColorAttachment &a, const PackedRenderPassColorAttachment &b) +{ + return std::tie(a.view, a.depthSlice, a.loadOp, a.storeOp, a.clearValue) == + std::tie(b.view, b.depthSlice, b.loadOp, b.storeOp, b.clearValue); +} + +bool operator==(const PackedRenderPassDepthStencilAttachment &a, + const PackedRenderPassDepthStencilAttachment &b) +{ + return std::tie(a.view, a.depthLoadOp, a.depthStoreOp, a.depthReadOnly, a.depthClearValue, + a.stencilLoadOp, a.stencilStoreOp, a.stencilReadOnly, a.stencilClearValue) == + std::tie(b.view, b.depthLoadOp, b.depthStoreOp, b.depthReadOnly, b.depthClearValue, + b.stencilLoadOp, b.stencilStoreOp, b.stencilReadOnly, b.stencilClearValue); +} + +bool operator==(const PackedRenderPassDescriptor &a, const PackedRenderPassDescriptor &b) +{ + return std::tie(a.colorAttachments, a.depthStencilAttachment) == + std::tie(b.colorAttachments, b.depthStencilAttachment); +} + +bool operator!=(const PackedRenderPassDescriptor &a, const PackedRenderPassDescriptor &b) +{ + return !(a == b); +} + +RenderPassEncoderHandle CreateRenderPass(const DawnProcTable *wgpu, + webgpu::CommandEncoderHandle commandEncoder, + const webgpu::PackedRenderPassDescriptor &packedDesc) +{ + WGPURenderPassDescriptor renderPassDesc = WGPU_RENDER_PASS_DESCRIPTOR_INIT; + + angle::FixedVector + colorAttachments; + for (size_t i = 0; i < packedDesc.colorAttachments.size(); i++) + { + const webgpu::PackedRenderPassColorAttachment &packedColorAttachment = + packedDesc.colorAttachments[i]; + WGPURenderPassColorAttachment colorAttachment = WGPU_RENDER_PASS_COLOR_ATTACHMENT_INIT; + + colorAttachment.view = packedColorAttachment.view.get(); + colorAttachment.depthSlice = packedColorAttachment.depthSlice; + colorAttachment.resolveTarget = nullptr; + colorAttachment.loadOp = packedColorAttachment.loadOp; + colorAttachment.storeOp = packedColorAttachment.storeOp; + colorAttachment.clearValue = { + packedColorAttachment.clearValue.red, packedColorAttachment.clearValue.green, + packedColorAttachment.clearValue.blue, packedColorAttachment.clearValue.alpha}; + + colorAttachments.push_back(colorAttachment); + } + renderPassDesc.colorAttachments = colorAttachments.data(); + renderPassDesc.colorAttachmentCount = colorAttachments.size(); + + WGPURenderPassDepthStencilAttachment depthStencilAttachment = + WGPU_RENDER_PASS_DEPTH_STENCIL_ATTACHMENT_INIT; + if (packedDesc.depthStencilAttachment.has_value()) + { + const webgpu::PackedRenderPassDepthStencilAttachment &packedDepthStencilAttachment = + packedDesc.depthStencilAttachment.value(); + + depthStencilAttachment.view = packedDepthStencilAttachment.view.get(); + depthStencilAttachment.depthLoadOp = packedDepthStencilAttachment.depthLoadOp; + depthStencilAttachment.depthStoreOp = packedDepthStencilAttachment.depthStoreOp; + depthStencilAttachment.depthReadOnly = packedDepthStencilAttachment.depthReadOnly; + depthStencilAttachment.depthClearValue = packedDepthStencilAttachment.depthClearValue; + depthStencilAttachment.stencilLoadOp = packedDepthStencilAttachment.stencilLoadOp; + depthStencilAttachment.stencilStoreOp = packedDepthStencilAttachment.stencilStoreOp; + depthStencilAttachment.stencilReadOnly = packedDepthStencilAttachment.stencilReadOnly; + depthStencilAttachment.stencilClearValue = packedDepthStencilAttachment.stencilClearValue; + + renderPassDesc.depthStencilAttachment = &depthStencilAttachment; + } + + return RenderPassEncoderHandle::Acquire( + wgpu, wgpu->commandEncoderBeginRenderPass(commandEncoder.get(), &renderPassDesc)); +} + +void GenerateCaps(const WGPULimits &limitsWgpu, gl::Caps *glCaps, gl::TextureCapsMap *glTextureCapsMap, gl::Extensions *glExtensions, @@ -127,6 +255,13 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, glExtensions->textureStorageEXT = true; glExtensions->rgb8Rgba8OES = true; + glExtensions->EGLImageOES = true; + glExtensions->EGLImageExternalOES = true; + glExtensions->EGLImageExternalEssl3OES = true; + glExtensions->EGLImageExternalWrapModesEXT = true; + glExtensions->requiredInternalformatOES = true; + glExtensions->copyTextureCHROMIUM = true; + // OpenGL ES caps glCaps->maxElementIndex = std::numeric_limits::max() - 1; glCaps->max3DTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension3D); @@ -162,8 +297,8 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, glCaps->maxVertexAttribStride = rx::LimitToInt(std::min(limitsWgpu.maxVertexBufferArrayStride, static_cast(std::numeric_limits::max()))); - glCaps->maxElementsIndices = std::numeric_limits::max(); - glCaps->maxElementsVertices = std::numeric_limits::max(); + glCaps->maxElementsIndices = std::numeric_limits::max(); + glCaps->maxElementsVertices = std::numeric_limits::max(); glCaps->vertexHighpFloat.setIEEEFloat(); glCaps->vertexMediumpFloat.setIEEEHalfFloat(); glCaps->vertexLowpFloat.setIEEEHalfFloat(); @@ -177,10 +312,8 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, glCaps->fragmentMediumpInt.setTwosComplementInt(16); glCaps->fragmentLowpInt.setTwosComplementInt(16); - // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size - // currently), on AMD the maxUniformBufferRange is near uint32_t max. - GLuint maxUniformBlockSize = static_cast( - std::min(static_cast(0x10000), limitsWgpu.maxUniformBufferBindingSize)); + const GLuint maxUniformBlockSize = static_cast(std::min( + gl::IMPLEMENTATION_MAX_UNIFORM_BLOCK_SIZE, limitsWgpu.maxUniformBufferBindingSize)); const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * 4); const GLuint maxUniformComponents = maxUniformVectors * 4; @@ -212,7 +345,7 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, glCaps->maxCombinedShaderUniformComponents[shaderType] = maxCombinedUniformComponents; } - const GLint maxVarryingComponents = rx::LimitToInt(limitsWgpu.maxInterStageShaderComponents); + const GLint maxVaryingComponents = rx::LimitToInt(limitsWgpu.maxInterStageShaderVariables * 4); glCaps->maxVertexAttributes = rx::LimitToInt( limitsWgpu.maxVertexBuffers); // WebGPU has maxVertexBuffers and maxVertexAttributes but @@ -222,10 +355,10 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, maxUniformVectors; // Uniforms are implemented using a uniform buffer, so the max number of // uniforms we can support is the max buffer range divided by the size // of a single uniform (4X float). - glCaps->maxVertexOutputComponents = maxVarryingComponents; + glCaps->maxVertexOutputComponents = maxVaryingComponents; glCaps->maxFragmentUniformVectors = maxUniformVectors; - glCaps->maxFragmentInputComponents = maxVarryingComponents; + glCaps->maxFragmentInputComponents = maxVaryingComponents; glCaps->minProgramTextureGatherOffset = 0; glCaps->maxProgramTextureGatherOffset = 0; glCaps->minProgramTexelOffset = -8; @@ -244,7 +377,7 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, glCaps->uniformBufferOffsetAlignment = rx::LimitToInt(limitsWgpu.minUniformBufferOffsetAlignment); glCaps->maxCombinedUniformBlocks = glCaps->maxUniformBufferBindings; - glCaps->maxVaryingComponents = maxVarryingComponents; + glCaps->maxVaryingComponents = maxVaryingComponents; glCaps->maxVaryingVectors = rx::LimitToInt(limitsWgpu.maxInterStageShaderVariables); glCaps->maxCombinedTextureImageUnits = rx::LimitToInt(limitsWgpu.maxSamplersPerShaderStage * kShaderStageCount); @@ -291,16 +424,12 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, eglExtensions->image = true; eglExtensions->imageBase = true; eglExtensions->glTexture2DImage = true; - eglExtensions->glTextureCubemapImage = true; - eglExtensions->glTexture3DImage = true; eglExtensions->glRenderbufferImage = true; eglExtensions->getAllProcAddresses = true; eglExtensions->noConfigContext = true; - eglExtensions->directComposition = true; eglExtensions->createContextNoError = true; eglExtensions->createContextWebGLCompatibility = true; eglExtensions->createContextBindGeneratesResource = true; - eglExtensions->swapBuffersWithDamage = true; eglExtensions->pixelFormatFloat = true; eglExtensions->surfacelessContext = true; eglExtensions->displayTextureShareGroup = true; @@ -308,14 +437,15 @@ void GenerateCaps(const wgpu::Limits &limitsWgpu, eglExtensions->createContextClientArrays = true; eglExtensions->programCacheControlANGLE = true; eglExtensions->robustResourceInitializationANGLE = true; + eglExtensions->webgpuTextureClientBuffer = true; } -bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology) +bool IsStripPrimitiveTopology(WGPUPrimitiveTopology topology) { switch (topology) { - case wgpu::PrimitiveTopology::LineStrip: - case wgpu::PrimitiveTopology::TriangleStrip: + case WGPUPrimitiveTopology_LineStrip: + case WGPUPrimitiveTopology_TriangleStrip: return true; default: @@ -323,10 +453,13 @@ bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology) } } -ErrorScope::ErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType) - : mInstance(instance), mDevice(device) +ErrorScope::ErrorScope(const DawnProcTable *procTable, + webgpu::InstanceHandle instance, + webgpu::DeviceHandle device, + WGPUErrorFilter errorType) + : mProcTable(procTable), mInstance(instance), mDevice(device) { - mDevice.PushErrorScope(errorType); + mProcTable->devicePushErrorScope(mDevice.get(), errorType); mActive = true; } @@ -346,43 +479,72 @@ angle::Result ErrorScope::PopScope(ContextWgpu *context, } mActive = false; - bool hadError = false; - wgpu::Future f = mDevice.PopErrorScope( - wgpu::CallbackMode::WaitAnyOnly, - [context, file, function, line, &hadError](wgpu::PopErrorScopeStatus status, - wgpu::ErrorType type, char const *message) { - if (type == wgpu::ErrorType::NoError) - { - return; - } - - if (context) - { - ASSERT(file); - ASSERT(function); - context->handleError(GL_INVALID_OPERATION, message, file, function, line); - } - else - { - ERR() << "Unhandled WebGPU error: " << message; - } - hadError = true; - }); - mInstance.WaitAny(f, -1); - - return hadError ? angle::Result::Stop : angle::Result::Continue; + struct PopScopeContext + { + ContextWgpu *context = nullptr; + const char *file = nullptr; + const char *function = nullptr; + unsigned int line = 0; + bool hadError = false; + }; + + WGPUPopErrorScopeCallbackInfo callbackInfo = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT; + callbackInfo.mode = WGPUCallbackMode_AllowSpontaneous; + callbackInfo.callback = [](WGPUPopErrorScopeStatus status, WGPUErrorType type, + struct WGPUStringView message, void *userdata1, void *userdata2) { + PopScopeContext *ctx = reinterpret_cast(userdata1); + ASSERT(userdata2 == nullptr); + + if (type == WGPUErrorType_NoError) + { + return; + } + + if (ctx) + { + ASSERT(ctx->file); + ASSERT(ctx->function); + std::string msgStr(message.data, message.length); + ctx->context->handleError(GL_INVALID_OPERATION, msgStr.c_str(), ctx->file, + ctx->function, ctx->line); + ctx->hadError = true; + } + else + { + ERR() << "Unhandled WebGPU error: " << std::string(message.data, message.length); + } + }; + + const angle::FeaturesWgpu &features = GetFeatures(context); + if (features.avoidWaitAny.enabled) + { + // End the error scope but don't wait on it. The error messages will be printed later. + mProcTable->devicePopErrorScope(mDevice.get(), callbackInfo); + return angle::Result::Continue; + } + else + { + PopScopeContext popScopeContext{context, file, function, line, false}; + callbackInfo.userdata1 = &popScopeContext; + + WGPUFutureWaitInfo future = WGPU_FUTURE_WAIT_INFO_INIT; + future.future = mProcTable->devicePopErrorScope(mDevice.get(), callbackInfo); + mProcTable->instanceWaitAny(mInstance.get(), 1, &future, -1); + + return popScopeContext.hadError ? angle::Result::Stop : angle::Result::Continue; + } } } // namespace webgpu namespace wgpu_gl { -gl::LevelIndex getLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel) +gl::LevelIndex GetLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel) { return gl::LevelIndex(levelWgpu.get() + baseLevel.get()); } -gl::Extents getExtents(wgpu::Extent3D wgpuExtent) +gl::Extents GetExtents(WGPUExtent3D wgpuExtent) { gl::Extents glExtent; glExtent.width = wgpuExtent.width; @@ -400,189 +562,188 @@ webgpu::LevelIndex getLevelIndex(gl::LevelIndex levelGl, gl::LevelIndex baseLeve return webgpu::LevelIndex(levelGl.get() - baseLevel.get()); } -wgpu::Extent3D getExtent3D(const gl::Extents &glExtent) +WGPUExtent3D GetExtent3D(const gl::Extents &glExtent) { - wgpu::Extent3D wgpuExtent; + WGPUExtent3D wgpuExtent = WGPU_EXTENT_3D_INIT; wgpuExtent.width = glExtent.width; wgpuExtent.height = glExtent.height; wgpuExtent.depthOrArrayLayers = glExtent.depth; return wgpuExtent; } -wgpu::PrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode) +WGPUPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode) { switch (mode) { case gl::PrimitiveMode::Points: - return wgpu::PrimitiveTopology::PointList; + return WGPUPrimitiveTopology_PointList; case gl::PrimitiveMode::Lines: - return wgpu::PrimitiveTopology::LineList; + return WGPUPrimitiveTopology_LineList; case gl::PrimitiveMode::LineLoop: - return wgpu::PrimitiveTopology::LineStrip; // Emulated + return WGPUPrimitiveTopology_LineStrip; // Emulated case gl::PrimitiveMode::LineStrip: - return wgpu::PrimitiveTopology::LineStrip; + return WGPUPrimitiveTopology_LineStrip; case gl::PrimitiveMode::Triangles: - return wgpu::PrimitiveTopology::TriangleList; + return WGPUPrimitiveTopology_TriangleList; case gl::PrimitiveMode::TriangleStrip: - return wgpu::PrimitiveTopology::TriangleStrip; + return WGPUPrimitiveTopology_TriangleStrip; case gl::PrimitiveMode::TriangleFan: - UNIMPLEMENTED(); - return wgpu::PrimitiveTopology::TriangleList; // Emulated + return WGPUPrimitiveTopology_TriangleList; // Emulated default: UNREACHABLE(); - return wgpu::PrimitiveTopology::Undefined; + return WGPUPrimitiveTopology_Undefined; } } -wgpu::IndexFormat GetIndexFormat(gl::DrawElementsType drawElementsType) +WGPUIndexFormat GetIndexFormat(gl::DrawElementsType drawElementsType) { switch (drawElementsType) { case gl::DrawElementsType::UnsignedByte: - return wgpu::IndexFormat::Uint16; // Emulated + return WGPUIndexFormat_Uint16; // Emulated case gl::DrawElementsType::UnsignedShort: - return wgpu::IndexFormat::Uint16; + return WGPUIndexFormat_Uint16; case gl::DrawElementsType::UnsignedInt: - return wgpu::IndexFormat::Uint32; + return WGPUIndexFormat_Uint32; default: UNREACHABLE(); - return wgpu::IndexFormat::Undefined; + return WGPUIndexFormat_Undefined; } } -wgpu::FrontFace GetFrontFace(GLenum frontFace) +WGPUFrontFace GetFrontFace(GLenum frontFace) { switch (frontFace) { case GL_CW: - return wgpu::FrontFace::CW; + return WGPUFrontFace_CW; case GL_CCW: - return wgpu::FrontFace::CCW; + return WGPUFrontFace_CCW; default: UNREACHABLE(); - return wgpu::FrontFace::Undefined; + return WGPUFrontFace_Undefined; } } -wgpu::CullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled) +WGPUCullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled) { if (!cullFaceEnabled) { - return wgpu::CullMode::None; + return WGPUCullMode_None; } switch (mode) { case gl::CullFaceMode::Front: - return wgpu::CullMode::Front; + return WGPUCullMode_Front; case gl::CullFaceMode::Back: - return wgpu::CullMode::Back; + return WGPUCullMode_Back; case gl::CullFaceMode::FrontAndBack: UNIMPLEMENTED(); - return wgpu::CullMode::None; // Emulated + return WGPUCullMode_None; // Emulated default: UNREACHABLE(); - return wgpu::CullMode::None; + return WGPUCullMode_None; } } -wgpu::ColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a) +WGPUColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a) { - return (r ? wgpu::ColorWriteMask::Red : wgpu::ColorWriteMask::None) | - (g ? wgpu::ColorWriteMask::Green : wgpu::ColorWriteMask::None) | - (b ? wgpu::ColorWriteMask::Blue : wgpu::ColorWriteMask::None) | - (a ? wgpu::ColorWriteMask::Alpha : wgpu::ColorWriteMask::None); + return (r ? WGPUColorWriteMask_Red : WGPUColorWriteMask_None) | + (g ? WGPUColorWriteMask_Green : WGPUColorWriteMask_None) | + (b ? WGPUColorWriteMask_Blue : WGPUColorWriteMask_None) | + (a ? WGPUColorWriteMask_Alpha : WGPUColorWriteMask_None); } -wgpu::BlendFactor GetBlendFactor(gl::BlendFactorType blendFactor) +WGPUBlendFactor GetBlendFactor(gl::BlendFactorType blendFactor) { switch (blendFactor) { case gl::BlendFactorType::Zero: - return wgpu::BlendFactor::Zero; + return WGPUBlendFactor_Zero; case gl::BlendFactorType::One: - return wgpu::BlendFactor::One; + return WGPUBlendFactor_One; case gl::BlendFactorType::SrcColor: - return wgpu::BlendFactor::Src; + return WGPUBlendFactor_Src; case gl::BlendFactorType::OneMinusSrcColor: - return wgpu::BlendFactor::OneMinusSrc; + return WGPUBlendFactor_OneMinusSrc; case gl::BlendFactorType::SrcAlpha: - return wgpu::BlendFactor::SrcAlpha; + return WGPUBlendFactor_SrcAlpha; case gl::BlendFactorType::OneMinusSrcAlpha: - return wgpu::BlendFactor::OneMinusSrcAlpha; + return WGPUBlendFactor_OneMinusSrcAlpha; case gl::BlendFactorType::DstAlpha: - return wgpu::BlendFactor::DstAlpha; + return WGPUBlendFactor_DstAlpha; case gl::BlendFactorType::OneMinusDstAlpha: - return wgpu::BlendFactor::OneMinusDstAlpha; + return WGPUBlendFactor_OneMinusDstAlpha; case gl::BlendFactorType::DstColor: - return wgpu::BlendFactor::Dst; + return WGPUBlendFactor_Dst; case gl::BlendFactorType::OneMinusDstColor: - return wgpu::BlendFactor::OneMinusDst; + return WGPUBlendFactor_OneMinusDst; case gl::BlendFactorType::SrcAlphaSaturate: - return wgpu::BlendFactor::SrcAlphaSaturated; + return WGPUBlendFactor_SrcAlphaSaturated; case gl::BlendFactorType::ConstantColor: - return wgpu::BlendFactor::Constant; + return WGPUBlendFactor_Constant; case gl::BlendFactorType::OneMinusConstantColor: - return wgpu::BlendFactor::OneMinusConstant; + return WGPUBlendFactor_OneMinusConstant; case gl::BlendFactorType::ConstantAlpha: UNIMPLEMENTED(); - return wgpu::BlendFactor::Undefined; + return WGPUBlendFactor_Undefined; case gl::BlendFactorType::OneMinusConstantAlpha: UNIMPLEMENTED(); - return wgpu::BlendFactor::Undefined; + return WGPUBlendFactor_Undefined; case gl::BlendFactorType::Src1Alpha: - return wgpu::BlendFactor::Src1Alpha; + return WGPUBlendFactor_Src1Alpha; case gl::BlendFactorType::Src1Color: - return wgpu::BlendFactor::Src1; + return WGPUBlendFactor_Src1; case gl::BlendFactorType::OneMinusSrc1Color: - return wgpu::BlendFactor::OneMinusSrc1; + return WGPUBlendFactor_OneMinusSrc1; case gl::BlendFactorType::OneMinusSrc1Alpha: - return wgpu::BlendFactor::OneMinusSrc1Alpha; + return WGPUBlendFactor_OneMinusSrc1Alpha; default: UNREACHABLE(); - return wgpu::BlendFactor::Undefined; + return WGPUBlendFactor_Undefined; } } -wgpu::BlendOperation GetBlendEquation(gl::BlendEquationType blendEquation) +WGPUBlendOperation GetBlendEquation(gl::BlendEquationType blendEquation) { switch (blendEquation) { case gl::BlendEquationType::Add: - return wgpu::BlendOperation::Add; + return WGPUBlendOperation_Add; case gl::BlendEquationType::Min: - return wgpu::BlendOperation::Min; + return WGPUBlendOperation_Min; case gl::BlendEquationType::Max: - return wgpu::BlendOperation::Max; + return WGPUBlendOperation_Max; case gl::BlendEquationType::Subtract: - return wgpu::BlendOperation::Subtract; + return WGPUBlendOperation_Subtract; case gl::BlendEquationType::ReverseSubtract: - return wgpu::BlendOperation::ReverseSubtract; + return WGPUBlendOperation_ReverseSubtract; case gl::BlendEquationType::Multiply: case gl::BlendEquationType::Screen: @@ -603,97 +764,243 @@ wgpu::BlendOperation GetBlendEquation(gl::BlendEquationType blendEquation) case gl::BlendEquationType::HslLuminosity: // EXT_blend_equation_advanced UNIMPLEMENTED(); - return wgpu::BlendOperation::Undefined; + return WGPUBlendOperation_Undefined; default: UNREACHABLE(); - return wgpu::BlendOperation::Undefined; + return WGPUBlendOperation_Undefined; } } -wgpu::TextureDimension getWgpuTextureDimension(gl::TextureType glTextureType) +WGPUTextureViewDimension GetWgpuTextureViewDimension(gl::TextureType textureType) { - wgpu::TextureDimension dimension = {}; - switch (glTextureType) + switch (textureType) { case gl::TextureType::_2D: case gl::TextureType::_2DMultisample: - case gl::TextureType::Rectangle: - case gl::TextureType::External: - case gl::TextureType::Buffer: - dimension = wgpu::TextureDimension::e2D; - break; + return WGPUTextureViewDimension_2D; case gl::TextureType::_2DArray: case gl::TextureType::_2DMultisampleArray: + return WGPUTextureViewDimension_2DArray; case gl::TextureType::_3D: + return WGPUTextureViewDimension_3D; + case gl::TextureType::CubeMap: + return WGPUTextureViewDimension_Cube; + case gl::TextureType::CubeMapArray: + return WGPUTextureViewDimension_CubeArray; + default: + UNIMPLEMENTED(); + return WGPUTextureViewDimension_Undefined; + } +} + +WGPUTextureDimension GetWgpuTextureDimension(gl::TextureType glTextureType) +{ + switch (glTextureType) + { + // See https://www.w3.org/TR/webgpu/#dom-gputexture-createview. + case gl::TextureType::_2D: + case gl::TextureType::_2DArray: + case gl::TextureType::_2DMultisample: + case gl::TextureType::_2DMultisampleArray: case gl::TextureType::CubeMap: case gl::TextureType::CubeMapArray: + case gl::TextureType::Rectangle: + case gl::TextureType::External: + case gl::TextureType::Buffer: + return WGPUTextureDimension_2D; + case gl::TextureType::_3D: case gl::TextureType::VideoImage: - dimension = wgpu::TextureDimension::e3D; - break; + return WGPUTextureDimension_3D; default: - break; + UNREACHABLE(); + return WGPUTextureDimension_Undefined; } - return dimension; } -wgpu::CompareFunction GetCompareFunc(const GLenum glCompareFunc, bool testEnabled) +WGPUCompareFunction GetCompareFunc(const GLenum glCompareFunc, bool testEnabled) { if (!testEnabled) { - return wgpu::CompareFunction::Always; + return WGPUCompareFunction_Always; } switch (glCompareFunc) { case GL_NEVER: - return wgpu::CompareFunction::Never; + return WGPUCompareFunction_Never; case GL_LESS: - return wgpu::CompareFunction::Less; + return WGPUCompareFunction_Less; case GL_EQUAL: - return wgpu::CompareFunction::Equal; + return WGPUCompareFunction_Equal; case GL_LEQUAL: - return wgpu::CompareFunction::LessEqual; + return WGPUCompareFunction_LessEqual; case GL_GREATER: - return wgpu::CompareFunction::Greater; + return WGPUCompareFunction_Greater; case GL_NOTEQUAL: - return wgpu::CompareFunction::NotEqual; + return WGPUCompareFunction_NotEqual; case GL_GEQUAL: - return wgpu::CompareFunction::GreaterEqual; + return WGPUCompareFunction_GreaterEqual; case GL_ALWAYS: - return wgpu::CompareFunction::Always; + return WGPUCompareFunction_Always; default: UNREACHABLE(); - return wgpu::CompareFunction::Always; + return WGPUCompareFunction_Always; + } +} + +WGPUTextureSampleType GetTextureSampleType(gl::SamplerFormat samplerFormat) +{ + switch (samplerFormat) + { + case gl::SamplerFormat::Float: + return WGPUTextureSampleType_Float; + case gl::SamplerFormat::Unsigned: + return WGPUTextureSampleType_Uint; + case gl::SamplerFormat::Signed: + return WGPUTextureSampleType_Sint; + case gl::SamplerFormat::Shadow: + return WGPUTextureSampleType_Depth; + default: + UNIMPLEMENTED(); + return WGPUTextureSampleType_Undefined; } } -wgpu::StencilOperation getStencilOp(const GLenum glStencilOp) +WGPUStencilOperation GetStencilOp(const GLenum glStencilOp) { switch (glStencilOp) { case GL_KEEP: - return wgpu::StencilOperation::Keep; + return WGPUStencilOperation_Keep; case GL_ZERO: - return wgpu::StencilOperation::Zero; + return WGPUStencilOperation_Zero; case GL_REPLACE: - return wgpu::StencilOperation::Replace; + return WGPUStencilOperation_Replace; case GL_INCR: - return wgpu::StencilOperation::IncrementClamp; + return WGPUStencilOperation_IncrementClamp; case GL_DECR: - return wgpu::StencilOperation::DecrementClamp; + return WGPUStencilOperation_DecrementClamp; case GL_INCR_WRAP: - return wgpu::StencilOperation::IncrementWrap; + return WGPUStencilOperation_IncrementWrap; case GL_DECR_WRAP: - return wgpu::StencilOperation::DecrementWrap; + return WGPUStencilOperation_DecrementWrap; case GL_INVERT: - return wgpu::StencilOperation::Invert; + return WGPUStencilOperation_Invert; default: UNREACHABLE(); - return wgpu::StencilOperation::Keep; + return WGPUStencilOperation_Keep; } } +WGPUFilterMode GetFilter(const GLenum filter) +{ + switch (filter) + { + case GL_LINEAR_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR: + return WGPUFilterMode_Linear; + case GL_NEAREST_MIPMAP_LINEAR: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST: + return WGPUFilterMode_Nearest; + default: + UNREACHABLE(); + return WGPUFilterMode_Undefined; + } +} + +WGPUMipmapFilterMode GetSamplerMipmapMode(const GLenum filter) +{ + switch (filter) + { + case GL_LINEAR_MIPMAP_LINEAR: + case GL_NEAREST_MIPMAP_LINEAR: + return WGPUMipmapFilterMode_Linear; + // GL_LINEAR and GL_NEAREST do not map directly to WebGPU but can be easily emulated, + // see below. + case GL_LINEAR: + case GL_NEAREST: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + return WGPUMipmapFilterMode_Nearest; + default: + UNREACHABLE(); + return WGPUMipmapFilterMode_Undefined; + } +} + +WGPUAddressMode GetSamplerAddressMode(const GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: + return WGPUAddressMode_Repeat; + case GL_MIRRORED_REPEAT: + return WGPUAddressMode_MirrorRepeat; + case GL_CLAMP_TO_BORDER: + // Not in WebGPU and not available in ES 3.0 or before. + UNIMPLEMENTED(); + return WGPUAddressMode_ClampToEdge; + case GL_CLAMP_TO_EDGE: + return WGPUAddressMode_ClampToEdge; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + // Not in WebGPU and not available in ES 3.0 or before. + return WGPUAddressMode_ClampToEdge; + default: + UNREACHABLE(); + return WGPUAddressMode_Undefined; + } +} + +WGPUCompareFunction GetSamplerCompareFunc(const gl::SamplerState *samplerState) +{ + if (samplerState->getCompareMode() != GL_COMPARE_REF_TO_TEXTURE) + { + return WGPUCompareFunction_Undefined; + } + + return GetCompareFunc(samplerState->getCompareFunc(), /*testEnabled=*/true); +} + +WGPUSamplerDescriptor GetWgpuSamplerDesc(const gl::SamplerState *samplerState) +{ + WGPUMipmapFilterMode wgpuMipmapFilterMode = GetSamplerMipmapMode(samplerState->getMinFilter()); + // Negative values don't seem to make a difference to the behavior of GLES, a min lod of 0.0 + // functions the same. + float wgpuLodMinClamp = + gl::clamp(samplerState->getMinLod(), webgpu::kWGPUMinLod, webgpu::kWGPUMaxLod); + float wgpuLodMaxClamp = + gl::clamp(samplerState->getMaxLod(), webgpu::kWGPUMinLod, webgpu::kWGPUMaxLod); + + if (!gl::IsMipmapFiltered(samplerState->getMinFilter())) + { + // Similarly to Vulkan, GL_NEAREST and GL_LINEAR do not map directly to WGPU, so + // they must be emulated (See "Mapping of OpenGL to Vulkan filter modes") + wgpuMipmapFilterMode = WGPUMipmapFilterMode_Nearest; + wgpuLodMinClamp = 0.0f; + wgpuLodMaxClamp = 0.25f; + } + + WGPUSamplerDescriptor samplerDesc = WGPU_SAMPLER_DESCRIPTOR_INIT; + samplerDesc.addressModeU = GetSamplerAddressMode(samplerState->getWrapS()); + samplerDesc.addressModeV = GetSamplerAddressMode(samplerState->getWrapT()); + samplerDesc.addressModeW = GetSamplerAddressMode(samplerState->getWrapR()); + samplerDesc.magFilter = GetFilter(samplerState->getMagFilter()); + samplerDesc.minFilter = GetFilter(samplerState->getMinFilter()); + samplerDesc.mipmapFilter = wgpuMipmapFilterMode; + samplerDesc.lodMinClamp = wgpuLodMinClamp; + samplerDesc.lodMaxClamp = wgpuLodMaxClamp; + samplerDesc.compare = GetSamplerCompareFunc(samplerState); + // TODO(anglebug.com/389145696): there's no way to get the supported maxAnisotropy value from + // WGPU, so there's no way to communicate to the GL client whether anisotropy is even supported + // as an extension, let alone what the max value is. + samplerDesc.maxAnisotropy = static_cast(std::floor(samplerState->getMaxAnisotropy())); + + return samplerDesc; +} + uint32_t GetFirstIndexForDrawCall(gl::DrawElementsType indexType, const void *indices) { const size_t indexSize = gl::GetDrawElementsTypeSize(indexType); diff --git a/src/libANGLE/renderer/wgpu/wgpu_utils.h b/src/libANGLE/renderer/wgpu/wgpu_utils.h index d8c78e370a8..ea5fb4cd725 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_utils.h +++ b/src/libANGLE/renderer/wgpu/wgpu_utils.h @@ -7,8 +7,9 @@ #ifndef LIBANGLE_RENDERER_WGPU_WGPU_UTILS_H_ #define LIBANGLE_RENDERER_WGPU_WGPU_UTILS_H_ -#include +#include #include +#include #include #include "libANGLE/Caps.h" @@ -27,9 +28,9 @@ } \ } while (0) -#define ANGLE_WGPU_BEGIN_DEBUG_ERROR_SCOPE(context) \ - ::rx::webgpu::DebugErrorScope(context->getInstance(), context->getDevice(), \ - wgpu::ErrorFilter::Validation) +#define ANGLE_WGPU_BEGIN_DEBUG_ERROR_SCOPE(context) \ + ::rx::webgpu::DebugErrorScope(context->getProcs(), context->getInstance(), \ + context->getDevice(), WGPUErrorFilter_Validation) #define ANGLE_WGPU_END_DEBUG_ERROR_SCOPE(context, scope) \ ANGLE_TRY(scope.PopScope(context, __FILE__, ANGLE_FUNCTION, __LINE__)) @@ -48,6 +49,7 @@ PROC(Query) \ PROC(Program) \ PROC(ProgramExecutable) \ + PROC(Renderbuffer) \ PROC(Sampler) \ PROC(Texture) \ PROC(TransformFeedback) \ @@ -55,10 +57,56 @@ #define ANGLE_EGL_OBJECTS_X(PROC) \ PROC(Display) \ + PROC(ExternalImageSibling) \ PROC(Image) \ PROC(Surface) \ PROC(Sync) +#define ANGLE_WGPU_OBJECTS_X(PROC) \ + PROC(Adapter, adapter) \ + PROC(BindGroup, bindGroup) \ + PROC(BindGroupLayout, bindGroupLayout) \ + PROC(Buffer, buffer) \ + PROC(CommandBuffer, commandBuffer) \ + PROC(CommandEncoder, commandEncoder) \ + PROC(ComputePassEncoder, computePassEncoder) \ + PROC(ComputePipeline, computePipeline) \ + PROC(Device, device) \ + PROC(ExternalTexture, externalTexture) \ + PROC(Instance, instance) \ + PROC(PipelineLayout, pipelineLayout) \ + PROC(QuerySet, querySet) \ + PROC(Queue, queue) \ + PROC(RenderBundle, renderBundle) \ + PROC(RenderBundleEncoder, renderBundleEncoder) \ + PROC(RenderPassEncoder, renderPassEncoder) \ + PROC(RenderPipeline, renderPipeline) \ + PROC(Sampler, sampler) \ + PROC(ShaderModule, shaderModule) \ + PROC(SharedBufferMemory, sharedBufferMemory) \ + PROC(SharedFence, sharedFence) \ + PROC(SharedTextureMemory, sharedTextureMemory) \ + PROC(Surface, surface) \ + PROC(Texture, texture) \ + PROC(TextureView, textureView) + +namespace gl +{ +#define ANGLE_PRE_DECLARE_GL_OBJECT(OBJ) class OBJ; +ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_GL_OBJECT) +} // namespace gl + +namespace egl +{ +#define ANGLE_PRE_DECLARE_EGL_OBJECT(OBJ) class OBJ; +ANGLE_EGL_OBJECTS_X(ANGLE_PRE_DECLARE_EGL_OBJECT) +} // namespace egl + +namespace angle +{ +struct FeaturesWgpu; +} + namespace rx { @@ -72,6 +120,122 @@ ANGLE_EGL_OBJECTS_X(ANGLE_PRE_DECLARE_WGPU_OBJECT) namespace webgpu { +#define ANGLE_DECLARE_WGPU_HANDLE_REF_FUNCS(OBJ, obj) \ + inline void AddRefWGPUCHandle(const DawnProcTable *wgpu, WGPU##OBJ handle) \ + { \ + if (handle) \ + { \ + ASSERT(wgpu != nullptr); \ + wgpu->obj##AddRef(handle); \ + } \ + } \ + \ + inline void ReleaseWGPUCHandle(const DawnProcTable *wgpu, WGPU##OBJ handle) \ + { \ + if (handle) \ + { \ + ASSERT(wgpu != nullptr); \ + wgpu->obj##Release(handle); \ + } \ + } + +ANGLE_WGPU_OBJECTS_X(ANGLE_DECLARE_WGPU_HANDLE_REF_FUNCS) +#undef ANGLE_DECLARE_WGPU_HANDLE_REF_FUNCS + +template +class WrapperBase +{ + public: + using ObjectType = CType; + + WrapperBase() = default; + WrapperBase(const WrapperBase &other) + : mProcTable(other.mProcTable), mHandle(other.mHandle) + { + AddRefWGPUCHandle(mProcTable, mHandle); + } + + ~WrapperBase() { ReleaseWGPUCHandle(mProcTable, mHandle); } + + WrapperBase &operator=(const WrapperBase &other) + { + if (&other != this) + { + ReleaseWGPUCHandle(mProcTable, mHandle); + mProcTable = other.mProcTable; + mHandle = other.mHandle; + AddRefWGPUCHandle(mProcTable, mHandle); + } + return *this; + } + + WrapperBase(WrapperBase &&other) + { + mProcTable = other.mProcTable; + mHandle = other.mHandle; + other.mProcTable = nullptr; + other.mHandle = nullptr; + } + + WrapperBase &operator=(WrapperBase &&other) + { + if (&other != this) + { + ReleaseWGPUCHandle(mProcTable, mHandle); + mProcTable = other.mProcTable; + mHandle = other.mHandle; + other.mProcTable = nullptr; + other.mHandle = nullptr; + } + return *this; + } + + WrapperBase(std::nullptr_t) {} + + WrapperBase &operator=(std::nullptr_t) + { + ReleaseWGPUCHandle(mProcTable, mHandle); + mProcTable = nullptr; + mHandle = nullptr; + return *this; + } + + bool operator==(const WrapperBase &other) const { return mHandle == other.mHandle; } + + bool operator!=(const WrapperBase &other) const { return !(*this == other); } + + bool operator==(std::nullptr_t) const { return mHandle == nullptr; } + + bool operator!=(std::nullptr_t) const { return mHandle != nullptr; } + + explicit operator bool() const { return mHandle != nullptr; } + + const CType &get() const { return mHandle; } + + static WrapperBase Acquire(const DawnProcTable *procTable, CType handle) + { + WrapperBase result; + result.mHandle = handle; + result.mProcTable = procTable; + return result; + } + + size_t hash() const + { + std::hash hasher; + return hasher(mHandle); + } + + private: + const DawnProcTable *mProcTable = nullptr; + CType mHandle = nullptr; +}; + +#define ANGLE_DECLARE_WGPU_OBJECT_WRAPPER(OBJ, obj) using OBJ##Handle = WrapperBase; + +ANGLE_WGPU_OBJECTS_X(ANGLE_DECLARE_WGPU_OBJECT_WRAPPER) +#undef ANGLE_DECLARE_WGPU_OBJECT_WRAPPER + template struct ImplTypeHelper; @@ -109,7 +273,10 @@ using LevelIndex = gl::LevelIndexWrapper; class ErrorScope : public angle::NonCopyable { public: - ErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType); + ErrorScope(const DawnProcTable *procTable, + webgpu::InstanceHandle instance, + webgpu::DeviceHandle device, + WGPUErrorFilter errorType); ~ErrorScope(); angle::Result PopScope(ContextWgpu *context, @@ -118,15 +285,20 @@ class ErrorScope : public angle::NonCopyable unsigned int line); private: - wgpu::Instance mInstance; - wgpu::Device mDevice; + const DawnProcTable *mProcTable = nullptr; + webgpu::InstanceHandle mInstance; + webgpu::DeviceHandle mDevice; bool mActive = false; }; class NoOpErrorScope : public angle::NonCopyable { public: - NoOpErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType) {} + NoOpErrorScope(const DawnProcTable *procTable, + webgpu::InstanceHandle instance, + webgpu::DeviceHandle device, + WGPUErrorFilter errorType) + {} ~NoOpErrorScope() {} angle::Result PopScope(ContextWgpu *context, @@ -156,6 +328,9 @@ enum class RenderPassClosureReason IndexRangeReadback, VertexArrayStreaming, VertexArrayLineLoop, + CopyBufferToTexture, + CopyTextureToTexture, + CopyImage, InvalidEnum, EnumCount = InvalidEnum, @@ -163,7 +338,7 @@ enum class RenderPassClosureReason struct ClearValues { - wgpu::Color clearColor; + gl::ColorF clearColor; uint32_t depthSlice; float depthValue; uint32_t stencilValue; @@ -218,7 +393,48 @@ class ClearValuesArray final gl::AttachmentsMask mEnabled; }; -void GenerateCaps(const wgpu::Limits &limitWgpu, +struct PackedRenderPassColorAttachment +{ + TextureViewHandle view; + uint32_t depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; + WGPULoadOp loadOp = WGPULoadOp_Undefined; + WGPUStoreOp storeOp = WGPUStoreOp_Undefined; + gl::ColorF clearValue; +}; + +bool operator==(const PackedRenderPassColorAttachment &a, const PackedRenderPassColorAttachment &b); + +struct PackedRenderPassDepthStencilAttachment +{ + TextureViewHandle view; + WGPULoadOp depthLoadOp = WGPULoadOp_Undefined; + WGPUStoreOp depthStoreOp = WGPUStoreOp_Undefined; + bool depthReadOnly = false; + float depthClearValue = NAN; + WGPULoadOp stencilLoadOp = WGPULoadOp_Undefined; + WGPUStoreOp stencilStoreOp = WGPUStoreOp_Undefined; + bool stencilReadOnly = false; + uint32_t stencilClearValue = 0; +}; + +bool operator==(const PackedRenderPassDepthStencilAttachment &a, + const PackedRenderPassDepthStencilAttachment &b); + +struct PackedRenderPassDescriptor +{ + angle::FixedVector + colorAttachments; + std::optional depthStencilAttachment; +}; + +bool operator==(const PackedRenderPassDescriptor &a, const PackedRenderPassDescriptor &b); +bool operator!=(const PackedRenderPassDescriptor &a, const PackedRenderPassDescriptor &b); + +RenderPassEncoderHandle CreateRenderPass(const DawnProcTable *wgpu, + webgpu::CommandEncoderHandle commandEncoder, + const webgpu::PackedRenderPassDescriptor &desc); + +void GenerateCaps(const WGPULimits &limitWgpu, gl::Caps *glCaps, gl::TextureCapsMap *glTextureCapsMap, gl::Extensions *glExtensions, @@ -228,22 +444,30 @@ void GenerateCaps(const wgpu::Limits &limitWgpu, gl::Version *maxSupportedESVersion); DisplayWgpu *GetDisplay(const gl::Context *context); -wgpu::Device GetDevice(const gl::Context *context); -wgpu::Instance GetInstance(const gl::Context *context); -wgpu::RenderPassColorAttachment CreateNewClearColorAttachment(wgpu::Color clearValue, +const DawnProcTable *GetProcs(const gl::Context *context); +const DawnProcTable *GetProcs(const ContextWgpu *context); +const angle::FeaturesWgpu &GetFeatures(const gl::Context *context); +const angle::FeaturesWgpu &GetFeatures(const ContextWgpu *context); +webgpu::DeviceHandle GetDevice(const gl::Context *context); +webgpu::InstanceHandle GetInstance(const gl::Context *context); +PackedRenderPassColorAttachment CreateNewClearColorAttachment(const gl::ColorF &clearValue, uint32_t depthSlice, - wgpu::TextureView textureView); -wgpu::RenderPassDepthStencilAttachment CreateNewDepthStencilAttachment( + TextureViewHandle textureView); +PackedRenderPassDepthStencilAttachment CreateNewClearDepthStencilAttachment( float depthClearValue, uint32_t stencilClearValue, - wgpu::TextureView textureView, + TextureViewHandle textureView, + bool hasDepthValue = false, + bool hasStencilValue = false); +PackedRenderPassDepthStencilAttachment CreateNewDepthStencilAttachment( + TextureViewHandle textureView, bool hasDepthValue = false, bool hasStencilValue = false); -bool IsWgpuError(wgpu::WaitStatus waitStatus); -bool IsWgpuError(WGPUBufferMapAsyncStatus mapBufferStatus); +bool IsWgpuError(WGPUWaitStatus waitStatus); +bool IsWgpuError(WGPUMapAsyncStatus mapAsyncStatus); -bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology); +bool IsStripPrimitiveTopology(WGPUPrimitiveTopology topology); // Required alignments for buffer sizes and mapping constexpr size_t kBufferSizeAlignment = 4; @@ -254,32 +478,47 @@ constexpr size_t kBufferMapOffsetAlignment = 8; // Required alignments for texture row uploads constexpr size_t kTextureRowSizeAlignment = 256; +// Structs in WGPU's uniform address space are always aligned to 16. I.e. RequiredAlignOf(struct S, +// uniform) = roundUp(16, AlignOf(S)) and AlignOf(S) is at most 16. +constexpr size_t kUniformStructAlignment = 16; + +// min and max LOD clamp values. +constexpr float kWGPUMinLod = 0.0; +constexpr float kWGPUMaxLod = 32.0; + } // namespace webgpu namespace wgpu_gl { -gl::LevelIndex getLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel); -gl::Extents getExtents(wgpu::Extent3D wgpuExtent); +gl::LevelIndex GetLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel); +gl::Extents GetExtents(WGPUExtent3D wgpuExtent); } // namespace wgpu_gl namespace gl_wgpu { webgpu::LevelIndex getLevelIndex(gl::LevelIndex levelGl, gl::LevelIndex baseLevel); -wgpu::TextureDimension getWgpuTextureDimension(gl::TextureType glTextureType); -wgpu::Extent3D getExtent3D(const gl::Extents &glExtent); +WGPUTextureViewDimension GetWgpuTextureViewDimension(gl::TextureType textureType); +WGPUTextureDimension GetWgpuTextureDimension(gl::TextureType glTextureType); +WGPUExtent3D GetExtent3D(const gl::Extents &glExtent); + +WGPUPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode); -wgpu::PrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode); +WGPUIndexFormat GetIndexFormat(gl::DrawElementsType drawElementsTYpe); +WGPUFrontFace GetFrontFace(GLenum frontFace); +WGPUCullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled); +WGPUColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a); -wgpu::IndexFormat GetIndexFormat(gl::DrawElementsType drawElementsTYpe); -wgpu::FrontFace GetFrontFace(GLenum frontFace); -wgpu::CullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled); -wgpu::ColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a); +WGPUBlendFactor GetBlendFactor(gl::BlendFactorType blendFactor); +WGPUBlendOperation GetBlendEquation(gl::BlendEquationType blendEquation); -wgpu::BlendFactor GetBlendFactor(gl::BlendFactorType blendFactor); -wgpu::BlendOperation GetBlendEquation(gl::BlendEquationType blendEquation); +WGPUCompareFunction GetCompareFunc(const GLenum glCompareFunc, bool testEnabled); +WGPUTextureSampleType GetTextureSampleType(gl::SamplerFormat samplerFormat); +WGPUStencilOperation GetStencilOp(const GLenum glStencilOp); +WGPUFilterMode GetFilter(const GLenum filter); +WGPUMipmapFilterMode GetSamplerMipmapMode(const GLenum filter); +WGPUAddressMode GetSamplerAddressMode(const GLenum wrap); -wgpu::CompareFunction GetCompareFunc(const GLenum glCompareFunc, bool testEnabled); -wgpu::StencilOperation getStencilOp(const GLenum glStencilOp); +WGPUSamplerDescriptor GetWgpuSamplerDesc(const gl::SamplerState *samplerState); uint32_t GetFirstIndexForDrawCall(gl::DrawElementsType indexType, const void *indices); } // namespace gl_wgpu @@ -289,42 +528,13 @@ constexpr uint32_t kReservedPerStageDefaultUniformSlotCount = 0; } // namespace rx -#define ANGLE_WGPU_WRAPPER_OBJECTS_X(PROC) \ - PROC(BindGroup) \ - PROC(Buffer) \ - PROC(RenderPipeline) - -// Add a hash function for all wgpu cpp wrappers that hashes the underlying C object pointer. -#define ANGLE_WGPU_WRAPPER_OBJECT_HASH(OBJ) \ - namespace std \ - { \ - template <> \ - struct hash \ - { \ - size_t operator()(const wgpu::OBJ &wrapper) const \ - { \ - std::hash cTypeHash; \ - return cTypeHash(wrapper.Get()); \ - } \ - }; \ - } - -ANGLE_WGPU_WRAPPER_OBJECTS_X(ANGLE_WGPU_WRAPPER_OBJECT_HASH) -#undef ANGLE_WGPU_WRAPPER_OBJECT_HASH - -// Add a hash function for all wgpu cpp wrappers that compares the underlying C object pointer. -#define ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY(OBJ) \ - namespace wgpu \ - { \ - inline bool operator==(const OBJ &a, const OBJ &b) \ - { \ - return a.Get() == b.Get(); \ - } \ - } - -ANGLE_WGPU_WRAPPER_OBJECTS_X(ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY) -#undef ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY - -#undef ANGLE_WGPU_WRAPPER_OBJECTS_X +namespace std +{ +template +struct hash> +{ + size_t operator()(const rx::webgpu::WrapperBase &obj) const { return obj.hash(); } +}; +} // namespace std #endif // LIBANGLE_RENDERER_WGPU_WGPU_UTILS_H_ diff --git a/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.cpp b/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.cpp index d3ab8a91a34..33c1c1a8288 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.cpp +++ b/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.cpp @@ -4,12 +4,20 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/renderer/wgpu/wgpu_wgsl_util.h" #include +#include #include "common/PackedEnums.h" #include "common/PackedGLEnums_autogen.h" +#include "common/log_utils.h" +#include "common/utilities.h" +#include "compiler/translator/wgsl/OutputUniformBlocks.h" #include "libANGLE/Program.h" #include "libANGLE/ProgramExecutable.h" @@ -22,70 +30,133 @@ namespace { const bool kOutputReplacements = false; -std::string WgslReplaceLocationMarkers(const std::string &shaderSource, - std::map varNameToLocation) +void ReplaceFoundMarker(const std::string &shaderSource, + std::string &newSource, + const std::map &varNameToLocation, + const char *marker, + const char *markerReplacement, + const char *replacementEnd, + size_t nextMarker, + size_t &currPos) { - const char *marker = "@location(@@@@@@) "; const char *endOfName = " : "; + // Copy up to the next marker + newSource.append(shaderSource, currPos, nextMarker - currPos); + + // Extract name from something like `@location(@@@@@@) NAME : TYPE`. + size_t startOfNamePos = nextMarker + strlen(marker); + size_t endOfNamePos = shaderSource.find(endOfName, startOfNamePos, strlen(endOfName)); + std::string name = shaderSource.substr(startOfNamePos, endOfNamePos - startOfNamePos); + + // Use the shader variable's name to get the assigned location + auto locationIter = varNameToLocation.find(name); + if (locationIter == varNameToLocation.end()) + { + if (kOutputReplacements) + { + std::cout << "Didn't find " << name << ", so skipping to next semicolon" << std::endl; + } + // This should be an ignored sampler, so just delete it. + size_t endOfLine = shaderSource.find(";\n", nextMarker); + currPos = endOfLine + 2; + return; + } + + // TODO(anglebug.com/42267100): if the GLSL input is a matrix there should be multiple + // WGSL input variables (multiple vectors representing the columns of the matrix). + int location = locationIter->second; + std::ostringstream locationReplacementStream; + locationReplacementStream << markerReplacement << location << replacementEnd << " " << name; + + if (kOutputReplacements) + { + std::cout << "Replace \"" << marker << name << "\" with \"" + << locationReplacementStream.str() << "\"" << std::endl; + } + + // Append the new `@location(N) name` and then continue from the ` : type`. + newSource.append(locationReplacementStream.str()); + currPos = endOfNamePos; +} + +std::string WgslReplaceMarkers(const std::string &shaderSource, + const std::map &varNameToLocation) +{ + const char *locationMarker = "@location(@@@@@@) "; + const char *bindingMarker = "@group(1) @binding(@@@@@@) var "; + std::string newSource; newSource.reserve(shaderSource.size()); size_t currPos = 0; while (true) { - size_t nextMarker = shaderSource.find(marker, currPos, strlen(marker)); - if (nextMarker == std::string::npos) + size_t nextMarker = shaderSource.find(locationMarker, currPos, strlen(locationMarker)); + if (nextMarker != std::string::npos) + { + ReplaceFoundMarker(shaderSource, newSource, varNameToLocation, locationMarker, + "@location(", ")", nextMarker, currPos); + } + else if ((nextMarker = shaderSource.find(bindingMarker, currPos, strlen(bindingMarker))) != + std::string::npos) + { + + ReplaceFoundMarker(shaderSource, newSource, varNameToLocation, bindingMarker, + "@group(1) @binding(", ") var", nextMarker, currPos); + } + else { // Copy the rest of the shader and end the loop. newSource.append(shaderSource, currPos); break; } - else - { - // Copy up to the next marker - newSource.append(shaderSource, currPos, nextMarker - currPos); - - // Extract name from something like `@location(@@@@@@) NAME : TYPE`. - size_t startOfNamePos = nextMarker + strlen(marker); - size_t endOfNamePos = shaderSource.find(endOfName, startOfNamePos, strlen(endOfName)); - std::string name(shaderSource.c_str() + startOfNamePos, endOfNamePos - startOfNamePos); + } + return newSource; +} - // Use the shader variable's name to get the assigned location - auto locationIter = varNameToLocation.find(name); - if (locationIter == varNameToLocation.end()) - { - ASSERT(false); - return ""; - } +void AddShaderVarLocation(std::map &varNameToLocation, + std::string varName, + int &startLoc, + GLenum varType, + unsigned int arraySize) +{ + ASSERT(!gl::IsSamplerType(varType)); - // TODO(anglebug.com/42267100): if the GLSL input is a matrix there should be multiple - // WGSL input variables (multiple vectors representing the columns of the matrix). - int location = locationIter->second; - std::ostringstream locationReplacementStream; - locationReplacementStream << "@location(" << location << ") " << name; + if (!arraySize && !gl::IsMatrixType(varType)) + { + ASSERT(varNameToLocation.find(varName) == varNameToLocation.end()); + varNameToLocation[varName] = startLoc++; + return; + } - if (kOutputReplacements) - { - std::cout << "Replace \"" << marker << name << "\" with \"" - << locationReplacementStream.str() << "\"" << std::endl; - } + if (arraySize) + { + // TODO(anglebug.com/42267100): need to support arrays (of scalars, vectors, and matrices). + UNIMPLEMENTED(); + return; + } - // Append the new `@location(N) name` and then continue from the ` : type`. - newSource.append(locationReplacementStream.str()); - currPos = endOfNamePos; + if (gl::IsMatrixType(varType)) + { + // Split into column vectors. + for (int i = 0; i < gl::VariableColumnCount(varType); i++) + { + std::string fullVarName = varName + "_col" + std::to_string(i); + ASSERT(varNameToLocation.find(fullVarName) == varNameToLocation.end()); + varNameToLocation[fullVarName] = startLoc++; } } - return newSource; } } // namespace template -std::string WgslAssignLocations(const std::string &shaderSource, - const std::vector shaderVars, - const gl::ProgramMergedVaryings &mergedVaryings, - gl::ShaderType shaderType) +std::string WgslAssignLocationsAndSamplerBindings(const gl::ProgramExecutable &executable, + const std::string &shaderSource, + const std::vector shaderVars, + const gl::ProgramMergedVaryings &mergedVaryings, + gl::ShaderType shaderType) { std::map varNameToLocation; for (const T &shaderVar : shaderVars) @@ -94,7 +165,9 @@ std::string WgslAssignLocations(const std::string &shaderSource, { continue; } - varNameToLocation[shaderVar.name] = shaderVar.getLocation(); + int loc = shaderVar.getLocation(); + AddShaderVarLocation(varNameToLocation, shaderVar.mappedName, loc, shaderVar.getType(), + shaderVar.isArray() ? shaderVar.getBasicTypeElementCount() : 0u); } int currLocMarker = 0; @@ -119,8 +192,9 @@ std::string WgslAssignLocations(const std::string &shaderSource, { continue; } - ASSERT(varNameToLocation.find(shaderVar->name) == varNameToLocation.end()); - varNameToLocation[shaderVar->name] = currLocMarker++; + AddShaderVarLocation(varNameToLocation, shaderVar->mappedName, currLocMarker, + shaderVar->type, + shaderVar->isArray() ? shaderVar->getBasicTypeElementCount() : 0u); } else { @@ -137,16 +211,43 @@ std::string WgslAssignLocations(const std::string &shaderSource, } } - return WgslReplaceLocationMarkers(shaderSource, varNameToLocation); + const std::vector &samplerBindings = executable.getSamplerBindings(); + + // GLSL samplers are split into WGSL samplers/textures and need to be assigned consecutive + // locations, alternating between a sampler and its corresponding texture. + // The WGPU backend will read the same metadata and lay out its bind groups in the same + // alternating fashion. + for (uint32_t textureIndex = 0; textureIndex < samplerBindings.size(); ++textureIndex) + { + if (samplerBindings[textureIndex].textureUnitsCount != 1) + { + // TODO(anglebug.com/389145696): implement sampler arrays. + UNIMPLEMENTED(); + continue; + } + // Get the name of the sampler variable from the uniform metadata. + uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(textureIndex); + const std::string &uniformName = executable.getUniformNames()[uniformIndex]; + std::string mappedSamplerName = sh::WGSLGetMappedSamplerName(uniformName); + + varNameToLocation[std::string(sh::kAngleSamplerPrefix) + mappedSamplerName] = + textureIndex * 2; + varNameToLocation[std::string(sh::kAngleTexturePrefix) + mappedSamplerName] = + textureIndex * 2 + 1; + } + + return WgslReplaceMarkers(shaderSource, varNameToLocation); } -template std::string WgslAssignLocations( +template std::string WgslAssignLocationsAndSamplerBindings( + const gl::ProgramExecutable &executable, const std::string &shaderSource, const std::vector shaderVars, const gl::ProgramMergedVaryings &mergedVaryings, gl::ShaderType shaderType); -template std::string WgslAssignLocations( +template std::string WgslAssignLocationsAndSamplerBindings( + const gl::ProgramExecutable &executable, const std::string &shaderSource, const std::vector shaderVars, const gl::ProgramMergedVaryings &mergedVaryings, diff --git a/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.h b/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.h index 37d56765ca0..9002ecf20c7 100644 --- a/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.h +++ b/src/libANGLE/renderer/wgpu/wgpu_wgsl_util.h @@ -21,11 +21,17 @@ namespace webgpu // `shaderVars` which is a vector of either gl::ProgramInputs or gl::ProgramOutputs, and for // `mergedVaryings` which get assigned sequentially increasing locations. There should be at most // vertex and fragment shader stages or this function will not assign locations correctly. +// +// Also assigns sampler bindings, which are split into two separate sampler/texture +// variables in WGSL and are assigned binding numbers as such: +// @binding(n*2) for the WGSL sampler variable corresponding to the n-th GLSL sampler +// @binding(n*2+1) for the WGSL texture variable corresponding to the n-th GLSL sampler. template -std::string WgslAssignLocations(const std::string &shaderSource, - const std::vector shaderVars, - const gl::ProgramMergedVaryings &mergedVaryings, - gl::ShaderType shaderType); +std::string WgslAssignLocationsAndSamplerBindings(const gl::ProgramExecutable &executable, + const std::string &shaderSource, + const std::vector shaderVars, + const gl::ProgramMergedVaryings &mergedVaryings, + gl::ShaderType shaderType); } // namespace webgpu } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.cpp b/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.cpp index 017055c14d1..d817bc99893 100644 --- a/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.cpp +++ b/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.cpp @@ -21,32 +21,23 @@ WindowSurfaceWgpuWin32::WindowSurfaceWgpuWin32(const egl::SurfaceState &surfaceS {} angle::Result WindowSurfaceWgpuWin32::createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) + webgpu::SurfaceHandle *outSurface) { DisplayWgpu *displayWgpu = webgpu::GetImpl(display); - auto &surfaceCache = displayWgpu->getSurfaceCache(); + const DawnProcTable *wgpu = displayWgpu->getProcs(); + webgpu::InstanceHandle instance = displayWgpu->getInstance(); - EGLNativeWindowType window = getNativeWindow(); - auto cachedSurfaceIter = surfaceCache.find(window); - if (cachedSurfaceIter != surfaceCache.end()) - { - *outSurface = cachedSurfaceIter->second; - return angle::Result::Continue; - } - - wgpu::Instance instance = displayWgpu->getInstance(); - - wgpu::SurfaceDescriptorFromWindowsHWND hwndDesc; - hwndDesc.hinstance = GetModuleHandle(nullptr); - hwndDesc.hwnd = window; + WGPUSurfaceSourceWindowsHWND hwndDesc = WGPU_SURFACE_SOURCE_WINDOWS_HWND_INIT; + hwndDesc.hinstance = GetModuleHandle(nullptr); + hwndDesc.hwnd = getNativeWindow(); - wgpu::SurfaceDescriptor surfaceDesc; - surfaceDesc.nextInChain = &hwndDesc; + WGPUSurfaceDescriptor surfaceDesc = WGPU_SURFACE_DESCRIPTOR_INIT; + surfaceDesc.nextInChain = &hwndDesc.chain; - wgpu::Surface surface = instance.CreateSurface(&surfaceDesc); + webgpu::SurfaceHandle surface = webgpu::SurfaceHandle::Acquire( + wgpu, wgpu->instanceCreateSurface(instance.get(), &surfaceDesc)); *outSurface = surface; - surfaceCache.insert_or_assign(window, surface); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.h b/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.h index ff95e52a103..f4656e6ff61 100644 --- a/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.h +++ b/src/libANGLE/renderer/wgpu/win32/WindowSurfaceWgpuWin32.h @@ -21,7 +21,7 @@ class WindowSurfaceWgpuWin32 : public WindowSurfaceWgpu private: angle::Result createWgpuSurface(const egl::Display *display, - wgpu::Surface *outSurface) override; + webgpu::SurfaceHandle *outSurface) override; angle::Result getCurrentWindowSize(const egl::Display *display, gl::Extents *outSize) override; }; diff --git a/src/libANGLE/trace.h b/src/libANGLE/trace.h index 18d66769aea..f827eb55a85 100644 --- a/src/libANGLE/trace.h +++ b/src/libANGLE/trace.h @@ -12,18 +12,29 @@ #include #include "common/base/anglebase/trace_event/trace_event.h" +#if defined(ANGLE_ENABLE_PLATFORM_TRACE_EVENTS) + // TODO: Pass platform directly to these methods. http://anglebug.com/42260698 -#define ANGLE_TRACE_EVENT_BEGIN(CATEGORY, EVENT, ...) \ - TRACE_EVENT_BEGIN(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) +# define ANGLE_TRACE_EVENT_BEGIN(CATEGORY, EVENT, ...) \ + TRACE_EVENT_BEGIN(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) + +# define ANGLE_TRACE_EVENT_END(CATEGORY, EVENT, ...) \ + TRACE_EVENT_END(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) + +# define ANGLE_TRACE_EVENT_INSTANT(CATEGORY, EVENT, ...) \ + TRACE_EVENT_INSTANT(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) + +# define ANGLE_TRACE_EVENT(CATEGORY, EVENT, ...) \ + TRACE_EVENT(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) -#define ANGLE_TRACE_EVENT_END(CATEGORY, EVENT, ...) \ - TRACE_EVENT_END(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) +#else // !defined(ANGLE_ENABLE_PLATFORM_TRACE_EVENTS) -#define ANGLE_TRACE_EVENT_INSTANT(CATEGORY, EVENT, ...) \ - TRACE_EVENT_INSTANT(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) +# define ANGLE_TRACE_EVENT_BEGIN(CATEGORY, EVENT, ...) ((void)0) +# define ANGLE_TRACE_EVENT_END(CATEGORY, EVENT, ...) ((void)0) +# define ANGLE_TRACE_EVENT_INSTANT(CATEGORY, EVENT, ...) ((void)0) +# define ANGLE_TRACE_EVENT(CATEGORY, EVENT, ...) ((void)0) -#define ANGLE_TRACE_EVENT(CATEGORY, EVENT, ...) \ - TRACE_EVENT(ANGLEPlatformCurrent(), CATEGORY, EVENT, ##__VA_ARGS__) +#endif // defined(ANGLE_ENABLE_PLATFORM_TRACE_EVENTS) // Deprecated, use ANGLE_TRACE_EVENT_BEGIN #define ANGLE_TRACE_EVENT_BEGIN0(CATEGORY, EVENT) ANGLE_TRACE_EVENT_BEGIN(CATEGORY, EVENT) diff --git a/src/libANGLE/validationCL.cpp b/src/libANGLE/validationCL.cpp index c4909b0b6dd..2b795de0995 100644 --- a/src/libANGLE/validationCL.cpp +++ b/src/libANGLE/validationCL.cpp @@ -6,6 +6,11 @@ // validationCL.cpp: Validation functions for generic CL entry point parameters // based on the OpenCL Specification V3.0.7, see https://www.khronos.org/registry/OpenCL/ // Each used CL error code is preceeded by a citation of the relevant rule in the spec. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/cl_utils.h" #include "libANGLE/validationCL_autogen.h" @@ -162,18 +167,158 @@ bool ValidateMapFlags(MapFlags flags, const Platform &platform) return true; } -bool ValidateMemoryProperties(const cl_mem_properties *properties) +cl_int ValidateMemoryProperties(cl_context context, + MemFlags flags, + const cl_mem_properties *properties, + const void *host_ptr) { - if (properties != nullptr) + // first, get/validate supported properties + const NameValueProperty *startOfProperties = + reinterpret_cast(properties); + const NameValueProperty *propertiesIterator = startOfProperties; + while (propertiesIterator->name != 0) { - // OpenCL 3.0 does not define any optional properties. - // This function is reserved for extensions and future use. - if (*properties != 0) + switch (propertiesIterator->name) { - return false; + case CL_MEM_DEVICE_HANDLE_LIST_KHR: + case CL_MEM_DEVICE_HANDLE_LIST_END_KHR: + case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR: + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR: + break; + default: + // CL_INVALID_PROPERTY if a property name in properties is not a supported property + // name + return CL_INVALID_PROPERTY; } + propertiesIterator++; } - return true; + + // next, get/validate the memory type/handle from properties (that we support) + const NameValueProperty *pMemoryHandle = nullptr; + propertiesIterator = startOfProperties; + while (propertiesIterator->name != 0) + { + switch (propertiesIterator->name) + { + case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR: + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR: + if (pMemoryHandle) + { + // CL_INVALID_PROPERTY if properties includes more than one external memory + // handle + return CL_INVALID_PROPERTY; + } + pMemoryHandle = propertiesIterator; + break; + default: + break; + } + propertiesIterator++; + } + if (!pMemoryHandle) + { + // CL_INVALID_PROPERTY if properties does not include a supported external memory handle + return CL_INVALID_PROPERTY; + } + else + { + switch (pMemoryHandle->name) + { + case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR: + case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR: + { + // just validate the basics for dma_buf and posix fd for now + uint32_t fdDmaBuf = *reinterpret_cast(pMemoryHandle->value); + if (host_ptr != nullptr) + { + // CL_INVALID_HOST_PTR if properties includes a supported external memory handle + // and host_ptr is not NULL + return CL_INVALID_HOST_PTR; + } + if (fdDmaBuf < 0) + { + return CL_INVALID_PROPERTY; + } + break; + } + default: + { + ASSERT(false); // should not reach here + return CL_INVALID_PROPERTY; + } + } + } + + // next, get/validate the device sub-list from properties + std::vector devices; + bool isDeviceListDefined = false; + cl::Context &ctx = context->cast(); + propertiesIterator = startOfProperties; + while (propertiesIterator->name != 0) + { + if (propertiesIterator->name == CL_MEM_DEVICE_HANDLE_LIST_KHR) + { + if (isDeviceListDefined) + { + // CL_INVALID_PROPERTY if the same property name is specified more than once + return CL_INVALID_PROPERTY; + } + isDeviceListDefined = true; + cl_device_id device = reinterpret_cast(propertiesIterator->value); + while (device != CL_MEM_DEVICE_HANDLE_LIST_END_KHR) + { + if (!Device::IsValid(device) || !ctx.hasDevice(device)) + { + // CL_INVALID_DEVICE if a device identified by the property + // CL_MEM_DEVICE_HANDLE_LIST_KHR is not a valid device or is not associated + // with context + return CL_INVALID_DEVICE; + } + devices.push_back(&device->cast()); + device++; + } + } + propertiesIterator++; + } + if (!devices.empty()) + { + for (const auto &device : devices) + { + if (!device->getInfo().externalMemoryHandleSupport.test( + FromCLenum(static_cast(pMemoryHandle->name)))) + { + // CL_INVALID_DEVICE if a device identified by property + // CL_MEM_DEVICE_HANDLE_LIST_KHR cannot import the requested external memory object + // type + return CL_INVALID_DEVICE; + } + } + } + else + { + // there was no device list defined in properties, use associated devices with context + for (const auto &devicePtr : ctx.getDevices()) + { + if (!devicePtr->getInfo().externalMemoryHandleSupport.test( + FromCLenum(static_cast(pMemoryHandle->name)))) + { + // if CL_MEM_DEVICE_HANDLE_LIST_KHR is not specified as part of properties and one + // or more devices in context cannot import the requested external memory object + // type + return CL_INVALID_DEVICE; + } + } + } + + // When a buffer or image is created from an external memory handle, + // the flags used to specify usage information for the buffer or image must not include + // CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR, or CL_MEM_COPY_HOST_PTR + if (flags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR)) + { + return CL_INVALID_VALUE; + } + + return CL_SUCCESS; } cl_int ValidateCommandQueueAndEventWaitList(cl_command_queue commandQueue, @@ -447,8 +592,8 @@ cl_int ValidateImageForDevice(const Image &image, // CL_INVALID_VALUE if the region being read or written // specified by origin and region is out of bounds. - if (!image.isRegionValid(cl::MemOffsets{origin[0], origin[1], origin[2]}, - cl::Coordinate{region[0], region[1], region[2]})) + if (!image.isRegionValid(cl::Offset{origin[0], origin[1], origin[2]}, + cl::Extents{region[0], region[1], region[2]})) { return CL_INVALID_VALUE; } @@ -559,6 +704,9 @@ cl_int ValidateGetPlatformInfo(cl_platform_id platform, break; } + // TODO: we need to validate cl_khr_external_memory enum queries here as well + // http://anglebug.com/439565645 + return CL_SUCCESS; } @@ -689,6 +837,12 @@ cl_int ValidateGetDeviceInfo(cl_device_id device, ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, 1, 2, info.khrFP64); break; + case DeviceInfo::IntegerDotProductCapabilities: + case DeviceInfo::IntegerDotProductAccelerationProperties8bit: + case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked: + ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, 3, 0, info.khrIntegerDotProduct); + break; + case DeviceInfo::InvalidEnum: return CL_INVALID_VALUE; default: @@ -696,6 +850,9 @@ cl_int ValidateGetDeviceInfo(cl_device_id device, break; } + // TODO: we need to validate cl_khr_external_memory enum queries here as well + // http://anglebug.com/439565645 + return CL_SUCCESS; } @@ -3636,8 +3793,9 @@ cl_int ValidateCreateCommandQueueWithProperties(cl_context context, // CL_INVALID_VALUE if values specified in properties are not valid. if (properties != nullptr) { - bool isQueueOnDevice = false; - bool hasQueueSize = false; + bool isQueueOnDevice = false; + bool hasQueueSize = false; + bool hasQueuePriority = false; while (*properties != 0) { switch (*properties++) @@ -3672,6 +3830,18 @@ cl_int ValidateCreateCommandQueueWithProperties(cl_context context, hasQueueSize = true; break; } + case CL_QUEUE_PRIORITY_KHR: + { + if (*properties != CL_QUEUE_PRIORITY_HIGH_KHR && + *properties != CL_QUEUE_PRIORITY_MED_KHR && + *properties != CL_QUEUE_PRIORITY_LOW_KHR) + { + return CL_INVALID_VALUE; + } + hasQueuePriority = true; + properties++; + break; + } default: return CL_INVALID_VALUE; } @@ -3682,6 +3852,14 @@ cl_int ValidateCreateCommandQueueWithProperties(cl_context context, { return CL_INVALID_VALUE; } + + // CL_INVALID_QUEUE_PROPERTIES if the cl_khr_priority_hints extension is supported, the + // CL_QUEUE_PRIORITY_KHR property is specified, and the queue is a CL_QUEUE_ON_DEVICE. + if (device->cast().getInfo().khrPriorityHints && hasQueuePriority && + isQueueOnDevice) + { + return CL_INVALID_QUEUE_PROPERTIES; + } } return CL_SUCCESS; @@ -3969,9 +4147,9 @@ cl_int ValidateCreateBufferWithProperties(cl_context context, // CL_INVALID_PROPERTY if a property name in properties is not a supported property name, // if the value specified for a supported property name is not valid, // or if the same property name is specified more than once. - if (!ValidateMemoryProperties(properties)) + if ((properties != nullptr) && (properties[0] != 0)) { - return CL_INVALID_PROPERTY; + return ValidateMemoryProperties(context, flags, properties, host_ptr); } return CL_SUCCESS; @@ -3995,14 +4173,175 @@ cl_int ValidateCreateImageWithProperties(cl_context context, // CL_INVALID_PROPERTY if a property name in properties is not a supported property name, // if the value specified for a supported property name is not valid, // or if the same property name is specified more than once. - if (!ValidateMemoryProperties(properties)) + if ((properties != nullptr) && (properties[0] != 0)) { - return CL_INVALID_PROPERTY; + return ValidateMemoryProperties(context, flags, properties, host_ptr); } return CL_SUCCESS; } +// cl_khr_external_memory +cl_int ValidateExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list) +{ + // CL_INVALID_VALUE if num_mem_objects is zero and mem_objects is not a NULL value, + // or if num_mem_objects is greater than 0 and mem_objects is NULL. + if ((num_mem_objects == 0u && mem_objects != nullptr) || + (num_mem_objects > 0u && mem_objects == nullptr)) + { + return CL_INVALID_VALUE; + } + + for (cl_uint i = 0u; i < num_mem_objects; ++i) + { + // CL_INVALID_MEM_OBJECT if any of the memory objects + // in mem_objects is not a valid memory object. + if (!Memory::IsValid(mem_objects[i])) + { + return CL_INVALID_MEM_OBJECT; + } + } + + // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue + ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false, + num_events_in_wait_list, event_wait_list)); + if (!command_queue->cast().getContext().getPlatform().isVersionOrNewer(3u, 0u)) + { + return CL_INVALID_COMMAND_QUEUE; + } + + // CL_INVALID_COMMAND_QUEUE if device associated with command_queue is not one of the devices + // specified by CL_MEM_DEVICE_HANDLE_LIST_KHR at the time of creating one or more of + // mem_objects, + const CommandQueue &queue = command_queue->cast(); + const cl_device_id devFromQueue = const_cast(queue.getDevice().getNative()); + bool isCmdQueueDevAssociatedWithMemObj = false; + bool isDevHandleMentionedInProp = false; + for (cl_uint i = 0u; i < num_mem_objects; ++i) + { + const cl_mem_properties *properties = mem_objects[i]->cast().getProperties().data(); + const NameValueProperty *propertiesIterator = + reinterpret_cast(properties); + // Process all NameValueProperty, [name, value] in properties + while (propertiesIterator->name != 0) + { + if (propertiesIterator->name == CL_MEM_DEVICE_HANDLE_LIST_KHR) + { + isDevHandleMentionedInProp = true; + cl_device_id devFromProp = + reinterpret_cast(propertiesIterator->value); + if (devFromProp == devFromQueue) + { + isCmdQueueDevAssociatedWithMemObj = true; + break; + } + } + propertiesIterator++; + } + + if (isDevHandleMentionedInProp && !isCmdQueueDevAssociatedWithMemObj) + { + return CL_INVALID_COMMAND_QUEUE; + } + } + + // CL_INVALID_COMMAND_QUEUE if one or more of mem_objects belong to a context + // that does not contain a device associated with command_queue + for (cl_uint i = 0u; i < num_mem_objects; ++i) + { + const Context &ctx = mem_objects[i]->cast().getContext(); + if (!ctx.hasDevice(devFromQueue)) + { + return CL_INVALID_COMMAND_QUEUE; + } + } + + return CL_SUCCESS; +} + +// cl_arm_import_memory +cl_int ValidateImportMemoryARM(cl_context context, + MemFlags flags, + const cl_import_properties_arm *properties, + const void *memory, + size_t size) +{ + // CL_INVALID_VALUE if memory is NULL. + if (memory == nullptr) + { + return CL_INVALID_VALUE; + } + + // CL_INVALID_PROPERTY when invalid properties or combination of properties are passed. + const NameValueProperty *propertiesIterator = + reinterpret_cast(properties); + bool foundImportType = false; + if (propertiesIterator != nullptr) + { + for (; propertiesIterator->name != 0; ++propertiesIterator) + { + if (propertiesIterator->name == CL_IMPORT_TYPE_ARM) + { + foundImportType = true; + if (propertiesIterator->value != CL_IMPORT_TYPE_HOST_ARM && + propertiesIterator->value != CL_IMPORT_TYPE_DMA_BUF_ARM && + propertiesIterator->value != CL_IMPORT_TYPE_ANDROID_HARDWARE_BUFFER_ARM) + { + return CL_INVALID_PROPERTY; + } + } + else if (propertiesIterator->name == CL_IMPORT_TYPE_PROTECTED_ARM) + { + if (propertiesIterator->value == CL_TRUE) + { + // we can allow non-protected memory, throw error otherwise + // (until cl_khr_external_memory can support this in some way) + WARN() + << "CL_IMPORT_TYPE_PROTECTED_ARM not supported since cl_arm_import_memory " + "is layered on cl_khr_external_memory (currently no equivalent)"; + return CL_INVALID_OPERATION; + } + } + } + if (!foundImportType) + { + return CL_INVALID_PROPERTY; + } + } + + // Redirect to ValidateCreateBufferWithProperties as it is implemented on top of + // cl_khr_external_memory + Memory::PropArray convertedProperties = Context::ConvertArmMemPropToMemProp(properties, memory); + return ValidateCreateBufferWithProperties(context, convertedProperties.data(), flags, size, + nullptr); +} + +cl_int ValidateEnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + const cl_event *event) +{ + return ValidateExternalMemObjectsKHR(command_queue, num_mem_objects, mem_objects, + num_events_in_wait_list, event_wait_list); +} + +cl_int ValidateEnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + const cl_event *event) +{ + return ValidateExternalMemObjectsKHR(command_queue, num_mem_objects, mem_objects, + num_events_in_wait_list, event_wait_list); +} + // cl_khr_icd cl_int ValidateIcdGetPlatformIDsKHR(cl_uint num_entries, const cl_platform_id *platforms, @@ -4016,4 +4355,14 @@ cl_int ValidateIcdGetPlatformIDsKHR(cl_uint num_entries, return CL_SUCCESS; } +cl_int ValidateIcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, const char *func_name) +{ + return CL_SUCCESS; +} + +cl_int ValidateIcdSetPlatformDispatchDataKHR(cl_platform_id platform, const void *dispatch_data) +{ + return CL_SUCCESS; +} + } // namespace cl diff --git a/src/libANGLE/validationCL_autogen.h b/src/libANGLE/validationCL_autogen.h index c53eba58fec..88f1e385035 100644 --- a/src/libANGLE/validationCL_autogen.h +++ b/src/libANGLE/validationCL_autogen.h @@ -576,10 +576,33 @@ cl_int ValidateCreateImageWithProperties(cl_context context, const cl_image_desc *image_desc, const void *host_ptr); +// cl_arm_import_memory +cl_int ValidateImportMemoryARM(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + const void *memory, + size_t size); + +// cl_khr_external_memory +cl_int ValidateEnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + const cl_event *event); +cl_int ValidateEnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + const cl_event *event); + // cl_khr_icd cl_int ValidateIcdGetPlatformIDsKHR(cl_uint num_entries, const cl_platform_id *platforms, const cl_uint *num_platforms); +cl_int ValidateIcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, const char *func_name); +cl_int ValidateIcdSetPlatformDispatchDataKHR(cl_platform_id platform, const void *dispatch_data); } // namespace cl #endif // LIBANGLE_VALIDATION_CL_AUTOGEN_H_ diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp index 447fb21e24a..b62b55995fb 100644 --- a/src/libANGLE/validationEGL.cpp +++ b/src/libANGLE/validationEGL.cpp @@ -6,6 +6,10 @@ // validationEGL.cpp: Validation functions for generic EGL entry point parameters +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/validationEGL_autogen.h" #include "common/utilities.h" @@ -677,7 +681,7 @@ bool ValidateGetPlatformDisplayCommon(const ValidationContext *val, } break; default: - val->setError(EGL_BAD_CONFIG, "Bad platform type."); + val->setError(EGL_BAD_PARAMETER, "Bad platform type."); return false; } @@ -697,6 +701,9 @@ bool ValidateGetPlatformDisplayCommon(const ValidationContext *val, Optional minorVersion; Optional deviceType; Optional eglHandle; + Optional dawnProcTable; + Optional webgpuInstance; + Optional webgpuDevice; for (const auto &curAttrib : attribMap) { @@ -889,6 +896,49 @@ bool ValidateGetPlatformDisplayCommon(const ValidationContext *val, } deviceIdSpecified = true; break; + + case EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE: + if (!clientExtensions.platformANGLEWebgpu) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_ANGLE_platform_angle_webgpu is not supported"); + return false; + } + + if (value != 0) + { + dawnProcTable = value; + } + break; + + case EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE: + if (!clientExtensions.platformANGLEWebgpu) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_ANGLE_platform_angle_webgpu is not supported"); + return false; + } + + if (value != 0) + { + webgpuInstance = value; + } + break; + + case EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE: + if (!clientExtensions.platformANGLEWebgpu) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_ANGLE_platform_angle_webgpu is not supported"); + return false; + } + + if (value != 0) + { + webgpuDevice = value; + } + break; + default: break; } @@ -1051,6 +1101,30 @@ bool ValidateGetPlatformDisplayCommon(const ValidationContext *val, "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE."); return false; } + + if (dawnProcTable.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_PLATFORM_ANGLE_DAWN_PROC_TABLE_ANGLE requires a " + "platform type of EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE."); + return false; + } + + if (webgpuInstance.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_PLATFORM_ANGLE_WEBGPU_INSTANCE_ANGLE requires a " + "platform type of EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE."); + return false; + } + + if (webgpuDevice.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_PLATFORM_ANGLE_WEBGPU_DEVICE_ANGLE requires a " + "platform type of EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE."); + return false; + } } else { @@ -1300,7 +1374,7 @@ bool ValidateCompatibleSurface(const ValidationContext *val, const Config *surfaceConfig = surface->getConfig(); // Surface compatible with client API - only OPENGL_ES supported - switch (context->getClientMajorVersion()) + switch (context->getClientVersion().getMajor()) { case 1: if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT)) @@ -1600,6 +1674,32 @@ bool ValidateCreateSyncBase(const ValidationContext *val, } break; + case EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE: + if (!attribs.isEmpty()) + { + val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute"); + return false; + } + if (!display->getExtensions().fenceSync) + { + val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available"); + return false; + } + if (!display->getExtensions().mtlSyncCommandsScheduledANGLE) + { + val->setError(EGL_BAD_DISPLAY, + "EGL_ANGLE_metal_shared_event_sync is not available"); + return false; + } + if (display != currentDisplay) + { + val->setError(EGL_BAD_MATCH, + "CreateSync can only be called on the current display"); + return false; + } + ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext->id())); + break; + default: if (isExt) { @@ -1634,6 +1734,7 @@ bool ValidateGetSyncAttribBase(const ValidationContext *val, case EGL_SYNC_NATIVE_FENCE_ANDROID: case EGL_SYNC_GLOBAL_FENCE_ANGLE: case EGL_SYNC_METAL_SHARED_EVENT_ANGLE: + case EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE: break; default: @@ -1755,6 +1856,17 @@ bool ValidateCreateContextAttribute(const ValidationContext *val, } break; + case EGL_CONTEXT_HARDENED_ANGLE: + if (!display->getExtensions().createContextWebGLCompatibility) + { + val->setError(EGL_BAD_ATTRIBUTE, + "Attribute " + "EGL_CONTEXT_HARDENED_ANGLE requires " + "EGL_ANGLE_create_context_webgl_compatibility."); + return false; + } + break; + case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM: if (!display->getExtensions().createContextBindGeneratesResource) { @@ -1907,6 +2019,15 @@ bool ValidateCreateContextAttribute(const ValidationContext *val, } break; + case EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE: + if (!display->getExtensions().createContextPassthroughShadersANGLE) + { + val->setError(EGL_BAD_ATTRIBUTE, + "Attribute EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE requires " + "EGL_ANGLE_create_context_passthrough_shaders."); + } + break; + default: val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute); return false; @@ -1986,6 +2107,16 @@ bool ValidateCreateContextAttributeValue(const ValidationContext *val, } break; + case EGL_CONTEXT_HARDENED_ANGLE: + if (value != EGL_TRUE && value != EGL_FALSE) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_CONTEXT_HARDENED_ANGLE must be " + "EGL_TRUE or EGL_FALSE."); + return false; + } + break; + case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM: if (value != EGL_TRUE && value != EGL_FALSE) { @@ -2101,12 +2232,22 @@ bool ValidateCreateContextAttributeValue(const ValidationContext *val, case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: case EGL_CONTEXT_PRIORITY_HIGH_IMG: break; + case EGL_CONTEXT_PRIORITY_REALTIME_NV: + if (!display->getExtensions().contextPriorityRealtimeNV) + { + val->setError(EGL_BAD_ATTRIBUTE, + "Attribute EGL_CONTEXT_PRIORITY_REALTIME_NV requires " + "extension EGL_NV_context_priority_realtime."); + return false; + } + break; default: val->setError(EGL_BAD_ATTRIBUTE, "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG " "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, " - "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or " - "EGL_CONTEXT_PRIORITY_HIGH_IMG."); + "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, " + "EGL_CONTEXT_PRIORITY_HIGH_IMG, or " + "EGL_CONTEXT_PRIORITY_REALTIME_NV."); return false; } break; @@ -2158,6 +2299,16 @@ bool ValidateCreateContextAttributeValue(const ValidationContext *val, } break; + case EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE: + if (value != EGL_TRUE && value != EGL_FALSE) + { + val->setError(EGL_BAD_ATTRIBUTE, + "EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE must " + "be either EGL_TRUE or EGL_FALSE."); + return false; + } + break; + default: UNREACHABLE(); return false; @@ -2579,16 +2730,6 @@ bool ValidateCreateWindowSurfaceAttributes(const ValidationContext *val, } break; - case EGL_GGP_STREAM_DESCRIPTOR_ANGLE: - if (!display->getExtensions().ggpStreamDescriptor) - { - val->setError(EGL_BAD_ATTRIBUTE, - "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires " - "EGL_ANGLE_ggp_stream_descriptor."); - return false; - } - break; - case EGL_PROTECTED_CONTENT_EXT: if (!displayExtensions.protectedContentEXT) { @@ -2822,7 +2963,7 @@ bool ValidateCreateContext(const ValidationContext *val, case 1: if (clientMinorVersion != 0 && clientMinorVersion != 1) { - val->setError(EGL_BAD_ATTRIBUTE); + val->setError(EGL_BAD_MATCH); return false; } if (configuration == EGL_NO_CONFIG_KHR) @@ -2841,7 +2982,7 @@ bool ValidateCreateContext(const ValidationContext *val, case 2: if (clientMinorVersion != 0) { - val->setError(EGL_BAD_ATTRIBUTE); + val->setError(EGL_BAD_MATCH); return false; } if ((configuration != EGL_NO_CONFIG_KHR) && @@ -2854,7 +2995,7 @@ bool ValidateCreateContext(const ValidationContext *val, case 3: if (clientMinorVersion < 0 || clientMinorVersion > 2) { - val->setError(EGL_BAD_ATTRIBUTE); + val->setError(EGL_BAD_MATCH); return false; } if ((configuration != EGL_NO_CONFIG_KHR) && @@ -2864,22 +3005,23 @@ bool ValidateCreateContext(const ValidationContext *val, return false; } if (display->getMaxSupportedESVersion() < - gl::Version(static_cast(clientMajorVersion), - static_cast(clientMinorVersion))) + gl::Version(static_cast(clientMajorVersion), + static_cast(clientMinorVersion))) { gl::Version max = display->getMaxSupportedESVersion(); - val->setError(EGL_BAD_ATTRIBUTE, + val->setError(EGL_BAD_MATCH, "Requested GLES version (%" PRIxPTR ".%" PRIxPTR ") is greater than " - "max supported (%d, %d).", - clientMajorVersion, clientMinorVersion, max.major, max.minor); + "max supported (%d.%d).", + clientMajorVersion, clientMinorVersion, max.getMajor(), + max.getMinor()); return false; } if ((attributes.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE) && (clientMinorVersion > 1)) { - val->setError(EGL_BAD_ATTRIBUTE, + val->setError(EGL_BAD_MATCH, "Requested GLES version (%" PRIxPTR ".%" PRIxPTR ") is greater than " "max supported 3.1 for WebGL.", @@ -2888,7 +3030,7 @@ bool ValidateCreateContext(const ValidationContext *val, } break; default: - val->setError(EGL_BAD_ATTRIBUTE); + val->setError(EGL_BAD_MATCH); return false; } break; @@ -3038,6 +3180,19 @@ bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val, } break; + case EGL_WEBGPU_TEXTURE_ANGLE: + if (!displayExtensions.webgpuTextureClientBuffer) + { + val->setError(EGL_BAD_PARAMETER); + return false; + } + if (buffer == nullptr) + { + val->setError(EGL_BAD_PARAMETER); + return false; + } + break; + case EGL_IOSURFACE_ANGLE: if (!displayExtensions.iosurfaceClientBuffer) { @@ -3152,7 +3307,8 @@ bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val, break; case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE: - if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE) + if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE && + buftype != EGL_WEBGPU_TEXTURE_ANGLE) { val->setError(EGL_BAD_ATTRIBUTE, " doesn't support texture internal format"); @@ -3607,12 +3763,14 @@ bool ValidateCreateImage(const ValidationContext *val, case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE: if (!displayExtensions.imageD3D11Texture && !displayExtensions.vulkanImageANGLE && - !displayExtensions.mtlTextureClientBuffer) + !displayExtensions.mtlTextureClientBuffer && + !displayExtensions.webgpuTextureClientBuffer) { val->setError(EGL_BAD_PARAMETER, "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE cannot be used without " - "EGL_ANGLE_image_d3d11_texture, EGL_ANGLE_vulkan_image, or " - "EGL_ANGLE_metal_texture_client_buffer support."); + "EGL_ANGLE_image_d3d11_texture, EGL_ANGLE_vulkan_image, " + "EGL_ANGLE_metal_texture_client_buffer, or " + "EGL_ANGLE_webgpu_texture_client_buffer support."); return false; } break; @@ -3859,6 +4017,13 @@ bool ValidateCreateImage(const ValidationContext *val, return false; } + if (texture->isEGLImageTarget()) + { + val->setError(EGL_BAD_ACCESS, + "The texture has been a target of an existing EGL image."); + return false; + } + ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level)); } break; @@ -3940,6 +4105,13 @@ bool ValidateCreateImage(const ValidationContext *val, "The texture has been bound to an existing EGL image."); return false; } + + if (texture->isEGLImageTarget()) + { + val->setError(EGL_BAD_ACCESS, + "The texture has been a target of an existing EGL image."); + return false; + } } break; @@ -4011,6 +4183,13 @@ bool ValidateCreateImage(const ValidationContext *val, return false; } + if (texture->isEGLImageTarget()) + { + val->setError(EGL_BAD_ACCESS, + "The texture has been a target of an existing EGL image."); + return false; + } + ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level)); } break; @@ -4069,6 +4248,13 @@ bool ValidateCreateImage(const ValidationContext *val, "The renderbuffer has been bound to an existing EGL image."); return false; } + + if (renderbuffer->isEGLImageTarget()) + { + val->setError(EGL_BAD_ACCESS, + "The renderbuffer has been a target of an existing EGL image."); + return false; + } } break; @@ -4112,6 +4298,26 @@ bool ValidateCreateImage(const ValidationContext *val, val->entryPoint, val->labeledObject, false); break; + case EGL_WEBGPU_TEXTURE_ANGLE: + if (!displayExtensions.webgpuTextureClientBuffer) + { + val->setError(EGL_BAD_PARAMETER, + "EGL_ANGLE_webgpu_texture_client_buffer not supported."); + return false; + } + + if (context != nullptr) + { + val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT."); + return false; + } + + ANGLE_EGL_TRY_RETURN( + val->eglThread, + display->validateImageClientBuffer(context, target, buffer, attributes), + val->entryPoint, val->labeledObject, false); + break; + case EGL_LINUX_DMA_BUF_EXT: if (!displayExtensions.imageDmaBufImportEXT) { @@ -6494,24 +6700,6 @@ bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val, return true; } -bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val, - const Display *display, - SurfaceID surfaceID, - EGLFrameTokenANGLE frametoken) -{ - ANGLE_VALIDATION_TRY(ValidateDisplay(val, display)); - - if (!display->getExtensions().swapWithFrameToken) - { - val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_swap_buffers_with_frame_token is not available."); - return false; - } - - ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surfaceID)); - - return true; -} - bool ValidatePrepareSwapBuffersANGLE(const ValidationContext *val, const Display *display, SurfaceID surfaceID) @@ -6662,6 +6850,14 @@ bool ValidateQueryDeviceAttribEXT(const ValidationContext *val, return false; } break; + case EGL_WEBGPU_DEVICE_ANGLE: + case EGL_WEBGPU_ADAPTER_ANGLE: + if (!device->getExtensions().deviceWebGPU) + { + val->setError(EGL_BAD_ATTRIBUTE); + return false; + } + break; case EGL_VULKAN_VERSION_ANGLE: case EGL_VULKAN_INSTANCE_ANGLE: case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE: diff --git a/src/libANGLE/validationEGL_autogen.h b/src/libANGLE/validationEGL_autogen.h index a3c83031a11..abdca6ce255 100644 --- a/src/libANGLE/validationEGL_autogen.h +++ b/src/libANGLE/validationEGL_autogen.h @@ -319,12 +319,6 @@ bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val, const void *texture, const AttributeMap &attrib_listPacked); -// EGL_ANGLE_swap_with_frame_token -bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val, - const egl::Display *dpyPacked, - SurfaceID surfacePacked, - EGLFrameTokenANGLE frametoken); - // EGL_ANGLE_sync_control_rate bool ValidateGetMscRateANGLE(const ValidationContext *val, const egl::Display *dpyPacked, diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp index 5646832f705..1f3b77efa6d 100644 --- a/src/libANGLE/validationES.cpp +++ b/src/libANGLE/validationES.cpp @@ -4,7 +4,11 @@ // found in the LICENSE file. // -// validationES.h: Validation functions for generic OpenGL ES entry point parameters +// validationES.cpp: Validation functions for generic OpenGL ES entry point parameters + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/validationES.h" @@ -503,10 +507,10 @@ bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context) const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context); const Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); - return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().to_ulong(), - framebuffer->getDrawBufferTypeMask().to_ulong(), - executable->getActiveOutputVariablesMask().to_ulong(), - framebuffer->getDrawBufferMask().to_ulong()); + return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().bits(), + framebuffer->getDrawBufferTypeMask().bits(), + executable->getActiveOutputVariablesMask().bits(), + framebuffer->getDrawBufferMask().bits()); } bool ValidateVertexShaderAttributeTypeMatch(const Context *context) @@ -520,17 +524,16 @@ bool ValidateVertexShaderAttributeTypeMatch(const Context *context) return false; } - unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong(); - unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong(); - unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong(); + uint64_t stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().bits(); + uint64_t vaoAttribTypeBits = vao->getAttributesTypeMask().bits(); + uint64_t vaoAttribEnabledMask = vao->getAttributesMask().bits(); vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex; vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits); vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits); - return ValidateComponentTypeMasks(executable->getAttributesTypeMask().to_ulong(), - vaoAttribTypeBits, executable->getAttributesMask().to_ulong(), - 0xFFFF); + return ValidateComponentTypeMasks(executable->getAttributesTypeMask().bits(), vaoAttribTypeBits, + executable->getAttributesMask().bits(), 0xFFFF); } bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode, @@ -579,6 +582,28 @@ bool IsValidGLES1TextureParameter(GLenum pname) } } +bool IsBlitSameResource(const FramebufferAttachment *read, const FramebufferAttachment *draw) +{ + if (read->getResource() == draw->getResource()) + { + if (read->type() == GL_TEXTURE) + { + bool sameMipLevel = read->mipLevel() == draw->mipLevel(); + bool sameLayer = read->layer() == draw->layer(); + bool sameFace = read->cubeMapFace() == draw->cubeMapFace(); + if (sameMipLevel && sameLayer && sameFace) + { + return true; + } + } + else + { + return true; + } + } + return false; +} + unsigned int GetSamplerParameterCount(GLenum pname) { return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1; @@ -592,7 +617,7 @@ const char *ValidateProgramDrawAdvancedBlendState(const Context *context, const DrawBufferMask &enabledDrawBufferMask = state.getBlendStateExt().getEnabledMask(); // Zero (default) means everything is BlendEquationType::Add, so check can be skipped - if (state.getBlendStateExt().getEquationColorBits() != 0) + if (ANGLE_UNLIKELY(state.getBlendStateExt().getEquationColorBits() != 0)) { for (size_t blendEnabledBufferIndex : enabledDrawBufferMask) { @@ -627,10 +652,12 @@ ANGLE_INLINE GLenum ShPixelLocalStorageFormatToGLenum(ShPixelLocalStorageFormat return GL_RGBA8I; case ShPixelLocalStorageFormat::RGBA8UI: return GL_RGBA8UI; - case ShPixelLocalStorageFormat::R32UI: - return GL_R32UI; case ShPixelLocalStorageFormat::R32F: return GL_R32F; + case ShPixelLocalStorageFormat::R32I: + return GL_R32I; + case ShPixelLocalStorageFormat::R32UI: + return GL_R32UI; } UNREACHABLE(); return GL_NONE; @@ -641,55 +668,62 @@ ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context, const ProgramExecutable &executable) { const State &state = context->getState(); - if (extensions.multiviewOVR || extensions.multiview2OVR) + if (extensions.multiviewOVR) { const int programNumViews = executable.usesMultiview() ? executable.getNumViews() : 1; + const bool hasVertexShader = executable.hasLinkedShaderStage(ShaderType::Vertex); Framebuffer *framebuffer = state.getDrawFramebuffer(); const int framebufferNumViews = framebuffer->getNumViews(); - if (framebufferNumViews != programNumViews) + // num_views layout qualifiers are allowed only in vertex shaders. + if (hasVertexShader && ANGLE_UNLIKELY(framebufferNumViews != programNumViews)) { return gl::err::kMultiviewMismatch; } - if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1) + if (ANGLE_UNLIKELY(state.isTransformFeedbackActiveUnpaused()) && + ANGLE_UNLIKELY(framebufferNumViews > 1)) { return gl::err::kMultiviewTransformFeedback; } - if (extensions.disjointTimerQueryEXT && framebufferNumViews > 1 && - state.isQueryActive(QueryType::TimeElapsed)) + if (extensions.disjointTimerQueryEXT && ANGLE_UNLIKELY(framebufferNumViews > 1) && + ANGLE_UNLIKELY(state.isQueryActive(QueryType::TimeElapsed))) { return gl::err::kMultiviewTimerQuery; } } - // Uniform buffer validation - for (size_t uniformBlockIndex = 0; uniformBlockIndex < executable.getUniformBlocks().size(); - uniformBlockIndex++) + if (ANGLE_UNLIKELY(context->isWebGL() || context->isBufferAccessValidationEnabled())) { - const InterfaceBlock &uniformBlock = executable.getUniformBlockByIndex(uniformBlockIndex); - GLuint blockBinding = executable.getUniformBlockBinding(uniformBlockIndex); - const OffsetBindingPointer &uniformBuffer = - state.getIndexedUniformBuffer(blockBinding); - - if (uniformBuffer.get() == nullptr && context->isWebGL()) + // Uniform buffer validation + for (size_t uniformBlockIndex = 0; uniformBlockIndex < executable.getUniformBlocks().size(); + uniformBlockIndex++) { - // undefined behaviour - return gl::err::kUniformBufferUnbound; - } + const InterfaceBlock &uniformBlock = + executable.getUniformBlockByIndex(uniformBlockIndex); + GLuint blockBinding = executable.getUniformBlockBinding(uniformBlockIndex); + const OffsetBindingPointer &uniformBuffer = + state.getIndexedUniformBuffer(blockBinding); - size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer); - if (uniformBufferSize < uniformBlock.pod.dataSize && - (context->isWebGL() || context->isBufferAccessValidationEnabled())) - { - // undefined behaviour - return gl::err::kUniformBufferTooSmall; - } + if (uniformBuffer.get() == nullptr && context->isWebGL()) + { + // undefined behaviour + return gl::err::kUniformBufferUnbound; + } - if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) - { - return gl::err::kUniformBufferBoundForTransformFeedback; + size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer); + if (uniformBufferSize < uniformBlock.pod.dataSize && + (context->isWebGL() || context->isBufferAccessValidationEnabled())) + { + // undefined behaviour + return gl::err::kUniformBufferTooSmall; + } + + if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) + { + return gl::err::kUniformBufferBoundForTransformFeedback; + } } } @@ -701,14 +735,14 @@ ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context, const auto &shaderPLSFormats = executable.getPixelLocalStorageFormats(); size_t activePLSCount = context->getState().getPixelLocalStorageActivePlanes(); - if (shaderPLSFormats.size() > activePLSCount) + if (ANGLE_UNLIKELY(shaderPLSFormats.size() > activePLSCount)) { // INVALID_OPERATION is generated if a draw is issued with a fragment shader that has a // pixel local uniform bound to an inactive pixel local storage plane. return gl::err::kPLSDrawProgramPlanesInactive; } - if (shaderPLSFormats.size() < activePLSCount) + if (ANGLE_UNLIKELY(shaderPLSFormats.size() < activePLSCount)) { // INVALID_OPERATION is generated if a draw is issued with a fragment shader that does // _not_ have a pixel local uniform bound to an _active_ pixel local storage plane @@ -721,7 +755,7 @@ ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context, { const auto &plsPlane = pls->getPlane(static_cast(i)); ASSERT(plsPlane.isActive()); - if (shaderPLSFormats[i] == ShPixelLocalStorageFormat::NotPLS) + if (ANGLE_UNLIKELY(shaderPLSFormats[i] == ShPixelLocalStorageFormat::NotPLS)) { // INVALID_OPERATION is generated if a draw is issued with a fragment shader that // does _not_ have a pixel local uniform bound to an _active_ pixel local storage @@ -730,8 +764,8 @@ ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context, return gl::err::kPLSDrawProgramActivePlanesUnused; } - if (ShPixelLocalStorageFormatToGLenum(shaderPLSFormats[i]) != - plsPlane.getInternalformat()) + if (ANGLE_UNLIKELY(ShPixelLocalStorageFormatToGLenum(shaderPLSFormats[i]) != + plsPlane.getInternalformat())) { // INVALID_OPERATION is generated if a draw is issued with a fragment shader that // has a pixel local storage uniform whose format layout qualifier does not @@ -745,7 +779,7 @@ ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context, // Enabled blend equation validation const char *errorString = nullptr; - if (extensions.blendEquationAdvancedKHR) + if (extensions.blendEquationAdvancedKHR || context->getClientVersion() >= ES_3_2) { errorString = ValidateProgramDrawAdvancedBlendState(context, executable); } @@ -828,7 +862,7 @@ bool ValidTexture3DTarget(const Context *context, TextureType target) { case TextureType::_3D: case TextureType::_2DArray: - return (context->getClientMajorVersion() >= 3); + return (context->getClientVersion() >= ES_3_0); case TextureType::CubeMapArray: return (context->getClientVersion() >= Version(3, 2) || @@ -886,9 +920,8 @@ bool ValidateTransformFeedbackPrimitiveMode(const Context *context, { ASSERT(context); - if ((!context->getExtensions().geometryShaderAny() || - !context->getExtensions().tessellationShaderAny()) && - context->getClientVersion() < ES_3_2) + if (!context->getExtensions().geometryShaderAny() && + !context->getExtensions().tessellationShaderAny() && context->getClientVersion() < ES_3_2) { // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode // that does not match the current transform feedback object's draw mode (if transform @@ -1015,7 +1048,8 @@ bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryP // an error. context->getState().getDebug().insertMessage( GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH, - std::string("Attempting to draw without a program"), gl::LOG_WARN, entryPoint); + std::string(GetEntryPointName(entryPoint)) + ": Attempting to draw without a program", + gl::LOG_WARN); return true; } @@ -1097,7 +1131,7 @@ bool ValidFramebufferTarget(const Context *context, GLenum target) case GL_READ_FRAMEBUFFER: case GL_DRAW_FRAMEBUFFER: return (context->getExtensions().framebufferBlitAny() || - context->getClientMajorVersion() >= 3); + context->getClientVersion() >= ES_3_0); default: return false; @@ -1257,11 +1291,6 @@ bool ValidCompressedImageSize(const Context *context, { return false; } - - if (!isPow2(width) || !isPow2(height)) - { - return false; - } } return true; @@ -1422,14 +1451,12 @@ bool ValidQueryType(const Context *context, QueryType queryType) { case QueryType::AnySamples: case QueryType::AnySamplesConservative: - return context->getClientMajorVersion() >= 3 || + return context->getClientVersion() >= ES_3_0 || context->getExtensions().occlusionQueryBooleanEXT; case QueryType::TransformFeedbackPrimitivesWritten: - return (context->getClientMajorVersion() >= 3); + return context->getClientVersion() >= ES_3_0; case QueryType::TimeElapsed: return context->getExtensions().disjointTimerQueryEXT; - case QueryType::CommandsCompleted: - return context->getExtensions().syncQueryCHROMIUM; case QueryType::PrimitivesGenerated: return context->getClientVersion() >= ES_3_2 || context->getExtensions().geometryShaderAny(); @@ -1545,7 +1572,7 @@ bool ValidateAttachmentTarget(const Context *context, { if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffersEXT) + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().drawBuffersEXT) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment); return false; @@ -1569,7 +1596,7 @@ bool ValidateAttachmentTarget(const Context *context, break; case GL_DEPTH_STENCIL_ATTACHMENT: - if (!context->isWebGL() && context->getClientMajorVersion() < 3) + if (!context->isWebGL() && context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment); return false; @@ -1831,6 +1858,12 @@ bool ValidateBlitFramebufferParameters(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageColor); return false; } + + if (IsBlitSameResource(readColorBuffer, attachment)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameResource); + return false; + } } } @@ -1879,6 +1912,12 @@ bool ValidateBlitFramebufferParameters(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil); return false; } + + if (IsBlitSameResource(readBuffer, drawBuffer)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameResource); + return false; + } } // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment else if (context->isWebGL() && drawBuffer) @@ -1889,7 +1928,7 @@ bool ValidateBlitFramebufferParameters(const Context *context, } } - // OVR_multiview2: + // OVR_multiview: // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the // current draw framebuffer isMultiview() or the number of // views in the current read framebuffer is more than one. @@ -2187,6 +2226,12 @@ bool ValidateGenerateMipmapBase(const Context *context, return false; } + if (context->getState().isTextureBoundToActivePLS(texture->id())) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture); + return false; + } + const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel(); // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so @@ -2201,8 +2246,8 @@ bool ValidateGenerateMipmapBase(const Context *context, ? TextureTarget::CubeMapPositiveX : NonCubeTextureTypeToTarget(target); const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info); - if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 || - format.stencilBits > 0) + if (format.sizedInternalFormat == GL_NONE || format.compressed || format.paletted || + format.depthBits > 0 || format.stencilBits > 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed); return false; @@ -2339,6 +2384,13 @@ bool ValidateReadnPixelsRobustANGLE(const Context *context, const GLsizei *rows, const void *data) { + if ((context->getClientVersion() < ES_3_2) && !context->getExtensions().robustnessEXT && + !context->getExtensions().robustnessKHR) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); + return false; + } + GLsizei writeLength = 0; GLsizei writeColumns = 0; GLsizei writeRows = 0; @@ -2371,14 +2423,7 @@ bool ValidateGenQueriesEXT(const Context *context, GLsizei n, const QueryID *ids) { - if (!context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, ids); } bool ValidateDeleteQueriesEXT(const Context *context, @@ -2386,25 +2431,11 @@ bool ValidateDeleteQueriesEXT(const Context *context, GLsizei n, const QueryID *ids) { - if (!context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, ids); } bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id) { - if (!context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled); - return false; - } - return true; } @@ -2470,14 +2501,6 @@ bool ValidateBeginQueryEXT(const Context *context, QueryType target, QueryID id) { - if (!context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().disjointTimerQueryEXT && - !context->getExtensions().syncQueryCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled); - return false; - } - return ValidateBeginQueryBase(context, entryPoint, target, id); } @@ -2502,14 +2525,6 @@ bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target) { - if (!context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().disjointTimerQueryEXT && - !context->getExtensions().syncQueryCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled); - return false; - } - return ValidateEndQueryBase(context, entryPoint, target); } @@ -2518,12 +2533,6 @@ bool ValidateQueryCounterEXT(const Context *context, QueryID id, QueryType target) { - if (!context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (target != QueryType::Timestamp) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget); @@ -2544,6 +2553,13 @@ bool ValidateQueryCounterEXT(const Context *context, return false; } + // Check if target type matches the query object target type + if (queryObject && queryObject->getType() != target) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryTargetMismatch); + return false; + } + return true; } @@ -2574,8 +2590,7 @@ bool ValidateGetQueryivBase(const Context *context, } break; case GL_QUERY_COUNTER_BITS_EXT: - if (!context->getExtensions().disjointTimerQueryEXT || - (target != QueryType::Timestamp && target != QueryType::TimeElapsed)) + if (!context->getExtensions().disjointTimerQueryEXT) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname); return false; @@ -2601,14 +2616,6 @@ bool ValidateGetQueryivEXT(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().disjointTimerQueryEXT && - !context->getExtensions().syncQueryCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr); } @@ -2620,6 +2627,13 @@ bool ValidateGetQueryivRobustANGLE(const Context *context, const GLsizei *length, const GLint *params) { + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().disjointTimerQueryEXT && + !context->getExtensions().occlusionQueryBooleanEXT) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -2655,23 +2669,21 @@ bool ValidateGetQueryObjectValueBase(const Context *context, if (context->isContextLost()) { - ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); - if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) { - // Generate an error but still return true, the context still needs to return a - // value in this case. + // The context needs to return a value in this case. + // It will also generate a CONTEXT_LOST error. return true; } else { + ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); return false; } } Query *queryObject = context->getQuery(id); - - if (!queryObject) + if (queryObject == nullptr) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId); return false; @@ -2703,11 +2715,6 @@ bool ValidateGetQueryObjectivEXT(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); } @@ -2753,13 +2760,6 @@ bool ValidateGetQueryObjectuivEXT(const Context *context, GLenum pname, const GLuint *params) { - if (!context->getExtensions().disjointTimerQueryEXT && - !context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().syncQueryCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); } @@ -2771,11 +2771,10 @@ bool ValidateGetQueryObjectuivRobustANGLE(const Context *context, const GLsizei *length, const GLuint *params) { - if (!context->getExtensions().disjointTimerQueryEXT && - !context->getExtensions().occlusionQueryBooleanEXT && - !context->getExtensions().syncQueryCHROMIUM) + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().disjointTimerQueryEXT && + !context->getExtensions().occlusionQueryBooleanEXT) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); return false; } @@ -2805,13 +2804,8 @@ bool ValidateGetQueryObjecti64vEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id, GLenum pname, - GLint64 *params) + const GLint64 *params) { - if (!context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); } @@ -2821,7 +2815,7 @@ bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context, GLenum pname, GLsizei bufSize, const GLsizei *length, - GLint64 *params) + const GLint64 *params) { if (!context->getExtensions().disjointTimerQueryEXT) { @@ -2855,13 +2849,8 @@ bool ValidateGetQueryObjectui64vEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id, GLenum pname, - GLuint64 *params) + const GLuint64 *params) { - if (!context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); } @@ -2871,7 +2860,7 @@ bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context, GLenum pname, GLsizei bufSize, const GLsizei *length, - GLuint64 *params) + const GLuint64 *params) { if (!context->getExtensions().disjointTimerQueryEXT) { @@ -2957,9 +2946,16 @@ bool ValidateUniform(const Context *context, { const LinkedUniform *uniform = nullptr; Program *programObject = context->getActiveLinkedProgram(); - return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, - &uniform) && - ValidateUniformValue(context, entryPoint, valueType, uniform->getType()); + if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform)) + { + // Error already generated. + return false; + } + if (uniform == nullptr) + { + return true; // no-op + } + return ValidateUniformValue(context, entryPoint, valueType, uniform->getType()); } bool ValidateUniform1iv(const Context *context, @@ -2970,9 +2966,16 @@ bool ValidateUniform1iv(const Context *context, { const LinkedUniform *uniform = nullptr; Program *programObject = context->getActiveLinkedProgram(); - return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, - &uniform) && - ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value); + if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform)) + { + // Error already generated. + return false; + } + if (uniform == nullptr) + { + return true; // no-op + } + return ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value); } bool ValidateUniformMatrix(const Context *context, @@ -2982,7 +2985,7 @@ bool ValidateUniformMatrix(const Context *context, GLsizei count, GLboolean transpose) { - if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3) + if (ConvertToBool(transpose) && context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kES3Required); return false; @@ -2990,9 +2993,16 @@ bool ValidateUniformMatrix(const Context *context, const LinkedUniform *uniform = nullptr; Program *programObject = context->getActiveLinkedProgram(); - return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, - &uniform) && - ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType()); + if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform)) + { + // Error already generated. + return false; + } + if (uniform == nullptr) + { + return true; // no-op + } + return ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType()); } bool ValidateStateQuery(const Context *context, @@ -3131,12 +3141,6 @@ bool ValidateStateQuery(const Context *context, break; } - // pname is valid, but there are no parameters to return - if (*numParams == 0) - { - return false; - } - return true; } @@ -3205,19 +3209,19 @@ bool ValidateGetInteger64vRobustANGLE(const Context *context, GLenum pname, GLsizei bufSize, const GLsizei *length, - GLint64 *data) + const GLint64 *data) { - GLenum nativeType; - unsigned int numParams = 0; - - if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams)) + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().disjointTimerQueryEXT) { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); return false; } - if (nativeType == GL_INT_64_ANGLEX) + GLenum nativeType; + unsigned int numParams = 0; + + if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams)) { - CastStateValues(context, nativeType, pname, numParams, data); return false; } @@ -3250,100 +3254,6 @@ bool ValidateRobustStateQuery(const Context *context, return true; } -bool ValidateCopyImageSubDataTarget(const Context *context, - angle::EntryPoint entryPoint, - GLuint name, - GLenum target) -{ - // From EXT_copy_image: INVALID_ENUM is generated if either or is not - // RENDERBUFFER or a valid non - proxy texture target, is TEXTURE_BUFFER, or is one of the - // cubemap face selectors described in table 3.17, or if the target does not match the type of - // the object. INVALID_VALUE is generated if either or does not correspond - // to a valid renderbuffer or texture object according to the corresponding target parameter. - switch (target) - { - case GL_RENDERBUFFER: - { - RenderbufferID renderbuffer = PackParam(name); - if (!context->isRenderbuffer(renderbuffer)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferName); - return false; - } - break; - } - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_ARRAY_EXT: - case GL_TEXTURE_EXTERNAL_OES: - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES: - { - TextureID texture = PackParam(name); - if (!context->isTexture(texture)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureName); - return false; - } - - Texture *textureObject = context->getTexture(texture); - if (textureObject && textureObject->getType() != PackParam(target)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kTextureTypeMismatch); - return false; - } - break; - } - default: - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget); - return false; - } - - return true; -} - -bool ValidateCopyImageSubDataLevel(const Context *context, - angle::EntryPoint entryPoint, - GLenum target, - GLint level) -{ - switch (target) - { - case GL_RENDERBUFFER: - { - if (level != 0) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel); - return false; - } - break; - } - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_ARRAY_EXT: - case GL_TEXTURE_EXTERNAL_OES: - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES: - { - if (!ValidMipLevel(context, PackParam(target), level)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel); - return false; - } - break; - } - default: - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget); - return false; - } - - return true; -} - bool ValidateCopyImageSubDataTargetRegion(const Context *context, angle::EntryPoint entryPoint, GLuint name, @@ -3354,6 +3264,7 @@ bool ValidateCopyImageSubDataTargetRegion(const Context *context, GLint offsetZ, GLsizei width, GLsizei height, + GLsizei depth, GLsizei *samples) { // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries @@ -3400,10 +3311,16 @@ bool ValidateCopyImageSubDataTargetRegion(const Context *context, texture->getWidth(PackParam(textureTargetToUse), level)); const GLsizei textureHeight = static_cast( texture->getHeight(PackParam(textureTargetToUse), level)); + const GLsizei textureDepth = + target == GL_TEXTURE_CUBE_MAP + ? 6 + : static_cast( + texture->getDepth(PackParam(textureTargetToUse), level)); // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the // boundaries of the corresponding image object - if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height)) + if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height) || + (textureDepth - offsetZ < depth)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall); return false; @@ -3418,16 +3335,44 @@ bool ValidateCopyImageSubDataTargetRegion(const Context *context, bool ValidateCompressedRegion(const Context *context, angle::EntryPoint entryPoint, + const gl::Texture &Texture, + GLenum textureTarget, + const GLint textureLevel, const InternalFormat &formatInfo, - GLsizei width, - GLsizei height) + const GLint offsetX, + const GLint offsetY, + const GLint offsetZ, + const GLsizei width, + const GLsizei height, + const GLsizei depth) { ASSERT(formatInfo.compressed); + bool subregionAlignedWithCompressedBlock = false; + if (textureTarget == GL_TEXTURE_CUBE_MAP) + { + // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight + textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + } + const gl::TextureTarget textureTargetPacked = gl::PackParam(textureTarget); + ASSERT(textureTargetPacked != gl::TextureTarget::InvalidEnum); + + const gl::Extents &textureExtents = Texture.getExtents(textureTargetPacked, textureLevel); + subregionAlignedWithCompressedBlock = ((offsetX % formatInfo.compressedBlockWidth) == 0) && + ((offsetX + width == textureExtents.width) || + (width % formatInfo.compressedBlockWidth == 0)); + subregionAlignedWithCompressedBlock = subregionAlignedWithCompressedBlock && + ((offsetY % formatInfo.compressedBlockHeight) == 0) && + ((offsetY + height == textureExtents.height) || + (height % formatInfo.compressedBlockHeight == 0)); + subregionAlignedWithCompressedBlock = subregionAlignedWithCompressedBlock && + ((offsetZ % formatInfo.compressedBlockDepth) == 0) && + ((offsetZ + depth == textureExtents.depth) || + (depth % formatInfo.compressedBlockDepth == 0)); + // INVALID_VALUE is generated if the image format is compressed and the dimensions of the // subregion fail to meet the alignment constraints of the format. - if ((width % formatInfo.compressedBlockWidth != 0) || - (height % formatInfo.compressedBlockHeight != 0)) + if (!subregionAlignedWithCompressedBlock) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedRegionSize); return false; @@ -3436,48 +3381,9 @@ bool ValidateCompressedRegion(const Context *context, return true; } -const InternalFormat &GetTargetFormatInfo(const Context *context, - angle::EntryPoint entryPoint, - GLuint name, - GLenum target, - GLint level) -{ - static const InternalFormat defaultInternalFormat; - - switch (target) - { - case GL_RENDERBUFFER: - { - Renderbuffer *buffer = context->getRenderbuffer(PackParam(name)); - return *buffer->getFormat().info; - } - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_ARRAY_EXT: - case GL_TEXTURE_EXTERNAL_OES: - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES: - { - Texture *texture = context->getTexture(PackParam(name)); - GLenum textureTargetToUse = target; - - if (target == GL_TEXTURE_CUBE_MAP) - { - // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the - // textureWidth/textureHeight - textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - } - return *texture->getFormat(PackParam(textureTargetToUse), level).info; - } - default: - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget); - return defaultInternalFormat; - } -} - -bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compressedFormat) +bool ValidateCopyMixedFormatCompatible(const Context *context, + GLenum uncompressedFormat, + GLenum compressedFormat) { // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the // EXT_copy_image spec. @@ -3578,6 +3484,9 @@ bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compres case GL_RG32I: case GL_RG32F: return true; + case GL_RGBA16_EXT: + case GL_RGBA16_SNORM_EXT: + return context->getExtensions().textureNorm16EXT; default: return false; } @@ -3709,7 +3618,8 @@ bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo, return false; } -bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo, +bool ValidateCopyFormatCompatible(const Context *context, + const InternalFormat &srcFormatInfo, const InternalFormat &dstFormatInfo) { // Matching source and destination formats are compatible. @@ -3725,7 +3635,7 @@ bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo, GLenum compressedFormat = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat : dstFormatInfo.internalFormat; - return ValidateCopyMixedFormatCompatible(uncompressedFormat, compressedFormat); + return ValidateCopyMixedFormatCompatible(context, uncompressedFormat, compressedFormat); } if (!srcFormatInfo.compressed) @@ -3737,6 +3647,117 @@ bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo, return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo); } +const InternalFormat *GetValidFormatInfoForCopyImageSubData(const Context *context, + angle::EntryPoint entryPoint, + GLuint name, + GLenum target, + GLint level) +{ + // An INVALID_ENUM error is generated if either target is not + // RENDERBUFFER or a valid texture target; is TEXTURE_BUFFER or one of the + // cubemap face selectors. + switch (target) + { + case GL_RENDERBUFFER: + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + break; + case GL_TEXTURE_2D_MULTISAMPLE: + if (context->getClientVersion() < ES_3_1 && + !context->getExtensions().textureMultisampleANGLE) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required); + return nullptr; + } + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + if (context->getClientVersion() < ES_3_2 && + !context->getExtensions().textureStorageMultisample2dArrayOES) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionOrES32Required); + return nullptr; + } + break; + case GL_TEXTURE_CUBE_MAP_ARRAY: + if (context->getClientVersion() < ES_3_2 && + !context->getExtensions().textureCubeMapArrayAny()) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget); + return nullptr; + } + break; + case GL_TEXTURE_EXTERNAL_OES: + if (!context->getExtensions().EGLImageExternalOES) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget); + return nullptr; + } + break; + default: + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget); + return nullptr; + } + + if (target == GL_RENDERBUFFER) + { + Renderbuffer *renderbufferObject = + context->getRenderbuffer(PackParam(name)); + if (renderbufferObject == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferName); + return nullptr; + } + + if (level != 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel); + return nullptr; + } + + return renderbufferObject->getFormat().info; + } + + // If the target is not RENDERBUFFER, it could only be a texture. + Texture *textureObject = context->getTexture(PackParam(name)); + if (textureObject == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureName); + return nullptr; + } + + // the target must match the texture type. + const TextureType textureType = textureObject->getType(); + if (ToGLenum(textureType) != target) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureTargetInvalidForCopyImage); + return nullptr; + } + + // Check that mip level is not greater than the maximum possible for the texture type. + if (!ValidMipLevel(context, textureType, level)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel); + return nullptr; + } + + const gl::TextureTarget textureTarget = (textureType == TextureType::CubeMap) + ? kCubeMapTextureTargetMin + : NonCubeTextureTypeToTarget(textureType); + const InternalFormat *internalFormat = textureObject->getFormat(textureTarget, level).info; + ASSERT(internalFormat != nullptr); + + // Check that an image exists at the specified level. + if (internalFormat->internalFormat == GL_NONE) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureLevel); + return nullptr; + } + + return internalFormat; +} + bool ValidateCopyImageSubDataBase(const Context *context, angle::EntryPoint entryPoint, GLuint srcName, @@ -3763,50 +3784,40 @@ bool ValidateCopyImageSubDataBase(const Context *context, return false; } - if (!ValidateCopyImageSubDataTarget(context, entryPoint, srcName, srcTarget)) - { - return false; - } - if (!ValidateCopyImageSubDataTarget(context, entryPoint, dstName, dstTarget)) + const InternalFormat *srcFormatInfo = + GetValidFormatInfoForCopyImageSubData(context, entryPoint, srcName, srcTarget, srcLevel); + if (srcFormatInfo == nullptr) { + // Error already generated. return false; } - if (!ValidateCopyImageSubDataLevel(context, entryPoint, srcTarget, srcLevel)) - { - return false; - } - if (!ValidateCopyImageSubDataLevel(context, entryPoint, dstTarget, dstLevel)) + const InternalFormat *dstFormatInfo = + GetValidFormatInfoForCopyImageSubData(context, entryPoint, dstName, dstTarget, dstLevel); + if (dstFormatInfo == nullptr) { + // Error already generated. return false; } - const InternalFormat &srcFormatInfo = - GetTargetFormatInfo(context, entryPoint, srcName, srcTarget, srcLevel); - const InternalFormat &dstFormatInfo = - GetTargetFormatInfo(context, entryPoint, dstName, dstTarget, dstLevel); GLsizei dstWidth = srcWidth; GLsizei dstHeight = srcHeight; + GLsizei dstDepth = srcDepth; GLsizei srcSamples = 1; GLsizei dstSamples = 1; - if (srcFormatInfo.internalFormat == GL_NONE || dstFormatInfo.internalFormat == GL_NONE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureLevel); - return false; - } - // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats // are not compatible, if one image is compressed and the other is uncompressed and the block // size of compressed image is not equal to the texel size of the compressed image. - if (!ValidateCopyFormatCompatible(srcFormatInfo, dstFormatInfo)) + if (!ValidateCopyFormatCompatible(context, *srcFormatInfo, *dstFormatInfo)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIncompatibleTextures); return false; } if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel, - srcX, srcY, srcZ, srcWidth, srcHeight, &srcSamples)) + srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth, + &srcSamples)) { return false; } @@ -3814,50 +3825,42 @@ bool ValidateCopyImageSubDataBase(const Context *context, // When copying from a compressed image to an uncompressed image the image texel dimensions // written to the uncompressed image will be source extent divided by the compressed texel block // dimensions. - if ((srcFormatInfo.compressed) && (!dstFormatInfo.compressed)) + if ((srcFormatInfo->compressed) && (!dstFormatInfo->compressed)) { - ASSERT(srcFormatInfo.compressedBlockWidth != 0); - ASSERT(srcFormatInfo.compressedBlockHeight != 0); + ASSERT(srcFormatInfo->compressedBlockWidth != 0); + ASSERT(srcFormatInfo->compressedBlockHeight != 0); - dstWidth /= srcFormatInfo.compressedBlockWidth; - dstHeight /= srcFormatInfo.compressedBlockHeight; + dstWidth /= srcFormatInfo->compressedBlockWidth; + dstHeight /= srcFormatInfo->compressedBlockHeight; } // When copying from an uncompressed image to a compressed image the image texel dimensions // written to the compressed image will be the source extent multiplied by the compressed texel // block dimensions. - else if ((!srcFormatInfo.compressed) && (dstFormatInfo.compressed)) + else if ((!srcFormatInfo->compressed) && (dstFormatInfo->compressed)) { - dstWidth *= dstFormatInfo.compressedBlockWidth; - dstHeight *= dstFormatInfo.compressedBlockHeight; + dstWidth *= dstFormatInfo->compressedBlockWidth; + dstHeight *= dstFormatInfo->compressedBlockHeight; } if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel, - dstX, dstY, dstZ, dstWidth, dstHeight, &dstSamples)) + dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth, + &dstSamples)) { return false; } - bool fillsEntireMip = false; - gl::Texture *dstTexture = context->getTexture({dstName}); - gl::TextureTarget dstTargetPacked = gl::PackParam(dstTarget); - // TODO(http://anglebug.com/42264179): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER) - // are unsupported when used with compressed formats due to gl::PackParam() returning - // TextureTarget::InvalidEnum. - if (dstTargetPacked != gl::TextureTarget::InvalidEnum) - { - const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel); - fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width && - srcHeight == dstExtents.height && srcDepth == dstExtents.depth; - } - - if (srcFormatInfo.compressed && !fillsEntireMip && - !ValidateCompressedRegion(context, entryPoint, srcFormatInfo, srcWidth, srcHeight)) + gl::Texture *srcTexture = context->getTexture({srcName}); + if (srcFormatInfo->compressed && + !ValidateCompressedRegion(context, entryPoint, *srcTexture, srcTarget, srcLevel, + *srcFormatInfo, srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth)) { return false; } - if (dstFormatInfo.compressed && !fillsEntireMip && - !ValidateCompressedRegion(context, entryPoint, dstFormatInfo, dstWidth, dstHeight)) + gl::Texture *dstTexture = context->getTexture({dstName}); + if (dstFormatInfo->compressed && + !ValidateCompressedRegion(context, entryPoint, *dstTexture, dstTarget, dstLevel, + *dstFormatInfo, dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth)) { return false; } @@ -4164,7 +4167,8 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) VertexArray *vertexArray = state.getVertexArray(); ASSERT(vertexArray); - if (!extensions.webglCompatibilityANGLE && vertexArray->hasInvalidMappedArrayBuffer()) + if (!extensions.webglCompatibilityANGLE && + ANGLE_UNLIKELY(vertexArray->hasInvalidMappedArrayBuffer())) { return kBufferMapped; } @@ -4174,8 +4178,8 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) Framebuffer *framebuffer = state.getDrawFramebuffer(); ASSERT(framebuffer); - if (context->getLimitations().noSeparateStencilRefsAndMasks || - extensions.webglCompatibilityANGLE) + if (ANGLE_UNLIKELY(context->getLimitations().noSeparateStencilRefsAndMasks || + extensions.webglCompatibilityANGLE)) { ASSERT(framebuffer); const FramebufferAttachment *dsAttachment = @@ -4213,13 +4217,13 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask = state.getBlendEnabledDrawBufferMask() & framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask(); - if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any()) + if (ANGLE_UNLIKELY(blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())) { return kUnsupportedFloatBlending; } } - if (extensions.renderSharedExponentQCOM) + if (ANGLE_UNLIKELY(extensions.renderSharedExponentQCOM)) { if (!ValidateColorMasksForSharedExponentColorBuffers(state.getBlendStateExt(), framebuffer)) { @@ -4227,8 +4231,8 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } } - if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc || - extensions.webglCompatibilityANGLE) + if (ANGLE_UNLIKELY(context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc || + extensions.webglCompatibilityANGLE)) { if (state.hasSimultaneousConstantColorAndAlphaBlendFunc()) { @@ -4243,7 +4247,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context); - if (!framebufferStatus.isComplete()) + if (ANGLE_UNLIKELY(!framebufferStatus.isComplete())) { *outErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION; ASSERT(framebufferStatus.reason); @@ -4251,7 +4255,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } bool framebufferIsYUV = framebuffer->hasYUVAttachment(); - if (framebufferIsYUV) + if (ANGLE_UNLIKELY(framebufferIsYUV)) { const BlendState &blendState = state.getBlendState(); if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue || @@ -4270,7 +4274,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } else { - if (framebuffer->hasExternalTextureAttachment()) + if (ANGLE_UNLIKELY(framebuffer->hasExternalTextureAttachment())) { // It is an error to render into an external texture that is not YUV. return kExternalTextureAttachmentNotYUV; @@ -4279,7 +4283,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) // Advanced blend equation can only be enabled for a single render target. const BlendStateExt &blendStateExt = state.getBlendStateExt(); - if (blendStateExt.getUsesAdvancedBlendEquationMask().any()) + if (ANGLE_UNLIKELY(blendStateExt.getUsesAdvancedBlendEquationMask().any())) { const size_t drawBufferCount = framebuffer->getDrawbufferStateCount(); uint32_t advancedBlendRenderTargetCount = 0; @@ -4302,7 +4306,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } // Dual-source blending functions limit the number of supported draw buffers. - if (blendStateExt.getUsesExtendedBlendFactorMask().any()) + if (ANGLE_UNLIKELY(blendStateExt.getUsesExtendedBlendFactorMask().any())) { // Imply the strictest spec interpretation to pass on all OpenGL drivers: // dual-source blending is considered active if the blend state contains @@ -4318,7 +4322,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } } - if (context->getStateCache().hasAnyEnabledClientAttrib()) + if (ANGLE_UNLIKELY(context->hasAnyEnabledClientAttrib())) { if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled()) { @@ -4338,7 +4342,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } // If we are running GLES1, there is no current program. - if (context->getClientVersion() >= Version(2, 0)) + if (ANGLE_LIKELY(context->getClientVersion() >= Version(2, 0))) { Program *program = state.getLinkedProgram(context); ProgramPipeline *programPipeline = state.getLinkedProgramPipeline(context); @@ -4346,7 +4350,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) bool programIsYUVOutput = false; - if (program) + if (ANGLE_LIKELY(program)) { const char *errorMsg = ValidateProgramDrawStates(context, extensions, *executable); if (errorMsg) @@ -4356,7 +4360,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) programIsYUVOutput = executable->isYUVOutput(); } - else if (programPipeline) + else if (ANGLE_UNLIKELY(programPipeline)) { const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline); if (errorMsg) @@ -4378,14 +4382,14 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) programIsYUVOutput = executable->isYUVOutput(); } - if (executable) + if (ANGLE_LIKELY(executable)) { if (!executable->validateSamplers(context->getCaps())) { return kTextureTypeConflict; } - if (executable->hasLinkedTessellationShader()) + if (ANGLE_UNLIKELY(executable->hasLinkedTessellationShader())) { if (!executable->hasLinkedShaderStage(ShaderType::Vertex)) { @@ -4399,7 +4403,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } } - if (state.isTransformFeedbackActive()) + if (ANGLE_UNLIKELY(state.isTransformFeedbackActive())) { if (!ValidateProgramExecutableXFBBuffersPresent(context, executable)) { @@ -4420,7 +4424,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } // Do some additional WebGL-specific validation - if (extensions.webglCompatibilityANGLE) + if (ANGLE_UNLIKELY(extensions.webglCompatibilityANGLE)) { const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback(); if (state.isTransformFeedbackActive() && @@ -4464,14 +4468,14 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode) } // Validate that we are rendering with a linked program. - if (!program->isLinked()) + if (program != nullptr && !program->isLinked()) { return kProgramNotLinked; } } // The QCOM_framebuffer_foveated spec: - if (framebuffer->isFoveationEnabled()) + if (ANGLE_UNLIKELY(framebuffer->isFoveationEnabled())) { ASSERT(extensions.framebufferFoveatedQCOM); @@ -4612,12 +4616,6 @@ bool ValidateDrawArraysInstancedANGLE(const Context *context, GLsizei count, GLsizei primcount) { - if (!context->getExtensions().instancedArraysANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0)) { return false; @@ -4633,12 +4631,6 @@ bool ValidateDrawArraysInstancedEXT(const Context *context, GLsizei count, GLsizei primcount) { - if (!context->getExtensions().instancedArraysEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0)) { return false; @@ -4651,7 +4643,7 @@ const char *ValidateDrawElementsStates(const Context *context) { const State &state = context->getState(); - if (context->getStateCache().isTransformFeedbackActiveUnpaused()) + if (ANGLE_UNLIKELY(context->getStateCache().isTransformFeedbackActiveUnpaused())) { // EXT_geometry_shader allows transform feedback to work with all draw commands. // [EXT_geometry_shader] Section 12.1, "Transform Feedback" @@ -4669,13 +4661,14 @@ const char *ValidateDrawElementsStates(const Context *context) if (elementArrayBuffer) { - if (elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) + if (ANGLE_UNLIKELY(context->isWebGL()) && + elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) { return kElementArrayBufferBoundForTransformFeedback; } - if (elementArrayBuffer->isMapped() && - (!elementArrayBuffer->isImmutable() || - (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0)) + if (ANGLE_UNLIKELY(elementArrayBuffer->isMapped()) && + ANGLE_UNLIKELY(!elementArrayBuffer->isImmutable() || + (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0)) { return kBufferMapped; } @@ -4685,7 +4678,7 @@ const char *ValidateDrawElementsStates(const Context *context) // [WebGL 1.0] Section 6.2 No Client Side Arrays // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated. - if (!context->getState().areClientArraysEnabled() || context->isWebGL()) + if (ANGLE_UNLIKELY(!context->getState().areClientArraysEnabled() || context->isWebGL())) { return kMustHaveElementArrayBinding; } @@ -4702,12 +4695,6 @@ bool ValidateDrawElementsInstancedANGLE(const Context *context, const void *indices, GLsizei primcount) { - if (!context->getExtensions().instancedArraysANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, primcount, 0)) { @@ -4725,12 +4712,6 @@ bool ValidateDrawElementsInstancedEXT(const Context *context, const void *indices, GLsizei primcount) { - if (!context->getExtensions().instancedArraysEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, primcount, 0)) { @@ -4752,12 +4733,13 @@ bool ValidateGetUniformBase(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } - if (!programObject || !programObject->isLinked()) + if (!programObject->isLinked()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); return false; @@ -4935,7 +4917,7 @@ bool ValidateGetUniformuivRobustANGLE(const Context *context, return false; } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); return false; @@ -5019,29 +5001,10 @@ bool ValidateDiscardFramebufferBase(const Context *context, } bool ValidateInsertEventMarkerEXT(const Context *context, - angle::EntryPoint entryPoint, - GLsizei length, - const char *marker) -{ - if (!context->getExtensions().debugMarkerEXT) - { - // The debug marker calls should not set error state - // However, it seems reasonable to set an error state if the extension is not enabled - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - // Note that debug marker calls must not set error state - if (length < 0) - { - return false; - } - - if (marker == nullptr) - { - return false; - } - + angle::EntryPoint entryPoint, + GLsizei length, + const char *marker) +{ return true; } @@ -5050,22 +5013,11 @@ bool ValidatePushGroupMarkerEXT(const Context *context, GLsizei length, const char *marker) { - if (!context->getExtensions().debugMarkerEXT) - { - // The debug marker calls should not set error state - // However, it seems reasonable to set an error state if the extension is not enabled - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - // Note that debug marker calls must not set error state - if (length < 0) - { - return false; - } - - if (length > 0 && marker == nullptr) + // This is to prevent the stack from getting too large. The limit used here is also used for + // pushing debug groups. + if (context->getState().getGroupMarkerCount() >= context->getCaps().maxDebugGroupStackDepth) { + ANGLE_VALIDATION_ERROR(GL_STACK_OVERFLOW, kExceedsMaxGroupMarkerStackDepth); return false; } @@ -5126,13 +5078,6 @@ bool ValidateEGLImageObject(const Context *context, return false; } - // 3d EGLImages are currently not supported - if (type == TextureType::_3D) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch); - return false; - } - if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, @@ -5148,18 +5093,13 @@ bool ValidateEGLImageTargetTexture2DOES(const Context *context, TextureType type, egl::ImageID image) { - if (!context->getExtensions().EGLImageOES && !context->getExtensions().EGLImageExternalOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (type) { case TextureType::_2D: if (!context->getExtensions().EGLImageOES) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type)); + return false; } break; @@ -5167,6 +5107,7 @@ bool ValidateEGLImageTargetTexture2DOES(const Context *context, if (!context->getExtensions().EGLImageArrayEXT) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type)); + return false; } break; @@ -5174,6 +5115,7 @@ bool ValidateEGLImageTargetTexture2DOES(const Context *context, if (!context->getExtensions().EGLImageExternalOES) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type)); + return false; } break; @@ -5190,12 +5132,6 @@ bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context, GLenum target, egl::ImageID image) { - if (!context->getExtensions().EGLImageOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (target) { case GL_RENDERBUFFER: @@ -5247,6 +5183,7 @@ bool ValidateProgramBinaryBase(const Context *context, Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } @@ -5279,6 +5216,7 @@ bool ValidateGetProgramBinaryBase(const Context *context, Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } @@ -5313,6 +5251,12 @@ bool ValidateDrawBuffersBase(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer); return false; } + // INVALID_VALUE is generated if n != 0 and bufs is NULL + if (n != 0 && bufs == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } ASSERT(context->getState().getDrawFramebuffer()); FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id(); @@ -5605,24 +5549,25 @@ bool ValidateFlushMappedBufferRangeBase(const Context *context, return true; } -bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n) +bool ValidateGenOrDelete(ErrorSet *errors, angle::EntryPoint entryPoint, GLint n, const void *ids) { if (n < 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); + errors->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); return false; } - return true; -} -bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize) -{ - if (!context->getExtensions().robustClientMemoryANGLE) + if (n > 0 && ids == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + errors->validationError(entryPoint, GL_INVALID_VALUE, kPLSParamsNULL); return false; } + return true; +} + +bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize) +{ if (bufSize < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); @@ -5659,7 +5604,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, return false; } - int clientVersion = context->getClientMajorVersion(); + const Version &clientVersion = context->getClientVersion(); switch (pname) { @@ -5671,8 +5616,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR: case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR: - if (clientVersion < 3 || - !(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR)) + if (!context->getExtensions().multiviewOVR) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -5688,7 +5632,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, break; case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - if (clientVersion < 3 && !context->getExtensions().sRGBEXT) + if (clientVersion < ES_3_0 && !context->getExtensions().sRGBEXT) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -5696,7 +5640,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, break; case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (clientVersion < 3 && !context->getExtensions().colorBufferHalfFloatEXT && + if (clientVersion < ES_3_0 && !context->getExtensions().colorBufferHalfFloatEXT && !context->getExtensions().colorBufferFloatRgbCHROMIUM && !context->getExtensions().colorBufferFloatRgbaCHROMIUM) { @@ -5712,7 +5656,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (clientVersion < 3) + if (clientVersion < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required); return false; @@ -5720,8 +5664,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, break; case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT: - if (!context->getExtensions().geometryShaderAny() && - context->getClientVersion() < ES_3_2) + if (!context->getExtensions().geometryShaderAny() && clientVersion < ES_3_2) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled); return false; @@ -5739,7 +5682,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, case GL_BACK: case GL_DEPTH: case GL_STENCIL: - if (clientVersion < 3) + if (clientVersion < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment); return false; @@ -5747,20 +5690,19 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, break; case GL_DEPTH_STENCIL_ATTACHMENT: - if (clientVersion < 3 && !context->isWebGL1()) + if (clientVersion < ES_3_0 && !context->isWebGL1()) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment); return false; } break; - case GL_COLOR_ATTACHMENT0: case GL_DEPTH_ATTACHMENT: case GL_STENCIL_ATTACHMENT: break; default: - if ((clientVersion < 3 && !context->getExtensions().drawBuffersEXT) || + if ((clientVersion < ES_3_0 && !context->getExtensions().drawBuffersEXT) || attachment < GL_COLOR_ATTACHMENT0_EXT || (attachment - GL_COLOR_ATTACHMENT0_EXT) >= static_cast(context->getCaps().maxColorAttachments)) @@ -5768,6 +5710,15 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment); return false; } + [[fallthrough]]; + + case GL_COLOR_ATTACHMENT0: + if (context->getPrivateState().isActivelyOverriddenPLSDrawBuffer( + attachment - GL_COLOR_ATTACHMENT0_EXT)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSColorAttachmentReserved); + return false; + } break; } @@ -5776,7 +5727,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, if (framebuffer->isDefault()) { - if (clientVersion < 3) + if (clientVersion < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget); return false; @@ -5892,7 +5843,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, break; case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (clientVersion < 3) + if (clientVersion < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter); return false; @@ -5900,7 +5851,7 @@ bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, break; default: - if (clientVersion < 3) + if (clientVersion < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter); return false; @@ -6040,6 +5991,12 @@ bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context, const GLsizei *length, const GLint64 *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + GLsizei numParams = 0; if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) @@ -6076,16 +6033,15 @@ bool ValidateGetProgramivBase(const Context *context, if (context->isContextLost()) { - ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); - if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR) { - // Generate an error but still return true, the context still needs to return a - // value in this case. + // The context needs to return a value in this case. + // It will also generate a CONTEXT_LOST error. return true; } else { + ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); return false; } } @@ -6094,8 +6050,9 @@ bool ValidateGetProgramivBase(const Context *context, Program *programObject = (pname == GL_COMPLETION_STATUS_KHR) ? GetValidProgramNoResolve(context, entryPoint, program) : GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -6121,7 +6078,7 @@ bool ValidateGetProgramivBase(const Context *context, break; case GL_PROGRAM_BINARY_LENGTH: - if (context->getClientMajorVersion() < 3 && + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().getProgramBinaryOES) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); @@ -6135,7 +6092,7 @@ bool ValidateGetProgramivBase(const Context *context, case GL_TRANSFORM_FEEDBACK_VARYINGS: case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30); return false; @@ -6210,6 +6167,24 @@ bool ValidateGetProgramivBase(const Context *context, } break; case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT: + if (!context->getExtensions().tessellationShaderAny() && + context->getClientVersion() < ES_3_2) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderEXTNotEnabled); + return false; + } + if (!programObject->isLinked()) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); + return false; + } + if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::TessControl)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, + kNoActiveTessellationControlShaderStage); + return false; + } + break; case GL_TESS_GEN_MODE_EXT: case GL_TESS_GEN_SPACING_EXT: case GL_TESS_GEN_VERTEX_ORDER_EXT: @@ -6225,6 +6200,12 @@ bool ValidateGetProgramivBase(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); return false; } + if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::TessEvaluation)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, + kNoActiveTessellationEvaluationShaderStage); + return false; + } break; default: ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); @@ -6443,6 +6424,8 @@ bool ValidateTexParameterIivRobustANGLE(const Context *context, GLsizei bufSize, const GLint *params) { + // TODO: Uncomment glTexParameterIivRobustANGLE tests in + // PixelLocalStorageValidationTest.ModifyTextureDuringPLS once implemented. UNIMPLEMENTED(); return false; } @@ -6454,6 +6437,8 @@ bool ValidateTexParameterIuivRobustANGLE(const Context *context, GLsizei bufSize, const GLuint *params) { + // TODO: Uncomment glTexParameterIuivRobustANGLE tests in + // PixelLocalStorageValidationTest.ModifyTextureDuringPLS once implemented. UNIMPLEMENTED(); return false; } @@ -6466,6 +6451,12 @@ bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context, const GLsizei *length, const GLfloat *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6473,7 +6464,7 @@ bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context, GLsizei numParams = 0; - if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams)) + if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams, params)) { return false; } @@ -6495,6 +6486,12 @@ bool ValidateGetSamplerParameterivRobustANGLE(const Context *context, const GLsizei *length, const GLint *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6502,7 +6499,7 @@ bool ValidateGetSamplerParameterivRobustANGLE(const Context *context, GLsizei numParams = 0; - if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams)) + if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams, params)) { return false; } @@ -6547,6 +6544,12 @@ bool ValidateSamplerParameterfvRobustANGLE(const Context *context, GLsizei bufSize, const GLfloat *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6562,6 +6565,12 @@ bool ValidateSamplerParameterivRobustANGLE(const Context *context, GLsizei bufSize, const GLint *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6607,7 +6616,7 @@ bool ValidateGetVertexAttribfvRobustANGLE(const Context *context, GLsizei writeLength = 0; - if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false)) + if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false)) { return false; } @@ -6636,7 +6645,7 @@ bool ValidateGetVertexAttribivRobustANGLE(const Context *context, GLsizei writeLength = 0; - if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false)) + if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false)) { return false; } @@ -6666,7 +6675,7 @@ bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context, GLsizei writeLength = 0; - if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true, false)) + if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true)) { return false; } @@ -6689,6 +6698,12 @@ bool ValidateGetVertexAttribIivRobustANGLE(const Context *context, const GLsizei *length, const GLint *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6696,7 +6711,7 @@ bool ValidateGetVertexAttribIivRobustANGLE(const Context *context, GLsizei writeLength = 0; - if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true)) + if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false)) { return false; } @@ -6719,6 +6734,12 @@ bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context, const GLsizei *length, const GLuint *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6726,7 +6747,7 @@ bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context, GLsizei writeLength = 0; - if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true)) + if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false)) { return false; } @@ -6750,6 +6771,12 @@ bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context, const GLsizei *length, const GLint *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6782,6 +6809,12 @@ bool ValidateGetInternalformativRobustANGLE(const Context *context, const GLsizei *length, const GLint *params) { + if (context->getClientVersion() < ES_3_0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; + } + if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) { return false; @@ -6821,6 +6854,7 @@ bool ValidateRobustCompressedTexImageBase(const Context *context, if (dataSize < imageSize) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall); + return false; } } return true; @@ -6870,7 +6904,7 @@ bool ValidateGetBufferParameterBase(const Context *context, case GL_BUFFER_MAPPED: static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal."); - if (context->getClientMajorVersion() < 3 && !extensions.mapbufferOES && + if (context->getClientVersion() < ES_3_0 && !extensions.mapbufferOES && !extensions.mapBufferRangeEXT) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); @@ -6889,7 +6923,7 @@ bool ValidateGetBufferParameterBase(const Context *context, case GL_BUFFER_ACCESS_FLAGS: case GL_BUFFER_MAP_OFFSET: case GL_BUFFER_MAP_LENGTH: - if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRangeEXT) + if (context->getClientVersion() < ES_3_0 && !extensions.mapBufferRangeEXT) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -6897,7 +6931,7 @@ bool ValidateGetBufferParameterBase(const Context *context, break; case GL_MEMORY_SIZE_ANGLE: - if (!context->getExtensions().memorySizeANGLE) + if (!extensions.memorySizeANGLE) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled); return false; @@ -6905,13 +6939,21 @@ bool ValidateGetBufferParameterBase(const Context *context, break; case GL_RESOURCE_INITIALIZED_ANGLE: - if (!context->getExtensions().robustResourceInitializationANGLE) + if (!extensions.robustResourceInitializationANGLE) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRobustResourceInitializationExtensionRequired); return false; } break; + case GL_BUFFER_IMMUTABLE_STORAGE_EXT: + case GL_BUFFER_STORAGE_FLAGS_EXT: + if (!extensions.bufferStorageEXT) + { + ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); + return false; + } + break; default: ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); @@ -6965,7 +7007,7 @@ bool ValidateGetRenderbufferParameterivBase(const Context *context, break; case GL_RENDERBUFFER_SAMPLES_ANGLE: - if (context->getClientMajorVersion() < 3 && + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().framebufferMultisampleANGLE) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled); @@ -7024,22 +7066,23 @@ bool ValidateGetShaderivBase(const Context *context, if (context->isContextLost()) { - ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); - if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR) { - // Generate an error but still return true, the context still needs to return a - // value in this case. + // The context needs to return a value in this case. + // It will also generate a CONTEXT_LOST error. return true; } else { + ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); return false; } } - if (GetValidShader(context, entryPoint, shader) == nullptr) + Shader *shaderObject = GetValidShader(context, entryPoint, shader); + if (shaderObject == nullptr) { + // Error already generated. return false; } @@ -7105,7 +7148,7 @@ bool ValidateGetTexParameterBase(const Context *context, return false; } - if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname)) + if (context->getClientVersion() < ES_2_0 && !IsValidGLES1TextureParameter(pname)) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -7135,7 +7178,7 @@ bool ValidateGetTexParameterBase(const Context *context, break; case GL_TEXTURE_IMMUTABLE_FORMAT: - if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorageEXT) + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().textureStorageEXT) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -7152,7 +7195,7 @@ bool ValidateGetTexParameterBase(const Context *context, case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30); return false; @@ -7161,7 +7204,7 @@ bool ValidateGetTexParameterBase(const Context *context, case GL_TEXTURE_COMPARE_MODE: case GL_TEXTURE_COMPARE_FUNC: - if (context->getClientMajorVersion() < 3 && !context->getExtensions().shadowSamplersEXT) + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().shadowSamplersEXT) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -7197,7 +7240,7 @@ bool ValidateGetTexParameterBase(const Context *context, case GL_TEXTURE_CROP_RECT_OES: // TODO(lfy@google.com): Restrict to GL_OES_draw_texture // after GL_OES_draw_texture functionality implemented - if (context->getClientMajorVersion() > 1) + if (context->getClientVersion() >= ES_2_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only); return false; @@ -7282,6 +7325,14 @@ bool ValidateGetTexParameterBase(const Context *context, return false; } break; + case GL_TEXTURE_ASTC_DECODE_PRECISION_EXT: + if (!context->getExtensions().textureCompressionAstcDecodeModeEXT) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, + kTextureCompressionASTCDecodeModeExtensionRequired); + return false; + } + break; default: ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); @@ -7300,20 +7351,13 @@ bool ValidateGetVertexAttribBase(const Context *context, GLuint index, GLenum pname, GLsizei *length, - bool pointer, - bool pureIntegerEntryPoint) + bool pointer) { if (length) { *length = 0; } - if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (index >= static_cast(context->getCaps().maxVertexAttributes)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); @@ -7345,7 +7389,7 @@ bool ValidateGetVertexAttribBase(const Context *context, static_assert( GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE, "ANGLE extension enums not equal to GL enums."); - if (context->getClientMajorVersion() < 3 && + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().instancedArraysAny()) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); @@ -7354,7 +7398,7 @@ bool ValidateGetVertexAttribBase(const Context *context, break; case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -7405,7 +7449,8 @@ bool ValidatePixelPack(const Context *context, { // Check for pixel pack buffer related API errors Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack); - if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped()) + if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped() && + !pixelPackBuffer->isPersistentlyMapped()) { // ...the buffer object's data store is currently mapped. ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped); @@ -7433,7 +7478,7 @@ bool ValidatePixelPack(const Context *context, if (bufSize >= 0) { - if (pixelPackBuffer == nullptr && static_cast(bufSize) < endByte) + if (static_cast(bufSize) < endByte) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize); return false; @@ -7446,7 +7491,8 @@ bool ValidatePixelPack(const Context *context, CheckedNumeric checkedOffset(reinterpret_cast(pixels)); checkedEndByte += checkedOffset; - if (checkedEndByte.ValueOrDie() > static_cast(pixelPackBuffer->getSize())) + if (!checkedEndByte.IsValid() || + checkedEndByte.ValueOrDie() > static_cast(pixelPackBuffer->getSize())) { // Overflow past the end of the buffer ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kParamOverflow); @@ -7508,16 +7554,14 @@ bool ValidateReadPixelsBase(const Context *context, GLsizei *rows, const void *pixels) { - if (length != nullptr) - { - *length = 0; - } - if (rows != nullptr) - { - *rows = 0; - } - if (columns != nullptr) + ASSERT((length == nullptr && columns == nullptr && rows == nullptr) || + (length != nullptr && columns != nullptr && rows != nullptr)); + const bool isRobust = (length != nullptr); + + if (isRobust) { + *length = 0; + *rows = 0; *columns = 0; } @@ -7564,7 +7608,7 @@ bool ValidateReadPixelsBase(const Context *context, break; } - // OVR_multiview2, Revision 1: + // OVR_multiview, Revision 1: // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if // the number of views in the current read framebuffer is more than one. if (readFramebuffer->readDisallowedByMultiview()) @@ -7637,12 +7681,8 @@ bool ValidateReadPixelsBase(const Context *context, } auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) { - angle::CheckedNumeric clippedExtent(length); - if (start < 0) - { - // "subtract" the area that is less than 0 - clippedExtent += start; - } + ASSERT(length >= 0); + ASSERT(bufferSize >= 0); angle::CheckedNumeric readExtent = start; readExtent += length; @@ -7651,43 +7691,60 @@ bool ValidateReadPixelsBase(const Context *context, return false; } - if (readExtent.ValueOrDie() > bufferSize) + if (outExtent == nullptr) { - // Subtract the region to the right of the read buffer - clippedExtent -= (readExtent - bufferSize); + // Only perform integer overflow validation when robust read is not used. + return true; } - if (!clippedExtent.IsValid()) + int clippedExtent = length; + if (start < 0) { - return false; + // "subtract" the area that is less than 0 + // Can't cause the overflow since |length| can't be negative. + clippedExtent += start; + } + + const int readExtentValue = readExtent.ValueOrDie(); + if (readExtentValue > bufferSize) + { + ASSERT(readExtentValue > 0); + ASSERT((start <= 0 && clippedExtent == readExtentValue) || + (start > 0 && clippedExtent == length && readExtentValue == start + length)); + // Subtract the region to the right of the read buffer + clippedExtent -= (readExtentValue - bufferSize); + // Integer overflow is not possible. + ASSERT((start <= 0 && clippedExtent == bufferSize) || + (start > 0 && clippedExtent >= -start)); } - *outExtent = std::max(clippedExtent.ValueOrDie(), 0); + *outExtent = std::max(clippedExtent, 0); return true; }; - GLsizei writtenColumns = 0; - if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns)) + Extents readBufferSize; + if (isRobust) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow); - return false; + // Only get size when robust read is used, since buffer size does not affect the integer + // overflow validation part of getClippedExtent() lambda. + if (readBuffer->ensureSizeResolved(context) == angle::Result::Stop) + { + // Context error must be generated by the failed call itself. + return false; + } + readBufferSize = readBuffer->getSize(); } - GLsizei writtenRows = 0; - if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows)) + if (!getClippedExtent(x, width, readBufferSize.width, columns)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow); return false; } - if (columns != nullptr) - { - *columns = writtenColumns; - } - - if (rows != nullptr) + if (!getClippedExtent(y, height, readBufferSize.height, rows)) { - *rows = writtenRows; + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow); + return false; } return true; @@ -7709,13 +7766,20 @@ bool ValidateTexParameterBase(const Context *context, return false; } - if (context->getTextureByType(target) == nullptr) + Texture *texture = context->getTextureByType(target); + if (texture == nullptr) { // Should only be possible for external textures ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound); return false; } + if (context->getState().isTextureBoundToActivePLS(texture->id())) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture); + return false; + } + const GLsizei minBufSize = GetTexParameterCount(pname); if (bufSize >= 0 && bufSize < minBufSize) { @@ -7723,7 +7787,7 @@ bool ValidateTexParameterBase(const Context *context, return false; } - if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname)) + if (context->getClientVersion() < ES_2_0 && !IsValidGLES1TextureParameter(pname)) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -7742,7 +7806,7 @@ bool ValidateTexParameterBase(const Context *context, case GL_TEXTURE_COMPARE_FUNC: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: - if (context->getClientMajorVersion() < 3 && + if (context->getClientVersion() < ES_3_0 && !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required); @@ -7751,12 +7815,13 @@ bool ValidateTexParameterBase(const Context *context, if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); + return false; } break; case GL_GENERATE_MIPMAP: case GL_TEXTURE_CROP_RECT_OES: - if (context->getClientMajorVersion() > 1) + if (context->getClientVersion() >= ES_2_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only); return false; @@ -7956,7 +8021,7 @@ bool ValidateTexParameterBase(const Context *context, break; case GL_GENERATE_MIPMAP: - if (context->getClientMajorVersion() > 1) + if (context->getClientVersion() >= ES_2_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only); return false; @@ -7964,7 +8029,7 @@ bool ValidateTexParameterBase(const Context *context, break; case GL_TEXTURE_CROP_RECT_OES: - if (context->getClientMajorVersion() > 1) + if (context->getClientVersion() >= ES_2_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only); return false; @@ -8078,6 +8143,33 @@ bool ValidateTexParameterBase(const Context *context, } break; + case GL_TEXTURE_ASTC_DECODE_PRECISION_EXT: + if (!context->getExtensions().textureCompressionAstcDecodeModeEXT) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, + kTextureCompressionASTCDecodeModeExtensionRequired); + return false; + } + switch (ConvertToGLenum(params[0])) + { + case GL_RGBA16F: + case GL_RGBA8: + break; + case GL_RGB9_E5: + if (!context->getExtensions().textureCompressionAstcDecodeModeRgb9e5EXT) + { + ANGLE_VALIDATION_ERROR( + GL_INVALID_ENUM, + kTextureCompressionASTCDecodeModeRGB9E5ExtensionRequired); + return false; + } + break; + + default: + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumInvalid); + return false; + } + break; default: ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); return false; @@ -8120,15 +8212,10 @@ bool ValidateGetActiveUniformBlockivBase(const Context *context, *length = 0; } - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -8181,15 +8268,15 @@ bool ValidateSamplerParameterBase(const Context *context, bool vectorParams, const ParamType *params) { - if (context->getClientMajorVersion() < 3) + if (!context->isSampler(sampler)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler); return false; } - if (!context->isSampler(sampler)) + if (params == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); return false; } @@ -8305,23 +8392,19 @@ template bool ValidateSamplerParameterBase(const Context *, bool, const GLuint *); +template bool ValidateGetSamplerParameterBase(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler, GLenum pname, - GLsizei *length) + GLsizei *length, + const ParamType *params) { if (length) { *length = 0; } - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!context->isSampler(sampler)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler); @@ -8374,15 +8457,41 @@ bool ValidateGetSamplerParameterBase(const Context *context, { *length = GetSamplerParameterCount(pname); } + + if (params == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return true; } +template bool ValidateGetSamplerParameterBase(const Context *, + angle::EntryPoint, + SamplerID, + GLenum, + GLsizei *, + const GLfloat *); +template bool ValidateGetSamplerParameterBase(const Context *, + angle::EntryPoint, + SamplerID, + GLenum, + GLsizei *, + const GLint *); +template bool ValidateGetSamplerParameterBase(const Context *, + angle::EntryPoint, + SamplerID, + GLenum, + GLsizei *, + const GLuint *); + bool ValidateGetInternalFormativBase(const Context *context, angle::EntryPoint entryPoint, GLenum target, GLenum internalformat, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *numParams) { if (numParams) @@ -8390,12 +8499,6 @@ bool ValidateGetInternalFormativBase(const Context *context, *numParams = 0; } - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); if (!formatCaps.renderbuffer) { @@ -8446,9 +8549,9 @@ bool ValidateGetInternalFormativBase(const Context *context, return false; } - if (bufSize < 0) + if (count < 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInsufficientBufferSize); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); return false; } @@ -8480,8 +8583,8 @@ bool ValidateGetInternalFormativBase(const Context *context, if (numParams) { - // glGetInternalFormativ will not overflow bufSize - *numParams = std::min(bufSize, maxWriteParams); + // glGetInternalFormativ will not overflow count + *numParams = std::min(count, maxWriteParams); } return true; @@ -8553,7 +8656,7 @@ bool ValidateTexStorageMultisample(const Context *context, return false; } - if (static_cast(samples) > formatCaps.getMaxSamples()) + if (static_cast(samples) > formatCaps.sampleCounts.getMaxSamples()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange); return false; @@ -8679,6 +8782,14 @@ bool ValidateGetTexLevelParameterBase(const Context *context, case GL_TEXTURE_COMPRESSED: break; + case GL_MEMORY_SIZE_ANGLE: + if (!context->getExtensions().memorySizeANGLE) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumNotSupported); + return false; + } + break; + case GL_TEXTURE_DEPTH: if (context->getClientVersion() < ES_3_0 && !context->getExtensions().texture3DOES) { @@ -8771,10 +8882,8 @@ bool ValidateSampleMaskiBase(const PrivateState &state, void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint) { // An overflow can happen when adding the offset. Check against a special constant. - if (context->getStateCache().getNonInstancedVertexElementLimit() == - VertexAttribute::kIntegerOverflow || - context->getStateCache().getInstancedVertexElementLimit() == - VertexAttribute::kIntegerOverflow) + if (context->getNonInstancedVertexElementLimit() == VertexAttribute::kIntegerOverflow || + context->getInstancedVertexElementLimit() == VertexAttribute::kIntegerOverflow) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow); } @@ -8791,12 +8900,6 @@ bool ValidateLoseContextCHROMIUM(const Context *context, GraphicsResetStatus current, GraphicsResetStatus other) { - if (!context->getExtensions().loseContextCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (current) { case GraphicsResetStatus::GuiltyContextReset: @@ -8806,6 +8909,7 @@ bool ValidateLoseContextCHROMIUM(const Context *context, default: ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidResetStatus); + return false; } switch (other) @@ -8817,12 +8921,12 @@ bool ValidateLoseContextCHROMIUM(const Context *context, default: ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidResetStatus); + return false; } return true; } -// GL_ANGLE_texture_storage_external bool ValidateTexImage2DExternalANGLE(const Context *context, angle::EntryPoint entryPoint, TextureTarget target, @@ -8834,12 +8938,6 @@ bool ValidateTexImage2DExternalANGLE(const Context *context, GLenum format, GLenum type) { - if (!context->getExtensions().textureExternalUpdateANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidTexture2DDestinationTarget(context, target) && !ValidTextureExternalTarget(context, target)) { @@ -8847,7 +8945,7 @@ bool ValidateTexImage2DExternalANGLE(const Context *context, return false; } - if (context->getClientMajorVersion() <= 2) + if (context->getClientVersion() < ES_3_0) { if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat, false, false, 0, 0, width, height, border, format, @@ -8873,15 +8971,16 @@ bool ValidateInvalidateTextureANGLE(const Context *context, angle::EntryPoint entryPoint, TextureType target) { - if (!context->getExtensions().textureExternalUpdateANGLE) + if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget); return false; } - if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) + Texture *texture = context->getTextureByType(target); + if (texture != nullptr && context->getState().isTextureBoundToActivePLS(texture->id())) { - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture); return false; } diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h index 1a03433187c..469ab8615f2 100644 --- a/src/libANGLE/validationES.h +++ b/src/libANGLE/validationES.h @@ -38,8 +38,9 @@ class Shader; #define ANGLE_VALIDATION_ERROR(errorCode, message) \ context->getMutableErrorSetForValidation()->validationError(entryPoint, errorCode, message) -#define ANGLE_VALIDATION_ERRORF(errorCode, ...) \ - context->getMutableErrorSetForValidation()->validationErrorF(entryPoint, errorCode, __VA_ARGS__) +#define ANGLE_VALIDATION_ERRORF(errorCode, ...) \ + ANGLE_UNSAFE_TODO(context->getMutableErrorSetForValidation()->validationErrorF( \ + entryPoint, errorCode, __VA_ARGS__)) void SetRobustLengthParam(const GLsizei *length, GLsizei value); bool ValidTextureTarget(const Context *context, TextureType type); @@ -187,136 +188,21 @@ bool ValidateReadPixelsBase(const Context *context, GLsizei *columns, GLsizei *rows, const void *pixels); -bool ValidateReadPixelsRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLsizei bufSize, - const GLsizei *length, - const GLsizei *columns, - const GLsizei *rows, - const void *pixels); -bool ValidateReadnPixelsEXT(const Context *context, - angle::EntryPoint entryPoint, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLsizei bufSize, - const void *pixels); -bool ValidateReadnPixelsRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLsizei bufSize, - const GLsizei *length, - const GLsizei *columns, - const GLsizei *rows, - const void *data); - -bool ValidateGenQueriesEXT(const Context *context, - angle::EntryPoint entryPoint, - GLsizei n, - const QueryID *ids); -bool ValidateDeleteQueriesEXT(const Context *context, - angle::EntryPoint entryPoint, - GLsizei n, - const QueryID *ids); -bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id); bool ValidateBeginQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target, QueryID id); -bool ValidateBeginQueryEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryType target, - QueryID id); bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target); -bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target); -bool ValidateQueryCounterEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - QueryType target); bool ValidateGetQueryivBase(const Context *context, angle::EntryPoint entryPoint, QueryType target, GLenum pname, GLsizei *numParams); -bool ValidateGetQueryivEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryType target, - GLenum pname, - const GLint *params); -bool ValidateGetQueryivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - QueryType target, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLint *params); bool ValidateGetQueryObjectValueBase(const Context *context, angle::EntryPoint entryPoint, QueryID id, GLenum pname, GLsizei *numParams); -bool ValidateGetQueryObjectivEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - const GLint *params); -bool ValidateGetQueryObjectivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLint *params); -bool ValidateGetQueryObjectuivEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - const GLuint *params); -bool ValidateGetQueryObjectuivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLuint *params); -bool ValidateGetQueryObjecti64vEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - GLint64 *params); -bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - GLint64 *params); -bool ValidateGetQueryObjectui64vEXT(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - GLuint64 *params); -bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - QueryID id, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - GLuint64 *params); ANGLE_INLINE bool ValidateUniformCommonBase(const Context *context, angle::EntryPoint entryPoint, @@ -326,19 +212,19 @@ ANGLE_INLINE bool ValidateUniformCommonBase(const Context *context, const LinkedUniform **uniformOut) { // TODO(Jiajia): Add image uniform check in future. - if (count < 0) + if (ANGLE_UNLIKELY(count < 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount); return false; } - if (!program) + if (ANGLE_UNLIKELY(!program)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidProgramName); return false; } - if (!program->isLinked()) + if (ANGLE_UNLIKELY(!program->isLinked())) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kProgramNotLinked); return false; @@ -346,14 +232,13 @@ ANGLE_INLINE bool ValidateUniformCommonBase(const Context *context, if (location.value == -1) { - // Silently ignore the uniform command - return false; + return true; // no-op } const ProgramExecutable &executable = program->getExecutable(); const auto &uniformLocations = executable.getUniformLocations(); size_t castedLocation = static_cast(location.value); - if (castedLocation >= uniformLocations.size()) + if (ANGLE_UNLIKELY(castedLocation >= uniformLocations.size())) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidUniformLocation); return false; @@ -362,11 +247,10 @@ ANGLE_INLINE bool ValidateUniformCommonBase(const Context *context, const auto &uniformLocation = uniformLocations[castedLocation]; if (uniformLocation.ignored) { - // Silently ignore the uniform command - return false; + return true; // no-op } - if (!uniformLocation.used()) + if (ANGLE_UNLIKELY(!uniformLocation.used())) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidUniformLocation); return false; @@ -375,7 +259,7 @@ ANGLE_INLINE bool ValidateUniformCommonBase(const Context *context, const LinkedUniform &uniform = executable.getUniformByIndex(uniformLocation.index); // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (count > 1 && !uniform.isArray()) + if (ANGLE_UNLIKELY(count > 1) && ANGLE_UNLIKELY(!uniform.isArray())) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidUniformCount); return false; @@ -398,7 +282,8 @@ ANGLE_INLINE bool ValidateUniformValue(const Context *context, { // Check that the value type is compatible with uniform type. // Do the cheaper test first, for a little extra speed. - if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType) + if (ANGLE_UNLIKELY(valueType != uniformType) && + ANGLE_UNLIKELY(VariableBoolVectorType(valueType) != uniformType)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kUniformSizeMismatch); return false; @@ -406,6 +291,24 @@ ANGLE_INLINE bool ValidateUniformValue(const Context *context, return true; } +template +ANGLE_INLINE bool ValidateUniformValuePointer(const Context *context, + angle::EntryPoint entryPoint, + const ParamType *value) +{ + if (ANGLE_UNLIKELY(value == nullptr)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kInvalidUniformValuePointer); + return false; + } + + return true; +} + +template bool ValidateUniformValuePointer(const Context *, angle::EntryPoint, const GLfloat *); +template bool ValidateUniformValuePointer(const Context *, angle::EntryPoint, const GLint *); +template bool ValidateUniformValuePointer(const Context *, angle::EntryPoint, const GLuint *); + bool ValidateUniformMatrixValue(const Context *context, angle::EntryPoint entryPoint, GLenum valueType, @@ -421,35 +324,11 @@ bool ValidateUniformMatrix(const Context *context, UniformLocation location, GLsizei count, GLboolean transpose); -bool ValidateGetBooleanvRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLboolean *params); -bool ValidateGetFloatvRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLfloat *params); bool ValidateStateQuery(const Context *context, angle::EntryPoint entryPoint, GLenum pname, GLenum *nativeType, unsigned int *numParams); -bool ValidateGetIntegervRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLint *data); -bool ValidateGetInteger64vRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - GLint64 *data); bool ValidateRobustStateQuery(const Context *context, angle::EntryPoint entryPoint, GLenum pname, @@ -500,7 +379,7 @@ ANGLE_INLINE bool ValidateDrawBase(const Context *context, { intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesErrorString( context, &context->getPrivateStateCache()); - if (drawStatesError) + if (ANGLE_UNLIKELY(drawStatesError)) { const char *errorMessage = reinterpret_cast(drawStatesError); GLenum errorCode = context->getStateCache().getBasicDrawElementsErrorCode(); @@ -508,7 +387,7 @@ ANGLE_INLINE bool ValidateDrawBase(const Context *context, return false; } - if (!context->getStateCache().isValidDrawMode(mode)) + if (ANGLE_UNLIKELY(!context->getStateCache().isValidDrawMode(mode))) { RecordDrawModeError(context, entryPoint, mode); return false; @@ -524,18 +403,6 @@ bool ValidateDrawArraysInstancedBase(const Context *context, GLsizei count, GLsizei primcount, GLuint baseinstance); -bool ValidateDrawArraysInstancedANGLE(const Context *context, - angle::EntryPoint entryPoint, - PrimitiveMode mode, - GLint first, - GLsizei count, - GLsizei primcount); -bool ValidateDrawArraysInstancedEXT(const Context *context, - angle::EntryPoint entryPoint, - PrimitiveMode mode, - GLint first, - GLsizei count, - GLsizei primcount); bool ValidateDrawElementsInstancedBase(const Context *context, angle::EntryPoint entryPoint, @@ -545,20 +412,6 @@ bool ValidateDrawElementsInstancedBase(const Context *context, const void *indices, GLsizei primcount, GLuint baseinstance); -bool ValidateDrawElementsInstancedANGLE(const Context *context, - angle::EntryPoint entryPoint, - PrimitiveMode mode, - GLsizei count, - DrawElementsType type, - const void *indices, - GLsizei primcount); -bool ValidateDrawElementsInstancedEXT(const Context *context, - angle::EntryPoint entryPoint, - PrimitiveMode mode, - GLsizei count, - DrawElementsType type, - const void *indices, - GLsizei primcount); bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint); @@ -572,60 +425,6 @@ bool ValidateSizedGetUniform(const Context *context, UniformLocation location, GLsizei bufSize, GLsizei *length); -bool ValidateGetnUniformfvEXT(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLfloat *params); -bool ValidateGetnUniformfvRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLsizei *length, - const GLfloat *params); -bool ValidateGetnUniformivEXT(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLint *params); -bool ValidateGetnUniformivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLsizei *length, - const GLint *params); -bool ValidateGetnUniformuivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLsizei *length, - const GLuint *params); -bool ValidateGetUniformfvRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLsizei *length, - const GLfloat *params); -bool ValidateGetUniformivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLsizei *length, - const GLint *params); -bool ValidateGetUniformuivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID program, - UniformLocation location, - GLsizei bufSize, - const GLsizei *length, - const GLuint *params); bool ValidateDiscardFramebufferBase(const Context *context, angle::EntryPoint entryPoint, @@ -634,26 +433,10 @@ bool ValidateDiscardFramebufferBase(const Context *context, const GLenum *attachments, bool defaultFramebuffer); -bool ValidateInsertEventMarkerEXT(const Context *context, - angle::EntryPoint entryPoint, - GLsizei length, - const char *marker); -bool ValidatePushGroupMarkerEXT(const Context *context, - angle::EntryPoint entryPoint, - GLsizei length, - const char *marker); bool ValidateEGLImageObject(const Context *context, angle::EntryPoint entryPoint, TextureType type, egl::ImageID image); -bool ValidateEGLImageTargetTexture2DOES(const Context *context, - angle::EntryPoint entryPoint, - TextureType type, - egl::ImageID image); -bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context, - angle::EntryPoint entryPoint, - GLenum target, - egl::ImageID image); bool ValidateProgramBinaryBase(const Context *context, angle::EntryPoint entryPoint, @@ -695,7 +478,7 @@ bool ValidateFlushMappedBufferRangeBase(const Context *context, GLintptr offset, GLsizeiptr length); -bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n); +bool ValidateGenOrDelete(ErrorSet *errors, angle::EntryPoint entryPoint, GLint n, const void *ids); bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, @@ -763,45 +546,47 @@ bool ValidateGetVertexAttribBase(const Context *context, GLuint index, GLenum pname, GLsizei *length, - bool pointer, - bool pureIntegerEntryPoint); + bool pointer); -ANGLE_INLINE bool ValidateVertexFormat(const Context *context, +ANGLE_INLINE bool ValidateVertexFormat(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLint size, VertexAttribTypeCase validation) { - const Caps &caps = context->getCaps(); - if (index >= static_cast(caps.maxVertexAttributes)) + const Caps &caps = privateState.getCaps(); + if (ANGLE_UNLIKELY(index >= static_cast(caps.maxVertexAttributes))) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute); + errors->validationError(entryPoint, GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute); return false; } switch (validation) { case VertexAttribTypeCase::Invalid: - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kInvalidType); + errors->validationError(entryPoint, GL_INVALID_ENUM, err::kInvalidType); return false; case VertexAttribTypeCase::Valid: if (size < 1 || size > 4) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kInvalidVertexAttrSize); + errors->validationError(entryPoint, GL_INVALID_VALUE, err::kInvalidVertexAttrSize); return false; } break; case VertexAttribTypeCase::ValidSize4Only: if (size != 4) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexAttribSize2101010); + errors->validationError(entryPoint, GL_INVALID_OPERATION, + err::kInvalidVertexAttribSize2101010); return false; } break; case VertexAttribTypeCase::ValidSize3or4: if (size != 3 && size != 4) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexAttribSize1010102); + errors->validationError(entryPoint, GL_INVALID_OPERATION, + err::kInvalidVertexAttribSize1010102); return false; } break; @@ -811,25 +596,28 @@ ANGLE_INLINE bool ValidateVertexFormat(const Context *context, } // Note: These byte, short, and int types are all converted to float for the shader. -ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context, +ANGLE_INLINE bool ValidateFloatVertexFormat(const PrivateState &privateState, + const PrivateStateCache &privateStateCache, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLint size, VertexAttribType type) { - return ValidateVertexFormat(context, entryPoint, index, size, - context->getStateCache().getVertexAttribTypeValidation(type)); + return ValidateVertexFormat(privateState, errors, entryPoint, index, size, + privateStateCache.getVertexAttribTypeValidation(type)); } -ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context, +ANGLE_INLINE bool ValidateIntegerVertexFormat(const PrivateState &privateState, + const PrivateStateCache &privateStateCache, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLint size, VertexAttribType type) { - return ValidateVertexFormat( - context, entryPoint, index, size, - context->getStateCache().getIntegerVertexAttribTypeValidation(type)); + return ValidateVertexFormat(privateState, errors, entryPoint, index, size, + privateStateCache.getIntegerVertexAttribTypeValidation(type)); } ANGLE_INLINE bool ValidateColorMasksForSharedExponentColorBuffers(const BlendStateExt &blendState, @@ -868,11 +656,13 @@ bool ValidateGetActiveUniformBlockivBase(const Context *context, GLenum pname, GLsizei *length); +template bool ValidateGetSamplerParameterBase(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler, GLenum pname, - GLsizei *length); + GLsizei *length, + const ParamType *params); template bool ValidateSamplerParameterBase(const Context *context, @@ -888,7 +678,7 @@ bool ValidateGetInternalFormativBase(const Context *context, GLenum target, GLenum internalformat, GLenum pname, - GLsizei bufSize, + GLsizei count, GLsizei *numParams); bool ValidateFramebufferNotMultisampled(const Context *context, @@ -1028,7 +818,7 @@ ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context, const Framebuffer *framebuffer) { const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context); - if (!framebufferStatus.isComplete()) + if (ANGLE_UNLIKELY(!framebufferStatus.isComplete())) { ASSERT(framebufferStatus.reason != nullptr); ANGLE_VALIDATION_ERROR(ErrorCode, framebufferStatus.reason); @@ -1054,8 +844,8 @@ ANGLE_INLINE bool ValidateDrawAttribs(const Context *context, // For non-instanced attributes, the maximum vertex must be accessible in the attribute buffers. // For instanced attributes, in non-instanced draw calls only attribute 0 is accessed. In // instanced draw calls, the instance limit is checked in ValidateDrawInstancedAttribs. - if (maxVertex >= context->getStateCache().getNonInstancedVertexElementLimit() || - context->getStateCache().getInstancedVertexElementLimit() < 1) + if (ANGLE_UNLIKELY(maxVertex >= context->getNonInstancedVertexElementLimit()) || + ANGLE_UNLIKELY(context->getInstancedVertexElementLimit() < 1)) { RecordDrawAttribsError(context, entryPoint); return false; @@ -1081,7 +871,7 @@ ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context, ASSERT(first >= 0); ASSERT(count > 0); int64_t maxVertex = static_cast(first) + static_cast(count) - 1; - if (maxVertex > static_cast(std::numeric_limits::max())) + if (ANGLE_UNLIKELY(maxVertex > static_cast(std::numeric_limits::max()))) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow); return false; @@ -1095,7 +885,7 @@ ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context, GLint primcount, GLuint baseinstance) { - if (!context->isBufferAccessValidationEnabled()) + if (ANGLE_LIKELY(!context->isBufferAccessValidationEnabled())) { return true; } @@ -1103,7 +893,7 @@ ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context, // Validate that the buffers bound for the attributes can hold enough vertices for this // instanced draw. For attributes with a divisor of 0, ValidateDrawAttribs already checks this. // Thus, the following only checks attributes with a non-zero divisor (i.e. "instanced"). - const GLint64 limit = context->getStateCache().getInstancedVertexElementLimit(); + const GLint64 limit = context->getInstancedVertexElementLimit(); if (baseinstance >= limit || primcount > limit - baseinstance) { RecordDrawAttribsError(context, entryPoint); @@ -1120,7 +910,7 @@ ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context, GLsizei count, GLsizei primcount) { - if (first < 0) + if (ANGLE_UNLIKELY(first < 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeStart); return false; @@ -1128,7 +918,7 @@ ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context, if (count <= 0) { - if (count < 0) + if (ANGLE_UNLIKELY(count < 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount); return false; @@ -1140,7 +930,7 @@ ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context, if (primcount <= 0) { - if (primcount < 0) + if (ANGLE_UNLIKELY(primcount < 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount); return false; @@ -1149,13 +939,13 @@ ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context, return ValidateDrawBase(context, entryPoint, mode); } - if (!ValidateDrawBase(context, entryPoint, mode)) + if (ANGLE_UNLIKELY(!ValidateDrawBase(context, entryPoint, mode))) { return false; } - if (context->getStateCache().isTransformFeedbackActiveUnpaused() && - !context->supportsGeometryOrTesselation()) + if (ANGLE_UNLIKELY(context->getStateCache().isTransformFeedbackActiveUnpaused()) && + ANGLE_UNLIKELY(!context->supportsGeometryOrTesselation())) { const State &state = context->getState(); TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); @@ -1174,7 +964,7 @@ ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context, PrimitiveMode mode, DrawElementsType type) { - if (!context->getStateCache().isValidDrawElementsType(type)) + if (ANGLE_UNLIKELY(!context->getStateCache().isValidDrawElementsType(type))) { if (type == DrawElementsType::UnsignedInt) { @@ -1187,8 +977,15 @@ ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context, return false; } - intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context); - if (drawElementsError) + intptr_t drawElementsError; + if (!context->getPrivateStateCache().isCachedBasicDrawElementsErrorValid()) + { + context->getPrivateStateCache().updateBasicDrawElementsError( + reinterpret_cast(ValidateDrawElementsStates(context))); + } + drawElementsError = context->getPrivateStateCache().getBasicDrawElementsError(); + + if (ANGLE_UNLIKELY(drawElementsError)) { // All errors from ValidateDrawElementsStates return INVALID_OPERATION. const char *errorMessage = reinterpret_cast(drawElementsError); @@ -1208,7 +1005,7 @@ ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, const void *indices, GLsizei primcount) { - if (!ValidateDrawElementsBase(context, entryPoint, mode, type)) + if (ANGLE_UNLIKELY(!ValidateDrawElementsBase(context, entryPoint, mode, type))) { return false; } @@ -1222,7 +1019,8 @@ ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, if (elementArrayBuffer != nullptr) { - if ((reinterpret_cast(indices) & static_cast(typeBytes - 1)) != 0) + if (ANGLE_UNLIKELY((reinterpret_cast(indices) & + static_cast(typeBytes - 1)) != 0)) { // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements: // The offset arguments to drawElements and [...], must be a multiple of the size of the @@ -1238,7 +1036,7 @@ ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE // error is generated. - if (reinterpret_cast(indices) < 0) + if (ANGLE_UNLIKELY(reinterpret_cast(indices) < 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeOffset); return false; @@ -1247,7 +1045,7 @@ ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, if (count <= 0) { - if (count < 0) + if (ANGLE_UNLIKELY(count < 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount); return false; @@ -1257,14 +1055,14 @@ ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, return ValidateDrawBase(context, entryPoint, mode); } - if (!ValidateDrawBase(context, entryPoint, mode)) + if (ANGLE_UNLIKELY(!ValidateDrawBase(context, entryPoint, mode))) { return false; } if (!elementArrayBuffer) { - if (!indices) + if (ANGLE_UNLIKELY(!indices)) { // This is an application error that would normally result in a crash, but we catch // it and return an error @@ -1291,45 +1089,49 @@ ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, // The offset can be any value, check for overflows uint64_t offset = static_cast(reinterpret_cast(indices)); uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset; - if (elementDataSizeWithOffset < elementDataSizeNoOffset) + if (ANGLE_UNLIKELY(elementDataSizeWithOffset < elementDataSizeNoOffset)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow); return false; } // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064 - if ((elementDataSizeWithOffset > static_cast(elementArrayBuffer->getSize())) && - (primcount > 0)) + if (ANGLE_UNLIKELY(elementDataSizeWithOffset > + static_cast(elementArrayBuffer->getSize())) && + ANGLE_UNLIKELY(primcount > 0)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInsufficientBufferSize); return false; } } - if (context->isBufferAccessValidationEnabled() && primcount > 0) + if (ANGLE_UNLIKELY(context->isBufferAccessValidationEnabled()) && ANGLE_UNLIKELY(primcount > 0)) { // Use the parameter buffer to retrieve and cache the index range. // TODO: this calculation should take basevertex into account for // glDrawElementsInstancedBaseVertexBaseInstanceEXT. http://anglebug.com/41481166 IndexRange indexRange{IndexRange::Undefined()}; - ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange)); + ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, + context->getState().isPrimitiveRestartEnabled(), + &indexRange)); - // If we use an index greater than our maximum supported index range, return an error. - // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should - // always return an error if possible here. - if (static_cast(indexRange.end) >= context->getCaps().maxElementIndex) + // No op if there are no real indices in the index data (all are primitive restart). + if (!indexRange.isEmpty()) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kExceedsMaxElement); - return false; - } + // If we use an index greater than our maximum supported index range, return an error. + // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should + // always return an error if possible here. + if (static_cast(indexRange.end()) >= context->getCaps().maxElementIndex) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kExceedsMaxElement); + return false; + } - if (!ValidateDrawAttribs(context, entryPoint, static_cast(indexRange.end))) - { - return false; + if (!ValidateDrawAttribs(context, entryPoint, static_cast(indexRange.end()))) + { + return false; + } } - - // No op if there are no real indices in the index data (all are primitive restart). - return (indexRange.vertexIndexCount > 0); } return true; @@ -1339,7 +1141,7 @@ ANGLE_INLINE bool ValidateBindVertexArrayBase(const Context *context, angle::EntryPoint entryPoint, VertexArrayID array) { - if (!context->isVertexArrayGenerated(array)) + if (ANGLE_UNLIKELY(!context->getPrivateState().isVertexArrayGenerated(array))) { // The default VAO should always exist ASSERT(array.value != 0); @@ -1355,7 +1157,7 @@ ANGLE_INLINE bool ValidateVertexAttribIndex(const PrivateState &state, angle::EntryPoint entryPoint, GLuint index) { - if (index >= static_cast(state.getCaps().maxVertexAttributes)) + if (ANGLE_UNLIKELY(index >= static_cast(state.getCaps().maxVertexAttributes))) { errors->validationError(entryPoint, GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute); return false; diff --git a/src/libANGLE/validationES1.cpp b/src/libANGLE/validationES1.cpp index 3f1dbf4a26b..a98ae0d9a2e 100644 --- a/src/libANGLE/validationES1.cpp +++ b/src/libANGLE/validationES1.cpp @@ -6,6 +6,10 @@ // validationES1.cpp: Validation functions for OpenGL ES 1.0 entry point parameters +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/validationES1_autogen.h" #include "common/debug.h" @@ -16,24 +20,15 @@ #include "libANGLE/queryutils.h" #include "libANGLE/validationES.h" -#define ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint) \ - do \ - { \ - if (state.getClientMajorVersion() > 1) \ - { \ - errors->validationError(entryPoint, GL_INVALID_OPERATION, kGLES1Only); \ - return false; \ - } \ - } while (0) - -#define ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint) \ - ANGLE_VALIDATE_IS_GLES1(context->getPrivateState(), \ - context->getMutableErrorSetForValidation(), entryPoint) - namespace gl { using namespace err; +void RecordVersionErrorES10(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES10); +} + bool ValidateAlphaFuncCommon(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, @@ -60,7 +55,6 @@ bool ValidateClientStateCommon(const Context *context, angle::EntryPoint entryPoint, ClientVertexArrayType arrayType) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); switch (arrayType) { case ClientVertexArrayType::Vertex: @@ -89,8 +83,6 @@ bool ValidateBuiltinVertexAttributeCommon(const Context *context, GLsizei stride, const void *pointer) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); - if (stride < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidVertexPointerStride); @@ -192,9 +184,6 @@ bool ValidateLightCommon(const PrivateState &state, LightParameter pname, const GLfloat *params) { - - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - if (!ValidateLightCaps(state, errors, entryPoint, light)) { return false; @@ -297,8 +286,6 @@ bool ValidateMaterialSetting(const PrivateState &state, MaterialParameter pname, const GLfloat *params) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - if (face != GL_FRONT_AND_BACK) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMaterialFace); @@ -314,8 +301,6 @@ bool ValidateMaterialQuery(const PrivateState &state, GLenum face, MaterialParameter pname) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - if (face != GL_FRONT && face != GL_BACK) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMaterialFace); @@ -353,7 +338,6 @@ bool ValidateLightModelCommon(const PrivateState &state, angle::EntryPoint entryPoint, GLenum pname) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); switch (pname) { case GL_LIGHT_MODEL_AMBIENT: @@ -390,8 +374,6 @@ bool ValidateClipPlaneCommon(const PrivateState &state, angle::EntryPoint entryPoint, GLenum plane) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + state.getCaps().maxClipPlanes) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidClipPlane); @@ -407,8 +389,6 @@ bool ValidateFogCommon(const PrivateState &state, GLenum pname, const GLfloat *params) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - switch (pname) { case GL_FOG_MODE: @@ -450,8 +430,6 @@ bool ValidateTexEnvCommon(const PrivateState &state, TextureEnvParameter pname, const GLfloat *params) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - switch (target) { case TextureEnvTarget::Env: @@ -648,8 +626,6 @@ bool ValidatePointParameterCommon(const PrivateState &state, PointParameter pname, const GLfloat *params) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - switch (pname) { case PointParameter::PointSizeMin: @@ -679,8 +655,6 @@ bool ValidatePointSizeCommon(const PrivateState &state, angle::EntryPoint entryPoint, GLfloat size) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - if (size <= 0.0f) { errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPointSizeValue); @@ -695,8 +669,6 @@ bool ValidateDrawTexCommon(const Context *context, float width, float height) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); - if (width <= 0.0f || height <= 0.0f) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNonPositiveDrawTextureDimension); @@ -717,7 +689,6 @@ bool ValidateAlphaFunc(const PrivateState &state, AlphaTestFunc func, GLfloat ref) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return ValidateAlphaFuncCommon(state, errors, entryPoint, func); } @@ -727,7 +698,6 @@ bool ValidateAlphaFuncx(const PrivateState &state, AlphaTestFunc func, GLfixed ref) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return ValidateAlphaFuncCommon(state, errors, entryPoint, func); } @@ -739,7 +709,6 @@ bool ValidateClearColorx(const PrivateState &state, GLfixed blue, GLfixed alpha) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -748,7 +717,6 @@ bool ValidateClearDepthx(const PrivateState &state, angle::EntryPoint entryPoint, GLfixed depth) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -756,7 +724,6 @@ bool ValidateClientActiveTexture(const Context *context, angle::EntryPoint entryPoint, GLenum texture) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); return ValidateMultitextureUnit(context->getPrivateState(), context->getMutableErrorSetForValidation(), entryPoint, texture); @@ -788,7 +755,6 @@ bool ValidateColor4f(const PrivateState &state, GLfloat blue, GLfloat alpha) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -800,7 +766,6 @@ bool ValidateColor4ub(const PrivateState &state, GLubyte blue, GLubyte alpha) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -812,7 +777,6 @@ bool ValidateColor4x(const PrivateState &state, GLfixed blue, GLfixed alpha) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -827,28 +791,12 @@ bool ValidateColorPointer(const Context *context, size, type, stride, pointer); } -bool ValidateCullFace(const PrivateState &state, - ErrorSet *errors, - angle::EntryPoint entryPoint, - GLenum mode) -{ - UNIMPLEMENTED(); - return true; -} - bool ValidateDepthRangex(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, GLfixed n, GLfixed f) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); - if (state.isWebGL() && n > f) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDepthRange); - return false; - } - return true; } @@ -890,7 +838,6 @@ bool ValidateFogx(const PrivateState &state, GLenum pname, GLfixed param) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); GLfloat asFloat = pname == GL_FOG_MODE ? static_cast(param) : ConvertFixedToFloat(param); return ValidateFogCommon(state, errors, entryPoint, pname, &asFloat); @@ -902,7 +849,6 @@ bool ValidateFogxv(const PrivateState &state, GLenum pname, const GLfixed *params) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); unsigned int paramCount = GetFogParameterCount(pname); GLfloat paramsf[4] = {}; @@ -931,7 +877,6 @@ bool ValidateFrustumf(const PrivateState &state, GLfloat n, GLfloat f) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); if (l == r || b == t || n == f || n <= 0.0f || f <= 0.0f) { errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix); @@ -950,7 +895,6 @@ bool ValidateFrustumx(const PrivateState &state, GLfixed n, GLfixed f) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); if (l == r || b == t || n == f || n <= 0 || f <= 0) { errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix); @@ -959,16 +903,6 @@ bool ValidateFrustumx(const PrivateState &state, return true; } -bool ValidateGetBufferParameteriv(const Context *context, - angle::EntryPoint entryPoint, - GLenum target, - GLenum pname, - const GLint *params) -{ - UNIMPLEMENTED(); - return true; -} - bool ValidateGetClipPlanef(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, @@ -992,7 +926,6 @@ bool ValidateGetFixedv(const Context *context, GLenum pname, const GLfixed *params) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); GLenum nativeType; unsigned int numParams = 0; return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); @@ -1076,14 +1009,7 @@ bool ValidateGetTexParameterxv(const Context *context, GLenum pname, const GLfixed *params) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); - - if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr)) - { - return false; - } - - return true; + return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); } bool ValidateLightModelf(const PrivateState &state, @@ -1174,7 +1100,6 @@ bool ValidateLineWidthx(const PrivateState &state, angle::EntryPoint entryPoint, GLfixed width) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); if (width <= 0) { errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidWidth); @@ -1186,7 +1111,6 @@ bool ValidateLineWidthx(const PrivateState &state, bool ValidateLoadIdentity(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1195,7 +1119,6 @@ bool ValidateLoadMatrixf(const PrivateState &state, angle::EntryPoint entryPoint, const GLfloat *m) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1204,7 +1127,6 @@ bool ValidateLoadMatrixx(const PrivateState &state, angle::EntryPoint entryPoint, const GLfixed *m) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1213,7 +1135,6 @@ bool ValidateLogicOp(const PrivateState &state, angle::EntryPoint entryPoint, LogicalOperation opcode) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return ValidateLogicOpCommon(state, errors, entryPoint, opcode); } @@ -1270,7 +1191,6 @@ bool ValidateMatrixMode(const PrivateState &state, angle::EntryPoint entryPoint, MatrixType mode) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); switch (mode) { case MatrixType::Projection: @@ -1288,7 +1208,6 @@ bool ValidateMultMatrixf(const PrivateState &state, angle::EntryPoint entryPoint, const GLfloat *m) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1297,7 +1216,6 @@ bool ValidateMultMatrixx(const PrivateState &state, angle::EntryPoint entryPoint, const GLfixed *m) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1310,7 +1228,6 @@ bool ValidateMultiTexCoord4f(const PrivateState &state, GLfloat r, GLfloat q) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return ValidateMultitextureUnit(state, errors, entryPoint, target); } @@ -1323,7 +1240,6 @@ bool ValidateMultiTexCoord4x(const PrivateState &state, GLfixed r, GLfixed q) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return ValidateMultitextureUnit(state, errors, entryPoint, target); } @@ -1334,7 +1250,6 @@ bool ValidateNormal3f(const PrivateState &state, GLfloat ny, GLfloat nz) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1345,7 +1260,6 @@ bool ValidateNormal3x(const PrivateState &state, GLfixed ny, GLfixed nz) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1369,7 +1283,6 @@ bool ValidateOrthof(const PrivateState &state, GLfloat n, GLfloat f) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); // [OpenGL ES 1.1.12] section 2.10.2 page 31: // If l is equal to r, b is equal to t, or n is equal to f, the // error INVALID VALUE results. @@ -1391,7 +1304,6 @@ bool ValidateOrthox(const PrivateState &state, GLfixed n, GLfixed f) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); if (l == r || b == t || n == f) { errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix); @@ -1478,13 +1390,11 @@ bool ValidatePolygonOffsetx(const PrivateState &state, GLfixed factor, GLfixed units) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } bool ValidatePopMatrix(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); const auto &stack = state.gles1().currentMatrixStack(); if (stack.size() == 1) { @@ -1496,7 +1406,6 @@ bool ValidatePopMatrix(const PrivateState &state, ErrorSet *errors, angle::Entry bool ValidatePushMatrix(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); const auto &stack = state.gles1().currentMatrixStack(); if (stack.size() == stack.max_size()) { @@ -1514,7 +1423,6 @@ bool ValidateRotatef(const PrivateState &state, GLfloat y, GLfloat z) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1526,7 +1434,6 @@ bool ValidateRotatex(const PrivateState &state, GLfixed y, GLfixed z) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1536,7 +1443,6 @@ bool ValidateSampleCoveragex(const PrivateState &state, GLclampx value, GLboolean invert) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1547,7 +1453,6 @@ bool ValidateScalef(const PrivateState &state, GLfloat y, GLfloat z) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1558,7 +1463,6 @@ bool ValidateScalex(const PrivateState &state, GLfixed y, GLfixed z) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1567,7 +1471,6 @@ bool ValidateShadeModel(const PrivateState &state, angle::EntryPoint entryPoint, ShadingModel mode) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); switch (mode) { case ShadingModel::Flat: @@ -1643,7 +1546,6 @@ bool ValidateTexEnvx(const PrivateState &state, TextureEnvParameter pname, GLfixed param) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); GLfloat paramsf[4] = {}; ConvertTextureEnvFromFixed(pname, ¶m, paramsf); return ValidateTexEnvCommon(state, errors, entryPoint, target, pname, paramsf); @@ -1656,7 +1558,6 @@ bool ValidateTexEnvxv(const PrivateState &state, TextureEnvParameter pname, const GLfixed *params) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); GLfloat paramsf[4] = {}; ConvertTextureEnvFromFixed(pname, params, paramsf); return ValidateTexEnvCommon(state, errors, entryPoint, target, pname, paramsf); @@ -1693,7 +1594,6 @@ bool ValidateTexParameterx(const Context *context, GLenum pname, GLfixed param) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); return ValidateTexParameterBaseForGLfixed(context, entryPoint, target, pname, -1, false, ¶m); } @@ -1704,7 +1604,6 @@ bool ValidateTexParameterxv(const Context *context, GLenum pname, const GLfixed *params) { - ANGLE_VALIDATE_IS_GLES1_CONTEXT(context, entryPoint); return ValidateTexParameterBaseForGLfixed(context, entryPoint, target, pname, -1, true, params); } @@ -1715,7 +1614,6 @@ bool ValidateTranslatef(const PrivateState &state, GLfloat y, GLfloat z) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1726,7 +1624,6 @@ bool ValidateTranslatex(const PrivateState &state, GLfixed y, GLfixed z) { - ANGLE_VALIDATE_IS_GLES1(state, errors, entryPoint); return true; } @@ -1877,13 +1774,8 @@ bool ValidateGenFramebuffersOES(const Context *context, GLsizei n, const FramebufferID *framebuffers) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + framebuffers); } bool ValidateDeleteFramebuffersOES(const Context *context, @@ -1891,13 +1783,8 @@ bool ValidateDeleteFramebuffersOES(const Context *context, GLsizei n, const FramebufferID *framebuffers) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + framebuffers); } bool ValidateGenRenderbuffersOES(const Context *context, @@ -1905,13 +1792,8 @@ bool ValidateGenRenderbuffersOES(const Context *context, GLsizei n, const RenderbufferID *renderbuffers) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + renderbuffers); } bool ValidateDeleteRenderbuffersOES(const Context *context, @@ -1919,13 +1801,8 @@ bool ValidateDeleteRenderbuffersOES(const Context *context, GLsizei n, const RenderbufferID *renderbuffers) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + renderbuffers); } bool ValidateBindFramebufferOES(const Context *context, @@ -1933,12 +1810,6 @@ bool ValidateBindFramebufferOES(const Context *context, GLenum target, FramebufferID framebuffer) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBindFramebufferBase(context, entryPoint, target, framebuffer); } @@ -1947,12 +1818,6 @@ bool ValidateBindRenderbufferOES(const Context *context, GLenum target, RenderbufferID renderbuffer) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBindRenderbufferBase(context, entryPoint, target, renderbuffer); } @@ -1960,12 +1825,6 @@ bool ValidateCheckFramebufferStatusOES(const Context *context, angle::EntryPoint entryPoint, GLenum target) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidFramebufferTarget(context, target)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget); @@ -1982,12 +1841,6 @@ bool ValidateFramebufferRenderbufferOES(const Context *context, GLenum rbtarget, RenderbufferID renderbuffer) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateFramebufferRenderbufferBase(context, entryPoint, target, attachment, rbtarget, renderbuffer); } @@ -2000,12 +1853,6 @@ bool ValidateFramebufferTexture2DOES(const Context *context, TextureID texture, GLint level) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (level != 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel); @@ -2080,12 +1927,6 @@ bool ValidateGenerateMipmapOES(const Context *context, angle::EntryPoint entryPoint, TextureType target) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGenerateMipmapBase(context, entryPoint, target); } @@ -2096,12 +1937,6 @@ bool ValidateGetFramebufferAttachmentParameterivOES(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment, pname, nullptr); } @@ -2112,12 +1947,6 @@ bool ValidateGetRenderbufferParameterivOES(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, nullptr); } @@ -2125,12 +1954,6 @@ bool ValidateIsFramebufferOES(const Context *context, angle::EntryPoint entryPoint, FramebufferID framebuffer) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -2138,12 +1961,6 @@ bool ValidateIsRenderbufferOES(const Context *context, angle::EntryPoint entryPoint, RenderbufferID renderbuffer) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -2154,12 +1971,6 @@ bool ValidateRenderbufferStorageOES(const Context *context, GLsizei width, GLsizei height) { - if (!context->getExtensions().framebufferObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, 0, internalformat, width, height); } diff --git a/src/libANGLE/validationES1.h b/src/libANGLE/validationES1.h index e2e62484007..6585199de7a 100644 --- a/src/libANGLE/validationES1.h +++ b/src/libANGLE/validationES1.h @@ -14,7 +14,9 @@ namespace gl { -// Nothing here yet. + +void RecordVersionErrorES10(const Context *context, angle::EntryPoint entryPoint); + } // namespace gl #endif // LIBANGLE_VALIDATION_ES1_H_ diff --git a/src/libANGLE/validationES1_autogen.h b/src/libANGLE/validationES1_autogen.h index 74301c76871..81835037650 100644 --- a/src/libANGLE/validationES1_autogen.h +++ b/src/libANGLE/validationES1_autogen.h @@ -18,6 +18,7 @@ namespace gl { class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; bool ValidateAlphaFunc(const PrivateState &state, diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp index df1efd1a8d4..66f70c893f7 100644 --- a/src/libANGLE/validationES2.cpp +++ b/src/libANGLE/validationES2.cpp @@ -6,6 +6,10 @@ // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/validationES2_autogen.h" #include @@ -13,6 +17,7 @@ #include "common/BinaryStream.h" #include "common/angle_version_info.h" #include "common/mathutil.h" +#include "common/span.h" #include "common/string_utils.h" #include "common/utilities.h" #include "libANGLE/Context.h" @@ -36,6 +41,11 @@ namespace gl { using namespace err; +void RecordVersionErrorES20(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES20); +} + namespace { @@ -73,6 +83,8 @@ bool IsPartialBlit(const Context *context, bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat) { // Table 1.1 from the CHROMIUM_copy_texture spec + // No extension checks for the source formats because the texture has already been created and + // passed validation. switch (GetUnsizedFormat(internalFormat)) { case GL_RED: @@ -86,6 +98,14 @@ bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat) case GL_BGRA_EXT: case GL_BGRA8_EXT: case GL_SRGB_ALPHA_EXT: + case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE: + case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE: + case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE: + case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE: + case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE: + case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE: + case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE: + case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE: return true; default: @@ -104,8 +124,8 @@ bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat) switch (internalFormat) { case GL_ALPHA: - case GL_BGRA8_EXT: case GL_BGRA_EXT: + case GL_BGRA8_EXT: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_R11F_G11F_B10F: @@ -237,18 +257,11 @@ bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLi } bool IsValidCopyTextureDestinationLevel(const Context *context, - angle::EntryPoint entryPoint, TextureType type, GLint level, GLsizei width, - GLsizei height, - bool isSubImage) + GLsizei height) { - if (!ValidImageSizeParameters(context, entryPoint, type, level, width, height, 1, isSubImage)) - { - return false; - } - const Caps &caps = context->getCaps(); switch (type) { @@ -411,7 +424,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, case GL_ALPHA: if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && - colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_BGR5_A1_ANGLEX && !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat); @@ -422,8 +436,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA_EXT && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { @@ -437,8 +451,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F && colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F && - colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA_EXT && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { @@ -451,8 +465,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F && - colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA_EXT && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { @@ -464,7 +478,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F && - colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA_EXT && + colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) @@ -478,7 +493,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, case GL_BGRA_EXT: if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F && - colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_BGR5_A1_ANGLEX && !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat); @@ -503,8 +519,9 @@ bool ValidateES2CopyTexImageParameters(const Context *context, case GL_ALPHA: case GL_ALPHA8_OES: if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA_EXT && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX && !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat); @@ -517,8 +534,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && - colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { @@ -529,8 +546,9 @@ bool ValidateES2CopyTexImageParameters(const Context *context, case GL_RG_EXT: if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA_EXT && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { @@ -543,8 +561,8 @@ bool ValidateES2CopyTexImageParameters(const Context *context, case GL_RGB8_OES: if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && - colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { @@ -561,8 +579,9 @@ bool ValidateES2CopyTexImageParameters(const Context *context, case GL_RGB5_A1_OES: case GL_RGBA8_OES: if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && - colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_RGBA16F && + colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && + colorbufferFormat != GL_RGBA16F && !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat); @@ -575,8 +594,7 @@ bool ValidateES2CopyTexImageParameters(const Context *context, } } - // If width or height is zero, it is a no-op. Return false without setting an error. - return (width > 0 && height > 0); + return true; } // ANGLE_shader_pixel_local_storage: INVALID_OPERATION is generated by Enable(), Disable() if @@ -597,6 +615,7 @@ static bool IsCapBannedWithActivePLS(GLenum cap) case GL_POLYGON_OFFSET_LINE_NV: // = GL_POLYGON_OFFSET_LINE_ANGLE case GL_POLYGON_OFFSET_FILL: case GL_PRIMITIVE_RESTART_FIXED_INDEX: + case GL_RASTERIZER_DISCARD: case GL_SCISSOR_TEST: case GL_SCISSOR_TEST_EXCLUSIVE_NV: case GL_STENCIL_TEST: @@ -638,7 +657,7 @@ bool ValidCapUncommon(const PrivateState &state, ErrorSet *errors, GLenum cap, b case GL_PRIMITIVE_RESTART_FIXED_INDEX: case GL_RASTERIZER_DISCARD: - return (state.getClientMajorVersion() >= 3); + return state.getClientVersion() >= ES_3_0; case GL_DEBUG_OUTPUT_SYNCHRONOUS: case GL_DEBUG_OUTPUT: @@ -694,15 +713,14 @@ bool ValidCapUncommon(const PrivateState &state, ErrorSet *errors, GLenum cap, b return queryOnly && state.getExtensions().shaderFramebufferFetchARM; case GL_BLEND_ADVANCED_COHERENT_KHR: - return state.getClientVersion() >= Version(2, 0) && - state.getExtensions().blendEquationAdvancedCoherentKHR; + return state.getExtensions().blendEquationAdvancedCoherentKHR; default: break; } // GLES1 emulation: GLES1-specific caps after this point - if (state.getClientVersion().major != 1) + if (state.getClientVersion() >= ES_2_0) { return false; } @@ -796,41 +814,29 @@ bool IsValidESSLString(const char *str, size_t len) return true; } -bool ValidateWebGLNamePrefix(const Context *context, - angle::EntryPoint entryPoint, - const GLchar *name) +bool ValidateWebGLName(const Context *context, angle::EntryPoint entryPoint, const char *name) { ASSERT(context->isWebGL()); + const bool isWebGL1 = context->getClientVersion() < ES_3_0; - // WebGL 1.0 [Section 6.16] GLSL Constructs - // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL. - if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kWebglBindAttribLocationReservedPrefix); - return false; - } - - return true; -} + // WebGL imposes a limit on the lengths of uniform and attribute locations. + const size_t maxLength = isWebGL1 ? 256 : 1024; + const size_t length = strlen(name); -bool ValidateWebGLNameLength(const Context *context, angle::EntryPoint entryPoint, size_t length) -{ - ASSERT(context->isWebGL()); - - if (context->isWebGL1() && length > 256) + // Do not validate uniform name length because Chromium may pass longer + // strings than allowed in WebGL during its internal operations. + if (entryPoint != angle::EntryPoint::GLBindUniformLocationCHROMIUM && + entryPoint != angle::EntryPoint::GLGetUniformLocation && length > maxLength) { - // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths - // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute - // locations. - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kWebglNameLengthLimitExceeded); - + ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kWebGLNameLengthLimitExceeded, + static_cast(maxLength)); return false; } - else if (length > 1024) + + // WebGL disallows strings containing invalid ESSL characters. + if (!IsValidESSLString(name, length)) { - // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of - // uniform and attribute locations. - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidNameCharacters); return false; } @@ -896,7 +902,7 @@ bool ValidateDstBlendFunc(const PrivateState &state, if (val == GL_SRC_ALPHA_SATURATE) { // Unextended ES2 does not allow GL_SRC_ALPHA_SATURATE as a dst blend func. - if (state.getClientMajorVersion() < 3 && !state.getExtensions().blendFuncExtendedEXT) + if (state.getClientVersion() < ES_3_0 && !state.getExtensions().blendFuncExtendedEXT) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction); return false; @@ -1025,6 +1031,9 @@ bool ValidateES2TexImageParametersBase(const Context *context, return false; } + // Pixel local storage isn't supported on ES2. + ASSERT(!context->getState().isTextureBoundToActivePLS(texture->id())); + // Verify zero border if (border != 0) { @@ -1662,7 +1671,7 @@ bool ValidateES2TexImageParametersBase(const Context *context, if (format != textureInternalFormat.format) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kTextureFormatMismatch); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureFormatMismatch); return false; } @@ -1909,12 +1918,6 @@ bool ValidateDiscardFramebufferEXT(const Context *context, GLsizei numAttachments, const GLenum *attachments) { - if (!context->getExtensions().discardFramebufferEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - bool defaultFramebuffer = false; switch (target) @@ -1936,12 +1939,6 @@ bool ValidateBindVertexArrayOES(const Context *context, angle::EntryPoint entryPoint, VertexArrayID array) { - if (!context->getExtensions().vertexArrayObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBindVertexArrayBase(context, entryPoint, array); } @@ -1950,13 +1947,7 @@ bool ValidateDeleteVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays) { - if (!context->getExtensions().vertexArrayObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, arrays); } bool ValidateGenVertexArraysOES(const Context *context, @@ -1964,25 +1955,14 @@ bool ValidateGenVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays) { - if (!context->getExtensions().vertexArrayObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, arrays); } -bool ValidateIsVertexArrayOES(const Context *context, +bool ValidateIsVertexArrayOES(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, VertexArrayID array) { - if (!context->getExtensions().vertexArrayObjectOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -1993,12 +1973,6 @@ bool ValidateProgramBinaryOES(const Context *context, const void *binary, GLint length) { - if (!context->getExtensions().getProgramBinaryOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length); } @@ -2010,12 +1984,6 @@ bool ValidateGetProgramBinaryOES(const Context *context, const GLenum *binaryFormat, const void *binary) { - if (!context->getExtensions().getProgramBinaryOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat, binary); } @@ -2075,21 +2043,14 @@ static bool ValidDebugSeverity(GLenum severity) } } -bool ValidateDebugMessageControlKHR(const Context *context, - angle::EntryPoint entryPoint, - GLenum source, - GLenum type, - GLenum severity, - GLsizei count, - const GLuint *ids, - GLboolean enabled) +bool ValidateDebugMessageControlBase(const Context *context, + angle::EntryPoint entryPoint, + GLenum source, + GLenum type, + GLenum severity, + GLsizei count, + const GLuint *ids) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidDebugSource(source, false) && source != GL_DONT_CARE) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource); @@ -2121,72 +2082,116 @@ bool ValidateDebugMessageControlKHR(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDebugSeverity); return false; } + + if (ids == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDebugMessageControlIdsNULL); + return false; + } + } + else if (count < 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeParam); + return false; } return true; } -bool ValidateDebugMessageInsertKHR(const Context *context, - angle::EntryPoint entryPoint, - GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *buf) +bool ValidateDebugMessageInsertBase(const Context *context, + angle::EntryPoint entryPoint, + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *buf) { - if (!context->getExtensions().debugKHR) + if (!ValidDebugSource(source, true)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource); return false; } - if (!context->getState().getDebug().isOutputEnabled()) + if (!ValidDebugType(type)) { - // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do - // not generate an error. + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugType); return false; } if (!ValidDebugSeverity(severity)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource); + ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSeverity); return false; } - if (!ValidDebugType(type)) + if (buf == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugType); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDebugMessageNULL); return false; } - if (!ValidDebugSource(source, true)) + const GLuint maxMessageLength = context->getCaps().maxDebugMessageLength; + const size_t messageLength = (length < 0) ? strnlen(buf, maxMessageLength) : length; + if (messageLength >= maxMessageLength) { - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength); return false; } - size_t messageLength = (length < 0) ? strlen(buf) : length; - if (messageLength > context->getCaps().maxDebugMessageLength) + return true; +} + +bool ValidateGetDebugMessageLogBase(const Context *context, + angle::EntryPoint entryPoint, + GLuint count, + GLsizei bufSize, + const GLenum *sources, + const GLenum *types, + const GLuint *ids, + const GLenum *severities, + const GLsizei *lengths, + const GLchar *messageLog) +{ + if (bufSize < 0 && messageLog != nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); return false; } return true; } +bool ValidateDebugMessageControlKHR(const Context *context, + angle::EntryPoint entryPoint, + GLenum source, + GLenum type, + GLenum severity, + GLsizei count, + const GLuint *ids, + GLboolean enabled) +{ + return ValidateDebugMessageControlBase(context, entryPoint, source, type, severity, count, ids); +} + +bool ValidateDebugMessageInsertKHR(const Context *context, + angle::EntryPoint entryPoint, + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *buf) +{ + return ValidateDebugMessageInsertBase(context, entryPoint, source, type, id, severity, length, + buf); +} + bool ValidateDebugMessageCallbackKHR(const Context *context, angle::EntryPoint entryPoint, GLDEBUGPROCKHR callback, const void *userParam) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -2201,19 +2206,8 @@ bool ValidateGetDebugMessageLogKHR(const Context *context, const GLsizei *lengths, const GLchar *messageLog) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (bufSize < 0 && messageLog != nullptr) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); - return false; - } - - return true; + return ValidateGetDebugMessageLogBase(context, entryPoint, count, bufSize, sources, types, ids, + severities, lengths, messageLog); } bool ValidatePushDebugGroupBase(const Context *context, @@ -2229,8 +2223,15 @@ bool ValidatePushDebugGroupBase(const Context *context, return false; } - size_t messageLength = (length < 0) ? strlen(message) : length; - if (messageLength > context->getCaps().maxDebugMessageLength) + if (message == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDebugMessageNULL); + return false; + } + + const GLuint maxMessageLength = context->getCaps().maxDebugMessageLength; + const size_t messageLength = (length < 0) ? strnlen(message, maxMessageLength) : length; + if (messageLength >= maxMessageLength) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength); return false; @@ -2265,23 +2266,11 @@ bool ValidatePushDebugGroupKHR(const Context *context, GLsizei length, const GLchar *message) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidatePushDebugGroupBase(context, entryPoint, source, id, length, message); } bool ValidatePopDebugGroupKHR(const Context *context, angle::EntryPoint entryPoint) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidatePopDebugGroupBase(context, entryPoint); } @@ -2317,7 +2306,7 @@ static bool ValidateObjectIdentifierAndName(const Context *context, return true; case GL_VERTEX_ARRAY: - if (context->getVertexArray({name}) == nullptr) + if (context->getPrivateState().getVertexArray({name}) == nullptr) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidVertexArrayName); return false; @@ -2391,13 +2380,14 @@ static bool ValidateLabelLength(const Context *context, GLsizei length, const GLchar *label) { + const GLuint maxLabelLength = context->getCaps().maxLabelLength; size_t labelLength = 0; if (length < 0) { if (label != nullptr) { - labelLength = strlen(label); + labelLength = strnlen(label, maxLabelLength); } } else @@ -2405,7 +2395,7 @@ static bool ValidateLabelLength(const Context *context, labelLength = static_cast(length); } - if (labelLength > context->getCaps().maxLabelLength) + if (labelLength >= maxLabelLength) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxLabelLength); return false; @@ -2441,18 +2431,7 @@ bool ValidateObjectLabelKHR(const Context *context, GLsizei length, const GLchar *label) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (!ValidateObjectLabelBase(context, entryPoint, identifier, name, length, label)) - { - return false; - } - - return true; + return ValidateObjectLabelBase(context, entryPoint, identifier, name, length, label); } bool ValidateGetObjectLabelBase(const Context *context, @@ -2485,18 +2464,8 @@ bool ValidateGetObjectLabelKHR(const Context *context, const GLsizei *length, const GLchar *label) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (!ValidateGetObjectLabelBase(context, entryPoint, identifier, name, bufSize, length, label)) - { - return false; - } - - return true; + return ValidateGetObjectLabelBase(context, entryPoint, identifier, name, bufSize, length, + label); } static bool ValidateObjectPtrName(const Context *context, @@ -2537,18 +2506,7 @@ bool ValidateObjectPtrLabelKHR(const Context *context, GLsizei length, const GLchar *label) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (!ValidateObjectPtrLabelBase(context, entryPoint, ptr, length, label)) - { - return false; - } - - return true; + return ValidateObjectPtrLabelBase(context, entryPoint, ptr, length, label); } bool ValidateGetObjectPtrLabelBase(const Context *context, @@ -2579,18 +2537,7 @@ bool ValidateGetObjectPtrLabelKHR(const Context *context, const GLsizei *length, const GLchar *label) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (!ValidateGetObjectPtrLabelBase(context, entryPoint, ptr, bufSize, length, label)) - { - return false; - } - - return true; + return ValidateGetObjectPtrLabelBase(context, entryPoint, ptr, bufSize, length, label); } bool ValidateGetPointervKHR(const Context *context, @@ -2598,12 +2545,6 @@ bool ValidateGetPointervKHR(const Context *context, GLenum pname, void *const *params) { - if (!context->getExtensions().debugKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetPointerv(context, entryPoint, pname, params); } @@ -2631,12 +2572,6 @@ bool ValidateBlitFramebufferANGLE(const Context *context, GLbitfield mask, GLenum filter) { - if (!context->getExtensions().framebufferBlitANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitExtensionNotAvailable); - return false; - } - if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) { // TODO(jmadill): Determine if this should be available on other implementations. @@ -2707,13 +2642,21 @@ bool ValidateBlitFramebufferANGLE(const Context *context, } GLint samples = readFramebuffer->getSamples(context); - if (samples != 0 && - IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0, - srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + if (samples != 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, - kBlitExtensionMultisampledWholeBufferBlit); - return false; + if (readColorAttachment->ensureSizeResolved(context) == angle::Result::Stop || + drawColorAttachment->ensureSizeResolved(context) == angle::Result::Stop) + { + // Context error must be generated by the failed call itself. + return false; + } + if (IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0, + srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, + kBlitExtensionMultisampledWholeBufferBlit); + return false; + } } } } @@ -2731,6 +2674,12 @@ bool ValidateBlitFramebufferANGLE(const Context *context, if (readBuffer && drawBuffer) { + if (readBuffer->ensureSizeResolved(context) == angle::Result::Stop || + drawBuffer->ensureSizeResolved(context) == angle::Result::Stop) + { + // Context error must be generated by the failed call itself. + return false; + } if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { @@ -2767,12 +2716,6 @@ bool ValidateBlitFramebufferNV(const Context *context, GLbitfield mask, GLenum filter) { - if (!context->getExtensions().framebufferBlitANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitExtensionNotAvailable); - return false; - } - return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } @@ -2827,7 +2770,7 @@ bool ValidateClear(const Context *context, angle::EntryPoint entryPoint, GLbitfi } } - if ((extensions.multiviewOVR || extensions.multiview2OVR) && extensions.disjointTimerQueryEXT) + if (extensions.multiviewOVR && extensions.disjointTimerQueryEXT) { const State &state = context->getState(); Framebuffer *framebuffer = state.getDrawFramebuffer(); @@ -2846,12 +2789,6 @@ bool ValidateDrawBuffersEXT(const Context *context, GLsizei n, const GLenum *bufs) { - if (!context->getExtensions().drawBuffersEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawBuffersBase(context, entryPoint, n, bufs); } @@ -2867,14 +2804,13 @@ bool ValidateTexImage2D(const Context *context, GLenum type, const void *pixels) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, false, false, 0, 0, width, height, border, format, type, -1, pixels); } - ASSERT(context->getClientMajorVersion() >= 3); return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat, false, false, 0, 0, 0, width, height, 1, border, format, type, -1, pixels); @@ -2898,14 +2834,13 @@ bool ValidateTexImage2DRobustANGLE(const Context *context, return false; } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, false, false, 0, 0, width, height, border, format, type, bufSize, pixels); } - ASSERT(context->getClientMajorVersion() >= 3); return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat, false, false, 0, 0, 0, width, height, 1, border, format, type, bufSize, pixels); @@ -2924,14 +2859,13 @@ bool ValidateTexSubImage2D(const Context *context, const void *pixels) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false, true, xoffset, yoffset, width, height, 0, format, type, -1, pixels); } - ASSERT(context->getClientMajorVersion() >= 3); return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true, xoffset, yoffset, 0, width, height, 1, 0, format, type, -1, pixels); @@ -2955,14 +2889,13 @@ bool ValidateTexSubImage2DRobustANGLE(const Context *context, return false; } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false, true, xoffset, yoffset, width, height, 0, format, type, bufSize, pixels); } - ASSERT(context->getClientMajorVersion() >= 3); return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true, xoffset, yoffset, 0, width, height, 1, 0, format, type, bufSize, pixels); @@ -2997,7 +2930,7 @@ bool ValidateCompressedTexImage2D(const Context *context, GLsizei imageSize, const void *data) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { if (!ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, true, false, 0, 0, width, height, border, GL_NONE, GL_NONE, -1, @@ -3008,7 +2941,6 @@ bool ValidateCompressedTexImage2D(const Context *context, } else { - ASSERT(context->getClientMajorVersion() >= 3); if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat, true, false, 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1, data)) @@ -3112,7 +3044,7 @@ bool ValidateCompressedTexSubImage2D(const Context *context, GLsizei imageSize, const void *data) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { if (!ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, true, true, xoffset, yoffset, width, height, 0, format, GL_NONE, -1, @@ -3123,7 +3055,6 @@ bool ValidateCompressedTexSubImage2D(const Context *context, } else { - ASSERT(context->getClientMajorVersion() >= 3); if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, true, true, xoffset, yoffset, 0, width, height, 1, 0, format, GL_NONE, -1, data)) @@ -3173,12 +3104,6 @@ bool ValidateGetBufferPointervOES(const Context *context, GLenum pname, void *const *params) { - if (!context->getExtensions().mapbufferOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params); } @@ -3187,12 +3112,6 @@ bool ValidateMapBufferOES(const Context *context, BufferBinding target, GLenum access) { - if (!context->getExtensions().mapbufferOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!context->isValidBufferBinding(target)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes); @@ -3235,12 +3154,6 @@ bool ValidateUnmapBufferOES(const Context *context, angle::EntryPoint entryPoint, BufferBinding target) { - if (!context->getExtensions().mapbufferOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateUnmapBufferBase(context, entryPoint, target); } @@ -3251,12 +3164,6 @@ bool ValidateMapBufferRangeEXT(const Context *context, GLsizeiptr length, GLbitfield access) { - if (!context->getExtensions().mapBufferRangeEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access); } @@ -3294,15 +3201,9 @@ bool ValidateMapBufferBase(const Context *context, bool ValidateFlushMappedBufferRangeEXT(const Context *context, angle::EntryPoint entryPoint, BufferBinding target, - GLintptr offset, - GLsizeiptr length) -{ - if (!context->getExtensions().mapBufferRangeEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - + GLintptr offset, + GLsizeiptr length) +{ return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length); } @@ -3312,15 +3213,10 @@ bool ValidateBindUniformLocationCHROMIUM(const Context *context, UniformLocation location, const GLchar *name) { - if (!context->getExtensions().bindUniformLocationCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -3338,17 +3234,21 @@ bool ValidateBindUniformLocationCHROMIUM(const Context *context, return false; } - // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for - // shader-related entry points - if (context->isWebGL() && !IsValidESSLString(name, strlen(name))) + if (name == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidNameCharacters); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformNameNull); + return false; + } + + if (context->nameStartsWithReservedPrefix(name)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNameStartsWithReservedPrefix); return false; } - if (strncmp(name, "gl_", 3) == 0) + if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNameBeginsWithGL); + // Error already generated. return false; } @@ -3360,11 +3260,6 @@ bool ValidateCoverageModulationCHROMIUM(const PrivateState &state, angle::EntryPoint entryPoint, GLenum components) { - if (!state.getExtensions().framebufferMixedSamplesCHROMIUM) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } switch (components) { case GL_RGB: @@ -3393,12 +3288,6 @@ bool ValidateCopyTextureCHROMIUM(const Context *context, GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha) { - if (!context->getExtensions().copyTextureCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const Texture *source = context->getTexture(sourceId); if (source == nullptr) { @@ -3464,8 +3353,15 @@ bool ValidateCopyTextureCHROMIUM(const Context *context, return false; } - if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel, - sourceWidth, sourceHeight, false)) + if (!ValidImageSizeParameters(context, entryPoint, dest->getType(), destLevel, sourceWidth, + sourceHeight, 1, false)) + { + // Error already generated. + return false; + } + + if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, sourceWidth, + sourceHeight)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel); return false; @@ -3508,12 +3404,6 @@ bool ValidateCopySubTextureCHROMIUM(const Context *context, GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha) { - if (!context->getExtensions().copyTextureCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const Texture *source = context->getTexture(sourceId); if (source == nullptr) { @@ -3590,8 +3480,14 @@ bool ValidateCopySubTextureCHROMIUM(const Context *context, return false; } - if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel, width, - height, true)) + if (!ValidImageSizeParameters(context, entryPoint, dest->getType(), destLevel, width, height, 1, + true)) + { + // Error already generated. + return false; + } + + if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, width, height)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel); return false; @@ -3638,12 +3534,6 @@ bool ValidateCompressedCopyTextureCHROMIUM(const Context *context, TextureID sourceId, TextureID destId) { - if (!context->getExtensions().copyCompressedTextureCHROMIUM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const Texture *source = context->getTexture(sourceId); if (source == nullptr) { @@ -3770,7 +3660,7 @@ bool ValidateBufferData(const Context *context, case BufferUsage::StreamCopy: case BufferUsage::StaticCopy: case BufferUsage::DynamicCopy: - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferUsage); return false; @@ -3796,10 +3686,24 @@ bool ValidateBufferData(const Context *context, return false; } - if (buffer->hasWebGLXFBBindingConflict(context->isWebGL())) + // Do some additional WebGL-specific validation + if (ANGLE_UNLIKELY(context->isWebGL())) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback); - return false; + if (buffer->hasWebGLXFBBindingConflict(true)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback); + return false; + } + + const TransformFeedback *transformFeedbackObject = + context->getState().getCurrentTransformFeedback(); + if (transformFeedbackObject && transformFeedbackObject->isActive() && + !transformFeedbackObject->isPaused() && + transformFeedbackObject->isBufferBound(buffer->id())) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback); + return false; + } } if (buffer->isImmutable()) @@ -3854,10 +3758,24 @@ bool ValidateBufferSubData(const Context *context, return false; } - if (buffer->hasWebGLXFBBindingConflict(context->isWebGL())) + // Do some additional WebGL-specific validation + if (ANGLE_UNLIKELY(context->isWebGL())) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback); - return false; + if (buffer->hasWebGLXFBBindingConflict(true)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback); + return false; + } + + const TransformFeedback *transformFeedbackObject = + context->getState().getCurrentTransformFeedback(); + if (transformFeedbackObject && transformFeedbackObject->isActive() && + !transformFeedbackObject->isPaused() && + transformFeedbackObject->isBufferBound(buffer->id())) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback); + return false; + } } if (buffer->isImmutable() && @@ -3889,12 +3807,6 @@ bool ValidateRequestExtensionANGLE(const Context *context, angle::EntryPoint entryPoint, const GLchar *name) { - if (!context->getExtensions().requestExtensionANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!context->isExtensionRequestable(name)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotRequestable); @@ -3908,12 +3820,6 @@ bool ValidateDisableExtensionANGLE(const Context *context, angle::EntryPoint entryPoint, const GLchar *name) { - if (!context->getExtensions().requestExtensionANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!context->isExtensionDisablable(name)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotDisablable); @@ -3928,7 +3834,7 @@ bool ValidateActiveTexture(const PrivateState &state, angle::EntryPoint entryPoint, GLenum texture) { - if (state.getClientMajorVersion() < 2) + if (state.getClientVersion() < ES_2_0) { return ValidateMultitextureUnit(state, errors, entryPoint, texture); } @@ -3950,14 +3856,16 @@ bool ValidateAttachShader(const Context *context, ShaderProgramID shader) { Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } Shader *shaderObject = GetValidShader(context, entryPoint, shader); - if (!shaderObject) + if (shaderObject == nullptr) { + // Error already generated. return false; } @@ -3982,32 +3890,32 @@ bool ValidateBindAttribLocation(const Context *context, return false; } - if (strncmp(name, "gl_", 3) == 0) + if (name == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNameBeginsWithGL); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kAttributeNameNull); return false; } - if (context->isWebGL()) + if (context->nameStartsWithReservedPrefix(name)) { - const size_t length = strlen(name); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNameStartsWithReservedPrefix); + return false; + } - if (!IsValidESSLString(name, length)) - { - // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters - // for shader-related entry points - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidNameCharacters); - return false; - } + if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name)) + { + // Error already generated. + return false; + } - if (!ValidateWebGLNameLength(context, entryPoint, length) || - !ValidateWebGLNamePrefix(context, entryPoint, name)) - { - return false; - } + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) + { + // Error already generated. + return false; } - return GetValidProgram(context, entryPoint, program) != nullptr; + return true; } bool ValidateBindFramebuffer(const Context *context, @@ -4266,12 +4174,6 @@ bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context, GLsizei width, GLsizei height) { - if (!context->getExtensions().framebufferMultisampleANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is // generated. @@ -4284,11 +4186,11 @@ bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context, // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create // the specified storage. This is different than ES 3.0 in which a sample number higher // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. - // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. - if (context->getClientMajorVersion() >= 3) + // The getMaxSamples method is only guaranteed to be valid when the context is ES3. + if (context->getClientVersion() >= ES_3_0) { const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (static_cast(samples) > formatCaps.getMaxSamples()) + if (static_cast(samples) > formatCaps.sampleCounts.getMaxSamples()) { ANGLE_VALIDATION_ERROR(GL_OUT_OF_MEMORY, kSamplesOutOfRange); return false; @@ -4388,7 +4290,7 @@ bool ValidateDeleteProgram(const Context *context, { if (program.value == 0) { - return false; + return true; // no-op } if (!context->getProgramResolveLink(program)) @@ -4414,7 +4316,7 @@ bool ValidateDeleteShader(const Context *context, { if (shader.value == 0) { - return false; + return true; // no-op } if (!context->getShaderNoResolveCompile(shader)) @@ -4473,14 +4375,16 @@ bool ValidateDetachShader(const Context *context, ShaderProgramID shader) { Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } Shader *shaderObject = GetValidShader(context, entryPoint, shader); - if (!shaderObject) + if (shaderObject == nullptr) { + // Error already generated. return false; } @@ -4494,26 +4398,28 @@ bool ValidateDetachShader(const Context *context, return true; } -bool ValidateDisableVertexAttribArray(const Context *context, +bool ValidateDisableVertexAttribArray(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index) { - if (index >= static_cast(context->getCaps().maxVertexAttributes)) + if (index >= static_cast(state.getCaps().maxVertexAttributes)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); + errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); return false; } return true; } -bool ValidateEnableVertexAttribArray(const Context *context, +bool ValidateEnableVertexAttribArray(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index) { - if (index >= static_cast(context->getCaps().maxVertexAttributes)) + if (index >= static_cast(state.getCaps().maxVertexAttributes)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); + errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); return false; } @@ -4565,9 +4471,9 @@ bool ValidateGetActiveAttrib(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4597,9 +4503,9 @@ bool ValidateGetActiveUniform(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4609,6 +4515,12 @@ bool ValidateGetActiveUniform(const Context *context, return false; } + if (bufsize > 0 && name == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidName); + return false; + } + return true; } @@ -4619,6 +4531,12 @@ bool ValidateGetAttachedShaders(const Context *context, const GLsizei *count, const ShaderProgramID *shaders) { + if (shaders == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + if (maxcount < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeMaxCount); @@ -4626,9 +4544,9 @@ bool ValidateGetAttachedShaders(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4640,35 +4558,22 @@ bool ValidateGetAttribLocation(const Context *context, ShaderProgramID program, const GLchar *name) { - if (strncmp(name, "gl_", 3) == 0) + if (name == nullptr) { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kAttributeNameNull); return false; } - if (context->isWebGL()) + if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name)) { - const size_t length = strlen(name); - - if (!IsValidESSLString(name, length)) - { - // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters - // for shader-related entry points - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidNameCharacters); - return false; - } - - if (!ValidateWebGLNameLength(context, entryPoint, length) || - strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0) - { - return false; - } + // Error already generated. + return false; } Program *programObject = GetValidProgram(context, entryPoint, program); - - if (!programObject) + if (programObject == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotBound); + // Error already generated. return false; } @@ -4688,6 +4593,13 @@ bool ValidateGetBooleanv(const Context *context, { GLenum nativeType; unsigned int numParams = 0; + + if (params == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); } @@ -4703,6 +4615,13 @@ bool ValidateGetFloatv(const Context *context, { GLenum nativeType; unsigned int numParams = 0; + + if (params == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); } @@ -4713,6 +4632,13 @@ bool ValidateGetIntegerv(const Context *context, { GLenum nativeType; unsigned int numParams = 0; + + if (params == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); } @@ -4730,8 +4656,9 @@ bool ValidateGetProgramInfoLog(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4752,8 +4679,9 @@ bool ValidateGetShaderInfoLog(const Context *context, } Shader *shaderObject = GetValidShader(context, entryPoint, shader); - if (!shaderObject) + if (shaderObject == nullptr) { + // Error already generated. return false; } @@ -4767,6 +4695,12 @@ bool ValidateGetShaderPrecisionFormat(const Context *context, const GLint *range, const GLint *precision) { + if (range == nullptr || precision == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + switch (shadertype) { case GL_VERTEX_SHADER: @@ -4812,8 +4746,9 @@ bool ValidateGetShaderSource(const Context *context, } Shader *shaderObject = GetValidShader(context, entryPoint, shader); - if (!shaderObject) + if (shaderObject == nullptr) { + // Error already generated. return false; } @@ -4825,23 +4760,22 @@ bool ValidateGetUniformLocation(const Context *context, ShaderProgramID program, const GLchar *name) { - if (strstr(name, "gl_") == name) + if (name == nullptr) { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformNameNull); return false; } - // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for - // shader-related entry points - if (context->isWebGL() && !IsValidESSLString(name, strlen(name))) + if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidNameCharacters); + // Error already generated. return false; } Program *programObject = GetValidProgram(context, entryPoint, program); - - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4889,7 +4823,7 @@ bool ValidateHint(const PrivateState &state, case GL_POINT_SMOOTH_HINT: case GL_LINE_SMOOTH_HINT: case GL_FOG_HINT: - if (state.getClientMajorVersion() >= 2) + if (state.getClientVersion() >= ES_2_0) { errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); return false; @@ -4946,7 +4880,7 @@ bool ValidatePixelStorei(const PrivateState &state, GLenum pname, GLint param) { - if (state.getClientMajorVersion() < 3) + if (state.getClientVersion() < ES_3_0) { switch (pname) { @@ -5005,6 +4939,7 @@ bool ValidatePixelStorei(const PrivateState &state, if (!state.getExtensions().packReverseRowOrderANGLE) { errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); + return false; } break; @@ -5104,15 +5039,16 @@ bool ValidateShaderBinary(const Context *context, } Shader *shaderObject = GetValidShader(context, entryPoint, shaders[0]); - if (!shaderObject) + if (shaderObject == nullptr) { + // Error already generated. return false; } // Check ANGLE version used to generate binary matches the current version. - BinaryInputStream stream(binary, length); - std::vector versionString(angle::GetANGLEShaderProgramVersionHashSize(), 0); - stream.readBytes(versionString.data(), versionString.size()); + BinaryInputStream stream(angle::Span(static_cast(binary), length)); + std::vector versionString(angle::GetANGLEShaderProgramVersionHashSize()); + stream.readBytes(versionString); if (memcmp(versionString.data(), angle::GetANGLEShaderProgramVersion(), versionString.size()) != 0) { @@ -5146,8 +5082,9 @@ bool ValidateShaderSource(const Context *context, } Shader *shaderObject = GetValidShader(context, entryPoint, shader); - if (!shaderObject) + if (shaderObject == nullptr) { + // Error already generated. return false; } @@ -5266,9 +5203,9 @@ bool ValidateValidateProgram(const Context *context, ShaderProgramID program) { Program *programObject = GetValidProgram(context, entryPoint, program); - - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -5323,13 +5260,12 @@ bool ValidateCopyTexImage2D(const Context *context, GLsizei height, GLint border) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, internalformat, false, 0, 0, x, y, width, height, border); } - ASSERT(context->getClientMajorVersion() == 3); return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, internalformat, false, 0, 0, 0, x, y, width, height, border); } @@ -5345,7 +5281,7 @@ bool ValidateCopyTexSubImage2D(const Context *context, GLsizei width, GLsizei height) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, GL_NONE, true, xoffset, yoffset, x, y, width, height, 0); @@ -5376,7 +5312,7 @@ bool ValidateDeleteBuffers(const Context *context, GLint n, const BufferID *buffers) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, buffers); } bool ValidateDeleteFramebuffers(const Context *context, @@ -5384,7 +5320,8 @@ bool ValidateDeleteFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + framebuffers); } bool ValidateDeleteRenderbuffers(const Context *context, @@ -5392,7 +5329,8 @@ bool ValidateDeleteRenderbuffers(const Context *context, GLint n, const RenderbufferID *renderbuffers) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + renderbuffers); } bool ValidateDeleteTextures(const Context *context, @@ -5400,7 +5338,7 @@ bool ValidateDeleteTextures(const Context *context, GLint n, const TextureID *textures) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, textures); } bool ValidateDisable(const PrivateState &state, @@ -5481,7 +5419,7 @@ bool ValidateFramebufferTexture2D(const Context *context, { // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap // extension - if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES && + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().fboRenderMipmapOES && level != 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel); @@ -5618,15 +5556,10 @@ bool ValidateFramebufferTexture3DOES(const Context *context, // We don't call into a base ValidateFramebufferTexture3D here because // it doesn't exist for OpenGL ES. This function is replaced by // FramebufferTextureLayer in ES 3.x, which has broader support. - if (!context->getExtensions().texture3DOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } // Attachments are required to be bound to level 0 without ES3 or the // GL_OES_fbo_render_mipmap extension - if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES && + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().fboRenderMipmapOES && level != 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel); @@ -5702,8 +5635,9 @@ bool ValidateLinkProgram(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -5752,12 +5686,6 @@ bool ValidateDeleteFencesNV(const Context *context, GLsizei n, const FenceNVID *fences) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - if (n < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); @@ -5769,12 +5697,6 @@ bool ValidateDeleteFencesNV(const Context *context, bool ValidateFinishFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - FenceNV *fenceObject = context->getFenceNV(fence); if (fenceObject == nullptr) @@ -5797,12 +5719,6 @@ bool ValidateGenFencesNV(const Context *context, GLsizei n, const FenceNVID *fences) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - if (n < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); @@ -5818,12 +5734,6 @@ bool ValidateGetFenceivNV(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - FenceNV *fenceObject = context->getFenceNV(fence); if (fenceObject == nullptr) @@ -5854,12 +5764,6 @@ bool ValidateGetFenceivNV(const Context *context, bool ValidateGetGraphicsResetStatusEXT(const Context *context, angle::EntryPoint entryPoint) { - if (!context->getExtensions().robustnessEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -5870,12 +5774,6 @@ bool ValidateGetTranslatedShaderSourceANGLE(const Context *context, const GLsizei *length, const GLchar *source) { - if (!context->getExtensions().translatedShaderSourceANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (bufsize < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); @@ -5895,12 +5793,6 @@ bool ValidateGetTranslatedShaderSourceANGLE(const Context *context, bool ValidateIsFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - return true; } @@ -5909,12 +5801,6 @@ bool ValidateSetFenceNV(const Context *context, FenceNVID fence, GLenum condition) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - if (condition != GL_ALL_COMPLETED_NV) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFenceCondition); @@ -5934,12 +5820,6 @@ bool ValidateSetFenceNV(const Context *context, bool ValidateTestFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence) { - if (!context->getExtensions().fenceNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNVFenceNotSupported); - return false; - } - FenceNV *fenceObject = context->getFenceNV(fence); if (fenceObject == nullptr) @@ -5965,45 +5845,34 @@ bool ValidateTexStorage2DEXT(const Context *context, GLsizei width, GLsizei height) { - if (!context->getExtensions().textureStorageEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2TexStorageParametersBase(context, entryPoint, type, levels, internalformat, width, height); } - ASSERT(context->getClientMajorVersion() >= 3); return ValidateES3TexStorage2DParameters(context, entryPoint, type, levels, internalformat, width, height, 1); } -bool ValidateVertexAttribDivisorANGLE(const Context *context, +bool ValidateVertexAttribDivisorANGLE(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLuint divisor) { - if (!context->getExtensions().instancedArraysANGLE) + if (index >= static_cast(privateState.getCaps().maxVertexAttributes)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (index >= static_cast(context->getCaps().maxVertexAttributes)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); + errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); return false; } - if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT) + if (privateState.getLimitations().attributeZeroRequiresZeroDivisorInEXT) { if (index == 0 && divisor != 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kAttributeZeroRequiresDivisorLimitation); + errors->validationError(entryPoint, GL_INVALID_OPERATION, + kAttributeZeroRequiresDivisorLimitation); // We also output an error message to the debugger window if tracing is active, so // that developers can see the error message. @@ -6015,20 +5884,15 @@ bool ValidateVertexAttribDivisorANGLE(const Context *context, return true; } -bool ValidateVertexAttribDivisorEXT(const Context *context, +bool ValidateVertexAttribDivisorEXT(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLuint divisor) { - if (!context->getExtensions().instancedArraysEXT) + if (index >= static_cast(privateState.getCaps().maxVertexAttributes)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (index >= static_cast(context->getCaps().maxVertexAttributes)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); + errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); return false; } @@ -6054,29 +5918,9 @@ bool ValidateTexImage3DOES(const Context *context, bool ValidatePopGroupMarkerEXT(const Context *context, angle::EntryPoint entryPoint) { - if (!context->getExtensions().debugMarkerEXT) - { - // The debug marker calls should not set error state - // However, it seems reasonable to set an error state if the extension is not enabled - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } -bool ValidateTexStorage1DEXT(const Context *context, - angle::EntryPoint entryPoint, - GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width) -{ - UNIMPLEMENTED(); - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; -} - bool ValidateTexStorage3DEXT(const Context *context, angle::EntryPoint entryPoint, TextureType target, @@ -6086,13 +5930,7 @@ bool ValidateTexStorage3DEXT(const Context *context, GLsizei height, GLsizei depth) { - if (!context->getExtensions().textureStorageEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; @@ -6106,11 +5944,6 @@ bool ValidateMaxShaderCompilerThreadsKHR(const Context *context, angle::EntryPoint entryPoint, GLuint count) { - if (!context->getExtensions().parallelShaderCompileKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } return true; } @@ -6121,9 +5954,9 @@ bool ValidateMultiDrawArraysANGLE(const Context *context, const GLsizei *counts, GLsizei drawcount) { - if (!context->getExtensions().multiDrawANGLE) + if (drawcount < 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount); return false; } for (GLsizei drawID = 0; drawID < drawcount; ++drawID) @@ -6144,9 +5977,9 @@ bool ValidateMultiDrawElementsANGLE(const Context *context, const GLvoid *const *indices, GLsizei drawcount) { - if (!context->getExtensions().multiDrawANGLE) + if (drawcount < 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount); return false; } for (GLsizei drawID = 0; drawID < drawcount; ++drawID) @@ -6168,21 +6001,10 @@ bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context, GLint level, GLsizei samples) { - if (!context->getExtensions().multisampledRenderToTextureEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (samples < 0) - { - return false; - } - // EXT_multisampled_render_to_texture states that the value of samples // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples) // otherwise GL_INVALID_VALUE is generated. - if (samples > context->getCaps().maxSamples) + if (samples < 0 || samples > context->getCaps().maxSamples) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesOutOfRange); return false; @@ -6195,13 +6017,13 @@ bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context, // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than // the maximum sample number supported by this format is passed. - // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. - if (texture.value != 0 && context->getClientMajorVersion() >= 3) + // The getMaxSamples method is only guaranteed to be valid when the context is ES3. + if (texture.value != 0 && context->getClientVersion() >= ES_3_0) { Texture *tex = context->getTexture(texture); GLenum sizedInternalFormat = tex->getFormat(textarget, level).info->sizedInternalFormat; const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); - if (static_cast(samples) > formatCaps.getMaxSamples()) + if (static_cast(samples) > formatCaps.sampleCounts.getMaxSamples()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange); return false; @@ -6233,11 +6055,6 @@ bool ValidateRenderbufferStorageMultisampleEXT(const Context *context, GLsizei width, GLsizei height) { - if (!context->getExtensions().multisampledRenderToTextureEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples, internalformat, width, height)) { @@ -6256,11 +6073,11 @@ bool ValidateRenderbufferStorageMultisampleEXT(const Context *context, // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create // the specified storage. This is different than ES 3.0 in which a sample number higher // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. - // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. - if (context->getClientMajorVersion() >= 3) + // The getMaxSamples method is only guaranteed to be valid when the context is ES3. + if (context->getClientVersion() >= ES_3_0) { const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (static_cast(samples) > formatCaps.getMaxSamples()) + if (static_cast(samples) > formatCaps.sampleCounts.getMaxSamples()) { ANGLE_VALIDATION_ERROR(GL_OUT_OF_MEMORY, kSamplesOutOfRange); return false; @@ -6276,12 +6093,6 @@ bool ValidateBlobCacheCallbacksANGLE(const Context *context, GLGETBLOBPROCANGLE get, const void *userParam) { - if (!context->getExtensions().blobCacheANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if ((get == nullptr) != (set == nullptr)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlobCacheCallbacksUnbalanced); @@ -6296,12 +6107,6 @@ bool ValidateGetPointervANGLE(const Context *context, GLenum pname, void *const *params) { - if (!context->getExtensions().blobCacheANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetPointerv(context, entryPoint, pname, params); } @@ -6320,18 +6125,18 @@ void RecordBindTextureTypeError(const Context *context, case TextureType::_3D: case TextureType::_2DArray: - ASSERT(context->getClientMajorVersion() < 3); + ASSERT(context->getClientVersion() < ES_3_0); ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required); break; case TextureType::_2DMultisample: - ASSERT(context->getClientVersion() < Version(3, 1) && + ASSERT(context->getClientVersion() < ES_3_1 && !context->getExtensions().textureMultisampleANGLE); ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required); break; case TextureType::_2DMultisampleArray: - ASSERT(context->getClientVersion() < Version(3, 2) && + ASSERT(context->getClientVersion() < ES_3_2 && !context->getExtensions().textureStorageMultisample2dArrayOES); ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionOrES32Required); break; diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h index 0c375be2af4..6deb05a3b0e 100644 --- a/src/libANGLE/validationES2.h +++ b/src/libANGLE/validationES2.h @@ -15,6 +15,9 @@ namespace gl { + +void RecordVersionErrorES20(const Context *context, angle::EntryPoint entryPoint); + ANGLE_INLINE bool ValidateDrawArrays(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode, @@ -38,6 +41,12 @@ ANGLE_INLINE bool ValidateUniform1fv(const Context *context, GLsizei count, const GLfloat *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_FLOAT, location, count); } @@ -64,6 +73,12 @@ ANGLE_INLINE bool ValidateUniform2fv(const Context *context, GLsizei count, const GLfloat *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, count); } @@ -82,6 +97,12 @@ ANGLE_INLINE bool ValidateUniform2iv(const Context *context, GLsizei count, const GLint *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, count); } @@ -101,6 +122,12 @@ ANGLE_INLINE bool ValidateUniform3fv(const Context *context, GLsizei count, const GLfloat *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, count); } @@ -120,6 +147,12 @@ ANGLE_INLINE bool ValidateUniform3iv(const Context *context, GLsizei count, const GLint *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, count); } @@ -140,6 +173,12 @@ ANGLE_INLINE bool ValidateUniform4fv(const Context *context, GLsizei count, const GLfloat *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, count); } @@ -160,6 +199,12 @@ ANGLE_INLINE bool ValidateUniform4iv(const Context *context, GLsizei count, const GLint *v) { + if (!ValidateUniformValuePointer(context, entryPoint, v)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, count); } @@ -208,6 +253,12 @@ ANGLE_INLINE bool ValidateVertexAttrib1fv(const PrivateState &state, GLuint index, const GLfloat *values) { + if (values == nullptr) + { + errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL); + return false; + } + return ValidateVertexAttribIndex(state, errors, entryPoint, index); } @@ -227,6 +278,12 @@ ANGLE_INLINE bool ValidateVertexAttrib2fv(const PrivateState &state, GLuint index, const GLfloat *values) { + if (values == nullptr) + { + errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL); + return false; + } + return ValidateVertexAttribIndex(state, errors, entryPoint, index); } @@ -247,6 +304,12 @@ ANGLE_INLINE bool ValidateVertexAttrib3fv(const PrivateState &state, GLuint index, const GLfloat *values) { + if (values == nullptr) + { + errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL); + return false; + } + return ValidateVertexAttribIndex(state, errors, entryPoint, index); } @@ -268,6 +331,12 @@ ANGLE_INLINE bool ValidateVertexAttrib4fv(const PrivateState &state, GLuint index, const GLfloat *values) { + if (values == nullptr) + { + errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL); + return false; + } + return ValidateVertexAttribIndex(state, errors, entryPoint, index); } @@ -276,7 +345,7 @@ ANGLE_INLINE bool ValidateGenBuffers(const Context *context, GLint n, const BufferID *buffers) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, buffers); } ANGLE_INLINE bool ValidateGenFramebuffers(const Context *context, @@ -284,7 +353,8 @@ ANGLE_INLINE bool ValidateGenFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + framebuffers); } ANGLE_INLINE bool ValidateGenRenderbuffers(const Context *context, @@ -292,7 +362,8 @@ ANGLE_INLINE bool ValidateGenRenderbuffers(const Context *context, GLint n, const RenderbufferID *renderbuffers) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + renderbuffers); } ANGLE_INLINE bool ValidateGenTextures(const Context *context, @@ -300,7 +371,7 @@ ANGLE_INLINE bool ValidateGenTextures(const Context *context, GLint n, const TextureID *textures) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, textures); } ANGLE_INLINE bool ValidateGenerateMipmap(const Context *context, @@ -334,6 +405,12 @@ ANGLE_INLINE bool ValidateGetShaderiv(const Context *context, GLenum pname, const GLint *params) { + if (params == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kPLSParamsNULL); + return false; + } + return ValidateGetShaderivBase(context, entryPoint, shader, pname, nullptr); } @@ -379,7 +456,7 @@ ANGLE_INLINE bool ValidateGetVertexAttribfv(const Context *context, GLenum pname, const GLfloat *params) { - return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false); + return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false); } ANGLE_INLINE bool ValidateGetVertexAttribiv(const Context *context, @@ -388,7 +465,7 @@ ANGLE_INLINE bool ValidateGetVertexAttribiv(const Context *context, GLenum pname, const GLint *params) { - return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false); + return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false); } ANGLE_INLINE bool ValidateGetVertexAttribPointerv(const Context *context, @@ -397,7 +474,7 @@ ANGLE_INLINE bool ValidateGetVertexAttribPointerv(const Context *context, GLenum pname, void *const *pointer) { - return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, true, false); + return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, true); } ANGLE_INLINE bool ValidateReadPixels(const Context *context, @@ -490,7 +567,9 @@ ANGLE_INLINE bool ValidateVertexAttribPointer(const Context *context, GLsizei stride, const void *ptr) { - if (!ValidateFloatVertexFormat(context, entryPoint, index, size, type)) + if (!ValidateFloatVertexFormat(context->getPrivateState(), context->getPrivateStateCache(), + context->getMutableErrorSetForValidation(), entryPoint, index, + size, type)) { return false; } @@ -626,6 +705,34 @@ bool ValidatePushDebugGroupBase(const Context *context, const GLchar *message); bool ValidatePopDebugGroupBase(const Context *context, angle::EntryPoint entryPoint); +bool ValidateDebugMessageControlBase(const Context *context, + angle::EntryPoint entryPoint, + GLenum source, + GLenum type, + GLenum severity, + GLsizei count, + const GLuint *ids); + +bool ValidateDebugMessageInsertBase(const Context *context, + angle::EntryPoint entryPoint, + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *buf); + +bool ValidateGetDebugMessageLogBase(const Context *context, + angle::EntryPoint entryPoint, + GLuint count, + GLsizei bufSize, + const GLenum *sources, + const GLenum *types, + const GLuint *ids, + const GLenum *severities, + const GLsizei *lengths, + const GLchar *messageLog); + // Validation of ObjectLabel bool ValidateObjectLabelBase(const Context *context, angle::EntryPoint entryPoint, diff --git a/src/libANGLE/validationES2_autogen.h b/src/libANGLE/validationES2_autogen.h index 01535cd53fa..441890c003a 100644 --- a/src/libANGLE/validationES2_autogen.h +++ b/src/libANGLE/validationES2_autogen.h @@ -18,6 +18,7 @@ namespace gl { class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; bool ValidateActiveTexture(const PrivateState &state, @@ -210,7 +211,8 @@ bool ValidateDisable(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, GLenum cap); -bool ValidateDisableVertexAttribArray(const Context *context, +bool ValidateDisableVertexAttribArray(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index); bool ValidateDrawArrays(const Context *context, @@ -228,7 +230,8 @@ bool ValidateEnable(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, GLenum cap); -bool ValidateEnableVertexAttribArray(const Context *context, +bool ValidateEnableVertexAttribArray(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index); bool ValidateFinish(const Context *context, angle::EntryPoint entryPoint); diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp index 34d5af50449..dcd30eeab1f 100644 --- a/src/libANGLE/validationES3.cpp +++ b/src/libANGLE/validationES3.cpp @@ -6,6 +6,10 @@ // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/validationES3_autogen.h" #include "anglebase/numerics/safe_conversions.h" @@ -29,22 +33,21 @@ namespace gl { using namespace err; +void RecordVersionErrorES30(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES30); +} + namespace { -bool ValidateFramebufferTextureMultiviewBaseANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLenum target, - GLenum attachment, - TextureID texture, - GLint level, - GLsizei numViews) +bool ValidateFramebufferTextureMultiviewBase(const Context *context, + angle::EntryPoint entryPoint, + GLenum target, + GLenum attachment, + TextureID texture, + GLint level, + GLsizei numViews) { - if (!(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultiviewNotAvailable); - return false; - } - if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level)) { return false; @@ -86,55 +89,8 @@ bool ValidateFramebufferTextureMultiviewLevelAndFormat(const Context *context, return true; } -bool ValidateUniformES3(const Context *context, - angle::EntryPoint entryPoint, - GLenum uniformType, - UniformLocation location, - GLint count) -{ - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - - return ValidateUniform(context, entryPoint, uniformType, location, count); -} - -bool ValidateUniformMatrixES3(const Context *context, - angle::EntryPoint entryPoint, - GLenum valueType, - UniformLocation location, - GLsizei count, - GLboolean transpose) -{ - // Check for ES3 uniform entry points - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - - return ValidateUniformMatrix(context, entryPoint, valueType, location, count, transpose); -} - -bool ValidateGenOrDeleteES3(const Context *context, angle::EntryPoint entryPoint, GLint n) -{ - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateGenOrDelete(context, entryPoint, n); -} - bool ValidateGenOrDeleteCountES3(const Context *context, angle::EntryPoint entryPoint, GLint count) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } if (count < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); @@ -153,18 +109,6 @@ bool ValidateCopyTexture3DCommon(const Context *context, GLint internalFormat, TextureTarget destTarget) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - - if (!context->getExtensions().copyTexture3dANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable); - return false; - } - if (!ValidTexture3DTarget(context, source->getType())) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget); @@ -608,31 +552,28 @@ bool ValidateES3TexImageParametersBase(const Context *context, break; case TextureType::CubeMapArray: - if (!isSubImage && width != height) + if (!isSubImage) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions); - return false; - } + if (width != height) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions); + return false; + } - if (width > (caps.maxCubeMapTextureSize >> level) || - height > (caps.maxCubeMapTextureSize >> level)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize); - return false; + if (depth % 6 != 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth); + return false; + } } - if (width > (caps.max3DTextureSize >> level) || - height > (caps.max3DTextureSize >> level) || depth > caps.max3DTextureSize) + if (width > (caps.maxCubeMapTextureSize >> level) || + height > (caps.maxCubeMapTextureSize >> level) || + depth > caps.maxArrayTextureLayers) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize); return false; } - - if (!isSubImage && depth % 6 != 0) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth); - return false; - } break; case TextureType::InvalidEnum: @@ -650,6 +591,12 @@ bool ValidateES3TexImageParametersBase(const Context *context, return false; } + if (context->getState().isTextureBoundToActivePLS(texture->id())) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture); + return false; + } + if (texture->getImmutableFormat() && !isSubImage) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable); @@ -1270,8 +1217,7 @@ bool ValidateES3CopyTexImageParametersBase(const Context *context, } } - // If width or height is zero, it is a no-op. Return false without setting an error. - return (width > 0 && height > 0); + return true; } bool ValidateES3CopyTexImage2DParameters(const Context *context, @@ -1335,7 +1281,8 @@ bool ValidateES3TexStorageParametersLevel(const Context *context, GLsizei depth) { GLsizei maxDim = std::max(width, height); - if (target != TextureType::_2DArray) + // The "depth" parameter of array texture types does not affect mip levels. + if (target == TextureType::_3D) { maxDim = std::max(maxDim, depth); } @@ -1433,14 +1380,7 @@ bool ValidateES3TexStorageParametersExtent(const Context *context, return false; } - if (width > caps.maxCubeMapTextureSize) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize); - return false; - } - - if (width > caps.max3DTextureSize || height > caps.max3DTextureSize || - depth > caps.max3DTextureSize) + if (width > caps.maxCubeMapTextureSize || depth > caps.maxArrayTextureLayers) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize); return false; @@ -1527,6 +1467,12 @@ bool ValidateES3TexStorageParametersFormat(const Context *context, return false; } + if (formatInfo.paletted) + { + ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat); + return false; + } + if (formatInfo.compressed) { if (target == TextureType::Rectangle) @@ -1560,6 +1506,12 @@ bool ValidateES3TexStorageParametersFormat(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize); return false; } + + if (formatInfo.compressedBlockDepth > 1 && target != TextureType::_3D) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget); + return false; + } } // From the ES 3.0 spec section 3.8.3: @@ -1666,23 +1618,11 @@ bool ValidateBeginQuery(const Context *context, QueryType target, QueryID id) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateBeginQueryBase(context, entryPoint, target, id); } bool ValidateEndQuery(const Context *context, angle::EntryPoint entryPoint, QueryType target) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateEndQueryBase(context, entryPoint, target); } @@ -1692,12 +1632,6 @@ bool ValidateGetQueryiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr); } @@ -1707,12 +1641,6 @@ bool ValidateGetQueryObjectuiv(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); } @@ -1724,12 +1652,6 @@ bool ValidateFramebufferTextureLayer(const Context *context, GLint level, GLint layer) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level)) { return false; @@ -1852,12 +1774,6 @@ bool ValidateInvalidateFramebuffer(const Context *context, GLsizei numAttachments, const GLenum *attachments) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - bool defaultFramebuffer = false; switch (target) @@ -1899,12 +1815,6 @@ bool ValidateInvalidateSubFramebuffer(const Context *context, bool ValidateClearBuffer(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer)) { @@ -1936,12 +1846,6 @@ bool ValidateDrawRangeElements(const Context *context, DrawElementsType type, const void *indices) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (end < start) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidElementRange); @@ -1968,23 +1872,11 @@ bool ValidateGetUniformuiv(const Context *context, UniformLocation location, const GLuint *params) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateGetUniformBase(context, entryPoint, program, location); } bool ValidateReadBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum src) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - const Framebuffer *readFBO = context->getState().getReadFramebuffer(); if (readFBO == nullptr) @@ -2038,12 +1930,6 @@ bool ValidateCompressedTexImage3D(const Context *context, GLsizei imageSize, const void *data) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!ValidTextureTarget(context, TextureTargetToType(target))) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget); @@ -2112,6 +1998,12 @@ bool ValidateCompressedTexImage3DRobustANGLE(const Context *context, GLsizei dataSize, const void *data) { + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().texture3DOES) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); + return false; + } + if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize)) { return false; @@ -2125,25 +2017,14 @@ bool ValidateBindVertexArray(const Context *context, angle::EntryPoint entryPoint, VertexArrayID array) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateBindVertexArrayBase(context, entryPoint, array); } -bool ValidateIsVertexArray(const Context *context, +bool ValidateIsVertexArray(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, VertexArrayID array) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return true; } @@ -2155,12 +2036,6 @@ static bool ValidateBindBufferCommon(const Context *context, GLintptr offset, GLsizeiptr size) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (buffer.value != 0 && offset < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset); @@ -2316,12 +2191,6 @@ bool ValidateProgramBinary(const Context *context, const void *binary, GLsizei length) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length); } @@ -2333,12 +2202,6 @@ bool ValidateGetProgramBinary(const Context *context, const GLenum *binaryFormat, const void *binary) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat, binary); } @@ -2349,8 +2212,10 @@ bool ValidateProgramParameteriBase(const Context *context, GLenum pname, GLint value) { - if (GetValidProgram(context, entryPoint, program) == nullptr) + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) { + // Error already generated. return false; } @@ -2392,12 +2257,6 @@ bool ValidateProgramParameteri(const Context *context, GLenum pname, GLint value) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateProgramParameteriBase(context, entryPoint, program, pname, value); } @@ -2414,12 +2273,6 @@ bool ValidateBlitFramebuffer(const Context *context, GLbitfield mask, GLenum filter) { - if (context->getClientMajorVersion() < 3 && !context->getExtensions().framebufferBlitNV) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } @@ -2430,6 +2283,13 @@ bool ValidateClearBufferiv(const Context *context, GLint drawbuffer, const GLint *value) { + // INVALID_VALUE is generated if the value pointer is NULL + if (value == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + switch (buffer) { case GL_COLOR: @@ -2523,6 +2383,12 @@ bool ValidateClearBufferuiv(const Context *context, return false; } + if (value == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateClearBuffer(context, entryPoint); } @@ -2578,6 +2444,12 @@ bool ValidateClearBufferfv(const Context *context, return false; } + if (value == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateClearBuffer(context, entryPoint); } @@ -2611,12 +2483,6 @@ bool ValidateDrawBuffers(const Context *context, GLsizei n, const GLenum *bufs) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateDrawBuffersBase(context, entryPoint, n, bufs); } @@ -2632,12 +2498,6 @@ bool ValidateCopyTexSubImage3D(const Context *context, GLsizei width, GLsizei height) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateES3CopyTexImage3DParameters(context, entryPoint, target, level, GL_NONE, true, xoffset, yoffset, zoffset, x, y, width, height, 0); } @@ -2808,12 +2668,6 @@ bool ValidateTexImage3D(const Context *context, GLenum type, const void *pixels) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat, false, false, 0, 0, 0, width, height, depth, border, format, type, -1, pixels); @@ -2833,9 +2687,9 @@ bool ValidateTexImage3DRobustANGLE(const Context *context, GLsizei bufSize, const void *pixels) { - if (context->getClientMajorVersion() < 3) + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().texture3DOES) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); return false; } @@ -2863,12 +2717,6 @@ bool ValidateTexSubImage3D(const Context *context, GLenum type, const void *pixels) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true, xoffset, yoffset, zoffset, width, height, depth, 0, format, type, -1, pixels); @@ -2889,9 +2737,9 @@ bool ValidateTexSubImage3DRobustANGLE(const Context *context, GLsizei bufSize, const void *pixels) { - if (context->getClientMajorVersion() < 3) + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().texture3DOES) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); return false; } @@ -2919,12 +2767,6 @@ bool ValidateCompressedTexSubImage3D(const Context *context, GLsizei imageSize, const void *data) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, true, true, xoffset, yoffset, zoffset, width, height, depth, 0, format, GL_NONE, -1, data)) @@ -2981,6 +2823,12 @@ bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context, GLsizei dataSize, const void *data) { + if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().texture3DOES) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); + return false; + } + if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize)) { return false; @@ -2995,7 +2843,7 @@ bool ValidateGenQueries(const Context *context, GLsizei n, const QueryID *queries) { - return ValidateGenOrDeleteES3(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, queries); } bool ValidateDeleteQueries(const Context *context, @@ -3003,7 +2851,7 @@ bool ValidateDeleteQueries(const Context *context, GLsizei n, const QueryID *queries) { - return ValidateGenOrDeleteES3(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, queries); } bool ValidateGenSamplers(const Context *context, @@ -3011,6 +2859,12 @@ bool ValidateGenSamplers(const Context *context, GLsizei count, const SamplerID *samplers) { + if (samplers == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateGenOrDeleteCountES3(context, entryPoint, count); } @@ -3019,6 +2873,12 @@ bool ValidateDeleteSamplers(const Context *context, GLsizei count, const SamplerID *samplers) { + if (samplers == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + return ValidateGenOrDeleteCountES3(context, entryPoint, count); } @@ -3027,7 +2887,7 @@ bool ValidateGenTransformFeedbacks(const Context *context, GLsizei n, const TransformFeedbackID *ids) { - return ValidateGenOrDeleteES3(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, ids); } bool ValidateDeleteTransformFeedbacks(const Context *context, @@ -3035,7 +2895,7 @@ bool ValidateDeleteTransformFeedbacks(const Context *context, GLsizei n, const TransformFeedbackID *ids) { - if (!ValidateGenOrDeleteES3(context, entryPoint, n)) + if (!ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, ids)) { return false; } @@ -3057,7 +2917,7 @@ bool ValidateGenVertexArrays(const Context *context, GLsizei n, const VertexArrayID *arrays) { - return ValidateGenOrDeleteES3(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, arrays); } bool ValidateDeleteVertexArrays(const Context *context, @@ -3065,18 +2925,13 @@ bool ValidateDeleteVertexArrays(const Context *context, GLsizei n, const VertexArrayID *arrays) { - return ValidateGenOrDeleteES3(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, arrays); } bool ValidateBeginTransformFeedback(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode primitiveMode) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } switch (primitiveMode) { case PrimitiveMode::Triangles: @@ -3148,12 +3003,6 @@ bool ValidateGetBufferPointerv(const Context *context, GLenum pname, void *const *params) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params); } @@ -3172,9 +3021,9 @@ bool ValidateGetBufferPointervRobustANGLE(const Context *context, GLsizei numParams = 0; - if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapbufferOES) + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().mapbufferOES) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported); return false; } @@ -3195,12 +3044,6 @@ bool ValidateGetBufferPointervRobustANGLE(const Context *context, bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding target) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateUnmapBufferBase(context, entryPoint, target); } @@ -3211,12 +3054,6 @@ bool ValidateMapBufferRange(const Context *context, GLsizeiptr length, GLbitfield access) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access); } @@ -3226,12 +3063,6 @@ bool ValidateFlushMappedBufferRange(const Context *context, GLintptr offset, GLsizeiptr length) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length); } @@ -3384,11 +3215,6 @@ bool ValidateGetIntegeri_v(const Context *context, GLuint index, const GLint *data) { - if (context->getClientVersion() < ES_3_0) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr); } @@ -3434,11 +3260,6 @@ bool ValidateGetInteger64i_v(const Context *context, GLuint index, const GLint64 *data) { - if (context->getClientVersion() < ES_3_0) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr); } @@ -3486,12 +3307,6 @@ bool ValidateCopyBufferSubData(const Context *context, GLintptr writeOffset, GLsizeiptr size) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes); @@ -3586,12 +3401,6 @@ bool ValidateGetStringi(const Context *context, GLenum name, GLuint index) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - switch (name) { case GL_EXTENSIONS: @@ -3631,12 +3440,6 @@ bool ValidateRenderbufferStorageMultisample(const Context *context, GLsizei width, GLsizei height) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples, internalformat, width, height)) { @@ -3659,7 +3462,7 @@ bool ValidateRenderbufferStorageMultisample(const Context *context, // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY. const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (static_cast(samples) > formatCaps.getMaxSamples()) + if (static_cast(samples) > formatCaps.sampleCounts.getMaxSamples()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange); return false; @@ -3676,13 +3479,9 @@ bool ValidateVertexAttribIPointer(const Context *context, GLsizei stride, const void *pointer) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - - if (!ValidateIntegerVertexFormat(context, entryPoint, index, size, type)) + if (!ValidateIntegerVertexFormat(context->getPrivateState(), context->getPrivateStateCache(), + context->getMutableErrorSetForValidation(), entryPoint, index, + size, type)) { return false; } @@ -3739,40 +3538,33 @@ bool ValidateGetSynciv(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked, GLenum pname, - GLsizei bufSize, + GLsizei count, const GLsizei *length, const GLint *values) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - - if (bufSize < 0) + if (count < 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); return false; } if (context->isContextLost()) { - ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); - if (pname == GL_SYNC_STATUS) { - // Generate an error but still return true, the context still needs to return a - // value in this case. + // The context needs to return a value in this case. + // It will also generate a CONTEXT_LOST error. return true; } else { + ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost); return false; } } Sync *syncObject = context->getSync(syncPacked); - if (!syncObject) + if (syncObject == nullptr) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing); return false; @@ -3802,12 +3594,6 @@ bool ValidateDrawElementsInstanced(const Context *context, const void *indices, GLsizei instanceCount) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, instanceCount, 0); } @@ -3820,12 +3606,7 @@ bool ValidateMultiDrawArraysInstancedANGLE(const Context *context, const GLsizei *instanceCounts, GLsizei drawcount) { - if (!context->getExtensions().multiDrawANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { if (!context->getExtensions().instancedArraysAny()) { @@ -3837,6 +3618,11 @@ bool ValidateMultiDrawArraysInstancedANGLE(const Context *context, return false; } } + if (drawcount < 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount); + return false; + } for (GLsizei drawID = 0; drawID < drawcount; ++drawID) { if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, firsts[drawID], @@ -3857,12 +3643,7 @@ bool ValidateMultiDrawElementsInstancedANGLE(const Context *context, const GLsizei *instanceCounts, GLsizei drawcount) { - if (!context->getExtensions().multiDrawANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { if (!context->getExtensions().instancedArraysAny()) { @@ -3874,6 +3655,11 @@ bool ValidateMultiDrawElementsInstancedANGLE(const Context *context, return false; } } + if (drawcount < 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount); + return false; + } for (GLsizei drawID = 0; drawID < drawcount; ++drawID) { if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, counts[drawID], type, @@ -3893,12 +3679,6 @@ bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context, GLsizei instanceCount, GLuint baseInstance) { - if (!context->getExtensions().baseVertexBaseInstanceANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount, baseInstance); } @@ -3913,12 +3693,6 @@ bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *con GLint baseVertex, GLuint baseInstance) { - if (!context->getExtensions().baseVertexBaseInstanceANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, instanceCount, baseInstance); } @@ -3939,6 +3713,7 @@ bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context, } if (drawcount < 0) { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount); return false; } for (GLsizei drawID = 0; drawID < drawcount; ++drawID) @@ -3971,6 +3746,7 @@ bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context } if (drawcount < 0) { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount); return false; } for (GLsizei drawID = 0; drawID < drawcount; ++drawID) @@ -3994,8 +3770,8 @@ bool ValidateFramebufferTextureMultiviewOVR(const Context *context, GLint baseViewIndex, GLsizei numViews) { - if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, entryPoint, target, attachment, - texture, level, numViews)) + if (!ValidateFramebufferTextureMultiviewBase(context, entryPoint, target, attachment, texture, + level, numViews)) { return false; } @@ -4048,12 +3824,62 @@ bool ValidateFramebufferTextureMultiviewOVR(const Context *context, return true; } +bool ValidateFramebufferTextureMultisampleMultiviewOVR(const Context *context, + angle::EntryPoint entryPoint, + GLenum target, + GLenum attachment, + TextureID texturePacked, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews) +{ + // OVR_multiview_multisampled_render_to_texture states that , , , + // , , and correspond to the same parameters for + // FramebufferTextureMultiviewOVR and have the same restrictions and errors. + if (!ValidateFramebufferTextureMultiviewOVR(context, entryPoint, target, attachment, + texturePacked, level, baseViewIndex, numViews)) + { + return false; + } + + // OVR_multiview_multisampled_render_to_texture states that the value of samples + // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples) + // otherwise GL_INVALID_VALUE is generated. + if (samples < 0 || samples > context->getCaps().maxSamples) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesOutOfRange); + return false; + } + + // OVR_multiview_multisampled_render_to_texture says corresponds to the same parameter + // for FramebufferTexture2DMultisampleEXT and has the same restrictions and errors. + // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than + // the maximum sample number supported by this format is passed. + // The getMaxSamples method is only guaranteed to be valid when the context is ES3. + if (texturePacked.value != 0 && context->getClientVersion() >= ES_3_0) + { + Texture *tex = context->getTexture(texturePacked); + GLenum sizedInternalFormat = + tex->getFormat(TextureTypeToTarget(tex->getType(), baseViewIndex), level) + .info->sizedInternalFormat; + const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); + if (static_cast(samples) > formatCaps.sampleCounts.getMaxSamples()) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange); + return false; + } + } + + return true; +} + bool ValidateUniform1ui(const Context *context, angle::EntryPoint entryPoint, UniformLocation location, GLuint v0) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, 1); + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT, location, 1); } bool ValidateUniform2ui(const Context *context, @@ -4062,7 +3888,7 @@ bool ValidateUniform2ui(const Context *context, GLuint v0, GLuint v1) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1); + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1); } bool ValidateUniform3ui(const Context *context, @@ -4072,7 +3898,7 @@ bool ValidateUniform3ui(const Context *context, GLuint v1, GLuint v2) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1); + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1); } bool ValidateUniform4ui(const Context *context, @@ -4083,7 +3909,7 @@ bool ValidateUniform4ui(const Context *context, GLuint v2, GLuint v3) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1); + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1); } bool ValidateUniform1uiv(const Context *context, @@ -4092,7 +3918,13 @@ bool ValidateUniform1uiv(const Context *context, GLsizei count, const GLuint *value) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, count); + if (!ValidateUniformValuePointer(context, entryPoint, value)) + { + // Error already generated. + return false; + } + + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT, location, count); } bool ValidateUniform2uiv(const Context *context, @@ -4101,7 +3933,12 @@ bool ValidateUniform2uiv(const Context *context, GLsizei count, const GLuint *value) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count); + if (!ValidateUniformValuePointer(context, entryPoint, value)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count); } bool ValidateUniform3uiv(const Context *context, @@ -4110,7 +3947,12 @@ bool ValidateUniform3uiv(const Context *context, GLsizei count, const GLuint *value) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count); + if (!ValidateUniformValuePointer(context, entryPoint, value)) + { + // Error already generated. + return false; + } + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count); } bool ValidateUniform4uiv(const Context *context, @@ -4119,17 +3961,17 @@ bool ValidateUniform4uiv(const Context *context, GLsizei count, const GLuint *value) { - return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count); -} - -bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id) -{ - if (context->getClientMajorVersion() < 3) + if (!ValidateUniformValuePointer(context, entryPoint, value)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + // Error already generated. return false; } + return ValidateUniform(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count); +} + +bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id) +{ return true; } @@ -4140,8 +3982,7 @@ bool ValidateUniformMatrix2x3fv(const Context *context, GLboolean transpose, const GLfloat *value) { - return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x3, location, count, - transpose); + return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT2x3, location, count, transpose); } bool ValidateUniformMatrix3x2fv(const Context *context, @@ -4151,8 +3992,7 @@ bool ValidateUniformMatrix3x2fv(const Context *context, GLboolean transpose, const GLfloat *value) { - return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x2, location, count, - transpose); + return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT3x2, location, count, transpose); } bool ValidateUniformMatrix2x4fv(const Context *context, @@ -4162,8 +4002,7 @@ bool ValidateUniformMatrix2x4fv(const Context *context, GLboolean transpose, const GLfloat *value) { - return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x4, location, count, - transpose); + return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT2x4, location, count, transpose); } bool ValidateUniformMatrix4x2fv(const Context *context, @@ -4173,8 +4012,7 @@ bool ValidateUniformMatrix4x2fv(const Context *context, GLboolean transpose, const GLfloat *value) { - return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x2, location, count, - transpose); + return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT4x2, location, count, transpose); } bool ValidateUniformMatrix3x4fv(const Context *context, @@ -4184,8 +4022,7 @@ bool ValidateUniformMatrix3x4fv(const Context *context, GLboolean transpose, const GLfloat *value) { - return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x4, location, count, - transpose); + return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT3x4, location, count, transpose); } bool ValidateUniformMatrix4x3fv(const Context *context, @@ -4195,18 +4032,11 @@ bool ValidateUniformMatrix4x3fv(const Context *context, GLboolean transpose, const GLfloat *value) { - return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x3, location, count, - transpose); + return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT4x3, location, count, transpose); } bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); ASSERT(transformFeedback != nullptr); @@ -4226,12 +4056,6 @@ bool ValidateTransformFeedbackVaryings(const Context *context, const GLchar *const *varyings, GLenum bufferMode) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (count < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); @@ -4258,8 +4082,9 @@ bool ValidateTransformFeedbackVaryings(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4276,12 +4101,6 @@ bool ValidateGetTransformFeedbackVarying(const Context *context, const GLenum *type, const GLchar *name) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (bufSize < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); @@ -4289,8 +4108,9 @@ bool ValidateGetTransformFeedbackVarying(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4309,12 +4129,6 @@ bool ValidateBindTransformFeedback(const Context *context, GLenum target, TransformFeedbackID id) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - switch (target) { case GL_TRANSFORM_FEEDBACK: @@ -4349,23 +4163,11 @@ bool ValidateIsTransformFeedback(const Context *context, angle::EntryPoint entryPoint, TransformFeedbackID id) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return true; } bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); ASSERT(transformFeedback != nullptr); @@ -4387,12 +4189,6 @@ bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint en bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); ASSERT(transformFeedback != nullptr); @@ -4428,12 +4224,6 @@ bool ValidateVertexAttribI4i(const PrivateState &state, GLint z, GLint w) { - if (state.getClientMajorVersion() < 3) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateVertexAttribIndex(state, errors, entryPoint, index); } @@ -4446,12 +4236,6 @@ bool ValidateVertexAttribI4ui(const PrivateState &state, GLuint z, GLuint w) { - if (state.getClientMajorVersion() < 3) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateVertexAttribIndex(state, errors, entryPoint, index); } @@ -4461,9 +4245,9 @@ bool ValidateVertexAttribI4iv(const PrivateState &state, GLuint index, const GLint *v) { - if (state.getClientMajorVersion() < 3) + if (v == nullptr) { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); + errors->validationError(entryPoint, GL_INVALID_VALUE, kVertexAttributeValueNULL); return false; } @@ -4476,9 +4260,9 @@ bool ValidateVertexAttribI4uiv(const PrivateState &state, GLuint index, const GLuint *v) { - if (state.getClientMajorVersion() < 3) + if (v == nullptr) { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); + errors->validationError(entryPoint, GL_INVALID_VALUE, kVertexAttributeValueNULL); return false; } @@ -4490,21 +4274,22 @@ bool ValidateGetFragDataLocation(const Context *context, ShaderProgramID program, const GLchar *name) { - if (context->getClientMajorVersion() < 3) + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + // Error already generated. return false; } - Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (!programObject->isLinked()) { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); return false; } - if (!programObject->isLinked()) + if (name == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFragDataNamePointer); return false; } @@ -4518,12 +4303,6 @@ bool ValidateGetUniformIndices(const Context *context, const GLchar *const *uniformNames, const GLuint *uniformIndices) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (uniformCount < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); @@ -4531,8 +4310,9 @@ bool ValidateGetUniformIndices(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4547,12 +4327,6 @@ bool ValidateGetActiveUniformsiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (uniformCount < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); @@ -4560,8 +4334,9 @@ bool ValidateGetActiveUniformsiv(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4615,15 +4390,10 @@ bool ValidateGetUniformBlockIndex(const Context *context, ShaderProgramID program, const GLchar *uniformBlockName) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4649,21 +4419,22 @@ bool ValidateGetActiveUniformBlockName(const Context *context, const GLsizei *length, const GLchar *uniformBlockName) { - if (context->getClientMajorVersion() < 3) + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + // Error already generated. return false; } - Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (uniformBlockIndex.value >= programObject->getExecutable().getUniformBlocks().size()) { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock); return false; } - if (uniformBlockIndex.value >= programObject->getExecutable().getUniformBlocks().size()) + if (uniformBlockName == nullptr) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformBlockNameNull); return false; } @@ -4676,12 +4447,6 @@ bool ValidateUniformBlockBinding(const Context *context, UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (uniformBlockBinding >= static_cast(context->getCaps().maxUniformBufferBindings)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings); @@ -4689,8 +4454,9 @@ bool ValidateUniformBlockBinding(const Context *context, } Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } @@ -4711,12 +4477,6 @@ bool ValidateDrawArraysInstanced(const Context *context, GLsizei count, GLsizei primcount) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0); } @@ -4725,12 +4485,6 @@ bool ValidateFenceSync(const Context *context, GLenum condition, GLbitfield flags) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFenceCondition); @@ -4748,23 +4502,11 @@ bool ValidateFenceSync(const Context *context, bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return true; } bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (syncPacked.value != 0 && !context->getSync(syncPacked)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing); @@ -4780,12 +4522,6 @@ bool ValidateClientWaitSync(const Context *context, GLbitfield flags, GLuint64 timeout) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags); @@ -4808,12 +4544,6 @@ bool ValidateWaitSync(const Context *context, GLbitfield flags, GLuint64 timeout) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (flags != 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags); @@ -4841,12 +4571,6 @@ bool ValidateGetInteger64v(const Context *context, GLenum pname, const GLint64 *params) { - if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - GLenum nativeType = GL_NONE; unsigned int numParams = 0; if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams)) @@ -4859,12 +4583,6 @@ bool ValidateGetInteger64v(const Context *context, bool ValidateIsSampler(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - return true; } @@ -4873,12 +4591,6 @@ bool ValidateBindSampler(const Context *context, GLuint unit, SamplerID sampler) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (GetIDValue(sampler) != 0 && !context->isSampler(sampler)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler); @@ -4894,19 +4606,13 @@ bool ValidateBindSampler(const Context *context, return true; } -bool ValidateVertexAttribDivisor(const Context *context, +bool ValidateVertexAttribDivisor(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLuint divisor) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - - return ValidateVertexAttribIndex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), entryPoint, index); + return ValidateVertexAttribIndex(privateState, errors, entryPoint, index); } bool ValidateTexStorage2D(const Context *context, @@ -4917,12 +4623,6 @@ bool ValidateTexStorage2D(const Context *context, GLsizei width, GLsizei height) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalformat, width, height, 1)) { @@ -4941,12 +4641,6 @@ bool ValidateTexStorage3D(const Context *context, GLsizei height, GLsizei depth) { - if (context->getClientMajorVersion() < 3) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - return false; - } - if (!ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat, width, height, depth)) { @@ -4971,7 +4665,7 @@ bool ValidateGetSamplerParameterfv(const Context *context, GLenum pname, const GLfloat *params) { - return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr); + return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr, params); } bool ValidateGetSamplerParameteriv(const Context *context, @@ -4980,7 +4674,7 @@ bool ValidateGetSamplerParameteriv(const Context *context, GLenum pname, const GLint *params) { - return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr); + return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr, params); } bool ValidateSamplerParameterf(const Context *context, @@ -5025,7 +4719,7 @@ bool ValidateGetVertexAttribIiv(const Context *context, GLenum pname, const GLint *params) { - return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true); + return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false); } bool ValidateGetVertexAttribIuiv(const Context *context, @@ -5034,7 +4728,7 @@ bool ValidateGetVertexAttribIuiv(const Context *context, GLenum pname, const GLuint *params) { - return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true); + return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false); } bool ValidateGetInternalformativ(const Context *context, @@ -5042,11 +4736,11 @@ bool ValidateGetInternalformativ(const Context *context, GLenum target, GLenum internalformat, GLenum pname, - GLsizei bufSize, + GLsizei count, const GLint *params) { return ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname, - bufSize, nullptr); + count, nullptr); } bool ValidateBindFragDataLocationIndexedEXT(const Context *context, @@ -5056,12 +4750,7 @@ bool ValidateBindFragDataLocationIndexedEXT(const Context *context, GLuint index, const char *name) { - if (!context->getExtensions().blendFuncExtendedEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); return false; @@ -5091,11 +4780,14 @@ bool ValidateBindFragDataLocationIndexedEXT(const Context *context, return false; } } + Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } + return true; } @@ -5114,26 +4806,25 @@ bool ValidateGetFragDataIndexEXT(const Context *context, ShaderProgramID program, const char *name) { - if (!context->getExtensions().blendFuncExtendedEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); return false; } + Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } + if (!programObject->isLinked()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); return false; } + return true; } @@ -5146,12 +4837,6 @@ bool ValidateTexStorage2DMultisampleANGLE(const Context *context, GLsizei height, GLboolean fixedSampleLocations) { - if (!context->getExtensions().textureMultisampleANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required); - return false; - } - return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat, width, height); } @@ -5163,12 +4848,6 @@ bool ValidateGetTexLevelParameterfvANGLE(const Context *context, GLenum pname, const GLfloat *params) { - if (!context->getExtensions().getTexLevelParameterANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr); } @@ -5179,12 +4858,6 @@ bool ValidateGetTexLevelParameterivANGLE(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().getTexLevelParameterANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr); } @@ -5194,12 +4867,6 @@ bool ValidateGetMultisamplefvANGLE(const Context *context, GLuint index, const GLfloat *val) { - if (!context->getExtensions().textureMultisampleANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required); - return false; - } - return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val); } @@ -5209,13 +4876,6 @@ bool ValidateSampleMaskiANGLE(const PrivateState &state, GLuint maskNumber, GLbitfield mask) { - if (!state.getExtensions().textureMultisampleANGLE) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, - kMultisampleTextureExtensionOrES31Required); - return false; - } - return ValidateSampleMaskiBase(state, errors, entryPoint, maskNumber, mask); } } // namespace gl diff --git a/src/libANGLE/validationES3.h b/src/libANGLE/validationES3.h index d3a52dc9f08..675bb1f1901 100644 --- a/src/libANGLE/validationES3.h +++ b/src/libANGLE/validationES3.h @@ -14,6 +14,9 @@ namespace gl { + +void RecordVersionErrorES30(const Context *context, angle::EntryPoint entryPoint); + bool ValidateTexImageFormatCombination(const Context *context, angle::EntryPoint entryPoint, TextureType target, diff --git a/src/libANGLE/validationES31.cpp b/src/libANGLE/validationES31.cpp index a3725cf2745..e500880e168 100644 --- a/src/libANGLE/validationES31.cpp +++ b/src/libANGLE/validationES31.cpp @@ -6,6 +6,10 @@ // validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/validationES31_autogen.h" #include "libANGLE/Context.h" @@ -26,6 +30,11 @@ namespace gl { using namespace err; +void RecordVersionErrorES31(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES31); +} + namespace { @@ -325,11 +334,24 @@ bool ValidateProgramUniformBase(const Context *context, UniformLocation location, GLsizei count) { + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) + { + // Error already generated. + return false; + } + const LinkedUniform *uniform = nullptr; - Program *programObject = GetValidProgram(context, entryPoint, program); - return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, - &uniform) && - ValidateUniformValue(context, entryPoint, valueType, uniform->getType()); + if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform)) + { + // Error already generated. + return false; + } + if (uniform == nullptr) + { + return true; // no-op + } + return ValidateUniformValue(context, entryPoint, valueType, uniform->getType()); } bool ValidateProgramUniformMatrixBase(const Context *context, @@ -340,35 +362,43 @@ bool ValidateProgramUniformMatrixBase(const Context *context, GLsizei count, GLboolean transpose) { + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) + { + // Error already generated. + return false; + } + const LinkedUniform *uniform = nullptr; - Program *programObject = GetValidProgram(context, entryPoint, program); - return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, - &uniform) && - ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType()); + if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform)) + { + // Error already generated. + return false; + } + if (uniform == nullptr) + { + return true; // no-op + } + return ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType()); } -bool ValidateVertexAttribFormatCommon(const Context *context, +bool ValidateVertexAttribFormatCommon(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint relativeOffset) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - - const Caps &caps = context->getCaps(); + const Caps &caps = privateState.getCaps(); if (relativeOffset > static_cast(caps.maxVertexAttribRelativeOffset)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kRelativeOffsetTooLarge); + errors->validationError(entryPoint, GL_INVALID_VALUE, kRelativeOffsetTooLarge); return false; } // [OpenGL ES 3.1] Section 10.3.1 page 243: // An INVALID_OPERATION error is generated if the default vertex array object is bound. - if (context->getState().getVertexArrayId().value == 0) + if (privateState.getVertexArrayId().value == 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultVertexArray); + errors->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); return false; } @@ -383,13 +413,6 @@ bool ValidateGetBooleani_v(const Context *context, GLuint index, const GLboolean *data) { - if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny()) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, - kES31OrDrawBuffersIndexedExtensionNotAvailable); - return false; - } - if (!ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr)) { return false; @@ -406,10 +429,9 @@ bool ValidateGetBooleani_vRobustANGLE(const Context *context, const GLsizei *length, const GLboolean *data) { - if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny()) + if (context->getClientVersion() < ES_3_1) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, - kES31OrDrawBuffersIndexedExtensionNotAvailable); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); return false; } @@ -439,12 +461,6 @@ bool ValidateDrawIndirectBase(const Context *context, PrimitiveMode mode, const void *indirect) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - // Here the third parameter 1 is only to pass the count validation. if (!ValidateDrawBase(context, entryPoint, mode)) { @@ -461,7 +477,7 @@ bool ValidateDrawIndirectBase(const Context *context, return false; } - if (context->getStateCache().hasAnyActiveClientAttrib()) + if (context->hasAnyActiveClientAttrib()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kClientDataInVertexArray); return false; @@ -498,16 +514,7 @@ bool ValidateDrawArraysIndirect(const Context *context, { // EXT_geometry_shader allows transform feedback to work with all draw commands. // [EXT_geometry_shader] Section 12.1, "Transform Feedback" - if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2) - { - if (!ValidateTransformFeedbackPrimitiveMode( - context, entryPoint, curTransformFeedback->getPrimitiveMode(), mode)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback); - return false; - } - } - else + if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2) { // An INVALID_OPERATION error is generated if transform feedback is active and not // paused. @@ -577,12 +584,6 @@ bool ValidateMultiDrawIndirectBase(const Context *context, GLsizei drawcount, GLsizei stride) { - if (!context->getExtensions().multiDrawIndirectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - // An INVALID_VALUE error is generated if stride is neither 0 nor a multiple of 4. if ((stride & 3) != 0) { @@ -742,11 +743,24 @@ bool ValidateProgramUniform1ivBase(const Context *context, GLsizei count, const GLint *value) { + Program *programObject = GetValidProgram(context, entryPoint, program); + if (programObject == nullptr) + { + // Error already generated. + return false; + } + const LinkedUniform *uniform = nullptr; - Program *programObject = GetValidProgram(context, entryPoint, program); - return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, - &uniform) && - ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value); + if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform)) + { + // Error already generated. + return false; + } + if (uniform == nullptr) + { + return true; // no-op + } + return ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value); } bool ValidateProgramUniform2ivBase(const Context *context, @@ -978,12 +992,6 @@ bool ValidateGetTexLevelParameterfv(const Context *context, GLenum pname, const GLfloat *params) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr); } @@ -1007,12 +1015,6 @@ bool ValidateGetTexLevelParameteriv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr); } @@ -1038,12 +1040,6 @@ bool ValidateTexStorage2DMultisample(const Context *context, GLsizei height, GLboolean fixedSampleLocations) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat, width, height); } @@ -1059,12 +1055,6 @@ bool ValidateTexStorageMem2DMultisampleEXT(const Context *context, MemoryObjectID memory, GLuint64 offset) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1075,12 +1065,6 @@ bool ValidateGetMultisamplefv(const Context *context, GLuint index, const GLfloat *val) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val); } @@ -1102,12 +1086,6 @@ bool ValidateFramebufferParameteri(const Context *context, GLenum pname, GLint param) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateFramebufferParameteriBase(context, entryPoint, target, pname, param); } @@ -1117,12 +1095,6 @@ bool ValidateGetFramebufferParameteriv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGetFramebufferParameterivBase(context, entryPoint, target, pname, params); } @@ -1144,15 +1116,10 @@ bool ValidateGetProgramResourceIndex(const Context *context, GLenum programInterface, const GLchar *name) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } @@ -1172,12 +1139,6 @@ bool ValidateBindVertexBuffer(const Context *context, GLintptr offset, GLsizei stride) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - if (!context->isBufferGenerated(buffer)) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated); @@ -1214,36 +1175,33 @@ bool ValidateBindVertexBuffer(const Context *context, return true; } -bool ValidateVertexBindingDivisor(const Context *context, +bool ValidateVertexBindingDivisor(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint bindingIndex, GLuint divisor) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - - const Caps &caps = context->getCaps(); + const Caps &caps = privateState.getCaps(); if (bindingIndex >= static_cast(caps.maxVertexAttribBindings)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings); + errors->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings); return false; } // [OpenGL ES 3.1] Section 10.3.1 page 243: // An INVALID_OPERATION error is generated if the default vertex array object is bound. - if (context->getState().getVertexArrayId().value == 0) + if (privateState.getVertexArrayId().value == 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultVertexArray); + errors->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); return false; } return true; } -bool ValidateVertexAttribFormat(const Context *context, +bool ValidateVertexAttribFormat(const PrivateState &privateState, + const PrivateStateCache &privateStateCache, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint attribindex, GLint size, @@ -1251,58 +1209,57 @@ bool ValidateVertexAttribFormat(const Context *context, GLboolean normalized, GLuint relativeoffset) { - if (!ValidateVertexAttribFormatCommon(context, entryPoint, relativeoffset)) + if (!ValidateVertexAttribFormatCommon(privateState, errors, entryPoint, relativeoffset)) { return false; } - return ValidateFloatVertexFormat(context, entryPoint, attribindex, size, type); + return ValidateFloatVertexFormat(privateState, privateStateCache, errors, entryPoint, + attribindex, size, type); } -bool ValidateVertexAttribIFormat(const Context *context, +bool ValidateVertexAttribIFormat(const PrivateState &privateState, + const PrivateStateCache &privateStateCache, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint attribindex, GLint size, VertexAttribType type, GLuint relativeoffset) { - if (!ValidateVertexAttribFormatCommon(context, entryPoint, relativeoffset)) + if (!ValidateVertexAttribFormatCommon(privateState, errors, entryPoint, relativeoffset)) { return false; } - return ValidateIntegerVertexFormat(context, entryPoint, attribindex, size, type); + return ValidateIntegerVertexFormat(privateState, privateStateCache, errors, entryPoint, + attribindex, size, type); } -bool ValidateVertexAttribBinding(const Context *context, +bool ValidateVertexAttribBinding(const PrivateState &privateState, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint attribIndex, GLuint bindingIndex) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - // [OpenGL ES 3.1] Section 10.3.1 page 243: // An INVALID_OPERATION error is generated if the default vertex array object is bound. - if (context->getState().getVertexArrayId().value == 0) + if (privateState.getVertexArrayId().value == 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultVertexArray); + errors->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); return false; } - const Caps &caps = context->getCaps(); + const Caps &caps = privateState.getCaps(); if (attribIndex >= static_cast(caps.maxVertexAttributes)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); + errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); return false; } if (bindingIndex >= static_cast(caps.maxVertexAttribBindings)) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings); + errors->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings); return false; } @@ -1318,15 +1275,10 @@ bool ValidateGetProgramResourceName(const Context *context, const GLsizei *length, const GLchar *name) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } @@ -1357,12 +1309,6 @@ bool ValidateDispatchCompute(const Context *context, GLuint numGroupsY, GLuint numGroupsZ) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - const State &state = context->getState(); const ProgramExecutable *executable = state.getLinkedProgramExecutable(context); @@ -1396,12 +1342,6 @@ bool ValidateDispatchComputeIndirect(const Context *context, angle::EntryPoint entryPoint, GLintptr indirect) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - const State &state = context->getState(); const ProgramExecutable *executable = state.getProgramExecutable(); @@ -1452,12 +1392,6 @@ bool ValidateBindImageTexture(const Context *context, GLenum access, GLenum format) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - GLuint maxImageUnits = static_cast(context->getCaps().maxImageUnits); if (unit >= maxImageUnits) { @@ -1542,15 +1476,10 @@ bool ValidateGetProgramResourceLocation(const Context *context, GLenum programInterface, const GLchar *name) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } @@ -1575,21 +1504,17 @@ bool ValidateGetProgramResourceiv(const Context *context, GLuint index, GLsizei propCount, const GLenum *props, - GLsizei bufSize, + GLsizei count, const GLsizei *length, const GLint *params) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } + if (!ValidateProgramInterface(programInterface)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidProgramInterface); @@ -1600,9 +1525,9 @@ bool ValidateGetProgramResourceiv(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidPropCount); return false; } - if (bufSize < 0) + if (count < 0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount); return false; } if (!ValidateProgramResourceIndex(programObject, programInterface, index)) @@ -1633,15 +1558,10 @@ bool ValidateGetProgramInterfaceiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - Program *programObject = GetValidProgram(context, entryPoint, program); if (programObject == nullptr) { + // Error already generated. return false; } @@ -1705,7 +1625,8 @@ bool ValidateGenProgramPipelinesBase(const Context *context, GLsizei n, const ProgramPipelineID *pipelines) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + pipelines); } bool ValidateDeleteProgramPipelinesBase(const Context *context, @@ -1713,7 +1634,8 @@ bool ValidateDeleteProgramPipelinesBase(const Context *context, GLsizei n, const ProgramPipelineID *pipelines) { - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + pipelines); } bool ValidateBindProgramPipelineBase(const Context *context, @@ -1767,7 +1689,7 @@ bool ValidateUseProgramStagesBase(const Context *context, // GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call // to glGenProgramPipelines or if such a name has been deleted by a call to // glDeleteProgramPipelines. - if (!context->isProgramPipelineGenerated({pipeline})) + if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated({pipeline}))) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated); return false; @@ -1818,7 +1740,7 @@ bool ValidateActiveShaderProgramBase(const Context *context, // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous // call to GenProgramPipelines or if such a name has since been deleted by // DeleteProgramPipelines. - if (!context->isProgramPipelineGenerated({pipeline})) + if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated({pipeline}))) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated); return false; @@ -1897,16 +1819,6 @@ bool ValidateCreateShaderProgramvBase(const Context *context, return true; } -bool ValidateCreateShaderProgramvBase(const Context *context, - angle::EntryPoint entryPoint, - ShaderType type, - GLsizei count, - const GLchar **strings) -{ - const GLchar *const *tmpStrings = strings; - return ValidateCreateShaderProgramvBase(context, entryPoint, type, count, tmpStrings); -} - bool ValidateGetProgramPipelineivBase(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipeline, @@ -1954,12 +1866,10 @@ bool ValidateValidateProgramPipelineBase(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipeline) { - if (pipeline.value == 0) - { - return false; - } - - if (!context->isProgramPipelineGenerated(pipeline)) + // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous + // call to GenProgramPipelines or if such a name has since been deleted by + // DeleteProgramPipelines. + if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated(pipeline))) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramPipelineDoesNotExist); return false; @@ -1981,6 +1891,12 @@ bool ValidateGetProgramPipelineInfoLogBase(const Context *context, return false; } + if (bufSize > 0 && infoLog == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kProgramPipelineInfoLogNULL); + return false; + } + if (!context->isProgramPipelineGenerated(pipeline)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kProgramPipelineDoesNotExist); @@ -1995,12 +1911,6 @@ bool ValidateActiveShaderProgram(const Context *context, ProgramPipelineID pipelinePacked, ShaderProgramID programPacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateActiveShaderProgramBase(context, entryPoint, pipelinePacked, programPacked); } @@ -2008,12 +1918,6 @@ bool ValidateBindProgramPipeline(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateBindProgramPipelineBase(context, entryPoint, pipelinePacked); } @@ -2023,12 +1927,6 @@ bool ValidateCreateShaderProgramv(const Context *context, GLsizei count, const GLchar *const *strings) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateCreateShaderProgramvBase(context, entryPoint, typePacked, count, strings); } @@ -2037,12 +1935,6 @@ bool ValidateDeleteProgramPipelines(const Context *context, GLsizei n, const ProgramPipelineID *pipelinesPacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateDeleteProgramPipelinesBase(context, entryPoint, n, pipelinesPacked); } @@ -2051,12 +1943,6 @@ bool ValidateGenProgramPipelines(const Context *context, GLsizei n, const ProgramPipelineID *pipelinesPacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGenProgramPipelinesBase(context, entryPoint, n, pipelinesPacked); } @@ -2067,12 +1953,6 @@ bool ValidateGetProgramPipelineInfoLog(const Context *context, const GLsizei *length, const GLchar *infoLog) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGetProgramPipelineInfoLogBase(context, entryPoint, pipelinePacked, bufSize, length, infoLog); } @@ -2083,12 +1963,6 @@ bool ValidateGetProgramPipelineiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateGetProgramPipelineivBase(context, entryPoint, pipelinePacked, pname, params); } @@ -2096,12 +1970,6 @@ bool ValidateIsProgramPipeline(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateIsProgramPipelineBase(context, entryPoint, pipelinePacked); } @@ -2111,12 +1979,6 @@ bool ValidateProgramUniform1f(const Context *context, UniformLocation locationPacked, GLfloat v0) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform1fBase(context, entryPoint, programPacked, locationPacked, v0); } @@ -2127,12 +1989,6 @@ bool ValidateProgramUniform1fv(const Context *context, GLsizei count, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform1fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2143,12 +1999,6 @@ bool ValidateProgramUniform1i(const Context *context, UniformLocation locationPacked, GLint v0) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform1iBase(context, entryPoint, programPacked, locationPacked, v0); } @@ -2159,12 +2009,6 @@ bool ValidateProgramUniform1iv(const Context *context, GLsizei count, const GLint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform1ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2175,12 +2019,6 @@ bool ValidateProgramUniform1ui(const Context *context, UniformLocation locationPacked, GLuint v0) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform1uiBase(context, entryPoint, programPacked, locationPacked, v0); } @@ -2191,12 +2029,6 @@ bool ValidateProgramUniform1uiv(const Context *context, GLsizei count, const GLuint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform1uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2208,12 +2040,6 @@ bool ValidateProgramUniform2f(const Context *context, GLfloat v0, GLfloat v1) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform2fBase(context, entryPoint, programPacked, locationPacked, v0, v1); } @@ -2224,12 +2050,6 @@ bool ValidateProgramUniform2fv(const Context *context, GLsizei count, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform2fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2241,12 +2061,6 @@ bool ValidateProgramUniform2i(const Context *context, GLint v0, GLint v1) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform2iBase(context, entryPoint, programPacked, locationPacked, v0, v1); } @@ -2257,12 +2071,6 @@ bool ValidateProgramUniform2iv(const Context *context, GLsizei count, const GLint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform2ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2274,12 +2082,6 @@ bool ValidateProgramUniform2ui(const Context *context, GLuint v0, GLuint v1) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform2uiBase(context, entryPoint, programPacked, locationPacked, v0, v1); } @@ -2291,12 +2093,6 @@ bool ValidateProgramUniform2uiv(const Context *context, GLsizei count, const GLuint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform2uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2309,12 +2105,6 @@ bool ValidateProgramUniform3f(const Context *context, GLfloat v1, GLfloat v2) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform3fBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2); } @@ -2326,12 +2116,6 @@ bool ValidateProgramUniform3fv(const Context *context, GLsizei count, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform3fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2344,12 +2128,6 @@ bool ValidateProgramUniform3i(const Context *context, GLint v1, GLint v2) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform3iBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2); } @@ -2361,12 +2139,6 @@ bool ValidateProgramUniform3iv(const Context *context, GLsizei count, const GLint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform3ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2379,12 +2151,6 @@ bool ValidateProgramUniform3ui(const Context *context, GLuint v1, GLuint v2) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform3uiBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2); } @@ -2396,12 +2162,6 @@ bool ValidateProgramUniform3uiv(const Context *context, GLsizei count, const GLuint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform3uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2415,12 +2175,6 @@ bool ValidateProgramUniform4f(const Context *context, GLfloat v2, GLfloat v3) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform4fBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2, v3); } @@ -2432,12 +2186,6 @@ bool ValidateProgramUniform4fv(const Context *context, GLsizei count, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform4fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2451,12 +2199,6 @@ bool ValidateProgramUniform4i(const Context *context, GLint v2, GLint v3) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform4iBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2, v3); } @@ -2468,12 +2210,6 @@ bool ValidateProgramUniform4iv(const Context *context, GLsizei count, const GLint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform4ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2487,12 +2223,6 @@ bool ValidateProgramUniform4ui(const Context *context, GLuint v2, GLuint v3) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform4uiBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2, v3); } @@ -2504,12 +2234,6 @@ bool ValidateProgramUniform4uiv(const Context *context, GLsizei count, const GLuint *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniform4uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -2522,12 +2246,6 @@ bool ValidateProgramUniformMatrix2fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix2fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2540,12 +2258,6 @@ bool ValidateProgramUniformMatrix2x3fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix2x3fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2558,12 +2270,6 @@ bool ValidateProgramUniformMatrix2x4fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix2x4fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2576,12 +2282,6 @@ bool ValidateProgramUniformMatrix3fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix3fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2594,12 +2294,6 @@ bool ValidateProgramUniformMatrix3x2fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix3x2fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2612,12 +2306,6 @@ bool ValidateProgramUniformMatrix3x4fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix3x4fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2630,12 +2318,6 @@ bool ValidateProgramUniformMatrix4fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix4fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2648,12 +2330,6 @@ bool ValidateProgramUniformMatrix4x2fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix4x2fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2666,12 +2342,6 @@ bool ValidateProgramUniformMatrix4x3fv(const Context *context, GLboolean transpose, const GLfloat *value) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateProgramUniformMatrix4x3fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -2682,12 +2352,6 @@ bool ValidateUseProgramStages(const Context *context, GLbitfield stages, ShaderProgramID programPacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateUseProgramStagesBase(context, entryPoint, pipelinePacked, stages, programPacked); } @@ -2695,12 +2359,6 @@ bool ValidateValidateProgramPipeline(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateValidateProgramPipelineBase(context, entryPoint, pipelinePacked); } @@ -2708,12 +2366,6 @@ bool ValidateMemoryBarrier(const Context *context, angle::EntryPoint entryPoint, GLbitfield barriers) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - if (barriers == GL_ALL_BARRIER_BITS) { return true; @@ -2744,12 +2396,6 @@ bool ValidateMemoryBarrierByRegion(const Context *context, angle::EntryPoint entryPoint, GLbitfield barriers) { - if (context->getClientVersion() < ES_3_1) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); - return false; - } - if (barriers == GL_ALL_BARRIER_BITS) { return true; @@ -2774,12 +2420,6 @@ bool ValidateSampleMaski(const PrivateState &state, GLuint maskNumber, GLbitfield mask) { - if (state.getClientVersion() < ES_3_1) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required); - return false; - } - return ValidateSampleMaskiBase(state, errors, entryPoint, maskNumber, mask); } @@ -2788,12 +2428,6 @@ bool ValidateMinSampleShadingOES(const PrivateState &state, angle::EntryPoint entryPoint, GLfloat value) { - if (!state.getExtensions().sampleShadingOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -2852,12 +2486,6 @@ bool ValidateFramebufferTextureEXT(const Context *context, TextureID texture, GLint level) { - if (!context->getExtensions().geometryShaderEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGeometryShaderExtensionNotEnabled); - return false; - } - return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture, level); } @@ -2869,12 +2497,6 @@ bool ValidateFramebufferTextureOES(const Context *context, TextureID texture, GLint level) { - if (!context->getExtensions().geometryShaderOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGeometryShaderExtensionNotEnabled); - return false; - } - return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture, level); } @@ -2891,12 +2513,6 @@ bool ValidateTexStorageMem3DMultisampleEXT(const Context *context, MemoryObjectID memory, GLuint64 offset) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -2907,11 +2523,6 @@ bool ValidateGetProgramResourceLocationIndexEXT(const Context *context, GLenum programInterface, const char *name) { - if (!context->getExtensions().blendFuncExtendedEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } if (context->getClientVersion() < ES_3_1) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES31Required); @@ -2922,16 +2533,20 @@ bool ValidateGetProgramResourceLocationIndexEXT(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProgramInterfaceMustBeProgramOutput); return false; } + Program *programObject = GetValidProgram(context, entryPoint, program); - if (!programObject) + if (programObject == nullptr) { + // Error already generated. return false; } + if (!programObject->isLinked()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked); return false; } + return true; } @@ -2942,12 +2557,6 @@ bool ValidateTexBufferOES(const Context *context, GLenum internalformat, BufferID bufferPacked) { - if (!context->getExtensions().textureBufferOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable); - return false; - } - return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked); } @@ -2959,12 +2568,6 @@ bool ValidateTexBufferRangeOES(const Context *context, GLintptr offset, GLsizeiptr size) { - if (!context->getExtensions().textureBufferOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable); - return false; - } - return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, bufferPacked, offset, size); } @@ -2976,12 +2579,6 @@ bool ValidateTexBufferEXT(const Context *context, GLenum internalformat, BufferID bufferPacked) { - if (!context->getExtensions().textureBufferEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable); - return false; - } - return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked); } @@ -2993,12 +2590,6 @@ bool ValidateTexBufferRangeEXT(const Context *context, GLintptr offset, GLsizeiptr size) { - if (!context->getExtensions().textureBufferEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable); - return false; - } - return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, bufferPacked, offset, size); } diff --git a/src/libANGLE/validationES31.h b/src/libANGLE/validationES31.h index e92c40a49f7..02c8d1bc09e 100644 --- a/src/libANGLE/validationES31.h +++ b/src/libANGLE/validationES31.h @@ -15,6 +15,8 @@ namespace gl { +void RecordVersionErrorES31(const Context *context, angle::EntryPoint entryPoint); + bool ValidateTexBufferBase(const Context *context, angle::EntryPoint entryPoint, TextureType target, @@ -54,7 +56,7 @@ bool ValidateCreateShaderProgramvBase(const Context *context, angle::EntryPoint entryPoint, ShaderType typePacked, GLsizei count, - const GLchar **strings); + const GLchar *const *strings); bool ValidateDeleteProgramPipelinesBase(const Context *context, angle::EntryPoint entryPoint, GLsizei n, @@ -77,11 +79,6 @@ bool ValidateGetProgramPipelineivBase(const Context *context, bool ValidateIsProgramPipelineBase(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked); -bool ValidateProgramParameteriBase(const Context *context, - angle::EntryPoint entryPoint, - ShaderProgramID programPacked, - GLenum pname, - GLint value); bool ValidateProgramUniform1fBase(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID programPacked, diff --git a/src/libANGLE/validationES31_autogen.h b/src/libANGLE/validationES31_autogen.h index 34daa4ab953..cdb288d355f 100644 --- a/src/libANGLE/validationES31_autogen.h +++ b/src/libANGLE/validationES31_autogen.h @@ -18,6 +18,7 @@ namespace gl { class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; bool ValidateActiveShaderProgram(const Context *context, @@ -392,24 +393,30 @@ bool ValidateUseProgramStages(const Context *context, bool ValidateValidateProgramPipeline(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked); -bool ValidateVertexAttribBinding(const Context *context, +bool ValidateVertexAttribBinding(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint attribindex, GLuint bindingindex); -bool ValidateVertexAttribFormat(const Context *context, +bool ValidateVertexAttribFormat(const PrivateState &state, + const PrivateStateCache &privateStateCache, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint attribindex, GLint size, VertexAttribType typePacked, GLboolean normalized, GLuint relativeoffset); -bool ValidateVertexAttribIFormat(const Context *context, +bool ValidateVertexAttribIFormat(const PrivateState &state, + const PrivateStateCache &privateStateCache, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint attribindex, GLint size, VertexAttribType typePacked, GLuint relativeoffset); -bool ValidateVertexBindingDivisor(const Context *context, +bool ValidateVertexBindingDivisor(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint bindingindex, GLuint divisor); diff --git a/src/libANGLE/validationES32.cpp b/src/libANGLE/validationES32.cpp index e882e8eb92e..ee3ae6660a6 100644 --- a/src/libANGLE/validationES32.cpp +++ b/src/libANGLE/validationES32.cpp @@ -27,6 +27,16 @@ namespace gl { using namespace err; +void RecordVersionErrorES1Or32(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES10or32); +} + +void RecordVersionErrorES32(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES32); +} + namespace { // ANGLE_shader_pixel_local_storage: INVALID_OPERATION is generated by Enablei*(), Disablei*() if @@ -47,12 +57,6 @@ static bool IsIndexedCapBannedWithActivePLS(GLenum cap) bool ValidateBlendBarrier(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return true; } @@ -181,12 +185,6 @@ bool ValidateCopyImageSubData(const Context *context, GLsizei srcHeight, GLsizei srcDepth) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateCopyImageSubDataBase(context, entryPoint, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); @@ -209,7 +207,7 @@ bool ValidateDebugMessageControl(const Context *context, const GLuint *ids, GLboolean enabled) { - return true; + return ValidateDebugMessageControlBase(context, entryPoint, source, type, severity, count, ids); } bool ValidateDebugMessageInsert(const Context *context, @@ -221,7 +219,8 @@ bool ValidateDebugMessageInsert(const Context *context, GLsizei length, const GLchar *buf) { - return true; + return ValidateDebugMessageInsertBase(context, entryPoint, source, type, id, severity, length, + buf); } bool ValidateDisablei(const PrivateState &state, @@ -235,7 +234,8 @@ bool ValidateDisablei(const PrivateState &state, { if (IsIndexedCapBannedWithActivePLS(target)) { - errors->validationErrorF(entryPoint, GL_INVALID_OPERATION, kPLSCapNotAllowed, target); + ANGLE_UNSAFE_TODO(errors->validationErrorF(entryPoint, GL_INVALID_OPERATION, + kPLSCapNotAllowed, target)); return false; } } @@ -250,7 +250,8 @@ bool ValidateDisablei(const PrivateState &state, } break; default: - errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); + ANGLE_UNSAFE_TODO( + errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target)); return false; } return true; @@ -321,7 +322,8 @@ bool ValidateEnablei(const PrivateState &state, { if (IsIndexedCapBannedWithActivePLS(target)) { - errors->validationErrorF(entryPoint, GL_INVALID_OPERATION, kPLSCapNotAllowed, target); + ANGLE_UNSAFE_TODO(errors->validationErrorF(entryPoint, GL_INVALID_OPERATION, + kPLSCapNotAllowed, target)); return false; } } @@ -336,7 +338,8 @@ bool ValidateEnablei(const PrivateState &state, } break; default: - errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); + ANGLE_UNSAFE_TODO( + errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target)); return false; } return true; @@ -349,12 +352,6 @@ bool ValidateFramebufferTexture(const Context *context, TextureID texture, GLint level) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture, level); } @@ -370,17 +367,12 @@ bool ValidateGetDebugMessageLog(const Context *context, const GLsizei *lengths, const GLchar *messageLog) { - return true; + return ValidateGetDebugMessageLogBase(context, entryPoint, count, bufSize, sources, types, ids, + severities, lengths, messageLog); } bool ValidateGetGraphicsResetStatus(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return true; } @@ -392,18 +384,8 @@ bool ValidateGetObjectLabel(const Context *context, const GLsizei *length, const GLchar *label) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - - if (!ValidateGetObjectLabelBase(context, entryPoint, identifier, name, bufSize, length, label)) - { - return false; - } - - return true; + return ValidateGetObjectLabelBase(context, entryPoint, identifier, name, bufSize, length, + label); } bool ValidateGetObjectPtrLabel(const Context *context, @@ -413,18 +395,7 @@ bool ValidateGetObjectPtrLabel(const Context *context, const GLsizei *length, const GLchar *label) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - - if (!ValidateGetObjectPtrLabelBase(context, entryPoint, ptr, bufSize, length, label)) - { - return false; - } - - return true; + return ValidateGetObjectPtrLabelBase(context, entryPoint, ptr, bufSize, length, label); } bool ValidateGetPointerv(const Context *context, @@ -439,7 +410,7 @@ bool ValidateGetPointerv(const Context *context, case GL_COLOR_ARRAY_POINTER: case GL_TEXTURE_COORD_ARRAY_POINTER: case GL_POINT_SIZE_ARRAY_POINTER_OES: - if (context->getClientMajorVersion() != 1) + if (context->getClientVersion() >= ES_2_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPointerQuery); return false; @@ -479,12 +450,7 @@ bool ValidateGetSamplerParameterIiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr); + return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr, params); } bool ValidateGetSamplerParameterIuiv(const Context *context, @@ -493,12 +459,7 @@ bool ValidateGetSamplerParameterIuiv(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr); + return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr, params); } bool ValidateGetTexParameterIiv(const Context *context, @@ -507,11 +468,6 @@ bool ValidateGetTexParameterIiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateGetTexParameterBase(context, entryPoint, targetPacked, pname, nullptr); } @@ -521,11 +477,6 @@ bool ValidateGetTexParameterIuiv(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateGetTexParameterBase(context, entryPoint, targetPacked, pname, nullptr); } @@ -536,12 +487,6 @@ bool ValidateGetnUniformfv(const Context *context, GLsizei bufSize, const GLfloat *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr); } @@ -552,12 +497,6 @@ bool ValidateGetnUniformiv(const Context *context, GLsizei bufSize, const GLint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr); } @@ -568,12 +507,6 @@ bool ValidateGetnUniformuiv(const Context *context, GLsizei bufSize, const GLuint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr); } @@ -593,7 +526,8 @@ bool ValidateIsEnabledi(const PrivateState &state, } break; default: - errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); + ANGLE_UNSAFE_TODO( + errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target)); return false; } return true; @@ -614,18 +548,7 @@ bool ValidateObjectLabel(const Context *context, GLsizei length, const GLchar *label) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - - if (!ValidateObjectLabelBase(context, entryPoint, identifier, name, length, label)) - { - return false; - } - - return true; + return ValidateObjectLabelBase(context, entryPoint, identifier, name, length, label); } bool ValidateObjectPtrLabel(const Context *context, @@ -634,18 +557,7 @@ bool ValidateObjectPtrLabel(const Context *context, GLsizei length, const GLchar *label) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - - if (!ValidateObjectPtrLabelBase(context, entryPoint, ptr, length, label)) - { - return false; - } - - return true; + return ValidateObjectPtrLabelBase(context, entryPoint, ptr, length, label); } bool ValidatePatchParameteri(const PrivateState &state, @@ -654,12 +566,6 @@ bool ValidatePatchParameteri(const PrivateState &state, GLenum pname, GLint value) { - if (state.getClientVersion() < ES_3_2) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidatePatchParameteriBase(state, errors, entryPoint, pname, value); } @@ -704,12 +610,6 @@ bool ValidateReadnPixels(const Context *context, GLsizei bufSize, const void *data) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - if (bufSize < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); @@ -726,11 +626,6 @@ bool ValidateSamplerParameterIiv(const Context *context, GLenum pname, const GLint *param) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, param); } @@ -740,11 +635,6 @@ bool ValidateSamplerParameterIuiv(const Context *context, GLenum pname, const GLuint *param) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, param); } @@ -754,12 +644,6 @@ bool ValidateTexBuffer(const Context *context, GLenum internalformat, BufferID buffer) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateTexBufferBase(context, entryPoint, target, internalformat, buffer); } @@ -771,12 +655,6 @@ bool ValidateTexBufferRange(const Context *context, GLintptr offset, GLsizeiptr size) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } - return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, buffer, offset, size); } @@ -787,11 +665,6 @@ bool ValidateTexParameterIiv(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateTexParameterBase(context, entryPoint, targetPacked, pname, -1, true, params); } @@ -801,11 +674,6 @@ bool ValidateTexParameterIuiv(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateTexParameterBase(context, entryPoint, targetPacked, pname, -1, true, params); } @@ -819,11 +687,6 @@ bool ValidateTexStorage3DMultisample(const Context *context, GLsizei depth, GLboolean fixedsamplelocations) { - if (context->getClientVersion() < ES_3_2) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES32Required); - return false; - } return ValidateTexStorage3DMultisampleBase(context, entryPoint, targetPacked, samples, internalformat, width, height, depth); } diff --git a/src/libANGLE/validationES32.h b/src/libANGLE/validationES32.h index 674bc81d060..2e9784a74d5 100644 --- a/src/libANGLE/validationES32.h +++ b/src/libANGLE/validationES32.h @@ -14,7 +14,10 @@ namespace gl { -// Nothing here yet. + +void RecordVersionErrorES1Or32(const Context *context, angle::EntryPoint entryPoint); +void RecordVersionErrorES32(const Context *context, angle::EntryPoint entryPoint); + } // namespace gl #endif // LIBANGLE_VALIDATION_ES32_H_ diff --git a/src/libANGLE/validationES32_autogen.h b/src/libANGLE/validationES32_autogen.h index a3a7c5480a6..bf9e40a85f7 100644 --- a/src/libANGLE/validationES32_autogen.h +++ b/src/libANGLE/validationES32_autogen.h @@ -18,6 +18,7 @@ namespace gl { class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; bool ValidateBlendBarrier(const Context *context, angle::EntryPoint entryPoint); diff --git a/src/libANGLE/validationES3_autogen.h b/src/libANGLE/validationES3_autogen.h index 714797204de..d3958df693b 100644 --- a/src/libANGLE/validationES3_autogen.h +++ b/src/libANGLE/validationES3_autogen.h @@ -18,6 +18,7 @@ namespace gl { class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; bool ValidateBeginQuery(const Context *context, @@ -355,7 +356,8 @@ bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, SyncID bool ValidateIsTransformFeedback(const Context *context, angle::EntryPoint entryPoint, TransformFeedbackID idPacked); -bool ValidateIsVertexArray(const Context *context, +bool ValidateIsVertexArray(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, VertexArrayID arrayPacked); bool ValidateMapBufferRange(const Context *context, @@ -537,7 +539,8 @@ bool ValidateUniformMatrix4x3fv(const Context *context, bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding targetPacked); -bool ValidateVertexAttribDivisor(const Context *context, +bool ValidateVertexAttribDivisor(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLuint divisor); diff --git a/src/libANGLE/validationESEXT.cpp b/src/libANGLE/validationESEXT.cpp index 31df3f190cf..1771d118684 100644 --- a/src/libANGLE/validationESEXT.cpp +++ b/src/libANGLE/validationESEXT.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // validationESEXT.cpp: Validation functions for OpenGL ES extension entry points. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/validationESEXT_autogen.h" @@ -24,6 +29,11 @@ namespace gl { using namespace err; +void RecordVersionErrorESEXT(const Context *context, angle::EntryPoint entryPoint) +{ + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresESEXT); +} + namespace { template @@ -73,7 +83,7 @@ bool IsValidImageLayout(ImageLayout layout) } } -bool IsValidMemoryObjectParamater(const Context *context, +bool IsValidMemoryObjectParameter(const Context *context, angle::EntryPoint entryPoint, GLenum pname) { @@ -100,9 +110,9 @@ bool ValidateObjectIdentifierAndName(const Context *context, GLenum identifier, GLuint name) { - bool isGLES11 = context->getClientVersion() == Version(1, 1); - bool isGLES3 = context->getClientMajorVersion() >= 3; - bool isGLES31 = context->getClientVersion() >= Version(3, 1); + const bool isGLES11 = context->getClientVersion() == ES_1_1; + const bool isGLES3 = context->getClientVersion() >= ES_3_0; + const bool isGLES31 = context->getClientVersion() >= ES_3_1; switch (identifier) { case GL_BUFFER_OBJECT_EXT: @@ -145,7 +155,7 @@ bool ValidateObjectIdentifierAndName(const Context *context, ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType); return false; } - if (context->getVertexArray({name}) == nullptr) + if (context->getPrivateState().getVertexArray({name}) == nullptr) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidVertexArrayName); return false; @@ -153,7 +163,8 @@ bool ValidateObjectIdentifierAndName(const Context *context, return true; case GL_QUERY_OBJECT_EXT: - if (!isGLES3 && !context->getExtensions().occlusionQueryBooleanEXT) + if (!isGLES3 && !(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType); return false; @@ -265,12 +276,6 @@ bool ValidateClearTexImageCommon(const Context *context, GLenum type, const void *data) { - if (!context->getExtensions().clearTextureEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (texturePacked.value == 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTextureName); @@ -376,12 +381,6 @@ bool ValidateGetTexImage(const Context *context, TextureTarget target, GLint level) { - if (!context->getExtensions().getImageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGetImageExtensionNotEnabled); - return false; - } - if (!ValidTexture2DDestinationTarget(context, target) && !ValidTexture3DDestinationTarget(context, target)) { @@ -470,12 +469,6 @@ bool ValidateGetRenderbufferImageANGLE(const Context *context, GLenum type, const void *pixels) { - if (!context->getExtensions().getImageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGetImageExtensionNotEnabled); - return false; - } - if (target != GL_RENDERBUFFER) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget); @@ -508,12 +501,6 @@ bool ValidateDrawElementsBaseVertexEXT(const Context *context, const void *indices, GLint basevertex) { - if (!context->getExtensions().drawElementsBaseVertexAny()) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1); } @@ -526,7 +513,9 @@ bool ValidateDrawElementsInstancedBaseVertexEXT(const Context *context, GLsizei instancecount, GLint basevertex) { - if (!context->getExtensions().drawElementsBaseVertexAny()) + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().drawInstancedEXT && + !context->getExtensions().instancedArraysANGLE && + !context->getExtensions().instancedArraysEXT) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; @@ -546,9 +535,9 @@ bool ValidateDrawRangeElementsBaseVertexEXT(const Context *context, const void *indices, GLint basevertex) { - if (!context->getExtensions().drawElementsBaseVertexAny()) + if (context->getClientVersion() < ES_3_0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); return false; } @@ -570,11 +559,11 @@ bool ValidateDrawRangeElementsBaseVertexEXT(const Context *context, } // Note that resolving the index range is a bit slow. We should probably optimize this. - IndexRange indexRange; - ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, - indices, &indexRange)); - - if (indexRange.end > end || indexRange.start < start) + IndexRange indexRange{IndexRange::Undefined()}; + ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange( + context, type, count, indices, context->getState().isPrimitiveRestartEnabled(), + &indexRange)); + if (!indexRange.isEmpty() && (indexRange.end() > end || indexRange.start() < start)) { // GL spec says that behavior in this case is undefined - generating an error is fine. ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsElementRange); @@ -592,9 +581,39 @@ bool ValidateMultiDrawElementsBaseVertexEXT(const Context *context, GLsizei drawcount, const GLint *basevertex) { + if (!context->getExtensions().multiDrawArraysEXT) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + return false; + } + + UNIMPLEMENTED(); return true; } +bool ValidateMultiDrawArraysEXT(const Context *context, + angle::EntryPoint entryPoint, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount) +{ + UNIMPLEMENTED(); + return false; +} + +bool ValidateMultiDrawElementsEXT(const Context *context, + angle::EntryPoint entryPoint, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount) +{ + UNIMPLEMENTED(); + return false; +} + bool ValidateMultiDrawArraysIndirectEXT(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode modePacked, @@ -640,16 +659,7 @@ bool ValidateMultiDrawElementsIndirectEXT(const Context *context, { // EXT_geometry_shader allows transform feedback to work with all draw commands. // [EXT_geometry_shader] Section 12.1, "Transform Feedback" - if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2) - { - if (!ValidateTransformFeedbackPrimitiveMode( - context, entryPoint, curTransformFeedback->getPrimitiveMode(), modePacked)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback); - return false; - } - } - else + if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2) { // An INVALID_OPERATION error is generated if transform feedback is active and not // paused. @@ -669,12 +679,6 @@ bool ValidateDrawArraysInstancedBaseInstanceEXT(const Context *context, GLsizei instanceCount, GLuint baseInstance) { - if (!context->getExtensions().baseInstanceEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount, baseInstance); } @@ -688,12 +692,6 @@ bool ValidateDrawElementsInstancedBaseInstanceEXT(const Context *context, GLsizei instancecount, GLuint baseinstance) { - if (!context->getExtensions().baseInstanceEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, instancecount, baseinstance); } @@ -708,12 +706,6 @@ bool ValidateDrawElementsInstancedBaseVertexBaseInstanceEXT(const Context *conte GLint basevertex, GLuint baseinstance) { - if (!context->getExtensions().baseInstanceEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, typePacked, indices, instancecount, baseinstance); } @@ -726,12 +718,6 @@ bool ValidateDrawElementsBaseVertexOES(const Context *context, const void *indices, GLint basevertex) { - if (!context->getExtensions().drawElementsBaseVertexAny()) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1); } @@ -744,7 +730,9 @@ bool ValidateDrawElementsInstancedBaseVertexOES(const Context *context, GLsizei instancecount, GLint basevertex) { - if (!context->getExtensions().drawElementsBaseVertexAny()) + if (context->getClientVersion() < ES_3_0 && !context->getExtensions().drawInstancedEXT && + !context->getExtensions().instancedArraysANGLE && + !context->getExtensions().instancedArraysEXT) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; @@ -764,9 +752,9 @@ bool ValidateDrawRangeElementsBaseVertexOES(const Context *context, const void *indices, GLint basevertex) { - if (!context->getExtensions().drawElementsBaseVertexAny()) + if (context->getClientVersion() < ES_3_0) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); return false; } @@ -788,11 +776,11 @@ bool ValidateDrawRangeElementsBaseVertexOES(const Context *context, } // Note that resolving the index range is a bit slow. We should probably optimize this. - IndexRange indexRange; - ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, - indices, &indexRange)); - - if (indexRange.end > end || indexRange.start < start) + IndexRange indexRange{IndexRange::Undefined()}; + ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange( + context, type, count, indices, context->getState().isPrimitiveRestartEnabled(), + &indexRange)); + if (!indexRange.isEmpty() && (indexRange.end() > end || indexRange.start() < start)) { // GL spec says that behavior in this case is undefined - generating an error is fine. ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsElementRange); @@ -804,17 +792,6 @@ bool ValidateDrawRangeElementsBaseVertexOES(const Context *context, // GL_KHR_blend_equation_advanced bool ValidateBlendBarrierKHR(const Context *context, angle::EntryPoint entryPoint) { - if (context->getClientVersion() < ES_2_0) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES2Required); - return false; - } - - if (!context->getExtensions().blendEquationAdvancedKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kAdvancedBlendExtensionNotEnabled); - } - return true; } @@ -826,12 +803,6 @@ bool ValidateGetGraphicsResetStatusKHR(const Context *context, angle::EntryPoint return false; } - if (!context->getExtensions().robustnessKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -848,12 +819,6 @@ bool ValidateGetnUniformfvKHR(const Context *context, return false; } - if (!context->getExtensions().robustnessKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateSizedGetUniform(context, entryPoint, programPacked, locationPacked, bufSize, nullptr); } @@ -871,12 +836,6 @@ bool ValidateGetnUniformivKHR(const Context *context, return false; } - if (!context->getExtensions().robustnessKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateSizedGetUniform(context, entryPoint, programPacked, locationPacked, bufSize, nullptr); } @@ -896,12 +855,6 @@ bool ValidateGetnUniformuivKHR(const Context *context, return false; } - if (!context->getExtensions().robustnessKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateSizedGetUniform(context, entryPoint, programPacked, locationPacked, bufSize, nullptr); } @@ -923,12 +876,6 @@ bool ValidateReadnPixelsKHR(const Context *context, return false; } - if (!context->getExtensions().robustnessKHR) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (bufSize < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); @@ -944,12 +891,6 @@ bool ValidateBlendEquationOES(const PrivateState &state, angle::EntryPoint entryPoint, GLenum mode) { - if (!state.getExtensions().blendSubtractOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (mode) { case GL_FUNC_ADD_OES: @@ -969,12 +910,6 @@ bool ValidateBlendEquationSeparateiEXT(const PrivateState &state, GLenum modeRGB, GLenum modeAlpha) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendEquationSeparatei(state, errors, entryPoint, buf, modeRGB, modeAlpha); } @@ -984,12 +919,6 @@ bool ValidateBlendEquationiEXT(const PrivateState &state, GLuint buf, GLenum mode) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendEquationi(state, errors, entryPoint, buf, mode); } @@ -1002,12 +931,6 @@ bool ValidateBlendFuncSeparateiEXT(const PrivateState &state, GLenum srcAlpha, GLenum dstAlpha) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendFuncSeparatei(state, errors, entryPoint, buf, srcRGB, dstRGB, srcAlpha, dstAlpha); } @@ -1019,12 +942,6 @@ bool ValidateBlendFunciEXT(const PrivateState &state, GLenum src, GLenum dst) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendFunci(state, errors, entryPoint, buf, src, dst); } @@ -1037,12 +954,6 @@ bool ValidateColorMaskiEXT(const PrivateState &state, GLboolean b, GLboolean a) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateColorMaski(state, errors, entryPoint, index, r, g, b, a); } @@ -1052,12 +963,6 @@ bool ValidateDisableiEXT(const PrivateState &state, GLenum target, GLuint index) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDisablei(state, errors, entryPoint, target, index); } @@ -1067,12 +972,6 @@ bool ValidateEnableiEXT(const PrivateState &state, GLenum target, GLuint index) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateEnablei(state, errors, entryPoint, target, index); } @@ -1082,12 +981,6 @@ bool ValidateIsEnablediEXT(const PrivateState &state, GLenum target, GLuint index) { - if (!state.getExtensions().drawBuffersIndexedEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateIsEnabledi(state, errors, entryPoint, target, index); } @@ -1098,12 +991,6 @@ bool ValidateBlendEquationSeparateiOES(const PrivateState &state, GLenum modeRGB, GLenum modeAlpha) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendEquationSeparatei(state, errors, entryPoint, buf, modeRGB, modeAlpha); } @@ -1113,12 +1000,6 @@ bool ValidateBlendEquationiOES(const PrivateState &state, GLuint buf, GLenum mode) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendEquationi(state, errors, entryPoint, buf, mode); } @@ -1131,12 +1012,6 @@ bool ValidateBlendFuncSeparateiOES(const PrivateState &state, GLenum srcAlpha, GLenum dstAlpha) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendFuncSeparatei(state, errors, entryPoint, buf, srcRGB, dstRGB, srcAlpha, dstAlpha); } @@ -1148,12 +1023,6 @@ bool ValidateBlendFunciOES(const PrivateState &state, GLenum src, GLenum dst) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBlendFunci(state, errors, entryPoint, buf, src, dst); } @@ -1166,12 +1035,6 @@ bool ValidateColorMaskiOES(const PrivateState &state, GLboolean b, GLboolean a) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateColorMaski(state, errors, entryPoint, index, r, g, b, a); } @@ -1181,12 +1044,6 @@ bool ValidateDisableiOES(const PrivateState &state, GLenum target, GLuint index) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDisablei(state, errors, entryPoint, target, index); } @@ -1196,12 +1053,6 @@ bool ValidateEnableiOES(const PrivateState &state, GLenum target, GLuint index) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateEnablei(state, errors, entryPoint, target, index); } @@ -1211,12 +1062,6 @@ bool ValidateIsEnablediOES(const PrivateState &state, GLenum target, GLuint index) { - if (!state.getExtensions().drawBuffersIndexedOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateIsEnabledi(state, errors, entryPoint, target, index); } @@ -1225,12 +1070,6 @@ bool ValidateProvokingVertexANGLE(const PrivateState &state, angle::EntryPoint entryPoint, ProvokingVertexConvention provokeModePacked) { - if (!state.getExtensions().provokingVertexANGLE) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (provokeModePacked) { case ProvokingVertexConvention::FirstVertexConvention: @@ -1249,12 +1088,6 @@ bool ValidateGetInteger64vEXT(const Context *context, GLenum pname, const GLint64 *data) { - if (!context->getExtensions().disjointTimerQueryEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - GLenum nativeType = GL_NONE; unsigned int numParams = 0; if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams)) @@ -1283,12 +1116,6 @@ bool ValidateCopyImageSubDataEXT(const Context *context, GLsizei srcHeight, GLsizei srcDepth) { - if (!context->getExtensions().copyImageEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateCopyImageSubDataBase(context, entryPoint, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); @@ -1312,12 +1139,6 @@ bool ValidateCopyImageSubDataOES(const Context *context, GLsizei srcHeight, GLsizei srcDepth) { - if (!context->getExtensions().copyImageOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateCopyImageSubDataBase(context, entryPoint, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); @@ -1330,12 +1151,6 @@ bool ValidateBufferStorageMemEXT(const Context *context, MemoryObjectID memory, GLuint64 offset) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1345,13 +1160,8 @@ bool ValidateCreateMemoryObjectsEXT(const Context *context, GLsizei n, const MemoryObjectID *memoryObjects) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + memoryObjects); } bool ValidateDeleteMemoryObjectsEXT(const Context *context, @@ -1359,13 +1169,8 @@ bool ValidateDeleteMemoryObjectsEXT(const Context *context, GLsizei n, const MemoryObjectID *memoryObjects) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + memoryObjects); } bool ValidateGetMemoryObjectParameterivEXT(const Context *context, @@ -1374,19 +1179,14 @@ bool ValidateGetMemoryObjectParameterivEXT(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const MemoryObject *memory = context->getMemoryObject(memoryObject); if (memory == nullptr) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMemoryObject); + return false; } - if (!IsValidMemoryObjectParamater(context, entryPoint, pname)) + if (!IsValidMemoryObjectParameter(context, entryPoint, pname)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMemoryObjectParameter); return false; @@ -1400,12 +1200,6 @@ bool ValidateGetUnsignedBytevEXT(const Context *context, GLenum pname, const GLubyte *data) { - if (!context->getExtensions().memoryObjectEXT && !context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1416,12 +1210,6 @@ bool ValidateGetUnsignedBytei_vEXT(const Context *context, GLuint index, const GLubyte *data) { - if (!context->getExtensions().memoryObjectEXT && !context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1430,12 +1218,6 @@ bool ValidateIsMemoryObjectEXT(const Context *context, angle::EntryPoint entryPoint, MemoryObjectID memoryObject) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -1445,12 +1227,6 @@ bool ValidateMemoryObjectParameterivEXT(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const MemoryObject *memory = context->getMemoryObject(memoryObject); if (memory == nullptr) { @@ -1464,7 +1240,7 @@ bool ValidateMemoryObjectParameterivEXT(const Context *context, return false; } - if (!IsValidMemoryObjectParamater(context, entryPoint, pname)) + if (!IsValidMemoryObjectParameter(context, entryPoint, pname)) { ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMemoryObjectParameter); return false; @@ -1483,19 +1259,12 @@ bool ValidateTexStorageMem2DEXT(const Context *context, MemoryObjectID memory, GLuint64 offset) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { return ValidateES2TexStorageParametersBase(context, entryPoint, target, levels, internalFormat, width, height); } - ASSERT(context->getClientMajorVersion() >= 3); return ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalFormat, width, height, 1); } @@ -1511,12 +1280,6 @@ bool ValidateTexStorageMem3DEXT(const Context *context, MemoryObjectID memory, GLuint64 offset) { - if (!context->getExtensions().memoryObjectEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1528,12 +1291,6 @@ bool ValidateImportMemoryFdEXT(const Context *context, HandleType handleType, GLint fd) { - if (!context->getExtensions().memoryObjectFdEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (handleType) { case HandleType::OpaqueFd: @@ -1553,13 +1310,7 @@ bool ValidateImportMemoryZirconHandleANGLE(const Context *context, HandleType handleType, GLuint handle) { - if (!context->getExtensions().memoryObjectFuchsiaANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - switch (handleType) + switch (handleType) { case HandleType::ZirconVmo: break; @@ -1576,13 +1327,8 @@ bool ValidateDeleteSemaphoresEXT(const Context *context, GLsizei n, const SemaphoreID *semaphores) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + semaphores); } bool ValidateGenSemaphoresEXT(const Context *context, @@ -1590,13 +1336,8 @@ bool ValidateGenSemaphoresEXT(const Context *context, GLsizei n, const SemaphoreID *semaphores) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - return ValidateGenOrDelete(context, entryPoint, n); + return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, + semaphores); } bool ValidateGetSemaphoreParameterui64vEXT(const Context *context, @@ -1605,12 +1346,6 @@ bool ValidateGetSemaphoreParameterui64vEXT(const Context *context, GLenum pname, const GLuint64 *params) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1619,12 +1354,6 @@ bool ValidateIsSemaphoreEXT(const Context *context, angle::EntryPoint entryPoint, SemaphoreID semaphore) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -1634,12 +1363,6 @@ bool ValidateSemaphoreParameterui64vEXT(const Context *context, GLenum pname, const GLuint64 *params) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -1653,12 +1376,6 @@ bool ValidateSignalSemaphoreEXT(const Context *context, const TextureID *textures, const GLenum *dstLayouts) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - for (GLuint i = 0; i < numBufferBarriers; ++i) { if (!context->getBuffer(buffers[i])) @@ -1694,12 +1411,6 @@ bool ValidateWaitSemaphoreEXT(const Context *context, const TextureID *textures, const GLenum *srcLayouts) { - if (!context->getExtensions().semaphoreEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - for (GLuint i = 0; i < numBufferBarriers; ++i) { if (!context->getBuffer(buffers[i])) @@ -1732,12 +1443,6 @@ bool ValidateImportSemaphoreFdEXT(const Context *context, HandleType handleType, GLint fd) { - if (!context->getExtensions().semaphoreFdEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (handleType) { case HandleType::OpaqueFd: @@ -1756,16 +1461,12 @@ bool ValidateGetTexParameterIivOES(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); } @@ -1775,15 +1476,12 @@ bool ValidateGetTexParameterIuivOES(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); + return false; } - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - } return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); } @@ -1793,16 +1491,12 @@ bool ValidateTexParameterIivOES(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params); } @@ -1812,14 +1506,9 @@ bool ValidateTexParameterIuivOES(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } @@ -1832,17 +1521,13 @@ bool ValidateGetSamplerParameterIivOES(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } - return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr); + + return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr, params); } bool ValidateGetSamplerParameterIuivOES(const Context *context, @@ -1851,17 +1536,13 @@ bool ValidateGetSamplerParameterIuivOES(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } - return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr); + + return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr, params); } bool ValidateSamplerParameterIivOES(const Context *context, @@ -1870,16 +1551,12 @@ bool ValidateSamplerParameterIivOES(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params); } @@ -1889,16 +1566,12 @@ bool ValidateSamplerParameterIuivOES(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params); } @@ -1908,17 +1581,14 @@ bool ValidateGetSamplerParameterIivEXT(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } - return ValidateGetSamplerParameterBase(context, entryPoint, samplerPacked, pname, nullptr); + + return ValidateGetSamplerParameterBase(context, entryPoint, samplerPacked, pname, nullptr, + params); } bool ValidateGetSamplerParameterIuivEXT(const Context *context, @@ -1927,17 +1597,14 @@ bool ValidateGetSamplerParameterIuivEXT(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } - return ValidateGetSamplerParameterBase(context, entryPoint, samplerPacked, pname, nullptr); + + return ValidateGetSamplerParameterBase(context, entryPoint, samplerPacked, pname, nullptr, + params); } bool ValidateGetTexParameterIivEXT(const Context *context, @@ -1946,16 +1613,12 @@ bool ValidateGetTexParameterIivEXT(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateGetTexParameterBase(context, entryPoint, targetPacked, pname, nullptr); } @@ -1965,16 +1628,12 @@ bool ValidateGetTexParameterIuivEXT(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateGetTexParameterBase(context, entryPoint, targetPacked, pname, nullptr); } @@ -1984,16 +1643,12 @@ bool ValidateSamplerParameterIivEXT(const Context *context, GLenum pname, const GLint *param) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateSamplerParameterBase(context, entryPoint, samplerPacked, pname, -1, true, param); } @@ -2003,16 +1658,12 @@ bool ValidateSamplerParameterIuivEXT(const Context *context, GLenum pname, const GLuint *param) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateSamplerParameterBase(context, entryPoint, samplerPacked, pname, -1, true, param); } @@ -2022,16 +1673,12 @@ bool ValidateTexParameterIivEXT(const Context *context, GLenum pname, const GLint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateTexParameterBase(context, entryPoint, targetPacked, pname, -1, true, params); } @@ -2041,16 +1688,12 @@ bool ValidateTexParameterIuivEXT(const Context *context, GLenum pname, const GLuint *params) { - if (context->getClientMajorVersion() < 3) + if (context->getClientVersion() < ES_3_0) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required); - } - - if (!context->getExtensions().textureBorderClampEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } + return ValidateTexParameterBase(context, entryPoint, targetPacked, pname, -1, true, params); } @@ -2060,12 +1703,6 @@ bool ValidateImportSemaphoreZirconHandleANGLE(const Context *context, HandleType handleType, GLuint handle) { - if (!context->getExtensions().semaphoreFuchsiaANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - switch (handleType) { case HandleType::ZirconEvent: @@ -2091,13 +1728,6 @@ bool ValidatePLSCommon(const Context *context, angle::EntryPoint entryPoint, PLSExpectedStatus expectedStatus) { - // Check that the pixel local storage extension is enabled at all. - if (!context->getExtensions().shaderPixelLocalStorageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSExtensionNotEnabled); - return false; - } - Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); if (expectedStatus != PLSExpectedStatus::Active) { @@ -2128,11 +1758,14 @@ bool ValidatePLSCommon(const Context *context, return false; } } - else + else if (expectedStatus == PLSExpectedStatus::Inactive) { - // PLSExpectedStatus::Inactive is validated by the allow list. - ASSERT(expectedStatus != PLSExpectedStatus::Inactive || - context->getState().getPixelLocalStorageActivePlanes() == 0); + // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero. + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSActive); + return false; + } } return true; @@ -2163,6 +1796,87 @@ bool ValidatePLSCommon(const Context *context, return true; } +bool ValidateGetFramebufferPixelLocalStorageParameterCommon(const Context *context, + angle::EntryPoint entryPoint, + GLint plane, + GLenum pname, + const void *params) +{ + if (context->getState().getDrawFramebuffer()->id().value == 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kPLSDefaultFramebufferBound); + return false; + } + + if (plane < 0) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSPlaneLessThanZero); + return false; + } + + if (plane >= static_cast(context->getCaps().maxPixelLocalStoragePlanes)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSPlaneOutOfRange); + return false; + } + + switch (pname) + { + case GL_PIXEL_LOCAL_FORMAT_ANGLE: + case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE: + case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: + case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: + break; + default: + ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); + return false; + } + + if (params == nullptr) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); + return false; + } + + return true; +} + +bool ValidateGetFramebufferPixelLocalStorageParameterRobustCommon(const Context *context, + angle::EntryPoint entryPoint, + GLint plane, + GLenum pname, + GLsizei bufSize, + const void *params) +{ + if (!ValidateGetFramebufferPixelLocalStorageParameterCommon(context, entryPoint, plane, pname, + params)) + { + // Error already generated. + return false; + } + + GLsizei paramCount = 1; + switch (pname) + { + case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: + case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: + paramCount = 4; + break; + } + + if (paramCount > bufSize) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientParams); + return false; + } + + return true; +} + bool ValidatePLSInternalformat(const Context *context, angle::EntryPoint entryPoint, GLenum internalformat) @@ -2175,6 +1889,7 @@ bool ValidatePLSInternalformat(const Context *context, case GL_RGBA8I: case GL_RGBA8UI: case GL_R32F: + case GL_R32I: case GL_R32UI: return true; default: @@ -2189,7 +1904,8 @@ bool ValidatePLSTextureType(const Context *context, size_t *textureDepth) { // INVALID_OPERATION is generated if is nonzero - // and not of type TEXTURE_2D or TEXTURE_2D_ARRAY. + // and not of type TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP, + // or TEXTURE_CUBE_MAP_ARRAY. switch (tex->getType()) { case TextureType::_2D: @@ -2198,6 +1914,12 @@ bool ValidatePLSTextureType(const Context *context, case TextureType::_2DArray: *textureDepth = tex->getDepth(TextureTarget::_2DArray, 0); return true; + case TextureType::CubeMap: + *textureDepth = 6; + return true; + case TextureType::CubeMapArray: + *textureDepth = tex->getDepth(TextureTarget::CubeMapArray, 0); + return true; default: ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSInvalidTextureType); return false; @@ -2230,7 +1952,8 @@ bool ValidatePLSActiveBlendEquation(const Context *context, { // INVALID_OPERATION is generated if BLEND_EQUATION_RGB and/or BLEND_EQUATION_ALPHA is an // advanced blend equation defined in KHR_blend_equation_advanced. - ASSERT(context->getState().getExtensions().blendEquationAdvancedKHR); + ASSERT(context->getState().getExtensions().blendEquationAdvancedKHR || + context->getClientVersion() >= ES_3_2); switch (blendEquation) { case gl::BlendEquationType::Multiply: @@ -2286,28 +2009,6 @@ bool ValidatePLSStoreOperation(const Context *context, angle::EntryPoint entryPo return false; } } - -bool ValidatePLSQueryCommon(const Context *context, - angle::EntryPoint entryPoint, - GLsizei paramCount, - GLsizei bufSize, - const void *params) -{ - // INVALID_OPERATION is generated if is not large enough to receive the requested - // parameter. - if (paramCount > bufSize) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientParams); - return false; - } - // INVALID_VALUE is generated if is NULL. - if (params == nullptr) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL); - return false; - } - return true; -} } // namespace bool ValidateFramebufferMemorylessPixelLocalStorageANGLE(const Context *context, @@ -2328,6 +2029,13 @@ bool ValidateFramebufferMemorylessPixelLocalStorageANGLE(const Context *context, { return false; } + + // INVALID_OPERATION is generated if is not NONE and not color-renderable. + if (!context->getTextureCaps().get(internalformat).textureAttachment) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFormatNotRenderable); + return false; + } } return true; @@ -2363,7 +2071,8 @@ bool ValidateFramebufferTexturePixelLocalStorageANGLE(const Context *context, } // INVALID_OPERATION is generated if is nonzero - // and not of type GL_TEXTURE_2D or GL_TEXTURE_2D_ARRAY. + // and not of type GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP, + // or GL_TEXTURE_CUBE_MAP_ARRAY. size_t textureDepth; if (!ValidatePLSTextureType(context, entryPoint, tex, &textureDepth)) { @@ -2408,6 +2117,14 @@ bool ValidateFramebufferTexturePixelLocalStorageANGLE(const Context *context, { return false; } + + // INVALID_OPERATION is generated if is nonzero and its internalformat + // is not color-renderable. + if (!context->getTextureCaps().get(internalformat).textureAttachment) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFormatNotRenderable); + return false; + } } return true; @@ -2465,17 +2182,17 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, return false; } - // INVALID_OPERATION is generated if RASTERIZER_DISCARD is enabled. - if (state.isRasterizerDiscardEnabled()) + // INVALID_OPERATION is generated if TRANSFORM_FEEDBACK_ACTIVE is true. + if (state.isTransformFeedbackActive()) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSRasterizerDiscardEnabled); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSTransformFeedbackActive); return false; } - // INVALID_OPERATION is generated if TRANSFORM_FEEDBACK_ACTIVE is true. - if (state.isTransformFeedbackActive()) + // INVALID_OPERATION is generated if QCOM_tiled_rendering is active. + if (context->getPrivateState().isTiledRendering()) { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSTransformFeedbackActive); + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSTiledRenderingActive); return false; } @@ -2499,7 +2216,7 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, // INVALID_OPERATION is generated if BLEND_EQUATION_RGB and/or BLEND_EQUATION_ALPHA is an // advanced blend equation defined in KHR_blend_equation_advanced. - if (state.getExtensions().blendEquationAdvancedKHR) + if (state.getExtensions().blendEquationAdvancedKHR || context->getClientVersion() >= ES_3_2) { if (!ValidatePLSActiveBlendEquation(context, entryPoint, state.getBlendStateExt().getEquationColorIndexed(0)) || @@ -2524,33 +2241,16 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to // any color attachment point on or after: // - // COLOR_ATTACHMENT0 + - // MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE + // COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - // const Caps &caps = context->getCaps(); - for (int i = caps.maxColorAttachmentsWithActivePixelLocalStorage; i < caps.maxColorAttachments; + for (int i = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - n; i < caps.maxDrawBuffers; ++i) { if (framebuffer->getColorAttachment(i)) { ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, - kPLSMaxColorAttachmentsExceded); - return false; - } - } - - // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to - // any color attachment point on or after: - // - // COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - // - for (GLuint i = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - n; - i < caps.maxColorAttachmentsWithActivePixelLocalStorage; ++i) - { - if (framebuffer->getColorAttachment(i)) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, - kPLSMaxCombinedDrawBuffersAndPlanesExceded); + kPLSMaxCombinedDrawBuffersAndPlanesExceded); return false; } } @@ -2607,15 +2307,76 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, } else { - // INVALID_OPERATION is generated if [0..-1] is - // LOAD_OP_LOAD_ANGLE and the pixel local storage plane at that same - // index is memoryless. + // INVALID_OPERATION is generated if [0..-1] is LOAD_OP_LOAD_ANGLE and the + // pixel local storage plane at that same index is memoryless. if (loadops[i] == GL_LOAD_OP_LOAD_ANGLE) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSKeepingMemorylessPlane); return false; } } + + if (!plane.isMemoryless()) + { + ASSERT(plane.getTextureID() != TextureID()); + + const ImageIndex &planeImageIdx = plane.getTextureImageIndex(); + ASSERT(planeImageIdx.getLayerCount() == 1); + ASSERT(planeImageIdx.getLevelIndex() >= 0); + + // INVALID_OPERATION is generated if, for any active backing texture, the mipmap level + // bound to pixel local storage is outside the effective base/max range of that texture. + const Texture *const backingTexture = plane.getBackingTexture(context); + if (planeImageIdx.getLevelIndex() < + static_cast(backingTexture->getState().getEffectiveBaseLevel()) || + planeImageIdx.getLevelIndex() > + static_cast(backingTexture->getState().getEffectiveMaxLevel())) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSLevelIndexOutOfRange); + return false; + } + + // INVALID_OPERATION is generated if a single texture slice is bound to more than one + // active pixel local storage plane. + for (GLsizei j = i + 1; j < n; ++j) + { + const PixelLocalStoragePlane &otherPlane = pls->getPlane(j); + if (!otherPlane.isMemoryless() && + plane.getTextureID() == otherPlane.getTextureID() && + planeImageIdx == otherPlane.getTextureImageIndex()) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSSingleTexImageMultiplePlanes); + return false; + } + } + + // INVALID_OPERATION is generated if a single texture slice is simultaneously bound to + // an active pixel local storage plane and attached to an enabled drawbuffer. + const GLuint maxDrawBuffersWithPLSPlanes = std::min( + caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - n, caps.maxDrawBuffers); + for (GLuint j = 0; j < maxDrawBuffersWithPLSPlanes; ++j) + { + if (framebuffer->getDrawBufferMask().test(j) && + framebuffer->getColorAttachment(j)->isTextureWithId(plane.getTextureID())) + { + // Compare the ImageIndex values for the PLS plane and framebuffer attachment + // manually; the framebuffer uses a layer index of -1 for texture2d attachments, + // whereas PLS uses a layer index of 0. + const ImageIndex &attachmentImageIdx = + framebuffer->getColorAttachment(j)->getTextureImageIndex(); + ASSERT(attachmentImageIdx.getLayerCount() == 1); + if (planeImageIdx.getType() == attachmentImageIdx.getType() && + planeImageIdx.getLevelIndex() == attachmentImageIdx.getLevelIndex() && + planeImageIdx.getLayerIndex() == + std::max(attachmentImageIdx.getLayerIndex(), 0)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, + kPLSSingleTexImagePLSAndAttachment); + return false; + } + } + } + } } const FramebufferAttachment *firstAttachment = @@ -2643,18 +2404,6 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, } } - // INVALID_OPERATION is generated if a single texture image is bound to more than one pixel - // local storage plane. - // - // TODO(anglebug.com/40096838): Block feedback loops - // - - // INVALID_OPERATION is generated if a single texture image is simultaneously bound to a pixel - // local storage plane and attached to the draw framebuffer. - // - // TODO(anglebug.com/40096838): Block feedback loops - // - return true; } @@ -2696,13 +2445,6 @@ bool ValidatePixelLocalStorageBarrierANGLE(const Context *context, angle::EntryP bool ValidateFramebufferPixelLocalStorageInterruptANGLE(const Context *context, angle::EntryPoint entryPoint) { - // Check that the pixel local storage extension is enabled at all. - if (!context->getExtensions().shaderPixelLocalStorageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSExtensionNotEnabled); - return false; - } - // INVALID_FRAMEBUFFER_OPERATION is generated if the current interrupt count on the draw // framebuffer is greater than or equal to 255. const PixelLocalStorage *pls = @@ -2719,13 +2461,6 @@ bool ValidateFramebufferPixelLocalStorageInterruptANGLE(const Context *context, bool ValidateFramebufferPixelLocalStorageRestoreANGLE(const Context *context, angle::EntryPoint entryPoint) { - // Check that the pixel local storage extension is enabled at all. - if (!context->getExtensions().shaderPixelLocalStorageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSExtensionNotEnabled); - return false; - } - // This command is ignored when the default framebuffer object name 0 is bound. const Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); if (context->getState().getDrawFramebuffer()->id().value == 0) @@ -2751,8 +2486,8 @@ bool ValidateGetFramebufferPixelLocalStorageParameterfvANGLE(const Context *cont GLenum pname, const GLfloat *params) { - return ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE( - context, entryPoint, plane, pname, std::numeric_limits::max(), nullptr, params); + return ValidateGetFramebufferPixelLocalStorageParameterCommon(context, entryPoint, plane, pname, + params); } bool ValidateGetFramebufferPixelLocalStorageParameterivANGLE(const Context *context, @@ -2761,8 +2496,8 @@ bool ValidateGetFramebufferPixelLocalStorageParameterivANGLE(const Context *cont GLenum pname, const GLint *params) { - return ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE( - context, entryPoint, plane, pname, std::numeric_limits::max(), nullptr, params); + return ValidateGetFramebufferPixelLocalStorageParameterCommon(context, entryPoint, plane, pname, + params); } bool ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE(const Context *context, @@ -2773,23 +2508,14 @@ bool ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE(const Context const GLsizei *length, const GLfloat *params) { - if (!ValidatePLSCommon(context, entryPoint, plane, PLSExpectedStatus::Any)) + if (!context->getExtensions().shaderPixelLocalStorageANGLE) { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } - GLsizei paramCount = 0; - switch (pname) - { - case GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE: - paramCount = 4; - break; - default: - // INVALID_ENUM is generated if is not in Table 6.Y, or if the command issued is - // not the associated "Get Command" for in Table 6.Y. - ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); - return false; - } - return ValidatePLSQueryCommon(context, entryPoint, paramCount, bufSize, params); + + return ValidateGetFramebufferPixelLocalStorageParameterRobustCommon(context, entryPoint, plane, + pname, bufSize, params); } bool ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE(const Context *context, @@ -2800,40 +2526,18 @@ bool ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE(const Context const GLsizei *length, const GLint *params) { - if (!ValidatePLSCommon(context, entryPoint, plane, PLSExpectedStatus::Any)) + if (!context->getExtensions().shaderPixelLocalStorageANGLE) { + ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } - GLsizei paramCount = 0; - switch (pname) - { - case GL_PIXEL_LOCAL_FORMAT_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: - case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE: - paramCount = 1; - break; - case GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE: - case GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE: - paramCount = 4; - break; - default: - // INVALID_ENUM is generated if is not in Table 6.Y, or if the command issued is - // not the associated "Get Command" for in Table 6.Y. - ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname); - return false; - } - return ValidatePLSQueryCommon(context, entryPoint, paramCount, bufSize, params); + + return ValidateGetFramebufferPixelLocalStorageParameterRobustCommon(context, entryPoint, plane, + pname, bufSize, params); } bool ValidateFramebufferFetchBarrierEXT(const Context *context, angle::EntryPoint entryPoint) { - if (!context->getExtensions().shaderFramebufferFetchNonCoherentEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, - kFramebufferFetchNonCoherentExtensionNotEnabled); - return false; - } return true; } @@ -2843,12 +2547,6 @@ bool ValidatePatchParameteriEXT(const PrivateState &state, GLenum pname, GLint value) { - if (!state.getExtensions().tessellationShaderEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kTessellationShaderEXTNotEnabled); - return false; - } - return ValidatePatchParameteriBase(state, errors, entryPoint, pname, value); } @@ -2858,12 +2556,6 @@ bool ValidatePatchParameteriOES(const PrivateState &state, GLenum pname, GLint value) { - if (!state.getExtensions().tessellationShaderOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kTessellationShaderOESNotEnabled); - return false; - } - return ValidatePatchParameteriBase(state, errors, entryPoint, pname, value); } @@ -2880,12 +2572,6 @@ bool ValidateTexStorageMemFlags2DANGLE(const Context *context, GLbitfield usageFlags, const void *imageCreateInfoPNext) { - if (!context->getExtensions().memoryObjectFlagsANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!ValidateTexStorageMem2DEXT(context, entryPoint, targetPacked, levels, internalFormat, width, height, memoryPacked, offset)) { @@ -3078,12 +2764,6 @@ bool ValidateClipControlEXT(const PrivateState &state, ClipOrigin originPacked, ClipDepthMode depthPacked) { - if (!state.getExtensions().clipControlEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (originPacked == ClipOrigin::InvalidEnum) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidOriginEnum); @@ -3128,18 +2808,119 @@ bool ValidateBufferStorageExternalEXT(const Context *context, return true; } -bool ValidateNamedBufferStorageExternalEXT(const Context *context, - angle::EntryPoint entryPoint, - GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags) +// GL_EXT_fragment_shading_rate +bool ValidateFramebufferShadingRateEXT(const Context *context, + angle::EntryPoint entryPoint, + GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight) { - UNIMPLEMENTED(); return false; } +bool ValidateGetFragmentShadingRatesEXT(const Context *context, + angle::EntryPoint entryPoint, + GLsizei samples, + GLsizei maxCount, + const GLsizei *count, + const GLenum *shadingRates) +{ + // If a negative number is provided where an argument of type sizei or + // sizeiptr is specified, an INVALID_VALUE error is generated. + if ((samples < 0) || (maxCount < 0)) + { + ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize); + return false; + } + return true; +} + +bool ValidateShadingRateEXT(const PrivateState &state, + ErrorSet *errors, + angle::EntryPoint entryPoint, + ShadingRate ratePacked) +{ + // INVALID_ENUM is generated by ShadingRateEXT if is not a valid shading rate. + if (ratePacked == gl::ShadingRate::Undefined || ratePacked == gl::ShadingRate::InvalidEnum) + { + errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShadingRate); + return false; + } + + return true; +} + +bool ValidateShadingRateCombinerOpsEXT(const PrivateState &state, + ErrorSet *errors, + angle::EntryPoint entryPoint, + CombinerOp combinerOp0Packed, + CombinerOp combinerOp1Packed) +{ + + // An INVALID_ENUM error is generated if / is not + // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + // FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT, + // FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT, + // FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT or + // FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT + if (combinerOp0Packed == gl::CombinerOp::Undefined || + combinerOp0Packed == gl::CombinerOp::InvalidEnum || + combinerOp1Packed == gl::CombinerOp::Undefined || + combinerOp1Packed == gl::CombinerOp::InvalidEnum) + { + errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShadingCombinerOp); + return false; + } + + // An INVALID_OPERATION error is generated if the value of + // FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT + // is FALSE and / is not + // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT or + // FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT + if (!state.getCaps() + .fragmentShadingRateProperties.fragmentShadingRateNonTrivialCombinersSupport) + { + if ((combinerOp0Packed != gl::CombinerOp::Keep && + combinerOp0Packed != gl::CombinerOp::Replace) || + (combinerOp1Packed != gl::CombinerOp::Keep && + combinerOp1Packed != gl::CombinerOp::Replace)) + { + errors->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShadingCombinerOp); + return false; + } + } + + // If GL_EXT_fragment_shading_rate_primitive is not supported + // An INVALID_OPERATION error is generated if is not + // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT + if (!state.getExtensions().fragmentShadingRatePrimitiveEXT) + { + if (combinerOp0Packed != gl::CombinerOp::Keep) + { + errors->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShadingCombinerOp); + return false; + } + } + + // If GL_EXT_fragment_shading_rate_attachment is not supported + // An INVALID_OPERATION error is generated if is not + // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT + if (!state.getExtensions().fragmentShadingRateAttachmentEXT) + { + if (combinerOp1Packed != gl::CombinerOp::Keep) + { + errors->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShadingCombinerOp); + return false; + } + } + + return true; +} + // GL_ANGLE_polygon_mode bool ValidatePolygonModeANGLE(const PrivateState &state, ErrorSet *errors, @@ -3147,12 +2928,6 @@ bool ValidatePolygonModeANGLE(const PrivateState &state, GLenum face, PolygonMode modePacked) { - if (!state.getExtensions().polygonModeANGLE) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (face != GL_FRONT_AND_BACK) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCullMode); @@ -3175,12 +2950,6 @@ bool ValidatePolygonModeNV(const PrivateState &state, GLenum face, PolygonMode modePacked) { - if (!state.getExtensions().polygonModeNV) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (face != GL_FRONT_AND_BACK) { errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCullMode); @@ -3204,12 +2973,6 @@ bool ValidatePolygonOffsetClampEXT(const PrivateState &state, GLfloat units, GLfloat clamp) { - if (!state.getExtensions().polygonOffsetClampEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -3226,12 +2989,6 @@ bool ValidatePrimitiveBoundingBoxEXT(const PrivateState &state, GLfloat maxZ, GLfloat maxW) { - if (!state.getExtensions().primitiveBoundingBoxEXT) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -3248,12 +3005,6 @@ bool ValidatePrimitiveBoundingBoxOES(const PrivateState &state, GLfloat maxZ, GLfloat maxW) { - if (!state.getExtensions().primitiveBoundingBoxOES) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -3268,12 +3019,6 @@ bool ValidateTexStorage3DMultisampleOES(const Context *context, GLsizei depth, GLboolean fixedsamplelocations) { - if (!context->getExtensions().textureStorageMultisample2dArrayOES) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateTexStorage3DMultisampleBase(context, entryPoint, target, samples, internalformat, width, height, depth); } @@ -3284,12 +3029,6 @@ bool ValidateActiveShaderProgramEXT(const Context *context, ProgramPipelineID pipelinePacked, ShaderProgramID programPacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateActiveShaderProgramBase(context, entryPoint, pipelinePacked, programPacked); } @@ -3297,12 +3036,6 @@ bool ValidateBindProgramPipelineEXT(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateBindProgramPipelineBase(context, entryPoint, pipelinePacked); } @@ -3310,14 +3043,8 @@ bool ValidateCreateShaderProgramvEXT(const Context *context, angle::EntryPoint entryPoint, ShaderType typePacked, GLsizei count, - const GLchar **strings) + const GLchar *const *strings) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateCreateShaderProgramvBase(context, entryPoint, typePacked, count, strings); } @@ -3326,12 +3053,6 @@ bool ValidateDeleteProgramPipelinesEXT(const Context *context, GLsizei n, const ProgramPipelineID *pipelinesPacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateDeleteProgramPipelinesBase(context, entryPoint, n, pipelinesPacked); } @@ -3340,12 +3061,6 @@ bool ValidateGenProgramPipelinesEXT(const Context *context, GLsizei n, const ProgramPipelineID *pipelinesPacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGenProgramPipelinesBase(context, entryPoint, n, pipelinesPacked); } @@ -3356,12 +3071,6 @@ bool ValidateGetProgramPipelineInfoLogEXT(const Context *context, const GLsizei *length, const GLchar *infoLog) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetProgramPipelineInfoLogBase(context, entryPoint, pipelinePacked, bufSize, length, infoLog); } @@ -3372,12 +3081,6 @@ bool ValidateGetProgramPipelineivEXT(const Context *context, GLenum pname, const GLint *params) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateGetProgramPipelineivBase(context, entryPoint, pipelinePacked, pname, params); } @@ -3385,12 +3088,6 @@ bool ValidateIsProgramPipelineEXT(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateIsProgramPipelineBase(context, entryPoint, pipelinePacked); } @@ -3400,12 +3097,6 @@ bool ValidateProgramParameteriEXT(const Context *context, GLenum pname, GLint value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramParameteriBase(context, entryPoint, programPacked, pname, value); } @@ -3415,12 +3106,6 @@ bool ValidateProgramUniform1fEXT(const Context *context, UniformLocation locationPacked, GLfloat v0) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform1fBase(context, entryPoint, programPacked, locationPacked, v0); } @@ -3431,12 +3116,6 @@ bool ValidateProgramUniform1fvEXT(const Context *context, GLsizei count, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform1fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3447,12 +3126,6 @@ bool ValidateProgramUniform1iEXT(const Context *context, UniformLocation locationPacked, GLint v0) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform1iBase(context, entryPoint, programPacked, locationPacked, v0); } @@ -3463,12 +3136,6 @@ bool ValidateProgramUniform1ivEXT(const Context *context, GLsizei count, const GLint *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform1ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3479,12 +3146,6 @@ bool ValidateProgramUniform1uiEXT(const Context *context, UniformLocation locationPacked, GLuint v0) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform1uiBase(context, entryPoint, programPacked, locationPacked, v0); } @@ -3495,12 +3156,6 @@ bool ValidateProgramUniform1uivEXT(const Context *context, GLsizei count, const GLuint *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform1uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3512,12 +3167,6 @@ bool ValidateProgramUniform2fEXT(const Context *context, GLfloat v0, GLfloat v1) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform2fBase(context, entryPoint, programPacked, locationPacked, v0, v1); } @@ -3528,12 +3177,6 @@ bool ValidateProgramUniform2fvEXT(const Context *context, GLsizei count, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform2fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3545,12 +3188,6 @@ bool ValidateProgramUniform2iEXT(const Context *context, GLint v0, GLint v1) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform2iBase(context, entryPoint, programPacked, locationPacked, v0, v1); } @@ -3560,13 +3197,7 @@ bool ValidateProgramUniform2ivEXT(const Context *context, UniformLocation locationPacked, GLsizei count, const GLint *value) -{ - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - +{ return ValidateProgramUniform2ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3578,12 +3209,6 @@ bool ValidateProgramUniform2uiEXT(const Context *context, GLuint v0, GLuint v1) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform2uiBase(context, entryPoint, programPacked, locationPacked, v0, v1); } @@ -3595,12 +3220,6 @@ bool ValidateProgramUniform2uivEXT(const Context *context, GLsizei count, const GLuint *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform2uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3613,12 +3232,6 @@ bool ValidateProgramUniform3fEXT(const Context *context, GLfloat v1, GLfloat v2) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform3fBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2); } @@ -3630,12 +3243,6 @@ bool ValidateProgramUniform3fvEXT(const Context *context, GLsizei count, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform3fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3648,12 +3255,6 @@ bool ValidateProgramUniform3iEXT(const Context *context, GLint v1, GLint v2) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform3iBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2); } @@ -3665,12 +3266,6 @@ bool ValidateProgramUniform3ivEXT(const Context *context, GLsizei count, const GLint *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform3ivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3683,12 +3278,6 @@ bool ValidateProgramUniform3uiEXT(const Context *context, GLuint v1, GLuint v2) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform3uiBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2); } @@ -3700,12 +3289,6 @@ bool ValidateProgramUniform3uivEXT(const Context *context, GLsizei count, const GLuint *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform3uivBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3719,12 +3302,6 @@ bool ValidateProgramUniform4fEXT(const Context *context, GLfloat v2, GLfloat v3) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform4fBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2, v3); } @@ -3736,12 +3313,6 @@ bool ValidateProgramUniform4fvEXT(const Context *context, GLsizei count, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform4fvBase(context, entryPoint, programPacked, locationPacked, count, value); } @@ -3755,12 +3326,6 @@ bool ValidateProgramUniform4iEXT(const Context *context, GLint v2, GLint v3) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform4iBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2, v3); } @@ -3785,12 +3350,6 @@ bool ValidateProgramUniform4uiEXT(const Context *context, GLuint v2, GLuint v3) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniform4uiBase(context, entryPoint, programPacked, locationPacked, v0, v1, v2, v3); } @@ -3814,12 +3373,6 @@ bool ValidateProgramUniformMatrix2fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix2fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3832,12 +3385,6 @@ bool ValidateProgramUniformMatrix2x3fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix2x3fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3850,12 +3397,6 @@ bool ValidateProgramUniformMatrix2x4fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix2x4fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3868,12 +3409,6 @@ bool ValidateProgramUniformMatrix3fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix3fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3886,12 +3421,6 @@ bool ValidateProgramUniformMatrix3x2fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix3x2fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3904,12 +3433,6 @@ bool ValidateProgramUniformMatrix3x4fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix3x4fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3922,12 +3445,6 @@ bool ValidateProgramUniformMatrix4fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix4fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3940,12 +3457,6 @@ bool ValidateProgramUniformMatrix4x2fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix4x2fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3958,12 +3469,6 @@ bool ValidateProgramUniformMatrix4x3fvEXT(const Context *context, GLboolean transpose, const GLfloat *value) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateProgramUniformMatrix4x3fvBase(context, entryPoint, programPacked, locationPacked, count, transpose, value); } @@ -3974,12 +3479,6 @@ bool ValidateUseProgramStagesEXT(const Context *context, GLbitfield stages, ShaderProgramID programPacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateUseProgramStagesBase(context, entryPoint, pipelinePacked, stages, programPacked); } @@ -3987,12 +3486,6 @@ bool ValidateValidateProgramPipelineEXT(const Context *context, angle::EntryPoint entryPoint, ProgramPipelineID pipelinePacked) { - if (!context->getExtensions().separateShaderObjectsEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateValidateProgramPipelineBase(context, entryPoint, pipelinePacked); } @@ -4005,12 +3498,6 @@ bool ValidateGetObjectLabelEXT(const Context *context, const GLsizei *length, const GLchar *label) { - if (!context->getExtensions().debugLabelEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (bufSize < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize); @@ -4027,12 +3514,6 @@ bool ValidateLabelObjectEXT(const Context *context, GLsizei length, const GLchar *label) { - if (!context->getExtensions().debugLabelEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (length < 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLength); @@ -4042,28 +3523,12 @@ bool ValidateLabelObjectEXT(const Context *context, return ValidateObjectIdentifierAndName(context, entryPoint, type, object); } -bool ValidateEGLImageTargetTextureStorageEXT(const Context *context, - angle::EntryPoint entryPoint, - GLuint texture, - egl::ImageID image, - const GLint *attrib_list) -{ - UNREACHABLE(); - return false; -} - bool ValidateEGLImageTargetTexStorageEXT(const Context *context, angle::EntryPoint entryPoint, GLenum target, egl::ImageID image, const GLint *attrib_list) { - if (!context->getExtensions().EGLImageStorageEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - gl::TextureType targetType = FromGLenum(target); switch (targetType) { @@ -4071,12 +3536,15 @@ bool ValidateEGLImageTargetTexStorageEXT(const Context *context, if (!context->getExtensions().EGLImageExternalOES) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(targetType)); + return false; } break; case TextureType::CubeMapArray: - if (!context->getExtensions().textureCubeMapArrayAny()) + if (!context->getExtensions().textureCubeMapArrayAny() && + context->getClientVersion() < ES_3_2) { ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(targetType)); + return false; } break; case TextureType::_2D: @@ -4184,12 +3652,6 @@ bool ValidateAcquireTexturesANGLE(const Context *context, const TextureID *textures, const GLenum *layouts) { - if (!context->getExtensions().vulkanImageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - for (GLuint i = 0; i < numTextures; ++i) { if (!context->getTexture(textures[i])) @@ -4213,11 +3675,6 @@ bool ValidateReleaseTexturesANGLE(const Context *context, const TextureID *textures, const GLenum *layouts) { - if (!context->getExtensions().vulkanImageANGLE) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } for (GLuint i = 0; i < numTextures; ++i) { if (!context->getTexture(textures[i])) @@ -4263,12 +3720,6 @@ bool ValidateBeginPerfMonitorAMD(const Context *context, angle::EntryPoint entryPoint, GLuint monitor) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -4277,24 +3728,12 @@ bool ValidateDeletePerfMonitorsAMD(const Context *context, GLsizei n, const GLuint *monitors) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - // Note: ANGLE does not really create monitor objects or track ids. return true; } bool ValidateEndPerfMonitorAMD(const Context *context, angle::EntryPoint entryPoint, GLuint monitor) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (!context->getState().isPerfMonitorActive()) { ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPerfMonitorNotActive); @@ -4309,12 +3748,6 @@ bool ValidateGenPerfMonitorsAMD(const Context *context, GLsizei n, const GLuint *monitors) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -4326,12 +3759,6 @@ bool ValidateGetPerfMonitorCounterDataAMD(const Context *context, const GLuint *data, const GLint *bytesWritten) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - if (monitor != 0) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidPerfMonitor); @@ -4360,13 +3787,7 @@ bool ValidateGetPerfMonitorCounterInfoAMD(const Context *context, GLenum pname, const void *data) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups(); + const angle::PerfMonitorCounterGroupsInfo &groups = context->getPerfMonitorCounterGroups(); if (group >= groups.size()) { @@ -4402,13 +3823,7 @@ bool ValidateGetPerfMonitorCounterStringAMD(const Context *context, const GLsizei *length, const GLchar *counterString) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups(); + const angle::PerfMonitorCounterGroupsInfo &groups = context->getPerfMonitorCounterGroups(); if (group >= groups.size()) { @@ -4433,13 +3848,7 @@ bool ValidateGetPerfMonitorCountersAMD(const Context *context, GLsizei counterSize, const GLuint *counters) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups(); + const angle::PerfMonitorCounterGroupsInfo &groups = context->getPerfMonitorCounterGroups(); if (group >= groups.size()) { @@ -4457,13 +3866,7 @@ bool ValidateGetPerfMonitorGroupStringAMD(const Context *context, const GLsizei *length, const GLchar *groupString) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups(); + const angle::PerfMonitorCounterGroupsInfo &groups = context->getPerfMonitorCounterGroups(); if (group >= groups.size()) { @@ -4480,12 +3883,6 @@ bool ValidateGetPerfMonitorGroupsAMD(const Context *context, GLsizei groupsSize, const GLuint *groups) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return true; } @@ -4497,12 +3894,6 @@ bool ValidateSelectPerfMonitorCountersAMD(const Context *context, GLint numCounters, const GLuint *counterList) { - if (!context->getExtensions().performanceMonitorAMD) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - UNIMPLEMENTED(); return false; } @@ -4510,22 +3901,28 @@ bool ValidateSelectPerfMonitorCountersAMD(const Context *context, bool ValidateShadingRateQCOM(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, - GLenum rate) -{ - if (!state.getExtensions().shadingRateQCOM) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - gl::ShadingRate shadingRate = gl::FromGLenum(rate); - if (shadingRate == gl::ShadingRate::Undefined || shadingRate == gl::ShadingRate::InvalidEnum) - { - errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShadingRate); - return false; + ShadingRate ratePacked) +{ + // Allowed in the parameter in ShadingRateQCOM: + // SHADING_RATE_1X1_PIXELS_QCOM + // SHADING_RATE_1X2_PIXELS_QCOM + // SHADING_RATE_2X1_PIXELS_QCOM + // SHADING_RATE_2X2_PIXELS_QCOM + // SHADING_RATE_4X2_PIXELS_QCOM + // SHADING_RATE_4X4_PIXELS_QCOM + switch (ratePacked) + { + case gl::ShadingRate::_1x1: + case gl::ShadingRate::_1x2: + case gl::ShadingRate::_2x1: + case gl::ShadingRate::_2x2: + case gl::ShadingRate::_4x2: + case gl::ShadingRate::_4x4: + return true; + default: + errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShadingRate); + return false; } - - return true; } bool ValidateLogicOpANGLE(const PrivateState &state, @@ -4533,12 +3930,6 @@ bool ValidateLogicOpANGLE(const PrivateState &state, angle::EntryPoint entryPoint, LogicalOperation opcodePacked) { - if (!state.getExtensions().logicOpANGLE) - { - errors->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - return ValidateLogicOpCommon(state, errors, entryPoint, opcodePacked); } @@ -4680,12 +4071,6 @@ bool ValidateEndTilingQCOM(const Context *context, angle::EntryPoint entryPoint, GLbitfield preserveMask) { - if (!context->getExtensions().tiledRenderingQCOM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const gl::PrivateState &privateState = context->getPrivateState(); if (!privateState.isTiledRendering()) { @@ -4707,12 +4092,6 @@ bool ValidateStartTilingQCOM(const Context *context, GLuint height, GLbitfield preserveMask) { - if (!context->getExtensions().tiledRenderingQCOM) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - const gl::PrivateState &privateState = context->getPrivateState(); if (privateState.isTiledRendering()) { @@ -4772,31 +4151,14 @@ bool ValidateTexStorageAttribs2DEXT(const Context *context, GLsizei height, const GLint *attrib_list) { - gl::TextureType targetType = FromGLenum(target); - if (!context->getExtensions().textureStorageCompressionEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (ValidateTexStorageAttribs(attrib_list) == false) + if (!ValidateTexStorageAttribs(attrib_list)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAttribList); + return false; } - if (context->getClientMajorVersion() < 3) - { - return ValidateES2TexStorageParametersBase(context, entryPoint, targetType, levels, - internalformat, width, height); - } - - if (context->getClientMajorVersion() >= 3) - { - return ValidateES3TexStorage2DParameters(context, entryPoint, targetType, levels, - internalformat, width, height, 1); - } - - return true; + return ValidateES3TexStorage2DParameters(context, entryPoint, FromGLenum(target), + levels, internalformat, width, height, 1); } bool ValidateTexStorageAttribs3DEXT(const Context *context, @@ -4809,31 +4171,14 @@ bool ValidateTexStorageAttribs3DEXT(const Context *context, GLsizei depth, const GLint *attrib_list) { - gl::TextureType targetType = FromGLenum(target); - if (!context->getExtensions().textureStorageCompressionEXT) - { - ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled); - return false; - } - - if (ValidateTexStorageAttribs(attrib_list) == false) + if (!ValidateTexStorageAttribs(attrib_list)) { ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAttribList); + return false; } - if (context->getClientMajorVersion() < 3) - { - return ValidateES2TexStorageParametersBase(context, entryPoint, targetType, levels, - internalformat, width, height); - } - - if (context->getClientMajorVersion() >= 3) - { - return ValidateES3TexStorage3DParameters(context, entryPoint, targetType, levels, - internalformat, width, height, depth); - } - - return true; + return ValidateES3TexStorage3DParameters(context, entryPoint, FromGLenum(target), + levels, internalformat, width, height, depth); } } // namespace gl diff --git a/src/libANGLE/validationESEXT.h b/src/libANGLE/validationESEXT.h index b22ed4e379e..e9eba805188 100644 --- a/src/libANGLE/validationESEXT.h +++ b/src/libANGLE/validationESEXT.h @@ -14,7 +14,9 @@ namespace gl { -// Nothing here yet. + +void RecordVersionErrorESEXT(const Context *context, angle::EntryPoint entryPoint); + } // namespace gl #endif // LIBANGLE_VALIDATION_ESEXT_H_ diff --git a/src/libANGLE/validationESEXT_autogen.h b/src/libANGLE/validationESEXT_autogen.h index 9bdc56f0bf1..e2a9a86604c 100644 --- a/src/libANGLE/validationESEXT_autogen.h +++ b/src/libANGLE/validationESEXT_autogen.h @@ -18,6 +18,7 @@ namespace gl { class Context; class PrivateState; +class PrivateStateCache; class ErrorSet; // GL_AMD_performance_monitor @@ -242,7 +243,8 @@ bool ValidateDrawElementsInstancedANGLE(const Context *context, DrawElementsType typePacked, const void *indices, GLsizei primcount); -bool ValidateVertexAttribDivisorANGLE(const Context *context, +bool ValidateVertexAttribDivisorANGLE(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLuint divisor); @@ -880,6 +882,20 @@ bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context, GLsizei bufSize, const GLsizei *length, const GLuint64 *params); +bool ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE(const Context *context, + angle::EntryPoint entryPoint, + GLint plane, + GLenum pname, + GLsizei bufSize, + const GLsizei *length, + const GLfloat *params); +bool ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE(const Context *context, + angle::EntryPoint entryPoint, + GLint plane, + GLenum pname, + GLsizei bufSize, + const GLsizei *length, + const GLint *params); // GL_ANGLE_robust_fragment_shader_output @@ -940,20 +956,6 @@ bool ValidateGetFramebufferPixelLocalStorageParameterivANGLE(const Context *cont GLint plane, GLenum pname, const GLint *params); -bool ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLint plane, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLfloat *params); -bool ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE(const Context *context, - angle::EntryPoint entryPoint, - GLint plane, - GLenum pname, - GLsizei bufSize, - const GLsizei *length, - const GLint *params); // GL_ANGLE_stencil_texturing @@ -1022,14 +1024,14 @@ bool ValidateReleaseTexturesANGLE(const Context *context, // GL_APPLE_clip_distance -// GL_ARB_sync - // GL_ARM_rgba8 // GL_ARM_shader_framebuffer_fetch // GL_ARM_shader_framebuffer_fetch_depth_stencil +// GL_ARM_texture_unnormalized_coordinates + // GL_CHROMIUM_bind_uniform_location bool ValidateBindUniformLocationCHROMIUM(const Context *context, angle::EntryPoint entryPoint, @@ -1093,11 +1095,6 @@ bool ValidateEGLImageTargetTexStorageEXT(const Context *context, GLenum target, egl::ImageID imagePacked, const GLint *attrib_list); -bool ValidateEGLImageTargetTextureStorageEXT(const Context *context, - angle::EntryPoint entryPoint, - GLuint texture, - egl::ImageID imagePacked, - const GLint *attrib_list); // GL_EXT_EGL_image_storage_compression @@ -1393,6 +1390,21 @@ bool ValidateMultiDrawElementsBaseVertexEXT(const Context *context, GLsizei drawcount, const GLint *basevertex); +// GL_EXT_draw_instanced +bool ValidateDrawArraysInstancedEXT(const Context *context, + angle::EntryPoint entryPoint, + PrimitiveMode modePacked, + GLint start, + GLsizei count, + GLsizei primcount); +bool ValidateDrawElementsInstancedEXT(const Context *context, + angle::EntryPoint entryPoint, + PrimitiveMode modePacked, + GLsizei count, + DrawElementsType typePacked, + const void *indices, + GLsizei primcount); + // GL_EXT_external_buffer bool ValidateBufferStorageExternalEXT(const Context *context, angle::EntryPoint entryPoint, @@ -1401,16 +1413,35 @@ bool ValidateBufferStorageExternalEXT(const Context *context, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); -bool ValidateNamedBufferStorageExternalEXT(const Context *context, - angle::EntryPoint entryPoint, - GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags); // GL_EXT_float_blend +// GL_EXT_fragment_shading_rate +bool ValidateFramebufferShadingRateEXT(const Context *context, + angle::EntryPoint entryPoint, + GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight); +bool ValidateGetFragmentShadingRatesEXT(const Context *context, + angle::EntryPoint entryPoint, + GLsizei samples, + GLsizei maxCount, + const GLsizei *count, + const GLenum *shadingRates); +bool ValidateShadingRateEXT(const PrivateState &state, + ErrorSet *errors, + angle::EntryPoint entryPoint, + ShadingRate ratePacked); +bool ValidateShadingRateCombinerOpsEXT(const PrivateState &state, + ErrorSet *errors, + angle::EntryPoint entryPoint, + CombinerOp combinerOp0Packed, + CombinerOp combinerOp1Packed); + // GL_EXT_geometry_shader bool ValidateFramebufferTextureEXT(const Context *context, angle::EntryPoint entryPoint, @@ -1422,20 +1453,8 @@ bool ValidateFramebufferTextureEXT(const Context *context, // GL_EXT_gpu_shader5 // GL_EXT_instanced_arrays -bool ValidateDrawArraysInstancedEXT(const Context *context, - angle::EntryPoint entryPoint, - PrimitiveMode modePacked, - GLint start, - GLsizei count, - GLsizei primcount); -bool ValidateDrawElementsInstancedEXT(const Context *context, - angle::EntryPoint entryPoint, - PrimitiveMode modePacked, - GLsizei count, - DrawElementsType typePacked, - const void *indices, - GLsizei primcount); -bool ValidateVertexAttribDivisorEXT(const Context *context, +bool ValidateVertexAttribDivisorEXT(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, GLuint index, GLuint divisor); @@ -1539,6 +1558,21 @@ bool ValidateImportMemoryFdEXT(const Context *context, HandleType handleTypePacked, GLint fd); +// GL_EXT_multi_draw_arrays +bool ValidateMultiDrawArraysEXT(const Context *context, + angle::EntryPoint entryPoint, + PrimitiveMode modePacked, + const GLint *first, + const GLsizei *count, + GLsizei primcount); +bool ValidateMultiDrawElementsEXT(const Context *context, + angle::EntryPoint entryPoint, + PrimitiveMode modePacked, + const GLsizei *count, + DrawElementsType typePacked, + const void *const *indices, + GLsizei primcount); + // GL_EXT_multi_draw_indirect bool ValidateMultiDrawArraysIndirectEXT(const Context *context, angle::EntryPoint entryPoint, @@ -1693,7 +1727,7 @@ bool ValidateCreateShaderProgramvEXT(const Context *context, angle::EntryPoint entryPoint, ShaderType typePacked, GLsizei count, - const GLchar **strings); + const GLchar *const *strings); bool ValidateDeleteProgramPipelinesEXT(const Context *context, angle::EntryPoint entryPoint, GLsizei n, @@ -1954,6 +1988,8 @@ bool ValidateFramebufferFetchBarrierEXT(const Context *context, angle::EntryPoin // GL_EXT_shader_texture_lod +// GL_EXT_shader_texture_samples + // GL_EXT_shadow_samplers // GL_EXT_tessellation_shader @@ -2058,12 +2094,6 @@ bool ValidateTexBufferRangeEXT(const Context *context, // GL_EXT_texture_shadow_lod // GL_EXT_texture_storage -bool ValidateTexStorage1DEXT(const Context *context, - angle::EntryPoint entryPoint, - GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width); bool ValidateTexStorage2DEXT(const Context *context, angle::EntryPoint entryPoint, TextureType targetPacked, @@ -2277,6 +2307,8 @@ bool ValidateBlitFramebufferNV(const Context *context, GLbitfield mask, GLenum filter); +// GL_NV_pack_subimage + // GL_NV_pixel_buffer_object // GL_NV_polygon_mode @@ -2866,7 +2898,8 @@ bool ValidateGenVertexArraysOES(const Context *context, angle::EntryPoint entryPoint, GLsizei n, const VertexArrayID *arraysPacked); -bool ValidateIsVertexArrayOES(const Context *context, +bool ValidateIsVertexArrayOES(const PrivateState &state, + ErrorSet *errors, angle::EntryPoint entryPoint, VertexArrayID arrayPacked); @@ -2886,6 +2919,17 @@ bool ValidateFramebufferTextureMultiviewOVR(const Context *context, // GL_OVR_multiview2 +// GL_OVR_multiview_multisampled_render_to_texture +bool ValidateFramebufferTextureMultisampleMultiviewOVR(const Context *context, + angle::EntryPoint entryPoint, + GLenum target, + GLenum attachment, + TextureID texturePacked, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews); + // GL_QCOM_framebuffer_foveated bool ValidateFramebufferFoveationConfigQCOM(const Context *context, angle::EntryPoint entryPoint, @@ -2911,7 +2955,7 @@ bool ValidateFramebufferFoveationParametersQCOM(const Context *context, bool ValidateShadingRateQCOM(const PrivateState &state, ErrorSet *errors, angle::EntryPoint entryPoint, - GLenum rate); + ShadingRate ratePacked); // GL_QCOM_texture_foveated bool ValidateTextureFoveationParametersQCOM(const Context *context, diff --git a/src/libEGL/egl_loader_autogen.cpp b/src/libEGL/egl_loader_autogen.cpp index 8019bf7c4b6..79684bdb743 100644 --- a/src/libEGL/egl_loader_autogen.cpp +++ b/src/libEGL/egl_loader_autogen.cpp @@ -87,7 +87,6 @@ PFNEGLPROGRAMCACHERESIZEANGLEPROC l_EGL_ProgramCacheResizeANGLE; PFNEGLQUERYSURFACEPOINTERANGLEPROC l_EGL_QuerySurfacePointerANGLE; PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC l_EGL_CreateStreamProducerD3DTextureANGLE; PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC l_EGL_StreamPostD3DTextureANGLE; -PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC l_EGL_SwapBuffersWithFrameTokenANGLE; PFNEGLGETMSCRATEANGLEPROC l_EGL_GetMscRateANGLE; PFNEGLEXPORTVKIMAGEANGLEPROC l_EGL_ExportVkImageANGLE; PFNEGLWAITUNTILWORKSCHEDULEDANGLEPROC l_EGL_WaitUntilWorkScheduledANGLE; @@ -258,9 +257,6 @@ void LoadLibEGL_EGL(LoadProc loadProc) loadProc("EGL_CreateStreamProducerD3DTextureANGLE")); l_EGL_StreamPostD3DTextureANGLE = reinterpret_cast( loadProc("EGL_StreamPostD3DTextureANGLE")); - l_EGL_SwapBuffersWithFrameTokenANGLE = - reinterpret_cast( - loadProc("EGL_SwapBuffersWithFrameTokenANGLE")); l_EGL_GetMscRateANGLE = reinterpret_cast(loadProc("EGL_GetMscRateANGLE")); l_EGL_ExportVkImageANGLE = diff --git a/src/libEGL/egl_loader_autogen.h b/src/libEGL/egl_loader_autogen.h index d52487fc4bc..7b4a293773d 100644 --- a/src/libEGL/egl_loader_autogen.h +++ b/src/libEGL/egl_loader_autogen.h @@ -91,7 +91,6 @@ #define EGL_QuerySurfacePointerANGLE l_EGL_QuerySurfacePointerANGLE #define EGL_CreateStreamProducerD3DTextureANGLE l_EGL_CreateStreamProducerD3DTextureANGLE #define EGL_StreamPostD3DTextureANGLE l_EGL_StreamPostD3DTextureANGLE -#define EGL_SwapBuffersWithFrameTokenANGLE l_EGL_SwapBuffersWithFrameTokenANGLE #define EGL_GetMscRateANGLE l_EGL_GetMscRateANGLE #define EGL_ExportVkImageANGLE l_EGL_ExportVkImageANGLE #define EGL_WaitUntilWorkScheduledANGLE l_EGL_WaitUntilWorkScheduledANGLE @@ -215,8 +214,6 @@ ANGLE_NO_EXPORT extern PFNEGLQUERYSURFACEPOINTERANGLEPROC l_EGL_QuerySurfacePoin ANGLE_NO_EXPORT extern PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC l_EGL_CreateStreamProducerD3DTextureANGLE; ANGLE_NO_EXPORT extern PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC l_EGL_StreamPostD3DTextureANGLE; -ANGLE_NO_EXPORT extern PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC - l_EGL_SwapBuffersWithFrameTokenANGLE; ANGLE_NO_EXPORT extern PFNEGLGETMSCRATEANGLEPROC l_EGL_GetMscRateANGLE; ANGLE_NO_EXPORT extern PFNEGLEXPORTVKIMAGEANGLEPROC l_EGL_ExportVkImageANGLE; ANGLE_NO_EXPORT extern PFNEGLWAITUNTILWORKSCHEDULEDANGLEPROC l_EGL_WaitUntilWorkScheduledANGLE; @@ -267,7 +264,7 @@ typedef GenericProc(KHRONOS_APIENTRY *LoadProc)(const char *); ANGLE_NO_EXPORT void LoadLibEGL_EGL(LoadProc loadProc); #if defined(__cplusplus) -} // extern "C" +} // extern "C" #endif // defined(__cplusplus) #endif // LIBEGL_EGL_LOADER_AUTOGEN_H_ diff --git a/src/libEGL/libEGL_autogen.cpp b/src/libEGL/libEGL_autogen.cpp index a4169afc4fe..39011965575 100644 --- a/src/libEGL/libEGL_autogen.cpp +++ b/src/libEGL/libEGL_autogen.cpp @@ -629,14 +629,6 @@ EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureANGLE(EGLDisplay dpy, return EGL_StreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list); } -// EGL_ANGLE_swap_with_frame_token -EGLBoolean EGLAPIENTRY eglSwapBuffersWithFrameTokenANGLE(EGLDisplay dpy, - EGLSurface surface, - EGLFrameTokenANGLE frametoken) -{ - EnsureEGLLoaded(); - return EGL_SwapBuffersWithFrameTokenANGLE(dpy, surface, frametoken); -} // EGL_ANGLE_sync_control_rate EGLBoolean EGLAPIENTRY eglGetMscRateANGLE(EGLDisplay dpy, diff --git a/src/libEGL/libEGL_autogen.def b/src/libEGL/libEGL_autogen.def index ceee24e88ea..dfa609a2883 100644 --- a/src/libEGL/libEGL_autogen.def +++ b/src/libEGL/libEGL_autogen.def @@ -127,9 +127,6 @@ EXPORTS eglCreateStreamProducerD3DTextureANGLE eglStreamPostD3DTextureANGLE - ; EGL_ANGLE_swap_with_frame_token - eglSwapBuffersWithFrameTokenANGLE - ; EGL_ANGLE_sync_control_rate eglGetMscRateANGLE diff --git a/src/libEGL/libEGL_vulkan_secondaries_autogen.def b/src/libEGL/libEGL_vulkan_secondaries_autogen.def index b45759c88ac..8b13b53f82b 100644 --- a/src/libEGL/libEGL_vulkan_secondaries_autogen.def +++ b/src/libEGL/libEGL_vulkan_secondaries_autogen.def @@ -127,9 +127,6 @@ EXPORTS eglCreateStreamProducerD3DTextureANGLE eglStreamPostD3DTextureANGLE - ; EGL_ANGLE_swap_with_frame_token - eglSwapBuffersWithFrameTokenANGLE - ; EGL_ANGLE_sync_control_rate eglGetMscRateANGLE diff --git a/src/libGLESv2.gni b/src/libGLESv2.gni index ed874b4bd4a..ce5ab0ba892 100644 --- a/src/libGLESv2.gni +++ b/src/libGLESv2.gni @@ -19,7 +19,6 @@ libangle_common_headers = [ "src/common/PackedGLEnums_autogen.h", "src/common/PackedCLEnums_autogen.h", "src/common/PoolAlloc.h", - "src/common/RingBufferAllocator.h", "src/common/SimpleMutex.h", "src/common/SynchronizedValue.h", "src/common/WorkerThread.h", @@ -60,10 +59,12 @@ libangle_common_headers = [ "src/common/platform.h", "src/common/platform_helpers.h", "src/common/span.h", + "src/common/span_util.h", "src/common/string_utils.h", "src/common/system_utils.h", "src/common/tls.h", "src/common/uniform_type_info_autogen.h", + "src/common/unsafe_buffers.h", "src/common/utilities.h", "src/common/vector_utils.h", "src/libANGLE/CLBitField.h", @@ -76,7 +77,6 @@ libangle_common_sources = libangle_common_headers + [ "src/common/PackedEnums.cpp", "src/common/PackedGLEnums_autogen.cpp", "src/common/PoolAlloc.cpp", - "src/common/RingBufferAllocator.cpp", "src/common/SimpleMutex.cpp", "src/common/WorkerThread.cpp", "src/common/aligned_memory.cpp", @@ -243,6 +243,7 @@ libangle_includes = [ "include/platform/autogen/FeaturesGL_autogen.h", "include/platform/autogen/FeaturesMtl_autogen.h", "include/platform/autogen/FeaturesVk_autogen.h", + "include/platform/autogen/FeaturesWgpu_autogen.h", "include/platform/autogen/FrontendFeatures_autogen.h", "include/platform/PlatformMethods.h", "include/vulkan/vulkan_fuchsia_ext.h", @@ -319,7 +320,6 @@ libangle_headers = [ "src/libANGLE/Uniform.h", "src/libANGLE/VaryingPacking.h", "src/libANGLE/Version.h", - "src/libANGLE/Version.inc", "src/libANGLE/VertexArray.h", "src/libANGLE/VertexAttribute.h", "src/libANGLE/VertexAttribute.inc", @@ -328,7 +328,6 @@ libangle_headers = [ "src/libANGLE/cl_types.h", "src/libANGLE/context_private_call.inl.h", "src/libANGLE/context_private_call_autogen.h", - "src/libANGLE/entry_points_utils.cpp", "src/libANGLE/entry_points_utils.h", "src/libANGLE/features.h", "src/libANGLE/formatutils.h", @@ -588,6 +587,7 @@ libangle_mac_sources = [ "src/libANGLE/renderer/driver_utils_mac.mm" ] # The frame capture headers are always visible to libANGLE. libangle_sources += [ + "src/common/frame_capture_binary_data.h", "src/common/frame_capture_utils.h", "src/common/frame_capture_utils_autogen.h", "src/common/gl_enum_utils.h", @@ -633,7 +633,7 @@ if (angle_enable_cl) { ] } -libglesv2_sources = [ +libglesv2_entry_point_sources = [ "src/libGLESv2/egl_context_lock_autogen.h", "src/libGLESv2/egl_context_lock_impl.h", "src/libGLESv2/egl_ext_stubs.cpp", @@ -659,10 +659,11 @@ libglesv2_sources = [ "src/libGLESv2/entry_points_gles_ext_autogen.h", "src/libGLESv2/global_state.cpp", "src/libGLESv2/global_state.h", - "src/libGLESv2/libGLESv2_autogen.cpp", "src/libGLESv2/resource.h", ] +libglesv2_sources = [ "src/libGLESv2/libGLESv2_autogen.cpp" ] + libglesv2_cl_sources = [ "src/libGLESv2/cl_dispatch_table.cpp", "src/libGLESv2/cl_dispatch_table.h", diff --git a/src/libGLESv2/cl_stubs.cpp b/src/libGLESv2/cl_stubs.cpp index 851fb914e1c..c8afac2f0aa 100644 --- a/src/libGLESv2/cl_stubs.cpp +++ b/src/libGLESv2/cl_stubs.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // cl_stubs.cpp: Stubs for CL entry points. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "libANGLE/cl_utils.h" #include "libGLESv2/cl_stubs_autogen.h" @@ -75,6 +80,18 @@ cl_int IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *platforms, cl_u CL_RETURN_ERROR((Platform::GetPlatformIDs(num_entries, platforms, num_platforms))); } +void *IcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, const char *func_name) +{ + WARN_NOT_SUPPORTED(IcdGetFunctionAddressForPlatformKHR); + return 0; +} + +cl_int IcdSetPlatformDispatchDataKHR(cl_platform_id platform, void *dispatch_data) +{ + WARN_NOT_SUPPORTED(IcdSetPlatformDispatchDataKHR); + return CL_INVALID_OPERATION; +} + cl_int GetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms) { CL_RETURN_ERROR(Platform::GetPlatformIDs(num_entries, platforms, num_platforms)); @@ -750,9 +767,9 @@ cl_int EnqueueReadBufferRect(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueReadBufferRect( - buffer, blocking_read, cl::MemOffsets{buffer_origin[0], buffer_origin[1], buffer_origin[2]}, - cl::MemOffsets{host_origin[0], host_origin[1], host_origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, buffer_row_pitch, buffer_slice_pitch, + buffer, blocking_read, cl::Offset{buffer_origin[0], buffer_origin[1], buffer_origin[2]}, + cl::Offset{host_origin[0], host_origin[1], host_origin[2]}, + cl::Extents{region[0], region[1], region[2]}, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event)); } @@ -787,10 +804,9 @@ cl_int EnqueueWriteBufferRect(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueWriteBufferRect( - buffer, blocking_write, - cl::MemOffsets{buffer_origin[0], buffer_origin[1], buffer_origin[2]}, - cl::MemOffsets{host_origin[0], host_origin[1], host_origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, buffer_row_pitch, buffer_slice_pitch, + buffer, blocking_write, cl::Offset{buffer_origin[0], buffer_origin[1], buffer_origin[2]}, + cl::Offset{host_origin[0], host_origin[1], host_origin[2]}, + cl::Extents{region[0], region[1], region[2]}, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event)); } @@ -839,10 +855,10 @@ cl_int EnqueueCopyBufferRect(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueCopyBufferRect( - src_buffer, dst_buffer, cl::MemOffsets{src_origin[0], src_origin[1], src_origin[2]}, - cl::MemOffsets{dst_origin[0], dst_origin[1], dst_origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, src_row_pitch, src_slice_pitch, - dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event)); + src_buffer, dst_buffer, cl::Offset{src_origin[0], src_origin[1], src_origin[2]}, + cl::Offset{dst_origin[0], dst_origin[1], dst_origin[2]}, + cl::Extents{region[0], region[1], region[2]}, src_row_pitch, src_slice_pitch, dst_row_pitch, + dst_slice_pitch, num_events_in_wait_list, event_wait_list, event)); } cl_int EnqueueReadImage(cl_command_queue command_queue, @@ -858,8 +874,8 @@ cl_int EnqueueReadImage(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueReadImage( - image, blocking_read, cl::MemOffsets{origin[0], origin[1], origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, row_pitch, slice_pitch, ptr, + image, blocking_read, cl::Offset{origin[0], origin[1], origin[2]}, + cl::Extents{region[0], region[1], region[2]}, row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event)); } @@ -876,8 +892,8 @@ cl_int EnqueueWriteImage(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueWriteImage( - image, blocking_write, cl::MemOffsets{origin[0], origin[1], origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, input_row_pitch, input_slice_pitch, ptr, + image, blocking_write, cl::Offset{origin[0], origin[1], origin[2]}, + cl::Extents{region[0], region[1], region[2]}, input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event)); } @@ -891,8 +907,8 @@ cl_int EnqueueFillImage(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueFillImage( - image, fill_color, cl::MemOffsets{origin[0], origin[1], origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, num_events_in_wait_list, event_wait_list, + image, fill_color, cl::Offset{origin[0], origin[1], origin[2]}, + cl::Extents{region[0], region[1], region[2]}, num_events_in_wait_list, event_wait_list, event)); } @@ -907,9 +923,9 @@ cl_int EnqueueCopyImage(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueCopyImage( - src_image, dst_image, cl::MemOffsets{src_origin[0], src_origin[1], src_origin[2]}, - cl::MemOffsets{dst_origin[0], dst_origin[1], dst_origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, num_events_in_wait_list, event_wait_list, + src_image, dst_image, cl::Offset{src_origin[0], src_origin[1], src_origin[2]}, + cl::Offset{dst_origin[0], dst_origin[1], dst_origin[2]}, + cl::Extents{region[0], region[1], region[2]}, num_events_in_wait_list, event_wait_list, event)); } @@ -924,8 +940,8 @@ cl_int EnqueueCopyImageToBuffer(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueCopyImageToBuffer( - src_image, dst_buffer, cl::MemOffsets{src_origin[0], src_origin[1], src_origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, dst_offset, num_events_in_wait_list, + src_image, dst_buffer, cl::Offset{src_origin[0], src_origin[1], src_origin[2]}, + cl::Extents{region[0], region[1], region[2]}, dst_offset, num_events_in_wait_list, event_wait_list, event)); } @@ -940,9 +956,8 @@ cl_int EnqueueCopyBufferToImage(cl_command_queue command_queue, cl_event *event) { CL_RETURN_ERROR(command_queue->cast().enqueueCopyBufferToImage( - src_buffer, dst_image, src_offset, - cl::MemOffsets{dst_origin[0], dst_origin[1], dst_origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, num_events_in_wait_list, event_wait_list, + src_buffer, dst_image, src_offset, cl::Offset{dst_origin[0], dst_origin[1], dst_origin[2]}, + cl::Extents{region[0], region[1], region[2]}, num_events_in_wait_list, event_wait_list, event)); } @@ -973,11 +988,11 @@ void *EnqueueMapImage(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_RETURN_PTR( - ptrOut, command_queue->cast().enqueueMapImage( - image, blocking_map, map_flags, cl::MemOffsets{origin[0], origin[1], origin[2]}, - cl::Coordinate{region[0], region[1], region[2]}, image_row_pitch, - image_slice_pitch, num_events_in_wait_list, event_wait_list, event, ptrOut)); + CL_RETURN_PTR(ptrOut, + command_queue->cast().enqueueMapImage( + image, blocking_map, map_flags, cl::Offset{origin[0], origin[1], origin[2]}, + cl::Extents{region[0], region[1], region[2]}, image_row_pitch, + image_slice_pitch, num_events_in_wait_list, event_wait_list, event, ptrOut)); } cl_int EnqueueUnmapMemObject(cl_command_queue command_queue, @@ -1130,6 +1145,39 @@ cl_int EnqueueSVMMigrateMem(cl_command_queue command_queue, return CL_INVALID_OPERATION; } +cl_int EnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) +{ + CL_RETURN_ERROR(command_queue->cast().enqueueAcquireExternalMemObjectsKHR( + num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, event)); +} + +cl_int EnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) +{ + CL_RETURN_ERROR(command_queue->cast().enqueueReleaseExternalMemObjectsKHR( + num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, event)); +} + +cl_mem ImportMemoryARM(cl_context context, + MemFlags flags, + const cl_import_properties_arm *properties, + void *memory, + size_t size) +{ + Memory::PropArray convertedProperties = Context::ConvertArmMemPropToMemProp(properties, memory); + CL_RETURN_OBJ( + context->cast().createBuffer(convertedProperties.data(), flags, size, nullptr)); +} + void *GetExtensionFunctionAddressForPlatform(cl_platform_id platform, const char *func_name) { return GetExtensionFunctionAddress(func_name); diff --git a/src/libGLESv2/cl_stubs_autogen.h b/src/libGLESv2/cl_stubs_autogen.h index 264bf678bd6..d9132a761bb 100644 --- a/src/libGLESv2/cl_stubs_autogen.h +++ b/src/libGLESv2/cl_stubs_autogen.h @@ -15,6 +15,25 @@ namespace cl { cl_int IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms); +void *IcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, const char *func_name); +cl_int IcdSetPlatformDispatchDataKHR(cl_platform_id platform, void *dispatch_data); +cl_int EnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event); +cl_int EnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event); +cl_mem ImportMemoryARM(cl_context context, + MemFlags flagsPacked, + const cl_import_properties_arm *properties, + void *memory, + size_t size); cl_int GetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms); cl_int GetPlatformInfo(cl_platform_id platform, PlatformInfo param_namePacked, diff --git a/src/libGLESv2/egl_context_lock_autogen.h b/src/libGLESv2/egl_context_lock_autogen.h index a1f445b9747..6d627507d24 100644 --- a/src/libGLESv2/egl_context_lock_autogen.h +++ b/src/libGLESv2/egl_context_lock_autogen.h @@ -189,10 +189,6 @@ ScopedContextMutexLock GetContextLock_CreateStreamProducerD3DTextureANGLE(Thread ScopedContextMutexLock GetContextLock_StreamPostD3DTextureANGLE(Thread *thread, egl::Display *dpyPacked); -// EGL_ANGLE_swap_with_frame_token -ScopedContextMutexLock GetContextLock_SwapBuffersWithFrameTokenANGLE(Thread *thread, - egl::Display *dpyPacked); - // EGL_ANGLE_sync_control_rate ScopedContextMutexLock GetContextLock_GetMscRateANGLE(Thread *thread, egl::Display *dpyPacked); diff --git a/src/libGLESv2/egl_context_lock_impl.h b/src/libGLESv2/egl_context_lock_impl.h index 44d119d90f4..705df0e5415 100644 --- a/src/libGLESv2/egl_context_lock_impl.h +++ b/src/libGLESv2/egl_context_lock_impl.h @@ -144,8 +144,10 @@ ANGLE_INLINE ScopedContextMutexLock GetContextLock_QuerySurface(Thread *thread, { switch (attribute) { - // EGL_BUFFER_AGE_EXT uses current Context and therefore requires the lock. + // EGL_BUFFER_AGE_EXT and EGL_SURFACE_COMPRESSION_EXT uses current Context + // and therefore requires the lock. case EGL_BUFFER_AGE_EXT: + case EGL_SURFACE_COMPRESSION_EXT: return TryLockCurrentContext(thread); // Other attributes are not using Context, therefore lock is not required. default: @@ -513,13 +515,6 @@ GetContextLock_StreamPostD3DTextureANGLE(Thread *thread, egl::Display *dpyPacked return {}; } -// EGL_ANGLE_swap_with_frame_token -ANGLE_INLINE ScopedContextMutexLock -GetContextLock_SwapBuffersWithFrameTokenANGLE(Thread *thread, egl::Display *dpyPacked) -{ - return TryLockCurrentContext(thread); -} - // EGL_ANGLE_sync_control_rate ANGLE_INLINE ScopedContextMutexLock GetContextLock_GetMscRateANGLE(Thread *thread, egl::Display *dpyPacked) @@ -682,7 +677,17 @@ ANGLE_INLINE ScopedContextMutexLock GetContextLock_QuerySurface64KHR(Thread *thr egl::Display *dpyPacked, EGLint attribute) { - return {}; + switch (attribute) + { + // EGL_BUFFER_AGE_EXT and EGL_SURFACE_COMPRESSION_EXT uses current Context + // and therefore requires the lock. + case EGL_BUFFER_AGE_EXT: + case EGL_SURFACE_COMPRESSION_EXT: + return TryLockCurrentContext(thread); + // Other attributes are not using Context, therefore lock is not required. + default: + return {}; + } } ANGLE_INLINE ScopedContextMutexLock GetContextLock_UnlockSurfaceKHR(Thread *thread, diff --git a/src/libGLESv2/egl_ext_stubs.cpp b/src/libGLESv2/egl_ext_stubs.cpp index a6aeae97efc..1071199a699 100644 --- a/src/libGLESv2/egl_ext_stubs.cpp +++ b/src/libGLESv2/egl_ext_stubs.cpp @@ -865,24 +865,6 @@ const char *QueryStringiANGLE(Thread *thread, Display *display, EGLint name, EGL return display->queryStringi(name, index); } -EGLBoolean SwapBuffersWithFrameTokenANGLE(Thread *thread, - Display *display, - SurfaceID surfaceID, - EGLFrameTokenANGLE frametoken) -{ - Surface *eglSurface = display->getSurface(surfaceID); - - ANGLE_EGL_TRY_PREPARE_FOR_CALL_RETURN(thread, display->prepareForCall(), - "eglSwapBuffersWithFrameTokenANGLE", - GetDisplayIfValid(display), EGL_FALSE); - ANGLE_EGL_TRY_RETURN(thread, eglSurface->swapWithFrameToken(thread->getContext(), frametoken), - "eglSwapBuffersWithFrameTokenANGLE", GetDisplayIfValid(display), - EGL_FALSE); - - thread->setSuccess(); - return EGL_TRUE; -} - void ReleaseHighPowerGPUANGLE(Thread *thread, Display *display, gl::ContextID contextID) { gl::Context *context = display->getContext(contextID); diff --git a/src/libGLESv2/egl_ext_stubs_autogen.h b/src/libGLESv2/egl_ext_stubs_autogen.h index cbd9a15c189..8d6d1e57983 100644 --- a/src/libGLESv2/egl_ext_stubs_autogen.h +++ b/src/libGLESv2/egl_ext_stubs_autogen.h @@ -257,10 +257,6 @@ void AcquireExternalContextANGLE(Thread *thread, egl::Display *dpyPacked, SurfaceID drawAndReadPacked); void ReleaseExternalContextANGLE(Thread *thread, egl::Display *dpyPacked); -EGLBoolean SwapBuffersWithFrameTokenANGLE(Thread *thread, - egl::Display *dpyPacked, - SurfaceID surfacePacked, - EGLFrameTokenANGLE frametoken); void LockVulkanQueueANGLE(Thread *thread, egl::Display *dpyPacked); void UnlockVulkanQueueANGLE(Thread *thread, egl::Display *dpyPacked); EGLBoolean PrepareSwapBuffersANGLE(Thread *thread, diff --git a/src/libGLESv2/egl_stubs.cpp b/src/libGLESv2/egl_stubs.cpp index 95d5aa12e5c..8edb333ee26 100644 --- a/src/libGLESv2/egl_stubs.cpp +++ b/src/libGLESv2/egl_stubs.cpp @@ -6,6 +6,10 @@ // egl_stubs.cpp: Stubs for EGL entry points. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libGLESv2/egl_stubs_autogen.h" #include "common/angle_version_info.h" @@ -625,8 +629,10 @@ EGLBoolean QuerySurface(Thread *thread, const gl::Context *context; switch (attribute) { - // EGL_BUFFER_AGE_EXT uses Context, so lock was taken in GetContextLock_QuerySurface(). + // EGL_BUFFER_AGE_EXT and EGL_SURFACE_COMPRESSION_EXT uses Context, + // so lock was taken in GetContextLock_QuerySurface(). case EGL_BUFFER_AGE_EXT: + case EGL_SURFACE_COMPRESSION_EXT: context = thread->getContext(); break; // Other attributes are not using Context, pass nullptr to be explicit about that. diff --git a/src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp b/src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp index 75583a64402..e76351479e2 100644 --- a/src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp +++ b/src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp @@ -150,7 +150,6 @@ const ProcEntry g_procTable[] = { {"eglSurfaceAttrib", P(EGL_SurfaceAttrib)}, {"eglSwapBuffers", P(EGL_SwapBuffers)}, {"eglSwapBuffersWithDamageKHR", P(EGL_SwapBuffersWithDamageKHR)}, - {"eglSwapBuffersWithFrameTokenANGLE", P(EGL_SwapBuffersWithFrameTokenANGLE)}, {"eglSwapInterval", P(EGL_SwapInterval)}, {"eglTerminate", P(EGL_Terminate)}, {"eglUnlockSurfaceKHR", P(EGL_UnlockSurfaceKHR)}, @@ -361,7 +360,6 @@ const ProcEntry g_procTable[] = { {"glEGLImageTargetRenderbufferStorageOES", P(GL_EGLImageTargetRenderbufferStorageOES)}, {"glEGLImageTargetTexStorageEXT", P(GL_EGLImageTargetTexStorageEXT)}, {"glEGLImageTargetTexture2DOES", P(GL_EGLImageTargetTexture2DOES)}, - {"glEGLImageTargetTextureStorageEXT", P(GL_EGLImageTargetTextureStorageEXT)}, {"glEnable", P(GL_Enable)}, {"glEnableClientState", P(GL_EnableClientState)}, {"glEnableVertexAttribArray", P(GL_EnableVertexAttribArray)}, @@ -397,6 +395,7 @@ const ProcEntry g_procTable[] = { {"glFramebufferPixelLocalStorageRestoreANGLE", P(GL_FramebufferPixelLocalStorageRestoreANGLE)}, {"glFramebufferRenderbuffer", P(GL_FramebufferRenderbuffer)}, {"glFramebufferRenderbufferOES", P(GL_FramebufferRenderbufferOES)}, + {"glFramebufferShadingRateEXT", P(GL_FramebufferShadingRateEXT)}, {"glFramebufferTexture", P(GL_FramebufferTexture)}, {"glFramebufferTexture2D", P(GL_FramebufferTexture2D)}, {"glFramebufferTexture2DMultisampleEXT", P(GL_FramebufferTexture2DMultisampleEXT)}, @@ -404,6 +403,7 @@ const ProcEntry g_procTable[] = { {"glFramebufferTexture3DOES", P(GL_FramebufferTexture3DOES)}, {"glFramebufferTextureEXT", P(GL_FramebufferTextureEXT)}, {"glFramebufferTextureLayer", P(GL_FramebufferTextureLayer)}, + {"glFramebufferTextureMultisampleMultiviewOVR", P(GL_FramebufferTextureMultisampleMultiviewOVR)}, {"glFramebufferTextureMultiviewOVR", P(GL_FramebufferTextureMultiviewOVR)}, {"glFramebufferTextureOES", P(GL_FramebufferTextureOES)}, {"glFramebufferTexturePixelLocalStorageANGLE", P(GL_FramebufferTexturePixelLocalStorageANGLE)}, @@ -460,6 +460,7 @@ const ProcEntry g_procTable[] = { {"glGetFloatvRobustANGLE", P(GL_GetFloatvRobustANGLE)}, {"glGetFragDataIndexEXT", P(GL_GetFragDataIndexEXT)}, {"glGetFragDataLocation", P(GL_GetFragDataLocation)}, + {"glGetFragmentShadingRatesEXT", P(GL_GetFragmentShadingRatesEXT)}, {"glGetFramebufferAttachmentParameteriv", P(GL_GetFramebufferAttachmentParameteriv)}, {"glGetFramebufferAttachmentParameterivOES", P(GL_GetFramebufferAttachmentParameterivOES)}, {"glGetFramebufferAttachmentParameterivRobustANGLE", P(GL_GetFramebufferAttachmentParameterivRobustANGLE)}, @@ -690,17 +691,18 @@ const ProcEntry g_procTable[] = { {"glMultMatrixf", P(GL_MultMatrixf)}, {"glMultMatrixx", P(GL_MultMatrixx)}, {"glMultiDrawArraysANGLE", P(GL_MultiDrawArraysANGLE)}, + {"glMultiDrawArraysEXT", P(GL_MultiDrawArraysEXT)}, {"glMultiDrawArraysIndirectEXT", P(GL_MultiDrawArraysIndirectEXT)}, {"glMultiDrawArraysInstancedANGLE", P(GL_MultiDrawArraysInstancedANGLE)}, {"glMultiDrawArraysInstancedBaseInstanceANGLE", P(GL_MultiDrawArraysInstancedBaseInstanceANGLE)}, {"glMultiDrawElementsANGLE", P(GL_MultiDrawElementsANGLE)}, {"glMultiDrawElementsBaseVertexEXT", P(GL_MultiDrawElementsBaseVertexEXT)}, + {"glMultiDrawElementsEXT", P(GL_MultiDrawElementsEXT)}, {"glMultiDrawElementsIndirectEXT", P(GL_MultiDrawElementsIndirectEXT)}, {"glMultiDrawElementsInstancedANGLE", P(GL_MultiDrawElementsInstancedANGLE)}, {"glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE", P(GL_MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE)}, {"glMultiTexCoord4f", P(GL_MultiTexCoord4f)}, {"glMultiTexCoord4x", P(GL_MultiTexCoord4x)}, - {"glNamedBufferStorageExternalEXT", P(GL_NamedBufferStorageExternalEXT)}, {"glNormal3f", P(GL_Normal3f)}, {"glNormal3x", P(GL_Normal3x)}, {"glNormalPointer", P(GL_NormalPointer)}, @@ -857,6 +859,8 @@ const ProcEntry g_procTable[] = { {"glShadeModel", P(GL_ShadeModel)}, {"glShaderBinary", P(GL_ShaderBinary)}, {"glShaderSource", P(GL_ShaderSource)}, + {"glShadingRateCombinerOpsEXT", P(GL_ShadingRateCombinerOpsEXT)}, + {"glShadingRateEXT", P(GL_ShadingRateEXT)}, {"glShadingRateQCOM", P(GL_ShadingRateQCOM)}, {"glSignalSemaphoreEXT", P(GL_SignalSemaphoreEXT)}, {"glStartTilingQCOM", P(GL_StartTilingQCOM)}, @@ -908,7 +912,6 @@ const ProcEntry g_procTable[] = { {"glTexParameterivRobustANGLE", P(GL_TexParameterivRobustANGLE)}, {"glTexParameterx", P(GL_TexParameterx)}, {"glTexParameterxv", P(GL_TexParameterxv)}, - {"glTexStorage1DEXT", P(GL_TexStorage1DEXT)}, {"glTexStorage2D", P(GL_TexStorage2D)}, {"glTexStorage2DEXT", P(GL_TexStorage2DEXT)}, {"glTexStorage2DMultisample", P(GL_TexStorage2DMultisample)}, @@ -1010,6 +1013,11 @@ const ProcEntry g_procTable[] = { __eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname) { + if (procname == nullptr) + { + return nullptr; + } + const ProcEntry *entry = std::lower_bound(std::begin(g_procTable), std::end(g_procTable), procname, CompareProc); diff --git a/src/libGLESv2/entry_points_cl_autogen.cpp b/src/libGLESv2/entry_points_cl_autogen.cpp index 6b44bb34e84..741f9490f82 100644 --- a/src/libGLESv2/entry_points_cl_autogen.cpp +++ b/src/libGLESv2/entry_points_cl_autogen.cpp @@ -26,9 +26,10 @@ cl_int CL_API_CALL clGetPlatformIDs(cl_uint num_entries, { InitBackEnds(false); - CL_EVENT(GetPlatformIDs, - "num_entries = %u, platforms = 0x%016" PRIxPTR ", num_platforms = 0x%016" PRIxPTR "", - num_entries, (uintptr_t)platforms, (uintptr_t)num_platforms); + ANGLE_UNSAFE_TODO(CL_EVENT(GetPlatformIDs, + "num_entries = %u, platforms = 0x%016" PRIxPTR + ", num_platforms = 0x%016" PRIxPTR "", + num_entries, (uintptr_t)platforms, (uintptr_t)num_platforms)); ANGLE_CL_VALIDATE_ERROR(GetPlatformIDs, num_entries, platforms, num_platforms); @@ -46,12 +47,13 @@ cl_int CL_API_CALL clGetPlatformInfo(cl_platform_id platform, { InitBackEnds(false); - CL_EVENT(GetPlatformInfo, - "platform = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)platform, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetPlatformInfo, + "platform = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)platform, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); PlatformInfo param_namePacked = PackParam(param_name); @@ -74,12 +76,12 @@ cl_int CL_API_CALL clGetDeviceIDs(cl_platform_id platform, { InitBackEnds(false); - CL_EVENT(GetDeviceIDs, - "platform = 0x%016" PRIxPTR - ", device_type = %llu, num_entries = %u, devices = 0x%016" PRIxPTR - ", num_devices = 0x%016" PRIxPTR "", - (uintptr_t)platform, static_cast(device_type), num_entries, - (uintptr_t)devices, (uintptr_t)num_devices); + ANGLE_UNSAFE_TODO(CL_EVENT(GetDeviceIDs, + "platform = 0x%016" PRIxPTR + ", device_type = %llu, num_entries = %u, devices = 0x%016" PRIxPTR + ", num_devices = 0x%016" PRIxPTR "", + (uintptr_t)platform, static_cast(device_type), + num_entries, (uintptr_t)devices, (uintptr_t)num_devices)); DeviceType device_typePacked = PackParam(device_type); @@ -100,12 +102,13 @@ cl_int CL_API_CALL clGetDeviceInfo(cl_device_id device, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetDeviceInfo, - "device = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)device, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetDeviceInfo, + "device = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)device, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); DeviceInfo param_namePacked = PackParam(param_name); @@ -132,12 +135,13 @@ cl_context CL_API_CALL clCreateContext(const cl_context_properties *properties, { InitBackEnds(false); - CL_EVENT(CreateContext, - "properties = 0x%016" PRIxPTR ", num_devices = %u, devices = 0x%016" PRIxPTR - ", pfn_notify = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)properties, num_devices, (uintptr_t)devices, (uintptr_t)pfn_notify, - (uintptr_t)user_data, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(CreateContext, + "properties = 0x%016" PRIxPTR ", num_devices = %u, devices = 0x%016" PRIxPTR + ", pfn_notify = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)properties, num_devices, (uintptr_t)devices, (uintptr_t)pfn_notify, + (uintptr_t)user_data, (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateContext, properties, num_devices, devices, pfn_notify, user_data); @@ -167,11 +171,12 @@ clCreateContextFromType(const cl_context_properties *properties, { InitBackEnds(false); - CL_EVENT(CreateContextFromType, - "properties = 0x%016" PRIxPTR ", device_type = %llu, pfn_notify = 0x%016" PRIxPTR - ", user_data = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)properties, static_cast(device_type), - (uintptr_t)pfn_notify, (uintptr_t)user_data, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(CreateContextFromType, + "properties = 0x%016" PRIxPTR ", device_type = %llu, pfn_notify = 0x%016" PRIxPTR + ", user_data = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)properties, static_cast(device_type), + (uintptr_t)pfn_notify, (uintptr_t)user_data, (uintptr_t)errcode_ret)); DeviceType device_typePacked = PackParam(device_type); @@ -193,7 +198,7 @@ clCreateContextFromType(const cl_context_properties *properties, cl_int CL_API_CALL clRetainContext(cl_context context) { - CL_EVENT(RetainContext, "context = 0x%016" PRIxPTR "", (uintptr_t)context); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainContext, "context = 0x%016" PRIxPTR "", (uintptr_t)context)); ANGLE_CL_VALIDATE_ERROR(RetainContext, context); @@ -205,7 +210,7 @@ cl_int CL_API_CALL clRetainContext(cl_context context) cl_int CL_API_CALL clReleaseContext(cl_context context) { - CL_EVENT(ReleaseContext, "context = 0x%016" PRIxPTR "", (uintptr_t)context); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseContext, "context = 0x%016" PRIxPTR "", (uintptr_t)context)); ANGLE_CL_VALIDATE_ERROR(ReleaseContext, context); @@ -221,12 +226,13 @@ cl_int CL_API_CALL clGetContextInfo(cl_context context, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetContextInfo, - "context = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetContextInfo, + "context = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); ContextInfo param_namePacked = PackParam(param_name); @@ -243,7 +249,8 @@ cl_int CL_API_CALL clGetContextInfo(cl_context context, cl_int CL_API_CALL clRetainCommandQueue(cl_command_queue command_queue) { - CL_EVENT(RetainCommandQueue, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainCommandQueue, "command_queue = 0x%016" PRIxPTR "", + (uintptr_t)command_queue)); ANGLE_CL_VALIDATE_ERROR(RetainCommandQueue, command_queue); @@ -255,7 +262,8 @@ cl_int CL_API_CALL clRetainCommandQueue(cl_command_queue command_queue) cl_int CL_API_CALL clReleaseCommandQueue(cl_command_queue command_queue) { - CL_EVENT(ReleaseCommandQueue, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseCommandQueue, "command_queue = 0x%016" PRIxPTR "", + (uintptr_t)command_queue)); ANGLE_CL_VALIDATE_ERROR(ReleaseCommandQueue, command_queue); @@ -271,12 +279,13 @@ cl_int CL_API_CALL clGetCommandQueueInfo(cl_command_queue command_queue, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetCommandQueueInfo, - "command_queue = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetCommandQueueInfo, + "command_queue = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); CommandQueueInfo param_namePacked = PackParam(param_name); @@ -297,11 +306,12 @@ cl_mem CL_API_CALL clCreateBuffer(cl_context context, void *host_ptr, cl_int *errcode_ret) { - CL_EVENT(CreateBuffer, - "context = 0x%016" PRIxPTR ", flags = %llu, size = %zu, host_ptr = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, static_cast(flags), size, (uintptr_t)host_ptr, - (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateBuffer, + "context = 0x%016" PRIxPTR + ", flags = %llu, size = %zu, host_ptr = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, static_cast(flags), size, + (uintptr_t)host_ptr, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -321,7 +331,7 @@ cl_mem CL_API_CALL clCreateBuffer(cl_context context, cl_int CL_API_CALL clRetainMemObject(cl_mem memobj) { - CL_EVENT(RetainMemObject, "memobj = 0x%016" PRIxPTR "", (uintptr_t)memobj); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainMemObject, "memobj = 0x%016" PRIxPTR "", (uintptr_t)memobj)); ANGLE_CL_VALIDATE_ERROR(RetainMemObject, memobj); @@ -333,7 +343,7 @@ cl_int CL_API_CALL clRetainMemObject(cl_mem memobj) cl_int CL_API_CALL clReleaseMemObject(cl_mem memobj) { - CL_EVENT(ReleaseMemObject, "memobj = 0x%016" PRIxPTR "", (uintptr_t)memobj); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseMemObject, "memobj = 0x%016" PRIxPTR "", (uintptr_t)memobj)); ANGLE_CL_VALIDATE_ERROR(ReleaseMemObject, memobj); @@ -350,12 +360,13 @@ cl_int CL_API_CALL clGetSupportedImageFormats(cl_context context, cl_image_format *image_formats, cl_uint *num_image_formats) { - CL_EVENT(GetSupportedImageFormats, - "context = 0x%016" PRIxPTR - ", flags = %llu, image_type = %u, num_entries = %u, image_formats = 0x%016" PRIxPTR - ", num_image_formats = 0x%016" PRIxPTR "", - (uintptr_t)context, static_cast(flags), image_type, num_entries, - (uintptr_t)image_formats, (uintptr_t)num_image_formats); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetSupportedImageFormats, + "context = 0x%016" PRIxPTR + ", flags = %llu, image_type = %u, num_entries = %u, image_formats = 0x%016" PRIxPTR + ", num_image_formats = 0x%016" PRIxPTR "", + (uintptr_t)context, static_cast(flags), image_type, + num_entries, (uintptr_t)image_formats, (uintptr_t)num_image_formats)); MemFlags flagsPacked = PackParam(flags); MemObjectType image_typePacked = PackParam(image_type); @@ -377,12 +388,13 @@ cl_int CL_API_CALL clGetMemObjectInfo(cl_mem memobj, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetMemObjectInfo, - "memobj = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)memobj, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetMemObjectInfo, + "memobj = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)memobj, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); MemInfo param_namePacked = PackParam(param_name); @@ -403,12 +415,13 @@ cl_int CL_API_CALL clGetImageInfo(cl_mem image, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetImageInfo, - "image = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)image, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetImageInfo, + "image = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)image, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); ImageInfo param_namePacked = PackParam(param_name); @@ -425,7 +438,7 @@ cl_int CL_API_CALL clGetImageInfo(cl_mem image, cl_int CL_API_CALL clRetainSampler(cl_sampler sampler) { - CL_EVENT(RetainSampler, "sampler = 0x%016" PRIxPTR "", (uintptr_t)sampler); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainSampler, "sampler = 0x%016" PRIxPTR "", (uintptr_t)sampler)); ANGLE_CL_VALIDATE_ERROR(RetainSampler, sampler); @@ -437,7 +450,7 @@ cl_int CL_API_CALL clRetainSampler(cl_sampler sampler) cl_int CL_API_CALL clReleaseSampler(cl_sampler sampler) { - CL_EVENT(ReleaseSampler, "sampler = 0x%016" PRIxPTR "", (uintptr_t)sampler); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseSampler, "sampler = 0x%016" PRIxPTR "", (uintptr_t)sampler)); ANGLE_CL_VALIDATE_ERROR(ReleaseSampler, sampler); @@ -453,12 +466,13 @@ cl_int CL_API_CALL clGetSamplerInfo(cl_sampler sampler, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetSamplerInfo, - "sampler = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)sampler, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetSamplerInfo, + "sampler = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)sampler, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); SamplerInfo param_namePacked = PackParam(param_name); @@ -479,11 +493,11 @@ cl_program CL_API_CALL clCreateProgramWithSource(cl_context context, const size_t *lengths, cl_int *errcode_ret) { - CL_EVENT(CreateProgramWithSource, - "context = 0x%016" PRIxPTR ", count = %u, strings = 0x%016" PRIxPTR - ", lengths = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, count, (uintptr_t)strings, (uintptr_t)lengths, - (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateProgramWithSource, + "context = 0x%016" PRIxPTR ", count = %u, strings = 0x%016" PRIxPTR + ", lengths = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, count, (uintptr_t)strings, (uintptr_t)lengths, + (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateProgramWithSource, context, count, strings, lengths); @@ -508,12 +522,13 @@ cl_program CL_API_CALL clCreateProgramWithBinary(cl_context context, cl_int *binary_status, cl_int *errcode_ret) { - CL_EVENT(CreateProgramWithBinary, - "context = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR - ", lengths = 0x%016" PRIxPTR ", binaries = 0x%016" PRIxPTR - ", binary_status = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, num_devices, (uintptr_t)device_list, (uintptr_t)lengths, - (uintptr_t)binaries, (uintptr_t)binary_status, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(CreateProgramWithBinary, + "context = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR + ", lengths = 0x%016" PRIxPTR ", binaries = 0x%016" PRIxPTR + ", binary_status = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, num_devices, (uintptr_t)device_list, (uintptr_t)lengths, + (uintptr_t)binaries, (uintptr_t)binary_status, (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateProgramWithBinary, context, num_devices, device_list, lengths, binaries, binary_status); @@ -534,7 +549,7 @@ cl_program CL_API_CALL clCreateProgramWithBinary(cl_context context, cl_int CL_API_CALL clRetainProgram(cl_program program) { - CL_EVENT(RetainProgram, "program = 0x%016" PRIxPTR "", (uintptr_t)program); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainProgram, "program = 0x%016" PRIxPTR "", (uintptr_t)program)); ANGLE_CL_VALIDATE_ERROR(RetainProgram, program); @@ -546,7 +561,7 @@ cl_int CL_API_CALL clRetainProgram(cl_program program) cl_int CL_API_CALL clReleaseProgram(cl_program program) { - CL_EVENT(ReleaseProgram, "program = 0x%016" PRIxPTR "", (uintptr_t)program); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseProgram, "program = 0x%016" PRIxPTR "", (uintptr_t)program)); ANGLE_CL_VALIDATE_ERROR(ReleaseProgram, program); @@ -564,12 +579,13 @@ cl_int CL_API_CALL clBuildProgram(cl_program program, void *user_data), void *user_data) { - CL_EVENT(BuildProgram, - "program = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR - ", options = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR - ", user_data = 0x%016" PRIxPTR "", - (uintptr_t)program, num_devices, (uintptr_t)device_list, (uintptr_t)options, - (uintptr_t)pfn_notify, (uintptr_t)user_data); + ANGLE_UNSAFE_TODO(CL_EVENT(BuildProgram, + "program = 0x%016" PRIxPTR + ", num_devices = %u, device_list = 0x%016" PRIxPTR + ", options = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR + ", user_data = 0x%016" PRIxPTR "", + (uintptr_t)program, num_devices, (uintptr_t)device_list, + (uintptr_t)options, (uintptr_t)pfn_notify, (uintptr_t)user_data)); ANGLE_CL_VALIDATE_ERROR(BuildProgram, program, num_devices, device_list, options, pfn_notify, user_data); @@ -588,12 +604,13 @@ cl_int CL_API_CALL clGetProgramInfo(cl_program program, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetProgramInfo, - "program = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)program, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetProgramInfo, + "program = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)program, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); ProgramInfo param_namePacked = PackParam(param_name); @@ -615,12 +632,13 @@ cl_int CL_API_CALL clGetProgramBuildInfo(cl_program program, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetProgramBuildInfo, - "program = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)program, (uintptr_t)device, param_name, param_value_size, - (uintptr_t)param_value, (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetProgramBuildInfo, + "program = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)program, (uintptr_t)device, param_name, param_value_size, + (uintptr_t)param_value, (uintptr_t)param_value_size_ret)); ProgramBuildInfo param_namePacked = PackParam(param_name); @@ -639,10 +657,10 @@ cl_kernel CL_API_CALL clCreateKernel(cl_program program, const char *kernel_name, cl_int *errcode_ret) { - CL_EVENT(CreateKernel, - "program = 0x%016" PRIxPTR ", kernel_name = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)program, (uintptr_t)kernel_name, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateKernel, + "program = 0x%016" PRIxPTR ", kernel_name = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)program, (uintptr_t)kernel_name, (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateKernel, program, kernel_name); @@ -663,10 +681,11 @@ cl_int CL_API_CALL clCreateKernelsInProgram(cl_program program, cl_kernel *kernels, cl_uint *num_kernels_ret) { - CL_EVENT(CreateKernelsInProgram, - "program = 0x%016" PRIxPTR ", num_kernels = %u, kernels = 0x%016" PRIxPTR - ", num_kernels_ret = 0x%016" PRIxPTR "", - (uintptr_t)program, num_kernels, (uintptr_t)kernels, (uintptr_t)num_kernels_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(CreateKernelsInProgram, + "program = 0x%016" PRIxPTR ", num_kernels = %u, kernels = 0x%016" PRIxPTR + ", num_kernels_ret = 0x%016" PRIxPTR "", + (uintptr_t)program, num_kernels, (uintptr_t)kernels, (uintptr_t)num_kernels_ret)); ANGLE_CL_VALIDATE_ERROR(CreateKernelsInProgram, program, num_kernels, kernels, num_kernels_ret); @@ -679,7 +698,7 @@ cl_int CL_API_CALL clCreateKernelsInProgram(cl_program program, cl_int CL_API_CALL clRetainKernel(cl_kernel kernel) { - CL_EVENT(RetainKernel, "kernel = 0x%016" PRIxPTR "", (uintptr_t)kernel); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainKernel, "kernel = 0x%016" PRIxPTR "", (uintptr_t)kernel)); ANGLE_CL_VALIDATE_ERROR(RetainKernel, kernel); @@ -691,7 +710,7 @@ cl_int CL_API_CALL clRetainKernel(cl_kernel kernel) cl_int CL_API_CALL clReleaseKernel(cl_kernel kernel) { - CL_EVENT(ReleaseKernel, "kernel = 0x%016" PRIxPTR "", (uintptr_t)kernel); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseKernel, "kernel = 0x%016" PRIxPTR "", (uintptr_t)kernel)); ANGLE_CL_VALIDATE_ERROR(ReleaseKernel, kernel); @@ -706,10 +725,10 @@ cl_int CL_API_CALL clSetKernelArg(cl_kernel kernel, size_t arg_size, const void *arg_value) { - CL_EVENT(SetKernelArg, - "kernel = 0x%016" PRIxPTR - ", arg_index = %u, arg_size = %zu, arg_value = 0x%016" PRIxPTR "", - (uintptr_t)kernel, arg_index, arg_size, (uintptr_t)arg_value); + ANGLE_UNSAFE_TODO(CL_EVENT(SetKernelArg, + "kernel = 0x%016" PRIxPTR + ", arg_index = %u, arg_size = %zu, arg_value = 0x%016" PRIxPTR "", + (uintptr_t)kernel, arg_index, arg_size, (uintptr_t)arg_value)); ANGLE_CL_VALIDATE_ERROR(SetKernelArg, kernel, arg_index, arg_size, arg_value); @@ -725,12 +744,13 @@ cl_int CL_API_CALL clGetKernelInfo(cl_kernel kernel, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetKernelInfo, - "kernel = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)kernel, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetKernelInfo, + "kernel = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)kernel, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); KernelInfo param_namePacked = PackParam(param_name); @@ -752,12 +772,13 @@ cl_int CL_API_CALL clGetKernelWorkGroupInfo(cl_kernel kernel, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetKernelWorkGroupInfo, - "kernel = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)kernel, (uintptr_t)device, param_name, param_value_size, - (uintptr_t)param_value, (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetKernelWorkGroupInfo, + "kernel = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)kernel, (uintptr_t)device, param_name, param_value_size, + (uintptr_t)param_value, (uintptr_t)param_value_size_ret)); KernelWorkGroupInfo param_namePacked = PackParam(param_name); @@ -774,8 +795,8 @@ cl_int CL_API_CALL clGetKernelWorkGroupInfo(cl_kernel kernel, cl_int CL_API_CALL clWaitForEvents(cl_uint num_events, const cl_event *event_list) { - CL_EVENT(WaitForEvents, "num_events = %u, event_list = 0x%016" PRIxPTR "", num_events, - (uintptr_t)event_list); + ANGLE_UNSAFE_TODO(CL_EVENT(WaitForEvents, "num_events = %u, event_list = 0x%016" PRIxPTR "", + num_events, (uintptr_t)event_list)); ANGLE_CL_VALIDATE_ERROR(WaitForEvents, num_events, event_list); @@ -791,12 +812,13 @@ cl_int CL_API_CALL clGetEventInfo(cl_event event, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetEventInfo, - "event = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)event, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetEventInfo, + "event = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)event, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); EventInfo param_namePacked = PackParam(param_name); @@ -813,7 +835,7 @@ cl_int CL_API_CALL clGetEventInfo(cl_event event, cl_int CL_API_CALL clRetainEvent(cl_event event) { - CL_EVENT(RetainEvent, "event = 0x%016" PRIxPTR "", (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainEvent, "event = 0x%016" PRIxPTR "", (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(RetainEvent, event); @@ -825,7 +847,7 @@ cl_int CL_API_CALL clRetainEvent(cl_event event) cl_int CL_API_CALL clReleaseEvent(cl_event event) { - CL_EVENT(ReleaseEvent, "event = 0x%016" PRIxPTR "", (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseEvent, "event = 0x%016" PRIxPTR "", (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(ReleaseEvent, event); @@ -841,12 +863,13 @@ cl_int CL_API_CALL clGetEventProfilingInfo(cl_event event, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetEventProfilingInfo, - "event = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)event, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetEventProfilingInfo, + "event = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)event, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); ProfilingInfo param_namePacked = PackParam(param_name); @@ -863,7 +886,8 @@ cl_int CL_API_CALL clGetEventProfilingInfo(cl_event event, cl_int CL_API_CALL clFlush(cl_command_queue command_queue) { - CL_EVENT(Flush, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue); + ANGLE_UNSAFE_TODO( + CL_EVENT(Flush, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue)); ANGLE_CL_VALIDATE_ERROR(Flush, command_queue); @@ -875,7 +899,8 @@ cl_int CL_API_CALL clFlush(cl_command_queue command_queue) cl_int CL_API_CALL clFinish(cl_command_queue command_queue) { - CL_EVENT(Finish, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue); + ANGLE_UNSAFE_TODO( + CL_EVENT(Finish, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue)); ANGLE_CL_VALIDATE_ERROR(Finish, command_queue); @@ -895,13 +920,14 @@ cl_int CL_API_CALL clEnqueueReadBuffer(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueReadBuffer, - "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR - ", blocking_read = %u, offset = %zu, size = %zu, ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)buffer, blocking_read, offset, size, - (uintptr_t)ptr, num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueReadBuffer, + "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR + ", blocking_read = %u, offset = %zu, size = %zu, ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)buffer, blocking_read, offset, size, (uintptr_t)ptr, + num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueReadBuffer, command_queue, buffer, blocking_read, offset, size, ptr, num_events_in_wait_list, event_wait_list, event); @@ -924,13 +950,14 @@ cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueWriteBuffer, - "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR - ", blocking_write = %u, offset = %zu, size = %zu, ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)buffer, blocking_write, offset, size, - (uintptr_t)ptr, num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueWriteBuffer, + "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR + ", blocking_write = %u, offset = %zu, size = %zu, ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)buffer, blocking_write, offset, size, (uintptr_t)ptr, + num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueWriteBuffer, command_queue, buffer, blocking_write, offset, size, ptr, num_events_in_wait_list, event_wait_list, event); @@ -953,14 +980,14 @@ cl_int CL_API_CALL clEnqueueCopyBuffer(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueCopyBuffer, - "command_queue = 0x%016" PRIxPTR ", src_buffer = 0x%016" PRIxPTR - ", dst_buffer = 0x%016" PRIxPTR - ", src_offset = %zu, dst_offset = %zu, size = %zu, num_events_in_wait_list = %u, " - "event_wait_list = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)src_buffer, (uintptr_t)dst_buffer, src_offset, - dst_offset, size, num_events_in_wait_list, (uintptr_t)event_wait_list, - (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueCopyBuffer, + "command_queue = 0x%016" PRIxPTR ", src_buffer = 0x%016" PRIxPTR + ", dst_buffer = 0x%016" PRIxPTR + ", src_offset = %zu, dst_offset = %zu, size = %zu, num_events_in_wait_list = %u, " + "event_wait_list = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)src_buffer, (uintptr_t)dst_buffer, src_offset, + dst_offset, size, num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueCopyBuffer, command_queue, src_buffer, dst_buffer, src_offset, dst_offset, size, num_events_in_wait_list, event_wait_list, event); @@ -987,15 +1014,16 @@ cl_int CL_API_CALL clEnqueueReadImage(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueReadImage, - "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR - ", blocking_read = %u, origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR - ", row_pitch = %zu, slice_pitch = %zu, ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)image, blocking_read, (uintptr_t)origin, - (uintptr_t)region, row_pitch, slice_pitch, (uintptr_t)ptr, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueReadImage, + "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR + ", blocking_read = %u, origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", row_pitch = %zu, slice_pitch = %zu, ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)image, blocking_read, (uintptr_t)origin, + (uintptr_t)region, row_pitch, slice_pitch, (uintptr_t)ptr, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueReadImage, command_queue, image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, @@ -1023,15 +1051,16 @@ cl_int CL_API_CALL clEnqueueWriteImage(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueWriteImage, - "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR - ", blocking_write = %u, origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR - ", input_row_pitch = %zu, input_slice_pitch = %zu, ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)image, blocking_write, (uintptr_t)origin, - (uintptr_t)region, input_row_pitch, input_slice_pitch, (uintptr_t)ptr, - num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueWriteImage, + "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR + ", blocking_write = %u, origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", input_row_pitch = %zu, input_slice_pitch = %zu, ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)image, blocking_write, (uintptr_t)origin, + (uintptr_t)region, input_row_pitch, input_slice_pitch, (uintptr_t)ptr, + num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueWriteImage, command_queue, image, blocking_write, origin, region, input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, @@ -1057,15 +1086,16 @@ cl_int CL_API_CALL clEnqueueCopyImage(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueCopyImage, - "command_queue = 0x%016" PRIxPTR ", src_image = 0x%016" PRIxPTR - ", dst_image = 0x%016" PRIxPTR ", src_origin = 0x%016" PRIxPTR - ", dst_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)src_image, (uintptr_t)dst_image, - (uintptr_t)src_origin, (uintptr_t)dst_origin, (uintptr_t)region, - num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueCopyImage, + "command_queue = 0x%016" PRIxPTR ", src_image = 0x%016" PRIxPTR + ", dst_image = 0x%016" PRIxPTR ", src_origin = 0x%016" PRIxPTR + ", dst_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)src_image, (uintptr_t)dst_image, + (uintptr_t)src_origin, (uintptr_t)dst_origin, (uintptr_t)region, + num_events_in_wait_list, (uintptr_t)event_wait_list, + (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueCopyImage, command_queue, src_image, dst_image, src_origin, dst_origin, region, num_events_in_wait_list, event_wait_list, event); @@ -1090,15 +1120,15 @@ cl_int CL_API_CALL clEnqueueCopyImageToBuffer(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueCopyImageToBuffer, - "command_queue = 0x%016" PRIxPTR ", src_image = 0x%016" PRIxPTR - ", dst_buffer = 0x%016" PRIxPTR ", src_origin = 0x%016" PRIxPTR - ", region = 0x%016" PRIxPTR - ", dst_offset = %zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)src_image, (uintptr_t)dst_buffer, - (uintptr_t)src_origin, (uintptr_t)region, dst_offset, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueCopyImageToBuffer, + "command_queue = 0x%016" PRIxPTR ", src_image = 0x%016" PRIxPTR + ", dst_buffer = 0x%016" PRIxPTR ", src_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", dst_offset = %zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)src_image, (uintptr_t)dst_buffer, + (uintptr_t)src_origin, (uintptr_t)region, dst_offset, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueCopyImageToBuffer, command_queue, src_image, dst_buffer, src_origin, region, dst_offset, num_events_in_wait_list, @@ -1124,15 +1154,16 @@ cl_int CL_API_CALL clEnqueueCopyBufferToImage(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueCopyBufferToImage, - "command_queue = 0x%016" PRIxPTR ", src_buffer = 0x%016" PRIxPTR - ", dst_image = 0x%016" PRIxPTR ", src_offset = %zu, dst_origin = 0x%016" PRIxPTR - ", region = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)src_buffer, (uintptr_t)dst_image, src_offset, - (uintptr_t)dst_origin, (uintptr_t)region, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueCopyBufferToImage, + "command_queue = 0x%016" PRIxPTR ", src_buffer = 0x%016" PRIxPTR + ", dst_image = 0x%016" PRIxPTR ", src_offset = %zu, dst_origin = 0x%016" PRIxPTR + ", region = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)src_buffer, (uintptr_t)dst_image, src_offset, + (uintptr_t)dst_origin, (uintptr_t)region, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueCopyBufferToImage, command_queue, src_buffer, dst_image, src_offset, dst_origin, region, num_events_in_wait_list, @@ -1159,14 +1190,15 @@ void *CL_API_CALL clEnqueueMapBuffer(cl_command_queue command_queue, cl_event *event, cl_int *errcode_ret) { - CL_EVENT(EnqueueMapBuffer, - "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR - ", blocking_map = %u, map_flags = %llu, offset = %zu, size = %zu, " - "num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)buffer, blocking_map, - static_cast(map_flags), offset, size, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueMapBuffer, + "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR + ", blocking_map = %u, map_flags = %llu, offset = %zu, size = %zu, " + "num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)buffer, blocking_map, + static_cast(map_flags), offset, size, + num_events_in_wait_list, (uintptr_t)event_wait_list, + (uintptr_t)event, (uintptr_t)errcode_ret)); MapFlags map_flagsPacked = PackParam(map_flags); @@ -1202,17 +1234,17 @@ void *CL_API_CALL clEnqueueMapImage(cl_command_queue command_queue, cl_event *event, cl_int *errcode_ret) { - CL_EVENT(EnqueueMapImage, - "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR - ", blocking_map = %u, map_flags = %llu, origin = 0x%016" PRIxPTR - ", region = 0x%016" PRIxPTR ", image_row_pitch = 0x%016" PRIxPTR - ", image_slice_pitch = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)image, blocking_map, - static_cast(map_flags), (uintptr_t)origin, (uintptr_t)region, - (uintptr_t)image_row_pitch, (uintptr_t)image_slice_pitch, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueMapImage, + "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR + ", blocking_map = %u, map_flags = %llu, origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", image_row_pitch = 0x%016" PRIxPTR ", image_slice_pitch = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)image, blocking_map, + static_cast(map_flags), (uintptr_t)origin, (uintptr_t)region, + (uintptr_t)image_row_pitch, (uintptr_t)image_slice_pitch, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event, (uintptr_t)errcode_ret)); MapFlags map_flagsPacked = PackParam(map_flags); @@ -1243,13 +1275,13 @@ cl_int CL_API_CALL clEnqueueUnmapMemObject(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueUnmapMemObject, - "command_queue = 0x%016" PRIxPTR ", memobj = 0x%016" PRIxPTR - ", mapped_ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)memobj, (uintptr_t)mapped_ptr, - num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueUnmapMemObject, + "command_queue = 0x%016" PRIxPTR ", memobj = 0x%016" PRIxPTR ", mapped_ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)memobj, (uintptr_t)mapped_ptr, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueUnmapMemObject, command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event); @@ -1272,15 +1304,16 @@ cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueNDRangeKernel, - "command_queue = 0x%016" PRIxPTR ", kernel = 0x%016" PRIxPTR - ", work_dim = %u, global_work_offset = 0x%016" PRIxPTR - ", global_work_size = 0x%016" PRIxPTR ", local_work_size = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)kernel, work_dim, (uintptr_t)global_work_offset, - (uintptr_t)global_work_size, (uintptr_t)local_work_size, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueNDRangeKernel, + "command_queue = 0x%016" PRIxPTR ", kernel = 0x%016" PRIxPTR + ", work_dim = %u, global_work_offset = 0x%016" PRIxPTR ", global_work_size = 0x%016" PRIxPTR + ", local_work_size = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)kernel, work_dim, (uintptr_t)global_work_offset, + (uintptr_t)global_work_size, (uintptr_t)local_work_size, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueNDRangeKernel, command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, @@ -1307,16 +1340,16 @@ cl_int CL_API_CALL clEnqueueNativeKernel(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueNativeKernel, - "command_queue = 0x%016" PRIxPTR ", user_func = 0x%016" PRIxPTR - ", args = 0x%016" PRIxPTR - ", cb_args = %zu, num_mem_objects = %u, mem_list = 0x%016" PRIxPTR - ", args_mem_loc = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)user_func, (uintptr_t)args, cb_args, - num_mem_objects, (uintptr_t)mem_list, (uintptr_t)args_mem_loc, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueNativeKernel, + "command_queue = 0x%016" PRIxPTR ", user_func = 0x%016" PRIxPTR ", args = 0x%016" PRIxPTR + ", cb_args = %zu, num_mem_objects = %u, mem_list = 0x%016" PRIxPTR + ", args_mem_loc = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)user_func, (uintptr_t)args, cb_args, num_mem_objects, + (uintptr_t)mem_list, (uintptr_t)args_mem_loc, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueNativeKernel, command_queue, user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, num_events_in_wait_list, @@ -1337,11 +1370,12 @@ cl_int CL_API_CALL clSetCommandQueueProperty(cl_command_queue command_queue, cl_bool enable, cl_command_queue_properties *old_properties) { - CL_EVENT(SetCommandQueueProperty, - "command_queue = 0x%016" PRIxPTR - ", properties = %llu, enable = %u, old_properties = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, static_cast(properties), enable, - (uintptr_t)old_properties); + ANGLE_UNSAFE_TODO( + CL_EVENT(SetCommandQueueProperty, + "command_queue = 0x%016" PRIxPTR + ", properties = %llu, enable = %u, old_properties = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, static_cast(properties), enable, + (uintptr_t)old_properties)); CommandQueueProperties propertiesPacked = PackParam(properties); @@ -1365,13 +1399,13 @@ cl_mem CL_API_CALL clCreateImage2D(cl_context context, void *host_ptr, cl_int *errcode_ret) { - CL_EVENT( + ANGLE_UNSAFE_TODO(CL_EVENT( CreateImage2D, "context = 0x%016" PRIxPTR ", flags = %llu, image_format = 0x%016" PRIxPTR ", image_width = %zu, image_height = %zu, image_row_pitch = %zu, host_ptr = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", (uintptr_t)context, static_cast(flags), (uintptr_t)image_format, - image_width, image_height, image_row_pitch, (uintptr_t)host_ptr, (uintptr_t)errcode_ret); + image_width, image_height, image_row_pitch, (uintptr_t)host_ptr, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -1403,14 +1437,14 @@ cl_mem CL_API_CALL clCreateImage3D(cl_context context, void *host_ptr, cl_int *errcode_ret) { - CL_EVENT(CreateImage3D, - "context = 0x%016" PRIxPTR ", flags = %llu, image_format = 0x%016" PRIxPTR - ", image_width = %zu, image_height = %zu, image_depth = %zu, image_row_pitch = %zu, " - "image_slice_pitch = %zu, host_ptr = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR - "", - (uintptr_t)context, static_cast(flags), (uintptr_t)image_format, - image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, - (uintptr_t)host_ptr, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT( + CreateImage3D, + "context = 0x%016" PRIxPTR ", flags = %llu, image_format = 0x%016" PRIxPTR + ", image_width = %zu, image_height = %zu, image_depth = %zu, image_row_pitch = %zu, " + "image_slice_pitch = %zu, host_ptr = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, static_cast(flags), (uintptr_t)image_format, + image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, + (uintptr_t)host_ptr, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -1435,8 +1469,9 @@ cl_mem CL_API_CALL clCreateImage3D(cl_context context, cl_int CL_API_CALL clEnqueueMarker(cl_command_queue command_queue, cl_event *event) { - CL_EVENT(EnqueueMarker, "command_queue = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueMarker, + "command_queue = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueMarker, command_queue, event); @@ -1450,9 +1485,10 @@ cl_int CL_API_CALL clEnqueueWaitForEvents(cl_command_queue command_queue, cl_uint num_events, const cl_event *event_list) { - CL_EVENT(EnqueueWaitForEvents, - "command_queue = 0x%016" PRIxPTR ", num_events = %u, event_list = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, num_events, (uintptr_t)event_list); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueWaitForEvents, + "command_queue = 0x%016" PRIxPTR + ", num_events = %u, event_list = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_events, (uintptr_t)event_list)); ANGLE_CL_VALIDATE_ERROR(EnqueueWaitForEvents, command_queue, num_events, event_list); @@ -1465,7 +1501,8 @@ cl_int CL_API_CALL clEnqueueWaitForEvents(cl_command_queue command_queue, cl_int CL_API_CALL clEnqueueBarrier(cl_command_queue command_queue) { - CL_EVENT(EnqueueBarrier, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueBarrier, "command_queue = 0x%016" PRIxPTR "", (uintptr_t)command_queue)); ANGLE_CL_VALIDATE_ERROR(EnqueueBarrier, command_queue); @@ -1477,7 +1514,7 @@ cl_int CL_API_CALL clEnqueueBarrier(cl_command_queue command_queue) cl_int CL_API_CALL clUnloadCompiler() { - CL_EVENT(UnloadCompiler, ""); + ANGLE_UNSAFE_TODO(CL_EVENT(UnloadCompiler, "")); ANGLE_CL_VALIDATE_ERROR(UnloadCompiler); @@ -1489,7 +1526,8 @@ cl_int CL_API_CALL clUnloadCompiler() void *CL_API_CALL clGetExtensionFunctionAddress(const char *func_name) { - CL_EVENT(GetExtensionFunctionAddress, "func_name = 0x%016" PRIxPTR "", (uintptr_t)func_name); + ANGLE_UNSAFE_TODO(CL_EVENT(GetExtensionFunctionAddress, "func_name = 0x%016" PRIxPTR "", + (uintptr_t)func_name)); cl::gClErrorTls = CL_SUCCESS; ANGLE_CL_VALIDATE_POINTER(GetExtensionFunctionAddress, func_name); @@ -1504,11 +1542,12 @@ cl_command_queue CL_API_CALL clCreateCommandQueue(cl_context context, cl_command_queue_properties properties, cl_int *errcode_ret) { - CL_EVENT(CreateCommandQueue, - "context = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR - ", properties = %llu, errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)device, static_cast(properties), - (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateCommandQueue, + "context = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR + ", properties = %llu, errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)device, + static_cast(properties), + (uintptr_t)errcode_ret)); CommandQueueProperties propertiesPacked = PackParam(properties); @@ -1533,12 +1572,12 @@ cl_sampler CL_API_CALL clCreateSampler(cl_context context, cl_filter_mode filter_mode, cl_int *errcode_ret) { - CL_EVENT(CreateSampler, - "context = 0x%016" PRIxPTR - ", normalized_coords = %u, addressing_mode = %u, filter_mode = %u, errcode_ret = " - "0x%016" PRIxPTR "", - (uintptr_t)context, normalized_coords, addressing_mode, filter_mode, - (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateSampler, + "context = 0x%016" PRIxPTR + ", normalized_coords = %u, addressing_mode = %u, filter_mode = %u, " + "errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, normalized_coords, addressing_mode, filter_mode, + (uintptr_t)errcode_ret)); AddressingMode addressing_modePacked = PackParam(addressing_mode); FilterMode filter_modePacked = PackParam(filter_mode); @@ -1566,12 +1605,12 @@ cl_int CL_API_CALL clEnqueueTask(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueTask, - "command_queue = 0x%016" PRIxPTR ", kernel = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)kernel, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueTask, + "command_queue = 0x%016" PRIxPTR ", kernel = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)kernel, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueTask, command_queue, kernel, num_events_in_wait_list, event_wait_list, event); @@ -1591,12 +1630,13 @@ cl_mem CL_API_CALL clCreateSubBuffer(cl_mem buffer, const void *buffer_create_info, cl_int *errcode_ret) { - CL_EVENT(CreateSubBuffer, - "buffer = 0x%016" PRIxPTR - ", flags = %llu, buffer_create_type = %u, buffer_create_info = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)buffer, static_cast(flags), buffer_create_type, - (uintptr_t)buffer_create_info, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(CreateSubBuffer, + "buffer = 0x%016" PRIxPTR + ", flags = %llu, buffer_create_type = %u, buffer_create_info = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)buffer, static_cast(flags), buffer_create_type, + (uintptr_t)buffer_create_info, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -1621,10 +1661,10 @@ cl_int CL_API_CALL clSetMemObjectDestructorCallback(cl_mem memobj, void *user_data), void *user_data) { - CL_EVENT(SetMemObjectDestructorCallback, - "memobj = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR - ", user_data = 0x%016" PRIxPTR "", - (uintptr_t)memobj, (uintptr_t)pfn_notify, (uintptr_t)user_data); + ANGLE_UNSAFE_TODO(CL_EVENT(SetMemObjectDestructorCallback, + "memobj = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR + ", user_data = 0x%016" PRIxPTR "", + (uintptr_t)memobj, (uintptr_t)pfn_notify, (uintptr_t)user_data)); ANGLE_CL_VALIDATE_ERROR(SetMemObjectDestructorCallback, memobj, pfn_notify, user_data); @@ -1637,8 +1677,9 @@ cl_int CL_API_CALL clSetMemObjectDestructorCallback(cl_mem memobj, cl_event CL_API_CALL clCreateUserEvent(cl_context context, cl_int *errcode_ret) { - CL_EVENT(CreateUserEvent, "context = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateUserEvent, + "context = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateUserEvent, context); @@ -1656,8 +1697,9 @@ cl_event CL_API_CALL clCreateUserEvent(cl_context context, cl_int *errcode_ret) cl_int CL_API_CALL clSetUserEventStatus(cl_event event, cl_int execution_status) { - CL_EVENT(SetUserEventStatus, "event = 0x%016" PRIxPTR ", execution_status = %d", - (uintptr_t)event, execution_status); + ANGLE_UNSAFE_TODO(CL_EVENT(SetUserEventStatus, + "event = 0x%016" PRIxPTR ", execution_status = %d", (uintptr_t)event, + execution_status)); ANGLE_CL_VALIDATE_ERROR(SetUserEventStatus, event, execution_status); @@ -1674,11 +1716,11 @@ cl_int CL_API_CALL clSetEventCallback(cl_event event, void *user_data), void *user_data) { - CL_EVENT( + ANGLE_UNSAFE_TODO(CL_EVENT( SetEventCallback, "event = 0x%016" PRIxPTR ", command_exec_callback_type = %d, pfn_notify = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR "", - (uintptr_t)event, command_exec_callback_type, (uintptr_t)pfn_notify, (uintptr_t)user_data); + (uintptr_t)event, command_exec_callback_type, (uintptr_t)pfn_notify, (uintptr_t)user_data)); ANGLE_CL_VALIDATE_ERROR(SetEventCallback, event, command_exec_callback_type, pfn_notify, user_data); @@ -1705,18 +1747,19 @@ cl_int CL_API_CALL clEnqueueReadBufferRect(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueReadBufferRect, - "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR - ", blocking_read = %u, buffer_origin = 0x%016" PRIxPTR ", host_origin = 0x%016" PRIxPTR - ", region = 0x%016" PRIxPTR - ", buffer_row_pitch = %zu, buffer_slice_pitch = %zu, host_row_pitch = %zu, " - "host_slice_pitch = %zu, ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)buffer, blocking_read, (uintptr_t)buffer_origin, - (uintptr_t)host_origin, (uintptr_t)region, buffer_row_pitch, buffer_slice_pitch, - host_row_pitch, host_slice_pitch, (uintptr_t)ptr, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueReadBufferRect, + "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR + ", blocking_read = %u, buffer_origin = 0x%016" PRIxPTR + ", host_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", buffer_row_pitch = %zu, buffer_slice_pitch = %zu, host_row_pitch " + "= %zu, host_slice_pitch = %zu, ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)buffer, blocking_read, + (uintptr_t)buffer_origin, (uintptr_t)host_origin, (uintptr_t)region, + buffer_row_pitch, buffer_slice_pitch, host_row_pitch, + host_slice_pitch, (uintptr_t)ptr, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueReadBufferRect, command_queue, buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch, @@ -1750,18 +1793,19 @@ cl_int CL_API_CALL clEnqueueWriteBufferRect(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueWriteBufferRect, - "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR - ", blocking_write = %u, buffer_origin = 0x%016" PRIxPTR - ", host_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR - ", buffer_row_pitch = %zu, buffer_slice_pitch = %zu, host_row_pitch = %zu, " - "host_slice_pitch = %zu, ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)buffer, blocking_write, (uintptr_t)buffer_origin, - (uintptr_t)host_origin, (uintptr_t)region, buffer_row_pitch, buffer_slice_pitch, - host_row_pitch, host_slice_pitch, (uintptr_t)ptr, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueWriteBufferRect, + "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR + ", blocking_write = %u, buffer_origin = 0x%016" PRIxPTR + ", host_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", buffer_row_pitch = %zu, buffer_slice_pitch = %zu, host_row_pitch " + "= %zu, host_slice_pitch = %zu, ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)buffer, blocking_write, + (uintptr_t)buffer_origin, (uintptr_t)host_origin, (uintptr_t)region, + buffer_row_pitch, buffer_slice_pitch, host_row_pitch, + host_slice_pitch, (uintptr_t)ptr, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueWriteBufferRect, command_queue, buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch, @@ -1794,17 +1838,18 @@ cl_int CL_API_CALL clEnqueueCopyBufferRect(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueCopyBufferRect, - "command_queue = 0x%016" PRIxPTR ", src_buffer = 0x%016" PRIxPTR - ", dst_buffer = 0x%016" PRIxPTR ", src_origin = 0x%016" PRIxPTR - ", dst_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR - ", src_row_pitch = %zu, src_slice_pitch = %zu, dst_row_pitch = %zu, dst_slice_pitch = " - "%zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)src_buffer, (uintptr_t)dst_buffer, - (uintptr_t)src_origin, (uintptr_t)dst_origin, (uintptr_t)region, src_row_pitch, - src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueCopyBufferRect, + "command_queue = 0x%016" PRIxPTR ", src_buffer = 0x%016" PRIxPTR + ", dst_buffer = 0x%016" PRIxPTR ", src_origin = 0x%016" PRIxPTR + ", dst_origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", src_row_pitch = %zu, src_slice_pitch = %zu, dst_row_pitch = %zu, dst_slice_pitch = %zu, " + "num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR + "", + (uintptr_t)command_queue, (uintptr_t)src_buffer, (uintptr_t)dst_buffer, + (uintptr_t)src_origin, (uintptr_t)dst_origin, (uintptr_t)region, src_row_pitch, + src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueCopyBufferRect, command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, src_slice_pitch, @@ -1829,12 +1874,12 @@ cl_int CL_API_CALL clCreateSubDevices(cl_device_id in_device, cl_device_id *out_devices, cl_uint *num_devices_ret) { - CL_EVENT(CreateSubDevices, - "in_device = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR - ", num_devices = %u, out_devices = 0x%016" PRIxPTR ", num_devices_ret = 0x%016" PRIxPTR - "", - (uintptr_t)in_device, (uintptr_t)properties, num_devices, (uintptr_t)out_devices, - (uintptr_t)num_devices_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateSubDevices, + "in_device = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR + ", num_devices = %u, out_devices = 0x%016" PRIxPTR + ", num_devices_ret = 0x%016" PRIxPTR "", + (uintptr_t)in_device, (uintptr_t)properties, num_devices, + (uintptr_t)out_devices, (uintptr_t)num_devices_ret)); ANGLE_CL_VALIDATE_ERROR(CreateSubDevices, in_device, properties, num_devices, out_devices, num_devices_ret); @@ -1849,7 +1894,7 @@ cl_int CL_API_CALL clCreateSubDevices(cl_device_id in_device, cl_int CL_API_CALL clRetainDevice(cl_device_id device) { - CL_EVENT(RetainDevice, "device = 0x%016" PRIxPTR "", (uintptr_t)device); + ANGLE_UNSAFE_TODO(CL_EVENT(RetainDevice, "device = 0x%016" PRIxPTR "", (uintptr_t)device)); ANGLE_CL_VALIDATE_ERROR(RetainDevice, device); @@ -1861,7 +1906,7 @@ cl_int CL_API_CALL clRetainDevice(cl_device_id device) cl_int CL_API_CALL clReleaseDevice(cl_device_id device) { - CL_EVENT(ReleaseDevice, "device = 0x%016" PRIxPTR "", (uintptr_t)device); + ANGLE_UNSAFE_TODO(CL_EVENT(ReleaseDevice, "device = 0x%016" PRIxPTR "", (uintptr_t)device)); ANGLE_CL_VALIDATE_ERROR(ReleaseDevice, device); @@ -1878,12 +1923,13 @@ cl_mem CL_API_CALL clCreateImage(cl_context context, void *host_ptr, cl_int *errcode_ret) { - CL_EVENT(CreateImage, - "context = 0x%016" PRIxPTR ", flags = %llu, image_format = 0x%016" PRIxPTR - ", image_desc = 0x%016" PRIxPTR ", host_ptr = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, static_cast(flags), (uintptr_t)image_format, - (uintptr_t)image_desc, (uintptr_t)host_ptr, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT( + CreateImage, + "context = 0x%016" PRIxPTR ", flags = %llu, image_format = 0x%016" PRIxPTR + ", image_desc = 0x%016" PRIxPTR ", host_ptr = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, static_cast(flags), (uintptr_t)image_format, + (uintptr_t)image_desc, (uintptr_t)host_ptr, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -1909,11 +1955,12 @@ cl_program CL_API_CALL clCreateProgramWithBuiltInKernels(cl_context context, const char *kernel_names, cl_int *errcode_ret) { - CL_EVENT(CreateProgramWithBuiltInKernels, - "context = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR - ", kernel_names = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, num_devices, (uintptr_t)device_list, (uintptr_t)kernel_names, - (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(CreateProgramWithBuiltInKernels, + "context = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR + ", kernel_names = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, num_devices, (uintptr_t)device_list, (uintptr_t)kernel_names, + (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateProgramWithBuiltInKernels, context, num_devices, device_list, kernel_names); @@ -1943,14 +1990,15 @@ cl_int CL_API_CALL clCompileProgram(cl_program program, void *user_data), void *user_data) { - CL_EVENT(CompileProgram, - "program = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR - ", options = 0x%016" PRIxPTR ", num_input_headers = %u, input_headers = 0x%016" PRIxPTR - ", header_include_names = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR - ", user_data = 0x%016" PRIxPTR "", - (uintptr_t)program, num_devices, (uintptr_t)device_list, (uintptr_t)options, - num_input_headers, (uintptr_t)input_headers, (uintptr_t)header_include_names, - (uintptr_t)pfn_notify, (uintptr_t)user_data); + ANGLE_UNSAFE_TODO(CL_EVENT( + CompileProgram, + "program = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR + ", options = 0x%016" PRIxPTR ", num_input_headers = %u, input_headers = 0x%016" PRIxPTR + ", header_include_names = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR + ", user_data = 0x%016" PRIxPTR "", + (uintptr_t)program, num_devices, (uintptr_t)device_list, (uintptr_t)options, + num_input_headers, (uintptr_t)input_headers, (uintptr_t)header_include_names, + (uintptr_t)pfn_notify, (uintptr_t)user_data)); ANGLE_CL_VALIDATE_ERROR(CompileProgram, program, num_devices, device_list, options, num_input_headers, input_headers, header_include_names, pfn_notify, @@ -1977,15 +2025,15 @@ cl_program CL_API_CALL clLinkProgram(cl_context context, void *user_data, cl_int *errcode_ret) { - CL_EVENT(LinkProgram, - "context = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR - ", options = 0x%016" PRIxPTR - ", num_input_programs = %u, input_programs = 0x%016" PRIxPTR - ", pfn_notify = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, num_devices, (uintptr_t)device_list, (uintptr_t)options, - num_input_programs, (uintptr_t)input_programs, (uintptr_t)pfn_notify, - (uintptr_t)user_data, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT( + LinkProgram, + "context = 0x%016" PRIxPTR ", num_devices = %u, device_list = 0x%016" PRIxPTR + ", options = 0x%016" PRIxPTR ", num_input_programs = %u, input_programs = 0x%016" PRIxPTR + ", pfn_notify = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, num_devices, (uintptr_t)device_list, (uintptr_t)options, + num_input_programs, (uintptr_t)input_programs, (uintptr_t)pfn_notify, (uintptr_t)user_data, + (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(LinkProgram, context, num_devices, device_list, options, num_input_programs, input_programs, pfn_notify, user_data); @@ -2007,7 +2055,8 @@ cl_program CL_API_CALL clLinkProgram(cl_context context, cl_int CL_API_CALL clUnloadPlatformCompiler(cl_platform_id platform) { - CL_EVENT(UnloadPlatformCompiler, "platform = 0x%016" PRIxPTR "", (uintptr_t)platform); + ANGLE_UNSAFE_TODO( + CL_EVENT(UnloadPlatformCompiler, "platform = 0x%016" PRIxPTR "", (uintptr_t)platform)); ANGLE_CL_VALIDATE_ERROR(UnloadPlatformCompiler, platform); @@ -2024,13 +2073,13 @@ cl_int CL_API_CALL clGetKernelArgInfo(cl_kernel kernel, void *param_value, size_t *param_value_size_ret) { - CL_EVENT( + ANGLE_UNSAFE_TODO(CL_EVENT( GetKernelArgInfo, "kernel = 0x%016" PRIxPTR ", arg_index = %u, param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR ", param_value_size_ret = 0x%016" PRIxPTR "", (uintptr_t)kernel, arg_index, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + (uintptr_t)param_value_size_ret)); KernelArgInfo param_namePacked = PackParam(param_name); @@ -2055,13 +2104,13 @@ cl_int CL_API_CALL clEnqueueFillBuffer(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueFillBuffer, - "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR - ", pattern = 0x%016" PRIxPTR - ", pattern_size = %zu, offset = %zu, size = %zu, num_events_in_wait_list = %u, " - "event_wait_list = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)buffer, (uintptr_t)pattern, pattern_size, offset, - size, num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueFillBuffer, + "command_queue = 0x%016" PRIxPTR ", buffer = 0x%016" PRIxPTR ", pattern = 0x%016" PRIxPTR + ", pattern_size = %zu, offset = %zu, size = %zu, num_events_in_wait_list = %u, " + "event_wait_list = 0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)buffer, (uintptr_t)pattern, pattern_size, offset, size, + num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueFillBuffer, command_queue, buffer, pattern, pattern_size, offset, size, num_events_in_wait_list, event_wait_list, event); @@ -2083,14 +2132,14 @@ cl_int CL_API_CALL clEnqueueFillImage(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueFillImage, - "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR - ", fill_color = 0x%016" PRIxPTR ", origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)image, (uintptr_t)fill_color, (uintptr_t)origin, - (uintptr_t)region, num_events_in_wait_list, (uintptr_t)event_wait_list, - (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueFillImage, + "command_queue = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR ", fill_color = 0x%016" PRIxPTR + ", origin = 0x%016" PRIxPTR ", region = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)image, (uintptr_t)fill_color, (uintptr_t)origin, + (uintptr_t)region, num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueFillImage, command_queue, image, fill_color, origin, region, num_events_in_wait_list, event_wait_list, event); @@ -2111,13 +2160,14 @@ cl_int CL_API_CALL clEnqueueMigrateMemObjects(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueMigrateMemObjects, - "command_queue = 0x%016" PRIxPTR ", num_mem_objects = %u, mem_objects = 0x%016" PRIxPTR - ", flags = %llu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, num_mem_objects, (uintptr_t)mem_objects, - static_cast(flags), num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueMigrateMemObjects, + "command_queue = 0x%016" PRIxPTR ", num_mem_objects = %u, mem_objects = 0x%016" PRIxPTR + ", flags = %llu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_mem_objects, (uintptr_t)mem_objects, + static_cast(flags), num_events_in_wait_list, (uintptr_t)event_wait_list, + (uintptr_t)event)); MemMigrationFlags flagsPacked = PackParam(flags); @@ -2138,12 +2188,12 @@ cl_int CL_API_CALL clEnqueueMarkerWithWaitList(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueMarkerWithWaitList, - "command_queue = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, num_events_in_wait_list, (uintptr_t)event_wait_list, - (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueMarkerWithWaitList, + "command_queue = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueMarkerWithWaitList, command_queue, num_events_in_wait_list, event_wait_list, event); @@ -2161,12 +2211,12 @@ cl_int CL_API_CALL clEnqueueBarrierWithWaitList(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueBarrierWithWaitList, - "command_queue = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, num_events_in_wait_list, (uintptr_t)event_wait_list, - (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueBarrierWithWaitList, + "command_queue = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueBarrierWithWaitList, command_queue, num_events_in_wait_list, event_wait_list, event); @@ -2182,9 +2232,9 @@ cl_int CL_API_CALL clEnqueueBarrierWithWaitList(cl_command_queue command_queue, void *CL_API_CALL clGetExtensionFunctionAddressForPlatform(cl_platform_id platform, const char *func_name) { - CL_EVENT(GetExtensionFunctionAddressForPlatform, - "platform = 0x%016" PRIxPTR ", func_name = 0x%016" PRIxPTR "", (uintptr_t)platform, - (uintptr_t)func_name); + ANGLE_UNSAFE_TODO(CL_EVENT(GetExtensionFunctionAddressForPlatform, + "platform = 0x%016" PRIxPTR ", func_name = 0x%016" PRIxPTR "", + (uintptr_t)platform, (uintptr_t)func_name)); cl::gClErrorTls = CL_SUCCESS; ANGLE_CL_VALIDATE_POINTER(GetExtensionFunctionAddressForPlatform, platform, func_name); @@ -2202,10 +2252,11 @@ clCreateCommandQueueWithProperties(cl_context context, const cl_queue_properties *properties, cl_int *errcode_ret) { - CL_EVENT(CreateCommandQueueWithProperties, - "context = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)device, (uintptr_t)properties, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateCommandQueueWithProperties, + "context = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR + ", properties = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)device, (uintptr_t)properties, + (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateCommandQueueWithProperties, context, device, properties); @@ -2229,13 +2280,13 @@ cl_mem CL_API_CALL clCreatePipe(cl_context context, const cl_pipe_properties *properties, cl_int *errcode_ret) { - CL_EVENT( + ANGLE_UNSAFE_TODO(CL_EVENT( CreatePipe, "context = 0x%016" PRIxPTR ", flags = %llu, pipe_packet_size = %u, pipe_max_packets = %u, properties = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", (uintptr_t)context, static_cast(flags), pipe_packet_size, - pipe_max_packets, (uintptr_t)properties, (uintptr_t)errcode_ret); + pipe_max_packets, (uintptr_t)properties, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -2262,12 +2313,13 @@ cl_int CL_API_CALL clGetPipeInfo(cl_mem pipe, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetPipeInfo, - "pipe = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)pipe, param_name, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO( + CL_EVENT(GetPipeInfo, + "pipe = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)pipe, param_name, param_value_size, (uintptr_t)param_value, + (uintptr_t)param_value_size_ret)); PipeInfo param_namePacked = PackParam(param_name); @@ -2287,8 +2339,9 @@ void *CL_API_CALL clSVMAlloc(cl_context context, size_t size, cl_uint alignment) { - CL_EVENT(SVMAlloc, "context = 0x%016" PRIxPTR ", flags = %llu, size = %zu, alignment = %u", - (uintptr_t)context, static_cast(flags), size, alignment); + ANGLE_UNSAFE_TODO( + CL_EVENT(SVMAlloc, "context = 0x%016" PRIxPTR ", flags = %llu, size = %zu, alignment = %u", + (uintptr_t)context, static_cast(flags), size, alignment)); SVM_MemFlags flagsPacked = PackParam(flags); @@ -2302,8 +2355,9 @@ void *CL_API_CALL clSVMAlloc(cl_context context, void CL_API_CALL clSVMFree(cl_context context, void *svm_pointer) { - CL_EVENT(SVMFree, "context = 0x%016" PRIxPTR ", svm_pointer = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)svm_pointer); + ANGLE_UNSAFE_TODO(CL_EVENT(SVMFree, + "context = 0x%016" PRIxPTR ", svm_pointer = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)svm_pointer)); ANGLE_CL_VALIDATE_VOID(SVMFree, context, svm_pointer); @@ -2317,10 +2371,11 @@ clCreateSamplerWithProperties(cl_context context, const cl_sampler_properties *sampler_properties, cl_int *errcode_ret) { - CL_EVENT(CreateSamplerWithProperties, - "context = 0x%016" PRIxPTR ", sampler_properties = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)sampler_properties, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateSamplerWithProperties, + "context = 0x%016" PRIxPTR ", sampler_properties = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)sampler_properties, + (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateSamplerWithProperties, context, sampler_properties); @@ -2341,9 +2396,10 @@ cl_int CL_API_CALL clSetKernelArgSVMPointer(cl_kernel kernel, cl_uint arg_index, const void *arg_value) { - CL_EVENT(SetKernelArgSVMPointer, - "kernel = 0x%016" PRIxPTR ", arg_index = %u, arg_value = 0x%016" PRIxPTR "", - (uintptr_t)kernel, arg_index, (uintptr_t)arg_value); + ANGLE_UNSAFE_TODO(CL_EVENT(SetKernelArgSVMPointer, + "kernel = 0x%016" PRIxPTR + ", arg_index = %u, arg_value = 0x%016" PRIxPTR "", + (uintptr_t)kernel, arg_index, (uintptr_t)arg_value)); ANGLE_CL_VALIDATE_ERROR(SetKernelArgSVMPointer, kernel, arg_index, arg_value); @@ -2358,10 +2414,11 @@ cl_int CL_API_CALL clSetKernelExecInfo(cl_kernel kernel, size_t param_value_size, const void *param_value) { - CL_EVENT(SetKernelExecInfo, - "kernel = 0x%016" PRIxPTR - ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR "", - (uintptr_t)kernel, param_name, param_value_size, (uintptr_t)param_value); + ANGLE_UNSAFE_TODO( + CL_EVENT(SetKernelExecInfo, + "kernel = 0x%016" PRIxPTR + ", param_name = %u, param_value_size = %zu, param_value = 0x%016" PRIxPTR "", + (uintptr_t)kernel, param_name, param_value_size, (uintptr_t)param_value)); KernelExecInfo param_namePacked = PackParam(param_name); @@ -2387,15 +2444,15 @@ cl_int CL_API_CALL clEnqueueSVMFree(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueSVMFree, - "command_queue = 0x%016" PRIxPTR - ", num_svm_pointers = %u, svm_pointers = 0x%016" PRIxPTR - ", pfn_free_func = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, num_svm_pointers, (uintptr_t)svm_pointers, - (uintptr_t)pfn_free_func, (uintptr_t)user_data, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueSVMFree, + "command_queue = 0x%016" PRIxPTR ", num_svm_pointers = %u, svm_pointers = 0x%016" PRIxPTR + ", pfn_free_func = 0x%016" PRIxPTR ", user_data = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_svm_pointers, (uintptr_t)svm_pointers, + (uintptr_t)pfn_free_func, (uintptr_t)user_data, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueSVMFree, command_queue, num_svm_pointers, svm_pointers, pfn_free_func, user_data, num_events_in_wait_list, event_wait_list, @@ -2420,13 +2477,14 @@ cl_int CL_API_CALL clEnqueueSVMMemcpy(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueSVMMemcpy, - "command_queue = 0x%016" PRIxPTR ", blocking_copy = %u, dst_ptr = 0x%016" PRIxPTR - ", src_ptr = 0x%016" PRIxPTR - ", size = %zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, blocking_copy, (uintptr_t)dst_ptr, (uintptr_t)src_ptr, size, - num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueSVMMemcpy, + "command_queue = 0x%016" PRIxPTR ", blocking_copy = %u, dst_ptr = 0x%016" PRIxPTR + ", src_ptr = 0x%016" PRIxPTR + ", size = %zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, blocking_copy, (uintptr_t)dst_ptr, (uintptr_t)src_ptr, + size, num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueSVMMemcpy, command_queue, blocking_copy, dst_ptr, src_ptr, size, num_events_in_wait_list, event_wait_list, event); @@ -2448,13 +2506,13 @@ cl_int CL_API_CALL clEnqueueSVMMemFill(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueSVMMemFill, - "command_queue = 0x%016" PRIxPTR ", svm_ptr = 0x%016" PRIxPTR - ", pattern = 0x%016" PRIxPTR - ", pattern_size = %zu, size = %zu, num_events_in_wait_list = %u, event_wait_list = " - "0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)svm_ptr, (uintptr_t)pattern, pattern_size, size, - num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueSVMMemFill, + "command_queue = 0x%016" PRIxPTR ", svm_ptr = 0x%016" PRIxPTR ", pattern = 0x%016" PRIxPTR + ", pattern_size = %zu, size = %zu, num_events_in_wait_list = %u, event_wait_list = " + "0x%016" PRIxPTR ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)svm_ptr, (uintptr_t)pattern, pattern_size, size, + num_events_in_wait_list, (uintptr_t)event_wait_list, (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueSVMMemFill, command_queue, svm_ptr, pattern, pattern_size, size, num_events_in_wait_list, event_wait_list, event); @@ -2476,14 +2534,15 @@ cl_int CL_API_CALL clEnqueueSVMMap(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueSVMMap, - "command_queue = 0x%016" PRIxPTR - ", blocking_map = %u, flags = %llu, svm_ptr = 0x%016" PRIxPTR - ", size = %zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, blocking_map, static_cast(flags), - (uintptr_t)svm_ptr, size, num_events_in_wait_list, (uintptr_t)event_wait_list, - (uintptr_t)event); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueSVMMap, + "command_queue = 0x%016" PRIxPTR + ", blocking_map = %u, flags = %llu, svm_ptr = 0x%016" PRIxPTR + ", size = %zu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, blocking_map, static_cast(flags), + (uintptr_t)svm_ptr, size, num_events_in_wait_list, (uintptr_t)event_wait_list, + (uintptr_t)event)); MapFlags flagsPacked = PackParam(flags); @@ -2504,12 +2563,13 @@ cl_int CL_API_CALL clEnqueueSVMUnmap(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueSVMUnmap, - "command_queue = 0x%016" PRIxPTR ", svm_ptr = 0x%016" PRIxPTR - ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, (uintptr_t)svm_ptr, num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO(CL_EVENT(EnqueueSVMUnmap, + "command_queue = 0x%016" PRIxPTR ", svm_ptr = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, (uintptr_t)svm_ptr, + num_events_in_wait_list, (uintptr_t)event_wait_list, + (uintptr_t)event)); ANGLE_CL_VALIDATE_ERROR(EnqueueSVMUnmap, command_queue, svm_ptr, num_events_in_wait_list, event_wait_list, event); @@ -2527,10 +2587,10 @@ cl_int CL_API_CALL clSetDefaultDeviceCommandQueue(cl_context context, cl_device_id device, cl_command_queue command_queue) { - CL_EVENT(SetDefaultDeviceCommandQueue, - "context = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR - ", command_queue = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)device, (uintptr_t)command_queue); + ANGLE_UNSAFE_TODO(CL_EVENT(SetDefaultDeviceCommandQueue, + "context = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR + ", command_queue = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)device, (uintptr_t)command_queue)); ANGLE_CL_VALIDATE_ERROR(SetDefaultDeviceCommandQueue, context, device, command_queue); @@ -2545,10 +2605,11 @@ cl_int CL_API_CALL clGetDeviceAndHostTimer(cl_device_id device, cl_ulong *device_timestamp, cl_ulong *host_timestamp) { - CL_EVENT(GetDeviceAndHostTimer, - "device = 0x%016" PRIxPTR ", device_timestamp = 0x%016" PRIxPTR - ", host_timestamp = 0x%016" PRIxPTR "", - (uintptr_t)device, (uintptr_t)device_timestamp, (uintptr_t)host_timestamp); + ANGLE_UNSAFE_TODO(CL_EVENT(GetDeviceAndHostTimer, + "device = 0x%016" PRIxPTR ", device_timestamp = 0x%016" PRIxPTR + ", host_timestamp = 0x%016" PRIxPTR "", + (uintptr_t)device, (uintptr_t)device_timestamp, + (uintptr_t)host_timestamp)); ANGLE_CL_VALIDATE_ERROR(GetDeviceAndHostTimer, device, device_timestamp, host_timestamp); @@ -2561,8 +2622,9 @@ cl_int CL_API_CALL clGetDeviceAndHostTimer(cl_device_id device, cl_int CL_API_CALL clGetHostTimer(cl_device_id device, cl_ulong *host_timestamp) { - CL_EVENT(GetHostTimer, "device = 0x%016" PRIxPTR ", host_timestamp = 0x%016" PRIxPTR "", - (uintptr_t)device, (uintptr_t)host_timestamp); + ANGLE_UNSAFE_TODO(CL_EVENT(GetHostTimer, + "device = 0x%016" PRIxPTR ", host_timestamp = 0x%016" PRIxPTR "", + (uintptr_t)device, (uintptr_t)host_timestamp)); ANGLE_CL_VALIDATE_ERROR(GetHostTimer, device, host_timestamp); @@ -2577,10 +2639,10 @@ cl_program CL_API_CALL clCreateProgramWithIL(cl_context context, size_t length, cl_int *errcode_ret) { - CL_EVENT(CreateProgramWithIL, - "context = 0x%016" PRIxPTR ", il = 0x%016" PRIxPTR - ", length = %zu, errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)il, length, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateProgramWithIL, + "context = 0x%016" PRIxPTR ", il = 0x%016" PRIxPTR + ", length = %zu, errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)il, length, (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CreateProgramWithIL, context, il, length); @@ -2598,8 +2660,9 @@ cl_program CL_API_CALL clCreateProgramWithIL(cl_context context, cl_kernel CL_API_CALL clCloneKernel(cl_kernel source_kernel, cl_int *errcode_ret) { - CL_EVENT(CloneKernel, "source_kernel = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)source_kernel, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CloneKernel, + "source_kernel = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)source_kernel, (uintptr_t)errcode_ret)); ANGLE_CL_VALIDATE_ERRCODE_RET(CloneKernel, source_kernel); @@ -2624,14 +2687,14 @@ cl_int CL_API_CALL clGetKernelSubGroupInfo(cl_kernel kernel, void *param_value, size_t *param_value_size_ret) { - CL_EVENT(GetKernelSubGroupInfo, - "kernel = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR - ", param_name = %u, input_value_size = %zu, input_value = 0x%016" PRIxPTR - ", param_value_size = %zu, param_value = 0x%016" PRIxPTR - ", param_value_size_ret = 0x%016" PRIxPTR "", - (uintptr_t)kernel, (uintptr_t)device, param_name, input_value_size, - (uintptr_t)input_value, param_value_size, (uintptr_t)param_value, - (uintptr_t)param_value_size_ret); + ANGLE_UNSAFE_TODO(CL_EVENT( + GetKernelSubGroupInfo, + "kernel = 0x%016" PRIxPTR ", device = 0x%016" PRIxPTR + ", param_name = %u, input_value_size = %zu, input_value = 0x%016" PRIxPTR + ", param_value_size = %zu, param_value = 0x%016" PRIxPTR + ", param_value_size_ret = 0x%016" PRIxPTR "", + (uintptr_t)kernel, (uintptr_t)device, param_name, input_value_size, (uintptr_t)input_value, + param_value_size, (uintptr_t)param_value, (uintptr_t)param_value_size_ret)); KernelSubGroupInfo param_namePacked = PackParam(param_name); @@ -2658,14 +2721,15 @@ cl_int CL_API_CALL clEnqueueSVMMigrateMem(cl_command_queue command_queue, const cl_event *event_wait_list, cl_event *event) { - CL_EVENT(EnqueueSVMMigrateMem, - "command_queue = 0x%016" PRIxPTR - ", num_svm_pointers = %u, svm_pointers = 0x%016" PRIxPTR ", sizes = 0x%016" PRIxPTR - ", flags = %llu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR - ", event = 0x%016" PRIxPTR "", - (uintptr_t)command_queue, num_svm_pointers, (uintptr_t)svm_pointers, (uintptr_t)sizes, - static_cast(flags), num_events_in_wait_list, - (uintptr_t)event_wait_list, (uintptr_t)event); + ANGLE_UNSAFE_TODO( + CL_EVENT(EnqueueSVMMigrateMem, + "command_queue = 0x%016" PRIxPTR + ", num_svm_pointers = %u, svm_pointers = 0x%016" PRIxPTR ", sizes = 0x%016" PRIxPTR + ", flags = %llu, num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_svm_pointers, (uintptr_t)svm_pointers, + (uintptr_t)sizes, static_cast(flags), num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); MemMigrationFlags flagsPacked = PackParam(flags); @@ -2688,10 +2752,10 @@ cl_int CL_API_CALL clSetProgramReleaseCallback(cl_program program, void *user_data), void *user_data) { - CL_EVENT(SetProgramReleaseCallback, - "program = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR - ", user_data = 0x%016" PRIxPTR "", - (uintptr_t)program, (uintptr_t)pfn_notify, (uintptr_t)user_data); + ANGLE_UNSAFE_TODO(CL_EVENT(SetProgramReleaseCallback, + "program = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR + ", user_data = 0x%016" PRIxPTR "", + (uintptr_t)program, (uintptr_t)pfn_notify, (uintptr_t)user_data)); ANGLE_CL_VALIDATE_ERROR(SetProgramReleaseCallback, program, pfn_notify, user_data); @@ -2706,10 +2770,10 @@ cl_int CL_API_CALL clSetProgramSpecializationConstant(cl_program program, size_t spec_size, const void *spec_value) { - CL_EVENT(SetProgramSpecializationConstant, - "program = 0x%016" PRIxPTR - ", spec_id = %u, spec_size = %zu, spec_value = 0x%016" PRIxPTR "", - (uintptr_t)program, spec_id, spec_size, (uintptr_t)spec_value); + ANGLE_UNSAFE_TODO(CL_EVENT(SetProgramSpecializationConstant, + "program = 0x%016" PRIxPTR + ", spec_id = %u, spec_size = %zu, spec_value = 0x%016" PRIxPTR "", + (uintptr_t)program, spec_id, spec_size, (uintptr_t)spec_value)); ANGLE_CL_VALIDATE_ERROR(SetProgramSpecializationConstant, program, spec_id, spec_size, spec_value); @@ -2727,10 +2791,10 @@ cl_int CL_API_CALL clSetContextDestructorCallback(cl_context context, void *user_data), void *user_data) { - CL_EVENT(SetContextDestructorCallback, - "context = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR - ", user_data = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)pfn_notify, (uintptr_t)user_data); + ANGLE_UNSAFE_TODO(CL_EVENT(SetContextDestructorCallback, + "context = 0x%016" PRIxPTR ", pfn_notify = 0x%016" PRIxPTR + ", user_data = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)pfn_notify, (uintptr_t)user_data)); ANGLE_CL_VALIDATE_ERROR(SetContextDestructorCallback, context, pfn_notify, user_data); @@ -2748,12 +2812,12 @@ cl_mem CL_API_CALL clCreateBufferWithProperties(cl_context context, void *host_ptr, cl_int *errcode_ret) { - CL_EVENT(CreateBufferWithProperties, - "context = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR - ", flags = %llu, size = %zu, host_ptr = 0x%016" PRIxPTR - ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)properties, static_cast(flags), - size, (uintptr_t)host_ptr, (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT( + CreateBufferWithProperties, + "context = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR + ", flags = %llu, size = %zu, host_ptr = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)properties, static_cast(flags), size, + (uintptr_t)host_ptr, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -2781,13 +2845,14 @@ cl_mem CL_API_CALL clCreateImageWithProperties(cl_context context, void *host_ptr, cl_int *errcode_ret) { - CL_EVENT(CreateImageWithProperties, - "context = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR - ", flags = %llu, image_format = 0x%016" PRIxPTR ", image_desc = 0x%016" PRIxPTR - ", host_ptr = 0x%016" PRIxPTR ", errcode_ret = 0x%016" PRIxPTR "", - (uintptr_t)context, (uintptr_t)properties, static_cast(flags), - (uintptr_t)image_format, (uintptr_t)image_desc, (uintptr_t)host_ptr, - (uintptr_t)errcode_ret); + ANGLE_UNSAFE_TODO(CL_EVENT(CreateImageWithProperties, + "context = 0x%016" PRIxPTR ", properties = 0x%016" PRIxPTR + ", flags = %llu, image_format = 0x%016" PRIxPTR + ", image_desc = 0x%016" PRIxPTR ", host_ptr = 0x%016" PRIxPTR + ", errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, (uintptr_t)properties, + static_cast(flags), (uintptr_t)image_format, + (uintptr_t)image_desc, (uintptr_t)host_ptr, (uintptr_t)errcode_ret)); MemFlags flagsPacked = PackParam(flags); @@ -2808,6 +2873,93 @@ cl_mem CL_API_CALL clCreateImageWithProperties(cl_context context, return object; } +// cl_arm_import_memory +cl_mem CL_API_CALL clImportMemoryARM(cl_context context, + cl_mem_flags flags, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret) +{ + ANGLE_UNSAFE_TODO( + CL_EVENT(ImportMemoryARM, + "context = 0x%016" PRIxPTR ", flags = %llu, properties = 0x%016" PRIxPTR + ", memory = 0x%016" PRIxPTR ", size = %zu, errcode_ret = 0x%016" PRIxPTR "", + (uintptr_t)context, static_cast(flags), (uintptr_t)properties, + (uintptr_t)memory, size, (uintptr_t)errcode_ret)); + + MemFlags flagsPacked = PackParam(flags); + + ANGLE_CL_VALIDATE_ERRCODE_RET(ImportMemoryARM, context, flagsPacked, properties, memory, size); + + cl::gClErrorTls = CL_SUCCESS; + cl_mem object = ImportMemoryARM(context, flagsPacked, properties, memory, size); + + ASSERT((cl::gClErrorTls == CL_SUCCESS) == (object != nullptr)); + if (errcode_ret != nullptr) + { + *errcode_ret = cl::gClErrorTls; + } + ANGLE_CAPTURE_CL(ImportMemoryARM, true, context, flagsPacked, properties, memory, size, + errcode_ret, object); + return object; +} + +// cl_khr_external_memory +cl_int CL_API_CALL clEnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) +{ + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueAcquireExternalMemObjectsKHR, + "command_queue = 0x%016" PRIxPTR ", num_mem_objects = %u, mem_objects = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_mem_objects, (uintptr_t)mem_objects, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); + + ANGLE_CL_VALIDATE_ERROR(EnqueueAcquireExternalMemObjectsKHR, command_queue, num_mem_objects, + mem_objects, num_events_in_wait_list, event_wait_list, event); + + cl::gClErrorTls = CL_SUCCESS; + cl_int returnValue = + EnqueueAcquireExternalMemObjectsKHR(command_queue, num_mem_objects, mem_objects, + num_events_in_wait_list, event_wait_list, event); + ANGLE_CAPTURE_CL(EnqueueAcquireExternalMemObjectsKHR, true, command_queue, num_mem_objects, + mem_objects, num_events_in_wait_list, event_wait_list, event, returnValue); + return returnValue; +} + +cl_int CL_API_CALL clEnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) +{ + ANGLE_UNSAFE_TODO(CL_EVENT( + EnqueueReleaseExternalMemObjectsKHR, + "command_queue = 0x%016" PRIxPTR ", num_mem_objects = %u, mem_objects = 0x%016" PRIxPTR + ", num_events_in_wait_list = %u, event_wait_list = 0x%016" PRIxPTR + ", event = 0x%016" PRIxPTR "", + (uintptr_t)command_queue, num_mem_objects, (uintptr_t)mem_objects, num_events_in_wait_list, + (uintptr_t)event_wait_list, (uintptr_t)event)); + + ANGLE_CL_VALIDATE_ERROR(EnqueueReleaseExternalMemObjectsKHR, command_queue, num_mem_objects, + mem_objects, num_events_in_wait_list, event_wait_list, event); + + cl::gClErrorTls = CL_SUCCESS; + cl_int returnValue = + EnqueueReleaseExternalMemObjectsKHR(command_queue, num_mem_objects, mem_objects, + num_events_in_wait_list, event_wait_list, event); + ANGLE_CAPTURE_CL(EnqueueReleaseExternalMemObjectsKHR, true, command_queue, num_mem_objects, + mem_objects, num_events_in_wait_list, event_wait_list, event, returnValue); + return returnValue; +} + // cl_khr_icd cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *platforms, @@ -2815,9 +2967,10 @@ cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, { InitBackEnds(true); - CL_EVENT(IcdGetPlatformIDsKHR, - "num_entries = %u, platforms = 0x%016" PRIxPTR ", num_platforms = 0x%016" PRIxPTR "", - num_entries, (uintptr_t)platforms, (uintptr_t)num_platforms); + ANGLE_UNSAFE_TODO(CL_EVENT(IcdGetPlatformIDsKHR, + "num_entries = %u, platforms = 0x%016" PRIxPTR + ", num_platforms = 0x%016" PRIxPTR "", + num_entries, (uintptr_t)platforms, (uintptr_t)num_platforms)); ANGLE_CL_VALIDATE_ERROR(IcdGetPlatformIDsKHR, num_entries, platforms, num_platforms); @@ -2828,4 +2981,33 @@ cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, return returnValue; } +void *CL_API_CALL clIcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, + const char *func_name) +{ + ANGLE_UNSAFE_TODO(CL_EVENT(IcdGetFunctionAddressForPlatformKHR, + "platform = 0x%016" PRIxPTR ", func_name = 0x%016" PRIxPTR "", + (uintptr_t)platform, (uintptr_t)func_name)); + + cl::gClErrorTls = CL_SUCCESS; + ANGLE_CL_VALIDATE_POINTER(IcdGetFunctionAddressForPlatformKHR, platform, func_name); + + void *returnValue = IcdGetFunctionAddressForPlatformKHR(platform, func_name); + ANGLE_CAPTURE_CL(IcdGetFunctionAddressForPlatformKHR, true, platform, func_name, returnValue); + return returnValue; +} + +cl_int CL_API_CALL clIcdSetPlatformDispatchDataKHR(cl_platform_id platform, void *dispatch_data) +{ + ANGLE_UNSAFE_TODO(CL_EVENT(IcdSetPlatformDispatchDataKHR, + "platform = 0x%016" PRIxPTR ", dispatch_data = 0x%016" PRIxPTR "", + (uintptr_t)platform, (uintptr_t)dispatch_data)); + + ANGLE_CL_VALIDATE_ERROR(IcdSetPlatformDispatchDataKHR, platform, dispatch_data); + + cl::gClErrorTls = CL_SUCCESS; + cl_int returnValue = IcdSetPlatformDispatchDataKHR(platform, dispatch_data); + ANGLE_CAPTURE_CL(IcdSetPlatformDispatchDataKHR, true, platform, dispatch_data, returnValue); + return returnValue; +} + } // namespace cl diff --git a/src/libGLESv2/entry_points_cl_autogen.h b/src/libGLESv2/entry_points_cl_autogen.h index c867da40f72..7d327578485 100644 --- a/src/libGLESv2/entry_points_cl_autogen.h +++ b/src/libGLESv2/entry_points_cl_autogen.h @@ -609,10 +609,35 @@ cl_mem CL_API_CALL clCreateImageWithProperties(cl_context context, void *host_ptr, cl_int *errcode_ret); +// cl_arm_import_memory +cl_mem CL_API_CALL clImportMemoryARM(cl_context context, + cl_mem_flags flags, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret); + +// cl_khr_external_memory +cl_int CL_API_CALL clEnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event); +cl_int CL_API_CALL clEnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event); + // cl_khr_icd cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms); +void *CL_API_CALL clIcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, + const char *func_name); +cl_int CL_API_CALL clIcdSetPlatformDispatchDataKHR(cl_platform_id platform, void *dispatch_data); } // namespace cl #endif // LIBGLESV2_ENTRY_POINTS_CL_AUTOGEN_H_ diff --git a/src/libGLESv2/entry_points_cl_utils.h b/src/libGLESv2/entry_points_cl_utils.h index bb03d4b9e27..d77fba5a0e3 100644 --- a/src/libGLESv2/entry_points_cl_utils.h +++ b/src/libGLESv2/entry_points_cl_utils.h @@ -16,10 +16,20 @@ #include #include +#ifdef ANDROID +# include +#endif + #if defined(ANGLE_ENABLE_DEBUG_TRACE) -# define CL_EVENT(entryPoint, ...) \ - std::printf("CL " #entryPoint ": " __VA_ARGS__); \ - std::printf("\n") +# if defined(ANDROID) +# define CL_EVENT(entryPoint, ...) \ + __android_log_print(ANDROID_LOG_INFO, "ANGLE-CL", "cl" #entryPoint ": " __VA_ARGS__) +# else +# define CL_EVENT(entryPoint, ...) \ + std::printf("cl" #entryPoint ": " __VA_ARGS__); \ + std::printf("\n") + +# endif #else # define CL_EVENT(entryPoint, ...) (void(0)) #endif diff --git a/src/libGLESv2/entry_points_egl_autogen.cpp b/src/libGLESv2/entry_points_egl_autogen.cpp index d87c5036a8e..710859899fc 100644 --- a/src/libGLESv2/entry_points_egl_autogen.cpp +++ b/src/libGLESv2/entry_points_egl_autogen.cpp @@ -36,11 +36,12 @@ EGLBoolean EGLAPIENTRY EGL_ChooseConfig(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ChooseConfig, - "dpy = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR - ", configs = 0x%016" PRIxPTR ", config_size = %d, num_config = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)attrib_list, (uintptr_t)configs, config_size, - (uintptr_t)num_config); + ANGLE_UNSAFE_TODO(EGL_EVENT(ChooseConfig, + "dpy = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR + ", configs = 0x%016" PRIxPTR + ", config_size = %d, num_config = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)attrib_list, (uintptr_t)configs, + config_size, (uintptr_t)num_config)); egl::Display *dpyPacked = PackParam(dpy); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -78,10 +79,10 @@ EGLBoolean EGLAPIENTRY EGL_CopyBuffers(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CopyBuffers, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", target = 0x%016" PRIxPTR - "", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)target); + ANGLE_UNSAFE_TODO(EGL_EVENT(CopyBuffers, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", target = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)target)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -117,11 +118,11 @@ EGLContext EGLAPIENTRY EGL_CreateContext(EGLDisplay dpy, EGLContext returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateContext, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", share_context = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)share_context, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreateContext, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", share_context = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)share_context, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -161,10 +162,10 @@ EGLSurface EGLAPIENTRY EGL_CreatePbufferSurface(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePbufferSurface, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreatePbufferSurface, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -203,10 +204,11 @@ EGLSurface EGLAPIENTRY EGL_CreatePixmapSurface(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePixmapSurface, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", pixmap = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)pixmap, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreatePixmapSurface, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR + ", pixmap = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)pixmap, + (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -246,10 +248,11 @@ EGLSurface EGLAPIENTRY EGL_CreateWindowSurface(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateWindowSurface, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", win = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)win, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreateWindowSurface, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR + ", win = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)win, + (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -286,8 +289,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroyContext(EGLDisplay dpy, EGLContext ctx) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(DestroyContext, "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)ctx); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroyContext, + "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)ctx)); egl::Display *dpyPacked = PackParam(dpy); gl::ContextID ctxPacked = PackParam(ctx); @@ -320,8 +324,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroySurface(EGLDisplay dpy, EGLSurface surface) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(DestroySurface, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroySurface, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -357,10 +362,11 @@ EGLBoolean EGLAPIENTRY EGL_GetConfigAttrib(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetConfigAttrib, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetConfigAttrib, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, attribute, + (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -397,10 +403,11 @@ EGLBoolean EGLAPIENTRY EGL_GetConfigs(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetConfigs, - "dpy = 0x%016" PRIxPTR ", configs = 0x%016" PRIxPTR - ", config_size = %d, num_config = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)configs, config_size, (uintptr_t)num_config); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetConfigs, + "dpy = 0x%016" PRIxPTR ", configs = 0x%016" PRIxPTR + ", config_size = %d, num_config = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)configs, config_size, + (uintptr_t)num_config)); egl::Display *dpyPacked = PackParam(dpy); @@ -432,7 +439,7 @@ EGLDisplay EGLAPIENTRY EGL_GetCurrentDisplay() ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); EGLDisplay returnValue; - EGL_EVENT(GetCurrentDisplay, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetCurrentDisplay, "")); if (IsEGLValidationEnabled()) { @@ -457,7 +464,7 @@ EGLSurface EGLAPIENTRY EGL_GetCurrentSurface(EGLint readdraw) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); EGLSurface returnValue; - EGL_EVENT(GetCurrentSurface, "readdraw = %d", readdraw); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetCurrentSurface, "readdraw = %d", readdraw)); if (IsEGLValidationEnabled()) { @@ -483,7 +490,8 @@ EGLDisplay EGLAPIENTRY EGL_GetDisplay(EGLNativeDisplayType display_id) EGLDisplay returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetDisplay, "display_id = 0x%016" PRIxPTR "", (uintptr_t)display_id); + ANGLE_UNSAFE_TODO( + EGL_EVENT(GetDisplay, "display_id = 0x%016" PRIxPTR "", (uintptr_t)display_id)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetDisplay, thread); @@ -511,7 +519,7 @@ EGLint EGLAPIENTRY EGL_GetError() ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); EGLint returnValue; - EGL_EVENT(GetError, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetError, "")); if (IsEGLValidationEnabled()) { @@ -537,7 +545,8 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY EGL_GetProcAddress(const ch __eglMustCastToProperFunctionPointerType returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetProcAddress, "procname = 0x%016" PRIxPTR "", (uintptr_t)procname); + ANGLE_UNSAFE_TODO( + EGL_EVENT(GetProcAddress, "procname = 0x%016" PRIxPTR "", (uintptr_t)procname)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetProcAddress, thread); @@ -567,9 +576,10 @@ EGLBoolean EGLAPIENTRY EGL_Initialize(EGLDisplay dpy, EGLint *major, EGLint *min EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK(); - EGL_EVENT(Initialize, - "dpy = 0x%016" PRIxPTR ", major = 0x%016" PRIxPTR ", minor = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)major, (uintptr_t)minor); + ANGLE_UNSAFE_TODO(EGL_EVENT(Initialize, + "dpy = 0x%016" PRIxPTR ", major = 0x%016" PRIxPTR + ", minor = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)major, (uintptr_t)minor)); egl::Display *dpyPacked = PackParam(dpy); @@ -604,10 +614,11 @@ EGLBoolean EGLAPIENTRY EGL_MakeCurrent(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(MakeCurrent, - "dpy = 0x%016" PRIxPTR ", draw = 0x%016" PRIxPTR ", read = 0x%016" PRIxPTR - ", ctx = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)draw, (uintptr_t)read, (uintptr_t)ctx); + ANGLE_UNSAFE_TODO(EGL_EVENT(MakeCurrent, + "dpy = 0x%016" PRIxPTR ", draw = 0x%016" PRIxPTR + ", read = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)draw, (uintptr_t)read, + (uintptr_t)ctx)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID drawPacked = PackParam(draw); @@ -646,10 +657,10 @@ EGLBoolean EGLAPIENTRY EGL_QueryContext(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryContext, - "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)ctx, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryContext, + "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)ctx, attribute, (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); gl::ContextID ctxPacked = PackParam(ctx); @@ -683,7 +694,8 @@ const char *EGLAPIENTRY EGL_QueryString(EGLDisplay dpy, EGLint name) const char *returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryString, "dpy = 0x%016" PRIxPTR ", name = %d", (uintptr_t)dpy, name); + ANGLE_UNSAFE_TODO( + EGL_EVENT(QueryString, "dpy = 0x%016" PRIxPTR ", name = %d", (uintptr_t)dpy, name)); egl::Display *dpyPacked = PackParam(dpy); @@ -712,7 +724,7 @@ EGLBoolean EGLAPIENTRY EGL_QuerySurface(EGLDisplay dpy, EGLint attribute, EGLint *value) { - if (attribute == EGL_BUFFER_AGE_EXT) + if (attribute == EGL_BUFFER_AGE_EXT || attribute == EGL_SURFACE_COMPRESSION_EXT) { ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(dpy, surface)); } @@ -721,10 +733,11 @@ EGLBoolean EGLAPIENTRY EGL_QuerySurface(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QuerySurface, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QuerySurface, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, attribute, + (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -758,8 +771,9 @@ EGLBoolean EGLAPIENTRY EGL_SwapBuffers(EGLDisplay dpy, EGLSurface surface) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SwapBuffers, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface); + ANGLE_UNSAFE_TODO(EGL_EVENT(SwapBuffers, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -792,7 +806,7 @@ EGLBoolean EGLAPIENTRY EGL_Terminate(EGLDisplay dpy) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK(); - EGL_EVENT(Terminate, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy); + ANGLE_UNSAFE_TODO(EGL_EVENT(Terminate, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy)); egl::Display *dpyPacked = PackParam(dpy); @@ -824,7 +838,7 @@ EGLBoolean EGLAPIENTRY EGL_WaitGL() EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(WaitGL, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(WaitGL, "")); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitGL, thread); @@ -853,7 +867,7 @@ EGLBoolean EGLAPIENTRY EGL_WaitNative(EGLint engine) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(WaitNative, "engine = %d", engine); + ANGLE_UNSAFE_TODO(EGL_EVENT(WaitNative, "engine = %d", engine)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitNative, thread); @@ -883,8 +897,9 @@ EGLBoolean EGLAPIENTRY EGL_BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLi EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(BindTexImage, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", buffer = %d", - (uintptr_t)dpy, (uintptr_t)surface, buffer); + ANGLE_UNSAFE_TODO(EGL_EVENT( + BindTexImage, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", buffer = %d", + (uintptr_t)dpy, (uintptr_t)surface, buffer)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -918,9 +933,9 @@ EGLBoolean EGLAPIENTRY EGL_ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, E EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ReleaseTexImage, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", buffer = %d", - (uintptr_t)dpy, (uintptr_t)surface, buffer); + ANGLE_UNSAFE_TODO(EGL_EVENT( + ReleaseTexImage, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", buffer = %d", + (uintptr_t)dpy, (uintptr_t)surface, buffer)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -957,10 +972,10 @@ EGLBoolean EGLAPIENTRY EGL_SurfaceAttrib(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SurfaceAttrib, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", attribute = %d, value = %d", - (uintptr_t)dpy, (uintptr_t)surface, attribute, value); + ANGLE_UNSAFE_TODO(EGL_EVENT(SurfaceAttrib, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", attribute = %d, value = %d", + (uintptr_t)dpy, (uintptr_t)surface, attribute, value)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -994,7 +1009,8 @@ EGLBoolean EGLAPIENTRY EGL_SwapInterval(EGLDisplay dpy, EGLint interval) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SwapInterval, "dpy = 0x%016" PRIxPTR ", interval = %d", (uintptr_t)dpy, interval); + ANGLE_UNSAFE_TODO(EGL_EVENT(SwapInterval, "dpy = 0x%016" PRIxPTR ", interval = %d", + (uintptr_t)dpy, interval)); egl::Display *dpyPacked = PackParam(dpy); @@ -1027,7 +1043,7 @@ EGLBoolean EGLAPIENTRY EGL_BindAPI(EGLenum api) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(BindAPI, "api = 0x%X", api); + ANGLE_UNSAFE_TODO(EGL_EVENT(BindAPI, "api = 0x%X", api)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(BindAPI, thread); @@ -1060,11 +1076,11 @@ EGLSurface EGLAPIENTRY EGL_CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePbufferFromClientBuffer, - "dpy = 0x%016" PRIxPTR ", buftype = 0x%X, buffer = 0x%016" PRIxPTR - ", config = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, buftype, (uintptr_t)buffer, (uintptr_t)config, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreatePbufferFromClientBuffer, + "dpy = 0x%016" PRIxPTR ", buftype = 0x%X, buffer = 0x%016" PRIxPTR + ", config = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, buftype, (uintptr_t)buffer, (uintptr_t)config, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -1102,7 +1118,7 @@ EGLenum EGLAPIENTRY EGL_QueryAPI() EGLenum returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryAPI, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryAPI, "")); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(QueryAPI, thread); @@ -1131,7 +1147,7 @@ EGLBoolean EGLAPIENTRY EGL_ReleaseThread() EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK(); - EGL_EVENT(ReleaseThread, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(ReleaseThread, "")); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(ReleaseThread, thread); @@ -1160,7 +1176,7 @@ EGLBoolean EGLAPIENTRY EGL_WaitClient() EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(WaitClient, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(WaitClient, "")); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitClient, thread); @@ -1189,7 +1205,7 @@ EGLContext EGLAPIENTRY EGL_GetCurrentContext() ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); EGLContext returnValue; - EGL_EVENT(GetCurrentContext, ""); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetCurrentContext, "")); if (IsEGLValidationEnabled()) { @@ -1216,9 +1232,10 @@ EGLint EGLAPIENTRY EGL_ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags EGLint returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(ClientWaitSync, - "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d, timeout = %llu", - (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast(timeout)); + ANGLE_UNSAFE_TODO(EGL_EVENT( + ClientWaitSync, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d, timeout = %llu", + (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast(timeout))); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -1256,11 +1273,11 @@ EGLImage EGLAPIENTRY EGL_CreateImage(EGLDisplay dpy, EGLImage returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateImage, - "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR - ", target = 0x%X, buffer = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)ctx, target, (uintptr_t)buffer, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreateImage, + "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR + ", target = 0x%X, buffer = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)ctx, target, (uintptr_t)buffer, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); gl::ContextID ctxPacked = PackParam(ctx); @@ -1300,11 +1317,11 @@ EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurface(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePlatformPixmapSurface, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", native_pixmap = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreatePlatformPixmapSurface, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", native_pixmap = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -1345,11 +1362,11 @@ EGLSurface EGLAPIENTRY EGL_CreatePlatformWindowSurface(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePlatformWindowSurface, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", native_window = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreatePlatformWindowSurface, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", native_window = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -1387,9 +1404,9 @@ EGLSync EGLAPIENTRY EGL_CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib EGLSync returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(CreateSync, - "dpy = 0x%016" PRIxPTR ", type = 0x%X, attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, type, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreateSync, "dpy = 0x%016" PRIxPTR ", type = 0x%X, attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, type, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -1424,8 +1441,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroyImage(EGLDisplay dpy, EGLImage image) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(DestroyImage, "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)image); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroyImage, + "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)image)); egl::Display *dpyPacked = PackParam(dpy); ImageID imagePacked = PackParam(image); @@ -1458,8 +1476,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroySync(EGLDisplay dpy, EGLSync sync) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(DestroySync, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", (uintptr_t)dpy, - (uintptr_t)sync); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroySync, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)sync)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -1494,10 +1513,10 @@ EGLDisplay EGLAPIENTRY EGL_GetPlatformDisplay(EGLenum platform, EGLDisplay returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetPlatformDisplay, - "platform = 0x%X, native_display = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - platform, (uintptr_t)native_display, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetPlatformDisplay, + "platform = 0x%X, native_display = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + platform, (uintptr_t)native_display, (uintptr_t)attrib_list)); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -1534,10 +1553,10 @@ EGLBoolean EGLAPIENTRY EGL_GetSyncAttrib(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(GetSyncAttrib, - "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetSyncAttrib, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -1571,8 +1590,9 @@ EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(WaitSync, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d", - (uintptr_t)dpy, (uintptr_t)sync, flags); + ANGLE_UNSAFE_TODO(EGL_EVENT(WaitSync, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d", + (uintptr_t)dpy, (uintptr_t)sync, flags)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); diff --git a/src/libGLESv2/entry_points_egl_ext_autogen.cpp b/src/libGLESv2/entry_points_egl_ext_autogen.cpp index 6a722f681f8..03bb224fe32 100644 --- a/src/libGLESv2/entry_points_egl_ext_autogen.cpp +++ b/src/libGLESv2/entry_points_egl_ext_autogen.cpp @@ -31,9 +31,10 @@ void EGLAPIENTRY EGL_SetBlobCacheFuncsANDROID(EGLDisplay dpy, ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SetBlobCacheFuncsANDROID, - "dpy = 0x%016" PRIxPTR ", set = 0x%016" PRIxPTR ", get = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)set, (uintptr_t)get); + ANGLE_UNSAFE_TODO(EGL_EVENT(SetBlobCacheFuncsANDROID, + "dpy = 0x%016" PRIxPTR ", set = 0x%016" PRIxPTR + ", get = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)set, (uintptr_t)get)); egl::Display *dpyPacked = PackParam(dpy); @@ -65,8 +66,8 @@ EGLClientBuffer EGLAPIENTRY EGL_CreateNativeClientBufferANDROID(const EGLint *at EGLClientBuffer returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateNativeClientBufferANDROID, "attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreateNativeClientBufferANDROID, + "attrib_list = 0x%016" PRIxPTR "", (uintptr_t)attrib_list)); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -103,9 +104,10 @@ EGLBoolean EGLAPIENTRY EGL_GetCompositorTimingSupportedANDROID(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetCompositorTimingSupportedANDROID, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", name = %d", (uintptr_t)dpy, - (uintptr_t)surface, name); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetCompositorTimingSupportedANDROID, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", name = %d", + (uintptr_t)dpy, (uintptr_t)surface, name)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -146,11 +148,12 @@ EGLBoolean EGLAPIENTRY EGL_GetCompositorTimingANDROID(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetCompositorTimingANDROID, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", numTimestamps = %d, names = 0x%016" PRIxPTR ", values = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, numTimestamps, (uintptr_t)names, - (uintptr_t)values); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetCompositorTimingANDROID, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", numTimestamps = %d, names = 0x%016" PRIxPTR + ", values = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, numTimestamps, + (uintptr_t)names, (uintptr_t)values)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -188,10 +191,10 @@ EGLBoolean EGLAPIENTRY EGL_GetNextFrameIdANDROID(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetNextFrameIdANDROID, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", frameId = 0x%016" PRIxPTR - "", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)frameId); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetNextFrameIdANDROID, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", frameId = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)frameId)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -227,9 +230,10 @@ EGLBoolean EGLAPIENTRY EGL_GetFrameTimestampSupportedANDROID(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetFrameTimestampSupportedANDROID, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", timestamp = %d", - (uintptr_t)dpy, (uintptr_t)surface, timestamp); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetFrameTimestampSupportedANDROID, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", timestamp = %d", + (uintptr_t)dpy, (uintptr_t)surface, timestamp)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -271,12 +275,13 @@ EGLBoolean EGLAPIENTRY EGL_GetFrameTimestampsANDROID(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetFrameTimestampsANDROID, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", frameId = %llu, numTimestamps = %d, timestamps = 0x%016" PRIxPTR - ", values = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, static_cast(frameId), - numTimestamps, (uintptr_t)timestamps, (uintptr_t)values); + ANGLE_UNSAFE_TODO( + EGL_EVENT(GetFrameTimestampsANDROID, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", frameId = %llu, numTimestamps = %d, timestamps = 0x%016" PRIxPTR + ", values = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, static_cast(frameId), + numTimestamps, (uintptr_t)timestamps, (uintptr_t)values)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -313,7 +318,8 @@ EGLClientBuffer EGLAPIENTRY EGL_GetNativeClientBufferANDROID(const struct AHardw EGLClientBuffer returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetNativeClientBufferANDROID, "buffer = 0x%016" PRIxPTR "", (uintptr_t)buffer); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetNativeClientBufferANDROID, "buffer = 0x%016" PRIxPTR "", + (uintptr_t)buffer)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetNativeClientBufferANDROID, thread); @@ -344,8 +350,9 @@ EGLint EGLAPIENTRY EGL_DupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) EGLint returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(DupNativeFenceFDANDROID, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)sync); + ANGLE_UNSAFE_TODO(EGL_EVENT(DupNativeFenceFDANDROID, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)sync)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -382,9 +389,10 @@ EGLBoolean EGLAPIENTRY EGL_PresentationTimeANDROID(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(PresentationTimeANDROID, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", time = %llu", - (uintptr_t)dpy, (uintptr_t)surface, static_cast(time)); + ANGLE_UNSAFE_TODO( + EGL_EVENT(PresentationTimeANDROID, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", time = %llu", + (uintptr_t)dpy, (uintptr_t)surface, static_cast(time))); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -421,10 +429,10 @@ EGLDeviceEXT EGLAPIENTRY EGL_CreateDeviceANGLE(EGLint device_type, EGLDeviceEXT returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateDeviceANGLE, - "device_type = %d, native_device = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - device_type, (uintptr_t)native_device, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreateDeviceANGLE, + "device_type = %d, native_device = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + device_type, (uintptr_t)native_device, (uintptr_t)attrib_list)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreateDeviceANGLE, thread); @@ -455,7 +463,8 @@ EGLBoolean EGLAPIENTRY EGL_ReleaseDeviceANGLE(EGLDeviceEXT device) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ReleaseDeviceANGLE, "device = 0x%016" PRIxPTR "", (uintptr_t)device); + ANGLE_UNSAFE_TODO( + EGL_EVENT(ReleaseDeviceANGLE, "device = 0x%016" PRIxPTR "", (uintptr_t)device)); egl::Device *devicePacked = PackParam(device); @@ -485,7 +494,7 @@ void EGLAPIENTRY EGL_LockVulkanQueueANGLE(EGLDisplay dpy) Thread *thread = egl::GetCurrentThread(); ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - EGL_EVENT(LockVulkanQueueANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy); + ANGLE_UNSAFE_TODO(EGL_EVENT(LockVulkanQueueANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy)); egl::Display *dpyPacked = PackParam(dpy); @@ -512,7 +521,7 @@ void EGLAPIENTRY EGL_UnlockVulkanQueueANGLE(EGLDisplay dpy) Thread *thread = egl::GetCurrentThread(); ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - EGL_EVENT(UnlockVulkanQueueANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy); + ANGLE_UNSAFE_TODO(EGL_EVENT(UnlockVulkanQueueANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy)); egl::Display *dpyPacked = PackParam(dpy); @@ -541,9 +550,9 @@ void EGLAPIENTRY EGL_AcquireExternalContextANGLE(EGLDisplay dpy, EGLSurface draw ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(AcquireExternalContextANGLE, - "dpy = 0x%016" PRIxPTR ", drawAndRead = 0x%016" PRIxPTR "", (uintptr_t)dpy, - (uintptr_t)drawAndRead); + ANGLE_UNSAFE_TODO(EGL_EVENT(AcquireExternalContextANGLE, + "dpy = 0x%016" PRIxPTR ", drawAndRead = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)drawAndRead)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID drawAndReadPacked = PackParam(drawAndRead); @@ -574,7 +583,8 @@ void EGLAPIENTRY EGL_ReleaseExternalContextANGLE(EGLDisplay dpy) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ReleaseExternalContextANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy); + ANGLE_UNSAFE_TODO( + EGL_EVENT(ReleaseExternalContextANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy)); egl::Display *dpyPacked = PackParam(dpy); @@ -606,8 +616,9 @@ const char *EGLAPIENTRY EGL_QueryStringiANGLE(EGLDisplay dpy, EGLint name, EGLin const char *returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryStringiANGLE, "dpy = 0x%016" PRIxPTR ", name = %d, index = %d", - (uintptr_t)dpy, name, index); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryStringiANGLE, + "dpy = 0x%016" PRIxPTR ", name = %d, index = %d", + (uintptr_t)dpy, name, index)); egl::Display *dpyPacked = PackParam(dpy); @@ -641,9 +652,10 @@ EGLBoolean EGLAPIENTRY EGL_QueryDisplayAttribANGLE(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDisplayAttribANGLE, - "dpy = 0x%016" PRIxPTR ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryDisplayAttribANGLE, + "dpy = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, attribute, (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); @@ -677,8 +689,9 @@ void *EGLAPIENTRY EGL_CopyMetalSharedEventANGLE(EGLDisplay dpy, EGLSyncKHR sync) void *returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(CopyMetalSharedEventANGLE, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)sync); + ANGLE_UNSAFE_TODO(EGL_EVENT(CopyMetalSharedEventANGLE, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)sync)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -712,7 +725,8 @@ void EGLAPIENTRY EGL_SetValidationEnabledANGLE(EGLBoolean validationState) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SetValidationEnabledANGLE, "validationState = %u", validationState); + ANGLE_UNSAFE_TODO( + EGL_EVENT(SetValidationEnabledANGLE, "validationState = %u", validationState)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(SetValidationEnabledANGLE, thread); @@ -741,8 +755,9 @@ void EGLAPIENTRY EGL_ReleaseHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ReleaseHighPowerGPUANGLE, "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)ctx); + ANGLE_UNSAFE_TODO(EGL_EVENT(ReleaseHighPowerGPUANGLE, + "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)ctx)); egl::Display *dpyPacked = PackParam(dpy); gl::ContextID ctxPacked = PackParam(ctx); @@ -773,8 +788,9 @@ void EGLAPIENTRY EGL_ReacquireHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ReacquireHighPowerGPUANGLE, "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)ctx); + ANGLE_UNSAFE_TODO(EGL_EVENT(ReacquireHighPowerGPUANGLE, + "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)ctx)); egl::Display *dpyPacked = PackParam(dpy); gl::ContextID ctxPacked = PackParam(ctx); @@ -805,7 +821,8 @@ void EGLAPIENTRY EGL_HandleGPUSwitchANGLE(EGLDisplay dpy) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(HandleGPUSwitchANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy); + ANGLE_UNSAFE_TODO( + EGL_EVENT(HandleGPUSwitchANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy)); egl::Display *dpyPacked = PackParam(dpy); @@ -835,8 +852,9 @@ void EGLAPIENTRY EGL_ForceGPUSwitchANGLE(EGLDisplay dpy, EGLint gpuIDHigh, EGLin ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ForceGPUSwitchANGLE, "dpy = 0x%016" PRIxPTR ", gpuIDHigh = %d, gpuIDLow = %d", - (uintptr_t)dpy, gpuIDHigh, gpuIDLow); + ANGLE_UNSAFE_TODO(EGL_EVENT(ForceGPUSwitchANGLE, + "dpy = 0x%016" PRIxPTR ", gpuIDHigh = %d, gpuIDLow = %d", + (uintptr_t)dpy, gpuIDHigh, gpuIDLow)); egl::Display *dpyPacked = PackParam(dpy); @@ -868,8 +886,9 @@ EGLBoolean EGLAPIENTRY EGL_PrepareSwapBuffersANGLE(EGLDisplay dpy, EGLSurface su EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(PrepareSwapBuffersANGLE, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface); + ANGLE_UNSAFE_TODO(EGL_EVENT(PrepareSwapBuffersANGLE, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -904,8 +923,9 @@ EGLint EGLAPIENTRY EGL_ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib EGLint returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ProgramCacheGetAttribANGLE, "dpy = 0x%016" PRIxPTR ", attrib = 0x%X", - (uintptr_t)dpy, attrib); + ANGLE_UNSAFE_TODO(EGL_EVENT(ProgramCacheGetAttribANGLE, + "dpy = 0x%016" PRIxPTR ", attrib = 0x%X", (uintptr_t)dpy, + attrib)); egl::Display *dpyPacked = PackParam(dpy); @@ -941,12 +961,12 @@ void EGLAPIENTRY EGL_ProgramCacheQueryANGLE(EGLDisplay dpy, ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ProgramCacheQueryANGLE, - "dpy = 0x%016" PRIxPTR ", index = %d, key = 0x%016" PRIxPTR - ", keysize = 0x%016" PRIxPTR ", binary = 0x%016" PRIxPTR - ", binarysize = 0x%016" PRIxPTR "", - (uintptr_t)dpy, index, (uintptr_t)key, (uintptr_t)keysize, (uintptr_t)binary, - (uintptr_t)binarysize); + ANGLE_UNSAFE_TODO(EGL_EVENT(ProgramCacheQueryANGLE, + "dpy = 0x%016" PRIxPTR ", index = %d, key = 0x%016" PRIxPTR + ", keysize = 0x%016" PRIxPTR ", binary = 0x%016" PRIxPTR + ", binarysize = 0x%016" PRIxPTR "", + (uintptr_t)dpy, index, (uintptr_t)key, (uintptr_t)keysize, + (uintptr_t)binary, (uintptr_t)binarysize)); egl::Display *dpyPacked = PackParam(dpy); @@ -982,10 +1002,11 @@ void EGLAPIENTRY EGL_ProgramCachePopulateANGLE(EGLDisplay dpy, ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ProgramCachePopulateANGLE, - "dpy = 0x%016" PRIxPTR ", key = 0x%016" PRIxPTR - ", keysize = %d, binary = 0x%016" PRIxPTR ", binarysize = %d", - (uintptr_t)dpy, (uintptr_t)key, keysize, (uintptr_t)binary, binarysize); + ANGLE_UNSAFE_TODO(EGL_EVENT(ProgramCachePopulateANGLE, + "dpy = 0x%016" PRIxPTR ", key = 0x%016" PRIxPTR + ", keysize = %d, binary = 0x%016" PRIxPTR ", binarysize = %d", + (uintptr_t)dpy, (uintptr_t)key, keysize, (uintptr_t)binary, + binarysize)); egl::Display *dpyPacked = PackParam(dpy); @@ -1018,8 +1039,9 @@ EGLint EGLAPIENTRY EGL_ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGL EGLint returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ProgramCacheResizeANGLE, "dpy = 0x%016" PRIxPTR ", limit = %d, mode = %d", - (uintptr_t)dpy, limit, mode); + ANGLE_UNSAFE_TODO(EGL_EVENT(ProgramCacheResizeANGLE, + "dpy = 0x%016" PRIxPTR ", limit = %d, mode = %d", + (uintptr_t)dpy, limit, mode)); egl::Display *dpyPacked = PackParam(dpy); @@ -1056,10 +1078,11 @@ EGLBoolean EGLAPIENTRY EGL_QuerySurfacePointerANGLE(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QuerySurfacePointerANGLE, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QuerySurfacePointerANGLE, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, attribute, + (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -1097,10 +1120,10 @@ EGLBoolean EGLAPIENTRY EGL_CreateStreamProducerD3DTextureANGLE(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateStreamProducerD3DTextureANGLE, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreateStreamProducerD3DTextureANGLE, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -1141,10 +1164,11 @@ EGLBoolean EGLAPIENTRY EGL_StreamPostD3DTextureANGLE(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(StreamPostD3DTextureANGLE, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR ", texture = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)texture, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + StreamPostD3DTextureANGLE, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR ", texture = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)texture, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -1173,46 +1197,6 @@ EGLBoolean EGLAPIENTRY EGL_StreamPostD3DTextureANGLE(EGLDisplay dpy, return returnValue; } -// EGL_ANGLE_swap_with_frame_token -EGLBoolean EGLAPIENTRY EGL_SwapBuffersWithFrameTokenANGLE(EGLDisplay dpy, - EGLSurface surface, - EGLFrameTokenANGLE frametoken) -{ - ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(dpy, surface)); - Thread *thread = egl::GetCurrentThread(); - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - EGLBoolean returnValue; - { - ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SwapBuffersWithFrameTokenANGLE, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", frametoken = 0x%llX", - (uintptr_t)dpy, (uintptr_t)surface, static_cast(frametoken)); - - egl::Display *dpyPacked = PackParam(dpy); - SurfaceID surfacePacked = PackParam(surface); - - { - ANGLE_EGL_SCOPED_CONTEXT_LOCK(SwapBuffersWithFrameTokenANGLE, thread, dpyPacked); - if (IsEGLValidationEnabled()) - { - ANGLE_EGL_VALIDATE(thread, SwapBuffersWithFrameTokenANGLE, - GetDisplayIfValid(dpyPacked), EGLBoolean, dpyPacked, - surfacePacked, frametoken); - } - else - { - } - - returnValue = - SwapBuffersWithFrameTokenANGLE(thread, dpyPacked, surfacePacked, frametoken); - } - - ANGLE_CAPTURE_EGL(SwapBuffersWithFrameTokenANGLE, true, thread, dpyPacked, surfacePacked, - frametoken, returnValue); - } - egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); - return returnValue; -} // EGL_ANGLE_sync_control_rate EGLBoolean EGLAPIENTRY EGL_GetMscRateANGLE(EGLDisplay dpy, @@ -1226,10 +1210,11 @@ EGLBoolean EGLAPIENTRY EGL_GetMscRateANGLE(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetMscRateANGLE, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", numerator = 0x%016" PRIxPTR - ", denominator = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)numerator, (uintptr_t)denominator); + ANGLE_UNSAFE_TODO(EGL_EVENT( + GetMscRateANGLE, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", numerator = 0x%016" PRIxPTR + ", denominator = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)numerator, (uintptr_t)denominator)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -1267,11 +1252,12 @@ EGLBoolean EGLAPIENTRY EGL_ExportVkImageANGLE(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(ExportVkImageANGLE, - "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR ", vk_image = 0x%016" PRIxPTR - ", vk_image_create_info = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)image, (uintptr_t)vk_image, - (uintptr_t)vk_image_create_info); + ANGLE_UNSAFE_TODO(EGL_EVENT(ExportVkImageANGLE, + "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR + ", vk_image = 0x%016" PRIxPTR + ", vk_image_create_info = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)image, (uintptr_t)vk_image, + (uintptr_t)vk_image_create_info)); egl::Display *dpyPacked = PackParam(dpy); ImageID imagePacked = PackParam(image); @@ -1307,7 +1293,8 @@ void EGLAPIENTRY EGL_WaitUntilWorkScheduledANGLE(EGLDisplay dpy) ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(WaitUntilWorkScheduledANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy); + ANGLE_UNSAFE_TODO( + EGL_EVENT(WaitUntilWorkScheduledANGLE, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy)); egl::Display *dpyPacked = PackParam(dpy); @@ -1343,11 +1330,11 @@ EGLBoolean EGLAPIENTRY EGL_GetSyncValuesCHROMIUM(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetSyncValuesCHROMIUM, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", ust = 0x%016" PRIxPTR - ", msc = 0x%016" PRIxPTR ", sbc = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)ust, (uintptr_t)msc, - (uintptr_t)sbc); + ANGLE_UNSAFE_TODO(EGL_EVENT( + GetSyncValuesCHROMIUM, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", ust = 0x%016" PRIxPTR + ", msc = 0x%016" PRIxPTR ", sbc = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)ust, (uintptr_t)msc, (uintptr_t)sbc)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -1384,9 +1371,10 @@ EGLBoolean EGLAPIENTRY EGL_QueryDeviceAttribEXT(EGLDeviceEXT device, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDeviceAttribEXT, - "device = 0x%016" PRIxPTR ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)device, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryDeviceAttribEXT, + "device = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)device, attribute, (uintptr_t)value)); egl::Device *devicePacked = PackParam(device); @@ -1419,8 +1407,8 @@ const char *EGLAPIENTRY EGL_QueryDeviceStringEXT(EGLDeviceEXT device, EGLint nam const char *returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDeviceStringEXT, "device = 0x%016" PRIxPTR ", name = %d", (uintptr_t)device, - name); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryDeviceStringEXT, "device = 0x%016" PRIxPTR ", name = %d", + (uintptr_t)device, name)); egl::Device *devicePacked = PackParam(device); @@ -1452,9 +1440,10 @@ EGLBoolean EGLAPIENTRY EGL_QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribut EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDisplayAttribEXT, - "dpy = 0x%016" PRIxPTR ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryDisplayAttribEXT, + "dpy = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, attribute, (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); @@ -1491,10 +1480,11 @@ EGLBoolean EGLAPIENTRY EGL_QueryDmaBufFormatsEXT(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDmaBufFormatsEXT, - "dpy = 0x%016" PRIxPTR ", max_formats = %d, formats = 0x%016" PRIxPTR - ", num_formats = 0x%016" PRIxPTR "", - (uintptr_t)dpy, max_formats, (uintptr_t)formats, (uintptr_t)num_formats); + ANGLE_UNSAFE_TODO( + EGL_EVENT(QueryDmaBufFormatsEXT, + "dpy = 0x%016" PRIxPTR ", max_formats = %d, formats = 0x%016" PRIxPTR + ", num_formats = 0x%016" PRIxPTR "", + (uintptr_t)dpy, max_formats, (uintptr_t)formats, (uintptr_t)num_formats)); egl::Display *dpyPacked = PackParam(dpy); @@ -1533,12 +1523,12 @@ EGLBoolean EGLAPIENTRY EGL_QueryDmaBufModifiersEXT(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDmaBufModifiersEXT, - "dpy = 0x%016" PRIxPTR - ", format = %d, max_modifiers = %d, modifiers = 0x%016" PRIxPTR - ", external_only = 0x%016" PRIxPTR ", num_modifiers = 0x%016" PRIxPTR "", - (uintptr_t)dpy, format, max_modifiers, (uintptr_t)modifiers, - (uintptr_t)external_only, (uintptr_t)num_modifiers); + ANGLE_UNSAFE_TODO(EGL_EVENT( + QueryDmaBufModifiersEXT, + "dpy = 0x%016" PRIxPTR ", format = %d, max_modifiers = %d, modifiers = 0x%016" PRIxPTR + ", external_only = 0x%016" PRIxPTR ", num_modifiers = 0x%016" PRIxPTR "", + (uintptr_t)dpy, format, max_modifiers, (uintptr_t)modifiers, (uintptr_t)external_only, + (uintptr_t)num_modifiers)); egl::Display *dpyPacked = PackParam(dpy); @@ -1577,11 +1567,11 @@ EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePlatformPixmapSurfaceEXT, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", native_pixmap = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreatePlatformPixmapSurfaceEXT, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", native_pixmap = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -1622,11 +1612,11 @@ EGLSurface EGLAPIENTRY EGL_CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLSurface returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreatePlatformWindowSurfaceEXT, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", native_window = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreatePlatformWindowSurfaceEXT, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", native_window = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -1666,10 +1656,10 @@ EGLDisplay EGLAPIENTRY EGL_GetPlatformDisplayEXT(EGLenum platform, EGLDisplay returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(GetPlatformDisplayEXT, - "platform = 0x%X, native_display = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - platform, (uintptr_t)native_display, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetPlatformDisplayEXT, + "platform = 0x%X, native_display = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + platform, (uintptr_t)native_display, (uintptr_t)attrib_list)); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -1710,12 +1700,12 @@ EGLBoolean EGLAPIENTRY EGL_QuerySupportedCompressionRatesEXT(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QuerySupportedCompressionRatesEXT, - "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR ", rates = 0x%016" PRIxPTR - ", rate_size = %d, num_rates = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list, (uintptr_t)rates, - rate_size, (uintptr_t)num_rates); + ANGLE_UNSAFE_TODO(EGL_EVENT(QuerySupportedCompressionRatesEXT, + "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR ", rates = 0x%016" PRIxPTR + ", rate_size = %d, num_rates = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list, + (uintptr_t)rates, rate_size, (uintptr_t)num_rates)); egl::Display *dpyPacked = PackParam(dpy); egl::Config *configPacked = PackParam(config); @@ -1753,9 +1743,9 @@ EGLint EGLAPIENTRY EGL_DebugMessageControlKHR(EGLDEBUGPROCKHR callback, EGLint returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(DebugMessageControlKHR, - "callback = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)callback, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(DebugMessageControlKHR, + "callback = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)callback, (uintptr_t)attrib_list)); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -1792,10 +1782,11 @@ EGLint EGLAPIENTRY EGL_LabelObjectKHR(EGLDisplay display, EGLint returnValue; { ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK(); - EGL_EVENT(LabelObjectKHR, - "display = 0x%016" PRIxPTR ", objectType = 0x%X, object = 0x%016" PRIxPTR - ", label = 0x%016" PRIxPTR "", - (uintptr_t)display, objectType, (uintptr_t)object, (uintptr_t)label); + ANGLE_UNSAFE_TODO( + EGL_EVENT(LabelObjectKHR, + "display = 0x%016" PRIxPTR ", objectType = 0x%X, object = 0x%016" PRIxPTR + ", label = 0x%016" PRIxPTR "", + (uintptr_t)display, objectType, (uintptr_t)object, (uintptr_t)label)); egl::Display *displayPacked = PackParam(display); ObjectType objectTypePacked = PackParam(objectType); @@ -1829,8 +1820,8 @@ EGLBoolean EGLAPIENTRY EGL_QueryDebugKHR(EGLint attribute, EGLAttrib *value) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryDebugKHR, "attribute = %d, value = 0x%016" PRIxPTR "", attribute, - (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryDebugKHR, "attribute = %d, value = 0x%016" PRIxPTR "", + attribute, (uintptr_t)value)); { ANGLE_EGL_SCOPED_CONTEXT_LOCK(QueryDebugKHR, thread, attribute); @@ -1863,9 +1854,10 @@ EGLint EGLAPIENTRY EGL_ClientWaitSyncKHR(EGLDisplay dpy, EGLint returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(ClientWaitSyncKHR, - "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d, timeout = %llu", - (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast(timeout)); + ANGLE_UNSAFE_TODO(EGL_EVENT( + ClientWaitSyncKHR, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d, timeout = %llu", + (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast(timeout))); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -1899,9 +1891,9 @@ EGLSyncKHR EGLAPIENTRY EGL_CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGL EGLSyncKHR returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(CreateSyncKHR, - "dpy = 0x%016" PRIxPTR ", type = 0x%X, attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, type, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreateSyncKHR, "dpy = 0x%016" PRIxPTR ", type = 0x%X, attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, type, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -1936,8 +1928,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(DestroySyncKHR, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)sync); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroySyncKHR, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)sync)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -1973,10 +1966,10 @@ EGLBoolean EGLAPIENTRY EGL_GetSyncAttribKHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(GetSyncAttribKHR, - "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(GetSyncAttribKHR, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -2015,11 +2008,11 @@ EGLImageKHR EGLAPIENTRY EGL_CreateImageKHR(EGLDisplay dpy, EGLImageKHR returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateImageKHR, - "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR - ", target = 0x%X, buffer = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)ctx, target, (uintptr_t)buffer, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT( + CreateImageKHR, + "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR + ", target = 0x%X, buffer = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)ctx, target, (uintptr_t)buffer, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); gl::ContextID ctxPacked = PackParam(ctx); @@ -2057,8 +2050,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(DestroyImageKHR, "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)image); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroyImageKHR, + "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)image)); egl::Display *dpyPacked = PackParam(dpy); ImageID imagePacked = PackParam(image); @@ -2094,10 +2088,10 @@ EGLBoolean EGLAPIENTRY EGL_LockSurfaceKHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(LockSurfaceKHR, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(LockSurfaceKHR, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -2130,7 +2124,7 @@ EGLBoolean EGLAPIENTRY EGL_QuerySurface64KHR(EGLDisplay dpy, EGLint attribute, EGLAttribKHR *value) { - if (attribute == EGL_BUFFER_AGE_EXT) + if (attribute == EGL_BUFFER_AGE_EXT || attribute == EGL_SURFACE_COMPRESSION_EXT) { ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(dpy, surface)); } @@ -2139,10 +2133,11 @@ EGLBoolean EGLAPIENTRY EGL_QuerySurface64KHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QuerySurface64KHR, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", attribute = %d, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QuerySurface64KHR, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", attribute = %d, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface, attribute, + (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -2176,8 +2171,9 @@ EGLBoolean EGLAPIENTRY EGL_UnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(UnlockSurfaceKHR, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)surface); + ANGLE_UNSAFE_TODO(EGL_EVENT(UnlockSurfaceKHR, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)surface)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -2214,10 +2210,10 @@ EGLBoolean EGLAPIENTRY EGL_SetDamageRegionKHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SetDamageRegionKHR, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", rects = 0x%016" PRIxPTR - ", n_rects = %d", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)rects, n_rects); + ANGLE_UNSAFE_TODO(EGL_EVENT(SetDamageRegionKHR, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", rects = 0x%016" PRIxPTR ", n_rects = %d", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)rects, n_rects)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -2252,8 +2248,9 @@ EGLBoolean EGLAPIENTRY EGL_SignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenu EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(SignalSyncKHR, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", mode = 0x%X", - (uintptr_t)dpy, (uintptr_t)sync, mode); + ANGLE_UNSAFE_TODO(EGL_EVENT( + SignalSyncKHR, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", mode = 0x%X", + (uintptr_t)dpy, (uintptr_t)sync, mode)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -2295,8 +2292,9 @@ EGLStreamKHR EGLAPIENTRY EGL_CreateStreamKHR(EGLDisplay dpy, const EGLint *attri EGLStreamKHR returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(CreateStreamKHR, "dpy = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(CreateStreamKHR, + "dpy = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); const AttributeMap &attrib_listPacked = PackParam(attrib_list); @@ -2330,8 +2328,9 @@ EGLBoolean EGLAPIENTRY EGL_DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(DestroyStreamKHR, "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream); + ANGLE_UNSAFE_TODO(EGL_EVENT(DestroyStreamKHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2367,10 +2366,11 @@ EGLBoolean EGLAPIENTRY EGL_QueryStreamKHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryStreamKHR, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR - ", attribute = 0x%X, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryStreamKHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR + ", attribute = 0x%X, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream, attribute, + (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2407,10 +2407,11 @@ EGLBoolean EGLAPIENTRY EGL_QueryStreamu64KHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(QueryStreamu64KHR, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR - ", attribute = 0x%X, value = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream, attribute, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EGL_EVENT(QueryStreamu64KHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR + ", attribute = 0x%X, value = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream, attribute, + (uintptr_t)value)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2447,10 +2448,10 @@ EGLBoolean EGLAPIENTRY EGL_StreamAttribKHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(StreamAttribKHR, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR - ", attribute = 0x%X, value = %d", - (uintptr_t)dpy, (uintptr_t)stream, attribute, value); + ANGLE_UNSAFE_TODO(EGL_EVENT(StreamAttribKHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR + ", attribute = 0x%X, value = %d", + (uintptr_t)dpy, (uintptr_t)stream, attribute, value)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2485,8 +2486,9 @@ EGLBoolean EGLAPIENTRY EGL_StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(StreamConsumerAcquireKHR, "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream); + ANGLE_UNSAFE_TODO(EGL_EVENT(StreamConsumerAcquireKHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2520,9 +2522,9 @@ EGLBoolean EGLAPIENTRY EGL_StreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EG EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(StreamConsumerGLTextureExternalKHR, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", (uintptr_t)dpy, - (uintptr_t)stream); + ANGLE_UNSAFE_TODO(EGL_EVENT(StreamConsumerGLTextureExternalKHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2557,8 +2559,9 @@ EGLBoolean EGLAPIENTRY EGL_StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(StreamConsumerReleaseKHR, "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream); + ANGLE_UNSAFE_TODO(EGL_EVENT(StreamConsumerReleaseKHR, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); @@ -2596,10 +2599,10 @@ EGLBoolean EGLAPIENTRY EGL_SwapBuffersWithDamageKHR(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(SwapBuffersWithDamageKHR, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", rects = 0x%016" PRIxPTR - ", n_rects = %d", - (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)rects, n_rects); + ANGLE_UNSAFE_TODO(EGL_EVENT(SwapBuffersWithDamageKHR, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", rects = 0x%016" PRIxPTR ", n_rects = %d", + (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)rects, n_rects)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -2635,8 +2638,9 @@ EGLint EGLAPIENTRY EGL_WaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags EGLint returnValue; { ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK(); - EGL_EVENT(WaitSyncKHR, "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d", - (uintptr_t)dpy, (uintptr_t)sync, flags); + ANGLE_UNSAFE_TODO(EGL_EVENT(WaitSyncKHR, + "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d", + (uintptr_t)dpy, (uintptr_t)sync, flags)); egl::Display *dpyPacked = PackParam(dpy); egl::SyncID syncPacked = PackParam(sync); @@ -2675,10 +2679,10 @@ EGLBoolean EGLAPIENTRY EGL_PostSubBufferNV(EGLDisplay dpy, EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(PostSubBufferNV, - "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR - ", x = %d, y = %d, width = %d, height = %d", - (uintptr_t)dpy, (uintptr_t)surface, x, y, width, height); + ANGLE_UNSAFE_TODO(EGL_EVENT(PostSubBufferNV, + "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR + ", x = %d, y = %d, width = %d, height = %d", + (uintptr_t)dpy, (uintptr_t)surface, x, y, width, height)); egl::Display *dpyPacked = PackParam(dpy); SurfaceID surfacePacked = PackParam(surface); @@ -2715,10 +2719,10 @@ EGLBoolean EGLAPIENTRY EGL_StreamConsumerGLTextureExternalAttribsNV(EGLDisplay d EGLBoolean returnValue; { ANGLE_SCOPED_GLOBAL_LOCK(); - EGL_EVENT(StreamConsumerGLTextureExternalAttribsNV, - "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR - ", attrib_list = 0x%016" PRIxPTR "", - (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EGL_EVENT(StreamConsumerGLTextureExternalAttribsNV, + "dpy = 0x%016" PRIxPTR ", stream = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)attrib_list)); egl::Display *dpyPacked = PackParam(dpy); egl::Stream *streamPacked = PackParam(stream); diff --git a/src/libGLESv2/entry_points_egl_ext_autogen.h b/src/libGLESv2/entry_points_egl_ext_autogen.h index 6139e69d1f8..32a96751995 100644 --- a/src/libGLESv2/entry_points_egl_ext_autogen.h +++ b/src/libGLESv2/entry_points_egl_ext_autogen.h @@ -133,12 +133,6 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_StreamPostD3DTextureANGLE(EGLDisplay dpy void *texture, const EGLAttrib *attrib_list); -// EGL_ANGLE_swap_with_frame_token -ANGLE_EXPORT EGLBoolean EGLAPIENTRY -EGL_SwapBuffersWithFrameTokenANGLE(EGLDisplay dpy, - EGLSurface surface, - EGLFrameTokenANGLE frametoken); - // EGL_ANGLE_sync_control_rate ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetMscRateANGLE(EGLDisplay dpy, EGLSurface surface, diff --git a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp index fbaec496dd5..1667063082c 100644 --- a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp @@ -28,17 +28,33 @@ void GL_APIENTRY GL_AlphaFunc(GLenum func, GLfloat ref) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLAlphaFunc, "context = %d, func = %s, ref = %f", CID(context), - GLenumToString(GLESEnum::AlphaFunction, func), ref); + ANGLE_UNSAFE_TODO(EVENT(context, GLAlphaFunc, "context = %d, func = %s, ref = %f", CID(context), + GLenumToString(GLESEnum::AlphaFunction, func), ref)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { AlphaTestFunc funcPacked = PackParam(func); - bool isCallValid = (context->skipValidation() || - ValidateAlphaFunc(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLAlphaFunc, funcPacked, ref)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateAlphaFunc(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLAlphaFunc, funcPacked, ref); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLAlphaFunc); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateAlphaFunc(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), funcPacked, ref); @@ -47,7 +63,7 @@ void GL_APIENTRY GL_AlphaFunc(GLenum func, GLfloat ref) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLAlphaFunc); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -56,17 +72,33 @@ void GL_APIENTRY GL_AlphaFuncx(GLenum func, GLfixed ref) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLAlphaFuncx, "context = %d, func = %s, ref = 0x%X", CID(context), - GLenumToString(GLESEnum::AlphaFunction, func), ref); + ANGLE_UNSAFE_TODO(EVENT(context, GLAlphaFuncx, "context = %d, func = %s, ref = 0x%X", + CID(context), GLenumToString(GLESEnum::AlphaFunction, func), ref)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { AlphaTestFunc funcPacked = PackParam(func); - bool isCallValid = (context->skipValidation() || - ValidateAlphaFuncx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLAlphaFuncx, funcPacked, ref)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateAlphaFuncx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLAlphaFuncx, funcPacked, ref); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLAlphaFuncx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateAlphaFuncx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), funcPacked, ref); @@ -75,7 +107,7 @@ void GL_APIENTRY GL_AlphaFuncx(GLenum func, GLfixed ref) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLAlphaFuncx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -84,18 +116,33 @@ void GL_APIENTRY GL_ClearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixe { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearColorx, - "context = %d, red = 0x%X, green = 0x%X, blue = 0x%X, alpha = 0x%X", CID(context), red, - green, blue, alpha); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearColorx, + "context = %d, red = 0x%X, green = 0x%X, blue = 0x%X, alpha = 0x%X", + CID(context), red, green, blue, alpha)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateClearColorx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearColorx, red, green, blue, alpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearColorx( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClearColorx, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLClearColorx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClearColorx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, @@ -105,7 +152,7 @@ void GL_APIENTRY GL_ClearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixe } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearColorx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -114,15 +161,32 @@ void GL_APIENTRY GL_ClearDepthx(GLfixed depth) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearDepthx, "context = %d, depth = 0x%X", CID(context), depth); + ANGLE_UNSAFE_TODO( + EVENT(context, GLClearDepthx, "context = %d, depth = 0x%X", CID(context), depth)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateClearDepthx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearDepthx, depth)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearDepthx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClearDepthx, depth); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLClearDepthx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClearDepthx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), depth); @@ -131,7 +195,7 @@ void GL_APIENTRY GL_ClearDepthx(GLfixed depth) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearDepthx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -140,16 +204,32 @@ void GL_APIENTRY GL_ClientActiveTexture(GLenum texture) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClientActiveTexture, "context = %d, texture = %s", CID(context), - GLenumToString(GLESEnum::TextureUnit, texture)); + ANGLE_UNSAFE_TODO(EVENT(context, GLClientActiveTexture, "context = %d, texture = %s", + CID(context), GLenumToString(GLESEnum::TextureUnit, texture))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateClientActiveTexture( - context, angle::EntryPoint::GLClientActiveTexture, texture)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClientActiveTexture( + context, angle::EntryPoint::GLClientActiveTexture, texture); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLClientActiveTexture); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clientActiveTexture(texture); } @@ -157,7 +237,7 @@ void GL_APIENTRY GL_ClientActiveTexture(GLenum texture) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClientActiveTexture); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -166,16 +246,33 @@ void GL_APIENTRY GL_ClipPlanef(GLenum p, const GLfloat *eqn) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClipPlanef, "context = %d, p = %s, eqn = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::ClipPlaneName, p), (uintptr_t)eqn); + ANGLE_UNSAFE_TODO(EVENT(context, GLClipPlanef, "context = %d, p = %s, eqn = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ClipPlaneName, p), + (uintptr_t)eqn)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateClipPlanef(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClipPlanef, p, eqn)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClipPlanef(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClipPlanef, p, eqn); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLClipPlanef); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClipPlanef(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), p, eqn); @@ -184,7 +281,7 @@ void GL_APIENTRY GL_ClipPlanef(GLenum p, const GLfloat *eqn) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClipPlanef); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -193,16 +290,33 @@ void GL_APIENTRY GL_ClipPlanex(GLenum plane, const GLfixed *equation) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClipPlanex, "context = %d, plane = %s, equation = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ClipPlaneName, plane), (uintptr_t)equation); + ANGLE_UNSAFE_TODO(EVENT(context, GLClipPlanex, + "context = %d, plane = %s, equation = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::ClipPlaneName, plane), (uintptr_t)equation)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateClipPlanex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClipPlanex, plane, equation)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClipPlanex(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClipPlanex, plane, equation); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLClipPlanex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClipPlanex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), plane, equation); @@ -211,7 +325,7 @@ void GL_APIENTRY GL_ClipPlanex(GLenum plane, const GLfixed *equation) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClipPlanex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -220,16 +334,33 @@ void GL_APIENTRY GL_Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat al { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColor4f, "context = %d, red = %f, green = %f, blue = %f, alpha = %f", - CID(context), red, green, blue, alpha); + ANGLE_UNSAFE_TODO(EVENT(context, GLColor4f, + "context = %d, red = %f, green = %f, blue = %f, alpha = %f", + CID(context), red, green, blue, alpha)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateColor4f(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColor4f, red, green, blue, alpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColor4f( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColor4f, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLColor4f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColor4f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, alpha); @@ -238,7 +369,7 @@ void GL_APIENTRY GL_Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat al } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColor4f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -247,17 +378,33 @@ void GL_APIENTRY GL_Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte a { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColor4ub, "context = %d, red = %d, green = %d, blue = %d, alpha = %d", - CID(context), red, green, blue, alpha); + ANGLE_UNSAFE_TODO(EVENT(context, GLColor4ub, + "context = %d, red = %d, green = %d, blue = %d, alpha = %d", + CID(context), red, green, blue, alpha)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateColor4ub(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColor4ub, red, green, blue, alpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColor4ub( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColor4ub, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLColor4ub); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColor4ub(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, alpha); @@ -266,7 +413,7 @@ void GL_APIENTRY GL_Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte a } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColor4ub); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -275,16 +422,33 @@ void GL_APIENTRY GL_Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed al { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColor4x, "context = %d, red = 0x%X, green = 0x%X, blue = 0x%X, alpha = 0x%X", - CID(context), red, green, blue, alpha); + ANGLE_UNSAFE_TODO(EVENT(context, GLColor4x, + "context = %d, red = 0x%X, green = 0x%X, blue = 0x%X, alpha = 0x%X", + CID(context), red, green, blue, alpha)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateColor4x(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColor4x, red, green, blue, alpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColor4x( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColor4x, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLColor4x); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColor4x(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, alpha); @@ -293,7 +457,7 @@ void GL_APIENTRY GL_Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed al } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColor4x); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -302,19 +466,36 @@ void GL_APIENTRY GL_ColorPointer(GLint size, GLenum type, GLsizei stride, const { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColorPointer, - "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", - CID(context), size, GLenumToString(GLESEnum::ColorPointerType, type), stride, - (uintptr_t)pointer); + ANGLE_UNSAFE_TODO( + EVENT(context, GLColorPointer, + "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), size, GLenumToString(GLESEnum::ColorPointerType, type), stride, + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateColorPointer(context, angle::EntryPoint::GLColorPointer, size, - typePacked, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColorPointer(context, angle::EntryPoint::GLColorPointer, size, + typePacked, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLColorPointer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->colorPointer(size, typePacked, stride, pointer); } @@ -322,7 +503,7 @@ void GL_APIENTRY GL_ColorPointer(GLint size, GLenum type, GLsizei stride, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColorPointer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -331,15 +512,32 @@ void GL_APIENTRY GL_DepthRangex(GLfixed n, GLfixed f) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDepthRangex, "context = %d, n = 0x%X, f = 0x%X", CID(context), n, f); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDepthRangex, "context = %d, n = 0x%X, f = 0x%X", CID(context), n, f)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDepthRangex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDepthRangex, n, f)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDepthRangex(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDepthRangex, n, f); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLDepthRangex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDepthRangex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), n, f); @@ -348,7 +546,7 @@ void GL_APIENTRY GL_DepthRangex(GLfixed n, GLfixed f) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDepthRangex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -357,17 +555,33 @@ void GL_APIENTRY GL_DisableClientState(GLenum array) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisableClientState, "context = %d, array = %s", CID(context), - GLenumToString(GLESEnum::EnableCap, array)); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisableClientState, "context = %d, array = %s", CID(context), + GLenumToString(GLESEnum::EnableCap, array))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ClientVertexArrayType arrayPacked = PackParam(array); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDisableClientState( - context, angle::EntryPoint::GLDisableClientState, arrayPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisableClientState( + context, angle::EntryPoint::GLDisableClientState, arrayPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLDisableClientState); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->disableClientState(arrayPacked); } @@ -375,7 +589,7 @@ void GL_APIENTRY GL_DisableClientState(GLenum array) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDisableClientState); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -384,17 +598,33 @@ void GL_APIENTRY GL_EnableClientState(GLenum array) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEnableClientState, "context = %d, array = %s", CID(context), - GLenumToString(GLESEnum::EnableCap, array)); + ANGLE_UNSAFE_TODO(EVENT(context, GLEnableClientState, "context = %d, array = %s", CID(context), + GLenumToString(GLESEnum::EnableCap, array))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ClientVertexArrayType arrayPacked = PackParam(array); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateEnableClientState( - context, angle::EntryPoint::GLEnableClientState, arrayPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEnableClientState( + context, angle::EntryPoint::GLEnableClientState, arrayPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLEnableClientState); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->enableClientState(arrayPacked); } @@ -402,7 +632,7 @@ void GL_APIENTRY GL_EnableClientState(GLenum array) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEnableClientState); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -411,16 +641,32 @@ void GL_APIENTRY GL_Fogf(GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFogf, "context = %d, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::FogParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLFogf, "context = %d, pname = %s, param = %f", CID(context), + GLenumToString(GLESEnum::FogParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateFogf(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFogf, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFogf(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFogf, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLFogf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFogf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -429,7 +675,7 @@ void GL_APIENTRY GL_Fogf(GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFogf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -438,16 +684,33 @@ void GL_APIENTRY GL_Fogfv(GLenum pname, const GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFogfv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::FogParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLFogfv, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::FogParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateFogfv(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFogfv, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFogfv(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFogfv, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLFogfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFogfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, params); @@ -456,7 +719,7 @@ void GL_APIENTRY GL_Fogfv(GLenum pname, const GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFogfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -465,16 +728,32 @@ void GL_APIENTRY GL_Fogx(GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFogx, "context = %d, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::FogPName, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLFogx, "context = %d, pname = %s, param = 0x%X", CID(context), + GLenumToString(GLESEnum::FogPName, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateFogx(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFogx, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFogx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFogx, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLFogx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFogx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -483,7 +762,7 @@ void GL_APIENTRY GL_Fogx(GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFogx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -492,16 +771,33 @@ void GL_APIENTRY GL_Fogxv(GLenum pname, const GLfixed *param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFogxv, "context = %d, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::FogPName, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLFogxv, "context = %d, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FogPName, pname), + (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateFogxv(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFogxv, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFogxv(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFogxv, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLFogxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFogxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -510,7 +806,7 @@ void GL_APIENTRY GL_Fogxv(GLenum pname, const GLfixed *param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFogxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -519,16 +815,33 @@ void GL_APIENTRY GL_Frustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFrustumf, "context = %d, l = %f, r = %f, b = %f, t = %f, n = %f, f = %f", - CID(context), l, r, b, t, n, f); + ANGLE_UNSAFE_TODO(EVENT(context, GLFrustumf, + "context = %d, l = %f, r = %f, b = %f, t = %f, n = %f, f = %f", + CID(context), l, r, b, t, n, f)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateFrustumf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFrustumf, l, r, b, t, n, f)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFrustumf(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFrustumf, l, r, b, t, n, f); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLFrustumf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFrustumf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), l, r, b, t, n, f); @@ -537,7 +850,7 @@ void GL_APIENTRY GL_Frustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFrustumf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -546,17 +859,34 @@ void GL_APIENTRY GL_Frustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFrustumx, - "context = %d, l = 0x%X, r = 0x%X, b = 0x%X, t = 0x%X, n = 0x%X, f = 0x%X", CID(context), - l, r, b, t, n, f); + ANGLE_UNSAFE_TODO( + EVENT(context, GLFrustumx, + "context = %d, l = 0x%X, r = 0x%X, b = 0x%X, t = 0x%X, n = 0x%X, f = 0x%X", + CID(context), l, r, b, t, n, f)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateFrustumx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFrustumx, l, r, b, t, n, f)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFrustumx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFrustumx, l, r, b, t, n, f); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLFrustumx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFrustumx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), l, r, b, t, n, f); @@ -565,7 +895,7 @@ void GL_APIENTRY GL_Frustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFrustumx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -574,17 +904,33 @@ void GL_APIENTRY GL_GetClipPlanef(GLenum plane, GLfloat *equation) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetClipPlanef, "context = %d, plane = %s, equation = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ClipPlaneName, plane), (uintptr_t)equation); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetClipPlanef, + "context = %d, plane = %s, equation = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::ClipPlaneName, plane), (uintptr_t)equation)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateGetClipPlanef(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetClipPlanef, plane, equation)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetClipPlanef( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetClipPlanef, plane, equation); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetClipPlanef); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetClipPlanef(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), plane, equation); @@ -593,7 +939,7 @@ void GL_APIENTRY GL_GetClipPlanef(GLenum plane, GLfloat *equation) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetClipPlanef); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -602,17 +948,33 @@ void GL_APIENTRY GL_GetClipPlanex(GLenum plane, GLfixed *equation) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetClipPlanex, "context = %d, plane = %s, equation = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ClipPlaneName, plane), (uintptr_t)equation); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetClipPlanex, + "context = %d, plane = %s, equation = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::ClipPlaneName, plane), (uintptr_t)equation)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateGetClipPlanex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetClipPlanex, plane, equation)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetClipPlanex( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetClipPlanex, plane, equation); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetClipPlanex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetClipPlanex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), plane, equation); @@ -621,7 +983,7 @@ void GL_APIENTRY GL_GetClipPlanex(GLenum plane, GLfixed *equation) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetClipPlanex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -630,16 +992,33 @@ void GL_APIENTRY GL_GetFixedv(GLenum pname, GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFixedv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFixedv, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFixedv(context, angle::EntryPoint::GLGetFixedv, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetFixedv(context, angle::EntryPoint::GLGetFixedv, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetFixedv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFixedv(pname, params); } @@ -647,7 +1026,7 @@ void GL_APIENTRY GL_GetFixedv(GLenum pname, GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetFixedv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -656,19 +1035,35 @@ void GL_APIENTRY GL_GetLightfv(GLenum light, GLenum pname, GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetLightfv, "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::LightName, light), - GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetLightfv, + "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::LightName, light), + GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LightParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetLightfv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetLightfv, light, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetLightfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetLightfv, light, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetLightfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetLightfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), light, pnamePacked, @@ -678,7 +1073,7 @@ void GL_APIENTRY GL_GetLightfv(GLenum light, GLenum pname, GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetLightfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -687,19 +1082,35 @@ void GL_APIENTRY GL_GetLightxv(GLenum light, GLenum pname, GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetLightxv, "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::LightName, light), - GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetLightxv, + "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::LightName, light), + GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LightParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetLightxv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetLightxv, light, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetLightxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetLightxv, light, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetLightxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetLightxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), light, pnamePacked, @@ -709,7 +1120,7 @@ void GL_APIENTRY GL_GetLightxv(GLenum light, GLenum pname, GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetLightxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -718,20 +1129,35 @@ void GL_APIENTRY GL_GetMaterialfv(GLenum face, GLenum pname, GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetMaterialfv, - "context = %d, face = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetMaterialfv, + "context = %d, face = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MaterialParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetMaterialfv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetMaterialfv, face, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetMaterialfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetMaterialfv, face, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetMaterialfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetMaterialfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, pnamePacked, @@ -741,7 +1167,7 @@ void GL_APIENTRY GL_GetMaterialfv(GLenum face, GLenum pname, GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetMaterialfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -750,20 +1176,35 @@ void GL_APIENTRY GL_GetMaterialxv(GLenum face, GLenum pname, GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetMaterialxv, - "context = %d, face = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetMaterialxv, + "context = %d, face = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MaterialParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetMaterialxv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetMaterialxv, face, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetMaterialxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetMaterialxv, face, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetMaterialxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetMaterialxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, pnamePacked, @@ -773,7 +1214,7 @@ void GL_APIENTRY GL_GetMaterialxv(GLenum face, GLenum pname, GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetMaterialxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -782,21 +1223,36 @@ void GL_APIENTRY GL_GetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexEnvfv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexEnvfv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexEnvfv( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetTexEnvfv, targetPacked, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexEnvfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetTexEnvfv, targetPacked, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetTexEnvfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetTexEnvfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, @@ -806,7 +1262,7 @@ void GL_APIENTRY GL_GetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexEnvfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -815,21 +1271,36 @@ void GL_APIENTRY GL_GetTexEnviv(GLenum target, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexEnviv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexEnviv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexEnviv( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetTexEnviv, targetPacked, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexEnviv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetTexEnviv, targetPacked, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetTexEnviv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetTexEnviv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, @@ -839,7 +1310,7 @@ void GL_APIENTRY GL_GetTexEnviv(GLenum target, GLenum pname, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexEnviv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -848,21 +1319,36 @@ void GL_APIENTRY GL_GetTexEnvxv(GLenum target, GLenum pname, GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexEnvxv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexEnvxv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexEnvxv( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLGetTexEnvxv, targetPacked, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexEnvxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLGetTexEnvxv, targetPacked, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetTexEnvxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateGetTexEnvxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, @@ -872,7 +1358,7 @@ void GL_APIENTRY GL_GetTexEnvxv(GLenum target, GLenum pname, GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexEnvxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -881,20 +1367,36 @@ void GL_APIENTRY GL_GetTexParameterxv(GLenum target, GLenum pname, GLfixed *para { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterxv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterxv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterxv(context, angle::EntryPoint::GLGetTexParameterxv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterxv( + context, angle::EntryPoint::GLGetTexParameterxv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLGetTexParameterxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterxv(targetPacked, pname, params); } @@ -902,7 +1404,7 @@ void GL_APIENTRY GL_GetTexParameterxv(GLenum target, GLenum pname, GLfixed *para } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -911,16 +1413,33 @@ void GL_APIENTRY GL_LightModelf(GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightModelf, "context = %d, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::LightModelParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLLightModelf, "context = %d, pname = %s, param = %f", + CID(context), GLenumToString(GLESEnum::LightModelParameter, pname), + param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLightModelf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightModelf, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightModelf(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightModelf, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightModelf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightModelf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -929,7 +1448,7 @@ void GL_APIENTRY GL_LightModelf(GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightModelf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -938,16 +1457,33 @@ void GL_APIENTRY GL_LightModelfv(GLenum pname, const GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightModelfv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::LightModelParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLLightModelfv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::LightModelParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLightModelfv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightModelfv, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightModelfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightModelfv, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightModelfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightModelfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, params); @@ -956,7 +1492,7 @@ void GL_APIENTRY GL_LightModelfv(GLenum pname, const GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightModelfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -965,16 +1501,33 @@ void GL_APIENTRY GL_LightModelx(GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightModelx, "context = %d, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::LightModelParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLLightModelx, "context = %d, pname = %s, param = 0x%X", + CID(context), GLenumToString(GLESEnum::LightModelParameter, pname), + param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLightModelx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightModelx, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightModelx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightModelx, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightModelx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightModelx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -983,7 +1536,7 @@ void GL_APIENTRY GL_LightModelx(GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightModelx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -992,16 +1545,33 @@ void GL_APIENTRY GL_LightModelxv(GLenum pname, const GLfixed *param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightModelxv, "context = %d, pname = %s, param = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::LightModelParameter, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT( + context, GLLightModelxv, "context = %d, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::LightModelParameter, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLightModelxv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightModelxv, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightModelxv(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightModelxv, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightModelxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightModelxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -1010,7 +1580,7 @@ void GL_APIENTRY GL_LightModelxv(GLenum pname, const GLfixed *param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightModelxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1019,18 +1589,34 @@ void GL_APIENTRY GL_Lightf(GLenum light, GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightf, "context = %d, light = %s, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::LightName, light), - GLenumToString(GLESEnum::LightParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLLightf, "context = %d, light = %s, pname = %s, param = %f", + CID(context), GLenumToString(GLESEnum::LightName, light), + GLenumToString(GLESEnum::LightParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LightParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateLightf(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightf, light, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightf( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightf, light, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), light, pnamePacked, param); @@ -1039,7 +1625,7 @@ void GL_APIENTRY GL_Lightf(GLenum light, GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1048,18 +1634,35 @@ void GL_APIENTRY GL_Lightfv(GLenum light, GLenum pname, const GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightfv, "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::LightName, light), - GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLLightfv, + "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::LightName, light), + GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LightParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateLightfv(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightfv, light, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightfv, light, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), light, pnamePacked, @@ -1069,7 +1672,7 @@ void GL_APIENTRY GL_Lightfv(GLenum light, GLenum pname, const GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1078,18 +1681,34 @@ void GL_APIENTRY GL_Lightx(GLenum light, GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightx, "context = %d, light = %s, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::LightName, light), - GLenumToString(GLESEnum::LightParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLLightx, "context = %d, light = %s, pname = %s, param = 0x%X", + CID(context), GLenumToString(GLESEnum::LightName, light), + GLenumToString(GLESEnum::LightParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LightParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateLightx(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightx, light, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightx( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightx, light, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), light, pnamePacked, param); @@ -1098,7 +1717,7 @@ void GL_APIENTRY GL_Lightx(GLenum light, GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1107,18 +1726,35 @@ void GL_APIENTRY GL_Lightxv(GLenum light, GLenum pname, const GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLightxv, "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::LightName, light), - GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLLightxv, + "context = %d, light = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::LightName, light), + GLenumToString(GLESEnum::LightParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LightParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateLightxv(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLightxv, light, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLightxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLightxv, light, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLightxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLightxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), light, pnamePacked, @@ -1128,7 +1764,7 @@ void GL_APIENTRY GL_Lightxv(GLenum light, GLenum pname, const GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLightxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1137,15 +1773,32 @@ void GL_APIENTRY GL_LineWidthx(GLfixed width) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLineWidthx, "context = %d, width = 0x%X", CID(context), width); + ANGLE_UNSAFE_TODO( + EVENT(context, GLLineWidthx, "context = %d, width = 0x%X", CID(context), width)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLineWidthx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLineWidthx, width)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLineWidthx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLineWidthx, width); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLineWidthx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLineWidthx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), width); @@ -1154,7 +1807,7 @@ void GL_APIENTRY GL_LineWidthx(GLfixed width) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLineWidthx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1163,15 +1816,31 @@ void GL_APIENTRY GL_LoadIdentity() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLoadIdentity, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLLoadIdentity, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLoadIdentity(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLoadIdentity)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLoadIdentity(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLoadIdentity); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLoadIdentity); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLoadIdentity(context->getMutablePrivateState(), context->getMutablePrivateStateCache()); @@ -1180,7 +1849,7 @@ void GL_APIENTRY GL_LoadIdentity() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLoadIdentity); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1189,16 +1858,32 @@ void GL_APIENTRY GL_LoadMatrixf(const GLfloat *m) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLoadMatrixf, "context = %d, m = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)m); + ANGLE_UNSAFE_TODO(EVENT(context, GLLoadMatrixf, "context = %d, m = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)m)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLoadMatrixf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLoadMatrixf, m)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLoadMatrixf(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLoadMatrixf, m); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLoadMatrixf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLoadMatrixf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), m); @@ -1207,7 +1892,7 @@ void GL_APIENTRY GL_LoadMatrixf(const GLfloat *m) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLoadMatrixf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1216,16 +1901,32 @@ void GL_APIENTRY GL_LoadMatrixx(const GLfixed *m) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLoadMatrixx, "context = %d, m = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)m); + ANGLE_UNSAFE_TODO(EVENT(context, GLLoadMatrixx, "context = %d, m = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)m)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateLoadMatrixx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLoadMatrixx, m)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLoadMatrixx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLoadMatrixx, m); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLoadMatrixx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLoadMatrixx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), m); @@ -1234,7 +1935,7 @@ void GL_APIENTRY GL_LoadMatrixx(const GLfixed *m) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLoadMatrixx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1243,17 +1944,33 @@ void GL_APIENTRY GL_LogicOp(GLenum opcode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLogicOp, "context = %d, opcode = %s", CID(context), - GLenumToString(GLESEnum::LogicOp, opcode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLLogicOp, "context = %d, opcode = %s", CID(context), + GLenumToString(GLESEnum::LogicOp, opcode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LogicalOperation opcodePacked = PackParam(opcode); - bool isCallValid = - (context->skipValidation() || - ValidateLogicOp(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLogicOp, opcodePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLogicOp(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLogicOp, opcodePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLLogicOp); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLogicOp(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), opcodePacked); @@ -1262,7 +1979,7 @@ void GL_APIENTRY GL_LogicOp(GLenum opcode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLogicOp); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1271,19 +1988,34 @@ void GL_APIENTRY GL_Materialf(GLenum face, GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMaterialf, "context = %d, face = %s, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::MaterialParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLMaterialf, "context = %d, face = %s, pname = %s, param = %f", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::MaterialParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MaterialParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateMaterialf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMaterialf, face, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMaterialf( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMaterialf, face, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMaterialf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMaterialf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, pnamePacked, @@ -1293,7 +2025,7 @@ void GL_APIENTRY GL_Materialf(GLenum face, GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMaterialf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1302,19 +2034,35 @@ void GL_APIENTRY GL_Materialfv(GLenum face, GLenum pname, const GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMaterialfv, "context = %d, face = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLMaterialfv, + "context = %d, face = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MaterialParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateMaterialfv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMaterialfv, face, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMaterialfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMaterialfv, face, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMaterialfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMaterialfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, pnamePacked, @@ -1324,7 +2072,7 @@ void GL_APIENTRY GL_Materialfv(GLenum face, GLenum pname, const GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMaterialfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1333,19 +2081,35 @@ void GL_APIENTRY GL_Materialx(GLenum face, GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMaterialx, "context = %d, face = %s, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::MaterialParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLMaterialx, + "context = %d, face = %s, pname = %s, param = 0x%X", CID(context), + GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::MaterialParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MaterialParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateMaterialx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMaterialx, face, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMaterialx( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMaterialx, face, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMaterialx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMaterialx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, pnamePacked, @@ -1355,7 +2119,7 @@ void GL_APIENTRY GL_Materialx(GLenum face, GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMaterialx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1364,19 +2128,35 @@ void GL_APIENTRY GL_Materialxv(GLenum face, GLenum pname, const GLfixed *param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMaterialxv, "context = %d, face = %s, pname = %s, param = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLMaterialxv, + "context = %d, face = %s, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::MaterialParameter, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MaterialParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateMaterialxv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMaterialxv, face, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMaterialxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMaterialxv, face, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMaterialxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMaterialxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, pnamePacked, @@ -1386,7 +2166,7 @@ void GL_APIENTRY GL_Materialxv(GLenum face, GLenum pname, const GLfixed *param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMaterialxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1395,17 +2175,33 @@ void GL_APIENTRY GL_MatrixMode(GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMatrixMode, "context = %d, mode = %s", CID(context), - GLenumToString(GLESEnum::MatrixMode, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLMatrixMode, "context = %d, mode = %s", CID(context), + GLenumToString(GLESEnum::MatrixMode, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MatrixType modePacked = PackParam(mode); - bool isCallValid = (context->skipValidation() || - ValidateMatrixMode(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMatrixMode, modePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMatrixMode(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMatrixMode, modePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMatrixMode); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMatrixMode(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), modePacked); @@ -1414,7 +2210,7 @@ void GL_APIENTRY GL_MatrixMode(GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMatrixMode); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1423,16 +2219,32 @@ void GL_APIENTRY GL_MultMatrixf(const GLfloat *m) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultMatrixf, "context = %d, m = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)m); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultMatrixf, "context = %d, m = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)m)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateMultMatrixf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultMatrixf, m)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultMatrixf(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMultMatrixf, m); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMultMatrixf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMultMatrixf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), m); @@ -1441,7 +2253,7 @@ void GL_APIENTRY GL_MultMatrixf(const GLfloat *m) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultMatrixf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1450,16 +2262,32 @@ void GL_APIENTRY GL_MultMatrixx(const GLfixed *m) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultMatrixx, "context = %d, m = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)m); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultMatrixx, "context = %d, m = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)m)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateMultMatrixx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultMatrixx, m)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultMatrixx(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMultMatrixx, m); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMultMatrixx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMultMatrixx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), m); @@ -1468,7 +2296,7 @@ void GL_APIENTRY GL_MultMatrixx(const GLfixed *m) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultMatrixx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1477,17 +2305,33 @@ void GL_APIENTRY GL_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiTexCoord4f, "context = %d, target = %s, s = %f, t = %f, r = %f, q = %f", - CID(context), GLenumToString(GLESEnum::TextureUnit, target), s, t, r, q); + ANGLE_UNSAFE_TODO(EVENT( + context, GLMultiTexCoord4f, "context = %d, target = %s, s = %f, t = %f, r = %f, q = %f", + CID(context), GLenumToString(GLESEnum::TextureUnit, target), s, t, r, q)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateMultiTexCoord4f(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiTexCoord4f, target, s, t, r, q)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiTexCoord4f( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMultiTexCoord4f, target, s, t, r, q); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMultiTexCoord4f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMultiTexCoord4f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, s, t, r, @@ -1497,7 +2341,7 @@ void GL_APIENTRY GL_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultiTexCoord4f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1506,18 +2350,34 @@ void GL_APIENTRY GL_MultiTexCoord4x(GLenum texture, GLfixed s, GLfixed t, GLfixe { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiTexCoord4x, - "context = %d, texture = %s, s = 0x%X, t = 0x%X, r = 0x%X, q = 0x%X", CID(context), - GLenumToString(GLESEnum::TextureUnit, texture), s, t, r, q); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiTexCoord4x, + "context = %d, texture = %s, s = 0x%X, t = 0x%X, r = 0x%X, q = 0x%X", + CID(context), GLenumToString(GLESEnum::TextureUnit, texture), s, t, r, + q)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateMultiTexCoord4x(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiTexCoord4x, texture, s, t, r, q)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiTexCoord4x( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMultiTexCoord4x, texture, s, t, r, q); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLMultiTexCoord4x); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMultiTexCoord4x(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), texture, s, t, r, @@ -1527,7 +2387,7 @@ void GL_APIENTRY GL_MultiTexCoord4x(GLenum texture, GLfixed s, GLfixed t, GLfixe } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultiTexCoord4x); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1536,15 +2396,32 @@ void GL_APIENTRY GL_Normal3f(GLfloat nx, GLfloat ny, GLfloat nz) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLNormal3f, "context = %d, nx = %f, ny = %f, nz = %f", CID(context), nx, ny, nz); + ANGLE_UNSAFE_TODO(EVENT(context, GLNormal3f, "context = %d, nx = %f, ny = %f, nz = %f", + CID(context), nx, ny, nz)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateNormal3f(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLNormal3f, nx, ny, nz)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateNormal3f(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLNormal3f, nx, ny, nz); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLNormal3f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateNormal3f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), nx, ny, nz); @@ -1553,7 +2430,7 @@ void GL_APIENTRY GL_Normal3f(GLfloat nx, GLfloat ny, GLfloat nz) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLNormal3f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1562,16 +2439,32 @@ void GL_APIENTRY GL_Normal3x(GLfixed nx, GLfixed ny, GLfixed nz) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLNormal3x, "context = %d, nx = 0x%X, ny = 0x%X, nz = 0x%X", CID(context), nx, - ny, nz); + ANGLE_UNSAFE_TODO(EVENT(context, GLNormal3x, "context = %d, nx = 0x%X, ny = 0x%X, nz = 0x%X", + CID(context), nx, ny, nz)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateNormal3x(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLNormal3x, nx, ny, nz)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateNormal3x(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLNormal3x, nx, ny, nz); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLNormal3x); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateNormal3x(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), nx, ny, nz); @@ -1580,7 +2473,7 @@ void GL_APIENTRY GL_Normal3x(GLfixed nx, GLfixed ny, GLfixed nz) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLNormal3x); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1589,18 +2482,35 @@ void GL_APIENTRY GL_NormalPointer(GLenum type, GLsizei stride, const void *point { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLNormalPointer, - "context = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::NormalPointerType, type), stride, (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT(context, GLNormalPointer, + "context = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::NormalPointerType, type), stride, + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateNormalPointer(context, angle::EntryPoint::GLNormalPointer, - typePacked, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateNormalPointer(context, angle::EntryPoint::GLNormalPointer, + typePacked, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLNormalPointer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->normalPointer(typePacked, stride, pointer); } @@ -1608,7 +2518,7 @@ void GL_APIENTRY GL_NormalPointer(GLenum type, GLsizei stride, const void *point } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLNormalPointer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1617,16 +2527,33 @@ void GL_APIENTRY GL_Orthof(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLOrthof, "context = %d, l = %f, r = %f, b = %f, t = %f, n = %f, f = %f", - CID(context), l, r, b, t, n, f); + ANGLE_UNSAFE_TODO(EVENT(context, GLOrthof, + "context = %d, l = %f, r = %f, b = %f, t = %f, n = %f, f = %f", + CID(context), l, r, b, t, n, f)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateOrthof(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLOrthof, l, r, b, t, n, f)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateOrthof(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLOrthof, l, r, b, t, n, f); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLOrthof); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateOrthof(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), l, r, b, t, n, f); @@ -1635,7 +2562,7 @@ void GL_APIENTRY GL_Orthof(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLOrthof); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1644,17 +2571,34 @@ void GL_APIENTRY GL_Orthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLOrthox, - "context = %d, l = 0x%X, r = 0x%X, b = 0x%X, t = 0x%X, n = 0x%X, f = 0x%X", CID(context), - l, r, b, t, n, f); + ANGLE_UNSAFE_TODO( + EVENT(context, GLOrthox, + "context = %d, l = 0x%X, r = 0x%X, b = 0x%X, t = 0x%X, n = 0x%X, f = 0x%X", + CID(context), l, r, b, t, n, f)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateOrthox(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLOrthox, l, r, b, t, n, f)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateOrthox(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLOrthox, l, r, b, t, n, f); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLOrthox); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateOrthox(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), l, r, b, t, n, f); @@ -1663,7 +2607,7 @@ void GL_APIENTRY GL_Orthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLOrthox); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1672,18 +2616,33 @@ void GL_APIENTRY GL_PointParameterf(GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointParameterf, "context = %d, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::AllEnums, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLPointParameterf, "context = %d, pname = %s, param = %f", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PointParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidatePointParameterf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPointParameterf, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointParameterf( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPointParameterf, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPointParameterf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePointParameterf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pnamePacked, @@ -1693,7 +2652,7 @@ void GL_APIENTRY GL_PointParameterf(GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointParameterf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1702,18 +2661,34 @@ void GL_APIENTRY GL_PointParameterfv(GLenum pname, const GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointParameterfv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLPointParameterfv, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PointParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidatePointParameterfv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPointParameterfv, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointParameterfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPointParameterfv, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPointParameterfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePointParameterfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pnamePacked, @@ -1723,7 +2698,7 @@ void GL_APIENTRY GL_PointParameterfv(GLenum pname, const GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointParameterfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1732,18 +2707,33 @@ void GL_APIENTRY GL_PointParameterx(GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointParameterx, "context = %d, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::AllEnums, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLPointParameterx, "context = %d, pname = %s, param = 0x%X", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PointParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidatePointParameterx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPointParameterx, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointParameterx( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPointParameterx, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPointParameterx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePointParameterx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pnamePacked, @@ -1753,7 +2743,7 @@ void GL_APIENTRY GL_PointParameterx(GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointParameterx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1762,18 +2752,34 @@ void GL_APIENTRY GL_PointParameterxv(GLenum pname, const GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointParameterxv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLPointParameterxv, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PointParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidatePointParameterxv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPointParameterxv, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointParameterxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPointParameterxv, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPointParameterxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePointParameterxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pnamePacked, @@ -1783,7 +2789,7 @@ void GL_APIENTRY GL_PointParameterxv(GLenum pname, const GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointParameterxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1792,15 +2798,31 @@ void GL_APIENTRY GL_PointSize(GLfloat size) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointSize, "context = %d, size = %f", CID(context), size); + ANGLE_UNSAFE_TODO(EVENT(context, GLPointSize, "context = %d, size = %f", CID(context), size)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidatePointSize(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPointSize, size)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointSize(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPointSize, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPointSize); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePointSize(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), size); @@ -1809,7 +2831,7 @@ void GL_APIENTRY GL_PointSize(GLfloat size) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointSize); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1818,15 +2840,32 @@ void GL_APIENTRY GL_PointSizex(GLfixed size) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointSizex, "context = %d, size = 0x%X", CID(context), size); + ANGLE_UNSAFE_TODO( + EVENT(context, GLPointSizex, "context = %d, size = 0x%X", CID(context), size)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidatePointSizex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPointSizex, size)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointSizex(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPointSizex, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPointSizex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePointSizex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), size); @@ -1835,7 +2874,7 @@ void GL_APIENTRY GL_PointSizex(GLfixed size) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointSizex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1844,17 +2883,32 @@ void GL_APIENTRY GL_PolygonOffsetx(GLfixed factor, GLfixed units) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPolygonOffsetx, "context = %d, factor = 0x%X, units = 0x%X", CID(context), - factor, units); + ANGLE_UNSAFE_TODO(EVENT(context, GLPolygonOffsetx, "context = %d, factor = 0x%X, units = 0x%X", + CID(context), factor, units)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidatePolygonOffsetx(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPolygonOffsetx, factor, units)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePolygonOffsetx( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPolygonOffsetx, factor, units); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPolygonOffsetx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePolygonOffsetx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), factor, units); @@ -1863,7 +2917,7 @@ void GL_APIENTRY GL_PolygonOffsetx(GLfixed factor, GLfixed units) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPolygonOffsetx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1872,15 +2926,31 @@ void GL_APIENTRY GL_PopMatrix() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPopMatrix, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPopMatrix, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidatePopMatrix(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPopMatrix)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePopMatrix(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPopMatrix); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPopMatrix); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePopMatrix(context->getMutablePrivateState(), context->getMutablePrivateStateCache()); @@ -1889,7 +2959,7 @@ void GL_APIENTRY GL_PopMatrix() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPopMatrix); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1898,15 +2968,31 @@ void GL_APIENTRY GL_PushMatrix() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPushMatrix, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPushMatrix, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidatePushMatrix(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPushMatrix)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePushMatrix(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPushMatrix); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLPushMatrix); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePushMatrix(context->getMutablePrivateState(), context->getMutablePrivateStateCache()); @@ -1915,7 +3001,7 @@ void GL_APIENTRY GL_PushMatrix() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPushMatrix); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1924,16 +3010,32 @@ void GL_APIENTRY GL_Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRotatef, "context = %d, angle = %f, x = %f, y = %f, z = %f", CID(context), - angle, x, y, z); + ANGLE_UNSAFE_TODO(EVENT(context, GLRotatef, "context = %d, angle = %f, x = %f, y = %f, z = %f", + CID(context), angle, x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateRotatef(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRotatef, angle, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRotatef(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLRotatef, angle, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLRotatef); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateRotatef(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), angle, x, y, z); @@ -1942,7 +3044,7 @@ void GL_APIENTRY GL_Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLRotatef); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1951,16 +3053,33 @@ void GL_APIENTRY GL_Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRotatex, "context = %d, angle = 0x%X, x = 0x%X, y = 0x%X, z = 0x%X", - CID(context), angle, x, y, z); + ANGLE_UNSAFE_TODO(EVENT(context, GLRotatex, + "context = %d, angle = 0x%X, x = 0x%X, y = 0x%X, z = 0x%X", + CID(context), angle, x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateRotatex(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRotatex, angle, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRotatex(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLRotatex, angle, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLRotatex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateRotatex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), angle, x, y, z); @@ -1969,7 +3088,7 @@ void GL_APIENTRY GL_Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLRotatex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1978,17 +3097,32 @@ void GL_APIENTRY GL_SampleCoveragex(GLclampx value, GLboolean invert) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSampleCoveragex, "context = %d, value = 0x%X, invert = %s", CID(context), - value, GLbooleanToString(invert)); + ANGLE_UNSAFE_TODO(EVENT(context, GLSampleCoveragex, "context = %d, value = 0x%X, invert = %s", + CID(context), value, GLbooleanToString(invert))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateSampleCoveragex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleCoveragex, value, invert)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSampleCoveragex( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLSampleCoveragex, value, invert); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLSampleCoveragex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateSampleCoveragex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), value, invert); @@ -1997,7 +3131,7 @@ void GL_APIENTRY GL_SampleCoveragex(GLclampx value, GLboolean invert) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSampleCoveragex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2006,15 +3140,32 @@ void GL_APIENTRY GL_Scalef(GLfloat x, GLfloat y, GLfloat z) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLScalef, "context = %d, x = %f, y = %f, z = %f", CID(context), x, y, z); + ANGLE_UNSAFE_TODO( + EVENT(context, GLScalef, "context = %d, x = %f, y = %f, z = %f", CID(context), x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateScalef(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLScalef, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateScalef(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLScalef, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLScalef); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateScalef(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), x, y, z); @@ -2023,7 +3174,7 @@ void GL_APIENTRY GL_Scalef(GLfloat x, GLfloat y, GLfloat z) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLScalef); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2032,15 +3183,32 @@ void GL_APIENTRY GL_Scalex(GLfixed x, GLfixed y, GLfixed z) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLScalex, "context = %d, x = 0x%X, y = 0x%X, z = 0x%X", CID(context), x, y, z); + ANGLE_UNSAFE_TODO(EVENT(context, GLScalex, "context = %d, x = 0x%X, y = 0x%X, z = 0x%X", + CID(context), x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateScalex(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLScalex, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateScalex(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLScalex, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLScalex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateScalex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), x, y, z); @@ -2049,7 +3217,7 @@ void GL_APIENTRY GL_Scalex(GLfixed x, GLfixed y, GLfixed z) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLScalex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2058,17 +3226,33 @@ void GL_APIENTRY GL_ShadeModel(GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLShadeModel, "context = %d, mode = %s", CID(context), - GLenumToString(GLESEnum::ShadingModel, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLShadeModel, "context = %d, mode = %s", CID(context), + GLenumToString(GLESEnum::ShadingModel, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShadingModel modePacked = PackParam(mode); - bool isCallValid = (context->skipValidation() || - ValidateShadeModel(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLShadeModel, modePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateShadeModel(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLShadeModel, modePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLShadeModel); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateShadeModel(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), modePacked); @@ -2077,7 +3261,7 @@ void GL_APIENTRY GL_ShadeModel(GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLShadeModel); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2086,19 +3270,36 @@ void GL_APIENTRY GL_TexCoordPointer(GLint size, GLenum type, GLsizei stride, con { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexCoordPointer, - "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", - CID(context), size, GLenumToString(GLESEnum::TexCoordPointerType, type), stride, - (uintptr_t)pointer); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexCoordPointer, + "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), size, GLenumToString(GLESEnum::TexCoordPointerType, type), stride, + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexCoordPointer(context, angle::EntryPoint::GLTexCoordPointer, - size, typePacked, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexCoordPointer(context, angle::EntryPoint::GLTexCoordPointer, + size, typePacked, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexCoordPointer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texCoordPointer(size, typePacked, stride, pointer); } @@ -2106,7 +3307,7 @@ void GL_APIENTRY GL_TexCoordPointer(GLint size, GLenum type, GLsizei stride, con } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexCoordPointer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2115,19 +3316,35 @@ void GL_APIENTRY GL_TexEnvf(GLenum target, GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexEnvf, "context = %d, target = %s, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexEnvf, "context = %d, target = %s, pname = %s, param = %f", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateTexEnvf(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexEnvf, targetPacked, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexEnvf( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTexEnvf, targetPacked, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexEnvf); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTexEnvf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, pnamePacked, @@ -2137,7 +3354,7 @@ void GL_APIENTRY GL_TexEnvf(GLenum target, GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexEnvf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2146,20 +3363,36 @@ void GL_APIENTRY GL_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexEnvfv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexEnvfv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateTexEnvfv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexEnvfv, targetPacked, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexEnvfv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTexEnvfv, targetPacked, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexEnvfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTexEnvfv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, @@ -2169,7 +3402,7 @@ void GL_APIENTRY GL_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexEnvfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2178,19 +3411,35 @@ void GL_APIENTRY GL_TexEnvi(GLenum target, GLenum pname, GLint param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexEnvi, "context = %d, target = %s, pname = %s, param = %d", CID(context), - GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexEnvi, "context = %d, target = %s, pname = %s, param = %d", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateTexEnvi(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexEnvi, targetPacked, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexEnvi( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTexEnvi, targetPacked, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexEnvi); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTexEnvi(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, pnamePacked, @@ -2200,7 +3449,7 @@ void GL_APIENTRY GL_TexEnvi(GLenum target, GLenum pname, GLint param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexEnvi); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2209,20 +3458,36 @@ void GL_APIENTRY GL_TexEnviv(GLenum target, GLenum pname, const GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexEnviv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexEnviv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateTexEnviv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexEnviv, targetPacked, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexEnviv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTexEnviv, targetPacked, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexEnviv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTexEnviv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, @@ -2232,7 +3497,7 @@ void GL_APIENTRY GL_TexEnviv(GLenum target, GLenum pname, const GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexEnviv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2241,19 +3506,36 @@ void GL_APIENTRY GL_TexEnvx(GLenum target, GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexEnvx, "context = %d, target = %s, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexEnvx, + "context = %d, target = %s, pname = %s, param = 0x%X", CID(context), + GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateTexEnvx(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexEnvx, targetPacked, pnamePacked, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexEnvx( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTexEnvx, targetPacked, pnamePacked, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexEnvx); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTexEnvx(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, pnamePacked, @@ -2263,7 +3545,7 @@ void GL_APIENTRY GL_TexEnvx(GLenum target, GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexEnvx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2272,20 +3554,36 @@ void GL_APIENTRY GL_TexEnvxv(GLenum target, GLenum pname, const GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexEnvxv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), - GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexEnvxv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureEnvTarget, target), + GLenumToString(GLESEnum::TextureEnvParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureEnvTarget targetPacked = PackParam(target); TextureEnvParameter pnamePacked = PackParam(pname); - bool isCallValid = - (context->skipValidation() || - ValidateTexEnvxv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexEnvxv, targetPacked, pnamePacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexEnvxv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTexEnvxv, targetPacked, pnamePacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexEnvxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTexEnvxv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), targetPacked, @@ -2295,7 +3593,7 @@ void GL_APIENTRY GL_TexEnvxv(GLenum target, GLenum pname, const GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexEnvxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2304,18 +3602,35 @@ void GL_APIENTRY GL_TexParameterx(GLenum target, GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterx, "context = %d, target = %s, pname = %s, param = 0x%X", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterx, + "context = %d, target = %s, pname = %s, param = 0x%X", CID(context), + GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterx(context, angle::EntryPoint::GLTexParameterx, - targetPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterx(context, angle::EntryPoint::GLTexParameterx, + targetPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexParameterx); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterx(targetPacked, pname, param); } @@ -2323,7 +3638,7 @@ void GL_APIENTRY GL_TexParameterx(GLenum target, GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterx); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2332,19 +3647,36 @@ void GL_APIENTRY GL_TexParameterxv(GLenum target, GLenum pname, const GLfixed *p { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterxv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterxv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterxv(context, angle::EntryPoint::GLTexParameterxv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterxv(context, angle::EntryPoint::GLTexParameterxv, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTexParameterxv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterxv(targetPacked, pname, params); } @@ -2352,7 +3684,7 @@ void GL_APIENTRY GL_TexParameterxv(GLenum target, GLenum pname, const GLfixed *p } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterxv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2361,15 +3693,32 @@ void GL_APIENTRY GL_Translatef(GLfloat x, GLfloat y, GLfloat z) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTranslatef, "context = %d, x = %f, y = %f, z = %f", CID(context), x, y, z); + ANGLE_UNSAFE_TODO(EVENT(context, GLTranslatef, "context = %d, x = %f, y = %f, z = %f", + CID(context), x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateTranslatef(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTranslatef, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTranslatef(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTranslatef, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTranslatef); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTranslatef(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), x, y, z); @@ -2378,7 +3727,7 @@ void GL_APIENTRY GL_Translatef(GLfloat x, GLfloat y, GLfloat z) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTranslatef); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2387,16 +3736,32 @@ void GL_APIENTRY GL_Translatex(GLfixed x, GLfixed y, GLfixed z) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTranslatex, "context = %d, x = 0x%X, y = 0x%X, z = 0x%X", CID(context), x, y, - z); + ANGLE_UNSAFE_TODO(EVENT(context, GLTranslatex, "context = %d, x = 0x%X, y = 0x%X, z = 0x%X", + CID(context), x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateTranslatex(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTranslatex, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTranslatex(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLTranslatex, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLTranslatex); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateTranslatex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), x, y, z); @@ -2405,7 +3770,7 @@ void GL_APIENTRY GL_Translatex(GLfixed x, GLfixed y, GLfixed z) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTranslatex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2414,19 +3779,36 @@ void GL_APIENTRY GL_VertexPointer(GLint size, GLenum type, GLsizei stride, const { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexPointer, - "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", - CID(context), size, GLenumToString(GLESEnum::VertexPointerType, type), stride, - (uintptr_t)pointer); + ANGLE_UNSAFE_TODO( + EVENT(context, GLVertexPointer, + "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), size, GLenumToString(GLESEnum::VertexPointerType, type), stride, + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateVertexPointer(context, angle::EntryPoint::GLVertexPointer, size, - typePacked, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexPointer(context, angle::EntryPoint::GLVertexPointer, + size, typePacked, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES10(context, angle::EntryPoint::GLVertexPointer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->vertexPointer(size, typePacked, stride, pointer); } @@ -2434,7 +3816,7 @@ void GL_APIENTRY GL_VertexPointer(GLint size, GLenum type, GLsizei stride, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexPointer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } diff --git a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp index 751fd2d52e9..18b5706d440 100644 --- a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp @@ -28,16 +28,28 @@ void GL_APIENTRY GL_ActiveTexture(GLenum texture) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLActiveTexture, "context = %d, texture = %s", CID(context), - GLenumToString(GLESEnum::TextureUnit, texture)); + ANGLE_UNSAFE_TODO(EVENT(context, GLActiveTexture, "context = %d, texture = %s", CID(context), + GLenumToString(GLESEnum::TextureUnit, texture))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateActiveTexture(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLActiveTexture, texture)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateActiveTexture(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLActiveTexture, texture); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateActiveTexture(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), texture); @@ -46,7 +58,7 @@ void GL_APIENTRY GL_ActiveTexture(GLenum texture) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLActiveTexture); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -55,22 +67,34 @@ void GL_APIENTRY GL_AttachShader(GLuint program, GLuint shader) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLAttachShader, "context = %d, program = %u, shader = %u", CID(context), program, - shader); + ANGLE_UNSAFE_TODO(EVENT(context, GLAttachShader, "context = %d, program = %u, shader = %u", + CID(context), program, shader)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLAttachShader) && - ValidateAttachShader(context, angle::EntryPoint::GLAttachShader, programPacked, - shaderPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateAttachShader(context, angle::EntryPoint::GLAttachShader, + programPacked, shaderPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLAttachShader); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->attachShader(programPacked, shaderPacked); } @@ -78,7 +102,7 @@ void GL_APIENTRY GL_AttachShader(GLuint program, GLuint shader) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLAttachShader); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -87,22 +111,34 @@ void GL_APIENTRY GL_BindAttribLocation(GLuint program, GLuint index, const GLcha { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindAttribLocation, - "context = %d, program = %u, index = %u, name = 0x%016" PRIxPTR "", CID(context), program, - index, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindAttribLocation, + "context = %d, program = %u, index = %u, name = 0x%016" PRIxPTR "", + CID(context), program, index, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindAttribLocation) && - ValidateBindAttribLocation(context, angle::EntryPoint::GLBindAttribLocation, - programPacked, index, name))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindAttribLocation( + context, angle::EntryPoint::GLBindAttribLocation, programPacked, index, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBindAttribLocation); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindAttribLocation(programPacked, index, name); } @@ -110,7 +146,7 @@ void GL_APIENTRY GL_BindAttribLocation(GLuint program, GLuint index, const GLcha } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindAttribLocation); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -119,18 +155,31 @@ void GL_APIENTRY GL_BindBuffer(GLenum target, GLuint buffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindBuffer, "context = %d, target = %s, buffer = %u", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), buffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindBuffer, "context = %d, target = %s, buffer = %u", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + buffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); - bool isCallValid = (context->skipValidation() || - ValidateBindBuffer(context, angle::EntryPoint::GLBindBuffer, - targetPacked, bufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindBuffer(context, angle::EntryPoint::GLBindBuffer, + targetPacked, bufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindBuffer(targetPacked, bufferPacked); } @@ -138,7 +187,7 @@ void GL_APIENTRY GL_BindBuffer(GLenum target, GLuint buffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindBuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -147,17 +196,38 @@ void GL_APIENTRY GL_BindFramebuffer(GLenum target, GLuint framebuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindFramebuffer, "context = %d, target = %s, framebuffer = %u", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target), framebuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindFramebuffer, + "context = %d, target = %s, framebuffer = %u", CID(context), + GLenumToString(GLESEnum::FramebufferTarget, target), framebuffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID framebufferPacked = PackParam(framebuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateBindFramebuffer(context, angle::EntryPoint::GLBindFramebuffer, - target, framebufferPacked)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindFramebuffer(context, angle::EntryPoint::GLBindFramebuffer, + target, framebufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBindFramebuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindFramebuffer(target, framebufferPacked); } @@ -165,7 +235,7 @@ void GL_APIENTRY GL_BindFramebuffer(GLenum target, GLuint framebuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindFramebuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -174,21 +244,34 @@ void GL_APIENTRY GL_BindRenderbuffer(GLenum target, GLuint renderbuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindRenderbuffer, "context = %d, target = %s, renderbuffer = %u", CID(context), - GLenumToString(GLESEnum::RenderbufferTarget, target), renderbuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindRenderbuffer, + "context = %d, target = %s, renderbuffer = %u", CID(context), + GLenumToString(GLESEnum::RenderbufferTarget, target), renderbuffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID renderbufferPacked = PackParam(renderbuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindRenderbuffer) && - ValidateBindRenderbuffer(context, angle::EntryPoint::GLBindRenderbuffer, target, - renderbufferPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindRenderbuffer( + context, angle::EntryPoint::GLBindRenderbuffer, target, renderbufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBindRenderbuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindRenderbuffer(target, renderbufferPacked); } @@ -196,7 +279,7 @@ void GL_APIENTRY GL_BindRenderbuffer(GLenum target, GLuint renderbuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindRenderbuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -205,18 +288,31 @@ void GL_APIENTRY GL_BindTexture(GLenum target, GLuint texture) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindTexture, "context = %d, target = %s, texture = %u", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), texture); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindTexture, "context = %d, target = %s, texture = %u", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + texture)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateBindTexture(context, angle::EntryPoint::GLBindTexture, - targetPacked, texturePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindTexture(context, angle::EntryPoint::GLBindTexture, + targetPacked, texturePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindTexture(targetPacked, texturePacked); } @@ -224,7 +320,7 @@ void GL_APIENTRY GL_BindTexture(GLenum target, GLuint texture) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindTexture); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -233,20 +329,33 @@ void GL_APIENTRY GL_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendColor, "context = %d, red = %f, green = %f, blue = %f, alpha = %f", - CID(context), red, green, blue, alpha); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendColor, + "context = %d, red = %f, green = %f, blue = %f, alpha = %f", + CID(context), red, green, blue, alpha)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendColor) && - ValidateBlendColor(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendColor, red, green, blue, alpha))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendColor( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendColor, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBlendColor); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendColor(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, @@ -256,7 +365,7 @@ void GL_APIENTRY GL_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendColor); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -265,16 +374,32 @@ void GL_APIENTRY GL_BlendEquation(GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquation, "context = %d, mode = %s", CID(context), - GLenumToString(GLESEnum::BlendEquationModeEXT, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquation, "context = %d, mode = %s", CID(context), + GLenumToString(GLESEnum::BlendEquationModeEXT, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateBlendEquation(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquation, mode)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquation(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquation, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBlendEquation); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquation(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), mode); @@ -283,7 +408,7 @@ void GL_APIENTRY GL_BlendEquation(GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquation); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -292,18 +417,34 @@ void GL_APIENTRY GL_BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationSeparate, "context = %d, modeRGB = %s, modeAlpha = %s", - CID(context), GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), - GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationSeparate, + "context = %d, modeRGB = %s, modeAlpha = %s", CID(context), + GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), + GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendEquationSeparate( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationSeparate, modeRGB, modeAlpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationSeparate( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationSeparate, modeRGB, modeAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBlendEquationSeparate); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationSeparate(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), modeRGB, @@ -313,7 +454,7 @@ void GL_APIENTRY GL_BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquationSeparate); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -322,17 +463,29 @@ void GL_APIENTRY GL_BlendFunc(GLenum sfactor, GLenum dfactor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFunc, "context = %d, sfactor = %s, dfactor = %s", CID(context), - GLenumToString(GLESEnum::BlendingFactor, sfactor), - GLenumToString(GLESEnum::BlendingFactor, dfactor)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendFunc, "context = %d, sfactor = %s, dfactor = %s", + CID(context), GLenumToString(GLESEnum::BlendingFactor, sfactor), + GLenumToString(GLESEnum::BlendingFactor, dfactor))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateBlendFunc(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFunc, sfactor, dfactor)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFunc(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFunc, sfactor, dfactor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFunc(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), sfactor, dfactor); @@ -341,7 +494,7 @@ void GL_APIENTRY GL_BlendFunc(GLenum sfactor, GLenum dfactor) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFunc); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -353,22 +506,38 @@ void GL_APIENTRY GL_BlendFuncSeparate(GLenum sfactorRGB, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFuncSeparate, - "context = %d, sfactorRGB = %s, dfactorRGB = %s, sfactorAlpha = %s, dfactorAlpha = %s", - CID(context), GLenumToString(GLESEnum::BlendingFactor, sfactorRGB), - GLenumToString(GLESEnum::BlendingFactor, dfactorRGB), - GLenumToString(GLESEnum::BlendingFactor, sfactorAlpha), - GLenumToString(GLESEnum::BlendingFactor, dfactorAlpha)); - - if (context) - { - bool isCallValid = - (context->skipValidation() || - ValidateBlendFuncSeparate(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFuncSeparate, sfactorRGB, - dfactorRGB, sfactorAlpha, dfactorAlpha)); - if (isCallValid) + ANGLE_UNSAFE_TODO(EVENT( + context, GLBlendFuncSeparate, + "context = %d, sfactorRGB = %s, dfactorRGB = %s, sfactorAlpha = %s, dfactorAlpha = %s", + CID(context), GLenumToString(GLESEnum::BlendingFactor, sfactorRGB), + GLenumToString(GLESEnum::BlendingFactor, dfactorRGB), + GLenumToString(GLESEnum::BlendingFactor, sfactorAlpha), + GLenumToString(GLESEnum::BlendingFactor, dfactorAlpha))); + + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFuncSeparate( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFuncSeparate, sfactorRGB, dfactorRGB, sfactorAlpha, + dfactorAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLBlendFuncSeparate); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFuncSeparate(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), sfactorRGB, @@ -379,7 +548,7 @@ void GL_APIENTRY GL_BlendFuncSeparate(GLenum sfactorRGB, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFuncSeparate); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -388,21 +557,34 @@ void GL_APIENTRY GL_BufferData(GLenum target, GLsizeiptr size, const void *data, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBufferData, - "context = %d, target = %s, size = %llu, data = 0x%016" PRIxPTR ", usage = %s", - CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), - static_cast(size), (uintptr_t)data, - GLenumToString(GLESEnum::BufferUsageARB, usage)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBufferData, + "context = %d, target = %s, size = %llu, data = 0x%016" PRIxPTR + ", usage = %s", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(size), (uintptr_t)data, + GLenumToString(GLESEnum::BufferUsageARB, usage))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); BufferUsage usagePacked = PackParam(usage); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateBufferData(context, angle::EntryPoint::GLBufferData, - targetPacked, size, data, usagePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBufferData(context, angle::EntryPoint::GLBufferData, + targetPacked, size, data, usagePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bufferData(targetPacked, size, data, usagePacked); } @@ -410,7 +592,7 @@ void GL_APIENTRY GL_BufferData(GLenum target, GLsizeiptr size, const void *data, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBufferData); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -419,20 +601,33 @@ void GL_APIENTRY GL_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr siz { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBufferSubData, - "context = %d, target = %s, offset = %llu, size = %llu, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), - static_cast(offset), static_cast(size), - (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBufferSubData, + "context = %d, target = %s, offset = %llu, size = %llu, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(offset), static_cast(size), + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateBufferSubData(context, angle::EntryPoint::GLBufferSubData, - targetPacked, offset, size, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBufferSubData(context, angle::EntryPoint::GLBufferSubData, + targetPacked, offset, size, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bufferSubData(targetPacked, offset, size, data); } @@ -440,7 +635,7 @@ void GL_APIENTRY GL_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr siz } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBufferSubData); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -449,17 +644,33 @@ GLenum GL_APIENTRY GL_CheckFramebufferStatus(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCheckFramebufferStatus, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLCheckFramebufferStatus, "context = %d, target = %s", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target))); GLenum returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateCheckFramebufferStatus( - context, angle::EntryPoint::GLCheckFramebufferStatus, target)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCheckFramebufferStatus( + context, angle::EntryPoint::GLCheckFramebufferStatus, target); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLCheckFramebufferStatus); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->checkFramebufferStatus(target); } @@ -472,7 +683,7 @@ GLenum GL_APIENTRY GL_CheckFramebufferStatus(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCheckFramebufferStatus); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -483,19 +694,27 @@ void GL_APIENTRY GL_Clear(GLbitfield mask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClear, "context = %d, mask = %s", CID(context), - GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLClear, "context = %d, mask = %s", CID(context), + GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClear) && - ValidateClear(context, angle::EntryPoint::GLClear, mask))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClear(context, angle::EntryPoint::GLClear, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clear(mask); } @@ -503,7 +722,7 @@ void GL_APIENTRY GL_Clear(GLbitfield mask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClear); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -512,20 +731,29 @@ void GL_APIENTRY GL_ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearColor, "context = %d, red = %f, green = %f, blue = %f, alpha = %f", - CID(context), red, green, blue, alpha); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearColor, + "context = %d, red = %f, green = %f, blue = %f, alpha = %f", + CID(context), red, green, blue, alpha)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearColor) && - ValidateClearColor(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearColor, red, green, blue, alpha))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearColor( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClearColor, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClearColor(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, @@ -535,7 +763,7 @@ void GL_APIENTRY GL_ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearColor); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -544,19 +772,27 @@ void GL_APIENTRY GL_ClearDepthf(GLfloat d) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearDepthf, "context = %d, d = %f", CID(context), d); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearDepthf, "context = %d, d = %f", CID(context), d)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearDepthf) && - ValidateClearDepthf(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearDepthf, d))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearDepthf(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClearDepthf, d); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClearDepthf(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), d); @@ -565,7 +801,7 @@ void GL_APIENTRY GL_ClearDepthf(GLfloat d) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearDepthf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -574,19 +810,27 @@ void GL_APIENTRY GL_ClearStencil(GLint s) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearStencil, "context = %d, s = %d", CID(context), s); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearStencil, "context = %d, s = %d", CID(context), s)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearStencil) && - ValidateClearStencil(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearStencil, s))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearStencil(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClearStencil, s); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClearStencil(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), s); @@ -595,7 +839,7 @@ void GL_APIENTRY GL_ClearStencil(GLint s) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearStencil); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -604,18 +848,30 @@ void GL_APIENTRY GL_ColorMask(GLboolean red, GLboolean green, GLboolean blue, GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColorMask, "context = %d, red = %s, green = %s, blue = %s, alpha = %s", - CID(context), GLbooleanToString(red), GLbooleanToString(green), GLbooleanToString(blue), - GLbooleanToString(alpha)); + ANGLE_UNSAFE_TODO(EVENT(context, GLColorMask, + "context = %d, red = %s, green = %s, blue = %s, alpha = %s", + CID(context), GLbooleanToString(red), GLbooleanToString(green), + GLbooleanToString(blue), GLbooleanToString(alpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateColorMask(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColorMask, red, green, blue, alpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColorMask( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColorMask, red, green, blue, alpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColorMask(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), red, green, blue, @@ -625,7 +881,7 @@ void GL_APIENTRY GL_ColorMask(GLboolean red, GLboolean green, GLboolean blue, GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColorMask); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -634,19 +890,33 @@ void GL_APIENTRY GL_CompileShader(GLuint shader) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompileShader, "context = %d, shader = %u", CID(context), shader); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCompileShader, "context = %d, shader = %u", CID(context), shader)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompileShader) && - ValidateCompileShader(context, angle::EntryPoint::GLCompileShader, shaderPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompileShader(context, angle::EntryPoint::GLCompileShader, + shaderPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLCompileShader); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compileShader(shaderPacked); } @@ -654,7 +924,7 @@ void GL_APIENTRY GL_CompileShader(GLuint shader) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCompileShader); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -670,26 +940,35 @@ void GL_APIENTRY GL_CompressedTexImage2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexImage2D, - "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " - "border = %d, imageSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, border, - imageSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLCompressedTexImage2D, + "context = %d, target = %s, level = %d, internalformat = %s, width = " + "%d, height = %d, border = %d, imageSize = %d, data = 0x%016" PRIxPTR + "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, + border, imageSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexImage2D) && - ValidateCompressedTexImage2D(context, angle::EntryPoint::GLCompressedTexImage2D, - targetPacked, level, internalformat, width, height, - border, imageSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexImage2D( + context, angle::EntryPoint::GLCompressedTexImage2D, targetPacked, level, + internalformat, width, height, border, imageSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexImage2D(targetPacked, level, internalformat, width, height, border, imageSize, data); @@ -699,7 +978,7 @@ void GL_APIENTRY GL_CompressedTexImage2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCompressedTexImage2D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -716,26 +995,35 @@ void GL_APIENTRY GL_CompressedTexSubImage2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexSubImage2D, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = " - "%d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - width, height, GLenumToString(GLESEnum::InternalFormat, format), imageSize, - (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCompressedTexSubImage2D, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, " + "height = %d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, + yoffset, width, height, GLenumToString(GLESEnum::InternalFormat, format), imageSize, + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexSubImage2D) && - ValidateCompressedTexSubImage2D(context, angle::EntryPoint::GLCompressedTexSubImage2D, - targetPacked, level, xoffset, yoffset, width, height, - format, imageSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexSubImage2D( + context, angle::EntryPoint::GLCompressedTexSubImage2D, targetPacked, level, + xoffset, yoffset, width, height, format, imageSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexSubImage2D(targetPacked, level, xoffset, yoffset, width, height, format, imageSize, data); @@ -745,7 +1033,8 @@ void GL_APIENTRY GL_CompressedTexSubImage2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexSubImage2D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -761,24 +1050,38 @@ void GL_APIENTRY GL_CopyTexImage2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyTexImage2D, - "context = %d, target = %s, level = %d, internalformat = %s, x = %d, y = %d, width = %d, " - "height = %d, border = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::InternalFormat, internalformat), x, y, width, height, border); + ANGLE_UNSAFE_TODO(EVENT(context, GLCopyTexImage2D, + "context = %d, target = %s, level = %d, internalformat = %s, x = %d, y " + "= %d, width = %d, height = %d, border = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::InternalFormat, internalformat), x, y, width, + height, border)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyTexImage2D) && - ValidateCopyTexImage2D(context, angle::EntryPoint::GLCopyTexImage2D, targetPacked, - level, internalformat, x, y, width, height, border))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyTexImage2D(context, angle::EntryPoint::GLCopyTexImage2D, + targetPacked, level, internalformat, x, y, + width, height, border); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyTexImage2D(targetPacked, level, internalformat, x, y, width, height, border); @@ -788,7 +1091,7 @@ void GL_APIENTRY GL_CopyTexImage2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyTexImage2D); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -804,25 +1107,37 @@ void GL_APIENTRY GL_CopyTexSubImage2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyTexSubImage2D, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, x = %d, y = %d, " - "width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, x, - y, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLCopyTexSubImage2D, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, x " + "= %d, y = %d, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + xoffset, yoffset, x, y, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyTexSubImage2D) && - ValidateCopyTexSubImage2D(context, angle::EntryPoint::GLCopyTexSubImage2D, - targetPacked, level, xoffset, yoffset, x, y, width, - height))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyTexSubImage2D( + context, angle::EntryPoint::GLCopyTexSubImage2D, targetPacked, level, xoffset, + yoffset, x, y, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyTexSubImage2D(targetPacked, level, xoffset, yoffset, x, y, width, height); } @@ -831,7 +1146,7 @@ void GL_APIENTRY GL_CopyTexSubImage2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyTexSubImage2D); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -840,19 +1155,31 @@ GLuint GL_APIENTRY GL_CreateProgram() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCreateProgram, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLCreateProgram, "context = %d", CID(context))); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCreateProgram) && - ValidateCreateProgram(context, angle::EntryPoint::GLCreateProgram))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCreateProgram(context, angle::EntryPoint::GLCreateProgram); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLCreateProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->createProgram(); } @@ -864,7 +1191,7 @@ GLuint GL_APIENTRY GL_CreateProgram() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCreateProgram); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -875,21 +1202,34 @@ GLuint GL_APIENTRY GL_CreateShader(GLenum type) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCreateShader, "context = %d, type = %s", CID(context), - GLenumToString(GLESEnum::ShaderType, type)); + ANGLE_UNSAFE_TODO(EVENT(context, GLCreateShader, "context = %d, type = %s", CID(context), + GLenumToString(GLESEnum::ShaderType, type))); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCreateShader) && - ValidateCreateShader(context, angle::EntryPoint::GLCreateShader, typePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateCreateShader(context, angle::EntryPoint::GLCreateShader, typePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLCreateShader); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->createShader(typePacked); } @@ -901,7 +1241,7 @@ GLuint GL_APIENTRY GL_CreateShader(GLenum type) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCreateShader); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -912,17 +1252,29 @@ void GL_APIENTRY GL_CullFace(GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCullFace, "context = %d, mode = %s", CID(context), - GLenumToString(GLESEnum::TriangleFace, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLCullFace, "context = %d, mode = %s", CID(context), + GLenumToString(GLESEnum::TriangleFace, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { CullFaceMode modePacked = PackParam(mode); - bool isCallValid = (context->skipValidation() || - ValidateCullFace(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCullFace, modePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCullFace(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLCullFace, modePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateCullFace(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), modePacked); @@ -931,7 +1283,7 @@ void GL_APIENTRY GL_CullFace(GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCullFace); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -940,17 +1292,30 @@ void GL_APIENTRY GL_DeleteBuffers(GLsizei n, const GLuint *buffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteBuffers, "context = %d, n = %d, buffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)buffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteBuffers, + "context = %d, n = %d, buffers = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)buffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const BufferID *buffersPacked = PackParam(buffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteBuffers(context, angle::EntryPoint::GLDeleteBuffers, n, buffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteBuffers(context, angle::EntryPoint::GLDeleteBuffers, n, + buffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteBuffers(n, buffersPacked); } @@ -958,7 +1323,7 @@ void GL_APIENTRY GL_DeleteBuffers(GLsizei n, const GLuint *buffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteBuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -967,18 +1332,34 @@ void GL_APIENTRY GL_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteFramebuffers, "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)framebuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteFramebuffers, + "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)framebuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const FramebufferID *framebuffersPacked = PackParam(framebuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteFramebuffers(context, angle::EntryPoint::GLDeleteFramebuffers, n, - framebuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteFramebuffers( + context, angle::EntryPoint::GLDeleteFramebuffers, n, framebuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLDeleteFramebuffers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteFramebuffers(n, framebuffersPacked); } @@ -986,7 +1367,7 @@ void GL_APIENTRY GL_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteFramebuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -995,16 +1376,33 @@ void GL_APIENTRY GL_DeleteProgram(GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteProgram, "context = %d, program = %u", CID(context), program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDeleteProgram, "context = %d, program = %u", CID(context), program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteProgram(context, angle::EntryPoint::GLDeleteProgram, programPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteProgram(context, angle::EntryPoint::GLDeleteProgram, + programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLDeleteProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteProgram(programPacked); } @@ -1012,7 +1410,7 @@ void GL_APIENTRY GL_DeleteProgram(GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteProgram); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1021,19 +1419,35 @@ void GL_APIENTRY GL_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteRenderbuffers, "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)renderbuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteRenderbuffers, + "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)renderbuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const RenderbufferID *renderbuffersPacked = PackParam(renderbuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteRenderbuffers(context, angle::EntryPoint::GLDeleteRenderbuffers, n, - renderbuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteRenderbuffers( + context, angle::EntryPoint::GLDeleteRenderbuffers, n, renderbuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLDeleteRenderbuffers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteRenderbuffers(n, renderbuffersPacked); } @@ -1041,7 +1455,7 @@ void GL_APIENTRY GL_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteRenderbuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1050,16 +1464,33 @@ void GL_APIENTRY GL_DeleteShader(GLuint shader) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteShader, "context = %d, shader = %u", CID(context), shader); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDeleteShader, "context = %d, shader = %u", CID(context), shader)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteShader(context, angle::EntryPoint::GLDeleteShader, shaderPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDeleteShader(context, angle::EntryPoint::GLDeleteShader, shaderPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLDeleteShader); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteShader(shaderPacked); } @@ -1067,7 +1498,7 @@ void GL_APIENTRY GL_DeleteShader(GLuint shader) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteShader); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1076,17 +1507,30 @@ void GL_APIENTRY GL_DeleteTextures(GLsizei n, const GLuint *textures) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteTextures, "context = %d, n = %d, textures = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)textures); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteTextures, + "context = %d, n = %d, textures = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)textures)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const TextureID *texturesPacked = PackParam(textures); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDeleteTextures(context, angle::EntryPoint::GLDeleteTextures, n, - texturesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteTextures(context, angle::EntryPoint::GLDeleteTextures, + n, texturesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteTextures(n, texturesPacked); } @@ -1094,7 +1538,7 @@ void GL_APIENTRY GL_DeleteTextures(GLsizei n, const GLuint *textures) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteTextures); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1103,16 +1547,28 @@ void GL_APIENTRY GL_DepthFunc(GLenum func) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDepthFunc, "context = %d, func = %s", CID(context), - GLenumToString(GLESEnum::DepthFunction, func)); + ANGLE_UNSAFE_TODO(EVENT(context, GLDepthFunc, "context = %d, func = %s", CID(context), + GLenumToString(GLESEnum::DepthFunction, func))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDepthFunc(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDepthFunc, func)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDepthFunc(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDepthFunc, func); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDepthFunc(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), func); @@ -1121,7 +1577,7 @@ void GL_APIENTRY GL_DepthFunc(GLenum func) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDepthFunc); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1130,15 +1586,28 @@ void GL_APIENTRY GL_DepthMask(GLboolean flag) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDepthMask, "context = %d, flag = %s", CID(context), GLbooleanToString(flag)); + ANGLE_UNSAFE_TODO(EVENT(context, GLDepthMask, "context = %d, flag = %s", CID(context), + GLbooleanToString(flag))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDepthMask(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDepthMask, flag)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDepthMask(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDepthMask, flag); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDepthMask(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), flag); @@ -1147,7 +1616,7 @@ void GL_APIENTRY GL_DepthMask(GLboolean flag) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDepthMask); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1156,15 +1625,28 @@ void GL_APIENTRY GL_DepthRangef(GLfloat n, GLfloat f) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDepthRangef, "context = %d, n = %f, f = %f", CID(context), n, f); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDepthRangef, "context = %d, n = %f, f = %f", CID(context), n, f)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDepthRangef(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDepthRangef, n, f)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDepthRangef(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDepthRangef, n, f); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDepthRangef(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), n, f); @@ -1173,7 +1655,7 @@ void GL_APIENTRY GL_DepthRangef(GLfloat n, GLfloat f) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDepthRangef); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1182,22 +1664,34 @@ void GL_APIENTRY GL_DetachShader(GLuint program, GLuint shader) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDetachShader, "context = %d, program = %u, shader = %u", CID(context), program, - shader); + ANGLE_UNSAFE_TODO(EVENT(context, GLDetachShader, "context = %d, program = %u, shader = %u", + CID(context), program, shader)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDetachShader) && - ValidateDetachShader(context, angle::EntryPoint::GLDetachShader, programPacked, - shaderPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDetachShader(context, angle::EntryPoint::GLDetachShader, + programPacked, shaderPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLDetachShader); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->detachShader(programPacked, shaderPacked); } @@ -1205,7 +1699,7 @@ void GL_APIENTRY GL_DetachShader(GLuint program, GLuint shader) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDetachShader); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1214,16 +1708,28 @@ void GL_APIENTRY GL_Disable(GLenum cap) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisable, "context = %d, cap = %s", CID(context), - GLenumToString(GLESEnum::EnableCap, cap)); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisable, "context = %d, cap = %s", CID(context), + GLenumToString(GLESEnum::EnableCap, cap))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateDisable(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDisable, cap)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisable(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDisable, cap); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDisable(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), cap); @@ -1232,7 +1738,7 @@ void GL_APIENTRY GL_Disable(GLenum cap) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDisable); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1241,23 +1747,42 @@ void GL_APIENTRY GL_DisableVertexAttribArray(GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisableVertexAttribArray, "context = %d, index = %u", CID(context), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisableVertexAttribArray, "context = %d, index = %u", + CID(context), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDisableVertexAttribArray( - context, angle::EntryPoint::GLDisableVertexAttribArray, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->disableVertexAttribArray(index); + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisableVertexAttribArray( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDisableVertexAttribArray, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLDisableVertexAttribArray); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateDisableVertexAttribArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index); } ANGLE_CAPTURE_GL(DisableVertexAttribArray, isCallValid, context, index); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDisableVertexAttribArray); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1266,17 +1791,30 @@ void GL_APIENTRY GL_DrawArrays(GLenum mode, GLint first, GLsizei count) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArrays, "context = %d, mode = %s, first = %d, count = %d", CID(context), - GLenumToString(GLESEnum::PrimitiveType, mode), first, count); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawArrays, + "context = %d, mode = %s, first = %d, count = %d", CID(context), + GLenumToString(GLESEnum::PrimitiveType, mode), first, count)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawArrays(context, angle::EntryPoint::GLDrawArrays, modePacked, - first, count)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawArrays(context, angle::EntryPoint::GLDrawArrays, + modePacked, first, count); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawArrays(modePacked, first, count); } @@ -1284,7 +1822,7 @@ void GL_APIENTRY GL_DrawArrays(GLenum mode, GLint first, GLsizei count) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawArrays); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1293,20 +1831,33 @@ void GL_APIENTRY GL_DrawElements(GLenum mode, GLsizei count, GLenum type, const { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElements, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElements, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElements(context, angle::EntryPoint::GLDrawElements, - modePacked, count, typePacked, indices)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElements(context, angle::EntryPoint::GLDrawElements, + modePacked, count, typePacked, indices); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElements(modePacked, count, typePacked, indices); } @@ -1315,7 +1866,7 @@ void GL_APIENTRY GL_DrawElements(GLenum mode, GLsizei count, GLenum type, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawElements); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1324,16 +1875,28 @@ void GL_APIENTRY GL_Enable(GLenum cap) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEnable, "context = %d, cap = %s", CID(context), - GLenumToString(GLESEnum::EnableCap, cap)); + ANGLE_UNSAFE_TODO(EVENT(context, GLEnable, "context = %d, cap = %s", CID(context), + GLenumToString(GLESEnum::EnableCap, cap))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateEnable(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEnable, cap)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEnable(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLEnable, cap); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateEnable(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), cap); @@ -1342,7 +1905,7 @@ void GL_APIENTRY GL_Enable(GLenum cap) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEnable); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1351,23 +1914,42 @@ void GL_APIENTRY GL_EnableVertexAttribArray(GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEnableVertexAttribArray, "context = %d, index = %u", CID(context), index); + ANGLE_UNSAFE_TODO( + EVENT(context, GLEnableVertexAttribArray, "context = %d, index = %u", CID(context), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateEnableVertexAttribArray( - context, angle::EntryPoint::GLEnableVertexAttribArray, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEnableVertexAttribArray( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLEnableVertexAttribArray, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLEnableVertexAttribArray); + } + } + if (ANGLE_LIKELY(isCallValid)) { - context->enableVertexAttribArray(index); + ContextPrivateEnableVertexAttribArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index); } ANGLE_CAPTURE_GL(EnableVertexAttribArray, isCallValid, context, index); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLEnableVertexAttribArray); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1376,18 +1958,26 @@ void GL_APIENTRY GL_Finish() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFinish, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFinish, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFinish) && - ValidateFinish(context, angle::EntryPoint::GLFinish))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFinish(context, angle::EntryPoint::GLFinish); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->finish(); } @@ -1395,7 +1985,7 @@ void GL_APIENTRY GL_Finish() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFinish); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -1404,18 +1994,26 @@ void GL_APIENTRY GL_Flush() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFlush, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFlush, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFlush) && - ValidateFlush(context, angle::EntryPoint::GLFlush))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFlush(context, angle::EntryPoint::GLFlush); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->flush(); } @@ -1423,7 +2021,7 @@ void GL_APIENTRY GL_Flush() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFlush); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -1435,21 +2033,42 @@ void GL_APIENTRY GL_FramebufferRenderbuffer(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferRenderbuffer, - "context = %d, target = %s, attachment = %s, renderbuffertarget = %s, renderbuffer = %u", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::RenderbufferTarget, renderbuffertarget), renderbuffer); + ANGLE_UNSAFE_TODO(EVENT( + context, GLFramebufferRenderbuffer, + "context = %d, target = %s, attachment = %s, renderbuffertarget = %s, renderbuffer = %u", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::RenderbufferTarget, renderbuffertarget), renderbuffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID renderbufferPacked = PackParam(renderbuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateFramebufferRenderbuffer( - context, angle::EntryPoint::GLFramebufferRenderbuffer, target, - attachment, renderbuffertarget, renderbufferPacked)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferRenderbuffer( + context, angle::EntryPoint::GLFramebufferRenderbuffer, target, attachment, + renderbuffertarget, renderbufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLFramebufferRenderbuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbufferPacked); @@ -1459,7 +2078,8 @@ void GL_APIENTRY GL_FramebufferRenderbuffer(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferRenderbuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1472,22 +2092,43 @@ void GL_APIENTRY GL_FramebufferTexture2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTexture2D, - "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::TextureTarget, textarget), texture, level); + ANGLE_UNSAFE_TODO(EVENT( + context, GLFramebufferTexture2D, + "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::TextureTarget, textarget), texture, level)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget textargetPacked = PackParam(textarget); TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateFramebufferTexture2D( - context, angle::EntryPoint::GLFramebufferTexture2D, target, - attachment, textargetPacked, texturePacked, level)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTexture2D( + context, angle::EntryPoint::GLFramebufferTexture2D, target, attachment, + textargetPacked, texturePacked, level); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLFramebufferTexture2D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexture2D(target, attachment, textargetPacked, texturePacked, level); @@ -1497,7 +2138,7 @@ void GL_APIENTRY GL_FramebufferTexture2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFramebufferTexture2D); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1506,16 +2147,28 @@ void GL_APIENTRY GL_FrontFace(GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFrontFace, "context = %d, mode = %s", CID(context), - GLenumToString(GLESEnum::FrontFaceDirection, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFrontFace, "context = %d, mode = %s", CID(context), + GLenumToString(GLESEnum::FrontFaceDirection, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateFrontFace(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFrontFace, mode)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFrontFace(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLFrontFace, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateFrontFace(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), mode); @@ -1524,7 +2177,7 @@ void GL_APIENTRY GL_FrontFace(GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFrontFace); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1533,17 +2186,30 @@ void GL_APIENTRY GL_GenBuffers(GLsizei n, GLuint *buffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenBuffers, "context = %d, n = %d, buffers = 0x%016" PRIxPTR "", CID(context), - n, (uintptr_t)buffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenBuffers, + "context = %d, n = %d, buffers = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)buffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferID *buffersPacked = PackParam(buffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenBuffers(context, angle::EntryPoint::GLGenBuffers, n, buffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGenBuffers(context, angle::EntryPoint::GLGenBuffers, n, buffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genBuffers(n, buffersPacked); } @@ -1551,7 +2217,7 @@ void GL_APIENTRY GL_GenBuffers(GLsizei n, GLuint *buffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenBuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1560,17 +2226,34 @@ void GL_APIENTRY GL_GenFramebuffers(GLsizei n, GLuint *framebuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenFramebuffers, "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)framebuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenFramebuffers, + "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)framebuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID *framebuffersPacked = PackParam(framebuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenFramebuffers(context, angle::EntryPoint::GLGenFramebuffers, - n, framebuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenFramebuffers(context, angle::EntryPoint::GLGenFramebuffers, + n, framebuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGenFramebuffers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genFramebuffers(n, framebuffersPacked); } @@ -1578,7 +2261,7 @@ void GL_APIENTRY GL_GenFramebuffers(GLsizei n, GLuint *framebuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenFramebuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1587,17 +2270,34 @@ void GL_APIENTRY GL_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenRenderbuffers, "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)renderbuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenRenderbuffers, + "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)renderbuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID *renderbuffersPacked = PackParam(renderbuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenRenderbuffers(context, angle::EntryPoint::GLGenRenderbuffers, - n, renderbuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenRenderbuffers( + context, angle::EntryPoint::GLGenRenderbuffers, n, renderbuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGenRenderbuffers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genRenderbuffers(n, renderbuffersPacked); } @@ -1605,7 +2305,7 @@ void GL_APIENTRY GL_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenRenderbuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1614,17 +2314,30 @@ void GL_APIENTRY GL_GenTextures(GLsizei n, GLuint *textures) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenTextures, "context = %d, n = %d, textures = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)textures); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenTextures, + "context = %d, n = %d, textures = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)textures)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID *texturesPacked = PackParam(textures); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenTextures(context, angle::EntryPoint::GLGenTextures, n, texturesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenTextures(context, angle::EntryPoint::GLGenTextures, n, + texturesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genTextures(n, texturesPacked); } @@ -1632,7 +2345,7 @@ void GL_APIENTRY GL_GenTextures(GLsizei n, GLuint *textures) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenTextures); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1641,17 +2354,33 @@ void GL_APIENTRY GL_GenerateMipmap(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenerateMipmap, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::TextureTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenerateMipmap, "context = %d, target = %s", CID(context), + GLenumToString(GLESEnum::TextureTarget, target))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenerateMipmap(context, angle::EntryPoint::GLGenerateMipmap, targetPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenerateMipmap(context, angle::EntryPoint::GLGenerateMipmap, + targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGenerateMipmap); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->generateMipmap(targetPacked); } @@ -1659,7 +2388,7 @@ void GL_APIENTRY GL_GenerateMipmap(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenerateMipmap); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1674,21 +2403,38 @@ void GL_APIENTRY GL_GetActiveAttrib(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetActiveAttrib, - "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", - CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size, - (uintptr_t)type, (uintptr_t)name); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetActiveAttrib, + "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", + CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size, + (uintptr_t)type, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetActiveAttrib(context, angle::EntryPoint::GLGetActiveAttrib, programPacked, - index, bufSize, length, size, type, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetActiveAttrib(context, angle::EntryPoint::GLGetActiveAttrib, + programPacked, index, bufSize, length, size, + type, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetActiveAttrib); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getActiveAttrib(programPacked, index, bufSize, length, size, type, name); } @@ -1697,7 +2443,7 @@ void GL_APIENTRY GL_GetActiveAttrib(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetActiveAttrib); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1712,21 +2458,38 @@ void GL_APIENTRY GL_GetActiveUniform(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetActiveUniform, - "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", - CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size, - (uintptr_t)type, (uintptr_t)name); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetActiveUniform, + "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", + CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size, + (uintptr_t)type, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetActiveUniform(context, angle::EntryPoint::GLGetActiveUniform, programPacked, - index, bufSize, length, size, type, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetActiveUniform( + context, angle::EntryPoint::GLGetActiveUniform, programPacked, index, bufSize, + length, size, type, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetActiveUniform); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getActiveUniform(programPacked, index, bufSize, length, size, type, name); } @@ -1735,7 +2498,7 @@ void GL_APIENTRY GL_GetActiveUniform(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetActiveUniform); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1747,21 +2510,37 @@ void GL_APIENTRY GL_GetAttachedShaders(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetAttachedShaders, - "context = %d, program = %u, maxCount = %d, count = 0x%016" PRIxPTR - ", shaders = 0x%016" PRIxPTR "", - CID(context), program, maxCount, (uintptr_t)count, (uintptr_t)shaders); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetAttachedShaders, + "context = %d, program = %u, maxCount = %d, count = 0x%016" PRIxPTR + ", shaders = 0x%016" PRIxPTR "", + CID(context), program, maxCount, (uintptr_t)count, (uintptr_t)shaders)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); ShaderProgramID *shadersPacked = PackParam(shaders); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetAttachedShaders(context, angle::EntryPoint::GLGetAttachedShaders, - programPacked, maxCount, count, shadersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetAttachedShaders(context, angle::EntryPoint::GLGetAttachedShaders, + programPacked, maxCount, count, shadersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetAttachedShaders); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getAttachedShaders(programPacked, maxCount, count, shadersPacked); } @@ -1770,7 +2549,7 @@ void GL_APIENTRY GL_GetAttachedShaders(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetAttachedShaders); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1779,19 +2558,35 @@ GLint GL_APIENTRY GL_GetAttribLocation(GLuint program, const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetAttribLocation, "context = %d, program = %u, name = 0x%016" PRIxPTR "", - CID(context), program, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetAttribLocation, + "context = %d, program = %u, name = 0x%016" PRIxPTR "", CID(context), + program, (uintptr_t)name)); GLint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetAttribLocation(context, angle::EntryPoint::GLGetAttribLocation, - programPacked, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetAttribLocation( + context, angle::EntryPoint::GLGetAttribLocation, programPacked, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetAttribLocation); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getAttribLocation(programPacked, name); } @@ -1803,7 +2598,7 @@ GLint GL_APIENTRY GL_GetAttribLocation(GLuint program, const GLchar *name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetAttribLocation); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -1814,16 +2609,29 @@ void GL_APIENTRY GL_GetBooleanv(GLenum pname, GLboolean *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBooleanv, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetBooleanv, + "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetBooleanv(context, angle::EntryPoint::GLGetBooleanv, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetBooleanv(context, angle::EntryPoint::GLGetBooleanv, pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBooleanv(pname, data); } @@ -1831,7 +2639,7 @@ void GL_APIENTRY GL_GetBooleanv(GLenum pname, GLboolean *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBooleanv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1840,20 +2648,32 @@ void GL_APIENTRY GL_GetBufferParameteriv(GLenum target, GLenum pname, GLint *par { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferParameteriv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetBufferParameteriv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetBufferParameteriv(context, angle::EntryPoint::GLGetBufferParameteriv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetBufferParameteriv(context, angle::EntryPoint::GLGetBufferParameteriv, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferParameteriv(targetPacked, pname, params); } @@ -1861,7 +2681,7 @@ void GL_APIENTRY GL_GetBufferParameteriv(GLenum target, GLenum pname, GLint *par } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBufferParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1870,15 +2690,27 @@ GLenum GL_APIENTRY GL_GetError() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetError, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetError, "context = %d", CID(context))); GLenum returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || ValidateGetError(context, angle::EntryPoint::GLGetError)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetError(context, angle::EntryPoint::GLGetError); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getError(); } @@ -1901,16 +2733,29 @@ void GL_APIENTRY GL_GetFloatv(GLenum pname, GLfloat *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFloatv, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFloatv, + "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFloatv(context, angle::EntryPoint::GLGetFloatv, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetFloatv(context, angle::EntryPoint::GLGetFloatv, pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFloatv(pname, data); } @@ -1918,7 +2763,7 @@ void GL_APIENTRY GL_GetFloatv(GLenum pname, GLfloat *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetFloatv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1930,20 +2775,38 @@ void GL_APIENTRY GL_GetFramebufferAttachmentParameteriv(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferAttachmentParameteriv, - "context = %d, target = %s, attachment = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetFramebufferAttachmentParameteriv, + "context = %d, target = %s, attachment = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetFramebufferAttachmentParameteriv( - context, angle::EntryPoint::GLGetFramebufferAttachmentParameteriv, - target, attachment, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferAttachmentParameteriv( + context, angle::EntryPoint::GLGetFramebufferAttachmentParameteriv, target, + attachment, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, + angle::EntryPoint::GLGetFramebufferAttachmentParameteriv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferAttachmentParameteriv(target, attachment, pname, params); } @@ -1952,7 +2815,8 @@ void GL_APIENTRY GL_GetFramebufferAttachmentParameteriv(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferAttachmentParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1961,16 +2825,29 @@ void GL_APIENTRY GL_GetIntegerv(GLenum pname, GLint *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetIntegerv, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetIntegerv, + "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetIntegerv(context, angle::EntryPoint::GLGetIntegerv, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetIntegerv(context, angle::EntryPoint::GLGetIntegerv, pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getIntegerv(pname, data); } @@ -1978,7 +2855,7 @@ void GL_APIENTRY GL_GetIntegerv(GLenum pname, GLint *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetIntegerv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1990,20 +2867,36 @@ void GL_APIENTRY GL_GetProgramInfoLog(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramInfoLog, - "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", infoLog = 0x%016" PRIxPTR "", - CID(context), program, bufSize, (uintptr_t)length, (uintptr_t)infoLog); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetProgramInfoLog, + "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", infoLog = 0x%016" PRIxPTR "", + CID(context), program, bufSize, (uintptr_t)length, (uintptr_t)infoLog)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramInfoLog(context, angle::EntryPoint::GLGetProgramInfoLog, - programPacked, bufSize, length, infoLog)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetProgramInfoLog(context, angle::EntryPoint::GLGetProgramInfoLog, + programPacked, bufSize, length, infoLog); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetProgramInfoLog); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramInfoLog(programPacked, bufSize, length, infoLog); } @@ -2012,7 +2905,7 @@ void GL_APIENTRY GL_GetProgramInfoLog(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramInfoLog); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2021,18 +2914,35 @@ void GL_APIENTRY GL_GetProgramiv(GLuint program, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetProgramiv, - "context = %d, program = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - program, GLenumToString(GLESEnum::ProgramPropertyARB, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetProgramiv, + "context = %d, program = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + program, GLenumToString(GLESEnum::ProgramPropertyARB, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramiv(context, angle::EntryPoint::GLGetProgramiv, - programPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramiv(context, angle::EntryPoint::GLGetProgramiv, + programPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetProgramiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramiv(programPacked, pname, params); } @@ -2048,19 +2958,36 @@ void GL_APIENTRY GL_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetRenderbufferParameteriv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::RenderbufferTarget, target), - GLenumToString(GLESEnum::RenderbufferParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetRenderbufferParameteriv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), + GLenumToString(GLESEnum::RenderbufferParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetRenderbufferParameteriv( - context, angle::EntryPoint::GLGetRenderbufferParameteriv, target, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetRenderbufferParameteriv( + context, angle::EntryPoint::GLGetRenderbufferParameteriv, target, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetRenderbufferParameteriv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getRenderbufferParameteriv(target, pname, params); } @@ -2068,7 +2995,8 @@ void GL_APIENTRY GL_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetRenderbufferParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2080,19 +3008,36 @@ void GL_APIENTRY GL_GetShaderInfoLog(GLuint shader, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetShaderInfoLog, - "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", infoLog = 0x%016" PRIxPTR "", - CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)infoLog); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetShaderInfoLog, + "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", infoLog = 0x%016" PRIxPTR "", + CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)infoLog)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetShaderInfoLog(context, angle::EntryPoint::GLGetShaderInfoLog, - shaderPacked, bufSize, length, infoLog)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetShaderInfoLog(context, angle::EntryPoint::GLGetShaderInfoLog, + shaderPacked, bufSize, length, infoLog); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetShaderInfoLog); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getShaderInfoLog(shaderPacked, bufSize, length, infoLog); } @@ -2101,7 +3046,7 @@ void GL_APIENTRY GL_GetShaderInfoLog(GLuint shader, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetShaderInfoLog); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2113,21 +3058,38 @@ void GL_APIENTRY GL_GetShaderPrecisionFormat(GLenum shadertype, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetShaderPrecisionFormat, - "context = %d, shadertype = %s, precisiontype = %s, range = 0x%016" PRIxPTR - ", precision = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ShaderType, shadertype), - GLenumToString(GLESEnum::PrecisionType, precisiontype), (uintptr_t)range, - (uintptr_t)precision); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetShaderPrecisionFormat, + "context = %d, shadertype = %s, precisiontype = %s, range = 0x%016" PRIxPTR + ", precision = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ShaderType, shadertype), + GLenumToString(GLESEnum::PrecisionType, precisiontype), (uintptr_t)range, + (uintptr_t)precision)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetShaderPrecisionFormat( - context, angle::EntryPoint::GLGetShaderPrecisionFormat, shadertype, - precisiontype, range, precision)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetShaderPrecisionFormat( + context, angle::EntryPoint::GLGetShaderPrecisionFormat, shadertype, + precisiontype, range, precision); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetShaderPrecisionFormat); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); } @@ -2136,7 +3098,8 @@ void GL_APIENTRY GL_GetShaderPrecisionFormat(GLenum shadertype, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetShaderPrecisionFormat); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2145,19 +3108,35 @@ void GL_APIENTRY GL_GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *len { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetShaderSource, - "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", source = 0x%016" PRIxPTR "", - CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)source); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetShaderSource, + "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", source = 0x%016" PRIxPTR "", + CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)source)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetShaderSource(context, angle::EntryPoint::GLGetShaderSource, - shaderPacked, bufSize, length, source)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetShaderSource(context, angle::EntryPoint::GLGetShaderSource, + shaderPacked, bufSize, length, source); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetShaderSource); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getShaderSource(shaderPacked, bufSize, length, source); } @@ -2166,7 +3145,7 @@ void GL_APIENTRY GL_GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *len } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetShaderSource); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2175,18 +3154,35 @@ void GL_APIENTRY GL_GetShaderiv(GLuint shader, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetShaderiv, - "context = %d, shader = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), shader, - GLenumToString(GLESEnum::ShaderParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetShaderiv, + "context = %d, shader = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + shader, GLenumToString(GLESEnum::ShaderParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetShaderiv(context, angle::EntryPoint::GLGetShaderiv, - shaderPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetShaderiv(context, angle::EntryPoint::GLGetShaderiv, + shaderPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetShaderiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getShaderiv(shaderPacked, pname, params); } @@ -2202,16 +3198,28 @@ const GLubyte *GL_APIENTRY GL_GetString(GLenum name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetString, "context = %d, name = %s", CID(context), - GLenumToString(GLESEnum::StringName, name)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetString, "context = %d, name = %s", CID(context), + GLenumToString(GLESEnum::StringName, name))); const GLubyte *returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetString(context, angle::EntryPoint::GLGetString, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetString(context, angle::EntryPoint::GLGetString, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getString(name); } @@ -2223,7 +3231,7 @@ const GLubyte *GL_APIENTRY GL_GetString(GLenum name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetString); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2234,20 +3242,32 @@ void GL_APIENTRY GL_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *para { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterfv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterfv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterfv(context, angle::EntryPoint::GLGetTexParameterfv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterfv( + context, angle::EntryPoint::GLGetTexParameterfv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterfv(targetPacked, pname, params); } @@ -2255,7 +3275,7 @@ void GL_APIENTRY GL_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *para } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2264,20 +3284,32 @@ void GL_APIENTRY GL_GetTexParameteriv(GLenum target, GLenum pname, GLint *params { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameteriv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameteriv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameteriv(context, angle::EntryPoint::GLGetTexParameteriv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameteriv( + context, angle::EntryPoint::GLGetTexParameteriv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameteriv(targetPacked, pname, params); } @@ -2285,7 +3317,7 @@ void GL_APIENTRY GL_GetTexParameteriv(GLenum target, GLenum pname, GLint *params } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2294,19 +3326,35 @@ GLint GL_APIENTRY GL_GetUniformLocation(GLuint program, const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformLocation, "context = %d, program = %u, name = 0x%016" PRIxPTR "", - CID(context), program, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUniformLocation, + "context = %d, program = %u, name = 0x%016" PRIxPTR "", CID(context), + program, (uintptr_t)name)); GLint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetUniformLocation(context, angle::EntryPoint::GLGetUniformLocation, - programPacked, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformLocation( + context, angle::EntryPoint::GLGetUniformLocation, programPacked, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetUniformLocation); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getUniformLocation(programPacked, name); } @@ -2319,7 +3367,7 @@ GLint GL_APIENTRY GL_GetUniformLocation(GLuint program, const GLchar *name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUniformLocation); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2330,19 +3378,35 @@ void GL_APIENTRY GL_GetUniformfv(GLuint program, GLint location, GLfloat *params { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformfv, - "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", CID(context), - program, location, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUniformfv, + "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUniformfv(context, angle::EntryPoint::GLGetUniformfv, - programPacked, locationPacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformfv(context, angle::EntryPoint::GLGetUniformfv, + programPacked, locationPacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetUniformfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformfv(programPacked, locationPacked, params); } @@ -2350,7 +3414,7 @@ void GL_APIENTRY GL_GetUniformfv(GLuint program, GLint location, GLfloat *params } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUniformfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2359,19 +3423,35 @@ void GL_APIENTRY GL_GetUniformiv(GLuint program, GLint location, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformiv, - "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", CID(context), - program, location, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUniformiv, + "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUniformiv(context, angle::EntryPoint::GLGetUniformiv, - programPacked, locationPacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformiv(context, angle::EntryPoint::GLGetUniformiv, + programPacked, locationPacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetUniformiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformiv(programPacked, locationPacked, params); } @@ -2379,7 +3459,7 @@ void GL_APIENTRY GL_GetUniformiv(GLuint program, GLint location, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUniformiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2388,18 +3468,34 @@ void GL_APIENTRY GL_GetVertexAttribPointerv(GLuint index, GLenum pname, void **p { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribPointerv, - "context = %d, index = %u, pname = %s, pointer = 0x%016" PRIxPTR "", CID(context), index, - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetVertexAttribPointerv, + "context = %d, index = %u, pname = %s, pointer = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetVertexAttribPointerv(context, angle::EntryPoint::GLGetVertexAttribPointerv, - index, pname, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribPointerv( + context, angle::EntryPoint::GLGetVertexAttribPointerv, index, pname, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetVertexAttribPointerv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribPointerv(index, pname, pointer); } @@ -2407,7 +3503,8 @@ void GL_APIENTRY GL_GetVertexAttribPointerv(GLuint index, GLenum pname, void **p } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetVertexAttribPointerv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2416,18 +3513,34 @@ void GL_APIENTRY GL_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *param { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribfv, - "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), index, - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetVertexAttribfv, + "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetVertexAttribfv(context, angle::EntryPoint::GLGetVertexAttribfv, index, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribfv( + context, angle::EntryPoint::GLGetVertexAttribfv, index, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetVertexAttribfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribfv(index, pname, params); } @@ -2435,7 +3548,7 @@ void GL_APIENTRY GL_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *param } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetVertexAttribfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2444,18 +3557,34 @@ void GL_APIENTRY GL_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribiv, - "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), index, - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetVertexAttribiv, + "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetVertexAttribiv(context, angle::EntryPoint::GLGetVertexAttribiv, index, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribiv( + context, angle::EntryPoint::GLGetVertexAttribiv, index, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLGetVertexAttribiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribiv(index, pname, params); } @@ -2463,7 +3592,7 @@ void GL_APIENTRY GL_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetVertexAttribiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2472,19 +3601,29 @@ void GL_APIENTRY GL_Hint(GLenum target, GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLHint, "context = %d, target = %s, mode = %s", CID(context), - GLenumToString(GLESEnum::HintTarget, target), GLenumToString(GLESEnum::HintMode, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLHint, "context = %d, target = %s, mode = %s", CID(context), + GLenumToString(GLESEnum::HintTarget, target), + GLenumToString(GLESEnum::HintMode, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLHint) && - ValidateHint(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLHint, target, mode))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateHint(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLHint, target, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateHint(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, mode); @@ -2493,7 +3632,7 @@ void GL_APIENTRY GL_Hint(GLenum target, GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLHint); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2502,16 +3641,30 @@ GLboolean GL_APIENTRY GL_IsBuffer(GLuint buffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsBuffer, "context = %d, buffer = %u", CID(context), buffer); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsBuffer, "context = %d, buffer = %u", CID(context), buffer)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsBuffer(context, angle::EntryPoint::GLIsBuffer, bufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsBuffer(context, angle::EntryPoint::GLIsBuffer, bufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isBuffer(bufferPacked); } @@ -2523,7 +3676,7 @@ GLboolean GL_APIENTRY GL_IsBuffer(GLuint buffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsBuffer); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2534,17 +3687,29 @@ GLboolean GL_APIENTRY GL_IsEnabled(GLenum cap) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsEnabled, "context = %d, cap = %s", CID(context), - GLenumToString(GLESEnum::EnableCap, cap)); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsEnabled, "context = %d, cap = %s", CID(context), + GLenumToString(GLESEnum::EnableCap, cap))); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateIsEnabled(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLIsEnabled, cap)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsEnabled(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLIsEnabled, cap); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = ContextPrivateIsEnabled(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), cap); @@ -2557,7 +3722,7 @@ GLboolean GL_APIENTRY GL_IsEnabled(GLenum cap) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsEnabled); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2568,17 +3733,34 @@ GLboolean GL_APIENTRY GL_IsFramebuffer(GLuint framebuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsFramebuffer, "context = %d, framebuffer = %u", CID(context), framebuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsFramebuffer, "context = %d, framebuffer = %u", + CID(context), framebuffer)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID framebufferPacked = PackParam(framebuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsFramebuffer(context, angle::EntryPoint::GLIsFramebuffer, framebufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsFramebuffer(context, angle::EntryPoint::GLIsFramebuffer, + framebufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLIsFramebuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isFramebuffer(framebufferPacked); } @@ -2590,7 +3772,7 @@ GLboolean GL_APIENTRY GL_IsFramebuffer(GLuint framebuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsFramebuffer); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2601,17 +3783,34 @@ GLboolean GL_APIENTRY GL_IsProgram(GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsProgram, "context = %d, program = %u", CID(context), program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsProgram, "context = %d, program = %u", CID(context), program)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsProgram(context, angle::EntryPoint::GLIsProgram, programPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsProgram(context, angle::EntryPoint::GLIsProgram, programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLIsProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isProgram(programPacked); } @@ -2623,7 +3822,7 @@ GLboolean GL_APIENTRY GL_IsProgram(GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsProgram); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2634,17 +3833,34 @@ GLboolean GL_APIENTRY GL_IsRenderbuffer(GLuint renderbuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsRenderbuffer, "context = %d, renderbuffer = %u", CID(context), renderbuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsRenderbuffer, "context = %d, renderbuffer = %u", + CID(context), renderbuffer)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID renderbufferPacked = PackParam(renderbuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsRenderbuffer(context, angle::EntryPoint::GLIsRenderbuffer, - renderbufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsRenderbuffer(context, angle::EntryPoint::GLIsRenderbuffer, + renderbufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLIsRenderbuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isRenderbuffer(renderbufferPacked); } @@ -2656,7 +3872,7 @@ GLboolean GL_APIENTRY GL_IsRenderbuffer(GLuint renderbuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsRenderbuffer); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2667,16 +3883,34 @@ GLboolean GL_APIENTRY GL_IsShader(GLuint shader) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsShader, "context = %d, shader = %u", CID(context), shader); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsShader, "context = %d, shader = %u", CID(context), shader)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsShader(context, angle::EntryPoint::GLIsShader, shaderPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsShader(context, angle::EntryPoint::GLIsShader, shaderPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLIsShader); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isShader(shaderPacked); } @@ -2688,7 +3922,7 @@ GLboolean GL_APIENTRY GL_IsShader(GLuint shader) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsShader); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2699,17 +3933,30 @@ GLboolean GL_APIENTRY GL_IsTexture(GLuint texture) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsTexture, "context = %d, texture = %u", CID(context), texture); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsTexture, "context = %d, texture = %u", CID(context), texture)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsTexture(context, angle::EntryPoint::GLIsTexture, texturePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsTexture(context, angle::EntryPoint::GLIsTexture, texturePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isTexture(texturePacked); } @@ -2721,7 +3968,7 @@ GLboolean GL_APIENTRY GL_IsTexture(GLuint texture) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsTexture); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2732,19 +3979,27 @@ void GL_APIENTRY GL_LineWidth(GLfloat width) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLineWidth, "context = %d, width = %f", CID(context), width); + ANGLE_UNSAFE_TODO(EVENT(context, GLLineWidth, "context = %d, width = %f", CID(context), width)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLineWidth(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLineWidth) && - ValidateLineWidth(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLineWidth, width))); - if (isCallValid) + angle::EntryPoint::GLLineWidth, width); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLineWidth(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), width); @@ -2753,7 +4008,7 @@ void GL_APIENTRY GL_LineWidth(GLfloat width) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLineWidth); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2762,19 +4017,33 @@ void GL_APIENTRY GL_LinkProgram(GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLinkProgram, "context = %d, program = %u", CID(context), program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLLinkProgram, "context = %d, program = %u", CID(context), program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLinkProgram) && - ValidateLinkProgram(context, angle::EntryPoint::GLLinkProgram, programPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateLinkProgram(context, angle::EntryPoint::GLLinkProgram, programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLLinkProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->linkProgram(programPacked); } @@ -2782,7 +4051,7 @@ void GL_APIENTRY GL_LinkProgram(GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLinkProgram); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2791,20 +4060,29 @@ void GL_APIENTRY GL_PixelStorei(GLenum pname, GLint param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPixelStorei, "context = %d, pname = %s, param = %d", CID(context), - GLenumToString(GLESEnum::PixelStoreParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLPixelStorei, "context = %d, pname = %s, param = %d", + CID(context), GLenumToString(GLESEnum::PixelStoreParameter, pname), + param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPixelStorei) && - ValidatePixelStorei(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPixelStorei, pname, param))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePixelStorei(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPixelStorei, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePixelStorei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, param); @@ -2813,7 +4091,7 @@ void GL_APIENTRY GL_PixelStorei(GLenum pname, GLint param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPixelStorei); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2822,17 +4100,28 @@ void GL_APIENTRY GL_PolygonOffset(GLfloat factor, GLfloat units) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPolygonOffset, "context = %d, factor = %f, units = %f", CID(context), factor, - units); + ANGLE_UNSAFE_TODO(EVENT(context, GLPolygonOffset, "context = %d, factor = %f, units = %f", + CID(context), factor, units)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidatePolygonOffset(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPolygonOffset, factor, units)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePolygonOffset( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPolygonOffset, factor, units); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePolygonOffset(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), factor, units); @@ -2841,7 +4130,7 @@ void GL_APIENTRY GL_PolygonOffset(GLfloat factor, GLfloat units) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPolygonOffset); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2856,23 +4145,36 @@ void GL_APIENTRY GL_ReadPixels(GLint x, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadPixels, - "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, pixels = " - "0x%016" PRIxPTR "", - CID(context), x, y, width, height, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels); + ANGLE_UNSAFE_TODO(EVENT(context, GLReadPixels, + "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, " + "type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), x, y, width, height, + GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadPixels) && - ValidateReadPixels(context, angle::EntryPoint::GLReadPixels, x, y, width, height, - format, type, pixels))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateReadPixels(context, angle::EntryPoint::GLReadPixels, x, y, + width, height, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readPixels(x, y, width, height, format, type, pixels); } @@ -2881,7 +4183,7 @@ void GL_APIENTRY GL_ReadPixels(GLint x, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadPixels); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2890,18 +4192,31 @@ void GL_APIENTRY GL_ReleaseShaderCompiler() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReleaseShaderCompiler, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLReleaseShaderCompiler, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReleaseShaderCompiler) && - ValidateReleaseShaderCompiler(context, angle::EntryPoint::GLReleaseShaderCompiler))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateReleaseShaderCompiler( + context, angle::EntryPoint::GLReleaseShaderCompiler); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLReleaseShaderCompiler); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->releaseShaderCompiler(); } @@ -2909,7 +4224,7 @@ void GL_APIENTRY GL_ReleaseShaderCompiler() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReleaseShaderCompiler); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2921,22 +4236,36 @@ void GL_APIENTRY GL_RenderbufferStorage(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRenderbufferStorage, - "context = %d, target = %s, internalformat = %s, width = %d, height = %d", CID(context), - GLenumToString(GLESEnum::RenderbufferTarget, target), - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO( + EVENT(context, GLRenderbufferStorage, + "context = %d, target = %s, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRenderbufferStorage) && - ValidateRenderbufferStorage(context, angle::EntryPoint::GLRenderbufferStorage, target, - internalformat, width, height))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateRenderbufferStorage(context, angle::EntryPoint::GLRenderbufferStorage, + target, internalformat, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLRenderbufferStorage); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->renderbufferStorage(target, internalformat, width, height); } @@ -2945,7 +4274,7 @@ void GL_APIENTRY GL_RenderbufferStorage(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLRenderbufferStorage); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2954,20 +4283,28 @@ void GL_APIENTRY GL_SampleCoverage(GLfloat value, GLboolean invert) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSampleCoverage, "context = %d, value = %f, invert = %s", CID(context), value, - GLbooleanToString(invert)); + ANGLE_UNSAFE_TODO(EVENT(context, GLSampleCoverage, "context = %d, value = %f, invert = %s", + CID(context), value, GLbooleanToString(invert))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleCoverage) && - ValidateSampleCoverage(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleCoverage, value, invert))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSampleCoverage( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLSampleCoverage, value, invert); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateSampleCoverage(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), value, invert); @@ -2976,7 +4313,7 @@ void GL_APIENTRY GL_SampleCoverage(GLfloat value, GLboolean invert) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSampleCoverage); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2985,16 +4322,29 @@ void GL_APIENTRY GL_Scissor(GLint x, GLint y, GLsizei width, GLsizei height) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLScissor, "context = %d, x = %d, y = %d, width = %d, height = %d", CID(context), - x, y, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLScissor, + "context = %d, x = %d, y = %d, width = %d, height = %d", CID(context), + x, y, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateScissor(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLScissor, x, y, width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateScissor(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLScissor, x, y, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateScissor(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), x, y, width, height); @@ -3003,7 +4353,7 @@ void GL_APIENTRY GL_Scissor(GLint x, GLint y, GLsizei width, GLsizei height) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLScissor); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3016,24 +4366,38 @@ void GL_APIENTRY GL_ShaderBinary(GLsizei count, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLShaderBinary, - "context = %d, count = %d, shaders = 0x%016" PRIxPTR - ", binaryFormat = %s, binary = 0x%016" PRIxPTR ", length = %d", - CID(context), count, (uintptr_t)shaders, - GLenumToString(GLESEnum::ShaderBinaryFormat, binaryFormat), (uintptr_t)binary, length); + ANGLE_UNSAFE_TODO(EVENT(context, GLShaderBinary, + "context = %d, count = %d, shaders = 0x%016" PRIxPTR + ", binaryFormat = %s, binary = 0x%016" PRIxPTR ", length = %d", + CID(context), count, (uintptr_t)shaders, + GLenumToString(GLESEnum::ShaderBinaryFormat, binaryFormat), + (uintptr_t)binary, length)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const ShaderProgramID *shadersPacked = PackParam(shaders); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLShaderBinary) && - ValidateShaderBinary(context, angle::EntryPoint::GLShaderBinary, count, shadersPacked, - binaryFormat, binary, length))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateShaderBinary(context, angle::EntryPoint::GLShaderBinary, count, + shadersPacked, binaryFormat, binary, length); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLShaderBinary); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->shaderBinary(count, shadersPacked, binaryFormat, binary, length); } @@ -3042,7 +4406,7 @@ void GL_APIENTRY GL_ShaderBinary(GLsizei count, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLShaderBinary); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -3054,23 +4418,35 @@ void GL_APIENTRY GL_ShaderSource(GLuint shader, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLShaderSource, - "context = %d, shader = %u, count = %d, string = 0x%016" PRIxPTR - ", length = 0x%016" PRIxPTR "", - CID(context), shader, count, (uintptr_t)string, (uintptr_t)length); + ANGLE_UNSAFE_TODO(EVENT(context, GLShaderSource, + "context = %d, shader = %u, count = %d, string = 0x%016" PRIxPTR + ", length = 0x%016" PRIxPTR "", + CID(context), shader, count, (uintptr_t)string, (uintptr_t)length)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLShaderSource) && - ValidateShaderSource(context, angle::EntryPoint::GLShaderSource, shaderPacked, count, - string, length))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateShaderSource(context, angle::EntryPoint::GLShaderSource, + shaderPacked, count, string, length); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLShaderSource); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->shaderSource(shaderPacked, count, string, length); } @@ -3078,7 +4454,7 @@ void GL_APIENTRY GL_ShaderSource(GLuint shader, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLShaderSource); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3087,16 +4463,29 @@ void GL_APIENTRY GL_StencilFunc(GLenum func, GLint ref, GLuint mask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStencilFunc, "context = %d, func = %s, ref = %d, mask = %u", CID(context), - GLenumToString(GLESEnum::StencilFunction, func), ref, mask); + ANGLE_UNSAFE_TODO(EVENT(context, GLStencilFunc, "context = %d, func = %s, ref = %d, mask = %u", + CID(context), GLenumToString(GLESEnum::StencilFunction, func), ref, + mask)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateStencilFunc(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStencilFunc, func, ref, mask)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStencilFunc( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLStencilFunc, func, ref, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateStencilFunc(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), func, ref, mask); @@ -3105,7 +4494,7 @@ void GL_APIENTRY GL_StencilFunc(GLenum func, GLint ref, GLuint mask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStencilFunc); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3114,18 +4503,34 @@ void GL_APIENTRY GL_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLu { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStencilFuncSeparate, "context = %d, face = %s, func = %s, ref = %d, mask = %u", - CID(context), GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::StencilFunction, func), ref, mask); + ANGLE_UNSAFE_TODO(EVENT(context, GLStencilFuncSeparate, + "context = %d, face = %s, func = %s, ref = %d, mask = %u", CID(context), + GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::StencilFunction, func), ref, mask)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateStencilFuncSeparate( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStencilFuncSeparate, face, func, ref, mask)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStencilFuncSeparate( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLStencilFuncSeparate, face, func, ref, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLStencilFuncSeparate); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateStencilFuncSeparate(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, func, @@ -3135,7 +4540,7 @@ void GL_APIENTRY GL_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLu } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStencilFuncSeparate); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3144,15 +4549,27 @@ void GL_APIENTRY GL_StencilMask(GLuint mask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStencilMask, "context = %d, mask = %u", CID(context), mask); + ANGLE_UNSAFE_TODO(EVENT(context, GLStencilMask, "context = %d, mask = %u", CID(context), mask)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateStencilMask(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStencilMask, mask)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStencilMask(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLStencilMask, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateStencilMask(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), mask); @@ -3161,7 +4578,7 @@ void GL_APIENTRY GL_StencilMask(GLuint mask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStencilMask); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3170,17 +4587,32 @@ void GL_APIENTRY GL_StencilMaskSeparate(GLenum face, GLuint mask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStencilMaskSeparate, "context = %d, face = %s, mask = %u", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), mask); + ANGLE_UNSAFE_TODO(EVENT(context, GLStencilMaskSeparate, "context = %d, face = %s, mask = %u", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), mask)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateStencilMaskSeparate(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStencilMaskSeparate, face, mask)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStencilMaskSeparate( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLStencilMaskSeparate, face, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLStencilMaskSeparate); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateStencilMaskSeparate(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, mask); @@ -3189,7 +4621,7 @@ void GL_APIENTRY GL_StencilMaskSeparate(GLenum face, GLuint mask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStencilMaskSeparate); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3198,17 +4630,30 @@ void GL_APIENTRY GL_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStencilOp, "context = %d, fail = %s, zfail = %s, zpass = %s", CID(context), - GLenumToString(GLESEnum::StencilOp, fail), GLenumToString(GLESEnum::StencilOp, zfail), - GLenumToString(GLESEnum::StencilOp, zpass)); + ANGLE_UNSAFE_TODO(EVENT(context, GLStencilOp, "context = %d, fail = %s, zfail = %s, zpass = %s", + CID(context), GLenumToString(GLESEnum::StencilOp, fail), + GLenumToString(GLESEnum::StencilOp, zfail), + GLenumToString(GLESEnum::StencilOp, zpass))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateStencilOp(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStencilOp, fail, zfail, zpass)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStencilOp(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLStencilOp, fail, zfail, zpass); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateStencilOp(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), fail, zfail, zpass); @@ -3217,7 +4662,7 @@ void GL_APIENTRY GL_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStencilOp); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3226,19 +4671,35 @@ void GL_APIENTRY GL_StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStencilOpSeparate, - "context = %d, face = %s, sfail = %s, dpfail = %s, dppass = %s", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), GLenumToString(GLESEnum::StencilOp, sfail), - GLenumToString(GLESEnum::StencilOp, dpfail), GLenumToString(GLESEnum::StencilOp, dppass)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLStencilOpSeparate, + "context = %d, face = %s, sfail = %s, dpfail = %s, dppass = %s", CID(context), + GLenumToString(GLESEnum::TriangleFace, face), GLenumToString(GLESEnum::StencilOp, sfail), + GLenumToString(GLESEnum::StencilOp, dpfail), GLenumToString(GLESEnum::StencilOp, dppass))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateStencilOpSeparate( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStencilOpSeparate, face, sfail, dpfail, dppass)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStencilOpSeparate( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLStencilOpSeparate, face, sfail, dpfail, dppass); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLStencilOpSeparate); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateStencilOpSeparate(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, sfail, @@ -3248,7 +4709,7 @@ void GL_APIENTRY GL_StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStencilOpSeparate); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3265,25 +4726,35 @@ void GL_APIENTRY GL_TexImage2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexImage2D, - "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, " - "border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, internalformat, - width, height, border, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexImage2D, + "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = " + "%d, border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, internalformat, + width, height, border, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexImage2D) && - ValidateTexImage2D(context, angle::EntryPoint::GLTexImage2D, targetPacked, level, - internalformat, width, height, border, format, type, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexImage2D(context, angle::EntryPoint::GLTexImage2D, + targetPacked, level, internalformat, width, height, + border, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texImage2D(targetPacked, level, internalformat, width, height, border, format, type, pixels); @@ -3293,7 +4764,7 @@ void GL_APIENTRY GL_TexImage2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexImage2D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -3302,18 +4773,31 @@ void GL_APIENTRY GL_TexParameterf(GLenum target, GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterf, "context = %d, target = %s, pname = %s, param = %f", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterf, + "context = %d, target = %s, pname = %s, param = %f", CID(context), + GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterf(context, angle::EntryPoint::GLTexParameterf, - targetPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterf(context, angle::EntryPoint::GLTexParameterf, + targetPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterf(targetPacked, pname, param); } @@ -3321,7 +4805,7 @@ void GL_APIENTRY GL_TexParameterf(GLenum target, GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3330,19 +4814,32 @@ void GL_APIENTRY GL_TexParameterfv(GLenum target, GLenum pname, const GLfloat *p { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterfv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterfv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterfv(context, angle::EntryPoint::GLTexParameterfv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterfv(context, angle::EntryPoint::GLTexParameterfv, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterfv(targetPacked, pname, params); } @@ -3350,7 +4847,7 @@ void GL_APIENTRY GL_TexParameterfv(GLenum target, GLenum pname, const GLfloat *p } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3359,18 +4856,31 @@ void GL_APIENTRY GL_TexParameteri(GLenum target, GLenum pname, GLint param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameteri, "context = %d, target = %s, pname = %s, param = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameteri, + "context = %d, target = %s, pname = %s, param = %d", CID(context), + GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameteri(context, angle::EntryPoint::GLTexParameteri, - targetPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameteri(context, angle::EntryPoint::GLTexParameteri, + targetPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameteri(targetPacked, pname, param); } @@ -3378,7 +4888,7 @@ void GL_APIENTRY GL_TexParameteri(GLenum target, GLenum pname, GLint param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameteri); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3387,19 +4897,32 @@ void GL_APIENTRY GL_TexParameteriv(GLenum target, GLenum pname, const GLint *par { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameteriv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameteriv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameteriv(context, angle::EntryPoint::GLTexParameteriv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameteriv(context, angle::EntryPoint::GLTexParameteriv, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameteriv(targetPacked, pname, params); } @@ -3407,7 +4930,7 @@ void GL_APIENTRY GL_TexParameteriv(GLenum target, GLenum pname, const GLint *par } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3424,25 +4947,35 @@ void GL_APIENTRY GL_TexSubImage2D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexSubImage2D, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = " - "%d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - width, height, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexSubImage2D, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, " + "height = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, + yoffset, width, height, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexSubImage2D) && - ValidateTexSubImage2D(context, angle::EntryPoint::GLTexSubImage2D, targetPacked, - level, xoffset, yoffset, width, height, format, type, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexSubImage2D(context, angle::EntryPoint::GLTexSubImage2D, + targetPacked, level, xoffset, yoffset, width, + height, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texSubImage2D(targetPacked, level, xoffset, yoffset, width, height, format, type, pixels); @@ -3452,7 +4985,7 @@ void GL_APIENTRY GL_TexSubImage2D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexSubImage2D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -3461,16 +4994,33 @@ void GL_APIENTRY GL_Uniform1f(GLint location, GLfloat v0) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform1f, "context = %d, location = %d, v0 = %f", CID(context), location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform1f, "context = %d, location = %d, v0 = %f", + CID(context), location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniform1f(context, angle::EntryPoint::GLUniform1f, locationPacked, v0)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniform1f(context, angle::EntryPoint::GLUniform1f, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform1f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform1f(locationPacked, v0); } @@ -3478,7 +5028,7 @@ void GL_APIENTRY GL_Uniform1f(GLint location, GLfloat v0) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform1f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3487,18 +5037,34 @@ void GL_APIENTRY GL_Uniform1fv(GLint location, GLsizei count, const GLfloat *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform1fv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform1fv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform1fv(context, angle::EntryPoint::GLUniform1fv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform1fv(context, angle::EntryPoint::GLUniform1fv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform1fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform1fv(locationPacked, count, value); } @@ -3506,7 +5072,7 @@ void GL_APIENTRY GL_Uniform1fv(GLint location, GLsizei count, const GLfloat *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform1fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3515,16 +5081,33 @@ void GL_APIENTRY GL_Uniform1i(GLint location, GLint v0) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform1i, "context = %d, location = %d, v0 = %d", CID(context), location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform1i, "context = %d, location = %d, v0 = %d", + CID(context), location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateUniform1i(context, angle::EntryPoint::GLUniform1i, locationPacked, v0)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniform1i(context, angle::EntryPoint::GLUniform1i, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform1i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform1i(locationPacked, v0); } @@ -3532,7 +5115,7 @@ void GL_APIENTRY GL_Uniform1i(GLint location, GLint v0) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform1i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3541,18 +5124,34 @@ void GL_APIENTRY GL_Uniform1iv(GLint location, GLsizei count, const GLint *value { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform1iv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform1iv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateUniform1iv(context, angle::EntryPoint::GLUniform1iv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform1iv(context, angle::EntryPoint::GLUniform1iv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform1iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform1iv(locationPacked, count, value); } @@ -3560,7 +5159,7 @@ void GL_APIENTRY GL_Uniform1iv(GLint location, GLsizei count, const GLint *value } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform1iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3569,17 +5168,33 @@ void GL_APIENTRY GL_Uniform2f(GLint location, GLfloat v0, GLfloat v1) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform2f, "context = %d, location = %d, v0 = %f, v1 = %f", CID(context), - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform2f, "context = %d, location = %d, v0 = %f, v1 = %f", + CID(context), location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniform2f(context, angle::EntryPoint::GLUniform2f, locationPacked, v0, v1)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform2f(context, angle::EntryPoint::GLUniform2f, + locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform2f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform2f(locationPacked, v0, v1); } @@ -3587,7 +5202,7 @@ void GL_APIENTRY GL_Uniform2f(GLint location, GLfloat v0, GLfloat v1) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform2f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3596,18 +5211,34 @@ void GL_APIENTRY GL_Uniform2fv(GLint location, GLsizei count, const GLfloat *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform2fv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform2fv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform2fv(context, angle::EntryPoint::GLUniform2fv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform2fv(context, angle::EntryPoint::GLUniform2fv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform2fv(locationPacked, count, value); } @@ -3615,7 +5246,7 @@ void GL_APIENTRY GL_Uniform2fv(GLint location, GLsizei count, const GLfloat *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3624,17 +5255,33 @@ void GL_APIENTRY GL_Uniform2i(GLint location, GLint v0, GLint v1) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform2i, "context = %d, location = %d, v0 = %d, v1 = %d", CID(context), - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform2i, "context = %d, location = %d, v0 = %d, v1 = %d", + CID(context), location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniform2i(context, angle::EntryPoint::GLUniform2i, locationPacked, v0, v1)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform2i(context, angle::EntryPoint::GLUniform2i, + locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform2i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform2i(locationPacked, v0, v1); } @@ -3642,7 +5289,7 @@ void GL_APIENTRY GL_Uniform2i(GLint location, GLint v0, GLint v1) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform2i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3651,18 +5298,34 @@ void GL_APIENTRY GL_Uniform2iv(GLint location, GLsizei count, const GLint *value { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform2iv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform2iv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform2iv(context, angle::EntryPoint::GLUniform2iv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform2iv(context, angle::EntryPoint::GLUniform2iv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform2iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform2iv(locationPacked, count, value); } @@ -3670,7 +5333,7 @@ void GL_APIENTRY GL_Uniform2iv(GLint location, GLsizei count, const GLint *value } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform2iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3679,17 +5342,34 @@ void GL_APIENTRY GL_Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2 { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform3f, "context = %d, location = %d, v0 = %f, v1 = %f, v2 = %f", - CID(context), location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform3f, + "context = %d, location = %d, v0 = %f, v1 = %f, v2 = %f", CID(context), + location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || ValidateUniform3f(context, angle::EntryPoint::GLUniform3f, - locationPacked, v0, v1, v2)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform3f(context, angle::EntryPoint::GLUniform3f, + locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform3f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform3f(locationPacked, v0, v1, v2); } @@ -3697,7 +5377,7 @@ void GL_APIENTRY GL_Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2 } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform3f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3706,18 +5386,34 @@ void GL_APIENTRY GL_Uniform3fv(GLint location, GLsizei count, const GLfloat *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform3fv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform3fv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform3fv(context, angle::EntryPoint::GLUniform3fv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform3fv(context, angle::EntryPoint::GLUniform3fv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform3fv(locationPacked, count, value); } @@ -3725,7 +5421,7 @@ void GL_APIENTRY GL_Uniform3fv(GLint location, GLsizei count, const GLfloat *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3734,17 +5430,34 @@ void GL_APIENTRY GL_Uniform3i(GLint location, GLint v0, GLint v1, GLint v2) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform3i, "context = %d, location = %d, v0 = %d, v1 = %d, v2 = %d", - CID(context), location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform3i, + "context = %d, location = %d, v0 = %d, v1 = %d, v2 = %d", CID(context), + location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || ValidateUniform3i(context, angle::EntryPoint::GLUniform3i, - locationPacked, v0, v1, v2)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform3i(context, angle::EntryPoint::GLUniform3i, + locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform3i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform3i(locationPacked, v0, v1, v2); } @@ -3752,7 +5465,7 @@ void GL_APIENTRY GL_Uniform3i(GLint location, GLint v0, GLint v1, GLint v2) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform3i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3761,18 +5474,34 @@ void GL_APIENTRY GL_Uniform3iv(GLint location, GLsizei count, const GLint *value { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform3iv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform3iv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform3iv(context, angle::EntryPoint::GLUniform3iv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform3iv(context, angle::EntryPoint::GLUniform3iv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform3iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform3iv(locationPacked, count, value); } @@ -3780,7 +5509,7 @@ void GL_APIENTRY GL_Uniform3iv(GLint location, GLsizei count, const GLint *value } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform3iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3789,17 +5518,34 @@ void GL_APIENTRY GL_Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2 { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform4f, "context = %d, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", - CID(context), location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform4f, + "context = %d, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", + CID(context), location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || ValidateUniform4f(context, angle::EntryPoint::GLUniform4f, - locationPacked, v0, v1, v2, v3)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform4f(context, angle::EntryPoint::GLUniform4f, + locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform4f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform4f(locationPacked, v0, v1, v2, v3); } @@ -3807,7 +5553,7 @@ void GL_APIENTRY GL_Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2 } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform4f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3816,18 +5562,34 @@ void GL_APIENTRY GL_Uniform4fv(GLint location, GLsizei count, const GLfloat *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform4fv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform4fv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform4fv(context, angle::EntryPoint::GLUniform4fv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform4fv(context, angle::EntryPoint::GLUniform4fv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform4fv(locationPacked, count, value); } @@ -3835,7 +5597,7 @@ void GL_APIENTRY GL_Uniform4fv(GLint location, GLsizei count, const GLfloat *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3844,17 +5606,34 @@ void GL_APIENTRY GL_Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform4i, "context = %d, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d", - CID(context), location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform4i, + "context = %d, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d", + CID(context), location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || ValidateUniform4i(context, angle::EntryPoint::GLUniform4i, - locationPacked, v0, v1, v2, v3)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform4i(context, angle::EntryPoint::GLUniform4i, + locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform4i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform4i(locationPacked, v0, v1, v2, v3); } @@ -3862,7 +5641,7 @@ void GL_APIENTRY GL_Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform4i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3871,18 +5650,34 @@ void GL_APIENTRY GL_Uniform4iv(GLint location, GLsizei count, const GLint *value { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform4iv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform4iv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform4iv(context, angle::EntryPoint::GLUniform4iv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform4iv(context, angle::EntryPoint::GLUniform4iv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniform4iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform4iv(locationPacked, count, value); } @@ -3890,7 +5685,7 @@ void GL_APIENTRY GL_Uniform4iv(GLint location, GLsizei count, const GLint *value } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform4iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3902,18 +5697,36 @@ void GL_APIENTRY GL_UniformMatrix2fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix2fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix2fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniformMatrix2fv(context, angle::EntryPoint::GLUniformMatrix2fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix2fv(context, angle::EntryPoint::GLUniformMatrix2fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniformMatrix2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix2fv(locationPacked, count, transpose, value); } @@ -3922,7 +5735,7 @@ void GL_APIENTRY GL_UniformMatrix2fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3934,18 +5747,36 @@ void GL_APIENTRY GL_UniformMatrix3fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix3fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix3fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniformMatrix3fv(context, angle::EntryPoint::GLUniformMatrix3fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix3fv(context, angle::EntryPoint::GLUniformMatrix3fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniformMatrix3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix3fv(locationPacked, count, transpose, value); } @@ -3954,7 +5785,7 @@ void GL_APIENTRY GL_UniformMatrix3fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3966,18 +5797,36 @@ void GL_APIENTRY GL_UniformMatrix4fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix4fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix4fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniformMatrix4fv(context, angle::EntryPoint::GLUniformMatrix4fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix4fv(context, angle::EntryPoint::GLUniformMatrix4fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUniformMatrix4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix4fv(locationPacked, count, transpose, value); } @@ -3986,7 +5835,7 @@ void GL_APIENTRY GL_UniformMatrix4fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3995,16 +5844,33 @@ void GL_APIENTRY GL_UseProgram(GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUseProgram, "context = %d, program = %u", CID(context), program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUseProgram, "context = %d, program = %u", CID(context), program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateUseProgram(context, angle::EntryPoint::GLUseProgram, programPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUseProgram(context, angle::EntryPoint::GLUseProgram, programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLUseProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->useProgram(programPacked); } @@ -4012,7 +5878,7 @@ void GL_APIENTRY GL_UseProgram(GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUseProgram); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4021,16 +5887,33 @@ void GL_APIENTRY GL_ValidateProgram(GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLValidateProgram, "context = %d, program = %u", CID(context), program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLValidateProgram, "context = %d, program = %u", CID(context), program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateValidateProgram(context, angle::EntryPoint::GLValidateProgram, programPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateValidateProgram(context, angle::EntryPoint::GLValidateProgram, + programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLValidateProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->validateProgram(programPacked); } @@ -4038,7 +5921,7 @@ void GL_APIENTRY GL_ValidateProgram(GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLValidateProgram); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4047,15 +5930,32 @@ void GL_APIENTRY GL_VertexAttrib1f(GLuint index, GLfloat x) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib1f, "context = %d, index = %u, x = %f", CID(context), index, x); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib1f, "context = %d, index = %u, x = %f", + CID(context), index, x)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateVertexAttrib1f(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib1f, index, x)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib1f(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib1f, index, x); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib1f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib1f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, x); @@ -4064,7 +5964,7 @@ void GL_APIENTRY GL_VertexAttrib1f(GLuint index, GLfloat x) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib1f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4073,17 +5973,33 @@ void GL_APIENTRY GL_VertexAttrib1fv(GLuint index, const GLfloat *v) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib1fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "", - CID(context), index, (uintptr_t)v); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib1fv, + "context = %d, index = %u, v = 0x%016" PRIxPTR "", CID(context), index, + (uintptr_t)v)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib1fv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib1fv, index, v)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib1fv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib1fv, index, v); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib1fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib1fv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, v); @@ -4092,7 +6008,7 @@ void GL_APIENTRY GL_VertexAttrib1fv(GLuint index, const GLfloat *v) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib1fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4101,17 +6017,32 @@ void GL_APIENTRY GL_VertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib2f, "context = %d, index = %u, x = %f, y = %f", CID(context), - index, x, y); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib2f, "context = %d, index = %u, x = %f, y = %f", + CID(context), index, x, y)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib2f(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib2f, index, x, y)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib2f( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib2f, index, x, y); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib2f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib2f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, x, y); @@ -4120,7 +6051,7 @@ void GL_APIENTRY GL_VertexAttrib2f(GLuint index, GLfloat x, GLfloat y) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib2f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4129,17 +6060,33 @@ void GL_APIENTRY GL_VertexAttrib2fv(GLuint index, const GLfloat *v) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib2fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "", - CID(context), index, (uintptr_t)v); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib2fv, + "context = %d, index = %u, v = 0x%016" PRIxPTR "", CID(context), index, + (uintptr_t)v)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib2fv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib2fv, index, v)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib2fv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib2fv, index, v); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib2fv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, v); @@ -4148,7 +6095,7 @@ void GL_APIENTRY GL_VertexAttrib2fv(GLuint index, const GLfloat *v) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4157,17 +6104,33 @@ void GL_APIENTRY GL_VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib3f, "context = %d, index = %u, x = %f, y = %f, z = %f", - CID(context), index, x, y, z); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib3f, + "context = %d, index = %u, x = %f, y = %f, z = %f", CID(context), index, + x, y, z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib3f(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib3f, index, x, y, z)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib3f( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib3f, index, x, y, z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib3f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib3f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, x, y, z); @@ -4176,7 +6139,7 @@ void GL_APIENTRY GL_VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib3f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4185,17 +6148,33 @@ void GL_APIENTRY GL_VertexAttrib3fv(GLuint index, const GLfloat *v) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib3fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "", - CID(context), index, (uintptr_t)v); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib3fv, + "context = %d, index = %u, v = 0x%016" PRIxPTR "", CID(context), index, + (uintptr_t)v)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib3fv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib3fv, index, v)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib3fv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib3fv, index, v); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib3fv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, v); @@ -4204,7 +6183,7 @@ void GL_APIENTRY GL_VertexAttrib3fv(GLuint index, const GLfloat *v) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4213,17 +6192,33 @@ void GL_APIENTRY GL_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib4f, "context = %d, index = %u, x = %f, y = %f, z = %f, w = %f", - CID(context), index, x, y, z, w); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib4f, + "context = %d, index = %u, x = %f, y = %f, z = %f, w = %f", + CID(context), index, x, y, z, w)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib4f(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib4f, index, x, y, z, w)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib4f( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib4f, index, x, y, z, w); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib4f); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib4f(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, x, y, z, w); @@ -4232,7 +6227,7 @@ void GL_APIENTRY GL_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib4f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4241,17 +6236,33 @@ void GL_APIENTRY GL_VertexAttrib4fv(GLuint index, const GLfloat *v) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttrib4fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "", - CID(context), index, (uintptr_t)v); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttrib4fv, + "context = %d, index = %u, v = 0x%016" PRIxPTR "", CID(context), index, + (uintptr_t)v)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttrib4fv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttrib4fv, index, v)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttrib4fv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttrib4fv, index, v); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttrib4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttrib4fv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, v); @@ -4260,7 +6271,7 @@ void GL_APIENTRY GL_VertexAttrib4fv(GLuint index, const GLfloat *v) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttrib4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4274,21 +6285,38 @@ void GL_APIENTRY GL_VertexAttribPointer(GLuint index, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribPointer, - "context = %d, index = %u, size = %d, type = %s, normalized = %s, stride = %d, pointer = " - "0x%016" PRIxPTR "", - CID(context), index, size, GLenumToString(GLESEnum::VertexAttribPointerType, type), - GLbooleanToString(normalized), stride, (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribPointer, + "context = %d, index = %u, size = %d, type = %s, normalized = %s, " + "stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), index, size, + GLenumToString(GLESEnum::VertexAttribPointerType, type), + GLbooleanToString(normalized), stride, (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribPointer(context, angle::EntryPoint::GLVertexAttribPointer, index, - size, typePacked, normalized, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_2_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribPointer( + context, angle::EntryPoint::GLVertexAttribPointer, index, size, typePacked, + normalized, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES20(context, angle::EntryPoint::GLVertexAttribPointer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->vertexAttribPointer(index, size, typePacked, normalized, stride, pointer); } @@ -4297,7 +6325,7 @@ void GL_APIENTRY GL_VertexAttribPointer(GLuint index, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribPointer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4306,16 +6334,29 @@ void GL_APIENTRY GL_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLViewport, "context = %d, x = %d, y = %d, width = %d, height = %d", - CID(context), x, y, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLViewport, + "context = %d, x = %d, y = %d, width = %d, height = %d", CID(context), + x, y, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateViewport(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLViewport, x, y, width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(true)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateViewport(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLViewport, x, y, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateViewport(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), x, y, width, height); @@ -4324,7 +6365,7 @@ void GL_APIENTRY GL_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLViewport); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } diff --git a/src/libGLESv2/entry_points_gles_3_0_autogen.cpp b/src/libGLESv2/entry_points_gles_3_0_autogen.cpp index 177f8fed3d0..7808db74fbb 100644 --- a/src/libGLESv2/entry_points_gles_3_0_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_3_0_autogen.cpp @@ -28,22 +28,34 @@ void GL_APIENTRY GL_BeginQuery(GLenum target, GLuint id) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBeginQuery, "context = %d, target = %s, id = %u", CID(context), - GLenumToString(GLESEnum::QueryTarget, target), id); + ANGLE_UNSAFE_TODO(EVENT(context, GLBeginQuery, "context = %d, target = %s, id = %u", + CID(context), GLenumToString(GLESEnum::QueryTarget, target), id)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBeginQuery) && - ValidateBeginQuery(context, angle::EntryPoint::GLBeginQuery, targetPacked, - idPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBeginQuery(context, angle::EntryPoint::GLBeginQuery, + targetPacked, idPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBeginQuery); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->beginQuery(targetPacked, idPacked); } @@ -51,7 +63,7 @@ void GL_APIENTRY GL_BeginQuery(GLenum target, GLuint id) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBeginQuery); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -60,21 +72,37 @@ void GL_APIENTRY GL_BeginTransformFeedback(GLenum primitiveMode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBeginTransformFeedback, "context = %d, primitiveMode = %s", CID(context), - GLenumToString(GLESEnum::PrimitiveType, primitiveMode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBeginTransformFeedback, "context = %d, primitiveMode = %s", + CID(context), GLenumToString(GLESEnum::PrimitiveType, primitiveMode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode primitiveModePacked = PackParam(primitiveMode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBeginTransformFeedback) && - ValidateBeginTransformFeedback(context, angle::EntryPoint::GLBeginTransformFeedback, - primitiveModePacked))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBeginTransformFeedback( + context, angle::EntryPoint::GLBeginTransformFeedback, primitiveModePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBeginTransformFeedback); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->beginTransformFeedback(primitiveModePacked); } @@ -82,7 +110,7 @@ void GL_APIENTRY GL_BeginTransformFeedback(GLenum primitiveMode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBeginTransformFeedback); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -91,18 +119,35 @@ void GL_APIENTRY GL_BindBufferBase(GLenum target, GLuint index, GLuint buffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindBufferBase, "context = %d, target = %s, index = %u, buffer = %u", - CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), index, buffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindBufferBase, + "context = %d, target = %s, index = %u, buffer = %u", CID(context), + GLenumToString(GLESEnum::BufferTargetARB, target), index, buffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateBindBufferBase(context, angle::EntryPoint::GLBindBufferBase, - targetPacked, index, bufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindBufferBase(context, angle::EntryPoint::GLBindBufferBase, + targetPacked, index, bufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBindBufferBase); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindBufferBase(targetPacked, index, bufferPacked); } @@ -110,7 +155,7 @@ void GL_APIENTRY GL_BindBufferBase(GLenum target, GLuint index, GLuint buffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindBufferBase); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -120,21 +165,38 @@ GL_BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindBufferRange, - "context = %d, target = %s, index = %u, buffer = %u, offset = %llu, size = %llu", - CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), index, buffer, - static_cast(offset), static_cast(size)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBindBufferRange, + "context = %d, target = %s, index = %u, buffer = %u, offset = %llu, size = %llu", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), index, buffer, + static_cast(offset), static_cast(size))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateBindBufferRange(context, angle::EntryPoint::GLBindBufferRange, targetPacked, - index, bufferPacked, offset, size)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateBindBufferRange(context, angle::EntryPoint::GLBindBufferRange, + targetPacked, index, bufferPacked, offset, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBindBufferRange); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindBufferRange(targetPacked, index, bufferPacked, offset, size); } @@ -143,7 +205,7 @@ GL_BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindBufferRange); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -152,17 +214,33 @@ void GL_APIENTRY GL_BindSampler(GLuint unit, GLuint sampler) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindSampler, "context = %d, unit = %u, sampler = %u", CID(context), unit, - sampler); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindSampler, "context = %d, unit = %u, sampler = %u", + CID(context), unit, sampler)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateBindSampler(context, angle::EntryPoint::GLBindSampler, unit, samplerPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindSampler(context, angle::EntryPoint::GLBindSampler, unit, + samplerPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBindSampler); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindSampler(unit, samplerPacked); } @@ -170,7 +248,7 @@ void GL_APIENTRY GL_BindSampler(GLuint unit, GLuint sampler) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindSampler); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -179,21 +257,34 @@ void GL_APIENTRY GL_BindTransformFeedback(GLenum target, GLuint id) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindTransformFeedback, "context = %d, target = %s, id = %u", CID(context), - GLenumToString(GLESEnum::BindTransformFeedbackTarget, target), id); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindTransformFeedback, "context = %d, target = %s, id = %u", + CID(context), + GLenumToString(GLESEnum::BindTransformFeedbackTarget, target), id)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TransformFeedbackID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindTransformFeedback) && - ValidateBindTransformFeedback(context, angle::EntryPoint::GLBindTransformFeedback, - target, idPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindTransformFeedback( + context, angle::EntryPoint::GLBindTransformFeedback, target, idPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBindTransformFeedback); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindTransformFeedback(target, idPacked); } @@ -201,7 +292,7 @@ void GL_APIENTRY GL_BindTransformFeedback(GLenum target, GLuint id) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindTransformFeedback); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -210,16 +301,33 @@ void GL_APIENTRY GL_BindVertexArray(GLuint array) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindVertexArray, "context = %d, array = %u", CID(context), array); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBindVertexArray, "context = %d, array = %u", CID(context), array)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexArrayID arrayPacked = PackParam(array); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateBindVertexArray(context, angle::EntryPoint::GLBindVertexArray, arrayPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindVertexArray(context, angle::EntryPoint::GLBindVertexArray, + arrayPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBindVertexArray); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindVertexArray(arrayPacked); } @@ -227,7 +335,7 @@ void GL_APIENTRY GL_BindVertexArray(GLuint array) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindVertexArray); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -245,24 +353,41 @@ void GL_APIENTRY GL_BlitFramebuffer(GLint srcX0, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlitFramebuffer, - "context = %d, srcX0 = %d, srcY0 = %d, srcX1 = %d, srcY1 = %d, dstX0 = %d, dstY0 = %d, " - "dstX1 = %d, dstY1 = %d, mask = %s, filter = %s", - CID(context), srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str(), - GLenumToString(GLESEnum::BlitFramebufferFilter, filter)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlitFramebuffer, + "context = %d, srcX0 = %d, srcY0 = %d, srcX1 = %d, srcY1 = %d, dstX0 = " + "%d, dstY0 = %d, dstX1 = %d, dstY1 = %d, mask = %s, filter = %s", + CID(context), srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str(), + GLenumToString(GLESEnum::BlitFramebufferFilter, filter))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlitFramebuffer) && - ValidateBlitFramebuffer(context, angle::EntryPoint::GLBlitFramebuffer, srcX0, srcY0, - srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlitFramebuffer(context, angle::EntryPoint::GLBlitFramebuffer, + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, + dstX1, dstY1, mask, filter); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLBlitFramebuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); @@ -272,7 +397,7 @@ void GL_APIENTRY GL_BlitFramebuffer(GLint srcX0, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlitFramebuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -281,17 +406,34 @@ void GL_APIENTRY GL_ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearBufferfi, - "context = %d, buffer = %s, drawbuffer = %d, depth = %f, stencil = %d", CID(context), - GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, depth, stencil); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearBufferfi, + "context = %d, buffer = %s, drawbuffer = %d, depth = %f, stencil = %d", + CID(context), GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, + depth, stencil)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateClearBufferfi(context, angle::EntryPoint::GLClearBufferfi, - buffer, drawbuffer, depth, stencil)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearBufferfi(context, angle::EntryPoint::GLClearBufferfi, + buffer, drawbuffer, depth, stencil); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLClearBufferfi); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clearBufferfi(buffer, drawbuffer, depth, stencil); } @@ -299,7 +441,7 @@ void GL_APIENTRY GL_ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearBufferfi); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -308,17 +450,34 @@ void GL_APIENTRY GL_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearBufferfv, - "context = %d, buffer = %s, drawbuffer = %d, value = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearBufferfv, + "context = %d, buffer = %s, drawbuffer = %d, value = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateClearBufferfv(context, angle::EntryPoint::GLClearBufferfv, - buffer, drawbuffer, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearBufferfv(context, angle::EntryPoint::GLClearBufferfv, + buffer, drawbuffer, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLClearBufferfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clearBufferfv(buffer, drawbuffer, value); } @@ -326,7 +485,7 @@ void GL_APIENTRY GL_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearBufferfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -335,17 +494,34 @@ void GL_APIENTRY GL_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearBufferiv, - "context = %d, buffer = %s, drawbuffer = %d, value = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearBufferiv, + "context = %d, buffer = %s, drawbuffer = %d, value = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateClearBufferiv(context, angle::EntryPoint::GLClearBufferiv, - buffer, drawbuffer, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearBufferiv(context, angle::EntryPoint::GLClearBufferiv, + buffer, drawbuffer, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLClearBufferiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clearBufferiv(buffer, drawbuffer, value); } @@ -353,7 +529,7 @@ void GL_APIENTRY GL_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearBufferiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -362,17 +538,34 @@ void GL_APIENTRY GL_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearBufferuiv, - "context = %d, buffer = %s, drawbuffer = %d, value = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLClearBufferuiv, + "context = %d, buffer = %s, drawbuffer = %d, value = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::Buffer, buffer), drawbuffer, + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateClearBufferuiv(context, angle::EntryPoint::GLClearBufferuiv, - buffer, drawbuffer, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearBufferuiv(context, angle::EntryPoint::GLClearBufferuiv, + buffer, drawbuffer, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLClearBufferuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clearBufferuiv(buffer, drawbuffer, value); } @@ -380,7 +573,7 @@ void GL_APIENTRY GL_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearBufferuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -389,24 +582,37 @@ GLenum GL_APIENTRY GL_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 tim { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClientWaitSync, - "context = %d, sync = 0x%016" PRIxPTR ", flags = %s, timeout = %llu", CID(context), - (uintptr_t)sync, GLbitfieldToString(GLESEnum::SyncObjectMask, flags).c_str(), - static_cast(timeout)); + ANGLE_UNSAFE_TODO(EVENT(context, GLClientWaitSync, + "context = %d, sync = 0x%016" PRIxPTR ", flags = %s, timeout = %llu", + CID(context), (uintptr_t)sync, + GLbitfieldToString(GLESEnum::SyncObjectMask, flags).c_str(), + static_cast(timeout))); GLenum returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SyncID syncPacked = PackParam(sync); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClientWaitSync) && - ValidateClientWaitSync(context, angle::EntryPoint::GLClientWaitSync, syncPacked, - flags, timeout))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClientWaitSync(context, angle::EntryPoint::GLClientWaitSync, + syncPacked, flags, timeout); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLClientWaitSync); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->clientWaitSync(syncPacked, flags, timeout); } @@ -419,7 +625,7 @@ GLenum GL_APIENTRY GL_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 tim } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClientWaitSync); returnValue = GetDefaultReturnValue(); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue); @@ -438,26 +644,39 @@ void GL_APIENTRY GL_CompressedTexImage3D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexImage3D, - "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, border = %d, imageSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, depth, border, - imageSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCompressedTexImage3D, + "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = " + "%d, depth = %d, border = %d, imageSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, depth, + border, imageSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexImage3D) && - ValidateCompressedTexImage3D(context, angle::EntryPoint::GLCompressedTexImage3D, - targetPacked, level, internalformat, width, height, - depth, border, imageSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexImage3D( + context, angle::EntryPoint::GLCompressedTexImage3D, targetPacked, level, + internalformat, width, height, depth, border, imageSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLCompressedTexImage3D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexImage3D(targetPacked, level, internalformat, width, height, depth, border, imageSize, data); @@ -467,7 +686,7 @@ void GL_APIENTRY GL_CompressedTexImage3D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCompressedTexImage3D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -486,26 +705,39 @@ void GL_APIENTRY GL_CompressedTexSubImage3D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexSubImage3D, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width " - "= %d, height = %d, depth = %d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - zoffset, width, height, depth, GLenumToString(GLESEnum::InternalFormat, format), - imageSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLCompressedTexSubImage3D, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width = " + "%d, height = %d, depth = %d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, + zoffset, width, height, depth, GLenumToString(GLESEnum::InternalFormat, format), imageSize, + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexSubImage3D) && - ValidateCompressedTexSubImage3D(context, angle::EntryPoint::GLCompressedTexSubImage3D, - targetPacked, level, xoffset, yoffset, zoffset, width, - height, depth, format, imageSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexSubImage3D( + context, angle::EntryPoint::GLCompressedTexSubImage3D, targetPacked, level, + xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLCompressedTexSubImage3D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexSubImage3D(targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); @@ -515,7 +747,8 @@ void GL_APIENTRY GL_CompressedTexSubImage3D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexSubImage3D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -528,28 +761,41 @@ void GL_APIENTRY GL_CopyBufferSubData(GLenum readTarget, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyBufferSubData, - "context = %d, readTarget = %s, writeTarget = %s, readOffset = %llu, writeOffset = %llu, " - "size = %llu", - CID(context), GLenumToString(GLESEnum::CopyBufferSubDataTarget, readTarget), - GLenumToString(GLESEnum::CopyBufferSubDataTarget, writeTarget), - static_cast(readOffset), static_cast(writeOffset), - static_cast(size)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopyBufferSubData, + "context = %d, readTarget = %s, writeTarget = %s, readOffset = %llu, writeOffset = " + "%llu, size = %llu", + CID(context), GLenumToString(GLESEnum::CopyBufferSubDataTarget, readTarget), + GLenumToString(GLESEnum::CopyBufferSubDataTarget, writeTarget), + static_cast(readOffset), + static_cast(writeOffset), static_cast(size))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding readTargetPacked = PackParam(readTarget); BufferBinding writeTargetPacked = PackParam(writeTarget); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyBufferSubData) && - ValidateCopyBufferSubData(context, angle::EntryPoint::GLCopyBufferSubData, - readTargetPacked, writeTargetPacked, readOffset, - writeOffset, size))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyBufferSubData( + context, angle::EntryPoint::GLCopyBufferSubData, readTargetPacked, + writeTargetPacked, readOffset, writeOffset, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLCopyBufferSubData); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyBufferSubData(readTargetPacked, writeTargetPacked, readOffset, writeOffset, size); @@ -559,7 +805,7 @@ void GL_APIENTRY GL_CopyBufferSubData(GLenum readTarget, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyBufferSubData); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -576,25 +822,41 @@ void GL_APIENTRY GL_CopyTexSubImage3D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyTexSubImage3D, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, x = " - "%d, y = %d, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - zoffset, x, y, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLCopyTexSubImage3D, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, " + "zoffset = %d, x = %d, y = %d, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + xoffset, yoffset, zoffset, x, y, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyTexSubImage3D) && - ValidateCopyTexSubImage3D(context, angle::EntryPoint::GLCopyTexSubImage3D, - targetPacked, level, xoffset, yoffset, zoffset, x, y, width, - height))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyTexSubImage3D( + context, angle::EntryPoint::GLCopyTexSubImage3D, targetPacked, level, xoffset, + yoffset, zoffset, x, y, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLCopyTexSubImage3D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyTexSubImage3D(targetPacked, level, xoffset, yoffset, zoffset, x, y, width, height); @@ -604,7 +866,7 @@ void GL_APIENTRY GL_CopyTexSubImage3D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyTexSubImage3D); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -613,17 +875,34 @@ void GL_APIENTRY GL_DeleteQueries(GLsizei n, const GLuint *ids) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteQueries, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), - n, (uintptr_t)ids); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteQueries, + "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)ids)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const QueryID *idsPacked = PackParam(ids); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteQueries(context, angle::EntryPoint::GLDeleteQueries, n, idsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteQueries(context, angle::EntryPoint::GLDeleteQueries, n, + idsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDeleteQueries); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteQueries(n, idsPacked); } @@ -631,7 +910,7 @@ void GL_APIENTRY GL_DeleteQueries(GLsizei n, const GLuint *ids) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteQueries); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -640,17 +919,34 @@ void GL_APIENTRY GL_DeleteSamplers(GLsizei count, const GLuint *samplers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteSamplers, "context = %d, count = %d, samplers = 0x%016" PRIxPTR "", - CID(context), count, (uintptr_t)samplers); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteSamplers, + "context = %d, count = %d, samplers = 0x%016" PRIxPTR "", CID(context), + count, (uintptr_t)samplers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const SamplerID *samplersPacked = PackParam(samplers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDeleteSamplers(context, angle::EntryPoint::GLDeleteSamplers, - count, samplersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteSamplers(context, angle::EntryPoint::GLDeleteSamplers, + count, samplersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDeleteSamplers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteSamplers(count, samplersPacked); } @@ -658,7 +954,7 @@ void GL_APIENTRY GL_DeleteSamplers(GLsizei count, const GLuint *samplers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteSamplers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -667,17 +963,33 @@ void GL_APIENTRY GL_DeleteSync(GLsync sync) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteSync, "context = %d, sync = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)sync); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteSync, "context = %d, sync = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)sync)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SyncID syncPacked = PackParam(sync); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteSync(context, angle::EntryPoint::GLDeleteSync, syncPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDeleteSync(context, angle::EntryPoint::GLDeleteSync, syncPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDeleteSync); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteSync(syncPacked); } @@ -685,7 +997,7 @@ void GL_APIENTRY GL_DeleteSync(GLsync sync) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteSync); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -694,18 +1006,34 @@ void GL_APIENTRY GL_DeleteTransformFeedbacks(GLsizei n, const GLuint *ids) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteTransformFeedbacks, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)ids); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteTransformFeedbacks, + "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)ids)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const TransformFeedbackID *idsPacked = PackParam(ids); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteTransformFeedbacks( - context, angle::EntryPoint::GLDeleteTransformFeedbacks, n, idsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteTransformFeedbacks( + context, angle::EntryPoint::GLDeleteTransformFeedbacks, n, idsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDeleteTransformFeedbacks); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteTransformFeedbacks(n, idsPacked); } @@ -713,7 +1041,8 @@ void GL_APIENTRY GL_DeleteTransformFeedbacks(GLsizei n, const GLuint *ids) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDeleteTransformFeedbacks); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -722,17 +1051,34 @@ void GL_APIENTRY GL_DeleteVertexArrays(GLsizei n, const GLuint *arrays) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteVertexArrays, "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)arrays); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteVertexArrays, + "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)arrays)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const VertexArrayID *arraysPacked = PackParam(arrays); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDeleteVertexArrays( - context, angle::EntryPoint::GLDeleteVertexArrays, n, arraysPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteVertexArrays( + context, angle::EntryPoint::GLDeleteVertexArrays, n, arraysPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDeleteVertexArrays); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteVertexArrays(n, arraysPacked); } @@ -740,7 +1086,7 @@ void GL_APIENTRY GL_DeleteVertexArrays(GLsizei n, const GLuint *arrays) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteVertexArrays); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -752,19 +1098,36 @@ void GL_APIENTRY GL_DrawArraysInstanced(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArraysInstanced, - "context = %d, mode = %s, first = %d, count = %d, instancecount = %d", CID(context), - GLenumToString(GLESEnum::PrimitiveType, mode), first, count, instancecount); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawArraysInstanced, + "context = %d, mode = %s, first = %d, count = %d, instancecount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), first, + count, instancecount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawArraysInstanced(context, angle::EntryPoint::GLDrawArraysInstanced, - modePacked, first, count, instancecount)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawArraysInstanced(context, angle::EntryPoint::GLDrawArraysInstanced, + modePacked, first, count, instancecount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDrawArraysInstanced); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawArraysInstanced(modePacked, first, count, instancecount); } @@ -773,7 +1136,7 @@ void GL_APIENTRY GL_DrawArraysInstanced(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawArraysInstanced); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -782,16 +1145,37 @@ void GL_APIENTRY GL_DrawBuffers(GLsizei n, const GLenum *bufs) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawBuffers, "context = %d, n = %d, bufs = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)bufs); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawBuffers, + "context = %d, n = %d, bufs = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)bufs)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawBuffers(context, angle::EntryPoint::GLDrawBuffers, n, bufs)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawBuffers(context, angle::EntryPoint::GLDrawBuffers, n, bufs); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDrawBuffers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawBuffers(n, bufs); } @@ -799,7 +1183,7 @@ void GL_APIENTRY GL_DrawBuffers(GLsizei n, const GLenum *bufs) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawBuffers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -812,22 +1196,39 @@ void GL_APIENTRY GL_DrawElementsInstanced(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstanced, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instancecount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstanced, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instancecount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawElementsInstanced(context, angle::EntryPoint::GLDrawElementsInstanced, - modePacked, count, typePacked, indices, instancecount)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstanced( + context, angle::EntryPoint::GLDrawElementsInstanced, modePacked, count, + typePacked, indices, instancecount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDrawElementsInstanced); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstanced(modePacked, count, typePacked, indices, instancecount); } @@ -836,7 +1237,7 @@ void GL_APIENTRY GL_DrawElementsInstanced(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawElementsInstanced); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -850,22 +1251,39 @@ void GL_APIENTRY GL_DrawRangeElements(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawRangeElements, - "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, indices = " - "0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawRangeElements, + "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, " + "indices = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, + count, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawRangeElements(context, angle::EntryPoint::GLDrawRangeElements, modePacked, - start, end, count, typePacked, indices)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawRangeElements(context, angle::EntryPoint::GLDrawRangeElements, + modePacked, start, end, count, typePacked, indices); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLDrawRangeElements); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawRangeElements(modePacked, start, end, count, typePacked, indices); } @@ -874,7 +1292,7 @@ void GL_APIENTRY GL_DrawRangeElements(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawRangeElements); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -883,20 +1301,33 @@ void GL_APIENTRY GL_EndQuery(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEndQuery, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::QueryTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLEndQuery, "context = %d, target = %s", CID(context), + GLenumToString(GLESEnum::QueryTarget, target))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEndQuery) && - ValidateEndQuery(context, angle::EntryPoint::GLEndQuery, targetPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateEndQuery(context, angle::EntryPoint::GLEndQuery, targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLEndQuery); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->endQuery(targetPacked); } @@ -904,7 +1335,7 @@ void GL_APIENTRY GL_EndQuery(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEndQuery); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -913,18 +1344,31 @@ void GL_APIENTRY GL_EndTransformFeedback() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEndTransformFeedback, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLEndTransformFeedback, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEndTransformFeedback) && - ValidateEndTransformFeedback(context, angle::EntryPoint::GLEndTransformFeedback))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEndTransformFeedback( + context, angle::EntryPoint::GLEndTransformFeedback); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLEndTransformFeedback); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->endTransformFeedback(); } @@ -932,7 +1376,7 @@ void GL_APIENTRY GL_EndTransformFeedback() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEndTransformFeedback); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -941,18 +1385,34 @@ GLsync GL_APIENTRY GL_FenceSync(GLenum condition, GLbitfield flags) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFenceSync, "context = %d, condition = %s, flags = %s", CID(context), - GLenumToString(GLESEnum::SyncCondition, condition), - GLbitfieldToString(GLESEnum::SyncBehaviorFlags, flags).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLFenceSync, "context = %d, condition = %s, flags = %s", + CID(context), GLenumToString(GLESEnum::SyncCondition, condition), + GLbitfieldToString(GLESEnum::SyncBehaviorFlags, flags).c_str())); GLsync returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFenceSync(context, angle::EntryPoint::GLFenceSync, condition, flags)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateFenceSync(context, angle::EntryPoint::GLFenceSync, condition, flags); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLFenceSync); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->fenceSync(condition, flags); } @@ -964,7 +1424,7 @@ GLsync GL_APIENTRY GL_FenceSync(GLenum condition, GLbitfield flags) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFenceSync); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -975,20 +1435,37 @@ void GL_APIENTRY GL_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsiz { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFlushMappedBufferRange, - "context = %d, target = %s, offset = %llu, length = %llu", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - static_cast(offset), static_cast(length)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFlushMappedBufferRange, + "context = %d, target = %s, offset = %llu, length = %llu", CID(context), + GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(offset), + static_cast(length))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFlushMappedBufferRange(context, angle::EntryPoint::GLFlushMappedBufferRange, - targetPacked, offset, length)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFlushMappedBufferRange( + context, angle::EntryPoint::GLFlushMappedBufferRange, targetPacked, offset, + length); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLFlushMappedBufferRange); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->flushMappedBufferRange(targetPacked, offset, length); } @@ -997,7 +1474,7 @@ void GL_APIENTRY GL_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsiz } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFlushMappedBufferRange); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1010,20 +1487,41 @@ void GL_APIENTRY GL_FramebufferTextureLayer(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTextureLayer, - "context = %d, target = %s, attachment = %s, texture = %u, level = %d, layer = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, level, layer); + ANGLE_UNSAFE_TODO( + EVENT(context, GLFramebufferTextureLayer, + "context = %d, target = %s, attachment = %s, texture = %u, level = %d, layer = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, level, layer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferTextureLayer(context, angle::EntryPoint::GLFramebufferTextureLayer, - target, attachment, texturePacked, level, layer)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTextureLayer( + context, angle::EntryPoint::GLFramebufferTextureLayer, target, attachment, + texturePacked, level, layer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLFramebufferTextureLayer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTextureLayer(target, attachment, texturePacked, level, layer); } @@ -1032,7 +1530,8 @@ void GL_APIENTRY GL_FramebufferTextureLayer(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTextureLayer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1041,17 +1540,33 @@ void GL_APIENTRY GL_GenQueries(GLsizei n, GLuint *ids) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenQueries, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)ids); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenQueries, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", + CID(context), n, (uintptr_t)ids)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID *idsPacked = PackParam(ids); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenQueries(context, angle::EntryPoint::GLGenQueries, n, idsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGenQueries(context, angle::EntryPoint::GLGenQueries, n, idsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGenQueries); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genQueries(n, idsPacked); } @@ -1059,7 +1574,7 @@ void GL_APIENTRY GL_GenQueries(GLsizei n, GLuint *ids) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenQueries); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1068,17 +1583,34 @@ void GL_APIENTRY GL_GenSamplers(GLsizei count, GLuint *samplers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenSamplers, "context = %d, count = %d, samplers = 0x%016" PRIxPTR "", - CID(context), count, (uintptr_t)samplers); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenSamplers, + "context = %d, count = %d, samplers = 0x%016" PRIxPTR "", CID(context), + count, (uintptr_t)samplers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID *samplersPacked = PackParam(samplers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenSamplers(context, angle::EntryPoint::GLGenSamplers, count, samplersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenSamplers(context, angle::EntryPoint::GLGenSamplers, count, + samplersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGenSamplers); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genSamplers(count, samplersPacked); } @@ -1086,7 +1618,7 @@ void GL_APIENTRY GL_GenSamplers(GLsizei count, GLuint *samplers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenSamplers); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1095,17 +1627,34 @@ void GL_APIENTRY GL_GenTransformFeedbacks(GLsizei n, GLuint *ids) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenTransformFeedbacks, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)ids); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenTransformFeedbacks, + "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)ids)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TransformFeedbackID *idsPacked = PackParam(ids); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenTransformFeedbacks( - context, angle::EntryPoint::GLGenTransformFeedbacks, n, idsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenTransformFeedbacks( + context, angle::EntryPoint::GLGenTransformFeedbacks, n, idsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGenTransformFeedbacks); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genTransformFeedbacks(n, idsPacked); } @@ -1113,7 +1662,7 @@ void GL_APIENTRY GL_GenTransformFeedbacks(GLsizei n, GLuint *ids) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenTransformFeedbacks); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1122,17 +1671,34 @@ void GL_APIENTRY GL_GenVertexArrays(GLsizei n, GLuint *arrays) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenVertexArrays, "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)arrays); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenVertexArrays, + "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)arrays)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexArrayID *arraysPacked = PackParam(arrays); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenVertexArrays(context, angle::EntryPoint::GLGenVertexArrays, - n, arraysPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenVertexArrays(context, angle::EntryPoint::GLGenVertexArrays, + n, arraysPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGenVertexArrays); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genVertexArrays(n, arraysPacked); } @@ -1140,7 +1706,7 @@ void GL_APIENTRY GL_GenVertexArrays(GLsizei n, GLuint *arrays) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenVertexArrays); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1153,24 +1719,39 @@ void GL_APIENTRY GL_GetActiveUniformBlockName(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT( + ANGLE_UNSAFE_TODO(EVENT( context, GLGetActiveUniformBlockName, "context = %d, program = %u, uniformBlockIndex = %u, bufSize = %d, length = 0x%016" PRIxPTR ", uniformBlockName = 0x%016" PRIxPTR "", CID(context), program, uniformBlockIndex, bufSize, (uintptr_t)length, - (uintptr_t)uniformBlockName); + (uintptr_t)uniformBlockName)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformBlockIndex uniformBlockIndexPacked = PackParam(uniformBlockIndex); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetActiveUniformBlockName( - context, angle::EntryPoint::GLGetActiveUniformBlockName, programPacked, - uniformBlockIndexPacked, bufSize, length, uniformBlockName)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetActiveUniformBlockName( + context, angle::EntryPoint::GLGetActiveUniformBlockName, programPacked, + uniformBlockIndexPacked, bufSize, length, uniformBlockName); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetActiveUniformBlockName); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getActiveUniformBlockName(programPacked, uniformBlockIndexPacked, bufSize, length, uniformBlockName); @@ -1180,7 +1761,8 @@ void GL_APIENTRY GL_GetActiveUniformBlockName(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetActiveUniformBlockName); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1192,22 +1774,39 @@ void GL_APIENTRY GL_GetActiveUniformBlockiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetActiveUniformBlockiv, - "context = %d, program = %u, uniformBlockIndex = %u, pname = %s, params = 0x%016" PRIxPTR - "", - CID(context), program, uniformBlockIndex, - GLenumToString(GLESEnum::UniformBlockPName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetActiveUniformBlockiv, + "context = %d, program = %u, uniformBlockIndex = %u, pname = %s, params = 0x%016" PRIxPTR + "", + CID(context), program, uniformBlockIndex, + GLenumToString(GLESEnum::UniformBlockPName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformBlockIndex uniformBlockIndexPacked = PackParam(uniformBlockIndex); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetActiveUniformBlockiv( - context, angle::EntryPoint::GLGetActiveUniformBlockiv, - programPacked, uniformBlockIndexPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetActiveUniformBlockiv( + context, angle::EntryPoint::GLGetActiveUniformBlockiv, programPacked, + uniformBlockIndexPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetActiveUniformBlockiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getActiveUniformBlockiv(programPacked, uniformBlockIndexPacked, pname, params); } @@ -1216,7 +1815,8 @@ void GL_APIENTRY GL_GetActiveUniformBlockiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetActiveUniformBlockiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1229,21 +1829,38 @@ void GL_APIENTRY GL_GetActiveUniformsiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetActiveUniformsiv, - "context = %d, program = %u, uniformCount = %d, uniformIndices = 0x%016" PRIxPTR - ", pname = %s, params = 0x%016" PRIxPTR "", - CID(context), program, uniformCount, (uintptr_t)uniformIndices, - GLenumToString(GLESEnum::UniformPName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetActiveUniformsiv, + "context = %d, program = %u, uniformCount = %d, uniformIndices = 0x%016" PRIxPTR + ", pname = %s, params = 0x%016" PRIxPTR "", + CID(context), program, uniformCount, (uintptr_t)uniformIndices, + GLenumToString(GLESEnum::UniformPName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetActiveUniformsiv( - context, angle::EntryPoint::GLGetActiveUniformsiv, programPacked, - uniformCount, uniformIndices, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetActiveUniformsiv( + context, angle::EntryPoint::GLGetActiveUniformsiv, programPacked, uniformCount, + uniformIndices, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetActiveUniformsiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getActiveUniformsiv(programPacked, uniformCount, uniformIndices, pname, params); @@ -1253,7 +1870,7 @@ void GL_APIENTRY GL_GetActiveUniformsiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetActiveUniformsiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1262,20 +1879,36 @@ void GL_APIENTRY GL_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferParameteri64v, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetBufferParameteri64v, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetBufferParameteri64v(context, angle::EntryPoint::GLGetBufferParameteri64v, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBufferParameteri64v( + context, angle::EntryPoint::GLGetBufferParameteri64v, targetPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetBufferParameteri64v); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferParameteri64v(targetPacked, pname, params); } @@ -1283,7 +1916,7 @@ void GL_APIENTRY GL_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBufferParameteri64v); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1292,20 +1925,35 @@ void GL_APIENTRY GL_GetBufferPointerv(GLenum target, GLenum pname, void **params { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferPointerv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetBufferPointerv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetBufferPointerv(context, angle::EntryPoint::GLGetBufferPointerv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBufferPointerv( + context, angle::EntryPoint::GLGetBufferPointerv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetBufferPointerv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferPointerv(targetPacked, pname, params); } @@ -1313,7 +1961,7 @@ void GL_APIENTRY GL_GetBufferPointerv(GLenum target, GLenum pname, void **params } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBufferPointerv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1322,19 +1970,35 @@ GLint GL_APIENTRY GL_GetFragDataLocation(GLuint program, const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFragDataLocation, "context = %d, program = %u, name = 0x%016" PRIxPTR "", - CID(context), program, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFragDataLocation, + "context = %d, program = %u, name = 0x%016" PRIxPTR "", CID(context), + program, (uintptr_t)name)); GLint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFragDataLocation(context, angle::EntryPoint::GLGetFragDataLocation, - programPacked, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFragDataLocation( + context, angle::EntryPoint::GLGetFragDataLocation, programPacked, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetFragDataLocation); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getFragDataLocation(programPacked, name); } @@ -1347,7 +2011,7 @@ GLint GL_APIENTRY GL_GetFragDataLocation(GLuint program, const GLchar *name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetFragDataLocation); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -1358,17 +2022,34 @@ void GL_APIENTRY GL_GetInteger64i_v(GLenum target, GLuint index, GLint64 *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInteger64i_v, - "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::GetPName, target), index, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetInteger64i_v, + "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::GetPName, target), index, + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetInteger64i_v(context, angle::EntryPoint::GLGetInteger64i_v, - target, index, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetInteger64i_v(context, angle::EntryPoint::GLGetInteger64i_v, + target, index, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetInteger64i_v); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInteger64i_v(target, index, data); } @@ -1376,7 +2057,7 @@ void GL_APIENTRY GL_GetInteger64i_v(GLenum target, GLuint index, GLint64 *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetInteger64i_v); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1385,16 +2066,33 @@ void GL_APIENTRY GL_GetInteger64v(GLenum pname, GLint64 *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInteger64v, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetInteger64v, + "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetInteger64v(context, angle::EntryPoint::GLGetInteger64v, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetInteger64v(context, angle::EntryPoint::GLGetInteger64v, pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetInteger64v); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInteger64v(pname, data); } @@ -1402,7 +2100,7 @@ void GL_APIENTRY GL_GetInteger64v(GLenum pname, GLint64 *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetInteger64v); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1411,17 +2109,33 @@ void GL_APIENTRY GL_GetIntegeri_v(GLenum target, GLuint index, GLint *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetIntegeri_v, - "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::GetPName, target), index, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetIntegeri_v, "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::GetPName, target), index, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetIntegeri_v(context, angle::EntryPoint::GLGetIntegeri_v, - target, index, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetIntegeri_v(context, angle::EntryPoint::GLGetIntegeri_v, + target, index, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetIntegeri_v); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getIntegeri_v(target, index, data); } @@ -1429,7 +2143,7 @@ void GL_APIENTRY GL_GetIntegeri_v(GLenum target, GLuint index, GLint *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetIntegeri_v); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1442,21 +2156,38 @@ void GL_APIENTRY GL_GetInternalformativ(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInternalformativ, - "context = %d, target = %s, internalformat = %s, pname = %s, count = %d, params = " - "0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::InternalFormat, internalformat), - GLenumToString(GLESEnum::InternalFormatPName, pname), count, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetInternalformativ, + "context = %d, target = %s, internalformat = %s, pname = %s, count = " + "%d, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::InternalFormat, internalformat), + GLenumToString(GLESEnum::InternalFormatPName, pname), count, + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetInternalformativ(context, angle::EntryPoint::GLGetInternalformativ, target, - internalformat, pname, count, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetInternalformativ(context, angle::EntryPoint::GLGetInternalformativ, + target, internalformat, pname, count, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetInternalformativ); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInternalformativ(target, internalformat, pname, count, params); } @@ -1465,7 +2196,7 @@ void GL_APIENTRY GL_GetInternalformativ(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetInternalformativ); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1478,21 +2209,37 @@ void GL_APIENTRY GL_GetProgramBinary(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramBinary, - "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", binaryFormat = 0x%016" PRIxPTR ", binary = 0x%016" PRIxPTR "", - CID(context), program, bufSize, (uintptr_t)length, (uintptr_t)binaryFormat, - (uintptr_t)binary); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetProgramBinary, + "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", binaryFormat = 0x%016" PRIxPTR ", binary = 0x%016" PRIxPTR "", + CID(context), program, bufSize, (uintptr_t)length, + (uintptr_t)binaryFormat, (uintptr_t)binary)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramBinary(context, angle::EntryPoint::GLGetProgramBinary, programPacked, - bufSize, length, binaryFormat, binary)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetProgramBinary(context, angle::EntryPoint::GLGetProgramBinary, + programPacked, bufSize, length, binaryFormat, binary); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetProgramBinary); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramBinary(programPacked, bufSize, length, binaryFormat, binary); } @@ -1501,7 +2248,7 @@ void GL_APIENTRY GL_GetProgramBinary(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramBinary); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1509,20 +2256,36 @@ void GL_APIENTRY GL_GetProgramBinary(GLuint program, void GL_APIENTRY GL_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryObjectuiv, - "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, - GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params); + Context *context = GetGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectuiv, + "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, + GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetQueryObjectuiv(context, angle::EntryPoint::GLGetQueryObjectuiv, idPacked, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectuiv( + context, angle::EntryPoint::GLGetQueryObjectuiv, idPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetQueryObjectuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectuiv(idPacked, pname, params); } @@ -1530,7 +2293,6 @@ void GL_APIENTRY GL_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1539,19 +2301,35 @@ void GL_APIENTRY GL_GetQueryiv(GLenum target, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryiv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::QueryTarget, target), - GLenumToString(GLESEnum::QueryParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetQueryiv, "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::QueryTarget, target), + GLenumToString(GLESEnum::QueryParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetQueryiv(context, angle::EntryPoint::GLGetQueryiv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryiv(context, angle::EntryPoint::GLGetQueryiv, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetQueryiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryiv(targetPacked, pname, params); } @@ -1559,7 +2337,7 @@ void GL_APIENTRY GL_GetQueryiv(GLenum target, GLenum pname, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetQueryiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1568,19 +2346,36 @@ void GL_APIENTRY GL_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterfv, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterF, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterfv, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterF, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetSamplerParameterfv(context, angle::EntryPoint::GLGetSamplerParameterfv, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterfv( + context, angle::EntryPoint::GLGetSamplerParameterfv, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetSamplerParameterfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterfv(samplerPacked, pname, params); } @@ -1588,7 +2383,7 @@ void GL_APIENTRY GL_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetSamplerParameterfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1597,19 +2392,36 @@ void GL_APIENTRY GL_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *p { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameteriv, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameteriv, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetSamplerParameteriv(context, angle::EntryPoint::GLGetSamplerParameteriv, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameteriv( + context, angle::EntryPoint::GLGetSamplerParameteriv, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetSamplerParameteriv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameteriv(samplerPacked, pname, params); } @@ -1617,7 +2429,7 @@ void GL_APIENTRY GL_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *p } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetSamplerParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1626,17 +2438,33 @@ const GLubyte *GL_APIENTRY GL_GetStringi(GLenum name, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetStringi, "context = %d, name = %s, index = %u", CID(context), - GLenumToString(GLESEnum::StringName, name), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetStringi, "context = %d, name = %s, index = %u", + CID(context), GLenumToString(GLESEnum::StringName, name), index)); const GLubyte *returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetStringi(context, angle::EntryPoint::GLGetStringi, name, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetStringi(context, angle::EntryPoint::GLGetStringi, name, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetStringi); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getStringi(name, index); } @@ -1648,7 +2476,7 @@ const GLubyte *GL_APIENTRY GL_GetStringi(GLenum name, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetStringi); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -1660,20 +2488,37 @@ GL_GetSynciv(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *v { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetSynciv, - "context = %d, sync = 0x%016" PRIxPTR ", pname = %s, count = %d, length = 0x%016" PRIxPTR - ", values = 0x%016" PRIxPTR "", - CID(context), (uintptr_t)sync, GLenumToString(GLESEnum::SyncParameterName, pname), count, - (uintptr_t)length, (uintptr_t)values); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetSynciv, + "context = %d, sync = 0x%016" PRIxPTR + ", pname = %s, count = %d, length = 0x%016" PRIxPTR ", values = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)sync, GLenumToString(GLESEnum::SyncParameterName, pname), + count, (uintptr_t)length, (uintptr_t)values)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SyncID syncPacked = PackParam(sync); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSynciv(context, angle::EntryPoint::GLGetSynciv, syncPacked, - pname, count, length, values)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSynciv(context, angle::EntryPoint::GLGetSynciv, syncPacked, + pname, count, length, values); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetSynciv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSynciv(syncPacked, pname, count, length, values); } @@ -1695,21 +2540,38 @@ void GL_APIENTRY GL_GetTransformFeedbackVarying(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTransformFeedbackVarying, - "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", - CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size, - (uintptr_t)type, (uintptr_t)name); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetTransformFeedbackVarying, + "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", + CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size, + (uintptr_t)type, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTransformFeedbackVarying( - context, angle::EntryPoint::GLGetTransformFeedbackVarying, - programPacked, index, bufSize, length, size, type, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTransformFeedbackVarying( + context, angle::EntryPoint::GLGetTransformFeedbackVarying, programPacked, index, + bufSize, length, size, type, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetTransformFeedbackVarying); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTransformFeedbackVarying(programPacked, index, bufSize, length, size, type, name); @@ -1719,7 +2581,8 @@ void GL_APIENTRY GL_GetTransformFeedbackVarying(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTransformFeedbackVarying); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1728,20 +2591,36 @@ GLuint GL_APIENTRY GL_GetUniformBlockIndex(GLuint program, const GLchar *uniform { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformBlockIndex, - "context = %d, program = %u, uniformBlockName = 0x%016" PRIxPTR "", CID(context), program, - (uintptr_t)uniformBlockName); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUniformBlockIndex, + "context = %d, program = %u, uniformBlockName = 0x%016" PRIxPTR "", + CID(context), program, (uintptr_t)uniformBlockName)); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetUniformBlockIndex(context, angle::EntryPoint::GLGetUniformBlockIndex, - programPacked, uniformBlockName)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetUniformBlockIndex(context, angle::EntryPoint::GLGetUniformBlockIndex, + programPacked, uniformBlockName); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetUniformBlockIndex); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getUniformBlockIndex(programPacked, uniformBlockName); } @@ -1755,7 +2634,7 @@ GLuint GL_APIENTRY GL_GetUniformBlockIndex(GLuint program, const GLchar *uniform } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUniformBlockIndex); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -1769,20 +2648,37 @@ void GL_APIENTRY GL_GetUniformIndices(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformIndices, - "context = %d, program = %u, uniformCount = %d, uniformNames = 0x%016" PRIxPTR - ", uniformIndices = 0x%016" PRIxPTR "", - CID(context), program, uniformCount, (uintptr_t)uniformNames, (uintptr_t)uniformIndices); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetUniformIndices, + "context = %d, program = %u, uniformCount = %d, uniformNames = 0x%016" PRIxPTR + ", uniformIndices = 0x%016" PRIxPTR "", + CID(context), program, uniformCount, (uintptr_t)uniformNames, (uintptr_t)uniformIndices)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetUniformIndices(context, angle::EntryPoint::GLGetUniformIndices, - programPacked, uniformCount, uniformNames, uniformIndices)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformIndices( + context, angle::EntryPoint::GLGetUniformIndices, programPacked, uniformCount, + uniformNames, uniformIndices); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetUniformIndices); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformIndices(programPacked, uniformCount, uniformNames, uniformIndices); } @@ -1791,7 +2687,7 @@ void GL_APIENTRY GL_GetUniformIndices(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUniformIndices); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1800,19 +2696,35 @@ void GL_APIENTRY GL_GetUniformuiv(GLuint program, GLint location, GLuint *params { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformuiv, - "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", CID(context), - program, location, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUniformuiv, + "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUniformuiv(context, angle::EntryPoint::GLGetUniformuiv, - programPacked, locationPacked, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformuiv(context, angle::EntryPoint::GLGetUniformuiv, + programPacked, locationPacked, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetUniformuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformuiv(programPacked, locationPacked, params); } @@ -1821,7 +2733,7 @@ void GL_APIENTRY GL_GetUniformuiv(GLuint program, GLint location, GLuint *params } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUniformuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1830,18 +2742,34 @@ void GL_APIENTRY GL_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribIiv, - "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), index, - GLenumToString(GLESEnum::VertexAttribEnum, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetVertexAttribIiv, + "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::VertexAttribEnum, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetVertexAttribIiv(context, angle::EntryPoint::GLGetVertexAttribIiv, index, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribIiv( + context, angle::EntryPoint::GLGetVertexAttribIiv, index, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetVertexAttribIiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribIiv(index, pname, params); } @@ -1849,7 +2777,7 @@ void GL_APIENTRY GL_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetVertexAttribIiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1858,18 +2786,34 @@ void GL_APIENTRY GL_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *para { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribIuiv, - "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), index, - GLenumToString(GLESEnum::VertexAttribEnum, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetVertexAttribIuiv, + "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::VertexAttribEnum, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetVertexAttribIuiv(context, angle::EntryPoint::GLGetVertexAttribIuiv, index, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribIuiv( + context, angle::EntryPoint::GLGetVertexAttribIuiv, index, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLGetVertexAttribIuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribIuiv(index, pname, params); } @@ -1877,7 +2821,7 @@ void GL_APIENTRY GL_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *para } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetVertexAttribIuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1888,22 +2832,40 @@ void GL_APIENTRY GL_InvalidateFramebuffer(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLInvalidateFramebuffer, - "context = %d, target = %s, numAttachments = %d, attachments = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), numAttachments, - (uintptr_t)attachments); + ANGLE_UNSAFE_TODO( + EVENT(context, GLInvalidateFramebuffer, + "context = %d, target = %s, numAttachments = %d, attachments = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), numAttachments, + (uintptr_t)attachments)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLInvalidateFramebuffer) && - ValidateInvalidateFramebuffer(context, angle::EntryPoint::GLInvalidateFramebuffer, - target, numAttachments, attachments))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateInvalidateFramebuffer( + context, angle::EntryPoint::GLInvalidateFramebuffer, target, numAttachments, + attachments); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLInvalidateFramebuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->invalidateFramebuffer(target, numAttachments, attachments); } @@ -1912,7 +2874,7 @@ void GL_APIENTRY GL_InvalidateFramebuffer(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLInvalidateFramebuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1927,24 +2889,41 @@ void GL_APIENTRY GL_InvalidateSubFramebuffer(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLInvalidateSubFramebuffer, - "context = %d, target = %s, numAttachments = %d, attachments = 0x%016" PRIxPTR - ", x = %d, y = %d, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), numAttachments, - (uintptr_t)attachments, x, y, width, height); + ANGLE_UNSAFE_TODO( + EVENT(context, GLInvalidateSubFramebuffer, + "context = %d, target = %s, numAttachments = %d, attachments = 0x%016" PRIxPTR + ", x = %d, y = %d, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), numAttachments, + (uintptr_t)attachments, x, y, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLInvalidateSubFramebuffer) && - ValidateInvalidateSubFramebuffer( - context, angle::EntryPoint::GLInvalidateSubFramebuffer, target, numAttachments, - attachments, x, y, width, height))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateInvalidateSubFramebuffer( + context, angle::EntryPoint::GLInvalidateSubFramebuffer, target, numAttachments, + attachments, x, y, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLInvalidateSubFramebuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->invalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height); @@ -1954,7 +2933,8 @@ void GL_APIENTRY GL_InvalidateSubFramebuffer(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLInvalidateSubFramebuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1963,16 +2943,32 @@ GLboolean GL_APIENTRY GL_IsQuery(GLuint id) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsQuery, "context = %d, id = %u", CID(context), id); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsQuery, "context = %d, id = %u", CID(context), id)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsQuery(context, angle::EntryPoint::GLIsQuery, idPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsQuery(context, angle::EntryPoint::GLIsQuery, idPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLIsQuery); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isQuery(idPacked); } @@ -1984,7 +2980,7 @@ GLboolean GL_APIENTRY GL_IsQuery(GLuint id) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsQuery); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -1995,17 +2991,34 @@ GLboolean GL_APIENTRY GL_IsSampler(GLuint sampler) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsSampler, "context = %d, sampler = %u", CID(context), sampler); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsSampler, "context = %d, sampler = %u", CID(context), sampler)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsSampler(context, angle::EntryPoint::GLIsSampler, samplerPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsSampler(context, angle::EntryPoint::GLIsSampler, samplerPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLIsSampler); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isSampler(samplerPacked); } @@ -2017,7 +3030,7 @@ GLboolean GL_APIENTRY GL_IsSampler(GLuint sampler) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsSampler); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2028,17 +3041,33 @@ GLboolean GL_APIENTRY GL_IsSync(GLsync sync) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsSync, "context = %d, sync = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)sync); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsSync, "context = %d, sync = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)sync)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SyncID syncPacked = PackParam(sync); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsSync(context, angle::EntryPoint::GLIsSync, syncPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsSync(context, angle::EntryPoint::GLIsSync, syncPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLIsSync); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isSync(syncPacked); } @@ -2050,7 +3079,7 @@ GLboolean GL_APIENTRY GL_IsSync(GLsync sync) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsSync); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2061,17 +3090,34 @@ GLboolean GL_APIENTRY GL_IsTransformFeedback(GLuint id) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsTransformFeedback, "context = %d, id = %u", CID(context), id); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsTransformFeedback, "context = %d, id = %u", CID(context), id)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TransformFeedbackID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsTransformFeedback( - context, angle::EntryPoint::GLIsTransformFeedback, idPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsTransformFeedback( + context, angle::EntryPoint::GLIsTransformFeedback, idPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLIsTransformFeedback); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isTransformFeedback(idPacked); } @@ -2084,7 +3130,7 @@ GLboolean GL_APIENTRY GL_IsTransformFeedback(GLuint id) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsTransformFeedback); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2095,19 +3141,38 @@ GLboolean GL_APIENTRY GL_IsVertexArray(GLuint array) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsVertexArray, "context = %d, array = %u", CID(context), array); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsVertexArray, "context = %d, array = %u", CID(context), array)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexArrayID arrayPacked = PackParam(array); - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsVertexArray(context, angle::EntryPoint::GLIsVertexArray, arrayPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - returnValue = context->isVertexArray(arrayPacked); + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsVertexArray( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLIsVertexArray, arrayPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLIsVertexArray); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + returnValue = + ContextPrivateIsVertexArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), arrayPacked); } else { @@ -2117,7 +3182,7 @@ GLboolean GL_APIENTRY GL_IsVertexArray(GLuint array) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsVertexArray); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2131,23 +3196,51 @@ void *GL_APIENTRY GL_MapBufferRange(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMapBufferRange, - "context = %d, target = %s, offset = %llu, length = %llu, access = %s", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - static_cast(offset), static_cast(length), - GLbitfieldToString(GLESEnum::MapBufferAccessMask, access).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLMapBufferRange, + "context = %d, target = %s, offset = %llu, length = %llu, access = %s", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(offset), + static_cast(length), + GLbitfieldToString(GLESEnum::MapBufferAccessMask, access).c_str())); void *returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateMapBufferRange(context, angle::EntryPoint::GLMapBufferRange, - targetPacked, offset, length, access)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMapBufferRange(context, angle::EntryPoint::GLMapBufferRange, + targetPacked, offset, length, access); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLMapBufferRange); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->mapBufferRange(targetPacked, offset, length, access); +#if ANGLE_CAPTURE_ENABLED + angle::FrameCaptureShared *frameCaptureShared = + context->getShareGroup()->getFrameCaptureShared(); + if (returnValue != nullptr && frameCaptureShared->enabled()) + { + Buffer *buffer = context->getState().getTargetBuffer(targetPacked); + ASSERT(buffer); + returnValue = + frameCaptureShared->maybeGetShadowMemoryPointer(buffer, length, access); + } +#endif } else { @@ -2158,7 +3251,7 @@ void *GL_APIENTRY GL_MapBufferRange(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMapBufferRange); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -2169,19 +3262,31 @@ void GL_APIENTRY GL_PauseTransformFeedback() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPauseTransformFeedback, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPauseTransformFeedback, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPauseTransformFeedback) && - ValidatePauseTransformFeedback(context, - angle::EntryPoint::GLPauseTransformFeedback))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePauseTransformFeedback( + context, angle::EntryPoint::GLPauseTransformFeedback); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLPauseTransformFeedback); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->pauseTransformFeedback(); } @@ -2189,7 +3294,7 @@ void GL_APIENTRY GL_PauseTransformFeedback() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPauseTransformFeedback); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2201,23 +3306,36 @@ void GL_APIENTRY GL_ProgramBinary(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramBinary, - "context = %d, program = %u, binaryFormat = %s, binary = 0x%016" PRIxPTR ", length = %d", - CID(context), program, GLenumToString(GLESEnum::AllEnums, binaryFormat), - (uintptr_t)binary, length); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramBinary, + "context = %d, program = %u, binaryFormat = %s, binary = 0x%016" PRIxPTR + ", length = %d", + CID(context), program, GLenumToString(GLESEnum::AllEnums, binaryFormat), + (uintptr_t)binary, length)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramBinary) && - ValidateProgramBinary(context, angle::EntryPoint::GLProgramBinary, programPacked, - binaryFormat, binary, length))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramBinary(context, angle::EntryPoint::GLProgramBinary, + programPacked, binaryFormat, binary, length); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLProgramBinary); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programBinary(programPacked, binaryFormat, binary, length); } @@ -2226,7 +3344,7 @@ void GL_APIENTRY GL_ProgramBinary(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramBinary); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2235,21 +3353,34 @@ void GL_APIENTRY GL_ProgramParameteri(GLuint program, GLenum pname, GLint value) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramParameteri, "context = %d, program = %u, pname = %s, value = %d", - CID(context), program, GLenumToString(GLESEnum::ProgramParameterPName, pname), value); + ANGLE_UNSAFE_TODO(EVENT( + context, GLProgramParameteri, "context = %d, program = %u, pname = %s, value = %d", + CID(context), program, GLenumToString(GLESEnum::ProgramParameterPName, pname), value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramParameteri) && - ValidateProgramParameteri(context, angle::EntryPoint::GLProgramParameteri, - programPacked, pname, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramParameteri( + context, angle::EntryPoint::GLProgramParameteri, programPacked, pname, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLProgramParameteri); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programParameteri(programPacked, pname, value); } @@ -2257,7 +3388,7 @@ void GL_APIENTRY GL_ProgramParameteri(GLuint program, GLenum pname, GLint value) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramParameteri); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2266,19 +3397,31 @@ void GL_APIENTRY GL_ReadBuffer(GLenum src) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadBuffer, "context = %d, src = %s", CID(context), - GLenumToString(GLESEnum::ReadBufferMode, src)); + ANGLE_UNSAFE_TODO(EVENT(context, GLReadBuffer, "context = %d, src = %s", CID(context), + GLenumToString(GLESEnum::ReadBufferMode, src))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadBuffer) && - ValidateReadBuffer(context, angle::EntryPoint::GLReadBuffer, src))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateReadBuffer(context, angle::EntryPoint::GLReadBuffer, src); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLReadBuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readBuffer(src); } @@ -2286,7 +3429,7 @@ void GL_APIENTRY GL_ReadBuffer(GLenum src) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadBuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2299,23 +3442,37 @@ void GL_APIENTRY GL_RenderbufferStorageMultisample(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRenderbufferStorageMultisample, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), samples, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO(EVENT( + context, GLRenderbufferStorageMultisample, + "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), samples, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRenderbufferStorageMultisample) && - ValidateRenderbufferStorageMultisample( - context, angle::EntryPoint::GLRenderbufferStorageMultisample, target, samples, - internalformat, width, height))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRenderbufferStorageMultisample( + context, angle::EntryPoint::GLRenderbufferStorageMultisample, target, samples, + internalformat, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, + angle::EntryPoint::GLRenderbufferStorageMultisample); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->renderbufferStorageMultisample(target, samples, internalformat, width, height); } @@ -2324,7 +3481,8 @@ void GL_APIENTRY GL_RenderbufferStorageMultisample(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLRenderbufferStorageMultisample); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2333,19 +3491,31 @@ void GL_APIENTRY GL_ResumeTransformFeedback() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLResumeTransformFeedback, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLResumeTransformFeedback, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLResumeTransformFeedback) && - ValidateResumeTransformFeedback(context, - angle::EntryPoint::GLResumeTransformFeedback))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateResumeTransformFeedback( + context, angle::EntryPoint::GLResumeTransformFeedback); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLResumeTransformFeedback); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->resumeTransformFeedback(); } @@ -2353,7 +3523,8 @@ void GL_APIENTRY GL_ResumeTransformFeedback() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLResumeTransformFeedback); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2362,18 +3533,34 @@ void GL_APIENTRY GL_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat para { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterf, "context = %d, sampler = %u, pname = %s, param = %f", - CID(context), sampler, GLenumToString(GLESEnum::SamplerParameterF, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterf, + "context = %d, sampler = %u, pname = %s, param = %f", CID(context), + sampler, GLenumToString(GLESEnum::SamplerParameterF, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterf(context, angle::EntryPoint::GLSamplerParameterf, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterf( + context, angle::EntryPoint::GLSamplerParameterf, samplerPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLSamplerParameterf); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterf(samplerPacked, pname, param); } @@ -2381,7 +3568,7 @@ void GL_APIENTRY GL_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat para } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameterf); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2390,19 +3577,35 @@ void GL_APIENTRY GL_SamplerParameterfv(GLuint sampler, GLenum pname, const GLflo { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterfv, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterF, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterfv, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterF, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterfv(context, angle::EntryPoint::GLSamplerParameterfv, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterfv( + context, angle::EntryPoint::GLSamplerParameterfv, samplerPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLSamplerParameterfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterfv(samplerPacked, pname, param); } @@ -2410,7 +3613,7 @@ void GL_APIENTRY GL_SamplerParameterfv(GLuint sampler, GLenum pname, const GLflo } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameterfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2419,18 +3622,34 @@ void GL_APIENTRY GL_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameteri, "context = %d, sampler = %u, pname = %s, param = %d", - CID(context), sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameteri, + "context = %d, sampler = %u, pname = %s, param = %d", CID(context), + sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameteri(context, angle::EntryPoint::GLSamplerParameteri, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameteri( + context, angle::EntryPoint::GLSamplerParameteri, samplerPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLSamplerParameteri); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameteri(samplerPacked, pname, param); } @@ -2438,7 +3657,7 @@ void GL_APIENTRY GL_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameteri); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2447,19 +3666,35 @@ void GL_APIENTRY GL_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameteriv, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameteriv, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameteriv(context, angle::EntryPoint::GLSamplerParameteriv, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameteriv( + context, angle::EntryPoint::GLSamplerParameteriv, samplerPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLSamplerParameteriv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameteriv(samplerPacked, pname, param); } @@ -2467,7 +3702,7 @@ void GL_APIENTRY GL_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2485,26 +3720,39 @@ void GL_APIENTRY GL_TexImage3D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexImage3D, - "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, " - "depth = %d, border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, internalformat, - width, height, depth, border, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexImage3D, + "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = " + "%d, depth = %d, border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, internalformat, + width, height, depth, border, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexImage3D) && - ValidateTexImage3D(context, angle::EntryPoint::GLTexImage3D, targetPacked, level, - internalformat, width, height, depth, border, format, type, - pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexImage3D(context, angle::EntryPoint::GLTexImage3D, + targetPacked, level, internalformat, width, height, + depth, border, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLTexImage3D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texImage3D(targetPacked, level, internalformat, width, height, depth, border, format, type, pixels); @@ -2514,7 +3762,7 @@ void GL_APIENTRY GL_TexImage3D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexImage3D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2524,23 +3772,37 @@ GL_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei wi { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage2D, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexStorage2D, + "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage2D) && - ValidateTexStorage2D(context, angle::EntryPoint::GLTexStorage2D, targetPacked, levels, - internalformat, width, height))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateTexStorage2D(context, angle::EntryPoint::GLTexStorage2D, targetPacked, + levels, internalformat, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLTexStorage2D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage2D(targetPacked, levels, internalformat, width, height); } @@ -2549,7 +3811,7 @@ GL_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei wi } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorage2D); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2563,24 +3825,38 @@ void GL_APIENTRY GL_TexStorage3D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage3D, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, depth); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorage3D, + "context = %d, target = %s, levels = %d, internalformat = %s, width = " + "%d, height = %d, depth = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, depth)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage3D) && - ValidateTexStorage3D(context, angle::EntryPoint::GLTexStorage3D, targetPacked, levels, - internalformat, width, height, depth))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateTexStorage3D(context, angle::EntryPoint::GLTexStorage3D, targetPacked, + levels, internalformat, width, height, depth); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLTexStorage3D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage3D(targetPacked, levels, internalformat, width, height, depth); } @@ -2589,7 +3865,7 @@ void GL_APIENTRY GL_TexStorage3D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorage3D); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2608,26 +3884,39 @@ void GL_APIENTRY GL_TexSubImage3D(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexSubImage3D, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width " - "= %d, height = %d, depth = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - zoffset, width, height, depth, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexSubImage3D, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width = " + "%d, height = %d, depth = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, + zoffset, width, height, depth, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexSubImage3D) && - ValidateTexSubImage3D(context, angle::EntryPoint::GLTexSubImage3D, targetPacked, - level, xoffset, yoffset, zoffset, width, height, depth, format, - type, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexSubImage3D(context, angle::EntryPoint::GLTexSubImage3D, + targetPacked, level, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLTexSubImage3D); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texSubImage3D(targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); @@ -2637,7 +3926,7 @@ void GL_APIENTRY GL_TexSubImage3D(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexSubImage3D); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2649,24 +3938,37 @@ void GL_APIENTRY GL_TransformFeedbackVaryings(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTransformFeedbackVaryings, - "context = %d, program = %u, count = %d, varyings = 0x%016" PRIxPTR ", bufferMode = %s", - CID(context), program, count, (uintptr_t)varyings, - GLenumToString(GLESEnum::TransformFeedbackBufferMode, bufferMode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTransformFeedbackVaryings, + "context = %d, program = %u, count = %d, varyings = 0x%016" PRIxPTR + ", bufferMode = %s", + CID(context), program, count, (uintptr_t)varyings, + GLenumToString(GLESEnum::TransformFeedbackBufferMode, bufferMode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTransformFeedbackVaryings) && - ValidateTransformFeedbackVaryings(context, - angle::EntryPoint::GLTransformFeedbackVaryings, - programPacked, count, varyings, bufferMode))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTransformFeedbackVaryings( + context, angle::EntryPoint::GLTransformFeedbackVaryings, programPacked, count, + varyings, bufferMode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLTransformFeedbackVaryings); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->transformFeedbackVaryings(programPacked, count, varyings, bufferMode); } @@ -2675,7 +3977,8 @@ void GL_APIENTRY GL_TransformFeedbackVaryings(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTransformFeedbackVaryings); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2684,17 +3987,33 @@ void GL_APIENTRY GL_Uniform1ui(GLint location, GLuint v0) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform1ui, "context = %d, location = %d, v0 = %u", CID(context), location, - v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform1ui, "context = %d, location = %d, v0 = %u", + CID(context), location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniform1ui(context, angle::EntryPoint::GLUniform1ui, locationPacked, v0)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform1ui(context, angle::EntryPoint::GLUniform1ui, + locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform1ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform1ui(locationPacked, v0); } @@ -2702,7 +4021,7 @@ void GL_APIENTRY GL_Uniform1ui(GLint location, GLuint v0) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform1ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2711,18 +4030,34 @@ void GL_APIENTRY GL_Uniform1uiv(GLint location, GLsizei count, const GLuint *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform1uiv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform1uiv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform1uiv(context, angle::EntryPoint::GLUniform1uiv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform1uiv(context, angle::EntryPoint::GLUniform1uiv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform1uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform1uiv(locationPacked, count, value); } @@ -2730,7 +4065,7 @@ void GL_APIENTRY GL_Uniform1uiv(GLint location, GLsizei count, const GLuint *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform1uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2739,17 +4074,33 @@ void GL_APIENTRY GL_Uniform2ui(GLint location, GLuint v0, GLuint v1) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform2ui, "context = %d, location = %d, v0 = %u, v1 = %u", CID(context), - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform2ui, "context = %d, location = %d, v0 = %u, v1 = %u", + CID(context), location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniform2ui(context, angle::EntryPoint::GLUniform2ui, locationPacked, v0, v1)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform2ui(context, angle::EntryPoint::GLUniform2ui, + locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform2ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform2ui(locationPacked, v0, v1); } @@ -2757,7 +4108,7 @@ void GL_APIENTRY GL_Uniform2ui(GLint location, GLuint v0, GLuint v1) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform2ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2766,18 +4117,34 @@ void GL_APIENTRY GL_Uniform2uiv(GLint location, GLsizei count, const GLuint *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform2uiv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform2uiv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform2uiv(context, angle::EntryPoint::GLUniform2uiv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform2uiv(context, angle::EntryPoint::GLUniform2uiv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform2uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform2uiv(locationPacked, count, value); } @@ -2785,7 +4152,7 @@ void GL_APIENTRY GL_Uniform2uiv(GLint location, GLsizei count, const GLuint *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform2uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2794,17 +4161,34 @@ void GL_APIENTRY GL_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform3ui, "context = %d, location = %d, v0 = %u, v1 = %u, v2 = %u", - CID(context), location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform3ui, + "context = %d, location = %d, v0 = %u, v1 = %u, v2 = %u", CID(context), + location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform3ui(context, angle::EntryPoint::GLUniform3ui, - locationPacked, v0, v1, v2)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform3ui(context, angle::EntryPoint::GLUniform3ui, + locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform3ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform3ui(locationPacked, v0, v1, v2); } @@ -2812,7 +4196,7 @@ void GL_APIENTRY GL_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform3ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2821,18 +4205,34 @@ void GL_APIENTRY GL_Uniform3uiv(GLint location, GLsizei count, const GLuint *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform3uiv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform3uiv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform3uiv(context, angle::EntryPoint::GLUniform3uiv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform3uiv(context, angle::EntryPoint::GLUniform3uiv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform3uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform3uiv(locationPacked, count, value); } @@ -2840,7 +4240,7 @@ void GL_APIENTRY GL_Uniform3uiv(GLint location, GLsizei count, const GLuint *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform3uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2849,17 +4249,34 @@ void GL_APIENTRY GL_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform4ui, "context = %d, location = %d, v0 = %u, v1 = %u, v2 = %u, v3 = %u", - CID(context), location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform4ui, + "context = %d, location = %d, v0 = %u, v1 = %u, v2 = %u, v3 = %u", + CID(context), location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform4ui(context, angle::EntryPoint::GLUniform4ui, - locationPacked, v0, v1, v2, v3)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform4ui(context, angle::EntryPoint::GLUniform4ui, + locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform4ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform4ui(locationPacked, v0, v1, v2, v3); } @@ -2867,7 +4284,7 @@ void GL_APIENTRY GL_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform4ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2876,18 +4293,34 @@ void GL_APIENTRY GL_Uniform4uiv(GLint location, GLsizei count, const GLuint *val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniform4uiv, - "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context), - location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLUniform4uiv, + "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = (context->skipValidation() || - ValidateUniform4uiv(context, angle::EntryPoint::GLUniform4uiv, - locationPacked, count, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniform4uiv(context, angle::EntryPoint::GLUniform4uiv, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniform4uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniform4uiv(locationPacked, count, value); } @@ -2895,7 +4328,7 @@ void GL_APIENTRY GL_Uniform4uiv(GLint location, GLsizei count, const GLuint *val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniform4uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2906,20 +4339,37 @@ void GL_APIENTRY GL_UniformBlockBinding(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformBlockBinding, - "context = %d, program = %u, uniformBlockIndex = %u, uniformBlockBinding = %u", - CID(context), program, uniformBlockIndex, uniformBlockBinding); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformBlockBinding, + "context = %d, program = %u, uniformBlockIndex = %u, uniformBlockBinding = %u", + CID(context), program, uniformBlockIndex, uniformBlockBinding)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformBlockIndex uniformBlockIndexPacked = PackParam(uniformBlockIndex); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateUniformBlockBinding( - context, angle::EntryPoint::GLUniformBlockBinding, programPacked, - uniformBlockIndexPacked, uniformBlockBinding)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUniformBlockBinding( + context, angle::EntryPoint::GLUniformBlockBinding, programPacked, + uniformBlockIndexPacked, uniformBlockBinding); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformBlockBinding); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformBlockBinding(programPacked, uniformBlockIndexPacked, uniformBlockBinding); @@ -2929,7 +4379,7 @@ void GL_APIENTRY GL_UniformBlockBinding(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformBlockBinding); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2941,19 +4391,36 @@ void GL_APIENTRY GL_UniformMatrix2x3fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix2x3fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix2x3fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniformMatrix2x3fv(context, angle::EntryPoint::GLUniformMatrix2x3fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix2x3fv(context, angle::EntryPoint::GLUniformMatrix2x3fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformMatrix2x3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix2x3fv(locationPacked, count, transpose, value); } @@ -2962,7 +4429,7 @@ void GL_APIENTRY GL_UniformMatrix2x3fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix2x3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2974,19 +4441,36 @@ void GL_APIENTRY GL_UniformMatrix2x4fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix2x4fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix2x4fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniformMatrix2x4fv(context, angle::EntryPoint::GLUniformMatrix2x4fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix2x4fv(context, angle::EntryPoint::GLUniformMatrix2x4fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformMatrix2x4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix2x4fv(locationPacked, count, transpose, value); } @@ -2995,7 +4479,7 @@ void GL_APIENTRY GL_UniformMatrix2x4fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix2x4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3007,19 +4491,36 @@ void GL_APIENTRY GL_UniformMatrix3x2fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix3x2fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix3x2fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniformMatrix3x2fv(context, angle::EntryPoint::GLUniformMatrix3x2fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix3x2fv(context, angle::EntryPoint::GLUniformMatrix3x2fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformMatrix3x2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix3x2fv(locationPacked, count, transpose, value); } @@ -3028,7 +4529,7 @@ void GL_APIENTRY GL_UniformMatrix3x2fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix3x2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3040,19 +4541,36 @@ void GL_APIENTRY GL_UniformMatrix3x4fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix3x4fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix3x4fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniformMatrix3x4fv(context, angle::EntryPoint::GLUniformMatrix3x4fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix3x4fv(context, angle::EntryPoint::GLUniformMatrix3x4fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformMatrix3x4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix3x4fv(locationPacked, count, transpose, value); } @@ -3061,7 +4579,7 @@ void GL_APIENTRY GL_UniformMatrix3x4fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix3x4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3073,19 +4591,36 @@ void GL_APIENTRY GL_UniformMatrix4x2fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix4x2fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix4x2fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniformMatrix4x2fv(context, angle::EntryPoint::GLUniformMatrix4x2fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix4x2fv(context, angle::EntryPoint::GLUniformMatrix4x2fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformMatrix4x2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix4x2fv(locationPacked, count, transpose, value); } @@ -3094,7 +4629,7 @@ void GL_APIENTRY GL_UniformMatrix4x2fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix4x2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3106,19 +4641,36 @@ void GL_APIENTRY GL_UniformMatrix4x3fv(GLint location, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUniformMatrix4x3fv, - "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", - CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUniformMatrix4x3fv, + "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "", + CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { UniformLocation locationPacked = PackParam(location); - bool isCallValid = - (context->skipValidation() || - ValidateUniformMatrix4x3fv(context, angle::EntryPoint::GLUniformMatrix4x3fv, - locationPacked, count, transpose, value)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUniformMatrix4x3fv(context, angle::EntryPoint::GLUniformMatrix4x3fv, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUniformMatrix4x3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->uniformMatrix4x3fv(locationPacked, count, transpose, value); } @@ -3127,7 +4679,7 @@ void GL_APIENTRY GL_UniformMatrix4x3fv(GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUniformMatrix4x3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3136,18 +4688,34 @@ GLboolean GL_APIENTRY GL_UnmapBuffer(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUnmapBuffer, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLUnmapBuffer, "context = %d, target = %s", CID(context), + GLenumToString(GLESEnum::BufferTargetARB, target))); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateUnmapBuffer(context, angle::EntryPoint::GLUnmapBuffer, targetPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUnmapBuffer(context, angle::EntryPoint::GLUnmapBuffer, targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLUnmapBuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->unmapBuffer(targetPacked); } @@ -3159,7 +4727,7 @@ GLboolean GL_APIENTRY GL_UnmapBuffer(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUnmapBuffer); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -3170,24 +4738,43 @@ void GL_APIENTRY GL_VertexAttribDivisor(GLuint index, GLuint divisor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribDivisor, "context = %d, index = %u, divisor = %u", CID(context), - index, divisor); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribDivisor, + "context = %d, index = %u, divisor = %u", CID(context), index, + divisor)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateVertexAttribDivisor( - context, angle::EntryPoint::GLVertexAttribDivisor, index, divisor)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->vertexAttribDivisor(index, divisor); + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribDivisor( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribDivisor, index, divisor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLVertexAttribDivisor); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateVertexAttribDivisor(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index, + divisor); } ANGLE_CAPTURE_GL(VertexAttribDivisor, isCallValid, context, index, divisor); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribDivisor); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3196,17 +4783,33 @@ void GL_APIENTRY GL_VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLi { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribI4i, "context = %d, index = %u, x = %d, y = %d, z = %d, w = %d", - CID(context), index, x, y, z, w); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribI4i, + "context = %d, index = %u, x = %d, y = %d, z = %d, w = %d", + CID(context), index, x, y, z, w)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribI4i(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttribI4i, index, x, y, z, w)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribI4i( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribI4i, index, x, y, z, w); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLVertexAttribI4i); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttribI4i(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, x, y, z, @@ -3216,7 +4819,7 @@ void GL_APIENTRY GL_VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLi } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribI4i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3225,17 +4828,33 @@ void GL_APIENTRY GL_VertexAttribI4iv(GLuint index, const GLint *v) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribI4iv, "context = %d, index = %u, v = 0x%016" PRIxPTR "", - CID(context), index, (uintptr_t)v); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribI4iv, + "context = %d, index = %u, v = 0x%016" PRIxPTR "", CID(context), index, + (uintptr_t)v)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribI4iv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttribI4iv, index, v)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribI4iv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribI4iv, index, v); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLVertexAttribI4iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttribI4iv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, v); @@ -3244,7 +4863,7 @@ void GL_APIENTRY GL_VertexAttribI4iv(GLuint index, const GLint *v) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribI4iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3253,17 +4872,33 @@ void GL_APIENTRY GL_VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribI4ui, "context = %d, index = %u, x = %u, y = %u, z = %u, w = %u", - CID(context), index, x, y, z, w); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribI4ui, + "context = %d, index = %u, x = %u, y = %u, z = %u, w = %u", + CID(context), index, x, y, z, w)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribI4ui(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttribI4ui, index, x, y, z, w)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribI4ui( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribI4ui, index, x, y, z, w); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLVertexAttribI4ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttribI4ui(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, x, y, z, @@ -3273,7 +4908,7 @@ void GL_APIENTRY GL_VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribI4ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3282,17 +4917,33 @@ void GL_APIENTRY GL_VertexAttribI4uiv(GLuint index, const GLuint *v) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribI4uiv, "context = %d, index = %u, v = 0x%016" PRIxPTR "", - CID(context), index, (uintptr_t)v); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribI4uiv, + "context = %d, index = %u, v = 0x%016" PRIxPTR "", CID(context), index, + (uintptr_t)v)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribI4uiv(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexAttribI4uiv, index, v)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribI4uiv( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribI4uiv, index, v); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLVertexAttribI4uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateVertexAttribI4uiv(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, v); @@ -3301,7 +4952,7 @@ void GL_APIENTRY GL_VertexAttribI4uiv(GLuint index, const GLuint *v) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribI4uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3311,21 +4962,37 @@ GL_VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, c { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribIPointer, - "context = %d, index = %u, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR - "", - CID(context), index, size, GLenumToString(GLESEnum::VertexAttribIType, type), stride, - (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT( + context, GLVertexAttribIPointer, + "context = %d, index = %u, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), index, size, GLenumToString(GLESEnum::VertexAttribIType, type), stride, + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribIPointer(context, angle::EntryPoint::GLVertexAttribIPointer, index, - size, typePacked, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateVertexAttribIPointer(context, angle::EntryPoint::GLVertexAttribIPointer, + index, size, typePacked, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLVertexAttribIPointer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->vertexAttribIPointer(index, size, typePacked, stride, pointer); } @@ -3334,7 +5001,7 @@ GL_VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, c } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribIPointer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3343,23 +5010,36 @@ void GL_APIENTRY GL_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLWaitSync, "context = %d, sync = 0x%016" PRIxPTR ", flags = %s, timeout = %llu", - CID(context), (uintptr_t)sync, - GLbitfieldToString(GLESEnum::SyncBehaviorFlags, flags).c_str(), - static_cast(timeout)); + ANGLE_UNSAFE_TODO(EVENT(context, GLWaitSync, + "context = %d, sync = 0x%016" PRIxPTR ", flags = %s, timeout = %llu", + CID(context), (uintptr_t)sync, + GLbitfieldToString(GLESEnum::SyncBehaviorFlags, flags).c_str(), + static_cast(timeout))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SyncID syncPacked = PackParam(sync); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLWaitSync) && - ValidateWaitSync(context, angle::EntryPoint::GLWaitSync, syncPacked, flags, - timeout))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_0)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateWaitSync(context, angle::EntryPoint::GLWaitSync, syncPacked, + flags, timeout); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES30(context, angle::EntryPoint::GLWaitSync); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->waitSync(syncPacked, flags, timeout); } @@ -3367,7 +5047,7 @@ void GL_APIENTRY GL_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLWaitSync); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } diff --git a/src/libGLESv2/entry_points_gles_3_1_autogen.cpp b/src/libGLESv2/entry_points_gles_3_1_autogen.cpp index 2b5c92372af..7bd9df412b0 100644 --- a/src/libGLESv2/entry_points_gles_3_1_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_3_1_autogen.cpp @@ -28,22 +28,36 @@ void GL_APIENTRY GL_ActiveShaderProgram(GLuint pipeline, GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLActiveShaderProgram, "context = %d, pipeline = %u, program = %u", CID(context), - pipeline, program); + ANGLE_UNSAFE_TODO(EVENT(context, GLActiveShaderProgram, + "context = %d, pipeline = %u, program = %u", CID(context), pipeline, + program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLActiveShaderProgram) && - ValidateActiveShaderProgram(context, angle::EntryPoint::GLActiveShaderProgram, - pipelinePacked, programPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateActiveShaderProgram(context, angle::EntryPoint::GLActiveShaderProgram, + pipelinePacked, programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLActiveShaderProgram); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->activeShaderProgram(pipelinePacked, programPacked); } @@ -51,7 +65,7 @@ void GL_APIENTRY GL_ActiveShaderProgram(GLuint pipeline, GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLActiveShaderProgram); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -66,25 +80,38 @@ void GL_APIENTRY GL_BindImageTexture(GLuint unit, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindImageTexture, - "context = %d, unit = %u, texture = %u, level = %d, layered = %s, layer = %d, access = " - "%s, format = %s", - CID(context), unit, texture, level, GLbooleanToString(layered), layer, - GLenumToString(GLESEnum::BufferAccessARB, access), - GLenumToString(GLESEnum::InternalFormat, format)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindImageTexture, + "context = %d, unit = %u, texture = %u, level = %d, layered = %s, " + "layer = %d, access = %s, format = %s", + CID(context), unit, texture, level, GLbooleanToString(layered), layer, + GLenumToString(GLESEnum::BufferAccessARB, access), + GLenumToString(GLESEnum::InternalFormat, format))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindImageTexture) && - ValidateBindImageTexture(context, angle::EntryPoint::GLBindImageTexture, unit, - texturePacked, level, layered, layer, access, format))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateBindImageTexture(context, angle::EntryPoint::GLBindImageTexture, unit, + texturePacked, level, layered, layer, access, format); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLBindImageTexture); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindImageTexture(unit, texturePacked, level, layered, layer, access, format); } @@ -93,7 +120,7 @@ void GL_APIENTRY GL_BindImageTexture(GLuint unit, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindImageTexture); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -102,20 +129,33 @@ void GL_APIENTRY GL_BindProgramPipeline(GLuint pipeline) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindProgramPipeline, "context = %d, pipeline = %u", CID(context), pipeline); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindProgramPipeline, "context = %d, pipeline = %u", + CID(context), pipeline)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindProgramPipeline) && - ValidateBindProgramPipeline(context, angle::EntryPoint::GLBindProgramPipeline, - pipelinePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindProgramPipeline( + context, angle::EntryPoint::GLBindProgramPipeline, pipelinePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLBindProgramPipeline); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindProgramPipeline(pipelinePacked); } @@ -123,7 +163,7 @@ void GL_APIENTRY GL_BindProgramPipeline(GLuint pipeline) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindProgramPipeline); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -135,22 +175,36 @@ void GL_APIENTRY GL_BindVertexBuffer(GLuint bindingindex, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindVertexBuffer, - "context = %d, bindingindex = %u, buffer = %u, offset = %llu, stride = %d", CID(context), - bindingindex, buffer, static_cast(offset), stride); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBindVertexBuffer, + "context = %d, bindingindex = %u, buffer = %u, offset = %llu, stride = %d", + CID(context), bindingindex, buffer, static_cast(offset), stride)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindVertexBuffer) && - ValidateBindVertexBuffer(context, angle::EntryPoint::GLBindVertexBuffer, bindingindex, - bufferPacked, offset, stride))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateBindVertexBuffer(context, angle::EntryPoint::GLBindVertexBuffer, + bindingindex, bufferPacked, offset, stride); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLBindVertexBuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindVertexBuffer(bindingindex, bufferPacked, offset, stride); } @@ -159,7 +213,7 @@ void GL_APIENTRY GL_BindVertexBuffer(GLuint bindingindex, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindVertexBuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -168,23 +222,36 @@ GLuint GL_APIENTRY GL_CreateShaderProgramv(GLenum type, GLsizei count, const GLc { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCreateShaderProgramv, - "context = %d, type = %s, count = %d, strings = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::ShaderType, type), count, (uintptr_t)strings); + ANGLE_UNSAFE_TODO(EVENT(context, GLCreateShaderProgramv, + "context = %d, type = %s, count = %d, strings = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ShaderType, type), count, + (uintptr_t)strings)); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCreateShaderProgramv) && - ValidateCreateShaderProgramv(context, angle::EntryPoint::GLCreateShaderProgramv, - typePacked, count, strings))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCreateShaderProgramv( + context, angle::EntryPoint::GLCreateShaderProgramv, typePacked, count, strings); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLCreateShaderProgramv); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->createShaderProgramv(typePacked, count, strings); } @@ -198,7 +265,7 @@ GLuint GL_APIENTRY GL_CreateShaderProgramv(GLenum type, GLsizei count, const GLc } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCreateShaderProgramv); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -209,18 +276,34 @@ void GL_APIENTRY GL_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteProgramPipelines, "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)pipelines); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteProgramPipelines, + "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)pipelines)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const ProgramPipelineID *pipelinesPacked = PackParam(pipelines); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteProgramPipelines(context, angle::EntryPoint::GLDeleteProgramPipelines, n, - pipelinesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteProgramPipelines( + context, angle::EntryPoint::GLDeleteProgramPipelines, n, pipelinesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLDeleteProgramPipelines); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteProgramPipelines(n, pipelinesPacked); } @@ -228,7 +311,7 @@ void GL_APIENTRY GL_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteProgramPipelines); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -237,21 +320,33 @@ void GL_APIENTRY GL_DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDispatchCompute, - "context = %d, num_groups_x = %u, num_groups_y = %u, num_groups_z = %u", CID(context), - num_groups_x, num_groups_y, num_groups_z); + ANGLE_UNSAFE_TODO(EVENT(context, GLDispatchCompute, + "context = %d, num_groups_x = %u, num_groups_y = %u, num_groups_z = %u", + CID(context), num_groups_x, num_groups_y, num_groups_z)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDispatchCompute) && - ValidateDispatchCompute(context, angle::EntryPoint::GLDispatchCompute, num_groups_x, - num_groups_y, num_groups_z))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDispatchCompute(context, angle::EntryPoint::GLDispatchCompute, + num_groups_x, num_groups_y, num_groups_z); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLDispatchCompute); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->dispatchCompute(num_groups_x, num_groups_y, num_groups_z); } @@ -260,7 +355,7 @@ void GL_APIENTRY GL_DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDispatchCompute); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -269,16 +364,32 @@ void GL_APIENTRY GL_DispatchComputeIndirect(GLintptr indirect) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDispatchComputeIndirect, "context = %d, indirect = %llu", CID(context), - static_cast(indirect)); + ANGLE_UNSAFE_TODO(EVENT(context, GLDispatchComputeIndirect, "context = %d, indirect = %llu", + CID(context), static_cast(indirect))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDispatchComputeIndirect( - context, angle::EntryPoint::GLDispatchComputeIndirect, indirect)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDispatchComputeIndirect( + context, angle::EntryPoint::GLDispatchComputeIndirect, indirect); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLDispatchComputeIndirect); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->dispatchComputeIndirect(indirect); } @@ -286,7 +397,8 @@ void GL_APIENTRY GL_DispatchComputeIndirect(GLintptr indirect) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDispatchComputeIndirect); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -295,18 +407,34 @@ void GL_APIENTRY GL_DrawArraysIndirect(GLenum mode, const void *indirect) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArraysIndirect, "context = %d, mode = %s, indirect = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)indirect); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawArraysIndirect, + "context = %d, mode = %s, indirect = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)indirect)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawArraysIndirect(context, angle::EntryPoint::GLDrawArraysIndirect, - modePacked, indirect)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawArraysIndirect( + context, angle::EntryPoint::GLDrawArraysIndirect, modePacked, indirect); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLDrawArraysIndirect); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawArraysIndirect(modePacked, indirect); } @@ -314,7 +442,7 @@ void GL_APIENTRY GL_DrawArraysIndirect(GLenum mode, const void *indirect) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawArraysIndirect); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -323,21 +451,37 @@ void GL_APIENTRY GL_DrawElementsIndirect(GLenum mode, GLenum type, const void *i { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsIndirect, - "context = %d, mode = %s, type = %s, indirect = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::PrimitiveType, mode), - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indirect); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawElementsIndirect, + "context = %d, mode = %s, type = %s, indirect = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indirect)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawElementsIndirect(context, angle::EntryPoint::GLDrawElementsIndirect, - modePacked, typePacked, indirect)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawElementsIndirect(context, angle::EntryPoint::GLDrawElementsIndirect, + modePacked, typePacked, indirect); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLDrawElementsIndirect); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsIndirect(modePacked, typePacked, indirect); } @@ -346,7 +490,7 @@ void GL_APIENTRY GL_DrawElementsIndirect(GLenum mode, GLenum type, const void *i } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawElementsIndirect); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -355,18 +499,38 @@ void GL_APIENTRY GL_FramebufferParameteri(GLenum target, GLenum pname, GLint par { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferParameteri, "context = %d, target = %s, pname = %s, param = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferParameterName, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferParameteri, + "context = %d, target = %s, pname = %s, param = %d", CID(context), + GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferParameterName, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferParameteri(context, angle::EntryPoint::GLFramebufferParameteri, - target, pname, param)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferParameteri( + context, angle::EntryPoint::GLFramebufferParameteri, target, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLFramebufferParameteri); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferParameteri(target, pname, param); } @@ -374,7 +538,7 @@ void GL_APIENTRY GL_FramebufferParameteri(GLenum target, GLenum pname, GLint par } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFramebufferParameteri); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -383,18 +547,34 @@ void GL_APIENTRY GL_GenProgramPipelines(GLsizei n, GLuint *pipelines) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenProgramPipelines, "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)pipelines); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenProgramPipelines, + "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)pipelines)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID *pipelinesPacked = PackParam(pipelines); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenProgramPipelines(context, angle::EntryPoint::GLGenProgramPipelines, n, - pipelinesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenProgramPipelines( + context, angle::EntryPoint::GLGenProgramPipelines, n, pipelinesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGenProgramPipelines); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genProgramPipelines(n, pipelinesPacked); } @@ -402,7 +582,7 @@ void GL_APIENTRY GL_GenProgramPipelines(GLsizei n, GLuint *pipelines) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenProgramPipelines); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -411,17 +591,33 @@ void GL_APIENTRY GL_GetBooleani_v(GLenum target, GLuint index, GLboolean *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBooleani_v, - "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), index, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetBooleani_v, "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), index, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetBooleani_v(context, angle::EntryPoint::GLGetBooleani_v, - target, index, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBooleani_v(context, angle::EntryPoint::GLGetBooleani_v, + target, index, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetBooleani_v); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBooleani_v(target, index, data); } @@ -429,7 +625,7 @@ void GL_APIENTRY GL_GetBooleani_v(GLenum target, GLuint index, GLboolean *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBooleani_v); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -438,19 +634,35 @@ void GL_APIENTRY GL_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferParameteriv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFramebufferParameteriv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferParameteriv( - context, angle::EntryPoint::GLGetFramebufferParameteriv, target, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferParameteriv( + context, angle::EntryPoint::GLGetFramebufferParameteriv, target, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetFramebufferParameteriv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferParameteriv(target, pname, params); } @@ -458,7 +670,8 @@ void GL_APIENTRY GL_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -467,17 +680,34 @@ void GL_APIENTRY GL_GetMultisamplefv(GLenum pname, GLuint index, GLfloat *val) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetMultisamplefv, - "context = %d, pname = %s, index = %u, val = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::AllEnums, pname), index, (uintptr_t)val); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetMultisamplefv, + "context = %d, pname = %s, index = %u, val = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), index, + (uintptr_t)val)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetMultisamplefv(context, angle::EntryPoint::GLGetMultisamplefv, - pname, index, val)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetMultisamplefv( + context, angle::EntryPoint::GLGetMultisamplefv, pname, index, val); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetMultisamplefv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getMultisamplefv(pname, index, val); } @@ -485,7 +715,7 @@ void GL_APIENTRY GL_GetMultisamplefv(GLenum pname, GLuint index, GLfloat *val) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetMultisamplefv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -497,21 +727,37 @@ void GL_APIENTRY GL_GetProgramInterfaceiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramInterfaceiv, - "context = %d, program = %u, programInterface = %s, pname = %s, params = 0x%016" PRIxPTR - "", - CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), - GLenumToString(GLESEnum::ProgramInterfacePName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetProgramInterfaceiv, + "context = %d, program = %u, programInterface = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), + GLenumToString(GLESEnum::ProgramInterfacePName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramInterfaceiv(context, angle::EntryPoint::GLGetProgramInterfaceiv, - programPacked, programInterface, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramInterfaceiv( + context, angle::EntryPoint::GLGetProgramInterfaceiv, programPacked, + programInterface, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramInterfaceiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramInterfaceiv(programPacked, programInterface, pname, params); } @@ -520,7 +766,7 @@ void GL_APIENTRY GL_GetProgramInterfaceiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramInterfaceiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -532,20 +778,37 @@ void GL_APIENTRY GL_GetProgramPipelineInfoLog(GLuint pipeline, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramPipelineInfoLog, - "context = %d, pipeline = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", infoLog = 0x%016" PRIxPTR "", - CID(context), pipeline, bufSize, (uintptr_t)length, (uintptr_t)infoLog); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetProgramPipelineInfoLog, + "context = %d, pipeline = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", infoLog = 0x%016" PRIxPTR "", + CID(context), pipeline, bufSize, (uintptr_t)length, + (uintptr_t)infoLog)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramPipelineInfoLog( - context, angle::EntryPoint::GLGetProgramPipelineInfoLog, - pipelinePacked, bufSize, length, infoLog)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramPipelineInfoLog( + context, angle::EntryPoint::GLGetProgramPipelineInfoLog, pipelinePacked, + bufSize, length, infoLog); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramPipelineInfoLog); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramPipelineInfoLog(pipelinePacked, bufSize, length, infoLog); } @@ -554,7 +817,8 @@ void GL_APIENTRY GL_GetProgramPipelineInfoLog(GLuint pipeline, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramPipelineInfoLog); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -563,19 +827,36 @@ void GL_APIENTRY GL_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *p { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramPipelineiv, - "context = %d, pipeline = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - pipeline, GLenumToString(GLESEnum::PipelineParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetProgramPipelineiv, + "context = %d, pipeline = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + pipeline, GLenumToString(GLESEnum::PipelineParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramPipelineiv(context, angle::EntryPoint::GLGetProgramPipelineiv, - pipelinePacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetProgramPipelineiv(context, angle::EntryPoint::GLGetProgramPipelineiv, + pipelinePacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramPipelineiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramPipelineiv(pipelinePacked, pname, params); } @@ -583,7 +864,7 @@ void GL_APIENTRY GL_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *p } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramPipelineiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -594,21 +875,37 @@ GLuint GL_APIENTRY GL_GetProgramResourceIndex(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramResourceIndex, - "context = %d, program = %u, programInterface = %s, name = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), - (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetProgramResourceIndex, + "context = %d, program = %u, programInterface = %s, name = 0x%016" PRIxPTR "", CID(context), + program, GLenumToString(GLESEnum::ProgramInterface, programInterface), (uintptr_t)name)); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramResourceIndex(context, angle::EntryPoint::GLGetProgramResourceIndex, - programPacked, programInterface, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramResourceIndex( + context, angle::EntryPoint::GLGetProgramResourceIndex, programPacked, + programInterface, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramResourceIndex); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getProgramResourceIndex(programPacked, programInterface, name); } @@ -622,7 +919,8 @@ GLuint GL_APIENTRY GL_GetProgramResourceIndex(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramResourceIndex); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -635,21 +933,37 @@ GLint GL_APIENTRY GL_GetProgramResourceLocation(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramResourceLocation, - "context = %d, program = %u, programInterface = %s, name = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), - (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetProgramResourceLocation, + "context = %d, program = %u, programInterface = %s, name = 0x%016" PRIxPTR "", CID(context), + program, GLenumToString(GLESEnum::ProgramInterface, programInterface), (uintptr_t)name)); GLint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramResourceLocation( - context, angle::EntryPoint::GLGetProgramResourceLocation, - programPacked, programInterface, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramResourceLocation( + context, angle::EntryPoint::GLGetProgramResourceLocation, programPacked, + programInterface, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramResourceLocation); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getProgramResourceLocation(programPacked, programInterface, name); @@ -664,7 +978,8 @@ GLint GL_APIENTRY GL_GetProgramResourceLocation(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramResourceLocation); returnValue = GetDefaultReturnValue(); } @@ -681,21 +996,38 @@ void GL_APIENTRY GL_GetProgramResourceName(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramResourceName, - "context = %d, program = %u, programInterface = %s, index = %u, bufSize = %d, length = " - "0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), - index, bufSize, (uintptr_t)length, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetProgramResourceName, + "context = %d, program = %u, programInterface = %s, index = %u, " + "bufSize = %d, length = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "", + CID(context), program, + GLenumToString(GLESEnum::ProgramInterface, programInterface), index, + bufSize, (uintptr_t)length, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramResourceName( - context, angle::EntryPoint::GLGetProgramResourceName, programPacked, - programInterface, index, bufSize, length, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramResourceName( + context, angle::EntryPoint::GLGetProgramResourceName, programPacked, + programInterface, index, bufSize, length, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramResourceName); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramResourceName(programPacked, programInterface, index, bufSize, length, name); @@ -705,7 +1037,7 @@ void GL_APIENTRY GL_GetProgramResourceName(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramResourceName); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -721,21 +1053,38 @@ void GL_APIENTRY GL_GetProgramResourceiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramResourceiv, - "context = %d, program = %u, programInterface = %s, index = %u, propCount = %d, props = " - "0x%016" PRIxPTR ", count = %d, length = 0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), - index, propCount, (uintptr_t)props, count, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetProgramResourceiv, + "context = %d, program = %u, programInterface = %s, index = %u, propCount = %d, props = " + "0x%016" PRIxPTR ", count = %d, length = 0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", + CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), index, + propCount, (uintptr_t)props, count, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramResourceiv( - context, angle::EntryPoint::GLGetProgramResourceiv, programPacked, - programInterface, index, propCount, props, count, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramResourceiv( + context, angle::EntryPoint::GLGetProgramResourceiv, programPacked, + programInterface, index, propCount, props, count, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetProgramResourceiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramResourceiv(programPacked, programInterface, index, propCount, props, count, length, params); @@ -745,7 +1094,7 @@ void GL_APIENTRY GL_GetProgramResourceiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramResourceiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -757,20 +1106,37 @@ void GL_APIENTRY GL_GetTexLevelParameterfv(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexLevelParameterfv, - "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetTexLevelParameterfv, + "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexLevelParameterfv(context, angle::EntryPoint::GLGetTexLevelParameterfv, - targetPacked, level, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexLevelParameterfv( + context, angle::EntryPoint::GLGetTexLevelParameterfv, targetPacked, level, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetTexLevelParameterfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexLevelParameterfv(targetPacked, level, pname, params); } @@ -779,7 +1145,7 @@ void GL_APIENTRY GL_GetTexLevelParameterfv(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexLevelParameterfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -788,20 +1154,37 @@ void GL_APIENTRY GL_GetTexLevelParameteriv(GLenum target, GLint level, GLenum pn { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexLevelParameteriv, - "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetTexLevelParameteriv, + "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexLevelParameteriv(context, angle::EntryPoint::GLGetTexLevelParameteriv, - targetPacked, level, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexLevelParameteriv( + context, angle::EntryPoint::GLGetTexLevelParameteriv, targetPacked, level, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLGetTexLevelParameteriv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexLevelParameteriv(targetPacked, level, pname, params); } @@ -810,7 +1193,7 @@ void GL_APIENTRY GL_GetTexLevelParameteriv(GLenum target, GLint level, GLenum pn } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexLevelParameteriv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -819,17 +1202,34 @@ GLboolean GL_APIENTRY GL_IsProgramPipeline(GLuint pipeline) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsProgramPipeline, "context = %d, pipeline = %u", CID(context), pipeline); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsProgramPipeline, "context = %d, pipeline = %u", CID(context), pipeline)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsProgramPipeline( - context, angle::EntryPoint::GLIsProgramPipeline, pipelinePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsProgramPipeline( + context, angle::EntryPoint::GLIsProgramPipeline, pipelinePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLIsProgramPipeline); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isProgramPipeline(pipelinePacked); } @@ -842,7 +1242,7 @@ GLboolean GL_APIENTRY GL_IsProgramPipeline(GLuint pipeline) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsProgramPipeline); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -853,19 +1253,32 @@ void GL_APIENTRY GL_MemoryBarrier(GLbitfield barriers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMemoryBarrier, "context = %d, barriers = %s", CID(context), - GLbitfieldToString(GLESEnum::MemoryBarrierMask, barriers).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLMemoryBarrier, "context = %d, barriers = %s", CID(context), + GLbitfieldToString(GLESEnum::MemoryBarrierMask, barriers).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMemoryBarrier) && - ValidateMemoryBarrier(context, angle::EntryPoint::GLMemoryBarrier, barriers))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateMemoryBarrier(context, angle::EntryPoint::GLMemoryBarrier, barriers); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLMemoryBarrier); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->memoryBarrier(barriers); } @@ -873,7 +1286,7 @@ void GL_APIENTRY GL_MemoryBarrier(GLbitfield barriers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMemoryBarrier); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -882,20 +1295,33 @@ void GL_APIENTRY GL_MemoryBarrierByRegion(GLbitfield barriers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMemoryBarrierByRegion, "context = %d, barriers = %s", CID(context), - GLbitfieldToString(GLESEnum::MemoryBarrierMask, barriers).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLMemoryBarrierByRegion, "context = %d, barriers = %s", + CID(context), + GLbitfieldToString(GLESEnum::MemoryBarrierMask, barriers).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMemoryBarrierByRegion) && - ValidateMemoryBarrierByRegion(context, angle::EntryPoint::GLMemoryBarrierByRegion, - barriers))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMemoryBarrierByRegion( + context, angle::EntryPoint::GLMemoryBarrierByRegion, barriers); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLMemoryBarrierByRegion); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->memoryBarrierByRegion(barriers); } @@ -903,7 +1329,7 @@ void GL_APIENTRY GL_MemoryBarrierByRegion(GLbitfield barriers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMemoryBarrierByRegion); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -912,22 +1338,36 @@ void GL_APIENTRY GL_ProgramUniform1f(GLuint program, GLint location, GLfloat v0) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1f, "context = %d, program = %u, location = %d, v0 = %f", - CID(context), program, location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform1f, + "context = %d, program = %u, location = %d, v0 = %f", CID(context), + program, location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1f) && - ValidateProgramUniform1f(context, angle::EntryPoint::GLProgramUniform1f, - programPacked, locationPacked, v0))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1f(context, angle::EntryPoint::GLProgramUniform1f, + programPacked, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform1f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1f(programPacked, locationPacked, v0); } @@ -935,7 +1375,7 @@ void GL_APIENTRY GL_ProgramUniform1f(GLuint program, GLint location, GLfloat v0) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -947,23 +1387,37 @@ void GL_APIENTRY GL_ProgramUniform1fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1fv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform1fv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1fv) && - ValidateProgramUniform1fv(context, angle::EntryPoint::GLProgramUniform1fv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1fv(context, angle::EntryPoint::GLProgramUniform1fv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform1fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1fv(programPacked, locationPacked, count, value); } @@ -972,7 +1426,7 @@ void GL_APIENTRY GL_ProgramUniform1fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -981,22 +1435,36 @@ void GL_APIENTRY GL_ProgramUniform1i(GLuint program, GLint location, GLint v0) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1i, "context = %d, program = %u, location = %d, v0 = %d", - CID(context), program, location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform1i, + "context = %d, program = %u, location = %d, v0 = %d", CID(context), + program, location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1i) && - ValidateProgramUniform1i(context, angle::EntryPoint::GLProgramUniform1i, - programPacked, locationPacked, v0))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1i(context, angle::EntryPoint::GLProgramUniform1i, + programPacked, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform1i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1i(programPacked, locationPacked, v0); } @@ -1004,7 +1472,7 @@ void GL_APIENTRY GL_ProgramUniform1i(GLuint program, GLint location, GLint v0) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1016,23 +1484,37 @@ void GL_APIENTRY GL_ProgramUniform1iv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1iv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform1iv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1iv) && - ValidateProgramUniform1iv(context, angle::EntryPoint::GLProgramUniform1iv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1iv(context, angle::EntryPoint::GLProgramUniform1iv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform1iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1iv(programPacked, locationPacked, count, value); } @@ -1041,7 +1523,7 @@ void GL_APIENTRY GL_ProgramUniform1iv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1050,22 +1532,36 @@ void GL_APIENTRY GL_ProgramUniform1ui(GLuint program, GLint location, GLuint v0) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1ui, "context = %d, program = %u, location = %d, v0 = %u", - CID(context), program, location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform1ui, + "context = %d, program = %u, location = %d, v0 = %u", CID(context), + program, location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1ui) && - ValidateProgramUniform1ui(context, angle::EntryPoint::GLProgramUniform1ui, - programPacked, locationPacked, v0))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1ui(context, angle::EntryPoint::GLProgramUniform1ui, + programPacked, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform1ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1ui(programPacked, locationPacked, v0); } @@ -1074,7 +1570,7 @@ void GL_APIENTRY GL_ProgramUniform1ui(GLuint program, GLint location, GLuint v0) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1086,23 +1582,37 @@ void GL_APIENTRY GL_ProgramUniform1uiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1uiv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform1uiv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1uiv) && - ValidateProgramUniform1uiv(context, angle::EntryPoint::GLProgramUniform1uiv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1uiv(context, angle::EntryPoint::GLProgramUniform1uiv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform1uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1uiv(programPacked, locationPacked, count, value); } @@ -1111,7 +1621,7 @@ void GL_APIENTRY GL_ProgramUniform1uiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1120,23 +1630,36 @@ void GL_APIENTRY GL_ProgramUniform2f(GLuint program, GLint location, GLfloat v0, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2f, - "context = %d, program = %u, location = %d, v0 = %f, v1 = %f", CID(context), program, - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform2f, + "context = %d, program = %u, location = %d, v0 = %f, v1 = %f", + CID(context), program, location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2f) && - ValidateProgramUniform2f(context, angle::EntryPoint::GLProgramUniform2f, - programPacked, locationPacked, v0, v1))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2f(context, angle::EntryPoint::GLProgramUniform2f, + programPacked, locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform2f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2f(programPacked, locationPacked, v0, v1); } @@ -1145,7 +1668,7 @@ void GL_APIENTRY GL_ProgramUniform2f(GLuint program, GLint location, GLfloat v0, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1157,23 +1680,37 @@ void GL_APIENTRY GL_ProgramUniform2fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2fv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform2fv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2fv) && - ValidateProgramUniform2fv(context, angle::EntryPoint::GLProgramUniform2fv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2fv(context, angle::EntryPoint::GLProgramUniform2fv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2fv(programPacked, locationPacked, count, value); } @@ -1182,7 +1719,7 @@ void GL_APIENTRY GL_ProgramUniform2fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1191,23 +1728,36 @@ void GL_APIENTRY GL_ProgramUniform2i(GLuint program, GLint location, GLint v0, G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2i, - "context = %d, program = %u, location = %d, v0 = %d, v1 = %d", CID(context), program, - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform2i, + "context = %d, program = %u, location = %d, v0 = %d, v1 = %d", + CID(context), program, location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2i) && - ValidateProgramUniform2i(context, angle::EntryPoint::GLProgramUniform2i, - programPacked, locationPacked, v0, v1))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2i(context, angle::EntryPoint::GLProgramUniform2i, + programPacked, locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform2i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2i(programPacked, locationPacked, v0, v1); } @@ -1216,7 +1766,7 @@ void GL_APIENTRY GL_ProgramUniform2i(GLuint program, GLint location, GLint v0, G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1228,23 +1778,37 @@ void GL_APIENTRY GL_ProgramUniform2iv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2iv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform2iv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2iv) && - ValidateProgramUniform2iv(context, angle::EntryPoint::GLProgramUniform2iv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2iv(context, angle::EntryPoint::GLProgramUniform2iv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform2iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2iv(programPacked, locationPacked, count, value); } @@ -1253,7 +1817,7 @@ void GL_APIENTRY GL_ProgramUniform2iv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1262,23 +1826,36 @@ void GL_APIENTRY GL_ProgramUniform2ui(GLuint program, GLint location, GLuint v0, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2ui, - "context = %d, program = %u, location = %d, v0 = %u, v1 = %u", CID(context), program, - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform2ui, + "context = %d, program = %u, location = %d, v0 = %u, v1 = %u", + CID(context), program, location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2ui) && - ValidateProgramUniform2ui(context, angle::EntryPoint::GLProgramUniform2ui, - programPacked, locationPacked, v0, v1))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2ui(context, angle::EntryPoint::GLProgramUniform2ui, + programPacked, locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform2ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2ui(programPacked, locationPacked, v0, v1); } @@ -1287,7 +1864,7 @@ void GL_APIENTRY GL_ProgramUniform2ui(GLuint program, GLint location, GLuint v0, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1299,23 +1876,37 @@ void GL_APIENTRY GL_ProgramUniform2uiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2uiv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform2uiv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2uiv) && - ValidateProgramUniform2uiv(context, angle::EntryPoint::GLProgramUniform2uiv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2uiv(context, angle::EntryPoint::GLProgramUniform2uiv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform2uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2uiv(programPacked, locationPacked, count, value); } @@ -1324,7 +1915,7 @@ void GL_APIENTRY GL_ProgramUniform2uiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1334,23 +1925,36 @@ GL_ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfl { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3f, - "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f", CID(context), - program, location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform3f, + "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f", + CID(context), program, location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3f) && - ValidateProgramUniform3f(context, angle::EntryPoint::GLProgramUniform3f, - programPacked, locationPacked, v0, v1, v2))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3f(context, angle::EntryPoint::GLProgramUniform3f, + programPacked, locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform3f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3f(programPacked, locationPacked, v0, v1, v2); } @@ -1359,7 +1963,7 @@ GL_ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfl } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1371,23 +1975,37 @@ void GL_APIENTRY GL_ProgramUniform3fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3fv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform3fv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3fv) && - ValidateProgramUniform3fv(context, angle::EntryPoint::GLProgramUniform3fv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3fv(context, angle::EntryPoint::GLProgramUniform3fv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3fv(programPacked, locationPacked, count, value); } @@ -1396,7 +2014,7 @@ void GL_APIENTRY GL_ProgramUniform3fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1405,23 +2023,36 @@ void GL_APIENTRY GL_ProgramUniform3i(GLuint program, GLint location, GLint v0, G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3i, - "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d", CID(context), - program, location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform3i, + "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d", + CID(context), program, location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3i) && - ValidateProgramUniform3i(context, angle::EntryPoint::GLProgramUniform3i, - programPacked, locationPacked, v0, v1, v2))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3i(context, angle::EntryPoint::GLProgramUniform3i, + programPacked, locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform3i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3i(programPacked, locationPacked, v0, v1, v2); } @@ -1430,7 +2061,7 @@ void GL_APIENTRY GL_ProgramUniform3i(GLuint program, GLint location, GLint v0, G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1442,23 +2073,37 @@ void GL_APIENTRY GL_ProgramUniform3iv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3iv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform3iv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3iv) && - ValidateProgramUniform3iv(context, angle::EntryPoint::GLProgramUniform3iv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3iv(context, angle::EntryPoint::GLProgramUniform3iv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform3iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3iv(programPacked, locationPacked, count, value); } @@ -1467,7 +2112,7 @@ void GL_APIENTRY GL_ProgramUniform3iv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1477,23 +2122,36 @@ GL_ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3ui, - "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u", CID(context), - program, location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform3ui, + "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u", + CID(context), program, location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3ui) && - ValidateProgramUniform3ui(context, angle::EntryPoint::GLProgramUniform3ui, - programPacked, locationPacked, v0, v1, v2))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3ui(context, angle::EntryPoint::GLProgramUniform3ui, + programPacked, locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform3ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3ui(programPacked, locationPacked, v0, v1, v2); } @@ -1502,7 +2160,7 @@ GL_ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1514,23 +2172,37 @@ void GL_APIENTRY GL_ProgramUniform3uiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3uiv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform3uiv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3uiv) && - ValidateProgramUniform3uiv(context, angle::EntryPoint::GLProgramUniform3uiv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3uiv(context, angle::EntryPoint::GLProgramUniform3uiv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform3uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3uiv(programPacked, locationPacked, count, value); } @@ -1539,7 +2211,7 @@ void GL_APIENTRY GL_ProgramUniform3uiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1549,23 +2221,37 @@ GL_ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfl { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4f, - "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", - CID(context), program, location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4f, + "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", + CID(context), program, location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4f) && - ValidateProgramUniform4f(context, angle::EntryPoint::GLProgramUniform4f, - programPacked, locationPacked, v0, v1, v2, v3))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4f(context, angle::EntryPoint::GLProgramUniform4f, + programPacked, locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform4f); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4f(programPacked, locationPacked, v0, v1, v2, v3); } @@ -1574,7 +2260,7 @@ GL_ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfl } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4f); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1586,23 +2272,37 @@ void GL_APIENTRY GL_ProgramUniform4fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4fv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4fv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4fv) && - ValidateProgramUniform4fv(context, angle::EntryPoint::GLProgramUniform4fv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4fv(context, angle::EntryPoint::GLProgramUniform4fv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4fv(programPacked, locationPacked, count, value); } @@ -1611,7 +2311,7 @@ void GL_APIENTRY GL_ProgramUniform4fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1621,23 +2321,37 @@ GL_ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2 { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4i, - "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d", - CID(context), program, location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4i, + "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d", + CID(context), program, location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4i) && - ValidateProgramUniform4i(context, angle::EntryPoint::GLProgramUniform4i, - programPacked, locationPacked, v0, v1, v2, v3))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4i(context, angle::EntryPoint::GLProgramUniform4i, + programPacked, locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform4i); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4i(programPacked, locationPacked, v0, v1, v2, v3); } @@ -1646,7 +2360,7 @@ GL_ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2 } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4i); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1658,23 +2372,37 @@ void GL_APIENTRY GL_ProgramUniform4iv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4iv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4iv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4iv) && - ValidateProgramUniform4iv(context, angle::EntryPoint::GLProgramUniform4iv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4iv(context, angle::EntryPoint::GLProgramUniform4iv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform4iv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4iv(programPacked, locationPacked, count, value); } @@ -1683,7 +2411,7 @@ void GL_APIENTRY GL_ProgramUniform4iv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4iv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1693,23 +2421,37 @@ GL_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4ui, - "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u, v3 = %u", - CID(context), program, location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4ui, + "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u, v3 = %u", + CID(context), program, location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4ui) && - ValidateProgramUniform4ui(context, angle::EntryPoint::GLProgramUniform4ui, - programPacked, locationPacked, v0, v1, v2, v3))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4ui(context, angle::EntryPoint::GLProgramUniform4ui, + programPacked, locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform4ui); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4ui(programPacked, locationPacked, v0, v1, v2, v3); } @@ -1718,7 +2460,7 @@ GL_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4ui); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1730,23 +2472,37 @@ void GL_APIENTRY GL_ProgramUniform4uiv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4uiv, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4uiv, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4uiv) && - ValidateProgramUniform4uiv(context, angle::EntryPoint::GLProgramUniform4uiv, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4uiv(context, angle::EntryPoint::GLProgramUniform4uiv, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniform4uiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4uiv(programPacked, locationPacked, count, value); } @@ -1755,7 +2511,7 @@ void GL_APIENTRY GL_ProgramUniform4uiv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4uiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1768,25 +2524,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix2fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix2fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix2fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix2fv) && - ValidateProgramUniformMatrix2fv(context, angle::EntryPoint::GLProgramUniformMatrix2fv, - programPacked, locationPacked, count, transpose, - value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix2fv( + context, angle::EntryPoint::GLProgramUniformMatrix2fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix2fv(programPacked, locationPacked, count, transpose, value); @@ -1796,7 +2565,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix2fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1809,25 +2579,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x3fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix2x3fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix2x3fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix2x3fv) && - ValidateProgramUniformMatrix2x3fv( - context, angle::EntryPoint::GLProgramUniformMatrix2x3fv, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix2x3fv( + context, angle::EntryPoint::GLProgramUniformMatrix2x3fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix2x3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix2x3fv(programPacked, locationPacked, count, transpose, value); @@ -1837,7 +2620,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x3fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix2x3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1850,25 +2634,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x4fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix2x4fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix2x4fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix2x4fv) && - ValidateProgramUniformMatrix2x4fv( - context, angle::EntryPoint::GLProgramUniformMatrix2x4fv, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix2x4fv( + context, angle::EntryPoint::GLProgramUniformMatrix2x4fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix2x4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix2x4fv(programPacked, locationPacked, count, transpose, value); @@ -1878,7 +2675,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x4fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix2x4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1891,25 +2689,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix3fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix3fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix3fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix3fv) && - ValidateProgramUniformMatrix3fv(context, angle::EntryPoint::GLProgramUniformMatrix3fv, - programPacked, locationPacked, count, transpose, - value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix3fv( + context, angle::EntryPoint::GLProgramUniformMatrix3fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix3fv(programPacked, locationPacked, count, transpose, value); @@ -1919,7 +2730,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix3fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1932,25 +2744,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x2fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix3x2fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix3x2fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix3x2fv) && - ValidateProgramUniformMatrix3x2fv( - context, angle::EntryPoint::GLProgramUniformMatrix3x2fv, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix3x2fv( + context, angle::EntryPoint::GLProgramUniformMatrix3x2fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix3x2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix3x2fv(programPacked, locationPacked, count, transpose, value); @@ -1960,7 +2785,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x2fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix3x2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1973,25 +2799,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x4fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix3x4fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix3x4fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix3x4fv) && - ValidateProgramUniformMatrix3x4fv( - context, angle::EntryPoint::GLProgramUniformMatrix3x4fv, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix3x4fv( + context, angle::EntryPoint::GLProgramUniformMatrix3x4fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix3x4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix3x4fv(programPacked, locationPacked, count, transpose, value); @@ -2001,7 +2840,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x4fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix3x4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2014,25 +2854,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix4fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix4fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix4fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix4fv) && - ValidateProgramUniformMatrix4fv(context, angle::EntryPoint::GLProgramUniformMatrix4fv, - programPacked, locationPacked, count, transpose, - value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix4fv( + context, angle::EntryPoint::GLProgramUniformMatrix4fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix4fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix4fv(programPacked, locationPacked, count, transpose, value); @@ -2042,7 +2895,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix4fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix4fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2055,25 +2909,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x2fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix4x2fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix4x2fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix4x2fv) && - ValidateProgramUniformMatrix4x2fv( - context, angle::EntryPoint::GLProgramUniformMatrix4x2fv, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix4x2fv( + context, angle::EntryPoint::GLProgramUniformMatrix4x2fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix4x2fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix4x2fv(programPacked, locationPacked, count, transpose, value); @@ -2083,7 +2950,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x2fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix4x2fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2096,25 +2964,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x3fv(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix4x3fv, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix4x3fv, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix4x3fv) && - ValidateProgramUniformMatrix4x3fv( - context, angle::EntryPoint::GLProgramUniformMatrix4x3fv, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix4x3fv( + context, angle::EntryPoint::GLProgramUniformMatrix4x3fv, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLProgramUniformMatrix4x3fv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix4x3fv(programPacked, locationPacked, count, transpose, value); @@ -2124,7 +3005,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x3fv(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix4x3fv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2133,20 +3015,33 @@ void GL_APIENTRY GL_SampleMaski(GLuint maskNumber, GLbitfield mask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSampleMaski, "context = %d, maskNumber = %u, mask = %s", CID(context), - maskNumber, GLbitfieldToString(GLESEnum::AllEnums, mask).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLSampleMaski, "context = %d, maskNumber = %u, mask = %s", + CID(context), maskNumber, + GLbitfieldToString(GLESEnum::AllEnums, mask).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleMaski) && - ValidateSampleMaski(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleMaski, maskNumber, mask))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSampleMaski( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLSampleMaski, maskNumber, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLSampleMaski); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateSampleMaski(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), maskNumber, mask); @@ -2155,7 +3050,7 @@ void GL_APIENTRY GL_SampleMaski(GLuint maskNumber, GLbitfield mask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSampleMaski); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2169,26 +3064,38 @@ void GL_APIENTRY GL_TexStorage2DMultisample(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage2DMultisample, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d, " - "fixedsamplelocations = %s", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, - GLbooleanToString(fixedsamplelocations)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorage2DMultisample, + "context = %d, target = %s, samples = %d, internalformat = %s, width = " + "%d, height = %d, fixedsamplelocations = %s", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, GLbooleanToString(fixedsamplelocations))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage2DMultisample) && - ValidateTexStorage2DMultisample(context, angle::EntryPoint::GLTexStorage2DMultisample, - targetPacked, samples, internalformat, width, height, - fixedsamplelocations))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorage2DMultisample( + context, angle::EntryPoint::GLTexStorage2DMultisample, targetPacked, samples, + internalformat, width, height, fixedsamplelocations); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLTexStorage2DMultisample); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage2DMultisample(targetPacked, samples, internalformat, width, height, fixedsamplelocations); @@ -2198,7 +3105,8 @@ void GL_APIENTRY GL_TexStorage2DMultisample(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorage2DMultisample); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2207,23 +3115,37 @@ void GL_APIENTRY GL_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUseProgramStages, "context = %d, pipeline = %u, stages = %s, program = %u", - CID(context), pipeline, GLbitfieldToString(GLESEnum::UseProgramStageMask, stages).c_str(), - program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUseProgramStages, "context = %d, pipeline = %u, stages = %s, program = %u", + CID(context), pipeline, + GLbitfieldToString(GLESEnum::UseProgramStageMask, stages).c_str(), program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLUseProgramStages) && - ValidateUseProgramStages(context, angle::EntryPoint::GLUseProgramStages, - pipelinePacked, stages, programPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUseProgramStages(context, angle::EntryPoint::GLUseProgramStages, + pipelinePacked, stages, programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLUseProgramStages); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->useProgramStages(pipelinePacked, stages, programPacked); } @@ -2232,7 +3154,7 @@ void GL_APIENTRY GL_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUseProgramStages); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2241,21 +3163,33 @@ void GL_APIENTRY GL_ValidateProgramPipeline(GLuint pipeline) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLValidateProgramPipeline, "context = %d, pipeline = %u", CID(context), - pipeline); + ANGLE_UNSAFE_TODO(EVENT(context, GLValidateProgramPipeline, "context = %d, pipeline = %u", + CID(context), pipeline)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLValidateProgramPipeline) && - ValidateValidateProgramPipeline(context, angle::EntryPoint::GLValidateProgramPipeline, - pipelinePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateValidateProgramPipeline( + context, angle::EntryPoint::GLValidateProgramPipeline, pipelinePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLValidateProgramPipeline); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->validateProgramPipeline(pipelinePacked); } @@ -2263,7 +3197,8 @@ void GL_APIENTRY GL_ValidateProgramPipeline(GLuint pipeline) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLValidateProgramPipeline); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2272,25 +3207,43 @@ void GL_APIENTRY GL_VertexAttribBinding(GLuint attribindex, GLuint bindingindex) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribBinding, "context = %d, attribindex = %u, bindingindex = %u", - CID(context), attribindex, bindingindex); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribBinding, + "context = %d, attribindex = %u, bindingindex = %u", CID(context), + attribindex, bindingindex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribBinding(context, angle::EntryPoint::GLVertexAttribBinding, - attribindex, bindingindex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribBinding( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribBinding, attribindex, bindingindex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLVertexAttribBinding); + } + } + if (ANGLE_LIKELY(isCallValid)) { - context->vertexAttribBinding(attribindex, bindingindex); + ContextPrivateVertexAttribBinding(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), attribindex, + bindingindex); } ANGLE_CAPTURE_GL(VertexAttribBinding, isCallValid, context, attribindex, bindingindex); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribBinding); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2303,30 +3256,50 @@ void GL_APIENTRY GL_VertexAttribFormat(GLuint attribindex, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribFormat, - "context = %d, attribindex = %u, size = %d, type = %s, normalized = %s, relativeoffset = " - "%u", - CID(context), attribindex, size, GLenumToString(GLESEnum::VertexAttribType, type), - GLbooleanToString(normalized), relativeoffset); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribFormat, + "context = %d, attribindex = %u, size = %d, type = %s, normalized = " + "%s, relativeoffset = %u", + CID(context), attribindex, size, + GLenumToString(GLESEnum::VertexAttribType, type), + GLbooleanToString(normalized), relativeoffset)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribFormat(context, angle::EntryPoint::GLVertexAttribFormat, - attribindex, size, typePacked, normalized, relativeoffset)); - if (isCallValid) - { - context->vertexAttribFormat(attribindex, size, typePacked, normalized, relativeoffset); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribFormat( + context->getPrivateState(), context->getPrivateStateCache(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribFormat, attribindex, size, typePacked, + normalized, relativeoffset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLVertexAttribFormat); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateVertexAttribFormat(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), attribindex, + size, typePacked, normalized, relativeoffset); } ANGLE_CAPTURE_GL(VertexAttribFormat, isCallValid, context, attribindex, size, typePacked, normalized, relativeoffset); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribFormat); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2338,28 +3311,48 @@ void GL_APIENTRY GL_VertexAttribIFormat(GLuint attribindex, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribIFormat, - "context = %d, attribindex = %u, size = %d, type = %s, relativeoffset = %u", CID(context), - attribindex, size, GLenumToString(GLESEnum::VertexAttribIType, type), relativeoffset); + ANGLE_UNSAFE_TODO(EVENT( + context, GLVertexAttribIFormat, + "context = %d, attribindex = %u, size = %d, type = %s, relativeoffset = %u", CID(context), + attribindex, size, GLenumToString(GLESEnum::VertexAttribIType, type), relativeoffset)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribIFormat(context, angle::EntryPoint::GLVertexAttribIFormat, - attribindex, size, typePacked, relativeoffset)); - if (isCallValid) - { - context->vertexAttribIFormat(attribindex, size, typePacked, relativeoffset); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribIFormat( + context->getPrivateState(), context->getPrivateStateCache(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribIFormat, attribindex, size, typePacked, + relativeoffset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLVertexAttribIFormat); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateVertexAttribIFormat(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), attribindex, + size, typePacked, relativeoffset); } ANGLE_CAPTURE_GL(VertexAttribIFormat, isCallValid, context, attribindex, size, typePacked, relativeoffset); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribIFormat); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2368,28 +3361,43 @@ void GL_APIENTRY GL_VertexBindingDivisor(GLuint bindingindex, GLuint divisor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexBindingDivisor, "context = %d, bindingindex = %u, divisor = %u", - CID(context), bindingindex, divisor); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexBindingDivisor, + "context = %d, bindingindex = %u, divisor = %u", CID(context), + bindingindex, divisor)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLVertexBindingDivisor) && - ValidateVertexBindingDivisor(context, angle::EntryPoint::GLVertexBindingDivisor, - bindingindex, divisor))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_1)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexBindingDivisor( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexBindingDivisor, bindingindex, divisor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES31(context, angle::EntryPoint::GLVertexBindingDivisor); + } + } + if (ANGLE_LIKELY(isCallValid)) { - context->vertexBindingDivisor(bindingindex, divisor); + ContextPrivateVertexBindingDivisor(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), bindingindex, + divisor); } ANGLE_CAPTURE_GL(VertexBindingDivisor, isCallValid, context, bindingindex, divisor); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexBindingDivisor); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } diff --git a/src/libGLESv2/entry_points_gles_3_2_autogen.cpp b/src/libGLESv2/entry_points_gles_3_2_autogen.cpp index 24e660db9fa..7d828929f74 100644 --- a/src/libGLESv2/entry_points_gles_3_2_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_3_2_autogen.cpp @@ -28,18 +28,30 @@ void GL_APIENTRY GL_BlendBarrier() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendBarrier, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendBarrier, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendBarrier) && - ValidateBlendBarrier(context, angle::EntryPoint::GLBlendBarrier))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendBarrier(context, angle::EntryPoint::GLBlendBarrier); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLBlendBarrier); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->blendBarrier(); } @@ -47,7 +59,7 @@ void GL_APIENTRY GL_BlendBarrier() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendBarrier); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -56,18 +68,34 @@ void GL_APIENTRY GL_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum mo { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationSeparatei, "context = %d, buf = %u, modeRGB = %s, modeAlpha = %s", - CID(context), buf, GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), - GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationSeparatei, + "context = %d, buf = %u, modeRGB = %s, modeAlpha = %s", CID(context), + buf, GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), + GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendEquationSeparatei( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationSeparatei, buf, modeRGB, modeAlpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationSeparatei( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationSeparatei, buf, modeRGB, modeAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLBlendEquationSeparatei); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationSeparatei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, @@ -77,7 +105,7 @@ void GL_APIENTRY GL_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum mo } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquationSeparatei); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -86,16 +114,33 @@ void GL_APIENTRY GL_BlendEquationi(GLuint buf, GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationi, "context = %d, buf = %u, mode = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendEquationModeEXT, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationi, "context = %d, buf = %u, mode = %s", + CID(context), buf, + GLenumToString(GLESEnum::BlendEquationModeEXT, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateBlendEquationi(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationi, buf, mode)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationi( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationi, buf, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLBlendEquationi); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationi(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, mode); @@ -104,7 +149,7 @@ void GL_APIENTRY GL_BlendEquationi(GLuint buf, GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquationi); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -114,21 +159,38 @@ GL_BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFuncSeparatei, - "context = %d, buf = %u, srcRGB = %s, dstRGB = %s, srcAlpha = %s, dstAlpha = %s", - CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, srcRGB), - GLenumToString(GLESEnum::BlendingFactor, dstRGB), - GLenumToString(GLESEnum::BlendingFactor, srcAlpha), - GLenumToString(GLESEnum::BlendingFactor, dstAlpha)); - - if (context) - { - bool isCallValid = - (context->skipValidation() || - ValidateBlendFuncSeparatei( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha)); - if (isCallValid) + ANGLE_UNSAFE_TODO( + EVENT(context, GLBlendFuncSeparatei, + "context = %d, buf = %u, srcRGB = %s, dstRGB = %s, srcAlpha = %s, dstAlpha = %s", + CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, srcRGB), + GLenumToString(GLESEnum::BlendingFactor, dstRGB), + GLenumToString(GLESEnum::BlendingFactor, srcAlpha), + GLenumToString(GLESEnum::BlendingFactor, dstAlpha))); + + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFuncSeparatei(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFuncSeparatei, + buf, srcRGB, dstRGB, srcAlpha, dstAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLBlendFuncSeparatei); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFuncSeparatei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, srcRGB, @@ -139,7 +201,7 @@ GL_BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFuncSeparatei); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -148,17 +210,33 @@ void GL_APIENTRY GL_BlendFunci(GLuint buf, GLenum src, GLenum dst) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFunci, "context = %d, buf = %u, src = %s, dst = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendingFactor, src), - GLenumToString(GLESEnum::BlendingFactor, dst)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendFunci, "context = %d, buf = %u, src = %s, dst = %s", + CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, src), + GLenumToString(GLESEnum::BlendingFactor, dst))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateBlendFunci(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFunci, buf, src, dst)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFunci(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFunci, buf, src, dst); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLBlendFunci); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFunci(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, src, dst); @@ -167,7 +245,7 @@ void GL_APIENTRY GL_BlendFunci(GLuint buf, GLenum src, GLenum dst) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFunci); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -176,17 +254,34 @@ void GL_APIENTRY GL_ColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColorMaski, "context = %d, index = %u, r = %s, g = %s, b = %s, a = %s", - CID(context), index, GLbooleanToString(r), GLbooleanToString(g), GLbooleanToString(b), - GLbooleanToString(a)); + ANGLE_UNSAFE_TODO(EVENT(context, GLColorMaski, + "context = %d, index = %u, r = %s, g = %s, b = %s, a = %s", + CID(context), index, GLbooleanToString(r), GLbooleanToString(g), + GLbooleanToString(b), GLbooleanToString(a))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateColorMaski(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColorMaski, index, r, g, b, a)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColorMaski( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColorMaski, index, r, g, b, a); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLColorMaski); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColorMaski(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, r, g, b, a); @@ -195,7 +290,7 @@ void GL_APIENTRY GL_ColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColorMaski); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -218,27 +313,41 @@ void GL_APIENTRY GL_CopyImageSubData(GLuint srcName, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyImageSubData, - "context = %d, srcName = %u, srcTarget = %s, srcLevel = %d, srcX = %d, srcY = %d, srcZ = " - "%d, dstName = %u, dstTarget = %s, dstLevel = %d, dstX = %d, dstY = %d, dstZ = %d, " - "srcWidth = %d, srcHeight = %d, srcDepth = %d", - CID(context), srcName, GLenumToString(GLESEnum::CopyImageSubDataTarget, srcTarget), - srcLevel, srcX, srcY, srcZ, dstName, - GLenumToString(GLESEnum::CopyImageSubDataTarget, dstTarget), dstLevel, dstX, dstY, dstZ, - srcWidth, srcHeight, srcDepth); - - if (context) + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopyImageSubData, + "context = %d, srcName = %u, srcTarget = %s, srcLevel = %d, srcX = %d, srcY = %d, " + "srcZ = %d, dstName = %u, dstTarget = %s, dstLevel = %d, dstX = %d, dstY = %d, dstZ " + "= %d, srcWidth = %d, srcHeight = %d, srcDepth = %d", + CID(context), srcName, GLenumToString(GLESEnum::CopyImageSubDataTarget, srcTarget), + srcLevel, srcX, srcY, srcZ, dstName, + GLenumToString(GLESEnum::CopyImageSubDataTarget, dstTarget), dstLevel, dstX, dstY, + dstZ, srcWidth, srcHeight, srcDepth)); + + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyImageSubData) && - ValidateCopyImageSubData(context, angle::EntryPoint::GLCopyImageSubData, srcName, - srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, - dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyImageSubData( + context, angle::EntryPoint::GLCopyImageSubData, srcName, srcTarget, srcLevel, + srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, + srcHeight, srcDepth); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLCopyImageSubData); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, @@ -250,7 +359,7 @@ void GL_APIENTRY GL_CopyImageSubData(GLuint srcName, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyImageSubData); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -259,18 +368,34 @@ void GL_APIENTRY GL_DebugMessageCallback(GLDEBUGPROC callback, const void *userP { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDebugMessageCallback, - "context = %d, callback = 0x%016" PRIxPTR ", userParam = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)callback, (uintptr_t)userParam); + ANGLE_UNSAFE_TODO(EVENT(context, GLDebugMessageCallback, + "context = %d, callback = 0x%016" PRIxPTR ", userParam = 0x%016" PRIxPTR + "", + CID(context), (uintptr_t)callback, (uintptr_t)userParam)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDebugMessageCallback(context, angle::EntryPoint::GLDebugMessageCallback, - callback, userParam)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDebugMessageCallback( + context, angle::EntryPoint::GLDebugMessageCallback, callback, userParam); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLDebugMessageCallback); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->debugMessageCallback(callback, userParam); } @@ -278,7 +403,7 @@ void GL_APIENTRY GL_DebugMessageCallback(GLDEBUGPROC callback, const void *userP } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDebugMessageCallback); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -292,22 +417,39 @@ void GL_APIENTRY GL_DebugMessageControl(GLenum source, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDebugMessageControl, - "context = %d, source = %s, type = %s, severity = %s, count = %d, ids = 0x%016" PRIxPTR - ", enabled = %s", - CID(context), GLenumToString(GLESEnum::DebugSource, source), - GLenumToString(GLESEnum::DebugType, type), - GLenumToString(GLESEnum::DebugSeverity, severity), count, (uintptr_t)ids, - GLbooleanToString(enabled)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLDebugMessageControl, + "context = %d, source = %s, type = %s, severity = %s, count = %d, ids = 0x%016" PRIxPTR + ", enabled = %s", + CID(context), GLenumToString(GLESEnum::DebugSource, source), + GLenumToString(GLESEnum::DebugType, type), + GLenumToString(GLESEnum::DebugSeverity, severity), count, (uintptr_t)ids, + GLbooleanToString(enabled))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDebugMessageControl(context, angle::EntryPoint::GLDebugMessageControl, source, - type, severity, count, ids, enabled)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDebugMessageControl(context, angle::EntryPoint::GLDebugMessageControl, + source, type, severity, count, ids, enabled); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLDebugMessageControl); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->debugMessageControl(source, type, severity, count, ids, enabled); } @@ -316,7 +458,7 @@ void GL_APIENTRY GL_DebugMessageControl(GLenum source, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDebugMessageControl); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -330,21 +472,38 @@ void GL_APIENTRY GL_DebugMessageInsert(GLenum source, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDebugMessageInsert, - "context = %d, source = %s, type = %s, id = %u, severity = %s, length = %d, buf = " - "0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::DebugSource, source), - GLenumToString(GLESEnum::DebugType, type), id, - GLenumToString(GLESEnum::DebugSeverity, severity), length, (uintptr_t)buf); + ANGLE_UNSAFE_TODO(EVENT(context, GLDebugMessageInsert, + "context = %d, source = %s, type = %s, id = %u, severity = %s, length " + "= %d, buf = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::DebugSource, source), + GLenumToString(GLESEnum::DebugType, type), id, + GLenumToString(GLESEnum::DebugSeverity, severity), length, + (uintptr_t)buf)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDebugMessageInsert(context, angle::EntryPoint::GLDebugMessageInsert, source, - type, id, severity, length, buf)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDebugMessageInsert(context, angle::EntryPoint::GLDebugMessageInsert, + source, type, id, severity, length, buf); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLDebugMessageInsert); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->debugMessageInsert(source, type, id, severity, length, buf); } @@ -353,7 +512,7 @@ void GL_APIENTRY GL_DebugMessageInsert(GLenum source, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDebugMessageInsert); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -362,16 +521,32 @@ void GL_APIENTRY GL_Disablei(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisablei, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisablei, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDisablei(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDisablei, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisablei(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDisablei, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLDisablei); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDisablei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, index); @@ -380,7 +555,7 @@ void GL_APIENTRY GL_Disablei(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDisablei); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -393,22 +568,39 @@ void GL_APIENTRY GL_DrawElementsBaseVertex(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsBaseVertex, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsBaseVertex, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawElementsBaseVertex(context, angle::EntryPoint::GLDrawElementsBaseVertex, - modePacked, count, typePacked, indices, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsBaseVertex( + context, angle::EntryPoint::GLDrawElementsBaseVertex, modePacked, count, + typePacked, indices, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLDrawElementsBaseVertex); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsBaseVertex(modePacked, count, typePacked, indices, basevertex); } @@ -417,7 +609,7 @@ void GL_APIENTRY GL_DrawElementsBaseVertex(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawElementsBaseVertex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -431,23 +623,41 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertex(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedBaseVertex, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instancecount = %d, basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, - basevertex); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedBaseVertex, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instancecount = %d, basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, + basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsInstancedBaseVertex( - context, angle::EntryPoint::GLDrawElementsInstancedBaseVertex, - modePacked, count, typePacked, indices, instancecount, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedBaseVertex( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertex, modePacked, + count, typePacked, indices, instancecount, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, + angle::EntryPoint::GLDrawElementsInstancedBaseVertex); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstancedBaseVertex(modePacked, count, typePacked, indices, instancecount, basevertex); @@ -457,7 +667,8 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertex(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedBaseVertex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -472,22 +683,39 @@ void GL_APIENTRY GL_DrawRangeElementsBaseVertex(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawRangeElementsBaseVertex, - "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, indices = " - "0x%016" PRIxPTR ", basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawRangeElementsBaseVertex, + "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, " + "indices = 0x%016" PRIxPTR ", basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, + count, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawRangeElementsBaseVertex( - context, angle::EntryPoint::GLDrawRangeElementsBaseVertex, - modePacked, start, end, count, typePacked, indices, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawRangeElementsBaseVertex( + context, angle::EntryPoint::GLDrawRangeElementsBaseVertex, modePacked, start, + end, count, typePacked, indices, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLDrawRangeElementsBaseVertex); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawRangeElementsBaseVertex(modePacked, start, end, count, typePacked, indices, basevertex); @@ -497,7 +725,8 @@ void GL_APIENTRY GL_DrawRangeElementsBaseVertex(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawRangeElementsBaseVertex); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -506,16 +735,32 @@ void GL_APIENTRY GL_Enablei(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEnablei, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLEnablei, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateEnablei(context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEnablei, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEnablei(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLEnablei, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLEnablei); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateEnablei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, index); @@ -524,7 +769,7 @@ void GL_APIENTRY GL_Enablei(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEnablei); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -536,20 +781,41 @@ void GL_APIENTRY GL_FramebufferTexture(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTexture, - "context = %d, target = %s, attachment = %s, texture = %u, level = %d", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, level); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTexture, + "context = %d, target = %s, attachment = %s, texture = %u, level = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, + level)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferTexture(context, angle::EntryPoint::GLFramebufferTexture, target, - attachment, texturePacked, level)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateFramebufferTexture(context, angle::EntryPoint::GLFramebufferTexture, + target, attachment, texturePacked, level); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLFramebufferTexture); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexture(target, attachment, texturePacked, level); } @@ -558,7 +824,7 @@ void GL_APIENTRY GL_FramebufferTexture(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFramebufferTexture); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -574,22 +840,39 @@ GLuint GL_APIENTRY GL_GetDebugMessageLog(GLuint count, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetDebugMessageLog, - "context = %d, count = %u, bufSize = %d, sources = 0x%016" PRIxPTR - ", types = 0x%016" PRIxPTR ", ids = 0x%016" PRIxPTR ", severities = 0x%016" PRIxPTR - ", lengths = 0x%016" PRIxPTR ", messageLog = 0x%016" PRIxPTR "", - CID(context), count, bufSize, (uintptr_t)sources, (uintptr_t)types, (uintptr_t)ids, - (uintptr_t)severities, (uintptr_t)lengths, (uintptr_t)messageLog); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetDebugMessageLog, + "context = %d, count = %u, bufSize = %d, sources = 0x%016" PRIxPTR + ", types = 0x%016" PRIxPTR ", ids = 0x%016" PRIxPTR ", severities = 0x%016" PRIxPTR + ", lengths = 0x%016" PRIxPTR ", messageLog = 0x%016" PRIxPTR "", + CID(context), count, bufSize, (uintptr_t)sources, (uintptr_t)types, (uintptr_t)ids, + (uintptr_t)severities, (uintptr_t)lengths, (uintptr_t)messageLog)); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetDebugMessageLog( - context, angle::EntryPoint::GLGetDebugMessageLog, count, bufSize, - sources, types, ids, severities, lengths, messageLog)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetDebugMessageLog( + context, angle::EntryPoint::GLGetDebugMessageLog, count, bufSize, sources, + types, ids, severities, lengths, messageLog); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetDebugMessageLog); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getDebugMessageLog(count, bufSize, sources, types, ids, severities, lengths, messageLog); @@ -603,7 +886,7 @@ GLuint GL_APIENTRY GL_GetDebugMessageLog(GLuint count, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetDebugMessageLog); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -614,16 +897,32 @@ GLenum GL_APIENTRY GL_GetGraphicsResetStatus() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetGraphicsResetStatus, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetGraphicsResetStatus, "context = %d", CID(context))); GLenum returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetGraphicsResetStatus(context, angle::EntryPoint::GLGetGraphicsResetStatus)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetGraphicsResetStatus( + context, angle::EntryPoint::GLGetGraphicsResetStatus); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetGraphicsResetStatus); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getGraphicsResetStatus(); } @@ -648,19 +947,36 @@ GL_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *leng { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetObjectLabel, - "context = %d, identifier = %s, name = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", label = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ObjectIdentifier, identifier), name, bufSize, - (uintptr_t)length, (uintptr_t)label); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetObjectLabel, + "context = %d, identifier = %s, name = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", label = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ObjectIdentifier, identifier), name, bufSize, + (uintptr_t)length, (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetObjectLabel(context, angle::EntryPoint::GLGetObjectLabel, - identifier, name, bufSize, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetObjectLabel(context, angle::EntryPoint::GLGetObjectLabel, + identifier, name, bufSize, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetObjectLabel); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getObjectLabel(identifier, name, bufSize, length, label); } @@ -669,7 +985,7 @@ GL_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *leng } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetObjectLabel); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -681,19 +997,35 @@ void GL_APIENTRY GL_GetObjectPtrLabel(const void *ptr, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetObjectPtrLabel, - "context = %d, ptr = 0x%016" PRIxPTR ", bufSize = %d, length = 0x%016" PRIxPTR - ", label = 0x%016" PRIxPTR "", - CID(context), (uintptr_t)ptr, bufSize, (uintptr_t)length, (uintptr_t)label); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetObjectPtrLabel, + "context = %d, ptr = 0x%016" PRIxPTR + ", bufSize = %d, length = 0x%016" PRIxPTR ", label = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)ptr, bufSize, (uintptr_t)length, + (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetObjectPtrLabel(context, angle::EntryPoint::GLGetObjectPtrLabel, ptr, - bufSize, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetObjectPtrLabel( + context, angle::EntryPoint::GLGetObjectPtrLabel, ptr, bufSize, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetObjectPtrLabel); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getObjectPtrLabel(ptr, bufSize, length, label); } @@ -701,7 +1033,7 @@ void GL_APIENTRY GL_GetObjectPtrLabel(const void *ptr, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetObjectPtrLabel); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -710,16 +1042,34 @@ void GL_APIENTRY GL_GetPointerv(GLenum pname, void **params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPointerv, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPointervPName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPointerv, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPointervPName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetPointerv(context, angle::EntryPoint::GLGetPointerv, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() < ES_2_0 || + context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetPointerv(context, angle::EntryPoint::GLGetPointerv, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES1Or32(context, angle::EntryPoint::GLGetPointerv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPointerv(pname, params); } @@ -727,7 +1077,7 @@ void GL_APIENTRY GL_GetPointerv(GLenum pname, void **params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetPointerv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -736,19 +1086,36 @@ void GL_APIENTRY GL_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint * { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIiv, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterIiv, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetSamplerParameterIiv(context, angle::EntryPoint::GLGetSamplerParameterIiv, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIiv( + context, angle::EntryPoint::GLGetSamplerParameterIiv, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetSamplerParameterIiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIiv(samplerPacked, pname, params); } @@ -757,7 +1124,7 @@ void GL_APIENTRY GL_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint * } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetSamplerParameterIiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -766,19 +1133,36 @@ void GL_APIENTRY GL_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIuiv, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterIuiv, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetSamplerParameterIuiv(context, angle::EntryPoint::GLGetSamplerParameterIuiv, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIuiv( + context, angle::EntryPoint::GLGetSamplerParameterIuiv, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetSamplerParameterIuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIuiv(samplerPacked, pname, params); } @@ -787,7 +1171,8 @@ void GL_APIENTRY GL_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -796,20 +1181,36 @@ void GL_APIENTRY GL_GetTexParameterIiv(GLenum target, GLenum pname, GLint *param { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIiv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterIiv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterIiv(context, angle::EntryPoint::GLGetTexParameterIiv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIiv( + context, angle::EntryPoint::GLGetTexParameterIiv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetTexParameterIiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIiv(targetPacked, pname, params); } @@ -817,7 +1218,7 @@ void GL_APIENTRY GL_GetTexParameterIiv(GLenum target, GLenum pname, GLint *param } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterIiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -826,20 +1227,36 @@ void GL_APIENTRY GL_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *par { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIuiv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterIuiv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterIuiv(context, angle::EntryPoint::GLGetTexParameterIuiv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIuiv( + context, angle::EntryPoint::GLGetTexParameterIuiv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetTexParameterIuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIuiv(targetPacked, pname, params); } @@ -847,7 +1264,7 @@ void GL_APIENTRY GL_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *par } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterIuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -856,19 +1273,36 @@ void GL_APIENTRY GL_GetnUniformfv(GLuint program, GLint location, GLsizei bufSiz { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformfv, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformfv, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetnUniformfv(context, angle::EntryPoint::GLGetnUniformfv, - programPacked, locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetnUniformfv(context, angle::EntryPoint::GLGetnUniformfv, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetnUniformfv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformfv(programPacked, locationPacked, bufSize, params); } @@ -877,7 +1311,7 @@ void GL_APIENTRY GL_GetnUniformfv(GLuint program, GLint location, GLsizei bufSiz } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformfv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -886,19 +1320,36 @@ void GL_APIENTRY GL_GetnUniformiv(GLuint program, GLint location, GLsizei bufSiz { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformiv, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformiv, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetnUniformiv(context, angle::EntryPoint::GLGetnUniformiv, - programPacked, locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetnUniformiv(context, angle::EntryPoint::GLGetnUniformiv, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetnUniformiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformiv(programPacked, locationPacked, bufSize, params); } @@ -907,7 +1358,7 @@ void GL_APIENTRY GL_GetnUniformiv(GLuint program, GLint location, GLsizei bufSiz } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -916,19 +1367,37 @@ void GL_APIENTRY GL_GetnUniformuiv(GLuint program, GLint location, GLsizei bufSi { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformuiv, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformuiv, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetnUniformuiv(context, angle::EntryPoint::GLGetnUniformuiv, - programPacked, locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetnUniformuiv(context, angle::EntryPoint::GLGetnUniformuiv, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLGetnUniformuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformuiv(programPacked, locationPacked, bufSize, params); } @@ -937,7 +1406,7 @@ void GL_APIENTRY GL_GetnUniformuiv(GLuint program, GLint location, GLsizei bufSi } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -946,17 +1415,33 @@ GLboolean GL_APIENTRY GL_IsEnabledi(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsEnabledi, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsEnabledi, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateIsEnabledi(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLIsEnabledi, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsEnabledi(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLIsEnabledi, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLIsEnabledi); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = ContextPrivateIsEnabledi(context->getMutablePrivateState(), @@ -970,7 +1455,7 @@ GLboolean GL_APIENTRY GL_IsEnabledi(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsEnabledi); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -981,19 +1466,32 @@ void GL_APIENTRY GL_MinSampleShading(GLfloat value) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMinSampleShading, "context = %d, value = %f", CID(context), value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLMinSampleShading, "context = %d, value = %f", CID(context), value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMinSampleShading) && - ValidateMinSampleShading(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMinSampleShading, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMinSampleShading( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMinSampleShading, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLMinSampleShading); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMinSampleShading(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), value); @@ -1002,7 +1500,7 @@ void GL_APIENTRY GL_MinSampleShading(GLfloat value) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMinSampleShading); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1011,18 +1509,35 @@ void GL_APIENTRY GL_ObjectLabel(GLenum identifier, GLuint name, GLsizei length, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLObjectLabel, - "context = %d, identifier = %s, name = %u, length = %d, label = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ObjectIdentifier, identifier), name, length, - (uintptr_t)label); + ANGLE_UNSAFE_TODO( + EVENT(context, GLObjectLabel, + "context = %d, identifier = %s, name = %u, length = %d, label = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ObjectIdentifier, identifier), name, length, + (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateObjectLabel(context, angle::EntryPoint::GLObjectLabel, - identifier, name, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateObjectLabel(context, angle::EntryPoint::GLObjectLabel, + identifier, name, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLObjectLabel); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->objectLabel(identifier, name, length, label); } @@ -1030,7 +1545,7 @@ void GL_APIENTRY GL_ObjectLabel(GLenum identifier, GLuint name, GLsizei length, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLObjectLabel); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1039,17 +1554,34 @@ void GL_APIENTRY GL_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLObjectPtrLabel, - "context = %d, ptr = 0x%016" PRIxPTR ", length = %d, label = 0x%016" PRIxPTR "", - CID(context), (uintptr_t)ptr, length, (uintptr_t)label); + ANGLE_UNSAFE_TODO(EVENT(context, GLObjectPtrLabel, + "context = %d, ptr = 0x%016" PRIxPTR + ", length = %d, label = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)ptr, length, (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateObjectPtrLabel(context, angle::EntryPoint::GLObjectPtrLabel, - ptr, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateObjectPtrLabel(context, angle::EntryPoint::GLObjectPtrLabel, + ptr, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLObjectPtrLabel); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->objectPtrLabel(ptr, length, label); } @@ -1057,7 +1589,7 @@ void GL_APIENTRY GL_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLObjectPtrLabel); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1066,20 +1598,33 @@ void GL_APIENTRY GL_PatchParameteri(GLenum pname, GLint value) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPatchParameteri, "context = %d, pname = %s, value = %d", CID(context), - GLenumToString(GLESEnum::PatchParameterName, pname), value); + ANGLE_UNSAFE_TODO(EVENT(context, GLPatchParameteri, "context = %d, pname = %s, value = %d", + CID(context), GLenumToString(GLESEnum::PatchParameterName, pname), + value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPatchParameteri) && - ValidatePatchParameteri(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPatchParameteri, pname, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePatchParameteri( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPatchParameteri, pname, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLPatchParameteri); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePatchParameteri(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, value); @@ -1088,7 +1633,7 @@ void GL_APIENTRY GL_PatchParameteri(GLenum pname, GLint value) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPatchParameteri); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1097,14 +1642,30 @@ void GL_APIENTRY GL_PopDebugGroup() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPopDebugGroup, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPopDebugGroup, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidatePopDebugGroup(context, angle::EntryPoint::GLPopDebugGroup)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePopDebugGroup(context, angle::EntryPoint::GLPopDebugGroup); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLPopDebugGroup); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->popDebugGroup(); } @@ -1112,7 +1673,7 @@ void GL_APIENTRY GL_PopDebugGroup() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPopDebugGroup); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1128,23 +1689,35 @@ void GL_APIENTRY GL_PrimitiveBoundingBox(GLfloat minX, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPrimitiveBoundingBox, - "context = %d, minX = %f, minY = %f, minZ = %f, minW = %f, maxX = %f, maxY = %f, maxZ = " - "%f, maxW = %f", - CID(context), minX, minY, minZ, minW, maxX, maxY, maxZ, maxW); - - if (context) - { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPrimitiveBoundingBox) && - ValidatePrimitiveBoundingBox(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPrimitiveBoundingBox, minX, minY, - minZ, minW, maxX, maxY, maxZ, maxW))); - if (isCallValid) + ANGLE_UNSAFE_TODO(EVENT(context, GLPrimitiveBoundingBox, + "context = %d, minX = %f, minY = %f, minZ = %f, minW = %f, maxX = %f, " + "maxY = %f, maxZ = %f, maxW = %f", + CID(context), minX, minY, minZ, minW, maxX, maxY, maxZ, maxW)); + + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePrimitiveBoundingBox( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPrimitiveBoundingBox, minX, minY, minZ, minW, maxX, maxY, + maxZ, maxW); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLPrimitiveBoundingBox); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePrimitiveBoundingBox(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), minX, minY, @@ -1155,7 +1728,7 @@ void GL_APIENTRY GL_PrimitiveBoundingBox(GLfloat minX, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPrimitiveBoundingBox); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1164,18 +1737,35 @@ void GL_APIENTRY GL_PushDebugGroup(GLenum source, GLuint id, GLsizei length, con { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPushDebugGroup, - "context = %d, source = %s, id = %u, length = %d, message = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::DebugSource, source), id, length, - (uintptr_t)message); + ANGLE_UNSAFE_TODO( + EVENT(context, GLPushDebugGroup, + "context = %d, source = %s, id = %u, length = %d, message = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::DebugSource, source), id, length, + (uintptr_t)message)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidatePushDebugGroup(context, angle::EntryPoint::GLPushDebugGroup, - source, id, length, message)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePushDebugGroup(context, angle::EntryPoint::GLPushDebugGroup, + source, id, length, message); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLPushDebugGroup); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->pushDebugGroup(source, id, length, message); } @@ -1183,7 +1773,7 @@ void GL_APIENTRY GL_PushDebugGroup(GLenum source, GLuint id, GLsizei length, con } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPushDebugGroup); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1199,23 +1789,36 @@ void GL_APIENTRY GL_ReadnPixels(GLint x, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadnPixels, - "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, bufSize " - "= %d, data = 0x%016" PRIxPTR "", - CID(context), x, y, width, height, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), bufSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLReadnPixels, + "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, " + "type = %s, bufSize = %d, data = 0x%016" PRIxPTR "", + CID(context), x, y, width, height, + GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), bufSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadnPixels) && - ValidateReadnPixels(context, angle::EntryPoint::GLReadnPixels, x, y, width, height, - format, type, bufSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateReadnPixels(context, angle::EntryPoint::GLReadnPixels, x, y, + width, height, format, type, bufSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLReadnPixels); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readnPixels(x, y, width, height, format, type, bufSize, data); } @@ -1224,7 +1827,7 @@ void GL_APIENTRY GL_ReadnPixels(GLint x, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadnPixels); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1233,19 +1836,35 @@ void GL_APIENTRY GL_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIiv, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterIiv, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterIiv(context, angle::EntryPoint::GLSamplerParameterIiv, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIiv( + context, angle::EntryPoint::GLSamplerParameterIiv, samplerPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLSamplerParameterIiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIiv(samplerPacked, pname, param); } @@ -1253,7 +1872,7 @@ void GL_APIENTRY GL_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameterIiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1262,19 +1881,36 @@ void GL_APIENTRY GL_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLu { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIuiv, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterIuiv, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterIuiv(context, angle::EntryPoint::GLSamplerParameterIuiv, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateSamplerParameterIuiv(context, angle::EntryPoint::GLSamplerParameterIuiv, + samplerPacked, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLSamplerParameterIuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIuiv(samplerPacked, pname, param); } @@ -1282,7 +1918,7 @@ void GL_APIENTRY GL_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLu } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameterIuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1291,23 +1927,36 @@ void GL_APIENTRY GL_TexBuffer(GLenum target, GLenum internalformat, GLuint buffe { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexBuffer, "context = %d, target = %s, internalformat = %s, buffer = %u", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexBuffer, + "context = %d, target = %s, internalformat = %s, buffer = %u", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexBuffer) && - ValidateTexBuffer(context, angle::EntryPoint::GLTexBuffer, targetPacked, - internalformat, bufferPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexBuffer(context, angle::EntryPoint::GLTexBuffer, + targetPacked, internalformat, bufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLTexBuffer); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texBuffer(targetPacked, internalformat, bufferPacked); } @@ -1316,7 +1965,7 @@ void GL_APIENTRY GL_TexBuffer(GLenum target, GLenum internalformat, GLuint buffe } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexBuffer); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1329,25 +1978,39 @@ void GL_APIENTRY GL_TexBufferRange(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexBufferRange, - "context = %d, target = %s, internalformat = %s, buffer = %u, offset = %llu, size = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer, - static_cast(offset), static_cast(size)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexBufferRange, + "context = %d, target = %s, internalformat = %s, buffer = %u, offset = %llu, size = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer, + static_cast(offset), static_cast(size))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexBufferRange) && - ValidateTexBufferRange(context, angle::EntryPoint::GLTexBufferRange, targetPacked, - internalformat, bufferPacked, offset, size))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexBufferRange(context, angle::EntryPoint::GLTexBufferRange, + targetPacked, internalformat, bufferPacked, + offset, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLTexBufferRange); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texBufferRange(targetPacked, internalformat, bufferPacked, offset, size); } @@ -1356,7 +2019,7 @@ void GL_APIENTRY GL_TexBufferRange(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexBufferRange); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1365,19 +2028,36 @@ void GL_APIENTRY GL_TexParameterIiv(GLenum target, GLenum pname, const GLint *pa { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIiv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterIiv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterIiv(context, angle::EntryPoint::GLTexParameterIiv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIiv(context, angle::EntryPoint::GLTexParameterIiv, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLTexParameterIiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIiv(targetPacked, pname, params); } @@ -1385,7 +2065,7 @@ void GL_APIENTRY GL_TexParameterIiv(GLenum target, GLenum pname, const GLint *pa } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterIiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1394,19 +2074,36 @@ void GL_APIENTRY GL_TexParameterIuiv(GLenum target, GLenum pname, const GLuint * { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIuiv, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterIuiv, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterIuiv(context, angle::EntryPoint::GLTexParameterIuiv, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIuiv( + context, angle::EntryPoint::GLTexParameterIuiv, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLTexParameterIuiv); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIuiv(targetPacked, pname, params); } @@ -1414,7 +2111,7 @@ void GL_APIENTRY GL_TexParameterIuiv(GLenum target, GLenum pname, const GLuint * } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterIuiv); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1429,26 +2126,38 @@ void GL_APIENTRY GL_TexStorage3DMultisample(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage3DMultisample, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, fixedsamplelocations = %s", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, depth, - GLbooleanToString(fixedsamplelocations)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorage3DMultisample, + "context = %d, target = %s, samples = %d, internalformat = %s, width = " + "%d, height = %d, depth = %d, fixedsamplelocations = %s", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, depth, GLbooleanToString(fixedsamplelocations))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage3DMultisample) && - ValidateTexStorage3DMultisample(context, angle::EntryPoint::GLTexStorage3DMultisample, - targetPacked, samples, internalformat, width, height, - depth, fixedsamplelocations))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getClientVersion() >= ES_3_2)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorage3DMultisample( + context, angle::EntryPoint::GLTexStorage3DMultisample, targetPacked, samples, + internalformat, width, height, depth, fixedsamplelocations); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorES32(context, angle::EntryPoint::GLTexStorage3DMultisample); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage3DMultisample(targetPacked, samples, internalformat, width, height, depth, fixedsamplelocations); @@ -1458,7 +2167,8 @@ void GL_APIENTRY GL_TexStorage3DMultisample(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorage3DMultisample); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.cpp b/src/libGLESv2/entry_points_gles_ext_autogen.cpp index b1c1f158678..d3206b0cfca 100644 --- a/src/libGLESv2/entry_points_gles_ext_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_ext_autogen.cpp @@ -43,19 +43,32 @@ void GL_APIENTRY GL_BeginPerfMonitorAMD(GLuint monitor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBeginPerfMonitorAMD, "context = %d, monitor = %u", CID(context), monitor); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBeginPerfMonitorAMD, "context = %d, monitor = %u", CID(context), monitor)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBeginPerfMonitorAMD) && - ValidateBeginPerfMonitorAMD(context, angle::EntryPoint::GLBeginPerfMonitorAMD, - monitor))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBeginPerfMonitorAMD( + context, angle::EntryPoint::GLBeginPerfMonitorAMD, monitor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBeginPerfMonitorAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->beginPerfMonitor(monitor); } @@ -63,7 +76,7 @@ void GL_APIENTRY GL_BeginPerfMonitorAMD(GLuint monitor) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBeginPerfMonitorAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -72,16 +85,33 @@ void GL_APIENTRY GL_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeletePerfMonitorsAMD, "context = %d, n = %d, monitors = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)monitors); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeletePerfMonitorsAMD, + "context = %d, n = %d, monitors = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)monitors)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDeletePerfMonitorsAMD( - context, angle::EntryPoint::GLDeletePerfMonitorsAMD, n, monitors)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeletePerfMonitorsAMD( + context, angle::EntryPoint::GLDeletePerfMonitorsAMD, n, monitors); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeletePerfMonitorsAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deletePerfMonitors(n, monitors); } @@ -89,7 +119,7 @@ void GL_APIENTRY GL_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeletePerfMonitorsAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -98,18 +128,32 @@ void GL_APIENTRY GL_EndPerfMonitorAMD(GLuint monitor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEndPerfMonitorAMD, "context = %d, monitor = %u", CID(context), monitor); + ANGLE_UNSAFE_TODO( + EVENT(context, GLEndPerfMonitorAMD, "context = %d, monitor = %u", CID(context), monitor)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEndPerfMonitorAMD) && - ValidateEndPerfMonitorAMD(context, angle::EntryPoint::GLEndPerfMonitorAMD, monitor))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEndPerfMonitorAMD( + context, angle::EntryPoint::GLEndPerfMonitorAMD, monitor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEndPerfMonitorAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->endPerfMonitor(monitor); } @@ -117,7 +161,7 @@ void GL_APIENTRY GL_EndPerfMonitorAMD(GLuint monitor) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEndPerfMonitorAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -126,16 +170,33 @@ void GL_APIENTRY GL_GenPerfMonitorsAMD(GLsizei n, GLuint *monitors) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenPerfMonitorsAMD, "context = %d, n = %d, monitors = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)monitors); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenPerfMonitorsAMD, + "context = %d, n = %d, monitors = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)monitors)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenPerfMonitorsAMD( - context, angle::EntryPoint::GLGenPerfMonitorsAMD, n, monitors)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenPerfMonitorsAMD( + context, angle::EntryPoint::GLGenPerfMonitorsAMD, n, monitors); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenPerfMonitorsAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genPerfMonitors(n, monitors); } @@ -143,7 +204,7 @@ void GL_APIENTRY GL_GenPerfMonitorsAMD(GLsizei n, GLuint *monitors) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenPerfMonitorsAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -156,20 +217,37 @@ void GL_APIENTRY GL_GetPerfMonitorCounterDataAMD(GLuint monitor, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPerfMonitorCounterDataAMD, - "context = %d, monitor = %u, pname = %s, dataSize = %d, data = 0x%016" PRIxPTR - ", bytesWritten = 0x%016" PRIxPTR "", - CID(context), monitor, GLenumToString(GLESEnum::AllEnums, pname), dataSize, - (uintptr_t)data, (uintptr_t)bytesWritten); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetPerfMonitorCounterDataAMD, + "context = %d, monitor = %u, pname = %s, dataSize = %d, data = 0x%016" PRIxPTR + ", bytesWritten = 0x%016" PRIxPTR "", + CID(context), monitor, GLenumToString(GLESEnum::AllEnums, pname), dataSize, + (uintptr_t)data, (uintptr_t)bytesWritten)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPerfMonitorCounterDataAMD( - context, angle::EntryPoint::GLGetPerfMonitorCounterDataAMD, monitor, - pname, dataSize, data, bytesWritten)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPerfMonitorCounterDataAMD( + context, angle::EntryPoint::GLGetPerfMonitorCounterDataAMD, monitor, pname, + dataSize, data, bytesWritten); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPerfMonitorCounterDataAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPerfMonitorCounterData(monitor, pname, dataSize, data, bytesWritten); } @@ -178,7 +256,8 @@ void GL_APIENTRY GL_GetPerfMonitorCounterDataAMD(GLuint monitor, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPerfMonitorCounterDataAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -190,18 +269,35 @@ void GL_APIENTRY GL_GetPerfMonitorCounterInfoAMD(GLuint group, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPerfMonitorCounterInfoAMD, - "context = %d, group = %u, counter = %u, pname = %s, data = 0x%016" PRIxPTR "", - CID(context), group, counter, GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetPerfMonitorCounterInfoAMD, + "context = %d, group = %u, counter = %u, pname = %s, data = 0x%016" PRIxPTR "", + CID(context), group, counter, GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPerfMonitorCounterInfoAMD( - context, angle::EntryPoint::GLGetPerfMonitorCounterInfoAMD, group, - counter, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPerfMonitorCounterInfoAMD( + context, angle::EntryPoint::GLGetPerfMonitorCounterInfoAMD, group, counter, + pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPerfMonitorCounterInfoAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPerfMonitorCounterInfo(group, counter, pname, data); } @@ -210,7 +306,8 @@ void GL_APIENTRY GL_GetPerfMonitorCounterInfoAMD(GLuint group, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPerfMonitorCounterInfoAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -223,19 +320,37 @@ void GL_APIENTRY GL_GetPerfMonitorCounterStringAMD(GLuint group, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPerfMonitorCounterStringAMD, - "context = %d, group = %u, counter = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", counterString = 0x%016" PRIxPTR "", - CID(context), group, counter, bufSize, (uintptr_t)length, (uintptr_t)counterString); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetPerfMonitorCounterStringAMD, + "context = %d, group = %u, counter = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", counterString = 0x%016" PRIxPTR "", + CID(context), group, counter, bufSize, (uintptr_t)length, (uintptr_t)counterString)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPerfMonitorCounterStringAMD( - context, angle::EntryPoint::GLGetPerfMonitorCounterStringAMD, group, - counter, bufSize, length, counterString)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPerfMonitorCounterStringAMD( + context, angle::EntryPoint::GLGetPerfMonitorCounterStringAMD, group, counter, + bufSize, length, counterString); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetPerfMonitorCounterStringAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPerfMonitorCounterString(group, counter, bufSize, length, counterString); } @@ -244,7 +359,8 @@ void GL_APIENTRY GL_GetPerfMonitorCounterStringAMD(GLuint group, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPerfMonitorCounterStringAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -257,20 +373,37 @@ void GL_APIENTRY GL_GetPerfMonitorCountersAMD(GLuint group, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPerfMonitorCountersAMD, - "context = %d, group = %u, numCounters = 0x%016" PRIxPTR - ", maxActiveCounters = 0x%016" PRIxPTR ", counterSize = %d, counters = 0x%016" PRIxPTR "", - CID(context), group, (uintptr_t)numCounters, (uintptr_t)maxActiveCounters, counterSize, - (uintptr_t)counters); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPerfMonitorCountersAMD, + "context = %d, group = %u, numCounters = 0x%016" PRIxPTR + ", maxActiveCounters = 0x%016" PRIxPTR + ", counterSize = %d, counters = 0x%016" PRIxPTR "", + CID(context), group, (uintptr_t)numCounters, + (uintptr_t)maxActiveCounters, counterSize, (uintptr_t)counters)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPerfMonitorCountersAMD( - context, angle::EntryPoint::GLGetPerfMonitorCountersAMD, group, - numCounters, maxActiveCounters, counterSize, counters)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPerfMonitorCountersAMD( + context, angle::EntryPoint::GLGetPerfMonitorCountersAMD, group, numCounters, + maxActiveCounters, counterSize, counters); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPerfMonitorCountersAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPerfMonitorCounters(group, numCounters, maxActiveCounters, counterSize, counters); @@ -280,7 +413,8 @@ void GL_APIENTRY GL_GetPerfMonitorCountersAMD(GLuint group, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPerfMonitorCountersAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -292,19 +426,36 @@ void GL_APIENTRY GL_GetPerfMonitorGroupStringAMD(GLuint group, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPerfMonitorGroupStringAMD, - "context = %d, group = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", groupString = 0x%016" PRIxPTR "", - CID(context), group, bufSize, (uintptr_t)length, (uintptr_t)groupString); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPerfMonitorGroupStringAMD, + "context = %d, group = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", groupString = 0x%016" PRIxPTR "", + CID(context), group, bufSize, (uintptr_t)length, + (uintptr_t)groupString)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPerfMonitorGroupStringAMD( - context, angle::EntryPoint::GLGetPerfMonitorGroupStringAMD, group, - bufSize, length, groupString)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPerfMonitorGroupStringAMD( + context, angle::EntryPoint::GLGetPerfMonitorGroupStringAMD, group, bufSize, + length, groupString); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPerfMonitorGroupStringAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPerfMonitorGroupString(group, bufSize, length, groupString); } @@ -313,7 +464,8 @@ void GL_APIENTRY GL_GetPerfMonitorGroupStringAMD(GLuint group, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPerfMonitorGroupStringAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -322,19 +474,35 @@ void GL_APIENTRY GL_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPerfMonitorGroupsAMD, - "context = %d, numGroups = 0x%016" PRIxPTR ", groupsSize = %d, groups = 0x%016" PRIxPTR - "", - CID(context), (uintptr_t)numGroups, groupsSize, (uintptr_t)groups); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPerfMonitorGroupsAMD, + "context = %d, numGroups = 0x%016" PRIxPTR + ", groupsSize = %d, groups = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)numGroups, groupsSize, (uintptr_t)groups)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetPerfMonitorGroupsAMD(context, angle::EntryPoint::GLGetPerfMonitorGroupsAMD, - numGroups, groupsSize, groups)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPerfMonitorGroupsAMD( + context, angle::EntryPoint::GLGetPerfMonitorGroupsAMD, numGroups, groupsSize, + groups); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPerfMonitorGroupsAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPerfMonitorGroups(numGroups, groupsSize, groups); } @@ -343,7 +511,8 @@ void GL_APIENTRY GL_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPerfMonitorGroupsAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -356,24 +525,36 @@ void GL_APIENTRY GL_SelectPerfMonitorCountersAMD(GLuint monitor, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSelectPerfMonitorCountersAMD, - "context = %d, monitor = %u, enable = %s, group = %u, numCounters = %d, counterList = " - "0x%016" PRIxPTR "", - CID(context), monitor, GLbooleanToString(enable), group, numCounters, - (uintptr_t)counterList); + ANGLE_UNSAFE_TODO(EVENT(context, GLSelectPerfMonitorCountersAMD, + "context = %d, monitor = %u, enable = %s, group = %u, numCounters = " + "%d, counterList = 0x%016" PRIxPTR "", + CID(context), monitor, GLbooleanToString(enable), group, numCounters, + (uintptr_t)counterList)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSelectPerfMonitorCountersAMD) && - ValidateSelectPerfMonitorCountersAMD( - context, angle::EntryPoint::GLSelectPerfMonitorCountersAMD, monitor, enable, - group, numCounters, counterList))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().performanceMonitorAMD)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSelectPerfMonitorCountersAMD( + context, angle::EntryPoint::GLSelectPerfMonitorCountersAMD, monitor, enable, + group, numCounters, counterList); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSelectPerfMonitorCountersAMD); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->selectPerfMonitorCounters(monitor, enable, group, numCounters, counterList); } @@ -382,7 +563,8 @@ void GL_APIENTRY GL_SelectPerfMonitorCountersAMD(GLuint monitor, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSelectPerfMonitorCountersAMD); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -398,20 +580,38 @@ void GL_APIENTRY GL_DrawArraysInstancedBaseInstanceANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArraysInstancedBaseInstanceANGLE, - "context = %d, mode = %s, first = %d, count = %d, instanceCount = %d, baseInstance = %u", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), first, count, instanceCount, - baseInstance); + ANGLE_UNSAFE_TODO(EVENT( + context, GLDrawArraysInstancedBaseInstanceANGLE, + "context = %d, mode = %s, first = %d, count = %d, instanceCount = %d, baseInstance = %u", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), first, count, instanceCount, + baseInstance)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawArraysInstancedBaseInstanceANGLE( - context, angle::EntryPoint::GLDrawArraysInstancedBaseInstanceANGLE, - modePacked, first, count, instanceCount, baseInstance)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseVertexBaseInstanceANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawArraysInstancedBaseInstanceANGLE( + context, angle::EntryPoint::GLDrawArraysInstancedBaseInstanceANGLE, modePacked, + first, count, instanceCount, baseInstance); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawArraysInstancedBaseInstanceANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawArraysInstancedBaseInstanceANGLE(modePacked, first, count, instanceCount, baseInstance); @@ -421,7 +621,8 @@ void GL_APIENTRY GL_DrawArraysInstancedBaseInstanceANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawArraysInstancedBaseInstanceANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -436,24 +637,42 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexBaseInstanceANGLE(GLenum mode { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedBaseVertexBaseInstanceANGLE, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instanceCount = %d, baseVertex = %d, baseInstance = %u", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instanceCount, - baseVertex, baseInstance); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedBaseVertexBaseInstanceANGLE, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instanceCount = %d, baseVertex = %d, baseInstance = %u", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instanceCount, + baseVertex, baseInstance)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE( - context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceANGLE, - modePacked, count, typePacked, indices, instanceCount, baseVertex, baseInstance)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseVertexBaseInstanceANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceANGLE, + modePacked, count, typePacked, indices, instanceCount, baseVertex, + baseInstance); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstancedBaseVertexBaseInstanceANGLE( modePacked, count, typePacked, indices, instanceCount, baseVertex, baseInstance); @@ -464,7 +683,8 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexBaseInstanceANGLE(GLenum mode } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -478,25 +698,39 @@ void GL_APIENTRY GL_MultiDrawArraysInstancedBaseInstanceANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawArraysInstancedBaseInstanceANGLE, - "context = %d, mode = %s, firsts = 0x%016" PRIxPTR ", counts = 0x%016" PRIxPTR - ", instanceCounts = 0x%016" PRIxPTR ", baseInstances = 0x%016" PRIxPTR ", drawcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)firsts, - (uintptr_t)counts, (uintptr_t)instanceCounts, (uintptr_t)baseInstances, drawcount); + ANGLE_UNSAFE_TODO(EVENT( + context, GLMultiDrawArraysInstancedBaseInstanceANGLE, + "context = %d, mode = %s, firsts = 0x%016" PRIxPTR ", counts = 0x%016" PRIxPTR + ", instanceCounts = 0x%016" PRIxPTR ", baseInstances = 0x%016" PRIxPTR ", drawcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)firsts, + (uintptr_t)counts, (uintptr_t)instanceCounts, (uintptr_t)baseInstances, drawcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawArraysInstancedBaseInstanceANGLE) && - ValidateMultiDrawArraysInstancedBaseInstanceANGLE( - context, angle::EntryPoint::GLMultiDrawArraysInstancedBaseInstanceANGLE, - modePacked, firsts, counts, instanceCounts, baseInstances, drawcount))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseVertexBaseInstanceANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawArraysInstancedBaseInstanceANGLE( + context, angle::EntryPoint::GLMultiDrawArraysInstancedBaseInstanceANGLE, + modePacked, firsts, counts, instanceCounts, baseInstances, drawcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLMultiDrawArraysInstancedBaseInstanceANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawArraysInstancedBaseInstance(modePacked, firsts, counts, instanceCounts, baseInstances, drawcount); @@ -506,7 +740,8 @@ void GL_APIENTRY GL_MultiDrawArraysInstancedBaseInstanceANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawArraysInstancedBaseInstanceANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -523,30 +758,45 @@ GL_MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, - "context = %d, mode = %s, counts = 0x%016" PRIxPTR ", type = %s, indices = 0x%016" PRIxPTR - ", instanceCounts = 0x%016" PRIxPTR ", baseVertices = 0x%016" PRIxPTR - ", baseInstances = 0x%016" PRIxPTR ", drawcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)counts, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, - (uintptr_t)instanceCounts, (uintptr_t)baseVertices, (uintptr_t)baseInstances, drawcount); + ANGLE_UNSAFE_TODO(EVENT( + context, GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, + "context = %d, mode = %s, counts = 0x%016" PRIxPTR ", type = %s, indices = 0x%016" PRIxPTR + ", instanceCounts = 0x%016" PRIxPTR ", baseVertices = 0x%016" PRIxPTR + ", baseInstances = 0x%016" PRIxPTR ", drawcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)counts, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, + (uintptr_t)instanceCounts, (uintptr_t)baseVertices, (uintptr_t)baseInstances, drawcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE) && - ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE( - context, - angle::EntryPoint::GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, - modePacked, counts, typePacked, indices, instanceCounts, baseVertices, - baseInstances, drawcount))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseVertexBaseInstanceANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE( + context, + angle::EntryPoint::GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, + modePacked, counts, typePacked, indices, instanceCounts, baseVertices, + baseInstances, drawcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, + angle::EntryPoint::GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawElementsInstancedBaseVertexBaseInstance( modePacked, counts, typePacked, indices, instanceCounts, baseVertices, @@ -558,7 +808,8 @@ GL_MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -570,22 +821,34 @@ void GL_APIENTRY GL_BlobCacheCallbacksANGLE(GLSETBLOBPROCANGLE set, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlobCacheCallbacksANGLE, - "context = %d, set = 0x%016" PRIxPTR ", get = 0x%016" PRIxPTR - ", userParam = 0x%016" PRIxPTR "", - CID(context), (uintptr_t)set, (uintptr_t)get, (uintptr_t)userParam); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlobCacheCallbacksANGLE, + "context = %d, set = 0x%016" PRIxPTR ", get = 0x%016" PRIxPTR + ", userParam = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)set, (uintptr_t)get, (uintptr_t)userParam)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlobCacheCallbacksANGLE) && - ValidateBlobCacheCallbacksANGLE(context, angle::EntryPoint::GLBlobCacheCallbacksANGLE, - set, get, userParam))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blobCacheANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlobCacheCallbacksANGLE( + context, angle::EntryPoint::GLBlobCacheCallbacksANGLE, set, get, userParam); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlobCacheCallbacksANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->blobCacheCallbacks(set, get, userParam); } @@ -593,7 +856,8 @@ void GL_APIENTRY GL_BlobCacheCallbacksANGLE(GLSETBLOBPROCANGLE set, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBlobCacheCallbacksANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -602,16 +866,33 @@ void GL_APIENTRY GL_GetPointervANGLE(GLenum pname, void **params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPointervANGLE, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPointervANGLE, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPointervANGLE(context, angle::EntryPoint::GLGetPointervANGLE, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blobCacheANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPointervANGLE( + context, angle::EntryPoint::GLGetPointervANGLE, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPointervANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPointerv(pname, params); } @@ -619,7 +900,7 @@ void GL_APIENTRY GL_GetPointervANGLE(GLenum pname, void **params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetPointervANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -642,31 +923,44 @@ void GL_APIENTRY GL_CopyTexture3DANGLE(GLuint sourceId, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyTexture3DANGLE, - "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, destLevel " - "= %d, internalFormat = %d, destType = %s, unpackFlipY = %s, unpackPremultiplyAlpha = " - "%s, unpackUnmultiplyAlpha = %s", - CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), - destId, destLevel, internalFormat, GLenumToString(GLESEnum::AllEnums, destType), - GLbooleanToString(unpackFlipY), GLbooleanToString(unpackPremultiplyAlpha), - GLbooleanToString(unpackUnmultiplyAlpha)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopyTexture3DANGLE, + "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, " + "destLevel = %d, internalFormat = %d, destType = %s, unpackFlipY = %s, " + "unpackPremultiplyAlpha = %s, unpackUnmultiplyAlpha = %s", + CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), + destId, destLevel, internalFormat, GLenumToString(GLESEnum::AllEnums, destType), + GLbooleanToString(unpackFlipY), GLbooleanToString(unpackPremultiplyAlpha), + GLbooleanToString(unpackUnmultiplyAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID sourceIdPacked = PackParam(sourceId); TextureTarget destTargetPacked = PackParam(destTarget); TextureID destIdPacked = PackParam(destId); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyTexture3DANGLE) && - ValidateCopyTexture3DANGLE( - context, angle::EntryPoint::GLCopyTexture3DANGLE, sourceIdPacked, sourceLevel, - destTargetPacked, destIdPacked, destLevel, internalFormat, destType, unpackFlipY, - unpackPremultiplyAlpha, unpackUnmultiplyAlpha))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyTexture3dANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyTexture3DANGLE( + context, angle::EntryPoint::GLCopyTexture3DANGLE, sourceIdPacked, sourceLevel, + destTargetPacked, destIdPacked, destLevel, internalFormat, destType, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopyTexture3DANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyTexture3D(sourceIdPacked, sourceLevel, destTargetPacked, destIdPacked, destLevel, internalFormat, destType, unpackFlipY, @@ -678,7 +972,7 @@ void GL_APIENTRY GL_CopyTexture3DANGLE(GLuint sourceId, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyTexture3DANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -703,33 +997,46 @@ void GL_APIENTRY GL_CopySubTexture3DANGLE(GLuint sourceId, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopySubTexture3DANGLE, - "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, destLevel " - "= %d, xoffset = %d, yoffset = %d, zoffset = %d, x = %d, y = %d, z = %d, width = %d, " - "height = %d, depth = %d, unpackFlipY = %s, unpackPremultiplyAlpha = %s, " - "unpackUnmultiplyAlpha = %s", - CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), - destId, destLevel, xoffset, yoffset, zoffset, x, y, z, width, height, depth, - GLbooleanToString(unpackFlipY), GLbooleanToString(unpackPremultiplyAlpha), - GLbooleanToString(unpackUnmultiplyAlpha)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopySubTexture3DANGLE, + "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, " + "destLevel = %d, xoffset = %d, yoffset = %d, zoffset = %d, x = %d, y = %d, z = %d, " + "width = %d, height = %d, depth = %d, unpackFlipY = %s, unpackPremultiplyAlpha = %s, " + "unpackUnmultiplyAlpha = %s", + CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), + destId, destLevel, xoffset, yoffset, zoffset, x, y, z, width, height, depth, + GLbooleanToString(unpackFlipY), GLbooleanToString(unpackPremultiplyAlpha), + GLbooleanToString(unpackUnmultiplyAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID sourceIdPacked = PackParam(sourceId); TextureTarget destTargetPacked = PackParam(destTarget); TextureID destIdPacked = PackParam(destId); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopySubTexture3DANGLE) && - ValidateCopySubTexture3DANGLE(context, angle::EntryPoint::GLCopySubTexture3DANGLE, - sourceIdPacked, sourceLevel, destTargetPacked, - destIdPacked, destLevel, xoffset, yoffset, zoffset, x, - y, z, width, height, depth, unpackFlipY, - unpackPremultiplyAlpha, unpackUnmultiplyAlpha))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyTexture3dANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopySubTexture3DANGLE( + context, angle::EntryPoint::GLCopySubTexture3DANGLE, sourceIdPacked, + sourceLevel, destTargetPacked, destIdPacked, destLevel, xoffset, yoffset, + zoffset, x, y, z, width, height, depth, unpackFlipY, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopySubTexture3DANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copySubTexture3D(sourceIdPacked, sourceLevel, destTargetPacked, destIdPacked, destLevel, xoffset, yoffset, zoffset, x, y, z, width, height, @@ -743,7 +1050,7 @@ void GL_APIENTRY GL_CopySubTexture3DANGLE(GLuint sourceId, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopySubTexture3DANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -764,25 +1071,37 @@ void GL_APIENTRY GL_BlitFramebufferANGLE(GLint srcX0, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlitFramebufferANGLE, - "context = %d, srcX0 = %d, srcY0 = %d, srcX1 = %d, srcY1 = %d, dstX0 = %d, dstY0 = %d, " - "dstX1 = %d, dstY1 = %d, mask = %s, filter = %s", - CID(context), srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str(), - GLenumToString(GLESEnum::BlitFramebufferFilter, filter)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlitFramebufferANGLE, + "context = %d, srcX0 = %d, srcY0 = %d, srcX1 = %d, srcY1 = %d, dstX0 = " + "%d, dstY0 = %d, dstX1 = %d, dstY1 = %d, mask = %s, filter = %s", + CID(context), srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str(), + GLenumToString(GLESEnum::BlitFramebufferFilter, filter))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlitFramebufferANGLE) && - ValidateBlitFramebufferANGLE(context, angle::EntryPoint::GLBlitFramebufferANGLE, - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferBlitANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlitFramebufferANGLE( + context, angle::EntryPoint::GLBlitFramebufferANGLE, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlitFramebufferANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); @@ -792,7 +1111,7 @@ void GL_APIENTRY GL_BlitFramebufferANGLE(GLint srcX0, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlitFramebufferANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -806,23 +1125,37 @@ void GL_APIENTRY GL_RenderbufferStorageMultisampleANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRenderbufferStorageMultisampleANGLE, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), samples, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO(EVENT( + context, GLRenderbufferStorageMultisampleANGLE, + "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), samples, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRenderbufferStorageMultisampleANGLE) && - ValidateRenderbufferStorageMultisampleANGLE( - context, angle::EntryPoint::GLRenderbufferStorageMultisampleANGLE, target, - samples, internalformat, width, height))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferMultisampleANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRenderbufferStorageMultisampleANGLE( + context, angle::EntryPoint::GLRenderbufferStorageMultisampleANGLE, target, + samples, internalformat, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLRenderbufferStorageMultisampleANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->renderbufferStorageMultisample(target, samples, internalformat, width, height); } @@ -831,7 +1164,8 @@ void GL_APIENTRY GL_RenderbufferStorageMultisampleANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLRenderbufferStorageMultisampleANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -842,21 +1176,38 @@ GL_GetTexImageANGLE(GLenum target, GLint level, GLenum format, GLenum type, void { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexImageANGLE, - "context = %d, target = %s, level = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR - "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::PixelFormat, format), GLenumToString(GLESEnum::PixelType, type), - (uintptr_t)pixels); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexImageANGLE, + "context = %d, target = %s, level = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::PixelFormat, format), GLenumToString(GLESEnum::PixelType, type), + (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexImageANGLE(context, angle::EntryPoint::GLGetTexImageANGLE, - targetPacked, level, format, type, pixels)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getImageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetTexImageANGLE(context, angle::EntryPoint::GLGetTexImageANGLE, + targetPacked, level, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexImageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexImage(targetPacked, level, format, type, pixels); } @@ -865,7 +1216,7 @@ GL_GetTexImageANGLE(GLenum target, GLint level, GLenum format, GLenum type, void } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexImageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -874,19 +1225,36 @@ void GL_APIENTRY GL_GetCompressedTexImageANGLE(GLenum target, GLint level, void { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetCompressedTexImageANGLE, - "context = %d, target = %s, level = %d, pixels = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), level, (uintptr_t)pixels); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetCompressedTexImageANGLE, + "context = %d, target = %s, level = %d, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetCompressedTexImageANGLE( - context, angle::EntryPoint::GLGetCompressedTexImageANGLE, - targetPacked, level, pixels)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getImageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetCompressedTexImageANGLE( + context, angle::EntryPoint::GLGetCompressedTexImageANGLE, targetPacked, level, + pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetCompressedTexImageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getCompressedTexImage(targetPacked, level, pixels); } @@ -895,7 +1263,8 @@ void GL_APIENTRY GL_GetCompressedTexImageANGLE(GLenum target, GLint level, void } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetCompressedTexImageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -907,20 +1276,37 @@ void GL_APIENTRY GL_GetRenderbufferImageANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetRenderbufferImageANGLE, - "context = %d, target = %s, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), - GLenumToString(GLESEnum::PixelFormat, format), GLenumToString(GLESEnum::PixelType, type), - (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetRenderbufferImageANGLE, + "context = %d, target = %s, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), + GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetRenderbufferImageANGLE( - context, angle::EntryPoint::GLGetRenderbufferImageANGLE, target, - format, type, pixels)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getImageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetRenderbufferImageANGLE( + context, angle::EntryPoint::GLGetRenderbufferImageANGLE, target, format, type, + pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetRenderbufferImageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getRenderbufferImage(target, format, type, pixels); } @@ -929,7 +1315,8 @@ void GL_APIENTRY GL_GetRenderbufferImageANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetRenderbufferImageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -944,20 +1331,37 @@ void GL_APIENTRY GL_GetTexLevelParameterivANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexLevelParameterivANGLE, - "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetTexLevelParameterivANGLE, + "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexLevelParameterivANGLE( - context, angle::EntryPoint::GLGetTexLevelParameterivANGLE, - targetPacked, level, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getTexLevelParameterANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexLevelParameterivANGLE( + context, angle::EntryPoint::GLGetTexLevelParameterivANGLE, targetPacked, level, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexLevelParameterivANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexLevelParameteriv(targetPacked, level, pname, params); } @@ -966,7 +1370,8 @@ void GL_APIENTRY GL_GetTexLevelParameterivANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexLevelParameterivANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -978,20 +1383,37 @@ void GL_APIENTRY GL_GetTexLevelParameterfvANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexLevelParameterfvANGLE, - "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetTexLevelParameterfvANGLE, + "context = %d, target = %s, level = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexLevelParameterfvANGLE( - context, angle::EntryPoint::GLGetTexLevelParameterfvANGLE, - targetPacked, level, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getTexLevelParameterANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexLevelParameterfvANGLE( + context, angle::EntryPoint::GLGetTexLevelParameterfvANGLE, targetPacked, level, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexLevelParameterfvANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexLevelParameterfv(targetPacked, level, pname, params); } @@ -1000,7 +1422,8 @@ void GL_APIENTRY GL_GetTexLevelParameterfvANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexLevelParameterfvANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1013,19 +1436,36 @@ void GL_APIENTRY GL_DrawArraysInstancedANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArraysInstancedANGLE, - "context = %d, mode = %s, first = %d, count = %d, primcount = %d", CID(context), - GLenumToString(GLESEnum::PrimitiveType, mode), first, count, primcount); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawArraysInstancedANGLE, + "context = %d, mode = %s, first = %d, count = %d, primcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), first, + count, primcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawArraysInstancedANGLE( - context, angle::EntryPoint::GLDrawArraysInstancedANGLE, modePacked, - first, count, primcount)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().instancedArraysANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawArraysInstancedANGLE( + context, angle::EntryPoint::GLDrawArraysInstancedANGLE, modePacked, first, + count, primcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawArraysInstancedANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawArraysInstanced(modePacked, first, count, primcount); } @@ -1034,7 +1474,8 @@ void GL_APIENTRY GL_DrawArraysInstancedANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawArraysInstancedANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1047,22 +1488,39 @@ void GL_APIENTRY GL_DrawElementsInstancedANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedANGLE, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", primcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::PrimitiveType, type), (uintptr_t)indices, primcount); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedANGLE, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", primcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, primcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsInstancedANGLE( - context, angle::EntryPoint::GLDrawElementsInstancedANGLE, - modePacked, count, typePacked, indices, primcount)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().instancedArraysANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedANGLE( + context, angle::EntryPoint::GLDrawElementsInstancedANGLE, modePacked, count, + typePacked, indices, primcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawElementsInstancedANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstanced(modePacked, count, typePacked, indices, primcount); } @@ -1071,7 +1529,8 @@ void GL_APIENTRY GL_DrawElementsInstancedANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1080,25 +1539,44 @@ void GL_APIENTRY GL_VertexAttribDivisorANGLE(GLuint index, GLuint divisor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribDivisorANGLE, "context = %d, index = %u, divisor = %u", - CID(context), index, divisor); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribDivisorANGLE, + "context = %d, index = %u, divisor = %u", CID(context), index, + divisor)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribDivisorANGLE( - context, angle::EntryPoint::GLVertexAttribDivisorANGLE, index, divisor)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->vertexAttribDivisor(index, divisor); + if (ANGLE_LIKELY(context->getExtensions().instancedArraysANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribDivisorANGLE( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribDivisorANGLE, index, divisor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLVertexAttribDivisorANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateVertexAttribDivisor(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index, + divisor); } ANGLE_CAPTURE_GL(VertexAttribDivisorANGLE, isCallValid, context, index, divisor); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLVertexAttribDivisorANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1108,21 +1586,33 @@ void GL_APIENTRY GL_LogicOpANGLE(GLenum opcode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLogicOpANGLE, "context = %d, opcode = %s", CID(context), - GLenumToString(GLESEnum::LogicOp, opcode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLLogicOpANGLE, "context = %d, opcode = %s", CID(context), + GLenumToString(GLESEnum::LogicOp, opcode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { LogicalOperation opcodePacked = PackParam(opcode); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLogicOpANGLE) && - ValidateLogicOpANGLE(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLogicOpANGLE, opcodePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().logicOpANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLogicOpANGLE(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLLogicOpANGLE, opcodePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLLogicOpANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateLogicOpANGLE(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), opcodePacked); @@ -1131,7 +1621,7 @@ void GL_APIENTRY GL_LogicOpANGLE(GLenum opcode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLogicOpANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1152,32 +1642,44 @@ void GL_APIENTRY GL_TexStorageMemFlags2DANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMemFlags2DANGLE, - "context = %d, target = %s, levels = %d, internalFormat = %s, width = %d, height = %d, " - "memory = %u, offset = %llu, createFlags = %s, usageFlags = %s, imageCreateInfoPNext = " - "0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, memory, - static_cast(offset), - GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), - GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), - (uintptr_t)imageCreateInfoPNext); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorageMemFlags2DANGLE, + "context = %d, target = %s, levels = %d, internalFormat = %s, width = " + "%d, height = %d, memory = %u, offset = %llu, createFlags = %s, " + "usageFlags = %s, imageCreateInfoPNext = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, + memory, static_cast(offset), + GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), + GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), + (uintptr_t)imageCreateInfoPNext)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMemFlags2DANGLE) && - ValidateTexStorageMemFlags2DANGLE( - context, angle::EntryPoint::GLTexStorageMemFlags2DANGLE, targetPacked, levels, - internalFormat, width, height, memoryPacked, offset, createFlags, usageFlags, - imageCreateInfoPNext))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectFlagsANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMemFlags2DANGLE( + context, angle::EntryPoint::GLTexStorageMemFlags2DANGLE, targetPacked, levels, + internalFormat, width, height, memoryPacked, offset, createFlags, usageFlags, + imageCreateInfoPNext); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorageMemFlags2DANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMemFlags2D(targetPacked, levels, internalFormat, width, height, memoryPacked, offset, createFlags, usageFlags, @@ -1189,7 +1691,8 @@ void GL_APIENTRY GL_TexStorageMemFlags2DANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorageMemFlags2DANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1208,32 +1711,46 @@ void GL_APIENTRY GL_TexStorageMemFlags2DMultisampleANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMemFlags2DMultisampleANGLE, - "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " - "fixedSampleLocations = %s, memory = %u, offset = %llu, createFlags = %s, usageFlags = " - "%s, imageCreateInfoPNext = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, - GLbooleanToString(fixedSampleLocations), memory, static_cast(offset), - GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), - GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), - (uintptr_t)imageCreateInfoPNext); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexStorageMemFlags2DMultisampleANGLE, + "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " + "fixedSampleLocations = %s, memory = %u, offset = %llu, createFlags = %s, usageFlags = %s, " + "imageCreateInfoPNext = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, + GLbooleanToString(fixedSampleLocations), memory, static_cast(offset), + GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), + GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), + (uintptr_t)imageCreateInfoPNext)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMemFlags2DMultisampleANGLE) && - ValidateTexStorageMemFlags2DMultisampleANGLE( - context, angle::EntryPoint::GLTexStorageMemFlags2DMultisampleANGLE, targetPacked, - samples, internalFormat, width, height, fixedSampleLocations, memoryPacked, - offset, createFlags, usageFlags, imageCreateInfoPNext))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectFlagsANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMemFlags2DMultisampleANGLE( + context, angle::EntryPoint::GLTexStorageMemFlags2DMultisampleANGLE, + targetPacked, samples, internalFormat, width, height, fixedSampleLocations, + memoryPacked, offset, createFlags, usageFlags, imageCreateInfoPNext); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLTexStorageMemFlags2DMultisampleANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMemFlags2DMultisample( targetPacked, samples, internalFormat, width, height, fixedSampleLocations, @@ -1245,7 +1762,8 @@ void GL_APIENTRY GL_TexStorageMemFlags2DMultisampleANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorageMemFlags2DMultisampleANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1264,32 +1782,44 @@ void GL_APIENTRY GL_TexStorageMemFlags3DANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMemFlags3DANGLE, - "context = %d, target = %s, levels = %d, internalFormat = %s, width = %d, height = %d, " - "depth = %d, memory = %u, offset = %llu, createFlags = %s, usageFlags = %s, " - "imageCreateInfoPNext = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, depth, memory, - static_cast(offset), - GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), - GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), - (uintptr_t)imageCreateInfoPNext); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorageMemFlags3DANGLE, + "context = %d, target = %s, levels = %d, internalFormat = %s, width = " + "%d, height = %d, depth = %d, memory = %u, offset = %llu, createFlags " + "= %s, usageFlags = %s, imageCreateInfoPNext = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, + depth, memory, static_cast(offset), + GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), + GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), + (uintptr_t)imageCreateInfoPNext)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMemFlags3DANGLE) && - ValidateTexStorageMemFlags3DANGLE( - context, angle::EntryPoint::GLTexStorageMemFlags3DANGLE, targetPacked, levels, - internalFormat, width, height, depth, memoryPacked, offset, createFlags, - usageFlags, imageCreateInfoPNext))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectFlagsANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMemFlags3DANGLE( + context, angle::EntryPoint::GLTexStorageMemFlags3DANGLE, targetPacked, levels, + internalFormat, width, height, depth, memoryPacked, offset, createFlags, + usageFlags, imageCreateInfoPNext); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorageMemFlags3DANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMemFlags3D(targetPacked, levels, internalFormat, width, height, depth, memoryPacked, offset, createFlags, usageFlags, @@ -1301,7 +1831,8 @@ void GL_APIENTRY GL_TexStorageMemFlags3DANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorageMemFlags3DANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1321,32 +1852,47 @@ void GL_APIENTRY GL_TexStorageMemFlags3DMultisampleANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMemFlags3DMultisampleANGLE, - "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " - "depth = %d, fixedSampleLocations = %s, memory = %u, offset = %llu, createFlags = %s, " - "usageFlags = %s, imageCreateInfoPNext = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, depth, - GLbooleanToString(fixedSampleLocations), memory, static_cast(offset), - GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), - GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), - (uintptr_t)imageCreateInfoPNext); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexStorageMemFlags3DMultisampleANGLE, + "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " + "depth = %d, fixedSampleLocations = %s, memory = %u, offset = %llu, createFlags = %s, " + "usageFlags = %s, imageCreateInfoPNext = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::AllEnums, internalFormat), width, height, depth, + GLbooleanToString(fixedSampleLocations), memory, static_cast(offset), + GLbitfieldToString(GLESEnum::AllEnums, createFlags).c_str(), + GLbitfieldToString(GLESEnum::AllEnums, usageFlags).c_str(), + (uintptr_t)imageCreateInfoPNext)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMemFlags3DMultisampleANGLE) && - ValidateTexStorageMemFlags3DMultisampleANGLE( - context, angle::EntryPoint::GLTexStorageMemFlags3DMultisampleANGLE, targetPacked, - samples, internalFormat, width, height, depth, fixedSampleLocations, memoryPacked, - offset, createFlags, usageFlags, imageCreateInfoPNext))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectFlagsANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMemFlags3DMultisampleANGLE( + context, angle::EntryPoint::GLTexStorageMemFlags3DMultisampleANGLE, + targetPacked, samples, internalFormat, width, height, depth, + fixedSampleLocations, memoryPacked, offset, createFlags, usageFlags, + imageCreateInfoPNext); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLTexStorageMemFlags3DMultisampleANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMemFlags3DMultisample( targetPacked, samples, internalFormat, width, height, depth, fixedSampleLocations, @@ -1358,7 +1904,8 @@ void GL_APIENTRY GL_TexStorageMemFlags3DMultisampleANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorageMemFlags3DMultisampleANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1371,25 +1918,38 @@ void GL_APIENTRY GL_ImportMemoryZirconHandleANGLE(GLuint memory, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLImportMemoryZirconHandleANGLE, - "context = %d, memory = %u, size = %llu, handleType = %s, handle = %u", CID(context), - memory, static_cast(size), - GLenumToString(GLESEnum::ExternalHandleType, handleType), handle); + ANGLE_UNSAFE_TODO(EVENT(context, GLImportMemoryZirconHandleANGLE, + "context = %d, memory = %u, size = %llu, handleType = %s, handle = %u", + CID(context), memory, static_cast(size), + GLenumToString(GLESEnum::ExternalHandleType, handleType), handle)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MemoryObjectID memoryPacked = PackParam(memory); HandleType handleTypePacked = PackParam(handleType); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLImportMemoryZirconHandleANGLE) && - ValidateImportMemoryZirconHandleANGLE( - context, angle::EntryPoint::GLImportMemoryZirconHandleANGLE, memoryPacked, size, - handleTypePacked, handle))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectFuchsiaANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateImportMemoryZirconHandleANGLE( + context, angle::EntryPoint::GLImportMemoryZirconHandleANGLE, memoryPacked, size, + handleTypePacked, handle); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLImportMemoryZirconHandleANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->importMemoryZirconHandle(memoryPacked, size, handleTypePacked, handle); } @@ -1398,7 +1958,8 @@ void GL_APIENTRY GL_ImportMemoryZirconHandleANGLE(GLuint memory, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLImportMemoryZirconHandleANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1413,24 +1974,37 @@ void GL_APIENTRY GL_MultiDrawArraysANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawArraysANGLE, - "context = %d, mode = %s, firsts = 0x%016" PRIxPTR ", counts = 0x%016" PRIxPTR - ", drawcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)firsts, - (uintptr_t)counts, drawcount); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawArraysANGLE, + "context = %d, mode = %s, firsts = 0x%016" PRIxPTR + ", counts = 0x%016" PRIxPTR ", drawcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)firsts, (uintptr_t)counts, drawcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawArraysANGLE) && - ValidateMultiDrawArraysANGLE(context, angle::EntryPoint::GLMultiDrawArraysANGLE, - modePacked, firsts, counts, drawcount))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateMultiDrawArraysANGLE(context, angle::EntryPoint::GLMultiDrawArraysANGLE, + modePacked, firsts, counts, drawcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMultiDrawArraysANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawArrays(modePacked, firsts, counts, drawcount); } @@ -1439,7 +2013,7 @@ void GL_APIENTRY GL_MultiDrawArraysANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultiDrawArraysANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1452,25 +2026,39 @@ void GL_APIENTRY GL_MultiDrawArraysInstancedANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawArraysInstancedANGLE, - "context = %d, mode = %s, firsts = 0x%016" PRIxPTR ", counts = 0x%016" PRIxPTR - ", instanceCounts = 0x%016" PRIxPTR ", drawcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)firsts, - (uintptr_t)counts, (uintptr_t)instanceCounts, drawcount); + ANGLE_UNSAFE_TODO( + EVENT(context, GLMultiDrawArraysInstancedANGLE, + "context = %d, mode = %s, firsts = 0x%016" PRIxPTR ", counts = 0x%016" PRIxPTR + ", instanceCounts = 0x%016" PRIxPTR ", drawcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)firsts, + (uintptr_t)counts, (uintptr_t)instanceCounts, drawcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawArraysInstancedANGLE) && - ValidateMultiDrawArraysInstancedANGLE( - context, angle::EntryPoint::GLMultiDrawArraysInstancedANGLE, modePacked, firsts, - counts, instanceCounts, drawcount))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawArraysInstancedANGLE( + context, angle::EntryPoint::GLMultiDrawArraysInstancedANGLE, modePacked, firsts, + counts, instanceCounts, drawcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLMultiDrawArraysInstancedANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawArraysInstanced(modePacked, firsts, counts, instanceCounts, drawcount); @@ -1480,7 +2068,8 @@ void GL_APIENTRY GL_MultiDrawArraysInstancedANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawArraysInstancedANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1493,25 +2082,39 @@ void GL_APIENTRY GL_MultiDrawElementsANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawElementsANGLE, - "context = %d, mode = %s, counts = 0x%016" PRIxPTR ", type = %s, indices = 0x%016" PRIxPTR - ", drawcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)counts, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, drawcount); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawElementsANGLE, + "context = %d, mode = %s, counts = 0x%016" PRIxPTR + ", type = %s, indices = 0x%016" PRIxPTR ", drawcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)counts, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, drawcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawElementsANGLE) && - ValidateMultiDrawElementsANGLE(context, angle::EntryPoint::GLMultiDrawElementsANGLE, - modePacked, counts, typePacked, indices, drawcount))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawElementsANGLE( + context, angle::EntryPoint::GLMultiDrawElementsANGLE, modePacked, counts, + typePacked, indices, drawcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMultiDrawElementsANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawElements(modePacked, counts, typePacked, indices, drawcount); } @@ -1520,7 +2123,7 @@ void GL_APIENTRY GL_MultiDrawElementsANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultiDrawElementsANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1534,27 +2137,41 @@ void GL_APIENTRY GL_MultiDrawElementsInstancedANGLE(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawElementsInstancedANGLE, - "context = %d, mode = %s, counts = 0x%016" PRIxPTR ", type = %s, indices = 0x%016" PRIxPTR - ", instanceCounts = 0x%016" PRIxPTR ", drawcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)counts, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, - (uintptr_t)instanceCounts, drawcount); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawElementsInstancedANGLE, + "context = %d, mode = %s, counts = 0x%016" PRIxPTR + ", type = %s, indices = 0x%016" PRIxPTR + ", instanceCounts = 0x%016" PRIxPTR ", drawcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)counts, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, (uintptr_t)instanceCounts, drawcount)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawElementsInstancedANGLE) && - ValidateMultiDrawElementsInstancedANGLE( - context, angle::EntryPoint::GLMultiDrawElementsInstancedANGLE, modePacked, counts, - typePacked, indices, instanceCounts, drawcount))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawElementsInstancedANGLE( + context, angle::EntryPoint::GLMultiDrawElementsInstancedANGLE, modePacked, + counts, typePacked, indices, instanceCounts, drawcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLMultiDrawElementsInstancedANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawElementsInstanced(modePacked, counts, typePacked, indices, instanceCounts, drawcount); @@ -1564,7 +2181,8 @@ void GL_APIENTRY GL_MultiDrawElementsInstancedANGLE(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawElementsInstancedANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1576,19 +2194,34 @@ void GL_APIENTRY GL_PolygonModeANGLE(GLenum face, GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPolygonModeANGLE, "context = %d, face = %s, mode = %s", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::PolygonMode, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPolygonModeANGLE, "context = %d, face = %s, mode = %s", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::PolygonMode, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PolygonMode modePacked = PackParam(mode); - bool isCallValid = - (context->skipValidation() || - ValidatePolygonModeANGLE(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPolygonModeANGLE, face, modePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().polygonModeANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePolygonModeANGLE( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPolygonModeANGLE, face, modePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPolygonModeANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePolygonMode(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, modePacked); @@ -1597,7 +2230,7 @@ void GL_APIENTRY GL_PolygonModeANGLE(GLenum face, GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPolygonModeANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1613,19 +2246,35 @@ void GL_APIENTRY GL_ProvokingVertexANGLE(GLenum provokeMode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProvokingVertexANGLE, "context = %d, provokeMode = %s", CID(context), - GLenumToString(GLESEnum::VertexProvokingMode, provokeMode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLProvokingVertexANGLE, "context = %d, provokeMode = %s", + CID(context), + GLenumToString(GLESEnum::VertexProvokingMode, provokeMode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProvokingVertexConvention provokeModePacked = PackParam(provokeMode); - bool isCallValid = - (context->skipValidation() || - ValidateProvokingVertexANGLE( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProvokingVertexANGLE, provokeModePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().provokingVertexANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProvokingVertexANGLE( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLProvokingVertexANGLE, provokeModePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProvokingVertexANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateProvokingVertex(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), @@ -1635,7 +2284,7 @@ void GL_APIENTRY GL_ProvokingVertexANGLE(GLenum provokeMode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProvokingVertexANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1647,20 +2296,33 @@ void GL_APIENTRY GL_RequestExtensionANGLE(const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRequestExtensionANGLE, "context = %d, name = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLRequestExtensionANGLE, + "context = %d, name = 0x%016" PRIxPTR "", CID(context), + (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRequestExtensionANGLE) && - ValidateRequestExtensionANGLE(context, angle::EntryPoint::GLRequestExtensionANGLE, - name))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().requestExtensionANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRequestExtensionANGLE( + context, angle::EntryPoint::GLRequestExtensionANGLE, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLRequestExtensionANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->requestExtension(name); } @@ -1668,7 +2330,7 @@ void GL_APIENTRY GL_RequestExtensionANGLE(const GLchar *name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLRequestExtensionANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1677,20 +2339,33 @@ void GL_APIENTRY GL_DisableExtensionANGLE(const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisableExtensionANGLE, "context = %d, name = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisableExtensionANGLE, + "context = %d, name = 0x%016" PRIxPTR "", CID(context), + (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDisableExtensionANGLE) && - ValidateDisableExtensionANGLE(context, angle::EntryPoint::GLDisableExtensionANGLE, - name))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().requestExtensionANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisableExtensionANGLE( + context, angle::EntryPoint::GLDisableExtensionANGLE, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDisableExtensionANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->disableExtension(name); } @@ -1698,7 +2373,7 @@ void GL_APIENTRY GL_DisableExtensionANGLE(const GLchar *name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDisableExtensionANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1713,20 +2388,36 @@ void GL_APIENTRY GL_GetBooleanvRobustANGLE(GLenum pname, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBooleanvRobustANGLE, - "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetBooleanvRobustANGLE, + "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetBooleanvRobustANGLE(context, angle::EntryPoint::GLGetBooleanvRobustANGLE, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBooleanvRobustANGLE( + context, angle::EntryPoint::GLGetBooleanvRobustANGLE, pname, bufSize, length, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetBooleanvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBooleanvRobust(pname, bufSize, length, params); } @@ -1735,7 +2426,7 @@ void GL_APIENTRY GL_GetBooleanvRobustANGLE(GLenum pname, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBooleanvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1748,21 +2439,39 @@ void GL_APIENTRY GL_GetBufferParameterivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferParameterivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetBufferParameterivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetBufferParameterivRobustANGLE( - context, angle::EntryPoint::GLGetBufferParameterivRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBufferParameterivRobustANGLE( + context, angle::EntryPoint::GLGetBufferParameterivRobustANGLE, targetPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetBufferParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferParameterivRobust(targetPacked, pname, bufSize, length, params); } @@ -1771,7 +2480,8 @@ void GL_APIENTRY GL_GetBufferParameterivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetBufferParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1783,20 +2493,36 @@ void GL_APIENTRY GL_GetFloatvRobustANGLE(GLenum pname, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFloatvRobustANGLE, - "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFloatvRobustANGLE, + "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFloatvRobustANGLE(context, angle::EntryPoint::GLGetFloatvRobustANGLE, pname, - bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetFloatvRobustANGLE(context, angle::EntryPoint::GLGetFloatvRobustANGLE, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetFloatvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFloatvRobust(pname, bufSize, length, params); } @@ -1805,7 +2531,7 @@ void GL_APIENTRY GL_GetFloatvRobustANGLE(GLenum pname, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetFloatvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1819,22 +2545,39 @@ void GL_APIENTRY GL_GetFramebufferAttachmentParameterivRobustANGLE(GLenum target { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferAttachmentParameterivRobustANGLE, - "context = %d, target = %s, attachment = %s, pname = %s, bufSize = %d, length = " - "0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, attachment), GLenumToString(GLESEnum::AllEnums, pname), - bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFramebufferAttachmentParameterivRobustANGLE, + "context = %d, target = %s, attachment = %s, pname = %s, bufSize = %d, " + "length = 0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, attachment), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferAttachmentParameterivRobustANGLE( - context, angle::EntryPoint::GLGetFramebufferAttachmentParameterivRobustANGLE, - target, attachment, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferAttachmentParameterivRobustANGLE( + context, angle::EntryPoint::GLGetFramebufferAttachmentParameterivRobustANGLE, + target, attachment, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLGetFramebufferAttachmentParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferAttachmentParameterivRobust(target, attachment, pname, bufSize, length, params); @@ -1844,7 +2587,8 @@ void GL_APIENTRY GL_GetFramebufferAttachmentParameterivRobustANGLE(GLenum target } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferAttachmentParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1856,20 +2600,36 @@ void GL_APIENTRY GL_GetIntegervRobustANGLE(GLenum pname, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetIntegervRobustANGLE, - "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetIntegervRobustANGLE, + "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetIntegervRobustANGLE(context, angle::EntryPoint::GLGetIntegervRobustANGLE, - pname, bufSize, length, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetIntegervRobustANGLE( + context, angle::EntryPoint::GLGetIntegervRobustANGLE, pname, bufSize, length, + data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetIntegervRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getIntegervRobust(pname, bufSize, length, data); } @@ -1878,7 +2638,7 @@ void GL_APIENTRY GL_GetIntegervRobustANGLE(GLenum pname, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetIntegervRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1891,21 +2651,38 @@ void GL_APIENTRY GL_GetProgramivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetProgramivRobustANGLE, - "context = %d, program = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetProgramivRobustANGLE, + "context = %d, program = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramivRobustANGLE(context, angle::EntryPoint::GLGetProgramivRobustANGLE, - programPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramivRobustANGLE( + context, angle::EntryPoint::GLGetProgramivRobustANGLE, programPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetProgramivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramivRobust(programPacked, pname, bufSize, length, params); } @@ -1926,20 +2703,38 @@ void GL_APIENTRY GL_GetRenderbufferParameterivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetRenderbufferParameterivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetRenderbufferParameterivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetRenderbufferParameterivRobustANGLE( - context, angle::EntryPoint::GLGetRenderbufferParameterivRobustANGLE, - target, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetRenderbufferParameterivRobustANGLE( + context, angle::EntryPoint::GLGetRenderbufferParameterivRobustANGLE, target, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetRenderbufferParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getRenderbufferParameterivRobust(target, pname, bufSize, length, params); } @@ -1948,7 +2743,8 @@ void GL_APIENTRY GL_GetRenderbufferParameterivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetRenderbufferParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -1961,21 +2757,38 @@ void GL_APIENTRY GL_GetShaderivRobustANGLE(GLuint shader, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetShaderivRobustANGLE, - "context = %d, shader = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), shader, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetShaderivRobustANGLE, + "context = %d, shader = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), shader, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetShaderivRobustANGLE(context, angle::EntryPoint::GLGetShaderivRobustANGLE, - shaderPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetShaderivRobustANGLE( + context, angle::EntryPoint::GLGetShaderivRobustANGLE, shaderPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetShaderivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getShaderivRobust(shaderPacked, pname, bufSize, length, params); } @@ -1996,21 +2809,38 @@ void GL_APIENTRY GL_GetTexParameterfvRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterfvRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexParameterfvRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexParameterfvRobustANGLE( - context, angle::EntryPoint::GLGetTexParameterfvRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterfvRobustANGLE( + context, angle::EntryPoint::GLGetTexParameterfvRobustANGLE, targetPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexParameterfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterfvRobust(targetPacked, pname, bufSize, length, params); } @@ -2019,7 +2849,8 @@ void GL_APIENTRY GL_GetTexParameterfvRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexParameterfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2032,21 +2863,38 @@ void GL_APIENTRY GL_GetTexParameterivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexParameterivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexParameterivRobustANGLE( - context, angle::EntryPoint::GLGetTexParameterivRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterivRobustANGLE( + context, angle::EntryPoint::GLGetTexParameterivRobustANGLE, targetPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterivRobust(targetPacked, pname, bufSize, length, params); } @@ -2055,7 +2903,8 @@ void GL_APIENTRY GL_GetTexParameterivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2068,21 +2917,38 @@ void GL_APIENTRY GL_GetUniformfvRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformfvRobustANGLE, - "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetUniformfvRobustANGLE, + "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUniformfvRobustANGLE( - context, angle::EntryPoint::GLGetUniformfvRobustANGLE, - programPacked, locationPacked, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformfvRobustANGLE( + context, angle::EntryPoint::GLGetUniformfvRobustANGLE, programPacked, + locationPacked, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetUniformfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformfvRobust(programPacked, locationPacked, bufSize, length, params); } @@ -2091,7 +2957,8 @@ void GL_APIENTRY GL_GetUniformfvRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetUniformfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2104,21 +2971,38 @@ void GL_APIENTRY GL_GetUniformivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformivRobustANGLE, - "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetUniformivRobustANGLE, + "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUniformivRobustANGLE( - context, angle::EntryPoint::GLGetUniformivRobustANGLE, - programPacked, locationPacked, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformivRobustANGLE( + context, angle::EntryPoint::GLGetUniformivRobustANGLE, programPacked, + locationPacked, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetUniformivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformivRobust(programPacked, locationPacked, bufSize, length, params); } @@ -2127,7 +3011,8 @@ void GL_APIENTRY GL_GetUniformivRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetUniformivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2140,20 +3025,37 @@ void GL_APIENTRY GL_GetVertexAttribfvRobustANGLE(GLuint index, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribfvRobustANGLE, - "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetVertexAttribfvRobustANGLE, + "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetVertexAttribfvRobustANGLE( - context, angle::EntryPoint::GLGetVertexAttribfvRobustANGLE, index, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribfvRobustANGLE( + context, angle::EntryPoint::GLGetVertexAttribfvRobustANGLE, index, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetVertexAttribfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribfvRobust(index, pname, bufSize, length, params); } @@ -2162,7 +3064,8 @@ void GL_APIENTRY GL_GetVertexAttribfvRobustANGLE(GLuint index, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetVertexAttribfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2175,20 +3078,37 @@ void GL_APIENTRY GL_GetVertexAttribivRobustANGLE(GLuint index, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribivRobustANGLE, - "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetVertexAttribivRobustANGLE, + "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetVertexAttribivRobustANGLE( - context, angle::EntryPoint::GLGetVertexAttribivRobustANGLE, index, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribivRobustANGLE( + context, angle::EntryPoint::GLGetVertexAttribivRobustANGLE, index, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetVertexAttribivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribivRobust(index, pname, bufSize, length, params); } @@ -2197,7 +3117,8 @@ void GL_APIENTRY GL_GetVertexAttribivRobustANGLE(GLuint index, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetVertexAttribivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2210,20 +3131,38 @@ void GL_APIENTRY GL_GetVertexAttribPointervRobustANGLE(GLuint index, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribPointervRobustANGLE, - "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", pointer = 0x%016" PRIxPTR "", - CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)pointer); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetVertexAttribPointervRobustANGLE, + "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", pointer = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetVertexAttribPointervRobustANGLE( - context, angle::EntryPoint::GLGetVertexAttribPointervRobustANGLE, - index, pname, bufSize, length, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribPointervRobustANGLE( + context, angle::EntryPoint::GLGetVertexAttribPointervRobustANGLE, index, pname, + bufSize, length, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetVertexAttribPointervRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribPointervRobust(index, pname, bufSize, length, pointer); } @@ -2232,7 +3171,8 @@ void GL_APIENTRY GL_GetVertexAttribPointervRobustANGLE(GLuint index, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetVertexAttribPointervRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2251,26 +3191,39 @@ void GL_APIENTRY GL_ReadPixelsRobustANGLE(GLint x, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadPixelsRobustANGLE, - "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, bufSize " - "= %d, length = 0x%016" PRIxPTR ", columns = 0x%016" PRIxPTR ", rows = 0x%016" PRIxPTR - ", pixels = 0x%016" PRIxPTR "", - CID(context), x, y, width, height, GLenumToString(GLESEnum::AllEnums, format), - GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)length, (uintptr_t)columns, - (uintptr_t)rows, (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLReadPixelsRobustANGLE, + "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, " + "bufSize = %d, length = 0x%016" PRIxPTR ", columns = 0x%016" PRIxPTR + ", rows = 0x%016" PRIxPTR ", pixels = 0x%016" PRIxPTR "", + CID(context), x, y, width, height, GLenumToString(GLESEnum::AllEnums, format), + GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)length, + (uintptr_t)columns, (uintptr_t)rows, (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadPixelsRobustANGLE) && - ValidateReadPixelsRobustANGLE(context, angle::EntryPoint::GLReadPixelsRobustANGLE, x, - y, width, height, format, type, bufSize, length, - columns, rows, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateReadPixelsRobustANGLE( + context, angle::EntryPoint::GLReadPixelsRobustANGLE, x, y, width, height, + format, type, bufSize, length, columns, rows, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLReadPixelsRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readPixelsRobust(x, y, width, height, format, type, bufSize, length, columns, rows, pixels); @@ -2280,7 +3233,7 @@ void GL_APIENTRY GL_ReadPixelsRobustANGLE(GLint x, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadPixelsRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2298,26 +3251,39 @@ void GL_APIENTRY GL_TexImage2DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexImage2DRobustANGLE, - "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, " - "border = %d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, internalformat, width, - height, border, GLenumToString(GLESEnum::AllEnums, format), - GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexImage2DRobustANGLE, + "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = " + "%d, border = %d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, internalformat, + width, height, border, GLenumToString(GLESEnum::AllEnums, format), + GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexImage2DRobustANGLE) && - ValidateTexImage2DRobustANGLE(context, angle::EntryPoint::GLTexImage2DRobustANGLE, - targetPacked, level, internalformat, width, height, - border, format, type, bufSize, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexImage2DRobustANGLE( + context, angle::EntryPoint::GLTexImage2DRobustANGLE, targetPacked, level, + internalformat, width, height, border, format, type, bufSize, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexImage2DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texImage2DRobust(targetPacked, level, internalformat, width, height, border, format, type, bufSize, pixels); @@ -2327,7 +3293,7 @@ void GL_APIENTRY GL_TexImage2DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexImage2DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2339,20 +3305,37 @@ void GL_APIENTRY GL_TexParameterfvRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterfvRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexParameterfvRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterfvRobustANGLE( - context, angle::EntryPoint::GLTexParameterfvRobustANGLE, - targetPacked, pname, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterfvRobustANGLE( + context, angle::EntryPoint::GLTexParameterfvRobustANGLE, targetPacked, pname, + bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterfvRobust(targetPacked, pname, bufSize, params); } @@ -2361,7 +3344,8 @@ void GL_APIENTRY GL_TexParameterfvRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexParameterfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2373,20 +3357,37 @@ void GL_APIENTRY GL_TexParameterivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexParameterivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterivRobustANGLE( - context, angle::EntryPoint::GLTexParameterivRobustANGLE, - targetPacked, pname, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterivRobustANGLE( + context, angle::EntryPoint::GLTexParameterivRobustANGLE, targetPacked, pname, + bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterivRobust(targetPacked, pname, bufSize, params); } @@ -2395,7 +3396,8 @@ void GL_APIENTRY GL_TexParameterivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2413,26 +3415,39 @@ void GL_APIENTRY GL_TexSubImage2DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexSubImage2DRobustANGLE, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = " - "%d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, width, - height, GLenumToString(GLESEnum::AllEnums, format), - GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexSubImage2DRobustANGLE, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, " + "height = %d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, + width, height, GLenumToString(GLESEnum::AllEnums, format), + GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexSubImage2DRobustANGLE) && - ValidateTexSubImage2DRobustANGLE( - context, angle::EntryPoint::GLTexSubImage2DRobustANGLE, targetPacked, level, - xoffset, yoffset, width, height, format, type, bufSize, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexSubImage2DRobustANGLE( + context, angle::EntryPoint::GLTexSubImage2DRobustANGLE, targetPacked, level, + xoffset, yoffset, width, height, format, type, bufSize, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexSubImage2DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texSubImage2DRobust(targetPacked, level, xoffset, yoffset, width, height, format, type, bufSize, pixels); @@ -2442,7 +3457,8 @@ void GL_APIENTRY GL_TexSubImage2DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexSubImage2DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2461,27 +3477,39 @@ void GL_APIENTRY GL_TexImage3DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexImage3DRobustANGLE, - "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, " - "depth = %d, border = %d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR - "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, internalformat, width, - height, depth, border, GLenumToString(GLESEnum::AllEnums, format), - GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexImage3DRobustANGLE, + "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, " + "depth = %d, border = %d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, internalformat, width, + height, depth, border, GLenumToString(GLESEnum::AllEnums, format), + GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexImage3DRobustANGLE) && - ValidateTexImage3DRobustANGLE(context, angle::EntryPoint::GLTexImage3DRobustANGLE, - targetPacked, level, internalformat, width, height, - depth, border, format, type, bufSize, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexImage3DRobustANGLE( + context, angle::EntryPoint::GLTexImage3DRobustANGLE, targetPacked, level, + internalformat, width, height, depth, border, format, type, bufSize, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexImage3DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texImage3DRobust(targetPacked, level, internalformat, width, height, depth, border, format, type, bufSize, pixels); @@ -2492,7 +3520,7 @@ void GL_APIENTRY GL_TexImage3DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexImage3DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2512,28 +3540,40 @@ void GL_APIENTRY GL_TexSubImage3DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT( + ANGLE_UNSAFE_TODO(EVENT( context, GLTexSubImage3DRobustANGLE, "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width = " "%d, height = %d, depth = %d, format = %s, type = %s, bufSize = %d, pixels = 0x%016" PRIxPTR "", CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, zoffset, width, height, depth, GLenumToString(GLESEnum::AllEnums, format), - GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels); + GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexSubImage3DRobustANGLE) && - ValidateTexSubImage3DRobustANGLE( - context, angle::EntryPoint::GLTexSubImage3DRobustANGLE, targetPacked, level, - xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexSubImage3DRobustANGLE( + context, angle::EntryPoint::GLTexSubImage3DRobustANGLE, targetPacked, level, + xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexSubImage3DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texSubImage3DRobust(targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize, pixels); @@ -2544,7 +3584,8 @@ void GL_APIENTRY GL_TexSubImage3DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexSubImage3DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2561,26 +3602,40 @@ void GL_APIENTRY GL_CompressedTexImage2DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexImage2DRobustANGLE, - "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " - "border = %d, imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, - GLenumToString(GLESEnum::AllEnums, internalformat), width, height, border, imageSize, - dataSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCompressedTexImage2DRobustANGLE, + "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = " + "%d, border = %d, imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + GLenumToString(GLESEnum::AllEnums, internalformat), width, height, border, imageSize, + dataSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexImage2DRobustANGLE) && - ValidateCompressedTexImage2DRobustANGLE( - context, angle::EntryPoint::GLCompressedTexImage2DRobustANGLE, targetPacked, - level, internalformat, width, height, border, imageSize, dataSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexImage2DRobustANGLE( + context, angle::EntryPoint::GLCompressedTexImage2DRobustANGLE, targetPacked, + level, internalformat, width, height, border, imageSize, dataSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLCompressedTexImage2DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexImage2DRobust(targetPacked, level, internalformat, width, height, border, imageSize, dataSize, data); @@ -2590,7 +3645,8 @@ void GL_APIENTRY GL_CompressedTexImage2DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexImage2DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2608,25 +3664,39 @@ void GL_APIENTRY GL_CompressedTexSubImage2DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexSubImage2DRobustANGLE, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = " - "%d, format = %s, imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, width, - height, GLenumToString(GLESEnum::AllEnums, format), imageSize, dataSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLCompressedTexSubImage2DRobustANGLE, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = " + "%d, format = %s, imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, width, + height, GLenumToString(GLESEnum::AllEnums, format), imageSize, dataSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexSubImage2DRobustANGLE) && - ValidateCompressedTexSubImage2DRobustANGLE( - context, angle::EntryPoint::GLCompressedTexSubImage2DRobustANGLE, targetPacked, - level, xoffset, yoffset, width, height, format, imageSize, dataSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexSubImage2DRobustANGLE( + context, angle::EntryPoint::GLCompressedTexSubImage2DRobustANGLE, targetPacked, + level, xoffset, yoffset, width, height, format, imageSize, dataSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLCompressedTexSubImage2DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexSubImage2DRobust(targetPacked, level, xoffset, yoffset, width, height, format, imageSize, dataSize, data); @@ -2636,7 +3706,8 @@ void GL_APIENTRY GL_CompressedTexSubImage2DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexSubImage2DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2654,26 +3725,40 @@ void GL_APIENTRY GL_CompressedTexImage3DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexImage3DRobustANGLE, - "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, border = %d, imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, - GLenumToString(GLESEnum::AllEnums, internalformat), width, height, depth, border, - imageSize, dataSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLCompressedTexImage3DRobustANGLE, + "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " + "depth = %d, border = %d, imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + GLenumToString(GLESEnum::AllEnums, internalformat), width, height, depth, border, imageSize, + dataSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexImage3DRobustANGLE) && - ValidateCompressedTexImage3DRobustANGLE( - context, angle::EntryPoint::GLCompressedTexImage3DRobustANGLE, targetPacked, - level, internalformat, width, height, depth, border, imageSize, dataSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexImage3DRobustANGLE( + context, angle::EntryPoint::GLCompressedTexImage3DRobustANGLE, targetPacked, + level, internalformat, width, height, depth, border, imageSize, dataSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLCompressedTexImage3DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexImage3DRobust(targetPacked, level, internalformat, width, height, depth, border, imageSize, dataSize, data); @@ -2683,7 +3768,8 @@ void GL_APIENTRY GL_CompressedTexImage3DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexImage3DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2703,28 +3789,42 @@ void GL_APIENTRY GL_CompressedTexSubImage3DRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexSubImage3DRobustANGLE, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width " - "= %d, height = %d, depth = %d, format = %s, imageSize = %d, dataSize = %d, data = " - "0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, - zoffset, width, height, depth, GLenumToString(GLESEnum::AllEnums, format), imageSize, - dataSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLCompressedTexSubImage3DRobustANGLE, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, " + "zoffset = %d, width = %d, height = %d, depth = %d, format = %s, " + "imageSize = %d, dataSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + xoffset, yoffset, zoffset, width, height, depth, + GLenumToString(GLESEnum::AllEnums, format), imageSize, dataSize, + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexSubImage3DRobustANGLE) && - ValidateCompressedTexSubImage3DRobustANGLE( - context, angle::EntryPoint::GLCompressedTexSubImage3DRobustANGLE, targetPacked, - level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, - dataSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexSubImage3DRobustANGLE( + context, angle::EntryPoint::GLCompressedTexSubImage3DRobustANGLE, targetPacked, + level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, + dataSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLCompressedTexSubImage3DRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexSubImage3DRobust(targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, @@ -2736,7 +3836,8 @@ void GL_APIENTRY GL_CompressedTexSubImage3DRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexSubImage3DRobustANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -2749,21 +3850,38 @@ void GL_APIENTRY GL_GetQueryivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetQueryivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetQueryivRobustANGLE(context, angle::EntryPoint::GLGetQueryivRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryivRobustANGLE( + context, angle::EntryPoint::GLGetQueryivRobustANGLE, targetPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryivRobust(targetPacked, pname, bufSize, length, params); } @@ -2772,7 +3890,7 @@ void GL_APIENTRY GL_GetQueryivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetQueryivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2784,22 +3902,39 @@ void GL_APIENTRY GL_GetQueryObjectuivRobustANGLE(GLuint id, GLuint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryObjectuivRobustANGLE, - "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + Context *context = GetGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectuivRobustANGLE, + "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetQueryObjectuivRobustANGLE( - context, angle::EntryPoint::GLGetQueryObjectuivRobustANGLE, - idPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectuivRobustANGLE( + context, angle::EntryPoint::GLGetQueryObjectuivRobustANGLE, idPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryObjectuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectuivRobust(idPacked, pname, bufSize, length, params); } @@ -2808,7 +3943,6 @@ void GL_APIENTRY GL_GetQueryObjectuivRobustANGLE(GLuint id, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2821,21 +3955,38 @@ void GL_APIENTRY GL_GetBufferPointervRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferPointervRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetBufferPointervRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetBufferPointervRobustANGLE( - context, angle::EntryPoint::GLGetBufferPointervRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBufferPointervRobustANGLE( + context, angle::EntryPoint::GLGetBufferPointervRobustANGLE, targetPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetBufferPointervRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferPointervRobust(targetPacked, pname, bufSize, length, params); } @@ -2844,7 +3995,8 @@ void GL_APIENTRY GL_GetBufferPointervRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetBufferPointervRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2857,20 +4009,37 @@ void GL_APIENTRY GL_GetIntegeri_vRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetIntegeri_vRobustANGLE, - "context = %d, target = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), index, bufSize, - (uintptr_t)length, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetIntegeri_vRobustANGLE, + "context = %d, target = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), index, bufSize, + (uintptr_t)length, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetIntegeri_vRobustANGLE( - context, angle::EntryPoint::GLGetIntegeri_vRobustANGLE, target, - index, bufSize, length, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetIntegeri_vRobustANGLE( + context, angle::EntryPoint::GLGetIntegeri_vRobustANGLE, target, index, bufSize, + length, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetIntegeri_vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getIntegeri_vRobust(target, index, bufSize, length, data); } @@ -2879,7 +4048,8 @@ void GL_APIENTRY GL_GetIntegeri_vRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetIntegeri_vRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2893,21 +4063,39 @@ void GL_APIENTRY GL_GetInternalformativRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInternalformativRobustANGLE, - "context = %d, target = %s, internalformat = %s, pname = %s, bufSize = %d, length = " - "0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, internalformat), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetInternalformativRobustANGLE, + "context = %d, target = %s, internalformat = %s, pname = %s, bufSize = " + "%d, length = 0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, internalformat), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetInternalformativRobustANGLE( - context, angle::EntryPoint::GLGetInternalformativRobustANGLE, - target, internalformat, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetInternalformativRobustANGLE( + context, angle::EntryPoint::GLGetInternalformativRobustANGLE, target, + internalformat, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetInternalformativRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInternalformativRobust(target, internalformat, pname, bufSize, length, params); @@ -2917,7 +4105,8 @@ void GL_APIENTRY GL_GetInternalformativRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetInternalformativRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2930,20 +4119,38 @@ void GL_APIENTRY GL_GetVertexAttribIivRobustANGLE(GLuint index, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribIivRobustANGLE, - "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetVertexAttribIivRobustANGLE, + "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetVertexAttribIivRobustANGLE( - context, angle::EntryPoint::GLGetVertexAttribIivRobustANGLE, index, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribIivRobustANGLE( + context, angle::EntryPoint::GLGetVertexAttribIivRobustANGLE, index, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetVertexAttribIivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribIivRobust(index, pname, bufSize, length, params); } @@ -2952,7 +4159,8 @@ void GL_APIENTRY GL_GetVertexAttribIivRobustANGLE(GLuint index, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetVertexAttribIivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -2965,20 +4173,38 @@ void GL_APIENTRY GL_GetVertexAttribIuivRobustANGLE(GLuint index, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetVertexAttribIuivRobustANGLE, - "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetVertexAttribIuivRobustANGLE, + "context = %d, index = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), index, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetVertexAttribIuivRobustANGLE( - context, angle::EntryPoint::GLGetVertexAttribIuivRobustANGLE, index, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetVertexAttribIuivRobustANGLE( + context, angle::EntryPoint::GLGetVertexAttribIuivRobustANGLE, index, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetVertexAttribIuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getVertexAttribIuivRobust(index, pname, bufSize, length, params); } @@ -2987,7 +4213,8 @@ void GL_APIENTRY GL_GetVertexAttribIuivRobustANGLE(GLuint index, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetVertexAttribIuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3000,21 +4227,38 @@ void GL_APIENTRY GL_GetUniformuivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUniformuivRobustANGLE, - "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetUniformuivRobustANGLE, + "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUniformuivRobustANGLE( - context, angle::EntryPoint::GLGetUniformuivRobustANGLE, - programPacked, locationPacked, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUniformuivRobustANGLE( + context, angle::EntryPoint::GLGetUniformuivRobustANGLE, programPacked, + locationPacked, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetUniformuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUniformuivRobust(programPacked, locationPacked, bufSize, length, params); } @@ -3023,7 +4267,8 @@ void GL_APIENTRY GL_GetUniformuivRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetUniformuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3037,23 +4282,40 @@ void GL_APIENTRY GL_GetActiveUniformBlockivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetActiveUniformBlockivRobustANGLE, - "context = %d, program = %u, uniformBlockIndex = %u, pname = %s, bufSize = %d, length = " - "0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", - CID(context), program, uniformBlockIndex, GLenumToString(GLESEnum::AllEnums, pname), - bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetActiveUniformBlockivRobustANGLE, + "context = %d, program = %u, uniformBlockIndex = %u, pname = %s, " + "bufSize = %d, length = 0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", + CID(context), program, uniformBlockIndex, + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformBlockIndex uniformBlockIndexPacked = PackParam(uniformBlockIndex); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetActiveUniformBlockivRobustANGLE( - context, angle::EntryPoint::GLGetActiveUniformBlockivRobustANGLE, programPacked, - uniformBlockIndexPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetActiveUniformBlockivRobustANGLE( + context, angle::EntryPoint::GLGetActiveUniformBlockivRobustANGLE, programPacked, + uniformBlockIndexPacked, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetActiveUniformBlockivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getActiveUniformBlockivRobust(programPacked, uniformBlockIndexPacked, pname, bufSize, length, params); @@ -3063,7 +4325,8 @@ void GL_APIENTRY GL_GetActiveUniformBlockivRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetActiveUniformBlockivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3075,20 +4338,36 @@ void GL_APIENTRY GL_GetInteger64vRobustANGLE(GLenum pname, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInteger64vRobustANGLE, - "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetInteger64vRobustANGLE, + "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetInteger64vRobustANGLE( - context, angle::EntryPoint::GLGetInteger64vRobustANGLE, pname, - bufSize, length, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetInteger64vRobustANGLE( + context, angle::EntryPoint::GLGetInteger64vRobustANGLE, pname, bufSize, length, + data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetInteger64vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInteger64vRobust(pname, bufSize, length, data); } @@ -3097,7 +4376,8 @@ void GL_APIENTRY GL_GetInteger64vRobustANGLE(GLenum pname, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetInteger64vRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3110,20 +4390,37 @@ void GL_APIENTRY GL_GetInteger64i_vRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInteger64i_vRobustANGLE, - "context = %d, target = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), index, bufSize, - (uintptr_t)length, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetInteger64i_vRobustANGLE, + "context = %d, target = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), index, bufSize, + (uintptr_t)length, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetInteger64i_vRobustANGLE( - context, angle::EntryPoint::GLGetInteger64i_vRobustANGLE, target, - index, bufSize, length, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetInteger64i_vRobustANGLE( + context, angle::EntryPoint::GLGetInteger64i_vRobustANGLE, target, index, + bufSize, length, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetInteger64i_vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInteger64i_vRobust(target, index, bufSize, length, data); } @@ -3132,7 +4429,8 @@ void GL_APIENTRY GL_GetInteger64i_vRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetInteger64i_vRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3145,21 +4443,39 @@ void GL_APIENTRY GL_GetBufferParameteri64vRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferParameteri64vRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetBufferParameteri64vRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetBufferParameteri64vRobustANGLE( - context, angle::EntryPoint::GLGetBufferParameteri64vRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBufferParameteri64vRobustANGLE( + context, angle::EntryPoint::GLGetBufferParameteri64vRobustANGLE, targetPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetBufferParameteri64vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferParameteri64vRobust(targetPacked, pname, bufSize, length, params); } @@ -3168,7 +4484,8 @@ void GL_APIENTRY GL_GetBufferParameteri64vRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetBufferParameteri64vRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3180,19 +4497,37 @@ void GL_APIENTRY GL_SamplerParameterivRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterivRobustANGLE, - "context = %d, sampler = %u, pname = %u, bufSize = %d, param = 0x%016" PRIxPTR "", - CID(context), sampler, pname, bufSize, (uintptr_t)param); + ANGLE_UNSAFE_TODO( + EVENT(context, GLSamplerParameterivRobustANGLE, + "context = %d, sampler = %u, pname = %u, bufSize = %d, param = 0x%016" PRIxPTR "", + CID(context), sampler, pname, bufSize, (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateSamplerParameterivRobustANGLE( - context, angle::EntryPoint::GLSamplerParameterivRobustANGLE, - samplerPacked, pname, bufSize, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterivRobustANGLE( + context, angle::EntryPoint::GLSamplerParameterivRobustANGLE, samplerPacked, + pname, bufSize, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLSamplerParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterivRobust(samplerPacked, pname, bufSize, param); } @@ -3201,7 +4536,8 @@ void GL_APIENTRY GL_SamplerParameterivRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSamplerParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3213,20 +4549,38 @@ void GL_APIENTRY GL_SamplerParameterfvRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterfvRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, param = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)param); + ANGLE_UNSAFE_TODO( + EVENT(context, GLSamplerParameterfvRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, param = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateSamplerParameterfvRobustANGLE( - context, angle::EntryPoint::GLSamplerParameterfvRobustANGLE, - samplerPacked, pname, bufSize, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterfvRobustANGLE( + context, angle::EntryPoint::GLSamplerParameterfvRobustANGLE, samplerPacked, + pname, bufSize, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLSamplerParameterfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterfvRobust(samplerPacked, pname, bufSize, param); } @@ -3235,7 +4589,8 @@ void GL_APIENTRY GL_SamplerParameterfvRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSamplerParameterfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3248,21 +4603,39 @@ void GL_APIENTRY GL_GetSamplerParameterivRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterivRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetSamplerParameterivRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterivRobustANGLE( - context, angle::EntryPoint::GLGetSamplerParameterivRobustANGLE, - samplerPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterivRobustANGLE( + context, angle::EntryPoint::GLGetSamplerParameterivRobustANGLE, samplerPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetSamplerParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterivRobust(samplerPacked, pname, bufSize, length, params); } @@ -3271,7 +4644,8 @@ void GL_APIENTRY GL_GetSamplerParameterivRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3284,21 +4658,39 @@ void GL_APIENTRY GL_GetSamplerParameterfvRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterfvRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetSamplerParameterfvRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterfvRobustANGLE( - context, angle::EntryPoint::GLGetSamplerParameterfvRobustANGLE, - samplerPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterfvRobustANGLE( + context, angle::EntryPoint::GLGetSamplerParameterfvRobustANGLE, samplerPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetSamplerParameterfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterfvRobust(samplerPacked, pname, bufSize, length, params); } @@ -3307,7 +4699,8 @@ void GL_APIENTRY GL_GetSamplerParameterfvRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3320,20 +4713,38 @@ void GL_APIENTRY GL_GetFramebufferParameterivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferParameterivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetFramebufferParameterivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetFramebufferParameterivRobustANGLE( - context, angle::EntryPoint::GLGetFramebufferParameterivRobustANGLE, - target, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferParameterivRobustANGLE( + context, angle::EntryPoint::GLGetFramebufferParameterivRobustANGLE, target, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetFramebufferParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferParameterivRobust(target, pname, bufSize, length, params); } @@ -3342,7 +4753,8 @@ void GL_APIENTRY GL_GetFramebufferParameterivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3356,21 +4768,39 @@ void GL_APIENTRY GL_GetProgramInterfaceivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramInterfaceivRobustANGLE, - "context = %d, program = %u, programInterface = %s, pname = %s, bufSize = %d, length = " - "0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::AllEnums, programInterface), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetProgramInterfaceivRobustANGLE, + "context = %d, program = %u, programInterface = %s, pname = %s, bufSize = %d, length = " + "0x%016" PRIxPTR ", params = 0x%016" PRIxPTR "", + CID(context), program, GLenumToString(GLESEnum::AllEnums, programInterface), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramInterfaceivRobustANGLE( - context, angle::EntryPoint::GLGetProgramInterfaceivRobustANGLE, - programPacked, programInterface, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramInterfaceivRobustANGLE( + context, angle::EntryPoint::GLGetProgramInterfaceivRobustANGLE, programPacked, + programInterface, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetProgramInterfaceivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramInterfaceivRobust(programPacked, programInterface, pname, bufSize, length, params); @@ -3380,7 +4810,8 @@ void GL_APIENTRY GL_GetProgramInterfaceivRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramInterfaceivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3393,20 +4824,37 @@ void GL_APIENTRY GL_GetBooleani_vRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBooleani_vRobustANGLE, - "context = %d, target = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), index, bufSize, - (uintptr_t)length, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetBooleani_vRobustANGLE, + "context = %d, target = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), index, bufSize, + (uintptr_t)length, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetBooleani_vRobustANGLE( - context, angle::EntryPoint::GLGetBooleani_vRobustANGLE, target, - index, bufSize, length, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetBooleani_vRobustANGLE( + context, angle::EntryPoint::GLGetBooleani_vRobustANGLE, target, index, bufSize, + length, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetBooleani_vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBooleani_vRobust(target, index, bufSize, length, data); } @@ -3415,7 +4863,8 @@ void GL_APIENTRY GL_GetBooleani_vRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetBooleani_vRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3428,20 +4877,37 @@ void GL_APIENTRY GL_GetMultisamplefvRobustANGLE(GLenum pname, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetMultisamplefvRobustANGLE, - "context = %d, pname = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", val = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), index, bufSize, - (uintptr_t)length, (uintptr_t)val); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetMultisamplefvRobustANGLE, + "context = %d, pname = %s, index = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", val = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), index, bufSize, + (uintptr_t)length, (uintptr_t)val)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetMultisamplefvRobustANGLE( - context, angle::EntryPoint::GLGetMultisamplefvRobustANGLE, pname, - index, bufSize, length, val)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetMultisamplefvRobustANGLE( + context, angle::EntryPoint::GLGetMultisamplefvRobustANGLE, pname, index, + bufSize, length, val); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetMultisamplefvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getMultisamplefvRobust(pname, index, bufSize, length, val); } @@ -3450,7 +4916,8 @@ void GL_APIENTRY GL_GetMultisamplefvRobustANGLE(GLenum pname, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetMultisamplefvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3464,21 +4931,39 @@ void GL_APIENTRY GL_GetTexLevelParameterivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexLevelParameterivRobustANGLE, - "context = %d, target = %s, level = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexLevelParameterivRobustANGLE, + "context = %d, target = %s, level = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexLevelParameterivRobustANGLE( - context, angle::EntryPoint::GLGetTexLevelParameterivRobustANGLE, - targetPacked, level, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexLevelParameterivRobustANGLE( + context, angle::EntryPoint::GLGetTexLevelParameterivRobustANGLE, targetPacked, + level, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetTexLevelParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexLevelParameterivRobust(targetPacked, level, pname, bufSize, length, params); @@ -3488,7 +4973,8 @@ void GL_APIENTRY GL_GetTexLevelParameterivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexLevelParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3502,21 +4988,39 @@ void GL_APIENTRY GL_GetTexLevelParameterfvRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexLevelParameterfvRobustANGLE, - "context = %d, target = %s, level = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexLevelParameterfvRobustANGLE, + "context = %d, target = %s, level = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexLevelParameterfvRobustANGLE( - context, angle::EntryPoint::GLGetTexLevelParameterfvRobustANGLE, - targetPacked, level, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexLevelParameterfvRobustANGLE( + context, angle::EntryPoint::GLGetTexLevelParameterfvRobustANGLE, targetPacked, + level, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetTexLevelParameterfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexLevelParameterfvRobust(targetPacked, level, pname, bufSize, length, params); @@ -3526,7 +5030,8 @@ void GL_APIENTRY GL_GetTexLevelParameterfvRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexLevelParameterfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3538,20 +5043,37 @@ void GL_APIENTRY GL_GetPointervRobustANGLERobustANGLE(GLenum pname, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPointervRobustANGLERobustANGLE, - "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPointervRobustANGLERobustANGLE, + "context = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetPointervRobustANGLERobustANGLE( - context, angle::EntryPoint::GLGetPointervRobustANGLERobustANGLE, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPointervRobustANGLERobustANGLE( + context, angle::EntryPoint::GLGetPointervRobustANGLERobustANGLE, pname, bufSize, + length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetPointervRobustANGLERobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPointervRobustANGLERobust(pname, bufSize, length, params); } @@ -3560,7 +5082,8 @@ void GL_APIENTRY GL_GetPointervRobustANGLERobustANGLE(GLenum pname, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetPointervRobustANGLERobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3579,26 +5102,39 @@ void GL_APIENTRY GL_ReadnPixelsRobustANGLE(GLint x, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadnPixelsRobustANGLE, - "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, bufSize " - "= %d, length = 0x%016" PRIxPTR ", columns = 0x%016" PRIxPTR ", rows = 0x%016" PRIxPTR - ", data = 0x%016" PRIxPTR "", - CID(context), x, y, width, height, GLenumToString(GLESEnum::AllEnums, format), - GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)length, (uintptr_t)columns, - (uintptr_t)rows, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLReadnPixelsRobustANGLE, + "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, " + "bufSize = %d, length = 0x%016" PRIxPTR ", columns = 0x%016" PRIxPTR + ", rows = 0x%016" PRIxPTR ", data = 0x%016" PRIxPTR "", + CID(context), x, y, width, height, GLenumToString(GLESEnum::AllEnums, format), + GLenumToString(GLESEnum::AllEnums, type), bufSize, (uintptr_t)length, + (uintptr_t)columns, (uintptr_t)rows, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadnPixelsRobustANGLE) && - ValidateReadnPixelsRobustANGLE(context, angle::EntryPoint::GLReadnPixelsRobustANGLE, - x, y, width, height, format, type, bufSize, length, - columns, rows, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateReadnPixelsRobustANGLE( + context, angle::EntryPoint::GLReadnPixelsRobustANGLE, x, y, width, height, + format, type, bufSize, length, columns, rows, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLReadnPixelsRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readnPixelsRobust(x, y, width, height, format, type, bufSize, length, columns, rows, data); @@ -3608,7 +5144,7 @@ void GL_APIENTRY GL_ReadnPixelsRobustANGLE(GLint x, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadnPixelsRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3621,21 +5157,38 @@ void GL_APIENTRY GL_GetnUniformfvRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformfvRobustANGLE, - "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformfvRobustANGLE, + "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetnUniformfvRobustANGLE( - context, angle::EntryPoint::GLGetnUniformfvRobustANGLE, - programPacked, locationPacked, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetnUniformfvRobustANGLE( + context, angle::EntryPoint::GLGetnUniformfvRobustANGLE, programPacked, + locationPacked, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformfvRobust(programPacked, locationPacked, bufSize, length, params); } @@ -3644,7 +5197,8 @@ void GL_APIENTRY GL_GetnUniformfvRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetnUniformfvRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3657,21 +5211,38 @@ void GL_APIENTRY GL_GetnUniformivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformivRobustANGLE, - "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformivRobustANGLE, + "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetnUniformivRobustANGLE( - context, angle::EntryPoint::GLGetnUniformivRobustANGLE, - programPacked, locationPacked, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetnUniformivRobustANGLE( + context, angle::EntryPoint::GLGetnUniformivRobustANGLE, programPacked, + locationPacked, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformivRobust(programPacked, locationPacked, bufSize, length, params); } @@ -3680,7 +5251,8 @@ void GL_APIENTRY GL_GetnUniformivRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetnUniformivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3693,21 +5265,38 @@ void GL_APIENTRY GL_GetnUniformuivRobustANGLE(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformuivRobustANGLE, - "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformuivRobustANGLE, + "context = %d, program = %u, location = %d, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetnUniformuivRobustANGLE( - context, angle::EntryPoint::GLGetnUniformuivRobustANGLE, - programPacked, locationPacked, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetnUniformuivRobustANGLE( + context, angle::EntryPoint::GLGetnUniformuivRobustANGLE, programPacked, + locationPacked, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformuivRobust(programPacked, locationPacked, bufSize, length, params); } @@ -3716,7 +5305,8 @@ void GL_APIENTRY GL_GetnUniformuivRobustANGLE(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetnUniformuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3728,20 +5318,37 @@ void GL_APIENTRY GL_TexParameterIivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexParameterIivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterIivRobustANGLE( - context, angle::EntryPoint::GLTexParameterIivRobustANGLE, - targetPacked, pname, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIivRobustANGLE( + context, angle::EntryPoint::GLTexParameterIivRobustANGLE, targetPacked, pname, + bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterIivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIivRobust(targetPacked, pname, bufSize, params); } @@ -3750,7 +5357,8 @@ void GL_APIENTRY GL_TexParameterIivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexParameterIivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3762,20 +5370,37 @@ void GL_APIENTRY GL_TexParameterIuivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIuivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexParameterIuivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateTexParameterIuivRobustANGLE( - context, angle::EntryPoint::GLTexParameterIuivRobustANGLE, - targetPacked, pname, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIuivRobustANGLE( + context, angle::EntryPoint::GLTexParameterIuivRobustANGLE, targetPacked, pname, + bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterIuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIuivRobust(targetPacked, pname, bufSize, params); } @@ -3784,7 +5409,8 @@ void GL_APIENTRY GL_TexParameterIuivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexParameterIuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3797,21 +5423,39 @@ void GL_APIENTRY GL_GetTexParameterIivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexParameterIivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexParameterIivRobustANGLE( - context, angle::EntryPoint::GLGetTexParameterIivRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIivRobustANGLE( + context, angle::EntryPoint::GLGetTexParameterIivRobustANGLE, targetPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetTexParameterIivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIivRobust(targetPacked, pname, bufSize, length, params); } @@ -3820,7 +5464,8 @@ void GL_APIENTRY GL_GetTexParameterIivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexParameterIivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3833,21 +5478,39 @@ void GL_APIENTRY GL_GetTexParameterIuivRobustANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIuivRobustANGLE, - "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetTexParameterIuivRobustANGLE, + "context = %d, target = %s, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexParameterIuivRobustANGLE( - context, angle::EntryPoint::GLGetTexParameterIuivRobustANGLE, - targetPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIuivRobustANGLE( + context, angle::EntryPoint::GLGetTexParameterIuivRobustANGLE, targetPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetTexParameterIuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIuivRobust(targetPacked, pname, bufSize, length, params); } @@ -3856,7 +5519,8 @@ void GL_APIENTRY GL_GetTexParameterIuivRobustANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTexParameterIuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3868,20 +5532,38 @@ void GL_APIENTRY GL_SamplerParameterIivRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIivRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, param = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)param); + ANGLE_UNSAFE_TODO( + EVENT(context, GLSamplerParameterIivRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, param = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateSamplerParameterIivRobustANGLE( - context, angle::EntryPoint::GLSamplerParameterIivRobustANGLE, - samplerPacked, pname, bufSize, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIivRobustANGLE( + context, angle::EntryPoint::GLSamplerParameterIivRobustANGLE, samplerPacked, + pname, bufSize, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLSamplerParameterIivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIivRobust(samplerPacked, pname, bufSize, param); } @@ -3890,7 +5572,8 @@ void GL_APIENTRY GL_SamplerParameterIivRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSamplerParameterIivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3902,20 +5585,38 @@ void GL_APIENTRY GL_SamplerParameterIuivRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIuivRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, param = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)param); + ANGLE_UNSAFE_TODO( + EVENT(context, GLSamplerParameterIuivRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, param = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateSamplerParameterIuivRobustANGLE( - context, angle::EntryPoint::GLSamplerParameterIuivRobustANGLE, - samplerPacked, pname, bufSize, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIuivRobustANGLE( + context, angle::EntryPoint::GLSamplerParameterIuivRobustANGLE, samplerPacked, + pname, bufSize, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLSamplerParameterIuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIuivRobust(samplerPacked, pname, bufSize, param); } @@ -3924,7 +5625,8 @@ void GL_APIENTRY GL_SamplerParameterIuivRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSamplerParameterIuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3937,21 +5639,39 @@ void GL_APIENTRY GL_GetSamplerParameterIivRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIivRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetSamplerParameterIivRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterIivRobustANGLE( - context, angle::EntryPoint::GLGetSamplerParameterIivRobustANGLE, - samplerPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIivRobustANGLE( + context, angle::EntryPoint::GLGetSamplerParameterIivRobustANGLE, samplerPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetSamplerParameterIivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIivRobust(samplerPacked, pname, bufSize, length, params); } @@ -3960,7 +5680,8 @@ void GL_APIENTRY GL_GetSamplerParameterIivRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -3973,21 +5694,39 @@ void GL_APIENTRY GL_GetSamplerParameterIuivRobustANGLE(GLuint sampler, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIuivRobustANGLE, - "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetSamplerParameterIuivRobustANGLE, + "context = %d, sampler = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), sampler, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterIuivRobustANGLE( - context, angle::EntryPoint::GLGetSamplerParameterIuivRobustANGLE, - samplerPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIuivRobustANGLE( + context, angle::EntryPoint::GLGetSamplerParameterIuivRobustANGLE, samplerPacked, + pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetSamplerParameterIuivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIuivRobust(samplerPacked, pname, bufSize, length, params); } @@ -3996,7 +5735,8 @@ void GL_APIENTRY GL_GetSamplerParameterIuivRobustANGLE(GLuint sampler, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIuivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4009,21 +5749,38 @@ void GL_APIENTRY GL_GetQueryObjectivRobustANGLE(GLuint id, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetQueryObjectivRobustANGLE, - "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectivRobustANGLE, + "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetQueryObjectivRobustANGLE( - context, angle::EntryPoint::GLGetQueryObjectivRobustANGLE, idPacked, - pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectivRobustANGLE( + context, angle::EntryPoint::GLGetQueryObjectivRobustANGLE, idPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryObjectivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectivRobust(idPacked, pname, bufSize, length, params); } @@ -4044,21 +5801,39 @@ void GL_APIENTRY GL_GetQueryObjecti64vRobustANGLE(GLuint id, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetQueryObjecti64vRobustANGLE, - "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjecti64vRobustANGLE, + "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetQueryObjecti64vRobustANGLE( - context, angle::EntryPoint::GLGetQueryObjecti64vRobustANGLE, - idPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjecti64vRobustANGLE( + context, angle::EntryPoint::GLGetQueryObjecti64vRobustANGLE, idPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetQueryObjecti64vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjecti64vRobust(idPacked, pname, bufSize, length, params); } @@ -4078,22 +5853,40 @@ void GL_APIENTRY GL_GetQueryObjectui64vRobustANGLE(GLuint id, GLuint64 *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryObjectui64vRobustANGLE, - "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, (uintptr_t)length, - (uintptr_t)params); + Context *context = GetGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectui64vRobustANGLE, + "context = %d, id = %u, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), id, GLenumToString(GLESEnum::AllEnums, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetQueryObjectui64vRobustANGLE( - context, angle::EntryPoint::GLGetQueryObjectui64vRobustANGLE, - idPacked, pname, bufSize, length, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectui64vRobustANGLE( + context, angle::EntryPoint::GLGetQueryObjectui64vRobustANGLE, idPacked, pname, + bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetQueryObjectui64vRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectui64vRobust(idPacked, pname, bufSize, length, params); } @@ -4102,7 +5895,120 @@ void GL_APIENTRY GL_GetQueryObjectui64vRobustANGLE(GLuint id, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE(GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE, + "context = %d, plane = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), plane, GLenumToString(GLESEnum::PLSQueryFloat, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); + + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE( + context, + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE, + plane, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->getFramebufferPixelLocalStorageParameterfvRobust(plane, pname, bufSize, length, + params); + } + ANGLE_CAPTURE_GL(GetFramebufferPixelLocalStorageParameterfvRobustANGLE, isCallValid, + context, plane, pname, bufSize, length, params); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE(GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetFramebufferPixelLocalStorageParameterivRobustANGLE, + "context = %d, plane = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR + ", params = 0x%016" PRIxPTR "", + CID(context), plane, GLenumToString(GLESEnum::PLSQueryInt, pname), bufSize, + (uintptr_t)length, (uintptr_t)params)); + + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustClientMemoryANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE( + context, + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivRobustANGLE, + plane, pname, bufSize, length, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivRobustANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->getFramebufferPixelLocalStorageParameterivRobust(plane, pname, bufSize, length, + params); + } + ANGLE_CAPTURE_GL(GetFramebufferPixelLocalStorageParameterivRobustANGLE, isCallValid, + context, plane, pname, bufSize, length, params); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivRobustANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4118,24 +6024,38 @@ void GL_APIENTRY GL_ImportSemaphoreZirconHandleANGLE(GLuint semaphore, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLImportSemaphoreZirconHandleANGLE, - "context = %d, semaphore = %u, handleType = %s, handle = %u", CID(context), semaphore, - GLenumToString(GLESEnum::ExternalHandleType, handleType), handle); + ANGLE_UNSAFE_TODO(EVENT(context, GLImportSemaphoreZirconHandleANGLE, + "context = %d, semaphore = %u, handleType = %s, handle = %u", + CID(context), semaphore, + GLenumToString(GLESEnum::ExternalHandleType, handleType), handle)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); HandleType handleTypePacked = PackParam(handleType); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLImportSemaphoreZirconHandleANGLE) && - ValidateImportSemaphoreZirconHandleANGLE( - context, angle::EntryPoint::GLImportSemaphoreZirconHandleANGLE, semaphorePacked, - handleTypePacked, handle))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreFuchsiaANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateImportSemaphoreZirconHandleANGLE( + context, angle::EntryPoint::GLImportSemaphoreZirconHandleANGLE, semaphorePacked, + handleTypePacked, handle); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLImportSemaphoreZirconHandleANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->importSemaphoreZirconHandle(semaphorePacked, handleTypePacked, handle); } @@ -4144,7 +6064,8 @@ void GL_APIENTRY GL_ImportSemaphoreZirconHandleANGLE(GLuint semaphore, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLImportSemaphoreZirconHandleANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4156,19 +6077,39 @@ void GL_APIENTRY GL_FramebufferMemorylessPixelLocalStorageANGLE(GLint plane, GLe { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferMemorylessPixelLocalStorageANGLE, - "context = %d, plane = %d, internalformat = %s", CID(context), plane, - GLenumToString(GLESEnum::AllEnums, internalformat)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferMemorylessPixelLocalStorageANGLE, + "context = %d, plane = %d, internalformat = %s", CID(context), plane, + GLenumToString(GLESEnum::AllEnums, internalformat))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferMemorylessPixelLocalStorageANGLE( - context, angle::EntryPoint::GLFramebufferMemorylessPixelLocalStorageANGLE, plane, - internalformat)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferMemorylessPixelLocalStorageANGLE( + context, angle::EntryPoint::GLFramebufferMemorylessPixelLocalStorageANGLE, + plane, internalformat); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferMemorylessPixelLocalStorageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferMemorylessPixelLocalStorage(plane, internalformat); } @@ -4177,7 +6118,8 @@ void GL_APIENTRY GL_FramebufferMemorylessPixelLocalStorageANGLE(GLint plane, GLe } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferMemorylessPixelLocalStorageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4189,20 +6131,40 @@ void GL_APIENTRY GL_FramebufferTexturePixelLocalStorageANGLE(GLint plane, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTexturePixelLocalStorageANGLE, - "context = %d, plane = %d, backingtexture = %u, level = %d, layer = %d", CID(context), - plane, backingtexture, level, layer); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTexturePixelLocalStorageANGLE, + "context = %d, plane = %d, backingtexture = %u, level = %d, layer = %d", + CID(context), plane, backingtexture, level, layer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID backingtexturePacked = PackParam(backingtexture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferTexturePixelLocalStorageANGLE( - context, angle::EntryPoint::GLFramebufferTexturePixelLocalStorageANGLE, plane, - backingtexturePacked, level, layer)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTexturePixelLocalStorageANGLE( + context, angle::EntryPoint::GLFramebufferTexturePixelLocalStorageANGLE, plane, + backingtexturePacked, level, layer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferTexturePixelLocalStorageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexturePixelLocalStorage(plane, backingtexturePacked, level, layer); } @@ -4211,7 +6173,8 @@ void GL_APIENTRY GL_FramebufferTexturePixelLocalStorageANGLE(GLint plane, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTexturePixelLocalStorageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4220,22 +6183,35 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValuefvANGLE(GLint plane, const GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferPixelLocalClearValuefvANGLE, - "context = %d, plane = %d, value = 0x%016" PRIxPTR "", CID(context), plane, - (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferPixelLocalClearValuefvANGLE, + "context = %d, plane = %d, value = 0x%016" PRIxPTR "", CID(context), + plane, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferPixelLocalClearValuefvANGLE) && - ValidateFramebufferPixelLocalClearValuefvANGLE( - context, angle::EntryPoint::GLFramebufferPixelLocalClearValuefvANGLE, plane, - value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferPixelLocalClearValuefvANGLE( + context, angle::EntryPoint::GLFramebufferPixelLocalClearValuefvANGLE, plane, + value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferPixelLocalClearValuefvANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferPixelLocalClearValuefv(plane, value); } @@ -4244,7 +6220,8 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValuefvANGLE(GLint plane, const GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferPixelLocalClearValuefvANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4253,22 +6230,35 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValueivANGLE(GLint plane, const GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferPixelLocalClearValueivANGLE, - "context = %d, plane = %d, value = 0x%016" PRIxPTR "", CID(context), plane, - (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferPixelLocalClearValueivANGLE, + "context = %d, plane = %d, value = 0x%016" PRIxPTR "", CID(context), + plane, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferPixelLocalClearValueivANGLE) && - ValidateFramebufferPixelLocalClearValueivANGLE( - context, angle::EntryPoint::GLFramebufferPixelLocalClearValueivANGLE, plane, - value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferPixelLocalClearValueivANGLE( + context, angle::EntryPoint::GLFramebufferPixelLocalClearValueivANGLE, plane, + value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferPixelLocalClearValueivANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferPixelLocalClearValueiv(plane, value); } @@ -4277,7 +6267,8 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValueivANGLE(GLint plane, const GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferPixelLocalClearValueivANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4286,22 +6277,35 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValueuivANGLE(GLint plane, const G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferPixelLocalClearValueuivANGLE, - "context = %d, plane = %d, value = 0x%016" PRIxPTR "", CID(context), plane, - (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferPixelLocalClearValueuivANGLE, + "context = %d, plane = %d, value = 0x%016" PRIxPTR "", CID(context), + plane, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferPixelLocalClearValueuivANGLE) && - ValidateFramebufferPixelLocalClearValueuivANGLE( - context, angle::EntryPoint::GLFramebufferPixelLocalClearValueuivANGLE, plane, - value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferPixelLocalClearValueuivANGLE( + context, angle::EntryPoint::GLFramebufferPixelLocalClearValueuivANGLE, plane, + value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferPixelLocalClearValueuivANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferPixelLocalClearValueuiv(plane, value); } @@ -4310,7 +6314,8 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValueuivANGLE(GLint plane, const G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferPixelLocalClearValueuivANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4319,20 +6324,33 @@ void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei n, const GLenum *loadops { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBeginPixelLocalStorageANGLE, - "context = %d, n = %d, loadops = 0x%016" PRIxPTR "", CID(context), n, (uintptr_t)loadops); + ANGLE_UNSAFE_TODO(EVENT(context, GLBeginPixelLocalStorageANGLE, + "context = %d, n = %d, loadops = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)loadops)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBeginPixelLocalStorageANGLE) && - ValidateBeginPixelLocalStorageANGLE( - context, angle::EntryPoint::GLBeginPixelLocalStorageANGLE, n, loadops))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBeginPixelLocalStorageANGLE( + context, angle::EntryPoint::GLBeginPixelLocalStorageANGLE, n, loadops); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBeginPixelLocalStorageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->beginPixelLocalStorage(n, loadops); } @@ -4340,7 +6358,8 @@ void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei n, const GLenum *loadops } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBeginPixelLocalStorageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4349,18 +6368,33 @@ void GL_APIENTRY GL_EndPixelLocalStorageANGLE(GLsizei n, const GLenum *storeops) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEndPixelLocalStorageANGLE, - "context = %d, n = %d, storeops = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)storeops); + ANGLE_UNSAFE_TODO(EVENT(context, GLEndPixelLocalStorageANGLE, + "context = %d, n = %d, storeops = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)storeops)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateEndPixelLocalStorageANGLE( - context, angle::EntryPoint::GLEndPixelLocalStorageANGLE, n, storeops)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEndPixelLocalStorageANGLE( + context, angle::EntryPoint::GLEndPixelLocalStorageANGLE, n, storeops); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEndPixelLocalStorageANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->endPixelLocalStorage(n, storeops); } @@ -4368,7 +6402,8 @@ void GL_APIENTRY GL_EndPixelLocalStorageANGLE(GLsizei n, const GLenum *storeops) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLEndPixelLocalStorageANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4377,15 +6412,33 @@ void GL_APIENTRY GL_PixelLocalStorageBarrierANGLE() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPixelLocalStorageBarrierANGLE, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLPixelLocalStorageBarrierANGLE, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidatePixelLocalStorageBarrierANGLE( - context, angle::EntryPoint::GLPixelLocalStorageBarrierANGLE)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePixelLocalStorageBarrierANGLE( + context, angle::EntryPoint::GLPixelLocalStorageBarrierANGLE); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLPixelLocalStorageBarrierANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->pixelLocalStorageBarrier(); } @@ -4393,7 +6446,8 @@ void GL_APIENTRY GL_PixelLocalStorageBarrierANGLE() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLPixelLocalStorageBarrierANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4402,16 +6456,33 @@ void GL_APIENTRY GL_FramebufferPixelLocalStorageInterruptANGLE() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferPixelLocalStorageInterruptANGLE, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLFramebufferPixelLocalStorageInterruptANGLE, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferPixelLocalStorageInterruptANGLE( - context, angle::EntryPoint::GLFramebufferPixelLocalStorageInterruptANGLE)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferPixelLocalStorageInterruptANGLE( + context, angle::EntryPoint::GLFramebufferPixelLocalStorageInterruptANGLE); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferPixelLocalStorageInterruptANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferPixelLocalStorageInterrupt(); } @@ -4419,7 +6490,8 @@ void GL_APIENTRY GL_FramebufferPixelLocalStorageInterruptANGLE() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferPixelLocalStorageInterruptANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4428,19 +6500,33 @@ void GL_APIENTRY GL_FramebufferPixelLocalStorageRestoreANGLE() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferPixelLocalStorageRestoreANGLE, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLFramebufferPixelLocalStorageRestoreANGLE, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferPixelLocalStorageRestoreANGLE) && - ValidateFramebufferPixelLocalStorageRestoreANGLE( - context, angle::EntryPoint::GLFramebufferPixelLocalStorageRestoreANGLE))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferPixelLocalStorageRestoreANGLE( + context, angle::EntryPoint::GLFramebufferPixelLocalStorageRestoreANGLE); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferPixelLocalStorageRestoreANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferPixelLocalStorageRestore(); } @@ -4448,7 +6534,8 @@ void GL_APIENTRY GL_FramebufferPixelLocalStorageRestoreANGLE() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferPixelLocalStorageRestoreANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4459,19 +6546,36 @@ void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterfvANGLE(GLint plane, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferPixelLocalStorageParameterfvANGLE, - "context = %d, plane = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), plane, - GLenumToString(GLESEnum::PLSQueryFloat, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFramebufferPixelLocalStorageParameterfvANGLE, + "context = %d, plane = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), plane, GLenumToString(GLESEnum::PLSQueryFloat, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferPixelLocalStorageParameterfvANGLE( - context, angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvANGLE, - plane, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferPixelLocalStorageParameterfvANGLE( + context, angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvANGLE, + plane, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferPixelLocalStorageParameterfv(plane, pname, params); } @@ -4480,7 +6584,8 @@ void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterfvANGLE(GLint plane, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4491,19 +6596,36 @@ void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterivANGLE(GLint plane, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferPixelLocalStorageParameterivANGLE, - "context = %d, plane = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), plane, - GLenumToString(GLESEnum::PLSQueryInt, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFramebufferPixelLocalStorageParameterivANGLE, + "context = %d, plane = %d, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), plane, GLenumToString(GLESEnum::PLSQueryInt, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferPixelLocalStorageParameterivANGLE( - context, angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivANGLE, - plane, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderPixelLocalStorageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferPixelLocalStorageParameterivANGLE( + context, angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivANGLE, + plane, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferPixelLocalStorageParameteriv(plane, pname, params); } @@ -4512,86 +6634,12 @@ void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterivANGLE(GLint plane, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE(GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params) -{ - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE, - "context = %d, plane = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), plane, GLenumToString(GLESEnum::PLSQueryFloat, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); - - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferPixelLocalStorageParameterfvRobustANGLE( - context, - angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterfvRobustANGLE, plane, - pname, bufSize, length, params)); - if (isCallValid) - { - context->getFramebufferPixelLocalStorageParameterfvRobust(plane, pname, bufSize, length, - params); - } - ANGLE_CAPTURE_GL(GetFramebufferPixelLocalStorageParameterfvRobustANGLE, isCallValid, - context, plane, pname, bufSize, length, params); - } - else - { - GenerateContextLostErrorOnCurrentGlobalContext(); - } - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); -} - -void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE(GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params) -{ - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferPixelLocalStorageParameterivRobustANGLE, - "context = %d, plane = %d, pname = %s, bufSize = %d, length = 0x%016" PRIxPTR - ", params = 0x%016" PRIxPTR "", - CID(context), plane, GLenumToString(GLESEnum::PLSQueryInt, pname), bufSize, - (uintptr_t)length, (uintptr_t)params); - - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferPixelLocalStorageParameterivRobustANGLE( - context, - angle::EntryPoint::GLGetFramebufferPixelLocalStorageParameterivRobustANGLE, plane, - pname, bufSize, length, params)); - if (isCallValid) - { - context->getFramebufferPixelLocalStorageParameterivRobust(plane, pname, bufSize, length, - params); - } - ANGLE_CAPTURE_GL(GetFramebufferPixelLocalStorageParameterivRobustANGLE, isCallValid, - context, plane, pname, bufSize, length, params); - } - else - { - GenerateContextLostErrorOnCurrentGlobalContext(); - } - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); -} // GL_ANGLE_stencil_texturing @@ -4611,26 +6659,39 @@ void GL_APIENTRY GL_TexImage2DExternalANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexImage2DExternalANGLE, - "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, " - "border = %d, format = %s, type = %s", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, internalformat, - width, height, border, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexImage2DExternalANGLE, + "context = %d, target = %s, level = %d, internalformat = %d, width = " + "%d, height = %d, border = %d, format = %s, type = %s", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + internalformat, width, height, border, + GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexImage2DExternalANGLE) && - ValidateTexImage2DExternalANGLE(context, angle::EntryPoint::GLTexImage2DExternalANGLE, - targetPacked, level, internalformat, width, height, - border, format, type))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureExternalUpdateANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexImage2DExternalANGLE( + context, angle::EntryPoint::GLTexImage2DExternalANGLE, targetPacked, level, + internalformat, width, height, border, format, type); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexImage2DExternalANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texImage2DExternal(targetPacked, level, internalformat, width, height, border, format, type); @@ -4640,7 +6701,8 @@ void GL_APIENTRY GL_TexImage2DExternalANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexImage2DExternalANGLE); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -4649,21 +6711,33 @@ void GL_APIENTRY GL_InvalidateTextureANGLE(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLInvalidateTextureANGLE, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::TextureTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLInvalidateTextureANGLE, "context = %d, target = %s", + CID(context), GLenumToString(GLESEnum::TextureTarget, target))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLInvalidateTextureANGLE) && - ValidateInvalidateTextureANGLE(context, angle::EntryPoint::GLInvalidateTextureANGLE, - targetPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureExternalUpdateANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateInvalidateTextureANGLE( + context, angle::EntryPoint::GLInvalidateTextureANGLE, targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLInvalidateTextureANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->invalidateTexture(targetPacked); } @@ -4671,7 +6745,7 @@ void GL_APIENTRY GL_InvalidateTextureANGLE(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLInvalidateTextureANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4686,26 +6760,38 @@ void GL_APIENTRY GL_TexStorage2DMultisampleANGLE(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage2DMultisampleANGLE, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d, " - "fixedsamplelocations = %s", - CID(context), GLenumToString(GLESEnum::AllEnums, target), samples, - GLenumToString(GLESEnum::AllEnums, internalformat), width, height, - GLbooleanToString(fixedsamplelocations)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorage2DMultisampleANGLE, + "context = %d, target = %s, samples = %d, internalformat = %s, width = " + "%d, height = %d, fixedsamplelocations = %s", + CID(context), GLenumToString(GLESEnum::AllEnums, target), samples, + GLenumToString(GLESEnum::AllEnums, internalformat), width, height, + GLbooleanToString(fixedsamplelocations))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage2DMultisampleANGLE) && - ValidateTexStorage2DMultisampleANGLE( - context, angle::EntryPoint::GLTexStorage2DMultisampleANGLE, targetPacked, samples, - internalformat, width, height, fixedsamplelocations))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureMultisampleANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorage2DMultisampleANGLE( + context, angle::EntryPoint::GLTexStorage2DMultisampleANGLE, targetPacked, + samples, internalformat, width, height, fixedsamplelocations); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorage2DMultisampleANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage2DMultisample(targetPacked, samples, internalformat, width, height, fixedsamplelocations); @@ -4715,7 +6801,8 @@ void GL_APIENTRY GL_TexStorage2DMultisampleANGLE(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorage2DMultisampleANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4724,18 +6811,34 @@ void GL_APIENTRY GL_GetMultisamplefvANGLE(GLenum pname, GLuint index, GLfloat *v { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetMultisamplefvANGLE, - "context = %d, pname = %s, index = %u, val = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::AllEnums, pname), index, (uintptr_t)val); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetMultisamplefvANGLE, + "context = %d, pname = %s, index = %u, val = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, pname), index, + (uintptr_t)val)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetMultisamplefvANGLE(context, angle::EntryPoint::GLGetMultisamplefvANGLE, - pname, index, val)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureMultisampleANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetMultisamplefvANGLE( + context, angle::EntryPoint::GLGetMultisamplefvANGLE, pname, index, val); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetMultisamplefvANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getMultisamplefv(pname, index, val); } @@ -4743,7 +6846,7 @@ void GL_APIENTRY GL_GetMultisamplefvANGLE(GLenum pname, GLuint index, GLfloat *v } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetMultisamplefvANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4752,20 +6855,33 @@ void GL_APIENTRY GL_SampleMaskiANGLE(GLuint maskNumber, GLbitfield mask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSampleMaskiANGLE, "context = %d, maskNumber = %u, mask = %s", CID(context), - maskNumber, GLbitfieldToString(GLESEnum::AllEnums, mask).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLSampleMaskiANGLE, "context = %d, maskNumber = %u, mask = %s", + CID(context), maskNumber, + GLbitfieldToString(GLESEnum::AllEnums, mask).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleMaskiANGLE) && - ValidateSampleMaskiANGLE(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSampleMaskiANGLE, maskNumber, mask))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureMultisampleANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSampleMaskiANGLE( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLSampleMaskiANGLE, maskNumber, mask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSampleMaskiANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateSampleMaski(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), maskNumber, mask); @@ -4774,7 +6890,7 @@ void GL_APIENTRY GL_SampleMaskiANGLE(GLuint maskNumber, GLbitfield mask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSampleMaskiANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4790,20 +6906,37 @@ void GL_APIENTRY GL_GetTranslatedShaderSourceANGLE(GLuint shader, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTranslatedShaderSourceANGLE, - "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", source = 0x%016" PRIxPTR "", - CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)source); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTranslatedShaderSourceANGLE, + "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", source = 0x%016" PRIxPTR "", + CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)source)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID shaderPacked = PackParam(shader); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTranslatedShaderSourceANGLE( - context, angle::EntryPoint::GLGetTranslatedShaderSourceANGLE, - shaderPacked, bufSize, length, source)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().translatedShaderSourceANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTranslatedShaderSourceANGLE( + context, angle::EntryPoint::GLGetTranslatedShaderSourceANGLE, shaderPacked, + bufSize, length, source); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetTranslatedShaderSourceANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTranslatedShaderSource(shaderPacked, bufSize, length, source); } @@ -4812,7 +6945,8 @@ void GL_APIENTRY GL_GetTranslatedShaderSourceANGLE(GLuint shader, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetTranslatedShaderSourceANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4824,23 +6958,36 @@ void GL_APIENTRY GL_AcquireTexturesANGLE(GLuint numTextures, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLAcquireTexturesANGLE, - "context = %d, numTextures = %u, textures = 0x%016" PRIxPTR ", layouts = 0x%016" PRIxPTR - "", - CID(context), numTextures, (uintptr_t)textures, (uintptr_t)layouts); + ANGLE_UNSAFE_TODO(EVENT(context, GLAcquireTexturesANGLE, + "context = %d, numTextures = %u, textures = 0x%016" PRIxPTR + ", layouts = 0x%016" PRIxPTR "", + CID(context), numTextures, (uintptr_t)textures, (uintptr_t)layouts)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const TextureID *texturesPacked = PackParam(textures); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLAcquireTexturesANGLE) && - ValidateAcquireTexturesANGLE(context, angle::EntryPoint::GLAcquireTexturesANGLE, - numTextures, texturesPacked, layouts))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().vulkanImageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateAcquireTexturesANGLE(context, angle::EntryPoint::GLAcquireTexturesANGLE, + numTextures, texturesPacked, layouts); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLAcquireTexturesANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->acquireTextures(numTextures, texturesPacked, layouts); } @@ -4849,7 +6996,7 @@ void GL_APIENTRY GL_AcquireTexturesANGLE(GLuint numTextures, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLAcquireTexturesANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4860,23 +7007,36 @@ void GL_APIENTRY GL_ReleaseTexturesANGLE(GLuint numTextures, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReleaseTexturesANGLE, - "context = %d, numTextures = %u, textures = 0x%016" PRIxPTR ", layouts = 0x%016" PRIxPTR - "", - CID(context), numTextures, (uintptr_t)textures, (uintptr_t)layouts); + ANGLE_UNSAFE_TODO(EVENT(context, GLReleaseTexturesANGLE, + "context = %d, numTextures = %u, textures = 0x%016" PRIxPTR + ", layouts = 0x%016" PRIxPTR "", + CID(context), numTextures, (uintptr_t)textures, (uintptr_t)layouts)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const TextureID *texturesPacked = PackParam(textures); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReleaseTexturesANGLE) && - ValidateReleaseTexturesANGLE(context, angle::EntryPoint::GLReleaseTexturesANGLE, - numTextures, texturesPacked, layouts))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().vulkanImageANGLE)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateReleaseTexturesANGLE(context, angle::EntryPoint::GLReleaseTexturesANGLE, + numTextures, texturesPacked, layouts); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLReleaseTexturesANGLE); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->releaseTextures(numTextures, texturesPacked, layouts); } @@ -4885,7 +7045,7 @@ void GL_APIENTRY GL_ReleaseTexturesANGLE(GLuint numTextures, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReleaseTexturesANGLE); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4894,50 +7054,49 @@ void GL_APIENTRY GL_ReleaseTexturesANGLE(GLuint numTextures, // GL_APPLE_clip_distance -// GL_ARB_sync -// ClientWaitSync is already defined. - -// DeleteSync is already defined. - -// FenceSync is already defined. - -// GetInteger64v is already defined. - -// GetSynciv is already defined. - -// IsSync is already defined. - -// WaitSync is already defined. - // GL_ARM_rgba8 // GL_ARM_shader_framebuffer_fetch // GL_ARM_shader_framebuffer_fetch_depth_stencil +// GL_ARM_texture_unnormalized_coordinates + // GL_CHROMIUM_bind_uniform_location void GL_APIENTRY GL_BindUniformLocationCHROMIUM(GLuint program, GLint location, const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindUniformLocationCHROMIUM, - "context = %d, program = %u, location = %d, name = 0x%016" PRIxPTR "", CID(context), - program, location, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindUniformLocationCHROMIUM, + "context = %d, program = %u, location = %d, name = 0x%016" PRIxPTR "", + CID(context), program, location, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindUniformLocationCHROMIUM) && - ValidateBindUniformLocationCHROMIUM(context, - angle::EntryPoint::GLBindUniformLocationCHROMIUM, - programPacked, locationPacked, name))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().bindUniformLocationCHROMIUM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindUniformLocationCHROMIUM( + context, angle::EntryPoint::GLBindUniformLocationCHROMIUM, programPacked, + locationPacked, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBindUniformLocationCHROMIUM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindUniformLocation(programPacked, locationPacked, name); } @@ -4946,7 +7105,8 @@ void GL_APIENTRY GL_BindUniformLocationCHROMIUM(GLuint program, GLint location, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBindUniformLocationCHROMIUM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -4956,23 +7116,37 @@ void GL_APIENTRY GL_CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedCopyTextureCHROMIUM, "context = %d, sourceId = %u, destId = %u", - CID(context), sourceId, destId); + ANGLE_UNSAFE_TODO(EVENT(context, GLCompressedCopyTextureCHROMIUM, + "context = %d, sourceId = %u, destId = %u", CID(context), sourceId, + destId)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID sourceIdPacked = PackParam(sourceId); TextureID destIdPacked = PackParam(destId); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedCopyTextureCHROMIUM) && - ValidateCompressedCopyTextureCHROMIUM( - context, angle::EntryPoint::GLCompressedCopyTextureCHROMIUM, sourceIdPacked, - destIdPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyCompressedTextureCHROMIUM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedCopyTextureCHROMIUM( + context, angle::EntryPoint::GLCompressedCopyTextureCHROMIUM, sourceIdPacked, + destIdPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLCompressedCopyTextureCHROMIUM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedCopyTexture(sourceIdPacked, destIdPacked); } @@ -4981,7 +7155,8 @@ void GL_APIENTRY GL_CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedCopyTextureCHROMIUM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5000,31 +7175,44 @@ void GL_APIENTRY GL_CopyTextureCHROMIUM(GLuint sourceId, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyTextureCHROMIUM, - "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, destLevel " - "= %d, internalFormat = %d, destType = %s, unpackFlipY = %s, unpackPremultiplyAlpha = " - "%s, unpackUnmultiplyAlpha = %s", - CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), - destId, destLevel, internalFormat, GLenumToString(GLESEnum::AllEnums, destType), - GLbooleanToString(unpackFlipY), GLbooleanToString(unpackPremultiplyAlpha), - GLbooleanToString(unpackUnmultiplyAlpha)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopyTextureCHROMIUM, + "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, " + "destLevel = %d, internalFormat = %d, destType = %s, unpackFlipY = %s, " + "unpackPremultiplyAlpha = %s, unpackUnmultiplyAlpha = %s", + CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), + destId, destLevel, internalFormat, GLenumToString(GLESEnum::AllEnums, destType), + GLbooleanToString(unpackFlipY), GLbooleanToString(unpackPremultiplyAlpha), + GLbooleanToString(unpackUnmultiplyAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID sourceIdPacked = PackParam(sourceId); TextureTarget destTargetPacked = PackParam(destTarget); TextureID destIdPacked = PackParam(destId); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyTextureCHROMIUM) && - ValidateCopyTextureCHROMIUM( - context, angle::EntryPoint::GLCopyTextureCHROMIUM, sourceIdPacked, sourceLevel, - destTargetPacked, destIdPacked, destLevel, internalFormat, destType, unpackFlipY, - unpackPremultiplyAlpha, unpackUnmultiplyAlpha))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyTextureCHROMIUM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyTextureCHROMIUM( + context, angle::EntryPoint::GLCopyTextureCHROMIUM, sourceIdPacked, sourceLevel, + destTargetPacked, destIdPacked, destLevel, internalFormat, destType, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopyTextureCHROMIUM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyTexture(sourceIdPacked, sourceLevel, destTargetPacked, destIdPacked, destLevel, internalFormat, destType, unpackFlipY, @@ -5036,7 +7224,7 @@ void GL_APIENTRY GL_CopyTextureCHROMIUM(GLuint sourceId, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyTextureCHROMIUM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5058,30 +7246,43 @@ void GL_APIENTRY GL_CopySubTextureCHROMIUM(GLuint sourceId, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopySubTextureCHROMIUM, - "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, destLevel " - "= %d, xoffset = %d, yoffset = %d, x = %d, y = %d, width = %d, height = %d, unpackFlipY " - "= %s, unpackPremultiplyAlpha = %s, unpackUnmultiplyAlpha = %s", - CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), - destId, destLevel, xoffset, yoffset, x, y, width, height, GLbooleanToString(unpackFlipY), - GLbooleanToString(unpackPremultiplyAlpha), GLbooleanToString(unpackUnmultiplyAlpha)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLCopySubTextureCHROMIUM, + "context = %d, sourceId = %u, sourceLevel = %d, destTarget = %s, destId = %u, destLevel = " + "%d, xoffset = %d, yoffset = %d, x = %d, y = %d, width = %d, height = %d, unpackFlipY = " + "%s, unpackPremultiplyAlpha = %s, unpackUnmultiplyAlpha = %s", + CID(context), sourceId, sourceLevel, GLenumToString(GLESEnum::AllEnums, destTarget), destId, + destLevel, xoffset, yoffset, x, y, width, height, GLbooleanToString(unpackFlipY), + GLbooleanToString(unpackPremultiplyAlpha), GLbooleanToString(unpackUnmultiplyAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID sourceIdPacked = PackParam(sourceId); TextureTarget destTargetPacked = PackParam(destTarget); TextureID destIdPacked = PackParam(destId); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopySubTextureCHROMIUM) && - ValidateCopySubTextureCHROMIUM( - context, angle::EntryPoint::GLCopySubTextureCHROMIUM, sourceIdPacked, sourceLevel, - destTargetPacked, destIdPacked, destLevel, xoffset, yoffset, x, y, width, height, - unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyTextureCHROMIUM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopySubTextureCHROMIUM( + context, angle::EntryPoint::GLCopySubTextureCHROMIUM, sourceIdPacked, + sourceLevel, destTargetPacked, destIdPacked, destLevel, xoffset, yoffset, x, y, + width, height, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopySubTextureCHROMIUM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copySubTexture(sourceIdPacked, sourceLevel, destTargetPacked, destIdPacked, destLevel, xoffset, yoffset, x, y, width, height, unpackFlipY, @@ -5093,7 +7294,7 @@ void GL_APIENTRY GL_CopySubTextureCHROMIUM(GLuint sourceId, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopySubTextureCHROMIUM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5103,20 +7304,32 @@ void GL_APIENTRY GL_CoverageModulationCHROMIUM(GLenum components) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCoverageModulationCHROMIUM, "context = %d, components = %s", CID(context), - GLenumToString(GLESEnum::AllEnums, components)); + ANGLE_UNSAFE_TODO(EVENT(context, GLCoverageModulationCHROMIUM, "context = %d, components = %s", + CID(context), GLenumToString(GLESEnum::AllEnums, components))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCoverageModulationCHROMIUM) && - ValidateCoverageModulationCHROMIUM( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCoverageModulationCHROMIUM, components))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferMixedSamplesCHROMIUM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCoverageModulationCHROMIUM( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLCoverageModulationCHROMIUM, components); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCoverageModulationCHROMIUM); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateCoverageModulation(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), components); @@ -5125,7 +7338,8 @@ void GL_APIENTRY GL_CoverageModulationCHROMIUM(GLenum components) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCoverageModulationCHROMIUM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5135,23 +7349,36 @@ void GL_APIENTRY GL_LoseContextCHROMIUM(GLenum current, GLenum other) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLoseContextCHROMIUM, "context = %d, current = %s, other = %s", CID(context), - GLenumToString(GLESEnum::GraphicsResetStatus, current), - GLenumToString(GLESEnum::GraphicsResetStatus, other)); + ANGLE_UNSAFE_TODO(EVENT(context, GLLoseContextCHROMIUM, + "context = %d, current = %s, other = %s", CID(context), + GLenumToString(GLESEnum::GraphicsResetStatus, current), + GLenumToString(GLESEnum::GraphicsResetStatus, other))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { GraphicsResetStatus currentPacked = PackParam(current); GraphicsResetStatus otherPacked = PackParam(other); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLoseContextCHROMIUM) && - ValidateLoseContextCHROMIUM(context, angle::EntryPoint::GLLoseContextCHROMIUM, - currentPacked, otherPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().loseContextCHROMIUM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLoseContextCHROMIUM( + context, angle::EntryPoint::GLLoseContextCHROMIUM, currentPacked, otherPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLLoseContextCHROMIUM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->loseContext(currentPacked, otherPacked); } @@ -5159,7 +7386,7 @@ void GL_APIENTRY GL_LoseContextCHROMIUM(GLenum current, GLenum other) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLoseContextCHROMIUM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5173,24 +7400,37 @@ void GL_APIENTRY GL_EGLImageTargetTexStorageEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEGLImageTargetTexStorageEXT, - "context = %d, target = %s, image = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, target), (uintptr_t)image, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EVENT(context, GLEGLImageTargetTexStorageEXT, + "context = %d, target = %s, image = 0x%016" PRIxPTR + ", attrib_list = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + (uintptr_t)image, (uintptr_t)attrib_list)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { egl::ImageID imagePacked = PackParam(image); SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEGLImageTargetTexStorageEXT) && - ValidateEGLImageTargetTexStorageEXT(context, - angle::EntryPoint::GLEGLImageTargetTexStorageEXT, - target, imagePacked, attrib_list))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().EGLImageStorageEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEGLImageTargetTexStorageEXT( + context, angle::EntryPoint::GLEGLImageTargetTexStorageEXT, target, imagePacked, + attrib_list); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEGLImageTargetTexStorageEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->eGLImageTargetTexStorage(target, imagePacked, attrib_list); } @@ -5199,46 +7439,12 @@ void GL_APIENTRY GL_EGLImageTargetTexStorageEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLEGLImageTargetTexStorageEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -void GL_APIENTRY GL_EGLImageTargetTextureStorageEXT(GLuint texture, - GLeglImageOES image, - const GLint *attrib_list) -{ - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLEGLImageTargetTextureStorageEXT, - "context = %d, texture = %u, image = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "", - CID(context), texture, (uintptr_t)image, (uintptr_t)attrib_list); - - if (context) - { - egl::ImageID imagePacked = PackParam(image); - SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEGLImageTargetTextureStorageEXT) && - ValidateEGLImageTargetTextureStorageEXT( - context, angle::EntryPoint::GLEGLImageTargetTextureStorageEXT, texture, - imagePacked, attrib_list))); - if (isCallValid) - { - context->eGLImageTargetTextureStorage(texture, imagePacked, attrib_list); - } - ANGLE_CAPTURE_GL(EGLImageTargetTextureStorageEXT, isCallValid, context, texture, - imagePacked, attrib_list); - } - else - { - GenerateContextLostErrorOnCurrentGlobalContext(); - } - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); -} // GL_EXT_EGL_image_storage_compression @@ -5253,20 +7459,38 @@ void GL_APIENTRY GL_DrawArraysInstancedBaseInstanceEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArraysInstancedBaseInstanceEXT, - "context = %d, mode = %s, first = %d, count = %d, instancecount = %d, baseinstance = %u", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), first, count, instancecount, - baseinstance); + ANGLE_UNSAFE_TODO(EVENT( + context, GLDrawArraysInstancedBaseInstanceEXT, + "context = %d, mode = %s, first = %d, count = %d, instancecount = %d, baseinstance = %u", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), first, count, instancecount, + baseinstance)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawArraysInstancedBaseInstanceEXT( - context, angle::EntryPoint::GLDrawArraysInstancedBaseInstanceEXT, - modePacked, first, count, instancecount, baseinstance)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseInstanceEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawArraysInstancedBaseInstanceEXT( + context, angle::EntryPoint::GLDrawArraysInstancedBaseInstanceEXT, modePacked, + first, count, instancecount, baseinstance); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawArraysInstancedBaseInstanceEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawArraysInstancedBaseInstance(modePacked, first, count, instancecount, baseinstance); @@ -5276,7 +7500,8 @@ void GL_APIENTRY GL_DrawArraysInstancedBaseInstanceEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawArraysInstancedBaseInstanceEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5290,24 +7515,41 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseInstanceEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedBaseInstanceEXT, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instancecount = %d, baseinstance = %u", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::PrimitiveType, type), (uintptr_t)indices, instancecount, - baseinstance); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedBaseInstanceEXT, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instancecount = %d, baseinstance = %u", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, + baseinstance)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawElementsInstancedBaseInstanceEXT( - context, angle::EntryPoint::GLDrawElementsInstancedBaseInstanceEXT, modePacked, - count, typePacked, indices, instancecount, baseinstance)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseInstanceEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedBaseInstanceEXT( + context, angle::EntryPoint::GLDrawElementsInstancedBaseInstanceEXT, modePacked, + count, typePacked, indices, instancecount, baseinstance); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawElementsInstancedBaseInstanceEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstancedBaseInstance(modePacked, count, typePacked, indices, instancecount, baseinstance); @@ -5317,7 +7559,8 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseInstanceEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedBaseInstanceEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5332,24 +7575,42 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexBaseInstanceEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedBaseVertexBaseInstanceEXT, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instancecount = %d, basevertex = %d, baseinstance = %u", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, - basevertex, baseinstance); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedBaseVertexBaseInstanceEXT, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instancecount = %d, basevertex = %d, baseinstance = %u", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, + basevertex, baseinstance)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawElementsInstancedBaseVertexBaseInstanceEXT( - context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceEXT, - modePacked, count, typePacked, indices, instancecount, basevertex, baseinstance)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().baseInstanceEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedBaseVertexBaseInstanceEXT( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceEXT, + modePacked, count, typePacked, indices, instancecount, basevertex, + baseinstance); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstancedBaseVertexBaseInstance( modePacked, count, typePacked, indices, instancecount, basevertex, baseinstance); @@ -5360,7 +7621,8 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexBaseInstanceEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedBaseVertexBaseInstanceEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5370,22 +7632,35 @@ void GL_APIENTRY GL_BindFragDataLocationEXT(GLuint program, GLuint color, const { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindFragDataLocationEXT, - "context = %d, program = %u, color = %u, name = 0x%016" PRIxPTR "", CID(context), program, - color, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindFragDataLocationEXT, + "context = %d, program = %u, color = %u, name = 0x%016" PRIxPTR "", + CID(context), program, color, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindFragDataLocationEXT) && - ValidateBindFragDataLocationEXT(context, angle::EntryPoint::GLBindFragDataLocationEXT, - programPacked, color, name))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blendFuncExtendedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindFragDataLocationEXT( + context, angle::EntryPoint::GLBindFragDataLocationEXT, programPacked, color, + name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBindFragDataLocationEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindFragDataLocation(programPacked, color, name); } @@ -5393,7 +7668,8 @@ void GL_APIENTRY GL_BindFragDataLocationEXT(GLuint program, GLuint color, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBindFragDataLocationEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5405,23 +7681,37 @@ void GL_APIENTRY GL_BindFragDataLocationIndexedEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindFragDataLocationIndexedEXT, - "context = %d, program = %u, colorNumber = %u, index = %u, name = 0x%016" PRIxPTR "", - CID(context), program, colorNumber, index, (uintptr_t)name); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBindFragDataLocationIndexedEXT, + "context = %d, program = %u, colorNumber = %u, index = %u, name = 0x%016" PRIxPTR "", + CID(context), program, colorNumber, index, (uintptr_t)name)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindFragDataLocationIndexedEXT) && - ValidateBindFragDataLocationIndexedEXT( - context, angle::EntryPoint::GLBindFragDataLocationIndexedEXT, programPacked, - colorNumber, index, name))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blendFuncExtendedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindFragDataLocationIndexedEXT( + context, angle::EntryPoint::GLBindFragDataLocationIndexedEXT, programPacked, + colorNumber, index, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLBindFragDataLocationIndexedEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindFragDataLocationIndexed(programPacked, colorNumber, index, name); } @@ -5430,7 +7720,8 @@ void GL_APIENTRY GL_BindFragDataLocationIndexedEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBindFragDataLocationIndexedEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5439,19 +7730,35 @@ GLint GL_APIENTRY GL_GetFragDataIndexEXT(GLuint program, const GLchar *name) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFragDataIndexEXT, "context = %d, program = %u, name = 0x%016" PRIxPTR "", - CID(context), program, (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFragDataIndexEXT, + "context = %d, program = %u, name = 0x%016" PRIxPTR "", CID(context), + program, (uintptr_t)name)); GLint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFragDataIndexEXT(context, angle::EntryPoint::GLGetFragDataIndexEXT, - programPacked, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blendFuncExtendedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFragDataIndexEXT( + context, angle::EntryPoint::GLGetFragDataIndexEXT, programPacked, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetFragDataIndexEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getFragDataIndex(programPacked, name); } @@ -5464,7 +7771,7 @@ GLint GL_APIENTRY GL_GetFragDataIndexEXT(GLuint program, const GLchar *name) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetFragDataIndexEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -5477,21 +7784,38 @@ GLint GL_APIENTRY GL_GetProgramResourceLocationIndexEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramResourceLocationIndexEXT, - "context = %d, program = %u, programInterface = %s, name = 0x%016" PRIxPTR "", - CID(context), program, GLenumToString(GLESEnum::ProgramInterface, programInterface), - (uintptr_t)name); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetProgramResourceLocationIndexEXT, + "context = %d, program = %u, programInterface = %s, name = 0x%016" PRIxPTR "", CID(context), + program, GLenumToString(GLESEnum::ProgramInterface, programInterface), (uintptr_t)name)); GLint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramResourceLocationIndexEXT( - context, angle::EntryPoint::GLGetProgramResourceLocationIndexEXT, - programPacked, programInterface, name)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blendFuncExtendedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramResourceLocationIndexEXT( + context, angle::EntryPoint::GLGetProgramResourceLocationIndexEXT, programPacked, + programInterface, name); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetProgramResourceLocationIndexEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getProgramResourceLocationIndex(programPacked, programInterface, name); @@ -5507,7 +7831,8 @@ GLint GL_APIENTRY GL_GetProgramResourceLocationIndexEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramResourceLocationIndexEXT); returnValue = GetDefaultReturnValue(); } @@ -5525,24 +7850,38 @@ void GL_APIENTRY GL_BufferStorageEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBufferStorageEXT, - "context = %d, target = %s, size = %llu, data = 0x%016" PRIxPTR ", flags = %s", - CID(context), GLenumToString(GLESEnum::BufferStorageTarget, target), - static_cast(size), (uintptr_t)data, - GLbitfieldToString(GLESEnum::BufferStorageMask, flags).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLBufferStorageEXT, + "context = %d, target = %s, size = %llu, data = 0x%016" PRIxPTR + ", flags = %s", + CID(context), GLenumToString(GLESEnum::BufferStorageTarget, target), + static_cast(size), (uintptr_t)data, + GLbitfieldToString(GLESEnum::BufferStorageMask, flags).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBufferStorageEXT) && - ValidateBufferStorageEXT(context, angle::EntryPoint::GLBufferStorageEXT, targetPacked, - size, data, flags))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().bufferStorageEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateBufferStorageEXT(context, angle::EntryPoint::GLBufferStorageEXT, + targetPacked, size, data, flags); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBufferStorageEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bufferStorage(targetPacked, size, data, flags); } @@ -5550,7 +7889,7 @@ void GL_APIENTRY GL_BufferStorageEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBufferStorageEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5561,24 +7900,37 @@ GL_ClearTexImageEXT(GLuint texture, GLint level, GLenum format, GLenum type, con { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearTexImageEXT, - "context = %d, texture = %u, level = %d, format = %s, type = %s, data = 0x%016" PRIxPTR - "", - CID(context), texture, level, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLClearTexImageEXT, + "context = %d, texture = %u, level = %d, format = %s, type = %s, data = 0x%016" PRIxPTR "", + CID(context), texture, level, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearTexImageEXT) && - ValidateClearTexImageEXT(context, angle::EntryPoint::GLClearTexImageEXT, - texturePacked, level, format, type, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().clearTextureEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateClearTexImageEXT(context, angle::EntryPoint::GLClearTexImageEXT, + texturePacked, level, format, type, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLClearTexImageEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clearTexImage(texturePacked, level, format, type, data); } @@ -5587,7 +7939,7 @@ GL_ClearTexImageEXT(GLuint texture, GLint level, GLenum format, GLenum type, con } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearTexImageEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5606,26 +7958,39 @@ void GL_APIENTRY GL_ClearTexSubImageEXT(GLuint texture, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClearTexSubImageEXT, - "context = %d, texture = %u, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width " - "= %d, height = %d, depth = %d, format = %s, type = %s, data = 0x%016" PRIxPTR "", - CID(context), texture, level, xoffset, yoffset, zoffset, width, height, depth, - GLenumToString(GLESEnum::PixelFormat, format), GLenumToString(GLESEnum::PixelType, type), - (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLClearTexSubImageEXT, + "context = %d, texture = %u, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width = " + "%d, height = %d, depth = %d, format = %s, type = %s, data = 0x%016" PRIxPTR "", + CID(context), texture, level, xoffset, yoffset, zoffset, width, height, depth, + GLenumToString(GLESEnum::PixelFormat, format), GLenumToString(GLESEnum::PixelType, type), + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClearTexSubImageEXT) && - ValidateClearTexSubImageEXT(context, angle::EntryPoint::GLClearTexSubImageEXT, - texturePacked, level, xoffset, yoffset, zoffset, width, - height, depth, format, type, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().clearTextureEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClearTexSubImageEXT( + context, angle::EntryPoint::GLClearTexSubImageEXT, texturePacked, level, + xoffset, yoffset, zoffset, width, height, depth, format, type, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLClearTexSubImageEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->clearTexSubImage(texturePacked, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); @@ -5635,7 +8000,7 @@ void GL_APIENTRY GL_ClearTexSubImageEXT(GLuint texture, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClearTexSubImageEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5645,19 +8010,35 @@ void GL_APIENTRY GL_ClipControlEXT(GLenum origin, GLenum depth) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLClipControlEXT, "context = %d, origin = %s, depth = %s", CID(context), - GLenumToString(GLESEnum::AllEnums, origin), GLenumToString(GLESEnum::AllEnums, depth)); + ANGLE_UNSAFE_TODO(EVENT(context, GLClipControlEXT, "context = %d, origin = %s, depth = %s", + CID(context), GLenumToString(GLESEnum::AllEnums, origin), + GLenumToString(GLESEnum::AllEnums, depth))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ClipOrigin originPacked = PackParam(origin); ClipDepthMode depthPacked = PackParam(depth); - bool isCallValid = - (context->skipValidation() || - ValidateClipControlEXT( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLClipControlEXT, originPacked, depthPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().clipControlEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateClipControlEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLClipControlEXT, originPacked, depthPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLClipControlEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateClipControl(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), originPacked, @@ -5667,7 +8048,7 @@ void GL_APIENTRY GL_ClipControlEXT(GLenum origin, GLenum depth) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLClipControlEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5699,28 +8080,41 @@ void GL_APIENTRY GL_CopyImageSubDataEXT(GLuint srcName, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyImageSubDataEXT, - "context = %d, srcName = %u, srcTarget = %s, srcLevel = %d, srcX = %d, srcY = %d, srcZ = " - "%d, dstName = %u, dstTarget = %s, dstLevel = %d, dstX = %d, dstY = %d, dstZ = %d, " - "srcWidth = %d, srcHeight = %d, srcDepth = %d", - CID(context), srcName, GLenumToString(GLESEnum::CopyBufferSubDataTarget, srcTarget), - srcLevel, srcX, srcY, srcZ, dstName, - GLenumToString(GLESEnum::CopyBufferSubDataTarget, dstTarget), dstLevel, dstX, dstY, dstZ, - srcWidth, srcHeight, srcDepth); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopyImageSubDataEXT, + "context = %d, srcName = %u, srcTarget = %s, srcLevel = %d, srcX = %d, srcY = %d, " + "srcZ = %d, dstName = %u, dstTarget = %s, dstLevel = %d, dstX = %d, dstY = %d, dstZ " + "= %d, srcWidth = %d, srcHeight = %d, srcDepth = %d", + CID(context), srcName, GLenumToString(GLESEnum::CopyBufferSubDataTarget, srcTarget), + srcLevel, srcX, srcY, srcZ, dstName, + GLenumToString(GLESEnum::CopyBufferSubDataTarget, dstTarget), dstLevel, dstX, dstY, + dstZ, srcWidth, srcHeight, srcDepth)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyImageSubDataEXT) && - ValidateCopyImageSubDataEXT(context, angle::EntryPoint::GLCopyImageSubDataEXT, - srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, - dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, - srcHeight, srcDepth))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyImageEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyImageSubDataEXT( + context, angle::EntryPoint::GLCopyImageSubDataEXT, srcName, srcTarget, srcLevel, + srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, + srcHeight, srcDepth); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopyImageSubDataEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, @@ -5732,7 +8126,7 @@ void GL_APIENTRY GL_CopyImageSubDataEXT(GLuint srcName, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyImageSubDataEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5743,20 +8137,37 @@ GL_GetObjectLabelEXT(GLenum type, GLuint object, GLsizei bufSize, GLsizei *lengt { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetObjectLabelEXT, - "context = %d, type = %s, object = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", label = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, type), object, bufSize, - (uintptr_t)length, (uintptr_t)label); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetObjectLabelEXT, + "context = %d, type = %s, object = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", label = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, type), object, bufSize, + (uintptr_t)length, (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetObjectLabelEXT(context, angle::EntryPoint::GLGetObjectLabelEXT, type, - object, bufSize, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugLabelEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetObjectLabelEXT(context, angle::EntryPoint::GLGetObjectLabelEXT, type, + object, bufSize, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetObjectLabelEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getObjectLabel(type, object, bufSize, length, label); } @@ -5765,7 +8176,7 @@ GL_GetObjectLabelEXT(GLenum type, GLuint object, GLsizei bufSize, GLsizei *lengt } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetObjectLabelEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5774,21 +8185,34 @@ void GL_APIENTRY GL_LabelObjectEXT(GLenum type, GLuint object, GLsizei length, c { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLabelObjectEXT, - "context = %d, type = %s, object = %u, length = %d, label = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, type), object, length, (uintptr_t)label); + ANGLE_UNSAFE_TODO(EVENT( + context, GLLabelObjectEXT, + "context = %d, type = %s, object = %u, length = %d, label = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, type), object, length, (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLLabelObjectEXT) && - ValidateLabelObjectEXT(context, angle::EntryPoint::GLLabelObjectEXT, type, object, - length, label))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugLabelEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLabelObjectEXT(context, angle::EntryPoint::GLLabelObjectEXT, + type, object, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLLabelObjectEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->labelObject(type, object, length, label); } @@ -5796,7 +8220,7 @@ void GL_APIENTRY GL_LabelObjectEXT(GLenum type, GLuint object, GLsizei length, c } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLLabelObjectEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5808,20 +8232,32 @@ void GL_APIENTRY GL_InsertEventMarkerEXT(GLsizei length, const GLchar *marker) Context *context = GetValidGlobalContext(); // Don't run the EVENT() macro on the EXT_debug_marker entry points. // It can interfere with the debug events being set by the caller. - // EVENT(context, GLInsertEventMarkerEXT, "context = %d, length = %d, marker = 0x%016" PRIxPTR - // "", CID(context), length, (uintptr_t)marker); + // ANGLE_UNSAFE_TODO(EVENT(context, GLInsertEventMarkerEXT, "context = %d, length = %d, marker = + // 0x%016" PRIxPTR "", CID(context), length, (uintptr_t)marker)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLInsertEventMarkerEXT) && - ValidateInsertEventMarkerEXT(context, angle::EntryPoint::GLInsertEventMarkerEXT, - length, marker))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugMarkerEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateInsertEventMarkerEXT( + context, angle::EntryPoint::GLInsertEventMarkerEXT, length, marker); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLInsertEventMarkerEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->insertEventMarker(length, marker); } @@ -5829,7 +8265,7 @@ void GL_APIENTRY GL_InsertEventMarkerEXT(GLsizei length, const GLchar *marker) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLInsertEventMarkerEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5840,18 +8276,31 @@ void GL_APIENTRY GL_PopGroupMarkerEXT() Context *context = GetValidGlobalContext(); // Don't run the EVENT() macro on the EXT_debug_marker entry points. // It can interfere with the debug events being set by the caller. - // EVENT(context, GLPopGroupMarkerEXT, "context = %d", CID(context)); + // ANGLE_UNSAFE_TODO(EVENT(context, GLPopGroupMarkerEXT, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPopGroupMarkerEXT) && - ValidatePopGroupMarkerEXT(context, angle::EntryPoint::GLPopGroupMarkerEXT))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugMarkerEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidatePopGroupMarkerEXT(context, angle::EntryPoint::GLPopGroupMarkerEXT); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPopGroupMarkerEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->popGroupMarker(); } @@ -5859,7 +8308,7 @@ void GL_APIENTRY GL_PopGroupMarkerEXT() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPopGroupMarkerEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5870,20 +8319,32 @@ void GL_APIENTRY GL_PushGroupMarkerEXT(GLsizei length, const GLchar *marker) Context *context = GetValidGlobalContext(); // Don't run the EVENT() macro on the EXT_debug_marker entry points. // It can interfere with the debug events being set by the caller. - // EVENT(context, GLPushGroupMarkerEXT, "context = %d, length = %d, marker = 0x%016" PRIxPTR "", - // CID(context), length, (uintptr_t)marker); + // ANGLE_UNSAFE_TODO(EVENT(context, GLPushGroupMarkerEXT, "context = %d, length = %d, marker = + // 0x%016" PRIxPTR "", CID(context), length, (uintptr_t)marker)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPushGroupMarkerEXT) && - ValidatePushGroupMarkerEXT(context, angle::EntryPoint::GLPushGroupMarkerEXT, length, - marker))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugMarkerEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePushGroupMarkerEXT( + context, angle::EntryPoint::GLPushGroupMarkerEXT, length, marker); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPushGroupMarkerEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->pushGroupMarker(length, marker); } @@ -5891,7 +8352,7 @@ void GL_APIENTRY GL_PushGroupMarkerEXT(GLsizei length, const GLchar *marker) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPushGroupMarkerEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5905,22 +8366,40 @@ void GL_APIENTRY GL_DiscardFramebufferEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDiscardFramebufferEXT, - "context = %d, target = %s, numAttachments = %d, attachments = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), numAttachments, - (uintptr_t)attachments); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDiscardFramebufferEXT, + "context = %d, target = %s, numAttachments = %d, attachments = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), numAttachments, + (uintptr_t)attachments)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDiscardFramebufferEXT) && - ValidateDiscardFramebufferEXT(context, angle::EntryPoint::GLDiscardFramebufferEXT, - target, numAttachments, attachments))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().discardFramebufferEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDiscardFramebufferEXT( + context, angle::EntryPoint::GLDiscardFramebufferEXT, target, numAttachments, + attachments); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDiscardFramebufferEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->discardFramebuffer(target, numAttachments, attachments); } @@ -5929,7 +8408,7 @@ void GL_APIENTRY GL_DiscardFramebufferEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDiscardFramebufferEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5939,22 +8418,35 @@ void GL_APIENTRY GL_BeginQueryEXT(GLenum target, GLuint id) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBeginQueryEXT, "context = %d, target = %s, id = %u", CID(context), - GLenumToString(GLESEnum::QueryTarget, target), id); + ANGLE_UNSAFE_TODO(EVENT(context, GLBeginQueryEXT, "context = %d, target = %s, id = %u", + CID(context), GLenumToString(GLESEnum::QueryTarget, target), id)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBeginQueryEXT) && - ValidateBeginQueryEXT(context, angle::EntryPoint::GLBeginQueryEXT, targetPacked, - idPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBeginQueryEXT(context, angle::EntryPoint::GLBeginQueryEXT, + targetPacked, idPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBeginQueryEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->beginQuery(targetPacked, idPacked); } @@ -5962,7 +8454,7 @@ void GL_APIENTRY GL_BeginQueryEXT(GLenum target, GLuint id) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBeginQueryEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5971,17 +8463,35 @@ void GL_APIENTRY GL_DeleteQueriesEXT(GLsizei n, const GLuint *ids) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteQueriesEXT, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)ids); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteQueriesEXT, + "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)ids)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const QueryID *idsPacked = PackParam(ids); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDeleteQueriesEXT(context, angle::EntryPoint::GLDeleteQueriesEXT, - n, idsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteQueriesEXT( + context, angle::EntryPoint::GLDeleteQueriesEXT, n, idsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteQueriesEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteQueries(n, idsPacked); } @@ -5989,7 +8499,7 @@ void GL_APIENTRY GL_DeleteQueriesEXT(GLsizei n, const GLuint *ids) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteQueriesEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -5998,20 +8508,34 @@ void GL_APIENTRY GL_EndQueryEXT(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEndQueryEXT, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::QueryTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLEndQueryEXT, "context = %d, target = %s", CID(context), + GLenumToString(GLESEnum::QueryTarget, target))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEndQueryEXT) && - ValidateEndQueryEXT(context, angle::EntryPoint::GLEndQueryEXT, targetPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateEndQueryEXT(context, angle::EntryPoint::GLEndQueryEXT, targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEndQueryEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->endQuery(targetPacked); } @@ -6019,7 +8543,7 @@ void GL_APIENTRY GL_EndQueryEXT(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEndQueryEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6028,17 +8552,35 @@ void GL_APIENTRY GL_GenQueriesEXT(GLsizei n, GLuint *ids) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenQueriesEXT, "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), - n, (uintptr_t)ids); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenQueriesEXT, + "context = %d, n = %d, ids = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)ids)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID *idsPacked = PackParam(ids); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenQueriesEXT(context, angle::EntryPoint::GLGenQueriesEXT, n, idsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenQueriesEXT(context, angle::EntryPoint::GLGenQueriesEXT, n, + idsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenQueriesEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genQueries(n, idsPacked); } @@ -6046,7 +8588,7 @@ void GL_APIENTRY GL_GenQueriesEXT(GLsizei n, GLuint *ids) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenQueriesEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6055,16 +8597,33 @@ void GL_APIENTRY GL_GetInteger64vEXT(GLenum pname, GLint64 *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetInteger64vEXT, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetInteger64vEXT, + "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetInteger64vEXT(context, angle::EntryPoint::GLGetInteger64vEXT, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetInteger64vEXT( + context, angle::EntryPoint::GLGetInteger64vEXT, pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetInteger64vEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getInteger64v(pname, data); } @@ -6072,7 +8631,7 @@ void GL_APIENTRY GL_GetInteger64vEXT(GLenum pname, GLint64 *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetInteger64vEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6081,19 +8640,35 @@ void GL_APIENTRY GL_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 *para { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetQueryObjecti64vEXT, - "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, - GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjecti64vEXT, + "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, + GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetQueryObjecti64vEXT(context, angle::EntryPoint::GLGetQueryObjecti64vEXT, - idPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjecti64vEXT( + context, angle::EntryPoint::GLGetQueryObjecti64vEXT, idPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryObjecti64vEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjecti64v(idPacked, pname, params); } @@ -6109,19 +8684,35 @@ void GL_APIENTRY GL_GetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetQueryObjectivEXT, - "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, - GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectivEXT, + "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, + GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetQueryObjectivEXT(context, angle::EntryPoint::GLGetQueryObjectivEXT, - idPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectivEXT( + context, angle::EntryPoint::GLGetQueryObjectivEXT, idPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryObjectivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectiv(idPacked, pname, params); } @@ -6136,20 +8727,36 @@ void GL_APIENTRY GL_GetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params) void GL_APIENTRY GL_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryObjectui64vEXT, - "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, - GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params); + Context *context = GetGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectui64vEXT, + "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, + GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetQueryObjectui64vEXT(context, angle::EntryPoint::GLGetQueryObjectui64vEXT, - idPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectui64vEXT( + context, angle::EntryPoint::GLGetQueryObjectui64vEXT, idPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryObjectui64vEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectui64v(idPacked, pname, params); } @@ -6157,7 +8764,6 @@ void GL_APIENTRY GL_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *pa } else { - GenerateContextLostErrorOnCurrentGlobalContext(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6165,20 +8771,37 @@ void GL_APIENTRY GL_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *pa void GL_APIENTRY GL_GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryObjectuivEXT, - "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, - GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params); + Context *context = GetGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetQueryObjectuivEXT, + "context = %d, id = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), id, + GLenumToString(GLESEnum::QueryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetQueryObjectuivEXT(context, angle::EntryPoint::GLGetQueryObjectuivEXT, - idPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryObjectuivEXT( + context, angle::EntryPoint::GLGetQueryObjectuivEXT, idPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryObjectuivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryObjectuiv(idPacked, pname, params); } @@ -6186,7 +8809,6 @@ void GL_APIENTRY GL_GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params } else { - GenerateContextLostErrorOnCurrentGlobalContext(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6195,19 +8817,37 @@ void GL_APIENTRY GL_GetQueryivEXT(GLenum target, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetQueryivEXT, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::QueryTarget, target), - GLenumToString(GLESEnum::QueryParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetQueryivEXT, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::QueryTarget, target), + GLenumToString(GLESEnum::QueryParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetQueryivEXT(context, angle::EntryPoint::GLGetQueryivEXT, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetQueryivEXT(context, angle::EntryPoint::GLGetQueryivEXT, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetQueryivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getQueryiv(targetPacked, pname, params); } @@ -6215,7 +8855,7 @@ void GL_APIENTRY GL_GetQueryivEXT(GLenum target, GLenum pname, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetQueryivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6224,16 +8864,34 @@ GLboolean GL_APIENTRY GL_IsQueryEXT(GLuint id) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsQueryEXT, "context = %d, id = %u", CID(context), id); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsQueryEXT, "context = %d, id = %u", CID(context), id)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsQueryEXT(context, angle::EntryPoint::GLIsQueryEXT, idPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT || + context->getExtensions().occlusionQueryBooleanEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsQueryEXT(context, angle::EntryPoint::GLIsQueryEXT, idPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsQueryEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isQuery(idPacked); } @@ -6245,7 +8903,7 @@ GLboolean GL_APIENTRY GL_IsQueryEXT(GLuint id) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsQueryEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -6256,22 +8914,35 @@ void GL_APIENTRY GL_QueryCounterEXT(GLuint id, GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLQueryCounterEXT, "context = %d, id = %u, target = %s", CID(context), id, - GLenumToString(GLESEnum::QueryCounterTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLQueryCounterEXT, "context = %d, id = %u, target = %s", + CID(context), id, + GLenumToString(GLESEnum::QueryCounterTarget, target))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { QueryID idPacked = PackParam(id); QueryType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLQueryCounterEXT) && - ValidateQueryCounterEXT(context, angle::EntryPoint::GLQueryCounterEXT, idPacked, - targetPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().disjointTimerQueryEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateQueryCounterEXT(context, angle::EntryPoint::GLQueryCounterEXT, + idPacked, targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLQueryCounterEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->queryCounter(idPacked, targetPacked); } @@ -6279,7 +8950,7 @@ void GL_APIENTRY GL_QueryCounterEXT(GLuint id, GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLQueryCounterEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6289,19 +8960,33 @@ void GL_APIENTRY GL_DrawBuffersEXT(GLsizei n, const GLenum *bufs) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawBuffersEXT, "context = %d, n = %d, bufs = 0x%016" PRIxPTR "", CID(context), - n, (uintptr_t)bufs); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawBuffersEXT, + "context = %d, n = %d, bufs = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)bufs)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDrawBuffersEXT) && - ValidateDrawBuffersEXT(context, angle::EntryPoint::GLDrawBuffersEXT, n, bufs))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawBuffersEXT(context, angle::EntryPoint::GLDrawBuffersEXT, n, bufs); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawBuffersEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawBuffers(n, bufs); } @@ -6309,7 +8994,7 @@ void GL_APIENTRY GL_DrawBuffersEXT(GLsizei n, const GLenum *bufs) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawBuffersEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6319,19 +9004,34 @@ void GL_APIENTRY GL_BlendEquationSeparateiEXT(GLuint buf, GLenum modeRGB, GLenum { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationSeparateiEXT, - "context = %d, buf = %u, modeRGB = %s, modeAlpha = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), - GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationSeparateiEXT, + "context = %d, buf = %u, modeRGB = %s, modeAlpha = %s", CID(context), + buf, GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), + GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendEquationSeparateiEXT( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationSeparateiEXT, buf, modeRGB, modeAlpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationSeparateiEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationSeparateiEXT, buf, modeRGB, modeAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendEquationSeparateiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationSeparatei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, @@ -6341,7 +9041,8 @@ void GL_APIENTRY GL_BlendEquationSeparateiEXT(GLuint buf, GLenum modeRGB, GLenum } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBlendEquationSeparateiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6350,17 +9051,33 @@ void GL_APIENTRY GL_BlendEquationiEXT(GLuint buf, GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationiEXT, "context = %d, buf = %u, mode = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendEquationModeEXT, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationiEXT, "context = %d, buf = %u, mode = %s", + CID(context), buf, + GLenumToString(GLESEnum::BlendEquationModeEXT, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendEquationiEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationiEXT, buf, mode)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationiEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationiEXT, buf, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendEquationiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationi(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, mode); @@ -6369,7 +9086,7 @@ void GL_APIENTRY GL_BlendEquationiEXT(GLuint buf, GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquationiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6379,22 +9096,38 @@ GL_BlendFuncSeparateiEXT(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlp { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFuncSeparateiEXT, - "context = %d, buf = %u, srcRGB = %s, dstRGB = %s, srcAlpha = %s, dstAlpha = %s", - CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, srcRGB), - GLenumToString(GLESEnum::BlendingFactor, dstRGB), - GLenumToString(GLESEnum::BlendingFactor, srcAlpha), - GLenumToString(GLESEnum::BlendingFactor, dstAlpha)); - - if (context) - { - bool isCallValid = - (context->skipValidation() || - ValidateBlendFuncSeparateiEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFuncSeparateiEXT, buf, srcRGB, - dstRGB, srcAlpha, dstAlpha)); - if (isCallValid) + ANGLE_UNSAFE_TODO( + EVENT(context, GLBlendFuncSeparateiEXT, + "context = %d, buf = %u, srcRGB = %s, dstRGB = %s, srcAlpha = %s, dstAlpha = %s", + CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, srcRGB), + GLenumToString(GLESEnum::BlendingFactor, dstRGB), + GLenumToString(GLESEnum::BlendingFactor, srcAlpha), + GLenumToString(GLESEnum::BlendingFactor, dstAlpha))); + + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFuncSeparateiEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFuncSeparateiEXT, buf, srcRGB, dstRGB, srcAlpha, + dstAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendFuncSeparateiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFuncSeparatei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, srcRGB, @@ -6405,7 +9138,7 @@ GL_BlendFuncSeparateiEXT(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlp } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFuncSeparateiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6414,18 +9147,33 @@ void GL_APIENTRY GL_BlendFunciEXT(GLuint buf, GLenum src, GLenum dst) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFunciEXT, "context = %d, buf = %u, src = %s, dst = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendingFactor, src), - GLenumToString(GLESEnum::BlendingFactor, dst)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendFunciEXT, "context = %d, buf = %u, src = %s, dst = %s", + CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, src), + GLenumToString(GLESEnum::BlendingFactor, dst))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendFunciEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFunciEXT, buf, src, dst)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFunciEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFunciEXT, buf, src, dst); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendFunciEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFunci(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, src, dst); @@ -6434,7 +9182,7 @@ void GL_APIENTRY GL_BlendFunciEXT(GLuint buf, GLenum src, GLenum dst) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFunciEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6443,18 +9191,34 @@ void GL_APIENTRY GL_ColorMaskiEXT(GLuint index, GLboolean r, GLboolean g, GLbool { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColorMaskiEXT, "context = %d, index = %u, r = %s, g = %s, b = %s, a = %s", - CID(context), index, GLbooleanToString(r), GLbooleanToString(g), GLbooleanToString(b), - GLbooleanToString(a)); + ANGLE_UNSAFE_TODO(EVENT(context, GLColorMaskiEXT, + "context = %d, index = %u, r = %s, g = %s, b = %s, a = %s", + CID(context), index, GLbooleanToString(r), GLbooleanToString(g), + GLbooleanToString(b), GLbooleanToString(a))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateColorMaskiEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColorMaskiEXT, index, r, g, b, a)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColorMaskiEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColorMaskiEXT, index, r, g, b, a); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLColorMaskiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColorMaski(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, r, g, b, a); @@ -6463,7 +9227,7 @@ void GL_APIENTRY GL_ColorMaskiEXT(GLuint index, GLboolean r, GLboolean g, GLbool } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColorMaskiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6472,16 +9236,32 @@ void GL_APIENTRY GL_DisableiEXT(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisableiEXT, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisableiEXT, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDisableiEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDisableiEXT, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisableiEXT(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDisableiEXT, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDisableiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDisablei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, index); @@ -6490,7 +9270,7 @@ void GL_APIENTRY GL_DisableiEXT(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDisableiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6499,16 +9279,32 @@ void GL_APIENTRY GL_EnableiEXT(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEnableiEXT, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLEnableiEXT, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateEnableiEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEnableiEXT, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEnableiEXT(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLEnableiEXT, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEnableiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateEnablei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, index); @@ -6517,7 +9313,7 @@ void GL_APIENTRY GL_EnableiEXT(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEnableiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6526,18 +9322,33 @@ GLboolean GL_APIENTRY GL_IsEnablediEXT(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsEnablediEXT, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsEnablediEXT, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); GLboolean returnValue; - if (context) - { - bool isCallValid = - (context->skipValidation() || - ValidateIsEnablediEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLIsEnablediEXT, target, index)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsEnablediEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLIsEnablediEXT, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsEnablediEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = ContextPrivateIsEnabledi(context->getMutablePrivateState(), @@ -6551,7 +9362,7 @@ GLboolean GL_APIENTRY GL_IsEnablediEXT(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsEnablediEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -6567,22 +9378,39 @@ void GL_APIENTRY GL_DrawElementsBaseVertexEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsBaseVertexEXT, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsBaseVertexEXT, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsBaseVertexEXT( - context, angle::EntryPoint::GLDrawElementsBaseVertexEXT, modePacked, - count, typePacked, indices, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsBaseVertexEXT( + context, angle::EntryPoint::GLDrawElementsBaseVertexEXT, modePacked, count, + typePacked, indices, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawElementsBaseVertexEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsBaseVertex(modePacked, count, typePacked, indices, basevertex); } @@ -6591,7 +9419,8 @@ void GL_APIENTRY GL_DrawElementsBaseVertexEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsBaseVertexEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6605,23 +9434,41 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedBaseVertexEXT, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instancecount = %d, basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, - basevertex); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedBaseVertexEXT, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instancecount = %d, basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, + basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsInstancedBaseVertexEXT( - context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexEXT, - modePacked, count, typePacked, indices, instancecount, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedBaseVertexEXT( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexEXT, modePacked, + count, typePacked, indices, instancecount, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawElementsInstancedBaseVertexEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstancedBaseVertex(modePacked, count, typePacked, indices, instancecount, basevertex); @@ -6631,7 +9478,8 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedBaseVertexEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6646,22 +9494,40 @@ void GL_APIENTRY GL_DrawRangeElementsBaseVertexEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawRangeElementsBaseVertexEXT, - "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, indices = " - "0x%016" PRIxPTR ", basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawRangeElementsBaseVertexEXT, + "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, " + "indices = 0x%016" PRIxPTR ", basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, + count, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawRangeElementsBaseVertexEXT( - context, angle::EntryPoint::GLDrawRangeElementsBaseVertexEXT, - modePacked, start, end, count, typePacked, indices, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawRangeElementsBaseVertexEXT( + context, angle::EntryPoint::GLDrawRangeElementsBaseVertexEXT, modePacked, start, + end, count, typePacked, indices, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawRangeElementsBaseVertexEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawRangeElementsBaseVertex(modePacked, start, end, count, typePacked, indices, basevertex); @@ -6671,7 +9537,8 @@ void GL_APIENTRY GL_DrawRangeElementsBaseVertexEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawRangeElementsBaseVertexEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6685,27 +9552,42 @@ void GL_APIENTRY GL_MultiDrawElementsBaseVertexEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawElementsBaseVertexEXT, - "context = %d, mode = %s, count = 0x%016" PRIxPTR ", type = %s, indices = 0x%016" PRIxPTR - ", drawcount = %d, basevertex = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, drawcount, - (uintptr_t)basevertex); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawElementsBaseVertexEXT, + "context = %d, mode = %s, count = 0x%016" PRIxPTR + ", type = %s, indices = 0x%016" PRIxPTR + ", drawcount = %d, basevertex = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)count, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, drawcount, (uintptr_t)basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawElementsBaseVertexEXT) && - ValidateMultiDrawElementsBaseVertexEXT( - context, angle::EntryPoint::GLMultiDrawElementsBaseVertexEXT, modePacked, count, - typePacked, indices, drawcount, basevertex))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexEXT || + context->getExtensions().drawElementsBaseVertexOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawElementsBaseVertexEXT( + context, angle::EntryPoint::GLMultiDrawElementsBaseVertexEXT, modePacked, count, + typePacked, indices, drawcount, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLMultiDrawElementsBaseVertexEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawElementsBaseVertex(modePacked, count, typePacked, indices, drawcount, basevertex); @@ -6715,7 +9597,116 @@ void GL_APIENTRY GL_MultiDrawElementsBaseVertexEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawElementsBaseVertexEXT); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +// GL_EXT_draw_instanced +void GL_APIENTRY GL_DrawArraysInstancedEXT(GLenum mode, + GLint start, + GLsizei count, + GLsizei primcount) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawArraysInstancedEXT, + "context = %d, mode = %s, start = %d, count = %d, primcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, + count, primcount)); + + if (ANGLE_LIKELY(context != nullptr)) + { + PrimitiveMode modePacked = PackParam(mode); + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawInstancedEXT || + context->getExtensions().instancedArraysEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawArraysInstancedEXT( + context, angle::EntryPoint::GLDrawArraysInstancedEXT, modePacked, start, count, + primcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawArraysInstancedEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->drawArraysInstanced(modePacked, start, count, primcount); + } + ANGLE_CAPTURE_GL(DrawArraysInstancedEXT, isCallValid, context, modePacked, start, count, + primcount); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawArraysInstancedEXT); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +void GL_APIENTRY GL_DrawElementsInstancedEXT(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei primcount) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedEXT, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", primcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, primcount)); + + if (ANGLE_LIKELY(context != nullptr)) + { + PrimitiveMode modePacked = PackParam(mode); + DrawElementsType typePacked = PackParam(type); + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawInstancedEXT || + context->getExtensions().instancedArraysEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedEXT( + context, angle::EntryPoint::GLDrawElementsInstancedEXT, modePacked, count, + typePacked, indices, primcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawElementsInstancedEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->drawElementsInstanced(modePacked, count, typePacked, indices, primcount); + } + ANGLE_CAPTURE_GL(DrawElementsInstancedEXT, isCallValid, context, modePacked, count, + typePacked, indices, primcount); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6729,26 +9720,39 @@ void GL_APIENTRY GL_BufferStorageExternalEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBufferStorageExternalEXT, - "context = %d, target = %s, offset = %llu, size = %llu, clientBuffer = 0x%016" PRIxPTR - ", flags = %s", - CID(context), GLenumToString(GLESEnum::AllEnums, target), - static_cast(offset), static_cast(size), - (uintptr_t)clientBuffer, GLbitfieldToString(GLESEnum::BufferStorageMask, flags).c_str()); + ANGLE_UNSAFE_TODO(EVENT( + context, GLBufferStorageExternalEXT, + "context = %d, target = %s, offset = %llu, size = %llu, clientBuffer = 0x%016" PRIxPTR + ", flags = %s", + CID(context), GLenumToString(GLESEnum::AllEnums, target), + static_cast(offset), static_cast(size), + (uintptr_t)clientBuffer, GLbitfieldToString(GLESEnum::BufferStorageMask, flags).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBufferStorageExternalEXT) && - ValidateBufferStorageExternalEXT(context, - angle::EntryPoint::GLBufferStorageExternalEXT, - targetPacked, offset, size, clientBuffer, flags))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().externalBufferEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBufferStorageExternalEXT( + context, angle::EntryPoint::GLBufferStorageExternalEXT, targetPacked, offset, + size, clientBuffer, flags); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBufferStorageExternalEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bufferStorageExternal(targetPacked, offset, size, clientBuffer, flags); } @@ -6757,211 +9761,361 @@ void GL_APIENTRY GL_BufferStorageExternalEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBufferStorageExternalEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -void GL_APIENTRY GL_NamedBufferStorageExternalEXT(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags) +// GL_EXT_float_blend + +// GL_EXT_fragment_shading_rate +void GL_APIENTRY GL_FramebufferShadingRateEXT(GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLNamedBufferStorageExternalEXT, - "context = %d, buffer = %u, offset = %llu, size = %llu, clientBuffer = 0x%016" PRIxPTR - ", flags = %s", - CID(context), buffer, static_cast(offset), - static_cast(size), (uintptr_t)clientBuffer, - GLbitfieldToString(GLESEnum::BufferStorageMask, flags).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferShadingRateEXT, + "context = %d, target = %s, attachment = %s, texture = %u, baseLayer = " + "%d, numLayers = %d, texelWidth = %d, texelHeight = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, + baseLayer, numLayers, texelWidth, texelHeight)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLNamedBufferStorageExternalEXT) && - ValidateNamedBufferStorageExternalEXT( - context, angle::EntryPoint::GLNamedBufferStorageExternalEXT, buffer, offset, size, - clientBuffer, flags))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->namedBufferStorageExternal(buffer, offset, size, clientBuffer, flags); + if (ANGLE_LIKELY(context->getExtensions().fragmentShadingRateEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferShadingRateEXT( + context, angle::EntryPoint::GLFramebufferShadingRateEXT, target, attachment, + texture, baseLayer, numLayers, texelWidth, texelHeight); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferShadingRateEXT); + } } - ANGLE_CAPTURE_GL(NamedBufferStorageExternalEXT, isCallValid, context, buffer, offset, size, - clientBuffer, flags); + if (ANGLE_LIKELY(isCallValid)) + { + context->framebufferShadingRate(target, attachment, texture, baseLayer, numLayers, + texelWidth, texelHeight); + } + ANGLE_CAPTURE_GL(FramebufferShadingRateEXT, isCallValid, context, target, attachment, + texture, baseLayer, numLayers, texelWidth, texelHeight); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferShadingRateEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -// GL_EXT_float_blend - -// GL_EXT_geometry_shader -void GL_APIENTRY GL_FramebufferTextureEXT(GLenum target, - GLenum attachment, - GLuint texture, - GLint level) +void GL_APIENTRY GL_GetFragmentShadingRatesEXT(GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTextureEXT, - "context = %d, target = %s, attachment = %s, texture = %u, level = %d", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, level); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFragmentShadingRatesEXT, + "context = %d, samples = %d, maxCount = %d, count = 0x%016" PRIxPTR + ", shadingRates = 0x%016" PRIxPTR "", + CID(context), samples, maxCount, (uintptr_t)count, + (uintptr_t)shadingRates)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferTextureEXT(context, angle::EntryPoint::GLFramebufferTextureEXT, - target, attachment, texturePacked, level)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->framebufferTexture(target, attachment, texturePacked, level); + if (ANGLE_LIKELY(context->getExtensions().fragmentShadingRateEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFragmentShadingRatesEXT( + context, angle::EntryPoint::GLGetFragmentShadingRatesEXT, samples, maxCount, + count, shadingRates); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetFragmentShadingRatesEXT); + } } - ANGLE_CAPTURE_GL(FramebufferTextureEXT, isCallValid, context, target, attachment, - texturePacked, level); + if (ANGLE_LIKELY(isCallValid)) + { + context->getFragmentShadingRates(samples, maxCount, count, shadingRates); + } + ANGLE_CAPTURE_GL(GetFragmentShadingRatesEXT, isCallValid, context, samples, maxCount, count, + shadingRates); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFragmentShadingRatesEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -// GL_EXT_gpu_shader5 +void GL_APIENTRY GL_ShadingRateEXT(GLenum rate) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO(EVENT(context, GLShadingRateEXT, "context = %d, rate = %s", CID(context), + GLenumToString(GLESEnum::ShadingRate, rate))); -// GL_EXT_instanced_arrays -void GL_APIENTRY GL_DrawArraysInstancedEXT(GLenum mode, - GLint start, - GLsizei count, - GLsizei primcount) + if (ANGLE_LIKELY(context != nullptr)) + { + ShadingRate ratePacked = PackParam(rate); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fragmentShadingRateEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateShadingRateEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLShadingRateEXT, ratePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLShadingRateEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateShadingRateEXT(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), ratePacked); + } + ANGLE_CAPTURE_GL(ShadingRateEXT, isCallValid, context, ratePacked); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLShadingRateEXT); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +void GL_APIENTRY GL_ShadingRateCombinerOpsEXT(GLenum combinerOp0, GLenum combinerOp1) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawArraysInstancedEXT, - "context = %d, mode = %s, start = %d, count = %d, primcount = %d", CID(context), - GLenumToString(GLESEnum::PrimitiveType, mode), start, count, primcount); + ANGLE_UNSAFE_TODO(EVENT(context, GLShadingRateCombinerOpsEXT, + "context = %d, combinerOp0 = %s, combinerOp1 = %s", CID(context), + GLenumToString(GLESEnum::ShadingRateCombinerOp, combinerOp0), + GLenumToString(GLESEnum::ShadingRateCombinerOp, combinerOp1))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - PrimitiveMode modePacked = PackParam(mode); - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawArraysInstancedEXT(context, angle::EntryPoint::GLDrawArraysInstancedEXT, - modePacked, start, count, primcount)); - if (isCallValid) + CombinerOp combinerOp0Packed = PackParam(combinerOp0); + CombinerOp combinerOp1Packed = PackParam(combinerOp1); + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->drawArraysInstanced(modePacked, start, count, primcount); + if (ANGLE_LIKELY(context->getExtensions().fragmentShadingRateEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateShadingRateCombinerOpsEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLShadingRateCombinerOpsEXT, combinerOp0Packed, + combinerOp1Packed); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLShadingRateCombinerOpsEXT); + } } - ANGLE_CAPTURE_GL(DrawArraysInstancedEXT, isCallValid, context, modePacked, start, count, - primcount); + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateShadingRateCombinerOps(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), + combinerOp0Packed, combinerOp1Packed); + } + ANGLE_CAPTURE_GL(ShadingRateCombinerOpsEXT, isCallValid, context, combinerOp0Packed, + combinerOp1Packed); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLShadingRateCombinerOpsEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -void GL_APIENTRY GL_DrawElementsInstancedEXT(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei primcount) +// GL_EXT_geometry_shader +void GL_APIENTRY GL_FramebufferTextureEXT(GLenum target, + GLenum attachment, + GLuint texture, + GLint level) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedEXT, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", primcount = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, primcount); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTextureEXT, + "context = %d, target = %s, attachment = %s, texture = %u, level = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, + level)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - PrimitiveMode modePacked = PackParam(mode); - DrawElementsType typePacked = PackParam(type); + TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsInstancedEXT( - context, angle::EntryPoint::GLDrawElementsInstancedEXT, modePacked, - count, typePacked, indices, primcount)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - context->drawElementsInstanced(modePacked, count, typePacked, indices, primcount); + if (ANGLE_LIKELY(context->getExtensions().geometryShaderEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTextureEXT( + context, angle::EntryPoint::GLFramebufferTextureEXT, target, attachment, + texturePacked, level); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferTextureEXT); + } } - ANGLE_CAPTURE_GL(DrawElementsInstancedEXT, isCallValid, context, modePacked, count, - typePacked, indices, primcount); + if (ANGLE_LIKELY(isCallValid)) + { + context->framebufferTexture(target, attachment, texturePacked, level); + } + ANGLE_CAPTURE_GL(FramebufferTextureEXT, isCallValid, context, target, attachment, + texturePacked, level); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFramebufferTextureEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } +// GL_EXT_gpu_shader5 + +// GL_EXT_instanced_arrays void GL_APIENTRY GL_VertexAttribDivisorEXT(GLuint index, GLuint divisor) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLVertexAttribDivisorEXT, "context = %d, index = %u, divisor = %u", CID(context), - index, divisor); + ANGLE_UNSAFE_TODO(EVENT(context, GLVertexAttribDivisorEXT, + "context = %d, index = %u, divisor = %u", CID(context), index, + divisor)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateVertexAttribDivisorEXT(context, angle::EntryPoint::GLVertexAttribDivisorEXT, - index, divisor)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().instancedArraysEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateVertexAttribDivisorEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLVertexAttribDivisorEXT, index, divisor); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLVertexAttribDivisorEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { - context->vertexAttribDivisor(index, divisor); + ContextPrivateVertexAttribDivisor(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), index, + divisor); } ANGLE_CAPTURE_GL(VertexAttribDivisorEXT, isCallValid, context, index, divisor); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLVertexAttribDivisorEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } +// DrawArraysInstancedEXT is already defined. + +// DrawElementsInstancedEXT is already defined. + // GL_EXT_map_buffer_range void GL_APIENTRY GL_FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFlushMappedBufferRangeEXT, - "context = %d, target = %s, offset = %llu, length = %llu", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - static_cast(offset), static_cast(length)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFlushMappedBufferRangeEXT, + "context = %d, target = %s, offset = %llu, length = %llu", CID(context), + GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(offset), + static_cast(length))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFlushMappedBufferRangeEXT) && - ValidateFlushMappedBufferRangeEXT(context, - angle::EntryPoint::GLFlushMappedBufferRangeEXT, - targetPacked, offset, length))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().mapBufferRangeEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFlushMappedBufferRangeEXT( + context, angle::EntryPoint::GLFlushMappedBufferRangeEXT, targetPacked, offset, + length); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFlushMappedBufferRangeEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->flushMappedBufferRange(targetPacked, offset, length); } @@ -6970,7 +10124,8 @@ void GL_APIENTRY GL_FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFlushMappedBufferRangeEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -6982,27 +10137,52 @@ void *GL_APIENTRY GL_MapBufferRangeEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMapBufferRangeEXT, - "context = %d, target = %s, offset = %llu, length = %llu, access = %s", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - static_cast(offset), static_cast(length), - GLbitfieldToString(GLESEnum::MapBufferAccessMask, access).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLMapBufferRangeEXT, + "context = %d, target = %s, offset = %llu, length = %llu, access = %s", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(offset), + static_cast(length), + GLbitfieldToString(GLESEnum::MapBufferAccessMask, access).c_str())); void *returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMapBufferRangeEXT) && - ValidateMapBufferRangeEXT(context, angle::EntryPoint::GLMapBufferRangeEXT, - targetPacked, offset, length, access))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().mapBufferRangeEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateMapBufferRangeEXT(context, angle::EntryPoint::GLMapBufferRangeEXT, + targetPacked, offset, length, access); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMapBufferRangeEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->mapBufferRange(targetPacked, offset, length, access); +#if ANGLE_CAPTURE_ENABLED + angle::FrameCaptureShared *frameCaptureShared = + context->getShareGroup()->getFrameCaptureShared(); + if (returnValue != nullptr && frameCaptureShared->enabled()) + { + Buffer *buffer = context->getState().getTargetBuffer(targetPacked); + ASSERT(buffer); + returnValue = + frameCaptureShared->maybeGetShadowMemoryPointer(buffer, length, access); + } +#endif } else { @@ -7013,7 +10193,7 @@ void *GL_APIENTRY GL_MapBufferRangeEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMapBufferRangeEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -7028,24 +10208,38 @@ void GL_APIENTRY GL_BufferStorageMemEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBufferStorageMemEXT, - "context = %d, target = %s, size = %llu, memory = %u, offset = %llu", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), static_cast(size), - memory, static_cast(offset)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBufferStorageMemEXT, + "context = %d, target = %s, size = %llu, memory = %u, offset = %llu", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + static_cast(size), memory, + static_cast(offset))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBufferStorageMemEXT) && - ValidateBufferStorageMemEXT(context, angle::EntryPoint::GLBufferStorageMemEXT, - targetPacked, size, memoryPacked, offset))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateBufferStorageMemEXT(context, angle::EntryPoint::GLBufferStorageMemEXT, + targetPacked, size, memoryPacked, offset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBufferStorageMemEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bufferStorageMem(targetPacked, size, memoryPacked, offset); } @@ -7054,7 +10248,7 @@ void GL_APIENTRY GL_BufferStorageMemEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBufferStorageMemEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7063,22 +10257,34 @@ void GL_APIENTRY GL_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCreateMemoryObjectsEXT, - "context = %d, n = %d, memoryObjects = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)memoryObjects); + ANGLE_UNSAFE_TODO(EVENT(context, GLCreateMemoryObjectsEXT, + "context = %d, n = %d, memoryObjects = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)memoryObjects)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MemoryObjectID *memoryObjectsPacked = PackParam(memoryObjects); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCreateMemoryObjectsEXT) && - ValidateCreateMemoryObjectsEXT(context, angle::EntryPoint::GLCreateMemoryObjectsEXT, - n, memoryObjectsPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCreateMemoryObjectsEXT( + context, angle::EntryPoint::GLCreateMemoryObjectsEXT, n, memoryObjectsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCreateMemoryObjectsEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->createMemoryObjects(n, memoryObjectsPacked); } @@ -7086,7 +10292,7 @@ void GL_APIENTRY GL_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCreateMemoryObjectsEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7095,20 +10301,35 @@ void GL_APIENTRY GL_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObject { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteMemoryObjectsEXT, - "context = %d, n = %d, memoryObjects = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)memoryObjects); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteMemoryObjectsEXT, + "context = %d, n = %d, memoryObjects = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)memoryObjects)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const MemoryObjectID *memoryObjectsPacked = PackParam(memoryObjects); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteMemoryObjectsEXT(context, angle::EntryPoint::GLDeleteMemoryObjectsEXT, n, - memoryObjectsPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteMemoryObjectsEXT( + context, angle::EntryPoint::GLDeleteMemoryObjectsEXT, n, memoryObjectsPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteMemoryObjectsEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteMemoryObjects(n, memoryObjectsPacked); } @@ -7116,7 +10337,7 @@ void GL_APIENTRY GL_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObject } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteMemoryObjectsEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7125,20 +10346,38 @@ void GL_APIENTRY GL_GetMemoryObjectParameterivEXT(GLuint memoryObject, GLenum pn { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetMemoryObjectParameterivEXT, - "context = %d, memoryObject = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - memoryObject, GLenumToString(GLESEnum::MemoryObjectParameterName, pname), - (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetMemoryObjectParameterivEXT, + "context = %d, memoryObject = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), memoryObject, + GLenumToString(GLESEnum::MemoryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MemoryObjectID memoryObjectPacked = PackParam(memoryObject); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetMemoryObjectParameterivEXT( - context, angle::EntryPoint::GLGetMemoryObjectParameterivEXT, - memoryObjectPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetMemoryObjectParameterivEXT( + context, angle::EntryPoint::GLGetMemoryObjectParameterivEXT, memoryObjectPacked, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetMemoryObjectParameterivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getMemoryObjectParameteriv(memoryObjectPacked, pname, params); } @@ -7147,7 +10386,8 @@ void GL_APIENTRY GL_GetMemoryObjectParameterivEXT(GLuint memoryObject, GLenum pn } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetMemoryObjectParameterivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7156,16 +10396,34 @@ void GL_APIENTRY GL_GetUnsignedBytevEXT(GLenum pname, GLubyte *data) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUnsignedBytevEXT, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUnsignedBytevEXT, + "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::GetPName, pname), (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetUnsignedBytevEXT( - context, angle::EntryPoint::GLGetUnsignedBytevEXT, pname, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT || + context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUnsignedBytevEXT( + context, angle::EntryPoint::GLGetUnsignedBytevEXT, pname, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetUnsignedBytevEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUnsignedBytev(pname, data); } @@ -7173,7 +10431,7 @@ void GL_APIENTRY GL_GetUnsignedBytevEXT(GLenum pname, GLubyte *data) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUnsignedBytevEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7182,18 +10440,35 @@ void GL_APIENTRY GL_GetUnsignedBytei_vEXT(GLenum target, GLuint index, GLubyte * { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetUnsignedBytei_vEXT, - "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::AllEnums, target), index, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetUnsignedBytei_vEXT, + "context = %d, target = %s, index = %u, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, target), index, + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetUnsignedBytei_vEXT(context, angle::EntryPoint::GLGetUnsignedBytei_vEXT, - target, index, data)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT || + context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetUnsignedBytei_vEXT( + context, angle::EntryPoint::GLGetUnsignedBytei_vEXT, target, index, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetUnsignedBytei_vEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getUnsignedBytei_v(target, index, data); } @@ -7201,7 +10476,7 @@ void GL_APIENTRY GL_GetUnsignedBytei_vEXT(GLenum target, GLuint index, GLubyte * } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetUnsignedBytei_vEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7210,19 +10485,34 @@ GLboolean GL_APIENTRY GL_IsMemoryObjectEXT(GLuint memoryObject) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsMemoryObjectEXT, "context = %d, memoryObject = %u", CID(context), - memoryObject); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsMemoryObjectEXT, "context = %d, memoryObject = %u", + CID(context), memoryObject)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MemoryObjectID memoryObjectPacked = PackParam(memoryObject); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsMemoryObjectEXT(context, angle::EntryPoint::GLIsMemoryObjectEXT, - memoryObjectPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsMemoryObjectEXT( + context, angle::EntryPoint::GLIsMemoryObjectEXT, memoryObjectPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsMemoryObjectEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isMemoryObject(memoryObjectPacked); } @@ -7235,7 +10525,7 @@ GLboolean GL_APIENTRY GL_IsMemoryObjectEXT(GLuint memoryObject) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsMemoryObjectEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -7248,24 +10538,37 @@ void GL_APIENTRY GL_MemoryObjectParameterivEXT(GLuint memoryObject, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMemoryObjectParameterivEXT, - "context = %d, memoryObject = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - memoryObject, GLenumToString(GLESEnum::MemoryObjectParameterName, pname), - (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLMemoryObjectParameterivEXT, + "context = %d, memoryObject = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), memoryObject, + GLenumToString(GLESEnum::MemoryObjectParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MemoryObjectID memoryObjectPacked = PackParam(memoryObject); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMemoryObjectParameterivEXT) && - ValidateMemoryObjectParameterivEXT(context, - angle::EntryPoint::GLMemoryObjectParameterivEXT, - memoryObjectPacked, pname, params))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMemoryObjectParameterivEXT( + context, angle::EntryPoint::GLMemoryObjectParameterivEXT, memoryObjectPacked, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMemoryObjectParameterivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->memoryObjectParameteriv(memoryObjectPacked, pname, params); } @@ -7274,7 +10577,8 @@ void GL_APIENTRY GL_MemoryObjectParameterivEXT(GLuint memoryObject, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMemoryObjectParameterivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7289,27 +10593,39 @@ void GL_APIENTRY GL_TexStorageMem2DEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMem2DEXT, - "context = %d, target = %s, levels = %d, internalFormat = %s, width = %d, height = %d, " - "memory = %u, offset = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, height, memory, - static_cast(offset)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorageMem2DEXT, + "context = %d, target = %s, levels = %d, internalFormat = %s, width = " + "%d, height = %d, memory = %u, offset = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, + height, memory, static_cast(offset))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMem2DEXT) && - ValidateTexStorageMem2DEXT(context, angle::EntryPoint::GLTexStorageMem2DEXT, - targetPacked, levels, internalFormat, width, height, - memoryPacked, offset))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMem2DEXT( + context, angle::EntryPoint::GLTexStorageMem2DEXT, targetPacked, levels, + internalFormat, width, height, memoryPacked, offset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorageMem2DEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMem2D(targetPacked, levels, internalFormat, width, height, memoryPacked, offset); @@ -7319,7 +10635,7 @@ void GL_APIENTRY GL_TexStorageMem2DEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorageMem2DEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7335,28 +10651,42 @@ void GL_APIENTRY GL_TexStorageMem2DMultisampleEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMem2DMultisampleEXT, - "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " - "fixedSampleLocations = %s, memory = %u, offset = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, height, - GLbooleanToString(fixedSampleLocations), memory, static_cast(offset)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexStorageMem2DMultisampleEXT, + "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " + "fixedSampleLocations = %s, memory = %u, offset = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, height, + GLbooleanToString(fixedSampleLocations), memory, static_cast(offset))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMem2DMultisampleEXT) && - ValidateTexStorageMem2DMultisampleEXT( - context, angle::EntryPoint::GLTexStorageMem2DMultisampleEXT, targetPacked, - samples, internalFormat, width, height, fixedSampleLocations, memoryPacked, - offset))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMem2DMultisampleEXT( + context, angle::EntryPoint::GLTexStorageMem2DMultisampleEXT, targetPacked, + samples, internalFormat, width, height, fixedSampleLocations, memoryPacked, + offset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLTexStorageMem2DMultisampleEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMem2DMultisample(targetPacked, samples, internalFormat, width, height, fixedSampleLocations, memoryPacked, offset); @@ -7366,7 +10696,8 @@ void GL_APIENTRY GL_TexStorageMem2DMultisampleEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorageMem2DMultisampleEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7382,27 +10713,39 @@ void GL_APIENTRY GL_TexStorageMem3DEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMem3DEXT, - "context = %d, target = %s, levels = %d, internalFormat = %s, width = %d, height = %d, " - "depth = %d, memory = %u, offset = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, height, depth, - memory, static_cast(offset)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorageMem3DEXT, + "context = %d, target = %s, levels = %d, internalFormat = %s, width = " + "%d, height = %d, depth = %d, memory = %u, offset = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, + height, depth, memory, static_cast(offset))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMem3DEXT) && - ValidateTexStorageMem3DEXT(context, angle::EntryPoint::GLTexStorageMem3DEXT, - targetPacked, levels, internalFormat, width, height, depth, - memoryPacked, offset))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMem3DEXT( + context, angle::EntryPoint::GLTexStorageMem3DEXT, targetPacked, levels, + internalFormat, width, height, depth, memoryPacked, offset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorageMem3DEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMem3D(targetPacked, levels, internalFormat, width, height, depth, memoryPacked, offset); @@ -7412,7 +10755,7 @@ void GL_APIENTRY GL_TexStorageMem3DEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorageMem3DEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7429,28 +10772,42 @@ void GL_APIENTRY GL_TexStorageMem3DMultisampleEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageMem3DMultisampleEXT, - "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " - "depth = %d, fixedSampleLocations = %s, memory = %u, offset = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, height, depth, - GLbooleanToString(fixedSampleLocations), memory, static_cast(offset)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexStorageMem3DMultisampleEXT, + "context = %d, target = %s, samples = %d, internalFormat = %s, width = %d, height = %d, " + "depth = %d, fixedSampleLocations = %s, memory = %u, offset = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::SizedInternalFormat, internalFormat), width, height, depth, + GLbooleanToString(fixedSampleLocations), memory, static_cast(offset))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); MemoryObjectID memoryPacked = PackParam(memory); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageMem3DMultisampleEXT) && - ValidateTexStorageMem3DMultisampleEXT( - context, angle::EntryPoint::GLTexStorageMem3DMultisampleEXT, targetPacked, - samples, internalFormat, width, height, depth, fixedSampleLocations, memoryPacked, - offset))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageMem3DMultisampleEXT( + context, angle::EntryPoint::GLTexStorageMem3DMultisampleEXT, targetPacked, + samples, internalFormat, width, height, depth, fixedSampleLocations, + memoryPacked, offset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLTexStorageMem3DMultisampleEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageMem3DMultisample(targetPacked, samples, internalFormat, width, height, depth, fixedSampleLocations, memoryPacked, @@ -7462,7 +10819,8 @@ void GL_APIENTRY GL_TexStorageMem3DMultisampleEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorageMem3DMultisampleEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7472,24 +10830,37 @@ void GL_APIENTRY GL_ImportMemoryFdEXT(GLuint memory, GLuint64 size, GLenum handl { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLImportMemoryFdEXT, - "context = %d, memory = %u, size = %llu, handleType = %s, fd = %d", CID(context), memory, - static_cast(size), - GLenumToString(GLESEnum::ExternalHandleType, handleType), fd); + ANGLE_UNSAFE_TODO(EVENT(context, GLImportMemoryFdEXT, + "context = %d, memory = %u, size = %llu, handleType = %s, fd = %d", + CID(context), memory, static_cast(size), + GLenumToString(GLESEnum::ExternalHandleType, handleType), fd)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { MemoryObjectID memoryPacked = PackParam(memory); HandleType handleTypePacked = PackParam(handleType); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLImportMemoryFdEXT) && - ValidateImportMemoryFdEXT(context, angle::EntryPoint::GLImportMemoryFdEXT, - memoryPacked, size, handleTypePacked, fd))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().memoryObjectFdEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateImportMemoryFdEXT(context, angle::EntryPoint::GLImportMemoryFdEXT, + memoryPacked, size, handleTypePacked, fd); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLImportMemoryFdEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->importMemoryFd(memoryPacked, size, handleTypePacked, fd); } @@ -7498,7 +10869,113 @@ void GL_APIENTRY GL_ImportMemoryFdEXT(GLuint memory, GLuint64 size, GLenum handl } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLImportMemoryFdEXT); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +// GL_EXT_multi_draw_arrays +void GL_APIENTRY GL_MultiDrawArraysEXT(GLenum mode, + const GLint *first, + const GLsizei *count, + GLsizei primcount) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawArraysEXT, + "context = %d, mode = %s, first = 0x%016" PRIxPTR + ", count = 0x%016" PRIxPTR ", primcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)first, (uintptr_t)count, primcount)); + + if (ANGLE_LIKELY(context != nullptr)) + { + PrimitiveMode modePacked = PackParam(mode); + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawArraysEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateMultiDrawArraysEXT(context, angle::EntryPoint::GLMultiDrawArraysEXT, + modePacked, first, count, primcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMultiDrawArraysEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->multiDrawArrays(modePacked, first, count, primcount); + } + ANGLE_CAPTURE_GL(MultiDrawArraysEXT, isCallValid, context, modePacked, first, count, + primcount); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultiDrawArraysEXT); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + +void GL_APIENTRY GL_MultiDrawElementsEXT(GLenum mode, + const GLsizei *count, + GLenum type, + const void *const *indices, + GLsizei primcount) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawElementsEXT, + "context = %d, mode = %s, count = 0x%016" PRIxPTR + ", type = %s, indices = 0x%016" PRIxPTR ", primcount = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)count, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, primcount)); + + if (ANGLE_LIKELY(context != nullptr)) + { + PrimitiveMode modePacked = PackParam(mode); + DrawElementsType typePacked = PackParam(type); + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawArraysEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateMultiDrawElementsEXT(context, angle::EntryPoint::GLMultiDrawElementsEXT, + modePacked, count, typePacked, indices, primcount); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMultiDrawElementsEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->multiDrawElements(modePacked, count, typePacked, indices, primcount); + } + ANGLE_CAPTURE_GL(MultiDrawElementsEXT, isCallValid, context, modePacked, count, typePacked, + indices, primcount); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMultiDrawElementsEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7511,24 +10988,37 @@ void GL_APIENTRY GL_MultiDrawArraysIndirectEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawArraysIndirectEXT, - "context = %d, mode = %s, indirect = 0x%016" PRIxPTR ", drawcount = %d, stride = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), (uintptr_t)indirect, - drawcount, stride); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawArraysIndirectEXT, + "context = %d, mode = %s, indirect = 0x%016" PRIxPTR + ", drawcount = %d, stride = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + (uintptr_t)indirect, drawcount, stride)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawArraysIndirectEXT) && - ValidateMultiDrawArraysIndirectEXT(context, - angle::EntryPoint::GLMultiDrawArraysIndirectEXT, - modePacked, indirect, drawcount, stride))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawIndirectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawArraysIndirectEXT( + context, angle::EntryPoint::GLMultiDrawArraysIndirectEXT, modePacked, indirect, + drawcount, stride); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMultiDrawArraysIndirectEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawArraysIndirect(modePacked, indirect, drawcount, stride); } @@ -7537,7 +11027,8 @@ void GL_APIENTRY GL_MultiDrawArraysIndirectEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawArraysIndirectEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7550,26 +11041,39 @@ void GL_APIENTRY GL_MultiDrawElementsIndirectEXT(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMultiDrawElementsIndirectEXT, - "context = %d, mode = %s, type = %s, indirect = 0x%016" PRIxPTR - ", drawcount = %d, stride = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indirect, drawcount, stride); + ANGLE_UNSAFE_TODO(EVENT(context, GLMultiDrawElementsIndirectEXT, + "context = %d, mode = %s, type = %s, indirect = 0x%016" PRIxPTR + ", drawcount = %d, stride = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indirect, + drawcount, stride)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMultiDrawElementsIndirectEXT) && - ValidateMultiDrawElementsIndirectEXT( - context, angle::EntryPoint::GLMultiDrawElementsIndirectEXT, modePacked, - typePacked, indirect, drawcount, stride))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiDrawIndirectEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMultiDrawElementsIndirectEXT( + context, angle::EntryPoint::GLMultiDrawElementsIndirectEXT, modePacked, + typePacked, indirect, drawcount, stride); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMultiDrawElementsIndirectEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->multiDrawElementsIndirect(modePacked, typePacked, indirect, drawcount, stride); } @@ -7578,7 +11082,8 @@ void GL_APIENTRY GL_MultiDrawElementsIndirectEXT(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMultiDrawElementsIndirectEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7593,24 +11098,45 @@ void GL_APIENTRY GL_FramebufferTexture2DMultisampleEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTexture2DMultisampleEXT, - "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d, " - "samples = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::TextureTarget, textarget), texture, level, samples); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTexture2DMultisampleEXT, + "context = %d, target = %s, attachment = %s, textarget = %s, texture = " + "%u, level = %d, samples = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::TextureTarget, textarget), texture, level, + samples)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget textargetPacked = PackParam(textarget); TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferTexture2DMultisampleEXT( - context, angle::EntryPoint::GLFramebufferTexture2DMultisampleEXT, target, - attachment, textargetPacked, texturePacked, level, samples)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multisampledRenderToTextureEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTexture2DMultisampleEXT( + context, angle::EntryPoint::GLFramebufferTexture2DMultisampleEXT, target, + attachment, textargetPacked, texturePacked, level, samples); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLFramebufferTexture2DMultisampleEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexture2DMultisample(target, attachment, textargetPacked, texturePacked, level, samples); @@ -7620,7 +11146,8 @@ void GL_APIENTRY GL_FramebufferTexture2DMultisampleEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTexture2DMultisampleEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7633,23 +11160,37 @@ void GL_APIENTRY GL_RenderbufferStorageMultisampleEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRenderbufferStorageMultisampleEXT, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), samples, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO(EVENT( + context, GLRenderbufferStorageMultisampleEXT, + "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), samples, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLRenderbufferStorageMultisampleEXT) && - ValidateRenderbufferStorageMultisampleEXT( - context, angle::EntryPoint::GLRenderbufferStorageMultisampleEXT, target, samples, - internalformat, width, height))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multisampledRenderToTextureEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRenderbufferStorageMultisampleEXT( + context, angle::EntryPoint::GLRenderbufferStorageMultisampleEXT, target, + samples, internalformat, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLRenderbufferStorageMultisampleEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->renderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); @@ -7659,7 +11200,8 @@ void GL_APIENTRY GL_RenderbufferStorageMultisampleEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLRenderbufferStorageMultisampleEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7686,17 +11228,33 @@ void GL_APIENTRY GL_PolygonOffsetClampEXT(GLfloat factor, GLfloat units, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPolygonOffsetClampEXT, "context = %d, factor = %f, units = %f, clamp = %f", - CID(context), factor, units, clamp); + ANGLE_UNSAFE_TODO(EVENT(context, GLPolygonOffsetClampEXT, + "context = %d, factor = %f, units = %f, clamp = %f", CID(context), + factor, units, clamp)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidatePolygonOffsetClampEXT( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPolygonOffsetClampEXT, factor, units, clamp)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().polygonOffsetClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePolygonOffsetClampEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPolygonOffsetClampEXT, factor, units, clamp); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPolygonOffsetClampEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePolygonOffsetClamp(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), factor, units, @@ -7706,7 +11264,7 @@ void GL_APIENTRY GL_PolygonOffsetClampEXT(GLfloat factor, GLfloat units, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPolygonOffsetClampEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7723,23 +11281,35 @@ void GL_APIENTRY GL_PrimitiveBoundingBoxEXT(GLfloat minX, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPrimitiveBoundingBoxEXT, - "context = %d, minX = %f, minY = %f, minZ = %f, minW = %f, maxX = %f, maxY = %f, maxZ = " - "%f, maxW = %f", - CID(context), minX, minY, minZ, minW, maxX, maxY, maxZ, maxW); + ANGLE_UNSAFE_TODO(EVENT(context, GLPrimitiveBoundingBoxEXT, + "context = %d, minX = %f, minY = %f, minZ = %f, minW = %f, maxX = %f, " + "maxY = %f, maxZ = %f, maxW = %f", + CID(context), minX, minY, minZ, minW, maxX, maxY, maxZ, maxW)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPrimitiveBoundingBoxEXT) && - ValidatePrimitiveBoundingBoxEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPrimitiveBoundingBoxEXT, minX, - minY, minZ, minW, maxX, maxY, maxZ, maxW))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().primitiveBoundingBoxEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePrimitiveBoundingBoxEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPrimitiveBoundingBoxEXT, minX, minY, minZ, minW, maxX, + maxY, maxZ, maxW); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPrimitiveBoundingBoxEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePrimitiveBoundingBox(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), minX, minY, @@ -7750,7 +11320,8 @@ void GL_APIENTRY GL_PrimitiveBoundingBoxEXT(GLfloat minX, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLPrimitiveBoundingBoxEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7768,16 +11339,32 @@ GLenum GL_APIENTRY GL_GetGraphicsResetStatusEXT() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetGraphicsResetStatusEXT, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetGraphicsResetStatusEXT, "context = %d", CID(context))); GLenum returnValue; - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetGraphicsResetStatusEXT( - context, angle::EntryPoint::GLGetGraphicsResetStatusEXT)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetGraphicsResetStatusEXT( + context, angle::EntryPoint::GLGetGraphicsResetStatusEXT); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetGraphicsResetStatusEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getGraphicsResetStatus(); } @@ -7805,20 +11392,37 @@ void GL_APIENTRY GL_GetnUniformfvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformfvEXT, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformfvEXT, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetnUniformfvEXT(context, angle::EntryPoint::GLGetnUniformfvEXT, programPacked, - locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetnUniformfvEXT(context, angle::EntryPoint::GLGetnUniformfvEXT, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformfvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformfv(programPacked, locationPacked, bufSize, params); } @@ -7827,7 +11431,7 @@ void GL_APIENTRY GL_GetnUniformfvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformfvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7836,20 +11440,37 @@ void GL_APIENTRY GL_GetnUniformivEXT(GLuint program, GLint location, GLsizei buf { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformivEXT, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformivEXT, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetnUniformivEXT(context, angle::EntryPoint::GLGetnUniformivEXT, programPacked, - locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetnUniformivEXT(context, angle::EntryPoint::GLGetnUniformivEXT, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformiv(programPacked, locationPacked, bufSize, params); } @@ -7858,7 +11479,7 @@ void GL_APIENTRY GL_GetnUniformivEXT(GLuint program, GLint location, GLsizei buf } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7874,23 +11495,37 @@ void GL_APIENTRY GL_ReadnPixelsEXT(GLint x, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadnPixelsEXT, - "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, bufSize " - "= %d, data = 0x%016" PRIxPTR "", - CID(context), x, y, width, height, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), bufSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLReadnPixelsEXT, + "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, " + "type = %s, bufSize = %d, data = 0x%016" PRIxPTR "", + CID(context), x, y, width, height, + GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), bufSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadnPixelsEXT) && - ValidateReadnPixelsEXT(context, angle::EntryPoint::GLReadnPixelsEXT, x, y, width, - height, format, type, bufSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateReadnPixelsEXT(context, angle::EntryPoint::GLReadnPixelsEXT, x, y, + width, height, format, type, bufSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLReadnPixelsEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readnPixels(x, y, width, height, format, type, bufSize, data); } @@ -7899,7 +11534,7 @@ void GL_APIENTRY GL_ReadnPixelsEXT(GLint x, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadnPixelsEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7913,18 +11548,34 @@ void GL_APIENTRY GL_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteSemaphoresEXT, "context = %d, n = %d, semaphores = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)semaphores); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteSemaphoresEXT, + "context = %d, n = %d, semaphores = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)semaphores)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const SemaphoreID *semaphoresPacked = PackParam(semaphores); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteSemaphoresEXT(context, angle::EntryPoint::GLDeleteSemaphoresEXT, n, - semaphoresPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteSemaphoresEXT( + context, angle::EntryPoint::GLDeleteSemaphoresEXT, n, semaphoresPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteSemaphoresEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteSemaphores(n, semaphoresPacked); } @@ -7932,7 +11583,7 @@ void GL_APIENTRY GL_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteSemaphoresEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7941,17 +11592,34 @@ void GL_APIENTRY GL_GenSemaphoresEXT(GLsizei n, GLuint *semaphores) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenSemaphoresEXT, "context = %d, n = %d, semaphores = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)semaphores); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenSemaphoresEXT, + "context = %d, n = %d, semaphores = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)semaphores)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID *semaphoresPacked = PackParam(semaphores); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenSemaphoresEXT(context, angle::EntryPoint::GLGenSemaphoresEXT, - n, semaphoresPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenSemaphoresEXT( + context, angle::EntryPoint::GLGenSemaphoresEXT, n, semaphoresPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenSemaphoresEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genSemaphores(n, semaphoresPacked); } @@ -7959,7 +11627,7 @@ void GL_APIENTRY GL_GenSemaphoresEXT(GLsizei n, GLuint *semaphores) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenSemaphoresEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7968,19 +11636,37 @@ void GL_APIENTRY GL_GetSemaphoreParameterui64vEXT(GLuint semaphore, GLenum pname { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSemaphoreParameterui64vEXT, - "context = %d, semaphore = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - semaphore, GLenumToString(GLESEnum::SemaphoreParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetSemaphoreParameterui64vEXT, + "context = %d, semaphore = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + semaphore, GLenumToString(GLESEnum::SemaphoreParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSemaphoreParameterui64vEXT( - context, angle::EntryPoint::GLGetSemaphoreParameterui64vEXT, - semaphorePacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSemaphoreParameterui64vEXT( + context, angle::EntryPoint::GLGetSemaphoreParameterui64vEXT, semaphorePacked, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetSemaphoreParameterui64vEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSemaphoreParameterui64v(semaphorePacked, pname, params); } @@ -7989,7 +11675,8 @@ void GL_APIENTRY GL_GetSemaphoreParameterui64vEXT(GLuint semaphore, GLenum pname } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSemaphoreParameterui64vEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -7998,17 +11685,34 @@ GLboolean GL_APIENTRY GL_IsSemaphoreEXT(GLuint semaphore) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsSemaphoreEXT, "context = %d, semaphore = %u", CID(context), semaphore); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsSemaphoreEXT, "context = %d, semaphore = %u", CID(context), semaphore)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsSemaphoreEXT(context, angle::EntryPoint::GLIsSemaphoreEXT, semaphorePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsSemaphoreEXT(context, angle::EntryPoint::GLIsSemaphoreEXT, + semaphorePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsSemaphoreEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isSemaphore(semaphorePacked); } @@ -8020,7 +11724,7 @@ GLboolean GL_APIENTRY GL_IsSemaphoreEXT(GLuint semaphore) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsSemaphoreEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -8033,23 +11737,36 @@ void GL_APIENTRY GL_SemaphoreParameterui64vEXT(GLuint semaphore, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSemaphoreParameterui64vEXT, - "context = %d, semaphore = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - semaphore, GLenumToString(GLESEnum::SemaphoreParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLSemaphoreParameterui64vEXT, + "context = %d, semaphore = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + semaphore, GLenumToString(GLESEnum::SemaphoreParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSemaphoreParameterui64vEXT) && - ValidateSemaphoreParameterui64vEXT(context, - angle::EntryPoint::GLSemaphoreParameterui64vEXT, - semaphorePacked, pname, params))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSemaphoreParameterui64vEXT( + context, angle::EntryPoint::GLSemaphoreParameterui64vEXT, semaphorePacked, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSemaphoreParameterui64vEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->semaphoreParameterui64v(semaphorePacked, pname, params); } @@ -8058,7 +11775,8 @@ void GL_APIENTRY GL_SemaphoreParameterui64vEXT(GLuint semaphore, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSemaphoreParameterui64vEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8072,27 +11790,41 @@ void GL_APIENTRY GL_SignalSemaphoreEXT(GLuint semaphore, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSignalSemaphoreEXT, - "context = %d, semaphore = %u, numBufferBarriers = %u, buffers = 0x%016" PRIxPTR - ", numTextureBarriers = %u, textures = 0x%016" PRIxPTR ", dstLayouts = 0x%016" PRIxPTR "", - CID(context), semaphore, numBufferBarriers, (uintptr_t)buffers, numTextureBarriers, - (uintptr_t)textures, (uintptr_t)dstLayouts); + ANGLE_UNSAFE_TODO(EVENT( + context, GLSignalSemaphoreEXT, + "context = %d, semaphore = %u, numBufferBarriers = %u, buffers = 0x%016" PRIxPTR + ", numTextureBarriers = %u, textures = 0x%016" PRIxPTR ", dstLayouts = 0x%016" PRIxPTR "", + CID(context), semaphore, numBufferBarriers, (uintptr_t)buffers, numTextureBarriers, + (uintptr_t)textures, (uintptr_t)dstLayouts)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); const BufferID *buffersPacked = PackParam(buffers); const TextureID *texturesPacked = PackParam(textures); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSignalSemaphoreEXT) && - ValidateSignalSemaphoreEXT(context, angle::EntryPoint::GLSignalSemaphoreEXT, - semaphorePacked, numBufferBarriers, buffersPacked, - numTextureBarriers, texturesPacked, dstLayouts))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateSignalSemaphoreEXT(context, angle::EntryPoint::GLSignalSemaphoreEXT, + semaphorePacked, numBufferBarriers, buffersPacked, + numTextureBarriers, texturesPacked, dstLayouts); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSignalSemaphoreEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->signalSemaphore(semaphorePacked, numBufferBarriers, buffersPacked, numTextureBarriers, texturesPacked, dstLayouts); @@ -8103,7 +11835,7 @@ void GL_APIENTRY GL_SignalSemaphoreEXT(GLuint semaphore, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSignalSemaphoreEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8117,27 +11849,41 @@ void GL_APIENTRY GL_WaitSemaphoreEXT(GLuint semaphore, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLWaitSemaphoreEXT, - "context = %d, semaphore = %u, numBufferBarriers = %u, buffers = 0x%016" PRIxPTR - ", numTextureBarriers = %u, textures = 0x%016" PRIxPTR ", srcLayouts = 0x%016" PRIxPTR "", - CID(context), semaphore, numBufferBarriers, (uintptr_t)buffers, numTextureBarriers, - (uintptr_t)textures, (uintptr_t)srcLayouts); + ANGLE_UNSAFE_TODO(EVENT( + context, GLWaitSemaphoreEXT, + "context = %d, semaphore = %u, numBufferBarriers = %u, buffers = 0x%016" PRIxPTR + ", numTextureBarriers = %u, textures = 0x%016" PRIxPTR ", srcLayouts = 0x%016" PRIxPTR "", + CID(context), semaphore, numBufferBarriers, (uintptr_t)buffers, numTextureBarriers, + (uintptr_t)textures, (uintptr_t)srcLayouts)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); const BufferID *buffersPacked = PackParam(buffers); const TextureID *texturesPacked = PackParam(textures); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLWaitSemaphoreEXT) && - ValidateWaitSemaphoreEXT(context, angle::EntryPoint::GLWaitSemaphoreEXT, - semaphorePacked, numBufferBarriers, buffersPacked, - numTextureBarriers, texturesPacked, srcLayouts))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateWaitSemaphoreEXT(context, angle::EntryPoint::GLWaitSemaphoreEXT, + semaphorePacked, numBufferBarriers, buffersPacked, + numTextureBarriers, texturesPacked, srcLayouts); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLWaitSemaphoreEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->waitSemaphore(semaphorePacked, numBufferBarriers, buffersPacked, numTextureBarriers, texturesPacked, srcLayouts); @@ -8147,7 +11893,7 @@ void GL_APIENTRY GL_WaitSemaphoreEXT(GLuint semaphore, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLWaitSemaphoreEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8161,22 +11907,36 @@ void GL_APIENTRY GL_ImportSemaphoreFdEXT(GLuint semaphore, GLenum handleType, GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLImportSemaphoreFdEXT, "context = %d, semaphore = %u, handleType = %s, fd = %d", - CID(context), semaphore, GLenumToString(GLESEnum::ExternalHandleType, handleType), fd); + ANGLE_UNSAFE_TODO(EVENT( + context, GLImportSemaphoreFdEXT, "context = %d, semaphore = %u, handleType = %s, fd = %d", + CID(context), semaphore, GLenumToString(GLESEnum::ExternalHandleType, handleType), fd)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SemaphoreID semaphorePacked = PackParam(semaphore); HandleType handleTypePacked = PackParam(handleType); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLImportSemaphoreFdEXT) && - ValidateImportSemaphoreFdEXT(context, angle::EntryPoint::GLImportSemaphoreFdEXT, - semaphorePacked, handleTypePacked, fd))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().semaphoreFdEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateImportSemaphoreFdEXT(context, angle::EntryPoint::GLImportSemaphoreFdEXT, + semaphorePacked, handleTypePacked, fd); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLImportSemaphoreFdEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->importSemaphoreFd(semaphorePacked, handleTypePacked, fd); } @@ -8185,7 +11945,7 @@ void GL_APIENTRY GL_ImportSemaphoreFdEXT(GLuint semaphore, GLenum handleType, GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLImportSemaphoreFdEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8197,22 +11957,36 @@ void GL_APIENTRY GL_ActiveShaderProgramEXT(GLuint pipeline, GLuint program) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLActiveShaderProgramEXT, "context = %d, pipeline = %u, program = %u", - CID(context), pipeline, program); + ANGLE_UNSAFE_TODO(EVENT(context, GLActiveShaderProgramEXT, + "context = %d, pipeline = %u, program = %u", CID(context), pipeline, + program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLActiveShaderProgramEXT) && - ValidateActiveShaderProgramEXT(context, angle::EntryPoint::GLActiveShaderProgramEXT, - pipelinePacked, programPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateActiveShaderProgramEXT( + context, angle::EntryPoint::GLActiveShaderProgramEXT, pipelinePacked, + programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLActiveShaderProgramEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->activeShaderProgram(pipelinePacked, programPacked); } @@ -8221,7 +11995,7 @@ void GL_APIENTRY GL_ActiveShaderProgramEXT(GLuint pipeline, GLuint program) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLActiveShaderProgramEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8230,20 +12004,33 @@ void GL_APIENTRY GL_BindProgramPipelineEXT(GLuint pipeline) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindProgramPipelineEXT, "context = %d, pipeline = %u", CID(context), pipeline); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindProgramPipelineEXT, "context = %d, pipeline = %u", + CID(context), pipeline)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindProgramPipelineEXT) && - ValidateBindProgramPipelineEXT(context, angle::EntryPoint::GLBindProgramPipelineEXT, - pipelinePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindProgramPipelineEXT( + context, angle::EntryPoint::GLBindProgramPipelineEXT, pipelinePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBindProgramPipelineEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindProgramPipeline(pipelinePacked); } @@ -8251,32 +12038,48 @@ void GL_APIENTRY GL_BindProgramPipelineEXT(GLuint pipeline) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindProgramPipelineEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } -GLuint GL_APIENTRY GL_CreateShaderProgramvEXT(GLenum type, GLsizei count, const GLchar **strings) +GLuint GL_APIENTRY GL_CreateShaderProgramvEXT(GLenum type, + GLsizei count, + const GLchar *const *strings) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCreateShaderProgramvEXT, - "context = %d, type = %s, count = %d, strings = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::ShaderType, type), count, (uintptr_t)strings); + ANGLE_UNSAFE_TODO(EVENT(context, GLCreateShaderProgramvEXT, + "context = %d, type = %s, count = %d, strings = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ShaderType, type), count, + (uintptr_t)strings)); GLuint returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCreateShaderProgramvEXT) && - ValidateCreateShaderProgramvEXT(context, angle::EntryPoint::GLCreateShaderProgramvEXT, - typePacked, count, strings))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCreateShaderProgramvEXT( + context, angle::EntryPoint::GLCreateShaderProgramvEXT, typePacked, count, + strings); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCreateShaderProgramvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->createShaderProgramv(typePacked, count, strings); } @@ -8290,7 +12093,8 @@ GLuint GL_APIENTRY GL_CreateShaderProgramvEXT(GLenum type, GLsizei count, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCreateShaderProgramvEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -8301,19 +12105,34 @@ void GL_APIENTRY GL_DeleteProgramPipelinesEXT(GLsizei n, const GLuint *pipelines { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteProgramPipelinesEXT, - "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)pipelines); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteProgramPipelinesEXT, + "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)pipelines)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const ProgramPipelineID *pipelinesPacked = PackParam(pipelines); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteProgramPipelinesEXT( - context, angle::EntryPoint::GLDeleteProgramPipelinesEXT, n, pipelinesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteProgramPipelinesEXT( + context, angle::EntryPoint::GLDeleteProgramPipelinesEXT, n, pipelinesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteProgramPipelinesEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteProgramPipelines(n, pipelinesPacked); } @@ -8321,7 +12140,8 @@ void GL_APIENTRY GL_DeleteProgramPipelinesEXT(GLsizei n, const GLuint *pipelines } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDeleteProgramPipelinesEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8330,18 +12150,34 @@ void GL_APIENTRY GL_GenProgramPipelinesEXT(GLsizei n, GLuint *pipelines) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenProgramPipelinesEXT, "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)pipelines); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenProgramPipelinesEXT, + "context = %d, n = %d, pipelines = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)pipelines)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID *pipelinesPacked = PackParam(pipelines); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenProgramPipelinesEXT(context, angle::EntryPoint::GLGenProgramPipelinesEXT, n, - pipelinesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenProgramPipelinesEXT( + context, angle::EntryPoint::GLGenProgramPipelinesEXT, n, pipelinesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenProgramPipelinesEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genProgramPipelines(n, pipelinesPacked); } @@ -8349,7 +12185,7 @@ void GL_APIENTRY GL_GenProgramPipelinesEXT(GLsizei n, GLuint *pipelines) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenProgramPipelinesEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8361,20 +12197,37 @@ void GL_APIENTRY GL_GetProgramPipelineInfoLogEXT(GLuint pipeline, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramPipelineInfoLogEXT, - "context = %d, pipeline = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", infoLog = 0x%016" PRIxPTR "", - CID(context), pipeline, bufSize, (uintptr_t)length, (uintptr_t)infoLog); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetProgramPipelineInfoLogEXT, + "context = %d, pipeline = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", infoLog = 0x%016" PRIxPTR "", + CID(context), pipeline, bufSize, (uintptr_t)length, + (uintptr_t)infoLog)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetProgramPipelineInfoLogEXT( - context, angle::EntryPoint::GLGetProgramPipelineInfoLogEXT, - pipelinePacked, bufSize, length, infoLog)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramPipelineInfoLogEXT( + context, angle::EntryPoint::GLGetProgramPipelineInfoLogEXT, pipelinePacked, + bufSize, length, infoLog); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetProgramPipelineInfoLogEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramPipelineInfoLog(pipelinePacked, bufSize, length, infoLog); } @@ -8383,7 +12236,8 @@ void GL_APIENTRY GL_GetProgramPipelineInfoLogEXT(GLuint pipeline, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramPipelineInfoLogEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8392,19 +12246,36 @@ void GL_APIENTRY GL_GetProgramPipelineivEXT(GLuint pipeline, GLenum pname, GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramPipelineivEXT, - "context = %d, pipeline = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - pipeline, GLenumToString(GLESEnum::PipelineParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetProgramPipelineivEXT, + "context = %d, pipeline = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + pipeline, GLenumToString(GLESEnum::PipelineParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramPipelineivEXT(context, angle::EntryPoint::GLGetProgramPipelineivEXT, - pipelinePacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramPipelineivEXT( + context, angle::EntryPoint::GLGetProgramPipelineivEXT, pipelinePacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetProgramPipelineivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramPipelineiv(pipelinePacked, pname, params); } @@ -8413,7 +12284,8 @@ void GL_APIENTRY GL_GetProgramPipelineivEXT(GLuint pipeline, GLenum pname, GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetProgramPipelineivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8422,18 +12294,34 @@ GLboolean GL_APIENTRY GL_IsProgramPipelineEXT(GLuint pipeline) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsProgramPipelineEXT, "context = %d, pipeline = %u", CID(context), pipeline); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsProgramPipelineEXT, "context = %d, pipeline = %u", + CID(context), pipeline)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsProgramPipelineEXT(context, angle::EntryPoint::GLIsProgramPipelineEXT, - pipelinePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsProgramPipelineEXT( + context, angle::EntryPoint::GLIsProgramPipelineEXT, pipelinePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsProgramPipelineEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isProgramPipeline(pipelinePacked); } @@ -8446,7 +12334,7 @@ GLboolean GL_APIENTRY GL_IsProgramPipelineEXT(GLuint pipeline) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsProgramPipelineEXT); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -8457,21 +12345,35 @@ void GL_APIENTRY GL_ProgramParameteriEXT(GLuint program, GLenum pname, GLint val { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramParameteriEXT, "context = %d, program = %u, pname = %s, value = %d", - CID(context), program, GLenumToString(GLESEnum::ProgramParameterPName, pname), value); + ANGLE_UNSAFE_TODO(EVENT( + context, GLProgramParameteriEXT, "context = %d, program = %u, pname = %s, value = %d", + CID(context), program, GLenumToString(GLESEnum::ProgramParameterPName, pname), value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramParameteriEXT) && - ValidateProgramParameteriEXT(context, angle::EntryPoint::GLProgramParameteriEXT, - programPacked, pname, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramParameteriEXT(context, angle::EntryPoint::GLProgramParameteriEXT, + programPacked, pname, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramParameteriEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programParameteri(programPacked, pname, value); } @@ -8479,7 +12381,7 @@ void GL_APIENTRY GL_ProgramParameteriEXT(GLuint program, GLenum pname, GLint val } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramParameteriEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8488,22 +12390,36 @@ void GL_APIENTRY GL_ProgramUniform1fEXT(GLuint program, GLint location, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1fEXT, "context = %d, program = %u, location = %d, v0 = %f", - CID(context), program, location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform1fEXT, + "context = %d, program = %u, location = %d, v0 = %f", CID(context), + program, location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1fEXT) && - ValidateProgramUniform1fEXT(context, angle::EntryPoint::GLProgramUniform1fEXT, - programPacked, locationPacked, v0))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1fEXT(context, angle::EntryPoint::GLProgramUniform1fEXT, + programPacked, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform1fEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1f(programPacked, locationPacked, v0); } @@ -8512,7 +12428,7 @@ void GL_APIENTRY GL_ProgramUniform1fEXT(GLuint program, GLint location, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1fEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8524,23 +12440,37 @@ void GL_APIENTRY GL_ProgramUniform1fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1fvEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform1fvEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1fvEXT) && - ValidateProgramUniform1fvEXT(context, angle::EntryPoint::GLProgramUniform1fvEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1fvEXT(context, angle::EntryPoint::GLProgramUniform1fvEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform1fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1fv(programPacked, locationPacked, count, value); } @@ -8549,7 +12479,7 @@ void GL_APIENTRY GL_ProgramUniform1fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8558,22 +12488,36 @@ void GL_APIENTRY GL_ProgramUniform1iEXT(GLuint program, GLint location, GLint v0 { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1iEXT, "context = %d, program = %u, location = %d, v0 = %d", - CID(context), program, location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform1iEXT, + "context = %d, program = %u, location = %d, v0 = %d", CID(context), + program, location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1iEXT) && - ValidateProgramUniform1iEXT(context, angle::EntryPoint::GLProgramUniform1iEXT, - programPacked, locationPacked, v0))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1iEXT(context, angle::EntryPoint::GLProgramUniform1iEXT, + programPacked, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform1iEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1i(programPacked, locationPacked, v0); } @@ -8582,7 +12526,7 @@ void GL_APIENTRY GL_ProgramUniform1iEXT(GLuint program, GLint location, GLint v0 } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1iEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8594,23 +12538,37 @@ void GL_APIENTRY GL_ProgramUniform1ivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1ivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform1ivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1ivEXT) && - ValidateProgramUniform1ivEXT(context, angle::EntryPoint::GLProgramUniform1ivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1ivEXT(context, angle::EntryPoint::GLProgramUniform1ivEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform1ivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1iv(programPacked, locationPacked, count, value); } @@ -8619,7 +12577,7 @@ void GL_APIENTRY GL_ProgramUniform1ivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1ivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8628,22 +12586,36 @@ void GL_APIENTRY GL_ProgramUniform1uiEXT(GLuint program, GLint location, GLuint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1uiEXT, "context = %d, program = %u, location = %d, v0 = %u", - CID(context), program, location, v0); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform1uiEXT, + "context = %d, program = %u, location = %d, v0 = %u", CID(context), + program, location, v0)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1uiEXT) && - ValidateProgramUniform1uiEXT(context, angle::EntryPoint::GLProgramUniform1uiEXT, - programPacked, locationPacked, v0))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform1uiEXT(context, angle::EntryPoint::GLProgramUniform1uiEXT, + programPacked, locationPacked, v0); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform1uiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1ui(programPacked, locationPacked, v0); } @@ -8652,7 +12624,7 @@ void GL_APIENTRY GL_ProgramUniform1uiEXT(GLuint program, GLint location, GLuint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1uiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8664,23 +12636,37 @@ void GL_APIENTRY GL_ProgramUniform1uivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform1uivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform1uivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform1uivEXT) && - ValidateProgramUniform1uivEXT(context, angle::EntryPoint::GLProgramUniform1uivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniform1uivEXT( + context, angle::EntryPoint::GLProgramUniform1uivEXT, programPacked, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform1uivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform1uiv(programPacked, locationPacked, count, value); } @@ -8689,7 +12675,7 @@ void GL_APIENTRY GL_ProgramUniform1uivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform1uivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8698,23 +12684,36 @@ void GL_APIENTRY GL_ProgramUniform2fEXT(GLuint program, GLint location, GLfloat { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2fEXT, - "context = %d, program = %u, location = %d, v0 = %f, v1 = %f", CID(context), program, - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform2fEXT, + "context = %d, program = %u, location = %d, v0 = %f, v1 = %f", + CID(context), program, location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2fEXT) && - ValidateProgramUniform2fEXT(context, angle::EntryPoint::GLProgramUniform2fEXT, - programPacked, locationPacked, v0, v1))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2fEXT(context, angle::EntryPoint::GLProgramUniform2fEXT, + programPacked, locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform2fEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2f(programPacked, locationPacked, v0, v1); } @@ -8723,7 +12722,7 @@ void GL_APIENTRY GL_ProgramUniform2fEXT(GLuint program, GLint location, GLfloat } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2fEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8735,23 +12734,37 @@ void GL_APIENTRY GL_ProgramUniform2fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2fvEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform2fvEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2fvEXT) && - ValidateProgramUniform2fvEXT(context, angle::EntryPoint::GLProgramUniform2fvEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2fvEXT(context, angle::EntryPoint::GLProgramUniform2fvEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform2fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2fv(programPacked, locationPacked, count, value); } @@ -8760,7 +12773,7 @@ void GL_APIENTRY GL_ProgramUniform2fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8769,23 +12782,36 @@ void GL_APIENTRY GL_ProgramUniform2iEXT(GLuint program, GLint location, GLint v0 { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2iEXT, - "context = %d, program = %u, location = %d, v0 = %d, v1 = %d", CID(context), program, - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform2iEXT, + "context = %d, program = %u, location = %d, v0 = %d, v1 = %d", + CID(context), program, location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2iEXT) && - ValidateProgramUniform2iEXT(context, angle::EntryPoint::GLProgramUniform2iEXT, - programPacked, locationPacked, v0, v1))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2iEXT(context, angle::EntryPoint::GLProgramUniform2iEXT, + programPacked, locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform2iEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2i(programPacked, locationPacked, v0, v1); } @@ -8794,7 +12820,7 @@ void GL_APIENTRY GL_ProgramUniform2iEXT(GLuint program, GLint location, GLint v0 } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2iEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8806,23 +12832,37 @@ void GL_APIENTRY GL_ProgramUniform2ivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2ivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform2ivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2ivEXT) && - ValidateProgramUniform2ivEXT(context, angle::EntryPoint::GLProgramUniform2ivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2ivEXT(context, angle::EntryPoint::GLProgramUniform2ivEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform2ivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2iv(programPacked, locationPacked, count, value); } @@ -8831,7 +12871,7 @@ void GL_APIENTRY GL_ProgramUniform2ivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2ivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8840,23 +12880,36 @@ void GL_APIENTRY GL_ProgramUniform2uiEXT(GLuint program, GLint location, GLuint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2uiEXT, - "context = %d, program = %u, location = %d, v0 = %u, v1 = %u", CID(context), program, - location, v0, v1); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform2uiEXT, + "context = %d, program = %u, location = %d, v0 = %u, v1 = %u", + CID(context), program, location, v0, v1)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2uiEXT) && - ValidateProgramUniform2uiEXT(context, angle::EntryPoint::GLProgramUniform2uiEXT, - programPacked, locationPacked, v0, v1))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform2uiEXT(context, angle::EntryPoint::GLProgramUniform2uiEXT, + programPacked, locationPacked, v0, v1); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform2uiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2ui(programPacked, locationPacked, v0, v1); } @@ -8865,7 +12918,7 @@ void GL_APIENTRY GL_ProgramUniform2uiEXT(GLuint program, GLint location, GLuint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2uiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8877,23 +12930,37 @@ void GL_APIENTRY GL_ProgramUniform2uivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform2uivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform2uivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform2uivEXT) && - ValidateProgramUniform2uivEXT(context, angle::EntryPoint::GLProgramUniform2uivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniform2uivEXT( + context, angle::EntryPoint::GLProgramUniform2uivEXT, programPacked, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform2uivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform2uiv(programPacked, locationPacked, count, value); } @@ -8902,7 +12969,7 @@ void GL_APIENTRY GL_ProgramUniform2uivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform2uivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8912,23 +12979,36 @@ GL_ProgramUniform3fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3fEXT, - "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f", CID(context), - program, location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform3fEXT, + "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f", + CID(context), program, location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3fEXT) && - ValidateProgramUniform3fEXT(context, angle::EntryPoint::GLProgramUniform3fEXT, - programPacked, locationPacked, v0, v1, v2))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3fEXT(context, angle::EntryPoint::GLProgramUniform3fEXT, + programPacked, locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform3fEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3f(programPacked, locationPacked, v0, v1, v2); } @@ -8937,7 +13017,7 @@ GL_ProgramUniform3fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3fEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8949,23 +13029,37 @@ void GL_APIENTRY GL_ProgramUniform3fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3fvEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform3fvEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3fvEXT) && - ValidateProgramUniform3fvEXT(context, angle::EntryPoint::GLProgramUniform3fvEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3fvEXT(context, angle::EntryPoint::GLProgramUniform3fvEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform3fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3fv(programPacked, locationPacked, count, value); } @@ -8974,7 +13068,7 @@ void GL_APIENTRY GL_ProgramUniform3fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -8984,23 +13078,36 @@ GL_ProgramUniform3iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3iEXT, - "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d", CID(context), - program, location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform3iEXT, + "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d", + CID(context), program, location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3iEXT) && - ValidateProgramUniform3iEXT(context, angle::EntryPoint::GLProgramUniform3iEXT, - programPacked, locationPacked, v0, v1, v2))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3iEXT(context, angle::EntryPoint::GLProgramUniform3iEXT, + programPacked, locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform3iEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3i(programPacked, locationPacked, v0, v1, v2); } @@ -9009,7 +13116,7 @@ GL_ProgramUniform3iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3iEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9021,23 +13128,37 @@ void GL_APIENTRY GL_ProgramUniform3ivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3ivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform3ivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3ivEXT) && - ValidateProgramUniform3ivEXT(context, angle::EntryPoint::GLProgramUniform3ivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3ivEXT(context, angle::EntryPoint::GLProgramUniform3ivEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform3ivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3iv(programPacked, locationPacked, count, value); } @@ -9046,7 +13167,7 @@ void GL_APIENTRY GL_ProgramUniform3ivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3ivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9056,23 +13177,36 @@ GL_ProgramUniform3uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3uiEXT, - "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u", CID(context), - program, location, v0, v1, v2); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniform3uiEXT, + "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u", + CID(context), program, location, v0, v1, v2)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3uiEXT) && - ValidateProgramUniform3uiEXT(context, angle::EntryPoint::GLProgramUniform3uiEXT, - programPacked, locationPacked, v0, v1, v2))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform3uiEXT(context, angle::EntryPoint::GLProgramUniform3uiEXT, + programPacked, locationPacked, v0, v1, v2); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform3uiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3ui(programPacked, locationPacked, v0, v1, v2); } @@ -9081,7 +13215,7 @@ GL_ProgramUniform3uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3uiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9093,23 +13227,37 @@ void GL_APIENTRY GL_ProgramUniform3uivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform3uivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform3uivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform3uivEXT) && - ValidateProgramUniform3uivEXT(context, angle::EntryPoint::GLProgramUniform3uivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniform3uivEXT( + context, angle::EntryPoint::GLProgramUniform3uivEXT, programPacked, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform3uivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform3uiv(programPacked, locationPacked, count, value); } @@ -9118,7 +13266,7 @@ void GL_APIENTRY GL_ProgramUniform3uivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform3uivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9132,23 +13280,37 @@ void GL_APIENTRY GL_ProgramUniform4fEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4fEXT, - "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", - CID(context), program, location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4fEXT, + "context = %d, program = %u, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", + CID(context), program, location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4fEXT) && - ValidateProgramUniform4fEXT(context, angle::EntryPoint::GLProgramUniform4fEXT, - programPacked, locationPacked, v0, v1, v2, v3))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4fEXT(context, angle::EntryPoint::GLProgramUniform4fEXT, + programPacked, locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform4fEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4f(programPacked, locationPacked, v0, v1, v2, v3); } @@ -9157,7 +13319,7 @@ void GL_APIENTRY GL_ProgramUniform4fEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4fEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9169,23 +13331,37 @@ void GL_APIENTRY GL_ProgramUniform4fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4fvEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4fvEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4fvEXT) && - ValidateProgramUniform4fvEXT(context, angle::EntryPoint::GLProgramUniform4fvEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4fvEXT(context, angle::EntryPoint::GLProgramUniform4fvEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform4fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4fv(programPacked, locationPacked, count, value); } @@ -9194,7 +13370,7 @@ void GL_APIENTRY GL_ProgramUniform4fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9204,23 +13380,37 @@ GL_ProgramUniform4iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4iEXT, - "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d", - CID(context), program, location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4iEXT, + "context = %d, program = %u, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d", + CID(context), program, location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4iEXT) && - ValidateProgramUniform4iEXT(context, angle::EntryPoint::GLProgramUniform4iEXT, - programPacked, locationPacked, v0, v1, v2, v3))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4iEXT(context, angle::EntryPoint::GLProgramUniform4iEXT, + programPacked, locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform4iEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4i(programPacked, locationPacked, v0, v1, v2, v3); } @@ -9229,7 +13419,7 @@ GL_ProgramUniform4iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4iEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9241,23 +13431,37 @@ void GL_APIENTRY GL_ProgramUniform4ivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4ivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4ivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4ivEXT) && - ValidateProgramUniform4ivEXT(context, angle::EntryPoint::GLProgramUniform4ivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4ivEXT(context, angle::EntryPoint::GLProgramUniform4ivEXT, + programPacked, locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform4ivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4iv(programPacked, locationPacked, count, value); } @@ -9266,7 +13470,7 @@ void GL_APIENTRY GL_ProgramUniform4ivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4ivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9276,23 +13480,37 @@ GL_ProgramUniform4uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GL { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4uiEXT, - "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u, v3 = %u", - CID(context), program, location, v0, v1, v2, v3); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4uiEXT, + "context = %d, program = %u, location = %d, v0 = %u, v1 = %u, v2 = %u, v3 = %u", + CID(context), program, location, v0, v1, v2, v3)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4uiEXT) && - ValidateProgramUniform4uiEXT(context, angle::EntryPoint::GLProgramUniform4uiEXT, - programPacked, locationPacked, v0, v1, v2, v3))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramUniform4uiEXT(context, angle::EntryPoint::GLProgramUniform4uiEXT, + programPacked, locationPacked, v0, v1, v2, v3); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform4uiEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4ui(programPacked, locationPacked, v0, v1, v2, v3); } @@ -9301,7 +13519,7 @@ GL_ProgramUniform4uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GL } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4uiEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9313,23 +13531,37 @@ void GL_APIENTRY GL_ProgramUniform4uivEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniform4uivEXT, - "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", - CID(context), program, location, count, (uintptr_t)value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLProgramUniform4uivEXT, + "context = %d, program = %u, location = %d, count = %d, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniform4uivEXT) && - ValidateProgramUniform4uivEXT(context, angle::EntryPoint::GLProgramUniform4uivEXT, - programPacked, locationPacked, count, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniform4uivEXT( + context, angle::EntryPoint::GLProgramUniform4uivEXT, programPacked, + locationPacked, count, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniform4uivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniform4uiv(programPacked, locationPacked, count, value); } @@ -9338,7 +13570,7 @@ void GL_APIENTRY GL_ProgramUniform4uivEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramUniform4uivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9351,25 +13583,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix2fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix2fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix2fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix2fvEXT) && - ValidateProgramUniformMatrix2fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix2fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix2fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix2fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix2fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix2fv(programPacked, locationPacked, count, transpose, value); @@ -9379,7 +13624,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix2fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix2fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9392,25 +13638,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x3fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix2x3fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix2x3fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT) && - ValidateProgramUniformMatrix2x3fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix2x3fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix2x3fv(programPacked, locationPacked, count, transpose, value); @@ -9420,7 +13679,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x3fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9433,25 +13693,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x4fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix2x4fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix2x4fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT) && - ValidateProgramUniformMatrix2x4fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix2x4fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix2x4fv(programPacked, locationPacked, count, transpose, value); @@ -9461,7 +13734,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix2x4fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9474,25 +13748,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix3fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix3fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix3fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix3fvEXT) && - ValidateProgramUniformMatrix3fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix3fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix3fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix3fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix3fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix3fv(programPacked, locationPacked, count, transpose, value); @@ -9502,7 +13789,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix3fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix3fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9515,25 +13803,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x2fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix3x2fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix3x2fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT) && - ValidateProgramUniformMatrix3x2fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix3x2fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix3x2fv(programPacked, locationPacked, count, transpose, value); @@ -9543,7 +13844,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x2fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9556,25 +13858,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x4fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix3x4fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix3x4fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT) && - ValidateProgramUniformMatrix3x4fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix3x4fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix3x4fv(programPacked, locationPacked, count, transpose, value); @@ -9584,7 +13899,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix3x4fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9597,25 +13913,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix4fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix4fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix4fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix4fvEXT) && - ValidateProgramUniformMatrix4fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix4fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix4fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix4fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix4fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix4fv(programPacked, locationPacked, count, transpose, value); @@ -9625,7 +13954,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix4fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix4fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9638,25 +13968,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x2fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix4x2fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix4x2fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT) && - ValidateProgramUniformMatrix4x2fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix4x2fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix4x2fv(programPacked, locationPacked, count, transpose, value); @@ -9666,7 +14009,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x2fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9679,25 +14023,38 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x3fvEXT(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramUniformMatrix4x3fvEXT, - "context = %d, program = %u, location = %d, count = %d, transpose = %s, value = " - "0x%016" PRIxPTR "", - CID(context), program, location, count, GLbooleanToString(transpose), (uintptr_t)value); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramUniformMatrix4x3fvEXT, + "context = %d, program = %u, location = %d, count = %d, transpose = " + "%s, value = 0x%016" PRIxPTR "", + CID(context), program, location, count, GLbooleanToString(transpose), + (uintptr_t)value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT) && - ValidateProgramUniformMatrix4x3fvEXT( - context, angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT, programPacked, - locationPacked, count, transpose, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateProgramUniformMatrix4x3fvEXT( + context, angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT, programPacked, + locationPacked, count, transpose, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programUniformMatrix4x3fv(programPacked, locationPacked, count, transpose, value); @@ -9707,7 +14064,8 @@ void GL_APIENTRY GL_ProgramUniformMatrix4x3fvEXT(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9716,23 +14074,37 @@ void GL_APIENTRY GL_UseProgramStagesEXT(GLuint pipeline, GLbitfield stages, GLui { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUseProgramStagesEXT, "context = %d, pipeline = %u, stages = %s, program = %u", - CID(context), pipeline, GLbitfieldToString(GLESEnum::UseProgramStageMask, stages).c_str(), - program); + ANGLE_UNSAFE_TODO( + EVENT(context, GLUseProgramStagesEXT, + "context = %d, pipeline = %u, stages = %s, program = %u", CID(context), pipeline, + GLbitfieldToString(GLESEnum::UseProgramStageMask, stages).c_str(), program)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLUseProgramStagesEXT) && - ValidateUseProgramStagesEXT(context, angle::EntryPoint::GLUseProgramStagesEXT, - pipelinePacked, stages, programPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateUseProgramStagesEXT(context, angle::EntryPoint::GLUseProgramStagesEXT, + pipelinePacked, stages, programPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLUseProgramStagesEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->useProgramStages(pipelinePacked, stages, programPacked); } @@ -9741,7 +14113,7 @@ void GL_APIENTRY GL_UseProgramStagesEXT(GLuint pipeline, GLbitfield stages, GLui } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUseProgramStagesEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9750,21 +14122,33 @@ void GL_APIENTRY GL_ValidateProgramPipelineEXT(GLuint pipeline) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLValidateProgramPipelineEXT, "context = %d, pipeline = %u", CID(context), - pipeline); + ANGLE_UNSAFE_TODO(EVENT(context, GLValidateProgramPipelineEXT, "context = %d, pipeline = %u", + CID(context), pipeline)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ProgramPipelineID pipelinePacked = PackParam(pipeline); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLValidateProgramPipelineEXT) && - ValidateValidateProgramPipelineEXT( - context, angle::EntryPoint::GLValidateProgramPipelineEXT, pipelinePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().separateShaderObjectsEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateValidateProgramPipelineEXT( + context, angle::EntryPoint::GLValidateProgramPipelineEXT, pipelinePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLValidateProgramPipelineEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->validateProgramPipeline(pipelinePacked); } @@ -9772,7 +14156,8 @@ void GL_APIENTRY GL_ValidateProgramPipelineEXT(GLuint pipeline) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLValidateProgramPipelineEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9784,19 +14169,31 @@ void GL_APIENTRY GL_FramebufferFetchBarrierEXT() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferFetchBarrierEXT, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferFetchBarrierEXT, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferFetchBarrierEXT) && - ValidateFramebufferFetchBarrierEXT(context, - angle::EntryPoint::GLFramebufferFetchBarrierEXT))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().shaderFramebufferFetchNonCoherentEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferFetchBarrierEXT( + context, angle::EntryPoint::GLFramebufferFetchBarrierEXT); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferFetchBarrierEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferFetchBarrier(); } @@ -9804,7 +14201,8 @@ void GL_APIENTRY GL_FramebufferFetchBarrierEXT() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferFetchBarrierEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9815,6 +14213,8 @@ void GL_APIENTRY GL_FramebufferFetchBarrierEXT() // GL_EXT_shader_texture_lod +// GL_EXT_shader_texture_samples + // GL_EXT_shadow_samplers // GL_EXT_tessellation_shader @@ -9822,20 +14222,33 @@ void GL_APIENTRY GL_PatchParameteriEXT(GLenum pname, GLint value) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPatchParameteriEXT, "context = %d, pname = %s, value = %d", CID(context), - GLenumToString(GLESEnum::PatchParameterName, pname), value); + ANGLE_UNSAFE_TODO(EVENT(context, GLPatchParameteriEXT, "context = %d, pname = %s, value = %d", + CID(context), GLenumToString(GLESEnum::PatchParameterName, pname), + value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPatchParameteriEXT) && - ValidatePatchParameteriEXT(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPatchParameteriEXT, pname, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().tessellationShaderEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePatchParameteriEXT( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPatchParameteriEXT, pname, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPatchParameteriEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePatchParameteri(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, value); @@ -9844,7 +14257,7 @@ void GL_APIENTRY GL_PatchParameteriEXT(GLenum pname, GLint value) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPatchParameteriEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9854,19 +14267,36 @@ void GL_APIENTRY GL_GetSamplerParameterIivEXT(GLuint sampler, GLenum pname, GLin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIivEXT, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterIivEXT, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterIivEXT( - context, angle::EntryPoint::GLGetSamplerParameterIivEXT, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIivEXT( + context, angle::EntryPoint::GLGetSamplerParameterIivEXT, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetSamplerParameterIivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIiv(samplerPacked, pname, params); } @@ -9875,7 +14305,8 @@ void GL_APIENTRY GL_GetSamplerParameterIivEXT(GLuint sampler, GLenum pname, GLin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9884,19 +14315,36 @@ void GL_APIENTRY GL_GetSamplerParameterIuivEXT(GLuint sampler, GLenum pname, GLu { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIuivEXT, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterIuivEXT, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterIuivEXT( - context, angle::EntryPoint::GLGetSamplerParameterIuivEXT, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIuivEXT( + context, angle::EntryPoint::GLGetSamplerParameterIuivEXT, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetSamplerParameterIuivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIuiv(samplerPacked, pname, params); } @@ -9905,7 +14353,8 @@ void GL_APIENTRY GL_GetSamplerParameterIuivEXT(GLuint sampler, GLenum pname, GLu } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIuivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9914,20 +14363,37 @@ void GL_APIENTRY GL_GetTexParameterIivEXT(GLenum target, GLenum pname, GLint *pa { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIivEXT, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterIivEXT, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterIivEXT(context, angle::EntryPoint::GLGetTexParameterIivEXT, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIivEXT( + context, angle::EntryPoint::GLGetTexParameterIivEXT, targetPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexParameterIivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIiv(targetPacked, pname, params); } @@ -9935,7 +14401,7 @@ void GL_APIENTRY GL_GetTexParameterIivEXT(GLenum target, GLenum pname, GLint *pa } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterIivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9944,20 +14410,37 @@ void GL_APIENTRY GL_GetTexParameterIuivEXT(GLenum target, GLenum pname, GLuint * { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIuivEXT, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterIuivEXT, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterIuivEXT(context, angle::EntryPoint::GLGetTexParameterIuivEXT, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIuivEXT( + context, angle::EntryPoint::GLGetTexParameterIuivEXT, targetPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexParameterIuivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIuiv(targetPacked, pname, params); } @@ -9965,7 +14448,7 @@ void GL_APIENTRY GL_GetTexParameterIuivEXT(GLenum target, GLenum pname, GLuint * } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterIuivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -9974,19 +14457,36 @@ void GL_APIENTRY GL_SamplerParameterIivEXT(GLuint sampler, GLenum pname, const G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIivEXT, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterIivEXT, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterIivEXT(context, angle::EntryPoint::GLSamplerParameterIivEXT, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIivEXT( + context, angle::EntryPoint::GLSamplerParameterIivEXT, samplerPacked, pname, + param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSamplerParameterIivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIiv(samplerPacked, pname, param); } @@ -9994,7 +14494,7 @@ void GL_APIENTRY GL_SamplerParameterIivEXT(GLuint sampler, GLenum pname, const G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameterIivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10003,19 +14503,36 @@ void GL_APIENTRY GL_SamplerParameterIuivEXT(GLuint sampler, GLenum pname, const { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIuivEXT, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterIuivEXT, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterIuivEXT(context, angle::EntryPoint::GLSamplerParameterIuivEXT, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIuivEXT( + context, angle::EntryPoint::GLSamplerParameterIuivEXT, samplerPacked, pname, + param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSamplerParameterIuivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIuiv(samplerPacked, pname, param); } @@ -10024,7 +14541,8 @@ void GL_APIENTRY GL_SamplerParameterIuivEXT(GLuint sampler, GLenum pname, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSamplerParameterIuivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10033,20 +14551,36 @@ void GL_APIENTRY GL_TexParameterIivEXT(GLenum target, GLenum pname, const GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIivEXT, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterIivEXT, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexParameterIivEXT(context, angle::EntryPoint::GLTexParameterIivEXT, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIivEXT( + context, angle::EntryPoint::GLTexParameterIivEXT, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterIivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIiv(targetPacked, pname, params); } @@ -10054,7 +14588,7 @@ void GL_APIENTRY GL_TexParameterIivEXT(GLenum target, GLenum pname, const GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterIivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10063,20 +14597,36 @@ void GL_APIENTRY GL_TexParameterIuivEXT(GLenum target, GLenum pname, const GLuin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIuivEXT, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterIuivEXT, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexParameterIuivEXT(context, angle::EntryPoint::GLTexParameterIuivEXT, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIuivEXT( + context, angle::EntryPoint::GLTexParameterIuivEXT, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterIuivEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIuiv(targetPacked, pname, params); } @@ -10084,7 +14634,7 @@ void GL_APIENTRY GL_TexParameterIuivEXT(GLenum target, GLenum pname, const GLuin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterIuivEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10094,23 +14644,36 @@ void GL_APIENTRY GL_TexBufferEXT(GLenum target, GLenum internalformat, GLuint bu { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexBufferEXT, "context = %d, target = %s, internalformat = %s, buffer = %u", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexBufferEXT, + "context = %d, target = %s, internalformat = %s, buffer = %u", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexBufferEXT) && - ValidateTexBufferEXT(context, angle::EntryPoint::GLTexBufferEXT, targetPacked, - internalformat, bufferPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBufferEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexBufferEXT(context, angle::EntryPoint::GLTexBufferEXT, + targetPacked, internalformat, bufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexBufferEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texBuffer(targetPacked, internalformat, bufferPacked); } @@ -10119,7 +14682,7 @@ void GL_APIENTRY GL_TexBufferEXT(GLenum target, GLenum internalformat, GLuint bu } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexBufferEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10132,25 +14695,39 @@ void GL_APIENTRY GL_TexBufferRangeEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexBufferRangeEXT, - "context = %d, target = %s, internalformat = %s, buffer = %u, offset = %llu, size = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer, - static_cast(offset), static_cast(size)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexBufferRangeEXT, + "context = %d, target = %s, internalformat = %s, buffer = %u, offset = %llu, size = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer, + static_cast(offset), static_cast(size))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexBufferRangeEXT) && - ValidateTexBufferRangeEXT(context, angle::EntryPoint::GLTexBufferRangeEXT, - targetPacked, internalformat, bufferPacked, offset, size))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBufferEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexBufferRangeEXT( + context, angle::EntryPoint::GLTexBufferRangeEXT, targetPacked, internalformat, + bufferPacked, offset, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexBufferRangeEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texBufferRange(targetPacked, internalformat, bufferPacked, offset, size); } @@ -10159,7 +14736,7 @@ void GL_APIENTRY GL_TexBufferRangeEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexBufferRangeEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10203,42 +14780,6 @@ void GL_APIENTRY GL_TexBufferRangeEXT(GLenum target, // GL_EXT_texture_shadow_lod // GL_EXT_texture_storage -void GL_APIENTRY GL_TexStorage1DEXT(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width) -{ - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); - Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage1DEXT, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width); - - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage1DEXT) && - ValidateTexStorage1DEXT(context, angle::EntryPoint::GLTexStorage1DEXT, target, levels, - internalformat, width))); - if (isCallValid) - { - context->texStorage1D(target, levels, internalformat, width); - } - ANGLE_CAPTURE_GL(TexStorage1DEXT, isCallValid, context, target, levels, internalformat, - width); - } - else - { - GenerateContextLostErrorOnCurrentGlobalContext(); - } - ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); -} - void GL_APIENTRY GL_TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, @@ -10247,23 +14788,37 @@ void GL_APIENTRY GL_TexStorage2DEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage2DEXT, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexStorage2DEXT, + "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage2DEXT) && - ValidateTexStorage2DEXT(context, angle::EntryPoint::GLTexStorage2DEXT, targetPacked, - levels, internalformat, width, height))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureStorageEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateTexStorage2DEXT(context, angle::EntryPoint::GLTexStorage2DEXT, + targetPacked, levels, internalformat, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorage2DEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage2D(targetPacked, levels, internalformat, width, height); } @@ -10272,7 +14827,7 @@ void GL_APIENTRY GL_TexStorage2DEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorage2DEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10286,24 +14841,38 @@ void GL_APIENTRY GL_TexStorage3DEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage3DEXT, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, depth); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorage3DEXT, + "context = %d, target = %s, levels = %d, internalformat = %s, width = " + "%d, height = %d, depth = %d", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, depth)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage3DEXT) && - ValidateTexStorage3DEXT(context, angle::EntryPoint::GLTexStorage3DEXT, targetPacked, - levels, internalformat, width, height, depth))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureStorageEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorage3DEXT(context, angle::EntryPoint::GLTexStorage3DEXT, + targetPacked, levels, internalformat, width, + height, depth); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorage3DEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage3D(targetPacked, levels, internalformat, width, height, depth); } @@ -10312,7 +14881,7 @@ void GL_APIENTRY GL_TexStorage3DEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorage3DEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10327,25 +14896,37 @@ void GL_APIENTRY GL_TexStorageAttribs2DEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageAttribs2DEXT, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d, " - "attrib_list = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorageAttribs2DEXT, + "context = %d, target = %s, levels = %d, internalformat = %s, width = " + "%d, height = %d, attrib_list = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, (uintptr_t)attrib_list)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageAttribs2DEXT) && - ValidateTexStorageAttribs2DEXT(context, angle::EntryPoint::GLTexStorageAttribs2DEXT, - target, levels, internalformat, width, height, - attrib_list))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureStorageCompressionEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageAttribs2DEXT( + context, angle::EntryPoint::GLTexStorageAttribs2DEXT, target, levels, + internalformat, width, height, attrib_list); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorageAttribs2DEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageAttribs2D(target, levels, internalformat, width, height, attrib_list); @@ -10355,7 +14936,7 @@ void GL_APIENTRY GL_TexStorageAttribs2DEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorageAttribs2DEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10370,25 +14951,37 @@ void GL_APIENTRY GL_TexStorageAttribs3DEXT(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorageAttribs3DEXT, - "context = %d, target = %s, levels = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, attrib_list = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, depth, - (uintptr_t)attrib_list); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorageAttribs3DEXT, + "context = %d, target = %s, levels = %d, internalformat = %s, width = " + "%d, height = %d, depth = %d, attrib_list = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), levels, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, depth, (uintptr_t)attrib_list)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorageAttribs3DEXT) && - ValidateTexStorageAttribs3DEXT(context, angle::EntryPoint::GLTexStorageAttribs3DEXT, - target, levels, internalformat, width, height, depth, - attrib_list))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureStorageCompressionEXT)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorageAttribs3DEXT( + context, angle::EntryPoint::GLTexStorageAttribs3DEXT, target, levels, + internalformat, width, height, depth, attrib_list); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorageAttribs3DEXT); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorageAttribs3D(target, levels, internalformat, width, height, depth, attrib_list); @@ -10398,7 +14991,7 @@ void GL_APIENTRY GL_TexStorageAttribs3DEXT(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexStorageAttribs3DEXT); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10416,18 +15009,31 @@ void GL_APIENTRY GL_BlendBarrierKHR() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendBarrierKHR, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendBarrierKHR, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendBarrierKHR) && - ValidateBlendBarrierKHR(context, angle::EntryPoint::GLBlendBarrierKHR))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blendEquationAdvancedKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateBlendBarrierKHR(context, angle::EntryPoint::GLBlendBarrierKHR); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendBarrierKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->blendBarrier(); } @@ -10435,7 +15041,7 @@ void GL_APIENTRY GL_BlendBarrierKHR() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendBarrierKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10447,18 +15053,34 @@ void GL_APIENTRY GL_DebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDebugMessageCallbackKHR, - "context = %d, callback = 0x%016" PRIxPTR ", userParam = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)callback, (uintptr_t)userParam); + ANGLE_UNSAFE_TODO(EVENT(context, GLDebugMessageCallbackKHR, + "context = %d, callback = 0x%016" PRIxPTR ", userParam = 0x%016" PRIxPTR + "", + CID(context), (uintptr_t)callback, (uintptr_t)userParam)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDebugMessageCallbackKHR(context, angle::EntryPoint::GLDebugMessageCallbackKHR, - callback, userParam)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDebugMessageCallbackKHR( + context, angle::EntryPoint::GLDebugMessageCallbackKHR, callback, userParam); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDebugMessageCallbackKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->debugMessageCallback(callback, userParam); } @@ -10466,7 +15088,8 @@ void GL_APIENTRY GL_DebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDebugMessageCallbackKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10480,22 +15103,39 @@ void GL_APIENTRY GL_DebugMessageControlKHR(GLenum source, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDebugMessageControlKHR, - "context = %d, source = %s, type = %s, severity = %s, count = %d, ids = 0x%016" PRIxPTR - ", enabled = %s", - CID(context), GLenumToString(GLESEnum::DebugSource, source), - GLenumToString(GLESEnum::DebugType, type), - GLenumToString(GLESEnum::DebugSeverity, severity), count, (uintptr_t)ids, - GLbooleanToString(enabled)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLDebugMessageControlKHR, + "context = %d, source = %s, type = %s, severity = %s, count = %d, ids = 0x%016" PRIxPTR + ", enabled = %s", + CID(context), GLenumToString(GLESEnum::DebugSource, source), + GLenumToString(GLESEnum::DebugType, type), + GLenumToString(GLESEnum::DebugSeverity, severity), count, (uintptr_t)ids, + GLbooleanToString(enabled))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDebugMessageControlKHR(context, angle::EntryPoint::GLDebugMessageControlKHR, - source, type, severity, count, ids, enabled)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDebugMessageControlKHR( + context, angle::EntryPoint::GLDebugMessageControlKHR, source, type, severity, + count, ids, enabled); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDebugMessageControlKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->debugMessageControl(source, type, severity, count, ids, enabled); } @@ -10504,7 +15144,7 @@ void GL_APIENTRY GL_DebugMessageControlKHR(GLenum source, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDebugMessageControlKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10518,21 +15158,38 @@ void GL_APIENTRY GL_DebugMessageInsertKHR(GLenum source, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDebugMessageInsertKHR, - "context = %d, source = %s, type = %s, id = %u, severity = %s, length = %d, buf = " - "0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::DebugSource, source), - GLenumToString(GLESEnum::DebugType, type), id, - GLenumToString(GLESEnum::DebugSeverity, severity), length, (uintptr_t)buf); + ANGLE_UNSAFE_TODO(EVENT(context, GLDebugMessageInsertKHR, + "context = %d, source = %s, type = %s, id = %u, severity = %s, length " + "= %d, buf = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::DebugSource, source), + GLenumToString(GLESEnum::DebugType, type), id, + GLenumToString(GLESEnum::DebugSeverity, severity), length, + (uintptr_t)buf)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDebugMessageInsertKHR(context, angle::EntryPoint::GLDebugMessageInsertKHR, - source, type, id, severity, length, buf)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDebugMessageInsertKHR( + context, angle::EntryPoint::GLDebugMessageInsertKHR, source, type, id, severity, + length, buf); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDebugMessageInsertKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->debugMessageInsert(source, type, id, severity, length, buf); } @@ -10541,7 +15198,7 @@ void GL_APIENTRY GL_DebugMessageInsertKHR(GLenum source, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDebugMessageInsertKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10557,22 +15214,39 @@ GLuint GL_APIENTRY GL_GetDebugMessageLogKHR(GLuint count, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetDebugMessageLogKHR, - "context = %d, count = %u, bufSize = %d, sources = 0x%016" PRIxPTR - ", types = 0x%016" PRIxPTR ", ids = 0x%016" PRIxPTR ", severities = 0x%016" PRIxPTR - ", lengths = 0x%016" PRIxPTR ", messageLog = 0x%016" PRIxPTR "", - CID(context), count, bufSize, (uintptr_t)sources, (uintptr_t)types, (uintptr_t)ids, - (uintptr_t)severities, (uintptr_t)lengths, (uintptr_t)messageLog); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetDebugMessageLogKHR, + "context = %d, count = %u, bufSize = %d, sources = 0x%016" PRIxPTR + ", types = 0x%016" PRIxPTR ", ids = 0x%016" PRIxPTR ", severities = 0x%016" PRIxPTR + ", lengths = 0x%016" PRIxPTR ", messageLog = 0x%016" PRIxPTR "", + CID(context), count, bufSize, (uintptr_t)sources, (uintptr_t)types, (uintptr_t)ids, + (uintptr_t)severities, (uintptr_t)lengths, (uintptr_t)messageLog)); GLuint returnValue; - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetDebugMessageLogKHR( - context, angle::EntryPoint::GLGetDebugMessageLogKHR, count, bufSize, - sources, types, ids, severities, lengths, messageLog)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetDebugMessageLogKHR( + context, angle::EntryPoint::GLGetDebugMessageLogKHR, count, bufSize, sources, + types, ids, severities, lengths, messageLog); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetDebugMessageLogKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getDebugMessageLog(count, bufSize, sources, types, ids, severities, lengths, messageLog); @@ -10587,7 +15261,7 @@ GLuint GL_APIENTRY GL_GetDebugMessageLogKHR(GLuint count, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetDebugMessageLogKHR); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -10602,20 +15276,37 @@ void GL_APIENTRY GL_GetObjectLabelKHR(GLenum identifier, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetObjectLabelKHR, - "context = %d, identifier = %s, name = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", label = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, identifier), name, bufSize, - (uintptr_t)length, (uintptr_t)label); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetObjectLabelKHR, + "context = %d, identifier = %s, name = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", label = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, identifier), name, bufSize, + (uintptr_t)length, (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetObjectLabelKHR(context, angle::EntryPoint::GLGetObjectLabelKHR, identifier, - name, bufSize, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetObjectLabelKHR(context, angle::EntryPoint::GLGetObjectLabelKHR, + identifier, name, bufSize, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetObjectLabelKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getObjectLabel(identifier, name, bufSize, length, label); } @@ -10624,7 +15315,7 @@ void GL_APIENTRY GL_GetObjectLabelKHR(GLenum identifier, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetObjectLabelKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10636,19 +15327,36 @@ void GL_APIENTRY GL_GetObjectPtrLabelKHR(const void *ptr, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetObjectPtrLabelKHR, - "context = %d, ptr = 0x%016" PRIxPTR ", bufSize = %d, length = 0x%016" PRIxPTR - ", label = 0x%016" PRIxPTR "", - CID(context), (uintptr_t)ptr, bufSize, (uintptr_t)length, (uintptr_t)label); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetObjectPtrLabelKHR, + "context = %d, ptr = 0x%016" PRIxPTR + ", bufSize = %d, length = 0x%016" PRIxPTR ", label = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)ptr, bufSize, (uintptr_t)length, + (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetObjectPtrLabelKHR(context, angle::EntryPoint::GLGetObjectPtrLabelKHR, ptr, - bufSize, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetObjectPtrLabelKHR(context, angle::EntryPoint::GLGetObjectPtrLabelKHR, + ptr, bufSize, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetObjectPtrLabelKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getObjectPtrLabel(ptr, bufSize, length, label); } @@ -10656,7 +15364,7 @@ void GL_APIENTRY GL_GetObjectPtrLabelKHR(const void *ptr, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetObjectPtrLabelKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10665,16 +15373,33 @@ void GL_APIENTRY GL_GetPointervKHR(GLenum pname, void **params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetPointervKHR, "context = %d, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetPointervKHR, + "context = %d, pname = %s, params = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetPointervKHR(context, angle::EntryPoint::GLGetPointervKHR, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetPointervKHR(context, angle::EntryPoint::GLGetPointervKHR, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetPointervKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getPointerv(pname, params); } @@ -10682,7 +15407,7 @@ void GL_APIENTRY GL_GetPointervKHR(GLenum pname, void **params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetPointervKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10694,18 +15419,35 @@ void GL_APIENTRY GL_ObjectLabelKHR(GLenum identifier, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLObjectLabelKHR, - "context = %d, identifier = %s, name = %u, length = %d, label = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::ObjectIdentifier, identifier), name, length, - (uintptr_t)label); + ANGLE_UNSAFE_TODO( + EVENT(context, GLObjectLabelKHR, + "context = %d, identifier = %s, name = %u, length = %d, label = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::ObjectIdentifier, identifier), name, length, + (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateObjectLabelKHR(context, angle::EntryPoint::GLObjectLabelKHR, - identifier, name, length, label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateObjectLabelKHR(context, angle::EntryPoint::GLObjectLabelKHR, + identifier, name, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLObjectLabelKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->objectLabel(identifier, name, length, label); } @@ -10713,7 +15455,7 @@ void GL_APIENTRY GL_ObjectLabelKHR(GLenum identifier, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLObjectLabelKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10722,18 +15464,34 @@ void GL_APIENTRY GL_ObjectPtrLabelKHR(const void *ptr, GLsizei length, const GLc { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLObjectPtrLabelKHR, - "context = %d, ptr = 0x%016" PRIxPTR ", length = %d, label = 0x%016" PRIxPTR "", - CID(context), (uintptr_t)ptr, length, (uintptr_t)label); + ANGLE_UNSAFE_TODO(EVENT(context, GLObjectPtrLabelKHR, + "context = %d, ptr = 0x%016" PRIxPTR + ", length = %d, label = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)ptr, length, (uintptr_t)label)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateObjectPtrLabelKHR(context, angle::EntryPoint::GLObjectPtrLabelKHR, ptr, length, - label)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateObjectPtrLabelKHR( + context, angle::EntryPoint::GLObjectPtrLabelKHR, ptr, length, label); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLObjectPtrLabelKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->objectPtrLabel(ptr, length, label); } @@ -10741,7 +15499,7 @@ void GL_APIENTRY GL_ObjectPtrLabelKHR(const void *ptr, GLsizei length, const GLc } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLObjectPtrLabelKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10750,15 +15508,31 @@ void GL_APIENTRY GL_PopDebugGroupKHR() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPopDebugGroupKHR, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPopDebugGroupKHR, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidatePopDebugGroupKHR(context, angle::EntryPoint::GLPopDebugGroupKHR)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidatePopDebugGroupKHR(context, angle::EntryPoint::GLPopDebugGroupKHR); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPopDebugGroupKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->popDebugGroup(); } @@ -10766,7 +15540,7 @@ void GL_APIENTRY GL_PopDebugGroupKHR() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPopDebugGroupKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10778,19 +15552,35 @@ void GL_APIENTRY GL_PushDebugGroupKHR(GLenum source, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPushDebugGroupKHR, - "context = %d, source = %s, id = %u, length = %d, message = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::DebugSource, source), id, length, - (uintptr_t)message); + ANGLE_UNSAFE_TODO( + EVENT(context, GLPushDebugGroupKHR, + "context = %d, source = %s, id = %u, length = %d, message = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::DebugSource, source), id, length, + (uintptr_t)message)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidatePushDebugGroupKHR(context, angle::EntryPoint::GLPushDebugGroupKHR, source, id, - length, message)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().debugKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePushDebugGroupKHR( + context, angle::EntryPoint::GLPushDebugGroupKHR, source, id, length, message); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPushDebugGroupKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->pushDebugGroup(source, id, length, message); } @@ -10798,7 +15588,7 @@ void GL_APIENTRY GL_PushDebugGroupKHR(GLenum source, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPushDebugGroupKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10810,19 +15600,32 @@ void GL_APIENTRY GL_MaxShaderCompilerThreadsKHR(GLuint count) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMaxShaderCompilerThreadsKHR, "context = %d, count = %u", CID(context), count); + ANGLE_UNSAFE_TODO(EVENT(context, GLMaxShaderCompilerThreadsKHR, "context = %d, count = %u", + CID(context), count)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMaxShaderCompilerThreadsKHR) && - ValidateMaxShaderCompilerThreadsKHR( - context, angle::EntryPoint::GLMaxShaderCompilerThreadsKHR, count))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().parallelShaderCompileKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMaxShaderCompilerThreadsKHR( + context, angle::EntryPoint::GLMaxShaderCompilerThreadsKHR, count); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMaxShaderCompilerThreadsKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->maxShaderCompilerThreads(count); } @@ -10830,7 +15633,8 @@ void GL_APIENTRY GL_MaxShaderCompilerThreadsKHR(GLuint count) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLMaxShaderCompilerThreadsKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10842,16 +15646,32 @@ GLenum GL_APIENTRY GL_GetGraphicsResetStatusKHR() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetGlobalContext(); - EVENT(context, GLGetGraphicsResetStatusKHR, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetGraphicsResetStatusKHR, "context = %d", CID(context))); GLenum returnValue; - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetGraphicsResetStatusKHR( - context, angle::EntryPoint::GLGetGraphicsResetStatusKHR)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetGraphicsResetStatusKHR( + context, angle::EntryPoint::GLGetGraphicsResetStatusKHR); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetGraphicsResetStatusKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->getGraphicsResetStatus(); } @@ -10879,20 +15699,37 @@ void GL_APIENTRY GL_GetnUniformfvKHR(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformfvKHR, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformfvKHR, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetnUniformfvKHR(context, angle::EntryPoint::GLGetnUniformfvKHR, programPacked, - locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetnUniformfvKHR(context, angle::EntryPoint::GLGetnUniformfvKHR, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformfvKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformfv(programPacked, locationPacked, bufSize, params); } @@ -10901,7 +15738,7 @@ void GL_APIENTRY GL_GetnUniformfvKHR(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformfvKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10910,20 +15747,37 @@ void GL_APIENTRY GL_GetnUniformivKHR(GLuint program, GLint location, GLsizei buf { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformivKHR, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformivKHR, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetnUniformivKHR(context, angle::EntryPoint::GLGetnUniformivKHR, programPacked, - locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetnUniformivKHR(context, angle::EntryPoint::GLGetnUniformivKHR, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformivKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformiv(programPacked, locationPacked, bufSize, params); } @@ -10932,7 +15786,7 @@ void GL_APIENTRY GL_GetnUniformivKHR(GLuint program, GLint location, GLsizei buf } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformivKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10944,20 +15798,37 @@ void GL_APIENTRY GL_GetnUniformuivKHR(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetnUniformuivKHR, - "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", - CID(context), program, location, bufSize, (uintptr_t)params); + ANGLE_UNSAFE_TODO( + EVENT(context, GLGetnUniformuivKHR, + "context = %d, program = %u, location = %d, bufSize = %d, params = 0x%016" PRIxPTR "", + CID(context), program, location, bufSize, (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); UniformLocation locationPacked = PackParam(location); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetnUniformuivKHR(context, angle::EntryPoint::GLGetnUniformuivKHR, - programPacked, locationPacked, bufSize, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetnUniformuivKHR(context, angle::EntryPoint::GLGetnUniformuivKHR, + programPacked, locationPacked, bufSize, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetnUniformuivKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getnUniformuiv(programPacked, locationPacked, bufSize, params); } @@ -10966,7 +15837,7 @@ void GL_APIENTRY GL_GetnUniformuivKHR(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetnUniformuivKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -10982,23 +15853,37 @@ void GL_APIENTRY GL_ReadnPixelsKHR(GLint x, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLReadnPixelsKHR, - "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, bufSize " - "= %d, data = 0x%016" PRIxPTR "", - CID(context), x, y, width, height, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), bufSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT(context, GLReadnPixelsKHR, + "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, " + "type = %s, bufSize = %d, data = 0x%016" PRIxPTR "", + CID(context), x, y, width, height, + GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), bufSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLReadnPixelsKHR) && - ValidateReadnPixelsKHR(context, angle::EntryPoint::GLReadnPixelsKHR, x, y, width, - height, format, type, bufSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().robustnessKHR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateReadnPixelsKHR(context, angle::EntryPoint::GLReadnPixelsKHR, x, y, + width, height, format, type, bufSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLReadnPixelsKHR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->readnPixels(x, y, width, height, format, type, bufSize, data); } @@ -11007,7 +15892,7 @@ void GL_APIENTRY GL_ReadnPixelsKHR(GLint x, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLReadnPixelsKHR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11023,18 +15908,38 @@ void GL_APIENTRY GL_FramebufferParameteriMESA(GLenum target, GLenum pname, GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferParameteriMESA, "context = %d, target = %s, pname = %s, param = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferParameterName, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferParameteriMESA, + "context = %d, target = %s, pname = %s, param = %d", CID(context), + GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferParameterName, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferParameteriMESA( - context, angle::EntryPoint::GLFramebufferParameteriMESA, target, pname, param)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferFlipYMESA)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferParameteriMESA( + context, angle::EntryPoint::GLFramebufferParameteriMESA, target, pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferParameteriMESA); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferParameteriMESA(target, pname, param); } @@ -11042,7 +15947,8 @@ void GL_APIENTRY GL_FramebufferParameteriMESA(GLenum target, GLenum pname, GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferParameteriMESA); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11051,19 +15957,37 @@ void GL_APIENTRY GL_GetFramebufferParameterivMESA(GLenum target, GLenum pname, G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferParameterivMESA, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetFramebufferParameterivMESA, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetFramebufferParameterivMESA( - context, angle::EntryPoint::GLGetFramebufferParameterivMESA, target, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferFlipYMESA)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferParameterivMESA( + context, angle::EntryPoint::GLGetFramebufferParameterivMESA, target, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetFramebufferParameterivMESA); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferParameterivMESA(target, pname, params); } @@ -11072,7 +15996,8 @@ void GL_APIENTRY GL_GetFramebufferParameterivMESA(GLenum target, GLenum pname, G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferParameterivMESA); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11082,17 +16007,34 @@ void GL_APIENTRY GL_DeleteFencesNV(GLsizei n, const GLuint *fences) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteFencesNV, "context = %d, n = %d, fences = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)fences); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteFencesNV, + "context = %d, n = %d, fences = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)fences)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const FenceNVID *fencesPacked = PackParam(fences); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteFencesNV(context, angle::EntryPoint::GLDeleteFencesNV, n, fencesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteFencesNV(context, angle::EntryPoint::GLDeleteFencesNV, + n, fencesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteFencesNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteFencesNV(n, fencesPacked); } @@ -11100,7 +16042,7 @@ void GL_APIENTRY GL_DeleteFencesNV(GLsizei n, const GLuint *fences) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteFencesNV); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11109,19 +16051,33 @@ void GL_APIENTRY GL_FinishFenceNV(GLuint fence) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFinishFenceNV, "context = %d, fence = %u", CID(context), fence); + ANGLE_UNSAFE_TODO( + EVENT(context, GLFinishFenceNV, "context = %d, fence = %u", CID(context), fence)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FenceNVID fencePacked = PackParam(fence); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFinishFenceNV) && - ValidateFinishFenceNV(context, angle::EntryPoint::GLFinishFenceNV, fencePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateFinishFenceNV(context, angle::EntryPoint::GLFinishFenceNV, fencePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFinishFenceNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->finishFenceNV(fencePacked); } @@ -11129,7 +16085,7 @@ void GL_APIENTRY GL_FinishFenceNV(GLuint fence) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFinishFenceNV); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -11138,17 +16094,34 @@ void GL_APIENTRY GL_GenFencesNV(GLsizei n, GLuint *fences) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenFencesNV, "context = %d, n = %d, fences = 0x%016" PRIxPTR "", CID(context), - n, (uintptr_t)fences); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenFencesNV, + "context = %d, n = %d, fences = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)fences)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FenceNVID *fencesPacked = PackParam(fences); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenFencesNV(context, angle::EntryPoint::GLGenFencesNV, n, fencesPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGenFencesNV(context, angle::EntryPoint::GLGenFencesNV, n, fencesPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenFencesNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genFencesNV(n, fencesPacked); } @@ -11156,7 +16129,7 @@ void GL_APIENTRY GL_GenFencesNV(GLsizei n, GLuint *fences) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenFencesNV); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11165,18 +16138,34 @@ void GL_APIENTRY GL_GetFenceivNV(GLuint fence, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFenceivNV, - "context = %d, fence = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), fence, - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetFenceivNV, "context = %d, fence = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), fence, GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FenceNVID fencePacked = PackParam(fence); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetFenceivNV(context, angle::EntryPoint::GLGetFenceivNV, - fencePacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFenceivNV(context, angle::EntryPoint::GLGetFenceivNV, + fencePacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetFenceivNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFenceivNV(fencePacked, pname, params); } @@ -11184,7 +16173,7 @@ void GL_APIENTRY GL_GetFenceivNV(GLuint fence, GLenum pname, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetFenceivNV); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11193,17 +16182,33 @@ GLboolean GL_APIENTRY GL_IsFenceNV(GLuint fence) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsFenceNV, "context = %d, fence = %u", CID(context), fence); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsFenceNV, "context = %d, fence = %u", CID(context), fence)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FenceNVID fencePacked = PackParam(fence); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsFenceNV(context, angle::EntryPoint::GLIsFenceNV, fencePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateIsFenceNV(context, angle::EntryPoint::GLIsFenceNV, fencePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsFenceNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isFenceNV(fencePacked); } @@ -11215,7 +16220,7 @@ GLboolean GL_APIENTRY GL_IsFenceNV(GLuint fence) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsFenceNV); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -11226,21 +16231,33 @@ void GL_APIENTRY GL_SetFenceNV(GLuint fence, GLenum condition) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSetFenceNV, "context = %d, fence = %u, condition = %s", CID(context), fence, - GLenumToString(GLESEnum::AllEnums, condition)); + ANGLE_UNSAFE_TODO(EVENT(context, GLSetFenceNV, "context = %d, fence = %u, condition = %s", + CID(context), fence, GLenumToString(GLESEnum::AllEnums, condition))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FenceNVID fencePacked = PackParam(fence); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLSetFenceNV) && - ValidateSetFenceNV(context, angle::EntryPoint::GLSetFenceNV, fencePacked, - condition))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSetFenceNV(context, angle::EntryPoint::GLSetFenceNV, + fencePacked, condition); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSetFenceNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->setFenceNV(fencePacked, condition); } @@ -11248,7 +16265,7 @@ void GL_APIENTRY GL_SetFenceNV(GLuint fence, GLenum condition) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSetFenceNV); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11257,20 +16274,34 @@ GLboolean GL_APIENTRY GL_TestFenceNV(GLuint fence) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTestFenceNV, "context = %d, fence = %u", CID(context), fence); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTestFenceNV, "context = %d, fence = %u", CID(context), fence)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FenceNVID fencePacked = PackParam(fence); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTestFenceNV) && - ValidateTestFenceNV(context, angle::EntryPoint::GLTestFenceNV, fencePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().fenceNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateTestFenceNV(context, angle::EntryPoint::GLTestFenceNV, fencePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTestFenceNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->testFenceNV(fencePacked); } @@ -11282,7 +16313,7 @@ GLboolean GL_APIENTRY GL_TestFenceNV(GLuint fence) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTestFenceNV); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -11303,25 +16334,37 @@ void GL_APIENTRY GL_BlitFramebufferNV(GLint srcX0, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlitFramebufferNV, - "context = %d, srcX0 = %d, srcY0 = %d, srcX1 = %d, srcY1 = %d, dstX0 = %d, dstY0 = %d, " - "dstX1 = %d, dstY1 = %d, mask = %s, filter = %s", - CID(context), srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str(), - GLenumToString(GLESEnum::BlitFramebufferFilter, filter)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlitFramebufferNV, + "context = %d, srcX0 = %d, srcY0 = %d, srcX1 = %d, srcY1 = %d, dstX0 = " + "%d, dstY0 = %d, dstX1 = %d, dstY1 = %d, mask = %s, filter = %s", + CID(context), srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + GLbitfieldToString(GLESEnum::ClearBufferMask, mask).c_str(), + GLenumToString(GLESEnum::BlitFramebufferFilter, filter))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlitFramebufferNV) && - ValidateBlitFramebufferNV(context, angle::EntryPoint::GLBlitFramebufferNV, srcX0, - srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, - filter))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferBlitNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlitFramebufferNV( + context, angle::EntryPoint::GLBlitFramebufferNV, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlitFramebufferNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->blitFramebufferNV(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); @@ -11331,11 +16374,13 @@ void GL_APIENTRY GL_BlitFramebufferNV(GLint srcX0, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlitFramebufferNV); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } +// GL_NV_pack_subimage + // GL_NV_pixel_buffer_object // GL_NV_polygon_mode @@ -11343,19 +16388,34 @@ void GL_APIENTRY GL_PolygonModeNV(GLenum face, GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPolygonModeNV, "context = %d, face = %s, mode = %s", CID(context), - GLenumToString(GLESEnum::TriangleFace, face), - GLenumToString(GLESEnum::PolygonMode, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLPolygonModeNV, "context = %d, face = %s, mode = %s", + CID(context), GLenumToString(GLESEnum::TriangleFace, face), + GLenumToString(GLESEnum::PolygonMode, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PolygonMode modePacked = PackParam(mode); - bool isCallValid = - (context->skipValidation() || - ValidatePolygonModeNV(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPolygonModeNV, face, modePacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().polygonModeNV)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePolygonModeNV( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPolygonModeNV, face, modePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPolygonModeNV); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePolygonModeNV(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), face, modePacked); @@ -11364,7 +16424,7 @@ void GL_APIENTRY GL_PolygonModeNV(GLenum face, GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPolygonModeNV); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11384,23 +16444,36 @@ void GL_APIENTRY GL_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglIma { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEGLImageTargetRenderbufferStorageOES, - "context = %d, target = %s, image = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::AllEnums, target), (uintptr_t)image); + ANGLE_UNSAFE_TODO(EVENT(context, GLEGLImageTargetRenderbufferStorageOES, + "context = %d, target = %s, image = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::AllEnums, target), (uintptr_t)image)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { egl::ImageID imagePacked = PackParam(image); SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEGLImageTargetRenderbufferStorageOES) && - ValidateEGLImageTargetRenderbufferStorageOES( - context, angle::EntryPoint::GLEGLImageTargetRenderbufferStorageOES, target, - imagePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().EGLImageOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEGLImageTargetRenderbufferStorageOES( + context, angle::EntryPoint::GLEGLImageTargetRenderbufferStorageOES, target, + imagePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLEGLImageTargetRenderbufferStorageOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->eGLImageTargetRenderbufferStorage(target, imagePacked); } @@ -11409,7 +16482,8 @@ void GL_APIENTRY GL_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglIma } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLEGLImageTargetRenderbufferStorageOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11418,24 +16492,37 @@ void GL_APIENTRY GL_EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES imag { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEGLImageTargetTexture2DOES, - "context = %d, target = %s, image = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::AllEnums, target), (uintptr_t)image); + ANGLE_UNSAFE_TODO(EVENT(context, GLEGLImageTargetTexture2DOES, + "context = %d, target = %s, image = 0x%016" PRIxPTR "", CID(context), + GLenumToString(GLESEnum::AllEnums, target), (uintptr_t)image)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); egl::ImageID imagePacked = PackParam(image); SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEGLImageTargetTexture2DOES) && - ValidateEGLImageTargetTexture2DOES(context, - angle::EntryPoint::GLEGLImageTargetTexture2DOES, - targetPacked, imagePacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().EGLImageExternalOES || + context->getExtensions().EGLImageOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEGLImageTargetTexture2DOES( + context, angle::EntryPoint::GLEGLImageTargetTexture2DOES, targetPacked, + imagePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEGLImageTargetTexture2DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->eGLImageTargetTexture2D(targetPacked, imagePacked); } @@ -11444,12 +16531,14 @@ void GL_APIENTRY GL_EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES imag } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLEGLImageTargetTexture2DOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } // GL_OES_EGL_image_external +// EGLImageTargetTexture2DOES is already defined. // GL_OES_EGL_image_external_essl3 @@ -11458,16 +16547,32 @@ void GL_APIENTRY GL_BlendEquationOES(GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationOES, "context = %d, mode = %s", CID(context), - GLenumToString(GLESEnum::BlendEquationModeEXT, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationOES, "context = %d, mode = %s", CID(context), + GLenumToString(GLESEnum::BlendEquationModeEXT, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateBlendEquationOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationOES, mode)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().blendSubtractOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationOES(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationOES, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendEquationOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquation(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), mode); @@ -11476,7 +16581,7 @@ void GL_APIENTRY GL_BlendEquationOES(GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquationOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11504,28 +16609,41 @@ void GL_APIENTRY GL_CopyImageSubDataOES(GLuint srcName, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyImageSubDataOES, - "context = %d, srcName = %u, srcTarget = %s, srcLevel = %d, srcX = %d, srcY = %d, srcZ = " - "%d, dstName = %u, dstTarget = %s, dstLevel = %d, dstX = %d, dstY = %d, dstZ = %d, " - "srcWidth = %d, srcHeight = %d, srcDepth = %d", - CID(context), srcName, GLenumToString(GLESEnum::CopyBufferSubDataTarget, srcTarget), - srcLevel, srcX, srcY, srcZ, dstName, - GLenumToString(GLESEnum::CopyBufferSubDataTarget, dstTarget), dstLevel, dstX, dstY, dstZ, - srcWidth, srcHeight, srcDepth); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCopyImageSubDataOES, + "context = %d, srcName = %u, srcTarget = %s, srcLevel = %d, srcX = %d, srcY = %d, " + "srcZ = %d, dstName = %u, dstTarget = %s, dstLevel = %d, dstX = %d, dstY = %d, dstZ " + "= %d, srcWidth = %d, srcHeight = %d, srcDepth = %d", + CID(context), srcName, GLenumToString(GLESEnum::CopyBufferSubDataTarget, srcTarget), + srcLevel, srcX, srcY, srcZ, dstName, + GLenumToString(GLESEnum::CopyBufferSubDataTarget, dstTarget), dstLevel, dstX, dstY, + dstZ, srcWidth, srcHeight, srcDepth)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyImageSubDataOES) && - ValidateCopyImageSubDataOES(context, angle::EntryPoint::GLCopyImageSubDataOES, - srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, - dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, - srcHeight, srcDepth))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().copyImageOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyImageSubDataOES( + context, angle::EntryPoint::GLCopyImageSubDataOES, srcName, srcTarget, srcLevel, + srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, + srcHeight, srcDepth); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopyImageSubDataOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, @@ -11537,7 +16655,7 @@ void GL_APIENTRY GL_CopyImageSubDataOES(GLuint srcName, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyImageSubDataOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11553,19 +16671,34 @@ void GL_APIENTRY GL_BlendEquationSeparateiOES(GLuint buf, GLenum modeRGB, GLenum { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationSeparateiOES, - "context = %d, buf = %u, modeRGB = %s, modeAlpha = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), - GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationSeparateiOES, + "context = %d, buf = %u, modeRGB = %s, modeAlpha = %s", CID(context), + buf, GLenumToString(GLESEnum::BlendEquationModeEXT, modeRGB), + GLenumToString(GLESEnum::BlendEquationModeEXT, modeAlpha))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendEquationSeparateiOES( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationSeparateiOES, buf, modeRGB, modeAlpha)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationSeparateiOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationSeparateiOES, buf, modeRGB, modeAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendEquationSeparateiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationSeparatei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, @@ -11575,7 +16708,8 @@ void GL_APIENTRY GL_BlendEquationSeparateiOES(GLuint buf, GLenum modeRGB, GLenum } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLBlendEquationSeparateiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11584,17 +16718,33 @@ void GL_APIENTRY GL_BlendEquationiOES(GLuint buf, GLenum mode) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendEquationiOES, "context = %d, buf = %u, mode = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendEquationModeEXT, mode)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendEquationiOES, "context = %d, buf = %u, mode = %s", + CID(context), buf, + GLenumToString(GLESEnum::BlendEquationModeEXT, mode))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendEquationiOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendEquationiOES, buf, mode)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendEquationiOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendEquationiOES, buf, mode); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendEquationiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendEquationi(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, mode); @@ -11603,7 +16753,7 @@ void GL_APIENTRY GL_BlendEquationiOES(GLuint buf, GLenum mode) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendEquationiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11613,22 +16763,38 @@ GL_BlendFuncSeparateiOES(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlp { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFuncSeparateiOES, - "context = %d, buf = %u, srcRGB = %s, dstRGB = %s, srcAlpha = %s, dstAlpha = %s", - CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, srcRGB), - GLenumToString(GLESEnum::BlendingFactor, dstRGB), - GLenumToString(GLESEnum::BlendingFactor, srcAlpha), - GLenumToString(GLESEnum::BlendingFactor, dstAlpha)); - - if (context) - { - bool isCallValid = - (context->skipValidation() || - ValidateBlendFuncSeparateiOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFuncSeparateiOES, buf, srcRGB, - dstRGB, srcAlpha, dstAlpha)); - if (isCallValid) + ANGLE_UNSAFE_TODO( + EVENT(context, GLBlendFuncSeparateiOES, + "context = %d, buf = %u, srcRGB = %s, dstRGB = %s, srcAlpha = %s, dstAlpha = %s", + CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, srcRGB), + GLenumToString(GLESEnum::BlendingFactor, dstRGB), + GLenumToString(GLESEnum::BlendingFactor, srcAlpha), + GLenumToString(GLESEnum::BlendingFactor, dstAlpha))); + + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFuncSeparateiOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFuncSeparateiOES, buf, srcRGB, dstRGB, srcAlpha, + dstAlpha); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendFuncSeparateiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFuncSeparatei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, srcRGB, @@ -11639,7 +16805,7 @@ GL_BlendFuncSeparateiOES(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlp } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFuncSeparateiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11648,18 +16814,33 @@ void GL_APIENTRY GL_BlendFunciOES(GLuint buf, GLenum src, GLenum dst) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBlendFunciOES, "context = %d, buf = %u, src = %s, dst = %s", CID(context), buf, - GLenumToString(GLESEnum::BlendingFactor, src), - GLenumToString(GLESEnum::BlendingFactor, dst)); + ANGLE_UNSAFE_TODO(EVENT(context, GLBlendFunciOES, "context = %d, buf = %u, src = %s, dst = %s", + CID(context), buf, GLenumToString(GLESEnum::BlendingFactor, src), + GLenumToString(GLESEnum::BlendingFactor, dst))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateBlendFunciOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBlendFunciOES, buf, src, dst)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBlendFunciOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLBlendFunciOES, buf, src, dst); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBlendFunciOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateBlendFunci(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), buf, src, dst); @@ -11668,7 +16849,7 @@ void GL_APIENTRY GL_BlendFunciOES(GLuint buf, GLenum src, GLenum dst) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBlendFunciOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11677,18 +16858,34 @@ void GL_APIENTRY GL_ColorMaskiOES(GLuint index, GLboolean r, GLboolean g, GLbool { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLColorMaskiOES, "context = %d, index = %u, r = %s, g = %s, b = %s, a = %s", - CID(context), index, GLbooleanToString(r), GLbooleanToString(g), GLbooleanToString(b), - GLbooleanToString(a)); + ANGLE_UNSAFE_TODO(EVENT(context, GLColorMaskiOES, + "context = %d, index = %u, r = %s, g = %s, b = %s, a = %s", + CID(context), index, GLbooleanToString(r), GLbooleanToString(g), + GLbooleanToString(b), GLbooleanToString(a))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - ValidateColorMaskiOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLColorMaskiOES, index, r, g, b, a)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateColorMaskiOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLColorMaskiOES, index, r, g, b, a); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLColorMaskiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateColorMaski(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), index, r, g, b, a); @@ -11697,7 +16894,7 @@ void GL_APIENTRY GL_ColorMaskiOES(GLuint index, GLboolean r, GLboolean g, GLbool } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLColorMaskiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11706,16 +16903,32 @@ void GL_APIENTRY GL_DisableiOES(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDisableiOES, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLDisableiOES, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateDisableiOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLDisableiOES, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDisableiOES(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLDisableiOES, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDisableiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateDisablei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, index); @@ -11724,7 +16937,7 @@ void GL_APIENTRY GL_DisableiOES(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDisableiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11733,16 +16946,32 @@ void GL_APIENTRY GL_EnableiOES(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEnableiOES, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLEnableiOES, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = (context->skipValidation() || - ValidateEnableiOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEnableiOES, target, index)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEnableiOES(context->getPrivateState(), + context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLEnableiOES, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEnableiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateEnablei(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), target, index); @@ -11751,7 +16980,7 @@ void GL_APIENTRY GL_EnableiOES(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEnableiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11760,18 +16989,33 @@ GLboolean GL_APIENTRY GL_IsEnablediOES(GLenum target, GLuint index) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsEnablediOES, "context = %d, target = %s, index = %u", CID(context), - GLenumToString(GLESEnum::EnableCap, target), index); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsEnablediOES, "context = %d, target = %s, index = %u", + CID(context), GLenumToString(GLESEnum::EnableCap, target), index)); GLboolean returnValue; - if (context) - { - bool isCallValid = - (context->skipValidation() || - ValidateIsEnablediOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLIsEnablediOES, target, index)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawBuffersIndexedOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsEnablediOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLIsEnablediOES, target, index); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsEnablediOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = ContextPrivateIsEnabledi(context->getMutablePrivateState(), @@ -11785,7 +17029,7 @@ GLboolean GL_APIENTRY GL_IsEnablediOES(GLenum target, GLuint index) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsEnablediOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -11801,22 +17045,39 @@ void GL_APIENTRY GL_DrawElementsBaseVertexOES(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsBaseVertexOES, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsBaseVertexOES, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsBaseVertexOES( - context, angle::EntryPoint::GLDrawElementsBaseVertexOES, modePacked, - count, typePacked, indices, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsBaseVertexOES( + context, angle::EntryPoint::GLDrawElementsBaseVertexOES, modePacked, count, + typePacked, indices, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawElementsBaseVertexOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsBaseVertex(modePacked, count, typePacked, indices, basevertex); } @@ -11825,7 +17086,8 @@ void GL_APIENTRY GL_DrawElementsBaseVertexOES(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsBaseVertexOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11839,23 +17101,41 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexOES(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawElementsInstancedBaseVertexOES, - "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR - ", instancecount = %d, basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, - basevertex); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawElementsInstancedBaseVertexOES, + "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR + ", instancecount = %d, basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), count, + GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, instancecount, + basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawElementsInstancedBaseVertexOES( - context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexOES, - modePacked, count, typePacked, indices, instancecount, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawElementsInstancedBaseVertexOES( + context, angle::EntryPoint::GLDrawElementsInstancedBaseVertexOES, modePacked, + count, typePacked, indices, instancecount, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawElementsInstancedBaseVertexOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawElementsInstancedBaseVertex(modePacked, count, typePacked, indices, instancecount, basevertex); @@ -11865,7 +17145,8 @@ void GL_APIENTRY GL_DrawElementsInstancedBaseVertexOES(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawElementsInstancedBaseVertexOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11880,22 +17161,40 @@ void GL_APIENTRY GL_DrawRangeElementsBaseVertexOES(GLenum mode, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawRangeElementsBaseVertexOES, - "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, indices = " - "0x%016" PRIxPTR ", basevertex = %d", - CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, count, - GLenumToString(GLESEnum::DrawElementsType, type), (uintptr_t)indices, basevertex); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawRangeElementsBaseVertexOES, + "context = %d, mode = %s, start = %u, end = %u, count = %d, type = %s, " + "indices = 0x%016" PRIxPTR ", basevertex = %d", + CID(context), GLenumToString(GLESEnum::PrimitiveType, mode), start, end, + count, GLenumToString(GLESEnum::DrawElementsType, type), + (uintptr_t)indices, basevertex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { PrimitiveMode modePacked = PackParam(mode); DrawElementsType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawRangeElementsBaseVertexOES( - context, angle::EntryPoint::GLDrawRangeElementsBaseVertexOES, - modePacked, start, end, count, typePacked, indices, basevertex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawElementsBaseVertexOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawRangeElementsBaseVertexOES( + context, angle::EntryPoint::GLDrawRangeElementsBaseVertexOES, modePacked, start, + end, count, typePacked, indices, basevertex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLDrawRangeElementsBaseVertexOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawRangeElementsBaseVertex(modePacked, start, end, count, typePacked, indices, basevertex); @@ -11905,7 +17204,8 @@ void GL_APIENTRY GL_DrawRangeElementsBaseVertexOES(GLenum mode, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLDrawRangeElementsBaseVertexOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11917,16 +17217,33 @@ void GL_APIENTRY GL_DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexfOES, "context = %d, x = %f, y = %f, z = %f, width = %f, height = %f", - CID(context), x, y, z, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexfOES, + "context = %d, x = %f, y = %f, z = %f, width = %f, height = %f", + CID(context), x, y, z, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawTexfOES(context, angle::EntryPoint::GLDrawTexfOES, x, y, z, - width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawTexfOES(context, angle::EntryPoint::GLDrawTexfOES, x, y, + z, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexfOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexf(x, y, z, width, height); } @@ -11934,7 +17251,7 @@ void GL_APIENTRY GL_DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexfOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11943,16 +17260,32 @@ void GL_APIENTRY GL_DrawTexfvOES(const GLfloat *coords) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexfvOES, "context = %d, coords = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)coords); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexfvOES, "context = %d, coords = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)coords)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawTexfvOES(context, angle::EntryPoint::GLDrawTexfvOES, coords)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawTexfvOES(context, angle::EntryPoint::GLDrawTexfvOES, coords); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexfvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexfv(coords); } @@ -11960,7 +17293,7 @@ void GL_APIENTRY GL_DrawTexfvOES(const GLfloat *coords) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexfvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11969,16 +17302,33 @@ void GL_APIENTRY GL_DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint he { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexiOES, "context = %d, x = %d, y = %d, z = %d, width = %d, height = %d", - CID(context), x, y, z, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexiOES, + "context = %d, x = %d, y = %d, z = %d, width = %d, height = %d", + CID(context), x, y, z, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawTexiOES(context, angle::EntryPoint::GLDrawTexiOES, x, y, z, - width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawTexiOES(context, angle::EntryPoint::GLDrawTexiOES, x, y, + z, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexiOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexi(x, y, z, width, height); } @@ -11986,7 +17336,7 @@ void GL_APIENTRY GL_DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint he } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexiOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -11995,16 +17345,32 @@ void GL_APIENTRY GL_DrawTexivOES(const GLint *coords) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexivOES, "context = %d, coords = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)coords); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexivOES, "context = %d, coords = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)coords)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawTexivOES(context, angle::EntryPoint::GLDrawTexivOES, coords)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawTexivOES(context, angle::EntryPoint::GLDrawTexivOES, coords); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexiv(coords); } @@ -12012,7 +17378,7 @@ void GL_APIENTRY GL_DrawTexivOES(const GLint *coords) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12021,16 +17387,33 @@ void GL_APIENTRY GL_DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexsOES, "context = %d, x = %d, y = %d, z = %d, width = %d, height = %d", - CID(context), x, y, z, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexsOES, + "context = %d, x = %d, y = %d, z = %d, width = %d, height = %d", + CID(context), x, y, z, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawTexsOES(context, angle::EntryPoint::GLDrawTexsOES, x, y, z, - width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawTexsOES(context, angle::EntryPoint::GLDrawTexsOES, x, y, + z, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexsOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexs(x, y, z, width, height); } @@ -12038,7 +17421,7 @@ void GL_APIENTRY GL_DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexsOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12047,16 +17430,32 @@ void GL_APIENTRY GL_DrawTexsvOES(const GLshort *coords) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexsvOES, "context = %d, coords = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)coords); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexsvOES, "context = %d, coords = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)coords)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawTexsvOES(context, angle::EntryPoint::GLDrawTexsvOES, coords)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawTexsvOES(context, angle::EntryPoint::GLDrawTexsvOES, coords); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexsvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexsv(coords); } @@ -12064,7 +17463,7 @@ void GL_APIENTRY GL_DrawTexsvOES(const GLshort *coords) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexsvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12073,17 +17472,34 @@ void GL_APIENTRY GL_DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexxOES, - "context = %d, x = 0x%X, y = 0x%X, z = 0x%X, width = 0x%X, height = 0x%X", CID(context), - x, y, z, width, height); + ANGLE_UNSAFE_TODO( + EVENT(context, GLDrawTexxOES, + "context = %d, x = 0x%X, y = 0x%X, z = 0x%X, width = 0x%X, height = 0x%X", + CID(context), x, y, z, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateDrawTexxOES(context, angle::EntryPoint::GLDrawTexxOES, x, y, z, - width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDrawTexxOES(context, angle::EntryPoint::GLDrawTexxOES, x, y, + z, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexxOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexx(x, y, z, width, height); } @@ -12091,7 +17507,7 @@ void GL_APIENTRY GL_DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexxOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12100,16 +17516,32 @@ void GL_APIENTRY GL_DrawTexxvOES(const GLfixed *coords) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDrawTexxvOES, "context = %d, coords = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)coords); + ANGLE_UNSAFE_TODO(EVENT(context, GLDrawTexxvOES, "context = %d, coords = 0x%016" PRIxPTR "", + CID(context), (uintptr_t)coords)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDrawTexxvOES(context, angle::EntryPoint::GLDrawTexxvOES, coords)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().drawTextureOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateDrawTexxvOES(context, angle::EntryPoint::GLDrawTexxvOES, coords); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDrawTexxvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->drawTexxv(coords); } @@ -12117,7 +17549,7 @@ void GL_APIENTRY GL_DrawTexxvOES(const GLfixed *coords) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDrawTexxvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12131,18 +17563,34 @@ void GL_APIENTRY GL_BindFramebufferOES(GLenum target, GLuint framebuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindFramebufferOES, "context = %d, target = %s, framebuffer = %u", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), framebuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindFramebufferOES, + "context = %d, target = %s, framebuffer = %u", CID(context), + GLenumToString(GLESEnum::FramebufferTarget, target), framebuffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID framebufferPacked = PackParam(framebuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateBindFramebufferOES(context, angle::EntryPoint::GLBindFramebufferOES, target, - framebufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindFramebufferOES( + context, angle::EntryPoint::GLBindFramebufferOES, target, framebufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBindFramebufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindFramebuffer(target, framebufferPacked); } @@ -12150,7 +17598,7 @@ void GL_APIENTRY GL_BindFramebufferOES(GLenum target, GLuint framebuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindFramebufferOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12159,18 +17607,34 @@ void GL_APIENTRY GL_BindRenderbufferOES(GLenum target, GLuint renderbuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindRenderbufferOES, "context = %d, target = %s, renderbuffer = %u", - CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), renderbuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLBindRenderbufferOES, + "context = %d, target = %s, renderbuffer = %u", CID(context), + GLenumToString(GLESEnum::RenderbufferTarget, target), renderbuffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID renderbufferPacked = PackParam(renderbuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateBindRenderbufferOES(context, angle::EntryPoint::GLBindRenderbufferOES, target, - renderbufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindRenderbufferOES( + context, angle::EntryPoint::GLBindRenderbufferOES, target, renderbufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBindRenderbufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindRenderbuffer(target, renderbufferPacked); } @@ -12178,7 +17642,7 @@ void GL_APIENTRY GL_BindRenderbufferOES(GLenum target, GLuint renderbuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindRenderbufferOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12187,17 +17651,33 @@ GLenum GL_APIENTRY GL_CheckFramebufferStatusOES(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCheckFramebufferStatusOES, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLCheckFramebufferStatusOES, "context = %d, target = %s", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target))); GLenum returnValue; - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateCheckFramebufferStatusOES( - context, angle::EntryPoint::GLCheckFramebufferStatusOES, target)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCheckFramebufferStatusOES( + context, angle::EntryPoint::GLCheckFramebufferStatusOES, target); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCheckFramebufferStatusOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->checkFramebufferStatus(target); } @@ -12210,7 +17690,8 @@ GLenum GL_APIENTRY GL_CheckFramebufferStatusOES(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCheckFramebufferStatusOES); returnValue = GetDefaultReturnValue(); } @@ -12222,19 +17703,34 @@ void GL_APIENTRY GL_DeleteFramebuffersOES(GLsizei n, const GLuint *framebuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteFramebuffersOES, - "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)framebuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteFramebuffersOES, + "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)framebuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const FramebufferID *framebuffersPacked = PackParam(framebuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteFramebuffersOES(context, angle::EntryPoint::GLDeleteFramebuffersOES, n, - framebuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteFramebuffersOES( + context, angle::EntryPoint::GLDeleteFramebuffersOES, n, framebuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteFramebuffersOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteFramebuffers(n, framebuffersPacked); } @@ -12242,7 +17738,7 @@ void GL_APIENTRY GL_DeleteFramebuffersOES(GLsizei n, const GLuint *framebuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteFramebuffersOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12251,20 +17747,35 @@ void GL_APIENTRY GL_DeleteRenderbuffersOES(GLsizei n, const GLuint *renderbuffer { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteRenderbuffersOES, - "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", CID(context), n, - (uintptr_t)renderbuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteRenderbuffersOES, + "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)renderbuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const RenderbufferID *renderbuffersPacked = PackParam(renderbuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteRenderbuffersOES(context, angle::EntryPoint::GLDeleteRenderbuffersOES, n, - renderbuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteRenderbuffersOES( + context, angle::EntryPoint::GLDeleteRenderbuffersOES, n, renderbuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteRenderbuffersOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteRenderbuffers(n, renderbuffersPacked); } @@ -12272,7 +17783,7 @@ void GL_APIENTRY GL_DeleteRenderbuffersOES(GLsizei n, const GLuint *renderbuffer } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteRenderbuffersOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12284,21 +17795,38 @@ void GL_APIENTRY GL_FramebufferRenderbufferOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferRenderbufferOES, - "context = %d, target = %s, attachment = %s, renderbuffertarget = %s, renderbuffer = %u", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::RenderbufferTarget, renderbuffertarget), renderbuffer); + ANGLE_UNSAFE_TODO(EVENT( + context, GLFramebufferRenderbufferOES, + "context = %d, target = %s, attachment = %s, renderbuffertarget = %s, renderbuffer = %u", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::RenderbufferTarget, renderbuffertarget), renderbuffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID renderbufferPacked = PackParam(renderbuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateFramebufferRenderbufferOES( - context, angle::EntryPoint::GLFramebufferRenderbufferOES, target, - attachment, renderbuffertarget, renderbufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferRenderbufferOES( + context, angle::EntryPoint::GLFramebufferRenderbufferOES, target, attachment, + renderbuffertarget, renderbufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferRenderbufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbufferPacked); @@ -12308,7 +17836,8 @@ void GL_APIENTRY GL_FramebufferRenderbufferOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferRenderbufferOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12321,22 +17850,43 @@ void GL_APIENTRY GL_FramebufferTexture2DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTexture2DOES, - "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::TextureTarget, textarget), texture, level); + ANGLE_UNSAFE_TODO(EVENT( + context, GLFramebufferTexture2DOES, + "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::TextureTarget, textarget), texture, level)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget textargetPacked = PackParam(textarget); TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateFramebufferTexture2DOES( - context, angle::EntryPoint::GLFramebufferTexture2DOES, target, - attachment, textargetPacked, texturePacked, level)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTexture2DOES( + context, angle::EntryPoint::GLFramebufferTexture2DOES, target, attachment, + textargetPacked, texturePacked, level); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferTexture2DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexture2D(target, attachment, textargetPacked, texturePacked, level); @@ -12346,7 +17896,8 @@ void GL_APIENTRY GL_FramebufferTexture2DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTexture2DOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12355,18 +17906,34 @@ void GL_APIENTRY GL_GenFramebuffersOES(GLsizei n, GLuint *framebuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenFramebuffersOES, "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)framebuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenFramebuffersOES, + "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)framebuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID *framebuffersPacked = PackParam(framebuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenFramebuffersOES(context, angle::EntryPoint::GLGenFramebuffersOES, n, - framebuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenFramebuffersOES( + context, angle::EntryPoint::GLGenFramebuffersOES, n, framebuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenFramebuffersOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genFramebuffers(n, framebuffersPacked); } @@ -12374,7 +17941,7 @@ void GL_APIENTRY GL_GenFramebuffersOES(GLsizei n, GLuint *framebuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenFramebuffersOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12383,18 +17950,34 @@ void GL_APIENTRY GL_GenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenRenderbuffersOES, "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)renderbuffers); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenRenderbuffersOES, + "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "", CID(context), + n, (uintptr_t)renderbuffers)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID *renderbuffersPacked = PackParam(renderbuffers); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGenRenderbuffersOES(context, angle::EntryPoint::GLGenRenderbuffersOES, n, - renderbuffersPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenRenderbuffersOES( + context, angle::EntryPoint::GLGenRenderbuffersOES, n, renderbuffersPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenRenderbuffersOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genRenderbuffers(n, renderbuffersPacked); } @@ -12402,7 +17985,7 @@ void GL_APIENTRY GL_GenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenRenderbuffersOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12411,17 +17994,33 @@ void GL_APIENTRY GL_GenerateMipmapOES(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenerateMipmapOES, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::TextureTarget, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenerateMipmapOES, "context = %d, target = %s", CID(context), + GLenumToString(GLESEnum::TextureTarget, target))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenerateMipmapOES( - context, angle::EntryPoint::GLGenerateMipmapOES, targetPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenerateMipmapOES( + context, angle::EntryPoint::GLGenerateMipmapOES, targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenerateMipmapOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->generateMipmap(targetPacked); } @@ -12429,7 +18028,7 @@ void GL_APIENTRY GL_GenerateMipmapOES(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenerateMipmapOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12441,21 +18040,38 @@ void GL_APIENTRY GL_GetFramebufferAttachmentParameterivOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetFramebufferAttachmentParameterivOES, - "context = %d, target = %s, attachment = %s, pname = %s, params = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLGetFramebufferAttachmentParameterivOES, + "context = %d, target = %s, attachment = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::FramebufferAttachmentParameterName, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetFramebufferAttachmentParameterivOES( - context, angle::EntryPoint::GLGetFramebufferAttachmentParameterivOES, target, - attachment, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetFramebufferAttachmentParameterivOES( + context, angle::EntryPoint::GLGetFramebufferAttachmentParameterivOES, target, + attachment, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLGetFramebufferAttachmentParameterivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getFramebufferAttachmentParameteriv(target, attachment, pname, params); } @@ -12464,7 +18080,8 @@ void GL_APIENTRY GL_GetFramebufferAttachmentParameterivOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetFramebufferAttachmentParameterivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12473,19 +18090,37 @@ void GL_APIENTRY GL_GetRenderbufferParameterivOES(GLenum target, GLenum pname, G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetRenderbufferParameterivOES, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::RenderbufferTarget, target), - GLenumToString(GLESEnum::RenderbufferParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetRenderbufferParameterivOES, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), + GLenumToString(GLESEnum::RenderbufferParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetRenderbufferParameterivOES( - context, angle::EntryPoint::GLGetRenderbufferParameterivOES, target, - pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetRenderbufferParameterivOES( + context, angle::EntryPoint::GLGetRenderbufferParameterivOES, target, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLGetRenderbufferParameterivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getRenderbufferParameteriv(target, pname, params); } @@ -12494,7 +18129,8 @@ void GL_APIENTRY GL_GetRenderbufferParameterivOES(GLenum target, GLenum pname, G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetRenderbufferParameterivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12503,17 +18139,34 @@ GLboolean GL_APIENTRY GL_IsFramebufferOES(GLuint framebuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsFramebufferOES, "context = %d, framebuffer = %u", CID(context), framebuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsFramebufferOES, "context = %d, framebuffer = %u", + CID(context), framebuffer)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID framebufferPacked = PackParam(framebuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateIsFramebufferOES(context, angle::EntryPoint::GLIsFramebufferOES, - framebufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsFramebufferOES( + context, angle::EntryPoint::GLIsFramebufferOES, framebufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsFramebufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isFramebuffer(framebufferPacked); } @@ -12525,7 +18178,7 @@ GLboolean GL_APIENTRY GL_IsFramebufferOES(GLuint framebuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsFramebufferOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -12536,19 +18189,34 @@ GLboolean GL_APIENTRY GL_IsRenderbufferOES(GLuint renderbuffer) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsRenderbufferOES, "context = %d, renderbuffer = %u", CID(context), - renderbuffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLIsRenderbufferOES, "context = %d, renderbuffer = %u", + CID(context), renderbuffer)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { RenderbufferID renderbufferPacked = PackParam(renderbuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsRenderbufferOES(context, angle::EntryPoint::GLIsRenderbufferOES, - renderbufferPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsRenderbufferOES( + context, angle::EntryPoint::GLIsRenderbufferOES, renderbufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsRenderbufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->isRenderbuffer(renderbufferPacked); } @@ -12561,7 +18229,7 @@ GLboolean GL_APIENTRY GL_IsRenderbufferOES(GLuint renderbuffer) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsRenderbufferOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -12575,19 +18243,36 @@ void GL_APIENTRY GL_RenderbufferStorageOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLRenderbufferStorageOES, - "context = %d, target = %s, internalformat = %s, width = %d, height = %d", CID(context), - GLenumToString(GLESEnum::RenderbufferTarget, target), - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height); + ANGLE_UNSAFE_TODO( + EVENT(context, GLRenderbufferStorageOES, + "context = %d, target = %s, internalformat = %s, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::RenderbufferTarget, target), + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateRenderbufferStorageOES(context, angle::EntryPoint::GLRenderbufferStorageOES, - target, internalformat, width, height)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateRenderbufferStorageOES( + context, angle::EntryPoint::GLRenderbufferStorageOES, target, internalformat, + width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLRenderbufferStorageOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->renderbufferStorage(target, internalformat, width, height); } @@ -12596,7 +18281,7 @@ void GL_APIENTRY GL_RenderbufferStorageOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLRenderbufferStorageOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12609,20 +18294,41 @@ void GL_APIENTRY GL_FramebufferTextureOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTextureOES, - "context = %d, target = %s, attachment = %s, texture = %u, level = %d", CID(context), - GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, level); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTextureOES, + "context = %d, target = %s, attachment = %s, texture = %u, level = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, + level)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateFramebufferTextureOES(context, angle::EntryPoint::GLFramebufferTextureOES, - target, attachment, texturePacked, level)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().geometryShaderOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTextureOES( + context, angle::EntryPoint::GLFramebufferTextureOES, target, attachment, + texturePacked, level); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferTextureOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexture(target, attachment, texturePacked, level); } @@ -12631,7 +18337,7 @@ void GL_APIENTRY GL_FramebufferTextureOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLFramebufferTextureOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12645,21 +18351,37 @@ void GL_APIENTRY GL_GetProgramBinaryOES(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetProgramBinaryOES, - "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR - ", binaryFormat = 0x%016" PRIxPTR ", binary = 0x%016" PRIxPTR "", - CID(context), program, bufSize, (uintptr_t)length, (uintptr_t)binaryFormat, - (uintptr_t)binary); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetProgramBinaryOES, + "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR + ", binaryFormat = 0x%016" PRIxPTR ", binary = 0x%016" PRIxPTR "", + CID(context), program, bufSize, (uintptr_t)length, + (uintptr_t)binaryFormat, (uintptr_t)binary)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetProgramBinaryOES(context, angle::EntryPoint::GLGetProgramBinaryOES, - programPacked, bufSize, length, binaryFormat, binary)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getProgramBinaryOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetProgramBinaryOES( + context, angle::EntryPoint::GLGetProgramBinaryOES, programPacked, bufSize, + length, binaryFormat, binary); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetProgramBinaryOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getProgramBinary(programPacked, bufSize, length, binaryFormat, binary); } @@ -12668,7 +18390,7 @@ void GL_APIENTRY GL_GetProgramBinaryOES(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetProgramBinaryOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12680,23 +18402,37 @@ void GL_APIENTRY GL_ProgramBinaryOES(GLuint program, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLProgramBinaryOES, - "context = %d, program = %u, binaryFormat = %s, binary = 0x%016" PRIxPTR ", length = %d", - CID(context), program, GLenumToString(GLESEnum::AllEnums, binaryFormat), - (uintptr_t)binary, length); + ANGLE_UNSAFE_TODO(EVENT(context, GLProgramBinaryOES, + "context = %d, program = %u, binaryFormat = %s, binary = 0x%016" PRIxPTR + ", length = %d", + CID(context), program, GLenumToString(GLESEnum::AllEnums, binaryFormat), + (uintptr_t)binary, length)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { ShaderProgramID programPacked = PackParam(program); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLProgramBinaryOES) && - ValidateProgramBinaryOES(context, angle::EntryPoint::GLProgramBinaryOES, - programPacked, binaryFormat, binary, length))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().getProgramBinaryOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateProgramBinaryOES(context, angle::EntryPoint::GLProgramBinaryOES, + programPacked, binaryFormat, binary, length); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLProgramBinaryOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->programBinary(programPacked, binaryFormat, binary, length); } @@ -12705,7 +18441,7 @@ void GL_APIENTRY GL_ProgramBinaryOES(GLuint program, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLProgramBinaryOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12717,20 +18453,36 @@ void GL_APIENTRY GL_GetBufferPointervOES(GLenum target, GLenum pname, void **par { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetBufferPointervOES, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetBufferPointervOES, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + GLenumToString(GLESEnum::AllEnums, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetBufferPointervOES(context, angle::EntryPoint::GLGetBufferPointervOES, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().mapbufferOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = + ValidateGetBufferPointervOES(context, angle::EntryPoint::GLGetBufferPointervOES, + targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetBufferPointervOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getBufferPointerv(targetPacked, pname, params); } @@ -12738,7 +18490,7 @@ void GL_APIENTRY GL_GetBufferPointervOES(GLenum target, GLenum pname, void **par } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetBufferPointervOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12747,23 +18499,35 @@ void *GL_APIENTRY GL_MapBufferOES(GLenum target, GLenum access) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMapBufferOES, "context = %d, target = %s, access = %s", CID(context), - GLenumToString(GLESEnum::BufferTargetARB, target), - GLenumToString(GLESEnum::BufferAccessARB, access)); + ANGLE_UNSAFE_TODO(EVENT(context, GLMapBufferOES, "context = %d, target = %s, access = %s", + CID(context), GLenumToString(GLESEnum::BufferTargetARB, target), + GLenumToString(GLESEnum::BufferAccessARB, access))); void *returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMapBufferOES) && - ValidateMapBufferOES(context, angle::EntryPoint::GLMapBufferOES, targetPacked, - access))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().mapbufferOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMapBufferOES(context, angle::EntryPoint::GLMapBufferOES, + targetPacked, access); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMapBufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->mapBuffer(targetPacked, access); } @@ -12775,7 +18539,7 @@ void *GL_APIENTRY GL_MapBufferOES(GLenum target, GLenum access) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMapBufferOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -12786,21 +18550,34 @@ GLboolean GL_APIENTRY GL_UnmapBufferOES(GLenum target) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLUnmapBufferOES, "context = %d, target = %s", CID(context), - GLenumToString(GLESEnum::AllEnums, target)); + ANGLE_UNSAFE_TODO(EVENT(context, GLUnmapBufferOES, "context = %d, target = %s", CID(context), + GLenumToString(GLESEnum::AllEnums, target))); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { BufferBinding targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLUnmapBufferOES) && - ValidateUnmapBufferOES(context, angle::EntryPoint::GLUnmapBufferOES, targetPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().mapbufferOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateUnmapBufferOES(context, angle::EntryPoint::GLUnmapBufferOES, + targetPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLUnmapBufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->unmapBuffer(targetPacked); } @@ -12812,7 +18589,7 @@ GLboolean GL_APIENTRY GL_UnmapBufferOES(GLenum target) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLUnmapBufferOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -12824,17 +18601,33 @@ void GL_APIENTRY GL_CurrentPaletteMatrixOES(GLuint matrixpaletteindex) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCurrentPaletteMatrixOES, "context = %d, matrixpaletteindex = %u", CID(context), - matrixpaletteindex); + ANGLE_UNSAFE_TODO(EVENT(context, GLCurrentPaletteMatrixOES, + "context = %d, matrixpaletteindex = %u", CID(context), + matrixpaletteindex)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateCurrentPaletteMatrixOES(context, angle::EntryPoint::GLCurrentPaletteMatrixOES, - matrixpaletteindex)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().matrixPaletteOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCurrentPaletteMatrixOES( + context, angle::EntryPoint::GLCurrentPaletteMatrixOES, matrixpaletteindex); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCurrentPaletteMatrixOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->currentPaletteMatrix(matrixpaletteindex); } @@ -12842,7 +18635,8 @@ void GL_APIENTRY GL_CurrentPaletteMatrixOES(GLuint matrixpaletteindex) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCurrentPaletteMatrixOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12851,15 +18645,33 @@ void GL_APIENTRY GL_LoadPaletteFromModelViewMatrixOES() { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLLoadPaletteFromModelViewMatrixOES, "context = %d", CID(context)); + ANGLE_UNSAFE_TODO( + EVENT(context, GLLoadPaletteFromModelViewMatrixOES, "context = %d", CID(context))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateLoadPaletteFromModelViewMatrixOES( - context, angle::EntryPoint::GLLoadPaletteFromModelViewMatrixOES)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().matrixPaletteOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateLoadPaletteFromModelViewMatrixOES( + context, angle::EntryPoint::GLLoadPaletteFromModelViewMatrixOES); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLLoadPaletteFromModelViewMatrixOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->loadPaletteFromModelViewMatrix(); } @@ -12867,7 +18679,8 @@ void GL_APIENTRY GL_LoadPaletteFromModelViewMatrixOES() } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLLoadPaletteFromModelViewMatrixOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12879,18 +18692,35 @@ void GL_APIENTRY GL_MatrixIndexPointerOES(GLint size, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMatrixIndexPointerOES, - "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", - CID(context), size, GLenumToString(GLESEnum::AllEnums, type), stride, (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT( + context, GLMatrixIndexPointerOES, + "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), size, GLenumToString(GLESEnum::AllEnums, type), stride, (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateMatrixIndexPointerOES(context, angle::EntryPoint::GLMatrixIndexPointerOES, - size, type, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().matrixPaletteOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMatrixIndexPointerOES( + context, angle::EntryPoint::GLMatrixIndexPointerOES, size, type, stride, + pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMatrixIndexPointerOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->matrixIndexPointer(size, type, stride, pointer); } @@ -12898,7 +18728,7 @@ void GL_APIENTRY GL_MatrixIndexPointerOES(GLint size, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMatrixIndexPointerOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12907,17 +18737,34 @@ void GL_APIENTRY GL_WeightPointerOES(GLint size, GLenum type, GLsizei stride, co { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLWeightPointerOES, - "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", - CID(context), size, GLenumToString(GLESEnum::AllEnums, type), stride, (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT( + context, GLWeightPointerOES, + "context = %d, size = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), size, GLenumToString(GLESEnum::AllEnums, type), stride, (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateWeightPointerOES(context, angle::EntryPoint::GLWeightPointerOES, - size, type, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().matrixPaletteOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateWeightPointerOES( + context, angle::EntryPoint::GLWeightPointerOES, size, type, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLWeightPointerOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->weightPointer(size, type, stride, pointer); } @@ -12925,7 +18772,7 @@ void GL_APIENTRY GL_WeightPointerOES(GLint size, GLenum type, GLsizei stride, co } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLWeightPointerOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12937,19 +18784,35 @@ void GL_APIENTRY GL_PointSizePointerOES(GLenum type, GLsizei stride, const void { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPointSizePointerOES, - "context = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::AllEnums, type), stride, (uintptr_t)pointer); + ANGLE_UNSAFE_TODO(EVENT(context, GLPointSizePointerOES, + "context = %d, type = %s, stride = %d, pointer = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::AllEnums, type), stride, + (uintptr_t)pointer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexAttribType typePacked = PackParam(type); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidatePointSizePointerOES(context, angle::EntryPoint::GLPointSizePointerOES, - typePacked, stride, pointer)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().pointSizeArrayOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePointSizePointerOES( + context, angle::EntryPoint::GLPointSizePointerOES, typePacked, stride, pointer); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPointSizePointerOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->pointSizePointer(typePacked, stride, pointer); } @@ -12957,7 +18820,7 @@ void GL_APIENTRY GL_PointSizePointerOES(GLenum type, GLsizei stride, const void } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPointSizePointerOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -12976,23 +18839,35 @@ void GL_APIENTRY GL_PrimitiveBoundingBoxOES(GLfloat minX, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPrimitiveBoundingBoxOES, - "context = %d, minX = %f, minY = %f, minZ = %f, minW = %f, maxX = %f, maxY = %f, maxZ = " - "%f, maxW = %f", - CID(context), minX, minY, minZ, minW, maxX, maxY, maxZ, maxW); + ANGLE_UNSAFE_TODO(EVENT(context, GLPrimitiveBoundingBoxOES, + "context = %d, minX = %f, minY = %f, minZ = %f, minW = %f, maxX = %f, " + "maxY = %f, maxZ = %f, maxW = %f", + CID(context), minX, minY, minZ, minW, maxX, maxY, maxZ, maxW)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPrimitiveBoundingBoxOES) && - ValidatePrimitiveBoundingBoxOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPrimitiveBoundingBoxOES, minX, - minY, minZ, minW, maxX, maxY, maxZ, maxW))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().primitiveBoundingBoxOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePrimitiveBoundingBoxOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPrimitiveBoundingBoxOES, minX, minY, minZ, minW, maxX, + maxY, maxZ, maxW); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPrimitiveBoundingBoxOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePrimitiveBoundingBox(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), minX, minY, @@ -13003,7 +18878,8 @@ void GL_APIENTRY GL_PrimitiveBoundingBoxOES(GLfloat minX, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLPrimitiveBoundingBoxOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13013,18 +18889,35 @@ GLbitfield GL_APIENTRY GL_QueryMatrixxOES(GLfixed *mantissa, GLint *exponent) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLQueryMatrixxOES, - "context = %d, mantissa = 0x%016" PRIxPTR ", exponent = 0x%016" PRIxPTR "", CID(context), - (uintptr_t)mantissa, (uintptr_t)exponent); + ANGLE_UNSAFE_TODO(EVENT(context, GLQueryMatrixxOES, + "context = %d, mantissa = 0x%016" PRIxPTR ", exponent = 0x%016" PRIxPTR + "", + CID(context), (uintptr_t)mantissa, (uintptr_t)exponent)); GLbitfield returnValue; - if (context) - { - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateQueryMatrixxOES(context, angle::EntryPoint::GLQueryMatrixxOES, - mantissa, exponent)); - if (isCallValid) + if (ANGLE_LIKELY(context != nullptr)) + { + SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().queryMatrixOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateQueryMatrixxOES(context, angle::EntryPoint::GLQueryMatrixxOES, + mantissa, exponent); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLQueryMatrixxOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { returnValue = context->queryMatrixx(mantissa, exponent); } @@ -13036,7 +18929,7 @@ GLbitfield GL_APIENTRY GL_QueryMatrixxOES(GLfixed *mantissa, GLint *exponent) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLQueryMatrixxOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -13052,19 +18945,32 @@ void GL_APIENTRY GL_MinSampleShadingOES(GLfloat value) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLMinSampleShadingOES, "context = %d, value = %f", CID(context), value); + ANGLE_UNSAFE_TODO( + EVENT(context, GLMinSampleShadingOES, "context = %d, value = %f", CID(context), value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMinSampleShadingOES) && - ValidateMinSampleShadingOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLMinSampleShadingOES, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().sampleShadingOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateMinSampleShadingOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLMinSampleShadingOES, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLMinSampleShadingOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivateMinSampleShading(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), value); @@ -13073,7 +18979,7 @@ void GL_APIENTRY GL_MinSampleShadingOES(GLfloat value) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLMinSampleShadingOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13095,20 +19001,33 @@ void GL_APIENTRY GL_PatchParameteriOES(GLenum pname, GLint value) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLPatchParameteriOES, "context = %d, pname = %s, value = %d", CID(context), - GLenumToString(GLESEnum::PatchParameterName, pname), value); + ANGLE_UNSAFE_TODO(EVENT(context, GLPatchParameteriOES, "context = %d, pname = %s, value = %d", + CID(context), GLenumToString(GLESEnum::PatchParameterName, pname), + value)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPatchParameteriOES) && - ValidatePatchParameteriOES(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLPatchParameteriOES, pname, value))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().tessellationShaderOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidatePatchParameteriOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLPatchParameteriOES, pname, value); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLPatchParameteriOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { ContextPrivatePatchParameteri(context->getMutablePrivateState(), context->getMutablePrivateStateCache(), pname, value); @@ -13117,7 +19036,7 @@ void GL_APIENTRY GL_PatchParameteriOES(GLenum pname, GLint value) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLPatchParameteriOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13135,26 +19054,39 @@ void GL_APIENTRY GL_CompressedTexImage3DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexImage3DOES, - "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, border = %d, imageSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, depth, border, - imageSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO( + EVENT(context, GLCompressedTexImage3DOES, + "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = " + "%d, depth = %d, border = %d, imageSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, depth, + border, imageSize, (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexImage3DOES) && - ValidateCompressedTexImage3DOES(context, angle::EntryPoint::GLCompressedTexImage3DOES, - targetPacked, level, internalformat, width, height, - depth, border, imageSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().texture3DOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexImage3DOES( + context, angle::EntryPoint::GLCompressedTexImage3DOES, targetPacked, level, + internalformat, width, height, depth, border, imageSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCompressedTexImage3DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexImage3D(targetPacked, level, internalformat, width, height, depth, border, imageSize, data); @@ -13164,7 +19096,8 @@ void GL_APIENTRY GL_CompressedTexImage3DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexImage3DOES); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -13183,26 +19116,39 @@ void GL_APIENTRY GL_CompressedTexSubImage3DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCompressedTexSubImage3DOES, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width " - "= %d, height = %d, depth = %d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - zoffset, width, height, depth, GLenumToString(GLESEnum::InternalFormat, format), - imageSize, (uintptr_t)data); + ANGLE_UNSAFE_TODO(EVENT( + context, GLCompressedTexSubImage3DOES, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width = " + "%d, height = %d, depth = %d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, + zoffset, width, height, depth, GLenumToString(GLESEnum::InternalFormat, format), imageSize, + (uintptr_t)data)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCompressedTexSubImage3DOES) && - ValidateCompressedTexSubImage3DOES( - context, angle::EntryPoint::GLCompressedTexSubImage3DOES, targetPacked, level, - xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().texture3DOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCompressedTexSubImage3DOES( + context, angle::EntryPoint::GLCompressedTexSubImage3DOES, targetPacked, level, + xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCompressedTexSubImage3DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->compressedTexSubImage3D(targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); @@ -13212,7 +19158,8 @@ void GL_APIENTRY GL_CompressedTexSubImage3DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLCompressedTexSubImage3DOES); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -13229,25 +19176,41 @@ void GL_APIENTRY GL_CopyTexSubImage3DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLCopyTexSubImage3DOES, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, x = " - "%d, y = %d, width = %d, height = %d", - CID(context), GLenumToString(GLESEnum::AllEnums, target), level, xoffset, yoffset, - zoffset, x, y, width, height); + ANGLE_UNSAFE_TODO(EVENT(context, GLCopyTexSubImage3DOES, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, " + "zoffset = %d, x = %d, y = %d, width = %d, height = %d", + CID(context), GLenumToString(GLESEnum::AllEnums, target), level, + xoffset, yoffset, zoffset, x, y, width, height)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLCopyTexSubImage3DOES) && - ValidateCopyTexSubImage3DOES(context, angle::EntryPoint::GLCopyTexSubImage3DOES, - targetPacked, level, xoffset, yoffset, zoffset, x, y, - width, height))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().texture3DOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateCopyTexSubImage3DOES( + context, angle::EntryPoint::GLCopyTexSubImage3DOES, targetPacked, level, + xoffset, yoffset, zoffset, x, y, width, height); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLCopyTexSubImage3DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->copyTexSubImage3D(targetPacked, level, xoffset, yoffset, zoffset, x, y, width, height); @@ -13257,7 +19220,7 @@ void GL_APIENTRY GL_CopyTexSubImage3DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLCopyTexSubImage3DOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13271,23 +19234,44 @@ void GL_APIENTRY GL_FramebufferTexture3DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTexture3DOES, - "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d, " - "zoffset = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), - GLenumToString(GLESEnum::TextureTarget, textarget), texture, level, zoffset); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTexture3DOES, + "context = %d, target = %s, attachment = %s, textarget = %s, texture = " + "%u, level = %d, zoffset = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), + GLenumToString(GLESEnum::TextureTarget, textarget), texture, level, + zoffset)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget textargetPacked = PackParam(textarget); TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateFramebufferTexture3DOES( - context, angle::EntryPoint::GLFramebufferTexture3DOES, target, - attachment, textargetPacked, texturePacked, level, zoffset)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().texture3DOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTexture3DOES( + context, angle::EntryPoint::GLFramebufferTexture3DOES, target, attachment, + textargetPacked, texturePacked, level, zoffset); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLFramebufferTexture3DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTexture3D(target, attachment, textargetPacked, texturePacked, level, zoffset); @@ -13297,7 +19281,8 @@ void GL_APIENTRY GL_FramebufferTexture3DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTexture3DOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13315,27 +19300,40 @@ void GL_APIENTRY GL_TexImage3DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexImage3DOES, - "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, - GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, depth, border, - GLenumToString(GLESEnum::PixelFormat, format), GLenumToString(GLESEnum::PixelType, type), - (uintptr_t)pixels); + ANGLE_UNSAFE_TODO( + EVENT(context, GLTexImage3DOES, + "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = " + "%d, depth = %d, border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, + GLenumToString(GLESEnum::InternalFormat, internalformat), width, height, depth, + border, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexImage3DOES) && - ValidateTexImage3DOES(context, angle::EntryPoint::GLTexImage3DOES, targetPacked, - level, internalformat, width, height, depth, border, format, - type, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().texture3DOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexImage3DOES(context, angle::EntryPoint::GLTexImage3DOES, + targetPacked, level, internalformat, width, + height, depth, border, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexImage3DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texImage3D(targetPacked, level, internalformat, width, height, depth, border, format, type, pixels); @@ -13345,7 +19343,7 @@ void GL_APIENTRY GL_TexImage3DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexImage3DOES); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -13364,26 +19362,39 @@ void GL_APIENTRY GL_TexSubImage3DOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexSubImage3DOES, - "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width " - "= %d, height = %d, depth = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, - zoffset, width, height, depth, GLenumToString(GLESEnum::PixelFormat, format), - GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexSubImage3DOES, + "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, zoffset = %d, width = " + "%d, height = %d, depth = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), level, xoffset, yoffset, + zoffset, width, height, depth, GLenumToString(GLESEnum::PixelFormat, format), + GLenumToString(GLESEnum::PixelType, type), (uintptr_t)pixels)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureTarget targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexSubImage3DOES) && - ValidateTexSubImage3DOES(context, angle::EntryPoint::GLTexSubImage3DOES, targetPacked, - level, xoffset, yoffset, zoffset, width, height, depth, - format, type, pixels))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().texture3DOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexSubImage3DOES( + context, angle::EntryPoint::GLTexSubImage3DOES, targetPacked, level, xoffset, + yoffset, zoffset, width, height, depth, format, type, pixels); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexSubImage3DOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texSubImage3D(targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); @@ -13393,7 +19404,7 @@ void GL_APIENTRY GL_TexSubImage3DOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexSubImage3DOES); } egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr); } @@ -13403,19 +19414,36 @@ void GL_APIENTRY GL_GetSamplerParameterIivOES(GLuint sampler, GLenum pname, GLin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIivOES, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterIivOES, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterIivOES( - context, angle::EntryPoint::GLGetSamplerParameterIivOES, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIivOES( + context, angle::EntryPoint::GLGetSamplerParameterIivOES, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetSamplerParameterIivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIiv(samplerPacked, pname, params); } @@ -13424,7 +19452,8 @@ void GL_APIENTRY GL_GetSamplerParameterIivOES(GLuint sampler, GLenum pname, GLin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13433,19 +19462,36 @@ void GL_APIENTRY GL_GetSamplerParameterIuivOES(GLuint sampler, GLenum pname, GLu { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetSamplerParameterIuivOES, - "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetSamplerParameterIuivOES, + "context = %d, sampler = %u, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetSamplerParameterIuivOES( - context, angle::EntryPoint::GLGetSamplerParameterIuivOES, - samplerPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetSamplerParameterIuivOES( + context, angle::EntryPoint::GLGetSamplerParameterIuivOES, samplerPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetSamplerParameterIuivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getSamplerParameterIuiv(samplerPacked, pname, params); } @@ -13454,7 +19500,8 @@ void GL_APIENTRY GL_GetSamplerParameterIuivOES(GLuint sampler, GLenum pname, GLu } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLGetSamplerParameterIuivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13463,20 +19510,37 @@ void GL_APIENTRY GL_GetTexParameterIivOES(GLenum target, GLenum pname, GLint *pa { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIivOES, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterIivOES, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterIivOES(context, angle::EntryPoint::GLGetTexParameterIivOES, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIivOES( + context, angle::EntryPoint::GLGetTexParameterIivOES, targetPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexParameterIivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIiv(targetPacked, pname, params); } @@ -13484,7 +19548,7 @@ void GL_APIENTRY GL_GetTexParameterIivOES(GLenum target, GLenum pname, GLint *pa } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterIivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13493,20 +19557,37 @@ void GL_APIENTRY GL_GetTexParameterIuivOES(GLenum target, GLenum pname, GLuint * { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexParameterIuivOES, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::GetTextureParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexParameterIuivOES, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::GetTextureParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateGetTexParameterIuivOES(context, angle::EntryPoint::GLGetTexParameterIuivOES, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexParameterIuivOES( + context, angle::EntryPoint::GLGetTexParameterIuivOES, targetPacked, pname, + params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexParameterIuivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexParameterIuiv(targetPacked, pname, params); } @@ -13514,7 +19595,7 @@ void GL_APIENTRY GL_GetTexParameterIuivOES(GLenum target, GLenum pname, GLuint * } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexParameterIuivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13523,19 +19604,36 @@ void GL_APIENTRY GL_SamplerParameterIivOES(GLuint sampler, GLenum pname, const G { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIivOES, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterIivOES, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterIivOES(context, angle::EntryPoint::GLSamplerParameterIivOES, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIivOES( + context, angle::EntryPoint::GLSamplerParameterIivOES, samplerPacked, pname, + param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSamplerParameterIivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIiv(samplerPacked, pname, param); } @@ -13543,7 +19641,7 @@ void GL_APIENTRY GL_SamplerParameterIivOES(GLuint sampler, GLenum pname, const G } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLSamplerParameterIivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13552,19 +19650,36 @@ void GL_APIENTRY GL_SamplerParameterIuivOES(GLuint sampler, GLenum pname, const { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLSamplerParameterIuivOES, - "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", CID(context), - sampler, GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param); + ANGLE_UNSAFE_TODO(EVENT(context, GLSamplerParameterIuivOES, + "context = %d, sampler = %u, pname = %s, param = 0x%016" PRIxPTR "", + CID(context), sampler, + GLenumToString(GLESEnum::SamplerParameterI, pname), (uintptr_t)param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SamplerID samplerPacked = PackParam(sampler); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateSamplerParameterIuivOES(context, angle::EntryPoint::GLSamplerParameterIuivOES, - samplerPacked, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateSamplerParameterIuivOES( + context, angle::EntryPoint::GLSamplerParameterIuivOES, samplerPacked, pname, + param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLSamplerParameterIuivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->samplerParameterIuiv(samplerPacked, pname, param); } @@ -13573,7 +19688,8 @@ void GL_APIENTRY GL_SamplerParameterIuivOES(GLuint sampler, GLenum pname, const } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLSamplerParameterIuivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13582,20 +19698,36 @@ void GL_APIENTRY GL_TexParameterIivOES(GLenum target, GLenum pname, const GLint { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIivOES, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterIivOES, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexParameterIivOES(context, angle::EntryPoint::GLTexParameterIivOES, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIivOES( + context, angle::EntryPoint::GLTexParameterIivOES, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterIivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIiv(targetPacked, pname, params); } @@ -13603,7 +19735,7 @@ void GL_APIENTRY GL_TexParameterIivOES(GLenum target, GLenum pname, const GLint } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterIivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13612,20 +19744,36 @@ void GL_APIENTRY GL_TexParameterIuivOES(GLenum target, GLenum pname, const GLuin { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexParameterIuivOES, - "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::TextureParameterName, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexParameterIuivOES, + "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::TextureParameterName, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexParameterIuivOES(context, angle::EntryPoint::GLTexParameterIuivOES, - targetPacked, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBorderClampOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexParameterIuivOES( + context, angle::EntryPoint::GLTexParameterIuivOES, targetPacked, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexParameterIuivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texParameterIuiv(targetPacked, pname, params); } @@ -13633,7 +19781,7 @@ void GL_APIENTRY GL_TexParameterIuivOES(GLenum target, GLenum pname, const GLuin } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexParameterIuivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13643,23 +19791,36 @@ void GL_APIENTRY GL_TexBufferOES(GLenum target, GLenum internalformat, GLuint bu { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexBufferOES, "context = %d, target = %s, internalformat = %s, buffer = %u", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexBufferOES, + "context = %d, target = %s, internalformat = %s, buffer = %u", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexBufferOES) && - ValidateTexBufferOES(context, angle::EntryPoint::GLTexBufferOES, targetPacked, - internalformat, bufferPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBufferOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexBufferOES(context, angle::EntryPoint::GLTexBufferOES, + targetPacked, internalformat, bufferPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexBufferOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texBuffer(targetPacked, internalformat, bufferPacked); } @@ -13668,7 +19829,7 @@ void GL_APIENTRY GL_TexBufferOES(GLenum target, GLenum internalformat, GLuint bu } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexBufferOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13681,25 +19842,39 @@ void GL_APIENTRY GL_TexBufferRangeOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexBufferRangeOES, - "context = %d, target = %s, internalformat = %s, buffer = %u, offset = %llu, size = %llu", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer, - static_cast(offset), static_cast(size)); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexBufferRangeOES, + "context = %d, target = %s, internalformat = %s, buffer = %u, offset = %llu, size = %llu", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), buffer, + static_cast(offset), static_cast(size))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); BufferID bufferPacked = PackParam(buffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexBufferRangeOES) && - ValidateTexBufferRangeOES(context, angle::EntryPoint::GLTexBufferRangeOES, - targetPacked, internalformat, bufferPacked, offset, size))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureBufferOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexBufferRangeOES( + context, angle::EntryPoint::GLTexBufferRangeOES, targetPacked, internalformat, + bufferPacked, offset, size); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexBufferRangeOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texBufferRange(targetPacked, internalformat, bufferPacked, offset, size); } @@ -13708,7 +19883,7 @@ void GL_APIENTRY GL_TexBufferRangeOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexBufferRangeOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13720,18 +19895,35 @@ void GL_APIENTRY GL_GetTexGenfvOES(GLenum coord, GLenum pname, GLfloat *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexGenfvOES, - "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexGenfvOES, + "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexGenfvOES(context, angle::EntryPoint::GLGetTexGenfvOES, - coord, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexGenfvOES(context, angle::EntryPoint::GLGetTexGenfvOES, + coord, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexGenfvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexGenfv(coord, pname, params); } @@ -13739,7 +19931,7 @@ void GL_APIENTRY GL_GetTexGenfvOES(GLenum coord, GLenum pname, GLfloat *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexGenfvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13748,18 +19940,35 @@ void GL_APIENTRY GL_GetTexGenivOES(GLenum coord, GLenum pname, GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexGenivOES, - "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexGenivOES, + "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexGenivOES(context, angle::EntryPoint::GLGetTexGenivOES, - coord, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexGenivOES(context, angle::EntryPoint::GLGetTexGenivOES, + coord, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexGenivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexGeniv(coord, pname, params); } @@ -13767,7 +19976,7 @@ void GL_APIENTRY GL_GetTexGenivOES(GLenum coord, GLenum pname, GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexGenivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13776,18 +19985,35 @@ void GL_APIENTRY GL_GetTexGenxvOES(GLenum coord, GLenum pname, GLfixed *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGetTexGenxvOES, - "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT(context, GLGetTexGenxvOES, + "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), + (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGetTexGenxvOES(context, angle::EntryPoint::GLGetTexGenxvOES, - coord, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGetTexGenxvOES(context, angle::EntryPoint::GLGetTexGenxvOES, + coord, pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGetTexGenxvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->getTexGenxv(coord, pname, params); } @@ -13795,7 +20021,7 @@ void GL_APIENTRY GL_GetTexGenxvOES(GLenum coord, GLenum pname, GLfixed *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGetTexGenxvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13804,17 +20030,34 @@ void GL_APIENTRY GL_TexGenfOES(GLenum coord, GLenum pname, GLfloat param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexGenfOES, "context = %d, coord = %s, pname = %s, param = %f", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexGenfOES, + "context = %d, coord = %s, pname = %s, param = %f", CID(context), + GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexGenfOES(context, angle::EntryPoint::GLTexGenfOES, coord, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexGenfOES(context, angle::EntryPoint::GLTexGenfOES, coord, + pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexGenfOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texGenf(coord, pname, param); } @@ -13822,7 +20065,7 @@ void GL_APIENTRY GL_TexGenfOES(GLenum coord, GLenum pname, GLfloat param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexGenfOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13831,18 +20074,34 @@ void GL_APIENTRY GL_TexGenfvOES(GLenum coord, GLenum pname, const GLfloat *param { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexGenfvOES, - "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexGenfvOES, "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexGenfvOES(context, angle::EntryPoint::GLTexGenfvOES, coord, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexGenfvOES(context, angle::EntryPoint::GLTexGenfvOES, coord, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexGenfvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texGenfv(coord, pname, params); } @@ -13850,7 +20109,7 @@ void GL_APIENTRY GL_TexGenfvOES(GLenum coord, GLenum pname, const GLfloat *param } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexGenfvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13859,17 +20118,34 @@ void GL_APIENTRY GL_TexGeniOES(GLenum coord, GLenum pname, GLint param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexGeniOES, "context = %d, coord = %s, pname = %s, param = %d", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexGeniOES, + "context = %d, coord = %s, pname = %s, param = %d", CID(context), + GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexGeniOES(context, angle::EntryPoint::GLTexGeniOES, coord, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexGeniOES(context, angle::EntryPoint::GLTexGeniOES, coord, + pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexGeniOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texGeni(coord, pname, param); } @@ -13877,7 +20153,7 @@ void GL_APIENTRY GL_TexGeniOES(GLenum coord, GLenum pname, GLint param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexGeniOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13886,18 +20162,34 @@ void GL_APIENTRY GL_TexGenivOES(GLenum coord, GLenum pname, const GLint *params) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexGenivOES, - "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexGenivOES, "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexGenivOES(context, angle::EntryPoint::GLTexGenivOES, coord, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexGenivOES(context, angle::EntryPoint::GLTexGenivOES, coord, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexGenivOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texGeniv(coord, pname, params); } @@ -13905,7 +20197,7 @@ void GL_APIENTRY GL_TexGenivOES(GLenum coord, GLenum pname, const GLint *params) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexGenivOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13914,17 +20206,34 @@ void GL_APIENTRY GL_TexGenxOES(GLenum coord, GLenum pname, GLfixed param) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexGenxOES, "context = %d, coord = %s, pname = %s, param = 0x%X", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), param); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexGenxOES, + "context = %d, coord = %s, pname = %s, param = 0x%X", CID(context), + GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), param)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexGenxOES(context, angle::EntryPoint::GLTexGenxOES, coord, pname, param)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexGenxOES(context, angle::EntryPoint::GLTexGenxOES, coord, + pname, param); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexGenxOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texGenx(coord, pname, param); } @@ -13932,7 +20241,7 @@ void GL_APIENTRY GL_TexGenxOES(GLenum coord, GLenum pname, GLfixed param) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexGenxOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13941,18 +20250,34 @@ void GL_APIENTRY GL_TexGenxvOES(GLenum coord, GLenum pname, const GLfixed *param { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexGenxvOES, - "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context), - GLenumToString(GLESEnum::TextureCoordName, coord), - GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params); + ANGLE_UNSAFE_TODO(EVENT( + context, GLTexGenxvOES, "context = %d, coord = %s, pname = %s, params = 0x%016" PRIxPTR "", + CID(context), GLenumToString(GLESEnum::TextureCoordName, coord), + GLenumToString(GLESEnum::TextureGenParameter, pname), (uintptr_t)params)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateTexGenxvOES(context, angle::EntryPoint::GLTexGenxvOES, coord, pname, params)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureCubeMapOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexGenxvOES(context, angle::EntryPoint::GLTexGenxvOES, coord, + pname, params); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexGenxvOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texGenxv(coord, pname, params); } @@ -13960,7 +20285,7 @@ void GL_APIENTRY GL_TexGenxvOES(GLenum coord, GLenum pname, const GLfixed *param } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLTexGenxvOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -13992,26 +20317,38 @@ void GL_APIENTRY GL_TexStorage3DMultisampleOES(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTexStorage3DMultisampleOES, - "context = %d, target = %s, samples = %d, internalformat = %s, width = %d, height = %d, " - "depth = %d, fixedsamplelocations = %s", - CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, - GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, height, depth, - GLbooleanToString(fixedsamplelocations)); + ANGLE_UNSAFE_TODO(EVENT(context, GLTexStorage3DMultisampleOES, + "context = %d, target = %s, samples = %d, internalformat = %s, width = " + "%d, height = %d, depth = %d, fixedsamplelocations = %s", + CID(context), GLenumToString(GLESEnum::TextureTarget, target), samples, + GLenumToString(GLESEnum::SizedInternalFormat, internalformat), width, + height, depth, GLbooleanToString(fixedsamplelocations))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureType targetPacked = PackParam(target); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTexStorage3DMultisampleOES) && - ValidateTexStorage3DMultisampleOES( - context, angle::EntryPoint::GLTexStorage3DMultisampleOES, targetPacked, samples, - internalformat, width, height, depth, fixedsamplelocations))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureStorageMultisample2dArrayOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTexStorage3DMultisampleOES( + context, angle::EntryPoint::GLTexStorage3DMultisampleOES, targetPacked, samples, + internalformat, width, height, depth, fixedsamplelocations); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLTexStorage3DMultisampleOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->texStorage3DMultisample(targetPacked, samples, internalformat, width, height, depth, fixedsamplelocations); @@ -14021,7 +20358,8 @@ void GL_APIENTRY GL_TexStorage3DMultisampleOES(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTexStorage3DMultisampleOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14031,20 +20369,33 @@ void GL_APIENTRY GL_BindVertexArrayOES(GLuint array) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLBindVertexArrayOES, "context = %d, array = %u", CID(context), array); + ANGLE_UNSAFE_TODO( + EVENT(context, GLBindVertexArrayOES, "context = %d, array = %u", CID(context), array)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexArrayID arrayPacked = PackParam(array); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLBindVertexArrayOES) && - ValidateBindVertexArrayOES(context, angle::EntryPoint::GLBindVertexArrayOES, - arrayPacked))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().vertexArrayObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateBindVertexArrayOES( + context, angle::EntryPoint::GLBindVertexArrayOES, arrayPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLBindVertexArrayOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->bindVertexArray(arrayPacked); } @@ -14052,7 +20403,7 @@ void GL_APIENTRY GL_BindVertexArrayOES(GLuint array) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLBindVertexArrayOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14061,18 +20412,34 @@ void GL_APIENTRY GL_DeleteVertexArraysOES(GLsizei n, const GLuint *arrays) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLDeleteVertexArraysOES, "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)arrays); + ANGLE_UNSAFE_TODO(EVENT(context, GLDeleteVertexArraysOES, + "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)arrays)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { const VertexArrayID *arraysPacked = PackParam(arrays); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateDeleteVertexArraysOES(context, angle::EntryPoint::GLDeleteVertexArraysOES, n, - arraysPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().vertexArrayObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateDeleteVertexArraysOES( + context, angle::EntryPoint::GLDeleteVertexArraysOES, n, arraysPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLDeleteVertexArraysOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->deleteVertexArrays(n, arraysPacked); } @@ -14080,7 +20447,7 @@ void GL_APIENTRY GL_DeleteVertexArraysOES(GLsizei n, const GLuint *arrays) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLDeleteVertexArraysOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14089,17 +20456,34 @@ void GL_APIENTRY GL_GenVertexArraysOES(GLsizei n, GLuint *arrays) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLGenVertexArraysOES, "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", - CID(context), n, (uintptr_t)arrays); + ANGLE_UNSAFE_TODO(EVENT(context, GLGenVertexArraysOES, + "context = %d, n = %d, arrays = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)arrays)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexArrayID *arraysPacked = PackParam(arrays); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateGenVertexArraysOES( - context, angle::EntryPoint::GLGenVertexArraysOES, n, arraysPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().vertexArrayObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateGenVertexArraysOES( + context, angle::EntryPoint::GLGenVertexArraysOES, n, arraysPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLGenVertexArraysOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->genVertexArrays(n, arraysPacked); } @@ -14107,7 +20491,7 @@ void GL_APIENTRY GL_GenVertexArraysOES(GLsizei n, GLuint *arrays) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLGenVertexArraysOES); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14116,19 +20500,38 @@ GLboolean GL_APIENTRY GL_IsVertexArrayOES(GLuint array) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLIsVertexArrayOES, "context = %d, array = %u", CID(context), array); + ANGLE_UNSAFE_TODO( + EVENT(context, GLIsVertexArrayOES, "context = %d, array = %u", CID(context), array)); GLboolean returnValue; - if (context) + if (ANGLE_LIKELY(context != nullptr)) { VertexArrayID arrayPacked = PackParam(array); - SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - ValidateIsVertexArrayOES(context, angle::EntryPoint::GLIsVertexArrayOES, arrayPacked)); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().vertexArrayObjectOES)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateIsVertexArrayOES( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLIsVertexArrayOES, arrayPacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLIsVertexArrayOES); + } + } + if (ANGLE_LIKELY(isCallValid)) { - returnValue = context->isVertexArray(arrayPacked); + returnValue = + ContextPrivateIsVertexArray(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), arrayPacked); } else { @@ -14138,7 +20541,7 @@ GLboolean GL_APIENTRY GL_IsVertexArrayOES(GLuint array) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLIsVertexArrayOES); returnValue = GetDefaultReturnValue(); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); @@ -14159,22 +20562,43 @@ void GL_APIENTRY GL_FramebufferTextureMultiviewOVR(GLenum target, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferTextureMultiviewOVR, - "context = %d, target = %s, attachment = %s, texture = %u, level = %d, baseViewIndex = " - "%d, numViews = %d", - CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), - GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, level, - baseViewIndex, numViews); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTextureMultiviewOVR, + "context = %d, target = %s, attachment = %s, texture = %u, level = %d, " + "baseViewIndex = %d, numViews = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, + level, baseViewIndex, numViews)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateFramebufferTextureMultiviewOVR( - context, angle::EntryPoint::GLFramebufferTextureMultiviewOVR, - target, attachment, texturePacked, level, baseViewIndex, numViews)); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiviewOVR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTextureMultiviewOVR( + context, angle::EntryPoint::GLFramebufferTextureMultiviewOVR, target, + attachment, texturePacked, level, baseViewIndex, numViews); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLFramebufferTextureMultiviewOVR); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferTextureMultiview(target, attachment, texturePacked, level, baseViewIndex, numViews); @@ -14184,13 +20608,77 @@ void GL_APIENTRY GL_FramebufferTextureMultiviewOVR(GLenum target, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTextureMultiviewOVR); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } // GL_OVR_multiview2 +// GL_OVR_multiview_multisampled_render_to_texture +void GL_APIENTRY GL_FramebufferTextureMultisampleMultiviewOVR(GLenum target, + GLenum attachment, + GLuint texture, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews) +{ + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); + Context *context = GetValidGlobalContext(); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferTextureMultisampleMultiviewOVR, + "context = %d, target = %s, attachment = %s, texture = %u, level = %d, " + "samples = %d, baseViewIndex = %d, numViews = %d", + CID(context), GLenumToString(GLESEnum::FramebufferTarget, target), + GLenumToString(GLESEnum::FramebufferAttachment, attachment), texture, + level, samples, baseViewIndex, numViews)); + + if (ANGLE_LIKELY(context != nullptr)) + { + TextureID texturePacked = PackParam(texture); + SCOPED_SHARE_CONTEXT_LOCK(context); + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().multiviewMultisampledRenderToTextureOVR)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferTextureMultisampleMultiviewOVR( + context, angle::EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR, target, + attachment, texturePacked, level, samples, baseViewIndex, numViews); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT( + context, angle::EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR); + } + } + if (ANGLE_LIKELY(isCallValid)) + { + context->framebufferTextureMultisampleMultiview( + target, attachment, texturePacked, level, samples, baseViewIndex, numViews); + } + ANGLE_CAPTURE_GL(FramebufferTextureMultisampleMultiviewOVR, isCallValid, context, target, + attachment, texturePacked, level, samples, baseViewIndex, numViews); + } + else + { + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR); + } + ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); +} + // GL_QCOM_framebuffer_foveated void GL_APIENTRY GL_FramebufferFoveationConfigQCOM(GLuint framebuffer, GLuint numLayers, @@ -14200,25 +20688,38 @@ void GL_APIENTRY GL_FramebufferFoveationConfigQCOM(GLuint framebuffer, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferFoveationConfigQCOM, - "context = %d, framebuffer = %u, numLayers = %u, focalPointsPerLayer = %u, " - "requestedFeatures = %u, providedFeatures = 0x%016" PRIxPTR "", - CID(context), framebuffer, numLayers, focalPointsPerLayer, requestedFeatures, - (uintptr_t)providedFeatures); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferFoveationConfigQCOM, + "context = %d, framebuffer = %u, numLayers = %u, focalPointsPerLayer = " + "%u, requestedFeatures = %u, providedFeatures = 0x%016" PRIxPTR "", + CID(context), framebuffer, numLayers, focalPointsPerLayer, + requestedFeatures, (uintptr_t)providedFeatures)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID framebufferPacked = PackParam(framebuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferFoveationConfigQCOM) && - ValidateFramebufferFoveationConfigQCOM( - context, angle::EntryPoint::GLFramebufferFoveationConfigQCOM, framebufferPacked, - numLayers, focalPointsPerLayer, requestedFeatures, providedFeatures))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferFoveatedQCOM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferFoveationConfigQCOM( + context, angle::EntryPoint::GLFramebufferFoveationConfigQCOM, framebufferPacked, + numLayers, focalPointsPerLayer, requestedFeatures, providedFeatures); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLFramebufferFoveationConfigQCOM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferFoveationConfig(framebufferPacked, numLayers, focalPointsPerLayer, requestedFeatures, providedFeatures); @@ -14228,7 +20729,8 @@ void GL_APIENTRY GL_FramebufferFoveationConfigQCOM(GLuint framebuffer, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferFoveationConfigQCOM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14244,24 +20746,38 @@ void GL_APIENTRY GL_FramebufferFoveationParametersQCOM(GLuint framebuffer, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLFramebufferFoveationParametersQCOM, - "context = %d, framebuffer = %u, layer = %u, focalPoint = %u, focalX = %f, focalY = %f, " - "gainX = %f, gainY = %f, foveaArea = %f", - CID(context), framebuffer, layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea); + ANGLE_UNSAFE_TODO(EVENT(context, GLFramebufferFoveationParametersQCOM, + "context = %d, framebuffer = %u, layer = %u, focalPoint = %u, focalX = " + "%f, focalY = %f, gainX = %f, gainY = %f, foveaArea = %f", + CID(context), framebuffer, layer, focalPoint, focalX, focalY, gainX, + gainY, foveaArea)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { FramebufferID framebufferPacked = PackParam(framebuffer); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLFramebufferFoveationParametersQCOM) && - ValidateFramebufferFoveationParametersQCOM( - context, angle::EntryPoint::GLFramebufferFoveationParametersQCOM, - framebufferPacked, layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().framebufferFoveatedQCOM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateFramebufferFoveationParametersQCOM( + context, angle::EntryPoint::GLFramebufferFoveationParametersQCOM, + framebufferPacked, layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLFramebufferFoveationParametersQCOM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->framebufferFoveationParameters(framebufferPacked, layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea); @@ -14272,7 +20788,8 @@ void GL_APIENTRY GL_FramebufferFoveationParametersQCOM(GLuint framebuffer, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLFramebufferFoveationParametersQCOM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14284,29 +20801,42 @@ void GL_APIENTRY GL_ShadingRateQCOM(GLenum rate) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLShadingRateQCOM, "context = %d, rate = %s", CID(context), - GLenumToString(GLESEnum::ShadingRateQCOM, rate)); + ANGLE_UNSAFE_TODO(EVENT(context, GLShadingRateQCOM, "context = %d, rate = %s", CID(context), + GLenumToString(GLESEnum::ShadingRateQCOM, rate))); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLShadingRateQCOM) && - ValidateShadingRateQCOM(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLShadingRateQCOM, rate))); - if (isCallValid) + ShadingRate ratePacked = PackParam(rate); + bool isCallValid = context->skipValidation(); + if (!isCallValid) { - ContextPrivateShadingRate(context->getMutablePrivateState(), - context->getMutablePrivateStateCache(), rate); + if (ANGLE_LIKELY(context->getExtensions().shadingRateQCOM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateShadingRateQCOM( + context->getPrivateState(), context->getMutableErrorSetForValidation(), + angle::EntryPoint::GLShadingRateQCOM, ratePacked); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(isCallValid || context->getPushedErrorCount() != errorCount); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLShadingRateQCOM); + } } - ANGLE_CAPTURE_GL(ShadingRateQCOM, isCallValid, context, rate); + if (ANGLE_LIKELY(isCallValid)) + { + ContextPrivateShadingRateQCOM(context->getMutablePrivateState(), + context->getMutablePrivateStateCache(), ratePacked); + } + ANGLE_CAPTURE_GL(ShadingRateQCOM, isCallValid, context, ratePacked); } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLShadingRateQCOM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14323,24 +20853,38 @@ void GL_APIENTRY GL_TextureFoveationParametersQCOM(GLuint texture, { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLTextureFoveationParametersQCOM, - "context = %d, texture = %u, layer = %u, focalPoint = %u, focalX = %f, focalY = %f, " - "gainX = %f, gainY = %f, foveaArea = %f", - CID(context), texture, layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea); + ANGLE_UNSAFE_TODO(EVENT(context, GLTextureFoveationParametersQCOM, + "context = %d, texture = %u, layer = %u, focalPoint = %u, focalX = %f, " + "focalY = %f, gainX = %f, gainY = %f, foveaArea = %f", + CID(context), texture, layer, focalPoint, focalX, focalY, gainX, gainY, + foveaArea)); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { TextureID texturePacked = PackParam(texture); SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive( - context->getPrivateState(), context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLTextureFoveationParametersQCOM) && - ValidateTextureFoveationParametersQCOM( - context, angle::EntryPoint::GLTextureFoveationParametersQCOM, texturePacked, - layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().textureFoveatedQCOM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateTextureFoveationParametersQCOM( + context, angle::EntryPoint::GLTextureFoveationParametersQCOM, texturePacked, + layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, + angle::EntryPoint::GLTextureFoveationParametersQCOM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->textureFoveationParameters(texturePacked, layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea); @@ -14350,7 +20894,8 @@ void GL_APIENTRY GL_TextureFoveationParametersQCOM(GLuint texture, } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext( + angle::EntryPoint::GLTextureFoveationParametersQCOM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14360,19 +20905,33 @@ void GL_APIENTRY GL_EndTilingQCOM(GLbitfield preserveMask) { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLEndTilingQCOM, "context = %d, preserveMask = %s", CID(context), - GLbitfieldToString(GLESEnum::BufferBitQCOM, preserveMask).c_str()); + ANGLE_UNSAFE_TODO(EVENT(context, GLEndTilingQCOM, "context = %d, preserveMask = %s", + CID(context), + GLbitfieldToString(GLESEnum::BufferBitQCOM, preserveMask).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLEndTilingQCOM) && - ValidateEndTilingQCOM(context, angle::EntryPoint::GLEndTilingQCOM, preserveMask))); - if (isCallValid) + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().tiledRenderingQCOM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateEndTilingQCOM(context, angle::EntryPoint::GLEndTilingQCOM, + preserveMask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLEndTilingQCOM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->endTiling(preserveMask); } @@ -14380,7 +20939,7 @@ void GL_APIENTRY GL_EndTilingQCOM(GLbitfield preserveMask) } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLEndTilingQCOM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } @@ -14390,21 +20949,38 @@ GL_StartTilingQCOM(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield p { ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); Context *context = GetValidGlobalContext(); - EVENT(context, GLStartTilingQCOM, - "context = %d, x = %u, y = %u, width = %u, height = %u, preserveMask = %s", CID(context), - x, y, width, height, GLbitfieldToString(GLESEnum::BufferBitQCOM, preserveMask).c_str()); + ANGLE_UNSAFE_TODO(EVENT( + context, GLStartTilingQCOM, + "context = %d, x = %u, y = %u, width = %u, height = %u, preserveMask = %s", CID(context), x, + y, width, height, GLbitfieldToString(GLESEnum::BufferBitQCOM, preserveMask).c_str())); - if (context) + if (ANGLE_LIKELY(context != nullptr)) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = - (context->skipValidation() || - (ValidatePixelLocalStorageInactive(context->getPrivateState(), - context->getMutableErrorSetForValidation(), - angle::EntryPoint::GLStartTilingQCOM) && - ValidateStartTilingQCOM(context, angle::EntryPoint::GLStartTilingQCOM, x, y, width, - height, preserveMask))); - if (isCallValid) + if (context->getState().getPixelLocalStorageActivePlanes() != 0) + { + context->endPixelLocalStorageImplicit(); + } + bool isCallValid = context->skipValidation(); + if (!isCallValid) + { + if (ANGLE_LIKELY(context->getExtensions().tiledRenderingQCOM)) + { +#if defined(ANGLE_ENABLE_ASSERTS) + const uint32_t errorCount = context->getPushedErrorCount(); +#endif + isCallValid = ValidateStartTilingQCOM(context, angle::EntryPoint::GLStartTilingQCOM, + x, y, width, height, preserveMask); +#if defined(ANGLE_ENABLE_ASSERTS) + ASSERT(context->getPushedErrorCount() - errorCount == (isCallValid ? 0 : 1)); +#endif + } + else + { + RecordVersionErrorESEXT(context, angle::EntryPoint::GLStartTilingQCOM); + } + } + if (ANGLE_LIKELY(isCallValid)) { context->startTiling(x, y, width, height, preserveMask); } @@ -14412,7 +20988,7 @@ GL_StartTilingQCOM(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield p } else { - GenerateContextLostErrorOnCurrentGlobalContext(); + GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint::GLStartTilingQCOM); } ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any()); } diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.h b/src/libGLESv2/entry_points_gles_ext_autogen.h index f50c97ac7c4..842d61c2bbd 100644 --- a/src/libGLESv2/entry_points_gles_ext_autogen.h +++ b/src/libGLESv2/entry_points_gles_ext_autogen.h @@ -660,6 +660,18 @@ ANGLE_EXPORT void GL_APIENTRY GL_GetQueryObjectui64vRobustANGLE(GLuint id, GLsizei bufSize, GLsizei *length, GLuint64 *params); +ANGLE_EXPORT void GL_APIENTRY +GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE(GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params); +ANGLE_EXPORT void GL_APIENTRY +GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE(GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params); // GL_ANGLE_robust_fragment_shader_output @@ -696,18 +708,6 @@ ANGLE_EXPORT void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterfvANGLE ANGLE_EXPORT void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterivANGLE(GLint plane, GLenum pname, GLint *params); -ANGLE_EXPORT void GL_APIENTRY -GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE(GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params); -ANGLE_EXPORT void GL_APIENTRY -GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE(GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params); // GL_ANGLE_stencil_texturing @@ -756,14 +756,14 @@ ANGLE_EXPORT void GL_APIENTRY GL_ReleaseTexturesANGLE(GLuint numTextures, // GL_APPLE_clip_distance -// GL_ARB_sync - // GL_ARM_rgba8 // GL_ARM_shader_framebuffer_fetch // GL_ARM_shader_framebuffer_fetch_depth_stencil +// GL_ARM_texture_unnormalized_coordinates + // GL_CHROMIUM_bind_uniform_location ANGLE_EXPORT void GL_APIENTRY GL_BindUniformLocationCHROMIUM(GLuint program, GLint location, @@ -810,9 +810,6 @@ ANGLE_EXPORT void GL_APIENTRY GL_LoseContextCHROMIUM(GLenum current, GLenum othe ANGLE_EXPORT void GL_APIENTRY GL_EGLImageTargetTexStorageEXT(GLenum target, GLeglImageOES image, const GLint *attrib_list); -ANGLE_EXPORT void GL_APIENTRY GL_EGLImageTargetTextureStorageEXT(GLuint texture, - GLeglImageOES image, - const GLint *attrib_list); // GL_EXT_EGL_image_storage_compression @@ -983,20 +980,41 @@ ANGLE_EXPORT void GL_APIENTRY GL_MultiDrawElementsBaseVertexEXT(GLenum mode, GLsizei drawcount, const GLint *basevertex); +// GL_EXT_draw_instanced +ANGLE_EXPORT void GL_APIENTRY GL_DrawArraysInstancedEXT(GLenum mode, + GLint start, + GLsizei count, + GLsizei primcount); +ANGLE_EXPORT void GL_APIENTRY GL_DrawElementsInstancedEXT(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei primcount); + // GL_EXT_external_buffer ANGLE_EXPORT void GL_APIENTRY GL_BufferStorageExternalEXT(GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); -ANGLE_EXPORT void GL_APIENTRY GL_NamedBufferStorageExternalEXT(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags); // GL_EXT_float_blend +// GL_EXT_fragment_shading_rate +ANGLE_EXPORT void GL_APIENTRY GL_FramebufferShadingRateEXT(GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight); +ANGLE_EXPORT void GL_APIENTRY GL_GetFragmentShadingRatesEXT(GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates); +ANGLE_EXPORT void GL_APIENTRY GL_ShadingRateEXT(GLenum rate); +ANGLE_EXPORT void GL_APIENTRY GL_ShadingRateCombinerOpsEXT(GLenum combinerOp0, GLenum combinerOp1); + // GL_EXT_geometry_shader ANGLE_EXPORT void GL_APIENTRY GL_FramebufferTextureEXT(GLenum target, GLenum attachment, @@ -1006,15 +1024,6 @@ ANGLE_EXPORT void GL_APIENTRY GL_FramebufferTextureEXT(GLenum target, // GL_EXT_gpu_shader5 // GL_EXT_instanced_arrays -ANGLE_EXPORT void GL_APIENTRY GL_DrawArraysInstancedEXT(GLenum mode, - GLint start, - GLsizei count, - GLsizei primcount); -ANGLE_EXPORT void GL_APIENTRY GL_DrawElementsInstancedEXT(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei primcount); ANGLE_EXPORT void GL_APIENTRY GL_VertexAttribDivisorEXT(GLuint index, GLuint divisor); // GL_EXT_map_buffer_range @@ -1081,6 +1090,17 @@ ANGLE_EXPORT void GL_APIENTRY GL_ImportMemoryFdEXT(GLuint memory, GLenum handleType, GLint fd); +// GL_EXT_multi_draw_arrays +ANGLE_EXPORT void GL_APIENTRY GL_MultiDrawArraysEXT(GLenum mode, + const GLint *first, + const GLsizei *count, + GLsizei primcount); +ANGLE_EXPORT void GL_APIENTRY GL_MultiDrawElementsEXT(GLenum mode, + const GLsizei *count, + GLenum type, + const void *const *indices, + GLsizei primcount); + // GL_EXT_multi_draw_indirect ANGLE_EXPORT void GL_APIENTRY GL_MultiDrawArraysIndirectEXT(GLenum mode, const void *indirect, @@ -1190,7 +1210,7 @@ ANGLE_EXPORT void GL_APIENTRY GL_ActiveShaderProgramEXT(GLuint pipeline, GLuint ANGLE_EXPORT void GL_APIENTRY GL_BindProgramPipelineEXT(GLuint pipeline); ANGLE_EXPORT GLuint GL_APIENTRY GL_CreateShaderProgramvEXT(GLenum type, GLsizei count, - const GLchar **strings); + const GLchar *const *strings); ANGLE_EXPORT void GL_APIENTRY GL_DeleteProgramPipelinesEXT(GLsizei n, const GLuint *pipelines); ANGLE_EXPORT void GL_APIENTRY GL_GenProgramPipelinesEXT(GLsizei n, GLuint *pipelines); ANGLE_EXPORT void GL_APIENTRY GL_GetProgramPipelineInfoLogEXT(GLuint pipeline, @@ -1342,6 +1362,8 @@ ANGLE_EXPORT void GL_APIENTRY GL_FramebufferFetchBarrierEXT(); // GL_EXT_shader_texture_lod +// GL_EXT_shader_texture_samples + // GL_EXT_shadow_samplers // GL_EXT_tessellation_shader @@ -1418,10 +1440,6 @@ ANGLE_EXPORT void GL_APIENTRY GL_TexBufferRangeEXT(GLenum target, // GL_EXT_texture_shadow_lod // GL_EXT_texture_storage -ANGLE_EXPORT void GL_APIENTRY GL_TexStorage1DEXT(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width); ANGLE_EXPORT void GL_APIENTRY GL_TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, @@ -1573,6 +1591,8 @@ ANGLE_EXPORT void GL_APIENTRY GL_BlitFramebufferNV(GLint srcX0, GLbitfield mask, GLenum filter); +// GL_NV_pack_subimage + // GL_NV_pixel_buffer_object // GL_NV_polygon_mode @@ -1941,6 +1961,15 @@ ANGLE_EXPORT void GL_APIENTRY GL_FramebufferTextureMultiviewOVR(GLenum target, // GL_OVR_multiview2 +// GL_OVR_multiview_multisampled_render_to_texture +ANGLE_EXPORT void GL_APIENTRY GL_FramebufferTextureMultisampleMultiviewOVR(GLenum target, + GLenum attachment, + GLuint texture, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews); + // GL_QCOM_framebuffer_foveated ANGLE_EXPORT void GL_APIENTRY GL_FramebufferFoveationConfigQCOM(GLuint framebuffer, GLuint numLayers, diff --git a/src/libGLESv2/global_state.cpp b/src/libGLESv2/global_state.cpp index 9a6eef05355..0a248caa55a 100644 --- a/src/libGLESv2/global_state.cpp +++ b/src/libGLESv2/global_state.cpp @@ -86,9 +86,8 @@ Thread *AllocateCurrentThread() } // anonymous namespace #if defined(ANGLE_PLATFORM_APPLE) -// TODO(angleproject:6479): Due to a bug in Apple's dyld loader, `thread_local` will cause -// excessive memory use. Temporarily avoid it by using pthread's thread -// local storage instead. +// TODO(http://anglebug.com/42264979): Due to a bug in Apple's dyld loader, `thread_local` will +// cause excessive memory use. Temporarily avoid it by using pthread's thread local storage instead. // https://bugs.webkit.org/show_bug.cgi?id=228240 static angle::TLSIndex GetCurrentThreadTLSIndex() @@ -191,23 +190,19 @@ bool IsEGLValidationEnabled() namespace gl { -void GenerateContextLostErrorOnContext(Context *context) -{ - if (context && context->isContextLost()) - { - context->getMutableErrorSetForValidation()->validationError( - angle::EntryPoint::Invalid, GL_CONTEXT_LOST, err::kContextLost); - } -} - -void GenerateContextLostErrorOnCurrentGlobalContext() +void GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint entryPoint) { // If the client starts issuing GL calls before ANGLE has had a chance to initialize, // GenerateContextLostErrorOnCurrentGlobalContext can be called before AllocateCurrentThread has // had a chance to run. Calling GetCurrentThread() ensures that TLS thread state is set up. egl::GetCurrentThread(); - GenerateContextLostErrorOnContext(GetGlobalContext()); + Context *context = GetGlobalContext(); + if (context != nullptr && context->isContextLost()) + { + context->getMutableErrorSetForValidation()->validationError(entryPoint, GL_CONTEXT_LOST, + err::kContextLost); + } } } // namespace gl diff --git a/src/libGLESv2/global_state.h b/src/libGLESv2/global_state.h index 10e3bf955a4..32c9921d9bb 100644 --- a/src/libGLESv2/global_state.h +++ b/src/libGLESv2/global_state.h @@ -9,6 +9,10 @@ #ifndef LIBGLESV2_GLOBALSTATE_H_ #define LIBGLESV2_GLOBALSTATE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Context.h" #include "libANGLE/Debug.h" #include "libANGLE/Display.h" @@ -149,8 +153,7 @@ ANGLE_INLINE Context *GetValidGlobalContext() } // Generate a context lost error on the context if it is non-null and lost. -void GenerateContextLostErrorOnContext(Context *context); -void GenerateContextLostErrorOnCurrentGlobalContext(); +void GenerateContextLostErrorOnCurrentGlobalContext(angle::EntryPoint entryPoint); #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL) // TODO(b/177574181): This should be handled in a backend-specific way. diff --git a/src/libGLESv2/libGLESv2_autogen.cpp b/src/libGLESv2/libGLESv2_autogen.cpp index 76ced2d9916..6ba6a2b1521 100644 --- a/src/libGLESv2/libGLESv2_autogen.cpp +++ b/src/libGLESv2/libGLESv2_autogen.cpp @@ -3788,6 +3788,26 @@ void GL_APIENTRY glGetQueryObjectui64vRobustANGLE(GLuint id, return GL_GetQueryObjectui64vRobustANGLE(id, pname, bufSize, length, params); } +void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLfloat *params) +{ + return GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE(plane, pname, bufSize, length, + params); +} + +void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivRobustANGLE(GLint plane, + GLenum pname, + GLsizei bufSize, + GLsizei *length, + GLint *params) +{ + return GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE(plane, pname, bufSize, length, + params); +} + // GL_ANGLE_robust_fragment_shader_output // GL_ANGLE_robust_resource_initialization @@ -3870,25 +3890,6 @@ void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivANGLE(GLint plane, return GL_GetFramebufferPixelLocalStorageParameterivANGLE(plane, pname, params); } -void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLfloat *params) -{ - return GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE(plane, pname, bufSize, length, - params); -} - -void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivRobustANGLE(GLint plane, - GLenum pname, - GLsizei bufSize, - GLsizei *length, - GLint *params) -{ - return GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE(plane, pname, bufSize, length, - params); -} // GL_ANGLE_stencil_texturing @@ -3965,14 +3966,14 @@ void GL_APIENTRY glReleaseTexturesANGLE(GLuint numTextures, const GLuint *textur // GL_APPLE_clip_distance -// GL_ARB_sync - // GL_ARM_rgba8 // GL_ARM_shader_framebuffer_fetch // GL_ARM_shader_framebuffer_fetch_depth_stencil +// GL_ARM_texture_unnormalized_coordinates + // GL_CHROMIUM_bind_uniform_location void GL_APIENTRY glBindUniformLocationCHROMIUM(GLuint program, GLint location, const GLchar *name) { @@ -4044,12 +4045,6 @@ void GL_APIENTRY glEGLImageTargetTexStorageEXT(GLenum target, return GL_EGLImageTargetTexStorageEXT(target, image, attrib_list); } -void GL_APIENTRY glEGLImageTargetTextureStorageEXT(GLuint texture, - GLeglImageOES image, - const GLint *attrib_list) -{ - return GL_EGLImageTargetTextureStorageEXT(texture, image, attrib_list); -} // GL_EXT_EGL_image_storage_compression @@ -4373,6 +4368,24 @@ void GL_APIENTRY glMultiDrawElementsBaseVertexEXT(GLenum mode, return GL_MultiDrawElementsBaseVertexEXT(mode, count, type, indices, drawcount, basevertex); } +// GL_EXT_draw_instanced +void GL_APIENTRY glDrawArraysInstancedEXT(GLenum mode, + GLint start, + GLsizei count, + GLsizei primcount) +{ + return GL_DrawArraysInstancedEXT(mode, start, count, primcount); +} + +void GL_APIENTRY glDrawElementsInstancedEXT(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei primcount) +{ + return GL_DrawElementsInstancedEXT(mode, count, type, indices, primcount); +} + // GL_EXT_external_buffer void GL_APIENTRY glBufferStorageExternalEXT(GLenum target, GLintptr offset, @@ -4383,16 +4396,39 @@ void GL_APIENTRY glBufferStorageExternalEXT(GLenum target, return GL_BufferStorageExternalEXT(target, offset, size, clientBuffer, flags); } -void GL_APIENTRY glNamedBufferStorageExternalEXT(GLuint buffer, - GLintptr offset, - GLsizeiptr size, - GLeglClientBufferEXT clientBuffer, - GLbitfield flags) + +// GL_EXT_float_blend + +// GL_EXT_fragment_shading_rate +void GL_APIENTRY glFramebufferShadingRateEXT(GLenum target, + GLenum attachment, + GLuint texture, + GLint baseLayer, + GLsizei numLayers, + GLsizei texelWidth, + GLsizei texelHeight) { - return GL_NamedBufferStorageExternalEXT(buffer, offset, size, clientBuffer, flags); + return GL_FramebufferShadingRateEXT(target, attachment, texture, baseLayer, numLayers, + texelWidth, texelHeight); } -// GL_EXT_float_blend +void GL_APIENTRY glGetFragmentShadingRatesEXT(GLsizei samples, + GLsizei maxCount, + GLsizei *count, + GLenum *shadingRates) +{ + return GL_GetFragmentShadingRatesEXT(samples, maxCount, count, shadingRates); +} + +void GL_APIENTRY glShadingRateEXT(GLenum rate) +{ + return GL_ShadingRateEXT(rate); +} + +void GL_APIENTRY glShadingRateCombinerOpsEXT(GLenum combinerOp0, GLenum combinerOp1) +{ + return GL_ShadingRateCombinerOpsEXT(combinerOp0, combinerOp1); +} // GL_EXT_geometry_shader void GL_APIENTRY glFramebufferTextureEXT(GLenum target, @@ -4406,23 +4442,6 @@ void GL_APIENTRY glFramebufferTextureEXT(GLenum target, // GL_EXT_gpu_shader5 // GL_EXT_instanced_arrays -void GL_APIENTRY glDrawArraysInstancedEXT(GLenum mode, - GLint start, - GLsizei count, - GLsizei primcount) -{ - return GL_DrawArraysInstancedEXT(mode, start, count, primcount); -} - -void GL_APIENTRY glDrawElementsInstancedEXT(GLenum mode, - GLsizei count, - GLenum type, - const void *indices, - GLsizei primcount) -{ - return GL_DrawElementsInstancedEXT(mode, count, type, indices, primcount); -} - void GL_APIENTRY glVertexAttribDivisorEXT(GLuint index, GLuint divisor) { return GL_VertexAttribDivisorEXT(index, divisor); @@ -4545,6 +4564,24 @@ void GL_APIENTRY glImportMemoryFdEXT(GLuint memory, GLuint64 size, GLenum handle return GL_ImportMemoryFdEXT(memory, size, handleType, fd); } +// GL_EXT_multi_draw_arrays +void GL_APIENTRY glMultiDrawArraysEXT(GLenum mode, + const GLint *first, + const GLsizei *count, + GLsizei primcount) +{ + return GL_MultiDrawArraysEXT(mode, first, count, primcount); +} + +void GL_APIENTRY glMultiDrawElementsEXT(GLenum mode, + const GLsizei *count, + GLenum type, + const void *const *indices, + GLsizei primcount) +{ + return GL_MultiDrawElementsEXT(mode, count, type, indices, primcount); +} + // GL_EXT_multi_draw_indirect void GL_APIENTRY glMultiDrawArraysIndirectEXT(GLenum mode, const void *indirect, @@ -4719,7 +4756,9 @@ void GL_APIENTRY glBindProgramPipelineEXT(GLuint pipeline) return GL_BindProgramPipelineEXT(pipeline); } -GLuint GL_APIENTRY glCreateShaderProgramvEXT(GLenum type, GLsizei count, const GLchar **strings) +GLuint GL_APIENTRY glCreateShaderProgramvEXT(GLenum type, + GLsizei count, + const GLchar *const *strings) { return GL_CreateShaderProgramvEXT(type, count, strings); } @@ -5027,6 +5066,8 @@ void GL_APIENTRY glFramebufferFetchBarrierEXT() // GL_EXT_shader_texture_lod +// GL_EXT_shader_texture_samples + // GL_EXT_shadow_samplers // GL_EXT_tessellation_shader @@ -5130,14 +5171,6 @@ void GL_APIENTRY glTexBufferRangeEXT(GLenum target, // GL_EXT_texture_shadow_lod // GL_EXT_texture_storage -void GL_APIENTRY glTexStorage1DEXT(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width) -{ - return GL_TexStorage1DEXT(target, levels, internalformat, width); -} - void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, @@ -5398,6 +5431,8 @@ void GL_APIENTRY glBlitFramebufferNV(GLint srcX0, filter); } +// GL_NV_pack_subimage + // GL_NV_pixel_buffer_object // GL_NV_polygon_mode @@ -6060,6 +6095,19 @@ void GL_APIENTRY glFramebufferTextureMultiviewOVR(GLenum target, // GL_OVR_multiview2 +// GL_OVR_multiview_multisampled_render_to_texture +void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR(GLenum target, + GLenum attachment, + GLuint texture, + GLint level, + GLsizei samples, + GLint baseViewIndex, + GLsizei numViews) +{ + return GL_FramebufferTextureMultisampleMultiviewOVR(target, attachment, texture, level, samples, + baseViewIndex, numViews); +} + // GL_QCOM_framebuffer_foveated void GL_APIENTRY glFramebufferFoveationConfigQCOM(GLuint framebuffer, GLuint numLayers, diff --git a/src/libGLESv2/libGLESv2_autogen.def b/src/libGLESv2/libGLESv2_autogen.def index f637f2b1818..227accf39b2 100644 --- a/src/libGLESv2/libGLESv2_autogen.def +++ b/src/libGLESv2/libGLESv2_autogen.def @@ -575,6 +575,8 @@ EXPORTS glGetFloatvRobustANGLE glGetFramebufferAttachmentParameterivRobustANGLE glGetFramebufferParameterivRobustANGLE + glGetFramebufferPixelLocalStorageParameterfvRobustANGLE + glGetFramebufferPixelLocalStorageParameterivRobustANGLE glGetInteger64i_vRobustANGLE glGetInteger64vRobustANGLE glGetIntegeri_vRobustANGLE @@ -647,9 +649,7 @@ EXPORTS glFramebufferPixelLocalStorageRestoreANGLE glFramebufferTexturePixelLocalStorageANGLE glGetFramebufferPixelLocalStorageParameterfvANGLE - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE glGetFramebufferPixelLocalStorageParameterivANGLE - glGetFramebufferPixelLocalStorageParameterivRobustANGLE glPixelLocalStorageBarrierANGLE ; GL_ANGLE_stencil_texturing @@ -680,14 +680,14 @@ EXPORTS ; GL_APPLE_clip_distance - ; GL_ARB_sync - ; GL_ARM_rgba8 ; GL_ARM_shader_framebuffer_fetch ; GL_ARM_shader_framebuffer_fetch_depth_stencil + ; GL_ARM_texture_unnormalized_coordinates + ; GL_CHROMIUM_bind_uniform_location glBindUniformLocationCHROMIUM @@ -708,7 +708,6 @@ EXPORTS ; GL_EXT_EGL_image_storage glEGLImageTargetTexStorageEXT - glEGLImageTargetTextureStorageEXT ; GL_EXT_EGL_image_storage_compression @@ -795,20 +794,27 @@ EXPORTS glDrawRangeElementsBaseVertexEXT glMultiDrawElementsBaseVertexEXT + ; GL_EXT_draw_instanced + glDrawArraysInstancedEXT + glDrawElementsInstancedEXT + ; GL_EXT_external_buffer glBufferStorageExternalEXT - glNamedBufferStorageExternalEXT ; GL_EXT_float_blend + ; GL_EXT_fragment_shading_rate + glFramebufferShadingRateEXT + glGetFragmentShadingRatesEXT + glShadingRateCombinerOpsEXT + glShadingRateEXT + ; GL_EXT_geometry_shader glFramebufferTextureEXT ; GL_EXT_gpu_shader5 ; GL_EXT_instanced_arrays - glDrawArraysInstancedEXT - glDrawElementsInstancedEXT glVertexAttribDivisorEXT ; GL_EXT_map_buffer_range @@ -832,6 +838,10 @@ EXPORTS ; GL_EXT_memory_object_fd glImportMemoryFdEXT + ; GL_EXT_multi_draw_arrays + glMultiDrawArraysEXT + glMultiDrawElementsEXT + ; GL_EXT_multi_draw_indirect glMultiDrawArraysIndirectEXT glMultiDrawElementsIndirectEXT @@ -939,6 +949,8 @@ EXPORTS ; GL_EXT_shader_texture_lod + ; GL_EXT_shader_texture_samples + ; GL_EXT_shadow_samplers ; GL_EXT_tessellation_shader @@ -997,7 +1009,6 @@ EXPORTS ; GL_EXT_texture_shadow_lod ; GL_EXT_texture_storage - glTexStorage1DEXT glTexStorage2DEXT glTexStorage3DEXT @@ -1067,6 +1078,8 @@ EXPORTS ; GL_NV_framebuffer_blit glBlitFramebufferNV + ; GL_NV_pack_subimage + ; GL_NV_pixel_buffer_object ; GL_NV_polygon_mode @@ -1276,6 +1289,9 @@ EXPORTS ; GL_OVR_multiview2 + ; GL_OVR_multiview_multisampled_render_to_texture + glFramebufferTextureMultisampleMultiviewOVR + ; GL_QCOM_framebuffer_foveated glFramebufferFoveationConfigQCOM glFramebufferFoveationParametersQCOM @@ -1412,9 +1428,6 @@ EXPORTS EGL_CreateStreamProducerD3DTextureANGLE EGL_StreamPostD3DTextureANGLE - ; EGL_ANGLE_swap_with_frame_token - EGL_SwapBuffersWithFrameTokenANGLE - ; EGL_ANGLE_sync_control_rate EGL_GetMscRateANGLE diff --git a/src/libGLESv2/libGLESv2_no_capture_autogen.def b/src/libGLESv2/libGLESv2_no_capture_autogen.def index 5c850d96382..f68878ce0f6 100644 --- a/src/libGLESv2/libGLESv2_no_capture_autogen.def +++ b/src/libGLESv2/libGLESv2_no_capture_autogen.def @@ -575,6 +575,8 @@ EXPORTS glGetFloatvRobustANGLE glGetFramebufferAttachmentParameterivRobustANGLE glGetFramebufferParameterivRobustANGLE + glGetFramebufferPixelLocalStorageParameterfvRobustANGLE + glGetFramebufferPixelLocalStorageParameterivRobustANGLE glGetInteger64i_vRobustANGLE glGetInteger64vRobustANGLE glGetIntegeri_vRobustANGLE @@ -647,9 +649,7 @@ EXPORTS glFramebufferPixelLocalStorageRestoreANGLE glFramebufferTexturePixelLocalStorageANGLE glGetFramebufferPixelLocalStorageParameterfvANGLE - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE glGetFramebufferPixelLocalStorageParameterivANGLE - glGetFramebufferPixelLocalStorageParameterivRobustANGLE glPixelLocalStorageBarrierANGLE ; GL_ANGLE_stencil_texturing @@ -680,14 +680,14 @@ EXPORTS ; GL_APPLE_clip_distance - ; GL_ARB_sync - ; GL_ARM_rgba8 ; GL_ARM_shader_framebuffer_fetch ; GL_ARM_shader_framebuffer_fetch_depth_stencil + ; GL_ARM_texture_unnormalized_coordinates + ; GL_CHROMIUM_bind_uniform_location glBindUniformLocationCHROMIUM @@ -708,7 +708,6 @@ EXPORTS ; GL_EXT_EGL_image_storage glEGLImageTargetTexStorageEXT - glEGLImageTargetTextureStorageEXT ; GL_EXT_EGL_image_storage_compression @@ -795,20 +794,27 @@ EXPORTS glDrawRangeElementsBaseVertexEXT glMultiDrawElementsBaseVertexEXT + ; GL_EXT_draw_instanced + glDrawArraysInstancedEXT + glDrawElementsInstancedEXT + ; GL_EXT_external_buffer glBufferStorageExternalEXT - glNamedBufferStorageExternalEXT ; GL_EXT_float_blend + ; GL_EXT_fragment_shading_rate + glFramebufferShadingRateEXT + glGetFragmentShadingRatesEXT + glShadingRateCombinerOpsEXT + glShadingRateEXT + ; GL_EXT_geometry_shader glFramebufferTextureEXT ; GL_EXT_gpu_shader5 ; GL_EXT_instanced_arrays - glDrawArraysInstancedEXT - glDrawElementsInstancedEXT glVertexAttribDivisorEXT ; GL_EXT_map_buffer_range @@ -832,6 +838,10 @@ EXPORTS ; GL_EXT_memory_object_fd glImportMemoryFdEXT + ; GL_EXT_multi_draw_arrays + glMultiDrawArraysEXT + glMultiDrawElementsEXT + ; GL_EXT_multi_draw_indirect glMultiDrawArraysIndirectEXT glMultiDrawElementsIndirectEXT @@ -939,6 +949,8 @@ EXPORTS ; GL_EXT_shader_texture_lod + ; GL_EXT_shader_texture_samples + ; GL_EXT_shadow_samplers ; GL_EXT_tessellation_shader @@ -997,7 +1009,6 @@ EXPORTS ; GL_EXT_texture_shadow_lod ; GL_EXT_texture_storage - glTexStorage1DEXT glTexStorage2DEXT glTexStorage3DEXT @@ -1067,6 +1078,8 @@ EXPORTS ; GL_NV_framebuffer_blit glBlitFramebufferNV + ; GL_NV_pack_subimage + ; GL_NV_pixel_buffer_object ; GL_NV_polygon_mode @@ -1276,6 +1289,9 @@ EXPORTS ; GL_OVR_multiview2 + ; GL_OVR_multiview_multisampled_render_to_texture + glFramebufferTextureMultisampleMultiviewOVR + ; GL_QCOM_framebuffer_foveated glFramebufferFoveationConfigQCOM glFramebufferFoveationParametersQCOM @@ -1412,9 +1428,6 @@ EXPORTS EGL_CreateStreamProducerD3DTextureANGLE EGL_StreamPostD3DTextureANGLE - ; EGL_ANGLE_swap_with_frame_token - EGL_SwapBuffersWithFrameTokenANGLE - ; EGL_ANGLE_sync_control_rate EGL_GetMscRateANGLE diff --git a/src/libGLESv2/libGLESv2_vulkan_secondaries_autogen.def b/src/libGLESv2/libGLESv2_vulkan_secondaries_autogen.def index 379e81a7094..b2b425b1282 100644 --- a/src/libGLESv2/libGLESv2_vulkan_secondaries_autogen.def +++ b/src/libGLESv2/libGLESv2_vulkan_secondaries_autogen.def @@ -575,6 +575,8 @@ EXPORTS glGetFloatvRobustANGLE glGetFramebufferAttachmentParameterivRobustANGLE glGetFramebufferParameterivRobustANGLE + glGetFramebufferPixelLocalStorageParameterfvRobustANGLE + glGetFramebufferPixelLocalStorageParameterivRobustANGLE glGetInteger64i_vRobustANGLE glGetInteger64vRobustANGLE glGetIntegeri_vRobustANGLE @@ -647,9 +649,7 @@ EXPORTS glFramebufferPixelLocalStorageRestoreANGLE glFramebufferTexturePixelLocalStorageANGLE glGetFramebufferPixelLocalStorageParameterfvANGLE - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE glGetFramebufferPixelLocalStorageParameterivANGLE - glGetFramebufferPixelLocalStorageParameterivRobustANGLE glPixelLocalStorageBarrierANGLE ; GL_ANGLE_stencil_texturing @@ -680,14 +680,14 @@ EXPORTS ; GL_APPLE_clip_distance - ; GL_ARB_sync - ; GL_ARM_rgba8 ; GL_ARM_shader_framebuffer_fetch ; GL_ARM_shader_framebuffer_fetch_depth_stencil + ; GL_ARM_texture_unnormalized_coordinates + ; GL_CHROMIUM_bind_uniform_location glBindUniformLocationCHROMIUM @@ -708,7 +708,6 @@ EXPORTS ; GL_EXT_EGL_image_storage glEGLImageTargetTexStorageEXT - glEGLImageTargetTextureStorageEXT ; GL_EXT_EGL_image_storage_compression @@ -795,20 +794,27 @@ EXPORTS glDrawRangeElementsBaseVertexEXT glMultiDrawElementsBaseVertexEXT + ; GL_EXT_draw_instanced + glDrawArraysInstancedEXT + glDrawElementsInstancedEXT + ; GL_EXT_external_buffer glBufferStorageExternalEXT - glNamedBufferStorageExternalEXT ; GL_EXT_float_blend + ; GL_EXT_fragment_shading_rate + glFramebufferShadingRateEXT + glGetFragmentShadingRatesEXT + glShadingRateCombinerOpsEXT + glShadingRateEXT + ; GL_EXT_geometry_shader glFramebufferTextureEXT ; GL_EXT_gpu_shader5 ; GL_EXT_instanced_arrays - glDrawArraysInstancedEXT - glDrawElementsInstancedEXT glVertexAttribDivisorEXT ; GL_EXT_map_buffer_range @@ -832,6 +838,10 @@ EXPORTS ; GL_EXT_memory_object_fd glImportMemoryFdEXT + ; GL_EXT_multi_draw_arrays + glMultiDrawArraysEXT + glMultiDrawElementsEXT + ; GL_EXT_multi_draw_indirect glMultiDrawArraysIndirectEXT glMultiDrawElementsIndirectEXT @@ -939,6 +949,8 @@ EXPORTS ; GL_EXT_shader_texture_lod + ; GL_EXT_shader_texture_samples + ; GL_EXT_shadow_samplers ; GL_EXT_tessellation_shader @@ -997,7 +1009,6 @@ EXPORTS ; GL_EXT_texture_shadow_lod ; GL_EXT_texture_storage - glTexStorage1DEXT glTexStorage2DEXT glTexStorage3DEXT @@ -1067,6 +1078,8 @@ EXPORTS ; GL_NV_framebuffer_blit glBlitFramebufferNV + ; GL_NV_pack_subimage + ; GL_NV_pixel_buffer_object ; GL_NV_polygon_mode @@ -1276,6 +1289,9 @@ EXPORTS ; GL_OVR_multiview2 + ; GL_OVR_multiview_multisampled_render_to_texture + glFramebufferTextureMultisampleMultiviewOVR + ; GL_QCOM_framebuffer_foveated glFramebufferFoveationConfigQCOM glFramebufferFoveationParametersQCOM @@ -1412,9 +1428,6 @@ EXPORTS EGL_CreateStreamProducerD3DTextureANGLE EGL_StreamPostD3DTextureANGLE - ; EGL_ANGLE_swap_with_frame_token - EGL_SwapBuffersWithFrameTokenANGLE - ; EGL_ANGLE_sync_control_rate EGL_GetMscRateANGLE diff --git a/src/libGLESv2/libGLESv2_with_capture_autogen.def b/src/libGLESv2/libGLESv2_with_capture_autogen.def index 4e329ce76aa..946c9639451 100644 --- a/src/libGLESv2/libGLESv2_with_capture_autogen.def +++ b/src/libGLESv2/libGLESv2_with_capture_autogen.def @@ -575,6 +575,8 @@ EXPORTS glGetFloatvRobustANGLE glGetFramebufferAttachmentParameterivRobustANGLE glGetFramebufferParameterivRobustANGLE + glGetFramebufferPixelLocalStorageParameterfvRobustANGLE + glGetFramebufferPixelLocalStorageParameterivRobustANGLE glGetInteger64i_vRobustANGLE glGetInteger64vRobustANGLE glGetIntegeri_vRobustANGLE @@ -647,9 +649,7 @@ EXPORTS glFramebufferPixelLocalStorageRestoreANGLE glFramebufferTexturePixelLocalStorageANGLE glGetFramebufferPixelLocalStorageParameterfvANGLE - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE glGetFramebufferPixelLocalStorageParameterivANGLE - glGetFramebufferPixelLocalStorageParameterivRobustANGLE glPixelLocalStorageBarrierANGLE ; GL_ANGLE_stencil_texturing @@ -680,14 +680,14 @@ EXPORTS ; GL_APPLE_clip_distance - ; GL_ARB_sync - ; GL_ARM_rgba8 ; GL_ARM_shader_framebuffer_fetch ; GL_ARM_shader_framebuffer_fetch_depth_stencil + ; GL_ARM_texture_unnormalized_coordinates + ; GL_CHROMIUM_bind_uniform_location glBindUniformLocationCHROMIUM @@ -708,7 +708,6 @@ EXPORTS ; GL_EXT_EGL_image_storage glEGLImageTargetTexStorageEXT - glEGLImageTargetTextureStorageEXT ; GL_EXT_EGL_image_storage_compression @@ -795,20 +794,27 @@ EXPORTS glDrawRangeElementsBaseVertexEXT glMultiDrawElementsBaseVertexEXT + ; GL_EXT_draw_instanced + glDrawArraysInstancedEXT + glDrawElementsInstancedEXT + ; GL_EXT_external_buffer glBufferStorageExternalEXT - glNamedBufferStorageExternalEXT ; GL_EXT_float_blend + ; GL_EXT_fragment_shading_rate + glFramebufferShadingRateEXT + glGetFragmentShadingRatesEXT + glShadingRateCombinerOpsEXT + glShadingRateEXT + ; GL_EXT_geometry_shader glFramebufferTextureEXT ; GL_EXT_gpu_shader5 ; GL_EXT_instanced_arrays - glDrawArraysInstancedEXT - glDrawElementsInstancedEXT glVertexAttribDivisorEXT ; GL_EXT_map_buffer_range @@ -832,6 +838,10 @@ EXPORTS ; GL_EXT_memory_object_fd glImportMemoryFdEXT + ; GL_EXT_multi_draw_arrays + glMultiDrawArraysEXT + glMultiDrawElementsEXT + ; GL_EXT_multi_draw_indirect glMultiDrawArraysIndirectEXT glMultiDrawElementsIndirectEXT @@ -939,6 +949,8 @@ EXPORTS ; GL_EXT_shader_texture_lod + ; GL_EXT_shader_texture_samples + ; GL_EXT_shadow_samplers ; GL_EXT_tessellation_shader @@ -997,7 +1009,6 @@ EXPORTS ; GL_EXT_texture_shadow_lod ; GL_EXT_texture_storage - glTexStorage1DEXT glTexStorage2DEXT glTexStorage3DEXT @@ -1067,6 +1078,8 @@ EXPORTS ; GL_NV_framebuffer_blit glBlitFramebufferNV + ; GL_NV_pack_subimage + ; GL_NV_pixel_buffer_object ; GL_NV_polygon_mode @@ -1276,6 +1289,9 @@ EXPORTS ; GL_OVR_multiview2 + ; GL_OVR_multiview_multisampled_render_to_texture + glFramebufferTextureMultisampleMultiviewOVR + ; GL_QCOM_framebuffer_foveated glFramebufferFoveationConfigQCOM glFramebufferFoveationParametersQCOM @@ -1412,9 +1428,6 @@ EXPORTS EGL_CreateStreamProducerD3DTextureANGLE EGL_StreamPostD3DTextureANGLE - ; EGL_ANGLE_swap_with_frame_token - EGL_SwapBuffersWithFrameTokenANGLE - ; EGL_ANGLE_sync_control_rate EGL_GetMscRateANGLE diff --git a/src/libGLESv2/opengl32_autogen.def b/src/libGLESv2/opengl32_autogen.def deleted file mode 100644 index a3d951ba0ee..00000000000 --- a/src/libGLESv2/opengl32_autogen.def +++ /dev/null @@ -1,1278 +0,0 @@ -; GENERATED FILE - DO NOT EDIT. -; Generated by generate_entry_points.py using data from Khronos and ANGLE XML files. -; -; Copyright 2020 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. -LIBRARY opengl32 -EXPORTS - - ; OpenGL ES 2.0 - glActiveTexture - glAttachShader - glBindAttribLocation - glBindBuffer - glBindFramebuffer - glBindRenderbuffer - glBindTexture - glBlendColor - glBlendEquation - glBlendEquationSeparate - glBlendFunc - glBlendFuncSeparate - glBufferData - glBufferSubData - glCheckFramebufferStatus - glClear - glClearColor - glClearDepthf - glClearStencil - glColorMask - glCompileShader - glCompressedTexImage2D - glCompressedTexSubImage2D - glCopyTexImage2D - glCopyTexSubImage2D - glCreateProgram - glCreateShader - glCullFace - glDeleteBuffers - glDeleteFramebuffers - glDeleteProgram - glDeleteRenderbuffers - glDeleteShader - glDeleteTextures - glDepthFunc - glDepthMask - glDepthRangef - glDetachShader - glDisable - glDisableVertexAttribArray - glDrawArrays - glDrawElements - glEnable - glEnableVertexAttribArray - glFinish - glFlush - glFramebufferRenderbuffer - glFramebufferTexture2D - glFrontFace - glGenBuffers - glGenFramebuffers - glGenRenderbuffers - glGenTextures - glGenerateMipmap - glGetActiveAttrib - glGetActiveUniform - glGetAttachedShaders - glGetAttribLocation - glGetBooleanv - glGetBufferParameteriv - glGetError - glGetFloatv - glGetFramebufferAttachmentParameteriv - glGetIntegerv - glGetProgramInfoLog - glGetProgramiv - glGetRenderbufferParameteriv - glGetShaderInfoLog - glGetShaderPrecisionFormat - glGetShaderSource - glGetShaderiv - glGetString - glGetTexParameterfv - glGetTexParameteriv - glGetUniformLocation - glGetUniformfv - glGetUniformiv - glGetVertexAttribPointerv - glGetVertexAttribfv - glGetVertexAttribiv - glHint - glIsBuffer - glIsEnabled - glIsFramebuffer - glIsProgram - glIsRenderbuffer - glIsShader - glIsTexture - glLineWidth - glLinkProgram - glPixelStorei - glPolygonOffset - glReadPixels - glReleaseShaderCompiler - glRenderbufferStorage - glSampleCoverage - glScissor - glShaderBinary - glShaderSource - glStencilFunc - glStencilFuncSeparate - glStencilMask - glStencilMaskSeparate - glStencilOp - glStencilOpSeparate - glTexImage2D - glTexParameterf - glTexParameterfv - glTexParameteri - glTexParameteriv - glTexSubImage2D - glUniform1f - glUniform1fv - glUniform1i - glUniform1iv - glUniform2f - glUniform2fv - glUniform2i - glUniform2iv - glUniform3f - glUniform3fv - glUniform3i - glUniform3iv - glUniform4f - glUniform4fv - glUniform4i - glUniform4iv - glUniformMatrix2fv - glUniformMatrix3fv - glUniformMatrix4fv - glUseProgram - glValidateProgram - glVertexAttrib1f - glVertexAttrib1fv - glVertexAttrib2f - glVertexAttrib2fv - glVertexAttrib3f - glVertexAttrib3fv - glVertexAttrib4f - glVertexAttrib4fv - glVertexAttribPointer - glViewport - - ; OpenGL ES 3.0 - glBeginQuery - glBeginTransformFeedback - glBindBufferBase - glBindBufferRange - glBindSampler - glBindTransformFeedback - glBindVertexArray - glBlitFramebuffer - glClearBufferfi - glClearBufferfv - glClearBufferiv - glClearBufferuiv - glClientWaitSync - glCompressedTexImage3D - glCompressedTexSubImage3D - glCopyBufferSubData - glCopyTexSubImage3D - glDeleteQueries - glDeleteSamplers - glDeleteSync - glDeleteTransformFeedbacks - glDeleteVertexArrays - glDrawArraysInstanced - glDrawBuffers - glDrawElementsInstanced - glDrawRangeElements - glEndQuery - glEndTransformFeedback - glFenceSync - glFlushMappedBufferRange - glFramebufferTextureLayer - glGenQueries - glGenSamplers - glGenTransformFeedbacks - glGenVertexArrays - glGetActiveUniformBlockName - glGetActiveUniformBlockiv - glGetActiveUniformsiv - glGetBufferParameteri64v - glGetBufferPointerv - glGetFragDataLocation - glGetInteger64i_v - glGetInteger64v - glGetIntegeri_v - glGetInternalformativ - glGetProgramBinary - glGetQueryObjectuiv - glGetQueryiv - glGetSamplerParameterfv - glGetSamplerParameteriv - glGetStringi - glGetSynciv - glGetTransformFeedbackVarying - glGetUniformBlockIndex - glGetUniformIndices - glGetUniformuiv - glGetVertexAttribIiv - glGetVertexAttribIuiv - glInvalidateFramebuffer - glInvalidateSubFramebuffer - glIsQuery - glIsSampler - glIsSync - glIsTransformFeedback - glIsVertexArray - glMapBufferRange - glPauseTransformFeedback - glProgramBinary - glProgramParameteri - glReadBuffer - glRenderbufferStorageMultisample - glResumeTransformFeedback - glSamplerParameterf - glSamplerParameterfv - glSamplerParameteri - glSamplerParameteriv - glTexImage3D - glTexStorage2D - glTexStorage3D - glTexSubImage3D - glTransformFeedbackVaryings - glUniform1ui - glUniform1uiv - glUniform2ui - glUniform2uiv - glUniform3ui - glUniform3uiv - glUniform4ui - glUniform4uiv - glUniformBlockBinding - glUniformMatrix2x3fv - glUniformMatrix2x4fv - glUniformMatrix3x2fv - glUniformMatrix3x4fv - glUniformMatrix4x2fv - glUniformMatrix4x3fv - glUnmapBuffer - glVertexAttribDivisor - glVertexAttribI4i - glVertexAttribI4iv - glVertexAttribI4ui - glVertexAttribI4uiv - glVertexAttribIPointer - glWaitSync - - ; OpenGL ES 3.1 - glActiveShaderProgram - glBindImageTexture - glBindProgramPipeline - glBindVertexBuffer - glCreateShaderProgramv - glDeleteProgramPipelines - glDispatchCompute - glDispatchComputeIndirect - glDrawArraysIndirect - glDrawElementsIndirect - glFramebufferParameteri - glGenProgramPipelines - glGetBooleani_v - glGetFramebufferParameteriv - glGetMultisamplefv - glGetProgramInterfaceiv - glGetProgramPipelineInfoLog - glGetProgramPipelineiv - glGetProgramResourceIndex - glGetProgramResourceLocation - glGetProgramResourceName - glGetProgramResourceiv - glGetTexLevelParameterfv - glGetTexLevelParameteriv - glIsProgramPipeline - glMemoryBarrier - glMemoryBarrierByRegion - glProgramUniform1f - glProgramUniform1fv - glProgramUniform1i - glProgramUniform1iv - glProgramUniform1ui - glProgramUniform1uiv - glProgramUniform2f - glProgramUniform2fv - glProgramUniform2i - glProgramUniform2iv - glProgramUniform2ui - glProgramUniform2uiv - glProgramUniform3f - glProgramUniform3fv - glProgramUniform3i - glProgramUniform3iv - glProgramUniform3ui - glProgramUniform3uiv - glProgramUniform4f - glProgramUniform4fv - glProgramUniform4i - glProgramUniform4iv - glProgramUniform4ui - glProgramUniform4uiv - glProgramUniformMatrix2fv - glProgramUniformMatrix2x3fv - glProgramUniformMatrix2x4fv - glProgramUniformMatrix3fv - glProgramUniformMatrix3x2fv - glProgramUniformMatrix3x4fv - glProgramUniformMatrix4fv - glProgramUniformMatrix4x2fv - glProgramUniformMatrix4x3fv - glSampleMaski - glTexStorage2DMultisample - glUseProgramStages - glValidateProgramPipeline - glVertexAttribBinding - glVertexAttribFormat - glVertexAttribIFormat - glVertexBindingDivisor - - ; OpenGL ES 3.2 - glBlendBarrier - glBlendEquationSeparatei - glBlendEquationi - glBlendFuncSeparatei - glBlendFunci - glColorMaski - glCopyImageSubData - glDebugMessageCallback - glDebugMessageControl - glDebugMessageInsert - glDisablei - glDrawElementsBaseVertex - glDrawElementsInstancedBaseVertex - glDrawRangeElementsBaseVertex - glEnablei - glFramebufferTexture - glGetDebugMessageLog - glGetGraphicsResetStatus - glGetObjectLabel - glGetObjectPtrLabel - glGetPointerv - glGetSamplerParameterIiv - glGetSamplerParameterIuiv - glGetTexParameterIiv - glGetTexParameterIuiv - glGetnUniformfv - glGetnUniformiv - glGetnUniformuiv - glIsEnabledi - glMinSampleShading - glObjectLabel - glObjectPtrLabel - glPatchParameteri - glPopDebugGroup - glPrimitiveBoundingBox - glPushDebugGroup - glReadnPixels - glSamplerParameterIiv - glSamplerParameterIuiv - glTexBuffer - glTexBufferRange - glTexParameterIiv - glTexParameterIuiv - glTexStorage3DMultisample - - ; OpenGL ES 1.0 - glAlphaFunc - glAlphaFuncx - glClearColorx - glClearDepthx - glClientActiveTexture - glClipPlanef - glClipPlanex - glColor4f - glColor4ub - glColor4x - glColorPointer - glDepthRangex - glDisableClientState - glEnableClientState - glFogf - glFogfv - glFogx - glFogxv - glFrustumf - glFrustumx - glGetClipPlanef - glGetClipPlanex - glGetFixedv - glGetLightfv - glGetLightxv - glGetMaterialfv - glGetMaterialxv - glGetTexEnvfv - glGetTexEnviv - glGetTexEnvxv - glGetTexParameterxv - glLightModelf - glLightModelfv - glLightModelx - glLightModelxv - glLightf - glLightfv - glLightx - glLightxv - glLineWidthx - glLoadIdentity - glLoadMatrixf - glLoadMatrixx - glLogicOp - glMaterialf - glMaterialfv - glMaterialx - glMaterialxv - glMatrixMode - glMultMatrixf - glMultMatrixx - glMultiTexCoord4f - glMultiTexCoord4x - glNormal3f - glNormal3x - glNormalPointer - glOrthof - glOrthox - glPointParameterf - glPointParameterfv - glPointParameterx - glPointParameterxv - glPointSize - glPointSizex - glPolygonOffsetx - glPopMatrix - glPushMatrix - glRotatef - glRotatex - glSampleCoveragex - glScalef - glScalex - glShadeModel - glTexCoordPointer - glTexEnvf - glTexEnvfv - glTexEnvi - glTexEnviv - glTexEnvx - glTexEnvxv - glTexParameterx - glTexParameterxv - glTranslatef - glTranslatex - glVertexPointer - - ; GL_AMD_performance_monitor - glBeginPerfMonitorAMD - glDeletePerfMonitorsAMD - glEndPerfMonitorAMD - glGenPerfMonitorsAMD - glGetPerfMonitorCounterDataAMD - glGetPerfMonitorCounterInfoAMD - glGetPerfMonitorCounterStringAMD - glGetPerfMonitorCountersAMD - glGetPerfMonitorGroupStringAMD - glGetPerfMonitorGroupsAMD - glSelectPerfMonitorCountersAMD - - ; GL_ANDROID_extension_pack_es31a - - ; GL_ANGLE_base_vertex_base_instance - glDrawArraysInstancedBaseInstanceANGLE - glDrawElementsInstancedBaseVertexBaseInstanceANGLE - glMultiDrawArraysInstancedBaseInstanceANGLE - glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE - - ; GL_ANGLE_blob_cache - glBlobCacheCallbacksANGLE - glGetPointervANGLE - - ; GL_ANGLE_client_arrays - - ; GL_ANGLE_clip_cull_distance - - ; GL_ANGLE_copy_texture_3d - glCopySubTexture3DANGLE - glCopyTexture3DANGLE - - ; GL_ANGLE_depth_texture - - ; GL_ANGLE_framebuffer_blit - glBlitFramebufferANGLE - - ; GL_ANGLE_framebuffer_multisample - glRenderbufferStorageMultisampleANGLE - - ; GL_ANGLE_get_image - glGetCompressedTexImageANGLE - glGetRenderbufferImageANGLE - glGetTexImageANGLE - - ; GL_ANGLE_get_serialized_context_string - - ; GL_ANGLE_get_tex_level_parameter - glGetTexLevelParameterfvANGLE - glGetTexLevelParameterivANGLE - - ; GL_ANGLE_instanced_arrays - glDrawArraysInstancedANGLE - glDrawElementsInstancedANGLE - glVertexAttribDivisorANGLE - - ; GL_ANGLE_logic_op - glLogicOpANGLE - - ; GL_ANGLE_lossy_etc_decode - - ; GL_ANGLE_memory_object_flags - glTexStorageMemFlags2DANGLE - glTexStorageMemFlags2DMultisampleANGLE - glTexStorageMemFlags3DANGLE - glTexStorageMemFlags3DMultisampleANGLE - - ; GL_ANGLE_memory_object_fuchsia - glImportMemoryZirconHandleANGLE - - ; GL_ANGLE_memory_size - - ; GL_ANGLE_multi_draw - glMultiDrawArraysANGLE - glMultiDrawArraysInstancedANGLE - glMultiDrawElementsANGLE - glMultiDrawElementsInstancedANGLE - - ; GL_ANGLE_pack_reverse_row_order - - ; GL_ANGLE_polygon_mode - glPolygonModeANGLE - - ; GL_ANGLE_program_binary - - ; GL_ANGLE_program_binary_readiness_query - - ; GL_ANGLE_program_cache_control - - ; GL_ANGLE_provoking_vertex - glProvokingVertexANGLE - - ; GL_ANGLE_renderability_validation - - ; GL_ANGLE_request_extension - glDisableExtensionANGLE - glRequestExtensionANGLE - - ; GL_ANGLE_rgbx_internal_format - - ; GL_ANGLE_robust_client_memory - glCompressedTexImage2DRobustANGLE - glCompressedTexImage3DRobustANGLE - glCompressedTexSubImage2DRobustANGLE - glCompressedTexSubImage3DRobustANGLE - glGetActiveUniformBlockivRobustANGLE - glGetBooleani_vRobustANGLE - glGetBooleanvRobustANGLE - glGetBufferParameteri64vRobustANGLE - glGetBufferParameterivRobustANGLE - glGetBufferPointervRobustANGLE - glGetFloatvRobustANGLE - glGetFramebufferAttachmentParameterivRobustANGLE - glGetFramebufferParameterivRobustANGLE - glGetInteger64i_vRobustANGLE - glGetInteger64vRobustANGLE - glGetIntegeri_vRobustANGLE - glGetIntegervRobustANGLE - glGetInternalformativRobustANGLE - glGetMultisamplefvRobustANGLE - glGetPointervRobustANGLERobustANGLE - glGetProgramInterfaceivRobustANGLE - glGetProgramivRobustANGLE - glGetQueryObjecti64vRobustANGLE - glGetQueryObjectivRobustANGLE - glGetQueryObjectui64vRobustANGLE - glGetQueryObjectuivRobustANGLE - glGetQueryivRobustANGLE - glGetRenderbufferParameterivRobustANGLE - glGetSamplerParameterIivRobustANGLE - glGetSamplerParameterIuivRobustANGLE - glGetSamplerParameterfvRobustANGLE - glGetSamplerParameterivRobustANGLE - glGetShaderivRobustANGLE - glGetTexLevelParameterfvRobustANGLE - glGetTexLevelParameterivRobustANGLE - glGetTexParameterIivRobustANGLE - glGetTexParameterIuivRobustANGLE - glGetTexParameterfvRobustANGLE - glGetTexParameterivRobustANGLE - glGetUniformfvRobustANGLE - glGetUniformivRobustANGLE - glGetUniformuivRobustANGLE - glGetVertexAttribIivRobustANGLE - glGetVertexAttribIuivRobustANGLE - glGetVertexAttribPointervRobustANGLE - glGetVertexAttribfvRobustANGLE - glGetVertexAttribivRobustANGLE - glGetnUniformfvRobustANGLE - glGetnUniformivRobustANGLE - glGetnUniformuivRobustANGLE - glReadPixelsRobustANGLE - glReadnPixelsRobustANGLE - glSamplerParameterIivRobustANGLE - glSamplerParameterIuivRobustANGLE - glSamplerParameterfvRobustANGLE - glSamplerParameterivRobustANGLE - glTexImage2DRobustANGLE - glTexImage3DRobustANGLE - glTexParameterIivRobustANGLE - glTexParameterIuivRobustANGLE - glTexParameterfvRobustANGLE - glTexParameterivRobustANGLE - glTexSubImage2DRobustANGLE - glTexSubImage3DRobustANGLE - - ; GL_ANGLE_robust_fragment_shader_output - - ; GL_ANGLE_robust_resource_initialization - - ; GL_ANGLE_semaphore_fuchsia - glImportSemaphoreZirconHandleANGLE - - ; GL_ANGLE_shader_binary - - ; GL_ANGLE_shader_pixel_local_storage - glBeginPixelLocalStorageANGLE - glEndPixelLocalStorageANGLE - glFramebufferMemorylessPixelLocalStorageANGLE - glFramebufferPixelLocalClearValuefvANGLE - glFramebufferPixelLocalClearValueivANGLE - glFramebufferPixelLocalClearValueuivANGLE - glFramebufferPixelLocalStorageInterruptANGLE - glFramebufferPixelLocalStorageRestoreANGLE - glFramebufferTexturePixelLocalStorageANGLE - glGetFramebufferPixelLocalStorageParameterfvANGLE - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE - glGetFramebufferPixelLocalStorageParameterivANGLE - glGetFramebufferPixelLocalStorageParameterivRobustANGLE - glPixelLocalStorageBarrierANGLE - - ; GL_ANGLE_stencil_texturing - - ; GL_ANGLE_texture_compression_dxt3 - - ; GL_ANGLE_texture_compression_dxt5 - - ; GL_ANGLE_texture_external_update - glInvalidateTextureANGLE - glTexImage2DExternalANGLE - - ; GL_ANGLE_texture_multisample - glGetMultisamplefvANGLE - glSampleMaskiANGLE - glTexStorage2DMultisampleANGLE - - ; GL_ANGLE_texture_usage - - ; GL_ANGLE_translated_shader_source - glGetTranslatedShaderSourceANGLE - - ; GL_ANGLE_vulkan_image - glAcquireTexturesANGLE - glReleaseTexturesANGLE - - ; GL_ANGLE_yuv_internal_format - - ; GL_APPLE_clip_distance - - ; GL_ARB_sync - - ; GL_ARM_shader_framebuffer_fetch - - ; GL_CHROMIUM_bind_uniform_location - glBindUniformLocationCHROMIUM - - ; GL_CHROMIUM_copy_compressed_texture - glCompressedCopyTextureCHROMIUM - - ; GL_CHROMIUM_copy_texture - glCopySubTextureCHROMIUM - glCopyTextureCHROMIUM - - ; GL_CHROMIUM_framebuffer_mixed_samples - glCoverageModulationCHROMIUM - - ; GL_CHROMIUM_lose_context - glLoseContextCHROMIUM - - ; GL_EXT_EGL_image_array - - ; GL_EXT_EGL_image_storage - glEGLImageTargetTexStorageEXT - glEGLImageTargetTextureStorageEXT - - ; GL_EXT_YUV_target - - ; GL_EXT_base_instance - glDrawArraysInstancedBaseInstanceEXT - glDrawElementsInstancedBaseInstanceEXT - glDrawElementsInstancedBaseVertexBaseInstanceEXT - - ; GL_EXT_blend_func_extended - glBindFragDataLocationEXT - glBindFragDataLocationIndexedEXT - glGetFragDataIndexEXT - glGetProgramResourceLocationIndexEXT - - ; GL_EXT_blend_minmax - - ; GL_EXT_buffer_storage - glBufferStorageEXT - - ; GL_EXT_clear_texture - glClearTexImageEXT - glClearTexSubImageEXT - - ; GL_EXT_clip_control - glClipControlEXT - - ; GL_EXT_clip_cull_distance - - ; GL_EXT_color_buffer_float - - ; GL_EXT_color_buffer_half_float - - ; GL_EXT_conservative_depth - - ; GL_EXT_copy_image - glCopyImageSubDataEXT - - ; GL_EXT_debug_label - glGetObjectLabelEXT - glLabelObjectEXT - - ; GL_EXT_debug_marker - glInsertEventMarkerEXT - glPopGroupMarkerEXT - glPushGroupMarkerEXT - - ; GL_EXT_depth_clamp - - ; GL_EXT_discard_framebuffer - glDiscardFramebufferEXT - - ; GL_EXT_disjoint_timer_query - glBeginQueryEXT - glDeleteQueriesEXT - glEndQueryEXT - glGenQueriesEXT - glGetInteger64vEXT - glGetQueryObjecti64vEXT - glGetQueryObjectivEXT - glGetQueryObjectui64vEXT - glGetQueryObjectuivEXT - glGetQueryivEXT - glIsQueryEXT - glQueryCounterEXT - - ; GL_EXT_draw_buffers - glDrawBuffersEXT - - ; GL_EXT_draw_buffers_indexed - glBlendEquationSeparateiEXT - glBlendEquationiEXT - glBlendFuncSeparateiEXT - glBlendFunciEXT - glColorMaskiEXT - glDisableiEXT - glEnableiEXT - glIsEnablediEXT - - ; GL_EXT_draw_elements_base_vertex - glDrawElementsBaseVertexEXT - glDrawElementsInstancedBaseVertexEXT - glDrawRangeElementsBaseVertexEXT - glMultiDrawElementsBaseVertexEXT - - ; GL_EXT_external_buffer - glBufferStorageExternalEXT - glNamedBufferStorageExternalEXT - - ; GL_EXT_float_blend - - ; GL_EXT_geometry_shader - glFramebufferTextureEXT - - ; GL_EXT_gpu_shader5 - - ; GL_EXT_instanced_arrays - glDrawArraysInstancedEXT - glDrawElementsInstancedEXT - glVertexAttribDivisorEXT - - ; GL_EXT_map_buffer_range - glFlushMappedBufferRangeEXT - glMapBufferRangeEXT - - ; GL_EXT_memory_object - glBufferStorageMemEXT - glCreateMemoryObjectsEXT - glDeleteMemoryObjectsEXT - glGetMemoryObjectParameterivEXT - glGetUnsignedBytei_vEXT - glGetUnsignedBytevEXT - glIsMemoryObjectEXT - glMemoryObjectParameterivEXT - glTexStorageMem2DEXT - glTexStorageMem2DMultisampleEXT - glTexStorageMem3DEXT - glTexStorageMem3DMultisampleEXT - - ; GL_EXT_memory_object_fd - glImportMemoryFdEXT - - ; GL_EXT_multi_draw_indirect - glMultiDrawArraysIndirectEXT - glMultiDrawElementsIndirectEXT - - ; GL_EXT_multisampled_render_to_texture - glFramebufferTexture2DMultisampleEXT - glRenderbufferStorageMultisampleEXT - - ; GL_EXT_multisampled_render_to_texture2 - - ; GL_EXT_occlusion_query_boolean - - ; GL_EXT_polygon_offset_clamp - glPolygonOffsetClampEXT - - ; GL_EXT_primitive_bounding_box - glPrimitiveBoundingBoxEXT - - ; GL_EXT_protected_textures - - ; GL_EXT_pvrtc_sRGB - - ; GL_EXT_read_format_bgra - - ; GL_EXT_render_snorm - - ; GL_EXT_robustness - glGetGraphicsResetStatusEXT - glGetnUniformfvEXT - glGetnUniformivEXT - glReadnPixelsEXT - - ; GL_EXT_sRGB - - ; GL_EXT_sRGB_write_control - - ; GL_EXT_semaphore - glDeleteSemaphoresEXT - glGenSemaphoresEXT - glGetSemaphoreParameterui64vEXT - glIsSemaphoreEXT - glSemaphoreParameterui64vEXT - glSignalSemaphoreEXT - glWaitSemaphoreEXT - - ; GL_EXT_semaphore_fd - glImportSemaphoreFdEXT - - ; GL_EXT_separate_depth_stencil - - ; GL_EXT_separate_shader_objects - glActiveShaderProgramEXT - glBindProgramPipelineEXT - glCreateShaderProgramvEXT - glDeleteProgramPipelinesEXT - glGenProgramPipelinesEXT - glGetProgramPipelineInfoLogEXT - glGetProgramPipelineivEXT - glIsProgramPipelineEXT - glProgramParameteriEXT - glProgramUniform1fEXT - glProgramUniform1fvEXT - glProgramUniform1iEXT - glProgramUniform1ivEXT - glProgramUniform1uiEXT - glProgramUniform1uivEXT - glProgramUniform2fEXT - glProgramUniform2fvEXT - glProgramUniform2iEXT - glProgramUniform2ivEXT - glProgramUniform2uiEXT - glProgramUniform2uivEXT - glProgramUniform3fEXT - glProgramUniform3fvEXT - glProgramUniform3iEXT - glProgramUniform3ivEXT - glProgramUniform3uiEXT - glProgramUniform3uivEXT - glProgramUniform4fEXT - glProgramUniform4fvEXT - glProgramUniform4iEXT - glProgramUniform4ivEXT - glProgramUniform4uiEXT - glProgramUniform4uivEXT - glProgramUniformMatrix2fvEXT - glProgramUniformMatrix2x3fvEXT - glProgramUniformMatrix2x4fvEXT - glProgramUniformMatrix3fvEXT - glProgramUniformMatrix3x2fvEXT - glProgramUniformMatrix3x4fvEXT - glProgramUniformMatrix4fvEXT - glProgramUniformMatrix4x2fvEXT - glProgramUniformMatrix4x3fvEXT - glUseProgramStagesEXT - glValidateProgramPipelineEXT - - ; GL_EXT_shader_framebuffer_fetch - - ; GL_EXT_shader_framebuffer_fetch_non_coherent - glFramebufferFetchBarrierEXT - - ; GL_EXT_shader_io_blocks - - ; GL_EXT_shader_non_constant_global_initializers - - ; GL_EXT_shader_texture_lod - - ; GL_EXT_shadow_samplers - - ; GL_EXT_tessellation_shader - glPatchParameteriEXT - - ; GL_EXT_texture_border_clamp - glGetSamplerParameterIivEXT - glGetSamplerParameterIuivEXT - glGetTexParameterIivEXT - glGetTexParameterIuivEXT - glSamplerParameterIivEXT - glSamplerParameterIuivEXT - glTexParameterIivEXT - glTexParameterIuivEXT - - ; GL_EXT_texture_buffer - glTexBufferEXT - glTexBufferRangeEXT - - ; GL_EXT_texture_compression_astc_decode_mode - - ; GL_EXT_texture_compression_bptc - - ; GL_EXT_texture_compression_dxt1 - - ; GL_EXT_texture_compression_rgtc - - ; GL_EXT_texture_compression_s3tc - - ; GL_EXT_texture_compression_s3tc_srgb - - ; GL_EXT_texture_cube_map_array - - ; GL_EXT_texture_filter_anisotropic - - ; GL_EXT_texture_filter_minmax - - ; GL_EXT_texture_format_BGRA8888 - - ; GL_EXT_texture_format_sRGB_override - - ; GL_EXT_texture_mirror_clamp_to_edge - - ; GL_EXT_texture_norm16 - - ; GL_EXT_texture_rg - - ; GL_EXT_texture_sRGB_R8 - - ; GL_EXT_texture_sRGB_RG8 - - ; GL_EXT_texture_sRGB_decode - - ; GL_EXT_texture_shadow_lod - - ; GL_EXT_texture_storage - glTexStorage1DEXT - glTexStorage2DEXT - glTexStorage3DEXT - - ; GL_EXT_texture_storage_compression - glTexStorageAttribs2DEXT - glTexStorageAttribs3DEXT - - ; GL_EXT_texture_type_2_10_10_10_REV - - ; GL_EXT_unpack_subimage - - ; GL_IMG_texture_compression_pvrtc - - ; GL_IMG_texture_compression_pvrtc2 - - ; GL_KHR_blend_equation_advanced - glBlendBarrierKHR - - ; GL_KHR_blend_equation_advanced_coherent - - ; GL_KHR_debug - glDebugMessageCallbackKHR - glDebugMessageControlKHR - glDebugMessageInsertKHR - glGetDebugMessageLogKHR - glGetObjectLabelKHR - glGetObjectPtrLabelKHR - glGetPointervKHR - glObjectLabelKHR - glObjectPtrLabelKHR - glPopDebugGroupKHR - glPushDebugGroupKHR - - ; GL_KHR_no_error - - ; GL_KHR_parallel_shader_compile - glMaxShaderCompilerThreadsKHR - - ; GL_KHR_robust_buffer_access_behavior - - ; GL_KHR_robustness - glGetGraphicsResetStatusKHR - glGetnUniformfvKHR - glGetnUniformivKHR - glGetnUniformuivKHR - glReadnPixelsKHR - - ; GL_KHR_texture_compression_astc_hdr - - ; GL_KHR_texture_compression_astc_ldr - - ; GL_KHR_texture_compression_astc_sliced_3d - - ; GL_MESA_framebuffer_flip_y - glFramebufferParameteriMESA - glGetFramebufferParameterivMESA - - ; GL_NV_fence - glDeleteFencesNV - glFinishFenceNV - glGenFencesNV - glGetFenceivNV - glIsFenceNV - glSetFenceNV - glTestFenceNV - - ; GL_NV_framebuffer_blit - glBlitFramebufferNV - - ; GL_NV_pixel_buffer_object - - ; GL_NV_polygon_mode - glPolygonModeNV - - ; GL_NV_read_depth - - ; GL_NV_read_depth_stencil - - ; GL_NV_read_stencil - - ; GL_NV_robustness_video_memory_purge - - ; GL_NV_shader_noperspective_interpolation - - ; GL_OES_EGL_image - glEGLImageTargetRenderbufferStorageOES - glEGLImageTargetTexture2DOES - - ; GL_OES_EGL_image_external - - ; GL_OES_EGL_image_external_essl3 - - ; GL_OES_compressed_ETC1_RGB8_texture - - ; GL_OES_compressed_paletted_texture - - ; GL_OES_copy_image - glCopyImageSubDataOES - - ; GL_OES_depth24 - - ; GL_OES_depth32 - - ; GL_OES_depth_texture - - ; GL_OES_draw_buffers_indexed - glBlendEquationSeparateiOES - glBlendEquationiOES - glBlendFuncSeparateiOES - glBlendFunciOES - glColorMaskiOES - glDisableiOES - glEnableiOES - glIsEnablediOES - - ; GL_OES_draw_elements_base_vertex - glDrawElementsBaseVertexOES - glDrawElementsInstancedBaseVertexOES - glDrawRangeElementsBaseVertexOES - - ; GL_OES_draw_texture - glDrawTexfOES - glDrawTexfvOES - glDrawTexiOES - glDrawTexivOES - glDrawTexsOES - glDrawTexsvOES - glDrawTexxOES - glDrawTexxvOES - - ; GL_OES_element_index_uint - - ; GL_OES_fbo_render_mipmap - - ; GL_OES_framebuffer_object - glBindFramebufferOES - glBindRenderbufferOES - glCheckFramebufferStatusOES - glDeleteFramebuffersOES - glDeleteRenderbuffersOES - glFramebufferRenderbufferOES - glFramebufferTexture2DOES - glGenFramebuffersOES - glGenRenderbuffersOES - glGenerateMipmapOES - glGetFramebufferAttachmentParameterivOES - glGetRenderbufferParameterivOES - glIsFramebufferOES - glIsRenderbufferOES - glRenderbufferStorageOES - - ; GL_OES_geometry_shader - glFramebufferTextureOES - - ; GL_OES_get_program_binary - glGetProgramBinaryOES - glProgramBinaryOES - - ; GL_OES_gpu_shader5 - - ; GL_OES_mapbuffer - glGetBufferPointervOES - glMapBufferOES - glUnmapBufferOES - - ; GL_OES_matrix_palette - glCurrentPaletteMatrixOES - glLoadPaletteFromModelViewMatrixOES - glMatrixIndexPointerOES - glWeightPointerOES - - ; GL_OES_packed_depth_stencil - - ; GL_OES_point_size_array - glPointSizePointerOES - - ; GL_OES_point_sprite - - ; GL_OES_primitive_bounding_box - glPrimitiveBoundingBoxOES - - ; GL_OES_query_matrix - glQueryMatrixxOES - - ; GL_OES_rgb8_rgba8 - - ; GL_OES_sample_shading - glMinSampleShadingOES - - ; GL_OES_sample_variables - - ; GL_OES_shader_image_atomic - - ; GL_OES_shader_io_blocks - - ; GL_OES_shader_multisample_interpolation - - ; GL_OES_standard_derivatives - - ; GL_OES_surfaceless_context - - ; GL_OES_tessellation_shader - glPatchParameteriOES - - ; GL_OES_texture_3D - glCompressedTexImage3DOES - glCompressedTexSubImage3DOES - glCopyTexSubImage3DOES - glFramebufferTexture3DOES - glTexImage3DOES - glTexSubImage3DOES - - ; GL_OES_texture_border_clamp - glGetSamplerParameterIivOES - glGetSamplerParameterIuivOES - glGetTexParameterIivOES - glGetTexParameterIuivOES - glSamplerParameterIivOES - glSamplerParameterIuivOES - glTexParameterIivOES - glTexParameterIuivOES - - ; GL_OES_texture_buffer - glTexBufferOES - glTexBufferRangeOES - - ; GL_OES_texture_compression_astc - - ; GL_OES_texture_cube_map - glGetTexGenfvOES - glGetTexGenivOES - glGetTexGenxvOES - glTexGenfOES - glTexGenfvOES - glTexGeniOES - glTexGenivOES - glTexGenxOES - glTexGenxvOES - - ; GL_OES_texture_cube_map_array - - ; GL_OES_texture_float - - ; GL_OES_texture_float_linear - - ; GL_OES_texture_half_float - - ; GL_OES_texture_half_float_linear - - ; GL_OES_texture_npot - - ; GL_OES_texture_stencil8 - - ; GL_OES_texture_storage_multisample_2d_array - glTexStorage3DMultisampleOES - - ; GL_OES_vertex_array_object - glBindVertexArrayOES - glDeleteVertexArraysOES - glGenVertexArraysOES - glIsVertexArrayOES - - ; GL_OES_vertex_half_float - - ; GL_OES_vertex_type_10_10_10_2 - - ; GL_OVR_multiview - glFramebufferTextureMultiviewOVR - - ; GL_OVR_multiview2 - - ; GL_QCOM_framebuffer_foveated - glFramebufferFoveationConfigQCOM - glFramebufferFoveationParametersQCOM - - ; GL_QCOM_render_shared_exponent - - ; GL_QCOM_shading_rate - glShadingRateQCOM - - ; GL_QCOM_texture_foveated - glTextureFoveationParametersQCOM - - ; GL_QCOM_tiled_rendering - glEndTilingQCOM - glStartTilingQCOM diff --git a/src/libGLESv2/opengl32_with_wgl_autogen.def b/src/libGLESv2/opengl32_with_wgl_autogen.def deleted file mode 100644 index 7afe7a5e959..00000000000 --- a/src/libGLESv2/opengl32_with_wgl_autogen.def +++ /dev/null @@ -1,2387 +0,0 @@ -; GENERATED FILE - DO NOT EDIT. -; Generated by generate_entry_points.py using data from Khronos and ANGLE XML files. -; -; Copyright 2020 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. -LIBRARY opengl32 -EXPORTS - - ; OpenGL ES 2.0 - glActiveTexture - glAttachShader - glBindAttribLocation - glBindBuffer - glBindFramebuffer - glBindRenderbuffer - glBindTexture - glBlendColor - glBlendEquation - glBlendEquationSeparate - glBlendFunc - glBlendFuncSeparate - glBufferData - glBufferSubData - glCheckFramebufferStatus - glClear - glClearColor - glClearDepthf - glClearStencil - glColorMask - glCompileShader - glCompressedTexImage2D - glCompressedTexSubImage2D - glCopyTexImage2D - glCopyTexSubImage2D - glCreateProgram - glCreateShader - glCullFace - glDeleteBuffers - glDeleteFramebuffers - glDeleteProgram - glDeleteRenderbuffers - glDeleteShader - glDeleteTextures - glDepthFunc - glDepthMask - glDepthRangef - glDetachShader - glDisable - glDisableVertexAttribArray - glDrawArrays - glDrawElements - glEnable - glEnableVertexAttribArray - glFinish - glFlush - glFramebufferRenderbuffer - glFramebufferTexture2D - glFrontFace - glGenBuffers - glGenFramebuffers - glGenRenderbuffers - glGenTextures - glGenerateMipmap - glGetActiveAttrib - glGetActiveUniform - glGetAttachedShaders - glGetAttribLocation - glGetBooleanv - glGetBufferParameteriv - glGetError - glGetFloatv - glGetFramebufferAttachmentParameteriv - glGetIntegerv - glGetProgramInfoLog - glGetProgramiv - glGetRenderbufferParameteriv - glGetShaderInfoLog - glGetShaderPrecisionFormat - glGetShaderSource - glGetShaderiv - glGetString - glGetTexParameterfv - glGetTexParameteriv - glGetUniformLocation - glGetUniformfv - glGetUniformiv - glGetVertexAttribPointerv - glGetVertexAttribfv - glGetVertexAttribiv - glHint - glIsBuffer - glIsEnabled - glIsFramebuffer - glIsProgram - glIsRenderbuffer - glIsShader - glIsTexture - glLineWidth - glLinkProgram - glPixelStorei - glPolygonOffset - glReadPixels - glReleaseShaderCompiler - glRenderbufferStorage - glSampleCoverage - glScissor - glShaderBinary - glShaderSource - glStencilFunc - glStencilFuncSeparate - glStencilMask - glStencilMaskSeparate - glStencilOp - glStencilOpSeparate - glTexImage2D - glTexParameterf - glTexParameterfv - glTexParameteri - glTexParameteriv - glTexSubImage2D - glUniform1f - glUniform1fv - glUniform1i - glUniform1iv - glUniform2f - glUniform2fv - glUniform2i - glUniform2iv - glUniform3f - glUniform3fv - glUniform3i - glUniform3iv - glUniform4f - glUniform4fv - glUniform4i - glUniform4iv - glUniformMatrix2fv - glUniformMatrix3fv - glUniformMatrix4fv - glUseProgram - glValidateProgram - glVertexAttrib1f - glVertexAttrib1fv - glVertexAttrib2f - glVertexAttrib2fv - glVertexAttrib3f - glVertexAttrib3fv - glVertexAttrib4f - glVertexAttrib4fv - glVertexAttribPointer - glViewport - - ; OpenGL ES 3.0 - glBeginQuery - glBeginTransformFeedback - glBindBufferBase - glBindBufferRange - glBindSampler - glBindTransformFeedback - glBindVertexArray - glBlitFramebuffer - glClearBufferfi - glClearBufferfv - glClearBufferiv - glClearBufferuiv - glClientWaitSync - glCompressedTexImage3D - glCompressedTexSubImage3D - glCopyBufferSubData - glCopyTexSubImage3D - glDeleteQueries - glDeleteSamplers - glDeleteSync - glDeleteTransformFeedbacks - glDeleteVertexArrays - glDrawArraysInstanced - glDrawBuffers - glDrawElementsInstanced - glDrawRangeElements - glEndQuery - glEndTransformFeedback - glFenceSync - glFlushMappedBufferRange - glFramebufferTextureLayer - glGenQueries - glGenSamplers - glGenTransformFeedbacks - glGenVertexArrays - glGetActiveUniformBlockName - glGetActiveUniformBlockiv - glGetActiveUniformsiv - glGetBufferParameteri64v - glGetBufferPointerv - glGetFragDataLocation - glGetInteger64i_v - glGetInteger64v - glGetIntegeri_v - glGetInternalformativ - glGetProgramBinary - glGetQueryObjectuiv - glGetQueryiv - glGetSamplerParameterfv - glGetSamplerParameteriv - glGetStringi - glGetSynciv - glGetTransformFeedbackVarying - glGetUniformBlockIndex - glGetUniformIndices - glGetUniformuiv - glGetVertexAttribIiv - glGetVertexAttribIuiv - glInvalidateFramebuffer - glInvalidateSubFramebuffer - glIsQuery - glIsSampler - glIsSync - glIsTransformFeedback - glIsVertexArray - glMapBufferRange - glPauseTransformFeedback - glProgramBinary - glProgramParameteri - glReadBuffer - glRenderbufferStorageMultisample - glResumeTransformFeedback - glSamplerParameterf - glSamplerParameterfv - glSamplerParameteri - glSamplerParameteriv - glTexImage3D - glTexStorage2D - glTexStorage3D - glTexSubImage3D - glTransformFeedbackVaryings - glUniform1ui - glUniform1uiv - glUniform2ui - glUniform2uiv - glUniform3ui - glUniform3uiv - glUniform4ui - glUniform4uiv - glUniformBlockBinding - glUniformMatrix2x3fv - glUniformMatrix2x4fv - glUniformMatrix3x2fv - glUniformMatrix3x4fv - glUniformMatrix4x2fv - glUniformMatrix4x3fv - glUnmapBuffer - glVertexAttribDivisor - glVertexAttribI4i - glVertexAttribI4iv - glVertexAttribI4ui - glVertexAttribI4uiv - glVertexAttribIPointer - glWaitSync - - ; OpenGL ES 3.1 - glActiveShaderProgram - glBindImageTexture - glBindProgramPipeline - glBindVertexBuffer - glCreateShaderProgramv - glDeleteProgramPipelines - glDispatchCompute - glDispatchComputeIndirect - glDrawArraysIndirect - glDrawElementsIndirect - glFramebufferParameteri - glGenProgramPipelines - glGetBooleani_v - glGetFramebufferParameteriv - glGetMultisamplefv - glGetProgramInterfaceiv - glGetProgramPipelineInfoLog - glGetProgramPipelineiv - glGetProgramResourceIndex - glGetProgramResourceLocation - glGetProgramResourceName - glGetProgramResourceiv - glGetTexLevelParameterfv - glGetTexLevelParameteriv - glIsProgramPipeline - glMemoryBarrier - glMemoryBarrierByRegion - glProgramUniform1f - glProgramUniform1fv - glProgramUniform1i - glProgramUniform1iv - glProgramUniform1ui - glProgramUniform1uiv - glProgramUniform2f - glProgramUniform2fv - glProgramUniform2i - glProgramUniform2iv - glProgramUniform2ui - glProgramUniform2uiv - glProgramUniform3f - glProgramUniform3fv - glProgramUniform3i - glProgramUniform3iv - glProgramUniform3ui - glProgramUniform3uiv - glProgramUniform4f - glProgramUniform4fv - glProgramUniform4i - glProgramUniform4iv - glProgramUniform4ui - glProgramUniform4uiv - glProgramUniformMatrix2fv - glProgramUniformMatrix2x3fv - glProgramUniformMatrix2x4fv - glProgramUniformMatrix3fv - glProgramUniformMatrix3x2fv - glProgramUniformMatrix3x4fv - glProgramUniformMatrix4fv - glProgramUniformMatrix4x2fv - glProgramUniformMatrix4x3fv - glSampleMaski - glTexStorage2DMultisample - glUseProgramStages - glValidateProgramPipeline - glVertexAttribBinding - glVertexAttribFormat - glVertexAttribIFormat - glVertexBindingDivisor - - ; OpenGL ES 3.2 - glBlendBarrier - glBlendEquationSeparatei - glBlendEquationi - glBlendFuncSeparatei - glBlendFunci - glColorMaski - glCopyImageSubData - glDebugMessageCallback - glDebugMessageControl - glDebugMessageInsert - glDisablei - glDrawElementsBaseVertex - glDrawElementsInstancedBaseVertex - glDrawRangeElementsBaseVertex - glEnablei - glFramebufferTexture - glGetDebugMessageLog - glGetGraphicsResetStatus - glGetObjectLabel - glGetObjectPtrLabel - glGetPointerv - glGetSamplerParameterIiv - glGetSamplerParameterIuiv - glGetTexParameterIiv - glGetTexParameterIuiv - glGetnUniformfv - glGetnUniformiv - glGetnUniformuiv - glIsEnabledi - glMinSampleShading - glObjectLabel - glObjectPtrLabel - glPatchParameteri - glPopDebugGroup - glPrimitiveBoundingBox - glPushDebugGroup - glReadnPixels - glSamplerParameterIiv - glSamplerParameterIuiv - glTexBuffer - glTexBufferRange - glTexParameterIiv - glTexParameterIuiv - glTexStorage3DMultisample - - ; OpenGL ES 1.0 - glAlphaFunc - glAlphaFuncx - glClearColorx - glClearDepthx - glClientActiveTexture - glClipPlanef - glClipPlanex - glColor4f - glColor4ub - glColor4x - glColorPointer - glDepthRangex - glDisableClientState - glEnableClientState - glFogf - glFogfv - glFogx - glFogxv - glFrustumf - glFrustumx - glGetClipPlanef - glGetClipPlanex - glGetFixedv - glGetLightfv - glGetLightxv - glGetMaterialfv - glGetMaterialxv - glGetTexEnvfv - glGetTexEnviv - glGetTexEnvxv - glGetTexParameterxv - glLightModelf - glLightModelfv - glLightModelx - glLightModelxv - glLightf - glLightfv - glLightx - glLightxv - glLineWidthx - glLoadIdentity - glLoadMatrixf - glLoadMatrixx - glLogicOp - glMaterialf - glMaterialfv - glMaterialx - glMaterialxv - glMatrixMode - glMultMatrixf - glMultMatrixx - glMultiTexCoord4f - glMultiTexCoord4x - glNormal3f - glNormal3x - glNormalPointer - glOrthof - glOrthox - glPointParameterf - glPointParameterfv - glPointParameterx - glPointParameterxv - glPointSize - glPointSizex - glPolygonOffsetx - glPopMatrix - glPushMatrix - glRotatef - glRotatex - glSampleCoveragex - glScalef - glScalex - glShadeModel - glTexCoordPointer - glTexEnvf - glTexEnvfv - glTexEnvi - glTexEnviv - glTexEnvx - glTexEnvxv - glTexParameterx - glTexParameterxv - glTranslatef - glTranslatex - glVertexPointer - - ; GL_AMD_performance_monitor - glBeginPerfMonitorAMD - glDeletePerfMonitorsAMD - glEndPerfMonitorAMD - glGenPerfMonitorsAMD - glGetPerfMonitorCounterDataAMD - glGetPerfMonitorCounterInfoAMD - glGetPerfMonitorCounterStringAMD - glGetPerfMonitorCountersAMD - glGetPerfMonitorGroupStringAMD - glGetPerfMonitorGroupsAMD - glSelectPerfMonitorCountersAMD - - ; GL_ANDROID_extension_pack_es31a - - ; GL_ANGLE_base_vertex_base_instance - glDrawArraysInstancedBaseInstanceANGLE - glDrawElementsInstancedBaseVertexBaseInstanceANGLE - glMultiDrawArraysInstancedBaseInstanceANGLE - glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE - - ; GL_ANGLE_client_arrays - - ; GL_ANGLE_clip_cull_distance - - ; GL_ANGLE_copy_texture_3d - glCopySubTexture3DANGLE - glCopyTexture3DANGLE - - ; GL_ANGLE_depth_texture - - ; GL_ANGLE_framebuffer_blit - glBlitFramebufferANGLE - - ; GL_ANGLE_framebuffer_multisample - glRenderbufferStorageMultisampleANGLE - - ; GL_ANGLE_get_image - glGetCompressedTexImageANGLE - glGetRenderbufferImageANGLE - glGetTexImageANGLE - - ; GL_ANGLE_get_serialized_context_string - - ; GL_ANGLE_get_tex_level_parameter - glGetTexLevelParameterfvANGLE - glGetTexLevelParameterivANGLE - - ; GL_ANGLE_instanced_arrays - glDrawArraysInstancedANGLE - glDrawElementsInstancedANGLE - glVertexAttribDivisorANGLE - - ; GL_ANGLE_logic_op - glLogicOpANGLE - - ; GL_ANGLE_lossy_etc_decode - - ; GL_ANGLE_memory_object_flags - glTexStorageMemFlags2DANGLE - glTexStorageMemFlags2DMultisampleANGLE - glTexStorageMemFlags3DANGLE - glTexStorageMemFlags3DMultisampleANGLE - - ; GL_ANGLE_memory_object_fuchsia - glImportMemoryZirconHandleANGLE - - ; GL_ANGLE_memory_size - - ; GL_ANGLE_multi_draw - glMultiDrawArraysANGLE - glMultiDrawArraysInstancedANGLE - glMultiDrawElementsANGLE - glMultiDrawElementsInstancedANGLE - - ; GL_ANGLE_pack_reverse_row_order - - ; GL_ANGLE_polygon_mode - glPolygonModeANGLE - - ; GL_ANGLE_program_binary - - ; GL_ANGLE_program_binary_readiness_query - - ; GL_ANGLE_program_cache_control - - ; GL_ANGLE_provoking_vertex - glProvokingVertexANGLE - - ; GL_ANGLE_renderability_validation - - ; GL_ANGLE_request_extension - glDisableExtensionANGLE - glRequestExtensionANGLE - - ; GL_ANGLE_rgbx_internal_format - - ; GL_ANGLE_robust_client_memory - glCompressedTexImage2DRobustANGLE - glCompressedTexImage3DRobustANGLE - glCompressedTexSubImage2DRobustANGLE - glCompressedTexSubImage3DRobustANGLE - glGetActiveUniformBlockivRobustANGLE - glGetBooleani_vRobustANGLE - glGetBooleanvRobustANGLE - glGetBufferParameteri64vRobustANGLE - glGetBufferParameterivRobustANGLE - glGetBufferPointervRobustANGLE - glGetFloatvRobustANGLE - glGetFramebufferAttachmentParameterivRobustANGLE - glGetFramebufferParameterivRobustANGLE - glGetInteger64i_vRobustANGLE - glGetInteger64vRobustANGLE - glGetIntegeri_vRobustANGLE - glGetIntegervRobustANGLE - glGetInternalformativRobustANGLE - glGetMultisamplefvRobustANGLE - glGetPointervRobustANGLERobustANGLE - glGetProgramInterfaceivRobustANGLE - glGetProgramivRobustANGLE - glGetQueryObjecti64vRobustANGLE - glGetQueryObjectivRobustANGLE - glGetQueryObjectui64vRobustANGLE - glGetQueryObjectuivRobustANGLE - glGetQueryivRobustANGLE - glGetRenderbufferParameterivRobustANGLE - glGetSamplerParameterIivRobustANGLE - glGetSamplerParameterIuivRobustANGLE - glGetSamplerParameterfvRobustANGLE - glGetSamplerParameterivRobustANGLE - glGetShaderivRobustANGLE - glGetTexLevelParameterfvRobustANGLE - glGetTexLevelParameterivRobustANGLE - glGetTexParameterIivRobustANGLE - glGetTexParameterIuivRobustANGLE - glGetTexParameterfvRobustANGLE - glGetTexParameterivRobustANGLE - glGetUniformfvRobustANGLE - glGetUniformivRobustANGLE - glGetUniformuivRobustANGLE - glGetVertexAttribIivRobustANGLE - glGetVertexAttribIuivRobustANGLE - glGetVertexAttribPointervRobustANGLE - glGetVertexAttribfvRobustANGLE - glGetVertexAttribivRobustANGLE - glGetnUniformfvRobustANGLE - glGetnUniformivRobustANGLE - glGetnUniformuivRobustANGLE - glReadPixelsRobustANGLE - glReadnPixelsRobustANGLE - glSamplerParameterIivRobustANGLE - glSamplerParameterIuivRobustANGLE - glSamplerParameterfvRobustANGLE - glSamplerParameterivRobustANGLE - glTexImage2DRobustANGLE - glTexImage3DRobustANGLE - glTexParameterIivRobustANGLE - glTexParameterIuivRobustANGLE - glTexParameterfvRobustANGLE - glTexParameterivRobustANGLE - glTexSubImage2DRobustANGLE - glTexSubImage3DRobustANGLE - - ; GL_ANGLE_robust_fragment_shader_output - - ; GL_ANGLE_robust_resource_initialization - - ; GL_ANGLE_semaphore_fuchsia - glImportSemaphoreZirconHandleANGLE - - ; GL_ANGLE_shader_binary - - ; GL_ANGLE_shader_pixel_local_storage - glBeginPixelLocalStorageANGLE - glEndPixelLocalStorageANGLE - glFramebufferMemorylessPixelLocalStorageANGLE - glFramebufferPixelLocalClearValuefvANGLE - glFramebufferPixelLocalClearValueivANGLE - glFramebufferPixelLocalClearValueuivANGLE - glFramebufferPixelLocalStorageInterruptANGLE - glFramebufferPixelLocalStorageRestoreANGLE - glFramebufferTexturePixelLocalStorageANGLE - glGetFramebufferPixelLocalStorageParameterfvANGLE - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE - glGetFramebufferPixelLocalStorageParameterivANGLE - glGetFramebufferPixelLocalStorageParameterivRobustANGLE - glPixelLocalStorageBarrierANGLE - - ; GL_ANGLE_stencil_texturing - - ; GL_ANGLE_texture_compression_dxt3 - - ; GL_ANGLE_texture_compression_dxt5 - - ; GL_ANGLE_texture_external_update - glInvalidateTextureANGLE - glTexImage2DExternalANGLE - - ; GL_ANGLE_texture_multisample - glGetMultisamplefvANGLE - glSampleMaskiANGLE - glTexStorage2DMultisampleANGLE - - ; GL_ANGLE_texture_usage - - ; GL_ANGLE_translated_shader_source - glGetTranslatedShaderSourceANGLE - - ; GL_ANGLE_vulkan_image - glAcquireTexturesANGLE - glReleaseTexturesANGLE - - ; GL_ANGLE_yuv_internal_format - - ; GL_APPLE_clip_distance - - ; GL_ARB_sync - - ; GL_ARM_shader_framebuffer_fetch - - ; GL_CHROMIUM_bind_uniform_location - glBindUniformLocationCHROMIUM - - ; GL_CHROMIUM_copy_compressed_texture - glCompressedCopyTextureCHROMIUM - - ; GL_CHROMIUM_copy_texture - glCopySubTextureCHROMIUM - glCopyTextureCHROMIUM - - ; GL_CHROMIUM_framebuffer_mixed_samples - glCoverageModulationCHROMIUM - - ; GL_CHROMIUM_lose_context - glLoseContextCHROMIUM - - ; GL_EXT_EGL_image_array - - ; GL_EXT_EGL_image_storage - glEGLImageTargetTexStorageEXT - glEGLImageTargetTextureStorageEXT - - ; GL_EXT_YUV_target - - ; GL_EXT_base_instance - glDrawArraysInstancedBaseInstanceEXT - glDrawElementsInstancedBaseInstanceEXT - glDrawElementsInstancedBaseVertexBaseInstanceEXT - - ; GL_EXT_blend_func_extended - glBindFragDataLocationEXT - glBindFragDataLocationIndexedEXT - glGetFragDataIndexEXT - glGetProgramResourceLocationIndexEXT - - ; GL_EXT_blend_minmax - - ; GL_EXT_buffer_storage - glBufferStorageEXT - - ; GL_EXT_clear_texture - glClearTexImageEXT - glClearTexSubImageEXT - - ; GL_EXT_clip_control - glClipControlEXT - - ; GL_EXT_clip_cull_distance - - ; GL_EXT_color_buffer_float - - ; GL_EXT_color_buffer_half_float - - ; GL_EXT_conservative_depth - - ; GL_EXT_copy_image - glCopyImageSubDataEXT - - ; GL_EXT_debug_label - glGetObjectLabelEXT - glLabelObjectEXT - - ; GL_EXT_debug_marker - glInsertEventMarkerEXT - glPopGroupMarkerEXT - glPushGroupMarkerEXT - - ; GL_EXT_depth_clamp - - ; GL_EXT_discard_framebuffer - glDiscardFramebufferEXT - - ; GL_EXT_disjoint_timer_query - glBeginQueryEXT - glDeleteQueriesEXT - glEndQueryEXT - glGenQueriesEXT - glGetInteger64vEXT - glGetQueryObjecti64vEXT - glGetQueryObjectivEXT - glGetQueryObjectui64vEXT - glGetQueryObjectuivEXT - glGetQueryivEXT - glIsQueryEXT - glQueryCounterEXT - - ; GL_EXT_draw_buffers - glDrawBuffersEXT - - ; GL_EXT_draw_buffers_indexed - glBlendEquationSeparateiEXT - glBlendEquationiEXT - glBlendFuncSeparateiEXT - glBlendFunciEXT - glColorMaskiEXT - glDisableiEXT - glEnableiEXT - glIsEnablediEXT - - ; GL_EXT_draw_elements_base_vertex - glDrawElementsBaseVertexEXT - glDrawElementsInstancedBaseVertexEXT - glDrawRangeElementsBaseVertexEXT - glMultiDrawElementsBaseVertexEXT - - ; GL_EXT_external_buffer - glBufferStorageExternalEXT - glNamedBufferStorageExternalEXT - - ; GL_EXT_float_blend - - ; GL_EXT_geometry_shader - glFramebufferTextureEXT - - ; GL_EXT_gpu_shader5 - - ; GL_EXT_instanced_arrays - glDrawArraysInstancedEXT - glDrawElementsInstancedEXT - glVertexAttribDivisorEXT - - ; GL_EXT_map_buffer_range - glFlushMappedBufferRangeEXT - glMapBufferRangeEXT - - ; GL_EXT_memory_object - glBufferStorageMemEXT - glCreateMemoryObjectsEXT - glDeleteMemoryObjectsEXT - glGetMemoryObjectParameterivEXT - glGetUnsignedBytei_vEXT - glGetUnsignedBytevEXT - glIsMemoryObjectEXT - glMemoryObjectParameterivEXT - glTexStorageMem2DEXT - glTexStorageMem2DMultisampleEXT - glTexStorageMem3DEXT - glTexStorageMem3DMultisampleEXT - - ; GL_EXT_memory_object_fd - glImportMemoryFdEXT - - ; GL_EXT_multi_draw_indirect - glMultiDrawArraysIndirectEXT - glMultiDrawElementsIndirectEXT - - ; GL_EXT_multisampled_render_to_texture - glFramebufferTexture2DMultisampleEXT - glRenderbufferStorageMultisampleEXT - - ; GL_EXT_multisampled_render_to_texture2 - - ; GL_EXT_occlusion_query_boolean - - ; GL_EXT_polygon_offset_clamp - glPolygonOffsetClampEXT - - ; GL_EXT_primitive_bounding_box - glPrimitiveBoundingBoxEXT - - ; GL_EXT_protected_textures - - ; GL_EXT_pvrtc_sRGB - - ; GL_EXT_read_format_bgra - - ; GL_EXT_render_snorm - - ; GL_EXT_robustness - glGetGraphicsResetStatusEXT - glGetnUniformfvEXT - glGetnUniformivEXT - glReadnPixelsEXT - - ; GL_EXT_sRGB - - ; GL_EXT_sRGB_write_control - - ; GL_EXT_semaphore - glDeleteSemaphoresEXT - glGenSemaphoresEXT - glGetSemaphoreParameterui64vEXT - glIsSemaphoreEXT - glSemaphoreParameterui64vEXT - glSignalSemaphoreEXT - glWaitSemaphoreEXT - - ; GL_EXT_semaphore_fd - glImportSemaphoreFdEXT - - ; GL_EXT_separate_depth_stencil - - ; GL_EXT_separate_shader_objects - glActiveShaderProgramEXT - glBindProgramPipelineEXT - glCreateShaderProgramvEXT - glDeleteProgramPipelinesEXT - glGenProgramPipelinesEXT - glGetProgramPipelineInfoLogEXT - glGetProgramPipelineivEXT - glIsProgramPipelineEXT - glProgramParameteriEXT - glProgramUniform1fEXT - glProgramUniform1fvEXT - glProgramUniform1iEXT - glProgramUniform1ivEXT - glProgramUniform1uiEXT - glProgramUniform1uivEXT - glProgramUniform2fEXT - glProgramUniform2fvEXT - glProgramUniform2iEXT - glProgramUniform2ivEXT - glProgramUniform2uiEXT - glProgramUniform2uivEXT - glProgramUniform3fEXT - glProgramUniform3fvEXT - glProgramUniform3iEXT - glProgramUniform3ivEXT - glProgramUniform3uiEXT - glProgramUniform3uivEXT - glProgramUniform4fEXT - glProgramUniform4fvEXT - glProgramUniform4iEXT - glProgramUniform4ivEXT - glProgramUniform4uiEXT - glProgramUniform4uivEXT - glProgramUniformMatrix2fvEXT - glProgramUniformMatrix2x3fvEXT - glProgramUniformMatrix2x4fvEXT - glProgramUniformMatrix3fvEXT - glProgramUniformMatrix3x2fvEXT - glProgramUniformMatrix3x4fvEXT - glProgramUniformMatrix4fvEXT - glProgramUniformMatrix4x2fvEXT - glProgramUniformMatrix4x3fvEXT - glUseProgramStagesEXT - glValidateProgramPipelineEXT - - ; GL_EXT_shader_framebuffer_fetch - - ; GL_EXT_shader_framebuffer_fetch_non_coherent - glFramebufferFetchBarrierEXT - - ; GL_EXT_shader_io_blocks - - ; GL_EXT_shader_non_constant_global_initializers - - ; GL_EXT_shader_texture_lod - - ; GL_EXT_shadow_samplers - - ; GL_EXT_tessellation_shader - glPatchParameteriEXT - - ; GL_EXT_texture_border_clamp - glGetSamplerParameterIivEXT - glGetSamplerParameterIuivEXT - glGetTexParameterIivEXT - glGetTexParameterIuivEXT - glSamplerParameterIivEXT - glSamplerParameterIuivEXT - glTexParameterIivEXT - glTexParameterIuivEXT - - ; GL_EXT_texture_buffer - glTexBufferEXT - glTexBufferRangeEXT - - ; GL_EXT_texture_compression_astc_decode_mode - - ; GL_EXT_texture_compression_bptc - - ; GL_EXT_texture_compression_dxt1 - - ; GL_EXT_texture_compression_rgtc - - ; GL_EXT_texture_compression_s3tc - - ; GL_EXT_texture_compression_s3tc_srgb - - ; GL_EXT_texture_cube_map_array - - ; GL_EXT_texture_filter_anisotropic - - ; GL_EXT_texture_filter_minmax - - ; GL_EXT_texture_format_BGRA8888 - - ; GL_EXT_texture_format_sRGB_override - - ; GL_EXT_texture_mirror_clamp_to_edge - - ; GL_EXT_texture_norm16 - - ; GL_EXT_texture_rg - - ; GL_EXT_texture_sRGB_R8 - - ; GL_EXT_texture_sRGB_RG8 - - ; GL_EXT_texture_sRGB_decode - - ; GL_EXT_texture_shadow_lod - - ; GL_EXT_texture_storage - glTexStorage1DEXT - glTexStorage2DEXT - glTexStorage3DEXT - - ; GL_EXT_texture_storage_compression - glTexStorageAttribs2DEXT - glTexStorageAttribs3DEXT - - ; GL_EXT_texture_type_2_10_10_10_REV - - ; GL_EXT_unpack_subimage - - ; GL_IMG_texture_compression_pvrtc - - ; GL_IMG_texture_compression_pvrtc2 - - ; GL_KHR_blend_equation_advanced - glBlendBarrierKHR - - ; GL_KHR_blend_equation_advanced_coherent - - ; GL_KHR_debug - glDebugMessageCallbackKHR - glDebugMessageControlKHR - glDebugMessageInsertKHR - glGetDebugMessageLogKHR - glGetObjectLabelKHR - glGetObjectPtrLabelKHR - glGetPointervKHR - glObjectLabelKHR - glObjectPtrLabelKHR - glPopDebugGroupKHR - glPushDebugGroupKHR - - ; GL_KHR_no_error - - ; GL_KHR_parallel_shader_compile - glMaxShaderCompilerThreadsKHR - - ; GL_KHR_robust_buffer_access_behavior - - ; GL_KHR_robustness - glGetGraphicsResetStatusKHR - glGetnUniformfvKHR - glGetnUniformivKHR - glGetnUniformuivKHR - glReadnPixelsKHR - - ; GL_KHR_texture_compression_astc_hdr - - ; GL_KHR_texture_compression_astc_ldr - - ; GL_KHR_texture_compression_astc_sliced_3d - - ; GL_MESA_framebuffer_flip_y - glFramebufferParameteriMESA - glGetFramebufferParameterivMESA - - ; GL_NV_fence - glDeleteFencesNV - glFinishFenceNV - glGenFencesNV - glGetFenceivNV - glIsFenceNV - glSetFenceNV - glTestFenceNV - - ; GL_NV_framebuffer_blit - glBlitFramebufferNV - - ; GL_NV_pixel_buffer_object - - ; GL_NV_polygon_mode - glPolygonModeNV - - ; GL_NV_read_depth - - ; GL_NV_read_depth_stencil - - ; GL_NV_read_stencil - - ; GL_NV_robustness_video_memory_purge - - ; GL_NV_shader_noperspective_interpolation - - ; GL_OES_EGL_image - glEGLImageTargetRenderbufferStorageOES - glEGLImageTargetTexture2DOES - - ; GL_OES_EGL_image_external - - ; GL_OES_EGL_image_external_essl3 - - ; GL_OES_compressed_ETC1_RGB8_texture - - ; GL_OES_compressed_paletted_texture - - ; GL_OES_copy_image - glCopyImageSubDataOES - - ; GL_OES_depth24 - - ; GL_OES_depth32 - - ; GL_OES_depth_texture - - ; GL_OES_draw_buffers_indexed - glBlendEquationSeparateiOES - glBlendEquationiOES - glBlendFuncSeparateiOES - glBlendFunciOES - glColorMaskiOES - glDisableiOES - glEnableiOES - glIsEnablediOES - - ; GL_OES_draw_elements_base_vertex - glDrawElementsBaseVertexOES - glDrawElementsInstancedBaseVertexOES - glDrawRangeElementsBaseVertexOES - - ; GL_OES_draw_texture - glDrawTexfOES - glDrawTexfvOES - glDrawTexiOES - glDrawTexivOES - glDrawTexsOES - glDrawTexsvOES - glDrawTexxOES - glDrawTexxvOES - - ; GL_OES_element_index_uint - - ; GL_OES_fbo_render_mipmap - - ; GL_OES_framebuffer_object - glBindFramebufferOES - glBindRenderbufferOES - glCheckFramebufferStatusOES - glDeleteFramebuffersOES - glDeleteRenderbuffersOES - glFramebufferRenderbufferOES - glFramebufferTexture2DOES - glGenFramebuffersOES - glGenRenderbuffersOES - glGenerateMipmapOES - glGetFramebufferAttachmentParameterivOES - glGetRenderbufferParameterivOES - glIsFramebufferOES - glIsRenderbufferOES - glRenderbufferStorageOES - - ; GL_OES_geometry_shader - glFramebufferTextureOES - - ; GL_OES_get_program_binary - glGetProgramBinaryOES - glProgramBinaryOES - - ; GL_OES_gpu_shader5 - - ; GL_OES_mapbuffer - glGetBufferPointervOES - glMapBufferOES - glUnmapBufferOES - - ; GL_OES_matrix_palette - glCurrentPaletteMatrixOES - glLoadPaletteFromModelViewMatrixOES - glMatrixIndexPointerOES - glWeightPointerOES - - ; GL_OES_packed_depth_stencil - - ; GL_OES_point_size_array - glPointSizePointerOES - - ; GL_OES_point_sprite - - ; GL_OES_primitive_bounding_box - glPrimitiveBoundingBoxOES - - ; GL_OES_query_matrix - glQueryMatrixxOES - - ; GL_OES_rgb8_rgba8 - - ; GL_OES_sample_shading - glMinSampleShadingOES - - ; GL_OES_sample_variables - - ; GL_OES_shader_image_atomic - - ; GL_OES_shader_io_blocks - - ; GL_OES_shader_multisample_interpolation - - ; GL_OES_standard_derivatives - - ; GL_OES_surfaceless_context - - ; GL_OES_tessellation_shader - glPatchParameteriOES - - ; GL_OES_texture_3D - glCompressedTexImage3DOES - glCompressedTexSubImage3DOES - glCopyTexSubImage3DOES - glFramebufferTexture3DOES - glTexImage3DOES - glTexSubImage3DOES - - ; GL_OES_texture_border_clamp - glGetSamplerParameterIivOES - glGetSamplerParameterIuivOES - glGetTexParameterIivOES - glGetTexParameterIuivOES - glSamplerParameterIivOES - glSamplerParameterIuivOES - glTexParameterIivOES - glTexParameterIuivOES - - ; GL_OES_texture_buffer - glTexBufferOES - glTexBufferRangeOES - - ; GL_OES_texture_compression_astc - - ; GL_OES_texture_cube_map - glGetTexGenfvOES - glGetTexGenivOES - glGetTexGenxvOES - glTexGenfOES - glTexGenfvOES - glTexGeniOES - glTexGenivOES - glTexGenxOES - glTexGenxvOES - - ; GL_OES_texture_cube_map_array - - ; GL_OES_texture_float - - ; GL_OES_texture_float_linear - - ; GL_OES_texture_half_float - - ; GL_OES_texture_half_float_linear - - ; GL_OES_texture_npot - - ; GL_OES_texture_stencil8 - - ; GL_OES_texture_storage_multisample_2d_array - glTexStorage3DMultisampleOES - - ; GL_OES_vertex_array_object - glBindVertexArrayOES - glDeleteVertexArraysOES - glGenVertexArraysOES - glIsVertexArrayOES - - ; GL_OES_vertex_half_float - - ; GL_OES_vertex_type_10_10_10_2 - - ; GL_OVR_multiview - glFramebufferTextureMultiviewOVR - - ; GL_OVR_multiview2 - - ; GL_QCOM_framebuffer_foveated - glFramebufferFoveationConfigQCOM - glFramebufferFoveationParametersQCOM - - ; GL_QCOM_render_shared_exponent - - ; GL_QCOM_shading_rate - glShadingRateQCOM - - ; GL_QCOM_texture_foveated - glTextureFoveationParametersQCOM - - ; GL_QCOM_tiled_rendering - glEndTilingQCOM - glStartTilingQCOM - - ; GL 1.0 - glAccum - glAlphaFunc - glBegin - glBitmap - glBlendFunc - glCallList - glCallLists - glClear - glClearAccum - glClearColor - glClearDepth - glClearIndex - glClearStencil - glClipPlane - glColor3b - glColor3bv - glColor3d - glColor3dv - glColor3f - glColor3fv - glColor3i - glColor3iv - glColor3s - glColor3sv - glColor3ub - glColor3ubv - glColor3ui - glColor3uiv - glColor3us - glColor3usv - glColor4b - glColor4bv - glColor4d - glColor4dv - glColor4f - glColor4fv - glColor4i - glColor4iv - glColor4s - glColor4sv - glColor4ub - glColor4ubv - glColor4ui - glColor4uiv - glColor4us - glColor4usv - glColorMask - glColorMaterial - glCopyPixels - glCullFace - glDeleteLists - glDepthFunc - glDepthMask - glDepthRange - glDisable - glDrawBuffer - glDrawPixels - glEdgeFlag - glEdgeFlagv - glEnable - glEnd - glEndList - glEvalCoord1d - glEvalCoord1dv - glEvalCoord1f - glEvalCoord1fv - glEvalCoord2d - glEvalCoord2dv - glEvalCoord2f - glEvalCoord2fv - glEvalMesh1 - glEvalMesh2 - glEvalPoint1 - glEvalPoint2 - glFeedbackBuffer - glFinish - glFlush - glFogf - glFogfv - glFogi - glFogiv - glFrontFace - glFrustum - glGenLists - glGetBooleanv - glGetClipPlane - glGetDoublev - glGetError - glGetFloatv - glGetIntegerv - glGetLightfv - glGetLightiv - glGetMapdv - glGetMapfv - glGetMapiv - glGetMaterialfv - glGetMaterialiv - glGetPixelMapfv - glGetPixelMapuiv - glGetPixelMapusv - glGetPolygonStipple - glGetString - glGetTexEnvfv - glGetTexEnviv - glGetTexGendv - glGetTexGenfv - glGetTexGeniv - glGetTexImage - glGetTexLevelParameterfv - glGetTexLevelParameteriv - glGetTexParameterfv - glGetTexParameteriv - glHint - glIndexMask - glIndexd - glIndexdv - glIndexf - glIndexfv - glIndexi - glIndexiv - glIndexs - glIndexsv - glInitNames - glIsEnabled - glIsList - glLightModelf - glLightModelfv - glLightModeli - glLightModeliv - glLightf - glLightfv - glLighti - glLightiv - glLineStipple - glLineWidth - glListBase - glLoadIdentity - glLoadMatrixd - glLoadMatrixf - glLoadName - glLogicOp - glMap1d - glMap1f - glMap2d - glMap2f - glMapGrid1d - glMapGrid1f - glMapGrid2d - glMapGrid2f - glMaterialf - glMaterialfv - glMateriali - glMaterialiv - glMatrixMode - glMultMatrixd - glMultMatrixf - glNewList - glNormal3b - glNormal3bv - glNormal3d - glNormal3dv - glNormal3f - glNormal3fv - glNormal3i - glNormal3iv - glNormal3s - glNormal3sv - glOrtho - glPassThrough - glPixelMapfv - glPixelMapuiv - glPixelMapusv - glPixelStoref - glPixelStorei - glPixelTransferf - glPixelTransferi - glPixelZoom - glPointSize - glPolygonMode - glPolygonStipple - glPopAttrib - glPopMatrix - glPopName - glPushAttrib - glPushMatrix - glPushName - glRasterPos2d - glRasterPos2dv - glRasterPos2f - glRasterPos2fv - glRasterPos2i - glRasterPos2iv - glRasterPos2s - glRasterPos2sv - glRasterPos3d - glRasterPos3dv - glRasterPos3f - glRasterPos3fv - glRasterPos3i - glRasterPos3iv - glRasterPos3s - glRasterPos3sv - glRasterPos4d - glRasterPos4dv - glRasterPos4f - glRasterPos4fv - glRasterPos4i - glRasterPos4iv - glRasterPos4s - glRasterPos4sv - glReadBuffer - glReadPixels - glRectd - glRectdv - glRectf - glRectfv - glRecti - glRectiv - glRects - glRectsv - glRenderMode - glRotated - glRotatef - glScaled - glScalef - glScissor - glSelectBuffer - glShadeModel - glStencilFunc - glStencilMask - glStencilOp - glTexCoord1d - glTexCoord1dv - glTexCoord1f - glTexCoord1fv - glTexCoord1i - glTexCoord1iv - glTexCoord1s - glTexCoord1sv - glTexCoord2d - glTexCoord2dv - glTexCoord2f - glTexCoord2fv - glTexCoord2i - glTexCoord2iv - glTexCoord2s - glTexCoord2sv - glTexCoord3d - glTexCoord3dv - glTexCoord3f - glTexCoord3fv - glTexCoord3i - glTexCoord3iv - glTexCoord3s - glTexCoord3sv - glTexCoord4d - glTexCoord4dv - glTexCoord4f - glTexCoord4fv - glTexCoord4i - glTexCoord4iv - glTexCoord4s - glTexCoord4sv - glTexEnvf - glTexEnvfv - glTexEnvi - glTexEnviv - glTexGend - glTexGendv - glTexGenf - glTexGenfv - glTexGeni - glTexGeniv - glTexImage1D - glTexImage2D - glTexParameterf - glTexParameterfv - glTexParameteri - glTexParameteriv - glTranslated - glTranslatef - glVertex2d - glVertex2dv - glVertex2f - glVertex2fv - glVertex2i - glVertex2iv - glVertex2s - glVertex2sv - glVertex3d - glVertex3dv - glVertex3f - glVertex3fv - glVertex3i - glVertex3iv - glVertex3s - glVertex3sv - glVertex4d - glVertex4dv - glVertex4f - glVertex4fv - glVertex4i - glVertex4iv - glVertex4s - glVertex4sv - glViewport - - ; GL 1.1 - glAreTexturesResident - glArrayElement - glBindTexture - glColorPointer - glCopyTexImage1D - glCopyTexImage2D - glCopyTexSubImage1D - glCopyTexSubImage2D - glDeleteTextures - glDisableClientState - glDrawArrays - glDrawElements - glEdgeFlagPointer - glEnableClientState - glGenTextures - glGetPointerv - glIndexPointer - glIndexub - glIndexubv - glInterleavedArrays - glIsTexture - glNormalPointer - glPolygonOffset - glPopClientAttrib - glPrioritizeTextures - glPushClientAttrib - glTexCoordPointer - glTexSubImage1D - glTexSubImage2D - glVertexPointer - - ; GL 1.2 - glCopyTexSubImage3D - glDrawRangeElements - glTexImage3D - glTexSubImage3D - - ; GL 1.3 - glActiveTexture - glClientActiveTexture - glCompressedTexImage1D - glCompressedTexImage2D - glCompressedTexImage3D - glCompressedTexSubImage1D - glCompressedTexSubImage2D - glCompressedTexSubImage3D - glGetCompressedTexImage - glLoadTransposeMatrixd - glLoadTransposeMatrixf - glMultTransposeMatrixd - glMultTransposeMatrixf - glMultiTexCoord1d - glMultiTexCoord1dv - glMultiTexCoord1f - glMultiTexCoord1fv - glMultiTexCoord1i - glMultiTexCoord1iv - glMultiTexCoord1s - glMultiTexCoord1sv - glMultiTexCoord2d - glMultiTexCoord2dv - glMultiTexCoord2f - glMultiTexCoord2fv - glMultiTexCoord2i - glMultiTexCoord2iv - glMultiTexCoord2s - glMultiTexCoord2sv - glMultiTexCoord3d - glMultiTexCoord3dv - glMultiTexCoord3f - glMultiTexCoord3fv - glMultiTexCoord3i - glMultiTexCoord3iv - glMultiTexCoord3s - glMultiTexCoord3sv - glMultiTexCoord4d - glMultiTexCoord4dv - glMultiTexCoord4f - glMultiTexCoord4fv - glMultiTexCoord4i - glMultiTexCoord4iv - glMultiTexCoord4s - glMultiTexCoord4sv - glSampleCoverage - - ; GL 1.4 - glBlendColor - glBlendEquation - glBlendFuncSeparate - glFogCoordPointer - glFogCoordd - glFogCoorddv - glFogCoordf - glFogCoordfv - glMultiDrawArrays - glMultiDrawElements - glPointParameterf - glPointParameterfv - glPointParameteri - glPointParameteriv - glSecondaryColor3b - glSecondaryColor3bv - glSecondaryColor3d - glSecondaryColor3dv - glSecondaryColor3f - glSecondaryColor3fv - glSecondaryColor3i - glSecondaryColor3iv - glSecondaryColor3s - glSecondaryColor3sv - glSecondaryColor3ub - glSecondaryColor3ubv - glSecondaryColor3ui - glSecondaryColor3uiv - glSecondaryColor3us - glSecondaryColor3usv - glSecondaryColorPointer - glWindowPos2d - glWindowPos2dv - glWindowPos2f - glWindowPos2fv - glWindowPos2i - glWindowPos2iv - glWindowPos2s - glWindowPos2sv - glWindowPos3d - glWindowPos3dv - glWindowPos3f - glWindowPos3fv - glWindowPos3i - glWindowPos3iv - glWindowPos3s - glWindowPos3sv - - ; GL 1.5 - glBeginQuery - glBindBuffer - glBufferData - glBufferSubData - glDeleteBuffers - glDeleteQueries - glEndQuery - glGenBuffers - glGenQueries - glGetBufferParameteriv - glGetBufferPointerv - glGetBufferSubData - glGetQueryObjectiv - glGetQueryObjectuiv - glGetQueryiv - glIsBuffer - glIsQuery - glMapBuffer - glUnmapBuffer - - ; GL 2.0 - glAttachShader - glBindAttribLocation - glBlendEquationSeparate - glCompileShader - glCreateProgram - glCreateShader - glDeleteProgram - glDeleteShader - glDetachShader - glDisableVertexAttribArray - glDrawBuffers - glEnableVertexAttribArray - glGetActiveAttrib - glGetActiveUniform - glGetAttachedShaders - glGetAttribLocation - glGetProgramInfoLog - glGetProgramiv - glGetShaderInfoLog - glGetShaderSource - glGetShaderiv - glGetUniformLocation - glGetUniformfv - glGetUniformiv - glGetVertexAttribPointerv - glGetVertexAttribdv - glGetVertexAttribfv - glGetVertexAttribiv - glIsProgram - glIsShader - glLinkProgram - glShaderSource - glStencilFuncSeparate - glStencilMaskSeparate - glStencilOpSeparate - glUniform1f - glUniform1fv - glUniform1i - glUniform1iv - glUniform2f - glUniform2fv - glUniform2i - glUniform2iv - glUniform3f - glUniform3fv - glUniform3i - glUniform3iv - glUniform4f - glUniform4fv - glUniform4i - glUniform4iv - glUniformMatrix2fv - glUniformMatrix3fv - glUniformMatrix4fv - glUseProgram - glValidateProgram - glVertexAttrib1d - glVertexAttrib1dv - glVertexAttrib1f - glVertexAttrib1fv - glVertexAttrib1s - glVertexAttrib1sv - glVertexAttrib2d - glVertexAttrib2dv - glVertexAttrib2f - glVertexAttrib2fv - glVertexAttrib2s - glVertexAttrib2sv - glVertexAttrib3d - glVertexAttrib3dv - glVertexAttrib3f - glVertexAttrib3fv - glVertexAttrib3s - glVertexAttrib3sv - glVertexAttrib4Nbv - glVertexAttrib4Niv - glVertexAttrib4Nsv - glVertexAttrib4Nub - glVertexAttrib4Nubv - glVertexAttrib4Nuiv - glVertexAttrib4Nusv - glVertexAttrib4bv - glVertexAttrib4d - glVertexAttrib4dv - glVertexAttrib4f - glVertexAttrib4fv - glVertexAttrib4iv - glVertexAttrib4s - glVertexAttrib4sv - glVertexAttrib4ubv - glVertexAttrib4uiv - glVertexAttrib4usv - glVertexAttribPointer - - ; GL 2.1 - glUniformMatrix2x3fv - glUniformMatrix2x4fv - glUniformMatrix3x2fv - glUniformMatrix3x4fv - glUniformMatrix4x2fv - glUniformMatrix4x3fv - - ; GL 3.0 - glBeginConditionalRender - glBeginTransformFeedback - glBindBufferBase - glBindBufferRange - glBindFragDataLocation - glBindFramebuffer - glBindRenderbuffer - glBindVertexArray - glBlitFramebuffer - glCheckFramebufferStatus - glClampColor - glClearBufferfi - glClearBufferfv - glClearBufferiv - glClearBufferuiv - glColorMaski - glDeleteFramebuffers - glDeleteRenderbuffers - glDeleteVertexArrays - glDisablei - glEnablei - glEndConditionalRender - glEndTransformFeedback - glFlushMappedBufferRange - glFramebufferRenderbuffer - glFramebufferTexture1D - glFramebufferTexture2D - glFramebufferTexture3D - glFramebufferTextureLayer - glGenFramebuffers - glGenRenderbuffers - glGenVertexArrays - glGenerateMipmap - glGetBooleani_v - glGetFragDataLocation - glGetFramebufferAttachmentParameteriv - glGetIntegeri_v - glGetRenderbufferParameteriv - glGetStringi - glGetTexParameterIiv - glGetTexParameterIuiv - glGetTransformFeedbackVarying - glGetUniformuiv - glGetVertexAttribIiv - glGetVertexAttribIuiv - glIsEnabledi - glIsFramebuffer - glIsRenderbuffer - glIsVertexArray - glMapBufferRange - glRenderbufferStorage - glRenderbufferStorageMultisample - glTexParameterIiv - glTexParameterIuiv - glTransformFeedbackVaryings - glUniform1ui - glUniform1uiv - glUniform2ui - glUniform2uiv - glUniform3ui - glUniform3uiv - glUniform4ui - glUniform4uiv - glVertexAttribI1i - glVertexAttribI1iv - glVertexAttribI1ui - glVertexAttribI1uiv - glVertexAttribI2i - glVertexAttribI2iv - glVertexAttribI2ui - glVertexAttribI2uiv - glVertexAttribI3i - glVertexAttribI3iv - glVertexAttribI3ui - glVertexAttribI3uiv - glVertexAttribI4bv - glVertexAttribI4i - glVertexAttribI4iv - glVertexAttribI4sv - glVertexAttribI4ubv - glVertexAttribI4ui - glVertexAttribI4uiv - glVertexAttribI4usv - glVertexAttribIPointer - - ; GL 3.1 - glCopyBufferSubData - glDrawArraysInstanced - glDrawElementsInstanced - glGetActiveUniformBlockName - glGetActiveUniformBlockiv - glGetActiveUniformName - glGetActiveUniformsiv - glGetUniformBlockIndex - glGetUniformIndices - glPrimitiveRestartIndex - glTexBuffer - glUniformBlockBinding - - ; GL 3.2 - glClientWaitSync - glDeleteSync - glDrawElementsBaseVertex - glDrawElementsInstancedBaseVertex - glDrawRangeElementsBaseVertex - glFenceSync - glFramebufferTexture - glGetBufferParameteri64v - glGetInteger64i_v - glGetInteger64v - glGetMultisamplefv - glGetSynciv - glIsSync - glMultiDrawElementsBaseVertex - glProvokingVertex - glSampleMaski - glTexImage2DMultisample - glTexImage3DMultisample - glWaitSync - - ; GL 3.3 - glBindFragDataLocationIndexed - glBindSampler - glColorP3ui - glColorP3uiv - glColorP4ui - glColorP4uiv - glDeleteSamplers - glGenSamplers - glGetFragDataIndex - glGetQueryObjecti64v - glGetQueryObjectui64v - glGetSamplerParameterIiv - glGetSamplerParameterIuiv - glGetSamplerParameterfv - glGetSamplerParameteriv - glIsSampler - glMultiTexCoordP1ui - glMultiTexCoordP1uiv - glMultiTexCoordP2ui - glMultiTexCoordP2uiv - glMultiTexCoordP3ui - glMultiTexCoordP3uiv - glMultiTexCoordP4ui - glMultiTexCoordP4uiv - glNormalP3ui - glNormalP3uiv - glQueryCounter - glSamplerParameterIiv - glSamplerParameterIuiv - glSamplerParameterf - glSamplerParameterfv - glSamplerParameteri - glSamplerParameteriv - glSecondaryColorP3ui - glSecondaryColorP3uiv - glTexCoordP1ui - glTexCoordP1uiv - glTexCoordP2ui - glTexCoordP2uiv - glTexCoordP3ui - glTexCoordP3uiv - glTexCoordP4ui - glTexCoordP4uiv - glVertexAttribDivisor - glVertexAttribP1ui - glVertexAttribP1uiv - glVertexAttribP2ui - glVertexAttribP2uiv - glVertexAttribP3ui - glVertexAttribP3uiv - glVertexAttribP4ui - glVertexAttribP4uiv - glVertexP2ui - glVertexP2uiv - glVertexP3ui - glVertexP3uiv - glVertexP4ui - glVertexP4uiv - - ; GL 4.0 - glBeginQueryIndexed - glBindTransformFeedback - glBlendEquationSeparatei - glBlendEquationi - glBlendFuncSeparatei - glBlendFunci - glDeleteTransformFeedbacks - glDrawArraysIndirect - glDrawElementsIndirect - glDrawTransformFeedback - glDrawTransformFeedbackStream - glEndQueryIndexed - glGenTransformFeedbacks - glGetActiveSubroutineName - glGetActiveSubroutineUniformName - glGetActiveSubroutineUniformiv - glGetProgramStageiv - glGetQueryIndexediv - glGetSubroutineIndex - glGetSubroutineUniformLocation - glGetUniformSubroutineuiv - glGetUniformdv - glIsTransformFeedback - glMinSampleShading - glPatchParameterfv - glPatchParameteri - glPauseTransformFeedback - glResumeTransformFeedback - glUniform1d - glUniform1dv - glUniform2d - glUniform2dv - glUniform3d - glUniform3dv - glUniform4d - glUniform4dv - glUniformMatrix2dv - glUniformMatrix2x3dv - glUniformMatrix2x4dv - glUniformMatrix3dv - glUniformMatrix3x2dv - glUniformMatrix3x4dv - glUniformMatrix4dv - glUniformMatrix4x2dv - glUniformMatrix4x3dv - glUniformSubroutinesuiv - - ; GL 4.1 - glActiveShaderProgram - glBindProgramPipeline - glClearDepthf - glCreateShaderProgramv - glDeleteProgramPipelines - glDepthRangeArrayv - glDepthRangeIndexed - glDepthRangef - glGenProgramPipelines - glGetDoublei_v - glGetFloati_v - glGetProgramBinary - glGetProgramPipelineInfoLog - glGetProgramPipelineiv - glGetShaderPrecisionFormat - glGetVertexAttribLdv - glIsProgramPipeline - glProgramBinary - glProgramParameteri - glProgramParameteri - glProgramUniform1d - glProgramUniform1dv - glProgramUniform1f - glProgramUniform1fv - glProgramUniform1i - glProgramUniform1iv - glProgramUniform1ui - glProgramUniform1uiv - glProgramUniform2d - glProgramUniform2dv - glProgramUniform2f - glProgramUniform2fv - glProgramUniform2i - glProgramUniform2iv - glProgramUniform2ui - glProgramUniform2uiv - glProgramUniform3d - glProgramUniform3dv - glProgramUniform3f - glProgramUniform3fv - glProgramUniform3i - glProgramUniform3iv - glProgramUniform3ui - glProgramUniform3uiv - glProgramUniform4d - glProgramUniform4dv - glProgramUniform4f - glProgramUniform4fv - glProgramUniform4i - glProgramUniform4iv - glProgramUniform4ui - glProgramUniform4uiv - glProgramUniformMatrix2dv - glProgramUniformMatrix2fv - glProgramUniformMatrix2x3dv - glProgramUniformMatrix2x3fv - glProgramUniformMatrix2x4dv - glProgramUniformMatrix2x4fv - glProgramUniformMatrix3dv - glProgramUniformMatrix3fv - glProgramUniformMatrix3x2dv - glProgramUniformMatrix3x2fv - glProgramUniformMatrix3x4dv - glProgramUniformMatrix3x4fv - glProgramUniformMatrix4dv - glProgramUniformMatrix4fv - glProgramUniformMatrix4x2dv - glProgramUniformMatrix4x2fv - glProgramUniformMatrix4x3dv - glProgramUniformMatrix4x3fv - glReleaseShaderCompiler - glScissorArrayv - glScissorIndexed - glScissorIndexedv - glShaderBinary - glUseProgramStages - glValidateProgramPipeline - glVertexAttribL1d - glVertexAttribL1dv - glVertexAttribL2d - glVertexAttribL2dv - glVertexAttribL3d - glVertexAttribL3dv - glVertexAttribL4d - glVertexAttribL4dv - glVertexAttribLPointer - glViewportArrayv - glViewportIndexedf - glViewportIndexedfv - - ; GL 4.2 - glBindImageTexture - glDrawArraysInstancedBaseInstance - glDrawElementsInstancedBaseInstance - glDrawElementsInstancedBaseVertexBaseInstance - glDrawTransformFeedbackInstanced - glDrawTransformFeedbackStreamInstanced - glGetActiveAtomicCounterBufferiv - glGetInternalformativ - glMemoryBarrier - glTexStorage1D - glTexStorage2D - glTexStorage3D - - ; GL 4.3 - glBindVertexBuffer - glClearBufferData - glClearBufferSubData - glCopyImageSubData - glDebugMessageCallback - glDebugMessageControl - glDebugMessageInsert - glDispatchCompute - glDispatchComputeIndirect - glFramebufferParameteri - glGetDebugMessageLog - glGetFramebufferParameteriv - glGetInternalformati64v - glGetObjectLabel - glGetObjectPtrLabel - glGetProgramInterfaceiv - glGetProgramResourceIndex - glGetProgramResourceLocation - glGetProgramResourceLocationIndex - glGetProgramResourceName - glGetProgramResourceiv - glInvalidateBufferData - glInvalidateBufferSubData - glInvalidateFramebuffer - glInvalidateSubFramebuffer - glInvalidateTexImage - glInvalidateTexSubImage - glMultiDrawArraysIndirect - glMultiDrawElementsIndirect - glObjectLabel - glObjectPtrLabel - glPopDebugGroup - glPushDebugGroup - glShaderStorageBlockBinding - glTexBufferRange - glTexStorage2DMultisample - glTexStorage3DMultisample - glTextureView - glVertexAttribBinding - glVertexAttribFormat - glVertexAttribIFormat - glVertexAttribLFormat - glVertexBindingDivisor - - ; GL 4.4 - glBindBuffersBase - glBindBuffersRange - glBindImageTextures - glBindSamplers - glBindTextures - glBindVertexBuffers - glBufferStorage - glClearTexImage - glClearTexSubImage - - ; GL 4.5 - glBindTextureUnit - glBlitNamedFramebuffer - glCheckNamedFramebufferStatus - glClearNamedBufferData - glClearNamedBufferSubData - glClearNamedFramebufferfi - glClearNamedFramebufferfv - glClearNamedFramebufferiv - glClearNamedFramebufferuiv - glClipControl - glCompressedTextureSubImage1D - glCompressedTextureSubImage2D - glCompressedTextureSubImage3D - glCopyNamedBufferSubData - glCopyTextureSubImage1D - glCopyTextureSubImage2D - glCopyTextureSubImage3D - glCreateBuffers - glCreateFramebuffers - glCreateProgramPipelines - glCreateQueries - glCreateRenderbuffers - glCreateSamplers - glCreateTextures - glCreateTransformFeedbacks - glCreateVertexArrays - glDisableVertexArrayAttrib - glEnableVertexArrayAttrib - glFlushMappedNamedBufferRange - glGenerateTextureMipmap - glGetCompressedTextureImage - glGetCompressedTextureSubImage - glGetGraphicsResetStatus - glGetNamedBufferParameteri64v - glGetNamedBufferParameteriv - glGetNamedBufferPointerv - glGetNamedBufferSubData - glGetNamedFramebufferAttachmentParameteriv - glGetNamedFramebufferParameteriv - glGetNamedRenderbufferParameteriv - glGetQueryBufferObjecti64v - glGetQueryBufferObjectiv - glGetQueryBufferObjectui64v - glGetQueryBufferObjectuiv - glGetTextureImage - glGetTextureLevelParameterfv - glGetTextureLevelParameteriv - glGetTextureParameterIiv - glGetTextureParameterIuiv - glGetTextureParameterfv - glGetTextureParameteriv - glGetTextureSubImage - glGetTransformFeedbacki64_v - glGetTransformFeedbacki_v - glGetTransformFeedbackiv - glGetVertexArrayIndexed64iv - glGetVertexArrayIndexediv - glGetVertexArrayiv - glGetnColorTable - glGetnCompressedTexImage - glGetnConvolutionFilter - glGetnHistogram - glGetnMapdv - glGetnMapfv - glGetnMapiv - glGetnMinmax - glGetnPixelMapfv - glGetnPixelMapuiv - glGetnPixelMapusv - glGetnPolygonStipple - glGetnSeparableFilter - glGetnTexImage - glGetnUniformdv - glGetnUniformfv - glGetnUniformiv - glGetnUniformuiv - glInvalidateNamedFramebufferData - glInvalidateNamedFramebufferSubData - glMapNamedBuffer - glMapNamedBufferRange - glMemoryBarrierByRegion - glNamedBufferData - glNamedBufferStorage - glNamedBufferSubData - glNamedFramebufferDrawBuffer - glNamedFramebufferDrawBuffers - glNamedFramebufferParameteri - glNamedFramebufferReadBuffer - glNamedFramebufferRenderbuffer - glNamedFramebufferTexture - glNamedFramebufferTextureLayer - glNamedRenderbufferStorage - glNamedRenderbufferStorageMultisample - glReadnPixels - glTextureBarrier - glTextureBuffer - glTextureBufferRange - glTextureParameterIiv - glTextureParameterIuiv - glTextureParameterf - glTextureParameterfv - glTextureParameteri - glTextureParameteriv - glTextureStorage1D - glTextureStorage2D - glTextureStorage2DMultisample - glTextureStorage3D - glTextureStorage3DMultisample - glTextureSubImage1D - glTextureSubImage2D - glTextureSubImage3D - glTransformFeedbackBufferBase - glTransformFeedbackBufferRange - glUnmapNamedBuffer - glVertexArrayAttribBinding - glVertexArrayAttribFormat - glVertexArrayAttribIFormat - glVertexArrayAttribLFormat - glVertexArrayBindingDivisor - glVertexArrayElementBuffer - glVertexArrayVertexBuffer - glVertexArrayVertexBuffers - - ; GL 4.6 - glMultiDrawArraysIndirectCount - glMultiDrawElementsIndirectCount - glPolygonOffsetClamp - glSpecializeShader - - ; WGL 1.0 - wglChoosePixelFormat - wglCopyContext - wglCreateContext - wglCreateLayerContext - wglDeleteContext - wglDescribeLayerPlane - wglDescribePixelFormat - wglGetCurrentContext - wglGetCurrentDC - wglGetEnhMetaFilePixelFormat - wglGetLayerPaletteEntries - wglGetPixelFormat - wglGetProcAddress - wglMakeCurrent - wglRealizeLayerPalette - wglSetLayerPaletteEntries - wglSetPixelFormat - wglShareLists - wglSwapBuffers - wglSwapLayerBuffers - wglUseFontBitmapsA - wglUseFontBitmapsW - wglUseFontOutlinesA - wglUseFontOutlinesW diff --git a/src/libGLESv2/proc_table_cl_autogen.cpp b/src/libGLESv2/proc_table_cl_autogen.cpp index 3f36b408d03..0d3ad2d6683 100644 --- a/src/libGLESv2/proc_table_cl_autogen.cpp +++ b/src/libGLESv2/proc_table_cl_autogen.cpp @@ -141,7 +141,12 @@ const ProcTable &GetProcTable() {"clSetContextDestructorCallback", P(::cl::clSetContextDestructorCallback)}, {"clCreateBufferWithProperties", P(::cl::clCreateBufferWithProperties)}, {"clCreateImageWithProperties", P(::cl::clCreateImageWithProperties)}, - {"clIcdGetPlatformIDsKHR", P(::cl::clIcdGetPlatformIDsKHR)}}); + {"clImportMemoryARM", P(::cl::clImportMemoryARM)}, + {"clEnqueueAcquireExternalMemObjectsKHR", P(::cl::clEnqueueAcquireExternalMemObjectsKHR)}, + {"clEnqueueReleaseExternalMemObjectsKHR", P(::cl::clEnqueueReleaseExternalMemObjectsKHR)}, + {"clIcdGetFunctionAddressForPlatformKHR", P(::cl::clIcdGetFunctionAddressForPlatformKHR)}, + {"clIcdGetPlatformIDsKHR", P(::cl::clIcdGetPlatformIDsKHR)}, + {"clIcdSetPlatformDispatchDataKHR", P(::cl::clIcdSetPlatformDispatchDataKHR)}}); return *sProcTable; } diff --git a/src/libGLESv2/proc_table_glx_autogen.cpp b/src/libGLESv2/proc_table_glx_autogen.cpp deleted file mode 100644 index d751189eb35..00000000000 --- a/src/libGLESv2/proc_table_glx_autogen.cpp +++ /dev/null @@ -1,1570 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_proc_table.py using data from gl.xml, gl_angle_ext.xml, glx.xml. -// -// Copyright 2019 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. -// -// getProcAddress loader table: -// Mapping from a string entry point name to function address. -// - -#include "libGLESv2/proc_table_glx.h" - -#include "libGLESv2/entry_points_egl_ext_autogen.h" -#include "libGLESv2/entry_points_gl_1_autogen.h" -#include "libGLESv2/entry_points_gl_2_autogen.h" -#include "libGLESv2/entry_points_gl_3_autogen.h" -#include "libGLESv2/entry_points_gl_4_autogen.h" -#include "libGLESv2/entry_points_gles_1_0_autogen.h" -#include "libGLESv2/entry_points_gles_2_0_autogen.h" -#include "libGLESv2/entry_points_gles_3_0_autogen.h" -#include "libGLESv2/entry_points_gles_3_1_autogen.h" -#include "libGLESv2/entry_points_gles_3_2_autogen.h" -#include "libGLESv2/entry_points_gles_ext_autogen.h" -#include "libGLESv2/entry_points_glx.h" -#include "platform/PlatformMethods.h" - -#include - -#define P(FUNC) reinterpret_cast<__GLXextFuncPtr>(FUNC) - -namespace glx -{ -// clang-format off -const ProcEntry g_procTable[] = { - {"ANGLEGetDisplayPlatform", P(ANGLEGetDisplayPlatform)}, - {"ANGLEResetDisplayPlatform", P(ANGLEResetDisplayPlatform)}, - {"glAccum", P(GL_Accum)}, - {"glAcquireTexturesANGLE", P(GL_AcquireTexturesANGLE)}, - {"glActiveShaderProgram", P(GL_ActiveShaderProgram)}, - {"glActiveShaderProgramEXT", P(GL_ActiveShaderProgramEXT)}, - {"glActiveTexture", P(GL_ActiveTexture)}, - {"glAlphaFunc", P(GL_AlphaFunc)}, - {"glAlphaFuncx", P(GL_AlphaFuncx)}, - {"glAreTexturesResident", P(GL_AreTexturesResident)}, - {"glArrayElement", P(GL_ArrayElement)}, - {"glAttachShader", P(GL_AttachShader)}, - {"glBegin", P(GL_Begin)}, - {"glBeginConditionalRender", P(GL_BeginConditionalRender)}, - {"glBeginPerfMonitorAMD", P(GL_BeginPerfMonitorAMD)}, - {"glBeginPixelLocalStorageANGLE", P(GL_BeginPixelLocalStorageANGLE)}, - {"glBeginQuery", P(GL_BeginQuery)}, - {"glBeginQueryEXT", P(GL_BeginQueryEXT)}, - {"glBeginQueryIndexed", P(GL_BeginQueryIndexed)}, - {"glBeginTransformFeedback", P(GL_BeginTransformFeedback)}, - {"glBindAttribLocation", P(GL_BindAttribLocation)}, - {"glBindBuffer", P(GL_BindBuffer)}, - {"glBindBufferBase", P(GL_BindBufferBase)}, - {"glBindBufferRange", P(GL_BindBufferRange)}, - {"glBindBuffersBase", P(GL_BindBuffersBase)}, - {"glBindBuffersRange", P(GL_BindBuffersRange)}, - {"glBindFragDataLocation", P(GL_BindFragDataLocation)}, - {"glBindFragDataLocationEXT", P(GL_BindFragDataLocationEXT)}, - {"glBindFragDataLocationIndexed", P(GL_BindFragDataLocationIndexed)}, - {"glBindFragDataLocationIndexedEXT", P(GL_BindFragDataLocationIndexedEXT)}, - {"glBindFramebuffer", P(GL_BindFramebuffer)}, - {"glBindFramebufferOES", P(GL_BindFramebufferOES)}, - {"glBindImageTexture", P(GL_BindImageTexture)}, - {"glBindImageTextures", P(GL_BindImageTextures)}, - {"glBindProgramPipeline", P(GL_BindProgramPipeline)}, - {"glBindProgramPipelineEXT", P(GL_BindProgramPipelineEXT)}, - {"glBindRenderbuffer", P(GL_BindRenderbuffer)}, - {"glBindRenderbufferOES", P(GL_BindRenderbufferOES)}, - {"glBindSampler", P(GL_BindSampler)}, - {"glBindSamplers", P(GL_BindSamplers)}, - {"glBindTexture", P(GL_BindTexture)}, - {"glBindTextureUnit", P(GL_BindTextureUnit)}, - {"glBindTextures", P(GL_BindTextures)}, - {"glBindTransformFeedback", P(GL_BindTransformFeedback)}, - {"glBindUniformLocationCHROMIUM", P(GL_BindUniformLocationCHROMIUM)}, - {"glBindVertexArray", P(GL_BindVertexArray)}, - {"glBindVertexArrayOES", P(GL_BindVertexArrayOES)}, - {"glBindVertexBuffer", P(GL_BindVertexBuffer)}, - {"glBindVertexBuffers", P(GL_BindVertexBuffers)}, - {"glBitmap", P(GL_Bitmap)}, - {"glBlendBarrier", P(GL_BlendBarrier)}, - {"glBlendBarrierKHR", P(GL_BlendBarrierKHR)}, - {"glBlendColor", P(GL_BlendColor)}, - {"glBlendEquation", P(GL_BlendEquation)}, - {"glBlendEquationSeparate", P(GL_BlendEquationSeparate)}, - {"glBlendEquationSeparatei", P(GL_BlendEquationSeparatei)}, - {"glBlendEquationSeparateiEXT", P(GL_BlendEquationSeparateiEXT)}, - {"glBlendEquationSeparateiOES", P(GL_BlendEquationSeparateiOES)}, - {"glBlendEquationi", P(GL_BlendEquationi)}, - {"glBlendEquationiEXT", P(GL_BlendEquationiEXT)}, - {"glBlendEquationiOES", P(GL_BlendEquationiOES)}, - {"glBlendFunc", P(GL_BlendFunc)}, - {"glBlendFuncSeparate", P(GL_BlendFuncSeparate)}, - {"glBlendFuncSeparatei", P(GL_BlendFuncSeparatei)}, - {"glBlendFuncSeparateiEXT", P(GL_BlendFuncSeparateiEXT)}, - {"glBlendFuncSeparateiOES", P(GL_BlendFuncSeparateiOES)}, - {"glBlendFunci", P(GL_BlendFunci)}, - {"glBlendFunciEXT", P(GL_BlendFunciEXT)}, - {"glBlendFunciOES", P(GL_BlendFunciOES)}, - {"glBlitFramebuffer", P(GL_BlitFramebuffer)}, - {"glBlitFramebufferANGLE", P(GL_BlitFramebufferANGLE)}, - {"glBlitFramebufferNV", P(GL_BlitFramebufferNV)}, - {"glBlitNamedFramebuffer", P(GL_BlitNamedFramebuffer)}, - {"glBufferData", P(GL_BufferData)}, - {"glBufferStorage", P(GL_BufferStorage)}, - {"glBufferStorageEXT", P(GL_BufferStorageEXT)}, - {"glBufferStorageExternalEXT", P(GL_BufferStorageExternalEXT)}, - {"glBufferStorageMemEXT", P(GL_BufferStorageMemEXT)}, - {"glBufferSubData", P(GL_BufferSubData)}, - {"glCallList", P(GL_CallList)}, - {"glCallLists", P(GL_CallLists)}, - {"glCheckFramebufferStatus", P(GL_CheckFramebufferStatus)}, - {"glCheckFramebufferStatusOES", P(GL_CheckFramebufferStatusOES)}, - {"glCheckNamedFramebufferStatus", P(GL_CheckNamedFramebufferStatus)}, - {"glClampColor", P(GL_ClampColor)}, - {"glClear", P(GL_Clear)}, - {"glClearAccum", P(GL_ClearAccum)}, - {"glClearBufferData", P(GL_ClearBufferData)}, - {"glClearBufferSubData", P(GL_ClearBufferSubData)}, - {"glClearBufferfi", P(GL_ClearBufferfi)}, - {"glClearBufferfv", P(GL_ClearBufferfv)}, - {"glClearBufferiv", P(GL_ClearBufferiv)}, - {"glClearBufferuiv", P(GL_ClearBufferuiv)}, - {"glClearColor", P(GL_ClearColor)}, - {"glClearColorx", P(GL_ClearColorx)}, - {"glClearDepth", P(GL_ClearDepth)}, - {"glClearDepthf", P(GL_ClearDepthf)}, - {"glClearDepthx", P(GL_ClearDepthx)}, - {"glClearIndex", P(GL_ClearIndex)}, - {"glClearNamedBufferData", P(GL_ClearNamedBufferData)}, - {"glClearNamedBufferSubData", P(GL_ClearNamedBufferSubData)}, - {"glClearNamedFramebufferfi", P(GL_ClearNamedFramebufferfi)}, - {"glClearNamedFramebufferfv", P(GL_ClearNamedFramebufferfv)}, - {"glClearNamedFramebufferiv", P(GL_ClearNamedFramebufferiv)}, - {"glClearNamedFramebufferuiv", P(GL_ClearNamedFramebufferuiv)}, - {"glClearStencil", P(GL_ClearStencil)}, - {"glClearTexImage", P(GL_ClearTexImage)}, - {"glClearTexImageEXT", P(GL_ClearTexImageEXT)}, - {"glClearTexSubImage", P(GL_ClearTexSubImage)}, - {"glClearTexSubImageEXT", P(GL_ClearTexSubImageEXT)}, - {"glClientActiveTexture", P(GL_ClientActiveTexture)}, - {"glClientWaitSync", P(GL_ClientWaitSync)}, - {"glClipControl", P(GL_ClipControl)}, - {"glClipControlEXT", P(GL_ClipControlEXT)}, - {"glClipPlane", P(GL_ClipPlane)}, - {"glClipPlanef", P(GL_ClipPlanef)}, - {"glClipPlanex", P(GL_ClipPlanex)}, - {"glColor3b", P(GL_Color3b)}, - {"glColor3bv", P(GL_Color3bv)}, - {"glColor3d", P(GL_Color3d)}, - {"glColor3dv", P(GL_Color3dv)}, - {"glColor3f", P(GL_Color3f)}, - {"glColor3fv", P(GL_Color3fv)}, - {"glColor3i", P(GL_Color3i)}, - {"glColor3iv", P(GL_Color3iv)}, - {"glColor3s", P(GL_Color3s)}, - {"glColor3sv", P(GL_Color3sv)}, - {"glColor3ub", P(GL_Color3ub)}, - {"glColor3ubv", P(GL_Color3ubv)}, - {"glColor3ui", P(GL_Color3ui)}, - {"glColor3uiv", P(GL_Color3uiv)}, - {"glColor3us", P(GL_Color3us)}, - {"glColor3usv", P(GL_Color3usv)}, - {"glColor4b", P(GL_Color4b)}, - {"glColor4bv", P(GL_Color4bv)}, - {"glColor4d", P(GL_Color4d)}, - {"glColor4dv", P(GL_Color4dv)}, - {"glColor4f", P(GL_Color4f)}, - {"glColor4fv", P(GL_Color4fv)}, - {"glColor4i", P(GL_Color4i)}, - {"glColor4iv", P(GL_Color4iv)}, - {"glColor4s", P(GL_Color4s)}, - {"glColor4sv", P(GL_Color4sv)}, - {"glColor4ub", P(GL_Color4ub)}, - {"glColor4ubv", P(GL_Color4ubv)}, - {"glColor4ui", P(GL_Color4ui)}, - {"glColor4uiv", P(GL_Color4uiv)}, - {"glColor4us", P(GL_Color4us)}, - {"glColor4usv", P(GL_Color4usv)}, - {"glColor4x", P(GL_Color4x)}, - {"glColorMask", P(GL_ColorMask)}, - {"glColorMaski", P(GL_ColorMaski)}, - {"glColorMaskiEXT", P(GL_ColorMaskiEXT)}, - {"glColorMaskiOES", P(GL_ColorMaskiOES)}, - {"glColorMaterial", P(GL_ColorMaterial)}, - {"glColorP3ui", P(GL_ColorP3ui)}, - {"glColorP3uiv", P(GL_ColorP3uiv)}, - {"glColorP4ui", P(GL_ColorP4ui)}, - {"glColorP4uiv", P(GL_ColorP4uiv)}, - {"glColorPointer", P(GL_ColorPointer)}, - {"glCompileShader", P(GL_CompileShader)}, - {"glCompressedCopyTextureCHROMIUM", P(GL_CompressedCopyTextureCHROMIUM)}, - {"glCompressedTexImage1D", P(GL_CompressedTexImage1D)}, - {"glCompressedTexImage2D", P(GL_CompressedTexImage2D)}, - {"glCompressedTexImage2DRobustANGLE", P(GL_CompressedTexImage2DRobustANGLE)}, - {"glCompressedTexImage3D", P(GL_CompressedTexImage3D)}, - {"glCompressedTexImage3DOES", P(GL_CompressedTexImage3DOES)}, - {"glCompressedTexImage3DRobustANGLE", P(GL_CompressedTexImage3DRobustANGLE)}, - {"glCompressedTexSubImage1D", P(GL_CompressedTexSubImage1D)}, - {"glCompressedTexSubImage2D", P(GL_CompressedTexSubImage2D)}, - {"glCompressedTexSubImage2DRobustANGLE", P(GL_CompressedTexSubImage2DRobustANGLE)}, - {"glCompressedTexSubImage3D", P(GL_CompressedTexSubImage3D)}, - {"glCompressedTexSubImage3DOES", P(GL_CompressedTexSubImage3DOES)}, - {"glCompressedTexSubImage3DRobustANGLE", P(GL_CompressedTexSubImage3DRobustANGLE)}, - {"glCompressedTextureSubImage1D", P(GL_CompressedTextureSubImage1D)}, - {"glCompressedTextureSubImage2D", P(GL_CompressedTextureSubImage2D)}, - {"glCompressedTextureSubImage3D", P(GL_CompressedTextureSubImage3D)}, - {"glCopyBufferSubData", P(GL_CopyBufferSubData)}, - {"glCopyImageSubData", P(GL_CopyImageSubData)}, - {"glCopyImageSubDataEXT", P(GL_CopyImageSubDataEXT)}, - {"glCopyImageSubDataOES", P(GL_CopyImageSubDataOES)}, - {"glCopyNamedBufferSubData", P(GL_CopyNamedBufferSubData)}, - {"glCopyPixels", P(GL_CopyPixels)}, - {"glCopySubTexture3DANGLE", P(GL_CopySubTexture3DANGLE)}, - {"glCopySubTextureCHROMIUM", P(GL_CopySubTextureCHROMIUM)}, - {"glCopyTexImage1D", P(GL_CopyTexImage1D)}, - {"glCopyTexImage2D", P(GL_CopyTexImage2D)}, - {"glCopyTexSubImage1D", P(GL_CopyTexSubImage1D)}, - {"glCopyTexSubImage2D", P(GL_CopyTexSubImage2D)}, - {"glCopyTexSubImage3D", P(GL_CopyTexSubImage3D)}, - {"glCopyTexSubImage3DOES", P(GL_CopyTexSubImage3DOES)}, - {"glCopyTexture3DANGLE", P(GL_CopyTexture3DANGLE)}, - {"glCopyTextureCHROMIUM", P(GL_CopyTextureCHROMIUM)}, - {"glCopyTextureSubImage1D", P(GL_CopyTextureSubImage1D)}, - {"glCopyTextureSubImage2D", P(GL_CopyTextureSubImage2D)}, - {"glCopyTextureSubImage3D", P(GL_CopyTextureSubImage3D)}, - {"glCoverageModulationCHROMIUM", P(GL_CoverageModulationCHROMIUM)}, - {"glCreateBuffers", P(GL_CreateBuffers)}, - {"glCreateFramebuffers", P(GL_CreateFramebuffers)}, - {"glCreateMemoryObjectsEXT", P(GL_CreateMemoryObjectsEXT)}, - {"glCreateProgram", P(GL_CreateProgram)}, - {"glCreateProgramPipelines", P(GL_CreateProgramPipelines)}, - {"glCreateQueries", P(GL_CreateQueries)}, - {"glCreateRenderbuffers", P(GL_CreateRenderbuffers)}, - {"glCreateSamplers", P(GL_CreateSamplers)}, - {"glCreateShader", P(GL_CreateShader)}, - {"glCreateShaderProgramv", P(GL_CreateShaderProgramv)}, - {"glCreateShaderProgramvEXT", P(GL_CreateShaderProgramvEXT)}, - {"glCreateTextures", P(GL_CreateTextures)}, - {"glCreateTransformFeedbacks", P(GL_CreateTransformFeedbacks)}, - {"glCreateVertexArrays", P(GL_CreateVertexArrays)}, - {"glCullFace", P(GL_CullFace)}, - {"glCurrentPaletteMatrixOES", P(GL_CurrentPaletteMatrixOES)}, - {"glDebugMessageCallback", P(GL_DebugMessageCallback)}, - {"glDebugMessageCallbackKHR", P(GL_DebugMessageCallbackKHR)}, - {"glDebugMessageControl", P(GL_DebugMessageControl)}, - {"glDebugMessageControlKHR", P(GL_DebugMessageControlKHR)}, - {"glDebugMessageInsert", P(GL_DebugMessageInsert)}, - {"glDebugMessageInsertKHR", P(GL_DebugMessageInsertKHR)}, - {"glDeleteBuffers", P(GL_DeleteBuffers)}, - {"glDeleteFencesNV", P(GL_DeleteFencesNV)}, - {"glDeleteFramebuffers", P(GL_DeleteFramebuffers)}, - {"glDeleteFramebuffersOES", P(GL_DeleteFramebuffersOES)}, - {"glDeleteLists", P(GL_DeleteLists)}, - {"glDeleteMemoryObjectsEXT", P(GL_DeleteMemoryObjectsEXT)}, - {"glDeletePerfMonitorsAMD", P(GL_DeletePerfMonitorsAMD)}, - {"glDeleteProgram", P(GL_DeleteProgram)}, - {"glDeleteProgramPipelines", P(GL_DeleteProgramPipelines)}, - {"glDeleteProgramPipelinesEXT", P(GL_DeleteProgramPipelinesEXT)}, - {"glDeleteQueries", P(GL_DeleteQueries)}, - {"glDeleteQueriesEXT", P(GL_DeleteQueriesEXT)}, - {"glDeleteRenderbuffers", P(GL_DeleteRenderbuffers)}, - {"glDeleteRenderbuffersOES", P(GL_DeleteRenderbuffersOES)}, - {"glDeleteSamplers", P(GL_DeleteSamplers)}, - {"glDeleteSemaphoresEXT", P(GL_DeleteSemaphoresEXT)}, - {"glDeleteShader", P(GL_DeleteShader)}, - {"glDeleteSync", P(GL_DeleteSync)}, - {"glDeleteTextures", P(GL_DeleteTextures)}, - {"glDeleteTransformFeedbacks", P(GL_DeleteTransformFeedbacks)}, - {"glDeleteVertexArrays", P(GL_DeleteVertexArrays)}, - {"glDeleteVertexArraysOES", P(GL_DeleteVertexArraysOES)}, - {"glDepthFunc", P(GL_DepthFunc)}, - {"glDepthMask", P(GL_DepthMask)}, - {"glDepthRange", P(GL_DepthRange)}, - {"glDepthRangeArrayv", P(GL_DepthRangeArrayv)}, - {"glDepthRangeIndexed", P(GL_DepthRangeIndexed)}, - {"glDepthRangef", P(GL_DepthRangef)}, - {"glDepthRangex", P(GL_DepthRangex)}, - {"glDetachShader", P(GL_DetachShader)}, - {"glDisable", P(GL_Disable)}, - {"glDisableClientState", P(GL_DisableClientState)}, - {"glDisableExtensionANGLE", P(GL_DisableExtensionANGLE)}, - {"glDisableVertexArrayAttrib", P(GL_DisableVertexArrayAttrib)}, - {"glDisableVertexAttribArray", P(GL_DisableVertexAttribArray)}, - {"glDisablei", P(GL_Disablei)}, - {"glDisableiEXT", P(GL_DisableiEXT)}, - {"glDisableiOES", P(GL_DisableiOES)}, - {"glDiscardFramebufferEXT", P(GL_DiscardFramebufferEXT)}, - {"glDispatchCompute", P(GL_DispatchCompute)}, - {"glDispatchComputeIndirect", P(GL_DispatchComputeIndirect)}, - {"glDrawArrays", P(GL_DrawArrays)}, - {"glDrawArraysIndirect", P(GL_DrawArraysIndirect)}, - {"glDrawArraysInstanced", P(GL_DrawArraysInstanced)}, - {"glDrawArraysInstancedANGLE", P(GL_DrawArraysInstancedANGLE)}, - {"glDrawArraysInstancedBaseInstance", P(GL_DrawArraysInstancedBaseInstance)}, - {"glDrawArraysInstancedBaseInstanceANGLE", P(GL_DrawArraysInstancedBaseInstanceANGLE)}, - {"glDrawArraysInstancedBaseInstanceEXT", P(GL_DrawArraysInstancedBaseInstanceEXT)}, - {"glDrawArraysInstancedEXT", P(GL_DrawArraysInstancedEXT)}, - {"glDrawBuffer", P(GL_DrawBuffer)}, - {"glDrawBuffers", P(GL_DrawBuffers)}, - {"glDrawBuffersEXT", P(GL_DrawBuffersEXT)}, - {"glDrawElements", P(GL_DrawElements)}, - {"glDrawElementsBaseVertex", P(GL_DrawElementsBaseVertex)}, - {"glDrawElementsBaseVertexEXT", P(GL_DrawElementsBaseVertexEXT)}, - {"glDrawElementsBaseVertexOES", P(GL_DrawElementsBaseVertexOES)}, - {"glDrawElementsIndirect", P(GL_DrawElementsIndirect)}, - {"glDrawElementsInstanced", P(GL_DrawElementsInstanced)}, - {"glDrawElementsInstancedANGLE", P(GL_DrawElementsInstancedANGLE)}, - {"glDrawElementsInstancedBaseInstance", P(GL_DrawElementsInstancedBaseInstance)}, - {"glDrawElementsInstancedBaseInstanceEXT", P(GL_DrawElementsInstancedBaseInstanceEXT)}, - {"glDrawElementsInstancedBaseVertex", P(GL_DrawElementsInstancedBaseVertex)}, - {"glDrawElementsInstancedBaseVertexBaseInstance", P(GL_DrawElementsInstancedBaseVertexBaseInstance)}, - {"glDrawElementsInstancedBaseVertexBaseInstanceANGLE", P(GL_DrawElementsInstancedBaseVertexBaseInstanceANGLE)}, - {"glDrawElementsInstancedBaseVertexBaseInstanceEXT", P(GL_DrawElementsInstancedBaseVertexBaseInstanceEXT)}, - {"glDrawElementsInstancedBaseVertexEXT", P(GL_DrawElementsInstancedBaseVertexEXT)}, - {"glDrawElementsInstancedBaseVertexOES", P(GL_DrawElementsInstancedBaseVertexOES)}, - {"glDrawElementsInstancedEXT", P(GL_DrawElementsInstancedEXT)}, - {"glDrawPixels", P(GL_DrawPixels)}, - {"glDrawRangeElements", P(GL_DrawRangeElements)}, - {"glDrawRangeElementsBaseVertex", P(GL_DrawRangeElementsBaseVertex)}, - {"glDrawRangeElementsBaseVertexEXT", P(GL_DrawRangeElementsBaseVertexEXT)}, - {"glDrawRangeElementsBaseVertexOES", P(GL_DrawRangeElementsBaseVertexOES)}, - {"glDrawTexfOES", P(GL_DrawTexfOES)}, - {"glDrawTexfvOES", P(GL_DrawTexfvOES)}, - {"glDrawTexiOES", P(GL_DrawTexiOES)}, - {"glDrawTexivOES", P(GL_DrawTexivOES)}, - {"glDrawTexsOES", P(GL_DrawTexsOES)}, - {"glDrawTexsvOES", P(GL_DrawTexsvOES)}, - {"glDrawTexxOES", P(GL_DrawTexxOES)}, - {"glDrawTexxvOES", P(GL_DrawTexxvOES)}, - {"glDrawTransformFeedback", P(GL_DrawTransformFeedback)}, - {"glDrawTransformFeedbackInstanced", P(GL_DrawTransformFeedbackInstanced)}, - {"glDrawTransformFeedbackStream", P(GL_DrawTransformFeedbackStream)}, - {"glDrawTransformFeedbackStreamInstanced", P(GL_DrawTransformFeedbackStreamInstanced)}, - {"glEGLImageTargetRenderbufferStorageOES", P(GL_EGLImageTargetRenderbufferStorageOES)}, - {"glEGLImageTargetTexStorageEXT", P(GL_EGLImageTargetTexStorageEXT)}, - {"glEGLImageTargetTexture2DOES", P(GL_EGLImageTargetTexture2DOES)}, - {"glEGLImageTargetTextureStorageEXT", P(GL_EGLImageTargetTextureStorageEXT)}, - {"glEdgeFlag", P(GL_EdgeFlag)}, - {"glEdgeFlagPointer", P(GL_EdgeFlagPointer)}, - {"glEdgeFlagv", P(GL_EdgeFlagv)}, - {"glEnable", P(GL_Enable)}, - {"glEnableClientState", P(GL_EnableClientState)}, - {"glEnableVertexArrayAttrib", P(GL_EnableVertexArrayAttrib)}, - {"glEnableVertexAttribArray", P(GL_EnableVertexAttribArray)}, - {"glEnablei", P(GL_Enablei)}, - {"glEnableiEXT", P(GL_EnableiEXT)}, - {"glEnableiOES", P(GL_EnableiOES)}, - {"glEnd", P(GL_End)}, - {"glEndConditionalRender", P(GL_EndConditionalRender)}, - {"glEndList", P(GL_EndList)}, - {"glEndPerfMonitorAMD", P(GL_EndPerfMonitorAMD)}, - {"glEndPixelLocalStorageANGLE", P(GL_EndPixelLocalStorageANGLE)}, - {"glEndQuery", P(GL_EndQuery)}, - {"glEndQueryEXT", P(GL_EndQueryEXT)}, - {"glEndQueryIndexed", P(GL_EndQueryIndexed)}, - {"glEndTilingQCOM", P(GL_EndTilingQCOM)}, - {"glEndTransformFeedback", P(GL_EndTransformFeedback)}, - {"glEvalCoord1d", P(GL_EvalCoord1d)}, - {"glEvalCoord1dv", P(GL_EvalCoord1dv)}, - {"glEvalCoord1f", P(GL_EvalCoord1f)}, - {"glEvalCoord1fv", P(GL_EvalCoord1fv)}, - {"glEvalCoord2d", P(GL_EvalCoord2d)}, - {"glEvalCoord2dv", P(GL_EvalCoord2dv)}, - {"glEvalCoord2f", P(GL_EvalCoord2f)}, - {"glEvalCoord2fv", P(GL_EvalCoord2fv)}, - {"glEvalMesh1", P(GL_EvalMesh1)}, - {"glEvalMesh2", P(GL_EvalMesh2)}, - {"glEvalPoint1", P(GL_EvalPoint1)}, - {"glEvalPoint2", P(GL_EvalPoint2)}, - {"glFeedbackBuffer", P(GL_FeedbackBuffer)}, - {"glFenceSync", P(GL_FenceSync)}, - {"glFinish", P(GL_Finish)}, - {"glFinishFenceNV", P(GL_FinishFenceNV)}, - {"glFlush", P(GL_Flush)}, - {"glFlushMappedBufferRange", P(GL_FlushMappedBufferRange)}, - {"glFlushMappedBufferRangeEXT", P(GL_FlushMappedBufferRangeEXT)}, - {"glFlushMappedNamedBufferRange", P(GL_FlushMappedNamedBufferRange)}, - {"glFogCoordPointer", P(GL_FogCoordPointer)}, - {"glFogCoordd", P(GL_FogCoordd)}, - {"glFogCoorddv", P(GL_FogCoorddv)}, - {"glFogCoordf", P(GL_FogCoordf)}, - {"glFogCoordfv", P(GL_FogCoordfv)}, - {"glFogf", P(GL_Fogf)}, - {"glFogfv", P(GL_Fogfv)}, - {"glFogi", P(GL_Fogi)}, - {"glFogiv", P(GL_Fogiv)}, - {"glFogx", P(GL_Fogx)}, - {"glFogxv", P(GL_Fogxv)}, - {"glFramebufferFetchBarrierEXT", P(GL_FramebufferFetchBarrierEXT)}, - {"glFramebufferFoveationConfigQCOM", P(GL_FramebufferFoveationConfigQCOM)}, - {"glFramebufferFoveationParametersQCOM", P(GL_FramebufferFoveationParametersQCOM)}, - {"glFramebufferMemorylessPixelLocalStorageANGLE", P(GL_FramebufferMemorylessPixelLocalStorageANGLE)}, - {"glFramebufferParameteri", P(GL_FramebufferParameteri)}, - {"glFramebufferParameteriMESA", P(GL_FramebufferParameteriMESA)}, - {"glFramebufferPixelLocalClearValuefvANGLE", P(GL_FramebufferPixelLocalClearValuefvANGLE)}, - {"glFramebufferPixelLocalClearValueivANGLE", P(GL_FramebufferPixelLocalClearValueivANGLE)}, - {"glFramebufferPixelLocalClearValueuivANGLE", P(GL_FramebufferPixelLocalClearValueuivANGLE)}, - {"glFramebufferPixelLocalStorageInterruptANGLE", P(GL_FramebufferPixelLocalStorageInterruptANGLE)}, - {"glFramebufferPixelLocalStorageRestoreANGLE", P(GL_FramebufferPixelLocalStorageRestoreANGLE)}, - {"glFramebufferRenderbuffer", P(GL_FramebufferRenderbuffer)}, - {"glFramebufferRenderbufferOES", P(GL_FramebufferRenderbufferOES)}, - {"glFramebufferTexture", P(GL_FramebufferTexture)}, - {"glFramebufferTexture1D", P(GL_FramebufferTexture1D)}, - {"glFramebufferTexture2D", P(GL_FramebufferTexture2D)}, - {"glFramebufferTexture2DMultisampleEXT", P(GL_FramebufferTexture2DMultisampleEXT)}, - {"glFramebufferTexture2DOES", P(GL_FramebufferTexture2DOES)}, - {"glFramebufferTexture3D", P(GL_FramebufferTexture3D)}, - {"glFramebufferTexture3DOES", P(GL_FramebufferTexture3DOES)}, - {"glFramebufferTextureEXT", P(GL_FramebufferTextureEXT)}, - {"glFramebufferTextureLayer", P(GL_FramebufferTextureLayer)}, - {"glFramebufferTextureMultiviewOVR", P(GL_FramebufferTextureMultiviewOVR)}, - {"glFramebufferTextureOES", P(GL_FramebufferTextureOES)}, - {"glFramebufferTexturePixelLocalStorageANGLE", P(GL_FramebufferTexturePixelLocalStorageANGLE)}, - {"glFrontFace", P(GL_FrontFace)}, - {"glFrustum", P(GL_Frustum)}, - {"glFrustumf", P(GL_Frustumf)}, - {"glFrustumx", P(GL_Frustumx)}, - {"glGenBuffers", P(GL_GenBuffers)}, - {"glGenFencesNV", P(GL_GenFencesNV)}, - {"glGenFramebuffers", P(GL_GenFramebuffers)}, - {"glGenFramebuffersOES", P(GL_GenFramebuffersOES)}, - {"glGenLists", P(GL_GenLists)}, - {"glGenPerfMonitorsAMD", P(GL_GenPerfMonitorsAMD)}, - {"glGenProgramPipelines", P(GL_GenProgramPipelines)}, - {"glGenProgramPipelinesEXT", P(GL_GenProgramPipelinesEXT)}, - {"glGenQueries", P(GL_GenQueries)}, - {"glGenQueriesEXT", P(GL_GenQueriesEXT)}, - {"glGenRenderbuffers", P(GL_GenRenderbuffers)}, - {"glGenRenderbuffersOES", P(GL_GenRenderbuffersOES)}, - {"glGenSamplers", P(GL_GenSamplers)}, - {"glGenSemaphoresEXT", P(GL_GenSemaphoresEXT)}, - {"glGenTextures", P(GL_GenTextures)}, - {"glGenTransformFeedbacks", P(GL_GenTransformFeedbacks)}, - {"glGenVertexArrays", P(GL_GenVertexArrays)}, - {"glGenVertexArraysOES", P(GL_GenVertexArraysOES)}, - {"glGenerateMipmap", P(GL_GenerateMipmap)}, - {"glGenerateMipmapOES", P(GL_GenerateMipmapOES)}, - {"glGenerateTextureMipmap", P(GL_GenerateTextureMipmap)}, - {"glGetActiveAtomicCounterBufferiv", P(GL_GetActiveAtomicCounterBufferiv)}, - {"glGetActiveAttrib", P(GL_GetActiveAttrib)}, - {"glGetActiveSubroutineName", P(GL_GetActiveSubroutineName)}, - {"glGetActiveSubroutineUniformName", P(GL_GetActiveSubroutineUniformName)}, - {"glGetActiveSubroutineUniformiv", P(GL_GetActiveSubroutineUniformiv)}, - {"glGetActiveUniform", P(GL_GetActiveUniform)}, - {"glGetActiveUniformBlockName", P(GL_GetActiveUniformBlockName)}, - {"glGetActiveUniformBlockiv", P(GL_GetActiveUniformBlockiv)}, - {"glGetActiveUniformBlockivRobustANGLE", P(GL_GetActiveUniformBlockivRobustANGLE)}, - {"glGetActiveUniformName", P(GL_GetActiveUniformName)}, - {"glGetActiveUniformsiv", P(GL_GetActiveUniformsiv)}, - {"glGetAttachedShaders", P(GL_GetAttachedShaders)}, - {"glGetAttribLocation", P(GL_GetAttribLocation)}, - {"glGetBooleani_v", P(GL_GetBooleani_v)}, - {"glGetBooleani_vRobustANGLE", P(GL_GetBooleani_vRobustANGLE)}, - {"glGetBooleanv", P(GL_GetBooleanv)}, - {"glGetBooleanvRobustANGLE", P(GL_GetBooleanvRobustANGLE)}, - {"glGetBufferParameteri64v", P(GL_GetBufferParameteri64v)}, - {"glGetBufferParameteri64vRobustANGLE", P(GL_GetBufferParameteri64vRobustANGLE)}, - {"glGetBufferParameteriv", P(GL_GetBufferParameteriv)}, - {"glGetBufferParameterivRobustANGLE", P(GL_GetBufferParameterivRobustANGLE)}, - {"glGetBufferPointerv", P(GL_GetBufferPointerv)}, - {"glGetBufferPointervOES", P(GL_GetBufferPointervOES)}, - {"glGetBufferPointervRobustANGLE", P(GL_GetBufferPointervRobustANGLE)}, - {"glGetBufferSubData", P(GL_GetBufferSubData)}, - {"glGetClipPlane", P(GL_GetClipPlane)}, - {"glGetClipPlanef", P(GL_GetClipPlanef)}, - {"glGetClipPlanex", P(GL_GetClipPlanex)}, - {"glGetCompressedTexImage", P(GL_GetCompressedTexImage)}, - {"glGetCompressedTexImageANGLE", P(GL_GetCompressedTexImageANGLE)}, - {"glGetCompressedTextureImage", P(GL_GetCompressedTextureImage)}, - {"glGetCompressedTextureSubImage", P(GL_GetCompressedTextureSubImage)}, - {"glGetDebugMessageLog", P(GL_GetDebugMessageLog)}, - {"glGetDebugMessageLogKHR", P(GL_GetDebugMessageLogKHR)}, - {"glGetDoublei_v", P(GL_GetDoublei_v)}, - {"glGetDoublev", P(GL_GetDoublev)}, - {"glGetError", P(GL_GetError)}, - {"glGetFenceivNV", P(GL_GetFenceivNV)}, - {"glGetFixedv", P(GL_GetFixedv)}, - {"glGetFloati_v", P(GL_GetFloati_v)}, - {"glGetFloatv", P(GL_GetFloatv)}, - {"glGetFloatvRobustANGLE", P(GL_GetFloatvRobustANGLE)}, - {"glGetFragDataIndex", P(GL_GetFragDataIndex)}, - {"glGetFragDataIndexEXT", P(GL_GetFragDataIndexEXT)}, - {"glGetFragDataLocation", P(GL_GetFragDataLocation)}, - {"glGetFramebufferAttachmentParameteriv", P(GL_GetFramebufferAttachmentParameteriv)}, - {"glGetFramebufferAttachmentParameterivOES", P(GL_GetFramebufferAttachmentParameterivOES)}, - {"glGetFramebufferAttachmentParameterivRobustANGLE", P(GL_GetFramebufferAttachmentParameterivRobustANGLE)}, - {"glGetFramebufferParameteriv", P(GL_GetFramebufferParameteriv)}, - {"glGetFramebufferParameterivMESA", P(GL_GetFramebufferParameterivMESA)}, - {"glGetFramebufferParameterivRobustANGLE", P(GL_GetFramebufferParameterivRobustANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterfvANGLE", P(GL_GetFramebufferPixelLocalStorageParameterfvANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterfvRobustANGLE", P(GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterivANGLE", P(GL_GetFramebufferPixelLocalStorageParameterivANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterivRobustANGLE", P(GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE)}, - {"glGetGraphicsResetStatus", P(GL_GetGraphicsResetStatus)}, - {"glGetGraphicsResetStatusEXT", P(GL_GetGraphicsResetStatusEXT)}, - {"glGetGraphicsResetStatusKHR", P(GL_GetGraphicsResetStatusKHR)}, - {"glGetInteger64i_v", P(GL_GetInteger64i_v)}, - {"glGetInteger64i_vRobustANGLE", P(GL_GetInteger64i_vRobustANGLE)}, - {"glGetInteger64v", P(GL_GetInteger64v)}, - {"glGetInteger64vEXT", P(GL_GetInteger64vEXT)}, - {"glGetInteger64vRobustANGLE", P(GL_GetInteger64vRobustANGLE)}, - {"glGetIntegeri_v", P(GL_GetIntegeri_v)}, - {"glGetIntegeri_vRobustANGLE", P(GL_GetIntegeri_vRobustANGLE)}, - {"glGetIntegerv", P(GL_GetIntegerv)}, - {"glGetIntegervRobustANGLE", P(GL_GetIntegervRobustANGLE)}, - {"glGetInternalformati64v", P(GL_GetInternalformati64v)}, - {"glGetInternalformativ", P(GL_GetInternalformativ)}, - {"glGetInternalformativRobustANGLE", P(GL_GetInternalformativRobustANGLE)}, - {"glGetLightfv", P(GL_GetLightfv)}, - {"glGetLightiv", P(GL_GetLightiv)}, - {"glGetLightxv", P(GL_GetLightxv)}, - {"glGetMapdv", P(GL_GetMapdv)}, - {"glGetMapfv", P(GL_GetMapfv)}, - {"glGetMapiv", P(GL_GetMapiv)}, - {"glGetMaterialfv", P(GL_GetMaterialfv)}, - {"glGetMaterialiv", P(GL_GetMaterialiv)}, - {"glGetMaterialxv", P(GL_GetMaterialxv)}, - {"glGetMemoryObjectParameterivEXT", P(GL_GetMemoryObjectParameterivEXT)}, - {"glGetMultisamplefv", P(GL_GetMultisamplefv)}, - {"glGetMultisamplefvANGLE", P(GL_GetMultisamplefvANGLE)}, - {"glGetMultisamplefvRobustANGLE", P(GL_GetMultisamplefvRobustANGLE)}, - {"glGetNamedBufferParameteri64v", P(GL_GetNamedBufferParameteri64v)}, - {"glGetNamedBufferParameteriv", P(GL_GetNamedBufferParameteriv)}, - {"glGetNamedBufferPointerv", P(GL_GetNamedBufferPointerv)}, - {"glGetNamedBufferSubData", P(GL_GetNamedBufferSubData)}, - {"glGetNamedFramebufferAttachmentParameteriv", P(GL_GetNamedFramebufferAttachmentParameteriv)}, - {"glGetNamedFramebufferParameteriv", P(GL_GetNamedFramebufferParameteriv)}, - {"glGetNamedRenderbufferParameteriv", P(GL_GetNamedRenderbufferParameteriv)}, - {"glGetObjectLabel", P(GL_GetObjectLabel)}, - {"glGetObjectLabelEXT", P(GL_GetObjectLabelEXT)}, - {"glGetObjectLabelKHR", P(GL_GetObjectLabelKHR)}, - {"glGetObjectPtrLabel", P(GL_GetObjectPtrLabel)}, - {"glGetObjectPtrLabelKHR", P(GL_GetObjectPtrLabelKHR)}, - {"glGetPerfMonitorCounterDataAMD", P(GL_GetPerfMonitorCounterDataAMD)}, - {"glGetPerfMonitorCounterInfoAMD", P(GL_GetPerfMonitorCounterInfoAMD)}, - {"glGetPerfMonitorCounterStringAMD", P(GL_GetPerfMonitorCounterStringAMD)}, - {"glGetPerfMonitorCountersAMD", P(GL_GetPerfMonitorCountersAMD)}, - {"glGetPerfMonitorGroupStringAMD", P(GL_GetPerfMonitorGroupStringAMD)}, - {"glGetPerfMonitorGroupsAMD", P(GL_GetPerfMonitorGroupsAMD)}, - {"glGetPixelMapfv", P(GL_GetPixelMapfv)}, - {"glGetPixelMapuiv", P(GL_GetPixelMapuiv)}, - {"glGetPixelMapusv", P(GL_GetPixelMapusv)}, - {"glGetPointerv", P(GL_GetPointerv)}, - {"glGetPointervKHR", P(GL_GetPointervKHR)}, - {"glGetPointervRobustANGLERobustANGLE", P(GL_GetPointervRobustANGLERobustANGLE)}, - {"glGetPolygonStipple", P(GL_GetPolygonStipple)}, - {"glGetProgramBinary", P(GL_GetProgramBinary)}, - {"glGetProgramBinaryOES", P(GL_GetProgramBinaryOES)}, - {"glGetProgramInfoLog", P(GL_GetProgramInfoLog)}, - {"glGetProgramInterfaceiv", P(GL_GetProgramInterfaceiv)}, - {"glGetProgramInterfaceivRobustANGLE", P(GL_GetProgramInterfaceivRobustANGLE)}, - {"glGetProgramPipelineInfoLog", P(GL_GetProgramPipelineInfoLog)}, - {"glGetProgramPipelineInfoLogEXT", P(GL_GetProgramPipelineInfoLogEXT)}, - {"glGetProgramPipelineiv", P(GL_GetProgramPipelineiv)}, - {"glGetProgramPipelineivEXT", P(GL_GetProgramPipelineivEXT)}, - {"glGetProgramResourceIndex", P(GL_GetProgramResourceIndex)}, - {"glGetProgramResourceLocation", P(GL_GetProgramResourceLocation)}, - {"glGetProgramResourceLocationIndex", P(GL_GetProgramResourceLocationIndex)}, - {"glGetProgramResourceLocationIndexEXT", P(GL_GetProgramResourceLocationIndexEXT)}, - {"glGetProgramResourceName", P(GL_GetProgramResourceName)}, - {"glGetProgramResourceiv", P(GL_GetProgramResourceiv)}, - {"glGetProgramStageiv", P(GL_GetProgramStageiv)}, - {"glGetProgramiv", P(GL_GetProgramiv)}, - {"glGetProgramivRobustANGLE", P(GL_GetProgramivRobustANGLE)}, - {"glGetQueryBufferObjecti64v", P(GL_GetQueryBufferObjecti64v)}, - {"glGetQueryBufferObjectiv", P(GL_GetQueryBufferObjectiv)}, - {"glGetQueryBufferObjectui64v", P(GL_GetQueryBufferObjectui64v)}, - {"glGetQueryBufferObjectuiv", P(GL_GetQueryBufferObjectuiv)}, - {"glGetQueryIndexediv", P(GL_GetQueryIndexediv)}, - {"glGetQueryObjecti64v", P(GL_GetQueryObjecti64v)}, - {"glGetQueryObjecti64vEXT", P(GL_GetQueryObjecti64vEXT)}, - {"glGetQueryObjecti64vRobustANGLE", P(GL_GetQueryObjecti64vRobustANGLE)}, - {"glGetQueryObjectiv", P(GL_GetQueryObjectiv)}, - {"glGetQueryObjectivEXT", P(GL_GetQueryObjectivEXT)}, - {"glGetQueryObjectivRobustANGLE", P(GL_GetQueryObjectivRobustANGLE)}, - {"glGetQueryObjectui64v", P(GL_GetQueryObjectui64v)}, - {"glGetQueryObjectui64vEXT", P(GL_GetQueryObjectui64vEXT)}, - {"glGetQueryObjectui64vRobustANGLE", P(GL_GetQueryObjectui64vRobustANGLE)}, - {"glGetQueryObjectuiv", P(GL_GetQueryObjectuiv)}, - {"glGetQueryObjectuivEXT", P(GL_GetQueryObjectuivEXT)}, - {"glGetQueryObjectuivRobustANGLE", P(GL_GetQueryObjectuivRobustANGLE)}, - {"glGetQueryiv", P(GL_GetQueryiv)}, - {"glGetQueryivEXT", P(GL_GetQueryivEXT)}, - {"glGetQueryivRobustANGLE", P(GL_GetQueryivRobustANGLE)}, - {"glGetRenderbufferImageANGLE", P(GL_GetRenderbufferImageANGLE)}, - {"glGetRenderbufferParameteriv", P(GL_GetRenderbufferParameteriv)}, - {"glGetRenderbufferParameterivOES", P(GL_GetRenderbufferParameterivOES)}, - {"glGetRenderbufferParameterivRobustANGLE", P(GL_GetRenderbufferParameterivRobustANGLE)}, - {"glGetSamplerParameterIiv", P(GL_GetSamplerParameterIiv)}, - {"glGetSamplerParameterIivEXT", P(GL_GetSamplerParameterIivEXT)}, - {"glGetSamplerParameterIivOES", P(GL_GetSamplerParameterIivOES)}, - {"glGetSamplerParameterIivRobustANGLE", P(GL_GetSamplerParameterIivRobustANGLE)}, - {"glGetSamplerParameterIuiv", P(GL_GetSamplerParameterIuiv)}, - {"glGetSamplerParameterIuivEXT", P(GL_GetSamplerParameterIuivEXT)}, - {"glGetSamplerParameterIuivOES", P(GL_GetSamplerParameterIuivOES)}, - {"glGetSamplerParameterIuivRobustANGLE", P(GL_GetSamplerParameterIuivRobustANGLE)}, - {"glGetSamplerParameterfv", P(GL_GetSamplerParameterfv)}, - {"glGetSamplerParameterfvRobustANGLE", P(GL_GetSamplerParameterfvRobustANGLE)}, - {"glGetSamplerParameteriv", P(GL_GetSamplerParameteriv)}, - {"glGetSamplerParameterivRobustANGLE", P(GL_GetSamplerParameterivRobustANGLE)}, - {"glGetSemaphoreParameterui64vEXT", P(GL_GetSemaphoreParameterui64vEXT)}, - {"glGetShaderInfoLog", P(GL_GetShaderInfoLog)}, - {"glGetShaderPrecisionFormat", P(GL_GetShaderPrecisionFormat)}, - {"glGetShaderSource", P(GL_GetShaderSource)}, - {"glGetShaderiv", P(GL_GetShaderiv)}, - {"glGetShaderivRobustANGLE", P(GL_GetShaderivRobustANGLE)}, - {"glGetString", P(GL_GetString)}, - {"glGetStringi", P(GL_GetStringi)}, - {"glGetSubroutineIndex", P(GL_GetSubroutineIndex)}, - {"glGetSubroutineUniformLocation", P(GL_GetSubroutineUniformLocation)}, - {"glGetSynciv", P(GL_GetSynciv)}, - {"glGetTexEnvfv", P(GL_GetTexEnvfv)}, - {"glGetTexEnviv", P(GL_GetTexEnviv)}, - {"glGetTexEnvxv", P(GL_GetTexEnvxv)}, - {"glGetTexGendv", P(GL_GetTexGendv)}, - {"glGetTexGenfv", P(GL_GetTexGenfv)}, - {"glGetTexGenfvOES", P(GL_GetTexGenfvOES)}, - {"glGetTexGeniv", P(GL_GetTexGeniv)}, - {"glGetTexGenivOES", P(GL_GetTexGenivOES)}, - {"glGetTexGenxvOES", P(GL_GetTexGenxvOES)}, - {"glGetTexImage", P(GL_GetTexImage)}, - {"glGetTexImageANGLE", P(GL_GetTexImageANGLE)}, - {"glGetTexLevelParameterfv", P(GL_GetTexLevelParameterfv)}, - {"glGetTexLevelParameterfvANGLE", P(GL_GetTexLevelParameterfvANGLE)}, - {"glGetTexLevelParameterfvRobustANGLE", P(GL_GetTexLevelParameterfvRobustANGLE)}, - {"glGetTexLevelParameteriv", P(GL_GetTexLevelParameteriv)}, - {"glGetTexLevelParameterivANGLE", P(GL_GetTexLevelParameterivANGLE)}, - {"glGetTexLevelParameterivRobustANGLE", P(GL_GetTexLevelParameterivRobustANGLE)}, - {"glGetTexParameterIiv", P(GL_GetTexParameterIiv)}, - {"glGetTexParameterIivEXT", P(GL_GetTexParameterIivEXT)}, - {"glGetTexParameterIivOES", P(GL_GetTexParameterIivOES)}, - {"glGetTexParameterIivRobustANGLE", P(GL_GetTexParameterIivRobustANGLE)}, - {"glGetTexParameterIuiv", P(GL_GetTexParameterIuiv)}, - {"glGetTexParameterIuivEXT", P(GL_GetTexParameterIuivEXT)}, - {"glGetTexParameterIuivOES", P(GL_GetTexParameterIuivOES)}, - {"glGetTexParameterIuivRobustANGLE", P(GL_GetTexParameterIuivRobustANGLE)}, - {"glGetTexParameterfv", P(GL_GetTexParameterfv)}, - {"glGetTexParameterfvRobustANGLE", P(GL_GetTexParameterfvRobustANGLE)}, - {"glGetTexParameteriv", P(GL_GetTexParameteriv)}, - {"glGetTexParameterivRobustANGLE", P(GL_GetTexParameterivRobustANGLE)}, - {"glGetTexParameterxv", P(GL_GetTexParameterxv)}, - {"glGetTextureImage", P(GL_GetTextureImage)}, - {"glGetTextureLevelParameterfv", P(GL_GetTextureLevelParameterfv)}, - {"glGetTextureLevelParameteriv", P(GL_GetTextureLevelParameteriv)}, - {"glGetTextureParameterIiv", P(GL_GetTextureParameterIiv)}, - {"glGetTextureParameterIuiv", P(GL_GetTextureParameterIuiv)}, - {"glGetTextureParameterfv", P(GL_GetTextureParameterfv)}, - {"glGetTextureParameteriv", P(GL_GetTextureParameteriv)}, - {"glGetTextureSubImage", P(GL_GetTextureSubImage)}, - {"glGetTransformFeedbackVarying", P(GL_GetTransformFeedbackVarying)}, - {"glGetTransformFeedbacki64_v", P(GL_GetTransformFeedbacki64_v)}, - {"glGetTransformFeedbacki_v", P(GL_GetTransformFeedbacki_v)}, - {"glGetTransformFeedbackiv", P(GL_GetTransformFeedbackiv)}, - {"glGetTranslatedShaderSourceANGLE", P(GL_GetTranslatedShaderSourceANGLE)}, - {"glGetUniformBlockIndex", P(GL_GetUniformBlockIndex)}, - {"glGetUniformIndices", P(GL_GetUniformIndices)}, - {"glGetUniformLocation", P(GL_GetUniformLocation)}, - {"glGetUniformSubroutineuiv", P(GL_GetUniformSubroutineuiv)}, - {"glGetUniformdv", P(GL_GetUniformdv)}, - {"glGetUniformfv", P(GL_GetUniformfv)}, - {"glGetUniformfvRobustANGLE", P(GL_GetUniformfvRobustANGLE)}, - {"glGetUniformiv", P(GL_GetUniformiv)}, - {"glGetUniformivRobustANGLE", P(GL_GetUniformivRobustANGLE)}, - {"glGetUniformuiv", P(GL_GetUniformuiv)}, - {"glGetUniformuivRobustANGLE", P(GL_GetUniformuivRobustANGLE)}, - {"glGetUnsignedBytei_vEXT", P(GL_GetUnsignedBytei_vEXT)}, - {"glGetUnsignedBytevEXT", P(GL_GetUnsignedBytevEXT)}, - {"glGetVertexArrayIndexed64iv", P(GL_GetVertexArrayIndexed64iv)}, - {"glGetVertexArrayIndexediv", P(GL_GetVertexArrayIndexediv)}, - {"glGetVertexArrayiv", P(GL_GetVertexArrayiv)}, - {"glGetVertexAttribIiv", P(GL_GetVertexAttribIiv)}, - {"glGetVertexAttribIivRobustANGLE", P(GL_GetVertexAttribIivRobustANGLE)}, - {"glGetVertexAttribIuiv", P(GL_GetVertexAttribIuiv)}, - {"glGetVertexAttribIuivRobustANGLE", P(GL_GetVertexAttribIuivRobustANGLE)}, - {"glGetVertexAttribLdv", P(GL_GetVertexAttribLdv)}, - {"glGetVertexAttribPointerv", P(GL_GetVertexAttribPointerv)}, - {"glGetVertexAttribPointervRobustANGLE", P(GL_GetVertexAttribPointervRobustANGLE)}, - {"glGetVertexAttribdv", P(GL_GetVertexAttribdv)}, - {"glGetVertexAttribfv", P(GL_GetVertexAttribfv)}, - {"glGetVertexAttribfvRobustANGLE", P(GL_GetVertexAttribfvRobustANGLE)}, - {"glGetVertexAttribiv", P(GL_GetVertexAttribiv)}, - {"glGetVertexAttribivRobustANGLE", P(GL_GetVertexAttribivRobustANGLE)}, - {"glGetnColorTable", P(GL_GetnColorTable)}, - {"glGetnCompressedTexImage", P(GL_GetnCompressedTexImage)}, - {"glGetnConvolutionFilter", P(GL_GetnConvolutionFilter)}, - {"glGetnHistogram", P(GL_GetnHistogram)}, - {"glGetnMapdv", P(GL_GetnMapdv)}, - {"glGetnMapfv", P(GL_GetnMapfv)}, - {"glGetnMapiv", P(GL_GetnMapiv)}, - {"glGetnMinmax", P(GL_GetnMinmax)}, - {"glGetnPixelMapfv", P(GL_GetnPixelMapfv)}, - {"glGetnPixelMapuiv", P(GL_GetnPixelMapuiv)}, - {"glGetnPixelMapusv", P(GL_GetnPixelMapusv)}, - {"glGetnPolygonStipple", P(GL_GetnPolygonStipple)}, - {"glGetnSeparableFilter", P(GL_GetnSeparableFilter)}, - {"glGetnTexImage", P(GL_GetnTexImage)}, - {"glGetnUniformdv", P(GL_GetnUniformdv)}, - {"glGetnUniformfv", P(GL_GetnUniformfv)}, - {"glGetnUniformfvEXT", P(GL_GetnUniformfvEXT)}, - {"glGetnUniformfvKHR", P(GL_GetnUniformfvKHR)}, - {"glGetnUniformfvRobustANGLE", P(GL_GetnUniformfvRobustANGLE)}, - {"glGetnUniformiv", P(GL_GetnUniformiv)}, - {"glGetnUniformivEXT", P(GL_GetnUniformivEXT)}, - {"glGetnUniformivKHR", P(GL_GetnUniformivKHR)}, - {"glGetnUniformivRobustANGLE", P(GL_GetnUniformivRobustANGLE)}, - {"glGetnUniformuiv", P(GL_GetnUniformuiv)}, - {"glGetnUniformuivKHR", P(GL_GetnUniformuivKHR)}, - {"glGetnUniformuivRobustANGLE", P(GL_GetnUniformuivRobustANGLE)}, - {"glHint", P(GL_Hint)}, - {"glImportMemoryFdEXT", P(GL_ImportMemoryFdEXT)}, - {"glImportMemoryZirconHandleANGLE", P(GL_ImportMemoryZirconHandleANGLE)}, - {"glImportSemaphoreFdEXT", P(GL_ImportSemaphoreFdEXT)}, - {"glImportSemaphoreZirconHandleANGLE", P(GL_ImportSemaphoreZirconHandleANGLE)}, - {"glIndexMask", P(GL_IndexMask)}, - {"glIndexPointer", P(GL_IndexPointer)}, - {"glIndexd", P(GL_Indexd)}, - {"glIndexdv", P(GL_Indexdv)}, - {"glIndexf", P(GL_Indexf)}, - {"glIndexfv", P(GL_Indexfv)}, - {"glIndexi", P(GL_Indexi)}, - {"glIndexiv", P(GL_Indexiv)}, - {"glIndexs", P(GL_Indexs)}, - {"glIndexsv", P(GL_Indexsv)}, - {"glIndexub", P(GL_Indexub)}, - {"glIndexubv", P(GL_Indexubv)}, - {"glInitNames", P(GL_InitNames)}, - {"glInsertEventMarkerEXT", P(GL_InsertEventMarkerEXT)}, - {"glInterleavedArrays", P(GL_InterleavedArrays)}, - {"glInvalidateBufferData", P(GL_InvalidateBufferData)}, - {"glInvalidateBufferSubData", P(GL_InvalidateBufferSubData)}, - {"glInvalidateFramebuffer", P(GL_InvalidateFramebuffer)}, - {"glInvalidateNamedFramebufferData", P(GL_InvalidateNamedFramebufferData)}, - {"glInvalidateNamedFramebufferSubData", P(GL_InvalidateNamedFramebufferSubData)}, - {"glInvalidateSubFramebuffer", P(GL_InvalidateSubFramebuffer)}, - {"glInvalidateTexImage", P(GL_InvalidateTexImage)}, - {"glInvalidateTexSubImage", P(GL_InvalidateTexSubImage)}, - {"glInvalidateTextureANGLE", P(GL_InvalidateTextureANGLE)}, - {"glIsBuffer", P(GL_IsBuffer)}, - {"glIsEnabled", P(GL_IsEnabled)}, - {"glIsEnabledi", P(GL_IsEnabledi)}, - {"glIsEnablediEXT", P(GL_IsEnablediEXT)}, - {"glIsEnablediOES", P(GL_IsEnablediOES)}, - {"glIsFenceNV", P(GL_IsFenceNV)}, - {"glIsFramebuffer", P(GL_IsFramebuffer)}, - {"glIsFramebufferOES", P(GL_IsFramebufferOES)}, - {"glIsList", P(GL_IsList)}, - {"glIsMemoryObjectEXT", P(GL_IsMemoryObjectEXT)}, - {"glIsProgram", P(GL_IsProgram)}, - {"glIsProgramPipeline", P(GL_IsProgramPipeline)}, - {"glIsProgramPipelineEXT", P(GL_IsProgramPipelineEXT)}, - {"glIsQuery", P(GL_IsQuery)}, - {"glIsQueryEXT", P(GL_IsQueryEXT)}, - {"glIsRenderbuffer", P(GL_IsRenderbuffer)}, - {"glIsRenderbufferOES", P(GL_IsRenderbufferOES)}, - {"glIsSampler", P(GL_IsSampler)}, - {"glIsSemaphoreEXT", P(GL_IsSemaphoreEXT)}, - {"glIsShader", P(GL_IsShader)}, - {"glIsSync", P(GL_IsSync)}, - {"glIsTexture", P(GL_IsTexture)}, - {"glIsTransformFeedback", P(GL_IsTransformFeedback)}, - {"glIsVertexArray", P(GL_IsVertexArray)}, - {"glIsVertexArrayOES", P(GL_IsVertexArrayOES)}, - {"glLabelObjectEXT", P(GL_LabelObjectEXT)}, - {"glLightModelf", P(GL_LightModelf)}, - {"glLightModelfv", P(GL_LightModelfv)}, - {"glLightModeli", P(GL_LightModeli)}, - {"glLightModeliv", P(GL_LightModeliv)}, - {"glLightModelx", P(GL_LightModelx)}, - {"glLightModelxv", P(GL_LightModelxv)}, - {"glLightf", P(GL_Lightf)}, - {"glLightfv", P(GL_Lightfv)}, - {"glLighti", P(GL_Lighti)}, - {"glLightiv", P(GL_Lightiv)}, - {"glLightx", P(GL_Lightx)}, - {"glLightxv", P(GL_Lightxv)}, - {"glLineStipple", P(GL_LineStipple)}, - {"glLineWidth", P(GL_LineWidth)}, - {"glLineWidthx", P(GL_LineWidthx)}, - {"glLinkProgram", P(GL_LinkProgram)}, - {"glListBase", P(GL_ListBase)}, - {"glLoadIdentity", P(GL_LoadIdentity)}, - {"glLoadMatrixd", P(GL_LoadMatrixd)}, - {"glLoadMatrixf", P(GL_LoadMatrixf)}, - {"glLoadMatrixx", P(GL_LoadMatrixx)}, - {"glLoadName", P(GL_LoadName)}, - {"glLoadPaletteFromModelViewMatrixOES", P(GL_LoadPaletteFromModelViewMatrixOES)}, - {"glLoadTransposeMatrixd", P(GL_LoadTransposeMatrixd)}, - {"glLoadTransposeMatrixf", P(GL_LoadTransposeMatrixf)}, - {"glLogicOp", P(GL_LogicOp)}, - {"glLogicOpANGLE", P(GL_LogicOpANGLE)}, - {"glLoseContextCHROMIUM", P(GL_LoseContextCHROMIUM)}, - {"glMap1d", P(GL_Map1d)}, - {"glMap1f", P(GL_Map1f)}, - {"glMap2d", P(GL_Map2d)}, - {"glMap2f", P(GL_Map2f)}, - {"glMapBuffer", P(GL_MapBuffer)}, - {"glMapBufferOES", P(GL_MapBufferOES)}, - {"glMapBufferRange", P(GL_MapBufferRange)}, - {"glMapBufferRangeEXT", P(GL_MapBufferRangeEXT)}, - {"glMapGrid1d", P(GL_MapGrid1d)}, - {"glMapGrid1f", P(GL_MapGrid1f)}, - {"glMapGrid2d", P(GL_MapGrid2d)}, - {"glMapGrid2f", P(GL_MapGrid2f)}, - {"glMapNamedBuffer", P(GL_MapNamedBuffer)}, - {"glMapNamedBufferRange", P(GL_MapNamedBufferRange)}, - {"glMaterialf", P(GL_Materialf)}, - {"glMaterialfv", P(GL_Materialfv)}, - {"glMateriali", P(GL_Materiali)}, - {"glMaterialiv", P(GL_Materialiv)}, - {"glMaterialx", P(GL_Materialx)}, - {"glMaterialxv", P(GL_Materialxv)}, - {"glMatrixIndexPointerOES", P(GL_MatrixIndexPointerOES)}, - {"glMatrixMode", P(GL_MatrixMode)}, - {"glMaxShaderCompilerThreadsKHR", P(GL_MaxShaderCompilerThreadsKHR)}, - {"glMemoryBarrier", P(GL_MemoryBarrier)}, - {"glMemoryBarrierByRegion", P(GL_MemoryBarrierByRegion)}, - {"glMemoryObjectParameterivEXT", P(GL_MemoryObjectParameterivEXT)}, - {"glMinSampleShading", P(GL_MinSampleShading)}, - {"glMinSampleShadingOES", P(GL_MinSampleShadingOES)}, - {"glMultMatrixd", P(GL_MultMatrixd)}, - {"glMultMatrixf", P(GL_MultMatrixf)}, - {"glMultMatrixx", P(GL_MultMatrixx)}, - {"glMultTransposeMatrixd", P(GL_MultTransposeMatrixd)}, - {"glMultTransposeMatrixf", P(GL_MultTransposeMatrixf)}, - {"glMultiDrawArrays", P(GL_MultiDrawArrays)}, - {"glMultiDrawArraysANGLE", P(GL_MultiDrawArraysANGLE)}, - {"glMultiDrawArraysIndirect", P(GL_MultiDrawArraysIndirect)}, - {"glMultiDrawArraysIndirectCount", P(GL_MultiDrawArraysIndirectCount)}, - {"glMultiDrawArraysIndirectEXT", P(GL_MultiDrawArraysIndirectEXT)}, - {"glMultiDrawArraysInstancedANGLE", P(GL_MultiDrawArraysInstancedANGLE)}, - {"glMultiDrawArraysInstancedBaseInstanceANGLE", P(GL_MultiDrawArraysInstancedBaseInstanceANGLE)}, - {"glMultiDrawElements", P(GL_MultiDrawElements)}, - {"glMultiDrawElementsANGLE", P(GL_MultiDrawElementsANGLE)}, - {"glMultiDrawElementsBaseVertex", P(GL_MultiDrawElementsBaseVertex)}, - {"glMultiDrawElementsBaseVertexEXT", P(GL_MultiDrawElementsBaseVertexEXT)}, - {"glMultiDrawElementsIndirect", P(GL_MultiDrawElementsIndirect)}, - {"glMultiDrawElementsIndirectCount", P(GL_MultiDrawElementsIndirectCount)}, - {"glMultiDrawElementsIndirectEXT", P(GL_MultiDrawElementsIndirectEXT)}, - {"glMultiDrawElementsInstancedANGLE", P(GL_MultiDrawElementsInstancedANGLE)}, - {"glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE", P(GL_MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE)}, - {"glMultiTexCoord1d", P(GL_MultiTexCoord1d)}, - {"glMultiTexCoord1dv", P(GL_MultiTexCoord1dv)}, - {"glMultiTexCoord1f", P(GL_MultiTexCoord1f)}, - {"glMultiTexCoord1fv", P(GL_MultiTexCoord1fv)}, - {"glMultiTexCoord1i", P(GL_MultiTexCoord1i)}, - {"glMultiTexCoord1iv", P(GL_MultiTexCoord1iv)}, - {"glMultiTexCoord1s", P(GL_MultiTexCoord1s)}, - {"glMultiTexCoord1sv", P(GL_MultiTexCoord1sv)}, - {"glMultiTexCoord2d", P(GL_MultiTexCoord2d)}, - {"glMultiTexCoord2dv", P(GL_MultiTexCoord2dv)}, - {"glMultiTexCoord2f", P(GL_MultiTexCoord2f)}, - {"glMultiTexCoord2fv", P(GL_MultiTexCoord2fv)}, - {"glMultiTexCoord2i", P(GL_MultiTexCoord2i)}, - {"glMultiTexCoord2iv", P(GL_MultiTexCoord2iv)}, - {"glMultiTexCoord2s", P(GL_MultiTexCoord2s)}, - {"glMultiTexCoord2sv", P(GL_MultiTexCoord2sv)}, - {"glMultiTexCoord3d", P(GL_MultiTexCoord3d)}, - {"glMultiTexCoord3dv", P(GL_MultiTexCoord3dv)}, - {"glMultiTexCoord3f", P(GL_MultiTexCoord3f)}, - {"glMultiTexCoord3fv", P(GL_MultiTexCoord3fv)}, - {"glMultiTexCoord3i", P(GL_MultiTexCoord3i)}, - {"glMultiTexCoord3iv", P(GL_MultiTexCoord3iv)}, - {"glMultiTexCoord3s", P(GL_MultiTexCoord3s)}, - {"glMultiTexCoord3sv", P(GL_MultiTexCoord3sv)}, - {"glMultiTexCoord4d", P(GL_MultiTexCoord4d)}, - {"glMultiTexCoord4dv", P(GL_MultiTexCoord4dv)}, - {"glMultiTexCoord4f", P(GL_MultiTexCoord4f)}, - {"glMultiTexCoord4fv", P(GL_MultiTexCoord4fv)}, - {"glMultiTexCoord4i", P(GL_MultiTexCoord4i)}, - {"glMultiTexCoord4iv", P(GL_MultiTexCoord4iv)}, - {"glMultiTexCoord4s", P(GL_MultiTexCoord4s)}, - {"glMultiTexCoord4sv", P(GL_MultiTexCoord4sv)}, - {"glMultiTexCoord4x", P(GL_MultiTexCoord4x)}, - {"glMultiTexCoordP1ui", P(GL_MultiTexCoordP1ui)}, - {"glMultiTexCoordP1uiv", P(GL_MultiTexCoordP1uiv)}, - {"glMultiTexCoordP2ui", P(GL_MultiTexCoordP2ui)}, - {"glMultiTexCoordP2uiv", P(GL_MultiTexCoordP2uiv)}, - {"glMultiTexCoordP3ui", P(GL_MultiTexCoordP3ui)}, - {"glMultiTexCoordP3uiv", P(GL_MultiTexCoordP3uiv)}, - {"glMultiTexCoordP4ui", P(GL_MultiTexCoordP4ui)}, - {"glMultiTexCoordP4uiv", P(GL_MultiTexCoordP4uiv)}, - {"glNamedBufferData", P(GL_NamedBufferData)}, - {"glNamedBufferStorage", P(GL_NamedBufferStorage)}, - {"glNamedBufferStorageExternalEXT", P(GL_NamedBufferStorageExternalEXT)}, - {"glNamedBufferSubData", P(GL_NamedBufferSubData)}, - {"glNamedFramebufferDrawBuffer", P(GL_NamedFramebufferDrawBuffer)}, - {"glNamedFramebufferDrawBuffers", P(GL_NamedFramebufferDrawBuffers)}, - {"glNamedFramebufferParameteri", P(GL_NamedFramebufferParameteri)}, - {"glNamedFramebufferReadBuffer", P(GL_NamedFramebufferReadBuffer)}, - {"glNamedFramebufferRenderbuffer", P(GL_NamedFramebufferRenderbuffer)}, - {"glNamedFramebufferTexture", P(GL_NamedFramebufferTexture)}, - {"glNamedFramebufferTextureLayer", P(GL_NamedFramebufferTextureLayer)}, - {"glNamedRenderbufferStorage", P(GL_NamedRenderbufferStorage)}, - {"glNamedRenderbufferStorageMultisample", P(GL_NamedRenderbufferStorageMultisample)}, - {"glNewList", P(GL_NewList)}, - {"glNormal3b", P(GL_Normal3b)}, - {"glNormal3bv", P(GL_Normal3bv)}, - {"glNormal3d", P(GL_Normal3d)}, - {"glNormal3dv", P(GL_Normal3dv)}, - {"glNormal3f", P(GL_Normal3f)}, - {"glNormal3fv", P(GL_Normal3fv)}, - {"glNormal3i", P(GL_Normal3i)}, - {"glNormal3iv", P(GL_Normal3iv)}, - {"glNormal3s", P(GL_Normal3s)}, - {"glNormal3sv", P(GL_Normal3sv)}, - {"glNormal3x", P(GL_Normal3x)}, - {"glNormalP3ui", P(GL_NormalP3ui)}, - {"glNormalP3uiv", P(GL_NormalP3uiv)}, - {"glNormalPointer", P(GL_NormalPointer)}, - {"glObjectLabel", P(GL_ObjectLabel)}, - {"glObjectLabelKHR", P(GL_ObjectLabelKHR)}, - {"glObjectPtrLabel", P(GL_ObjectPtrLabel)}, - {"glObjectPtrLabelKHR", P(GL_ObjectPtrLabelKHR)}, - {"glOrtho", P(GL_Ortho)}, - {"glOrthof", P(GL_Orthof)}, - {"glOrthox", P(GL_Orthox)}, - {"glPassThrough", P(GL_PassThrough)}, - {"glPatchParameterfv", P(GL_PatchParameterfv)}, - {"glPatchParameteri", P(GL_PatchParameteri)}, - {"glPatchParameteriEXT", P(GL_PatchParameteriEXT)}, - {"glPatchParameteriOES", P(GL_PatchParameteriOES)}, - {"glPauseTransformFeedback", P(GL_PauseTransformFeedback)}, - {"glPixelLocalStorageBarrierANGLE", P(GL_PixelLocalStorageBarrierANGLE)}, - {"glPixelMapfv", P(GL_PixelMapfv)}, - {"glPixelMapuiv", P(GL_PixelMapuiv)}, - {"glPixelMapusv", P(GL_PixelMapusv)}, - {"glPixelStoref", P(GL_PixelStoref)}, - {"glPixelStorei", P(GL_PixelStorei)}, - {"glPixelTransferf", P(GL_PixelTransferf)}, - {"glPixelTransferi", P(GL_PixelTransferi)}, - {"glPixelZoom", P(GL_PixelZoom)}, - {"glPointParameterf", P(GL_PointParameterf)}, - {"glPointParameterfv", P(GL_PointParameterfv)}, - {"glPointParameteri", P(GL_PointParameteri)}, - {"glPointParameteriv", P(GL_PointParameteriv)}, - {"glPointParameterx", P(GL_PointParameterx)}, - {"glPointParameterxv", P(GL_PointParameterxv)}, - {"glPointSize", P(GL_PointSize)}, - {"glPointSizePointerOES", P(GL_PointSizePointerOES)}, - {"glPointSizex", P(GL_PointSizex)}, - {"glPolygonMode", P(GL_PolygonMode)}, - {"glPolygonModeANGLE", P(GL_PolygonModeANGLE)}, - {"glPolygonModeNV", P(GL_PolygonModeNV)}, - {"glPolygonOffset", P(GL_PolygonOffset)}, - {"glPolygonOffsetClamp", P(GL_PolygonOffsetClamp)}, - {"glPolygonOffsetClampEXT", P(GL_PolygonOffsetClampEXT)}, - {"glPolygonOffsetx", P(GL_PolygonOffsetx)}, - {"glPolygonStipple", P(GL_PolygonStipple)}, - {"glPopAttrib", P(GL_PopAttrib)}, - {"glPopClientAttrib", P(GL_PopClientAttrib)}, - {"glPopDebugGroup", P(GL_PopDebugGroup)}, - {"glPopDebugGroupKHR", P(GL_PopDebugGroupKHR)}, - {"glPopGroupMarkerEXT", P(GL_PopGroupMarkerEXT)}, - {"glPopMatrix", P(GL_PopMatrix)}, - {"glPopName", P(GL_PopName)}, - {"glPrimitiveBoundingBox", P(GL_PrimitiveBoundingBox)}, - {"glPrimitiveBoundingBoxEXT", P(GL_PrimitiveBoundingBoxEXT)}, - {"glPrimitiveBoundingBoxOES", P(GL_PrimitiveBoundingBoxOES)}, - {"glPrimitiveRestartIndex", P(GL_PrimitiveRestartIndex)}, - {"glPrioritizeTextures", P(GL_PrioritizeTextures)}, - {"glProgramBinary", P(GL_ProgramBinary)}, - {"glProgramBinaryOES", P(GL_ProgramBinaryOES)}, - {"glProgramParameteri", P(GL_ProgramParameteri)}, - {"glProgramParameteriEXT", P(GL_ProgramParameteriEXT)}, - {"glProgramUniform1d", P(GL_ProgramUniform1d)}, - {"glProgramUniform1dv", P(GL_ProgramUniform1dv)}, - {"glProgramUniform1f", P(GL_ProgramUniform1f)}, - {"glProgramUniform1fEXT", P(GL_ProgramUniform1fEXT)}, - {"glProgramUniform1fv", P(GL_ProgramUniform1fv)}, - {"glProgramUniform1fvEXT", P(GL_ProgramUniform1fvEXT)}, - {"glProgramUniform1i", P(GL_ProgramUniform1i)}, - {"glProgramUniform1iEXT", P(GL_ProgramUniform1iEXT)}, - {"glProgramUniform1iv", P(GL_ProgramUniform1iv)}, - {"glProgramUniform1ivEXT", P(GL_ProgramUniform1ivEXT)}, - {"glProgramUniform1ui", P(GL_ProgramUniform1ui)}, - {"glProgramUniform1uiEXT", P(GL_ProgramUniform1uiEXT)}, - {"glProgramUniform1uiv", P(GL_ProgramUniform1uiv)}, - {"glProgramUniform1uivEXT", P(GL_ProgramUniform1uivEXT)}, - {"glProgramUniform2d", P(GL_ProgramUniform2d)}, - {"glProgramUniform2dv", P(GL_ProgramUniform2dv)}, - {"glProgramUniform2f", P(GL_ProgramUniform2f)}, - {"glProgramUniform2fEXT", P(GL_ProgramUniform2fEXT)}, - {"glProgramUniform2fv", P(GL_ProgramUniform2fv)}, - {"glProgramUniform2fvEXT", P(GL_ProgramUniform2fvEXT)}, - {"glProgramUniform2i", P(GL_ProgramUniform2i)}, - {"glProgramUniform2iEXT", P(GL_ProgramUniform2iEXT)}, - {"glProgramUniform2iv", P(GL_ProgramUniform2iv)}, - {"glProgramUniform2ivEXT", P(GL_ProgramUniform2ivEXT)}, - {"glProgramUniform2ui", P(GL_ProgramUniform2ui)}, - {"glProgramUniform2uiEXT", P(GL_ProgramUniform2uiEXT)}, - {"glProgramUniform2uiv", P(GL_ProgramUniform2uiv)}, - {"glProgramUniform2uivEXT", P(GL_ProgramUniform2uivEXT)}, - {"glProgramUniform3d", P(GL_ProgramUniform3d)}, - {"glProgramUniform3dv", P(GL_ProgramUniform3dv)}, - {"glProgramUniform3f", P(GL_ProgramUniform3f)}, - {"glProgramUniform3fEXT", P(GL_ProgramUniform3fEXT)}, - {"glProgramUniform3fv", P(GL_ProgramUniform3fv)}, - {"glProgramUniform3fvEXT", P(GL_ProgramUniform3fvEXT)}, - {"glProgramUniform3i", P(GL_ProgramUniform3i)}, - {"glProgramUniform3iEXT", P(GL_ProgramUniform3iEXT)}, - {"glProgramUniform3iv", P(GL_ProgramUniform3iv)}, - {"glProgramUniform3ivEXT", P(GL_ProgramUniform3ivEXT)}, - {"glProgramUniform3ui", P(GL_ProgramUniform3ui)}, - {"glProgramUniform3uiEXT", P(GL_ProgramUniform3uiEXT)}, - {"glProgramUniform3uiv", P(GL_ProgramUniform3uiv)}, - {"glProgramUniform3uivEXT", P(GL_ProgramUniform3uivEXT)}, - {"glProgramUniform4d", P(GL_ProgramUniform4d)}, - {"glProgramUniform4dv", P(GL_ProgramUniform4dv)}, - {"glProgramUniform4f", P(GL_ProgramUniform4f)}, - {"glProgramUniform4fEXT", P(GL_ProgramUniform4fEXT)}, - {"glProgramUniform4fv", P(GL_ProgramUniform4fv)}, - {"glProgramUniform4fvEXT", P(GL_ProgramUniform4fvEXT)}, - {"glProgramUniform4i", P(GL_ProgramUniform4i)}, - {"glProgramUniform4iEXT", P(GL_ProgramUniform4iEXT)}, - {"glProgramUniform4iv", P(GL_ProgramUniform4iv)}, - {"glProgramUniform4ivEXT", P(GL_ProgramUniform4ivEXT)}, - {"glProgramUniform4ui", P(GL_ProgramUniform4ui)}, - {"glProgramUniform4uiEXT", P(GL_ProgramUniform4uiEXT)}, - {"glProgramUniform4uiv", P(GL_ProgramUniform4uiv)}, - {"glProgramUniform4uivEXT", P(GL_ProgramUniform4uivEXT)}, - {"glProgramUniformMatrix2dv", P(GL_ProgramUniformMatrix2dv)}, - {"glProgramUniformMatrix2fv", P(GL_ProgramUniformMatrix2fv)}, - {"glProgramUniformMatrix2fvEXT", P(GL_ProgramUniformMatrix2fvEXT)}, - {"glProgramUniformMatrix2x3dv", P(GL_ProgramUniformMatrix2x3dv)}, - {"glProgramUniformMatrix2x3fv", P(GL_ProgramUniformMatrix2x3fv)}, - {"glProgramUniformMatrix2x3fvEXT", P(GL_ProgramUniformMatrix2x3fvEXT)}, - {"glProgramUniformMatrix2x4dv", P(GL_ProgramUniformMatrix2x4dv)}, - {"glProgramUniformMatrix2x4fv", P(GL_ProgramUniformMatrix2x4fv)}, - {"glProgramUniformMatrix2x4fvEXT", P(GL_ProgramUniformMatrix2x4fvEXT)}, - {"glProgramUniformMatrix3dv", P(GL_ProgramUniformMatrix3dv)}, - {"glProgramUniformMatrix3fv", P(GL_ProgramUniformMatrix3fv)}, - {"glProgramUniformMatrix3fvEXT", P(GL_ProgramUniformMatrix3fvEXT)}, - {"glProgramUniformMatrix3x2dv", P(GL_ProgramUniformMatrix3x2dv)}, - {"glProgramUniformMatrix3x2fv", P(GL_ProgramUniformMatrix3x2fv)}, - {"glProgramUniformMatrix3x2fvEXT", P(GL_ProgramUniformMatrix3x2fvEXT)}, - {"glProgramUniformMatrix3x4dv", P(GL_ProgramUniformMatrix3x4dv)}, - {"glProgramUniformMatrix3x4fv", P(GL_ProgramUniformMatrix3x4fv)}, - {"glProgramUniformMatrix3x4fvEXT", P(GL_ProgramUniformMatrix3x4fvEXT)}, - {"glProgramUniformMatrix4dv", P(GL_ProgramUniformMatrix4dv)}, - {"glProgramUniformMatrix4fv", P(GL_ProgramUniformMatrix4fv)}, - {"glProgramUniformMatrix4fvEXT", P(GL_ProgramUniformMatrix4fvEXT)}, - {"glProgramUniformMatrix4x2dv", P(GL_ProgramUniformMatrix4x2dv)}, - {"glProgramUniformMatrix4x2fv", P(GL_ProgramUniformMatrix4x2fv)}, - {"glProgramUniformMatrix4x2fvEXT", P(GL_ProgramUniformMatrix4x2fvEXT)}, - {"glProgramUniformMatrix4x3dv", P(GL_ProgramUniformMatrix4x3dv)}, - {"glProgramUniformMatrix4x3fv", P(GL_ProgramUniformMatrix4x3fv)}, - {"glProgramUniformMatrix4x3fvEXT", P(GL_ProgramUniformMatrix4x3fvEXT)}, - {"glProvokingVertex", P(GL_ProvokingVertex)}, - {"glProvokingVertexANGLE", P(GL_ProvokingVertexANGLE)}, - {"glPushAttrib", P(GL_PushAttrib)}, - {"glPushClientAttrib", P(GL_PushClientAttrib)}, - {"glPushDebugGroup", P(GL_PushDebugGroup)}, - {"glPushDebugGroupKHR", P(GL_PushDebugGroupKHR)}, - {"glPushGroupMarkerEXT", P(GL_PushGroupMarkerEXT)}, - {"glPushMatrix", P(GL_PushMatrix)}, - {"glPushName", P(GL_PushName)}, - {"glQueryCounter", P(GL_QueryCounter)}, - {"glQueryCounterEXT", P(GL_QueryCounterEXT)}, - {"glQueryMatrixxOES", P(GL_QueryMatrixxOES)}, - {"glRasterPos2d", P(GL_RasterPos2d)}, - {"glRasterPos2dv", P(GL_RasterPos2dv)}, - {"glRasterPos2f", P(GL_RasterPos2f)}, - {"glRasterPos2fv", P(GL_RasterPos2fv)}, - {"glRasterPos2i", P(GL_RasterPos2i)}, - {"glRasterPos2iv", P(GL_RasterPos2iv)}, - {"glRasterPos2s", P(GL_RasterPos2s)}, - {"glRasterPos2sv", P(GL_RasterPos2sv)}, - {"glRasterPos3d", P(GL_RasterPos3d)}, - {"glRasterPos3dv", P(GL_RasterPos3dv)}, - {"glRasterPos3f", P(GL_RasterPos3f)}, - {"glRasterPos3fv", P(GL_RasterPos3fv)}, - {"glRasterPos3i", P(GL_RasterPos3i)}, - {"glRasterPos3iv", P(GL_RasterPos3iv)}, - {"glRasterPos3s", P(GL_RasterPos3s)}, - {"glRasterPos3sv", P(GL_RasterPos3sv)}, - {"glRasterPos4d", P(GL_RasterPos4d)}, - {"glRasterPos4dv", P(GL_RasterPos4dv)}, - {"glRasterPos4f", P(GL_RasterPos4f)}, - {"glRasterPos4fv", P(GL_RasterPos4fv)}, - {"glRasterPos4i", P(GL_RasterPos4i)}, - {"glRasterPos4iv", P(GL_RasterPos4iv)}, - {"glRasterPos4s", P(GL_RasterPos4s)}, - {"glRasterPos4sv", P(GL_RasterPos4sv)}, - {"glReadBuffer", P(GL_ReadBuffer)}, - {"glReadPixels", P(GL_ReadPixels)}, - {"glReadPixelsRobustANGLE", P(GL_ReadPixelsRobustANGLE)}, - {"glReadnPixels", P(GL_ReadnPixels)}, - {"glReadnPixelsEXT", P(GL_ReadnPixelsEXT)}, - {"glReadnPixelsKHR", P(GL_ReadnPixelsKHR)}, - {"glReadnPixelsRobustANGLE", P(GL_ReadnPixelsRobustANGLE)}, - {"glRectd", P(GL_Rectd)}, - {"glRectdv", P(GL_Rectdv)}, - {"glRectf", P(GL_Rectf)}, - {"glRectfv", P(GL_Rectfv)}, - {"glRecti", P(GL_Recti)}, - {"glRectiv", P(GL_Rectiv)}, - {"glRects", P(GL_Rects)}, - {"glRectsv", P(GL_Rectsv)}, - {"glReleaseShaderCompiler", P(GL_ReleaseShaderCompiler)}, - {"glReleaseTexturesANGLE", P(GL_ReleaseTexturesANGLE)}, - {"glRenderMode", P(GL_RenderMode)}, - {"glRenderbufferStorage", P(GL_RenderbufferStorage)}, - {"glRenderbufferStorageMultisample", P(GL_RenderbufferStorageMultisample)}, - {"glRenderbufferStorageMultisampleANGLE", P(GL_RenderbufferStorageMultisampleANGLE)}, - {"glRenderbufferStorageMultisampleEXT", P(GL_RenderbufferStorageMultisampleEXT)}, - {"glRenderbufferStorageOES", P(GL_RenderbufferStorageOES)}, - {"glRequestExtensionANGLE", P(GL_RequestExtensionANGLE)}, - {"glResumeTransformFeedback", P(GL_ResumeTransformFeedback)}, - {"glRotated", P(GL_Rotated)}, - {"glRotatef", P(GL_Rotatef)}, - {"glRotatex", P(GL_Rotatex)}, - {"glSampleCoverage", P(GL_SampleCoverage)}, - {"glSampleCoveragex", P(GL_SampleCoveragex)}, - {"glSampleMaski", P(GL_SampleMaski)}, - {"glSampleMaskiANGLE", P(GL_SampleMaskiANGLE)}, - {"glSamplerParameterIiv", P(GL_SamplerParameterIiv)}, - {"glSamplerParameterIivEXT", P(GL_SamplerParameterIivEXT)}, - {"glSamplerParameterIivOES", P(GL_SamplerParameterIivOES)}, - {"glSamplerParameterIivRobustANGLE", P(GL_SamplerParameterIivRobustANGLE)}, - {"glSamplerParameterIuiv", P(GL_SamplerParameterIuiv)}, - {"glSamplerParameterIuivEXT", P(GL_SamplerParameterIuivEXT)}, - {"glSamplerParameterIuivOES", P(GL_SamplerParameterIuivOES)}, - {"glSamplerParameterIuivRobustANGLE", P(GL_SamplerParameterIuivRobustANGLE)}, - {"glSamplerParameterf", P(GL_SamplerParameterf)}, - {"glSamplerParameterfv", P(GL_SamplerParameterfv)}, - {"glSamplerParameterfvRobustANGLE", P(GL_SamplerParameterfvRobustANGLE)}, - {"glSamplerParameteri", P(GL_SamplerParameteri)}, - {"glSamplerParameteriv", P(GL_SamplerParameteriv)}, - {"glSamplerParameterivRobustANGLE", P(GL_SamplerParameterivRobustANGLE)}, - {"glScaled", P(GL_Scaled)}, - {"glScalef", P(GL_Scalef)}, - {"glScalex", P(GL_Scalex)}, - {"glScissor", P(GL_Scissor)}, - {"glScissorArrayv", P(GL_ScissorArrayv)}, - {"glScissorIndexed", P(GL_ScissorIndexed)}, - {"glScissorIndexedv", P(GL_ScissorIndexedv)}, - {"glSecondaryColor3b", P(GL_SecondaryColor3b)}, - {"glSecondaryColor3bv", P(GL_SecondaryColor3bv)}, - {"glSecondaryColor3d", P(GL_SecondaryColor3d)}, - {"glSecondaryColor3dv", P(GL_SecondaryColor3dv)}, - {"glSecondaryColor3f", P(GL_SecondaryColor3f)}, - {"glSecondaryColor3fv", P(GL_SecondaryColor3fv)}, - {"glSecondaryColor3i", P(GL_SecondaryColor3i)}, - {"glSecondaryColor3iv", P(GL_SecondaryColor3iv)}, - {"glSecondaryColor3s", P(GL_SecondaryColor3s)}, - {"glSecondaryColor3sv", P(GL_SecondaryColor3sv)}, - {"glSecondaryColor3ub", P(GL_SecondaryColor3ub)}, - {"glSecondaryColor3ubv", P(GL_SecondaryColor3ubv)}, - {"glSecondaryColor3ui", P(GL_SecondaryColor3ui)}, - {"glSecondaryColor3uiv", P(GL_SecondaryColor3uiv)}, - {"glSecondaryColor3us", P(GL_SecondaryColor3us)}, - {"glSecondaryColor3usv", P(GL_SecondaryColor3usv)}, - {"glSecondaryColorP3ui", P(GL_SecondaryColorP3ui)}, - {"glSecondaryColorP3uiv", P(GL_SecondaryColorP3uiv)}, - {"glSecondaryColorPointer", P(GL_SecondaryColorPointer)}, - {"glSelectBuffer", P(GL_SelectBuffer)}, - {"glSelectPerfMonitorCountersAMD", P(GL_SelectPerfMonitorCountersAMD)}, - {"glSemaphoreParameterui64vEXT", P(GL_SemaphoreParameterui64vEXT)}, - {"glSetFenceNV", P(GL_SetFenceNV)}, - {"glShadeModel", P(GL_ShadeModel)}, - {"glShaderBinary", P(GL_ShaderBinary)}, - {"glShaderSource", P(GL_ShaderSource)}, - {"glShaderStorageBlockBinding", P(GL_ShaderStorageBlockBinding)}, - {"glShadingRateQCOM", P(GL_ShadingRateQCOM)}, - {"glSignalSemaphoreEXT", P(GL_SignalSemaphoreEXT)}, - {"glSpecializeShader", P(GL_SpecializeShader)}, - {"glStartTilingQCOM", P(GL_StartTilingQCOM)}, - {"glStencilFunc", P(GL_StencilFunc)}, - {"glStencilFuncSeparate", P(GL_StencilFuncSeparate)}, - {"glStencilMask", P(GL_StencilMask)}, - {"glStencilMaskSeparate", P(GL_StencilMaskSeparate)}, - {"glStencilOp", P(GL_StencilOp)}, - {"glStencilOpSeparate", P(GL_StencilOpSeparate)}, - {"glTestFenceNV", P(GL_TestFenceNV)}, - {"glTexBuffer", P(GL_TexBuffer)}, - {"glTexBufferEXT", P(GL_TexBufferEXT)}, - {"glTexBufferOES", P(GL_TexBufferOES)}, - {"glTexBufferRange", P(GL_TexBufferRange)}, - {"glTexBufferRangeEXT", P(GL_TexBufferRangeEXT)}, - {"glTexBufferRangeOES", P(GL_TexBufferRangeOES)}, - {"glTexCoord1d", P(GL_TexCoord1d)}, - {"glTexCoord1dv", P(GL_TexCoord1dv)}, - {"glTexCoord1f", P(GL_TexCoord1f)}, - {"glTexCoord1fv", P(GL_TexCoord1fv)}, - {"glTexCoord1i", P(GL_TexCoord1i)}, - {"glTexCoord1iv", P(GL_TexCoord1iv)}, - {"glTexCoord1s", P(GL_TexCoord1s)}, - {"glTexCoord1sv", P(GL_TexCoord1sv)}, - {"glTexCoord2d", P(GL_TexCoord2d)}, - {"glTexCoord2dv", P(GL_TexCoord2dv)}, - {"glTexCoord2f", P(GL_TexCoord2f)}, - {"glTexCoord2fv", P(GL_TexCoord2fv)}, - {"glTexCoord2i", P(GL_TexCoord2i)}, - {"glTexCoord2iv", P(GL_TexCoord2iv)}, - {"glTexCoord2s", P(GL_TexCoord2s)}, - {"glTexCoord2sv", P(GL_TexCoord2sv)}, - {"glTexCoord3d", P(GL_TexCoord3d)}, - {"glTexCoord3dv", P(GL_TexCoord3dv)}, - {"glTexCoord3f", P(GL_TexCoord3f)}, - {"glTexCoord3fv", P(GL_TexCoord3fv)}, - {"glTexCoord3i", P(GL_TexCoord3i)}, - {"glTexCoord3iv", P(GL_TexCoord3iv)}, - {"glTexCoord3s", P(GL_TexCoord3s)}, - {"glTexCoord3sv", P(GL_TexCoord3sv)}, - {"glTexCoord4d", P(GL_TexCoord4d)}, - {"glTexCoord4dv", P(GL_TexCoord4dv)}, - {"glTexCoord4f", P(GL_TexCoord4f)}, - {"glTexCoord4fv", P(GL_TexCoord4fv)}, - {"glTexCoord4i", P(GL_TexCoord4i)}, - {"glTexCoord4iv", P(GL_TexCoord4iv)}, - {"glTexCoord4s", P(GL_TexCoord4s)}, - {"glTexCoord4sv", P(GL_TexCoord4sv)}, - {"glTexCoordP1ui", P(GL_TexCoordP1ui)}, - {"glTexCoordP1uiv", P(GL_TexCoordP1uiv)}, - {"glTexCoordP2ui", P(GL_TexCoordP2ui)}, - {"glTexCoordP2uiv", P(GL_TexCoordP2uiv)}, - {"glTexCoordP3ui", P(GL_TexCoordP3ui)}, - {"glTexCoordP3uiv", P(GL_TexCoordP3uiv)}, - {"glTexCoordP4ui", P(GL_TexCoordP4ui)}, - {"glTexCoordP4uiv", P(GL_TexCoordP4uiv)}, - {"glTexCoordPointer", P(GL_TexCoordPointer)}, - {"glTexEnvf", P(GL_TexEnvf)}, - {"glTexEnvfv", P(GL_TexEnvfv)}, - {"glTexEnvi", P(GL_TexEnvi)}, - {"glTexEnviv", P(GL_TexEnviv)}, - {"glTexEnvx", P(GL_TexEnvx)}, - {"glTexEnvxv", P(GL_TexEnvxv)}, - {"glTexGend", P(GL_TexGend)}, - {"glTexGendv", P(GL_TexGendv)}, - {"glTexGenf", P(GL_TexGenf)}, - {"glTexGenfOES", P(GL_TexGenfOES)}, - {"glTexGenfv", P(GL_TexGenfv)}, - {"glTexGenfvOES", P(GL_TexGenfvOES)}, - {"glTexGeni", P(GL_TexGeni)}, - {"glTexGeniOES", P(GL_TexGeniOES)}, - {"glTexGeniv", P(GL_TexGeniv)}, - {"glTexGenivOES", P(GL_TexGenivOES)}, - {"glTexGenxOES", P(GL_TexGenxOES)}, - {"glTexGenxvOES", P(GL_TexGenxvOES)}, - {"glTexImage1D", P(GL_TexImage1D)}, - {"glTexImage2D", P(GL_TexImage2D)}, - {"glTexImage2DExternalANGLE", P(GL_TexImage2DExternalANGLE)}, - {"glTexImage2DMultisample", P(GL_TexImage2DMultisample)}, - {"glTexImage2DRobustANGLE", P(GL_TexImage2DRobustANGLE)}, - {"glTexImage3D", P(GL_TexImage3D)}, - {"glTexImage3DMultisample", P(GL_TexImage3DMultisample)}, - {"glTexImage3DOES", P(GL_TexImage3DOES)}, - {"glTexImage3DRobustANGLE", P(GL_TexImage3DRobustANGLE)}, - {"glTexParameterIiv", P(GL_TexParameterIiv)}, - {"glTexParameterIivEXT", P(GL_TexParameterIivEXT)}, - {"glTexParameterIivOES", P(GL_TexParameterIivOES)}, - {"glTexParameterIivRobustANGLE", P(GL_TexParameterIivRobustANGLE)}, - {"glTexParameterIuiv", P(GL_TexParameterIuiv)}, - {"glTexParameterIuivEXT", P(GL_TexParameterIuivEXT)}, - {"glTexParameterIuivOES", P(GL_TexParameterIuivOES)}, - {"glTexParameterIuivRobustANGLE", P(GL_TexParameterIuivRobustANGLE)}, - {"glTexParameterf", P(GL_TexParameterf)}, - {"glTexParameterfv", P(GL_TexParameterfv)}, - {"glTexParameterfvRobustANGLE", P(GL_TexParameterfvRobustANGLE)}, - {"glTexParameteri", P(GL_TexParameteri)}, - {"glTexParameteriv", P(GL_TexParameteriv)}, - {"glTexParameterivRobustANGLE", P(GL_TexParameterivRobustANGLE)}, - {"glTexParameterx", P(GL_TexParameterx)}, - {"glTexParameterxv", P(GL_TexParameterxv)}, - {"glTexStorage1D", P(GL_TexStorage1D)}, - {"glTexStorage1DEXT", P(GL_TexStorage1DEXT)}, - {"glTexStorage2D", P(GL_TexStorage2D)}, - {"glTexStorage2DEXT", P(GL_TexStorage2DEXT)}, - {"glTexStorage2DMultisample", P(GL_TexStorage2DMultisample)}, - {"glTexStorage2DMultisampleANGLE", P(GL_TexStorage2DMultisampleANGLE)}, - {"glTexStorage3D", P(GL_TexStorage3D)}, - {"glTexStorage3DEXT", P(GL_TexStorage3DEXT)}, - {"glTexStorage3DMultisample", P(GL_TexStorage3DMultisample)}, - {"glTexStorage3DMultisampleOES", P(GL_TexStorage3DMultisampleOES)}, - {"glTexStorageAttribs2DEXT", P(GL_TexStorageAttribs2DEXT)}, - {"glTexStorageAttribs3DEXT", P(GL_TexStorageAttribs3DEXT)}, - {"glTexStorageMem2DEXT", P(GL_TexStorageMem2DEXT)}, - {"glTexStorageMem2DMultisampleEXT", P(GL_TexStorageMem2DMultisampleEXT)}, - {"glTexStorageMem3DEXT", P(GL_TexStorageMem3DEXT)}, - {"glTexStorageMem3DMultisampleEXT", P(GL_TexStorageMem3DMultisampleEXT)}, - {"glTexStorageMemFlags2DANGLE", P(GL_TexStorageMemFlags2DANGLE)}, - {"glTexStorageMemFlags2DMultisampleANGLE", P(GL_TexStorageMemFlags2DMultisampleANGLE)}, - {"glTexStorageMemFlags3DANGLE", P(GL_TexStorageMemFlags3DANGLE)}, - {"glTexStorageMemFlags3DMultisampleANGLE", P(GL_TexStorageMemFlags3DMultisampleANGLE)}, - {"glTexSubImage1D", P(GL_TexSubImage1D)}, - {"glTexSubImage2D", P(GL_TexSubImage2D)}, - {"glTexSubImage2DRobustANGLE", P(GL_TexSubImage2DRobustANGLE)}, - {"glTexSubImage3D", P(GL_TexSubImage3D)}, - {"glTexSubImage3DOES", P(GL_TexSubImage3DOES)}, - {"glTexSubImage3DRobustANGLE", P(GL_TexSubImage3DRobustANGLE)}, - {"glTextureBarrier", P(GL_TextureBarrier)}, - {"glTextureBuffer", P(GL_TextureBuffer)}, - {"glTextureBufferRange", P(GL_TextureBufferRange)}, - {"glTextureFoveationParametersQCOM", P(GL_TextureFoveationParametersQCOM)}, - {"glTextureParameterIiv", P(GL_TextureParameterIiv)}, - {"glTextureParameterIuiv", P(GL_TextureParameterIuiv)}, - {"glTextureParameterf", P(GL_TextureParameterf)}, - {"glTextureParameterfv", P(GL_TextureParameterfv)}, - {"glTextureParameteri", P(GL_TextureParameteri)}, - {"glTextureParameteriv", P(GL_TextureParameteriv)}, - {"glTextureStorage1D", P(GL_TextureStorage1D)}, - {"glTextureStorage2D", P(GL_TextureStorage2D)}, - {"glTextureStorage2DMultisample", P(GL_TextureStorage2DMultisample)}, - {"glTextureStorage3D", P(GL_TextureStorage3D)}, - {"glTextureStorage3DMultisample", P(GL_TextureStorage3DMultisample)}, - {"glTextureSubImage1D", P(GL_TextureSubImage1D)}, - {"glTextureSubImage2D", P(GL_TextureSubImage2D)}, - {"glTextureSubImage3D", P(GL_TextureSubImage3D)}, - {"glTextureView", P(GL_TextureView)}, - {"glTransformFeedbackBufferBase", P(GL_TransformFeedbackBufferBase)}, - {"glTransformFeedbackBufferRange", P(GL_TransformFeedbackBufferRange)}, - {"glTransformFeedbackVaryings", P(GL_TransformFeedbackVaryings)}, - {"glTranslated", P(GL_Translated)}, - {"glTranslatef", P(GL_Translatef)}, - {"glTranslatex", P(GL_Translatex)}, - {"glUniform1d", P(GL_Uniform1d)}, - {"glUniform1dv", P(GL_Uniform1dv)}, - {"glUniform1f", P(GL_Uniform1f)}, - {"glUniform1fv", P(GL_Uniform1fv)}, - {"glUniform1i", P(GL_Uniform1i)}, - {"glUniform1iv", P(GL_Uniform1iv)}, - {"glUniform1ui", P(GL_Uniform1ui)}, - {"glUniform1uiv", P(GL_Uniform1uiv)}, - {"glUniform2d", P(GL_Uniform2d)}, - {"glUniform2dv", P(GL_Uniform2dv)}, - {"glUniform2f", P(GL_Uniform2f)}, - {"glUniform2fv", P(GL_Uniform2fv)}, - {"glUniform2i", P(GL_Uniform2i)}, - {"glUniform2iv", P(GL_Uniform2iv)}, - {"glUniform2ui", P(GL_Uniform2ui)}, - {"glUniform2uiv", P(GL_Uniform2uiv)}, - {"glUniform3d", P(GL_Uniform3d)}, - {"glUniform3dv", P(GL_Uniform3dv)}, - {"glUniform3f", P(GL_Uniform3f)}, - {"glUniform3fv", P(GL_Uniform3fv)}, - {"glUniform3i", P(GL_Uniform3i)}, - {"glUniform3iv", P(GL_Uniform3iv)}, - {"glUniform3ui", P(GL_Uniform3ui)}, - {"glUniform3uiv", P(GL_Uniform3uiv)}, - {"glUniform4d", P(GL_Uniform4d)}, - {"glUniform4dv", P(GL_Uniform4dv)}, - {"glUniform4f", P(GL_Uniform4f)}, - {"glUniform4fv", P(GL_Uniform4fv)}, - {"glUniform4i", P(GL_Uniform4i)}, - {"glUniform4iv", P(GL_Uniform4iv)}, - {"glUniform4ui", P(GL_Uniform4ui)}, - {"glUniform4uiv", P(GL_Uniform4uiv)}, - {"glUniformBlockBinding", P(GL_UniformBlockBinding)}, - {"glUniformMatrix2dv", P(GL_UniformMatrix2dv)}, - {"glUniformMatrix2fv", P(GL_UniformMatrix2fv)}, - {"glUniformMatrix2x3dv", P(GL_UniformMatrix2x3dv)}, - {"glUniformMatrix2x3fv", P(GL_UniformMatrix2x3fv)}, - {"glUniformMatrix2x4dv", P(GL_UniformMatrix2x4dv)}, - {"glUniformMatrix2x4fv", P(GL_UniformMatrix2x4fv)}, - {"glUniformMatrix3dv", P(GL_UniformMatrix3dv)}, - {"glUniformMatrix3fv", P(GL_UniformMatrix3fv)}, - {"glUniformMatrix3x2dv", P(GL_UniformMatrix3x2dv)}, - {"glUniformMatrix3x2fv", P(GL_UniformMatrix3x2fv)}, - {"glUniformMatrix3x4dv", P(GL_UniformMatrix3x4dv)}, - {"glUniformMatrix3x4fv", P(GL_UniformMatrix3x4fv)}, - {"glUniformMatrix4dv", P(GL_UniformMatrix4dv)}, - {"glUniformMatrix4fv", P(GL_UniformMatrix4fv)}, - {"glUniformMatrix4x2dv", P(GL_UniformMatrix4x2dv)}, - {"glUniformMatrix4x2fv", P(GL_UniformMatrix4x2fv)}, - {"glUniformMatrix4x3dv", P(GL_UniformMatrix4x3dv)}, - {"glUniformMatrix4x3fv", P(GL_UniformMatrix4x3fv)}, - {"glUniformSubroutinesuiv", P(GL_UniformSubroutinesuiv)}, - {"glUnmapBuffer", P(GL_UnmapBuffer)}, - {"glUnmapBufferOES", P(GL_UnmapBufferOES)}, - {"glUnmapNamedBuffer", P(GL_UnmapNamedBuffer)}, - {"glUseProgram", P(GL_UseProgram)}, - {"glUseProgramStages", P(GL_UseProgramStages)}, - {"glUseProgramStagesEXT", P(GL_UseProgramStagesEXT)}, - {"glValidateProgram", P(GL_ValidateProgram)}, - {"glValidateProgramPipeline", P(GL_ValidateProgramPipeline)}, - {"glValidateProgramPipelineEXT", P(GL_ValidateProgramPipelineEXT)}, - {"glVertex2d", P(GL_Vertex2d)}, - {"glVertex2dv", P(GL_Vertex2dv)}, - {"glVertex2f", P(GL_Vertex2f)}, - {"glVertex2fv", P(GL_Vertex2fv)}, - {"glVertex2i", P(GL_Vertex2i)}, - {"glVertex2iv", P(GL_Vertex2iv)}, - {"glVertex2s", P(GL_Vertex2s)}, - {"glVertex2sv", P(GL_Vertex2sv)}, - {"glVertex3d", P(GL_Vertex3d)}, - {"glVertex3dv", P(GL_Vertex3dv)}, - {"glVertex3f", P(GL_Vertex3f)}, - {"glVertex3fv", P(GL_Vertex3fv)}, - {"glVertex3i", P(GL_Vertex3i)}, - {"glVertex3iv", P(GL_Vertex3iv)}, - {"glVertex3s", P(GL_Vertex3s)}, - {"glVertex3sv", P(GL_Vertex3sv)}, - {"glVertex4d", P(GL_Vertex4d)}, - {"glVertex4dv", P(GL_Vertex4dv)}, - {"glVertex4f", P(GL_Vertex4f)}, - {"glVertex4fv", P(GL_Vertex4fv)}, - {"glVertex4i", P(GL_Vertex4i)}, - {"glVertex4iv", P(GL_Vertex4iv)}, - {"glVertex4s", P(GL_Vertex4s)}, - {"glVertex4sv", P(GL_Vertex4sv)}, - {"glVertexArrayAttribBinding", P(GL_VertexArrayAttribBinding)}, - {"glVertexArrayAttribFormat", P(GL_VertexArrayAttribFormat)}, - {"glVertexArrayAttribIFormat", P(GL_VertexArrayAttribIFormat)}, - {"glVertexArrayAttribLFormat", P(GL_VertexArrayAttribLFormat)}, - {"glVertexArrayBindingDivisor", P(GL_VertexArrayBindingDivisor)}, - {"glVertexArrayElementBuffer", P(GL_VertexArrayElementBuffer)}, - {"glVertexArrayVertexBuffer", P(GL_VertexArrayVertexBuffer)}, - {"glVertexArrayVertexBuffers", P(GL_VertexArrayVertexBuffers)}, - {"glVertexAttrib1d", P(GL_VertexAttrib1d)}, - {"glVertexAttrib1dv", P(GL_VertexAttrib1dv)}, - {"glVertexAttrib1f", P(GL_VertexAttrib1f)}, - {"glVertexAttrib1fv", P(GL_VertexAttrib1fv)}, - {"glVertexAttrib1s", P(GL_VertexAttrib1s)}, - {"glVertexAttrib1sv", P(GL_VertexAttrib1sv)}, - {"glVertexAttrib2d", P(GL_VertexAttrib2d)}, - {"glVertexAttrib2dv", P(GL_VertexAttrib2dv)}, - {"glVertexAttrib2f", P(GL_VertexAttrib2f)}, - {"glVertexAttrib2fv", P(GL_VertexAttrib2fv)}, - {"glVertexAttrib2s", P(GL_VertexAttrib2s)}, - {"glVertexAttrib2sv", P(GL_VertexAttrib2sv)}, - {"glVertexAttrib3d", P(GL_VertexAttrib3d)}, - {"glVertexAttrib3dv", P(GL_VertexAttrib3dv)}, - {"glVertexAttrib3f", P(GL_VertexAttrib3f)}, - {"glVertexAttrib3fv", P(GL_VertexAttrib3fv)}, - {"glVertexAttrib3s", P(GL_VertexAttrib3s)}, - {"glVertexAttrib3sv", P(GL_VertexAttrib3sv)}, - {"glVertexAttrib4Nbv", P(GL_VertexAttrib4Nbv)}, - {"glVertexAttrib4Niv", P(GL_VertexAttrib4Niv)}, - {"glVertexAttrib4Nsv", P(GL_VertexAttrib4Nsv)}, - {"glVertexAttrib4Nub", P(GL_VertexAttrib4Nub)}, - {"glVertexAttrib4Nubv", P(GL_VertexAttrib4Nubv)}, - {"glVertexAttrib4Nuiv", P(GL_VertexAttrib4Nuiv)}, - {"glVertexAttrib4Nusv", P(GL_VertexAttrib4Nusv)}, - {"glVertexAttrib4bv", P(GL_VertexAttrib4bv)}, - {"glVertexAttrib4d", P(GL_VertexAttrib4d)}, - {"glVertexAttrib4dv", P(GL_VertexAttrib4dv)}, - {"glVertexAttrib4f", P(GL_VertexAttrib4f)}, - {"glVertexAttrib4fv", P(GL_VertexAttrib4fv)}, - {"glVertexAttrib4iv", P(GL_VertexAttrib4iv)}, - {"glVertexAttrib4s", P(GL_VertexAttrib4s)}, - {"glVertexAttrib4sv", P(GL_VertexAttrib4sv)}, - {"glVertexAttrib4ubv", P(GL_VertexAttrib4ubv)}, - {"glVertexAttrib4uiv", P(GL_VertexAttrib4uiv)}, - {"glVertexAttrib4usv", P(GL_VertexAttrib4usv)}, - {"glVertexAttribBinding", P(GL_VertexAttribBinding)}, - {"glVertexAttribDivisor", P(GL_VertexAttribDivisor)}, - {"glVertexAttribDivisorANGLE", P(GL_VertexAttribDivisorANGLE)}, - {"glVertexAttribDivisorEXT", P(GL_VertexAttribDivisorEXT)}, - {"glVertexAttribFormat", P(GL_VertexAttribFormat)}, - {"glVertexAttribI1i", P(GL_VertexAttribI1i)}, - {"glVertexAttribI1iv", P(GL_VertexAttribI1iv)}, - {"glVertexAttribI1ui", P(GL_VertexAttribI1ui)}, - {"glVertexAttribI1uiv", P(GL_VertexAttribI1uiv)}, - {"glVertexAttribI2i", P(GL_VertexAttribI2i)}, - {"glVertexAttribI2iv", P(GL_VertexAttribI2iv)}, - {"glVertexAttribI2ui", P(GL_VertexAttribI2ui)}, - {"glVertexAttribI2uiv", P(GL_VertexAttribI2uiv)}, - {"glVertexAttribI3i", P(GL_VertexAttribI3i)}, - {"glVertexAttribI3iv", P(GL_VertexAttribI3iv)}, - {"glVertexAttribI3ui", P(GL_VertexAttribI3ui)}, - {"glVertexAttribI3uiv", P(GL_VertexAttribI3uiv)}, - {"glVertexAttribI4bv", P(GL_VertexAttribI4bv)}, - {"glVertexAttribI4i", P(GL_VertexAttribI4i)}, - {"glVertexAttribI4iv", P(GL_VertexAttribI4iv)}, - {"glVertexAttribI4sv", P(GL_VertexAttribI4sv)}, - {"glVertexAttribI4ubv", P(GL_VertexAttribI4ubv)}, - {"glVertexAttribI4ui", P(GL_VertexAttribI4ui)}, - {"glVertexAttribI4uiv", P(GL_VertexAttribI4uiv)}, - {"glVertexAttribI4usv", P(GL_VertexAttribI4usv)}, - {"glVertexAttribIFormat", P(GL_VertexAttribIFormat)}, - {"glVertexAttribIPointer", P(GL_VertexAttribIPointer)}, - {"glVertexAttribL1d", P(GL_VertexAttribL1d)}, - {"glVertexAttribL1dv", P(GL_VertexAttribL1dv)}, - {"glVertexAttribL2d", P(GL_VertexAttribL2d)}, - {"glVertexAttribL2dv", P(GL_VertexAttribL2dv)}, - {"glVertexAttribL3d", P(GL_VertexAttribL3d)}, - {"glVertexAttribL3dv", P(GL_VertexAttribL3dv)}, - {"glVertexAttribL4d", P(GL_VertexAttribL4d)}, - {"glVertexAttribL4dv", P(GL_VertexAttribL4dv)}, - {"glVertexAttribLFormat", P(GL_VertexAttribLFormat)}, - {"glVertexAttribLPointer", P(GL_VertexAttribLPointer)}, - {"glVertexAttribP1ui", P(GL_VertexAttribP1ui)}, - {"glVertexAttribP1uiv", P(GL_VertexAttribP1uiv)}, - {"glVertexAttribP2ui", P(GL_VertexAttribP2ui)}, - {"glVertexAttribP2uiv", P(GL_VertexAttribP2uiv)}, - {"glVertexAttribP3ui", P(GL_VertexAttribP3ui)}, - {"glVertexAttribP3uiv", P(GL_VertexAttribP3uiv)}, - {"glVertexAttribP4ui", P(GL_VertexAttribP4ui)}, - {"glVertexAttribP4uiv", P(GL_VertexAttribP4uiv)}, - {"glVertexAttribPointer", P(GL_VertexAttribPointer)}, - {"glVertexBindingDivisor", P(GL_VertexBindingDivisor)}, - {"glVertexP2ui", P(GL_VertexP2ui)}, - {"glVertexP2uiv", P(GL_VertexP2uiv)}, - {"glVertexP3ui", P(GL_VertexP3ui)}, - {"glVertexP3uiv", P(GL_VertexP3uiv)}, - {"glVertexP4ui", P(GL_VertexP4ui)}, - {"glVertexP4uiv", P(GL_VertexP4uiv)}, - {"glVertexPointer", P(GL_VertexPointer)}, - {"glViewport", P(GL_Viewport)}, - {"glViewportArrayv", P(GL_ViewportArrayv)}, - {"glViewportIndexedf", P(GL_ViewportIndexedf)}, - {"glViewportIndexedfv", P(GL_ViewportIndexedfv)}, - {"glWaitSemaphoreEXT", P(GL_WaitSemaphoreEXT)}, - {"glWaitSync", P(GL_WaitSync)}, - {"glWeightPointerOES", P(GL_WeightPointerOES)}, - {"glWindowPos2d", P(GL_WindowPos2d)}, - {"glWindowPos2dv", P(GL_WindowPos2dv)}, - {"glWindowPos2f", P(GL_WindowPos2f)}, - {"glWindowPos2fv", P(GL_WindowPos2fv)}, - {"glWindowPos2i", P(GL_WindowPos2i)}, - {"glWindowPos2iv", P(GL_WindowPos2iv)}, - {"glWindowPos2s", P(GL_WindowPos2s)}, - {"glWindowPos2sv", P(GL_WindowPos2sv)}, - {"glWindowPos3d", P(GL_WindowPos3d)}, - {"glWindowPos3dv", P(GL_WindowPos3dv)}, - {"glWindowPos3f", P(GL_WindowPos3f)}, - {"glWindowPos3fv", P(GL_WindowPos3fv)}, - {"glWindowPos3i", P(GL_WindowPos3i)}, - {"glWindowPos3iv", P(GL_WindowPos3iv)}, - {"glWindowPos3s", P(GL_WindowPos3s)}, - {"glWindowPos3sv", P(GL_WindowPos3sv)}, - {"glXChooseFBConfig", P(glXChooseFBConfig)}, - {"glXChooseVisual", P(glXChooseVisual)}, - {"glXCopyContext", P(glXCopyContext)}, - {"glXCreateContext", P(glXCreateContext)}, - {"glXCreateGLXPixmap", P(glXCreateGLXPixmap)}, - {"glXCreateNewContext", P(glXCreateNewContext)}, - {"glXCreatePbuffer", P(glXCreatePbuffer)}, - {"glXCreatePixmap", P(glXCreatePixmap)}, - {"glXCreateWindow", P(glXCreateWindow)}, - {"glXDestroyContext", P(glXDestroyContext)}, - {"glXDestroyGLXPixmap", P(glXDestroyGLXPixmap)}, - {"glXDestroyPbuffer", P(glXDestroyPbuffer)}, - {"glXDestroyPixmap", P(glXDestroyPixmap)}, - {"glXDestroyWindow", P(glXDestroyWindow)}, - {"glXGetClientString", P(glXGetClientString)}, - {"glXGetConfig", P(glXGetConfig)}, - {"glXGetCurrentContext", P(glXGetCurrentContext)}, - {"glXGetCurrentDisplay", P(glXGetCurrentDisplay)}, - {"glXGetCurrentDrawable", P(glXGetCurrentDrawable)}, - {"glXGetCurrentReadDrawable", P(glXGetCurrentReadDrawable)}, - {"glXGetFBConfigAttrib", P(glXGetFBConfigAttrib)}, - {"glXGetFBConfigs", P(glXGetFBConfigs)}, - {"glXGetProcAddress", P(glXGetProcAddress)}, - {"glXGetSelectedEvent", P(glXGetSelectedEvent)}, - {"glXGetVisualFromFBConfig", P(glXGetVisualFromFBConfig)}, - {"glXIsDirect", P(glXIsDirect)}, - {"glXMakeContextCurrent", P(glXMakeContextCurrent)}, - {"glXMakeCurrent", P(glXMakeCurrent)}, - {"glXQueryContext", P(glXQueryContext)}, - {"glXQueryDrawable", P(glXQueryDrawable)}, - {"glXQueryExtension", P(glXQueryExtension)}, - {"glXQueryExtensionsString", P(glXQueryExtensionsString)}, - {"glXQueryServerString", P(glXQueryServerString)}, - {"glXQueryVersion", P(glXQueryVersion)}, - {"glXSelectEvent", P(glXSelectEvent)}, - {"glXSwapBuffers", P(glXSwapBuffers)}, - {"glXUseXFont", P(glXUseXFont)}, - {"glXWaitGL", P(glXWaitGL)}, - {"glXWaitX", P(glXWaitX)}, -}; -// clang-format on -const size_t g_numProcs = std::size(g_procTable); -} // namespace glx diff --git a/src/libGLESv2/proc_table_wgl_autogen.cpp b/src/libGLESv2/proc_table_wgl_autogen.cpp deleted file mode 100644 index cdc215fb1e6..00000000000 --- a/src/libGLESv2/proc_table_wgl_autogen.cpp +++ /dev/null @@ -1,1557 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_proc_table.py using data from gl.xml, gl_angle_ext.xml, wgl.xml. -// -// Copyright 2019 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. -// -// getProcAddress loader table: -// Mapping from a string entry point name to function address. -// - -#include "libGLESv2/proc_table_wgl.h" - -#include "libGLESv2/entry_points_egl_ext_autogen.h" -#include "libGLESv2/entry_points_gl_1_autogen.h" -#include "libGLESv2/entry_points_gl_2_autogen.h" -#include "libGLESv2/entry_points_gl_3_autogen.h" -#include "libGLESv2/entry_points_gl_4_autogen.h" -#include "libGLESv2/entry_points_gles_1_0_autogen.h" -#include "libGLESv2/entry_points_gles_2_0_autogen.h" -#include "libGLESv2/entry_points_gles_3_0_autogen.h" -#include "libGLESv2/entry_points_gles_3_1_autogen.h" -#include "libGLESv2/entry_points_gles_3_2_autogen.h" -#include "libGLESv2/entry_points_gles_ext_autogen.h" -#include "libGLESv2/entry_points_wgl.h" -#include "platform/PlatformMethods.h" - -#include - -#define P(FUNC) reinterpret_cast(FUNC) - -namespace wgl -{ -// clang-format off -const ProcEntry g_procTable[] = { - {"ANGLEGetDisplayPlatform", P(ANGLEGetDisplayPlatform)}, - {"ANGLEResetDisplayPlatform", P(ANGLEResetDisplayPlatform)}, - {"glAccum", P(GL_Accum)}, - {"glAcquireTexturesANGLE", P(GL_AcquireTexturesANGLE)}, - {"glActiveShaderProgram", P(GL_ActiveShaderProgram)}, - {"glActiveShaderProgramEXT", P(GL_ActiveShaderProgramEXT)}, - {"glActiveTexture", P(GL_ActiveTexture)}, - {"glAlphaFunc", P(GL_AlphaFunc)}, - {"glAlphaFuncx", P(GL_AlphaFuncx)}, - {"glAreTexturesResident", P(GL_AreTexturesResident)}, - {"glArrayElement", P(GL_ArrayElement)}, - {"glAttachShader", P(GL_AttachShader)}, - {"glBegin", P(GL_Begin)}, - {"glBeginConditionalRender", P(GL_BeginConditionalRender)}, - {"glBeginPerfMonitorAMD", P(GL_BeginPerfMonitorAMD)}, - {"glBeginPixelLocalStorageANGLE", P(GL_BeginPixelLocalStorageANGLE)}, - {"glBeginQuery", P(GL_BeginQuery)}, - {"glBeginQueryEXT", P(GL_BeginQueryEXT)}, - {"glBeginQueryIndexed", P(GL_BeginQueryIndexed)}, - {"glBeginTransformFeedback", P(GL_BeginTransformFeedback)}, - {"glBindAttribLocation", P(GL_BindAttribLocation)}, - {"glBindBuffer", P(GL_BindBuffer)}, - {"glBindBufferBase", P(GL_BindBufferBase)}, - {"glBindBufferRange", P(GL_BindBufferRange)}, - {"glBindBuffersBase", P(GL_BindBuffersBase)}, - {"glBindBuffersRange", P(GL_BindBuffersRange)}, - {"glBindFragDataLocation", P(GL_BindFragDataLocation)}, - {"glBindFragDataLocationEXT", P(GL_BindFragDataLocationEXT)}, - {"glBindFragDataLocationIndexed", P(GL_BindFragDataLocationIndexed)}, - {"glBindFragDataLocationIndexedEXT", P(GL_BindFragDataLocationIndexedEXT)}, - {"glBindFramebuffer", P(GL_BindFramebuffer)}, - {"glBindFramebufferOES", P(GL_BindFramebufferOES)}, - {"glBindImageTexture", P(GL_BindImageTexture)}, - {"glBindImageTextures", P(GL_BindImageTextures)}, - {"glBindProgramPipeline", P(GL_BindProgramPipeline)}, - {"glBindProgramPipelineEXT", P(GL_BindProgramPipelineEXT)}, - {"glBindRenderbuffer", P(GL_BindRenderbuffer)}, - {"glBindRenderbufferOES", P(GL_BindRenderbufferOES)}, - {"glBindSampler", P(GL_BindSampler)}, - {"glBindSamplers", P(GL_BindSamplers)}, - {"glBindTexture", P(GL_BindTexture)}, - {"glBindTextureUnit", P(GL_BindTextureUnit)}, - {"glBindTextures", P(GL_BindTextures)}, - {"glBindTransformFeedback", P(GL_BindTransformFeedback)}, - {"glBindUniformLocationCHROMIUM", P(GL_BindUniformLocationCHROMIUM)}, - {"glBindVertexArray", P(GL_BindVertexArray)}, - {"glBindVertexArrayOES", P(GL_BindVertexArrayOES)}, - {"glBindVertexBuffer", P(GL_BindVertexBuffer)}, - {"glBindVertexBuffers", P(GL_BindVertexBuffers)}, - {"glBitmap", P(GL_Bitmap)}, - {"glBlendBarrier", P(GL_BlendBarrier)}, - {"glBlendBarrierKHR", P(GL_BlendBarrierKHR)}, - {"glBlendColor", P(GL_BlendColor)}, - {"glBlendEquation", P(GL_BlendEquation)}, - {"glBlendEquationSeparate", P(GL_BlendEquationSeparate)}, - {"glBlendEquationSeparatei", P(GL_BlendEquationSeparatei)}, - {"glBlendEquationSeparateiEXT", P(GL_BlendEquationSeparateiEXT)}, - {"glBlendEquationSeparateiOES", P(GL_BlendEquationSeparateiOES)}, - {"glBlendEquationi", P(GL_BlendEquationi)}, - {"glBlendEquationiEXT", P(GL_BlendEquationiEXT)}, - {"glBlendEquationiOES", P(GL_BlendEquationiOES)}, - {"glBlendFunc", P(GL_BlendFunc)}, - {"glBlendFuncSeparate", P(GL_BlendFuncSeparate)}, - {"glBlendFuncSeparatei", P(GL_BlendFuncSeparatei)}, - {"glBlendFuncSeparateiEXT", P(GL_BlendFuncSeparateiEXT)}, - {"glBlendFuncSeparateiOES", P(GL_BlendFuncSeparateiOES)}, - {"glBlendFunci", P(GL_BlendFunci)}, - {"glBlendFunciEXT", P(GL_BlendFunciEXT)}, - {"glBlendFunciOES", P(GL_BlendFunciOES)}, - {"glBlitFramebuffer", P(GL_BlitFramebuffer)}, - {"glBlitFramebufferANGLE", P(GL_BlitFramebufferANGLE)}, - {"glBlitFramebufferNV", P(GL_BlitFramebufferNV)}, - {"glBlitNamedFramebuffer", P(GL_BlitNamedFramebuffer)}, - {"glBufferData", P(GL_BufferData)}, - {"glBufferStorage", P(GL_BufferStorage)}, - {"glBufferStorageEXT", P(GL_BufferStorageEXT)}, - {"glBufferStorageExternalEXT", P(GL_BufferStorageExternalEXT)}, - {"glBufferStorageMemEXT", P(GL_BufferStorageMemEXT)}, - {"glBufferSubData", P(GL_BufferSubData)}, - {"glCallList", P(GL_CallList)}, - {"glCallLists", P(GL_CallLists)}, - {"glCheckFramebufferStatus", P(GL_CheckFramebufferStatus)}, - {"glCheckFramebufferStatusOES", P(GL_CheckFramebufferStatusOES)}, - {"glCheckNamedFramebufferStatus", P(GL_CheckNamedFramebufferStatus)}, - {"glClampColor", P(GL_ClampColor)}, - {"glClear", P(GL_Clear)}, - {"glClearAccum", P(GL_ClearAccum)}, - {"glClearBufferData", P(GL_ClearBufferData)}, - {"glClearBufferSubData", P(GL_ClearBufferSubData)}, - {"glClearBufferfi", P(GL_ClearBufferfi)}, - {"glClearBufferfv", P(GL_ClearBufferfv)}, - {"glClearBufferiv", P(GL_ClearBufferiv)}, - {"glClearBufferuiv", P(GL_ClearBufferuiv)}, - {"glClearColor", P(GL_ClearColor)}, - {"glClearColorx", P(GL_ClearColorx)}, - {"glClearDepth", P(GL_ClearDepth)}, - {"glClearDepthf", P(GL_ClearDepthf)}, - {"glClearDepthx", P(GL_ClearDepthx)}, - {"glClearIndex", P(GL_ClearIndex)}, - {"glClearNamedBufferData", P(GL_ClearNamedBufferData)}, - {"glClearNamedBufferSubData", P(GL_ClearNamedBufferSubData)}, - {"glClearNamedFramebufferfi", P(GL_ClearNamedFramebufferfi)}, - {"glClearNamedFramebufferfv", P(GL_ClearNamedFramebufferfv)}, - {"glClearNamedFramebufferiv", P(GL_ClearNamedFramebufferiv)}, - {"glClearNamedFramebufferuiv", P(GL_ClearNamedFramebufferuiv)}, - {"glClearStencil", P(GL_ClearStencil)}, - {"glClearTexImage", P(GL_ClearTexImage)}, - {"glClearTexImageEXT", P(GL_ClearTexImageEXT)}, - {"glClearTexSubImage", P(GL_ClearTexSubImage)}, - {"glClearTexSubImageEXT", P(GL_ClearTexSubImageEXT)}, - {"glClientActiveTexture", P(GL_ClientActiveTexture)}, - {"glClientWaitSync", P(GL_ClientWaitSync)}, - {"glClipControl", P(GL_ClipControl)}, - {"glClipControlEXT", P(GL_ClipControlEXT)}, - {"glClipPlane", P(GL_ClipPlane)}, - {"glClipPlanef", P(GL_ClipPlanef)}, - {"glClipPlanex", P(GL_ClipPlanex)}, - {"glColor3b", P(GL_Color3b)}, - {"glColor3bv", P(GL_Color3bv)}, - {"glColor3d", P(GL_Color3d)}, - {"glColor3dv", P(GL_Color3dv)}, - {"glColor3f", P(GL_Color3f)}, - {"glColor3fv", P(GL_Color3fv)}, - {"glColor3i", P(GL_Color3i)}, - {"glColor3iv", P(GL_Color3iv)}, - {"glColor3s", P(GL_Color3s)}, - {"glColor3sv", P(GL_Color3sv)}, - {"glColor3ub", P(GL_Color3ub)}, - {"glColor3ubv", P(GL_Color3ubv)}, - {"glColor3ui", P(GL_Color3ui)}, - {"glColor3uiv", P(GL_Color3uiv)}, - {"glColor3us", P(GL_Color3us)}, - {"glColor3usv", P(GL_Color3usv)}, - {"glColor4b", P(GL_Color4b)}, - {"glColor4bv", P(GL_Color4bv)}, - {"glColor4d", P(GL_Color4d)}, - {"glColor4dv", P(GL_Color4dv)}, - {"glColor4f", P(GL_Color4f)}, - {"glColor4fv", P(GL_Color4fv)}, - {"glColor4i", P(GL_Color4i)}, - {"glColor4iv", P(GL_Color4iv)}, - {"glColor4s", P(GL_Color4s)}, - {"glColor4sv", P(GL_Color4sv)}, - {"glColor4ub", P(GL_Color4ub)}, - {"glColor4ubv", P(GL_Color4ubv)}, - {"glColor4ui", P(GL_Color4ui)}, - {"glColor4uiv", P(GL_Color4uiv)}, - {"glColor4us", P(GL_Color4us)}, - {"glColor4usv", P(GL_Color4usv)}, - {"glColor4x", P(GL_Color4x)}, - {"glColorMask", P(GL_ColorMask)}, - {"glColorMaski", P(GL_ColorMaski)}, - {"glColorMaskiEXT", P(GL_ColorMaskiEXT)}, - {"glColorMaskiOES", P(GL_ColorMaskiOES)}, - {"glColorMaterial", P(GL_ColorMaterial)}, - {"glColorP3ui", P(GL_ColorP3ui)}, - {"glColorP3uiv", P(GL_ColorP3uiv)}, - {"glColorP4ui", P(GL_ColorP4ui)}, - {"glColorP4uiv", P(GL_ColorP4uiv)}, - {"glColorPointer", P(GL_ColorPointer)}, - {"glCompileShader", P(GL_CompileShader)}, - {"glCompressedCopyTextureCHROMIUM", P(GL_CompressedCopyTextureCHROMIUM)}, - {"glCompressedTexImage1D", P(GL_CompressedTexImage1D)}, - {"glCompressedTexImage2D", P(GL_CompressedTexImage2D)}, - {"glCompressedTexImage2DRobustANGLE", P(GL_CompressedTexImage2DRobustANGLE)}, - {"glCompressedTexImage3D", P(GL_CompressedTexImage3D)}, - {"glCompressedTexImage3DOES", P(GL_CompressedTexImage3DOES)}, - {"glCompressedTexImage3DRobustANGLE", P(GL_CompressedTexImage3DRobustANGLE)}, - {"glCompressedTexSubImage1D", P(GL_CompressedTexSubImage1D)}, - {"glCompressedTexSubImage2D", P(GL_CompressedTexSubImage2D)}, - {"glCompressedTexSubImage2DRobustANGLE", P(GL_CompressedTexSubImage2DRobustANGLE)}, - {"glCompressedTexSubImage3D", P(GL_CompressedTexSubImage3D)}, - {"glCompressedTexSubImage3DOES", P(GL_CompressedTexSubImage3DOES)}, - {"glCompressedTexSubImage3DRobustANGLE", P(GL_CompressedTexSubImage3DRobustANGLE)}, - {"glCompressedTextureSubImage1D", P(GL_CompressedTextureSubImage1D)}, - {"glCompressedTextureSubImage2D", P(GL_CompressedTextureSubImage2D)}, - {"glCompressedTextureSubImage3D", P(GL_CompressedTextureSubImage3D)}, - {"glCopyBufferSubData", P(GL_CopyBufferSubData)}, - {"glCopyImageSubData", P(GL_CopyImageSubData)}, - {"glCopyImageSubDataEXT", P(GL_CopyImageSubDataEXT)}, - {"glCopyImageSubDataOES", P(GL_CopyImageSubDataOES)}, - {"glCopyNamedBufferSubData", P(GL_CopyNamedBufferSubData)}, - {"glCopyPixels", P(GL_CopyPixels)}, - {"glCopySubTexture3DANGLE", P(GL_CopySubTexture3DANGLE)}, - {"glCopySubTextureCHROMIUM", P(GL_CopySubTextureCHROMIUM)}, - {"glCopyTexImage1D", P(GL_CopyTexImage1D)}, - {"glCopyTexImage2D", P(GL_CopyTexImage2D)}, - {"glCopyTexSubImage1D", P(GL_CopyTexSubImage1D)}, - {"glCopyTexSubImage2D", P(GL_CopyTexSubImage2D)}, - {"glCopyTexSubImage3D", P(GL_CopyTexSubImage3D)}, - {"glCopyTexSubImage3DOES", P(GL_CopyTexSubImage3DOES)}, - {"glCopyTexture3DANGLE", P(GL_CopyTexture3DANGLE)}, - {"glCopyTextureCHROMIUM", P(GL_CopyTextureCHROMIUM)}, - {"glCopyTextureSubImage1D", P(GL_CopyTextureSubImage1D)}, - {"glCopyTextureSubImage2D", P(GL_CopyTextureSubImage2D)}, - {"glCopyTextureSubImage3D", P(GL_CopyTextureSubImage3D)}, - {"glCoverageModulationCHROMIUM", P(GL_CoverageModulationCHROMIUM)}, - {"glCreateBuffers", P(GL_CreateBuffers)}, - {"glCreateFramebuffers", P(GL_CreateFramebuffers)}, - {"glCreateMemoryObjectsEXT", P(GL_CreateMemoryObjectsEXT)}, - {"glCreateProgram", P(GL_CreateProgram)}, - {"glCreateProgramPipelines", P(GL_CreateProgramPipelines)}, - {"glCreateQueries", P(GL_CreateQueries)}, - {"glCreateRenderbuffers", P(GL_CreateRenderbuffers)}, - {"glCreateSamplers", P(GL_CreateSamplers)}, - {"glCreateShader", P(GL_CreateShader)}, - {"glCreateShaderProgramv", P(GL_CreateShaderProgramv)}, - {"glCreateShaderProgramvEXT", P(GL_CreateShaderProgramvEXT)}, - {"glCreateTextures", P(GL_CreateTextures)}, - {"glCreateTransformFeedbacks", P(GL_CreateTransformFeedbacks)}, - {"glCreateVertexArrays", P(GL_CreateVertexArrays)}, - {"glCullFace", P(GL_CullFace)}, - {"glCurrentPaletteMatrixOES", P(GL_CurrentPaletteMatrixOES)}, - {"glDebugMessageCallback", P(GL_DebugMessageCallback)}, - {"glDebugMessageCallbackKHR", P(GL_DebugMessageCallbackKHR)}, - {"glDebugMessageControl", P(GL_DebugMessageControl)}, - {"glDebugMessageControlKHR", P(GL_DebugMessageControlKHR)}, - {"glDebugMessageInsert", P(GL_DebugMessageInsert)}, - {"glDebugMessageInsertKHR", P(GL_DebugMessageInsertKHR)}, - {"glDeleteBuffers", P(GL_DeleteBuffers)}, - {"glDeleteFencesNV", P(GL_DeleteFencesNV)}, - {"glDeleteFramebuffers", P(GL_DeleteFramebuffers)}, - {"glDeleteFramebuffersOES", P(GL_DeleteFramebuffersOES)}, - {"glDeleteLists", P(GL_DeleteLists)}, - {"glDeleteMemoryObjectsEXT", P(GL_DeleteMemoryObjectsEXT)}, - {"glDeletePerfMonitorsAMD", P(GL_DeletePerfMonitorsAMD)}, - {"glDeleteProgram", P(GL_DeleteProgram)}, - {"glDeleteProgramPipelines", P(GL_DeleteProgramPipelines)}, - {"glDeleteProgramPipelinesEXT", P(GL_DeleteProgramPipelinesEXT)}, - {"glDeleteQueries", P(GL_DeleteQueries)}, - {"glDeleteQueriesEXT", P(GL_DeleteQueriesEXT)}, - {"glDeleteRenderbuffers", P(GL_DeleteRenderbuffers)}, - {"glDeleteRenderbuffersOES", P(GL_DeleteRenderbuffersOES)}, - {"glDeleteSamplers", P(GL_DeleteSamplers)}, - {"glDeleteSemaphoresEXT", P(GL_DeleteSemaphoresEXT)}, - {"glDeleteShader", P(GL_DeleteShader)}, - {"glDeleteSync", P(GL_DeleteSync)}, - {"glDeleteTextures", P(GL_DeleteTextures)}, - {"glDeleteTransformFeedbacks", P(GL_DeleteTransformFeedbacks)}, - {"glDeleteVertexArrays", P(GL_DeleteVertexArrays)}, - {"glDeleteVertexArraysOES", P(GL_DeleteVertexArraysOES)}, - {"glDepthFunc", P(GL_DepthFunc)}, - {"glDepthMask", P(GL_DepthMask)}, - {"glDepthRange", P(GL_DepthRange)}, - {"glDepthRangeArrayv", P(GL_DepthRangeArrayv)}, - {"glDepthRangeIndexed", P(GL_DepthRangeIndexed)}, - {"glDepthRangef", P(GL_DepthRangef)}, - {"glDepthRangex", P(GL_DepthRangex)}, - {"glDetachShader", P(GL_DetachShader)}, - {"glDisable", P(GL_Disable)}, - {"glDisableClientState", P(GL_DisableClientState)}, - {"glDisableExtensionANGLE", P(GL_DisableExtensionANGLE)}, - {"glDisableVertexArrayAttrib", P(GL_DisableVertexArrayAttrib)}, - {"glDisableVertexAttribArray", P(GL_DisableVertexAttribArray)}, - {"glDisablei", P(GL_Disablei)}, - {"glDisableiEXT", P(GL_DisableiEXT)}, - {"glDisableiOES", P(GL_DisableiOES)}, - {"glDiscardFramebufferEXT", P(GL_DiscardFramebufferEXT)}, - {"glDispatchCompute", P(GL_DispatchCompute)}, - {"glDispatchComputeIndirect", P(GL_DispatchComputeIndirect)}, - {"glDrawArrays", P(GL_DrawArrays)}, - {"glDrawArraysIndirect", P(GL_DrawArraysIndirect)}, - {"glDrawArraysInstanced", P(GL_DrawArraysInstanced)}, - {"glDrawArraysInstancedANGLE", P(GL_DrawArraysInstancedANGLE)}, - {"glDrawArraysInstancedBaseInstance", P(GL_DrawArraysInstancedBaseInstance)}, - {"glDrawArraysInstancedBaseInstanceANGLE", P(GL_DrawArraysInstancedBaseInstanceANGLE)}, - {"glDrawArraysInstancedBaseInstanceEXT", P(GL_DrawArraysInstancedBaseInstanceEXT)}, - {"glDrawArraysInstancedEXT", P(GL_DrawArraysInstancedEXT)}, - {"glDrawBuffer", P(GL_DrawBuffer)}, - {"glDrawBuffers", P(GL_DrawBuffers)}, - {"glDrawBuffersEXT", P(GL_DrawBuffersEXT)}, - {"glDrawElements", P(GL_DrawElements)}, - {"glDrawElementsBaseVertex", P(GL_DrawElementsBaseVertex)}, - {"glDrawElementsBaseVertexEXT", P(GL_DrawElementsBaseVertexEXT)}, - {"glDrawElementsBaseVertexOES", P(GL_DrawElementsBaseVertexOES)}, - {"glDrawElementsIndirect", P(GL_DrawElementsIndirect)}, - {"glDrawElementsInstanced", P(GL_DrawElementsInstanced)}, - {"glDrawElementsInstancedANGLE", P(GL_DrawElementsInstancedANGLE)}, - {"glDrawElementsInstancedBaseInstance", P(GL_DrawElementsInstancedBaseInstance)}, - {"glDrawElementsInstancedBaseInstanceEXT", P(GL_DrawElementsInstancedBaseInstanceEXT)}, - {"glDrawElementsInstancedBaseVertex", P(GL_DrawElementsInstancedBaseVertex)}, - {"glDrawElementsInstancedBaseVertexBaseInstance", P(GL_DrawElementsInstancedBaseVertexBaseInstance)}, - {"glDrawElementsInstancedBaseVertexBaseInstanceANGLE", P(GL_DrawElementsInstancedBaseVertexBaseInstanceANGLE)}, - {"glDrawElementsInstancedBaseVertexBaseInstanceEXT", P(GL_DrawElementsInstancedBaseVertexBaseInstanceEXT)}, - {"glDrawElementsInstancedBaseVertexEXT", P(GL_DrawElementsInstancedBaseVertexEXT)}, - {"glDrawElementsInstancedBaseVertexOES", P(GL_DrawElementsInstancedBaseVertexOES)}, - {"glDrawElementsInstancedEXT", P(GL_DrawElementsInstancedEXT)}, - {"glDrawPixels", P(GL_DrawPixels)}, - {"glDrawRangeElements", P(GL_DrawRangeElements)}, - {"glDrawRangeElementsBaseVertex", P(GL_DrawRangeElementsBaseVertex)}, - {"glDrawRangeElementsBaseVertexEXT", P(GL_DrawRangeElementsBaseVertexEXT)}, - {"glDrawRangeElementsBaseVertexOES", P(GL_DrawRangeElementsBaseVertexOES)}, - {"glDrawTexfOES", P(GL_DrawTexfOES)}, - {"glDrawTexfvOES", P(GL_DrawTexfvOES)}, - {"glDrawTexiOES", P(GL_DrawTexiOES)}, - {"glDrawTexivOES", P(GL_DrawTexivOES)}, - {"glDrawTexsOES", P(GL_DrawTexsOES)}, - {"glDrawTexsvOES", P(GL_DrawTexsvOES)}, - {"glDrawTexxOES", P(GL_DrawTexxOES)}, - {"glDrawTexxvOES", P(GL_DrawTexxvOES)}, - {"glDrawTransformFeedback", P(GL_DrawTransformFeedback)}, - {"glDrawTransformFeedbackInstanced", P(GL_DrawTransformFeedbackInstanced)}, - {"glDrawTransformFeedbackStream", P(GL_DrawTransformFeedbackStream)}, - {"glDrawTransformFeedbackStreamInstanced", P(GL_DrawTransformFeedbackStreamInstanced)}, - {"glEGLImageTargetRenderbufferStorageOES", P(GL_EGLImageTargetRenderbufferStorageOES)}, - {"glEGLImageTargetTexStorageEXT", P(GL_EGLImageTargetTexStorageEXT)}, - {"glEGLImageTargetTexture2DOES", P(GL_EGLImageTargetTexture2DOES)}, - {"glEGLImageTargetTextureStorageEXT", P(GL_EGLImageTargetTextureStorageEXT)}, - {"glEdgeFlag", P(GL_EdgeFlag)}, - {"glEdgeFlagPointer", P(GL_EdgeFlagPointer)}, - {"glEdgeFlagv", P(GL_EdgeFlagv)}, - {"glEnable", P(GL_Enable)}, - {"glEnableClientState", P(GL_EnableClientState)}, - {"glEnableVertexArrayAttrib", P(GL_EnableVertexArrayAttrib)}, - {"glEnableVertexAttribArray", P(GL_EnableVertexAttribArray)}, - {"glEnablei", P(GL_Enablei)}, - {"glEnableiEXT", P(GL_EnableiEXT)}, - {"glEnableiOES", P(GL_EnableiOES)}, - {"glEnd", P(GL_End)}, - {"glEndConditionalRender", P(GL_EndConditionalRender)}, - {"glEndList", P(GL_EndList)}, - {"glEndPerfMonitorAMD", P(GL_EndPerfMonitorAMD)}, - {"glEndPixelLocalStorageANGLE", P(GL_EndPixelLocalStorageANGLE)}, - {"glEndQuery", P(GL_EndQuery)}, - {"glEndQueryEXT", P(GL_EndQueryEXT)}, - {"glEndQueryIndexed", P(GL_EndQueryIndexed)}, - {"glEndTilingQCOM", P(GL_EndTilingQCOM)}, - {"glEndTransformFeedback", P(GL_EndTransformFeedback)}, - {"glEvalCoord1d", P(GL_EvalCoord1d)}, - {"glEvalCoord1dv", P(GL_EvalCoord1dv)}, - {"glEvalCoord1f", P(GL_EvalCoord1f)}, - {"glEvalCoord1fv", P(GL_EvalCoord1fv)}, - {"glEvalCoord2d", P(GL_EvalCoord2d)}, - {"glEvalCoord2dv", P(GL_EvalCoord2dv)}, - {"glEvalCoord2f", P(GL_EvalCoord2f)}, - {"glEvalCoord2fv", P(GL_EvalCoord2fv)}, - {"glEvalMesh1", P(GL_EvalMesh1)}, - {"glEvalMesh2", P(GL_EvalMesh2)}, - {"glEvalPoint1", P(GL_EvalPoint1)}, - {"glEvalPoint2", P(GL_EvalPoint2)}, - {"glFeedbackBuffer", P(GL_FeedbackBuffer)}, - {"glFenceSync", P(GL_FenceSync)}, - {"glFinish", P(GL_Finish)}, - {"glFinishFenceNV", P(GL_FinishFenceNV)}, - {"glFlush", P(GL_Flush)}, - {"glFlushMappedBufferRange", P(GL_FlushMappedBufferRange)}, - {"glFlushMappedBufferRangeEXT", P(GL_FlushMappedBufferRangeEXT)}, - {"glFlushMappedNamedBufferRange", P(GL_FlushMappedNamedBufferRange)}, - {"glFogCoordPointer", P(GL_FogCoordPointer)}, - {"glFogCoordd", P(GL_FogCoordd)}, - {"glFogCoorddv", P(GL_FogCoorddv)}, - {"glFogCoordf", P(GL_FogCoordf)}, - {"glFogCoordfv", P(GL_FogCoordfv)}, - {"glFogf", P(GL_Fogf)}, - {"glFogfv", P(GL_Fogfv)}, - {"glFogi", P(GL_Fogi)}, - {"glFogiv", P(GL_Fogiv)}, - {"glFogx", P(GL_Fogx)}, - {"glFogxv", P(GL_Fogxv)}, - {"glFramebufferFetchBarrierEXT", P(GL_FramebufferFetchBarrierEXT)}, - {"glFramebufferFoveationConfigQCOM", P(GL_FramebufferFoveationConfigQCOM)}, - {"glFramebufferFoveationParametersQCOM", P(GL_FramebufferFoveationParametersQCOM)}, - {"glFramebufferMemorylessPixelLocalStorageANGLE", P(GL_FramebufferMemorylessPixelLocalStorageANGLE)}, - {"glFramebufferParameteri", P(GL_FramebufferParameteri)}, - {"glFramebufferParameteriMESA", P(GL_FramebufferParameteriMESA)}, - {"glFramebufferPixelLocalClearValuefvANGLE", P(GL_FramebufferPixelLocalClearValuefvANGLE)}, - {"glFramebufferPixelLocalClearValueivANGLE", P(GL_FramebufferPixelLocalClearValueivANGLE)}, - {"glFramebufferPixelLocalClearValueuivANGLE", P(GL_FramebufferPixelLocalClearValueuivANGLE)}, - {"glFramebufferPixelLocalStorageInterruptANGLE", P(GL_FramebufferPixelLocalStorageInterruptANGLE)}, - {"glFramebufferPixelLocalStorageRestoreANGLE", P(GL_FramebufferPixelLocalStorageRestoreANGLE)}, - {"glFramebufferRenderbuffer", P(GL_FramebufferRenderbuffer)}, - {"glFramebufferRenderbufferOES", P(GL_FramebufferRenderbufferOES)}, - {"glFramebufferTexture", P(GL_FramebufferTexture)}, - {"glFramebufferTexture1D", P(GL_FramebufferTexture1D)}, - {"glFramebufferTexture2D", P(GL_FramebufferTexture2D)}, - {"glFramebufferTexture2DMultisampleEXT", P(GL_FramebufferTexture2DMultisampleEXT)}, - {"glFramebufferTexture2DOES", P(GL_FramebufferTexture2DOES)}, - {"glFramebufferTexture3D", P(GL_FramebufferTexture3D)}, - {"glFramebufferTexture3DOES", P(GL_FramebufferTexture3DOES)}, - {"glFramebufferTextureEXT", P(GL_FramebufferTextureEXT)}, - {"glFramebufferTextureLayer", P(GL_FramebufferTextureLayer)}, - {"glFramebufferTextureMultiviewOVR", P(GL_FramebufferTextureMultiviewOVR)}, - {"glFramebufferTextureOES", P(GL_FramebufferTextureOES)}, - {"glFramebufferTexturePixelLocalStorageANGLE", P(GL_FramebufferTexturePixelLocalStorageANGLE)}, - {"glFrontFace", P(GL_FrontFace)}, - {"glFrustum", P(GL_Frustum)}, - {"glFrustumf", P(GL_Frustumf)}, - {"glFrustumx", P(GL_Frustumx)}, - {"glGenBuffers", P(GL_GenBuffers)}, - {"glGenFencesNV", P(GL_GenFencesNV)}, - {"glGenFramebuffers", P(GL_GenFramebuffers)}, - {"glGenFramebuffersOES", P(GL_GenFramebuffersOES)}, - {"glGenLists", P(GL_GenLists)}, - {"glGenPerfMonitorsAMD", P(GL_GenPerfMonitorsAMD)}, - {"glGenProgramPipelines", P(GL_GenProgramPipelines)}, - {"glGenProgramPipelinesEXT", P(GL_GenProgramPipelinesEXT)}, - {"glGenQueries", P(GL_GenQueries)}, - {"glGenQueriesEXT", P(GL_GenQueriesEXT)}, - {"glGenRenderbuffers", P(GL_GenRenderbuffers)}, - {"glGenRenderbuffersOES", P(GL_GenRenderbuffersOES)}, - {"glGenSamplers", P(GL_GenSamplers)}, - {"glGenSemaphoresEXT", P(GL_GenSemaphoresEXT)}, - {"glGenTextures", P(GL_GenTextures)}, - {"glGenTransformFeedbacks", P(GL_GenTransformFeedbacks)}, - {"glGenVertexArrays", P(GL_GenVertexArrays)}, - {"glGenVertexArraysOES", P(GL_GenVertexArraysOES)}, - {"glGenerateMipmap", P(GL_GenerateMipmap)}, - {"glGenerateMipmapOES", P(GL_GenerateMipmapOES)}, - {"glGenerateTextureMipmap", P(GL_GenerateTextureMipmap)}, - {"glGetActiveAtomicCounterBufferiv", P(GL_GetActiveAtomicCounterBufferiv)}, - {"glGetActiveAttrib", P(GL_GetActiveAttrib)}, - {"glGetActiveSubroutineName", P(GL_GetActiveSubroutineName)}, - {"glGetActiveSubroutineUniformName", P(GL_GetActiveSubroutineUniformName)}, - {"glGetActiveSubroutineUniformiv", P(GL_GetActiveSubroutineUniformiv)}, - {"glGetActiveUniform", P(GL_GetActiveUniform)}, - {"glGetActiveUniformBlockName", P(GL_GetActiveUniformBlockName)}, - {"glGetActiveUniformBlockiv", P(GL_GetActiveUniformBlockiv)}, - {"glGetActiveUniformBlockivRobustANGLE", P(GL_GetActiveUniformBlockivRobustANGLE)}, - {"glGetActiveUniformName", P(GL_GetActiveUniformName)}, - {"glGetActiveUniformsiv", P(GL_GetActiveUniformsiv)}, - {"glGetAttachedShaders", P(GL_GetAttachedShaders)}, - {"glGetAttribLocation", P(GL_GetAttribLocation)}, - {"glGetBooleani_v", P(GL_GetBooleani_v)}, - {"glGetBooleani_vRobustANGLE", P(GL_GetBooleani_vRobustANGLE)}, - {"glGetBooleanv", P(GL_GetBooleanv)}, - {"glGetBooleanvRobustANGLE", P(GL_GetBooleanvRobustANGLE)}, - {"glGetBufferParameteri64v", P(GL_GetBufferParameteri64v)}, - {"glGetBufferParameteri64vRobustANGLE", P(GL_GetBufferParameteri64vRobustANGLE)}, - {"glGetBufferParameteriv", P(GL_GetBufferParameteriv)}, - {"glGetBufferParameterivRobustANGLE", P(GL_GetBufferParameterivRobustANGLE)}, - {"glGetBufferPointerv", P(GL_GetBufferPointerv)}, - {"glGetBufferPointervOES", P(GL_GetBufferPointervOES)}, - {"glGetBufferPointervRobustANGLE", P(GL_GetBufferPointervRobustANGLE)}, - {"glGetBufferSubData", P(GL_GetBufferSubData)}, - {"glGetClipPlane", P(GL_GetClipPlane)}, - {"glGetClipPlanef", P(GL_GetClipPlanef)}, - {"glGetClipPlanex", P(GL_GetClipPlanex)}, - {"glGetCompressedTexImage", P(GL_GetCompressedTexImage)}, - {"glGetCompressedTexImageANGLE", P(GL_GetCompressedTexImageANGLE)}, - {"glGetCompressedTextureImage", P(GL_GetCompressedTextureImage)}, - {"glGetCompressedTextureSubImage", P(GL_GetCompressedTextureSubImage)}, - {"glGetDebugMessageLog", P(GL_GetDebugMessageLog)}, - {"glGetDebugMessageLogKHR", P(GL_GetDebugMessageLogKHR)}, - {"glGetDoublei_v", P(GL_GetDoublei_v)}, - {"glGetDoublev", P(GL_GetDoublev)}, - {"glGetError", P(GL_GetError)}, - {"glGetFenceivNV", P(GL_GetFenceivNV)}, - {"glGetFixedv", P(GL_GetFixedv)}, - {"glGetFloati_v", P(GL_GetFloati_v)}, - {"glGetFloatv", P(GL_GetFloatv)}, - {"glGetFloatvRobustANGLE", P(GL_GetFloatvRobustANGLE)}, - {"glGetFragDataIndex", P(GL_GetFragDataIndex)}, - {"glGetFragDataIndexEXT", P(GL_GetFragDataIndexEXT)}, - {"glGetFragDataLocation", P(GL_GetFragDataLocation)}, - {"glGetFramebufferAttachmentParameteriv", P(GL_GetFramebufferAttachmentParameteriv)}, - {"glGetFramebufferAttachmentParameterivOES", P(GL_GetFramebufferAttachmentParameterivOES)}, - {"glGetFramebufferAttachmentParameterivRobustANGLE", P(GL_GetFramebufferAttachmentParameterivRobustANGLE)}, - {"glGetFramebufferParameteriv", P(GL_GetFramebufferParameteriv)}, - {"glGetFramebufferParameterivMESA", P(GL_GetFramebufferParameterivMESA)}, - {"glGetFramebufferParameterivRobustANGLE", P(GL_GetFramebufferParameterivRobustANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterfvANGLE", P(GL_GetFramebufferPixelLocalStorageParameterfvANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterfvRobustANGLE", P(GL_GetFramebufferPixelLocalStorageParameterfvRobustANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterivANGLE", P(GL_GetFramebufferPixelLocalStorageParameterivANGLE)}, - {"glGetFramebufferPixelLocalStorageParameterivRobustANGLE", P(GL_GetFramebufferPixelLocalStorageParameterivRobustANGLE)}, - {"glGetGraphicsResetStatus", P(GL_GetGraphicsResetStatus)}, - {"glGetGraphicsResetStatusEXT", P(GL_GetGraphicsResetStatusEXT)}, - {"glGetGraphicsResetStatusKHR", P(GL_GetGraphicsResetStatusKHR)}, - {"glGetInteger64i_v", P(GL_GetInteger64i_v)}, - {"glGetInteger64i_vRobustANGLE", P(GL_GetInteger64i_vRobustANGLE)}, - {"glGetInteger64v", P(GL_GetInteger64v)}, - {"glGetInteger64vEXT", P(GL_GetInteger64vEXT)}, - {"glGetInteger64vRobustANGLE", P(GL_GetInteger64vRobustANGLE)}, - {"glGetIntegeri_v", P(GL_GetIntegeri_v)}, - {"glGetIntegeri_vRobustANGLE", P(GL_GetIntegeri_vRobustANGLE)}, - {"glGetIntegerv", P(GL_GetIntegerv)}, - {"glGetIntegervRobustANGLE", P(GL_GetIntegervRobustANGLE)}, - {"glGetInternalformati64v", P(GL_GetInternalformati64v)}, - {"glGetInternalformativ", P(GL_GetInternalformativ)}, - {"glGetInternalformativRobustANGLE", P(GL_GetInternalformativRobustANGLE)}, - {"glGetLightfv", P(GL_GetLightfv)}, - {"glGetLightiv", P(GL_GetLightiv)}, - {"glGetLightxv", P(GL_GetLightxv)}, - {"glGetMapdv", P(GL_GetMapdv)}, - {"glGetMapfv", P(GL_GetMapfv)}, - {"glGetMapiv", P(GL_GetMapiv)}, - {"glGetMaterialfv", P(GL_GetMaterialfv)}, - {"glGetMaterialiv", P(GL_GetMaterialiv)}, - {"glGetMaterialxv", P(GL_GetMaterialxv)}, - {"glGetMemoryObjectParameterivEXT", P(GL_GetMemoryObjectParameterivEXT)}, - {"glGetMultisamplefv", P(GL_GetMultisamplefv)}, - {"glGetMultisamplefvANGLE", P(GL_GetMultisamplefvANGLE)}, - {"glGetMultisamplefvRobustANGLE", P(GL_GetMultisamplefvRobustANGLE)}, - {"glGetNamedBufferParameteri64v", P(GL_GetNamedBufferParameteri64v)}, - {"glGetNamedBufferParameteriv", P(GL_GetNamedBufferParameteriv)}, - {"glGetNamedBufferPointerv", P(GL_GetNamedBufferPointerv)}, - {"glGetNamedBufferSubData", P(GL_GetNamedBufferSubData)}, - {"glGetNamedFramebufferAttachmentParameteriv", P(GL_GetNamedFramebufferAttachmentParameteriv)}, - {"glGetNamedFramebufferParameteriv", P(GL_GetNamedFramebufferParameteriv)}, - {"glGetNamedRenderbufferParameteriv", P(GL_GetNamedRenderbufferParameteriv)}, - {"glGetObjectLabel", P(GL_GetObjectLabel)}, - {"glGetObjectLabelEXT", P(GL_GetObjectLabelEXT)}, - {"glGetObjectLabelKHR", P(GL_GetObjectLabelKHR)}, - {"glGetObjectPtrLabel", P(GL_GetObjectPtrLabel)}, - {"glGetObjectPtrLabelKHR", P(GL_GetObjectPtrLabelKHR)}, - {"glGetPerfMonitorCounterDataAMD", P(GL_GetPerfMonitorCounterDataAMD)}, - {"glGetPerfMonitorCounterInfoAMD", P(GL_GetPerfMonitorCounterInfoAMD)}, - {"glGetPerfMonitorCounterStringAMD", P(GL_GetPerfMonitorCounterStringAMD)}, - {"glGetPerfMonitorCountersAMD", P(GL_GetPerfMonitorCountersAMD)}, - {"glGetPerfMonitorGroupStringAMD", P(GL_GetPerfMonitorGroupStringAMD)}, - {"glGetPerfMonitorGroupsAMD", P(GL_GetPerfMonitorGroupsAMD)}, - {"glGetPixelMapfv", P(GL_GetPixelMapfv)}, - {"glGetPixelMapuiv", P(GL_GetPixelMapuiv)}, - {"glGetPixelMapusv", P(GL_GetPixelMapusv)}, - {"glGetPointerv", P(GL_GetPointerv)}, - {"glGetPointervKHR", P(GL_GetPointervKHR)}, - {"glGetPointervRobustANGLERobustANGLE", P(GL_GetPointervRobustANGLERobustANGLE)}, - {"glGetPolygonStipple", P(GL_GetPolygonStipple)}, - {"glGetProgramBinary", P(GL_GetProgramBinary)}, - {"glGetProgramBinaryOES", P(GL_GetProgramBinaryOES)}, - {"glGetProgramInfoLog", P(GL_GetProgramInfoLog)}, - {"glGetProgramInterfaceiv", P(GL_GetProgramInterfaceiv)}, - {"glGetProgramInterfaceivRobustANGLE", P(GL_GetProgramInterfaceivRobustANGLE)}, - {"glGetProgramPipelineInfoLog", P(GL_GetProgramPipelineInfoLog)}, - {"glGetProgramPipelineInfoLogEXT", P(GL_GetProgramPipelineInfoLogEXT)}, - {"glGetProgramPipelineiv", P(GL_GetProgramPipelineiv)}, - {"glGetProgramPipelineivEXT", P(GL_GetProgramPipelineivEXT)}, - {"glGetProgramResourceIndex", P(GL_GetProgramResourceIndex)}, - {"glGetProgramResourceLocation", P(GL_GetProgramResourceLocation)}, - {"glGetProgramResourceLocationIndex", P(GL_GetProgramResourceLocationIndex)}, - {"glGetProgramResourceLocationIndexEXT", P(GL_GetProgramResourceLocationIndexEXT)}, - {"glGetProgramResourceName", P(GL_GetProgramResourceName)}, - {"glGetProgramResourceiv", P(GL_GetProgramResourceiv)}, - {"glGetProgramStageiv", P(GL_GetProgramStageiv)}, - {"glGetProgramiv", P(GL_GetProgramiv)}, - {"glGetProgramivRobustANGLE", P(GL_GetProgramivRobustANGLE)}, - {"glGetQueryBufferObjecti64v", P(GL_GetQueryBufferObjecti64v)}, - {"glGetQueryBufferObjectiv", P(GL_GetQueryBufferObjectiv)}, - {"glGetQueryBufferObjectui64v", P(GL_GetQueryBufferObjectui64v)}, - {"glGetQueryBufferObjectuiv", P(GL_GetQueryBufferObjectuiv)}, - {"glGetQueryIndexediv", P(GL_GetQueryIndexediv)}, - {"glGetQueryObjecti64v", P(GL_GetQueryObjecti64v)}, - {"glGetQueryObjecti64vEXT", P(GL_GetQueryObjecti64vEXT)}, - {"glGetQueryObjecti64vRobustANGLE", P(GL_GetQueryObjecti64vRobustANGLE)}, - {"glGetQueryObjectiv", P(GL_GetQueryObjectiv)}, - {"glGetQueryObjectivEXT", P(GL_GetQueryObjectivEXT)}, - {"glGetQueryObjectivRobustANGLE", P(GL_GetQueryObjectivRobustANGLE)}, - {"glGetQueryObjectui64v", P(GL_GetQueryObjectui64v)}, - {"glGetQueryObjectui64vEXT", P(GL_GetQueryObjectui64vEXT)}, - {"glGetQueryObjectui64vRobustANGLE", P(GL_GetQueryObjectui64vRobustANGLE)}, - {"glGetQueryObjectuiv", P(GL_GetQueryObjectuiv)}, - {"glGetQueryObjectuivEXT", P(GL_GetQueryObjectuivEXT)}, - {"glGetQueryObjectuivRobustANGLE", P(GL_GetQueryObjectuivRobustANGLE)}, - {"glGetQueryiv", P(GL_GetQueryiv)}, - {"glGetQueryivEXT", P(GL_GetQueryivEXT)}, - {"glGetQueryivRobustANGLE", P(GL_GetQueryivRobustANGLE)}, - {"glGetRenderbufferImageANGLE", P(GL_GetRenderbufferImageANGLE)}, - {"glGetRenderbufferParameteriv", P(GL_GetRenderbufferParameteriv)}, - {"glGetRenderbufferParameterivOES", P(GL_GetRenderbufferParameterivOES)}, - {"glGetRenderbufferParameterivRobustANGLE", P(GL_GetRenderbufferParameterivRobustANGLE)}, - {"glGetSamplerParameterIiv", P(GL_GetSamplerParameterIiv)}, - {"glGetSamplerParameterIivEXT", P(GL_GetSamplerParameterIivEXT)}, - {"glGetSamplerParameterIivOES", P(GL_GetSamplerParameterIivOES)}, - {"glGetSamplerParameterIivRobustANGLE", P(GL_GetSamplerParameterIivRobustANGLE)}, - {"glGetSamplerParameterIuiv", P(GL_GetSamplerParameterIuiv)}, - {"glGetSamplerParameterIuivEXT", P(GL_GetSamplerParameterIuivEXT)}, - {"glGetSamplerParameterIuivOES", P(GL_GetSamplerParameterIuivOES)}, - {"glGetSamplerParameterIuivRobustANGLE", P(GL_GetSamplerParameterIuivRobustANGLE)}, - {"glGetSamplerParameterfv", P(GL_GetSamplerParameterfv)}, - {"glGetSamplerParameterfvRobustANGLE", P(GL_GetSamplerParameterfvRobustANGLE)}, - {"glGetSamplerParameteriv", P(GL_GetSamplerParameteriv)}, - {"glGetSamplerParameterivRobustANGLE", P(GL_GetSamplerParameterivRobustANGLE)}, - {"glGetSemaphoreParameterui64vEXT", P(GL_GetSemaphoreParameterui64vEXT)}, - {"glGetShaderInfoLog", P(GL_GetShaderInfoLog)}, - {"glGetShaderPrecisionFormat", P(GL_GetShaderPrecisionFormat)}, - {"glGetShaderSource", P(GL_GetShaderSource)}, - {"glGetShaderiv", P(GL_GetShaderiv)}, - {"glGetShaderivRobustANGLE", P(GL_GetShaderivRobustANGLE)}, - {"glGetString", P(GL_GetString)}, - {"glGetStringi", P(GL_GetStringi)}, - {"glGetSubroutineIndex", P(GL_GetSubroutineIndex)}, - {"glGetSubroutineUniformLocation", P(GL_GetSubroutineUniformLocation)}, - {"glGetSynciv", P(GL_GetSynciv)}, - {"glGetTexEnvfv", P(GL_GetTexEnvfv)}, - {"glGetTexEnviv", P(GL_GetTexEnviv)}, - {"glGetTexEnvxv", P(GL_GetTexEnvxv)}, - {"glGetTexGendv", P(GL_GetTexGendv)}, - {"glGetTexGenfv", P(GL_GetTexGenfv)}, - {"glGetTexGenfvOES", P(GL_GetTexGenfvOES)}, - {"glGetTexGeniv", P(GL_GetTexGeniv)}, - {"glGetTexGenivOES", P(GL_GetTexGenivOES)}, - {"glGetTexGenxvOES", P(GL_GetTexGenxvOES)}, - {"glGetTexImage", P(GL_GetTexImage)}, - {"glGetTexImageANGLE", P(GL_GetTexImageANGLE)}, - {"glGetTexLevelParameterfv", P(GL_GetTexLevelParameterfv)}, - {"glGetTexLevelParameterfvANGLE", P(GL_GetTexLevelParameterfvANGLE)}, - {"glGetTexLevelParameterfvRobustANGLE", P(GL_GetTexLevelParameterfvRobustANGLE)}, - {"glGetTexLevelParameteriv", P(GL_GetTexLevelParameteriv)}, - {"glGetTexLevelParameterivANGLE", P(GL_GetTexLevelParameterivANGLE)}, - {"glGetTexLevelParameterivRobustANGLE", P(GL_GetTexLevelParameterivRobustANGLE)}, - {"glGetTexParameterIiv", P(GL_GetTexParameterIiv)}, - {"glGetTexParameterIivEXT", P(GL_GetTexParameterIivEXT)}, - {"glGetTexParameterIivOES", P(GL_GetTexParameterIivOES)}, - {"glGetTexParameterIivRobustANGLE", P(GL_GetTexParameterIivRobustANGLE)}, - {"glGetTexParameterIuiv", P(GL_GetTexParameterIuiv)}, - {"glGetTexParameterIuivEXT", P(GL_GetTexParameterIuivEXT)}, - {"glGetTexParameterIuivOES", P(GL_GetTexParameterIuivOES)}, - {"glGetTexParameterIuivRobustANGLE", P(GL_GetTexParameterIuivRobustANGLE)}, - {"glGetTexParameterfv", P(GL_GetTexParameterfv)}, - {"glGetTexParameterfvRobustANGLE", P(GL_GetTexParameterfvRobustANGLE)}, - {"glGetTexParameteriv", P(GL_GetTexParameteriv)}, - {"glGetTexParameterivRobustANGLE", P(GL_GetTexParameterivRobustANGLE)}, - {"glGetTexParameterxv", P(GL_GetTexParameterxv)}, - {"glGetTextureImage", P(GL_GetTextureImage)}, - {"glGetTextureLevelParameterfv", P(GL_GetTextureLevelParameterfv)}, - {"glGetTextureLevelParameteriv", P(GL_GetTextureLevelParameteriv)}, - {"glGetTextureParameterIiv", P(GL_GetTextureParameterIiv)}, - {"glGetTextureParameterIuiv", P(GL_GetTextureParameterIuiv)}, - {"glGetTextureParameterfv", P(GL_GetTextureParameterfv)}, - {"glGetTextureParameteriv", P(GL_GetTextureParameteriv)}, - {"glGetTextureSubImage", P(GL_GetTextureSubImage)}, - {"glGetTransformFeedbackVarying", P(GL_GetTransformFeedbackVarying)}, - {"glGetTransformFeedbacki64_v", P(GL_GetTransformFeedbacki64_v)}, - {"glGetTransformFeedbacki_v", P(GL_GetTransformFeedbacki_v)}, - {"glGetTransformFeedbackiv", P(GL_GetTransformFeedbackiv)}, - {"glGetTranslatedShaderSourceANGLE", P(GL_GetTranslatedShaderSourceANGLE)}, - {"glGetUniformBlockIndex", P(GL_GetUniformBlockIndex)}, - {"glGetUniformIndices", P(GL_GetUniformIndices)}, - {"glGetUniformLocation", P(GL_GetUniformLocation)}, - {"glGetUniformSubroutineuiv", P(GL_GetUniformSubroutineuiv)}, - {"glGetUniformdv", P(GL_GetUniformdv)}, - {"glGetUniformfv", P(GL_GetUniformfv)}, - {"glGetUniformfvRobustANGLE", P(GL_GetUniformfvRobustANGLE)}, - {"glGetUniformiv", P(GL_GetUniformiv)}, - {"glGetUniformivRobustANGLE", P(GL_GetUniformivRobustANGLE)}, - {"glGetUniformuiv", P(GL_GetUniformuiv)}, - {"glGetUniformuivRobustANGLE", P(GL_GetUniformuivRobustANGLE)}, - {"glGetUnsignedBytei_vEXT", P(GL_GetUnsignedBytei_vEXT)}, - {"glGetUnsignedBytevEXT", P(GL_GetUnsignedBytevEXT)}, - {"glGetVertexArrayIndexed64iv", P(GL_GetVertexArrayIndexed64iv)}, - {"glGetVertexArrayIndexediv", P(GL_GetVertexArrayIndexediv)}, - {"glGetVertexArrayiv", P(GL_GetVertexArrayiv)}, - {"glGetVertexAttribIiv", P(GL_GetVertexAttribIiv)}, - {"glGetVertexAttribIivRobustANGLE", P(GL_GetVertexAttribIivRobustANGLE)}, - {"glGetVertexAttribIuiv", P(GL_GetVertexAttribIuiv)}, - {"glGetVertexAttribIuivRobustANGLE", P(GL_GetVertexAttribIuivRobustANGLE)}, - {"glGetVertexAttribLdv", P(GL_GetVertexAttribLdv)}, - {"glGetVertexAttribPointerv", P(GL_GetVertexAttribPointerv)}, - {"glGetVertexAttribPointervRobustANGLE", P(GL_GetVertexAttribPointervRobustANGLE)}, - {"glGetVertexAttribdv", P(GL_GetVertexAttribdv)}, - {"glGetVertexAttribfv", P(GL_GetVertexAttribfv)}, - {"glGetVertexAttribfvRobustANGLE", P(GL_GetVertexAttribfvRobustANGLE)}, - {"glGetVertexAttribiv", P(GL_GetVertexAttribiv)}, - {"glGetVertexAttribivRobustANGLE", P(GL_GetVertexAttribivRobustANGLE)}, - {"glGetnColorTable", P(GL_GetnColorTable)}, - {"glGetnCompressedTexImage", P(GL_GetnCompressedTexImage)}, - {"glGetnConvolutionFilter", P(GL_GetnConvolutionFilter)}, - {"glGetnHistogram", P(GL_GetnHistogram)}, - {"glGetnMapdv", P(GL_GetnMapdv)}, - {"glGetnMapfv", P(GL_GetnMapfv)}, - {"glGetnMapiv", P(GL_GetnMapiv)}, - {"glGetnMinmax", P(GL_GetnMinmax)}, - {"glGetnPixelMapfv", P(GL_GetnPixelMapfv)}, - {"glGetnPixelMapuiv", P(GL_GetnPixelMapuiv)}, - {"glGetnPixelMapusv", P(GL_GetnPixelMapusv)}, - {"glGetnPolygonStipple", P(GL_GetnPolygonStipple)}, - {"glGetnSeparableFilter", P(GL_GetnSeparableFilter)}, - {"glGetnTexImage", P(GL_GetnTexImage)}, - {"glGetnUniformdv", P(GL_GetnUniformdv)}, - {"glGetnUniformfv", P(GL_GetnUniformfv)}, - {"glGetnUniformfvEXT", P(GL_GetnUniformfvEXT)}, - {"glGetnUniformfvKHR", P(GL_GetnUniformfvKHR)}, - {"glGetnUniformfvRobustANGLE", P(GL_GetnUniformfvRobustANGLE)}, - {"glGetnUniformiv", P(GL_GetnUniformiv)}, - {"glGetnUniformivEXT", P(GL_GetnUniformivEXT)}, - {"glGetnUniformivKHR", P(GL_GetnUniformivKHR)}, - {"glGetnUniformivRobustANGLE", P(GL_GetnUniformivRobustANGLE)}, - {"glGetnUniformuiv", P(GL_GetnUniformuiv)}, - {"glGetnUniformuivKHR", P(GL_GetnUniformuivKHR)}, - {"glGetnUniformuivRobustANGLE", P(GL_GetnUniformuivRobustANGLE)}, - {"glHint", P(GL_Hint)}, - {"glImportMemoryFdEXT", P(GL_ImportMemoryFdEXT)}, - {"glImportMemoryZirconHandleANGLE", P(GL_ImportMemoryZirconHandleANGLE)}, - {"glImportSemaphoreFdEXT", P(GL_ImportSemaphoreFdEXT)}, - {"glImportSemaphoreZirconHandleANGLE", P(GL_ImportSemaphoreZirconHandleANGLE)}, - {"glIndexMask", P(GL_IndexMask)}, - {"glIndexPointer", P(GL_IndexPointer)}, - {"glIndexd", P(GL_Indexd)}, - {"glIndexdv", P(GL_Indexdv)}, - {"glIndexf", P(GL_Indexf)}, - {"glIndexfv", P(GL_Indexfv)}, - {"glIndexi", P(GL_Indexi)}, - {"glIndexiv", P(GL_Indexiv)}, - {"glIndexs", P(GL_Indexs)}, - {"glIndexsv", P(GL_Indexsv)}, - {"glIndexub", P(GL_Indexub)}, - {"glIndexubv", P(GL_Indexubv)}, - {"glInitNames", P(GL_InitNames)}, - {"glInsertEventMarkerEXT", P(GL_InsertEventMarkerEXT)}, - {"glInterleavedArrays", P(GL_InterleavedArrays)}, - {"glInvalidateBufferData", P(GL_InvalidateBufferData)}, - {"glInvalidateBufferSubData", P(GL_InvalidateBufferSubData)}, - {"glInvalidateFramebuffer", P(GL_InvalidateFramebuffer)}, - {"glInvalidateNamedFramebufferData", P(GL_InvalidateNamedFramebufferData)}, - {"glInvalidateNamedFramebufferSubData", P(GL_InvalidateNamedFramebufferSubData)}, - {"glInvalidateSubFramebuffer", P(GL_InvalidateSubFramebuffer)}, - {"glInvalidateTexImage", P(GL_InvalidateTexImage)}, - {"glInvalidateTexSubImage", P(GL_InvalidateTexSubImage)}, - {"glInvalidateTextureANGLE", P(GL_InvalidateTextureANGLE)}, - {"glIsBuffer", P(GL_IsBuffer)}, - {"glIsEnabled", P(GL_IsEnabled)}, - {"glIsEnabledi", P(GL_IsEnabledi)}, - {"glIsEnablediEXT", P(GL_IsEnablediEXT)}, - {"glIsEnablediOES", P(GL_IsEnablediOES)}, - {"glIsFenceNV", P(GL_IsFenceNV)}, - {"glIsFramebuffer", P(GL_IsFramebuffer)}, - {"glIsFramebufferOES", P(GL_IsFramebufferOES)}, - {"glIsList", P(GL_IsList)}, - {"glIsMemoryObjectEXT", P(GL_IsMemoryObjectEXT)}, - {"glIsProgram", P(GL_IsProgram)}, - {"glIsProgramPipeline", P(GL_IsProgramPipeline)}, - {"glIsProgramPipelineEXT", P(GL_IsProgramPipelineEXT)}, - {"glIsQuery", P(GL_IsQuery)}, - {"glIsQueryEXT", P(GL_IsQueryEXT)}, - {"glIsRenderbuffer", P(GL_IsRenderbuffer)}, - {"glIsRenderbufferOES", P(GL_IsRenderbufferOES)}, - {"glIsSampler", P(GL_IsSampler)}, - {"glIsSemaphoreEXT", P(GL_IsSemaphoreEXT)}, - {"glIsShader", P(GL_IsShader)}, - {"glIsSync", P(GL_IsSync)}, - {"glIsTexture", P(GL_IsTexture)}, - {"glIsTransformFeedback", P(GL_IsTransformFeedback)}, - {"glIsVertexArray", P(GL_IsVertexArray)}, - {"glIsVertexArrayOES", P(GL_IsVertexArrayOES)}, - {"glLabelObjectEXT", P(GL_LabelObjectEXT)}, - {"glLightModelf", P(GL_LightModelf)}, - {"glLightModelfv", P(GL_LightModelfv)}, - {"glLightModeli", P(GL_LightModeli)}, - {"glLightModeliv", P(GL_LightModeliv)}, - {"glLightModelx", P(GL_LightModelx)}, - {"glLightModelxv", P(GL_LightModelxv)}, - {"glLightf", P(GL_Lightf)}, - {"glLightfv", P(GL_Lightfv)}, - {"glLighti", P(GL_Lighti)}, - {"glLightiv", P(GL_Lightiv)}, - {"glLightx", P(GL_Lightx)}, - {"glLightxv", P(GL_Lightxv)}, - {"glLineStipple", P(GL_LineStipple)}, - {"glLineWidth", P(GL_LineWidth)}, - {"glLineWidthx", P(GL_LineWidthx)}, - {"glLinkProgram", P(GL_LinkProgram)}, - {"glListBase", P(GL_ListBase)}, - {"glLoadIdentity", P(GL_LoadIdentity)}, - {"glLoadMatrixd", P(GL_LoadMatrixd)}, - {"glLoadMatrixf", P(GL_LoadMatrixf)}, - {"glLoadMatrixx", P(GL_LoadMatrixx)}, - {"glLoadName", P(GL_LoadName)}, - {"glLoadPaletteFromModelViewMatrixOES", P(GL_LoadPaletteFromModelViewMatrixOES)}, - {"glLoadTransposeMatrixd", P(GL_LoadTransposeMatrixd)}, - {"glLoadTransposeMatrixf", P(GL_LoadTransposeMatrixf)}, - {"glLogicOp", P(GL_LogicOp)}, - {"glLogicOpANGLE", P(GL_LogicOpANGLE)}, - {"glLoseContextCHROMIUM", P(GL_LoseContextCHROMIUM)}, - {"glMap1d", P(GL_Map1d)}, - {"glMap1f", P(GL_Map1f)}, - {"glMap2d", P(GL_Map2d)}, - {"glMap2f", P(GL_Map2f)}, - {"glMapBuffer", P(GL_MapBuffer)}, - {"glMapBufferOES", P(GL_MapBufferOES)}, - {"glMapBufferRange", P(GL_MapBufferRange)}, - {"glMapBufferRangeEXT", P(GL_MapBufferRangeEXT)}, - {"glMapGrid1d", P(GL_MapGrid1d)}, - {"glMapGrid1f", P(GL_MapGrid1f)}, - {"glMapGrid2d", P(GL_MapGrid2d)}, - {"glMapGrid2f", P(GL_MapGrid2f)}, - {"glMapNamedBuffer", P(GL_MapNamedBuffer)}, - {"glMapNamedBufferRange", P(GL_MapNamedBufferRange)}, - {"glMaterialf", P(GL_Materialf)}, - {"glMaterialfv", P(GL_Materialfv)}, - {"glMateriali", P(GL_Materiali)}, - {"glMaterialiv", P(GL_Materialiv)}, - {"glMaterialx", P(GL_Materialx)}, - {"glMaterialxv", P(GL_Materialxv)}, - {"glMatrixIndexPointerOES", P(GL_MatrixIndexPointerOES)}, - {"glMatrixMode", P(GL_MatrixMode)}, - {"glMaxShaderCompilerThreadsKHR", P(GL_MaxShaderCompilerThreadsKHR)}, - {"glMemoryBarrier", P(GL_MemoryBarrier)}, - {"glMemoryBarrierByRegion", P(GL_MemoryBarrierByRegion)}, - {"glMemoryObjectParameterivEXT", P(GL_MemoryObjectParameterivEXT)}, - {"glMinSampleShading", P(GL_MinSampleShading)}, - {"glMinSampleShadingOES", P(GL_MinSampleShadingOES)}, - {"glMultMatrixd", P(GL_MultMatrixd)}, - {"glMultMatrixf", P(GL_MultMatrixf)}, - {"glMultMatrixx", P(GL_MultMatrixx)}, - {"glMultTransposeMatrixd", P(GL_MultTransposeMatrixd)}, - {"glMultTransposeMatrixf", P(GL_MultTransposeMatrixf)}, - {"glMultiDrawArrays", P(GL_MultiDrawArrays)}, - {"glMultiDrawArraysANGLE", P(GL_MultiDrawArraysANGLE)}, - {"glMultiDrawArraysIndirect", P(GL_MultiDrawArraysIndirect)}, - {"glMultiDrawArraysIndirectCount", P(GL_MultiDrawArraysIndirectCount)}, - {"glMultiDrawArraysIndirectEXT", P(GL_MultiDrawArraysIndirectEXT)}, - {"glMultiDrawArraysInstancedANGLE", P(GL_MultiDrawArraysInstancedANGLE)}, - {"glMultiDrawArraysInstancedBaseInstanceANGLE", P(GL_MultiDrawArraysInstancedBaseInstanceANGLE)}, - {"glMultiDrawElements", P(GL_MultiDrawElements)}, - {"glMultiDrawElementsANGLE", P(GL_MultiDrawElementsANGLE)}, - {"glMultiDrawElementsBaseVertex", P(GL_MultiDrawElementsBaseVertex)}, - {"glMultiDrawElementsBaseVertexEXT", P(GL_MultiDrawElementsBaseVertexEXT)}, - {"glMultiDrawElementsIndirect", P(GL_MultiDrawElementsIndirect)}, - {"glMultiDrawElementsIndirectCount", P(GL_MultiDrawElementsIndirectCount)}, - {"glMultiDrawElementsIndirectEXT", P(GL_MultiDrawElementsIndirectEXT)}, - {"glMultiDrawElementsInstancedANGLE", P(GL_MultiDrawElementsInstancedANGLE)}, - {"glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE", P(GL_MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE)}, - {"glMultiTexCoord1d", P(GL_MultiTexCoord1d)}, - {"glMultiTexCoord1dv", P(GL_MultiTexCoord1dv)}, - {"glMultiTexCoord1f", P(GL_MultiTexCoord1f)}, - {"glMultiTexCoord1fv", P(GL_MultiTexCoord1fv)}, - {"glMultiTexCoord1i", P(GL_MultiTexCoord1i)}, - {"glMultiTexCoord1iv", P(GL_MultiTexCoord1iv)}, - {"glMultiTexCoord1s", P(GL_MultiTexCoord1s)}, - {"glMultiTexCoord1sv", P(GL_MultiTexCoord1sv)}, - {"glMultiTexCoord2d", P(GL_MultiTexCoord2d)}, - {"glMultiTexCoord2dv", P(GL_MultiTexCoord2dv)}, - {"glMultiTexCoord2f", P(GL_MultiTexCoord2f)}, - {"glMultiTexCoord2fv", P(GL_MultiTexCoord2fv)}, - {"glMultiTexCoord2i", P(GL_MultiTexCoord2i)}, - {"glMultiTexCoord2iv", P(GL_MultiTexCoord2iv)}, - {"glMultiTexCoord2s", P(GL_MultiTexCoord2s)}, - {"glMultiTexCoord2sv", P(GL_MultiTexCoord2sv)}, - {"glMultiTexCoord3d", P(GL_MultiTexCoord3d)}, - {"glMultiTexCoord3dv", P(GL_MultiTexCoord3dv)}, - {"glMultiTexCoord3f", P(GL_MultiTexCoord3f)}, - {"glMultiTexCoord3fv", P(GL_MultiTexCoord3fv)}, - {"glMultiTexCoord3i", P(GL_MultiTexCoord3i)}, - {"glMultiTexCoord3iv", P(GL_MultiTexCoord3iv)}, - {"glMultiTexCoord3s", P(GL_MultiTexCoord3s)}, - {"glMultiTexCoord3sv", P(GL_MultiTexCoord3sv)}, - {"glMultiTexCoord4d", P(GL_MultiTexCoord4d)}, - {"glMultiTexCoord4dv", P(GL_MultiTexCoord4dv)}, - {"glMultiTexCoord4f", P(GL_MultiTexCoord4f)}, - {"glMultiTexCoord4fv", P(GL_MultiTexCoord4fv)}, - {"glMultiTexCoord4i", P(GL_MultiTexCoord4i)}, - {"glMultiTexCoord4iv", P(GL_MultiTexCoord4iv)}, - {"glMultiTexCoord4s", P(GL_MultiTexCoord4s)}, - {"glMultiTexCoord4sv", P(GL_MultiTexCoord4sv)}, - {"glMultiTexCoord4x", P(GL_MultiTexCoord4x)}, - {"glMultiTexCoordP1ui", P(GL_MultiTexCoordP1ui)}, - {"glMultiTexCoordP1uiv", P(GL_MultiTexCoordP1uiv)}, - {"glMultiTexCoordP2ui", P(GL_MultiTexCoordP2ui)}, - {"glMultiTexCoordP2uiv", P(GL_MultiTexCoordP2uiv)}, - {"glMultiTexCoordP3ui", P(GL_MultiTexCoordP3ui)}, - {"glMultiTexCoordP3uiv", P(GL_MultiTexCoordP3uiv)}, - {"glMultiTexCoordP4ui", P(GL_MultiTexCoordP4ui)}, - {"glMultiTexCoordP4uiv", P(GL_MultiTexCoordP4uiv)}, - {"glNamedBufferData", P(GL_NamedBufferData)}, - {"glNamedBufferStorage", P(GL_NamedBufferStorage)}, - {"glNamedBufferStorageExternalEXT", P(GL_NamedBufferStorageExternalEXT)}, - {"glNamedBufferSubData", P(GL_NamedBufferSubData)}, - {"glNamedFramebufferDrawBuffer", P(GL_NamedFramebufferDrawBuffer)}, - {"glNamedFramebufferDrawBuffers", P(GL_NamedFramebufferDrawBuffers)}, - {"glNamedFramebufferParameteri", P(GL_NamedFramebufferParameteri)}, - {"glNamedFramebufferReadBuffer", P(GL_NamedFramebufferReadBuffer)}, - {"glNamedFramebufferRenderbuffer", P(GL_NamedFramebufferRenderbuffer)}, - {"glNamedFramebufferTexture", P(GL_NamedFramebufferTexture)}, - {"glNamedFramebufferTextureLayer", P(GL_NamedFramebufferTextureLayer)}, - {"glNamedRenderbufferStorage", P(GL_NamedRenderbufferStorage)}, - {"glNamedRenderbufferStorageMultisample", P(GL_NamedRenderbufferStorageMultisample)}, - {"glNewList", P(GL_NewList)}, - {"glNormal3b", P(GL_Normal3b)}, - {"glNormal3bv", P(GL_Normal3bv)}, - {"glNormal3d", P(GL_Normal3d)}, - {"glNormal3dv", P(GL_Normal3dv)}, - {"glNormal3f", P(GL_Normal3f)}, - {"glNormal3fv", P(GL_Normal3fv)}, - {"glNormal3i", P(GL_Normal3i)}, - {"glNormal3iv", P(GL_Normal3iv)}, - {"glNormal3s", P(GL_Normal3s)}, - {"glNormal3sv", P(GL_Normal3sv)}, - {"glNormal3x", P(GL_Normal3x)}, - {"glNormalP3ui", P(GL_NormalP3ui)}, - {"glNormalP3uiv", P(GL_NormalP3uiv)}, - {"glNormalPointer", P(GL_NormalPointer)}, - {"glObjectLabel", P(GL_ObjectLabel)}, - {"glObjectLabelKHR", P(GL_ObjectLabelKHR)}, - {"glObjectPtrLabel", P(GL_ObjectPtrLabel)}, - {"glObjectPtrLabelKHR", P(GL_ObjectPtrLabelKHR)}, - {"glOrtho", P(GL_Ortho)}, - {"glOrthof", P(GL_Orthof)}, - {"glOrthox", P(GL_Orthox)}, - {"glPassThrough", P(GL_PassThrough)}, - {"glPatchParameterfv", P(GL_PatchParameterfv)}, - {"glPatchParameteri", P(GL_PatchParameteri)}, - {"glPatchParameteriEXT", P(GL_PatchParameteriEXT)}, - {"glPatchParameteriOES", P(GL_PatchParameteriOES)}, - {"glPauseTransformFeedback", P(GL_PauseTransformFeedback)}, - {"glPixelLocalStorageBarrierANGLE", P(GL_PixelLocalStorageBarrierANGLE)}, - {"glPixelMapfv", P(GL_PixelMapfv)}, - {"glPixelMapuiv", P(GL_PixelMapuiv)}, - {"glPixelMapusv", P(GL_PixelMapusv)}, - {"glPixelStoref", P(GL_PixelStoref)}, - {"glPixelStorei", P(GL_PixelStorei)}, - {"glPixelTransferf", P(GL_PixelTransferf)}, - {"glPixelTransferi", P(GL_PixelTransferi)}, - {"glPixelZoom", P(GL_PixelZoom)}, - {"glPointParameterf", P(GL_PointParameterf)}, - {"glPointParameterfv", P(GL_PointParameterfv)}, - {"glPointParameteri", P(GL_PointParameteri)}, - {"glPointParameteriv", P(GL_PointParameteriv)}, - {"glPointParameterx", P(GL_PointParameterx)}, - {"glPointParameterxv", P(GL_PointParameterxv)}, - {"glPointSize", P(GL_PointSize)}, - {"glPointSizePointerOES", P(GL_PointSizePointerOES)}, - {"glPointSizex", P(GL_PointSizex)}, - {"glPolygonMode", P(GL_PolygonMode)}, - {"glPolygonModeANGLE", P(GL_PolygonModeANGLE)}, - {"glPolygonModeNV", P(GL_PolygonModeNV)}, - {"glPolygonOffset", P(GL_PolygonOffset)}, - {"glPolygonOffsetClamp", P(GL_PolygonOffsetClamp)}, - {"glPolygonOffsetClampEXT", P(GL_PolygonOffsetClampEXT)}, - {"glPolygonOffsetx", P(GL_PolygonOffsetx)}, - {"glPolygonStipple", P(GL_PolygonStipple)}, - {"glPopAttrib", P(GL_PopAttrib)}, - {"glPopClientAttrib", P(GL_PopClientAttrib)}, - {"glPopDebugGroup", P(GL_PopDebugGroup)}, - {"glPopDebugGroupKHR", P(GL_PopDebugGroupKHR)}, - {"glPopGroupMarkerEXT", P(GL_PopGroupMarkerEXT)}, - {"glPopMatrix", P(GL_PopMatrix)}, - {"glPopName", P(GL_PopName)}, - {"glPrimitiveBoundingBox", P(GL_PrimitiveBoundingBox)}, - {"glPrimitiveBoundingBoxEXT", P(GL_PrimitiveBoundingBoxEXT)}, - {"glPrimitiveBoundingBoxOES", P(GL_PrimitiveBoundingBoxOES)}, - {"glPrimitiveRestartIndex", P(GL_PrimitiveRestartIndex)}, - {"glPrioritizeTextures", P(GL_PrioritizeTextures)}, - {"glProgramBinary", P(GL_ProgramBinary)}, - {"glProgramBinaryOES", P(GL_ProgramBinaryOES)}, - {"glProgramParameteri", P(GL_ProgramParameteri)}, - {"glProgramParameteriEXT", P(GL_ProgramParameteriEXT)}, - {"glProgramUniform1d", P(GL_ProgramUniform1d)}, - {"glProgramUniform1dv", P(GL_ProgramUniform1dv)}, - {"glProgramUniform1f", P(GL_ProgramUniform1f)}, - {"glProgramUniform1fEXT", P(GL_ProgramUniform1fEXT)}, - {"glProgramUniform1fv", P(GL_ProgramUniform1fv)}, - {"glProgramUniform1fvEXT", P(GL_ProgramUniform1fvEXT)}, - {"glProgramUniform1i", P(GL_ProgramUniform1i)}, - {"glProgramUniform1iEXT", P(GL_ProgramUniform1iEXT)}, - {"glProgramUniform1iv", P(GL_ProgramUniform1iv)}, - {"glProgramUniform1ivEXT", P(GL_ProgramUniform1ivEXT)}, - {"glProgramUniform1ui", P(GL_ProgramUniform1ui)}, - {"glProgramUniform1uiEXT", P(GL_ProgramUniform1uiEXT)}, - {"glProgramUniform1uiv", P(GL_ProgramUniform1uiv)}, - {"glProgramUniform1uivEXT", P(GL_ProgramUniform1uivEXT)}, - {"glProgramUniform2d", P(GL_ProgramUniform2d)}, - {"glProgramUniform2dv", P(GL_ProgramUniform2dv)}, - {"glProgramUniform2f", P(GL_ProgramUniform2f)}, - {"glProgramUniform2fEXT", P(GL_ProgramUniform2fEXT)}, - {"glProgramUniform2fv", P(GL_ProgramUniform2fv)}, - {"glProgramUniform2fvEXT", P(GL_ProgramUniform2fvEXT)}, - {"glProgramUniform2i", P(GL_ProgramUniform2i)}, - {"glProgramUniform2iEXT", P(GL_ProgramUniform2iEXT)}, - {"glProgramUniform2iv", P(GL_ProgramUniform2iv)}, - {"glProgramUniform2ivEXT", P(GL_ProgramUniform2ivEXT)}, - {"glProgramUniform2ui", P(GL_ProgramUniform2ui)}, - {"glProgramUniform2uiEXT", P(GL_ProgramUniform2uiEXT)}, - {"glProgramUniform2uiv", P(GL_ProgramUniform2uiv)}, - {"glProgramUniform2uivEXT", P(GL_ProgramUniform2uivEXT)}, - {"glProgramUniform3d", P(GL_ProgramUniform3d)}, - {"glProgramUniform3dv", P(GL_ProgramUniform3dv)}, - {"glProgramUniform3f", P(GL_ProgramUniform3f)}, - {"glProgramUniform3fEXT", P(GL_ProgramUniform3fEXT)}, - {"glProgramUniform3fv", P(GL_ProgramUniform3fv)}, - {"glProgramUniform3fvEXT", P(GL_ProgramUniform3fvEXT)}, - {"glProgramUniform3i", P(GL_ProgramUniform3i)}, - {"glProgramUniform3iEXT", P(GL_ProgramUniform3iEXT)}, - {"glProgramUniform3iv", P(GL_ProgramUniform3iv)}, - {"glProgramUniform3ivEXT", P(GL_ProgramUniform3ivEXT)}, - {"glProgramUniform3ui", P(GL_ProgramUniform3ui)}, - {"glProgramUniform3uiEXT", P(GL_ProgramUniform3uiEXT)}, - {"glProgramUniform3uiv", P(GL_ProgramUniform3uiv)}, - {"glProgramUniform3uivEXT", P(GL_ProgramUniform3uivEXT)}, - {"glProgramUniform4d", P(GL_ProgramUniform4d)}, - {"glProgramUniform4dv", P(GL_ProgramUniform4dv)}, - {"glProgramUniform4f", P(GL_ProgramUniform4f)}, - {"glProgramUniform4fEXT", P(GL_ProgramUniform4fEXT)}, - {"glProgramUniform4fv", P(GL_ProgramUniform4fv)}, - {"glProgramUniform4fvEXT", P(GL_ProgramUniform4fvEXT)}, - {"glProgramUniform4i", P(GL_ProgramUniform4i)}, - {"glProgramUniform4iEXT", P(GL_ProgramUniform4iEXT)}, - {"glProgramUniform4iv", P(GL_ProgramUniform4iv)}, - {"glProgramUniform4ivEXT", P(GL_ProgramUniform4ivEXT)}, - {"glProgramUniform4ui", P(GL_ProgramUniform4ui)}, - {"glProgramUniform4uiEXT", P(GL_ProgramUniform4uiEXT)}, - {"glProgramUniform4uiv", P(GL_ProgramUniform4uiv)}, - {"glProgramUniform4uivEXT", P(GL_ProgramUniform4uivEXT)}, - {"glProgramUniformMatrix2dv", P(GL_ProgramUniformMatrix2dv)}, - {"glProgramUniformMatrix2fv", P(GL_ProgramUniformMatrix2fv)}, - {"glProgramUniformMatrix2fvEXT", P(GL_ProgramUniformMatrix2fvEXT)}, - {"glProgramUniformMatrix2x3dv", P(GL_ProgramUniformMatrix2x3dv)}, - {"glProgramUniformMatrix2x3fv", P(GL_ProgramUniformMatrix2x3fv)}, - {"glProgramUniformMatrix2x3fvEXT", P(GL_ProgramUniformMatrix2x3fvEXT)}, - {"glProgramUniformMatrix2x4dv", P(GL_ProgramUniformMatrix2x4dv)}, - {"glProgramUniformMatrix2x4fv", P(GL_ProgramUniformMatrix2x4fv)}, - {"glProgramUniformMatrix2x4fvEXT", P(GL_ProgramUniformMatrix2x4fvEXT)}, - {"glProgramUniformMatrix3dv", P(GL_ProgramUniformMatrix3dv)}, - {"glProgramUniformMatrix3fv", P(GL_ProgramUniformMatrix3fv)}, - {"glProgramUniformMatrix3fvEXT", P(GL_ProgramUniformMatrix3fvEXT)}, - {"glProgramUniformMatrix3x2dv", P(GL_ProgramUniformMatrix3x2dv)}, - {"glProgramUniformMatrix3x2fv", P(GL_ProgramUniformMatrix3x2fv)}, - {"glProgramUniformMatrix3x2fvEXT", P(GL_ProgramUniformMatrix3x2fvEXT)}, - {"glProgramUniformMatrix3x4dv", P(GL_ProgramUniformMatrix3x4dv)}, - {"glProgramUniformMatrix3x4fv", P(GL_ProgramUniformMatrix3x4fv)}, - {"glProgramUniformMatrix3x4fvEXT", P(GL_ProgramUniformMatrix3x4fvEXT)}, - {"glProgramUniformMatrix4dv", P(GL_ProgramUniformMatrix4dv)}, - {"glProgramUniformMatrix4fv", P(GL_ProgramUniformMatrix4fv)}, - {"glProgramUniformMatrix4fvEXT", P(GL_ProgramUniformMatrix4fvEXT)}, - {"glProgramUniformMatrix4x2dv", P(GL_ProgramUniformMatrix4x2dv)}, - {"glProgramUniformMatrix4x2fv", P(GL_ProgramUniformMatrix4x2fv)}, - {"glProgramUniformMatrix4x2fvEXT", P(GL_ProgramUniformMatrix4x2fvEXT)}, - {"glProgramUniformMatrix4x3dv", P(GL_ProgramUniformMatrix4x3dv)}, - {"glProgramUniformMatrix4x3fv", P(GL_ProgramUniformMatrix4x3fv)}, - {"glProgramUniformMatrix4x3fvEXT", P(GL_ProgramUniformMatrix4x3fvEXT)}, - {"glProvokingVertex", P(GL_ProvokingVertex)}, - {"glProvokingVertexANGLE", P(GL_ProvokingVertexANGLE)}, - {"glPushAttrib", P(GL_PushAttrib)}, - {"glPushClientAttrib", P(GL_PushClientAttrib)}, - {"glPushDebugGroup", P(GL_PushDebugGroup)}, - {"glPushDebugGroupKHR", P(GL_PushDebugGroupKHR)}, - {"glPushGroupMarkerEXT", P(GL_PushGroupMarkerEXT)}, - {"glPushMatrix", P(GL_PushMatrix)}, - {"glPushName", P(GL_PushName)}, - {"glQueryCounter", P(GL_QueryCounter)}, - {"glQueryCounterEXT", P(GL_QueryCounterEXT)}, - {"glQueryMatrixxOES", P(GL_QueryMatrixxOES)}, - {"glRasterPos2d", P(GL_RasterPos2d)}, - {"glRasterPos2dv", P(GL_RasterPos2dv)}, - {"glRasterPos2f", P(GL_RasterPos2f)}, - {"glRasterPos2fv", P(GL_RasterPos2fv)}, - {"glRasterPos2i", P(GL_RasterPos2i)}, - {"glRasterPos2iv", P(GL_RasterPos2iv)}, - {"glRasterPos2s", P(GL_RasterPos2s)}, - {"glRasterPos2sv", P(GL_RasterPos2sv)}, - {"glRasterPos3d", P(GL_RasterPos3d)}, - {"glRasterPos3dv", P(GL_RasterPos3dv)}, - {"glRasterPos3f", P(GL_RasterPos3f)}, - {"glRasterPos3fv", P(GL_RasterPos3fv)}, - {"glRasterPos3i", P(GL_RasterPos3i)}, - {"glRasterPos3iv", P(GL_RasterPos3iv)}, - {"glRasterPos3s", P(GL_RasterPos3s)}, - {"glRasterPos3sv", P(GL_RasterPos3sv)}, - {"glRasterPos4d", P(GL_RasterPos4d)}, - {"glRasterPos4dv", P(GL_RasterPos4dv)}, - {"glRasterPos4f", P(GL_RasterPos4f)}, - {"glRasterPos4fv", P(GL_RasterPos4fv)}, - {"glRasterPos4i", P(GL_RasterPos4i)}, - {"glRasterPos4iv", P(GL_RasterPos4iv)}, - {"glRasterPos4s", P(GL_RasterPos4s)}, - {"glRasterPos4sv", P(GL_RasterPos4sv)}, - {"glReadBuffer", P(GL_ReadBuffer)}, - {"glReadPixels", P(GL_ReadPixels)}, - {"glReadPixelsRobustANGLE", P(GL_ReadPixelsRobustANGLE)}, - {"glReadnPixels", P(GL_ReadnPixels)}, - {"glReadnPixelsEXT", P(GL_ReadnPixelsEXT)}, - {"glReadnPixelsKHR", P(GL_ReadnPixelsKHR)}, - {"glReadnPixelsRobustANGLE", P(GL_ReadnPixelsRobustANGLE)}, - {"glRectd", P(GL_Rectd)}, - {"glRectdv", P(GL_Rectdv)}, - {"glRectf", P(GL_Rectf)}, - {"glRectfv", P(GL_Rectfv)}, - {"glRecti", P(GL_Recti)}, - {"glRectiv", P(GL_Rectiv)}, - {"glRects", P(GL_Rects)}, - {"glRectsv", P(GL_Rectsv)}, - {"glReleaseShaderCompiler", P(GL_ReleaseShaderCompiler)}, - {"glReleaseTexturesANGLE", P(GL_ReleaseTexturesANGLE)}, - {"glRenderMode", P(GL_RenderMode)}, - {"glRenderbufferStorage", P(GL_RenderbufferStorage)}, - {"glRenderbufferStorageMultisample", P(GL_RenderbufferStorageMultisample)}, - {"glRenderbufferStorageMultisampleANGLE", P(GL_RenderbufferStorageMultisampleANGLE)}, - {"glRenderbufferStorageMultisampleEXT", P(GL_RenderbufferStorageMultisampleEXT)}, - {"glRenderbufferStorageOES", P(GL_RenderbufferStorageOES)}, - {"glRequestExtensionANGLE", P(GL_RequestExtensionANGLE)}, - {"glResumeTransformFeedback", P(GL_ResumeTransformFeedback)}, - {"glRotated", P(GL_Rotated)}, - {"glRotatef", P(GL_Rotatef)}, - {"glRotatex", P(GL_Rotatex)}, - {"glSampleCoverage", P(GL_SampleCoverage)}, - {"glSampleCoveragex", P(GL_SampleCoveragex)}, - {"glSampleMaski", P(GL_SampleMaski)}, - {"glSampleMaskiANGLE", P(GL_SampleMaskiANGLE)}, - {"glSamplerParameterIiv", P(GL_SamplerParameterIiv)}, - {"glSamplerParameterIivEXT", P(GL_SamplerParameterIivEXT)}, - {"glSamplerParameterIivOES", P(GL_SamplerParameterIivOES)}, - {"glSamplerParameterIivRobustANGLE", P(GL_SamplerParameterIivRobustANGLE)}, - {"glSamplerParameterIuiv", P(GL_SamplerParameterIuiv)}, - {"glSamplerParameterIuivEXT", P(GL_SamplerParameterIuivEXT)}, - {"glSamplerParameterIuivOES", P(GL_SamplerParameterIuivOES)}, - {"glSamplerParameterIuivRobustANGLE", P(GL_SamplerParameterIuivRobustANGLE)}, - {"glSamplerParameterf", P(GL_SamplerParameterf)}, - {"glSamplerParameterfv", P(GL_SamplerParameterfv)}, - {"glSamplerParameterfvRobustANGLE", P(GL_SamplerParameterfvRobustANGLE)}, - {"glSamplerParameteri", P(GL_SamplerParameteri)}, - {"glSamplerParameteriv", P(GL_SamplerParameteriv)}, - {"glSamplerParameterivRobustANGLE", P(GL_SamplerParameterivRobustANGLE)}, - {"glScaled", P(GL_Scaled)}, - {"glScalef", P(GL_Scalef)}, - {"glScalex", P(GL_Scalex)}, - {"glScissor", P(GL_Scissor)}, - {"glScissorArrayv", P(GL_ScissorArrayv)}, - {"glScissorIndexed", P(GL_ScissorIndexed)}, - {"glScissorIndexedv", P(GL_ScissorIndexedv)}, - {"glSecondaryColor3b", P(GL_SecondaryColor3b)}, - {"glSecondaryColor3bv", P(GL_SecondaryColor3bv)}, - {"glSecondaryColor3d", P(GL_SecondaryColor3d)}, - {"glSecondaryColor3dv", P(GL_SecondaryColor3dv)}, - {"glSecondaryColor3f", P(GL_SecondaryColor3f)}, - {"glSecondaryColor3fv", P(GL_SecondaryColor3fv)}, - {"glSecondaryColor3i", P(GL_SecondaryColor3i)}, - {"glSecondaryColor3iv", P(GL_SecondaryColor3iv)}, - {"glSecondaryColor3s", P(GL_SecondaryColor3s)}, - {"glSecondaryColor3sv", P(GL_SecondaryColor3sv)}, - {"glSecondaryColor3ub", P(GL_SecondaryColor3ub)}, - {"glSecondaryColor3ubv", P(GL_SecondaryColor3ubv)}, - {"glSecondaryColor3ui", P(GL_SecondaryColor3ui)}, - {"glSecondaryColor3uiv", P(GL_SecondaryColor3uiv)}, - {"glSecondaryColor3us", P(GL_SecondaryColor3us)}, - {"glSecondaryColor3usv", P(GL_SecondaryColor3usv)}, - {"glSecondaryColorP3ui", P(GL_SecondaryColorP3ui)}, - {"glSecondaryColorP3uiv", P(GL_SecondaryColorP3uiv)}, - {"glSecondaryColorPointer", P(GL_SecondaryColorPointer)}, - {"glSelectBuffer", P(GL_SelectBuffer)}, - {"glSelectPerfMonitorCountersAMD", P(GL_SelectPerfMonitorCountersAMD)}, - {"glSemaphoreParameterui64vEXT", P(GL_SemaphoreParameterui64vEXT)}, - {"glSetFenceNV", P(GL_SetFenceNV)}, - {"glShadeModel", P(GL_ShadeModel)}, - {"glShaderBinary", P(GL_ShaderBinary)}, - {"glShaderSource", P(GL_ShaderSource)}, - {"glShaderStorageBlockBinding", P(GL_ShaderStorageBlockBinding)}, - {"glShadingRateQCOM", P(GL_ShadingRateQCOM)}, - {"glSignalSemaphoreEXT", P(GL_SignalSemaphoreEXT)}, - {"glSpecializeShader", P(GL_SpecializeShader)}, - {"glStartTilingQCOM", P(GL_StartTilingQCOM)}, - {"glStencilFunc", P(GL_StencilFunc)}, - {"glStencilFuncSeparate", P(GL_StencilFuncSeparate)}, - {"glStencilMask", P(GL_StencilMask)}, - {"glStencilMaskSeparate", P(GL_StencilMaskSeparate)}, - {"glStencilOp", P(GL_StencilOp)}, - {"glStencilOpSeparate", P(GL_StencilOpSeparate)}, - {"glTestFenceNV", P(GL_TestFenceNV)}, - {"glTexBuffer", P(GL_TexBuffer)}, - {"glTexBufferEXT", P(GL_TexBufferEXT)}, - {"glTexBufferOES", P(GL_TexBufferOES)}, - {"glTexBufferRange", P(GL_TexBufferRange)}, - {"glTexBufferRangeEXT", P(GL_TexBufferRangeEXT)}, - {"glTexBufferRangeOES", P(GL_TexBufferRangeOES)}, - {"glTexCoord1d", P(GL_TexCoord1d)}, - {"glTexCoord1dv", P(GL_TexCoord1dv)}, - {"glTexCoord1f", P(GL_TexCoord1f)}, - {"glTexCoord1fv", P(GL_TexCoord1fv)}, - {"glTexCoord1i", P(GL_TexCoord1i)}, - {"glTexCoord1iv", P(GL_TexCoord1iv)}, - {"glTexCoord1s", P(GL_TexCoord1s)}, - {"glTexCoord1sv", P(GL_TexCoord1sv)}, - {"glTexCoord2d", P(GL_TexCoord2d)}, - {"glTexCoord2dv", P(GL_TexCoord2dv)}, - {"glTexCoord2f", P(GL_TexCoord2f)}, - {"glTexCoord2fv", P(GL_TexCoord2fv)}, - {"glTexCoord2i", P(GL_TexCoord2i)}, - {"glTexCoord2iv", P(GL_TexCoord2iv)}, - {"glTexCoord2s", P(GL_TexCoord2s)}, - {"glTexCoord2sv", P(GL_TexCoord2sv)}, - {"glTexCoord3d", P(GL_TexCoord3d)}, - {"glTexCoord3dv", P(GL_TexCoord3dv)}, - {"glTexCoord3f", P(GL_TexCoord3f)}, - {"glTexCoord3fv", P(GL_TexCoord3fv)}, - {"glTexCoord3i", P(GL_TexCoord3i)}, - {"glTexCoord3iv", P(GL_TexCoord3iv)}, - {"glTexCoord3s", P(GL_TexCoord3s)}, - {"glTexCoord3sv", P(GL_TexCoord3sv)}, - {"glTexCoord4d", P(GL_TexCoord4d)}, - {"glTexCoord4dv", P(GL_TexCoord4dv)}, - {"glTexCoord4f", P(GL_TexCoord4f)}, - {"glTexCoord4fv", P(GL_TexCoord4fv)}, - {"glTexCoord4i", P(GL_TexCoord4i)}, - {"glTexCoord4iv", P(GL_TexCoord4iv)}, - {"glTexCoord4s", P(GL_TexCoord4s)}, - {"glTexCoord4sv", P(GL_TexCoord4sv)}, - {"glTexCoordP1ui", P(GL_TexCoordP1ui)}, - {"glTexCoordP1uiv", P(GL_TexCoordP1uiv)}, - {"glTexCoordP2ui", P(GL_TexCoordP2ui)}, - {"glTexCoordP2uiv", P(GL_TexCoordP2uiv)}, - {"glTexCoordP3ui", P(GL_TexCoordP3ui)}, - {"glTexCoordP3uiv", P(GL_TexCoordP3uiv)}, - {"glTexCoordP4ui", P(GL_TexCoordP4ui)}, - {"glTexCoordP4uiv", P(GL_TexCoordP4uiv)}, - {"glTexCoordPointer", P(GL_TexCoordPointer)}, - {"glTexEnvf", P(GL_TexEnvf)}, - {"glTexEnvfv", P(GL_TexEnvfv)}, - {"glTexEnvi", P(GL_TexEnvi)}, - {"glTexEnviv", P(GL_TexEnviv)}, - {"glTexEnvx", P(GL_TexEnvx)}, - {"glTexEnvxv", P(GL_TexEnvxv)}, - {"glTexGend", P(GL_TexGend)}, - {"glTexGendv", P(GL_TexGendv)}, - {"glTexGenf", P(GL_TexGenf)}, - {"glTexGenfOES", P(GL_TexGenfOES)}, - {"glTexGenfv", P(GL_TexGenfv)}, - {"glTexGenfvOES", P(GL_TexGenfvOES)}, - {"glTexGeni", P(GL_TexGeni)}, - {"glTexGeniOES", P(GL_TexGeniOES)}, - {"glTexGeniv", P(GL_TexGeniv)}, - {"glTexGenivOES", P(GL_TexGenivOES)}, - {"glTexGenxOES", P(GL_TexGenxOES)}, - {"glTexGenxvOES", P(GL_TexGenxvOES)}, - {"glTexImage1D", P(GL_TexImage1D)}, - {"glTexImage2D", P(GL_TexImage2D)}, - {"glTexImage2DExternalANGLE", P(GL_TexImage2DExternalANGLE)}, - {"glTexImage2DMultisample", P(GL_TexImage2DMultisample)}, - {"glTexImage2DRobustANGLE", P(GL_TexImage2DRobustANGLE)}, - {"glTexImage3D", P(GL_TexImage3D)}, - {"glTexImage3DMultisample", P(GL_TexImage3DMultisample)}, - {"glTexImage3DOES", P(GL_TexImage3DOES)}, - {"glTexImage3DRobustANGLE", P(GL_TexImage3DRobustANGLE)}, - {"glTexParameterIiv", P(GL_TexParameterIiv)}, - {"glTexParameterIivEXT", P(GL_TexParameterIivEXT)}, - {"glTexParameterIivOES", P(GL_TexParameterIivOES)}, - {"glTexParameterIivRobustANGLE", P(GL_TexParameterIivRobustANGLE)}, - {"glTexParameterIuiv", P(GL_TexParameterIuiv)}, - {"glTexParameterIuivEXT", P(GL_TexParameterIuivEXT)}, - {"glTexParameterIuivOES", P(GL_TexParameterIuivOES)}, - {"glTexParameterIuivRobustANGLE", P(GL_TexParameterIuivRobustANGLE)}, - {"glTexParameterf", P(GL_TexParameterf)}, - {"glTexParameterfv", P(GL_TexParameterfv)}, - {"glTexParameterfvRobustANGLE", P(GL_TexParameterfvRobustANGLE)}, - {"glTexParameteri", P(GL_TexParameteri)}, - {"glTexParameteriv", P(GL_TexParameteriv)}, - {"glTexParameterivRobustANGLE", P(GL_TexParameterivRobustANGLE)}, - {"glTexParameterx", P(GL_TexParameterx)}, - {"glTexParameterxv", P(GL_TexParameterxv)}, - {"glTexStorage1D", P(GL_TexStorage1D)}, - {"glTexStorage1DEXT", P(GL_TexStorage1DEXT)}, - {"glTexStorage2D", P(GL_TexStorage2D)}, - {"glTexStorage2DEXT", P(GL_TexStorage2DEXT)}, - {"glTexStorage2DMultisample", P(GL_TexStorage2DMultisample)}, - {"glTexStorage2DMultisampleANGLE", P(GL_TexStorage2DMultisampleANGLE)}, - {"glTexStorage3D", P(GL_TexStorage3D)}, - {"glTexStorage3DEXT", P(GL_TexStorage3DEXT)}, - {"glTexStorage3DMultisample", P(GL_TexStorage3DMultisample)}, - {"glTexStorage3DMultisampleOES", P(GL_TexStorage3DMultisampleOES)}, - {"glTexStorageAttribs2DEXT", P(GL_TexStorageAttribs2DEXT)}, - {"glTexStorageAttribs3DEXT", P(GL_TexStorageAttribs3DEXT)}, - {"glTexStorageMem2DEXT", P(GL_TexStorageMem2DEXT)}, - {"glTexStorageMem2DMultisampleEXT", P(GL_TexStorageMem2DMultisampleEXT)}, - {"glTexStorageMem3DEXT", P(GL_TexStorageMem3DEXT)}, - {"glTexStorageMem3DMultisampleEXT", P(GL_TexStorageMem3DMultisampleEXT)}, - {"glTexStorageMemFlags2DANGLE", P(GL_TexStorageMemFlags2DANGLE)}, - {"glTexStorageMemFlags2DMultisampleANGLE", P(GL_TexStorageMemFlags2DMultisampleANGLE)}, - {"glTexStorageMemFlags3DANGLE", P(GL_TexStorageMemFlags3DANGLE)}, - {"glTexStorageMemFlags3DMultisampleANGLE", P(GL_TexStorageMemFlags3DMultisampleANGLE)}, - {"glTexSubImage1D", P(GL_TexSubImage1D)}, - {"glTexSubImage2D", P(GL_TexSubImage2D)}, - {"glTexSubImage2DRobustANGLE", P(GL_TexSubImage2DRobustANGLE)}, - {"glTexSubImage3D", P(GL_TexSubImage3D)}, - {"glTexSubImage3DOES", P(GL_TexSubImage3DOES)}, - {"glTexSubImage3DRobustANGLE", P(GL_TexSubImage3DRobustANGLE)}, - {"glTextureBarrier", P(GL_TextureBarrier)}, - {"glTextureBuffer", P(GL_TextureBuffer)}, - {"glTextureBufferRange", P(GL_TextureBufferRange)}, - {"glTextureFoveationParametersQCOM", P(GL_TextureFoveationParametersQCOM)}, - {"glTextureParameterIiv", P(GL_TextureParameterIiv)}, - {"glTextureParameterIuiv", P(GL_TextureParameterIuiv)}, - {"glTextureParameterf", P(GL_TextureParameterf)}, - {"glTextureParameterfv", P(GL_TextureParameterfv)}, - {"glTextureParameteri", P(GL_TextureParameteri)}, - {"glTextureParameteriv", P(GL_TextureParameteriv)}, - {"glTextureStorage1D", P(GL_TextureStorage1D)}, - {"glTextureStorage2D", P(GL_TextureStorage2D)}, - {"glTextureStorage2DMultisample", P(GL_TextureStorage2DMultisample)}, - {"glTextureStorage3D", P(GL_TextureStorage3D)}, - {"glTextureStorage3DMultisample", P(GL_TextureStorage3DMultisample)}, - {"glTextureSubImage1D", P(GL_TextureSubImage1D)}, - {"glTextureSubImage2D", P(GL_TextureSubImage2D)}, - {"glTextureSubImage3D", P(GL_TextureSubImage3D)}, - {"glTextureView", P(GL_TextureView)}, - {"glTransformFeedbackBufferBase", P(GL_TransformFeedbackBufferBase)}, - {"glTransformFeedbackBufferRange", P(GL_TransformFeedbackBufferRange)}, - {"glTransformFeedbackVaryings", P(GL_TransformFeedbackVaryings)}, - {"glTranslated", P(GL_Translated)}, - {"glTranslatef", P(GL_Translatef)}, - {"glTranslatex", P(GL_Translatex)}, - {"glUniform1d", P(GL_Uniform1d)}, - {"glUniform1dv", P(GL_Uniform1dv)}, - {"glUniform1f", P(GL_Uniform1f)}, - {"glUniform1fv", P(GL_Uniform1fv)}, - {"glUniform1i", P(GL_Uniform1i)}, - {"glUniform1iv", P(GL_Uniform1iv)}, - {"glUniform1ui", P(GL_Uniform1ui)}, - {"glUniform1uiv", P(GL_Uniform1uiv)}, - {"glUniform2d", P(GL_Uniform2d)}, - {"glUniform2dv", P(GL_Uniform2dv)}, - {"glUniform2f", P(GL_Uniform2f)}, - {"glUniform2fv", P(GL_Uniform2fv)}, - {"glUniform2i", P(GL_Uniform2i)}, - {"glUniform2iv", P(GL_Uniform2iv)}, - {"glUniform2ui", P(GL_Uniform2ui)}, - {"glUniform2uiv", P(GL_Uniform2uiv)}, - {"glUniform3d", P(GL_Uniform3d)}, - {"glUniform3dv", P(GL_Uniform3dv)}, - {"glUniform3f", P(GL_Uniform3f)}, - {"glUniform3fv", P(GL_Uniform3fv)}, - {"glUniform3i", P(GL_Uniform3i)}, - {"glUniform3iv", P(GL_Uniform3iv)}, - {"glUniform3ui", P(GL_Uniform3ui)}, - {"glUniform3uiv", P(GL_Uniform3uiv)}, - {"glUniform4d", P(GL_Uniform4d)}, - {"glUniform4dv", P(GL_Uniform4dv)}, - {"glUniform4f", P(GL_Uniform4f)}, - {"glUniform4fv", P(GL_Uniform4fv)}, - {"glUniform4i", P(GL_Uniform4i)}, - {"glUniform4iv", P(GL_Uniform4iv)}, - {"glUniform4ui", P(GL_Uniform4ui)}, - {"glUniform4uiv", P(GL_Uniform4uiv)}, - {"glUniformBlockBinding", P(GL_UniformBlockBinding)}, - {"glUniformMatrix2dv", P(GL_UniformMatrix2dv)}, - {"glUniformMatrix2fv", P(GL_UniformMatrix2fv)}, - {"glUniformMatrix2x3dv", P(GL_UniformMatrix2x3dv)}, - {"glUniformMatrix2x3fv", P(GL_UniformMatrix2x3fv)}, - {"glUniformMatrix2x4dv", P(GL_UniformMatrix2x4dv)}, - {"glUniformMatrix2x4fv", P(GL_UniformMatrix2x4fv)}, - {"glUniformMatrix3dv", P(GL_UniformMatrix3dv)}, - {"glUniformMatrix3fv", P(GL_UniformMatrix3fv)}, - {"glUniformMatrix3x2dv", P(GL_UniformMatrix3x2dv)}, - {"glUniformMatrix3x2fv", P(GL_UniformMatrix3x2fv)}, - {"glUniformMatrix3x4dv", P(GL_UniformMatrix3x4dv)}, - {"glUniformMatrix3x4fv", P(GL_UniformMatrix3x4fv)}, - {"glUniformMatrix4dv", P(GL_UniformMatrix4dv)}, - {"glUniformMatrix4fv", P(GL_UniformMatrix4fv)}, - {"glUniformMatrix4x2dv", P(GL_UniformMatrix4x2dv)}, - {"glUniformMatrix4x2fv", P(GL_UniformMatrix4x2fv)}, - {"glUniformMatrix4x3dv", P(GL_UniformMatrix4x3dv)}, - {"glUniformMatrix4x3fv", P(GL_UniformMatrix4x3fv)}, - {"glUniformSubroutinesuiv", P(GL_UniformSubroutinesuiv)}, - {"glUnmapBuffer", P(GL_UnmapBuffer)}, - {"glUnmapBufferOES", P(GL_UnmapBufferOES)}, - {"glUnmapNamedBuffer", P(GL_UnmapNamedBuffer)}, - {"glUseProgram", P(GL_UseProgram)}, - {"glUseProgramStages", P(GL_UseProgramStages)}, - {"glUseProgramStagesEXT", P(GL_UseProgramStagesEXT)}, - {"glValidateProgram", P(GL_ValidateProgram)}, - {"glValidateProgramPipeline", P(GL_ValidateProgramPipeline)}, - {"glValidateProgramPipelineEXT", P(GL_ValidateProgramPipelineEXT)}, - {"glVertex2d", P(GL_Vertex2d)}, - {"glVertex2dv", P(GL_Vertex2dv)}, - {"glVertex2f", P(GL_Vertex2f)}, - {"glVertex2fv", P(GL_Vertex2fv)}, - {"glVertex2i", P(GL_Vertex2i)}, - {"glVertex2iv", P(GL_Vertex2iv)}, - {"glVertex2s", P(GL_Vertex2s)}, - {"glVertex2sv", P(GL_Vertex2sv)}, - {"glVertex3d", P(GL_Vertex3d)}, - {"glVertex3dv", P(GL_Vertex3dv)}, - {"glVertex3f", P(GL_Vertex3f)}, - {"glVertex3fv", P(GL_Vertex3fv)}, - {"glVertex3i", P(GL_Vertex3i)}, - {"glVertex3iv", P(GL_Vertex3iv)}, - {"glVertex3s", P(GL_Vertex3s)}, - {"glVertex3sv", P(GL_Vertex3sv)}, - {"glVertex4d", P(GL_Vertex4d)}, - {"glVertex4dv", P(GL_Vertex4dv)}, - {"glVertex4f", P(GL_Vertex4f)}, - {"glVertex4fv", P(GL_Vertex4fv)}, - {"glVertex4i", P(GL_Vertex4i)}, - {"glVertex4iv", P(GL_Vertex4iv)}, - {"glVertex4s", P(GL_Vertex4s)}, - {"glVertex4sv", P(GL_Vertex4sv)}, - {"glVertexArrayAttribBinding", P(GL_VertexArrayAttribBinding)}, - {"glVertexArrayAttribFormat", P(GL_VertexArrayAttribFormat)}, - {"glVertexArrayAttribIFormat", P(GL_VertexArrayAttribIFormat)}, - {"glVertexArrayAttribLFormat", P(GL_VertexArrayAttribLFormat)}, - {"glVertexArrayBindingDivisor", P(GL_VertexArrayBindingDivisor)}, - {"glVertexArrayElementBuffer", P(GL_VertexArrayElementBuffer)}, - {"glVertexArrayVertexBuffer", P(GL_VertexArrayVertexBuffer)}, - {"glVertexArrayVertexBuffers", P(GL_VertexArrayVertexBuffers)}, - {"glVertexAttrib1d", P(GL_VertexAttrib1d)}, - {"glVertexAttrib1dv", P(GL_VertexAttrib1dv)}, - {"glVertexAttrib1f", P(GL_VertexAttrib1f)}, - {"glVertexAttrib1fv", P(GL_VertexAttrib1fv)}, - {"glVertexAttrib1s", P(GL_VertexAttrib1s)}, - {"glVertexAttrib1sv", P(GL_VertexAttrib1sv)}, - {"glVertexAttrib2d", P(GL_VertexAttrib2d)}, - {"glVertexAttrib2dv", P(GL_VertexAttrib2dv)}, - {"glVertexAttrib2f", P(GL_VertexAttrib2f)}, - {"glVertexAttrib2fv", P(GL_VertexAttrib2fv)}, - {"glVertexAttrib2s", P(GL_VertexAttrib2s)}, - {"glVertexAttrib2sv", P(GL_VertexAttrib2sv)}, - {"glVertexAttrib3d", P(GL_VertexAttrib3d)}, - {"glVertexAttrib3dv", P(GL_VertexAttrib3dv)}, - {"glVertexAttrib3f", P(GL_VertexAttrib3f)}, - {"glVertexAttrib3fv", P(GL_VertexAttrib3fv)}, - {"glVertexAttrib3s", P(GL_VertexAttrib3s)}, - {"glVertexAttrib3sv", P(GL_VertexAttrib3sv)}, - {"glVertexAttrib4Nbv", P(GL_VertexAttrib4Nbv)}, - {"glVertexAttrib4Niv", P(GL_VertexAttrib4Niv)}, - {"glVertexAttrib4Nsv", P(GL_VertexAttrib4Nsv)}, - {"glVertexAttrib4Nub", P(GL_VertexAttrib4Nub)}, - {"glVertexAttrib4Nubv", P(GL_VertexAttrib4Nubv)}, - {"glVertexAttrib4Nuiv", P(GL_VertexAttrib4Nuiv)}, - {"glVertexAttrib4Nusv", P(GL_VertexAttrib4Nusv)}, - {"glVertexAttrib4bv", P(GL_VertexAttrib4bv)}, - {"glVertexAttrib4d", P(GL_VertexAttrib4d)}, - {"glVertexAttrib4dv", P(GL_VertexAttrib4dv)}, - {"glVertexAttrib4f", P(GL_VertexAttrib4f)}, - {"glVertexAttrib4fv", P(GL_VertexAttrib4fv)}, - {"glVertexAttrib4iv", P(GL_VertexAttrib4iv)}, - {"glVertexAttrib4s", P(GL_VertexAttrib4s)}, - {"glVertexAttrib4sv", P(GL_VertexAttrib4sv)}, - {"glVertexAttrib4ubv", P(GL_VertexAttrib4ubv)}, - {"glVertexAttrib4uiv", P(GL_VertexAttrib4uiv)}, - {"glVertexAttrib4usv", P(GL_VertexAttrib4usv)}, - {"glVertexAttribBinding", P(GL_VertexAttribBinding)}, - {"glVertexAttribDivisor", P(GL_VertexAttribDivisor)}, - {"glVertexAttribDivisorANGLE", P(GL_VertexAttribDivisorANGLE)}, - {"glVertexAttribDivisorEXT", P(GL_VertexAttribDivisorEXT)}, - {"glVertexAttribFormat", P(GL_VertexAttribFormat)}, - {"glVertexAttribI1i", P(GL_VertexAttribI1i)}, - {"glVertexAttribI1iv", P(GL_VertexAttribI1iv)}, - {"glVertexAttribI1ui", P(GL_VertexAttribI1ui)}, - {"glVertexAttribI1uiv", P(GL_VertexAttribI1uiv)}, - {"glVertexAttribI2i", P(GL_VertexAttribI2i)}, - {"glVertexAttribI2iv", P(GL_VertexAttribI2iv)}, - {"glVertexAttribI2ui", P(GL_VertexAttribI2ui)}, - {"glVertexAttribI2uiv", P(GL_VertexAttribI2uiv)}, - {"glVertexAttribI3i", P(GL_VertexAttribI3i)}, - {"glVertexAttribI3iv", P(GL_VertexAttribI3iv)}, - {"glVertexAttribI3ui", P(GL_VertexAttribI3ui)}, - {"glVertexAttribI3uiv", P(GL_VertexAttribI3uiv)}, - {"glVertexAttribI4bv", P(GL_VertexAttribI4bv)}, - {"glVertexAttribI4i", P(GL_VertexAttribI4i)}, - {"glVertexAttribI4iv", P(GL_VertexAttribI4iv)}, - {"glVertexAttribI4sv", P(GL_VertexAttribI4sv)}, - {"glVertexAttribI4ubv", P(GL_VertexAttribI4ubv)}, - {"glVertexAttribI4ui", P(GL_VertexAttribI4ui)}, - {"glVertexAttribI4uiv", P(GL_VertexAttribI4uiv)}, - {"glVertexAttribI4usv", P(GL_VertexAttribI4usv)}, - {"glVertexAttribIFormat", P(GL_VertexAttribIFormat)}, - {"glVertexAttribIPointer", P(GL_VertexAttribIPointer)}, - {"glVertexAttribL1d", P(GL_VertexAttribL1d)}, - {"glVertexAttribL1dv", P(GL_VertexAttribL1dv)}, - {"glVertexAttribL2d", P(GL_VertexAttribL2d)}, - {"glVertexAttribL2dv", P(GL_VertexAttribL2dv)}, - {"glVertexAttribL3d", P(GL_VertexAttribL3d)}, - {"glVertexAttribL3dv", P(GL_VertexAttribL3dv)}, - {"glVertexAttribL4d", P(GL_VertexAttribL4d)}, - {"glVertexAttribL4dv", P(GL_VertexAttribL4dv)}, - {"glVertexAttribLFormat", P(GL_VertexAttribLFormat)}, - {"glVertexAttribLPointer", P(GL_VertexAttribLPointer)}, - {"glVertexAttribP1ui", P(GL_VertexAttribP1ui)}, - {"glVertexAttribP1uiv", P(GL_VertexAttribP1uiv)}, - {"glVertexAttribP2ui", P(GL_VertexAttribP2ui)}, - {"glVertexAttribP2uiv", P(GL_VertexAttribP2uiv)}, - {"glVertexAttribP3ui", P(GL_VertexAttribP3ui)}, - {"glVertexAttribP3uiv", P(GL_VertexAttribP3uiv)}, - {"glVertexAttribP4ui", P(GL_VertexAttribP4ui)}, - {"glVertexAttribP4uiv", P(GL_VertexAttribP4uiv)}, - {"glVertexAttribPointer", P(GL_VertexAttribPointer)}, - {"glVertexBindingDivisor", P(GL_VertexBindingDivisor)}, - {"glVertexP2ui", P(GL_VertexP2ui)}, - {"glVertexP2uiv", P(GL_VertexP2uiv)}, - {"glVertexP3ui", P(GL_VertexP3ui)}, - {"glVertexP3uiv", P(GL_VertexP3uiv)}, - {"glVertexP4ui", P(GL_VertexP4ui)}, - {"glVertexP4uiv", P(GL_VertexP4uiv)}, - {"glVertexPointer", P(GL_VertexPointer)}, - {"glViewport", P(GL_Viewport)}, - {"glViewportArrayv", P(GL_ViewportArrayv)}, - {"glViewportIndexedf", P(GL_ViewportIndexedf)}, - {"glViewportIndexedfv", P(GL_ViewportIndexedfv)}, - {"glWaitSemaphoreEXT", P(GL_WaitSemaphoreEXT)}, - {"glWaitSync", P(GL_WaitSync)}, - {"glWeightPointerOES", P(GL_WeightPointerOES)}, - {"glWindowPos2d", P(GL_WindowPos2d)}, - {"glWindowPos2dv", P(GL_WindowPos2dv)}, - {"glWindowPos2f", P(GL_WindowPos2f)}, - {"glWindowPos2fv", P(GL_WindowPos2fv)}, - {"glWindowPos2i", P(GL_WindowPos2i)}, - {"glWindowPos2iv", P(GL_WindowPos2iv)}, - {"glWindowPos2s", P(GL_WindowPos2s)}, - {"glWindowPos2sv", P(GL_WindowPos2sv)}, - {"glWindowPos3d", P(GL_WindowPos3d)}, - {"glWindowPos3dv", P(GL_WindowPos3dv)}, - {"glWindowPos3f", P(GL_WindowPos3f)}, - {"glWindowPos3fv", P(GL_WindowPos3fv)}, - {"glWindowPos3i", P(GL_WindowPos3i)}, - {"glWindowPos3iv", P(GL_WindowPos3iv)}, - {"glWindowPos3s", P(GL_WindowPos3s)}, - {"glWindowPos3sv", P(GL_WindowPos3sv)}, - {"wglChoosePixelFormat", P(wglChoosePixelFormat)}, - {"wglCopyContext", P(wglCopyContext)}, - {"wglCreateContext", P(wglCreateContext)}, - {"wglCreateLayerContext", P(wglCreateLayerContext)}, - {"wglDeleteContext", P(wglDeleteContext)}, - {"wglDescribeLayerPlane", P(wglDescribeLayerPlane)}, - {"wglDescribePixelFormat", P(wglDescribePixelFormat)}, - {"wglGetCurrentContext", P(wglGetCurrentContext)}, - {"wglGetCurrentDC", P(wglGetCurrentDC)}, - {"wglGetEnhMetaFilePixelFormat", P(wglGetEnhMetaFilePixelFormat)}, - {"wglGetLayerPaletteEntries", P(wglGetLayerPaletteEntries)}, - {"wglGetPixelFormat", P(wglGetPixelFormat)}, - {"wglGetProcAddress", P(wglGetProcAddress)}, - {"wglMakeCurrent", P(wglMakeCurrent)}, - {"wglRealizeLayerPalette", P(wglRealizeLayerPalette)}, - {"wglSetLayerPaletteEntries", P(wglSetLayerPaletteEntries)}, - {"wglSetPixelFormat", P(wglSetPixelFormat)}, - {"wglShareLists", P(wglShareLists)}, - {"wglSwapBuffers", P(wglSwapBuffers)}, - {"wglSwapLayerBuffers", P(wglSwapLayerBuffers)}, - {"wglUseFontBitmaps", P(wglUseFontBitmaps)}, - {"wglUseFontBitmapsA", P(wglUseFontBitmapsA)}, - {"wglUseFontBitmapsW", P(wglUseFontBitmapsW)}, - {"wglUseFontOutlines", P(wglUseFontOutlines)}, - {"wglUseFontOutlinesA", P(wglUseFontOutlinesA)}, - {"wglUseFontOutlinesW", P(wglUseFontOutlinesW)}, -}; -// clang-format on -const size_t g_numProcs = std::size(g_procTable); -} // namespace wgl diff --git a/src/libOpenCL/dispatch.cpp b/src/libOpenCL/dispatch.cpp index d513ce35302..ca8d113eb78 100644 --- a/src/libOpenCL/dispatch.cpp +++ b/src/libOpenCL/dispatch.cpp @@ -89,6 +89,18 @@ IcdDispatch CreateDispatch() static_cast(dispatch) = *clIcdDispatch; dispatch.clIcdGetPlatformIDsKHR = reinterpret_cast( clIcdDispatch->clGetExtensionFunctionAddress("clIcdGetPlatformIDsKHR")); + // TODO: below extensions will be refactored to not to expose them publicly later + // http://anglebug.com/378017028 + dispatch.clEnqueueAcquireExternalMemObjectsKHR = + reinterpret_cast( + clIcdDispatch->clGetExtensionFunctionAddress( + "clEnqueueAcquireExternalMemObjectsKHR")); + dispatch.clEnqueueReleaseExternalMemObjectsKHR = + reinterpret_cast( + clIcdDispatch->clGetExtensionFunctionAddress( + "clEnqueueReleaseExternalMemObjectsKHR")); + dispatch.clImportMemoryARM = reinterpret_cast( + clIcdDispatch->clGetExtensionFunctionAddress("clImportMemoryARM")); } else if (error != nullptr) { diff --git a/src/libOpenCL/dispatch.h b/src/libOpenCL/dispatch.h index 58391c3abe3..1fea7195e3d 100644 --- a/src/libOpenCL/dispatch.h +++ b/src/libOpenCL/dispatch.h @@ -21,6 +21,13 @@ namespace cl struct IcdDispatch : public _cl_icd_dispatch { clIcdGetPlatformIDsKHR_fn clIcdGetPlatformIDsKHR; + // TODO: below extensions will be refactored to not to expose them publicly later + // http://anglebug.com/378017028 + clIcdGetFunctionAddressForPlatformKHR_fn clIcdGetFunctionAddressForPlatformKHR; + clIcdSetPlatformDispatchDataKHR_fn clIcdSetPlatformDispatchDataKHR; + clEnqueueAcquireExternalMemObjectsKHR_fn clEnqueueAcquireExternalMemObjectsKHR; + clEnqueueReleaseExternalMemObjectsKHR_fn clEnqueueReleaseExternalMemObjectsKHR; + clImportMemoryARM_fn clImportMemoryARM; }; const IcdDispatch &GetDispatch(); diff --git a/src/libOpenCL/libOpenCL_autogen.cpp b/src/libOpenCL/libOpenCL_autogen.cpp index c554ddc39cb..c8e41ad53b1 100644 --- a/src/libOpenCL/libOpenCL_autogen.cpp +++ b/src/libOpenCL/libOpenCL_autogen.cpp @@ -1150,6 +1150,43 @@ cl_mem CL_API_CALL clCreateImageWithProperties(cl_context context, image_desc, host_ptr, errcode_ret); } +// cl_arm_import_memory +cl_mem CL_API_CALL clImportMemoryARM(cl_context context, + cl_mem_flags flags, + const cl_import_properties_arm *properties, + void *memory, + size_t size, + cl_int *errcode_ret) +{ + return cl::GetDispatch().clImportMemoryARM(context, flags, properties, memory, size, + errcode_ret); +} + +// cl_khr_external_memory +cl_int CL_API_CALL clEnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) +{ + return cl::GetDispatch().clEnqueueAcquireExternalMemObjectsKHR( + command_queue, num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, + event); +} + +cl_int CL_API_CALL clEnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) +{ + return cl::GetDispatch().clEnqueueReleaseExternalMemObjectsKHR( + command_queue, num_mem_objects, mem_objects, num_events_in_wait_list, event_wait_list, + event); +} + // cl_khr_icd cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *platforms, @@ -1158,4 +1195,15 @@ cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, return cl::GetDispatch().clIcdGetPlatformIDsKHR(num_entries, platforms, num_platforms); } +void *CL_API_CALL clIcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, + const char *func_name) +{ + return cl::GetDispatch().clIcdGetFunctionAddressForPlatformKHR(platform, func_name); +} + +cl_int CL_API_CALL clIcdSetPlatformDispatchDataKHR(cl_platform_id platform, void *dispatch_data) +{ + return cl::GetDispatch().clIcdSetPlatformDispatchDataKHR(platform, dispatch_data); +} + } // extern "C" diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn index 545d39a4ded..bc9a221e6b5 100644 --- a/src/tests/BUILD.gn +++ b/src/tests/BUILD.gn @@ -110,6 +110,9 @@ angle_static_library("angle_test_expectations") { sources += test_expectation_sources_ios frameworks = [ "Foundation.framework" ] } + if (angle_ir) { + configs += [ "${angle_root}:angle_translator_ir" ] + } } config("angle_common_test_utils_config") { @@ -254,6 +257,10 @@ angle_test("angle_unittests") { if (angle_has_rapidjson) { sources += [ "../common/serializer/JsonSerializer_unittest.cpp" ] } + + if (angle_ir) { + configs += [ "${angle_root}:angle_translator_ir" ] + } } if (is_ios) { @@ -329,24 +336,20 @@ if (is_win || is_linux || is_chromeos || is_android || is_fuchsia || is_apple) { deps += [ "$angle_root:angle_json_serializer" ] } - if (build_angle_end2end_tests_aosp) { - # AOSP end2end tests builds don't bundle ANGLE libs or Vulkan tests and don't need the NDK path - } else { - if (is_android) { - include_dirs += [ "${android_ndk_root}/sysroot/usr/includes" ] - } + if (angle_enable_vulkan) { + sources += [ + "gl_tests/VulkanExternalImageTest.cpp", + "gl_tests/VulkanImageTest.cpp", + "test_utils/VulkanHelper.cpp", + "test_utils/VulkanHelper.h", + ] + deps += [ "$angle_root/src/common/vulkan" ] + } + if (angle_test_enable_system_egl) { + # Don't bundle the ANGLE libraries. + } else { data_deps = [ "$angle_root:angle" ] - - if (angle_enable_vulkan) { - sources += [ - "gl_tests/VulkanExternalImageTest.cpp", - "gl_tests/VulkanImageTest.cpp", - "test_utils/VulkanHelper.cpp", - "test_utils/VulkanHelper.h", - ] - deps += [ "$angle_root/src/common/vulkan" ] - } } if (is_android) { @@ -377,6 +380,15 @@ if (is_win || is_linux || is_chromeos || is_android || is_fuchsia || is_apple) { # Need to bundle the libraries inside the .app. deps += [ "$angle_root:angle" ] } + + if (angle_enable_wgpu) { + deps += [ + "${angle_dawn_dir}/include/dawn:headers", + "${angle_dawn_dir}/src/dawn:proc", + "${angle_dawn_dir}/src/dawn/native", + ] + defines += [ "ANGLE_ENABLE_WGPU" ] + } } } @@ -542,6 +554,10 @@ if (is_win || is_linux || is_chromeos || is_android || is_fuchsia || is_apple) { sources += angle_white_box_tests_vulkan_sources deps += [ "$angle_root/src/common/vulkan:angle_vulkan_entry_points" ] } + + if (angle_ir) { + configs += [ "${angle_root}:angle_translator_ir" ] + } } } @@ -589,7 +605,7 @@ template("angle_perftests_common") { public_deps = [ "$angle_root:angle_gl_enum_utils", "$angle_root/src/tests:angle_test_expectations", - "$angle_root/third_party/rapidjson:rapidjson", + "$angle_root/third_party/rapidjson", "${invoker.test_utils}", ] public_configs += [ @@ -699,6 +715,15 @@ if (build_angle_perftests) { } } +if (is_ios) { + bundle_data("angle_trace_tests_bundle_data") { + testonly = true + sources = [ "perf_tests/angle_trace_tests_expectations.txt" ] + outputs = [ "{{bundle_resources_dir}}/" + + "{{source_root_relative_dir}}/{{source_file_part}}" ] + } +} + if (build_angle_trace_tests) { angle_test("angle_trace_tests") { # http://anglebug.com/42264541: Traces with long shaders are hitting string literal @@ -741,6 +766,14 @@ if (build_angle_trace_tests) { data = [ "$angle_root/src/tests/py_utils/android_helper.py" ] + if (is_ios) { + deps += [ ":angle_trace_tests_bundle_data" ] + } else { + data += [ + "$angle_root/src/tests/perf_tests/angle_trace_tests_expectations.txt", + ] + } + if (is_android) { android_test_runner_script = "$angle_root/src/tests/angle_android_test_runner.py" @@ -1329,10 +1362,7 @@ if (build_angle_deqp_tests && !is_fuchsia) { if (is_android) { include_dirs += [ "$deqp_path/framework/platform/android" ] - _android_api = android64_ndk_api_level - if (!angle_64bit_current_cpu) { - _android_api = android32_ndk_api_level - } + _android_api = android_ndk_api_level defines += [ "DE_ANDROID_API=" + "${_android_api}" ] } @@ -1523,7 +1553,7 @@ if (build_angle_deqp_tests && !is_fuchsia) { public_deps = [ ":angle_deqp_framework_debase" ] } - config("angle_deqp_framework_common_config") { + config("angle_deqp_framework_common_public_config") { include_dirs = [ "$deqp_path/framework/common", "$deqp_path/framework/randomshaders", @@ -1531,9 +1561,18 @@ if (build_angle_deqp_tests && !is_fuchsia) { ] } + config("angle_deqp_framework_common_private_config") { + cflags_cc = [ + # Usage of deprecated std::float_denorm_style. + # https://github.com/KhronosGroup/VK-GL-CTS/blob/84f86d999680e3d8a416b578bfc6e86ce8910853/framework/common/tcuFloatFormat.cpp#L275C32-L279 + "-Wno-deprecated-declarations", + ] + } + angle_deqp_source_set("angle_deqp_framework_common") { sources = deqp_framework_common_sources - public_configs = [ ":angle_deqp_framework_common_config" ] + public_configs = [ ":angle_deqp_framework_common_public_config" ] + configs += [ ":angle_deqp_framework_common_private_config" ] public_deps = [ ":angle_deqp_framework_decpp", ":angle_deqp_framework_qphelper", @@ -1755,10 +1794,6 @@ if (build_angle_deqp_tests && !is_fuchsia) { ":angle_deqp_framework_egl", ":angle_deqp_glshared", ] - if (is_clang) { - # TODO(crbug.com/393942204): Unused field in es31fSRGBDecodeTests.cpp - cflags_cc = [ "-Wno-unused-private-field" ] - } } template("angle_deqp_core_gtest") { @@ -1852,6 +1887,7 @@ if (build_angle_deqp_tests && !is_fuchsia) { config("angle_deqp_khr_common_config") { include_dirs = [ "$deqp_path/external/openglcts/modules/common", + "$deqp_path/external/openglcts/modules/common/meshShader", "$deqp_path/external/openglcts/modules/common/subgroups", "$deqp_path/external/openglcts/modules/gl", "$deqp_path/external/openglcts/modules/gles2", @@ -1981,6 +2017,12 @@ if (build_angle_deqp_tests && !is_fuchsia) { api = "gles32" } + angle_deqp_khr_gtest("khr_glesext") { + defines = [ "ANGLE_DEQP_KHR_GLESEXT_TESTS" ] + mustpass_name = "gles32-khr-glesext.txt" + api = "gles32" + } + template("angle_deqp_rotate_gtest") { split_target = string_split(target_name, "_") _api = split_target[0] @@ -2104,6 +2146,7 @@ group("angle_tests") { ":angle_deqp_khr_gles31_tests", ":angle_deqp_khr_gles32_tests", ":angle_deqp_khr_gles3_tests", + ":angle_deqp_khr_glesext_tests", ":angle_deqp_khr_noctx_gles2_tests", ":angle_deqp_khr_noctx_gles32_tests", ":angle_deqp_khr_single_gles32_tests", diff --git a/src/tests/DIR_METADATA b/src/tests/DIR_METADATA new file mode 100644 index 00000000000..25d918dd7d5 --- /dev/null +++ b/src/tests/DIR_METADATA @@ -0,0 +1,3 @@ +buganizer_public { + component_id: 853171 # Public Trackers > ANGLE +} diff --git a/src/tests/angle_android_test_runner.py b/src/tests/angle_android_test_runner.py index a898ed1b642..2fc358ab9d1 100755 --- a/src/tests/angle_android_test_runner.py +++ b/src/tests/angle_android_test_runner.py @@ -52,6 +52,7 @@ def AddCommonParserArgs(parser): 'angle_deqp_khr_gles31_tests', 'angle_deqp_khr_gles32_tests', 'angle_deqp_khr_gles3_tests', + 'angle_deqp_khr_glesext_tests', 'angle_deqp_khr_noctx_gles2_tests', 'angle_deqp_khr_noctx_gles32_tests', 'angle_deqp_khr_single_gles32_tests', diff --git a/src/tests/angle_end2end_tests.gni b/src/tests/angle_end2end_tests.gni index cbb5de01b49..915946ca7b3 100644 --- a/src/tests/angle_end2end_tests.gni +++ b/src/tests/angle_end2end_tests.gni @@ -11,6 +11,7 @@ angle_end2end_tests_sources = [ "egl_tests/EGLChooseConfigTest.cpp", "egl_tests/EGLContextASANTest.cpp", "egl_tests/EGLContextCompatibilityTest.cpp", + "egl_tests/EGLContextPassthroughShadersTest.cpp", "egl_tests/EGLContextSharingTest.cpp", "egl_tests/EGLCreateContextAttribsTest.cpp", "egl_tests/EGLDebugTest.cpp", @@ -88,7 +89,10 @@ angle_end2end_tests_sources = [ "gl_tests/FramebufferMultiviewTest.cpp", "gl_tests/FramebufferRenderMipmapTest.cpp", "gl_tests/FramebufferTest.cpp", + "gl_tests/GLSLConstantFoldingTest.cpp", + "gl_tests/GLSLOutputTest.cpp", "gl_tests/GLSLTest.cpp", + "gl_tests/GLSLValidationTest.cpp", "gl_tests/GeometryShaderTest.cpp", "gl_tests/GetImageTest.cpp", "gl_tests/GetTexLevelParameterTest.cpp", @@ -113,11 +117,13 @@ angle_end2end_tests_sources = [ "gl_tests/MultisampledRenderToTextureTest.cpp", "gl_tests/MultithreadingTest.cpp", "gl_tests/MultiviewDrawTest.cpp", + "gl_tests/MultiviewMultisampledRenderToTextureTest.cpp", "gl_tests/ObjectAllocationTest.cpp", "gl_tests/OcclusionQueriesTest.cpp", "gl_tests/PBOExtensionTest.cpp", "gl_tests/PVRTCCompressedTextureTest.cpp", "gl_tests/PackUnpackTest.cpp", + "gl_tests/PalettedTextureTest.cpp", "gl_tests/ParallelShaderCompileTest.cpp", "gl_tests/PbufferTest.cpp", "gl_tests/PixelLocalStorageTest.cpp", @@ -153,13 +159,13 @@ angle_end2end_tests_sources = [ "gl_tests/ShaderNonConstGlobalInitializerTest.cpp", "gl_tests/ShaderOpTest.cpp", "gl_tests/ShaderStorageBufferTest.cpp", + "gl_tests/ShadingRateEXTTest.cpp", "gl_tests/ShadingRateQcomTest.cpp", "gl_tests/ShadowSamplerFunctionsTest.cpp", "gl_tests/SimpleOperationTest.cpp", "gl_tests/SixteenBppTextureTest.cpp", "gl_tests/StateChangeTest.cpp", "gl_tests/SwizzleTest.cpp", - "gl_tests/SyncQueriesTest.cpp", "gl_tests/TextureExternalUpdateTest.cpp", "gl_tests/TextureFixedRateCompressionTest.cpp", "gl_tests/TextureMultisampleTest.cpp", @@ -167,6 +173,7 @@ angle_end2end_tests_sources = [ "gl_tests/TextureTest.cpp", "gl_tests/TextureUploadFormatTest.cpp", "gl_tests/TiledRenderingTest.cpp", + "gl_tests/TimeoutDrawTest.cpp", "gl_tests/TimerQueriesTest.cpp", "gl_tests/TransformFeedbackTest.cpp", "gl_tests/UniformBufferTest.cpp", @@ -202,7 +209,6 @@ angle_end2end_tests_sources = [ "gl_tests/gles1/MatrixModeTest.cpp", "gl_tests/gles1/MatrixMultTest.cpp", "gl_tests/gles1/MatrixStackTest.cpp", - "gl_tests/gles1/PalettedTextureTest.cpp", "gl_tests/gles1/PointParameterTest.cpp", "gl_tests/gles1/PointSpriteTest.cpp", "gl_tests/gles1/QueryTest.cpp", @@ -217,6 +223,8 @@ angle_end2end_tests_sources = [ "test_utils/ANGLETest.h", "test_utils/ANGLETestCL.cpp", "test_utils/ANGLETestCL.h", + "test_utils/CompilerTest.cpp", + "test_utils/CompilerTest.h", "test_utils/MultiviewTest.cpp", "test_utils/MultiviewTest.h", "test_utils/system_info_util.cpp", @@ -229,6 +237,7 @@ angle_end2end_tests_mac_sources = [ "egl_tests/EGLIOSurfaceClientBufferTest.cpp", "egl_tests/EGLPowerPreferenceTest.cpp", "egl_tests/EGLSurfaceTestMac.mm", + "egl_tests/EGLSyncTestMetalCommandsScheduled.mm", "egl_tests/EGLSyncTestMetalSharedEvent.mm", "egl_tests/EGLWaitUntilWorkScheduledTest.cpp", "gl_tests/ImageTestMetal.mm", diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt index 16dd2f024f7..1fc153eec4a 100644 --- a/src/tests/angle_end2end_tests_expectations.txt +++ b/src/tests/angle_end2end_tests_expectations.txt @@ -10,31 +10,30 @@ 42266467 TSAN : MultithreadingTest.CreateMultiSharedContextAndDraw/* = SKIP // Generic -// Fails in the flush thread when calling eglMakeCurrent. -42264594 OPENGL : SimpleStateChangeTestES31.DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed/* = SKIP -42264594 GLES : SimpleStateChangeTestES31.DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed/* = SKIP // Crashes in setUniformValuesFromBindingQualifiers() because mUniformRealLocationMap is not // initialized when the program is loaded from cache. 42264670 VULKAN : BlitFramebufferTest.BlitDepthStencilPixelByPixel/* = SKIP 42264678 VULKAN WIN INTEL : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP 42264678 VULKAN PIXEL4ORXL : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP -42264866 OPENGL : FramebufferTestWithFormatFallback.R5G5B5A1_BlitCopyTexImage/* = SKIP -42264866 OPENGL : FramebufferTestWithFormatFallback.RGBA4444_BlitCopyTexImage/* = SKIP -42264866 GLES : FramebufferTestWithFormatFallback.R5G5B5A1_BlitCopyTexImage/* = SKIP -42264866 GLES : FramebufferTestWithFormatFallback.RGBA4444_BlitCopyTexImage/* = SKIP 42265462 OPENGL : BlitFramebufferTestES31.OOBResolve/* = SKIP 42265462 GLES : BlitFramebufferTestES31.OOBResolve/* = SKIP +410584013 GLES : ImageTestES3.ImmutableTextureOverwriteBaseLevelAndGenerateMipmapWhileInUse/* = SKIP 42266349 VULKAN : MultithreadingTestES3.UnsynchronizedTextureReads/* = SKIP 42266349 VULKAN : MultithreadingTestES3.UnsynchronizedTextureReads2/* = SKIP -377614665 VULKAN : GLSLTest.StructSamplerVsComma/* = SKIP -// Incorrectly handled pretty much in all backends -42266871 : CopyTexImageTestES3.RedefineSameLevel/* = SKIP +377614665 VULKAN : GLSLValidationTest.StructSamplerVsComma/* = SKIP +410584007 VULKAN : ImageTestES31.UseSourceTextureAsStorageImage/* = SKIP // Fails in Android with EGL_BAD_ALLOC 374797737 : EGLSurfaceTest.CreateMultiWindowsSurfaceNoDestroy/* = SKIP -// Currently fails on WebGPU as it's not fully implemented yet. 381742474 : ShaderStorageBufferTest31.ExceedMaxShaderStorageBlockSize/* = SKIP +// Vulkan color attachment incorrectly configured when GL_RASTERIZER_DISCARD is enabled and no glClear is issued. +// Fails on non-ARM Linux due to unsupported setConfigAlphaBits(0) causing EGL config error. +419403194 VULKAN : VulkanPerformanceCounterTest_RGBSurface.UnrenderedSurfaceShouldNotClear/* = SKIP + +// Angle does not support Array of Arrays in tessellation shader. +413447006 : ProgramInterfaceTestES31.ArrayofArraysQueries/* = SKIP + // ES 3.2 tests are skipped on SwS. 376899587 VULKAN SWIFTSHADER : */ES3_2* = SKIP @@ -53,19 +52,16 @@ 359729255 D3D9 : VertexAttributeTest.VertexAttribPointerCopyBufferFromInvalid* = SKIP 359729255 D3D11 : VertexAttributeTest.VertexAttribPointerCopyBufferFromInvalid* = SKIP 359729255 METAL : VertexAttributeTest.VertexAttribPointerCopyBufferFromInvalid* = SKIP +359729255 WGPU : VertexAttributeTest.VertexAttribPointerCopyBufferFromInvalid* = SKIP + +// Using a non-zero offset non-aligned with the stride. +468923885 WGPU : VertexAttributeTest.BufferOffsetNonAlignedWithStride/* = SKIP -// Does not work due to SeparateDeclarations. -// Would need a pass to name in-out structs based on the contents and dedupe the structs. -42267047 GLES : GLSLTest_ES3.VaryingAnonymousStructEquality/* = SKIP -42267047 GLES : GLSLTest_ES3.VaryingAnonymousStructWithInlineDefinition2/* = SKIP -42267047 GLES : GLSLTest_ES3.VaryingAnonymousStructWithInlineDefinition3/* = SKIP -42267047 OPENGL : GLSLTest_ES3.VaryingAnonymousStructEquality/* = SKIP -42267047 OPENGL : GLSLTest_ES3.VaryingAnonymousStructWithInlineDefinition2/* = SKIP -42267047 OPENGL : GLSLTest_ES3.VaryingAnonymousStructWithInlineDefinition3/* = SKIP -// Crash -42267047 PIXEL4ORXL VULKAN : GLSLTest_ES3.VaryingAnonymousStructEquality/* = SKIP -42267047 PIXEL4ORXL VULKAN : GLSLTest_ES3.VaryingAnonymousStructWithInlineDefinition2/* = SKIP -42267047 PIXEL4ORXL VULKAN : GLSLTest_ES3.VaryingAnonymousStructWithInlineDefinition3/* = SKIP +// Propagate buffer changes to VertexArray fail on some desktop drivers +433331119 LINUX NVIDIA OPENGL : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = SKIP +433331119 LINUX NVIDIA OPENGL : ValidationStateChangeTestES31.RebindVertexBufferShouldPickupBufferChange/* = SKIP +433331119 LINUX INTEL OPENGL : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = SKIP +433331119 LINUX INTEL OPENGL : ValidationStateChangeTestES31.RebindVertexBufferShouldPickupBufferChange/* = SKIP // Shared context failing on OpenGL and D3D11 42266326 METAL : MultithreadingTest.CreateMultiSharedContextAndDraw/* = SKIP @@ -85,8 +81,6 @@ 42265405 VULKAN : Texture2DTestES3.TextureRGBUpdateWithPBO/ES3_Vulkan* = SKIP 42265226 VULKAN : GLSLTest_ES3.GLVertexIDIntegerTextureDrawElementsU8Line/* = SKIP 42265226 VULKAN : GLSLTest_ES3.GLVertexIDIntegerTextureDrawElementsU8LineIds/* = SKIP -42265671 VULKAN : BlitFramebufferTest.BlitMultisampleStencilToDefault/ES3_Vulkan_EmulatedPrerotation90 = SKIP -42265671 VULKAN : BlitFramebufferTest.BlitMultisampleStencilToDefault/ES3_Vulkan_EmulatedPrerotation270 = SKIP 235877059 VULKAN : MultisampleTestES3.ResolveToFBO/ES3_Vulkan_EmulatedPrerotation180 = SKIP 235877059 VULKAN : MultisampleTestES3.ResolveToFBO/ES3_Vulkan_EmulatedPrerotation270 = SKIP // ANGLE is broken if a context is made current before a surface is created in the presence of multiple queue families @@ -98,7 +92,6 @@ 40096654 WIN VULKAN : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP 40096654 WIN OPENGL : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP 40096654 WIN GLES : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP -42264595 WIN D3D11 : SimpleStateChangeTestES31.DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed/* = SKIP 42264632 WIN OPENGL INTEL : BlitFramebufferTest.OOBWrite/* = SKIP 1229184 WIN NVIDIA VULKAN : SimpleStateChangeTest.RedefineFramebufferTexture/* = SKIP 42264699 WIN INTEL OPENGL : GLSLTest_ES31.BoolInInterfaceBlocks/* = SKIP @@ -111,25 +104,36 @@ 42263316 WIN NVIDIA GLES : CopyTextureTest.CopyOutsideMipmap/* = SKIP 42265771 WIN INTEL D3D11 : BlitFramebufferTest.Blit3DTo2DArray/* = SKIP 42265885 WIN NVIDIA VULKAN : DebugTestES3.MessageControl1/* = SKIP -42266168 WIN INTEL D3D11 : FramebufferTest_ES31.ChangeFBOSizeAndAttachmentsCount/* = SKIP -42266132 WIN NVIDIA D3D11 : FramebufferTest_ES31.ChangeFBOSizeAndAttachmentsCount/* = SKIP 42266165 WIN INTEL VULKAN : FramebufferTest_ES31.ChangeFBOSizeAndAttachmentsCount/* = SKIP +42266132 WIN INTEL OPENGL : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP 42266165 WIN INTEL VULKAN : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP 42266165 WIN INTEL VULKAN : FramebufferTest_ES31.CreateNoAttachmentFBOWithDifferentSize/* = SKIP 42266165 WIN INTEL VULKAN : FramebufferTest_ES31.RenderingLimitToDefaultFBOSizeWithNoAttachments/* = SKIP 42266241 WIN INTEL VULKAN : VertexAttributeTestES31.MismatchingSignsChangingAttributeType/* = SKIP 42266241 WIN INTEL VULKAN : VertexAttributeTestES31.MismatchingSignsChangingProgramType/* = SKIP -b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = SKIP +273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = SKIP +448658624 WIN INTEL VULKAN : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP +448658624 WIN INTEL VULKAN : GLSLTest_ES31.ConstantPrecisionPropagation/* = SKIP +452159379 WIN INTEL VULKAN : ProgramBinaryTest.ReturnedBinaryTwiceShouldMatch/* = SKIP + 42266241 PIXEL6 VULKAN : VertexAttributeTestES31.MismatchingSignsChangingAttributeType/* = SKIP 42266241 PIXEL6 VULKAN : VertexAttributeTestES31.MismatchingSignsChangingProgramType/* = SKIP 42266963 WIN NVIDIA GLES : PbufferTest.BindTexImageOverwriteNoCrashOnReleaseTexImage/* = SKIP 42266963 WIN NVIDIA OPENGL : PbufferTest.BindTexImageOverwriteNoCrashOnReleaseTexImage/* = SKIP 42266963 WIN NVIDIA GLES : PbufferTest.UseAsFramebufferColorThenDeferredDestroy/* = SKIP 42266963 WIN NVIDIA OPENGL : PbufferTest.UseAsFramebufferColorThenDeferredDestroy/* = SKIP -377537290 WIN D3D11 : ReadPixelsMultisampleTest.DefaultFramebufferPBO/* = SKIP 234602034 WIN INTEL D3D9 : ImageTest.SourceCubeAndSameTargetTextureWithEachCubeFace/* = SKIP 234602034 WIN NVIDIA D3D9 : ImageTest.SourceCubeAndSameTargetTextureWithEachCubeFace/* = SKIP 42266127 WIN INTEL OPENGL : StateChangeTestES3.LogicOp/* = SKIP +402532204 WIN OPENGL : PbufferTest.ZeroSizedSurfaceFormatQuery/* = SKIP +402532204 WIN GLES : PbufferTest.ZeroSizedSurfaceFormatQuery/* = SKIP +410591534 WIN INTEL OPENGL : Texture2DTestES3.SampleThenFullUpdateThenSampleAgain/* = SKIP +410591534 WIN INTEL OPENGL : TextureCubeTestES3.IncompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain*/* = SKIP +409821658 WIN INTEL OPENGL : SRGBTextureTestES3.SRGBSkipEncodeAndDecodeInGenerateMipmap/ES3_OpenGL* = SKIP +447556589 WIN INTEL OPENGL : GeometryShaderTest.ImplicitSizedArrayMatchesExplicitSizedArray/* = SKIP +447556589 WIN INTEL OPENGL : GeometryShaderTest.ImplicitSizedArrayMatchesExplicitSizedArray2/* = SKIP +451644991 WIN INTEL OPENGL : WebGL2GLSLTest.NotInfiniteLoop/* = SKIP +436598955 WIN D3D11 : DepthStencilFormatsTest.DepthTextureRender/ES3*D3D11 = SKIP // Failures on Intel Comet Lake S UHD Graphics 630 (8086:9bc5-31.0.101.2111) 40644896 WIN INTEL OPENGL : D3DImageFormatConversionTest.WriteColorFunctionR8G8B8A8/* = SKIP @@ -153,6 +157,7 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 40644896 WIN INTEL OPENGL : ViewportTest.DoubleWindowCentered/* = SKIP 42266866 WIN INTEL OPENGL : GLSLTest_ES3.LargeInterfaceBlockArray/* = SKIP 42266866 WIN INTEL OPENGL : GLSLTest_ES3.LargeInterfaceBlockNestedArray/* = SKIP +463961767 WIN INTEL OPENGL : EGLSurfacelessContextTest.Switcheroo/* = SKIP // Failures on Intel Alder Lake S UHD Graphics 770 (8086:4680-31.0.101.5333) 352085732 WIN INTEL OPENGL : GeometryShaderTest.LayeredFramebufferClear2DArrayColor/* = SKIP @@ -178,20 +183,25 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 373818282 WIN INTEL OPENGL : ClearTest.ChangeFramebufferAttachmentFromRGBAtoRGB/* = SKIP 388144480 WIN INTEL VULKAN : OcclusionQueriesTest.WrongSkippedQuery/* = SKIP +434453468 WIN INTEL VULKAN : LineLoopIndirectTest.TwoIndirectDrawsInDifferentIndirectBuffer/* = SKIP + +// Texture border clamp ES 3.2 test failures +390710636 PIXEL4ORXL VULKAN : TextureBorderClampTestES32.CustomBorderColorWithStencil/* = SKIP +390710636 LINUX NVIDIA VULKAN : TextureBorderClampTestES32.CustomBorderColorWithStencil/* = SKIP + // Failures on NVIDIA GTX 1660 driver 31.0.15.4601 42267037 WIN NVIDIA VULKAN : RobustResourceInitTest.MaskedStencilClear/ES2_Vulkan_AllocateNonZeroMemory = SKIP 42267037 WIN NVIDIA VULKAN : RobustResourceInitTestES3.MaskedStencilClearBuffer/ES3_Vulkan_AllocateNonZeroMemory = SKIP 42267037 WIN NVIDIA VULKAN : Texture2DTestES3.TexImageWithStencilData/ES3_Vulkan_AllocateNonZeroMemory = SKIP 42267037 WIN NVIDIA VULKAN : Texture2DTestES3.TexImageWithStencilPBO/ES3_Vulkan_AllocateNonZeroMemory = SKIP 42267037 WIN NVIDIA VULKAN : Texture2DTestES3.TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData/* = SKIP +42267037 LINUX NVIDIA VULKAN : ParallelShaderCompileTestES31.LinkAndDispatchManyPrograms/ES3_1_Vulkan_EnableParallelCompileAndLink_VaryingsRequireMatchingPrecisionInSpirv = SKIP 42267037 WIN NVIDIA GLES : TextureCubeTestES3.SpecifyAndSampleFromBaseLevel1/* = SKIP 42267037 WIN NVIDIA OPENGL : TextureCubeTestES3.SpecifyAndSampleFromBaseLevel1/* = SKIP -42267037 WIN NVIDIA VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinary/* = SKIP -42267037 WIN NVIDIA VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinaryTwice/* = SKIP -42267037 WIN NVIDIA VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsWarmedUpAtLinkTime/* = SKIP // Intel/windows does not ignore gl_Layer for non-layered framebuffers 374790899 WIN INTEL OPENGL : GeometryShaderTest.GLLayerIneffectiveWithoutLayeredFramebuffer/* = SKIP +462344532 WIN INTEL OPENGL : GLSLTest_ES3.SingleStructArrayConstructor/* = SKIP // Linux 42264596 LINUX INTEL VULKAN : SimpleStateChangeTestES31.DrawThenUpdateUBOThenDrawThenDrawIndexed/* = SKIP @@ -209,25 +219,26 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42266128 LINUX INTEL OPENGL : CopyTexImageTest.CopyTexImageMesaYFlipPartial/* = SKIP 342316794 LINUX INTEL VULKAN : GLSLTest_ES31.TernaryOnStructsInDifferentBlockStorages/* = SKIP 347282472 LINUX NVIDIA OPENGL : CopyTextureTest.CopyOutsideMipmap/* = SKIP +454915387 LINUX NVIDIA OPENGL : GLSLConstantFoldingTest.ArrayMixedArgumentsWithSideEffectIndex/* = SKIP // New failures when upgrading to Ubuntu 22/newer driver. -362545033 LINUX NVIDIA VULKAN : ClearTextureEXTTestES31Renderable.Clear2DArray/* = SKIP -362545033 LINUX NVIDIA VULKAN : ClearTextureEXTTestES31Renderable.Clear3D/* = SKIP -362545033 LINUX NVIDIA VULKAN : ClearTextureEXTTestES31Renderable.ClearCubeMap/* = SKIP -362545033 LINUX NVIDIA VULKAN : ClearTextureEXTTestES31Renderable.ClearCubeMapArray/* = SKIP +362545033 LINUX NVIDIA VULKAN : ClearTextureEXTTestES31Renderable.Clear/*__GL_RGBA4_GL_RGBA_GL_UNSIGNED_BYTE_* = SKIP +362545033 LINUX NVIDIA VULKAN : ClearTextureEXTTestES31Renderable.Clear/*__GL_RGB5_A1_GL_RGBA_GL_UNSIGNED_SHORT_5_5_5_1_* = SKIP 362545033 LINUX NVIDIA VULKAN : EGLBufferAgeTest.SingleBuffer/* = SKIP 362545033 LINUX NVIDIA VULKAN : GLSLTest.NestedPowStatements/* = SKIP 362486580 LINUX NVIDIA VULKAN : SixteenBppTextureTestES3.RGB5A1UploadRGBA8/* = SKIP -362545033 LINUX NVIDIA VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinary/* = SKIP -362545033 LINUX NVIDIA VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinaryTwice/* = SKIP -362545033 LINUX NVIDIA VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsWarmedUpAtLinkTime/* = SKIP 362545033 LINUX NVIDIA VULKAN : VulkanPerformanceCounterTest_SingleBuffer.SwapBuffersAfterFlushIgnored/* = SKIP 362545033 LINUX NVIDIA OPENGL : PointSpriteTest.TrianglesNotTreatedAsPointSprites/* = SKIP 362545033 LINUX NVIDIA OPENGL : TextureCubeTestES3.SpecifyAndSampleFromBaseLevel1/* = SKIP // Intel/mesa does not ignore gl_Layer for non-layered framebuffers 374790899 LINUX INTEL OPENGL : GeometryShaderTest.GLLayerIneffectiveWithoutLayeredFramebuffer/* = SKIP - +// Base level greater than max level fails on Linux/OpenGL +42267266 LINUX INTEL OPENGL : Texture2DTestES3.TextureBaseLevelGreaterThanMaxLevel3Levels/* = SKIP 379758210 LINUX INTEL OPENGL : GLSLTest_ES3.SwizzledToBoolCoercion/* = SKIP -383164783 LINUX NVIDIA VULKAN : MultithreadingTest.ProgramLinkAndBind/* = SKIP +437259106 LINUX INTEL : EGLDisplayTest.ContextLeakAfterTerminate/* = SKIP +448675904 LINUX INTEL OPENGL : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP + +//Angle has bugs for sampler validation +401546698 : TextureCubeTest.CubeMapBug2/* = SKIP // Nvidia 42264645 NVIDIA OPENGL : GLSLTestLoops.DoWhileContinue/* = SKIP @@ -243,8 +254,12 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42264698 NVIDIA GLES : GLSLTest_ES31.TypesUsedInDifferentBlockStorages/* = SKIP 42265449 NVIDIA OpenGL : MipmapTestES31.GenerateMipmapWithDraw/* = SKIP 42265449 NVIDIA GLES : MipmapTestES31.GenerateMipmapWithDraw/* = SKIP +448658625 NVIDIA OpenGL : GLSLTest_ES3.SwitchConstantFoldWithVariables/* = SKIP +448658625 NVIDIA GLES : GLSLTest_ES3.SwitchConstantFoldWithVariables/* = SKIP +448658624 NVIDIA OpenGL : GLSLTest_ES31.ConstantPrecisionPropagation/* = SKIP +448658624 NVIDIA GLES : GLSLTest_ES31.ConstantPrecisionPropagation/* = SKIP 42265449 LINUX NVIDIA OpenGL : MipmapTestES31.GenerateLowerMipsWithDraw/* = SKIP -42265775 LINUX NVIDIA OpenGL : CopyTexImageTest.RGBAToRGB/ES2_OpenGL_EmulateCopyTexImage2DFromRenderbuffers/* = SKIP +42265775 LINUX NVIDIA OpenGL : CopyTexImageTest.RGBAToRGB/ES2_OpenGL_EmulateCopyTexImage2DFromRenderbuffers = SKIP 42265842 LINUX NVIDIA OpenGL : FramebufferTest_ES3.SurfaceDimensionsChangeAndFragCoord/* = SKIP 42266866 NVIDIA OPENGL : GLSLTest_ES3.LargeInterfaceBlockArray/* = SKIP 42266866 NVIDIA OPENGL : GLSLTest_ES3.LargeInterfaceBlockNestedArray/* = SKIP @@ -258,6 +273,11 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = // Nvidia does not ignore gl_Layer for non-layered framebuffers 374790899 NVIDIA OPENGL : GeometryShaderTest.GLLayerIneffectiveWithoutLayeredFramebuffer/* = SKIP 374790899 NVIDIA GLES : GeometryShaderTest.GLLayerIneffectiveWithoutLayeredFramebuffer/* = SKIP +42265887 NVIDIA VULKAN : CopyCompressedTextureTestES31.CopyFromUncompressedToCompressed/* = SKIP +// RobustBufferAccess is not actually robust (will hang). +435228814 NVIDIA GLES : RobustBufferAccessBehaviorTest.DynamicBufferCrash/* = SKIP +435228814 NVIDIA OPENGL : RobustBufferAccessBehaviorTest.DynamicBufferCrash/* = SKIP +464010023 NVIDIA GLES : BlitFramebufferANGLETest.* = SKIP // Nvidia Vulkan 42265709 NVIDIA VULKAN : GLSLTest_ES31.TessellationControlShaderMatrixCopyBug/* = SKIP @@ -293,13 +313,13 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 40644895 WIN INTEL VULKAN : RobustBufferAccessBehaviorTest.DynamicBuffer/* = SKIP 40644895 WIN INTEL VULKAN : RobustBufferAccessBehaviorTest.InterleavedAttributes/* = SKIP 40644895 WIN INTEL VULKAN : Texture2DTestES3.NonZeroBaseEmulatedClear/* = SKIP -40644895 WIN INTEL VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinary/* = SKIP -40644895 WIN INTEL VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinaryTwice/* = SKIP -40644895 WIN INTEL VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsWarmedUpAtLinkTime/* = SKIP 342557702 WIN INTEL VULKAN : StateChangeTestES3.RasterizerDiscard/ES3_Vulkan_NoSupportsExtendedDynamicState2 = SKIP +433836330 WIN INTEL VULKAN : TransformFeedbackTestES31.ModeMismatchClassMismatch/* = SKIP // vk_icdNegotiateLoaderICDInterfaceVersion crashes (possibly Mesa bug?) 40096893 LINUX INTEL VULKAN : RGBTextureBufferTestES31.* = SKIP 40096893 LINUX INTEL VULKAN : TextureBufferTestES31.TexBufferFormatMismatch/* = SKIP +// RobustBufferAccess is not actually robust (will hang). +435228814 LINUX INTEL VULKAN : RobustBufferAccessBehaviorTest.DynamicBufferCrash/* = SKIP // Advanced blend tests fail on Intel (ES 3.2) 340942999 WIN INTEL VULKAN : AdvancedBlendTestES32.* = SKIP @@ -328,10 +348,6 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 772651 MAC NVIDIA OPENGL : GLSLTest.VectorScalarMultiplyAndAddInLoop/* = SKIP 42264835 MAC NVIDIA METAL : EGLBlobCacheTest.FragmentOutputLocationKey/* = SKIP 42264835 MAC NVIDIA METAL : BlobCacheTest.FragmentOutputLocationKey/* = SKIP -42264866 MAC OPENGL : FramebufferTestWithFormatFallback.R5G5B5A1_TexImage/* = SKIP -42264866 MAC OPENGL : FramebufferTestWithFormatFallback.R5G5B5A1_CopyTexImage/* = SKIP -42264866 MAC OPENGL : FramebufferTestWithFormatFallback.R5G5B5A1_CubeTexImage/* = SKIP -42264866 MAC OPENGL : FramebufferTestWithFormatFallback.R4G4B4A4_OutOfRangeStagedUpdateReformated/* = SKIP 40644820 MAC AMD METAL : GLSLTest_ES3.ValidIndexClampES300/* = SKIP 42265067 MAC INTEL OPENGL : WebGLCompatibilityTest.L32FTextures/* = SKIP 42265067 MAC INTEL OPENGL : WebGLCompatibilityTest.R32FTextures/* = SKIP @@ -367,6 +383,15 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42263073 MAC AMD OPENGL : ClipDistanceAPPLETest.EachClipDistance/* = SKIP 42263073 MAC AMD OPENGL : ClipCullDistanceTest.EachClipDistance/ES3_OpenGL__ANGLE = SKIP 373506513 MAC OPENGL : BlitFramebufferTest.BlitMultisampledFramebufferToMRT/* = SKIP +406566447 MAC AMD OPENGL : Texture3DTestES3.PixelUnpackParamsChangeTexImage/* = SKIP +410601694 MAC NVIDIA OPENGL : Texture2DTestES3.SampleThenAddLevel0ThenSampleAgain/* = SKIP +410601694 MAC AMD OPENGL : Texture2DTestES3.SampleThenAddLevel0ThenSampleAgain/* = SKIP +409821658 MAC NVIDIA OPENGL : SRGBTextureTestES3.SRGBSkipEncodeAndDecodeInGenerateMipmap/ES3_OpenGL* = SKIP +435683799 MAC OPENGL : CopyTexImageTest.MixedCubeMapFormats/ES2_OpenGL* = SKIP +448658625 MAC OPENGL : GLSLTest_ES3.SwitchConstantFoldWithVariables/* = SKIP +448658630 MAC OPENGL : GLSLTestLoops.ForContinueInConstSwitch/* = SKIP +448658630 MAC OPENGL : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP +475587478 MAC OPENGL : VertexAttributeTestES3.MaxAttribsWithBuiltInAttribs/* = SKIP // BlitFramebufferTest.ScissoredMultisampleStencil failures 42262159 MAC INTEL OPENGL : BlitFramebufferTest.ScissoredMultisampleStencil/* = SKIP @@ -374,6 +399,16 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42265665 MAC NVIDIA OPENGL : BlitFramebufferTest.ScissoredMultisampleStencil/* = SKIP 273808966 MAC AMD OPENGL : BlitFramebufferTest.scissorDrawBlitAndDrawAgain/* = SKIP +42266214 MAC APPLE OPENGL : ReadPixelsTextureNorm16PBOTest.R16_SNORM_RGBA/* = SKIP +42266214 MAC APPLE OPENGL : ReadPixelsTextureNorm16PBOTest.RG16_SNORM_RGBA/* = SKIP +42266214 MAC APPLE OPENGL : ReadPixelsTextureTest.LayerAttachment3DPBO/* = SKIP +42266214 MAC APPLE OPENGL : ReadPixelsTextureTest.MipLayerAttachment3DPBO/* = SKIP +42266214 MAC APPLE OPENGL : SRGBTextureTestES3.SRGBDecodeTexelFetch/* = SKIP +42266214 MAC APPLE OPENGL : SRGBTextureTestES3.SRGBDecodeTexelFetchArray/* = SKIP +42266214 MAC APPLE OPENGL : SRGBTextureTestES3.SRGBSkipEncodeAndDecodeInGenerateMipmap/* = SKIP +42266214 MAC APPLE OPENGL : Texture2DTestES3.SampleThenAddLevel0ThenSampleAgain/* = SKIP +42266214 MAC APPLE OPENGL : TextureUploadFormatTest_ES3.AllWithPBO/* = SKIP + // Mac Metal // Failures from Transform Feedback Enablement. Passes on BigSur @@ -382,10 +417,6 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 40644822 MAC INTEL METAL : CompressedTexturePVRTC1SRGBTest.Test/ES3_Metal__SRGB_PVRTC_2BPPV1 = SKIP 42263887 MAC METAL AMD : TransformFeedbackTest.BufferOutOfMemory/* = SKIP 42263887 MAC METAL INTEL : TransformFeedbackTest.BufferOutOfMemory/* = SKIP - -// Old Macs can't run these and there's apparently no way to filter the old Macs -// from running these tests at the moment. - 40644829 MAC NVIDIA METAL : GLSLTest_ES3.DynamicIndexingOfSwizzledLValuesShouldWork/* = SKIP 40644829 MAC NVIDIA METAL : GLSLTest_ES3.WriteIntoDynamicIndexingOfSwizzledVector/* = SKIP 40644830 MAC NVIDIA METAL : PointSpritesTest.PointCoordRegressionTest/* = SKIP @@ -407,17 +438,25 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 40644823 MAC NVIDIA METAL : UniformBlockWithOneLargeArrayMemberTest.TwoUniformBlocksInSameProgram/* = SKIP 40644823 MAC NVIDIA METAL : UniformBlockWithOneLargeArrayMemberTest.SharedSameBufferWithOtherOne/* = SKIP 40644823 MAC NVIDIA METAL : UniformBlockWithOneLargeArrayMemberTest.MemberTypeIsStruct/* = SKIP - 42265550 MAC METAL INTEL : MultisampleResolveTest.ResolveD32FS8F4Samples/ES3_Metal_AlwaysResolveMultisampleRenderBuffers = SKIP 42265550 MAC METAL INTEL : MultisampleResolveTest.ResolveD24S8Samples/ES3_Metal_AlwaysResolveMultisampleRenderBuffers = SKIP 42265550 MAC METAL INTEL : MultisampleResolveTest.ResolveD32FSamples/ES3_Metal_AlwaysResolveMultisampleRenderBuffers = SKIP 42265550 MAC METAL INTEL : MultisampleResolveTest.ResolveD24Samples/ES3_Metal_AlwaysResolveMultisampleRenderBuffers = SKIP 42265550 MAC METAL INTEL : MultisampleResolveTest.ResolveD16Samples/ES3_Metal_AlwaysResolveMultisampleRenderBuffers = SKIP - 40644744 MAC METAL INTEL : BlitFramebufferTest.MultisampleDepth/* = SKIP 40644744 MAC METAL AMD : BlitFramebufferTest.MultisampleDepth/* = SKIP - 40644777 MAC METAL AMD : ColorMaskForDrawBuffersTest.Blit/* = SKIP +440536251 MAC METAL AMD : GLSLValidationTest_ES3.ManySamplerFieldsInStructComplex/* = SKIP +443101808 MAC METAL AMD : SimpleUniformTestES3.BoolInArray/* = SKIP +409867243 MAC METAL : Texture2DTestES3.RGB565RenderAndReadIntoRGB565PBO/* = SKIP +448658625 METAL : GLSLTest_ES3.SwitchConstantFoldWithVariables/* = SKIP +464927523 METAL : GLSLTest_ES3_PackUnpackEmulation.PackHalf2x16/* = SKIP +464927523 METAL : GLSLTest_ES3_PackUnpackEmulation.PackSnorm2x16/* = SKIP +464927523 METAL : GLSLTest_ES3_PackUnpackEmulation.PackUnorm2x16/* = SKIP +42266214 MAC APPLE METAL : PixelLocalStorageTest.Coherency_noncoherent/ES3_Metal_EmulatePixelLocalStorage_DisableProgrammableBlending* = SKIP +42266214 MAC APPLE METAL : PixelLocalStorageTest.R32_noncoherent/ES3_Metal_EmulatePixelLocalStorage_DisableProgrammableBlending* = SKIP +42266214 MAC APPLE METAL : PixelLocalStorageTest.RGBA8_noncoherent/ES3_Metal_EmulatePixelLocalStorage_DisableProgrammableBlending* = SKIP +42266214 MAC APPLE METAL : Texture2DTest.ManySupersedingTextureUpdates/* = SKIP // The workaround is not intended to be enabled in this configuration so // skip it as the failure is likely a driver bug. @@ -440,6 +479,9 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 40644833 MAC METAL NVIDIA : Texture2DBaseMaxTestES3.Fuzz545ImmutableTexRenderFeedback/* = SKIP +// Skipped because these tests crash with these backends +457478042 OPENGL : Texture2DBaseMaxTestES3.BaseExceedsMaxFboAttachAtBase/ES3_OpenGL* = SKIP + 40644834 MAC METAL INTEL : Texture2DTest.TextureSizeCase1/* = SKIP 40096847 MAC METAL INTEL : PointSpritesTest.PointSizeAboveMaxIsClamped/* = SKIP @@ -458,19 +500,9 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 351275980 MAC METAL : GLSLTest_ES3.DynamicIndexingOfSwizzledLValuesShouldWork2/* = SKIP 351275980 IOS METAL : GLSLTest_ES3.DynamicIndexingOfSwizzledLValuesShouldWork2/* = SKIP -373659619 MAC METAL : EGLSurfaceTest.ResizeWindow/* = SKIP -373659619 IOS METAL : EGLSurfaceTest.ResizeWindow/* = SKIP - // D3D -42264944 WIN D3D9 : GLSLTest.HandleExcessiveLoopBug/* = SKIP -42264620 WIN D3D11 : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP +42264944 WIN D3D9 : GLSLValidationTest.HandleExcessiveLoopBug/* = SKIP 42264653 WIN D3D11 : GLSLTestLoops.*ContinueInSwitch/* = SKIP -42264675 WIN D3D11 : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP -// Fails on assertion in translation to D3D -42262486 WIN D3D11 : GLSLTest_ES31.TypesUsedInDifferentBlockStorages/* = SKIP -42262486 WIN D3D11 : GLSLTest_ES31.BoolInInterfaceBlocks/* = SKIP -// Mistranslation -42264738 WIN D3D11 : GLSLTest_ES31.StorageBufferBoolVectorPassedToFunctions/* = SKIP // D3D does not support compressed textures where the base mip level is not a multiple of 4 40644741 WIN D3D9 : DXT1CompressedTextureTest.NonBlockSizesMipLevels/* = SKIP 40644741 WIN D3D11 : DXT1CompressedTextureTest.NonBlockSizesMipLevels/* = SKIP @@ -478,7 +510,7 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42265582 WIN D3D11 : SimpleStateChangeTestES3.InvalidateRGBThenDraw/* = SKIP 42265582 WIN D3D11 : SimpleStateChangeTestES3.DrawInvalidateRGBThenDraw/* = SKIP 42265582 WIN D3D11 : SimpleStateChangeTestES3.DrawAndInvalidateRGBThenVerifyAlpha/* = SKIP -42265587 WIN D3D9 : GLSLTest.LoopBodyEndingInBranch*/* = SKIP +42265587 WIN D3D9 : GLSLValidationTest.LoopBodyEndingInBranch*/* = SKIP 42265622 WIN D3D9 : RobustResourceInitTest.OutOfBoundsArrayBuffers/* = SKIP 42265686 WIN D3D11 : BufferDataTestES3.BufferDataWithNullFollowedByMap/* = SKIP 42265767 WIN INTEL D3D11 : StateChangeTestES3.PolygonOffset/* = SKIP @@ -488,15 +520,21 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42265799 WIN D3D11 : StateChangeTestES3.PrimitiveRestart/* = SKIP 40050019 WIN D3D11 : WebGL2GLSLTest.InitOutputParams/* = SKIP 1456243 WIN D3D11 : WebGL2CompatibilityTest.DrawWithZeroSizedBuffer/* = SKIP -42266836 WIN D3D9 : GLSLTest.VectorScalarArithmeticWithSideEffectInLoop/* = SKIP +42266836 WIN D3D9 : GLSLValidationTest.VectorScalarArithmeticWithSideEffectInLoop/* = SKIP 42267092 WIN D3D11 : BlitFramebufferTest.FlippedBlits/* = SKIP -343249129 WIN D3D11 : GLSLTest_ES31.TernaryOnStructsInDifferentBlockStorages/* = SKIP +432303915 WIN D3D11 : GLSLTest.VerifyMaxFragmentUniformVectorsWithSamplers/* = SKIP +432303915 WIN D3D11 : GLSLTest.VerifyMaxVertexUniformVectors/* = SKIP +432303915 WIN D3D11 : GLSLTest.VerifyMaxVertexUniformVectorsWithSamplers/* = SKIP +448658631 WIN D3D9 : GLSLTest.EmptyForLoopWithSideEffect/* = SKIP +448658631 WIN D3D11 : GLSLTestLoops.ForContinueInConstSwitch/* = SKIP +448658631 WIN D3D11 : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP +448658631 WIN D3D11 : GLSLTest_ES3.SwitchConstantFold/* = SKIP +448658631 WIN D3D11 : GLSLTest_ES3.SwitchConstantFoldWithVariables/* = SKIP // Android 42264624 ANDROID GLES : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP 42264646 ANDROID GLES : GLSLTestLoops.ForNoCondition/* = SKIP 42264756 ANDROID GLES : BufferDataTestES3.DrawWithNotCallingBufferData/* = SKIP -42265529 ANDROID VULKAN : EGLSurfaceTest.ResizeWindowWithDraw/* = SKIP 42265529 ANDROID : EGLReadinessCheckTest.IsRunningOnANGLE/* = SKIP 42265529 ANDROID : EGLReadinessCheckTest.GetProcAddressNegativeTest/* = SKIP 42265529 ANDROID : EGLReadinessCheckTest.HasGetPlatformDisplayEXT/* = SKIP @@ -509,9 +547,14 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42264972 ANDROID GLES : ImageTestES3.RGBXAHBImportThenUpload/* = SKIP 42264972 ANDROID GLES : ImageTestES3.RGBXAHBImportMultipleLayers/* = SKIP +436598955 ANDROID GLES : DepthStencilFormatsTest.DepthTextureRender/ES3*OpenGLES = SKIP + // Unimplemented fallback path for when format is not renderable or AHB hasn't specified the GPU_FRAMEBUFFER usage. 42264676 ANDROID VULKAN : ImageTestES3.RGBXAHBImportNoFramebufferUsage/* = SKIP +// Test is not suitable for GLES. +444335354 ANDROID GLES : ImageTestES3.RGBXAHBUploadDataRGBA/* = SKIP + // Nexus 5X expectations. 42264673 NEXUS5X GLES : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP 42264717 NEXUS5X GLES : GLSLTest_ES31.BuiltInsWithOutParameters/* = SKIP @@ -530,6 +573,11 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42264513 PIXEL4ORXL GLES : CopyTexImageTest.CopyTexSubImageFrom3DTexureOES/* = SKIP 42264513 PIXEL4ORXL GLES : CubeMapTextureTest.SampleCoordinateTransform/* = SKIP 42265301 PIXEL4ORXL GLES : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP +452919815 PIXEL4ORXL GLES : GLSLTest_ES3.VaryingAnonymousStructEquality/* = SKIP +454827197 PIXEL4ORXL GLES : GLSLConstantFoldingTest_ES31.NamedArrayOfArrayIndex/* = SKIP +42265301 PIXEL4ORXL GLES : GeometryShaderTest.RedeclareGlIn/* = SKIP +42265301 PIXEL4ORXL GLES : GeometryShaderTest.RedeclareGlInBeforeInputSize/* = SKIP +42265301 PIXEL4ORXL GLES : GeometryShaderTest.RedeclareGlInBeforeInputSizeButUnused/* = SKIP 42264513 PIXEL4ORXL GLES : ImageTest.Source2DTarget2D_Colorspace/* = SKIP 42264513 PIXEL4ORXL GLES : ImageTest.Source2DTargetExternal_Colorspace/* = SKIP 42264513 PIXEL4ORXL GLES : ImageTest.Source2DTargetRenderbuffer_Colorspace/* = SKIP @@ -598,9 +646,16 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42266774 PIXEL4ORXL GLES : MultithreadingTestES3.SimultaneousUploadAndDraw/* = SKIP 42266774 PIXEL4ORXL VULKAN : MultithreadingTestES3.SimultaneousUploadAndDraw/* = SKIP 384314370 PIXEL4ORXL GLES : FramebufferFetchES31.WriteOnlyInOutVariableConditional/* = SKIP +384314370 PIXEL4ORXL GLES : FramebufferFetchES31.WriteOnlyInOutVariableConditionalFunctionCall/* = SKIP 384314370 PIXEL4ORXL GLES : FramebufferFetchES31.WriteOnlyInOutVariableDiscard/* = SKIP 384314370 PIXEL4ORXL GLES : FramebufferFetchES31.WriteOnlyInOutVariableEarlyReturn/* = SKIP 384314370 PIXEL4ORXL GLES : FramebufferFetchES31.WriteOnlyInOutVariablePartial/* = SKIP +384314370 PIXEL4ORXL GLES : FramebufferFetchES31.WriteOnlyInOutVariableInOutArgument/* = SKIP +42264513 PIXEL4ORXL GLES : GLSLTest.NestedInoutVars2/* = SKIP +42264513 PIXEL4ORXL GLES : GLSLTest.NestedInoutVars3/* = SKIP +42264513 PIXEL4ORXL GLES : SimpleUniformTestES3.TernarySelectAnArrayThenIndex/* = SKIP +458082809 PIXEL4ORXL GLES : GLSLValidationExtensionDirectiveTest_ES3.Sampler2DShadow/* = SKIP +458082810 PIXEL4ORXL GLES : GLSLValidationExtensionDirectiveTest_ES31.TextureCubeMapArray/* = SKIP 42267082 PIXEL4ORXL GLES : BlobCacheTest.FragmentOutputLocationKey/* = SKIP 42267082 PIXEL4ORXL GLES : EGLBlobCacheTest.FragmentOutputLocationKey/* = SKIP @@ -609,8 +664,15 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42267082 PIXEL4ORXL GLES : EXTBlendFuncExtendedDrawTestES3.MultipleDrawBuffersAPI/* = SKIP 42267082 PIXEL4ORXL GLES : EXTBlendFuncExtendedTestES3.FragmentOutputLocationsPartiallyAutomatic/* = SKIP +463961764 PIXEL4ORXL GLES : BlitFramebufferANGLETest.BlitWithDepthDefaultToUser/* = SKIP +463961764 PIXEL4ORXL GLES : BlitFramebufferANGLETest.BlitWithMissingAttachments/* = SKIP +463961764 PIXEL4ORXL GLES : BlitFramebufferANGLETest.OversizedBlit/* = SKIP + 372269602 PIXEL4ORXL GLES : FramebufferFetchES31.MultiSampled/* = SKIP +405840226 PIXEL4ORXL GLES : ImageTestES3.SourceAHBTargetTexture2DGenerateMipmap/* = SKIP +410584011 PIXEL4ORXL GLES : ImageTestES31.UseSourceTextureAsStorageImage/* = SKIP + // Qualcomm on Pixel4 does not ignore gl_Layer for non-layered framebuffers 374790899 PIXEL4ORXL GLES : GeometryShaderTest.GLLayerIneffectiveWithoutLayeredFramebuffer/* = SKIP @@ -652,17 +714,17 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 42266902 PIXEL4ORXL : GLSLTest_ES3.LargeConstGlobalArraysOfStructs/* = SKIP -42265843 PIXEL4ORXL VULKAN : FramebufferTest_ES3.SurfaceDimensionsChangeAndFragCoord/* = SKIP - 42266150 PIXEL4ORXL VULKAN : PixelLocalStorageTest.MaxCombinedDrawBuffersAndPLSPlanes/* = SKIP 42266150 PIXEL4ORXL VULKAN : PixelLocalStorageTest.BlendColorMaskAndClear/* = SKIP +42266150 PIXEL4ORXL VULKAN : PixelLocalStorageTest.ClearWithActivePLS/* = SKIP +42266150 PIXEL4ORXL VULKAN : PixelLocalStorageTest.CopyTexSubImage/* = SKIP 42266151 PIXEL4ORXL VULKAN : PixelLocalStorageTest.MipMapLevels/* = SKIP 42266242 PIXEL4ORXL VULKAN : PixelLocalStorageTest.DrawStateReset/* = SKIP 42266242 PIXEL4ORXL VULKAN : PixelLocalStorageTestES31.DrawStateReset/* = SKIP -b/305292977 PIXEL4ORXL VULKAN : FramebufferTest_ES31.ClearWithColorMasksRGB5A1/* = SKIP -b/305311693 PIXEL4ORXL GLES : FramebufferTest_ES31.ClearColorMorePrecisionThanFBOFormatShouldNotApplyDithering/* = SKIP -b/308668391 PIXEL4ORXL VULKAN : ImageTest.SourceYUVAHBTargetExternalRGBSampleNoData/* = SKIP +305292977 PIXEL4ORXL VULKAN : FramebufferTest_ES31.ClearWithColorMasksRGB5A1/* = SKIP +305311693 PIXEL4ORXL GLES : FramebufferTest_ES31.ClearColorMorePrecisionThanFBOFormatShouldNotApplyDithering/* = SKIP +308668391 PIXEL4ORXL VULKAN : ImageTest.SourceYUVAHBTargetExternalRGBSampleNoData/* = SKIP 343011429 PIXEL4ORXL VULKAN : GLSLTest_ES3.InactiveVaryingStructUnusedInFragmentShader/*_ForceInitShaderVariables* = SKIP 343011429 PIXEL4ORXL VULKAN : GLSLTest_ES3.VaryingStructUsedInFragmentShader/*_ForceInitShaderVariables* = SKIP @@ -674,7 +736,7 @@ b/308668391 PIXEL4ORXL VULKAN : ImageTest.SourceYUVAHBTargetExternalRGBSampleNoD 343218490 PIXEL4ORXL : GLSLTest_ES31.TernaryOnStructsInDifferentBlockStorages/* = SKIP -b/346650202 PIXEL4ORXL : GeometryShaderTest.CreateAndAttachGeometryShaderOES/* = SKIP +346650202 PIXEL4ORXL : GeometryShaderTest.CreateAndAttachGeometryShaderOES/* = SKIP 42266743 PIXEL4ORXL VULKAN : VulkanExternalImageTest.PreInitializedOnGLImportLinear*/* = SKIP 42266743 LINUX SWIFTSHADER : VulkanExternalImageTest.PreInitializedOnGLImportLinear*/* = SKIP @@ -696,6 +758,9 @@ b/346650202 PIXEL4ORXL : GeometryShaderTest.CreateAndAttachGeometryShaderOES/* = 42266163 PIXEL4ORXL VULKAN : FramebufferTest_ES31.RenderingLimitToDefaultFBOSizeWithNoAttachments/* = SKIP 42266173 PIXEL4ORXL GLES : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP 42266381 PIXEL4ORXL GLES : DepthStencilFormatsTestES31.DrawReadDrawDispatch/* = SKIP +433331119 PIXEL4ORXL GLES : ValidationStateChangeTest.MapBufferWithAttribDisabledThenEnableAndDraw/* = SKIP + +448658625 PIXEL4ORXL GLES : GLSLTest_ES3.SwitchConstantFoldWithVariables/* = SKIP // Internal driver failures on both GLES and Vulkan 42262483 NEXUS5X : GLSLTest_ES31.TypesUsedInDifferentBlockStorages/* = SKIP @@ -718,7 +783,9 @@ b/346650202 PIXEL4ORXL : GeometryShaderTest.CreateAndAttachGeometryShaderOES/* = 42267061 PIXEL4ORXL : FramebufferTest_ES31.MultisampleResolveBothAttachments/* = SKIP 42267061 PIXEL4ORXL VULKAN : VulkanPerformanceCounterTest_ES31.MultisampleResolveBothAttachments/* = SKIP -42267094 PIXEL4ORXL VULKAN : MultisampledRenderToTextureES3Test.RenderbufferDrawThenBlitDepthStencilOnly/* = SKIP +42267094 PIXEL4ORXL VULKAN : MSRTTES3Test.RenderbufferDrawThenBlitDepthStencilOnly/* = SKIP + +42266019 PIXEL4ORXL VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.MultisampleDepthStencilResolveSeparately/* = SKIP 374790905 PIXEL4ORXL VULKAN : GLSLTest_ES3.ReadFromDynamicIndexingOfSwizzledVector/* = SKIP @@ -732,7 +799,6 @@ b/346650202 PIXEL4ORXL : GeometryShaderTest.CreateAndAttachGeometryShaderOES/* = // Pixel 6 expectations. 40096826 PIXEL6 VULKAN : BlitFramebufferTest.OOBWrite/* = SKIP 40096826 PIXEL6 VULKAN : BufferSubDataTest.MapInvalidateThenBufferSubData/* = SKIP -40096826 PIXEL6 VULKAN : EGLSurfaceTest.ResizeWindowWithDraw/* = SKIP 40096826 PIXEL6 VULKAN : ExternalBufferTestES31.BufferDoesNotLeakAHB/* = SKIP 40096826 PIXEL6 VULKAN : FramebufferMultiviewLayeredClearTest.ScissoredClearBufferfi/* = SKIP 40096826 PIXEL6 VULKAN : FramebufferTest_ES31.MultipleTextureMultisampleResolveWithBlitMultipleResolves* = SKIP @@ -769,40 +835,41 @@ b/346650202 PIXEL4ORXL : GeometryShaderTest.CreateAndAttachGeometryShaderOES/* = 42265632 PIXEL6 VULKAN : ImageTestES3.SourceAHBMipTarget2DMip/* = SKIP 42265632 PIXEL6 VULKAN : ImageTestES3.SourceAHBMipTarget2DMipGenerateMipmap/* = SKIP 40096838 PIXEL6 VULKAN : PixelLocalStorageTest.EarlyFragmentTests/ES3_1_Vulkan_EmulatePixelLocalStorage* = SKIP +448658624 PIXEL6 VULKAN : GLSLTest_ES31.ConstantPrecisionPropagation/* = SKIP +448658624 PIXEL6 VULKAN : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP // New failures after TP1A.220624.021 upgrade -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidate/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateAndClear/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDetachModifyTexAttachDrawWithBlend/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDisableDraw/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDisableDrawEnable/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDisableEnableDraw/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDraw/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDrawAndDeleteRenderbuffer/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDrawDisableEnable/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDrawDisableEnableInvalidate/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateDrawDisableEnableInvalidateDraw/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DepthStencilInvalidateSub/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DisableDrawInvalidateEnable/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.DisableInvalidateDraw/* = SKIP -42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest.ReadOnlyDepthBufferLayout/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidate/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateAndClear/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDetachModifyTexAttachDrawWithBlend/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDisableDraw/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDisableDrawEnable/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDisableEnableDraw/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDraw/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDrawAndDeleteRenderbuffer/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDrawDisableEnable/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDrawDisableEnableInvalidate/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDrawDisableEnableInvalidateDraw/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateSub/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DisableDrawInvalidateEnable/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DisableInvalidateDraw/* = SKIP +42266050 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.ReadOnlyDepthBufferLayout/* = SKIP 42266173 PIXEL6 GLES : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP // New failures after UQ1A.240105.002 upgrade 42267029 PIXEL6 VULKAN : ImageTest.SourceNativeClientBufferTargetRenderbuffer/* = SKIP -42267029 PIXEL6 VULKAN : MultisampledRenderToTextureES31Test.BlitFramebufferAttachment1/* = SKIP -42267029 PIXEL6 VULKAN : MultisampledRenderToTextureES31Test.MixedMultisampledAndMultisampledRenderToTexture/* = SKIP -42267029 PIXEL6 VULKAN : MultisampledRenderToTextureES31Test.RenderbufferBlitFramebufferAttachment1/* = SKIP +42267029 PIXEL6 VULKAN : MSRTTES31Test.BlitFramebufferAttachment1/* = SKIP +42267029 PIXEL6 VULKAN : MSRTTES31Test.MixedMultisampledAndMultisampledRenderToTexture/* = SKIP +42267029 PIXEL6 VULKAN : MSRTTES31Test.RenderbufferBlitFramebufferAttachment1/* = SKIP 42267029 PIXEL6 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.ClearThenDraw/* = SKIP 42267029 PIXEL6 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.LoadThenDraw/* = SKIP 42267029 PIXEL6 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.RenderbufferClearThenDraw/* = SKIP 42267029 PIXEL6 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.RenderbufferLoadThenDraw/* = SKIP 42267029 PIXEL6 VULKAN : MultiviewDrawValidationTest.ActiveTransformFeedback/* = SKIP 42267029 PIXEL6 VULKAN : OcclusionQueriesTestES3.UnresolveNotCounted/* = SKIP -42267029 PIXEL6 VULKAN : VulkanPerformanceCounterTest.RenderToTextureDepthStencilRenderbufferShouldNotLoad/* = SKIP +42267029 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.RenderToTextureDepthStencilRenderbufferShouldNotLoad/* = SKIP 42267029 PIXEL6 VULKAN : VulkanPerformanceCounterTest.RenderToTextureDepthStencilTextureShouldNotLoad/* = SKIP -42267029 PIXEL6 VULKAN : VulkanPerformanceCounterTest.RenderToTextureUninitializedAndUnusedDepthStencil/* = SKIP -395520107 PIXEL6 VULKAN : ImageTestES3.SourceYUVAHBTargetExternalCopySrc/* = SKIP +42267029 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.RenderToTextureUninitializedAndUnusedDepthStencil/* = SKIP // New failures after AP1A.240405.002 upgrade -b/336847261 PIXEL6 VULKAN : StateChangeTestES3.LineWidth/* = SKIP +336847261 PIXEL6 VULKAN : StateChangeTestES3.LineWidth/* = SKIP // ARM drivers cannot support xfb emulation because they lack support for the // vertexPipelineStoresAndAtomics Vulkan feature. The tests that force-enable this feature are @@ -810,12 +877,16 @@ b/336847261 PIXEL6 VULKAN : StateChangeTestES3.LineWidth/* = SKIP 42265847 PIXEL6 VULKAN : *_NoSupportsTransformFeedbackExtension* = SKIP // Crashing in Mali shader compiler -b/217922015 PIXEL6 VULKAN : GLSLTest_ES3.NestedPowFromUniform/* = SKIP +217922015 PIXEL6 VULKAN : GLSLTest_ES3.NestedPowFromUniform/* = SKIP 42266242 PIXEL6 VULKAN : PixelLocalStorageTest.DrawStateReset/* = SKIP 42266242 PIXEL6 VULKAN : PixelLocalStorageTestES31.DrawStateReset/* = SKIP 378404998 PIXEL6 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFramebufferFetchDrawThenClear/* = SKIP -b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachments/* = SKIP +330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachments/* = SKIP +42266019 PIXEL6 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.MultisampleDepthStencilResolveSeparately/* = SKIP + +465140993 PIXEL6 VULKAN : GLSLTest_ES3_PackUnpackEmulation.PackHalf2x16/* = SKIP +465140993 PIXEL6 VULKAN : GLSLTest_ES3_PackUnpackEmulation.PackSnorm2x16/* = SKIP // Some Metal tests fail on iOS Intel simulator 40096874 IOS METAL : CubeMapTextureTest.SampleCoordinateTransformGrad/* = SKIP @@ -829,6 +900,10 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 40096874 IOS METAL : PixelLocalStorageTest.BlendColorMaskAndClear/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.ClearValues_r32/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.Coherency/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096874 IOS METAL : PixelLocalStorageTest.Coherency_noncoherent/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096838 IOS METAL : PixelLocalStorageTest.ColorAttachment0Workaround/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096838 IOS METAL : PixelLocalStorageTest.CopyTexSubImage/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096838 IOS METAL : PixelLocalStorageTest.FlushFinishSync/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.ForgetBarrier/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.FragmentReject_depth/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.FragmentReject_stencil/ES3_Metal_EmulatePixelLocalStorage* = SKIP @@ -844,7 +919,13 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 40096874 IOS METAL : PixelLocalStorageTest.PLSWithSamplers/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.ProgramCache/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.R32/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096874 IOS METAL : PixelLocalStorageTest.R32_noncoherent/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.RGBA8/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096874 IOS METAL : PixelLocalStorageTest.RGBA8_noncoherent/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096838 IOS METAL : PixelLocalStorageTest.RasterizerDiscard/ES3_Metal_EmulatePixelLocalStorage* = SKIP +474583528 IOS METAL : PixelLocalStorageTest.Texture2DArrayMultipleLayers/ES3_Metal_EmulatePixelLocalStorage* = SKIP +40096838 IOS METAL : PixelLocalStorageTest.TextureCubeFaces/* = SKIP +474583528 IOS METAL : PixelLocalStorageTest.TextureCubeMultipleFaces/ES3_Metal_EmulatePixelLocalStorage* = SKIP 40096874 IOS METAL : PixelLocalStorageTest.TextureLevelsAndLayers/* = SKIP 40096874 IOS METAL : PointSpritesTest.PointSizeAboveMaxIsClamped/* = SKIP 40096874 IOS METAL : RobustBufferAccessWebGL2ValidationStateChangeTest.BindZeroSizeBufferThenDeleteBufferBug/* = SKIP @@ -873,6 +954,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 40096874 IOS METAL : Texture2DDepthTest.DepthTextureES2Compatibility/* = SKIP 40096874 IOS METAL : Texture2DTest.ManySupersedingTextureUpdates/* = SKIP 40096874 IOS METAL : Texture2DTest.TextureSizeCase1/* = SKIP +40096874 IOS METAL : Texture2DTestES3.RGB565RenderAndReadIntoRGB565PBO/* = SKIP 40096874 IOS METAL : TextureUploadFormatTest.All/* = SKIP 40096874 IOS METAL : UniformBlockWithOneLargeArrayMemberTest.MemberTypeIsMatrixAndInstanced/* = SKIP 40096874 IOS METAL : UniformBlockWithOneLargeArrayMemberTest.MemberTypeIsMixStructFloatAndMat4/* = SKIP @@ -882,6 +964,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 40096874 IOS METAL : UniformBlockWithOneLargeArrayMemberTest.TwoUniformBlocksInSameProgram/* = SKIP 40096879 IOS METAL : FramebufferTest_ES3.RenderSharedExponent/* = SKIP 40096883 IOS METAL : Texture2DDepthStencilTestES3.TexSampleModes*Swizzled/* = SKIP +375244081 IOS METAL : GLSLTest_ES3.MaxVaryingWithFeedbackAndGLline/* = SKIP // Simulator does not support compare functions in the sampler state 365066518 IOS METAL : ShadowSamplerFunctionTexture2DTest.Test/* = SKIP @@ -961,6 +1044,9 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen // Metal internal compiler error 42265076 MAC AMD METAL : ProgramBinaryES3Test.SaveAndLoadDetachedShaders/* = SKIP +// Issue with the ANGLE workaround for a driver bug. +402810076 MAC AMD METAL : PixelLocalStorageTest.ColorAttachment0Workaround/* = SKIP + // GLES1 failures introduced during ubershader optimization 42265148 MAC INTEL OPENGL : BootAnimationTest.DefaultBootAnimation/* = SKIP 42265148 MAC INTEL OPENGL : DrawTextureTest.Basic/* = SKIP @@ -968,6 +1054,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 42265148 MAC INTEL OPENGL : DrawTextureTest.ColorArrayNotUsed/* = SKIP 42265148 MAC INTEL OPENGL : DrawTextureTest.CorrectNdcForOddViewportDimensions/* = SKIP +371987004 MAC APPLE OPENGL : BlitFramebufferANGLETest.BlitWithMissingAttachments/* = SKIP 371987004 MAC INTEL OPENGL : BlitFramebufferANGLETest.BlitWithMissingAttachments/* = SKIP 371987004 MAC NVIDIA OPENGL : BlitFramebufferANGLETest.BlitWithMissingAttachments/* = SKIP 371987004 WIN D3D9 : BlitFramebufferANGLETest.BlitWithMissingAttachments/* = SKIP @@ -1020,7 +1107,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 42265501 NVIDIA OPENGL : GLSLTest.SwizzledChainedAssignIncrement/* = SKIP 42265501 NVIDIA GLES : GLSLTest.SwizzledChainedAssignIncrement/* = SKIP -42265557 : VulkanPerformanceCounterTest.DepthStencilInvalidateDrawDisable/* = SKIP +42265557 : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthStencilInvalidateDrawDisable/* = SKIP // Causes incompatible error in GL back-end. 42265690 OPENGL : TransformFeedbackTest.DrawAfterDeletingPausedBuffer/* = SKIP @@ -1028,29 +1115,24 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen // // Cannot create 2D (array) view of 3D texture. These fail with validation errors, and cause a crash in syncval. 42262531 VULKAN : ComputeShaderTest.BindImageTexture3D/* = SKIP -42262531 D3D11 : ComputeShaderTest.BindImageTexture3D/* = SKIP // Produces VVL errors 42265827 VULKAN : FramebufferTest_ES3.FramebufferConditionalFeedbackLoop/* = SKIP 42265967 VULKAN : Texture2DTest.TextureMaxSize/* = SKIP -343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerTypeShadow_TextureTypeUnsignedNormalized_* = SKIP -343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerTypeShadow_TextureTypeSignedNormalized_* = SKIP -343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerTypeShadow_TextureTypeFloat_* = SKIP +343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerSD_TexNorm_* = SKIP +343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerSD_TexSNorm_* = SKIP +343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerSD_TexF_* = SKIP +343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerSD_TexUI_* = SKIP +343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerSD_TexSI_* = SKIP +343922404 VULKAN : IncompatibleTextureTest.Test/ES3_*__SamplerSD_TexS_* = SKIP // Intel Mesa 19.0.2 appears to have a driver bug. -// imageLoad isn't fully implemented for fragment shaders on D3D11. 42265826 INTEL OPENGL : GLSLTest_ES31.ImageLoadAfterClear/* = SKIP -42265826 D3D11 : GLSLTest_ES31.ImageLoadAfterClear/* = SKIP -// On D3D: UAVs don't allow aliasing. // On OpenGL, there's also an issue with this test. -42261718 D3D11 : GLSLTest_ES31.AliasedLoadStore/* = SKIP 42265869 OpenGL : GLSLTest_ES31.AliasedLoadStore/* = SKIP -// On D3D: readonly image2D handles don't return the texture's existing contents. -42266078 D3D11 : GLSLTest_ES31.ReadOnlyImage2DAsFunctionArg/* = SKIP - // Flaky timeouts - SwiftShader hits a heavy emulation path in this test 42266366 WIN SWIFTSHADER : InstancingTestES3.LargeDivisor/* = SKIP 42266366 LINUX ASAN SWIFTSHADER : InstancingTestES3.LargeDivisor/* = SKIP @@ -1073,14 +1155,11 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 42266575 WIN OpenGL : RGBTextureBufferTestES31.*/* = SKIP 42266575 WIN GLES : RGBTextureBufferTestES31.*/* = SKIP 42266575 LINUX NVIDIA OpenGL : RGBTextureBufferTestES31.*/* = SKIP -// Misbehaves on D3D11 (pixels remain black or reading from wrong offsets) -42266575 D3D11 : RGBTextureBufferTestES31.*/* = SKIP - -42266013 LINUX VULKAN : FramebufferTest_ES3.SurfaceDimensionsChangeAndFragCoord/* = SKIP 42266091 WIN INTEL : *EmulateCopyTexImage2DFromRenderbuffers* = SKIP 42266092 WIN SWIFTSHADER : VulkanPerformanceCounterTest.EndXfbAfterRenderPassClosed/* = SKIP +466331749 SWIFTSHADER : GLSLTest_ES31.ShortCircuitOutOfBoundsAccess/* = SKIP // Flat shading bug with lighting 42264726 VULKAN : LightsTest.FlatLitMesh/* = SKIP @@ -1088,6 +1167,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen // Adreno drivers erroneously reject certain sub-image uploads 42265943 PIXEL4ORXL GLES : CompressedTextureASTCTest.Test/* = SKIP 42265943 PIXEL4ORXL GLES : CompressedTextureASTCSliced3DTest.Test/* = SKIP +42265943 PIXEL4ORXL GLES : CompressedTextureASTC3DTest.Test/* = SKIP 42265943 PIXEL4ORXL GLES : CompressedTextureETC1SubTest.Test/* = SKIP 42265943 PIXEL4ORXL GLES : CompressedTextureEACR11STest.Test/* = SKIP 42265943 PIXEL4ORXL GLES : CompressedTextureEACR11UTest.Test/* = SKIP @@ -1149,32 +1229,32 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen 358407353 LINUX INTEL OPENGL : ReadPixelsPBOTest.SmallRowLength/* = SKIP // D3D needs a workaround to follow OpenGL rules -42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenZeroAndNearPlane_* = SKIP -42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenFarPlaneAndOne_* = SKIP -42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthNegative_* = SKIP -42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthGreaterThanOne_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenZeroAndNearPlane_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenFarPlaneAndOne_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthNegative_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthGreaterThanOne_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenZeroAndNearPlane_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenFarPlaneAndOne_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthNegative_* = SKIP -42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthGreaterThanOne_* = SKIP +42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__Reduced_Clipped_VInside_FZeroToNear_* = SKIP +42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__Reduced_Clipped_VInside_FFarToOne_* = SKIP +42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__Reduced_Clipped_VInside_FNegative_* = SKIP +42266528 D3D9 : DepthWriteTest.Test/ES2_D3D9__Reduced_Clipped_VInside_FOverOne_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__Reduced_Clipped_VInside_FZeroToNear_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__Reduced_Clipped_VInside_FFarToOne_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__Reduced_Clipped_VInside_FNegative_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES2_D3D11__Reduced_Clipped_VInside_FOverOne_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__Reduced_Clipped_VInside_FZeroToNear_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__Reduced_Clipped_VInside_FFarToOne_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__Reduced_Clipped_VInside_FNegative_* = SKIP +42266528 D3D11 : DepthWriteTest.Test/ES3_D3D11__Reduced_Clipped_VInside_FOverOne_* = SKIP // Driver bugs -42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenZeroAndNearPlane_* = SKIP -42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenFarPlaneAndOne_* = SKIP -42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthNegative_* = SKIP -42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthGreaterThanOne_* = SKIP -42266528 MAC INTEL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenZeroAndNearPlane_* = SKIP -42266528 MAC INTEL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenFarPlaneAndOne_* = SKIP -42266528 MAC INTEL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthNegative_* = SKIP -42266528 MAC INTEL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthGreaterThanOne_* = SKIP -42266528 IOS METAL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenZeroAndNearPlane_* = SKIP -42266528 IOS METAL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthBetweenFarPlaneAndOne_* = SKIP -42266528 IOS METAL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthNegative_* = SKIP -42266528 IOS METAL : DepthWriteTest.Test/*__DepthRangeReduced_Clipped_VertexDepthInsideClipVolume_FragmentDepthGreaterThanOne_* = SKIP +42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FZeroToNear_* = SKIP +42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FFarToOne_* = SKIP +42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FNegative_* = SKIP +42266528 WIN INTEL OPENGL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FOverOne_* = SKIP +42266528 MAC INTEL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FZeroToNear_* = SKIP +42266528 MAC INTEL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FFarToOne_* = SKIP +42266528 MAC INTEL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FNegative_* = SKIP +42266528 MAC INTEL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FOverOne_* = SKIP +42266528 IOS METAL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FZeroToNear_* = SKIP +42266528 IOS METAL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FFarToOne_* = SKIP +42266528 IOS METAL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FNegative_* = SKIP +42266528 IOS METAL : DepthWriteTest.Test/*__Reduced_Clipped_VInside_FOverOne_* = SKIP // gl_PointCoord origin is flipped for non-default framebuffers 40096885 WIN INTEL OPENGL : ClipControlTest.OriginPointCoord/* = SKIP @@ -1220,44 +1300,40 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen // SSBO Alias Overwrite 42264522 PIXEL4ORXL VULKAN : ComputeShaderTest.SSBOAliasOverWrite/* = SKIP -b/266235549 D3D11 : ComputeShaderTest.SSBOAliasOverWrite/* = SKIP // Samsung Galaxy S22 (Xclipse) -b/267953710 GALAXYS22 GLES : VulkanImageTest.DeviceVulkan/* = SKIP -b/267953710 GALAXYS22 GLES : VulkanImageTest.HasVulkanImageExtensions/* = SKIP -b/267953710 GALAXYS22 GLES : VulkanExternalImageTest.TextureFormatCompatChromiumFd/* = SKIP -b/267953710 GALAXYS22 GLES : VulkanExternalImageTestES31.UninitializedOnGLImportAndStorageWrite/* = SKIP -b/267953710 GALAXYS22 VULKAN : FramebufferFetchES31.DrawNonFetchDrawFetchInStorageBufferThenClear_NonCoherent/* = SKIP -b/267953710 GALAXYS22 VULKAN : ImageTestES3.RGBAHBUploadDataColorspace/* = SKIP -b/267953710 GALAXYS22 VULKAN : ImageTestES3.SourceAHBMipTarget2DMip/* = SKIP -b/267953710 GALAXYS22 VULKAN : ImageTestES3.SourceAHBMipTarget2DMipGenerateMipmap/* = SKIP -b/267953710 GALAXYS22 VULKAN : MultisampledRenderToTextureES3Test.DrawCopyDrawAttachDepthStencilClearThenDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : MultisampledRenderToTextureES3Test.RenderbufferDrawCopyDrawAttachDepthStencilClearThenDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.LoadThenDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.RenderbufferLoadThenDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : MultithreadingTestES3.SimultaneousUploadAndDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : OcclusionQueriesTest.ClearNotCounted/* = SKIP -b/267953710 GALAXYS22 VULKAN : OcclusionQueriesTest.MultiQueries/* = SKIP -b/267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.BufferDataWithIncreasedSize/* = SKIP -b/267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.BufferDataWithIncreasedSizeAndUseWithVAOs/* = SKIP -b/267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.D3D11StateSynchronizationOrderBug/* = SKIP -b/267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithDynamicDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithStaticDraw/* = SKIP -b/267953710 GALAXYS22 VULKAN : SampleVariablesTest.SampleID/* = SKIP -b/267953710 GALAXYS22 VULKAN : SampleVariablesTest.SamplePosition/* = SKIP -b/267953710 GALAXYS22 VULKAN : SimpleStateChangeTestES31.TransformFeedbackThenReadWithCompute/* = SKIP -b/267953710 GALAXYS22 VULKAN : Texture2DFloatTestES2.TextureFloatLinearLegacyTest/* = SKIP -b/267953710 GALAXYS22 VULKAN : Texture2DFloatTestES3.TextureFloatLinearLegacyTest/* = SKIP -b/267953710 GALAXYS22 VULKAN : Texture2DFloatTestES2.TextureFloatLinearTest/* = SKIP -b/267953710 GALAXYS22 VULKAN : Texture2DFloatTestES3.TextureFloatLinearTest/* = SKIP -b/267953710 GALAXYS22 VULKAN : TextureSampleShadingTest.Basic/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.bufferDataWithSizeFollowedByZeroAndThenSizeAgainShouldReuseStorage/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.BufferSubDataShouldNotTriggerSyncState_Copy/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.BufferSubDataShouldNotTriggerSyncState_SubData/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinary/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinaryTwice/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsWarmedUpAtLinkTime/* = SKIP -b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFramebufferFetchDrawThenClear/* = SKIP +267953710 GALAXYS22 GLES : VulkanImageTest.DeviceVulkan/* = SKIP +267953710 GALAXYS22 GLES : VulkanImageTest.HasVulkanImageExtensions/* = SKIP +267953710 GALAXYS22 GLES : VulkanExternalImageTest.TextureFormatCompatChromiumFd/* = SKIP +267953710 GALAXYS22 GLES : VulkanExternalImageTestES31.UninitializedOnGLImportAndStorageWrite/* = SKIP +267953710 GALAXYS22 VULKAN : FramebufferFetchES31.DrawNonFetchDrawFetchInStorageBufferThenClear_NonCoherent/* = SKIP +267953710 GALAXYS22 VULKAN : ImageTestES3.RGBAHBUploadDataColorspace/* = SKIP +267953710 GALAXYS22 VULKAN : ImageTestES3.SourceAHBMipTarget2DMip/* = SKIP +267953710 GALAXYS22 VULKAN : ImageTestES3.SourceAHBMipTarget2DMipGenerateMipmap/* = SKIP +267953710 GALAXYS22 VULKAN : MSRTTES3Test.DrawCopyDrawAttachDepthStencilClearThenDraw/* = SKIP +267953710 GALAXYS22 VULKAN : MSRTTES3Test.RenderbufferDrawCopyDrawAttachDepthStencilClearThenDraw/* = SKIP +267953710 GALAXYS22 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.LoadThenDraw/* = SKIP +267953710 GALAXYS22 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.RenderbufferLoadThenDraw/* = SKIP +267953710 GALAXYS22 VULKAN : MultithreadingTestES3.SimultaneousUploadAndDraw/* = SKIP +267953710 GALAXYS22 VULKAN : OcclusionQueriesTest.ClearNotCounted/* = SKIP +267953710 GALAXYS22 VULKAN : OcclusionQueriesTest.MultiQueries/* = SKIP +267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.BufferDataWithIncreasedSize/* = SKIP +267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.BufferDataWithIncreasedSizeAndUseWithVAOs/* = SKIP +267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.D3D11StateSynchronizationOrderBug/* = SKIP +267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithDynamicDraw/* = SKIP +267953710 GALAXYS22 VULKAN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithStaticDraw/* = SKIP +267953710 GALAXYS22 VULKAN : SampleVariablesTest.SampleID/* = SKIP +267953710 GALAXYS22 VULKAN : SampleVariablesTest.SamplePosition/* = SKIP +267953710 GALAXYS22 VULKAN : SimpleStateChangeTestES31.TransformFeedbackThenReadWithCompute/* = SKIP +267953710 GALAXYS22 VULKAN : Texture2DFloatTestES2.TextureFloatLinearLegacyTest/* = SKIP +267953710 GALAXYS22 VULKAN : Texture2DFloatTestES3.TextureFloatLinearLegacyTest/* = SKIP +267953710 GALAXYS22 VULKAN : Texture2DFloatTestES2.TextureFloatLinearTest/* = SKIP +267953710 GALAXYS22 VULKAN : Texture2DFloatTestES3.TextureFloatLinearTest/* = SKIP +267953710 GALAXYS22 VULKAN : TextureSampleShadingTest.Basic/* = SKIP +267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.bufferDataWithSizeFollowedByZeroAndThenSizeAgainShouldReuseStorage/* = SKIP +267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.BufferSubDataShouldNotTriggerSyncState_Copy/* = SKIP +267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest.BufferSubDataShouldNotTriggerSyncState_SubData/* = SKIP +267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFramebufferFetchDrawThenClear/* = SKIP 372059358 GALAXYS22 VULKAN : MultisampleTestES3.CopyTexImage2DFromMsaaDefaultFbo/* = SKIP 40644776 GALAXYS22 VULKAN : ImageTestES3.SourceAHBTarget2DGenerateMipmap* = SKIP 377923479 GALAXYS22 VULKAN : FramebufferFetchES31.DrawNonFetchDrawFetchInStorageBufferThenClear_ARM/* = SKIP @@ -1304,8 +1380,7 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 42266622 GALAXYS23 VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP // Skip all forms of _*Prerotation* tests 42266622 GALAXYS23 VULKAN : */*Vulkan_EmulatedPrerotation* = SKIP -42266622 GALAXYS23 VULKAN : */*PreRotationEnabled* = SKIP -42266622 GALAXYS23 VULKAN : */*PreRotationDisabled* = SKIP +42266622 GALAXYS23 VULKAN : EGLPreRotation*/* = SKIP // Samsung GalaxyS23 crashes and failures: 42266598 GALAXYS23 VULKAN : EGLBlobCacheTest.ThreadSafety/* = SKIP @@ -1318,7 +1393,7 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 42266598 GALAXYS23 VULKAN : StateChangeTestES3.CullFaceAndFrontFace/* = SKIP 42266598 GALAXYS23 VULKAN : TransformFeedbackTestIOBlocks.Interleaved/* = SKIP 42266598 GALAXYS23 VULKAN : TransformFeedbackTestES32.PrimitivesGeneratedVsIndirectDraw/* = SKIP -42266598 GALAXYS23 VULKAN : VulkanPerformanceCounterTest.DepthFuncALWAYSWithDepthMaskDisabledShouldNotLoadStore/* = SKIP +42266598 GALAXYS23 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.DepthFuncALWAYSWithDepthMaskDisabledShouldNotLoadStore/* = SKIP 42266598 GALAXYS23 VULKAN : VulkanPerformanceCounterTest.FenceSyncAndColorInvalidate/* = SKIP // Samsung Galaxy A23 crashes and failures (split from combined A23+S23 list): @@ -1358,8 +1433,7 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 42266622 GALAXYA23 VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP // Skip all forms of _*Prerotation* tests 42266622 GALAXYA23 VULKAN : */*Vulkan_EmulatedPrerotation* = SKIP -42266622 GALAXYA23 VULKAN : */*PreRotationEnabled* = SKIP -42266622 GALAXYA23 VULKAN : */*PreRotationDisabled* = SKIP +42266622 GALAXYA23 VULKAN : EGLPreRotation*/* = SKIP // Samsung Galaxy A23 crashes: 42266622 GALAXYA23 VULKAN : ClearTest.Stencil8Scissored/* = SKIP @@ -1367,7 +1441,6 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 42266622 GALAXYA23 VULKAN : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP // Samsung Galaxy A23 non-crash failures -42266622 GALAXYA23 VULKAN : BlitFramebufferTest.BlitMultisampleStencilToDefault/* = SKIP 42266622 GALAXYA23 VULKAN : ClearTestES3.ClearMaxAttachmentsAfterDraw/* = SKIP 42266622 GALAXYA23 VULKAN : ClearTestES3.ClearStencilAfterDraw/* = SKIP 42266622 GALAXYA23 VULKAN : ClearTestES3.MaskedClearBufferBug/* = SKIP @@ -1396,7 +1469,9 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 42266622 GALAXYA23 VULKAN : PixelLocalStorageTest.MipMapLevels/* = SKIP 42266622 GALAXYA23 VULKAN : PixelLocalStorageTest.PLSWithSamplers/* = SKIP 42266622 GALAXYA23 VULKAN : PixelLocalStorageTest.R32/* = SKIP +42266622 GALAXYA23 VULKAN : PixelLocalStorageTest.R32_noncoherent/* = SKIP 42266622 GALAXYA23 VULKAN : PixelLocalStorageTest.RGBA8/* = SKIP +42266622 GALAXYA23 VULKAN : PixelLocalStorageTest.RGBA8_noncoherent/* = SKIP 42266622 GALAXYA23 VULKAN : ProgramBinaryES3Test.SaveAndLoadDetachedShaders/* = SKIP 42266622 GALAXYA23 VULKAN : TransformFeedbackTest.BaseInstance/* = SKIP 42266622 GALAXYA23 VULKAN : TransformFeedbackTestES32.PrimitivesWrittenAndGenerated/* = SKIP @@ -1410,49 +1485,263 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 42266622 GALAXYA23 VULKAN : VulkanExternalImageTest.TextureFormatCompatChromiumFd/* = SKIP // Samsung Galaxy S24 (Xclipse/Exynos) -359904354 GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.ChangeFBOSizeAndAttachmentsCount/* = SKIP -359904354 GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP -359904354 GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.CreateNoAttachmentFBOWithDifferentSize/* = SKIP -359904354 GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.RenderingLimitToDefaultFBOSizeWithNoAttachments/* = SKIP +359904354 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.ChangeFBOSizeAndAttachmentsCount/* = SKIP +359904354 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP +359904354 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.CreateNoAttachmentFBOWithDifferentSize/* = SKIP +359904354 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferTest_ES31.RenderingLimitToDefaultFBOSizeWithNoAttachments/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferFetchES31.DrawNonFetchDrawFetchInStorageBufferThenClear_ARM/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferFetchES31.DrawNonFetchDrawFetchInStorageBufferThenClear_Coherent/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferFetchES31.DrawNonFetchDrawFetchInStorageBufferThenClear_NonCoherent/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : FramebufferFetchES31.MultiSampled/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTest.SourceNativeClientBufferTargetRenderbuffer/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTest.SourceNativeClientBufferTargetRenderbuffer_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceAHBTarget2DGenerateMipmap/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceAHBTarget2DGenerateMipmapColorspaceBlend/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceAHBTarget2DGenerateMipmap_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceYUVAHBTargetExternalCopySrc/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : MultisampleTestES3.CopyTexImage2DFromMsaaDefaultFbo/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : RobustBufferAccessBehaviorTest.BufferDataWithIncreasedSize/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : RobustBufferAccessBehaviorTest.BufferDataWithIncreasedSizeAndUseWithVAOs/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : RobustBufferAccessBehaviorTest.D3D11StateSynchronizationOrderBug/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithDynamicDraw/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithStaticDraw/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : SampleVariablesTest.SampleID/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : SampleVariablesTest.SamplePosition/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : Texture2DFloatTestES2.TextureFloatLinearLegacyTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : Texture2DFloatTestES2.TextureFloatLinearTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : Texture2DFloatTestES3.TextureFloatLinearLegacyTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : Texture2DFloatTestES3.TextureFloatLinearTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : TextureMultisampleTest.MaskedDrawWithSampleID/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : TextureSampleShadingTest.Basic/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFramebufferFetchDrawThenClear/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceAHBMipTarget2DMip/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceAHBMipTarget2DMipGenerateMipmap/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS VULKAN : ImageTestES3.SourceAHBTargetTexture2DGenerateMipmap/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : VulkanImageTest.DeviceVulkan/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : VulkanImageTest.HasVulkanImageExtensions/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : VulkanExternalImageTestES31.UninitializedOnGLImportAndStorageWrite/* = SKIP +465357680 SAMSUNG GALAXYS24EXYNOS VULKAN : StateChangeTestES3.PrimitiveRestart/ES3_Vulkan_NoSupportsExtendedDynamicState2* = SKIP +465357680 SAMSUNG GALAXYS24EXYNOS VULKAN : StateChangeTestES3.PrimitiveRestart/ES3_Vulkan_NoUsePrimitiveRestartEnableDynamicState = SKIP + +// Additional Xclipse failures on latest public +410630704 SAMSUNG GALAXYS24EXYNOS GLES : AdvancedBlendTest.AdvancedBlendDisabledAndThenEnabledKHR/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : AdvancedBlendTest.AdvancedBlendEnabledAndThenDisabledKHR/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : AdvancedBlendTest.AdvancedBlendNotAppliedWhenBlendIsDisabledKHR/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : AtomicCounterBufferTest31.AtomicCounterQueries/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : BlitFramebufferTest.BlitMultisampledFramebufferToMRT/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : BlitFramebufferTest.BlitWithDifferentSizesColorAttachments/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : BlitFramebufferTestES31.BlitNonZeroLevelSource/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : BlobCacheInternalRejectionTest.ShaderCacheFunctional/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.ClipCullInterpolation/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.ClipInterpolation/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.CullInterpolation/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.EachClipDistance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.FourClipDistances/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.FourCullDistances/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.Octagon/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.OneClipDistance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.OneCullDistance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.Pruned/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.SizeCheckCombined/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.SizeCheck/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.SizedArrayLength/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.StorageQualifiers/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.ThreeClipDistancesRedeclared/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.ThreeClipDistances/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ClipCullDistanceTest.Unused/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ContextNoErrorPPOTest31.DrawWithPPO/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ContextNoErrorPPOTest31.DrawWithProgramThenPPO/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ContextNoErrorPPOTest31.RepeatedCallToUseProgramStagesWithSamePrograms/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ContextNoErrorPPOTest31.UseProgramStagesWithDifferentPrograms/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : CopyTexImageTestES3.CopyTexSubImageFromNonZeroBaseDifferentFormats/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseInstanceTest.DrawArraysInstancedBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseInstanceTest.DrawElementsInstancedBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseInstanceTest.DrawElementsInstancedBaseVertexBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseVertexBaseInstanceTest.DrawArraysInstancedBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseVertexBaseInstanceTest.DrawElementsInstancedBaseVertexBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseVertexBaseInstanceTest.MultiDrawArraysInstancedBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawBaseVertexBaseInstanceTest.MultiDrawElementsInstancedBaseVertexBaseInstance/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DrawElementsTest.MaxElementIndex/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : DXT1CompressedTextureTest.ReinitImageWithIncompatibleLevels/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLBlobCacheInternalRejectionTest.ShaderCacheFunctional/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLBufferAgeTest.BufferPreserved/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLBufferAgeTest.QueryBufferAgeAfterLoop/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLContextCompatibilityTest.PbufferSameConfig/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLSurfaceTest.GetMultisamplefvAfterClear/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EGLSurfaceTest.ResizeBeforeDraw/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EXTBlendFuncExtendedDrawTestES31.UseProgramPipeline/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EXTBlendFuncExtendedDrawTestES31.UseTwoProgramStages/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : EXTMultisampleCompatibilityTest.DrawAndResolve/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES31.ChangeFBOSizeAndAttachmentsCount/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES31.ChangeFBOSizeWithNoAttachments/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES31.CreateNoAttachmentFBOWithDifferentSize/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES31.MixesMultisampleTextureRenderbuffer/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES31.RenderingLimitToDefaultFBOSizeWithNoAttachments/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES3.BlitWithDifferentPreRotations/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : FramebufferTest_ES3.BlitWithin2DTexture/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GeometryShaderTest.GLLayerIneffectiveWithoutLayeredFramebuffer/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GeometryShaderTest.RecompileSeparableVSWithVaryings/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GeometryShaderTest.RedeclareGlInBeforeInputSize/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GeometryShaderTest.RedeclareGlIn/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GetImageTestES1.PalettedTexImage/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GLSLTest_ES31.SeparableProgramWithMismatchingShaderInterface/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GLSLTest_ES31.TernaryOnStructsInDifferentBlockStorages/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GLSLTest_ES3.DenormFloatsToIntValues/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : GLSLTest.ScreenFlipCauseStandardDerivativesWrong/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES31.UseSourceTextureAsStorageImage/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.AHBImportReleaseStress/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.PartialClearYUVAHB/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.Source2DTargetExternalESSL3_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.Source3DTargetExternalESSL3_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.SourceAHBTargetTexture2DGenerateMipmap/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.SourceCubeTargetExternalESSL3_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.SourceRenderbufferTargetTextureExternalESSL3_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTestES3.SourceYUVAHBTargetExternalYUVSampleVS/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.Source2DTarget2D_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.Source2DTargetExternal_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.Source2DTargetRenderbuffer_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.Source3DTargetExternal_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.Source3DTargetTexture_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceAHBCorrupt/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceAHBInvalid/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceCubeTarget2D_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceCubeTargetExternal_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceCubeTargetRenderbuffer_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceNativeClientBufferTargetRenderbuffer_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceRenderbufferTargetRenderbuffer_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceRenderbufferTargetTexture_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ImageTest.SourceRenderbufferTargetTextureExternal_Colorspace/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : LineLoopIndirectTest.TwoIndirectDrawsInDifferentIndirectBuffer/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : LineLoopTest.DrawTriangleElementsBetweenArrays/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : LinkAndRelinkTestES31.SuccessfulLinkThenFailingRelinkWithPPO/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : MultithreadingTestES3.SharedSrgbTextureMultipleContexts/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : OcclusionQueriesTest.WrongSkippedQuery/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PalettedTextureTest.PalettedFormatsAreSupported/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PalettedTextureTest.PalettedTextureSampling/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PbufferTest.BindTexImageOverwriteReleasesOrphanedPbuffer/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PbufferTest.BindTexImageOverwrite/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PbufferTest.ClearAndBindTexImageSrgb/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PbufferTest.ClearAndBindTexImageSrgbSkipDecode/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.BlendColorMaskAndClear/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.ColorAttachment0Workaround/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.CopyTexSubImage/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.DrawStateReset/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTestES31.DrawStateReset/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTestES31.TextureCubeArrayFaces/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.FragmentReject_depth/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.FragmentReject_stencil/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.FragmentReject_viewport/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.FunctionArguments/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.Interrupt/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.LoadAfterStore/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.LoadOps/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.MaxCombinedDrawBuffersAndPLSPlanes/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.PLSWithSamplers/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.ProgramCache/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.RasterizerDiscard/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.TextureCubeFaces/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : PixelLocalStorageTest.TextureLevelsAndLayers/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.BindBufferRangeForMultipleUBOsInMultipleStages/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.BindSamplerBeforeCreatingPipeline/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.DetachAndModifyShader/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.DrawWith2DTexture/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.FragmentStageUniformBlockBindBufferRangeTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.FragmentStageUniformBlockBinding/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.FragmentStageUniformBlockBufferDataTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.FragmentStageUniformTest/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.LinkedImageUniforms/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.ModifyAndRelinkShader/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.ProgramBinary/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.ProgramPipelineBindBufferRange/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.ProgramPipelineVaryings/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.SampleTextureAThenTextureB/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.UniformBufferUpdatesBeforeBindToPPO/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.UniformUpdate/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.UniformUpdateTwoPipelines/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.UseCreateShaderProgramv/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.UseProgramStages/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.UseProgramStagesWithDifferentPrograms/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.VaryingIOBlockSeparableProgram/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineTest31.VaryingLocationMismatch/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineXFBTest31.SeparableProgramWithXFBSeparateMode/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : ProgramPipelineXFBTest31.VaryingIOBlockSeparableProgramWithXFB/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : SRGBFramebufferTestES3.BlitFramebuffer/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : SRGBFramebufferTest.MultipleFramebuffers/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : SRGBFramebufferTest.NegativeLifetimeTracking/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : SRGBTextureTestES3.SRGBDecodeTexelFetchArray/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : SRGBTextureTestES3.SRGBDecodeTexelFetch/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : SRGBTextureTestES3.SRGBSkipEncodeAndDecodeInGenerateMipmap/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : Texture2DMemoryTestES3.TextureDataInLoopManyTimes/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : Texture2DMemoryTestES3.TextureDataInLoopUntilFlush/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : Texture2DTestES31PPO.SingleTextureMultipleSamplers/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : Texture2DTestES31PPO.TexStorage/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : Texture2DTestES3.TextureBaseLevelGreaterThanMaxLevel3Levels/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : Texture3DTestES3.PixelUnpackReloadTexImage/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : TextureTestES31.Texture2DArrayChangeLayerLevel/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : TextureTestES31.Texture2DChangeLevel/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : TextureUploadFormatTest_ES3.AllWithPBO/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : UniformBufferMemoryTest.BufferDataInLoopManyTimes/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS GLES : WebGLCompatibilityTest.GenerateMipmapUnsizedFloatingPointTexture/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.Coherency_noncoherent/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.Coherency/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.DrawCommandValidation/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.FlushFinishSync/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.ForgetBarrier/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.LoadOnly/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.MemorylessStorage/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.MipMapLevels/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.R32_noncoherent/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.R32/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.RGBA8_noncoherent/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageTest.RGBA8/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageValidationTest.DrawCommandValidation/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageValidationTest.FramebufferTexturePixelLocalStorageANGLE/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageValidationTest.GetFramebufferPixelLocalStorageParametersANGLE/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageValidationTest.ModifyTextureDuringPLS/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageValidationTest.PLSActive_bans_blend_equation_advanced/* = SKIP +410630704 SAMSUNG GALAXYS24EXYNOS : PixelLocalStorageValidationTest.PLSActive_bans_blend_func_extended/* = SKIP + // Snapdragon 8 Gen3 Mobile Reference Device -b/328156792 PINEAPPLE VULKAN : BlitFramebufferTest.*Stencil* = SKIP -b/328156792 PINEAPPLE VULKAN : ClearTestES3.RepeatedStencilClearWithBlitInBetween/* = SKIP -b/328156792 PINEAPPLE VULKAN : ClearTestES31.Bind3DTextureAndClearUsingAttachment0/* = SKIP -b/328156792 PINEAPPLE VULKAN : ClearTest.MaskedClearThenDrawWithUniform/* = SKIP -b/328156792 PINEAPPLE VULKAN : ClearTest.Stencil8Scissored/* = SKIP -b/328156792 PINEAPPLE VULKAN : ClearTextureEXTTest.Clear3D*/* = SKIP -b/328156792 PINEAPPLE VULKAN : ClearTextureEXTTest.StencilTexture/* = SKIP -b/328156792 PINEAPPLE VULKAN : DepthStencilTestES3.FramebufferClearThenStencilAttachedThenStencilTestState/* = SKIP -b/328156792 PINEAPPLE VULKAN : DepthStencilTestES3.FramebufferClearThenStencilTestStateThenStencilAttached/* = SKIP -b/328156792 PINEAPPLE VULKAN : DepthStencilTestES3.StencilTestStateThenFramebufferClearThenStencilAttached/* = SKIP -b/328156792 PINEAPPLE VULKAN : DepthStencilTest.StencilOnlyDrawThenCopyThenDraw/* = SKIP -b/328156792 PINEAPPLE VULKAN : DepthStencilTest.StencilOnlyEmulatedWithPacked/* = SKIP -b/328156792 PINEAPPLE VULKAN : DrawBuffersTest.NoneWithStencil/* = SKIP -b/328156792 PINEAPPLE VULKAN : FramebufferTest_ES31.* = SKIP -b/328156792 PINEAPPLE VULKAN : GeometryShaderTest.LayeredFramebuffer* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest.ConstantFoldedConstantsRetainPrecision/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest_ES31.ArrayOfArrayOfSamplerInStructDynamicIndex/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest_ES31.ParameterArrayArrayArraySampler/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest_ES31.TypesUsedInDifferentBlockStorages/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest_ES3.*ArrayOfMatrices/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest_ES3.SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest_ES3.ValidIndexClampES300/* = SKIP -b/328156792 PINEAPPLE VULKAN : GLSLTest.VectorAndMatrixScalarizationDoesNotAffectRendering/* = SKIP -b/328156792 PINEAPPLE VULKAN : ImageTestES3.RGBAHBUploadDataColorspace/* = SKIP -b/328156792 PINEAPPLE VULKAN : ImageTest.SourceAHBTarget2DMSRTTInteraction/* = SKIP -b/328156792 PINEAPPLE VULKAN : MultisampledRenderToTexture* = SKIP -b/328156792 PINEAPPLE VULKAN : OcclusionQueriesTestES3.UnresolveNotCounted/* = SKIP -b/328156792 PINEAPPLE VULKAN : PackUnpackTest.PackUnpack* = SKIP -b/328156792 PINEAPPLE VULKAN : ProgramPipelineTest31.SampleTextureAThenTextureB/* = SKIP -b/328156792 PINEAPPLE VULKAN : RobustResourceInitTest* = SKIP -b/328156792 PINEAPPLE VULKAN : SampleVariablesTest.SamplePosition/* = SKIP -b/328156792 PINEAPPLE VULKAN : StateChangeTestES3.RasterizerDiscard/* = SKIP -b/328156792 PINEAPPLE VULKAN : StateChangeTestES3.StencilReferenceAndCompareMask/* = SKIP -b/328156792 PINEAPPLE VULKAN : Texture2DMemoryTestES3.TextureDataInLoopManyTimes/* = SKIP -b/328156792 PINEAPPLE VULKAN : TransformFeedbackTestIOBlocks.Interleaved/* = SKIP -b/328156792 PINEAPPLE VULKAN : VulkanPerformanceCounterTest.RenderToTexture* = SKIP -b/328156792 PINEAPPLE VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP +328156792 PINEAPPLE VULKAN : BlitFramebufferTest.*Stencil* = SKIP +328156792 PINEAPPLE VULKAN : ClearTestES3.RepeatedStencilClearWithBlitInBetween/* = SKIP +328156792 PINEAPPLE VULKAN : ClearTestES31.Bind3DTextureAndClearUsingAttachment0/* = SKIP +328156792 PINEAPPLE VULKAN : ClearTest.MaskedClearThenDrawWithUniform/* = SKIP +328156792 PINEAPPLE VULKAN : ClearTest.Stencil8Scissored/* = SKIP +328156792 PINEAPPLE VULKAN : ClearTextureEXTTest.Clear3D*/* = SKIP +328156792 PINEAPPLE VULKAN : ClearTextureEXTTest.StencilTexture/* = SKIP +328156792 PINEAPPLE VULKAN : DepthStencilTestES3.FramebufferClearThenStencilAttachedThenStencilTestState/* = SKIP +328156792 PINEAPPLE VULKAN : DepthStencilTestES3.FramebufferClearThenStencilTestStateThenStencilAttached/* = SKIP +328156792 PINEAPPLE VULKAN : DepthStencilTestES3.StencilTestStateThenFramebufferClearThenStencilAttached/* = SKIP +328156792 PINEAPPLE VULKAN : DepthStencilTest.StencilOnlyDrawThenCopyThenDraw/* = SKIP +328156792 PINEAPPLE VULKAN : DepthStencilTest.StencilOnlyEmulatedWithPacked/* = SKIP +328156792 PINEAPPLE VULKAN : DrawBuffersTest.NoneWithStencil/* = SKIP +328156792 PINEAPPLE VULKAN : FramebufferTest_ES31.* = SKIP +328156792 PINEAPPLE VULKAN : GeometryShaderTest.LayeredFramebuffer* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest.ConstantFoldedConstantsRetainPrecision/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest_ES31.ArrayOfArrayOfSamplerInStructDynamicIndex/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest_ES31.ParameterArrayArrayArraySampler/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest_ES31.TypesUsedInDifferentBlockStorages/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest_ES3.*ArrayOfMatrices/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest_ES3.SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest_ES3.ValidIndexClampES300/* = SKIP +328156792 PINEAPPLE VULKAN : GLSLTest.VectorAndMatrixScalarizationDoesNotAffectRendering/* = SKIP +328156792 PINEAPPLE VULKAN : ImageTestES3.RGBAHBUploadDataColorspace/* = SKIP +328156792 PINEAPPLE VULKAN : ImageTest.SourceAHBTarget2DMSRTTInteraction/* = SKIP +328156792 PINEAPPLE VULKAN : MultisampledRenderToTexture* = SKIP +328156792 PINEAPPLE VULKAN : OcclusionQueriesTestES3.UnresolveNotCounted/* = SKIP +328156792 PINEAPPLE VULKAN : PackUnpackTest.PackUnpack* = SKIP +328156792 PINEAPPLE VULKAN : ProgramPipelineTest31.SampleTextureAThenTextureB/* = SKIP +328156792 PINEAPPLE VULKAN : RobustResourceInitTest* = SKIP +328156792 PINEAPPLE VULKAN : SampleVariablesTest.SamplePosition/* = SKIP +328156792 PINEAPPLE VULKAN : StateChangeTestES3.RasterizerDiscard/* = SKIP +328156792 PINEAPPLE VULKAN : StateChangeTestES3.StencilReferenceAndCompareMask/* = SKIP +328156792 PINEAPPLE VULKAN : Texture2DMemoryTestES3.TextureDataInLoopManyTimes/* = SKIP +328156792 PINEAPPLE VULKAN : TransformFeedbackTestIOBlocks.Interleaved/* = SKIP +328156792 PINEAPPLE VULKAN : VulkanPerformanceCounterTest.RenderToTexture* = SKIP +328156792 PINEAPPLE VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP // MaliG710 crashes 42266649 MALIG710 VULKAN : BufferSubDataTest.MapInvalidateThenBufferSubData/* = SKIP @@ -1479,9 +1768,9 @@ b/328156792 PINEAPPLE VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP 42266649 MALIG710 VULKAN : ImageTest.ANGLEExtensionAvailability/* = SKIP 42266649 MALIG710 VULKAN : ImageTestES3.SourceAHBCubeTargetCube/* = SKIP 42266649 MALIG710 VULKAN : ImageTestES31.SourceAHBCubeArrayTargetCubeArray/* = SKIP -42266649 MALIG710 VULKAN : MultisampledRenderToTextureES31Test.BlitFramebufferAttachment1/* = SKIP -42266649 MALIG710 VULKAN : MultisampledRenderToTextureES31Test.MixedMultisampledAndMultisampledRenderToTexture/* = SKIP -42266649 MALIG710 VULKAN : MultisampledRenderToTextureES31Test.RenderbufferBlitFramebufferAttachment1/* = SKIP +42266649 MALIG710 VULKAN : MSRTTES31Test.BlitFramebufferAttachment1/* = SKIP +42266649 MALIG710 VULKAN : MSRTTES31Test.MixedMultisampledAndMultisampledRenderToTexture/* = SKIP +42266649 MALIG710 VULKAN : MSRTTES31Test.RenderbufferBlitFramebufferAttachment1/* = SKIP 42266649 MALIG710 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.ClearThenDraw/* = SKIP 42266649 MALIG710 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.LoadThenDraw/* = SKIP 42266649 MALIG710 VULKAN : MultisampledRenderToTextureWithAdvancedBlendTest.RenderbufferClearThenDraw/* = SKIP @@ -1504,9 +1793,9 @@ b/328156792 PINEAPPLE VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP 42266649 MALIG710 VULKAN : TransformFeedbackWithDepthBufferTest.RecordAndDrawWithDepthWriteEnabled/* = SKIP 42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest.MappingGpuReadOnlyBufferGhostsBuffer_Copy/* = SKIP 42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest.MappingGpuReadOnlyBufferGhostsBuffer_SubData/* = SKIP -42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest.RenderToTextureDepthStencilRenderbufferShouldNotLoad/* = SKIP +42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.RenderToTextureDepthStencilRenderbufferShouldNotLoad/* = SKIP 42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest.RenderToTextureDepthStencilTextureShouldNotLoad/* = SKIP -42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest.RenderToTextureUninitializedAndUnusedDepthStencil/* = SKIP +42266649 MALIG710 VULKAN : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps.RenderToTextureUninitializedAndUnusedDepthStencil/* = SKIP 42266649 MALIG710 VULKAN : WebGLCompatibilityTest.FramebufferFloatColorAttachmentMRT/* = SKIP 42266807 VULKAN : Texture2DBaseMaxTestES3.NotColorRenderableWithColorRenderableBeyondMaxLevel/* = SKIP @@ -1520,7 +1809,7 @@ b/328156792 PINEAPPLE VULKAN : WebGL2GLSLTest.InitUninitializedLocals/* = SKIP 42266876 LINUX VULKAN : VulkanPerformanceCounterTest.SubmittingOutsideCommandBufferDoesNotBreakRenderPass/* = SKIP // Workaround feature that is only supposed to be enabled on vulkan backend -b/292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = SKIP +292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = SKIP // NVIDIA driver has a bug in its YCbCr implementation 42267014 NVIDIA VULKAN : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues/* = SKIP @@ -1531,14 +1820,20 @@ b/292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = 42264369 ANDROID GLES : TextureBufferTestES31.DrawIncompleteNonZeroTexture/* = SKIP 42264369 ANDROID GLES : TextureBufferTestES31.DrawCompleteZeroTexture/* = SKIP 42264369 ANDROID GLES : TextureBufferTestES31.DrawCompleteNonZeroTexture/* = SKIP +42264369 ANDROID GLES : TextureBufferTestES31.TexBufferDrawTwice/* = SKIP +42264369 ANDROID GLES : TextureBufferTestES31.UseAsUBOThenUpdateThenAsTextureBuffer/* = SKIP +42264369 ANDROID GLES : TextureBufferTestES31.MapTextureBufferInvalidateThenWrite/* = SKIP +42264369 ANDROID GLES : ComputeShaderTest.ImageBufferMapWrite/* = SKIP +42264369 ANDROID GLES : ComputeShaderTest.ImageBufferMapWriteAndBufferSubData/* = SKIP +42264369 ANDROID GLES : GLSLTest_ES31.ShortCircuitOutOfBoundsAccess/* = SKIP // WebGPU failures -42266907 WGPU : RendererTest.SimpleOperation/* = SKIP -42266907 WGPU : RendererTest.Draw/* = SKIP +// All tests are flaky on Linux Intel due to X errors. +454630429 WGPU LINUX INTEL : * = SKIP // BasicUniformUsage tests fail too frequently with WGPU 376553328 LINUX INTEL WGPU : BasicUniformUsageTest.* = SKIP // Can't use a uniform struct outside of uniform address space. -376553328 WGPU : SimpleUniformUsageTestES3.UseUniformStructOutsideOfUniformAddressSpace/* = SKIP +376553328 WGPU : SimpleUniformTestES3.UseUniformStructOutsideOfUniformAddressSpace/* = SKIP 42267012 WGPU : ClearTest.*Scissor* = SKIP 42267012 WGPU : ClearTest.*Mask* = SKIP 42267012 WGPU : ClearTest.DefaultFramebuffer* = SKIP @@ -1547,22 +1842,212 @@ b/292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = 42266974 WGPU : Texture2DTest.Tex* = SKIP 42266974 WGPU : Texture2DTest.Upload* = SKIP 42266974 WGPU : Texture2DTest.*Superseding* = SKIP -42266974 WGPU : Texture2DTest.*Multiple* = SKIP 42266974 WGPU : Texture2DTest.*Copy* = SKIP 42266974 WGPU : Texture2DTest.*Mutable* = SKIP +// Can't generate mipmaps at the moment +389145696 WGPU : MipmapTestES3.*Generate* = SKIP +389145696 WGPU : MipmapTestES3.*TextureArray* = SKIP +389145696 WGPU : MipmapTestES3.*Texture3D* = SKIP +// Can't handle the resize of the texture +389145696 WGPU : MipmapTestES3.ResizeBaseMipTo1x1ThenDelete/* = SKIP +// Can't glReadPixels from a cube map face correctly. +420782526 WGPU : CubeMapTextureTest.SampleCoordinateTransformGrad* = SKIP // 383356846 ubyte index formats are not fully supported yet. 383356846 WGPU : LineLoopTest.*UByte* = SKIP 383356846 WGPU : LineLoopTest.*UShort* = SKIP 383356846 WGPU : LineLoopTest.DrawTriangleElementsBetweenArrays/* = SKIP 383356846 WGPU : LineLoopTest.*IndicesBlend* = SKIP 383356846 WGPU : LineLoopTest.*BufferBlend* = SKIP + +42266907 WGPU : AddMockTextureNoRenderTargetTest.NoProgramOutputWorkaround/* = SKIP +42266907 WGPU : AttributeLayoutBufferIndexed.Test/* = SKIP +42266907 WGPU : AttributeLayoutMemoryIndexed.Test/* = SKIP +42266907 WGPU : AttributeLayoutNonIndexed.Test/* = SKIP +42266907 WGPU : BindUniformLocationTest.Compositor/* = SKIP +42266907 WGPU : BlendPackedTest.RGB565/* = SKIP +42266907 WGPU : BlitFramebufferANGLETest.* = SKIP +42266907 WGPU : DebugMarkerTest.Rendering/* = SKIP +42266907 WGPU : DepthStencilFormatsTest.DepthBuffer16/* = SKIP +42266907 WGPU : DepthStencilTest.StencilOnlyEmulatedWithPacked/* = SKIP +42266907 WGPU : FramebufferFormatsTest.RGB565Renderbuffer/* = SKIP +42266907 WGPU : FramebufferFormatsTest.RGB8AndRGBA8Renderbuffers/* = SKIP +42266907 WGPU : FramebufferFormatsTest.RGB8Renderbuffer/* = SKIP +42267100 WGPU : GLSLTest.SwizzledChainedAssignIncrement/* = SKIP +42267100 WGPU : GLSLTest.NamelessScopedStructs/* = SKIP +42267100 WGPU : GLSLTest.ScopedStructsOrderBug/* = SKIP +42267100 WGPU : GLSLTest.ScopedStructsOrderBug2/* = SKIP +42267100 WGPU : GLSLTest.StructConstantFoldingBug2/* = SKIP +42267100 WGPU : GLSLTest.ScopedStructsBug/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnFloat/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnVec2/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnVec3/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnVec4/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnIVec4/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnMat4/* = SKIP +42267100 WGPU : GLSLValidationTest.MissingReturnStruct/* = SKIP +42267100 WGPU : GLSLTest.CommaTestNoRedundantStatements/* = SKIP +42267100 WGPU : GLSLTest.MaxVaryingVec4_TwoBuiltins/* = SKIP +42267100 WGPU : GLSLTest.MaxVaryingVec4_ThreeBuiltins/* = SKIP +42267100 WGPU : GLSLTest.MaxVaryingVec3Array/* = SKIP +42267100 WGPU : GLSLTest.MaxVaryingVec3AndOneFloat/* = SKIP +42267100 WGPU : GLSLTest.MaxVaryingVec3ArrayAndOneFloatArray/* = SKIP +42267100 WGPU : GLSLTest.MaxVaryingVec2Arrays/* = SKIP +42267100 WGPU : GLSLTest.VerifyMaxVertexUniformVectorsWithSamplers/* = SKIP +42267100 WGPU : GLSLTest.VerifyMaxFragmentUniformVectorsWithSamplers/* = SKIP +42267100 WGPU : GLSLTest.TextureLODRewriteInVertexShader/* = SKIP +42267100 WGPU : GLSLTest.ArrayOfStructContainingArrayOfSamplers/* = SKIP +42267100 WGPU : GLSLValidationTest.IndexConstantSamplerArrayIndexing/* = SKIP +42267100 WGPU : GLSLTest.RenderTrisWithPointCoord/* = SKIP +42267100 WGPU : GLSLTest.NestedSequenceOperatorWithTernaryInside/* = SKIP +42267100 WGPU : GLSLTest.NestedTernaryAndShortCircuit/* = SKIP +42267100 WGPU : GLSLTest.VaryingMatrixArray/* = SKIP +42267100 WGPU : GLSLTest.InactiveVaryingInVertexActiveInFragment/* = SKIP +42267100 WGPU : GLSLTest.StructsWithSamplersAsFunctionArgWithPrototype/* = SKIP +42267100 WGPU : GLSLTest.ArrayOfStructsWithSamplersAsFunctionArg/* = SKIP +42267100 WGPU : GLSLTest.StructWithSamplerArrayAsFunctionArg/* = SKIP +42267100 WGPU : GLSLTest.VectorScalarDivideAndAddInLoop/* = SKIP +42267100 WGPU : GLSLTest.PointCoordConsistency/* = SKIP +42267100 WGPU : GLSLTest.ScreenFlipCauseStandardDerivativesWrong/* = SKIP +42267100 WGPU : GLSLTest.FragCoordConsistency/* = SKIP +42267100 WGPU : GLSLTest.FragData/* = SKIP +42267100 WGPU : GLSLTest.FragData_AlphaToCoverage/* = SKIP +42267100 WGPU : GLSLTest.SeparateStructDeclaratorStructInStruct/* = SKIP +42267100 WGPU : GLSLTest.ConstructorinSequenceOperator/* = SKIP +42267100 WGPU : GLSLTest.VectorAndMatrixScalarizationDoesNotAffectRendering/* = SKIP +42267100 WGPU : GLSLTest.AliasingFunctionOutParams/* = SKIP +42267100 WGPU : GLSLTest.AliasingFunctionOutParamsMultiple/* = SKIP +42267100 WGPU : GLSLTest.AliasingFunctionInOutParams/* = SKIP +42267100 WGPU : GLSLTest.MatrixScalarOps/* = SKIP +42267100 WGPU : GLSLTest.MatrixNegate/* = SKIP +42267100 WGPU : GLSLTest.AliasingFunctionInOutParamsMultiple/* = SKIP +42267100 WGPU : GLSLTest.AliasingFunctionOutParamAndGlobal/* = SKIP +42267100 WGPU : GLSLTest.ConstSamplerParameter/* = SKIP +42267100 WGPU : GLSLTest.ConstInSamplerParameter/* = SKIP +42267100 WGPU : GLSLTest.ConstSamplerParameterAsArgument/* = SKIP +42267100 WGPU : GLSLTest.StructDefinitionInFunctionPrototype/* = SKIP +42267100 WGPU : GLSLTest.NestedReturnedStructs/* = SKIP +42267100 WGPU : GLSLTest.MatEquality/* = SKIP +42267100 WGPU : GLSLTest.StructEquality/* = SKIP +42267100 WGPU : GLSLTest.NestedStructEquality/* = SKIP +42267100 WGPU : GLSLValidationTest.VectorScalarArithmeticWithSideEffectInLoop/* = SKIP +42267100 WGPU : GLSLTestNoValidation.DepthRangeUniforms/* = SKIP +42266907 WGPU : IncompleteTextureTest.IncompleteTexture2D/* = SKIP +42266907 WGPU : IncompleteTextureTest.UpdateTexture/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.DrawArraysLineLoopFollowedByDrawElementsTriangle/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.DrawAtDifferentOffsetAlignments/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.DrawWithDifferentCountsSameOffset/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.DrawWithSameBufferButDifferentModes/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.DrawWithSameBufferButDifferentTypes/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.UInt8Index/* = SKIP +42266907 WGPU : IndexBufferOffsetTest.UInt8IndexSmallUpdates/* = SKIP +42266907 WGPU : IndexedPointsTest* = SKIP +42266907 WGPU : LinkAndRelinkTest.RenderingProgramFailsWithProgramInstalled/* = SKIP +42266907 WGPU : LineLoopStateChangeTest.DrawElementsThenDrawArrays/* = SKIP +42266907 WGPU : LineLoopStateChangeTest.DrawArraysThenDrawElements/* = SKIP +42266907 WGPU : LineLoopStateChangeTest.DrawElementsThenDrawElements/* = SKIP +42266907 WGPU : MaskedScissoredClearTest.Test/* = SKIP +42266907 WGPU : PbufferTest.* = SKIP +42266907 WGPU : PointSpritesTest.* = SKIP +42266907 WGPU : RobustResourceInitTest.* = SKIP +42266907 WGPU : Sampler2DAsFunctionParameterTest.Sampler2DAsFunctionParameter/* = SKIP +42266907 WGPU : SamplerArrayAsFunctionParameterTest.SamplerArrayAsFunctionParameter/* = SKIP +42266907 WGPU : SamplerArrayTest.SamplerArrayDraw/* = SKIP +42266907 WGPU : SamplerInNestedStructAsFunctionParameterTest.SamplerInNestedStructAsFunctionParameter/* = SKIP +42266907 WGPU : SamplerInStructArrayAsFunctionParameterTest.SamplerInStructArrayAsFunctionParameter/* = SKIP +395659799 WGPU : SimpleOperationTest.BlendEquationGetInteger/* = SKIP +395659799 WGPU : SimpleOperationTest.DrawsWithNoAttributeData/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DeleteNonActiveTextureThenDraw/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DeleteTextureThenDraw/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawArraysThenDrawElements/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawArraysWithZeroSizedElementArrayBuffer/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawElementsThenDrawElementsNewIndexBuffer/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawElementsThenDrawElementsNewIndices/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawElementsThenDrawElementsWholeNewIndices/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawElementsUBYTEX2ThenDrawElementsUSHORT/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawRepeatUnalignedVboChange/* = SKIP +42266907 WGPU : SimpleStateChangeTest.DrawWithTextureTexSubImageThenDrawAgain/* = SKIP +42266907 WGPU : SimpleStateChangeTest.FboEarlyCullFaceBackCCWState/* = SKIP +42266907 WGPU : SimpleStateChangeTest.FboEarlyCullFaceBackCWState/* = SKIP +42266907 WGPU : SimpleStateChangeTest.RebindTranslatedAttribute/* = SKIP +42266907 WGPU : SimpleStateChangeTest.RedefineFramebufferTexture/* = SKIP +42266907 WGPU : SimpleStateChangeTest.RedefineTextureInUse/* = SKIP +42266907 WGPU : SimpleStateChangeTest.UpdateBoundElementArrayBuffer/* = SKIP +42266907 WGPU : SimpleStateChangeTest.UpdateBufferInUse/* = SKIP +42266907 WGPU : SixteenBppTextureTest.RGB565Validation/* = SKIP +42266907 WGPU : SixteenBppTextureTest.RGBA4444Validation/* = SKIP +42266907 WGPU : SixteenBppTextureTest.RGBA5551Validation/* = SKIP +42266907 WGPU : StateChangeRenderTest.DepthRangeUpdates/* = SKIP +42266907 WGPU : StateChangeRenderTest.GenerateMipmap/* = SKIP +42266907 WGPU : StateChangeRenderTest.RecreateTexture/* = SKIP +42266907 WGPU : StateChangeTest.DisablingBufferedVertexAttribute/* = SKIP +42266907 WGPU : StateChangeTest.MultiContextVertexAttribute/* = SKIP +42266907 WGPU : StateChangeTest.SetCurrentAttribute/* = SKIP +42266907 WGPU : Texture2DTestWithDrawScale.MipmapsTwice/* = SKIP +42266907 WGPU : TextureCubeTest.CubeMapFBOScissoredClear/* = SKIP +42266907 WGPU : TextureLimitsTest.MaxActiveVertexTextures/* = SKIP +42266907 WGPU : TextureLimitsTest.MaxCombinedTextures/* = SKIP +42266907 WGPU : TextureLimitsTest.MaxVertexTextures/* = SKIP +42266907 WGPU : TextureLimitsTest.TextureTypeConflict/* = SKIP +42266907 WGPU : TextureUploadFormatTest.All/* = SKIP +42266907 WGPU : TriangleFanDrawTest.DrawTriangleFan/* = SKIP +42266907 WGPU : TriangleFanDrawTest.DrawTriangleFanElements/* = SKIP +42266907 WGPU : UniformTest.SamplerUniformsAppearOnce/* = SKIP +42266907 WGPU : UniformTest.UnusedUniformsInSamplerArray/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment1AUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment1LAUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment1LUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment2AUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment2LAByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment2LAUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment4AUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment4LAUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment4LUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment8AUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment8LAUByte/* = SKIP +42266907 WGPU : UnpackAlignmentTest.Alignment8LUByte/* = SKIP +42266907 WGPU : VertexAttributeCachingTest.BufferMulticaching/* = SKIP +42266907 WGPU : VertexAttributeCachingTest.BufferMulticachingWithOneUnchangedAttrib/* = SKIP +42266907 WGPU : VertexAttributeTest.AliasingVectorAttribLocationsDifferingPrecisions/* = SKIP +42266907 WGPU : VertexAttributeTest.DisabledAttribArrays/* = SKIP +42266907 WGPU : VertexAttributeTest.DisabledAttribUpdates/* = SKIP +42266907 WGPU : VertexAttributeTest.DrawArraysWithAlignedAndUnalignedBufferOffset/* = SKIP +42266907 WGPU : VertexAttributeTest.DrawArraysWithOverlapBufferSubData/* = SKIP +42266907 WGPU : VertexAttributeTest.DrawArraysWithUnalignedBufferOffset/* = SKIP +42266907 WGPU : VertexAttributeTest.MaxAttribs/* = SKIP +42266907 WGPU : VertexAttributeTest.MixedMatrixSources/* = SKIP +42266907 WGPU : VertexAttributeTest.MixedUsingBufferAndClientMemoryPointer/* = SKIP +42266907 WGPU : VertexAttributeTest.NegativeUsingDifferentFormatAndSameBuffer/* = SKIP +42266907 WGPU : VertexAttributeTest.NegativeUsingDifferentFormatAndSameClientMemoryPointer/* = SKIP +42266907 WGPU : VertexAttributeTest.ShortNormalized/* = SKIP +42266907 WGPU : VertexAttributeTest.SimpleBindAttribLocation/* = SKIP +42266907 WGPU : VertexAttributeTest.UnusedVertexAttribWorks/* = SKIP +42266907 WGPU : VertexAttributeTest.UsingDifferentFormatAndSameBuffer/* = SKIP +42266907 WGPU : VertexAttributeTest.UsingDifferentFormatAndSameClientMemoryPointer/* = SKIP +42266907 WGPU : VertexAttributeTest.VertexFormatConversionOfNonExistingAttribute/* = SKIP +42266907 WGPU : ViewportTest.* = SKIP +42266907 WGPU : WebGLGLSLTest.MaxVaryingVec4PlusPointCoord/* = SKIP +42266907 WGPU : WebGLGLSLTest.MaxPlusOneVaryingVec3Array/* = SKIP +42266907 WGPU : WebGLGLSLTest.MaxVaryingVec3ArrayAndMaxPlusOneFloatArray/* = SKIP +42266907 WGPU : WebGLGLSLTest.InitUninitializedGlobals/* = SKIP +42266907 WGPU : WebGLGLSLTest.GlobalVariableDeclaredAfterMain/* = SKIP +42266907 WGPU : WebGLGLSLTest.InvalidGlobalsNotInlined/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.DepthStencilBindingPoint/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.DrawElementsBufferOutOfBoundsInIndexBuffer/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.DrawElementsBufferOutOfBoundsInVertexBuffer/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.DrawElementsOffsetRestriction/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.TextureCopyingFeedbackLoops/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.BuiltInInvariant/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.StencilTestDisabledAllowsDifferentStencilMaskAndRef/* = SKIP +42266907 WGPU : WebGLCompatibilityTest.StencilTestEnabledDisallowsDifferentStencilMaskAndRef/* = SKIP +42266907 WGPU : WebGLFramebufferTest.TestAttachments/* = SKIP +42266907 WGPU : WebGLFramebufferTest.TestFramebufferRequiredCombinations/* = SKIP +42266907 WGPU : WebGLReadOutsideFramebufferTest.CopyTexSubImage2D/* = SKIP +42266907 WGPU : WebGLReadOutsideFramebufferTest.CopyTexImage2D/* = SKIP + // 42267100 failures are due to the shader (which uses textures) failing to compile 42267100 WGPU : Texture2DTest.NegativeAPISubImage* = SKIP 42267100 WGPU : Texture2DTest.ZeroSizedUploads* = SKIP -360083331 LINUX INTEL WGPU : ClearTest.ClearColorThenClearNonExistingDepthStencil/* = SKIP -360083331 LINUX INTEL WGPU : ClearTest.DepthRangefIsClamped/* = SKIP -360083331 LINUX INTEL WGPU : ClearTest.RGBA8Framebuffer/* = SKIP -360083331 LINUX INTEL WGPU : ClearTest.TextureUploadAndRGBA8Framebuffer/* = SKIP +406204357 WGPU : LineLoopPrimitiveRestartTest.PrimitiveRestartRestartOnlyIndicesNoCrash/* = SKIP 360083331 LINUX INTEL WGPU : RendererTest.BufferData/* = SKIP 360083331 LINUX INTEL WGPU : RendererTest.RequestedRendererCreated/* = SKIP 360083331 LINUX INTEL WGPU : Texture2DTest.NPOTSubImageParameters/* = SKIP @@ -1570,9 +2055,32 @@ b/292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = 360083331 LINUX INTEL WGPU : Texture2DTest.QueryBinding/* = SKIP 360083331 LINUX INTEL WGPU : Texture2DTest.SubImageValidationOverflow/* = SKIP 360083331 LINUX INTEL WGPU : Texture2DTest.ZeroSizedUploads/* = SKIP +// Mac Nvidia devices just draw black screens. +389145696 WGPU MAC NVIDIA : * = SKIP +// Unimplemented cube map and non-zero mipmap EGLImages +418022112 WGPU : ImageTest.MipLevels/* = SKIP +418022112 WGPU : ImageTest.RespecificationOfOtherLevel/* = SKIP +418022112 WGPU : ImageTest.SourceCubeAndSameTargetTextureWithEachCubeFace/* = SKIP +423702346 WGPU : SimpleUniformTestES3.PackUniformFP16Test/* = SKIP +438268609 WGPU : CopyTexImageTest.CopyTex*Cube*/* = SKIP +// Unimplemented format conversions for image copies +438268609 WGPU : CopyTexImageTest.RGBAToL*/* = SKIP +438268609 WGPU : CopyTexImageTest.RGBToL/* = SKIP +438268609 WGPU : CopyTexImageTest.RGBAToA*/* = SKIP +438268609 WGPU : CopyTexImageTest.SubImageRGB*ToL*/* = SKIP +438268609 WGPU : CopyTexImageTest.DeleteAfterCopyingToTextures/* = SKIP +438268609 WGPU : CopyTextureTest.InternalFormat/* = SKIP +// WGPU does not currently resize textures +438268609 WGPU : CopyTextureTest.CopyOutsideMipmap/* = SKIP +// Unimplemented format conversions for texture copies +438268609 WGPU : CopyTextureVariationsTest.Copy*Texture/ES2_WebGPU__AToRGB* = SKIP +438268609 WGPU : CopyTextureVariationsTest.Copy*Texture/ES2_WebGPU__LToRGB* = SKIP +438268609 WGPU : CopyTextureVariationsTest.Copy*Texture/ES2_WebGPU__LAToRGB* = SKIP +// WGPU y-flip transforms have a bug when run on NVIDIA GPUs on Linux or Windows. +468025322 NVIDIA WGPU : CopyTextureVariationsTest.Copy*Texture/ES2_WebGPU__*YFlip* = SKIP // SPIR-V compilation error -384593678 VULKAN : SimpleUniformUsageTestES3.CopyOfUniformsWithArrays/* = SKIP +384593678 VULKAN : SimpleUniformTestES3.CopyOfUniformsWithArrays/* = SKIP // Linux/UHD 630 failures caused by OS/driver upgrade. 42267119 LINUX INTEL OPENGL : AtomicCounterBufferTest31.AtomicCounterReadCompute/* = SKIP @@ -1587,27 +2095,60 @@ b/292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = 42267119 LINUX INTEL OPENGL : WEBGLVideoTextureTest.VerifySamplerVideoWEBGLAsParameter/* = SKIP 42267119 LINUX INTEL OPENGL : WEBGLVideoTextureTest.VerifyStateManagerKnowsBindingVideoImage/* = SKIP +// Linux/Nvidia GTX 1660 failures after OS/driver upgrade to Ubuntu 22.04. +362486580 LINUX NVIDIA OPENGL : InstancingTestES31.UpdateAttribBindingByVertexAttribDivisor/* = SKIP +362486580 LINUX NVIDIA OPENGL : LineLoopIndirectTest.TwoIndirectDrawsShareIndexBuffer/* = SKIP +362486580 LINUX NVIDIA OPENGL : LineLoopIndirectTest.UByteIndexIndirectBuffer/* = SKIP +362486580 LINUX NVIDIA OPENGL : LineLoopIndirectTest.UseAsUBOThenUpdateThenUByteIndexIndirectBuffer/* = SKIP +362486580 LINUX NVIDIA OPENGL : MultiDrawIndirectTest.MultiDrawArraysIndirect/* = SKIP +362486580 LINUX NVIDIA OPENGL : MultiDrawIndirectTest.MultiDrawElementsIndirect/* = SKIP +362486580 LINUX NVIDIA VULKAN : SixteenBppTextureTest.RGBA5551Validation/* = SKIP +362486580 LINUX NVIDIA VULKAN : SixteenBppTextureTestES3.RGB5A1UploadRGB10A2/* = SKIP +362486580 LINUX NVIDIA VULKAN : FramebufferTestWithFormatFallback.R4G4B4A4_OutOfRangeStagedUpdateReformated/* = SKIP +362486580 LINUX NVIDIA VULKAN : EXTBlendFuncExtendedDrawTestES31.UseProgramPipeline/* = SKIP +362486580 LINUX NVIDIA VULKAN : EGLSurfaceTest.ResizeBeforeMakeCurrent*/* = SKIP + // OpenGL/GLES failures related to GL_EXT_clear_texture 361623543 WIN INTEL OPENGL : ClearTextureEXTTest.ClearCubeMapArray/* = SKIP 361623543 WIN INTEL OPENGL : ClearTextureEXTTest.StencilTexture/* = SKIP 361623543 WIN INTEL OPENGL : FramebufferTest_ES31.ClearTextureEXT2DMSStencil/* = SKIP 361623543 LINUX INTEL OPENGL : FramebufferTest_ES31.ClearTextureEXT2DMSStencil/* = SKIP -384967031 WIN INTEL OPENGL : ClearTextureEXTTestES31*.ClearCubeMapArray/* = SKIP -384967031 WIN INTEL OPENGL : ClearTextureEXTTestES31Unrenderable.ClearRGB9E5/* = SKIP -384967031 LINUX INTEL OPENGL : ClearTextureEXTTestES31Unrenderable.Clear3D/* = SKIP -384967031 LINUX INTEL OPENGL : ClearTextureEXTTestES31Renderable.Clear2DArray/* = SKIP - -// MSRTT D3D11 failures -40644740 D3D11 : MultisampledRenderToTextureES3Test.MultipleLevelsMultisampleMRTDraw2DColor/* = SKIP +384967031 WIN INTEL OPENGL : ClearTextureEXTTestES31*.Clear/*TEXTURE_CUBE_MAP_ARRAY = SKIP +384967031 WIN INTEL OPENGL : ClearTextureEXTTestES31Unrenderable.Clear*RGB9_E5* = SKIP +384967031 LINUX INTEL OPENGL : ClearTextureEXTTestES31Unrenderable.Clear/*GL_TEXTURE_3D = SKIP +384967031 LINUX INTEL OPENGL : ClearTextureEXTTestES31Renderable.Clear/*GL_TEXTURE_2D_ARRAY = SKIP // EGL_experimental_present_path_angle D3D11 failure 347060511 D3D11 : EGLPresentPathD3D11.ClientBufferPresentPathFast/* = SKIP // Metal backend doesn't support different sized attachments. -42261786 METAL : MultisampledRenderToTextureES3Test.MultipleLevelsMultisampleMRTDraw2DColor/* = SKIP +42261786 METAL : MSRTTES3Test.MultipleLevelsMultisampleMRTDraw2DColor/* = SKIP + +// Blit on out-of-bounds regions failures on NVIDIA, INTEL and AMD +404959030 METAL : BlitFramebufferTest.BlitWithDifferentSizesColorAttachments/* = SKIP +404959030 METAL : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404959030 METAL : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404958318 D3D11 : BlitFramebufferTest.BlitWithDifferentSizesColorAttachments/* = SKIP +404958318 D3D11 : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404958318 D3D11 : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404958319 LINUX NVIDIA OPENGL : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404958319 LINUX NVIDIA OPENGL : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404983220 LINUX NVIDIA VULKAN : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404983220 LINUX NVIDIA VULKAN : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404958319 LINUX INTEL OPENGL : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404958319 LINUX INTEL OPENGL : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404983220 LINUX INTEL VULKAN : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404983220 LINUX INTEL VULKAN : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404959032 MAC AMD OPENGL : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404959032 MAC AMD OPENGL : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404959032 MAC INTEL OPENGL : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404959032 MAC INTEL OPENGL : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404958320 WIN INTEL VULKAN : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404958320 WIN INTEL VULKAN : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP +404958320 WIN NVIDIA VULKAN : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP +404958320 WIN NVIDIA VULKAN : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP // EGLImage colorspace renderbuffer failures on NVIDIA, INTEL and ANDROID -40644776 D3D11 : ImageTest.SourceRenderbufferTargetTexture* = SKIP 40644776 D3D11 : ImageTestES3.SourceRenderbufferTargetTextureExternalESSL3* = SKIP 40644776 WIN INTEL VULKAN : ImageTest.SourceRenderbufferTargetTexture* = SKIP 40644776 WIN INTEL VULKAN : ImageTestES3.SourceRenderbufferTargetTextureExternalESSL3* = SKIP @@ -1623,10 +2164,123 @@ b/292285899 PIXEL4ORXL GLES : EGLSurfaceTest.DestroyAndRecreateWhileCurrent/* = 40644776 ANDROID PIXEL4ORXL : Texture3DCopy.UnsignedByteFormats/* = SKIP 40644776 ANDROID PIXEL4ORXL : Texture3DCopy.UnsizedFormats/* = SKIP +// Some GLES drivers don't accept BGRA as internal format for renderbuffers +42267264 GLES : FramebufferFormatsTest.Renderbuffer_BGRA_EXT/* = SKIP +42267264 GLES : FramebufferFormatsTest.Renderbuffer_BGRA8_EXT/* = SKIP + +// WebGPU does not support BGRA +42267264 WGPU : ClearTest.*BGRA* = SKIP + +// Fails on Mac & OpenGL & NVIDIA +406807990 MAC NVIDIA OPENGL : TextureUploadFormatTest_ES3.AllWithPBO/* = SKIP + +405286904 SWIFTSHADER : TextureBufferTestES31.UseAsXFBThenAsTextureBuffer/* = SKIP + +// EGLSurfaceTest.Resize* failures +42264022 IOS : EGLSurfaceTest.ResizeAfterSwap/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeAfterSwapSkipSizeQuery/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeBeforeDraw/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeBeforeDrawPostSizeQuery/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeAfterDraw/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeLargeWindow/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeInvisibleWindow/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeBeforeMakeCurrent/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeBeforeMakeCurrentPostSizeQuery/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeAndReadPixelsRobustANGLE/* = SKIP +42264022 IOS : EGLSurfaceTest.ResizeAndBlitFramebufferANGLE/* = SKIP +373659619 MAC METAL : EGLSurfaceTest.ResizeAfterSwap/* = SKIP +373659619 MAC METAL : EGLSurfaceTest.ResizeAndBlitFramebufferANGLE/* = SKIP +373659619 MAC OPENGL : EGLSurfaceTest.ResizeBeforeDrawPostSizeQuery/* = SKIP +373659619 MAC OPENGL : EGLSurfaceTest.ResizeAfterDraw/* = SKIP +373659619 MAC : EGLSurfaceTest.ResizeBeforeDraw/* = SKIP +373659619 MAC : EGLSurfaceTest.ResizeLargeWindow/* = SKIP +373659619 MAC : EGLSurfaceTest.ResizeBeforeMakeCurrent/* = SKIP +373659619 MAC : EGLSurfaceTest.ResizeBeforeMakeCurrentPostSizeQuery/* = SKIP +397848903 LINUX NVIDIA OPENGL : EGLSurfaceTest.ResizeBeforeDraw/* = SKIP +397848903 LINUX NVIDIA OPENGL : EGLSurfaceTest.ResizeBeforeDrawPostSizeQuery/* = SKIP +397848903 LINUX NVIDIA OPENGL : EGLSurfaceTest.ResizeAfterDraw/* = SKIP +397848903 LINUX NVIDIA OPENGL : EGLSurfaceTest.ResizeInvisibleWindow/* = SKIP + +406827038 SWIFTSHADER : GLSLTest_ES3.DenormFloatsToIntValues/* = SKIP +406827038 PIXEL6 VULKAN : GLSLTest_ES3.DenormFloatsToIntValues/* = SKIP + +351867710 NVIDIA VULKAN : CopyImageTestES31.CompressedToNorm16/* = SKIP +351867710 NVIDIA VULKAN : CopyImageTestES31.Norm16ToCompressed/* = SKIP + +// Pixel4's GLES driver fails new test: TransformFeedbackTest.CaptureThenUseAsUBO. +419403192 PIXEL4ORXL GLES : TransformFeedbackTest.CaptureThenUseAsUBO/* = SKIP + +454067880 D3D9 : GLSLTest.ComplicatedMultielementSwizzle1/* = SKIP +454067880 D3D11 : GLSLTest.ComplicatedMultielementSwizzle1/* = SKIP + +454067880 D3D9 : GLSLTest.ComplicatedMultielementSwizzle2/* = SKIP +454067880 D3D11 : GLSLTest.ComplicatedMultielementSwizzle2/* = SKIP +454067880 OPENGL : GLSLTest.ComplicatedMultielementSwizzle2/* = SKIP +454067880 GLES : GLSLTest.ComplicatedMultielementSwizzle2/* = SKIP + +454016926 D3D9 : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP +454016926 D3D11 : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP +454016926 OPENGL : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP +454016926 GLES : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP +454016926 VULKAN : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP +454016926 METAL : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP + +454016926 OPENGL : GLSLTest.FunctionArgumentEvalOrder/* = SKIP +454016926 GLES : GLSLTest.FunctionArgumentEvalOrder/* = SKIP +454016926 VULKAN : GLSLTest.FunctionArgumentEvalOrder/* = SKIP +454016926 METAL : GLSLTest.FunctionArgumentEvalOrder/* = SKIP + +454016926 OPENGL : GLSLTest.FunctionArgumentEvalOrderOverloaded/* = SKIP +454016926 GLES : GLSLTest.FunctionArgumentEvalOrderOverloaded/* = SKIP +454016926 VULKAN : GLSLTest.FunctionArgumentEvalOrderOverloaded/* = SKIP +454016926 METAL : GLSLTest.FunctionArgumentEvalOrderOverloaded/* = SKIP + +455800276 : DrawBaseVertexBaseInstanceTest_ES3.AllowsUserDefinedANGLEDrawID/* = SKIP +455800276 : MultiDrawEmulationTest.AllowsUserDefinedANGLEDrawID/* = SKIP + +// Translator IR failures +// Constant fold is not yet done if only the index is constant +349994211 IR : GLSLConstantFoldingTest.ArrayMixedArgumentsIndex/* = SKIP +// Function argument evaluation order is not per spec. +454016926 IR : GLSLTest.FunctionArgumentEvalOrder/* = SKIP +454016926 IR : GLSLTest.FunctionArgumentEvalOrderOverloaded/* = SKIP +454016926 IR : GLSLTest.TernaryModifiesVariableInSameStatement/* = SKIP +// Untriaged failures with MSL +349994211 IR METAL : GLSLTestLoops.ForContinueInSwitch/* = SKIP +349994211 IR METAL : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP +349994211 IR METAL : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP +// Struct generation with HLSL produces non-existing names +349994211 IR D3D11 : UniformBufferTest.BlockArrayContainingArrayOfStructs/* = SKIP +349994211 IR D3D11 : UniformBufferTest.BlockContainingArrayOfStructs/* = SKIP +349994211 IR D3D11 : UniformBufferTest.BlockContainingArrayOfStructsContainingArrays/* = SKIP +349994211 IR D3D11 : UniformBufferTest.BlockContainingNestedStructs/* = SKIP +349994211 IR D3D11 : UniformBufferTest.Std140UniformBlockInstanceWithNestedStructsContainingVec3s/* = SKIP +// The astify pass generates a temp variable to hold the result of a function call that returns a large array. +// That leads to an extra copy that makes the shader run slower and time out. +// Apparently the unnecessary copy is not optimized out by the d3d compiler. +349994211 IR D3D11 : UniformBlockWithOneLargeArrayMemberTest.MemberArrayOperations/* = SKIP +// When the IR prunes cases that do not match the constant switch expression, and there is only the `default` case left, +// the d3d compiler miscompiles the shader it seems. +349994211 IR D3D11 : GLSLTest_ES3.SwitchWithConstantExpr/* = SKIP +// The workaround in b/274859104 is not applied because the IR does not generate non-constant initializers +274859104 IR PIXEL6 VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = SKIP +// Turning short-circuit && to if/else leads to incorrect evaluation on the Pixel 4 compiler +349994211 IR PIXEL4ORXL GLES : GLSLTest.AliasingFunctionInOutParamsMultiple/* = SKIP +349994211 IR PIXEL4ORXL GLES : GLSLTest.AliasingFunctionOutParamsMultiple/* = SKIP +// Pixel 4's GLES compiler complains that gl_LastFragData's array size cannot be redefined +349994211 IR PIXEL4ORXL GLES : GLSLValidationTest.FramebufferFetchWithLastFragData/* = SKIP +// The test's alpha channel is wrong (like 0.25) even though the shader calculates that as a bool cast to float! +349994211 IR PIXEL4ORXL GLES : SampleVariablesTest.SamplePosition/* = SKIP +// Untriaged failures on Pixel 4 / GLES +349994211 IR PIXEL4ORXL GLES : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Slow tests, should appear last in this file +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 42263645 : GLSLTest.VerifyMaxVertexUniformVectors* = TIMEOUT 42263645 : GLSLTest.VerifyMaxFragmentUniformVectors* = TIMEOUT 42264781 : MultithreadingTest* = TIMEOUT - +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Please do not add expectations below this line, // so that TIMEOUT expectations above don't override more precise SKIP expectations +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/tests/angle_end2end_tests_main.cpp b/src/tests/angle_end2end_tests_main.cpp index a44ad420e16..8a58f995097 100644 --- a/src/tests/angle_end2end_tests_main.cpp +++ b/src/tests/angle_end2end_tests_main.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gtest/gtest.h" #if defined(ANGLE_HAS_RAPIDJSON) # include "test_utils/runner/TestSuite.h" @@ -41,8 +45,8 @@ int main(int argc, char **argv) if (!HasArg(argc, argv, "--list-tests") && !HasArg(argc, argv, "--gtest_list_tests") && HasArg(argc, argv, "--use-gl")) { - std::cerr << "--use-gl isn't supported by end2end tests - use *_EGL configs instead " - "(angle_test_enable_system_egl=true)\n"; + std::cerr << "--use-gl isn't supported by end2end tests - use the GN arg instead: " + "angle_test_enable_system_egl=true\n"; return EXIT_FAILURE; } diff --git a/src/tests/angle_perftests.gni b/src/tests/angle_perftests.gni index df760f2eabc..8892c063032 100644 --- a/src/tests/angle_perftests.gni +++ b/src/tests/angle_perftests.gni @@ -12,6 +12,7 @@ angle_perf_tests_sources = [ "perf_tests/DrawElementsPerf.cpp", "perf_tests/DynamicPromotionPerfTest.cpp", "perf_tests/EGLMakeCurrentPerf.cpp", + "perf_tests/FormatUploadDrawPerf.cpp", "perf_tests/FramebufferAttachmentPerfTest.cpp", "perf_tests/GenerateMipmapPerf.cpp", "perf_tests/ImagelessFramebufferPerfTest.cpp", diff --git a/src/tests/angle_system_info_tests_main.cpp b/src/tests/angle_system_info_tests_main.cpp index 124303e50b8..e543eaffa16 100644 --- a/src/tests/angle_system_info_tests_main.cpp +++ b/src/tests/angle_system_info_tests_main.cpp @@ -30,6 +30,10 @@ // ] // } +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gpu_info_util/SystemInfo.h" #include @@ -191,4 +195,4 @@ TEST(ANGLE, SystemInfo) { FAIL() << "Failed to find GPU info."; } -} \ No newline at end of file +} diff --git a/src/tests/angle_unittest_main.cpp b/src/tests/angle_unittest_main.cpp index 1356dceac33..31be8e39d1d 100644 --- a/src/tests/angle_unittest_main.cpp +++ b/src/tests/angle_unittest_main.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLSLANG/ShaderLang.h" #include "gtest/gtest.h" #include "test_utils/runner/TestSuite.h" diff --git a/src/tests/angle_unittests.gni b/src/tests/angle_unittests.gni index 127882302e8..8db133d38d8 100644 --- a/src/tests/angle_unittests.gni +++ b/src/tests/angle_unittests.gni @@ -24,6 +24,7 @@ angle_unittests_sources = [ "../common/mathutil_unittest.cpp", "../common/matrix_utils_unittest.cpp", "../common/span_unittest.cpp", + "../common/span_util_unittest.cpp", "../common/string_utils_unittest.cpp", "../common/system_utils_unittest.cpp", "../common/utilities_unittest.cpp", @@ -82,7 +83,6 @@ angle_unittests_sources = [ "preprocessor_tests/token_test.cpp", "preprocessor_tests/version_test.cpp", "test_expectations/GPUTestExpectationsParser_unittest.cpp", - "test_utils/ShaderExtensionTest.h", "test_utils/angle_test_instantiate.h", "test_utils/compiler_test.cpp", "test_utils/compiler_test.h", @@ -90,45 +90,18 @@ angle_unittests_sources = [ angle_unittests_compiler_tests_sources = [ "compiler_tests/API_test.cpp", - "compiler_tests/APPLE_clip_distance_test.cpp", - "compiler_tests/ARB_texture_rectangle_test.cpp", - "compiler_tests/AppendixALimitations_test.cpp", - "compiler_tests/AtomicCounter_test.cpp", - "compiler_tests/BufferVariables_test.cpp", "compiler_tests/CollectVariables_test.cpp", - "compiler_tests/ConstantFoldingNaN_test.cpp", - "compiler_tests/ConstantFoldingOverflow_test.cpp", - "compiler_tests/ConstantFolding_test.cpp", "compiler_tests/ConstructCompiler_test.cpp", - "compiler_tests/EXT_YUV_target_test.cpp", - "compiler_tests/EXT_blend_func_extended_test.cpp", - "compiler_tests/EXT_clip_cull_distance_test.cpp", - "compiler_tests/EXT_frag_depth_test.cpp", - "compiler_tests/EXT_shader_framebuffer_fetch_test.cpp", - "compiler_tests/EXT_shader_texture_lod_test.cpp", - "compiler_tests/EXT_shadow_samplers_test.cpp", - "compiler_tests/EmulateGLBaseVertexBaseInstance_test.cpp", - "compiler_tests/EmulateGLDrawID_test.cpp", - "compiler_tests/EmulateGLFragColorBroadcast_test.cpp", "compiler_tests/ExpressionLimit_test.cpp", - "compiler_tests/ExtensionDirective_test.cpp", "compiler_tests/FloatLex_test.cpp", - "compiler_tests/FragDepth_test.cpp", "compiler_tests/GLSLCompatibilityOutput_test.cpp", "compiler_tests/GeometryShader_test.cpp", "compiler_tests/GlFragDataNotModified_test.cpp", "compiler_tests/ImmutableString_test.cpp", - "compiler_tests/InitOutputVariables_test.cpp", - "compiler_tests/InitializeUninitializedLocals_test.cpp", "compiler_tests/IntermNode_test.cpp", - "compiler_tests/KHR_blend_equation_advanced_test.cpp", "compiler_tests/NV_draw_buffers_test.cpp", - "compiler_tests/OES_sample_variables_test.cpp", - "compiler_tests/OES_standard_derivatives_test.cpp", - "compiler_tests/OES_texture_cube_map_array_test.cpp", "compiler_tests/OVR_multiview2_test.cpp", "compiler_tests/OVR_multiview_test.cpp", - "compiler_tests/Pack_Unpack_test.cpp", "compiler_tests/Parse_test.cpp", "compiler_tests/PruneEmptyCases_test.cpp", "compiler_tests/PruneEmptyDeclarations_test.cpp", @@ -141,10 +114,8 @@ angle_unittests_compiler_tests_sources = [ "compiler_tests/RegenerateStructNames_test.cpp", "compiler_tests/RemoveUnreferencedVariables_test.cpp", "compiler_tests/SamplerMultisample_test.cpp", - "compiler_tests/SamplerVideoWEBGL_test.cpp", "compiler_tests/SeparateDeclarations_test.cpp", "compiler_tests/ShCompile_test.cpp", - "compiler_tests/ShaderImage_test.cpp", "compiler_tests/ShaderValidation_test.cpp", "compiler_tests/ShaderVariable_test.cpp", "compiler_tests/SimplifyLoopConditions_test.cpp", @@ -153,16 +124,12 @@ angle_unittests_compiler_tests_sources = [ "compiler_tests/Type_test.cpp", "compiler_tests/VariablePacker_test.cpp", "compiler_tests/WorkGroupSize_test.cpp", - "test_utils/ConstantFoldingTest.cpp", - "test_utils/ConstantFoldingTest.h", "test_utils/ShaderCompileTreeTest.cpp", "test_utils/ShaderCompileTreeTest.h", ] -angle_unittests_glsl_mac_sources = [ - "compiler_tests/RewriteDoWhile_test.cpp", - "compiler_tests/UnfoldShortCircuitAST_test.cpp", -] +angle_unittests_glsl_mac_sources = + [ "compiler_tests/UnfoldShortCircuitAST_test.cpp" ] # TODO(jmadill): should probably call this windows sources angle_unittests_hlsl_sources = [ diff --git a/src/tests/angle_unittests_utils.h b/src/tests/angle_unittests_utils.h index a8c6dd67d9b..8400776ff3a 100644 --- a/src/tests/angle_unittests_utils.h +++ b/src/tests/angle_unittests_utils.h @@ -51,7 +51,8 @@ class NullFactory : public GLImplFactory BufferImpl *createBuffer(const gl::BufferState &state) override { return nullptr; } // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data, + const gl::VertexArrayBuffers &vertexArrayBuffers) override { return nullptr; } @@ -96,7 +97,8 @@ class MockGLFactory : public GLImplFactory MOCK_METHOD1(createTexture, TextureImpl *(const gl::TextureState &)); MOCK_METHOD1(createRenderbuffer, RenderbufferImpl *(const gl::RenderbufferState &)); MOCK_METHOD1(createBuffer, BufferImpl *(const gl::BufferState &)); - MOCK_METHOD1(createVertexArray, VertexArrayImpl *(const gl::VertexArrayState &)); + MOCK_METHOD2(createVertexArray, + VertexArrayImpl *(const gl::VertexArrayState &, const gl::VertexArrayBuffers &)); MOCK_METHOD1(createQuery, QueryImpl *(gl::QueryType type)); MOCK_METHOD0(createFenceNV, FenceNVImpl *()); MOCK_METHOD0(createSync, SyncImpl *()); diff --git a/src/tests/angle_white_box_tests.gni b/src/tests/angle_white_box_tests.gni index 5f260ded09d..e742a308c26 100644 --- a/src/tests/angle_white_box_tests.gni +++ b/src/tests/angle_white_box_tests.gni @@ -4,6 +4,7 @@ angle_white_box_tests_sources = [ "egl_tests/EGLFeatureControlTest.cpp", + "gl_tests/ErrorMessages.cpp", "gl_tests/FormatPrintTest.cpp", "test_utils/ANGLETest.cpp", "test_utils/ANGLETest.h", @@ -14,7 +15,6 @@ angle_white_box_tests_win_sources = [ "gl_tests/D3D11FormatTablesTest.cpp", "gl_tests/D3D11InputLayoutCacheTest.cpp", "gl_tests/D3DTextureTest.cpp", - "gl_tests/ErrorMessages.cpp", ] angle_white_box_tests_vulkan_sources = [ "gl_tests/VulkanDescriptorSetTest.cpp", diff --git a/src/tests/capture_replay_tests.py b/src/tests/capture_replay_tests.py index 28412cc4684..42731b8415c 100755 --- a/src/tests/capture_replay_tests.py +++ b/src/tests/capture_replay_tests.py @@ -50,7 +50,7 @@ import angle_test_util PIPE_STDOUT = True -DEFAULT_OUT_DIR = "out/CaptureReplayTest" # relative to angle folder +DEFAULT_OUT_DIR = "out_CaptureReplayTest" # relative to angle folder DEFAULT_FILTER = "*/ES2_Vulkan_SwiftShader" DEFAULT_TEST_SUITE = "angle_end2end_tests" REPLAY_SAMPLE_FOLDER = "src/tests/capture_replay_tests" # relative to angle folder @@ -97,7 +97,7 @@ def winext(name, ext): return ("%s.%s" % (name, ext)) if sys.platform == "win32" else name -GN_PATH = os.path.join('third_party', 'depot_tools', winext('gn', 'bat')) +GN_PATH = os.path.join('third_party', 'depot_tools', 'gn.py') AUTONINJA_PATH = os.path.join('third_party', 'depot_tools', 'autoninja.py') @@ -105,7 +105,9 @@ def GetGnArgsStr(args, extra_gn_args=[]): gn_args = [('angle_with_capture_by_default', 'true'), ('angle_enable_vulkan_api_dump_layer', 'false'), ('angle_enable_wgpu', 'false')] + extra_gn_args - if args.use_reclient: + if args.use_siso: + gn_args.append(('use_siso', 'true')) + if args.use_remoteexec: gn_args.append(('use_remoteexec', 'true')) if not args.debug: gn_args.append(('is_debug', 'false')) @@ -288,7 +290,7 @@ def CaptureProducedRequiredFiles(all_trace_files, test_name): context_id = 0 for f in test_files: # TODO: Consolidate. http://anglebug.com/42266223 - if "_001.cpp" in f or "_001.c" in f: + if "_0001.cpp" in f or "_0001.c" in f: frame_files_count += 1 elif f.endswith(".json"): source_json_count += 1 @@ -689,7 +691,15 @@ def main(args): logging.info('Building capture tests') - subprocess.check_call([GN_PATH, 'gen', '--args=%s' % GetGnArgsStr(args), capture_build_dir]) + if args.use_siso: + for build_dir in [capture_build_dir, replay_build_dir]: + if os.path.exists(os.path.join(build_dir, '.ninja_deps')): + logging.info('Removing %s to switch from Ninja to Siso', build_dir) + shutil.rmtree(build_dir) + + subprocess.check_call( + [sys.executable, GN_PATH, 'gen', + '--args=%s' % GetGnArgsStr(args), capture_build_dir]) subprocess.check_call( [sys.executable, AUTONINJA_PATH, '-C', capture_build_dir, args.test_suite]) @@ -763,9 +773,10 @@ def main(args): extra_gn_args = [('angle_build_capture_replay_tests', 'true'), ('angle_capture_replay_test_trace_dir', '"%s"' % trace_dir), ('angle_capture_replay_composite_file_id', str(composite_file_id))] - subprocess.check_call( - [GN_PATH, 'gen', - '--args=%s' % GetGnArgsStr(args, extra_gn_args), replay_build_dir]) + subprocess.check_call([ + sys.executable, GN_PATH, 'gen', + '--args=%s' % GetGnArgsStr(args, extra_gn_args), replay_build_dir + ]) subprocess.check_call( [sys.executable, AUTONINJA_PATH, '-C', replay_build_dir, REPLAY_BINARY]) @@ -822,10 +833,12 @@ def main(args): action='store_true', help='Whether to keep the temp files and folders. Off by default') parser.add_argument( - '--use-reclient', + '--use-remoteexec', default=False, action='store_true', help='Set use_remoteexec=true in args.gn.') + parser.add_argument( + '--use-siso', default=False, action='store_true', help='Set use_siso=true in args.gn.') parser.add_argument( '--result-file', default=DEFAULT_RESULT_FILE, diff --git a/src/tests/capture_replay_tests/CaptureReplayTests.cpp b/src/tests/capture_replay_tests/CaptureReplayTests.cpp index fbe0f2f33a7..907270bc2fe 100644 --- a/src/tests/capture_replay_tests/CaptureReplayTests.cpp +++ b/src/tests/capture_replay_tests/CaptureReplayTests.cpp @@ -7,6 +7,10 @@ // Application that runs replay for testing of capture replay // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/debug.h" #include "common/system_utils.h" #include "platform/PlatformMethods.h" diff --git a/src/tests/capture_replay_tests/capture_replay_expectations.txt b/src/tests/capture_replay_tests/capture_replay_expectations.txt index 3a9a08f6f2f..6da0474a653 100644 --- a/src/tests/capture_replay_tests/capture_replay_expectations.txt +++ b/src/tests/capture_replay_tests/capture_replay_expectations.txt @@ -55,6 +55,9 @@ # Fails because of unsupported combined depth/stencil GetImage. 42263287 : DepthStencilTest.DepthOnlyEmulatedWithPacked/* = FAIL +# Provoking vertex +463966221 : ProvokingVertexTest.* = FAIL + # ES3 42264706 : BlitFramebufferTest.BlitDepthStencilPixelByPixel/* = NOT_RUN 42264706 : GLSLTest_ES3.UnsuccessfulRelinkWithBindAttribLocation/* = NOT_RUN @@ -105,6 +108,7 @@ # ES3_1 Crashed 42264706 : EGLMultiContextTest.ComputeShaderOkayWithRendering/* = SKIP_FOR_CAPTURE 42264706 : EGLMultiContextTest.TestContextDestroySimple/* = SKIP_FOR_CAPTURE +400473059 : ProgramPipelineTest31.ProgramPipelineivTest/* = SKIP_FOR_CAPTURE # ES3_1 gtest skips 42264706 : GLSLTest_ES31.InterpolateAtWithSwizzle/* = NOT_RUN @@ -170,6 +174,8 @@ 42265218 : EGLMultiContextTest.ReuseUnterminatedDisplay/* = SKIP_FOR_CAPTURE +434453466 : SimpleOperationTest.NullParameterInGetAttachedShaders/* = SKIP_FOR_CAPTURE + # No support yet for Capture/Replay of External Textures using other attribs 42266040 : ImageTest.MipLevels/* = SKIP_FOR_CAPTURE 42266040 : ImageTest.Source2DTarget2D_Colorspace/* = SKIP_FOR_CAPTURE @@ -235,6 +241,8 @@ # error: duplicate case value '1' 42264614 : EGLSyncTest.GlobalFenceSync/* = COMPILE_FAIL +433331119 : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = COMPILE_FAIL +433331119 : ValidationStateChangeTestES31.RebindVertexBufferShouldPickupBufferChange/* = COMPILE_FAIL # VVL error 42264614 LINUX : VulkanExternalImageTestES31.UninitializedOnGLImportAndStorageWrite/* = SKIP_FOR_CAPTURE @@ -248,6 +256,19 @@ 381727390 : MultisampleTexture2DTestES31.CopyMultisampleArrayImageEXT/* = SKIP_FOR_CAPTURE 381727390 : MultisampleTexture2DTestES31.CopyMultisampleArrayImageOES/* = SKIP_FOR_CAPTURE +# Crashes in gl::JoinShaderSources during replay +447613212 : GLSLTest.EmptyShader/* = SKIP_FOR_CAPTURE + +# Missing support for GL_ANGLE_translated_shader_source +454830637 : GLSLConstantFoldingTest* = SKIP_FOR_CAPTURE +454830637 : GLSLValidation*Test* = SKIP_FOR_CAPTURE +454830637 : WebGLGLSLValidation*Test* = SKIP_FOR_CAPTURE +454830637 : WebGL2GLSLValidation*Test* = SKIP_FOR_CAPTURE +454830637 : GLSLOutput*Test* = SKIP_FOR_CAPTURE # Crashes on win and linux trace bots 372059358 : MultisampleTestES3.CopyTexImage2DFromMsaaDefaultFbo/* = SKIP_FOR_CAPTURE + +# Test failure on win and linux trace +400584608 : BlitFramebufferTest.BlitLargeColorSmallDepthAttachments/* = SKIP_FOR_CAPTURE +400584608 : BlitFramebufferTest.BlitSmallColorLargeDepthAttachments/* = SKIP_FOR_CAPTURE diff --git a/src/tests/capture_tests/CapturedTestCL.cpp b/src/tests/capture_tests/CapturedTestCL.cpp index 86359a1bed6..784eb82d862 100644 --- a/src/tests/capture_tests/CapturedTestCL.cpp +++ b/src/tests/capture_tests/CapturedTestCL.cpp @@ -75,10 +75,6 @@ class MultiFrameCL { int gid = get_global_id(0); output[gid] = gid; - if (gid == 0) - { - printf("Frame 4!\n"); - } } __kernel void frame5(__global float *output) diff --git a/src/tests/capture_tests/capture_tests.py b/src/tests/capture_tests/capture_tests.py index ff939ddc4ee..f4430a3ddaa 100755 --- a/src/tests/capture_tests/capture_tests.py +++ b/src/tests/capture_tests/capture_tests.py @@ -12,6 +12,7 @@ import logging import os import pathlib +import re import shutil import subprocess import sys @@ -76,7 +77,7 @@ def diff_files(path, expected_path): return True -def run_test(test_name, overwrite_expected): +def run_test(args, test_name, overwrite_expected): with temporary_dir() as temp_dir: cmd = [angle_test_util.ExecutablePathInCurrentDir('angle_end2end_tests')] if angle_test_util.IsAndroid(): @@ -97,13 +98,20 @@ def run_test(test_name, overwrite_expected): expected_dir = os.path.join(SCRIPT_DIR, 'expected') expected_files = sorted(fn for fn in os.listdir(expected_dir) if not fn.startswith('.')) + if args.skip_cl: + filtered_files = [ + file for file in expected_files if not re.search('CapturedTestCL', file) + ] + else: + filtered_files = expected_files + if overwrite_expected: - for f in expected_files: + for f in filtered_files: os.remove(os.path.join(expected_dir, f)) shutil.copytree(temp_dir, expected_dir, dirs_exist_ok=True) return True - if files != expected_files: + if files != filtered_files: logging.error( 'Checks failed. Capture produced a different set of files: %s\nDiff:\n%s\n', files, '\n'.join(difflib.unified_diff(expected_files, files))) @@ -123,6 +131,7 @@ def main(): parser.add_argument('--log', help='Logging level.', default='info') parser.add_argument( '--overwrite-expected', help='Overwrite contents of expected/', action='store_true') + parser.add_argument('--skip-cl', help='Skip CL tests', action='store_true') args, extra_flags = parser.parse_known_args() logging.basicConfig(level=args.log.upper()) @@ -132,7 +141,7 @@ def main(): test_name = 'CapturedTest*/ES3_Vulkan' had_error = False try: - if not run_test(test_name, args.overwrite_expected): + if not run_test(args, test_name, args.overwrite_expected): had_error = True logging.error( 'Found capture diffs. If diffs are expected, build angle_end2end_tests and run ' diff --git a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.cpp b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.cpp index 280bc5b5c9c..b2eca0e3d80 100644 --- a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.cpp +++ b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.cpp @@ -2,6 +2,8 @@ #include "trace_fixture_cl.h" const char clGetExtensionFunctionAddress_func_name_0[] = { "clIcdGetPlatformIDsKHR" }; +const char clGetExtensionFunctionAddress_func_name_1[] = { "clEnqueueAcquireExternalMemObjectsKHR" }; +const char clGetExtensionFunctionAddress_func_name_2[] = { "clEnqueueReleaseExternalMemObjectsKHR" }; const char * clCreateProgramWithSource_strings_0[] = { "\n" " __kernel void frame1(__global float *output)\n" @@ -26,10 +28,6 @@ const char * clCreateProgramWithSource_strings_0[] = { " {\n" " int gid = get_global_id(0);\n" " output[gid] = gid;\n" -" if (gid == 0)\n" -" {\n" -" printf(\"Frame 4!\\n\");\n" -" }\n" " }\n" "\n" " __kernel void frame5(__global float *output)\n" @@ -58,7 +56,8 @@ void InitReplay(void) // clKernelsMapSize = 16 // clSamplerMapSize = 0 // clVoidMapSize = 0 - InitializeReplayCL("CapturedTestCL_MultiFrameCL_ES3_Vulkan.angledata", 0, 512, 8, 8, 8, 8, 8, 0, 8, 16, 0, 0); + InitializeReplayCL2("CapturedTestCL_MultiFrameCL_ES3_Vulkan.angledata", 0, 512, 8, 8, 8, 8, 8, 0, 8, 16, 0, 0); + InitializeBinaryDataLoader(); } // Public Functions @@ -87,6 +86,8 @@ void ReplayFrame(uint32_t frameIndex) void SetupFirstFrame() { clIcdGetPlatformIDsKHR = (clIcdGetPlatformIDsKHR_fn)clGetExtensionFunctionAddress(clGetExtensionFunctionAddress_func_name_0); + clEnqueueAcquireExternalMemObjectsKHR = (clEnqueueAcquireExternalMemObjectsKHR_fn)clGetExtensionFunctionAddress(clGetExtensionFunctionAddress_func_name_1); + clEnqueueReleaseExternalMemObjectsKHR = (clEnqueueReleaseExternalMemObjectsKHR_fn)clGetExtensionFunctionAddress(clGetExtensionFunctionAddress_func_name_2); clGetPlatformIDs(1, clPlatformsMap, NULL); temporaryDevicesList.clear(); temporaryDevicesList.resize(1); @@ -96,11 +97,11 @@ void SetupFirstFrame() clContextsMap[0] = clCreateContext(NULL, 1, temporaryDevicesList.data(), NULL, 0, NULL); clCommandQueuesMap[0] = clCreateCommandQueue(clContextsMap[0], clDevicesMap[0], 0, NULL); clProgramsMap[0] = clCreateProgramWithSource(clContextsMap[0], 1, clCreateProgramWithSource_strings_0, NULL, NULL); - clBuildProgram(clProgramsMap[0], 0, NULL, 0, NULL, 0); + clBuildProgram(clProgramsMap[0], 0, NULL, NULL, NULL, 0); clMemMap[0] = clCreateBuffer(clContextsMap[0], 1, 512, 0, NULL); clKernelsMap[0] = clCreateKernel(clProgramsMap[0], clCreateKernel_kernel_name_4, NULL); clSetKernelArg(clKernelsMap[0], 0, 8, (const void *)&clMemMap[0]); - clEnqueueWriteBuffer(clCommandQueuesMap[0], clMemMap[0], 1, 0, 512, (const GLubyte *)&gBinaryData[64], 0, NULL, NULL); + clEnqueueWriteBuffer(clCommandQueuesMap[0], clMemMap[0], 1, 0, 512, (const GLubyte *)GetBinaryData(64), 0, NULL, NULL); } void ResetReplay(void) diff --git a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.h b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.h index b2ac0ff1b94..b5fef017625 100644 --- a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.h +++ b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.h @@ -19,3 +19,5 @@ void InitReplay(void); extern const char * clCreateProgramWithSource_strings_0[]; static clIcdGetPlatformIDsKHR_fn clIcdGetPlatformIDsKHR; +static clEnqueueAcquireExternalMemObjectsKHR_fn clEnqueueAcquireExternalMemObjectsKHR; +static clEnqueueReleaseExternalMemObjectsKHR_fn clEnqueueReleaseExternalMemObjectsKHR; diff --git a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.json b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.json index 17721d6201c..614963e11c4 100644 --- a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.json +++ b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan.json @@ -1,14 +1,21 @@ { "TraceMetadata": { - "CaptureRevision": 24837, + "CaptureRevision": 26132, "FrameEnd": 5, "FrameStart": 2, "IsBinaryDataCompressed": false, "IsOpenCL": true }, + "BinaryMetadata": { + "BlockCount": 1, + "BlockSize": "268435456", + "IndexOffset": "0", + "ResidentSize": "2147483648", + "Version": 1 + }, "TraceFiles": [ "CapturedTestCL_MultiFrameCL_ES3_Vulkan.cpp", "CapturedTestCL_MultiFrameCL_ES3_Vulkan.h", - "CapturedTestCL_MultiFrameCL_ES3_Vulkan_001.cpp" + "CapturedTestCL_MultiFrameCL_ES3_Vulkan_0001.cpp" ] } \ No newline at end of file diff --git a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_001.cpp b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_0001.cpp similarity index 90% rename from src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_001.cpp rename to src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_0001.cpp index 0e1c316b354..286bdfacb75 100644 --- a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_001.cpp +++ b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_0001.cpp @@ -19,7 +19,7 @@ void ReplayFrame2(void) clMemMap[0] = clCreateBuffer(clContextsMap[0], 1, 512, 0, NULL); clKernelsMap[1] = clCreateKernel(clProgramsMap[0], clCreateKernel_kernel_name_0, NULL); clSetKernelArg(clKernelsMap[1], 0, 8, (const void *)&clMemMap[0]); - clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)&gBinaryData[0], NULL, 0, NULL, NULL); + clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)GetBinaryData(0), NULL, 0, NULL, NULL); } void ReplayFrame3(void) @@ -30,7 +30,7 @@ void ReplayFrame3(void) clMemMap[0] = clCreateBuffer(clContextsMap[0], 1, 512, 0, NULL); clKernelsMap[1] = clCreateKernel(clProgramsMap[0], clCreateKernel_kernel_name_1, NULL); clSetKernelArg(clKernelsMap[1], 0, 8, (const void *)&clMemMap[0]); - clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)&gBinaryData[16], NULL, 0, NULL, NULL); + clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)GetBinaryData(16), NULL, 0, NULL, NULL); } void ReplayFrame4(void) @@ -41,7 +41,7 @@ void ReplayFrame4(void) clMemMap[0] = clCreateBuffer(clContextsMap[0], 1, 512, 0, NULL); clKernelsMap[1] = clCreateKernel(clProgramsMap[0], clCreateKernel_kernel_name_2, NULL); clSetKernelArg(clKernelsMap[1], 0, 8, (const void *)&clMemMap[0]); - clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)&gBinaryData[32], NULL, 0, NULL, NULL); + clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)GetBinaryData(32), NULL, 0, NULL, NULL); } void ReplayFrame5(void) @@ -52,7 +52,7 @@ void ReplayFrame5(void) clMemMap[0] = clCreateBuffer(clContextsMap[0], 1, 512, 0, NULL); clKernelsMap[1] = clCreateKernel(clProgramsMap[0], clCreateKernel_kernel_name_3, NULL); clSetKernelArg(clKernelsMap[1], 0, 8, (const void *)&clMemMap[0]); - clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)&gBinaryData[48], NULL, 0, NULL, NULL); + clEnqueueNDRangeKernel(clCommandQueuesMap[0], clKernelsMap[1], 1, NULL, (const size_t *)GetBinaryData(48), NULL, 0, NULL, NULL); } // Public Functions diff --git a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_OpenCL_info.json b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_OpenCL_info.json index 93806e2278a..29e0b14630f 100644 --- a/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_OpenCL_info.json +++ b/src/tests/capture_tests/expected/CapturedTestCL_MultiFrameCL_ES3_Vulkan_OpenCL_info.json @@ -1,37 +1,37 @@ { "clGetProgramBuildInfo": { "CL_PROGRAM_BUILD_STATUS": 0, - "device": "0x5652b4c49440", - "program": "0x5652b5054db0" + "device": "0x5e89bfa44800", + "program": "0x5e89c00ef340" } }, { "clGetMemObjectInfo": { "CL_MEM_SIZE": 512, - "memObj": "0x5652b50efdd0" + "memObj": "0x5e89bf6d14c0" } }, { "clGetMemObjectInfo": { "CL_MEM_SIZE": 512, - "memObj": "0x5652b50efdd0" + "memObj": "0x5e89bf6d14c0" } }, { "clGetMemObjectInfo": { "CL_MEM_SIZE": 512, - "memObj": "0x5652b50efdd0" + "memObj": "0x5e89bf6d14c0" } }, { "clGetMemObjectInfo": { "CL_MEM_SIZE": 512, - "memObj": "0x5652b50efdd0" + "memObj": "0x5e89bf6d14c0" } }, { "clGetMemObjectInfo": { "CL_MEM_SIZE": 512, - "memObj": "0x5652b50efdd0" + "memObj": "0x5e89bf6d14c0" } }, diff --git a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.angledata b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.angledata index cf1f3677996..fee26d48617 100644 Binary files a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.angledata and b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.angledata differ diff --git a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.cpp b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.cpp index 19497cf0e56..0a1c6970294 100644 --- a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.cpp +++ b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.cpp @@ -29,7 +29,8 @@ void InitReplay(void) // maxTransformFeedback = 0 // maxVertexArray = 0 // maxegl_Sync = 0 - InitializeReplay4("CapturedTest_ActiveTextures_ES3_Vulkan.angledata", 72, 276, 0, 3, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 3, 0, 0, 0); + InitializeReplay5("CapturedTest_ActiveTextures_ES3_Vulkan.angledata", 72, 276, 0, 3, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 3, 0, 0, 0); + InitializeBinaryDataLoader(); } // Public Functions diff --git a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.json b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.json index 14f3690ea55..d5d933b846c 100644 --- a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.json +++ b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan.json @@ -1,7 +1,7 @@ { "TraceMetadata": { "AreClientArraysEnabled": true, - "CaptureRevision": 24515, + "CaptureRevision": 26132, "ConfigAlphaBits": 8, "ConfigBlueBits": 8, "ConfigDepthBits": 24, @@ -22,10 +22,17 @@ "IsRobustResourceInitEnabled": false, "IsWebGLCompatibilityEnabled": false }, + "BinaryMetadata": { + "BlockCount": 1, + "BlockSize": "268435456", + "IndexOffset": "0", + "ResidentSize": "2147483648", + "Version": 1 + }, "TraceFiles": [ "CapturedTest_ActiveTextures_ES3_Vulkan.cpp", "CapturedTest_ActiveTextures_ES3_Vulkan.h", - "CapturedTest_ActiveTextures_ES3_Vulkan_001.cpp", + "CapturedTest_ActiveTextures_ES3_Vulkan_0001.cpp", "CapturedTest_ActiveTextures_ES3_Vulkan_shared.cpp" ], "WindowSurfaceContextID": 3 diff --git a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_001.cpp b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_0001.cpp similarity index 90% rename from src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_001.cpp rename to src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_0001.cpp index 92a22a7649a..247985dce78 100644 --- a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_001.cpp +++ b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_0001.cpp @@ -6,10 +6,11 @@ void SetupReplayContext3(void) { eglMakeCurrent(gEGLDisplay, gSurfaceMap2[0], gSurfaceMap2[0], gContextMap2[3]); + UpdateCurrentContext(3); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, gTextureMap[2]); glUseProgram(gShaderProgramMap[1]); - UpdateCurrentProgram(1); + UpdateCurrentProgramPerContext(1); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, gTransformFeedbackMap[0]); glViewport(0, 0, 128, 128); glScissor(0, 0, 128, 128); @@ -25,7 +26,7 @@ void ReplayFrame1(void) glGetAttribLocation(gShaderProgramMap[1], "a_position"); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, gClientArrays[0]); glEnableVertexAttribArray(0); - UpdateClientArrayPointer(0, (const GLubyte *)&gBinaryData[0], 72); + UpdateClientArrayPointer(0, (const GLubyte *)GetBinaryData(0), 72); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); @@ -41,7 +42,7 @@ void ReplayFrame1(void) glGetAttribLocation(gShaderProgramMap[1], "a_position"); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, gClientArrays[0]); glEnableVertexAttribArray(0); - UpdateClientArrayPointer(0, (const GLubyte *)&gBinaryData[80], 72); + UpdateClientArrayPointer(0, (const GLubyte *)GetBinaryData(80), 72); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); @@ -50,7 +51,7 @@ void ReplayFrame1(void) glGetError(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gTextureMap[2]); - glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[160]); + glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(160)); } void ReplayFrame2(void) @@ -69,7 +70,7 @@ void ResetReplayContextShared(void) glBindTexture(GL_TEXTURE_2D, gTextureMap[2]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); - glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[224]); + glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(224)); } void ResetReplayContext3(void) diff --git a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_shared.cpp b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_shared.cpp index a0c937c2305..9ad4e6a34d6 100644 --- a/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_shared.cpp +++ b/src/tests/capture_tests/expected/CapturedTest_ActiveTextures_ES3_Vulkan_shared.cpp @@ -32,20 +32,20 @@ void SetupReplayContextShared(void) glBindTexture(GL_TEXTURE_2D, gTextureMap[1]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); - glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[288]); + glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(288)); glGenTextures(1, (GLuint *)gReadBuffer); UpdateTextureID(2, 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gTextureMap[2]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); - glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[352]); + glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(352)); glGenTextures(1, (GLuint *)gReadBuffer); UpdateTextureID(3, 0); glBindTexture(GL_TEXTURE_2D, gTextureMap[3]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); - glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[416]); + glTexImage2D(GL_TEXTURE_2D, 0, 6408, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(416)); CreateProgram(1); CreateShader(GL_VERTEX_SHADER, 4); glShaderSource(gShaderProgramMap[4], 1, glShaderSource_string_0, 0); @@ -61,9 +61,9 @@ void SetupReplayContextShared(void) UpdateUniformLocation(1, "s_texture1", 0, 1); UpdateUniformLocation(1, "s_texture2", 1, 1); glUseProgram(gShaderProgramMap[1]); - UpdateCurrentProgram(1); - glUniform1iv(gUniformLocations[gCurrentProgram][0], 1, (const GLint *)&gBinaryData[480]); - glUniform1iv(gUniformLocations[gCurrentProgram][1], 1, (const GLint *)&gBinaryData[496]); + UpdateCurrentProgramPerContext(1); + glUniform1iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][0], 1, (const GLint *)GetBinaryData(480)); + glUniform1iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][1], 1, (const GLint *)GetBinaryData(496)); glDeleteShader(gShaderProgramMap[4]); glDeleteShader(gShaderProgramMap[5]); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); diff --git a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.angledata b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.angledata index 88493659a7f..cc7b5e8a308 100644 Binary files a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.angledata and b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.angledata differ diff --git a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.cpp b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.cpp index 026e3314f7c..2213c9ea111 100644 --- a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.cpp +++ b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.cpp @@ -29,7 +29,8 @@ void InitReplay(void) // maxTransformFeedback = 0 // maxVertexArray = 1 // maxegl_Sync = 0 - InitializeReplay4("CapturedTest_MultiFrame_ES3_Vulkan.angledata", 72, 32, 1, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, 3, 0, 1, 0); + InitializeReplay5("CapturedTest_MultiFrame_ES3_Vulkan.angledata", 72, 32, 1, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, 3, 0, 1, 0); + InitializeBinaryDataLoader(); } // Public Functions diff --git a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.json b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.json index 0436284c43d..04c35a3e46f 100644 --- a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.json +++ b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan.json @@ -1,7 +1,7 @@ { "TraceMetadata": { "AreClientArraysEnabled": true, - "CaptureRevision": 24515, + "CaptureRevision": 26132, "ConfigAlphaBits": 8, "ConfigBlueBits": 8, "ConfigDepthBits": 24, @@ -22,10 +22,17 @@ "IsRobustResourceInitEnabled": false, "IsWebGLCompatibilityEnabled": false }, + "BinaryMetadata": { + "BlockCount": 1, + "BlockSize": "268435456", + "IndexOffset": "0", + "ResidentSize": "2147483648", + "Version": 1 + }, "TraceFiles": [ "CapturedTest_MultiFrame_ES3_Vulkan.cpp", "CapturedTest_MultiFrame_ES3_Vulkan.h", - "CapturedTest_MultiFrame_ES3_Vulkan_001.cpp", + "CapturedTest_MultiFrame_ES3_Vulkan_0001.cpp", "CapturedTest_MultiFrame_ES3_Vulkan_shared.cpp" ], "WindowSurfaceContextID": 1 diff --git a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_001.cpp b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_0001.cpp similarity index 85% rename from src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_001.cpp rename to src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_0001.cpp index 04b2e30707b..22e332f8c17 100644 --- a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_001.cpp +++ b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_0001.cpp @@ -40,8 +40,9 @@ const char *const glShaderSource_string_3[] = { void SetupReplayContext1(void) { eglMakeCurrent(gEGLDisplay, gSurfaceMap2[0], gSurfaceMap2[0], gContextMap2[1]); + UpdateCurrentContext(1); glUseProgram(gShaderProgramMap[0]); - UpdateCurrentProgram(0); + UpdateCurrentProgramPerContext(0); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, gTransformFeedbackMap[0]); glViewport(0, 0, 128, 128); glScissor(0, 0, 128, 128); @@ -56,15 +57,15 @@ void ReplayFrame1(void) glGetError(); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(gShaderProgramMap[8]); - UpdateCurrentProgram(8); + UpdateCurrentProgramPerContext(8); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, gClientArrays[0]); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, gClientArrays[1]); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); - glUniform1i(gUniformLocations[gCurrentProgram][0], 0); - UpdateClientArrayPointer(0, (const GLubyte *)&gBinaryData[0], 72); - UpdateClientArrayPointer(1, (const GLubyte *)&gBinaryData[80], 68); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLubyte *)&gBinaryData[160]); + glUniform1i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][0], 0); + UpdateClientArrayPointer(0, (const GLubyte *)GetBinaryData(0), 72); + UpdateClientArrayPointer(1, (const GLubyte *)GetBinaryData(80), 68); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLubyte *)GetBinaryData(160)); glReadPixels(20, 20, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)gReadBuffer); glGetError(); UpdateResourceIDBuffer(0, gVertexArrayMap[0]); @@ -79,10 +80,10 @@ void ReplayFrame2(void) CreateProgram(11); CreateShader(GL_VERTEX_SHADER, 12); CreateShader(GL_FRAGMENT_SHADER, 13); - glShaderSource(gShaderProgramMap[12], 1, glShaderSource_string_0, (const GLint *)&gBinaryData[176]); + glShaderSource(gShaderProgramMap[12], 1, glShaderSource_string_0, (const GLint *)GetBinaryData(176)); glCompileShader(gShaderProgramMap[12]); glAttachShader(gShaderProgramMap[11], gShaderProgramMap[12]); - glShaderSource(gShaderProgramMap[13], 1, glShaderSource_string_1, (const GLint *)&gBinaryData[192]); + glShaderSource(gShaderProgramMap[13], 1, glShaderSource_string_1, (const GLint *)GetBinaryData(192)); glCompileShader(gShaderProgramMap[13]); glAttachShader(gShaderProgramMap[11], gShaderProgramMap[13]); glLinkProgram(gShaderProgramMap[11]); @@ -95,20 +96,20 @@ void ReplayFrame2(void) UpdateTextureID(3, 0); glBindTexture(GL_TEXTURE_2D, gTextureMap[3]); glGetError(); - glTexImage2D(GL_TEXTURE_2D, 0, 6407, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[208]); + glTexImage2D(GL_TEXTURE_2D, 0, 6407, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(208)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(gShaderProgramMap[11]); - UpdateCurrentProgram(11); + UpdateCurrentProgramPerContext(11); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, gClientArrays[0]); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, gClientArrays[1]); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); - glUniform1i(gUniformLocations[gCurrentProgram][0], 0); - UpdateClientArrayPointer(0, (const GLubyte *)&gBinaryData[224], 72); - UpdateClientArrayPointer(1, (const GLubyte *)&gBinaryData[304], 68); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLubyte *)&gBinaryData[384]); + glUniform1i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][0], 0); + UpdateClientArrayPointer(0, (const GLubyte *)GetBinaryData(224), 72); + UpdateClientArrayPointer(1, (const GLubyte *)GetBinaryData(304), 68); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLubyte *)GetBinaryData(384)); glReadPixels(108, 108, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)gReadBuffer); glGetError(); UpdateResourceIDBuffer(0, gTextureMap[3]); @@ -131,11 +132,11 @@ void ReplayFrame3(void) glBindBuffer(GL_ARRAY_BUFFER, gBufferMap[1]); CreateProgram(14); CreateShader(GL_VERTEX_SHADER, 15); - glShaderSource(gShaderProgramMap[15], 1, glShaderSource_string_2, (const GLint *)&gBinaryData[400]); + glShaderSource(gShaderProgramMap[15], 1, glShaderSource_string_2, (const GLint *)GetBinaryData(400)); glCompileShader(gShaderProgramMap[15]); glGetShaderiv(gShaderProgramMap[15], GL_COMPILE_STATUS, (GLint *)gReadBuffer); CreateShader(GL_FRAGMENT_SHADER, 16); - glShaderSource(gShaderProgramMap[16], 1, glShaderSource_string_3, (const GLint *)&gBinaryData[416]); + glShaderSource(gShaderProgramMap[16], 1, glShaderSource_string_3, (const GLint *)GetBinaryData(416)); glCompileShader(gShaderProgramMap[16]); glGetShaderiv(gShaderProgramMap[16], GL_COMPILE_STATUS, (GLint *)gReadBuffer); glAttachShader(gShaderProgramMap[14], gShaderProgramMap[15]); @@ -150,7 +151,7 @@ void ReplayFrame3(void) glGetError(); glGetProgramiv(gShaderProgramMap[14], GL_LINK_STATUS, (GLint *)gReadBuffer); glUseProgram(gShaderProgramMap[14]); - UpdateCurrentProgram(14); + UpdateCurrentProgramPerContext(14); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0); glDrawArrays(GL_TRIANGLES, 0, 3); @@ -186,20 +187,20 @@ void ReplayFrame4(void) UpdateTextureID(3, 0); glBindTexture(GL_TEXTURE_2D, gTextureMap[3]); glGetError(); - glTexImage2D(GL_TEXTURE_2D, 0, 6407, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[432]); + glTexImage2D(GL_TEXTURE_2D, 0, 6407, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(432)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(gShaderProgramMap[5]); - UpdateCurrentProgram(5); + UpdateCurrentProgramPerContext(5); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, gClientArrays[0]); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, gClientArrays[1]); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); - glUniform1i(gUniformLocations[gCurrentProgram][0], 0); - UpdateClientArrayPointer(0, (const GLubyte *)&gBinaryData[448], 72); - UpdateClientArrayPointer(1, (const GLubyte *)&gBinaryData[528], 68); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLubyte *)&gBinaryData[608]); + glUniform1i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][0], 0); + UpdateClientArrayPointer(0, (const GLubyte *)GetBinaryData(448), 72); + UpdateClientArrayPointer(1, (const GLubyte *)GetBinaryData(528), 68); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLubyte *)GetBinaryData(608)); glReadPixels(108, 108, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)gReadBuffer); glGetError(); // Skipping invalid call to glBindTexture with error: GL_INVALID_ENUM; @@ -233,7 +234,7 @@ void ResetReplay(void) // Reset main context state glUseProgram(gShaderProgramMap[0]); - UpdateCurrentProgram(0); + UpdateCurrentProgramPerContext(0); glBindBuffer(GL_ARRAY_BUFFER, gBufferMap[0]); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gBufferMap[0]); glBindTexture(GL_TEXTURE_2D, gTextureMap[2]); diff --git a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_shared.cpp b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_shared.cpp index 57e666241b5..f60342f1179 100644 --- a/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_shared.cpp +++ b/src/tests/capture_tests/expected/CapturedTest_MultiFrame_ES3_Vulkan_shared.cpp @@ -28,7 +28,7 @@ void SetupReplayContextShared(void) glBindTexture(GL_TEXTURE_2D, gTextureMap[2]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9728); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9728); - glTexImage2D(GL_TEXTURE_2D, 0, 6407, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, (const GLubyte *)&gBinaryData[624]); + glTexImage2D(GL_TEXTURE_2D, 0, 6407, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, (const GLubyte *)GetBinaryData(624)); CreateProgram(5); CreateProgram(6); CreateProgram(8); @@ -45,8 +45,8 @@ void SetupReplayContextShared(void) glLinkProgram(gShaderProgramMap[8]); UpdateUniformLocation(8, "s_texture", 0, 1); glUseProgram(gShaderProgramMap[8]); - UpdateCurrentProgram(8); - glUniform1iv(gUniformLocations[gCurrentProgram][0], 1, (const GLint *)&gBinaryData[640]); + UpdateCurrentProgramPerContext(8); + glUniform1iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][0], 1, (const GLint *)GetBinaryData(640)); glDeleteShader(gShaderProgramMap[11]); glDeleteShader(gShaderProgramMap[12]); CreateShader(GL_FRAGMENT_SHADER, 2); @@ -78,8 +78,8 @@ void SetupReplayContextSharedInactive(void) glLinkProgram(gShaderProgramMap[3]); UpdateUniformLocation(3, "s_texture", 0, 1); glUseProgram(gShaderProgramMap[3]); - UpdateCurrentProgram(3); - glUniform1iv(gUniformLocations[gCurrentProgram][0], 1, (const GLint *)&gBinaryData[656]); + UpdateCurrentProgramPerContext(3); + glUniform1iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]][0], 1, (const GLint *)GetBinaryData(656)); glDeleteShader(gShaderProgramMap[11]); glDeleteShader(gShaderProgramMap[12]); CreateShader(GL_VERTEX_SHADER, 1); diff --git a/src/tests/cl_support/openclcts_expectations.txt b/src/tests/cl_support/openclcts_expectations.txt index fc2cfd1fde7..e748bec85dd 100644 --- a/src/tests/cl_support/openclcts_expectations.txt +++ b/src/tests/cl_support/openclcts_expectations.txt @@ -9,4 +9,8 @@ 42267085 LINUX NVIDIA VULKAN : non_uniform_work_group.non_uniform_1d_basic = FAIL 42267085 LINUX NVIDIA VULKAN : non_uniform_work_group.non_uniform_other_basic = FAIL +6831861 LINUX NVIDIA VULKAN : non_uniform_work_group.non_uniform_2d_atomics = FAIL +6831861 LINUX NVIDIA VULKAN : non_uniform_work_group.non_uniform_3d_barriers = FAIL + +399969262 LINUX NVIDIA VULKAN : basic.local_kernel_def = SKIP diff --git a/src/tests/cl_support/openclcts_mustpass.txt b/src/tests/cl_support/openclcts_mustpass.txt index c4c772143ea..a5605762202 100644 --- a/src/tests/cl_support/openclcts_mustpass.txt +++ b/src/tests/cl_support/openclcts_mustpass.txt @@ -68,6 +68,7 @@ api.queue_properties api.sub_group_dispatch api.consistency_device_enqueue api.get_buffer_info +api.clone_kernel compiler.load_program_source compiler.load_multistring_source compiler.load_null_terminated_partial_multi_line_source @@ -141,4 +142,4 @@ non_uniform_work_group.non_uniform_1d_basic non_uniform_work_group.non_uniform_2d_atomics non_uniform_work_group.non_uniform_3d_barriers non_uniform_work_group.non_uniform_other_basic -bruteforce.-w4 log2 modf mad +bruteforce.-w4 -d log2 modf mad diff --git a/src/tests/compiler_tests/API_test.cpp b/src/tests/compiler_tests/API_test.cpp index 0fb809897d3..a29891f7c99 100644 --- a/src/tests/compiler_tests/API_test.cpp +++ b/src/tests/compiler_tests/API_test.cpp @@ -7,6 +7,10 @@ // Some tests for the compiler API. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLSLANG/ShaderLang.h" #include "angle_gl.h" #include "gtest/gtest.h" diff --git a/src/tests/compiler_tests/APPLE_clip_distance_test.cpp b/src/tests/compiler_tests/APPLE_clip_distance_test.cpp deleted file mode 100644 index 629bea83bfc..00000000000 --- a/src/tests/compiler_tests/APPLE_clip_distance_test.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright 2020 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. -// -// APPLE_clip_distance_test.cpp: -// Test for APPLE_clip_distance -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -namespace -{ -const char EXTPragma[] = "#extension GL_APPLE_clip_distance : require\n"; - -// Shader using gl_ClipDistance -const char ESSL100_APPLEClipDistanceShader1[] = - R"( - uniform vec4 uPlane; - - attribute vec4 aPosition; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[1] = dot(aPosition, uPlane); - })"; - -// Shader redeclares gl_ClipDistance -const char ESSL100_APPLEClipDistanceShader2[] = - R"( - uniform vec4 uPlane; - - attribute vec4 aPosition; - - varying highp float gl_ClipDistance[4]; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); - gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); - })"; - -// ESSL 3.00 Shader using gl_ClipDistance -const char ESSL300_APPLEClipDistanceShader1[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[1] = dot(aPosition, uPlane); - })"; - -// ESSL 3.00 Shader redeclares gl_ClipDistance -const char ESSL300_APPLEClipDistanceShader2[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - out highp float gl_ClipDistance[4]; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); - gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); - })"; - -class APPLEClipDistanceTest : public sh::ShaderExtensionTest -{ - public: - void InitializeCompiler() { InitializeCompiler(SH_GLSL_130_OUTPUT); } - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - DestroyCompiler(); - - mCompiler = sh::ConstructCompiler(GL_VERTEX_SHADER, testing::get<0>(GetParam()), - shaderOutputType, &mResources); - ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; - } - - testing::AssertionResult TestShaderCompile(const char *pragma) - { - const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma, - testing::get<2>(GetParam())}; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - - bool success = sh::Compile(mCompiler, shaderStrings, 3, compileOptions); - if (success) - { - return ::testing::AssertionSuccess() << "Compilation success"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); - } -}; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(APPLEClipDistanceTest, CompileFailsWithoutExtension) -{ - mResources.APPLE_clip_distance = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(APPLEClipDistanceTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.APPLE_clip_distance = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(APPLEClipDistanceTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.APPLE_clip_distance = 1; - mResources.MaxClipDistances = 8; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); -} - -#if defined(ANGLE_ENABLE_VULKAN) -// With extension flag and extension directive, compiling using TranslatorVulkan succeeds. -TEST_P(APPLEClipDistanceTest, CompileSucceedsVulkan) -{ - mResources.APPLE_clip_distance = 1; - mResources.MaxClipDistances = 8; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); -} - -// Test that the SPIR-V gen path can compile a shader when this extension is not supported. -TEST_P(APPLEClipDistanceTest, CompileSucceedsWithoutExtSupportVulkan) -{ - mResources.APPLE_clip_distance = 0; - mResources.MaxClipDistances = 0; - mResources.MaxCullDistances = 0; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - - constexpr char kNoClipCull[] = R"( - void main() - { - gl_Position = vec4(0); - })"; - const char *shaderStrings[] = {kNoClipCull}; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - - bool success = sh::Compile(mCompiler, shaderStrings, 1, compileOptions); - if (success) - { - ::testing::AssertionSuccess() << "Compilation success"; - } - else - { - ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); - } - - EXPECT_TRUE(success); -} -#endif - -#if defined(ANGLE_ENABLE_METAL) -// With extension flag and extension directive, compiling using TranslatorMSL succeeds. -TEST_P(APPLEClipDistanceTest, CompileSucceedsMetal) -{ - mResources.APPLE_clip_distance = 1; - mResources.MaxClipDistances = 8; - - InitializeCompiler(SH_MSL_METAL_OUTPUT); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); -} -#endif - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - APPLEClipDistanceTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_APPLEClipDistanceShader1, - ESSL100_APPLEClipDistanceShader2))); - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - APPLEClipDistanceTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_APPLEClipDistanceShader1, - ESSL300_APPLEClipDistanceShader2))); - -} // anonymous namespace diff --git a/src/tests/compiler_tests/ARB_texture_rectangle_test.cpp b/src/tests/compiler_tests/ARB_texture_rectangle_test.cpp deleted file mode 100644 index 93669e16808..00000000000 --- a/src/tests/compiler_tests/ARB_texture_rectangle_test.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// -// Copyright 2014 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. -// -// ARB_texture_rectangle_test.cpp: -// Test for the ARB_texture_rectangle extension -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class ARBTextureRectangleTestNoExt : public ShaderCompileTreeTest -{ - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_SPEC; } -}; - -class ARBTextureRectangleTest : public ARBTextureRectangleTestNoExt -{ - protected: - void initResources(ShBuiltInResources *resources) override - { - resources->ARB_texture_rectangle = 1; - } -}; - -// Check that if the extension is not supported, trying to use the features without having an -// extension directive fails. -TEST_F(ARBTextureRectangleTestNoExt, NewTypeAndBuiltinsWithoutExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - uniform sampler2DRect tex; - void main() - { - vec4 color = texture2DRect(tex, vec2(1.0)); - color = texture2DRectProj(tex, vec3(1.0)); - color = texture2DRectProj(tex, vec4(1.0)); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension is not supported, trying to use the features fails. -TEST_F(ARBTextureRectangleTestNoExt, NewTypeAndBuiltinsWithExtensionDirective) -{ - const std::string &shaderString = - R"( - #extension GL_ARB_texture_rectangle : enable - precision mediump float; - uniform sampler2DRect tex; - void main() - { - vec4 color = texture2DRect(tex, vec2(1.0)); - color = texture2DRectProj(tex, vec3(1.0)); - color = texture2DRectProj(tex, vec4(1.0)); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that new types and builtins are usable even with the #extension directive -// Issue #15 of ARB_texture_rectangle explains that the extension was specified before the -// #extension mechanism was in place so it doesn't require explicit enabling. -TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltinsWithoutExtensionDirective) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform sampler2DRect tex;\n" - "void main() {\n" - " vec4 color = texture2DRect(tex, vec2(1.0));" - " color = texture2DRectProj(tex, vec3(1.0));" - " color = texture2DRectProj(tex, vec4(1.0));" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test valid usage of the new types and builtins -TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltingsWithExtensionDirective) -{ - const std::string &shaderString = - "#extension GL_ARB_texture_rectangle : require\n" - "precision mediump float;\n" - "uniform sampler2DRect tex;\n" - "void main() {\n" - " vec4 color = texture2DRect(tex, vec2(1.0));" - " color = texture2DRectProj(tex, vec3(1.0));" - " color = texture2DRectProj(tex, vec4(1.0));" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Check that it is not possible to pass a sampler2DRect where sampler2D is expected, and vice versa -TEST_F(ARBTextureRectangleTest, Rect2DVs2DMismatch) -{ - const std::string &shaderString1 = - "#extension GL_ARB_texture_rectangle : require\n" - "precision mediump float;\n" - "uniform sampler2DRect tex;\n" - "void main() {\n" - " vec4 color = texture2D(tex, vec2(1.0));" - "}\n"; - if (compile(shaderString1)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } - - const std::string &shaderString2 = - "#extension GL_ARB_texture_rectangle : require\n" - "precision mediump float;\n" - "uniform sampler2D tex;\n" - "void main() {\n" - " vec4 color = texture2DRect(tex, vec2(1.0));" - "}\n"; - if (compile(shaderString2)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Disabling ARB_texture_rectangle in GLSL should work, even if it is enabled by default. -// See ARB_texture_rectangle spec: "a shader can still include all variations of #extension -// GL_ARB_texture_rectangle in its source code" -TEST_F(ARBTextureRectangleTest, DisableARBTextureRectangle) -{ - const std::string &shaderString = - R"( - #extension GL_ARB_texture_rectangle : disable - - precision mediump float; - - uniform sampler2DRect s; - void main() - {})"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// The compiler option to disable ARB_texture_rectangle should prevent shaders from -// enabling it. -TEST_F(ARBTextureRectangleTest, CompilerOption) -{ - const std::string &shaderString = - R"( - #extension GL_ARB_texture_rectangle : enable - precision mediump float; - uniform sampler2DRect s; - void main() {})"; - mCompileOptions.disableARBTextureRectangle = true; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// The compiler option to disable ARB_texture_rectangle should be toggleable. -TEST_F(ARBTextureRectangleTest, ToggleCompilerOption) -{ - const std::string &shaderString = - R"( - precision mediump float; - uniform sampler2DRect s; - void main() {})"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } - mCompileOptions.disableARBTextureRectangle = true; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } - mCompileOptions.disableARBTextureRectangle = false; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} diff --git a/src/tests/compiler_tests/AppendixALimitations_test.cpp b/src/tests/compiler_tests/AppendixALimitations_test.cpp deleted file mode 100644 index 415299599b5..00000000000 --- a/src/tests/compiler_tests/AppendixALimitations_test.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// -// Copyright 2017 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. -// -// AppendixALimitations_test.cpp: -// Tests for validating ESSL 1.00 Appendix A limitations. -// - -#include "gtest/gtest.h" - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class AppendixALimitationsTest : public ShaderCompileTreeTest -{ - public: - AppendixALimitationsTest() {} - - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_WEBGL_SPEC; } -}; - -// Test an invalid shader where a for loop index is used as an out parameter. -TEST_F(AppendixALimitationsTest, IndexAsFunctionOutParameter) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void fun(out int a)\n" - "{\n" - " a = 2;\n" - "}\n" - "void main()\n" - "{\n" - " for (int i = 0; i < 2; ++i)\n" - " {\n" - " fun(i);\n" - " }\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test an invalid shader where a for loop index is used as an inout parameter. -TEST_F(AppendixALimitationsTest, IndexAsFunctionInOutParameter) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void fun(int b, inout int a)\n" - "{\n" - " a += b;\n" - "}\n" - "void main()\n" - "{\n" - " for (int i = 0; i < 2; ++i)\n" - " {\n" - " fun(2, i);\n" - " }\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test a valid shader where a for loop index is used as an in parameter in a function that also has -// an out parameter. -TEST_F(AppendixALimitationsTest, IndexAsFunctionInParameter) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void fun(int b, inout int a)\n" - "{\n" - " a += b;\n" - "}\n" - "void main()\n" - "{\n" - " for (int i = 0; i < 2; ++i)\n" - " {\n" - " int a = 1;" - " fun(i, a);\n" - " }\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test an invalid shader where a for loop index is used as a target of assignment. -TEST_F(AppendixALimitationsTest, IndexAsTargetOfAssignment) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main()\n" - "{\n" - " for (int i = 0; i < 2; ++i)\n" - " {\n" - " i = 2;\n" - " }\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test an invalid shader where a for loop index is incremented inside the loop. -TEST_F(AppendixALimitationsTest, IndexIncrementedInLoopBody) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main()\n" - "{\n" - " for (int i = 0; i < 2; ++i)\n" - " {\n" - " ++i;\n" - " }\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} diff --git a/src/tests/compiler_tests/AtomicCounter_test.cpp b/src/tests/compiler_tests/AtomicCounter_test.cpp deleted file mode 100644 index 3773cc7dde1..00000000000 --- a/src/tests/compiler_tests/AtomicCounter_test.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// -// Copyright 2017 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. -// -// AtomicCounter_test.cpp: -// Tests for validating ESSL 3.10 section 4.4.6. -// - -#include "gtest/gtest.h" - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class AtomicCounterTest : public ShaderCompileTreeTest -{ - public: - AtomicCounterTest() {} - - protected: - ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } - void initResources(ShBuiltInResources *resources) override - { - resources->MaxAtomicCounterBindings = 8; - } -}; - -// Test that layout qualifiers described in ESSL 3.10 section 4.4.6 can be successfully compiled, -// and the values of offset are properly assigned to counter variables. -TEST_F(AtomicCounterTest, BasicAtomicCounterDeclaration) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint a;\n" - "layout(binding = 2) uniform atomic_uint b;\n" - "layout(binding = 2, offset = 12) uniform atomic_uint c, d;\n" - "layout(binding = 1, offset = 4) uniform atomic_uint e;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } - - std::vector counters = getUniforms(); - - EXPECT_EQ(std::string("a"), counters[0].name); - EXPECT_EQ(2, counters[0].binding); - EXPECT_EQ(4, counters[0].offset); - - EXPECT_EQ(std::string("b"), counters[1].name); - EXPECT_EQ(2, counters[1].binding); - EXPECT_EQ(8, counters[1].offset); - - EXPECT_EQ(std::string("c"), counters[2].name); - EXPECT_EQ(2, counters[2].binding); - EXPECT_EQ(12, counters[2].offset); - - EXPECT_EQ(std::string("d"), counters[3].name); - EXPECT_EQ(2, counters[3].binding); - EXPECT_EQ(16, counters[3].offset); - - EXPECT_EQ(std::string("e"), counters[4].name); - EXPECT_EQ(1, counters[4].binding); - EXPECT_EQ(4, counters[4].offset); -} - -// Test that ESSL 3.00 doesn't support atomic_uint. -TEST_F(AtomicCounterTest, InvalidShaderVersion) -{ - const std::string &source = - "#version 300 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint a;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that any qualifier other than uniform leads to compile-time error. -TEST_F(AtomicCounterTest, InvalidQualifier) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) in atomic_uint a;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that uniform must be specified for declaration. -TEST_F(AtomicCounterTest, UniformMustSpecifiedForDeclaration) -{ - const std::string &source = - "#version 310 es\n" - "atomic_uint a;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that offset overlapping leads to compile-time error(ESSL 3.10 section 4.4.6). -TEST_F(AtomicCounterTest, BindingOffsetOverlapping) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint a;\n" - "layout(binding = 2, offset = 6) uniform atomic_uint b;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test offset inheritance for multiple variables in one same declaration. -TEST_F(AtomicCounterTest, MultipleVariablesDeclaration) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint a, b;\n" - "layout(binding = 2, offset = 8) uniform atomic_uint c;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that subsequent declarations inherit the globally specified offset. -TEST_F(AtomicCounterTest, GlobalBindingOffsetOverlapping) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint;\n" - "layout(binding = 2) uniform atomic_uint b;\n" - "layout(binding = 2, offset = 4) uniform atomic_uint c;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// The spec only demands offset unique and non-overlapping. So this should be allowed. -TEST_F(AtomicCounterTest, DeclarationSequenceWithDecrementalOffsetsSpecified) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint a;\n" - "layout(binding = 2, offset = 0) uniform atomic_uint b;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that image format qualifiers are not allowed for atomic counters. -TEST_F(AtomicCounterTest, ImageFormatMustNotSpecified) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4, rgba32f) uniform atomic_uint a;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that global layout qualifiers must not use 'offset'. -TEST_F(AtomicCounterTest, OffsetMustNotSpecifiedForGlobalLayoutQualifier) -{ - const std::string &source = - "#version 310 es\n" - "layout(offset = 4) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that offset overlapping leads to compile-time error (ESSL 3.10 section 4.4.6). -// Note that there is some vagueness in the spec when it comes to this test. -TEST_F(AtomicCounterTest, BindingOffsetOverlappingForArrays) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 2, offset = 4) uniform atomic_uint[2] a;\n" - "layout(binding = 2, offset = 8) uniform atomic_uint b;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} diff --git a/src/tests/compiler_tests/BufferVariables_test.cpp b/src/tests/compiler_tests/BufferVariables_test.cpp deleted file mode 100644 index f9b533d7664..00000000000 --- a/src/tests/compiler_tests/BufferVariables_test.cpp +++ /dev/null @@ -1,684 +0,0 @@ -// -// Copyright 2017 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. -// -// BufferVariables_test.cpp: -// Tests for buffer variables in GLSL ES 3.10 section 4.3.7. -// - -#include "gtest/gtest.h" - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" -#include "tests/test_utils/compiler_test.h" - -using namespace sh; - -class BufferVariablesTest : public ShaderCompileTreeTest -{ - public: - BufferVariablesTest() {} - - protected: - ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } - void initResources(ShBuiltInResources *resources) override - { - resources->MaxShaderStorageBufferBindings = 8; - } -}; - -class BufferVariablesMatchTest : public MatchOutputCodeTest -{ - public: - BufferVariablesMatchTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_ESSL_OUTPUT) - { - getResources()->MaxShaderStorageBufferBindings = 8; - } -}; - -// Test that the buffer qualifier described in GLSL ES 3.10 section 4.3.7 can be successfully -// compiled. -TEST_F(BufferVariablesTest, BasicShaderStorageBlockDeclaration) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " int b1;\n" - " buffer int b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that shader storage block layout qualifiers can be declared for global scope. -TEST_F(BufferVariablesTest, LayoutQualifiersDeclaredInGlobal) -{ - const std::string &source = - "#version 310 es\n" - "layout(shared, column_major) buffer;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that shader storage block can be used with one or more memory qualifiers. -TEST_F(BufferVariablesTest, ShaderStorageBlockWithMemoryQualifier) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) writeonly buffer buf {\n" - " int b1;\n" - " buffer int b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that buffer variables can be used with one or more memory qualifiers. -TEST_F(BufferVariablesTest, BufferVariablesWithMemoryQualifier) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly int b1;\n" - " writeonly buffer int b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that it is a compile-time error to declare buffer variables at global scope (outside a -// block). -TEST_F(BufferVariablesTest, DeclareBufferVariableAtGlobal) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer int a;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that the buffer variable can't be opaque type. -TEST_F(BufferVariablesTest, BufferVariableWithOpaqueType) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " int b1;\n" - " atomic_uint b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that the uniform variable can't be in shader storage block. -TEST_F(BufferVariablesTest, UniformVariableInShaderStorageBlock) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " uniform int a;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that buffer qualifier is not supported in verson lower than GLSL ES 3.10. -TEST_F(BufferVariablesTest, BufferQualifierInESSL3) -{ - const std::string &source = - "#version 300 es\n" - "layout(binding = 3) buffer buf {\n" - " int b1;\n" - " buffer int b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that can't assign to a readonly buffer variable. -TEST_F(BufferVariablesTest, AssignToReadonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " readonly int b1;\n" - "};\n" - "void main()\n" - "{\n" - " b1 = 5;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that can't assign to a buffer variable declared within shader storage block with readonly. -TEST_F(BufferVariablesTest, AssignToBufferVariableWithinReadonlyBlock) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) readonly buffer buf {\n" - " int b1;\n" - "};\n" - "void main()\n" - "{\n" - " b1 = 5;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that can't assign to a readonly buffer variable through an instance name. -TEST_F(BufferVariablesTest, AssignToReadonlyBufferVariableByInstanceName) -{ - const std::string &source = - R"(#version 310 es - layout(binding = 3) buffer buf { - readonly float f; - } instanceBuffer; - void main() - { - instanceBuffer.f += 0.2; - })"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that can't assign to a readonly struct buffer variable. -TEST_F(BufferVariablesTest, AssignToReadonlyStructBufferVariable) -{ - const std::string &source = - R"(#version 310 es - struct S { - float f; - }; - layout(binding = 3) buffer buf { - readonly S s; - }; - void main() - { - s.f += 0.2; - })"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that can't assign to a readonly struct buffer variable through an instance name. -TEST_F(BufferVariablesTest, AssignToReadonlyStructBufferVariableByInstanceName) -{ - const std::string &source = - R"(#version 310 es - struct S { - float f; - }; - layout(binding = 3) buffer buf { - readonly S s; - } instanceBuffer; - void main() - { - instanceBuffer.s.f += 0.2; - })"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that a readonly and writeonly buffer variable should neither read or write. -TEST_F(BufferVariablesTest, AccessReadonlyWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " readonly writeonly int b1;\n" - "};\n" - "void main()\n" - "{\n" - " b1 = 5;\n" - " int test = b1;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that accessing a writeonly buffer variable should be error. -TEST_F(BufferVariablesTest, AccessWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly int b1;\n" - "};\n" - "void main()\n" - "{\n" - " int test = b1;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that accessing a buffer variable through an instance name is ok. -TEST_F(BufferVariablesTest, AccessReadonlyBufferVariableByInstanceName) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " readonly float f;\n" - "} instanceBuffer;\n" - "void main()\n" - "{\n" - " gl_Position.x = instanceBuffer.f;\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that accessing a buffer variable through an instance name inherits the writeonly qualifier -// and generates errors. -TEST_F(BufferVariablesTest, AccessWriteonlyBufferVariableByInstanceName) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) writeonly buffer buf {\n" - " float f;\n" - "} instanceBuffer;\n" - "void main()\n" - "{\n" - " float test = instanceBuffer.f;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as the argument of a unary operator should be error. -TEST_F(BufferVariablesTest, UnaryOperatorWithWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly int b1;\n" - "};\n" - "void main()\n" - "{\n" - " ++b1;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable on the left-hand side of compound assignment should be error. -TEST_F(BufferVariablesTest, CompoundAssignmentToWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly int b1;\n" - "};\n" - "void main()\n" - "{\n" - " b1 += 5;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as ternary op argument should be error. -TEST_F(BufferVariablesTest, TernarySelectionWithWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly bool b1;\n" - "};\n" - "void main()\n" - "{\n" - " int test = b1 ? 1 : 0;\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as array constructor argument should be error. -TEST_F(BufferVariablesTest, ArrayConstructorWithWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly float f;\n" - "};\n" - "void main()\n" - "{\n" - " float a[3] = float[3](f, f, f);\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as structure constructor argument should be error. -TEST_F(BufferVariablesTest, StructureConstructorWithWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "struct S {\n" - " int a;\n" - "};\n" - "struct T {\n" - " S b;\n" - "};\n" - "layout(binding = 3) buffer buf {\n" - " writeonly S c;\n" - "};\n" - "void main()\n" - "{\n" - " T t = T(c);\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as built-in function argument should be error. -TEST_F(BufferVariablesTest, BuildInFunctionWithWriteonlyBufferVariable) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly int a;\n" - "};\n" - "void main()\n" - "{\n" - " int test = min(a, 1);\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that readonly buffer variable as user-defined function in argument should be ok. -TEST_F(BufferVariablesTest, UserDefinedFunctionWithReadonlyBufferVariableInArgument) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " readonly float f;\n" - "};\n" - "void foo(float a) {}\n" - "void main()\n" - "{\n" - " foo(f);\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as user-defined function in argument should be error. -TEST_F(BufferVariablesTest, UserDefinedFunctionWithWriteonlyBufferVariableInArgument) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly float f;\n" - "};\n" - "void foo(float a) {}\n" - "void main()\n" - "{\n" - " foo(f);\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that writeonly buffer variable as user-defined function out argument should be ok. -TEST_F(BufferVariablesTest, UserDefinedFunctionWithWriteonlyBufferVariableOutArgument) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " writeonly float f;\n" - "};\n" - "void foo(out float a) {}\n" - "void main()\n" - "{\n" - " foo(f);\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that readonly buffer variable as user-defined function out argument should be error. -TEST_F(BufferVariablesTest, UserDefinedFunctionWithReadonlyBufferVariableOutArgument) -{ - const std::string &source = - "#version 310 es\n" - "layout(binding = 3) buffer buf {\n" - " readonly float f;\n" - "};\n" - "void foo(out float a) {}\n" - "void main()\n" - "{\n" - " foo(f);\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that buffer qualifier can't modify a function parameter. -TEST_F(BufferVariablesTest, BufferQualifierOnFunctionParameter) -{ - const std::string &source = - "#version 310 es\n" - "void foo(buffer float a) {}\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that std430 qualifier is supported for shader storage blocks. -TEST_F(BufferVariablesTest, ShaderStorageBlockWithStd430) -{ - const std::string &source = - "#version 310 es\n" - "layout(std430) buffer buf {\n" - " int b1;\n" - " int b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that using std430 qualifier on a uniform block will fail to compile. -TEST_F(BufferVariablesTest, UniformBlockWithStd430) -{ - const std::string &source = - "#version 310 es\n" - "layout(std430) uniform buf {\n" - " int b1;\n" - " int b2;\n" - "};\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing a runtime-sized array with a positive index compiles. -TEST_F(BufferVariablesTest, IndexRuntimeSizedArray) -{ - const std::string &source = - R"(#version 310 es - - layout(std430) buffer buf - { - int arr[]; - }; - - void main() - { - arr[100]; - })"; - if (!compile(source)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that indexing a runtime-sized array with a negative constant index does not compile. -TEST_F(BufferVariablesTest, IndexRuntimeSizedArrayWithNegativeIndex) -{ - const std::string &source = - R"(#version 310 es - - layout(std430) buffer buf - { - int arr[]; - }; - - void main() - { - arr[-1]; - })"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that only the last member of a buffer can be runtime-sized. -TEST_F(BufferVariablesTest, RuntimeSizedVariableInNotLastInBuffer) -{ - const std::string &source = - R"(#version 310 es - - layout(std430) buffer buf - { - int arr[]; - int i; - }; - - void main() - { - })"; - if (compile(source)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that memory qualifiers are output. -TEST_F(BufferVariablesMatchTest, MemoryQualifiers) -{ - const std::string &source = - R"(#version 310 es - - layout(std430) coherent buffer buf - { - int defaultCoherent; - coherent ivec2 specifiedCoherent; - volatile ivec3 specifiedVolatile; - restrict ivec4 specifiedRestrict; - readonly float specifiedReadOnly; - writeonly vec2 specifiedWriteOnly; - volatile readonly vec3 specifiedMultiple; - }; - - void main() - { - })"; - compile(source); - ASSERT_TRUE(foundInESSLCode("coherent highp int")); - ASSERT_TRUE(foundInESSLCode("coherent highp ivec2")); - ASSERT_TRUE(foundInESSLCode("coherent volatile highp ivec3")); - ASSERT_TRUE(foundInESSLCode("coherent restrict highp ivec4")); - ASSERT_TRUE(foundInESSLCode("readonly coherent highp float")); - ASSERT_TRUE(foundInESSLCode("writeonly coherent highp vec2")); - ASSERT_TRUE(foundInESSLCode("readonly coherent volatile highp vec3")); -} diff --git a/src/tests/compiler_tests/CollectVariables_test.cpp b/src/tests/compiler_tests/CollectVariables_test.cpp index 29ebab5bfec..347e27e9783 100644 --- a/src/tests/compiler_tests/CollectVariables_test.cpp +++ b/src/tests/compiler_tests/CollectVariables_test.cpp @@ -7,6 +7,10 @@ // Some tests for shader inspection // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "GLSLANG/ShaderLang.h" @@ -58,7 +62,7 @@ class CollectVariablesTest : public testing::Test { const char *shaderStrings[] = {shaderString.c_str()}; ShCompileOptions compileOptions = {}; - ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, compileOptions)); + ASSERT_TRUE(mTranslator->compile(shaderStrings, compileOptions)); const std::vector &uniforms = mTranslator->getUniforms(); ASSERT_EQ(1u, uniforms.size()); @@ -109,7 +113,7 @@ class CollectVariablesTest : public testing::Test { const char *shaderStrings[] = {shaderString.c_str()}; ShCompileOptions compileOptions = {}; - ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, compileOptions)) + ASSERT_TRUE(mTranslator->compile(shaderStrings, compileOptions)) << mTranslator->getInfoSink().info.str(); const auto &outputVariables = mTranslator->getOutputVariables(); @@ -125,7 +129,7 @@ class CollectVariablesTest : public testing::Test void compile(const std::string &shaderString, ShCompileOptions *compileOptions) { const char *shaderStrings[] = {shaderString.c_str()}; - ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, *compileOptions)); + ASSERT_TRUE(mTranslator->compile(shaderStrings, *compileOptions)); } void compile(const std::string &shaderString) @@ -667,30 +671,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDataUniform) } // Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output -// variables list. Also test that the precision is mediump. -TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthMediump) -{ - const std::string &fragDepthShader = - "#extension GL_EXT_frag_depth : require\n" - "precision mediump float;\n" - "void main() {\n" - " gl_FragDepthEXT = 0.7;" - "}\n"; - - ShBuiltInResources resources = mTranslator->getResources(); - resources.EXT_frag_depth = 1; - initTranslator(resources); - - const ShaderVariable *outputVariable = nullptr; - validateOutputVariableForShader(fragDepthShader, 0u, "gl_FragDepthEXT", &outputVariable); - ASSERT_NE(outputVariable, nullptr); - EXPECT_FALSE(outputVariable->isArray()); - EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type); - EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision); -} - -// Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output -// variables list. Also test that the precision is highp if user requests it. +// variables list. Also test that the precision is highp because the translator assumes it's always +// supported. TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp) { const std::string &fragDepthHighShader = @@ -701,7 +683,6 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp) ShBuiltInResources resources = mTranslator->getResources(); resources.EXT_frag_depth = 1; - resources.FragmentPrecisionHigh = 1; initTranslator(resources); const ShaderVariable *outputVariable = nullptr; diff --git a/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp b/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp deleted file mode 100644 index 1fa62489b3b..00000000000 --- a/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2016 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. -// -// ConstantFoldingNaN_test.cpp: -// Tests for constant folding that results in NaN according to IEEE and should also generate a -// warning. The ESSL spec does not mandate generating NaNs, but this is reasonable behavior in -// this case. -// - -#include "tests/test_utils/ConstantFoldingTest.h" - -using namespace sh; - -namespace -{ - -class ConstantFoldingNaNExpressionTest : public ConstantFoldingExpressionTest -{ - public: - ConstantFoldingNaNExpressionTest() {} - - void evaluateFloatNaN(const std::string &floatString) - { - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::quiet_NaN())); - ASSERT_TRUE(hasWarning()); - } -}; - -} // anonymous namespace - -// Test that infinity - infinity evaluates to NaN. -TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityMinusInfinity) -{ - const std::string &floatString = "1.0e2048 - 1.0e2048"; - evaluateFloatNaN(floatString); -} - -// Test that infinity + negative infinity evaluates to NaN. -TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityPlusNegativeInfinity) -{ - const std::string &floatString = "1.0e2048 + (-1.0e2048)"; - evaluateFloatNaN(floatString); -} - -// Test that infinity multiplied by zero evaluates to NaN. -TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityMultipliedByZero) -{ - const std::string &floatString = "1.0e2048 * 0.0"; - evaluateFloatNaN(floatString); -} - -// Test that infinity divided by infinity evaluates to NaN. -TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityDividedByInfinity) -{ - const std::string &floatString = "1.0e2048 / 1.0e2048"; - evaluateFloatNaN(floatString); -} - -// Test that zero divided by zero evaluates to NaN. -TEST_F(ConstantFoldingNaNExpressionTest, FoldZeroDividedByZero) -{ - const std::string &floatString = "0.0 / 0.0"; - evaluateFloatNaN(floatString); -} diff --git a/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp b/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp deleted file mode 100644 index 32fb58fb592..00000000000 --- a/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright 2016 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. -// -// ConstantFoldingOverflow_test.cpp: -// Tests for constant folding that results in floating point overflow. -// In IEEE floating point, the overflow result depends on which of the various rounding modes is -// chosen - it's either the maximum representable value or infinity. -// ESSL 3.00.6 section 4.5.1 says that the rounding mode cannot be set and is undefined, so the -// result in this case is not defined by the spec. -// We decide to overflow to infinity and issue a warning. -// - -#include "tests/test_utils/ConstantFoldingTest.h" - -using namespace sh; - -namespace -{ - -class ConstantFoldingOverflowExpressionTest : public ConstantFoldingExpressionTest -{ - public: - ConstantFoldingOverflowExpressionTest() {} - - void evaluateFloatOverflow(const std::string &floatString, bool positive) - { - evaluateFloat(floatString); - float expected = positive ? std::numeric_limits::infinity() - : -std::numeric_limits::infinity(); - ASSERT_TRUE(constantFoundInAST(expected)); - ASSERT_TRUE(hasWarning()); - } -}; - -} // anonymous namespace - -// Test that addition that overflows is evaluated correctly. -TEST_F(ConstantFoldingOverflowExpressionTest, Add) -{ - const std::string &floatString = "2.0e38 + 2.0e38"; - evaluateFloatOverflow(floatString, true); -} - -// Test that subtraction that overflows is evaluated correctly. -TEST_F(ConstantFoldingOverflowExpressionTest, Subtract) -{ - const std::string &floatString = "2.0e38 - (-2.0e38)"; - evaluateFloatOverflow(floatString, true); -} - -// Test that multiplication that overflows is evaluated correctly. -TEST_F(ConstantFoldingOverflowExpressionTest, Multiply) -{ - const std::string &floatString = "1.0e30 * 1.0e10"; - evaluateFloatOverflow(floatString, true); -} - -// Test that division that overflows is evaluated correctly. -TEST_F(ConstantFoldingOverflowExpressionTest, Divide) -{ - const std::string &floatString = "1.0e30 / 1.0e-10"; - evaluateFloatOverflow(floatString, true); -} diff --git a/src/tests/compiler_tests/ConstantFolding_test.cpp b/src/tests/compiler_tests/ConstantFolding_test.cpp deleted file mode 100644 index 41285fea90b..00000000000 --- a/src/tests/compiler_tests/ConstantFolding_test.cpp +++ /dev/null @@ -1,1652 +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. -// -// ConstantFolding_test.cpp: -// Tests for constant folding -// - -#include "tests/test_utils/ConstantFoldingTest.h" - -using namespace sh; - -// Test that zero, true or false are not found in AST when they are not expected. This is to make -// sure that the subsequent tests run correctly. -TEST_F(ConstantFoldingExpressionTest, FoldFloatTestCheck) -{ - const std::string &floatString = "1.0"; - evaluateFloat(floatString); - ASSERT_FALSE(constantFoundInAST(0.0f)); - ASSERT_FALSE(constantFoundInAST(true)); - ASSERT_FALSE(constantFoundInAST(false)); -} - -TEST_F(ConstantFoldingTest, FoldIntegerAdd) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out int my_Int;\n" - "void main() {\n" - " const int i = 1124 + 5;\n" - " my_Int = i;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(1124)); - ASSERT_FALSE(constantFoundInAST(5)); - ASSERT_TRUE(constantFoundInAST(1129)); -} - -TEST_F(ConstantFoldingTest, FoldIntegerSub) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out int my_Int;\n" - "void main() {\n" - " const int i = 1124 - 5;\n" - " my_Int = i;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(1124)); - ASSERT_FALSE(constantFoundInAST(5)); - ASSERT_TRUE(constantFoundInAST(1119)); -} - -TEST_F(ConstantFoldingTest, FoldIntegerMul) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out int my_Int;\n" - "void main() {\n" - " const int i = 1124 * 5;\n" - " my_Int = i;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(1124)); - ASSERT_FALSE(constantFoundInAST(5)); - ASSERT_TRUE(constantFoundInAST(5620)); -} - -TEST_F(ConstantFoldingTest, FoldIntegerDiv) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out int my_Int;\n" - "void main() {\n" - " const int i = 1124 / 5;\n" - " my_Int = i;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(1124)); - ASSERT_FALSE(constantFoundInAST(5)); - // Rounding mode of division is undefined in the spec but ANGLE can be expected to round down. - ASSERT_TRUE(constantFoundInAST(224)); -} - -TEST_F(ConstantFoldingTest, FoldIntegerModulus) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out int my_Int;\n" - "void main() {\n" - " const int i = 1124 % 5;\n" - " my_Int = i;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(1124)); - ASSERT_FALSE(constantFoundInAST(5)); - ASSERT_TRUE(constantFoundInAST(4)); -} - -TEST_F(ConstantFoldingTest, FoldVectorCrossProduct) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec3 my_Vec3;" - "void main() {\n" - " const vec3 v3 = cross(vec3(1.0f, 1.0f, 1.0f), vec3(1.0f, -1.0f, 1.0f));\n" - " my_Vec3 = v3;\n" - "}\n"; - compileAssumeSuccess(shaderString); - std::vector input1(3, 1.0f); - ASSERT_FALSE(constantVectorFoundInAST(input1)); - std::vector input2; - input2.push_back(1.0f); - input2.push_back(-1.0f); - input2.push_back(1.0f); - ASSERT_FALSE(constantVectorFoundInAST(input2)); - std::vector result; - result.push_back(2.0f); - result.push_back(0.0f); - result.push_back(-2.0f); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -// FoldMxNMatrixInverse tests check if the matrix 'inverse' operation -// on MxN matrix is constant folded when argument is constant expression and also -// checks the correctness of the result returned by the constant folding operation. -// All the matrices including matrices in the shader code are in column-major order. -TEST_F(ConstantFoldingTest, Fold2x2MatrixInverse) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "in float i;\n" - "out vec2 my_Vec;\n" - "void main() {\n" - " const mat2 m2 = inverse(mat2(2.0f, 3.0f,\n" - " 5.0f, 7.0f));\n" - " mat2 m = m2 * mat2(i);\n" - " my_Vec = m[0];\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {2.0f, 3.0f, 5.0f, 7.0f}; - std::vector input(inputElements, inputElements + 4); - ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input)); - float outputElements[] = {-7.0f, 3.0f, 5.0f, -2.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Check if the matrix 'inverse' operation on 3x3 matrix is constant folded. -TEST_F(ConstantFoldingTest, Fold3x3MatrixInverse) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "in float i;\n" - "out vec3 my_Vec;\n" - "void main() {\n" - " const mat3 m3 = inverse(mat3(11.0f, 13.0f, 19.0f,\n" - " 23.0f, 29.0f, 31.0f,\n" - " 37.0f, 41.0f, 43.0f));\n" - " mat3 m = m3 * mat3(i);\n" - " my_Vec = m[0];\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f}; - std::vector input(inputElements, inputElements + 9); - ASSERT_FALSE(constantVectorFoundInAST(input)); - float outputElements[] = {3.0f / 85.0f, -11.0f / 34.0f, 37.0f / 170.0f, - -79.0f / 340.0f, 23.0f / 68.0f, -12.0f / 85.0f, - 13.0f / 68.0f, -3.0f / 68.0f, -1.0f / 34.0f}; - std::vector result(outputElements, outputElements + 9); - const float floatFaultTolerance = 0.000001f; - ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance)); -} - -// Check if the matrix 'inverse' operation on 4x4 matrix is constant folded. -TEST_F(ConstantFoldingTest, Fold4x4MatrixInverse) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "in float i;\n" - "out vec4 my_Vec;\n" - "void main() {\n" - " const mat4 m4 = inverse(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n" - " 43.0f, 47.0f, 53.0f, 59.0f,\n" - " 61.0f, 67.0f, 71.0f, 73.0f,\n" - " 79.0f, 83.0f, 89.0f, 97.0f));\n" - " mat4 m = m4 * mat4(i);\n" - " my_Vec = m[0];\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {29.0f, 31.0f, 37.0f, 41.0f, 43.0f, 47.0f, 53.0f, 59.0f, - 61.0f, 67.0f, 71.0f, 73.0f, 79.0f, 83.0f, 89.0f, 97.0f}; - std::vector input(inputElements, inputElements + 16); - ASSERT_FALSE(constantVectorFoundInAST(input)); - float outputElements[] = {43.0f / 126.0f, -11.0f / 21.0f, -2.0f / 21.0f, 31.0f / 126.0f, - -5.0f / 7.0f, 9.0f / 14.0f, 1.0f / 14.0f, -1.0f / 7.0f, - 85.0f / 126.0f, -11.0f / 21.0f, 43.0f / 210.0f, -38.0f / 315.0f, - -2.0f / 7.0f, 5.0f / 14.0f, -6.0f / 35.0f, 3.0f / 70.0f}; - std::vector result(outputElements, outputElements + 16); - const float floatFaultTolerance = 0.00001f; - ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance)); -} - -// FoldMxNMatrixDeterminant tests check if the matrix 'determinant' operation -// on MxN matrix is constant folded when argument is constant expression and also -// checks the correctness of the result returned by the constant folding operation. -// All the matrices including matrices in the shader code are in column-major order. -TEST_F(ConstantFoldingTest, Fold2x2MatrixDeterminant) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out float my_Float;" - "void main() {\n" - " const float f = determinant(mat2(2.0f, 3.0f,\n" - " 5.0f, 7.0f));\n" - " my_Float = f;\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {2.0f, 3.0f, 5.0f, 7.0f}; - std::vector input(inputElements, inputElements + 4); - ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input)); - ASSERT_TRUE(constantFoundInAST(-1.0f)); -} - -// Check if the matrix 'determinant' operation on 3x3 matrix is constant folded. -TEST_F(ConstantFoldingTest, Fold3x3MatrixDeterminant) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out float my_Float;" - "void main() {\n" - " const float f = determinant(mat3(11.0f, 13.0f, 19.0f,\n" - " 23.0f, 29.0f, 31.0f,\n" - " 37.0f, 41.0f, 43.0f));\n" - " my_Float = f;\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f}; - std::vector input(inputElements, inputElements + 9); - ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input)); - ASSERT_TRUE(constantFoundInAST(-680.0f)); -} - -// Check if the matrix 'determinant' operation on 4x4 matrix is constant folded. -TEST_F(ConstantFoldingTest, Fold4x4MatrixDeterminant) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out float my_Float;" - "void main() {\n" - " const float f = determinant(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n" - " 43.0f, 47.0f, 53.0f, 59.0f,\n" - " 61.0f, 67.0f, 71.0f, 73.0f,\n" - " 79.0f, 83.0f, 89.0f, 97.0f));\n" - " my_Float = f;\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {29.0f, 31.0f, 37.0f, 41.0f, 43.0f, 47.0f, 53.0f, 59.0f, - 61.0f, 67.0f, 71.0f, 73.0f, 79.0f, 83.0f, 89.0f, 97.0f}; - std::vector input(inputElements, inputElements + 16); - ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input)); - ASSERT_TRUE(constantFoundInAST(-2520.0f)); -} - -// Check if the matrix 'transpose' operation on 3x3 matrix is constant folded. -// All the matrices including matrices in the shader code are in column-major order. -TEST_F(ConstantFoldingTest, Fold3x3MatrixTranspose) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "in float i;\n" - "out vec3 my_Vec;\n" - "void main() {\n" - " const mat3 m3 = transpose(mat3(11.0f, 13.0f, 19.0f,\n" - " 23.0f, 29.0f, 31.0f,\n" - " 37.0f, 41.0f, 43.0f));\n" - " mat3 m = m3 * mat3(i);\n" - " my_Vec = m[0];\n" - "}\n"; - compileAssumeSuccess(shaderString); - float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f}; - std::vector input(inputElements, inputElements + 9); - ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input)); - float outputElements[] = {11.0f, 23.0f, 37.0f, 13.0f, 29.0f, 41.0f, 19.0f, 31.0f, 43.0f}; - std::vector result(outputElements, outputElements + 9); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that 0xFFFFFFFF wraps to -1 when parsed as integer. -// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42 -// means that any 32-bit unsigned integer value is a valid literal. -TEST_F(ConstantFoldingTest, ParseWrappedHexIntLiteral) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision highp int;\n" - "uniform int inInt;\n" - "out vec4 my_Vec;\n" - "void main() {\n" - " const int i = 0xFFFFFFFF;\n" - " my_Vec = vec4(i * inInt);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(-1)); -} - -// Test that 3000000000 wraps to -1294967296 when parsed as integer. -// This is featured in the examples of GLSL 4.5, and ESSL behavior should match -// desktop GLSL when it comes to integer parsing. -TEST_F(ConstantFoldingTest, ParseWrappedDecimalIntLiteral) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision highp int;\n" - "uniform int inInt;\n" - "out vec4 my_Vec;\n" - "void main() {\n" - " const int i = 3000000000;\n" - " my_Vec = vec4(i * inInt);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(-1294967296)); -} - -// Test that 0xFFFFFFFFu is parsed correctly as an unsigned integer literal. -// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42 -// means that any 32-bit unsigned integer value is a valid literal. -TEST_F(ConstantFoldingTest, ParseMaxUintLiteral) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision highp int;\n" - "uniform uint inInt;\n" - "out vec4 my_Vec;\n" - "void main() {\n" - " const uint i = 0xFFFFFFFFu;\n" - " my_Vec = vec4(i * inInt);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu)); -} - -// Test that unary minus applied to unsigned int is constant folded correctly. -// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42 -// means that any 32-bit unsigned integer value is a valid literal. -TEST_F(ConstantFoldingTest, FoldUnaryMinusOnUintLiteral) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision highp int;\n" - "uniform uint inInt;\n" - "out vec4 my_Vec;\n" - "void main() {\n" - " const uint i = -1u;\n" - " my_Vec = vec4(i * inInt);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu)); -} - -// Test that constant mat2 initialization with a mat2 parameter works correctly. -TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat2) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float mult;\n" - "void main() {\n" - " const mat2 cm = mat2(mat2(0.0, 1.0, 2.0, 3.0));\n" - " mat2 m = cm * mult;\n" - " gl_FragColor = vec4(m[0], m[1]);\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {0.0f, 1.0f, 2.0f, 3.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that constant mat2 initialization with an int parameter works correctly. -TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingScalar) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float mult;\n" - "void main() {\n" - " const mat2 cm = mat2(3);\n" - " mat2 m = cm * mult;\n" - " gl_FragColor = vec4(m[0], m[1]);\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {3.0f, 0.0f, 0.0f, 3.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that constant mat2 initialization with a mix of parameters works correctly. -TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMix) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float mult;\n" - "void main() {\n" - " const mat2 cm = mat2(-1, vec2(0.0, 1.0), vec4(2.0));\n" - " mat2 m = cm * mult;\n" - " gl_FragColor = vec4(m[0], m[1]);\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {-1.0, 0.0f, 1.0f, 2.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that constant mat2 initialization with a mat3 parameter works correctly. -TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat3) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float mult;\n" - "void main() {\n" - " const mat2 cm = mat2(mat3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0));\n" - " mat2 m = cm * mult;\n" - " gl_FragColor = vec4(m[0], m[1]);\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {0.0f, 1.0f, 3.0f, 4.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that constant mat4x3 initialization with a mat3x2 parameter works correctly. -TEST_F(ConstantFoldingTest, FoldMat4x3ConstructorTakingMat3x2) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform float mult;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " const mat4x3 cm = mat4x3(mat3x2(1.0, 2.0,\n" - " 3.0, 4.0,\n" - " 5.0, 6.0));\n" - " mat4x3 m = cm * mult;\n" - " my_FragColor = vec4(m[0], m[1][0]);\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {1.0f, 2.0f, 0.0f, 3.0f, 4.0f, 0.0f, - 5.0f, 6.0f, 1.0f, 0.0f, 0.0f, 0.0f}; - std::vector result(outputElements, outputElements + 12); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that constant mat2 initialization with a vec4 parameter works correctly. -TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingVec4) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float mult;\n" - "void main() {\n" - " const mat2 cm = mat2(vec4(0.0, 1.0, 2.0, 3.0));\n" - " mat2 m = cm * mult;\n" - " gl_FragColor = vec4(m[0], m[1]);\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {0.0f, 1.0f, 2.0f, 3.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that equality comparison of two different structs with a nested struct inside returns false. -TEST_F(ConstantFoldingTest, FoldNestedDifferentStructEqualityComparison) -{ - const std::string &shaderString = - "precision mediump float;\n" - "struct nested {\n" - " float f\n;" - "};\n" - "struct S {\n" - " nested a;\n" - " float f;\n" - "};\n" - "uniform vec4 mult;\n" - "void main()\n" - "{\n" - " const S s1 = S(nested(0.0), 2.0);\n" - " const S s2 = S(nested(0.0), 3.0);\n" - " gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0.5f)); -} - -// Test that equality comparison of two identical structs with a nested struct inside returns true. -TEST_F(ConstantFoldingTest, FoldNestedIdenticalStructEqualityComparison) -{ - const std::string &shaderString = - "precision mediump float;\n" - "struct nested {\n" - " float f\n;" - "};\n" - "struct S {\n" - " nested a;\n" - " float f;\n" - " int i;\n" - "};\n" - "uniform vec4 mult;\n" - "void main()\n" - "{\n" - " const S s1 = S(nested(0.0), 2.0, 3);\n" - " const S s2 = S(nested(0.0), 2.0, 3);\n" - " gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(1.0f)); -} - -// Test that right elements are chosen from non-square matrix -TEST_F(ConstantFoldingTest, FoldNonSquareMatrixIndexing) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " my_FragColor = mat3x4(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)[1];\n" - "}\n"; - compileAssumeSuccess(shaderString); - float outputElements[] = {4.0f, 5.0f, 6.0f, 7.0f}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -// Test that folding outer product of vectors with non-matching lengths works. -TEST_F(ConstantFoldingTest, FoldNonSquareOuterProduct) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " mat3x2 prod = outerProduct(vec2(2.0, 3.0), vec3(5.0, 7.0, 11.0));\n" - " my_FragColor = vec4(prod[0].x);\n" - "}\n"; - compileAssumeSuccess(shaderString); - // clang-format off - float outputElements[] = - { - 10.0f, 15.0f, - 14.0f, 21.0f, - 22.0f, 33.0f - }; - // clang-format on - std::vector result(outputElements, outputElements + 6); - ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result)); -} - -// Test that folding bit shift left with non-matching signedness works. -TEST_F(ConstantFoldingTest, FoldBitShiftLeftDifferentSignedness) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " uint u = 0xffffffffu << 31;\n" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0x80000000u)); -} - -// Test that folding bit shift right with non-matching signedness works. -TEST_F(ConstantFoldingTest, FoldBitShiftRightDifferentSignedness) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " uint u = 0xffffffffu >> 30;\n" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0x3u)); -} - -// Test that folding signed bit shift right extends the sign bit. -// ESSL 3.00.6 section 5.9 Expressions. -TEST_F(ConstantFoldingTest, FoldBitShiftRightExtendSignBit) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const int i = 0x8fffe000 >> 6;\n" - " uint u = uint(i);" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - // The bits of the operand are 0x8fffe000 = 1000 1111 1111 1111 1110 0000 0000 0000 - // After shifting, they become 1111 1110 0011 1111 1111 1111 1000 0000 = 0xfe3fff80 - ASSERT_TRUE(constantFoundInAST(0xfe3fff80u)); -} - -// Signed bit shift left should interpret its operand as a bit pattern. As a consequence a number -// may turn from positive to negative when shifted left. -// ESSL 3.00.6 section 5.9 Expressions. -TEST_F(ConstantFoldingTest, FoldBitShiftLeftInterpretedAsBitPattern) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const int i = 0x1fffffff << 3;\n" - " uint u = uint(i);" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0xfffffff8u)); -} - -// Test that dividing the minimum signed integer by -1 works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "However, for the case where the minimum representable value is divided by -1, it is allowed to -// return either the minimum representable value or the maximum representable value." -TEST_F(ConstantFoldingTest, FoldDivideMinimumIntegerByMinusOne) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = 0x80000000 / (-1);\n" - " my_FragColor = vec4(i);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0x7fffffff) || constantFoundInAST(-0x7fffffff - 1)); -} - -// Test that folding an unsigned integer addition that overflows works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldUnsignedIntegerAddOverflow) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " uint u = 0xffffffffu + 43u;\n" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(42u)); -} - -// Test that folding a signed integer addition that overflows works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldSignedIntegerAddOverflow) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = 0x7fffffff + 4;\n" - " my_FragColor = vec4(i);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(-0x7ffffffd)); -} - -// Test that folding an unsigned integer subtraction that overflows works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldUnsignedIntegerDiffOverflow) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " uint u = 0u - 5u;\n" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0xfffffffbu)); -} - -// Test that folding a signed integer subtraction that overflows works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldSignedIntegerDiffOverflow) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = -0x7fffffff - 7;\n" - " my_FragColor = vec4(i);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0x7ffffffa)); -} - -// Test that folding an unsigned integer multiplication that overflows works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldUnsignedIntegerMultiplyOverflow) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " uint u = 0xffffffffu * 10u;\n" - " my_FragColor = vec4(u);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(0xfffffff6u)); -} - -// Test that folding a signed integer multiplication that overflows works. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldSignedIntegerMultiplyOverflow) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = 0x7fffffff * 42;\n" - " my_FragColor = vec4(i);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(-42)); -} - -// Test that folding of negating the minimum representable integer works. Note that in the test -// "0x80000000" is a negative literal, and the minus sign before it is the negation operator. -// ESSL 3.00.6 section 4.1.3 Integers: -// "For all precisions, operations resulting in overflow or underflow will not cause any exception, -// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where -// n is the size in bits of the integer." -TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerNegation) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = -0x80000000;\n" - " my_FragColor = vec4(i);\n" - "}\n"; - compileAssumeSuccess(shaderString); - // Negating the minimum signed integer overflows the positive range, so it wraps back to itself. - ASSERT_TRUE(constantFoundInAST(-0x7fffffff - 1)); -} - -// Test that folding of shifting the minimum representable integer works. -TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerRightShift) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = (0x80000000 >> 1);\n" - " int j = (0x80000000 >> 7);\n" - " my_FragColor = vec4(i, j, i, j);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(-0x40000000)); - ASSERT_TRUE(constantFoundInAST(-0x01000000)); -} - -// Test that folding of shifting by 0 works. -TEST_F(ConstantFoldingTest, FoldShiftByZero) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int i = (3 >> 0);\n" - " int j = (73 << 0);\n" - " my_FragColor = vec4(i, j, i, j);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(3)); - ASSERT_TRUE(constantFoundInAST(73)); -} - -// Test that folding IsInf results in true when the parameter is an out-of-range float literal. -// ESSL 3.00.6 section 4.1.4 Floats: -// "If the value of the floating point number is too large (small) to be stored as a single -// precision value, it is converted to positive (negative) infinity." -// ESSL 3.00.6 section 12.4: -// "Mandate support for signed infinities." -TEST_F(ConstantFoldingTest, FoldIsInfOutOfRangeFloatLiteral) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " bool b = isinf(1.0e2048);\n" - " my_FragColor = vec4(b);\n" - "}\n"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(true)); -} - -// Regression test case of unary + constant folding of a void struct member. -TEST_F(ConstantFoldingTest, VoidStructMember) -{ - constexpr const char *kShaderString = "struct U{void t;}n(){+U().t"; - ASSERT_FALSE(compile(kShaderString)); -} - -// Test that floats that are too small to be represented get flushed to zero. -// ESSL 3.00.6 section 4.1.4 Floats: -// "A value with a magnitude too small to be represented as a mantissa and exponent is converted to -// zero." -TEST_F(ConstantFoldingExpressionTest, FoldTooSmallFloat) -{ - const std::string &floatString = "1.0e-2048"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(0.0f)); -} - -// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. -// lim radians(x) x -> inf = inf -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldRadiansInfinity) -{ - const std::string &floatString = "radians(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. -// lim degrees(x) x -> inf = inf -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldDegreesInfinity) -{ - const std::string &floatString = "degrees(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that sinh(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldSinhInfinity) -{ - const std::string &floatString = "sinh(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that sinh(-inf) = -inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldSinhNegativeInfinity) -{ - const std::string &floatString = "sinh(-1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that cosh(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldCoshInfinity) -{ - const std::string &floatString = "cosh(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that cosh(-inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldCoshNegativeInfinity) -{ - const std::string &floatString = "cosh(-1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that asinh(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldAsinhInfinity) -{ - const std::string &floatString = "asinh(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that asinh(-inf) = -inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldAsinhNegativeInfinity) -{ - const std::string &floatString = "asinh(-1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that acosh(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldAcoshInfinity) -{ - const std::string &floatString = "acosh(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that pow or powr(0, inf) = 0. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldPowInfinity) -{ - const std::string &floatString = "pow(0.0, 1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(0.0f)); -} - -// IEEE 754 dictates that exp(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldExpInfinity) -{ - const std::string &floatString = "exp(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that exp(-inf) = 0. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldExpNegativeInfinity) -{ - const std::string &floatString = "exp(-1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(0.0f)); -} - -// IEEE 754 dictates that log(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldLogInfinity) -{ - const std::string &floatString = "log(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that exp2(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldExp2Infinity) -{ - const std::string &floatString = "exp2(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that exp2(-inf) = 0. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldExp2NegativeInfinity) -{ - const std::string &floatString = "exp2(-1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(0.0f)); -} - -// IEEE 754 dictates that log2(inf) = inf. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldLog2Infinity) -{ - const std::string &floatString = "log2(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. -// lim sqrt(x) x -> inf = inf -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldSqrtInfinity) -{ - const std::string &floatString = "sqrt(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that rSqrt(inf) = 0 -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldInversesqrtInfinity) -{ - const std::string &floatString = "inversesqrt(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(0.0f)); -} - -// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. -// lim length(x) x -> inf = inf -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldLengthInfinity) -{ - const std::string &floatString = "length(1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. -// lim dot(x, y) x -> inf, y > 0 = inf -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity) -{ - const std::string &floatString = "dot(1.0e2048, 1.0)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. -// lim dot(vec2(x, y), vec2(z)) x -> inf, finite y, z > 0 = inf -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity2) -{ - const std::string &floatString = "dot(vec2(1.0e2048, -1.0), vec2(1.0))"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// Faceforward behavior with infinity as a parameter can be derived from dot(). -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity) -{ - const std::string &floatString = "faceforward(4.0, 1.0e2048, 1.0)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-4.0f)); -} - -// Faceforward behavior with infinity as a parameter can be derived from dot(). -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity2) -{ - const std::string &floatString = "faceforward(vec2(4.0), vec2(1.0e2048, -1.0), vec2(1.0)).x"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-4.0f)); -} - -// Test that infinity - finite value evaluates to infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldInfinityMinusFinite) -{ - const std::string &floatString = "1.0e2048 - 1.0e20"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// Test that -infinity + finite value evaluates to -infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityPlusFinite) -{ - const std::string &floatString = "(-1.0e2048) + 1.0e20"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-std::numeric_limits::infinity())); -} - -// Test that infinity * finite value evaluates to infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByFinite) -{ - const std::string &floatString = "1.0e2048 * 1.0e-20"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// Test that infinity * infinity evaluates to infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByInfinity) -{ - const std::string &floatString = "1.0e2048 * 1.0e2048"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); -} - -// Test that infinity * negative infinity evaluates to negative infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByNegativeInfinity) -{ - const std::string &floatString = "1.0e2048 * (-1.0e2048)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-std::numeric_limits::infinity())); -} - -// Test that dividing by minus zero results in the appropriately signed infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -// "If both positive and negative zeros are implemented, the correctly signed Inf will be -// generated". -TEST_F(ConstantFoldingExpressionTest, FoldDivideByNegativeZero) -{ - const std::string &floatString = "1.0 / (-0.0)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-std::numeric_limits::infinity())); - ASSERT_TRUE(hasWarning()); -} - -// Test that infinity divided by zero evaluates to infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldInfinityDividedByZero) -{ - const std::string &floatString = "1.0e2048 / 0.0"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::infinity())); - ASSERT_TRUE(hasWarning()); -} - -// Test that negative infinity divided by zero evaluates to negative infinity. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityDividedByZero) -{ - const std::string &floatString = "(-1.0e2048) / 0.0"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-std::numeric_limits::infinity())); - ASSERT_TRUE(hasWarning()); -} - -// Test that dividing a finite number by infinity results in zero. -// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE". -TEST_F(ConstantFoldingExpressionTest, FoldDivideByInfinity) -{ - const std::string &floatString = "1.0e30 / 1.0e2048"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(0.0f)); -} - -// Test that unsigned bitfieldExtract is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract) -{ - const std::string &uintString = "bitfieldExtract(0x00110000u, 16, 5)"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(0x11u)); -} - -// Test that unsigned bitfieldExtract to extract 32 bits is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract32Bits) -{ - const std::string &uintString = "bitfieldExtract(0xff0000ffu, 0, 32)"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(0xff0000ffu)); -} - -// Test that signed bitfieldExtract is folded correctly. The higher bits should be set to 1 if the -// most significant bit of the extracted value is 1. -TEST_F(ConstantFoldingExpressionTest, FoldSignedBitfieldExtract) -{ - const std::string &intString = "bitfieldExtract(0x00110000, 16, 5)"; - evaluateInt(intString); - // 0xfffffff1 == -15 - ASSERT_TRUE(constantFoundInAST(-15)); -} - -// Test that bitfieldInsert is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert) -{ - const std::string &uintString = "bitfieldInsert(0x04501701u, 0x11u, 8, 5)"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(0x04501101u)); -} - -// Test that bitfieldInsert to insert 32 bits is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert32Bits) -{ - const std::string &uintString = "bitfieldInsert(0xff0000ffu, 0x11u, 0, 32)"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(0x11u)); -} - -// Test that bitfieldReverse is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldBitfieldReverse) -{ - const std::string &uintString = "bitfieldReverse((1u << 4u) | (1u << 7u))"; - evaluateUint(uintString); - uint32_t flag1 = 1u << (31u - 4u); - uint32_t flag2 = 1u << (31u - 7u); - ASSERT_TRUE(constantFoundInAST(flag1 | flag2)); -} - -// Test that bitCount is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldBitCount) -{ - const std::string &intString = "bitCount(0x17103121u)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(10)); -} - -// Test that findLSB is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldFindLSB) -{ - const std::string &intString = "findLSB(0x80010000u)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(16)); -} - -// Test that findLSB is folded correctly when the operand is zero. -TEST_F(ConstantFoldingExpressionTest, FoldFindLSBZero) -{ - const std::string &intString = "findLSB(0u)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(-1)); -} - -// Test that findMSB is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldFindMSB) -{ - const std::string &intString = "findMSB(0x01000008u)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(24)); -} - -// Test that findMSB is folded correctly when the operand is zero. -TEST_F(ConstantFoldingExpressionTest, FoldFindMSBZero) -{ - const std::string &intString = "findMSB(0u)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(-1)); -} - -// Test that findMSB is folded correctly for a negative integer. -// It is supposed to return the index of the most significant bit set to 0. -TEST_F(ConstantFoldingExpressionTest, FoldFindMSBNegativeInt) -{ - const std::string &intString = "findMSB(-8)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(2)); -} - -// Test that findMSB is folded correctly for -1. -TEST_F(ConstantFoldingExpressionTest, FoldFindMSBMinusOne) -{ - const std::string &intString = "findMSB(-1)"; - evaluateInt(intString); - ASSERT_TRUE(constantFoundInAST(-1)); -} - -// Test that packUnorm4x8 is folded correctly for a vector of zeroes. -TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8Zero) -{ - const std::string &intString = "packUnorm4x8(vec4(0.0))"; - evaluateUint(intString); - ASSERT_TRUE(constantFoundInAST(0u)); -} - -// Test that packUnorm4x8 is folded correctly for a vector of ones. -TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8One) -{ - const std::string &intString = "packUnorm4x8(vec4(1.0))"; - evaluateUint(intString); - ASSERT_TRUE(constantFoundInAST(0xffffffffu)); -} - -// Test that packSnorm4x8 is folded correctly for a vector of zeroes. -TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8Zero) -{ - const std::string &intString = "packSnorm4x8(vec4(0.0))"; - evaluateUint(intString); - ASSERT_TRUE(constantFoundInAST(0u)); -} - -// Test that packSnorm4x8 is folded correctly for a vector of ones. -TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8One) -{ - const std::string &intString = "packSnorm4x8(vec4(1.0))"; - evaluateUint(intString); - ASSERT_TRUE(constantFoundInAST(0x7f7f7f7fu)); -} - -// Test that packSnorm4x8 is folded correctly for a vector of minus ones. -TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8MinusOne) -{ - const std::string &intString = "packSnorm4x8(vec4(-1.0))"; - evaluateUint(intString); - ASSERT_TRUE(constantFoundInAST(0x81818181u)); -} - -// Test that unpackSnorm4x8 is folded correctly when it needs to clamp the result. -TEST_F(ConstantFoldingExpressionTest, FoldUnpackSnorm4x8Clamp) -{ - const std::string &floatString = "unpackSnorm4x8(0x00000080u).x"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(-1.0f)); -} - -// Test that unpackUnorm4x8 is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldUnpackUnorm4x8) -{ - const std::string &floatString = "unpackUnorm4x8(0x007bbeefu).z"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(123.0f / 255.0f)); -} - -// Test that ldexp is folded correctly. -TEST_F(ConstantFoldingExpressionTest, FoldLdexp) -{ - const std::string &floatString = "ldexp(0.625, 1)"; - evaluateFloat(floatString); - ASSERT_TRUE(constantFoundInAST(1.25f)); -} - -// Fold a ternary operator. -TEST_F(ConstantFoldingTest, FoldTernary) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp int; - uniform int u; - out int my_FragColor; - void main() - { - my_FragColor = (true ? 1 : u); - })"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(1)); - ASSERT_FALSE(symbolFoundInMain("u")); -} - -// Fold a ternary operator inside a consuming expression. -TEST_F(ConstantFoldingTest, FoldTernaryInsideExpression) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp int; - uniform int u; - out int my_FragColor; - void main() - { - my_FragColor = ivec2((true ? 1 : u) + 2, 4).x; - })"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(3)); - ASSERT_FALSE(symbolFoundInMain("u")); -} - -// Fold indexing into an array constructor. -TEST_F(ConstantFoldingExpressionTest, FoldArrayConstructorIndexing) -{ - const std::string &floatString = "(float[3](-1.0, 1.0, 2.0))[2]"; - evaluateFloat(floatString); - ASSERT_FALSE(constantFoundInAST(-1.0f)); - ASSERT_FALSE(constantFoundInAST(1.0f)); - ASSERT_TRUE(constantFoundInAST(2.0f)); -} - -// Fold indexing into an array of arrays constructor. -TEST_F(ConstantFoldingExpressionTest, FoldArrayOfArraysConstructorIndexing) -{ - const std::string &floatString = "(float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)))[1][0]"; - evaluateFloat(floatString); - ASSERT_FALSE(constantFoundInAST(-1.0f)); - ASSERT_FALSE(constantFoundInAST(1.0f)); - ASSERT_FALSE(constantFoundInAST(3.0f)); - ASSERT_TRUE(constantFoundInAST(2.0f)); -} - -// Fold indexing into a named constant array. -TEST_F(ConstantFoldingTest, FoldNamedArrayIndexing) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp float; - const float[3] arr = float[3](-1.0, 1.0, 2.0); - out float my_FragColor; - void main() - { - my_FragColor = arr[1]; - })"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(-1.0f)); - ASSERT_FALSE(constantFoundInAST(2.0f)); - ASSERT_TRUE(constantFoundInAST(1.0f)); - // The variable should be pruned out since after folding the indexing, there are no more - // references to it. - ASSERT_FALSE(symbolFoundInAST("arr")); -} - -// Fold indexing into a named constant array of arrays. -TEST_F(ConstantFoldingTest, FoldNamedArrayOfArraysIndexing) -{ - const std::string &shaderString = - R"(#version 310 es - precision highp float; - const float[2][2] arr = float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)); - out float my_FragColor; - void main() - { - my_FragColor = arr[0][1]; - })"; - compileAssumeSuccess(shaderString); - ASSERT_FALSE(constantFoundInAST(-1.0f)); - ASSERT_FALSE(constantFoundInAST(2.0f)); - ASSERT_FALSE(constantFoundInAST(3.0f)); - ASSERT_TRUE(constantFoundInAST(1.0f)); - // The variable should be pruned out since after folding the indexing, there are no more - // references to it. - ASSERT_FALSE(symbolFoundInAST("arr")); -} - -// Fold indexing into an array constructor where some of the arguments are constant and others are -// non-constant but without side effects. -TEST_F(ConstantFoldingTest, FoldArrayConstructorIndexingWithMixedArguments) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp float; - uniform float u; - out float my_FragColor; - void main() - { - my_FragColor = float[2](u, 1.0)[1]; - })"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(1.0f)); - ASSERT_FALSE(constantFoundInAST(1)); - ASSERT_FALSE(symbolFoundInMain("u")); -} - -// Indexing into an array constructor where some of the arguments have side effects can't be folded. -TEST_F(ConstantFoldingTest, CantFoldArrayConstructorIndexingWithSideEffects) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp float; - out float my_FragColor; - void main() - { - float sideEffectTarget = 0.0; - float f = float[3](sideEffectTarget = 1.0, 1.0, 2.0)[1]; - my_FragColor = f + sideEffectTarget; - })"; - compileAssumeSuccess(shaderString); - // All of the array constructor arguments should be present in the final AST. - ASSERT_TRUE(constantFoundInAST(1.0f)); - ASSERT_TRUE(constantFoundInAST(2.0f)); -} - -// Fold comparing two array constructors. -TEST_F(ConstantFoldingTest, FoldArrayConstructorEquality) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp float; - out float my_FragColor; - void main() - { - const bool b = (float[3](2.0, 1.0, -1.0) == float[3](2.0, 1.0, -1.0)); - my_FragColor = b ? 3.0 : 4.0; - })"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(3.0f)); - ASSERT_FALSE(constantFoundInAST(4.0f)); -} - -// Fold comparing two named constant arrays. -TEST_F(ConstantFoldingExpressionTest, FoldNamedArrayEquality) -{ - const std::string &shaderString = - R"(#version 300 es - precision highp float; - const float[3] arrA = float[3](-1.0, 1.0, 2.0); - const float[3] arrB = float[3](-1.0, 1.0, 2.0); - out float my_FragColor; - void main() - { - const bool b = (arrA == arrB); - my_FragColor = b ? 3.0 : 4.0; - })"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(3.0f)); - ASSERT_FALSE(constantFoundInAST(4.0f)); -} - -// Fold comparing two array of arrays constructors. -TEST_F(ConstantFoldingTest, FoldArrayOfArraysConstructorEquality) -{ - const std::string &shaderString = - R"(#version 310 es - precision highp float; - out float my_FragColor; - void main() - { - const bool b = (float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)) == - float[2][2](float[2](-1.0, 1.0), float[2](2.0, 1000.0))); - my_FragColor = b ? 4.0 : 5.0; - })"; - compileAssumeSuccess(shaderString); - ASSERT_TRUE(constantFoundInAST(5.0f)); - ASSERT_FALSE(constantFoundInAST(4.0f)); -} - -// Test that casting a negative float to uint results in a warning. ESSL 3.00.6 section 5.4.1 -// specifies this as an undefined conversion. -TEST_F(ConstantFoldingExpressionTest, FoldNegativeFloatToUint) -{ - const std::string &uintString = "uint(-1.0)"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::max())); - ASSERT_TRUE(hasWarning()); -} - -// Test that casting a negative float to uint inside a uvec constructor results in a warning. ESSL -// 3.00.6 section 5.4.1 specifies this as an undefined conversion. -TEST_F(ConstantFoldingExpressionTest, FoldNegativeFloatToUvec) -{ - const std::string &uintString = "uvec4(2.0, 1.0, vec2(0.0, -1.0)).w"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(std::numeric_limits::max())); - ASSERT_TRUE(hasWarning()); -} - -// Test that a negative float doesn't result in a warning when it is inside a constructor but isn't -// actually converted. -TEST_F(ConstantFoldingExpressionTest, NegativeFloatInsideUvecConstructorButOutOfRange) -{ - const std::string &uintString = "uvec2(1.0, vec2(0.0, -1.0)).x"; - evaluateUint(uintString); - ASSERT_FALSE(hasWarning()); -} - -// Test that a large float (above max int32_t) is converted to unsigned integer correctly. -TEST_F(ConstantFoldingExpressionTest, LargeFloatToUint) -{ - const std::string &uintString = "uint(3221225472.0)"; - evaluateUint(uintString); - ASSERT_TRUE(constantFoundInAST(3221225472u)); - ASSERT_FALSE(hasWarning()); -} - -// Test that folding % with a negative dividend generates a warning. -TEST_F(ConstantFoldingExpressionTest, IntegerModulusNegativeDividend) -{ - const std::string &intString = "(-5) % 3"; - evaluateInt(intString); - ASSERT_TRUE(hasWarning()); -} - -// Test that folding % with a negative divisor generates a warning. -TEST_F(ConstantFoldingExpressionTest, IntegerModulusNegativeDivisor) -{ - const std::string &intString = "5 % (-3)"; - evaluateInt(intString); - ASSERT_TRUE(hasWarning()); -} - -TEST_F(ConstantFoldingExpressionTest, IsnanDifferentComponents) -{ - const std::string &ivec4String = - "ivec4(mix(ivec2(2), ivec2(3), isnan(vec2(1.0, 0.0 / 0.0))), 4, 5)"; - evaluateIvec4(ivec4String); - int outputElements[] = {2, 3, 4, 5}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -TEST_F(ConstantFoldingExpressionTest, IsinfDifferentComponents) -{ - const std::string &ivec4String = - "ivec4(mix(ivec2(2), ivec2(3), isinf(vec2(0.0, 1.0e2048))), 4, 5)"; - evaluateIvec4(ivec4String); - int outputElements[] = {2, 3, 4, 5}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -TEST_F(ConstantFoldingExpressionTest, FloatBitsToIntDifferentComponents) -{ - const std::string &ivec4String = "ivec4(floatBitsToInt(vec2(0.0, 1.0)), 4, 5)"; - evaluateIvec4(ivec4String); - int outputElements[] = {0, 0x3f800000, 4, 5}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -TEST_F(ConstantFoldingExpressionTest, FloatBitsToUintDifferentComponents) -{ - const std::string &ivec4String = "ivec4(floatBitsToUint(vec2(0.0, 1.0)), 4, 5)"; - evaluateIvec4(ivec4String); - int outputElements[] = {0, 0x3f800000, 4, 5}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -TEST_F(ConstantFoldingExpressionTest, IntBitsToFloatDifferentComponents) -{ - const std::string &vec4String = "vec4(intBitsToFloat(ivec2(0, 0x3f800000)), 0.25, 0.5)"; - evaluateVec4(vec4String); - float outputElements[] = {0.0, 1.0, 0.25, 0.5}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} - -TEST_F(ConstantFoldingExpressionTest, UintBitsToFloatDifferentComponents) -{ - const std::string &vec4String = "vec4(uintBitsToFloat(uvec2(0U, 0x3f800000U)), 0.25, 0.5)"; - evaluateVec4(vec4String); - float outputElements[] = {0.0, 1.0, 0.25, 0.5}; - std::vector result(outputElements, outputElements + 4); - ASSERT_TRUE(constantVectorFoundInAST(result)); -} diff --git a/src/tests/compiler_tests/EXT_YUV_target_test.cpp b/src/tests/compiler_tests/EXT_YUV_target_test.cpp deleted file mode 100644 index a45cb9b3617..00000000000 --- a/src/tests/compiler_tests/EXT_YUV_target_test.cpp +++ /dev/null @@ -1,461 +0,0 @@ -// -// Copyright 2017 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. -// -// EXT_YUV_target.cpp: -// Test for EXT_YUV_target implementation. -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -namespace -{ -class EXTYUVTargetTest : public sh::ShaderExtensionTest -{ - public: - void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); } - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - DestroyCompiler(); - - mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), - shaderOutputType, &mResources); - ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; - } -}; - -const char EXTYTPragma[] = "#extension GL_EXT_YUV_target : require\n"; - -const char ESSL300_SimpleShader[] = - R"(precision mediump float; - uniform __samplerExternal2DY2YEXT uSampler; - out vec4 fragColor; - void main() { - fragColor = vec4(1.0); - })"; - -// Shader that samples the texture and writes to FragColor. -const char ESSL300_FragColorShader[] = - R"(precision mediump float; - uniform __samplerExternal2DY2YEXT uSampler; - layout(yuv) out vec4 fragColor; - void main() { - fragColor = texture(uSampler, vec2(0.0)); - })"; - -// Shader that samples the texture and swizzle and writes to FragColor. -const char ESSL300_textureSwizzleFragColorShader[] = - R"(precision mediump float; - uniform __samplerExternal2DY2YEXT uSampler; - layout(yuv) out vec4 fragColor; - void main() { - fragColor = vec4(texture(uSampler, vec2(0.0)).zyx, 1.0); - })"; - -// Shader that specifies yuv layout qualifier multiple times. -const char ESSL300_YUVQualifierMultipleTimesShader[] = - R"(precision mediump float; - layout(yuv, yuv, yuv) out vec4 fragColor; - void main() { - })"; - -// Shader that specifies yuv layout qualifier for not output fails to compile. -const char ESSL300_YUVQualifierFailureShader1[] = - R"(precision mediump float; - layout(yuv) in vec4 fragColor; - void main() { - })"; - -const char ESSL300_YUVQualifierFailureShader2[] = - R"(precision mediump float; - layout(yuv) uniform; - layout(yuv) uniform Transform { - mat4 M1; - }; - void main() { - })"; - -// Shader that specifies yuv layout qualifier with location fails to compile. -const char ESSL300_LocationAndYUVFailureShader[] = - R"(precision mediump float; - layout(location = 0, yuv) out vec4 fragColor; - void main() { - })"; - -// Shader that specifies yuv layout qualifier with multiple color outputs fails to compile. -const char ESSL300_MultipleColorAndYUVOutputsFailureShader1[] = - R"(precision mediump float; - layout(yuv) out vec4 fragColor; - layout out vec4 fragColor1; - void main() { - })"; - -const char ESSL300_MultipleColorAndYUVOutputsFailureShader2[] = - R"(precision mediump float; - layout(yuv) out vec4 fragColor; - layout(location = 1) out vec4 fragColor1; - void main() { - })"; - -// Shader that specifies yuv layout qualifier with depth output fails to compile. -const char ESSL300_DepthAndYUVOutputsFailureShader[] = - R"(precision mediump float; - layout(yuv) out vec4 fragColor; - void main() { - gl_FragDepth = 1.0f; - })"; - -// Shader that specifies yuv layout qualifier with multiple outputs fails to compile. -const char ESSL300_MultipleYUVOutputsFailureShader[] = - R"(precision mediump float; - layout(yuv) out vec4 fragColor; - layout(yuv) out vec4 fragColor1; - void main() { - })"; - -// Shader that specifies yuvCscStandartEXT type and associated values. -const char ESSL300_YuvCscStandardEXTShader[] = - R"(precision mediump float; - yuvCscStandardEXT; - yuvCscStandardEXT conv; - yuvCscStandardEXT conv1 = itu_601; - yuvCscStandardEXT conv2 = itu_601_full_range; - yuvCscStandardEXT conv3 = itu_709; - const yuvCscStandardEXT conv4 = itu_709; - - uniform int u; - out vec4 my_color; - - yuvCscStandardEXT conv_standard() - { - switch(u) - { - case 1: - return conv1; - case 2: - return conv2; - case 3: - return conv3; - default: - return conv; - } - } - bool is_itu_601(inout yuvCscStandardEXT csc) - { - csc = itu_601; - return csc == itu_601; - } - bool is_itu_709(yuvCscStandardEXT csc) - { - return csc == itu_709; - } - void main() - { - yuvCscStandardEXT conv = conv_standard(); - bool csc_check1 = is_itu_601(conv); - bool csc_check2 = is_itu_709(itu_709); - if (csc_check1 && csc_check2) { - my_color = vec4(0, 1, 0, 1); - } - })"; - -// Shader that specifies yuvCscStandardEXT type constructor fails to compile. -const char ESSL300_YuvCscStandardEXTConstructFailureShader1[] = - R"(precision mediump float; - yuvCscStandardEXT conv = yuvCscStandardEXT(); - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTConstructFailureShader2[] = - R"(precision mediump float; - yuvCscStandardEXT conv = yuvCscStandardEXT(itu_601); - void main() { - })"; - -// Shader that specifies yuvCscStandardEXT type conversion fails to compile. -const char ESSL300_YuvCscStandardEXTConversionFailureShader1[] = - R"(precision mediump float; - yuvCscStandardEXT conv = false; - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTConversionFailureShader2[] = - R"(precision mediump float; - yuvCscStandardEXT conv = 0; - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTConversionFailureShader3[] = - R"(precision mediump float; - yuvCscStandardEXT conv = 2.0f; - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTConversionFailureShader4[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601 | itu_709; - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTConversionFailureShader5[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601 & 3.0f; - void main() { - })"; - -// Shader that specifies yuvCscStandardEXT type qualifiers fails to compile. -const char ESSL300_YuvCscStandardEXTQualifiersFailureShader1[] = - R"(precision mediump float; - in yuvCscStandardEXT conv = itu_601; - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTQualifiersFailureShader2[] = - R"(precision mediump float; - out yuvCscStandardEXT conv = itu_601; - void main() { - })"; - -const char ESSL300_YuvCscStandardEXTQualifiersFailureShader3[] = - R"(precision mediump float; - uniform yuvCscStandardEXT conv = itu_601; - void main() { - })"; - -// Shader that specifies yuv_to_rgb() and rgb_to_yuv() built-in functions. -const char ESSL300_BuiltInFunctionsShader[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601; - - out vec4 my_color; - - void main() - { - vec3 yuv = rgb_2_yuv(vec3(0.0f), conv); - vec3 rgb = yuv_2_rgb(yuv, itu_601); - my_color = vec4(rgb, 1.0); - })"; - -// Shader with nested yuv_to_rgb() and rgb_to_yuv() built-in functions. -const char ESSL300_BuiltInFunctionsNested1Shader[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601; - - out vec4 my_color; - - void main() - { - vec3 rgb = yuv_2_rgb(rgb_2_yuv(vec3(0.0f), conv), conv); - my_color = vec4(rgb, 1.0); - })"; -const char ESSL300_BuiltInFunctionsNested2Shader[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601_full_range; - - out vec4 my_color; - - void main() - { - vec3 rgb = yuv_2_rgb(vec3(0.1) + rgb_2_yuv(vec3(0.0f), conv), conv); - my_color = vec4(rgb, 1.0); - })"; -const char ESSL300_BuiltInFunctionsNested3Shader[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_709; - - out vec4 my_color; - - vec3 f(vec3 v) { return v + vec3(0.1); } - - void main() - { - vec3 rgb = yuv_2_rgb(f(rgb_2_yuv(vec3(0.0f), conv)), conv); - my_color = vec4(rgb, 1.0); - })"; -const char ESSL300_BuiltInFunctionsNested4Shader[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601; - - out vec4 my_color; - - vec3 f(vec3 v) { return v + vec3(0.1); } - - void main() - { - vec3 rgb = f(yuv_2_rgb(f(rgb_2_yuv(vec3(0.0f), conv)), conv)); - my_color = vec4(rgb, 1.0); - })"; - -// Shader with yuv_to_rgb() and rgb_to_yuv() built-in functions with different precision. -const char ESSL300_BuiltInFunctionsPrecisionShader[] = - R"(precision mediump float; - yuvCscStandardEXT conv = itu_601; - - out vec4 my_color; - - void main() - { - lowp vec3 rgbLow = vec3(0.1); - mediump vec3 rgbMedium = vec3(0.2); - highp vec3 rgbHigh = vec3(0.3); - - lowp vec3 yuvLow = vec3(0.4); - mediump vec3 yuvMedium = vec3(0.5); - highp vec3 yuvHigh = vec3(0.6); - - my_color = vec4( - rgb_2_yuv(rgbLow, conv) - rgb_2_yuv(rgbMedium, conv) + rgb_2_yuv(rgbHigh, conv) - - yuv_2_rgb(yuvLow, conv) - yuv_2_rgb(yuvMedium, conv) + yuv_2_rgb(yuvHigh, conv), - 1.0); - })"; - -const char ESSL300_OverloadRgb2Yuv[] = - R"(precision mediump float; - float rgb_2_yuv(float x) { return x + 1.0; } - - in float i; - out float o; - - void main() - { - o = rgb_2_yuv(i); - })"; - -const char ESSL300_OverloadYuv2Rgb[] = - R"(precision mediump float; - float yuv_2_rgb(float x) { return x + 1.0; } - - in float i; - out float o; - - void main() - { - o = yuv_2_rgb(i); - })"; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTYUVTargetTest, CompileFailsWithoutExtension) -{ - mResources.EXT_YUV_target = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTYTPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTYUVTargetTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.EXT_YUV_target = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTYUVTargetTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.EXT_YUV_target = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTYTPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTYTPragma)); -} - -INSTANTIATE_TEST_SUITE_P(CorrectVariantsWithExtensionAndPragma, - EXTYUVTargetTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_SimpleShader, ESSL300_FragColorShader))); - -class EXTYUVTargetCompileSuccessTest : public EXTYUVTargetTest -{}; - -TEST_P(EXTYUVTargetCompileSuccessTest, CompileSucceeds) -{ - // Expect compile success. - mResources.EXT_YUV_target = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTYTPragma)); -} - -#ifdef ANGLE_ENABLE_VULKAN -// Test that YUV built-in emulation works on Vulkan -TEST_P(EXTYUVTargetCompileSuccessTest, CompileSucceedsWithExtensionAndPragmaOnVulkan) -{ - mResources.EXT_YUV_target = 1; - mCompileOptions.validateAST = 1; - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(EXTYTPragma)); -} -#endif - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTYUVTargetCompileSuccessTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_FragColorShader, - ESSL300_textureSwizzleFragColorShader, - ESSL300_YUVQualifierMultipleTimesShader, - ESSL300_YuvCscStandardEXTShader, - ESSL300_BuiltInFunctionsShader, - ESSL300_BuiltInFunctionsNested1Shader, - ESSL300_BuiltInFunctionsNested2Shader, - ESSL300_BuiltInFunctionsNested3Shader, - ESSL300_BuiltInFunctionsNested4Shader, - ESSL300_BuiltInFunctionsPrecisionShader))); - -class EXTYUVTargetCompileFailureTest : public EXTYUVTargetTest -{}; - -TEST_P(EXTYUVTargetCompileFailureTest, CompileFails) -{ - // Expect compile failure due to shader error, with shader having correct pragma. - mResources.EXT_YUV_target = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTYTPragma)); -} - -INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders, - EXTYUVTargetCompileFailureTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_YUVQualifierFailureShader1, - ESSL300_YUVQualifierFailureShader2, - ESSL300_LocationAndYUVFailureShader, - ESSL300_MultipleColorAndYUVOutputsFailureShader1, - ESSL300_MultipleColorAndYUVOutputsFailureShader2, - ESSL300_DepthAndYUVOutputsFailureShader, - ESSL300_MultipleYUVOutputsFailureShader, - ESSL300_YuvCscStandardEXTConstructFailureShader1, - ESSL300_YuvCscStandardEXTConstructFailureShader2, - ESSL300_YuvCscStandardEXTConversionFailureShader1, - ESSL300_YuvCscStandardEXTConversionFailureShader2, - ESSL300_YuvCscStandardEXTConversionFailureShader3, - ESSL300_YuvCscStandardEXTConversionFailureShader4, - ESSL300_YuvCscStandardEXTConversionFailureShader5, - ESSL300_YuvCscStandardEXTQualifiersFailureShader1, - ESSL300_YuvCscStandardEXTQualifiersFailureShader2, - ESSL300_YuvCscStandardEXTQualifiersFailureShader3))); - -class EXTYUVNotEnabledTest : public EXTYUVTargetTest -{}; - -TEST_P(EXTYUVNotEnabledTest, CanOverloadConversions) -{ - // Expect compile success with a shader that overloads functions in the EXT_YUV_target - // extension. - mResources.EXT_YUV_target = 0; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile("")); -} - -INSTANTIATE_TEST_SUITE_P(CoreESSL300Shaders, - EXTYUVNotEnabledTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_OverloadRgb2Yuv, ESSL300_OverloadYuv2Rgb))); - -} // namespace diff --git a/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp b/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp deleted file mode 100644 index abe66face64..00000000000 --- a/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp +++ /dev/null @@ -1,317 +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. -// -// EXT_blend_func_extended.cpp: -// Test for EXT_blend_func_extended_test -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -namespace -{ -const char EXTBFEPragma[] = "#extension GL_EXT_blend_func_extended : require\n"; - -const char ESSL100_SimpleShader1[] = - "precision mediump float;\n" - "void main() { \n" - " gl_FragColor = vec4(1.0);\n" - " gl_SecondaryFragColorEXT = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n" - "}\n"; - -// Shader that tests only the access to gl_MaxDualSourceDrawBuffersEXT. -const char ESSL100_MaxDualSourceAccessShader[] = - "precision mediump float;\n" - "void main() { gl_FragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10); }\n"; - -// Shader that writes to SecondaryFragData. -const char ESSL100_FragDataShader[] = - "#extension GL_EXT_draw_buffers : require\n" - "precision mediump float;\n" - "void main() {\n" - " gl_FragData[gl_MaxDrawBuffers - 1] = vec4(1.0);\n" - " gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1);\n" - "}\n"; - -// Shader that writes to SecondaryFragColor and SecondaryFragData does not compile. -const char ESSL100_ColorAndDataWriteFailureShader1[] = - "precision mediump float;\n" - "void main() {\n" - " gl_SecondaryFragColorEXT = vec4(1.0);\n" - " gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n" - "}\n"; - -// Shader that writes to FragColor and SecondaryFragData does not compile. -const char ESSL100_ColorAndDataWriteFailureShader2[] = - "precision mediump float;\n" - "void main() {\n" - " gl_FragColor = vec4(1.0);\n" - " gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n" - "}\n"; - -// Shader that writes to FragData and SecondaryFragColor. -const char ESSL100_ColorAndDataWriteFailureShader3[] = - "#extension GL_EXT_draw_buffers : require\n" - "precision mediump float;\n" - "void main() {\n" - " gl_SecondaryFragColorEXT = vec4(1.0);\n" - " gl_FragData[gl_MaxDrawBuffers] = vec4(0.1);\n" - "}\n"; - -// Dynamic indexing of SecondaryFragData is not allowed in WebGL 2.0. -const char ESSL100_IndexSecondaryFragDataWithNonConstantShader[] = - "precision mediump float;\n" - "void main() {\n" - " for (int i = 0; i < 2; ++i) {\n" - " gl_SecondaryFragDataEXT[true ? 0 : i] = vec4(0.0);\n" - " }\n" - "}\n"; - -// In GLSL version 300 es, the gl_MaxDualSourceDrawBuffersEXT is available. -const char ESSL300_MaxDualSourceAccessShader[] = - "precision mediump float;\n" - "layout(location = 0) out mediump vec4 fragColor;" - "void main() {\n" - " fragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n" - "}\n"; - -// In ES 3.0, the locations can be assigned through the API with glBindFragDataLocationIndexedEXT. -// It's fine to have a mix of specified and unspecified locations. -const char ESSL300_LocationAndUnspecifiedOutputShader[] = - "precision mediump float;\n" - "layout(location = 0) out mediump vec4 fragColor;" - "out mediump vec4 secondaryFragColor;" - "void main() {\n" - " fragColor = vec4(1.0);\n" - " secondaryFragColor = vec4(1.0);\n" - "}\n"; - -// It's also fine to leave locations completely unspecified. -const char ESSL300_TwoUnspecifiedLocationOutputsShader[] = - "precision mediump float;\n" - "out mediump vec4 fragColor;" - "out mediump vec4 secondaryFragColor;" - "void main() {\n" - " fragColor = vec4(1.0);\n" - " secondaryFragColor = vec4(1.0);\n" - "}\n"; - -// Shader that is specifies two outputs with the same location but different indexes is valid. -const char ESSL300_LocationIndexShader[] = - R"(precision mediump float; -layout(location = 0) out mediump vec4 fragColor; -layout(location = 0, index = 1) out mediump vec4 secondaryFragColor; -void main() { - fragColor = vec4(1); - secondaryFragColor = vec4(1); -})"; - -// Shader that specifies index layout qualifier but not location fails to compile. -const char ESSL300_LocationIndexFailureShader[] = - R"(precision mediump float; -layout(index = 0) out vec4 fragColor; -void main() { - fragColor = vec4(1.0); -})"; - -// Shader that specifies index layout qualifier multiple times fails to compile. -const char ESSL300_DoubleIndexFailureShader[] = - R"(precision mediump float; -layout(index = 0, location = 0, index = 1) out vec4 fragColor; -void main() { - fragColor = vec4(1.0); -})"; - -// Shader that specifies an output with out-of-bounds location -// for index 0 when another output uses index 1 is invalid. -const char ESSL300_Index0OutOfBoundsFailureShader[] = - R"(precision mediump float; -layout(location = 1, index = 0) out mediump vec4 fragColor; -layout(location = 0, index = 1) out mediump vec4 secondaryFragColor; -void main() { - fragColor = vec4(1); - secondaryFragColor = vec4(1); -})"; - -// Shader that specifies an output with out-of-bounds location for index 1 is invalid. -const char ESSL300_Index1OutOfBoundsFailureShader[] = - R"(precision mediump float; -layout(location = 1, index = 1) out mediump vec4 secondaryFragColor; -void main() { - secondaryFragColor = vec4(1); -})"; - -// Shader that specifies two outputs with the same location -// but different indices and different base types is invalid. -const char ESSL300_IndexTypeMismatchFailureShader[] = - R"(precision mediump float; -layout(location = 0, index = 0) out mediump vec4 fragColor; -layout(location = 0, index = 1) out mediump ivec4 secondaryFragColor; -void main() { - fragColor = vec4(1); - secondaryFragColor = ivec4(1); -})"; - -// Global index layout qualifier fails. -const char ESSL300_GlobalIndexFailureShader[] = - R"(precision mediump float; -layout(index = 0); -out vec4 fragColor; -void main() { - fragColor = vec4(1.0); -})"; - -// Index layout qualifier on a non-output variable fails. -const char ESSL300_IndexOnUniformVariableFailureShader[] = - R"(precision mediump float; -layout(index = 0) uniform vec4 u; -out vec4 fragColor; -void main() { - fragColor = u; -})"; - -// Index layout qualifier on a struct fails. -const char ESSL300_IndexOnStructFailureShader[] = - R"(precision mediump float; -layout(index = 0) struct S { - vec4 field; -}; -out vec4 fragColor; -void main() { - fragColor = vec4(1.0); -})"; - -// Index layout qualifier on a struct member fails. -const char ESSL300_IndexOnStructFieldFailureShader[] = - R"(precision mediump float; -struct S { - layout(index = 0) vec4 field; -}; -out mediump vec4 fragColor; -void main() { - fragColor = vec4(1.0); -})"; - -class EXTBlendFuncExtendedTest : public sh::ShaderExtensionTest -{ - protected: - void SetUp() override - { - sh::ShaderExtensionTest::SetUp(); - // EXT_draw_buffers is used in some of the shaders for test purposes. - mResources.EXT_draw_buffers = 1; - mResources.NV_draw_buffers = 2; - } -}; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithoutExtension) -{ - mResources.EXT_blend_func_extended = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTBFEPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.EXT_blend_func_extended = 1; - mResources.MaxDualSourceDrawBuffers = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTBlendFuncExtendedTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.EXT_blend_func_extended = 1; - mResources.MaxDualSourceDrawBuffers = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTBFEPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTBFEPragma)); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTBlendFuncExtendedTest, - Combine(Values(SH_GLES2_SPEC, SH_GLES3_SPEC), - Values("", sh::ESSLVersion100), - Values(ESSL100_SimpleShader1, - ESSL100_MaxDualSourceAccessShader, - ESSL100_FragDataShader))); - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTBlendFuncExtendedTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_MaxDualSourceAccessShader, - ESSL300_LocationAndUnspecifiedOutputShader, - ESSL300_TwoUnspecifiedLocationOutputsShader, - ESSL300_LocationIndexShader))); - -class EXTBlendFuncExtendedCompileFailureTest : public EXTBlendFuncExtendedTest -{}; - -TEST_P(EXTBlendFuncExtendedCompileFailureTest, CompileFails) -{ - // Expect compile failure due to shader error, with shader having correct pragma. - mResources.EXT_blend_func_extended = 1; - mResources.MaxDualSourceDrawBuffers = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTBFEPragma)); -} - -// Incorrect #version 100 shaders fail. -INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders, - EXTBlendFuncExtendedCompileFailureTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_ColorAndDataWriteFailureShader1, - ESSL100_ColorAndDataWriteFailureShader2, - ESSL100_ColorAndDataWriteFailureShader3))); - -// Correct #version 100 shaders that are incorrect in WebGL 2.0. -INSTANTIATE_TEST_SUITE_P(IncorrectESSL100ShadersWebGL2, - EXTBlendFuncExtendedCompileFailureTest, - Combine(Values(SH_WEBGL2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_IndexSecondaryFragDataWithNonConstantShader))); - -// Correct #version 300 es shaders fail in GLES2 context, regardless of version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTBlendFuncExtendedCompileFailureTest, - Combine(Values(SH_GLES2_SPEC), - Values("", sh::ESSLVersion100, sh::ESSLVersion300), - Values(ESSL300_LocationAndUnspecifiedOutputShader, - ESSL300_TwoUnspecifiedLocationOutputsShader))); - -// Correct #version 100 shaders fail when used with #version 300 es. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTBlendFuncExtendedCompileFailureTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL100_SimpleShader1, ESSL100_FragDataShader))); - -// Incorrect #version 300 es shaders always fail. -INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders, - EXTBlendFuncExtendedCompileFailureTest, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion300, sh::ESSLVersion310), - Values(ESSL300_LocationIndexFailureShader, - ESSL300_DoubleIndexFailureShader, - ESSL300_Index0OutOfBoundsFailureShader, - ESSL300_Index1OutOfBoundsFailureShader, - ESSL300_IndexTypeMismatchFailureShader, - ESSL300_GlobalIndexFailureShader, - ESSL300_IndexOnUniformVariableFailureShader, - ESSL300_IndexOnStructFailureShader, - ESSL300_IndexOnStructFieldFailureShader))); - -} // namespace diff --git a/src/tests/compiler_tests/EXT_clip_cull_distance_test.cpp b/src/tests/compiler_tests/EXT_clip_cull_distance_test.cpp deleted file mode 100644 index 842e6970e67..00000000000 --- a/src/tests/compiler_tests/EXT_clip_cull_distance_test.cpp +++ /dev/null @@ -1,532 +0,0 @@ -// -// Copyright 2020 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. -// -// EXT_clip_cull_distance_test.cpp: -// Test for EXT_clip_cull_distance -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -namespace -{ -const char EXTPragma[] = "#extension GL_EXT_clip_cull_distance : require\n"; - -const char ANGLEPragma[] = "#extension GL_ANGLE_clip_cull_distance : require\n"; - -// Shader using gl_ClipDistance and gl_CullDistance -const char VertexShaderCompileSucceeds1[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[1] = dot(aPosition, uPlane); - gl_CullDistance[1] = dot(aPosition, uPlane); - })"; - -// Shader redeclares gl_ClipDistance and gl_CullDistance -const char VertexShaderCompileSucceeds2[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - out highp float gl_ClipDistance[4]; - out highp float gl_CullDistance[4]; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); - gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); - gl_ClipDistance[gl_MaxCombinedClipAndCullDistances - 5] = dot(aPosition, uPlane); - gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane); - gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane); - })"; - -#if defined(ANGLE_ENABLE_VULKAN) -// Shader using gl_ClipDistance and gl_CullDistance -// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances -const char VertexShaderCompileFails1[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[5] = dot(aPosition, uPlane); - gl_CullDistance[4] = dot(aPosition, uPlane); - })"; - -// Shader redeclares gl_ClipDistance and gl_CullDistance -// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances -const char VertexShaderCompileFails2[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - out highp float gl_ClipDistance[5]; - out highp float gl_CullDistance[4]; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); - gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); - gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane); - gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane); - })"; - -// Shader redeclares gl_ClipDistance -// But, the array size is greater than gl_MaxClipDistances -const char VertexShaderCompileFails3[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - out highp float gl_ClipDistance[gl_MaxClipDistances + 1]; - - void main() - { - gl_Position = aPosition; - gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); - gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); - })"; - -// Access gl_CullDistance with integral constant index -// But, the index is greater than gl_MaxCullDistances -const char VertexShaderCompileFails4[] = - R"( - uniform vec4 uPlane; - - in vec4 aPosition; - - void main() - { - gl_Position = aPosition; - gl_CullDistance[gl_MaxCullDistances] = dot(aPosition, uPlane); - })"; - -// Simple ESSL1 vertex shader that should still fail because of incompatible -// #extension require -const char VertexShaderCompileFails5[] = - R"( - attribute vec4 aPosition; - - void main() - { - gl_Position = aPosition; - })"; -#endif - -// Shader using gl_ClipDistance and gl_CullDistance -const char FragmentShaderCompileSucceeds1[] = - R"( - out highp vec4 fragColor; - - void main() - { - fragColor = vec4(gl_ClipDistance[0], gl_CullDistance[0], 0, 1); - })"; - -// Shader redeclares gl_ClipDistance and gl_CullDistance -const char FragmentShaderCompileSucceeds2[] = - R"( - in highp float gl_ClipDistance[4]; - in highp float gl_CullDistance[4]; - - in highp vec4 aPosition; - - out highp vec4 fragColor; - - void main() - { - fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1]; - fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)]; - fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1]; - fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)]; - fragColor *= gl_CullDistance[gl_MaxCombinedClipAndCullDistances - 5]; - })"; - -#if defined(ANGLE_ENABLE_VULKAN) -// Shader using gl_ClipDistance and gl_CullDistance -// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances -const char FragmentShaderCompileFails1[] = - R"( - out highp vec4 fragColor; - - void main() - { - fragColor = vec4(gl_ClipDistance[4], gl_CullDistance[5], 0, 1); - })"; - -// Shader redeclares gl_ClipDistance and gl_CullDistance -// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances -const char FragmentShaderCompileFails2[] = - R"( - in highp float gl_ClipDistance[5]; - in highp float gl_CullDistance[4]; - - in highp vec4 aPosition; - - out highp vec4 fragColor; - - void main() - { - fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1]; - fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)]; - fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1]; - fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)]; - })"; - -// In fragment shader, writing to gl_ClipDistance should be denied. -const char FragmentShaderCompileFails3[] = - R"( - out highp vec4 fragColor; - - void main() - { - gl_ClipDistance[0] = 0.0f; - fragColor = vec4(1, gl_ClipDistance[0], 0, 1); - })"; - -// In fragment shader, writing to gl_CullDistance should be denied even if redeclaring it with the -// array size -const char FragmentShaderCompileFails4[] = - R"( - out highp vec4 fragColor; - - in highp float gl_CullDistance[1]; - - void main() - { - gl_CullDistance[0] = 0.0f; - fragColor = vec4(1, gl_CullDistance[0], 0, 1); - })"; - -// Accessing to gl_Clip/CullDistance with non-const index should be denied if the size of -// gl_Clip/CullDistance is not decided. -const char FragmentShaderCompileFails5[] = - R"( - out highp vec4 fragColor; - - void main() - { - medium float color[3]; - for(int i = 0 ; i < 3 ; i++) - { - color[i] = gl_CullDistance[i]; - } - fragColor = vec4(color[0], color[1], color[2], 1.0f); - })"; - -// In compute shader, redeclaring gl_ClipDistance should be denied. -const char ComputeShaderCompileFails1[] = - R"( - layout(local_size_x = 1) in; - highp float gl_ClipDistance[1]; - void main() {})"; - -// In compute shader, writing to gl_ClipDistance should be denied. -const char ComputeShaderCompileFails2[] = - R"( - layout(local_size_x = 1) in; - void main() { gl_ClipDistance[0] = 1.0; })"; - -// In compute shader, reading gl_ClipDistance should be denied. -const char ComputeShaderCompileFails3[] = - R"( - layout(local_size_x = 1) in; - void main() { highp float c = gl_ClipDistance[0]; })"; - -// In compute shader, redeclaring gl_CullDistance should be denied. -const char ComputeShaderCompileFails4[] = - R"( - layout(local_size_x = 1) in; - highp float gl_CullDistance[1]; - void main() {})"; - -// In compute shader, writing to gl_CullDistance should be denied. -const char ComputeShaderCompileFails5[] = - R"( - layout(local_size_x = 1) in; - void main() { gl_CullDistance[0] = 1.0; })"; - -// In compute shader, reading gl_CullDistance should be denied. -const char ComputeShaderCompileFails6[] = - R"( - layout(local_size_x = 1) in; - void main() { highp float c = gl_CullDistance[0]; })"; -#endif - -class EXTClipCullDistanceTest : public sh::ShaderExtensionTest -{ - public: - void InitializeCompiler(ShShaderOutput shaderOutputType, GLenum shaderType) - { - DestroyCompiler(); - - mCompiler = sh::ConstructCompiler(shaderType, testing::get<0>(GetParam()), shaderOutputType, - &mResources); - ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; - } - - testing::AssertionResult TestShaderCompile(const char *pragma) - { - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - - const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma, - testing::get<2>(GetParam())}; - bool success = sh::Compile(mCompiler, shaderStrings, 3, compileOptions); - if (success) - { - return ::testing::AssertionSuccess() << "Compilation success"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); - } - - void SetExtensionEnable(bool enable) - { - // GL_APPLE_clip_distance is implicitly enabled when GL_EXT_clip_cull_distance or - // GL_ANGLE_clip_cull_distance are enabled -#if defined(ANGLE_ENABLE_VULKAN) - mResources.APPLE_clip_distance = enable; -#endif - mResources.EXT_clip_cull_distance = enable; - - mResources.ANGLE_clip_cull_distance = enable; - } -}; - -class EXTClipCullDistanceForVertexShaderTest : public EXTClipCullDistanceTest -{ - public: - void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); } - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_VERTEX_SHADER); - } -}; - -class EXTClipCullDistanceForFragmentShaderTest : public EXTClipCullDistanceTest -{ - public: - void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); } - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_FRAGMENT_SHADER); - } -}; - -class EXTClipCullDistanceForComputeShaderTest : public EXTClipCullDistanceTest -{ - public: - void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); } - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_COMPUTE_SHADER); - } -}; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileFailsWithoutExtension) -{ - SetExtensionEnable(false); - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(ANGLEPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileFailsWithExtensionWithoutPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -#if defined(ANGLE_ENABLE_VULKAN) -// With extension flag and extension directive, compiling using TranslatorVulkan succeeds. -TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileSucceedsVulkan) -{ - SetExtensionEnable(true); - - mResources.MaxClipDistances = 8; - mResources.MaxCullDistances = 8; - mResources.MaxCombinedClipAndCullDistances = 8; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(ANGLEPragma)); - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(ANGLEPragma)); -} -#endif - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileFailsWithoutExtension) -{ - SetExtensionEnable(false); - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(ANGLEPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileFailsWithExtensionWithoutPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -#if defined(ANGLE_ENABLE_VULKAN) -// With extension flag and extension directive, compiling using TranslatorVulkan succeeds. -TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileSucceedsVulkan) -{ - SetExtensionEnable(true); - - mResources.MaxClipDistances = 8; - mResources.MaxCullDistances = 8; - mResources.MaxCombinedClipAndCullDistances = 8; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(ANGLEPragma)); - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(ANGLEPragma)); -} - -class EXTClipCullDistanceForVertexShaderCompileFailureTest - : public EXTClipCullDistanceForVertexShaderTest -{}; - -class EXTClipCullDistanceForFragmentShaderCompileFailureTest - : public EXTClipCullDistanceForFragmentShaderTest -{}; - -class EXTClipCullDistanceForComputeShaderCompileFailureTest - : public EXTClipCullDistanceForComputeShaderTest -{}; - -TEST_P(EXTClipCullDistanceForVertexShaderCompileFailureTest, CompileFails) -{ - SetExtensionEnable(true); - - mResources.MaxClipDistances = 8; - mResources.MaxCullDistances = 8; - mResources.MaxCombinedClipAndCullDistances = 8; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_FALSE(TestShaderCompile(ANGLEPragma)); -} - -TEST_P(EXTClipCullDistanceForFragmentShaderCompileFailureTest, CompileFails) -{ - SetExtensionEnable(true); - - mResources.MaxClipDistances = 8; - mResources.MaxCullDistances = 8; - mResources.MaxCombinedClipAndCullDistances = 8; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_FALSE(TestShaderCompile(ANGLEPragma)); -} - -// Test that the clip and cull distance built-ins are not defined for compute shaders. -TEST_P(EXTClipCullDistanceForComputeShaderCompileFailureTest, CompileFails) -{ - SetExtensionEnable(true); - - mResources.MaxClipDistances = 8; - mResources.MaxCullDistances = 8; - mResources.MaxCombinedClipAndCullDistances = 8; - - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_FALSE(TestShaderCompile(ANGLEPragma)); -} -#endif - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTClipCullDistanceForVertexShaderTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(VertexShaderCompileSucceeds1, - VertexShaderCompileSucceeds2))); - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTClipCullDistanceForFragmentShaderTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(FragmentShaderCompileSucceeds1, - FragmentShaderCompileSucceeds2))); - -// The corresponding TEST_Ps are defined only when ANGLE_ENABLE_VULKAN is -// defined. -#if defined(ANGLE_ENABLE_VULKAN) -INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders, - EXTClipCullDistanceForVertexShaderCompileFailureTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(VertexShaderCompileFails5))); - -INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders, - EXTClipCullDistanceForVertexShaderCompileFailureTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(VertexShaderCompileFails1, - VertexShaderCompileFails2, - VertexShaderCompileFails3, - VertexShaderCompileFails4))); - -INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders, - EXTClipCullDistanceForFragmentShaderCompileFailureTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(FragmentShaderCompileFails1, - FragmentShaderCompileFails2, - FragmentShaderCompileFails3, - FragmentShaderCompileFails4, - FragmentShaderCompileFails5))); - -INSTANTIATE_TEST_SUITE_P(IncorrectESSL310Shaders, - EXTClipCullDistanceForComputeShaderCompileFailureTest, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion310), - Values(ComputeShaderCompileFails1, - ComputeShaderCompileFails2, - ComputeShaderCompileFails3, - ComputeShaderCompileFails4, - ComputeShaderCompileFails5, - ComputeShaderCompileFails6))); -#endif - -} // anonymous namespace diff --git a/src/tests/compiler_tests/EXT_frag_depth_test.cpp b/src/tests/compiler_tests/EXT_frag_depth_test.cpp deleted file mode 100644 index c04f3711e94..00000000000 --- a/src/tests/compiler_tests/EXT_frag_depth_test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2018 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. -// -// EXT_frag_depth_test.cpp: -// Test for EXT_frag_depth -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -using EXTFragDepthTest = sh::ShaderExtensionTest; - -namespace -{ -const char EXTPragma[] = "#extension GL_EXT_frag_depth : require\n"; - -// Shader setting gl_FragDepthEXT -const char ESSL100_FragDepthShader[] = - - R"( - precision mediump float; - - void main() - { - gl_FragDepthEXT = 1.0; - })"; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTFragDepthTest, CompileFailsWithoutExtension) -{ - mResources.EXT_frag_depth = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTFragDepthTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.EXT_frag_depth = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTFragDepthTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.EXT_frag_depth = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTFragDepthTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_FragDepthShader))); - -} // anonymous namespace diff --git a/src/tests/compiler_tests/EXT_shader_framebuffer_fetch_test.cpp b/src/tests/compiler_tests/EXT_shader_framebuffer_fetch_test.cpp deleted file mode 100644 index 277b7bb29a5..00000000000 --- a/src/tests/compiler_tests/EXT_shader_framebuffer_fetch_test.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// -// Copyright 2020 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. -// -// EXT_shader_framebuffer_fetch_test.cpp: -// Test for EXT_shader_framebuffer_fetch and EXT_shader_framebuffer_fetch_non_coherent -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -namespace -{ -const char EXTPragma[] = "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"; - -// Redeclare gl_LastFragData with noncoherent qualifier -const char ESSL100_LastFragDataRedeclared1[] = - R"( - uniform highp vec4 u_color; - layout(noncoherent) highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; - - void main (void) - { - gl_FragColor = u_color + gl_LastFragData[0] + gl_LastFragData[2]; - })"; - -// Use inout variable with noncoherent qualifier -const char ESSL300_InOut[] = - R"( - layout(noncoherent, location = 0) inout highp vec4 o_color; - uniform highp vec4 u_color; - - void main (void) - { - o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f)); - })"; - -// Use inout variable with noncoherent qualifier and 3-components vector -const char ESSL300_InOut2[] = - R"( - layout(noncoherent, location = 0) inout highp vec3 o_color; - uniform highp vec3 u_color; - - void main (void) - { - o_color = clamp(o_color + u_color, vec3(0.0f), vec3(1.0f)); - })"; - -// Use inout variable with noncoherent qualifier and integer type qualifier -const char ESSL300_InOut3[] = - R"( - layout(noncoherent, location = 0) inout highp ivec4 o_color; - uniform highp ivec4 u_color; - - void main (void) - { - o_color = clamp(o_color + u_color, ivec4(0), ivec4(1)); - })"; - -// Use inout variable with noncoherent qualifier and unsigned integer type qualifier -const char ESSL300_InOut4[] = - R"( - layout(noncoherent, location = 0) inout highp uvec4 o_color; - uniform highp uvec4 u_color; - - void main (void) - { - o_color = clamp(o_color + u_color, uvec4(0), uvec4(1)); - })"; - -// Use inout variable with noncoherent qualifier and inout function parameter -const char ESSL300_InOut5[] = - R"( - layout(noncoherent, location = 0) inout highp vec4 o_color; - uniform highp vec4 u_color; - - void getClampValue(inout highp mat4 io_color, highp vec4 i_color) - { - io_color[0] = clamp(io_color[0] + i_color, vec4(0.0f), vec4(1.0f)); - } - - void main (void) - { - highp mat4 o_color_mat = mat4(0); - o_color_mat[0] = o_color; - getClampValue(o_color_mat, u_color); - o_color = o_color_mat[0]; - })"; - -// Use multiple inout variables with noncoherent qualifier -const char ESSL300_InOut6[] = - R"( - layout(noncoherent, location = 0) inout highp vec4 o_color0; - layout(noncoherent, location = 1) inout highp vec4 o_color1; - layout(noncoherent, location = 2) inout highp vec4 o_color2; - layout(noncoherent, location = 3) inout highp vec4 o_color3; - uniform highp vec4 u_color; - - void main (void) - { - o_color0 = clamp(o_color0 + u_color, vec4(0.0f), vec4(1.0f)); - o_color1 = clamp(o_color1 + u_color, vec4(0.0f), vec4(1.0f)); - o_color2 = clamp(o_color2 + u_color, vec4(0.0f), vec4(1.0f)); - o_color3 = clamp(o_color3 + u_color, vec4(0.0f), vec4(1.0f)); - })"; - -class EXTShaderFramebufferFetchNoncoherentTest : public sh::ShaderExtensionTest -{ - public: - void SetUp() override - { - std::map shaderOutputList = { - {SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"}, -#if defined(ANGLE_ENABLE_VULKAN) - {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"} -#endif - }; - - Initialize(shaderOutputList); - } - - void TearDown() override - { - for (auto shaderOutputType : mShaderOutputList) - { - DestroyCompiler(shaderOutputType.first); - } - } - - void Initialize(std::map &shaderOutputList) - { - mShaderOutputList = std::move(shaderOutputList); - - for (auto shaderOutputType : mShaderOutputList) - { - sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]); - mCompilerList[shaderOutputType.first] = nullptr; - } - } - - void DestroyCompiler(ShShaderOutput shaderOutputType) - { - if (mCompilerList[shaderOutputType]) - { - sh::Destruct(mCompilerList[shaderOutputType]); - mCompilerList[shaderOutputType] = nullptr; - } - } - - void InitializeCompiler() - { - for (auto shaderOutputType : mShaderOutputList) - { - InitializeCompiler(shaderOutputType.first); - } - } - - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - DestroyCompiler(shaderOutputType); - - mCompilerList[shaderOutputType] = - sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType, - &mResourceList[shaderOutputType]); - ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr) - << "Compiler for " << mShaderOutputList[shaderOutputType] - << " could not be constructed."; - } - - testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType, const char *pragma) - { - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - - const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma, - testing::get<2>(GetParam())}; - - bool success = - sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3, compileOptions); - if (success) - { - return ::testing::AssertionSuccess() - << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]); - } - - void TestShaderCompile(bool expectation, const char *pragma) - { - for (auto shaderOutputType : mShaderOutputList) - { - if (expectation) - { - EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma)); - } - else - { - EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma)); - } - } - } - - void SetExtensionEnable(bool enable) - { - for (auto shaderOutputType : mShaderOutputList) - { - mResourceList[shaderOutputType.first].MaxDrawBuffers = 8; - mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent = - enable; - } - } - - private: - std::map mShaderOutputList; - std::map mCompilerList; - std::map mResourceList; -}; - -class EXTShaderFramebufferFetchNoncoherentES100Test - : public EXTShaderFramebufferFetchNoncoherentTest -{}; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithoutExtension) -{ - SetExtensionEnable(false); - InitializeCompiler(); - TestShaderCompile(false, EXTPragma); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithExtensionWithoutPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(false, ""); -} - -class EXTShaderFramebufferFetchNoncoherentES300Test - : public EXTShaderFramebufferFetchNoncoherentTest -{}; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithoutExtension) -{ - SetExtensionEnable(false); - InitializeCompiler(); - TestShaderCompile(false, EXTPragma); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithExtensionWithoutPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(false, ""); -} - -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTShaderFramebufferFetchNoncoherentES100Test, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_LastFragDataRedeclared1))); - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTShaderFramebufferFetchNoncoherentES300Test, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_InOut, - ESSL300_InOut2, - ESSL300_InOut3, - ESSL300_InOut4, - ESSL300_InOut5, - ESSL300_InOut6))); - -#if defined(ANGLE_ENABLE_VULKAN) - -// Use gl_LastFragData without redeclaration of gl_LastFragData with noncoherent qualifier -const char ESSL100_LastFragDataWithoutRedeclaration[] = - R"( - uniform highp vec4 u_color; - - void main (void) - { - gl_FragColor = u_color + gl_LastFragData[0]; - })"; - -// Redeclare gl_LastFragData without noncoherent qualifier -const char ESSL100_LastFragDataRedeclaredWithoutNoncoherent[] = - R"( - uniform highp vec4 u_color; - highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; - - void main (void) - { - gl_FragColor = u_color + gl_LastFragData[0]; - })"; - -// Use inout variable without noncoherent qualifier -const char ESSL300_InOutWithoutNoncoherent[] = - R"( - layout(location = 0) inout highp vec4 o_color; - uniform highp vec4 u_color; - - void main (void) - { - o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f)); - })"; - -class EXTShaderFramebufferFetchNoncoherentSuccessTest - : public EXTShaderFramebufferFetchNoncoherentTest -{ - public: - void SetUp() override - { - std::map shaderOutputList = { - {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}}; - - Initialize(shaderOutputList); - } -}; - -class EXTShaderFramebufferFetchNoncoherentFailureTest - : public EXTShaderFramebufferFetchNoncoherentSuccessTest -{}; - -class EXTShaderFramebufferFetchNoncoherentES100SuccessTest - : public EXTShaderFramebufferFetchNoncoherentSuccessTest -{}; - -class EXTShaderFramebufferFetchNoncoherentES100FailureTest - : public EXTShaderFramebufferFetchNoncoherentFailureTest -{}; - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTShaderFramebufferFetchNoncoherentES100SuccessTest, CompileSucceedsWithExtensionAndPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma); - // Test reset functionality. - TestShaderCompile(false, ""); - TestShaderCompile(true, EXTPragma); -} - -// -TEST_P(EXTShaderFramebufferFetchNoncoherentES100FailureTest, CompileFailsWithoutNoncoherent) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(false, EXTPragma); -} - -class EXTShaderFramebufferFetchNoncoherentES300SuccessTest - : public EXTShaderFramebufferFetchNoncoherentSuccessTest -{}; - -class EXTShaderFramebufferFetchNoncoherentES300FailureTest - : public EXTShaderFramebufferFetchNoncoherentFailureTest -{}; - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTShaderFramebufferFetchNoncoherentES300SuccessTest, CompileSucceedsWithExtensionAndPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma); - // Test reset functionality. - TestShaderCompile(false, ""); - TestShaderCompile(true, EXTPragma); -} - -// -TEST_P(EXTShaderFramebufferFetchNoncoherentES300FailureTest, CompileFailsWithoutNoncoherent) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(false, EXTPragma); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTShaderFramebufferFetchNoncoherentES100SuccessTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_LastFragDataRedeclared1))); - -INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders, - EXTShaderFramebufferFetchNoncoherentES100FailureTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_LastFragDataWithoutRedeclaration, - ESSL100_LastFragDataRedeclaredWithoutNoncoherent))); - -INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders, - EXTShaderFramebufferFetchNoncoherentES300SuccessTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_InOut, - ESSL300_InOut2, - ESSL300_InOut3, - ESSL300_InOut4, - ESSL300_InOut5, - ESSL300_InOut6))); - -INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders, - EXTShaderFramebufferFetchNoncoherentES300FailureTest, - Combine(Values(SH_GLES3_SPEC), - Values(sh::ESSLVersion300), - Values(ESSL300_InOutWithoutNoncoherent))); -#endif - -} // anonymous namespace diff --git a/src/tests/compiler_tests/EXT_shader_texture_lod_test.cpp b/src/tests/compiler_tests/EXT_shader_texture_lod_test.cpp deleted file mode 100644 index 8aac5bd7d72..00000000000 --- a/src/tests/compiler_tests/EXT_shader_texture_lod_test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2018 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. -// -// EXT_shader_texture_lod_test.cpp: -// Test for EXT_shader_texture_lod -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -using EXTShaderTextureLodTest = sh::ShaderExtensionTest; - -namespace -{ -const char EXTPragma[] = "#extension GL_EXT_shader_texture_lod : require\n"; - -// Shader calling texture2DLodEXT() -const char ESSL100_TextureLodShader[] = - R"( - precision mediump float; - varying vec2 texCoord0v; - uniform float lod; - uniform sampler2D tex; - void main() - { - vec4 color = texture2DLodEXT(tex, texCoord0v, lod); - })"; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTShaderTextureLodTest, CompileFailsWithoutExtension) -{ - mResources.EXT_shader_texture_lod = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTShaderTextureLodTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.EXT_shader_texture_lod = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTShaderTextureLodTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.EXT_shader_texture_lod = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTShaderTextureLodTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_TextureLodShader))); - -} // anonymous namespace diff --git a/src/tests/compiler_tests/EXT_shadow_samplers_test.cpp b/src/tests/compiler_tests/EXT_shadow_samplers_test.cpp deleted file mode 100644 index c73f8d40b90..00000000000 --- a/src/tests/compiler_tests/EXT_shadow_samplers_test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2020 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. -// -// EXT_shadow_samplers_test.cpp: -// Test for EXT_shadow_samplers -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -using EXTShadowSamplersTest = sh::ShaderExtensionTest; - -namespace -{ -const char EXTPragma[] = "#extension GL_EXT_shadow_samplers : require\n"; - -// Shader calling shadow2DEXT() -const char ESSL100_ShadowSamplersShader[] = - R"( - precision mediump float; - varying vec3 texCoord0v; - uniform sampler2DShadow tex; - void main() - { - float color = shadow2DEXT(tex, texCoord0v); - })"; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(EXTShadowSamplersTest, CompileFailsWithoutExtension) -{ - mResources.EXT_shadow_samplers = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(EXTPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(EXTShadowSamplersTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.EXT_shadow_samplers = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(EXTShadowSamplersTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.EXT_shadow_samplers = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(EXTPragma)); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders, - EXTShadowSamplersTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_ShadowSamplersShader))); - -} // anonymous namespace \ No newline at end of file diff --git a/src/tests/compiler_tests/EmulateGLBaseVertexBaseInstance_test.cpp b/src/tests/compiler_tests/EmulateGLBaseVertexBaseInstance_test.cpp deleted file mode 100644 index 86543d3995b..00000000000 --- a/src/tests/compiler_tests/EmulateGLBaseVertexBaseInstance_test.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// -// Copyright 2019 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. -// -// ANGLE_base_vertex_base_instance.cpp: -// Test for ANGLE_base_vertex_base_instance extension -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" -#include "gtest/gtest.h" -#include "tests/test_utils/compiler_test.h" - -using namespace sh; - -class EmulateGLBaseVertexBaseInstanceTest : public MatchOutputCodeTest -{ - public: - EmulateGLBaseVertexBaseInstanceTest() - : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_GLSL_COMPATIBILITY_OUTPUT) - { - ShCompileOptions defaultCompileOptions = {}; - setDefaultCompileOptions(defaultCompileOptions); - - getResources()->ANGLE_base_vertex_base_instance_shader_builtin = 1; - } - - protected: - void CheckCompileFailure(const std::string &shaderString, - const char *expectedError = nullptr, - ShCompileOptions *compileOptions = nullptr) - { - ShCompileOptions options = {}; - if (compileOptions != nullptr) - { - options = *compileOptions; - } - - std::string translatedCode; - std::string infoLog; - bool success = - compileTestShader(GL_VERTEX_SHADER, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT, - shaderString, getResources(), options, &translatedCode, &infoLog); - EXPECT_FALSE(success); - if (expectedError) - { - EXPECT_TRUE(infoLog.find(expectedError) != std::string::npos); - } - } -}; - -// Check that compilation fails if the compile option to emulate gl_BaseVertex and gl_BaseInstance -// is not set -TEST_F(EmulateGLBaseVertexBaseInstanceTest, RequiresEmulation) -{ - CheckCompileFailure( - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" - "}\n", - "extension is not supported"); -} - -// Check that compiling with emulation with gl_BaseVertex and gl_BaseInstance works -TEST_F(EmulateGLBaseVertexBaseInstanceTest, CheckCompile) -{ - const std::string shaderString = - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLBaseVertexBaseInstance = true; - - compile(shaderString, compileOptions); -} - -// Check that compiling with the old extension doesn't work -TEST_F(EmulateGLBaseVertexBaseInstanceTest, CheckCompileOldExtension) -{ - const std::string shaderString = - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLBaseVertexBaseInstance = true; - - CheckCompileFailure(shaderString, "extension is not supported", &compileOptions); -} - -// Check that gl_BaseVertex and gl_BaseInstance is properly emulated -TEST_F(EmulateGLBaseVertexBaseInstanceTest, EmulatesUniform) -{ - addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); - addOutputType(SH_ESSL_OUTPUT); -#ifdef ANGLE_ENABLE_VULKAN - addOutputType(SH_SPIRV_VULKAN_OUTPUT); -#endif -#ifdef ANGLE_ENABLE_HLSL - addOutputType(SH_HLSL_3_0_OUTPUT); - addOutputType(SH_HLSL_3_0_OUTPUT); -#endif - - const std::string &shaderString = - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLBaseVertexBaseInstance = true; - - compile(shaderString, compileOptions); - - EXPECT_TRUE(notFoundInCode("gl_BaseVertex")); - EXPECT_TRUE(foundInCode("angle_BaseVertex")); - EXPECT_TRUE(notFoundInCode("gl_BaseInstance")); - EXPECT_TRUE(foundInCode("angle_BaseInstance")); - EXPECT_TRUE(notFoundInCode("GL_ANGLE_base_vertex_base_instance_shader_builtin")); - - EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseVertex")); - EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseInstance")); - EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseVertex")); - EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseInstance")); - -#ifdef ANGLE_ENABLE_HLSL - EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseVertex : register")); - EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseInstance : register")); -#endif -} - -// Check that a user-defined "gl_BaseVertex" or "gl_BaseInstance" is not permitted -TEST_F(EmulateGLBaseVertexBaseInstanceTest, DisallowsUserDefinedGLDrawID) -{ - // Check that it is not permitted without the extension - CheckCompileFailure( - "#version 300 es\n" - "uniform int gl_BaseVertex;\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#version 300 es\n" - "uniform int gl_BaseInstance;\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#version 300 es\n" - "void main() {\n" - " int gl_BaseVertex = 0;\n" - " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#version 300 es\n" - "void main() {\n" - " int gl_BaseInstance = 0;\n" - " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - // Check that it is not permitted with the extension - CheckCompileFailure( - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "uniform int gl_BaseVertex;\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "uniform int gl_BaseInstance;\n" - "void main() {\n" - " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "void main() {\n" - " int gl_BaseVertex = 0;\n" - " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "void main() {\n" - " int gl_BaseInstance = 0;\n" - " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); -} - -// gl_BaseVertex and gl_BaseInstance are translated to angle_BaseVertex and angle_BaseInstance -// internally. Check that a user-defined angle_BaseVertex or angle_BaseInstance is permitted -TEST_F(EmulateGLBaseVertexBaseInstanceTest, AllowsUserDefinedANGLEDrawID) -{ - addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); - addOutputType(SH_ESSL_OUTPUT); -#ifdef ANGLE_ENABLE_VULKAN - addOutputType(SH_SPIRV_VULKAN_OUTPUT); -#endif -#ifdef ANGLE_ENABLE_HLSL - addOutputType(SH_HLSL_3_0_OUTPUT); - addOutputType(SH_HLSL_3_0_OUTPUT); -#endif - - const std::string &shaderString = - "#version 300 es\n" - "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" - "uniform int angle_BaseVertex;\n" - "uniform int angle_BaseInstance;\n" - "void main() {\n" - " gl_Position = vec4(\n" - " float(angle_BaseVertex + gl_BaseVertex),\n" - " float(angle_BaseInstance + gl_BaseInstance),\n" - " 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLBaseVertexBaseInstance = true; - - compile(shaderString, compileOptions); - - // " angle_BaseVertex" (note the space) should appear exactly twice: - // once in the declaration and once in the body. - // The user-defined angle_BaseVertex should be decorated - EXPECT_TRUE(foundInCode(" angle_BaseVertex", 2)); - EXPECT_TRUE(foundInCode(" angle_BaseInstance", 2)); -} diff --git a/src/tests/compiler_tests/EmulateGLDrawID_test.cpp b/src/tests/compiler_tests/EmulateGLDrawID_test.cpp deleted file mode 100644 index 0ab1b64ef8f..00000000000 --- a/src/tests/compiler_tests/EmulateGLDrawID_test.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// -// Copyright 2018 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. -// -// ANGLE_draw_id.cpp: -// Test for ANGLE_draw_id extension -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" -#include "gtest/gtest.h" -#include "tests/test_utils/compiler_test.h" - -using namespace sh; - -class EmulateGLDrawIDTest : public MatchOutputCodeTest -{ - public: - EmulateGLDrawIDTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_GLSL_COMPATIBILITY_OUTPUT) - { - ShCompileOptions defaultCompileOptions = {}; - setDefaultCompileOptions(defaultCompileOptions); - - getResources()->ANGLE_multi_draw = 1; - } - - protected: - void CheckCompileFailure(const std::string &shaderString, const char *expectedError = nullptr) - { - ShCompileOptions compileOptions = {}; - - std::string translatedCode; - std::string infoLog; - bool success = compileTestShader(GL_VERTEX_SHADER, SH_GLES2_SPEC, - SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, getResources(), - compileOptions, &translatedCode, &infoLog); - EXPECT_FALSE(success); - if (expectedError) - { - EXPECT_TRUE(infoLog.find(expectedError) != std::string::npos); - } - } -}; - -// Check that compilation fails if the compile option to emulate gl_DrawID -// is not set -TEST_F(EmulateGLDrawIDTest, RequiresEmulation) -{ - CheckCompileFailure( - "#extension GL_ANGLE_multi_draw : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n", - "extension is not supported"); -} - -// Check that compiling with emulation with gl_DrawID works with different shader versions -TEST_F(EmulateGLDrawIDTest, CheckCompile) -{ - const std::string shaderString = - "#extension GL_ANGLE_multi_draw : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLDrawID = true; - - compile(shaderString, compileOptions); - compile("#version 100\n" + shaderString, compileOptions); - compile("#version 300 es\n" + shaderString, compileOptions); -} - -// Check that gl_DrawID is properly emulated -TEST_F(EmulateGLDrawIDTest, EmulatesUniform) -{ - addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); - addOutputType(SH_ESSL_OUTPUT); -#ifdef ANGLE_ENABLE_VULKAN - addOutputType(SH_SPIRV_VULKAN_OUTPUT); -#endif -#ifdef ANGLE_ENABLE_HLSL - addOutputType(SH_HLSL_3_0_OUTPUT); - addOutputType(SH_HLSL_3_0_OUTPUT); -#endif - - const std::string &shaderString = - "#extension GL_ANGLE_multi_draw : require\n" - "void main() {\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLDrawID = true; - compile(shaderString, compileOptions); - - EXPECT_TRUE(notFoundInCode("gl_DrawID")); - EXPECT_TRUE(foundInCode("angle_DrawID")); - EXPECT_TRUE(notFoundInCode("GL_ANGLE_multi_draw")); - - EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_DrawID")); - EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_DrawID")); - -#ifdef ANGLE_ENABLE_HLSL - EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register")); - EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register")); -#endif -} - -// Check that a user-defined "gl_DrawID" is not permitted -TEST_F(EmulateGLDrawIDTest, DisallowsUserDefinedGLDrawID) -{ - // Check that it is not permitted without the extension - CheckCompileFailure( - "uniform int gl_DrawID;\n" - "void main() {\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "void main() {\n" - " int gl_DrawID = 0;\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - // Check that it is not permitted with the extension - CheckCompileFailure( - "#extension GL_ANGLE_multi_draw : require\n" - "uniform int gl_DrawID;\n" - "void main() {\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); - - CheckCompileFailure( - "#extension GL_ANGLE_multi_draw : require\n" - "void main() {\n" - " int gl_DrawID = 0;\n" - " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n", - "reserved built-in name"); -} - -// gl_DrawID is translated to angle_DrawID internally. Check that a user-defined -// angle_DrawID is permitted -TEST_F(EmulateGLDrawIDTest, AllowsUserDefinedANGLEDrawID) -{ - addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); - addOutputType(SH_ESSL_OUTPUT); -#ifdef ANGLE_ENABLE_VULKAN - addOutputType(SH_SPIRV_VULKAN_OUTPUT); -#endif -#ifdef ANGLE_ENABLE_HLSL - addOutputType(SH_HLSL_3_0_OUTPUT); - addOutputType(SH_HLSL_3_0_OUTPUT); -#endif - - const std::string &shaderString = - "#extension GL_ANGLE_multi_draw : require\n" - "uniform int angle_DrawID;\n" - "void main() {\n" - " gl_Position = vec4(float(angle_DrawID + gl_DrawID), 0.0, 0.0, 1.0);\n" - "}\n"; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - compileOptions.emulateGLDrawID = true; - compile(shaderString, compileOptions); - - // " angle_DrawID" (note the space) should appear exactly twice: - // once in the declaration and once in the body. - // The user-defined angle_DrawID should be decorated - EXPECT_TRUE(foundInCode(" angle_DrawID", 2)); -} diff --git a/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp b/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp deleted file mode 100644 index 1a93333c69a..00000000000 --- a/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2016 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. -// -// EmulateGLFragColorBroadcast_test.cpp: -// Tests for gl_FragColor broadcast behavior emulation. -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/compiler_test.h" - -using namespace sh; - -namespace -{ - -const int kMaxDrawBuffers = 2; - -class EmulateGLFragColorBroadcastTest : public MatchOutputCodeTest -{ - public: - EmulateGLFragColorBroadcastTest() - : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_GLSL_COMPATIBILITY_OUTPUT) - { - getResources()->MaxDrawBuffers = kMaxDrawBuffers; - getResources()->EXT_draw_buffers = 1; - } -}; - -// Verifies that without explicitly enabling GL_EXT_draw_buffers extension -// in the shader, no broadcast emulation. -TEST_F(EmulateGLFragColorBroadcastTest, FragColorNoBroadcast) -{ - const std::string shaderString = - "void main()\n" - "{\n" - " gl_FragColor = vec4(1, 0, 0, 0);\n" - "}\n"; - compile(shaderString); - EXPECT_TRUE(foundInCode("gl_FragColor")); - EXPECT_FALSE(foundInCode("gl_FragData[0]")); - EXPECT_FALSE(foundInCode("gl_FragData[1]")); -} - -// Verifies that with explicitly enabling GL_EXT_draw_buffers extension -// in the shader, broadcast is emualted by replacing gl_FragColor with gl_FragData. -TEST_F(EmulateGLFragColorBroadcastTest, FragColorBroadcast) -{ - const std::string shaderString = - "#extension GL_EXT_draw_buffers : require\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(1, 0, 0, 0);\n" - "}\n"; - compile(shaderString); - EXPECT_FALSE(foundInCode("gl_FragColor")); - EXPECT_TRUE(foundInCode("gl_FragData[0]")); - EXPECT_TRUE(foundInCode("gl_FragData[1]")); -} - -// Verifies that with explicitly enabling GL_EXT_draw_buffers extension -// in the shader with an empty main(), anothing happens. -TEST_F(EmulateGLFragColorBroadcastTest, EmptyMain) -{ - const std::string shaderString = - "#extension GL_EXT_draw_buffers : require\n" - "void main()\n" - "{\n" - "}\n"; - compile(shaderString); - EXPECT_FALSE(foundInCode("gl_FragColor")); - EXPECT_FALSE(foundInCode("gl_FragData[0]")); - EXPECT_FALSE(foundInCode("gl_FragData[1]")); -} - -} // namespace diff --git a/src/tests/compiler_tests/ExpressionLimit_test.cpp b/src/tests/compiler_tests/ExpressionLimit_test.cpp index e17eace1b4b..e59b5b4c196 100644 --- a/src/tests/compiler_tests/ExpressionLimit_test.cpp +++ b/src/tests/compiler_tests/ExpressionLimit_test.cpp @@ -3,6 +3,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include #include @@ -236,7 +241,6 @@ constexpr char kExpressionTooComplex[] = "Expression too complex"; constexpr char kCallStackTooDeep[] = "Call stack too deep"; constexpr char kHasRecursion[] = "Recursive function call in the following call chain"; constexpr char kTooManyParameters[] = "Function has too many parameters"; -constexpr char kTooComplexSwitch[] = "too complex expressions inside a switch statement"; constexpr char kGlobalVariableInit[] = "global variable initializers must be constant expressions"; constexpr char kTooManyFields[] = "Too many fields in the struct"; @@ -583,7 +587,7 @@ TEST_F(ExpressionLimitTest, NestingInsideSwitch) // gracefully. EXPECT_TRUE(CheckShaderCompilation(compiler, GenerateShaderWithNestingInsideSwitch(5000).c_str(), - compileOptions, kTooComplexSwitch)); + compileOptions, kExpressionTooComplex)); // Test nesting over the limit without limit does not fail. compileOptions.limitExpressionComplexity = false; EXPECT_TRUE(CheckShaderCompilation( diff --git a/src/tests/compiler_tests/ExtensionDirective_test.cpp b/src/tests/compiler_tests/ExtensionDirective_test.cpp deleted file mode 100644 index 6e69b6e9932..00000000000 --- a/src/tests/compiler_tests/ExtensionDirective_test.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// Copyright 2017 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. -// -// ExtensionDirective_test.cpp: -// Miscellaneous tests for extension directives toggling functionality correctly. -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class FragmentShaderExtensionDirectiveTest : public ShaderCompileTreeTest -{ - public: - FragmentShaderExtensionDirectiveTest() {} - - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } - - void testCompileNeedsExtensionDirective(const std::string &shader, const std::string &extension) - { - testCompileNeedsExtensionDirective(shader, extension, ""); - } - - void testCompileNeedsExtensionDirective(const std::string &shader, - const std::string &extension, - const std::string &versionDirective) - { - if (compile(versionDirective + shader)) - { - FAIL() - << "Shader compilation without extension directive succeeded, expecting failure:\n" - << mInfoLog; - } - if (compile(versionDirective + getExtensionDirective(extension, sh::EBhDisable) + shader)) - { - FAIL() << "Shader compilation with extension disable directive succeeded, expecting " - "failure:\n" - << mInfoLog; - } - if (!compile(versionDirective + getExtensionDirective(extension, sh::EBhEnable) + shader)) - { - FAIL() - << "Shader compilation with extension enable directive failed, expecting success:\n" - << mInfoLog; - } - - if (!compile(versionDirective + getExtensionDirective(extension, sh::EBhWarn) + shader)) - { - FAIL() - << "Shader compilation with extension warn directive failed, expecting success:\n" - << mInfoLog; - } - else if (!hasWarning()) - { - FAIL() << "Expected compilation to succeed with warning, but warning not present:\n" - << mInfoLog; - } - } - - private: - std::string getExtensionDirective(const std::string &extension, sh::TBehavior behavior) - { - std::string extensionDirective("#extension "); - extensionDirective += extension + " : "; - switch (behavior) - { - case EBhRequire: - extensionDirective += "require"; - break; - case EBhEnable: - extensionDirective += "enable"; - break; - case EBhWarn: - extensionDirective += "warn"; - break; - case EBhDisable: - extensionDirective += "disable"; - break; - default: - break; - } - extensionDirective += "\n"; - return extensionDirective; - } -}; - -class OESEGLImageExternalExtensionTest : public FragmentShaderExtensionDirectiveTest -{ - public: - OESEGLImageExternalExtensionTest() {} - - protected: - void initResources(ShBuiltInResources *resources) override - { - resources->OES_EGL_image_external = 1; - } -}; - -// OES_EGL_image_external needs to be enabled in GLSL to be able to use samplerExternalOES. -TEST_F(OESEGLImageExternalExtensionTest, SamplerExternalOESUsageNeedsExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - - uniform samplerExternalOES s; - void main() - {})"; - testCompileNeedsExtensionDirective(shaderString, "GL_OES_EGL_image_external"); -} - -class NVEGLStreamConsumerExternalExtensionTest : public FragmentShaderExtensionDirectiveTest -{ - public: - NVEGLStreamConsumerExternalExtensionTest() {} - - protected: - void initResources(ShBuiltInResources *resources) override - { - resources->NV_EGL_stream_consumer_external = 1; - } -}; - -// NV_EGL_stream_consumer_external needs to be enabled in GLSL to be able to use samplerExternalOES. -TEST_F(NVEGLStreamConsumerExternalExtensionTest, SamplerExternalOESUsageNeedsExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - - uniform samplerExternalOES s; - void main() - {})"; - testCompileNeedsExtensionDirective(shaderString, "GL_NV_EGL_stream_consumer_external"); -} - -class EXTYUVTargetExtensionTest : public FragmentShaderExtensionDirectiveTest -{ - public: - EXTYUVTargetExtensionTest() {} - - protected: - void initResources(ShBuiltInResources *resources) override { resources->EXT_YUV_target = 1; } -}; - -// GL_EXT_YUV_target needs to be enabled in GLSL to be able to use samplerExternal2DY2YEXT. -TEST_F(EXTYUVTargetExtensionTest, SamplerExternal2DY2YEXTUsageNeedsExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - - uniform __samplerExternal2DY2YEXT s; - void main() - {})"; - testCompileNeedsExtensionDirective(shaderString, "GL_EXT_YUV_target", "#version 300 es\n"); -} - -// GL_EXT_YUV_target needs to be enabled in GLSL to be able to use samplerExternal2DY2YEXT. -TEST_F(EXTYUVTargetExtensionTest, YUVLayoutNeedsExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - - layout(yuv) out vec4 color; - void main() - {})"; - testCompileNeedsExtensionDirective(shaderString, "GL_EXT_YUV_target", "#version 300 es\n"); -} diff --git a/src/tests/compiler_tests/FloatLex_test.cpp b/src/tests/compiler_tests/FloatLex_test.cpp index f4d4db0145c..07bb6948df3 100644 --- a/src/tests/compiler_tests/FloatLex_test.cpp +++ b/src/tests/compiler_tests/FloatLex_test.cpp @@ -24,7 +24,7 @@ class StrtofClampParser static float Parse(std::string str) { float value; - sh::strtof_clamp(str, &value); + sh::strtof_clamp(str, &value, true); return value; } }; @@ -32,7 +32,10 @@ class StrtofClampParser class NumericLexFloatParser { public: - static float Parse(std::string str) { return sh::NumericLexFloat32OutOfRangeToInfinity(str); } + static float Parse(std::string str) + { + return sh::NumericLexFloat32OutOfRangeToInfinity(str, true); + } }; } // anonymous namespace @@ -214,3 +217,15 @@ TYPED_TEST(FloatLexTest, ExponentBitAboveMinIntAndSmallMantissa) ss << "0." << TestFixture::Zeros(32) << "1e-2147483640"; ASSERT_TRUE(TestFixture::ParsedMatches(ss.str(), 0.0f)); } + +// Ensure the smallest possible denorm float value is preserved +TYPED_TEST(FloatLexTest, SmallestPossibleDenormFloat) +{ + ASSERT_TRUE(TestFixture::ParsedMatches("1.40129846e-45", 1.40129846e-45f)); +} + +// Ensure the largest possible denorm float value is preserved +TYPED_TEST(FloatLexTest, LargestPossibleDenormFloat) +{ + ASSERT_TRUE(TestFixture::ParsedMatches("1.1754942107e-38", 1.1754942107e-38f)); +} diff --git a/src/tests/compiler_tests/FragDepth_test.cpp b/src/tests/compiler_tests/FragDepth_test.cpp deleted file mode 100644 index 9fe4a9f70ec..00000000000 --- a/src/tests/compiler_tests/FragDepth_test.cpp +++ /dev/null @@ -1,108 +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. -// -// FragDepth_test.cpp: -// Test for GLES SL 3.0 gl_FragDepth variable implementation. -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" - -namespace -{ -const char ESSLVersion100[] = "#version 100\n"; -const char ESSLVersion300[] = "#version 300 es\n"; -const char EXTFDPragma[] = "#extension GL_EXT_frag_depth : require\n"; -} // namespace - -class FragDepthTest : public testing::TestWithParam -{ - protected: - void SetUp() override - { - sh::InitBuiltInResources(&mResources); - mCompiler = nullptr; - mResources.EXT_frag_depth = GetParam(); - } - - void TearDown() override { DestroyCompiler(); } - void DestroyCompiler() - { - if (mCompiler) - { - sh::Destruct(mCompiler); - mCompiler = nullptr; - } - } - - void InitializeCompiler() - { - DestroyCompiler(); - mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES3_SPEC, - SH_GLSL_COMPATIBILITY_OUTPUT, &mResources); - ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; - } - - testing::AssertionResult TestShaderCompile(const char *version, - const char *pragma, - const char *shader) - { - const char *shaderStrings[] = {version, pragma, shader}; - bool success = sh::Compile(mCompiler, shaderStrings, 3, {}); - if (success) - { - return ::testing::AssertionSuccess() << "Compilation success"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); - } - - protected: - ShBuiltInResources mResources; - ShHandle mCompiler; -}; - -// The GLES SL 3.0 built-in variable gl_FragDepth fails to compile with GLES SL 1.0. -TEST_P(FragDepthTest, CompileFailsESSL100) -{ - static const char shaderString[] = - "precision mediump float;\n" - "void main() { \n" - " gl_FragDepth = 1.0;\n" - "}\n"; - - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(ESSLVersion100, "", shaderString)); - EXPECT_FALSE(TestShaderCompile("", "", shaderString)); - EXPECT_FALSE(TestShaderCompile("", EXTFDPragma, shaderString)); -} - -// The GLES SL 3.0 built-in variable gl_FragDepth compiles with GLES SL 3.0. -TEST_P(FragDepthTest, CompileSucceedsESSL300) -{ - static const char shaderString[] = - "precision mediump float;\n" - "void main() { \n" - " gl_FragDepth = 1.0;\n" - "}\n"; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(ESSLVersion300, "", shaderString)); -} - -// Using #extension GL_EXT_frag_depth in GLSL ES 3.0 shader fails to compile. -TEST_P(FragDepthTest, ExtensionFDFailsESSL300) -{ - static const char shaderString[] = - "precision mediump float;\n" - "out vec4 fragColor;\n" - "void main() { \n" - " fragColor = vec4(1.0);\n" - "}\n"; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(ESSLVersion300, EXTFDPragma, shaderString)); -} - -// The tests should pass regardless whether the EXT_frag_depth is on or not. -INSTANTIATE_TEST_SUITE_P(FragDepthTests, FragDepthTest, testing::Values(false, true)); diff --git a/src/tests/compiler_tests/ImmutableString_test.cpp b/src/tests/compiler_tests/ImmutableString_test.cpp index 23ddd6ea760..7ca41e3f03a 100644 --- a/src/tests/compiler_tests/ImmutableString_test.cpp +++ b/src/tests/compiler_tests/ImmutableString_test.cpp @@ -20,14 +20,13 @@ class ImmutableStringBuilderTest : public testing::Test protected: void SetUp() override { - allocator.push(); SetGlobalPoolAllocator(&allocator); } void TearDown() override { SetGlobalPoolAllocator(nullptr); - allocator.pop(); + allocator.reset(); } angle::PoolAllocator allocator; diff --git a/src/tests/compiler_tests/ImmutableString_test_autogen.cpp b/src/tests/compiler_tests/ImmutableString_test_autogen.cpp index 1dacd2b152d..75319bd1b2e 100644 --- a/src/tests/compiler_tests/ImmutableString_test_autogen.cpp +++ b/src/tests/compiler_tests/ImmutableString_test_autogen.cpp @@ -514,7 +514,7 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x000001efu, ImmutableString("texture2DProjGradEXT(00H20B10B10B").mangledNameHash()); ASSERT_EQ(0x000001f0u, ImmutableString("texture2DProjGradEXT(00H30B10B10B").mangledNameHash()); ASSERT_EQ(0x000001f1u, ImmutableString("textureCubeGradEXT(00J20B20B20B").mangledNameHash()); - ASSERT_EQ(0x000001f2u, ImmutableString("textureVideoWEBGL(00p10B").mangledNameHash()); + ASSERT_EQ(0x000001f2u, ImmutableString("textureVideoWEBGL(00o10B").mangledNameHash()); ASSERT_EQ(0x000001f3u, ImmutableString("texture2D(00H10B00B").mangledNameHash()); ASSERT_EQ(0x000001f4u, ImmutableString("texture2DProj(00H20B00B").mangledNameHash()); ASSERT_EQ(0x000001f5u, ImmutableString("texture2DProj(00H30B00B").mangledNameHash()); @@ -547,13 +547,13 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x00000210u, ImmutableString("texture(00d30B").mangledNameHash()); ASSERT_EQ(0x00000211u, ImmutableString("texture(00e30B").mangledNameHash()); ASSERT_EQ(0x00000212u, ImmutableString("texture(00g30B").mangledNameHash()); - ASSERT_EQ(0x00000213u, ImmutableString("texture(00l30B").mangledNameHash()); - ASSERT_EQ(0x00000214u, ImmutableString("texture(00o30B").mangledNameHash()); + ASSERT_EQ(0x00000213u, ImmutableString("texture(00k30B").mangledNameHash()); + ASSERT_EQ(0x00000214u, ImmutableString("texture(00n30B").mangledNameHash()); ASSERT_EQ(0x00000215u, ImmutableString("texture(00h30B00B").mangledNameHash()); ASSERT_EQ(0x00000216u, ImmutableString("texture(00L10B").mangledNameHash()); ASSERT_EQ(0x00000217u, ImmutableString("texture(00M10B").mangledNameHash()); ASSERT_EQ(0x00000218u, ImmutableString("texture(00N10B").mangledNameHash()); - ASSERT_EQ(0x00000219u, ImmutableString("texture(00p10B").mangledNameHash()); + ASSERT_EQ(0x00000219u, ImmutableString("texture(00o10B").mangledNameHash()); ASSERT_EQ(0x0000021au, ImmutableString("textureProj(00H20B").mangledNameHash()); ASSERT_EQ(0x0000021bu, ImmutableString("textureProj(00Q20B").mangledNameHash()); ASSERT_EQ(0x0000021cu, ImmutableString("textureProj(00W20B").mangledNameHash()); @@ -587,8 +587,8 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x00000238u, ImmutableString("textureLod(00e30B00B").mangledNameHash()); ASSERT_EQ(0x00000239u, ImmutableString("textureLod(00h30B00B00B").mangledNameHash()); ASSERT_EQ(0x0000023au, ImmutableString("textureLod(00g30B00B").mangledNameHash()); - ASSERT_EQ(0x0000023bu, ImmutableString("textureLod(00l30B00B").mangledNameHash()); - ASSERT_EQ(0x0000023cu, ImmutableString("textureLod(00o30B00B").mangledNameHash()); + ASSERT_EQ(0x0000023bu, ImmutableString("textureLod(00k30B00B").mangledNameHash()); + ASSERT_EQ(0x0000023cu, ImmutableString("textureLod(00n30B00B").mangledNameHash()); ASSERT_EQ(0x0000023du, ImmutableString("textureSize(00H00C").mangledNameHash()); ASSERT_EQ(0x0000023eu, ImmutableString("textureSize(00Q00C").mangledNameHash()); ASSERT_EQ(0x0000023fu, ImmutableString("textureSize(00W00C").mangledNameHash()); @@ -605,12 +605,12 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x0000024au, ImmutableString("textureSize(00d00C").mangledNameHash()); ASSERT_EQ(0x0000024bu, ImmutableString("textureSize(00e00C").mangledNameHash()); ASSERT_EQ(0x0000024cu, ImmutableString("textureSize(00g00C").mangledNameHash()); - ASSERT_EQ(0x0000024du, ImmutableString("textureSize(00l00C").mangledNameHash()); - ASSERT_EQ(0x0000024eu, ImmutableString("textureSize(00o00C").mangledNameHash()); + ASSERT_EQ(0x0000024du, ImmutableString("textureSize(00k00C").mangledNameHash()); + ASSERT_EQ(0x0000024eu, ImmutableString("textureSize(00n00C").mangledNameHash()); ASSERT_EQ(0x0000024fu, ImmutableString("textureSize(00h00C").mangledNameHash()); ASSERT_EQ(0x00000250u, ImmutableString("textureSize(00f").mangledNameHash()); - ASSERT_EQ(0x00000251u, ImmutableString("textureSize(00k").mangledNameHash()); - ASSERT_EQ(0x00000252u, ImmutableString("textureSize(00n").mangledNameHash()); + ASSERT_EQ(0x00000251u, ImmutableString("textureSize(00j").mangledNameHash()); + ASSERT_EQ(0x00000252u, ImmutableString("textureSize(00m").mangledNameHash()); ASSERT_EQ(0x00000253u, ImmutableString("textureSize(00O").mangledNameHash()); ASSERT_EQ(0x00000254u, ImmutableString("textureSize(00U").mangledNameHash()); ASSERT_EQ(0x00000255u, ImmutableString("textureSize(00a").mangledNameHash()); @@ -639,8 +639,8 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x0000026cu, ImmutableString("texelFetch(00T20C00C").mangledNameHash()); ASSERT_EQ(0x0000026du, ImmutableString("texelFetch(00Z20C00C").mangledNameHash()); ASSERT_EQ(0x0000026eu, ImmutableString("texelFetch(00f00C").mangledNameHash()); - ASSERT_EQ(0x0000026fu, ImmutableString("texelFetch(00k00C").mangledNameHash()); - ASSERT_EQ(0x00000270u, ImmutableString("texelFetch(00n00C").mangledNameHash()); + ASSERT_EQ(0x0000026fu, ImmutableString("texelFetch(00j00C").mangledNameHash()); + ASSERT_EQ(0x00000270u, ImmutableString("texelFetch(00m00C").mangledNameHash()); ASSERT_EQ(0x00000271u, ImmutableString("texelFetch(00O10C00C").mangledNameHash()); ASSERT_EQ(0x00000272u, ImmutableString("texelFetch(00U10C00C").mangledNameHash()); ASSERT_EQ(0x00000273u, ImmutableString("texelFetch(00a10C00C").mangledNameHash()); @@ -665,8 +665,8 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x00000286u, ImmutableString("textureGrad(00Z20B10B10B").mangledNameHash()); ASSERT_EQ(0x00000287u, ImmutableString("textureGrad(00e30B10B10B").mangledNameHash()); ASSERT_EQ(0x00000288u, ImmutableString("textureGrad(00g30B20B20B").mangledNameHash()); - ASSERT_EQ(0x00000289u, ImmutableString("textureGrad(00l30B20B20B").mangledNameHash()); - ASSERT_EQ(0x0000028au, ImmutableString("textureGrad(00o30B20B20B").mangledNameHash()); + ASSERT_EQ(0x00000289u, ImmutableString("textureGrad(00k30B20B20B").mangledNameHash()); + ASSERT_EQ(0x0000028au, ImmutableString("textureGrad(00n30B20B20B").mangledNameHash()); ASSERT_EQ(0x0000028bu, ImmutableString("textureProjGrad(00H20B10B10B").mangledNameHash()); ASSERT_EQ(0x0000028cu, ImmutableString("textureProjGrad(00Q20B10B10B").mangledNameHash()); ASSERT_EQ(0x0000028du, ImmutableString("textureProjGrad(00W20B10B10B").mangledNameHash()); @@ -703,8 +703,8 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x000002acu, ImmutableString("textureProj(00c30B00B").mangledNameHash()); ASSERT_EQ(0x000002adu, ImmutableString("texture(00e30B00B").mangledNameHash()); ASSERT_EQ(0x000002aeu, ImmutableString("texture(00g30B00B").mangledNameHash()); - ASSERT_EQ(0x000002afu, ImmutableString("texture(00l30B00B").mangledNameHash()); - ASSERT_EQ(0x000002b0u, ImmutableString("texture(00o30B00B").mangledNameHash()); + ASSERT_EQ(0x000002afu, ImmutableString("texture(00k30B00B").mangledNameHash()); + ASSERT_EQ(0x000002b0u, ImmutableString("texture(00n30B00B").mangledNameHash()); ASSERT_EQ(0x000002b1u, ImmutableString("texture(00h30B00B00B").mangledNameHash()); ASSERT_EQ(0x000002b2u, ImmutableString("texture(00L10B00B").mangledNameHash()); ASSERT_EQ(0x000002b3u, ImmutableString("textureProj(00L20B00B").mangledNameHash()); @@ -818,821 +818,661 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x00000315u, ImmutableString("textureGather(00H10B").mangledNameHash()); ASSERT_EQ(0x00000316u, ImmutableString("textureGather(00Q10B").mangledNameHash()); ASSERT_EQ(0x00000317u, ImmutableString("textureGather(00W10B").mangledNameHash()); - ASSERT_EQ(0x00000318u, ImmutableString("textureGather(00H10B00C").mangledNameHash()); - ASSERT_EQ(0x00000319u, ImmutableString("textureGather(00Q10B00C").mangledNameHash()); - ASSERT_EQ(0x0000031au, ImmutableString("textureGather(00W10B00C").mangledNameHash()); - ASSERT_EQ(0x0000031bu, ImmutableString("textureGather(00K20B").mangledNameHash()); - ASSERT_EQ(0x0000031cu, ImmutableString("textureGather(00T20B").mangledNameHash()); - ASSERT_EQ(0x0000031du, ImmutableString("textureGather(00Z20B").mangledNameHash()); - ASSERT_EQ(0x0000031eu, ImmutableString("textureGather(00K20B00C").mangledNameHash()); - ASSERT_EQ(0x0000031fu, ImmutableString("textureGather(00T20B00C").mangledNameHash()); - ASSERT_EQ(0x00000320u, ImmutableString("textureGather(00Z20B00C").mangledNameHash()); - ASSERT_EQ(0x00000321u, ImmutableString("textureGather(00J20B").mangledNameHash()); - ASSERT_EQ(0x00000322u, ImmutableString("textureGather(00S20B").mangledNameHash()); - ASSERT_EQ(0x00000323u, ImmutableString("textureGather(00Y20B").mangledNameHash()); - ASSERT_EQ(0x00000324u, ImmutableString("textureGather(00J20B00C").mangledNameHash()); - ASSERT_EQ(0x00000325u, ImmutableString("textureGather(00S20B00C").mangledNameHash()); - ASSERT_EQ(0x00000326u, ImmutableString("textureGather(00Y20B00C").mangledNameHash()); - ASSERT_EQ(0x00000327u, ImmutableString("textureGather(00g30B").mangledNameHash()); - ASSERT_EQ(0x00000328u, ImmutableString("textureGather(00l30B").mangledNameHash()); - ASSERT_EQ(0x00000329u, ImmutableString("textureGather(00o30B").mangledNameHash()); + ASSERT_EQ(0x00000318u, ImmutableString("textureGather(00K20B").mangledNameHash()); + ASSERT_EQ(0x00000319u, ImmutableString("textureGather(00T20B").mangledNameHash()); + ASSERT_EQ(0x0000031au, ImmutableString("textureGather(00Z20B").mangledNameHash()); + ASSERT_EQ(0x0000031bu, ImmutableString("textureGather(00J20B").mangledNameHash()); + ASSERT_EQ(0x0000031cu, ImmutableString("textureGather(00S20B").mangledNameHash()); + ASSERT_EQ(0x0000031du, ImmutableString("textureGather(00Y20B").mangledNameHash()); + ASSERT_EQ(0x0000031eu, ImmutableString("textureGather(00g30B").mangledNameHash()); + ASSERT_EQ(0x0000031fu, ImmutableString("textureGather(00k30B").mangledNameHash()); + ASSERT_EQ(0x00000320u, ImmutableString("textureGather(00n30B").mangledNameHash()); + ASSERT_EQ(0x00000321u, ImmutableString("textureGather(00H10B00C").mangledNameHash()); + ASSERT_EQ(0x00000322u, ImmutableString("textureGather(00Q10B00C").mangledNameHash()); + ASSERT_EQ(0x00000323u, ImmutableString("textureGather(00W10B00C").mangledNameHash()); + ASSERT_EQ(0x00000324u, ImmutableString("textureGather(00K20B00C").mangledNameHash()); + ASSERT_EQ(0x00000325u, ImmutableString("textureGather(00T20B00C").mangledNameHash()); + ASSERT_EQ(0x00000326u, ImmutableString("textureGather(00Z20B00C").mangledNameHash()); + ASSERT_EQ(0x00000327u, ImmutableString("textureGather(00J20B00C").mangledNameHash()); + ASSERT_EQ(0x00000328u, ImmutableString("textureGather(00S20B00C").mangledNameHash()); + ASSERT_EQ(0x00000329u, ImmutableString("textureGather(00Y20B00C").mangledNameHash()); ASSERT_EQ(0x0000032au, ImmutableString("textureGather(00g30B00C").mangledNameHash()); - ASSERT_EQ(0x0000032bu, ImmutableString("textureGather(00l30B00C").mangledNameHash()); - ASSERT_EQ(0x0000032cu, ImmutableString("textureGather(00o30B00C").mangledNameHash()); + ASSERT_EQ(0x0000032bu, ImmutableString("textureGather(00k30B00C").mangledNameHash()); + ASSERT_EQ(0x0000032cu, ImmutableString("textureGather(00n30B00C").mangledNameHash()); ASSERT_EQ(0x0000032du, ImmutableString("textureGather(00h30B00B").mangledNameHash()); - ASSERT_EQ(0x0000032eu, ImmutableString("textureGather(00c10B").mangledNameHash()); - ASSERT_EQ(0x0000032fu, ImmutableString("textureGather(00c10B00B").mangledNameHash()); - ASSERT_EQ(0x00000330u, ImmutableString("textureGather(00e20B").mangledNameHash()); - ASSERT_EQ(0x00000331u, ImmutableString("textureGather(00e20B00B").mangledNameHash()); - ASSERT_EQ(0x00000332u, ImmutableString("textureGather(00d20B").mangledNameHash()); - ASSERT_EQ(0x00000333u, ImmutableString("textureGather(00d20B00B").mangledNameHash()); - ASSERT_EQ(0x00000334u, ImmutableString("textureGatherOffset(00H10B10C").mangledNameHash()); - ASSERT_EQ(0x00000335u, ImmutableString("textureGatherOffset(00Q10B10C").mangledNameHash()); - ASSERT_EQ(0x00000336u, ImmutableString("textureGatherOffset(00W10B10C").mangledNameHash()); - ASSERT_EQ(0x00000337u, ImmutableString("textureGatherOffset(00K20B10C").mangledNameHash()); - ASSERT_EQ(0x00000338u, ImmutableString("textureGatherOffset(00T20B10C").mangledNameHash()); - ASSERT_EQ(0x00000339u, ImmutableString("textureGatherOffset(00Z20B10C").mangledNameHash()); - ASSERT_EQ(0x0000033au, ImmutableString("textureGatherOffset(00c10B00B10C").mangledNameHash()); - ASSERT_EQ(0x0000033bu, ImmutableString("textureGatherOffset(00e20B00B10C").mangledNameHash()); - ASSERT_EQ(0x0000033cu, ImmutableString("textureGatherOffset(00H10B10C00C").mangledNameHash()); - ASSERT_EQ(0x0000033du, ImmutableString("textureGatherOffset(00Q10B10C00C").mangledNameHash()); - ASSERT_EQ(0x0000033eu, ImmutableString("textureGatherOffset(00W10B10C00C").mangledNameHash()); - ASSERT_EQ(0x0000033fu, ImmutableString("textureGatherOffset(00K20B10C00C").mangledNameHash()); - ASSERT_EQ(0x00000340u, ImmutableString("textureGatherOffset(00T20B10C00C").mangledNameHash()); - ASSERT_EQ(0x00000341u, ImmutableString("textureGatherOffset(00Z20B10C00C").mangledNameHash()); - ASSERT_EQ(0x00000342u, ImmutableString("textureGatherOffsets(00H10B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000343u, ImmutableString("textureGatherOffsets(00Q10B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000344u, ImmutableString("textureGatherOffsets(00W10B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000345u, ImmutableString("textureGatherOffsets(00K20B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000346u, ImmutableString("textureGatherOffsets(00T20B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000347u, ImmutableString("textureGatherOffsets(00Z20B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000348u, - ImmutableString("textureGatherOffsets(00c10B00B10Cx4").mangledNameHash()); - ASSERT_EQ(0x00000349u, - ImmutableString("textureGatherOffsets(00e20B00B10Cx4").mangledNameHash()); - ASSERT_EQ(0x0000034au, + ASSERT_EQ(0x0000032eu, ImmutableString("textureGather(00c10B00B").mangledNameHash()); + ASSERT_EQ(0x0000032fu, ImmutableString("textureGather(00e20B00B").mangledNameHash()); + ASSERT_EQ(0x00000330u, ImmutableString("textureGather(00d20B00B").mangledNameHash()); + ASSERT_EQ(0x00000331u, ImmutableString("textureGatherOffset(00H10B10C").mangledNameHash()); + ASSERT_EQ(0x00000332u, ImmutableString("textureGatherOffset(00Q10B10C").mangledNameHash()); + ASSERT_EQ(0x00000333u, ImmutableString("textureGatherOffset(00W10B10C").mangledNameHash()); + ASSERT_EQ(0x00000334u, ImmutableString("textureGatherOffset(00K20B10C").mangledNameHash()); + ASSERT_EQ(0x00000335u, ImmutableString("textureGatherOffset(00T20B10C").mangledNameHash()); + ASSERT_EQ(0x00000336u, ImmutableString("textureGatherOffset(00Z20B10C").mangledNameHash()); + ASSERT_EQ(0x00000337u, ImmutableString("textureGatherOffset(00H10B10C00C").mangledNameHash()); + ASSERT_EQ(0x00000338u, ImmutableString("textureGatherOffset(00Q10B10C00C").mangledNameHash()); + ASSERT_EQ(0x00000339u, ImmutableString("textureGatherOffset(00W10B10C00C").mangledNameHash()); + ASSERT_EQ(0x0000033au, ImmutableString("textureGatherOffset(00K20B10C00C").mangledNameHash()); + ASSERT_EQ(0x0000033bu, ImmutableString("textureGatherOffset(00T20B10C00C").mangledNameHash()); + ASSERT_EQ(0x0000033cu, ImmutableString("textureGatherOffset(00Z20B10C00C").mangledNameHash()); + ASSERT_EQ(0x0000033du, ImmutableString("textureGatherOffset(00c10B00B10C").mangledNameHash()); + ASSERT_EQ(0x0000033eu, ImmutableString("textureGatherOffset(00e20B00B10C").mangledNameHash()); + ASSERT_EQ(0x0000033fu, ImmutableString("textureGatherOffsets(00H10B10Cx4").mangledNameHash()); + ASSERT_EQ(0x00000340u, ImmutableString("textureGatherOffsets(00Q10B10Cx4").mangledNameHash()); + ASSERT_EQ(0x00000341u, ImmutableString("textureGatherOffsets(00W10B10Cx4").mangledNameHash()); + ASSERT_EQ(0x00000342u, ImmutableString("textureGatherOffsets(00K20B10Cx4").mangledNameHash()); + ASSERT_EQ(0x00000343u, ImmutableString("textureGatherOffsets(00T20B10Cx4").mangledNameHash()); + ASSERT_EQ(0x00000344u, ImmutableString("textureGatherOffsets(00Z20B10Cx4").mangledNameHash()); + ASSERT_EQ(0x00000345u, ImmutableString("textureGatherOffsets(00H10B10Cx400C").mangledNameHash()); - ASSERT_EQ(0x0000034bu, + ASSERT_EQ(0x00000346u, ImmutableString("textureGatherOffsets(00Q10B10Cx400C").mangledNameHash()); - ASSERT_EQ(0x0000034cu, + ASSERT_EQ(0x00000347u, ImmutableString("textureGatherOffsets(00W10B10Cx400C").mangledNameHash()); - ASSERT_EQ(0x0000034du, + ASSERT_EQ(0x00000348u, ImmutableString("textureGatherOffsets(00K20B10Cx400C").mangledNameHash()); - ASSERT_EQ(0x0000034eu, + ASSERT_EQ(0x00000349u, ImmutableString("textureGatherOffsets(00T20B10Cx400C").mangledNameHash()); - ASSERT_EQ(0x0000034fu, + ASSERT_EQ(0x0000034au, ImmutableString("textureGatherOffsets(00Z20B10Cx400C").mangledNameHash()); - ASSERT_EQ(0x00000350u, ImmutableString("textureQueryLOD(00H10B").mangledNameHash()); - ASSERT_EQ(0x00000351u, ImmutableString("textureQueryLOD(00Q10B").mangledNameHash()); - ASSERT_EQ(0x00000352u, ImmutableString("textureQueryLOD(00W10B").mangledNameHash()); - ASSERT_EQ(0x00000353u, ImmutableString("textureQueryLOD(00I20B").mangledNameHash()); - ASSERT_EQ(0x00000354u, ImmutableString("textureQueryLOD(00R20B").mangledNameHash()); - ASSERT_EQ(0x00000355u, ImmutableString("textureQueryLOD(00X20B").mangledNameHash()); - ASSERT_EQ(0x00000356u, ImmutableString("textureQueryLOD(00J20B").mangledNameHash()); - ASSERT_EQ(0x00000357u, ImmutableString("textureQueryLOD(00S20B").mangledNameHash()); - ASSERT_EQ(0x00000358u, ImmutableString("textureQueryLOD(00Y20B").mangledNameHash()); - ASSERT_EQ(0x00000359u, ImmutableString("textureQueryLOD(00K10B").mangledNameHash()); - ASSERT_EQ(0x0000035au, ImmutableString("textureQueryLOD(00T10B").mangledNameHash()); - ASSERT_EQ(0x0000035bu, ImmutableString("textureQueryLOD(00Z10B").mangledNameHash()); - ASSERT_EQ(0x0000035cu, ImmutableString("textureQueryLOD(00c10B").mangledNameHash()); - ASSERT_EQ(0x0000035du, ImmutableString("textureQueryLOD(00d20B").mangledNameHash()); - ASSERT_EQ(0x0000035eu, ImmutableString("textureQueryLOD(00e10B").mangledNameHash()); - ASSERT_EQ(0x0000035fu, ImmutableString("textureQueryLOD(00g20B").mangledNameHash()); - ASSERT_EQ(0x00000360u, ImmutableString("textureQueryLOD(00l20B").mangledNameHash()); - ASSERT_EQ(0x00000361u, ImmutableString("textureQueryLOD(00o20B").mangledNameHash()); - ASSERT_EQ(0x00000362u, ImmutableString("textureQueryLOD(00h20B").mangledNameHash()); - ASSERT_EQ(0x00000363u, ImmutableString("rgb_2_yuv(20B00G").mangledNameHash()); - ASSERT_EQ(0x00000364u, ImmutableString("yuv_2_rgb(20B00G").mangledNameHash()); - ASSERT_EQ(0x00000365u, ImmutableString("dFdx(00B").mangledNameHash()); - ASSERT_EQ(0x00000366u, ImmutableString("dFdx(10B").mangledNameHash()); - ASSERT_EQ(0x00000367u, ImmutableString("dFdx(20B").mangledNameHash()); - ASSERT_EQ(0x00000368u, ImmutableString("dFdx(30B").mangledNameHash()); - ASSERT_EQ(0x00000369u, ImmutableString("dFdy(00B").mangledNameHash()); - ASSERT_EQ(0x0000036au, ImmutableString("dFdy(10B").mangledNameHash()); - ASSERT_EQ(0x0000036bu, ImmutableString("dFdy(20B").mangledNameHash()); - ASSERT_EQ(0x0000036cu, ImmutableString("dFdy(30B").mangledNameHash()); - ASSERT_EQ(0x0000036du, ImmutableString("fwidth(00B").mangledNameHash()); - ASSERT_EQ(0x0000036eu, ImmutableString("fwidth(10B").mangledNameHash()); - ASSERT_EQ(0x0000036fu, ImmutableString("fwidth(20B").mangledNameHash()); - ASSERT_EQ(0x00000370u, ImmutableString("fwidth(30B").mangledNameHash()); - ASSERT_EQ(0x00000371u, ImmutableString("interpolateAtCentroid(00B").mangledNameHash()); - ASSERT_EQ(0x00000372u, ImmutableString("interpolateAtCentroid(10B").mangledNameHash()); - ASSERT_EQ(0x00000373u, ImmutableString("interpolateAtCentroid(20B").mangledNameHash()); - ASSERT_EQ(0x00000374u, ImmutableString("interpolateAtCentroid(30B").mangledNameHash()); - ASSERT_EQ(0x00000375u, ImmutableString("interpolateAtSample(00B00C").mangledNameHash()); - ASSERT_EQ(0x00000376u, ImmutableString("interpolateAtSample(10B00C").mangledNameHash()); - ASSERT_EQ(0x00000377u, ImmutableString("interpolateAtSample(20B00C").mangledNameHash()); - ASSERT_EQ(0x00000378u, ImmutableString("interpolateAtSample(30B00C").mangledNameHash()); - ASSERT_EQ(0x00000379u, ImmutableString("interpolateAtOffset(00B10B").mangledNameHash()); - ASSERT_EQ(0x0000037au, ImmutableString("interpolateAtOffset(10B10B").mangledNameHash()); - ASSERT_EQ(0x0000037bu, ImmutableString("interpolateAtOffset(20B10B").mangledNameHash()); - ASSERT_EQ(0x0000037cu, ImmutableString("interpolateAtOffset(30B10B").mangledNameHash()); - ASSERT_EQ(0x0000037du, ImmutableString("atomicCounter(00F").mangledNameHash()); - ASSERT_EQ(0x0000037eu, ImmutableString("atomicCounterIncrement(00F").mangledNameHash()); - ASSERT_EQ(0x0000037fu, ImmutableString("atomicCounterDecrement(00F").mangledNameHash()); - ASSERT_EQ(0x00000380u, ImmutableString("atomicAdd(00D00D").mangledNameHash()); - ASSERT_EQ(0x00000381u, ImmutableString("atomicAdd(00C00C").mangledNameHash()); - ASSERT_EQ(0x00000382u, ImmutableString("atomicMin(00D00D").mangledNameHash()); - ASSERT_EQ(0x00000383u, ImmutableString("atomicMin(00C00C").mangledNameHash()); - ASSERT_EQ(0x00000384u, ImmutableString("atomicMax(00D00D").mangledNameHash()); - ASSERT_EQ(0x00000385u, ImmutableString("atomicMax(00C00C").mangledNameHash()); - ASSERT_EQ(0x00000386u, ImmutableString("atomicAnd(00D00D").mangledNameHash()); - ASSERT_EQ(0x00000387u, ImmutableString("atomicAnd(00C00C").mangledNameHash()); - ASSERT_EQ(0x00000388u, ImmutableString("atomicOr(00D00D").mangledNameHash()); - ASSERT_EQ(0x00000389u, ImmutableString("atomicOr(00C00C").mangledNameHash()); - ASSERT_EQ(0x0000038au, ImmutableString("atomicXor(00D00D").mangledNameHash()); - ASSERT_EQ(0x0000038bu, ImmutableString("atomicXor(00C00C").mangledNameHash()); - ASSERT_EQ(0x0000038cu, ImmutableString("atomicExchange(00D00D").mangledNameHash()); - ASSERT_EQ(0x0000038du, ImmutableString("atomicExchange(00C00C").mangledNameHash()); - ASSERT_EQ(0x0000038eu, ImmutableString("atomicCompSwap(00D00D00D").mangledNameHash()); - ASSERT_EQ(0x0000038fu, ImmutableString("atomicCompSwap(00C00C00C").mangledNameHash()); + ASSERT_EQ(0x0000034bu, + ImmutableString("textureGatherOffsets(00c10B00B10Cx4").mangledNameHash()); + ASSERT_EQ(0x0000034cu, + ImmutableString("textureGatherOffsets(00e20B00B10Cx4").mangledNameHash()); + ASSERT_EQ(0x0000034du, ImmutableString("textureQueryLOD(00H10B").mangledNameHash()); + ASSERT_EQ(0x0000034eu, ImmutableString("textureQueryLOD(00Q10B").mangledNameHash()); + ASSERT_EQ(0x0000034fu, ImmutableString("textureQueryLOD(00W10B").mangledNameHash()); + ASSERT_EQ(0x00000350u, ImmutableString("textureQueryLOD(00I20B").mangledNameHash()); + ASSERT_EQ(0x00000351u, ImmutableString("textureQueryLOD(00R20B").mangledNameHash()); + ASSERT_EQ(0x00000352u, ImmutableString("textureQueryLOD(00X20B").mangledNameHash()); + ASSERT_EQ(0x00000353u, ImmutableString("textureQueryLOD(00J20B").mangledNameHash()); + ASSERT_EQ(0x00000354u, ImmutableString("textureQueryLOD(00S20B").mangledNameHash()); + ASSERT_EQ(0x00000355u, ImmutableString("textureQueryLOD(00Y20B").mangledNameHash()); + ASSERT_EQ(0x00000356u, ImmutableString("textureQueryLOD(00K10B").mangledNameHash()); + ASSERT_EQ(0x00000357u, ImmutableString("textureQueryLOD(00T10B").mangledNameHash()); + ASSERT_EQ(0x00000358u, ImmutableString("textureQueryLOD(00Z10B").mangledNameHash()); + ASSERT_EQ(0x00000359u, ImmutableString("textureQueryLOD(00c10B").mangledNameHash()); + ASSERT_EQ(0x0000035au, ImmutableString("textureQueryLOD(00d20B").mangledNameHash()); + ASSERT_EQ(0x0000035bu, ImmutableString("textureQueryLOD(00e10B").mangledNameHash()); + ASSERT_EQ(0x0000035cu, ImmutableString("textureQueryLOD(00g20B").mangledNameHash()); + ASSERT_EQ(0x0000035du, ImmutableString("textureQueryLOD(00k20B").mangledNameHash()); + ASSERT_EQ(0x0000035eu, ImmutableString("textureQueryLOD(00n20B").mangledNameHash()); + ASSERT_EQ(0x0000035fu, ImmutableString("textureQueryLOD(00h20B").mangledNameHash()); + ASSERT_EQ(0x00000360u, ImmutableString("rgb_2_yuv(20B00G").mangledNameHash()); + ASSERT_EQ(0x00000361u, ImmutableString("yuv_2_rgb(20B00G").mangledNameHash()); + ASSERT_EQ(0x00000362u, ImmutableString("dFdx(00B").mangledNameHash()); + ASSERT_EQ(0x00000363u, ImmutableString("dFdx(10B").mangledNameHash()); + ASSERT_EQ(0x00000364u, ImmutableString("dFdx(20B").mangledNameHash()); + ASSERT_EQ(0x00000365u, ImmutableString("dFdx(30B").mangledNameHash()); + ASSERT_EQ(0x00000366u, ImmutableString("dFdy(00B").mangledNameHash()); + ASSERT_EQ(0x00000367u, ImmutableString("dFdy(10B").mangledNameHash()); + ASSERT_EQ(0x00000368u, ImmutableString("dFdy(20B").mangledNameHash()); + ASSERT_EQ(0x00000369u, ImmutableString("dFdy(30B").mangledNameHash()); + ASSERT_EQ(0x0000036au, ImmutableString("fwidth(00B").mangledNameHash()); + ASSERT_EQ(0x0000036bu, ImmutableString("fwidth(10B").mangledNameHash()); + ASSERT_EQ(0x0000036cu, ImmutableString("fwidth(20B").mangledNameHash()); + ASSERT_EQ(0x0000036du, ImmutableString("fwidth(30B").mangledNameHash()); + ASSERT_EQ(0x0000036eu, ImmutableString("interpolateAtCentroid(00B").mangledNameHash()); + ASSERT_EQ(0x0000036fu, ImmutableString("interpolateAtCentroid(10B").mangledNameHash()); + ASSERT_EQ(0x00000370u, ImmutableString("interpolateAtCentroid(20B").mangledNameHash()); + ASSERT_EQ(0x00000371u, ImmutableString("interpolateAtCentroid(30B").mangledNameHash()); + ASSERT_EQ(0x00000372u, ImmutableString("interpolateAtSample(00B00C").mangledNameHash()); + ASSERT_EQ(0x00000373u, ImmutableString("interpolateAtSample(10B00C").mangledNameHash()); + ASSERT_EQ(0x00000374u, ImmutableString("interpolateAtSample(20B00C").mangledNameHash()); + ASSERT_EQ(0x00000375u, ImmutableString("interpolateAtSample(30B00C").mangledNameHash()); + ASSERT_EQ(0x00000376u, ImmutableString("interpolateAtOffset(00B10B").mangledNameHash()); + ASSERT_EQ(0x00000377u, ImmutableString("interpolateAtOffset(10B10B").mangledNameHash()); + ASSERT_EQ(0x00000378u, ImmutableString("interpolateAtOffset(20B10B").mangledNameHash()); + ASSERT_EQ(0x00000379u, ImmutableString("interpolateAtOffset(30B10B").mangledNameHash()); + ASSERT_EQ(0x0000037au, ImmutableString("atomicCounter(00F").mangledNameHash()); + ASSERT_EQ(0x0000037bu, ImmutableString("atomicCounterIncrement(00F").mangledNameHash()); + ASSERT_EQ(0x0000037cu, ImmutableString("atomicCounterDecrement(00F").mangledNameHash()); + ASSERT_EQ(0x0000037du, ImmutableString("atomicAdd(00D00D").mangledNameHash()); + ASSERT_EQ(0x0000037eu, ImmutableString("atomicAdd(00C00C").mangledNameHash()); + ASSERT_EQ(0x0000037fu, ImmutableString("atomicMin(00D00D").mangledNameHash()); + ASSERT_EQ(0x00000380u, ImmutableString("atomicMin(00C00C").mangledNameHash()); + ASSERT_EQ(0x00000381u, ImmutableString("atomicMax(00D00D").mangledNameHash()); + ASSERT_EQ(0x00000382u, ImmutableString("atomicMax(00C00C").mangledNameHash()); + ASSERT_EQ(0x00000383u, ImmutableString("atomicAnd(00D00D").mangledNameHash()); + ASSERT_EQ(0x00000384u, ImmutableString("atomicAnd(00C00C").mangledNameHash()); + ASSERT_EQ(0x00000385u, ImmutableString("atomicOr(00D00D").mangledNameHash()); + ASSERT_EQ(0x00000386u, ImmutableString("atomicOr(00C00C").mangledNameHash()); + ASSERT_EQ(0x00000387u, ImmutableString("atomicXor(00D00D").mangledNameHash()); + ASSERT_EQ(0x00000388u, ImmutableString("atomicXor(00C00C").mangledNameHash()); + ASSERT_EQ(0x00000389u, ImmutableString("atomicExchange(00D00D").mangledNameHash()); + ASSERT_EQ(0x0000038au, ImmutableString("atomicExchange(00C00C").mangledNameHash()); + ASSERT_EQ(0x0000038bu, ImmutableString("atomicCompSwap(00D00D00D").mangledNameHash()); + ASSERT_EQ(0x0000038cu, ImmutableString("atomicCompSwap(00C00C00C").mangledNameHash()); + ASSERT_EQ(0x0000038du, ImmutableString("imageSize(00p").mangledNameHash()); + ASSERT_EQ(0x0000038eu, ImmutableString("imageSize(00v").mangledNameHash()); + ASSERT_EQ(0x0000038fu, ImmutableString("imageSize(01B").mangledNameHash()); ASSERT_EQ(0x00000390u, ImmutableString("imageSize(00q").mangledNameHash()); - ASSERT_EQ(0x00000391u, ImmutableString("imageSize(00z").mangledNameHash()); - ASSERT_EQ(0x00000392u, ImmutableString("imageSize(01I").mangledNameHash()); + ASSERT_EQ(0x00000391u, ImmutableString("imageSize(00w").mangledNameHash()); + ASSERT_EQ(0x00000392u, ImmutableString("imageSize(01C").mangledNameHash()); ASSERT_EQ(0x00000393u, ImmutableString("imageSize(00r").mangledNameHash()); - ASSERT_EQ(0x00000394u, ImmutableString("imageSize(01A").mangledNameHash()); - ASSERT_EQ(0x00000395u, ImmutableString("imageSize(01J").mangledNameHash()); + ASSERT_EQ(0x00000394u, ImmutableString("imageSize(00x").mangledNameHash()); + ASSERT_EQ(0x00000395u, ImmutableString("imageSize(01D").mangledNameHash()); ASSERT_EQ(0x00000396u, ImmutableString("imageSize(00s").mangledNameHash()); - ASSERT_EQ(0x00000397u, ImmutableString("imageSize(01B").mangledNameHash()); - ASSERT_EQ(0x00000398u, ImmutableString("imageSize(01K").mangledNameHash()); + ASSERT_EQ(0x00000397u, ImmutableString("imageSize(00y").mangledNameHash()); + ASSERT_EQ(0x00000398u, ImmutableString("imageSize(01E").mangledNameHash()); ASSERT_EQ(0x00000399u, ImmutableString("imageSize(00t").mangledNameHash()); - ASSERT_EQ(0x0000039au, ImmutableString("imageSize(01C").mangledNameHash()); - ASSERT_EQ(0x0000039bu, ImmutableString("imageSize(01L").mangledNameHash()); - ASSERT_EQ(0x0000039cu, ImmutableString("imageSize(00w").mangledNameHash()); - ASSERT_EQ(0x0000039du, ImmutableString("imageSize(01F").mangledNameHash()); - ASSERT_EQ(0x0000039eu, ImmutableString("imageSize(01O").mangledNameHash()); - ASSERT_EQ(0x0000039fu, ImmutableString("imageSize(00y").mangledNameHash()); - ASSERT_EQ(0x000003a0u, ImmutableString("imageSize(01H").mangledNameHash()); - ASSERT_EQ(0x000003a1u, ImmutableString("imageSize(01Q").mangledNameHash()); - ASSERT_EQ(0x000003a2u, ImmutableString("imageStore(00q10C30B").mangledNameHash()); - ASSERT_EQ(0x000003a3u, ImmutableString("imageStore(00z10C30C").mangledNameHash()); - ASSERT_EQ(0x000003a4u, ImmutableString("imageStore(01I10C30D").mangledNameHash()); + ASSERT_EQ(0x0000039au, ImmutableString("imageSize(00z").mangledNameHash()); + ASSERT_EQ(0x0000039bu, ImmutableString("imageSize(01F").mangledNameHash()); + ASSERT_EQ(0x0000039cu, ImmutableString("imageSize(00u").mangledNameHash()); + ASSERT_EQ(0x0000039du, ImmutableString("imageSize(01A").mangledNameHash()); + ASSERT_EQ(0x0000039eu, ImmutableString("imageSize(01G").mangledNameHash()); + ASSERT_EQ(0x0000039fu, ImmutableString("imageStore(00p10C30B").mangledNameHash()); + ASSERT_EQ(0x000003a0u, ImmutableString("imageStore(00v10C30C").mangledNameHash()); + ASSERT_EQ(0x000003a1u, ImmutableString("imageStore(01B10C30D").mangledNameHash()); + ASSERT_EQ(0x000003a2u, ImmutableString("imageStore(00q20C30B").mangledNameHash()); + ASSERT_EQ(0x000003a3u, ImmutableString("imageStore(00w20C30C").mangledNameHash()); + ASSERT_EQ(0x000003a4u, ImmutableString("imageStore(01C20C30D").mangledNameHash()); ASSERT_EQ(0x000003a5u, ImmutableString("imageStore(00r20C30B").mangledNameHash()); - ASSERT_EQ(0x000003a6u, ImmutableString("imageStore(01A20C30C").mangledNameHash()); - ASSERT_EQ(0x000003a7u, ImmutableString("imageStore(01J20C30D").mangledNameHash()); + ASSERT_EQ(0x000003a6u, ImmutableString("imageStore(00x20C30C").mangledNameHash()); + ASSERT_EQ(0x000003a7u, ImmutableString("imageStore(01D20C30D").mangledNameHash()); ASSERT_EQ(0x000003a8u, ImmutableString("imageStore(00s20C30B").mangledNameHash()); - ASSERT_EQ(0x000003a9u, ImmutableString("imageStore(01B20C30C").mangledNameHash()); - ASSERT_EQ(0x000003aau, ImmutableString("imageStore(01K20C30D").mangledNameHash()); + ASSERT_EQ(0x000003a9u, ImmutableString("imageStore(00y20C30C").mangledNameHash()); + ASSERT_EQ(0x000003aau, ImmutableString("imageStore(01E20C30D").mangledNameHash()); ASSERT_EQ(0x000003abu, ImmutableString("imageStore(00t20C30B").mangledNameHash()); - ASSERT_EQ(0x000003acu, ImmutableString("imageStore(01C20C30C").mangledNameHash()); - ASSERT_EQ(0x000003adu, ImmutableString("imageStore(01L20C30D").mangledNameHash()); - ASSERT_EQ(0x000003aeu, ImmutableString("imageStore(00w20C30B").mangledNameHash()); - ASSERT_EQ(0x000003afu, ImmutableString("imageStore(01F20C30C").mangledNameHash()); - ASSERT_EQ(0x000003b0u, ImmutableString("imageStore(01O20C30D").mangledNameHash()); - ASSERT_EQ(0x000003b1u, ImmutableString("imageStore(00y00C30B").mangledNameHash()); - ASSERT_EQ(0x000003b2u, ImmutableString("imageStore(01H00C30C").mangledNameHash()); - ASSERT_EQ(0x000003b3u, ImmutableString("imageStore(01Q00C30D").mangledNameHash()); - ASSERT_EQ(0x000003b4u, ImmutableString("imageLoad(00q10C").mangledNameHash()); - ASSERT_EQ(0x000003b5u, ImmutableString("imageLoad(00z10C").mangledNameHash()); - ASSERT_EQ(0x000003b6u, ImmutableString("imageLoad(01I10C").mangledNameHash()); + ASSERT_EQ(0x000003acu, ImmutableString("imageStore(00z20C30C").mangledNameHash()); + ASSERT_EQ(0x000003adu, ImmutableString("imageStore(01F20C30D").mangledNameHash()); + ASSERT_EQ(0x000003aeu, ImmutableString("imageStore(00u00C30B").mangledNameHash()); + ASSERT_EQ(0x000003afu, ImmutableString("imageStore(01A00C30C").mangledNameHash()); + ASSERT_EQ(0x000003b0u, ImmutableString("imageStore(01G00C30D").mangledNameHash()); + ASSERT_EQ(0x000003b1u, ImmutableString("imageLoad(00p10C").mangledNameHash()); + ASSERT_EQ(0x000003b2u, ImmutableString("imageLoad(00v10C").mangledNameHash()); + ASSERT_EQ(0x000003b3u, ImmutableString("imageLoad(01B10C").mangledNameHash()); + ASSERT_EQ(0x000003b4u, ImmutableString("imageLoad(00q20C").mangledNameHash()); + ASSERT_EQ(0x000003b5u, ImmutableString("imageLoad(00w20C").mangledNameHash()); + ASSERT_EQ(0x000003b6u, ImmutableString("imageLoad(01C20C").mangledNameHash()); ASSERT_EQ(0x000003b7u, ImmutableString("imageLoad(00r20C").mangledNameHash()); - ASSERT_EQ(0x000003b8u, ImmutableString("imageLoad(01A20C").mangledNameHash()); - ASSERT_EQ(0x000003b9u, ImmutableString("imageLoad(01J20C").mangledNameHash()); + ASSERT_EQ(0x000003b8u, ImmutableString("imageLoad(00x20C").mangledNameHash()); + ASSERT_EQ(0x000003b9u, ImmutableString("imageLoad(01D20C").mangledNameHash()); ASSERT_EQ(0x000003bau, ImmutableString("imageLoad(00s20C").mangledNameHash()); - ASSERT_EQ(0x000003bbu, ImmutableString("imageLoad(01B20C").mangledNameHash()); - ASSERT_EQ(0x000003bcu, ImmutableString("imageLoad(01K20C").mangledNameHash()); + ASSERT_EQ(0x000003bbu, ImmutableString("imageLoad(00y20C").mangledNameHash()); + ASSERT_EQ(0x000003bcu, ImmutableString("imageLoad(01E20C").mangledNameHash()); ASSERT_EQ(0x000003bdu, ImmutableString("imageLoad(00t20C").mangledNameHash()); - ASSERT_EQ(0x000003beu, ImmutableString("imageLoad(01C20C").mangledNameHash()); - ASSERT_EQ(0x000003bfu, ImmutableString("imageLoad(01L20C").mangledNameHash()); - ASSERT_EQ(0x000003c0u, ImmutableString("imageLoad(00w20C").mangledNameHash()); - ASSERT_EQ(0x000003c1u, ImmutableString("imageLoad(01F20C").mangledNameHash()); - ASSERT_EQ(0x000003c2u, ImmutableString("imageLoad(01O20C").mangledNameHash()); - ASSERT_EQ(0x000003c3u, ImmutableString("imageLoad(00y00C").mangledNameHash()); - ASSERT_EQ(0x000003c4u, ImmutableString("imageLoad(01H00C").mangledNameHash()); - ASSERT_EQ(0x000003c5u, ImmutableString("imageLoad(01Q00C").mangledNameHash()); - ASSERT_EQ(0x000003c6u, ImmutableString("imageAtomicAdd(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x000003c7u, ImmutableString("imageAtomicAdd(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x000003c8u, ImmutableString("imageAtomicAdd(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x000003c9u, ImmutableString("imageAtomicAdd(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x000003cau, ImmutableString("imageAtomicAdd(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x000003cbu, ImmutableString("imageAtomicAdd(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x000003ccu, ImmutableString("imageAtomicAdd(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x000003cdu, ImmutableString("imageAtomicAdd(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x000003ceu, ImmutableString("imageAtomicAdd(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x000003cfu, ImmutableString("imageAtomicAdd(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x000003d0u, ImmutableString("imageAtomicAdd(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x000003d1u, ImmutableString("imageAtomicAdd(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x000003d2u, ImmutableString("imageAtomicAdd(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x000003d3u, ImmutableString("imageAtomicAdd(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x000003d4u, ImmutableString("imageAtomicAdd(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x000003d5u, ImmutableString("imageAtomicAdd(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x000003d6u, ImmutableString("imageAtomicAdd(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x000003d7u, ImmutableString("imageAtomicAdd(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x000003d8u, ImmutableString("imageAtomicAdd(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x000003d9u, ImmutableString("imageAtomicAdd(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x000003dau, ImmutableString("imageAtomicAdd(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x000003dbu, ImmutableString("imageAtomicAdd(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000003dcu, ImmutableString("imageAtomicAdd(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000003ddu, ImmutableString("imageAtomicAdd(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000003deu, ImmutableString("imageAtomicAdd(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000003dfu, ImmutableString("imageAtomicAdd(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000003e0u, ImmutableString("imageAtomicAdd(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000003e1u, ImmutableString("imageAtomicAdd(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x000003e2u, ImmutableString("imageAtomicAdd(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x000003e3u, ImmutableString("imageAtomicAdd(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x000003e4u, ImmutableString("imageAtomicAdd(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x000003e5u, ImmutableString("imageAtomicAdd(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x000003e6u, ImmutableString("imageAtomicAdd(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x000003e7u, ImmutableString("imageAtomicAdd(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x000003e8u, ImmutableString("imageAtomicAdd(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x000003e9u, ImmutableString("imageAtomicAdd(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x000003eau, ImmutableString("imageAtomicAdd(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x000003ebu, ImmutableString("imageAtomicAdd(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x000003ecu, ImmutableString("imageAtomicAdd(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x000003edu, ImmutableString("imageAtomicAdd(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x000003eeu, ImmutableString("imageAtomicAdd(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x000003efu, ImmutableString("imageAtomicAdd(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x000003f0u, ImmutableString("imageAtomicAdd(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x000003f1u, ImmutableString("imageAtomicAdd(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x000003f2u, ImmutableString("imageAtomicAdd(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x000003f3u, ImmutableString("imageAtomicAdd(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x000003f4u, ImmutableString("imageAtomicAdd(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x000003f5u, ImmutableString("imageAtomicAdd(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x000003f6u, ImmutableString("imageAtomicAdd(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x000003f7u, ImmutableString("imageAtomicAdd(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x000003f8u, ImmutableString("imageAtomicAdd(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x000003f9u, ImmutableString("imageAtomicAdd(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x000003fau, ImmutableString("imageAtomicAdd(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x000003fbu, ImmutableString("imageAtomicAdd(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x000003fcu, ImmutableString("imageAtomicMin(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x000003fdu, ImmutableString("imageAtomicMin(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x000003feu, ImmutableString("imageAtomicMin(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x000003ffu, ImmutableString("imageAtomicMin(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x00000400u, ImmutableString("imageAtomicMin(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x00000401u, ImmutableString("imageAtomicMin(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x00000402u, ImmutableString("imageAtomicMin(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x00000403u, ImmutableString("imageAtomicMin(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x00000404u, ImmutableString("imageAtomicMin(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x00000405u, ImmutableString("imageAtomicMin(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x00000406u, ImmutableString("imageAtomicMin(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x00000407u, ImmutableString("imageAtomicMin(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x00000408u, ImmutableString("imageAtomicMin(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x00000409u, ImmutableString("imageAtomicMin(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x0000040au, ImmutableString("imageAtomicMin(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x0000040bu, ImmutableString("imageAtomicMin(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x0000040cu, ImmutableString("imageAtomicMin(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x0000040du, ImmutableString("imageAtomicMin(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x0000040eu, ImmutableString("imageAtomicMin(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x0000040fu, ImmutableString("imageAtomicMin(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x00000410u, ImmutableString("imageAtomicMin(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x00000411u, ImmutableString("imageAtomicMin(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000412u, ImmutableString("imageAtomicMin(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000413u, ImmutableString("imageAtomicMin(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000414u, ImmutableString("imageAtomicMin(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000415u, ImmutableString("imageAtomicMin(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000416u, ImmutableString("imageAtomicMin(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000417u, ImmutableString("imageAtomicMin(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x00000418u, ImmutableString("imageAtomicMin(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x00000419u, ImmutableString("imageAtomicMin(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x0000041au, ImmutableString("imageAtomicMin(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x0000041bu, ImmutableString("imageAtomicMin(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x0000041cu, ImmutableString("imageAtomicMin(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x0000041du, ImmutableString("imageAtomicMin(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x0000041eu, ImmutableString("imageAtomicMin(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x0000041fu, ImmutableString("imageAtomicMin(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x00000420u, ImmutableString("imageAtomicMin(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x00000421u, ImmutableString("imageAtomicMin(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x00000422u, ImmutableString("imageAtomicMin(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x00000423u, ImmutableString("imageAtomicMin(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x00000424u, ImmutableString("imageAtomicMin(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x00000425u, ImmutableString("imageAtomicMin(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x00000426u, ImmutableString("imageAtomicMin(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x00000427u, ImmutableString("imageAtomicMin(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x00000428u, ImmutableString("imageAtomicMin(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x00000429u, ImmutableString("imageAtomicMin(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x0000042au, ImmutableString("imageAtomicMin(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x0000042bu, ImmutableString("imageAtomicMin(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x0000042cu, ImmutableString("imageAtomicMin(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000042du, ImmutableString("imageAtomicMin(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000042eu, ImmutableString("imageAtomicMin(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000042fu, ImmutableString("imageAtomicMin(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000430u, ImmutableString("imageAtomicMin(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000431u, ImmutableString("imageAtomicMin(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000432u, ImmutableString("imageAtomicMax(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x00000433u, ImmutableString("imageAtomicMax(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x00000434u, ImmutableString("imageAtomicMax(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x00000435u, ImmutableString("imageAtomicMax(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x00000436u, ImmutableString("imageAtomicMax(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x00000437u, ImmutableString("imageAtomicMax(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x00000438u, ImmutableString("imageAtomicMax(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x00000439u, ImmutableString("imageAtomicMax(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x0000043au, ImmutableString("imageAtomicMax(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x0000043bu, ImmutableString("imageAtomicMax(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x0000043cu, ImmutableString("imageAtomicMax(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x0000043du, ImmutableString("imageAtomicMax(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x0000043eu, ImmutableString("imageAtomicMax(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x0000043fu, ImmutableString("imageAtomicMax(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x00000440u, ImmutableString("imageAtomicMax(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x00000441u, ImmutableString("imageAtomicMax(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x00000442u, ImmutableString("imageAtomicMax(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x00000443u, ImmutableString("imageAtomicMax(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x00000444u, ImmutableString("imageAtomicMax(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x00000445u, ImmutableString("imageAtomicMax(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x00000446u, ImmutableString("imageAtomicMax(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x00000447u, ImmutableString("imageAtomicMax(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000448u, ImmutableString("imageAtomicMax(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000449u, ImmutableString("imageAtomicMax(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x0000044au, ImmutableString("imageAtomicMax(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x0000044bu, ImmutableString("imageAtomicMax(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x0000044cu, ImmutableString("imageAtomicMax(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x0000044du, ImmutableString("imageAtomicMax(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x0000044eu, ImmutableString("imageAtomicMax(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x0000044fu, ImmutableString("imageAtomicMax(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x00000450u, ImmutableString("imageAtomicMax(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x00000451u, ImmutableString("imageAtomicMax(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x00000452u, ImmutableString("imageAtomicMax(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x00000453u, ImmutableString("imageAtomicMax(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x00000454u, ImmutableString("imageAtomicMax(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x00000455u, ImmutableString("imageAtomicMax(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x00000456u, ImmutableString("imageAtomicMax(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x00000457u, ImmutableString("imageAtomicMax(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x00000458u, ImmutableString("imageAtomicMax(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x00000459u, ImmutableString("imageAtomicMax(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x0000045au, ImmutableString("imageAtomicMax(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x0000045bu, ImmutableString("imageAtomicMax(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x0000045cu, ImmutableString("imageAtomicMax(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x0000045du, ImmutableString("imageAtomicMax(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x0000045eu, ImmutableString("imageAtomicMax(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x0000045fu, ImmutableString("imageAtomicMax(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x00000460u, ImmutableString("imageAtomicMax(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x00000461u, ImmutableString("imageAtomicMax(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x00000462u, ImmutableString("imageAtomicMax(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000463u, ImmutableString("imageAtomicMax(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000464u, ImmutableString("imageAtomicMax(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000465u, ImmutableString("imageAtomicMax(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000466u, ImmutableString("imageAtomicMax(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000467u, ImmutableString("imageAtomicMax(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000468u, ImmutableString("imageAtomicAnd(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x00000469u, ImmutableString("imageAtomicAnd(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x0000046au, ImmutableString("imageAtomicAnd(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x0000046bu, ImmutableString("imageAtomicAnd(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x0000046cu, ImmutableString("imageAtomicAnd(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x0000046du, ImmutableString("imageAtomicAnd(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x0000046eu, ImmutableString("imageAtomicAnd(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x0000046fu, ImmutableString("imageAtomicAnd(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x00000470u, ImmutableString("imageAtomicAnd(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x00000471u, ImmutableString("imageAtomicAnd(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x00000472u, ImmutableString("imageAtomicAnd(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x00000473u, ImmutableString("imageAtomicAnd(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x00000474u, ImmutableString("imageAtomicAnd(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x00000475u, ImmutableString("imageAtomicAnd(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x00000476u, ImmutableString("imageAtomicAnd(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x00000477u, ImmutableString("imageAtomicAnd(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x00000478u, ImmutableString("imageAtomicAnd(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x00000479u, ImmutableString("imageAtomicAnd(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x0000047au, ImmutableString("imageAtomicAnd(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x0000047bu, ImmutableString("imageAtomicAnd(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x0000047cu, ImmutableString("imageAtomicAnd(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x0000047du, ImmutableString("imageAtomicAnd(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x0000047eu, ImmutableString("imageAtomicAnd(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x0000047fu, ImmutableString("imageAtomicAnd(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000480u, ImmutableString("imageAtomicAnd(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000481u, ImmutableString("imageAtomicAnd(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000482u, ImmutableString("imageAtomicAnd(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000483u, ImmutableString("imageAtomicAnd(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x00000484u, ImmutableString("imageAtomicAnd(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x00000485u, ImmutableString("imageAtomicAnd(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x00000486u, ImmutableString("imageAtomicAnd(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x00000487u, ImmutableString("imageAtomicAnd(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x00000488u, ImmutableString("imageAtomicAnd(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x00000489u, ImmutableString("imageAtomicAnd(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x0000048au, ImmutableString("imageAtomicAnd(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x0000048bu, ImmutableString("imageAtomicAnd(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x0000048cu, ImmutableString("imageAtomicAnd(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x0000048du, ImmutableString("imageAtomicAnd(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x0000048eu, ImmutableString("imageAtomicAnd(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x0000048fu, ImmutableString("imageAtomicAnd(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x00000490u, ImmutableString("imageAtomicAnd(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x00000491u, ImmutableString("imageAtomicAnd(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x00000492u, ImmutableString("imageAtomicAnd(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x00000493u, ImmutableString("imageAtomicAnd(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x00000494u, ImmutableString("imageAtomicAnd(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x00000495u, ImmutableString("imageAtomicAnd(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x00000496u, ImmutableString("imageAtomicAnd(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x00000497u, ImmutableString("imageAtomicAnd(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x00000498u, ImmutableString("imageAtomicAnd(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000499u, ImmutableString("imageAtomicAnd(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000049au, ImmutableString("imageAtomicAnd(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000049bu, ImmutableString("imageAtomicAnd(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000049cu, ImmutableString("imageAtomicAnd(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000049du, ImmutableString("imageAtomicAnd(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000049eu, ImmutableString("imageAtomicOr(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x0000049fu, ImmutableString("imageAtomicOr(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x000004a0u, ImmutableString("imageAtomicOr(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x000004a1u, ImmutableString("imageAtomicOr(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x000004a2u, ImmutableString("imageAtomicOr(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x000004a3u, ImmutableString("imageAtomicOr(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x000004a4u, ImmutableString("imageAtomicOr(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x000004a5u, ImmutableString("imageAtomicOr(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x000004a6u, ImmutableString("imageAtomicOr(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x000004a7u, ImmutableString("imageAtomicOr(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x000004a8u, ImmutableString("imageAtomicOr(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x000004a9u, ImmutableString("imageAtomicOr(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x000004aau, ImmutableString("imageAtomicOr(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x000004abu, ImmutableString("imageAtomicOr(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x000004acu, ImmutableString("imageAtomicOr(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x000004adu, ImmutableString("imageAtomicOr(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x000004aeu, ImmutableString("imageAtomicOr(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x000004afu, ImmutableString("imageAtomicOr(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x000004b0u, ImmutableString("imageAtomicOr(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x000004b1u, ImmutableString("imageAtomicOr(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x000004b2u, ImmutableString("imageAtomicOr(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x000004b3u, ImmutableString("imageAtomicOr(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004b4u, ImmutableString("imageAtomicOr(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004b5u, ImmutableString("imageAtomicOr(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004b6u, ImmutableString("imageAtomicOr(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004b7u, ImmutableString("imageAtomicOr(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004b8u, ImmutableString("imageAtomicOr(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004b9u, ImmutableString("imageAtomicOr(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x000004bau, ImmutableString("imageAtomicOr(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x000004bbu, ImmutableString("imageAtomicOr(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x000004bcu, ImmutableString("imageAtomicOr(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x000004bdu, ImmutableString("imageAtomicOr(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x000004beu, ImmutableString("imageAtomicOr(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x000004bfu, ImmutableString("imageAtomicOr(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c0u, ImmutableString("imageAtomicOr(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c1u, ImmutableString("imageAtomicOr(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c2u, ImmutableString("imageAtomicOr(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x000004c3u, ImmutableString("imageAtomicOr(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x000004c4u, ImmutableString("imageAtomicOr(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x000004c5u, ImmutableString("imageAtomicOr(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c6u, ImmutableString("imageAtomicOr(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c7u, ImmutableString("imageAtomicOr(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c8u, ImmutableString("imageAtomicOr(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x000004c9u, ImmutableString("imageAtomicOr(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x000004cau, ImmutableString("imageAtomicOr(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x000004cbu, ImmutableString("imageAtomicOr(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x000004ccu, ImmutableString("imageAtomicOr(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x000004cdu, ImmutableString("imageAtomicOr(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x000004ceu, ImmutableString("imageAtomicOr(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x000004cfu, ImmutableString("imageAtomicOr(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x000004d0u, ImmutableString("imageAtomicOr(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x000004d1u, ImmutableString("imageAtomicOr(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x000004d2u, ImmutableString("imageAtomicOr(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x000004d3u, ImmutableString("imageAtomicOr(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x000004d4u, ImmutableString("imageAtomicXor(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x000004d5u, ImmutableString("imageAtomicXor(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x000004d6u, ImmutableString("imageAtomicXor(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x000004d7u, ImmutableString("imageAtomicXor(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x000004d8u, ImmutableString("imageAtomicXor(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x000004d9u, ImmutableString("imageAtomicXor(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x000004dau, ImmutableString("imageAtomicXor(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x000004dbu, ImmutableString("imageAtomicXor(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x000004dcu, ImmutableString("imageAtomicXor(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x000004ddu, ImmutableString("imageAtomicXor(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x000004deu, ImmutableString("imageAtomicXor(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x000004dfu, ImmutableString("imageAtomicXor(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x000004e0u, ImmutableString("imageAtomicXor(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x000004e1u, ImmutableString("imageAtomicXor(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x000004e2u, ImmutableString("imageAtomicXor(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x000004e3u, ImmutableString("imageAtomicXor(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x000004e4u, ImmutableString("imageAtomicXor(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x000004e5u, ImmutableString("imageAtomicXor(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x000004e6u, ImmutableString("imageAtomicXor(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x000004e7u, ImmutableString("imageAtomicXor(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x000004e8u, ImmutableString("imageAtomicXor(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x000004e9u, ImmutableString("imageAtomicXor(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004eau, ImmutableString("imageAtomicXor(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004ebu, ImmutableString("imageAtomicXor(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004ecu, ImmutableString("imageAtomicXor(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004edu, ImmutableString("imageAtomicXor(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004eeu, ImmutableString("imageAtomicXor(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x000004efu, ImmutableString("imageAtomicXor(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x000004f0u, ImmutableString("imageAtomicXor(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x000004f1u, ImmutableString("imageAtomicXor(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x000004f2u, ImmutableString("imageAtomicXor(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x000004f3u, ImmutableString("imageAtomicXor(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x000004f4u, ImmutableString("imageAtomicXor(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x000004f5u, ImmutableString("imageAtomicXor(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x000004f6u, ImmutableString("imageAtomicXor(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x000004f7u, ImmutableString("imageAtomicXor(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x000004f8u, ImmutableString("imageAtomicXor(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x000004f9u, ImmutableString("imageAtomicXor(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x000004fau, ImmutableString("imageAtomicXor(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x000004fbu, ImmutableString("imageAtomicXor(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x000004fcu, ImmutableString("imageAtomicXor(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x000004fdu, ImmutableString("imageAtomicXor(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x000004feu, ImmutableString("imageAtomicXor(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x000004ffu, ImmutableString("imageAtomicXor(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x00000500u, ImmutableString("imageAtomicXor(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x00000501u, ImmutableString("imageAtomicXor(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x00000502u, ImmutableString("imageAtomicXor(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x00000503u, ImmutableString("imageAtomicXor(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x00000504u, ImmutableString("imageAtomicXor(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000505u, ImmutableString("imageAtomicXor(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000506u, ImmutableString("imageAtomicXor(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000507u, ImmutableString("imageAtomicXor(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000508u, ImmutableString("imageAtomicXor(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000509u, ImmutableString("imageAtomicXor(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000050au, ImmutableString("imageAtomicExchange(00q10C00D").mangledNameHash()); - ASSERT_EQ(0x0000050bu, ImmutableString("imageAtomicExchange(00z10C00D").mangledNameHash()); - ASSERT_EQ(0x0000050cu, ImmutableString("imageAtomicExchange(01I10C00D").mangledNameHash()); - ASSERT_EQ(0x0000050du, ImmutableString("imageAtomicExchange(00r20C00D").mangledNameHash()); - ASSERT_EQ(0x0000050eu, ImmutableString("imageAtomicExchange(01A20C00D").mangledNameHash()); - ASSERT_EQ(0x0000050fu, ImmutableString("imageAtomicExchange(01J20C00D").mangledNameHash()); - ASSERT_EQ(0x00000510u, ImmutableString("imageAtomicExchange(00t20C00D").mangledNameHash()); - ASSERT_EQ(0x00000511u, ImmutableString("imageAtomicExchange(01C20C00D").mangledNameHash()); - ASSERT_EQ(0x00000512u, ImmutableString("imageAtomicExchange(01L20C00D").mangledNameHash()); - ASSERT_EQ(0x00000513u, ImmutableString("imageAtomicExchange(00y00C00D").mangledNameHash()); - ASSERT_EQ(0x00000514u, ImmutableString("imageAtomicExchange(01H00C00D").mangledNameHash()); - ASSERT_EQ(0x00000515u, ImmutableString("imageAtomicExchange(01Q00C00D").mangledNameHash()); - ASSERT_EQ(0x00000516u, ImmutableString("imageAtomicExchange(00s20C00D").mangledNameHash()); - ASSERT_EQ(0x00000517u, ImmutableString("imageAtomicExchange(01B20C00D").mangledNameHash()); - ASSERT_EQ(0x00000518u, ImmutableString("imageAtomicExchange(01K20C00D").mangledNameHash()); - ASSERT_EQ(0x00000519u, ImmutableString("imageAtomicExchange(00w20C00D").mangledNameHash()); - ASSERT_EQ(0x0000051au, ImmutableString("imageAtomicExchange(01F20C00D").mangledNameHash()); - ASSERT_EQ(0x0000051bu, ImmutableString("imageAtomicExchange(01O20C00D").mangledNameHash()); - ASSERT_EQ(0x0000051cu, ImmutableString("imageAtomicExchange(00x10C00D").mangledNameHash()); - ASSERT_EQ(0x0000051du, ImmutableString("imageAtomicExchange(01G10C00D").mangledNameHash()); - ASSERT_EQ(0x0000051eu, ImmutableString("imageAtomicExchange(01P10C00D").mangledNameHash()); - ASSERT_EQ(0x0000051fu, ImmutableString("imageAtomicExchange(00u10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000520u, ImmutableString("imageAtomicExchange(01D10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000521u, ImmutableString("imageAtomicExchange(01M10C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000522u, ImmutableString("imageAtomicExchange(00v20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000523u, ImmutableString("imageAtomicExchange(01E20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000524u, ImmutableString("imageAtomicExchange(01N20C00C00D").mangledNameHash()); - ASSERT_EQ(0x00000525u, ImmutableString("imageAtomicExchange(00q10C00C").mangledNameHash()); - ASSERT_EQ(0x00000526u, ImmutableString("imageAtomicExchange(00z10C00C").mangledNameHash()); - ASSERT_EQ(0x00000527u, ImmutableString("imageAtomicExchange(01I10C00C").mangledNameHash()); - ASSERT_EQ(0x00000528u, ImmutableString("imageAtomicExchange(00r20C00C").mangledNameHash()); - ASSERT_EQ(0x00000529u, ImmutableString("imageAtomicExchange(01A20C00C").mangledNameHash()); - ASSERT_EQ(0x0000052au, ImmutableString("imageAtomicExchange(01J20C00C").mangledNameHash()); - ASSERT_EQ(0x0000052bu, ImmutableString("imageAtomicExchange(00t20C00C").mangledNameHash()); - ASSERT_EQ(0x0000052cu, ImmutableString("imageAtomicExchange(01C20C00C").mangledNameHash()); - ASSERT_EQ(0x0000052du, ImmutableString("imageAtomicExchange(01L20C00C").mangledNameHash()); - ASSERT_EQ(0x0000052eu, ImmutableString("imageAtomicExchange(00y00C00C").mangledNameHash()); - ASSERT_EQ(0x0000052fu, ImmutableString("imageAtomicExchange(01H00C00C").mangledNameHash()); - ASSERT_EQ(0x00000530u, ImmutableString("imageAtomicExchange(01Q00C00C").mangledNameHash()); - ASSERT_EQ(0x00000531u, ImmutableString("imageAtomicExchange(00s20C00C").mangledNameHash()); - ASSERT_EQ(0x00000532u, ImmutableString("imageAtomicExchange(01B20C00C").mangledNameHash()); - ASSERT_EQ(0x00000533u, ImmutableString("imageAtomicExchange(01K20C00C").mangledNameHash()); - ASSERT_EQ(0x00000534u, ImmutableString("imageAtomicExchange(00w20C00C").mangledNameHash()); - ASSERT_EQ(0x00000535u, ImmutableString("imageAtomicExchange(01F20C00C").mangledNameHash()); - ASSERT_EQ(0x00000536u, ImmutableString("imageAtomicExchange(01O20C00C").mangledNameHash()); - ASSERT_EQ(0x00000537u, ImmutableString("imageAtomicExchange(00x10C00C").mangledNameHash()); - ASSERT_EQ(0x00000538u, ImmutableString("imageAtomicExchange(01G10C00C").mangledNameHash()); - ASSERT_EQ(0x00000539u, ImmutableString("imageAtomicExchange(01P10C00C").mangledNameHash()); - ASSERT_EQ(0x0000053au, ImmutableString("imageAtomicExchange(00u10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000053bu, ImmutableString("imageAtomicExchange(01D10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000053cu, ImmutableString("imageAtomicExchange(01M10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000053du, ImmutableString("imageAtomicExchange(00v20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000053eu, ImmutableString("imageAtomicExchange(01E20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000053fu, ImmutableString("imageAtomicExchange(01N20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000540u, ImmutableString("imageAtomicExchange(00q10C00B").mangledNameHash()); - ASSERT_EQ(0x00000541u, ImmutableString("imageAtomicExchange(00z10C00B").mangledNameHash()); - ASSERT_EQ(0x00000542u, ImmutableString("imageAtomicExchange(01I10C00B").mangledNameHash()); - ASSERT_EQ(0x00000543u, ImmutableString("imageAtomicExchange(00r20C00B").mangledNameHash()); - ASSERT_EQ(0x00000544u, ImmutableString("imageAtomicExchange(01A20C00B").mangledNameHash()); - ASSERT_EQ(0x00000545u, ImmutableString("imageAtomicExchange(01J20C00B").mangledNameHash()); - ASSERT_EQ(0x00000546u, ImmutableString("imageAtomicExchange(00t20C00B").mangledNameHash()); - ASSERT_EQ(0x00000547u, ImmutableString("imageAtomicExchange(01C20C00B").mangledNameHash()); - ASSERT_EQ(0x00000548u, ImmutableString("imageAtomicExchange(01L20C00B").mangledNameHash()); - ASSERT_EQ(0x00000549u, ImmutableString("imageAtomicExchange(00y00C00B").mangledNameHash()); - ASSERT_EQ(0x0000054au, ImmutableString("imageAtomicExchange(01H00C00B").mangledNameHash()); - ASSERT_EQ(0x0000054bu, ImmutableString("imageAtomicExchange(01Q00C00B").mangledNameHash()); - ASSERT_EQ(0x0000054cu, ImmutableString("imageAtomicExchange(00s20C00B").mangledNameHash()); - ASSERT_EQ(0x0000054du, ImmutableString("imageAtomicExchange(01B20C00B").mangledNameHash()); - ASSERT_EQ(0x0000054eu, ImmutableString("imageAtomicExchange(01K20C00B").mangledNameHash()); - ASSERT_EQ(0x0000054fu, ImmutableString("imageAtomicExchange(00w20C00B").mangledNameHash()); - ASSERT_EQ(0x00000550u, ImmutableString("imageAtomicExchange(01F20C00B").mangledNameHash()); - ASSERT_EQ(0x00000551u, ImmutableString("imageAtomicExchange(01O20C00B").mangledNameHash()); - ASSERT_EQ(0x00000552u, ImmutableString("imageAtomicExchange(00x10C00B").mangledNameHash()); - ASSERT_EQ(0x00000553u, ImmutableString("imageAtomicExchange(01G10C00B").mangledNameHash()); - ASSERT_EQ(0x00000554u, ImmutableString("imageAtomicExchange(01P10C00B").mangledNameHash()); - ASSERT_EQ(0x00000555u, ImmutableString("imageAtomicExchange(00u10C00C00B").mangledNameHash()); - ASSERT_EQ(0x00000556u, ImmutableString("imageAtomicExchange(01D10C00C00B").mangledNameHash()); - ASSERT_EQ(0x00000557u, ImmutableString("imageAtomicExchange(01M10C00C00B").mangledNameHash()); - ASSERT_EQ(0x00000558u, ImmutableString("imageAtomicExchange(00v20C00C00B").mangledNameHash()); - ASSERT_EQ(0x00000559u, ImmutableString("imageAtomicExchange(01E20C00C00B").mangledNameHash()); - ASSERT_EQ(0x0000055au, ImmutableString("imageAtomicExchange(01N20C00C00B").mangledNameHash()); - ASSERT_EQ(0x0000055bu, ImmutableString("imageAtomicCompSwap(00q10C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000055cu, ImmutableString("imageAtomicCompSwap(00z10C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000055du, ImmutableString("imageAtomicCompSwap(01I10C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000055eu, ImmutableString("imageAtomicCompSwap(00r20C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000055fu, ImmutableString("imageAtomicCompSwap(01A20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000560u, ImmutableString("imageAtomicCompSwap(01J20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000561u, ImmutableString("imageAtomicCompSwap(00t20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000562u, ImmutableString("imageAtomicCompSwap(01C20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000563u, ImmutableString("imageAtomicCompSwap(01L20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000564u, ImmutableString("imageAtomicCompSwap(00y00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000565u, ImmutableString("imageAtomicCompSwap(01H00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000566u, ImmutableString("imageAtomicCompSwap(01Q00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000567u, ImmutableString("imageAtomicCompSwap(00s20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000568u, ImmutableString("imageAtomicCompSwap(01B20C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000569u, ImmutableString("imageAtomicCompSwap(01K20C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000056au, ImmutableString("imageAtomicCompSwap(00w20C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000056bu, ImmutableString("imageAtomicCompSwap(01F20C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000056cu, ImmutableString("imageAtomicCompSwap(01O20C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000056du, ImmutableString("imageAtomicCompSwap(00x10C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000056eu, ImmutableString("imageAtomicCompSwap(01G10C00D00D").mangledNameHash()); - ASSERT_EQ(0x0000056fu, ImmutableString("imageAtomicCompSwap(01P10C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000570u, - ImmutableString("imageAtomicCompSwap(00u10C00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000571u, - ImmutableString("imageAtomicCompSwap(01D10C00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000572u, - ImmutableString("imageAtomicCompSwap(01M10C00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000573u, - ImmutableString("imageAtomicCompSwap(00v20C00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000574u, - ImmutableString("imageAtomicCompSwap(01E20C00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000575u, - ImmutableString("imageAtomicCompSwap(01N20C00C00D00D").mangledNameHash()); - ASSERT_EQ(0x00000576u, ImmutableString("imageAtomicCompSwap(00q10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000577u, ImmutableString("imageAtomicCompSwap(00z10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000578u, ImmutableString("imageAtomicCompSwap(01I10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000579u, ImmutableString("imageAtomicCompSwap(00r20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000057au, ImmutableString("imageAtomicCompSwap(01A20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000057bu, ImmutableString("imageAtomicCompSwap(01J20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000057cu, ImmutableString("imageAtomicCompSwap(00t20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000057du, ImmutableString("imageAtomicCompSwap(01C20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000057eu, ImmutableString("imageAtomicCompSwap(01L20C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000057fu, ImmutableString("imageAtomicCompSwap(00y00C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000580u, ImmutableString("imageAtomicCompSwap(01H00C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000581u, ImmutableString("imageAtomicCompSwap(01Q00C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000582u, ImmutableString("imageAtomicCompSwap(00s20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000583u, ImmutableString("imageAtomicCompSwap(01B20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000584u, ImmutableString("imageAtomicCompSwap(01K20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000585u, ImmutableString("imageAtomicCompSwap(00w20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000586u, ImmutableString("imageAtomicCompSwap(01F20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000587u, ImmutableString("imageAtomicCompSwap(01O20C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000588u, ImmutableString("imageAtomicCompSwap(00x10C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000589u, ImmutableString("imageAtomicCompSwap(01G10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000058au, ImmutableString("imageAtomicCompSwap(01P10C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000058bu, - ImmutableString("imageAtomicCompSwap(00u10C00C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000058cu, - ImmutableString("imageAtomicCompSwap(01D10C00C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000058du, - ImmutableString("imageAtomicCompSwap(01M10C00C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000058eu, - ImmutableString("imageAtomicCompSwap(00v20C00C00C00C").mangledNameHash()); - ASSERT_EQ(0x0000058fu, - ImmutableString("imageAtomicCompSwap(01E20C00C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000590u, - ImmutableString("imageAtomicCompSwap(01N20C00C00C00C").mangledNameHash()); - ASSERT_EQ(0x00000591u, ImmutableString("pixelLocalLoadANGLE(01R").mangledNameHash()); - ASSERT_EQ(0x00000592u, ImmutableString("pixelLocalLoadANGLE(01S").mangledNameHash()); - ASSERT_EQ(0x00000593u, ImmutableString("pixelLocalLoadANGLE(01T").mangledNameHash()); - ASSERT_EQ(0x00000594u, ImmutableString("pixelLocalStoreANGLE(01R30B").mangledNameHash()); - ASSERT_EQ(0x00000595u, ImmutableString("pixelLocalStoreANGLE(01S30C").mangledNameHash()); - ASSERT_EQ(0x00000596u, ImmutableString("pixelLocalStoreANGLE(01T30D").mangledNameHash()); - ASSERT_EQ(0x00000597u, ImmutableString("beginInvocationInterlockNV(").mangledNameHash()); - ASSERT_EQ(0x00000598u, ImmutableString("endInvocationInterlockNV(").mangledNameHash()); - ASSERT_EQ(0x00000599u, ImmutableString("beginFragmentShaderOrderingINTEL(").mangledNameHash()); - ASSERT_EQ(0x0000059au, ImmutableString("beginInvocationInterlockARB(").mangledNameHash()); - ASSERT_EQ(0x0000059bu, ImmutableString("endInvocationInterlockARB(").mangledNameHash()); - ASSERT_EQ(0x0000059cu, ImmutableString("memoryBarrier(").mangledNameHash()); - ASSERT_EQ(0x0000059du, ImmutableString("memoryBarrierAtomicCounter(").mangledNameHash()); - ASSERT_EQ(0x0000059eu, ImmutableString("memoryBarrierBuffer(").mangledNameHash()); - ASSERT_EQ(0x0000059fu, ImmutableString("memoryBarrierImage(").mangledNameHash()); - ASSERT_EQ(0x000005a0u, ImmutableString("barrier(").mangledNameHash()); - ASSERT_EQ(0x000005a1u, ImmutableString("memoryBarrierShared(").mangledNameHash()); - ASSERT_EQ(0x000005a2u, ImmutableString("groupMemoryBarrier(").mangledNameHash()); - ASSERT_EQ(0x000005a3u, ImmutableString("EmitVertex(").mangledNameHash()); - ASSERT_EQ(0x000005a4u, ImmutableString("EndPrimitive(").mangledNameHash()); - ASSERT_EQ(0x000005a5u, ImmutableString("subpassLoad(01U").mangledNameHash()); - ASSERT_EQ(0x000005a6u, ImmutableString("subpassLoad(01V").mangledNameHash()); - ASSERT_EQ(0x000005a7u, ImmutableString("subpassLoad(01W").mangledNameHash()); - ASSERT_EQ(0x000005a8u, ImmutableString("numSamples(").mangledNameHash()); - ASSERT_EQ(0x000005a9u, ImmutableString("samplePosition(00D").mangledNameHash()); - ASSERT_EQ(0x000005aau, ImmutableString("interpolateAtCenter(00B").mangledNameHash()); - ASSERT_EQ(0x000005abu, ImmutableString("interpolateAtCenter(10B").mangledNameHash()); - ASSERT_EQ(0x000005acu, ImmutableString("interpolateAtCenter(20B").mangledNameHash()); - ASSERT_EQ(0x000005adu, ImmutableString("interpolateAtCenter(30B").mangledNameHash()); - ASSERT_EQ(0x000005aeu, ImmutableString("saturate(00B").mangledNameHash()); - ASSERT_EQ(0x000005afu, ImmutableString("saturate(10B").mangledNameHash()); - ASSERT_EQ(0x000005b0u, ImmutableString("saturate(20B").mangledNameHash()); - ASSERT_EQ(0x000005b1u, ImmutableString("saturate(30B").mangledNameHash()); - ASSERT_EQ(0x000005b2u, ImmutableString("gl_DepthRangeParameters").mangledNameHash()); - ASSERT_EQ(0x000005b3u, ImmutableString("gl_DepthRange").mangledNameHash()); - ASSERT_EQ(0x000005b4u, ImmutableString("gl_NumSamples").mangledNameHash()); - ASSERT_EQ(0x000005b5u, ImmutableString("gl_MaxVertexAttribs").mangledNameHash()); - ASSERT_EQ(0x000005b6u, ImmutableString("gl_MaxVertexUniformVectors").mangledNameHash()); - ASSERT_EQ(0x000005b7u, ImmutableString("gl_MaxVertexTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005b8u, ImmutableString("gl_MaxCombinedTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005b9u, ImmutableString("gl_MaxTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005bau, ImmutableString("gl_MaxFragmentUniformVectors").mangledNameHash()); - ASSERT_EQ(0x000005bbu, ImmutableString("gl_MaxVaryingVectors").mangledNameHash()); - ASSERT_EQ(0x000005bcu, ImmutableString("gl_MaxDrawBuffers").mangledNameHash()); - ASSERT_EQ(0x000005bdu, ImmutableString("gl_MaxDualSourceDrawBuffersEXT").mangledNameHash()); - ASSERT_EQ(0x000005beu, ImmutableString("gl_MaxVertexOutputVectors").mangledNameHash()); - ASSERT_EQ(0x000005bfu, ImmutableString("gl_MaxFragmentInputVectors").mangledNameHash()); - ASSERT_EQ(0x000005c0u, ImmutableString("gl_MinProgramTexelOffset").mangledNameHash()); - ASSERT_EQ(0x000005c1u, ImmutableString("gl_MaxProgramTexelOffset").mangledNameHash()); - ASSERT_EQ(0x000005c2u, ImmutableString("gl_MaxImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005c3u, ImmutableString("gl_MaxVertexImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005c4u, ImmutableString("gl_MaxFragmentImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005c5u, ImmutableString("gl_MaxComputeImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005c6u, ImmutableString("gl_MaxCombinedImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005c7u, + ASSERT_EQ(0x000003beu, ImmutableString("imageLoad(00z20C").mangledNameHash()); + ASSERT_EQ(0x000003bfu, ImmutableString("imageLoad(01F20C").mangledNameHash()); + ASSERT_EQ(0x000003c0u, ImmutableString("imageLoad(00u00C").mangledNameHash()); + ASSERT_EQ(0x000003c1u, ImmutableString("imageLoad(01A00C").mangledNameHash()); + ASSERT_EQ(0x000003c2u, ImmutableString("imageLoad(01G00C").mangledNameHash()); + ASSERT_EQ(0x000003c3u, ImmutableString("imageAtomicAdd(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x000003c4u, ImmutableString("imageAtomicAdd(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x000003c5u, ImmutableString("imageAtomicAdd(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x000003c6u, ImmutableString("imageAtomicAdd(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x000003c7u, ImmutableString("imageAtomicAdd(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x000003c8u, ImmutableString("imageAtomicAdd(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x000003c9u, ImmutableString("imageAtomicAdd(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x000003cau, ImmutableString("imageAtomicAdd(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x000003cbu, ImmutableString("imageAtomicAdd(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x000003ccu, ImmutableString("imageAtomicAdd(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x000003cdu, ImmutableString("imageAtomicAdd(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x000003ceu, ImmutableString("imageAtomicAdd(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x000003cfu, ImmutableString("imageAtomicAdd(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x000003d0u, ImmutableString("imageAtomicAdd(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x000003d1u, ImmutableString("imageAtomicAdd(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x000003d2u, ImmutableString("imageAtomicAdd(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x000003d3u, ImmutableString("imageAtomicAdd(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x000003d4u, ImmutableString("imageAtomicAdd(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x000003d5u, ImmutableString("imageAtomicAdd(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x000003d6u, ImmutableString("imageAtomicAdd(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x000003d7u, ImmutableString("imageAtomicAdd(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x000003d8u, ImmutableString("imageAtomicAdd(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x000003d9u, ImmutableString("imageAtomicAdd(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x000003dau, ImmutableString("imageAtomicAdd(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x000003dbu, ImmutableString("imageAtomicAdd(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x000003dcu, ImmutableString("imageAtomicAdd(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x000003ddu, ImmutableString("imageAtomicAdd(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x000003deu, ImmutableString("imageAtomicAdd(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x000003dfu, ImmutableString("imageAtomicAdd(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x000003e0u, ImmutableString("imageAtomicAdd(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x000003e1u, ImmutableString("imageAtomicAdd(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x000003e2u, ImmutableString("imageAtomicAdd(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x000003e3u, ImmutableString("imageAtomicAdd(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x000003e4u, ImmutableString("imageAtomicAdd(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x000003e5u, ImmutableString("imageAtomicAdd(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x000003e6u, ImmutableString("imageAtomicAdd(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x000003e7u, ImmutableString("imageAtomicMin(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x000003e8u, ImmutableString("imageAtomicMin(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x000003e9u, ImmutableString("imageAtomicMin(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x000003eau, ImmutableString("imageAtomicMin(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x000003ebu, ImmutableString("imageAtomicMin(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x000003ecu, ImmutableString("imageAtomicMin(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x000003edu, ImmutableString("imageAtomicMin(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x000003eeu, ImmutableString("imageAtomicMin(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x000003efu, ImmutableString("imageAtomicMin(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f0u, ImmutableString("imageAtomicMin(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x000003f1u, ImmutableString("imageAtomicMin(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x000003f2u, ImmutableString("imageAtomicMin(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x000003f3u, ImmutableString("imageAtomicMin(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f4u, ImmutableString("imageAtomicMin(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f5u, ImmutableString("imageAtomicMin(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f6u, ImmutableString("imageAtomicMin(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f7u, ImmutableString("imageAtomicMin(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f8u, ImmutableString("imageAtomicMin(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x000003f9u, ImmutableString("imageAtomicMin(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x000003fau, ImmutableString("imageAtomicMin(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x000003fbu, ImmutableString("imageAtomicMin(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x000003fcu, ImmutableString("imageAtomicMin(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x000003fdu, ImmutableString("imageAtomicMin(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x000003feu, ImmutableString("imageAtomicMin(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x000003ffu, ImmutableString("imageAtomicMin(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x00000400u, ImmutableString("imageAtomicMin(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x00000401u, ImmutableString("imageAtomicMin(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x00000402u, ImmutableString("imageAtomicMin(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x00000403u, ImmutableString("imageAtomicMin(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x00000404u, ImmutableString("imageAtomicMin(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x00000405u, ImmutableString("imageAtomicMin(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x00000406u, ImmutableString("imageAtomicMin(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x00000407u, ImmutableString("imageAtomicMin(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x00000408u, ImmutableString("imageAtomicMin(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x00000409u, ImmutableString("imageAtomicMin(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x0000040au, ImmutableString("imageAtomicMin(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x0000040bu, ImmutableString("imageAtomicMax(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x0000040cu, ImmutableString("imageAtomicMax(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x0000040du, ImmutableString("imageAtomicMax(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x0000040eu, ImmutableString("imageAtomicMax(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x0000040fu, ImmutableString("imageAtomicMax(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x00000410u, ImmutableString("imageAtomicMax(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x00000411u, ImmutableString("imageAtomicMax(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x00000412u, ImmutableString("imageAtomicMax(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x00000413u, ImmutableString("imageAtomicMax(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x00000414u, ImmutableString("imageAtomicMax(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x00000415u, ImmutableString("imageAtomicMax(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x00000416u, ImmutableString("imageAtomicMax(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x00000417u, ImmutableString("imageAtomicMax(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x00000418u, ImmutableString("imageAtomicMax(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x00000419u, ImmutableString("imageAtomicMax(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x0000041au, ImmutableString("imageAtomicMax(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x0000041bu, ImmutableString("imageAtomicMax(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x0000041cu, ImmutableString("imageAtomicMax(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x0000041du, ImmutableString("imageAtomicMax(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x0000041eu, ImmutableString("imageAtomicMax(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x0000041fu, ImmutableString("imageAtomicMax(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x00000420u, ImmutableString("imageAtomicMax(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x00000421u, ImmutableString("imageAtomicMax(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x00000422u, ImmutableString("imageAtomicMax(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x00000423u, ImmutableString("imageAtomicMax(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x00000424u, ImmutableString("imageAtomicMax(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x00000425u, ImmutableString("imageAtomicMax(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x00000426u, ImmutableString("imageAtomicMax(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x00000427u, ImmutableString("imageAtomicMax(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x00000428u, ImmutableString("imageAtomicMax(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x00000429u, ImmutableString("imageAtomicMax(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x0000042au, ImmutableString("imageAtomicMax(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x0000042bu, ImmutableString("imageAtomicMax(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x0000042cu, ImmutableString("imageAtomicMax(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x0000042du, ImmutableString("imageAtomicMax(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x0000042eu, ImmutableString("imageAtomicMax(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x0000042fu, ImmutableString("imageAtomicAnd(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x00000430u, ImmutableString("imageAtomicAnd(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x00000431u, ImmutableString("imageAtomicAnd(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x00000432u, ImmutableString("imageAtomicAnd(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x00000433u, ImmutableString("imageAtomicAnd(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x00000434u, ImmutableString("imageAtomicAnd(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x00000435u, ImmutableString("imageAtomicAnd(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x00000436u, ImmutableString("imageAtomicAnd(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x00000437u, ImmutableString("imageAtomicAnd(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x00000438u, ImmutableString("imageAtomicAnd(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x00000439u, ImmutableString("imageAtomicAnd(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x0000043au, ImmutableString("imageAtomicAnd(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x0000043bu, ImmutableString("imageAtomicAnd(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x0000043cu, ImmutableString("imageAtomicAnd(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x0000043du, ImmutableString("imageAtomicAnd(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x0000043eu, ImmutableString("imageAtomicAnd(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x0000043fu, ImmutableString("imageAtomicAnd(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x00000440u, ImmutableString("imageAtomicAnd(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x00000441u, ImmutableString("imageAtomicAnd(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x00000442u, ImmutableString("imageAtomicAnd(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x00000443u, ImmutableString("imageAtomicAnd(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x00000444u, ImmutableString("imageAtomicAnd(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x00000445u, ImmutableString("imageAtomicAnd(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x00000446u, ImmutableString("imageAtomicAnd(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x00000447u, ImmutableString("imageAtomicAnd(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x00000448u, ImmutableString("imageAtomicAnd(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x00000449u, ImmutableString("imageAtomicAnd(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x0000044au, ImmutableString("imageAtomicAnd(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x0000044bu, ImmutableString("imageAtomicAnd(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x0000044cu, ImmutableString("imageAtomicAnd(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x0000044du, ImmutableString("imageAtomicAnd(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x0000044eu, ImmutableString("imageAtomicAnd(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x0000044fu, ImmutableString("imageAtomicAnd(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x00000450u, ImmutableString("imageAtomicAnd(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x00000451u, ImmutableString("imageAtomicAnd(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x00000452u, ImmutableString("imageAtomicAnd(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x00000453u, ImmutableString("imageAtomicOr(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x00000454u, ImmutableString("imageAtomicOr(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x00000455u, ImmutableString("imageAtomicOr(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x00000456u, ImmutableString("imageAtomicOr(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x00000457u, ImmutableString("imageAtomicOr(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x00000458u, ImmutableString("imageAtomicOr(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x00000459u, ImmutableString("imageAtomicOr(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x0000045au, ImmutableString("imageAtomicOr(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x0000045bu, ImmutableString("imageAtomicOr(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x0000045cu, ImmutableString("imageAtomicOr(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x0000045du, ImmutableString("imageAtomicOr(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x0000045eu, ImmutableString("imageAtomicOr(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x0000045fu, ImmutableString("imageAtomicOr(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x00000460u, ImmutableString("imageAtomicOr(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x00000461u, ImmutableString("imageAtomicOr(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x00000462u, ImmutableString("imageAtomicOr(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x00000463u, ImmutableString("imageAtomicOr(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x00000464u, ImmutableString("imageAtomicOr(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x00000465u, ImmutableString("imageAtomicOr(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x00000466u, ImmutableString("imageAtomicOr(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x00000467u, ImmutableString("imageAtomicOr(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x00000468u, ImmutableString("imageAtomicOr(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x00000469u, ImmutableString("imageAtomicOr(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x0000046au, ImmutableString("imageAtomicOr(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x0000046bu, ImmutableString("imageAtomicOr(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x0000046cu, ImmutableString("imageAtomicOr(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x0000046du, ImmutableString("imageAtomicOr(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x0000046eu, ImmutableString("imageAtomicOr(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x0000046fu, ImmutableString("imageAtomicOr(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x00000470u, ImmutableString("imageAtomicOr(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x00000471u, ImmutableString("imageAtomicOr(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x00000472u, ImmutableString("imageAtomicOr(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x00000473u, ImmutableString("imageAtomicOr(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x00000474u, ImmutableString("imageAtomicOr(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x00000475u, ImmutableString("imageAtomicOr(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x00000476u, ImmutableString("imageAtomicOr(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x00000477u, ImmutableString("imageAtomicXor(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x00000478u, ImmutableString("imageAtomicXor(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x00000479u, ImmutableString("imageAtomicXor(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x0000047au, ImmutableString("imageAtomicXor(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x0000047bu, ImmutableString("imageAtomicXor(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x0000047cu, ImmutableString("imageAtomicXor(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x0000047du, ImmutableString("imageAtomicXor(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x0000047eu, ImmutableString("imageAtomicXor(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x0000047fu, ImmutableString("imageAtomicXor(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x00000480u, ImmutableString("imageAtomicXor(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x00000481u, ImmutableString("imageAtomicXor(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x00000482u, ImmutableString("imageAtomicXor(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x00000483u, ImmutableString("imageAtomicXor(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x00000484u, ImmutableString("imageAtomicXor(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x00000485u, ImmutableString("imageAtomicXor(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x00000486u, ImmutableString("imageAtomicXor(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x00000487u, ImmutableString("imageAtomicXor(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x00000488u, ImmutableString("imageAtomicXor(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x00000489u, ImmutableString("imageAtomicXor(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x0000048au, ImmutableString("imageAtomicXor(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x0000048bu, ImmutableString("imageAtomicXor(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x0000048cu, ImmutableString("imageAtomicXor(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x0000048du, ImmutableString("imageAtomicXor(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x0000048eu, ImmutableString("imageAtomicXor(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x0000048fu, ImmutableString("imageAtomicXor(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x00000490u, ImmutableString("imageAtomicXor(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x00000491u, ImmutableString("imageAtomicXor(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x00000492u, ImmutableString("imageAtomicXor(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x00000493u, ImmutableString("imageAtomicXor(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x00000494u, ImmutableString("imageAtomicXor(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x00000495u, ImmutableString("imageAtomicXor(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x00000496u, ImmutableString("imageAtomicXor(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x00000497u, ImmutableString("imageAtomicXor(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x00000498u, ImmutableString("imageAtomicXor(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x00000499u, ImmutableString("imageAtomicXor(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x0000049au, ImmutableString("imageAtomicXor(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x0000049bu, ImmutableString("imageAtomicExchange(00p10C00D").mangledNameHash()); + ASSERT_EQ(0x0000049cu, ImmutableString("imageAtomicExchange(00v10C00D").mangledNameHash()); + ASSERT_EQ(0x0000049du, ImmutableString("imageAtomicExchange(01B10C00D").mangledNameHash()); + ASSERT_EQ(0x0000049eu, ImmutableString("imageAtomicExchange(00q20C00D").mangledNameHash()); + ASSERT_EQ(0x0000049fu, ImmutableString("imageAtomicExchange(00w20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a0u, ImmutableString("imageAtomicExchange(01C20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a1u, ImmutableString("imageAtomicExchange(00s20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a2u, ImmutableString("imageAtomicExchange(00y20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a3u, ImmutableString("imageAtomicExchange(01E20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a4u, ImmutableString("imageAtomicExchange(00u00C00D").mangledNameHash()); + ASSERT_EQ(0x000004a5u, ImmutableString("imageAtomicExchange(01A00C00D").mangledNameHash()); + ASSERT_EQ(0x000004a6u, ImmutableString("imageAtomicExchange(01G00C00D").mangledNameHash()); + ASSERT_EQ(0x000004a7u, ImmutableString("imageAtomicExchange(00r20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a8u, ImmutableString("imageAtomicExchange(00x20C00D").mangledNameHash()); + ASSERT_EQ(0x000004a9u, ImmutableString("imageAtomicExchange(01D20C00D").mangledNameHash()); + ASSERT_EQ(0x000004aau, ImmutableString("imageAtomicExchange(00t20C00D").mangledNameHash()); + ASSERT_EQ(0x000004abu, ImmutableString("imageAtomicExchange(00z20C00D").mangledNameHash()); + ASSERT_EQ(0x000004acu, ImmutableString("imageAtomicExchange(01F20C00D").mangledNameHash()); + ASSERT_EQ(0x000004adu, ImmutableString("imageAtomicExchange(00p10C00C").mangledNameHash()); + ASSERT_EQ(0x000004aeu, ImmutableString("imageAtomicExchange(00v10C00C").mangledNameHash()); + ASSERT_EQ(0x000004afu, ImmutableString("imageAtomicExchange(01B10C00C").mangledNameHash()); + ASSERT_EQ(0x000004b0u, ImmutableString("imageAtomicExchange(00q20C00C").mangledNameHash()); + ASSERT_EQ(0x000004b1u, ImmutableString("imageAtomicExchange(00w20C00C").mangledNameHash()); + ASSERT_EQ(0x000004b2u, ImmutableString("imageAtomicExchange(01C20C00C").mangledNameHash()); + ASSERT_EQ(0x000004b3u, ImmutableString("imageAtomicExchange(00s20C00C").mangledNameHash()); + ASSERT_EQ(0x000004b4u, ImmutableString("imageAtomicExchange(00y20C00C").mangledNameHash()); + ASSERT_EQ(0x000004b5u, ImmutableString("imageAtomicExchange(01E20C00C").mangledNameHash()); + ASSERT_EQ(0x000004b6u, ImmutableString("imageAtomicExchange(00u00C00C").mangledNameHash()); + ASSERT_EQ(0x000004b7u, ImmutableString("imageAtomicExchange(01A00C00C").mangledNameHash()); + ASSERT_EQ(0x000004b8u, ImmutableString("imageAtomicExchange(01G00C00C").mangledNameHash()); + ASSERT_EQ(0x000004b9u, ImmutableString("imageAtomicExchange(00r20C00C").mangledNameHash()); + ASSERT_EQ(0x000004bau, ImmutableString("imageAtomicExchange(00x20C00C").mangledNameHash()); + ASSERT_EQ(0x000004bbu, ImmutableString("imageAtomicExchange(01D20C00C").mangledNameHash()); + ASSERT_EQ(0x000004bcu, ImmutableString("imageAtomicExchange(00t20C00C").mangledNameHash()); + ASSERT_EQ(0x000004bdu, ImmutableString("imageAtomicExchange(00z20C00C").mangledNameHash()); + ASSERT_EQ(0x000004beu, ImmutableString("imageAtomicExchange(01F20C00C").mangledNameHash()); + ASSERT_EQ(0x000004bfu, ImmutableString("imageAtomicExchange(00p10C00B").mangledNameHash()); + ASSERT_EQ(0x000004c0u, ImmutableString("imageAtomicExchange(00v10C00B").mangledNameHash()); + ASSERT_EQ(0x000004c1u, ImmutableString("imageAtomicExchange(01B10C00B").mangledNameHash()); + ASSERT_EQ(0x000004c2u, ImmutableString("imageAtomicExchange(00q20C00B").mangledNameHash()); + ASSERT_EQ(0x000004c3u, ImmutableString("imageAtomicExchange(00w20C00B").mangledNameHash()); + ASSERT_EQ(0x000004c4u, ImmutableString("imageAtomicExchange(01C20C00B").mangledNameHash()); + ASSERT_EQ(0x000004c5u, ImmutableString("imageAtomicExchange(00s20C00B").mangledNameHash()); + ASSERT_EQ(0x000004c6u, ImmutableString("imageAtomicExchange(00y20C00B").mangledNameHash()); + ASSERT_EQ(0x000004c7u, ImmutableString("imageAtomicExchange(01E20C00B").mangledNameHash()); + ASSERT_EQ(0x000004c8u, ImmutableString("imageAtomicExchange(00u00C00B").mangledNameHash()); + ASSERT_EQ(0x000004c9u, ImmutableString("imageAtomicExchange(01A00C00B").mangledNameHash()); + ASSERT_EQ(0x000004cau, ImmutableString("imageAtomicExchange(01G00C00B").mangledNameHash()); + ASSERT_EQ(0x000004cbu, ImmutableString("imageAtomicExchange(00r20C00B").mangledNameHash()); + ASSERT_EQ(0x000004ccu, ImmutableString("imageAtomicExchange(00x20C00B").mangledNameHash()); + ASSERT_EQ(0x000004cdu, ImmutableString("imageAtomicExchange(01D20C00B").mangledNameHash()); + ASSERT_EQ(0x000004ceu, ImmutableString("imageAtomicExchange(00t20C00B").mangledNameHash()); + ASSERT_EQ(0x000004cfu, ImmutableString("imageAtomicExchange(00z20C00B").mangledNameHash()); + ASSERT_EQ(0x000004d0u, ImmutableString("imageAtomicExchange(01F20C00B").mangledNameHash()); + ASSERT_EQ(0x000004d1u, ImmutableString("imageAtomicCompSwap(00p10C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d2u, ImmutableString("imageAtomicCompSwap(00v10C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d3u, ImmutableString("imageAtomicCompSwap(01B10C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d4u, ImmutableString("imageAtomicCompSwap(00q20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d5u, ImmutableString("imageAtomicCompSwap(00w20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d6u, ImmutableString("imageAtomicCompSwap(01C20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d7u, ImmutableString("imageAtomicCompSwap(00s20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d8u, ImmutableString("imageAtomicCompSwap(00y20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004d9u, ImmutableString("imageAtomicCompSwap(01E20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004dau, ImmutableString("imageAtomicCompSwap(00u00C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004dbu, ImmutableString("imageAtomicCompSwap(01A00C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004dcu, ImmutableString("imageAtomicCompSwap(01G00C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004ddu, ImmutableString("imageAtomicCompSwap(00r20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004deu, ImmutableString("imageAtomicCompSwap(00x20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004dfu, ImmutableString("imageAtomicCompSwap(01D20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004e0u, ImmutableString("imageAtomicCompSwap(00t20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004e1u, ImmutableString("imageAtomicCompSwap(00z20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004e2u, ImmutableString("imageAtomicCompSwap(01F20C00D00D").mangledNameHash()); + ASSERT_EQ(0x000004e3u, ImmutableString("imageAtomicCompSwap(00p10C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004e4u, ImmutableString("imageAtomicCompSwap(00v10C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004e5u, ImmutableString("imageAtomicCompSwap(01B10C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004e6u, ImmutableString("imageAtomicCompSwap(00q20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004e7u, ImmutableString("imageAtomicCompSwap(00w20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004e8u, ImmutableString("imageAtomicCompSwap(01C20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004e9u, ImmutableString("imageAtomicCompSwap(00s20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004eau, ImmutableString("imageAtomicCompSwap(00y20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004ebu, ImmutableString("imageAtomicCompSwap(01E20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004ecu, ImmutableString("imageAtomicCompSwap(00u00C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004edu, ImmutableString("imageAtomicCompSwap(01A00C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004eeu, ImmutableString("imageAtomicCompSwap(01G00C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004efu, ImmutableString("imageAtomicCompSwap(00r20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004f0u, ImmutableString("imageAtomicCompSwap(00x20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004f1u, ImmutableString("imageAtomicCompSwap(01D20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004f2u, ImmutableString("imageAtomicCompSwap(00t20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004f3u, ImmutableString("imageAtomicCompSwap(00z20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004f4u, ImmutableString("imageAtomicCompSwap(01F20C00C00C").mangledNameHash()); + ASSERT_EQ(0x000004f5u, ImmutableString("pixelLocalLoadANGLE(01H").mangledNameHash()); + ASSERT_EQ(0x000004f6u, ImmutableString("pixelLocalLoadANGLE(01I").mangledNameHash()); + ASSERT_EQ(0x000004f7u, ImmutableString("pixelLocalLoadANGLE(01J").mangledNameHash()); + ASSERT_EQ(0x000004f8u, ImmutableString("pixelLocalStoreANGLE(01H30B").mangledNameHash()); + ASSERT_EQ(0x000004f9u, ImmutableString("pixelLocalStoreANGLE(01I30C").mangledNameHash()); + ASSERT_EQ(0x000004fau, ImmutableString("pixelLocalStoreANGLE(01J30D").mangledNameHash()); + ASSERT_EQ(0x000004fbu, ImmutableString("beginInvocationInterlockNV(").mangledNameHash()); + ASSERT_EQ(0x000004fcu, ImmutableString("endInvocationInterlockNV(").mangledNameHash()); + ASSERT_EQ(0x000004fdu, ImmutableString("beginFragmentShaderOrderingINTEL(").mangledNameHash()); + ASSERT_EQ(0x000004feu, ImmutableString("beginInvocationInterlockARB(").mangledNameHash()); + ASSERT_EQ(0x000004ffu, ImmutableString("endInvocationInterlockARB(").mangledNameHash()); + ASSERT_EQ(0x00000500u, ImmutableString("memoryBarrier(").mangledNameHash()); + ASSERT_EQ(0x00000501u, ImmutableString("memoryBarrierAtomicCounter(").mangledNameHash()); + ASSERT_EQ(0x00000502u, ImmutableString("memoryBarrierBuffer(").mangledNameHash()); + ASSERT_EQ(0x00000503u, ImmutableString("memoryBarrierImage(").mangledNameHash()); + ASSERT_EQ(0x00000504u, ImmutableString("barrier(").mangledNameHash()); + ASSERT_EQ(0x00000505u, ImmutableString("memoryBarrierShared(").mangledNameHash()); + ASSERT_EQ(0x00000506u, ImmutableString("groupMemoryBarrier(").mangledNameHash()); + ASSERT_EQ(0x00000507u, ImmutableString("EmitVertex(").mangledNameHash()); + ASSERT_EQ(0x00000508u, ImmutableString("EndPrimitive(").mangledNameHash()); + ASSERT_EQ(0x00000509u, ImmutableString("subpassLoad(01K").mangledNameHash()); + ASSERT_EQ(0x0000050au, ImmutableString("subpassLoad(01L").mangledNameHash()); + ASSERT_EQ(0x0000050bu, ImmutableString("subpassLoad(01M").mangledNameHash()); + ASSERT_EQ(0x0000050cu, ImmutableString("numSamples(").mangledNameHash()); + ASSERT_EQ(0x0000050du, ImmutableString("samplePosition(00D").mangledNameHash()); + ASSERT_EQ(0x0000050eu, ImmutableString("interpolateAtCenter(00B").mangledNameHash()); + ASSERT_EQ(0x0000050fu, ImmutableString("interpolateAtCenter(10B").mangledNameHash()); + ASSERT_EQ(0x00000510u, ImmutableString("interpolateAtCenter(20B").mangledNameHash()); + ASSERT_EQ(0x00000511u, ImmutableString("interpolateAtCenter(30B").mangledNameHash()); + ASSERT_EQ(0x00000512u, ImmutableString("loopForwardProgress(").mangledNameHash()); + ASSERT_EQ(0x00000513u, ImmutableString("saturate(00B").mangledNameHash()); + ASSERT_EQ(0x00000514u, ImmutableString("saturate(10B").mangledNameHash()); + ASSERT_EQ(0x00000515u, ImmutableString("saturate(20B").mangledNameHash()); + ASSERT_EQ(0x00000516u, ImmutableString("saturate(30B").mangledNameHash()); + ASSERT_EQ(0x00000517u, ImmutableString("gl_DepthRangeParameters").mangledNameHash()); + ASSERT_EQ(0x00000518u, ImmutableString("gl_DepthRange").mangledNameHash()); + ASSERT_EQ(0x00000519u, ImmutableString("gl_NumSamples").mangledNameHash()); + ASSERT_EQ(0x0000051au, ImmutableString("gl_MaxVertexAttribs").mangledNameHash()); + ASSERT_EQ(0x0000051bu, ImmutableString("gl_MaxVertexUniformVectors").mangledNameHash()); + ASSERT_EQ(0x0000051cu, ImmutableString("gl_MaxVertexTextureImageUnits").mangledNameHash()); + ASSERT_EQ(0x0000051du, ImmutableString("gl_MaxCombinedTextureImageUnits").mangledNameHash()); + ASSERT_EQ(0x0000051eu, ImmutableString("gl_MaxTextureImageUnits").mangledNameHash()); + ASSERT_EQ(0x0000051fu, ImmutableString("gl_MaxFragmentUniformVectors").mangledNameHash()); + ASSERT_EQ(0x00000520u, ImmutableString("gl_MaxVaryingVectors").mangledNameHash()); + ASSERT_EQ(0x00000521u, ImmutableString("gl_MaxDrawBuffers").mangledNameHash()); + ASSERT_EQ(0x00000522u, ImmutableString("gl_MaxDualSourceDrawBuffersEXT").mangledNameHash()); + ASSERT_EQ(0x00000523u, ImmutableString("gl_MaxVertexOutputVectors").mangledNameHash()); + ASSERT_EQ(0x00000524u, ImmutableString("gl_MaxFragmentInputVectors").mangledNameHash()); + ASSERT_EQ(0x00000525u, ImmutableString("gl_MinProgramTexelOffset").mangledNameHash()); + ASSERT_EQ(0x00000526u, ImmutableString("gl_MaxProgramTexelOffset").mangledNameHash()); + ASSERT_EQ(0x00000527u, ImmutableString("gl_MaxImageUnits").mangledNameHash()); + ASSERT_EQ(0x00000528u, ImmutableString("gl_MaxVertexImageUniforms").mangledNameHash()); + ASSERT_EQ(0x00000529u, ImmutableString("gl_MaxFragmentImageUniforms").mangledNameHash()); + ASSERT_EQ(0x0000052au, ImmutableString("gl_MaxComputeImageUniforms").mangledNameHash()); + ASSERT_EQ(0x0000052bu, ImmutableString("gl_MaxCombinedImageUniforms").mangledNameHash()); + ASSERT_EQ(0x0000052cu, ImmutableString("gl_MaxCombinedShaderOutputResources").mangledNameHash()); - ASSERT_EQ(0x000005c8u, ImmutableString("gl_MaxComputeWorkGroupCount").mangledNameHash()); - ASSERT_EQ(0x000005c9u, ImmutableString("gl_MaxComputeWorkGroupSize").mangledNameHash()); - ASSERT_EQ(0x000005cau, ImmutableString("gl_MaxComputeUniformComponents").mangledNameHash()); - ASSERT_EQ(0x000005cbu, ImmutableString("gl_MaxComputeTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005ccu, ImmutableString("gl_MaxComputeAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005cdu, ImmutableString("gl_MaxComputeAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005ceu, ImmutableString("gl_MaxVertexAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005cfu, ImmutableString("gl_MaxFragmentAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005d0u, ImmutableString("gl_MaxCombinedAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005d1u, ImmutableString("gl_MaxAtomicCounterBindings").mangledNameHash()); - ASSERT_EQ(0x000005d2u, ImmutableString("gl_MaxVertexAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005d3u, ImmutableString("gl_MaxFragmentAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005d4u, ImmutableString("gl_MaxCombinedAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005d5u, ImmutableString("gl_MaxAtomicCounterBufferSize").mangledNameHash()); - ASSERT_EQ(0x000005d6u, ImmutableString("gl_MaxGeometryInputComponents").mangledNameHash()); - ASSERT_EQ(0x000005d7u, ImmutableString("gl_MaxGeometryOutputComponents").mangledNameHash()); - ASSERT_EQ(0x000005d8u, ImmutableString("gl_MaxGeometryImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005d9u, ImmutableString("gl_MaxGeometryTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005dau, ImmutableString("gl_MaxGeometryOutputVertices").mangledNameHash()); - ASSERT_EQ(0x000005dbu, + ASSERT_EQ(0x0000052du, ImmutableString("gl_MaxComputeWorkGroupCount").mangledNameHash()); + ASSERT_EQ(0x0000052eu, ImmutableString("gl_MaxComputeWorkGroupSize").mangledNameHash()); + ASSERT_EQ(0x0000052fu, ImmutableString("gl_MaxComputeUniformComponents").mangledNameHash()); + ASSERT_EQ(0x00000530u, ImmutableString("gl_MaxComputeTextureImageUnits").mangledNameHash()); + ASSERT_EQ(0x00000531u, ImmutableString("gl_MaxComputeAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x00000532u, ImmutableString("gl_MaxComputeAtomicCounterBuffers").mangledNameHash()); + ASSERT_EQ(0x00000533u, ImmutableString("gl_MaxVertexAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x00000534u, ImmutableString("gl_MaxFragmentAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x00000535u, ImmutableString("gl_MaxCombinedAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x00000536u, ImmutableString("gl_MaxAtomicCounterBindings").mangledNameHash()); + ASSERT_EQ(0x00000537u, ImmutableString("gl_MaxVertexAtomicCounterBuffers").mangledNameHash()); + ASSERT_EQ(0x00000538u, ImmutableString("gl_MaxFragmentAtomicCounterBuffers").mangledNameHash()); + ASSERT_EQ(0x00000539u, ImmutableString("gl_MaxCombinedAtomicCounterBuffers").mangledNameHash()); + ASSERT_EQ(0x0000053au, ImmutableString("gl_MaxAtomicCounterBufferSize").mangledNameHash()); + ASSERT_EQ(0x0000053bu, + ImmutableString("gl_ShadingRateFlag2VerticalPixelsEXT").mangledNameHash()); + ASSERT_EQ(0x0000053cu, + ImmutableString("gl_ShadingRateFlag4VerticalPixelsEXT").mangledNameHash()); + ASSERT_EQ(0x0000053du, + ImmutableString("gl_ShadingRateFlag2HorizontalPixelsEXT").mangledNameHash()); + ASSERT_EQ(0x0000053eu, + ImmutableString("gl_ShadingRateFlag4HorizontalPixelsEXT").mangledNameHash()); + ASSERT_EQ(0x0000053fu, ImmutableString("gl_MaxGeometryInputComponents").mangledNameHash()); + ASSERT_EQ(0x00000540u, ImmutableString("gl_MaxGeometryOutputComponents").mangledNameHash()); + ASSERT_EQ(0x00000541u, ImmutableString("gl_MaxGeometryImageUniforms").mangledNameHash()); + ASSERT_EQ(0x00000542u, ImmutableString("gl_MaxGeometryTextureImageUnits").mangledNameHash()); + ASSERT_EQ(0x00000543u, ImmutableString("gl_MaxGeometryOutputVertices").mangledNameHash()); + ASSERT_EQ(0x00000544u, ImmutableString("gl_MaxGeometryTotalOutputComponents").mangledNameHash()); - ASSERT_EQ(0x000005dcu, ImmutableString("gl_MaxGeometryUniformComponents").mangledNameHash()); - ASSERT_EQ(0x000005ddu, ImmutableString("gl_MaxGeometryAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005deu, ImmutableString("gl_MaxGeometryAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005dfu, ImmutableString("gl_MaxTessControlInputComponents").mangledNameHash()); - ASSERT_EQ(0x000005e0u, ImmutableString("gl_MaxTessControlOutputComponents").mangledNameHash()); - ASSERT_EQ(0x000005e1u, ImmutableString("gl_MaxTessControlTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005e2u, ImmutableString("gl_MaxTessControlUniformComponents").mangledNameHash()); - ASSERT_EQ(0x000005e3u, + ASSERT_EQ(0x00000545u, ImmutableString("gl_MaxGeometryUniformComponents").mangledNameHash()); + ASSERT_EQ(0x00000546u, ImmutableString("gl_MaxGeometryAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x00000547u, ImmutableString("gl_MaxGeometryAtomicCounterBuffers").mangledNameHash()); + ASSERT_EQ(0x00000548u, ImmutableString("gl_MaxTessControlInputComponents").mangledNameHash()); + ASSERT_EQ(0x00000549u, ImmutableString("gl_MaxTessControlOutputComponents").mangledNameHash()); + ASSERT_EQ(0x0000054au, ImmutableString("gl_MaxTessControlTextureImageUnits").mangledNameHash()); + ASSERT_EQ(0x0000054bu, ImmutableString("gl_MaxTessControlUniformComponents").mangledNameHash()); + ASSERT_EQ(0x0000054cu, ImmutableString("gl_MaxTessControlTotalOutputComponents").mangledNameHash()); - ASSERT_EQ(0x000005e4u, ImmutableString("gl_MaxTessControlImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005e5u, ImmutableString("gl_MaxTessControlAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005e6u, + ASSERT_EQ(0x0000054du, ImmutableString("gl_MaxTessControlImageUniforms").mangledNameHash()); + ASSERT_EQ(0x0000054eu, ImmutableString("gl_MaxTessControlAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x0000054fu, ImmutableString("gl_MaxTessControlAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005e7u, ImmutableString("gl_MaxTessPatchComponents").mangledNameHash()); - ASSERT_EQ(0x000005e8u, ImmutableString("gl_MaxPatchVertices").mangledNameHash()); - ASSERT_EQ(0x000005e9u, ImmutableString("gl_MaxTessGenLevel").mangledNameHash()); - ASSERT_EQ(0x000005eau, + ASSERT_EQ(0x00000550u, ImmutableString("gl_MaxTessPatchComponents").mangledNameHash()); + ASSERT_EQ(0x00000551u, ImmutableString("gl_MaxPatchVertices").mangledNameHash()); + ASSERT_EQ(0x00000552u, ImmutableString("gl_MaxTessGenLevel").mangledNameHash()); + ASSERT_EQ(0x00000553u, ImmutableString("gl_MaxTessEvaluationInputComponents").mangledNameHash()); - ASSERT_EQ(0x000005ebu, + ASSERT_EQ(0x00000554u, ImmutableString("gl_MaxTessEvaluationOutputComponents").mangledNameHash()); - ASSERT_EQ(0x000005ecu, + ASSERT_EQ(0x00000555u, ImmutableString("gl_MaxTessEvaluationTextureImageUnits").mangledNameHash()); - ASSERT_EQ(0x000005edu, + ASSERT_EQ(0x00000556u, ImmutableString("gl_MaxTessEvaluationUniformComponents").mangledNameHash()); - ASSERT_EQ(0x000005eeu, ImmutableString("gl_MaxTessEvaluationImageUniforms").mangledNameHash()); - ASSERT_EQ(0x000005efu, ImmutableString("gl_MaxTessEvaluationAtomicCounters").mangledNameHash()); - ASSERT_EQ(0x000005f0u, + ASSERT_EQ(0x00000557u, ImmutableString("gl_MaxTessEvaluationImageUniforms").mangledNameHash()); + ASSERT_EQ(0x00000558u, ImmutableString("gl_MaxTessEvaluationAtomicCounters").mangledNameHash()); + ASSERT_EQ(0x00000559u, ImmutableString("gl_MaxTessEvaluationAtomicCounterBuffers").mangledNameHash()); - ASSERT_EQ(0x000005f1u, ImmutableString("gl_MaxSamples").mangledNameHash()); - ASSERT_EQ(0x000005f2u, ImmutableString("gl_MaxClipDistances").mangledNameHash()); - ASSERT_EQ(0x000005f3u, ImmutableString("gl_MaxCullDistances").mangledNameHash()); - ASSERT_EQ(0x000005f4u, ImmutableString("gl_MaxCombinedClipAndCullDistances").mangledNameHash()); - ASSERT_EQ(0x000005f5u, ImmutableString("gl_FragCoord").mangledNameHash()); - ASSERT_EQ(0x000005f6u, ImmutableString("gl_FrontFacing").mangledNameHash()); - ASSERT_EQ(0x000005f7u, ImmutableString("gl_PointCoord").mangledNameHash()); - ASSERT_EQ(0x000005f8u, ImmutableString("gl_FragColor").mangledNameHash()); - ASSERT_EQ(0x000005f9u, ImmutableString("gl_FragData").mangledNameHash()); - ASSERT_EQ(0x000005fau, ImmutableString("gl_FragDepth").mangledNameHash()); - ASSERT_EQ(0x000005fbu, ImmutableString("gl_HelperInvocation").mangledNameHash()); - ASSERT_EQ(0x000005fcu, ImmutableString("gl_SecondaryFragColorEXT").mangledNameHash()); - ASSERT_EQ(0x000005fdu, ImmutableString("gl_SecondaryFragDataEXT").mangledNameHash()); - ASSERT_EQ(0x000005feu, ImmutableString("gl_FragDepthEXT").mangledNameHash()); - ASSERT_EQ(0x000005ffu, ImmutableString("gl_LastFragData").mangledNameHash()); - ASSERT_EQ(0x00000600u, ImmutableString("gl_LastFragColor").mangledNameHash()); - ASSERT_EQ(0x00000601u, ImmutableString("gl_LastFragColorARM").mangledNameHash()); - ASSERT_EQ(0x00000602u, ImmutableString("gl_LastFragDepthARM").mangledNameHash()); - ASSERT_EQ(0x00000603u, ImmutableString("gl_LastFragStencilARM").mangledNameHash()); - ASSERT_EQ(0x00000604u, ImmutableString("gl_PrimitiveID").mangledNameHash()); - ASSERT_EQ(0x00000605u, ImmutableString("gl_Layer").mangledNameHash()); - ASSERT_EQ(0x00000606u, ImmutableString("gl_SampleID").mangledNameHash()); - ASSERT_EQ(0x00000607u, ImmutableString("gl_SamplePosition").mangledNameHash()); - ASSERT_EQ(0x00000608u, ImmutableString("gl_SampleMaskIn").mangledNameHash()); - ASSERT_EQ(0x00000609u, ImmutableString("gl_SampleMask").mangledNameHash()); - ASSERT_EQ(0x0000060au, ImmutableString("gl_Position").mangledNameHash()); - ASSERT_EQ(0x0000060bu, ImmutableString("gl_PointSize").mangledNameHash()); - ASSERT_EQ(0x0000060cu, ImmutableString("gl_InstanceID").mangledNameHash()); - ASSERT_EQ(0x0000060du, ImmutableString("gl_InstanceIndex").mangledNameHash()); - ASSERT_EQ(0x0000060eu, ImmutableString("gl_VertexID").mangledNameHash()); - ASSERT_EQ(0x0000060fu, ImmutableString("gl_VertexIndex").mangledNameHash()); - ASSERT_EQ(0x00000610u, ImmutableString("gl_DrawID").mangledNameHash()); - ASSERT_EQ(0x00000611u, ImmutableString("gl_BaseVertex").mangledNameHash()); - ASSERT_EQ(0x00000612u, ImmutableString("gl_BaseInstance").mangledNameHash()); - ASSERT_EQ(0x00000613u, ImmutableString("angle_BaseVertex").mangledNameHash()); - ASSERT_EQ(0x00000614u, ImmutableString("angle_BaseInstance").mangledNameHash()); - ASSERT_EQ(0x00000615u, ImmutableString("gl_ClipDistance").mangledNameHash()); - ASSERT_EQ(0x00000616u, ImmutableString("gl_NumWorkGroups").mangledNameHash()); - ASSERT_EQ(0x00000617u, ImmutableString("gl_WorkGroupSize").mangledNameHash()); - ASSERT_EQ(0x00000618u, ImmutableString("gl_WorkGroupID").mangledNameHash()); - ASSERT_EQ(0x00000619u, ImmutableString("gl_LocalInvocationID").mangledNameHash()); - ASSERT_EQ(0x0000061au, ImmutableString("gl_GlobalInvocationID").mangledNameHash()); - ASSERT_EQ(0x0000061bu, ImmutableString("gl_LocalInvocationIndex").mangledNameHash()); - ASSERT_EQ(0x0000061cu, ImmutableString("gl_PrimitiveIDIn").mangledNameHash()); - ASSERT_EQ(0x0000061du, ImmutableString("gl_InvocationID").mangledNameHash()); - ASSERT_EQ(0x0000061eu, ImmutableString("gl_PerVertex").mangledNameHash()); - ASSERT_EQ(0x0000061fu, ImmutableString("gl_in").mangledNameHash()); - ASSERT_EQ(0x00000620u, ImmutableString("gl_PatchVerticesIn").mangledNameHash()); - ASSERT_EQ(0x00000621u, ImmutableString("gl_TessLevelOuter").mangledNameHash()); - ASSERT_EQ(0x00000622u, ImmutableString("gl_TessLevelInner").mangledNameHash()); - ASSERT_EQ(0x00000623u, ImmutableString("gl_out").mangledNameHash()); - ASSERT_EQ(0x00000624u, ImmutableString("gl_BoundingBox").mangledNameHash()); - ASSERT_EQ(0x00000625u, ImmutableString("gl_BoundingBoxEXT").mangledNameHash()); - ASSERT_EQ(0x00000626u, ImmutableString("gl_BoundingBoxOES").mangledNameHash()); - ASSERT_EQ(0x00000627u, ImmutableString("gl_TessCoord").mangledNameHash()); - ASSERT_EQ(0x00000628u, ImmutableString("gl_ViewID_OVR").mangledNameHash()); - ASSERT_EQ(0x00000629u, ImmutableString("gl_CullDistance").mangledNameHash()); + ASSERT_EQ(0x0000055au, ImmutableString("gl_MaxSamples").mangledNameHash()); + ASSERT_EQ(0x0000055bu, ImmutableString("gl_MaxClipDistances").mangledNameHash()); + ASSERT_EQ(0x0000055cu, ImmutableString("gl_MaxCullDistances").mangledNameHash()); + ASSERT_EQ(0x0000055du, ImmutableString("gl_MaxCombinedClipAndCullDistances").mangledNameHash()); + ASSERT_EQ(0x0000055eu, ImmutableString("gl_FragCoord").mangledNameHash()); + ASSERT_EQ(0x0000055fu, ImmutableString("gl_FrontFacing").mangledNameHash()); + ASSERT_EQ(0x00000560u, ImmutableString("gl_PointCoord").mangledNameHash()); + ASSERT_EQ(0x00000561u, ImmutableString("gl_FragColor").mangledNameHash()); + ASSERT_EQ(0x00000562u, ImmutableString("gl_FragData").mangledNameHash()); + ASSERT_EQ(0x00000563u, ImmutableString("gl_FragDepth").mangledNameHash()); + ASSERT_EQ(0x00000564u, ImmutableString("gl_HelperInvocation").mangledNameHash()); + ASSERT_EQ(0x00000565u, ImmutableString("gl_SecondaryFragColorEXT").mangledNameHash()); + ASSERT_EQ(0x00000566u, ImmutableString("gl_SecondaryFragDataEXT").mangledNameHash()); + ASSERT_EQ(0x00000567u, ImmutableString("gl_FragDepthEXT").mangledNameHash()); + ASSERT_EQ(0x00000568u, ImmutableString("gl_LastFragData").mangledNameHash()); + ASSERT_EQ(0x00000569u, ImmutableString("gl_LastFragColorARM").mangledNameHash()); + ASSERT_EQ(0x0000056au, ImmutableString("gl_LastFragDepthARM").mangledNameHash()); + ASSERT_EQ(0x0000056bu, ImmutableString("gl_LastFragStencilARM").mangledNameHash()); + ASSERT_EQ(0x0000056cu, ImmutableString("gl_PrimitiveID").mangledNameHash()); + ASSERT_EQ(0x0000056du, ImmutableString("gl_Layer").mangledNameHash()); + ASSERT_EQ(0x0000056eu, ImmutableString("gl_ShadingRateEXT").mangledNameHash()); + ASSERT_EQ(0x0000056fu, ImmutableString("gl_SampleID").mangledNameHash()); + ASSERT_EQ(0x00000570u, ImmutableString("gl_SamplePosition").mangledNameHash()); + ASSERT_EQ(0x00000571u, ImmutableString("gl_SampleMaskIn").mangledNameHash()); + ASSERT_EQ(0x00000572u, ImmutableString("gl_SampleMask").mangledNameHash()); + ASSERT_EQ(0x00000573u, ImmutableString("gl_Position").mangledNameHash()); + ASSERT_EQ(0x00000574u, ImmutableString("gl_PointSize").mangledNameHash()); + ASSERT_EQ(0x00000575u, ImmutableString("gl_InstanceID").mangledNameHash()); + ASSERT_EQ(0x00000576u, ImmutableString("gl_InstanceIndex").mangledNameHash()); + ASSERT_EQ(0x00000577u, ImmutableString("gl_VertexID").mangledNameHash()); + ASSERT_EQ(0x00000578u, ImmutableString("gl_VertexIndex").mangledNameHash()); + ASSERT_EQ(0x00000579u, ImmutableString("gl_DrawID").mangledNameHash()); + ASSERT_EQ(0x0000057au, ImmutableString("gl_BaseVertex").mangledNameHash()); + ASSERT_EQ(0x0000057bu, ImmutableString("gl_BaseInstance").mangledNameHash()); + ASSERT_EQ(0x0000057cu, ImmutableString("gl_ClipDistance").mangledNameHash()); + ASSERT_EQ(0x0000057du, ImmutableString("gl_PrimitiveShadingRateEXT").mangledNameHash()); + ASSERT_EQ(0x0000057eu, ImmutableString("gl_NumWorkGroups").mangledNameHash()); + ASSERT_EQ(0x0000057fu, ImmutableString("gl_WorkGroupSize").mangledNameHash()); + ASSERT_EQ(0x00000580u, ImmutableString("gl_WorkGroupID").mangledNameHash()); + ASSERT_EQ(0x00000581u, ImmutableString("gl_LocalInvocationID").mangledNameHash()); + ASSERT_EQ(0x00000582u, ImmutableString("gl_GlobalInvocationID").mangledNameHash()); + ASSERT_EQ(0x00000583u, ImmutableString("gl_LocalInvocationIndex").mangledNameHash()); + ASSERT_EQ(0x00000584u, ImmutableString("gl_PrimitiveIDIn").mangledNameHash()); + ASSERT_EQ(0x00000585u, ImmutableString("gl_InvocationID").mangledNameHash()); + ASSERT_EQ(0x00000586u, ImmutableString("gl_PerVertex").mangledNameHash()); + ASSERT_EQ(0x00000587u, ImmutableString("gl_in").mangledNameHash()); + ASSERT_EQ(0x00000588u, ImmutableString("gl_PatchVerticesIn").mangledNameHash()); + ASSERT_EQ(0x00000589u, ImmutableString("gl_TessLevelOuter").mangledNameHash()); + ASSERT_EQ(0x0000058au, ImmutableString("gl_TessLevelInner").mangledNameHash()); + ASSERT_EQ(0x0000058bu, ImmutableString("gl_out").mangledNameHash()); + ASSERT_EQ(0x0000058cu, ImmutableString("gl_BoundingBox").mangledNameHash()); + ASSERT_EQ(0x0000058du, ImmutableString("gl_BoundingBoxEXT").mangledNameHash()); + ASSERT_EQ(0x0000058eu, ImmutableString("gl_BoundingBoxOES").mangledNameHash()); + ASSERT_EQ(0x0000058fu, ImmutableString("gl_TessCoord").mangledNameHash()); + ASSERT_EQ(0x00000590u, ImmutableString("gl_ViewID_OVR").mangledNameHash()); + ASSERT_EQ(0x00000591u, ImmutableString("gl_CullDistance").mangledNameHash()); ASSERT_EQ(0x00000000u, ImmutableString("radians").unmangledNameHash()); ASSERT_EQ(0x00000001u, ImmutableString("degrees").unmangledNameHash()); ASSERT_EQ(0x00000002u, ImmutableString("sin").unmangledNameHash()); @@ -1811,7 +1651,8 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ASSERT_EQ(0x000000afu, ImmutableString("numSamples").unmangledNameHash()); ASSERT_EQ(0x000000b0u, ImmutableString("samplePosition").unmangledNameHash()); ASSERT_EQ(0x000000b1u, ImmutableString("interpolateAtCenter").unmangledNameHash()); - ASSERT_EQ(0x000000b2u, ImmutableString("saturate").unmangledNameHash()); + ASSERT_EQ(0x000000b2u, ImmutableString("loopForwardProgress").unmangledNameHash()); + ASSERT_EQ(0x000000b3u, ImmutableString("saturate").unmangledNameHash()); } } // namespace sh diff --git a/src/tests/compiler_tests/InitOutputVariables_test.cpp b/src/tests/compiler_tests/InitOutputVariables_test.cpp deleted file mode 100644 index 4159985cc51..00000000000 --- a/src/tests/compiler_tests/InitOutputVariables_test.cpp +++ /dev/null @@ -1,484 +0,0 @@ -// -// Copyright 2017 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. -// -// InitOutputVariables_test.cpp: Tests correctness of the AST pass enabled through -// SH_INIT_OUTPUT_VARIABLES. -// - -#include "common/angleutils.h" - -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/tree_util/FindMain.h" -#include "compiler/translator/tree_util/IntermNode_util.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -#include - -namespace sh -{ - -namespace -{ - -typedef std::vector ExpectedLValues; - -bool AreSymbolsTheSame(const TIntermSymbol *expected, const TIntermSymbol *candidate) -{ - if (expected == nullptr || candidate == nullptr) - { - return false; - } - const TType &expectedType = expected->getType(); - const TType &candidateType = candidate->getType(); - const bool sameTypes = expectedType == candidateType && - expectedType.getPrecision() == candidateType.getPrecision() && - expectedType.getQualifier() == candidateType.getQualifier(); - const bool sameSymbols = (expected->variable().symbolType() == SymbolType::Empty && - candidate->variable().symbolType() == SymbolType::Empty) || - expected->getName() == candidate->getName(); - return sameSymbols && sameTypes; -} - -bool AreLValuesTheSame(TIntermTyped *expected, TIntermTyped *candidate) -{ - const TIntermBinary *expectedBinary = expected->getAsBinaryNode(); - if (expectedBinary) - { - ASSERT(expectedBinary->getOp() == EOpIndexDirect); - const TIntermBinary *candidateBinary = candidate->getAsBinaryNode(); - if (candidateBinary == nullptr || candidateBinary->getOp() != EOpIndexDirect) - { - return false; - } - if (expectedBinary->getRight()->getAsConstantUnion()->getIConst(0) != - candidateBinary->getRight()->getAsConstantUnion()->getIConst(0)) - { - return false; - } - return AreSymbolsTheSame(expectedBinary->getLeft()->getAsSymbolNode(), - candidateBinary->getLeft()->getAsSymbolNode()); - } - return AreSymbolsTheSame(expected->getAsSymbolNode(), candidate->getAsSymbolNode()); -} - -TIntermTyped *CreateLValueNode(const ImmutableString &lValueName, const TType &type) -{ - // We're using a mock symbol table here, don't need to assign proper symbol ids to these nodes. - TSymbolTable symbolTable; - TVariable *variable = - new TVariable(&symbolTable, lValueName, new TType(type), SymbolType::UserDefined); - return new TIntermSymbol(variable); -} - -ExpectedLValues CreateIndexedLValueNodeList(const ImmutableString &lValueName, - const TType &elementType, - unsigned arraySize) -{ - ASSERT(elementType.isArray() == false); - TType *arrayType = new TType(elementType); - arrayType->makeArray(arraySize); - - // We're using a mock symbol table here, don't need to assign proper symbol ids to these nodes. - TSymbolTable symbolTable; - TVariable *variable = - new TVariable(&symbolTable, lValueName, arrayType, SymbolType::UserDefined); - TIntermSymbol *arraySymbol = new TIntermSymbol(variable); - - ExpectedLValues expected(arraySize); - for (unsigned index = 0u; index < arraySize; ++index) - { - expected[index] = new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), - CreateIndexNode(static_cast(index))); - } - return expected; -} - -// VerifyOutputVariableInitializers traverses the subtree covering main and collects the lvalues in -// assignments for which the rvalue is an expression containing only zero constants. -class VerifyOutputVariableInitializers final : public TIntermTraverser -{ - public: - VerifyOutputVariableInitializers(TIntermBlock *root) : TIntermTraverser(true, false, false) - { - ASSERT(root != nullptr); - - // The traversal starts in the body of main because this is where the varyings and output - // variables are initialized. - sh::TIntermFunctionDefinition *main = FindMain(root); - ASSERT(main != nullptr); - main->traverse(this); - } - - bool visitBinary(Visit visit, TIntermBinary *node) override - { - if (node->getOp() == EOpAssign && IsZero(node->getRight())) - { - mCandidateLValues.push_back(node->getLeft()); - return false; - } - return true; - } - - // The collected lvalues are considered valid if every expected lvalue in expectedLValues is - // matched by name and type with any lvalue in mCandidateLValues. - bool areAllExpectedLValuesFound(const ExpectedLValues &expectedLValues) const - { - for (size_t i = 0u; i < expectedLValues.size(); ++i) - { - if (!isExpectedLValueFound(expectedLValues[i])) - { - return false; - } - } - return true; - } - - bool isExpectedLValueFound(TIntermTyped *expectedLValue) const - { - bool isFound = false; - for (size_t j = 0; j < mCandidateLValues.size() && !isFound; ++j) - { - isFound = AreLValuesTheSame(expectedLValue, mCandidateLValues[j]); - } - return isFound; - } - - const ExpectedLValues &getCandidates() const { return mCandidateLValues; } - - private: - ExpectedLValues mCandidateLValues; -}; - -// Traverses the AST and records a pointer to a structure with a given name. -class FindStructByName final : public TIntermTraverser -{ - public: - FindStructByName(const ImmutableString &structName) - : TIntermTraverser(true, false, false), mStructName(structName), mStructure(nullptr) - {} - - void visitSymbol(TIntermSymbol *symbol) override - { - if (isStructureFound()) - { - return; - } - - const TStructure *structure = symbol->getType().getStruct(); - - if (structure != nullptr && structure->symbolType() != SymbolType::Empty && - structure->name() == mStructName) - { - mStructure = structure; - } - } - - bool isStructureFound() const { return mStructure != nullptr; } - const TStructure *getStructure() const { return mStructure; } - - private: - ImmutableString mStructName; - const TStructure *mStructure; -}; - -} // namespace - -class InitOutputVariablesWebGL2Test : public ShaderCompileTreeTest -{ - public: - void SetUp() override - { - mCompileOptions.initOutputVariables = true; - if (getShaderType() == GL_VERTEX_SHADER) - { - mCompileOptions.initGLPosition = true; - } - ShaderCompileTreeTest::SetUp(); - } - - protected: - ShShaderSpec getShaderSpec() const override { return SH_WEBGL2_SPEC; } -}; - -class InitOutputVariablesWebGL2VertexShaderTest : public InitOutputVariablesWebGL2Test -{ - protected: - ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; } -}; - -class InitOutputVariablesWebGL2FragmentShaderTest : public InitOutputVariablesWebGL2Test -{ - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - void initResources(ShBuiltInResources *resources) override - { - resources->EXT_draw_buffers = 1; - resources->MaxDrawBuffers = 2; - } -}; - -class InitOutputVariablesWebGL1FragmentShaderTest : public ShaderCompileTreeTest -{ - public: - InitOutputVariablesWebGL1FragmentShaderTest() { mCompileOptions.initOutputVariables = true; } - - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_WEBGL_SPEC; } - void initResources(ShBuiltInResources *resources) override - { - resources->EXT_draw_buffers = 1; - resources->MaxDrawBuffers = 2; - } -}; - -class InitOutputVariablesVertexShaderClipDistanceTest : public ShaderCompileTreeTest -{ - public: - InitOutputVariablesVertexShaderClipDistanceTest() - { - mCompileOptions.initOutputVariables = true; - mCompileOptions.validateAST = true; - } - - protected: - ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES2_SPEC; } - void initResources(ShBuiltInResources *resources) override - { - resources->APPLE_clip_distance = 1; - resources->MaxClipDistances = 8; - } -}; - -// Test the initialization of output variables with various qualifiers in a vertex shader. -TEST_F(InitOutputVariablesWebGL2VertexShaderTest, OutputAllQualifiers) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision lowp int;\n" - "out vec4 out1;\n" - "flat out int out2;\n" - "centroid out float out3;\n" - "smooth out float out4;\n" - "void main() {\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - ExpectedLValues expectedLValues = { - CreateLValueNode(ImmutableString("out1"), TType(EbtFloat, EbpMedium, EvqVertexOut, 4)), - CreateLValueNode(ImmutableString("out2"), TType(EbtInt, EbpLow, EvqFlatOut)), - CreateLValueNode(ImmutableString("out3"), TType(EbtFloat, EbpMedium, EvqCentroidOut)), - CreateLValueNode(ImmutableString("out4"), TType(EbtFloat, EbpMedium, EvqSmoothOut))}; - EXPECT_TRUE(verifier.areAllExpectedLValuesFound(expectedLValues)); -} - -// Test the initialization of an output array in a vertex shader. -TEST_F(InitOutputVariablesWebGL2VertexShaderTest, OutputArray) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out float out1[2];\n" - "void main() {\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - ExpectedLValues expectedLValues = CreateIndexedLValueNodeList( - ImmutableString("out1"), TType(EbtFloat, EbpMedium, EvqVertexOut), 2); - EXPECT_TRUE(verifier.areAllExpectedLValuesFound(expectedLValues)); -} - -// Test the initialization of a struct output variable in a vertex shader. -TEST_F(InitOutputVariablesWebGL2VertexShaderTest, OutputStruct) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "struct MyS{\n" - " float a;\n" - " float b;\n" - "};\n" - "out MyS out1;\n" - "void main() {\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - FindStructByName findStruct(ImmutableString("MyS")); - mASTRoot->traverse(&findStruct); - ASSERT(findStruct.isStructureFound()); - - TType type(findStruct.getStructure(), false); - type.setQualifier(EvqVertexOut); - - TIntermTyped *expectedLValue = CreateLValueNode(ImmutableString("out1"), type); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValue)); - delete expectedLValue; -} - -// Test the initialization of a varying variable in an ESSL1 vertex shader. -TEST_F(InitOutputVariablesWebGL2VertexShaderTest, OutputFromESSL1Shader) -{ - const std::string &shaderString = - "precision mediump float;\n" - "varying vec4 out1;\n" - "void main() {\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - TIntermTyped *expectedLValue = - CreateLValueNode(ImmutableString("out1"), TType(EbtFloat, EbpMedium, EvqVaryingOut, 4)); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValue)); - delete expectedLValue; -} - -// Test the initialization of output variables in a fragment shader. -TEST_F(InitOutputVariablesWebGL2FragmentShaderTest, Output) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 out1;\n" - "void main() {\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - TIntermTyped *expectedLValue = - CreateLValueNode(ImmutableString("out1"), TType(EbtFloat, EbpMedium, EvqFragmentOut, 4)); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValue)); - delete expectedLValue; -} - -// Test the initialization of gl_FragData in a WebGL2 ESSL1 fragment shader. Only writes to -// gl_FragData[0] should be found. -TEST_F(InitOutputVariablesWebGL2FragmentShaderTest, FragData) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main() {\n" - " gl_FragData[0] = vec4(1.);\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - ExpectedLValues expectedLValues = CreateIndexedLValueNodeList( - ImmutableString("gl_FragData"), TType(EbtFloat, EbpMedium, EvqFragData, 4), 1); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValues[0])); - EXPECT_EQ(1u, verifier.getCandidates().size()); -} - -// Test the initialization of gl_FragData in a WebGL1 ESSL1 fragment shader. Only writes to -// gl_FragData[0] should be found. -TEST_F(InitOutputVariablesWebGL1FragmentShaderTest, FragData) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main() {\n" - " gl_FragData[0] = vec4(1.);\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - // In the symbol table, gl_FragData array has 2 elements. However, only the 1st one should be - // initialized. - ExpectedLValues expectedLValues = CreateIndexedLValueNodeList( - ImmutableString("gl_FragData"), TType(EbtFloat, EbpMedium, EvqFragData, 4), 2); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValues[0])); - EXPECT_EQ(1u, verifier.getCandidates().size()); -} - -// Test the initialization of gl_FragData in a WebGL1 ESSL1 fragment shader with GL_EXT_draw_buffers -// enabled. All attachment slots should be initialized. -TEST_F(InitOutputVariablesWebGL1FragmentShaderTest, FragDataWithDrawBuffersExtEnabled) -{ - const std::string &shaderString = - "#extension GL_EXT_draw_buffers : enable\n" - "precision mediump float;\n" - "void main() {\n" - " gl_FragData[0] = vec4(1.);\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - ExpectedLValues expectedLValues = CreateIndexedLValueNodeList( - ImmutableString("gl_FragData"), TType(EbtFloat, EbpMedium, EvqFragData, 4), 2); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValues[0])); - EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValues[1])); - EXPECT_EQ(2u, verifier.getCandidates().size()); -} - -// Test that gl_Position is initialized once in case it is not statically used and both -// SH_INIT_OUTPUT_VARIABLES and SH_INIT_GL_POSITION flags are set. -TEST_F(InitOutputVariablesWebGL2VertexShaderTest, InitGLPositionWhenNotStaticallyUsed) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision highp float;\n" - "void main() {\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - TIntermTyped *glPosition = - CreateLValueNode(ImmutableString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)); - EXPECT_TRUE(verifier.isExpectedLValueFound(glPosition)); - EXPECT_EQ(1u, verifier.getCandidates().size()); -} - -// Test that gl_Position is initialized once in case it is statically used and both -// SH_INIT_OUTPUT_VARIABLES and SH_INIT_GL_POSITION flags are set. -TEST_F(InitOutputVariablesWebGL2VertexShaderTest, InitGLPositionOnceWhenStaticallyUsed) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision highp float;\n" - "void main() {\n" - " gl_Position = vec4(1.0);\n" - "}\n"; - compileAssumeSuccess(shaderString); - VerifyOutputVariableInitializers verifier(mASTRoot); - - TIntermTyped *glPosition = - CreateLValueNode(ImmutableString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)); - EXPECT_TRUE(verifier.isExpectedLValueFound(glPosition)); - EXPECT_EQ(1u, verifier.getCandidates().size()); -} - -// Mirrors ClipDistanceTest.ThreeClipDistancesRedeclared -TEST_F(InitOutputVariablesVertexShaderClipDistanceTest, RedeclareClipDistance) -{ - constexpr char shaderString[] = R"( -#extension GL_APPLE_clip_distance : require - -varying highp float gl_ClipDistance[3]; - -void computeClipDistances(in vec4 position, in vec4 plane[3]) -{ - gl_ClipDistance[0] = dot(position, plane[0]); - gl_ClipDistance[1] = dot(position, plane[1]); - gl_ClipDistance[2] = dot(position, plane[2]); -} - -uniform vec4 u_plane[3]; - -attribute vec2 a_position; - -void main() -{ - gl_Position = vec4(a_position, 0.0, 1.0); - - computeClipDistances(gl_Position, u_plane); -})"; - - compileAssumeSuccess(shaderString); -} -} // namespace sh diff --git a/src/tests/compiler_tests/InitializeUninitializedLocals_test.cpp b/src/tests/compiler_tests/InitializeUninitializedLocals_test.cpp deleted file mode 100644 index 90e8b74a239..00000000000 --- a/src/tests/compiler_tests/InitializeUninitializedLocals_test.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// Copyright 2017 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. -// -// InitializeUninitializedVariables_test.cpp: Tests InitializeUninitializedVariables pass. -// - -#include "common/angleutils.h" - -#include "tests/test_utils/compiler_test.h" - -namespace sh -{ - -namespace -{ - -class InitializeUninitializedVariables : public MatchOutputCodeTest -{ - public: - InitializeUninitializedVariables() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_ESSL_OUTPUT) - { - ShCompileOptions options{}; - options.intermediateTree = true; - options.initializeUninitializedLocals = true; - options.validateAST = true; - setDefaultCompileOptions(options); - } -}; - -// Tests that when unnamed variables must be initialized, the variables get internal names. -TEST_F(InitializeUninitializedVariables, VariableNamesInPrototypesUnnamedOut) -{ - const char kShader[] = R"(#version 300 es -precision highp float; -out vec4 o; -void f(out float, out float); -void main() -{ - o = vec4(0.5); - f(o.r, o.g); -} -void f(out float r, out float) -{ - r = 1.0; -} -)"; - const char kExpected[] = R"(#version 300 es -out highp vec4 _uo; -void _uf(out highp float _ur, out highp float sbc2); -void main(){ - (_uo = vec4(0.5, 0.5, 0.5, 0.5)); - _uf(_uo.x, _uo.y); -} -void _uf(out highp float _ur, out highp float sbc2){ - (_ur = 0.0); - (sbc2 = 0.0); - (_ur = 1.0); -} -)"; - compile(kShader); - EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT)); -} - -// Tests that when unnamed variables must be initialized, the variables get internal names. -TEST_F(InitializeUninitializedVariables, VariableNamesInPrototypesUnnamedOut2) -{ - const char kShader[] = R"(#version 300 es -precision highp float; -out vec4 o; -void f(out float, out float); -void g(out float a, out float b) -{ - f(a, b); -} -void main() -{ - o = vec4(0.5); - g(o.r, o.g); -} -void f(out float r, out float) -{ - r = 1.0; -} -)"; - const char kExpected[] = R"(#version 300 es -out highp vec4 _uo; -void _uf(out highp float _ur, out highp float sbc5); -void _ug(out highp float _ua, out highp float _ub){ - (_ua = 0.0); - (_ub = 0.0); - _uf(_ua, _ub); -} -void main(){ - (_uo = vec4(0.5, 0.5, 0.5, 0.5)); - _ug(_uo.x, _uo.y); -} -void _uf(out highp float _ur, out highp float sbc5){ - (_ur = 0.0); - (sbc5 = 0.0); - (_ur = 1.0); -} -)"; - compile(kShader); - EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT)); -} - -// Tests that when unnamed variables must be initialized, the variables get internal names. -// Tests the case where local z is initialized with a function f, when f must be rewritten. -TEST_F(InitializeUninitializedVariables, VariableNamesInPrototypesUnnamedOut3) -{ - const char kShader[] = R"(#version 300 es -precision highp float; -out vec4 o; -float f(out float r, out float) -{ - r = 1.0; - return 3.0; -} -void main() -{ - o = vec4(0.5); - float z = f(o.r, o.g); -} -)"; - const char kExpected[] = R"(#version 300 es -out highp vec4 _uo; -highp float _uf(out highp float _ur, out highp float sbc0){ - (_ur = 0.0); - (sbc0 = 0.0); - (_ur = 1.0); - return 3.0; -} -void main(){ - (_uo = vec4(0.5, 0.5, 0.5, 0.5)); - highp float _uz = _uf(_uo.x, _uo.y); -} -)"; - compile(kShader); - EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT)); -} - -} // namespace - -} // namespace sh diff --git a/src/tests/compiler_tests/IntermNode_test.cpp b/src/tests/compiler_tests/IntermNode_test.cpp index 6b20cbca016..d2b10bf594e 100644 --- a/src/tests/compiler_tests/IntermNode_test.cpp +++ b/src/tests/compiler_tests/IntermNode_test.cpp @@ -25,14 +25,13 @@ class IntermNodeTest : public testing::Test protected: void SetUp() override { - allocator.push(); SetGlobalPoolAllocator(&allocator); } void TearDown() override { SetGlobalPoolAllocator(nullptr); - allocator.pop(); + allocator.reset(); } TIntermSymbol *createTestSymbol(const TType &type) diff --git a/src/tests/compiler_tests/KHR_blend_equation_advanced_test.cpp b/src/tests/compiler_tests/KHR_blend_equation_advanced_test.cpp deleted file mode 100644 index a921bb6baba..00000000000 --- a/src/tests/compiler_tests/KHR_blend_equation_advanced_test.cpp +++ /dev/null @@ -1,366 +0,0 @@ -// -// Copyright 2021 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. -// -// KHR_blend_equation_advanced_test.cpp: -// Test for KHR_blend_equation_advanced and KHR_blend_equation_advanced_coherent -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -#include "common/PackedEnums.h" - -namespace -{ -const char EXTPragma[] = - "#extension GL_KHR_blend_equation_advanced : require\n" - "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"; - -// Use the multiply equation for blending -const char ESSL310_Simple[] = - R"( - precision highp float; - - layout (blend_support_multiply) out; - layout (location = 0) out vec4 oCol; - - uniform vec4 uSrcCol; - - void main (void) - { - oCol = uSrcCol; - })"; - -const char ESSL310_DeclaredMultiplyScreenSeparately[] = - R"( - precision highp float; - - layout (blend_support_multiply) out; - layout (blend_support_screen) out; - layout (location = 0) out vec4 oCol; - - uniform vec4 uSrcCol; - - void main (void) - { - oCol = uSrcCol; - })"; - -const char ESSL310_DeclaredMultiplyScreenSuccessively[] = - R"( - precision highp float; - - layout (blend_support_multiply, blend_support_screen) out; - layout (location = 0) out vec4 oCol; - - uniform vec4 uSrcCol; - - void main (void) - { - oCol = uSrcCol; - })"; - -const char ESSL310_With_FramebufferFetch[] = - R"( - precision highp float; - - layout (blend_support_multiply) out; - layout (location = 0, noncoherent) inout vec4 oCol; - - uniform vec4 uSrcCol; - - void main (void) - { - oCol = mix(oCol, uSrcCol, 0.5f); - })"; - -const char ESSL310_With_FramebufferFetchVec3[] = - R"( - precision highp float; - - layout (blend_support_multiply) out; - layout (location = 0, noncoherent) inout vec3 oCol; - - uniform vec3 uSrcCol; - - void main (void) - { - oCol = mix(oCol, uSrcCol, 0.5f); - })"; - -class KHRBlendEquationAdvancedTest : public sh::ShaderExtensionTest -{ - public: - void SetUp() override - { - std::map shaderOutputList = { - {SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"}, -#if defined(ANGLE_ENABLE_VULKAN) - {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"} -#endif - }; - - Initialize(shaderOutputList); - } - - void TearDown() override - { - for (auto shaderOutputType : mShaderOutputList) - { - DestroyCompiler(shaderOutputType.first); - } - } - - void Initialize(std::map &shaderOutputList) - { - mShaderOutputList = std::move(shaderOutputList); - - for (auto shaderOutputType : mShaderOutputList) - { - sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]); - mCompilerList[shaderOutputType.first] = nullptr; - } - } - - void DestroyCompiler(ShShaderOutput shaderOutputType) - { - if (mCompilerList[shaderOutputType]) - { - sh::Destruct(mCompilerList[shaderOutputType]); - mCompilerList[shaderOutputType] = nullptr; - } - } - - void InitializeCompiler() - { - for (auto shaderOutputType : mShaderOutputList) - { - InitializeCompiler(shaderOutputType.first); - } - } - - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - DestroyCompiler(shaderOutputType); - - mCompilerList[shaderOutputType] = - sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType, - &mResourceList[shaderOutputType]); - ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr) - << "Compiler for " << mShaderOutputList[shaderOutputType] - << " could not be constructed."; - } - - enum class Emulation - { - Disabled, - Enabled - }; - - testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType, - const char *pragma, - Emulation emulate) - { - const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma, - testing::get<2>(GetParam())}; - - ShCompileOptions compileFlags = {}; - compileFlags.objectCode = true; - if (emulate == Emulation::Enabled) - { - compileFlags.addAdvancedBlendEquationsEmulation = true; - } - - bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3, compileFlags); - if (success) - { - return ::testing::AssertionSuccess() - << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]); - } - - void TestShaderCompile(bool expectation, const char *pragma, Emulation emulate) - { - for (auto shaderOutputType : mShaderOutputList) - { - if (expectation) - { - EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma, emulate)); - } - else - { - EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma, emulate)); - } - } - } - - void SetExtensionEnable(bool enable) - { - for (auto shaderOutputType : mShaderOutputList) - { - mResourceList[shaderOutputType.first].KHR_blend_equation_advanced = enable; - mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent = - enable; - } - } - - protected: - std::map mShaderOutputList; - std::map mCompilerList; - std::map mResourceList; -}; - -class KHRBlendEquationAdvancedES310Test : public KHRBlendEquationAdvancedTest -{}; - -// Extension flag is required to compile properly. Expect failure when it is not present. -TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithoutExtension) -{ - SetExtensionEnable(false); - InitializeCompiler(); - TestShaderCompile(false, EXTPragma, Emulation::Disabled); -} - -// Extension directive is required to compile properly. Expect failure when it is not present. -TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithExtensionWithoutPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(false, "", Emulation::Disabled); -} - -INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders, - KHRBlendEquationAdvancedES310Test, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion310), - Values(ESSL310_Simple, - ESSL310_With_FramebufferFetch, - ESSL310_With_FramebufferFetchVec3, - ESSL310_DeclaredMultiplyScreenSeparately, - ESSL310_DeclaredMultiplyScreenSuccessively))); - -#if defined(ANGLE_ENABLE_VULKAN) - -class KHRBlendEquationAdvancedSuccessTest : public KHRBlendEquationAdvancedTest -{ - public: - void SetUp() override - { - std::map shaderOutputList = { - {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}}; - - Initialize(shaderOutputList); - } -}; - -class KHRBlendEquationAdvancedES310SuccessTest : public KHRBlendEquationAdvancedSuccessTest -{}; - -// With extension flag and extension directive, compiling succeeds. Also test that the extension -// directive state is reset correctly. -TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragma) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma, Emulation::Disabled); - // Test reset functionality. - TestShaderCompile(false, "", Emulation::Disabled); - TestShaderCompile(true, EXTPragma, Emulation::Disabled); -} - -// Same as CompileSucceedsWithExtensionAndPragma but with emulation. -TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragmaWithEmulation) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma, Emulation::Enabled); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders, - KHRBlendEquationAdvancedES310SuccessTest, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion310), - Values(ESSL310_Simple, - ESSL310_With_FramebufferFetch, - ESSL310_With_FramebufferFetchVec3, - ESSL310_DeclaredMultiplyScreenSeparately, - ESSL310_DeclaredMultiplyScreenSuccessively))); - -class KHRBlendEquationAdvancedEnabledListCheckTest : public KHRBlendEquationAdvancedTest -{ - public: - void SetUp() override - { - std::map shaderOutputList = { - {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}}; - - Initialize(shaderOutputList); - } - - const ShHandle &GetCompilerHandle(const ShShaderOutput outputType) const - { - return mCompilerList.at(outputType); - } -}; - -class KHRBlendEquationAdvancedEnabledSeparatelyTest - : public KHRBlendEquationAdvancedEnabledListCheckTest -{}; - -// Test for declaring different blend equations in separate layout declarations -TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparately) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma, Emulation::Disabled); - - const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT); - gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle)); - EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply)); - EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen)); -} - -// Same as DeclaredEquationSeparately but with emulation. -TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparatelyWithEmulation) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma, Emulation::Enabled); -} - -INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders, - KHRBlendEquationAdvancedEnabledSeparatelyTest, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion310), - Values(ESSL310_DeclaredMultiplyScreenSeparately))); - -class KHRBlendEquationAdvancedEnabledSuccessivelyTest - : public KHRBlendEquationAdvancedEnabledListCheckTest -{}; - -// Test for declaring different blend equations in the same layout declaration -TEST_P(KHRBlendEquationAdvancedEnabledSuccessivelyTest, DeclaredEquationSuccessively) -{ - SetExtensionEnable(true); - InitializeCompiler(); - TestShaderCompile(true, EXTPragma, Emulation::Disabled); - - const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT); - gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle)); - EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply)); - EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen)); -} - -INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders, - KHRBlendEquationAdvancedEnabledSuccessivelyTest, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion310), - Values(ESSL310_DeclaredMultiplyScreenSuccessively))); - -#endif - -} // anonymous namespace diff --git a/src/tests/compiler_tests/MSLOutput_test.cpp b/src/tests/compiler_tests/MSLOutput_test.cpp index ed7c87fd9aa..b525c5b983d 100644 --- a/src/tests/compiler_tests/MSLOutput_test.cpp +++ b/src/tests/compiler_tests/MSLOutput_test.cpp @@ -30,6 +30,7 @@ class MSLOutputTestBase : public MatchOutputCodeTest options.simplifyLoopConditions = true; options.initializeUninitializedLocals = true; options.separateCompoundStructDeclarations = true; + options.removeInactiveVariables = true; // The tests also test that validation succeeds. This should be also the // default forced option, but currently MSL backend does not generate // valid trees. Once validateAST is forced, move to above hunk. @@ -1046,9 +1047,71 @@ TEST_F(MSLOutputTest, UnnamedOutParameterNoCrash) TEST_F(MSLOutputTest, ExplicitBoolCastsNoCrash) { ShCompileOptions options = defaultOptions(); - options.addExplicitBoolCasts = 1; const char kShader[] = R"( precision mediump float; void main(){vec2 c;bvec2 U=bvec2(c.xx);if (U.x) gl_FragColor = vec4(1);})"; compile(kShader, options); } + +// The following tests check that the SeparateCompoundExpressions step during MSL shader translation +// handles comma expressions correctly when at least one of the operands is a function call. +TEST_F(MSLOutputTest, CommaOpTwoFunctionCallsWithGlobalsNoCrash) +{ + ShCompileOptions options = defaultOptions(); + const char kShader[] = R"( +int g; +void F(int v) { g = v; } +void main() { F(g), F(g); })"; + compile(kShader, options); +} + +TEST_F(MSLOutputTest, CommaOpLeftFunctionCallWithGlobalsNoCrash) +{ + ShCompileOptions options = defaultOptions(); + const char kShader[] = R"( +int g; +void F(int v) { g = v; } +void main() { F(g), F(1); })"; + compile(kShader, options); +} + +TEST_F(MSLOutputTest, CommaOpRightFunctionCallWithGlobalsNoCrash) +{ + ShCompileOptions options = defaultOptions(); + const char kShader[] = R"( +int g; +void F(int v) { g = v; } +void main() { F(1), F(g); })"; + compile(kShader, options); +} + +TEST_F(MSLOutputTest, EnsureLoopForwardProgressInfinite) +{ + ShCompileOptions options = defaultOptions(); + options.ensureLoopForwardProgress = 1; + const std::string &shaderString = + R"( + precision mediump float; + void main() { + for (int i = 0; i < i + 1; ++i) { } + gl_FragColor = vec4(1); + })"; + compile(shaderString, options); + ASSERT_TRUE(foundInCode(SH_MSL_METAL_OUTPUT, "loopForwardProgress();")); + ASSERT_TRUE(foundInCode(SH_MSL_METAL_OUTPUT, "volatile bool p = true;")); +} + +TEST_F(MSLOutputTest, EnsureLoopForwardProgressFinite) +{ + ShCompileOptions options = defaultOptions(); + options.ensureLoopForwardProgress = 1; + const std::string &shaderString = + R"( + precision mediump float; + void main() { + for (int i = 0; i < 1; ++i) { } + gl_FragColor = vec4(1); + })"; + compile(shaderString, options); + ASSERT_FALSE(foundInCode(SH_MSL_METAL_OUTPUT, "loopForwardProgress();")); +} diff --git a/src/tests/compiler_tests/OES_sample_variables_test.cpp b/src/tests/compiler_tests/OES_sample_variables_test.cpp deleted file mode 100644 index bf1dd98f2dd..00000000000 --- a/src/tests/compiler_tests/OES_sample_variables_test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright 2020 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. -// -// OES_sample_variables_test.cpp: -// Test for OES_sample_variables -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -namespace -{ -const char OESPragma[] = "#extension GL_OES_sample_variables : require\n"; - -// Shader using gl_SampleMask with non-constant index -// This shader is in the deqp test -// (functional_shaders_sample_variables_sample_mask_discard_half_per_sample_default_framebuffer) -const char ESSL310_GLSampleMaskShader[] = - R"( - layout(location = 0) out mediump vec4 fragColor; - void main (void) - { - for (int i = 0; i < gl_SampleMask.length(); ++i) - gl_SampleMask[i] = int(0xAAAAAAAA); - - // force per-sample shading - highp float blue = float(gl_SampleID); - - fragColor = vec4(0.0, 1.0, blue, 1.0); - })"; - -// Shader using gl_SampleMask with non-constant index -// This shader is based on the deqp test on below -// (functional_shaders_sample_variables_sample_mask_in_bit_count_per_sample_multisample_texture_2) -const char ESSL310_GLSampleMaskInShader[] = - R"( - layout(location = 0) out mediump vec4 fragColor; - void main (void) - { - mediump int maskBitCount = 0; - for (int j = 0; j < gl_SampleMaskIn.length(); ++j) - { - for (int i = 0; i < 32; ++i) - { - if (((gl_SampleMaskIn[j] >> i) & 0x01) == 0x01) - { - ++maskBitCount; - } - } - } - - // force per-sample shading - highp float blue = float(gl_SampleID); - - if (maskBitCount != 1) - fragColor = vec4(1.0, 0.0, blue, 1.0); - else - fragColor = vec4(0.0, 1.0, blue, 1.0); - })"; - -class OESSampleVariablesTest : public sh::ShaderExtensionTest -{ - public: - void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); } - void InitializeCompiler(ShShaderOutput shaderOutputType) - { - DestroyCompiler(); - - mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), - shaderOutputType, &mResources); - ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; - } - - testing::AssertionResult TestShaderCompile(const char *pragma) - { - const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma, - testing::get<2>(GetParam())}; - - ShCompileOptions compileOptions = {}; - compileOptions.objectCode = true; - - bool success = sh::Compile(mCompiler, shaderStrings, 3, compileOptions); - if (success) - { - return ::testing::AssertionSuccess() << "Compilation success"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); - } -}; - -// GLES3 needs OES_sample_variables extension -class OESSampleVariablesTestES31 : public OESSampleVariablesTest -{}; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(OESSampleVariablesTestES31, CompileFailsWithoutExtension) -{ - mResources.OES_sample_variables = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(OESPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(OESSampleVariablesTestES31, CompileFailsWithExtensionWithoutPragma) -{ - mResources.OES_sample_variables = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -#ifdef ANGLE_ENABLE_VULKAN -TEST_P(OESSampleVariablesTestES31, CompileSucceedsWithExtensionAndPragmaOnVulkan) -{ - mResources.OES_sample_variables = 1; - InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT); - EXPECT_TRUE(TestShaderCompile(OESPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(OESPragma)); -} -#endif - -INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders, - OESSampleVariablesTestES31, - Combine(Values(SH_GLES3_1_SPEC), - Values(sh::ESSLVersion310), - Values(ESSL310_GLSampleMaskShader, ESSL310_GLSampleMaskInShader))); - -} // anonymous namespace diff --git a/src/tests/compiler_tests/OES_standard_derivatives_test.cpp b/src/tests/compiler_tests/OES_standard_derivatives_test.cpp deleted file mode 100644 index e4741cee5d0..00000000000 --- a/src/tests/compiler_tests/OES_standard_derivatives_test.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright 2018 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. -// -// OES_standard_derivatives_test.cpp: -// Test for OES_standard_derivatives -// - -#include "tests/test_utils/ShaderExtensionTest.h" - -using OESStandardDerivativesTest = sh::ShaderExtensionTest; - -namespace -{ -const char OESPragma[] = "#extension GL_OES_standard_derivatives : require\n"; - -// Shader calling dFdx() -const char ESSL100_DfdxShader[] = - R"( - precision mediump float; - varying float x; - - void main() - { - gl_FragColor = vec4(dFdx(x)); - })"; - -// Shader calling dFdy() -const char ESSL100_DfdyShader[] = - R"( - precision mediump float; - varying float x; - - void main() - { - gl_FragColor = vec4(dFdy(x)); - })"; - -// Shader calling fwidth() -const char ESSL100_FwidthShader[] = - R"( - precision mediump float; - varying float x; - - void main() - { - gl_FragColor = vec4(fwidth(x)); - })"; - -// Extension flag is required to compile properly. Expect failure when it is -// not present. -TEST_P(OESStandardDerivativesTest, CompileFailsWithoutExtension) -{ - mResources.OES_standard_derivatives = 0; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile(OESPragma)); -} - -// Extension directive is required to compile properly. Expect failure when -// it is not present. -TEST_P(OESStandardDerivativesTest, CompileFailsWithExtensionWithoutPragma) -{ - mResources.OES_standard_derivatives = 1; - InitializeCompiler(); - EXPECT_FALSE(TestShaderCompile("")); -} - -// With extension flag and extension directive, compiling succeeds. -// Also test that the extension directive state is reset correctly. -TEST_P(OESStandardDerivativesTest, CompileSucceedsWithExtensionAndPragma) -{ - mResources.OES_standard_derivatives = 1; - InitializeCompiler(); - EXPECT_TRUE(TestShaderCompile(OESPragma)); - // Test reset functionality. - EXPECT_FALSE(TestShaderCompile("")); - EXPECT_TRUE(TestShaderCompile(OESPragma)); -} - -// The SL #version 100 shaders that are correct work similarly -// in both GL2 and GL3, with and without the version string. -INSTANTIATE_TEST_SUITE_P( - CorrectESSL100Shaders, - OESStandardDerivativesTest, - Combine(Values(SH_GLES2_SPEC), - Values(sh::ESSLVersion100), - Values(ESSL100_DfdxShader, ESSL100_DfdyShader, ESSL100_FwidthShader))); - -} // anonymous namespace diff --git a/src/tests/compiler_tests/OES_texture_cube_map_array_test.cpp b/src/tests/compiler_tests/OES_texture_cube_map_array_test.cpp deleted file mode 100644 index 7add03fc28f..00000000000 --- a/src/tests/compiler_tests/OES_texture_cube_map_array_test.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// -// Copyright 2020 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. -// -// OES_texture_cube_map_array_test.cpp: -// Test for the [OES/EXT]_texture_cube_map_array extension -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class TextureCubeMapArrayTestNoExt : public ShaderCompileTreeTest -{ - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } -}; - -class OESTextureCubeMapArrayTest : public TextureCubeMapArrayTestNoExt -{ - protected: - void initResources(ShBuiltInResources *resources) override - { - resources->OES_texture_cube_map_array = 1; - } -}; - -class EXTTextureCubeMapArrayTest : public TextureCubeMapArrayTestNoExt -{ - protected: - void initResources(ShBuiltInResources *resources) override - { - resources->EXT_texture_cube_map_array = 1; - } -}; - -// Check that if the extension is not supported, trying to use the features without having an -// extension directive fails. -TEST_F(TextureCubeMapArrayTestNoExt, MissingExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension is not supported, trying to use the features without having an -// extension directive fails. -TEST_F(OESTextureCubeMapArrayTest, MissingExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension is not supported, trying to use the features without having an -// extension directive fails. -TEST_F(EXTTextureCubeMapArrayTest, MissingExtensionDirective) -{ - const std::string &shaderString = - R"( - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension is enabled, trying to use the features without the extension -// enabled fails. -TEST_F(TextureCubeMapArrayTestNoExt, ExtensionEnabledOES) -{ - const std::string &shaderString = - R"(#version 310 es - #extension GL_OES_texture_cube_map_array : enable - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension supported and enabled, using the features succeeds. -TEST_F(OESTextureCubeMapArrayTest, ExtensionEnabledOES) -{ - const std::string &shaderString = - R"(#version 310 es - #extension GL_OES_texture_cube_map_array : enable - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Check that if the extension is enabled, trying to use the features without the extension -// enabled fails. -TEST_F(EXTTextureCubeMapArrayTest, ExtensionEnabledOES) -{ - const std::string &shaderString = - R"(#version 310 es - #extension GL_OES_texture_cube_map_array : enable - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension is enabled, trying to use the features without the extension -// enabled fails. -TEST_F(TextureCubeMapArrayTestNoExt, ExtensionEnabledEXT) -{ - const std::string &shaderString = - R"(#version 310 es - #extension GL_EXT_texture_cube_map_array : enable - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension is enabled, trying to use the features without the extension -// enabled fails. -TEST_F(OESTextureCubeMapArrayTest, ExtensionEnabledEXT) -{ - const std::string &shaderString = - R"(#version 310 es - #extension GL_EXT_texture_cube_map_array : enable - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Check that if the extension supported and enabled, using the features succeeds. -TEST_F(EXTTextureCubeMapArrayTest, ExtensionEnabledEXT) -{ - const std::string &shaderString = - R"(#version 310 es - #extension GL_EXT_texture_cube_map_array : enable - precision mediump float; - uniform highp isamplerCubeArray u_sampler; - void main() - { - vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); - })"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} diff --git a/src/tests/compiler_tests/OVR_multiview2_test.cpp b/src/tests/compiler_tests/OVR_multiview2_test.cpp index 6cd0ea664f6..cad53ed25a8 100644 --- a/src/tests/compiler_tests/OVR_multiview2_test.cpp +++ b/src/tests/compiler_tests/OVR_multiview2_test.cpp @@ -94,7 +94,7 @@ class OVRMultiview2VertexShaderTest : public ShaderCompileTreeTest protected: ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; } + ShShaderSpec getShaderSpec() const override { return SH_WEBGL2_SPEC; } void initResources(ShBuiltInResources *resources) override { resources->OVR_multiview = 1; @@ -110,7 +110,7 @@ class OVRMultiview2FragmentShaderTest : public ShaderCompileTreeTest protected: ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; } + ShShaderSpec getShaderSpec() const override { return SH_WEBGL2_SPEC; } void initResources(ShBuiltInResources *resources) override { resources->OVR_multiview = 1; diff --git a/src/tests/compiler_tests/Pack_Unpack_test.cpp b/src/tests/compiler_tests/Pack_Unpack_test.cpp deleted file mode 100644 index 629009b85d5..00000000000 --- a/src/tests/compiler_tests/Pack_Unpack_test.cpp +++ /dev/null @@ -1,128 +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. -// -// Pack_Unpack_test.cpp: -// Tests for the emulating pack_unpack functions for GLSL. -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/compiler_test.h" - -using namespace sh; - -namespace -{ - -class PackUnpackTest : public MatchOutputCodeTest -{ - public: - PackUnpackTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_GLSL_400_CORE_OUTPUT) {} -}; - -// Check if PackSnorm2x16 Emulation for GLSL < 4.2 compile correctly. -TEST_F(PackUnpackTest, PackSnorm2x16Emulation) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - layout(location = 0) out mediump vec4 fragColor; - void main() - { - vec2 v; - uint u = packSnorm2x16(v); - fragColor = vec4(u); - })"; - compile(shaderString); - ASSERT_TRUE(foundInCode("uint packSnorm2x16_emu(vec2 v)")); -} - -// Check if UnpackSnorm2x16 Emulation for GLSL < 4.2 compile correctly. -TEST_F(PackUnpackTest, UnpackSnorm2x16Emulation) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - layout(location = 0) out mediump vec4 fragColor; - void main() - { - uint u; - vec2 v = unpackSnorm2x16(u); - fragColor = vec4(v, 0.0, 0.0); - })"; - compile(shaderString); - ASSERT_TRUE(foundInCode("vec2 unpackSnorm2x16_emu(uint u)")); -} - -// Check if PackUnorm2x16 Emulation for GLSL < 4.1 compiles correctly. -TEST_F(PackUnpackTest, PackUnorm2x16Emulation) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - layout(location = 0) out mediump vec4 fragColor; - void main() - { - vec2 v; - uint u = packUnorm2x16(v); - fragColor = vec4(u); - })"; - compile(shaderString); - ASSERT_TRUE(foundInCode("uint packUnorm2x16_emu(vec2 v)")); -} - -// Check if UnpackSnorm2x16 Emulation for GLSL < 4.1 compiles correctly. -TEST_F(PackUnpackTest, UnpackUnorm2x16Emulation) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - layout(location = 0) out mediump vec4 fragColor; - void main() - { - uint u; - vec2 v = unpackUnorm2x16(u); - fragColor = vec4(v, 0.0, 0.0); - })"; - compile(shaderString); - ASSERT_TRUE(foundInCode("vec2 unpackUnorm2x16_emu(uint u)")); -} - -// Check if PackHalf2x16 Emulation for GLSL < 4.2 compiles correctly. -TEST_F(PackUnpackTest, PackHalf2x16Emulation) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - layout(location = 0) out mediump vec4 fragColor; - void main() - { - vec2 v; - uint u = packHalf2x16(v); - fragColor = vec4(u); - })"; - compile(shaderString); - ASSERT_TRUE(foundInCode("uint packHalf2x16_emu(vec2 v)")); -} - -// Check if UnpackHalf2x16 Emulation for GLSL < 4.2 compiles correctly. -TEST_F(PackUnpackTest, UnpackHalf2x16Emulation) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - layout(location = 0) out mediump vec4 fragColor; - void main() - { - uint u; - vec2 v = unpackHalf2x16(u); - fragColor = vec4(v, 0.0, 0.0); - })"; - compile(shaderString); - ASSERT_TRUE(foundInCode("vec2 unpackHalf2x16_emu(uint u)")); -} - -} // namespace diff --git a/src/tests/compiler_tests/Parse_test.cpp b/src/tests/compiler_tests/Parse_test.cpp index 43b58dd1fda..2d55f3172f2 100644 --- a/src/tests/compiler_tests/Parse_test.cpp +++ b/src/tests/compiler_tests/Parse_test.cpp @@ -21,7 +21,6 @@ class ParseTest : public testing::Test ParseTest() { InitBuiltInResources(&mResources); - mResources.FragmentPrecisionHigh = 1; mCompileOptions.intermediateTree = true; } @@ -42,7 +41,7 @@ class ParseTest : public testing::Test } const char *shaderStrings[] = {shaderString.c_str()}; - bool compilationSuccess = mTranslator->compile(shaderStrings, 1, mCompileOptions); + bool compilationSuccess = mTranslator->compile(shaderStrings, mCompileOptions); mInfoLog = mTranslator->getInfoSink().info.str(); if (!compilationSuccess) { @@ -125,6 +124,100 @@ void main() { } EXPECT_TRUE(foundInIntermediateTree("'index' : invalid layout qualifier")); } +// Test that with the conservative depth extension, gl_FragDepth +// can be redeclared successfully. +TEST_F(ParseTest, RedeclareFragDepthSuccess) +{ + mShaderSpec = SH_WEBGL2_SPEC; + mResources.EXT_conservative_depth = 1; + mCompileOptions.validateAST = 1; + const char kShader[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: enable +precision mediump float; +layout (depth_any) out float gl_FragDepth; +void main() { +} +)"; + EXPECT_TRUE(compile(kShader)); +} + +// Test that without the conservative depth extension, gl_FragDepth, +// cannot be redeclared. +TEST_F(ParseTest, RedeclareFragDepthNoExtFail) +{ + mShaderSpec = SH_WEBGL2_SPEC; + mResources.EXT_conservative_depth = 1; + mCompileOptions.validateAST = 1; + const char kShader[] = R"(#version 300 es +precision mediump float; +layout (depth_any) out float gl_FragDepth; +void main() { +} +)"; + EXPECT_FALSE(compile(kShader)); + EXPECT_TRUE(foundErrorInIntermediateTree()); + EXPECT_TRUE(foundInIntermediateTree("reserved built-in name")); +} + +// Test that even with the conservative depth extension, gl_FragDepth +// cannot be redeclared locally. +TEST_F(ParseTest, RedeclareFragDepthLocallyFail) +{ + mShaderSpec = SH_WEBGL2_SPEC; + mResources.EXT_conservative_depth = 1; + mCompileOptions.validateAST = 1; + const char kShader[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: enable +precision mediump float; +void main() { + layout (depth_any) out float gl_FragDepth; +} +)"; + EXPECT_FALSE(compile(kShader)); + EXPECT_TRUE(foundErrorInIntermediateTree()); + EXPECT_TRUE(foundInIntermediateTree("gl_FragDepth can only be redeclared as fragment output")); +} + +// Test that with the conservative depth extension, gl_FragDepth +// can only be redeclared once. +TEST_F(ParseTest, RedeclareFragDepthTwiceFail) +{ + mShaderSpec = SH_WEBGL2_SPEC; + mResources.EXT_conservative_depth = 1; + mCompileOptions.validateAST = 1; + const char kShader[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: enable +precision mediump float; +layout (depth_any) out float gl_FragDepth; +layout (depth_any) out float gl_FragDepth; +void main() { +} +)"; + EXPECT_FALSE(compile(kShader)); + EXPECT_TRUE(foundErrorInIntermediateTree()); + EXPECT_TRUE(foundInIntermediateTree("redefinition")); +} + +// Test that with the conservative depth extension gl_FragDepth +// can only be redeclared globally. +TEST_F(ParseTest, RedeclareFragDepthGlobalAndLocalFail) +{ + mShaderSpec = SH_WEBGL2_SPEC; + mResources.EXT_conservative_depth = 1; + mCompileOptions.validateAST = 1; + const char kShader[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: enable +precision mediump float; +layout (depth_any) out float gl_FragDepth; +void main() { + float gl_FragDepth = 1.0; +} +)"; + EXPECT_FALSE(compile(kShader)); + EXPECT_TRUE(foundErrorInIntermediateTree()); + EXPECT_TRUE(foundInIntermediateTree("reserved built-in name")); +} + TEST_F(ParseTest, Radians320NoCrash) { const char kShader[] = R"(#version 320 es @@ -148,21 +241,6 @@ void main() { EXPECT_TRUE(foundInIntermediateTree("coherent specified multiple times")); } -TEST_F(ParseTest, LargeArrayIndexNoCrash) -{ - mShaderSpec = SH_WEBGL2_SPEC; - const char kShader[] = R"(#version 300 es -int rr[~1U]; -out int o; -void main() { - o = rr[1]; -})"; - EXPECT_FALSE(compile(kShader)); - EXPECT_TRUE(foundErrorInIntermediateTree()); - EXPECT_TRUE( - foundInIntermediateTree("Size of declared variable exceeds implementation-defined limit")); -} - // Tests that separating variable declaration of multiple instances of a anonymous structure // rewrites the expression types for expressions that use the variables. At the time of writing // the expression types were left referencing the original anonymous function. @@ -803,7 +881,7 @@ void f(out float r, out float) 0:4: Function Prototype: 'main' (symbol id 3004) (void) 0:5: Code block 0:6: move second child to first child (mediump 4-component vector of float) -0:6: gl_FragColor (symbol id 2230) (FragColor mediump 4-component vector of float) +0:6: gl_FragColor (symbol id 1917) (FragColor mediump 4-component vector of float) 0:6: Constant union (const mediump 4-component vector of float) 0:6: 0.5 (const float) 0:6: 0.5 (const float) @@ -811,9 +889,9 @@ void f(out float r, out float) 0:6: 0.5 (const float) 0:7: Call a function: 'f' (symbol id 3001) (void) 0:7: vector swizzle (x) (mediump float) -0:7: gl_FragColor (symbol id 2230) (FragColor mediump 4-component vector of float) +0:7: gl_FragColor (symbol id 1917) (FragColor mediump 4-component vector of float) 0:7: vector swizzle (y) (mediump float) -0:7: gl_FragColor (symbol id 2230) (FragColor mediump 4-component vector of float) +0:7: gl_FragColor (symbol id 1917) (FragColor mediump 4-component vector of float) 0:9: Function Definition: 0:9: Function Prototype: 'f' (symbol id 3001) (void) 0:9: parameter: 'r' (symbol id 3006) (out highp float) @@ -824,7 +902,7 @@ void f(out float r, out float) 0:11: Constant union (const highp float) 0:11: 1.0 (const float) )"; - compile(kShader); + EXPECT_TRUE(compile(kShader)); EXPECT_EQ(kExpected, intermediateTree()); } diff --git a/src/tests/compiler_tests/Precise_test.cpp b/src/tests/compiler_tests/Precise_test.cpp index 7dac0e15156..beb231480cb 100644 --- a/src/tests/compiler_tests/Precise_test.cpp +++ b/src/tests/compiler_tests/Precise_test.cpp @@ -82,6 +82,10 @@ class PreciseTest : public testing::TestWithParam ShCompileOptions options = {}; options.objectCode = true; + if (shaderOutputType == SH_SPIRV_VULKAN_OUTPUT || shaderOutputType == SH_MSL_METAL_OUTPUT) + { + options.removeInactiveVariables = true; + } bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 1, options); if (success) diff --git a/src/tests/compiler_tests/RewriteDoWhile_test.cpp b/src/tests/compiler_tests/RewriteDoWhile_test.cpp deleted file mode 100644 index cfa05fd19ea..00000000000 --- a/src/tests/compiler_tests/RewriteDoWhile_test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2017 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. -// -// RewriteDoWhile_test.cpp: -// Tests that the RewriteDoWhile AST transform works correctly. -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class RewriteDoWhileCrashTest : public ShaderCompileTreeTest -{ - public: - RewriteDoWhileCrashTest() {} - - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } - - void SetUp() override - { - mCompileOptions.rewriteDoWhileLoops = true; - ShaderCompileTreeTest::SetUp(); - } -}; - -// Make sure that the RewriteDoWhile step doesn't crash. Regression test. -TEST_F(RewriteDoWhileCrashTest, RunsSuccessfully) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform int u;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " int foo = 1;" - " do\n" - " {\n" - " foo *= u;\n" - " } while (foo < 8);\n" - " my_FragColor = vec4(foo) * 0.1;" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} diff --git a/src/tests/compiler_tests/SamplerMultisample_test.cpp b/src/tests/compiler_tests/SamplerMultisample_test.cpp index 472bbfd19fb..9d337a8620c 100644 --- a/src/tests/compiler_tests/SamplerMultisample_test.cpp +++ b/src/tests/compiler_tests/SamplerMultisample_test.cpp @@ -39,50 +39,6 @@ class SamplerMultisampleArrayTest : public ShaderCompileTreeTest ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } }; -// Checks whether compiler has parsed the gsampler2DMS, texelfetch correctly. -TEST_F(SamplerMultisampleTest, TexelFetchSampler2DMS) -{ - constexpr char kShaderString[] = - R"(#version 310 es - precision highp float; - uniform highp sampler2DMS s; - uniform highp isampler2DMS is; - uniform highp usampler2DMS us; - - void main() { - vec4 tex1 = texelFetch(s, ivec2(0, 0), 0); - ivec4 tex2 = texelFetch(is, ivec2(0, 0), 0); - uvec4 tex3 = texelFetch(us, ivec2(0, 0), 0); - })"; - - if (!compile(kShaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Checks whether compiler has parsed the gsampler2DMS, textureSize correctly. -TEST_F(SamplerMultisampleTest, TextureSizeSampler2DMS) -{ - constexpr char kShaderString[] = - R"(#version 310 es - precision highp float; - uniform highp sampler2DMS s; - uniform highp isampler2DMS is; - uniform highp usampler2DMS us; - - void main() { - ivec2 size = textureSize(s); - size = textureSize(is); - size = textureSize(us); - })"; - - if (!compile(kShaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - // Check that sampler2DMS has no default precision. TEST_F(SamplerMultisampleTest, NoPrecisionSampler2DMS) { @@ -233,52 +189,6 @@ TEST_F(SamplerMultisampleTest, USampler2DMSArrayNotSupported) } } -// Checks whether compiler has parsed the gsampler2DMSArray, texelfetch correctly. -TEST_F(SamplerMultisampleArrayTest, TexelFetchSampler2DMSArray) -{ - constexpr char kShaderString[] = - R"(#version 310 es - #extension GL_OES_texture_storage_multisample_2d_array : require - precision highp float; - uniform highp sampler2DMSArray s; - uniform highp isampler2DMSArray is; - uniform highp usampler2DMSArray us; - - void main() { - vec4 tex1 = texelFetch(s, ivec3(0, 0, 0), 0); - ivec4 tex2 = texelFetch(is, ivec3(0, 0, 0), 0); - uvec4 tex3 = texelFetch(us, ivec3(0, 0, 0), 0); - })"; - - if (!compile(kShaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Checks whether compiler has parsed the gsampler2DMSArray, textureSize correctly. -TEST_F(SamplerMultisampleArrayTest, TextureSizeSampler2DMSArray) -{ - constexpr char kShaderString[] = - R"(#version 310 es - #extension GL_OES_texture_storage_multisample_2d_array : require - precision highp float; - uniform highp sampler2DMSArray s; - uniform highp isampler2DMSArray is; - uniform highp usampler2DMSArray us; - - void main() { - ivec3 size = textureSize(s); - size = textureSize(is); - size = textureSize(us); - })"; - - if (!compile(kShaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - // Check that sampler2DMSArray has no default precision. TEST_F(SamplerMultisampleArrayTest, NoPrecisionSampler2DMSArray) { @@ -345,32 +255,6 @@ class SamplerMultisampleEXTTest : public SamplerMultisampleTest ShShaderSpec getShaderSpec() const override { return SH_GLES3_SPEC; } }; -// checks ANGLE_texture_multisample is supported in es 3.0 -TEST_F(SamplerMultisampleEXTTest, TextureMultisampleEXTEnabled) -{ - constexpr char kShaderString[] = - R"(#version 300 es - #extension GL_ANGLE_texture_multisample : require - precision highp float; - uniform highp sampler2DMS s; - uniform highp isampler2DMS is; - uniform highp usampler2DMS us; - - void main() { - ivec2 size = textureSize(s); - size = textureSize(is); - size = textureSize(us); - vec4 tex1 = texelFetch(s, ivec2(0, 0), 0); - ivec4 tex2 = texelFetch(is, ivec2(0, 0), 0); - uvec4 tex3 = texelFetch(us, ivec2(0, 0), 0); - })"; - - if (!compile(kShaderString)) - { - FAIL() << "Shader compilation failure, expecting success:\n" << mInfoLog; - } -} - // checks that multisample texture is not supported without ANGLE_texture_multisample in es 3.0 TEST_F(SamplerMultisampleEXTTest, TextureMultisampleEXTDisabled) { diff --git a/src/tests/compiler_tests/SamplerVideoWEBGL_test.cpp b/src/tests/compiler_tests/SamplerVideoWEBGL_test.cpp deleted file mode 100644 index df1d0c77170..00000000000 --- a/src/tests/compiler_tests/SamplerVideoWEBGL_test.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright 2019 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. -// -// samplerVideoWEBGL_test.cpp: -// Tests compiling shaders that use samplerVideoWEBGL types -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -using namespace sh; - -class SamplerVideoWEBGLTest : public ShaderCompileTreeTest -{ - public: - SamplerVideoWEBGLTest() {} - - void initResources(ShBuiltInResources *resources) override - { - resources->WEBGL_video_texture = 1; - } - - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } -}; - -// Checks whether compiler returns error when extension isn't enabled but samplerVideoWEBGL is -// used in shader. -TEST_F(SamplerVideoWEBGLTest, UsingSamplerVideoWEBGLWithoutWEBGLVideoTextureExtensionRequired) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform mediump samplerVideoWEBGL s;\n" - "void main()\n" - "{\n" - " gl_FragColor = textureVideoWEBGL(s, vec2(0.0, 0.0));\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation passed, expecting fail:\n" << mInfoLog; - } -} - -// Checks whether compiler returns error when extension isn't enabled but use samplerVideoWEBGL is -// used in ES300 shader. -TEST_F(SamplerVideoWEBGLTest, - UsingSamplerVideoWEBGLWithoutWEBGLVideoTextureExtensionRequiredInES300) -{ - const std::string &shaderString = - "#version 300 es" - "precision mediump float;\n" - "uniform mediump samplerVideoWEBGL s;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " my_FragColor = texture(s, vec2(0.0, 0.0));\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation passed, expecting fail:\n" << mInfoLog; - } -} - -// Checks whether compiler can support samplerVideoWEBGL as texture2D parameter. -TEST_F(SamplerVideoWEBGLTest, SamplerVideoWEBGLCanBeSupportedInTexture2D) -{ - const std::string &shaderString = - "#extension GL_WEBGL_video_texture : require\n" - "precision mediump float;\n" - "uniform mediump samplerVideoWEBGL s;\n" - "void main()\n" - "{\n" - " gl_FragColor = textureVideoWEBGL(s, vec2(0.0, 0.0));\n" - "}\n"; - - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Checks whether compiler can support samplerVideoWEBGL as texture parameter in ES300. -TEST_F(SamplerVideoWEBGLTest, SamplerVideoWEBGLCanBeSupportedInTextureInES300) -{ - const std::string &shaderString = - "#version 300 es\n" - "#extension GL_WEBGL_video_texture : require\n" - "precision mediump float;\n" - "uniform mediump samplerVideoWEBGL s;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " my_FragColor = texture(s, vec2(0.0, 0.0));\n" - "}\n"; - - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} \ No newline at end of file diff --git a/src/tests/compiler_tests/SeparateDeclarations_test.cpp b/src/tests/compiler_tests/SeparateDeclarations_test.cpp index 30390267727..01fb3f607c9 100644 --- a/src/tests/compiler_tests/SeparateDeclarations_test.cpp +++ b/src/tests/compiler_tests/SeparateDeclarations_test.cpp @@ -168,10 +168,12 @@ void main() { o = vec4(1); })"; const char kExpected[] = R"(#version 300 es -struct sbbe { +struct { highp vec3 _ud; } _ua; -sbbe _ub; +struct { + highp vec3 _ud; +} _ub; out highp vec4 _uo; void main(){ if (any(lessThan(_ua._ud, _ub._ud))) @@ -195,10 +197,9 @@ void main() { o = vec4(1); })"; const char kExpected[] = R"(#version 300 es -struct sbbd { +struct { highp vec3 _ud; -}; -sbbd _ua; +} _ua; out highp vec4 _uo; void main(){ if (any(lessThan(_ua._ud, vec3(2.0, 2.0, 2.0)))) @@ -222,11 +223,12 @@ void main() { o = vec4(1); })"; const char kExpected[] = R"(#version 300 es -struct sbbe { +struct { highp vec3 _ud; -}; -sbbe _ua; -sbbe _ub; +} _ua; +struct { + highp vec3 _ud; +} _ub; out highp vec4 _uo; void main(){ if (any(lessThan(_ua._ud, _ub._ud))) @@ -352,10 +354,9 @@ void main(){ gl_FragColor = g.e + s.f; })"; compile(kShader); - const char kExpected[] = R"(struct sbbf { + const char kExpected[] = R"(struct { highp vec4 _ue; -}; -sbbf _ug; +} _ug; struct _usbbf { highp vec4 _uf; }; diff --git a/src/tests/compiler_tests/ShCompile_test.cpp b/src/tests/compiler_tests/ShCompile_test.cpp index c9f4ddfb436..ed67f9b1b32 100644 --- a/src/tests/compiler_tests/ShCompile_test.cpp +++ b/src/tests/compiler_tests/ShCompile_test.cpp @@ -83,7 +83,7 @@ class ShCompileComputeTest : public ShCompileTest void SetUp() override { sh::InitBuiltInResources(&mResources); - mCompiler = sh::ConstructCompiler(GL_COMPUTE_SHADER, SH_WEBGL3_SPEC, + mCompiler = sh::ConstructCompiler(GL_COMPUTE_SHADER, SH_GLES3_1_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT, &mResources); ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; } diff --git a/src/tests/compiler_tests/ShaderImage_test.cpp b/src/tests/compiler_tests/ShaderImage_test.cpp deleted file mode 100644 index 743c770088c..00000000000 --- a/src/tests/compiler_tests/ShaderImage_test.cpp +++ /dev/null @@ -1,260 +0,0 @@ -// -// Copyright 2016 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. -// -// ShaderImage_test.cpp: -// Tests for images -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "compiler/translator/StaticType.h" -#include "gtest/gtest.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" -#include "tests/test_utils/compiler_test.h" - -using namespace sh; - -namespace -{ - -// Checks that the imageStore call with mangled name imageStoreMangledName exists in the AST. -// Further each argument is checked whether it matches the expected properties given the compiled -// shader. -void CheckImageStoreCall(TIntermNode *astRoot, - const TString &imageStoreMangledName, - TBasicType imageType, - int storeLocationNominalSize, - TBasicType storeValueType, - int storeValueNominalSize) -{ - const TIntermAggregate *imageStoreFunctionCall = - FindFunctionCallNode(astRoot, imageStoreMangledName); - ASSERT_NE(nullptr, imageStoreFunctionCall); - - const TIntermSequence *storeArguments = imageStoreFunctionCall->getSequence(); - ASSERT_EQ(3u, storeArguments->size()); - - const TIntermTyped *storeArgument1Typed = (*storeArguments)[0]->getAsTyped(); - ASSERT_EQ(imageType, storeArgument1Typed->getBasicType()); - - const TIntermTyped *storeArgument2Typed = (*storeArguments)[1]->getAsTyped(); - ASSERT_EQ(EbtInt, storeArgument2Typed->getBasicType()); - ASSERT_EQ(storeLocationNominalSize, storeArgument2Typed->getNominalSize()); - - const TIntermTyped *storeArgument3Typed = (*storeArguments)[2]->getAsTyped(); - ASSERT_EQ(storeValueType, storeArgument3Typed->getBasicType()); - ASSERT_EQ(storeValueNominalSize, storeArgument3Typed->getNominalSize()); -} - -// Checks that the imageLoad call with mangled name imageLoadMangledName exists in the AST. -// Further each argument is checked whether it matches the expected properties given the compiled -// shader. -void CheckImageLoadCall(TIntermNode *astRoot, - const TString &imageLoadMangledName, - TBasicType imageType, - int loadLocationNominalSize) -{ - const TIntermAggregate *imageLoadFunctionCall = - FindFunctionCallNode(astRoot, imageLoadMangledName); - ASSERT_NE(nullptr, imageLoadFunctionCall); - - const TIntermSequence *loadArguments = imageLoadFunctionCall->getSequence(); - ASSERT_EQ(2u, loadArguments->size()); - - const TIntermTyped *loadArgument1Typed = (*loadArguments)[0]->getAsTyped(); - ASSERT_EQ(imageType, loadArgument1Typed->getBasicType()); - - const TIntermTyped *loadArgument2Typed = (*loadArguments)[1]->getAsTyped(); - ASSERT_EQ(EbtInt, loadArgument2Typed->getBasicType()); - ASSERT_EQ(loadLocationNominalSize, loadArgument2Typed->getNominalSize()); -} - -// Checks whether the image is properly exported as a uniform by the compiler. -void CheckExportedImageUniform(const std::vector &uniforms, - size_t uniformIndex, - ::GLenum imageTypeGL, - const TString &imageName) -{ - ASSERT_EQ(1u, uniforms.size()); - - const auto &imageUniform = uniforms[uniformIndex]; - ASSERT_EQ(imageTypeGL, imageUniform.type); - ASSERT_STREQ(imageUniform.name.c_str(), imageName.c_str()); -} - -// Checks whether the image is saved in the AST as a node with the correct properties given the -// shader. -void CheckImageDeclaration(TIntermNode *astRoot, - const ImmutableString &imageName, - TBasicType imageType, - TLayoutImageInternalFormat internalFormat, - bool readonly, - bool writeonly, - bool coherent, - bool restrictQualifier, - bool volatileQualifier, - int binding) -{ - const TIntermSymbol *myImageNode = FindSymbolNode(astRoot, imageName); - ASSERT_NE(nullptr, myImageNode); - - ASSERT_EQ(imageType, myImageNode->getBasicType()); - const TType &myImageType = myImageNode->getType(); - TLayoutQualifier myImageLayoutQualifier = myImageType.getLayoutQualifier(); - ASSERT_EQ(internalFormat, myImageLayoutQualifier.imageInternalFormat); - TMemoryQualifier myImageMemoryQualifier = myImageType.getMemoryQualifier(); - ASSERT_EQ(readonly, myImageMemoryQualifier.readonly); - ASSERT_EQ(writeonly, myImageMemoryQualifier.writeonly); - ASSERT_EQ(coherent, myImageMemoryQualifier.coherent); - ASSERT_EQ(restrictQualifier, myImageMemoryQualifier.restrictQualifier); - ASSERT_EQ(volatileQualifier, myImageMemoryQualifier.volatileQualifier); - ASSERT_EQ(binding, myImageType.getLayoutQualifier().binding); -} - -} // namespace - -class ShaderImageTest : public ShaderCompileTreeTest -{ - public: - ShaderImageTest() {} - - protected: - void SetUp() override { ShaderCompileTreeTest::SetUp(); } - - ::GLenum getShaderType() const override { return GL_COMPUTE_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } -}; - -// Test that an image2D is properly parsed and exported as a uniform. -TEST_F(ShaderImageTest, Image2DDeclaration) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 4) in;\n" - "layout(rgba32f, binding = 1) uniform highp readonly image2D myImage;\n" - "void main() {\n" - " ivec2 sz = imageSize(myImage);\n" - "}"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed" << mInfoLog; - } - - CheckExportedImageUniform(getUniforms(), 0, GL_IMAGE_2D, "myImage"); - CheckImageDeclaration(mASTRoot, ImmutableString("myImage"), EbtImage2D, EiifRGBA32F, true, - false, false, false, false, 1); -} - -// Test that an image3D is properly parsed and exported as a uniform. -TEST_F(ShaderImageTest, Image3DDeclaration) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 4) in;\n" - "layout(rgba32ui, binding = 3) uniform highp writeonly readonly uimage3D myImage;\n" - "void main() {\n" - " ivec3 sz = imageSize(myImage);\n" - "}"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed" << mInfoLog; - } - - CheckExportedImageUniform(getUniforms(), 0, GL_UNSIGNED_INT_IMAGE_3D, "myImage"); - CheckImageDeclaration(mASTRoot, ImmutableString("myImage"), EbtUImage3D, EiifRGBA32UI, true, - true, false, false, false, 3); -} - -// Check that imageLoad calls get correctly parsed. -TEST_F(ShaderImageTest, ImageLoad) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 4) in;\n" - "layout(rgba32f) uniform highp readonly image2D my2DImageInput;\n" - "layout(rgba32i) uniform highp readonly iimage3D my3DImageInput;\n" - "layout(rgba32f) uniform highp writeonly image2D imageOutput;\n" - "void main() {\n" - " vec4 result = imageLoad(my2DImageInput, ivec2(gl_LocalInvocationID.xy));\n" - " ivec4 result2 = imageLoad(my3DImageInput, ivec3(gl_LocalInvocationID.xyz));\n" - " // Ensure the imageLoad calls are not dead-code eliminated\n" - " imageStore(imageOutput, ivec2(0), result + vec4(result2));\n" - "}"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed" << mInfoLog; - } - - // imageLoad call with image2D passed - std::string mangledName2D = "imageLoad("; - mangledName2D += StaticType::GetBasic()->getMangledName(); - mangledName2D += StaticType::GetBasic()->getMangledName(); - CheckImageLoadCall(mASTRoot, mangledName2D.c_str(), EbtImage2D, 2); - - // imageLoad call with image3D passed - std::string mangledName3D = "imageLoad("; - mangledName3D += StaticType::GetBasic()->getMangledName(); - mangledName3D += StaticType::GetBasic()->getMangledName(); - CheckImageLoadCall(mASTRoot, mangledName3D.c_str(), EbtIImage3D, 3); -} - -// Check that imageStore calls get correctly parsed. -TEST_F(ShaderImageTest, ImageStore) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 4) in;\n" - "layout(rgba32f) uniform highp writeonly image2D my2DImageOutput;\n" - "layout(rgba32ui) uniform highp writeonly uimage2DArray my2DImageArrayOutput;\n" - "void main() {\n" - " imageStore(my2DImageOutput, ivec2(gl_LocalInvocationID.xy), vec4(0.0));\n" - " imageStore(my2DImageArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));\n" - "}"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed" << mInfoLog; - } - - // imageStore call with image2D - std::string mangledName2D = "imageStore("; - mangledName2D += StaticType::GetBasic()->getMangledName(); - mangledName2D += StaticType::GetBasic()->getMangledName(); - mangledName2D += StaticType::GetBasic()->getMangledName(); - CheckImageStoreCall(mASTRoot, mangledName2D.c_str(), EbtImage2D, 2, EbtFloat, 4); - - // imageStore call with image2DArray - std::string mangledName2DArray = "imageStore("; - mangledName2DArray += StaticType::GetBasic()->getMangledName(); - mangledName2DArray += StaticType::GetBasic()->getMangledName(); - mangledName2DArray += StaticType::GetBasic()->getMangledName(); - CheckImageStoreCall(mASTRoot, mangledName2DArray.c_str(), EbtUImage2DArray, 3, EbtUInt, 4); -} - -// Check that memory qualifiers are correctly parsed. -TEST_F(ShaderImageTest, ImageMemoryQualifiers) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 4) in;" - "layout(rgba32f) uniform highp coherent readonly image2D image1;\n" - "layout(rgba32f) uniform highp volatile writeonly image2D image2;\n" - "layout(rgba32f) uniform highp volatile restrict readonly writeonly image2D image3;\n" - "void main() {\n" - " imageSize(image1);\n" - " imageSize(image2);\n" - " imageSize(image3);\n" - "}"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed" << mInfoLog; - } - - CheckImageDeclaration(mASTRoot, ImmutableString("image1"), EbtImage2D, EiifRGBA32F, true, false, - true, false, false, -1); - CheckImageDeclaration(mASTRoot, ImmutableString("image2"), EbtImage2D, EiifRGBA32F, false, true, - true, false, true, -1); - CheckImageDeclaration(mASTRoot, ImmutableString("image3"), EbtImage2D, EiifRGBA32F, true, true, - true, true, true, -1); -} diff --git a/src/tests/compiler_tests/ShaderValidation_test.cpp b/src/tests/compiler_tests/ShaderValidation_test.cpp index d08410e85e3..a75960bf960 100644 --- a/src/tests/compiler_tests/ShaderValidation_test.cpp +++ b/src/tests/compiler_tests/ShaderValidation_test.cpp @@ -7,8 +7,11 @@ // Tests that malformed shaders fail compilation, and that correct shaders pass compilation. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" #include "gtest/gtest.h" #include "tests/test_utils/ShaderCompileTreeTest.h" @@ -22,6 +25,8 @@ class FragmentShaderValidationTest : public ShaderCompileTreeTest FragmentShaderValidationTest() {} protected: + void initResources(ShBuiltInResources *resources) override { resources->MaxDrawBuffers = 8; } + ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } }; @@ -120,2306 +125,6 @@ class FragmentShaderEXTGeometryShaderValidationTest : public FragmentShaderValid } }; -// This is a test for a bug that used to exist in ANGLE: -// Calling a function with all parameters missing should not succeed. -TEST_F(FragmentShaderValidationTest, FunctionParameterMismatch) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float fun(float a) {\n" - " return a * 2.0;\n" - "}\n" - "void main() {\n" - " float ff = fun();\n" - " gl_FragColor = vec4(ff);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Functions can't be redeclared as variables in the same scope (ESSL 1.00 section 4.2.7) -TEST_F(FragmentShaderValidationTest, RedeclaringFunctionAsVariable) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float fun(float a) {\n" - " return a * 2.0;\n" - "}\n" - "float fun;\n" - "void main() {\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Functions can't be redeclared as structs in the same scope (ESSL 1.00 section 4.2.7) -TEST_F(FragmentShaderValidationTest, RedeclaringFunctionAsStruct) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float fun(float a) {\n" - " return a * 2.0;\n" - "}\n" - "struct fun { float a; };\n" - "void main() {\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Functions can't be redeclared with different qualifiers (ESSL 1.00 section 6.1.0) -TEST_F(FragmentShaderValidationTest, RedeclaringFunctionWithDifferentQualifiers) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float fun(out float a);\n" - "float fun(float a) {\n" - " return a * 2.0;\n" - "}\n" - "void main() {\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7) -TEST_F(FragmentShaderValidationTest, CompareStructsContainingArrays) -{ - const std::string &shaderString = - "precision mediump float;\n" - "struct s { float a[3]; };\n" - "void main() {\n" - " s a;\n" - " s b;\n" - " bool c = (a == b);\n" - " gl_FragColor = vec4(c ? 1.0 : 0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7) -TEST_F(FragmentShaderValidationTest, AssignStructsContainingArrays) -{ - const std::string &shaderString = - "precision mediump float;\n" - "struct s { float a[3]; };\n" - "void main() {\n" - " s a;\n" - " s b;\n" - " b.a[0] = 0.0;\n" - " a = b;\n" - " gl_FragColor = vec4(a.a[0]);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7 -// and 5.9) -TEST_F(FragmentShaderValidationTest, CompareStructsContainingSamplers) -{ - const std::string &shaderString = - "precision mediump float;\n" - "struct s { sampler2D foo; };\n" - "uniform s a;\n" - "uniform s b;\n" - "void main() {\n" - " bool c = (a == b);\n" - " gl_FragColor = vec4(c ? 1.0 : 0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this -// extends to structs containing samplers. ESSL 1.00 spec is clearer about this. -TEST_F(FragmentShaderValidationTest, AssignStructsContainingSamplers) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "struct s { sampler2D foo; };\n" - "uniform s a;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " s b;\n" - " b = a;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// This is a regression test for a particular bug that was in ANGLE. -// It also verifies that ESSL3 functionality doesn't leak to ESSL1. -TEST_F(FragmentShaderValidationTest, ArrayWithNoSizeInInitializerList) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main() {\n" - " float a[2], b[];\n" - " gl_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Const variables need an initializer. -TEST_F(FragmentShaderValidationTest, ConstVarNotInitialized) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " const float a;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Const variables need an initializer. In ESSL1 const structs containing -// arrays are not allowed at all since it's impossible to initialize them. -// Even though this test is for ESSL3 the only thing that's critical for -// ESSL1 is the non-initialization check that's used for both language versions. -// Whether ESSL1 compilation generates the most helpful error messages is a -// secondary concern. -TEST_F(FragmentShaderValidationTest, ConstStructNotInitialized) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "struct S {\n" - " float a[3];\n" - "};\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " const S b;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Const variables need an initializer. In ESSL1 const arrays are not allowed -// at all since it's impossible to initialize them. -// Even though this test is for ESSL3 the only thing that's critical for -// ESSL1 is the non-initialization check that's used for both language versions. -// Whether ESSL1 compilation generates the most helpful error messages is a -// secondary concern. -TEST_F(FragmentShaderValidationTest, ConstArrayNotInitialized) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " const float a[3];\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3) -TEST_F(FragmentShaderValidationTest, BlockLayoutQualifierOnRegularUniform) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "layout(packed) uniform mat2 x;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3) -TEST_F(FragmentShaderValidationTest, BlockLayoutQualifierOnUniformWithEmptyDecl) -{ - // Yes, the comma in the declaration below is not a typo. - // Empty declarations are allowed in GLSL. - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "layout(packed) uniform mat2, x;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9) -TEST_F(FragmentShaderValidationTest, ArraysOfArrays1) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " float[5] a[3];\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9) -TEST_F(FragmentShaderValidationTest, ArraysOfArrays2) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " float[2] a, b[3];\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9). Test this in a struct. -TEST_F(FragmentShaderValidationTest, ArraysOfArraysInStruct) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "struct S {\n" - " float[2] foo[3];\n" - "};\n" - "void main() {\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test invalid dimensionality of implicitly sized array constructor arguments. -TEST_F(FragmentShaderValidationTest, - TooHighDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments) -{ - const std::string &shaderString = - "#version 310 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " float[][] a = float[][](float[1][1](float[1](1.0)), float[1][1](float[1](2.0)));\n" - " my_FragColor = vec4(a[0][0]);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test invalid dimensionality of implicitly sized array constructor arguments. -TEST_F(FragmentShaderValidationTest, - TooLowDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments) -{ - const std::string &shaderString = - "#version 310 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " float[][][] a = float[][][](float[2](1.0, 2.0), float[2](3.0, 4.0));\n" - " my_FragColor = vec4(a[0][0][0]);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Implicitly sized arrays need to be initialized (ESSL 3.00 section 4.1.9) -TEST_F(FragmentShaderValidationTest, UninitializedImplicitArraySize) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " float[] a;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// An operator can only form a constant expression if all the operands are constant expressions -// - even operands of ternary operator that are never evaluated. (ESSL 3.00 section 4.3.3) -TEST_F(FragmentShaderValidationTest, TernaryOperatorNotConstantExpression) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform bool u;\n" - "void main() {\n" - " const bool a = true ? true : u;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Ternary operator can operate on arrays (ESSL 3.00 section 5.7) -TEST_F(FragmentShaderValidationTest, TernaryOperatorOnArrays) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " float[1] a = float[1](0.0);\n" - " float[1] b = float[1](1.0);\n" - " float[1] c = true ? a : b;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Ternary operator can operate on structs (ESSL 3.00 section 5.7) -TEST_F(FragmentShaderValidationTest, TernaryOperatorOnStructs) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "struct S { float foo; };\n" - "void main() {\n" - " S a = S(0.0);\n" - " S b = S(1.0);\n" - " S c = true ? a : b;\n" - " my_FragColor = vec4(1.0);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Array length() returns a constant signed integral expression (ESSL 3.00 section 4.1.9) -// Assigning it to unsigned should result in an error. -TEST_F(FragmentShaderValidationTest, AssignArrayLengthToUnsigned) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " int[1] arr;\n" - " uint l = arr.length();\n" - " my_FragColor = vec4(float(l));\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with a varying should be an error. -TEST_F(FragmentShaderValidationTest, AssignVaryingToGlobal) -{ - const std::string &shaderString = - "precision mediump float;\n" - "varying float a;\n" - "float b = a * 2.0;\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) -// Initializing with an uniform should be an error. -TEST_F(FragmentShaderValidationTest, AssignUniformToGlobalESSL3) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform float a;\n" - "float b = a * 2.0;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with an uniform used to generate a warning on ESSL 1.00 because of legacy -// compatibility, but that causes dEQP to fail (which expects an error) -TEST_F(FragmentShaderValidationTest, AssignUniformToGlobalESSL1) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float a;\n" - "float b = a * 2.0;\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with an user-defined function call should be an error. -TEST_F(FragmentShaderValidationTest, AssignFunctionCallToGlobal) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float foo() { return 1.0; }\n" - "float b = foo();\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with an assignment to another global should be an error. -TEST_F(FragmentShaderValidationTest, AssignAssignmentToGlobal) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float c = 1.0;\n" - "float b = (c = 0.0);\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with incrementing another global should be an error. -TEST_F(FragmentShaderValidationTest, AssignIncrementToGlobal) -{ - const std::string &shaderString = - "precision mediump float;\n" - "float c = 1.0;\n" - "float b = (c++);\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with a texture lookup function call should be an error. -TEST_F(FragmentShaderValidationTest, AssignTexture2DToGlobal) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform mediump sampler2D s;\n" - "float b = texture2D(s, vec2(0.5, 0.5)).x;\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) -// Initializing with a non-constant global should be an error. -TEST_F(FragmentShaderValidationTest, AssignNonConstGlobalToGlobal) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "float a = 1.0;\n" - "float b = a * 2.0;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) -// Initializing with a constant global should be fine. -TEST_F(FragmentShaderValidationTest, AssignConstGlobalToGlobal) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "const float a = 1.0;\n" - "float b = a * 2.0;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(b);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Statically assigning to both gl_FragData and gl_FragColor is forbidden (ESSL 1.00 section 7.2) -TEST_F(FragmentShaderValidationTest, WriteBothFragDataAndFragColor) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void foo() {\n" - " gl_FragData[0].a++;\n" - "}\n" - "void main() {\n" - " gl_FragColor.x += 0.0;\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Version directive must be on the first line (ESSL 3.00 section 3.3) -TEST_F(FragmentShaderValidationTest, VersionOnSecondLine) -{ - const std::string &shaderString = - "\n" - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Layout qualifier can only appear in global scope (ESSL 3.00 section 4.3.8) -TEST_F(FragmentShaderValidationTest, LayoutQualifierInCondition) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform vec4 u;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " int i = 0;\n" - " for (int j = 0; layout(location = 0) bool b = false; ++j) {\n" - " ++i;\n" - " }\n" - " my_FragColor = u;\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Layout qualifier can only appear where specified (ESSL 3.00 section 4.3.8) -TEST_F(FragmentShaderValidationTest, LayoutQualifierInFunctionReturnType) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform vec4 u;\n" - "out vec4 my_FragColor;\n" - "layout(location = 0) vec4 foo() {\n" - " return u;\n" - "}\n" - "void main() {\n" - " my_FragColor = foo();\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// If there is more than one output, the location must be specified for all outputs. -// (ESSL 3.00.04 section 4.3.8.2) -TEST_F(FragmentShaderValidationTest, TwoOutputsNoLayoutQualifiers) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform vec4 u;\n" - "out vec4 my_FragColor;\n" - "out vec4 my_SecondaryFragColor;\n" - "void main() {\n" - " my_FragColor = vec4(1.0);\n" - " my_SecondaryFragColor = vec4(0.5);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// (ESSL 3.00.04 section 4.3.8.2) -TEST_F(FragmentShaderValidationTest, TwoOutputsFirstLayoutQualifier) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform vec4 u;\n" - "layout(location = 0) out vec4 my_FragColor;\n" - "out vec4 my_SecondaryFragColor;\n" - "void main() {\n" - " my_FragColor = vec4(1.0);\n" - " my_SecondaryFragColor = vec4(0.5);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// (ESSL 3.00.04 section 4.3.8.2) -TEST_F(FragmentShaderValidationTest, TwoOutputsSecondLayoutQualifier) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform vec4 u;\n" - "out vec4 my_FragColor;\n" - "layout(location = 0) out vec4 my_SecondaryFragColor;\n" - "void main() {\n" - " my_FragColor = vec4(1.0);\n" - " my_SecondaryFragColor = vec4(0.5);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Uniforms can be arrays (ESSL 3.00 section 4.3.5) -TEST_F(FragmentShaderValidationTest, UniformArray) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform vec4[2] u;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = u[0];\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Fragment shader input variables cannot be arrays of structs (ESSL 3.00 section 4.3.4) -TEST_F(FragmentShaderValidationTest, FragmentInputArrayOfStructs) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "struct S {\n" - " vec4 foo;\n" - "};\n" - "in S i[2];\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = i[0].foo;\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4) -// This test is testing the case where the array brackets are after the variable name, so -// the arrayness isn't known when the type and qualifiers are initially parsed. -TEST_F(VertexShaderValidationTest, VertexShaderInputArray) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "in vec4 i[2];\n" - "void main() {\n" - " gl_Position = i[0];\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4) -// This test is testing the case where the array brackets are after the type. -TEST_F(VertexShaderValidationTest, VertexShaderInputArrayType) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "in vec4[2] i;\n" - "void main() {\n" - " gl_Position = i[0];\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Fragment shader inputs can't contain booleans (ESSL 3.00 section 4.3.4) -TEST_F(FragmentShaderValidationTest, FragmentShaderInputStructWithBool) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "struct S {\n" - " bool foo;\n" - "};\n" - "in S s;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Fragment shader inputs without a flat qualifier can't contain integers (ESSL 3.00 section 4.3.4) -TEST_F(FragmentShaderValidationTest, FragmentShaderInputStructWithInt) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "struct S {\n" - " int foo;\n" - "};\n" - "in S s;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Selecting a field of a vector that's the result of dynamic indexing a constant array should work. -TEST_F(FragmentShaderValidationTest, ShaderSelectingFieldOfVectorIndexedFromArray) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform int i;\n" - "void main() {\n" - " float f = vec2[1](vec2(0.0, 0.1))[i].x;\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Passing an array into a function and then passing a value from that array into another function -// should work. This is a regression test for a bug where the mangled name of a TType was not -// properly updated when determining the type resulting from array indexing. -TEST_F(FragmentShaderValidationTest, ArrayValueFromFunctionParameterAsParameter) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float u;\n" - "float foo(float f) {\n" - " return f * 2.0;\n" - "}\n" - "float bar(float[2] f) {\n" - " return foo(f[0]);\n" - "}\n" - "void main()\n" - "{\n" - " float arr[2];\n" - " arr[0] = u;\n" - " gl_FragColor = vec4(bar(arr));\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that out-of-range integer literal generates an error in ESSL 3.00. -TEST_F(FragmentShaderValidationTest, OutOfRangeIntegerLiteral) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision highp int;\n" - "out vec4 my_FragColor;\n" - "void main() {\n" - " my_FragColor = vec4(0x100000000);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that vector field selection from a value taken from an array constructor is accepted as a -// constant expression. -TEST_F(FragmentShaderValidationTest, FieldSelectionFromVectorArrayConstructorIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const float f = vec2[1](vec2(0.0, 1.0))[0].x;\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that structure field selection from a value taken from an array constructor is accepted as a -// constant expression. -TEST_F(FragmentShaderValidationTest, FieldSelectionFromStructArrayConstructorIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "struct S { float member; };\n" - "void main()\n" - "{\n" - " const float f = S[1](S(0.0))[0].member;\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that a reference to a const array is accepted as a constant expression. -TEST_F(FragmentShaderValidationTest, ArraySymbolIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const float[2] arr = float[2](0.0, 1.0);\n" - " const float f = arr[0];\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that using an array constructor in a parameter to a built-in function is accepted as a -// constant expression. -TEST_F(FragmentShaderValidationTest, BuiltInFunctionAppliedToArrayConstructorIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const float f = sin(float[2](0.0, 1.0)[0]);\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that using an array constructor in a parameter to a built-in function is accepted as a -// constant expression. -TEST_F(FragmentShaderValidationTest, - BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const float f = pow(1.0, float[2](0.0, 1.0)[0]);\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that using an array constructor in a parameter to a constructor is accepted as a constant -// expression. -TEST_F(FragmentShaderValidationTest, - ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const vec2 f = vec2(1.0, float[2](0.0, 1.0)[0]);\n" - " my_FragColor = vec4(f.x);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that using an array constructor in an operand of the ternary selection operator is accepted -// as a constant expression. -TEST_F(FragmentShaderValidationTest, TernaryOperatorAppliedToArrayConstructorIsConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " const float f = true ? float[2](0.0, 1.0)[0] : 1.0;\n" - " my_FragColor = vec4(f);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that a ternary operator with one unevaluated non-constant operand is not a constant -// expression. -TEST_F(FragmentShaderValidationTest, TernaryOperatorNonConstantOperand) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float u;\n" - "void main()\n" - "{\n" - " const float f = true ? 1.0 : u;\n" - " gl_FragColor = vec4(f);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that a sampler can't be used in constructor argument list -TEST_F(FragmentShaderValidationTest, SamplerInConstructorArguments) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform sampler2D s;\n" - "void main()\n" - "{\n" - " vec2 v = vec2(0.0, s);\n" - " gl_FragColor = vec4(v, 0.0, 0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that void can't be used in constructor argument list -TEST_F(FragmentShaderValidationTest, VoidInConstructorArguments) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void foo() {}\n" - "void main()\n" - "{\n" - " vec2 v = vec2(0.0, foo());\n" - " gl_FragColor = vec4(v, 0.0, 0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that a shader passing a struct into a constructor of array of structs with 1 element works. -TEST_F(FragmentShaderValidationTest, SingleStructArrayConstructor) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform float u;\n" - "struct S { float member; };\n" - "void main()\n" - "{\n" - " S[1] sarr = S[1](S(u));\n" - " my_FragColor = vec4(sarr[0].member);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that a shader with empty constructor parameter list is not accepted. -TEST_F(FragmentShaderValidationTest, EmptyArrayConstructor) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform float u;\n" - "const float[] f = f[]();\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing fragment outputs with a non-constant expression is forbidden, even if ANGLE -// is able to constant fold the index expression. ESSL 3.00 section 4.3.6. -TEST_F(FragmentShaderValidationTest, DynamicallyIndexedFragmentOutput) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform int a;\n" - "out vec4[2] my_FragData;\n" - "void main()\n" - "{\n" - " my_FragData[true ? 0 : a] = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing a uniform buffer array with a non-constant expression is forbidden, even if -// ANGLE is able to constant fold the index expression. ESSL 3.00 section 4.3.7. -TEST_F(FragmentShaderValidationTest, DynamicallyIndexedUniformBuffer) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - uniform int a; - uniform B - { - vec4 f; - } - blocks[2]; - out vec4 my_FragColor; - void main() - { - my_FragColor = blocks[true ? 0 : a].f; - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing a storage buffer array with a non-constant expression is forbidden, even if -// ANGLE is able to constant fold the index expression. ESSL 3.10 section 4.3.9. -TEST_F(FragmentShaderValidationTest, DynamicallyIndexedStorageBuffer) -{ - const std::string &shaderString = - R"(#version 310 es - precision mediump float; - uniform int a; - layout(std140) buffer B - { - vec4 f; - } - blocks[2]; - out vec4 my_FragColor; - void main() - { - my_FragColor = blocks[true ? 0 : a].f; - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing a sampler array with a non-constant expression is forbidden, even if ANGLE is -// able to constant fold the index expression. ESSL 3.00 section 4.1.7.1. -TEST_F(FragmentShaderValidationTest, DynamicallyIndexedSampler) -{ - const std::string &shaderString = - R"(#version 300 es - precision mediump float; - uniform int a; - uniform sampler2D s[2]; - out vec4 my_FragColor; - void main() - { - my_FragColor = texture(s[true ? 0 : a], vec2(0)); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing an image array with a non-constant expression is forbidden, even if ANGLE is -// able to constant fold the index expression. ESSL 3.10 section 4.1.7.2. -TEST_F(FragmentShaderValidationTest, DynamicallyIndexedImage) -{ - const std::string &shaderString = - R"(#version 310 es - precision mediump float; - uniform int a; - layout(rgba32f) uniform highp readonly image2D image[2]; - out vec4 my_FragColor; - void main() - { - my_FragColor = imageLoad(image[true ? 0 : a], ivec2(0)); - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that a shader that uses a struct definition in place of a struct constructor does not -// compile. See GLSL ES 1.00 section 5.4.3. -TEST_F(FragmentShaderValidationTest, StructConstructorWithStructDefinition) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main()\n" - "{\n" - " struct s { float f; } (0.0);\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that indexing gl_FragData with a non-constant expression is forbidden in WebGL 2.0, even -// when ANGLE is able to constant fold the index. -// WebGL 2.0 spec section 'GLSL ES 1.00 Fragment Shader Output' -TEST_F(WebGL2FragmentShaderValidationTest, IndexFragDataWithNonConstant) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main()\n" - "{\n" - " for (int i = 0; i < 2; ++i) {\n" - " gl_FragData[true ? 0 : i] = vec4(0.0);\n" - " }\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with an uniform should generate a warning -// (we don't generate an error on ESSL 1.00 because of WebGL compatibility) -TEST_F(WebGL2FragmentShaderValidationTest, AssignUniformToGlobalESSL1) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float a;\n" - "float b = a * 2.0;\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - if (!hasWarning()) - { - FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n" - << mInfoLog; - } - } - else - { - FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog; - } -} - -// Test that deferring global variable init works with an empty main(). -TEST_F(WebGL2FragmentShaderValidationTest, DeferGlobalVariableInitWithEmptyMain) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float u;\n" - "float foo = u;\n" - "void main() {}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that a non-constant texture offset is not accepted for textureOffset. -// ESSL 3.00 section 8.8 -TEST_F(FragmentShaderValidationTest, TextureOffsetNonConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform vec3 u_texCoord;\n" - "uniform mediump sampler3D u_sampler;\n" - "uniform int x;\n" - "void main()\n" - "{\n" - " my_FragColor = textureOffset(u_sampler, u_texCoord, ivec3(x, 3, -8));\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that a non-constant texture offset is not accepted for textureProjOffset with bias. -// ESSL 3.00 section 8.8 -TEST_F(FragmentShaderValidationTest, TextureProjOffsetNonConst) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform vec4 u_texCoord;\n" - "uniform mediump sampler3D u_sampler;\n" - "uniform int x;\n" - "void main()\n" - "{\n" - " my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec3(x, 3, -8), 0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that an out-of-range texture offset is not accepted. -// GLES 3.0.4 section 3.8.10 specifies that out-of-range offset has undefined behavior. -TEST_F(FragmentShaderValidationTest, TextureLodOffsetOutOfRange) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform vec3 u_texCoord;\n" - "uniform mediump sampler3D u_sampler;\n" - "void main()\n" - "{\n" - " my_FragColor = textureLodOffset(u_sampler, u_texCoord, 0.0, ivec3(0, 0, 8));\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that default precision qualifier for uint is not accepted. -// ESSL 3.00.4 section 4.5.4: Only allowed for float, int and sampler types. -TEST_F(FragmentShaderValidationTest, DefaultPrecisionUint) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "precision mediump uint;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that sampler3D needs to be precision qualified. -// ESSL 3.00.4 section 4.5.4: New ESSL 3.00 sampler types don't have predefined precision. -TEST_F(FragmentShaderValidationTest, NoPrecisionSampler3D) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "uniform sampler3D s;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Test that using a non-constant expression in a for loop initializer is forbidden in WebGL 1.0, -// even when ANGLE is able to constant fold the initializer. -// ESSL 1.00 Appendix A. -TEST_F(WebGL1FragmentShaderValidationTest, NonConstantLoopIndex) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform int u;\n" - "void main()\n" - "{\n" - " for (int i = (true ? 1 : u); i < 5; ++i) {\n" - " gl_FragColor = vec4(0.0);\n" - " }\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) -// Initializing with an uniform should generate a warning -// (we don't generate an error on ESSL 1.00 because of WebGL compatibility) -TEST_F(WebGL1FragmentShaderValidationTest, AssignUniformToGlobalESSL1) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float a;\n" - "float b = a * 2.0;\n" - "void main() {\n" - " gl_FragColor = vec4(b);\n" - "}\n"; - if (compile(shaderString)) - { - if (!hasWarning()) - { - FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n" - << mInfoLog; - } - } - else - { - FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog; - } -} - -// Test that deferring global variable init works with an empty main(). -TEST_F(WebGL1FragmentShaderValidationTest, DeferGlobalVariableInitWithEmptyMain) -{ - const std::string &shaderString = - "precision mediump float;\n" - "uniform float u;\n" - "float foo = u;\n" - "void main() {}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Check that indices that are not integers are rejected. -// The check should be done even if ESSL 1.00 Appendix A limitations are not applied. -TEST_F(FragmentShaderValidationTest, NonIntegerIndex) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void main()\n" - "{\n" - " float f[3];\n" - " const float i = 2.0;\n" - " gl_FragColor = vec4(f[i]);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// ESSL1 shaders with a duplicate function prototype should be rejected. -// ESSL 1.00.17 section 4.2.7. -TEST_F(FragmentShaderValidationTest, DuplicatePrototypeESSL1) -{ - const std::string &shaderString = - "precision mediump float;\n" - "void foo();\n" - "void foo();\n" - "void foo() {}\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// ESSL3 shaders with a duplicate function prototype should be allowed. -// ESSL 3.00.4 section 4.2.3. -TEST_F(FragmentShaderValidationTest, DuplicatePrototypeESSL3) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void foo();\n" - "void foo();\n" - "void foo() {}\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Shaders with a local function prototype should be rejected. -// ESSL 3.00.4 section 4.2.4. -TEST_F(FragmentShaderValidationTest, LocalFunctionPrototype) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " void foo();\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// ESSL 3.00 fragment shaders can not use #pragma STDGL invariant(all). -// ESSL 3.00.4 section 4.6.1. Does not apply to other versions of ESSL. -TEST_F(FragmentShaderValidationTest, ESSL300FragmentInvariantAll) -{ - const std::string &shaderString = - "#version 300 es\n" - "#pragma STDGL invariant(all)\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Built-in functions can be overloaded in ESSL 1.00. -TEST_F(FragmentShaderValidationTest, ESSL100BuiltInFunctionOverload) -{ - const std::string &shaderString = - "precision mediump float;\n" - "int sin(int x)\n" - "{\n" - " return int(sin(float(x)));\n" - "}\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(sin(1));" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Built-in functions can not be overloaded in ESSL 3.00. -TEST_F(FragmentShaderValidationTest, ESSL300BuiltInFunctionOverload) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "int sin(int x)\n" - "{\n" - " return int(sin(float(x)));\n" - "}\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(sin(1));" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Multiplying a 4x2 matrix with a 4x2 matrix should not work. -TEST_F(FragmentShaderValidationTest, CompoundMultiplyMatrixIdenticalNonSquareDimensions) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " mat4x2 foo;\n" - " foo *= mat4x2(4.0);\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Multiplying a matrix with 2 columns and 4 rows with a 2x2 matrix should work. -TEST_F(FragmentShaderValidationTest, CompoundMultiplyMatrixValidNonSquareDimensions) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " mat2x4 foo;\n" - " foo *= mat2x2(4.0);\n" - " my_FragColor = vec4(0.0);\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Covers a bug where we would set the incorrect result size on an out-of-bounds vector swizzle. -TEST_F(FragmentShaderValidationTest, OutOfBoundsVectorSwizzle) -{ - const std::string &shaderString = - "void main() {\n" - " vec2(0).qq;\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Covers a bug where strange preprocessor defines could trigger asserts. -TEST_F(FragmentShaderValidationTest, DefineWithSemicolon) -{ - const std::string &shaderString = - "#define Def; highp\n" - "uniform Def vec2 a;\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Covers a bug in our parsing of malformed shift preprocessor expressions. -TEST_F(FragmentShaderValidationTest, LineDirectiveUndefinedShift) -{ - const std::string &shaderString = "#line x << y"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Covers a bug in our parsing of malformed shift preprocessor expressions. -TEST_F(FragmentShaderValidationTest, LineDirectiveNegativeShift) -{ - const std::string &shaderString = "#line x << -1"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// gl_MaxImageUnits is only available in ES 3.1 shaders. -TEST_F(FragmentShaderValidationTest, MaxImageUnitsInES3Shader) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 myOutput;" - "void main() {\n" - " float ff = float(gl_MaxImageUnits);\n" - " myOutput = vec4(ff);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// struct += struct is an invalid operation. -TEST_F(FragmentShaderValidationTest, StructCompoundAssignStruct) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 myOutput;\n" - "struct S { float foo; };\n" - "void main() {\n" - " S a, b;\n" - " a += b;\n" - " myOutput = vec4(0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// struct == different struct is an invalid operation. -TEST_F(FragmentShaderValidationTest, StructEqDifferentStruct) -{ - const std::string &shaderString = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 myOutput;\n" - "struct S { float foo; };\n" - "struct S2 { float foobar; };\n" - "void main() {\n" - " S a;\n" - " S2 b;\n" - " a == b;\n" - " myOutput = vec4(0);\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Compute shaders are not supported in versions lower than 310. -TEST_F(ComputeShaderValidationTest, Version100) -{ - const std::string &shaderString = - R"(void main() - { - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Compute shaders are not supported in versions lower than 310. -TEST_F(ComputeShaderValidationTest, Version300) -{ - const std::string &shaderString = - R"(#version 300 es - void main() - { - })"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Compute shaders should have work group size specified. However, it is not a compile time error -// to not have the size specified, but rather a link time one. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, NoWorkGroupSizeSpecified) -{ - const std::string &shaderString = - "#version 310 es\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Test that workgroup size declaration doesn't accept variable declaration. -TEST_F(ComputeShaderValidationTest, NoVariableDeclrationAfterWorkGroupSize) -{ - constexpr char kShaderString[] = - R"(#version 310 es - layout(local_size_x = 1) in vec4 x; - void main() - { - })"; - if (compile(kShaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size is less than 1. It should be at least 1. -// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables -// The spec is not clear whether having a local size qualifier equal zero -// is correct. -// TODO (mradev): Ask people from Khronos to clarify the spec. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooSmallXdimension) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 0) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size is correct for the x and y dimensions, but not for the z dimension. -// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables -TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooSmallZDimension) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 4, local_size_y = 6, local_size_z = 0) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size is bigger than the minimum in the x dimension. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigXDimension) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 9989899) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size is bigger than the minimum in the y dimension. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigYDimension) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, local_size_y = 9989899) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size is definitely bigger than the minimum in the z dimension. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigZDimension) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, local_size_y = 5, local_size_z = 9989899) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size specified through macro expansion. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeMacro) -{ - const std::string &shaderString = - "#version 310 es\n" - "#define MYDEF(x) x" - "layout(local_size_x = MYDEF(127)) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Work group size specified as an unsigned integer. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeUnsignedInteger) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 123u) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Work group size specified in hexadecimal. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeHexadecimal) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 0x3A) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// local_size_x is -1 in hexadecimal format. -// -1 is used as unspecified value in the TLayoutQualifier structure. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeMinusOneHexadecimal) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 0xFFFFFFFF) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Work group size specified in octal. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeOctal) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 013) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Work group size is negative. It is specified in hexadecimal. -TEST_F(ComputeShaderValidationTest, WorkGroupSizeNegativeHexadecimal) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 0xFFFFFFEC) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Multiple work group layout qualifiers with differing values. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, DifferingLayoutQualifiers) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, local_size_x = 6) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Multiple work group input variables with differing local size values. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, MultipleInputVariablesDifferingLocalSize) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, local_size_y = 6) in;\n" - "layout(local_size_x = 5, local_size_y = 7) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Multiple work group input variables with differing local size values. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, MultipleInputVariablesDifferingLocalSize2) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5) in;\n" - "layout(local_size_x = 5, local_size_y = 7) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Multiple work group input variables with the same local size values. It should compile. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, local_size_y = 6) in;\n" - "layout(local_size_x = 5, local_size_y = 6) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Multiple work group input variables with the same local size values. It should compile. -// Since the default value is 1, it should compile. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize2) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5) in;\n" - "layout(local_size_x = 5, local_size_y = 1) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Multiple work group input variables with the same local size values. It should compile. -// Since the default value is 1, it should compile. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize3) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, local_size_y = 1) in;\n" - "layout(local_size_x = 5) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (!compile(shaderString)) - { - FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; - } -} - -// Specifying row_major qualifier in a work group size layout. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, RowMajorInComputeInputLayout) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5, row_major) in;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// local size layout can be used only with compute input variables -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, UniformComputeInputLayout) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5) uniform;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// local size layout can be used only with compute input variables -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, UniformBufferComputeInputLayout) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5) uniform SomeBuffer { vec4 something; };\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// local size layout can be used only with compute input variables -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, StructComputeInputLayout) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5) struct SomeBuffer { vec4 something; };\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// local size layout can be used only with compute input variables -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, StructBodyComputeInputLayout) -{ - const std::string &shaderString = - "#version 310 es\n" - "struct S {\n" - " layout(local_size_x = 12) vec4 foo;\n" - "};\n" - "void main()" - "{" - "}"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// local size layout can be used only with compute input variables -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, TypeComputeInputLayout) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 5) vec4;\n" - "void main()\n" - "{\n" - "}\n"; - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Invalid use of the out storage qualifier in a compute shader. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, InvalidOutStorageQualifier) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 15) in;\n" - "out vec4 myOutput;\n" - "void main() {\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Invalid use of the out storage qualifier in a compute shader. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, InvalidOutStorageQualifier2) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 15) in;\n" - "out myOutput;\n" - "void main() {\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Invalid use of the in storage qualifier. Can be only used to describe the local block size. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, InvalidInStorageQualifier) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 15) in;\n" - "in vec4 myInput;\n" - "void main() {\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// Invalid use of the in storage qualifier. Can be only used to describe the local block size. -// The test checks a different part of the GLSL grammar than what InvalidInStorageQualifier checks. -// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs -TEST_F(ComputeShaderValidationTest, InvalidInStorageQualifier2) -{ - const std::string &shaderString = - "#version 310 es\n" - "layout(local_size_x = 15) in;\n" - "in myInput;\n" - "void main() {\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// The local_size layout qualifier is only available in compute shaders. -TEST_F(VertexShaderValidationTest, InvalidUseOfLocalSizeX) -{ - const std::string &shaderString = - "#version 310 es\n" - "precision mediump float;\n" - "layout(local_size_x = 15) in vec4 myInput;\n" - "out vec4 myOutput;\n" - "void main() {\n" - " myOutput = myInput;\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - -// The local_size layout qualifier is only available in compute shaders. -TEST_F(FragmentShaderValidationTest, InvalidUseOfLocalSizeX) -{ - const std::string &shaderString = - "#version 310 es\n" - "precision mediump float;\n" - "layout(local_size_x = 15) in vec4 myInput;\n" - "out vec4 myOutput;\n" - "void main() {\n" - " myOutput = myInput;\n" - "}\n"; - - if (compile(shaderString)) - { - FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; - } -} - // The local_size layout qualifier is only available in compute shaders. TEST_F(GeometryShaderValidationTest, InvalidUseOfLocalSizeX) { diff --git a/src/tests/compiler_tests/TypeTracking_test.cpp b/src/tests/compiler_tests/TypeTracking_test.cpp index f624a85e875..520a1376f5a 100644 --- a/src/tests/compiler_tests/TypeTracking_test.cpp +++ b/src/tests/compiler_tests/TypeTracking_test.cpp @@ -25,7 +25,6 @@ class TypeTrackingTest : public testing::Test { ShBuiltInResources resources; InitBuiltInResources(&resources); - resources.FragmentPrecisionHigh = 1; mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC); ASSERT_TRUE(mTranslator->Init(resources)); @@ -39,7 +38,7 @@ class TypeTrackingTest : public testing::Test compileOptions.intermediateTree = true; const char *shaderStrings[] = {shaderString.c_str()}; - bool compilationSuccess = mTranslator->compile(shaderStrings, 1, compileOptions); + bool compilationSuccess = mTranslator->compile(shaderStrings, compileOptions); TInfoSink &infoSink = mTranslator->getInfoSink(); mInfoLog = RemoveSymbolIdsFromInfoLog(infoSink.info.c_str()); if (!compilationSuccess) @@ -677,13 +676,14 @@ void main() } )"; const char kExpected[] = R"(0:2: Code block -0:3: Declaration -0:3: 'o' (out highp 4-component vector of float) 0:6: Declaration -0:? : '' (structure 's2' (specifier)) +0:?: '' (structure 's2' (specifier)) +0:?: member: 'i' (mediump int) 0:10: Declaration 0:10: initialize first child with second child (const structure 's1' (specifier)) 0:10: 's11' (const structure 's1' (specifier)) +0:10: member: 'ss' (structure 's2') +0:10: member: 'm' (highp 4X4 matrix of float) 0:10: Construct (const structure 's1') 0:10: Constant union (const structure 's2' (specifier)) 0:10: 8 (const int) @@ -704,6 +704,8 @@ void main() 0:10: 0.0 (const float) 0:10: 0.0 (const float) 0:10: 5.0 (const float) +0:3: Declaration +0:3: 'o' (out highp 4-component vector of float) 0:11: Function Definition: 0:11: Function Prototype: 'f' (structure 's1') 0:11: parameter: 's' (in structure 's1') @@ -718,8 +720,12 @@ void main() 0:17: Compare Equal (bool) 0:17: Call a function: 'f' (structure 's1') 0:17: 's11' (const structure 's1' (specifier)) +0:17: member: 'ss' (structure 's2') +0:17: member: 'm' (highp 4X4 matrix of float) 0:17: Call a function: 'f' (structure 's1') 0:17: 's11' (const structure 's1' (specifier)) +0:17: member: 'ss' (structure 's2') +0:17: member: 'm' (highp 4X4 matrix of float) 0:17: true case 0:18: Code block 0:18: move second child to first child (highp 4-component vector of float) @@ -761,13 +767,17 @@ void main() 0:8: Declaration 0:8: initialize first child with second child (structure 's2' (specifier)) 0:8: 's22' (structure 's2' (specifier)) +0:8: member: 'i' (mediump int) 0:8: Constant union (const structure 's2') 0:8: 8 (const int) 0:12: Declaration 0:12: initialize first child with second child (structure 's1' (specifier)) 0:12: 's11' (structure 's1' (specifier)) +0:12: member: 'ss' (structure 's2') +0:12: member: 'm' (highp 4X4 matrix of float) 0:12: Construct (structure 's1') 0:12: 's22' (structure 's2' (specifier)) +0:12: member: 'i' (mediump int) 0:12: Constant union (const 4X4 matrix of float) 0:12: 5.0 (const float) 0:12: 0.0 (const float) @@ -787,12 +797,20 @@ void main() 0:12: 5.0 (const float) 0:13: move second child to first child (structure 's1' (specifier)) 0:13: 's11' (structure 's1' (specifier)) +0:13: member: 'ss' (structure 's2') +0:13: member: 'm' (highp 4X4 matrix of float) 0:13: 's11' (structure 's1' (specifier)) +0:13: member: 'ss' (structure 's2') +0:13: member: 'm' (highp 4X4 matrix of float) 0:14: If test 0:14: Condition 0:14: Compare Equal (bool) 0:14: 's11' (structure 's1' (specifier)) +0:14: member: 'ss' (structure 's2') +0:14: member: 'm' (highp 4X4 matrix of float) 0:14: 's11' (structure 's1' (specifier)) +0:14: member: 'ss' (structure 's2') +0:14: member: 'm' (highp 4X4 matrix of float) 0:14: true case 0:15: Code block 0:15: move second child to first child (highp 4-component vector of float) diff --git a/src/tests/compiler_tests/Type_test.cpp b/src/tests/compiler_tests/Type_test.cpp index 565fb730d6e..1f1fd1c1755 100644 --- a/src/tests/compiler_tests/Type_test.cpp +++ b/src/tests/compiler_tests/Type_test.cpp @@ -7,6 +7,10 @@ // Tests for StaticType, TType and BasicType. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "angle_gl.h" #include "compiler/translator/PoolAlloc.h" #include "compiler/translator/StaticType.h" @@ -19,9 +23,7 @@ namespace sh // Verify that mangled name matches between a vector/matrix TType and a corresponding StaticType. TEST(Type, VectorAndMatrixMangledNameConsistent) { - angle::PoolAllocator allocator; - allocator.push(); - SetGlobalPoolAllocator(&allocator); + TScopedPoolAllocator allocator; const TType *staticTypeScalar = StaticType::Get(); const TType *staticTypeVec2 = StaticType::Get(); @@ -35,9 +37,6 @@ TEST(Type, VectorAndMatrixMangledNameConsistent) std::string(typeVec2->getMangledName())); EXPECT_EQ(std::string(staticTypeMat2x4->getMangledName()), std::string(typeMat2x4->getMangledName())); - - SetGlobalPoolAllocator(nullptr); - allocator.pop(); } // Verify that basic type mangled names are unique. diff --git a/src/tests/compiler_tests/UnrollFlatten_test.cpp b/src/tests/compiler_tests/UnrollFlatten_test.cpp index 49e9e7511a0..ba2f27444ca 100644 --- a/src/tests/compiler_tests/UnrollFlatten_test.cpp +++ b/src/tests/compiler_tests/UnrollFlatten_test.cpp @@ -8,6 +8,10 @@ // This test can only be enabled when HLSL support is enabled. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLSLANG/ShaderLang.h" #include "angle_gl.h" #include "common/angleutils.h" diff --git a/src/tests/compiler_tests/VariablePacker_test.cpp b/src/tests/compiler_tests/VariablePacker_test.cpp index eabd93bb15f..d4caee91870 100644 --- a/src/tests/compiler_tests/VariablePacker_test.cpp +++ b/src/tests/compiler_tests/VariablePacker_test.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "gtest/gtest.h" #include "angle_gl.h" diff --git a/src/tests/compiler_tests/WGSLOutput_test.cpp b/src/tests/compiler_tests/WGSLOutput_test.cpp index 824c7ec5336..4669c1ca5fb 100644 --- a/src/tests/compiler_tests/WGSLOutput_test.cpp +++ b/src/tests/compiler_tests/WGSLOutput_test.cpp @@ -4,9 +4,8 @@ // found in the LICENSE file. // // WGSLOutput_test.cpp: -// Tests for corect WGSL translations. +// Tests for correct WGSL translations. // - #include #include "GLSLANG/ShaderLang.h" @@ -35,6 +34,8 @@ class WGSLOutputTest : public MatchOutputCodeTest ShCompileOptions defaultCompileOptions = {}; defaultCompileOptions.validateAST = true; setDefaultCompileOptions(defaultCompileOptions); + + getResources()->MaxDrawBuffers = 2; } }; @@ -57,7 +58,6 @@ TEST_F(WGSLOutputTest, BasicTranslation) vec4 doFoo(Foo foo, float zw) { - // foo.x = foo.y; return vec4(foo.x, foo.y, zw, zw); } @@ -100,23 +100,34 @@ TEST_F(WGSLOutputTest, BasicTranslation) doFoo(returnFoo(foo), returnFloat(3.0)); takeArgs(vec2(1.0, 2.0), foo.x); returnFloat(doFoo(foo, 7.0 + 9.0).x); - outColor = vec4(0.0, 0.0, 0.0, 0.0); + + vec3 comp1 = vec3(0.0, 0.0, 0.0); + float f3 = float(comp1 == foo.multiArray[0][0]); + + outColor = vec4(f3, 0.0, 0.0, 0.0); })"; const std::string &outputString = - R"(struct ANGLE_Output_Global { - outColor : vec4, + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _uoutColor : vec4, gl_FragDepth_ : f32, }; var ANGLE_output_global : ANGLE_Output_Global; struct ANGLE_Output_Annotated { - @location(@@@@@@) outColor : vec4, + @location(@@@@@@) _uoutColor : vec4, @builtin(frag_depth) gl_FragDepth_ : f32, }; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; -; +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; struct _uFoo { @@ -126,7 +137,20 @@ struct _uFoo _uaMatrix : mat3x3, }; -fn _udoFoo(_ufoo : _uFoo, _uzw : f32) -> vec4; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; +; fn _udoFoo(_ufoo : _uFoo, _uzw : f32) -> vec4 { @@ -161,14 +185,16 @@ fn _umain() _udoFoo(_ureturnFoo(_ufoo), _ureturnFloat(3.0f)); _utakeArgs(vec2(1.0f, 2.0f), (_ufoo)._ux); _ureturnFloat((_udoFoo(_ufoo, 16.0f)).x); - (ANGLE_output_global.outColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + var _ucomp1 : vec3 = (vec3(0.0f, 0.0f, 0.0f)); + var _uf3 : f32 = (f32(all((_ucomp1) == ((((_ufoo)._umultiArray)[0i])[0i])))); + (ANGLE_output_global._uoutColor) = (vec4(_uf3, 0.0f, 0.0f, 0.0f)); } @fragment fn wgslMain() -> ANGLE_Output_Annotated { _umain(); var ANGLE_output_annotated : ANGLE_Output_Annotated; - ANGLE_output_annotated.outColor = ANGLE_output_global.outColor; + ANGLE_output_annotated._uoutColor = ANGLE_output_global._uoutColor; ANGLE_output_annotated.gl_FragDepth_ = ANGLE_output_global.gl_FragDepth_; return ANGLE_output_annotated; } @@ -177,202 +203,2365 @@ fn wgslMain() -> ANGLE_Output_Annotated EXPECT_TRUE(foundInCode(outputString.c_str())); } -TEST_F(WGSLOutputTest, ControlFlow) +TEST_F(WGSLOutputTest, OverloadedFunctions) { const std::string &shaderString = - R"(#version 300 es + R"(#version 310 es precision highp float; - int ifElseDemo() { - int x = 5; - if (x == 5) { - return 6; - } else if (x == 6) { - return 7; - } else { - return 8; - } + out vec4 outColor; + + struct Foo { + float x; + float y; + vec3 multiArray[2][3]; + mat3 aMatrix; + }; + + vec4 doFoo(Foo foo) + { + return vec4(foo.x, foo.y, 0.0, 0.0); } - void switchDemo() { - int x = 5; - switch (x) { - case 5: - case 6: - discard; - case 7: { - return; - } - case 8: - case 9: - { - x = 7; - } - return; - default: - return; - } + vec4 doFoo(Foo foo, float zw) + { + return vec4(foo.x, foo.y, zw, zw); } - void forLoopDemo() { - for (int i = 0; i < 5; i++) { - if (i == 4) { - break; - } else if (i == 5) { - continue; - } - } + vec4 doFoo(Foo[2] foo, float zw) + { + return vec4(foo[0].x, foo[0].y, zw, zw); } - void whileLoopDemo() { - int i = 0; - while (i < 5) { - i++; - } + vec4 doFoo(Foo[3] foo, float zw) + { + return vec4(foo[0].x, foo[0].y, zw, zw); + } - do { - i++; - } while (i < 5); + vec4 doFoo(Foo[2][2] foo, float zw, mat2x2 a) + { + return vec4(foo[0][0].x, foo[0][0].y, zw, zw); + } + + vec4 doFoo(Foo[2][2] foo, float zw, mat2x2 a, bvec2 b) + { + return vec4(foo[0][0].x, foo[0][0].y, zw, zw); + } + + vec4 doFoo(Foo[2][2] foo, float zw, mat2x2 a, ivec2 b) + { + return vec4(foo[0][0].x, foo[0][0].y, zw, zw); + } + + vec4 doFoo(Foo[2][2] foo, float zw, mat2x2 a, uvec2 b) + { + return vec4(foo[0][0].x, foo[0][0].y, zw, zw); } void main() { - ifElseDemo(); - switchDemo(); - forLoopDemo(); - whileLoopDemo(); + Foo foo; + doFoo(foo); + doFoo(foo, 3.0); + doFoo(Foo[2](foo, foo), 3.0); + doFoo(Foo[3](foo, foo, foo), 3.0); + doFoo(Foo[2][2](Foo[2](foo, foo), Foo[2](foo, foo)), 3.0, + mat2x2(1.0)); + doFoo(Foo[2][2](Foo[2](foo, foo), Foo[2](foo, foo)), 3.0, + mat2x2(1.0), bvec2(true, false)); + doFoo(Foo[2][2](Foo[2](foo, foo), Foo[2](foo, foo)), 3.0, + mat2x2(1.0), ivec2(1, 2)); + doFoo(Foo[2][2](Foo[2](foo, foo), Foo[2](foo, foo)), 3.0, + mat2x2(1.0), uvec2(1, 2)); + + outColor = vec4(foo.x, 0.0, 0.0, 0.0); })"; const std::string &outputString = - R"(fn _uifElseDemo() -> i32 + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _uoutColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _uoutColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams { - var _ux : i32 = (5i); - if ((_ux) == (5i)) - { - return 6i; - } - else - { - if ((_ux) == (6i)) - { - return 7i; - } - else - { - return 8i; - } - } + near : f32, + far : f32, + diff : f32, +}; + +struct _uFoo +{ + _ux : f32, + _uy : f32, + _umultiArray : array, 3>, 2>, + _uaMatrix : mat3x3, +}; + +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _udoFoo(_ufoo : _uFoo) -> vec4 +{ + return vec4((_ufoo)._ux, (_ufoo)._uy, 0.0f, 0.0f); } -fn _uswitchDemo() +fn ANGLEfunc3006_udoFoo(_ufoo : _uFoo, _uzw : f32) -> vec4 { - var _ux : i32 = (5i); - switch _ux - { - case 5i, 6i: - { - discard; - } - case 7i: - { - { - return; - } - } - case 8i, 9i: - { - { - (_ux) = (7i); - } - return; - } - case default: - { - return; - } - } + return vec4((_ufoo)._ux, (_ufoo)._uy, _uzw, _uzw); } -fn _uforLoopDemo() +fn ANGLEfunc3009_udoFoo(_ufoo : array<_uFoo, 2>, _uzw : f32) -> vec4 { - for (var _ui : i32 = (0i); (_ui) < (5i); (_ui)++) - { - if ((_ui) == (4i)) - { - break; - } - else - { - if ((_ui) == (5i)) - { - continue; - } - } - } + return vec4(((_ufoo)[0i])._ux, ((_ufoo)[0i])._uy, _uzw, _uzw); } -fn _uwhileLoopDemo() +fn ANGLEfunc3012_udoFoo(_ufoo : array<_uFoo, 3>, _uzw : f32) -> vec4 { - var _ui : i32 = (0i); - while ((_ui) < (5i)) - { - (_ui)++; - } - loop { - { - (_ui)++; - } - if (!((_ui) < (5i)) { break; } - } + return vec4(((_ufoo)[0i])._ux, ((_ufoo)[0i])._uy, _uzw, _uzw); +} + +fn ANGLEfunc3015_udoFoo(_ufoo : array, 2>, _uzw : f32, _ua : mat2x2) -> vec4 +{ + return vec4((((_ufoo)[0i])[0i])._ux, (((_ufoo)[0i])[0i])._uy, _uzw, _uzw); +} + +fn ANGLEfunc3019_udoFoo(_ufoo : array, 2>, _uzw : f32, _ua : mat2x2, _ub : vec2) -> vec4 +{ + return vec4((((_ufoo)[0i])[0i])._ux, (((_ufoo)[0i])[0i])._uy, _uzw, _uzw); +} + +fn ANGLEfunc3024_udoFoo(_ufoo : array, 2>, _uzw : f32, _ua : mat2x2, _ub : vec2) -> vec4 +{ + return vec4((((_ufoo)[0i])[0i])._ux, (((_ufoo)[0i])[0i])._uy, _uzw, _uzw); +} + +fn ANGLEfunc3029_udoFoo(_ufoo : array, 2>, _uzw : f32, _ua : mat2x2, _ub : vec2) -> vec4 +{ + return vec4((((_ufoo)[0i])[0i])._ux, (((_ufoo)[0i])[0i])._uy, _uzw, _uzw); } fn _umain() { - _uifElseDemo(); - _uswitchDemo(); - _uforLoopDemo(); - _uwhileLoopDemo(); + var _ufoo : _uFoo; + _udoFoo(_ufoo); + ANGLEfunc3006_udoFoo(_ufoo, 3.0f); + ANGLEfunc3009_udoFoo(array<_uFoo, 2>(_ufoo, _ufoo), 3.0f); + ANGLEfunc3012_udoFoo(array<_uFoo, 3>(_ufoo, _ufoo, _ufoo), 3.0f); + ANGLEfunc3015_udoFoo(array, 2>(array<_uFoo, 2>(_ufoo, _ufoo), array<_uFoo, 2>(_ufoo, _ufoo)), 3.0f, mat2x2(1.0f, 0.0f, 0.0f, 1.0f)); + ANGLEfunc3019_udoFoo(array, 2>(array<_uFoo, 2>(_ufoo, _ufoo), array<_uFoo, 2>(_ufoo, _ufoo)), 3.0f, mat2x2(1.0f, 0.0f, 0.0f, 1.0f), vec2(true, false)); + ANGLEfunc3024_udoFoo(array, 2>(array<_uFoo, 2>(_ufoo, _ufoo), array<_uFoo, 2>(_ufoo, _ufoo)), 3.0f, mat2x2(1.0f, 0.0f, 0.0f, 1.0f), vec2(1i, 2i)); + ANGLEfunc3029_udoFoo(array, 2>(array<_uFoo, 2>(_ufoo, _ufoo), array<_uFoo, 2>(_ufoo, _ufoo)), 3.0f, mat2x2(1.0f, 0.0f, 0.0f, 1.0f), vec2(1u, 2u)); + (ANGLE_output_global._uoutColor) = (vec4((_ufoo)._ux, 0.0f, 0.0f, 0.0f)); } @fragment -fn wgslMain() +fn wgslMain() -> ANGLE_Output_Annotated { _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._uoutColor = ANGLE_output_global._uoutColor; + return ANGLE_output_annotated; } )"; compile(shaderString); EXPECT_TRUE(foundInCode(outputString.c_str())); } -TEST_F(WGSLOutputTest, GLFragColorWithUniform) +TEST_F(WGSLOutputTest, ModifyFunctionParameters) { const std::string &shaderString = - R"( -uniform mediump vec4 u_color; -void main(void) -{ - gl_FragColor = u_color; -})"; + R"(#version 310 es + precision highp float; + + out vec4 outColor; + + struct Foo { + float x; + float y; + }; + + vec4 doFoo(Foo foo, float zw) + { + foo.x = foo.y; + return vec4(foo.x, foo.y, zw, zw); + } + + float returnFloat(float x) { + x += 5.0; + return x; + } + + float takeArgs(vec2 x, float y, float z) { + y -= x.x; + z -= 1.0; + return y; + } + + void main() + { + Foo foo; + // Struct field accesses. + foo.x = 2.0; + foo.y = 2.0; + + doFoo(foo, returnFloat(3.0)); + takeArgs(vec2(1.0, 2.0), foo.x, 7.0); + float f3 = returnFloat(doFoo(foo, 7.0 + 9.0).x); + + outColor = vec4(f3, 0.0, 0.0, 0.0); + })"; const std::string &outputString = - R"(struct ANGLE_Output_Global { - gl_FragColor_ : vec4, + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _uoutColor : vec4, }; var ANGLE_output_global : ANGLE_Output_Global; struct ANGLE_Output_Annotated { - @location(0) gl_FragColor_ : vec4, + @location(@@@@@@) _uoutColor : vec4, }; -struct ANGLE_DefaultUniformBlock { - u_color : vec4, +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, }; -@group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +struct _uFoo +{ + _ux : f32, + _uy : f32, +}; ; -fn _umain() +struct ANGLEUniformBlock { - (ANGLE_output_global.gl_FragColor_) = (ANGLE_defaultUniformBlock.u_color); + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _udoFoo(_ufoo : _uFoo, _uzw : f32) -> vec4 +{ + var sbc8 : _uFoo = (_ufoo); + ((sbc8)._ux) = ((sbc8)._uy); + return vec4((sbc8)._ux, (sbc8)._uy, _uzw, _uzw); +} + +fn _ureturnFloat(_ux : f32) -> f32 +{ + var sbc9 : f32 = (_ux); + (sbc9) += (5.0f); + return sbc9; +} + +fn _utakeArgs(_ux : vec2, _uy : f32, _uz : f32) -> f32 +{ + var sbca : f32 = (_uy); + var sbcb : f32 = (_uz); + (sbca) -= ((_ux).x); + (sbcb) -= (1.0f); + return sbca; +} + +fn _umain() +{ + var _ufoo : _uFoo; + ((_ufoo)._ux) = (2.0f); + ((_ufoo)._uy) = (2.0f); + _udoFoo(_ufoo, _ureturnFloat(3.0f)); + _utakeArgs(vec2(1.0f, 2.0f), (_ufoo)._ux, 7.0f); + var _uf3 : f32 = (_ureturnFloat((_udoFoo(_ufoo, 16.0f)).x)); + (ANGLE_output_global._uoutColor) = (vec4(_uf3, 0.0f, 0.0f, 0.0f)); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._uoutColor = ANGLE_output_global._uoutColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, MultiElementSwizzle) +{ + const std::string &shaderString = + R"(#version 300 es + precision highp float; + + in vec3 inVec; + out vec4 outColor; + + void main() + { + outColor = vec4(0.0, 0.0, 0.0, 0.0); + + // Unimplemented or buggy: + // outColor.xy += 0.25; + // (outColor.xy + 0.25, outColor.yz) += 0.25; + + outColor.zx = vec2(1.0, 1.0); + + outColor.zx = inVec.xz; + + outColor.xy *= mat2(1.0, 0.0, 0.0, 1.0); + })"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Input_Global { + _uinVec : vec3, +}; + +var ANGLE_input_global : ANGLE_Input_Global; + +struct ANGLE_Input_Annotated { + @location(@@@@@@) _uinVec : vec3, +}; + +struct ANGLE_Output_Global { + _uoutColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _uoutColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global._uoutColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + var sbbc : vec2 = (vec2(1.0f, 1.0f)); + ((ANGLE_output_global._uoutColor).z) = ((sbbc).x); + ((ANGLE_output_global._uoutColor).x) = ((sbbc).y); + var sbbd : vec2 = ((ANGLE_input_global._uinVec).xz); + ((ANGLE_output_global._uoutColor).z) = ((sbbd).x); + ((ANGLE_output_global._uoutColor).x) = ((sbbd).y); + var sbbe : mat2x2 = (mat2x2(1.0f, 0.0f, 0.0f, 1.0f)); + ((ANGLE_output_global._uoutColor).x) = ((((ANGLE_output_global._uoutColor).xy) * (sbbe)).x); + ((ANGLE_output_global._uoutColor).y) = ((((ANGLE_output_global._uoutColor).xy) * (sbbe)).y); +} +@fragment +fn wgslMain(ANGLE_input_annotated : ANGLE_Input_Annotated) -> ANGLE_Output_Annotated +{ + ANGLE_input_global._uinVec = ANGLE_input_annotated._uinVec; + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._uoutColor = ANGLE_output_global._uoutColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, ControlFlow) +{ + const std::string &shaderString = + R"(#version 300 es + precision highp float; + + int ifElseDemo() { + int x = 5; + if (x == 5) { + return 6; + } else if (x == 6) { + return 7; + } else { + return 8; + } + } + + void switchDemo() { + int x = 5; + switch (x) { + case 5: + case 6: + discard; + case 7: { + return; + } + case 8: + case 9: + { + x = 7; + } + return; + default: + return; + } + } + + void forLoopDemo() { + for (int i = 0; i < 5; i++) { + if (i == 4) { + break; + } else if (i == 5) { + continue; + } + } + } + + void whileLoopDemo() { + int i = 0; + while (i < 5) { + i++; + } + + do { + i++; + } while (i < 5); + } + + void main() + { + ifElseDemo(); + switchDemo(); + forLoopDemo(); + whileLoopDemo(); + })"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _uifElseDemo() -> i32 +{ + var _ux : i32 = (5i); + if ((_ux) == (5i)) + { + return 6i; + } + else + { + if ((_ux) == (6i)) + { + return 7i; + } + else + { + return 8i; + } + } +} + +fn _uswitchDemo() +{ + var _ux : i32 = (5i); + switch _ux + { + case 5i, 6i: + { + discard; + } + case 7i: + { + { + return; + } + } + case 8i, 9i: + { + { + (_ux) = (7i); + } + return; + } + case default: + { + return; + } + } +} + +fn _uforLoopDemo() +{ + for (var _ui : i32 = (0i); (_ui) < (5i); (_ui)++) + { + if ((_ui) == (4i)) + { + break; + } + else + { + if ((_ui) == (5i)) + { + continue; + } + } + } +} + +fn _uwhileLoopDemo() +{ + var _ui : i32 = (0i); + while ((_ui) < (5i)) + { + (_ui)++; + } + loop { + { + (_ui)++; + } + continuing { + break if !((_ui) < (5i)); + } + } +} + +fn _umain() +{ + _uifElseDemo(); + _uswitchDemo(); + _uforLoopDemo(); + _uwhileLoopDemo(); +} +@fragment +fn wgslMain() +{ + _umain(); +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, ChainedAssignment) +{ + const std::string &shaderString = + R"(#version 300 es + precision highp float; + + in vec4 inColor; + layout (location = 0) out vec4 color1; + layout (location = 1) out vec4 color2; + + float globVar = 1.0; + + void main() + { + vec4 tempColor; + if ((tempColor = inColor).x == 1.0) { + color1 = color2 = inColor; + } + })"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +fn ANGLE_assignPriv_0(dest : ptr>, src : vec4) -> vec4 { + *dest = src; + return *dest; +} +fn ANGLE_assignFunc_0(dest : ptr>, src : vec4) -> vec4 { + *dest = src; + return *dest; +} +struct ANGLE_Input_Global { + _uinColor : vec4, +}; + +var ANGLE_input_global : ANGLE_Input_Global; + +struct ANGLE_Input_Annotated { + @location(@@@@@@) _uinColor : vec4, +}; + +struct ANGLE_Output_Global { + _ucolor1 : vec4, + _ucolor2 : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ucolor1 : vec4, + @location(@@@@@@) _ucolor2 : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + var _utempColor : vec4; + if (((ANGLE_assignFunc_0(&_utempColor, ANGLE_input_global._uinColor)).x) == (1.0f)) + { + (ANGLE_output_global._ucolor1) = (ANGLE_assignPriv_0(&ANGLE_output_global._ucolor2, ANGLE_input_global._uinColor)); + } +} +@fragment +fn wgslMain(ANGLE_input_annotated : ANGLE_Input_Annotated) -> ANGLE_Output_Annotated +{ + ANGLE_input_global._uinColor = ANGLE_input_annotated._uinColor; + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ucolor1 = ANGLE_output_global._ucolor1; + ANGLE_output_annotated._ucolor2 = ANGLE_output_global._ucolor2; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, IncrementDecrement) +{ + + const std::string &shaderString = + R"(#version 300 es + precision highp float; + + out vec4 color; + + float globVar = 1.0; + + void main() + { + for (int i = 0; i < 5; i++) { + color.x++; + } + + uint i = 0u; + while (i++ < 5u) { + color.y++; + } + + color++; + + ivec4 iv = ivec4(1,2,3,4); + iv++; + ++iv; + color.x += float(iv.x); + + mat2x2 m = mat2x2(4); + m++; + + color.xy *= m; + + mat2x2 m2 = m++; + + color.xy *= m2; + + color++; + + globVar++; + + color.x += globVar; + })"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +fn ANGLE_preIncPriv_4(x : ptr>) -> vec4 { + (*x) += vec4(1); + return *x; +} +fn ANGLE_preIncFunc_4(x : ptr>) -> vec4 { + (*x) += vec4(1); + return *x; +} +fn ANGLE_postIncPriv_0(x : ptr) -> f32 { + var old = *x; + (*x) += f32(1); + return old; +} +fn ANGLE_postIncFunc_0(x : ptr) -> f32 { + var old = *x; + (*x) += f32(1); + return old; +} +fn ANGLE_postIncPriv_5(x : ptr>) -> mat2x2 { + var old = *x; + (*x) += mat2x2(1, 1, 1, 1); + return old; +} +fn ANGLE_postIncFunc_5(x : ptr>) -> mat2x2 { + var old = *x; + (*x) += mat2x2(1, 1, 1, 1); + return old; +} +fn ANGLE_postIncPriv_2(x : ptr>) -> vec4 { + var old = *x; + (*x) += vec4(1); + return old; +} +fn ANGLE_postIncFunc_2(x : ptr>) -> vec4 { + var old = *x; + (*x) += vec4(1); + return old; +} +fn ANGLE_postIncPriv_3(x : ptr>) -> vec4 { + var old = *x; + (*x) += vec4(1); + return old; +} +fn ANGLE_postIncFunc_3(x : ptr>) -> vec4 { + var old = *x; + (*x) += vec4(1); + return old; +} +fn ANGLE_postIncPriv_1(x : ptr) -> u32 { + var old = *x; + (*x) += u32(1); + return old; +} +fn ANGLE_postIncFunc_1(x : ptr) -> u32 { + var old = *x; + (*x) += u32(1); + return old; +} +struct ANGLE_Output_Global { + _ucolor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ucolor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +var _uglobVar : f32 = (1.0f); + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + for (var _ui : i32 = (0i); (_ui) < (5i); (_ui)++) + { + ANGLE_postIncFunc_0(&((ANGLE_output_global._ucolor).x)); + } + var _ui : u32 = (0u); + while ((ANGLE_postIncFunc_1(&(_ui))) < (5u)) + { + ANGLE_postIncFunc_0(&((ANGLE_output_global._ucolor).y)); + } + ANGLE_postIncPriv_2(&(ANGLE_output_global._ucolor)); + var _uiv : vec4 = (vec4(1i, 2i, 3i, 4i)); + ANGLE_postIncFunc_3(&(_uiv)); + ANGLE_preIncFunc_4(&(_uiv)); + ((ANGLE_output_global._ucolor).x) += (f32((_uiv).x)); + var _um : mat2x2 = (mat2x2(4.0f, 0.0f, 0.0f, 4.0f)); + ANGLE_postIncFunc_5(&(_um)); + var sbc1 : mat2x2 = (_um); + ((ANGLE_output_global._ucolor).x) = ((((ANGLE_output_global._ucolor).xy) * (sbc1)).x); + ((ANGLE_output_global._ucolor).y) = ((((ANGLE_output_global._ucolor).xy) * (sbc1)).y); + var _um2 : mat2x2 = (ANGLE_postIncFunc_5(&(_um))); + var sbc2 : mat2x2 = (_um2); + ((ANGLE_output_global._ucolor).x) = ((((ANGLE_output_global._ucolor).xy) * (sbc2)).x); + ((ANGLE_output_global._ucolor).y) = ((((ANGLE_output_global._ucolor).xy) * (sbc2)).y); + ANGLE_postIncPriv_2(&(ANGLE_output_global._ucolor)); + ANGLE_postIncPriv_0(&(_uglobVar)); + ((ANGLE_output_global._ucolor).x) += (_uglobVar); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ucolor = ANGLE_output_global._ucolor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, GLFragColorWithUniform) +{ + const std::string &shaderString = + R"( +uniform mediump vec4 u_color; +void main(void) +{ + gl_FragColor = u_color; +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + gl_FragColor_ : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(0) gl_FragColor_ : vec4, +}; + +@group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +struct ANGLE_DefaultUniformBlock +{ + @align(16) _uu_color : vec4, +}; + +; + +fn _umain() +{ + (ANGLE_output_global.gl_FragColor_) = ((ANGLE_defaultUniformBlock)._uu_color); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated.gl_FragColor_ = ANGLE_output_global.gl_FragColor_; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, UniformsWithNestedStructs) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; +struct NestedUniforms { + float x; +}; +struct Uniforms { + NestedUniforms a; + float b; + float c; + float[5] d; + float e; + vec3 f[7]; + float[5] g; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + float[5] dCopy = unis.d; + fragColor = vec4(unis.a.x, unis.b, unis.c, dCopy[1]); + fragColor += vec4(unis.d[2], unis.e, unis.f[0][2], (unis.e > 0.5 ? unis.d : unis.g)[1]); +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLE_wrapped_float +{ + @align(16) elem : f32 +}; +fn ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements(wrappedArr : array) -> array +{ + var retVal : array; + for (var i : u32 = 0; i < 5; i++) {; + retVal[i] = wrappedArr[i].elem; + } + return retVal; +} +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +struct _uNestedUniforms +{ + @align(16) _ux : f32, +}; + +struct _uUniforms +{ + @align(16) _ua : _uNestedUniforms, + @align(16) _ub : f32, + _uc : f32, + @align(16) _ud : array, + _ue : f32, + @align(16) _uf : array, 7>, + @align(16) _ug : array, +}; + +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; +; + +struct ANGLE_DefaultUniformBlock +{ + @align(16) _uunis : _uUniforms, +}; + +; + +fn _umain() +{ + var _udCopy : array = (ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements(((ANGLE_defaultUniformBlock)._uunis)._ud)); + (ANGLE_output_global._ufragColor) = (vec4((((ANGLE_defaultUniformBlock)._uunis)._ua)._ux, ((ANGLE_defaultUniformBlock)._uunis)._ub, ((ANGLE_defaultUniformBlock)._uunis)._uc, (_udCopy)[1i])); + (ANGLE_output_global._ufragColor) += (vec4(((ANGLE_defaultUniformBlock)._uunis)._ud[2i].elem, ((ANGLE_defaultUniformBlock)._uunis)._ue, ((((ANGLE_defaultUniformBlock)._uunis)._uf)[0i])[2i], (sbc1())[1i])); +} + +fn sbc1() -> array +{ + if ((((ANGLE_defaultUniformBlock)._uunis)._ue) > (0.5f)) + { + return ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements(((ANGLE_defaultUniformBlock)._uunis)._ud); + } + else + { + return ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements(((ANGLE_defaultUniformBlock)._uunis)._ug); + } +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, Ternaries) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; + +float globVar; + +in float inVar; +out vec4 fragColor; +void main() { + fragColor = vec4(0.0); + // Basic ternary + fragColor.x = inVar > 0.5 ? 1.0 : 0.0; + // Ternary with reference to temp vars + float x = inVar + 1.0; + fragColor.y = x > 0.5 ? 1.0 + x : x - 1.0; + // Ternary with reference to global vars or in vars + globVar = inVar - 2.0; + fragColor.z = x > globVar ? 1.0 + x : x - 1.0; + + float y = inVar - 7.0; + fragColor.w = (x > globVar ? (x > globVar + 0.5 ? y + 0.5 : y - 0.5) : y); + + float z = (x > globVar ? y : x); + fragColor.w += z; + + fragColor.w += (z > 0.5 ? z : z + 0.5); +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Input_Global { + _uinVar : f32, +}; + +var ANGLE_input_global : ANGLE_Input_Global; + +struct ANGLE_Input_Annotated { + @location(@@@@@@) _uinVar : f32, +}; + +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +var _uglobVar : f32; +; +; +var _ux : f32; +var _uy : f32; +var _uz : f32; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; +; +; +; +; +; +; +; + +fn _umain() +{ + (ANGLE_output_global._ufragColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + ((ANGLE_output_global._ufragColor).x) = (sbc3()); + (_ux) = ((ANGLE_input_global._uinVar) + (1.0f)); + ((ANGLE_output_global._ufragColor).y) = (sbc4()); + (_uglobVar) = ((ANGLE_input_global._uinVar) - (2.0f)); + ((ANGLE_output_global._ufragColor).z) = (sbc5()); + (_uy) = ((ANGLE_input_global._uinVar) - (7.0f)); + ((ANGLE_output_global._ufragColor).w) = (sbc6()); + (_uz) = (sbc7()); + ((ANGLE_output_global._ufragColor).w) += (_uz); + ((ANGLE_output_global._ufragColor).w) += (sbc8()); +} + +fn sbc3() -> f32 +{ + if ((ANGLE_input_global._uinVar) > (0.5f)) + { + return 1.0f; + } + else + { + return 0.0f; + } +} + +fn sbc4() -> f32 +{ + if ((_ux) > (0.5f)) + { + return (1.0f) + (_ux); + } + else + { + return (_ux) - (1.0f); + } +} + +fn sbc5() -> f32 +{ + if ((_ux) > (_uglobVar)) + { + return (1.0f) + (_ux); + } + else + { + return (_ux) - (1.0f); + } +} + +fn sbc6() -> f32 +{ + if ((_ux) > (_uglobVar)) + { + return sbc9(); + } + else + { + return _uy; + } +} + +fn sbc7() -> f32 +{ + if ((_ux) > (_uglobVar)) + { + return _uy; + } + else + { + return _ux; + } +} + +fn sbc8() -> f32 +{ + if ((_uz) > (0.5f)) + { + return _uz; + } + else + { + return (_uz) + (0.5f); + } +} + +fn sbc9() -> f32 +{ + if ((_ux) > ((_uglobVar) + (0.5f))) + { + return (_uy) + (0.5f); + } + else + { + return (_uy) - (0.5f); + } +} +@fragment +fn wgslMain(ANGLE_input_annotated : ANGLE_Input_Annotated) -> ANGLE_Output_Annotated +{ + ANGLE_input_global._uinVar = ANGLE_input_annotated._uinVar; + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, CommaOperator) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; + +float globVar; + +in float inVar; +out vec4 fragColor; + +void setGlobVar() { + globVar = 1.0; +} + +void main() { + fragColor = vec4(0.0); + float tempVar; + fragColor.x = (globVar = inVar, tempVar = globVar, tempVar); + + (tempVar = 5.0, globVar = 6.0, setGlobVar()); + + float a,b,c,d,e; + fragColor.x += ((a = 1.0, b = a), (c = b, (d = c)), (setGlobVar(), e = d, e)); +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Input_Global { + _uinVar : f32, +}; + +var ANGLE_input_global : ANGLE_Input_Global; + +struct ANGLE_Input_Annotated { + @location(@@@@@@) _uinVar : f32, +}; + +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +var _uglobVar : f32; +; +; +var _utempVar : f32; +var _ua : f32; +var _ub : f32; +var _uc : f32; +var _ud : f32; +var _ue : f32; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; +; +; +; + +fn _usetGlobVar() +{ + (_uglobVar) = (1.0f); +} + +fn _umain() +{ + (ANGLE_output_global._ufragColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + ((ANGLE_output_global._ufragColor).x) = (sbca()); + sbcb(); + ((ANGLE_output_global._ufragColor).x) += (sbcc()); +} + +fn sbca() -> f32 +{ + (_uglobVar) = (ANGLE_input_global._uinVar); + (_utempVar) = (_uglobVar); + return _utempVar; +} + +fn sbcb() +{ + (_utempVar) = (5.0f); + (_uglobVar) = (6.0f); + _usetGlobVar(); +} + +fn sbcc() -> f32 +{ + (_ua) = (1.0f); + (_ub) = (_ua); + (_uc) = (_ub); + (_ud) = (_uc); + _usetGlobVar(); + (_ue) = (_ud); + return _ue; +} +@fragment +fn wgslMain(ANGLE_input_annotated : ANGLE_Input_Annotated) -> ANGLE_Output_Annotated +{ + ANGLE_input_global._uinVar = ANGLE_input_annotated._uinVar; + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, DifficultMultiElementSwizzle) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; + +float globVar; + +in float inVar; +out vec4 fragColor; +void main() { + fragColor.xy = vec2(1.0, 2.0); + + vec4[2] vecs; + int i = 0; + float a = 0.0; + vecs[i++].yz = (vecs[i++].xy = vec2(a++, a++)); +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +fn ANGLE_postIncPriv_1(x : ptr) -> f32 { + var old = *x; + (*x) += f32(1); + return old; +} +fn ANGLE_postIncFunc_1(x : ptr) -> f32 { + var old = *x; + (*x) += f32(1); + return old; +} +fn ANGLE_postIncPriv_0(x : ptr) -> i32 { + var old = *x; + (*x) += i32(1); + return old; +} +fn ANGLE_postIncFunc_0(x : ptr) -> i32 { + var old = *x; + (*x) += i32(1); + return old; +} +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +var _uinVar : f32; +; +var _uvecs : array, 2>; +var _ui : i32; +var _ua : f32; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; +; +; +; +; + +fn _umain() +{ + var sbd9 : vec2 = (vec2(1.0f, 2.0f)); + ((ANGLE_output_global._ufragColor).x) = ((sbd9).x); + ((ANGLE_output_global._ufragColor).y) = ((sbd9).y); + (_ui) = (0i); + (_ua) = (0.0f); + sbca(); +} + +fn sbc4(sbc3 : ptr>) -> vec2 +{ + var sbda : vec2 = (sbd7(&(*sbc3))); + (((*sbc3)).y) = ((sbda).x); + (((*sbc3)).z) = ((sbda).y); + return ((*sbc3)).yz; +} + +fn sbca() -> vec2 +{ + let sbc6 : ptr> = (&((_uvecs)[clamp((ANGLE_postIncPriv_0(&(_ui))), 0, 1)])); + var sbc5 : vec4; + var sbc9 : vec2 = (sbc4(&sbc5)); + ((*sbc6)) = (sbc5); + return sbc9; +} + +fn sbcc(sbcb : ptr>, sbc3 : ptr>) -> vec2 +{ + var sbdb : vec2 = (vec2(ANGLE_postIncPriv_1(&(_ua)), ANGLE_postIncPriv_1(&(_ua)))); + (((*sbcb)).x) = ((sbdb).x); + (((*sbcb)).y) = ((sbdb).y); + return ((*sbcb)).xy; +} + +fn sbd7(sbc3 : ptr>) -> vec2 +{ + let sbcf : ptr> = (&((_uvecs)[clamp((ANGLE_postIncPriv_0(&(_ui))), 0, 1)])); + var sbce : vec4; + let sbd3 : ptr> = (&((*sbc3))); + var sbd2 : vec4; + var sbd6 : vec2 = (sbcc(&sbce, &sbd2)); + ((*sbcf)) = (sbce); + ((*sbd3)) = (sbd2); + return sbd6; +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, UniformsWithMatCx2) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; +struct Uniforms { + mat2 a; + mat3x2 b; + mat4x2 c; + + mat2[2] aArr; + mat3x2[2] bArr; + mat4x2[2] cArr; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + mat2 a = unis.a; + mat3x2 b = unis.b; + mat4x2 c = unis.c; + + mat2[2] aArr = unis.aArr; + mat3x2[2] bArr = unis.bArr; + mat4x2[2] cArr = unis.cArr; + + mat2 aIndexed = unis.aArr[1]; + mat3x2 bIndexed = unis.bArr[1]; + mat4x2 cIndexed = unis.cArr[1]; + + fragColor = vec4(a[0][0], b[0][0], c[0][0], 1.0); + fragColor += vec4(aArr[0][0][0], bArr[0][0][0], cArr[0][0][0], 1.0); + fragColor += vec4(aIndexed[0][0], bIndexed[0][0], cIndexed[0][0], 1.0); +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLE_wrapped_vec2 +{ + @align(16) elem : vec2 +}; +fn ANGLE_Convert_Mat2x2(mangledMatrix : array) -> mat2x2 +{ + var retVal : mat2x2; + retVal = mat2x2(mangledMatrix[0].elem, mangledMatrix[1].elem); + return retVal; +} +fn ANGLE_Convert_Array2_Mat2x2(mangledMatrix : array, 2>) -> array, 2> +{ + var retVal : array, 2>; + for (var i : u32 = 0; i < 2; i++) {; + retVal[i] = mat2x2(mangledMatrix[i][0].elem, mangledMatrix[i][1].elem); + } + return retVal; +} +fn ANGLE_Convert_Mat3x2(mangledMatrix : array) -> mat3x2 +{ + var retVal : mat3x2; + retVal = mat3x2(mangledMatrix[0].elem, mangledMatrix[1].elem, mangledMatrix[2].elem); + return retVal; +} +fn ANGLE_Convert_Array2_Mat3x2(mangledMatrix : array, 2>) -> array, 2> +{ + var retVal : array, 2>; + for (var i : u32 = 0; i < 2; i++) {; + retVal[i] = mat3x2(mangledMatrix[i][0].elem, mangledMatrix[i][1].elem, mangledMatrix[i][2].elem); + } + return retVal; +} +fn ANGLE_Convert_Mat4x2(mangledMatrix : array) -> mat4x2 +{ + var retVal : mat4x2; + retVal = mat4x2(mangledMatrix[0].elem, mangledMatrix[1].elem, mangledMatrix[2].elem, mangledMatrix[3].elem); + return retVal; +} +fn ANGLE_Convert_Array2_Mat4x2(mangledMatrix : array, 2>) -> array, 2> +{ + var retVal : array, 2>; + for (var i : u32 = 0; i < 2; i++) {; + retVal[i] = mat4x2(mangledMatrix[i][0].elem, mangledMatrix[i][1].elem, mangledMatrix[i][2].elem, mangledMatrix[i][3].elem); + } + return retVal; +} +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +struct _uUniforms +{ + @align(16) _ua : array, + @align(16) _ub : array, + @align(16) _uc : array, + @align(16) _uaArr : array, 2>, + @align(16) _ubArr : array, 2>, + @align(16) _ucArr : array, 2>, +}; + +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +struct ANGLE_DefaultUniformBlock +{ + @align(16) _uunis : _uUniforms, +}; + +; + +fn _umain() +{ + var _ua : mat2x2 = (ANGLE_Convert_Mat2x2(((ANGLE_defaultUniformBlock)._uunis)._ua)); + var _ub : mat3x2 = (ANGLE_Convert_Mat3x2(((ANGLE_defaultUniformBlock)._uunis)._ub)); + var _uc : mat4x2 = (ANGLE_Convert_Mat4x2(((ANGLE_defaultUniformBlock)._uunis)._uc)); + var _uaArr : array, 2> = (ANGLE_Convert_Array2_Mat2x2(((ANGLE_defaultUniformBlock)._uunis)._uaArr)); + var _ubArr : array, 2> = (ANGLE_Convert_Array2_Mat3x2(((ANGLE_defaultUniformBlock)._uunis)._ubArr)); + var _ucArr : array, 2> = (ANGLE_Convert_Array2_Mat4x2(((ANGLE_defaultUniformBlock)._uunis)._ucArr)); + var _uaIndexed : mat2x2 = (ANGLE_Convert_Mat2x2(((ANGLE_defaultUniformBlock)._uunis)._uaArr[1i])); + var _ubIndexed : mat3x2 = (ANGLE_Convert_Mat3x2(((ANGLE_defaultUniformBlock)._uunis)._ubArr[1i])); + var _ucIndexed : mat4x2 = (ANGLE_Convert_Mat4x2(((ANGLE_defaultUniformBlock)._uunis)._ucArr[1i])); + (ANGLE_output_global._ufragColor) = (vec4(((_ua)[0i])[0i], ((_ub)[0i])[0i], ((_uc)[0i])[0i], 1.0f)); + (ANGLE_output_global._ufragColor) += (vec4((((_uaArr)[0i])[0i])[0i], (((_ubArr)[0i])[0i])[0i], (((_ucArr)[0i])[0i])[0i], 1.0f)); + (ANGLE_output_global._ufragColor) += (vec4(((_uaIndexed)[0i])[0i], ((_ubIndexed)[0i])[0i], ((_ucIndexed)[0i])[0i], 1.0f)); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, UniformsWithBool) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; +struct Uniforms { + bool a; + + bool[2] aArr; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + bool a = unis.a; + + bool[2] aArr = unis.aArr; + + bool aIndexed = unis.aArr[1]; + + fragColor = vec4(a, aArr[0], aIndexed, 1.0); +})"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLE_wrapped_uint +{ + @align(16) elem : u32 +}; +fn ANGLE_Convert_Array2_ANGLE_wrapped_uint_ElementsTo_bool_Elements(wrappedArr : array) -> array +{ + var retVal : array; + for (var i : u32 = 0; i < 2; i++) {; + retVal[i] = bool(wrappedArr[i].elem); + } + return retVal; +} +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +struct _uUniforms +{ + @align(16) _ua : u32, + @align(16) _uaArr : array, +}; + +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +struct ANGLE_DefaultUniformBlock +{ + @align(16) _uunis : _uUniforms, +}; + +; + +fn _umain() +{ + var _ua : bool = (bool(((ANGLE_defaultUniformBlock)._uunis)._ua)); + var _uaArr : array = (ANGLE_Convert_Array2_ANGLE_wrapped_uint_ElementsTo_bool_Elements(((ANGLE_defaultUniformBlock)._uunis)._uaArr)); + var _uaIndexed : bool = (bool(((ANGLE_defaultUniformBlock)._uunis)._uaArr[1i].elem)); + (ANGLE_output_global._ufragColor) = (vec4(_ua, (_uaArr)[0i], _uaIndexed, 1.0f)); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, BasicSamplers) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; +struct SamplerStruct { + sampler2D samp1; +}; +uniform SamplerStruct sampStruct; + +uniform sampler2D samp2D; +uniform mediump sampler3D samp3D; +uniform mediump samplerCube sampCube; + +out vec4 fragColor; +void main() { + fragColor = texture(sampStruct.samp1, vec2(0.0, 0.0)); + + // --- texture --- + fragColor += texture(samp2D, vec2(0.0, 0.0)); + fragColor += texture(samp3D, vec3(0.0, 0.0, 0.0)); + fragColor += texture(sampCube, vec3(0.0, 0.0, 0.0)); + // --- texture with bias --- + fragColor += texture(samp2D, vec2(0.0, 0.0), /*bias=*/1.0); + fragColor += texture(samp3D, vec3(0.0, 0.0, 0.0), /*bias=*/1.0); + fragColor += texture(sampCube, vec3(0.0, 0.0, 0.0), /*bias=*/1.0); + + // --- textureOffset --- + fragColor += textureOffset(samp2D, vec2(0.0, 0.0), ivec2(5,6)); + fragColor += textureOffset(samp3D, vec3(0.0, 0.0, 0.0), ivec3(5,6,7)); + // --- textureOffset with bias --- + fragColor += textureOffset(samp2D, vec2(0.0, 0.0), ivec2(5,6), /*bias=*/1.0); + fragColor += textureOffset(samp3D, vec3(0.0, 0.0, 0.0), ivec3(5,6,7), /*bias=*/1.0); + + // --- textureProj --- + // All coordinates should be divided by the last + // --- textureProj with bias--- + fragColor += textureProj(samp2D, vec3(0.0, 0.0, 1.0), /*bias=*/1.0); + fragColor += textureProj(samp2D, vec4(0.0, 0.0, 0.0, 1.0), /*bias=*/1.0); // 3rd coordinate ignored + fragColor += textureProj(samp3D, vec4(0.0, 0.0, 0.0, 1.0), /*bias=*/1.0); + + // --- textureLod --- + fragColor += textureLod(samp2D, vec2(0.5, 0.5), /*lod=*/0.0); + fragColor += textureLod(samp3D, vec3(0.5, 0.5, 0.5), /*lod=*/0.0); + fragColor += textureLod(sampCube, vec3(0.5, 0.5, 0.5), /*lod=*/0.0); + + // --- texelFetch --- + ivec2 size2D = textureSize(samp2D, 0); + ivec3 size3D = textureSize(samp3D, 0); + fragColor += texelFetch(samp2D, ivec2(vec2(0.5, 0.5) * vec2(size2D)), 0); + fragColor += texelFetch(samp3D, ivec3(vec3(0.5, 0.5, 0.5) * vec3(size3D)), 0); + + // --- texelFetchOffset --- + fragColor += texelFetchOffset(samp2D, ivec2(vec2(0.5, 0.5) * vec2(size2D)), 0, ivec2(0, 0)); + fragColor += texelFetchOffset(samp3D, ivec3(vec3(0.5, 0.5, 0.5) * vec3(size3D)), 0, ivec3(0, 0, 0)); + + // --- textureProjOffset --- + fragColor += textureProjOffset(samp2D, vec3(0.5, 0.5, 1.0), ivec2(0, 0)); + fragColor += textureProjOffset(samp2D, vec4(0.5, 0.5, 0.0, 1.0), ivec2(0, 0)); + fragColor += textureProjOffset(samp3D, vec4(0.5, 0.5, 0.5, 1.0), ivec3(0, 0, 0)); + // --- textureProjOffset with bias --- + fragColor += textureProjOffset(samp2D, vec3(0.5, 0.5, 1.0), ivec2(0, 0), /*bias=*/1.0); + fragColor += textureProjOffset(samp2D, vec4(0.5, 0.5, 0.0, 1.0), ivec2(0, 0), /*bias=*/1.0); + fragColor += textureProjOffset(samp3D, vec4(0.5, 0.5, 0.5, 1.0), ivec3(0, 0, 0), /*bias=*/1.0); + + // --- textureLodOffset --- + fragColor += textureLodOffset(samp2D, vec2(0.5, 0.5), 0.0, ivec2(0, 0)); + fragColor += textureLodOffset(samp3D, vec3(0.5, 0.5, 0.5), 0.0, ivec3(0, 0, 0)); + + // --- textureProjLod --- + fragColor += textureProjLod(samp2D, vec3(0.5, 0.5, 1.0), /*lod=*/0.0); + fragColor += textureProjLod(samp2D, vec4(0.5, 0.5, 0.0, 1.0), /*lod=*/0.0); + fragColor += textureProjLod(samp3D, vec4(0.5, 0.5, 0.5, 1.0), /*lod=*/0.0); + + // --- textureProjLodOffset --- + fragColor += textureProjLodOffset(samp2D, vec3(0.5, 0.5, 1.0), 0.0, ivec2(0, 0)); + fragColor += textureProjLodOffset(samp2D, vec4(0.5, 0.5, 0.0, 1.0), 0.0, ivec2(0, 0)); + fragColor += textureProjLodOffset(samp3D, vec4(0.5, 0.5, 0.5, 1.0), 0.0, ivec3(0, 0, 0)); + + // --- textureGrad --- + fragColor += textureGrad(samp2D, vec2(0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0)); + fragColor += textureGrad(samp3D, vec3(0.5, 0.5, 0.5), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0)); + fragColor += textureGrad(sampCube, vec3(0.5, 0.5, 0.5), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0)); + + // --- textureGradOffset --- + fragColor += textureGradOffset(samp2D, vec2(0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0)); + fragColor += textureGradOffset(samp3D, vec3(0.5, 0.5, 0.5), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0), ivec3(0, 0, 0)); + + // --- textureProjGrad --- + fragColor += textureProjGrad(samp2D, vec3(0.5, 0.5, 1.0), vec2(0.0, 0.0), vec2(0.0, 0.0)); + fragColor += textureProjGrad(samp2D, vec4(0.5, 0.5, 0.0, 1.0), vec2(0.0, 0.0), vec2(0.0, 0.0)); + fragColor += textureProjGrad(samp3D, vec4(0.5, 0.5, 0.5, 1.0), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0)); + + // --- textureProjGradOffset --- + fragColor += textureProjGradOffset(samp2D, vec3(0.5, 0.5, 1.0), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0)); + fragColor += textureProjGradOffset(samp2D, vec4(0.5, 0.5, 0.0, 1.0), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0)); + fragColor += textureProjGradOffset(samp3D, vec4(0.5, 0.5, 0.5, 1.0), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0), ivec3(0, 0, 0)); +} +)"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp2D : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp2D : texture_2d; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp3D : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp3D : texture_3d; +@group(1) @binding(@@@@@@) var ANGLE_sampler_sampCube : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_sampCube : texture_cube; +@group(1) @binding(@@@@@@) var ANGLE_sampler_sampStruct_samp1 : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_sampStruct_samp1 : texture_2d; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; +; +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global._ufragColor) = (textureSample(ANGLE_texture_sampStruct_samp1, ANGLE_sampler_sampStruct_samp1, (vec2(0.0f, 0.0f)).xy)); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy)); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.0f, 0.0f, 0.0f)).xyz)); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.0f, 0.0f, 0.0f)).xyz)); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy, 1.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.0f, 0.0f, 0.0f)).xyz, 1.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.0f, 0.0f, 0.0f)).xyz, 1.0f)); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy, vec2(5i, 6i))); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.0f, 0.0f, 0.0f)).xyz, vec3(5i, 6i, 7i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy, 1.0f, vec2(5i, 6i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.0f, 0.0f, 0.0f)).xyz, 1.0f, vec3(5i, 6i, 7i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.0f, 0.0f, 1.0f)).xy / (vec3(0.0f, 0.0f, 1.0f)).z, 1.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.0f, 0.0f, 0.0f, 1.0f)).xy / (vec4(0.0f, 0.0f, 0.0f, 1.0f)).w, 1.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.0f, 0.0f, 0.0f, 1.0f)).xyz / (vec4(0.0f, 0.0f, 0.0f, 1.0f)).w, 1.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.5f, 0.5f)).xy, 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.5f, 0.5f, 0.5f)).xyz, 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.5f, 0.5f, 0.5f)).xyz, 0.0f)); + var _usize2D : vec2 = (textureDimensions(ANGLE_texture_samp2D, 0i)); + var _usize3D : vec3 = (textureDimensions(ANGLE_texture_samp3D, 0i)); + (ANGLE_output_global._ufragColor) += (textureLoad(ANGLE_texture_samp2D, (vec2((vec2(0.5f, 0.5f)) * (vec2(_usize2D)))), 0i)); + (ANGLE_output_global._ufragColor) += (textureLoad(ANGLE_texture_samp3D, (vec3((vec3(0.5f, 0.5f, 0.5f)) * (vec3(_usize3D)))), 0i)); + (ANGLE_output_global._ufragColor) += (textureLoad(ANGLE_texture_samp2D, (vec2((vec2(0.5f, 0.5f)) * (vec2(_usize2D)))), 0i, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureLoad(ANGLE_texture_samp3D, (vec3((vec3(0.5f, 0.5f, 0.5f)) * (vec3(_usize3D)))), 0i, vec3(0i, 0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.5f, 0.5f, 1.0f)).xy / (vec3(0.5f, 0.5f, 1.0f)).z, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.5f, 0.5f, 0.0f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.0f, 1.0f)).w, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xyz / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, vec3(0i, 0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.5f, 0.5f, 1.0f)).xy / (vec3(0.5f, 0.5f, 1.0f)).z, 1.0f, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.5f, 0.5f, 0.0f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.0f, 1.0f)).w, 1.0f, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xyz / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 1.0f, vec3(0i, 0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.5f, 0.5f)).xy, 0.0f, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.5f, 0.5f, 0.5f)).xyz, 0.0f, vec3(0i, 0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.5f, 0.5f, 1.0f)).xy / (vec3(0.5f, 0.5f, 1.0f)).z, 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.5f, 0.5f, 0.0f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.0f, 1.0f)).w, 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xyz / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.5f, 0.5f, 1.0f)).xy / (vec3(0.5f, 0.5f, 1.0f)).z, 0.0f, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.5f, 0.5f, 0.0f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.0f, 1.0f)).w, 0.0f, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xyz / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 0.0f, vec3(0i, 0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.5f, 0.5f)).xy, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.5f, 0.5f, 0.5f)).xyz, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.5f, 0.5f, 0.5f)).xyz, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.5f, 0.5f)).xy, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec3(0.5f, 0.5f, 0.5f)).xyz, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0i, 0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.5f, 0.5f, 1.0f)).xy / (vec3(0.5f, 0.5f, 1.0f)).z, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.5f, 0.5f, 0.0f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.0f, 1.0f)).w, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xyz / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.5f, 0.5f, 1.0f)).xy / (vec3(0.5f, 0.5f, 1.0f)).z, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.5f, 0.5f, 0.0f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.0f, 1.0f)).w, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp3D, ANGLE_sampler_samp3D, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xyz / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0i, 0i, 0i))); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, ShadowSamplers) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; + +uniform mediump sampler2DShadow samp2DShadow; +uniform mediump samplerCubeShadow sampCubeShadow; + +out vec4 fragColor; +void main() { + fragColor = vec4(0.0); + + // --- textureSize --- + fragColor += vec4(textureSize(samp2DShadow, 0), 0.0, 0.0); + fragColor += vec4(textureSize(sampCubeShadow, 0), 0.0, 0.0); + + // --- texture --- + fragColor += vec4(texture(samp2DShadow, vec3(0.5, 0.5, 0.5))); + fragColor += vec4(texture(sampCubeShadow, vec4(0.5, 0.5, 0.5, 0.5))); + // --- texture with bias --- + fragColor += vec4(texture(samp2DShadow, vec3(0.5, 0.5, 0.5), /*bias=*/0.0)); + fragColor += vec4(texture(sampCubeShadow, vec4(0.5, 0.5, 0.5, 0.5), /*bias=*/0.0)); + + // --- textureProj --- + fragColor += vec4(textureProj(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0))); + // --- textureProj with bias --- + fragColor += vec4(textureProj(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), /*bias=*/0.0)); + + // --- textureLod --- + fragColor += vec4(textureLod(samp2DShadow, vec3(0.5, 0.5, 0.5), /*lod=*/0.0)); + + // --- textureOffset --- + fragColor += vec4(textureOffset(samp2DShadow, vec3(0.5, 0.5, 0.5), ivec2(0, 0))); + // --- textureOffset with bias --- + fragColor += vec4(textureOffset(samp2DShadow, vec3(0.5, 0.5, 0.5), ivec2(0, 0), /*bias=*/0.0)); + + // --- textureProjOffset --- + fragColor += vec4(textureProjOffset(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), ivec2(0, 0))); + // --- textureProjOffset bias --- + fragColor += vec4(textureProjOffset(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), ivec2(0, 0), /*bias=*/0.0)); + + // --- textureLodOffset --- + fragColor += vec4(textureLodOffset(samp2DShadow, vec3(0.5, 0.5, 0.5), 0.0, ivec2(0, 0))); + + // --- textureProjLod --- + fragColor += vec4(textureProjLod(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), /*lod=*/0.0)); + + // --- textureProjLodOffset --- + fragColor += vec4(textureProjLodOffset(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), 0.0, ivec2(0, 0))); + + // --- textureGrad --- + fragColor += vec4(textureGrad(samp2DShadow, vec3(0.5, 0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0))); + fragColor += vec4(textureGrad(sampCubeShadow, vec4(0.5, 0.5, 0.5, 0.5), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0))); + + // --- textureGradOffset --- + fragColor += vec4(textureGradOffset(samp2DShadow, vec3(0.5, 0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0))); + + // --- textureProjGrad --- + fragColor += vec4(textureProjGrad(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), vec2(0.0, 0.0), vec2(0.0, 0.0))); + + // --- textureProjGradOffset --- + fragColor += vec4(textureProjGradOffset(samp2DShadow, vec4(0.5, 0.5, 0.5, 1.0), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0))); +} +)"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp2DShadow : sampler_comparison; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp2DShadow : texture_depth_2d; +@group(1) @binding(@@@@@@) var ANGLE_sampler_sampCubeShadow : sampler_comparison; +@group(1) @binding(@@@@@@) var ANGLE_texture_sampCubeShadow : texture_depth_cube; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global._ufragColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + (ANGLE_output_global._ufragColor) += (vec4(textureDimensions(ANGLE_texture_samp2DShadow, 0i), 0.0f, 0.0f)); + (ANGLE_output_global._ufragColor) += (vec4(textureDimensions(ANGLE_texture_sampCubeShadow, 0i), 0.0f, 0.0f)); + (ANGLE_output_global._ufragColor) += (vec4(textureSampleCompare(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z))); + (ANGLE_output_global._ufragColor) += (vec4(textureSampleCompare(ANGLE_texture_sampCubeShadow, ANGLE_sampler_sampCubeShadow, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).xyz, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).w))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_BIAS_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, 0.0f))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_BIAS_WITH_SHADOW_SAMPLER(ANGLE_texture_sampCubeShadow, ANGLE_sampler_sampCubeShadow, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).xyz, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).w, 0.0f))); + (ANGLE_output_global._ufragColor) += (vec4(textureSampleCompare(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_BIAS_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 0.0f))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_LOD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, 0.0f))); + (ANGLE_output_global._ufragColor) += (vec4(textureSampleCompare(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_BIAS_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, 0.0f, vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(textureSampleCompare(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_BIAS_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 0.0f, vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_LOD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, 0.0f, vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_LOD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 0.0f))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_LOD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, 0.0f, vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_sampCubeShadow, ANGLE_sampler_sampCubeShadow, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).xyz, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).w, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec3(0.5f, 0.5f, 0.5f)).xy, (vec3(0.5f, 0.5f, 0.5f)).z, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DShadow, ANGLE_sampler_samp2DShadow, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).xy / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, (vec4(0.5f, 0.5f, 0.5f, 1.0f)).z / (vec4(0.5f, 0.5f, 0.5f, 1.0f)).w, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i)))); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +// Including arrays of shadow samplers. +TEST_F(WGSLOutputTest, ArraySamplers) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; + +uniform mediump sampler2DArray samp2DArray; +uniform mediump sampler2DArrayShadow samp2DArrayShadow; + +out vec4 fragColor; +void main() { + fragColor = vec4(0.0); + + // --- textureSize --- + fragColor += vec4(textureSize(samp2DArray, 0), 0.0); + fragColor += vec4(textureSize(samp2DArrayShadow, 0), 0.0); + + // --- texture --- + fragColor += texture(samp2DArray, vec3(0.5, 0.5, 0.5)); + fragColor += texture(samp2DArray, vec3(0.5, 0.5, 0.5), /*bias=*/0.0); + fragColor += vec4(texture(samp2DArrayShadow, vec4(0.5, 0.5, 0.5, 0.5))); + + // --- textureLod --- + fragColor += textureLod(samp2DArray, vec3(0.5, 0.5, 0.5), 0.0); + + // --- textureOffset --- + fragColor += textureOffset(samp2DArray, vec3(0.5, 0.5, 0.5), ivec2(0, 0)); + fragColor += textureOffset(samp2DArray, vec3(0.5, 0.5, 0.5), ivec2(0, 0), /*bias=*/0.0); + + // --- texelFetch --- + ivec3 size2DArray = textureSize(samp2DArray, 0); + fragColor += texelFetch(samp2DArray, ivec3(vec3(0.5, 0.5, 0.5) * vec3(size2DArray)), /*lod=*/0); + + // --- texelFetchOffset --- + fragColor += texelFetchOffset(samp2DArray, ivec3(vec3(0.5, 0.5, 0.5) * vec3(size2DArray)), 0, ivec2(0, 0)); + + // --- textureLodOffset --- + fragColor += textureLodOffset(samp2DArray, vec3(0.5, 0.5, 0.5), 0.0, ivec2(0, 0)); + + // --- textureGrad --- + fragColor += textureGrad(samp2DArray, vec3(0.5, 0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0)); + fragColor += vec4(textureGrad(samp2DArrayShadow, vec4(0.5, 0.5, 0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0))); + + // --- textureGradOffset --- + fragColor += textureGradOffset(samp2DArray, vec3(0.5, 0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0)); + fragColor += textureGradOffset(samp2DArrayShadow, vec4(0.5, 0.5, 0.5, 0.5), vec2(0.0, 0.0), vec2(0.0, 0.0), ivec2(0, 0)); +} +)"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(@@@@@@) _ufragColor : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp2DArray : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp2DArray : texture_2d_array; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp2DArrayShadow : sampler_comparison; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp2DArrayShadow : texture_depth_2d_array; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global._ufragColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + (ANGLE_output_global._ufragColor) += (vec4(textureDimensions(ANGLE_texture_samp2DArray, 0i), 0.0f)); + (ANGLE_output_global._ufragColor) += (vec4(textureDimensions(ANGLE_texture_samp2DArrayShadow, 0i), 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), 0.0f)); + (ANGLE_output_global._ufragColor) += (vec4(textureSampleCompare(ANGLE_texture_samp2DArrayShadow, ANGLE_sampler_samp2DArrayShadow, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).xy, i32((vec4(0.5f, 0.5f, 0.5f, 0.5f)).z), (vec4(0.5f, 0.5f, 0.5f, 0.5f)).w))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), 0.0f)); + (ANGLE_output_global._ufragColor) += (textureSample(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleBias(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), 0.0f, vec2(0i, 0i))); + var _usize2DArray : vec3 = (textureDimensions(ANGLE_texture_samp2DArray, 0i)); + (ANGLE_output_global._ufragColor) += (textureLoad(ANGLE_texture_samp2DArray, (vec3((vec3(0.5f, 0.5f, 0.5f)) * (vec3(_usize2DArray)))), 0i)); + (ANGLE_output_global._ufragColor) += (textureLoad(ANGLE_texture_samp2DArray, (vec3((vec3(0.5f, 0.5f, 0.5f)) * (vec3(_usize2DArray)))), 0i, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleLevel(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), 0.0f, vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), vec2(0.0f, 0.0f), vec2(0.0f, 0.0f))); + (ANGLE_output_global._ufragColor) += (vec4(TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DArrayShadow, ANGLE_sampler_samp2DArrayShadow, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).xy, i32((vec4(0.5f, 0.5f, 0.5f, 0.5f)).z), (vec4(0.5f, 0.5f, 0.5f, 0.5f)).w, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)))); + (ANGLE_output_global._ufragColor) += (textureSampleGrad(ANGLE_texture_samp2DArray, ANGLE_sampler_samp2DArray, (vec3(0.5f, 0.5f, 0.5f)).xy, i32((vec3(0.5f, 0.5f, 0.5f)).z), vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i))); + (ANGLE_output_global._ufragColor) += (TODO_CANNOT_USE_EXPLICIT_GRAD_WITH_SHADOW_SAMPLER(ANGLE_texture_samp2DArrayShadow, ANGLE_sampler_samp2DArrayShadow, (vec4(0.5f, 0.5f, 0.5f, 0.5f)).xy, i32((vec4(0.5f, 0.5f, 0.5f, 0.5f)).z), (vec4(0.5f, 0.5f, 0.5f, 0.5f)).w, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f), vec2(0i, 0i))); +} +@fragment +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +// ES2 versions. +TEST_F(WGSLOutputTest, SamplersES2) +{ + const std::string &shaderString = + R"(precision mediump float; + +uniform sampler2D samp2D; +uniform samplerCube sampCube; + +void main() { + gl_FragColor = vec4(0.0); + + // --- texture2D --- + gl_FragColor += texture2D(samp2D, vec2(0.0, 0.0)); + gl_FragColor += texture2D(samp2D, vec2(0.0, 0.0), /*bias=*/0.0); + + // --- texture2DProj --- + gl_FragColor += texture2DProj(samp2D, vec4(0.0, 0.0, 0.0, 0.0).xyz); + gl_FragColor += texture2DProj(samp2D, vec4(0.0, 0.0, 0.0, 0.0)); + gl_FragColor += texture2DProj(samp2D, vec4(0.0, 0.0, 0.0, 0.0).xyz, /*bias=*/0.0); + gl_FragColor += texture2DProj(samp2D, vec4(0.0, 0.0, 0.0, 0.0), /*bias=*/0.0); + + // --- textureCube --- + gl_FragColor += textureCube(sampCube, vec3(0.0, 0.0, 0.0)); + gl_FragColor += textureCube(sampCube, vec3(0.0, 0.0, 0.0), /*bias=*/0.0); + + // Explicit LOD versions not available in fragment shaders. +} +)"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + gl_FragColor_ : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @location(0) gl_FragColor_ : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp2D : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp2D : texture_2d; +@group(1) @binding(@@@@@@) var ANGLE_sampler_sampCube : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_sampCube : texture_cube; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global.gl_FragColor_) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + (ANGLE_output_global.gl_FragColor_) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy)); + (ANGLE_output_global.gl_FragColor_) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy, 0.0f)); + (ANGLE_output_global.gl_FragColor_) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.0f, 0.0f, 0.0f)).xy / (vec3(0.0f, 0.0f, 0.0f)).z)); + (ANGLE_output_global.gl_FragColor_) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.0f, 0.0f, 0.0f, 0.0f)).xy / (vec4(0.0f, 0.0f, 0.0f, 0.0f)).w)); + (ANGLE_output_global.gl_FragColor_) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.0f, 0.0f, 0.0f)).xy / (vec3(0.0f, 0.0f, 0.0f)).z, 0.0f)); + (ANGLE_output_global.gl_FragColor_) += (textureSampleBias(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.0f, 0.0f, 0.0f, 0.0f)).xy / (vec4(0.0f, 0.0f, 0.0f, 0.0f)).w, 0.0f)); + (ANGLE_output_global.gl_FragColor_) += (textureSample(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.0f, 0.0f, 0.0f)).xyz)); + (ANGLE_output_global.gl_FragColor_) += (textureSampleBias(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.0f, 0.0f, 0.0f)).xyz, 0.0f)); } @fragment fn wgslMain() -> ANGLE_Output_Annotated @@ -387,90 +2576,293 @@ fn wgslMain() -> ANGLE_Output_Annotated EXPECT_TRUE(foundInCode(outputString.c_str())); } -TEST_F(WGSLOutputTest, UniformsWithNestedStructs) +TEST_F(WGSLVertexOutputTest, SamplersES2) +{ + const std::string &shaderString = + R"(precision mediump float; + +uniform sampler2D samp2D; +uniform samplerCube sampCube; + +void main() { + gl_Position = vec4(0.0); + + // Bias versions not available in the vertex shader. + + // --- texture2D --- + gl_Position += texture2D(samp2D, vec2(0.0, 0.0)); + + // --- texture2DProj --- + gl_Position += texture2DProj(samp2D, vec4(0.0, 0.0, 0.0, 0.0).xyz); + gl_Position += texture2DProj(samp2D, vec4(0.0, 0.0, 0.0, 0.0)); + + // --- textureCube --- + gl_Position += textureCube(sampCube, vec3(0.0, 0.0, 0.0)); + + // These explicit LOD versions only available in vertex shaders. + + // --- texture2DLod --- + gl_Position += texture2DLod(samp2D, vec2(0.0, 0.0), /*lod=*/0.0); + + // --- texture2DProjLod --- + gl_Position += texture2DProjLod(samp2D, vec4(0.0, 0.0, 0.0, 0.0).xyz, /*lod=*/0.0); + gl_Position += texture2DProjLod(samp2D, vec4(0.0, 0.0, 0.0, 0.0), /*lod=*/0.0); + + // --- textureCubeLod --- + gl_Position += textureCubeLod(sampCube, vec3(0.0, 0.0, 0.0), /*lod=*/0.0); +} +)"; + + // TODO(anglebug.com/389145696): these are incorrect translations in vertex shaders, They should + // be textureLoad(), as the basic textureSample*() functions aren't available in WGSL vertex + // shaders. + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + gl_Position_ : vec4, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @builtin(position) gl_Position_ : vec4, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; +@group(1) @binding(@@@@@@) var ANGLE_sampler_samp2D : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_samp2D : texture_2d; +@group(1) @binding(@@@@@@) var ANGLE_sampler_sampCube : sampler; +@group(1) @binding(@@@@@@) var ANGLE_texture_sampCube : texture_cube; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global.gl_Position_) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + (ANGLE_output_global.gl_Position_) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy)); + (ANGLE_output_global.gl_Position_) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.0f, 0.0f, 0.0f)).xy / (vec3(0.0f, 0.0f, 0.0f)).z)); + (ANGLE_output_global.gl_Position_) += (textureSample(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.0f, 0.0f, 0.0f, 0.0f)).xy / (vec4(0.0f, 0.0f, 0.0f, 0.0f)).w)); + (ANGLE_output_global.gl_Position_) += (textureSample(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.0f, 0.0f, 0.0f)).xyz)); + (ANGLE_output_global.gl_Position_) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec2(0.0f, 0.0f)).xy, 0.0f)); + (ANGLE_output_global.gl_Position_) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec3(0.0f, 0.0f, 0.0f)).xy / (vec3(0.0f, 0.0f, 0.0f)).z, 0.0f)); + (ANGLE_output_global.gl_Position_) += (textureSampleLevel(ANGLE_texture_samp2D, ANGLE_sampler_samp2D, (vec4(0.0f, 0.0f, 0.0f, 0.0f)).xy / (vec4(0.0f, 0.0f, 0.0f, 0.0f)).w, 0.0f)); + (ANGLE_output_global.gl_Position_) += (textureSampleLevel(ANGLE_texture_sampCube, ANGLE_sampler_sampCube, (vec3(0.0f, 0.0f, 0.0f)).xyz, 0.0f)); + ((ANGLE_output_global.gl_Position_).y) = (((ANGLE_output_global.gl_Position_).y) * ((unpack4x8snorm((ANGLEUniforms).flipXY)).w)); +} +@vertex +fn wgslMain() -> ANGLE_Output_Annotated +{ + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated.gl_Position_ = ANGLE_output_global.gl_Position_; + return ANGLE_output_annotated; +} +)"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLVertexOutputTest, MatrixAttributesAndVaryings) { const std::string &shaderString = R"(#version 300 es -precision mediump float; -struct NestedUniforms { - float x; + precision highp float; + + in mat3 inMat; + out mat3 outMatArr; + + void main() + { + outMatArr = inMat; + })"; + const std::string &outputString = + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Input_Global { + _uinMat : mat3x3, }; -struct Uniforms { - NestedUniforms a; - float b; - float c; - float[5] d; - float e; - vec3 f[7]; - float[5] g; + +var ANGLE_input_global : ANGLE_Input_Global; + +struct ANGLE_Input_Annotated { + @location(@@@@@@) _uinMat_col0 : vec3, + @location(@@@@@@) _uinMat_col1 : vec3, + @location(@@@@@@) _uinMat_col2 : vec3, }; -uniform Uniforms unis; + +struct ANGLE_Output_Global { + gl_Position_ : vec4, + _uoutMatArr : mat3x3, +}; + +var ANGLE_output_global : ANGLE_Output_Global; + +struct ANGLE_Output_Annotated { + @builtin(position) gl_Position_ : vec4, + @location(@@@@@@) _uoutMatArr_col0 : vec3, + @location(@@@@@@) _uoutMatArr_col1 : vec3, + @location(@@@@@@) _uoutMatArr_col2 : vec3, +}; + +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; + +struct ANGLEDepthRangeParams +{ + near : f32, + far : f32, + diff : f32, +}; + +; +; + +struct ANGLEUniformBlock +{ + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, +}; + +; + +fn _umain() +{ + (ANGLE_output_global._uoutMatArr) = (ANGLE_input_global._uinMat); + ((ANGLE_output_global.gl_Position_).y) = (((ANGLE_output_global.gl_Position_).y) * ((unpack4x8snorm((ANGLEUniforms).flipXY)).w)); +} +@vertex +fn wgslMain(ANGLE_input_annotated : ANGLE_Input_Annotated) -> ANGLE_Output_Annotated +{ + ANGLE_input_global._uinMat = mat3x3(ANGLE_input_annotated._uinMat_col0, ANGLE_input_annotated._uinMat_col1, ANGLE_input_annotated._uinMat_col2); + _umain(); + var ANGLE_output_annotated : ANGLE_Output_Annotated; + ANGLE_output_annotated.gl_Position_ = ANGLE_output_global.gl_Position_; + ANGLE_output_annotated._uoutMatArr_col0 = ANGLE_output_global._uoutMatArr[0]; + ANGLE_output_annotated._uoutMatArr_col1 = ANGLE_output_global._uoutMatArr[1]; + ANGLE_output_annotated._uoutMatArr_col2 = ANGLE_output_global._uoutMatArr[2]; + return ANGLE_output_annotated; +})"; + compile(shaderString); + EXPECT_TRUE(foundInCode(outputString.c_str())); +} + +TEST_F(WGSLOutputTest, BVecsUniforms) +{ + const std::string &shaderString = + R"(#version 300 es +precision mediump float; + +uniform bvec2 uni_bvec; + +uniform bvec2[2] uni_bvec_array; + out vec4 fragColor; + void main() { - float[5] dCopy = unis.d; - fragColor = vec4(unis.a.x, unis.b, unis.c, dCopy[1]); - fragColor += vec4(unis.d[2], unis.e, unis.f[0][2], (unis.e > 0.5 ? unis.d : unis.g)[1]); -})"; + bvec2[2] local_bvec_array = uni_bvec_array; + if (uni_bvec_array[0] == uni_bvec && uni_bvec == local_bvec_array[1]) { + fragColor = vec4(1.0); + } else { + fragColor = vec4(0.0); + } +} +)"; const std::string &outputString = - R"(struct ANGLE_Output_Global { - fragColor : vec4, + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, }; var ANGLE_output_global : ANGLE_Output_Global; struct ANGLE_Output_Annotated { - @location(@@@@@@) fragColor : vec4, -}; - -struct ANGLE_DefaultUniformBlock { - unis : _uUniforms, + @location(@@@@@@) _ufragColor : vec4, }; @group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; -struct ANGLE_wrapped_float +struct ANGLE_wrapped_uvec2 { - @align(16) elem : f32 + @align(16) elem : vec2 }; -fn ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements(wrappedArr : array) -> array +fn ANGLE_Convert_Array2_ANGLE_wrapped_uvec2_ElementsTo_bvec2_Elements(wrappedArr : array) -> array, 2> { - var retVal : array; - for (var i : u32 = 0; i < 5; i++) {; - retVal[i] = wrappedArr[i].elem; + var retVal : array, 2>; + for (var i : u32 = 0; i < 2; i++) {; + retVal[i] = (vec2(0u) != wrappedArr[i].elem); } return retVal; } -struct _uNestedUniforms +struct ANGLEDepthRangeParams { - @align(16) _ux : f32, + near : f32, + far : f32, + diff : f32, }; -struct _uUniforms +; + +struct ANGLEUniformBlock { - @align(16) _ua : _uNestedUniforms, - @align(16) _ub : f32, - _uc : f32, - @align(16) _ud : array, - _ue : f32, - @align(16) _uf : array, 7>, - @align(16) _ug : array, + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, }; ; + +struct ANGLE_DefaultUniformBlock +{ + @align(16) _uuni_bvec : vec2, + @align(16) _uuni_bvec_array : array, +}; + ; fn _umain() { - var _udCopy : array = (ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements((ANGLE_defaultUniformBlock.unis)._ud)); - (ANGLE_output_global.fragColor) = (vec4(((ANGLE_defaultUniformBlock.unis)._ua)._ux, (ANGLE_defaultUniformBlock.unis)._ub, (ANGLE_defaultUniformBlock.unis)._uc, (_udCopy)[1i])); - (ANGLE_output_global.fragColor) += (vec4((ANGLE_defaultUniformBlock.unis)._ud[2i].elem, (ANGLE_defaultUniformBlock.unis)._ue, (((ANGLE_defaultUniformBlock.unis)._uf)[0i])[2i], (select((ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements((ANGLE_defaultUniformBlock.unis)._ug)), (ANGLE_Convert_Array5_ANGLE_wrapped_float_ElementsTo_float_Elements((ANGLE_defaultUniformBlock.unis)._ud)), (((ANGLE_defaultUniformBlock.unis)._ue) > (0.5f))))[1i])); + var _ulocal_bvec_array : array, 2> = (ANGLE_Convert_Array2_ANGLE_wrapped_uvec2_ElementsTo_bvec2_Elements((ANGLE_defaultUniformBlock)._uuni_bvec_array)); + if ((all(((vec2(0u) != (ANGLE_defaultUniformBlock)._uuni_bvec_array[0i].elem)) == ((vec2(0u) != (ANGLE_defaultUniformBlock)._uuni_bvec)))) && (all(((vec2(0u) != (ANGLE_defaultUniformBlock)._uuni_bvec)) == ((_ulocal_bvec_array)[1i])))) + { + (ANGLE_output_global._ufragColor) = (vec4(1.0f, 1.0f, 1.0f, 1.0f)); + } + else + { + (ANGLE_output_global._ufragColor) = (vec4(0.0f, 0.0f, 0.0f, 0.0f)); + } } @fragment fn wgslMain() -> ANGLE_Output_Annotated { _umain(); var ANGLE_output_annotated : ANGLE_Output_Annotated; - ANGLE_output_annotated.fragColor = ANGLE_output_global.fragColor; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; return ANGLE_output_annotated; } )"; @@ -478,136 +2870,111 @@ fn wgslMain() -> ANGLE_Output_Annotated EXPECT_TRUE(foundInCode(outputString.c_str())); } -TEST_F(WGSLOutputTest, UniformsWithMatCx2) +TEST_F(WGSLOutputTest, DefaultUniformsNoStructWrapper) { const std::string &shaderString = R"(#version 300 es precision mediump float; -struct Uniforms { - mat2 a; - mat3x2 b; - mat4x2 c; - - mat2[2] aArr; - mat3x2[2] bArr; - mat4x2[2] cArr; -}; -uniform Uniforms unis; -out vec4 fragColor; -void main() { - mat2 a = unis.a; - mat3x2 b = unis.b; - mat4x2 c = unis.c; - mat2[2] aArr = unis.aArr; - mat3x2[2] bArr = unis.bArr; - mat4x2[2] cArr = unis.cArr; +uniform float x1; +uniform int y1; +uniform vec2 z1; +uniform mat3x2 a1; +uniform mat4x4 b1; - mat2 aIndexed = unis.aArr[1]; - mat3x2 bIndexed = unis.bArr[1]; - mat4x2 cIndexed = unis.cArr[1]; +uniform float[2] x2; +uniform int[2] y2; +uniform vec2[2] z2; +uniform mat3x2[2] a2; +uniform mat4x4[2] b2; - fragColor = vec4(a[0][0], b[0][0], c[0][0], 1.0); - fragColor += vec4(aArr[0][0][0], bArr[0][0][0], cArr[0][0][0], 1.0); - fragColor += vec4(aIndexed[0][0], bIndexed[0][0], cIndexed[0][0], 1.0); -})"; +out vec4 fragColor; +void main() { + fragColor = vec4(x1 + float(y1), z1.x, a1[0][0], b1[0][0]); + fragColor += vec4(x2[0] + float(y2[0]), z2[0].x, a2[0][0][0], b2[0][0][0]); +} +)"; const std::string &outputString = - R"(struct ANGLE_Output_Global { - fragColor : vec4, + R"(diagnostic(warning,derivative_uniformity); +struct ANGLE_Output_Global { + _ufragColor : vec4, }; var ANGLE_output_global : ANGLE_Output_Global; struct ANGLE_Output_Annotated { - @location(@@@@@@) fragColor : vec4, -}; - -struct ANGLE_DefaultUniformBlock { - unis : _uUniforms, + @location(@@@@@@) _ufragColor : vec4, }; @group(0) @binding(1) var ANGLE_defaultUniformBlock : ANGLE_DefaultUniformBlock; +@group(2) @binding(0) var ANGLEUniforms : ANGLEUniformBlock; +struct ANGLE_wrapped_float +{ + @align(16) elem : f32 +}; struct ANGLE_wrapped_vec2 { @align(16) elem : vec2 }; -fn ANGLE_Convert_Mat2x2(mangledMatrix : array) -> mat2x2 -{ - var retVal : mat2x2; - retVal = mat2x2(mangledMatrix[0].elem, mangledMatrix[1].elem); - return retVal; -} -fn ANGLE_Convert_Array2_Mat2x2(mangledMatrix : array, 2>) -> array, 2> +struct ANGLE_wrapped_int { - var retVal : array, 2>; - for (var i : u32 = 0; i < 2; i++) {; - retVal[i] = mat2x2(mangledMatrix[i][0].elem, mangledMatrix[i][1].elem); - } - return retVal; -} + @align(16) elem : i32 +}; fn ANGLE_Convert_Mat3x2(mangledMatrix : array) -> mat3x2 { var retVal : mat3x2; retVal = mat3x2(mangledMatrix[0].elem, mangledMatrix[1].elem, mangledMatrix[2].elem); return retVal; } -fn ANGLE_Convert_Array2_Mat3x2(mangledMatrix : array, 2>) -> array, 2> -{ - var retVal : array, 2>; - for (var i : u32 = 0; i < 2; i++) {; - retVal[i] = mat3x2(mangledMatrix[i][0].elem, mangledMatrix[i][1].elem, mangledMatrix[i][2].elem); - } - return retVal; -} -fn ANGLE_Convert_Mat4x2(mangledMatrix : array) -> mat4x2 -{ - var retVal : mat4x2; - retVal = mat4x2(mangledMatrix[0].elem, mangledMatrix[1].elem, mangledMatrix[2].elem, mangledMatrix[3].elem); - return retVal; -} -fn ANGLE_Convert_Array2_Mat4x2(mangledMatrix : array, 2>) -> array, 2> +struct ANGLEDepthRangeParams { - var retVal : array, 2>; - for (var i : u32 = 0; i < 2; i++) {; - retVal[i] = mat4x2(mangledMatrix[i][0].elem, mangledMatrix[i][1].elem, mangledMatrix[i][2].elem, mangledMatrix[i][3].elem); - } - return retVal; -} -struct _uUniforms + near : f32, + far : f32, + diff : f32, +}; + +; + +struct ANGLEUniformBlock { - @align(16) _ua : array, - @align(16) _ub : array, - @align(16) _uc : array, - @align(16) _uaArr : array, 2>, - @align(16) _ubArr : array, 2>, - @align(16) _ucArr : array, 2>, + @align(16) acbBufferOffsets : vec2, + depthRange : vec2, + renderArea : u32, + flipXY : u32, + dither : u32, + misc : u32, }; ; + +struct ANGLE_DefaultUniformBlock +{ + @align(16) _ux1 : f32, + _uy1 : i32, + _uz1 : vec2, + @align(16) _ua1 : array, + _ub1 : mat4x4, + @align(16) _ux2 : array, + @align(16) _uy2 : array, + @align(16) _uz2 : array, + @align(16) _ua2 : array, 2>, + @align(16) _ub2 : array, 2>, +}; + ; fn _umain() { - var _ua : mat2x2 = (ANGLE_Convert_Mat2x2((ANGLE_defaultUniformBlock.unis)._ua)); - var _ub : mat3x2 = (ANGLE_Convert_Mat3x2((ANGLE_defaultUniformBlock.unis)._ub)); - var _uc : mat4x2 = (ANGLE_Convert_Mat4x2((ANGLE_defaultUniformBlock.unis)._uc)); - var _uaArr : array, 2> = (ANGLE_Convert_Array2_Mat2x2((ANGLE_defaultUniformBlock.unis)._uaArr)); - var _ubArr : array, 2> = (ANGLE_Convert_Array2_Mat3x2((ANGLE_defaultUniformBlock.unis)._ubArr)); - var _ucArr : array, 2> = (ANGLE_Convert_Array2_Mat4x2((ANGLE_defaultUniformBlock.unis)._ucArr)); - var _uaIndexed : mat2x2 = (ANGLE_Convert_Mat2x2((ANGLE_defaultUniformBlock.unis)._uaArr[1i])); - var _ubIndexed : mat3x2 = (ANGLE_Convert_Mat3x2((ANGLE_defaultUniformBlock.unis)._ubArr[1i])); - var _ucIndexed : mat4x2 = (ANGLE_Convert_Mat4x2((ANGLE_defaultUniformBlock.unis)._ucArr[1i])); - (ANGLE_output_global.fragColor) = (vec4(((_ua)[0i])[0i], ((_ub)[0i])[0i], ((_uc)[0i])[0i], 1.0f)); - (ANGLE_output_global.fragColor) += (vec4((((_uaArr)[0i])[0i])[0i], (((_ubArr)[0i])[0i])[0i], (((_ucArr)[0i])[0i])[0i], 1.0f)); - (ANGLE_output_global.fragColor) += (vec4(((_uaIndexed)[0i])[0i], ((_ubIndexed)[0i])[0i], ((_ucIndexed)[0i])[0i], 1.0f)); + (ANGLE_output_global._ufragColor) = (vec4(((ANGLE_defaultUniformBlock)._ux1) + (f32((ANGLE_defaultUniformBlock)._uy1)), ((ANGLE_defaultUniformBlock)._uz1).x, (ANGLE_Convert_Mat3x2((ANGLE_defaultUniformBlock)._ua1)[0i])[0i], (((ANGLE_defaultUniformBlock)._ub1)[0i])[0i])); + (ANGLE_output_global._ufragColor) += (vec4(((ANGLE_defaultUniformBlock)._ux2[0i].elem) + (f32((ANGLE_defaultUniformBlock)._uy2[0i].elem)), ((ANGLE_defaultUniformBlock)._uz2[0i].elem).x, ((ANGLE_Convert_Mat3x2((ANGLE_defaultUniformBlock)._ua2[0i]))[0i])[0i], ((((ANGLE_defaultUniformBlock)._ub2)[0i])[0i])[0i])); } @fragment fn wgslMain() -> ANGLE_Output_Annotated { _umain(); var ANGLE_output_annotated : ANGLE_Output_Annotated; - ANGLE_output_annotated.fragColor = ANGLE_output_global.fragColor; + ANGLE_output_annotated._ufragColor = ANGLE_output_global._ufragColor; return ANGLE_output_annotated; } )"; diff --git a/src/tests/compiler_tests/WorkGroupSize_test.cpp b/src/tests/compiler_tests/WorkGroupSize_test.cpp index 3e234819cff..a67f0622295 100644 --- a/src/tests/compiler_tests/WorkGroupSize_test.cpp +++ b/src/tests/compiler_tests/WorkGroupSize_test.cpp @@ -39,7 +39,7 @@ class WorkGroupSizeTest : public testing::Test compileOptions.intermediateTree = true; const char *shaderStrings[] = {shaderString.c_str()}; - bool status = mTranslator->compile(shaderStrings, 1, compileOptions); + bool status = mTranslator->compile(shaderStrings, compileOptions); TInfoSink &infoSink = mTranslator->getInfoSink(); mInfoLog = infoSink.info.c_str(); return status; diff --git a/src/tests/deqp_support/angle_deqp_gtest.cpp b/src/tests/deqp_support/angle_deqp_gtest.cpp index 5909837d311..f63dbd1e8e1 100644 --- a/src/tests/deqp_support/angle_deqp_gtest.cpp +++ b/src/tests/deqp_support/angle_deqp_gtest.cpp @@ -7,6 +7,10 @@ // dEQP and GoogleTest integration logic. Calls through to the random // order executor. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include @@ -72,6 +76,7 @@ const char *gCaseListFiles[] = { GLES_CTS_DIR("khronos_mustpass/main/gles3-khr-main.txt"), GLES_CTS_DIR("khronos_mustpass/main/gles31-khr-main.txt"), GLES_CTS_DIR("khronos_mustpass/main/gles32-khr-main.txt"), + GLES_CTS_DIR("khronos_mustpass/main/gles32-khr-glesext.txt"), GLES_CTS_DIR("khronos_mustpass_noctx/main/gles2-khr-noctx-main.txt"), GLES_CTS_DIR("khronos_mustpass_noctx/main/gles32-khr-noctx-main.txt"), GLES_CTS_DIR("khronos_mustpass_single/main/gles32-khr-single.txt"), @@ -96,6 +101,7 @@ const std::vector gTestSuiteConfigParameters[] = { {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // gles3_khr {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // gles31_khr {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // gles32_khr + {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // glesext_khr {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // gles2_khr_noctx {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // gles32_khr_noctx {"--deqp-gl-config-name=rgba8888d24s8ms0"}, // gles32_khr_single @@ -123,6 +129,7 @@ const char *gTestExpectationsFiles[] = { "deqp_khr_gles3_test_expectations.txt", "deqp_khr_gles31_test_expectations.txt", "deqp_khr_gles32_test_expectations.txt", + "deqp_khr_glesext_test_expectations.txt", "deqp_khr_noctx_gles2_test_expectations.txt", "deqp_khr_noctx_gles32_test_expectations.txt", "deqp_khr_single_gles32_test_expectations.txt", @@ -318,57 +325,61 @@ size_t GetTestModuleIndex() return 7; #endif -#ifdef ANGLE_DEQP_KHR_NOCTX_GLES2_TESTS +#ifdef ANGLE_DEQP_KHR_GLESEXT_TESTS return 8; #endif -#ifdef ANGLE_DEQP_KHR_NOCTX_GLES32_TESTS +#ifdef ANGLE_DEQP_KHR_NOCTX_GLES2_TESTS return 9; #endif -#ifdef ANGLE_DEQP_KHR_SINGLE_GLES32_TESTS +#ifdef ANGLE_DEQP_KHR_NOCTX_GLES32_TESTS return 10; #endif -#ifdef ANGLE_DEQP_GLES3_ROTATE90_TESTS +#ifdef ANGLE_DEQP_KHR_SINGLE_GLES32_TESTS return 11; #endif -#ifdef ANGLE_DEQP_GLES3_ROTATE180_TESTS +#ifdef ANGLE_DEQP_GLES3_ROTATE90_TESTS return 12; #endif -#ifdef ANGLE_DEQP_GLES3_ROTATE270_TESTS +#ifdef ANGLE_DEQP_GLES3_ROTATE180_TESTS return 13; #endif -#ifdef ANGLE_DEQP_GLES31_ROTATE90_TESTS +#ifdef ANGLE_DEQP_GLES3_ROTATE270_TESTS return 14; #endif -#ifdef ANGLE_DEQP_GLES31_ROTATE180_TESTS +#ifdef ANGLE_DEQP_GLES31_ROTATE90_TESTS return 15; #endif -#ifdef ANGLE_DEQP_GLES31_ROTATE270_TESTS +#ifdef ANGLE_DEQP_GLES31_ROTATE180_TESTS return 16; #endif -#ifdef ANGLE_DEQP_GLES3_MULTISAMPLE_TESTS +#ifdef ANGLE_DEQP_GLES31_ROTATE270_TESTS return 17; #endif -#ifdef ANGLE_DEQP_GLES3_565_NO_DEPTH_NO_STENCIL_TESTS +#ifdef ANGLE_DEQP_GLES3_MULTISAMPLE_TESTS return 18; #endif -#ifdef ANGLE_DEQP_GLES31_MULTISAMPLE_TESTS +#ifdef ANGLE_DEQP_GLES3_565_NO_DEPTH_NO_STENCIL_TESTS return 19; #endif -#ifdef ANGLE_DEQP_GLES31_565_NO_DEPTH_NO_STENCIL_TESTS +#ifdef ANGLE_DEQP_GLES31_MULTISAMPLE_TESTS return 20; #endif + +#ifdef ANGLE_DEQP_GLES31_565_NO_DEPTH_NO_STENCIL_TESTS + return 21; +#endif } class dEQPCaseList diff --git a/src/tests/deqp_support/angle_deqp_libtester_main.cpp b/src/tests/deqp_support/angle_deqp_libtester_main.cpp index 74d0a7f4e43..323609c11c0 100644 --- a/src/tests/deqp_support/angle_deqp_libtester_main.cpp +++ b/src/tests/deqp_support/angle_deqp_libtester_main.cpp @@ -56,7 +56,7 @@ ANGLE_LIBTESTER_EXPORT bool deqp_libtester_init_platform(int argc, { #if (DE_OS != DE_OS_WIN32) // Set stdout to line-buffered mode (will be fully buffered by default if stdout is pipe). - setvbuf(stdout, DE_NULL, _IOLBF, 4 * 1024); + setvbuf(stdout, nullptr, _IOLBF, 4 * 1024); #endif g_platform = CreateANGLEPlatform(reinterpret_cast(logErrorFunc), options.preRotation, options.driverOption); @@ -78,14 +78,14 @@ ANGLE_LIBTESTER_EXPORT bool deqp_libtester_init_platform(int argc, g_cmdLine = new tcu::CommandLine(argc, argv); g_archive = new tcu::DirArchive(deqpDataDir); g_log = new tcu::TestLog(GetLogFileName(deqpDataDir).c_str(), g_cmdLine->getLogFlags()); - g_testCtx = new tcu::TestContext(*g_platform, *g_archive, *g_log, *g_cmdLine, DE_NULL); + g_testCtx = new tcu::TestContext(*g_platform, *g_archive, *g_log, *g_cmdLine, nullptr); g_root = new tcu::TestPackageRoot(*g_testCtx, tcu::TestPackageRegistry::getSingleton()); g_executor = new tcu::RandomOrderExecutor(*g_root, *g_testCtx, options.enableRenderDocCapture); } catch (const std::exception &e) { - tcu::die("%s", e.what()); + ANGLE_UNSAFE_TODO(tcu::die("%s", e.what())); return false; } @@ -114,7 +114,7 @@ ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[]) catch (const std::exception &e) { deqp_libtester_shutdown_platform(); - tcu::die("%s", e.what()); + ANGLE_UNSAFE_TODO(tcu::die("%s", e.what())); } deqp_libtester_shutdown_platform(); diff --git a/src/tests/deqp_support/deqp.gni b/src/tests/deqp_support/deqp.gni index 56c2cacdd46..a163a8998f8 100644 --- a/src/tests/deqp_support/deqp.gni +++ b/src/tests/deqp_support/deqp.gni @@ -926,6 +926,8 @@ deqp_khr_common_sources = [ "$deqp_path/external/openglcts/modules/common/glcMultipleContextsTests.hpp", "$deqp_path/external/openglcts/modules/common/glcNearestEdgeTests.cpp", "$deqp_path/external/openglcts/modules/common/glcNearestEdgeTests.hpp", + "$deqp_path/external/openglcts/modules/common/glcNegativeTextureLookupFunctionsBiasTests.cpp", + "$deqp_path/external/openglcts/modules/common/glcNegativeTextureLookupFunctionsBiasTests.hpp", "$deqp_path/external/openglcts/modules/common/glcNoDefaultContextPackage.cpp", "$deqp_path/external/openglcts/modules/common/glcNoDefaultContextPackage.hpp", "$deqp_path/external/openglcts/modules/common/glcNoErrorTests.cpp", @@ -1015,6 +1017,16 @@ deqp_khr_common_sources = [ "$deqp_path/external/openglcts/modules/common/glcViewportArrayTests.cpp", "$deqp_path/external/openglcts/modules/common/glcViewportArrayTests.hpp", "$deqp_path/external/openglcts/modules/common/glcWaiver.hpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderApiTests.cpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderApiTests.hpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderPropertyTests.cpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderPropertyTests.hpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderSmokeTests.cpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderSmokeTests.hpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderTests.cpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderTests.hpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderTestsUtils.cpp", + "$deqp_path/external/openglcts/modules/common/meshShader/glcMeshShaderTestsUtils.hpp", "$deqp_path/external/openglcts/modules/common/subgroups/glcSubgroupsArithmeticTests.cpp", "$deqp_path/external/openglcts/modules/common/subgroups/glcSubgroupsArithmeticTests.hpp", "$deqp_path/external/openglcts/modules/common/subgroups/glcSubgroupsBallotBroadcastTests.cpp", @@ -1093,6 +1105,8 @@ deqp_khr_gl_sources = [ "$deqp_path/external/openglcts/modules/gl/gl3cPrimitiveRestart.cpp", "$deqp_path/external/openglcts/modules/gl/gl3cPrimitiveRestart.hpp", "$deqp_path/external/openglcts/modules/gl/gl3cTestPackages.cpp", + "$deqp_path/external/openglcts/modules/gl/gl3cTextureFilterMinmaxTests.cpp", + "$deqp_path/external/openglcts/modules/gl/gl3cTextureFilterMinmaxTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl3cTextureSizePromotion.cpp", "$deqp_path/external/openglcts/modules/gl/gl3cTextureSizePromotion.hpp", "$deqp_path/external/openglcts/modules/gl/gl3cTextureSwizzleTests.cpp", @@ -1111,10 +1125,14 @@ deqp_khr_gl_sources = [ "$deqp_path/external/openglcts/modules/gl/gl4cComputeShaderTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cConditionalRenderInvertedTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl4cConditionalRenderInvertedTests.hpp", + "$deqp_path/external/openglcts/modules/gl/gl4cTextureBufferTests.cpp", + "$deqp_path/external/openglcts/modules/gl/gl4cTextureBufferTests.hpp", # These tests are also disabled in the dEQP CMake build. # "$deqp_path/external/openglcts/modules/gl/gl4cContextFlushControlTests.cpp", # "$deqp_path/external/openglcts/modules/gl/gl4cContextFlushControlTests.hpp", + "$deqp_path/external/openglcts/modules/gl/gl4cClearTexImageAndSubImageTests.cpp", + "$deqp_path/external/openglcts/modules/gl/gl4cClearTexImageAndSubImageTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cCopyImageTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl4cCopyImageTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cDirectStateAccessBuffersTests.cpp", @@ -1192,10 +1210,12 @@ deqp_khr_gl_sources = [ "$deqp_path/external/openglcts/modules/gl/gl4cTestPackages.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cTextureBarrierTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl4cTextureBarrierTests.hpp", - "$deqp_path/external/openglcts/modules/gl/gl4cTextureFilterMinmaxTests.cpp", - "$deqp_path/external/openglcts/modules/gl/gl4cTextureFilterMinmaxTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cTextureGatherTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl4cTextureGatherTests.hpp", + "$deqp_path/external/openglcts/modules/gl/gl4cTextureQueryLevelsTests.cpp", + "$deqp_path/external/openglcts/modules/gl/gl4cTextureQueryLevelsTests.hpp", + "$deqp_path/external/openglcts/modules/gl/gl4cTextureQueryLodTests.cpp", + "$deqp_path/external/openglcts/modules/gl/gl4cTextureQueryLodTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cTextureViewTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl4cTextureViewTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl4cVertexAttrib64BitTest.cpp", diff --git a/src/tests/deqp_support/deqp_egl_test_expectations.txt b/src/tests/deqp_support/deqp_egl_test_expectations.txt index 7780d1577cb..457b4b52f1c 100644 --- a/src/tests/deqp_support/deqp_egl_test_expectations.txt +++ b/src/tests/deqp_support/deqp_egl_test_expectations.txt @@ -109,6 +109,7 @@ // New failures when upgrading to Ubuntu 22/newer driver. 362486580 LINUX NVIDIA VULKAN : dEQP-EGL.functional.mutable_render_buffer.basic = FAIL 362486580 LINUX NVIDIA VULKAN : dEQP-EGL.functional.mutable_render_buffer.querySurface = FAIL +362486580 LINUX NVIDIA VULKAN : dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.*.local_array.* = SKIP // Mac failures 42261255 MAC : dEQP-EGL.functional.negative_api.copy_buffers = FAIL @@ -165,6 +166,10 @@ b/286921997 SWIFTSHADER : dEQP-EGL.functional.robustness.reset_context.shaders.o // Samsung Galaxy S22 (Xclipse) b/267953710 GALAXYS22 VULKAN : dEQP-EGL.functional.wide_color.window_*_colorspace_srgb = SKIP +// Samsung Galaxy S24 (Xclipse) +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-EGL.functional.wide_color.window_8888_colorspace_srgb = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-EGL.functional.wide_color.window_888_colorspace_srgb = SKIP + // Snapdragon 8 Gen3 Mobile Reference Device b/328156792 PINEAPPLE VULKAN : dEQP-EGL.functional.*.other = SKIP b/328156792 PINEAPPLE VULKAN : dEQP-EGL.functional.image.modify.renderbuffer_stencil_renderbuffer_clear_stencil = SKIP diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt index 123e1ef4e30..065a5a830d5 100644 --- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt @@ -222,6 +222,22 @@ 42263733 MAC OPENGL AMD : dEQP-GLES2.functional.shaders.fragdata.* = FAIL 42263733 MAC OPENGL AMD : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.* = FAIL +// Apple M2 +42266214 MAC APPLE : dEQP-GLES2.functional.shaders.indexing.tmp_array.float_const_write_dynamic_* = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_linear_clamp = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_nearest_clamp = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_nearest_mirror = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_nearest_repeat = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES2.functional.texture.mipmap.2d.projected.nearest_nearest_mirror = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES2.functional.texture.mipmap.cube.projected.nearest_linear = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_linear_clamp = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_linear_repeat = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_nearest_clamp = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_nearest_mirror = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.linear_nearest_repeat = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.nearest_linear_repeat = FAIL +42266214 MAC APPLE WGPU : dEQP-GLES2.functional.texture.mipmap.2d.projected.nearest_nearest_mirror = FAIL + // D3D11 AMD already covered by Line 148 42261921 D3D11 INTEL : dEQP-GLES2.functional.texture.mipmap.cube.basic.linear_nearest = FAIL 42261921 D3D11 INTEL : dEQP-GLES2.functional.texture.mipmap.cube.basic.linear_linear = FAIL @@ -258,6 +274,9 @@ 40644666 VULKAN LINUX NVIDIA : dEQP-GLES2.functional.shaders.invariance.mediump.subexpression_precision_lowp = FAIL // New failures when upgrading to Ubuntu 22/newer driver 535.183.01. 362486580 VULKAN LINUX NVIDIA : dEQP-GLES2.functional.texture.completeness.cube.npot_mirrored_repeat = FAIL +362486580 VULKAN LINUX NVIDIA : dEQP-GLES2.functional.texture.completeness.cube.npot_s_repeat = FAIL +362486580 VULKAN LINUX NVIDIA : dEQP-GLES2.functional.texture.completeness.cube.npot_t_repeat = FAIL +362486580 VULKAN LINUX NVIDIA : dEQP-GLES2.functional.texture.filtering.cube.linear_mipmap_linear_linear_clamp_etc1 = FAIL 362486580 VULKAN LINUX NVIDIA : dEQP-GLES2.functional.texture.filtering.cube.linear_mipmap_linear_nearest_clamp_etc1 = FAIL // Fails on 431.02 NVIDIA driver 40644697 VULKAN WIN NVIDIA : dEQP-GLES2.functional.fbo.render.repeated_clear.* = FAIL @@ -331,12 +350,16 @@ 42264522 PIXEL4ORXL VULKAN : dEQP-GLES2.functional.fragment_ops.random.77* = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES2.functional.fragment_ops.random.82* = SKIP 42267039 PIXEL4ORXL VULKAN : dEQP-GLES2.functional.texture.mipmap.cube.projected.nearest_linear = SKIP +428802465 PIXEL4ORXL VULKAN : dEQP-GLES2.functional.negative_api.texture.generatemipmap_zero_level_array_compressed = FAIL 42265027 PIXEL4ORXL GLES : dEQP-GLES2.functional.shaders.struct.uniform.sampler_in_array_function_arg_vertex = FAIL 42265027 PIXEL4ORXL GLES : dEQP-GLES2.functional.shaders.struct.uniform.sampler_in_function_arg_vertex = FAIL 42266310 PIXEL4ORXL GLES : dEQP-GLES2.functional.shaders.function.global_variable_aliasing_* = FAIL 42267039 PIXEL4ORXL GLES : dEQP-GLES2.functional.texture.mipmap.cube.projected.nearest_linear = FAIL +// Pixel 6 test expectations. +428802465 PIXEL6 VULKAN : dEQP-GLES2.functional.negative_api.texture.generatemipmap_zero_level_array_compressed = FAIL + 42265203 LINUX NVIDIA GTX1660 VULKAN : dEQP-GLES2.functional.shaders.random.all_features.fragment.13 = FAIL 42265203 LINUX NVIDIA GTX1660 VULKAN : dEQP-GLES2.functional.shaders.random.all_features.fragment.26 = FAIL 42265203 LINUX NVIDIA GTX1660 VULKAN : dEQP-GLES2.functional.shaders.random.all_features.fragment.31 = FAIL @@ -378,16 +401,6 @@ 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 -42267264 : dEQP-GLES2.functional.fbo.completeness.renderable.renderbuffer*bgra = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.color*bgra* = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.depth*bgra* = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.*_colorbuffer*bgra* = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.*_depthbuffer*bgra* = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.*_stencilbuffer*bgra* = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.resize*bgra* = FAIL -42267264 : dEQP-GLES2.functional.fbo.render.stencil*bgra* = FAIL - // WebGPU failures // These tests fail because the WGSL translator doesn't know what to do with matrix attributes yet. 42267100 WGPU : dEQP-GLES2.functional.attribute_location.bind_relink_hole.mat* = FAIL @@ -402,7 +415,8 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.uniform_api.value.assigned. // These tests crash because redeclarations of gl_ variables as invariant are not yet supported in the WGSL translator. 42267100 WGPU : dEQP-GLES2.functional.shaders.invariance.* = SKIP // Other WebGPU failures. -356399840 WGPU : dEQP-GLES2.functional.buffer.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.buffer.write.use.index_array.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.buffer.write.random.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.clipping.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.color_clear.*complex* = FAIL 356399840 WGPU : dEQP-GLES2.functional.color_clear.*masked* = FAIL @@ -410,7 +424,6 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.uniform_api.value.assigned. 356399840 WGPU : dEQP-GLES2.functional.default_vertex_attrib.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.depth_range.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.depth_stencil_clear.* = FAIL -356399840 WGPU : dEQP-GLES2.functional.dither.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.draw.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.fbo.api.attachment_query_tex2d = FAIL 356399840 WGPU : dEQP-GLES2.functional.fbo.api.delete_tex_2d_attached_to_bound_fbo = FAIL @@ -421,7 +434,7 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.uniform_api.value.assigned. 370690274 WGPU : dEQP-GLES2.functional.fragment_ops.depth.* = FAIL 370690274 WGPU : dEQP-GLES2.functional.fragment_ops.stencil.* = FAIL 370690274 WGPU : dEQP-GLES2.functional.fragment_ops.depth_stencil.* = FAIL -370690274 WGPU : dEQP-GLES2.functional.fragment_ops.scissor.* = FAIL +370690274 WGPU : dEQP-GLES2.functional.fragment_ops.scissor.clear_* = FAIL 356399840 WGPU : dEQP-GLES2.functional.fragment_ops.blend.*constant_alpha* = FAIL 370690274 WGPU MAC INTEL : dEQP-GLES2.functional.fragment_ops.blend.* = FAIL 370690274 WGPU : dEQP-GLES2.functional.fragment_ops.random.* = FAIL @@ -431,9 +444,67 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.uniform_api.value.assigned. 356399840 WGPU : dEQP-GLES2.functional.lifetime.attach.deleted_output.renderbuffer_framebuffer = FAIL 356399840 WGPU : dEQP-GLES2.functional.negative_api.texture.generatemipmap_npot_wdt_hgt = FAIL 356399840 WGPU : dEQP-GLES2.functional.polygon_offset.* = FAIL -356399840 WGPU : dEQP-GLES2.functional.rasterization.* = FAIL -356399840 WGPU : dEQP-GLES2.functional.shaders.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.rasterization.primitives.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.rasterization.culling.*triangle_fan* = FAIL +356399840 WGPU : dEQP-GLES2.functional.rasterization.culling.*both_triangle* = FAIL +356399840 WGPU : dEQP-GLES2.functional.rasterization.interpolation.*triangle_fan* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.builtin_variable.depth_range* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.builtin_variable.fragcoord_xyz = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.builtin_variable.frontfacing = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.builtin_variable.pointcoord = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.conditionals.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.constant_expressions.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.constants.bool_* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.conversions.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.discard.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.fragdata.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.function.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.array_arguments.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.control_flow.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.datatypes.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.declarations.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.misc.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.overloading.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.functions.qualifiers.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.indexing.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.linkage.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.loops.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.matrix.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.misc.compound_assignment.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.operator.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.qualification_order.parameters.valid.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.random.comparison_ops.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.random.conditionals.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.random.texture.vertex.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.random.all_features.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.scoping.valid.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.struct.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.swizzles.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.shaders.texture_functions.vertex.* = FAIL 356399840 WGPU : dEQP-GLES2.functional.state_query.shader.uniform_value_* = FAIL -356399840 WGPU : dEQP-GLES2.functional.texture.* = FAIL +// Unfortunately Intel and AMD GPUs on Mac fail texture filtering tests. +389145696 WGPU MAC INTEL : dEQP-GLES2.functional.texture.filtering.2d.* = FAIL +389145696 WGPU MAC AMD : dEQP-GLES2.functional.texture.filtering.2d.* = FAIL +// 2D filtering tests pass but cube textures do not work yet. +389145696 WGPU : dEQP-GLES2.functional.texture.filtering.cube.* = SKIP +// Except luminance format doesn't work +389145696 WGPU : dEQP-GLES2.functional.texture.filtering.2d.*_l8* = FAIL +389145696 WGPU : dEQP-GLES2.functional.texture.wrap.*_l8* = FAIL +// Cube textures not yet supported +389145696 WGPU : dEQP-GLES2.functional.texture.mipmap.cube.* = SKIP +// Mipmap generation not supported +389145696 WGPU : dEQP-GLES2.functional.texture.mipmap.2d.generate.* = SKIP +389145696 WGPU : dEQP-GLES2.functional.texture.format.* = SKIP +389145696 WGPU : dEQP-GLES2.functional.texture.size.* = SKIP +389145696 WGPU : dEQP-GLES2.functional.texture.specification.* = SKIP +389145696 WGPU : dEQP-GLES2.functional.texture.completeness.* = SKIP +389145696 WGPU : dEQP-GLES2.functional.texture.vertex.* = SKIP 356399840 WGPU : dEQP-GLES2.functional.uniform_api.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.uniform_api.*.bool_* = FAIL +356399840 WGPU : dEQP-GLES2.functional.uniform_api.value.*.render.* = FAIL +356399840 WGPU : dEQP-GLES2.functional.uniform_api.random.* = FAIL 392542001 WGPU : dEQP-GLES2.functional.vertex_arrays.multiple_attributes* = FAIL + +// Translator IR failures +// The workaround in b/274859104 is not applied because the IR does not generate non-constant initializers +274859104 IR PIXEL6 VULKAN : dEQP-GLES2.functional.shaders.algorithm.rgb_to_hsl_vertex = SKIP diff --git a/src/tests/deqp_support/deqp_gles31_multisample_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_multisample_test_expectations.txt index 09ecdb2b00d..8385f6813c9 100644 --- a/src/tests/deqp_support/deqp_gles31_multisample_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles31_multisample_test_expectations.txt @@ -31,4 +31,12 @@ b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_ b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.default_framebuffer = SKIP b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.default_framebuffer = SKIP b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_sample.default_framebuffer = SKIP -b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_two_samples.default_framebuffer = SKIP \ No newline at end of file +b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_two_samples.default_framebuffer = SKIP + +// Samsung Galaxy S24 (Xclipse) +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.default_framebuffer_color = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.default_framebuffer_discard = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.default_framebuffer = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.default_framebuffer = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_sample.default_framebuffer = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_two_samples.default_framebuffer = SKIP diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_test_expectations.txt index 9789d27808e..cfa88517b02 100644 --- a/src/tests/deqp_support/deqp_gles31_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles31_test_expectations.txt @@ -11,91 +11,9 @@ // Crashing Tests 42260436 OPENGL : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.resource_list.vertex_fragment.builtin_gl_position = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32f_rgba8ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32f_rgba8i = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32f_rgba8 = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32f_rgba8_snorm = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8ui_r32f = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8ui_r32ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8ui_r32i = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32ui_rgba8ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32ui_rgba8i = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32ui_rgba8 = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32ui_rgba8_snorm = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8i_r32f = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8i_r32ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8i_r32i = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32i_rgba8ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32i_rgba8i = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32i_rgba8 = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.r32i_rgba8_snorm = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8_r32f = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8_r32ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8_r32i = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8_snorm_r32f = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8_snorm_r32ui = SKIP -42260436 D3D11 : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.rgba8_snorm_r32i = SKIP -42265815 D3D11 : dEQP-GLES31.functional.image_load_store.*.qualifiers.* = SKIP - -// D3D11 Failing Tests -// Below cases are failed due to binding multi-UAVs to a single buffer is not supported in D3D backend. -// http://anglebug.com/42261718 -42261718 D3D11 : dEQP-GLES31.functional.ssbo.layout.*.single_buffer* = FAIL -42261718 D3D11 : dEQP-GLES31.functional.ssbo.layout.random.all_shared_buffer* = FAIL - -42260436 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counters_* = FAIL -42260436 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_size_* = FAIL -42260436 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_atomic_counters* = FAIL -42260436 D3D11 : dEQP-GLES31.functional.state_query.integer.max_uniform_buffer_bindings_* = FAIL -42260436 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_texture_image_units_* = FAIL -42260436 D3D11 : dEQP-GLES31.functional.state_query.program.compute_work_group_size_get_programiv = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.async.case_4_log = SKIP -42260436 D3D11 : dEQP-GLES31.functional.debug.async.case_5_callback = SKIP -42260436 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_2 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_3 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_9 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_10 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_27 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_28 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_2 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_3 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_9 = FAIL -42260436 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_10 = FAIL - -42260728 D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.*geometry = FAIL -42260728 D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.*geometry = FAIL -42260728 D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.*geometry = FAIL -42260728 D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.geometry_shader.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.state_query.program.geometry_shader_state_get_programiv = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.query.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.basic.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.conversion.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.emit.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.varying.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.layered.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.instanced.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.input.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.negative.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.geometry_shading.vertex_transform_feedback.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.shaders.linkage.es31.geometry.* = FAIL -42260728 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.geometry_shader = FAIL -42260728 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.geometry_shader = FAIL -42260728 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.geometry_shader = FAIL -42261528 D3D11 : dEQP-GLES31.functional.texture.gather.basic.cube.rgba8.texture_swizzle.* = FAIL -42261528 D3D11 : dEQP-GLES31.functional.texture.gather.basic.cube.rgba8i.* = FAIL -42261528 D3D11 : dEQP-GLES31.functional.texture.gather.basic.cube.rgba8ui.* = FAIL -42262509 D3D11 : dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_large = FAIL -42262509 D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_large = FAIL - // Failing with dEQP roll -42262109 D3D11 : dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.22 = FAIL -42262109 D3D11 : dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.41 = FAIL -42262862 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = SKIP 42262862 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = SKIP -42262862 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = SKIP 42262862 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = SKIP -42262862 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.renderbuffer_storage_multisample = FAIL -42262862 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = SKIP 42262862 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = SKIP // OpenGL Passing tests. @@ -127,30 +45,9 @@ b/266710445 WIN OPENGL NVIDIA : dEQP-GLES31.functional.image_load_store.buffer.a // OpenGL/D3D11 Failing Tests 42260436 OPENGL : dEQP-GLES31.functional.shaders.opaque_type_indexing.* = FAIL -42260436 OPENGL : dEQP-GLES31.functional.separate_shader.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.separate_shader.* = SKIP +42260436 OPENGL : dEQP-GLES31.functional.separate_shader.* = FAIL 42260436 OPENGL : dEQP-GLES31.functional.state_query.program.program_separable_get_programiv = FAIL -42260436 OPENGL : dEQP-GLES31.functional.state_query.program_pipeline.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.state_query.program_pipeline.* = SKIP - -// These tests are failing because of compile errors with SSBOs in compute shaders. - -42260436 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP -// TODO(xinghua.cao@intel.com): FAIL expectation instead of SKIP should be sufficient for OpenGL, but the -// test expectations parser doesn't support having FAIL for GL and SKIP for D3D with the same test filter. - -42262961 D3D11 : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.* = SKIP -42262959 D3D11 : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_fragment.* = SKIP -42262959 D3D11 : dEQP-GLES31.functional.program_interface_query.buffer_variable.random.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.program_interface_query.program_input.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.program_interface_query.program_output.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.program_interface_query.shader_storage_block.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.program_interface_query.uniform* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.synchronization.* = SKIP -42260436 D3D11 : dEQP-GLES31.functional.layout_binding.image.* = SKIP -// This case is skipped since it uses atomic counter builtin functions which haven't been implemented. -42260658 D3D11 : dEQP-GLES31.functional.state_query.program.active_atomic_counter_buffers_get_programiv = SKIP +42260436 OPENGL : dEQP-GLES31.functional.state_query.program_pipeline.* = FAIL //// //// Failures blocking an official GLES 3.1 conformance run on SwiftShader @@ -218,7 +115,6 @@ b/266710445 WIN OPENGL NVIDIA : dEQP-GLES31.functional.image_load_store.buffer.a 42264177 NVIDIA VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgba8.cubemap_to_texture3d = SKIP // Pixel 4 expectations. -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16f.texture2d_array_to_cubemap = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16i.cubemap_to_renderbuffer = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16i.texture2d_array_to_renderbuffer = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16i.texture2d_to_renderbuffer = SKIP @@ -227,100 +123,9 @@ b/266710445 WIN OPENGL NVIDIA : dEQP-GLES31.functional.image_load_store.buffer.a 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16ui.texture2d_array_to_renderbuffer = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16ui.texture2d_to_renderbuffer = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_r16ui.texture3d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_rg8.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.rg8_snorm_rg8ui.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_r11f_g11f_b10f.texture3d_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_r32i.texture2d_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_r32ui.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_r32ui.texture2d_array_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_r32ui.texture2d_array_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rg16ui.texture3d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgb10_a2ui.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgb10_a2ui.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgb10_a2ui.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgb10_a2ui.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgb10_a2ui.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgb9_e5.cubemap_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8_snorm.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8_snorm.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8_snorm.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8_snorm.texture2d_array_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8i.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8ui.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8ui.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8ui.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_rgba8ui.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_r32i.cubemap_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_r32ui.texture3d_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rg16i.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgb10_a2ui.texture2d_array_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgb10_a2ui.texture2d_array_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgb10_a2ui.texture2d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgb9_e5.cubemap_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgb9_e5.texture2d_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgba8i.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgba8i.texture3d_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_rgba8ui.texture2d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgb10_a2ui.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgb10_a2ui.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgb10_a2ui.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgb10_a2ui.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8_snorm.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8_snorm.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8_snorm.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8i.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8ui.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8ui.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8ui.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8ui.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_rgba8ui.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32i.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32i.texture2d_array_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32i.texture2d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32i.texture3d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32ui.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32ui.texture2d_array_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32ui.texture2d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32ui.texture2d_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_r32ui.texture3d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16i.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16i.texture2d_array_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16i.texture2d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16i.texture3d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16ui.cubemap_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16ui.texture2d_array_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16ui.texture2d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16ui.texture3d_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rg16ui.texture3d_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rgba8i.texture3d_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rgba8ui.texture2d_array_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_r32ui.texture2d_array_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_r32ui.texture3d_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_rgb10_a2ui.texture3d_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_rgb9_e5.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_rgba8.texture2d_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_rgba8_snorm.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_rgba8ui.cubemap_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_srgb8_alpha8.texture2d_array_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_r32f.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rg16ui.texture2d_array_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rg16ui.texture3d_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rgb10_a2ui.texture2d_array_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rgb9_e5.texture2d_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rgba8i.texture2d_array_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rgba8i.texture3d_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_rgba8ui.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8_snorm.renderbuffer_to_cubemap = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8_snorm.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8_snorm.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8_snorm.renderbuffer_to_texture3d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgb10_a2ui.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgb10_a2ui.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8i.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8ui.renderbuffer_to_renderbuffer = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8ui.renderbuffer_to_texture2d = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8ui.renderbuffer_to_texture2d_array = SKIP -42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8ui.texture2d_to_texture2d = SKIP +440743718 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_16_bits.*.texture2d_array_to_texture3d = SKIP +440743718 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.* = SKIP +440743718 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_64_bits.*.texture2d_array_to_texture3d = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.negative.interpolate_global = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.no_qualifiers.multisample_texture_2 = SKIP 42264522 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_sample.centroid_qualified.multisample_texture_1 = SKIP @@ -461,6 +266,51 @@ b/267953710 GALAXYS22 VULKAN : dEQP-GLES31.functional.texture.border_clamp.* = S 42266598 GALAXYS23 VULKAN : dEQP-GLES31.functional.shaders.linkage.es31.geometry.varying.types.float_struct = SKIP 42266598 GALAXYS23 VULKAN : dEQP-GLES31.functional.texture.border_clamp.* = SKIP +// Samsung Galaxy S24 (Xclipse) +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.draw_indirect.random.19 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.draw_indirect.random.36 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.draw_indirect.random.42 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.draw_indirect.random.45 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.draw_indirect.random.49 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.draw_indirect.random.51 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_renderbuffer_samples_2_color = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_renderbuffer_samples_2_discard = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_renderbuffer_samples_4_color = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_renderbuffer_samples_4_discard = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_texture_samples_2_color = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_texture_samples_2_discard = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_texture_samples_4_color = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.sample_shading.min_sample_shading.multisample_texture_samples_4_discard = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.helper_invocation.derivate.lines_max_samples_dfdy = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.helper_invocation.derivate.points_8_samples_dfdy = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.helper_invocation.derivate.triangles_8_samples_fwidth = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.input_before_literal.mul.uint_to_vec3_vertex = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.input_before_literal.sub.int_to_float_vertex = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.input_before_literal.sub.uint_to_vec2_fragment = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.literal_before_input.mul.uvec3_to_vec3_vertex = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.literal_before_input.sub.uint_to_vec2_fragment = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.multisample_rbo_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.multisample_rbo_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.multisample_rbo_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.multisample_texture_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.multisample_texture_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.sample_qualifier.multisample_texture_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.multisample_rbo_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.multisample_rbo_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.multisample_rbo_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.multisample_texture_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.multisample_texture_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_id.multisample_texture_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_sample.multisample_rbo_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_sample.multisample_texture_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bits_unique_per_sample.multisample_texture_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bits_unique_per_sample.multisample_texture_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bits_unique_per_sample.multisample_texture_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bits_unique_per_two_samples.multisample_texture_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_pos.distribution.multisample_texture_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_pos.distribution.multisample_texture_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES31.functional.shaders.sample_variables.sample_pos.distribution.multisample_texture_4 = SKIP + // Snapdragon 8 Gen3 Mobile Reference Device b/328156792 PINEAPPLE VULKAN : dEQP-GLES31.functional.blend_equation_advanced.basic.hsl_hue = SKIP b/328156792 PINEAPPLE VULKAN : dEQP-GLES31.functional.blend_equation_advanced.barrier.hsl_hue = SKIP diff --git a/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_test_expectations.txt index 1864c7abb89..54ebd68fda9 100644 --- a/src/tests/deqp_support/deqp_gles3_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles3_test_expectations.txt @@ -481,6 +481,42 @@ 40096672 MAC OPENGL INTEL : dEQP-GLES3.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.14 = FAIL 40096672 MAC OPENGL INTEL : dEQP-GLES3.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.17 = FAIL +// Apple M2 +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_mag = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_mag_reverse_src_dst_x = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_mag_reverse_src_dst_y = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_x = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_y = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.completeness.attachment_combinations.none_rbo_none_none = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.fbo.completeness.attachment_combinations.none_tex_none_none = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.multisample.fbo_4_samples.proportionality_sample_coverage_inverted = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.multisample.fbo_4_samples.sample_coverage_invert = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.multisample.fbo_max_samples.proportionality_sample_coverage_inverted = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.multisample.fbo_max_samples.sample_coverage_invert = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_* = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_inout_parameter_with_index_with_side_effects_* = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.invariance.*.common_subexpression_1 = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.invariance.*.common_subexpression_2 = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.invariance.*.common_subexpression_3 = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.invariance.highp.loop_4 = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.invariance.lowp.loop_1 = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.shaders.invariance.mediump.loop_4 = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.combinations.nearest_linear_mirror_repeat = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.combinations.nearest_linear_repeat_* = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.combinations.nearest_mipmap_*repeat* = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.combinations.nearest_nearest_mirror_repeat = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.combinations.nearest_nearest_repeat_clamp = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.combinations.nearest_nearest_repeat_mirror = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.sizes.63x63_nearest_mipmap_* = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.filtering.cube.sizes.7x7_nearest = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_linear_clamp = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_nearest_clamp = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_nearest_mirror = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_nearest_repeat = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_nearest_mirror = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.3d.projected.linear_linear_clamp = FAIL +42266214 MAC APPLE OPENGL : dEQP-GLES3.functional.texture.mipmap.3d.projected.linear_linear_repeat = FAIL // Android only failures 42260746 ANDROID GLES : dEQP-GLES3.functional.occlusion_query.* = FAIL @@ -753,6 +789,8 @@ 42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.3d.min_lod.nearest_nearest = FAIL 42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.max_lod.nearest_linear = FAIL 42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.max_lod.nearest_nearest = FAIL +42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.max_lod.linear_nearest = FAIL +42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.max_lod.linear_linear = FAIL 42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.min_lod.linear_linear = FAIL 42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.min_lod.linear_nearest = FAIL 42265068 MAC METAL INTEL : dEQP-GLES3.functional.texture.mipmap.cube.min_lod.nearest_linear = FAIL @@ -832,6 +870,53 @@ b/267953710 GALAXYS22 VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attrib 42266598 GALAXYS23 VULKAN : dEQP-GLES3.functional.shaders.random.texture.* = SKIP 42266598 GALAXYS23 VULKAN : dEQP-GLES3.functional.shaders.random.trigonometric.fragment.* = SKIP +// Samsung Galaxy S24 (Xclipse) +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.draw.random.118 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.draw.random.124 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.draw.random.136 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.draw.random.138 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first24_offset16_stride32_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first24_offset16_stride32_quads5 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first24_offset16_stride8_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first24_offset16_stride8_quads5 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first6_offset16_stride32_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first6_offset16_stride32_quads5 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first6_offset16_stride8_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.first.int2_10_10_10.first6_offset16_stride8_quads5 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.normalize.int2_10_10_10.components4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.normalize.int2_10_10_10.components4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.normalize.usigned_int2_10_10_10.components4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.normalize.usigned_int2_10_10_10.components4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset32_stride32_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset32_stride32_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset32_stride4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset32_stride4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset4_stride32_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset4_stride32_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset4_stride4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.offset.int2_10_10_10.offset4_stride4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.int2_10_10_10.components4_vec2_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.int2_10_10_10.components4_vec2_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.int2_10_10_10.components4_vec3_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.int2_10_10_10.components4_vec3_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.int2_10_10_10.components4_vec4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.int2_10_10_10.components4_vec4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.usigned_int2_10_10_10.components4_vec2_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.usigned_int2_10_10_10.components4_vec2_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.usigned_int2_10_10_10.components4_vec3_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.usigned_int2_10_10_10.components4_vec3_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.usigned_int2_10_10_10.components4_vec4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.usigned_int2_10_10_10.components4_vec4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.buffer_stride16_components4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.buffer_stride16_components4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.buffer_stride32_components4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.buffer_stride32_components4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.user_ptr_stride16_components4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.user_ptr_stride16_components4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.user_ptr_stride17_components4_quads256 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.user_ptr_stride32_components4_quads1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.int2_10_10_10.user_ptr_stride32_components4_quads256 = SKIP + // Snapdragon 8 Gen3 Mobile Reference Device b/328156792 PINEAPPLE VULKAN : dEQP-GLES3.functional.fbo.blit.depth_stencil.*stencil* = SKIP b/328156792 PINEAPPLE VULKAN : dEQP-GLES3.functional.fbo.msaa.*_samples.*stencil* = SKIP @@ -869,7 +954,6 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES3.functional.uniform_api.value.assigned. 42262773 VULKAN : dEQP-GLES3.functional.transform_feedback.random.* = FAIL // BGRA failures -42267264 : dEQP-GLES3.functional.fbo.completeness.renderable.renderbuffer*bgra = FAIL 42267264 MAC : dEQP-GLES3.functional.texture.filtering.2d_array.formats.bgra* = FAIL // Tests failing on SwS due to ES 3.2 being enabled for testing regardless of support. @@ -885,3 +969,11 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES3.functional.uniform_api.value.assigned. 376899587 PIXEL4ORXL : dEQP-GLES3.functional.negative_api.vertex_array.draw_elements_instanced_incomplete_primitive = SKIP 376899587 PIXEL4ORXL : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements = SKIP 376899587 PIXEL4ORXL : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements_incomplete_primitive = SKIP + +// Translator IR failures +/// IR's use of `while` and `if (!condition) break` instead of `for(..)` makes the HLSL generator think the loops are discontinous, and as a result it drops the derivative built-ins! +349994211 IR D3D11 NVIDIA : dEQP-GLES3.functional.shaders.derivate.*_loop* = SKIP +// Untriaged failures with HLSL +349994211 IR D3D11 NVIDIA : dEQP-GLES3.functional.shaders.switch.default_label_static_* = SKIP +349994211 IR D3D11 NVIDIA : dEQP-GLES3.functional.shaders.switch.default_not_last_static_* = SKIP +349994211 IR D3D11 NVIDIA : dEQP-GLES3.functional.shaders.switch.if_in_switch_static_* = SKIP diff --git a/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt index 1e717907b12..5660c7b5a34 100644 --- a/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt +++ b/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt @@ -70,6 +70,7 @@ 362486580 LINUX NVIDIA VULKAN : KHR-GLES31.core.pixelstoragemodes.teximage3d.rgb10a2.16_16_1 = FAIL 362486580 LINUX NVIDIA VULKAN : KHR-GLES31.core.tessellation_shader.tessellation_shader_tessellation.max_in_out_attributes = SKIP 362486580 LINUX NVIDIA VULKAN : KHR-GLES31.core.texture_cube_map_array.image_op_fragment_sh = FAIL +362486580 LINUX NVIDIA VULKAN : KHR-GLES31.core.texture_cube_map_array.image_op_compute_sh = SKIP //// //// SwANGLE expectations @@ -354,6 +355,61 @@ b/267953710 GALAXYS22 VULKAN : KHR-GLES31.core.vertex_attrib_binding.basic-input 42266598 GALAXYS23 VULKAN : KHR-GLES31.core.texture_cube_map_array.color_depth_attachments = SKIP 42266598 GALAXYS23 VULKAN : KHR-GLES31.core.texture_storage_multisample.FunctionalTests.blitting_multisampled_depth_attachment = SKIP +// Samsung Galaxy S24 +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba32f.full = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba32f.half = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba8.full = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba8.half = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba8i.full = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba8i.half = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba8ui.full = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_shading.render.rgba8ui.half = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_variables.position.fixed.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_variables.position.fixed.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_variables.position.non-fixed.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.sample_variables.position.non-fixed.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba32f.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba32f.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba8.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba8.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba8i.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba8i.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba8ui.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset.rgba8ui.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba32f.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba32f.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba8.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba8.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba8i.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba8i.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba8ui.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_offset_check.rgba8ui.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba32f.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba32f.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba8.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba8.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba8i.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba8i.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba8ui.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample.rgba8ui.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba32f.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba32f.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba8.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba8.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba8i.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba8i.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba8ui.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.interpolate_at_sample_check.rgba8ui.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba32f.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba32f.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba8.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba8.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba8i.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba8i.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba8ui.samples_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.shader_multisample_interpolation.render.sample.rgba8ui.samples_4 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES31.core.texture_stencil8.multisample = SKIP + // Snapdragon 8 Gen3 Mobile Reference Device b/328156792 PINEAPPLE VULKAN : KHR-GLES31.core.blend_equation_advanced.blend* = SKIP b/328156792 PINEAPPLE VULKAN : KHR-GLES31.core.blend_equation_advanced.test_coherency.mixedSequence = SKIP 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 f3d4e7bd615..076e8ddb85b 100644 --- a/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt +++ b/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt @@ -87,6 +87,7 @@ 42264540 VULKAN NVIDIA LINUX : KHR-GLES32.core.framebuffer_completeness.cube_map_layered_attachment_valid_size_and_format = SKIP // New failures when upgrading to Ubuntu 22/newer driver. +362486580 VULKAN LINUX NVIDIA : KHR-GLES32.core.draw_buffers_indexed.blending = FAIL 362486580 VULKAN LINUX NVIDIA : KHR-GLES32.core.draw_buffers_indexed.color_masks = SKIP 362486580 VULKAN LINUX NVIDIA : KHR-GLES32.core.texture_cube_map_array.image_op_compute_sh = FAIL 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 3c9e0efcd93..9934d4f65e0 100644 --- a/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt +++ b/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt @@ -71,6 +71,10 @@ 40096882 VULKAN NVIDIA : KHR-GLES3.packed_pixels.rectangle.rg8_snorm = SKIP 40096882 VULKAN NVIDIA : KHR-GLES3.packed_pixels.rectangle.rgba8_snorm = SKIP +// Failures related to clip/cull distance in geometry/tessellation shaders +42264006 VULKAN : KHR-GLES3.cull_distance.functional_test_item_5_* = SKIP +42264006 VULKAN : KHR-GLES3.cull_distance.functional_test_item_6_* = SKIP + // New failures with latest dEQP roll (2020-04-28) 42263198 SWIFTSHADER : KHR-GLES3.core.nearest_edge.offset_left = FAIL @@ -87,6 +91,15 @@ b/267953710 GALAXYS22 VULKAN : KHR-GLES3.framebuffer_blit.scissor_blit = FAIL 42266598 GALAXYS23 VULKAN : KHR-GLES3.shaders.function.global_variable_aliasing_fragment = SKIP 341780527 GALAXYS23 VULKAN : KHR-GLES3.clip_distance.coverage = FAIL +// Samsung Galaxy S24 (Xclipse) +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.clip_distance.coverage = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.cull_distance.functional_test_item_8_primitive_mode_points_max_culldist_1 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.cull_distance.functional_test_item_8_primitive_mode_points_max_culldist_2 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.cull_distance.functional_test_item_8_primitive_mode_points_max_culldist_3 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.cull_distance.functional_test_item_8_primitive_mode_points_max_culldist_5 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.cull_distance.functional_test_item_8_primitive_mode_points_max_culldist_6 = SKIP +b/410630704 GALAXYS24EXYNOS VULKAN : KHR-GLES3.cull_distance.functional_test_item_8_primitive_mode_points_max_culldist_7 = SKIP + // Snapdragon 8 Gen3 Mobile Reference Device b/328156792 PINEAPPLE VULKAN : KHR-GLES3.copy_tex_image_conversions.required.* = SKIP b/328156792 PINEAPPLE VULKAN : KHR-GLES3.shaders.function.global_variable_aliasing_fragment = SKIP @@ -94,21 +107,25 @@ b/328156792 PINEAPPLE VULKAN : KHR-GLES3.shaders.function.global_variable_aliasi // Mali G710 42266649 MALIG710 VULKAN : KHR-GLES3.number_parsing.* = FAIL +// Apple M2 +42266214 MAC APPLE OPENGL : KHR-GLES3.copy_tex_image_conversions.required.* = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.framebuffer_completeness.incomplete_texture_2d_mm_layer_oob = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.framebuffer_completeness.status_tracking = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.depth24_stencil8_format_depth_stencil = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.depth32f_stencil8_format_depth_stencil = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.depth_component16_format_depth_component = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.depth_component24_format_depth_component = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.rgb565_format_rgb = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.rgb5_a1_format_rgba = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.packed_pixels.*.rgba4_format_rgba = FAIL +42266214 MAC APPLE OPENGL : KHR-GLES3.texture_storage.compressed_data = FAIL + // The newly added cases are failing -42267072 ANDROID : KHR-GLES3.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singlesampled_blit = FAIL -42267072 LINUX : KHR-GLES3.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singlesampled_blit = FAIL -42267072 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 332383430 SWIFTSHADER : KHR-GLES3.texture_lod_bias.texture_lod_bias_all = TIMEOUT -353358652 VULKAN : KHR-GLES3.cull_distance.functional_test_item_5_primitive_mode_lines_max_culldist* = FAIL -353358652 VULKAN : KHR-GLES3.cull_distance.functional_test_item_5_primitive_mode_points_max_culldist* = FAIL -353358652 VULKAN : KHR-GLES3.cull_distance.functional_test_item_5_primitive_mode_triangles_max_culldist* = FAIL -353358652 VULKAN : KHR-GLES3.cull_distance.functional_test_item_6_primitive_mode_lines_max_culldist* = FAIL -353358652 VULKAN : KHR-GLES3.cull_distance.functional_test_item_6_primitive_mode_points_max_culldist* = FAIL -353358652 VULKAN : KHR-GLES3.cull_distance.functional_test_item_6_primitive_mode_triangles_max_culldist* = FAIL 353358652 SWIFTSHADER : KHR-GLES3.cull_distance.functional_test_item_*_primitive_mode_points_max_culldist_* = FAIL 355292302 : KHR-GLES3.api.coverage* = FAIL diff --git a/src/tests/deqp_support/deqp_khr_glesext_test_expectations.txt b/src/tests/deqp_support/deqp_khr_glesext_test_expectations.txt new file mode 100644 index 00000000000..20bf2272d1a --- /dev/null +++ b/src/tests/deqp_support/deqp_khr_glesext_test_expectations.txt @@ -0,0 +1,8 @@ +// Copyright 2025 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. + +// See README.md for format. + +42264522 PIXEL4ORXL VULKAN : KHR-GLESEXT.draw_elements_base_vertex_tests.valid_active_tf = SKIP + diff --git a/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp b/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp index e5c3b6276d6..5479ce433be 100644 --- a/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp +++ b/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp @@ -18,6 +18,10 @@ * */ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "egluNativeDisplay.hpp" #include "tcuANGLENativeDisplayFactory.h" @@ -218,12 +222,12 @@ NativePixmap::NativePixmap(EGLNativeDisplayType display, int width, int height, #else if (!mPixmap) { - throw ResourceError("Failed to create pixmap", DE_NULL, __FILE__, __LINE__); + throw ResourceError("Failed to create pixmap", nullptr, __FILE__, __LINE__); } if (!mPixmap->initialize(display, width, height, bitDepth)) { - throw ResourceError("Failed to initialize pixmap", DE_NULL, __FILE__, __LINE__); + throw ResourceError("Failed to initialize pixmap", nullptr, __FILE__, __LINE__); } #endif } @@ -409,12 +413,12 @@ void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const mWindow->getWidth(), mWindow->getHeight()); if (!mWindow->takeScreenshot(reinterpret_cast(dst->getAccess().getDataPtr()))) { - throw InternalError("Failed to read screen pixels", DE_NULL, __FILE__, __LINE__); + throw InternalError("Failed to read screen pixels", nullptr, __FILE__, __LINE__); } if (mPreRotation != 0) { - throw InternalError("Read screen pixels with prerotation is not supported", DE_NULL, + throw InternalError("Read screen pixels with prerotation is not supported", nullptr, __FILE__, __LINE__); } } @@ -513,7 +517,7 @@ eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay( #endif else { - throw InternalError("unsupported platform type", DE_NULL, __FILE__, __LINE__); + throw InternalError("unsupported platform type", nullptr, __FILE__, __LINE__); } } diff --git a/src/tests/deqp_support/tcuRandomOrderExecutor.cpp b/src/tests/deqp_support/tcuRandomOrderExecutor.cpp index e12968f24c5..95b20d1b394 100644 --- a/src/tests/deqp_support/tcuRandomOrderExecutor.cpp +++ b/src/tests/deqp_support/tcuRandomOrderExecutor.cpp @@ -80,7 +80,7 @@ void RandomOrderExecutor::pruneStack(size_t newStackSize) else DE_ASSERT(curEntry.children.empty()); - curEntry.node = DE_NULL; + curEntry.node = nullptr; curEntry.children.clear(); } @@ -99,7 +99,7 @@ static TestNode *findNodeByName(vector &nodes, const std::string &na return *node; } - return DE_NULL; + return nullptr; } TestCase *RandomOrderExecutor::seekToCase(const string &path) diff --git a/src/tests/deqp_support/tcuRandomOrderExecutor.h b/src/tests/deqp_support/tcuRandomOrderExecutor.h index d7433d8557b..e5e763104af 100644 --- a/src/tests/deqp_support/tcuRandomOrderExecutor.h +++ b/src/tests/deqp_support/tcuRandomOrderExecutor.h @@ -51,7 +51,7 @@ class RandomOrderExecutor TestNode *node; std::vector children; - NodeStackEntry(void) : node(DE_NULL) {} + NodeStackEntry(void) : node(nullptr) {} NodeStackEntry(TestNode *node_) : node(node_) {} }; diff --git a/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp b/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp index d13d853fea9..12e5c4ab11c 100644 --- a/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp +++ b/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp @@ -16,16 +16,6 @@ namespace angle { -namespace -{ -std::pair GetCurrentContextVersion() -{ - const char *versionString = reinterpret_cast(glGetString(GL_VERSION)); - EXPECT_TRUE(strstr(versionString, "OpenGL ES") != nullptr); - return {versionString[10] - '0', versionString[12] - '0'}; -} -} // anonymous namespace - class EGLBackwardsCompatibleContextTest : public ANGLETest<> { public: @@ -33,9 +23,9 @@ class EGLBackwardsCompatibleContextTest : public ANGLETest<> void testSetUp() override { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -95,6 +85,9 @@ class EGLBackwardsCompatibleContextTest : public ANGLETest<> // Test extension presence. All backends should expose this extension TEST_P(EGLBackwardsCompatibleContextTest, PbufferDifferentConfig) { + // The system EGL may not expose ANGLE-specific extensions, which is not a failure. + ANGLE_SKIP_TEST_IF(isDriverSystemEgl()); + EXPECT_TRUE( IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); } diff --git a/src/tests/egl_tests/EGLBlobCacheTest.cpp b/src/tests/egl_tests/EGLBlobCacheTest.cpp index c334211e7de..1a77b5dafb7 100644 --- a/src/tests/egl_tests/EGLBlobCacheTest.cpp +++ b/src/tests/egl_tests/EGLBlobCacheTest.cpp @@ -6,6 +6,10 @@ // EGLBlobCacheTest: // Unit tests for the EGL_ANDROID_blob_cache extension. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // Must be included first to prevent errors with "None". #include "test_utils/ANGLETest.h" @@ -507,7 +511,7 @@ TEST_P(EGLBlobCacheTest, ThreadSafety) // Insert a new entry into the cache unique to this thread. std::stringstream ss; ss << essl1_shaders::vs::Simple() << "//" << threadID; - std::string newEntryVSSource = ss.str().c_str(); + std::string newEntryVSSource = ss.str(); ANGLE_GL_PROGRAM(unusedProgramTemp2, newEntryVSSource.c_str(), essl1_shaders::fs::Red()); // Clean up diff --git a/src/tests/egl_tests/EGLBufferAgeTest.cpp b/src/tests/egl_tests/EGLBufferAgeTest.cpp index d914e510283..6199167ab08 100644 --- a/src/tests/egl_tests/EGLBufferAgeTest.cpp +++ b/src/tests/egl_tests/EGLBufferAgeTest.cpp @@ -7,6 +7,10 @@ // EGL extension EGL_EXT_buffer_age // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" @@ -22,9 +26,9 @@ class EGLBufferAgeTest : public ANGLETest<> void testSetUp() override { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); mMajorVersion = GetParam().majorVersion; @@ -557,6 +561,66 @@ TEST_P(EGLBufferAgeTest, UncurrentContextBadSurface) context = EGL_NO_CONTEXT; } +// Test if the content in damage region is defined +TEST_P(EGLBufferAgeTest, ValidateDamageRegion) +{ + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_partial_update")); + + EGLConfig config = EGL_NO_CONFIG_KHR; + EXPECT_TRUE(chooseConfig(&config)); + + EGLContext context = EGL_NO_CONTEXT; + EXPECT_TRUE(createContext(config, &context)); + ASSERT_EGL_SUCCESS() << "eglCreateContext failed."; + + EGLSurface surface = EGL_NO_SURFACE; + + OSWindow *osWindow = OSWindow::New(); + osWindow->initialize("EGLBufferAgeTest", 16, 16); + EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface)); + ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed."; + EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); + + EGLint age = 0; + EGLint rect[4] = {0, 0, 1, 1}; + std::vector> colors = {{1.0f, 1.0f, 1.0f, 1.0f}, + {1.0f, 0.0f, 0.0f, 1.0f}, + {0.0f, 1.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f, 1.0f}}; + + glDisable(GL_SCISSOR_TEST); + for (auto color : colors) + { + + glClearColor(color[0], color[1], color[2], color[3]); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface)); + EXPECT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); + } + + EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_KHR, &age)); + EXPECT_EGL_SUCCESS(); + EXPECT_GE(age, 0); + + eglSetDamageRegionKHR(mDisplay, surface, rect, 1); + EXPECT_EGL_SUCCESS(); + + glClearColor(1.0f, 1.0f, 0.0f, 1.0f); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + ASSERT_GL_NO_ERROR(); + + std::vector expectColorf = colors[colors.size() - age]; + GLColor expectColor(expectColorf[0] * 255, expectColorf[1] * 255, expectColorf[2] * 255, + expectColorf[3] * 255); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); + EXPECT_PIXEL_COLOR_EQ(1, 1, expectColor); +} + // Expect age always == 1 when EGL_BUFFER_PRESERVED is chosen TEST_P(EGLBufferAgeTest, BufferPreserved) { diff --git a/src/tests/egl_tests/EGLChooseConfigTest.cpp b/src/tests/egl_tests/EGLChooseConfigTest.cpp index 4c3f18a4ac3..5978b1f02df 100644 --- a/src/tests/egl_tests/EGLChooseConfigTest.cpp +++ b/src/tests/egl_tests/EGLChooseConfigTest.cpp @@ -6,6 +6,10 @@ // EGLChooseConfigTest.cpp: // Tests of proper default-value semantics for eglChooseConfig +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" @@ -136,6 +140,38 @@ TEST_P(EGLChooseConfigTest, NegativeValidationBadAttributes) } } +// Test that if all the config ID can be successfully chosen +TEST_P(EGLChooseConfigTest, ValidateConfigID) +{ + EGLDisplay display = getEGLWindow()->getDisplay(); + + EGLint nConfigs = 0; + EGLint allConfigCount = 0; + ASSERT_EGL_TRUE(eglGetConfigs(display, nullptr, 0, &nConfigs)); + ASSERT_NE(nConfigs, 0); + + std::vector allConfigs(nConfigs); + ASSERT_EGL_TRUE(eglGetConfigs(display, allConfigs.data(), nConfigs, &allConfigCount)); + ASSERT_EQ(nConfigs, allConfigCount); + + // All attributes except EGL_CONFIG_ID should be ignored when EGL_CONFIG_ID is include. + EGLint configIDAttributes[] = {EGL_CONFIG_ID, EGL_DONT_CARE, EGL_COLOR_BUFFER_TYPE, + EGL_RGB_BUFFER, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, + EGL_SURFACE_TYPE, EGL_PIXMAP_BIT, EGL_NONE}; + for (EGLConfig configs : allConfigs) + { + EGLConfig configsWithID; + EGLint configID; + EGLint configCount; + eglGetConfigAttrib(display, configs, EGL_CONFIG_ID, &configID); + configIDAttributes[1] = configID; + ASSERT_EGL_TRUE( + eglChooseConfig(display, configIDAttributes, &configsWithID, 1, &configCount)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(configCount, 1); + } +} + } // namespace angle ANGLE_INSTANTIATE_TEST(EGLChooseConfigTest, diff --git a/src/tests/egl_tests/EGLContextCompatibilityTest.cpp b/src/tests/egl_tests/EGLContextCompatibilityTest.cpp index 1100becfbc7..38e7afe9118 100644 --- a/src/tests/egl_tests/EGLContextCompatibilityTest.cpp +++ b/src/tests/egl_tests/EGLContextCompatibilityTest.cpp @@ -163,7 +163,7 @@ std::string EGLConfigName(EGLDisplay display, EGLConfig config) const std::array kContextAttribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; -class EGLContextCompatibilityTest : public ANGLETestBase, public testing::Test +class EGLContextCompatibilityTest : public ANGLETestBase { public: EGLContextCompatibilityTest(EGLint renderer) @@ -173,11 +173,11 @@ class EGLContextCompatibilityTest : public ANGLETestBase, public testing::Test void SetUp() final { ANGLETestBase::ANGLETestSetUp(); - ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr); + ASSERT_TRUE(eglGetPlatformDisplay != nullptr); - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, mRenderer, EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, mRenderer, EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); ASSERT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE); @@ -488,11 +488,11 @@ void RegisterContextCompatibilityTests() EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, }}; - LoadEntryPointsWithUtilLoader(angle::GLESDriverType::AngleEGL); + LoadEntryPointsWithUtilLoader(kDefaultGLESDriver); - if (eglGetPlatformDisplayEXT == nullptr) + if (eglGetPlatformDisplay == nullptr) { - std::cerr << "EGLContextCompatibilityTest: missing eglGetPlatformDisplayEXT\n"; + std::cerr << "EGLContextCompatibilityTest: missing eglGetPlatformDisplay\n"; return; } @@ -502,12 +502,12 @@ void RegisterContextCompatibilityTests() if (!IsPlatformAvailable(params)) continue; - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, renderer, EGL_NONE}; - EGLDisplay display = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, renderer, EGL_NONE}; + EGLDisplay display = eglGetPlatformDisplay( + GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); if (display == EGL_NO_DISPLAY) { - std::cerr << "EGLContextCompatibilityTest: eglGetPlatformDisplayEXT error\n"; + std::cerr << "EGLContextCompatibilityTest: eglGetPlatformDisplay error\n"; return; } diff --git a/src/tests/egl_tests/EGLContextPassthroughShadersTest.cpp b/src/tests/egl_tests/EGLContextPassthroughShadersTest.cpp new file mode 100644 index 00000000000..288f8283545 --- /dev/null +++ b/src/tests/egl_tests/EGLContextPassthroughShadersTest.cpp @@ -0,0 +1,235 @@ +// +// Copyright 2025 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. +// +// EGLContextPassthroughShadersTest.cpp: +// Tests of the EGL_ANGLE_create_context_passthrough_shaders extension. +// + +#include + +#include "GLES2/gl2.h" +#include "test_utils/ANGLETest.h" +#include "test_utils/angle_test_instantiate.h" +#include "test_utils/angle_test_platform.h" +#include "test_utils/gl_raii.h" +#include "util/gles_loader_autogen.h" + +using namespace angle; + +class EGLContextPassthroughShadersTest : public ANGLETest<> +{ + public: + EGLContextPassthroughShadersTest() : mDisplay(EGL_NO_DISPLAY) {} + + void testSetUp() override + { + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); + EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr) != EGL_FALSE); + + EGLint attribs[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, + EGL_PBUFFER_BIT, + EGL_NONE}; + + EGLint count = 0; + EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &mConfig, 1, &count)); + ANGLE_SKIP_TEST_IF(mConfig == EGL_NO_CONFIG_KHR); + EXPECT_GT(count, 0); + + EGLint pBufferAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE}; + mSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttribs); + EXPECT_NE(mSurface, EGL_NO_SURFACE); + } + + void testTearDown() override + { + if (mDisplay != EGL_NO_DISPLAY) + { + eglTerminate(mDisplay); + eglReleaseThread(); + mDisplay = EGL_NO_DISPLAY; + } + ASSERT_EGL_SUCCESS() << "Error during test TearDown"; + } + + bool supportsPassthroughShadersExtension() + { + return IsEGLDisplayExtensionEnabled(mDisplay, + "EGL_ANGLE_create_context_passthrough_shaders"); + } + + EGLDisplay mDisplay; + EGLConfig mConfig; + EGLSurface mSurface; +}; + +// Test creating a context with passthrough shaders enabled and verify by querying translated +// shaders source +TEST_P(EGLContextPassthroughShadersTest, CreateContext) +{ + ANGLE_SKIP_TEST_IF(!supportsPassthroughShadersExtension()); + + EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, 2, EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE, + EGL_TRUE, EGL_NONE}; + EGLContext context = eglCreateContext(mDisplay, mConfig, nullptr, ctxAttribs); + EXPECT_NE(context, EGL_NO_CONTEXT); + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, context)); + + constexpr const char kFragmentShader[] = R"( + precision highp float; + uniform sampler2D tex; + varying vec2 texcoord; + + #define TEST_MACRO_THAT_WOULD_BE_REMOVED + + void main() + { + gl_FragColor = texture2D(tex, texcoord); + } + )"; + GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFragmentShader); + + EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_translated_shader_source")); + std::array translatedSourceBuffer; + glGetTranslatedShaderSourceANGLE(shader, static_cast(translatedSourceBuffer.size()), + nullptr, translatedSourceBuffer.data()); + EXPECT_EQ(std::string(kFragmentShader), std::string(translatedSourceBuffer.data())); +} + +// Regression test for a Skia shader which had assertion failures in CollectVariables +TEST_P(EGLContextPassthroughShadersTest, ShaderRegressionTest) +{ + ANGLE_SKIP_TEST_IF(!supportsPassthroughShadersExtension()); + + EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE, + EGL_TRUE, EGL_NONE}; + EGLContext context = eglCreateContext(mDisplay, mConfig, nullptr, ctxAttribs); + EXPECT_NE(context, EGL_NO_CONTEXT); + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, context)); + + constexpr const char kVS[] = R"(#version 300 es + +precision mediump float; +precision mediump sampler2D; +const highp float PRECISION = 4.0; +const highp float MAX_FIXED_RESOLVE_LEVEL = 5.0; +const highp float MAX_FIXED_SEGMENTS = 32.0; +uniform highp vec4 sk_RTAdjust; +uniform highp vec4 uaffineMatrix_S0; +uniform highp vec2 utranslate_S0; +in highp vec2 resolveLevel_and_idx; +in highp vec4 p01; +in highp vec4 p23; +in highp vec2 fanPointAttrib; +highp float wangs_formula_max_fdiff_p2_ff2f2f2f2f22(highp vec2 p0, highp vec2 p1, highp vec2 p2, highp vec2 p3, highp mat2 matrix) { +highp vec2 d0 = matrix * (((vec2(-2.0)) * (p1) + (p2)) + p0); +highp vec2 d1 = matrix * (((vec2(-2.0)) * (p2) + (p3)) + p1); +return max(dot(d0, d0), dot(d1, d1)); +} +highp float wangs_formula_conic_p2_fff2f2f2f(highp float _precision_, highp vec2 p0, highp vec2 p1, highp vec2 p2, highp float w) { +highp vec2 C = (min(min(p0, p1), p2) + max(max(p0, p1), p2)) * 0.5; +p0 -= C; +p1 -= C; +p2 -= C; +highp float m = sqrt(max(max(dot(p0, p0), dot(p1, p1)), dot(p2, p2))); +highp vec2 dp = ((vec2(-2.0 * w)) * (p1) + (p0)) + p2; +highp float dw = abs(((-2.0) * (w) + (2.0))); +highp float rp_minus_1 = max(0.0, ((m) * (_precision_) + (-1.0))); +highp float numer = length(dp) * _precision_ + rp_minus_1 * dw; +highp float denom = 4.0 * min(w, 1.0); +return numer / denom; +} +void main() { +highp mat2 AFFINE_MATRIX = mat2(uaffineMatrix_S0.xy, uaffineMatrix_S0.zw); +highp vec2 TRANSLATE = utranslate_S0; +highp float resolveLevel = resolveLevel_and_idx.x; +highp float idxInResolveLevel = resolveLevel_and_idx.y; +highp vec2 localcoord; +if (resolveLevel < 0.0) { +localcoord = fanPointAttrib; +} else { +if (isinf(p23.z)) { +localcoord = resolveLevel != 0.0 ? p01.zw : (idxInResolveLevel != 0.0 ? p23.xy : p01.xy); +} else { +highp vec2 p0 = p01.xy; +highp vec2 p1 = p01.zw; +highp vec2 p2 = p23.xy; +highp vec2 p3 = p23.zw; +highp float w = -1.0; +highp float maxResolveLevel; +if (isinf(p23.w)) { +w = p3.x; +highp float _0_n2 = wangs_formula_conic_p2_fff2f2f2f(PRECISION, AFFINE_MATRIX * p0, AFFINE_MATRIX * p1, AFFINE_MATRIX * p2, w); +maxResolveLevel = ceil(log2(max(_0_n2, 1.0)) * 0.5); +p1 *= w; +p3 = p2; +} else { +highp float _1_m = wangs_formula_max_fdiff_p2_ff2f2f2f2f22(p0, p1, p2, p3, AFFINE_MATRIX); +maxResolveLevel = ceil(log2(max(9.0 * _1_m, 1.0)) * 0.25); +} +if (resolveLevel > maxResolveLevel) { +idxInResolveLevel = floor(idxInResolveLevel * exp2(maxResolveLevel - resolveLevel)); +resolveLevel = maxResolveLevel; +} +highp float fixedVertexID = floor(0.5 + idxInResolveLevel * exp2(MAX_FIXED_RESOLVE_LEVEL - resolveLevel)); +if (0.0 < fixedVertexID && fixedVertexID < MAX_FIXED_SEGMENTS) { +highp float T = fixedVertexID * 0.03125; +highp vec2 ab = mix(p0, p1, T); +highp vec2 bc = mix(p1, p2, T); +highp vec2 cd = mix(p2, p3, T); +highp vec2 abc = mix(ab, bc, T); +highp vec2 bcd = mix(bc, cd, T); +highp vec2 abcd = mix(abc, bcd, T); +highp float u = mix(1.0, w, T); +highp float v = (w + 1.0) - u; +highp float uv = mix(u, v, T); +localcoord = w < 0.0 ? abcd : abc / uv; +} else { +localcoord = fixedVertexID == 0.0 ? p0 : p3; +} +} +} +highp vec2 vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE; +gl_Position = vec4(vertexpos, 0.0, 1.0); +gl_Position = vec4(gl_Position.xy * sk_RTAdjust.xz + gl_Position.ww * sk_RTAdjust.yw, 0.0, gl_Position.w); +} +)"; + + constexpr const char kFS[] = R"(#version 300 es +precision highp float; +out vec4 my_FragColor; +void main() +{ + my_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLContextPassthroughShadersTest); +ANGLE_INSTANTIATE_TEST(EGLContextPassthroughShadersTest, + WithNoFixture(ES2_D3D9()), + WithNoFixture(ES2_D3D11()), + WithNoFixture(ES2_OPENGL()), + WithNoFixture(ES2_OPENGLES()), + WithNoFixture(ES2_VULKAN()), + WithNoFixture(ES3_D3D11()), + WithNoFixture(ES3_OPENGL()), + WithNoFixture(ES3_OPENGLES()), + WithNoFixture(ES3_VULKAN())); diff --git a/src/tests/egl_tests/EGLContextSharingTest.cpp b/src/tests/egl_tests/EGLContextSharingTest.cpp index 99d7797d91c..0db19320995 100644 --- a/src/tests/egl_tests/EGLContextSharingTest.cpp +++ b/src/tests/egl_tests/EGLContextSharingTest.cpp @@ -6,6 +6,10 @@ // EGLContextSharingTest.cpp: // Tests relating to shared Contexts. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/tls.h" @@ -411,7 +415,7 @@ TEST_P(EGLContextSharingTest, DisplayShareGroupReleaseShareGroupThatOwnsStagedUp // Tests that after creating a texture using EGL_ANGLE_display_texture_share_group, // and use it for sampling, and then deleting the Context (which destroys shareGroup) works. If // anything cached in ShareGroup, it should be handled nicely if texture can outlive ShareGroup (for -// example, bugs like angleproject:7466). +// example, bugs like http://anglebug.com/42265935). TEST_P(EGLContextSharingTest, DisplayShareGroupReleaseShareGroupThenDestroyTexture) { EGLDisplay display = getEGLWindow()->getDisplay(); @@ -903,9 +907,9 @@ TEST_P(EGLContextSharingTest, UnmakeFromCurrentOnThreadExit) // Test that an inactive but alive thread doesn't prevent memory cleanup. TEST_P(EGLContextSharingTestNoFixture, InactiveThreadDoesntPreventCleanup) { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), - EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, GetParam().getDeviceType(), - EGL_NONE}; + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, GetParam().getDeviceType(), + EGL_NONE}; // Synchronization tools to ensure the two threads are interleaved as designed by this test. std::mutex mutex; @@ -929,8 +933,8 @@ TEST_P(EGLContextSharingTestNoFixture, InactiveThreadDoesntPreventCleanup) ASSERT_TRUE(threadSynchronization.waitForStep(Step::Start)); - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -1008,8 +1012,8 @@ TEST_P(EGLContextSharingTestNoFixture, EglTerminateMultiThreaded) // B: eglTerminate() <<--- this release context A // Thread A: eglMakeCurrent(context B) - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -1063,8 +1067,8 @@ TEST_P(EGLContextSharingTestNoFixture, EglTerminateMultiThreaded) ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1Terminate)); // First Display was terminated, so we need to create a new one to create a new Context. - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); config = EGL_NO_CONFIG_KHR; @@ -1126,8 +1130,8 @@ TEST_P(EGLContextSharingTestNoFixture, EglTerminateMultiThreaded) // errors. TEST_P(EGLContextSharingTestNoFixture, EglDestoryContextManyTimesSameContext) { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -1181,8 +1185,8 @@ TEST_P(EGLContextSharingTestNoFixture, EglDestoryContextManyTimesSameContext) ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1Terminate)); // First Display was terminated, so we need to create a new one to create a new Context. - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); config = EGL_NO_CONFIG_KHR; @@ -1262,8 +1266,8 @@ TEST_P(EGLContextSharingTestNoFixture, EglTerminateMultipleTimes) // eglDestroySurface(srf1) // eglTerminate(shared-display) - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -1305,8 +1309,8 @@ TEST_P(EGLContextSharingTestNoFixture, EglTerminateMultipleTimes) // Test that we can eglSwapBuffers in one thread while another thread renders to a texture. TEST_P(EGLContextSharingTestNoFixture, SwapBuffersShared) { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -1576,7 +1580,7 @@ TEST_P(EGLContextSharingTestNoSyncTextureUploads, NoSync) TEST_P(EGLContextSharingTestNoFixture, ImmediateContextDestroyAfterCreation) { EGLAttrib dispattrs[3] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); @@ -1592,6 +1596,97 @@ TEST_P(EGLContextSharingTestNoFixture, ImmediateContextDestroyAfterCreation) EXPECT_TRUE(SafeDestroyContext(mDisplay, mContexts[0])); ASSERT_EGL_SUCCESS(); } + +class EGLPriorityContextSharingTestNoFixture : public EGLContextSharingTest +{ + public: + EGLPriorityContextSharingTestNoFixture() : EGLContextSharingTest() {} + + void testSetUp() override + { + mMajorVersion = GetParam().majorVersion; + EGLAttrib dispattrs[3] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), + EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); + EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); + } + + void testTearDown() override + { + ASSERT_EGL_SUCCESS() << "Error during EGLPriorityContextSharingTestNoFixture TearDown"; + } + + bool chooseConfig(EGLConfig *config) const + { + bool result = false; + EGLint count = 0; + EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT; + EGLint attribs[] = {EGL_RENDERABLE_TYPE, clientVersion, EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_PBUFFER_BIT, EGL_NONE}; + + result = eglChooseConfig(mDisplay, attribs, config, 1, &count); + EXPECT_EGL_TRUE(result && (count > 0)); + return result; + } + + EGLDisplay mDisplay = EGL_NO_DISPLAY; + const EGLint kWidth = 64; + const EGLint kHeight = 64; + EGLint mMajorVersion = 0; +}; + +// Tests that create and destroy higher priority shared context +TEST_P(EGLPriorityContextSharingTestNoFixture, MultiContextsCreateDestroy) +{ + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_IMG_context_priority")); + + EGLConfig config = EGL_NO_CONFIG_KHR; + EXPECT_TRUE(chooseConfig(&config)); + + // Initialize contexts + constexpr size_t kContextCount = 2; + + EGLSurface surface[kContextCount] = {EGL_NO_SURFACE, EGL_NO_SURFACE}; + EGLContext ctx[kContextCount] = {EGL_NO_CONTEXT, EGL_NO_CONTEXT}; + + EGLint priorities[kContextCount] = {EGL_CONTEXT_PRIORITY_LOW_IMG, + EGL_CONTEXT_PRIORITY_HIGH_IMG}; + + EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE}; + + EGLint attributes[] = {EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_NONE, EGL_NONE}; + + for (size_t t = 0; t < kContextCount; ++t) + { + surface[t] = eglCreatePbufferSurface(mDisplay, config, pbufferAttributes); + EXPECT_EGL_SUCCESS(); + + attributes[1] = priorities[t]; + + ctx[t] = eglCreateContext(mDisplay, config, t == 0 ? EGL_NO_CONTEXT : ctx[0], attributes); + EXPECT_NE(EGL_NO_CONTEXT, ctx[t]); + EXPECT_EGL_SUCCESS(); + + eglMakeCurrent(mDisplay, surface[t], surface[t], ctx[t]); + EXPECT_EGL_SUCCESS(); + } + + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + for (size_t t = 0; t < kContextCount; ++t) + { + eglDestroySurface(mDisplay, surface[t]); + eglDestroyContext(mDisplay, ctx[t]); + EXPECT_EGL_SUCCESS(); + } + + eglTerminate(mDisplay); + mDisplay = EGL_NO_DISPLAY; + ASSERT_EGL_SUCCESS(); + eglReleaseThread(); + ASSERT_EGL_SUCCESS(); +} } // anonymous namespace GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLContextSharingTest); @@ -1620,3 +1715,6 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLContextSharingTestNoSyncTexture ANGLE_INSTANTIATE_TEST(EGLContextSharingTestNoSyncTextureUploads, ES2_VULKAN().enable(Feature::ForceSubmitImmutableTextureUpdates), ES3_VULKAN().enable(Feature::ForceSubmitImmutableTextureUpdates)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPriorityContextSharingTestNoFixture); +ANGLE_INSTANTIATE_TEST(EGLPriorityContextSharingTestNoFixture, WithNoFixture(ES3_VULKAN())); diff --git a/src/tests/egl_tests/EGLCreateContextAttribsTest.cpp b/src/tests/egl_tests/EGLCreateContextAttribsTest.cpp index 775336eb1a4..8ba3d2053e5 100644 --- a/src/tests/egl_tests/EGLCreateContextAttribsTest.cpp +++ b/src/tests/egl_tests/EGLCreateContextAttribsTest.cpp @@ -22,9 +22,9 @@ class EGLCreateContextAttribsTest : public ANGLETest<> void testSetUp() override { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr) != EGL_FALSE); } @@ -33,7 +33,7 @@ class EGLCreateContextAttribsTest : public ANGLETest<> }; // Specify invalid client version in the attributes to eglCreateContext -// and verify EGL_BAD_ATTRIBUTE +// and verify EGL_BAD_MATCH TEST_P(EGLCreateContextAttribsTest, InvalidClientVersion) { EGLContext context = EGL_NO_CONTEXT; @@ -52,7 +52,7 @@ TEST_P(EGLCreateContextAttribsTest, InvalidClientVersion) EGL_NONE}; context = eglCreateContext(mDisplay, config, nullptr, contextAttribs1); EXPECT_EQ(context, EGL_NO_CONTEXT); - ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE); + ASSERT_EGL_ERROR(EGL_BAD_MATCH); // Get a 2.0/3.x compatible config EGLint cfgAttribList2[] = {EGL_RENDERABLE_TYPE, (EGL_OPENGL_ES2_BIT), EGL_NONE}; @@ -64,21 +64,21 @@ TEST_P(EGLCreateContextAttribsTest, InvalidClientVersion) EGL_NONE}; context = eglCreateContext(mDisplay, config, nullptr, contextAttribs2); EXPECT_EQ(context, EGL_NO_CONTEXT); - ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE); + ASSERT_EGL_ERROR(EGL_BAD_MATCH); // GLES 3.3 is invalid verify invalid attribute request EGLint contextAttribs3[] = {EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_MINOR_VERSION, 3, EGL_NONE}; context = eglCreateContext(mDisplay, config, nullptr, contextAttribs3); EXPECT_EQ(context, EGL_NO_CONTEXT); - ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE); + ASSERT_EGL_ERROR(EGL_BAD_MATCH); // GLES 4.0 is invalid verify invalid attribute request EGLint contextAttribs4[] = {EGL_CONTEXT_MAJOR_VERSION, 4, EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE}; context = eglCreateContext(mDisplay, config, nullptr, contextAttribs4); EXPECT_EQ(context, EGL_NO_CONTEXT); - ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE); + ASSERT_EGL_ERROR(EGL_BAD_MATCH); // Cleanup contexts eglTerminate(mDisplay); @@ -215,6 +215,52 @@ TEST_P(EGLCreateContextAttribsTest, IMGContextPriorityExtension) eglTerminate(mDisplay); } +// Test that creating and querying context with realtime priority works +TEST_P(EGLCreateContextAttribsTest, RealtimePriority) +{ + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_IMG_context_priority")); + + const EGLint configAttributes[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, EGL_NONE}; + + // Get all the configs + EGLint count = 0; + EGLConfig config; + EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, configAttributes, &config, 1, &count)); + EXPECT_TRUE(count == 1); + + EGLContext context = EGL_NO_CONTEXT; + EGLint contextAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, + 2, + EGL_CONTEXT_MINOR_VERSION, + 0, + EGL_CONTEXT_PRIORITY_LEVEL_IMG, + EGL_CONTEXT_PRIORITY_REALTIME_NV, + EGL_NONE}; + + if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_NV_context_priority_realtime")) + { + context = eglCreateContext(mDisplay, config, nullptr, contextAttribs); + EXPECT_NE(context, EGL_NO_CONTEXT); + ASSERT_EGL_ERROR(EGL_SUCCESS); + + EGLint value = 0; + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value)); + ASSERT_EGL_ERROR(EGL_SUCCESS); + } + else // Not supported so should get EGL_BAD_ATTRIBUTE + { + context = eglCreateContext(mDisplay, config, nullptr, contextAttribs); + EXPECT_EQ(context, EGL_NO_CONTEXT); + ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE); + } + + // Cleanup contexts + ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + eglDestroyContext(mDisplay, context); + eglTerminate(mDisplay); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLCreateContextAttribsTest); ANGLE_INSTANTIATE_TEST(EGLCreateContextAttribsTest, WithNoFixture(ES2_D3D9()), diff --git a/src/tests/egl_tests/EGLDeviceCGLTest.cpp b/src/tests/egl_tests/EGLDeviceCGLTest.cpp index c262d01bd4c..2a96759324c 100644 --- a/src/tests/egl_tests/EGLDeviceCGLTest.cpp +++ b/src/tests/egl_tests/EGLDeviceCGLTest.cpp @@ -3,9 +3,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// EGLDeviceCGLTest.cpp: tests for the EGL_ANGLE_device_cgl extension. +// EGLDeviceCGLTest.cpp: tests for the EGL_ANGLE_device_cgl extension. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "util/EGLWindow.h" #include "util/OSWindow.h" diff --git a/src/tests/egl_tests/EGLDeviceTest.cpp b/src/tests/egl_tests/EGLDeviceTest.cpp index 05c1834fe9f..6f74bbbdb86 100644 --- a/src/tests/egl_tests/EGLDeviceTest.cpp +++ b/src/tests/egl_tests/EGLDeviceTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #ifndef ANGLE_ENABLE_D3D9 # define ANGLE_ENABLE_D3D9 #endif @@ -232,7 +236,7 @@ TEST_P(EGLDeviceCreationTest, RenderingUsingD3D11Device) ASSERT_EGL_SUCCESS(); // Create an EGLDisplay using the EGLDevice - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr); + mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr); ASSERT_NE(EGL_NO_DISPLAY, mDisplay); // Create a surface using the display @@ -251,7 +255,7 @@ TEST_P(EGLDeviceCreationTest, RenderingUsingD3D11Device) eglReleaseDeviceANGLE(eglDevice); } -// Test that calling eglGetPlatformDisplayEXT with the same device returns the same display +// Test that calling eglGetPlatformDisplay with the same device returns the same display TEST_P(EGLDeviceCreationTest, GetPlatformDisplayTwice) { CreateD3D11Device(); @@ -261,10 +265,10 @@ TEST_P(EGLDeviceCreationTest, GetPlatformDisplayTwice) ASSERT_EGL_SUCCESS(); // Create an EGLDisplay using the EGLDevice - EGLDisplay display1 = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr); + EGLDisplay display1 = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr); ASSERT_NE(EGL_NO_DISPLAY, display1); - EGLDisplay display2 = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr); + EGLDisplay display2 = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr); ASSERT_NE(EGL_NO_DISPLAY, display2); ASSERT_EQ(display1, display2); @@ -439,8 +443,8 @@ TEST_P(EGLDeviceQueryTest, GetPlatformDisplayDeviceReuse) EXPECT_EGL_TRUE( eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &eglDevice)); - EGLDisplay display2 = eglGetPlatformDisplayEXT( - EGL_PLATFORM_DEVICE_EXT, reinterpret_cast(eglDevice), nullptr); + EGLDisplay display2 = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, + reinterpret_cast(eglDevice), nullptr); EXPECT_EQ(getEGLWindow()->getDisplay(), display2); } diff --git a/src/tests/egl_tests/EGLDirectCompositionTest.cpp b/src/tests/egl_tests/EGLDirectCompositionTest.cpp index a1cbd7fdb05..d1e43a1b314 100644 --- a/src/tests/egl_tests/EGLDirectCompositionTest.cpp +++ b/src/tests/egl_tests/EGLDirectCompositionTest.cpp @@ -7,6 +7,10 @@ // EGLDirectCompositionTest.cpp: // Tests pertaining to DirectComposition and WindowsUIComposition. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW # include @@ -15,7 +19,7 @@ # include # include # include -# include +# include # include # include # include @@ -146,20 +150,20 @@ class EGLDirectCompositionTest : public ANGLETest<> EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_NONE}; - const EGLint defaultDisplayAttributes[] = { + const EGLAttrib defaultDisplayAttributes[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE, }; - PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = - reinterpret_cast( - eglGetProcAddress("eglGetPlatformDisplayEXT")); - ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr); + PFNEGLGETPLATFORMDISPLAYPROC eglGetPlatformDisplay = + reinterpret_cast( + eglGetProcAddress("eglGetPlatformDisplay")); + ASSERT_TRUE(eglGetPlatformDisplay != nullptr); - mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(EGL_DEFAULT_DISPLAY), - defaultDisplayAttributes); + mEglDisplay = + eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), + defaultDisplayAttributes); ASSERT_TRUE(mEglDisplay != EGL_NO_DISPLAY); ASSERT_EGL_TRUE(eglInitialize(mEglDisplay, nullptr, nullptr)); diff --git a/src/tests/egl_tests/EGLDisplayLuidTest.cpp b/src/tests/egl_tests/EGLDisplayLuidTest.cpp index 06d281ec59b..88ad291cb50 100644 --- a/src/tests/egl_tests/EGLDisplayLuidTest.cpp +++ b/src/tests/egl_tests/EGLDisplayLuidTest.cpp @@ -25,18 +25,16 @@ class EGLDisplayLuidTest : public ANGLETest<> } } - void testInvalidAttribs(const EGLint displayAttribs[]) + void testInvalidAttribs(const EGLAttrib displayAttribs[]) { - EXPECT_EQ( - eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttribs), - EGL_NO_DISPLAY); + EXPECT_EQ(eglGetPlatformDisplay(GetEglPlatform(), EGL_DEFAULT_DISPLAY, displayAttribs), + EGL_NO_DISPLAY); EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE); } - void testValidAttribs(const EGLint displayAttribs[]) + void testValidAttribs(const EGLAttrib displayAttribs[]) { - mDisplay = - eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttribs); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), EGL_DEFAULT_DISPLAY, displayAttribs); EXPECT_EGL_SUCCESS(); EXPECT_NE(mDisplay, EGL_NO_DISPLAY); @@ -56,28 +54,29 @@ class EGLDisplayLuidTest : public ANGLETest<> // if D3D9 is specified in the attributes. TEST_P(EGLDisplayLuidTest, D3D9Failure) { - EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, - EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 1, EGL_NONE}; + EGLAttrib displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, + EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 1, EGL_NONE}; testInvalidAttribs(displayAttribs); } // Verify failure if the specified LUID is zero. TEST_P(EGLDisplayLuidTest, ZeroLuidFailure) { - EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, - 0, - EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, - 0, - EGL_NONE}; + EGLAttrib displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, + 0, + EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, + 0, + EGL_NONE}; testInvalidAttribs(displayAttribs); } TEST_P(EGLDisplayLuidTest, D3D11) { - EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 1, EGL_NONE}; + EGLAttrib displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 1, EGL_NONE}; testValidAttribs(displayAttribs); } diff --git a/src/tests/egl_tests/EGLDisplaySelectionTest.cpp b/src/tests/egl_tests/EGLDisplaySelectionTest.cpp index 33d283db1d7..cf996da1493 100644 --- a/src/tests/egl_tests/EGLDisplaySelectionTest.cpp +++ b/src/tests/egl_tests/EGLDisplaySelectionTest.cpp @@ -116,7 +116,7 @@ class EGLDisplaySelectionTestMultiDisplay : public EGLDisplaySelectionTestNoFixt GLenum platformType = GetParam().getRenderer(); GLenum deviceType = GetParam().getDeviceType(); - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platformType); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -129,9 +129,9 @@ class EGLDisplaySelectionTestMultiDisplay : public EGLDisplaySelectionTestNoFixt displayAttributes.push_back(powerPreference); displayAttributes.push_back(EGL_NONE); - *display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - displayAttributes.data()); + *display = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(mOSWindow->getNativeDisplay()), + displayAttributes.data()); ASSERT_TRUE(*display != EGL_NO_DISPLAY); EGLint majorVersion, minorVersion; @@ -145,7 +145,7 @@ class EGLDisplaySelectionTestMultiDisplay : public EGLDisplaySelectionTestNoFixt { GLenum deviceType = GetParam().getDeviceType(); - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platformType); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -156,9 +156,9 @@ class EGLDisplaySelectionTestMultiDisplay : public EGLDisplaySelectionTestNoFixt displayAttributes.push_back(deviceType); displayAttributes.push_back(EGL_NONE); - *display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - displayAttributes.data()); + *display = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(mOSWindow->getNativeDisplay()), + displayAttributes.data()); ASSERT_TRUE(*display != EGL_NO_DISPLAY); EGLint majorVersion, minorVersion; @@ -484,7 +484,7 @@ class EGLDisplaySelectionTestDeviceId : public EGLDisplaySelectionTestNoFixture EGLAttrib high = ((deviceId >> 32) & 0xFFFFFFFF); EGLAttrib low = (deviceId & 0xFFFFFFFF); - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platformType); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -504,9 +504,9 @@ class EGLDisplaySelectionTestDeviceId : public EGLDisplaySelectionTestNoFixture } displayAttributes.push_back(EGL_NONE); - *display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - displayAttributes.data()); + *display = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(mOSWindow->getNativeDisplay()), + displayAttributes.data()); ASSERT_TRUE(*display != EGL_NO_DISPLAY); EGLint majorVersion, minorVersion; diff --git a/src/tests/egl_tests/EGLDisplayTest.cpp b/src/tests/egl_tests/EGLDisplayTest.cpp index 795cf3e1e80..b51b5f07cba 100644 --- a/src/tests/egl_tests/EGLDisplayTest.cpp +++ b/src/tests/egl_tests/EGLDisplayTest.cpp @@ -55,6 +55,9 @@ class EGLDisplayTest : public ANGLETest<> } }; +class EGLDisplayTestES3 : public EGLDisplayTest +{}; + // Tests that an eglInitialize can be re-initialized. The spec says: // // > Initializing an already-initialized display is allowed, but the only effect of such a call is @@ -173,6 +176,41 @@ TEST_P(EGLDisplayTest, ContextLeakAfterTerminate) EXPECT_EQ(eglGetError(), EGL_NOT_INITIALIZED); } +// Tests eglGetPlatformDisplayEXT() when EGL_EXT_platform_base is enabled. +TEST_P(EGLDisplayTest, GetPlatformDisplayEXT) +{ + // eglGetPlatformDisplayEXT() requires EGL_EXT_platform_base. + ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_EXT_platform_base")); + + ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr); + + EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + EGLDisplay display = eglGetPlatformDisplayEXT( + GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + + ASSERT_NE(EGL_NO_DISPLAY, display); + ASSERT_EGL_SUCCESS(); +} + +// Tests that eglGetPlatformDisplayEXT can use EGL_PLATFORM_ANDROID_KHR to get a display. +TEST_P(EGLDisplayTestES3, GetPlatformDisplayAndroidValidation) +{ + ANGLE_SKIP_TEST_IF(!IsAndroid()); + ANGLE_SKIP_TEST_IF(getDriverType() != GLESDriverType::SystemEGL); + + // Get an EGLDisplay on GBM platform, expect EGL_BAD_PARAMETER + EGLDisplay display1 = eglGetPlatformDisplay( + EGL_PLATFORM_GBM_KHR, reinterpret_cast(EGL_DEFAULT_DISPLAY), nullptr); + ASSERT_EQ(EGL_NO_DISPLAY, display1); + ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); + + // Get an EGLDisplay on Android platform, expect EGL_SUCCESS + EGLDisplay display2 = eglGetPlatformDisplay( + EGL_PLATFORM_ANDROID_KHR, reinterpret_cast(EGL_DEFAULT_DISPLAY), nullptr); + ASSERT_NE(EGL_NO_DISPLAY, display2); + ASSERT_EGL_SUCCESS(); +} + ANGLE_INSTANTIATE_TEST(EGLDisplayTest, WithNoFixture(ES2_D3D9()), WithNoFixture(ES2_D3D11()), @@ -183,3 +221,6 @@ ANGLE_INSTANTIATE_TEST(EGLDisplayTest, WithNoFixture(ES3_METAL()), WithNoFixture(ES3_OPENGL()), WithNoFixture(ES3_VULKAN())); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplayTestES3); +ANGLE_INSTANTIATE_TEST(EGLDisplayTestES3, WithNoFixture(ES3_VULKAN())); diff --git a/src/tests/egl_tests/EGLFeatureControlTest.cpp b/src/tests/egl_tests/EGLFeatureControlTest.cpp index aabae6c62e7..3cec895c29b 100644 --- a/src/tests/egl_tests/EGLFeatureControlTest.cpp +++ b/src/tests/egl_tests/EGLFeatureControlTest.cpp @@ -6,6 +6,10 @@ // Tests the eglQueryStringiANGLE and eglQueryDisplayAttribANGLE functions exposed by the // extension EGL_ANGLE_feature_control. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -38,7 +42,7 @@ class EGLFeatureControlTest : public ANGLETest<> return false; EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_NE(mDisplay, EGL_NO_DISPLAY); @@ -178,7 +182,7 @@ void EGLFeatureControlTest::testOverrideFeatures(FeatureNameModifier modifyName) EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, reinterpret_cast(disabled.data()), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_EGL_SUCCESS(); ASSERT_NE(mDisplay, EGL_NO_DISPLAY); @@ -258,7 +262,7 @@ TEST_P(EGLFeatureControlTest, OverrideFeaturesWildcard) testEnableOverride ? EGL_FEATURE_OVERRIDES_ENABLED_ANGLE : EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, reinterpret_cast(featuresToOverride.data()), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_EGL_SUCCESS(); ASSERT_NE(mDisplay, EGL_NO_DISPLAY); @@ -300,6 +304,9 @@ TEST_P(EGLFeatureControlTest, OverrideFeaturesDependent) GetFeatureName(Feature::SupportsDepthStencilIndependentResolveNone), GetFeatureName(Feature::SupportsSampler2dViewOf3d), GetFeatureName(Feature::SupportsFragmentShadingRate), + + // Features that must become disabled as a result of the above + GetFeatureName(Feature::SupportFragmentShadingRateExtExtensions), }; // Features that could be different on some vendors @@ -348,7 +355,7 @@ TEST_P(EGLFeatureControlTest, OverrideFeaturesDependent) EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, reinterpret_cast(featuresDisabled.data()), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_EGL_SUCCESS(); ASSERT_NE(mDisplay, EGL_NO_DISPLAY); diff --git a/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp b/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp index e827f99066a..0979256eef6 100644 --- a/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp +++ b/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp @@ -3,9 +3,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// EGLIOSurfaceClientBufferTest.cpp: tests for the EGL_ANGLE_iosurface_client_buffer extension. +// EGLIOSurfaceClientBufferTest.cpp: tests for the EGL_ANGLE_iosurface_client_buffer extension. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "common/mathutil.h" diff --git a/src/tests/egl_tests/EGLLockSurface3Test.cpp b/src/tests/egl_tests/EGLLockSurface3Test.cpp index d121e620621..08cf24738a6 100644 --- a/src/tests/egl_tests/EGLLockSurface3Test.cpp +++ b/src/tests/egl_tests/EGLLockSurface3Test.cpp @@ -7,6 +7,10 @@ // EGL extension EGL_KHR_lock_surface // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -32,9 +36,9 @@ class EGLLockSurface3Test : public ANGLETest<> { mMajorVersion = GetParam().majorVersion; - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_NE(mDisplay, EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); } @@ -629,45 +633,57 @@ TEST_P(EGLLockSurface3Test, WindowMsaaSurfaceReadTest) EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; - glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A); - glClear(GL_COLOR_BUFFER_BIT); - ASSERT_GL_NO_ERROR() << "glClear failed"; + // EGL 1.5 Spec: + // 3.5.1 Creating On-Screen Rendering Surfaces + // Client APIs may not be able to respect the requested rendering buffer. To determine the + // actual buffer that a context will render to by default, call eglQueryContext with attribute + // EGL_RENDER_BUFFER(see section 3.7.4). + EGLint buffer = 0; + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &buffer)); + if (buffer == EGL_SINGLE_BUFFER) + { + glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR() << "glClear failed"; - const GLColor drawColor = GLColor::red; - GLuint texture = createTexture(); - EXPECT_TRUE(fillTexture(texture, drawColor)); - renderTexture(texture); - eglSwapBuffers(mDisplay, windowSurface); + const GLColor drawColor = GLColor::red; + GLuint texture = createTexture(); + EXPECT_TRUE(fillTexture(texture, drawColor)); + renderTexture(texture); + eglSwapBuffers(mDisplay, windowSurface); - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); - EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR, - EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_NONE}; - EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, windowSurface, lockAttribs)); + EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR, + EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_NONE}; + EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, windowSurface, lockAttribs)); - EGLAttribKHR bitMap = 0; - EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); - EGLAttribKHR bitMapPitch = 0; - EXPECT_EGL_TRUE( - eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); + EGLAttribKHR bitMap = 0; + EXPECT_EGL_TRUE( + eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); + EGLAttribKHR bitMapPitch = 0; + EXPECT_EGL_TRUE( + eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); - uint32_t *bitMapPtr = (uint32_t *)(bitMap); - EXPECT_TRUE(checkBitMapRGBA32(drawColor, bitMapPtr, bitMapPitch)); - - EXPECT_TRUE(eglUnlockSurfaceKHR(mDisplay, windowSurface)); + uint32_t *bitMapPtr = (uint32_t *)(bitMap); + EXPECT_TRUE(checkBitMapRGBA32(drawColor, bitMapPtr, bitMapPitch)); - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); - ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; - EXPECT_TRUE(checkSurfaceRGBA32(drawColor)); - EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, windowSurface)); + EXPECT_TRUE(eglUnlockSurfaceKHR(mDisplay, windowSurface)); - glDeleteTextures(1, &texture); + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; + EXPECT_TRUE(checkSurfaceRGBA32(drawColor)); + EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, windowSurface)); + glDeleteTextures(1, &texture); + } EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, windowSurface)); EXPECT_EGL_TRUE(eglDestroyContext(mDisplay, context)); + osWindow->destroy(); OSWindow::Delete(&osWindow); + ANGLE_SKIP_TEST_IF(buffer != EGL_SINGLE_BUFFER); } // Create WindowSurface, Lock surface, Write pixels red, Unlock, check pixels, diff --git a/src/tests/egl_tests/EGLMultiContextTest.cpp b/src/tests/egl_tests/EGLMultiContextTest.cpp index 1086fc22d3a..de69b5883ac 100644 --- a/src/tests/egl_tests/EGLMultiContextTest.cpp +++ b/src/tests/egl_tests/EGLMultiContextTest.cpp @@ -6,6 +6,10 @@ // EGLMultiContextTest.cpp: // Tests relating to multiple non-shared Contexts. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" @@ -358,15 +362,15 @@ TEST_P(EGLMultiContextTest, RepeatedEglInitAndTerminate) EGLDisplay dpy; EGLSurface srf; EGLContext ctx; - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), - EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, GetParam().getDeviceType(), - EGL_NONE}; + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, GetParam().getDeviceType(), + EGL_NONE}; for (int i = 0; i < 50; i++) // Note: this test is fairly slow b/303089709 { std::thread thread = std::thread([&]() { - dpy = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + dpy = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(dpy != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(dpy, nullptr, nullptr)); @@ -405,13 +409,13 @@ TEST_P(EGLMultiContextTest, ReuseUnterminatedDisplay) getEGLWindow()->destroyGL(); EGLDisplay dpy; - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), - EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, GetParam().getDeviceType(), - EGL_NONE}; + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, GetParam().getDeviceType(), + EGL_NONE}; std::thread threadA = std::thread([&]() { - dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + dpy = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), + dispattrs); EXPECT_TRUE(dpy != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(dpy, nullptr, nullptr)); }); diff --git a/src/tests/egl_tests/EGLNoConfigContextTest.cpp b/src/tests/egl_tests/EGLNoConfigContextTest.cpp index 327409bb762..0e1cce3fd28 100644 --- a/src/tests/egl_tests/EGLNoConfigContextTest.cpp +++ b/src/tests/egl_tests/EGLNoConfigContextTest.cpp @@ -26,9 +26,9 @@ class EGLNoConfigContextTest : public ANGLETest<> { int clientVersion = GetParam().majorVersion; - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); diff --git a/src/tests/egl_tests/EGLPreRotationTest.cpp b/src/tests/egl_tests/EGLPreRotationTest.cpp index 37a06bc0c90..7c32cf77db1 100644 --- a/src/tests/egl_tests/EGLPreRotationTest.cpp +++ b/src/tests/egl_tests/EGLPreRotationTest.cpp @@ -7,6 +7,10 @@ // Tests pertaining to Android pre-rotation. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -25,24 +29,6 @@ using namespace angle; namespace { -using EGLPreRotationSurfaceTestParams = std::tuple; - -std::string PrintToStringParamName( - const ::testing::TestParamInfo &info) -{ - std::stringstream ss; - ss << std::get<0>(info.param); - if (std::get<1>(info.param)) - { - ss << "__PreRotationEnabled"; - } - else - { - ss << "__PreRotationDisabled"; - } - return ss.str(); -} - // A class to test various Android pre-rotation cases. In order to make it easier to debug test // failures, the initial window size is 256x256, and each pixel will have a unique and predictable // value. The red channel will increment with the x axis, and the green channel will increment @@ -53,7 +39,7 @@ std::string PrintToStringParamName( // Lower-right, which is ( 1.0,-1.0) & (256, 0) in GLES will be red (0xFF, 0x00, 0x00, 0xFF) // Upper-left, which is (-1.0, 1.0) & ( 0, 256) in GLES will be green (0x00, 0xFF, 0x00, 0xFF) // Upper-right, which is ( 1.0, 1.0) & (256, 256) in GLES will be yellow (0xFF, 0xFF, 0x00, 0xFF) -class EGLPreRotationSurfaceTest : public ANGLETest +class EGLPreRotationSurfaceTest : public ANGLETest<> { protected: EGLPreRotationSurfaceTest() @@ -101,23 +87,10 @@ class EGLPreRotationSurfaceTest : public ANGLETest(GetParam()); + const angle::PlatformParameters platform = GetParam(); GLenum platformType = platform.getRenderer(); GLenum deviceType = platform.getDeviceType(); - std::vector enabledFeatures; - std::vector disabledFeatures; - if (::testing::get<1>(GetParam())) - { - enabledFeatures.push_back("enablePreRotateSurfaces"); - } - else - { - disabledFeatures.push_back("enablePreRotateSurfaces"); - } - enabledFeatures.push_back(nullptr); - disabledFeatures.push_back(nullptr); - std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platformType); @@ -127,13 +100,9 @@ class EGLPreRotationSurfaceTest : public ANGLETest(enabledFeatures.data())); - displayAttributes.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE); - displayAttributes.push_back(reinterpret_cast(disabledFeatures.data())); displayAttributes.push_back(EGL_NONE); - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(mOSWindow->getNativeDisplay()), displayAttributes.data()); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); @@ -147,8 +116,7 @@ class EGLPreRotationSurfaceTest : public ANGLETest(GetParam()).majorVersion, EGL_NONE}; + EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion, EGL_NONE}; mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes); ASSERT_EGL_SUCCESS(); @@ -627,79 +595,6 @@ TEST_P(EGLPreRotationSurfaceTest, ChangeRotationWithDraw) } } -// Android-specific test that changes a window's rotation and size. This is to check the actual size -// and the surface capabilities returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR. -TEST_P(EGLPreRotationSurfaceTest, CheckSurfaceCapabilities) -{ - // This test is confined to Android. - ANGLE_SKIP_TEST_IF(isVulkanRenderer() && !IsAndroid() && IsLinux() && isSwiftshader()); - - initializeDisplay(); - initializeSurfaceWithRGBA8888Config(); - - eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); - ASSERT_EGL_SUCCESS(); - - EGLint preWindowSurfaceWidth = 0; - EGLint preWindowSurfaceHeight = 0; - EGLint curWindowSurfaceWidth = 300; - EGLint curWindowSurfaceHeight = 200; - EGLint actualWidth = 0; - EGLint actualHeight = 0; - - // Set the initial window surface size. - mOSWindow->resize(curWindowSurfaceWidth, curWindowSurfaceHeight); - mOSWindow->setOrientation(curWindowSurfaceWidth, curWindowSurfaceHeight); - angle::Sleep(1000); - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &actualWidth); - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &actualHeight); - ASSERT_EGL_SUCCESS(); - - // eglSwapBuffers(vkQueuePresentKHR) is called before eglQuerySurface - // so actualWidth and actualHeight need to be curWindowSurfaceHeight and curWindowSurfaceHeight - // (300, 200). - EXPECT_EQ(curWindowSurfaceWidth, actualWidth); - EXPECT_EQ(curWindowSurfaceHeight, actualHeight); - - // Store the old values - preWindowSurfaceWidth = curWindowSurfaceWidth; - preWindowSurfaceHeight = curWindowSurfaceHeight; - - // Set the new values - curWindowSurfaceWidth = 200; - curWindowSurfaceHeight = 300; - - mOSWindow->resize(curWindowSurfaceWidth, curWindowSurfaceHeight); - mOSWindow->setOrientation(curWindowSurfaceWidth, curWindowSurfaceHeight); - angle::Sleep(1000); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &actualWidth); - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &actualHeight); - ASSERT_EGL_SUCCESS(); - - // eglSwapBuffers(vkQueuePresentKHR) is not called before eglQuerySurface - // so actualWidth and actualHeight need to be preWindowSurfaceWidth and preWindowSurfaceHeight - // (300, 200). - EXPECT_EQ(preWindowSurfaceWidth, actualWidth); - EXPECT_EQ(preWindowSurfaceHeight, actualHeight); - - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &actualWidth); - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &actualHeight); - ASSERT_EGL_SUCCESS(); - - // Now eglSwapBuffers(vkQueuePresentKHR) is called - // so actualWidth and actualHeight will be curWindowSurfaceHeight and curWindowSurfaceHeight - // (200, 300). - EXPECT_EQ(curWindowSurfaceWidth, actualWidth); - EXPECT_EQ(curWindowSurfaceHeight, actualHeight); -} - // A slight variation of EGLPreRotationSurfaceTest, where the initial window size is 400x300, yet // the drawing is still 256x256. In addition, gl_FragCoord is used in a "clever" way, as the color // of the 256x256 drawing area, which reproduces an interesting pre-rotation case from the @@ -2594,31 +2489,22 @@ TEST_P(EGLPreRotationInterpolateAtOffsetTest, InterpolateAtOffsetWithCustomFBO) } // anonymous namespace GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPreRotationInterpolateAtOffsetTest); -ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationInterpolateAtOffsetTest, - PrintToStringParamName, - testing::Bool(), - WithNoFixture(ES31_VULKAN())); +ANGLE_INSTANTIATE_TEST(EGLPreRotationInterpolateAtOffsetTest, WithNoFixture(ES31_VULKAN())); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPreRotationSurfaceTest); -ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationSurfaceTest, - PrintToStringParamName, - testing::Bool(), - WithNoFixture(ES2_VULKAN()), - WithNoFixture(ES3_VULKAN()), - WithNoFixture(ES3_VULKAN_SWIFTSHADER())); +ANGLE_INSTANTIATE_TEST(EGLPreRotationSurfaceTest, + WithNoFixture(ES2_VULKAN()), + WithNoFixture(ES3_VULKAN()), + WithNoFixture(ES3_VULKAN_SWIFTSHADER())); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPreRotationLargeSurfaceTest); -ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationLargeSurfaceTest, - PrintToStringParamName, - testing::Bool(), - WithNoFixture(ES2_VULKAN()), - WithNoFixture(ES3_VULKAN()), - WithNoFixture(ES3_VULKAN_SWIFTSHADER())); +ANGLE_INSTANTIATE_TEST(EGLPreRotationLargeSurfaceTest, + WithNoFixture(ES2_VULKAN()), + WithNoFixture(ES3_VULKAN()), + WithNoFixture(ES3_VULKAN_SWIFTSHADER())); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPreRotationBlitFramebufferTest); -ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationBlitFramebufferTest, - PrintToStringParamName, - testing::Bool(), - WithNoFixture(ES2_VULKAN()), - WithNoFixture(ES3_VULKAN()), - WithNoFixture(ES3_VULKAN_SWIFTSHADER())); +ANGLE_INSTANTIATE_TEST(EGLPreRotationBlitFramebufferTest, + WithNoFixture(ES2_VULKAN()), + WithNoFixture(ES3_VULKAN()), + WithNoFixture(ES3_VULKAN_SWIFTSHADER())); diff --git a/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp b/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp index 62c474a89c2..c454287d99e 100644 --- a/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp +++ b/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include @@ -39,18 +43,17 @@ class EGLPresentPathD3D11 : public ANGLETest<> int clientVersion = GetParam().majorVersion; // Set up EGL Display - EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, - GetParam().getRenderer(), - EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, - GetParam().eglParameters.majorVersion, - EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, - GetParam().eglParameters.majorVersion, - EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, - usePresentPathFast ? EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE - : EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE, - EGL_NONE}; - mDisplay = - eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttribs); + EGLAttrib displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, + GetParam().getRenderer(), + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, + GetParam().eglParameters.majorVersion, + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, + GetParam().eglParameters.majorVersion, + EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, + usePresentPathFast ? EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE + : EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE, + EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), EGL_DEFAULT_DISPLAY, displayAttribs); ASSERT_TRUE(EGL_NO_DISPLAY != mDisplay); ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); diff --git a/src/tests/egl_tests/EGLPrintEGLinfoTest.cpp b/src/tests/egl_tests/EGLPrintEGLinfoTest.cpp index c267f0d186d..d3359ba4148 100644 --- a/src/tests/egl_tests/EGLPrintEGLinfoTest.cpp +++ b/src/tests/egl_tests/EGLPrintEGLinfoTest.cpp @@ -7,6 +7,10 @@ // This test prints out the extension strings, configs and their attributes // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/string_utils.h" @@ -78,20 +82,20 @@ const char *GetGLString(EGLint name) TEST_P(EGLPrintEGLinfoTest, PrintEGLInfo) { std::cout << " EGL Information:" << std::endl; - std::cout << "\tVendor: " << GetEGLString(mDisplay, EGL_VENDOR) << std::endl; - std::cout << "\tVersion: " << GetEGLString(mDisplay, EGL_VERSION) << std::endl; - std::cout << "\tClient APIs: " << GetEGLString(mDisplay, EGL_CLIENT_APIS) << std::endl; + std::cout << " Vendor: " << GetEGLString(mDisplay, EGL_VENDOR) << std::endl; + std::cout << " Version: " << GetEGLString(mDisplay, EGL_VERSION) << std::endl; + std::cout << " Client APIs: " << GetEGLString(mDisplay, EGL_CLIENT_APIS) << std::endl; - std::cout << "\tEGL Client Extensions:" << std::endl; + std::cout << " EGL Client Extensions:" << std::endl; for (auto extension : ParseExtensions(GetEGLString(EGL_NO_DISPLAY, EGL_EXTENSIONS))) { - std::cout << "\t\t" << extension << std::endl; + std::cout << " " << extension << std::endl; } - std::cout << "\tEGL Display Extensions:" << std::endl; + std::cout << " EGL Display Extensions:" << std::endl; for (auto extension : ParseExtensions(GetEGLString(mDisplay, EGL_EXTENSIONS))) { - std::cout << "\t\t" << extension << std::endl; + std::cout << " " << extension << std::endl; } std::cout << std::endl; @@ -101,18 +105,18 @@ TEST_P(EGLPrintEGLinfoTest, PrintEGLInfo) TEST_P(EGLPrintEGLinfoTest, PrintGLInfo) { std::cout << " GLES Information:" << std::endl; - std::cout << "\tVendor: " << GetGLString(GL_VENDOR) << std::endl; - std::cout << "\tVersion: " << GetGLString(GL_VERSION) << std::endl; - std::cout << "\tRenderer: " << GetGLString(GL_RENDERER) << std::endl; - std::cout << "\tShader: " << GetGLString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + std::cout << " Vendor: " << GetGLString(GL_VENDOR) << std::endl; + std::cout << " Version: " << GetGLString(GL_VERSION) << std::endl; + std::cout << " Renderer: " << GetGLString(GL_RENDERER) << std::endl; + std::cout << " Shader: " << GetGLString(GL_SHADING_LANGUAGE_VERSION) << std::endl; - std::cout << "\tExtensions:" << std::endl; + std::cout << " Extensions:" << std::endl; const std::vector extensions = ParseExtensions(GetGLString(GL_EXTENSIONS)); for (const std::string &extension : extensions) { - std::cout << "\t\t" << extension << std::endl; + std::cout << " " << extension << std::endl; } std::cout << std::endl; @@ -418,7 +422,7 @@ TEST_P(EGLPrintEGLinfoTest, PrintConfigInfo) (GetAttrib(mDisplay, config, EGL_COLOR_BUFFER_TYPE) == EGL_LUMINANCE_BUFFER) ? "LUMINANCE" : "RGB"; - std::cout << "\tColor:" << GetAttrib(mDisplay, config, EGL_BUFFER_SIZE) << "bit " + std::cout << " Color:" << GetAttrib(mDisplay, config, EGL_BUFFER_SIZE) << "bit " << componentType << colorBuffType << " Red:" << GetAttrib(mDisplay, config, EGL_RED_SIZE) << " Green:" << GetAttrib(mDisplay, config, EGL_GREEN_SIZE) @@ -428,7 +432,8 @@ TEST_P(EGLPrintEGLinfoTest, PrintConfigInfo) << " AlphaMask:" << GetAttrib(mDisplay, config, EGL_ALPHA_MASK_SIZE) << std::endl; // Texture Binding - std::cout << "\tBinding RGB:" << (bool)GetAttrib(mDisplay, config, EGL_BIND_TO_TEXTURE_RGB) + std::cout << " Binding RGB:" + << (bool)GetAttrib(mDisplay, config, EGL_BIND_TO_TEXTURE_RGB) << " RGBA:" << (bool)GetAttrib(mDisplay, config, EGL_BIND_TO_TEXTURE_RGBA) << " MaxWidth:" << GetAttrib(mDisplay, config, EGL_MAX_PBUFFER_WIDTH) << " MaxHeight:" << GetAttrib(mDisplay, config, EGL_MAX_PBUFFER_HEIGHT) @@ -452,7 +457,7 @@ TEST_P(EGLPrintEGLinfoTest, PrintConfigInfo) default: caveat = "."; } - std::cout << "\tCaveate: " << caveat; + std::cout << " Caveate: " << caveat; EGLint conformant = GetAttrib(mDisplay, config, EGL_CONFORMANT); std::cout << " Conformant: "; @@ -465,57 +470,57 @@ TEST_P(EGLPrintEGLinfoTest, PrintConfigInfo) std::cout << std::endl; // Ancilary buffers - std::cout << "\tAncilary " << "Depth:" << GetAttrib(mDisplay, config, EGL_DEPTH_SIZE) + std::cout << " Ancilary " << "Depth:" << GetAttrib(mDisplay, config, EGL_DEPTH_SIZE) << " Stencil:" << GetAttrib(mDisplay, config, EGL_STENCIL_SIZE) << " SampleBuffs:" << GetAttrib(mDisplay, config, EGL_SAMPLE_BUFFERS) << " Samples:" << GetAttrib(mDisplay, config, EGL_SAMPLES) << std::endl; // Swap interval - std::cout << "\tSwap Interval" + std::cout << " Swap Interval" << " Min:" << GetAttrib(mDisplay, config, EGL_MIN_SWAP_INTERVAL) << " Max:" << GetAttrib(mDisplay, config, EGL_MAX_SWAP_INTERVAL) << std::endl; // Native - std::cout << "\tNative Renderable: " << GetAttrib(mDisplay, config, EGL_NATIVE_RENDERABLE) + std::cout << " Native Renderable: " << GetAttrib(mDisplay, config, EGL_NATIVE_RENDERABLE) << ", VisualID: " << GetAttrib(mDisplay, config, EGL_NATIVE_VISUAL_ID) << ", VisualType: " << GetAttrib(mDisplay, config, EGL_NATIVE_VISUAL_TYPE) << std::endl; // Surface type EGLint surfaceType = GetAttrib(mDisplay, config, EGL_SURFACE_TYPE); - std::cout << "\tSurface Type: "; + std::cout << " Surface Type:"; if (surfaceType & EGL_WINDOW_BIT) - std::cout << "WINDOW "; + std::cout << " WINDOW"; if (surfaceType & EGL_PIXMAP_BIT) - std::cout << "PIXMAP "; + std::cout << " PIXMAP"; if (surfaceType & EGL_PBUFFER_BIT) - std::cout << "PBUFFER "; + std::cout << " PBUFFER"; if (surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) - std::cout << "MULTISAMPLE_RESOLVE_BOX "; + std::cout << " MULTISAMPLE_RESOLVE_BOX"; if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) - std::cout << "SWAP_PRESERVE "; + std::cout << " SWAP_PRESERVE"; std::cout << std::endl; // Renderable EGLint rendType = GetAttrib(mDisplay, config, EGL_RENDERABLE_TYPE); - std::cout << "\tRender: "; + std::cout << " Render:"; if (rendType & EGL_OPENGL_ES_BIT) - std::cout << "ES1 "; + std::cout << " ES1"; if (rendType & EGL_OPENGL_ES2_BIT) - std::cout << "ES2 "; + std::cout << " ES2"; if (rendType & EGL_OPENGL_ES3_BIT) - std::cout << "ES3 "; + std::cout << " ES3"; std::cout << std::endl; // Extensions if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_recordable")) { - std::cout << "\tAndroid Recordable: " + std::cout << " Android Recordable: " << GetAttrib(mDisplay, config, EGL_RECORDABLE_ANDROID) << std::endl; } if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_framebuffer_target")) { - std::cout << "\tAndroid framebuffer target: " + std::cout << " Android framebuffer target: " << GetAttrib(mDisplay, config, EGL_FRAMEBUFFER_TARGET_ANDROID) << std::endl; } @@ -524,14 +529,96 @@ TEST_P(EGLPrintEGLinfoTest, PrintConfigInfo) } } +class EGLPrintFeaturesVulkanExtensionsInfoTest : public EGLPrintEGLinfoTest +{}; + +// Log enabled features +TEST_P(EGLPrintFeaturesVulkanExtensionsInfoTest, LogEnabledFeatures) +{ + // The system EGL may not expose ANGLE-specific extensions, which is not a failure. + ANGLE_SKIP_TEST_IF(isDriverSystemEgl()); + + ASSERT_EQ(IsEGLClientExtensionEnabled("EGL_ANGLE_feature_control"), true); + + EGLAttrib featureCount = -1; + EXPECT_EQ(static_cast(EGL_TRUE), + eglQueryDisplayAttribANGLE(mDisplay, EGL_FEATURE_COUNT_ANGLE, &featureCount)); + ASSERT_EGL_SUCCESS(); + ASSERT_GT(featureCount, 0); + ASSERT_LT(featureCount, std::numeric_limits::max()); + + const char *kEnabled = "enabled"; + + std::cout << "Enabled ANGLE features:" << std::endl; + for (int32_t i = 0; i < featureCount; i++) + { + const char *name = eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE, i); + const char *status = eglQueryStringiANGLE(mDisplay, EGL_FEATURE_STATUS_ANGLE, i); + if (std::strcmp(status, kEnabled) == 0) + { + std::cout << name << std::endl; + } + } +} + +// Log enabled vulkan instance and device extensions +TEST_P(EGLPrintFeaturesVulkanExtensionsInfoTest, LogEnabledVulkanExtensions) +{ + // This test is only for the Vulkan backend + ANGLE_SKIP_TEST_IF(!IsVulkan()); + + EGLDeviceEXT eglDevice = 0; + EGLAttrib result = 0; + size_t nextExtension = 0; + const char *const *extensions = nullptr; + + // Query EGL device + EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, (EGLAttrib *)&eglDevice)); + EXPECT_NE(EGL_NO_DEVICE_EXT, eglDevice); + + // Query enabled Vulkan Instance extensions + EXPECT_EGL_TRUE( + eglQueryDeviceAttribEXT(eglDevice, EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE, &result)); + extensions = reinterpret_cast(result); + nextExtension = 0; + EXPECT_NE(extensions, nullptr); + + std::cout << "Enabled Vulkan Instance extensions:" << std::endl; + while (extensions[nextExtension]) + { + std::cout << extensions[nextExtension] << std::endl; + nextExtension++; + } + + // Query enabled Vulkan Device extensions + EXPECT_EGL_TRUE( + eglQueryDeviceAttribEXT(eglDevice, EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE, &result)); + extensions = reinterpret_cast(result); + nextExtension = 0; + EXPECT_NE(extensions, nullptr); + + std::cout << "Enabled Vulkan Device extensions:" << std::endl; + while (extensions[nextExtension]) + { + std::cout << extensions[nextExtension] << std::endl; + nextExtension++; + } +} + +// This test suite is not instantiated on some OSes. +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPrintEGLinfoTest); ANGLE_INSTANTIATE_TEST(EGLPrintEGLinfoTest, ES1_VULKAN(), ES1_VULKAN_SWIFTSHADER(), ES2_VULKAN(), ES3_VULKAN(), ES32_VULKAN(), - ES31_VULKAN_SWIFTSHADER(), - ES32_EGL()); + ES31_VULKAN_SWIFTSHADER()); // This test suite is not instantiated on some OSes. -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPrintEGLinfoTest); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPrintFeaturesVulkanExtensionsInfoTest); +ANGLE_INSTANTIATE_TEST(EGLPrintFeaturesVulkanExtensionsInfoTest, + ES2_VULKAN(), + ES3_VULKAN(), + ES31_VULKAN(), + ES32_VULKAN()); diff --git a/src/tests/egl_tests/EGLProgramCacheControlTest.cpp b/src/tests/egl_tests/EGLProgramCacheControlTest.cpp index 8713eaf602c..83d0737f8f8 100644 --- a/src/tests/egl_tests/EGLProgramCacheControlTest.cpp +++ b/src/tests/egl_tests/EGLProgramCacheControlTest.cpp @@ -6,6 +6,10 @@ // EGLProgramCacheControlTest: // Unit tests for the EGL_ANGLE_program_cache_control extension. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/angleutils.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/egl_tests/EGLProtectedContentTest.cpp b/src/tests/egl_tests/EGLProtectedContentTest.cpp index 381e4c3b100..3b96a375bc2 100644 --- a/src/tests/egl_tests/EGLProtectedContentTest.cpp +++ b/src/tests/egl_tests/EGLProtectedContentTest.cpp @@ -7,6 +7,10 @@ // EGL extension EGL_EXT_protected_content // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -31,9 +35,9 @@ class EGLProtectedContentTest : public ANGLETest<> void testSetUp() override { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); mMajorVersion = GetParam().majorVersion; diff --git a/src/tests/egl_tests/EGLQueryContextTest.cpp b/src/tests/egl_tests/EGLQueryContextTest.cpp index 64751958488..c9b0afe7eba 100644 --- a/src/tests/egl_tests/EGLQueryContextTest.cpp +++ b/src/tests/egl_tests/EGLQueryContextTest.cpp @@ -17,9 +17,9 @@ class EGLQueryContextTest : public ANGLETest<> { int clientVersion = GetParam().majorVersion; - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY); EXPECT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) != EGL_FALSE); diff --git a/src/tests/egl_tests/EGLReadinessCheckTest.cpp b/src/tests/egl_tests/EGLReadinessCheckTest.cpp index 8b13884988f..a836b57da68 100644 --- a/src/tests/egl_tests/EGLReadinessCheckTest.cpp +++ b/src/tests/egl_tests/EGLReadinessCheckTest.cpp @@ -7,6 +7,10 @@ // EGLReadinessCheckTest.cpp: // Tests used to check environment in which other tests are run. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include "gpu_info_util/SystemInfo.h" @@ -27,22 +31,29 @@ TEST_P(EGLReadinessCheckTest, IsRunningOnANGLE) } // Checks that getting function pointer works -TEST_P(EGLReadinessCheckTest, HasGetPlatformDisplayEXT) +TEST_P(EGLReadinessCheckTest, HasGetPlatformDisplay) { - ASSERT_NE(eglGetPlatformDisplayEXT, nullptr); + ASSERT_NE(eglGetPlatformDisplay, nullptr); } -// Checks that calling GetProcAddress for a non-existant function fails. +// Checks that calling GetProcAddress for a non-existent function fails. TEST_P(EGLReadinessCheckTest, GetProcAddressNegativeTest) { auto check = eglGetProcAddress("WigglyWombats"); EXPECT_EQ(nullptr, check); } +// Checks that calling GetProcAddress for a null pointer function fails. +TEST_P(EGLReadinessCheckTest, GetProcAddressNullInput) +{ + auto check = eglGetProcAddress(nullptr); + EXPECT_EQ(nullptr, check); +} + // Tests that our allowlist function generally maps to our support function. // We can add specific exceptions here if needed. // Disabled because it was creating a large number of configs. This could even result -// in a BDOD on Windows. +// in a BSOD on Windows. TEST_P(EGLReadinessCheckTest, DISABLED_AllowlistMatchesSupport) { // Has issues with Vulkan support detection on Android. @@ -72,7 +83,6 @@ TEST_P(EGLReadinessCheckTest, DISABLED_AllowlistMatchesSupport) check(ES1_D3D11()); check(ES2_D3D11()); check(ES3_D3D11()); - check(ES31_D3D11()); check(ES1_VULKAN()); check(ES2_VULKAN()); diff --git a/src/tests/egl_tests/EGLRobustnessTest.cpp b/src/tests/egl_tests/EGLRobustnessTest.cpp index f30feba3f18..6c7a7894fd6 100644 --- a/src/tests/egl_tests/EGLRobustnessTest.cpp +++ b/src/tests/egl_tests/EGLRobustnessTest.cpp @@ -5,7 +5,11 @@ // // EGLRobustnessTest.cpp: tests for EGL_EXT_create_context_robustness -// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // Tests causing GPU resets are disabled, use the following args to run them: // --gtest_also_run_disabled_tests --gtest_filter=EGLRobustnessTest\* @@ -35,7 +39,7 @@ class EGLRobustnessTest : public ANGLETest<> const auto &platform = GetParam().eglParameters; - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platform.renderer); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -51,9 +55,9 @@ class EGLRobustnessTest : public ANGLETest<> displayAttributes.push_back(EGL_NONE); - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - &displayAttributes[0]); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(mOSWindow->getNativeDisplay()), + &displayAttributes[0]); ASSERT_NE(EGL_NO_DISPLAY, mDisplay); ASSERT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE); diff --git a/src/tests/egl_tests/EGLStreamTest.cpp b/src/tests/egl_tests/EGLStreamTest.cpp index c9f90db1816..6b3e6fcc950 100644 --- a/src/tests/egl_tests/EGLStreamTest.cpp +++ b/src/tests/egl_tests/EGLStreamTest.cpp @@ -7,6 +7,10 @@ // Tests pertaining to egl::Stream. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include @@ -976,5 +980,5 @@ ANGLE_INSTANTIATE_TEST(EGLStreamTest, ES2_OPENGL(), ES3_OPENGL(), ES2_VULKAN()); -ANGLE_INSTANTIATE_TEST(D3D11TextureStreamSamplingTest, ES2_D3D11(), ES3_D3D11(), ES31_D3D11()); +ANGLE_INSTANTIATE_TEST(D3D11TextureStreamSamplingTest, ES2_D3D11(), ES3_D3D11()); } // anonymous namespace diff --git a/src/tests/egl_tests/EGLSurfaceTest.cpp b/src/tests/egl_tests/EGLSurfaceTest.cpp index d317ca15ab6..34e75be63f7 100644 --- a/src/tests/egl_tests/EGLSurfaceTest.cpp +++ b/src/tests/egl_tests/EGLSurfaceTest.cpp @@ -7,6 +7,10 @@ // Tests pertaining to egl::Surface. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -19,6 +23,7 @@ #include "util/EGLWindow.h" #include "util/OSWindow.h" #include "util/Timer.h" +#include "util/test_utils.h" #if defined(ANGLE_ENABLE_D3D11) # define INITGUID @@ -117,7 +122,7 @@ class EGLSurfaceTest : public ANGLETest<> GLenum platformType = GetParam().getRenderer(); GLenum deviceType = GetParam().getDeviceType(); - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platformType); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -128,9 +133,9 @@ class EGLSurfaceTest : public ANGLETest<> displayAttributes.push_back(deviceType); displayAttributes.push_back(EGL_NONE); - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - displayAttributes.data()); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(mOSWindow->getNativeDisplay()), + displayAttributes.data()); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); EGLint majorVersion, minorVersion; @@ -327,6 +332,8 @@ class EGLSurfaceTest : public ANGLETest<> void drawQuadThenTearDown(); + int drawSizeCheckRect(EGLSurface surface, GLsizei checkRectWidth, GLsizei checkRectHeight); + EGLDisplay mDisplay; EGLSurface mWindowSurface; EGLSurface mPbufferSurface; @@ -413,9 +420,9 @@ class EGLSingleBufferTest : public ANGLETest<> void testSetUp() override { - EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); mMajorVersion = GetParam().majorVersion; @@ -734,154 +741,6 @@ TEST_P(EGLSurfaceTest, SurfaceUseAfterFreeBug) mSecondContext = EGL_NO_CONTEXT; } -// Test that the window surface is correctly resized after calling swapBuffers -TEST_P(EGLSurfaceTest, ResizeWindow) -{ - // http://anglebug.com/42263074 - ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel()); - // Flaky on Linux SwANGLE http://anglebug.com/42263074 - ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader()); - // http://anglebug.com/42264022 - ANGLE_SKIP_TEST_IF(IsIOS()); - ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); - - // Necessary for a window resizing test if there is no per-frame window size query - setWindowVisible(mOSWindow, true); - - GLenum platform = GetParam().getRenderer(); - bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || - platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE; - int minSize = platformSupportsZeroSize ? 0 : 1; - - initializeDisplay(); - initializeSurfaceWithDefaultConfig(true); - initializeMainContext(); - ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - - eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - EGLint height; - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(64, height); // initial size - - // set window's height to 0 (if possible) or 1 - mOSWindow->resize(64, minSize); - - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - // TODO(syoussefi): the GLX implementation still reads the window size as 64x64 through - // XGetGeometry. http://anglebug.com/42261800 - ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL()); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(minSize, height); - - // restore window's height - mOSWindow->resize(64, 64); - - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(64, height); -} - -// Test that the backbuffer is correctly resized after calling swapBuffers -TEST_P(EGLSurfaceTest, ResizeWindowWithDraw) -{ - // http://anglebug.com/42263074 - ANGLE_SKIP_TEST_IF(IsLinux()); - // http://anglebug.com/42264022 - ANGLE_SKIP_TEST_IF(IsIOS()); - - // Necessary for a window resizing test if there is no per-frame window size query - setWindowVisible(mOSWindow, true); - - initializeDisplay(); - initializeSurfaceWithDefaultConfig(true); - initializeMainContext(); - ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - - int size = 64; - EGLint height = 0; - EGLint width = 0; - - eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - // Clear to red - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); - eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width); - ASSERT_EGL_SUCCESS(); - - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::red); - EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::red); - EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::red); - EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack); - - // set window's size small - size = 1; - mOSWindow->resize(size, size); - - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - // Clear to green - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); - eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width); - ASSERT_EGL_SUCCESS(); - - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::green); - EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::green); - EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::green); - EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack); - - // set window's height large - size = 128; - mOSWindow->resize(size, size); - - eglSwapBuffers(mDisplay, mWindowSurface); - ASSERT_EGL_SUCCESS(); - - // Clear to blue - glClearColor(0.0f, 0.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); - eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width); - ASSERT_EGL_SUCCESS(); - - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack); - EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack); -} - // Test that the window can be reset repeatedly before surface creation. TEST_P(EGLSurfaceTest, ResetNativeWindow) { @@ -2107,12 +1966,16 @@ TEST_P(EGLSingleBufferTest, OnCreateWindowSurface) EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; + bool skipped = false; EGLint actualRenderbuffer; EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); if (actualRenderbuffer == EGL_SINGLE_BUFFER) { EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 2, 2); + glClearColor(0.0, 1.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); @@ -2120,10 +1983,18 @@ TEST_P(EGLSingleBufferTest, OnCreateWindowSurface) // Flush should result in update of screen. Must be visually confirmed. // Pixel test for automation. EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green); + + // Check second flush + glClearColor(1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); } else { std::cout << "SKIP test, no EGL_SINGLE_BUFFER support." << std::endl; + skipped = true; } EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); @@ -2136,6 +2007,7 @@ TEST_P(EGLSingleBufferTest, OnCreateWindowSurface) eglDestroyContext(mDisplay, context); context = EGL_NO_CONTEXT; + ANGLE_SKIP_TEST_IF(skipped); } TEST_P(EGLSingleBufferTest, OnSetSurfaceAttrib) @@ -2170,6 +2042,9 @@ TEST_P(EGLSingleBufferTest, OnSetSurfaceAttrib) EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 2, 2); + glClearColor(0.0, 1.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); @@ -2178,7 +2053,13 @@ TEST_P(EGLSingleBufferTest, OnSetSurfaceAttrib) // Check color for automation. EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green); - // Switch back to EGL_BACK_BUFFEr and check. + // Check second flush + glClearColor(1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + + // Switch back to EGL_BACK_BUFFER and check. EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER)); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); @@ -2252,6 +2133,7 @@ TEST_P(EGLSingleBufferTest, MutableRenderBuffer) EGL_NONE}; EGLint count = 0; ANGLE_SKIP_TEST_IF(!eglChooseConfig(mDisplay, attribs, &config, 1, &count)); + ANGLE_SKIP_TEST_IF(count == 0); EGLContext context = EGL_NO_CONTEXT; EXPECT_EGL_TRUE(createContext(config, &context)); @@ -2437,7 +2319,7 @@ TEST_P(EGLSingleBufferTest, ScissoredClear) context = EGL_NO_CONTEXT; } -// Tests scissored clear on single buffer surface +// Tests scissored draw on single buffer surface TEST_P(EGLSingleBufferTest, ScissoredDraw) { ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); @@ -2607,7 +2489,7 @@ TEST_P(EGLSingleBufferTest, AcquireImageFromSwapImpl) drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f); glFlush(); - // Prepare auxilary framebuffer. + // Prepare auxiliary framebuffer. GLRenderbuffer renderBuffer; GLFramebuffer framebuffer; glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer); @@ -2617,7 +2499,7 @@ TEST_P(EGLSingleBufferTest, AcquireImageFromSwapImpl) renderBuffer); EXPECT_GL_NO_ERROR(); - // Draw into the auxilary framebuffer just to generate commands into the command buffers. + // Draw into the auxiliary framebuffer just to generate commands into the command buffers. // Otherwise below flush will be ignored. drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f); @@ -2645,17 +2527,32 @@ TEST_P(EGLSingleBufferTest, AcquireImageFromSwapImpl) context = EGL_NO_CONTEXT; } -// Test that setting a surface to EGL_SINGLE_BUFFER after enabling -// EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID does not disable auto refresh -TEST_P(EGLAndroidAutoRefreshTest, Basic) +// Tests that staged clear into MSAA surface is resolved and not dropped on swap. +TEST_P(EGLSingleBufferTest, StagedClearResolveOnSwap) { - ANGLE_SKIP_TEST_IF( - !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_front_buffer_auto_refresh")); ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); - ANGLE_SKIP_TEST_IF(!IsAndroid()); - EGLConfig config = EGL_NO_CONFIG_KHR; - ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true)); + EGLConfig config = EGL_NO_CONFIG_KHR; + const EGLint attribs[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_SAMPLE_BUFFERS, + 1, + EGL_SAMPLES, + 4, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_NONE}; + EGLint count = 0; + ANGLE_SKIP_TEST_IF(!eglChooseConfig(mDisplay, attribs, &config, 1, &count)); + ANGLE_SKIP_TEST_IF(count == 0); EGLContext context = EGL_NO_CONTEXT; EXPECT_EGL_TRUE(createContext(config, &context)); @@ -2671,40 +2568,17 @@ TEST_P(EGLAndroidAutoRefreshTest, Basic) EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; - EXPECT_EGL_TRUE( - eglSurfaceAttrib(mDisplay, surface, EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID, EGL_TRUE)); - EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); - - // Transition into EGL_SINGLE_BUFFER mode. - glClearColor(1.0, 1.0, 1.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); if (eglSwapBuffers(mDisplay, surface)) { - EGLint actualRenderbuffer; - EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); - EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER); - - glClearColor(0.0, 1.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - glFlush(); - // Flush should result in update of screen. Must be visually confirmed Green window. - - // Check color for automation. - EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green); - - // Switch back to EGL_BACK_BUFFER and check. - EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER)); - glClearColor(1.0, 1.0, 1.0, 1.0); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface)); - EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); - EXPECT_EGL_TRUE(actualRenderbuffer == EGL_BACK_BUFFER); + // Flush here performs swap and tests the code that performs the resolve optimization. + glFlush(); - glClearColor(1.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + // Confirm that staged clear was not dropped in the above resolve on swap optimization. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); } else { @@ -2723,24 +2597,32 @@ TEST_P(EGLAndroidAutoRefreshTest, Basic) context = EGL_NO_CONTEXT; } -// Tests that CPU throttling unlocked call, added in the implicit swap buffers call, is executed. -TEST_P(EGLAndroidAutoRefreshTest, SwapCPUThrottling) +// Tests that SharedPresent image layout is not changed by the renderpass resolve operation. +TEST_P(EGLSingleBufferTest, SharedPresentLayoutWithMSAA) { - ANGLE_SKIP_TEST_IF( - !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_front_buffer_auto_refresh")); ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); - ANGLE_SKIP_TEST_IF(!IsAndroid()); - - // Use high resolution to increase GPU load. - const EGLint kWidth = 2048; - const EGLint kHeight = 2048; - - // These settings are expected to trigger CPU throttling in present. - constexpr size_t kFrameFlushCount = 8; - constexpr GLuint kDrawInstanceCount = 256; - EGLConfig config = EGL_NO_CONFIG_KHR; - ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true)); + EGLConfig config = EGL_NO_CONFIG_KHR; + const EGLint attribs[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_SAMPLE_BUFFERS, + 1, + EGL_SAMPLES, + 4, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_NONE}; + EGLint count = 0; + ANGLE_SKIP_TEST_IF(!eglChooseConfig(mDisplay, attribs, &config, 1, &count)); + ANGLE_SKIP_TEST_IF(count == 0); EGLContext context = EGL_NO_CONTEXT; EXPECT_EGL_TRUE(createContext(config, &context)); @@ -2750,36 +2632,20 @@ TEST_P(EGLAndroidAutoRefreshTest, SwapCPUThrottling) OSWindow *osWindow = OSWindow::New(); osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight); EXPECT_EGL_TRUE( - createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_SINGLE_BUFFER)); + createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER)); ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed."; EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; - EGLint actualRenderbuffer; - EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); - if (actualRenderbuffer == EGL_SINGLE_BUFFER) + EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + if (eglSwapBuffers(mDisplay, surface)) { - // Enable auto refresh to prevent present from waiting on GPU. - EXPECT_EGL_TRUE( - eglSurfaceAttrib(mDisplay, surface, EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID, EGL_TRUE)); - - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glViewport(0, 0, kWidth, kHeight); - - for (size_t i = 0; i < kFrameFlushCount; ++i) - { - // Perform heavy draw call to load GPU. - drawQuadInstanced(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, false, - kDrawInstanceCount); - // This should cause implicit swap and possible CPU throttling in the tail call. - glFlush(); - } - - // Tests same as the glFlush above. - drawQuadInstanced(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, false, - kDrawInstanceCount); - glFinish(); + // Draw using renderpass. + ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f); + // This should perform resolve with renderpass but must keep the SharedPresent layout. + glFlush(); } else { @@ -2798,246 +2664,1400 @@ TEST_P(EGLAndroidAutoRefreshTest, SwapCPUThrottling) context = EGL_NO_CONTEXT; } -void EGLSurfaceTest::runWaitSemaphoreTest(bool useSecondContext) +// Tests that Window resize does not invalidate the previous content. +TEST_P(EGLSingleBufferTest, WindowResize) { - // Note: This test requires visual inspection for rendering artifacts. - // However, absence of artifacts does not guarantee that there is no problem. - - initializeDisplay(); + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); - constexpr int kInitialSize = 64; - constexpr int kWindowWidth = 1080; - constexpr int kWindowWHeight = 1920; + EGLConfig config = EGL_NO_CONFIG_KHR; + ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true)); - mOSWindow->resize(kWindowWidth, kWindowWHeight); + EGLContext context = EGL_NO_CONTEXT; + EXPECT_EGL_TRUE(createContext(config, &context)); + ASSERT_EGL_SUCCESS() << "eglCreateContext failed."; - // Initialize an RGBA8 window and pbuffer surface - constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, - EGL_NONE}; + EGLSurface surface = EGL_NO_SURFACE; + OSWindow *osWindow = OSWindow::New(); + osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight); + EXPECT_EGL_TRUE( + createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER)); + ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed."; - EGLint configCount = 0; - EGLConfig surfaceConfig = nullptr; - ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); - ASSERT_NE(configCount, 0); - ASSERT_NE(surfaceConfig, nullptr); + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; - initializeSurface(surfaceConfig); - initializeMainContext(); - ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE); + EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); - eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + // Transition into EGL_SINGLE_BUFFER mode. + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + if (eglSwapBuffers(mDisplay, surface)) + { + EGLint actualRenderbuffer; + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); + EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER); + + glEnable(GL_SCISSOR_TEST); + + // Draw before resize + glScissor(0, 0, 2, 2); + glClearColor(0.0, 1.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + + // Window resize should not invalidate the previous content. Note, window resize may be + // ignored to preserve the content (native GLES Android behavior). + osWindow->resize(kWidth + 16, kHeight + 16); + + // Draw after resize + glScissor(1, 1, 1, 1); + glClearColor(1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + + // Check result from both draws. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + } + else + { + std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl; + } + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed."; + + eglDestroySurface(mDisplay, surface); + surface = EGL_NO_SURFACE; + osWindow->destroy(); + OSWindow::Delete(&osWindow); + + eglDestroyContext(mDisplay, context); + context = EGL_NO_CONTEXT; +} + +// Tests that Window rotation does not invalidate the previous content. +TEST_P(EGLSingleBufferTest, WindowRotation) +{ + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); + // This test uses functionality that is only available on Android + ANGLE_SKIP_TEST_IF(!IsAndroid()); + + EGLConfig config = EGL_NO_CONFIG_KHR; + ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true)); + + EGLContext context = EGL_NO_CONTEXT; + EXPECT_EGL_TRUE(createContext(config, &context)); + ASSERT_EGL_SUCCESS() << "eglCreateContext failed."; + + EGLSurface surface = EGL_NO_SURFACE; + OSWindow *osWindow = OSWindow::New(); + osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight); + EXPECT_EGL_TRUE( + createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER)); + ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed."; + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; + + EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + + // Transition into EGL_SINGLE_BUFFER mode. + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + if (eglSwapBuffers(mDisplay, surface)) + { + EGLint actualRenderbuffer; + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); + EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER); + + glEnable(GL_SCISSOR_TEST); + + // Set landscape orientation. Note, this will not change window size. + osWindow->setOrientation(200, 100); + angle::Sleep(1000); + + // Draw in landscape orientation. + glScissor(0, 0, 2, 2); + glClearColor(0.0, 1.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + + // Set portrait orientation. Window rotation should not invalidate the previous content. + // Note, window rotation may be ignored to preserve content (native GLES Android behavior). + osWindow->setOrientation(100, 200); + angle::Sleep(1000); + + // Draw in portrait orientation. + glScissor(1, 1, 1, 1); + glClearColor(1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + + // Check result from both draws. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + } + else + { + std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl; + } + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed."; + + eglDestroySurface(mDisplay, surface); + surface = EGL_NO_SURFACE; + osWindow->destroy(); + OSWindow::Delete(&osWindow); + + eglDestroyContext(mDisplay, context); + context = EGL_NO_CONTEXT; +} + +// Test that setting a surface to EGL_SINGLE_BUFFER after enabling +// EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID does not disable auto refresh +TEST_P(EGLAndroidAutoRefreshTest, Basic) +{ + ANGLE_SKIP_TEST_IF( + !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_front_buffer_auto_refresh")); + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); + ANGLE_SKIP_TEST_IF(!IsAndroid()); + + EGLConfig config = EGL_NO_CONFIG_KHR; + ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true)); + + EGLContext context = EGL_NO_CONTEXT; + EXPECT_EGL_TRUE(createContext(config, &context)); + ASSERT_EGL_SUCCESS() << "eglCreateContext failed."; + + EGLSurface surface = EGL_NO_SURFACE; + OSWindow *osWindow = OSWindow::New(); + osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight); + EXPECT_EGL_TRUE( + createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER)); + ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed."; + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; + + EXPECT_EGL_TRUE( + eglSurfaceAttrib(mDisplay, surface, EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID, EGL_TRUE)); + + EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + + // Transition into EGL_SINGLE_BUFFER mode. + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + if (eglSwapBuffers(mDisplay, surface)) + { + EGLint actualRenderbuffer; + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); + EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER); + + glClearColor(0.0, 1.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + // Flush should result in update of screen. Must be visually confirmed Green window. + + // Check color for automation. + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green); + + // Switch back to EGL_BACK_BUFFER and check. + EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER)); + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface)); + + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); + EXPECT_EGL_TRUE(actualRenderbuffer == EGL_BACK_BUFFER); + + glClearColor(1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + } + else + { + std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl; + } + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed."; + + eglDestroySurface(mDisplay, surface); + surface = EGL_NO_SURFACE; + osWindow->destroy(); + OSWindow::Delete(&osWindow); + + eglDestroyContext(mDisplay, context); + context = EGL_NO_CONTEXT; +} + +// Tests that CPU throttling unlocked call, added in the implicit swap buffers call, is executed. +TEST_P(EGLAndroidAutoRefreshTest, SwapCPUThrottling) +{ + ANGLE_SKIP_TEST_IF( + !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_front_buffer_auto_refresh")); + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); + ANGLE_SKIP_TEST_IF(!IsAndroid()); + + // Use high resolution to increase GPU load. + const EGLint kWidth = 2048; + const EGLint kHeight = 2048; + + // These settings are expected to trigger CPU throttling in present. + constexpr size_t kFrameFlushCount = 8; + constexpr GLuint kDrawInstanceCount = 256; + + EGLConfig config = EGL_NO_CONFIG_KHR; + ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true)); + + EGLContext context = EGL_NO_CONTEXT; + EXPECT_EGL_TRUE(createContext(config, &context)); + ASSERT_EGL_SUCCESS() << "eglCreateContext failed."; + + EGLSurface surface = EGL_NO_SURFACE; + OSWindow *osWindow = OSWindow::New(); + osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight); + EXPECT_EGL_TRUE( + createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_SINGLE_BUFFER)); + ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed."; + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; + + EGLint actualRenderbuffer; + EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer)); + if (actualRenderbuffer == EGL_SINGLE_BUFFER) + { + // Enable auto refresh to prevent present from waiting on GPU. + EXPECT_EGL_TRUE( + eglSurfaceAttrib(mDisplay, surface, EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID, EGL_TRUE)); + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glViewport(0, 0, kWidth, kHeight); + + for (size_t i = 0; i < kFrameFlushCount; ++i) + { + // Perform heavy draw call to load GPU. + drawQuadInstanced(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, false, + kDrawInstanceCount); + // This should cause implicit swap and possible CPU throttling in the tail call. + glFlush(); + } + + // Tests same as the glFlush above. + drawQuadInstanced(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, false, + kDrawInstanceCount); + glFinish(); + } + else + { + std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl; + } + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed."; + + eglDestroySurface(mDisplay, surface); + surface = EGL_NO_SURFACE; + osWindow->destroy(); + OSWindow::Delete(&osWindow); + + eglDestroyContext(mDisplay, context); + context = EGL_NO_CONTEXT; +} + +// Tests that draw draw does not also synchronize read framebuffer binding. +TEST_P(EGLSurfaceTest, ReadFramebufferBindingSyncState) +{ + // This test uses functionality that is only available on Android + ANGLE_SKIP_TEST_IF(!IsAndroid()); + + const EGLint kPortraitWidth = 128; + const EGLint kPortraitHeight = 256; + + // Set portrait orientation before surface creation. + mOSWindow->resize(kPortraitWidth, kPortraitHeight); + mOSWindow->setOrientation(kPortraitWidth, kPortraitHeight); + angle::Sleep(1000); + + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + // Make sure swapchain is created. + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + // Set landscape orientation after swapchain creation. Note, this will not change window size. + mOSWindow->setOrientation(kPortraitHeight, kPortraitWidth); + angle::Sleep(1000); + + // Current swapchain is expected to be invalidated because of the present SUBOPTIMAL result. + // This will invalidate draw and read framebuffer bindings context state dirty bits. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 64, 64); + ASSERT_GL_NO_ERROR(); + + // Bind only draw framebuffer, keeping default read framebuffer. + GLFramebuffer fbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + ASSERT_GL_NO_ERROR(); + + // Draw should not sync read framebuffer binding (at least not without read framebuffer object). + ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + drawQuad(drawRed.get(), essl3_shaders::PositionAttrib(), 0.8f); + ASSERT_GL_NO_ERROR(); + + // Clear default framebuffer. This should sync both, read framebuffer object and binding. + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + // Check the entire surface. + EXPECT_PIXEL_RECT_EQ(0, 0, kPortraitWidth, kPortraitHeight, GLColor::red); + + // Revert to the portrait orientation. + mOSWindow->setOrientation(kPortraitWidth, kPortraitHeight); + angle::Sleep(1000); +} + +void EGLSurfaceTest::runWaitSemaphoreTest(bool useSecondContext) +{ + // Note: This test requires visual inspection for rendering artifacts. + // However, absence of artifacts does not guarantee that there is no problem. + + initializeDisplay(); + + constexpr int kInitialSize = 64; + constexpr int kWindowWidth = 1080; + constexpr int kWindowWHeight = 1920; + + mOSWindow->resize(kWindowWidth, kWindowWHeight); + + // Initialize an RGBA8 window and pbuffer surface + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, + EGL_NONE}; + + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ASSERT_NE(configCount, 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query")); + + if (useSecondContext) + { + ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading()); + initializeSingleContext(&mSecondContext, 0); + } + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glUseProgram(program); + ASSERT_GL_NO_ERROR(); + + GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib()); + ASSERT_NE(posAttrib, -1); + glEnableVertexAttribArray(posAttrib); + ASSERT_GL_NO_ERROR(); + + GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform()); + ASSERT_NE(colorUniformLocation, -1); + + constexpr int kFrameCount = 60 * 4; // 4 sec @ 60Hz; 2 sec @ 120Hz; + constexpr int kGridW = 5; + constexpr int kGridH = 5; + constexpr int kAnimDiv = 20; + + for (int frame = 0; frame < kFrameCount; ++frame) + { + glClearColor(0.1f, 0.1f, 0.2f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + for (int y = 0; y < kGridH; ++y) + { + // This should force "flushToPrimary()" each line in ANGLE + GLuint query; + glGenQueries(1, &query); + ASSERT_GL_NO_ERROR(); + glBeginQuery(GL_TIME_ELAPSED_EXT, query); + ASSERT_GL_NO_ERROR(); + + for (int x = 0; x < kGridW; ++x) + { + const int xc = (x + frame / kAnimDiv) % kGridW; + const Vector4 color = {(xc + 0.5f) / kGridW, (y + 0.5f) / kGridH, 0.0f, 1.0f}; + + const GLfloat x0 = (x + 0.1f) / kGridW * 2.0f - 1.0f; + const GLfloat x1 = (x + 0.9f) / kGridW * 2.0f - 1.0f; + const GLfloat y0 = (y + 0.1f) / kGridH * 2.0f - 1.0f; + const GLfloat y1 = (y + 0.9f) / kGridH * 2.0f - 1.0f; + + std::array vertexData; + vertexData[0] = {x0, y1, 0.5f}; + vertexData[1] = {x0, y0, 0.5f}; + vertexData[2] = {x1, y1, 0.5f}; + vertexData[3] = {x1, y1, 0.5f}; + vertexData[4] = {x0, y0, 0.5f}; + vertexData[5] = {x1, y0, 0.5f}; + + glUniform4f(colorUniformLocation, color.x(), color.y(), color.z(), color.w()); + glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertexData.data()); + glDrawArrays(GL_TRIANGLES, 0, 6); + ASSERT_GL_NO_ERROR(); + } + + glEndQuery(GL_TIME_ELAPSED_EXT); + glDeleteQueries(1, &query); + ASSERT_GL_NO_ERROR(); + } + + if (useSecondContext) + { + std::thread([this] { + eglBindAPI(EGL_OPENGL_ES_API); + ASSERT_EGL_SUCCESS(); + eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mSecondContext); + ASSERT_EGL_SUCCESS(); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + ASSERT_EGL_SUCCESS(); + }).join(); + } + else + { + eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext); + ASSERT_EGL_SUCCESS(); + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + ASSERT_EGL_SUCCESS(); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + } + + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + } + + mOSWindow->resize(kInitialSize, kInitialSize); +} + +// Test that there no artifacts because of the bug when wait semaphore could be added after +// rendering commands. This was possible by switching to Pbuffer surface and submit. +TEST_P(EGLSurfaceTest, DISABLED_WaitSemaphoreAddedAfterCommands) +{ + runWaitSemaphoreTest(false); +} + +// Test that there no artifacts because of the bug when rendering commands could be submitted +// without adding wait semaphore. This was possible if submit commands from other thread. +TEST_P(EGLSurfaceTest, DISABLED_CommandsSubmittedWithoutWaitSemaphore) +{ + runWaitSemaphoreTest(true); +} + +void EGLSurfaceTest::runDestroyNotCurrentSurfaceTest(bool testWindowsSurface) +{ + initializeDisplay(); + + // Initialize an RGBA8 window and pbuffer surface + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, + EGL_NONE}; + + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ASSERT_NE(configCount, 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE); + + EGLSurface &testSurface = testWindowsSurface ? mWindowSurface : mPbufferSurface; + EGLSurface &otherSurface = testWindowsSurface ? mPbufferSurface : mWindowSurface; + + eglMakeCurrent(mDisplay, testSurface, testSurface, mContext); + ASSERT_EGL_SUCCESS(); + + // Start RenderPass in the testSurface + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 4, 4); + glClearColor(0.5f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + ASSERT_GL_NO_ERROR(); + + // Make other surface current keeping the context. + // If bug present, the context may have unflushed work, related to the testSurface. + eglMakeCurrent(mDisplay, otherSurface, otherSurface, mContext); + ASSERT_EGL_SUCCESS(); + + if (testWindowsSurface) + { + // This may flush Window Surface RenderPass + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 4, 4); + glClearColor(0.5f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + ASSERT_GL_NO_ERROR(); + } + + // Destroy the surface + eglDestroySurface(mDisplay, testSurface); + testSurface = EGL_NO_SURFACE; + + // This will submit all work (if bug present - include work related to the deleted testSurface). + eglMakeCurrent(mDisplay, otherSurface, otherSurface, mContext); + ASSERT_EGL_SUCCESS(); +} + +// Test that there is no crash because of the bug when not current PBuffer Surface destroyed, while +// there are still unflushed work in the Context. +TEST_P(EGLSurfaceTest, DestroyNotCurrentPbufferSurface) +{ + runDestroyNotCurrentSurfaceTest(false); +} + +// Test that there is no crash because of the bug when not current Window Surface destroyed, while +// there are still unflushed work in the Context. +TEST_P(EGLSurfaceTest, DestroyNotCurrentWindowSurface) +{ + runDestroyNotCurrentSurfaceTest(true); +} + +// Test that there is no tearing because of incorrect pipeline barriers +TEST_P(EGLSurfaceTest, DISABLED_RandomClearTearing) +{ + // Note: This test requires visual inspection for rendering artifacts. + // However, absence of artifacts does not guarantee that there is no problem. + + initializeDisplay(); + + constexpr int kInitialSize = 64; + constexpr int kWindowWidth = 1080; + constexpr int kWindowWHeight = 1920; + + mOSWindow->resize(kWindowWidth, kWindowWHeight); + + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + constexpr int kFrameCount = 60 * 4; // 4 sec @ 60Hz; 2 sec @ 120Hz; + + for (int frame = 0; frame < kFrameCount; ++frame) + { + glClearColor(rand() % 256 / 255.0f, rand() % 256 / 255.0f, rand() % 256 / 255.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + } + + mOSWindow->resize(kInitialSize, kInitialSize); +} + +// Make sure a surface (from the same window) can be recreated after being destroyed, even if it's +// still current. +// This is to recreate the app behavior in https://issuetracker.google.com/292285899, which is +// not the correct spec behavior. It serves as a purpose to test the workaround feature +// uncurrent_egl_surface_upon_surface_destroy that is enabled only on vulkan backend to help +// the app get over the problem. +TEST_P(EGLSurfaceTest, DestroyAndRecreateWhileCurrent) +{ + setWindowVisible(mOSWindow, true); + + initializeDisplay(); + + mConfig = chooseDefaultConfig(true); + ASSERT_NE(mConfig, nullptr); + + EGLint surfaceType = EGL_NONE; + eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType); + ASSERT_NE((surfaceType & EGL_WINDOW_BIT), 0); + + initializeWindowSurfaceWithAttribs(mConfig, {}, EGL_SUCCESS); + initializeMainContext(); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + // Draw with this surface to make sure it's used. + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glViewport(0, 0, 64, 64); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + + // Destroy the surface while it's current; it won't actually be destroyed. + eglDestroySurface(mDisplay, mWindowSurface); + mWindowSurface = EGL_NO_SURFACE; + + // Create another surface from the same window right away. + initializeWindowSurfaceWithAttribs(mConfig, {}, EGL_SUCCESS); + + // Make the new surface current; this leads to the actual destruction of the previous surface. + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); + ASSERT_EGL_SUCCESS(); + + // Verify everything still works + ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + +// Regression test for a bug where destroying more than 2 surfaces during termination +// overflowed the unlocked tail call storage. +TEST_P(EGLSurfaceTest, CreateMultiWindowsSurfaceNoDestroy) +{ + initializeDisplay(); + + // Initialize and create multi RGBA8 window surfaces + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, + EGL_NONE}; + + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ASSERT_NE(configCount, 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + + // Create 3 window surfaces to trigger error + std::vector windowAttributes; + windowAttributes.push_back(EGL_NONE); + + for (int i = 0; i < 3; i++) + { + OSWindow *w = OSWindow::New(); + w->initialize("EGLSurfaceTest", 64, 64); + + eglCreateWindowSurface(mDisplay, mConfig, w->getNativeWindow(), windowAttributes.data()); + ASSERT_EGL_SUCCESS(); + mOtherWindows.push_back(w); + } +} + +// Test that querying EGL_RENDER_BUFFER of surface and context returns correct value. +// Context's render buffer should only change once eglSwapBuffers is called. +TEST_P(EGLSurfaceTest, QueryRenderBuffer) +{ + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); + ANGLE_SKIP_TEST_IF(!IsAndroid()); + + const EGLint configAttributes[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, + EGL_NONE}; + + initializeDisplay(); + ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE); + + // Create window surface and make current + mWindowSurface = + eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr); + ASSERT_EGL_SUCCESS(); + ASSERT_NE(EGL_NO_SURFACE, mWindowSurface); + + initializeMainContext(); + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); + ASSERT_EGL_SUCCESS(); + + // Set to single buffer mode and query the value + ASSERT_EGL_TRUE( + eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + + EGLint queryRenderBuffer; + ASSERT_EGL_TRUE( + eglQuerySurface(mDisplay, mWindowSurface, EGL_RENDER_BUFFER, &queryRenderBuffer)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(queryRenderBuffer, EGL_SINGLE_BUFFER); + + ASSERT_EGL_TRUE(eglQueryContext(mDisplay, mContext, EGL_RENDER_BUFFER, &queryRenderBuffer)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(queryRenderBuffer, EGL_BACK_BUFFER); + + // Swap buffers and then query the value + ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); + ASSERT_EGL_SUCCESS(); + + ASSERT_EGL_TRUE( + eglQuerySurface(mDisplay, mWindowSurface, EGL_RENDER_BUFFER, &queryRenderBuffer)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(queryRenderBuffer, EGL_SINGLE_BUFFER); + + ASSERT_EGL_TRUE(eglQueryContext(mDisplay, mContext, EGL_RENDER_BUFFER, &queryRenderBuffer)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(queryRenderBuffer, EGL_SINGLE_BUFFER); + + ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + ASSERT_EGL_TRUE(eglDestroySurface(mDisplay, mWindowSurface)); + mWindowSurface = EGL_NO_SURFACE; + ASSERT_EGL_TRUE(eglDestroyContext(mDisplay, mContext)); + mContext = EGL_NO_CONTEXT; + ASSERT_EGL_SUCCESS(); +} + +// Test that new API eglQuerySupportedCompressionRatesEXT could work, and +// validation for the API should also work. If any rate can be queried, then use +// that rate to create window surface. Query the surface's compression rate +// should get the expected rate, and a simple draw should succeed on the surface. +TEST_P(EGLSurfaceTest, SurfaceFixedRateCompression) +{ + initializeDisplay(); + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_surface_compression")); + // Initialize an RGBA8 window and pbuffer surface + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_NONE}; + EGLint configCount = 0; + EGLint numRates = 0; + EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &mConfig, 1, &configCount)); + ASSERT_NE(configCount, 0); + ASSERT_NE(mConfig, nullptr); + // Fail, invalid display + EXPECT_EGL_FALSE(eglQuerySupportedCompressionRatesEXT(EGL_NO_DISPLAY, mConfig, nullptr, nullptr, + 0, &numRates)); + ASSERT_EGL_ERROR(EGL_BAD_DISPLAY); + // Fail, rate_size < 0 + EXPECT_EGL_FALSE( + eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, nullptr, nullptr, -1, &numRates)); + ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); + // Fail, pointer rates is nullptr + EXPECT_EGL_FALSE( + eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, nullptr, nullptr, 1, &numRates)); + ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); + // Fail, return num_rates is nullptr + EXPECT_EGL_FALSE( + eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, nullptr, nullptr, 0, nullptr)); + ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); + EGLint rates[3]; + // Success, actual values of rates are depended on each platform + EXPECT_EGL_TRUE( + eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, NULL, rates, 3, &numRates)); + ASSERT_EGL_SUCCESS(); + + if (numRates > 0 && rates[0] != EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT) + { + // If any rate can be queried, then use that rate to create window surface and test + std::vector winSurfaceAttribs; + winSurfaceAttribs.push_back(EGL_SURFACE_COMPRESSION_EXT); + winSurfaceAttribs.push_back(rates[0]); + // Create window surface using the selected rate. + initializeWindowSurfaceWithAttribs(mConfig, winSurfaceAttribs, EGL_SUCCESS); + ASSERT_EGL_SUCCESS(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + EGLint selectedRate; + ASSERT_EGL_TRUE( + eglQuerySurface(mDisplay, mWindowSurface, EGL_SURFACE_COMPRESSION_EXT, &selectedRate)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(selectedRate, rates[0]); + initializeMainContext(); + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); + ASSERT_EGL_SUCCESS(); + // Make sure the surface works. Draw red and verify. + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glUseProgram(program); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, nullptr, nullptr, mContext)); + EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, mWindowSurface)); + mWindowSurface = EGL_NO_SURFACE; + + // Create another surface using default rate. + winSurfaceAttribs.back() = EGL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT; + initializeWindowSurfaceWithAttribs(mConfig, winSurfaceAttribs, EGL_SUCCESS); + ASSERT_EGL_SUCCESS(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + selectedRate = EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT; + ASSERT_EGL_TRUE( + eglQuerySurface(mDisplay, mWindowSurface, EGL_SURFACE_COMPRESSION_EXT, &selectedRate)); + ASSERT_EGL_SUCCESS(); + ASSERT_NE(selectedRate, EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT); + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); + ASSERT_EGL_SUCCESS(); + // Make sure the surface works. Draw red and verify. + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); + } +} + +// Test the validation errors for eglSetDamageRegionKHR +TEST_P(EGLSurfaceTest, SetDamageRegionNegativeValidation) +{ + initializeDisplay(); + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_partial_update")); + + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE}; + + EGLint age = 0; + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + + ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ASSERT_NE(configCount, 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + initializeAllContexts(); + EXPECT_EGL_SUCCESS(); + EXPECT_NE(mWindowSurface, EGL_NO_SURFACE); + EXPECT_NE(mPbufferSurface, EGL_NO_SURFACE); + + // Fail: surface is not a postable surface + EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mPbufferSurface, nullptr, 0)); + EXPECT_EGL_ERROR(EGL_BAD_MATCH); + + // Fail: surface is not the current draw surface for the calling thread + EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); + EXPECT_EGL_ERROR(EGL_BAD_MATCH); + + EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mSecondContext)); + EXPECT_EGL_SUCCESS(); + + // Fail: EGL_BUFFER_AGE_KHR attribute of surface has not been queried since the most recent + // frame boundary + EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); + EXPECT_EGL_ERROR(EGL_BAD_ACCESS); + + // Perform empty swap + EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); + EXPECT_EGL_SUCCESS(); + + EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_BUFFER_AGE_KHR, &age)); + EXPECT_EGL_SUCCESS(); + EXPECT_GE(age, 0); + + // Fail: n_rects should be a valid value + EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, -1)); + EXPECT_EGL_ERROR(EGL_BAD_PARAMETER); + + // Success + EXPECT_EGL_TRUE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); + EXPECT_EGL_SUCCESS(); + + // Fail: damage region has already been set on surface since the most recent frame boundary + EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); + EXPECT_EGL_ERROR(EGL_BAD_ACCESS); +} + +// Verifies that swapchain image is transitioned into the Present layout after MSAA resolve, +// regardless if it was performed as part of the renderpass or by using an outside renderpass +// command. +TEST_P(EGLSurfaceTest, PresentLayoutTransitionWithMSAA) +{ + initializeDisplay(); + + constexpr EGLint kInitialSize = 64; + + // Initialize an RGBA8 window surface with 4x MSAA + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_SAMPLE_BUFFERS, + 1, + EGL_SAMPLES, + 4, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_NONE}; + + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + ANGLE_SKIP_TEST_IF( + !eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ANGLE_SKIP_TEST_IF(configCount == 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + initializeMainContext(); ASSERT_EGL_SUCCESS(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query")); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); - if (useSecondContext) - { - ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading()); - initializeSingleContext(&mSecondContext, 0); - } + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glUseProgram(program); - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glViewport(0, 0, kInitialSize, kInitialSize); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + // Tests that swapchain image layout is in Present layout after resolve with renderpass. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, kInitialSize / 2, kInitialSize / 2); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + // Tests that swapchain image layout is in Present layout after outside renderpass resolve. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); +} + +// Test resolve a 4xMSAA surface that supports a EGLConfig without alpha support +TEST_P(EGLSurfaceTest, MSAAResolveWithEGLConfig8880) +{ + initializeDisplay(); + + // Initialize an RGB8 window surface with 4x MSAA + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 0, + EGL_SAMPLE_BUFFERS, + 1, + EGL_SAMPLES, + 4, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_NONE}; + + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + ANGLE_SKIP_TEST_IF( + !eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ANGLE_SKIP_TEST_IF(configCount == 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + initializeMainContext(); + ASSERT_EGL_SUCCESS(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); glUseProgram(program); - ASSERT_GL_NO_ERROR(); - GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib()); - ASSERT_NE(posAttrib, -1); - glEnableVertexAttribArray(posAttrib); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + // Tests resolve during read pixels. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Tests outside renderpass resolve during swap. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + // Tests renderpass resolve during swap. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); +} + +// Regression test for a bug in the Vulkan backend where a staged clear was not applied if +// glGetMultisamplefv is called. +TEST_P(EGLSurfaceTest, GetMultisamplefvAfterClear) +{ + initializeDisplay(); + + // Initialize an RGBA8 window surface with 4x MSAA + constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_SAMPLE_BUFFERS, + 1, + EGL_SAMPLES, + 4, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_NONE}; + + EGLint configCount = 0; + EGLConfig surfaceConfig = nullptr; + ANGLE_SKIP_TEST_IF( + !eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ANGLE_SKIP_TEST_IF(configCount == 0); + ASSERT_NE(surfaceConfig, nullptr); + + initializeSurface(surfaceConfig); + initializeMainContext(); + ASSERT_EGL_SUCCESS(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_texture_multisample")); + + // Clear operation will be staged (Vulkan backend). + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // Calling this API will perform draw framebuffer sync which will flush staged clear. + // If there is no bug, clear will not be deferred during the flush. + GLfloat samplePosition[2]; + glGetMultisamplefvANGLE(GL_SAMPLE_POSITION, 0, samplePosition); ASSERT_GL_NO_ERROR(); - GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform()); - ASSERT_NE(colorUniformLocation, -1); + // Prepare auxiliary framebuffer. + GLFramebuffer framebuffer; + GLRenderbuffer renderBuffer; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 50, 50); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + renderBuffer); + EXPECT_GL_NO_ERROR(); - constexpr int kFrameCount = 60 * 4; // 4 sec @ 60Hz; 2 sec @ 120Hz; - constexpr int kGridW = 5; - constexpr int kGridH = 5; - constexpr int kAnimDiv = 20; + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); - for (int frame = 0; frame < kFrameCount; ++frame) + // Check default framebuffer contains expected value. + // In case of a bug, previously deferred clear will not be applied. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +int EGLSurfaceTest::drawSizeCheckRect(EGLSurface surface, + GLsizei checkRectWidth, + GLsizei checkRectHeight) +{ + glDisable(GL_SCISSOR_TEST); + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glEnable(GL_SCISSOR_TEST); + glScissor(1, 1, checkRectWidth - 2, checkRectHeight - 2); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + + const angle::GLColor referenceColors[8] = {GLColor::green, GLColor::green, GLColor::red, + GLColor::red, GLColor::red, GLColor::red, + GLColor::green, GLColor::green}; + angle::GLColor surfaceColors[std::size(referenceColors)]; + + // Pixels are listed in a scanning order (left->right, bottom->top). + surfaceColors[0] = angle::ReadColor(0, 0); + surfaceColors[1] = angle::ReadColor(checkRectWidth - 1, 0); + surfaceColors[2] = angle::ReadColor(1, 1); + surfaceColors[3] = angle::ReadColor(checkRectWidth - 2, 1); + surfaceColors[4] = angle::ReadColor(1, checkRectHeight - 2); + surfaceColors[5] = angle::ReadColor(checkRectWidth - 2, checkRectHeight - 2); + surfaceColors[6] = angle::ReadColor(0, checkRectHeight - 1); + surfaceColors[7] = angle::ReadColor(checkRectWidth - 1, checkRectHeight - 1); + EXPECT_GL_NO_ERROR(); + + EXPECT_EQ(surfaceColors[0], referenceColors[0]); + EXPECT_EQ(surfaceColors[1], referenceColors[1]); + EXPECT_EQ(surfaceColors[2], referenceColors[2]); + EXPECT_EQ(surfaceColors[3], referenceColors[3]); + EXPECT_EQ(surfaceColors[4], referenceColors[4]); + EXPECT_EQ(surfaceColors[5], referenceColors[5]); + EXPECT_EQ(surfaceColors[6], referenceColors[6]); + EXPECT_EQ(surfaceColors[7], referenceColors[7]); + + int result = 0; + for (size_t i = 0; i < std::size(referenceColors); ++i) { - glClearColor(0.1f, 0.1f, 0.2f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - ASSERT_GL_NO_ERROR(); + result += (surfaceColors[i] != referenceColors[i]) ? 1 : 0; + } - for (int y = 0; y < kGridH; ++y) - { - // This should force "flushToPrimary()" each line in ANGLE - GLuint query; - glGenQueries(1, &query); - ASSERT_GL_NO_ERROR(); - glBeginQuery(GL_TIME_ELAPSED_EXT, query); - ASSERT_GL_NO_ERROR(); + // Surface size must not change after the draw. + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; + eglQuerySurface(mDisplay, surface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, surface, EGL_HEIGHT, &surfaceHeight); + EXPECT_EGL_SUCCESS(); + EXPECT_EQ(surfaceWidth, checkRectWidth); + EXPECT_EQ(surfaceHeight, checkRectHeight); - for (int x = 0; x < kGridW; ++x) - { - const int xc = (x + frame / kAnimDiv) % kGridW; - const Vector4 color = {(xc + 0.5f) / kGridW, (y + 0.5f) / kGridH, 0.0f, 1.0f}; + result += (surfaceWidth != checkRectWidth) ? 10 : 0; + result += (surfaceHeight != checkRectHeight) ? 10 : 0; - const GLfloat x0 = (x + 0.1f) / kGridW * 2.0f - 1.0f; - const GLfloat x1 = (x + 0.9f) / kGridW * 2.0f - 1.0f; - const GLfloat y0 = (y + 0.1f) / kGridH * 2.0f - 1.0f; - const GLfloat y1 = (y + 0.9f) / kGridH * 2.0f - 1.0f; + return result; +} - std::array vertexData; - vertexData[0] = {x0, y1, 0.5f}; - vertexData[1] = {x0, y0, 0.5f}; - vertexData[2] = {x1, y1, 0.5f}; - vertexData[3] = {x1, y1, 0.5f}; - vertexData[4] = {x0, y0, 0.5f}; - vertexData[5] = {x1, y0, 0.5f}; +// Tests window surface resize after swap that follows window resize. +TEST_P(EGLSurfaceTest, ResizeAfterSwap) +{ + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{199, 500}; + constexpr std::array kHeights{499, 200}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + for (size_t i = 0; i < kSizeCount; ++i) + { + // Resize before swap. + mOSWindow->resize(kWidths[i], kHeights[i]); + + // Swap must resize the surface if it is not already resized. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; + + // Surface must have window size after swap. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + EXPECT_EQ(surfaceWidth, kWidths[i]); + EXPECT_EQ(surfaceHeight, kHeights[i]); + + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); + } +} + +// Tests window surface resize after swap that follows window resize, while skipping size query. +TEST_P(EGLSurfaceTest, ResizeAfterSwapSkipSizeQuery) +{ + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{199, 500}; + constexpr std::array kHeights{499, 200}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); + + for (size_t i = 0; i < kSizeCount; ++i) + { + // Resize before swap. + mOSWindow->resize(kWidths[i], kHeights[i]); + + // Swap must resize the surface if it is not already resized. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, kWidths[i], kHeights[i]), 0); + } +} + +// Tests window surface resize when window is resized before draw and swap. +TEST_P(EGLSurfaceTest, ResizeBeforeDraw) +{ + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 3; + constexpr std::array kWidths{64, 199, 500}; + constexpr std::array kHeights{64, 499, 200}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - glUniform4f(colorUniformLocation, color.x(), color.y(), color.z(), color.w()); - glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertexData.data()); - glDrawArrays(GL_TRIANGLES, 0, 6); - ASSERT_GL_NO_ERROR(); - } + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); - glEndQuery(GL_TIME_ELAPSED_EXT); - glDeleteQueries(1, &query); - ASSERT_GL_NO_ERROR(); - } + for (size_t i = 1; i < kSizeCount; ++i) + { + // Resize after create/swap (before draw). + mOSWindow->resize(kWidths[i], kHeights[i]); - if (useSecondContext) + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; + + // Some platforms may resize the surface before draw, while others may wait until swap. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + if (surfaceWidth == kWidths[i]) { - std::thread([this] { - eglBindAPI(EGL_OPENGL_ES_API); - ASSERT_EGL_SUCCESS(); - eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mSecondContext); - ASSERT_EGL_SUCCESS(); - glEnable(GL_SCISSOR_TEST); - glScissor(0, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT); - ASSERT_GL_NO_ERROR(); - eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - ASSERT_EGL_SUCCESS(); - }).join(); + EXPECT_EQ(surfaceHeight, kHeights[i]); } else { - eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext); - ASSERT_EGL_SUCCESS(); - eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - ASSERT_EGL_SUCCESS(); - eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); - ASSERT_EGL_SUCCESS(); + EXPECT_EQ(surfaceWidth, kWidths[i - 1]); + EXPECT_EQ(surfaceHeight, kHeights[i - 1]); } + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); + + // Start a new frame. eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); } - - mOSWindow->resize(kInitialSize, kInitialSize); -} - -// Test that there no artifacts because of the bug when wait semaphore could be added after -// rendering commands. This was possible by switching to Pbuffer surface and submit. -TEST_P(EGLSurfaceTest, DISABLED_WaitSemaphoreAddedAfterCommands) -{ - runWaitSemaphoreTest(false); -} - -// Test that there no artifacts because of the bug when rendering commands could be submitted -// without adding wait semaphore. This was possible if submit commands from other thread. -TEST_P(EGLSurfaceTest, DISABLED_CommandsSubmittedWithoutWaitSemaphore) -{ - runWaitSemaphoreTest(true); } -void EGLSurfaceTest::runDestroyNotCurrentSurfaceTest(bool testWindowsSurface) +// Tests window surface resize when window is resized before draw and swap, while delaying size +// query after the draw. +TEST_P(EGLSurfaceTest, ResizeBeforeDrawPostSizeQuery) { - initializeDisplay(); + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); - // Initialize an RGBA8 window and pbuffer surface - constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, - EGL_NONE}; + constexpr size_t kSizeCount = 3; + constexpr std::array kWidths{64, 199, 500}; + constexpr std::array kHeights{64, 499, 200}; - EGLint configCount = 0; - EGLConfig surfaceConfig = nullptr; - ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); - ASSERT_NE(configCount, 0); - ASSERT_NE(surfaceConfig, nullptr); + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); - initializeSurface(surfaceConfig); + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); initializeMainContext(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE); - - EGLSurface &testSurface = testWindowsSurface ? mWindowSurface : mPbufferSurface; - EGLSurface &otherSurface = testWindowsSurface ? mPbufferSurface : mWindowSurface; - - eglMakeCurrent(mDisplay, testSurface, testSurface, mContext); - ASSERT_EGL_SUCCESS(); - - // Start RenderPass in the testSurface - glEnable(GL_SCISSOR_TEST); - glScissor(0, 0, 4, 4); - glClearColor(0.5f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_SCISSOR_TEST); - ASSERT_GL_NO_ERROR(); - // Make other surface current keeping the context. - // If bug present, the context may have unflushed work, related to the testSurface. - eglMakeCurrent(mDisplay, otherSurface, otherSurface, mContext); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); - if (testWindowsSurface) + for (size_t i = 1; i < kSizeCount; ++i) { - // This may flush Window Surface RenderPass + // Resize after create/swap (before draw). + mOSWindow->resize(kWidths[i], kHeights[i]); + + // A warm-up draw in order to acquire the back buffer image before size query. glEnable(GL_SCISSOR_TEST); - glScissor(0, 0, 4, 4); - glClearColor(0.5f, 0.0f, 0.0f, 1.0f); + glScissor(1, 1, 1, 1); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_SCISSOR_TEST); - ASSERT_GL_NO_ERROR(); - } + EXPECT_GL_NO_ERROR(); - // Destroy the surface - eglDestroySurface(mDisplay, testSurface); - testSurface = EGL_NO_SURFACE; + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; - // This will submit all work (if bug present - include work related to the deleted testSurface). - eglMakeCurrent(mDisplay, otherSurface, otherSurface, mContext); - ASSERT_EGL_SUCCESS(); -} + // Some platforms may resize the surface, while others may wait until swap. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + if (surfaceWidth == kWidths[i]) + { + EXPECT_EQ(surfaceHeight, kHeights[i]); + } + else + { + EXPECT_EQ(surfaceWidth, kWidths[i - 1]); + EXPECT_EQ(surfaceHeight, kHeights[i - 1]); + } -// Test that there is no crash because of the bug when not current PBuffer Surface destroyed, while -// there are still unflushed work in the Context. -TEST_P(EGLSurfaceTest, DestroyNotCurrentPbufferSurface) -{ - runDestroyNotCurrentSurfaceTest(false); -} + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); -// Test that there is no crash because of the bug when not current Window Surface destroyed, while -// there are still unflushed work in the Context. -TEST_P(EGLSurfaceTest, DestroyNotCurrentWindowSurface) -{ - runDestroyNotCurrentSurfaceTest(true); + // Start a new frame. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + } } -// Test that there is no tearing because of incorrect pipeline barriers -TEST_P(EGLSurfaceTest, DISABLED_RandomClearTearing) +// Tests window surface resize when window is resized after draw but before swap. +TEST_P(EGLSurfaceTest, ResizeAfterDraw) { - // Note: This test requires visual inspection for rendering artifacts. - // However, absence of artifacts does not guarantee that there is no problem. - - initializeDisplay(); + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); - constexpr int kInitialSize = 64; - constexpr int kWindowWidth = 1080; - constexpr int kWindowWHeight = 1920; + constexpr size_t kSizeCount = 3; + constexpr std::array kWidths{64, 199, 500}; + constexpr std::array kHeights{64, 499, 200}; - mOSWindow->resize(kWindowWidth, kWindowWHeight); + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + initializeDisplay(); initializeSurfaceWithDefaultConfig(true); initializeMainContext(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); @@ -3045,175 +4065,346 @@ TEST_P(EGLSurfaceTest, DISABLED_RandomClearTearing) eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); - constexpr int kFrameCount = 60 * 4; // 4 sec @ 60Hz; 2 sec @ 120Hz; + // http://anglebug.com/397848903 + ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES()); - for (int frame = 0; frame < kFrameCount; ++frame) + for (size_t i = 1; i < kSizeCount; ++i) { - glClearColor(rand() % 256 / 255.0f, rand() % 256 / 255.0f, rand() % 256 / 255.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - ASSERT_GL_NO_ERROR(); + // Actual buffer size must match the window size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, kWidths[i - 1], kHeights[i - 1]), 0); + + // Resize after draw (before swap). + mOSWindow->resize(kWidths[i], kHeights[i]); + + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; + + // Some platforms may resize the surface after draw, while others may wait until swap. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + if (surfaceWidth == kWidths[i]) + { + EXPECT_EQ(surfaceHeight, kHeights[i]); + } + else + { + EXPECT_EQ(surfaceWidth, kWidths[i - 1]); + EXPECT_EQ(surfaceHeight, kHeights[i - 1]); + } + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); + + // Start a new frame. eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); } - - mOSWindow->resize(kInitialSize, kInitialSize); } -// Make sure a surface (from the same window) can be recreated after being destroyed, even if it's -// still current. -// This is to recreate the app behavior in https://issuetracker.google.com/292285899, which is -// not the correct spec behavior. It serves as a purpose to test the workaround feature -// uncurrent_egl_surface_upon_surface_destroy that is enabled only on vulkan backend to help -// the app get over the problem. -TEST_P(EGLSurfaceTest, DestroyAndRecreateWhileCurrent) +// Tests window surface resize using large window sizes. +TEST_P(EGLSurfaceTest, ResizeLargeWindow) { + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{1079, 999}; + constexpr std::array kHeights{999, 1079}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. setWindowVisible(mOSWindow, true); initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - mConfig = chooseDefaultConfig(true); - ASSERT_NE(mConfig, nullptr); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); - EGLint surfaceType = EGL_NONE; - eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType); - ASSERT_NE((surfaceType & EGL_WINDOW_BIT), 0); + for (size_t i = 0; i < kSizeCount; ++i) + { + // Resize before swap. + mOSWindow->resize(kWidths[i], kHeights[i]); - initializeWindowSurfaceWithAttribs(mConfig, {}, EGL_SUCCESS); + // Swap must resize the surface if it is not already resized. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + // A warm-up draw in order to acquire the back buffer image before size query. + glEnable(GL_SCISSOR_TEST); + glScissor(1, 1, 1, 1); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; + + // Surface must have window size after swap and draw. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + EXPECT_EQ(surfaceWidth, kWidths[i]); + EXPECT_EQ(surfaceHeight, kHeights[i]); + + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); + } +} + +// Tests that window surface resize when window is invisible does not cause failure. +TEST_P(EGLSurfaceTest, ResizeInvisibleWindow) +{ + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{199, 500}; + constexpr std::array kHeights{499, 200}; + + setWindowVisible(mOSWindow, false); + + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); - // Draw with this surface to make sure it's used. - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glViewport(0, 0, 64, 64); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); - ASSERT_GL_NO_ERROR(); + for (size_t i = 0; i < kSizeCount; ++i) + { + // Resize before swap. + mOSWindow->resize(kWidths[i], kHeights[i]); - // Destroy the surface while it's current; it won't actually be destroyed. - eglDestroySurface(mDisplay, mWindowSurface); - mWindowSurface = EGL_NO_SURFACE; + // Swap should resize the surface if it is not already resized. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); - // Create another surface from the same window right away. - initializeWindowSurfaceWithAttribs(mConfig, {}, EGL_SUCCESS); + // A warm-up draw in order to acquire the back buffer image before size query. + glEnable(GL_SCISSOR_TEST); + glScissor(1, 1, 1, 1); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); - // Make the new surface current; this leads to the actual destruction of the previous surface. - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); - ASSERT_EGL_SUCCESS(); + EGLint surfaceHeight = 0; + EGLint surfaceWidth = 0; - // Verify everything still works - ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); - drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - ASSERT_GL_NO_ERROR(); + // Query surface size but skip the check since size may not change when window is invisible. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); + } } -// Regression test for a bug where destroying more than 2 surfaces during termination -// overflowed the unlocked tail call storage. -TEST_P(EGLSurfaceTest, CreateMultiWindowsSurfaceNoDestroy) +// Tests that making context current after window surface resize sets correct viewport size. +TEST_P(EGLSurfaceTest, ResizeBeforeMakeCurrent) { + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{64, 199}; + constexpr std::array kHeights{64, 499}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - // Initialize and create multi RGBA8 window surfaces - constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, - EGL_NONE}; + // Resize before make current. + mOSWindow->resize(kWidths[1], kHeights[1]); - EGLint configCount = 0; - EGLConfig surfaceConfig = nullptr; - ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); - ASSERT_NE(configCount, 0); - ASSERT_NE(surfaceConfig, nullptr); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); - initializeSurface(surfaceConfig); + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; - // Create 3 window surfaces to trigger error - std::vector windowAttributes; - windowAttributes.push_back(EGL_NONE); + // Some platforms may resize the surface, while others may wait until swap. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); + ASSERT_EGL_SUCCESS(); + if (surfaceWidth == kWidths[1]) + { + EXPECT_EQ(surfaceHeight, kHeights[1]); + } + else + { + EXPECT_EQ(surfaceWidth, kWidths[0]); + EXPECT_EQ(surfaceHeight, kHeights[0]); + } - for (int i = 0; i < 3; i++) + // Viewport should match the reported surface size. + struct { - OSWindow *w = OSWindow::New(); - w->initialize("EGLSurfaceTest", 64, 64); + GLint x, y, width, height; + } vp; + glGetIntegerv(GL_VIEWPORT, &vp.x); + EXPECT_EQ(vp.x, 0); + EXPECT_EQ(vp.y, 0); + EXPECT_EQ(vp.width, surfaceWidth); + EXPECT_EQ(vp.height, surfaceHeight); + + // Draw after the size query. + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); - eglCreateWindowSurface(mDisplay, mConfig, w->getNativeWindow(), windowAttributes.data()); - ASSERT_EGL_SUCCESS(); - mOtherWindows.push_back(w); - } + // Draw should cover the entire viewport. + EXPECT_PIXEL_COLOR_EQ(vp.x, vp.y, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(vp.x + vp.width - 1, vp.y, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(vp.x, vp.y + vp.height - 1, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(vp.x + vp.width - 1, vp.y + vp.height - 1, GLColor::blue); + + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); } -// Test that querying EGL_RENDER_BUFFER of surface and context returns correct value. -// Context's render buffer should only change once eglSwapBuffers is called. -TEST_P(EGLSurfaceTest, QueryRenderBuffer) +// Tests that making context current after window surface resize sets correct viewport size, while +// delaying size query after the draw. +TEST_P(EGLSurfaceTest, ResizeBeforeMakeCurrentPostSizeQuery) { - ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer")); - ANGLE_SKIP_TEST_IF(!IsAndroid()); + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); - const EGLint configAttributes[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, - EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, - EGL_NONE}; + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{64, 199}; + constexpr std::array kHeights{64, 499}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); initializeDisplay(); - ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - // Create window surface and make current - mWindowSurface = - eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr); - ASSERT_EGL_SUCCESS(); - ASSERT_NE(EGL_NO_SURFACE, mWindowSurface); + // Resize before make current. + mOSWindow->resize(kWidths[1], kHeights[1]); - initializeMainContext(); - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); - // Set to single buffer mode and query the value - ASSERT_EGL_TRUE( - eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + // Draw before the size query to acquire the back buffer image. + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); - EGLint queryRenderBuffer; - ASSERT_EGL_TRUE( - eglQuerySurface(mDisplay, mWindowSurface, EGL_RENDER_BUFFER, &queryRenderBuffer)); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(queryRenderBuffer, EGL_SINGLE_BUFFER); + EGLint surfaceWidth = 0; + EGLint surfaceHeight = 0; - ASSERT_EGL_TRUE(eglQueryContext(mDisplay, mContext, EGL_RENDER_BUFFER, &queryRenderBuffer)); + // Some platforms may resize the surface, while others may wait until swap. + eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &surfaceWidth); + eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &surfaceHeight); ASSERT_EGL_SUCCESS(); - ASSERT_EQ(queryRenderBuffer, EGL_BACK_BUFFER); + if (surfaceWidth == kWidths[1]) + { + EXPECT_EQ(surfaceHeight, kHeights[1]); + } + else + { + EXPECT_EQ(surfaceWidth, kWidths[0]); + EXPECT_EQ(surfaceHeight, kHeights[0]); + } - // Swap buffers and then query the value - ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); - ASSERT_EGL_SUCCESS(); + // Viewport should match the reported surface size. + struct + { + GLint x, y, width, height; + } vp; + glGetIntegerv(GL_VIEWPORT, &vp.x); + EXPECT_EQ(vp.x, 0); + EXPECT_EQ(vp.y, 0); + EXPECT_EQ(vp.width, surfaceWidth); + EXPECT_EQ(vp.height, surfaceHeight); + + // Draw should cover the entire viewport. + EXPECT_PIXEL_COLOR_EQ(vp.x, vp.y, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(vp.x + vp.width - 1, vp.y, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(vp.x, vp.y + vp.height - 1, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(vp.x + vp.width - 1, vp.y + vp.height - 1, GLColor::blue); + + // Actual buffer size must match the reported size. + EXPECT_EQ(drawSizeCheckRect(mWindowSurface, surfaceWidth, surfaceHeight), 0); +} - ASSERT_EGL_TRUE( - eglQuerySurface(mDisplay, mWindowSurface, EGL_RENDER_BUFFER, &queryRenderBuffer)); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(queryRenderBuffer, EGL_SINGLE_BUFFER); +// Tests window surface resize is correctly tracked by glReadPixelsRobustANGLE. +TEST_P(EGLSurfaceTest, ResizeAndReadPixelsRobustANGLE) +{ + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); - ASSERT_EGL_TRUE(eglQueryContext(mDisplay, mContext, EGL_RENDER_BUFFER, &queryRenderBuffer)); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(queryRenderBuffer, EGL_SINGLE_BUFFER); + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{199, 500}; + constexpr std::array kHeights{499, 200}; - ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); - ASSERT_EGL_TRUE(eglDestroySurface(mDisplay, mWindowSurface)); - mWindowSurface = EGL_NO_SURFACE; - ASSERT_EGL_TRUE(eglDestroyContext(mDisplay, mContext)); - mContext = EGL_NO_CONTEXT; + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + + initializeDisplay(); + initializeSurfaceWithDefaultConfig(true); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); + + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); + + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")); + + // This is here just to acquire the back buffer. + glClear(GL_COLOR_BUFFER_BIT); + + for (size_t i = 0; i < kSizeCount; ++i) + { + // Resize before swap. + mOSWindow->resize(kWidths[i], kHeights[i]); + + // Swap must resize the surface if it is not already resized. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); + + std::vector rgbaData(kWidths[i] * kHeights[i] * 4); + + // We should be able to read the entire buffer using the new size. + GLsizei length = 0; + GLsizei width = 0; + GLsizei height = 0; + glReadPixelsRobustANGLE(0, 0, kWidths[i], kHeights[i], GL_RGBA, GL_UNSIGNED_BYTE, + static_cast(rgbaData.size()), &length, &width, &height, + rgbaData.data()); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(static_cast(rgbaData.size()), length); + EXPECT_EQ(kWidths[i], width); + EXPECT_EQ(kHeights[i], height); + } } -// Test that new API eglQuerySupportedCompressionRatesEXT could work, and -// validation for the API should also work. If any rate can be queried, then use -// that rate to create window surface. Query the surface's compression rate -// should get the expected rate, and a simple draw should succeed on the surface. -TEST_P(EGLSurfaceTest, SurfaceFixedRateCompression) +// Tests window surface resize is correctly tracked by glBlitFramebufferANGLE. +TEST_P(EGLSurfaceTest, ResizeAndBlitFramebufferANGLE) { + // http://anglebug.com/42263074 + ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); + + constexpr size_t kSizeCount = 2; + constexpr std::array kWidths{199, 500}; + constexpr std::array kHeights{499, 200}; + + // Necessary for some platforms (NVIDIA on Linux) if there is no per-frame window size query. + setWindowVisible(mOSWindow, true); + initializeDisplay(); - ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_surface_compression")); - // Initialize an RGBA8 window and pbuffer surface + + // Initialize an RGBA8 window surface with 4x MSAA constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, @@ -3222,152 +4413,62 @@ TEST_P(EGLSurfaceTest, SurfaceFixedRateCompression) 8, EGL_ALPHA_SIZE, 8, + EGL_SAMPLE_BUFFERS, + 1, + EGL_SAMPLES, + 4, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, - EGL_OPENGL_ES2_BIT, - EGL_NONE}; - EGLint configCount = 0; - EGLint numRates = 0; - EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &mConfig, 1, &configCount)); - ASSERT_NE(configCount, 0); - ASSERT_NE(mConfig, nullptr); - // Fail, invalid display - EXPECT_EGL_FALSE(eglQuerySupportedCompressionRatesEXT(EGL_NO_DISPLAY, mConfig, nullptr, nullptr, - 0, &numRates)); - ASSERT_EGL_ERROR(EGL_BAD_DISPLAY); - // Fail, rate_size < 0 - EXPECT_EGL_FALSE( - eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, nullptr, nullptr, -1, &numRates)); - ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); - // Fail, pointer rates is nullptr - EXPECT_EGL_FALSE( - eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, nullptr, nullptr, 1, &numRates)); - ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); - // Fail, return num_rates is nullptr - EXPECT_EGL_FALSE( - eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, nullptr, nullptr, 0, nullptr)); - ASSERT_EGL_ERROR(EGL_BAD_PARAMETER); - EGLint rates[3]; - // Success, actual values of rates are depended on each platform - EXPECT_EGL_TRUE( - eglQuerySupportedCompressionRatesEXT(mDisplay, mConfig, NULL, rates, 3, &numRates)); - ASSERT_EGL_SUCCESS(); - - if (numRates > 0 && rates[0] != EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT) - { - // If any rate can be queried, then use that rate to create window surface and test - std::vector winSurfaceAttribs; - winSurfaceAttribs.push_back(EGL_SURFACE_COMPRESSION_EXT); - winSurfaceAttribs.push_back(rates[0]); - // Create window surface using the selected rate. - initializeWindowSurfaceWithAttribs(mConfig, winSurfaceAttribs, EGL_SUCCESS); - ASSERT_EGL_SUCCESS(); - ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - EGLint selectedRate; - ASSERT_EGL_TRUE( - eglQuerySurface(mDisplay, mWindowSurface, EGL_SURFACE_COMPRESSION_EXT, &selectedRate)); - ASSERT_EGL_SUCCESS(); - ASSERT_EQ(selectedRate, rates[0]); - initializeMainContext(); - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); - ASSERT_EGL_SUCCESS(); - // Make sure the surface works. Draw red and verify. - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glUseProgram(program); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); - - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, nullptr, nullptr, mContext)); - EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, mWindowSurface)); - mWindowSurface = EGL_NO_SURFACE; - - // Create another surface using default rate. - winSurfaceAttribs.back() = EGL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT; - initializeWindowSurfaceWithAttribs(mConfig, winSurfaceAttribs, EGL_SUCCESS); - ASSERT_EGL_SUCCESS(); - ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - selectedRate = EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT; - ASSERT_EGL_TRUE( - eglQuerySurface(mDisplay, mWindowSurface, EGL_SURFACE_COMPRESSION_EXT, &selectedRate)); - ASSERT_EGL_SUCCESS(); - ASSERT_NE(selectedRate, EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT); - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); - ASSERT_EGL_SUCCESS(); - // Make sure the surface works. Draw red and verify. - drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); - } -} - -// Test the validation errors for eglSetDamageRegionKHR -TEST_P(EGLSurfaceTest, SetDamageRegionNegativeValidation) -{ - initializeDisplay(); - ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_partial_update")); - - constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE}; - EGLint age = 0; EGLint configCount = 0; EGLConfig surfaceConfig = nullptr; - - ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); - ASSERT_NE(configCount, 0); + ANGLE_SKIP_TEST_IF( + !eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount)); + ANGLE_SKIP_TEST_IF(configCount == 0); ASSERT_NE(surfaceConfig, nullptr); initializeSurface(surfaceConfig); - initializeAllContexts(); - EXPECT_EGL_SUCCESS(); - EXPECT_NE(mWindowSurface, EGL_NO_SURFACE); - EXPECT_NE(mPbufferSurface, EGL_NO_SURFACE); - - // Fail: surface is not a postable surface - EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mPbufferSurface, nullptr, 0)); - EXPECT_EGL_ERROR(EGL_BAD_MATCH); + initializeMainContext(); + ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); - // Fail: surface is not the current draw surface for the calling thread - EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); - EXPECT_EGL_ERROR(EGL_BAD_MATCH); + eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); + ASSERT_EGL_SUCCESS(); - EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mSecondContext)); - EXPECT_EGL_SUCCESS(); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit")); - // Fail: EGL_BUFFER_AGE_KHR attribute of surface has not been queried since the most recent - // frame boundary - EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); - EXPECT_EGL_ERROR(EGL_BAD_ACCESS); + // This is here just to acquire the back buffer. + glClear(GL_COLOR_BUFFER_BIT); - // Perform empty swap - EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface)); - EXPECT_EGL_SUCCESS(); + for (size_t i = 0; i < kSizeCount; ++i) + { + // Resize before swap. + mOSWindow->resize(kWidths[i], kHeights[i]); - EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_BUFFER_AGE_KHR, &age)); - EXPECT_EGL_SUCCESS(); - EXPECT_GE(age, 0); + // Swap must resize the surface if it is not already resized. + eglSwapBuffers(mDisplay, mWindowSurface); + ASSERT_EGL_SUCCESS(); - // Fail: n_rects should be a valid value - EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, -1)); - EXPECT_EGL_ERROR(EGL_BAD_PARAMETER); + // Create render target texture. + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidths[i], kHeights[i], 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); - // Success - EXPECT_EGL_TRUE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); - EXPECT_EGL_SUCCESS(); + // Create single sampled draw framebuffer. + GLFramebuffer fbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); - // Fail: damage region has already been set on surface since the most recent frame boundary - EXPECT_EGL_FALSE(eglSetDamageRegionKHR(mDisplay, mWindowSurface, nullptr, 0)); - EXPECT_EGL_ERROR(EGL_BAD_ACCESS); + // This should not generate following error: + // "Only whole-buffer blit is supported from a multisampled read buffer in this extension" + glBlitFramebufferANGLE(0, 0, kWidths[i], kHeights[i], 0, 0, kWidths[i], kHeights[i], + GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_NO_ERROR(); + } } - } // anonymous namespace GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSingleBufferTest); diff --git a/src/tests/egl_tests/EGLSurfaceTestMac.mm b/src/tests/egl_tests/EGLSurfaceTestMac.mm index dee0531c756..e1ac70b56cb 100644 --- a/src/tests/egl_tests/EGLSurfaceTestMac.mm +++ b/src/tests/egl_tests/EGLSurfaceTestMac.mm @@ -32,7 +32,7 @@ void testSetUp() override { // Get display. EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); diff --git a/src/tests/egl_tests/EGLSurfacelessContextTest.cpp b/src/tests/egl_tests/EGLSurfacelessContextTest.cpp index 5726bee118e..9626b11bb10 100644 --- a/src/tests/egl_tests/EGLSurfacelessContextTest.cpp +++ b/src/tests/egl_tests/EGLSurfacelessContextTest.cpp @@ -27,7 +27,7 @@ class EGLSurfacelessContextTest : public ANGLETest<> { EGLAttrib dispattrs[3] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); diff --git a/src/tests/egl_tests/EGLSyncControlTest.cpp b/src/tests/egl_tests/EGLSyncControlTest.cpp index 7203f87501c..f2b6b651d17 100644 --- a/src/tests/egl_tests/EGLSyncControlTest.cpp +++ b/src/tests/egl_tests/EGLSyncControlTest.cpp @@ -7,6 +7,10 @@ // EGLSyncControlTest.cpp: // Tests pertaining to eglGetSyncValuesCHROMIUM. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include "test_utils/ANGLETest.h" @@ -90,15 +94,15 @@ class EGLSyncControlTest : public testing::Test void InitializeDisplay() { - EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, - EGL_DONT_CARE, - EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, - EGL_DONT_CARE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, - EGL_NONE}; + EGLAttrib displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, + EGL_DONT_CARE, + EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, + EGL_DONT_CARE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, + EGL_NONE}; // Create an OS Window mOSWindow = OSWindow::New(); @@ -106,9 +110,9 @@ class EGLSyncControlTest : public testing::Test mOSWindow->setVisible(true); // Create an EGLDisplay using the EGLDevice - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - displayAttribs); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), + reinterpret_cast(mOSWindow->getNativeDisplay()), + displayAttribs); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); EGLint majorVersion, minorVersion; diff --git a/src/tests/egl_tests/EGLSyncTest.cpp b/src/tests/egl_tests/EGLSyncTest.cpp index 9aae69de0aa..8d9391f3ee5 100644 --- a/src/tests/egl_tests/EGLSyncTest.cpp +++ b/src/tests/egl_tests/EGLSyncTest.cpp @@ -6,6 +6,10 @@ // EGLSyncTest.cpp: // Tests of EGL_KHR_fence_sync and EGL_KHR_wait_sync extensions. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" @@ -358,13 +362,27 @@ TEST_P(EGLSyncTest, AndroidNativeFence_DupNativeFenceFD) EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR); int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD); - EXPECT_EGL_SUCCESS(); // Clean up created objects. if (fd != EGL_NO_NATIVE_FENCE_FD_ANDROID) { + EXPECT_EGL_SUCCESS(); close(fd); } + else + { + // For some driver, eglDupNativeFenceFDANDROID() may return -1 with EGL_BAD_PARAMETER, if + // the sync has been signalled. + EXPECT_EGL_ERROR(EGL_BAD_PARAMETER); + EGLint value; + EXPECT_EGL_TRUE( + eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value)); + EXPECT_EQ(value, EGL_SIGNALED_KHR); + + EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, + EGL_SYNC_NATIVE_FENCE_FD_ANDROID, &value)); + EXPECT_EQ(value, EGL_NO_NATIVE_FENCE_FD_ANDROID); + } EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD)); } @@ -707,7 +725,7 @@ void main(void) EGLSyncKHR sync1 = eglCreateSyncKHR(display, EGL_SYNC_GLOBAL_FENCE_ANGLE, nullptr); // Wait for the global fence sync to finish. - constexpr GLuint64 kTimeout = 1'000'000'000; // 1 second + constexpr GLuint64 kTimeout = 2'000'000'000; // 2 seconds ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR, eglClientWaitSyncKHR(display, sync1, 0, kTimeout)); // If the global fence sync is signaled, then the signal from context2 must also be signaled. @@ -925,4 +943,6 @@ void main(void) EXPECT_LT(numLongWaits, kMinLongWaitsToFail); } -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLSyncTest); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(EGLSyncTest, + ES2_VULKAN().enable(Feature::EnableExtraSubmitFence), + ES3_VULKAN().enable(Feature::EnableExtraSubmitFence)); diff --git a/src/tests/egl_tests/EGLSyncTestMetalCommandsScheduled.mm b/src/tests/egl_tests/EGLSyncTestMetalCommandsScheduled.mm new file mode 100644 index 00000000000..482855d482d --- /dev/null +++ b/src/tests/egl_tests/EGLSyncTestMetalCommandsScheduled.mm @@ -0,0 +1,142 @@ +// Copyright 2025 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. +// +// EGLSyncTestCommandsScheduled: +// Tests pertaining to EGL_ANGLE_metal_commands_scheduled_sync extension. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include + +#include "test_utils/ANGLETest.h" +#include "test_utils/gl_raii.h" +#include "util/EGLWindow.h" + +#include +#include + +using namespace angle; + +class EGLSyncTestMetalCommandsScheduled : public ANGLETest<> +{ + protected: + bool hasCommandsScheduledSyncExtension() const + { + return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), + "EGL_ANGLE_metal_commands_scheduled_sync"); + } + + void waitForCommandsScheduled(EGLDisplay display, EGLSync sync) + { + // Don't wait forever to make sure the test terminates + constexpr GLuint64 kTimeout = 1000'000'000ul; // 1 second + EXPECT_EQ(EGL_CONDITION_SATISFIED, + eglClientWaitSync(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT, kTimeout)); + + EGLAttrib value = 0; + EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_STATUS, &value)); + EXPECT_EQ(value, EGL_SIGNALED); + } + + void recordCommands() + { + // Create work to do + ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f); + } +}; + +// Test that a sync object is signaled after commands are scheduled. +TEST_P(EGLSyncTestMetalCommandsScheduled, SingleThread) +{ + ANGLE_SKIP_TEST_IF(!hasCommandsScheduledSyncExtension()); + + recordCommands(); + + EGLDisplay display = getEGLWindow()->getDisplay(); + EGLSync sync = eglCreateSync(display, EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, nullptr); + EXPECT_NE(sync, EGL_NO_SYNC); + + waitForCommandsScheduled(display, sync); + + EXPECT_EGL_TRUE(eglDestroySync(display, sync)); +} + +// Test that a sync object can be waited on from another thread. +TEST_P(EGLSyncTestMetalCommandsScheduled, MultiThread) +{ + ANGLE_SKIP_TEST_IF(!hasCommandsScheduledSyncExtension()); + + recordCommands(); + + EGLDisplay display = getEGLWindow()->getDisplay(); + EGLSync sync = eglCreateSync(display, EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, nullptr); + EXPECT_NE(sync, EGL_NO_SYNC); + + std::thread thread([&]() { waitForCommandsScheduled(display, sync); }); + thread.join(); + + EXPECT_EGL_TRUE(eglDestroySync(display, sync)); +} + +// Test that a sync object can be waited on after the work is done. +TEST_P(EGLSyncTestMetalCommandsScheduled, AfterFinish) +{ + ANGLE_SKIP_TEST_IF(!hasCommandsScheduledSyncExtension()); + + recordCommands(); + + EGLDisplay display = getEGLWindow()->getDisplay(); + EGLSync sync = eglCreateSync(display, EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, nullptr); + EXPECT_NE(sync, EGL_NO_SYNC); + + glFinish(); + + waitForCommandsScheduled(display, sync); + + EXPECT_EGL_TRUE(eglDestroySync(display, sync)); +} + +// Test that a sync object is signaled even if no work is done. +TEST_P(EGLSyncTestMetalCommandsScheduled, NoWork) +{ + ANGLE_SKIP_TEST_IF(!hasCommandsScheduledSyncExtension()); + + EGLDisplay display = getEGLWindow()->getDisplay(); + EGLSync sync = eglCreateSync(display, EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, nullptr); + EXPECT_NE(sync, EGL_NO_SYNC); + + waitForCommandsScheduled(display, sync); + + EXPECT_EGL_TRUE(eglDestroySync(display, sync)); +} + +// Test that there's no crash if a sync object is destroyed before its command buffer is scheduled. +TEST_P(EGLSyncTestMetalCommandsScheduled, DestroyBeforeScheduled) +{ + ANGLE_SKIP_TEST_IF(!hasCommandsScheduledSyncExtension()); + + recordCommands(); + + EGLDisplay display = getEGLWindow()->getDisplay(); + EGLSync sync1 = eglCreateSync(display, EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, nullptr); + EXPECT_NE(sync1, EGL_NO_SYNC); + + // Create and destroy another sync object immediately - it will add a callback to the commands + // scheduled handler, but the callback shouldn't crash even after the sync object is destroyed. + EGLSync sync2 = eglCreateSync(display, EGL_SYNC_METAL_COMMANDS_SCHEDULED_ANGLE, nullptr); + EXPECT_NE(sync2, EGL_NO_SYNC); + EXPECT_EGL_TRUE(eglDestroySync(display, sync2)); + + waitForCommandsScheduled(display, sync1); + + EXPECT_EGL_TRUE(eglDestroySync(display, sync1)); +} + +ANGLE_INSTANTIATE_TEST(EGLSyncTestMetalCommandsScheduled, ES2_METAL(), ES3_METAL()); +// This test suite is not instantiated on non-Metal backends and OSes. +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSyncTestMetalCommandsScheduled); diff --git a/src/tests/egl_tests/EGLSyncTestMetalSharedEvent.mm b/src/tests/egl_tests/EGLSyncTestMetalSharedEvent.mm index a55bdee7a41..3c7e4c21356 100644 --- a/src/tests/egl_tests/EGLSyncTestMetalSharedEvent.mm +++ b/src/tests/egl_tests/EGLSyncTestMetalSharedEvent.mm @@ -7,6 +7,10 @@ // Tests pertaining to EGL_ANGLE_sync_mtl_shared_event extension. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" diff --git a/src/tests/egl_tests/EGLWaylandTest.cpp b/src/tests/egl_tests/EGLWaylandTest.cpp index 369d1969680..01f9f862c36 100644 --- a/src/tests/egl_tests/EGLWaylandTest.cpp +++ b/src/tests/egl_tests/EGLWaylandTest.cpp @@ -26,9 +26,9 @@ const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; class EGLWaylandTest : public ANGLETest<> { public: - std::vector getDisplayAttributes() const + std::vector getDisplayAttributes() const { - std::vector attribs; + std::vector attribs; attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); attribs.push_back(GetParam().getRenderer()); @@ -44,9 +44,8 @@ class EGLWaylandTest : public ANGLETest<> setWindowVisible(mOsWindow, true); EGLNativeDisplayType waylandDisplay = mOsWindow->getNativeDisplay(); - std::vector attribs = getDisplayAttributes(); - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, (void *)waylandDisplay, - attribs.data()); + std::vector attribs = getDisplayAttributes(); + mDisplay = eglGetPlatformDisplay(GetEglPlatform(), (void *)waylandDisplay, attribs.data()); ASSERT_NE(EGL_NO_DISPLAY, mDisplay); ASSERT_TRUE(EGL_TRUE == eglInitialize(mDisplay, nullptr, nullptr)); diff --git a/src/tests/egl_tests/EGLX11VisualTest.cpp b/src/tests/egl_tests/EGLX11VisualTest.cpp index 82f07b30fbd..5ac836267d4 100644 --- a/src/tests/egl_tests/EGLX11VisualTest.cpp +++ b/src/tests/egl_tests/EGLX11VisualTest.cpp @@ -6,6 +6,10 @@ // EGLX11VisualTest.cpp: tests for EGL_ANGLE_x11_visual extension +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include @@ -31,9 +35,9 @@ class EGLX11VisualHintTest : public ANGLETest<> public: void testSetUp() override { mDisplay = XOpenDisplay(nullptr); } - std::vector getDisplayAttributes(int visualId) const + std::vector getDisplayAttributes(int visualId) const { - std::vector attribs; + std::vector attribs; attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); attribs.push_back(GetParam().getRenderer()); @@ -78,9 +82,8 @@ TEST_P(EGLX11VisualHintTest, InvalidVisualID) static const int gInvalidVisualId = -1; auto attributes = getDisplayAttributes(gInvalidVisualId); - EGLDisplay display = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<_XDisplay *>(EGL_DEFAULT_DISPLAY), - attributes.data()); + EGLDisplay display = eglGetPlatformDisplay( + GetEglPlatform(), reinterpret_cast<_XDisplay *>(EGL_DEFAULT_DISPLAY), attributes.data()); ASSERT_TRUE(display != EGL_NO_DISPLAY); ASSERT_TRUE(EGL_FALSE == eglInitialize(display, nullptr, nullptr)); @@ -104,9 +107,8 @@ TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear) int visualId = windowAttributes.visual->visualid; auto attributes = getDisplayAttributes(visualId); - EGLDisplay display = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<_XDisplay *>(EGL_DEFAULT_DISPLAY), - attributes.data()); + EGLDisplay display = eglGetPlatformDisplay( + GetEglPlatform(), reinterpret_cast<_XDisplay *>(EGL_DEFAULT_DISPLAY), attributes.data()); ASSERT_NE(EGL_NO_DISPLAY, display); ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr)); @@ -182,9 +184,8 @@ TEST_P(EGLX11VisualHintTest, InvalidWindowVisualID) } auto attributes = getDisplayAttributes(visualId); - EGLDisplay display = eglGetPlatformDisplayEXT( - EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<_XDisplay *>(EGL_DEFAULT_DISPLAY), - attributes.data()); + EGLDisplay display = eglGetPlatformDisplay( + GetEglPlatform(), reinterpret_cast<_XDisplay *>(EGL_DEFAULT_DISPLAY), attributes.data()); ASSERT_NE(EGL_NO_DISPLAY, display); ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr)); diff --git a/src/tests/gl_tests/AdvancedBlendTest.cpp b/src/tests/gl_tests/AdvancedBlendTest.cpp index 15c05bf6820..15a6c496b30 100644 --- a/src/tests/gl_tests/AdvancedBlendTest.cpp +++ b/src/tests/gl_tests/AdvancedBlendTest.cpp @@ -22,6 +22,7 @@ class AdvancedBlendTest : public ANGLETest<> setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); + setExtensionsEnabled(false); } void callBlendBarrier(APIExtensionVersion usedExtension); @@ -51,7 +52,7 @@ void AdvancedBlendTest::testAdvancedBlendNotAppliedWhenBlendIsDisabled( { ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR); - constexpr char kGLSLVersion31[] = R"(#version 310 es + constexpr char kGLSLVersion30[] = R"(#version 300 es )"; constexpr char kGLSLVersion32[] = R"(#version 320 es )"; @@ -63,8 +64,8 @@ void AdvancedBlendTest::testAdvancedBlendNotAppliedWhenBlendIsDisabled( if (usedExtension == APIExtensionVersion::KHR) { - vertSrc.append(kGLSLVersion31); - fragSrc.append(kGLSLVersion31); + vertSrc.append(kGLSLVersion30); + fragSrc.append(kGLSLVersion30); fragSrc.append(kBlendKHR); } else @@ -121,16 +122,18 @@ void AdvancedBlendTest::testAdvancedBlendNotAppliedWhenBlendIsDisabled( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Disable the blend. The next glDrawElements() should not blend the a_color with clear color + const int w = getWindowWidth(); + const int h = getWindowHeight(); glDisable(GL_BLEND); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); - EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 51, 128, 255), kPixelColorThreshhold); + EXPECT_PIXEL_COLOR_NEAR(w / 2, h / 2, GLColor(255, 51, 128, 255), kPixelColorThreshhold); } // Test that when blending is disabled, advanced blend is not applied. // Regression test for a bug in the emulation path in the Vulkan backend. TEST_P(AdvancedBlendTest, AdvancedBlendNotAppliedWhenBlendIsDisabledKHR) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced")); testAdvancedBlendNotAppliedWhenBlendIsDisabled(APIExtensionVersion::KHR); } @@ -144,7 +147,7 @@ void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVers { ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR); - constexpr char kGLSLVersion31[] = R"(#version 310 es + constexpr char kGLSLVersion30[] = R"(#version 300 es )"; constexpr char kGLSLVersion32[] = R"(#version 320 es )"; @@ -156,8 +159,8 @@ void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVers if (usedExtension == APIExtensionVersion::KHR) { - vertSrc.append(kGLSLVersion31); - fragSrc.append(kGLSLVersion31); + vertSrc.append(kGLSLVersion30); + fragSrc.append(kGLSLVersion30); fragSrc.append(kBlendKHR); } else @@ -180,7 +183,7 @@ void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVers constexpr char kFragSrcBody[] = R"( in mediump vec4 v_color; - layout(blend_support_colorburn) out; + layout(blend_support_colorburn, blend_support_multiply) out; layout(location = 0) out mediump vec4 o_color; void main() { @@ -217,12 +220,16 @@ void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVers glDisable(GL_BLEND); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); + const int w = getWindowWidth(); + const int h = getWindowHeight(); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, w / 2, h); // Enable the blend. The next glDrawElements() should blend a_color // with the the existing framebuffer output with GL_COLORBURN blend mode glEnable(GL_BLEND); // Test the blend with coherent blend disabled. This make the test cover both devices that // support / do not support GL_KHR_blend_equation_advanced_coherent - if (IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")) + if (EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")) { glDisable(GL_BLEND_ADVANCED_COHERENT_KHR); } @@ -233,7 +240,8 @@ void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVers glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData2.data()); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); - EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 0, 0, 255), kPixelColorThreshhold); + EXPECT_PIXEL_COLOR_NEAR(w / 4, h / 2, GLColor(255, 0, 0, 255), kPixelColorThreshhold); + EXPECT_PIXEL_COLOR_NEAR(3 * w / 4, h / 2, GLColor(255, 51, 128, 255), kPixelColorThreshhold); } // Test that when blending is disabled, advanced blend is not applied, but is applied after @@ -241,7 +249,7 @@ void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVers // Regression test for a bug in the emulation path in the Vulkan backend. TEST_P(AdvancedBlendTest, AdvancedBlendDisabledAndThenEnabledKHR) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced")); testAdvancedBlendDisabledAndThenEnabled(APIExtensionVersion::KHR); } @@ -256,7 +264,7 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers { ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR); - constexpr char kGLSLVersion31[] = R"(#version 310 es + constexpr char kGLSLVersion30[] = R"(#version 300 es )"; constexpr char kGLSLVersion32[] = R"(#version 320 es )"; @@ -268,8 +276,8 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers if (usedExtension == APIExtensionVersion::KHR) { - vertSrc.append(kGLSLVersion31); - fragSrc.append(kGLSLVersion31); + vertSrc.append(kGLSLVersion30); + fragSrc.append(kGLSLVersion30); fragSrc.append(kBlendKHR); } else @@ -292,7 +300,7 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers constexpr char kFragSrcBody[] = R"( in mediump vec4 v_color; - layout(blend_support_colorburn) out; + layout(blend_support_colorburn, blend_support_darken) out; layout(location = 0) out mediump vec4 o_color; void main() { @@ -319,18 +327,18 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers glEnableVertexAttribArray(attribColorLoc); glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data()); - glBlendEquation(GL_COLORBURN); + glBlendEquation(GL_DARKEN); const uint16_t indices[] = {0, 1, 2, 2, 1, 3}; glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Enable the blend. The next glDrawElements() should blend the a_color with clear color - // using the GL_COLORBURN blend mode + // using the GL_DARKEN blend mode glEnable(GL_BLEND); // Test the blend with coherent blend disabled. This make the test cover both devices that // support / do not support GL_KHR_blend_equation_advanced_coherent - if (IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")) + if (EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")) { glDisable(GL_BLEND_ADVANCED_COHERENT_KHR); } @@ -338,7 +346,11 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); // Disable the blend. The next glDrawElements() should not blend the a_color with - // the existing framebuffer output with GL_COLORBURN blend mode + // the existing framebuffer output with GL_DARKEN blend mode + const int w = getWindowWidth(); + const int h = getWindowHeight(); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, w / 2, h); glDisable(GL_BLEND); std::array attribColorData2 = {0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1}; @@ -346,7 +358,8 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData2.data()); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); - EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(128, 128, 0, 255), kPixelColorThreshhold); + EXPECT_PIXEL_COLOR_NEAR(w / 4, h / 2, GLColor(128, 128, 0, 255), kPixelColorThreshhold); + EXPECT_PIXEL_COLOR_NEAR(3 * w / 4, h / 2, GLColor(128, 51, 128, 255), kPixelColorThreshhold); } // Test that when blending is enabled, advanced blend is applied, but is not applied after @@ -354,10 +367,19 @@ void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVers // Regression test for a bug in the emulation path in the Vulkan backend. TEST_P(AdvancedBlendTest, AdvancedBlendEnabledAndThenDisabledKHR) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced")); testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion::KHR); } +// Test that extension blend barrier results in an error if the extension is not enabled. +TEST_P(AdvancedBlendTest, AdvancedBlendBarrierKHRFailsIfNotSupported) +{ + ASSERT_FALSE(IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); + + glBlendBarrierKHR(); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + // Test that when blending is enabled, advanced blend is applied, but is not applied after // it is disabled (using ES 3.2). TEST_P(AdvancedBlendTestES32, AdvancedBlendEnabledAndThenDisabled) @@ -365,10 +387,19 @@ TEST_P(AdvancedBlendTestES32, AdvancedBlendEnabledAndThenDisabled) testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion::Core); } +// Test that core blend barrier results in no error if the extension is not enabled. +TEST_P(AdvancedBlendTestES32, AdvancedBlendBarrierAlwaysPasses) +{ + ASSERT_FALSE(IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); + + glBlendBarrier(); + EXPECT_GL_NO_ERROR(); +} + // Test querying advanced blend equation coherent on supported devices (enabled by default). TEST_P(AdvancedBlendTest, AdvancedBlendCoherentQuery) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")); GLint status = -1; glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status); @@ -384,21 +415,28 @@ TEST_P(AdvancedBlendTest, AdvancedBlendCoherentQuery) glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status); EXPECT_GL_NO_ERROR(); EXPECT_EQ(status, 1); + + const GLboolean statusBool = glIsEnabled(GL_BLEND_ADVANCED_COHERENT_KHR); + EXPECT_GL_NO_ERROR(); + EXPECT_TRUE(statusBool); } // Test that querying advanced blend equation coherent results in an error as if this enum does not // exist. TEST_P(AdvancedBlendTest, AdvancedBlendCoherentQueryFailsIfNotSupported) { - ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")); + ASSERT_FALSE(IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")); GLint status = -1; glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status); EXPECT_GL_ERROR(GL_INVALID_ENUM); + + glEnable(GL_BLEND_ADVANCED_COHERENT_KHR); + EXPECT_GL_ERROR(GL_INVALID_ENUM); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AdvancedBlendTest); -ANGLE_INSTANTIATE_TEST_ES31(AdvancedBlendTest); +ANGLE_INSTANTIATE_TEST_ES3(AdvancedBlendTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AdvancedBlendTestES32); ANGLE_INSTANTIATE_TEST_ES32(AdvancedBlendTestES32); diff --git a/src/tests/gl_tests/AtomicCounterBufferTest.cpp b/src/tests/gl_tests/AtomicCounterBufferTest.cpp index 5daa65e1c40..b00e84867e9 100644 --- a/src/tests/gl_tests/AtomicCounterBufferTest.cpp +++ b/src/tests/gl_tests/AtomicCounterBufferTest.cpp @@ -7,6 +7,10 @@ // Various tests related for atomic counter buffers. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -917,6 +921,153 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterMemoryBarrier) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Tests queries for atomic counter +TEST_P(AtomicCounterBufferTest31, AtomicCounterQueries) +{ + constexpr uint32_t kAtomicCounterCount = 1 + 2 + 2 * 3; + + GLint maxAtomicCounters = 0; + glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters); + EXPECT_GL_NO_ERROR(); + + // Required minimum is 8 by the spec + EXPECT_GE(maxAtomicCounters, 8); + ANGLE_SKIP_TEST_IF(static_cast(maxAtomicCounters) < kAtomicCounterCount); + + constexpr char kComputeShaderSource[] = R"(#version 310 es +/* 1x1x1 workgroup */ +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +/* GL_MAX_COMPUTE_ATOMIC_COUNTERS is min 8 and GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE + * is min 32 bytes according to GLES 3.1 spec */ +layout (binding=0, offset=0) uniform atomic_uint ac; +layout (binding=0, offset=4) uniform atomic_uint acArray[2]; +layout (binding=0, offset=12) uniform atomic_uint acArrayArray[2][3]; + +void main() +{ + atomicCounterIncrement(ac); + atomicCounterDecrement(acArray[0]); + atomicCounterIncrement(acArray[1]); + atomicCounterIncrement(acArrayArray[0][0]); + atomicCounterDecrement(acArrayArray[0][1]); + atomicCounterIncrement(acArrayArray[0][2]); + atomicCounterDecrement(acArrayArray[1][0]); + atomicCounterIncrement(acArrayArray[1][1]); + atomicCounterIncrement(acArrayArray[1][2]); +} +)"; + + ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource); + EXPECT_GL_NO_ERROR(); + + glUseProgram(program); + EXPECT_GL_NO_ERROR(); + + GLsizei length = 0; + // Tests the resource property GL_BUFFER_DATA_SIZE query for ACB + GLenum ACBDataSizeProp = GL_BUFFER_DATA_SIZE; + GLint ACBDataSize; + glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, 0, 1, &ACBDataSizeProp, 1, &length, + &ACBDataSize); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(1, length); + // sizeof(GLuint) * 9 = 36 + // Vulkan rounds up to the required buffer alignment, so >= 36 + EXPECT_GE(ACBDataSize, 36); + + // Array containing the names of all active atomic counters in the shader */ + GLenum activeVariablesProperty = GL_ACTIVE_VARIABLES; + const char *activeACNames[] = {"ac", "acArray[0]", "acArrayArray[0][0]", "acArrayArray[1][0]"}; + const int numACs = sizeof(activeACNames) / sizeof(activeACNames[0]); + GLuint uniformsIndices[numACs]; + + // Getting the uniform indices for the later queries. + glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, 0, 1, &activeVariablesProperty, + numACs, &length, (GLint *)&uniformsIndices[0]); + EXPECT_EQ(length, numACs); + + // If is UNIFORM_OFFSET, then the returned value will be its offset + // relative to the beginning of its active atomic counter buffer. + GLint queryOffsets[numACs] = {0}; + glGetActiveUniformsiv(program, numACs, uniformsIndices, GL_UNIFORM_OFFSET, queryOffsets); + + GLint maxLength; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); + std::vector queryNames(maxLength); + for (uint32_t index = 0; index < numACs; index++) + { + GLint size; + GLenum type; + + glGetActiveUniform(program, uniformsIndices[index], maxLength, nullptr, &size, &type, + queryNames.data()); + + if (0 == std::strcmp(queryNames.data(), activeACNames[0])) + { + EXPECT_EQ(queryOffsets[index], 0); + } + else if (0 == std::strcmp(queryNames.data(), activeACNames[1])) + { + EXPECT_EQ(queryOffsets[index], 4); + } + else if (0 == std::strcmp(queryNames.data(), activeACNames[2])) + { + EXPECT_EQ(queryOffsets[index], 12); + } + else if (0 == std::strcmp(queryNames.data(), activeACNames[3])) + { + EXPECT_EQ(queryOffsets[index], 24); + } + else + { + ASSERT(false); + } + } + + // Create buffer with 9 GLuints = 36 bytes (0, 100, 200, ..., 800) + constexpr GLuint kInitialValues[kAtomicCounterCount] = {0, 100, 200, 300, 400, + 500, 600, 700, 800}; + + GLBuffer acBuffer; + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, acBuffer); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kInitialValues), kInitialValues, GL_DYNAMIC_DRAW); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, acBuffer); + EXPECT_GL_NO_ERROR(); + + // Dispatch single 1x1x1 work group + glDispatchCompute(1, 1, 1); + EXPECT_GL_NO_ERROR(); + + // Make sure compute shader has finished writing + glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT); + EXPECT_GL_NO_ERROR(); + + // Read back buffer data + GLuint results[kAtomicCounterCount] = {}; + void *ptr = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(results), GL_MAP_READ_BIT); + ASSERT_NE(ptr, nullptr); + memcpy(results, ptr, sizeof(results)); + glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); + + // Validate values: + // ac = 0 + 1 = 1 + // acArray[0] = 100 - 1 = 99 + // acArray[1] = 200 + 1 = 201 + // acArrayArray[0][0] = 300 + 1 = 301 + // acArrayArray[0][1] = 400 - 1 = 399 + // acArrayArray[0][2] = 500 + 1 = 501 + // acArrayArray[1][0] = 600 - 1 = 599 + // acArrayArray[1][1] = 700 + 1 = 701 + // acArrayArray[1][2] = 800 + 1 = 801 + const GLuint kExpectedResults[kAtomicCounterCount] = {1, 99, 201, 301, 399, 501, 599, 701, 801}; + for (uint32_t i = 0; i < kAtomicCounterCount; ++i) + { + EXPECT_EQ(results[i], kExpectedResults[i]) << "at index " << i; + } + EXPECT_GL_NO_ERROR(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtomicCounterBufferTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtomicCounterBufferTest31); ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(AtomicCounterBufferTest); diff --git a/src/tests/gl_tests/AttributeLayoutTest.cpp b/src/tests/gl_tests/AttributeLayoutTest.cpp index 57f0f14c358..2d64cd86944 100644 --- a/src/tests/gl_tests/AttributeLayoutTest.cpp +++ b/src/tests/gl_tests/AttributeLayoutTest.cpp @@ -8,6 +8,11 @@ // - in memory, in buffer object, or combination of both // - sequential or interleaved // - various combinations of data types +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include diff --git a/src/tests/gl_tests/BlendFuncExtendedTest.cpp b/src/tests/gl_tests/BlendFuncExtendedTest.cpp index 9784fdb4dba..8c9d8d306d7 100644 --- a/src/tests/gl_tests/BlendFuncExtendedTest.cpp +++ b/src/tests/gl_tests/BlendFuncExtendedTest.cpp @@ -3,8 +3,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// BlendFuncExtendedTest +// BlendFuncExtendedTest.cpp: // Test EXT_blend_func_extended +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -464,17 +469,16 @@ TEST_P(EXTBlendFuncExtendedDrawTest, FragColor) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); - const char *kFragColorShader = - "#extension GL_EXT_blend_func_extended : require\n" - "precision mediump float;\n" - "uniform vec4 src0;\n" - "uniform vec4 src1;\n" - "void main() {\n" - " gl_FragColor = src0;\n" - " gl_SecondaryFragColorEXT = src1;\n" - "}\n"; + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +precision mediump float; +uniform vec4 src0; +uniform vec4 src1; +void main() { + gl_FragColor = src0; + gl_SecondaryFragColorEXT = src1; +})"; - makeProgram(essl1_shaders::vs::Simple(), kFragColorShader); + makeProgram(essl1_shaders::vs::Simple(), kFS); drawTest(); } @@ -485,18 +489,17 @@ TEST_P(EXTBlendFuncExtendedDrawTest, FragColorBroadcast) ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers")); - const char *kFragColorShader = - "#extension GL_EXT_blend_func_extended : require\n" - "#extension GL_EXT_draw_buffers : require\n" - "precision mediump float;\n" - "uniform vec4 src0;\n" - "uniform vec4 src1;\n" - "void main() {\n" - " gl_FragColor = src0;\n" - " gl_SecondaryFragColorEXT = src1;\n" - "}\n"; + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +#extension GL_EXT_draw_buffers : require +precision mediump float; +uniform vec4 src0; +uniform vec4 src1; +void main() { + gl_FragColor = src0; + gl_SecondaryFragColorEXT = src1; +})"; - makeProgram(essl1_shaders::vs::Simple(), kFragColorShader); + makeProgram(essl1_shaders::vs::Simple(), kFS); drawTest(); } @@ -507,21 +510,66 @@ TEST_P(EXTBlendFuncExtendedDrawTest, FragData) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); - const char *kFragColorShader = - "#extension GL_EXT_blend_func_extended : require\n" - "precision mediump float;\n" - "uniform vec4 src0;\n" - "uniform vec4 src1;\n" - "void main() {\n" - " gl_FragData[0] = src0;\n" - " gl_SecondaryFragDataEXT[0] = src1;\n" - "}\n"; + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +precision mediump float; +uniform vec4 src0; +uniform vec4 src1; +void main() { + gl_FragData[0] = src0; + gl_SecondaryFragDataEXT[0] = src1; +})"; - makeProgram(essl1_shaders::vs::Simple(), kFragColorShader); + makeProgram(essl1_shaders::vs::Simple(), kFS); drawTest(); } +// Test that gl_MaxDualSourceDrawBuffersEXT is defined in ESSL 100 shaders. +TEST_P(EXTBlendFuncExtendedDrawTest, MaxDualSourceDrawBuffers) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +precision mediump float; +void main() { + gl_FragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10, 0, 0, 1); +})"; + + GLint maxDualSourceDrawBuffers; + glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers); + ASSERT_GE(maxDualSourceDrawBuffers, 1); + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR( + 0, 0, GLColor(static_cast(maxDualSourceDrawBuffers / 10.0), 0, 0, 255), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that gl_MaxDualSourceDrawBuffersEXT is defined in ESSL 300 shaders. +TEST_P(EXTBlendFuncExtendedDrawTestES3, MaxDualSourceDrawBuffers) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(location = 0) out mediump vec4 fragColor; +void main() { + fragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10, 0, 0, 1); +})"; + + GLint maxDualSourceDrawBuffers; + glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers); + ASSERT_GE(maxDualSourceDrawBuffers, 1); + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR( + 0, 0, GLColor(static_cast(maxDualSourceDrawBuffers / 10.0), 0, 0, 255), 1); + ASSERT_GL_NO_ERROR(); +} + // Test that min/max blending works correctly with SRC1 factors. TEST_P(EXTBlendFuncExtendedDrawTest, MinMax) { diff --git a/src/tests/gl_tests/BlendIntegerTest.cpp b/src/tests/gl_tests/BlendIntegerTest.cpp index c9a043f166d..0d7cfdaf86f 100644 --- a/src/tests/gl_tests/BlendIntegerTest.cpp +++ b/src/tests/gl_tests/BlendIntegerTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/BlendMinMaxTest.cpp b/src/tests/gl_tests/BlendMinMaxTest.cpp index 5b004f34c03..86f61e6d0d5 100644 --- a/src/tests/gl_tests/BlendMinMaxTest.cpp +++ b/src/tests/gl_tests/BlendMinMaxTest.cpp @@ -6,6 +6,10 @@ #include "test_utils/ANGLETest.h" +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + using namespace angle; class BlendMinMaxTest : public ANGLETest<> diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp index 604909a15b6..d68f75b623f 100644 --- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp +++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -497,8 +501,16 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithFlip) glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0, - getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0, + getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0, + getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -514,8 +526,17 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithFlip) glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(), - getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(), + getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(), + getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -532,8 +553,17 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithFlip) glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0, - getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0, + getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0, + getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -549,8 +579,17 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithFlip) glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(), - getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(), + getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(), + getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -592,8 +631,16 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipSrc) glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, - fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, + fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, + fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -633,10 +680,21 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipDst) glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, - fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth() / 2, 0, - getWindowWidth(), getWindowHeight() / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, + fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth() / 2, 0, + getWindowWidth(), getWindowHeight() / 2, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, + fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth() / 2, 0, + getWindowWidth(), getWindowHeight() / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 0); @@ -704,10 +762,20 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipSrcDst) glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, - fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), fb0Width / 2, 0, fb0Width, - fb0Height / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, + fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), fb0Width / 2, 0, fb0Width, + fb0Height / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth, + fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), fb0Width / 2, 0, fb0Width, + fb0Height / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -776,8 +844,16 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipInteger) glClearColor(0.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fb1_target_width, - fb1_target_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fb1_target_width, + fb1_target_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fb1_target_width, + fb1_target_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } EXPECT_GL_NO_ERROR(); @@ -807,8 +883,17 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipInteger) glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, fb1_target_width, fb1_target_height, 0, 0, getWindowWidth(), - getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + + if (getClientMajorVersion() < 3) + { + glBlitFramebufferNV(0, 0, fb1_target_width, fb1_target_height, 0, 0, getWindowWidth(), + getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + glBlitFramebuffer(0, 0, fb1_target_width, fb1_target_height, 0, 0, getWindowWidth(), + getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + } // And explicitly disable y-flip so that read does not implicitly use this flag. glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 0); @@ -1534,7 +1619,9 @@ class BlitFramebufferTest : public ANGLETest<> void BlitDepthStencilPixelByPixelTestHelper(bool mesaYFlip) { if (mesaYFlip) + { ASSERT_TRUE(IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y")); + } ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); @@ -1712,6 +1799,107 @@ class BlitFramebufferTest : public ANGLETest<> quadVertices.data()); glDrawArrays(GL_TRIANGLES, 0, 6); } + + void BlitSampleStencilToDefault(GLsizei samples) + { + GLsizei w = 3, h = 2; + GLint stencilValue = 1; + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + GLRenderbuffer colorbuf; + glBindRenderbuffer(GL_RENDERBUFFER, colorbuf); + if (samples != 0) + { + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, w, h); + } + else + { + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h); + } + + GLRenderbuffer depthstencilbuf; + glBindRenderbuffer(GL_RENDERBUFFER, depthstencilbuf); + if (samples != 0) + { + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, w, h); + } + else + { + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); + } + + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + depthstencilbuf); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + depthstencilbuf); + glCheckFramebufferStatus(GL_FRAMEBUFFER); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glFlush(); + + // Clear the stencil of each pixel to a different value. + glEnable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + glViewport(0, 0, w, h); + for (GLsizei y = 0; y < h; y++) + { + for (GLsizei x = 0; x < w; x++) + { + glScissor(x, y, 1, 1); + glClearStencil(stencilValue); + glClear(GL_STENCIL_BUFFER_BIT); + stencilValue += 1; + } + } + glDisable(GL_SCISSOR_TEST); + + // Blit stencil buffer to default framebuffer. + GLenum attachments1[] = {GL_COLOR_ATTACHMENT0}; + glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, + GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + // Disable stencil and draw full_screen green color. + ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green()); + glDisable(GL_STENCIL_TEST); + drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.5f); + + // Get the stencil through drawQuad. + // If the blit finished successfully, the stencil test should all pass. + ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + GLint colorUniformLocation = + glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorUniformLocation, -1); + glUseProgram(drawColor); + glEnable(GL_STENCIL_TEST); + for (GLsizei i = 1; i <= 6; i++) + { + glStencilFunc(GL_EQUAL, i, 255); + glUniform4f(colorUniformLocation, i * 1.0f / 255, 0.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f); + ASSERT_GL_NO_ERROR(); + } + + // Check the result. + std::vector pixels(w * h); + GLuint color_ref = 1; + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + for (GLsizei y = 0; y < h; y++) + { + for (GLsizei x = 0; x < w; x++) + { + const int curPos = y * w + x; + EXPECT_COLOR_NEAR(GLColor(color_ref, 0, 0, 255), pixels[curPos], 1); + color_ref += 1; + } + } + } }; class BlitFramebufferTestES31 : public BlitFramebufferTest @@ -1793,72 +1981,16 @@ TEST_P(BlitFramebufferTest, MultisampleDepth) ASSERT_GL_NO_ERROR(); } -// Blit multisample stencil buffer to default framebuffer without prerotaion. -TEST_P(BlitFramebufferTest, BlitMultisampleStencilToDefault) +// Blit stencil buffer to default framebuffer with prerotaion. +TEST_P(BlitFramebufferTest, BlitStencilToDefault) { - // http://anglebug.com/42262159 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - GLRenderbuffer colorbuf; - glBindRenderbuffer(GL_RENDERBUFFER, colorbuf); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 128, 128); - - GLRenderbuffer depthstencilbuf; - glBindRenderbuffer(GL_RENDERBUFFER, depthstencilbuf); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, 128, 128); - - GLFramebuffer framebuffer; - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - depthstencilbuf); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - depthstencilbuf); - glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glFlush(); - - // Replace stencil to 1. - ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); - glEnable(GL_STENCIL_TEST); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - glStencilFunc(GL_ALWAYS, 1, 255); - drawQuad(drawRed, essl3_shaders::PositionAttrib(), 0.8f); - - // Blit multisample stencil buffer to default frambuffer. - GLenum attachments1[] = {GL_COLOR_ATTACHMENT0}; - glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, 0, 128, 128, 0, 0, 128, 128, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, - GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - // Disable stencil and draw full_screen green color. - ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green()); - glDisable(GL_STENCIL_TEST); - drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.5f); - - // Draw blue color if the stencil is equal to 1. - // If the blit finished successfully, the stencil test should all pass. - ANGLE_GL_PROGRAM(drawBlue, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue()); - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_EQUAL, 1, 255); - drawQuad(drawBlue, essl3_shaders::PositionAttrib(), 0.2f); - - // Check the result, especially the boundaries. - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(127, 0, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(50, 0, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(127, 1, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(0, 127, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(127, 127, GLColor::blue); - EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::blue); + BlitSampleStencilToDefault(0); +} - ASSERT_GL_NO_ERROR(); +// Blit multisample stencil buffer to default framebuffer with prerotaion. +TEST_P(BlitFramebufferTest, BlitMultisampleStencilToDefault) +{ + BlitSampleStencilToDefault(4); } // Test blit multisampled framebuffer to MRT framebuffer @@ -3268,6 +3400,250 @@ TEST_P(BlitFramebufferTest, BlitFramebufferStencilClipNoIntersection) EXPECT_GL_NO_ERROR(); } +// Test that blit with FBOs with multiple color attachments of different size. +TEST_P(BlitFramebufferTest, BlitWithDifferentSizesColorAttachments) +{ + GLFramebuffer srcFramebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, srcFramebuffer); + constexpr GLint kWidth = 32; + constexpr GLint kHeight = 48; + GLColor texture_pattern[kWidth * kHeight]; + + // Prepare texture pattern + for (int y = 0; y < kHeight; y++) + { + for (int x = 0; x < kWidth; x++) + { + switch ((x + 2 * y) % 3) + { + case 0: + texture_pattern[y * kWidth + x] = GLColor::red; + break; + case 1: + texture_pattern[y * kWidth + x] = GLColor::green; + break; + case 2: + texture_pattern[y * kWidth + x] = GLColor::blue; + break; + default: + break; + } + } + } + + GLTexture largeColorBuffer; + glBindTexture(GL_TEXTURE_2D, largeColorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texture_pattern); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeColorBuffer, + 0); + EXPECT_GL_NO_ERROR(); + + GLTexture smallColorBuffer; + glBindTexture(GL_TEXTURE_2D, smallColorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth / 2, kHeight / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, smallColorBuffer, + 0); + EXPECT_GL_NO_ERROR(); + + GLFramebuffer dstFramebuffer; + GLRenderbuffer dstRenderbuffer; + glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, dstRenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + dstRenderbuffer); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, kWidth / 2 + 1, kHeight / 2 + 1, 0, 0, kWidth / 2 + 1, kHeight / 2 + 1, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer); + + for (int x = 0; x < kWidth / 2; x++) + { + for (int y = 0; y < kHeight / 2; y++) + { + switch ((x + 2 * y) % 3) + { + case 0: + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red) << x << " " << y; + break; + case 1: + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green) << x << " " << y; + break; + case 2: + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue) << x << " " << y; + break; + default: + break; + } + } + } + + EXPECT_GL_NO_ERROR(); +} + +// Test that blit with FBOs with large color attachment and small depth attachment. +TEST_P(BlitFramebufferTest, BlitLargeColorSmallDepthAttachments) +{ + constexpr GLint kWidth = 32; + constexpr GLint kHeight = 48; + GLFramebuffer srcFramebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, srcFramebuffer); + glDisable(GL_DEPTH_TEST); + + GLTexture srcLargeColorBuffer; + glBindTexture(GL_TEXTURE_2D, srcLargeColorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcLargeColorBuffer, + 0); + EXPECT_GL_NO_ERROR(); + + GLRenderbuffer srcSmallDepthBuffer; + glBindRenderbuffer(GL_RENDERBUFFER, srcSmallDepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth / 2, kHeight / 2); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + srcSmallDepthBuffer); + ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green()); + drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.5f); + + GLFramebuffer dstFramebuffer; + GLRenderbuffer dstColorBuffer; + glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, dstColorBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + dstColorBuffer); + GLRenderbuffer dstDepthBuffer; + glBindRenderbuffer(GL_RENDERBUFFER, dstDepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, dstDepthBuffer); + glClearDepthf(1.0f); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT0); + // The blit is larger than the size of srcFramebuffer, so the actual blit area is (kWidth / 2) * + // (kHeight / 2) + glBlitFramebuffer(0, 0, kWidth / 2 + 1, kHeight / 2 + 1, 0, 0, kWidth / 2 + 1, kHeight / 2 + 1, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer); + + for (int x = 0; x < kWidth / 2; x++) + { + for (int y = 0; y < kHeight / 2; y++) + { + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green) << x << " " << y; + } + } + + ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + glEnable(GL_DEPTH_TEST); + glDepthMask(false); + glDepthFunc(GL_LESS); + drawQuad(drawRed, essl3_shaders::PositionAttrib(), 0.7f); + + for (int x = 0; x < kWidth / 2; x++) + { + for (int y = 0; y < kHeight / 2; y++) + { + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green) << x << " " << y; + } + } + + EXPECT_GL_NO_ERROR(); +} + +// Test that blit with FBOs with small color attachment and large depth attachment. +TEST_P(BlitFramebufferTest, BlitSmallColorLargeDepthAttachments) +{ + constexpr GLint kWidth = 32; + constexpr GLint kHeight = 48; + GLFramebuffer srcFramebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, srcFramebuffer); + glDisable(GL_DEPTH_TEST); + + GLTexture srcSmallColorBuffer; + glBindTexture(GL_TEXTURE_2D, srcSmallColorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth / 2, kHeight / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcSmallColorBuffer, + 0); + EXPECT_GL_NO_ERROR(); + + GLRenderbuffer srcLargeDepthBuffer; + glBindRenderbuffer(GL_RENDERBUFFER, srcLargeDepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + srcLargeDepthBuffer); + ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green()); + drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.5f); + + GLFramebuffer dstFramebuffer; + GLRenderbuffer dstColorBuffer; + glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, dstColorBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + dstColorBuffer); + GLRenderbuffer dstDepthBuffer; + glBindRenderbuffer(GL_RENDERBUFFER, dstDepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, dstDepthBuffer); + glClearDepthf(1.0f); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT0); + // The blit is larger than the size of srcFramebuffer, so the actual blit area is (kWidth / 2) * + // (kHeight / 2) + glBlitFramebuffer(0, 0, kWidth / 2 + 1, kHeight / 2 + 1, 0, 0, kWidth / 2 + 1, kHeight / 2 + 1, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer); + for (int x = 0; x < kWidth / 2; x++) + { + for (int y = 0; y < kHeight / 2; y++) + { + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green) << x << " " << y; + } + } + + ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + glEnable(GL_DEPTH_TEST); + glDepthMask(false); + glDepthFunc(GL_LESS); + drawQuad(drawRed, essl3_shaders::PositionAttrib(), 0.7f); + + for (int x = 0; x < kWidth / 2; x++) + { + for (int y = 0; y < kHeight / 2; y++) + { + EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green) << x << " " << y; + } + } + + EXPECT_GL_NO_ERROR(); +} + // Covers an edge case with blitting borderline values. TEST_P(BlitFramebufferTest, OOBWrite) { @@ -4030,26 +4406,63 @@ TEST_P(BlitFramebufferTest, Blit2DArrayTo3D) test3DBlit(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D); } +// Test that glBlitFramebuffer works when the framebuffer attachment level is not zero. At the same +// time, the texture's base level is also non-zero. +TEST_P(BlitFramebufferTestES31, BlitNonZeroLevelSource) +{ + GLFramebuffer readFbo, drawFbo; + GLTexture readColor, drawColor; + + glBindTexture(GL_TEXTURE_2D, readColor); + glTexStorage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 128, 64); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + + glBindFramebuffer(GL_FRAMEBUFFER, readFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readColor, 3); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + glBindTexture(GL_TEXTURE_2D, drawColor); + glTexStorage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 64, 128); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawColor, 5); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + + // Blit 1-to-1 + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); + + // Blit with stretch + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glBlitFramebuffer(0, 0, 1, 2, 0, 0, 3, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_RECT_EQ(0, 0, 2, 3, GLColor::blue); + ASSERT_GL_NO_ERROR(); +} + // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlitFramebufferANGLETest); -ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest, - ES2_D3D9(), - ES2_D3D11(), - ES2_D3D11_PRESENT_PATH_FAST(), - ES2_OPENGL(), - ES3_OPENGL(), - ES2_VULKAN(), - ES3_VULKAN(), - ES3_VULKAN().enable(Feature::EmulatedPrerotation90), - ES3_VULKAN().enable(Feature::EmulatedPrerotation180), - ES3_VULKAN().enable(Feature::EmulatedPrerotation270), - ES3_VULKAN() - .disable(Feature::SupportsExtendedDynamicState) - .disable(Feature::SupportsExtendedDynamicState2), - ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2), - ES2_METAL(), - ES2_METAL().disable(Feature::HasShaderStencilOutput)); +ANGLE_INSTANTIATE_TEST_ES2_AND(BlitFramebufferANGLETest, + ES2_D3D11_PRESENT_PATH_FAST(), + ES3_OPENGL(), + ES3_VULKAN(), + ES3_VULKAN().enable(Feature::EmulatedPrerotation90), + ES3_VULKAN().enable(Feature::EmulatedPrerotation180), + ES3_VULKAN().enable(Feature::EmulatedPrerotation270), + ES3_VULKAN() + .disable(Feature::SupportsExtendedDynamicState) + .disable(Feature::SupportsExtendedDynamicState2), + ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2), + ES2_METAL().disable(Feature::HasShaderStencilOutput)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlitFramebufferTest); ANGLE_INSTANTIATE_TEST_ES3_AND(BlitFramebufferTest, @@ -4060,7 +4473,6 @@ ANGLE_INSTANTIATE_TEST_ES3_AND(BlitFramebufferTest, .disable(Feature::SupportsExtendedDynamicState) .disable(Feature::SupportsExtendedDynamicState2), ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2), - ES3_VULKAN().enable(Feature::DisableFlippingBlitWithCommand), ES3_METAL().disable(Feature::HasShaderStencilOutput)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlitFramebufferTestES31); diff --git a/src/tests/gl_tests/BlobCacheTest.cpp b/src/tests/gl_tests/BlobCacheTest.cpp index a6e7ccd5ca9..ea255b4f4c9 100644 --- a/src/tests/gl_tests/BlobCacheTest.cpp +++ b/src/tests/gl_tests/BlobCacheTest.cpp @@ -6,6 +6,10 @@ // BlobCacheTest: // Unit tests for the GL_ANGLE_blob_cache extension. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + // Must be included first to prevent errors with "None". #include "test_utils/ANGLETest.h" diff --git a/src/tests/gl_tests/BufferDataTest.cpp b/src/tests/gl_tests/BufferDataTest.cpp index 08dee98c3b6..f9960a42077 100644 --- a/src/tests/gl_tests/BufferDataTest.cpp +++ b/src/tests/gl_tests/BufferDataTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -1312,7 +1316,7 @@ precision mediump float; uniform block { uvec4 data; } ubo; -uniform uint expect; +uniform highp uint expect; uniform vec4 successOutput; out vec4 colorOut; void main() @@ -1962,6 +1966,40 @@ TEST_P(BufferStorageTestES3, VertexBufferMapped) EXPECT_GL_NO_ERROR(); } +// Verify that glReadPixels works with a persistently mapped buffer. +TEST_P(BufferStorageTestES3, ReadPixelsPersistentBuffer) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage")); + + GLBuffer buffer; + glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer); + glBufferStorageEXT(GL_PIXEL_PACK_BUFFER, 4, nullptr, + GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT); + ASSERT_GL_NO_ERROR(); + + void *mapPtr = + glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 4, + GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT); + ASSERT_NE(nullptr, mapPtr); + ASSERT_GL_NO_ERROR(); + + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0); + ASSERT_GL_NO_ERROR(); + + glFinish(); + + GLColor actual; + memcpy(&actual, mapPtr, sizeof(actual)); + + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + ASSERT_GL_NO_ERROR(); + + EXPECT_EQ(GLColor::green, actual); +} + void TestPageSharingBuffers(std::function swapCallback, size_t bufferSize, const std::array &quadVertices, @@ -2334,6 +2372,47 @@ void main() ASSERT_GL_NO_ERROR(); } +// Test that checks buffer object state after calling glBufferStorageEXT +TEST_P(BufferStorageTestES3, BufferStorageGetParameter) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage")); + + GLint64 value = -1; + GLint size = 3; + + GLBuffer buffer; + glBindBuffer(GL_COPY_READ_BUFFER, buffer); + glBufferStorageEXT(GL_COPY_READ_BUFFER, size, NULL, GL_MAP_WRITE_BIT); + ASSERT_GL_NO_ERROR(); + + /* Check the value of GL_BUFFER_SIZE. */ + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_SIZE, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(size, static_cast(value)); + + /* Check the value of GL_BUFFER_USAGE. */ + value = -1; + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_USAGE, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(GL_DYNAMIC_DRAW, value); + + /* Check the value of GL_BUFFER_IMMUTABLE_STORAGE_EXT. */ + value = -1; + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE_EXT, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(GL_TRUE, value); + + /* Check the value of GL_BUFFER_STORAGE_FLAGS_EXT. */ + value = -1; + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_STORAGE_FLAGS_EXT, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(GL_MAP_WRITE_BIT, value); + + /* Clean up. */ + glUnmapBuffer(GL_COPY_READ_BUFFER); + glBindBuffer(GL_COPY_READ_BUFFER, 0); +} + ANGLE_INSTANTIATE_TEST_ES2(BufferDataTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferSubDataTest); diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp index 97bc7ae5bde..2f7ef29546b 100644 --- a/src/tests/gl_tests/ClearTest.cpp +++ b/src/tests/gl_tests/ClearTest.cpp @@ -4,10 +4,15 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" +#include "common/gl_enum_utils.h" #include "test_utils/gl_raii.h" #include "util/random_utils.h" #include "util/shader_utils.h" @@ -118,8 +123,27 @@ class ClearTestES3 : public ClearTestBase glDepthMask(GL_FALSE); } glDepthFunc(GL_LESS); - drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), depthValue * 2 - 1 - 0.01f); - drawQuad(depthTestProgramFail, essl1_shaders::PositionAttrib(), depthValue * 2 - 1 + 0.01f); + + GLfloat normalizedDepth = depthValue * 2 - 1; + + // A depth value clamped to 0.0 will be normalized to -1.0. In this case, clear the color + // buffer to blue and then attempt to draw red only. Otherwise, attempt to draw blue and + // red. + if (normalizedDepth < -0.999999f) + { + glClearColor(0.0, 0.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + GLfloat redNormalizedDepth = normalizedDepth + 0.01f; + drawQuad(depthTestProgramFail, essl1_shaders::PositionAttrib(), redNormalizedDepth); + } + else + { + GLfloat blueNormalizedDepth = normalizedDepth - 0.01f; + GLfloat redNormalizedDepth = normalizedDepth + 0.01f; + drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), blueNormalizedDepth); + drawQuad(depthTestProgramFail, essl1_shaders::PositionAttrib(), redNormalizedDepth); + } + if (!hasDepthTest) { glDisable(GL_DEPTH_TEST); @@ -213,7 +237,31 @@ class ClearTextureEXTTest : public ANGLETest<> } }; -class ClearTextureEXTTestES31 : public ANGLETest<> +struct ClearTextureParams +{ + FormatTableElement format; + GLenum textureType; +}; + +using ClearTextureVariationsTestParams = std::tuple; + +std::string ClearTextureVariationsTestPrint( + const ::testing::TestParamInfo ¶msInfo) +{ + const ClearTextureVariationsTestParams ¶ms = paramsInfo.param; + std::ostringstream out; + + ClearTextureParams clearParams = std::get<1>(params); + out << std::get<0>(params) << "__" + << gl::GLenumToString(gl::GLESEnum::AllEnums, clearParams.format.internalformat) << "_" + << gl::GLenumToString(gl::GLESEnum::AllEnums, clearParams.format.format) << "_" + << gl::GLenumToString(gl::GLESEnum::AllEnums, clearParams.format.type) << "_" + << gl::GLenumToString(gl::GLESEnum::AllEnums, clearParams.textureType); + + return out.str(); +} + +class ClearTextureEXTTestES31 : public ANGLETest { protected: ClearTextureEXTTestES31() @@ -233,20 +281,7 @@ class ClearTextureEXTTestES31 : public ANGLETest<> mLevels = std::log2(std::max(mWidth, mHeight)) + 1; } - // Texture's information. - int mWidth; - int mHeight; - int mDepth; - int mLevels; - - GLenum mTarget; - - bool mIsArray = true; - bool mHasLayer = true; - bool mExtraSupport = true; - - GLColor mFullColorRef = GLColor::red; - GLColor mPartialColorRef = GLColor::blue; + void setTestParams(); // Convert the reference color so that it can be suitable for different type of format. ColorTypes convertColorTypeInternal(const GLenum &type, const GLColor &color); @@ -292,8 +327,54 @@ class ClearTextureEXTTestES31 : public ANGLETest<> ColorTypes &fullColor, GLColor &partialColorRef, ColorTypes &partialColor); + + // Texture's information. + int mWidth; + int mHeight; + int mDepth; + int mLevels; + + GLenum mTarget; + + bool mIsArray = true; + bool mHasLayer = true; + bool mExtraSupport = true; + + GLColor mFullColorRef = GLColor::red; + GLColor mPartialColorRef = GLColor::blue; }; +void ClearTextureEXTTestES31::setTestParams() +{ + mTarget = std::get<1>(GetParam()).textureType; + + switch (mTarget) + { + case GL_TEXTURE_2D: + mDepth = 1; + mIsArray = mHasLayer = false; + break; + case GL_TEXTURE_2D_ARRAY: + break; + case GL_TEXTURE_3D: + mIsArray = false; + break; + case GL_TEXTURE_CUBE_MAP: + mHeight = mWidth; + mDepth = 6; + mLevels = std::log2(mWidth) + 1; + break; + case GL_TEXTURE_CUBE_MAP_ARRAY: + mHeight = mWidth; + mDepth = 2 * 6; + mLevels = std::log2(mWidth) + 1; + mExtraSupport = IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"); + break; + default: + ASSERT(false); + } +} + ColorTypes ClearTextureEXTTestES31::convertColorTypeInternal(const GLenum &type, const GLColor &color) { @@ -995,267 +1076,239 @@ void ClearTextureEXTTestES31::clearCheckUnrenderable(int level, } } +constexpr std::array kClearTextureRenderableFormats = {{ + {{GL_R8, GL_RED, GL_UNSIGNED_BYTE}, GL_TEXTURE_2D}, + {{GL_R16F, GL_RED, GL_HALF_FLOAT}, GL_TEXTURE_2D_ARRAY}, + {{GL_R16F, GL_RED, GL_FLOAT}, GL_TEXTURE_3D}, + {{GL_R32F, GL_RED, GL_FLOAT}, GL_TEXTURE_CUBE_MAP}, + {{GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RG16F, GL_RG, GL_HALF_FLOAT}, GL_TEXTURE_2D}, + {{GL_RG16F, GL_RG, GL_FLOAT}, GL_TEXTURE_2D_ARRAY}, + {{GL_RG32F, GL_RG, GL_FLOAT}, GL_TEXTURE_3D}, + {{GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE}, GL_TEXTURE_2D}, + {{GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, GL_TEXTURE_2D_ARRAY}, + {{GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT}, GL_TEXTURE_3D}, + {{GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT}, GL_TEXTURE_CUBE_MAP}, + {{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE}, GL_TEXTURE_2D}, + {{GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, GL_TEXTURE_3D}, + {{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, GL_TEXTURE_2D}, + {{GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, GL_TEXTURE_3D}, + {{GL_RGBA16F, GL_RGBA, GL_FLOAT}, GL_TEXTURE_CUBE_MAP}, + {{GL_RGBA32F, GL_RGBA, GL_FLOAT}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT}, GL_TEXTURE_2D}, + {{GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT}, GL_TEXTURE_3D}, + {{GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_R8I, GL_RED_INTEGER, GL_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, GL_TEXTURE_2D}, + {{GL_R16I, GL_RED_INTEGER, GL_SHORT}, GL_TEXTURE_2D_ARRAY}, + {{GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, GL_TEXTURE_3D}, + {{GL_R32I, GL_RED_INTEGER, GL_INT}, GL_TEXTURE_CUBE_MAP}, + {{GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RG8I, GL_RG_INTEGER, GL_BYTE}, GL_TEXTURE_2D}, + {{GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, GL_TEXTURE_2D_ARRAY}, + {{GL_RG16I, GL_RG_INTEGER, GL_SHORT}, GL_TEXTURE_3D}, + {{GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, GL_TEXTURE_CUBE_MAP}, + {{GL_RG32I, GL_RG_INTEGER, GL_INT}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, GL_TEXTURE_2D}, + {{GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, GL_TEXTURE_3D}, + {{GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, GL_TEXTURE_CUBE_MAP}, + {{GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, GL_TEXTURE_2D}, +}}; + class ClearTextureEXTTestES31Renderable : public ClearTextureEXTTestES31 { protected: - std::vector mFormats = { - {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, - {GL_R16F, GL_RED, GL_HALF_FLOAT}, - {GL_R16F, GL_RED, GL_FLOAT}, - {GL_R32F, GL_RED, GL_FLOAT}, - {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, - {GL_RG16F, GL_RG, GL_HALF_FLOAT}, - {GL_RG16F, GL_RG, GL_FLOAT}, - {GL_RG32F, GL_RG, GL_FLOAT}, - {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE}, - {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, - {GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE}, - {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, - {GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT}, - {GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT}, - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE}, - {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE}, - {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, - {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, - {GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE}, - {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, - {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, - {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, - {GL_RGBA16F, GL_RGBA, GL_FLOAT}, - {GL_RGBA32F, GL_RGBA, GL_FLOAT}, - {GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT}, - {GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT}, - {GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT}, - {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, - {GL_R8I, GL_RED_INTEGER, GL_BYTE}, - {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, - {GL_R16I, GL_RED_INTEGER, GL_SHORT}, - {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, - {GL_R32I, GL_RED_INTEGER, GL_INT}, - {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, - {GL_RG8I, GL_RG_INTEGER, GL_BYTE}, - {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, - {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, - {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, - {GL_RG32I, GL_RG_INTEGER, GL_INT}, - {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, - {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, - {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, - {GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, - {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, - {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, - }; - void testRenderable() { + FormatTableElement fmt = std::get<1>(GetParam()).format; + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || !IsGLExtensionEnabled("GL_EXT_clear_texture") || !mExtraSupport); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16") && + requiredNorm16(fmt.internalformat)); - const auto test = [&](FormatTableElement &fmt) { - // Update MAX level numbers. - if (mTarget == GL_TEXTURE_3D) - { - mLevels = std::max(mLevels, static_cast(std::log2(mDepth)) + 1); - } - - GLTexture tex; - initTexture(mLevels, fmt, tex); + // Update MAX level numbers. + if (mTarget == GL_TEXTURE_3D) + { + mLevels = std::max(mLevels, static_cast(std::log2(mDepth)) + 1); + } - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + GLTexture tex; + initTexture(mLevels, fmt, tex); - // Calculate specific clear color value. - GLColor fullColorRef = getClearColor(fmt.format, mFullColorRef); - ColorTypes fullColor = convertColorType(fmt.format, fmt.type, fullColorRef); - GLColor partialColorRef = getClearColor(fmt.format, mPartialColorRef); - ColorTypes partialColor = convertColorType(fmt.format, fmt.type, partialColorRef); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); - for (int level = 0; level < mLevels; ++level) - { - int width = std::max(mWidth >> level, 1); - int height = std::max(mHeight >> level, 1); - int depth = mIsArray ? mDepth : std::max(mDepth >> level, 1); + // Calculate specific clear color value. + GLColor fullColorRef = getClearColor(fmt.format, mFullColorRef); + ColorTypes fullColor = convertColorType(fmt.format, fmt.type, fullColorRef); + GLColor partialColorRef = getClearColor(fmt.format, mPartialColorRef); + ColorTypes partialColor = convertColorType(fmt.format, fmt.type, partialColorRef); - clearCheckRenderable(level, width, height, depth, tex, fmt, fullColorRef, fullColor, - partialColorRef, partialColor); - } - }; - - bool supportNorm16 = IsGLExtensionEnabled("GL_EXT_texture_norm16"); - for (auto fmt : mFormats) + for (int level = 0; level < mLevels; ++level) { - if (!supportNorm16 && requiredNorm16(fmt.internalformat)) - { - continue; - } - test(fmt); + int width = std::max(mWidth >> level, 1); + int height = std::max(mHeight >> level, 1); + int depth = mIsArray ? mDepth : std::max(mDepth >> level, 1); + + clearCheckRenderable(level, width, height, depth, tex, fmt, fullColorRef, fullColor, + partialColorRef, partialColor); } } void testMS() { + FormatTableElement fmt = std::get<1>(GetParam()).format; + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || !IsGLExtensionEnabled("GL_EXT_clear_texture") || !mExtraSupport); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16") && + requiredNorm16(fmt.internalformat)); - const auto test = [&](FormatTableElement &fmt) { - // Initialize the texture. - GLTexture tex; - glBindTexture(mTarget, tex); - int sampleNum = 0; - glGetInternalformativ(mTarget, fmt.internalformat, GL_SAMPLES, 1, &sampleNum); - sampleNum = std::min(sampleNum, 4); - if (mIsArray) - { - glTexStorage3DMultisampleOES(mTarget, sampleNum, fmt.internalformat, mWidth, - mHeight, mDepth, GL_TRUE); - } - else - { - glTexStorage2DMultisample(mTarget, sampleNum, fmt.internalformat, mWidth, mHeight, - GL_TRUE); - } - EXPECT_GL_ERROR(GL_NO_ERROR); - ANGLE_GL_PROGRAM(initProgram, essl31_shaders::vs::Simple(), - essl31_shaders::fs::Green()); - glUseProgram(initProgram); - drawQuad(initProgram, essl31_shaders::PositionAttrib(), 0.5f); - - // Calculate specific clear color value. - GLColor fullColorRef = getClearColor(fmt.format, mFullColorRef); - ColorTypes fullColor = convertColorType(fmt.format, fmt.type, fullColorRef); - GLColor partialColorRef = getClearColor(fmt.format, mPartialColorRef); - ColorTypes partialColor = convertColorType(fmt.format, fmt.type, partialColorRef); - - ANGLE_GL_PROGRAM(program, getVertexShader(mTarget).c_str(), - getFragmentShader(mTarget, fmt.isInt(), fmt.isUInt()).c_str()); - glUseProgram(program); - - std::vector uniformLocs = {0, 0, 0}; - - uniformLocs[0] = glGetUniformLocation(program, "s"); - ASSERT_NE(-1, uniformLocs[0]); - uniformLocs[2] = glGetUniformLocation(program, "texsize"); - ASSERT_NE(-1, uniformLocs[2]); - glUniform2f(uniformLocs[2], static_cast(mWidth), static_cast(mHeight)); - if (mIsArray) - { - uniformLocs[1] = glGetUniformLocation(program, "slice"); - ASSERT_NE(-1, uniformLocs[1]); - } - - clearCheckUnrenderable(0, mWidth, mHeight, mDepth, tex, fmt, program, uniformLocs, - fullColorRef, fullColor, partialColorRef, partialColor); - }; - - bool supportNorm16 = IsGLExtensionEnabled("GL_EXT_texture_norm16"); - for (auto fmt : mFormats) + // Initialize the texture. + GLTexture tex; + glBindTexture(mTarget, tex); + int sampleNum = 0; + glGetInternalformativ(mTarget, fmt.internalformat, GL_SAMPLES, 1, &sampleNum); + sampleNum = std::min(sampleNum, 4); + if (mIsArray) { - if (!supportNorm16 && requiredNorm16(fmt.internalformat)) - { - continue; - } - test(fmt); + glTexStorage3DMultisampleOES(mTarget, sampleNum, fmt.internalformat, mWidth, mHeight, + mDepth, GL_TRUE); + } + else + { + glTexStorage2DMultisample(mTarget, sampleNum, fmt.internalformat, mWidth, mHeight, + GL_TRUE); + } + EXPECT_GL_ERROR(GL_NO_ERROR); + ANGLE_GL_PROGRAM(initProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green()); + glUseProgram(initProgram); + drawQuad(initProgram, essl31_shaders::PositionAttrib(), 0.5f); + + // Calculate specific clear color value. + GLColor fullColorRef = getClearColor(fmt.format, mFullColorRef); + ColorTypes fullColor = convertColorType(fmt.format, fmt.type, fullColorRef); + GLColor partialColorRef = getClearColor(fmt.format, mPartialColorRef); + ColorTypes partialColor = convertColorType(fmt.format, fmt.type, partialColorRef); + + ANGLE_GL_PROGRAM(program, getVertexShader(mTarget).c_str(), + getFragmentShader(mTarget, fmt.isInt(), fmt.isUInt()).c_str()); + glUseProgram(program); + + std::vector uniformLocs = {0, 0, 0}; + + uniformLocs[0] = glGetUniformLocation(program, "s"); + ASSERT_NE(-1, uniformLocs[0]); + uniformLocs[2] = glGetUniformLocation(program, "texsize"); + ASSERT_NE(-1, uniformLocs[2]); + glUniform2f(uniformLocs[2], static_cast(mWidth), static_cast(mHeight)); + if (mIsArray) + { + uniformLocs[1] = glGetUniformLocation(program, "slice"); + ASSERT_NE(-1, uniformLocs[1]); } + + clearCheckUnrenderable(0, mWidth, mHeight, mDepth, tex, fmt, program, uniformLocs, + fullColorRef, fullColor, partialColorRef, partialColor); } }; +constexpr std::array kClearTextureUnrenderableFormats = {{ + {{GL_RGB16F, GL_RGB, GL_HALF_FLOAT}, GL_TEXTURE_2D}, + {{GL_RGB16F, GL_RGB, GL_FLOAT}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE}, GL_TEXTURE_3D}, + {{GL_RGB8I, GL_RGB_INTEGER, GL_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RGB16I, GL_RGB_INTEGER, GL_SHORT}, GL_TEXTURE_2D}, + {{GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGB32I, GL_RGB_INTEGER, GL_INT}, GL_TEXTURE_3D}, + {{GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_R8_SNORM, GL_RED, GL_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_RG8_SNORM, GL_RG, GL_BYTE}, GL_TEXTURE_2D}, + {{GL_RGB8_SNORM, GL_RGB, GL_BYTE}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGB32F, GL_RGB, GL_FLOAT}, GL_TEXTURE_3D}, + {{GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_R16_SNORM_EXT, GL_RED, GL_SHORT}, GL_TEXTURE_2D}, + {{GL_RG16_SNORM_EXT, GL_RG, GL_SHORT}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT}, GL_TEXTURE_3D}, + {{GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP}, + {{GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE}, GL_TEXTURE_CUBE_MAP_ARRAY}, + {{GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE}, GL_TEXTURE_2D}, + {{GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, GL_TEXTURE_2D_ARRAY}, + {{GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT}, GL_TEXTURE_3D}, + {{GL_RGB9_E5, GL_RGB, GL_FLOAT}, GL_TEXTURE_CUBE_MAP}, +}}; + class ClearTextureEXTTestES31Unrenderable : public ClearTextureEXTTestES31 { protected: - std::vector mFormats = { - {GL_RGB16F, GL_RGB, GL_HALF_FLOAT}, - {GL_RGB16F, GL_RGB, GL_FLOAT}, - {GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE}, - {GL_RGB8I, GL_RGB_INTEGER, GL_BYTE}, - {GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT}, - {GL_RGB16I, GL_RGB_INTEGER, GL_SHORT}, - {GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT}, - {GL_RGB32I, GL_RGB_INTEGER, GL_INT}, - {GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE}, - {GL_R8_SNORM, GL_RED, GL_BYTE}, - {GL_RG8_SNORM, GL_RG, GL_BYTE}, - {GL_RGB8_SNORM, GL_RGB, GL_BYTE}, - {GL_RGB32F, GL_RGB, GL_FLOAT}, - {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, - {GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT}, - {GL_R16_SNORM_EXT, GL_RED, GL_SHORT}, - {GL_RG16_SNORM_EXT, GL_RG, GL_SHORT}, - {GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT}, - {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE}, - {GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE}, - {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE}, - }; - - std::vector mFormatsRGB9E5 = { - {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, - {GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT}, - {GL_RGB9_E5, GL_RGB, GL_FLOAT}, - }; - - void testUnrenderable(std::vector &formats) + void testUnrenderable() { + FormatTableElement fmt = std::get<1>(GetParam()).format; + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || !IsGLExtensionEnabled("GL_EXT_clear_texture") || !mExtraSupport); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16") && + requiredNorm16(fmt.internalformat)); - const auto test = [&](FormatTableElement &fmt) { - // Update MAX level numbers. - if (mTarget == GL_TEXTURE_3D) - { - mLevels = std::max(mLevels, static_cast(std::log2(mDepth)) + 1); - } + // Update MAX level numbers. + if (mTarget == GL_TEXTURE_3D) + { + mLevels = std::max(mLevels, static_cast(std::log2(mDepth)) + 1); + } - GLTexture tex; - initTexture(mLevels, fmt, tex); + GLTexture tex; + initTexture(mLevels, fmt, tex); - // Calculate specific clear color value. - GLColor fullColorRef = getClearColor(fmt.format, mFullColorRef); - ColorTypes fullColor = convertColorType(fmt.format, fmt.type, fullColorRef); - GLColor partialColorRef = getClearColor(fmt.format, mPartialColorRef); - ColorTypes partialColor = convertColorType(fmt.format, fmt.type, partialColorRef); + // Calculate specific clear color value. + GLColor fullColorRef = getClearColor(fmt.format, mFullColorRef); + ColorTypes fullColor = convertColorType(fmt.format, fmt.type, fullColorRef); + GLColor partialColorRef = getClearColor(fmt.format, mPartialColorRef); + ColorTypes partialColor = convertColorType(fmt.format, fmt.type, partialColorRef); - ANGLE_GL_PROGRAM(program, getVertexShader(mTarget).c_str(), - getFragmentShader(mTarget, fmt.isInt(), fmt.isUInt()).c_str()); - glUseProgram(program); + ANGLE_GL_PROGRAM(program, getVertexShader(mTarget).c_str(), + getFragmentShader(mTarget, fmt.isInt(), fmt.isUInt()).c_str()); + glUseProgram(program); - std::vector uniformLocs = {0, 0}; - if (mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_3D) - { - uniformLocs[0] = glGetUniformLocation(program, "slice"); - ASSERT_NE(-1, uniformLocs[0]); - } - else if (mTarget == GL_TEXTURE_CUBE_MAP) - { - uniformLocs[0] = glGetUniformLocation(program, "cubeFace"); - } - else if (mTarget == GL_TEXTURE_CUBE_MAP_ARRAY) - { - uniformLocs[0] = glGetUniformLocation(program, "cubeFace"); - ASSERT_NE(-1, uniformLocs[0]); - uniformLocs[1] = glGetUniformLocation(program, "layer"); - ASSERT_NE(-1, uniformLocs[1]); - } - - // For each level, clear the texture. - for (int level = 0; level < mLevels; ++level) - { - int width = std::max(mWidth >> level, 1); - int height = std::max(mHeight >> level, 1); - int depth = mIsArray ? mDepth : std::max(mDepth >> level, 1); - - clearCheckUnrenderable(level, width, height, depth, tex, fmt, program, uniformLocs, - fullColorRef, fullColor, partialColorRef, partialColor); - } - }; + std::vector uniformLocs = {0, 0}; + if (mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_3D) + { + uniformLocs[0] = glGetUniformLocation(program, "slice"); + ASSERT_NE(-1, uniformLocs[0]); + } + else if (mTarget == GL_TEXTURE_CUBE_MAP) + { + uniformLocs[0] = glGetUniformLocation(program, "cubeFace"); + } + else if (mTarget == GL_TEXTURE_CUBE_MAP_ARRAY) + { + uniformLocs[0] = glGetUniformLocation(program, "cubeFace"); + ASSERT_NE(-1, uniformLocs[0]); + uniformLocs[1] = glGetUniformLocation(program, "layer"); + ASSERT_NE(-1, uniformLocs[1]); + } - bool supportNorm16 = IsGLExtensionEnabled("GL_EXT_texture_norm16"); - for (auto fmt : formats) + // For each level, clear the texture. + for (int level = 0; level < mLevels; ++level) { - if (!supportNorm16 && requiredNorm16(fmt.internalformat)) - { - continue; - } - test(fmt); + int width = std::max(mWidth >> level, 1); + int height = std::max(mHeight >> level, 1); + int depth = mIsArray ? mDepth : std::max(mDepth >> level, 1); + + clearCheckUnrenderable(level, width, height, depth, tex, fmt, program, uniformLocs, + fullColorRef, fullColor, partialColorRef, partialColor); } } }; @@ -1566,6 +1619,26 @@ TEST_P(ClearTest, RGBA8Framebuffer) EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0); } +// Test clearing a BGRA8 Framebuffer +TEST_P(ClearTest, BGRA8Framebuffer) +{ + ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::BgraTexImageFormatsBroken)); + + glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]); + + GLTexture texture; + + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, getWindowWidth(), getWindowHeight(), 0, GL_BGRA_EXT, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + EXPECT_PIXEL_NEAR(0, 0, 0, 255, 0, 255, 1.0); +} + // Test uploading a texture and then clearing a RGBA8 Framebuffer TEST_P(ClearTest, TextureUploadAndRGBA8Framebuffer) { @@ -4196,6 +4269,60 @@ TEST_P(ClearTestES3, RepeatedDepthClear) ASSERT_GL_NO_ERROR(); } +// Tests that calls to glClearBufferfi clamp the depth value. +TEST_P(ClearTestES3, ClampDepthClearBufferfi) +{ + glClearBufferfi(GL_DEPTH_STENCIL, 0, -0.01f, 0x55); + verifyDepth(0.00f, 1); + + glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.00f, 0x55); + verifyDepth(0.00f, 1); + + glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.01f, 0x55); + verifyDepth(0.01f, 1); + + glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.99f, 0x55); + verifyDepth(0.99f, 1); + + glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.00f, 0x55); + verifyDepth(1.00f, 1); + + glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.01f, 0x55); + verifyDepth(1.0f, 1); + + ASSERT_GL_NO_ERROR(); +} + +// Tests that calls to glClearBufferfv clamp the depth value. +TEST_P(ClearTestES3, ClampDepthClearBufferfv) +{ + float depthClearValue = -0.01f; + glClearBufferfv(GL_DEPTH, 0, &depthClearValue); + verifyDepth(0.00f, 1); + + depthClearValue = 0.00f; + glClearBufferfv(GL_DEPTH, 0, &depthClearValue); + verifyDepth(0.00f, 1); + + depthClearValue = 0.01f; + glClearBufferfv(GL_DEPTH, 0, &depthClearValue); + verifyDepth(0.01f, 1); + + depthClearValue = 0.99f; + glClearBufferfv(GL_DEPTH, 0, &depthClearValue); + verifyDepth(0.99f, 1); + + depthClearValue = 1.00f; + glClearBufferfv(GL_DEPTH, 0, &depthClearValue); + verifyDepth(1.00f, 1); + + depthClearValue = 1.01f; + glClearBufferfv(GL_DEPTH, 0, &depthClearValue); + verifyDepth(1.0f, 1); + + ASSERT_GL_NO_ERROR(); +} + // Test that reclearing stencil to the same value works. TEST_P(ClearTestES3, RepeatedStencilClear) { @@ -6321,155 +6448,48 @@ TEST_P(ClearTextureEXTTest, ClearTextureAfterMaskedClearBug) } } -// Test clearing renderable format textures with GL_EXT_clear_texture for TEXTURE_2D. -TEST_P(ClearTextureEXTTestES31Renderable, Clear2D) +// Test clearing renderable format textures with GL_EXT_clear_texture. +TEST_P(ClearTextureEXTTestES31Renderable, Clear) { - mDepth = 1; - mTarget = GL_TEXTURE_2D; - mIsArray = mHasLayer = false; + setTestParams(); testRenderable(); } -// Test clearing unrenderable format textures with GL_EXT_clear_texture for TEXTURE_2D. -TEST_P(ClearTextureEXTTestES31Unrenderable, Clear2D) +// Test clearing unrenderable format textures with GL_EXT_clear_texture. +TEST_P(ClearTextureEXTTestES31Unrenderable, Clear) { - mDepth = 1; - mTarget = GL_TEXTURE_2D; - mIsArray = mHasLayer = false; - testUnrenderable(mFormats); -} - -// Test clearing renderable format textures with GL_EXT_clear_texture for TEXTURE_2D_ARRAY. -TEST_P(ClearTextureEXTTestES31Renderable, Clear2DArray) -{ - mTarget = GL_TEXTURE_2D_ARRAY; - testRenderable(); -} - -// Test clearing unrenderable format textures with GL_EXT_clear_texture for TEXTURE_2D_ARRAY. -TEST_P(ClearTextureEXTTestES31Unrenderable, Clear2DArray) -{ - mTarget = GL_TEXTURE_2D_ARRAY; - testUnrenderable(mFormats); -} - -// Test clearing renderable format textures with GL_EXT_clear_texture for TEXTURE_3D. -TEST_P(ClearTextureEXTTestES31Renderable, Clear3D) -{ - mTarget = GL_TEXTURE_3D; - mIsArray = false; - testRenderable(); -} - -// Test clearing unrenderable format textures with GL_EXT_clear_texture for TEXTURE_3D. -TEST_P(ClearTextureEXTTestES31Unrenderable, Clear3D) -{ - mTarget = GL_TEXTURE_3D; - mIsArray = false; - testUnrenderable(mFormats); -} - -// Test clearing renderable format textures with GL_EXT_clear_texture for TEXTURE_CUBE_MAP. -TEST_P(ClearTextureEXTTestES31Renderable, ClearCubeMap) -{ - mHeight = mWidth; - mDepth = 6; - mLevels = std::log2(mWidth) + 1; - mTarget = GL_TEXTURE_CUBE_MAP; - testRenderable(); -} - -// Test clearing unrenderable format textures with GL_EXT_clear_texture for TEXTURE_CUBE_MAP. -TEST_P(ClearTextureEXTTestES31Unrenderable, ClearCubeMap) -{ - mHeight = mWidth; - mDepth = 6; - mLevels = std::log2(mWidth) + 1; - mTarget = GL_TEXTURE_CUBE_MAP; - testUnrenderable(mFormats); -} - -// Test clearing renderable format textures with GL_EXT_clear_texture for -// TEXTURE_CUBE_MAP_ARRAY. -TEST_P(ClearTextureEXTTestES31Renderable, ClearCubeMapArray) -{ - mHeight = mWidth; - mDepth = 2 * 6; - mLevels = std::log2(mWidth) + 1; - mTarget = GL_TEXTURE_CUBE_MAP_ARRAY; - mExtraSupport = IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"); - testRenderable(); -} - -// Test clearing unrenderable format textures with GL_EXT_clear_texture for -// TEXTURE_CUBE_MAP_ARRAY. -TEST_P(ClearTextureEXTTestES31Unrenderable, ClearCubeMapArray) -{ - mHeight = mWidth; - mDepth = 2 * 6; - mLevels = std::log2(mWidth) + 1; - mTarget = GL_TEXTURE_CUBE_MAP_ARRAY; - mExtraSupport = IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"); - testUnrenderable(mFormats); -} - -// Test clearing GL_RGB9_E5 format. -TEST_P(ClearTextureEXTTestES31Unrenderable, ClearRGB9E5) -{ - // Test for TEXTURE_2D_ARRAY. - mTarget = GL_TEXTURE_2D_ARRAY; - testUnrenderable(mFormatsRGB9E5); - - // Test for TEXTURE_3D. - mTarget = GL_TEXTURE_3D; - mIsArray = false; - testUnrenderable(mFormatsRGB9E5); - - // Test for TEXTURE_2D. - mDepth = 1; - mLevels = std::log2(std::max(mWidth, mHeight)) + 1; - mTarget = GL_TEXTURE_2D; - mIsArray = mHasLayer = false; - testUnrenderable(mFormatsRGB9E5); - - // Test for TEXTURE_CUBE_MAP. - mHeight = mWidth; - mDepth = 6; - mLevels = std::log2(mWidth) + 1; - mTarget = GL_TEXTURE_CUBE_MAP; - mIsArray = mHasLayer = true; - testUnrenderable(mFormatsRGB9E5); - - // Test for TEXTURE_CUBE_MAP_ARRAY. - mDepth = 2 * 6; - mTarget = GL_TEXTURE_CUBE_MAP_ARRAY; - mExtraSupport = IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"); - testUnrenderable(mFormatsRGB9E5); + setTestParams(); + testUnrenderable(); } // Test clearing unrenderable format textures with GL_EXT_clear_texture for TEXTURE_2D_MULTISAMPLE. TEST_P(ClearTextureEXTTestES31Renderable, ClearMultisample) { - mDepth = 1; - mTarget = GL_TEXTURE_2D_MULTISAMPLE; - mIsArray = mHasLayer = false; - testMS(); -} - -// Test clearing unrenderable format textures with GL_EXT_clear_texture for -// TEXTURE_2D_MULTISAMPLE_ARRAY. -TEST_P(ClearTextureEXTTestES31Renderable, ClearMultisampleArray) -{ - mTarget = GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES; - mExtraSupport = EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"); + // Divide up the tests between TEXTURE_2D_MULTISAMPLE and TEXTURE_2D_MULTISAMPLE_ARRAY. + switch (std::get<1>(GetParam()).textureType) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + mDepth = 1; + mTarget = GL_TEXTURE_2D_MULTISAMPLE; + mIsArray = mHasLayer = false; + break; + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: + mTarget = GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES; + mExtraSupport = EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"); + break; + default: + ASSERT(false); + } testMS(); } ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( ClearTest, ES3_VULKAN().enable(Feature::ForceFallbackFormat), - ES3_VULKAN().enable(Feature::PreferDrawClearOverVkCmdClearAttachments), - ES2_WEBGPU()); + ES3_VULKAN().enable(Feature::PreferDrawClearOverVkCmdClearAttachments)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClearTestES3); ANGLE_INSTANTIATE_TEST_ES3_AND( @@ -6522,7 +6542,18 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClearTestRGB_ES3); ANGLE_INSTANTIATE_TEST(ClearTestRGB_ES3, ES3_D3D11(), ES3_VULKAN(), ES3_METAL()); ANGLE_INSTANTIATE_TEST_ES3(ClearTextureEXTTest); -ANGLE_INSTANTIATE_TEST_ES31(ClearTextureEXTTestES31Renderable); -ANGLE_INSTANTIATE_TEST_ES31(ClearTextureEXTTestES31Unrenderable); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClearTextureEXTTestES31Renderable); +ANGLE_INSTANTIATE_TEST_COMBINE_1(ClearTextureEXTTestES31Renderable, + ClearTextureVariationsTestPrint, + testing::ValuesIn(kClearTextureRenderableFormats), + ANGLE_ALL_TEST_PLATFORMS_ES31, + ES31_VULKAN_SWIFTSHADER().enable(Feature::PreferBGR565ToRGB565)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClearTextureEXTTestES31Unrenderable); +ANGLE_INSTANTIATE_TEST_COMBINE_1(ClearTextureEXTTestES31Unrenderable, + ClearTextureVariationsTestPrint, + testing::ValuesIn(kClearTextureUnrenderableFormats), + ANGLE_ALL_TEST_PLATFORMS_ES31); } // anonymous namespace diff --git a/src/tests/gl_tests/ClipDistanceTest.cpp b/src/tests/gl_tests/ClipDistanceTest.cpp index 071adbc6e71..b335c989f0a 100644 --- a/src/tests/gl_tests/ClipDistanceTest.cpp +++ b/src/tests/gl_tests/ClipDistanceTest.cpp @@ -1371,6 +1371,26 @@ void main() EXPECT_FALSE(prg.valid()); } +// Test that bad index to gl_ClipDistance does not cause a translator crash +TEST_P(ClipCullDistanceTest, BadIndexNoCrash) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled(kExtensionName)); + + std::string kVS = R"(#version 300 es +#extension )" + kExtensionName + + R"( : require + +void main() +{ + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + gl_ClipDistance[float(0)] = gl_Position.w; +})"; + + GLProgram prg; + prg.makeRaster(kVS.c_str(), essl1_shaders::fs::Red()); + EXPECT_FALSE(prg.valid()); +} + // Test that length() does not compile for unsized arrays TEST_P(ClipCullDistanceTest, UnsizedArrayLength) { diff --git a/src/tests/gl_tests/CompressedTextureFormatsTest.cpp b/src/tests/gl_tests/CompressedTextureFormatsTest.cpp index d6d9ada8dd5..dc0fb4d849b 100644 --- a/src/tests/gl_tests/CompressedTextureFormatsTest.cpp +++ b/src/tests/gl_tests/CompressedTextureFormatsTest.cpp @@ -22,6 +22,7 @@ struct FormatDesc GLenum format; GLsizei blockX; GLsizei blockY; + GLsizei blockZ; GLsizei size; bool isPVRTC1() const @@ -191,12 +192,12 @@ class CompressedTextureFormatsTest : public ANGLETest= 3) { - testSamplerSliced3D(GL_TEXTURE_2D_ARRAY); - testSamplerSliced3D(GL_TEXTURE_3D); + testSampler3D(GL_TEXTURE_2D_ARRAY); + testSampler3D(GL_TEXTURE_3D); + } + } + + void test3D() + { + for (const std::string &extName : mExtNames) + { + if (!extName.empty()) + { + if (IsGLExtensionRequestable(extName)) + { + glRequestExtensionANGLE(extName.c_str()); + } + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extName)); + } } + + check3D(GL_TEXTURE_2D_ARRAY, true, mSupports2DArray); + check3D(GL_TEXTURE_3D, true, mSupports3D && !mDisableTexture3D); + + testSampler3D(GL_TEXTURE_3D); } private: @@ -742,6 +765,7 @@ const char kETC2RGBA8[] = "GL_OES_compressed_ETC2_RGBA8_texture"; const char kETC2RGBA8SRGB[] = "GL_OES_compressed_ETC2_sRGB8_alpha8_texture"; const char kASTC[] = "GL_KHR_texture_compression_astc_ldr"; +const char kASTC3D[] = "GL_OES_texture_compression_astc"; const char kASTCSliced3D[] = "GL_KHR_texture_compression_astc_sliced_3d"; const char kPVRTC1[] = "GL_IMG_texture_compression_pvrtc"; @@ -773,6 +797,7 @@ using CompressedTextureETC2RGBA8Test = _Test; using CompressedTextureASTCTest = _Test; +using CompressedTextureASTC3DTest = _Test; using CompressedTextureASTCSliced3DTest = _Test; using CompressedTextureSamplerASTCSliced3DTest = _Test; @@ -801,82 +826,106 @@ std::string PrintToStringParamName( return nameStr.str(); } -static const FormatDesc kDXT1Formats[] = {{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8}, - {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8}}; +static const FormatDesc kDXT1Formats[] = {{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 1, 8}, + {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 1, 8}}; -static const FormatDesc kDXT3Formats[] = {{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 16}}; +static const FormatDesc kDXT3Formats[] = {{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 1, 16}}; -static const FormatDesc kDXT5Formats[] = {{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 16}}; +static const FormatDesc kDXT5Formats[] = {{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 1, 16}}; -static const FormatDesc kS3TCSRGBFormats[] = {{GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8}, - {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8}, - {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16}, - {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16}}; +static const FormatDesc kS3TCSRGBFormats[] = { + {GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 1, 8}, + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 1, 8}, + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 1, 16}, + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 1, 16}}; -static const FormatDesc kRGTCFormats[] = {{GL_COMPRESSED_RED_RGTC1_EXT, 4, 4, 8}, - {GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 8}, - {GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 16}, - {GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 16}}; +static const FormatDesc kRGTCFormats[] = {{GL_COMPRESSED_RED_RGTC1_EXT, 4, 4, 1, 8}, + {GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 1, 8}, + {GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 1, 16}, + {GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 1, 16}}; -static const FormatDesc kBPTCFormats[] = {{GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 16}, - {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 16}, - {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 16}, - {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 16}}; +static const FormatDesc kBPTCFormats[] = {{GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 1, 16}, + {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 1, 16}, + {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 1, 16}, + {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 1, 16}}; -static const FormatDesc kETC1Formats[] = {{GL_ETC1_RGB8_OES, 4, 4, 8}}; +static const FormatDesc kETC1Formats[] = {{GL_ETC1_RGB8_OES, 4, 4, 1, 8}}; // clang-format off -static const FormatDesc kEACR11UFormats[] = {{GL_COMPRESSED_R11_EAC, 4, 4, 8}}; -static const FormatDesc kEACR11SFormats[] = {{GL_COMPRESSED_SIGNED_R11_EAC, 4, 4, 8}}; -static const FormatDesc kEACRG11UFormats[] = {{GL_COMPRESSED_RG11_EAC, 4, 4, 16}}; -static const FormatDesc kEACRG11SFormats[] = {{GL_COMPRESSED_SIGNED_RG11_EAC, 4, 4, 16}}; -static const FormatDesc kETC2RGB8Formats[] = {{GL_COMPRESSED_RGB8_ETC2, 4, 4, 8}}; -static const FormatDesc kETC2RGB8SRGBFormats[] = {{GL_COMPRESSED_SRGB8_ETC2, 4, 4, 8}}; -static const FormatDesc kETC2RGB8A1Formats[] = {{GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 8}}; -static const FormatDesc kETC2RGB8A1SRGBFormats[] = {{GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 8}}; -static const FormatDesc kETC2RGBA8Formats[] = {{GL_COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 16}}; -static const FormatDesc kETC2RGBA8SRGBFormats[] = {{GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 16}}; +static const FormatDesc kEACR11UFormats[] = {{GL_COMPRESSED_R11_EAC, 4, 4, 1, 8}}; +static const FormatDesc kEACR11SFormats[] = {{GL_COMPRESSED_SIGNED_R11_EAC, 4, 4, 1, 8}}; +static const FormatDesc kEACRG11UFormats[] = {{GL_COMPRESSED_RG11_EAC, 4, 4, 1, 16}}; +static const FormatDesc kEACRG11SFormats[] = {{GL_COMPRESSED_SIGNED_RG11_EAC, 4, 4, 1, 16}}; +static const FormatDesc kETC2RGB8Formats[] = {{GL_COMPRESSED_RGB8_ETC2, 4, 4, 1, 8}}; +static const FormatDesc kETC2RGB8SRGBFormats[] = {{GL_COMPRESSED_SRGB8_ETC2, 4, 4, 1, 8}}; +static const FormatDesc kETC2RGB8A1Formats[] = {{GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 1, 8}}; +static const FormatDesc kETC2RGB8A1SRGBFormats[] = {{GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 1, 8}}; +static const FormatDesc kETC2RGBA8Formats[] = {{GL_COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 1, 16}}; +static const FormatDesc kETC2RGBA8SRGBFormats[] = {{GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 1, 16}}; // clang-format on -static const FormatDesc kASTCFormats[] = {{GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 4, 4, 16}, - {GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 5, 4, 16}, - {GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 5, 5, 16}, - {GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 6, 5, 16}, - {GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 6, 6, 16}, - {GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, 16}, - {GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 8, 6, 16}, - {GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 8, 8, 16}, - {GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 10, 5, 16}, - {GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 10, 6, 16}, - {GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 10, 8, 16}, - {GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 10, 10, 16}, - {GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 12, 10, 16}, - {GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 12, 12, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 4, 4, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 5, 4, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 5, 5, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 6, 5, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 6, 6, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 8, 5, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 8, 6, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 8, 8, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 10, 5, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 10, 6, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 10, 8, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, 16}, - {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, 16}}; - -static const FormatDesc kPVRTC1Formats[] = {{GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 8}, - {GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 8, 4, 8}, - {GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 4, 4, 8}, - {GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 8, 4, 8}}; +static const FormatDesc kASTCFormats[] = { + {GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 4, 4, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 5, 4, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 5, 5, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 6, 5, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 6, 6, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 8, 6, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 8, 8, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 10, 5, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 10, 6, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 10, 8, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 10, 10, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 12, 10, 1, 16}, + {GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 12, 12, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 4, 4, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 5, 4, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 5, 5, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 6, 5, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 6, 6, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 8, 5, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 8, 6, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 8, 8, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 10, 5, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 10, 6, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 10, 8, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, 1, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, 1, 16}}; + +static const FormatDesc kASTC3DFormats[] = { + {GL_COMPRESSED_RGBA_ASTC_3x3x3_OES, 3, 3, 3, 16}, + {GL_COMPRESSED_RGBA_ASTC_4x3x3_OES, 4, 3, 3, 16}, + {GL_COMPRESSED_RGBA_ASTC_4x4x3_OES, 4, 4, 3, 16}, + {GL_COMPRESSED_RGBA_ASTC_4x4x4_OES, 4, 4, 4, 16}, + {GL_COMPRESSED_RGBA_ASTC_5x4x4_OES, 5, 4, 4, 16}, + {GL_COMPRESSED_RGBA_ASTC_5x5x4_OES, 5, 5, 4, 16}, + {GL_COMPRESSED_RGBA_ASTC_5x5x5_OES, 5, 5, 5, 16}, + {GL_COMPRESSED_RGBA_ASTC_6x5x5_OES, 6, 5, 5, 16}, + {GL_COMPRESSED_RGBA_ASTC_6x6x5_OES, 6, 6, 5, 16}, + {GL_COMPRESSED_RGBA_ASTC_6x6x6_OES, 6, 6, 6, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES, 3, 3, 3, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES, 4, 3, 3, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES, 4, 4, 3, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES, 4, 4, 4, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES, 5, 4, 4, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES, 5, 5, 4, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES, 5, 5, 5, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES, 6, 5, 5, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES, 6, 6, 5, 16}, + {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES, 6, 6, 6, 16}}; + +static const FormatDesc kPVRTC1Formats[] = {{GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 1, 8}, + {GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 8, 4, 1, 8}, + {GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 4, 4, 1, 8}, + {GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 8, 4, 1, 8}}; static const FormatDesc kPVRTC1SRGBFormats[] = { - {GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, 8, 4, 8}, - {GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, 4, 4, 8}, - {GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, 8, 4, 8}, - {GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, 4, 4, 8}}; + {GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, 8, 4, 1, 8}, + {GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, 4, 4, 1, 8}, + {GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, 8, 4, 1, 8}, + {GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, 4, 4, 1, 8}}; ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureDXT1Test, PrintToStringParamName, @@ -992,6 +1041,11 @@ ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureASTCTest, ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); +ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureASTC3DTest, + PrintToStringParamName, + testing::ValuesIn(kASTC3DFormats), + ANGLE_ALL_TEST_PLATFORMS_ES3); + ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureASTCSliced3DTest, PrintToStringParamName, testing::ValuesIn(kASTCFormats), @@ -1040,6 +1094,7 @@ TEST_P(CompressedTextureETC2RGBA8Test, Test) { test(); } TEST_P(CompressedTextureETC2RGBA8SRGBTest, Test) { test(); } TEST_P(CompressedTextureASTCTest, Test) { test(); } +TEST_P(CompressedTextureASTC3DTest, Test) { test3D(); } TEST_P(CompressedTextureASTCSliced3DTest, Test) { test(); } // Check that texture sampling works correctly diff --git a/src/tests/gl_tests/ComputeShaderTest.cpp b/src/tests/gl_tests/ComputeShaderTest.cpp index 802db8fdc2b..67bf3f71d18 100644 --- a/src/tests/gl_tests/ComputeShaderTest.cpp +++ b/src/tests/gl_tests/ComputeShaderTest.cpp @@ -5,6 +5,11 @@ // // ComputeShaderTest: // Compute shader specific tests. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include #include "test_utils/ANGLETest.h" @@ -2288,6 +2293,90 @@ TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS) EXPECT_EQ(0u, computeProgram); } +// Tests running a compute shader writing to separate components on SSBO without explicit barrier. +// Based on dEQP test: KHR-GLES31.core.shader_storage_buffer_object.advanced-switchBuffers-cs +TEST_P(ComputeShaderTest, WriteToSeparateSSBOComponentsWithoutExplicitBarrier) +{ + constexpr char kCS[] = R"(#version 310 es +precision highp float; +precision highp int; + +layout(local_size_x = 1) in; +layout(binding = 0, std430) buffer Input { + uint cookie[4]; +} g_in; + +layout(binding = 1, std430) buffer Output { + uvec4 digest; +}; + +void main() +{ + uint sum = g_in.cookie[0] + g_in.cookie[1] + g_in.cookie[2] + g_in.cookie[3]; + switch (sum) + { + case 0x000000FFu: + digest.x = 0xFF000000u; + break; + case 0x0000FF00u: + digest.y = 0x00FF0000u; + break; + case 0x00FF0000u: + digest.z = 0x0000FF00u; + break; + case 0xFF000000u: + digest.w = 0x000000FFu; + break; + default: + break; + } +})"; + ANGLE_GL_COMPUTE_PROGRAM(program, kCS); + EXPECT_GL_NO_ERROR(); + glUseProgram(program); + + GLBuffer ssboIn[4]; + GLBuffer ssboOut; + + const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22}; + const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0}; + const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0}; + const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0}; + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboIn[0]); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboIn[1]); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboIn[2]); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboIn[3]); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW); + + const GLubyte dataZero[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboOut); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(dataZero), dataZero, GL_STATIC_DRAW); + + // Since the write is expected to occur on separate components on the output SSBO, no explicit + // barrier is used between the dispatch calls. + for (uint32_t i = 0; i < 4; ++i) + { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboIn[i]); + glDispatchCompute(1, 1, 1); + } + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboOut); + glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + auto actualOutput = static_cast( + glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT)); + EXPECT_NE(actualOutput, nullptr); + + GLuint expectedOutput[4] = {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}; + for (uint32_t i = 0; i < 4; i++) + { + EXPECT_EQ(actualOutput[i], expectedOutput[i]) << "Failed at index " << i; + } +} + // Test that uniform block with struct member in compute shader is supported. TEST_P(ComputeShaderTest, UniformBlockWithStructMember) { @@ -3172,6 +3261,12 @@ void main() // 3.10 TEST_P(ComputeShaderTestES3, NotSupported) { + // Allow the system EGL to skip the test if the context version is not exactly 3.0, which is + // possible when the driver does not support "EGL_ANGLE_create_context_backwards_compatible". + ANGLE_SKIP_TEST_IF(isDriverSystemEgl() && + (getClientMajorVersion() > 3 || + (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1))); + GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER); EXPECT_EQ(0u, computeShaderHandle); EXPECT_GL_ERROR(GL_INVALID_ENUM); @@ -4378,6 +4473,207 @@ void main() { glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); } +// This test mirrors a dEQP test that is failing on some platforms +// - KHR-GLES31.core.shader_image_load_store.advanced-sync-vertexArray +// The test has three pipelines: +// - First uses a vertex shader to store data to images +// - Second uses a compute shader to read from those images and store to buffers +// - Third uses those buffers as vertex input to render a color +// It does this twice with different colors, and we were failing the second pass. +// http://anglebug.com/416573908 +TEST_P(ComputeShaderTest, AdvancedSyncVertexArray) +{ + GLint maxVertexImageUniforms = 0; + glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms); + ANGLE_SKIP_TEST_IF(maxVertexImageUniforms < 3); + + constexpr char kCopyCS[] = R"(#version 310 es +#define KSIZE 4 +layout (local_size_x = KSIZE) in; + +layout(rgba32f, binding = 0) readonly uniform highp image2D positionImage; +layout(rgba32f, binding = 1) readonly uniform highp image2D colorImage; +layout(r32ui, binding = 2) readonly uniform highp uimage2D elementImage; + +layout(std430, binding = 1) buffer positionBuffer { + vec2 position[KSIZE]; +}; +layout(std430, binding = 2) buffer colorBuffer { + vec4 color[KSIZE]; +}; +layout(std430, binding = 3) buffer elementBuffer { + uint element[KSIZE]; +}; + +void main() { + ivec2 coord = ivec2(gl_LocalInvocationID.x, 0); + + position[coord.x] = imageLoad(positionImage, coord).xy; + color[coord.x] = imageLoad(colorImage, coord); + element[coord.x] = uint(imageLoad(elementImage, coord).x); +})"; + + constexpr char kStoreVS[] = R"(#version 310 es +layout(rgba32f, binding = 0) writeonly uniform highp image2D positionImage; +layout(rgba32f, binding = 1) writeonly uniform highp image2D colorImage; +layout(r32ui, binding = 2) writeonly uniform highp uimage2D elementImage; + +uniform vec4 inColor; + +void main() { + vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1)); + + imageStore(positionImage, ivec2(gl_VertexID, 0), vec4(data[gl_VertexID], 0.0, 1.0)); + imageStore(colorImage, ivec2(gl_VertexID, 0), inColor); + imageStore(elementImage, ivec2(gl_VertexID, 0), uvec4(gl_VertexID)); +})"; + + constexpr char kStoreFS[] = R"(#version 310 es +precision mediump float; + +void main() { + discard; +})"; + + constexpr char kDrawVS[] = R"(#version 310 es +layout(location = 0) in vec4 inPosition; +layout(location = 1) in vec4 inColor; + +out vec4 vsColor; + +void main() { + gl_Position = inPosition; + vsColor = inColor; +})"; + + constexpr char kDrawFS[] = R"(#version 310 es +precision mediump float; + +in vec4 vsColor; +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vsColor; +})"; + + // The store program writes values to images + ANGLE_GL_PROGRAM(storeProgram, kStoreVS, kStoreFS); + // The compute program copies from images to buffers + ANGLE_GL_COMPUTE_PROGRAM(copyProgram, kCopyCS); + // The draw program reads from vertex input buffers + ANGLE_GL_PROGRAM(drawProgram, kDrawVS, kDrawFS); + EXPECT_GL_NO_ERROR(); + + GLint inColorLoc = glGetUniformLocation(storeProgram, "inColor"); + ASSERT_NE(inColorLoc, -1); + + GLuint texture[3]; + glGenTextures(3, texture); + glBindTexture(GL_TEXTURE_2D, texture[0]); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, texture[1]); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, texture[2]); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_GL_NO_ERROR(); + + GLuint attribless_vao; + GLuint draw_vao; + glGenVertexArrays(1, &attribless_vao); + glGenVertexArrays(1, &draw_vao); + glBindVertexArray(draw_vao); + EXPECT_GL_NO_ERROR(); + + GLuint position_buffer; + glGenBuffers(1, &position_buffer); + glBindBuffer(GL_ARRAY_BUFFER, position_buffer); + glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); + EXPECT_GL_NO_ERROR(); + + GLuint color_buffer; + glGenBuffers(1, &color_buffer); + glBindBuffer(GL_ARRAY_BUFFER, color_buffer); + glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + EXPECT_GL_NO_ERROR(); + + GLuint element_buffer; + glGenBuffers(1, &element_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + glBindVertexArray(0); + // Vertex position + glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + // Vertex color + glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + // Vertex ID + glBindImageTexture(2, texture[2], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + EXPECT_GL_NO_ERROR(); + + // Store Vertex Positions, GREEN, and Vertex ID to the images + glUseProgram(storeProgram); + glUniform4f(inColorLoc, 0.0f, 1.0f, 0.0f, 1.0f); + glBindVertexArray(attribless_vao); + glDrawArrays(GL_POINTS, 0, 4); + EXPECT_GL_NO_ERROR(); + + // Copy GREEN from images to vertex array buffers + glUseProgram(copyProgram); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, position_buffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, color_buffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, element_buffer); + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + glDispatchCompute(1, 1, 1); + EXPECT_GL_NO_ERROR(); + + // Draw GREEN using the incoming vertex data + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(drawProgram); + glBindVertexArray(draw_vao); + glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); + EXPECT_GL_NO_ERROR(); + + // Check for GREEN + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Store Vertex Positions, BLUE, and Vertex ID to the images + glUseProgram(storeProgram); + glUniform4f(inColorLoc, 0.0f, 0.0f, 1.0f, 1.0f); + glBindVertexArray(attribless_vao); + glDrawArrays(GL_POINTS, 0, 4); + EXPECT_GL_NO_ERROR(); + + // Copy BLUE from images to vertex array buffers + glUseProgram(copyProgram); + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + glDispatchCompute(1, 1, 1); + EXPECT_GL_NO_ERROR(); + + // Draw BLUE using incoming vertex data + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(drawProgram); + glBindVertexArray(draw_vao); + glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); + EXPECT_GL_NO_ERROR(); + + // Check for BLUE + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); +} + // Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is // made. Blit stencil may issue a dispatch call. TEST_P(ComputeShaderTest, DispatchBlitStencilDispatch) @@ -4800,10 +5096,6 @@ TEST_P(ComputeShaderTest, ImageBufferMapWrite) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer")); - // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension - // 'GL_OES_texture_buffer' is not supported". http://anglebug.com/42264369 - ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES()); - constexpr char kComputeImageBuffer[] = R"(#version 310 es #extension GL_OES_texture_buffer : require layout(local_size_x=1, local_size_y=1, local_size_z=1) in; @@ -4871,13 +5163,6 @@ TEST_P(ComputeShaderTest, ImageBufferMapWriteAndBufferSubData) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer")); - // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension - // 'GL_OES_texture_buffer' is not supported". http://anglebug.com/42264369 - ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES()); - - // angleporject:6545. Known bug. - ANGLE_SKIP_TEST_IF(IsVulkan()); - constexpr char kComputeImageBuffer[] = R"(#version 310 es #extension GL_OES_texture_buffer : require layout(local_size_x=1, local_size_y=1, local_size_z=1) in; @@ -4933,9 +5218,9 @@ void main() if (loop == 1) { - // Make write operation finished but read operation pending. We don't care actual - // rendering result but just to have a unflushed rendering using the buffer so that it - // will appears as pending. + // Make write operation finished but read operation pending. We don't care about the + // actual rendering result but just to have unflushed commands using the buffer so that + // it appears as pending. glFinish(); constexpr char kVS[] = R"(attribute vec4 in_attrib; varying vec4 v_attrib; diff --git a/src/tests/gl_tests/ContextLostTest.cpp b/src/tests/gl_tests/ContextLostTest.cpp index 32331f6dced..1192e7e7828 100644 --- a/src/tests/gl_tests/ContextLostTest.cpp +++ b/src/tests/gl_tests/ContextLostTest.cpp @@ -139,6 +139,32 @@ TEST_P(ContextLostTest, ParallelCompileReadyQuery) EXPECT_GLENUM_EQ(linkStatus, 0xBADF00D); } +// Use GL_CHROMIUM_lose_context to lose a context and verify using glGetQueryObject* functions +TEST_P(ContextLostTest, QueryObject) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_lose_context")); + bool disjointTimerQueryEnabled = IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"); + + glLoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET, GL_INNOCENT_CONTEXT_RESET); + EXPECT_GL_NO_ERROR(); + + if (getClientMajorVersion() >= 3) + { + GLuint uint_res; + glGetQueryObjectuiv(0, GL_QUERY_RESULT_AVAILABLE, &uint_res); + EXPECT_GL_ERROR(GL_CONTEXT_LOST); + EXPECT_GLENUM_EQ(uint_res, GL_TRUE); + } + + if (disjointTimerQueryEnabled) + { + GLint int_res; + glGetQueryObjectivEXT(0, GL_QUERY_RESULT_AVAILABLE, &int_res); + EXPECT_GL_ERROR(GL_CONTEXT_LOST); + EXPECT_GLENUM_EQ(int_res, GL_TRUE); + } +} + class ContextLostTestES32 : public ContextLostTest {}; diff --git a/src/tests/gl_tests/ContextNoErrorTest.cpp b/src/tests/gl_tests/ContextNoErrorTest.cpp index 3ae70f41292..e64b3922c19 100644 --- a/src/tests/gl_tests/ContextNoErrorTest.cpp +++ b/src/tests/gl_tests/ContextNoErrorTest.cpp @@ -416,9 +416,195 @@ void main() ASSERT_GL_NO_ERROR(); } +// Tests that a program is resolved before draw calls. +TEST_P(ContextNoErrorTestES3, DrawCommandsWaitOnProgramRelinking) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error")); + + int w = getWindowWidth(); + int h = getWindowHeight(); + glViewport(0, 0, w, h); + + glClearColor(0, 0, 0, 1); + + constexpr char kVS[] = R"(#version 300 es +void main() +{ + vec2 position = vec2(-1, -1); + if (gl_VertexID == 1) + position = vec2(3, -1); + else if (gl_VertexID == 2) + position = vec2(-1, 3); + gl_Position = vec4(position, 0, 1); +})"; + + GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS); + GLuint red = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Red()); + GLuint green = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Green()); + + enum class DrawType + { + DrawArrays, + DrawArraysInstanced, + MultiDrawArrays + }; + + for (auto drawType : + {DrawType::DrawArrays, DrawType::DrawArraysInstanced, DrawType::MultiDrawArrays}) + { + glClear(GL_COLOR_BUFFER_BIT); + + GLuint program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, red); + glLinkProgram(program); + glUseProgram(program); + + // Relink to green while the program is bound. + glDetachShader(program, red); + glAttachShader(program, green); + glLinkProgram(program); + + // Draw must wait until relinking is done. + std::string command; + switch (drawType) + { + case DrawType::DrawArrays: + glDrawArrays(GL_TRIANGLES, 0, 3); + command = "DrawArrays"; + break; + case DrawType::DrawArraysInstanced: + glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1); + command = "glDrawArraysInstanced"; + break; + case DrawType::MultiDrawArrays: + if (IsGLExtensionEnabled("GL_ANGLE_multi_draw")) + { + GLint firsts[1] = {0}; + GLint counts[1] = {3}; + glMultiDrawArraysANGLE(GL_TRIANGLES, firsts, counts, 1); + command = "MultiDrawArrays"; + } + break; + } + EXPECT_PIXEL_COLOR_EQ(w / 2, h / 2, GLColor::green) << command; + ASSERT_GL_NO_ERROR() << command; + } +} + +class ContextNoErrorTestES31 : public ContextNoErrorTest +{}; + +// Tests that a program is resolved before indirect draw calls. +TEST_P(ContextNoErrorTestES31, IndirectDrawCommandsWaitOnProgramRelinking) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error")); + + int w = getWindowWidth(); + int h = getWindowHeight(); + glViewport(0, 0, w, h); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + constexpr char kVS[] = R"(#version 300 es +void main() +{ + vec2 position = vec2(-1, -1); + if (gl_VertexID == 1) + position = vec2(3, -1); + else if (gl_VertexID == 2) + position = vec2(-1, 3); + gl_Position = vec4(position, 0, 1); +})"; + + GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS); + GLuint red = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Red()); + GLuint green = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Green()); + + GLVertexArray vao; + glBindVertexArray(vao); + + const GLushort indexData[3] = {0, 1, 2}; + GLBuffer indexBuffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6, indexData, GL_STATIC_DRAW); + + const GLuint drawArraysData[4] = {3, 1, 0, 0}; + GLBuffer drawArraysIndirectCommandBuffer; + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawArraysIndirectCommandBuffer); + glBufferData(GL_DRAW_INDIRECT_BUFFER, 16, drawArraysData, GL_STATIC_DRAW); + + const GLuint drawElementsData[5] = {3, 1, 0, 0, 0}; + GLBuffer drawElementsIndirectCommandBuffer; + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawElementsIndirectCommandBuffer); + glBufferData(GL_DRAW_INDIRECT_BUFFER, 20, drawElementsData, GL_STATIC_DRAW); + + enum class DrawType + { + DrawArraysIndirect, + DrawElementsIndirect + }; + + for (auto drawType : {DrawType::DrawArraysIndirect, DrawType::DrawElementsIndirect}) + { + glClear(GL_COLOR_BUFFER_BIT); + + // Bind buffers before creating the program + switch (drawType) + { + case DrawType::DrawArraysIndirect: + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawArraysIndirectCommandBuffer); + break; + case DrawType::DrawElementsIndirect: + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawElementsIndirectCommandBuffer); + break; + } + + GLuint program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, red); + glLinkProgram(program); + glUseProgram(program); + + // Relink to green while the program is bound. + glDetachShader(program, red); + glAttachShader(program, green); + glLinkProgram(program); + + // Draw must wait until relinking is done. + std::string command; + switch (drawType) + { + case DrawType::DrawArraysIndirect: + glDrawArraysIndirect(GL_TRIANGLES, nullptr); + command = "DrawArraysIndirect"; + break; + case DrawType::DrawElementsIndirect: + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr); + command = "DrawElementsIndirect"; + break; + } + EXPECT_PIXEL_COLOR_EQ(w / 2, h / 2, GLColor::green) << command; + ASSERT_GL_NO_ERROR() << command; + } +} + ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ContextNoErrorTest); -ANGLE_INSTANTIATE_TEST_ES3(ContextNoErrorTestES3); +#define ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3 \ + ES3_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ + ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ + ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ + ES3_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ + ES3_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ + ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions) +ANGLE_INSTANTIATE_TEST(ContextNoErrorTestES3, ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextNoErrorTestES31); +ANGLE_INSTANTIATE_TEST_ES31(ContextNoErrorTestES31); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextNoErrorPPOTest31); ANGLE_INSTANTIATE_TEST_ES31(ContextNoErrorPPOTest31); diff --git a/src/tests/gl_tests/CopyCompressedTextureTest.cpp b/src/tests/gl_tests/CopyCompressedTextureTest.cpp index 1ba6b556246..6ddadba6370 100644 --- a/src/tests/gl_tests/CopyCompressedTextureTest.cpp +++ b/src/tests/gl_tests/CopyCompressedTextureTest.cpp @@ -7,6 +7,7 @@ // CopyCompressedTextureTest.cpp: Tests of the GL_CHROMIUM_copy_compressed_texture extension #include "test_utils/ANGLETest.h" +#include "test_utils/gl_raii.h" namespace angle { @@ -370,8 +371,213 @@ TEST_P(CopyCompressedTextureTest, Immutable) EXPECT_GL_ERROR(GL_INVALID_OPERATION); } +class CopyCompressedTextureTestES31 : public ANGLETest<> +{ + protected: + CopyCompressedTextureTestES31() + { + setWindowWidth(256); + setWindowHeight(256); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +// Test that if the copy subregion depth is bigger than the depth range of either source texture +// image or destination texture image, glCopyImageSubData() fails with GL_INVALID_VALUE +TEST_P(CopyCompressedTextureTestES31, CopyRegionDepthOverflow) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + // Initialize texture data + std::vector compressedSrcImgDataLevel0; + for (uint8_t i = 1; i < 32 + 1; ++i) + { + compressedSrcImgDataLevel0.push_back(i); + } + + std::vector compressedSrcImgDataLevel1; + for (uint8_t i = 1; i < 16 + 1; ++i) + { + compressedSrcImgDataLevel1.push_back(i); + } + + // Allocate storage for compressedTexture2D, and fills each of 2 levels with the texture data + GLTexture compressedTexture2D; + glBindTexture(GL_TEXTURE_2D, compressedTexture2D); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 8, 4); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 4, GL_COMPRESSED_RGBA_ASTC_6x6, 32, + compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 4, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 16, + compressedSrcImgDataLevel1.data()); + + // Allocate storage for compressedTexture2DArray, and fills each of 2 levels with the texture + // data + GLTexture compressedTexture2DArray; + glBindTexture(GL_TEXTURE_2D_ARRAY, compressedTexture2DArray); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 8, 4, 2); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 4, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 32, compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 8, 4, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 32, compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 2, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 16, compressedSrcImgDataLevel1.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 4, 2, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 16, compressedSrcImgDataLevel1.data()); + + // Perform a copy from compressedTexture2D mipmap 0 to compressedTexture2DArray mipmap 0, where + // the copy region depth is bigger than the depth of source texture mTexture2D mipmap 0. This + // should fail with GL_INVALID_VALUE. + glCopyImageSubDataEXT(compressedTexture2D, GL_TEXTURE_2D, 0, 0, 0, 0, compressedTexture2DArray, + GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 4, 2); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + // Perform a copy from compressedTexture2DArray mipmap 0 to compressedTexture2D mipmap 0, where + // the copy region depth is bigger than the depth of destination texture mTexture2D mipmap 0. + // This should fail with GL_INVALID_VALUE. + glCopyImageSubDataEXT(compressedTexture2DArray, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, + compressedTexture2D, GL_TEXTURE_2D, 0, 0, 0, 0, 8, 4, 2); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that if the copy subregion width and height equals to the texture level width and height, +// even if width and height are not aligned with the compressed texture block size, the +// glCopyImageSubData() should be allowed. +TEST_P(CopyCompressedTextureTestES31, CopyRegionOccupiesEntireMipDoNotNeedAlignment) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + // Initialize texture data + std::vector compressedSrcImgDataLevel0; + for (uint8_t i = 1; i < 32 + 1; ++i) + { + compressedSrcImgDataLevel0.push_back(i); + } + + std::vector compressedSrcImgDataLevel1; + for (uint8_t i = 1; i < 16 + 1; ++i) + { + compressedSrcImgDataLevel1.push_back(i); + } + + // Allocate storage for compressedTexture2D, and fills each of 2 levels with the texture data + GLTexture compressedTexture2D; + glBindTexture(GL_TEXTURE_2D, compressedTexture2D); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 8, 4); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 4, GL_COMPRESSED_RGBA_ASTC_6x6, 32, + compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 4, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 16, + compressedSrcImgDataLevel1.data()); + + // Allocate storage for compressedTexture2DArray, and fills each of 2 levels with the texture + // data + GLTexture compressedTexture2DArray; + glBindTexture(GL_TEXTURE_2D_ARRAY, compressedTexture2DArray); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 8, 4, 2); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 4, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 32, compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 8, 4, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 32, compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 2, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 16, compressedSrcImgDataLevel1.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 4, 2, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 16, compressedSrcImgDataLevel1.data()); + + // Perform a copy from compressedTexture2D mipmap 0 to compressedTexture2DArray mipmap 0. + // This should succeed. Even if the width and height are not multiple of 6, the region covers + // the entire mipmap 0 of source texture mTexture2D, and the region covers the entire slice 0 of + // mipmap 0 of destination texture mTexture2DArray + glCopyImageSubDataEXT(compressedTexture2D, GL_TEXTURE_2D, 0, 0, 0, 0, compressedTexture2DArray, + GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 4, 1); + EXPECT_GL_NO_ERROR(); +} + +// Test that if the copy region offsets are not aligned with the compressed texture block size, +// glCopyImageSubData() should fail with a validation error. +TEST_P(CopyCompressedTextureTestES31, CopyRegionoOffSetNotAlignedShouldGenerateGLError) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + // Initialize texture data + std::vector compressedSrcImgDataLevel0; + for (uint8_t i = 1; i < 32 + 1; ++i) + { + compressedSrcImgDataLevel0.push_back(i); + } + + std::vector compressedSrcImgDataLevel1; + for (uint8_t i = 1; i < 16 + 1; ++i) + { + compressedSrcImgDataLevel1.push_back(i); + } + + // Allocate storage for compressedTexture2D, and fills each of 2 levels with the texture data + GLTexture compressedTexture2D; + glBindTexture(GL_TEXTURE_2D, compressedTexture2D); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 8, 4); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 4, GL_COMPRESSED_RGBA_ASTC_6x6, 32, + compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 4, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 16, + compressedSrcImgDataLevel1.data()); + + // Allocate storage for compressedTexture2DArray, and fills each of 2 levels with the texture + // data + GLTexture compressedTexture2DArray; + glBindTexture(GL_TEXTURE_2D_ARRAY, compressedTexture2DArray); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_COMPRESSED_RGBA_ASTC_6x6, 8, 4, 2); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 4, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 32, compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 8, 4, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 32, compressedSrcImgDataLevel0.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 2, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 16, compressedSrcImgDataLevel1.data()); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 4, 2, 1, GL_COMPRESSED_RGBA_ASTC_6x6, + 16, compressedSrcImgDataLevel1.data()); + + // Perform a copy from compressedTexture2D mipmap 0 to compressedTexture2DArray mipmap 0. + // The copy region offset srcX does not aligned at multiple of 6. + // This should fail with GL_INVALID_VALUE + glCopyImageSubDataEXT(compressedTexture2D, GL_TEXTURE_2D, 0, 2, 0, 0, compressedTexture2DArray, + GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 6, 4, 1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that copying from uncompressed texture to compressed texture works, if their internal +// formats are compatible, and the transformed compressed texture copy subregion aligns with the +// compressed texture block. +TEST_P(CopyCompressedTextureTestES31, CopyFromUncompressedToCompressed) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + + GLTexture uncompressedTexture2D; + glBindTexture(GL_TEXTURE_2D, uncompressedTexture2D); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 2, 1); + constexpr GLuint kTex2DData[] = {0, 0, 0, 0, 0, 0, 0, 0}; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, kTex2DData); + ASSERT_GL_NO_ERROR(); + + // Initialize compressed texture data + std::vector compressedSrcImgDataLevel0; + for (uint8_t i = 1; i < 32 + 1; ++i) + { + compressedSrcImgDataLevel0.push_back(i); + } + + // Allocate storage for compressedTexture2D, and fills with texture data + GLTexture compressedTexture2D; + glBindTexture(GL_TEXTURE_2D, compressedTexture2D); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_ASTC_6x6, 12, 6); + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 12, 6, GL_COMPRESSED_RGBA_ASTC_6x6, 32, + compressedSrcImgDataLevel0.data()); + + glCopyImageSubDataEXT(uncompressedTexture2D, GL_TEXTURE_2D, 0, 0, 0, 0, compressedTexture2D, + GL_TEXTURE_2D, 0, 0, 0, 0, 2, 1, 1); + EXPECT_GL_NO_ERROR(); +} + // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(CopyCompressedTextureTest); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyCompressedTextureTestES31); +ANGLE_INSTANTIATE_TEST_ES31(CopyCompressedTextureTestES31); + } // namespace angle diff --git a/src/tests/gl_tests/CopyTexImageTest.cpp b/src/tests/gl_tests/CopyTexImageTest.cpp index ef25091e805..c3b0c15c97c 100644 --- a/src/tests/gl_tests/CopyTexImageTest.cpp +++ b/src/tests/gl_tests/CopyTexImageTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -104,6 +108,7 @@ class CopyTexImageTest : public ANGLETest<> EXPECT_PIXEL_NEAR(xe - 1, ye - 1, data[0], data[1], data[2], data[3], errorBounds); EXPECT_PIXEL_NEAR((xs + xe) / 2, (ys + ye) / 2, data[0], data[1], data[2], data[3], errorBounds); + ASSERT_GL_NO_ERROR(); } void verifyCheckeredResults(GLuint texture, @@ -160,6 +165,56 @@ class CopyTexImageTest : public ANGLETest<> } } + // Similar test to runCopyTexImageTest, except a different texture is used when the fbo size + // changes. This is to add more coverage for the webgpu backend specifically, as whenever a + // texture changes size an entirely new texture has to be created, and this tests a simpler set + // of functionality. + void runCopyTexImageTestNoResize(GLenum format, + GLubyte expected[3][4], + double errorBounds = 1.0) + { + GLTexture tex1; + glBindTexture(GL_TEXTURE_2D, tex1); + + // Disable mipmapping + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // First iteration, bind a new texture, then attempt a copy with the first fbo size. + glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]); + + glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[0], kFboSizes[0], 0); + ASSERT_GL_NO_ERROR(); + + verifyResults(tex1, expected[0], kFboSizes[0], 0, 0, kFboSizes[0], kFboSizes[0], + errorBounds); + + // Second iteration, use the same texture and same fbo size, attempt another copy. + glBindFramebuffer(GL_FRAMEBUFFER, mFbos[1]); + + glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[1], kFboSizes[1], 0); + ASSERT_GL_NO_ERROR(); + + verifyResults(tex1, expected[1], kFboSizes[1], 0, 0, kFboSizes[1], kFboSizes[1], + errorBounds); + + GLTexture tex2; + glBindTexture(GL_TEXTURE_2D, tex2); + + // Disable mipmapping + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Third iteration, bind a new texture with a different size, do another copy. + glBindFramebuffer(GL_FRAMEBUFFER, mFbos[2]); + + glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[2], kFboSizes[2], 0); + ASSERT_GL_NO_ERROR(); + + verifyResults(tex2, expected[2], kFboSizes[2], 0, 0, kFboSizes[2], kFboSizes[2], + errorBounds); + } + // x, y, width, height specify the portion of fbo to be copied into tex. // flip_y specifies if the glCopyTextImage must be done from y-flipped fbo. void runCopyTexImageTestCheckered(GLenum format, @@ -362,6 +417,20 @@ TEST_P(CopyTexImageTest, RGBAToRGB8) runCopyTexImageTest(GL_RGB8, expected); } +// CopyTexImage from GL_RGBA to GL_RGB8 +TEST_P(CopyTexImageTest, NoResizeRGBAToRGB8) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat")); + GLubyte expected[3][4] = { + {64, 255, 191, 255}, + {255, 191, 127, 255}, + {127, 64, 255, 255}, + }; + + initializeResources(GL_RGBA, GL_UNSIGNED_BYTE); + runCopyTexImageTestNoResize(GL_RGB8, expected); +} + // CopyTexImage from GL_RGBA to GL_RGBA TEST_P(CopyTexImageTest, RGBAToRGBA) { @@ -376,6 +445,20 @@ TEST_P(CopyTexImageTest, RGBAToRGBA) runCopyTexImageTest(GL_RGBA, expected); } +// CopyTexImage from GL_RGBA to GL_RGBA without resizing the same texture. +TEST_P(CopyTexImageTest, NoResizeRGBAToRGBA) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat")); + GLubyte expected[3][4] = { + {64, 255, 191, 128}, + {255, 191, 127, 64}, + {127, 64, 255, 192}, + }; + + initializeResources(GL_RGBA, GL_UNSIGNED_BYTE); + runCopyTexImageTestNoResize(GL_RGBA, expected); +} + TEST_P(CopyTexImageTest, RGBAToL) { GLubyte expected[3][4] = { @@ -1211,6 +1294,50 @@ TEST_P(CopyTexImageTestES3, CopyTexSubImageFromNonZeroBase) kTexSize, 1.0); } +// Similar to CopyTexSubImageFromNonZeroBase, but with different source and dest formats. +TEST_P(CopyTexImageTestES3, CopyTexSubImageFromNonZeroBaseDifferentFormats) +{ + // http://anglebug.com/40644750 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows()); + + constexpr GLsizei kTexSize = 4; + std::vector red(kTexSize * kTexSize, GLColor::red); + std::vector green(kTexSize * kTexSize * 4, GLColor::green); + + // Create a framebuffer attached to a non-zero base texture + GLTexture srcColor; + glBindTexture(GL_TEXTURE_2D, srcColor); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kTexSize * 2, kTexSize * 2); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize * 2, kTexSize * 2, GL_RGBA, GL_UNSIGNED_BYTE, + green.data()); + glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kTexSize, kTexSize, GL_RGBA, GL_UNSIGNED_BYTE, + red.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + ASSERT_GL_NO_ERROR(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Create a texture with an identical format + GLTexture dstColor; + glBindTexture(GL_TEXTURE_2D, dstColor); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, kTexSize, kTexSize, 0, GL_LUMINANCE_ALPHA, + GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + + // Copy into a part of this texture. + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2); + ASSERT_GL_NO_ERROR(); + + // Verify it. Note: the sampled texture is LUMA, with 255 in both luminance and alpha. + constexpr std::array kExpected = {255, 255, 255, 255}; + verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2, 1.0); +} + // Test that copying into a non-zero base texture works. TEST_P(CopyTexImageTestES3, CopyTexSubImageToNonZeroBase) { @@ -1665,6 +1792,32 @@ TEST_P(CopyTexImageTestES3, BGRAAndRGBAConversions) testRGBAToBGRAConversion(); } +// Test that the implementation can handle uploading data with mixed formats to cube maps even if it +// the cube map is not complete. +TEST_P(CopyTexImageTest, MixedCubeMapFormats) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); + + GLTexture texture; + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); + + constexpr GLsizei size = 512; + constexpr GLenum internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + const std::vector data(size * size, 129); + + glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalFormat, size, size, 0, + data.size(), data.data()); + EXPECT_GL_NO_ERROR(); + + glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_LUMINANCE_ALPHA, 0, 0, size, size, 0); + EXPECT_GL_NO_ERROR(); + + const std::vector subData(size * size, 124); + glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, size, size, internalFormat, + subData.size(), subData.data()); + EXPECT_GL_NO_ERROR(); +} + ANGLE_INSTANTIATE_TEST_ES2_AND( CopyTexImageTest, ES2_D3D11_PRESENT_PATH_FAST(), diff --git a/src/tests/gl_tests/CopyTexture3DTest.cpp b/src/tests/gl_tests/CopyTexture3DTest.cpp index 91d6bb9def5..f9fa6fa53d0 100644 --- a/src/tests/gl_tests/CopyTexture3DTest.cpp +++ b/src/tests/gl_tests/CopyTexture3DTest.cpp @@ -6,6 +6,10 @@ // CopyTexture3DTest.cpp: Tests of the GL_ANGLE_copy_texture_3d extension +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp index c89c2606621..cd9bc970b7f 100644 --- a/src/tests/gl_tests/CopyTextureTest.cpp +++ b/src/tests/gl_tests/CopyTextureTest.cpp @@ -6,6 +6,10 @@ // CopyTextureTest.cpp: Tests of the GL_CHROMIUM_copy_texture extension +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -503,7 +507,9 @@ class CopyTextureVariationsTest : public ANGLETest GLint mColorLocation; }; +// Verify that uploading to the faces of a cube map consecutively will correctly upload to each +// face. +TEST_P(CubeMapTextureTest, UploadToFacesConsecutively) +{ + const GLColor faceColors[] = { + GLColor::red, GLColor::green, GLColor::blue, + GLColor::yellow, GLColor::magenta, GLColor::cyan, + }; + + GLuint tex = 0; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_CUBE_MAP, tex); + for (int face = 5; face >= 0; face--) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, faceColors[face].data()); + EXPECT_GL_NO_ERROR(); + } + EXPECT_GL_NO_ERROR(); + + GLuint fbo = 0; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + EXPECT_GL_NO_ERROR(); + + for (GLenum face = 0; face < 6; face++) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, tex, 0); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[face]); + EXPECT_GL_NO_ERROR(); + } + + glDeleteFramebuffers(1, &fbo); + glDeleteTextures(1, &tex); + + EXPECT_GL_NO_ERROR(); +} + // Verify that rendering to the faces of a cube map consecutively will correctly render to each // face. TEST_P(CubeMapTextureTest, RenderToFacesConsecutively) @@ -95,6 +142,10 @@ TEST_P(CubeMapTextureTest, RenderToFacesConsecutively) drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f); EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_EQ(0, 0, faceColor[0] * 255, faceColor[1] * 255, faceColor[2] * 255, + faceColor[3] * 255); + EXPECT_GL_NO_ERROR(); } for (GLenum face = 0; face < 6; face++) @@ -361,4 +412,4 @@ void main() // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(CubeMapTextureTest); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(CubeMapTextureTest); diff --git a/src/tests/gl_tests/D3D11FormatTablesTest.cpp b/src/tests/gl_tests/D3D11FormatTablesTest.cpp index 331d32f7ae6..0583cb2125a 100644 --- a/src/tests/gl_tests/D3D11FormatTablesTest.cpp +++ b/src/tests/gl_tests/D3D11FormatTablesTest.cpp @@ -130,7 +130,7 @@ TEST_P(D3D11FormatTablesTest, TestFormatSupport) EXPECT_EQ(renderable, textureInfo.textureAttachment) << " for " << gl::FmtHex(internalFormat); EXPECT_EQ(renderable, textureInfo.renderbuffer) << " for " << gl::FmtHex(internalFormat); - if (!textureInfo.sampleCounts.empty()) + if (textureInfo.sampleCounts.getMaxSamples() > 0) { EXPECT_TRUE(renderable) << " for " << gl::FmtHex(internalFormat); } @@ -138,24 +138,25 @@ TEST_P(D3D11FormatTablesTest, TestFormatSupport) // Multisample counts if (renderable) { + auto sampleCounts = textureInfo.sampleCounts.sampleCounts(); if ((renderSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0) { - EXPECT_TRUE(!textureInfo.sampleCounts.empty()); + EXPECT_TRUE(!sampleCounts.empty()); for (unsigned int sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2) { UINT qualityCount = 0; bool sampleSuccess = SUCCEEDED(device->CheckMultisampleQualityLevels( renderFormat, sampleCount, &qualityCount)); - GLuint expectedCount = (!sampleSuccess || qualityCount == 0) ? 0 : 1; - EXPECT_EQ(expectedCount, textureInfo.sampleCounts.count(sampleCount)) - << " for " << gl::FmtHex(internalFormat); + bool expected = sampleSuccess && qualityCount != 0; + bool exists = std::find(sampleCounts.begin(), sampleCounts.end(), + sampleCount) != sampleCounts.end(); + EXPECT_EQ(expected, exists) << " for " << gl::FmtHex(internalFormat); } } else { - EXPECT_TRUE(textureInfo.sampleCounts.empty()) - << " for " << gl::FmtHex(internalFormat); + EXPECT_TRUE(sampleCounts.empty()) << " for " << gl::FmtHex(internalFormat); } } } diff --git a/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp b/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp index 3196dd23c1f..4e1fc20ef70 100644 --- a/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp +++ b/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp @@ -125,6 +125,6 @@ TEST_P(D3D11InputLayoutCacheTest, StressTest) } } -ANGLE_INSTANTIATE_TEST(D3D11InputLayoutCacheTest, ES2_D3D11(), ES3_D3D11(), ES31_D3D11()); +ANGLE_INSTANTIATE_TEST(D3D11InputLayoutCacheTest, ES2_D3D11(), ES3_D3D11()); } // anonymous namespace diff --git a/src/tests/gl_tests/D3DImageFormatConversionTest.cpp b/src/tests/gl_tests/D3DImageFormatConversionTest.cpp index a0ddbd1bd25..3d9e0e46376 100644 --- a/src/tests/gl_tests/D3DImageFormatConversionTest.cpp +++ b/src/tests/gl_tests/D3DImageFormatConversionTest.cpp @@ -6,6 +6,10 @@ // D3DImageFormatConversionTest: // Basic tests to validate code relating to D3D Image format conversions. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "image_util/imageformats.h" diff --git a/src/tests/gl_tests/D3DTextureTest.cpp b/src/tests/gl_tests/D3DTextureTest.cpp index b20f755785d..e777d31a3c7 100644 --- a/src/tests/gl_tests/D3DTextureTest.cpp +++ b/src/tests/gl_tests/D3DTextureTest.cpp @@ -6,6 +6,10 @@ // D3DTextureTest: // Tests of the EGL_ANGLE_d3d_texture_client_buffer extension +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/DXT1CompressedTextureTest.cpp b/src/tests/gl_tests/DXT1CompressedTextureTest.cpp index 5decc7929c4..e7251997ea4 100644 --- a/src/tests/gl_tests/DXT1CompressedTextureTest.cpp +++ b/src/tests/gl_tests/DXT1CompressedTextureTest.cpp @@ -222,6 +222,68 @@ TEST_P(DXT1CompressedTextureTest, CompressedTexStorage) EXPECT_GL_NO_ERROR(); } +// Test to verify that reinitializing an image with incompatible mip levels but non-mipmap filtering +// does not cause a crash. +TEST_P(DXT1CompressedTextureTest, ReinitImageWithIncompatibleLevels) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1")); + + // Blue color. + const std::vector kSingleLevelData(pixel_0_width * pixel_0_height, 0x001f); + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + // Use GL_LINEAR filtering so that mipmap is not used. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // Store a compressed image data with a level count of 10. + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_0_width, + pixel_0_height, 0, pixel_0_size, pixel_0_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_1_width, + pixel_1_height, 0, pixel_1_size, pixel_1_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_2_width, + pixel_2_height, 0, pixel_2_size, pixel_2_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_3_width, + pixel_3_height, 0, pixel_3_size, pixel_3_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_4_width, + pixel_4_height, 0, pixel_4_size, pixel_4_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 5, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_5_width, + pixel_5_height, 0, pixel_5_size, pixel_5_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 6, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_6_width, + pixel_6_height, 0, pixel_6_size, pixel_6_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 7, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_7_width, + pixel_7_height, 0, pixel_7_size, pixel_7_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 8, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_8_width, + pixel_8_height, 0, pixel_8_size, pixel_8_data); + glCompressedTexImage2D(GL_TEXTURE_2D, 9, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_9_width, + pixel_9_height, 0, pixel_9_size, pixel_9_data); + EXPECT_GL_NO_ERROR(); + + glUseProgram(mTextureProgram); + glUniform1i(mTextureUniformLocation, 0); + + // Verify draw with level 10. + drawQuad(mTextureProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + + // Reinit image with a different sized internal format with a level count of 1. This will + // redefine the texture level. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pixel_0_width, pixel_0_height, 0, GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, kSingleLevelData.data()); + EXPECT_GL_NO_ERROR(); + + // Verify that the image with level 0 is successfully redefined, and expect no crash. + drawQuad(mTextureProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); +} + // Test validation of non block sizes, width 672 and height 114 and multiple mip levels TEST_P(DXT1CompressedTextureTest, NonBlockSizesMipLevels) { diff --git a/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp b/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp index 52f324977da..b4f738bedcd 100644 --- a/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp +++ b/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// DXTSRGBCompressedTextureTest.cpp +// DXTSRGBCompressedTextureTest.cpp: // Tests for sRGB DXT textures (GL_EXT_texture_compression_s3tc_srgb) // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/DebugTest.cpp b/src/tests/gl_tests/DebugTest.cpp index a9142eb2f0d..80b95b41c46 100644 --- a/src/tests/gl_tests/DebugTest.cpp +++ b/src/tests/gl_tests/DebugTest.cpp @@ -35,11 +35,12 @@ class DebugTest : public ANGLETest<> setConfigAlphaBits(8); setConfigDepthBits(24); setDebugEnabled(true); + setExtensionsEnabled(false); } void testSetUp() override { - mDebugExtensionAvailable = IsGLExtensionEnabled("GL_KHR_debug"); + mDebugExtensionAvailable = EnsureGLExtensionEnabled("GL_KHR_debug"); if (mDebugExtensionAvailable) { glEnable(GL_DEBUG_OUTPUT); @@ -49,7 +50,11 @@ class DebugTest : public ANGLETest<> bool mDebugExtensionAvailable; }; -void createGLObjectAndLabel(GLenum identifier, GLuint &object, const char **label) +void createGLObjectAndLabel(GLenum identifier, + GLuint &object, + const char **label, + int major, + int minor) { switch (identifier) { @@ -67,18 +72,42 @@ void createGLObjectAndLabel(GLenum identifier, GLuint &object, const char **labe *label = kProgramObjLabel; break; case GL_VERTEX_ARRAY_OBJECT_EXT: - glGenVertexArrays(1, &object); - glBindVertexArray(object); + if (major < 3) + { + glGenVertexArraysOES(1, &object); + glBindVertexArrayOES(object); + } + else + { + glGenVertexArrays(1, &object); + glBindVertexArray(object); + } *label = kVertexArrayObjLabel; break; case GL_QUERY_OBJECT_EXT: - glGenQueries(1, &object); - glBeginQuery(GL_ANY_SAMPLES_PASSED, object); + if (major < 3) + { + glGenQueriesEXT(1, &object); + glBeginQueryEXT(GL_ANY_SAMPLES_PASSED, object); + } + else + { + glGenQueries(1, &object); + glBeginQuery(GL_ANY_SAMPLES_PASSED, object); + } *label = kQueryObjLabel; break; case GL_PROGRAM_PIPELINE_OBJECT_EXT: - glGenProgramPipelines(1, &object); - glBindProgramPipeline(object); + if (major < 3 || minor < 1) + { + glGenProgramPipelinesEXT(1, &object); + glBindProgramPipelineEXT(object); + } + else + { + glGenProgramPipelines(1, &object); + glBindProgramPipeline(object); + } *label = kProgramPipelineObjLabel; break; default: @@ -87,7 +116,7 @@ void createGLObjectAndLabel(GLenum identifier, GLuint &object, const char **labe } } -void deleteGLObject(GLenum identifier, GLuint &object) +void deleteGLObject(GLenum identifier, GLuint &object, int major, int minor) { switch (identifier) { @@ -101,14 +130,36 @@ void deleteGLObject(GLenum identifier, GLuint &object) glDeleteProgram(object); break; case GL_VERTEX_ARRAY_OBJECT_EXT: - glDeleteVertexArrays(1, &object); + if (major < 3) + { + glDeleteVertexArraysOES(1, &object); + } + else + { + glDeleteVertexArrays(1, &object); + } break; case GL_QUERY_OBJECT_EXT: - glEndQuery(GL_ANY_SAMPLES_PASSED); - glDeleteQueries(1, &object); + if (major < 3) + { + glEndQueryEXT(GL_ANY_SAMPLES_PASSED); + glDeleteQueriesEXT(1, &object); + } + else + { + glEndQuery(GL_ANY_SAMPLES_PASSED); + glDeleteQueries(1, &object); + } break; case GL_PROGRAM_PIPELINE_OBJECT_EXT: - glDeleteProgramPipelines(1, &object); + if (major < 3 || minor < 1) + { + glDeleteProgramPipelinesEXT(1, &object); + } + else + { + glDeleteProgramPipelines(1, &object); + } break; default: UNREACHABLE(); @@ -126,23 +177,30 @@ TEST_P(DebugTest, ObjectLabelsEXT) bool skip = false; switch (identifier) { + case GL_PROGRAM_OBJECT_EXT: + case GL_SHADER_OBJECT_EXT: + if (getClientMajorVersion() < 2) + { + skip = true; + } + break; case GL_PROGRAM_PIPELINE_OBJECT_EXT: - if (!(getClientMajorVersion() >= 3 && getClientMinorVersion() >= 1) || - !IsGLExtensionEnabled("GL_EXT_separate_shader_objects")) + if ((getClientMajorVersion() < 3 || getClientMinorVersion() < 1) && + !EnsureGLExtensionEnabled("GL_EXT_separate_shader_objects")) { skip = true; } break; case GL_QUERY_OBJECT_EXT: - // GLES3 context is required for glGenQueries() - if (getClientMajorVersion() < 3 || - !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean")) + if (getClientMajorVersion() < 3 && + !EnsureGLExtensionEnabled("GL_EXT_occlusion_query_boolean")) { skip = true; } break; case GL_VERTEX_ARRAY_OBJECT_EXT: - if (getClientMajorVersion() < 3) + if (getClientMajorVersion() < 3 && + !EnsureGLExtensionEnabled("GL_OES_vertex_array_object")) { skip = true; } @@ -159,7 +217,9 @@ TEST_P(DebugTest, ObjectLabelsEXT) GLuint object; const char *label; - createGLObjectAndLabel(identifier, object, &label); + createGLObjectAndLabel(identifier, object, &label, getClientMajorVersion(), + getClientMinorVersion()); + ASSERT_GL_NO_ERROR(); glLabelObjectEXT(identifier, object, 0, label); ASSERT_GL_NO_ERROR(); @@ -173,10 +233,9 @@ TEST_P(DebugTest, ObjectLabelsEXT) EXPECT_EQ(static_cast(strlen(label)), labelLengthBuf); EXPECT_STREQ(label, labelBuf.data()); + deleteGLObject(identifier, object, getClientMajorVersion(), getClientMinorVersion()); ASSERT_GL_NO_ERROR(); - deleteGLObject(identifier, object); - glLabelObjectEXT(identifier, object, 0, label); EXPECT_GL_ERROR(GL_INVALID_OPERATION); @@ -186,6 +245,61 @@ TEST_P(DebugTest, ObjectLabelsEXT) } } +// Test basic usage of setting and getting labels using GL_EXT_debug_label on timer query objects +TEST_P(DebugTest, TimerQueryObjectLabelsEXT) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_debug_label")); + + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_disjoint_timer_query")); + + GLuint object; + glGenQueriesEXT(1, &object); + glBeginQueryEXT(GL_TIME_ELAPSED_EXT, object); + ASSERT_GL_NO_ERROR(); + + glLabelObjectEXT(GL_QUERY_OBJECT_EXT, object, 0, kQueryObjLabel); + EXPECT_GL_NO_ERROR(); + + std::vector labelBuf(strlen(kQueryObjLabel) + 1); + GLsizei labelLengthBuf = 0; + glGetObjectLabelEXT(GL_QUERY_OBJECT_EXT, object, static_cast(labelBuf.size()), + &labelLengthBuf, labelBuf.data()); + ASSERT_GL_NO_ERROR(); + + EXPECT_EQ(static_cast(strlen(kQueryObjLabel)), labelLengthBuf); + EXPECT_STREQ(kQueryObjLabel, labelBuf.data()); + + glEndQueryEXT(GL_TIME_ELAPSED_EXT); + glDeleteQueriesEXT(1, &object); + ASSERT_GL_NO_ERROR(); + + glLabelObjectEXT(GL_QUERY_OBJECT_EXT, object, 0, kQueryObjLabel); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glGetObjectLabelEXT(GL_QUERY_OBJECT_EXT, object, static_cast(labelBuf.size()), + &labelLengthBuf, labelBuf.data()); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Simple test for GetDebugMessageLogKHR validation +TEST_P(DebugTest, GetDebugMessageLog) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + + glGetDebugMessageLogKHR(1, -1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + EXPECT_GL_NO_ERROR(); + + glGetDebugMessageLogKHR(1, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + EXPECT_GL_NO_ERROR(); + + std::vector messageBuf(1); + glGetDebugMessageLogKHR(1, -1, nullptr, nullptr, nullptr, nullptr, nullptr, messageBuf.data()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glGetDebugMessageLogKHR(1, 0, nullptr, nullptr, nullptr, nullptr, nullptr, messageBuf.data()); + EXPECT_GL_NO_ERROR(); +} + class DebugTestES3 : public DebugTest {}; @@ -347,6 +461,185 @@ TEST_P(DebugTestES3, InsertMessageMultiple) ASSERT_GL_NO_ERROR(); } +// Test that a too long label fails +TEST_P(DebugTest, ObjectLabelTooLong) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + + // Limit includes the null terminator + GLint maxLength = 0; + glGetIntegerv(GL_MAX_LABEL_LENGTH_KHR, &maxLength); + ASSERT_GE(maxLength, 1); + + GLBuffer object; + glBindBuffer(GL_ARRAY_BUFFER, object); + ASSERT_GL_NO_ERROR(); + + // Implicit length + glObjectLabelKHR(GL_BUFFER_KHR, object, -1, std::string(maxLength - 1, 'A').c_str()); + EXPECT_GL_NO_ERROR(); + + glObjectLabelKHR(GL_BUFFER_KHR, object, -1, std::string(maxLength, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glObjectLabelKHR(GL_BUFFER_KHR, object, -1, std::string(maxLength + 1, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + // Explicit length + const std::string label = std::string(maxLength + 1, 'B'); + + glObjectLabelKHR(GL_BUFFER_KHR, object, maxLength - 1, label.c_str()); + EXPECT_GL_NO_ERROR(); + + glObjectLabelKHR(GL_BUFFER_KHR, object, maxLength, label.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glObjectLabelKHR(GL_BUFFER_KHR, object, maxLength + 1, label.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that a too long sync object label fails +TEST_P(DebugTestES3, ObjectPtrLabelTooLong) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + + // Limit includes the null terminator + GLint maxLength = 0; + glGetIntegerv(GL_MAX_LABEL_LENGTH_KHR, &maxLength); + ASSERT_GE(maxLength, 1); + + GLsync object = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + ASSERT_GL_NO_ERROR(); + + // Implicit length + glObjectPtrLabelKHR(object, -1, std::string(maxLength - 1, 'A').c_str()); + EXPECT_GL_NO_ERROR(); + + glObjectPtrLabelKHR(object, -1, std::string(maxLength, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glObjectPtrLabelKHR(object, -1, std::string(maxLength + 1, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + // Explicit length + const std::string label = std::string(maxLength + 1, 'B'); + + glObjectPtrLabelKHR(object, maxLength - 1, label.c_str()); + EXPECT_GL_NO_ERROR(); + + glObjectPtrLabelKHR(object, maxLength, label.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glObjectPtrLabelKHR(object, maxLength + 1, label.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glDeleteSync(object); +} + +// Test that a too long debug group fails +TEST_P(DebugTest, PushDebugGroupTooLong) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + + // Limit includes the null terminator + GLint maxLength = 0; + glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH_KHR, &maxLength); + ASSERT_GE(maxLength, 1); + + const GLenum source = GL_DEBUG_SOURCE_APPLICATION_KHR; + + // Implicit length + glPushDebugGroupKHR(source, 1, -1, std::string(maxLength - 1, 'A').c_str()); + EXPECT_GL_NO_ERROR(); + + glPushDebugGroupKHR(source, 1, -1, std::string(maxLength, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glPushDebugGroupKHR(source, 1, -1, std::string(maxLength + 1, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + // Explicit length + const std::string message = std::string(maxLength + 1, 'B'); + + glPushDebugGroupKHR(source, 1, maxLength - 1, message.c_str()); + EXPECT_GL_NO_ERROR(); + + glPushDebugGroupKHR(source, 1, maxLength, message.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glPushDebugGroupKHR(source, 1, maxLength + 1, message.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that a too long message fails +TEST_P(DebugTest, InsertMessageTooLong) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + + // Limit includes the null terminator + GLint maxLength = 0; + glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH_KHR, &maxLength); + ASSERT_GE(maxLength, 1); + + const GLenum source = GL_DEBUG_SOURCE_APPLICATION_KHR; + const GLenum type = GL_DEBUG_TYPE_OTHER_KHR; + const GLenum severity = GL_DEBUG_SEVERITY_NOTIFICATION_KHR; + + // Implicit length + glDebugMessageInsertKHR(source, type, 1, severity, -1, std::string(maxLength - 1, 'A').c_str()); + EXPECT_GL_NO_ERROR(); + + glDebugMessageInsertKHR(source, type, 1, severity, -1, std::string(maxLength, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glDebugMessageInsertKHR(source, type, 1, severity, -1, std::string(maxLength + 1, 'A').c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + // Explicit length + const std::string message = std::string(maxLength + 1, 'B'); + + glDebugMessageInsertKHR(source, type, 1, severity, maxLength - 1, message.c_str()); + EXPECT_GL_NO_ERROR(); + + glDebugMessageInsertKHR(source, type, 1, severity, maxLength, message.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glDebugMessageInsertKHR(source, type, 1, severity, maxLength + 1, message.c_str()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that passing a zero length inserts an empty message +TEST_P(DebugTest, InsertMessageZeroLength) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + + GLint numMessages = 0; + glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES_KHR, &numMessages); + ASSERT_EQ(0, numMessages); + + const GLenum source = GL_DEBUG_SOURCE_APPLICATION_KHR; + const GLenum type = GL_DEBUG_TYPE_OTHER_KHR; + const GLenum severity = GL_DEBUG_SEVERITY_NOTIFICATION_KHR; + + glDebugMessageInsertKHR(source, type, 1, severity, 0, "abc"); + EXPECT_GL_NO_ERROR(); + + GLsizei lengthBuf = 0; + std::vector messageBuf(4, 0xFF); + GLuint ret = glGetDebugMessageLogKHR(1, static_cast(messageBuf.size()), nullptr, + nullptr, nullptr, nullptr, &lengthBuf, messageBuf.data()); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(1u, ret); + EXPECT_EQ(lengthBuf, 1); + EXPECT_EQ('\x00', messageBuf[0]); + EXPECT_EQ('\xFF', messageBuf[1]); + EXPECT_EQ('\xFF', messageBuf[2]); + EXPECT_EQ('\xFF', messageBuf[3]); + + glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES_KHR, &numMessages); + EXPECT_EQ(0, numMessages); +} + // Test using a debug callback TEST_P(DebugTestES3, DebugCallback) { @@ -637,16 +930,44 @@ TEST_P(DebugTestES3, Rendering) glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_HIGH, -1, inGroup3Marker.c_str()); } - glPopGroupMarkerEXT(); + glPopDebugGroupKHR(); glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, -1, afterDrawMarker.c_str()); } - glPopGroupMarkerEXT(); + glPopDebugGroupKHR(); ASSERT_GL_NO_ERROR(); } +// Test that glPushGroupMarker() issues a stack overflow error when the stack size is capped. +TEST_P(DebugTestES3, PushTooManyGroupMarkers) +{ + ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_debug_marker")); + + GLint maxStackDepth; + glGetIntegerv(GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR, &maxStackDepth); + + const std::string markerLabel = "Test Group Marker"; + for (GLint i = 0; i < maxStackDepth; i++) + { + glPushGroupMarkerEXT(0, markerLabel.c_str()); + ASSERT_GL_NO_ERROR(); + } + + glPushGroupMarkerEXT(0, markerLabel.c_str()); + EXPECT_GL_ERROR(GL_STACK_OVERFLOW); +} + +// Test that glPopGroupMarker() is ignored if the stack is already empty. +TEST_P(DebugTestES3, PopGroupMarkerWithEmptyStack) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_debug_marker")); + glPopGroupMarkerEXT(); + ASSERT_GL_NO_ERROR(); +} + // Simple test for gl[Push, Pop]DebugGroup using ES32 core APIs TEST_P(DebugTestES32, DebugGroup) { @@ -723,6 +1044,23 @@ TEST_P(DebugTestES32, ObjectPtrLabels) EXPECT_GL_ERROR(GL_INVALID_VALUE); } +// Simple test for GetDebugMessageLog validation using ES32 core API +TEST_P(DebugTestES32, GetDebugMessageLog) +{ + glGetDebugMessageLog(1, -1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + EXPECT_GL_NO_ERROR(); + + glGetDebugMessageLog(1, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + EXPECT_GL_NO_ERROR(); + + std::vector messageBuf(1); + glGetDebugMessageLog(1, -1, nullptr, nullptr, nullptr, nullptr, nullptr, messageBuf.data()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glGetDebugMessageLog(1, 0, nullptr, nullptr, nullptr, nullptr, nullptr, messageBuf.data()); + EXPECT_GL_NO_ERROR(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DebugTestES3); ANGLE_INSTANTIATE_TEST_ES3(DebugTestES3); diff --git a/src/tests/gl_tests/DepthStencilFormatsTest.cpp b/src/tests/gl_tests/DepthStencilFormatsTest.cpp index dd5c7c64577..804309054ea 100644 --- a/src/tests/gl_tests/DepthStencilFormatsTest.cpp +++ b/src/tests/gl_tests/DepthStencilFormatsTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -15,8 +19,9 @@ using namespace angle; struct ReadbackTestParam { GLuint attachment; - GLuint format; - GLuint type; + GLint internalformat; + GLenum format; + GLenum type; void *data; int depthBits; int stencilBits; @@ -257,17 +262,19 @@ void DepthStencilFormatsTestBase::depthStencilReadbackCase(const ReadbackTestPar glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_GL_NO_ERROR(); // test level > 0 - glTexImage2D(GL_TEXTURE_2D, 1, type.format, 1, 1, 0, type.format, type.type, nullptr); + glTexImage2D(GL_TEXTURE_2D, 1, type.internalformat, 1, 1, 0, type.format, type.type, nullptr); EXPECT_GL_NO_ERROR(); // test with data - glTexImage2D(GL_TEXTURE_2D, 0, type.format, 1, 1, 0, type.format, type.type, type.data); + glTexImage2D(GL_TEXTURE_2D, 0, type.internalformat, 1, 1, 0, type.format, type.type, type.data); EXPECT_GL_NO_ERROR(); // test real thing - glTexImage2D(GL_TEXTURE_2D, 0, type.format, res, res, 0, type.format, type.type, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, type.internalformat, res, res, 0, type.format, type.type, + nullptr); EXPECT_GL_NO_ERROR(); // test texSubImage2D @@ -440,7 +447,15 @@ TEST_P(DepthStencilFormatsTest, DepthStencilReadback_UShort) { GLuint fakeData[10] = {0}; ReadbackTestParam type = { - GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, fakeData, 16, 0}; + GL_DEPTH_ATTACHMENT, + // GLES 2.0: If internalformat does not match format, the error INVALID_OPERATION is + // generated. + // GLES 3.0+: Specifying a combination of values for format, type, and internalformat that + // is not listed as a valid combination in tables 3.2 or 3.3 generates the error + // INVALID_OPERATION. + getClientMajorVersion() < 3 ? GL_DEPTH_COMPONENT : GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, + GL_UNSIGNED_SHORT, fakeData, 16, 0}; + depthStencilReadbackCase(type); } @@ -452,7 +467,14 @@ TEST_P(DepthStencilFormatsTest, DepthStencilReadback_UInt) GLuint fakeData[10] = {0}; ReadbackTestParam type = { - GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, fakeData, 16, 0}; + GL_DEPTH_ATTACHMENT, + // GLES 2.0: If internalformat does not match format, the error INVALID_OPERATION is + // generated. + // GLES 3.0+: Specifying a combination of values for format, type, and internalformat that + // is not listed as a valid combination in tables 3.2 or 3.3 generates the error + // INVALID_OPERATION. + getClientMajorVersion() < 3 ? GL_DEPTH_COMPONENT : GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, fakeData, 16, 0}; depthStencilReadbackCase(type); } @@ -463,7 +485,16 @@ TEST_P(DepthStencilFormatsTest, DepthStencilReadback_Float) ANGLE_SKIP_TEST_IF(IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); GLuint fakeData[10] = {0}; - ReadbackTestParam type = {GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_FLOAT, fakeData, 32, 0}; + ReadbackTestParam type = { + GL_DEPTH_ATTACHMENT, + // GLES 2.0: If internalformat does not match format, the error INVALID_OPERATION is + // generated. + // GLES 3.0+: Specifying a combination of values for format, type, and internalformat that + // is not listed as a valid combination in tables 3.2 or 3.3 generates the error + // INVALID_OPERATION. + getClientMajorVersion() < 3 ? GL_DEPTH_COMPONENT : GL_DEPTH_COMPONENT32F, + GL_DEPTH_COMPONENT, GL_FLOAT, fakeData, 32, 0}; + depthStencilReadbackCase(type); } @@ -472,7 +503,15 @@ TEST_P(DepthStencilFormatsTest, DepthStencilReadback_DepthStencil) { GLuint fakeData[10] = {0}; ReadbackTestParam type = { - GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_OES, fakeData, 24, 8}; + GL_DEPTH_STENCIL_ATTACHMENT, + // GLES 2.0: If internalformat does not match format, the error INVALID_OPERATION is + // generated. + // GLES 3.0+: Specifying a combination of values for format, type, and internalformat that + // is not listed as a valid combination in tables 3.2 or 3.3 generates the error + // INVALID_OPERATION. + getClientMajorVersion() < 3 ? GL_DEPTH_STENCIL : GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, + GL_UNSIGNED_INT_24_8_OES, fakeData, 24, 8}; + depthStencilReadbackCase(type); } @@ -540,7 +579,8 @@ void main() ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth_texture") && !IsGLExtensionEnabled("GL_ANGLE_depth_texture")); - bool depthTextureCubeSupport = IsGLExtensionEnabled("GL_OES_depth_texture_cube_map"); + bool depthTextureCubeSupport = + IsGLExtensionEnabled("GL_OES_depth_texture_cube_map") || getClientMajorVersion() >= 3; bool textureSrgbDecodeSupport = IsGLExtensionEnabled("GL_EXT_texture_sRGB_decode"); // http://anglebug.com/42262117 @@ -826,8 +866,25 @@ void main() glFramebufferTexture2D(GL_FRAMEBUFFER, type.attachment, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex, 0); - EXPECT_GLENUM_NE(GL_NO_ERROR, glGetError()); - EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + if (getClientMajorVersion() < 3) + { + EXPECT_GLENUM_NE(GL_NO_ERROR, glGetError()); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } + else + { + EXPECT_GL_NO_ERROR(); + // Attaching a level of a texture to GL_DEPTH_STENCIL_ATTACHMENT is equivalent + // to attaching that level to both the GL_DEPTH_ATTACHMENT and the + // GL_STENCIL_ATTACHMENT attachment points simultaneously. + // The texture type is depth-only, so expect incomplete when attempting to + // attach to GL_DEPTH_STENCIL_ATTACHMENT. + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } + glClear(GL_DEPTH_BUFFER_BIT); EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -1294,7 +1351,7 @@ void main() EXPECT_GL_NO_ERROR(); } -ANGLE_INSTANTIATE_TEST_ES2(DepthStencilFormatsTest); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DepthStencilFormatsTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DepthStencilFormatsTestES3); ANGLE_INSTANTIATE_TEST_ES3(DepthStencilFormatsTestES3); @@ -1428,8 +1485,7 @@ TEST_P(TinyDepthStencilWorkaroundTest, DepthTexturesStick) } // Initialize a depth texture by writing to it in a fragment shader then attempt to read it from a -// compute shader. Regression test for D3D11 not unbinding the depth texture and the sampler binding -// failing. +// compute shader. TEST_P(DepthStencilFormatsTestES31, ReadDepthStencilInComputeShader) { constexpr char kTestVertexShader[] = R"(#version 310 es diff --git a/src/tests/gl_tests/DepthStencilTest.cpp b/src/tests/gl_tests/DepthStencilTest.cpp index 5c32bbe4101..42eee68ca05 100644 --- a/src/tests/gl_tests/DepthStencilTest.cpp +++ b/src/tests/gl_tests/DepthStencilTest.cpp @@ -354,7 +354,7 @@ TEST_P(DepthStencilTestES3, ClearThenDraw) // Test that VK_EXT_load_op_none is working properly when // one of the depth / stencil load op is none. -// This reproduces a deqp failure on ARM: angleproject:7370 +// This reproduces a deqp failure on ARM: http://anglebug.com/42265841 TEST_P(DepthStencilTestES3, LoadStoreOpNoneExtension) { GLFramebuffer fbo; diff --git a/src/tests/gl_tests/DepthWriteTest.cpp b/src/tests/gl_tests/DepthWriteTest.cpp index b8c55919842..400df3da947 100644 --- a/src/tests/gl_tests/DepthWriteTest.cpp +++ b/src/tests/gl_tests/DepthWriteTest.cpp @@ -82,13 +82,13 @@ std::ostream &operator<<(std::ostream &out, VertexDepth vertexDepth) switch (vertexDepth) { case VertexDepth::InsideClipVolume: - out << "InsideClipVolume"; + out << "VInside"; break; case VertexDepth::LessThanMinusOne: - out << "LessThanMinusOne"; + out << "VUnderNegOne"; break; case VertexDepth::GreaterThanOne: - out << "GreaterThanOne"; + out << "VOverOne"; break; } @@ -100,25 +100,25 @@ std::ostream &operator<<(std::ostream &out, FragmentDepth fragmentDepth) switch (fragmentDepth) { case FragmentDepth::Unused: - out << "Unused"; + out << "FUnused"; break; case FragmentDepth::Passthrough: - out << "Passthrough"; + out << "FPassthru"; break; case FragmentDepth::WithinDepthRange: - out << "WithinDepthRange"; + out << "FWithinRange"; break; case FragmentDepth::BetweenZeroAndNearPlane: - out << "BetweenZeroAndNearPlane"; + out << "FZeroToNear"; break; case FragmentDepth::BetweenFarPlaneAndOne: - out << "BetweenFarPlaneAndOne"; + out << "FFarToOne"; break; case FragmentDepth::Negative: - out << "Negative"; + out << "FNegative"; break; case FragmentDepth::GreaterThanOne: - out << "GreaterThanOne"; + out << "FOverOne"; break; } @@ -130,11 +130,11 @@ std::string BufferFormatToString(GLenum format) switch (format) { case GL_DEPTH_COMPONENT16: - return "Depth16Unorm"; + return "D16"; case GL_DEPTH_COMPONENT32F: - return "Depth32Float"; + return "D32F"; default: - return nullptr; + return ""; } } @@ -168,10 +168,8 @@ std::string DepthWriteVariationsTestPrint( ParseDepthWriteVariationsTestParams(params, &depthRange, &depthClampEnabled, &vertexDepth, &fragmentDepth, &depthBufferFormat); - out << "__" - << "DepthRange" << depthRange << "_" << (depthClampEnabled ? "Clamped" : "Clipped") << "_" - << "VertexDepth" << vertexDepth << "_" - << "FragmentDepth" << fragmentDepth << "_" << BufferFormatToString(depthBufferFormat); + out << "__" << depthRange << "_" << (depthClampEnabled ? "Clamped" : "Clipped") << "_" + << vertexDepth << "_" << fragmentDepth << "_" << BufferFormatToString(depthBufferFormat); return out.str(); } diff --git a/src/tests/gl_tests/DrawBaseVertexBaseInstanceTest.cpp b/src/tests/gl_tests/DrawBaseVertexBaseInstanceTest.cpp index a05fe675acc..c12b651c16a 100644 --- a/src/tests/gl_tests/DrawBaseVertexBaseInstanceTest.cpp +++ b/src/tests/gl_tests/DrawBaseVertexBaseInstanceTest.cpp @@ -95,7 +95,7 @@ struct PrintToStringParamName // are checked by using them to select the color of the draw. class DrawBaseVertexBaseInstanceTest : public ANGLETestBase, - public ::testing::TestWithParam + public ::testing::WithParamInterface { protected: DrawBaseVertexBaseInstanceTest() : ANGLETestBase(std::get<0>(GetParam())) @@ -490,7 +490,7 @@ using DrawBaseInstanceTestParams = std:: // gl_VertexID, gl_InstanceID, gl_BaseVertex, and gl_BaseInstance // are checked by using them to select the color of the draw. class DrawBaseInstanceTest : public ANGLETestBase, - public ::testing::TestWithParam + public ::testing::WithParamInterface { protected: DrawBaseInstanceTest() : ANGLETestBase(std::get<0>(GetParam())) @@ -928,6 +928,38 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance) checkDrawResult(false, true); } +// Tests basic drawcount validation +TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawValidation) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_multi_draw")); + + const GLint first = 0; + const GLsizei count = 0; + const GLsizei instanceCount = 0; + const GLint baseVertex = 0; + const GLuint baseInstance = 0; + const GLvoid *const indices[1]{nullptr}; + + glMultiDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, &first, &count, &instanceCount, + &baseInstance, -1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glMultiDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, &first, &count, &instanceCount, + &baseInstance, 0); + EXPECT_GL_NO_ERROR(); + + glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, + indices, &instanceCount, &baseVertex, + &baseInstance, -1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, + indices, &instanceCount, &baseVertex, + &baseInstance, 0); + EXPECT_GL_NO_ERROR(); +} + // Tests basic functionality of glMultiDrawArraysInstancedBaseInstance TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance) { @@ -1181,6 +1213,98 @@ TEST_P(DrawBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance) checkDrawResult(true, true); } +class DrawBaseVertexBaseInstanceTest_ES3 : public ANGLETest<> +{ + public: + DrawBaseVertexBaseInstanceTest_ES3() + { + setWindowWidth(16); + setWindowHeight(16); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +// gl_BaseVertex and gl_BaseInstance are translated to angle_BaseVertex and angle_BaseInstance +// internally. Check that a user-defined angle_BaseVertex or angle_BaseInstance is permitted +TEST_P(DrawBaseVertexBaseInstanceTest_ES3, AllowsUserDefinedANGLEDrawID) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance")); + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance_shader_builtin")); + + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require +in vec2 position; +uniform int angle_BaseVertex; +uniform int angle_BaseInstance; +out vec4 verified; + +void main() +{ + // Expect gl_BaseVertex and gl_BaseInstance to be untouched when angle_BaseVertex and + // angle_BaseInstance are not. + verified = vec4(gl_BaseVertex == 2, gl_BaseInstance == 0, + angle_BaseVertex == 3, angle_BaseInstance == 5); + gl_Position = vec4(position, 0, 1); +})"; + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +in vec4 verified; +out vec4 color; + +void main() +{ + color = verified; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + glUniform1i(glGetUniformLocation(program, "angle_BaseVertex"), 3); + glUniform1i(glGetUniformLocation(program, "angle_BaseInstance"), 5); + + constexpr std::array kVertexData = { + // Vertex 0, unused + 10000, + 10000, + // Vertex 1, unused + 10000, + 10000, + // Vertices 2, 3 and 4 define the triangle because base vertex is 2. + -1, + -1, + 3, + -1, + -1, + 3, + }; + constexpr std::array kIndexData = { + 0, + 1, + 2, + }; + + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData.data(), GL_STATIC_DRAW); + const GLint positionLoc = glGetAttribLocation(program, "position"); + glEnableVertexAttribArray(positionLoc); + glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); + + GLBuffer indexBuffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW); + ASSERT_GL_NO_ERROR(); + + glDrawElementsInstancedBaseVertexBaseInstanceANGLE(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr, + 1, 2, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + ASSERT_GL_NO_ERROR(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexBaseInstanceTest); #define ANGLE_ALL_BASEVERTEXBASEINTANCE_TEST_PLATFORMS_ES3 \ @@ -1207,4 +1331,8 @@ ANGLE_INSTANTIATE_TEST_COMBINE_3( testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw), ANGLE_ALL_BASEVERTEXBASEINTANCE_TEST_PLATFORMS_ES3); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexBaseInstanceTest_ES3); +ANGLE_INSTANTIATE_TEST(DrawBaseVertexBaseInstanceTest_ES3, + ANGLE_ALL_BASEVERTEXBASEINTANCE_TEST_PLATFORMS_ES3); + } // namespace diff --git a/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp b/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp index bc26a26bf3f..504b9ac9996 100644 --- a/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp +++ b/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp @@ -57,10 +57,14 @@ constexpr std::array, 4> GetQuadVertices(uint32_t x, uint enum class DrawCallVariants { - DrawElementsBaseVertex, - DrawElementsInstancedBaseVertex, - DrawRangeElementsBaseVertex, - DrawElementsInstancedBaseVertexBaseInstance + DrawElementsBaseVertexEXT, + DrawElementsBaseVertexOES, + DrawElementsInstancedBaseVertexEXT, + DrawElementsInstancedBaseVertexOES, + DrawRangeElementsBaseVertexEXT, + DrawRangeElementsBaseVertexOES, + DrawElementsInstancedBaseVertexBaseInstanceEXT, + DrawElementsInstancedBaseVertexBaseInstanceANGLE }; using DrawBaseVertexVariantsTestParams = std::tuple; @@ -105,6 +109,7 @@ class DrawBaseVertexVariantsTest : public ANGLETest indices = {0, 1, 2, 0, 2, 3}; mIndices.resize(indices.size() * kIndexPatternRepeatCount); @@ -225,6 +230,101 @@ void main() ASSERT_GL_NO_ERROR(); } + void doDrawElementsBaseVertex(DrawCallVariants drawCallType, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLint basevertex) + { + switch (drawCallType) + { + case DrawCallVariants::DrawElementsBaseVertexEXT: + glDrawElementsBaseVertexEXT(mode, count, type, indices, basevertex); + break; + case DrawCallVariants::DrawElementsBaseVertexOES: + glDrawElementsBaseVertexOES(mode, count, type, indices, basevertex); + break; + default: + UNREACHABLE(); + break; + } + } + + void doDrawElementsInstancedBaseVertex(DrawCallVariants drawCallType, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instancecount, + GLint basevertex) + { + switch (drawCallType) + { + case DrawCallVariants::DrawElementsInstancedBaseVertexEXT: + glDrawElementsInstancedBaseVertexEXT(mode, count, type, indices, instancecount, + basevertex); + break; + case DrawCallVariants::DrawElementsInstancedBaseVertexOES: + glDrawElementsInstancedBaseVertexOES(mode, count, type, indices, instancecount, + basevertex); + break; + default: + UNREACHABLE(); + break; + } + } + + void doDrawRangeElementsBaseVertex(DrawCallVariants drawCallType, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices, + GLint basevertex) + { + switch (drawCallType) + { + case DrawCallVariants::DrawRangeElementsBaseVertexEXT: + glDrawRangeElementsBaseVertexEXT(mode, start, end, count, type, indices, + basevertex); + break; + case DrawCallVariants::DrawRangeElementsBaseVertexOES: + glDrawRangeElementsBaseVertexOES(mode, start, end, count, type, indices, + basevertex); + break; + default: + UNREACHABLE(); + break; + } + } + + void doDrawElementsInstancedBaseVertexBaseInstance(DrawCallVariants drawCallType, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instancecount, + GLint basevertex, + GLuint baseinstance) + { + switch (drawCallType) + { + case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstanceEXT: + glDrawElementsInstancedBaseVertexBaseInstanceEXT( + mode, count, type, indices, instancecount, basevertex, baseinstance); + break; + case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstanceANGLE: + glDrawElementsInstancedBaseVertexBaseInstanceANGLE( + mode, count, type, indices, instancecount, basevertex, baseinstance); + break; + default: + UNREACHABLE(); + break; + } + } + void doDrawElementsBaseVertexVariants(DrawCallVariants drawCallType) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -245,35 +345,38 @@ void main() switch (drawCallType) { - case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstance: - glDrawElementsInstancedBaseVertexBaseInstanceANGLE( - GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT, + case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstanceEXT: + case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstanceANGLE: + doDrawElementsInstancedBaseVertexBaseInstance( + drawCallType, GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT, reinterpret_cast( static_cast(baseRepetition * 6 * sizeof(GLushort))), 1, (i - baseRepetition) * 4, 0); break; - case DrawCallVariants::DrawElementsBaseVertex: - glDrawElementsBaseVertexEXT( - GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT, + case DrawCallVariants::DrawElementsBaseVertexEXT: + case DrawCallVariants::DrawElementsBaseVertexOES: + doDrawElementsBaseVertex( + drawCallType, GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT, reinterpret_cast( static_cast(baseRepetition * 6 * sizeof(GLushort))), (i - baseRepetition) * 4); break; - case DrawCallVariants::DrawElementsInstancedBaseVertex: - glDrawElementsInstancedBaseVertexEXT( - GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT, + case DrawCallVariants::DrawElementsInstancedBaseVertexEXT: + case DrawCallVariants::DrawElementsInstancedBaseVertexOES: + doDrawElementsInstancedBaseVertex( + drawCallType, GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT, reinterpret_cast( static_cast(baseRepetition * 6 * sizeof(GLushort))), 1, (i - baseRepetition) * 4); break; - case DrawCallVariants::DrawRangeElementsBaseVertex: - glDrawRangeElementsBaseVertexEXT( - GL_TRIANGLES, baseRepetition * 4, - (baseRepetition + repetitionCount) * 4 - 1, repetitionCount * 6, - GL_UNSIGNED_SHORT, - reinterpret_cast( - static_cast(baseRepetition * 6 * sizeof(GLushort))), - (i - baseRepetition) * 4); + case DrawCallVariants::DrawRangeElementsBaseVertexEXT: + case DrawCallVariants::DrawRangeElementsBaseVertexOES: + doDrawRangeElementsBaseVertex(drawCallType, GL_TRIANGLES, baseRepetition * 4, + (baseRepetition + repetitionCount) * 4 - 1, + repetitionCount * 6, GL_UNSIGNED_SHORT, + reinterpret_cast(static_cast( + baseRepetition * 6 * sizeof(GLushort))), + (i - baseRepetition) * 4); break; default: EXPECT_TRUE(false); @@ -347,12 +450,6 @@ void main() return EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance_shader_builtin"); } - bool requestNativeBaseVertexExtensions() - { - return (EnsureGLExtensionEnabled("GL_OES_draw_elements_base_vertex") || - EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex")); - } - std::vector mIndices; std::vector mVertices; std::vector mVertexColors; @@ -363,10 +460,86 @@ void main() GLint mColorLoc; }; -// Test drawElementsBaseVertex from OES/EXT_draw_elements_base_vertex -TEST_P(DrawBaseVertexVariantsTest, DrawElementsBaseVertex) +// Test drawElementsBaseVertex from EXT_draw_elements_base_vertex +TEST_P(DrawBaseVertexVariantsTest, DrawElementsBaseVertexEXT) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex")); + + GLProgram program; + setupProgram(program); + + GLBuffer indexBuffer; + GLBuffer vertexPositionBuffer; + GLBuffer vertexColorBuffer; + setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer); + + // for potential update vertex color later + glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); + + doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsBaseVertexEXT); +} + +// Test drawElementsBaseVertex from OES_draw_elements_base_vertex +TEST_P(DrawBaseVertexVariantsTest, DrawElementsBaseVertexOES) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_draw_elements_base_vertex")); + + GLProgram program; + setupProgram(program); + + GLBuffer indexBuffer; + GLBuffer vertexPositionBuffer; + GLBuffer vertexColorBuffer; + setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer); + + // for potential update vertex color later + glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); + + doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsBaseVertexOES); +} + +// Test drawElementsInstancedBaseVertex from EXT_draw_elements_base_vertex +TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexEXT) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex")); + + GLProgram program; + setupProgram(program); + + GLBuffer indexBuffer; + GLBuffer vertexPositionBuffer; + GLBuffer vertexColorBuffer; + setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer); + + // for potential update vertex color later + glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); + + doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertexEXT); +} + +// Test drawElementsInstancedBaseVertex from OES_draw_elements_base_vertex +TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexOES) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_draw_elements_base_vertex")); + + GLProgram program; + setupProgram(program); + + GLBuffer indexBuffer; + GLBuffer vertexPositionBuffer; + GLBuffer vertexColorBuffer; + setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer); + + // for potential update vertex color later + glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); + + doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertexOES); +} + +// Test drawRangeElementsBaseVertex from EXT_draw_elements_base_vertex +TEST_P(DrawBaseVertexVariantsTest, DrawRangeElementsBaseVertexEXT) { - ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions()); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex")); GLProgram program; setupProgram(program); @@ -379,13 +552,13 @@ TEST_P(DrawBaseVertexVariantsTest, DrawElementsBaseVertex) // for potential update vertex color later glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); - doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsBaseVertex); + doDrawElementsBaseVertexVariants(DrawCallVariants::DrawRangeElementsBaseVertexEXT); } -// Test drawElementsInstancedBaseVertex from OES/EXT_draw_elements_base_vertex -TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertex) +// Test drawRangeElementsBaseVertex from OES_draw_elements_base_vertex +TEST_P(DrawBaseVertexVariantsTest, DrawRangeElementsBaseVertexOES) { - ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions()); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_draw_elements_base_vertex")); GLProgram program; setupProgram(program); @@ -398,13 +571,14 @@ TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertex) // for potential update vertex color later glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); - doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertex); + doDrawElementsBaseVertexVariants(DrawCallVariants::DrawRangeElementsBaseVertexOES); } -// Test drawRangeElementsBaseVertex from OES/EXT_draw_elements_base_vertex -TEST_P(DrawBaseVertexVariantsTest, DrawRangeElementsBaseVertex) +// Test drawElementsInstancedBaseVertexBaseInstance from EXT_base_instance +TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexBaseInstanceEXT) { - ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions()); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_base_instance") || + !EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex")); GLProgram program; setupProgram(program); @@ -417,11 +591,12 @@ TEST_P(DrawBaseVertexVariantsTest, DrawRangeElementsBaseVertex) // for potential update vertex color later glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); - doDrawElementsBaseVertexVariants(DrawCallVariants::DrawRangeElementsBaseVertex); + doDrawElementsBaseVertexVariants( + DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstanceEXT); } // Test drawElementsInstancedBaseVertexBaseInstance from ANGLE_base_vertex_base_instance -TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexBaseInstance) +TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexBaseInstanceANGLE) { ANGLE_SKIP_TEST_IF(!requestAngleBaseVertexBaseInstanceExtensions()); @@ -436,17 +611,19 @@ TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexBaseInstance) // for potential update vertex color later glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer); - doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstance); + doDrawElementsBaseVertexVariants( + DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstanceANGLE); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexVariantsTest); -ANGLE_INSTANTIATE_TEST_COMBINE_1(DrawBaseVertexVariantsTest, - DrawBaseVertexVariantsTestPrint, - testing::ValuesIn(kBufferDataUsage), - ES3_D3D11(), - ES3_METAL(), - ES3_OPENGL(), - ES3_OPENGLES(), - ES3_VULKAN()); +ANGLE_INSTANTIATE_TEST_COMBINE_1( + DrawBaseVertexVariantsTest, + DrawBaseVertexVariantsTestPrint, + testing::ValuesIn(kBufferDataUsage), + ES3_D3D11(), + ES3_METAL(), + ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_VULKAN()); } // namespace diff --git a/src/tests/gl_tests/DrawBuffersTest.cpp b/src/tests/gl_tests/DrawBuffersTest.cpp index 33b6de3ab77..e7c61803f00 100644 --- a/src/tests/gl_tests/DrawBuffersTest.cpp +++ b/src/tests/gl_tests/DrawBuffersTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -601,18 +605,47 @@ TEST_P(DrawBuffersTest, FirstHalfNULL) glDeleteProgram(program); } -// Test that non-zero draw buffers can be queried on the default framebuffer +// Test draw buffers query on the default framebuffer TEST_P(DrawBuffersTest, DefaultFramebufferDrawBufferQuery) { ANGLE_SKIP_TEST_IF(!setupTest()); glBindFramebuffer(GL_FRAMEBUFFER, 0); + EGLWindow *window = getEGLWindow(); + EGLDisplay display = window->getDisplay(); + EGLSurface surface = window->getSurface(); GLint drawbuffer = 0; + + if (EGL_NO_SURFACE != surface) + { + // Check that the draw buffer state is GL_BACK + glGetIntegerv(GL_DRAW_BUFFER0, &drawbuffer); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(GL_BACK, drawbuffer); + } + + // Test that non-zero draw buffers can be queried on the default framebuffer glGetIntegerv(GL_DRAW_BUFFER1, &drawbuffer); EXPECT_GL_NO_ERROR(); + EXPECT_EQ(GL_NONE, drawbuffer); + // Make our context current with no surfaces + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, window->getContext()); + // Check that the draw buffer state is GL_NONE + glGetIntegerv(GL_DRAW_BUFFER0, &drawbuffer); + EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_NONE, drawbuffer); + + if (EGL_NO_SURFACE != surface) + { + // Make our context current with a surface again + eglMakeCurrent(display, surface, surface, window->getContext()); + // Test that the draw buffer state is GL_BACK once again + glGetIntegerv(GL_DRAW_BUFFER0, &drawbuffer); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(GL_BACK, drawbuffer); + } } // Test that drawing with all color buffers disabled works. @@ -1298,20 +1331,20 @@ TEST_P(DrawBuffersTestES3, BlendWithDrawBufferAndFramebufferChanges) } ASSERT_GL_NO_ERROR(); - glEnablei(GL_BLEND, 0); - glEnablei(GL_BLEND, 1); - glEnablei(GL_BLEND, 2); - glEnablei(GL_BLEND, 3); + glEnableiOES(GL_BLEND, 0); + glEnableiOES(GL_BLEND, 1); + glEnableiOES(GL_BLEND, 2); + glEnableiOES(GL_BLEND, 3); - glBlendEquationi(0, GL_FUNC_REVERSE_SUBTRACT); - glBlendEquationi(1, GL_MIN); - glBlendEquationi(2, GL_FUNC_REVERSE_SUBTRACT); - glBlendEquationi(3, GL_FUNC_REVERSE_SUBTRACT); + glBlendEquationiOES(0, GL_FUNC_REVERSE_SUBTRACT); + glBlendEquationiOES(1, GL_MIN); + glBlendEquationiOES(2, GL_FUNC_REVERSE_SUBTRACT); + glBlendEquationiOES(3, GL_FUNC_REVERSE_SUBTRACT); - glBlendFunci(0, GL_ONE, GL_ONE); - glBlendFunci(1, GL_DST_ALPHA, GL_DST_ALPHA); - glBlendFunci(2, GL_SRC_ALPHA, GL_SRC_ALPHA); - glBlendFunci(3, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); + glBlendFunciOES(0, GL_ONE, GL_ONE); + glBlendFunciOES(1, GL_DST_ALPHA, GL_DST_ALPHA); + glBlendFunciOES(2, GL_SRC_ALPHA, GL_SRC_ALPHA); + glBlendFunciOES(3, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); bufs[0] = GL_NONE; bufs[2] = GL_NONE; @@ -1752,13 +1785,11 @@ TEST_P(ColorMaskForDrawBuffersTest, StateChangeAffectsBlendState) EXPECT_GL_NO_ERROR(); } -ANGLE_INSTANTIATE_TEST(DrawBuffersTest, - ANGLE_ALL_TEST_PLATFORMS_ES2, - ANGLE_ALL_TEST_PLATFORMS_ES3, - ES2_METAL().enable(Feature::LimitMaxDrawBuffersForTesting), - ES2_VULKAN() - .disable(Feature::SupportsTransformFeedbackExtension) - .disable(Feature::EmulateTransformFeedback)); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(DrawBuffersTest, + ES2_METAL().enable(Feature::LimitMaxDrawBuffersForTesting), + ES2_VULKAN() + .disable(Feature::SupportsTransformFeedbackExtension) + .disable(Feature::EmulateTransformFeedback)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBuffersWebGL2Test); ANGLE_INSTANTIATE_TEST_ES3(DrawBuffersWebGL2Test); diff --git a/src/tests/gl_tests/DrawElementsTest.cpp b/src/tests/gl_tests/DrawElementsTest.cpp index 415c41165be..4595eedf64b 100644 --- a/src/tests/gl_tests/DrawElementsTest.cpp +++ b/src/tests/gl_tests/DrawElementsTest.cpp @@ -7,6 +7,10 @@ // Tests for indexed draws. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -651,6 +655,100 @@ TEST_P(DrawElementsTest, DrawElementsWithDifferentIndexBufferOffsets) ASSERT_GL_NO_ERROR(); } +// Test one element buffer bind to two vertexArrays and switch vertexArray should draw correctly +TEST_P(DrawElementsTest, TwoVertexArraysWithSameElementBuffer) +{ + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + + ANGLE_GL_PROGRAM(programDrawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + glUseProgram(programDrawRed); + GLint posLocation = glGetAttribLocation(programDrawRed, essl3_shaders::PositionAttrib()); + ASSERT_NE(-1, posLocation); + + GLBuffer vertexBuffer; + const std::array &vertices = GetIndexedQuadVertices(); + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(), + GL_STATIC_DRAW); + + GLBuffer elementBuffer; + std::array zeros; + size_t elementBufferSize = sizeof(zeros[0]) * zeros.size(); + zeros.fill(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, zeros.data(), GL_DYNAMIC_DRAW); + + // Set up two vertex arrays using same set of buffers. Since initial element buffer all point to + // the same vertex, it should only draw one point + GLuint vertexArray[2]; + glGenVertexArrays(2, vertexArray); + + glBindVertexArray(vertexArray[0]); + glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(posLocation); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast(0)); + + glBindVertexArray(vertexArray[1]); + glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(posLocation); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast(0)); + + // Use vertexArray[0] and update elementBuffer and draw + const std::array &indices = {0, 1, 2, 0, 2, 3}; + glBindVertexArray(vertexArray[0]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, indices.data(), GL_DYNAMIC_DRAW); + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast(0)); + + // Use vertexArray[1] and and draw + glBindVertexArray(vertexArray[1]); + size_t elementBufferOffset = sizeof(indices[0]) * 3; + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, + reinterpret_cast(elementBufferOffset)); + + // We should see both triangles + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red); + + glDeleteVertexArrays(2, vertexArray); + + ASSERT_GL_NO_ERROR(); +} + +// Test that drawing with index value a little bit less than or equal to GL_MAX_ELEMENT_INDEX +// should not have error +TEST_P(DrawElementsTest, MaxElementIndex) +{ + constexpr GLuint indicesNumber = 10; + std::array indices; + GLint64 maxIndex = 0; + GLBuffer vertexBuffer; + + ANGLE_GL_PROGRAM(programDrawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + glUseProgram(programDrawRed); + GLint posLocation = glGetAttribLocation(programDrawRed, essl3_shaders::PositionAttrib()); + ASSERT_NE(-1, posLocation); + + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + + glEnableVertexAttribArray(posLocation); + glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); + glVertexAttribDivisor(posLocation, 0xFFFFFFFF); + + glGetInteger64v(GL_MAX_ELEMENT_INDEX, &maxIndex); + // Draw using index from maxIndex - 9 to maxIndex. Should have no error + for (GLuint i = 0; i < indicesNumber; ++i) + { + indices[i] = static_cast(maxIndex) - (indicesNumber - 1) + i; + } + + glDrawElements(GL_TRIANGLES, static_cast(indicesNumber), GL_UNSIGNED_INT, + indices.data()); + ASSERT_GL_NO_ERROR(); +} + // Test that the offset in the index buffer is forced to be a multiple of the element size TEST_P(WebGLDrawElementsTest, DrawElementsTypeAlignment) { @@ -695,8 +793,81 @@ TEST_P(WebGLDrawElementsTest, DrawElementsTypeAlignment) EXPECT_GL_ERROR(GL_INVALID_OPERATION); } +class WebGLDrawElementsTest3 : public WebGLDrawElementsTest +{}; +// Test one element buffer bind to two vertexArrays and switch vertexArray should draw correctly. +// With WebGL, we will go through element buffer range validation check which will catch bugs if the +// cached index range is incorrect. +TEST_P(WebGLDrawElementsTest3, TwoVertexArraysWithSameElementBuffer) +{ + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + + ANGLE_GL_PROGRAM(programDrawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + glUseProgram(programDrawRed); + GLint posLocation = glGetAttribLocation(programDrawRed, essl3_shaders::PositionAttrib()); + ASSERT_NE(-1, posLocation); + + GLBuffer vertexBuffer; + const std::array &vertices = GetIndexedQuadVertices(); + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(), + GL_STATIC_DRAW); + + GLBuffer elementBuffer; + std::array invalidIndexData; + size_t elementBufferSize = sizeof(invalidIndexData[0]) * invalidIndexData.size(); + invalidIndexData.fill(0xffffffff); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, invalidIndexData.data(), + GL_DYNAMIC_DRAW); + + // Set up two vertex arrays using same set of buffers. Since initial element buffer all point to + // 0xffffffff, which exceed max index range, it should generate GL_INVALID_OPERATION. + GLuint vertexArray[2]; + glGenVertexArrays(2, vertexArray); + + glBindVertexArray(vertexArray[0]); + glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(posLocation); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, reinterpret_cast(0)); + + glBindVertexArray(vertexArray[1]); + glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(posLocation); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + size_t elementBufferOffset1 = sizeof(invalidIndexData[0]) * 3; + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, + reinterpret_cast(elementBufferOffset1)); + + // This should alsop clear the context error code. + ASSERT_TRUE(glGetError() == GL_INVALID_OPERATION); + + // Use vertexArray[0] and update elementBuffer and draw + const std::array &indices = {0, 1, 2, 0, 2, 3}; + glBindVertexArray(vertexArray[0]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, indices.data(), GL_DYNAMIC_DRAW); + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, reinterpret_cast(0)); + + // Use vertexArray[1] and and draw + glBindVertexArray(vertexArray[1]); + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, + reinterpret_cast(elementBufferOffset1)); + ASSERT_TRUE(glGetError() == GL_NO_ERROR); + + // We should see both triangles + EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red); + + glDeleteVertexArrays(2, vertexArray); + + ASSERT_GL_NO_ERROR(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawElementsTest); ANGLE_INSTANTIATE_TEST_ES3(DrawElementsTest); ANGLE_INSTANTIATE_TEST_ES2(WebGLDrawElementsTest); +ANGLE_INSTANTIATE_TEST_ES3(WebGLDrawElementsTest3); } // namespace diff --git a/src/tests/gl_tests/DrawRangeElementsTest.cpp b/src/tests/gl_tests/DrawRangeElementsTest.cpp index e3a37cebccc..6da58349887 100644 --- a/src/tests/gl_tests/DrawRangeElementsTest.cpp +++ b/src/tests/gl_tests/DrawRangeElementsTest.cpp @@ -18,7 +18,6 @@ namespace enum class DrawCallVariants { DrawRangeElements, - DrawRangeElementsBaseVertex, DrawRangeElementsBaseVertexEXT, DrawRangeElementsBaseVertexOES, }; @@ -43,10 +42,6 @@ class DrawRangeElementsTest : public ANGLETest<> case DrawCallVariants::DrawRangeElements: glDrawRangeElements(GL_TRIANGLES, 0, 1000, count, GL_UNSIGNED_BYTE, nullptr); break; - case DrawCallVariants::DrawRangeElementsBaseVertex: - glDrawRangeElementsBaseVertex(GL_TRIANGLES, 0, 1000, count, GL_UNSIGNED_BYTE, - nullptr, baseVertex); - break; case DrawCallVariants::DrawRangeElementsBaseVertexEXT: glDrawRangeElementsBaseVertexEXT(GL_TRIANGLES, 0, 1000, count, GL_UNSIGNED_BYTE, nullptr, baseVertex); @@ -107,19 +102,9 @@ class WebGLDrawRangeElementsTest : public DrawRangeElementsTest // equals 0. TEST_P(WebGLDrawRangeElementsTest, DrawRangeElementArrayZeroCount) { - ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); - doDrawRangeElementsVariant(DrawCallVariants::DrawRangeElements); } -// Test that glDrawRangeElementsBaseVertex generates an error when trying to -// draw from an empty element array buffer with count other than 0 and no error -// when count equals 0. -TEST_P(WebGLDrawRangeElementsTest, DrawRangeElementBaseVertexArrayZeroCount) -{ - doDrawRangeElementsVariant(DrawCallVariants::DrawRangeElementsBaseVertex); -} - // Test that glDrawRangeElementsBaseVertexEXT generates an error when trying to // draw from an empty element array buffer with count other than 0 and no error // when count equals 0. @@ -141,6 +126,6 @@ TEST_P(WebGLDrawRangeElementsTest, DrawRangeElementBaseVertexOESArrayZeroCount) } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawRangeElementsTest); -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WebGLDrawRangeElementsTest); +ANGLE_INSTANTIATE_TEST_ES3(WebGLDrawRangeElementsTest); } // namespace diff --git a/src/tests/gl_tests/EGLImageMECFriendlyTest.cpp b/src/tests/gl_tests/EGLImageMECFriendlyTest.cpp index ea5b59166c6..5c8ef359fe9 100644 --- a/src/tests/gl_tests/EGLImageMECFriendlyTest.cpp +++ b/src/tests/gl_tests/EGLImageMECFriendlyTest.cpp @@ -8,6 +8,10 @@ // MEC will have to capture everything, and we can test with capture/replay // whether this is done correctly. In this case the focus is on external images +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" @@ -50,7 +54,6 @@ class EGLImageMECFriendlyTest : public ANGLETest<> data[(y * texSize + x) * 4 + 0] = 0; data[(y * texSize + x) * 4 + 1] = static_cast(green * 255); data[(y * texSize + x) * 4 + 2] = static_cast(blue * 255); - ; data[(y * texSize + x) * 4 + 3] = 255; } } diff --git a/src/tests/gl_tests/ETCTextureTest.cpp b/src/tests/gl_tests/ETCTextureTest.cpp index 821668533b4..319eb1c9ffe 100644 --- a/src/tests/gl_tests/ETCTextureTest.cpp +++ b/src/tests/gl_tests/ETCTextureTest.cpp @@ -7,6 +7,10 @@ // Tests for ETC lossy decode formats. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "media/etc2bc_srgb8_alpha8.inc" diff --git a/src/tests/gl_tests/ErrorMessages.cpp b/src/tests/gl_tests/ErrorMessages.cpp index 4def7feb631..ca6c8e85431 100644 --- a/src/tests/gl_tests/ErrorMessages.cpp +++ b/src/tests/gl_tests/ErrorMessages.cpp @@ -85,7 +85,8 @@ TEST_P(ErrorMessagesTest, ErrorMessages) constexpr GLenum type = GL_DEBUG_TYPE_ERROR; constexpr GLenum severity = GL_DEBUG_SEVERITY_HIGH; constexpr GLuint id1 = 1282; - const std::string message1 = gl::err::kWebglBindAttribLocationReservedPrefix; + const std::string message1 = + std::string("glBindAttribLocation: ") + gl::err::kNameStartsWithReservedPrefix; Message expectedMessage; GLint numMessages = 0; @@ -106,16 +107,5 @@ TEST_P(ErrorMessagesTest, ErrorMessages) ASSERT_TRUE(m == expectedMessage); } -// Use this to select which configurations (e.g. which renderer, which GLES major version) these -// tests should be run against. -ANGLE_INSTANTIATE_TEST(ErrorMessagesTest, - ES2_D3D9(), - ES2_D3D11(), - ES3_D3D11(), - ES2_METAL(), - ES2_OPENGL(), - ES3_OPENGL(), - ES2_OPENGLES(), - ES3_OPENGLES(), - ES2_VULKAN()); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ErrorMessagesTest); } // namespace angle diff --git a/src/tests/gl_tests/ExternalBufferTest.cpp b/src/tests/gl_tests/ExternalBufferTest.cpp index 254b8a592fa..37ee5d18cd0 100644 --- a/src/tests/gl_tests/ExternalBufferTest.cpp +++ b/src/tests/gl_tests/ExternalBufferTest.cpp @@ -7,6 +7,10 @@ // Tests the correctness of external buffer ext extension. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" @@ -134,6 +138,7 @@ TEST_P(ExternalBufferTestES31, BufferSubData) unlockAndroidHardwareBuffer(aHardwareBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + buffer.reset(); // Delete the source AHB destroyAndroidHardwareBuffer(aHardwareBuffer); } @@ -187,6 +192,8 @@ TEST_P(ExternalBufferTestES31, SubDataDoesNotCauseOrphaning) glBindBuffer(GL_COPY_READ_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + copyReadBuffer.reset(); + externalBuffer.reset(); // Delete the source AHB destroyAndroidHardwareBuffer(aHardwareBuffer); } @@ -244,6 +251,7 @@ TEST_P(ExternalBufferTestES31, DispatchCompute) unlockAndroidHardwareBuffer(aHardwareBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + buffer.reset(); // Delete the source AHB destroyAndroidHardwareBuffer(aHardwareBuffer); } @@ -282,6 +290,7 @@ TEST_P(ExternalBufferTestES31, MapBuffer) glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + buffer.reset(); // Delete the source AHB destroyAndroidHardwareBuffer(aHardwareBuffer); } @@ -344,6 +353,8 @@ TEST_P(ExternalBufferTestES31, MapBufferDoesNotCauseOrphaning) glBindBuffer(GL_COPY_READ_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + copyReadBuffer.reset(); + buffer.reset(); // Delete the source AHB destroyAndroidHardwareBuffer(aHardwareBuffer); } @@ -368,11 +379,62 @@ TEST_P(ExternalBufferTestES31, BufferDoesNotLeakAHB) glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags); ASSERT_GL_NO_ERROR(); + buffer.reset(); // Delete the source AHB destroyAndroidHardwareBuffer(aHardwareBuffer); } } +// Test that checks buffer object state after calling glBufferStorageExternalEXT +TEST_P(ExternalBufferTestES31, getBufferParameter) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") || + !IsGLExtensionEnabled("GL_EXT_buffer_storage")); + + GLint64 value = -1; + + constexpr uint8_t kBufferSize = 3; + std::vector initData(kBufferSize, 0xA); + + // Create the Image + AHardwareBuffer *aHardwareBuffer; + constexpr GLbitfield kFlags = GL_MAP_WRITE_BIT; + aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data()); + + GLBuffer buffer; + glBindBuffer(GL_COPY_READ_BUFFER, buffer); + glBufferStorageExternalEXT(GL_COPY_READ_BUFFER, 0, kBufferSize, + eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags); + ASSERT_GL_NO_ERROR(); + + /* Check the value of GL_BUFFER_SIZE. */ + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_SIZE, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(kBufferSize, static_cast(value)); + + /* Check the value of GL_BUFFER_USAGE. */ + value = -1; + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_USAGE, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(GL_DYNAMIC_DRAW, value); + + /* Check the value of GL_BUFFER_IMMUTABLE_STORAGE_EXT. */ + value = -1; + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE_EXT, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(GL_TRUE, value); + + /* Check the value of GL_BUFFER_STORAGE_FLAGS_EXT. */ + value = -1; + glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_STORAGE_FLAGS_EXT, &value); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(kFlags, value); + + /* Clean up. */ + glUnmapBuffer(GL_COPY_READ_BUFFER); + glBindBuffer(GL_COPY_READ_BUFFER, 0); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ExternalBufferTestES31); ANGLE_INSTANTIATE_TEST_ES31(ExternalBufferTestES31); } // namespace angle diff --git a/src/tests/gl_tests/ExternalWrapTest.cpp b/src/tests/gl_tests/ExternalWrapTest.cpp index 249b219cd81..df78b412cc9 100644 --- a/src/tests/gl_tests/ExternalWrapTest.cpp +++ b/src/tests/gl_tests/ExternalWrapTest.cpp @@ -7,6 +7,10 @@ // Tests EXT_EGL_image_external_wrap_modes // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" @@ -75,7 +79,6 @@ void main() data[(y * texSize + x) * 4 + 0] = static_cast(red * 255); data[(y * texSize + x) * 4 + 1] = static_cast(green * 255); - data[(y * texSize + x) * 4 + 2] = 0; data[(y * texSize + x) * 4 + 3] = 255; } diff --git a/src/tests/gl_tests/FragDepthTest.cpp b/src/tests/gl_tests/FragDepthTest.cpp index 9ef71612664..e4fa7a3424b 100644 --- a/src/tests/gl_tests/FragDepthTest.cpp +++ b/src/tests/gl_tests/FragDepthTest.cpp @@ -214,6 +214,8 @@ void main() { })"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); } // Test gl_FragDepth redeclaration with depth_any layout qualifier @@ -231,6 +233,8 @@ void main() { })"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); } // Test gl_FragDepth redeclaration with depth_greater layout qualifier @@ -248,6 +252,8 @@ void main() { })"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); } // Test gl_FragDepth redeclaration with depth_less layout qualifier @@ -265,6 +271,8 @@ void main() { })"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); } // Test gl_FragDepth redeclaration with depth_unchanged layout qualifier @@ -282,6 +290,84 @@ void main() { })"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); +} + +// Test gl_FragDepth redeclaration with depth_any layout qualifier and gl_FragCoord +TEST_P(FragDepthRedeclarationTest, AnyWithFragCoord) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth")); + + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: require +out highp vec4 color; +layout (depth_any) out highp float gl_FragDepth; +void main() { + color = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragDepth = cos(gl_FragCoord.z); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); +} + +// Test gl_FragDepth redeclaration with depth_greater layout qualifier and gl_FragCoord +TEST_P(FragDepthRedeclarationTest, GreaterWithFragCoord) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth")); + + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: require +out highp vec4 color; +layout (depth_greater) out highp float gl_FragDepth; +void main() { + color = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragDepth = gl_FragCoord.z + 0.5; +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); +} + +// Test gl_FragDepth redeclaration with depth_less layout qualifier and gl_FragCoord +TEST_P(FragDepthRedeclarationTest, LessWithFragCoord) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth")); + + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: require +out highp vec4 color; +layout (depth_less) out highp float gl_FragDepth; +void main() { + color = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragDepth = gl_FragCoord.z - 0.5; +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); +} + +// Test gl_FragDepth redeclaration with depth_unchanged layout qualifier and gl_FragCoord +TEST_P(FragDepthRedeclarationTest, UnchangedWithFragCoord) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth")); + + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: require +out highp vec4 color; +layout (depth_unchanged) out highp float gl_FragDepth; +void main() { + color = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragDepth = gl_FragCoord.z; +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_GL_NO_ERROR(); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FragDepthTest); diff --git a/src/tests/gl_tests/FramebufferFetchTest.cpp b/src/tests/gl_tests/FramebufferFetchTest.cpp index 1136ea3fc6b..cebe27a5fc9 100644 --- a/src/tests/gl_tests/FramebufferFetchTest.cpp +++ b/src/tests/gl_tests/FramebufferFetchTest.cpp @@ -8,6 +8,10 @@ // EXT_shader_framebuffer_fetch_non_coherent extensions. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/debug.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -6617,6 +6621,86 @@ void main (void) EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); } +// Test that declaring inout variables but only ever writing to them works, using a format with +// fewer than 4 channels. +TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableVec2) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kVS[] = R"(#version 310 es +in highp vec4 position; +void main (void) +{ + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require + +layout(location = 0) inout highp vec2 color; + +void main (void) +{ + color = vec2(1, 0); +})"; + + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG8, getWindowWidth(), getWindowHeight()); + + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + ASSERT_GL_NO_ERROR(); + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glClearColor(0, 1, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 0); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); +} + +// Test that declaring inout variables but only ever writing to them works, using a format with +// a single channel. +TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableFloat) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kVS[] = R"(#version 310 es +in highp vec4 position; +void main (void) +{ + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require + +layout(location = 0) inout highp float color; + +void main (void) +{ + color = 1.; +})"; + + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, getWindowWidth(), getWindowHeight()); + + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + ASSERT_GL_NO_ERROR(); + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 0); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); +} + // Test that declaring inout variables but only ever writing to them works. This test writes to // different channels of the variable separately. TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableSplit) @@ -6703,7 +6787,47 @@ void main (void) { if (gl_FragCoord.x < 8.) { - color.yz = vec2(1, 0); + color.yzw = vec3(1, 0, 1); + } + color.x = 1.; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glClearColor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 0); + EXPECT_PIXEL_RECT_EQ(0, 0, 8, getWindowHeight(), GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(8, 0, getWindowWidth() - 8, getWindowHeight(), GLColor::magenta); +} + +// Verify that conditional writes to an |inout| variable don't make ANGLE consider it as an |out| +// variable. The write is done in a function and the condition is at call site. +TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableConditionalFunctionCall) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kVS[] = R"(#version 310 es +in highp vec4 position; +void main (void) +{ + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require + +layout(location = 0) inout highp vec4 color; + +void f() +{ + color = vec4(0, 1, 0, 1); +} + +void main (void) +{ + if (gl_FragCoord.x < 8.) + { + f(); } color.x = 1.; })"; @@ -6791,6 +6915,115 @@ void main (void) EXPECT_PIXEL_RECT_EQ(8, 0, getWindowWidth() - 8, getWindowHeight(), GLColor::magenta); } +// Verify that passing an |inout| variable to an |in| parameter stops ANGLE from considering it as +// an |out| variable. +TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableInArgument) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kVS[] = R"(#version 310 es +in highp vec4 position; +void main (void) +{ + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require + +layout(location = 0) inout highp vec4 color; + +void f(highp vec4 c) +{ + c += vec4(0.1); +} + +void main (void) +{ + f(color); + color.x = 1.; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glClearColor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 0); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::magenta); +} + +// Verify that passing an |inout| variable to an |inout| parameter stops ANGLE from considering it +// as an |out| variable. +TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableInOutArgument) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kVS[] = R"(#version 310 es +in highp vec4 position; +void main (void) +{ + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require + +layout(location = 0) inout highp vec4 color; + +void f(inout highp vec4 c) +{ + highp vec4 readFromC = c + vec4(0.1); + readFromC += vec4(0.2); + c.w = 1.; +} + +void main (void) +{ + f(color); + color.x = 1.; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glClearColor(0, 0, 1, 0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 0); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::magenta); +} + +// Test that declaring |inout| variables but only ever writing to them in a function |out| parameter +// works. +TEST_P(FramebufferFetchES31, WriteOnlyInOutVariableOutArgument) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kVS[] = R"(#version 310 es +in highp vec4 position; +void main (void) +{ + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require + +layout(location = 0) inout highp vec4 color; + +void f(out highp vec4 c) +{ + c = vec4(0, 1, 0, 1); +} + +void main (void) +{ + f(color); +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glClearColor(0, 0, 1, 0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 0); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferFetchES31); ANGLE_INSTANTIATE_TEST_ES31_AND(FramebufferFetchES31, ES31_VULKAN().disable(Feature::SupportsSPIRV14)); diff --git a/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp b/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp index 2359ff8f4a6..88dfd0e676e 100644 --- a/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp +++ b/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp @@ -3,11 +3,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// CHROMIUMFramebufferMixedSamplesTest +// FramebufferMixedSamplesTest: // Test CHROMIUM subset of NV_framebuffer_mixed_samples. // This extension allows rendering to a framebuffer that has different // sample counts for different render buffers (stencil, depth, color) +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" using namespace angle; diff --git a/src/tests/gl_tests/FramebufferMultiviewTest.cpp b/src/tests/gl_tests/FramebufferMultiviewTest.cpp index 3bc42741c2f..c19e55bf570 100644 --- a/src/tests/gl_tests/FramebufferMultiviewTest.cpp +++ b/src/tests/gl_tests/FramebufferMultiviewTest.cpp @@ -193,6 +193,8 @@ TEST_P(FramebufferMultiviewTest, DefaultState) // the OVR_multiview2 tokens results in an INVALID_ENUM error. TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries) { + ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_OVR_multiview2")); + GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -449,7 +451,7 @@ TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered) glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 3, 2); ASSERT_GL_NO_ERROR(); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, glCheckFramebufferStatus(GL_FRAMEBUFFER)); // Test that framebuffer is complete when the number of views, base view index and layouts are @@ -751,8 +753,14 @@ TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest) ANGLE_SKIP_TEST_IF(!requestMultiviewExtension()); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array")); + // GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES is valid for glFramebufferTextureMultiviewOVR when + // GL_ANGLE_multiview_multisample is enabled. + // The ANGLE_multiview_multisample extension depends on both OVR_multiview and + // OES_texture_storage_multisample_2d_array. Its only function is allowing multisample 2D array + // textures to be used with multiview framebuffers. + ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_ANGLE_multiview_multisample")); - // We don't enable OVR_multiview2_multisample + // We don't enable ANGLE_multiview2_multisample GLTexture multisampleTexture; glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, multisampleTexture); @@ -762,7 +770,8 @@ TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest) glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, multisampleTexture, 0, 0, 2); // From the extension spec: "An INVALID_OPERATION error is generated if texture is not zero, and - // does not name an existing texture object of type TEXTURE_2D_ARRAY." + // does not name an existing texture object of type TEXTURE_2D_ARRAY or + // TEXTURE_2D_MULTISAMPLE_ARRAY_OES" EXPECT_GL_ERROR(GL_INVALID_OPERATION); } diff --git a/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp b/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp index 3a32cc21fd9..b087af2a5a7 100644 --- a/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp +++ b/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" using namespace angle; diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp index 27c77d8b1c7..020a0416881 100644 --- a/src/tests/gl_tests/FramebufferTest.cpp +++ b/src/tests/gl_tests/FramebufferTest.cpp @@ -3,13 +3,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Framebuffer tests: +// FramebufferTest.cpp: // Various tests related for Frambuffers. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/mathutil.h" #include "platform/autogen/FeaturesD3D_autogen.h" #include "test_utils/ANGLETest.h" +#include "test_utils/angle_test_configs.h" #include "test_utils/gl_raii.h" #include "util/OSWindow.h" @@ -214,7 +219,8 @@ TEST_P(FramebufferFormatsTest, RGB8) testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0); } -TEST_P(FramebufferFormatsTest, BGRA8) +// Test that BGRA8_EXT can be used as a framebuffer texture format +TEST_P(FramebufferFormatsTest, BGRA8_EXT) { ANGLE_SKIP_TEST_IF( !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") || @@ -223,6 +229,16 @@ TEST_P(FramebufferFormatsTest, BGRA8) testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8); } +// Test that BGRA_EXT can be used as a framebuffer texture format +TEST_P(FramebufferFormatsTest, BGRA_EXT) +{ + ANGLE_SKIP_TEST_IF( + !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") || + (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage"))); + + testTextureFormat(GL_BGRA_EXT, 8, 8, 8, 8); +} + TEST_P(FramebufferFormatsTest, RGBA8) { ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && @@ -232,6 +248,54 @@ TEST_P(FramebufferFormatsTest, RGBA8) testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8); } +// Test whether glRenderbufferStorage supports GL_BGRA_EXT. +TEST_P(FramebufferFormatsTest, Renderbuffer_BGRA_EXT) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888")); + + glGenRenderbuffers(1, &mRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); + EXPECT_GL_NO_ERROR(); + + glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA_EXT, 128, 128); + EXPECT_GL_NO_ERROR(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer); + EXPECT_GL_NO_ERROR(); + + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test whether glRenderbufferStorage supports GL_BGRA8_EXT. +TEST_P(FramebufferFormatsTest, Renderbuffer_BGRA8_EXT) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888")); + + glGenRenderbuffers(1, &mRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); + EXPECT_GL_NO_ERROR(); + + glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, 128, 128); + EXPECT_GL_NO_ERROR(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer); + EXPECT_GL_NO_ERROR(); + + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16) { testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16); @@ -1123,6 +1187,39 @@ TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glClearColor(0, 0, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); +} + +using FramebufferTest_ES3_WebGPU = FramebufferTest_ES3; + +// Tests reading from nonzero mip levels of a mipmap-complete texture. +TEST_P(FramebufferTest_ES3_WebGPU, TextureAttachmentMipLevelsReadBackComplete) +{ + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + + const std::array mip0Data = { + GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, + GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, + GLColor::red, GLColor::red, GLColor::red, GLColor::red}; + const std::array mip1Data = {GLColor::green, GLColor::green, GLColor::green, + GLColor::green}; + const std::array mip2Data = {GLColor::blue}; + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data()); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip2Data.data()); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); glClearColor(0, 0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); @@ -1698,6 +1795,244 @@ TEST_P(FramebufferTest_ES3, RenderSharedExponent) EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed); } +// Test that glBlitFramebuffer within same renderbuffer is illegal. +TEST_P(FramebufferTest_ES3, BlitWithinRenderBuffer) +{ + ANGLE_SKIP_TEST_IF(!IsVulkan()); + GLRenderbuffer color; + glBindRenderbuffer(GL_RENDERBUFFER, color); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1); + ASSERT_GL_NO_ERROR(); + + GLRenderbuffer ds; + glBindRenderbuffer(GL_RENDERBUFFER, ds); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1); + + GLFramebuffer readFbo; + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + ds); + ASSERT_GL_NO_ERROR(); + + GLFramebuffer drawFbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + ds); + ASSERT_GL_NO_ERROR(); + + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_STENCIL_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Test that glBlitFramebuffer within same 2D texture is illegal, while it's legal for different +// levels. +TEST_P(FramebufferTest_ES3, BlitWithin2DTexture) +{ + ANGLE_SKIP_TEST_IF(!IsVulkan()); + GLFramebuffer readFbo, drawFbo; + GLTexture texColor, texDepthStencil; + glBindTexture(GL_TEXTURE_2D, texColor); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texDepthStencil); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 4, 4, 0, GL_DEPTH_STENCIL, + GL_UNSIGNED_INT_24_8, nullptr); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, + texDepthStencil, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, + texDepthStencil, 0); + + ASSERT_GL_NO_ERROR(); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_STENCIL_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + glBindFramebuffer(GL_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 2); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glUseProgram(blueProgram); + drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + + // Depth/stencil format cannot be used to generate mipmap, so skip depth/stencil blit. + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 2); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 1); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + ASSERT_GL_NO_ERROR(); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + // blit with stretch + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue); + ASSERT_GL_NO_ERROR(); +} + +// Test that glBlitFramebuffer within same 3D texture is illegal, while it's legal for different +// layers. +TEST_P(FramebufferTest_ES3, BlitWithinLayeredTexture) +{ + ANGLE_SKIP_TEST_IF(!IsVulkan()); + GLFramebuffer readFbo, drawFbo; + GLTexture texColor, texDepthStencil; + glBindTexture(GL_TEXTURE_3D, texColor); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D_ARRAY, texDepthStencil); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, 4, 4, 3, 0, GL_DEPTH_STENCIL, + GL_UNSIGNED_INT_24_8, nullptr); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texColor, 0, 1); + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texDepthStencil, 0, + 1); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texColor, 0, 1); + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texDepthStencil, 0, + 1); + ASSERT_GL_NO_ERROR(); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_STENCIL_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + glBindFramebuffer(GL_FRAMEBUFFER, drawFbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texColor, 0, 1); + glUseProgram(blueProgram); + drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texColor, 0, 1); + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texDepthStencil, 0, + 1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texColor, 0, 2); + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texDepthStencil, 0, + 2); + ASSERT_GL_NO_ERROR(); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, + GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + // blit with stretch + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 2, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, + GL_NEAREST); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue); +} + +// Test that glBlitFramebuffer within same cubemap texture is illegal, while it's legal for +// different faces. +TEST_P(FramebufferTest_ES3, BlitWithinCubeMapTexture) +{ + ANGLE_SKIP_TEST_IF(!IsVulkan()); + GLTexture texColor, texDepthStencil; + GLFramebuffer readFbo, drawFbo; + glBindTexture(GL_TEXTURE_CUBE_MAP, texColor); + for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++) + { + glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 4, 4, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + } + glBindTexture(GL_TEXTURE_CUBE_MAP, texDepthStencil); + for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++) + { + glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_DEPTH24_STENCIL8, 4, 4, 0, + GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, texColor, 0); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, texDepthStencil, 0); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, texColor, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, texDepthStencil, 0); + ASSERT_GL_NO_ERROR(); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_STENCIL_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + glBindFramebuffer(GL_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, + texColor, 0); + glUseProgram(blueProgram); + drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, texColor, 0); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, texDepthStencil, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texColor, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texDepthStencil, 0); + ASSERT_GL_NO_ERROR(); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, + GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); + // blit with stretch + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 2, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, + GL_NEAREST); + ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo); + EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue); +} + // Test color write masks with GL_RGB9_E5 color buffers. TEST_P(FramebufferTest_ES3, RenderSharedExponentWithMask) { @@ -4435,14 +4770,14 @@ void main() // 2. change the no-attachment framebuffer size to 2*2, draw // works properly GLFramebuffer framebufferWithVariousSizeGrow; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeGrow); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferWithVariousSizeGrow); for (int loop = 0; loop < 2; loop++) { GLuint defaultWidth = 1 << loop; GLuint defaultHeight = 1 << loop; - glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth); - glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); + glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth); + glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); // Draw and check the FBO size validateSamplePass(query, defaultWidth, defaultHeight); @@ -4455,14 +4790,14 @@ void main() // 2. change the no-attachment framebuffer size to 1*1, draw // works properly GLFramebuffer framebufferWithVariousSizeShrink; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeShrink); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferWithVariousSizeShrink); for (int loop = 1; loop >= 0; loop--) { GLuint defaultWidth = 1 << loop; GLuint defaultHeight = 1 << loop; - glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth); - glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); + glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth); + glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); // Draw and check the FBO size validateSamplePass(query, defaultWidth, defaultHeight); @@ -4837,6 +5172,8 @@ void main() // KHR-GLES32.core.draw_buffers_indexed.color_masks TEST_P(FramebufferTest_ES31, ClearWithColorMasksRGB5A1) { + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); + constexpr int kSize = 4; GLint maxDrawBuffers = 0; glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); @@ -4883,22 +5220,22 @@ TEST_P(FramebufferTest_ES31, ClearWithColorMasksRGB5A1) { if (i % 4 == 0) { - glColorMaski(i, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); + glColorMaskiOES(i, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); } if (i % 4 == 1) { - glColorMaski(i, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + glColorMaskiOES(i, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); } if (i % 4 == 2) { - glColorMaski(i, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + glColorMaskiOES(i, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); } if (i % 4 == 3) { - glColorMaski(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + glColorMaskiOES(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); } } @@ -4967,7 +5304,7 @@ TEST_P(FramebufferTest_ES31, ClearWithColorMasksRGB5A1) // Set the framebuffer color mask back to default values for (int i = 0; i < maxDrawBuffers; ++i) { - glColorMaski(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glColorMaskiOES(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } ASSERT_GL_NO_ERROR(); @@ -8571,6 +8908,9 @@ ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3, ES3_VULKAN().enable(Feature::EmulatedPrerotation180), ES3_VULKAN().enable(Feature::EmulatedPrerotation270)); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3_WebGPU); +ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3_WebGPU, ES3_WEBGPU()); + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3Metal); ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3Metal, ES3_METAL().enable(Feature::LimitMaxColorTargetBitsForTesting)); diff --git a/src/tests/gl_tests/GLSLConstantFoldingTest.cpp b/src/tests/gl_tests/GLSLConstantFoldingTest.cpp new file mode 100644 index 00000000000..c78a0d3cd45 --- /dev/null +++ b/src/tests/gl_tests/GLSLConstantFoldingTest.cpp @@ -0,0 +1,1349 @@ +// +// Copyright 2025 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. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "test_utils/CompilerTest.h" + +#include "test_utils/angle_test_configs.h" +#include "test_utils/gl_raii.h" + +using namespace angle; + +namespace +{ +class GLSLConstantFoldingTest : public CompilerTest +{ + protected: + GLSLConstantFoldingTest() {} + + virtual const char *version() { return "300"; } + + // Helper to verify constant folding result. It's given: + // + // * The type of the constant: a varying `v` will be created of this type. + // * The expression to define and set `c` of that type: The varying is assigned the value of `c` + // in the vertex shader. + // * An expression involving `v` that compares it with the expectation in the fragment shader, + // resulting in a bool. + void test(const char *type, const char *defineC, const char *compareWithV) + { + std::stringstream vsSrc; + vsSrc << "#version " << version() << R"( es +precision highp float; +precision highp int; +flat out )" << type + << R"( v; +void main() +{ + )" << defineC + << R"(; + v = c; + + vec2 pos = vec2(0.); + switch (gl_VertexID) { + // The tests often include 1 and 3, reduce the chance of checking for those values hitting + // the values for position by using 1.1 and 3.1 instead of 1.0 and 3.0. + case 0: pos = vec2(-1.5, -1.5); break; + case 1: pos = vec2(3.5, -1.5); break; + case 2: pos = vec2(-1.5, 3.5); break; + }; + gl_Position = vec4(pos, 0.1, 1.1); +})"; + + std::stringstream fsSrc; + fsSrc << "#version " << version() << R"( es +precision highp float; +precision highp int; +flat in )" << type + << R"( v; +out vec4 color; +void main() +{ + if ()" << compareWithV + << R"() + { + color = vec4(0, 1, 0, 1); + } + else + { + color = vec4(1, 0, 0, 1); + } +})"; + + const CompiledShader &vs = compile(GL_VERTEX_SHADER, vsSrc.str().c_str()); + const CompiledShader &fs = compile(GL_FRAGMENT_SHADER, fsSrc.str().c_str()); + ASSERT_TRUE(vs.success()); + ASSERT_TRUE(fs.success()); + + const GLuint program = link(); + glUseProgram(program); + glDrawArrays(GL_TRIANGLES, 0, 3); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + } + + // Check that the expected constant (the result of folding) is present in the translated source + // for the vertex shader (where constant folding is expected to have happened). + // + // Given the various backends and formatting details of the generators, we can't realistically + // completely verify the translated output. Often, it's enough to verify that a substring only + // found if the constant folding is performed is present; the correctness check in test() makes + // sure constant folding is functionally correct. + // + // Additionally, due to the numerous shader massaging in non-GLSL backends, it's easy for + // expectations to mismatch. Therefore, these expectations are only checked with the GLSL + // backend. + void verifyIsInTranslation(const char *expect) + { + if (IsOpenGL()) + { + EXPECT_TRUE(getCompiledShader(GL_VERTEX_SHADER).verifyInTranslatedSource(expect)) + << '"' << expect << "\" should have been in:\n" + << getCompiledShader(GL_VERTEX_SHADER).getTranslatedSource(); + } + } + void verifyIsNotInTranslation(const char *expect) + { + if (IsOpenGL()) + { + EXPECT_TRUE(getCompiledShader(GL_VERTEX_SHADER).verifyNotInTranslatedSource(expect)) + << '"' << expect << "\" should not have been in:\n" + << getCompiledShader(GL_VERTEX_SHADER).getTranslatedSource(); + } + } +}; + +class GLSLConstantFoldingTest_ES31 : public GLSLConstantFoldingTest +{ + public: + const char *version() override { return "310"; } +}; + +// Constant fold integer addition +TEST_P(GLSLConstantFoldingTest, IntegerAdd) +{ + test("int", "const int c = 1124 + 5", "v == 1129"); + verifyIsInTranslation(" 1129"); + verifyIsNotInTranslation("1124"); +} + +// Constant fold integer subtraction +TEST_P(GLSLConstantFoldingTest, IntegerSub) +{ + test("int", "const int c = 1124 - 5", "v == 1119"); + verifyIsInTranslation(" 1119"); + verifyIsNotInTranslation("1124"); +} + +// Constant fold integer multiplication +TEST_P(GLSLConstantFoldingTest, IntegerMul) +{ + test("int", "const int c = 1124 * 5", "v == 5620"); + verifyIsInTranslation(" 5620"); + verifyIsNotInTranslation("1124"); +} + +// Constant fold integer division +TEST_P(GLSLConstantFoldingTest, IntegerDiv) +{ + // Rounding mode of division is undefined in the spec but ANGLE can be expected to round down. + test("int", "const int c = 1124 / 5", "v == 224"); + verifyIsInTranslation(" 224"); + verifyIsNotInTranslation("1124"); +} + +// Constant fold integer modulus +TEST_P(GLSLConstantFoldingTest, IntegerMod) +{ + test("int", "const int c = 1124 % 5", "v == 4"); + verifyIsInTranslation(" 4"); + verifyIsNotInTranslation("1124"); +} + +// Constant fold cross() +TEST_P(GLSLConstantFoldingTest, Cross) +{ + test("vec3", "const vec3 c = cross(vec3(1., 1., 1.), vec3(1., -1., 1.))", + "all(equal(v, vec3(2., 0., -2.)))"); + verifyIsInTranslation("-2.0"); + verifyIsNotInTranslation("cross"); + verifyIsNotInTranslation("-1.0"); +} + +// Constant fold inverse() +TEST_P(GLSLConstantFoldingTest, Inverse2x2) +{ + test("mat2", "const mat2 c = inverse(mat2(2., 3., 5., 7.))", + "all(equal(v[0], vec2(-7., 3.))) && all(equal(v[1], vec2(5., -2.)))"); + verifyIsInTranslation("-7.0"); + verifyIsNotInTranslation("5.0, 7.0"); + verifyIsNotInTranslation("inverse"); +} + +// Constant fold inverse() +TEST_P(GLSLConstantFoldingTest, Inverse3x3) +{ + test("mat3", "const mat3 c = inverse(mat3(11., 13., 19., 23., 29., 31., 37., 41., 43.))", + "all(lessThan(abs(v[0] - vec3(31.*41.-29.*43., 13.*43.-19.*41., 19.*29.-13.*31.)/680.), " + "vec3(0.000001))) && " + "all(lessThan(abs(v[1] - vec3(23.*43.-31.*37., 19.*37.-11.*43., 11.*31.-19.*23.)/680.), " + "vec3(0.000001))) && " + "all(lessThan(abs(v[2] - vec3(29.*37.-23.*41., 11.*41.-13.*37., 13.*23.-11.*29.)/680.), " + "vec3(0.000001)))"); + verifyIsInTranslation("0.0352"); + verifyIsNotInTranslation("29.0"); + verifyIsNotInTranslation("inverse"); +} + +// Constant fold inverse() +TEST_P(GLSLConstantFoldingTest, Inverse4x4) +{ + test("mat4", + "const mat4 c = inverse(mat4(29., 31., 37., 41., " + "43., 47., 53., 59., " + "61., 67., 71., 73., " + "79., 83., 89., 97.))", + "all(lessThan(abs(v[0] - vec4(215., -330., -60., 155.)/630.), vec4(0.000001))) && " + "all(lessThan(abs(v[1] - vec4(-450., 405., 45., -90.)/630.), vec4(0.000001))) && " + "all(lessThan(abs(v[2] - vec4(425., -330., 129., -76.)/630.), vec4(0.000001))) && " + "all(lessThan(abs(v[3] - vec4(-180., 225., -108., 27.)/630.), vec4(0.000001)))"); + verifyIsInTranslation("0.3412"); + verifyIsNotInTranslation("53.0"); + verifyIsNotInTranslation("inverse"); +} + +// Constant fold determinant() +TEST_P(GLSLConstantFoldingTest, Determinant2x2) +{ + test("float", "const float c = determinant(mat2(2., 3., 5., 7.))", "v == -1."); + verifyIsInTranslation("-1.0"); + verifyIsNotInTranslation("7.0"); + verifyIsNotInTranslation("determinant"); +} + +// Constant fold determinant() +TEST_P(GLSLConstantFoldingTest, Determinant3x3) +{ + test("float", "const float c = determinant(mat3(11., 13., 19., 23., 29., 31., 37., 41., 43.))", + "v == -680."); + verifyIsInTranslation("-680."); + verifyIsNotInTranslation("31.0"); + verifyIsNotInTranslation("determinant"); +} + +// Constant fold determinant() +TEST_P(GLSLConstantFoldingTest, Determinant4x4) +{ + test("float", + "const float c = determinant(mat4(29., 31., 37., 41., " + "43., 47., 53., 59., " + "61., 67., 71., 73., " + "79., 83., 89., 97.))", + "v == -2520."); + verifyIsInTranslation("-2520.0"); + verifyIsNotInTranslation("71.0"); + verifyIsNotInTranslation("determinant"); +} + +// Constant fold transpose() +TEST_P(GLSLConstantFoldingTest, Transpose3x3) +{ + test("mat3", "const mat3 c = transpose(mat3(11., 13., 19., 23., 29., 31., 37., 41., 43.))", + "all(lessThan(abs(v[0] - vec3(11., 23., 37.)), vec3(0.000001))) && " + "all(lessThan(abs(v[1] - vec3(13., 29., 41.)), vec3(0.000001))) && " + "all(lessThan(abs(v[2] - vec3(19., 31., 43.)), vec3(0.000001)))"); + verifyIsInTranslation("11.0, 23.0"); + verifyIsNotInTranslation("11.0, 13.0"); + verifyIsNotInTranslation("transpose"); +} + +// 0xFFFFFFFF as int should evaluate to -1. +// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42 +// means that any 32-bit unsigned integer value is a valid literal. +TEST_P(GLSLConstantFoldingTest, ParseWrappedHexIntLiteral) +{ + test("int", "const int c = 0xFFFFFFFF", "v == -1"); + verifyIsInTranslation("-1"); +} + +// 3000000000 as int should wrap to -1294967296. +// This is featured in the examples of GLSL 4.5, and ESSL behavior should match +// desktop GLSL when it comes to integer parsing. +TEST_P(GLSLConstantFoldingTest, ParseWrappedDecimalIntLiteral) +{ + test("int", "const int c = 3000000000", "v == -1294967296"); + verifyIsInTranslation("-1294967296"); +} + +// 0xFFFFFFFF as uint should be unchanged. +// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42 +// means that any 32-bit unsigned integer value is a valid literal. +TEST_P(GLSLConstantFoldingTest, ParseMaxUintLiteral) +{ + test("uint", "const uint c = 0xFFFFFFFFu", "v == 0xFFFFFFFFu"); + verifyIsInTranslation("4294967295"); +} + +// -1 as uint should wrap to 0xFFFFFFFF. +// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42 +// means that any 32-bit unsigned integer value is a valid literal. +TEST_P(GLSLConstantFoldingTest, ParseUnaryMinusOneUintLiteral) +{ + test("uint", "const uint c = -1u", "v == 0xFFFFFFFFu"); + verifyIsInTranslation("4294967295"); +} + +// Constant fold matrix constructor from matrix with identical size +TEST_P(GLSLConstantFoldingTest, ConstructMat2FromMat2) +{ + test("mat2", "const mat2 c = mat2(mat2(0., 1., 2., 3.))", + "all(equal(v[0], vec2(0., 1.))) && " + "all(equal(v[1], vec2(2., 3.)))"); +} + +// Constant fold matrix constructor from scalar +TEST_P(GLSLConstantFoldingTest, ConstructMat2FromScalar) +{ + test("mat2", "const mat2 c = mat2(3)", + "all(equal(v[0], vec2(3., 0.))) && " + "all(equal(v[1], vec2(0., 3.)))"); + verifyIsInTranslation("0.0"); +} + +// Constant fold matrix constructor from vector +TEST_P(GLSLConstantFoldingTest, ConstructMat2FromVector) +{ + test("mat2", "const mat2 c = mat2(vec4(0., 1., 2., 3.))", + "all(equal(v[0], vec2(0., 1.))) && " + "all(equal(v[1], vec2(2., 3.)))"); +} + +// Constant fold matrix constructor from multiple args +TEST_P(GLSLConstantFoldingTest, ConstructMat2FromMultiple) +{ + test("mat2", "const mat2 c = mat2(-1, vec2(0., 1.), vec4(2.))", + "all(equal(v[0], vec2(-1., 0.))) && " + "all(equal(v[1], vec2(1., 2.)))"); + verifyIsInTranslation("1.0, 2.0"); +} + +// Constant fold matrix constructor from larger matrix +TEST_P(GLSLConstantFoldingTest, ConstructMat2FromMat3) +{ + test("mat2", "const mat2 c = mat2(mat3(0., 1., 2., 3., 4., 5., 6., 7., 8.))", + "all(equal(v[0], vec2(0., 1.))) && " + "all(equal(v[1], vec2(3., 4.)))"); +} + +// Constant fold matrix constructor from smaller matrix +TEST_P(GLSLConstantFoldingTest, ConstructMat4x3FromMat3x2) +{ + test("mat4x3", "const mat4x3 c = mat4x3(mat3x2(1., 2., 3., 4., 5., 6.))", + "all(equal(v[0], vec3(1., 2., 0.))) && " + "all(equal(v[1], vec3(3., 4., 0.))) && " + "all(equal(v[2], vec3(5., 6., 1.))) && " + "all(equal(v[3], vec3(0., 0., 0.)))"); + verifyIsInTranslation("2.0, 0.0"); +} + +// Constant fold struct comparison when structs are different +TEST_P(GLSLConstantFoldingTest, StructEqualityFalse) +{ + test("int", R"( +struct nested { + float f; +}; +struct S { + nested a; + float f; +}; +const S s1 = S(nested(0.), 2.); +const S s2 = S(nested(0.), 3.); +const int c = s1 == s2 ? 1 : 0;)", + "!bool(v)"); + + verifyIsNotInTranslation("2.0"); + verifyIsNotInTranslation("3.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold struct comparison when structs are identical +TEST_P(GLSLConstantFoldingTest, StructEqualityTrue) +{ + test("int", R"( +struct nested { + float f; +}; +struct S { + nested a; + float f; + int i; +}; +const S s1 = S(nested(0.), 2., 3); +const S s2 = S(nested(0.), 2., 3); +const int c = s1 == s2 ? 1 : 0;)", + "bool(v)"); + + verifyIsNotInTranslation("2.0"); + verifyIsNotInTranslation("3.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold indexing of a non-square matrix +TEST_P(GLSLConstantFoldingTest, NonSquareMatrixIndex) +{ + test("vec4", "const vec4 c = mat3x4(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)[1]", + "all(equal(v, vec4(4, 5, 6, 7)))"); + verifyIsInTranslation("4.0"); + verifyIsNotInTranslation("[1]"); +} + +// Constant fold outerProduct with vectors of non-matching length +TEST_P(GLSLConstantFoldingTest, NonSquareOuterProduct) +{ + test("mat3x2", "const mat3x2 c = outerProduct(vec2(2., 3.), vec3(5., 7., 11.))", + "all(equal(v[0], vec2(10., 15.))) &&" + "all(equal(v[1], vec2(14., 21.))) &&" + "all(equal(v[2], vec2(22., 33.)))"); + verifyIsInTranslation("15.0"); + verifyIsNotInTranslation("7.0"); + verifyIsNotInTranslation("outerProduct"); +} + +// Constant fold shift left with different non-matching signedness +TEST_P(GLSLConstantFoldingTest, ShiftLeftMismatchingSignedness) +{ + test("uint", "const uint c = 0xFFFFFFFFu << 31", "v == 0x80000000u"); + verifyIsInTranslation("2147483648"); + if (!IsOpenGLES()) + { + // Do not check with GLES, because `#version 310 es` would match this. + verifyIsNotInTranslation("31"); + } + verifyIsNotInTranslation("<<"); +} + +// Constant fold shift right with different non-matching signedness +TEST_P(GLSLConstantFoldingTest, ShiftRightMismatchingSignedness) +{ + test("uint", "const uint c = 0xFFFFFFFFu >> 29", "v == 0x7u"); + verifyIsInTranslation("7"); + verifyIsNotInTranslation("29"); + verifyIsNotInTranslation(">>"); +} + +// Constant fold shift right, expecting sign extension +TEST_P(GLSLConstantFoldingTest, ShiftRightSignExtension) +{ + test("int", "const int c = 0x8FFFE000 >> 6", "v == 0xFE3FFF80"); + verifyIsInTranslation("29360256"); + verifyIsNotInTranslation(" 6"); + verifyIsNotInTranslation(">>"); +} + +// Constant fold shift left, such that the number turns from positive to negative +TEST_P(GLSLConstantFoldingTest, ShiftLeftChangeSign) +{ + test("int", "const int c = 0x1FFFFFFF << 7", "v == 0xFFFFFF80"); + verifyIsInTranslation("-128"); + verifyIsNotInTranslation(" 7"); + verifyIsNotInTranslation("<<"); +} + +// Constant fold divide minimum integer by -1. +// ESSL 3.00.6 section 4.1.3 Integers: +// > However, for the case where the minimum representable value is divided by -1, it is allowed to +// > return either the minimum representable value or the maximum representable value. +// +// ANGLE always returns the maximum value. +TEST_P(GLSLConstantFoldingTest, DivideMinimumIntegerByMinusOne) +{ + test("int", "const int c = 0x80000000 / -1", "v == 0x7FFFFFFF"); + verifyIsInTranslation("2147483647"); +} + +// Constant fold unsigned addition with overflow +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, UnsignedIntegerAddOverflow) +{ + test("uint", "const uint c = 0xFFFFFFFFu + 43u", "v == 42u"); + verifyIsInTranslation("42"); + verifyIsNotInTranslation("43"); +} + +// Constant fold signed addition with overflow +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, SignedIntegerAddOverflow) +{ + test("int", "const int c = 0x7FFFFFFF + 4", "v == -0x7FFFFFFD"); + verifyIsInTranslation("-2147483645"); +} + +// Constant fold unsigned subtraction with underflow +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, UnsignedIntegerSubUnderflow) +{ + test("uint", "const uint c = 0u - 5u", "v == 0xFFFFFFFBu"); + verifyIsInTranslation("4294967291"); +} + +// Constant fold signed subtraction with underflow +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, SignedIntegerSubUnderflow) +{ + test("int", "const int c = -0x7FFFFFFF - 7", "v == 0x7FFFFFFA"); + verifyIsInTranslation("2147483642"); +} + +// Constant fold unsigned multiplication with overflow +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, UnsignedIntegerMulOverflow) +{ + test("uint", "const uint c = 0xFFFFFFFFu * 10u", "v == 0xFFFFFFF6u"); + verifyIsInTranslation("4294967286"); +} + +// Constant fold signed multiplication with overflow +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, SignedIntegerMulOverflow) +{ + test("int", "const int c = 0x7FFFFFFF * 42", "v == -42"); + verifyIsInTranslation("-42"); +} + +// Constant fold negation of minimum integer value, which is 0x80000000. +// ESSL 3.00.6 section 4.1.3 Integers: +// > For all precisions, operations resulting in overflow or underflow will not cause any exception, +// > nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result +// > where n is the size in bits of the integer. +TEST_P(GLSLConstantFoldingTest, SignedIntegerNegateOverflow) +{ + test("int", "const int c = -0x80000000", "v == 0x80000000"); + verifyIsInTranslation("-2147483648"); +} + +// Constant fold shift right of minimum integer value, which is 0x80000000. +TEST_P(GLSLConstantFoldingTest, SignedIntegerShiftRightMinimumValue) +{ + test("int", "const int c = (0x80000000 >> 1) + (0x80000000 >> 7)", "v == -0x41000000"); + verifyIsInTranslation("-1090519040"); +} + +// Constant fold shift left by zero. +TEST_P(GLSLConstantFoldingTest, SignedIntegerShiftLeftZero) +{ + test("int", "const int c = 73 << 0", "v == 73"); +} + +// Constant fold shift right by zero. +TEST_P(GLSLConstantFoldingTest, SignedIntegerShiftRightZero) +{ + test("int", "const int c = 3 >> 0", "v == 3"); +} + +// Constant fold isinf with an out-of-range value +// ESSL 3.00.6 section 4.1.4 Floats: +// > If the value of the floating point number is too large (small) to be stored as a single +// > precision value, it is converted to positive (negative) infinity. +// ESSL 3.00.6 section 12.4: +// > Mandate support for signed infinities. +TEST_P(GLSLConstantFoldingTest, IsInfTrue) +{ + test("int", "const int c = isinf(1.0e2048) ? 1 : 0", "bool(v)"); + verifyIsNotInTranslation("isinf"); +} + +// Test that floats that are too small to be represented get flushed to zero. +// ESSL 3.00.6 section 4.1.4 Floats: +// > A value with a magnitude too small to be represented as a mantissa and exponent is converted to +// > zero. +TEST_P(GLSLConstantFoldingTest, TooSmallFloat) +{ + test("float", "const float c = 1.0e-2048", "v == 0."); +} + +// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. +// lim radians(x) x -> inf = inf +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, RadiansInfinity) +{ + test("float", "const float c = radians(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("radians"); +} + +// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. +// lim degrees(x) x -> inf = inf +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, DegreesInfinity) +{ + test("float", "const float c = degrees(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("degress"); +} + +// IEEE 754 dictates that sinh(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, SinhInfinity) +{ + test("float", "const float c = sinh(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("sinh"); +} + +// IEEE 754 dictates that sinh(-inf) = -inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, SinhNegativeInfinity) +{ + test("float", "const float c = sinh(-1.0e2048)", "isinf(v) && v < 0."); + verifyIsNotInTranslation("sinh"); +} + +// IEEE 754 dictates that cosh(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, CoshInfinity) +{ + test("float", "const float c = cosh(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("cosh"); +} + +// IEEE 754 dictates that cosh(-inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, CoshNegativeInfinity) +{ + test("float", "const float c = cosh(-1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("cosh"); +} + +// IEEE 754 dictates that asinh(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, AsinhInfinity) +{ + test("float", "const float c = asinh(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("asinh"); +} + +// IEEE 754 dictates that asinh(-inf) = -inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, AsinhNegativeInfinity) +{ + test("float", "const float c = asinh(-1.0e2048)", "isinf(v) && v < 0."); + verifyIsNotInTranslation("asinh"); +} + +// IEEE 754 dictates that acosh(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, AcoshInfinity) +{ + test("float", "const float c = acosh(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("acosh"); +} + +// IEEE 754 dictates that pow or powr(0, inf) = 0. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, PowInfinity) +{ + test("float", "const float c = pow(0.0, 1.0e2048)", "v == 0."); + verifyIsNotInTranslation("pow"); +} + +// IEEE 754 dictates that exp(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, ExpInfinity) +{ + test("float", "const float c = exp(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("exp"); +} + +// IEEE 754 dictates that exp(-inf) = 0. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, ExpNegativeInfinity) +{ + test("float", "const float c = exp(-1.0e2048)", "v == 0."); + verifyIsNotInTranslation("exp"); +} + +// IEEE 754 dictates that log(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, LogInfinity) +{ + test("float", "const float c = log(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("log"); +} + +// IEEE 754 dictates that exp2(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, Exp2Infinity) +{ + test("float", "const float c = exp2(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("exp2"); +} + +// IEEE 754 dictates that exp2(-inf) = 0. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, Exp2NegativeInfinity) +{ + test("float", "const float c = exp2(-1.0e2048)", "v == 0."); + verifyIsNotInTranslation("exp2"); +} + +// IEEE 754 dictates that log2(inf) = inf. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, Log2Infinity) +{ + test("float", "const float c = log2(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("log2"); +} + +// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. +// lim sqrt(x) x -> inf = inf +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, SqrtInfinity) +{ + test("float", "const float c = sqrt(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("sqrt"); +} + +// IEEE 754 dictates that rSqrt(inf) = 0 +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, InversesqrtInfinity) +{ + test("float", "const float c = inversesqrt(1.0e2048)", "v == 0."); + verifyIsNotInTranslation("inversesqrt"); +} + +// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. +// lim length(x) x -> inf = inf +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, LengthInfinity) +{ + test("float", "const float c = length(1.0e2048)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("length"); +} + +// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. +// lim dot(x, y) x -> inf, y > 0 = inf +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, DotInfinity) +{ + test("float", "const float c = dot(1.0e2048, 1.)", "isinf(v) && v > 0."); + verifyIsNotInTranslation("dot"); +} + +// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic. +// lim dot(vec2(x, y), vec2(z)) x -> inf, finite y, z > 0 = inf +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, DotInfinity2) +{ + test("float", "const float c = dot(vec2(1.0e2048, -1.), vec2(1.))", "isinf(v) && v > 0."); + verifyIsNotInTranslation("dot"); +} + +// Faceforward behavior with infinity as a parameter can be derived from dot(). +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, FaceForwardInfinity) +{ + test("float", "const float c = faceforward(4., 1.0e2048, 1.)", "v == -4."); + verifyIsNotInTranslation("faceforward"); +} + +// Faceforward behavior with infinity as a parameter can be derived from dot(). +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, FaceForwardInfinity2) +{ + test("float", "const float c = faceforward(vec2(4.), vec2(1.0e2048, -1.), vec2(1.)).x", + "v == -4."); + verifyIsNotInTranslation("faceforward"); +} + +// Test that infinity - finite value evaluates to infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, InfinityMinusFinite) +{ + test("float", "const float c = 1.0e2048 - 1.0e20", "isinf(v) && v > 0."); +} + +// Test that -infinity + finite value evaluates to -infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, MinusInfinityPlusFinite) +{ + test("float", "const float c = (-1.0e2048) + 1.0e20", "isinf(v) && v < 0."); +} + +// Test that infinity * finite value evaluates to infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, InfinityMultipliedByFinite) +{ + test("float", "const float c = 1.0e2048 * 1.0e-20", "isinf(v) && v > 0."); +} + +// Test that infinity * infinity evaluates to infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, InfinityMultipliedByInfinity) +{ + test("float", "const float c = 1.0e2048 * 1.0e2048", "isinf(v) && v > 0."); +} + +// Test that infinity * negative infinity evaluates to negative infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, InfinityMultipliedByNegativeInfinity) +{ + test("float", "const float c = 1.0e2048 * (-1.0e2048)", "isinf(v) && v < 0."); +} + +// Test that dividing by minus zero results in the appropriately signed infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +// > If both positive and negative zeros are implemented, the correctly signed Inf will be +// > generated. +TEST_P(GLSLConstantFoldingTest, DivideByNegativeZero) +{ + test("float", "const float c = 1. / (-0.)", "isinf(v) && v < 0."); + verifyIsNotInTranslation("-0.0"); +} + +// Test that infinity divided by zero evaluates to infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, InfinityDividedByZero) +{ + test("float", "const float c = 1.0e2048 / 0.", "isinf(v) && v > 0."); +} + +// Test that negative infinity divided by zero evaluates to negative infinity. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, MinusInfinityDividedByZero) +{ + test("float", "const float c = (-1.0e2048) / 0.", "isinf(v) && v < 0."); +} + +// Test that dividing a finite number by infinity results in zero. +// ESSL 3.00.6 section 4.5.1: +// > Infinities and zeroes are generated as dictated by IEEE. +TEST_P(GLSLConstantFoldingTest, DivideByInfinity) +{ + test("float", "const float c = 1.0e30 / 1.0e2048", "v == 0."); +} + +// Test that unsigned bitfieldExtract is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, UnsignedBitfieldExtract) +{ + test("uint", "const uint c = bitfieldExtract(0x00110000u, 16, 5)", "v == 0x11u"); + verifyIsInTranslation("17"); + verifyIsNotInTranslation("16"); + verifyIsNotInTranslation("bitfieldExtract"); +} + +// Test that unsigned bitfieldExtract to extract 32 bits is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, UnsignedBitfieldExtract32Bits) +{ + test("uint", "const uint c = bitfieldExtract(0xFF0000FFu, 0, 32)", "v == 0xFF0000FFu"); + verifyIsNotInTranslation("32"); + verifyIsNotInTranslation("bitfieldExtract"); +} + +// Test that signed bitfieldExtract is folded correctly. The higher bits should be set to 1 if the +// most significant bit of the extracted value is 1. +TEST_P(GLSLConstantFoldingTest_ES31, SignedBitfieldExtract) +{ + test("int", "const int c = bitfieldExtract(0x00110000, 16, 5)", "v == -15"); + verifyIsInTranslation("-15"); + verifyIsNotInTranslation("16"); + verifyIsNotInTranslation("bitfieldExtract"); +} + +// Test that bitfieldInsert is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, BitfieldInsert) +{ + test("uint", "const uint c = bitfieldInsert(0x04501701u, 0x11u, 8, 5)", "v == 0x04501101u"); + verifyIsInTranslation("72356097"); + verifyIsNotInTranslation(" 8"); + verifyIsNotInTranslation("bitfieldInsert"); +} + +// Test that bitfieldInsert to insert 32 bits is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, BitfieldInsert32Bits) +{ + test("uint", "const uint c = bitfieldInsert(0xFF0000FFu, 0x11u, 0, 32)", "v == 0x11u"); + verifyIsInTranslation("17"); + verifyIsNotInTranslation("32"); + verifyIsNotInTranslation("bitfieldInsert"); +} + +// Test that bitfieldReverse is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, BitfieldReverse) +{ + test("uint", "const uint c = bitfieldReverse((1u << 4u) | (1u << 7u))", "v == 0x9000000u"); + verifyIsInTranslation("150994944"); + verifyIsNotInTranslation(" 7"); + verifyIsNotInTranslation("bitfieldReverse"); +} + +// Test that bitCount is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, BitCount) +{ + test("int", "const int c = bitCount(0x17103121u)", "v == 10"); + verifyIsInTranslation("10"); + verifyIsNotInTranslation("386937121"); + verifyIsNotInTranslation("bitCount"); +} + +// Test that findLSB is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, FindLSB) +{ + test("int", "const int c = findLSB(0x80010000u)", "v == 16"); + verifyIsInTranslation("16"); + verifyIsNotInTranslation("2147549184"); + verifyIsNotInTranslation("findLSB"); +} + +// Test that findLSB is folded correctly when the operand is zero. +TEST_P(GLSLConstantFoldingTest_ES31, FindLSBZero) +{ + test("int", "const int c = findLSB(0u)", "v == -1"); + verifyIsInTranslation("-1"); + verifyIsNotInTranslation("findLSB"); +} + +// Test that findMSB is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, FindMSB) +{ + test("int", "const int c = findMSB(0x01000008u)", "v == 24"); + verifyIsInTranslation("24"); + verifyIsNotInTranslation("16777224"); + verifyIsNotInTranslation("findMSB"); +} + +// Test that findMSB is folded correctly when the operand is zero. +TEST_P(GLSLConstantFoldingTest_ES31, FindMSBZero) +{ + test("int", "const int c = findMSB(0u)", "v == -1"); + verifyIsInTranslation("-1"); + verifyIsNotInTranslation("findMSB"); +} + +// Test that findMSB is folded correctly for a negative integer. +// It is supposed to return the index of the most significant bit set to 0. +TEST_P(GLSLConstantFoldingTest_ES31, FindMSBNegativeInt) +{ + test("int", "const int c = findMSB(-8)", "v == 2"); + verifyIsInTranslation("2"); + verifyIsNotInTranslation("-8"); + verifyIsNotInTranslation("findMSB"); +} + +// Test that findMSB is folded correctly for -1. +TEST_P(GLSLConstantFoldingTest_ES31, FindMSBMinusOne) +{ + test("int", "const int c = findMSB(-1)", "v == -1"); + verifyIsNotInTranslation("findMSB"); +} + +// Test that packUnorm4x8 is folded correctly for a vector of zeroes. +TEST_P(GLSLConstantFoldingTest_ES31, PackUnorm4x8Zero) +{ + test("uint", "const uint c = packUnorm4x8(vec4(0.))", "v == 0u"); + verifyIsNotInTranslation("packUnorm4x8"); +} + +// Test that packUnorm4x8 is folded correctly for a vector of ones. +TEST_P(GLSLConstantFoldingTest_ES31, PackUnorm4x8One) +{ + test("uint", "const uint c = packUnorm4x8(vec4(1.))", "v == 0xFFFFFFFFu"); + verifyIsInTranslation("4294967295"); + verifyIsNotInTranslation("packUnorm4x8"); +} + +// Test that packSnorm4x8 is folded correctly for a vector of zeroes. +TEST_P(GLSLConstantFoldingTest_ES31, PackSnorm4x8Zero) +{ + test("uint", "const uint c = packSnorm4x8(vec4(0.))", "v == 0u"); + verifyIsNotInTranslation("packSnorm4x8"); +} + +// Test that packSnorm4x8 is folded correctly for a vector of ones. +TEST_P(GLSLConstantFoldingTest_ES31, PackSnorm4x8One) +{ + test("uint", "const uint c = packSnorm4x8(vec4(1.))", "v == 0x7F7F7F7Fu"); + verifyIsInTranslation("2139062143"); + verifyIsNotInTranslation("packSnorm4x8"); +} + +// Test that packSnorm4x8 is folded correctly for a vector of minus ones. +TEST_P(GLSLConstantFoldingTest_ES31, PackSnorm4x8MinusOne) +{ + test("uint", "const uint c = packSnorm4x8(vec4(-1.))", "v == 0x81818181u"); + verifyIsInTranslation("2172748161"); + verifyIsNotInTranslation("packSnorm4x8"); +} + +// Test that unpackSnorm4x8 is folded correctly when it needs to clamp the result. +TEST_P(GLSLConstantFoldingTest_ES31, UnpackSnorm4x8Clamp) +{ + test("float", "const float c = unpackSnorm4x8(0x00000080u).x", "v == -1."); + verifyIsInTranslation("-1.0"); + verifyIsNotInTranslation("packSnorm4x8"); +} + +// Test that unpackUnorm4x8 is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, UnpackUnorm4x8) +{ + test("float", "const float c = unpackUnorm4x8(0x007bbeefu).z", "abs(v - 123./255.) < 0.000001"); + verifyIsInTranslation("0.48235"); + verifyIsNotInTranslation("8109807"); + verifyIsNotInTranslation("packUnorm4x8"); +} + +// Test that ldexp is folded correctly. +TEST_P(GLSLConstantFoldingTest_ES31, Ldexp) +{ + test("float", "const float c = ldexp(0.625, 1)", "v == 1.25"); + verifyIsNotInTranslation("0.625"); + verifyIsNotInTranslation("ldexp"); +} + +// Constant fold ternary +TEST_P(GLSLConstantFoldingTest, Ternary) +{ + test("int", "int c = true ? 1 : v", "v == 1"); + verifyIsNotInTranslation("?"); + verifyIsNotInTranslation("if"); + verifyIsNotInTranslation("else"); +} + +// Constant fold ternary +TEST_P(GLSLConstantFoldingTest, TernaryInsideExpression) +{ + test("int", "int c = ivec2((true ? 1 : v) + 2, 4).x", "v == 3"); + verifyIsNotInTranslation("?"); + verifyIsNotInTranslation("if"); + verifyIsNotInTranslation("else"); +} + +// Constant fold indexing of an array +TEST_P(GLSLConstantFoldingTest, ArrayIndex) +{ + test("float", "const float c = float[3](-1., 1., 2.)[2]", "v == 2."); + verifyIsNotInTranslation("[2]"); +} + +// Constant fold indexing of an array of array +TEST_P(GLSLConstantFoldingTest_ES31, ArrayOfArrayIndex) +{ + test("float", "const float c = float[2][2](float[2](-1., 1.), float[2](2., 3.))[1][0]", + "v == 2."); + verifyIsNotInTranslation("[1]"); + verifyIsNotInTranslation("[0]"); +} + +// Constant fold indexing of an array stashed in another variable +TEST_P(GLSLConstantFoldingTest, NamedArrayIndex) +{ + test("float", R"(const float[3] arr = float[3](-1., 1., 2.); +const float c = arr[1])", + "v == 1."); + verifyIsNotInTranslation("[1]"); +} + +// Constant fold indexing of an array of array stashed in another variable +TEST_P(GLSLConstantFoldingTest_ES31, NamedArrayOfArrayIndex) +{ + test("float[2]", R"(const float[2][2] arr = float[2][2](float[2](-1., 1.), float[2](2., 3.)); +const float[2] c = arr[1])", + "v[0] == 2. && v[1] == 3."); + + // The AST path does not remove the definition of `arr`. + if (getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + verifyIsNotInTranslation("1.0"); + } +} + +// Constant fold indexing of an array of mixed constant and non-constant values (without side +// effect). +TEST_P(GLSLConstantFoldingTest, ArrayMixedArgumentsIndex) +{ + test("float", R"(float c = float[2](v, 1.)[1])", "v == 1."); + verifyIsNotInTranslation("[1]"); +} + +// Constant fold indexing of an array of mixed constant and non-constant values with side +// effect should not discard the side effect. +TEST_P(GLSLConstantFoldingTest, ArrayMixedArgumentsWithSideEffectIndex) +{ + test("float", R"(float sideEffectTarget = 0.; +float indexedElement = float[3](sideEffectTarget = 5., 11., 102.)[1]; +float c = indexedElement + sideEffectTarget)", + "v == 16."); +} + +// Constant fold equality of constructed arrays. +TEST_P(GLSLConstantFoldingTest, ArrayEqualityFalse) +{ + test("float", "const float c = float[3](2., 1., 1.) == float[3](2., 1., -1.) ? 1. : 2.", + "v == 2."); + verifyIsNotInTranslation("-1.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold equality of constructed arrays. +TEST_P(GLSLConstantFoldingTest, ArrayEqualityTrue) +{ + test("float", "const float c = float[3](2., 1., -1.) == float[3](2., 1., -1.) ? 1. : 2.", + "v == 1."); + verifyIsNotInTranslation("-1.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold equality of constructed arrays stashed in variables. +TEST_P(GLSLConstantFoldingTest, NamedArrayEqualityFalse) +{ + test("float", R"(const float[3] arrA = float[3](-1., 1., 2.); +const float[3] arrB = float[3](1., 1., 2.); +float c = arrA == arrB ? 1. : 2.)", + "v == 2."); + verifyIsNotInTranslation("-1.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold equality of constructed arrays stashed in variables. +TEST_P(GLSLConstantFoldingTest, NamedArrayEqualityTrue) +{ + test("float", R"(const float[3] arrA = float[3](-1., 1., 2.); +const float[3] arrB = float[3](-1., 1., 2.); +float c = arrA == arrB ? 1. : 2.)", + "v == 1."); + verifyIsNotInTranslation("-1.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold equality of constructed arrays of arrays. +TEST_P(GLSLConstantFoldingTest_ES31, ArrayOfArrayEqualityFalse) +{ + test("float", R"(const float c = float[2][2](float[2](-1., 1.), float[2](2., 3.)) + == float[2][2](float[2](-1., 1.), float[2](2., 1000.)) ? 1. : 2.)", + "v == 2."); + verifyIsNotInTranslation("-1.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold equality of constructed arrays. +TEST_P(GLSLConstantFoldingTest_ES31, ArrayOfArrayEqualityTrue) +{ + test("float", R"(const float c = float[2][2](float[2](-1., 1.), float[2](2., 3.)) + == float[2][2](float[2](-1., 1.), float[2](2., 3.)) ? 1. : 2.)", + "v == 1."); + verifyIsNotInTranslation("-1.0"); + verifyIsNotInTranslation("=="); +} + +// Constant fold casting a negative float to uint. +// ESSL 3.00.6 section 5.4.1 specifies this as an undefined conversion. +TEST_P(GLSLConstantFoldingTest, NegativeFloatToUint) +{ + test("uint", "const uint c = uint(-1.)", "v == 0xFFFFFFFFu"); + verifyIsInTranslation("4294967295"); +} + +// Constant fold casting a negative float to uint inside a uvec constructor. +// ESSL 3.00.6 section 5.4.1 specifies this as an undefined conversion. +TEST_P(GLSLConstantFoldingTest, NegativeFloatToUvec) +{ + test("uint", "const uint c = uvec4(2., 1., vec2(0., -1.)).w", "v == 0xFFFFFFFFu"); + verifyIsInTranslation("4294967295"); + verifyIsNotInTranslation("2.0"); +} + +// Constant fold casting a negative float to uint inside a uvec constructor, but that which is not +// used by the constructor. +TEST_P(GLSLConstantFoldingTest, NegativeFloatInsideUvecConstructorButOutOfRange) +{ + test("uint", "const uint c = uvec2(1., vec2(0., -1.)).x", "v == 1u"); + verifyIsNotInTranslation("-1.0"); +} + +// Constant fold a large float (above max signed int) to uint. +TEST_P(GLSLConstantFoldingTest, LargeFloatToUint) +{ + test("uint", "const uint c = uint(3221225472.)", "v == 3221225472u"); +} + +// Constant fold modulus with a negative dividend. +TEST_P(GLSLConstantFoldingTest, IntegerModulusNegativeDividend) +{ + test("int", "const int c = (-5) % 3", "v == 0"); + verifyIsNotInTranslation("%"); +} + +// Constant fold modulus with a negative divisor. +TEST_P(GLSLConstantFoldingTest, IntegerModulusNegativeDivisor) +{ + test("int", "const int c = 5 % (-3)", "v == 0"); + verifyIsNotInTranslation("%"); +} + +// Constant fold isnan with multiple components +TEST_P(GLSLConstantFoldingTest_ES31, IsnanMultipleComponents) +{ + test("ivec4", "const ivec4 c = ivec4(mix(ivec2(2), ivec2(3), isnan(vec2(1., 0. / 0.))), 4, 5)", + "all(equal(v, ivec4(2, 3, 4, 5)))"); + verifyIsNotInTranslation("1.0"); + verifyIsNotInTranslation("isnan"); + verifyIsNotInTranslation("mix"); +} + +// Constant fold isinf with multiple components +TEST_P(GLSLConstantFoldingTest_ES31, IsinfMultipleComponents) +{ + test("ivec4", + "const ivec4 c = ivec4(mix(ivec2(2), ivec2(3), isinf(vec2(0.0, 1.0e2048))), 4, 5)", + "all(equal(v, ivec4(2, 3, 4, 5)))"); + verifyIsNotInTranslation("isnan"); + verifyIsNotInTranslation("mix"); +} + +// Constant fold floatBitsToInt with multiple components +TEST_P(GLSLConstantFoldingTest, FloatBitsToIntMultipleComponents) +{ + test("ivec4", "const ivec4 c = ivec4(floatBitsToInt(vec2(0.0, 1.0)), 4, 5)", + "all(equal(v, ivec4(0, 0x3f800000, 4, 5)))"); + verifyIsNotInTranslation("1.0"); + verifyIsNotInTranslation("floatBitsToInt"); +} + +// Constant fold floatBitsToUint with multiple components +TEST_P(GLSLConstantFoldingTest, FloatBitsToUintMultipleComponents) +{ + test("ivec4", "const ivec4 c = ivec4(floatBitsToUint(vec2(0.0, 1.0)), 4, 5)", + "all(equal(v, ivec4(0, 0x3f800000, 4, 5)))"); + verifyIsNotInTranslation("1.0"); + verifyIsNotInTranslation("floatBitsToInt"); +} + +// Constant fold intBitsToFloat with multiple components +TEST_P(GLSLConstantFoldingTest, IntBitsToFloatMultipleComponents) +{ + test("vec4", "const vec4 c = vec4(intBitsToFloat(ivec2(0, 0x3f800000)), 0.25, 0.5)", + "all(equal(v, vec4(0., 1., 0.25, 0.5)))"); + verifyIsNotInTranslation("1065353216"); + verifyIsNotInTranslation("intBitsToFloat"); +} + +// Constant fold uintBitsToFloat with multiple components +TEST_P(GLSLConstantFoldingTest, UintBitsToFloatMultipleComponents) +{ + test("vec4", "const vec4 c = vec4(uintBitsToFloat(uvec2(0U, 0x3f800000U)), 0.25, 0.5)", + "all(equal(v, vec4(0., 1., 0.25, 0.5)))"); + verifyIsNotInTranslation("1065353216"); + verifyIsNotInTranslation("uintBitsToFloat"); +} + +// Test that infinity - infinity evaluates to NaN. +TEST_P(GLSLConstantFoldingTest, InfinityMinusInfinity) +{ + test("float", "const float c = 1.0e2048 - 1.0e2048", "isnan(v)"); +} + +// Test that infinity + negative infinity evaluates to NaN. +TEST_P(GLSLConstantFoldingTest, InfinityPlusNegativeInfinity) +{ + test("float", "const float c = 1.0e2048 + (-1.0e2048)", "isnan(v)"); +} + +// Test that infinity multiplied by zero evaluates to NaN. +TEST_P(GLSLConstantFoldingTest, InfinityMultipliedByZero) +{ + test("float", "const float c = 1.0e2048 * 0.", "isnan(v)"); +} + +// Test that infinity divided by infinity evaluates to NaN. +TEST_P(GLSLConstantFoldingTest, InfinityDividedByInfinity) +{ + test("float", "const float c = 1.0e2048 / 1.0e2048", "isnan(v)"); +} + +// Test that zero divided by zero evaluates to NaN. +TEST_P(GLSLConstantFoldingTest, ZeroDividedByZero) +{ + test("float", "const float c = 0. / 0.", "isnan(v)"); +} + +// Test that addition that overflows is evaluated correctly. +TEST_P(GLSLConstantFoldingTest, FloatOverflowAdd) +{ + test("float", "const float c = 2.0e38 + 2.0e38", "isinf(v) && v > 0."); +} + +// Test that subtraction that overflows is evaluated correctly. +TEST_P(GLSLConstantFoldingTest, FloatOverflowSubtract) +{ + test("float", "const float c = 2.0e38 - (-2.0e38)", "isinf(v) && v > 0."); +} + +// Test that multiplication that overflows is evaluated correctly. +TEST_P(GLSLConstantFoldingTest, FloatOverflowMultiply) +{ + test("float", "const float c = 1.0e30 * 1.0e10", "isinf(v) && v > 0."); +} + +// Test that division that overflows is evaluated correctly. +TEST_P(GLSLConstantFoldingTest, FloatOverflowDivide) +{ + test("float", "const float c = 1.0e30 / 1.0e-10", "isinf(v) && v > 0."); +} +} // namespace + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLConstantFoldingTest); +ANGLE_INSTANTIATE_TEST_ES3(GLSLConstantFoldingTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLConstantFoldingTest_ES31); +ANGLE_INSTANTIATE_TEST_ES31(GLSLConstantFoldingTest_ES31); diff --git a/src/tests/gl_tests/GLSLOutputTest.cpp b/src/tests/gl_tests/GLSLOutputTest.cpp new file mode 100644 index 00000000000..6b2ab0eef8e --- /dev/null +++ b/src/tests/gl_tests/GLSLOutputTest.cpp @@ -0,0 +1,490 @@ +// +// Copyright 2025 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. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "test_utils/CompilerTest.h" + +#include "test_utils/angle_test_configs.h" +#include "test_utils/gl_raii.h" + +using namespace angle; + +namespace +{ +class GLSLOutputTest : public CompilerTest +{ + protected: + GLSLOutputTest() {} + + // Helper to create a shader + void compileShader(GLenum shaderType, const char *shaderSource) + { + const CompiledShader &shader = compile(shaderType, shaderSource); + EXPECT_TRUE(shader.success()); + } + + // Check that the output contains (or not) the expected substring. + void verifyIsInTranslation(GLenum shaderType, const char *expect) + { + EXPECT_TRUE(getCompiledShader(shaderType).verifyInTranslatedSource(expect)) << expect; + } + void verifyIsNotInTranslation(GLenum shaderType, const char *expect) + { + EXPECT_TRUE(getCompiledShader(shaderType).verifyNotInTranslatedSource(expect)) << expect; + } + void verifyCountInTranslation(GLenum shaderType, const char *expect, size_t expectCount) + { + EXPECT_TRUE( + getCompiledShader(shaderType).verifyCountInTranslatedSource(expect, expectCount)) + << expectCount << "x " << expect; + } +}; + +class GLSLOutputGLSLTest : public GLSLOutputTest +{}; + +class GLSLOutputGLSLTest_ES3 : public GLSLOutputTest +{}; + +class WebGLGLSLOutputGLSLTest : public GLSLOutputGLSLTest +{ + protected: + WebGLGLSLOutputGLSLTest() { setWebGLCompatibilityEnabled(true); } +}; + +class WebGL2GLSLOutputGLSLTest : public GLSLOutputGLSLTest_ES3 +{ + protected: + WebGL2GLSLOutputGLSLTest() { setWebGLCompatibilityEnabled(true); } +}; + +// Verifies that without explicitly enabling GL_EXT_draw_buffers extension in the shader, no +// broadcast emulation. +TEST_P(GLSLOutputGLSLTest, FragColorNoBroadcast) +{ + constexpr char kFS[] = R"(void main() +{ + gl_FragColor = vec4(1, 0, 0, 0); +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragColor"); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[0]"); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[1]"); +} + +// Verifies that with explicitly enabling GL_EXT_draw_buffers extension +// in the shader, broadcast is emualted by replacing gl_FragColor with gl_FragData. +TEST_P(GLSLOutputGLSLTest, FragColorBroadcast) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers")); + + constexpr char kFS[] = R"(#extension GL_EXT_draw_buffers : require +void main() +{ + gl_FragColor = vec4(1, 0, 0, 0); +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragColor"); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[0]"); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[1]"); +} + +// Verifies that with explicitly enabling GL_EXT_draw_buffers extension +// in the shader with an empty main(), nothing happens. +TEST_P(GLSLOutputGLSLTest, EmptyMain) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers")); + + constexpr char kFS[] = R"(#extension GL_EXT_draw_buffers : require +void main() +{ +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragColor"); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[0]"); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[1]"); +} + +// Test the initialization of output variables with various qualifiers in a vertex shader. +TEST_P(WebGL2GLSLOutputGLSLTest, OutputAllQualifiers) +{ + constexpr char kVS[] = R"(#version 300 es +precision mediump float; +precision lowp int; +out vec4 out1; +flat out int out2; +centroid out float out3; +smooth out float out4; +void main() { + out1.x += 0.0001; + out2 += 1; + out3 += 0.0001; + out4 += 0.0001; +})"; + compileShader(GL_VERTEX_SHADER, kVS); + verifyIsInTranslation(GL_VERTEX_SHADER, "gl_Position = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1 = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout2 = 0"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout3 = 0.0"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout4 = 0.0"); +} + +// Test the initialization of an output array in a vertex shader. +TEST_P(WebGL2GLSLOutputGLSLTest, OutputArray) +{ + constexpr char kVS[] = R"(#version 300 es +precision mediump float; +out float out1[2]; +void main() { + out1[0] += 0.0001; +})"; + compileShader(GL_VERTEX_SHADER, kVS); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1[0] = 0.0"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1[1] = 0.0"); +} + +// Test the initialization of a struct output variable in a vertex shader. +TEST_P(WebGL2GLSLOutputGLSLTest, OutputStruct) +{ + constexpr char kVS[] = R"(#version 300 es +precision mediump float; +struct MyS{ + float a; + float b; +}; +out MyS out1; +void main() { + out1.a += 0.0001; +})"; + compileShader(GL_VERTEX_SHADER, kVS); + if (getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1._ua = 0.0"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1._ub = 0.0"); + } + else + { + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1 = _uMyS("); + } +} + +// Test the initialization of a varying variable in an ESSL1 vertex shader. +TEST_P(WebGL2GLSLOutputGLSLTest, OutputFromESSL1Shader) +{ + constexpr char kVS[] = R"(precision mediump float; +varying vec4 out1; +void main() { + out1.x += 0.0001; +})"; + compileShader(GL_VERTEX_SHADER, kVS); + verifyIsInTranslation(GL_VERTEX_SHADER, "gl_Position = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsInTranslation(GL_VERTEX_SHADER, "_uout1 = vec4(0.0, 0.0, 0.0, 0.0)"); +} + +// Test the initialization of output variables in a fragment shader. +TEST_P(WebGL2GLSLOutputGLSLTest, FragmentOutput) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 out1; +void main() { + out1.x += 0.0001; +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "_uout1 = vec4(0.0, 0.0, 0.0, 0.0)"); +} + +// Test the initialization of gl_FragData in a WebGL2 ESSL1 fragment shader. Only writes to +// gl_FragData[0] should be found. +TEST_P(WebGL2GLSLOutputGLSLTest, FragData) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() { + gl_FragData[0] = vec4(1.); +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[0] = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[1]"); +} + +// Test the initialization of gl_FragData in a WebGL1 ESSL1 fragment shader. Only writes to +// gl_FragData[0] should be found. +TEST_P(WebGLGLSLOutputGLSLTest, FragData) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() { + gl_FragData[0] = vec4(1.); +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[0] = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[1]"); +} + +// Test the initialization of gl_FragData in a WebGL1 ESSL1 fragment shader with GL_EXT_draw_buffers +// enabled. All attachment slots should be initialized. +TEST_P(WebGLGLSLOutputGLSLTest, FragDataWithDrawBuffersExtEnabled) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers")); + + constexpr char kFS[] = R"(#extension GL_EXT_draw_buffers : enable +precision mediump float; +void main() { + gl_FragData[0] = vec4(1.); +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[0] = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsInTranslation(GL_FRAGMENT_SHADER, "gl_FragData[1] = vec4(0.0, 0.0, 0.0, 0.0)"); +} + +// Test that gl_Position is initialized once in case it is not statically used and both +// initOutputVariables (by webgl) and initGLPosition (by webgl, but also the GL backend) flags are +// set. +TEST_P(WebGL2GLSLOutputGLSLTest, InitGLPositionWhenNotStaticallyUsed) +{ + constexpr char kVS[] = R"(#version 300 es +precision highp float; +void main() { +})"; + compileShader(GL_VERTEX_SHADER, kVS); + verifyCountInTranslation(GL_VERTEX_SHADER, "gl_Position = vec4(0.0, 0.0, 0.0, 0.0)", 1); +} + +// Test that gl_Position is initialized once in case it is statically used and both +// initOutputVariables (by webgl) and initGLPosition (by webgl, but also the GL backend) flags are +// set. +TEST_P(WebGL2GLSLOutputGLSLTest, InitGLPositionOnceWhenStaticallyUsed) +{ + constexpr char kVS[] = R"(#version 300 es +precision highp float; +void main() { + gl_Position = vec4(1.0); +})"; + compileShader(GL_VERTEX_SHADER, kVS); + verifyCountInTranslation(GL_VERTEX_SHADER, "gl_Position = vec4(0.0, 0.0, 0.0, 0.0)", 1); +} + +class GLSLOutputGLSLTest_InitShaderVariables : public GLSLOutputGLSLTest +{}; + +// Mirrors ClipDistanceTest.ThreeClipDistancesRedeclared +TEST_P(GLSLOutputGLSLTest_InitShaderVariables, RedeclareClipDistance) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_APPLE_clip_distance")); + + constexpr char kVS[] = R"(#extension GL_APPLE_clip_distance : require + +varying highp float gl_ClipDistance[3]; + +void computeClipDistances(in vec4 position, in vec4 plane[3]) +{ + gl_ClipDistance[0] = dot(position, plane[0]); + gl_ClipDistance[1] = dot(position, plane[1]); + gl_ClipDistance[2] = dot(position, plane[2]); +} + +uniform vec4 u_plane[3]; + +attribute vec2 a_position; + +void main() +{ + gl_Position = vec4(a_position, 0.0, 1.0); + + computeClipDistances(gl_Position, u_plane); +})"; + compileShader(GL_VERTEX_SHADER, kVS); + verifyIsInTranslation(GL_VERTEX_SHADER, "gl_Position = vec4(0.0, 0.0, 0.0, 0.0)"); + verifyIsInTranslation(GL_VERTEX_SHADER, "gl_ClipDistance[0] = 0.0"); + verifyIsInTranslation(GL_VERTEX_SHADER, "gl_ClipDistance[1] = 0.0"); + verifyIsInTranslation(GL_VERTEX_SHADER, "gl_ClipDistance[2] = 0.0"); +} + +class GLSLOutputGLSLVerifyIRUseTest : public GLSLOutputGLSLTest +{}; + +// A basic test that makes sure the `useIr` feature is actually effective. +TEST_P(GLSLOutputGLSLVerifyIRUseTest, Basic) +{ + constexpr char kFS[] = R"(void main() +{ +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + // With AST, implicit `return` remains implicit. With IR, every block ends in a branch, so the + // `return` is explicit. + if (getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + verifyIsInTranslation(GL_FRAGMENT_SHADER, "return"); + } + else + { + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "return"); + } +} + +class GLSLOutputMSLTest_EnsureLoopForwardProgress : public GLSLOutputTest +{}; + +// Test that loopForwardProgress() is not inserted when the for loop is obviously not an infinite +// loop. +TEST_P(GLSLOutputMSLTest_EnsureLoopForwardProgress, FiniteBasicFor) +{ + constexpr char kFS[] = R"(#version 300 es +void main() { + for (highp int i = 0; i < 100; ++i) { } +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + // The AST transformation (EnsureLoopForwardProgress ) expects a |for| loop, but the IR changes + // it to |while| before that's run. So when the IR is used, the test would fail as the + // transformaiton is unable to correctly detect finite loops. + // + // Once the transformation is ported to the IR, the test verification can be enabled. + if (!getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "loopForwardProgress"); + } +} + +// Test that loopForwardProgress() is inserted when the for loop is an infinite loop. +TEST_P(GLSLOutputMSLTest_EnsureLoopForwardProgress, InfiniteFor) +{ + constexpr char kFS[] = R"(#version 300 es +void main() { + for (highp int i = 0; i < 100; i++) { i = 0; } +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + if (!getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + // One occurrence for defining |loopForwardProgress()|, and one call in the loop. + verifyCountInTranslation(GL_FRAGMENT_SHADER, "loopForwardProgress", 1 + 1); + } +} + +// Test that loopForwardProgress() is inserted when nested for loops are infinite loops. +TEST_P(GLSLOutputMSLTest_EnsureLoopForwardProgress, InfiniteNestedFor) +{ + constexpr char kFS[] = R"(#version 300 es +void main() { + for (highp int i = 0; i < 100; i++) + { + for (highp int j = 0; j < 100; j++) + { + j = 0; + } + i = 0; + } +})"; + compileShader(GL_FRAGMENT_SHADER, kFS); + if (!getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + // One occurrence for defining |loopForwardProgress()|, and one call in each loop. + verifyCountInTranslation(GL_FRAGMENT_SHADER, "loopForwardProgress", 2 + 1); + } +} + +// Test that loopForwardProgress() is not inserted when the for loop is not an infinite loop, +// testing various tricky loops. +TEST_P(GLSLOutputMSLTest_EnsureLoopForwardProgress, FiniteFors) +{ + const char kShaderPrefix[] = R"(#version 300 es +precision highp int; +uniform int a; +uniform uint b; +void main() { + +)"; + const char kShaderSuffix[] = "}\n"; + const char *kTests[]{"int i = 101; for (; i < 10; i++) { }", + "int i = 101; for (; i < 10; i+=1) { }", + "int i = 101; for (; i < 10; i-=1) { }", + "for (int i = 0; i < 10; i++) { }", + "for (int i = 0; i < a; i++) { }", + "for (int i = 0; i < 100000/2; ++i) { }", + "for (uint i = 0u; i < 10u; i++) { }", + "for (uint i = 0u; i < b; i++) { }", + "for (uint i = 0u; i < 100000u/2u; ++i) { }", + "for (uint i = 0u; i < 4294967295u; ++i) { }", + "for (uint i = 10u; i > 1u+3u ; --i) { }", + "const int z = 7; for (int i = 0; i < z; i++) { }", + "for (int i = 0; i < 10; i++) { for (int j = 0; j < 1000; ++j) { }}"}; + + for (const char *test : kTests) + { + std::string shader = (std::stringstream() << kShaderPrefix << test << kShaderSuffix).str(); + compileShader(GL_FRAGMENT_SHADER, shader.c_str()); + if (!getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + verifyIsNotInTranslation(GL_FRAGMENT_SHADER, "loopForwardProgress"); + } + } +} + +// Test that loopForwardProgress() is inserted when the for loop is an infinite loop, +// testing various tricky loops. +TEST_P(GLSLOutputMSLTest_EnsureLoopForwardProgress, InfiniteFors) +{ + const char kShaderPrefix[] = R"(#version 300 es +precision highp int; +uniform int a; +uniform uint b; +void main() { + +)"; + const char kShaderSuffix[] = "}\n"; + const char *kTests[]{"for (;;) { }", + "for (bool b = true; b; b = false) { }", + "for (int i = 0; i < 10;) { }", + "int i = 101; for (; i < 10; i+=2) { }", + "int i = 101; for (; i < 10; i-=2) { }", + "int z = 7; for (int i = 0; i < z; i++) { }", + "for (int i = 0; i < 10; i++) { i++; }", + "for (int i = 0; i < 10;) { i++; }", + "for (int i = 0; i < a/2; i++) { }", + "for (int i = 0; float(i) < 10e10; ++i) { }", + "for (int i = 0; i < 10; i++) { for (int j = 0; j < 1000; ++i) { }}", + "for (int i = 0; i != 1; i+=2) { }"}; + + for (const char *test : kTests) + { + std::string shader = (std::stringstream() << kShaderPrefix << test << kShaderSuffix).str(); + compileShader(GL_FRAGMENT_SHADER, shader.c_str()); + if (!getEGLWindow()->isFeatureEnabled(Feature::UseIr)) + { + verifyIsInTranslation(GL_FRAGMENT_SHADER, "loopForwardProgress"); + } + } +} +} // namespace + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLOutputGLSLTest); +ANGLE_INSTANTIATE_TEST(GLSLOutputGLSLTest, ES2_OPENGL(), ES2_OPENGLES()); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLOutputGLSLTest_ES3); +ANGLE_INSTANTIATE_TEST(GLSLOutputGLSLTest_ES3, ES3_OPENGL(), ES3_OPENGLES()); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLGLSLOutputGLSLTest); +ANGLE_INSTANTIATE_TEST(WebGLGLSLOutputGLSLTest, ES2_OPENGL(), ES2_OPENGLES()); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLOutputGLSLTest); +ANGLE_INSTANTIATE_TEST(WebGL2GLSLOutputGLSLTest, ES3_OPENGL(), ES3_OPENGLES()); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLOutputGLSLTest_InitShaderVariables); +ANGLE_INSTANTIATE_TEST(GLSLOutputGLSLTest_InitShaderVariables, + ES2_OPENGL().enable(Feature::ForceInitShaderVariables), + ES2_OPENGLES().enable(Feature::ForceInitShaderVariables)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLOutputGLSLVerifyIRUseTest); +ANGLE_INSTANTIATE_TEST(GLSLOutputGLSLVerifyIRUseTest, + ES2_OPENGL(), + ES2_OPENGLES(), + ES2_OPENGL().disable(Feature::UseIr), + ES2_OPENGLES().disable(Feature::UseIr)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLOutputMSLTest_EnsureLoopForwardProgress); +ANGLE_INSTANTIATE_TEST(GLSLOutputMSLTest_EnsureLoopForwardProgress, + ES3_METAL().enable(Feature::EnsureLoopForwardProgress)); diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp index 0141830644f..5fd384635eb 100644 --- a/src/tests/gl_tests/GLSLTest.cpp +++ b/src/tests/gl_tests/GLSLTest.cpp @@ -4,8 +4,13 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" +#include "test_utils/angle_test_configs.h" #include "test_utils/gl_raii.h" #include "util/shader_utils.h" @@ -534,6 +539,9 @@ class GLSLTestNoValidation : public GLSLTest GLSLTestNoValidation() { setNoErrorEnabled(true); } }; +class GLSLTest_ClampPointSize : public GLSLTest +{}; + class GLSLTest_ES3 : public GLSLTest {}; @@ -550,22 +558,227 @@ class GLSLTest_ES3_InitShaderVariables : public GLSLTest class GLSLTest_ES31_InitShaderVariables : public GLSLTest {}; -std::string BuildBigInitialStackShader(int length) +// Selecting a field of a vector that's the result of dynamic indexing a constant array should work. +TEST_P(GLSLTest_ES3, ShaderSelectingFieldOfVectorIndexedFromArray) { - std::string result; - result += "void main() { \n"; - for (int i = 0; i < length; i++) - { - result += " if (true) { \n"; - } - result += " int temp; \n"; - for (int i = 0; i <= length; i++) - { - result += "} \n"; - } - return result; + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform int i; + void main() { + float f = vec2[1](vec2(0.5, 0.1))[i].x; + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 127, 127), 1); + ASSERT_GL_NO_ERROR(); +} + +// Passing an array into a function and then passing a value from that array into another function +// should work. This is a regression test for a bug where the mangled name of a TType was not +// properly updated when determining the type resulting from array indexing. +TEST_P(GLSLTest, ArrayValueFromFunctionParameterAsParameter) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform float u; + float foo(float f) { return f * 2.0 + 0.1; } + float bar(float[2] f) { return foo(f[0]); } + void main() { + float arr[2]; + arr[0] = u; + gl_FragColor = vec4(bar(arr)); + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(26, 26, 26, 26), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that vector field selection from a value taken from an array constructor is accepted as a +// constant expression. +TEST_P(GLSLTest_ES3, FieldSelectionFromVectorArrayConstructorIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float f = vec2[1](vec2(0.5, 1.0))[0].x; + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 127, 127), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that structure field selection from a value taken from an array constructor is accepted as a +// constant expression. +TEST_P(GLSLTest_ES3, FieldSelectionFromStructArrayConstructorIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + struct S { float member; }; + void main() { + const float f = S[1](S(0.5))[0].member; + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 127, 127), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that a reference to a const array is accepted as a constant expression. +TEST_P(GLSLTest_ES3, ArraySymbolIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float[2] arr = float[2](0.5, 1.0); + const float f = arr[0]; + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 127, 127), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that using an array constructor in a parameter to a built-in function is accepted as a +// constant expression. +TEST_P(GLSLTest_ES3, BuiltInFunctionAppliedToArrayConstructorIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float f = sin(float[2](0.5, 1.0)[0]); + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(122, 122, 122, 122), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that using an array constructor in a parameter to a built-in function is accepted as a +// constant expression. +TEST_P(GLSLTest_ES3, BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float f = pow(1.0, float[2](0.5, 1.0)[0]); + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + ASSERT_GL_NO_ERROR(); +} + +// Test that using an array constructor in a parameter to a constructor is accepted as a constant +// expression. +TEST_P(GLSLTest_ES3, ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const vec2 f = vec2(1.0, float[2](0.5, 1.0)[0]); + my_FragColor = vec4(f.x); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + ASSERT_GL_NO_ERROR(); +} + +// Test that using an array constructor in an operand of the ternary selection operator is accepted +// as a constant expression. +TEST_P(GLSLTest_ES3, TernaryOperatorAppliedToArrayConstructorIsConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float f = true ? float[2](0.5, 1.0)[0] : 1.0; + my_FragColor = vec4(f); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 128), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that a shader passing a struct into a constructor of array of structs with 1 element works. +TEST_P(GLSLTest_ES3, SingleStructArrayConstructor) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform float u; + struct S { float member; }; + void main() + { + S[1] sarr = S[1](S(u + 0.5)); + my_FragColor = vec4(sarr[0].member); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 128), 1); + ASSERT_GL_NO_ERROR(); +} + +// Built-in functions can be overloaded in ESSL 1.00. +TEST_P(GLSLTest, ESSL100BuiltInFunctionOverload) +{ + constexpr char kFS[] = R"(precision mediump float; + int sin(int x) + { + return int(sin(float(x))); + } + void main() { + gl_FragColor = vec4(sin(0.5)); + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(122, 122, 122, 122), 1); + ASSERT_GL_NO_ERROR(); } +// Multiplying a matrix with 2 columns and 4 rows with a 2x2 matrix should work. +TEST_P(GLSLTest_ES3, CompoundMultiplyMatrixValidNonSquareDimensions) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + mat2x4 foo = mat2x4(0.25); + foo *= mat2x2(4.0); + my_FragColor = vec4(foo); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 0, 0)); + ASSERT_GL_NO_ERROR(); +} // Tests a shader from conformance.olges/GL/build/build_017_to_024 // This shader uses chained assign-equals ops with swizzle, often reusing the same variable // as part of a swizzle. @@ -592,6 +805,29 @@ TEST_P(GLSLTest, SwizzledChainedAssignIncrement) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(75, 75, 38, 38)); } +// Same test as above without unary increments. +TEST_P(GLSLTest, SwizzledChainedAssign) +{ + constexpr char kFS[] = + R"( + precision mediump float; + void main() { + vec2 v = vec2(1,5); + // at the end of next statement, values in + // v.x = 12, v.y = 12 + v.xy += v.yx += v.xy; + // v1 and v2, both are initialized with (12,12) + vec2 v1 = v, v2 = v; + v1.xy += v2.yx += (v.xy) += 1.0; // v1 = 37, v2 = 25 each + gl_FragColor = vec4(v1,v2)/255.; // 37, 37, 25, 25 + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(37, 37, 25, 25)); +} + TEST_P(GLSLTest, NamelessScopedStructs) { constexpr char kFS[] = R"(precision mediump float; @@ -1962,291 +2198,87 @@ TEST_P(GLSLTest, InvariantAllBoth) EXPECT_EQ(0u, program); } -// Verify that using a struct as both invariant and non-invariant output works. -TEST_P(GLSLTest_ES31, StructBothInvariantAndNot) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); - - constexpr char kVS[] = R"(#version 310 es -#extension GL_EXT_shader_io_blocks : require - -struct S -{ - vec4 s; -}; - -out Output -{ - vec4 x; - invariant S s; -}; - -out S s2; - -void main(){ - x = vec4(0); - s.s = vec4(1); - s2.s = vec4(2); - S s3 = s; - s.s = s3.s; -})"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} - -// Verify that using maximum size as atomic counter offset results in compilation failure. -TEST_P(GLSLTest_ES31, CompileWithMaxAtomicCounterOffsetFails) +// Verify that using invariant(all) in both shaders fails in ESSL 3.00. +TEST_P(GLSLTest_ES3, InvariantAllBoth) { - GLint maxSize; - glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &maxSize); - - std::ostringstream srcStream; - srcStream << "#version 310 es\n" - << "layout(location = 0) out uvec4 color;\n" - << "layout(binding = 0, offset = " << maxSize << ") uniform atomic_uint a_counter;\n" - << "void main() {\n" - << "color = uvec4(atomicCounterIncrement(a_counter)); \n" - << "}"; - std::string fsStream = srcStream.str(); - const char *strFS = fsStream.c_str(); - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, strFS); - EXPECT_EQ(0u, shader); -} + constexpr char kFS[] = + "#version 300 es\n" + "#pragma STDGL invariant(all)\n" + "precision mediump float;\n" + "in float v_varying;\n" + "out vec4 my_FragColor;\n" + "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnFloat) -{ constexpr char kVS[] = - "varying float v_varying;\n" - "float f() { if (v_varying > 0.0) return 1.0; }\n" - "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n"; + "#version 300 es\n" + "#pragma STDGL invariant(all)\n" + "in vec4 a_position;\n" + "out float v_varying;\n" + "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); + GLuint program = CompileProgram(kVS, kFS); + EXPECT_EQ(0u, program); } -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnVec2) +// Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00. +TEST_P(GLSLTest, InvariantAllIn) { - constexpr char kVS[] = + constexpr char kFS[] = + "#pragma STDGL invariant(all)\n" + "precision mediump float;\n" "varying float v_varying;\n" - "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n" - "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n"; - - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); -} + "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnVec3) -{ constexpr char kVS[] = + "attribute vec4 a_position;\n" "varying float v_varying;\n" - "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n" - "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n"; + "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); + GLuint program = CompileProgram(kVS, kFS); EXPECT_NE(0u, program); } -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnVec4) +// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00. +TEST_P(GLSLTest_ES3, InvariantAllIn) { - constexpr char kVS[] = - "varying float v_varying;\n" - "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n" - "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n"; - - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); -} + constexpr char kFS[] = + "#version 300 es\n" + "#pragma STDGL invariant(all)\n" + "precision mediump float;\n" + "in float v_varying;\n" + "out vec4 my_FragColor;\n" + "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnIVec4) -{ constexpr char kVS[] = - "varying float v_varying;\n" - "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n" - "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n"; + "#version 300 es\n" + "in vec4 a_position;\n" + "out float v_varying;\n" + "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); + GLuint program = CompileProgram(kVS, kFS); + EXPECT_EQ(0u, program); } -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnMat4) +// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00. +TEST_P(GLSLTest, InvariantAllOut) { - constexpr char kVS[] = + constexpr char kFS[] = + "precision mediump float;\n" "varying float v_varying;\n" - "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n" - "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n"; - - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); -} + "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; -// Verify that functions without return statements still compile -TEST_P(GLSLTest, MissingReturnStruct) -{ constexpr char kVS[] = + "#pragma STDGL invariant(all)\n" + "attribute vec4 a_position;\n" "varying float v_varying;\n" - "struct s { float a; int b; vec2 c; };\n" - "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n" - "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n"; + "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); + GLuint program = CompileProgram(kVS, kFS); + EXPECT_EQ(0u, program); } -// Verify that functions without return statements still compile -TEST_P(GLSLTest_ES3, MissingReturnArray) -{ - constexpr char kVS[] = - "#version 300 es\n" - "in float v_varying;\n" - "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n" - "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n"; - - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Verify that functions without return statements still compile -TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs) -{ - constexpr char kVS[] = - "#version 300 es\n" - "in float v_varying;\n" - "struct s { float a; int b; vec2 c; };\n" - "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, " - "vec2(1.0, 1.0))); } }\n" - "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n"; - - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Verify that functions without return statements still compile -TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays) -{ - // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV) - ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); - - constexpr char kVS[] = - "#version 300 es\n" - "in float v_varying;\n" - "struct s { float a[2]; int b[2]; vec2 c[2]; };\n" - "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1)," - "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n" - "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n"; - - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Verify that non-const index used on an array returned by a function compiles -TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex) -{ - constexpr char kVS[] = R"(#version 300 es -in float v_varying; -struct s { float a; int b; vec2 c; }; -s[2] f() -{ - return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0))); -} -void main() -{ - gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1); -})"; - - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Verify that using invariant(all) in both shaders fails in ESSL 3.00. -TEST_P(GLSLTest_ES3, InvariantAllBoth) -{ - constexpr char kFS[] = - "#version 300 es\n" - "#pragma STDGL invariant(all)\n" - "precision mediump float;\n" - "in float v_varying;\n" - "out vec4 my_FragColor;\n" - "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; - - constexpr char kVS[] = - "#version 300 es\n" - "#pragma STDGL invariant(all)\n" - "in vec4 a_position;\n" - "out float v_varying;\n" - "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - - GLuint program = CompileProgram(kVS, kFS); - EXPECT_EQ(0u, program); -} - -// Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00. -TEST_P(GLSLTest, InvariantAllIn) -{ - constexpr char kFS[] = - "#pragma STDGL invariant(all)\n" - "precision mediump float;\n" - "varying float v_varying;\n" - "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; - - constexpr char kVS[] = - "attribute vec4 a_position;\n" - "varying float v_varying;\n" - "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - - GLuint program = CompileProgram(kVS, kFS); - EXPECT_NE(0u, program); -} - -// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00. -TEST_P(GLSLTest_ES3, InvariantAllIn) -{ - constexpr char kFS[] = - "#version 300 es\n" - "#pragma STDGL invariant(all)\n" - "precision mediump float;\n" - "in float v_varying;\n" - "out vec4 my_FragColor;\n" - "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; - - constexpr char kVS[] = - "#version 300 es\n" - "in vec4 a_position;\n" - "out float v_varying;\n" - "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - - GLuint program = CompileProgram(kVS, kFS); - EXPECT_EQ(0u, program); -} - -// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00. -TEST_P(GLSLTest, InvariantAllOut) -{ - constexpr char kFS[] = - "precision mediump float;\n" - "varying float v_varying;\n" - "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n"; - - constexpr char kVS[] = - "#pragma STDGL invariant(all)\n" - "attribute vec4 a_position;\n" - "varying float v_varying;\n" - "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; - - GLuint program = CompileProgram(kVS, kFS); - EXPECT_EQ(0u, program); -} - -// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00. -TEST_P(GLSLTest_ES3, InvariantAllOut) +// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00. +TEST_P(GLSLTest_ES3, InvariantAllOut) { // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader // for varyings which are invariant in vertex shader, @@ -2512,170 +2544,6 @@ TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue)); } -// Verify shader source with a fixed length that is less than the null-terminated length will -// compile. -TEST_P(GLSLTest, FixedShaderLength) -{ - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz"; - const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage; - const char *sourceArray[1] = {source.c_str()}; - GLint lengths[1] = {static_cast(source.length() - appendGarbage.length())}; - glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Verify that a negative shader source length is treated as a null-terminated length. -TEST_P(GLSLTest, NegativeShaderLength) -{ - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {essl1_shaders::fs::Red()}; - GLint lengths[1] = {-10}; - glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Check that having an invalid char after the "." doesn't cause an assert. -TEST_P(GLSLTest, InvalidFieldFirstChar) -{ - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - const char *source = "void main() {vec4 x; x.}"; - glShaderSource(shader, 1, &source, 0); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_EQ(0, compileResult); -} - -// Verify that a length array with mixed positive and negative values compiles. -TEST_P(GLSLTest, MixedShaderLengths) -{ - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[] = { - "void main()", - "{", - " gl_FragColor = vec4(0, 0, 0, 0);", - "}", - }; - GLint lengths[] = { - -10, - 1, - static_cast(strlen(sourceArray[2])), - -1, - }; - ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths)); - - glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Verify that zero-length shader source does not affect shader compilation. -TEST_P(GLSLTest, ZeroShaderLength) -{ - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[] = { - "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm", - }; - GLint lengths[] = { - 0, 0, -1, 0, 0, - }; - ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths)); - - glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Tests that bad index expressions don't crash ANGLE's translator. -// https://code.google.com/p/angleproject/issues/detail?id=857 -TEST_P(GLSLTest, BadIndexBug) -{ - constexpr char kFSSourceVec[] = - "precision mediump float;\n" - "uniform vec4 uniformVec;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(uniformVec[int()]);\n" - "}"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec); - EXPECT_EQ(0u, shader); - - if (shader != 0) - { - glDeleteShader(shader); - } - - constexpr char kFSSourceMat[] = - "precision mediump float;\n" - "uniform mat4 uniformMat;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(uniformMat[int()]);\n" - "}"; - - shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat); - EXPECT_EQ(0u, shader); - - if (shader != 0) - { - glDeleteShader(shader); - } - - constexpr char kFSSourceArray[] = - "precision mediump float;\n" - "uniform vec4 uniformArray;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(uniformArray[int()]);\n" - "}"; - - shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray); - EXPECT_EQ(0u, shader); - - if (shader != 0) - { - glDeleteShader(shader); - } -} - -// Test that structs defined in uniforms are translated correctly. -TEST_P(GLSLTest, StructSpecifiersUniforms) -{ - constexpr char kFS[] = R"(precision mediump float; - -uniform struct S { float field; } s; - -void main() -{ - gl_FragColor = vec4(1, 0, 0, 1); - gl_FragColor.a += s.field; -})"; - - GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS); - EXPECT_NE(0u, program); -} - // Test that structs declaration followed directly by an initialization is translated correctly. TEST_P(GLSLTest, StructWithInitializer) { @@ -2994,24 +2862,6 @@ TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded) CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false); } -// Test compiling shaders using the GL_EXT_shader_texture_lod extension -TEST_P(GLSLTest, TextureLOD) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod")); - - constexpr char kFS[] = - "#extension GL_EXT_shader_texture_lod : require\n" - "uniform sampler2D u_texture;\n" - "void main() {\n" - " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, " - "0.0));\n" - "}\n"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - ASSERT_NE(0u, shader); - glDeleteShader(shader); -} - // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte // function calls to use them in vertex shaders. http://anglebug.com/42262136 TEST_P(GLSLTest, TextureLODRewriteInVertexShader) @@ -3126,115 +2976,33 @@ TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers) EXPECT_PIXEL_COLOR_EQ(0, 0, expected); } -// Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow -// extension pragmas later -TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks) +// Test that constructing matrices from non-float types works. +TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat) { - constexpr const char *kFS = R"( -#if __VERSION__ >= 300 - inout mediump vec4 fragData; -#else - #extension GL_EXT_shader_texture_lod :enable -#endif + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 color; + +uniform int i; +uniform uint u; +uniform bool b; void main() { -} - )"; + mat3x2 mi = mat3x2(i); + mat4 mu = mat4(u); + mat2x4 mb = mat2x4(b); - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(0u, shader); -} + mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b)); -// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in -// HLSL). -TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2) -{ - constexpr char kVS[] = - "#version 300 es\n" - "precision highp float;\n" - "in vec4 a_vec;\n" - "in mat2 a_mat;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(a_vec) + vec4(a_mat);\n" - "}"; + color = vec4(mi[0][0] == -123.0 ? 1 : 0, + mu[2][2] == 456.0 ? 1 : 0, + mb[1][1] == 1.0 ? 1 : 0, + m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0); +})"; - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated. -// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between -// the function signatures in this case. -TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3) -{ - constexpr char kVS[] = - "#version 300 es\n" - "precision highp float;\n" - "in mat3x2 a_matA;\n" - "in mat2x3 a_matB;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(a_matA) + vec4(a_matB);\n" - "}"; - - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL). -TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2) -{ - constexpr char kVS[] = - "#version 300 es\n" - "precision highp float;\n" - "in vec4 a_vec;\n" - "in mat2 a_mat;\n" - "vec4 foo(vec4 a)\n" - "{\n" - " return a;\n" - "}\n" - "vec4 foo(mat2 a)\n" - "{\n" - " return vec4(a[0][0]);\n" - "}\n" - "void main()\n" - "{\n" - " gl_Position = foo(a_vec) + foo(a_mat);\n" - "}"; - - GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// Test that constructing matrices from non-float types works. -TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -out vec4 color; - -uniform int i; -uniform uint u; -uniform bool b; - -void main() -{ - mat3x2 mi = mat3x2(i); - mat4 mu = mat4(u); - mat2x4 mb = mat2x4(b); - - mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b)); - - color = vec4(mi[0][0] == -123.0 ? 1 : 0, - mu[2][2] == 456.0 ? 1 : 0, - mb[1][1] == 1.0 ? 1 : 0, - m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0); -})"; - - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); - glUseProgram(program); + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); GLint iloc = glGetUniformLocation(program, "i"); GLint uloc = glGetUniformLocation(program, "u"); @@ -3386,6 +3154,79 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); } +// Test that textureLod in a discontinuous loop does not generate HLSL loop unrolling errors. +TEST_P(GLSLTest_ES3, TextureLODShadowSamplerInDiscontinuousLoop) +{ + constexpr char kVS[] = + R"(#version 300 es +out float vLoop; +void main() +{ + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + vLoop = 10.0; +})"; + + constexpr char kFS0[] = + R"(#version 300 es +precision highp float; +precision highp sampler2DShadow; + +uniform sampler2DShadow shadowMap; +in float vLoop; +out vec4 fragColor; + +void main() +{ + int loopCount = int(vLoop); /* Each fragment may have a different value here. + This makes it invalid to use gradient functions + inside the loop! */ + + float shadowSum = 0.0; + int i = 0; + while (i < loopCount) + { + float x = float(i) + 1.0; /* Makes sure sample operation cannot be optimized + to be outside of the loop */ + shadowSum += textureLod(shadowMap, vec3(1.0 / x, 1.0 / x, 0.5), 0.0); + ++i; + } + + fragColor = vec4(shadowSum, shadowSum, shadowSum, 1.0); +})"; + + ANGLE_GL_PROGRAM(program0, kVS, kFS0); + ASSERT_TRUE(program0.valid()); + + constexpr char kFS1[] = + R"(#version 300 es +precision highp float; +precision highp sampler2DShadow; + +uniform sampler2DShadow u_testSampler; + +out vec4 fragOut4f; + +void main() { + float a = texture(u_testSampler, vec3(10.0, 10.0, 0.5)); + for(;;) { + if (a != 10.0) { + a = textureLod(u_testSampler, vec3(4.0, 4.0, 0.1), 0.0); + break; + } + if (a != 4.0) { + a = textureLod(u_testSampler, vec3(10.0, 10.0, 0.4), 0.0); + break; + } + fragOut4f = vec4(0.0); + return; + } + fragOut4f = vec4(a); +})"; + + ANGLE_GL_PROGRAM(program1, kVS, kFS1); + ASSERT_TRUE(program1.valid()); +} + // Test that == and != for structs and array types work. TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator) { @@ -3469,73 +3310,6 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); } -// Test that an user-defined function with a large number of float4 parameters doesn't fail due to -// the function name being too long. -TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters) -{ - std::stringstream vertexShaderStream; - // Note: SPIR-V doesn't allow more than 255 parameters to a function. - const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u; - - vertexShaderStream << "#version 300 es\n" - "precision highp float;\n" - "in vec4 a_vec;\n" - "vec4 lotsOfVec4Parameters("; - for (unsigned int i = 0; i < paramCount - 1; ++i) - { - vertexShaderStream << "vec4 a" << i << ", "; - } - vertexShaderStream << "vec4 aLast)\n" - "{\n" - " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n"; - for (unsigned int i = 0; i < paramCount - 1; ++i) - { - vertexShaderStream << " sum += a" << i << ";\n"; - } - vertexShaderStream << " sum += aLast;\n" - " return sum;\n " - "}\n" - "void main()\n" - "{\n" - " gl_Position = lotsOfVec4Parameters("; - for (unsigned int i = 0; i < paramCount - 1; ++i) - { - vertexShaderStream << "a_vec, "; - } - vertexShaderStream << "a_vec);\n" - "}"; - - GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - -// This test was written specifically to stress DeferGlobalInitializers AST transformation. -// Test a shader where a global constant array is initialized with an expression containing array -// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to -// be handled in a way that doesn't generate statements in the global scope in HLSL output. -// Also includes multiple array initializers in one declaration, where only the second one has -// array indexing. This makes sure that the qualifier for the declaration is set correctly if -// transformations are applied to the declaration also in the case of ESSL output. -TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing) -{ - // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260423 is fixed - ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES()); - - constexpr char kFS[] = - "#version 300 es\n" - "precision highp float;\n" - "out vec4 my_FragColor;\n" - "const highp float f[2] = float[2](0.1, 0.2);\n" - "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n" - "void main()\n" - "{\n" - " my_FragColor = vec4(h[1]);\n" - "}"; - - GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS); - EXPECT_NE(0u, program); -} - // Test that constant global matrix array with an initializer compiles. TEST_P(GLSLTest_ES3, InitConstantMatrixArray) { @@ -3556,75 +3330,26 @@ TEST_P(GLSLTest_ES3, InitConstantMatrixArray) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that index-constant sampler array indexing is supported. -TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing) -{ - constexpr char kFS[] = - "precision mediump float;\n" - "uniform sampler2D uni[2];\n" - "\n" - "float zero(int x)\n" - "{\n" - " return float(x) - float(x);\n" - "}\n" - "\n" - "void main()\n" - "{\n" - " vec4 c = vec4(0,0,0,0);\n" - " for (int ii = 1; ii < 3; ++ii) {\n" - " if (c.x > 255.0) {\n" - " c.x = 255.0 + zero(ii);\n" - " break;\n" - " }\n" - // Index the sampler array with a predictable loop index (index-constant) as opposed to - // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions, - // without an extension. - " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n" - " }\n" - " gl_FragColor = c;\n" - "}"; - - GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS); - EXPECT_NE(0u, program); -} - -// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the -// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't -// want to test its behavior, so don't use any varyings. -TEST_P(GLSLTest, PragmaDirective) -{ - constexpr char kVS[] = - "#pragma STDGL invariant(all)\n" - "void main()\n" - "{\n" - " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" - "}\n"; - - GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red()); - EXPECT_NE(0u, program); -} - // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9). // The function call that returns the array needs to be evaluated after ++j for the expression to // return the correct value (true). TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray) { - constexpr char kFS[] = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor; \n" - "int[2] func(int param) {\n" - " return int[2](param, param);\n" - "}\n" - "void main() {\n" - " int a[2]; \n" - " for (int i = 0; i < 2; ++i) {\n" - " a[i] = 1;\n" - " }\n" - " int j = 0; \n" - " bool result = ((++j), (a == func(j)));\n" - " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 my_FragColor; +int[2] func(int param) { + return int[2](param, param); +} +void main() { + int a[2]; + for (int i = 0; i < 2; ++i) { + a[i] = 1; + } + int j = 0; + bool result = ((++j), (a == func(j))); + my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0); +})"; GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS); ASSERT_NE(0u, program); @@ -3639,15 +3364,14 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray) // correct value (true). TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit) { - constexpr char kFS[] = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor; \n" - "void main() {\n" - " int j = 0; \n" - " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n" - " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 my_FragColor; +void main() { + int j = 0; + bool result = ((++j), (j == 1 ? true : (++j == 3))); + my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0); +})"; GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS); ASSERT_NE(0u, program); @@ -3661,22 +3385,21 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit) // Indexing the vector needs to be evaluated after func() for the right result. TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue) { - constexpr char kFS[] = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform int u_zero;\n" - "int sideEffectCount = 0;\n" - "float func() {\n" - " ++sideEffectCount;\n" - " return -1.0;\n" - "}\n" - "void main() {\n" - " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n" - " float f = (func(), (++v[u_zero + sideEffectCount]));\n" - " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n" - " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 my_FragColor; +uniform int u_zero; +int sideEffectCount = 0; +float func() { + ++sideEffectCount; + return -1.0; +} +void main() { + vec4 v = vec4(0.0, 2.0, 4.0, 6.0); + float f = (func(), (++v[u_zero + sideEffectCount])); + bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1; + my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0); +})"; GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS); ASSERT_NE(0u, program); @@ -3691,19 +3414,17 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValu // See http://anglebug.com/42260376 TEST_P(GLSLTest, RenderTrisWithPointCoord) { - constexpr char kVS[] = - "attribute vec2 aPosition;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(aPosition, 0, 1);\n" - " gl_PointSize = 1.0;\n" - "}"; - constexpr char kFS[] = - "void main()\n" - "{\n" - " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n" - " gl_FragColor = vec4(0, 1, 0, 1);\n" - "}"; + constexpr char kVS[] = R"(attribute vec2 aPosition; +void main() +{ + gl_Position = vec4(aPosition, 0, 1); + gl_PointSize = 1.0; +})"; + constexpr char kFS[] = R"(void main() +{ + gl_FragColor = vec4(gl_PointCoord.xy, 0, 1); + gl_FragColor = vec4(0, 1, 0, 1); +})"; ANGLE_GL_PROGRAM(prog, kVS, kFS); drawQuad(prog, "aPosition", 0.5f); @@ -3716,18 +3437,17 @@ TEST_P(GLSLTest, NestedPowStatements) // https://crbug.com/1127866 - possible NVIDIA driver issue ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows()); - constexpr char kFS[] = - "precision mediump float;\n" - "float func(float v)\n" - "{\n" - " float f1 = pow(v, 2.0);\n" - " return pow(f1 + v, 2.0);\n" - "}\n" - "void main()\n" - "{\n" - " float v = func(2.0);\n" - " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n" - "}"; + constexpr char kFS[] = R"(precision mediump float; +float func(float v) +{ + float f1 = pow(v, 2.0); + return pow(f1 + v, 2.0); +} +void main() +{ + float v = func(2.0); + gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); @@ -3808,15 +3528,14 @@ void main() // Test that -float calculation is correct. TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat) { - constexpr char kFS[] = - "#version 300 es\n" - "out highp vec4 o_color;\n" - "void main() {\n" - " highp float f = -1.0;\n" - " // atan(tan(0.5), -f) should be 0.5.\n" - " highp float v = atan(tan(0.5), -f);\n" - " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +out highp vec4 o_color; +void main() { + highp float f = -1.0; + // atan(tan(0.5), -f) should be 0.5. + highp float v = atan(tan(0.5), -f); + o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS); drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f); @@ -3826,16 +3545,15 @@ TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat) // Test that atan(vec2, vec2) calculation is correct. TEST_P(GLSLTest_ES3, AtanVec2) { - constexpr char kFS[] = - "#version 300 es\n" - "out highp vec4 o_color;\n" - "void main() {\n" - " highp float f = 1.0;\n" - " // atan(tan(0.5), f) should be 0.5.\n" - " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n" - " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : " - "vec4(1, 0, 0, 1);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +out highp vec4 o_color; +void main() { + highp float f = 1.0; + // atan(tan(0.5), f) should be 0.5. + highp vec2 v = atan(vec2(tan(0.5)), vec2(f)); + o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? + vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS); drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f); @@ -3845,32 +3563,30 @@ TEST_P(GLSLTest_ES3, AtanVec2) // Convers a bug with the unary minus operator on signed integer workaround. TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt) { - constexpr char kVS[] = - "#version 300 es\n" - "in highp vec4 position;\n" - "out mediump vec4 v_color;\n" - "uniform int ui_one;\n" - "uniform int ui_two;\n" - "uniform int ui_three;\n" - "void main() {\n" - " int s[3];\n" - " s[0] = ui_one;\n" - " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two - " s[2] = ui_three;\n" - " int result = 0;\n" - " for (int i = 0; i < ui_three; i++) {\n" - " result += s[i];\n" - " }\n" - " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n" - " gl_Position = position;\n" - "}\n"; - constexpr char kFS[] = - "#version 300 es\n" - "in mediump vec4 v_color;\n" - "layout(location=0) out mediump vec4 o_color;\n" - "void main() {\n" - " o_color = v_color;\n" - "}\n"; + constexpr char kVS[] = R"(#version 300 es +in highp vec4 position; +out mediump vec4 v_color; +uniform int ui_one; +uniform int ui_two; +uniform int ui_three; +void main() { + int s[3]; + s[0] = ui_one; + s[1] = -(-(-ui_two + 1) + 1); // s[1] = -ui_two + s[2] = ui_three; + int result = 0; + for (int i = 0; i < ui_three; i++) { + result += s[i]; + } + v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); + gl_Position = position; +})"; + constexpr char kFS[] = R"(#version 300 es +in mediump vec4 v_color; +layout(location=0) out mediump vec4 o_color; +void main() { + o_color = v_color; +})"; ANGLE_GL_PROGRAM(prog, kVS, kFS); @@ -3892,32 +3608,30 @@ TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt) // Convers a bug with the unary minus operator on unsigned integer workaround. TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt) { - constexpr char kVS[] = - "#version 300 es\n" - "in highp vec4 position;\n" - "out mediump vec4 v_color;\n" - "uniform uint ui_one;\n" - "uniform uint ui_two;\n" - "uniform uint ui_three;\n" - "void main() {\n" - " uint s[3];\n" - " s[0] = ui_one;\n" - " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two - " s[2] = ui_three;\n" - " uint result = 0u;\n" - " for (uint i = 0u; i < ui_three; i++) {\n" - " result += s[i];\n" - " }\n" - " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n" - " gl_Position = position;\n" - "}\n"; - constexpr char kFS[] = - "#version 300 es\n" - "in mediump vec4 v_color;\n" - "layout(location=0) out mediump vec4 o_color;\n" - "void main() {\n" - " o_color = v_color;\n" - "}\n"; + constexpr char kVS[] = R"(#version 300 es +in highp vec4 position; +out mediump vec4 v_color; +uniform uint ui_one; +uniform uint ui_two; +uniform uint ui_three; +void main() { + uint s[3]; + s[0] = ui_one; + s[1] = -(-(-ui_two + 1u) + 1u); // s[1] = -ui_two + s[2] = ui_three; + uint result = 0u; + for (uint i = 0u; i < ui_three; i++) { + result += s[i]; + } + v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); + gl_Position = position; +})"; + constexpr char kFS[] = R"(#version 300 es +in mediump vec4 v_color; +layout(location=0) out mediump vec4 o_color; +void main() { + o_color = v_color; +})"; ANGLE_GL_PROGRAM(prog, kVS, kFS); @@ -3936,28 +3650,269 @@ TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test ternaries with a void type. This is not allowed in WebGL2 (tested in +// glsl3/forbidden-operators.html) but is allowed in GLES. +TEST_P(GLSLTest_ES3, TernaryVoidType) +{ + // Most backends mishandle this shader. Some OpenGL drivers do not accept the shader either. + // The test is run only with IR. + ANGLE_SKIP_TEST_IF(!getEGLWindow()->isFeatureEnabled(Feature::UseIr)); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +uniform bool falseBool; +vec4 global; +out vec4 color; + +void f() { global = vec4(1, 0, 0, 1); } +void g() { global = vec4(0, 1, 0, 1); } +void main() { + falseBool ? f() : g(); + color = global; +})"; + + ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS); + drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + // Test a nested sequence operator with a ternary operator inside. The ternary operator is // intended to be such that it gets converted to an if statement on the HLSL backend. TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside) { // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have // its default value false. - constexpr char kFS[] = - "precision mediump float;\n" - "uniform bool keep_flop_positive;\n" - "float flop;\n" - "void main() {\n" - " flop = -1.0,\n" - " (flop *= -1.0,\n" - " keep_flop_positive ? 0.0 : flop *= -1.0),\n" - " gl_FragColor = vec4(0, -flop, 0, 1);\n" - "}"; + constexpr char kFS[] = R"(precision mediump float; +uniform bool keep_flop_positive; +float flop; +void main() { + flop = -1.0, + (flop *= -1.0, + keep_flop_positive ? 0.0 : flop *= -1.0), + gl_FragColor = vec4(0, -flop, 0, 1); +})"; ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Tests that function arguments are evaluated left to right. +// See GLSL ES 3.0 spec, 6.1.1 Function Calling Conventions: +// "All arguments are evaluated at call time, exactly once, in order, from left to right." +TEST_P(GLSLTest, FunctionArgumentEvalOrder) +{ + constexpr char kFS[] = R"( +precision mediump float; +uniform bool u; + +int outVar1, outVar2; + +void f (int arg1, int arg2) { + outVar1 = arg1; + outVar2 = arg2; +} + +void main() +{ + int a = u ? 1 : 2; // will be 2 + f (a, a++); + + // Verify that both args were 2 but a was incremented afterwards. + gl_FragColor = vec4(outVar1 == 2, outVar2 == 2, a == 3, 1); +})"; + + ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); + drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Same as FunctionArgumentEvalOrder, but with f as an overloaded function. +TEST_P(GLSLTest, FunctionArgumentEvalOrderOverloaded) +{ + constexpr char kFS[] = R"( +precision mediump float; +uniform bool u; + +int outVar1, outVar2; + +void f (in int arg1, in int arg2) { + outVar1 = arg1; + outVar2 = arg2; +} + +void f (out int arg1, in float arg2) { + arg1 = int(arg2); +} + +void main() +{ + int a = u ? 1 : 2; // will be 2 + f (a, a++); + f (a, float(a++)); // Should NOT modify `a` because the first arg is assigned the current + // value of `a` (before it is incremented as part of the side effects + // of evaluating the second argument). + + // Verify that both args were 2 but a was incremented afterwards. + gl_FragColor = vec4(outVar1 == 2, outVar2 == 2, a == 3, 1); +})"; + + ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); + drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Tests that function arguments are evaluated left to right. +TEST_P(GLSLTest, FunctionArgumentEvalOrderIncrement) +{ + constexpr char kFS[] = R"( +precision mediump float; +uniform bool u; + +int outVar1, outVar2; + +void f (int arg1, int arg2) { + outVar1 = arg1; + outVar2 = arg2; +} + +void main() +{ + int a = u ? 1 : 2; // will be 2 + f (a++, a); + + // Verify that the first arg was still 2 but its evaluation set a == 3 for the second + // argument. + gl_FragColor = vec4(outVar1 == 2, outVar2 == 3, a == 3, 1); +})"; + + ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); + drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Tests that function arguments are evaluated left to right, specifically when one argument is a +// ternary that modifies a variable used by an earlier function argument. +TEST_P(GLSLTest, TernaryModifiesVariableInSameStatement) +{ + constexpr char kFS[] = R"( +precision mediump float; +uniform bool u; + +int outVar1, outVar2; + +void f (int arg1, int arg2) { + outVar1 = arg1; + outVar2 = arg2; +} + +void main() +{ + int a = u ? 1 : 2; // will be 2 + f (a, a == 2 ? a++ : a + 1); // Ternary causes `a` to be incremented. + + // Verify that both args were 2 but a was incremented afterwards. + gl_FragColor = vec4(outVar1 == 2, outVar2 == 2, a == 3, 1); +})"; + + ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); + drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Test that short circuit doesn't evaluate out of bounds expressions. +TEST_P(GLSLTest_ES31, ShortCircuitOutOfBoundsAccess) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer")); + + // Note that the uniform doesn't need to be set, and will contain the default value of false. + constexpr char kCS[] = R"(#version 310 es +#extension GL_OES_texture_buffer : require +layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in; + +uniform bool falseValue; +uniform uint zero; + +layout(binding = 0) readonly buffer Input +{ + uint inData[]; +}; + +layout(binding = 1, std430) writeonly buffer Output +{ + uint outData[]; +}; + +layout(r32ui, binding = 0) uniform highp uimageBuffer image; + +void main() +{ + outData[0] = falseValue ? inData[123456] : 1u; + outData[1] = falseValue ? inData[~zero] : 2u; + outData[2] = falseValue ? inData[123456] : 3u; + outData[3] = !falseValue ? 4u : inData[~zero]; + outData[4] = !falseValue ? 5u : imageLoad(image, 1234567).x; + outData[5] = falseValue ? imageLoad(image, int(~zero)).x : 6u; + + bool eval6 = falseValue && bool(inData[123456]); + bool eval7 = falseValue && bool(inData[~zero]); + bool eval8 = !falseValue || bool(inData[123456]); + bool eval9 = !falseValue || bool(inData[~zero]); + bool eval10 = falseValue && bool(imageLoad(image, 1234567).x); + bool eval11 = !falseValue || bool(imageLoad(image, int(~zero)).x); + + outData[6] = eval6 ? 1234u : 7u; + outData[7] = eval7 ? 2345u : 8u; + outData[8] = eval8 ? 9u : 3456u; + outData[9] = eval9 ? 10u : 4567u; + outData[10] = eval10 ? 5678u : 11u; + outData[11] = eval11 ? 12u : 6789u; +})"; + + ANGLE_GL_COMPUTE_PROGRAM(program, kCS); + + GLBuffer input; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, input); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t), nullptr, GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input); + + constexpr std::array kInitialData = {}; + + GLBuffer output; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, output); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kInitialData), kInitialData.data(), + GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, output); + + GLBuffer imageBufferStorage; + GLTexture imageBuffer; + + glBindBuffer(GL_TEXTURE_BUFFER, imageBufferStorage); + glBufferData(GL_TEXTURE_BUFFER, sizeof(uint32_t), nullptr, GL_STATIC_DRAW); + + glBindTexture(GL_TEXTURE_BUFFER, imageBuffer); + glTexBufferEXT(GL_TEXTURE_BUFFER, GL_R32UI, imageBufferStorage); + glBindImageTexture(0, imageBuffer, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + ASSERT_GL_NO_ERROR(); + + glUseProgram(program); + glDispatchCompute(1, 1, 1); + glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + glFinish(); + + std::array readback = {}; + void *mapped = + glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitialData), GL_MAP_READ_BIT); + memcpy(readback.data(), mapped, sizeof(kInitialData)); + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + ASSERT_GL_NO_ERROR(); + + for (size_t i = 0; i < kInitialData.size(); ++i) + { + EXPECT_EQ(readback[i], i + 1) << i; + } +} + // Test that nesting ternary and short-circuitting operators work. TEST_P(GLSLTest, NestedTernaryAndShortCircuit) { @@ -3996,6 +3951,53 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); } +// Test that nesting ternary and short-circuitting operators work, but using function calls +// instead of assignments for side effects. +TEST_P(GLSLTest, NestedTernaryAndShortCircuitWithFunctionCalls) +{ + // Note that the uniform doesn't need to be set, and will contain the default value of false. + constexpr char kFS[] = R"( +precision mediump float; +uniform bool u; + +int globVar = 0; + +int f () { + globVar++; + return globVar; +} + +void main() +{ + int a = u ? 12345 : 2; // will be 2 + int b = u ? 12345 : 4; // will be 4 + int c = u ? 12345 : 0; // will be 0 + + if (a == 2 // true path is taken + ? (b == 3 // false path is taken + ? f() != 0 + : b != 0 // true + ) && ( // short-circuit evaluates RHS + f() == 1 // true, modifies globVar + || // short-circuit doesn't evaluate RHS + f() == 8 + ) + : (a == 0 && b == 0 + ? (int(f() == 2 && f() == 0)) != 0 + : (int(f() != 2 && f() != 0)) != 0)) + { + c += 15; // will execute + } + + // Verify that a is 7, b is 4 and c is 15. + gl_FragColor = vec4(a == 2, b == 4, c == 15, globVar == 1); +})"; + + ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS); + drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + // Test that uniform bvecN passed to functions work. TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions) { @@ -4076,7 +4078,6 @@ void main() { const GLuint *ptr = reinterpret_cast( glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT)); - fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]); EXPECT_FALSE(ptr[0]); EXPECT_TRUE(ptr[1]); EXPECT_FALSE(ptr[2]); @@ -4122,6 +4123,63 @@ void main() { ASSERT_GL_NO_ERROR(); } +// Tests that a vertex shader retrieving values from a 2D texture to +// use as an offset for gl_PointSize successfully compiles. +// https://issues.angleproject.org/444653099 +TEST_P(GLSLTest_ClampPointSize, MonomorphizeMainPrototypeNoCrash) +{ + constexpr char kVS[] = R"( +attribute vec2 a_texCoord; +struct Wrapper{ + sampler2D sampler; +}; +float getRedValue(Wrapper wrapper){ + return texture2D(wrapper.sampler, a_texCoord).r; +} +uniform Wrapper u_wrappedSampler; + +void main(); +void main(){ + float offset = getRedValue(u_wrappedSampler); + gl_PointSize = 10.0 + offset; + return; +} +)"; + CompileShader(GL_VERTEX_SHADER, kVS); + ASSERT_GL_NO_ERROR(); +} + +// Test that using a varying matrix is supported. +TEST_P(GLSLTest, VaryingMatrix) +{ + constexpr char kVS[] = + "uniform vec2 u_a1;\n" + "attribute vec4 a_position;\n" + "varying mat2 v_mat;\n" + "void main() {\n" + " v_mat = mat2(u_a1, 0.0, 0.0);\n" + " gl_Position = a_position;\n" + "}"; + + constexpr char kFS[] = + "precision mediump float;\n" + "varying mat2 v_mat;\n" + "void main(void)\n" + "{\n" + " gl_FragColor = vec4(v_mat[0].x, v_mat[0].y, v_mat[0].x, 1.0);\n" + "}"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + + GLint oneIndex = glGetUniformLocation(program, "u_a1"); + ASSERT_NE(-1, oneIndex); + glUseProgram(program); + glUniform2f(oneIndex, 0.25f, 0.5f); + + drawQuad(program, "a_position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 128, 63, 255), 1.0); +} + // Test that using a varying matrix array is supported. TEST_P(GLSLTest, VaryingMatrixArray) { @@ -4422,21 +4480,40 @@ TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression) ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); } +// Test that dynamic indexing of constant vectors work. +TEST_P(GLSLTest_ES3, DynamicIndexingConstantVector) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; +uniform int zero; + +void main() { + float r = vec3(1, 0.5, 0)[zero + 1]; + const vec3 c = vec3(0.1, 0.3, 0.25); + float g = c[zero + 2]; + color = vec4(r, g, 0, 1); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 63, 0, 255), 1); +} + // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works // correctly. TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue) { - constexpr char kFS[] = - "#version 300 es\n" - "precision mediump float;\n" - "out vec4 my_FragColor;\n" - "uniform int u_zero;\n" - "void main() {\n" - " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n" - " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n" - " float f = m[1][1];\n" - " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 my_FragColor; +uniform int u_zero; +void main() { + mat2 m = mat2(0.0, 0.0, 0.0, 0.0); + m[u_zero + 1][u_zero + 1] = float(u_zero + 1); + float f = m[1][1]; + my_FragColor = vec4(1.0 - f, f, 0.0, 1.0); +})"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); @@ -4546,16 +4623,45 @@ TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that reading from a swizzled vector that is dynamically indexed succeeds. -TEST_P(GLSLTest_ES3, ReadFromDynamicIndexingOfSwizzledVector) +// Test that a comma expression does not add any redundant statements +// during shader translation rewrite steps. The test will verify the +// correct color is drawn as a result of the called functions being +// executed in the correct order and only once each. +TEST_P(GLSLTest, CommaTestNoRedundantStatements) { - constexpr char kFS[] = R"(#version 300 es -precision highp float; - -uniform int index; -uniform vec4 data; - -out vec4 color; + const char kFS[] = R"( +precision mediump float; +int g = 1; +void F() { g *= 3; } +void G() { g += 5; } +void main() { + F(), G(); + if (g == 8) + { + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); + } + else + { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } +})"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test that reading from a swizzled vector that is dynamically indexed succeeds. +TEST_P(GLSLTest_ES3, ReadFromDynamicIndexingOfSwizzledVector) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; + +uniform int index; +uniform vec4 data; + +out vec4 color; void main() { color = vec4(vec4(data.x, data.y, data.z, data.w).zyxw[index], 0, 0, 1); })"; @@ -6394,74 +6500,41 @@ TEST_P(GLSLTest_ES3, NestedSamplingOperation) EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]); } -// Tests that using a constant declaration as the only statement in a for loop without curly braces -// doesn't crash. -TEST_P(GLSLTest, ConstantStatementInForLoop) +// Test that side effect in for loop expressions are retained even if loop body is empty. +TEST_P(GLSLTest, EmptyForLoopWithSideEffect) { - constexpr char kVS[] = - "void main()\n" - "{\n" - " for (int i = 0; i < 10; ++i)\n" - " const int b = 0;\n" - "}\n"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} - -// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this -// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3. -TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit) + constexpr char kFS1[] = R"(void main() { - constexpr char kVS[] = - "void main()\n" - "{\n" - " for (const int i = 0; i < 0;) {}\n" - "}\n"; + int j = 0; + for (int i = ++j; i < 1;) {} + gl_FragColor = vec4(j, 0, 0, 1); +})"; - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS1); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); -// Tests that using a constant condition guarding a discard works -// Covers a failing case in the Vulkan backend: http://anglebug.com/42265506 -TEST_P(GLSLTest_ES3, ConstantConditionGuardingDiscard) -{ - constexpr char kFS[] = R"(#version 300 es -void main() + constexpr char kFS2[] = R"(void main() { - if (true) - { - discard; - } + int i; + for (i = 0; i++ < 5;) {} + gl_FragColor = vec4(0, float(i) / 12.0, 0, 1); })"; - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} + ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), kFS2); + drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 127, 0, 255), 1); -// Tests that nesting a discard in unconditional blocks works -// Covers a failing case in the Vulkan backend: http://anglebug.com/42265506 -TEST_P(GLSLTest_ES3, NestedUnconditionalDiscards) + constexpr char kFS3[] = R"(void main() { - constexpr char kFS[] = R"(#version 300 es -out mediump vec4 c; -void main() -{ - { - c = vec4(0); - { - discard; - } - } + int i; + for (i = 0; i < 5; i++) {} + gl_FragColor = vec4(0, 0, float(i) / 10.0, 1); })"; - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); + ANGLE_GL_PROGRAM(program3, essl1_shaders::vs::Simple(), kFS3); + drawQuad(program3, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 127, 255), 1); } // Test that uninitialized local variables are initialized to 0. @@ -6854,60 +6927,80 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Tests that rewriting samplers in structs works when passed as function argument. In this test, -// the function references another struct, which is not being modified. Regression test for AST -// validation applied to a multipass transformation, where references to declarations were attempted -// to be validated without having the entire shader. In this case, the reference to S2 was flagged -// as invalid because S2's declaration was not visible. -TEST_P(GLSLTest, SamplerInStructAsFunctionArg) +// Test that nested structs with samplers work when the nested struct is not the last element. +TEST_P(GLSLTest_ES3, NestedStructWithSamplers) { - const char kFS[] = R"(precision mediump float; -struct S { sampler2D samp; bool b; }; -struct S2 { float f; }; + const char kFS[] = R"(#version 300 es +precision mediump float; -uniform S us; +struct Inner +{ + sampler2D s; + float a; +}; -float f(S s) +uniform struct Outer { - S2 s2; - s2.f = float(s.b); - return s2.f; -} + Inner i; + float b; +} u; + +out vec4 color; void main() { - gl_FragColor = vec4(f(us), 0, 0, 1); + color = texture(u.i.s, vec2(0)) + vec4(u.i.a, u.b, 0, 1); })"; - GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(fs, 0u); - ASSERT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + + GLint uniLocA = glGetUniformLocation(program, "u.i.a"); + ASSERT_NE(-1, uniLocA); + glUniform1f(uniLocA, 0.5f); + + GLint uniLocB = glGetUniformLocation(program, "u.b"); + ASSERT_NE(-1, uniLocB); + glUniform1f(uniLocB, 0.75f); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 191, 0, 255), 1); } -// Test that structs with samplers are not allowed in interface blocks. This is forbidden per -// GLES3: -// -// > Types and declarators are the same as for other uniform variable declarations outside blocks, -// > with these exceptions: -// > * opaque types are not allowed -TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock) +// Test that nested structs with samplers work when the nested struct is not the last element and +// includes nothing but samplers. +TEST_P(GLSLTest_ES3, NestedStructWithOnlySamplers) { const char kFS[] = R"(#version 300 es precision mediump float; -struct S { sampler2D samp; bool b; }; -layout(std140) uniform Buffer { S s; } buffer; +struct Inner +{ + sampler2D s; +}; + +uniform struct Outer +{ + Inner i; + float a; +} u; out vec4 color; void main() { - color = texture(buffer.s.samp, vec2(0)); + color = texture(u.i.s, vec2(0)) + vec4(u.a, 0, 0, 1); })"; - GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(fs, 0u); - ASSERT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + + GLint uniLocA = glGetUniformLocation(program, "u.a"); + ASSERT_NE(-1, uniLocA); + glUniform1f(uniLocA, 0.5f); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1); } // Tests two nameless struct uniforms. @@ -6942,29 +7035,29 @@ void main() // Test that a loop condition that has an initializer declares a variable. TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable) { - constexpr char kFS[] = - "#version 300 es\n" - "precision highp float;\n" - "out vec4 my_FragColor;\n" - "void main()\n" - "{\n" - " float i = 0.0;\n" - " while (bool foo = (i < 1.5))\n" - " {\n" - " if (!foo)\n" - " {\n" - " ++i;\n" - " }\n" - " if (i > 3.5)\n" - " {\n" - " break;\n" - " }\n" - " ++i;\n" - " }\n" - " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n" - "}\n"; + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 my_FragColor; +void main() +{ + float i = 0.0; + while (bool foo = (i < 1.5)) + { + if (!foo) + { + ++i; + } + if (i > 3.5) + { + break; + } + ++i; + } + my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0); +})"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + ASSERT_GL_NO_ERROR(); drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } @@ -7044,6 +7137,37 @@ TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment) ASSERT_GL_NO_ERROR(); } +// Test that standard derivatives work as expected with FBOs since the render target +// might have flipped viewport orientation. +TEST_P(GLSLTest, ScreenFlipCauseStandardDerivativesWrong) +{ + constexpr char kFS[] = + R"( +#extension GL_OES_standard_derivatives : enable +precision mediump float; + +void main() +{ + gl_FragColor = vec4( + dFdx(gl_FragCoord.x), + dFdy(gl_FragCoord.y), + 0.0, 1.0 + ); +} + )"; + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClearColor(0.0, 0.0, 0.0, 1.0); + ASSERT_GL_NO_ERROR(); + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow); +} + // Test that a varying struct that's not statically used in the fragment shader works. // GLSL ES 3.00.6 section 4.3.10. TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader) @@ -7269,137 +7393,311 @@ TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut) ASSERT_GL_NO_ERROR(); } -// Test that `smooth sample` and `flat sample` pass the validation. -TEST_P(GLSLTest_ES3, AliasedSampleQualifiers) +// Test that GetProgramiv with tessellation parameters generates an INVALID_OPERATION error when +// there is no tessellation shader. +TEST_P(GLSLTest_ES31, ValidateGetProgramivNoTessellationShader) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader")); constexpr char kVS[] = - R"(#version 300 es - #extension GL_OES_shader_multisample_interpolation : require + R"(#version 310 es + + precision highp float; + in vec4 inputAttribute; - smooth sample out mediump float f; - flat sample out mediump int i; void main() { - f = 1.0; - i = 1; - gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + gl_Position = inputAttribute; })"; constexpr char kFS[] = - R"(#version 300 es - #extension GL_OES_shader_multisample_interpolation : require + R"(#version 310 es + + precision highp float; + layout(location = 0) out mediump vec4 color; - smooth sample in mediump float f; - flat sample in mediump int i; - out mediump vec4 color; void main() { - color = vec4(f, float(i), 0, 1); + color = vec4(1.0, 0.0, 0.0, 1.0); })"; ANGLE_GL_PROGRAM(program, kVS, kFS); -} - -// Test that `noperspective centroid` passes the validation and compiles. -TEST_P(GLSLTest_ES3, NoPerspectiveCentroid) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation")); - - constexpr char kVS[] = - R"(#version 300 es - #extension GL_NV_shader_noperspective_interpolation : require - noperspective centroid out mediump float f; - void main() - { - f = 1.0; - gl_Position = vec4(0.0, 0.0, 0.0, 1.0); - })"; + GLint params = 0; - constexpr char kFS[] = - R"(#version 300 es - #extension GL_NV_shader_noperspective_interpolation : require + glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES_EXT, ¶ms); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); - noperspective centroid in mediump float f; - out mediump vec4 color; - void main() - { - color = vec4(f, 0.0, 0.0, 1.0); - })"; + glGetProgramiv(program, GL_TESS_GEN_MODE, ¶ms); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); - ANGLE_GL_PROGRAM(program, kVS, kFS); + glGetProgramiv(program, GL_TESS_GEN_SPACING, ¶ms); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); } -// Test that `noperspective sample` passes the validation and compiles. -TEST_P(GLSLTest_ES3, NoPerspectiveSample) +// Test that GetProgramiv with tessellation parameters generates an INVALID_OPERATION error when +// there is no tessellation control shader. +TEST_P(GLSLTest_ES31, ValidateGetProgramivNoTessellationControlShader) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader")); constexpr char kVS[] = - R"(#version 300 es - #extension GL_OES_shader_multisample_interpolation : require - #extension GL_NV_shader_noperspective_interpolation : require + R"(#version 310 es + + precision highp float; + in vec4 inputAttribute; - noperspective sample out mediump float f; void main() { - f = 1.0; - gl_Position = vec4(f, 0.0, 0.0, 1.0); + gl_Position = inputAttribute; })"; + static const char kTES[] = + "#version 310 es\n" + "#extension GL_EXT_tessellation_shader : require\n" + "layout(triangles, fractional_even_spacing, cw, point_mode) in;\n" + "void main(void)\n" + "{}"; + constexpr char kFS[] = - R"(#version 300 es - #extension GL_OES_shader_multisample_interpolation : require - #extension GL_NV_shader_noperspective_interpolation : require + R"(#version 310 es + + precision highp float; + layout(location = 0) out mediump vec4 color; - noperspective sample in mediump float f; - out mediump vec4 color; void main() { - color = vec4(f, 0.0, 0.0, 1.0); + color = vec4(1.0, 0.0, 0.0, 1.0); })"; - ANGLE_GL_PROGRAM(program, kVS, kFS); + GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS); + GLuint tes = CompileShader(GL_TESS_EVALUATION_SHADER, kTES); + GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); + GLuint program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, tes); + glAttachShader(program, fs); + glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); + glLinkProgram(program); + ASSERT_GL_NO_ERROR(); + + GLint params = 0; + + glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES_EXT, ¶ms); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glGetProgramiv(program, GL_TESS_GEN_MODE, ¶ms); + EXPECT_EQ(static_cast(GL_TRIANGLES), params); + glGetProgramiv(program, GL_TESS_GEN_SPACING, ¶ms); + EXPECT_EQ(static_cast(GL_FRACTIONAL_EVEN), params); + + glDetachShader(program, vs); + glDetachShader(program, tes); + glDetachShader(program, fs); + glDeleteShader(vs); + glDeleteShader(tes); + glDeleteShader(fs); + glDeleteProgram(program); + ASSERT_GL_NO_ERROR(); } -// Test that a shader with sample in / sample out can be used successfully when the varying -// precision is different between VS and FS. -TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision) +// Test that GetProgramiv with tessellation parameters generates an INVALID_OPERATION error when +// there is no tessellation evaluation shader. +TEST_P(GLSLTest_ES31, ValidateGetProgramivNoTessellationEvaluationShader) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader")); constexpr char kVS[] = R"(#version 310 es - #extension GL_OES_shader_multisample_interpolation : require precision highp float; in vec4 inputAttribute; - sample out highp float v; void main() { - v = inputAttribute[0]; gl_Position = inputAttribute; })"; + static const char kTCS[] = + "#version 310 es\n" + "#extension GL_EXT_tessellation_shader : require\n" + "layout(vertices = 3) out;\n" + "void main(void)\n" + "{}"; + constexpr char kFS[] = R"(#version 310 es - #extension GL_OES_shader_multisample_interpolation : require precision highp float; - sample in mediump float v; layout(location = 0) out mediump vec4 color; void main() { - color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1); + color = vec4(1.0, 0.0, 0.0, 1.0); })"; - ANGLE_GL_PROGRAM(program, kVS, kFS); - drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE); + GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS); + GLuint tcs = CompileShader(GL_TESS_CONTROL_SHADER, kTCS); + GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); + GLuint program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, tcs); + glAttachShader(program, fs); + glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); + glLinkProgram(program); + ASSERT_GL_NO_ERROR(); + + GLint params = 0; + glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES_EXT, ¶ms); + EXPECT_EQ(3, params); + + glGetProgramiv(program, GL_TESS_GEN_MODE, ¶ms); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glGetProgramiv(program, GL_TESS_GEN_SPACING, ¶ms); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glDetachShader(program, vs); + glDetachShader(program, tcs); + glDetachShader(program, fs); + glDeleteShader(vs); + glDeleteShader(tcs); + glDeleteShader(fs); + glDeleteProgram(program); + ASSERT_GL_NO_ERROR(); +} + +// Test that `smooth sample` and `flat sample` pass the validation. +TEST_P(GLSLTest_ES3, AliasedSampleQualifiers) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + constexpr char kVS[] = + R"(#version 300 es + #extension GL_OES_shader_multisample_interpolation : require + + smooth sample out mediump float f; + flat sample out mediump int i; + void main() + { + f = 1.0; + i = 1; + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + })"; + + constexpr char kFS[] = + R"(#version 300 es + #extension GL_OES_shader_multisample_interpolation : require + + smooth sample in mediump float f; + flat sample in mediump int i; + out mediump vec4 color; + void main() + { + color = vec4(f, float(i), 0, 1); + })"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); +} + +// Test that `noperspective centroid` passes the validation and compiles. +TEST_P(GLSLTest_ES3, NoPerspectiveCentroid) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation")); + + constexpr char kVS[] = + R"(#version 300 es + #extension GL_NV_shader_noperspective_interpolation : require + + noperspective centroid out mediump float f; + void main() + { + f = 1.0; + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + })"; + + constexpr char kFS[] = + R"(#version 300 es + #extension GL_NV_shader_noperspective_interpolation : require + + noperspective centroid in mediump float f; + out mediump vec4 color; + void main() + { + color = vec4(f, 0.0, 0.0, 1.0); + })"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); +} + +// Test that `noperspective sample` passes the validation and compiles. +TEST_P(GLSLTest_ES3, NoPerspectiveSample) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation")); + + constexpr char kVS[] = + R"(#version 300 es + #extension GL_OES_shader_multisample_interpolation : require + #extension GL_NV_shader_noperspective_interpolation : require + + noperspective sample out mediump float f; + void main() + { + f = 1.0; + gl_Position = vec4(f, 0.0, 0.0, 1.0); + })"; + + constexpr char kFS[] = + R"(#version 300 es + #extension GL_OES_shader_multisample_interpolation : require + #extension GL_NV_shader_noperspective_interpolation : require + + noperspective sample in mediump float f; + out mediump vec4 color; + void main() + { + color = vec4(f, 0.0, 0.0, 1.0); + })"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); +} + +// Test that a shader with sample in / sample out can be used successfully when the varying +// precision is different between VS and FS. +TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + constexpr char kVS[] = + R"(#version 310 es + #extension GL_OES_shader_multisample_interpolation : require + + precision highp float; + in vec4 inputAttribute; + + sample out highp float v; + void main() + { + v = inputAttribute[0]; + gl_Position = inputAttribute; + })"; + + constexpr char kFS[] = + R"(#version 310 es + #extension GL_OES_shader_multisample_interpolation : require + + precision highp float; + sample in mediump float v; + layout(location = 0) out mediump vec4 color; + + void main() + { + color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1); + })"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE); ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red); @@ -9174,22 +9472,20 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); } -// Test that basic infinite loops are either rejected or are pruned in WebGL -TEST_P(WebGL2GLSLTest, BasicInfiniteLoop) +// Basic test that loops are not mistakenly considered infinite loops. +TEST_P(WebGL2GLSLTest, NotInfiniteLoop) { constexpr char kFS[] = R"(#version 300 es precision highp float; uniform uint zero; out vec4 color; -bool globalConstantVariable = true; - float f() { - // Should not be pruned + // Not infinite loop while (true) { - // Should not be pruned + // Not infinite loop for (int i = 0; true; ++i) { if (zero < 10u) @@ -9197,7 +9493,7 @@ float f() switch (zero) { case 0u: - // Loops should be pruned because of this `return`. + // Loops are not infinite because of this `return`. return 0.7; default: break; @@ -9207,6 +9503,13 @@ float f() } } +void writeFalse(out bool v) +{ + v = false; +} + +bool globalConstantVariable = true; + void main() { float r = 0.; @@ -9215,29 +9518,14 @@ void main() bool localConstantVariable = true; bool localVariable = true; - - // Should be pruned - while (true) - { - r += 0.1; - if (r > 0.) - { - continue; - } - } + bool localVariable2 = true; if (zero != 0u) { localVariable = false; } - // Should be pruned - while (localConstantVariable) - { - g -= 0.1; - } - - // Should not be pruned + // Not infinite loop because of break while (localConstantVariable) { b += 0.3; @@ -9245,49 +9533,79 @@ void main() if (g > 0.4) { break; } } - // Should be pruned - for (; globalConstantVariable; ) + // Not infinite loop because of break + while (globalConstantVariable) { - g -= 0.1; + b += 0.2; - switch (zero) - { - case 0u: - r = 0.4; - break; - default: - r = 0.2; - break; - } + if (g > 0.4) { break; } } - // Should not be pruned + // Not infinite loop because variable gets modified. while (localVariable) { b += 0.2; localVariable = !localVariable; } + // Not infinite loop because variable gets modified. + while (localVariable2) + { + b += 0.1; + writeFalse(localVariable2); + } + r = f(); color = vec4(r, g, b, 1); })"; - if (getEGLWindow()->isFeatureEnabled(Feature::RejectWebglShadersWithUndefinedBehavior)) - { - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); - } - else + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); + EXPECT_PIXEL_NEAR(0, 0, 178, 255, 204, 255, 1); +} + +// Test that while(global) loops are not rejected if global is modified in a function call whose +// definition is after the loop. +TEST_P(WebGL2GLSLTest, NotInfiniteLoopIfGlobalIsModified) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +uniform uint zero; +out vec4 color; + +bool globalVariable = true; + +// resetGlobal modifies globalVariable, but its definition is not visible while parsing the loop +void resetGlobal(); + +void main() +{ + float r = 0.; + float g = 1.; + float b = 0.; + + while (globalVariable) { - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); - drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); - EXPECT_PIXEL_NEAR(0, 0, 178, 255, 127, 255, 1); + r += 0.5; + resetGlobal(); } + + color = vec4(r, g, b, 1); } -// Test that while(true) loops with break/return are not rejected -TEST_P(WebGL2GLSLTest, NotInfiniteLoop) +void resetGlobal() +{ + globalVariable = false; +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); + EXPECT_PIXEL_NEAR(0, 0, 127, 255, 0, 255, 1); +} + +// Test that while(true) loops with break or return are not rejected +TEST_P(WebGL2GLSLTest, NotInfiniteLoopIfBreakOrReturn) { constexpr char kFS[] = R"(#version 300 es precision highp float; @@ -9836,15 +10154,6 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that *= on boolean vectors fails compilation -TEST_P(GLSLTest, BVecMultiplyAssign) -{ - constexpr char kFS[] = R"(bvec4 c,s;void main(){s*=c;})"; - - GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(fs, 0u); -} - // Test vector/scalar arithmetic (in this case multiplication and addition). TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop) { @@ -9894,84 +10203,6 @@ void main() { EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation. -TEST_P(GLSLTest, VectorScalarArithmeticWithSideEffectInLoop) -{ - // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past - // (notice how sbcd references i outside the for loop. The loop condition doesn't look right - // either): - // - // #version 450 - // void main(){ - // (gl_Position = vec4(0.0, 0.0, 0.0, 0.0)); - // mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - // vec3 _ures = vec3(0.0, 0.0, 0.0); - // vec3 sbcd = vec3(_ures[_ui]); - // for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)), - // sbcd)), _ui)], (_ui < 7)); ) - // { - // } - // } - - constexpr char kVS[] = R"( -void main() -{ - mat3 tmp; - vec3 res; - for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;); -})"; - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {kVS}; - GLint lengths[1] = {static_cast(sizeof(kVS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that packing of excessive 3-column variables does not overflow the count of 3-column -// variables in VariablePacker -TEST_P(WebGL2GLSLTest, ExcessiveMat3UniformPacking) -{ - std::ostringstream srcStream; - - srcStream << "#version 300 es\n"; - srcStream << "precision mediump float;\n"; - srcStream << "out vec4 finalColor;\n"; - srcStream << "in vec4 color;\n"; - srcStream << "uniform mat4 r[254];\n"; - - srcStream << "uniform mat3 "; - constexpr size_t kNumUniforms = 10000; - for (size_t i = 0; i < kNumUniforms; ++i) - { - if (i > 0) - { - srcStream << ", "; - } - srcStream << "m3a_" << i << "[256]"; - } - srcStream << ";\n"; - - srcStream << "void main(void) { finalColor = color; }\n"; - std::string src = std::move(srcStream).str(); - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {src.c_str()}; - GLint lengths[1] = {static_cast(src.length())}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_EQ(compileResult, 0); -} - // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator // is handled correctly. TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary) @@ -10799,7 +11030,7 @@ bool SubrectEquals(const std::vector &bigArray, return badPixels == 0; } -// Tests that FragCoord behaves the same betweeen a user FBO and the back buffer. +// Tests that FragCoord behaves the same between a user FBO and the back buffer. TEST_P(GLSLTest, FragCoordConsistency) { constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize; @@ -11092,23 +11323,8 @@ foo ANGLE_GL_PROGRAM(program, kVS, kFS); } -// Test that inactive output variables compile ok in combination with initOutputVariables -// (which is enabled on WebGL). -TEST_P(WebGL2GLSLTest, InactiveOutput) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -out vec4 _cassgl_2_; -void main() -{ -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(shader, 0u); -} - -// Test that clamp applied on non-literal indices is correct on es 100 shaders. -TEST_P(GLSLTest, ValidIndexClampES100) +// Test that clamp applied on non-literal indices is correct on es 100 shaders. +TEST_P(GLSLTest, ValidIndexClampES100) { // http://anglebug.com/42264558 ANGLE_SKIP_TEST_IF(IsD3D9()); @@ -11245,14 +11461,6 @@ TEST_P(GLSLTest, FragData_AlphaToCoverage) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); } -// Test angle can handle big initial stack size with dynamic stack allocation. -TEST_P(GLSLTest, MemoryExhaustedTest) -{ - GLuint program = - CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str()); - EXPECT_NE(0u, program); -} - // Test that inactive samplers in structs don't cause any errors. TEST_P(GLSLTest, InactiveSamplersInStruct) { @@ -12319,23 +12527,6 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that indexing swizzles out of bounds fails -TEST_P(GLSLTest_ES3, OutOfBoundsIndexingOfSwizzle) -{ - constexpr char kFS[] = R"(#version 300 es -precision mediump float; -out vec4 colorOut; -uniform vec3 colorIn; - -void main() -{ - colorOut = vec4(colorIn.yx[2], 0, 0, 1); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); -} - // Test that indexing l-value swizzles work TEST_P(GLSLTest_ES3, IndexingOfSwizzledLValuesShouldWork) { @@ -12552,6 +12743,64 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test nested dead code with `if` +TEST_P(GLSLTest_ES3, NestedIfDeadCodeIsPruned) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +void main() +{ + vec4 result = vec4(0, 0.5, 0, 1); + + for (int i = 0; i < 3; ++i) + { + if (i < 1) + { + result.x += 0.5; + continue; + // dead code + if (result.y > 0.) + { + break; + result.z += 0.5; + // dead code + if (false) + { + result.w -= 0.5; + } + } + // dead code + if (result.x > 0.) + { + result.w -= 0.5; + } + } + + break; + // dead code + if (result.x > 0.) + { + return; + if (result.y > 0.) + { + result.w -= 0.5; + } + } + } + + color = result; +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 0, 255), 1); +} + // Regression test based on fuzzer issue. If a case has statements that are pruned, and those // pruned statements in turn have branches, and another case follows, a prior implementation of // dead-code elimination doubly pruned some statements. @@ -12583,6 +12832,216 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test dead code after constant folded control flow structures +TEST_P(GLSLTest_ES3, DeadCodeInConstFoldControlFlow) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +vec4 constantIf() +{ + vec4 ret = vec4(0, 0.1, 0, 0); + if (true) + { + return ret; + } + ret = vec4(1, 0, 0, 0); + return ret; +} + +vec4 constantFor() +{ + vec4 ret = vec4(0.1, 0, 0, 0); + for (int i = 0; i < 10; ++i) + { + ret.r += 0.1; + break; + } + ret.a += 0.1; + return ret; +} + +vec4 constantWhileFalse() +{ + vec4 ret = vec4(0, 0, 0.1, 0); + while (false) + { + ret.g = 1.0; + return ret; + } + ret.b += 0.1; + return ret; +} + +vec4 constantWhileTrue() +{ + vec4 ret = vec4(0, 0.1, 0, 0); + while (true) + { + ret.g += 0.3; + break; + } + ret.g += 0.1; + return ret; +} + +vec4 constantDoWhileFalse() +{ + vec4 ret = vec4(0, 0, 0.1, 0); + do + { + ret.b += 0.1; + return ret; + } while (false); + + ret.a = 1.; + return ret; +} + +vec4 constantDoWhileTrue() +{ + vec4 ret = vec4(0, 0, 0.1, 0); + do + { + ret.b += 0.1; + return ret; + } while (true); + + ret.r = 1.; + return ret; +} + +vec4 constantSwitch() +{ + vec4 ret = vec4(0, 0, 0.1, 0); + switch (4) + { + case 1: + ret.r = 1.; + break; + case 3: + ret.b = 1.; + // fallthrough + case 4: + ret.a += 0.1; + // fallthrough + case 5: + return ret; + default: + ret.g = 1.; + } + ret.r = 1.; + return ret; +} + +void main() +{ + vec4 result = constantIf(); + result += constantFor(); + result += constantWhileFalse(); + result += constantWhileTrue(); + result += constantDoWhileFalse(); + result += constantDoWhileTrue(); + result += constantSwitch(); + + color = result; +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51, 153, 179, 51), 1); +} + +// Test that blocks with only variable declarations inside are handled correctly +TEST_P(GLSLTest_ES3, BlocksWithOnlyVariableDeclaration) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; +uniform float zero; + +float global = 1.0; +int iglobal = 100; + +void main() +{ + float local = 0.5; + int ilocal = 200; + + if (false) + { + float a = 0.; + int b = 1; + } + + if (zero < 1.) + { + float c = 0.; + int d = 1; + } + + for (int i = 0; i < 2; ++i) + { + break; + // dead code + if (zero < 1.) + { + float e = 0.; + int f = 1; + } + } + + if (false) + { + float g = global + 1.; + } + if (zero < 1.) + { + float h = global + 1.; + } + + if (false) + { + float i = local + 1.; + } + if (zero < 1.) + { + float j = local + 1.; + } + + if (false) + { + int j = ++iglobal; + } + if (zero < 1.) + { + int k = ++iglobal; + } + + if (false) + { + int l = ++ilocal; + } + if (zero < 1.) + { + int m = ++ilocal; + } + + color = vec4(global, local, iglobal == 101 ? 0.5 : 0., ilocal == 201 ? 1.0 : 0.); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 127, 255), 1); +} + // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to // make sure they are all linked ok. The front-end sorts these resources and traverses the list of // "uniforms" to find the range for each resource. A bug there was causing some resource ranges to @@ -14757,7 +15216,7 @@ void main() EXPECT_EQ(0u, program); } -// Verify I/O block array locations +// Verify I/O block locations TEST_P(GLSLTest_ES31, IOBlockLocations) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); @@ -14899,6 +15358,100 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); } +// Verify I/O block array locations +TEST_P(GLSLTest_ES31, IOBlockArrayLocations) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require + +in highp vec4 position; + +layout(location = 0) out vec4 a; + +// This should consume locations [3, 8] +layout(location = 3) out Block +{ + vec4 b; + vec4 c; +} block[3]; + +layout(location = 1) out vec4 d[2]; +layout(location = 9) out vec4 e[4]; + +void main() +{ + a = vec4(0.03, 0.06, 0.09, 0.12); + block[0].b = vec4(0.15, 0.18, 0.21, 0.24); + block[0].c = vec4(0.27, 0.30, 0.33, 0.36); + block[1].b = vec4(0.39, 0.42, 0.45, 0.48); + block[1].c = vec4(0.51, 0.54, 0.57, 0.6); + block[2].b = vec4(0.63, 0.66, 0.66, 0.69); + block[2].c = vec4(0.72, 0.75, 0.78, 0.81); + d[0] = vec4(0.84, 0.87, 0.9, 0.93); + d[1] = vec4(0.96, 0.99, 0.94, 0.89); + e[0] = vec4(0.84, 0.79, 0.74, 0.69); + e[1] = vec4(0.64, 0.59, 0.54, 0.49); + e[2] = vec4(0.44, 0.39, 0.34, 0.29); + e[3] = vec4(0.24, 0.19, 0.14, 0.09); + gl_Position = position; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require +precision mediump float; + +layout(location = 0) out mediump vec4 color; + +layout(location = 0) in vec4 a; + +layout(location = 3) in Block +{ + vec4 b; + vec4 c; +} block[3]; + +layout(location = 1) in vec4 d[2]; +layout(location = 9) in vec4 e[4]; + +bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); } + +void main() +{ + bool passR = isEq(a, vec4(0.03, 0.06, 0.09, 0.12)); + bool passG = isEq(block[0].b, vec4(0.15, 0.18, 0.21, 0.24)) && + isEq(block[0].c, vec4(0.27, 0.30, 0.33, 0.36)) && + isEq(block[1].b, vec4(0.39, 0.42, 0.45, 0.48)) && + isEq(block[1].c, vec4(0.51, 0.54, 0.57, 0.6)) && + isEq(block[2].b, vec4(0.63, 0.66, 0.66, 0.69)) && + isEq(block[2].c, vec4(0.72, 0.75, 0.78, 0.81)); + bool passB = isEq(d[0], vec4(0.84, 0.87, 0.9, 0.93)) && + isEq(d[1], vec4(0.96, 0.99, 0.94, 0.89)); + bool passA = isEq(e[0], vec4(0.84, 0.79, 0.74, 0.69)) && + isEq(e[1], vec4(0.64, 0.59, 0.54, 0.49)) && + isEq(e[2], vec4(0.44, 0.39, 0.34, 0.29)) && + isEq(e[3], vec4(0.24, 0.19, 0.14, 0.09)); + + color = vec4(passR, passG, passB, passA); +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + EXPECT_GL_NO_ERROR(); + + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + + drawQuad(program, "position", 0); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + // Test using builtins that can only be redefined with gl_PerVertex TEST_P(GLSLTest_ES31, PerVertexRedefinition) { @@ -15567,119 +16120,14 @@ void main() EXPECT_EQ(0u, program); } -// Test that separating declarators works with structs that have been separately defined. -TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType) +// Test separation of struct declarations, case where separated struct is used as a member of +// another struct. +TEST_P(GLSLTest, SeparateStructDeclaratorStructInStruct) { - constexpr char kVS[] = R"(#version 310 es -precision highp float; - -struct S -{ - mat4 a; - mat4 b; -}; - -S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5))); - -void main() { - S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5; - - gl_Position = vec4(s3[1].a[0].x, s2[0][2].b[1].y, s4[1][0].a[2].z, s6[0].b[3].w); -})"; - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {kVS}; - GLint lengths[1] = {static_cast(sizeof(kVS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that separating declarators works with structs that are simultaneously defined. -TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified) -{ - constexpr char kVS[] = R"(#version 310 es -precision highp float; - -struct S -{ - mat4 a; - mat4 b; -} s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5))); - -void main() { - struct T - { - mat4 a; - mat4 b; - } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5; - - float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y; - - gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w); -})"; - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {kVS}; - GLint lengths[1] = {static_cast(sizeof(kVS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that separating declarators works with structs that are simultaneously defined and that are -// nameless. -TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType) -{ - constexpr char kVS[] = R"(#version 310 es -precision highp float; - -struct -{ - mat4 a; - mat4 b; -} s1, s2[2][3], s3[2]; - -void main() { - struct - { - mat4 a; - mat4 b; - } s4[2][3], s5, s6[2], s7 = s5; - - float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z; - - gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w); -})"; - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {kVS}; - GLint lengths[1] = {static_cast(sizeof(kVS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test separation of struct declarations, case where separated struct is used as a member of -// another struct. -TEST_P(GLSLTest, SeparateStructDeclaratorStructInStruct) -{ - const char kFragmentShader[] = R"(precision mediump float; -uniform vec4 u; -struct S1 { vec4 v; } a; -void main() + const char kFragmentShader[] = R"(precision mediump float; +uniform vec4 u; +struct S1 { vec4 v; } a; +void main() { struct S2 { S1 s1; } b; a.v = u; @@ -15695,193 +16143,64 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Regression test for transformation bug which separates struct declarations from uniform -// declarations. The bug was that the uniform variable usage in the initializer of a new -// declaration (y below) was not being processed. -TEST_P(GLSLTest, UniformStructBug) -{ - constexpr char kVS[] = R"(precision highp float; - -uniform struct Global -{ - float x; -} u_global; - -void main() { - float y = u_global.x; - - gl_Position = vec4(y); -})"; - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {kVS}; - GLint lengths[1] = {static_cast(sizeof(kVS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Regression test for transformation bug which separates struct declarations from uniform -// declarations. The bug was that the arrayness of the declaration was not being applied to the -// replaced uniform variable. -TEST_P(GLSLTest_ES31, UniformStructBug2) -{ - constexpr char kVS[] = R"(#version 310 es -precision highp float; - -uniform struct Global -{ - float x; -} u_global[2][3]; - -void main() { - float y = u_global[0][0].x; - - gl_Position = vec4(y); -})"; - - GLuint shader = glCreateShader(GL_VERTEX_SHADER); - - const char *sourceArray[1] = {kVS}; - GLint lengths[1] = {static_cast(sizeof(kVS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition -// was not found in the tree. Tests that struct declaration in function return value is visible to -// instantiations later on. -TEST_P(GLSLTest, MissingStructDeclarationBug) -{ - constexpr char kVS[] = R"( -struct S -{ - vec4 i; -} p(); -void main() -{ - S s; -})"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} - -// Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition -// was not found in the tree. Tests that struct declaration in function return value is visible to -// other struct declarations. -TEST_P(GLSLTest, MissingStructDeclarationBug2) -{ - constexpr char kVS[] = R"( -struct T -{ - vec4 I; -} p(); -struct -{ - T c; -}; -void main() -{ -})"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} - -// Regression test for bug in HLSL code generation where the for loop init expression was expected -// to always have an initializer. -TEST_P(GLSLTest, HandleExcessiveLoopBug) -{ - constexpr char kVS[] = R"(void main(){for(int i;i>6;);})"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} - -// Regression test for a validation bug in the translator where func(void, int) was accepted even -// though it's illegal, and the function was callable as if the void parameter isn't there. -TEST_P(GLSLTest, NoParameterAfterVoid) -{ - constexpr char kVS[] = R"(void f(void, int a){} -void main(){f(1);})"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_EQ(0u, shader); - glDeleteShader(shader); -} - -// Similar to NoParameterAfterVoid, but tests func(void, void). -TEST_P(GLSLTest, NoParameterAfterVoid2) +// Test that separable program with multiple shaders with mismatching shader interface works. +TEST_P(GLSLTest_ES31, SeparableProgramWithMismatchingShaderInterface) { - constexpr char kVS[] = R"(void f(void, void){} -void main(){f();})"; + ANGLE_SKIP_TEST_IF(!IsVulkan()); + constexpr char kVS[] = + "#version 300 es\n" + "in vec4 a_position;\n" + "out float out_val;\n" + "void main()\n" + "{\n" + " gl_Position = a_position;\n" + "}\n"; - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_EQ(0u, shader); - glDeleteShader(shader); -} + constexpr char kFS[] = + "#version 300 es\n" + "precision highp float;\n" + "out vec4 fragColor;\n" + "void main()\n" + "{\n" + " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + "}\n"; -// Test that providing more components to a matrix constructor than necessary works. Based on a -// clusterfuzz test that caught an OOB array write in glslang. -TEST_P(GLSLTest, MatrixConstructor) -{ - constexpr char kVS[] = R"(attribute vec4 aPosition; -varying vec4 vColor; -void main() -{ - gl_Position = aPosition; - vec4 color = vec4(aPosition.xy, 0, 1); - mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz); - vColor = m4[0]; -})"; + GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS); + GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); + GLuint program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, fs); - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} + glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); + glLinkProgram(program); + EXPECT_GL_NO_ERROR(); -// Test constructors without precision -TEST_P(GLSLTest, ConstructFromBoolVector) -{ - constexpr char kFS[] = R"(precision mediump float; -uniform float u; -void main() -{ - mat4 m = mat4(u); - mat2(0, bvec3(m)); - gl_FragColor = vec4(m); -})"; + GLuint pipeline = 0; + glGenProgramPipelines(1, &pipeline); + glBindProgramPipeline(pipeline); + glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, program); + glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, program); - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} + std::array quadVertices = ANGLETestBase::GetQuadVertices(); + GLint positionLocation = glGetAttribLocation(program, "a_position"); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data()); + glEnableVertexAttribArray(positionLocation); + glDrawArrays(GL_TRIANGLES, 0, 6); + glDisableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + ASSERT_GL_NO_ERROR(); -// Test constructing vector from matrix -TEST_P(GLSLTest, VectorConstructorFromMatrix) -{ - constexpr char kFS[] = R"(precision mediump float; -uniform mat2 umat2; -void main() -{ - gl_FragColor = vec4(umat2); -})"; + glDetachShader(program, vs); + glDetachShader(program, fs); + glDeleteShader(vs); + glDeleteShader(fs); + glDeleteProgram(program); + glDeleteProgramPipelines(1, &pipeline); - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); + ASSERT_GL_NO_ERROR(); } // Test constructing matrix from vectors @@ -16056,27 +16375,22 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); } -// Test that initializing global variables with non-constant values work -TEST_P(GLSLTest_ES3, InitGlobalNonConstant) +// Test when a constant constructor is nested inside a constructor of a different type, where the +// outer constructor itself is not a constant. +TEST_P(GLSLTest, ConstantConstructorNestedInConstructorOfDifferentType) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers")); - - constexpr char kVS[] = R"(#version 300 es -#extension GL_EXT_shader_non_constant_global_initializers : require -uniform vec4 u; -out vec4 color; - -vec4 global1 = u; -vec4 global2 = u + vec4(1); -vec4 global3 = global1 * global2; + constexpr char kFS[] = R"(precision mediump float; void main() { - color = global3; + float e = 1.; + gl_FragColor.xyz = vec3(ivec2(1, 0),e); + gl_FragColor.a = 1.; })"; - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta); + ASSERT_GL_NO_ERROR(); } // Test that initializing global variables with complex constants work @@ -16235,73 +16549,343 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); } -class GLSLTestLoops : public GLSLTest -{ - protected: - void runTest(const char *fs) - { - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs); - - drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_GL_NO_ERROR(); - - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - } -}; - -// Test basic for loops -TEST_P(GLSLTestLoops, BasicFor) +// Test that case fallthrough after diverging control flow works. +TEST_P(GLSLTest_ES3, CaseFallThroughAfterIf) { constexpr char kFS[] = R"(#version 300 es precision mediump float; out vec4 color; +uniform int zero; void main() { int result = 0; - for (int i = 0; i < 10; ++i) - for (int j = 0; j < 8; ++j) - { - for (int k = 0; k < 2; ++k, ++j) ++result; - for (int k = 0; k < 3; ++k) ++result; - for (int k = 0; k < 0; ++k) ++result; - } + switch (zero) + { + case 1: + result += 100; + // fallthrough + default: + result += 1000; + if (result == 1000) + { + result += 10000; + } + // fallthrough + case 0: + ++result; + if (result == 2) + { + result += 100000; + break; + } + // fallthrough + case 3: + result += 10; + if (result == 2) + { + result += 1000000; + } + break; + case 5: + result += 10000000; + } - color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); + color = result == 11 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); })"; - runTest(kFS); + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test for loop without condition -TEST_P(GLSLTestLoops, ForNoCondition) +// Test simple switch constant folding +TEST_P(GLSLTest_ES3, SwitchConstantFold) { constexpr char kFS[] = R"(#version 300 es precision mediump float; out vec4 color; +uniform int zero; void main() { int result = 0; - for (int i = 0; i < 10; ++i) - for (int j = 0; ; ++j) - { - for (int k = 0; k < 2; ++k, ++j) ++result; - for (int k = 0; k < 3; ++k) ++result; - for (int k = 0; k < 0; ++k) ++result; + switch (10) + { + } - if (j >= 8) - break; - } + switch (11) + { + case 11: + result++; + } - color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); -})"; + switch (12) + { + default: + result += 10; + } - runTest(kFS); -} + switch (123) + { + case 1: + result += 100; + break; + default: + result += 10000; + // fallthrough + case 123: + result += 2; + // fallthrough + case 3: + result += 4; + break; + case 5: + result += 100000; + } -// Test for loop without init and expression -TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression) + // After dead code: + while (true) + { + break; + // dead code + switch (123) + { + default: + result = 123456; + // fallthrough + case 123: + result = 234567; + // fallthrough + case 3: + result = 345678; + break; + } + } + + color = result == 17 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test switch constant folding with variable definition in unreachable cases. +TEST_P(GLSLTest_ES3, SwitchConstantFoldWithVariables) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; +uniform int zero; + +void main() +{ + int result = 0; + switch (10) + { + default: + int a; + } + + switch (11) + { + case 11: + int b = result++; + } + + switch (12) + { + default: + int c = result += 10; + } + + switch (123) + { + case 1: + result += 100; + break; + default: + result += 10000; + int d = 31; + // fallthrough + case 123: + result += 2 + d; + // fallthrough + case 3: + result += 4; + break; + case 5: + result += 100000; + } + + color = result == 48 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test complex situations with switch constant folding +TEST_P(GLSLTest_ES3, SwitchConstantFoldComplex) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; +uniform int zero; + +void main() +{ + int result = 0; + switch (123) + { + case 1: + result += 100; + if (false) + { + result += 1000; + } + break; + default: + result += 10000; + if (zero == 0) + { + result += 100000; + } + // fallthrough + case 123: + ++result; + if (result == 2) + { + result += 1000000; + break; + } + // fallthrough + case 3: + result += 10; + if (result == 2) + { + result += 10000000; + } + break; + case 5: + result += 100000000; + } + + color = result == 11 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +class GLSLTestLoops : public GLSLTest +{ + protected: + void runTest(const char *fs) + { + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + } +}; + +// Test basic for loops +TEST_P(GLSLTestLoops, BasicFor) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +void main() +{ + int result = 0; + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 8; ++j) + { + for (int k = 0; k < 2; ++k, ++j) ++result; + for (int k = 0; k < 3; ++k) ++result; + for (int k = 0; k < 0; ++k) ++result; + } + + color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + runTest(kFS); +} + +// Test for loop with a continue expression that is void. +TEST_P(GLSLTestLoops, ForVoidContinue) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +void f() +{ +} + +void main() +{ + int result = 0; + for (int i = 0; i < 10; f()) + { + ++result; + ++i; + } + + color = result == 10 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + runTest(kFS); +} + +// Test for loop without condition +TEST_P(GLSLTestLoops, ForNoCondition) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +void main() +{ + int result = 0; + for (int i = 0; i < 10; ++i) + for (int j = 0; ; ++j) + { + for (int k = 0; k < 2; ++k, ++j) ++result; + for (int k = 0; k < 3; ++k) ++result; + for (int k = 0; k < 0; ++k) ++result; + + if (j >= 8) + break; + } + + color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + runTest(kFS); +} + +// Test for loop without init and expression +TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression) { constexpr char kFS[] = R"(#version 300 es precision mediump float; @@ -16794,6 +17378,105 @@ void main() runTest(kFS); } +// Test for loop with continue inside constant-foldable switch. +TEST_P(GLSLTestLoops, ForContinueInConstSwitch) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +void main() +{ + int result = 0; + for (int i = 0; i < 10; ++i) + { + switch (10) + { + case 2: + result += 100; + continue; + // dead code + result += 1000; + // fallthrough + case 9: + result += 10000; + // fallthrough + case 10: + ++result; + continue; + default: + result += 100000; + break; + } + result += 1000000; + } + + color = result == 10 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + runTest(kFS); +} + +// Test for loop with continue inside nested switches, with side effects after continue. +TEST_P(GLSLTestLoops, ForContinueInSwitchComplex) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 color; + +void main() +{ + int result = 0; + for (int i = 0; i < 10; ++i) + { + for (int j = 0; j < 8; ++j) + { + switch (j) + { + case 2: + switch (i) + { + case 3: + case 4: + case 5: + result += 100; + continue; + default: + result += 10000; + continue; + } + result = 123456789; + // fallthrough + case 3: + case 4: + ++result; + // fallthrough + case 5: + case 6: + ++result; + break; + default: + continue; + } + result += 3; + } + } + + // j | result + // 0 | 0 (default continues) + // 1 | 0 (default continues) + // 2 | 3x100 (cases 3-5) + 7x10000 (default) + // 3 | 10x1 (cases 3,4) + 10x1 (cases 5,6) + 10x3 (after switch) + // 4 | 10x1 (cases 3,4) + 10x1 (cases 5,6) + 10x3 (after switch) + // 5 | 10x1 (cases 5,6) + 10x3 (after switch) + // 6 | 10x1 (cases 5,6) + 10x3 (after switch) + // 7 | 0 (default continues) + color = result == 70480 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +})"; + + runTest(kFS); +} + // Test while loop with continue inside switch TEST_P(GLSLTestLoops, WhileContinueInSwitch) { @@ -16934,19 +17617,145 @@ void main() { EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that vector and matrix scalarization does not affect rendering. -TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering) +// Test that precision is derived for constants in various expressions. Note that constants don't +// inherently have a precision. Their precision in the expression they are used are derived from +// the adjacent operands. +// This test mostly relies on the translator's internal validation to catch missing propagations. +TEST_P(GLSLTest_ES31, ConstantPrecisionPropagation) { - constexpr char kFS[] = R"( -precision mediump float; + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); -varying vec2 v_texCoord; + constexpr char kVS[] = R"(#version 310 es +in vec4 position; +out vec2 interpolant; +void main() +{ + gl_Position = position; + interpolant = vec2(1, 2); +})"; -float a = 0.; -#define A 0. + constexpr char kFS[] = R"(#version 310 es +#extension GL_OES_shader_multisample_interpolation: require -#define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) ) -vec2 c; +in mediump vec2 interpolant; +out highp vec4 color; + +uniform bool always_false1; +uniform bool always_false2; +uniform bool always_false3; + +highp float f(mediump float v) +{ + return v; +} + +struct S1 +{ + bool b; + lowp float f; +}; + +struct S2 +{ + highp uint i; + S1 s1; +}; + +layout(binding = 0, std430) buffer B { + uint b; +} b; + +mediump uniform sampler2D samp; + +void main() +{ + mediump vec4 v1 = always_false1 + ? vec4(0, 0, 1, 0) + : always_false2 ? vec4(0, 1, 0, 0) : vec4(1, 0, 0, 0); + mediump vec4 v2 = always_false1 + ? always_false2 ? vec4(0, 1, 0, 0) : vec4(1, 0, 0, 0) + : vec4(0, 0, 1, 0); + mediump vec4 v3 = always_false1 + ? vec4(0, 0, 1, 0) + : ((always_false2 ? vec4(0, 1, 0, 0) : vec4(1, 0, 0, 0)) + vec4(0, 0, 0, 1)); + lowp vec4 v4 = always_false1 + ? (always_false2 ? vec4(0, 1, 0, 0) : vec4(1, 0, 0, 0)) + vec4(0, 0, 0, 1) + : vec4(0, 0, 1, 0); + highp vec4 v5 = vec4(0, 0, 0, 1) + (always_false1 ? vec4(0, 1, 0, 0) : vec4(0, 0, 1, 0)); + mediump ivec2 v6 = (always_false1 ? ivec2(100, 200) : ivec2(300, 400)) + + (always_false2 ? ivec2(1000, 2000) : ivec2(3000, 4000)); + highp ivec2 v7 = (always_false1 ? ivec2(100, 200) : ivec2(300, 400)) + + (always_false2 ? ivec3(1000, 2000, 3000) : ivec3(4000, 5000, 6000)).yx; + lowp uvec3 v8 = uvec3((always_false1 ? 10 : 20) + +(always_false2 ? 30 : 60)); + mediump float v9 = f(always_false1 ? 10. : 20.); + S2 v10 = S2((always_false1 ? 1u : 2u), S1(false, (always_false2 ? 3. : 4.))); + bool v11 = (always_false1 ? 1. : 2.) < (always_false2 ? 3. : 4.); + bool v12 = (always_false1 ? v4.w : 2.) < (always_false2 ? 3. : 4.); + bvec3 v13 = greaterThan((always_false1 ? vec3(-1, -2, -3) : vec3(1, 2, 3)) + + (always_false2 ? vec3(-4, -5, -6) : vec3(4, 5, 6)), + vec3(3, 4, 10)); + + mediump uint array[5] = uint[5](5u, 7u, 9u, 11u, 13u); + highp uint v14 = array[(always_false1 ? 5 : 4) - (always_false2 ? 5 : 3) + 1]; + + atomicAdd(b.b, (always_false1 ? 4u : 5u)); + highp float v15 = clamp((always_false1 ? 5. : 4.), (always_false2 ? 3. : 2.), (always_false3 ? 7. : 3.5)); + highp uint v16 = packHalf2x16((always_false1 ? vec2(8., 16.) : vec2(32., 64.)) + + (always_false2 ? vec2(1., 2.) : vec2(4., 128.))); + lowp vec2 v17 = interpolateAtOffset(interpolant, + always_false2 ? vec2(1000., 2000.) : vec2(3000., 4000.)); + lowp ivec2 v18 = textureSize(samp, always_false1 ? 1 : 2); + mediump float v19 = 0.; + switch ((always_false1 ? 2 : 1) + (always_false1 ? 3 : 2) + 4) + { + case 6: v19 = 0.25; break; + case 7: v19 = 1.; break; + case 8: v19 = 0.75; break; + default: v19 = 0.5; break; + } + + if (!all(lessThan(abs(v1 - vec4(1, 0, 0, 0)), vec4(0.01)))) color = vec4(0.1, 0, 0, 0); + else if (!all(lessThan(abs(v2 - vec4(0, 0, 1, 0)), vec4(0.01)))) color = vec4(0.2, 0, 0, 0); + else if (!all(lessThan(abs(v3 - vec4(1, 0, 0, 1)), vec4(0.01)))) color = vec4(0.3, 0, 0, 0); + else if (!all(lessThan(abs(v4 - vec4(0, 0, 1, 0)), vec4(0.01)))) color = vec4(0.4, 0, 0, 0); + else if (!all(lessThan(abs(v5 - vec4(0, 0, 1, 1)), vec4(0.01)))) color = vec4(0.5, 0, 0, 0); + else if (!all(equal(v6, ivec2(3300, 4400)))) color = vec4(0.6, 0, 0, 0); + else if (!all(equal(v7, ivec2(5300, 4400)))) color = vec4(0.7, 0, 0, 0); + else if (!all(equal(v8, uvec3(80, 80, 80)))) color = vec4(0.8, 0, 0, 0); + else if (abs(v9 - 20.) > 0.01) color = vec4(0.9, 0, 0, 0); + else if (v10.i != 2u) color = vec4(1, 0, 0, 0); + else if (abs(v10.s1.f - 4.0) > 0.01) color = vec4(0, 0.1, 0, 0); + else if (!v11) color = vec4(0, 0.2, 0, 0); + else if (!v12) color = vec4(0, 0.3, 0, 0); + else if (!v13.x || !v13.y || v13.z) color = vec4(0, 0.4, 0, 0); + else if (v14 != 9u) color = vec4(0, 0.5, 0, 0); + else if (abs(v15 - 3.5) > 0.01) color = vec4(0, 0.6, 0, 0); + else if (v16 != 0x5A005080u) color = vec4(0, 0.7, 0, 0); + else if (!all(lessThan(abs(v17 - vec2(1, 2)), vec2(0.01)))) color = vec4(0, 0.8, 0, 0); + else if (abs(v19 - 1.) > 0.01) color = vec4(0, 0.9, 0, 0); + else color = vec4(0, 0, 1, 1); +} +)"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + drawQuad(program, "position", 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); +} + +// Test that vector and matrix scalarization does not affect rendering. +TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering) +{ + constexpr char kFS[] = R"( +precision mediump float; + +varying vec2 v_texCoord; + +float a = 0.; +#define A 0. + +#define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) ) +vec2 c; #define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) ) void main() { @@ -17275,6 +18084,35 @@ TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation) EXPECT_GL_NO_ERROR(); } +// Regression test for an unsuccessful link with a varying followed by another link +TEST_P(GLSLTest_ES3, UnsuccessfulLinkFollowedByAnotherLink) +{ + // Make a simple program. + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + + // Install the executable. + glUseProgram(program); + + // Re-link with a bad XFB varying and a bound attrib location. + const char *tfVaryings = "gl_FragColor"; + glTransformFeedbackVaryings(program, 1, &tfVaryings, GL_SEPARATE_ATTRIBS); + glBindAttribLocation(program, 8, essl1_shaders::PositionAttrib()); + glLinkProgram(program); + GLint linkStatus = 999; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + ASSERT_GL_NO_ERROR(); + // Link expected to fail on the first program + ASSERT_EQ(linkStatus, GL_FALSE); + + // Another program with the same shaders but without the varying is expected to link + ANGLE_GL_PROGRAM(anotherProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + ASSERT_NE(program, anotherProgram); + glUseProgram(anotherProgram); + glLinkProgram(anotherProgram); + ASSERT_GL_NO_ERROR(); + ASSERT_NE(CheckLinkStatusAndReturnProgram(anotherProgram, true), 0u); +} + // Tests an unsuccessful re-link using glBindAttribLocation under WebGL. TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation) { @@ -17316,90 +18154,6 @@ void main() ASSERT_GL_NO_ERROR(); } -// Regression test for a crash in SPIR-V output when faced with an array of struct constant. -TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug) -{ - constexpr char kFS[] = R"(#version 300 es -struct S { - int foo; -}; -void main() { - S a[3]; - a = S[3](S(0), S(1), S(2)); -})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Regression test for a bug in SPIR-V output where float+matrix was mishandled. -TEST_P(GLSLTest_ES3, FloatPlusMatrix) -{ - constexpr char kFS[] = R"(#version 300 es - -precision mediump float; - -layout(location=0) out vec4 color; - -uniform float f; - -void main() -{ - mat3x2 m = f + mat3x2(0); - color = vec4(m[0][0]); -})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Regression test for a bug in SPIR-V output where a transformation creates float(constant) without -// folding it into a TIntermConstantUnion. This transformation is clamping non-constant indices in -// WebGL. The |false ? i : 5| as index caused the transformation to consider this a non-constant -// index. -TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; - -layout(location=0) out float f; - -uniform int i; - -void main() -{ - float data[10]; - f = data[false ? i : 5]; -})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - // Test robustness of out-of-bounds lod in texelFetch TEST_P(WebGL2GLSLTest, TexelFetchLodOutOfBounds) { @@ -17449,135 +18203,6 @@ void main() { glDrawArrays(GL_TRIANGLES, 0, 6); } -// Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without -// failing validation (adapted from a Chromium test, see anglebug.com/42265427) -TEST_P(GLSLTest, FramebufferFetchWithLastFragData) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); - - constexpr char kFS[] = R"(#version 100 - -#extension GL_EXT_shader_framebuffer_fetch : require -varying mediump vec4 color; -void main() { - gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0]; -})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that loop body ending in a branch doesn't fail compilation -TEST_P(GLSLTest, LoopBodyEndingInBranch1) -{ - constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that loop body ending in a branch doesn't fail compilation -TEST_P(GLSLTest, LoopBodyEndingInBranch2) -{ - constexpr char kFS[] = - R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that loop body ending in a branch doesn't fail compilation -TEST_P(GLSLTest, LoopBodyEndingInBranch3) -{ - constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that loop body ending in a branch doesn't fail compilation -TEST_P(GLSLTest, LoopBodyEndingInBranch4) -{ - constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that loop body ending in a branch doesn't fail compilation -TEST_P(GLSLTest, LoopBodyEndingInBranch5) -{ - constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - -// Test that loop body ending in a branch doesn't fail compilation -TEST_P(GLSLTest, LoopBodyEndingInBranch6) -{ - constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})"; - - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *sourceArray[1] = {kFS}; - GLint lengths[1] = {static_cast(sizeof(kFS) - 1)}; - glShaderSource(shader, 1, sourceArray, lengths); - glCompileShader(shader); - - GLint compileResult; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); - EXPECT_NE(compileResult, 0); -} - // Test that aliasing function out parameters work. The GLSL spec says: // // > Because the function works with local copies of parameters, there are no issues regarding @@ -17730,6 +18355,32 @@ void main() { ASSERT_GL_NO_ERROR(); } +// Test mix(float, float, bool) is not affected by an invalid value not selected. +TEST_P(GLSLTest_ES3, MixFloatFloatBoolInvalid) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +uniform vec2 xy; +uniform bool a; +out vec4 fragColor; +void main() { + fragColor = vec4(mix(xy.x, xy.y, a) == xy.y, 0.0, 0.0, 1.0); +} +)"; + ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS); + glUseProgram(testProgram); + auto xy = glGetUniformLocation(testProgram, "xy"); + auto a = glGetUniformLocation(testProgram, "a"); + ASSERT_GL_NO_ERROR(); + glUniform2f(xy, NAN, 0.5f); + glUniform1i(a, 1); + ASSERT_GL_NO_ERROR(); + + drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 0, 255)); + ASSERT_GL_NO_ERROR(); +} + // Test coverage of the mix(uint, uint, bool) overload which was missing in D3D11 translation TEST_P(GLSLTest_ES31, MixUintUintBool) { @@ -18148,7 +18799,7 @@ TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue) constexpr char kFS[] = R"(#version 300 es - + precision mediump float; out vec4 fragOut; struct aParam @@ -18175,7 +18826,7 @@ TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue) void main() { fragOut.a = monomorphizedFunction(theParam); - } + } )"; CompileShader(GL_FRAGMENT_SHADER, kFS); ASSERT_GL_NO_ERROR(); @@ -19500,7 +20151,6 @@ TEST_P(GLSLTest, ESSL1ExtensionMacros) "GL_EXT_shadow_samplers", "GL_KHR_blend_equation_advanced", "GL_NV_EGL_stream_consumer_external", - "GL_NV_shader_framebuffer_fetch", "GL_OES_EGL_image_external", "GL_OES_standard_derivatives", "GL_OES_texture_3D", @@ -19588,7 +20238,6 @@ TEST_P(GLSLTest_ES3, ESSL3ExtensionMacros) "GL_EXT_tessellation_shader", "GL_EXT_texture_buffer", "GL_EXT_texture_cube_map_array", - "GL_NV_shader_framebuffer_fetch", "GL_OES_geometry_shader", "GL_OES_primitive_bounding_box", "GL_OES_shader_image_atomic", @@ -19655,7 +20304,6 @@ TEST_P(GLSLTest_ES31, ESSL31ExtensionMacros) "GL_EXT_frag_depth", "GL_EXT_shader_texture_lod", "GL_EXT_shadow_samplers", - "GL_NV_shader_framebuffer_fetch", "GL_OES_standard_derivatives", }); ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fs.c_str()); @@ -19732,6 +20380,10 @@ TEST_P(WebGLGLSLTest, InvalidGlobalsNotInlined) // fields having unique names. TEST_P(GLSLTest_ES3, LotsOfFieldsInStruct) { + int maxUniformBlockSize = 0; + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize); + ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4); + std::ostringstream fs; fs << R"(#version 300 es precision highp float; @@ -19753,278 +20405,38 @@ void main() { ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.str().c_str()); } -// Test that structs with too many fields are rejected. In SPIR-V, the instruction that defines the -// struct lists the fields which means the length of the instruction is a function of the field -// count. Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be -// represented. -TEST_P(GLSLTest_ES3, TooManyFieldsInStruct) +// Make sure an SSBO with a large array links successfully. +TEST_P(GLSLTest_ES31, LargeInterfaceBlockArray) { - std::ostringstream fs; - fs << R"(#version 300 es + constexpr char kFS[] = R"(#version 310 es precision highp float; -struct TooManyFields -{ -)"; - for (uint32_t i = 0; i < (1 << 16); ++i) - { - fs << " float field" << i << ";\n"; - } - fs << R"(}; -uniform B { TooManyFields s; }; +layout(std430) buffer Large { float a[65536]; }; out vec4 color; void main() { - color = vec4(s.field0, 0.0, 0.0, 1.0); + color = vec4(a[0], 0.0, 0.0, 1.0); })"; - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str()); - EXPECT_EQ(0u, shader); + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); } -// Same as TooManyFieldsInStruct, but with samplers in the struct. -TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct) +// Make sure an SSBO with a nested large array links successfully. +TEST_P(GLSLTest_ES31, LargeInterfaceBlockNestedArray) { - std::ostringstream fs; - fs << R"(#version 300 es + constexpr char kFS[] = R"(#version 310 es precision highp float; -struct TooManyFields -{ -)"; - for (uint32_t i = 0; i < (1 << 16); ++i) - { - fs << " sampler2D field" << i << ";\n"; - } - fs << R"(}; -uniform TooManyFields s; +struct S { float a[65536]; }; +layout(std430) buffer Large { S s; }; out vec4 color; void main() { - color = texture(s.field0, vec2(0)); + color = vec4(s.a[0], 0.0, 0.0, 1.0); })"; - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str()); - EXPECT_EQ(0u, shader); + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); } -// More complex variation of ManySamplerFieldsInStruct. This one compiles fine. -TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex) -{ - // D3D and OpenGL may be more restrictive about this many samplers. - ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL()); - - std::ostringstream fs; - fs << R"(#version 300 es -precision highp float; - -struct X { - mediump sampler2D a[0xf00]; - mediump sampler2D b[0xf00]; - mediump sampler2D c[0xf000]; - mediump sampler2D d[0xf00]; -}; - -struct Y { - X s1; - mediump sampler2D a[0xf00]; - mediump sampler2D b[0xf000]; - mediump sampler2D c[0x14000]; -}; - -struct S { - Y s1; -}; - -struct structBuffer { S s; }; - -uniform structBuffer b; - -out vec4 color; -void main() -{ - color = texture(b.s.s1.s1.c[0], vec2(0)); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str()); - EXPECT_NE(0u, shader); -} - -// Make sure a large array of samplers works. -TEST_P(GLSLTest, ManySamplers) -{ - // D3D and OpenGL may be more restrictive about this many samplers. - ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL()); - - std::ostringstream fs; - fs << R"(precision highp float; - -uniform mediump sampler2D c[0x12000]; - -void main() -{ - gl_FragColor = texture2D(c[0], vec2(0)); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str()); - EXPECT_NE(0u, shader); -} - -// Make sure a large array of samplers works when declared in a struct. -TEST_P(GLSLTest, ManySamplersInStruct) -{ - // D3D and OpenGL may be more restrictive about this many samplers. - ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL()); - - std::ostringstream fs; - fs << R"(precision highp float; - -struct X { - mediump sampler2D c[0x12000]; -}; - -uniform X x; - -void main() -{ - gl_FragColor = texture2D(x.c[0], vec2(0)); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str()); - EXPECT_NE(0u, shader); -} - -// Test that passing large arrays to functions are compiled correctly. Regression test for the -// SPIR-V generator that made a copy of the array to pass to the function, by decomposing and -// reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a -// length higher than can fit in SPIR-V. -TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayPassedToFunction) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -uniform Large { float a[65536]; }; -float f(float b[65536]) -{ - b[0] = 1.0; - return b[0] + b[1]; -} -out vec4 color; -void main() { - color = vec4(f(a), 0.0, 0.0, 1.0); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); -} - -// Make sure the shader in LargeInterfaceBlockArrayPassedToFunction works if the large local is -// avoided. -TEST_P(GLSLTest_ES3, LargeInterfaceBlockArray) -{ - int maxUniformBlockSize = 0; - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize); - ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4); - - constexpr char kFS[] = R"(#version 300 es -precision highp float; -uniform Large { float a[16384]; }; -out vec4 color; -void main() { - color = vec4(a[0], 0.0, 0.0, 1.0); -})"; - - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); -} - -// Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct. -TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayPassedToFunction) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -struct S { float a[65536]; }; -uniform Large { S s; }; -float f(float b[65536]) -{ - b[0] = 1.0; - return b[0] + b[1]; -} -out vec4 color; -void main() { - color = vec4(f(s.a), 0.0, 0.0, 1.0); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); -} - -// Make sure the shader in LargeInterfaceBlockNestedArrayPassedToFunction works if the large local -// is avoided. -TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArray) -{ - int maxUniformBlockSize = 0; - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize); - ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4); - - constexpr char kFS[] = R"(#version 300 es -precision highp float; -struct S { float a[16384]; }; -uniform Large { S s; }; -out vec4 color; -void main() { - color = vec4(s.a[0], 0.0, 0.0, 1.0); -})"; - - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); -} - -// Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local -// variable instead. -TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayCopiedToLocal) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -uniform Large { float a[65536]; }; -out vec4 color; -void main() { - float b[65536] = a; - color = vec4(b[0], 0.0, 0.0, 1.0); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); -} - -// Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct -TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayCopiedToLocal) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -struct S { float a[65536]; }; -uniform Large { S s; }; -out vec4 color; -void main() { - S s2 = s; - color = vec4(s2.a[0], 0.0, 0.0, 1.0); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); -} - -// Test that too large varyings are rejected. -TEST_P(GLSLTest_ES3, LargeArrayVarying) -{ - constexpr char kFS[] = R"(#version 300 es -precision highp float; -in float a[65536]; -out vec4 color; -void main() { - color = vec4(a[0], 0.0, 0.0, 1.0); -})"; - - GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); - EXPECT_EQ(0u, shader); -} - -// Regression test for const globals losing const qualifiers during MSL -// translation and exceeding available temporary registers on Apple GPUs. -TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs) +// Regression test for const globals losing const qualifiers during MSL +// translation and exceeding available temporary registers on Apple GPUs. +TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs) { const int n = 128; std::stringstream fragmentShader; @@ -20189,6 +20601,212 @@ void main (void) EXPECT_EQ(type, static_cast(GL_FLOAT_VEC4)); } +// Test that with feature varyingsRequireMatchingPrecisionInSpirv enabled, and when tessellation +// control shader input and output varyings are of array type and they need precision adjustments, +// the spirv generated by ANGLE is correct. Adapted from +// dEQP-GLES31.functional.shaders.linkage.es31.tessellation.varying.rules.internal_different_precision +TEST_P(GLSLTest_ES31, PrecisionAdjustmentInTessellationControlShader) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader") && + !IsGLExtensionEnabled("GL_OES_tessellation_shader")); + constexpr char kVS[] = R"(#version 310 es +in highp vec4 pos; +in float in0; + +out mediump float tc_in; +void main() +{ + tc_in = in0; + gl_Position = pos; +})"; + + constexpr char kTC[] = R"(#version 310 es +#extension GL_OES_tessellation_shader : require +layout (vertices=3) out; + +in highp float tc_in[]; +out highp float tc_out[]; +void main() +{ + tc_out[gl_InvocationID] = tc_in[gl_InvocationID]; + gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; + gl_TessLevelInner[0] = 2.0; + gl_TessLevelInner[1] = 2.0; + gl_TessLevelOuter[0] = 2.0; + gl_TessLevelOuter[1] = 2.0; + gl_TessLevelOuter[2] = 2.0; + gl_TessLevelOuter[3] = 2.0; +})"; + + constexpr char kTE[] = R"(#version 310 es +#extension GL_OES_tessellation_shader : require +layout (triangles) in; + +in lowp float tc_out[]; +out mediump float te_out; +void main() +{ + te_out = tc_out[2]; + gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position; +} +)"; + + constexpr char kFS[] = R"(#version 310 es +precision mediump float; +bool isOk (float a, float b, float eps) { return (abs(a-b) <= (eps*abs(b) + eps)); } +layout(location = 0) out mediump vec4 fragColor; +uniform float ref_out0; +float out0; + +in mediump float te_out; +void main() +{ + out0 = te_out; + bool res = isOk(out0, ref_out0, 0.05); + fragColor = vec4(res, res, res, 1.0); +} +)"; + + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTC, kTE, kFS); + glUseProgram(program); + glUniform1f(glGetUniformLocation(program, "ref_out0"), 1.0); + GLint vertexPosLocation = glGetAttribLocation(program, "pos"); + std::array quadVertices = GetQuadVertices(); + glVertexAttribPointer(vertexPosLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data()); + glEnableVertexAttribArray(vertexPosLocation); + GLint vertexIn0Location = glGetAttribLocation(program, "in0"); + std::array quadAttribs = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + glVertexAttribPointer(vertexIn0Location, 1, GL_FLOAT, GL_FALSE, 0, quadAttribs.data()); + glEnableVertexAttribArray(vertexIn0Location); + glDrawArrays(GL_PATCHES, 0, 6); + glDisableVertexAttribArray(vertexPosLocation); + glVertexAttribPointer(vertexPosLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); + glDisableVertexAttribArray(vertexIn0Location); + glVertexAttribPointer(vertexIn0Location, 1, GL_FLOAT, GL_FALSE, 0, nullptr); + + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white); +} + +// Similar to PrecisionAdjustmentInTessellationControlShader test, except that the tessellation +// control shader also read from tc_out written by other invocations. This is to test that with +// feature varyingsRequireMatchingPrecisionInSpirv enabled, write to tessellation control shader +// output are flushed after each tc_out[gl_InvocationID] = tc_in[gl_InvocationID], not at the end of +// the tessellation control shader, so that "reading from output written by other invocations" can +// work properly. This test also purposefully make below precisions in shader inputs and outputs: +// VS output: mediump +// TCS input: highp, TCS output: highp +// TES input: lowp +// In TCS, we do below conversions: +// multiply input with 50 to produce a number that is bigger than upper limit of mediump and write +// to output: +// output[gl_InvocationID] = input[gl_InvocationID] * 50.0; +// Read the output written by other invocations, and bring it down to a number that can be +// represented with lowp: +// output[gl_InvocationID] = resultFromOtherInvocation / (50.0 * 10000.0); +// This tests that with feature varyingsRequireMatchingPrecisionInSpirv enabled, if TCS output has +// higher precision than TES input, we are adjusting the precision of TES input, so that if we need +// to read values written by other invocations in the middle of TCS, they are not lost. +TEST_P(GLSLTest_ES31, PrecisionAdjustmentInTessellationControlShaderWithBarrier) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader") && + !IsGLExtensionEnabled("GL_OES_tessellation_shader")); + ANGLE_SKIP_TEST_IF( + !getEGLWindow()->isFeatureEnabled(Feature::VaryingsRequireMatchingPrecisionInSpirv)); + constexpr char kVS[] = R"(#version 310 es +in highp vec4 pos; +in float in0; + +out mediump float tc_in; +void main() +{ + tc_in = in0; + gl_Position = pos; +})"; + + constexpr char kTC[] = R"(#version 310 es +#extension GL_OES_tessellation_shader : require +layout (vertices=3) out; + +in highp float tc_in[]; +out highp float tc_out[]; +void main() +{ + tc_out[gl_InvocationID] = tc_in[gl_InvocationID] * 50.0; + barrier(); + float resultFromOtherInvocation = 0.0; + if (gl_InvocationID==0) { + resultFromOtherInvocation = tc_out[1]; + } + if (gl_InvocationID==1) { + resultFromOtherInvocation = tc_out[2]; + } + if (gl_InvocationID==2) { + resultFromOtherInvocation = tc_out[0]; + } + barrier(); + tc_out[gl_InvocationID] = resultFromOtherInvocation / (50.0 * 10000.0); + gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; + gl_TessLevelInner[0] = 2.0; + gl_TessLevelInner[1] = 2.0; + gl_TessLevelOuter[0] = 2.0; + gl_TessLevelOuter[1] = 2.0; + gl_TessLevelOuter[2] = 2.0; + gl_TessLevelOuter[3] = 2.0; +})"; + + constexpr char kTE[] = R"(#version 310 es +#extension GL_OES_tessellation_shader : require +layout (triangles) in; + +in lowp float tc_out[]; +out mediump float te_out; +void main() +{ + te_out = tc_out[2]; + gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position; +} +)"; + + constexpr char kFS[] = R"(#version 310 es +precision mediump float; +bool isOk (float a, float b, float eps) { return (abs(a-b) <= (eps*abs(b) + eps)); } +layout(location = 0) out mediump vec4 fragColor; +uniform float ref_out0; +float out0; + +in mediump float te_out; +void main() +{ + out0 = te_out; + bool res = isOk(out0, ref_out0, 0.05); + fragColor = vec4(res, res, res, 1.0); +} +)"; + + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTC, kTE, kFS); + glUseProgram(program); + glUniform1f(glGetUniformLocation(program, "ref_out0"), 3.0); + GLint vertexPosLocation = glGetAttribLocation(program, "pos"); + std::array quadVertices = GetQuadVertices(); + glVertexAttribPointer(vertexPosLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data()); + glEnableVertexAttribArray(vertexPosLocation); + GLint vertexIn0Location = glGetAttribLocation(program, "in0"); + std::array quadAttribs = {30000.0, 20000.0, 10000.0, 30000.0, 20000.0, 10000.0}; + glVertexAttribPointer(vertexIn0Location, 1, GL_FLOAT, GL_FALSE, 0, quadAttribs.data()); + glEnableVertexAttribArray(vertexIn0Location); + glDrawArrays(GL_PATCHES, 0, 6); + glDisableVertexAttribArray(vertexPosLocation); + glVertexAttribPointer(vertexPosLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); + glDisableVertexAttribArray(vertexIn0Location); + glVertexAttribPointer(vertexIn0Location, 1, GL_FLOAT, GL_FALSE, 0, nullptr); + + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white); +} + // Tests struct in function return type. TEST_P(GLSLTest, StructInFunctionDefinition) { @@ -20316,6 +20934,33 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test that a struct used without any variables instantiated out of it works. +TEST_P(GLSLTest, StructUsedWithoutVariable) +{ + const char kFragmentShader[] = R"(precision mediump float; + +struct S +{ + float f; + int i; +}; + +void main() +{ + float f = S(0.5, 2).f; + gl_FragColor = vec4( + f, + S(0.75, 1).i, + 0, 1); +})"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader); + glUseProgram(program); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 255, 0, 255), 1); +} + // Test that struct declarations are introduced into the correct scope. TEST_P(GLSLTest, NestedReturnedStructs) { @@ -20568,105 +21213,1047 @@ void main() verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white); } -// Fuzzer test involving struct samplers and comma operator -TEST_P(GLSLTest, StructSamplerVsComma) -{ - constexpr char kVS[] = R"(uniform struct S1 -{ - samplerCube ar; - vec2 c; -} a; - -struct S2 -{ - vec3 c; -} b[2]; - -void main (void) -{ - ++b[0].c,a; -})"; - - GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS); - EXPECT_NE(0u, shader); - glDeleteShader(shader); -} - // Make sure there is no name look up clash when initializing output variables TEST_P(GLSLTest_ES3_InitShaderVariables, NameLookup) { constexpr char kFS[] = R"(#version 300 es out highp vec4 color; + +void make_color_active() +{ + color.zw = vec2(1.0); +} + void main() { highp vec4 color; color.x = 1.0; + make_color_active(); } )"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); drawQuad(program, essl3_shaders::PositionAttrib(), 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); ASSERT_GL_NO_ERROR(); } -// Test that lowp and mediump varyings can be correctly matched between VS and FS. -TEST_P(GLSLTest, LowpMediumpVarying) +// Make sure unnamed `out` function parameters are initialized correctly. +TEST_P(GLSLTest_ES3_InitShaderVariables, UnnamedOutParamInPrototype) { - const char kVS[] = R"(varying lowp float lowpVarying; -attribute vec4 position; -void main () + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 o; +void f(out float, out float); +void main() { - lowpVarying = 1.; - gl_Position = position; -})"; - - const char kFS[] = R"(varying mediump float lowpVarying; -void main () + o = vec4(0.5); + // o.g is reset to 0 because of the forceInitShaderVariables feature + f(o.r, o.g); +} +void f(out float r, out float) { - gl_FragColor = vec4(lowpVarying, 0, 0, 1); -})"; - - ANGLE_GL_PROGRAM(program, kVS, kFS); - drawQuad(program, "position", 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + r = 1.0; +} +)"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 0, 127, 127), 1); +} + +// Same as UnnamedOutParamInPrototype, but with nested calls. +TEST_P(GLSLTest_ES3_InitShaderVariables, UnnamedOutParamInPrototype2) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 o; +void f(out float, out float); +void g(out float a, out float b) +{ + f(a, b); +} +void main() +{ + o = vec4(0.75); + // o.g is reset to 0 because of the forceInitShaderVariables feature + g(o.r, o.g); +} +void f(out float r, out float) +{ + r = 0.5; +} +)"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 191, 191), 1); +} + +// Same as UnnamedOutParamInPrototype, but with a non-void function. +TEST_P(GLSLTest_ES3_InitShaderVariables, UnnamedOutParamInPrototype3) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 o; +float f(out float r, out float) +{ + r = 0.75; + return 0.25; +} +void main() +{ + o = vec4(0.5); + float z = f(o.r, o.g); + o.z = z; +} +)"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 63, 127), 1); +} + +// Test that lowp and mediump varyings can be correctly matched between VS and FS. +TEST_P(GLSLTest, LowpMediumpVarying) +{ + const char kVS[] = R"(varying lowp float lowpVarying; +attribute vec4 position; +void main () +{ + lowpVarying = 1.; + gl_Position = position; +})"; + + const char kFS[] = R"(varying mediump float lowpVarying; +void main () +{ + gl_FragColor = vec4(lowpVarying, 0, 0, 1); +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + drawQuad(program, "position", 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); } // Test that a mismatched varying that is unused in fragshader compiles. TEST_P(GLSLTest, MismatchedInactiveVarying) { - const char kVS[] = R"(precision mediump float; + const char kVS[] = R"(precision mediump float; + +attribute vec2 a_position_0; +attribute vec4 a_color_0; + +varying vec4 vertexColor; + +void main() +{ + vertexColor = a_color_0; + gl_Position = vec4(a_position_0, 0.0, 1.0); +})"; + + const char kFS[] = R"(precision highp float; + +uniform vec2 resolution; +uniform vec2 fragOffset; +uniform vec2 fragScale; + +varying vec4 vertexColor; +varying vec2 texCoord; + +void main() +{ + vec2 uv = (fragScale * gl_FragCoord.xy + fragOffset) / resolution; + gl_FragColor = vec4(uv, 1.0, 1.0); +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); +} + +// Test that denorm float values in GLSL are preserved +TEST_P(GLSLTest_ES3, DenormFloatsToIntValues) +{ + ANGLE_SKIP_TEST_IF(!IsVulkan()); + + constexpr char kFS[] = + "#version 300 es\n" + "precision highp float;\n" + "out vec4 out_color;\n" + "uniform float u;\n" + "void main()\n" + "{\n" + " float smallDenormFloat = 1.40129846e-45;\n" + " int smallBits = floatBitsToInt(smallDenormFloat);\n" + " bool smallCorrect = smallBits == 1;\n" + "\n" + " float largeDenormFloat = 1.1754942107e-38f;\n" + " int largeBits = floatBitsToInt(largeDenormFloat);\n" + " bool largeCorrect = largeBits == 0x007FFFFF;\n" + "\n" + " out_color = (smallCorrect && largeCorrect)\n" + " ? vec4(0.0, 1.0, 0.0, 1.0)\n" + " : vec4(1.0, 0.0, 0.0, 1.0);\n" + "}\n"; + + 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 output initialization vs. fragment output arrays +TEST_P(WebGL2GLSLTest, FragmentOutputArray) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +layout(location = 0) out vec4 activeColor; +layout(location = 1) out vec4 inactive[3]; +void main() { + // Make activeColor active without fully initializing it. + activeColor.x += 0.0001; +})"; + + glClearColor(100, 200, 50, 150); + glClear(GL_COLOR_BUFFER_BIT); + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); +} + +// Tests that outparams work when used with globals. +TEST_P(GLSLTest, OutparamWorksGlobal) +{ + constexpr char kFS[] = + R"( + precision mediump float; + float globalX = 0.5; + void f(inout float x) { + x += x; + } + void main() { + f (globalX); + gl_FragColor = vec4(globalX, 1.0, 1.0, 1.0); // white + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Tests that outparams work when used with temporary arrays. +TEST_P(GLSLTest, OutparamWorksTempArray) +{ + constexpr char kFS[] = + R"( + precision mediump float; + void f(inout float x, out float y, in float val) { + y = x; + x = val; + } + void main() { + float arr[3]; + arr[0] = 1.0; + arr[1] = 0.25; + arr[2] = 127.0/255.0; + f (arr[0], arr[1], arr[2]); + // arr[1] = arr[0] = 1.0; + // arr[0] = arr[2] = 0.5; + gl_FragColor = vec4(arr[0], arr[1], arr[2], 1.0); + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(127u, 255u, 127u, 255u)); +} + +// Checks (add-)assigning to a multielement-swizzle where both the LHS and RHS have side effects. +// Doesn't test the LHS side effects. +TEST_P(GLSLTest, ComplicatedMultielementSwizzle1) +{ + + constexpr char kFS[] = + R"( + precision mediump float; + void main() { + int i = 0; + float a = 0.0; + vec4 vecs[2]; + vecs[0] = vec4(0.0); + vecs[1] = vec4(1.0); + vecs[++i].yz += vec2(a++, a++); // vecs[1].yz += vec2(0.0, 1.0); + + gl_FragColor = vecs[1]/255.0; // 1, 1, 2, 1 + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 1, 2, 1)); +} + +// Checks (add-)assigning to a multielement-swizzle where both the LHS and RHS have side effects. +// See GLSL ES 3.0 Spec. 5.8 Assignments: +// "Expressions on the left of an assignment are evaluated before expressions on the right of the +// assignment." +TEST_P(GLSLTest, ComplicatedMultielementSwizzle2) +{ + + constexpr char kFS[] = + R"( + precision mediump float; + void main() { + int i = 0; + float a = 0.0; + vec4 vecs[2]; + vecs[0] = vec4(0.0); + vecs[1] = vec4(1.0); + // Essentially vecs[0].yz = (vecs[1].xy += vec2(0.0, 1.0)); + // Resulting in: + // vecs[1] = vec4(1.0, 2.0, 1.0, 1.0); + // So vecs[1].xy = vec2(1.0, 2.0); + // So vecs[0] = vec4(0.0, 1.0, 2.0, 0.0); + vecs[i++].yz = (vecs[i++].xy += vec2(a++, a++)); + + gl_FragColor = vec4(vecs[0].yz, vecs[1].zw)/255.; // 1, 2, 1, 1 + })"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 1, 1)); +} + +// Checks that ternaries work with params. +TEST_P(GLSLTest, TernariesWithParams1) +{ + constexpr char kFS[] = + R"(precision mediump float; + +float func (in float a, in float b) +{ + return a > b ? -1.0 : 1.0; +} + +void main() +{ + float x = 1.0; + float m = func(x, x); // returns 1.0 + gl_FragColor = vec4(m, m, m, 1.0); +} + +)"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Checks that ternaries work with params and the return value is passed to an outparam. +TEST_P(GLSLTest, TernariesWithParams2) +{ + constexpr char kFS[] = + R"(precision mediump float; + +void func (in float a, in float b, out float ret) +{ + ret = a > b ? -1.0 : 1.0; +} + +void main() +{ + float x = 1.0; + float m; + func(x, x, m); // returns 1.0 + gl_FragColor = vec4(m, m, m, 1.0); +} + +)"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Checks that ternaries work with params where one is an inout param. The inout param is read from +// and written to. +TEST_P(GLSLTest, TernariesWithParams3) +{ + constexpr char kFS[] = + R"(precision mediump float; + +void func (in float a, inout float b) +{ + b = a > b ? -1.0 : 1.0; +} + +void main() +{ + float x = 1.0; + func(x, x); // x = 1.0 + gl_FragColor = vec4(x, x, x, 1.0); +} + +)"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Tests that calling a function with an in parameter as an inout argument works. +TEST_P(GLSLTest, NestedInoutVars1) +{ + + constexpr char kFS[] = + R"(precision mediump float; + +void negate (inout float x); + +float func (in float a, in float b) +{ + negate(a); + if (abs(a-b) < 0.1) { + return -1.0; + } else { + return 1.0; + } +} + +void main() +{ + float x = 1.0; + float m = func(x, x); // returns 1.0 + gl_FragColor = vec4(m, m, m, 1.0); +} + +void negate (inout float x) { x = -x; } + +)"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Tests that calling a function with inout parameters as in, out, and inout arguments works. +TEST_P(GLSLTest, NestedInoutVars2) +{ + constexpr char kFS[] = + R"(precision mediump float; + + float get (in float x); + void set (out float x, in float val); + void negate (inout float x); + + float func (inout float a, inout float b) + { + negate(a); + return abs(a - b) < 0.1 ? -1.0 : 1.0; + } + + void main() + { + float x; + set(x, 1.0); + float m = func(x, x); // returns 1.0 + gl_FragColor = vec4(m, m, m, 1.0); + } + + float get (in float x) { return x; } + void set (out float x, in float val) { x = val; } + void negate (inout float x) { set(x, -get(x)); } + + )"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +// Tests that calling a function with out parameters as out arguments works. +TEST_P(GLSLTest, NestedInoutVars3) +{ + constexpr char kFS[] = + R"(precision mediump float; + + float globVar; + + void g (out float y, out float x) { + x = 127.0/255.0; + y = 1.0; + } + + void f (out float x) { + g(x, x); + } + + void main() + { + f (globVar); + gl_FragColor = vec4(globVar, 0.0, 0.0, 1.0); + } + + )"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + + // According to the GLES spec, it's undefined which order outparams are copied out, so globVar + // could have ended with either 0.5 or 1.0. + GLColor color = angle::ReadColor(0, 0); + ASSERT_GL_NO_ERROR(); + if (color != GLColor::red && color != GLColor(127u, 0u, 0u, 255u)) + { + ADD_FAILURE() << "Got " << color << ", expected white or grey"; + } +} + +// Test that nesting rgb_2_yuv and yuv_2_rgb works. +TEST_P(GLSLTest_ES3, rgbYuvBuiltInNesting1) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + const char kFS[] = R"(#version 300 es +#extension GL_EXT_YUV_target: require +precision mediump float; +const yuvCscStandardEXT conv = itu_601; + +out vec4 color; + +void main() +{ + vec3 rgb = yuv_2_rgb(rgb_2_yuv(vec3(0.2, 0.3, 0.4), conv), conv); + color = vec4(rgb, 1.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51, 77, 102, 255), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that nesting rgb_2_yuv and yuv_2_rgb works. +TEST_P(GLSLTest_ES3, rgbYuvBuiltInNesting2) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + const char kFS[] = R"(#version 300 es +#extension GL_EXT_YUV_target: require +precision mediump float; +const yuvCscStandardEXT conv = itu_601_full_range; + +out vec4 color; + +void main() +{ + vec3 rgb = yuv_2_rgb(vec3(0.1, 0.2, 0.3) + rgb_2_yuv(vec3(0.15, 0.25, 0.35), conv), conv); + color = vec4(rgb, 1.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(171, 17, 205, 255), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that nesting rgb_2_yuv and yuv_2_rgb works. +TEST_P(GLSLTest_ES3, rgbYuvBuiltInNesting3) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + const char kFS[] = R"(#version 300 es +#extension GL_EXT_YUV_target: require +precision mediump float; +const yuvCscStandardEXT conv = itu_709; + +out vec4 color; + +vec3 f(vec3 v) { return v + vec3(0.1); } + +void main() +{ + vec3 rgb = yuv_2_rgb(f(rgb_2_yuv(vec3(0.1, 0.2, 0.3), conv)), conv); + color = vec4(rgb, 1.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(102, 62, 161, 255), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that nesting rgb_2_yuv and yuv_2_rgb works. +TEST_P(GLSLTest_ES3, rgbYuvBuiltInNesting4) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + const char kFS[] = R"(#version 300 es +#extension GL_EXT_YUV_target: require +precision mediump float; +const yuvCscStandardEXT conv = itu_601; + +out vec4 color; + +vec3 f(vec3 v) { return v + vec3(0.1); } + +void main() +{ + vec3 rgb = f(yuv_2_rgb(f(rgb_2_yuv(vec3(0.1, 0.2, 0.3), conv)), conv)); + color = vec4(rgb, 1.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(122, 75, 183, 255), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that using rgb_2_yuv and yuv_2_rgb with different precisions work. +TEST_P(GLSLTest_ES3, rgbYuvBuiltInUsedWithDifferentPrecisions) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + const char kFS[] = R"(#version 300 es +#extension GL_EXT_YUV_target: require +precision mediump float; +const yuvCscStandardEXT conv = itu_601; + +out vec4 color; + +void main() +{ + lowp vec3 rgbLow = vec3(0.1); + mediump vec3 rgbMedium = vec3(0.2); + highp vec3 rgbHigh = vec3(0.3); + + lowp vec3 yuvLow = vec3(0.4); + mediump vec3 yuvMedium = vec3(0.5); + highp vec3 yuvHigh = vec3(0.6); + + color = vec4( + rgb_2_yuv(rgbLow, conv) - rgb_2_yuv(rgbMedium, conv) + rgb_2_yuv(rgbHigh, conv) - + yuv_2_rgb(yuvLow, conv) - yuv_2_rgb(yuvMedium, conv) + yuv_2_rgb(yuvHigh, conv), + 1.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(72, 0, 161, 255), 1); + ASSERT_GL_NO_ERROR(); +} + +// Test that link fails if UBO size is larger than MAX. +TEST_P(GLSLTest_ES3, UBOExceedsMaxSize) +{ + int maxUniformBlockSize = 0; + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize); + // ANGLE limits the UBO size to 64KB, so in practice the test always runs. + ANGLE_SKIP_TEST_IF(maxUniformBlockSize > 65536); -attribute vec2 a_position_0; -attribute vec4 a_color_0; + const char kFS[] = R"(#version 300 es +precision mediump float; +struct S64 +{ + vec4 f[64]; +}; -varying vec4 vertexColor; +layout(std140) uniform Block { + S64 arr[256]; +}; + +out vec4 color; void main() { - vertexColor = a_color_0; - gl_Position = vec4(a_position_0, 0.0, 1.0); + color = vec4(arr[10].f[15]); })"; - const char kFS[] = R"(precision highp float; + GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS); + EXPECT_EQ(0u, program); +} -uniform vec2 resolution; -uniform vec2 fragOffset; -uniform vec2 fragScale; +// Test that link fails if SSBO size is larger than MAX. +TEST_P(GLSLTest_ES31, SSBOExceedsMaxSize) +{ + int maxShaderStorageBlockSize = 0; + glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxShaderStorageBlockSize); + // ANGLE limits the SSBO size to INT_MAX, so in practice the test always runs. + ANGLE_SKIP_TEST_IF(maxShaderStorageBlockSize > 0x7FFF'FFFF); -varying vec4 vertexColor; -varying vec2 texCoord; + const char kFS[] = R"(#version 310 es +precision mediump float; +struct S +{ + vec4 f[8192]; +}; + +layout(std140) buffer Block { + S arr[32768]; +}; + +out vec4 color; void main() { - vec2 uv = (fragScale * gl_FragCoord.xy + fragOffset) / resolution; - gl_FragColor = vec4(uv, 1.0, 1.0); + color = vec4(arr[10].f[15]); })"; + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFS); + EXPECT_EQ(0u, program); +} + +// Test that an unused gl_LastFragDepthARM does not lead to errors +TEST_P(GLSLTest_ES31, UnsedLastFragDepth) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARM_shader_framebuffer_fetch_depth_stencil")); + + const char kFS[] = R"(#extension GL_ARM_shader_framebuffer_fetch_depth_stencil:require +int gl_LastFragDepthARM; +void main() +{ + gl_FragColor = vec4(0, 1, 0, 1); +} +)"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + +// Test that inactive fragment inout variable compiles fine, with inout locations start from +// non-zero +TEST_P(GLSLTest_ES31, InactiveFragmentInout) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + const char kVS[] = R"(#version 310 es + in vec3 POSITION; + void main() + { + gl_Position = vec4(POSITION, 1.0); + })"; + const char kFS[] = R"(#version 310 es + #extension GL_EXT_shader_framebuffer_fetch : require + precision mediump float; + precision highp int; + layout(location = 1) inout highp vec4 activeVar; + layout(location = 2) inout highp vec4 inactiveVar; + void main() + { + activeVar = vec4(0.0, 0.0, 0.0, 1.0); + })"; + ANGLE_GL_PROGRAM(program, kVS, kFS); +} + +// Test that inactive fragment inout variable used in an unused function compiles fine, with inout +// locations start from non-zero +TEST_P(GLSLTest_ES31, InactiveFragmentInoutReferencedInUnusedFunction) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + const char kVS[] = R"(#version 310 es + in vec3 POSITION; + void main() + { + gl_Position = vec4(POSITION, 1.0); + })"; + const char kFS[] = R"(#version 310 es + #extension GL_EXT_shader_framebuffer_fetch : require + precision mediump float; + precision highp int; + layout(location = 1) inout highp vec4 activeVar; + layout(location = 2) inout highp vec4 inactiveVar; + + void unusedFunction() { + vec4 unusedVar = inactiveVar; + } + + void main() + { + activeVar = vec4(0.0, 0.0, 0.0, 1.0); + })"; ANGLE_GL_PROGRAM(program, kVS, kFS); } + +// Test that if the inout variable is inactive, its' location attachment content is preserved +TEST_P(GLSLTest_ES31, testInactiveInoutPreservesAttachmentContent) +{ + const unsigned int kWidth = 2; + const unsigned int kHeight = 2; + + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + const char kFS[] = R"(#version 310 es + #extension GL_EXT_shader_framebuffer_fetch : require + precision mediump float; + precision highp int; + layout(location = 1) inout highp vec4 activeVar; + layout(location = 2) inout highp vec4 inactiveVar; + + void main() + { + activeVar = vec4(0.0, 1.0, 0.0, 1.0); + })"; + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + // Fill texture1 with red color + const std::array texture1Data = {GLColor::red, GLColor::red, + GLColor::red, GLColor::red}; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + &texture1Data[0]); + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + // Fill texture2 with blue color + const std::array texture2Data = {GLColor::blue, GLColor::blue, + GLColor::blue, GLColor::blue}; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kHeight, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + &texture2Data[0]); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture1, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, texture2, 0); + + GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2}; + glDrawBuffers(3, drawBuffers); + glUseProgram(program); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f); + + // Verify that texture1 changes to green, texture2 remains unchanged. + GLFramebuffer verifyTextureFBO; + glBindFramebuffer(GL_FRAMEBUFFER, verifyTextureFBO); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); +} + +// Tests pack/unpack emulation in the shader translator. +class GLSLTest_ES3_PackUnpackEmulation : public GLSLTest_ES3 +{ + protected: + void testUnsignedInt(GLuint program, uint32_t expect); + void testFloat(GLuint program, float r, float g, float b, float a); +}; + +void GLSLTest_ES3_PackUnpackEmulation::testUnsignedInt(GLuint program, uint32_t expect) +{ + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_GL_NO_ERROR(); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_EQ(expect, static_cast(GetFirstIntPixelRedValue())); + EXPECT_GL_NO_ERROR(); +} + +void GLSLTest_ES3_PackUnpackEmulation::testFloat(GLuint program, float r, float g, float b, float a) +{ + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_GL_NO_ERROR(); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_32F_NEAR(0, 0, r, g, b, a, 1e-6); + EXPECT_GL_NO_ERROR(); +} + +// Verify correct emulation of packSnorm2x16 +TEST_P(GLSLTest_ES3_PackUnpackEmulation, PackSnorm2x16) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +precision highp int; +uniform vec2 u; +out uvec4 color; +void main() +{ + uint v = packSnorm2x16(u); + color = uvec4(v, 0, 0, 0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + glUniform2f(glGetUniformLocation(program, "u"), 4096.0 / 32767.0, -8192.0 / 32767.0); + testUnsignedInt(program, 0xE000'1000); +} + +// Verify correct emulation of unpackSnorm2x16 +TEST_P(GLSLTest_ES3_PackUnpackEmulation, UnpackSnorm2x16) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +precision highp int; +uniform uint u; +out vec4 color; +void main() +{ + vec2 v = unpackSnorm2x16(u); + color = vec4(v, 0.0, 0.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + glUniform1ui(glGetUniformLocation(program, "u"), 0xE0001000); + testFloat(program, 4096.0 / 32767.0, -8192.0 / 32767.0, 0, 0); +} + +// Verify correct emulation of packUnorm2x16 +TEST_P(GLSLTest_ES3_PackUnpackEmulation, PackUnorm2x16) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +precision highp int; +uniform vec2 u; +out uvec4 color; +void main() +{ + uint v = packUnorm2x16(u); + color = uvec4(v, 0, 0, 0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + glUniform2f(glGetUniformLocation(program, "u"), 64.0 / 65535.0, 16384.0 / 65535.0); + testUnsignedInt(program, 0x4000'0040); +} + +// Verify correct emulation of unpackSnorm2x16 +TEST_P(GLSLTest_ES3_PackUnpackEmulation, UnpackUnorm2x16) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +precision highp int; +uniform uint u; +out vec4 color; +void main() +{ + vec2 v = unpackUnorm2x16(u); + color = vec4(v, 0.0, 0.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + glUniform1ui(glGetUniformLocation(program, "u"), 0x4000'0040); + testFloat(program, 64.0 / 65535.0, 16384.0 / 65535.0, 0, 0); +} + +// Verify correct emulation of packHalf2x16 +TEST_P(GLSLTest_ES3_PackUnpackEmulation, PackHalf2x16) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +precision highp int; +uniform vec2 u; +out uvec4 color; +void main() +{ + uint v = packHalf2x16(u); + color = uvec4(v, 0, 0, 0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + glUniform2f(glGetUniformLocation(program, "u"), 47.03125, -20.6875); + testUnsignedInt(program, 0xCD2C'51E1); +} + +// Verify correct emulation of unpackHalf2x16 +TEST_P(GLSLTest_ES3_PackUnpackEmulation, UnpackHalf2x16) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +precision highp int; +uniform uint u; +out vec4 color; +void main() +{ + vec2 v = unpackHalf2x16(u); + color = vec4(v, 0.0, 0.0); +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + glUniform1ui(glGetUniformLocation(program, "u"), 0xCD2C'51E1); + testFloat(program, 47.03125, -20.6875, 0, 0); +} + +// Regression test for a bug where the translator assumed the last case can be simply pruned because +// it is no-op. +TEST_P(GLSLTest_ES3, EmptyLastCaseInSwitch) +{ + // Incorrect translation before IR. + ANGLE_SKIP_TEST_IF(!getEGLWindow()->isFeatureEnabled(Feature::UseIr)); + + constexpr char kFS[] = R"(#version 300 es +uniform int ui; +out mediump vec4 color; + +void main(void) +{ + color = vec4(1, 0, 0, 1); + + int i = ui; + switch (i) + { + default: + // This shouldn't run, because `ui` is zero. + color = vec4(0, 1, 0, 1); + break; + case 0: + int j; + 1; + } +})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + ASSERT_GL_NO_ERROR(); +} + +// Test that if the uniform struct specifier is referenced by non-uniform variables, the +// sortUniforms() step does not reorder the uniform struct specifier and place it after where it is +// referenced. +TEST_P(GLSLTest_ES3, UniformStructSpecifierIsReferencedByNonUniforms) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +uniform struct b{vec2 S;}t; +struct{b x;}; +out vec4 color; +void main() +{ + color = vec4(1.0, 0.0, 0.0, 1.0); +})"; + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_GL_NO_ERROR(); +} + } // anonymous namespace -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_ES32( GLSLTest, ES3_OPENGL().enable(Feature::ForceInitShaderVariables), ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs), @@ -20693,17 +22280,28 @@ ANGLE_INSTANTIATE_TEST_ES3(GLSLTestLoops); ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ClampPointSize); +ANGLE_INSTANTIATE_TEST_ES2_AND(GLSLTest_ClampPointSize, + ES2_OPENGL().enable(Feature::ClampPointSize), + ES2_VULKAN().enable(Feature::ClampPointSize)); + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest); ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31); -ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31, - ES31_VULKAN().enable(Feature::ForceInitShaderVariables), - ES31_VULKAN().disable(Feature::SupportsSPIRV14)); +ANGLE_INSTANTIATE_TEST_ES31_AND( + GLSLTest_ES31, + ES31_VULKAN().enable(Feature::ForceInitShaderVariables), + ES31_VULKAN().enable(Feature::VaryingsRequireMatchingPrecisionInSpirv), + ES31_VULKAN().disable(Feature::SupportsSPIRV14)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3_InitShaderVariables); ANGLE_INSTANTIATE_TEST( GLSLTest_ES3_InitShaderVariables, + ES3_D3D11().enable(Feature::ForceInitShaderVariables), + ES3_OPENGL().enable(Feature::ForceInitShaderVariables), + ES3_OPENGLES().enable(Feature::ForceInitShaderVariables), + ES3_METAL().enable(Feature::ForceInitShaderVariables), ES3_VULKAN().enable(Feature::ForceInitShaderVariables), ES3_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables)); @@ -20712,3 +22310,12 @@ ANGLE_INSTANTIATE_TEST( GLSLTest_ES31_InitShaderVariables, ES31_VULKAN().enable(Feature::ForceInitShaderVariables), ES31_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3_PackUnpackEmulation); +ANGLE_INSTANTIATE_TEST(GLSLTest_ES3_PackUnpackEmulation, + ES3_D3D11(), + ES3_OPENGL(), + ES3_OPENGL().enable(Feature::EmitMaxGlsl400ForTesting), + ES3_OPENGLES(), + ES3_METAL(), + ES3_VULKAN()); diff --git a/src/tests/gl_tests/GLSLValidationTest.cpp b/src/tests/gl_tests/GLSLValidationTest.cpp new file mode 100644 index 00000000000..1ebe4adb6a1 --- /dev/null +++ b/src/tests/gl_tests/GLSLValidationTest.cpp @@ -0,0 +1,7007 @@ +// +// Copyright 2025 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. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "test_utils/CompilerTest.h" +#include "test_utils/angle_test_configs.h" + +using namespace angle; + +namespace +{ +class GLSLValidationTest : public CompilerTest +{ + protected: + GLSLValidationTest() {} + + // Helper to create a shader, then verify that it fails to compile with the given reason. It's + // given: + // + // * The type of shader. + // * The shader source itself. + // * An error string to look for in the compile logs. + void validateError(GLenum shaderType, const char *shaderSource, const char *expectedError) + { + const CompiledShader &shader = compile(shaderType, shaderSource); + EXPECT_FALSE(shader.success()); + + EXPECT_TRUE(shader.hasInfoLog(expectedError)) << expectedError; + reset(); + } + + // Helper to create a shader, then verify that compilation succeeded. + void validateSuccess(GLenum shaderType, const char *shaderSource) + { + const CompiledShader &shader = compile(shaderType, shaderSource); + EXPECT_TRUE(shader.success()); + reset(); + } + + void validateWarning(GLenum shaderType, const char *shaderSource, const char *expectedWarning) + { + const CompiledShader &shader = compile(shaderType, shaderSource); + EXPECT_TRUE(shader.success()); + + EXPECT_TRUE(shader.hasInfoLog(expectedWarning)) << expectedWarning; + reset(); + } +}; + +class GLSLValidationTest_ES3 : public GLSLValidationTest +{}; + +class GLSLValidationTest_ES31 : public GLSLValidationTest +{}; + +class GLSLValidationTestNoValidation : public GLSLValidationTest +{ + public: + GLSLValidationTestNoValidation() { setNoErrorEnabled(true); } +}; + +class WebGLGLSLValidationTest : public GLSLValidationTest +{ + protected: + WebGLGLSLValidationTest() { setWebGLCompatibilityEnabled(true); } +}; + +class WebGL2GLSLValidationTest : public GLSLValidationTest_ES3 +{ + protected: + WebGL2GLSLValidationTest() { setWebGLCompatibilityEnabled(true); } + + void testInfiniteLoop(const char *fs) + { + const CompiledShader &shader = compile(GL_FRAGMENT_SHADER, fs); + EXPECT_FALSE(shader.success()); + reset(); + } +}; + +// Test that an empty shader fails to compile +TEST_P(GLSLValidationTest, EmptyShader) +{ + constexpr char kFS[] = ""; + validateError(GL_FRAGMENT_SHADER, kFS, "syntax error"); +} + +// Test that a shader with no main in it fails to compile +TEST_P(GLSLValidationTest, MissingMain) +{ + constexpr char kFS[] = R"(precision mediump float;)"; + validateError(GL_FRAGMENT_SHADER, kFS, "Missing main()"); +} + +// Test that a shader with only a main prototype in it fails to compile +TEST_P(GLSLValidationTest, MainPrototypeOnly) +{ + constexpr char kFS[] = R"(precision mediump float; +void main(); +)"; + validateError(GL_FRAGMENT_SHADER, kFS, "Missing main()"); +} + +// Test relational operations between bools is rejected. +TEST_P(GLSLValidationTest, BoolLessThan) +{ + constexpr char kFS[] = R"(uniform mediump vec4 u; +void main() { + bool a = bool(u.x); + bool b = bool(u.y); + bool c = a < b; + gl_FragColor = vec4(c, !c, c, !c); +} +)"; + validateError(GL_FRAGMENT_SHADER, kFS, "'<' : comparison operator not defined for booleans"); +} + +// This is a test for a bug that used to exist in ANGLE: +// Calling a function with all parameters missing should not succeed. +TEST_P(GLSLValidationTest, FunctionParameterMismatch) +{ + constexpr char kFS[] = R"( + precision mediump float; + float fun(float a) { + return a * 2.0; + } + void main() { + float ff = fun(); + gl_FragColor = vec4(ff); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'fun' : no matching overloaded function found"); +} + +// Functions can't be redeclared as variables in the same scope (ESSL 1.00 section 4.2.7) +TEST_P(GLSLValidationTest, RedeclaringFunctionAsVariable) +{ + constexpr char kFS[] = R"( + precision mediump float; + float fun(float a) { + return a * 2.0; + } + + float fun; + void main() { + gl_FragColor = vec4(0.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'fun' : redefinition"); +} + +// Functions can't be redeclared as structs in the same scope (ESSL 1.00 section 4.2.7) +TEST_P(GLSLValidationTest, RedeclaringFunctionAsStruct) +{ + constexpr char kFS[] = R"( + precision mediump float; + float fun(float a) { + return a * 2.0; + } + struct fun { float a; }; + void main() { + gl_FragColor = vec4(0.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'fun' : redefinition of a struct"); +} + +// Functions can't be redeclared with different qualifiers (ESSL 1.00 section 6.1.0) +TEST_P(GLSLValidationTest, RedeclaringFunctionWithDifferentQualifiers) +{ + constexpr char kFS[] = R"( + precision mediump float; + float fun(out float a); + float fun(float a) { + return a * 2.0; + } + void main() { + gl_FragColor = vec4(0.0); + } + )"; + + validateError( + GL_FRAGMENT_SHADER, kFS, + "'in' : function must have the same parameter qualifiers in all of its declarations"); +} + +// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7) +TEST_P(GLSLValidationTest, CompareStructsContainingArrays) +{ + constexpr char kFS[] = R"( + precision mediump float; + struct s { float a[3]; }; + void main() { + s a; + s b; + bool c = (a == b); + gl_FragColor = vec4(c ? 1.0 : 0.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'==' : undefined operation for structs containing arrays"); +} + +// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7) +TEST_P(GLSLValidationTest, AssignStructsContainingArrays) +{ + constexpr char kFS[] = R"( + precision mediump float; + struct s { float a[3]; }; + void main() { + s a; + s b; + b.a[0] = 0.0; + a = b; + gl_FragColor = vec4(a.a[0]); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : undefined operation for structs containing arrays"); +} + +// Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7 +// and 5.9) +TEST_P(GLSLValidationTest, CompareStructsContainingSamplers) +{ + constexpr char kFS[] = R"( + precision mediump float; + struct s { sampler2D foo; }; + uniform s a; + uniform s b; + void main() { + bool c = (a == b); + gl_FragColor = vec4(c ? 1.0 : 0.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'==' : undefined operation for structs containing samplers"); +} + +// Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this +// extends to structs containing samplers. ESSL 1.00 spec is clearer about this. +TEST_P(GLSLValidationTest_ES3, AssignStructsContainingSamplers) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + struct s { sampler2D foo; }; + uniform s a; + out vec4 my_FragColor; + void main() { + s b; + b = a; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'structure' : structures must be uniform (structure contains a sampler)"); +} + +// This is a regression test for a particular bug that was in ANGLE. +// It also verifies that ESSL3 functionality doesn't leak to ESSL1. +TEST_P(GLSLValidationTest, ArrayWithNoSizeInInitializerList) +{ + constexpr char kFS[] = R"( + precision mediump float; + void main() { + float a[2], b[]; + gl_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + " '[]' : implicitly sized array supported in GLSL ES 3.00 and above only"); +} + +// Const variables need an initializer. +TEST_P(GLSLValidationTest_ES3, ConstVarNotInitialized) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float a; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'a' : variables with qualifier 'const' must be initialized"); +} + +// Const variables need an initializer. In ESSL1 const structs containing +// arrays are not allowed at all since it's impossible to initialize them. +// Even though this test is for ESSL3 the only thing that's critical for +// ESSL1 is the non-initialization check that's used for both language versions. +// Whether ESSL1 compilation generates the most helpful error messages is a +// secondary concern. +TEST_P(GLSLValidationTest_ES3, ConstStructNotInitialized) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + struct S { float a[3]; }; + out vec4 my_FragColor; + void main() { + const S b; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'b' : variables with qualifier 'const' must be initialized"); +} + +// Const variables need an initializer. In ESSL1 const arrays are not allowed +// at all since it's impossible to initialize them. +// Even though this test is for ESSL3 the only thing that's critical for +// ESSL1 is the non-initialization check that's used for both language versions. +// Whether ESSL1 compilation generates the most helpful error messages is a +// secondary concern. +TEST_P(GLSLValidationTest_ES3, ConstArrayNotInitialized) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + const float a[3]; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'a' : variables with qualifier 'const' must be initialized"); +} + +// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3) +TEST_P(GLSLValidationTest_ES3, BlockLayoutQualifierOnRegularUniform) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + layout(packed) uniform mat2 x; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'packed' : layout qualifier only valid for interface blocks"); +} + +// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3) +TEST_P(GLSLValidationTest_ES3, BlockLayoutQualifierOnUniformWithEmptyDecl) +{ + // Yes, the comma in the declaration below is not a typo. + // Empty declarations are allowed in GLSL. + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + layout(packed) uniform mat2, x; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'packed' : layout qualifier only valid for interface blocks"); +} + +// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9) +TEST_P(GLSLValidationTest_ES3, ArraysOfArrays1) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + float[5] a[3]; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'mediump array[5] of float' : cannot declare arrays of arrays"); +} + +// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9) +TEST_P(GLSLValidationTest_ES3, ArraysOfArrays2) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + float[2] a, b[3]; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "mediump array[2] of float' : cannot declare arrays of arrays"); +} + +// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9). Test this in a struct. +TEST_P(GLSLValidationTest_ES3, ArraysOfArraysInStruct) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + struct S { float[2] foo[3]; }; + void main() { my_FragColor = vec4(1.0); } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'mediump array[2] of float' : cannot declare arrays of arrays"); +} + +// Test invalid dimensionality of implicitly sized array constructor arguments. +TEST_P(GLSLValidationTest_ES31, + TooHighDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments) +{ + constexpr char kFS[] = R"(#version 310 es + precision mediump float; + out vec4 my_FragColor; + void main() { + float[][] a = float[][](float[1][1](float[1](1.0)), float[1][1](float[1](2.0))); + my_FragColor = vec4(a[0][0]); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : constructing from a non-dereferenced array"); +} + +// Test invalid dimensionality of implicitly sized array constructor arguments. +TEST_P(GLSLValidationTest_ES31, + TooLowDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments) +{ + constexpr char kFS[] = R"(#version 310 es + precision mediump float; + out vec4 my_FragColor; + void main() { + float[][][] a = float[][][](float[2](1.0, 2.0), float[2](3.0, 4.0)); + my_FragColor = vec4(a[0][0][0]); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : implicitly sized array of arrays constructor argument " + "dimensionality is too low"); +} + +// Implicitly sized arrays need to be initialized (ESSL 3.00 section 4.1.9) +TEST_P(GLSLValidationTest_ES3, UninitializedImplicitArraySize) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + float[] a; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'a' : implicitly sized arrays only allowed for tessellation shaders or geometry " + "shader inputs"); +} + +// An operator can only form a constant expression if all the operands are constant expressions +// - even operands of ternary operator that are never evaluated. (ESSL 3.00 section 4.3.3) +TEST_P(GLSLValidationTest_ES3, TernaryOperatorNotConstantExpression) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform bool u; + void main() { + const bool a = true ? true : u; + my_FragColor = vec4(1.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'=' : assigning non-constant to 'const bool'"); +} + +// Ternary operator can operate on arrays (ESSL 3.00 section 5.7) +TEST_P(GLSLValidationTest_ES3, TernaryOperatorOnArrays) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + float[1] a = float[1](0.0); + float[1] b = float[1](1.0); + float[1] c = true ? a : b; + my_FragColor = vec4(1.0); + } + )"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Ternary operator can operate on structs (ESSL 3.00 section 5.7) +TEST_P(GLSLValidationTest_ES3, TernaryOperatorOnStructs) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + struct S { float foo; }; + void main() { + S a = S(0.0); + S b = S(1.0); + S c = true ? a : b; + my_FragColor = vec4(1.0); + } + )"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Array length() returns a constant signed integral expression (ESSL 3.00 section 4.1.9) +// Assigning it to unsigned should result in an error. +TEST_P(GLSLValidationTest_ES3, AssignArrayLengthToUnsigned) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + int[1] arr; + uint l = arr.length(); + my_FragColor = vec4(float(l)); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : cannot convert from 'const highp int' to 'mediump uint'"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with a varying should be an error. +TEST_P(GLSLValidationTest, AssignVaryingToGlobal) +{ + constexpr char kFS[] = R"( + precision mediump float; + varying float a; + float b = a * 2.0; + void main() { + gl_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) +// Initializing with an uniform should be an error. +TEST_P(GLSLValidationTest_ES3, AssignUniformToGlobalESSL3) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform float a; + float b = a * 2.0; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an uniform used to generate a warning on ESSL 1.00 because of legacy +// compatibility, but that causes dEQP to fail (which expects an error) +TEST_P(GLSLValidationTest, AssignUniformToGlobalESSL1) +{ + constexpr char kFS[] = R"( + precision mediump float; + uniform float a; + float b = a * 2.0; + void main() { + gl_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an user-defined function call should be an error. +TEST_P(GLSLValidationTest, AssignFunctionCallToGlobal) +{ + constexpr char kFS[] = R"( + precision mediump float; + float foo() { return 1.0; } + float b = foo(); + void main() { + gl_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an assignment to another global should be an error. +TEST_P(GLSLValidationTest, AssignAssignmentToGlobal) +{ + constexpr char kFS[] = R"( + precision mediump float; + float c = 1.0; + float b = (c = 0.0); + void main() { + gl_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + " '=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with incrementing another global should be an error. +TEST_P(GLSLValidationTest, AssignIncrementToGlobal) +{ + constexpr char kFS[] = R"( + precision mediump float; + float c = 1.0; + float b = (c++); + void main() { + gl_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + " '=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an assignment to another global should be an error. +TEST_P(GLSLValidationTest, AssignTexture2DToGlobal) +{ + constexpr char kFS[] = R"( + precision mediump float; + uniform mediump sampler2D s; + float b = texture2D(s, vec2(0.5, 0.5)).x; + void main() { + gl_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) +// Initializing with a non-constant global should be an error. +TEST_P(GLSLValidationTest_ES3, AssignNonConstGlobalToGlobal) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + float a = 1.0; + float b = a * 2.0; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(b); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers must be constant expressions"); +} + +// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) +// Initializing with a constant global should be fine. +TEST_P(GLSLValidationTest_ES3, AssignConstGlobalToGlobal) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + const float a = 1.0; + float b = a * 2.0; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(b); + } + )"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Statically assigning to both gl_FragData and gl_FragColor is forbidden (ESSL 1.00 section 7.2) +TEST_P(GLSLValidationTest, WriteBothFragDataAndFragColor) +{ + constexpr char kFS[] = R"( + precision mediump float; + void foo() { + gl_FragData[0].a++; + } + void main() { + gl_FragColor.x += 0.0; + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "cannot use both gl_FragData and gl_FragColor"); +} + +// Version directive must be on the first line (ESSL 3.00 section 3.3) +TEST_P(GLSLValidationTest_ES3, VersionOnSecondLine) +{ + constexpr char kFS[] = R"( + #version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0.0); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "#version directive must occur on the first line of the shader"); +} + +// Layout qualifier can only appear in global scope (ESSL 3.00 section 4.3.8) +TEST_P(GLSLValidationTest_ES3, LayoutQualifierInCondition) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform vec4 u; + out vec4 my_FragColor; + void main() { + int i = 0; + for (int j = 0; layout(location = 0) bool b = false; ++j) { + ++i; + } + my_FragColor = u; + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'layout' : only allowed at global scope"); +} + +// Layout qualifier can only appear where specified (ESSL 3.00 section 4.3.8) +TEST_P(GLSLValidationTest_ES3, LayoutQualifierInFunctionReturnType) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform vec4 u; + out vec4 my_FragColor; + layout(location = 0) vec4 foo() { + return u; + } + void main() { + my_FragColor = foo(); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'layout' : no qualifiers allowed for function return"); +} + +// If there is more than one output, the location must be specified for all outputs. +// (ESSL 3.00.04 section 4.3.8.2) +TEST_P(GLSLValidationTest_ES3, TwoOutputsNoLayoutQualifiers) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform vec4 u; + out vec4 my_FragColor; + out vec4 my_SecondaryFragColor; + void main() { + my_FragColor = vec4(1.0); + my_SecondaryFragColor = vec4(0.5); + } + )"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'my_FragColor' : when EXT_blend_func_extended extension is not enabled, must " + "explicitly specify all locations when using multiple fragment outputs"); +} + +// (ESSL 3.00.04 section 4.3.8.2) +TEST_P(GLSLValidationTest_ES3, TwoOutputsFirstLayoutQualifier) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform vec4 u; + layout(location = 0) out vec4 my_FragColor; + out vec4 my_SecondaryFragColor; + void main() { + my_FragColor = vec4(1.0); + my_SecondaryFragColor = vec4(0.5); + })"; + + validateError( + GL_FRAGMENT_SHADER, kFS, + "'my_SecondaryFragColor' : when EXT_blend_func_extended extension is not enabled, must " + "explicitly specify all locations when using multiple fragment outputs"); +} + +// (ESSL 3.00.04 section 4.3.8.2) +TEST_P(GLSLValidationTest_ES3, TwoOutputsSecondLayoutQualifier) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform vec4 u; + out vec4 my_FragColor; + layout(location = 0) out vec4 my_SecondaryFragColor; + void main() { + my_FragColor = vec4(1.0); + my_SecondaryFragColor = vec4(0.5); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'my_FragColor' : when EXT_blend_func_extended extension is not enabled, must " + "explicitly specify all locations when using multiple fragment outputs"); +} + +// Uniforms can be arrays (ESSL 3.00 section 4.3.5) +TEST_P(GLSLValidationTest_ES3, UniformArray) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform vec4[2] u; + out vec4 my_FragColor; + void main() { + my_FragColor = u[0]; + })"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Fragment shader input variables cannot be arrays of structs (ESSL 3.00 section 4.3.4) +TEST_P(GLSLValidationTest_ES3, FragmentInputArrayOfStructs) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + struct S { + vec4 foo; + }; + in S i[2]; + out vec4 my_FragColor; + void main() { + my_FragColor = i[0].foo; + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "cannot declare arrays of structs of this qualifier"); +} + +// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4) +// This test is testing the case where the array brackets are after the variable name, so +// the arrayness isn't known when the type and qualifiers are initially parsed. +TEST_P(GLSLValidationTest_ES3, VertexShaderInputArray) +{ + constexpr char kVS[] = R"(#version 300 es + precision mediump float; + in vec4 i[2]; + void main() { + gl_Position = i[0]; + })"; + + validateError(GL_VERTEX_SHADER, kVS, "'in' : cannot declare arrays of this qualifier"); +} + +// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4) +// This test is testing the case where the array brackets are after the type. +TEST_P(GLSLValidationTest_ES3, VertexShaderInputArrayType) +{ + constexpr char kVS[] = R"(#version 300 es + precision mediump float; + in vec4[2] i; + void main() { + gl_Position = i[0]; + })"; + + validateError(GL_VERTEX_SHADER, kVS, "'in' : cannot be array"); +} + +// Fragment shader inputs can't contain booleans (ESSL 3.00 section 4.3.4) +TEST_P(GLSLValidationTest_ES3, FragmentShaderInputStructWithBool) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + struct S { bool foo; }; + in S s; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, " 'in' : cannot be a structure containing a bool"); +} + +// Fragment shader inputs without a flat qualifier can't contain integers (ESSL 3.00 section 4.3.4) +TEST_P(GLSLValidationTest_ES3, FragmentShaderInputStructWithInt) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + struct S { int foo; }; + in S s; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'in' : must use 'flat' interpolation here"); +} + +// Test that out-of-range integer literal generates an error in ESSL 3.00. +TEST_P(GLSLValidationTest_ES3, OutOfRangeIntegerLiteral) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + precision highp int; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0x100000000); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'0x100000000' : Integer overflow"); +} + +// Test that a ternary operator with one unevaluated non-constant operand is not a constant +// expression. +TEST_P(GLSLValidationTest, TernaryOperatorNonConstantOperand) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform float u; + void main() { + const float f = true ? 1.0 : u; + gl_FragColor = vec4(f); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'=' : assigning non-constant to 'const mediump float'"); +} + +// Test that a sampler can't be used in constructor argument list +TEST_P(GLSLValidationTest, SamplerInConstructorArguments) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform sampler2D s; + void main() + { + vec2 v = vec2(0.0, s); + gl_FragColor = vec4(v, 0.0, 0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : cannot convert a variable with type sampler2D"); +} + +// Test that void can't be used in constructor argument list +TEST_P(GLSLValidationTest, VoidInConstructorArguments) +{ + constexpr char kFS[] = R"(precision mediump float; + void foo() {} + void main() + { + vec2 v = vec2(0.0, foo()); + gl_FragColor = vec4(v, 0.0, 0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'constructor' : cannot convert a void"); +} + +// Test that a shader with empty constructor parameter list is not accepted. +TEST_P(GLSLValidationTest_ES3, EmptyArrayConstructor) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform float u; + const float[] f = float[](); + void main() { + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'[]' : implicitly sized array constructor must have at least one argument"); +} + +// Test that indexing fragment outputs with a non-constant expression is forbidden, even if ANGLE +// is able to constant fold the index expression. ESSL 3.00 section 4.3.6. +TEST_P(GLSLValidationTest_ES3, DynamicallyIndexedFragmentOutput) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform int a; + out vec4[2] my_FragData; + void main() + { + my_FragData[true ? 0 : a] = vec4(0.0); + } + )"; + + validateError( + GL_FRAGMENT_SHADER, kFS, + " '[' : array indexes for fragment outputs must be constant integral expressions"); +} + +// Test that indexing a uniform buffer array with a non-constant expression is forbidden, even if +// ANGLE is able to constant fold the index expression. ESSL 3.00 section 4.3.7. +TEST_P(GLSLValidationTest_ES3, DynamicallyIndexedUniformBuffer) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform int a; + uniform B + { + vec4 f; + } + blocks[2]; + out vec4 my_FragColor; + void main() + { + my_FragColor = blocks[true ? 0 : a].f; + })"; + + validateError( + GL_FRAGMENT_SHADER, kFS, + "'[' : array indexes for uniform block arrays must be constant integral expressions"); +} + +// Test that indexing a storage buffer array with a non-constant expression is forbidden, even if +// ANGLE is able to constant fold the index expression. ESSL 3.10 section 4.3.9. +TEST_P(GLSLValidationTest_ES31, DynamicallyIndexedStorageBuffer) +{ + constexpr char kFS[] = R"(#version 310 es + precision mediump float; + uniform int a; + layout(std140) buffer B + { + vec4 f; + } + blocks[2]; + out vec4 my_FragColor; + void main() + { + my_FragColor = blocks[true ? 0 : a].f; + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'[' : array indexes for shader storage block arrays must be constant integral " + "expressions"); +} + +// Test that indexing a sampler array with a non-constant expression is forbidden, even if ANGLE is +// able to constant fold the index expression. ESSL 3.00 section 4.1.7.1. +TEST_P(GLSLValidationTest_ES3, DynamicallyIndexedSampler) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform int a; + uniform sampler2D s[2]; + out vec4 my_FragColor; + void main() + { + my_FragColor = texture(s[true ? 0 : a], vec2(0)); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'[' : array index for samplers must be constant integral expressions"); +} + +// Test that indexing an image array with a non-constant expression is forbidden, even if ANGLE is +// able to constant fold the index expression. ESSL 3.10 section 4.1.7.2. +TEST_P(GLSLValidationTest_ES31, DynamicallyIndexedImage) +{ + constexpr char kFS[] = R"(#version 310 es + precision mediump float; + uniform int a; + layout(rgba32f) uniform highp readonly image2D image[2]; + out vec4 my_FragColor; + void main() + { + my_FragColor = imageLoad(image[true ? 0 : a], ivec2(0)); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + " '[' : array indexes for image arrays must be constant integral expressions"); +} + +// Test that a shader that uses a struct definition in place of a struct constructor does not +// compile. See GLSL ES 1.00 section 5.4.3. +TEST_P(GLSLValidationTest, StructConstructorWithStructDefinition) +{ + constexpr char kFS[] = R"(precision mediump float; + void main() { + struct s { float f; } (0.0); + gl_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'structure' : constructor can't be a structure definition"); +} + +// Test that indexing gl_FragData with a non-constant expression is forbidden in WebGL 2.0, even +// when ANGLE is able to constant fold the index. +// WebGL 2.0 spec section 'GLSL ES 1.00 Fragment Shader Output' +TEST_P(WebGL2GLSLValidationTest, IndexFragDataWithNonConstant) +{ + + constexpr char kFS[] = R"(precision mediump float; + void main() { + for (int i = 0; i < 2; ++i) { + gl_FragData[true ? 0 : i] = vec4(0.0); + } + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'[' : array index for gl_FragData must be constant zero"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an uniform should generate a warning +// (we don't generate an error on ESSL 1.00 because of WebGL compatibility) +TEST_P(WebGL2GLSLValidationTest, AssignUniformToGlobalESSL1) +{ + + constexpr char kFS[] = R"(precision mediump float; + uniform float a; + float b = a * 2.0; + void main() { + gl_FragColor = vec4(b); + })"; + + validateWarning(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers should be constant expressions"); +} + +// Test that deferring global variable init works with an empty main(). +TEST_P(WebGL2GLSLValidationTest, DeferGlobalVariableInitWithEmptyMain) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform float u; + float foo = u; + void main() {} + )"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that a non-constant texture offset is not accepted for textureOffset. +// ESSL 3.00 section 8.8 +TEST_P(GLSLValidationTest_ES3, TextureOffsetNonConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform vec3 u_texCoord; + uniform mediump sampler3D u_sampler; + uniform int x; + void main() { + my_FragColor = textureOffset(u_sampler, u_texCoord, ivec3(x, 3, -8)); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'textureOffset' : Texture offset must be a constant expression"); +} + +// Test that a non-constant texture offset is not accepted for textureProjOffset with bias. +// ESSL 3.00 section 8.8 +TEST_P(GLSLValidationTest_ES3, TextureProjOffsetNonConst) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform vec4 u_texCoord; + uniform mediump sampler3D u_sampler; + uniform int x; + void main() { + my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec3(x, 3, -8), 0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'textureProjOffset' : Texture offset must be a constant expression"); +} + +// Test that an out-of-range texture offset is not accepted. +// GLES 3.0.4 section 3.8.10 specifies that out-of-range offset has undefined behavior. +TEST_P(GLSLValidationTest_ES3, TextureLodOffsetOutOfRange) +{ + + GLint maxOffset = 0; + + glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &maxOffset); + + const std::string kFS = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + uniform vec3 u_texCoord; + uniform mediump sampler3D u_sampler; + void main() { + my_FragColor = textureLodOffset(u_sampler, u_texCoord, 0.0, ivec3(0, 0, )" + + std::to_string(maxOffset + 1) + R"()); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS.c_str(), "Texture offset value out of valid range"); +} + +// Test that default precision qualifier for uint is not accepted. +// ESSL 3.00.4 section 4.5.4: Only allowed for float, int and sampler types. +TEST_P(GLSLValidationTest_ES3, DefaultPrecisionUint) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + precision mediump uint; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'uint' : illegal type argument for default precision qualifier"); +} + +// Test that sampler3D needs to be precision qualified. +// ESSL 3.00.4 section 4.5.4: New ESSL 3.00 sampler types don't have predefined precision. +TEST_P(GLSLValidationTest_ES3, NoPrecisionSampler3D) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + uniform sampler3D s; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'sampler3D' : No precision specified"); +} + +// Test that using a non-constant expression in a for loop initializer is forbidden in WebGL 1.0, +// even when ANGLE is able to constant fold the initializer. +// ESSL 1.00 Appendix A. +TEST_P(WebGLGLSLValidationTest, NonConstantLoopIndex) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform int u; + void main() { + for (int i = (true ? 1 : u); i < 5; ++i) { + gl_FragColor = vec4(0.0); + } + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'i' : Loop index cannot be initialized with non-constant expression"); +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an uniform should generate a warning +// (we don't generate an error on ESSL 1.00 because of WebGL compatibility) +TEST_P(WebGLGLSLValidationTest, AssignUniformToGlobalESSL1) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform float a; + float b = a * 2.0; + void main() { + gl_FragColor = vec4(b); + })"; + + validateWarning(GL_FRAGMENT_SHADER, kFS, + "'=' : global variable initializers should be constant expressions"); +} + +// Test that deferring global variable init works with an empty main(). +TEST_P(WebGLGLSLValidationTest, DeferGlobalVariableInitWithEmptyMain) +{ + constexpr char kFS[] = R"(precision mediump float; + uniform float u; + float foo = u; + void main() {} + )"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Check that indices that are not integers are rejected. +// The check should be done even if ESSL 1.00 Appendix A limitations are not applied. +TEST_P(GLSLValidationTest, NonIntegerIndex) +{ + constexpr char kFS[] = R"(precision mediump float; + void main() { + float f[3]; + const float i = 2.0; + gl_FragColor = vec4(f[i]); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'[]' : integer expression required"); +} + +// ESSL1 shaders with a duplicate function prototype should be rejected. +// ESSL 1.00.17 section 4.2.7. +TEST_P(GLSLValidationTest, DuplicatePrototypeESSL1) +{ + constexpr char kFS[] = R"(precision mediump float; + void foo(); + void foo(); + void foo() {} + void main() + { + gl_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'function' : duplicate function prototype declarations are not allowed"); +} + +// ESSL3 shaders with a duplicate function prototype should be allowed. +// ESSL 3.00.4 section 4.2.3. +TEST_P(GLSLValidationTest_ES3, DuplicatePrototypeESSL3) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void foo(); + void foo(); + void foo() {} + void main() { + my_FragColor = vec4(0.0); + })"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Shaders with a local function prototype should be rejected. +// ESSL 3.00.4 section 4.2.4. +TEST_P(GLSLValidationTest_ES3, LocalFunctionPrototype) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + void foo(); + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + " 'function' : local function prototype declarations are not allowed"); +} + +// Built-in functions can not be overloaded in ESSL 3.00. +TEST_P(GLSLValidationTest_ES3, ESSL300BuiltInFunctionOverload) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + int sin(int x) { + return int(sin(float(x))); + } + void main() { + my_FragColor = vec4(sin(1)); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'sin' : Name of a built-in function cannot be redeclared as function"); +} + +// Multiplying a 4x2 matrix with a 4x2 matrix should not work. +TEST_P(GLSLValidationTest_ES3, CompoundMultiplyMatrixIdenticalNonSquareDimensions) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 my_FragColor; + void main() { + mat4x2 foo; + foo *= mat4x2(4.0); + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'assign' : cannot convert from 'const 4X2 matrix of float' to 'mediump 4X2 " + "matrix of float'"); +} + +// ESSL 3.00 fragment shaders can not use #pragma STDGL invariant(all). +// ESSL 3.00.4 section 4.6.1. Does not apply to other versions of ESSL. +TEST_P(GLSLValidationTest_ES3, ESSL300FragmentInvariantAll) +{ + constexpr char kFS[] = R"(#version 300 es + #pragma STDGL invariant(all) + precision mediump float; + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(0.0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'invariant' : #pragma STDGL invariant(all) can not be used in fragment shader"); +} + +// Covers a bug where we would set the incorrect result size on an out-of-bounds vector swizzle. +TEST_P(GLSLValidationTest, OutOfBoundsVectorSwizzle) +{ + constexpr char kFS[] = R"( + void main() { + vec2(0).qq; + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'qq' : vector field selection out of range"); +} + +// Covers a bug where strange preprocessor defines could trigger asserts. +TEST_P(GLSLValidationTest, DefineWithSemicolon) +{ + constexpr char kFS[] = R"(#define Def; highp + uniform Def vec2 a;)"; + + validateError(GL_FRAGMENT_SHADER, kFS, " '?' : Error during layout qualifier parsing."); +} + +// Covers a bug in our parsing of malformed shift preprocessor expressions. +TEST_P(GLSLValidationTest, LineDirectiveUndefinedShift) +{ + constexpr char kFS[] = "#line x << y"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'x' : invalid line number"); +} + +// Covers a bug in our parsing of malformed shift preprocessor expressions. +TEST_P(GLSLValidationTest, LineDirectiveNegativeShift) +{ + constexpr char kFS[] = "#line x << -1"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'x' : invalid line number"); +} + +// gl_MaxImageUnits is only available in ES 3.1 shaders. +TEST_P(GLSLValidationTest_ES3, MaxImageUnitsInES3Shader) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 myOutput; + void main() { + float ff = float(gl_MaxImageUnits); + myOutput = vec4(ff); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'gl_MaxImageUnits' : undeclared identifier"); +} + +// struct += struct is an invalid operation. +TEST_P(GLSLValidationTest_ES3, StructCompoundAssignStruct) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 myOutput; + struct S { float foo; }; + void main() { + S a, b; + a += b; + myOutput = vec4(0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'+=' : Invalid operation for structs"); +} + +// struct == different struct is an invalid operation. +TEST_P(GLSLValidationTest_ES3, StructEqDifferentStruct) +{ + constexpr char kFS[] = R"(#version 300 es + precision mediump float; + out vec4 myOutput; + struct S { float foo; }; + struct S2 { float foobar; }; + void main() { + S a; + S2 b; + a == b; + myOutput = vec4(0); + })"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'==' : wrong operand types - no operation '==' exists that takes a left-hand " + "operand of type 'structure 'S'"); +} + +// Compute shaders are not supported in versions lower than 310. +TEST_P(GLSLValidationTest_ES31, Version100) +{ + constexpr char kCS[] = R"(void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "Compute shader is not supported in this shader version."); +} + +// Compute shaders are not supported in versions lower than 310. +TEST_P(GLSLValidationTest_ES31, Version300) +{ + constexpr char kCS[] = R"(#version 300 es + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "Compute shader is not supported in this shader version."); +} + +// Compute shaders should have work group size specified. However, it is not a compile time error +// to not have the size specified, but rather a link time one. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, NoWorkGroupSizeSpecified) +{ + constexpr char kCS[] = R"(#version 310 es + void main() { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Test that workgroup size declaration doesn't accept variable declaration. +TEST_P(GLSLValidationTest_ES31, NoVariableDeclrationAfterWorkGroupSize) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 1) in vec4 x; + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// Work group size is less than 1. It should be at least 1. +// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables +// The spec is not clear whether having a local size qualifier equal zero +// is correct. +// TODO (mradev): Ask people from Khronos to clarify the spec. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeTooSmallXdimension) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 0) in; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, "'0' : out of range: local_size_x must be positive"); +} + +// Work group size is correct for the x and y dimensions, but not for the z dimension. +// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeTooSmallZDimension) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 4, local_size_y = 6, local_size_z = 0) in; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, "'0' : out of range: local_size_z must be positive"); +} + +// Work group size is bigger than the maximum in the x dimension. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeTooBigXDimension) +{ + + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 9989899) in; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid value: Value must be at least 1 and no greater than"); +} + +// Work group size is bigger than the maximum in the y dimension. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeTooBigYDimension) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, local_size_y = 9989899) in; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_y' : invalid value: Value must be at least 1 and no greater than"); +} + +// Work group size is definitely bigger than the maximum in the z dimension. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeTooBigZDimension) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, local_size_y = 5, local_size_z = 9989899) in; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_z' : invalid value: Value must be at least 1 and no greater than"); +} + +// Work group size specified through macro expansion. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeMacro) +{ + constexpr char kCS[] = R"(#version 310 es + #define MYDEF(x) x + layout(local_size_x = MYDEF(127)) in; + void main() + { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Work group size specified as an unsigned integer. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeUnsignedInteger) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 123u) in; + void main() { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Work group size specified in hexadecimal. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeHexadecimal) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 0x3A) in; + void main() + { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// local_size_x is -1 in hexadecimal format. +// -1 is used as unspecified value in the TLayoutQualifier structure. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeMinusOneHexadecimal) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 0xFFFFFFFF) in; + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, "'-1' : out of range: local_size_x must be positive"); +} + +// Work group size specified in octal. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeOctal) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 013) in; + void main() { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Work group size is negative. It is specified in hexadecimal. +TEST_P(GLSLValidationTest_ES31, WorkGroupSizeNegativeHexadecimal) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 0xFFFFFFEC) in; + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, "'-20' : out of range: local_size_x must be positive"); +} + +// Multiple work group layout qualifiers with differing values. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, DifferingLayoutQualifiers) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, local_size_x = 6) in; + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : Cannot have multiple different work group size specifiers"); +} + +// Multiple work group input variables with differing local size values. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, MultipleInputVariablesDifferingLocalSize) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, local_size_y = 6) in; + layout(local_size_x = 5, local_size_y = 7) in; + void main() + { + } + )"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'layout' : Work group size does not match the previous declaration"); +} + +// Multiple work group input variables with differing local size values. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, MultipleInputVariablesDifferingLocalSize2) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5) in; + layout(local_size_x = 5, local_size_y = 7) in; + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'layout' : Work group size does not match the previous declaration"); +} + +// Multiple work group input variables with the same local size values. It should compile. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, MultipleInputVariablesSameLocalSize) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, local_size_y = 6) in; + layout(local_size_x = 5, local_size_y = 6) in; + void main() { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Multiple work group input variables with the same local size values. It should compile. +// Since the default value is 1, it should compile. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, MultipleInputVariablesSameLocalSize2) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5) in; + layout(local_size_x = 5, local_size_y = 1) in; + void main() { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Multiple work group input variables with the same local size values. It should compile. +// Since the default value is 1, it should compile. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, MultipleInputVariablesSameLocalSize3) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, local_size_y = 1) in; + layout(local_size_x = 5) in; + void main() { + })"; + + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Specifying row_major qualifier in a work group size layout. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, RowMajorInComputeInputLayout) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5, row_major) in; + void main() + { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, "'layout' : invalid layout qualifier combination"); +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, UniformComputeInputLayout) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5) uniform; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, UniformBufferComputeInputLayout) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5) uniform SomeBuffer { vec4 something; }; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, StructComputeInputLayout) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5) struct SomeBuffer { vec4 something; }; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, StructBodyComputeInputLayout) +{ + constexpr char kCS[] = R"(#version 310 es + struct S { + layout(local_size_x = 12) vec4 foo; + }; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, TypeComputeInputLayout) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 5) vec4; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// Invalid use of the out storage qualifier in a compute shader. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, InvalidOutStorageQualifier) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 15) in; + out vec4 myOutput; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + " 'out' : storage qualifier isn't supported in compute shaders"); +} + +// Invalid use of the out storage qualifier in a compute shader. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, InvalidOutStorageQualifier2) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 15) in; + out myOutput; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'out' : storage qualifier isn't supported in compute shaders"); +} + +// Invalid use of the in storage qualifier. Can be only used to describe the local block size. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, InvalidInStorageQualifier) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 15) in; + in vec4 myInput; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, + "'in' : 'in' can be only used to specify the local group size"); +} + +// Invalid use of the in storage qualifier. Can be only used to describe the local block size. +// The test checks a different part of the GLSL grammar than what InvalidInStorageQualifier +// checks. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_P(GLSLValidationTest_ES31, InvalidInStorageQualifier2) +{ + constexpr char kCS[] = R"(#version 310 es + layout(local_size_x = 15) in; + in myInput; + void main() { + })"; + + validateError(GL_COMPUTE_SHADER, kCS, "'myInput' : Expected invariant or precise"); +} + +// The local_size layout qualifier is only available in compute shaders. +TEST_P(GLSLValidationTest_ES31, VS_InvalidUseOfLocalSizeX) +{ + constexpr char kVS[] = R"(#version 310 es + precision mediump float; + layout(local_size_x = 15) in vec4 myInput; + out vec4 myOutput; + void main() { + myOutput = myInput; + })"; + + validateError(GL_VERTEX_SHADER, kVS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} + +// The local_size layout qualifier is only available in compute shaders. +TEST_P(GLSLValidationTest_ES31, FS_InvalidUseOfLocalSizeX) +{ + constexpr char kFS[] = R"(#version 310 es + precision mediump float; + layout(local_size_x = 15) in vec4 myInput; + out vec4 myOutput; + void main() { + myOutput = myInput; + })"; + + validateError(GL_VERTEX_SHADER, kFS, + "'local_size_x' : invalid layout qualifier: only valid when used with 'in' in a " + "compute shader global layout declaration"); +} +// Verify that using maximum size as atomic counter offset results in compilation failure. +TEST_P(GLSLValidationTest_ES31, CompileWithMaxAtomicCounterOffsetFails) +{ + GLint maxSize; + glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &maxSize); + + std::ostringstream fs; + fs << R"(#version 310 es +layout(location = 0) out uvec4 color; +layout(binding = 0, offset = )" + << maxSize << R"() uniform atomic_uint a_counter; +void main() { +color = uvec4(atomicCounterIncrement(a_counter)); +})"; + validateError( + GL_FRAGMENT_SHADER, fs.str().c_str(), + "'atomic counter' : Offset must not exceed the maximum atomic counter buffer size"); +} + +// Check that having an invalid char after the "." doesn't cause an assert. +TEST_P(GLSLValidationTest, InvalidFieldFirstChar) +{ + constexpr char kVS[] = "void main() {vec4 x; x.}"; + validateError(GL_VERTEX_SHADER, kVS, ": '}' : Illegal character at fieldname start"); +} + +// Tests that bad index expressions don't crash ANGLE's translator. +// http://anglebug.com/42266998 +TEST_P(GLSLValidationTest, BadIndexBugVec) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform vec4 uniformVec; +void main() +{ + gl_FragColor = vec4(uniformVec[int()]); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : constructor does not have any arguments"); +} + +// Tests that bad index expressions don't crash ANGLE's translator. +// http://anglebug.com/42266998 +TEST_P(GLSLValidationTest, BadIndexBugMat) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform mat4 uniformMat; +void main() +{ + gl_FragColor = vec4(uniformMat[int()]); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : constructor does not have any arguments"); +} + +// Tests that bad index expressions don't crash ANGLE's translator. +// http://anglebug.com/42266998 +TEST_P(GLSLValidationTest, BadIndexBugArray) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform vec4 uniformArray; +void main() +{ + gl_FragColor = vec4(uniformArray[int()]); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : constructor does not have any arguments"); +} + +// Test that GLSL error on gl_DepthRange does not crash. +TEST_P(GLSLValidationTestNoValidation, DepthRangeError) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() +{ + gl_DepthRange + 1; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'+' : Invalid operation for structs"); +} + +// Test that an inout value in a location beyond the MaxDrawBuffer limit when using the shader +// framebuffer fetch extension results in a compilation error. +// (Based on a fuzzer-discovered issue) +TEST_P(GLSLValidationTest_ES3, CompileFSWithInoutLocBeyondMaxDrawBuffers) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + GLint maxDrawBuffers; + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); + + const std::string fs = R"(#version 300 es +#extension GL_EXT_shader_framebuffer_fetch : require +precision highp float; +layout(location = )" + std::to_string(maxDrawBuffers) + + R"() inout vec4 inoutArray[1]; +void main() +{ + vec4 val = inoutArray[0]; + inoutArray[0] = val + vec4(0.1, 0.2, 0.3, 0.4); +})"; + validateError(GL_FRAGMENT_SHADER, fs.c_str(), + "'inoutArray' : output location must be < MAX_DRAW_BUFFERS"); +} + +// Test that structs with samplers are not allowed in interface blocks. This is forbidden per +// GLES3: +// +// > Types and declarators are the same as for other uniform variable declarations outside blocks, +// > with these exceptions: +// > * opaque types are not allowed +TEST_P(GLSLValidationTest_ES3, StructWithSamplersDisallowedInInterfaceBlock) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +struct S { sampler2D samp; bool b; }; + +layout(std140) uniform Buffer { S s; } buffer; + +out vec4 color; + +void main() +{ + color = texture(buffer.s.samp, vec2(0)); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'Buffer' : Opaque types are not allowed in interface blocks"); +} + +// Test that *= on boolean vectors fails compilation +TEST_P(GLSLValidationTest, BVecMultiplyAssign) +{ + constexpr char kFS[] = R"(bvec4 c,s;void main(){s*=c;})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'assign' : cannot convert from '4-component vector of bool' to '4-component " + "vector of bool'"); +} + +// Test that packing of excessive 3-column variables does not overflow the count of 3-column +// variables in VariablePacker +TEST_P(WebGL2GLSLValidationTest, ExcessiveMat3UniformPacking) +{ + std::ostringstream vs; + + vs << R"(#version 300 es +precision mediump float; +out vec4 finalColor; +in vec4 color; +uniform mat4 r[254]; + +uniform mat3 )"; + + constexpr size_t kNumUniforms = 10000; + for (size_t i = 0; i < kNumUniforms; ++i) + { + if (i > 0) + { + vs << ", "; + } + vs << "m3a_" << i << "[256]"; + } + vs << R"(; +void main(void) { finalColor = color; })"; + validateError(GL_VERTEX_SHADER, vs.str().c_str(), "too many uniforms"); +} + +// Test that infinite loop with while(true) is rejected +TEST_P(WebGL2GLSLValidationTest, InfiniteLoopWhileTrue) +{ + testInfiniteLoop(R"(#version 300 es +precision highp float; +uniform uint zero; +out vec4 color; + +void main() +{ + float r = 0.; + float g = 1.; + float b = 0.; + + // Infinite loop + while (true) + { + r += 0.1; + if (r > 0.) + { + continue; + } + } + + color = vec4(r, g, b, 1); +})"); +} + +// Test that infinite loop with for(;true;) is rejected +TEST_P(WebGL2GLSLValidationTest, InfiniteLoopForTrue) +{ + testInfiniteLoop(R"(#version 300 es +precision highp float; +uniform uint zero; +out vec4 color; + +void main() +{ + float r = 0.; + float g = 1.; + float b = 0.; + + // Infinite loop + for (;!false;) + { + r += 0.1; + } + + color = vec4(r, g, b, 1); +})"); +} + +// Test that infinite loop with do{} while(true) is rejected +TEST_P(WebGL2GLSLValidationTest, InfiniteLoopDoWhileTrue) +{ + testInfiniteLoop(R"(#version 300 es +precision highp float; +uniform uint zero; +out vec4 color; + +void main() +{ + float r = 0.; + float g = 1.; + float b = 0.; + + // Infinite loop + do + { + r += 0.1; + switch (uint(r)) + { + case 0: + g += 0.1; + break; + default: + b += 0.1; + continue; + } + } while (true); + + color = vec4(r, g, b, 1); +})"); +} + +// Test that infinite loop with constant local variable is rejected +TEST_P(WebGL2GLSLValidationTest, InfiniteLoopLocalVariable) +{ + testInfiniteLoop(R"(#version 300 es +precision highp float; +uniform uint zero; +out vec4 color; + +void main() +{ + float r = 0.; + float g = 1.; + float b = 0.; + + bool localConstTrue = true; + + // Infinite loop + do + { + r += 0.1; + switch (uint(r)) + { + case 0: + g += 0.1; + break; + default: + b += 0.1; + continue; + } + } while (localConstTrue); + + color = vec4(r, g, b, 1); +})"); +} + +// Test that infinite loop with global variable is rejected +TEST_P(WebGL2GLSLValidationTest, InfiniteLoopGlobalVariable) +{ + testInfiniteLoop(R"(#version 300 es +precision highp float; +uniform uint zero; +out vec4 color; + +bool globalConstTrue = true; + +void main() +{ + float r = 0.; + float g = 1.; + float b = 0.; + + // Infinite loop + do + { + r += 0.1; + switch (uint(r)) + { + case 0: + g += 0.1; + break; + default: + b += 0.1; + continue; + } + } while (globalConstTrue); + + color = vec4(r, g, b, 1); +})"); +} + +// Test that indexing swizzles out of bounds fails +TEST_P(GLSLValidationTest_ES3, OutOfBoundsIndexingOfSwizzle) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 colorOut; +uniform vec3 colorIn; + +void main() +{ + colorOut = vec4(colorIn.yx[2], 0, 0, 1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'[]' : vector field selection out of range"); +} + +// Regression test for a validation bug in the translator where func(void, int) was accepted even +// though it's illegal, and the function was callable as if the void parameter isn't there. +TEST_P(GLSLValidationTest, NoParameterAfterVoid) +{ + constexpr char kVS[] = R"(void f(void, int a){} +void main(){f(1);})"; + validateError(GL_VERTEX_SHADER, kVS, "'void' : cannot be a parameter type except for '(void)'"); +} + +// Similar to NoParameterAfterVoid, but tests func(void, void). +TEST_P(GLSLValidationTest, NoParameterAfterVoid2) +{ + constexpr char kVS[] = R"(void f(void, void){} +void main(){f();})"; + validateError(GL_VERTEX_SHADER, kVS, "'void' : cannot be a parameter type except for '(void)'"); +} + +// Test that structs with too many fields are rejected. In SPIR-V, the instruction that defines the +// struct lists the fields which means the length of the instruction is a function of the field +// count. Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be +// represented. +TEST_P(GLSLValidationTest_ES3, TooManyFieldsInStruct) +{ + std::ostringstream fs; + fs << R"(#version 300 es +precision highp float; +struct TooManyFields +{ +)"; + for (uint32_t i = 0; i < (1 << 16); ++i) + { + fs << " float field" << i << ";\n"; + } + fs << R"(}; +uniform B { TooManyFields s; }; +out vec4 color; +void main() { + color = vec4(s.field0, 0.0, 0.0, 1.0); +})"; + validateError(GL_FRAGMENT_SHADER, fs.str().c_str(), + "'TooManyFields' : Too many fields in the struct"); +} + +// Same as TooManyFieldsInStruct, but with samplers in the struct. +TEST_P(GLSLValidationTest_ES3, TooManySamplerFieldsInStruct) +{ + std::ostringstream fs; + fs << R"(#version 300 es +precision highp float; +struct TooManyFields +{ +)"; + for (uint32_t i = 0; i < (1 << 16); ++i) + { + fs << " sampler2D field" << i << ";\n"; + } + fs << R"(}; +uniform TooManyFields s; +out vec4 color; +void main() { + color = texture(s.field0, vec2(0)); +})"; + validateError(GL_FRAGMENT_SHADER, fs.str().c_str(), + "'TooManyFields' : Too many fields in the struct"); +} + +// Test having many samplers in nested structs. +TEST_P(GLSLValidationTest_ES3, ManySamplerFieldsInStructComplex) +{ + // D3D and OpenGL may be more restrictive about this many samplers. + ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL()); + + constexpr char kFS[] = R"(#version 300 es +precision highp float; + +struct X { + mediump sampler2D a[0xf00]; + mediump sampler2D b[0xf00]; + mediump sampler2D c[0xf000]; + mediump sampler2D d[0xf00]; +}; + +struct Y { + X s1; + mediump sampler2D a[0xf00]; + mediump sampler2D b[0xf000]; + mediump sampler2D c[0x14000]; +}; + +struct S { + Y s1; +}; + +struct structBuffer { S s; }; + +uniform structBuffer b; + +out vec4 color; +void main() +{ + color = texture(b.s.s1.s1.c[0], vec2(0)); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Make sure a large array of samplers works. +TEST_P(GLSLValidationTest, ManySamplers) +{ + // D3D and OpenGL may be more restrictive about this many samplers. + ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL()); + + constexpr char kFS[] = R"(precision highp float; + +uniform mediump sampler2D c[0x12000]; + +void main() +{ + gl_FragColor = texture2D(c[0], vec2(0)); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Make sure a large array of samplers works when declared in a struct. +TEST_P(GLSLValidationTest, ManySamplersInStruct) +{ + // D3D and OpenGL may be more restrictive about this many samplers. + ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL()); + + constexpr char kFS[] = R"(precision highp float; + +struct X { + mediump sampler2D c[0x12000]; +}; + +uniform X x; + +void main() +{ + gl_FragColor = texture2D(x.c[0], vec2(0)); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that passing large arrays to functions are compiled correctly. Regression test for the +// SPIR-V generator that made a copy of the array to pass to the function, by decomposing and +// reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a +// length higher than can fit in SPIR-V. +TEST_P(WebGL2GLSLValidationTest, LargeInterfaceBlockArrayPassedToFunction) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +uniform Large { float a[65536]; }; +float f(float b[65536]) +{ + b[0] = 1.0; + return b[0] + b[1]; +} +out vec4 color; +void main() { + color = vec4(f(a), 0.0, 0.0, 1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "Size of declared private variable exceeds implementation-defined limit"); +} + +// Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct. +TEST_P(WebGL2GLSLValidationTest, LargeInterfaceBlockNestedArrayPassedToFunction) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +struct S { float a[65536]; }; +uniform Large { S s; }; +float f(float b[65536]) +{ + b[0] = 1.0; + return b[0] + b[1]; +} +out vec4 color; +void main() { + color = vec4(f(s.a), 0.0, 0.0, 1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "Size of declared private variable exceeds implementation-defined limit"); +} + +// Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local +// variable instead. +TEST_P(WebGL2GLSLValidationTest, LargeInterfaceBlockArrayCopiedToLocal) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +uniform Large { float a[65536]; }; +out vec4 color; +void main() { + float b[65536] = a; + color = vec4(b[0], 0.0, 0.0, 1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "Size of declared private variable exceeds implementation-defined limit"); +} + +// Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct +TEST_P(WebGL2GLSLValidationTest, LargeInterfaceBlockNestedArrayCopiedToLocal) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +struct S { float a[65536]; }; +uniform Large { S s; }; +out vec4 color; +void main() { + S s2 = s; + color = vec4(s2.a[0], 0.0, 0.0, 1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "Size of declared private variable exceeds implementation-defined limit"); +} + +// Test that too large varyings are rejected. +TEST_P(WebGL2GLSLValidationTest, LargeArrayVarying) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +in float a[65536]; +out vec4 color; +void main() { + color = vec4(a[0], 0.0, 0.0, 1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'a' : Size of declared private variable exceeds implementation-defined limit"); +} + +// Test that too large array, where cast to signed int would produce negative sizes, does not crash. +TEST_P(WebGL2GLSLValidationTest, LargeArrayUintMaxSize) +{ + constexpr char kFS[] = R"(#version 300 es +int rr[~1U]; +out int o; +void main() { + o = rr[1]; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'rr' : Size of declared variable exceeds implementation-defined limit"); +} + +// Test that too large color outputs are rejected +TEST_P(WebGL2GLSLValidationTest, LargeColorOutput) +{ + GLint maxDrawBuffers = 0; + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); + ANGLE_SKIP_TEST_IF(maxDrawBuffers >= 32); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 colorOut[32]; + +void main() +{ + colorOut[0] = vec4(0, 0, 0, 1); + colorOut[31] = vec4(0, 0, 0, 1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'colorOut' : output array locations would exceed MAX_DRAW_BUFFERS"); +} + +// Test that too large color outputs are rejected +TEST_P(WebGL2GLSLValidationTest, LargeColorOutputWithLocation) +{ + GLint maxDrawBuffers = 0; + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); + ANGLE_SKIP_TEST_IF(maxDrawBuffers >= 10); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +layout(location = 0) out vec4 colorOut[4]; +layout(location = 4) out vec4 colorOut2[6]; + +void main() +{ + colorOut[0] = vec4(0, 0, 0, 1); + colorOut[3] = vec4(0, 0, 0, 1); + colorOut2[0] = vec4(0, 0, 0, 1); + colorOut2[5] = vec4(0, 0, 0, 1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'colorOut2' : output array locations would exceed MAX_DRAW_BUFFERS"); +} + +// Test that marking a built-in as invariant and then redeclaring it is an error. +TEST_P(GLSLValidationTest_ES3, FragDepthInvariantThenRedeclare) +{ + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_conservative_depth:enable +precision mediump float; +invariant gl_FragDepth; +out float gl_FragDepth; +void main() { + gl_FragDepth = 0.5; +} +)"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'gl_FragDepth' : built-ins cannot be redeclared after being qualified as " + "invariant or precise"); +} + +// Make sure gl_PerVertex is not accepted other than as `out` and with no name in vertex shader +TEST_P(GLSLValidationTest_ES31, ValidatePerVertexVertexShader) +{ + { + // Cannot use gl_PerVertex with attribute + constexpr char kVS[] = R"(attribute gl_PerVertex{vec4 gl_Position;}; +void main() {})"; + validateError(GL_VERTEX_SHADER, kVS, + "'gl_PerVertex' : interface blocks supported in GLSL ES 3.00 and above only"); + } + + { + // Cannot use gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kVS[] = R"(#version 300 es +out gl_PerVertex{vec4 gl_Position;} name; +void main() {})"; + validateError(GL_VERTEX_SHADER, kVS, + "'out' : invalid qualifier: interface blocks must be uniform in version " + "lower than GLSL ES 3.10"); + } + + { + // Cannot use gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kVS[] = R"(#version 310 es +out gl_PerVertex{vec4 gl_Position;}; +void main() {})"; + validateError(GL_VERTEX_SHADER, kVS, + "'out' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); + + { + // Cannot use gl_PerVertex with a name + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require +out gl_PerVertex{vec4 gl_Position;} name; +void main() {})"; + validateError(GL_VERTEX_SHADER, kVS, + "'name' : out gl_PerVertex instance name must be empty in this shader"); + } + + { + // out gl_PerVertex without a name is ok. + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require +out gl_PerVertex{vec4 gl_Position;}; +void main() {})"; + validateSuccess(GL_VERTEX_SHADER, kVS); + } +} + +// Make sure gl_PerVertex is not accepted other than as `out .. gl_out[]`, or `in .. gl_in[]` in +// tessellation control shader. +TEST_P(GLSLValidationTest_ES31, ValidatePerVertexTessellationControlShader) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader")); + + { + // Cannot use out gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kTCS[] = R"(#version 300 es +out gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, + "'out' : invalid qualifier: interface blocks must be uniform in version " + "lower than GLSL ES 3.10"); + } + + { + // Cannot use in gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kTCS[] = R"(#version 300 es +in gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, + "'in' : invalid qualifier: interface blocks must be uniform in version lower " + "than GLSL ES 3.10"); + } + + { + // Cannot use out gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kTCS[] = R"(#version 310 es +out gl_PerVertex{vec4 gl_Position;} gl_out[]; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, + "'out' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + { + // Cannot use in gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kTCS[] = R"(#version 310 es +in gl_PerVertex{vec4 gl_Position;} gl_in[]; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, + "'in' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + { + // Cannot use out gl_PerVertex with a name + constexpr char kTCS[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (vertices=4) out; +out gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, + "'name' : out gl_PerVertex instance name must be gl_out in this shader"); + } + + { + // Cannot use in gl_PerVertex with a name + constexpr char kTCS[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (vertices=4) out; +in gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, + "'name' : in gl_PerVertex instance name must be gl_in"); + } + + { + // Cannot use out gl_PerVertex if not arrayed + constexpr char kTCS[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (vertices=4) out; +out gl_PerVertex{vec4 gl_Position;} gl_out; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, "'gl_PerVertex' : type must be an array"); + } + + { + // Cannot use in gl_PerVertex if not arrayed + constexpr char kTCS[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (vertices=4) out; +in gl_PerVertex{vec4 gl_Position;} gl_in; +void main() {})"; + validateError(GL_TESS_CONTROL_SHADER, kTCS, "'gl_PerVertex' : type must be an array"); + } + + { + // out gl_PerVertex with gl_out, and in gl_PerVertex with gl_in are ok. + constexpr char kTCS[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (vertices=4) out; +out gl_PerVertex{vec4 gl_Position;} gl_out[]; +in gl_PerVertex{vec4 gl_Position;} gl_in[]; +void main() {})"; + validateSuccess(GL_TESS_CONTROL_SHADER, kTCS); + } +} + +// Make sure gl_PerVertex is not accepted other than as `out .. gl_out`, or `in .. gl_in[]` in +// tessellation evaluation shader. +TEST_P(GLSLValidationTest_ES31, ValidatePerVertexTessellationEvaluationShader) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader")); + + { + // Cannot use out gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kTES[] = R"(#version 300 es +out gl_PerVertex{vec4 gl_Position;} name; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'out' : invalid qualifier: interface blocks must be uniform in version " + "lower than GLSL ES 3.10"); + } + + { + // Cannot use in gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kTES[] = R"(#version 300 es +in gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'in' : invalid qualifier: interface blocks must be uniform in version lower " + "than GLSL ES 3.10"); + } + + { + // Cannot use out gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kTES[] = R"(#version 310 es +out gl_PerVertex{vec4 gl_Position;}; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'out' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + { + // Cannot use in gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kTES[] = R"(#version 310 es +in gl_PerVertex{vec4 gl_Position;} gl_in[]; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'in' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + { + // Cannot use out gl_PerVertex with a name + constexpr char kTES[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (isolines, point_mode) in; +out gl_PerVertex{vec4 gl_Position;} name; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'name' : out gl_PerVertex instance name must be empty in this shader"); + } + + { + // Cannot use in gl_PerVertex with a name + constexpr char kTES[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (isolines, point_mode) in; +in gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'name' : in gl_PerVertex instance name must be gl_in"); + } + + { + // Cannot use out gl_PerVertex if arrayed + constexpr char kTES[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (isolines, point_mode) in; +out gl_PerVertex{vec4 gl_Position;} gl_out[]; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, + "'gl_out' : out gl_PerVertex instance name must be empty in this shader"); + } + + { + // Cannot use in gl_PerVertex if not arrayed + constexpr char kTES[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (isolines, point_mode) in; +in gl_PerVertex{vec4 gl_Position;} gl_in; +void main() {})"; + validateError(GL_TESS_EVALUATION_SHADER, kTES, "'gl_PerVertex' : type must be an array"); + } + + { + // out gl_PerVertex without a name, and in gl_PerVertex with gl_in are ok. + constexpr char kTES[] = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout (isolines, point_mode) in; +out gl_PerVertex{vec4 gl_Position;}; +in gl_PerVertex{vec4 gl_Position;} gl_in[]; +void main() {})"; + validateSuccess(GL_TESS_EVALUATION_SHADER, kTES); + } +} + +// Make sure gl_PerVertex is not accepted other than as `out .. gl_out`, or `in .. gl_in[]` in +// geometry shader. +TEST_P(GLSLValidationTest_ES31, ValidatePerVertexGeometryShader) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + { + // Cannot use out gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kGS[] = R"(#version 300 es +out gl_PerVertex{vec4 gl_Position;} name; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'out' : invalid qualifier: interface blocks must be uniform in version " + "lower than GLSL ES 3.10"); + } + + { + // Cannot use in gl_PerVertex with a name (without EXT_shader_io_blocks) + constexpr char kGS[] = R"(#version 300 es +in gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'in' : invalid qualifier: interface blocks must be uniform in version lower " + "than GLSL ES 3.10"); + } + + { + // Cannot use out gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kGS[] = R"(#version 310 es +out gl_PerVertex{vec4 gl_Position;}; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'out' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + { + // Cannot use in gl_PerVertex (without EXT_shader_io_blocks) + constexpr char kGS[] = R"(#version 310 es +in gl_PerVertex{vec4 gl_Position;} gl_in[]; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'in' : invalid qualifier: shader IO blocks need shader io block extension"); + } + + { + // Cannot use out gl_PerVertex with a name + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +layout (triangles) in; +layout (points, max_vertices = 1) out; +out gl_PerVertex{vec4 gl_Position;} name; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'name' : out gl_PerVertex instance name must be empty in this shader"); + } + + { + // Cannot use in gl_PerVertex with a name + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +layout (triangles) in; +layout (points, max_vertices = 1) out; +in gl_PerVertex{vec4 gl_Position;} name[]; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'name' : in gl_PerVertex instance name must be gl_in"); + } + + { + // Cannot use out gl_PerVertex if arrayed + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +layout (triangles) in; +layout (points, max_vertices = 1) out; +out gl_PerVertex{vec4 gl_Position;} gl_out[]; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, + "'gl_out' : out gl_PerVertex instance name must be empty in this shader"); + } + + { + // Cannot use in gl_PerVertex if not arrayed + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +layout (triangles) in; +layout (points, max_vertices = 1) out; +in gl_PerVertex{vec4 gl_Position;} gl_in; +void main() {})"; + validateError(GL_GEOMETRY_SHADER, kGS, "'gl_PerVertex' : type must be an array"); + } + + { + // out gl_PerVertex without a name, and in gl_PerVertex with gl_in are ok. + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +layout (triangles) in; +layout (points, max_vertices = 1) out; +out gl_PerVertex{vec4 gl_Position;}; +in gl_PerVertex{vec4 gl_Position;} gl_in[]; +void main() {})"; + validateSuccess(GL_GEOMETRY_SHADER, kGS); + } +} + +// Regression test case of unary + constant folding of a void struct member. +TEST_P(GLSLValidationTest, UnaryPlusOnVoidStructMemory) +{ + constexpr char kFS[] = R"(uniform mediump vec4 u; +struct U +{ + void t; +}; +void main() { + +U().t; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'t' : illegal use of type 'void'"); +} + +// Test compiling shaders using the GL_EXT_shader_texture_lod extension +TEST_P(GLSLValidationTest, TextureLOD) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod")); + + constexpr char kFS[] = R"(#extension GL_EXT_shader_texture_lod : require +uniform sampler2D u_texture; +void main() { + gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 0.0)); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Verify that using a struct as both invariant and non-invariant output works. +TEST_P(GLSLValidationTest_ES31, StructBothInvariantAndNot) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require + +struct S +{ + vec4 s; +}; + +out Output +{ + vec4 x; + invariant S s; +}; + +out S s2; + +void main(){ + x = vec4(0); + s.s = vec4(1); + s2.s = vec4(2); + S s3 = s; + s.s = s3.s; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that using a struct as both invariant and non-invariant output works. +// The shader interface block has a variable name in this variant. +TEST_P(GLSLValidationTest_ES31, StructBothInvariantAndNot2) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require + +struct S +{ + vec4 s; +}; + +out Output +{ + vec4 x; + invariant S s; +} o; + +out S s2; + +void main(){ + o.x = vec4(0); + o.s.s = vec4(1); + s2.s = vec4(2); + S s3 = o.s; + o.s.s = s3.s; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnFloat) +{ + constexpr char kVS[] = R"(varying float v_varying; +float f(); +void main() { gl_Position = vec4(f(), 0, 0, 1); } +float f() { if (v_varying > 0.0) return 1.0; })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnVec2) +{ + constexpr char kVS[] = R"(varying float v_varying; +vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); } +void main() { gl_Position = vec4(f().x, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnVec3) +{ + constexpr char kVS[] = R"(varying float v_varying; +vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); } +void main() { gl_Position = vec4(f().x, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnVec4) +{ + constexpr char kVS[] = R"(varying float v_varying; +vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); } +void main() { gl_Position = vec4(f().x, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnIVec4) +{ + constexpr char kVS[] = R"(varying float v_varying; +ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); } +void main() { gl_Position = vec4(f().x, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnMat4) +{ + constexpr char kVS[] = R"(varying float v_varying; +mat4 f() { if (v_varying > 0.0) return mat4(1.0); } +void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest, MissingReturnStruct) +{ + constexpr char kVS[] = R"(varying float v_varying; +struct s { float a; int b; vec2 c; }; +s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); } +void main() { gl_Position = vec4(f().a, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest_ES3, MissingReturnArray) +{ + constexpr char kVS[] = R"(#version 300 es +in float v_varying; +vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } } +void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest_ES3, MissingReturnArrayOfStructs) +{ + constexpr char kVS[] = R"(#version 300 es +in float v_varying; +struct s { float a; int b; vec2 c; }; +s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, vec2(1.0, 1.0))); } } +void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that functions without return statements still compile +TEST_P(GLSLValidationTest_ES3, MissingReturnStructOfArrays) +{ + // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV) + ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); + + constexpr char kVS[] = R"(#version 300 es +in float v_varying; +struct s { float a[2]; int b[2]; vec2 c[2]; }; +s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1), vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } } +void main() { gl_Position = vec4(f().a[0], 0, 0, 1); })"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify that non-const index used on an array returned by a function compiles +TEST_P(GLSLValidationTest_ES3, ReturnArrayOfStructsThenNonConstIndex) +{ + constexpr char kVS[] = R"(#version 300 es +in float v_varying; +struct s { float a; int b; vec2 c; }; +s[2] f() +{ + return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0))); +} +void main() +{ + gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Verify shader source with a fixed length that is less than the null-terminated length will +// compile. +TEST_P(GLSLValidationTest, FixedShaderLength) +{ + GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); + + const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz"; + const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage; + const char *sourceArray[1] = {source.c_str()}; + GLint lengths[1] = {static_cast(source.length() - appendGarbage.length())}; + glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); + glCompileShader(shader); + + GLint compileResult; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); + EXPECT_NE(compileResult, 0); +} + +// Verify that a negative shader source length is treated as a null-terminated length. +TEST_P(GLSLValidationTest, NegativeShaderLength) +{ + GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); + + const char *sourceArray[1] = {essl1_shaders::fs::Red()}; + GLint lengths[1] = {-10}; + glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); + glCompileShader(shader); + + GLint compileResult; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); + EXPECT_NE(compileResult, 0); +} + +// Verify that a length array with mixed positive and negative values compiles. +TEST_P(GLSLValidationTest, MixedShaderLengths) +{ + GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); + + const char *sourceArray[] = { + "void main()", + "{", + " gl_FragColor = vec4(0, 0, 0, 0);", + "}", + }; + GLint lengths[] = { + -10, + 1, + static_cast(strlen(sourceArray[2])), + -1, + }; + ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths)); + + glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); + glCompileShader(shader); + + GLint compileResult; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); + EXPECT_NE(compileResult, 0); +} + +// Verify that zero-length shader source does not affect shader compilation. +TEST_P(GLSLValidationTest, ZeroShaderLength) +{ + GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); + + const char *sourceArray[] = { + "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm", + }; + GLint lengths[] = { + 0, 0, -1, 0, 0, + }; + ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths)); + + glShaderSource(shader, static_cast(ArraySize(sourceArray)), sourceArray, lengths); + glCompileShader(shader); + + GLint compileResult; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); + EXPECT_NE(compileResult, 0); +} + +// Test that structs defined in uniforms are translated correctly. +TEST_P(GLSLValidationTest, StructSpecifiersUniforms) +{ + constexpr char kFS[] = R"(precision mediump float; + +uniform struct S { float field; } s; + +void main() +{ + gl_FragColor = vec4(1, 0, 0, 1); + gl_FragColor.a += s.field; +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow +// extension pragmas later +TEST_P(GLSLValidationTest, NonPreprocessorTokensInIfBlocks) +{ + constexpr const char *kFS = R"( +#if __VERSION__ >= 300 + inout mediump vec4 fragData; +#else + #extension GL_EXT_shader_texture_lod :enable +#endif + +void main() +{ +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in +// HLSL). +TEST_P(GLSLValidationTest_ES3, AmbiguousConstructorCall2x2) +{ + constexpr char kVS[] = R"(#version 300 es +precision highp float; +in vec4 a_vec; +in mat2 a_mat; +void main() +{ + gl_Position = vec4(a_vec) + vec4(a_mat); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated. +// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between +// the function signatures in this case. +TEST_P(GLSLValidationTest_ES3, AmbiguousConstructorCall2x3) +{ + constexpr char kVS[] = R"(#version 300 es +precision highp float; +in mat3x2 a_matA; +in mat2x3 a_matB; +void main() +{ + gl_Position = vec4(a_matA) + vec4(a_matB); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL). +TEST_P(GLSLValidationTest_ES3, AmbiguousFunctionCall2x2) +{ + constexpr char kVS[] = R"(#version 300 es +precision highp float; +in vec4 a_vec; +in mat2 a_mat; +vec4 foo(vec4 a) +{ + return a; +} +vec4 foo(mat2 a) +{ + return vec4(a[0][0]); +} +void main() +{ + gl_Position = foo(a_vec) + foo(a_mat); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that an user-defined function with a large number of float4 parameters doesn't fail due to +// the function name being too long. +TEST_P(GLSLValidationTest_ES3, LargeNumberOfFloat4Parameters) +{ + std::stringstream vs; + // Note: SPIR-V doesn't allow more than 255 parameters to a function. + const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u; + + vs << R"(#version 300 es +precision highp float; +in vec4 a_vec; +vec4 lotsOfVec4Parameters()"; + for (unsigned int i = 0; i < paramCount - 1; ++i) + { + vs << "vec4 a" << i << ", "; + } + vs << R"(vec4 aLast) +{ + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);)"; + for (unsigned int i = 0; i < paramCount - 1; ++i) + { + vs << " sum += a" << i << ";\n"; + } + vs << R"( sum += aLast; + return sum; +} +void main() +{ + gl_Position = lotsOfVec4Parameters()"; + for (unsigned int i = 0; i < paramCount - 1; ++i) + { + vs << "a_vec, "; + } + vs << R"(a_vec); +})"; + validateSuccess(GL_VERTEX_SHADER, vs.str().c_str()); +} + +// This test was written specifically to stress DeferGlobalInitializers AST transformation. +// Test a shader where a global constant array is initialized with an expression containing array +// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to +// be handled in a way that doesn't generate statements in the global scope in HLSL output. +// Also includes multiple array initializers in one declaration, where only the second one has +// array indexing. This makes sure that the qualifier for the declaration is set correctly if +// transformations are applied to the declaration also in the case of ESSL output. +TEST_P(GLSLValidationTest_ES3, InitGlobalArrayWithArrayIndexing) +{ + // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260423 is fixed + ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES()); + + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 my_FragColor; +const highp float f[2] = float[2](0.1, 0.2); +const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]); +void main() +{ + my_FragColor = vec4(h[1]); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that index-constant sampler array indexing is supported. +TEST_P(GLSLValidationTest, IndexConstantSamplerArrayIndexing) +{ + constexpr char kFS[] = R"( +precision mediump float; +uniform sampler2D uni[2]; + +float zero(int x) +{ + return float(x) - float(x); +} + +void main() +{ + vec4 c = vec4(0,0,0,0); + for (int ii = 1; ii < 3; ++ii) { + if (c.x > 255.0) { + c.x = 255.0 + zero(ii); + break; + } + // Index the sampler array with a predictable loop index (index-constant) as opposed to + // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions, + // without an extension. + c += texture2D(uni[ii - 1], vec2(0.5, 0.5)); + } + gl_FragColor = c; +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the +// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't +// want to test its behavior, so don't use any varyings. +TEST_P(GLSLValidationTest, PragmaDirective) +{ + constexpr char kVS[] = R"(#pragma STDGL invariant(all) +void main() +{ + gl_Position = vec4(1.0, 0.0, 0.0, 1.0); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Tests that using a constant declaration as the only statement in a for loop without curly braces +// doesn't crash. +TEST_P(GLSLValidationTest, ConstantStatementInForLoop) +{ + constexpr char kVS[] = R"(void main() +{ + for (int i = 0; i < 10; ++i) + const int b = 0; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this +// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3. +TEST_P(GLSLValidationTest_ES3, ConstantStatementAsLoopInit) +{ + constexpr char kVS[] = R"(void main() +{ + for (const int i = 0; i < 0;) {} +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Tests that using a constant condition guarding a discard works +// Covers a failing case in the Vulkan backend: http://anglebug.com/42265506 +TEST_P(GLSLValidationTest_ES3, ConstantConditionGuardingDiscard) +{ + constexpr char kFS[] = R"(#version 300 es +void main() +{ + if (true) + { + discard; + } +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Tests that nesting a discard in unconditional blocks works +// Covers a failing case in the Vulkan backend: http://anglebug.com/42265506 +TEST_P(GLSLValidationTest_ES3, NestedUnconditionalDiscards) +{ + constexpr char kFS[] = R"(#version 300 es +out mediump vec4 c; +void main() +{ + { + c = vec4(0); + { + discard; + } + } +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Tests that rewriting samplers in structs works when passed as function argument. In this test, +// the function references another struct, which is not being modified. Regression test for AST +// validation applied to a multipass transformation, where references to declarations were attempted +// to be validated without having the entire shader. In this case, the reference to S2 was flagged +// as invalid because S2's declaration was not visible. +TEST_P(GLSLValidationTest, SamplerInStructAsFunctionArg) +{ + constexpr char kFS[] = R"(precision mediump float; +struct S { sampler2D samp; bool b; }; +struct S2 { float f; }; + +uniform S us; + +float f(S s) +{ + S2 s2; + s2.f = float(s.b); + return s2.f; +} + +void main() +{ + gl_FragColor = vec4(f(us), 0, 0, 1); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation. +TEST_P(GLSLValidationTest, VectorScalarArithmeticWithSideEffectInLoop) +{ + // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past + // (notice how sbcd references i outside the for loop. The loop condition doesn't look right + // either): + // + // #version 450 + // void main(){ + // (gl_Position = vec4(0.0, 0.0, 0.0, 0.0)); + // mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + // vec3 _ures = vec3(0.0, 0.0, 0.0); + // vec3 sbcd = vec3(_ures[_ui]); + // for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)), + // sbcd)), _ui)], (_ui < 7)); ) + // { + // } + // } + + constexpr char kVS[] = R"( +void main() +{ + mat3 tmp; + vec3 res; + for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that inactive output variables compile ok in combination with initOutputVariables +// (which is enabled on WebGL). +TEST_P(WebGL2GLSLValidationTest, InactiveOutput) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; +out vec4 _cassgl_2_; +void main() +{ +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that output variables declared after main work in combination with initOutputVariables +// (which is enabled on WebGL). +TEST_P(WebGLGLSLValidationTest, OutputAfterMain) +{ + constexpr char kVS[] = R"(void main(){} +varying float r;)"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test angle can handle big initial stack size with dynamic stack allocation. +TEST_P(GLSLValidationTest, MemoryExhaustedTest) +{ + constexpr int kLength = 36; + + std::stringstream fs; + fs << "void main() {\n"; + for (int i = 0; i < kLength; i++) + { + fs << " if (true) {\n"; + } + fs << " int temp;\n"; + for (int i = 0; i <= kLength; i++) + { + fs << "}"; + } + validateSuccess(GL_FRAGMENT_SHADER, fs.str().c_str()); +} + +// Test that separating declarators works with structs that have been separately defined. +TEST_P(GLSLValidationTest_ES31, SeparateDeclaratorsOfStructType) +{ + constexpr char kVS[] = R"(#version 310 es +precision highp float; + +struct S +{ + mat4 a; + mat4 b; +}; + +S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5))); + +void main() { + S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5; + + gl_Position = vec4(s3[1].a[0].x, s2[0][2].b[1].y, s4[1][0].a[2].z, s6[0].b[3].w); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that separating declarators works with structs that are simultaneously defined. +TEST_P(GLSLValidationTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified) +{ + constexpr char kVS[] = R"(#version 310 es +precision highp float; + +struct S +{ + mat4 a; + mat4 b; +} s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5))); + +void main() { + struct T + { + mat4 a; + mat4 b; + } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5; + + float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y; + + gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that separating declarators works with structs that are simultaneously defined and that are +// nameless. +TEST_P(GLSLValidationTest_ES31, SeparateDeclaratorsOfNamelessStructType) +{ + constexpr char kVS[] = R"(#version 310 es +precision highp float; + +struct +{ + mat4 a; + mat4 b; +} s1, s2[2][3], s3[2]; + +void main() { + struct + { + mat4 a; + mat4 b; + } s4[2][3], s5, s6[2], s7 = s5; + + float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z; + + gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test for transformation bug which separates struct declarations from uniform +// declarations. The bug was that the uniform variable usage in the initializer of a new +// declaration (y below) was not being processed. +TEST_P(GLSLValidationTest, UniformStructBug) +{ + constexpr char kVS[] = R"(precision highp float; + +uniform struct Global +{ + float x; +} u_global; + +void main() { + float y = u_global.x; + + gl_Position = vec4(y); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test for transformation bug which separates struct declarations from uniform +// declarations. The bug was that the arrayness of the declaration was not being applied to the +// replaced uniform variable. +TEST_P(GLSLValidationTest_ES31, UniformStructBug2) +{ + constexpr char kVS[] = R"(#version 310 es +precision highp float; + +uniform struct Global +{ + float x; +} u_global[2][3]; + +void main() { + float y = u_global[0][0].x; + + gl_Position = vec4(y); +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition +// was not found in the tree. Tests that struct declaration in function return value is visible to +// instantiations later on. +TEST_P(GLSLValidationTest, MissingStructDeclarationBug) +{ + constexpr char kVS[] = R"( +struct S +{ + vec4 i; +} p(); +void main() +{ + S s; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition +// was not found in the tree. Tests that struct declaration in function return value is visible to +// other struct declarations. +TEST_P(GLSLValidationTest, MissingStructDeclarationBug2) +{ + constexpr char kVS[] = R"( +struct T +{ + vec4 I; +} p(); +struct +{ + T c; +}; +void main() +{ +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test for bug in HLSL code generation where the for loop init expression was expected +// to always have an initializer. +TEST_P(GLSLValidationTest, HandleExcessiveLoopBug) +{ + constexpr char kVS[] = R"(void main(){for(int i;i>6;);})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that providing more components to a matrix constructor than necessary works. Based on a +// clusterfuzz test that caught an OOB array write in glslang. +TEST_P(GLSLValidationTest, MatrixConstructor) +{ + constexpr char kVS[] = R"(attribute vec4 aPosition; +varying vec4 vColor; +void main() +{ + gl_Position = aPosition; + vec4 color = vec4(aPosition.xy, 0, 1); + mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz); + vColor = m4[0]; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test constructors without precision +TEST_P(GLSLValidationTest, ConstructFromBoolVector) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform float u; +void main() +{ + mat4 m = mat4(u); + mat2(0, bvec3(m)); + gl_FragColor = vec4(m); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test constructing vector from matrix +TEST_P(GLSLValidationTest, VectorConstructorFromMatrix) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform mat2 umat2; +void main() +{ + gl_FragColor = vec4(umat2); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that initializing global variables with non-constant values work +TEST_P(GLSLValidationTest_ES3, InitGlobalNonConstant) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers")); + + constexpr char kVS[] = R"(#version 300 es +#extension GL_EXT_shader_non_constant_global_initializers : require +uniform vec4 u; +out vec4 color; + +vec4 global1 = u; +vec4 global2 = u + vec4(1); +vec4 global3 = global1 * global2; +void main() +{ + color = global3; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test for a crash in SPIR-V output when faced with an array of struct constant. +TEST_P(GLSLValidationTest_ES3, ArrayOfStructConstantBug) +{ + constexpr char kFS[] = R"(#version 300 es +struct S { + int foo; +}; +void main() { + S a[3]; + a = S[3](S(0), S(1), S(2)); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Regression test for a bug in SPIR-V output where float+matrix was mishandled. +TEST_P(GLSLValidationTest_ES3, FloatPlusMatrix) +{ + constexpr char kFS[] = R"(#version 300 es + +precision mediump float; + +layout(location=0) out vec4 color; + +uniform float f; + +void main() +{ + mat3x2 m = f + mat3x2(0); + color = vec4(m[0][0]); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Regression test for a bug in SPIR-V output where a transformation creates float(constant) without +// folding it into a TIntermConstantUnion. This transformation is clamping non-constant indices in +// WebGL. The |false ? i : 5| as index caused the transformation to consider this a non-constant +// index. +TEST_P(WebGL2GLSLValidationTest, IndexClampConstantIndexBug) +{ + constexpr char kFS[] = R"(#version 300 es +precision highp float; + +layout(location=0) out float f; + +uniform int i; + +void main() +{ + float data[10]; + f = data[false ? i : 5]; +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without +// failing validation (adapted from a Chromium test, see anglebug.com/42265427) +TEST_P(GLSLValidationTest, FramebufferFetchWithLastFragData) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kFS[] = R"(#version 100 + +#extension GL_EXT_shader_framebuffer_fetch : require +varying mediump vec4 color; +void main() { + gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0]; +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that loop body ending in a branch doesn't fail compilation +TEST_P(GLSLValidationTest, LoopBodyEndingInBranch1) +{ + constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that loop body ending in a branch doesn't fail compilation +TEST_P(GLSLValidationTest, LoopBodyEndingInBranch2) +{ + constexpr char kFS[] = + R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that loop body ending in a branch doesn't fail compilation +TEST_P(GLSLValidationTest, LoopBodyEndingInBranch3) +{ + constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that loop body ending in a branch doesn't fail compilation +TEST_P(GLSLValidationTest, LoopBodyEndingInBranch4) +{ + constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that loop body ending in a branch doesn't fail compilation +TEST_P(GLSLValidationTest, LoopBodyEndingInBranch5) +{ + constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that loop body ending in a branch doesn't fail compilation +TEST_P(GLSLValidationTest, LoopBodyEndingInBranch6) +{ + constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Fuzzer test involving struct samplers and comma operator +TEST_P(GLSLValidationTest, StructSamplerVsComma) +{ + constexpr char kVS[] = R"(uniform struct S1 +{ + samplerCube ar; + vec2 c; +} a; + +struct S2 +{ + vec3 c; +} b[2]; + +void main (void) +{ + ++b[0].c,a; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test for a bug where the sampler-in-struct rewrite transformation did not take a +// specific pattern of side_effect,index_the_struct_to_write into account. +TEST_P(GLSLValidationTest_ES3, StructWithSamplerRHSOfCommaWithSideEffect) +{ + constexpr char kVS[] = R"(uniform struct S { + sampler2D s; + mat2 m; +} u[2]; +void main() +{ + ++gl_Position, u[0]; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Regression test for a bug where the sampler-in-struct rewrite transformation did not take a +// specific pattern of side_effect,struct_with_only_samplers into account. +TEST_P(GLSLValidationTest_ES3, StructWithOnlySamplersRHSOfCommaWithSideEffect) +{ + constexpr char kVS[] = R"(uniform struct S { + sampler2D s; +} u; +void main() +{ + ++gl_Position, u; +})"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test that structs-with-samplers cannot be the result of the ternary operator. The spec says for +// the ternary operator that: +// +// > The second and third expressions cannot be opaque types, or there will be an error. +// +// While it doesn't specifically rule out structs with samplers in them, it's reasonable to also +// disallow that. +TEST_P(GLSLValidationTest_ES31, StructWithSamplerAsTernaryResult) +{ + constexpr char kVS[] = R"(#version 310 es +struct A { + vec4 v; + sampler2D s; +}; +struct B { + A a[2]; +}; +uniform B b1[3]; +uniform B b2[4]; +uniform bool choose; + +vec4 f(A a[2]) +{ + return texture(a[0].s, vec2(0)); +} + +void main() +{ + gl_Position = f(choose ? b1[0].a : b2[0].a); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'?:' : ternary operator is not allowed for opaque types"); +} + +// Test that gl_FragDepth can be marked invariant. +TEST_P(GLSLValidationTest_ES3, FragDepthInvariant) +{ + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_conservative_depth: enable +precision mediump float; +invariant gl_FragDepth; +void main() { + gl_FragDepth = 0.5; +} +)"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that gl_Position and gl_PointSize can be marked invariant and redeclared in separate +// statements. Note that EXT_seperate_shader_objects expects the redeclaration to come first. +TEST_P(GLSLValidationTest_ES31, PositionRedeclaredAndInvariant) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_separate_shader_objects")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_separate_shader_objects: require +precision mediump float; +out vec4 gl_Position; +out float gl_PointSize; +invariant gl_Position; +invariant gl_PointSize; +void main() { +} +)"; + validateSuccess(GL_VERTEX_SHADER, kVS); +} + +// Test an invalid shader where a for loop index is used as an out parameter. +// See limitations in ESSL 1.00 Appendix A. +TEST_P(WebGLGLSLValidationTest, IndexAsFunctionOutParameter) +{ + constexpr char kFS[] = R"(precision mediump float; +void fun(out int a) +{ + a = 2; +} +void main() +{ + for (int i = 0; i < 2; ++i) + { + fun(i); + } + gl_FragColor = vec4(0.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'i' : Loop index cannot be statically assigned to within the body of the loop"); +} + +// Test an invalid shader where a for loop index is used as an inout parameter. +// See limitations in ESSL 1.00 Appendix A. +TEST_P(WebGLGLSLValidationTest, IndexAsFunctionInOutParameter) +{ + constexpr char kFS[] = R"(precision mediump float; +void fun(int b, inout int a) +{ + a += b; +} +void main() +{ + for (int i = 0; i < 2; ++i) + { + fun(2, i); + } + gl_FragColor = vec4(0.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'i' : Loop index cannot be statically assigned to within the body of the loop"); +} + +// Test a valid shader where a for loop index is used as an in parameter in a function that also has +// an out parameter. +// See limitations in ESSL 1.00 Appendix A. +TEST_P(WebGLGLSLValidationTest, IndexAsFunctionInParameter) +{ + constexpr char kFS[] = R"(precision mediump float; +void fun(int b, inout int a) +{ + a += b; +} +void main() +{ + for (int i = 0; i < 2; ++i) + { + int a = 1; + fun(i, a); + } + gl_FragColor = vec4(0.0); +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test an invalid shader where a for loop index is used as a target of assignment. +// See limitations in ESSL 1.00 Appendix A. +TEST_P(WebGLGLSLValidationTest, IndexAsTargetOfAssignment) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() +{ + for (int i = 0; i < 2; ++i) + { + i = 2; + } + gl_FragColor = vec4(0.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'i' : Loop index cannot be statically assigned to within the body of the loop"); +} + +// Test an invalid shader where a for loop index is incremented inside the loop. +// See limitations in ESSL 1.00 Appendix A. +TEST_P(WebGLGLSLValidationTest, IndexIncrementedInLoopBody) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() +{ + for (int i = 0; i < 2; ++i) + { + ++i; + } + gl_FragColor = vec4(0.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'i' : Loop index cannot be statically assigned to within the body of the loop"); +} + +// Shader that writes to SecondaryFragColor and SecondaryFragData does not compile. +TEST_P(GLSLValidationTest, BlendFuncExtendedSecondaryColorAndData) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +precision mediump float; +void main() { + gl_SecondaryFragColorEXT = vec4(1.0); + gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT) and " + "(gl_FragColor, gl_SecondaryFragColorEXT)"); +} + +// Shader that writes to FragColor and SecondaryFragData does not compile. +TEST_P(GLSLValidationTest, BlendFuncExtendedColorAndSecondaryData) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +precision mediump float; +void main() { + gl_FragColor = vec4(1.0); + gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT) and " + "(gl_FragColor, gl_SecondaryFragColorEXT)"); +} + +// Shader that writes to FragData and SecondaryFragColor. +TEST_P(GLSLValidationTest, BlendFuncExtendedDataAndSecondaryColor) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers")); + + constexpr char kFS[] = R"(#extension GL_EXT_draw_buffers : require +#extension GL_EXT_blend_func_extended : require +precision mediump float; +void main() { + gl_SecondaryFragColorEXT = vec4(1.0); + gl_FragData[gl_MaxDrawBuffers - 1] = vec4(0.1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT) and " + "(gl_FragColor, gl_SecondaryFragColorEXT)"); +} + +// Dynamic indexing of SecondaryFragData is not allowed in WebGL 2.0. +TEST_P(WebGL2GLSLValidationTest, BlendFuncExtendedSecondaryDataIndexing) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = R"(#extension GL_EXT_blend_func_extended : require +precision mediump float; +void main() { + for (int i = 0; i < 2; ++i) { + gl_SecondaryFragDataEXT[true ? 0 : i] = vec4(0.0); + } +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "array index for gl_SecondaryFragDataEXT must be constant zero"); +} + +// Shader that specifies index layout qualifier but not location fails to compile. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedNoLocationQualifier) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(index = 0) out vec4 fragColor; +void main() { + fragColor = vec4(1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'index' : If index layout qualifier is specified for a fragment output, " + "location must also be specified"); +} + +// Shader that specifies index layout qualifier multiple times fails to compile. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedMultipleIndexQualifiers) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(index = 0, location = 0, index = 1) out vec4 fragColor; +void main() { + fragColor = vec4(1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'index' : Cannot have multiple index specifiers"); +} + +// Shader that specifies an output with out-of-bounds location +// for index 0 when another output uses index 1 is invalid. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedOutOfBoundsLocationQualifier) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + GLint maxDualSourceDrawBuffers = 0; + glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers); + ANGLE_SKIP_TEST_IF(maxDualSourceDrawBuffers > 1); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(location = 1, index = 0) out mediump vec4 fragColor; +layout(location = 0, index = 1) out mediump vec4 secondaryFragColor; +void main() { + fragColor = vec4(1); + secondaryFragColor = vec4(1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'fragColor' : output location must be < MAX_DUAL_SOURCE_DRAW_BUFFERS"); +} + +// Shader that specifies an output with out-of-bounds location for index 1 is invalid. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedOutOfBoundsLocationQualifierIndex1) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + GLint maxDualSourceDrawBuffers = 0; + glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers); + ANGLE_SKIP_TEST_IF(maxDualSourceDrawBuffers > 1); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(location = 1, index = 1) out mediump vec4 secondaryFragColor; +void main() { + secondaryFragColor = vec4(1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'secondaryFragColor' : output location must be < MAX_DUAL_SOURCE_DRAW_BUFFERS"); +} + +// Shader that specifies two outputs with the same location +// but different indices and different base types is invalid. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedLocationOverlap) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(location = 0, index = 0) out mediump vec4 fragColor; +layout(location = 0, index = 1) out mediump ivec4 secondaryFragColor; +void main() { + fragColor = vec4(1); + secondaryFragColor = ivec4(1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'secondaryFragColor' : conflicting output types with previously defined output " + "'fragColor' for location 0"); +} + +// Global index layout qualifier fails. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedGlobalIndexQualifier) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(index = 0); +out vec4 fragColor; +void main() { + fragColor = vec4(1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'index' : invalid layout qualifier: only valid when used with a fragment shader " + "output in ESSL version >= 3.00 and EXT_blend_func_extended is enabled"); +} + +// Index layout qualifier on a non-output variable fails. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedIndexQualifierOnUniform) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(index = 0) uniform vec4 u; +out vec4 fragColor; +void main() { + fragColor = u; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'index' : invalid layout qualifier: only valid when used with a fragment shader " + "output in ESSL version >= 3.00 and EXT_blend_func_extended is enabled"); +} + +// Index layout qualifier on a struct fails. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedIndexQualifierOnStruct) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +layout(index = 0) struct S { + vec4 field; +}; +out vec4 fragColor; +void main() { + fragColor = vec4(1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'index' : invalid layout qualifier: only valid when used with a fragment shader " + "output in ESSL version >= 3.00 and EXT_blend_func_extended is enabled"); +} + +// Index layout qualifier on a struct member fails. +TEST_P(GLSLValidationTest_ES3, BlendFuncExtendedIndexQualifierOnField) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_blend_func_extended : require +precision mediump float; +struct S { + layout(index = 0) vec4 field; +}; +out mediump vec4 fragColor; +void main() { + fragColor = vec4(1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'index' : invalid layout qualifier: only valid when used with a fragment shader " + "output in ESSL version >= 3.00 and EXT_blend_func_extended is enabled"); +} + +// Shader that specifies yuv layout qualifier for not output fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetYuvQualifierOnInput) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(yuv) in vec4 fragColor; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'yuv' : invalid layout qualifier: only valid on program outputs"); +} + +// Shader that specifies yuv layout qualifier for not output fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetYuvQualifierOnUniform) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(yuv) uniform; +layout(yuv) uniform Transform { + mat4 M1; +}; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'yuv' : invalid layout qualifier: only valid on program outputs"); +} + +// Shader that specifies yuv layout qualifier with location fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetYuvQualifierAndLocation) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(location = 0, yuv) out vec4 fragColor; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'yuv' : invalid layout qualifier combination"); +} + +// Shader that specifies yuv layout qualifier with multiple color outputs fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetYuvAndColorOutput) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(yuv) out vec4 fragColor; +out vec4 fragColor1; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'fragColor' : not allowed to specify yuv qualifier when using depth or multiple " + "color fragment outputs"); +} + +// Shader that specifies yuv layout qualifier with multiple color outputs fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetYuvAndColorOutputWithLocation) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(yuv) out vec4 fragColor; +layout(location = 1) out vec4 fragColor1; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'fragColor' : not allowed to specify yuv qualifier when using depth or multiple " + "color fragment outputs"); +} + +// Shader that specifies yuv layout qualifier with depth output fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetWithFragDepth) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(yuv) out vec4 fragColor; +void main() { + gl_FragDepth = 1.0f; +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'fragColor' : not allowed to specify yuv qualifier when using depth or multiple " + "color fragment outputs"); +} + +// Shader that specifies yuv layout qualifier with multiple outputs fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetMultipleYuvOutputs) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +layout(yuv) out vec4 fragColor; +layout(yuv) out vec4 fragColor1; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'fragColor' : not allowed to specify yuv qualifier when using depth or multiple " + "color fragment outputs"); + validateError(GL_FRAGMENT_SHADER, kFS, + "'fragColor1' : not allowed to specify yuv qualifier when using depth or " + "multiple color fragment outputs"); +} + +// Shader that specifies yuvCscStandardEXT type constructor fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetEmptyCscStandardConstructor) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = yuvCscStandardEXT(); +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'yuvCscStandardEXT' : cannot construct this type"); +} + +// Shader that specifies yuvCscStandardEXT type constructor fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetCscStandardConstructor) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = yuvCscStandardEXT(itu_601); +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'yuvCscStandardEXT' : cannot construct this type"); +} + +// Shader that specifies yuvCscStandardEXT type conversion fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetImplicitTypeConversionToCscStandardFromBool) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = false; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "cannot convert from 'const bool' to 'yuvCscStandardEXT'"); +} + +// Shader that specifies yuvCscStandardEXT type conversion fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetImplicitTypeConversionToCscStandardFromInt) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = 0; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "cannot convert from 'const int' to 'yuvCscStandardEXT'"); +} + +// Shader that specifies yuvCscStandardEXT type conversion fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetImplicitTypeConversionToCscStandardFromFloat) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = 2.0f; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "cannot convert from 'const float' to 'yuvCscStandardEXT'"); +} + +// Shader that does arithmetics on yuvCscStandardEXT fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetCscStandardOr) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = itu_601 | itu_709; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "wrong operand types - no operation '|' exists that takes a left-hand operand of " + "type 'const yuvCscStandardEXT' and a right operand of type 'const " + "yuvCscStandardEXT' (or there is no acceptable conversion)"); +} + +// Shader that does arithmetics on yuvCscStandardEXT fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetCscStandardAnd) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +yuvCscStandardEXT conv = itu_601 & 3.0f; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "wrong operand types - no operation '&' exists that takes a left-hand operand of " + "type 'const yuvCscStandardEXT' and a right operand of type 'const float' (or " + "there is no acceptable conversion)"); +} + +// Shader that specifies yuvCscStandardEXT type qualifiers fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetCscStandardInput) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +in yuvCscStandardEXT conv = itu_601; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'in' : cannot be used with a yuvCscStandardEXT"); +} + +// Shader that specifies yuvCscStandardEXT type qualifiers fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetCscStandardOutput) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +out yuvCscStandardEXT conv = itu_601; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'out' : cannot be used with a yuvCscStandardEXT"); +} + +// Shader that specifies yuvCscStandardEXT type qualifiers fails to compile. +TEST_P(GLSLValidationTest_ES3, YUVTargetCscStandardUniform) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision mediump float; +uniform yuvCscStandardEXT conv = itu_601; +void main() { +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "'uniform' : cannot be used with a yuvCscStandardEXT"); +} + +// Overloading rgb_2_yuv is ok if the extension is not supported. +TEST_P(GLSLValidationTest_ES3, OverloadRgb2Yuv) +{ + ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +float rgb_2_yuv(float x) { return x + 1.0; } + +in float i; +out float o; + +void main() +{ + o = rgb_2_yuv(i); +})"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Overloading yuv_2_rgb is ok if the extension is not supported. +TEST_P(GLSLValidationTest_ES3, OverloadYuv2Rgb) +{ + ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_YUV_target")); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +float yuv_2_rgb(float x) { return x + 1.0; } + +in float i; +out float o; + +void main() +{ + o = yuv_2_rgb(i); +})"; + + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Use gl_LastFragData without redeclaration of gl_LastFragData with noncoherent qualifier +TEST_P(GLSLValidationTest, FramebufferFetchNoLastFragDataRedeclaration) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent")); + + constexpr char kFS[] = + R"(#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require +uniform highp vec4 u_color; + +void main (void) +{ + gl_FragColor = u_color + gl_LastFragData[0]; +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'noncoherent' qualifier must be used when " + "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used"); +} + +// Redeclare gl_LastFragData without noncoherent qualifier +TEST_P(GLSLValidationTest, FramebufferFetchLastFragDataWithoutNoncoherentQualifier) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent")); + + constexpr char kFS[] = + R"(#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require +uniform highp vec4 u_color; +highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; + +void main (void) +{ + gl_FragColor = u_color + gl_LastFragData[0]; +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'noncoherent' qualifier must be used when " + "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used"); +} + +// Declare inout without noncoherent qualifier +TEST_P(GLSLValidationTest_ES3, FramebufferFetchInoutWithoutNoncoherentQualifier) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent")); + + constexpr char kFS[] = + R"(#version 300 es +#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require +layout(location = 0) inout highp vec4 o_color; +uniform highp vec4 u_color; + +void main (void) +{ + o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f)); +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, + "'noncoherent' qualifier must be used when " + "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used"); +} + +// Ensure that a negative index after a comma generates an error. +TEST_P(GLSLValidationTest_ES3, NegativeIndexAfterComma) +{ + constexpr char kFS[] = R"(#version 300 es +layout(location = 0) out mediump vec4 o_color; +uniform mediump float u; +uniform mediump vec4 u_color[4]; + +void main (void) +{ + o_color = u_color[u,-2]; +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "index expression is negative"); +} + +// Ensure that a negative const-variable index after a comma generates an error. +TEST_P(GLSLValidationTest_ES3, NegativeConstVarIndexAfterComma) +{ + constexpr char kFS[] = R"(#version 300 es +layout(location = 0) out mediump vec4 o_color; +uniform mediump float u; +uniform mediump vec4 u_color[4]; + +void main (void) +{ + const int index = -2; + o_color = u_color[u,index]; +})"; + + validateError(GL_FRAGMENT_SHADER, kFS, "index expression is negative"); +} + +// Validate that clip/cull distance extensions are not available in ESSL 100 +TEST_P(GLSLValidationTest, ClipCullDistance) +{ + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + constexpr char kVS[] = R"(#extension GL_ANGLE_clip_cull_distance : require +attribute vec4 aPosition; +void main() +{ + gl_Position = aPosition; +})"; + validateError(GL_VERTEX_SHADER, kVS, + "'GL_ANGLE_clip_cull_distance' : extension is not supported"); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + constexpr char kVS[] = R"(#extension GL_EXT_clip_cull_distance : require +attribute vec4 aPosition; +void main() +{ + gl_Position = aPosition; +})"; + validateError(GL_VERTEX_SHADER, kVS, + "'GL_EXT_clip_cull_distance' : extension is not supported"); + } +} + +// Validate that conflicts are generated for locations consumed by an I/O block array. +TEST_P(GLSLValidationTest_ES31, IOBlockArrayLocations) +{ + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_shader_io_blocks : require + +in highp vec4 position; + +// This should consume locations [3, 8] +layout(location = 3) out Block +{ + vec4 a; + vec4 b; +} block[3]; + +// c will conflict with block[0].a +layout(location = 2) out vec4 c[2]; + +// d will conflict with block[0].b, block[1].a and block[1].b +layout(location = 4) out vec4 d[3]; + +// e will conflict with block[2].a +layout(location = 7) out vec4 e; + +// f will conflict with block[2].b +layout(location = 7) out vec4 f[2]; + +void main() +{ + block[0].a = vec4(0.1); + block[0].b = vec4(0.2); + block[1].a = vec4(0.3); + block[1].b = vec4(0.4); + block[2].a = vec4(0.5); + block[2].b = vec4(0.6); + c[0] = vec4(0.7); + c[1] = vec4(0.8); + d[0] = vec4(0.9); + d[1] = vec4(1.0); + d[2] = vec4(1.1); + e = vec4(1.2); + f[0] = vec4(1.3); + f[1] = vec4(1.4); + gl_Position = position; +})"; + + const CompiledShader &shader = compile(GL_VERTEX_SHADER, kVS); + EXPECT_FALSE(shader.success()); + + const char *kExpect[] = { + "'c' conflicting location with 'block.a'", + "'d' conflicting location with 'block.b'", + "'e' conflicting location with 'block'", + "'f' conflicting location with 'block'", + }; + + for (const char *expect : kExpect) + { + EXPECT_TRUE(shader.hasInfoLog(expect)) << expect; + } + + reset(); +} + +class GLSLValidationClipDistanceTest_ES3 : public GLSLValidationTest_ES3 +{ + protected: + void validateErrorWithExt(GLenum shaderType, + const char *extension, + const char *shaderSource, + const char *expectedError) + { + std::stringstream src; + src << R"(#version 300 es +#extension )" + << extension << ": require\n" + << shaderSource; + validateError(shaderType, src.str().c_str(), expectedError); + } +}; + +class GLSLValidationClipDistanceTest_ES31 : public GLSLValidationTest_ES31 +{ + protected: + void validateErrorWithExt(GLenum shaderType, + const char *extension, + const char *shaderSource, + const char *expectedError) + { + std::stringstream src; + src << R"(#version 310 es +#extension )" + << extension << ": require\n" + << shaderSource; + validateError(shaderType, src.str().c_str(), expectedError); + } +}; + +// Extension support is required to compile properly. Expect failure when it is not present. +TEST_P(GLSLValidationClipDistanceTest_ES3, CompileFailsWithoutExtension) +{ + ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_APPLE_clip_distance")); + + { + constexpr char kVS[] = R"(#extension GL_APPLE_clip_distance : require +uniform vec4 uPlane; + +attribute vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[1] = dot(aPosition, uPlane); +})"; + validateError(GL_VERTEX_SHADER, kVS, + "'GL_APPLE_clip_distance' : extension is not supported"); + } + + { + constexpr char kVS[] = R"(#version 300 es +#extension GL_APPLE_clip_distance : require +uniform vec4 uPlane; + +in vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[1] = dot(aPosition, uPlane); +})"; + validateError(GL_VERTEX_SHADER, kVS, + "'GL_APPLE_clip_distance' : extension is not supported"); + } +} + +// Extension directive is required to compile properly. Expect failure when it is not present. +TEST_P(GLSLValidationClipDistanceTest_ES3, CompileFailsWithExtensionWithoutPragma) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance")); + + { + constexpr char kVS[] = R"(uniform vec4 uPlane; + +attribute vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[1] = dot(aPosition, uPlane); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'GL_APPLE_clip_distance' : extension is disabled"); + } + + { + constexpr char kVS[] = R"(#version 300 es +uniform vec4 uPlane; + +in vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[1] = dot(aPosition, uPlane); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'GL_APPLE_clip_distance' : extension is disabled"); + } +} + +// Shader using gl_ClipDistance and gl_CullDistance +// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances +TEST_P(GLSLValidationClipDistanceTest_ES3, TooManyCombined) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_clip_cull_distance"); + const bool hasAngle = IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance"); + ANGLE_SKIP_TEST_IF(!hasExt && !hasAngle); + + GLint maxCombinedClipAndCullDistances = 0; + glGetIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT, &maxCombinedClipAndCullDistances); + ANGLE_SKIP_TEST_IF(maxCombinedClipAndCullDistances > 11); + + constexpr char kVS[] = + R"(uniform vec4 uPlane; + +in vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[5] = dot(aPosition, uPlane); + gl_CullDistance[4] = dot(aPosition, uPlane); +})"; + constexpr char kExpect[] = + "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " + "gl_MaxCombinedClipAndCullDistance"; + + if (hasAngle) + { + GLint maxCullDistances = 0; + glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances); + if (maxCullDistances > 0) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_ANGLE_clip_cull_distance", kVS, kExpect); + } + } + + if (hasExt) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_EXT_clip_cull_distance", kVS, kExpect); + } +} + +// Shader redeclares gl_ClipDistance and gl_CullDistance +// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances +TEST_P(GLSLValidationClipDistanceTest_ES3, TooManyCombined2) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_clip_cull_distance"); + const bool hasAngle = IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance"); + ANGLE_SKIP_TEST_IF(!hasExt && !hasAngle); + + GLint maxCombinedClipAndCullDistances = 0; + glGetIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT, &maxCombinedClipAndCullDistances); + ANGLE_SKIP_TEST_IF(maxCombinedClipAndCullDistances > 9); + + constexpr char kVS[] = + R"(uniform vec4 uPlane; + +in vec4 aPosition; + +out highp float gl_ClipDistance[5]; +out highp float gl_CullDistance[4]; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); + gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); + gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane); + gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane); +})"; + constexpr char kExpect[] = + "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " + "gl_MaxCombinedClipAndCullDistance"; + + if (hasAngle) + { + GLint maxCullDistances = 0; + glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances); + if (maxCullDistances > 0) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_ANGLE_clip_cull_distance", kVS, kExpect); + } + } + + if (hasExt) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_EXT_clip_cull_distance", kVS, kExpect); + } +} + +// Shader redeclares gl_ClipDistance +// But, the array size is greater than gl_MaxClipDistances +TEST_P(GLSLValidationClipDistanceTest_ES3, TooManyClip) +{ + constexpr char kVS[] = + R"(uniform vec4 uPlane; + +in vec4 aPosition; + +out highp float gl_ClipDistance[gl_MaxClipDistances + 1]; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); + gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); +})"; + constexpr char kExpect[] = "redeclaration of gl_ClipDistance with size > gl_MaxClipDistances"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_ANGLE_clip_cull_distance", kVS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_EXT_clip_cull_distance", kVS, kExpect); + } +} + +// Access gl_CullDistance with integral constant index +// But, the index is gl_MaxCullDistances, greater than gl_CullDistance array size. +TEST_P(GLSLValidationClipDistanceTest_ES3, OutOfBoundsCullIndex) +{ + constexpr char kVS[] = + R"(uniform vec4 uPlane; + +in vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_CullDistance[gl_MaxCullDistances] = dot(aPosition, uPlane); +})"; + constexpr char kExpect[] = "array index out of range"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + GLint maxCullDistances = 0; + glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances); + if (maxCullDistances > 0) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_ANGLE_clip_cull_distance", kVS, kExpect); + } + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_VERTEX_SHADER, "GL_EXT_clip_cull_distance", kVS, kExpect); + } +} + +// Shader using gl_ClipDistance and gl_CullDistance +// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances +TEST_P(GLSLValidationClipDistanceTest_ES3, TooManyCombinedFS) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_clip_cull_distance"); + const bool hasAngle = IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance"); + ANGLE_SKIP_TEST_IF(!hasExt && !hasAngle); + + GLint maxCombinedClipAndCullDistances = 0; + glGetIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT, &maxCombinedClipAndCullDistances); + ANGLE_SKIP_TEST_IF(maxCombinedClipAndCullDistances > 11); + + constexpr char kFS[] = R"(out highp vec4 fragColor; + +void main() +{ + fragColor = vec4(gl_ClipDistance[4], gl_CullDistance[5], 0, 1); +})"; + constexpr char kExpect[] = + "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " + "gl_MaxCombinedClipAndCullDistances"; + + if (hasAngle) + { + GLint maxCullDistances = 0; + glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances); + if (maxCullDistances > 0) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_ANGLE_clip_cull_distance", kFS, kExpect); + } + } + + if (hasExt) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_EXT_clip_cull_distance", kFS, kExpect); + } +} + +// Shader redeclares gl_ClipDistance and gl_CullDistance +// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances +TEST_P(GLSLValidationClipDistanceTest_ES3, TooManyCombinedFS2) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_clip_cull_distance"); + const bool hasAngle = IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance"); + ANGLE_SKIP_TEST_IF(!hasExt && !hasAngle); + + GLint maxCombinedClipAndCullDistances = 0; + glGetIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT, &maxCombinedClipAndCullDistances); + ANGLE_SKIP_TEST_IF(maxCombinedClipAndCullDistances > 9); + + constexpr char kFS[] = R"(in highp float gl_ClipDistance[5]; +in highp float gl_CullDistance[4]; + +in highp vec4 aPosition; + +out highp vec4 fragColor; + +void main() +{ + fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1]; + fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)]; + fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1]; + fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)]; +})"; + constexpr char kExpect[] = + "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " + "gl_MaxCombinedClipAndCullDistances"; + + if (hasAngle) + { + GLint maxCullDistances = 0; + glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances); + if (maxCullDistances > 0) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_ANGLE_clip_cull_distance", kFS, kExpect); + } + } + + if (hasExt) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_EXT_clip_cull_distance", kFS, kExpect); + } +} + +// In fragment shader, writing to gl_ClipDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES3, FragmentWriteToClipDistance) +{ + constexpr char kFS[] = R"(out highp vec4 fragColor; + +void main() +{ + gl_ClipDistance[0] = 0.0f; + fragColor = vec4(1, gl_ClipDistance[0], 0, 1); +})"; + constexpr char kExpect[] = + "l-value required (can't modify gl_ClipDistance in a fragment shader \"gl_ClipDistance\")"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_ANGLE_clip_cull_distance", kFS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_EXT_clip_cull_distance", kFS, kExpect); + } +} + +// In fragment shader, writing to gl_CullDistance should be denied even if redeclaring it with the +// array size +TEST_P(GLSLValidationClipDistanceTest_ES3, FragmentWriteToCullDistance) +{ + constexpr char kFS[] = R"(out highp vec4 fragColor; + +in highp float gl_CullDistance[1]; + +void main() +{ + gl_CullDistance[0] = 0.0f; + fragColor = vec4(1, gl_CullDistance[0], 0, 1); +})"; + constexpr char kExpect[] = + "l-value required (can't modify gl_CullDistance in a fragment shader \"gl_CullDistance\")"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_ANGLE_clip_cull_distance", kFS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_EXT_clip_cull_distance", kFS, kExpect); + } +} + +// Accessing to gl_Clip/CullDistance with non-const index should be denied if the size of +// gl_Clip/CullDistance is not decided. +TEST_P(GLSLValidationClipDistanceTest_ES3, FragmentDynamicIndexWhenNotRedeclared) +{ + constexpr char kFS[] = R"(out highp vec4 fragColor; + +void main() +{ + mediump float color[3]; + for(int i = 0 ; i < 3 ; i++) + { + color[i] = gl_CullDistance[i]; + } + fragColor = vec4(color[0], color[1], color[2], 1.0f); +})"; + constexpr char kExpect[] = + "The gl_CullDistance array must be sized by the shader either redeclaring it with a size " + "or indexing it only with constant integral expressions"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_ANGLE_clip_cull_distance", kFS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_FRAGMENT_SHADER, "GL_EXT_clip_cull_distance", kFS, kExpect); + } +} + +// In compute shader, redeclaring gl_ClipDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES31, ComputeDeclareClipDistance) +{ + constexpr char kCS[] = R"(layout(local_size_x = 1) in; +highp float gl_ClipDistance[1]; +void main() {})"; + constexpr char kExpect[] = "reserved built-in name"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_ANGLE_clip_cull_distance", kCS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_EXT_clip_cull_distance", kCS, kExpect); + } +} + +// In compute shader, writing to gl_ClipDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES31, ComputeWriteClipDistance) +{ + constexpr char kCS[] = R"(layout(local_size_x = 1) in; +void main() { gl_ClipDistance[0] = 1.0; })"; + constexpr char kExpect[] = "'gl_ClipDistance' : undeclared identifier"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_ANGLE_clip_cull_distance", kCS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_EXT_clip_cull_distance", kCS, kExpect); + } +} + +// In compute shader, reading gl_ClipDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES31, ComputeReadClipDistance) +{ + constexpr char kCS[] = R"(layout(local_size_x = 1) in; +void main() { highp float c = gl_ClipDistance[0]; })"; + constexpr char kExpect[] = "'gl_ClipDistance' : undeclared identifier"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_ANGLE_clip_cull_distance", kCS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_EXT_clip_cull_distance", kCS, kExpect); + } +} + +// In compute shader, redeclaring gl_CullDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES31, ComputeDeclareCullDistance) +{ + constexpr char kCS[] = R"(layout(local_size_x = 1) in; +highp float gl_CullDistance[1]; +void main() {})"; + constexpr char kExpect[] = "reserved built-in name"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_ANGLE_clip_cull_distance", kCS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_EXT_clip_cull_distance", kCS, kExpect); + } +} + +// In compute shader, writing to gl_CullDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES31, ComputeWriteCullDistance) +{ + constexpr char kCS[] = R"(layout(local_size_x = 1) in; +void main() { gl_CullDistance[0] = 1.0; })"; + constexpr char kExpect[] = "'gl_CullDistance' : undeclared identifier"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_ANGLE_clip_cull_distance", kCS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_EXT_clip_cull_distance", kCS, kExpect); + } +} + +// In compute shader, reading gl_CullDistance should be denied. +TEST_P(GLSLValidationClipDistanceTest_ES31, ComputeReadCullDistance) +{ + constexpr char kCS[] = R"(layout(local_size_x = 1) in; +void main() { highp float c = gl_CullDistance[0]; })"; + constexpr char kExpect[] = "'gl_CullDistance' : undeclared identifier"; + + if (IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_ANGLE_clip_cull_distance", kCS, kExpect); + } + + if (IsGLExtensionEnabled("GL_EXT_clip_cull_distance")) + { + validateErrorWithExt(GL_COMPUTE_SHADER, "GL_EXT_clip_cull_distance", kCS, kExpect); + } +} + +class GLSLValidationTextureRectangleTest : public GLSLValidationTest +{}; + +// Check that if the extension is not supported, trying to use the features without having an +// extension directive fails. +// +// If the extension is supported, check that new types and builtins are usable even with the +// #extension directive +// Issue #15 of ARB_texture_rectangle explains that the extension was specified before the +// #extension mechanism was in place so it doesn't require explicit enabling. +TEST_P(GLSLValidationTextureRectangleTest, NewTypeAndBuiltinsWithoutExtensionDirective) +{ + constexpr char kFS[] = R"( +precision mediump float; +uniform sampler2DRect tex; +void main() +{ + vec4 color = texture2DRect(tex, vec2(1.0)); + color = texture2DRectProj(tex, vec3(1.0)); + color = texture2DRectProj(tex, vec4(1.0)); +})"; + if (IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")) + { + validateSuccess(GL_FRAGMENT_SHADER, kFS); + } + else + { + validateError(GL_FRAGMENT_SHADER, kFS, + "'GL_ARB_texture_rectangle' : extension is not supported"); + } +} + +// Check that if the extension is not supported, trying to use the features fails. +// +// If the extension is supported, test that using the feature with the extension directive passes. +TEST_P(GLSLValidationTextureRectangleTest, NewTypeAndBuiltinsWithExtensionDirective) +{ + constexpr char kFS[] = R"(#extension GL_ARB_texture_rectangle : enable +precision mediump float; +uniform sampler2DRect tex; +void main() +{ + vec4 color = texture2DRect(tex, vec2(1.0)); + color = texture2DRectProj(tex, vec3(1.0)); + color = texture2DRectProj(tex, vec4(1.0)); +})"; + if (IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")) + { + validateSuccess(GL_FRAGMENT_SHADER, kFS); + } + else + { + validateError(GL_FRAGMENT_SHADER, kFS, + "'GL_ARB_texture_rectangle' : extension is not supported"); + } +} + +// Check that it is not possible to pass a sampler2DRect where sampler2D is expected, and vice versa +TEST_P(GLSLValidationTextureRectangleTest, Rect2DVs2DMismatch) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")); + + { + constexpr char kFS[] = R"( +#extension GL_ARB_texture_rectangle : require +precision mediump float; +uniform sampler2DRect tex; +void main() { + vec4 color = texture2D(tex, vec2(1.0));" +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'texture2D' : no matching overloaded function found"); + } + + { + constexpr char kFS[] = R"( +#extension GL_ARB_texture_rectangle : require +precision mediump float; +uniform sampler2D tex; +void main() { + vec4 color = texture2DRect(tex, vec2(1.0));" +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'texture2DRect' : no matching overloaded function found"); + } +} + +// Disabling ARB_texture_rectangle in GLSL should work, even if it is enabled by default. +// See ARB_texture_rectangle spec: "a shader can still include all variations of #extension +// GL_ARB_texture_rectangle in its source code" +TEST_P(GLSLValidationTextureRectangleTest, DisableARBTextureRectangle) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")); + + constexpr char kFS[] = R"(#extension GL_ARB_texture_rectangle : disable +precision mediump float; + +uniform sampler2DRect s; +void main() +{})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'GL_ARB_texture_rectangle' : extension is disabled"); +} + +class GLSLValidationAtomicCounterTest_ES31 : public GLSLValidationTest_ES31 +{}; + +// Test that ESSL 3.00 doesn't support atomic_uint. +TEST_P(GLSLValidationAtomicCounterTest_ES31, InvalidShaderVersion) +{ + constexpr char kFS[] = R"(#version 300 es +layout(binding = 0, offset = 4) uniform atomic_uint a; +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'atomic_uint' : Illegal use of reserved word"); +} + +// Test that any qualifier other than uniform leads to compile-time error. +TEST_P(GLSLValidationAtomicCounterTest_ES31, InvalidQualifier) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 0, offset = 4) in atomic_uint a; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, "'atomic_uint' : atomic_uints must be uniform"); +} + +// Test that uniform must be specified for declaration. +TEST_P(GLSLValidationAtomicCounterTest_ES31, UniformMustSpecifiedForDeclaration) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +atomic_uint a; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, "'atomic_uint' : atomic_uints must be uniform"); +} + +// Test that offset overlapping leads to compile-time error (ESSL 3.10 section 4.4.6). +TEST_P(GLSLValidationAtomicCounterTest_ES31, BindingOffsetOverlapping) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 0, offset = 4) uniform atomic_uint a; +layout(binding = 0, offset = 6) uniform atomic_uint b; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, "'atomic counter' : Offset overlapping"); +} + +// Test offset inheritance for multiple variables in one same declaration. +TEST_P(GLSLValidationAtomicCounterTest_ES31, MultipleVariablesDeclaration) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 0, offset = 4) uniform atomic_uint a, b; +layout(binding = 0, offset = 8) uniform atomic_uint c; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, "'atomic counter' : Offset overlapping"); +} + +// Test that subsequent declarations inherit the globally specified offset. +TEST_P(GLSLValidationAtomicCounterTest_ES31, GlobalBindingOffsetOverlapping) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 2, offset = 4) uniform atomic_uint; +layout(binding = 2) uniform atomic_uint b; +layout(binding = 2, offset = 4) uniform atomic_uint c; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, "'atomic counter' : Offset overlapping"); +} + +// The spec only demands offset unique and non-overlapping. So this should be allowed. +TEST_P(GLSLValidationAtomicCounterTest_ES31, DeclarationSequenceWithDecrementalOffsetsSpecified) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 2, offset = 4) uniform atomic_uint a; +layout(binding = 2, offset = 0) uniform atomic_uint b; +void main() +{ +})"; + validateSuccess(GL_COMPUTE_SHADER, kCS); +} + +// Test that image format qualifiers are not allowed for atomic counters. +TEST_P(GLSLValidationAtomicCounterTest_ES31, ImageFormatMustNotSpecified) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 0, offset = 4, rgba32f) uniform atomic_uint a; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, + "'rgba32f' : invalid layout qualifier: only valid when used with images"); +} + +// Test that global layout qualifiers must not use 'offset'. +TEST_P(GLSLValidationAtomicCounterTest_ES31, OffsetMustNotSpecifiedForGlobalLayoutQualifier) +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(offset = 4) in; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, + "'offset' : invalid layout qualifier: only valid when used with atomic counters"); +} + +// Test that offset overlapping leads to compile-time error (ESSL 3.10 section 4.4.6). +// Note that there is some vagueness in the spec when it comes to this test. +TEST_P(GLSLValidationAtomicCounterTest_ES31, BindingOffsetOverlappingForArrays) +{ + GLint maxAtomicCounterBuffers = 0; + glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers); + ANGLE_SKIP_TEST_IF(maxAtomicCounterBuffers < 3); + + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=1) in; +layout(binding = 2, offset = 4) uniform atomic_uint[2] a; +layout(binding = 2, offset = 8) uniform atomic_uint b; +void main() +{ +})"; + validateError(GL_COMPUTE_SHADER, kCS, "'atomic counter' : Offset overlapping"); +} + +class GLSLValidationShaderStorageBlockTest_ES31 : public GLSLValidationTest_ES31 +{}; + +// Test that shader storage block layout qualifiers can be declared for global scope. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, LayoutQualifiersDeclaredInGlobal) +{ + constexpr char kFS[] = R"(#version 310 es +layout(shared, column_major) buffer; +void main() +{ +})"; + validateSuccess(GL_FRAGMENT_SHADER, kFS); +} + +// Test that it is a compile-time error to declare buffer variables at global scope (outside a +// block). +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, DeclareBufferVariableAtGlobal) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer int a; +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'buffer' : cannot declare buffer variables at global scope(outside a block)"); +} + +// Test that the buffer variable can't be opaque type. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, BufferVariableWithOpaqueType) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + int b1; + atomic_uint b2; +}; +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'buf' : Opaque types are not allowed in interface blocks"); +} + +// Test that the uniform variable can't be in shader storage block. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, UniformVariableInShaderStorageBlock) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + uniform int a; +}; +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'uniform' : invalid qualifier on shader storage block member"); +} + +// Test that buffer qualifier is not supported in version lower than GLSL ES 3.10. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, BufferQualifierInESSL3) +{ + constexpr char kFS[] = R"(#version 300 es +layout(binding = 3) buffer buf { + int b1; + buffer int b2; +}; +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'binding' : invalid layout qualifier: not supported"); +} + +// Test that can't assign to a readonly buffer variable. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AssignToReadonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + readonly int b1; +}; +void main() +{ + b1 = 5; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + R"('assign' : l-value required (can't modify a readonly variable "b1"))"); +} + +// Test that can't assign to a buffer variable declared within shader storage block with readonly. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AssignToBufferVariableWithinReadonlyBlock) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) readonly buffer buf { + int b1; +}; +void main() +{ + b1 = 5; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + R"('assign' : l-value required (can't modify a readonly variable "b1"))"); +} + +// Test that can't assign to a readonly buffer variable through an instance name. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AssignToReadonlyBufferVariableByInstanceName) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +layout(binding = 3) buffer buf { + readonly float f; +} instanceBuffer; +void main() +{ + instanceBuffer.f += 0.2; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'assign' : can't modify a readonly variable"); +} + +// Test that can't assign to a readonly struct buffer variable. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AssignToReadonlyStructBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +struct S { + float f; +}; +layout(binding = 3) buffer buf { + readonly S s; +}; +void main() +{ + s.f += 0.2; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + R"('assign' : l-value required (can't modify a readonly variable "s"))"); +} + +// Test that can't assign to a readonly struct buffer variable through an instance name. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, + AssignToReadonlyStructBufferVariableByInstanceName) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +struct S { + float f; +}; +layout(binding = 3) buffer buf { + readonly S s; +} instanceBuffer; +void main() +{ + instanceBuffer.s.f += 0.2; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'assign' : can't modify a readonly variable"); +} + +// Test that a readonly and writeonly buffer variable should neither read or write. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AccessReadonlyWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + readonly writeonly int b1; +}; +void main() +{ + b1 = 5; + int test = b1; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + R"('assign' : l-value required (can't modify a readonly variable "b1"))"); +} + +// Test that accessing a writeonly buffer variable should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AccessWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + writeonly int b1; +}; +void main() +{ + int test = b1; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'=' : Invalid operation for variables with writeonly"); +} + +// Test that accessing a buffer variable through an instance name inherits the writeonly qualifier +// and generates errors. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, AccessWriteonlyBufferVariableByInstanceName) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +layout(binding = 3) writeonly buffer buf { + float f; +} instanceBuffer; +void main() +{ + float test = instanceBuffer.f; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'=' : Invalid operation for variables with writeonly"); +} + +// Test that writeonly buffer variable as the argument of a unary operator should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, UnaryOperatorWithWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + writeonly int b1; +}; +void main() +{ + ++b1; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'++' : wrong operand type - no operation '++' exists that takes an operand of " + "type buffer mediump writeonly int (or there is no acceptable conversion)"); +} + +// Test that writeonly buffer variable on the left-hand side of compound assignment should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, CompoundAssignmentToWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + writeonly int b1; +}; +void main() +{ + b1 += 5; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'+=' : Invalid operation for variables with writeonly"); +} + +// Test that writeonly buffer variable as ternary op argument should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, TernarySelectionWithWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + writeonly bool b1; +}; +void main() +{ + int test = b1 ? 1 : 0; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'?:' : ternary operator is not allowed for variables with writeonly"); +} + +// Test that writeonly buffer variable as array constructor argument should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, ArrayConstructorWithWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +layout(binding = 3) buffer buf { + writeonly float f; +}; +void main() +{ + float a[3] = float[3](f, f, f); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : cannot convert a variable with writeonly"); +} + +// Test that writeonly buffer variable as structure constructor argument should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, StructureConstructorWithWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +struct S { + int a; +}; +struct T { + S b; +}; +layout(binding = 3) buffer buf { + writeonly S c; +}; +void main() +{ + T t = T(c); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'constructor' : cannot convert a variable with writeonly"); +} + +// Test that writeonly buffer variable as built-in function argument should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, BuiltInFunctionWithWriteonlyBufferVariable) +{ + constexpr char kFS[] = R"(#version 310 es +layout(binding = 3) buffer buf { + writeonly int a; +}; +void main() +{ + int test = min(a, 1); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'min' : Writeonly value cannot be passed for 'in' or 'inout' parameters"); +} + +// Test that writeonly buffer variable as user-defined function in argument should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, + UserDefinedFunctionWithWriteonlyBufferVariableInArgument) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +layout(binding = 3) buffer buf { + writeonly float f; +}; +void foo(float a) {} +void main() +{ + foo(f); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "foo' : Writeonly value cannot be passed for 'in' or 'inout' parameters"); +} + +// Test that readonly buffer variable as user-defined function out argument should be error. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, + UserDefinedFunctionWithReadonlyBufferVariableOutArgument) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +layout(binding = 3) buffer buf { + readonly float f; +}; +void foo(out float a) {} +void main() +{ + foo(f); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + R"('assign' : l-value required (can't modify a readonly variable "f"))"); +} + +// Test that buffer qualifier can't modify a function parameter. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, BufferQualifierOnFunctionParameter) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +void foo(buffer float a) {} +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'buffer' : only allowed at global scope"); +} + +// Test that using std430 qualifier on a uniform block will fail to compile. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, UniformBlockWithStd430) +{ + constexpr char kFS[] = R"(#version 310 es +layout(std430) uniform buf { + int b1; + int b2; +}; +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'std430' : The std430 layout is supported only for shader storage blocks"); +} + +// Test that indexing a runtime-sized array with a negative constant index does not compile. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, IndexRuntimeSizedArrayWithNegativeIndex) +{ + constexpr char kFS[] = R"(#version 310 es +layout(std430) buffer buf +{ + int arr[]; +}; + +void main() +{ + arr[-1]; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'[]' : index expression is negative"); +} + +// Test that only the last member of a buffer can be runtime-sized. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, RuntimeSizedVariableInNotLastInBuffer) +{ + constexpr char kFS[] = R"(#version 310 es +layout(std430) buffer buf +{ + int arr[]; + int i; +}; + +void main() +{ +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'arr' : array members of interface blocks must specify a size"); +} + +// Test that memory qualifiers are output. +TEST_P(GLSLValidationShaderStorageBlockTest_ES31, MemoryQualifiers) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +precision highp int; +layout(std430) coherent buffer buf +{ + int defaultCoherent; + coherent ivec2 specifiedCoherent; + volatile ivec3 specifiedVolatile; + restrict ivec4 specifiedRestrict; + readonly float specifiedReadOnly; + writeonly vec2 specifiedWriteOnly; + volatile readonly vec3 specifiedMultiple; +}; + +void main() +{ +})"; + const CompiledShader &shader = compile(GL_FRAGMENT_SHADER, kFS); + EXPECT_TRUE(shader.success()); + if (IsOpenGLES()) + { + // The following are GLSL qualifiers, so only valid with GLSL translation. + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent highp int")); + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent highp ivec2")); + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent volatile highp ivec3")); + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent restrict highp ivec4")); + EXPECT_TRUE(shader.verifyInTranslatedSource("readonly coherent highp float")); + EXPECT_TRUE(shader.verifyInTranslatedSource("writeonly coherent highp vec2")); + EXPECT_TRUE(shader.verifyInTranslatedSource("readonly coherent volatile highp vec3")); + } + else if (IsOpenGL()) + { + // The following are GLSL qualifiers, so only valid with GLSL translation. + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent int")); + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent ivec2")); + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent volatile ivec3")); + EXPECT_TRUE(shader.verifyInTranslatedSource("coherent restrict ivec4")); + EXPECT_TRUE(shader.verifyInTranslatedSource("readonly coherent float")); + EXPECT_TRUE(shader.verifyInTranslatedSource("writeonly coherent vec2")); + EXPECT_TRUE(shader.verifyInTranslatedSource("readonly coherent volatile vec3")); + } + reset(); +} + +class GLSLValidationBaseVertexTest_ES3 : public GLSLValidationTest_ES3 +{}; + +class WebGL2GLSLValidationBaseVertexTest : public WebGL2GLSLValidationTest +{}; + +// Check that base vertex/instance is not exposed to WebGL. +TEST_P(WebGL2GLSLValidationBaseVertexTest, NoSupport) +{ + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require +void main() { + gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0); +})"; + validateError( + GL_VERTEX_SHADER, kVS, + "'GL_ANGLE_base_vertex_base_instance_shader_builtin' : extension is not supported"); +} + +// Check that compiling with the old extension doesn't work +TEST_P(GLSLValidationBaseVertexTest_ES3, CheckCompileOldExtension) +{ + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance : require +void main() { + gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, + "'GL_ANGLE_base_vertex_base_instance' : extension is not supported"); +} + +// Check that a user-defined "gl_BaseVertex" or "gl_BaseInstance" is not permitted +TEST_P(GLSLValidationBaseVertexTest_ES3, DisallowsUserDefinedGLDrawID) +{ + { + // Check that it is not permitted without the + // GL_ANGLE_base_vertex_base_instance_shader_builtin extension + constexpr char kVS[] = R"(#version 300 es +uniform int gl_BaseVertex; +void main() { + gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#version 300 es +uniform int gl_BaseInstance; +void main() { + gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#version 300 es +void main() { + int gl_BaseVertex = 0; + gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#version 300 es +void main() { + int gl_BaseInstance = 0; + gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + // Check that it is not permitted with the extension + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require +uniform int gl_BaseVertex; +void main() { + gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require +uniform int gl_BaseInstance; +void main() { + gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require +void main() { + int gl_BaseVertex = 0; + gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#version 300 es +#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require +void main() { + int gl_BaseInstance = 0; + gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } +} + +class GLSLValidationDrawIDTest : public GLSLValidationTest +{}; + +// Check that a user-defined "gl_DrawID" is not permitted +TEST_P(GLSLValidationDrawIDTest, DisallowsUserDefinedGLDrawID) +{ + { + // Check that it is not permitted without the GL_ANGLE_multi_draw extension + constexpr char kVS[] = R"(uniform int gl_DrawID; +void main() { + gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(void main() { + int gl_DrawID = 0; + gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + // Check that it is not permitted with the extension + constexpr char kVS[] = R"(#extension GL_ANGLE_multi_draw : require +uniform int gl_DrawID; +void main() { + gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } + + { + constexpr char kVS[] = R"(#extension GL_ANGLE_multi_draw : require +void main() { + int gl_DrawID = 0; + gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0); +})"; + validateError(GL_VERTEX_SHADER, kVS, "'gl_' : reserved built-in name"); + } +} + +class GLSLValidationExtensionDirectiveTest_ES3 : public GLSLValidationTest_ES3 +{ + public: + void testCompileNeedsExtensionDirective(GLenum shaderType, + const char *shaderSource, + const char *version, + const char *extension, + bool isExtensionSupported, + const char *expectWithoutPragma, + const char *expectWithExtDisabled) + { + testCompileNeedsExtensionDirectiveImpl(shaderType, shaderSource, version, extension, + isExtensionSupported, true, expectWithoutPragma, + expectWithExtDisabled); + } + + void testCompileNeedsExtensionDirectiveGenericKeyword(GLenum shaderType, + const char *shaderSource, + const char *version, + const char *extension, + bool isExtensionSupported, + const char *expect) + { + testCompileNeedsExtensionDirectiveImpl(shaderType, shaderSource, version, extension, + isExtensionSupported, false, expect, expect); + } + + void testCompileNeedsExtensionDirectiveImpl(GLenum shaderType, + const char *shaderSource, + const char *version, + const char *extension, + bool isExtensionSupported, + bool willWarnOnUse, + const char *expectWithoutPragma, + const char *expectWithExtDisabled) + { + { + std::stringstream src; + if (version) + { + src << version << "\n"; + } + src << shaderSource; + const CompiledShader &shader = compile(shaderType, src.str().c_str()); + EXPECT_FALSE(shader.success()); + EXPECT_TRUE(shader.hasInfoLog(expectWithoutPragma)); + reset(); + } + + { + std::stringstream src; + if (version) + { + src << version << "\n"; + } + src << "#extension " << extension << ": disable\n" << shaderSource; + const CompiledShader &shader = compile(shaderType, src.str().c_str()); + EXPECT_FALSE(shader.success()); + EXPECT_TRUE(shader.hasInfoLog(expectWithExtDisabled)); + reset(); + } + + { + std::stringstream src; + if (version) + { + src << version << "\n"; + } + src << "#extension " << extension << ": enable\n" << shaderSource; + if (isExtensionSupported) + { + EXPECT_TRUE(compile(shaderType, src.str().c_str()).success()); + } + else + { + const CompiledShader &shader = compile(shaderType, src.str().c_str()); + EXPECT_FALSE(shader.success()); + EXPECT_TRUE(shader.hasInfoLog("extension is not supported")); + } + reset(); + } + + // The Nvidia/GLES driver doesn't treat warn like enable and gives an error, declaring that + // using a token from the extension needs `#extension EXT: enable`. Don't run these tests + // on that config. + const bool driverMishandlesWarn = IsOpenGLES() && IsNVIDIA(); + + if (!driverMishandlesWarn) + { + std::stringstream src; + if (version) + { + src << version << "\n"; + } + src << "#extension " << extension << ": warn\n" << shaderSource; + const CompiledShader &shader = compile(shaderType, src.str().c_str()); + if (!isExtensionSupported) + { + EXPECT_FALSE(shader.success()); + EXPECT_TRUE(shader.hasInfoLog("extension is not supported")); + } + else + { + EXPECT_TRUE(shader.success()); + if (willWarnOnUse) + { + EXPECT_TRUE(shader.hasInfoLog("WARNING")); + EXPECT_TRUE(shader.hasInfoLog("extension is being used")); + } + } + reset(); + } + } +}; + +class GLSLValidationExtensionDirectiveTest_ES31 : public GLSLValidationExtensionDirectiveTest_ES3 +{}; + +// OES_EGL_image_external needs to be enabled in GLSL to be able to use samplerExternalOES. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SamplerExternalOESWithImage) +{ + const bool hasExt = IsGLExtensionEnabled("GL_OES_EGL_image_external"); + const bool hasAnyExt = hasExt || IsGLExtensionEnabled("GL_NV_EGL_stream_consumer_external"); + + constexpr char kFS[] = R"(precision mediump float; +uniform samplerExternalOES s; +void main() +{})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_OES_EGL_image_external", hasExt, + hasAnyExt ? "extension is disabled" : "extension is not supported", + hasAnyExt ? "extension is disabled" : "extension is not supported"); +} + +// NV_EGL_stream_consumer_external needs to be enabled in GLSL to be able to use samplerExternalOES. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SamplerExternalOESWithStreamConstumer) +{ + const bool hasExt = IsGLExtensionEnabled("GL_NV_EGL_stream_consumer_external"); + const bool hasAnyExt = hasExt || IsGLExtensionEnabled("GL_OES_EGL_image_external"); + + constexpr char kFS[] = R"(precision mediump float; +uniform samplerExternalOES s; +void main() +{})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_NV_EGL_stream_consumer_external", hasExt, + hasAnyExt ? "extension is disabled" : "extension is not supported", + hasAnyExt ? "extension is disabled" : "extension is not supported"); +} + +// GL_EXT_YUV_target needs to be enabled in GLSL to be able to use samplerExternal2DY2YEXT. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SamplerExternal2DY2YEXT) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_YUV_target"); + + constexpr char kFS[] = R"(precision mediump float; +uniform __samplerExternal2DY2YEXT s; +void main() +{})"; + // __samplerExternal2DY2YEXT is not a reserved keyword, and the translator fails with syntax + // error if extension is not specified. + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_EXT_YUV_target", hasExt, + "'s' : syntax error", hasExt ? "'s' : syntax error" : "extension is not supported"); +} + +// GL_WEBGL_video_texture needs to be enabled in GLSL to be able to use samplerVideoWEBGL. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SamplerVideoWEBGL_ESSL100) +{ + const bool hasExt = IsGLExtensionEnabled("GL_WEBGL_video_texture"); + + constexpr char kFS[] = R"(precision mediump float; +uniform mediump samplerVideoWEBGL s; +void main() { + gl_FragColor = textureVideoWEBGL(s, vec2(0.0, 0.0)); +})"; + // samplerVideoWEBGL is not a reserved keyword, and the translator fails with syntax + // error if extension is not specified. + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_WEBGL_video_texture", hasExt, "'s' : syntax error", + hasExt ? "'s' : syntax error" : "extension is not supported"); +} + +// GL_WEBGL_video_texture needs to be enabled in GLSL to be able to use samplerVideoWEBGL. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SamplerVideoWEBGL_ESSL300) +{ + const bool hasExt = IsGLExtensionEnabled("GL_WEBGL_video_texture"); + + constexpr char kFS[] = R"(precision mediump float; +uniform mediump samplerVideoWEBGL s; +out vec4 my_FragColor; +void main() { + my_FragColor = texture(s, vec2(0.0, 0.0)); +})"; + // samplerVideoWEBGL is not a reserved keyword, and the translator fails with syntax + // error if extension is not specified. + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_WEBGL_video_texture", hasExt, + "'s' : syntax error", hasExt ? "'s' : syntax error" : "extension is not supported"); +} + +// GL_EXT_YUV_target needs to be enabled in GLSL to be able to use layout(yuv). +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, YUVLayoutNeedsExtensionDirective) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_YUV_target"); + + constexpr char kFS[] = R"(precision mediump float; +layout(yuv) out vec4 color; +void main() +{})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_EXT_YUV_target", hasExt, + hasExt ? "extension is disabled" : "extension is not supported", + hasExt ? "extension is disabled" : "extension is not supported"); +} + +// GL_EXT_blend_func_extended needs to be enabled in GLSL to be able to use +// gl_MaxDualSourceDrawBuffersEXT. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, MaxDualSourceDrawBuffersNeedsExtensionDirective) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_blend_func_extended"); + + { + constexpr char kFS[] = R"(precision mediump float; +void main() { + gl_FragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_EXT_blend_func_extended", hasExt, + hasExt ? "extension is disabled" + : "'gl_MaxDualSourceDrawBuffersEXT' : undeclared identifier", + hasExt ? "extension is disabled" + : "'gl_MaxDualSourceDrawBuffersEXT' : undeclared identifier"); + } + + { + constexpr char kFS[] = R"(precision mediump float; +layout(location = 0) out mediump vec4 fragColor; +void main() { + fragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_EXT_blend_func_extended", hasExt, + hasExt ? "extension is disabled" + : "'gl_MaxDualSourceDrawBuffersEXT' : undeclared identifier", + hasExt ? "extension is disabled" + : "'gl_MaxDualSourceDrawBuffersEXT' : undeclared identifier"); + } +} + +// GL_EXT_clip_cull_distance or GL_ANGLE_clip_cull_distance needs to be enabled in GLSL to be able +// to use gl_ClipDistance and gl_CullDistance. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, ClipCullDistanceNeedsExtensionDirective) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_clip_cull_distance"); + const bool hasAngle = IsGLExtensionEnabled("GL_ANGLE_clip_cull_distance"); + + GLint maxClipDistances = 0; + GLint maxCullDistances = 0; + if (hasExt || hasAngle) + { + glGetIntegerv(GL_MAX_CLIP_DISTANCES_EXT, &maxClipDistances); + EXPECT_GE(maxClipDistances, 8); + + glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances); + EXPECT_TRUE(maxCullDistances == 0 || maxCullDistances >= 8); + if (hasExt) + { + EXPECT_GE(maxCullDistances, 8); + } + } + + constexpr char kVS1[] = R"(uniform vec4 uPlane; +in vec4 aPosition; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[0] = dot(aPosition, uPlane); + gl_CullDistance[0] = dot(aPosition, uPlane); +})"; + + constexpr char kVS2[] = R"(uniform vec4 uPlane; +in vec4 aPosition; + +out highp float gl_ClipDistance[4]; +out highp float gl_CullDistance[4]; + +void main() +{ + gl_Position = aPosition; + gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane); + gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane); + gl_ClipDistance[gl_MaxCombinedClipAndCullDistances / 4 - 1] = dot(aPosition, uPlane); + gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane); + gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane); +})"; + + // Shader using gl_ClipDistance and gl_CullDistance + constexpr char kFS1[] = R"(out highp vec4 fragColor; +void main() +{ + fragColor = vec4(gl_ClipDistance[0], gl_CullDistance[0], 0, 1); +})"; + + // Shader redeclares gl_ClipDistance and gl_CullDistance + constexpr char kFS2[] = R"(in highp float gl_ClipDistance[4]; +in highp float gl_CullDistance[4]; +in highp vec4 aPosition; + +out highp vec4 fragColor; + +void main() +{ + fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1]; + fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)]; + fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1]; + fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)]; + fragColor *= gl_CullDistance[gl_MaxCombinedClipAndCullDistances / 4 - 1]; +})"; + + if (hasExt) + { + const char *expectWithoutPragma = + hasExt ? "extension is disabled" : "extension is not supported"; + const char *expectWithExtDisabled = + hasExt ? "extension is disabled" : "extension is not supported"; + + testCompileNeedsExtensionDirective(GL_VERTEX_SHADER, kVS1, "#version 300 es", + "GL_EXT_clip_cull_distance", hasExt, expectWithoutPragma, + expectWithExtDisabled); + testCompileNeedsExtensionDirective(GL_VERTEX_SHADER, kVS2, "#version 300 es", + "GL_EXT_clip_cull_distance", hasExt, expectWithoutPragma, + expectWithExtDisabled); + testCompileNeedsExtensionDirective(GL_FRAGMENT_SHADER, kFS1, "#version 300 es", + "GL_EXT_clip_cull_distance", hasExt, expectWithoutPragma, + expectWithExtDisabled); + testCompileNeedsExtensionDirective(GL_FRAGMENT_SHADER, kFS2, "#version 300 es", + "GL_EXT_clip_cull_distance", hasExt, expectWithoutPragma, + expectWithExtDisabled); + } + + if (hasAngle && maxCullDistances > 0) + { + const char *expectWithoutPragma = + hasAngle ? "extension is disabled" : "extension is not supported"; + const char *expectWithExtDisabled = + hasAngle ? "extension is disabled" : "extension is not supported"; + + testCompileNeedsExtensionDirective(GL_VERTEX_SHADER, kVS1, "#version 300 es", + "GL_ANGLE_clip_cull_distance", hasAngle, + expectWithoutPragma, expectWithExtDisabled); + testCompileNeedsExtensionDirective(GL_VERTEX_SHADER, kVS2, "#version 300 es", + "GL_ANGLE_clip_cull_distance", hasAngle, + expectWithoutPragma, expectWithExtDisabled); + testCompileNeedsExtensionDirective(GL_FRAGMENT_SHADER, kFS1, "#version 300 es", + "GL_ANGLE_clip_cull_distance", hasAngle, + expectWithoutPragma, expectWithExtDisabled); + testCompileNeedsExtensionDirective(GL_FRAGMENT_SHADER, kFS2, "#version 300 es", + "GL_ANGLE_clip_cull_distance", hasAngle, + expectWithoutPragma, expectWithExtDisabled); + } +} + +// GL_EXT_frag_depth needs to be enabled in GLSL 100 to be able to use gl_FragDepthEXT. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, FragDepth) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_frag_depth"); + + constexpr char kFS[] = R"(precision mediump float; +void main() +{ + gl_FragDepthEXT = 1.0; +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_EXT_frag_depth", hasExt, + hasExt ? "extension is disabled" : "'gl_FragDepthEXT' : undeclared identifier", + hasExt ? "extension is disabled" : "extension is not supported"); +} + +// The GLES SL 3.0 built-in variable gl_FragDepth fails to compile with GLES SL 1.0. +TEST_P(GLSLValidationTest, FragDepthFailsESSL100) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() { + gl_FragDepth = 1.0; +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "'gl_FragDepth' : undeclared identifier"); + + // Even with GL_EXT_frag_depth extension enabled, gl_FragDepth (ES3 built-in) should fail in + // ESSL 100. Note: The extension provides gl_FragDepthEXT, not gl_FragDepth. + if (IsGLExtensionEnabled("GL_EXT_frag_depth")) + { + constexpr char kFSWithExt[] = R"(#extension GL_EXT_frag_depth : enable +precision mediump float; +void main() { + gl_FragDepth = 1.0; +})"; + validateError(GL_FRAGMENT_SHADER, kFSWithExt, "'gl_FragDepth' : undeclared identifier"); + } +} + +// Using #extension GL_EXT_frag_depth in GLSL ES 3.0 shader fails to compile. +TEST_P(GLSLValidationTest_ES3, FragDepthExtensionFailsESSL300) +{ + constexpr char kFS[] = R"(#version 300 es +#extension GL_EXT_frag_depth : require +precision mediump float; +out vec4 fragColor; +void main() { + fragColor = vec4(1.0); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, "extension is not supported"); +} + +// GL_EXT_shader_framebuffer_fetch or GL_EXT_shader_framebuffer_fetch_non_coherent needs to be +// enabled in GLSL 100 to be able to use gl_LastFragData and in GLSL 300+ to use inout. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, LastFragData) +{ + const bool hasCoherent = IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"); + const bool hasNonCoherent = + IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"); + + constexpr char kFS100Coherent[] = R"( +uniform highp vec4 u_color; +highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; + +void main (void) +{ + gl_FragColor = u_color + gl_LastFragData[0] + gl_LastFragData[2]; +})"; + + constexpr char kFS300Coherent[] = R"( +inout highp vec4 o_color; +uniform highp vec4 u_color; + +void main (void) +{ + o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f)); +})"; + + constexpr char kFS100NonCoherent[] = R"( +uniform highp vec4 u_color; +layout(noncoherent) highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; + +void main (void) +{ + gl_FragColor = u_color + gl_LastFragData[0] + gl_LastFragData[2]; +})"; + + constexpr char kFS300NonCoherent[] = R"( +layout(noncoherent, location = 0) inout highp vec4 o_color; +uniform highp vec4 u_color; + +void main (void) +{ + o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f)); +})"; + + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS100Coherent, nullptr, "GL_EXT_shader_framebuffer_fetch", hasCoherent, + hasCoherent ? hasNonCoherent ? "extension is disabled" : "extension is not supported" + : "'gl_' : reserved built-in name", + hasCoherent ? hasNonCoherent ? "extension is disabled" : "extension is not supported" + : "extension is not supported"); + testCompileNeedsExtensionDirectiveGenericKeyword( + GL_FRAGMENT_SHADER, kFS300Coherent, "#version 300 es", "GL_EXT_shader_framebuffer_fetch", + hasCoherent, "'inout' : invalid qualifier"); + + testCompileNeedsExtensionDirectiveGenericKeyword(GL_FRAGMENT_SHADER, kFS100NonCoherent, nullptr, + "GL_EXT_shader_framebuffer_fetch_non_coherent", + hasNonCoherent, "'layout' : syntax error"); + testCompileNeedsExtensionDirectiveGenericKeyword(GL_FRAGMENT_SHADER, kFS300NonCoherent, + "#version 300 es", + "GL_EXT_shader_framebuffer_fetch_non_coherent", + hasNonCoherent, "'inout' : invalid qualifier"); +} + +// GL_EXT_shader_texture_lod needs to be enabled to be able to use texture2DLodEXT. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, Texture2DLod) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_shader_texture_lod"); + + constexpr char kFS[] = R"(precision mediump float; +varying vec2 texCoord0v; +uniform float lod; +uniform sampler2D tex; +void main() +{ + vec4 color = texture2DLodEXT(tex, texCoord0v, lod); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_EXT_shader_texture_lod", hasExt, + hasExt ? "extension is disabled" + : "'texture2DLodEXT' : no matching overloaded function found", + hasExt ? "extension is disabled" : "extension is not supported"); +} + +// GL_EXT_shadow_samplers needs to be enabled to be able to use shadow2DEXT. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, Sampler2DShadow) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_shadow_samplers"); + + constexpr char kFS[] = R"(precision mediump float; +varying vec3 texCoord0v; +uniform mediump sampler2DShadow tex; +void main() +{ + float color = shadow2DEXT(tex, texCoord0v); +})"; + testCompileNeedsExtensionDirective(GL_FRAGMENT_SHADER, kFS, nullptr, "GL_EXT_shadow_samplers", + hasExt, "'sampler2DShadow' : Illegal use of reserved word", + "'sampler2DShadow' : Illegal use of reserved word"); +} + +// GL_KHR_blend_equation_advanced needs to be enabled to be able to use layout(blend_support_*). +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, AdvancedBlendSupport) +{ + const bool hasExt = IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"); + const bool hasAnyExt = + hasExt || IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent"); + + constexpr char kFS[] = R"(precision highp float; +layout (blend_support_multiply) out; +layout (location = 0) out vec4 oCol; + +uniform vec4 uSrcCol; + +void main (void) +{ + oCol = uSrcCol; +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_KHR_blend_equation_advanced", hasExt, + hasAnyExt ? "extension is disabled" : "extension is not supported", + hasAnyExt ? "extension is disabled" : "extension is not supported"); +} + +// GL_OES_sample_variables needs to be enabled to be able to use gl_SampleMask. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SampleMask) +{ + const bool hasExt = IsGLExtensionEnabled("GL_OES_sample_variables"); + + // This shader is in the deqp test + // functional_shaders_sample_variables_sample_mask_discard_half_per_sample_default_framebuffer + constexpr char kFS[] = R"(layout(location = 0) out mediump vec4 fragColor; +void main (void) +{ + for (int i = 0; i < gl_SampleMask.length(); ++i) + gl_SampleMask[i] = int(0xAAAAAAAA); + + // force per-sample shading + highp float blue = float(gl_SampleID); + + fragColor = vec4(0.0, 1.0, blue, 1.0); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_OES_sample_variables", hasExt, + hasExt ? "extension is disabled" : "'gl_SampleMask' : undeclared identifier", + hasExt ? "extension is disabled" : "extension is not supported"); +} + +// GL_OES_sample_variables needs to be enabled to be able to use gl_SampleMaskIn. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, SampleMaskIn) +{ + const bool hasExt = IsGLExtensionEnabled("GL_OES_sample_variables"); + + // This shader is in the deqp test + // functional_shaders_sample_variables_sample_mask_in_bit_count_per_sample_multisample_texture_2 + constexpr char kFS[] = R"(layout(location = 0) out mediump vec4 fragColor; +void main (void) +{ + mediump int maskBitCount = 0; + for (int j = 0; j < gl_SampleMaskIn.length(); ++j) + { + for (int i = 0; i < 32; ++i) + { + if (((gl_SampleMaskIn[j] >> i) & 0x01) == 0x01) + { + ++maskBitCount; + } + } + } + + // force per-sample shading + highp float blue = float(gl_SampleID); + + if (maskBitCount != 1) + fragColor = vec4(1.0, 0.0, blue, 1.0); + else + fragColor = vec4(0.0, 1.0, blue, 1.0); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 300 es", "GL_OES_sample_variables", hasExt, + hasExt ? "extension is disabled" : "'gl_SampleMaskIn' : undeclared identifier", + hasExt ? "extension is disabled" : "extension is not supported"); +} + +// GL_OES_standard_derivatives needs to be enabled to be able to use dFdx, dFdy and fwidth. +TEST_P(GLSLValidationExtensionDirectiveTest_ES3, StandardDerivatives) +{ + const bool hasExt = IsGLExtensionEnabled("GL_OES_standard_derivatives"); + + { + constexpr char kFS[] = R"(precision mediump float; +varying float x; + +void main() +{ + gl_FragColor = vec4(dFdx(x)); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_OES_standard_derivatives", hasExt, + hasExt ? "extension is disabled" : "extension is not supported", + hasExt ? "extension is disabled" : "extension is not supported"); + } + + { + constexpr char kFS[] = R"(precision mediump float; +varying float x; + +void main() +{ + gl_FragColor = vec4(dFdy(x)); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_OES_standard_derivatives", hasExt, + hasExt ? "extension is disabled" : "extension is not supported", + hasExt ? "extension is disabled" : "extension is not supported"); + } + + { + constexpr char kFS[] = R"(precision mediump float; +varying float x; + +void main() +{ + gl_FragColor = vec4(fwidth(x)); +})"; + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, nullptr, "GL_OES_standard_derivatives", hasExt, + hasExt ? "extension is disabled" : "extension is not supported", + hasExt ? "extension is disabled" : "extension is not supported"); + } +} + +// GL_OES_texture_cube_map_array or GL_EXT_texture_cube_map_array needs to be enabled to be able to +// use *samplerCubeArray. +TEST_P(GLSLValidationExtensionDirectiveTest_ES31, TextureCubeMapArray) +{ + const bool hasExt = IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"); + const bool hasOes = IsGLExtensionEnabled("GL_OES_texture_cube_map_array"); + const bool hasAnyExt = hasExt || hasOes; + + { + constexpr char kFS[] = R"(precision mediump float; +uniform highp isamplerCubeArray u_sampler; +void main() +{ + vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); +})"; + + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 310 es", "GL_EXT_texture_cube_map_array", hasExt, + "'isamplerCubeArray' : Illegal use of reserved word", + hasAnyExt ? "'isamplerCubeArray' : Illegal use of reserved word" + : "extension is not supported"); + testCompileNeedsExtensionDirective( + GL_FRAGMENT_SHADER, kFS, "#version 310 es", "GL_OES_texture_cube_map_array", hasOes, + "'isamplerCubeArray' : Illegal use of reserved word", + hasAnyExt ? "'isamplerCubeArray' : Illegal use of reserved word" + : "extension is not supported"); + } + + // Make sure support for EXT or OES doesn't imply support for the other. + if (hasExt && !hasOes) + { + constexpr char kFS[] = R"(#version 310 es +#extension GL_OES_texture_cube_map_array: enable +precision mediump float; +uniform highp isamplerCubeArray u_sampler; +void main() +{ + vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'isamplerCubeArray' : Illegal use of reserved word"); + } + if (!hasExt && hasOes) + { + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_texture_cube_map_array: enable +precision mediump float; +uniform highp isamplerCubeArray u_sampler; +void main() +{ + vec4 color = vec4(texture(u_sampler, vec4(0, 0, 0, 0))); +})"; + validateError(GL_FRAGMENT_SHADER, kFS, + "'isamplerCubeArray' : Illegal use of reserved word"); + } +} + +} // namespace + +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLValidationTest); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLValidationTestNoValidation); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationTest_ES3); +ANGLE_INSTANTIATE_TEST_ES3(GLSLValidationTest_ES3); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationTest_ES31); +ANGLE_INSTANTIATE_TEST_ES31(GLSLValidationTest_ES31); + +ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLValidationTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLValidationTest); +ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLValidationTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationClipDistanceTest_ES3); +ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLValidationClipDistanceTest_ES3, + ES3_VULKAN().disable(Feature::SupportsAppleClipDistance)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationClipDistanceTest_ES31); +ANGLE_INSTANTIATE_TEST_ES31(GLSLValidationClipDistanceTest_ES31); + +ANGLE_INSTANTIATE_TEST_ES2(GLSLValidationTextureRectangleTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationAtomicCounterTest_ES31); +ANGLE_INSTANTIATE_TEST_ES31(GLSLValidationAtomicCounterTest_ES31); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationShaderStorageBlockTest_ES31); +ANGLE_INSTANTIATE_TEST_ES31(GLSLValidationShaderStorageBlockTest_ES31); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationBaseVertexTest_ES3); +ANGLE_INSTANTIATE_TEST( + GLSLValidationBaseVertexTest_ES3, + ES3_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLValidationBaseVertexTest); +ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLValidationBaseVertexTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationDrawIDTest); +ANGLE_INSTANTIATE_TEST( + GLSLValidationDrawIDTest, + ES3_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), + ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationExtensionDirectiveTest_ES3); +ANGLE_INSTANTIATE_TEST_ES3(GLSLValidationExtensionDirectiveTest_ES3); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLValidationExtensionDirectiveTest_ES31); +ANGLE_INSTANTIATE_TEST_ES31(GLSLValidationExtensionDirectiveTest_ES31); diff --git a/src/tests/gl_tests/GeometryShaderTest.cpp b/src/tests/gl_tests/GeometryShaderTest.cpp index 285833e424e..a30cd607ab7 100644 --- a/src/tests/gl_tests/GeometryShaderTest.cpp +++ b/src/tests/gl_tests/GeometryShaderTest.cpp @@ -6,6 +6,10 @@ // GeometryShaderTest.cpp : Tests of the implementation of geometry shader +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -108,7 +112,11 @@ class GeometryShaderTestES32 : public GeometryShaderTest // ES 3.1 is required. TEST_P(GeometryShaderTestES3, CreateGeometryShaderInES3) { - EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + // Only run the test against OpenGL ES 3.0. + ANGLE_SKIP_TEST_IF(getClientMajorVersion() == 3 && getClientMinorVersion() > 0); + // GL_EXT_geometry_shader requires OpenGL ES 3.1. + ASSERT_FALSE(IsGLExtensionEnabled("GL_EXT_geometry_shader")); + GLuint geometryShader = glCreateShader(GL_GEOMETRY_SHADER_EXT); EXPECT_EQ(0u, geometryShader); EXPECT_GL_ERROR(GL_INVALID_ENUM); @@ -197,6 +205,294 @@ TEST_P(GeometryShaderTestES32, CreateAndAttachGeometryShader) testCreateAndAttachGeometryShader(APIExtensionVersion::Core); } +// Basic functionality test. +TEST_P(GeometryShaderTest, Basic) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + constexpr char kVS[] = R"(#version 310 es +precision highp float; +layout(location = 0) in highp vec4 position; +void main() +{ + gl_Position = position; +})"; + + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +uniform vec4 u_color; +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +out vec4 gs_out; +void main() +{ + gl_Position = gl_in[0].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[2].gl_Position; + gs_out = u_color; + EmitVertex(); +})"; + + constexpr char kFS[] = R"(#version 310 es +precision highp float; +in vec4 gs_out; +layout(location = 0) out vec4 oColor; +void main() +{ + oColor = gs_out; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + glUniform4f(glGetUniformLocation(program, "u_color"), 0, 1, 0, 1); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + +// Test that redeclaring gl_in works. +TEST_P(GeometryShaderTest, RedeclareGlIn) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +precision highp float; +layout(location = 0) in highp vec4 position; +out gl_PerVertex +{ + highp vec4 gl_Position; +}; +void main() +{ + gl_Position = position; +})"; + + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +uniform vec4 u_color; +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +in gl_PerVertex +{ + highp vec4 gl_Position; +} gl_in[]; +out vec4 gs_out; +void main() +{ + gl_Position = gl_in[0].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[2].gl_Position; + gs_out = u_color; + EmitVertex(); +})"; + + constexpr char kFS[] = R"(#version 310 es +precision highp float; +in vec4 gs_out; +layout(location = 0) out vec4 oColor; +void main() +{ + oColor = gs_out; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + glUniform4f(glGetUniformLocation(program, "u_color"), 0, 1, 0, 1); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + +// Test that redeclaring gl_PerVertex for output works. +TEST_P(GeometryShaderTest, RedeclareGlOut) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + constexpr char kVS[] = R"(#version 310 es +precision highp float; +layout(location = 0) in highp vec4 position; +void main() +{ + gl_Position = position; +})"; + + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +uniform vec4 u_color; +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +out gl_PerVertex +{ + highp vec4 gl_Position; +}; +out vec4 gs_out; +void main() +{ + gl_Position = gl_in[0].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[2].gl_Position; + gs_out = u_color; + EmitVertex(); +})"; + + constexpr char kFS[] = R"(#version 310 es +precision highp float; +in vec4 gs_out; +layout(location = 0) out vec4 oColor; +void main() +{ + oColor = gs_out; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + glUniform4f(glGetUniformLocation(program, "u_color"), 0, 1, 0, 1); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + +// Test that redeclaring gl_in works when geometry shader array input size +// is set after shader input variables. +TEST_P(GeometryShaderTest, RedeclareGlInBeforeInputSize) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +precision highp float; +layout(location = 0) in highp vec4 position; +out gl_PerVertex +{ + highp vec4 gl_Position; +}; +void main() +{ + gl_Position = position; +})"; + + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +uniform vec4 u_color; +in gl_PerVertex +{ + highp vec4 gl_Position; +} gl_in[]; +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +out vec4 gs_out; +void main() +{ + gl_Position = gl_in[0].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + gs_out = u_color; + EmitVertex(); + gl_Position = gl_in[2].gl_Position; + gs_out = u_color; + EmitVertex(); +})"; + + constexpr char kFS[] = R"(#version 310 es +precision highp float; +in vec4 gs_out; +layout(location = 0) out vec4 oColor; +void main() +{ + oColor = gs_out; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + glUniform4f(glGetUniformLocation(program, "u_color"), 0, 1, 0, 1); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + +// Test that redeclaring gl_in works when geometry shader array input size +// is set after shader input variables, but gl_in itself is not used. +TEST_P(GeometryShaderTest, RedeclareGlInBeforeInputSizeButUnused) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + constexpr char kVS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +precision highp float; +layout(location = 0) in highp vec4 position; +out gl_PerVertex +{ + highp vec4 gl_Position; +}; +void main() +{ + gl_Position = vec4(0, 0, 0, position.w); +})"; + + constexpr char kGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +uniform vec4 u_color; +in gl_PerVertex +{ + highp vec4 gl_Position; +} gl_in[]; +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +out vec4 gs_out; +void main() +{ + gl_Position = vec4(-1, -1, 0, 1); + gs_out = u_color; + EmitVertex(); + gl_Position = vec4(3, -1, 0, 1); + gs_out = u_color; + EmitVertex(); + gl_Position = vec4(-1, 3, 0, 1); + gs_out = u_color; + EmitVertex(); +})"; + + constexpr char kFS[] = R"(#version 310 es +precision highp float; +in vec4 gs_out; +layout(location = 0) out vec4 oColor; +void main() +{ + oColor = gs_out; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + glUniform4f(glGetUniformLocation(program, "u_color"), 0, 1, 0, 1); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); +} + // Verify that Geometry Shader can be compiled when geometry shader array input size // is set after shader input variables. // http://anglebug.com/42265598 GFXBench Car Chase uses this pattern @@ -1790,6 +2086,147 @@ void main() EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue); } +// Test that implicitly sized geometry shader input and an explicitly sized array are compatible. +// The explicitly sized array is declared after the implicitly sized one. +TEST_P(GeometryShaderTest, ImplicitSizedArrayMatchesExplicitSizedArray) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + const char *kVS = R"(#version 310 es +precision mediump float; +in vec4 position; +out vec4 vgVarying; +uniform vec4 uniVec; +void main() +{ + vgVarying = uniVec; + gl_Position = position; +})"; + + const char *kGS = R"(#version 310 es +#extension GL_EXT_geometry_shader : require + +precision mediump float; + +in vec4 vgVarying[]; +layout(location = 5) out vec4 gfVarying; + +// The layout is intentionally provided after the input varying is specified, such that its size +// cannot be determined at declaration time. +layout (triangles) in; +layout (triangle_strip, max_vertices = 4) out; + +void main() +{ + // Use an explicit array type that matches the implicitly typed one. + vec4 varyingCopy[3]; + // Make sure the types are compatible + varyingCopy = vgVarying; + + for (int n = 0; n < gl_in.length(); n++) + { + gl_Position = gl_in[n].gl_Position; + gfVarying = varyingCopy[n]; + EmitVertex(); + } + EndPrimitive(); +})"; + + const char *kFS = R"(#version 310 es +precision mediump float; + +layout(location = 5) in vec4 gfVarying; +out vec4 fOut; + +void main() +{ + fOut = gfVarying; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + GLint uniLoc = glGetUniformLocation(program, "uniVec"); + ASSERT_NE(-1, uniLoc); + glUniform4f(uniLoc, 0, 1, 0, 1); + ASSERT_GL_NO_ERROR(); + + drawQuad(program, "position", 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test that implicitly sized geometry shader input and an explicitly sized array are compatible. +// The explicitly sized array is declared before the implicitly sized one. +TEST_P(GeometryShaderTest, ImplicitSizedArrayMatchesExplicitSizedArray2) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + const char *kVS = R"(#version 310 es +precision mediump float; +in vec4 position; +out vec4 vgVarying; +uniform vec4 uniVec; +void main() +{ + vgVarying = uniVec; + gl_Position = position; +})"; + + const char *kGS = R"(#version 310 es +#extension GL_EXT_geometry_shader : require + +precision mediump float; + +// Use an explicit array type that will match the implicitly typed one. +vec4 varyingCopy[3]; + +in vec4 vgVarying[]; +layout(location = 5) out vec4 gfVarying; + +// The layout is intentionally provided after the input varying is specified, such that its size +// cannot be determined at declaration time. +layout (triangles) in; +layout (triangle_strip, max_vertices = 4) out; + +void main() +{ + // Make sure the types are compatible + varyingCopy = vgVarying; + + for (int n = 0; n < gl_in.length(); n++) + { + gl_Position = gl_in[n].gl_Position; + gfVarying = varyingCopy[n]; + EmitVertex(); + } + EndPrimitive(); +})"; + + const char *kFS = R"(#version 310 es +precision mediump float; + +layout(location = 5) in vec4 gfVarying; +out vec4 fOut; + +void main() +{ + fOut = gfVarying; +})"; + + ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS); + glUseProgram(program); + + GLint uniLoc = glGetUniformLocation(program, "uniVec"); + ASSERT_NE(-1, uniLoc); + glUniform4f(uniLoc, 0, 1, 0, 1); + ASSERT_GL_NO_ERROR(); + + drawQuad(program, "position", 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + // Tests separating the VS from the GS/FS and then modifying the shader. TEST_P(GeometryShaderTest, RecompileSeparableVSWithVaryings) { @@ -2066,7 +2503,7 @@ void main() } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GeometryShaderTestES3); -ANGLE_INSTANTIATE_TEST_ES3(GeometryShaderTestES3); +ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND_ES32(GeometryShaderTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GeometryShaderTest); ANGLE_INSTANTIATE_TEST_ES31_AND(GeometryShaderTest, diff --git a/src/tests/gl_tests/GetImageTest.cpp b/src/tests/gl_tests/GetImageTest.cpp index b5710b7d005..304ee5b3291 100644 --- a/src/tests/gl_tests/GetImageTest.cpp +++ b/src/tests/gl_tests/GetImageTest.cpp @@ -7,6 +7,10 @@ // Tests for the ANGLE_get_image extension. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "image_util/storeimage.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -901,10 +905,10 @@ TEST_P(GetImageTest, CompressedTexImageNotBlockMultiple) EXPECT_EQ(expectedData, actualData); } -void TestCompressedTexImage3D(GLenum target, uint32_t numLayers) +void TestCompressedTexImage3D(GLenum target, uint32_t numLayers, int clientMajorVersion) { - auto func = [target, numLayers](const CompressionExtension &ext, - const CompressedFormat &format) { + auto func = [target, numLayers, clientMajorVersion](const CompressionExtension &ext, + const CompressedFormat &format) { // Skip extensions lacking 2D array and 3D support if ((target == GL_TEXTURE_2D_ARRAY && !ext.supports2DArray) || (target == GL_TEXTURE_3D && !ext.supports3D)) @@ -932,8 +936,17 @@ void TestCompressedTexImage3D(GLenum target, uint32_t numLayers) expectedData.push_back(i); } - glCompressedTexImage3D(target, 0, format.id, format.w, format.h, numLayers, 0, size, - expectedData.data()); + if (clientMajorVersion < 3) + { + ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_texture_3D")); + glCompressedTexImage3DOES(target, 0, format.id, format.w, format.h, numLayers, 0, size, + expectedData.data()); + } + else + { + glCompressedTexImage3D(target, 0, format.id, format.w, format.h, numLayers, 0, size, + expectedData.data()); + } if (IsFormatEmulated(target)) { @@ -955,15 +968,17 @@ TEST_P(GetImageTestES3, CompressedTexImage2DArray) { // Verify the extension is enabled. ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName)); - TestCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 8); + TestCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 8, getClientMajorVersion()); } // Tests GetCompressedTexImage with 3D textures. TEST_P(GetImageTest, CompressedTexImage3D) { + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D")); + // Verify the extension is enabled. ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName)); - TestCompressedTexImage3D(GL_TEXTURE_3D, 8); + TestCompressedTexImage3D(GL_TEXTURE_3D, 8, getClientMajorVersion()); } // Simple cube map test for GetCompressedTexImage @@ -1238,4 +1253,4 @@ ANGLE_INSTANTIATE_TEST(GetImageTestNoExtensions, ES2_VULKAN_SWIFTSHADER(), ES3_VULKAN_SWIFTSHADER()); -} // namespace \ No newline at end of file +} // namespace diff --git a/src/tests/gl_tests/ImageTest.cpp b/src/tests/gl_tests/ImageTest.cpp index e1430bfb610..5f610f5789f 100644 --- a/src/tests/gl_tests/ImageTest.cpp +++ b/src/tests/gl_tests/ImageTest.cpp @@ -7,12 +7,21 @@ // Tests the correctness of eglImage. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/MultiThreadSteps.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" #include "util/test_utils.h" +#if defined(ANGLE_ENABLE_WGPU) +# include +# include +#endif + #include "common/android_util.h" #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 29 @@ -50,6 +59,8 @@ constexpr char kEGLAndroidImageNativeBufferExt[] = "EGL_ANDROID_image_native_buf constexpr char kEGLImageStorageExt[] = "GL_EXT_EGL_image_storage"; constexpr char kEGLImageStorageCompressionExt[] = "GL_EXT_EGL_image_storage_compression"; constexpr char kTextureStorageCompressionExt[] = "GL_EXT_texture_storage_compression"; +constexpr char kWebGPUDeviceExt[] = "EGL_ANGLE_device_webgpu"; +constexpr char kWebGPUTextureExt[] = "EGL_ANGLE_webgpu_texture_client_buffer"; constexpr EGLint kDefaultAttribs[] = { EGL_IMAGE_PRESERVED, EGL_TRUE, @@ -105,6 +116,16 @@ GLubyte kSrgbColorCube[] = {148, 192, 232, 255, 230, 159, 191, 255, 176, 230, GLfloat kCubeFaceX[] = {1.0, -1.0, 0.0, 0.0, 0.0, 0.0}; GLfloat kCubeFaceY[] = {0.0, 0.0, 1.0, -1.0, 0.0, 0.0}; GLfloat kCubeFaceZ[] = {0.0, 0.0, 0.0, 0.0, 1.0, -1.0}; +// YUV texture data - ensure they are narrow range compatible values +GLubyte kYUVColorBlackY[] = {16, 16, 16, 16}; +GLubyte kYUVColorBlackCb[] = {128}; +GLubyte kYUVColorBlackCr[] = {128}; +GLubyte kYUVColorPurpleY[] = {125, 125, 125, 125}; +GLubyte kYUVColorPurpleCb[] = {193}; +GLubyte kYUVColorPurpleCr[] = {174}; +GLubyte kYUVColorRedY[] = {81, 81, 81, 81}; +GLubyte kYUVColorRedCb[] = {90}; +GLubyte kYUVColorRedCr[] = {240}; constexpr int kColorspaceAttributeIndex = 2; constexpr int k3DColorspaceAttributeIndex = 4; @@ -117,6 +138,7 @@ constexpr int AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3; constexpr int AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31; constexpr int AHARDWAREBUFFER_FORMAT_Y8Cr8Cb8_420_SP = 0x11; constexpr int AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23; +constexpr int AHARDWAREBUFFER_FORMAT_YCbCr_P210 = 0x3c; constexpr int AHARDWAREBUFFER_FORMAT_YV12 = 0x32315659; [[maybe_unused]] constexpr uint64_t ANGLE_AHARDWAREBUFFER_USAGE_FRONT_BUFFER = (1ULL << 32); @@ -156,6 +178,19 @@ void main() return R"(#version 300 es out vec2 texcoord; in vec4 position; +void main() +{ + gl_Position = vec4(position.xy, 0.0, 1.0); + texcoord = (position.xy * 0.5) + 0.5; +})"; + } + + const char *getVS3D() const + { + return R"(#version 300 es +out vec2 texcoord; +in vec4 position; + void main() { gl_Position = vec4(position.xy, 0.0, 1.0); @@ -224,6 +259,20 @@ void main() })"; } + const char *getTexture3DFS() const + { + return R"(#version 300 es +precision highp float; +uniform highp sampler3D tex3D; +uniform float layer; +in vec2 texcoord; +out vec4 fragColor; +void main() +{ + fragColor = texture(tex3D, vec3(texcoord.x, texcoord.y, layer)); +})"; + } + const char *getTextureCubeFS() const { return R"(#version 300 es @@ -280,6 +329,57 @@ void main() })"; } + const char *getTextureYUVVS() const + { + return R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision highp float; +uniform __samplerExternal2DY2YEXT tex; +in vec4 position; +out vec4 color; + +void main() +{ + gl_Position = position; + vec2 texcoord = (position.xy * 0.5) + 0.5; + texcoord.y = 1.0 - texcoord.y; + color = texture(tex, texcoord); +})"; + } + + const char *getFetchYUVVS() const + { + return R"(#version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable +precision highp float; +uniform samplerExternalOES tex; +in vec4 position; +out vec4 color; + +void main() +{ + gl_Position = position; + vec2 texcoord = (position.xy * 0.5) + 0.5; + texcoord.y = 1.0 - texcoord.y; + ivec2 fetchcoord = ivec2(texcoord * vec2(textureSize(tex, 0))); + fetchcoord = min(fetchcoord, textureSize(tex, 0) - ivec2(1.0)); + color = texelFetch(tex, fetchcoord, 0); +})"; + } + + const char *getPassThroughFS() const + { + return R"(#version 300 es +precision highp float; +in vec4 color; +out vec4 frag_color; + +void main() +{ + frag_color = color; +})"; + } + const char *getTextureYUVFS() const { return R"(#version 300 es @@ -295,6 +395,23 @@ void main() })"; } + const char *getFetchYUVFS() const + { + return R"(#version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable +precision highp float; +uniform samplerExternalOES tex; +in vec2 texcoord; +out vec4 color; + +void main() +{ + ivec2 fetchcoord = ivec2(texcoord * vec2(textureSize(tex, 0))); + fetchcoord = min(fetchcoord, textureSize(tex, 0) - ivec2(1.0)); + color = texelFetch(tex, fetchcoord, 0); +})"; + } + const char *getRenderYUVFS() const { return R"(#version 300 es @@ -303,6 +420,23 @@ precision highp float; uniform vec4 u_color; layout (yuv) out vec4 color; +void main() +{ + color = u_color; +})"; + } + + // Same as getRenderYUVFS(), but with the yuv layout specified multiple times, which should not + // make a difference. Some tests use this shader instead of getRenderYUVFS() just to exercise + // compiling such a shader. + const char *getRenderYUV2FS() const + { + return R"(#version 300 es +#extension GL_EXT_YUV_target : require +precision highp float; +uniform vec4 u_color; +layout (yuv, yuv, yuv) out vec4 color; + void main() { color = u_color; @@ -333,6 +467,18 @@ void main() glGetUniformLocation(m2DArrayTextureProgram, "layer"); } + if (getClientMajorVersion() >= 3) + { + m3DTextureProgram = CompileProgram(getVS3D(), getTexture3DFS()); + if (m3DTextureProgram == 0) + { + FAIL() << "shader compilation failed."; + } + + m3DTextureUniformLocation = glGetUniformLocation(m3DTextureProgram, "tex3D"); + m3DTextureLayerUniformLocation = glGetUniformLocation(m3DTextureProgram, "layer"); + } + if (IsGLExtensionEnabled("GL_OES_EGL_image_external")) { mTextureExternalProgram = CompileProgram(getVS(), getTextureExternalFS()); @@ -358,10 +504,33 @@ void main() mTextureYUVUniformLocation = glGetUniformLocation(mTextureYUVProgram, "tex"); + mTextureYUVVSProgram = CompileProgram(getTextureYUVVS(), getPassThroughFS()); + ASSERT_NE(0u, mTextureYUVVSProgram) << "shader compilation failed."; + + mTextureYUVVSUniformLocation = glGetUniformLocation(mTextureYUVVSProgram, "tex"); + mRenderYUVProgram = CompileProgram(getVSESSL3(), getRenderYUVFS()); ASSERT_NE(0u, mRenderYUVProgram) << "shader compilation failed."; mRenderYUVUniformLocation = glGetUniformLocation(mRenderYUVProgram, "u_color"); + + mRenderYUVProgram2 = CompileProgram(getVSESSL3(), getRenderYUV2FS()); + ASSERT_NE(0u, mRenderYUVProgram2) << "shader compilation failed."; + + mRenderYUVUniformLocation = glGetUniformLocation(mRenderYUVProgram2, "u_color"); + } + + if (IsGLExtensionEnabled(kExternalESSL3Ext)) + { + mFetchYUVProgram = CompileProgram(getVSESSL3(), getFetchYUVFS()); + ASSERT_NE(0u, mFetchYUVProgram) << "shader compilation failed."; + + mFetchYUVUniformLocation = glGetUniformLocation(mFetchYUVProgram, "tex"); + + mFetchYUVVSProgram = CompileProgram(getFetchYUVVS(), getPassThroughFS()); + ASSERT_NE(0u, mFetchYUVVSProgram) << "shader compilation failed."; + + mFetchYUVVSUniformLocation = glGetUniformLocation(mFetchYUVVSProgram, "tex"); } if (IsGLExtensionEnabled(kEGLImageStorageExt)) @@ -493,7 +662,7 @@ void main() GLenum format, GLenum type, const EGLint *attribs, - void *data, + const void *data, GLTexture &sourceTexture, EGLImageKHR *outSourceImage) { @@ -526,7 +695,7 @@ void main() GLenum format, GLenum type, const EGLint *attribs, - uint8_t *data, + const uint8_t *data, size_t dataStride, EGLenum imageTarget, GLTexture &sourceTexture, @@ -566,16 +735,26 @@ void main() GLenum format, GLenum type, const EGLint *attribs, - void *data, + const void *data, GLTexture &sourceTexture, EGLImageKHR *outSourceImage) { // Create a source 3D texture glBindTexture(GL_TEXTURE_3D, sourceTexture); - glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast(width), - static_cast(height), static_cast(depth), 0, format, type, - data); + if (getClientMajorVersion() < 3) + { + ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_texture_3D")); + glTexImage3DOES(GL_TEXTURE_3D, 0, format, static_cast(width), + static_cast(height), static_cast(depth), 0, format, + type, data); + } + else + { + glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast(width), + static_cast(height), static_cast(depth), 0, format, type, + data); + } // Disable mipmapping glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -867,7 +1046,8 @@ void main() if (!data.empty()) { const bool isYUV = androidFormat == AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 || - androidFormat == AHARDWAREBUFFER_FORMAT_YV12; + androidFormat == AHARDWAREBUFFER_FORMAT_YV12 || + androidFormat == AHARDWAREBUFFER_FORMAT_YCbCr_P210; writeAHBData(aHardwareBuffer, width, height, depth, isYUV, data); } @@ -949,6 +1129,66 @@ void main() *outSourceImage = image; } +#if defined(ANGLE_ENABLE_WGPU) + const DawnProcTable &getWebGPUProcs() { return dawn::native::GetProcs(); } + + WGPUDevice getWebGPUDevice() + { + EXPECT_TRUE(IsEGLClientExtensionEnabled("EGL_EXT_device_query")); + EGLAttrib eglDevice = 0; + EXPECT_EGL_TRUE( + eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &eglDevice)); + EXPECT_TRUE(IsEGLDeviceExtensionEnabled(reinterpret_cast(eglDevice), + kWebGPUDeviceExt)); + + EGLAttrib wgpuDevice = 0; + EXPECT_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast(eglDevice), + EGL_WEBGPU_DEVICE_ANGLE, &wgpuDevice)); + + return reinterpret_cast(wgpuDevice); + } + + void createEGLImageWebGPUTextureClientBufferSource(const WGPUTextureDescriptor &desc, + const EGLint *attribsImage, + const std::vector &data, + uint32_t bytesPerRow, + WGPUTexture *outSourceWebGPUTexture, + EGLImageKHR *outSourceImage) + { + const DawnProcTable &wgpu = getWebGPUProcs(); + + WGPUDevice device = getWebGPUDevice(); + WGPUTexture texture = wgpu.deviceCreateTexture(device, &desc); + + EGLImageKHR image = eglCreateImageKHR(getEGLWindow()->getDisplay(), EGL_NO_CONTEXT, + EGL_WEBGPU_TEXTURE_ANGLE, texture, attribsImage); + ASSERT_EGL_SUCCESS(); + + if (!data.empty()) + { + WGPUQueue queue = wgpu.deviceGetQueue(device); + + WGPUTexelCopyTextureInfo copyDest = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT; + copyDest.texture = texture; + copyDest.mipLevel = 0; + copyDest.origin = {0, 0, 0}; + + WGPUTexelCopyBufferLayout dataLayout = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT; + dataLayout.bytesPerRow = bytesPerRow; + + wgpu.queueWriteTexture(queue, ©Dest, data.data(), data.size(), &dataLayout, + &desc.size); + + wgpu.queueRelease(queue); + } + + wgpu.deviceRelease(device); + + *outSourceWebGPUTexture = texture; + *outSourceImage = image; + } +#endif // defined(ANGLE_ENABLE_WGPU) + void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint targetRenderbuffer) { // Create a target texture from the image @@ -1039,6 +1279,20 @@ void main() mTextureUniformLocation); } + void verifyResults3D(GLuint texture, + const GLubyte data[4], + uint32_t layerIndex, + uint32_t totalLayers) + { + glUseProgram(m3DTextureProgram); + float layerInterval = 1.0f / totalLayers; + float layerCenter = ((layerIndex + 1) * 1.0f / totalLayers) - layerInterval / 2.0f; + glUniform1f(m3DTextureLayerUniformLocation, layerCenter); + + verifyResultsTexture(texture, data, GL_TEXTURE_3D, m3DTextureProgram, + m3DTextureUniformLocation); + } + void verifyResults2DLeftAndRight(GLuint texture, const GLubyte left[4], const GLubyte right[4]) { verifyResultsTextureLeftAndRight(texture, left, right, GL_TEXTURE_2D, mTextureProgram, @@ -1096,6 +1350,24 @@ void main() mTextureYUVUniformLocation); } + void verifyResultsExternalYUVVS(GLuint texture, const GLubyte data[4]) + { + verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureYUVVSProgram, + mTextureYUVVSUniformLocation); + } + + void verifyResultsExternalYUVFetch(GLuint texture, const GLubyte data[4]) + { + verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mFetchYUVProgram, + mFetchYUVUniformLocation); + } + + void verifyResultsExternalYUVFetchVS(GLuint texture, const GLubyte data[4]) + { + verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mFetchYUVVSProgram, + mFetchYUVVSUniformLocation); + } + void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte referenceColor[4]) { // Bind the renderbuffer to a framebuffer @@ -1366,6 +1638,24 @@ void main() return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kCubemapExt); } + bool hasWebGPUDeviceExt() const + { + if (!IsEGLClientExtensionEnabled("EGL_EXT_device_query")) + { + return false; + } + EGLAttrib device = 0; + EXPECT_EGL_TRUE( + eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &device)); + return IsEGLDeviceExtensionEnabled(reinterpret_cast(device), + kWebGPUDeviceExt); + } + + bool hasWebGPUTextureExt() const + { + return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kWebGPUTextureExt); + } + angle::VulkanPerfCounters getPerfCounters() { ASSERT(IsVulkan()); @@ -1514,11 +1804,14 @@ void main() }; GLuint mTextureProgram; GLuint m2DArrayTextureProgram; + GLuint m3DTextureProgram; GLuint mCubeTextureProgram; GLuint mCubeArrayTextureProgram; GLint mTextureUniformLocation; GLuint m2DArrayTextureUniformLocation; GLuint m2DArrayTextureLayerUniformLocation; + GLuint m3DTextureUniformLocation; + GLuint m3DTextureLayerUniformLocation; GLuint mCubeTextureUniformLocation; GLuint mCubeTextureFaceCoordUniformLocation; GLuint mCubeArrayTextureUniformLocation; @@ -1534,7 +1827,16 @@ void main() GLuint mTextureYUVProgram = 0; GLint mTextureYUVUniformLocation = -1; + GLuint mTextureYUVVSProgram = 0; + GLint mTextureYUVVSUniformLocation = -1; + + GLuint mFetchYUVProgram = 0; + GLint mFetchYUVUniformLocation = -1; + GLuint mFetchYUVVSProgram = 0; + GLint mFetchYUVVSUniformLocation = -1; + GLuint mRenderYUVProgram = 0; + GLuint mRenderYUVProgram2 = 0; GLint mRenderYUVUniformLocation = -1; CounterNameToIndexMap mCounterNameToIndexMap; @@ -1611,6 +1913,29 @@ TEST_P(ImageTest, ANGLEExtensionAvailability) EXPECT_FALSE(has3DTextureExt()); EXPECT_FALSE(hasRenderbufferExt()); } + else if (IsWebGPU()) + { + EXPECT_TRUE(hasOESExt()); + EXPECT_TRUE(hasBaseExt()); + EXPECT_TRUE(hasExternalExt()); + if (getClientMajorVersion() >= 3) + { + EXPECT_TRUE(hasExternalESSL3Ext()); + } + else + { + EXPECT_FALSE(hasExternalESSL3Ext()); + } + EXPECT_TRUE(has2DTextureExt()); + EXPECT_FALSE(hasCubemapExt()); + EXPECT_FALSE(has3DTextureExt()); + EXPECT_TRUE(hasRenderbufferExt()); + EXPECT_TRUE(hasWebGPUDeviceExt()); + EXPECT_TRUE(hasWebGPUTextureExt()); +#if !defined(ANGLE_ENABLE_WGPU) + FAIL() << "ANGLE_ENABLE_WGPU not defined when running on WebGPU backend"; +#endif + } else { EXPECT_FALSE(hasOESExt()); @@ -2481,89 +2806,293 @@ TEST_P(ImageTestES3, SourceAHBTarget2DGenerateMipmapColorspaceBlend) destroyAndroidHardwareBuffer(aHardwareBuffer); } -// Try to orphan image created with the GL_EXT_EGL_image_storage extension -TEST_P(ImageTestES3, Source2DTarget2DStorageOrphan) +// Test interaction between AHB, GL_OES_EGL_image_external and glGenerateMipmap. +TEST_P(ImageTestES3, SourceAHBTargetTexture2DGenerateMipmap) { EGLWindow *window = getEGLWindow(); ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); - ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); - // Create the Image - GLTexture source; + GLubyte red_data[16] = {255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255}; + + AHardwareBuffer *source; EGLImageKHR image; - createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, - static_cast(&kLinearColor), source, &image); + createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {{red_data, 16}}, + &source, &image); - // Create the target - GLTexture target; - createEGLImageTargetTextureStorage(image, GL_TEXTURE_2D, target, nullptr); + // Create a texture target to bind the egl image. + GLTexture tex1; + createEGLImageTargetTexture2D(image, tex1); - // Expect that the target texture has the same color as the source texture - verifyResults2D(target, kLinearColor); + // Draw to the tex1. + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); - // Try to orphan this target texture - glBindTexture(GL_TEXTURE_2D, target); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kLinearColor); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); + // Generate mipmap for texture. + glBindTexture(GL_TEXTURE_2D, tex1); + glGenerateMipmap(GL_TEXTURE_2D); + ASSERT_GL_NO_ERROR(); - // Clean up + // Attach the texture to fbo2. + GLTexture tex2; + glBindTexture(GL_TEXTURE_2D, tex2); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Sample tex1. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glBindTexture(GL_TEXTURE_2D, tex1); + ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + glUseProgram(drawTexture); + GLint texLocation = glGetUniformLocation(drawTexture, essl1_shaders::Texture2DUniform()); + ASSERT_NE(-1, texLocation); + glUniform1i(texLocation, 0); + drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f); + + // Verify results. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Clean up. eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); } -// Create target texture from EGL image and then trigger texture respecification. -TEST_P(ImageTest, Source2DTarget2DTargetTextureRespecifyColorspace) +// Test that drawing to an AHB works. +TEST_P(ImageTestES3, SourceAHBTarget2DDraw) { EGLWindow *window = getEGLWindow(); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_sRGB_override")); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); - // Create the Image - GLTexture source; + // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT + AHardwareBuffer *source; EGLImageKHR image; - createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, - static_cast(&kSrgbColor), source, &image); + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {}, &source, + &image); - // Create the target + // Create a texture target to bind the egl image GLTexture target; createEGLImageTargetTexture2D(image, target); - // Expect that the target texture has the same color as the source texture - verifyResults2D(target, kSrgbColor); + // Draw to the target and verify results. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Respecify texture colorspace and verify results - glBindTexture(GL_TEXTURE_2D, target); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_SRGB); + ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f); ASSERT_GL_NO_ERROR(); - // Expect that the target texture decodes the sRGB color to linear when sampling - verifyResults2D(target, kLinearColor); - // Reset texture parameter and verify results again - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_NONE); - ASSERT_GL_NO_ERROR(); - // Expect that the target texture has the same color as the source texture - verifyResults2D(target, kSrgbColor); + // Verify results for completeness. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); // Clean up eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); } -// Create target texture from EGL image and then trigger texture respecification. -TEST_P(ImageTest, Source2DTarget2DTargetTextureRespecifySize) +// Test that using an image through a texture, detaching it, then using it again with another +// texture works. This is similar to the usage pattern of |SourceAHBTarget2DGenerateMipmap|, but +// doesn't require the |kAHBUsageGPUMipMapComplete| flags. +TEST_P(ImageTestES3, SourceAHBTarget2DUseAfterDetach) { EGLWindow *window = getEGLWindow(); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); - // Create the Image - GLTexture source; + // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT + AHardwareBuffer *source; EGLImageKHR image; - createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, - static_cast(&kLinearColor), source, &image); + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {}, &source, + &image); - // Create the target + // Create a texture target to bind the egl image GLTexture target; createEGLImageTargetTexture2D(image, target); - // Expect that the target texture has the same color as the source texture + // Clear the texture, use a temporary framebuffer. + { + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + // Use the texture in a command buffer, but don't let it get submitted (use the default + // framebuffer). + ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + GLint texLocation = glGetUniformLocation(drawTexture, essl1_shaders::Texture2DUniform()); + ASSERT_NE(-1, texLocation); + glUseProgram(drawTexture); + glUniform1i(texLocation, 0); + ASSERT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, target); + drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f); + + // Release the texture. In the Vulkan backend, the image is scheduled to be transitioned to the + // FORIENG queue because this is an AHB. + glBindTexture(GL_TEXTURE_2D, 0); + target.reset(); + + // Now attach another texture to the same image. + GLTexture target2; + glBindTexture(GL_TEXTURE_2D, target2); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + ASSERT_GL_NO_ERROR(); + + // Use the new texture. In the Vulkan backend, the management of transfer to FOREIGN queue and + // back should be correct. + drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + + // Verify results for completeness. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Try to orphan image created with the GL_EXT_EGL_image_storage extension +TEST_P(ImageTestES3, Source2DTarget2DStorageOrphan) +{ + EGLWindow *window = getEGLWindow(); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt()); + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + static_cast(&kLinearColor), source, &image); + + // Create the target + GLTexture target; + createEGLImageTargetTextureStorage(image, GL_TEXTURE_2D, target, nullptr); + + // Expect that the target texture has the same color as the source texture + verifyResults2D(target, kLinearColor); + + // Try to orphan this target texture + glBindTexture(GL_TEXTURE_2D, target); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kLinearColor); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); +} + +// Try to orphan 3D image created with the GL_EXT_EGL_image_storage extension +TEST_P(ImageTestES3, Source3DTarget3DStorageOrphan) +{ + EGLWindow *window = getEGLWindow(); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt()); + + constexpr size_t depth = 2; + EGLint attribs[3] = {EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE}; + + // Create the Image + GLTexture source; + EGLImageKHR image; + + createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, attribs, + static_cast(&kLinearColor3D), source, &image); + + // Create the target + GLTexture target; + createEGLImageTargetTextureStorage(image, GL_TEXTURE_3D, target, nullptr); + + for (size_t layer = 0; layer < depth; layer++) + { + // Expect that the target texture has the same color as the source texture + verifyResults3D(target, &kLinearColor3D[layer * 4], layer, depth); + } + + // Try to orphan this target texture + glBindTexture(GL_TEXTURE_3D, target); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kLinearColor); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); +} + +// Create target texture from EGL image and then trigger texture respecification. +TEST_P(ImageTest, Source2DTarget2DTargetTextureRespecifyColorspace) +{ + EGLWindow *window = getEGLWindow(); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_sRGB_override")); + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + static_cast(&kSrgbColor), source, &image); + + // Create the target + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Expect that the target texture has the same color as the source texture + verifyResults2D(target, kSrgbColor); + + // Respecify texture colorspace and verify results + glBindTexture(GL_TEXTURE_2D, target); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_SRGB); + ASSERT_GL_NO_ERROR(); + // Expect that the target texture decodes the sRGB color to linear when sampling + verifyResults2D(target, kLinearColor); + + // Reset texture parameter and verify results again + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_NONE); + ASSERT_GL_NO_ERROR(); + // Expect that the target texture has the same color as the source texture + verifyResults2D(target, kSrgbColor); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); +} + +// Create target texture from EGL image and then trigger texture respecification. +TEST_P(ImageTest, Source2DTarget2DTargetTextureRespecifySize) +{ + EGLWindow *window = getEGLWindow(); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + static_cast(&kLinearColor), source, &image); + + // Create the target + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Expect that the target texture has the same color as the source texture verifyResults2D(target, kLinearColor); // Respecify texture size and verify results @@ -2613,6 +3142,45 @@ TEST_P(ImageTestES3, Source2DTarget2DTargetTextureRespecifyLevel) eglDestroyImageKHR(window->getDisplay(), image); } +// Test that drawing to an AHB with MSRTSS works. +TEST_P(ImageTestES3, SourceAHBTarget2DTextureThenMSRTSS) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); + + // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {}, &source, + &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Draw to the target and verify results. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + target, 0, 4); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + + // Verify results for completeness. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + // Create target texture from EGL image and then trigger texture respecification which releases the // last image ref. TEST_P(ImageTest, ImageOrphanRefCountingBug) @@ -2902,6 +3470,133 @@ TEST_P(ImageTest, SourceBadAccess) } } +// Testing GLES resources when creating EGL image, if the client buffer itself is an EGL target, +// eglCreateImageKHR should return NO_IMAGE and generate error EGL_BAD_ACCESS. +TEST_P(ImageTest, ImageSiblingAsSourceTarget) +{ + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !IsVulkan() || !has2DTextureExt() || + !hasRenderbufferExt()); + EGLWindow *window = getEGLWindow(); + + // Validate gles texture + GLRenderbuffer renderBufferSource; + EGLImageKHR image1; + createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, kDefaultAttribs, renderBufferSource, + &image1); + GLTexture texture; + createEGLImageTargetTexture2D(image1, texture); + + // Texture is both an EGL target and an EGL source. EGL_BAD_ACCESS should be returned + EGLImageKHR invalidImage = + eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D, + reinterpretHelper(texture), kDefaultAttribs); + ASSERT_EGL_ERROR(EGL_BAD_ACCESS); + EXPECT_EQ(invalidImage, EGL_NO_IMAGE_KHR); + + // Validate gles renderbuffer + GLTexture textureSource; + EGLImageKHR image2; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + static_cast(&kLinearColor), textureSource, &image2); + GLRenderbuffer renderBuffer; + createEGLImageTargetRenderbuffer(image2, renderBuffer); + + // Renderbuffer is both an EGL target and an EGL source. EGL_BAD_ACCESS should be returned + invalidImage = + eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR, + reinterpretHelper(renderBuffer), kDefaultAttribs); + ASSERT_EGL_ERROR(EGL_BAD_ACCESS); + EXPECT_EQ(invalidImage, EGL_NO_IMAGE_KHR); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image1); + eglDestroyImageKHR(window->getDisplay(), image2); +} + +#if defined(ANGLE_ENABLE_WGPU) +// Testing source WebGPU Texture EGL image, target 2D texture +TEST_P(ImageTest, SourceWebGPUTextureTarget2D) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasWebGPUDeviceExt() || !hasWebGPUTextureExt()); + + const DawnProcTable &wgpu = getWebGPUProcs(); + + std::vector data = {190, 128, 238, 255}; + uint32_t dataBytesPerRow = 4; + + WGPUTextureDescriptor desc = WGPU_TEXTURE_DESCRIPTOR_INIT; + desc.usage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | + WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding; + desc.dimension = WGPUTextureDimension_2D; + desc.size = {1, 1, 1}; + desc.format = WGPUTextureFormat_RGBA8Unorm; + + const EGLint attribs[] = {EGL_NONE}; + + // Create the Image + WGPUTexture source; + EGLImageKHR image; + createEGLImageWebGPUTextureClientBufferSource(desc, attribs, data, dataBytesPerRow, &source, + &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Use texture target bound to egl image as source and render to framebuffer + // Verify that the target texture has the expected color + verifyResults2D(target, getExpected2DColorForAttribList(attribs)); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + wgpu.textureRelease(source); +} + +// Testing source WebGPU Texture EGL image, target 2D renderbuffer +TEST_P(ImageTest, SourceWebGPUTextureRenderbuffer) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasWebGPUDeviceExt() || !hasWebGPUTextureExt()); + + const DawnProcTable &wgpu = getWebGPUProcs(); + + std::vector data = {190, 128, 238, 255}; + uint32_t dataBytesPerRow = 4; + + WGPUTextureDescriptor desc = WGPU_TEXTURE_DESCRIPTOR_INIT; + desc.usage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | + WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding; + desc.dimension = WGPUTextureDimension_2D; + desc.size = {1, 1, 1}; + desc.format = WGPUTextureFormat_RGBA8Unorm; + + const EGLint attribs[] = {EGL_NONE}; + + // Create the Image + WGPUTexture source; + EGLImageKHR image; + createEGLImageWebGPUTextureClientBufferSource(desc, attribs, data, dataBytesPerRow, &source, + &image); + + // Create a renderbuffer target to bind the egl image + GLRenderbuffer target; + createEGLImageTargetRenderbuffer(image, target); + + // Use renderbuffer target bound to egl image as source and render to framebuffer + // Verify that the target renderbuffer has the expected color + verifyResultsRenderbuffer(target, getExpected2DColorForAttribList(attribs)); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + wgpu.textureRelease(source); +} +#endif // defined(ANGLE_ENABLE_WGPU) + // Testing source AHB EGL image, target 2D texture and delete when in use // If refcounted correctly, the test should pass without issues TEST_P(ImageTest, SourceAHBTarget2DEarlyDelete) @@ -2992,8 +3687,8 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvSourcesNoData) AHardwareBuffer *ycbcrSource; EGLImageKHR ycbcrImage; createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, - kDefaultAHBUsage, kDefaultAttribs, {}, &ycbcrSource, - &ycbcrImage); + kDefaultAHBYUVUsage, kDefaultAttribs, {}, + &ycbcrSource, &ycbcrImage); EXPECT_NE(ycbcrSource, nullptr); EXPECT_NE(ycbcrImage, EGL_NO_IMAGE_KHR); @@ -3001,8 +3696,8 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvSourcesNoData) AHardwareBuffer *ycrcbSource; EGLImageKHR ycrcbImage; createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cr8Cb8_420_SP, - kDefaultAHBUsage, kDefaultAttribs, {}, &ycrcbSource, - &ycrcbImage); + kDefaultAHBYUVUsage, kDefaultAttribs, {}, + &ycrcbSource, &ycrcbImage); EXPECT_NE(ycrcbSource, nullptr); EXPECT_NE(ycrcbImage, EGL_NO_IMAGE_KHR); @@ -3010,7 +3705,7 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvSourcesNoData) AHardwareBuffer *yv12Source; EGLImageKHR yv12Image; createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_YV12, - kDefaultAHBUsage, kDefaultAttribs, {}, &yv12Source, + kDefaultAHBYUVUsage, kDefaultAttribs, {}, &yv12Source, &yv12Image); EXPECT_NE(yv12Source, nullptr); EXPECT_NE(yv12Image, EGL_NO_IMAGE_KHR); @@ -3071,34 +3766,22 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvSources) ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported( 1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage)); ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported( - 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage)); + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage)); // Create RGB Image - GLubyte rgbColor[4] = {0, 0, 255, 255}; - AHardwareBuffer *rgbSource; EGLImageKHR rgbImage; createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, - kDefaultAHBUsage, kDefaultAttribs, {{rgbColor, 4}}, - &rgbSource, &rgbImage); + kDefaultAHBUsage, kDefaultAttribs, + {{GLColor::blue.data(), 4}}, &rgbSource, &rgbImage); // Create YUV Image - // 3 planes of data - GLubyte dataY[4] = {40, 40, 40, 40}; - GLubyte dataCb[1] = { - 240, - }; - GLubyte dataCr[1] = { - 109, - }; - - GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; - AHardwareBuffer *yuvSource; EGLImageKHR yuvImage; createEGLImageAndroidHardwareBufferSource( - 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, - {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &yuvSource, &yuvImage); + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorPurpleY, 1}, {kYUVColorPurpleCb, 1}, {kYUVColorPurpleCr, 1}}, &yuvSource, + &yuvImage); // Create a texture target to bind the egl image GLTexture target; @@ -3108,20 +3791,23 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvSources) glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); + // Expected purple color in RGB colorspace + constexpr GLColor kRGBColorPurple = GLColor(200u, 64u, 255u, 255u); + // Bind YUV image glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage); - // Expect render target to have the same color as expectedRgbColor - verifyResultsExternal(target, expectedRgbColor); + // Expect render target to have the same color as yuvImage + verifyResultsExternal(target, kRGBColorPurple.data()); // Bind RGB image glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, rgbImage); - // Expect render target to have the same color as rgbColor - verifyResultsExternal(target, rgbColor); + // Expect render target to have the same color as rgbImage + verifyResultsExternal(target, GLColor::blue.data()); // Bind YUV image glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage); - // Expect render target to have the same color as expectedRgbColor - verifyResultsExternal(target, expectedRgbColor); + // Expect render target to have the same color as yuvImage + verifyResultsExternal(target, kRGBColorPurple.data()); // Clean up eglDestroyImageKHR(window->getDisplay(), yuvImage); @@ -3143,31 +3829,19 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvTargets) ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); // Create RGBA Image - GLubyte rgbaColor[4] = {0, 0, 255, 255}; - AHardwareBuffer *rgbaSource; EGLImageKHR rgbaImage; createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, - kDefaultAHBUsage, kDefaultAttribs, {{rgbaColor, 4}}, - &rgbaSource, &rgbaImage); + kDefaultAHBUsage, kDefaultAttribs, + {{GLColor::blue.data(), 4}}, &rgbaSource, &rgbaImage); // Create YUV Image - // 3 planes of data - GLubyte dataY[4] = {40, 40, 40, 40}; - GLubyte dataCb[1] = { - 240, - }; - GLubyte dataCr[1] = { - 109, - }; - - GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; - AHardwareBuffer *yuvSource; EGLImageKHR yuvImage; createEGLImageAndroidHardwareBufferSource( - 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, - {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &yuvSource, &yuvImage); + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorPurpleY, 1}, {kYUVColorPurpleCb, 1}, {kYUVColorPurpleCr, 1}}, &yuvSource, + &yuvImage); // Create texture target siblings to bind the egl images // Create YUV target and bind the image @@ -3190,21 +3864,24 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvTargets) glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, rgbaImage); ASSERT_GL_NO_ERROR(); + // Expected purple color in RGB colorspace + constexpr GLColor kRGBColorPurple = GLColor(200u, 64u, 255u, 255u); + // Cycle through targets // YUV target glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTarget); - // Expect render target to have the same color as expectedRgbColor - verifyResultsExternal(yuvTarget, expectedRgbColor); + // Expect render target to have the same color as yuvImage + verifyResultsExternal(yuvTarget, kRGBColorPurple.data()); // RGBA target glBindTexture(GL_TEXTURE_EXTERNAL_OES, rgbaTarget); - // Expect render target to have the same color as rgbColor - verifyResultsExternal(rgbaTarget, rgbaColor); + // Expect render target to have the same color as rgbaImage + verifyResultsExternal(rgbaTarget, GLColor::blue.data()); // YUV target glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTarget); - // Expect render target to have the same color as expectedRgbColor - verifyResultsExternal(yuvTarget, expectedRgbColor); + // Expect render target to have the same color as yuvImage + verifyResultsExternal(yuvTarget, kRGBColorPurple.data()); // Clean up eglDestroyImageKHR(window->getDisplay(), yuvImage); @@ -3228,8 +3905,8 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvTargetsNoData) AHardwareBuffer *ycbcrSource; EGLImageKHR ycbcrImage; createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, - kDefaultAHBUsage, kDefaultAttribs, {}, &ycbcrSource, - &ycbcrImage); + kDefaultAHBYUVUsage, kDefaultAttribs, {}, + &ycbcrSource, &ycbcrImage); EXPECT_NE(ycbcrSource, nullptr); EXPECT_NE(ycbcrImage, EGL_NO_IMAGE_KHR); @@ -3237,7 +3914,7 @@ TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvTargetsNoData) AHardwareBuffer *yv12Source; EGLImageKHR yv12Image; createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_YV12, - kDefaultAHBUsage, kDefaultAttribs, {}, &yv12Source, + kDefaultAHBYUVUsage, kDefaultAttribs, {}, &yv12Source, &yv12Image); EXPECT_NE(yv12Source, nullptr); EXPECT_NE(yv12Image, EGL_NO_IMAGE_KHR); @@ -3730,28 +4407,18 @@ TEST_P(ImageTest, SourceYUVAHBTargetExternalRGBSampleInitData) ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL()); ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); - // 3 planes of data - GLubyte dataY[4] = {7, 51, 197, 231}; - GLubyte dataCb[1] = { - 128, - }; - GLubyte dataCr[1] = { - 192, - }; - // Create the Image AHardwareBuffer *source; EGLImageKHR image; createEGLImageAndroidHardwareBufferSource( - 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, - {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image); + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}, &source, &image); // Create a texture target to bind the egl image GLTexture target; createEGLImageTargetTextureExternal(image, target); - GLubyte pixelColor[4] = {255, 159, 211, 255}; - verifyResultsExternal(target, pixelColor); + verifyResultsExternal(target, GLColor::red.data()); // Clean up eglDestroyImageKHR(window->getDisplay(), image); @@ -3771,7 +4438,7 @@ TEST_P(ImageTest, SourceYUVAHBTargetExternalRGBSampleNoData) AHardwareBuffer *source; EGLImageKHR image; createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, - kDefaultAHBUsage, kDefaultAttribs, {}, &source, + kDefaultAHBYUVUsage, kDefaultAttribs, {}, &source, &image); // Create a texture target to bind the egl image @@ -3806,27 +4473,18 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSample) ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); - // 3 planes of data - GLubyte dataY[4] = {7, 51, 197, 231}; - GLubyte dataCb[1] = { - 128, - }; - GLubyte dataCr[1] = { - 192, - }; - // Create the Image AHardwareBuffer *source; EGLImageKHR image; createEGLImageAndroidHardwareBufferSource( - 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, - {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image); + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}, &source, &image); // Create a texture target to bind the egl image GLTexture target; createEGLImageTargetTextureExternal(image, target); - GLubyte pixelColor[4] = {197, 128, 192, 255}; + GLubyte pixelColor[4] = {kYUVColorRedY[0], kYUVColorRedCb[0], kYUVColorRedCr[0], 255}; verifyResultsExternalYUV(target, pixelColor); // Clean up @@ -3834,6 +4492,90 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSample) destroyAndroidHardwareBuffer(source); } +// Test sampling from a YUV AHB using EXT_yuv_target in the vertex shader +TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSampleVS) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + // Create the Image + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}, &source, &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); + + GLubyte pixelColor[4] = {kYUVColorRedY[0], kYUVColorRedCb[0], kYUVColorRedCr[0], 255}; + verifyResultsExternalYUVVS(target, pixelColor); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Test texelFetch from a YUV AHB using samplerExternalOES in the fragment shader +TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVFetchSamplerExternalOES) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || + !hasExternalESSL3Ext()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + // Create the Image + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}, &source, &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); + + verifyResultsExternalYUVFetch(target, GLColor::red.data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Test texelFetch from a YUV AHB using samplerExternalOES in the vertex shader +TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVFetchVSSamplerExternalOES) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || + !hasExternalESSL3Ext()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + // Create the Image + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, + {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}, &source, &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); + + verifyResultsExternalYUVFetchVS(target, GLColor::red.data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + // Test using glCopySubTextureCHROMIUM with YUV AHB as the source TEST_P(ImageTestES3, SourceYUVAHBTargetExternalCopySrc) { @@ -3844,8 +4586,8 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalCopySrc) ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_copy_texture")); - // 3 planes of data - GLubyte dataY[4] = {7, 51, 197, 231}; + // 3 planes of data - ensure they are narrow range compatible values + GLubyte dataY[4] = {20, 51, 197, 231}; GLubyte dataCb[1] = { 128, }; @@ -3857,7 +4599,7 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalCopySrc) AHardwareBuffer *source; EGLImageKHR image; createEGLImageAndroidHardwareBufferSource( - 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBYUVUsage, kDefaultAttribs, {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image); // Create a texture target to bind the egl image @@ -3879,7 +4621,7 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalCopySrc) EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(92, 0, 0, 255), 2); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(107, 0, 5, 255), 2); EXPECT_PIXEL_COLOR_NEAR(1, 0, GLColor(143, 0, 41, 255), 2); EXPECT_PIXEL_COLOR_NEAR(0, 1, GLColor(255, 159, 211, 255), 2); EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(255, 198, 250, 255), 2); @@ -3908,18 +4650,18 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSampleLinearFiltering) // clang-format off GLubyte dataY[] = { - 81, 81, - 81, 81, - 16, 16, - 16, 16, + kYUVColorRedY[0], kYUVColorRedY[0], + kYUVColorRedY[0], kYUVColorRedY[0], + kYUVColorBlackY[0], kYUVColorBlackY[0], + kYUVColorBlackY[0], kYUVColorBlackY[0], }; GLubyte dataCb[] = { - 90, - 128, + kYUVColorRedCb[0], + kYUVColorBlackCb[0], }; GLubyte dataCr[] = { - 240, - 128, + kYUVColorRedCr[0], + kYUVColorBlackCr[0], }; // clang-format on @@ -3963,6 +4705,45 @@ TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSampleLinearFiltering) destroyAndroidHardwareBuffer(ahbSource); } +// Test to verify that the image view is properly initialized in a program using +// __samplerExternal2DY2YEXT sampler when sampling from the YUV image. +TEST_P(ImageTestES3, SourceYUVAHBTargetExternal2DY2YSample) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + + ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported( + 2, 2, 1, AHARDWAREBUFFER_FORMAT_YCbCr_P210, kDefaultAHBYUVUsage)); + + // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_YCbCr_P210, + kDefaultAHBYUVUsage, kDefaultAttribs, {}, &source, + &image); + ASSERT_GL_NO_ERROR(); + + // Create a texture target to bind the egl image + GLTexture texture; + createEGLImageTargetTextureExternal(image, texture); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture); + ASSERT_GL_NO_ERROR(); + + // Use the program to sample YUV image directly in a shader + glUseProgram(mTextureYUVProgram); + glUniform1i(mTextureYUVUniformLocation, 0); + + // Expect that the image view is created properly without any crashes or assertions + drawQuad(mTextureYUVProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + // Test rendering to a YUV AHB using EXT_yuv_target TEST_P(ImageTestES3, RenderToYUVAHB) { @@ -4000,33 +4781,85 @@ TEST_P(ImageTestES3, RenderToYUVAHB) ASSERT_GL_NO_ERROR(); EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - GLubyte drawColor[4] = {197, 128, 192, 255}; + glUseProgram(mRenderYUVProgram2); + glUniform4f(mRenderYUVUniformLocation, kYUVColorRedY[0] / 255.0f, kYUVColorRedCb[0] / 255.0f, + kYUVColorRedCr[0] / 255.0f, 1.0f); + + drawQuad(mRenderYUVProgram2, "position", 0.0f); + ASSERT_GL_NO_ERROR(); + + // ReadPixels returns the RGB converted color + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, 1.0); + + // Finish before reading back AHB data + glFinish(); + + verifyResultAHB(source, {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Test rendering to a YUV AHB using EXT_yuv_target with a normal depth attachment +TEST_P(ImageTestES3, RenderToYUVAHBWithDepth) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + // 3 planes of data, initialize to all zeroes + GLubyte dataY[4] = {0, 0, 0, 0}; + GLubyte dataCb[1] = { + 0, + }; + GLubyte dataCr[1] = { + 0, + }; + + // Create the Image + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, + {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); + + // Create a depth texture + GLTexture depthTexture; + glBindTexture(GL_TEXTURE_2D, depthTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + nullptr); + EXPECT_GL_NO_ERROR(); + + // Set up a framebuffer to render into the AHB + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target, + 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); glUseProgram(mRenderYUVProgram); - glUniform4f(mRenderYUVUniformLocation, drawColor[0] / 255.0f, drawColor[1] / 255.0f, - drawColor[2] / 255.0f, drawColor[3] / 255.0f); + glUniform4f(mRenderYUVUniformLocation, kYUVColorRedY[0] / 255.0f, kYUVColorRedCb[0] / 255.0f, + kYUVColorRedCr[0] / 255.0f, 1.0f); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - drawQuad(mRenderYUVProgram, "position", 0.0f); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); drawQuad(mRenderYUVProgram, "position", 0.0f); ASSERT_GL_NO_ERROR(); // ReadPixels returns the RGB converted color - EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 159, 212, 255), 1.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, 1.0); // Finish before reading back AHB data glFinish(); - GLubyte expectedDataY[4] = {drawColor[0], drawColor[0], drawColor[0], drawColor[0]}; - GLubyte expectedDataCb[1] = { - drawColor[1], - }; - GLubyte expectedDataCr[1] = { - drawColor[2], - }; - verifyResultAHB(source, {{expectedDataY, 1}, {expectedDataCb, 1}, {expectedDataCr, 1}}); + verifyResultAHB(source, {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}); // Clean up eglDestroyImageKHR(window->getDisplay(), image); @@ -4062,80 +4895,300 @@ TEST_P(ImageTestES3, ClearYUVAHB) // Clearing a YUV framebuffer reinterprets the rgba clear color as YUV values and writes them // directly to the buffer - GLubyte clearColor[4] = {197, 128, 192, 255}; - glClearColor(clearColor[0] / 255.0f, clearColor[1] / 255.0f, clearColor[2] / 255.0f, - clearColor[3] / 255.0f); + glClearColor(kYUVColorRedY[0] / 255.0f, kYUVColorRedCb[0] / 255.0f, kYUVColorRedCr[0] / 255.0f, + 1.0f); glClear(GL_COLOR_BUFFER_BIT); ASSERT_GL_NO_ERROR(); // ReadPixels returns the RGB converted color - EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 159, 212, 255), 1.0); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, 1.0); // Clean up eglDestroyImageKHR(window->getDisplay(), image); destroyAndroidHardwareBuffer(source); } -// Test glClear on FBO with AHB attachment is applied to the AHB image before we read back -TEST_P(ImageTestES3, AHBClearAppliedBeforeReadBack) +// Test clearing to a YUV AHB using EXT_yuv_target with a normal depth attachment +TEST_P(ImageTestES3, ClearYUVAHBWithDepth) { EGLWindow *window = getEGLWindow(); - ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt()); ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); - ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); - const GLubyte kRed[] = {255, 0, 0, 255}; - const GLubyte kBlack[] = {0, 0, 0, 0}; + // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, + kDefaultAHBUsage, kDefaultAttribs, {}, &source, + &image); - // Create one image backed by the AHB. - AHardwareBuffer *ahb; - EGLImageKHR ahbImage; - createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, - kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}}, - &ahb, &ahbImage); - GLTexture ahbTexture; - createEGLImageTargetTexture2D(ahbImage, ahbTexture); + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); - // Create one framebuffer backed by the AHB. - { - GLFramebuffer ahbFbo; - glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + // Create a depth texture + GLTexture depthTexture; + glBindTexture(GL_TEXTURE_2D, depthTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + nullptr); + EXPECT_GL_NO_ERROR(); - // Clear to red - glClearColor(1, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - glFinish(); - } + // Set up a framebuffer to render into the AHB + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target, + 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - verifyResultAHB(ahb, {{kRed, 4}}); + // Clearing a YUV framebuffer reinterprets the rgba clear color as YUV values and writes them + // directly to the buffer + glClearColor(kYUVColorRedY[0] / 255.0f, kYUVColorRedCb[0] / 255.0f, kYUVColorRedCr[0] / 255.0f, + 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); - eglDestroyImageKHR(window->getDisplay(), ahbImage); - destroyAndroidHardwareBuffer(ahb); + // ReadPixels returns the RGB converted color + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, 1.0); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); } -// Similar to AHBClearAppliedBeforeReadBack, but clear is applied twice. -TEST_P(ImageTestES3, AHBTwiceClearAppliedBeforeReadBack) +// Test partial clearing to a YUV AHB using EXT_yuv_target +TEST_P(ImageTestES3, PartialClearYUVAHB) { EGLWindow *window = getEGLWindow(); - ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt()); ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); - ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); - - const GLubyte kRed[] = {255, 0, 0, 255}; - const GLubyte kBlack[] = {0, 0, 0, 0}; - // Create one image backed by the AHB. - AHardwareBuffer *ahb; - EGLImageKHR ahbImage; - createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, - kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}}, - &ahb, &ahbImage); - GLTexture ahbTexture; - createEGLImageTargetTexture2D(ahbImage, ahbTexture); + // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT + GLubyte dataY[4] = {0, 0, 0, 0}; + GLubyte dataCb[1] = { + 0, + }; + GLubyte dataCr[1] = { + 0, + }; + + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + 8, 8, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, + {{dataY, 64}, {dataCb, 64}, {dataCr, 64}}, &source, &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); + + // Set up a framebuffer to render into the AHB + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target, + 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Full clear the background + glClearColor(kYUVColorBlackY[0] / 255.0f, kYUVColorBlackCb[0] / 255.0f, + kYUVColorBlackCr[0] / 255.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::black, 2.0); + + // Partial clear the corner with another color + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 4, 4); + + glClearColor(kYUVColorRedY[0] / 255.0f, kYUVColorRedCb[0] / 255.0f, kYUVColorRedCr[0] / 255.0f, + 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + // ReadPixels returns the RGB converted color + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, 2.0); + EXPECT_PIXEL_COLOR_NEAR(4, 4, GLColor::black, 2.0); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Test initial YUV AHB content is preserved during rendering by rendering to only half of the YUV +// AHB. +TEST_P(ImageTestES3, PartialRenderToYUVAHB) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + // 3 planes of data, initialize to a color + GLubyte dataY[8] = {kYUVColorBlackY[0], kYUVColorBlackY[0], kYUVColorBlackY[0], + kYUVColorBlackY[0], kYUVColorBlackY[0], kYUVColorBlackY[0], + kYUVColorBlackY[0], kYUVColorBlackY[0]}; + GLubyte dataCb[2] = { + kYUVColorBlackCb[0], + kYUVColorBlackCb[0], + }; + GLubyte dataCr[2] = { + kYUVColorBlackCr[0], + kYUVColorBlackCr[0], + }; + + // Create the Image + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + 4, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs, + {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image); + + // Create a texture target to bind the egl image + GLTexture target; + createEGLImageTargetTextureExternal(image, target); + + // Set up a framebuffer to render into the AHB + glViewport(0, 0, 4, 2); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target, + 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Set up draw to only render to the left half of AHB + GLint positionLocation = glGetAttribLocation(mRenderYUVProgram, "position"); + std::array quadVertices = GetQuadVertices(); + for (Vector3 &vertex : quadVertices) + { + vertex.x() = (vertex.x() * 0.5f) - 0.5f; + vertex.z() = 0.0f; + } + glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data()); + glEnableVertexAttribArray(positionLocation); + + glUseProgram(mRenderYUVProgram); + glUniform4f(mRenderYUVUniformLocation, kYUVColorRedY[0] / 255.0f, kYUVColorRedCb[0] / 255.0f, + kYUVColorRedCr[0] / 255.0f, 1.0f); + + // Only draw to left half of AHB + glDrawArrays(GL_TRIANGLES, 0, 6); + ASSERT_GL_NO_ERROR(); + + // Finish before reading back AHB data + glFinish(); + + // Check left half of AHB is draw color + verifyResultAHB(source, {{kYUVColorRedY, 1}, {kYUVColorRedCb, 1}, {kYUVColorRedCr, 1}}, + AHBVerifyRegion::LeftHalf); + + // Check right half of AHB is original color + verifyResultAHB(source, {{kYUVColorBlackY, 1}, {kYUVColorBlackCb, 1}, {kYUVColorBlackCr, 1}}, + AHBVerifyRegion::RightHalf); + + // Clean up + glViewport(0, 0, getWindowWidth(), getWindowHeight()); + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Test glClear on FBO with AHB attachment is applied to the AHB image before we read back +TEST_P(ImageTestES3, AHBClearAppliedBeforeReadBack) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + const GLubyte kRed[] = {255, 0, 0, 255}; + const GLubyte kBlack[] = {0, 0, 0, 0}; + + // Create one image backed by the AHB. + AHardwareBuffer *ahb; + EGLImageKHR ahbImage; + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}}, + &ahb, &ahbImage); + GLTexture ahbTexture; + createEGLImageTargetTexture2D(ahbImage, ahbTexture); + + // Create one framebuffer backed by the AHB. + { + GLFramebuffer ahbFbo; + glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Clear to red + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glFinish(); + } + + verifyResultAHB(ahb, {{kRed, 4}}); + + eglDestroyImageKHR(window->getDisplay(), ahbImage); + destroyAndroidHardwareBuffer(ahb); +} + +// Similar to AHBClearAppliedBeforeReadBack, but clear is applied glClearTexImage(). +TEST_P(ImageTestES3, AHBClearAppliedViaClearTexImageBeforeReadBack) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clear_texture")); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + EGLWindow *window = getEGLWindow(); + + const GLubyte kRed[] = {255, 0, 0, 255}; + const GLubyte kBlack[] = {0, 0, 0, 0}; + + // Create one image backed by the AHB. + AHardwareBuffer *ahb; + EGLImageKHR ahbImage; + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}}, + &ahb, &ahbImage); + GLTexture ahbTexture; + createEGLImageTargetTexture2D(ahbImage, ahbTexture); + + // Clear to red + glClearTexImageEXT(ahbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red); + glFinish(); + + verifyResultAHB(ahb, {{kRed, 4}}); + + eglDestroyImageKHR(window->getDisplay(), ahbImage); + destroyAndroidHardwareBuffer(ahb); +} + +// Similar to AHBClearAppliedBeforeReadBack, but clear is applied twice. +TEST_P(ImageTestES3, AHBTwiceClearAppliedBeforeReadBack) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + const GLubyte kRed[] = {255, 0, 0, 255}; + const GLubyte kBlack[] = {0, 0, 0, 0}; + + // Create one image backed by the AHB. + AHardwareBuffer *ahb; + EGLImageKHR ahbImage; + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}}, + &ahb, &ahbImage); + GLTexture ahbTexture; + createEGLImageTargetTexture2D(ahbImage, ahbTexture); // Create one framebuffer backed by the AHB. { @@ -4158,6 +5211,38 @@ TEST_P(ImageTestES3, AHBTwiceClearAppliedBeforeReadBack) destroyAndroidHardwareBuffer(ahb); } +// Similar to AHBTwiceClearAppliedBeforeReadBack, but clear is applied using glClearTexImage(). +TEST_P(ImageTestES3, AHBTwiceClearViaClearTexImageAppliedBeforeReadBack) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clear_texture")); + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + EGLWindow *window = getEGLWindow(); + + const GLubyte kRed[] = {255, 0, 0, 255}; + const GLubyte kBlack[] = {0, 0, 0, 0}; + + // Create one image backed by the AHB. + AHardwareBuffer *ahb; + EGLImageKHR ahbImage; + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}}, + &ahb, &ahbImage); + GLTexture ahbTexture; + createEGLImageTargetTexture2D(ahbImage, ahbTexture); + + // Clear to green, then to red + glClearTexImageEXT(ahbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); + glClearTexImageEXT(ahbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red); + glFinish(); + + verifyResultAHB(ahb, {{kRed, 4}}); + + eglDestroyImageKHR(window->getDisplay(), ahbImage); + destroyAndroidHardwareBuffer(ahb); +} + // Test that glClear on FBO with AHB attachment is applied to the AHB image before detaching the AHB // image from FBO TEST_P(ImageTestES3, AHBClearAndDetachBeforeReadback) @@ -4857,6 +5942,43 @@ TEST_P(ImageTestES3, RGBXAHBUploadDataColorspace) destroyAndroidHardwareBuffer(ahb); } +// Test that RGBX data are preserved when importing from AHB and glTexSubImage is able to update +// data using GL_RGBA. +TEST_P(ImageTestES3, RGBXAHBUploadDataRGBA) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); + + const GLubyte kGarbage[] = {123, 123, 123, 123}; + const GLubyte kRed50LinearNoAlpha[] = {128, 0, 0, 0}; + const GLubyte kRed50Linear[] = {128, 0, 0, 255}; + + // Create the Image + AHardwareBuffer *ahb; + EGLImageKHR ahbImage; + createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, {{kGarbage, 4}}, + &ahb, &ahbImage); + + GLTexture ahbTexture; + createEGLImageTargetTexture2D(ahbImage, ahbTexture); + + glBindTexture(GL_TEXTURE_2D, ahbTexture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kRed50LinearNoAlpha); + glFinish(); + + // Make sure the alpha channel is always 1. + verifyResults2D(ahbTexture, kRed50Linear); + verifyResultAHB(ahb, {{kRed50Linear, 4}}); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), ahbImage); + destroyAndroidHardwareBuffer(ahb); +} + // Test that RGB data are preserved when importing from AHB created with sRGB color space and // glTexSubImage is able to update data. TEST_P(ImageTestES3, RGBAHBUploadDataColorspace) @@ -5369,29 +6491,35 @@ TEST_P(ImageTestES3, YUVValidation) drawQuad(mRenderYUVProgram, "position", 0.5f); EXPECT_GL_ERROR(GL_INVALID_OPERATION); - // It's an error to set disable r, g, or b color writes when rendering to a yuv framebuffer + // It's an error to disable r, g, b, a writes when rendering to a yuv framebuffer glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo); glUseProgram(mRenderYUVProgram); - glColorMask(false, true, true, true); + glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); + drawQuad(mRenderYUVProgram, "position", 0.5f); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE); drawQuad(mRenderYUVProgram, "position", 0.5f); EXPECT_GL_ERROR(GL_INVALID_OPERATION); - glColorMask(true, false, true, true); + glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); drawQuad(mRenderYUVProgram, "position", 0.5f); EXPECT_GL_ERROR(GL_INVALID_OPERATION); - glColorMask(true, true, false, true); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); drawQuad(mRenderYUVProgram, "position", 0.5f); EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // It's an error to enable blending when rendering to a yuv framebuffer glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo); glUseProgram(mRenderYUVProgram); - glDisable(GL_BLEND); + glEnable(GL_BLEND); drawQuad(mRenderYUVProgram, "position", 0.5f); EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glDisable(GL_BLEND); // It's an error to blit to/from a yuv framebuffer glBindFramebuffer(GL_READ_FRAMEBUFFER, yuvFbo); @@ -6368,6 +7496,7 @@ void ImageTest::SourceRenderbufferTargetTexture_helper(const EGLint *attribs) glClearColor(kSrgbColor[0] / 255.0f, kSrgbColor[1] / 255.0f, kSrgbColor[2] / 255.0f, kSrgbColor[3] / 255.0f); glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, 0); ASSERT_GL_NO_ERROR(); // Create the target @@ -6413,6 +7542,7 @@ void ImageTest::SourceRenderbufferTargetTextureExternal_helper(const EGLint *att glClearColor(kSrgbColor[0] / 255.0f, kSrgbColor[1] / 255.0f, kSrgbColor[2] / 255.0f, kSrgbColor[3] / 255.0f); glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, 0); ASSERT_GL_NO_ERROR(); // Create the target @@ -7071,27 +8201,104 @@ TEST_P(ImageTest, AHBUpdatedExternalTexture) destroyAndroidHardwareBuffer(source); } -// Check that the texture successfully updates when an image is deleted -TEST_P(ImageTest, DeletedImageWithSameSizeAndFormat) +// Check that the texture is successfully updated using PBO. +TEST_P(ImageTest, AHBUpdatedUnpackBuffer) { EGLWindow *window = getEGLWindow(); ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport()); - GLubyte originalData[4] = {255, 0, 255, 255}; - GLubyte updateData[4] = {0, 255, 0, 255}; + GLubyte originalData[4 * 4] = { + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, + }; + + static const unsigned char pbo[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0x7F, 0x7F, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, + 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, + }; + GLubyte resultData[4 * 4] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, + }; + const uint32_t bytesPerPixel = 4; // Create the Image - GLTexture source; + AHardwareBuffer *source; EGLImageKHR image; - createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData, - source, &image); + createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + kDefaultAHBUsage, kDefaultAttribs, + {{originalData, bytesPerPixel}}, &source, &image); - // Create texture & bind to Image - GLTexture texture; - createEGLImageTargetTexture2D(image, texture); + // Create target + GLTexture targetTexture; + createEGLImageTargetTexture2D(image, targetTexture); - // Delete Image + // Expect that both the target have the original data + verifyResults2D(targetTexture, originalData); + + GLBuffer buf; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 1); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(pbo), NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, sizeof(pbo), pbo); + EXPECT_GL_NO_ERROR(); + + // Update the data of the source + glBindTexture(GL_TEXTURE_2D, targetTexture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 2, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 0, 1, 2, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + // Set sync object and flush the GL commands + EGLSyncKHR fence = eglCreateSyncKHR(window->getDisplay(), EGL_SYNC_FENCE_KHR, NULL); + ASSERT_NE(fence, EGL_NO_SYNC_KHR); + glFlush(); + + // Wait that the flush command is finished + EGLint result = eglClientWaitSyncKHR(window->getDisplay(), fence, 0, 1000000000); + ASSERT_EQ(result, EGL_CONDITION_SATISFIED_KHR); + ASSERT_EGL_TRUE(eglDestroySyncKHR(window->getDisplay(), fence)); + + // Delete the EGL image + eglDestroyImageKHR(window->getDisplay(), image); + + // Access the android hardware buffer directly to check the data is updated + verifyResultAHB(source, {{resultData, bytesPerPixel}}); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + destroyAndroidHardwareBuffer(source); +} + +// Check that the texture successfully updates when an image is deleted +TEST_P(ImageTest, DeletedImageWithSameSizeAndFormat) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + GLubyte originalData[4] = {255, 0, 255, 255}; + GLubyte updateData[4] = {0, 255, 0, 255}; + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData, + source, &image); + + // Create texture & bind to Image + GLTexture texture; + createEGLImageTargetTexture2D(image, texture); + + // Delete Image eglDestroyImageKHR(window->getDisplay(), image); ASSERT_EGL_SUCCESS(); @@ -8208,6 +9415,172 @@ TEST_P(ImageTestES3, ResolveForeignDraw) useAHBByGLThenForeignThenGLHelper(first, second); } +// Tests that uploading to a foreign image until the outside RP command buffer is submitted does not +// break the render pass. +TEST_P(ImageTest, UploadForeignUntilSubmitDoesNotBreakRenderPass) +{ + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + + constexpr size_t kMaxBufferToImageCopySize = 64 * 1024 * 1024; + constexpr uint64_t kNumOutsideSubmits = 1; + constexpr uint32_t kWidth = 53; + constexpr uint32_t kHeight = 37; + + ANGLE_GL_PROGRAM(drawTextureProgram, essl1_shaders::vs::Texture2D(), + essl1_shaders::fs::Texture2D()); + glUseProgram(drawTextureProgram); + GLint texLocation = glGetUniformLocation(drawTextureProgram, essl1_shaders::Texture2DUniform()); + ASSERT_NE(-1, texLocation); + glUniform1i(texLocation, 0); + + // Set up FBO. + GLFramebuffer fbo; + GLTexture colorTexFBO; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindTexture(GL_TEXTURE_2D, colorTexFBO); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexFBO, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glViewport(0, 0, kWidth, kHeight); + + // Create the EGL image and a texture target to bind it. + AHardwareBuffer *source; + EGLImageKHR image; + createEGLImageAndroidHardwareBufferSource( + kWidth, kHeight, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage, + kDefaultAttribs, {}, &source, &image); + + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Use the image in GL once. + glBindTexture(GL_TEXTURE_2D, target); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + std::vector kDrawData1(kWidth * kHeight, GLColor::blue); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kDrawData1.data()); + drawQuad(drawTextureProgram, essl1_shaders::PositionAttrib(), 0.5f); + + // Upload data to and draw with a temp texture. In the Vulkan backend, the data may get flushed + // without closing the render pass. + // The draw will be limited to one pixel via glScissor(). + std::vector kDrawData2(kWidth * kHeight, GLColor::green); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 1, 1); + + constexpr size_t kMaxLoadCount = + kMaxBufferToImageCopySize / (kWidth * kHeight * 4) * kNumOutsideSubmits + 1; + for (size_t loadCount = 0; loadCount < kMaxLoadCount; loadCount++) + { + GLTexture tempTexture; + glBindTexture(GL_TEXTURE_2D, tempTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kDrawData2.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + drawQuad(drawTextureProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + } + + // Verify the draws. + EXPECT_PIXEL_RECT_EQ(1, 0, kWidth - 1, kHeight, GLColor::blue); + EXPECT_PIXEL_RECT_EQ(0, 1, kWidth, kHeight - 1, GLColor::blue); + EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor::green); + + glDisable(GL_SCISSOR_TEST); + ASSERT_GL_NO_ERROR(); +} + +// Tests that copying to a foreign image until the outside RP command buffer is submitted does not +// break the render pass. +TEST_P(ImageTest, CopyToForeignUntilSubmitDoesNotBreakRenderPass) +{ + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + + constexpr size_t kMaxBufferToImageCopySize = 64 * 1024 * 1024; + constexpr uint64_t kNumOutsideSubmits = 1; + constexpr uint32_t kWidth = 53; + constexpr uint32_t kHeight = 37; + + ANGLE_GL_PROGRAM(drawTextureProgram, essl1_shaders::vs::Texture2D(), + essl1_shaders::fs::Texture2D()); + glUseProgram(drawTextureProgram); + GLint texLocation = glGetUniformLocation(drawTextureProgram, essl1_shaders::Texture2DUniform()); + ASSERT_NE(-1, texLocation); + glUniform1i(texLocation, 0); + + // Set up FBO. + GLFramebuffer fbo; + GLTexture colorTexFBO; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindTexture(GL_TEXTURE_2D, colorTexFBO); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexFBO, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glViewport(0, 0, kWidth, kHeight); + + // Create the EGL images and the texture targets to bind them. + AHardwareBuffer *source1; + EGLImageKHR image1; + createEGLImageAndroidHardwareBufferSource( + kWidth, kHeight, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage, + kDefaultAttribs, {}, &source1, &image1); + + GLTexture target1; + createEGLImageTargetTexture2D(image1, target1); + + AHardwareBuffer *source2; + EGLImageKHR image2; + createEGLImageAndroidHardwareBufferSource( + kWidth, kHeight, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage, + kDefaultAttribs, {}, &source2, &image2); + + GLTexture target2; + createEGLImageTargetTexture2D(image2, target2); + + // Use the first image in GL. + glBindTexture(GL_TEXTURE_2D, target1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + std::vector kDrawData(kWidth * kHeight, GLColor::blue); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kDrawData.data()); + drawQuad(drawTextureProgram, essl1_shaders::PositionAttrib(), 0.5f); + + // Copy to the second image in GL. + std::vector kCopyData(kWidth * kHeight, GLColor::green); + constexpr size_t kMaxLoadCount = + kMaxBufferToImageCopySize / (kWidth * kHeight * 4) * kNumOutsideSubmits + 1; + + for (size_t loadCount = 0; loadCount < kMaxLoadCount; loadCount++) + { + GLTexture tempTexture; + glBindTexture(GL_TEXTURE_2D, tempTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kCopyData.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glCopyImageSubDataEXT(tempTexture, GL_TEXTURE_2D, 0, 0, 0, 0, target2, GL_TEXTURE_2D, 0, 0, + 0, 0, kWidth, kHeight, 1); + ASSERT_GL_NO_ERROR(); + } + + // Verify the draw. + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); +} + // Test upload, use in foreign, then draw TEST_P(ImageTest, UploadForeignDraw) { @@ -8682,6 +10055,347 @@ TEST_P(ImageTestES3, DmaBufNegativeValidation) } } +// Test redefining the source GL texture +TEST_P(ImageTestES3, RedefineSourceTexture) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + const GLColor originalColor = GLColor::yellow; + const std::vector updateColor(4, GLColor::blue); + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + originalColor.data(), source, &image); + + // Create texture & bind to Image + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Verify that the target texture has the expected color, makes sure everything is synced and + // |texture| is fully set up. + verifyResults2D(target, originalColor.data()); + + // Change the source texture. The size is changed to make sure a new image is definitely + // created for the texture. + glBindTexture(GL_TEXTURE_2D, source); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateColor.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + + // Make sure source is fully set up. + verifyResults2D(source, updateColor[0].data()); + + // Make sure the target still points to the old image. + verifyResults2D(target, originalColor.data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + + ASSERT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); +} + +// Test fully overwriting the source GL texture +TEST_P(ImageTestES3, RewriteSourceTexture) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + const GLColor originalColor = GLColor::yellow; + const GLColor updateColor = GLColor::blue; + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + originalColor.data(), source, &image); + + // Create texture & bind to Image + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Verify that the target texture has the expected color, makes sure everything is synced and + // |texture| is fully set up. + verifyResults2D(target, originalColor.data()); + + // Upload new data to source texture such that it's completely overwritten. + glBindTexture(GL_TEXTURE_2D, source); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateColor.data()); + + // Make sure the target sees the update written to the source texture. + verifyResults2D(target, updateColor.data()); + + // For completeness, check source too + verifyResults2D(source, updateColor.data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + + ASSERT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); +} + +// Test orphaning the image by destroying the source texture. +TEST_P(ImageTestES3, DestroySourceTexture) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + const GLColor originalColor = GLColor::yellow; + + // Create the Image + GLTexture source; + EGLImageKHR image; + createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, + originalColor.data(), source, &image); + + // Delete the texture. + glBindTexture(GL_TEXTURE_2D, 0); + source.reset(); + + // Make sure the image is still valid. + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Verify that the target texture has the expected color, makes sure everything is synced and + // |texture| is fully set up. + verifyResults2D(target, originalColor.data()); + + // Destroy the texture before the image. + glBindTexture(GL_TEXTURE_2D, 0); + target.reset(); + + // Finally, destroy the image itself. + eglDestroyImageKHR(window->getDisplay(), image); + + ASSERT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); +} + +// Test using the source GL texture as a storage image. Internally, the Vulkan backend recreates +// the Texture's image backing. +TEST_P(ImageTestES31, UseSourceTextureAsStorageImage) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + const GLColor originalColor = GLColor::yellow; + + // Create the Image, use glTexStorage2D for storage image use later. + GLTexture source; + glBindTexture(GL_TEXTURE_2D, source); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalColor.data()); + + EGLImageKHR image = + eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR, + reinterpretHelper(source), kDefaultAttribs); + ASSERT_EGL_SUCCESS(); + + // Create texture & bind to Image + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Verify that the target texture has the expected color, makes sure everything is synced and + // |texture| is fully set up. + verifyResults2D(target, originalColor.data()); + + // Use the source texture as a storage image + const char kCS[] = R"(#version 310 es +layout(local_size_x=1, local_size_y=1, local_size_z=1) in; +layout(rgba8) uniform highp writeonly image2D img; +void main() +{ + imageStore(img, ivec2(0, 0), vec4(0, 0, 1, 1)); +})"; + + ANGLE_GL_COMPUTE_PROGRAM(program, kCS); + glUseProgram(program); + + glBindImageTexture(0, source, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); + glDispatchCompute(1, 1, 1); + EXPECT_GL_NO_ERROR(); + + // Make sure the target sees the update written to the source texture. + glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + verifyResults2D(target, GLColor::blue.data()); + + // For completeness, check source too + verifyResults2D(source, GLColor::blue.data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + + ASSERT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); +} + +// Basic test for using an EGL image as storage for compute +// This is similar to the above UseSourceTextureAsStorageImage but is a bit more basic +// and mirrors an application issue. +TEST_P(ImageTestES31, UseEGLImageAsStorage) +{ + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt()); + + EGLWindow *window = getEGLWindow(); + + const GLColor originalColor = GLColor::yellow; + + // Create a storage texture, pre-populate with yellow + GLTexture source; + glBindTexture(GL_TEXTURE_2D, source); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalColor.data()); + + // Create an image bound to our target texture + EGLImageKHR image = + eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR, + reinterpretHelper(source), kDefaultAttribs); + ASSERT_EGL_SUCCESS(); + + // Create another texture make it a sibling of the original + GLTexture target; + glBindTexture(GL_TEXTURE_2D, target); + glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, image, nullptr); + ASSERT_GL_NO_ERROR(); + + // Just write blue to the image + const char kCS[] = R"(#version 310 es +layout(local_size_x=1, local_size_y=1, local_size_z=1) in; +layout(rgba8) uniform highp writeonly image2D img; +void main() +{ + imageStore(img, ivec2(0, 0), vec4(0.0, 0.0, 1.0, 1.0)); +})"; + + ANGLE_GL_COMPUTE_PROGRAM(program, kCS); + glUseProgram(program); + + // Use the target texture as a storage image + glBindImageTexture(0, target, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); + // TODO (http://issuetracker.google.com/456806880) + // Turn this back on when the VVL error is fixed. + // glDispatchCompute(1, 1, 1); + EXPECT_GL_NO_ERROR(); + + // We want to sample the target texture, so use the appropriate barrier + glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + + // Make sure the target sees the update written to the image. + // TODO (http://issuetracker.google.com/456806880) + // Turn this back on when the VVL error is fixed. + // verifyResults2D(target, GLColor::blue.data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + + ASSERT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); +} + +// Test overwriting the base level and calling glGenerateMipmap on the source GL texture while the +// texture is in use. +TEST_P(ImageTestES3, ImmutableTextureOverwriteBaseLevelAndGenerateMipmapWhileInUse) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + + constexpr char kVS[] = R"(#version 300 es +out vec2 texcoord; +in vec4 position; +void main() +{ + gl_Position = vec4(position.xy, 0.0, 1.0); + texcoord = (position.xy * 0.5) + 0.5; +})"; + + constexpr char kFS[] = R"(#version 300 es +precision highp float; +uniform sampler2D tex; +in vec2 texcoord; +out vec4 fragColor; +void main() +{ + vec4 test = vec4(0.8, 0.8, 0.8, 0.8); + for (int i = 0; i < 500; i++) + { + test = sqrt(test); + } + fragColor = texture(tex, texcoord * test.xy); +})"; + + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; + const std::vector originalColor(kWidth * kHeight, GLColor::yellow); + const std::vector updateColor1(kWidth * kHeight, GLColor::red); + const std::vector updateColor2(kWidth * kHeight, GLColor::green); + const std::vector updateColor3(kWidth * kHeight, GLColor::blue); + const std::vector *updateColors[] = {&updateColor1, &updateColor2, &updateColor3}; + + // Create the Image, use glTexStorage2D for glGenerateMipmap not to orphan the EGL image. + GLTexture source; + glBindTexture(GL_TEXTURE_2D, source); + glTexStorage2D(GL_TEXTURE_2D, 5, GL_RGBA8, kWidth, kHeight); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + originalColor.data()); + + EGLImageKHR image = + eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR, + reinterpretHelper(source), kDefaultAttribs); + ASSERT_EGL_SUCCESS(); + + // Create texture & bind to Image + GLTexture target; + createEGLImageTargetTexture2D(image, target); + + // Verify that the target texture has the expected color, makes sure everything is synced and + // |texture| is fully set up. + verifyResults2D(target, originalColor[0].data()); + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glBindTexture(GL_TEXTURE_2D, source); + + // Use the source texture in an expensive draw call. Then completely overwrite the base level, + // then generate mipmap. Do this multiple times, for any "redefines base level then generates + // mipmap" tracking heuristics that might trigger recreating the backing image of the texture to + // make sure the target texture still points to the same backing image. + for (uint32_t i = 0; i < 13; ++i) + { + for (const auto *updateColor : updateColors) + { + drawQuad(program, "position", 0.0f); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + updateColor->data()); + glGenerateMipmap(GL_TEXTURE_2D); + } + } + + // http://anglebug.com/410584007 + ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllowGenerateMipmapWithCompute)); + + // Make sure the target sees the update written to the source texture. + verifyResults2D(target, updateColor3[0].data()); + + // For completeness, check source too + verifyResults2D(source, updateColor3[0].data()); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), image); + + ASSERT_EGL_SUCCESS(); + ASSERT_GL_NO_ERROR(); +} + ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(ImageTest, ES3_VULKAN().enable(Feature::AllocateNonZeroMemory)); diff --git a/src/tests/gl_tests/ImageTestMetal.mm b/src/tests/gl_tests/ImageTestMetal.mm index 170879bf90a..249ac9bd9f6 100644 --- a/src/tests/gl_tests/ImageTestMetal.mm +++ b/src/tests/gl_tests/ImageTestMetal.mm @@ -7,6 +7,10 @@ // Tests the correctness of eglImage with native Metal texture extensions. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "common/mathutil.h" diff --git a/src/tests/gl_tests/IncompatibleTextureTest.cpp b/src/tests/gl_tests/IncompatibleTextureTest.cpp index a47c629001d..01ddd70435c 100644 --- a/src/tests/gl_tests/IncompatibleTextureTest.cpp +++ b/src/tests/gl_tests/IncompatibleTextureTest.cpp @@ -49,16 +49,16 @@ std::ostream &operator<<(std::ostream &out, SamplerType samplerType) switch (samplerType) { case SamplerType::Float: - out << "Float"; + out << "F"; break; case SamplerType::SignedInteger: - out << "SignedInteger"; + out << "SI"; break; case SamplerType::UnsignedInteger: - out << "UnsignedInteger"; + out << "UI"; break; case SamplerType::Shadow: - out << "Shadow"; + out << "SD"; break; } @@ -70,31 +70,31 @@ std::ostream &operator<<(std::ostream &out, TextureType textureType) switch (textureType) { case TextureType::UnsignedNormalized: - out << "UnsignedNormalized"; + out << "Norm"; break; case TextureType::SignedNormalized: - out << "SignedNormalized"; + out << "SNorm"; break; case TextureType::Float: - out << "Float"; + out << "F"; break; case TextureType::UnsignedInteger: - out << "UnsignedInteger"; + out << "UI"; break; case TextureType::SignedInteger: - out << "SignedInteger"; + out << "SI"; break; case TextureType::Depth: - out << "Depth"; + out << "D"; break; case TextureType::DepthStencilDepthMode: - out << "DepthStencilDepthMode"; + out << "DSD"; break; case TextureType::DepthStencilStencilMode: - out << "DepthStencilStencilMode"; + out << "DSS"; break; case TextureType::Stencil: - out << "Stencil"; + out << "S"; break; } @@ -106,7 +106,7 @@ std::ostream &operator<<(std::ostream &out, TextureCompareMode textureCompareMod switch (textureCompareMode) { case TextureCompareMode::None: - out << "None"; + out << "Non"; break; case TextureCompareMode::Ref: out << "Ref"; @@ -139,8 +139,8 @@ std::string IncompatibleTextureVariationsTestPrint( TextureCompareMode textureCompareMode; ParseIncompatibleTextureTestParams(params, &samplerType, &textureType, &textureCompareMode); - out << "__" << "SamplerType" << samplerType << "_" << "TextureType" << textureType << "_" - << "TextureCompareMode" << textureCompareMode; + out << "__" << "Sampler" << samplerType << "_" << "Tex" << textureType << "_" + << "Comp" << textureCompareMode; return out.str(); } @@ -171,6 +171,8 @@ TEST_P(IncompatibleTextureTest, Test) case SamplerType::Shadow: fragmentSource << "uniform mediump sampler2DShadow tex;\n"; break; + default: + UNREACHABLE(); } fragmentSource << "void main()\n" << "{\n"; fragmentSource << " my_FragColor = vec4(texture(tex, " diff --git a/src/tests/gl_tests/IndexBufferOffsetTest.cpp b/src/tests/gl_tests/IndexBufferOffsetTest.cpp index 69232cdda85..075cf30c515 100644 --- a/src/tests/gl_tests/IndexBufferOffsetTest.cpp +++ b/src/tests/gl_tests/IndexBufferOffsetTest.cpp @@ -6,6 +6,10 @@ // IndexBufferOffsetTest.cpp: Test glDrawElements with an offset and an index buffer +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/test_utils.h" diff --git a/src/tests/gl_tests/InstancingTest.cpp b/src/tests/gl_tests/InstancingTest.cpp index 6b2257bf059..8c886f684b9 100644 --- a/src/tests/gl_tests/InstancingTest.cpp +++ b/src/tests/gl_tests/InstancingTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/LineLoopTest.cpp b/src/tests/gl_tests/LineLoopTest.cpp index 9329fb6e3c6..696dde31e55 100644 --- a/src/tests/gl_tests/LineLoopTest.cpp +++ b/src/tests/gl_tests/LineLoopTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -409,6 +413,53 @@ TEST_P(LineLoopTest, DrawTriangleElementsBetweenArrays) checkPixels(); } +// Tests drawing elements with line loop arrays and drawing elements with line strip arrays and +// confirms the draws are the same. +TEST_P(LineLoopTest, SimpleDrawArrays) +{ + // http://anglebug.com/42265165: Disable D3D11 SDK Layers warnings checks. + ignoreD3D11SDKLayersWarnings(); + + static const GLfloat positions[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, -0.5f, -0.5f, -0.5f, -0.1f, 0.1f, + -0.1f, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f}; + + std::vector expectedPixels(getWindowWidth() * getWindowHeight()); + std::vector renderedPixels(getWindowWidth() * getWindowHeight()); + + GLBuffer arrayBuffer; + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW); + + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(mProgram); + glEnableVertexAttribArray(mPositionLocation); + glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + + glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f); + glDrawArrays(GL_LINE_STRIP, 0, 5); + glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, + expectedPixels.data()); + + glClear(GL_COLOR_BUFFER_BIT); + + glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f); + glDrawArrays(GL_LINE_LOOP, 0, 4); + glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, + renderedPixels.data()); + + for (int y = 0; y < getWindowHeight(); ++y) + { + for (int x = 0; x < getWindowWidth(); ++x) + { + int idx = y * getWindowWidth() + x; + EXPECT_EQ(expectedPixels[idx], renderedPixels[idx]) + << "Expected pixel at " << x << ", " << y << " to be " << expectedPixels[idx] + << std::endl; + } + } +} + class LineLoopTestES3 : public LineLoopTest {}; @@ -671,6 +722,25 @@ void main() } } +// Tests that drawing an element buffer with primitive restart indices only +// does not crash. +TEST_P(LineLoopPrimitiveRestartTest, PrimitiveRestartRestartOnlyIndicesNoCrash) +{ + constexpr char kVS[] = "void main() { gl_Position = vec4(0); }"; + constexpr char kFS[] = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + ASSERT_GL_NO_ERROR(); + std::vector indices(0x1000, static_cast(0xFFFFF)); + GLBuffer indexBuffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), &indices[0], + GL_STATIC_DRAW); + glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + glDrawElements(GL_LINE_LOOP, 0x800, GL_UNSIGNED_SHORT, 0); + ASSERT_GL_NO_ERROR(); +} + class LineLoopPrimitiveRestartXfbTest : public ANGLETest<> { protected: @@ -1281,14 +1351,114 @@ TEST_P(LineLoopIndirectTest, IndirectAndElementDrawsShareIndexBuffer) } } -ANGLE_INSTANTIATE_TEST_ES2_AND(LineLoopTest, ES2_WEBGPU()); +// Test that two indirect draws using glDrawArraysIndirect with GL_LINE_LOOP mode +// and different vertex ranges work correctly. +TEST_P(LineLoopIndirectTest, TwoIndirectDrawsInDifferentIndirectBuffer) +{ + // EXT_geometry_shader allows transform feedback to work with draw indirect. + // Otherwise, INVALID_OPERATION will be generated. + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + GLVertexArray vertexArray; + GLBuffer vertexBuffer, xfbBuffer, indirectBuffer[2]; + const std::vector vertices = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; + const std::vector expected = { + 2.0, 1.0, 4.0, 4.0, 4.0, 4.0, 6.0, 9.0, 6.0, 9.0, 8.0, 16.0, 8.0, 16.0, + 2.0, 1.0, 10.0, 25.0, 12.0, 36.0, 12.0, 36.0, 14.0, 49.0, 14.0, 49.0, 10.0, 25.0}; + constexpr char kVS[] = R"(#version 300 es +in float in_val; +out float out_val; +out float out_val2; + +void main() +{ + out_val = in_val * 2.0; + out_val2 = in_val * in_val; + gl_Position = vec4(in_val); +})"; + + constexpr char kFS[] = R"(#version 300 es +precision highp float; +in float out_val; +in float out_val2; +out vec4 fragColor; +void main() +{ + fragColor = vec4(1.0); +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + + std::vector varyings = {"out_val", "out_val2"}; + glTransformFeedbackVaryings(program, static_cast(varyings.size()), varyings.data(), + GL_INTERLEAVED_ATTRIBS); + glLinkProgram(program); + glUseProgram(program); + ASSERT_GL_NO_ERROR(); + + glBindVertexArray(vertexArray); + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), + GL_STATIC_DRAW); + ASSERT_GL_NO_ERROR(); + + GLuint pos = glGetAttribLocation(program, "in_val"); + glEnableVertexAttribArray(pos); + glVertexAttribPointer(pos, 1, GL_FLOAT, GL_FALSE, 0, 0); + ASSERT_GL_NO_ERROR(); + + std::vector initialData(expected.size(), 0.0); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, expected.size() * sizeof(GLfloat), + initialData.data(), GL_STATIC_READ); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer); + ASSERT_GL_NO_ERROR(); + + glBeginTransformFeedback(GL_LINES); + ASSERT_GL_NO_ERROR(); + + DrawCommand indirectDrawArgs1 = {}; + indirectDrawArgs1.count = 4; + indirectDrawArgs1.firstIndex = 0; + indirectDrawArgs1.primCount = 1; + DrawCommand indirectDrawArgs2 = {}; + indirectDrawArgs2.count = 3; + indirectDrawArgs2.firstIndex = 4; + indirectDrawArgs2.primCount = 1; + + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer[0]); + glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand), &indirectDrawArgs1, GL_STATIC_DRAW); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer[1]); + glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand), &indirectDrawArgs2, GL_STATIC_DRAW); + ASSERT_GL_NO_ERROR(); + + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer[0]); + glDrawArraysIndirect(GL_LINE_LOOP, nullptr); + ASSERT_GL_NO_ERROR(); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer[1]); + glDrawArraysIndirect(GL_LINE_LOOP, nullptr); + ASSERT_GL_NO_ERROR(); + + glEndTransformFeedback(); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer); + GLfloat *mapped = (GLfloat *)glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, + expected.size() * sizeof(float), GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + for (size_t i = 0; i < expected.size(); i++) + { + EXPECT_EQ(mapped[i], expected[i]); + } +} +ANGLE_INSTANTIATE_TEST_ES2_AND(LineLoopTest, + ES2_OPENGLES().enable(Feature::ForcePassthroughShaders)); ANGLE_INSTANTIATE_TEST_ES3(LineLoopTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LineLoopPrimitiveRestartTest); ANGLE_INSTANTIATE_TEST_ES3_AND( LineLoopPrimitiveRestartTest, ES3_METAL().enable(Feature::ForceBufferGPUStorage), - ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass)); + ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass), + ES3_WEBGPU()); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LineLoopIndirectTest); ANGLE_INSTANTIATE_TEST_ES31(LineLoopIndirectTest); diff --git a/src/tests/gl_tests/MaxTextureSizeTest.cpp b/src/tests/gl_tests/MaxTextureSizeTest.cpp index f91601688f8..25288603b4f 100644 --- a/src/tests/gl_tests/MaxTextureSizeTest.cpp +++ b/src/tests/gl_tests/MaxTextureSizeTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "test_utils/ANGLETest.h" diff --git a/src/tests/gl_tests/MemoryBarrierTest.cpp b/src/tests/gl_tests/MemoryBarrierTest.cpp index 424e26dd5be..9a1db618d89 100644 --- a/src/tests/gl_tests/MemoryBarrierTest.cpp +++ b/src/tests/gl_tests/MemoryBarrierTest.cpp @@ -28,6 +28,11 @@ // In summary, every bit defines a memory barrier for some access after a shader write. // Additionally, SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT bits are used to // define a memory barrier for shader writes after other accesses. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/MemoryObjectTest.cpp b/src/tests/gl_tests/MemoryObjectTest.cpp index d831c9a5eb6..33fd81d7530 100644 --- a/src/tests/gl_tests/MemoryObjectTest.cpp +++ b/src/tests/gl_tests/MemoryObjectTest.cpp @@ -6,6 +6,10 @@ // MemoryObjectTest.cpp : Tests of the GL_EXT_memory_object extension. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -78,6 +82,17 @@ TEST_P(MemoryObjectTest, MemoryObjectQueries) // http://anglebug.com/42263921 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL()); + // Validate that configuring or querying memory object zero fails + { + GLint dedicatedMemory = GL_TRUE; + glMemoryObjectParameterivEXT(0, GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicatedMemory); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glGetMemoryObjectParameterivEXT(0, GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicatedMemory); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + EXPECT_EQ(dedicatedMemory, GL_TRUE); + } + GLMemoryObject memoryObject; // Validate that the initial state of GL_DEDICATED_MEMORY_OBJECT_EXT is GL_FALSE diff --git a/src/tests/gl_tests/MemorySizeTest.cpp b/src/tests/gl_tests/MemorySizeTest.cpp index 83768b994e0..56dd9808e28 100644 --- a/src/tests/gl_tests/MemorySizeTest.cpp +++ b/src/tests/gl_tests/MemorySizeTest.cpp @@ -62,6 +62,16 @@ TEST_P(MemorySizeTest, BasicUsageTexture) EXPECT_GL_NO_ERROR(); EXPECT_GT(result, 0); } + else if (EnsureGLExtensionEnabled("GL_ANGLE_get_tex_level_parameter")) + { + glGetTexLevelParameterivANGLE(GL_TEXTURE_2D, 1, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(0, result); + + glGetTexLevelParameterivANGLE(GL_TEXTURE_2D, 0, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_GT(result, 0); + } } // Test basic queries of buffers @@ -134,5 +144,5 @@ TEST_P(MemorySizeTest, BasicUsageRenderbuffer) // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MemorySizeTest); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_ES32(MemorySizeTest); } // namespace angle diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp index 182f77671e6..ce2a53de122 100644 --- a/src/tests/gl_tests/MipmapTest.cpp +++ b/src/tests/gl_tests/MipmapTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -562,6 +566,31 @@ TEST_P(MipmapTestES3, GenerateMipmap1x1Texture) verifyAllMips(kTextureSize, kTextureSize, kInitialColor[0]); } +// This test generates mipmaps twice in a row. +TEST_P(MipmapTestES3, GenerateMipmapTwice) +{ + constexpr uint32_t kTextureSize = 1024; + + const std::vector kInitialColor(kTextureSize * kTextureSize, + GLColor(35, 81, 184, 211)); + + // Create the texture. + glBindTexture(GL_TEXTURE_2D, mTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, + GL_UNSIGNED_BYTE, kInitialColor.data()); + + // Then generate the mips twice. + glGenerateMipmap(GL_TEXTURE_2D); + glGenerateMipmap(GL_TEXTURE_2D); + ASSERT_GL_NO_ERROR(); + + // Enable mipmaps. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + + // Verify that every mip is correct. + verifyAllMips(kTextureSize, kTextureSize, kInitialColor[0]); +} + // This test generates mipmaps for a large texture and ensures all mips are generated. TEST_P(MipmapTestES3, GenerateMipmapLargeTexture) { @@ -1503,6 +1532,58 @@ TEST_P(MipmapTestES3, MipmapForDeepTextureArray) EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red); } +// Creates a mipmapped 3D texture with 1x1x2 size, GL_ALPHA, and calls GenerateMipmap. Should not +// crash. Tests the case where the format is non-renderable and depth has more mip levels than +// width, height. +TEST_P(MipmapTestES3, MipmapsForTexture3DNonRenderableMoreMipLevelsInDepthNoCrash) +{ + int px = getWindowWidth() / 2; + int py = getWindowHeight() / 2; + + glUseProgram(m3DProgram); + EXPECT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_3D, mTexture); + uint8_t colors[] = {5, 200}; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage3D(GL_TEXTURE_3D, 0, GL_ALPHA, 1, 1, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &colors); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + EXPECT_GL_NO_ERROR(); + glGenerateMipmap(GL_TEXTURE_3D); + EXPECT_GL_NO_ERROR(); + + // Mipmap level 0 slice 0. + glUniform1f(mTexture3DLODUniformLocation, 0.); + glUniform1f(mTexture3DSliceUniformLocation, 0.25f); + drawQuad(m3DProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor(0, 0, 0, 5)); + glClear(GL_COLOR_BUFFER_BIT); + + // Mipmap level 0 slice 1. + glUniform1f(mTexture3DSliceUniformLocation, 0.75f); + drawQuad(m3DProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor(0, 0, 0, 200)); + + // Mipmap level 1 slice 0, the only slice. + glUniform1f(mTexture3DLODUniformLocation, 1.); + glUniform1f(mTexture3DSliceUniformLocation, 0.); + drawQuad(m3DProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + GLColor pixel; + glReadPixels(px, py, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel.data()); + GLColor err(0, 0, 0, 1); + // Nearest or box filtering implementation. + if (!(pixel.ExpectNear(GLColor(0, 0, 0, 5), err) || + pixel.ExpectNear(GLColor(0, 0, 0, 102), err) || + pixel.ExpectNear(GLColor(0, 0, 0, 200), err))) + { + FAIL() << "Unexpected pixel color: " << pixel; + } +} + // Creates a mipmapped 3D texture with two layers, and calls ANGLE's GenerateMipmap. // Then tests if the mipmaps are rendered correctly for all two layers. TEST_P(MipmapTestES3, MipmapsForTexture3D) @@ -2391,22 +2472,18 @@ TEST_P(MipmapTestES31, GenerateLowerMipsWithDraw) // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MipmapTest); - -namespace extraPlatforms -{ -ANGLE_INSTANTIATE_TEST(MipmapTest, - ES2_METAL().disable(Feature::AllowGenMultipleMipsPerPass), - ES2_OPENGLES().enable(Feature::UseIntermediateTextureForGenerateMipmap)); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( + MipmapTest, + ES2_METAL().disable(Feature::AllowGenMultipleMipsPerPass), + ES2_OPENGLES().enable(Feature::UseIntermediateTextureForGenerateMipmap)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Mipmap3DBoxFilterTest); ANGLE_INSTANTIATE_TEST(Mipmap3DBoxFilterTest, ES2_METAL(), ES2_METAL().disable(Feature::AllowGenMultipleMipsPerPass)); -} // namespace extraPlatforms GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MipmapTestES3); -ANGLE_INSTANTIATE_TEST_ES3(MipmapTestES3); +ANGLE_INSTANTIATE_TEST_ES3_AND(MipmapTestES3, ES3_WEBGPU()); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MipmapTestES31); ANGLE_INSTANTIATE_TEST_ES31(MipmapTestES31); diff --git a/src/tests/gl_tests/MultiDrawTest.cpp b/src/tests/gl_tests/MultiDrawTest.cpp index 61500942c08..a23b0979da4 100644 --- a/src/tests/gl_tests/MultiDrawTest.cpp +++ b/src/tests/gl_tests/MultiDrawTest.cpp @@ -131,7 +131,8 @@ struct DrawElementsIndirectCommand // more fully tested in InstancingTest.cpp. // Correct interaction with the instancing APIs is tested here by using scaling // and then instancing the array of quads over four quadrants on the screen. -class MultiDrawTest : public ANGLETestBase, public ::testing::TestWithParam +class MultiDrawTest : public ANGLETestBase, + public ::testing::WithParamInterface { protected: MultiDrawTest() @@ -154,9 +155,9 @@ class MultiDrawTest : public ANGLETestBase, public ::testing::TestWithParam(GetParam()) == DrawIDOption::UseDrawID; } + bool isDrawIDTest() const { return std::get<1>(GetParam()) == DrawIDOption::UseDrawID; } - bool IsInstancedTest() const + bool isInstancedTest() const { return std::get<2>(GetParam()) == InstancingOption::UseInstancing; } @@ -167,18 +168,39 @@ class MultiDrawTest : public ANGLETestBase, public ::testing::TestWithParam instanceCounts(kTriCount, 4); glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, firsts.data(), counts.data(), instanceCounts.data(), kTriCount); @@ -334,7 +421,7 @@ void main() } } - void DoDrawElements() + void doDrawElements() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); @@ -349,12 +436,12 @@ void main() indices[i] = reinterpret_cast(static_cast(i * 3 * 2)); } - if (IsInstancedTest()) + if (isInstancedTest()) { glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer); glEnableVertexAttribArray(mInstanceLoc); glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr); - DoVertexAttribDivisor(mInstanceLoc, 1); + doVertexAttribDivisor(mInstanceLoc, 1); std::vector instanceCounts(kTriCount, 4); glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, indices.data(), instanceCounts.data(), kTriCount); @@ -373,7 +460,7 @@ void main() UseDrawID, }; - void CheckDrawResult(DrawIDOptionOverride overrideDrawID) + void checkDrawResult(DrawIDOptionOverride overrideDrawID) { for (uint32_t y = 0; y < kCountY; ++y) { @@ -381,7 +468,7 @@ void main() { uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2; uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2; - uint32_t quadID = IsDrawIDTest() && overrideDrawID != DrawIDOptionOverride::NoDrawID + uint32_t quadID = isDrawIDTest() && overrideDrawID != DrawIDOptionOverride::NoDrawID ? y * kCountX + x : 0; uint32_t colorID = quadID % 3u; @@ -389,7 +476,7 @@ void main() GLColor(0, 0, 255, 255)}; GLColor expected = colors[colorID]; - if (IsInstancedTest()) + if (isInstancedTest()) { EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4, center_y / 2 - kPixelCheckSize[1] / 4, @@ -448,7 +535,7 @@ void main() bool requestExtensions() { - if (IsInstancedTest() && getClientMajorVersion() <= 2) + if (isInstancedTest() && getClientMajorVersion() <= 2) { if (!requestInstancedExtension()) { @@ -471,14 +558,17 @@ void main() }; class MultiDrawTestES3 : public MultiDrawTest -{}; +{ + protected: + bool isES3() override { return true; } +}; class MultiDrawNoInstancingSupportTest : public MultiDrawTest { void SetUp() override { ASSERT_LE(getClientMajorVersion(), 2); - ASSERT_TRUE(IsInstancedTest()); + ASSERT_TRUE(isInstancedTest()); MultiDrawTest::SetUp(); } }; @@ -488,7 +578,7 @@ class MultiDrawNoInstancingSupportTest : public MultiDrawTest // 4 magenta triangles are drawn at the corners of the screen // in different orders from the same vertex and index arrays. class MultiDrawIndirectTest : public ANGLETestBase, - public ::testing::TestWithParam + public ::testing::WithParamInterface { protected: MultiDrawIndirectTest() @@ -589,7 +679,48 @@ void main() TEST_P(MultiDrawTest, CanCompile) { ANGLE_SKIP_TEST_IF(!requestExtensions()); - SetupProgram(); + setupProgram(); +} + +// Tests basic drawcount validation +TEST_P(MultiDrawTest, Validation) +{ + ANGLE_SKIP_TEST_IF(!requestMultiDrawExtension()); + + const GLint first = 0; + const GLsizei count = 0; + const GLvoid *const indices[1]{nullptr}; + + glMultiDrawArraysANGLE(GL_TRIANGLES, &first, &count, -1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glMultiDrawArraysANGLE(GL_TRIANGLES, &first, &count, 0); + EXPECT_GL_NO_ERROR(); + + glMultiDrawElementsANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, indices, -1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glMultiDrawElementsANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, indices, 0); + EXPECT_GL_NO_ERROR(); + + if (isInstancedTest()) + { + const GLsizei instances = 0; + + glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, &first, &count, &instances, -1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, &first, &count, &instances, 0); + EXPECT_GL_NO_ERROR(); + + glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, indices, + &instances, -1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, indices, + &instances, 0); + EXPECT_GL_NO_ERROR(); + } } // Tests basic functionality of glMultiDrawArraysANGLE @@ -598,13 +729,13 @@ TEST_P(MultiDrawTest, MultiDrawArrays) ANGLE_SKIP_TEST_IF(!requestExtensions()); // http://anglebug.com/40644769 - ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); + ANGLE_SKIP_TEST_IF(isInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); - SetupBuffers(); - SetupProgram(); - DoDrawArrays(); + setupBuffers(); + setupProgram(); + doDrawArrays(); EXPECT_GL_NO_ERROR(); - CheckDrawResult(DrawIDOptionOverride::Default); + checkDrawResult(DrawIDOptionOverride::Default); } // Tests basic functionality of glMultiDrawArraysANGLE after a failed program relink @@ -613,10 +744,10 @@ TEST_P(MultiDrawTestES3, MultiDrawArraysAfterFailedRelink) ANGLE_SKIP_TEST_IF(!requestExtensions()); // http://anglebug.com/40644769 - ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); + ANGLE_SKIP_TEST_IF(isInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); - SetupBuffers(); - SetupProgram(); + setupBuffers(); + setupProgram(); // mProgram is already installed. Destroy its state by a failed relink. const char *tfVaryings = "invalidvaryingname"; @@ -627,20 +758,66 @@ TEST_P(MultiDrawTestES3, MultiDrawArraysAfterFailedRelink) ASSERT_GL_NO_ERROR(); ASSERT_EQ(linkStatus, GL_FALSE); - DoDrawArrays(); + doDrawArrays(); EXPECT_GL_NO_ERROR(); - CheckDrawResult(DrawIDOptionOverride::Default); + checkDrawResult(DrawIDOptionOverride::Default); } // Tests basic functionality of glMultiDrawElementsANGLE TEST_P(MultiDrawTest, MultiDrawElements) { ANGLE_SKIP_TEST_IF(!requestExtensions()); - SetupBuffers(); - SetupProgram(); - DoDrawElements(); + setupBuffers(); + setupProgram(); + doDrawElements(); EXPECT_GL_NO_ERROR(); - CheckDrawResult(DrawIDOptionOverride::Default); + checkDrawResult(DrawIDOptionOverride::Default); +} + +// Bool uniform does not have a precision. If the "uniform sort by precision" places bool uniform +// in front of uniforms added by ANGLE (e.g. ANGLE_angle_DrawID), it can cause uniforms not +// interpreted correctly on Mac. e.g. http://crbug.com/437678149 For example, following uniform +// order can cause _umodelViewMatrix not being read correctly +// struct ANGLE_UserUniforms { +// bool _uapplyOffset; +// int ANGLE_angle_DrawID; +// metal::float4x4 _umodelViewMatrix; +// metal::float4x4 _uprojectionMatrix; +//} + +// Changing above to the following fix the bug on Mac +// struct ANGLE_UserUniforms { +// int ANGLE_angle_DrawID; +// metal::float4x4 _umodelViewMatrix; +// metal::float4x4 _uprojectionMatrix; +// int _uapplyOffset; +//} +// Add a test that check "adding a bool uniform will not mess up other uniforms on Mac". +TEST_P(MultiDrawTest, MultiDrawElementsWithBoolUniforms) +{ + ANGLE_SKIP_TEST_IF(!requestExtensions()); + setupBuffers(); + mProgram = + CompileProgram(vertexShaderSourceWithUniforms().c_str(), fragmentShaderSource().c_str()); + EXPECT_GL_NO_ERROR(); + ASSERT_GE(mProgram, 1u); + glUseProgram(mProgram); + mPositionLoc = glGetAttribLocation(mProgram, "vPosition"); + mInstanceLoc = glGetAttribLocation(mProgram, "vInstance"); + GLint boolUniformLoc = glGetUniformLocation(mProgram, "boolUniform"); + glUniform1i(boolUniformLoc, true); + GLfloat colorId0UniformValue[4] = {1.0, 0.0, 0.0, 1.0}; + GLint colorId0UniformLoc = glGetUniformLocation(mProgram, "colorId0Uniform"); + glUniform4fv(colorId0UniformLoc, 1, colorId0UniformValue); + GLfloat colorId1UniformValue[4] = {0.0, 1.0, 0.0, 1.0}; + GLint colorId1UniformLoc = glGetUniformLocation(mProgram, "colorId1Uniform"); + glUniform4fv(colorId1UniformLoc, 1, colorId1UniformValue); + GLfloat colorId2UniformValue[4] = {0.0, 0.0, 1.0, 1.0}; + GLint colorId2UniformLoc = glGetUniformLocation(mProgram, "colorId2Uniform"); + glUniform4fv(colorId2UniformLoc, 1, colorId2UniformValue); + doDrawElements(); + EXPECT_GL_NO_ERROR(); + checkDrawResult(DrawIDOptionOverride::Default); } // Tests that glMultiDrawArraysANGLE followed by glDrawArrays works. gl_DrawID in the second call @@ -650,15 +827,15 @@ TEST_P(MultiDrawTest, MultiDrawArraysThenDrawArrays) ANGLE_SKIP_TEST_IF(!requestExtensions()); // http://anglebug.com/40644769 - ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); + ANGLE_SKIP_TEST_IF(isInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); - SetupBuffers(); - SetupProgram(); - DoDrawArrays(); + setupBuffers(); + setupProgram(); + doDrawArrays(); EXPECT_GL_NO_ERROR(); - CheckDrawResult(DrawIDOptionOverride::Default); + checkDrawResult(DrawIDOptionOverride::Default); - if (IsInstancedTest()) + if (isInstancedTest()) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_instanced_arrays") && !IsGLExtensionEnabled("GL_ANGLE_instanced_arrays")); @@ -677,7 +854,7 @@ TEST_P(MultiDrawTest, MultiDrawArraysThenDrawArrays) glDrawArrays(GL_TRIANGLES, 0, 3 * kTriCount); ASSERT_GL_NO_ERROR(); } - CheckDrawResult(DrawIDOptionOverride::NoDrawID); + checkDrawResult(DrawIDOptionOverride::NoDrawID); } // Tests basic functionality of glMultiDrawArraysIndirectEXT @@ -1215,8 +1392,8 @@ TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation) { ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays")); requestMultiDrawExtension(); - SetupBuffers(); - SetupProgram(); + setupBuffers(); + setupProgram(); GLint first = 0; GLsizei count = 3; @@ -1240,6 +1417,110 @@ TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation) EXPECT_GL_ERROR(GL_INVALID_OPERATION); } +// Test that a no-op multi-draw call does not leave deferred clears around in the backends that do +// that. +TEST_P(MultiDrawTest, ClearThenNoopMultiDraw) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_multi_draw")); + + setupProgram(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + GLRenderbuffer rbo; + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + ASSERT_GL_NO_ERROR(); + + // Clear the framebuffer first; this clear may be deferred. + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + // Issue a multi-draw call that is no-op + constexpr GLsizei kDrawCount = 3; + GLsizei counts[kDrawCount] = {}; + const void *indices[kDrawCount] = {}; + glMultiDrawElementsANGLE(GL_TRIANGLES, counts, GL_UNSIGNED_BYTE, indices, kDrawCount); + + // Modify the framebuffer so it's sync'ed again on the next call. + GLRenderbuffer rbo2; + glBindRenderbuffer(GL_RENDERBUFFER, rbo2); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 8, 8); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo2); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + ASSERT_GL_NO_ERROR(); + + // Issue any command that uses the framebuffer. + glClear(GL_COLOR_BUFFER_BIT); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); +} + +class MultiDrawEmulationTest : public ANGLETest<> +{ + public: + MultiDrawEmulationTest() + { + setWindowWidth(16); + setWindowHeight(16); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +// gl_DrawID is translated to angle_DrawID internally. Check that a user-defined angle_DrawID is +// permitted. +TEST_P(MultiDrawEmulationTest, AllowsUserDefinedANGLEDrawID) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_multi_draw")); + + constexpr char kVS[] = R"(#extension GL_ANGLE_multi_draw : require +attribute vec2 position; +uniform int angle_DrawID; +varying vec4 verified; + +void main() +{ + // Expect gl_DrawID to be untouched when angle_DrawID is not. + verified = vec4(gl_DrawID == 0, 0, angle_DrawID == 3, 1); + gl_Position = vec4(position, 0, 1); +})"; + + constexpr char kFS[] = R"(precision mediump float; +varying vec4 verified; + +void main() +{ + gl_FragColor = verified; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + glUniform1i(glGetUniformLocation(program, "angle_DrawID"), 3); + + constexpr std::array kVertexData = { + -1, -1, 3, -1, -1, 3, + }; + + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData.data(), GL_STATIC_DRAW); + const GLint positionLoc = glGetAttribLocation(program, "position"); + glEnableVertexAttribArray(positionLoc); + glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); + + const GLint first = 0; + const GLint count = 3; + glMultiDrawArraysANGLE(GL_TRIANGLES, &first, &count, 1); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta); + ASSERT_GL_NO_ERROR(); +} + #define ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES2 \ ES2_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ ES2_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ @@ -1257,7 +1538,6 @@ TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation) ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions) #define ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3_1 \ - ES31_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ ES31_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ ES31_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ ES31_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \ @@ -1295,4 +1575,6 @@ ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawTestES3, GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiDrawIndirectTest); ANGLE_INSTANTIATE_TEST(MultiDrawIndirectTest, ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3_1); + +ANGLE_INSTANTIATE_TEST(MultiDrawEmulationTest, ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES2); } // namespace diff --git a/src/tests/gl_tests/MultisampleCompatibilityTest.cpp b/src/tests/gl_tests/MultisampleCompatibilityTest.cpp index a0e79a5a5d8..82abfe502dc 100644 --- a/src/tests/gl_tests/MultisampleCompatibilityTest.cpp +++ b/src/tests/gl_tests/MultisampleCompatibilityTest.cpp @@ -7,6 +7,10 @@ // Tests for the EXT_multisample_compatibility extension. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/MultisampledRenderToTextureTest.cpp b/src/tests/gl_tests/MultisampledRenderToTextureTest.cpp index 01b2bdf2dd8..29aca9d4213 100644 --- a/src/tests/gl_tests/MultisampledRenderToTextureTest.cpp +++ b/src/tests/gl_tests/MultisampledRenderToTextureTest.cpp @@ -4,7 +4,11 @@ // found in the LICENSE file. // -// MultisampledRenderToTextureTest: Tests of EXT_multisampled_render_to_texture extension +// MSRTTTest: Tests of EXT_multisampled_render_to_texture extension + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -30,10 +34,10 @@ std::string PrintToStringParamName( return ss.str(); } -class MultisampledRenderToTextureTest : public ANGLETest +class MSRTTTest : public ANGLETest { protected: - MultisampledRenderToTextureTest() + MSRTTTest() { setWindowWidth(64); setWindowHeight(64); @@ -182,7 +186,7 @@ class MultisampledRenderToTextureTest : public ANGLETest= 3; @@ -338,6 +342,11 @@ TEST_P(MultisampledRenderToTextureTest, Texture2DParameterCheck) ASSERT_GL_NO_ERROR(); EXPECT_GE(samples, 1); + // Samples negative + glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + texture, 0, -1); + ASSERT_GL_ERROR(GL_INVALID_VALUE); + // Samples too large glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0, samples + 1); @@ -356,7 +365,7 @@ TEST_P(MultisampledRenderToTextureTest, Texture2DParameterCheck) } // Checking against invalid parameters for FramebufferTexture2DMultisampleEXT (cubemap). -TEST_P(MultisampledRenderToTextureTest, TextureCubeMapParameterCheck) +TEST_P(MSRTTTest, TextureCubeMapParameterCheck) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); bool isES3 = getClientMajorVersion() >= 3; @@ -421,7 +430,7 @@ TEST_P(MultisampledRenderToTextureTest, TextureCubeMapParameterCheck) } // Checking for framebuffer completeness using extension methods. -TEST_P(MultisampledRenderToTextureTest, FramebufferCompleteness) +TEST_P(MSRTTTest, FramebufferCompleteness) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -468,10 +477,6 @@ TEST_P(MultisampledRenderToTextureTest, FramebufferCompleteness) colorRenderbuffer); EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // D3D backend doesn't implement multisampled render to texture renderbuffers correctly. - // http://anglebug.com/42261786 - ANGLE_SKIP_TEST_IF(IsD3D()); - if (getClientMajorVersion() >= 3 && EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")) { @@ -503,7 +508,7 @@ TEST_P(MultisampledRenderToTextureTest, FramebufferCompleteness) } // Checking for framebuffer completeness using extension methods. -TEST_P(MultisampledRenderToTextureTest, FramebufferCompletenessSmallSampleCount) +TEST_P(MSRTTTest, FramebufferCompletenessSmallSampleCount) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -544,7 +549,7 @@ TEST_P(MultisampledRenderToTextureTest, FramebufferCompletenessSmallSampleCount) // Test mixing unsized and sized formats with multisampling. Regression test for // http://crbug.com/1238327 -TEST_P(MultisampledRenderToTextureTest, UnsizedTextureFormatSampleMissmatch) +TEST_P(MSRTTTest, UnsizedTextureFormatSampleMissmatch) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_texture_rg")); @@ -574,14 +579,13 @@ TEST_P(MultisampledRenderToTextureTest, UnsizedTextureFormatSampleMissmatch) EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); } -void MultisampledRenderToTextureTest::createAndAttachColorAttachment( - bool useRenderbuffer, - GLsizei size, - GLenum renderbufferTarget, - const GLType *glType, - GLint samples, - GLTexture *textureOut, - GLRenderbuffer *renderbufferOut) +void MSRTTTest::createAndAttachColorAttachment(bool useRenderbuffer, + GLsizei size, + GLenum renderbufferTarget, + const GLType *glType, + GLint samples, + GLTexture *textureOut, + GLRenderbuffer *renderbufferOut) { GLenum internalFormat = glType ? glType->internalFormat : GL_RGBA; GLenum format = glType ? glType->format : GL_RGBA; @@ -610,11 +614,10 @@ void MultisampledRenderToTextureTest::createAndAttachColorAttachment( ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureTest::createAndAttachDepthStencilAttachment( - bool useRenderbuffer, - GLsizei size, - GLTexture *textureOut, - GLRenderbuffer *renderbufferOut) +void MSRTTTest::createAndAttachDepthStencilAttachment(bool useRenderbuffer, + GLsizei size, + GLTexture *textureOut, + GLRenderbuffer *renderbufferOut) { if (useRenderbuffer) { @@ -637,7 +640,7 @@ void MultisampledRenderToTextureTest::createAndAttachDepthStencilAttachment( ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureTest::colorAttachmentMultisampleDrawTestCommon(bool useRenderbuffer) +void MSRTTTest::colorAttachmentMultisampleDrawTestCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -695,19 +698,19 @@ void MultisampledRenderToTextureTest::colorAttachmentMultisampleDrawTestCommon(b } // Draw test with color attachment only. -TEST_P(MultisampledRenderToTextureTest, 2DColorAttachmentMultisampleDrawTest) +TEST_P(MSRTTTest, 2DColorAttachmentMultisampleDrawTest) { colorAttachmentMultisampleDrawTestCommon(false); } // Draw test with renderbuffer color attachment only -TEST_P(MultisampledRenderToTextureTest, RenderbufferColorAttachmentMultisampleDrawTest) +TEST_P(MSRTTTest, RenderbufferColorAttachmentMultisampleDrawTest) { colorAttachmentMultisampleDrawTestCommon(true); } // Test draw with a scissored region. -TEST_P(MultisampledRenderToTextureTest, ScissoredDrawTest) +TEST_P(MSRTTTest, ScissoredDrawTest) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -781,7 +784,7 @@ TEST_P(MultisampledRenderToTextureTest, ScissoredDrawTest) // Test transform feedback with state change. In the Vulkan backend, this results in an implicit // break of the render pass, and must work correctly with respect to the subpass index that's used. -TEST_P(MultisampledRenderToTextureES3Test, TransformFeedbackTest) +TEST_P(MSRTTES3Test, TransformFeedbackTest) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -851,7 +854,7 @@ TEST_P(MultisampledRenderToTextureES3Test, TransformFeedbackTest) } // Draw test using both color and depth attachments. -TEST_P(MultisampledRenderToTextureTest, 2DColorDepthMultisampleDrawTest) +TEST_P(MSRTTTest, 2DColorDepthMultisampleDrawTest) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -920,7 +923,7 @@ TEST_P(MultisampledRenderToTextureTest, 2DColorDepthMultisampleDrawTest) } // Draw test using color attachment with multiple levels. -TEST_P(MultisampledRenderToTextureTest, MultipleLevelsMultisampleDraw2DColor) +TEST_P(MSRTTTest, MultipleLevelsMultisampleDraw2DColor) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -974,7 +977,7 @@ TEST_P(MultisampledRenderToTextureTest, MultipleLevelsMultisampleDraw2DColor) } // Draw test using color attachment with multiple levels and multiple render targets. -TEST_P(MultisampledRenderToTextureES3Test, MultipleLevelsMultisampleMRTDraw2DColor) +TEST_P(MSRTTES3Test, MultipleLevelsMultisampleMRTDraw2DColor) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers")); @@ -1043,7 +1046,7 @@ TEST_P(MultisampledRenderToTextureES3Test, MultipleLevelsMultisampleMRTDraw2DCol EXPECT_PIXEL_COLOR_EQ((kSize >> 1) - 1, (kSize >> 1) - 1, GLColor::yellow); } -void MultisampledRenderToTextureES3Test::readPixelsTestCommon(bool useRenderbuffer) +void MSRTTES3Test::readPixelsTestCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -1082,22 +1085,18 @@ void MultisampledRenderToTextureES3Test::readPixelsTestCommon(bool useRenderbuff } // Read pixels with pack buffer. ES3+. -TEST_P(MultisampledRenderToTextureES3Test, ReadPixelsTest) +TEST_P(MSRTTES3Test, ReadPixelsTest) { readPixelsTestCommon(false); } // Read pixels with pack buffer from renderbuffer. ES3+. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferReadPixelsTest) +TEST_P(MSRTTES3Test, RenderbufferReadPixelsTest) { - // D3D backend doesn't implement multisampled render to texture renderbuffers correctly. - // http://anglebug.com/42261786 - ANGLE_SKIP_TEST_IF(IsD3D()); - readPixelsTestCommon(true); } -void MultisampledRenderToTextureTest::copyTexImageTestCommon(bool useRenderbuffer) +void MSRTTTest::copyTexImageTestCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 16; @@ -1132,18 +1131,18 @@ void MultisampledRenderToTextureTest::copyTexImageTestCommon(bool useRenderbuffe } // CopyTexImage from a multisampled texture functionality test. -TEST_P(MultisampledRenderToTextureTest, CopyTexImageTest) +TEST_P(MSRTTTest, CopyTexImageTest) { copyTexImageTestCommon(false); } // CopyTexImage from a multisampled texture functionality test using renderbuffer. -TEST_P(MultisampledRenderToTextureTest, RenderbufferCopyTexImageTest) +TEST_P(MSRTTTest, RenderbufferCopyTexImageTest) { copyTexImageTestCommon(true); } -void MultisampledRenderToTextureTest::copyTexSubImageTestCommon(bool useRenderbuffer) +void MSRTTTest::copyTexSubImageTestCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 16; @@ -1216,18 +1215,18 @@ void MultisampledRenderToTextureTest::copyTexSubImageTestCommon(bool useRenderbu } // CopyTexSubImage from a multisampled texture functionality test. -TEST_P(MultisampledRenderToTextureTest, CopyTexSubImageTest) +TEST_P(MSRTTTest, CopyTexSubImageTest) { copyTexSubImageTestCommon(false); } // CopyTexSubImage from a multisampled texture functionality test with renderbuffers -TEST_P(MultisampledRenderToTextureTest, RenderbufferCopyTexSubImageTest) +TEST_P(MSRTTTest, RenderbufferCopyTexSubImageTest) { copyTexSubImageTestCommon(true); } -void MultisampledRenderToTextureES3Test::blitFramebufferTestCommon(bool useRenderbuffer) +void MSRTTES3Test::blitFramebufferTestCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -1290,19 +1289,19 @@ void MultisampledRenderToTextureES3Test::blitFramebufferTestCommon(bool useRende } // BlitFramebuffer functionality test. ES3+. -TEST_P(MultisampledRenderToTextureES3Test, BlitFramebufferTest) +TEST_P(MSRTTES3Test, BlitFramebufferTest) { blitFramebufferTestCommon(false); } // BlitFramebuffer functionality test with renderbuffer. ES3+. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferBlitFramebufferTest) +TEST_P(MSRTTES3Test, RenderbufferBlitFramebufferTest) { blitFramebufferTestCommon(true); } // GenerateMipmap functionality test -TEST_P(MultisampledRenderToTextureTest, GenerateMipmapTest) +TEST_P(MSRTTTest, GenerateMipmapTest) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -1349,7 +1348,7 @@ TEST_P(MultisampledRenderToTextureTest, GenerateMipmapTest) ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureTest::drawCopyThenBlendCommon(bool useRenderbuffer) +void MSRTTTest::drawCopyThenBlendCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -1411,19 +1410,19 @@ void MultisampledRenderToTextureTest::drawCopyThenBlendCommon(bool useRenderbuff // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the // following draw should retain the data written by the first draw command. -TEST_P(MultisampledRenderToTextureTest, DrawCopyThenBlend) +TEST_P(MSRTTTest, DrawCopyThenBlend) { drawCopyThenBlendCommon(false); } // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the // following draw should retain the data written by the first draw command. Uses renderbuffer. -TEST_P(MultisampledRenderToTextureTest, RenderbufferDrawCopyThenBlend) +TEST_P(MSRTTTest, RenderbufferDrawCopyThenBlend) { drawCopyThenBlendCommon(true); } -void MultisampledRenderToTextureTest::clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer) +void MSRTTTest::clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -1509,21 +1508,20 @@ void MultisampledRenderToTextureTest::clearDrawCopyThenBlendSameProgramCommon(bo // operation). The same program is used for the first and second draw calls, and the fact that the // attachment is cleared or unresolved should not cause issues. In the Vulkan backend, the program // will be used in different subpass indices, so two graphics pipelines should be created for it. -TEST_P(MultisampledRenderToTextureTest, ClearDrawCopyThenBlendSameProgram) +TEST_P(MSRTTTest, ClearDrawCopyThenBlendSameProgram) { clearDrawCopyThenBlendSameProgramCommon(false); } // Same as ClearDrawCopyThenBlendSameProgram but with renderbuffers -TEST_P(MultisampledRenderToTextureTest, RenderbufferClearDrawCopyThenBlendSameProgram) +TEST_P(MSRTTTest, RenderbufferClearDrawCopyThenBlendSameProgram) { clearDrawCopyThenBlendSameProgramCommon(true); } // Similar to RenderbufferClearDrawCopyThenBlendSameProgram, but with the depth/stencil attachment // being unresolved only. -TEST_P(MultisampledRenderToTextureES3Test, - RenderbufferClearDrawCopyThenBlendWithDepthStencilSameProgram) +TEST_P(MSRTTES3Test, RenderbufferClearDrawCopyThenBlendWithDepthStencilSameProgram) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -1638,7 +1636,7 @@ TEST_P(MultisampledRenderToTextureES3Test, ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureTest::drawCopyDrawThenMaskedClearCommon(bool useRenderbuffer) +void MSRTTTest::drawCopyDrawThenMaskedClearCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -1704,19 +1702,18 @@ void MultisampledRenderToTextureTest::drawCopyDrawThenMaskedClearCommon(bool use // happens. The second draw should retain the data written by the first draw command ("unresolve" // operation). The final clear uses a draw call to perform the clear in the Vulkan backend, and it // should use the correct subpass index. -TEST_P(MultisampledRenderToTextureTest, DrawCopyDrawThenMaskedClear) +TEST_P(MSRTTTest, DrawCopyDrawThenMaskedClear) { drawCopyDrawThenMaskedClearCommon(false); } // Same as DrawCopyDrawThenMaskedClearCommon but with renderbuffers -TEST_P(MultisampledRenderToTextureTest, RenderbufferDrawCopyDrawThenMaskedClear) +TEST_P(MSRTTTest, RenderbufferDrawCopyDrawThenMaskedClear) { drawCopyDrawThenMaskedClearCommon(true); } -void MultisampledRenderToTextureES3Test::drawCopyDrawAttachInvalidatedThenDrawCommon( - bool useRenderbuffer) +void MSRTTES3Test::drawCopyDrawAttachInvalidatedThenDrawCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -1810,13 +1807,13 @@ void MultisampledRenderToTextureES3Test::drawCopyDrawAttachInvalidatedThenDrawCo // color. Attaching an invalidated image changes the framebuffer, and the following draw doesn't // require an unresolve. In the Vulkan backend, mismatches in unresolve state between framebuffer // and render pass will result in an ASSERT. -TEST_P(MultisampledRenderToTextureES3Test, DrawCopyDrawAttachInvalidatedThenDraw) +TEST_P(MSRTTES3Test, DrawCopyDrawAttachInvalidatedThenDraw) { drawCopyDrawAttachInvalidatedThenDrawCommon(false); } // Same as DrawCopyDrawAttachInvalidatedThenDraw but with renderbuffers -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawCopyDrawAttachInvalidatedThenDraw) +TEST_P(MSRTTES3Test, RenderbufferDrawCopyDrawAttachInvalidatedThenDraw) { drawCopyDrawAttachInvalidatedThenDrawCommon(true); } @@ -1826,7 +1823,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawCopyDrawAttachInvalid // existence was masked out by mistake in the framebuffer cache key, so the same framebuffer object // was used for both render passes, even though they could have different subpass counts due to // stencil unresolve. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawStencilThenUnresolveStencil) +TEST_P(MSRTTES3Test, RenderbufferDrawStencilThenUnresolveStencil) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -1897,8 +1894,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawStencilThenUnresolveS ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureES3Test::drawCopyDrawAttachDepthStencilClearThenDrawCommon( - bool useRenderbuffer) +void MSRTTES3Test::drawCopyDrawAttachDepthStencilClearThenDrawCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); // Use glFramebufferTexture2DMultisampleEXT for depth/stencil texture is only supported with @@ -1907,9 +1903,6 @@ void MultisampledRenderToTextureES3Test::drawCopyDrawAttachDepthStencilClearThen !EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); constexpr GLsizei kSize = 64; - // http://anglebug.com/42263509 - ANGLE_SKIP_TEST_IF(IsD3D11()); - setupCopyTexProgram(); GLFramebuffer fboMS; @@ -1995,13 +1988,13 @@ void MultisampledRenderToTextureES3Test::drawCopyDrawAttachDepthStencilClearThen // color. Attaching depth/stencil changes the framebuffer, and the following clear ensures no // unresolve is necessary. In the Vulkan backend, mismatches in unresolve state between framebuffer // and render pass will result in an ASSERT. -TEST_P(MultisampledRenderToTextureES3Test, DrawCopyDrawAttachDepthStencilClearThenDraw) +TEST_P(MSRTTES3Test, DrawCopyDrawAttachDepthStencilClearThenDraw) { drawCopyDrawAttachDepthStencilClearThenDrawCommon(false); } // Same as DrawCopyDrawAttachDepthStencilClearThenDraw but with renderbuffers -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawCopyDrawAttachDepthStencilClearThenDraw) +TEST_P(MSRTTES3Test, RenderbufferDrawCopyDrawAttachDepthStencilClearThenDraw) { drawCopyDrawAttachDepthStencilClearThenDrawCommon(true); } @@ -2012,7 +2005,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawCopyDrawAttachDepthSt // second copy resolves the clear and the final draw unresolves again. In the Vulkan backend, // mismatches in unresolve state between framebuffer and render pass will result in an ASSERT and a // validation error (if ASSERT is removed). -TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRedefineClearCopyThenDraw) +TEST_P(MSRTTES3Test, DrawCopyRedefineClearCopyThenDraw) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -2093,7 +2086,7 @@ TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRedefineClearCopyThenDraw) // the final draw from doing an unresolve. In the Vulkan backend, mismatches in unresolve state // between framebuffer and render pass will result in an ASSERT and a validation error (if ASSERT is // removed). -TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRebindAttachmentClearThenDraw) +TEST_P(MSRTTES3Test, DrawCopyRebindAttachmentClearThenDraw) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -2171,7 +2164,7 @@ TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRebindAttachmentClearThenDraw ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureTest::clearThenBlendCommon(bool useRenderbuffer) +void MSRTTTest::clearThenBlendCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -2214,18 +2207,18 @@ void MultisampledRenderToTextureTest::clearThenBlendCommon(bool useRenderbuffer) } // Clear then blend. The clear should be applied correctly. -TEST_P(MultisampledRenderToTextureTest, ClearThenBlend) +TEST_P(MSRTTTest, ClearThenBlend) { clearThenBlendCommon(false); } // Clear then blend. The clear should be applied correctly. Uses renderbuffer. -TEST_P(MultisampledRenderToTextureTest, RenderbufferClearThenBlend) +TEST_P(MSRTTTest, RenderbufferClearThenBlend) { clearThenBlendCommon(true); } -void MultisampledRenderToTextureES3Test::depthStencilClearThenDrawCommon(bool useRenderbuffer) +void MSRTTES3Test::depthStencilClearThenDrawCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); if (!useRenderbuffer) @@ -2287,13 +2280,13 @@ void MultisampledRenderToTextureES3Test::depthStencilClearThenDrawCommon(bool us } // Clear depth stencil, then draw. The clear should be applied correctly. -TEST_P(MultisampledRenderToTextureES3Test, DepthStencilClearThenDraw) +TEST_P(MSRTTES3Test, DepthStencilClearThenDraw) { depthStencilClearThenDrawCommon(false); } // Clear depth stencil, then draw. The clear should be applied correctly. Uses renderbuffer. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearThenDraw) +TEST_P(MSRTTES3Test, RenderbufferDepthStencilClearThenDraw) { depthStencilClearThenDrawCommon(true); } @@ -2302,7 +2295,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearThenDraw // tests uses a depth/stencil buffer and makes sure the second draw (in the second render pass) // succeeds (i.e. depth/stencil data is not lost). Note that this test doesn't apply to // depth/stencil textures as they are explicitly autoinvalidated between render passes. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearDrawCopyThenBlend) +TEST_P(MSRTTES3Test, RenderbufferDepthStencilClearDrawCopyThenBlend) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -2391,7 +2384,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearDrawCopy // with RenderbufferDepthStencilClearDrawCopyThenBlend is that color is cleared in the second render // pass, so only depth/stencil data is unresolved. This test doesn't apply to depth/stencil // textures as they are explicitly autoinvalidated between render passes. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilDrawCopyClearThenBlend) +TEST_P(MSRTTES3Test, RenderbufferDepthStencilDrawCopyClearThenBlend) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -2493,14 +2486,10 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilDrawCopyClear // Clear, then blit depth/stencil with renderbuffers. This test makes sure depth/stencil blit uses // the correct image. Note that this test doesn't apply to depth/stencil textures as they are // explicitly autoinvalidated between render passes. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferClearThenBlitDepthStencil) +TEST_P(MSRTTES3Test, RenderbufferClearThenBlitDepthStencil) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); - // D3D backend doesn't implement multisampled render to texture renderbuffers correctly. - // http://anglebug.com/42261786 - ANGLE_SKIP_TEST_IF(IsD3D()); - constexpr GLsizei kSize = 64; setupCopyTexProgram(); @@ -2605,7 +2594,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferClearThenBlitDepthStencil // Draw, then blit depth/stencil with renderbuffers. This test makes sure depth/stencil resolve is // correctly implemented. Note that this test doesn't apply to depth/stencil textures as they are // explicitly autoinvalidated between render passes. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencil) +TEST_P(MSRTTES3Test, RenderbufferDrawThenBlitDepthStencil) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -2694,6 +2683,101 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencil) EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red); } +// Makes sure that mixed drawing/reading into/from the same texture using multisampled and single +// sampled framebuffers produce expected results. +TEST_P(MSRTTES3Test, MixedMultisampleSingleSampledDraw) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); + + constexpr GLsizei kSize = 64; + + // Create render target texture. + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + + // Create multisampled framebuffer. + GLFramebuffer fboMS; + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, + 0, 4); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Create single sampled framebuffer. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Set up program + ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glUseProgram(drawColor); + GLint colorUniformLocation = + glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorUniformLocation, -1); + + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + + // Draw blue multisampled. + glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Draw red single sampled. + glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + + // Check that single sampled framebuffer is red. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red); + + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + + // Check that multisampled framebuffer is also red since it uses same texture. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Check that single sampled framebuffer is still red. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red); + + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + + // Draw green multisampled with scissor. + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, kSize / 2, kSize / 2); + glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Draw yellow single sampled with scissor. + glScissor(kSize / 2, kSize / 2, kSize / 2, kSize / 2); + glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f); + ASSERT_GL_NO_ERROR(); + + // Check that single sampled framebuffer contains expected colors. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::yellow); +} + // Draw, then blit depth/stencil with renderbuffers, without a color attachment. Note that this test // doesn't apply to depth/stencil textures as they are explicitly autoinvalidated between render // passes. @@ -2714,16 +2798,13 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencil) // +--------------------+ // // Blit is used again to copy the depth/stencil attachment data, and the result is verified. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencilOnly) +TEST_P(MSRTTES3Test, RenderbufferDrawThenBlitDepthStencilOnly) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); // http://anglebug.com/42263663 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan()); - // http://anglebug.com/42263677 - ANGLE_SKIP_TEST_IF(IsD3D()); - constexpr GLsizei kSize = 64; GLFramebuffer fboMS; @@ -2869,7 +2950,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencilO // Test the depth read/write mode change within the renderpass while there is color unresolve // attachment -TEST_P(MultisampledRenderToTextureTest, DepthReadWriteToggleWithStartedRenderPass) +TEST_P(MSRTTTest, DepthReadWriteToggleWithStartedRenderPass) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -2971,7 +3052,7 @@ TEST_P(MultisampledRenderToTextureTest, DepthReadWriteToggleWithStartedRenderPas EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::white); } -void MultisampledRenderToTextureES3Test::colorAttachment1Common(bool useRenderbuffer) +void MSRTTES3Test::colorAttachment1Common(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); @@ -3044,7 +3125,7 @@ void MultisampledRenderToTextureES3Test::colorAttachment1Common(bool useRenderbu // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the // following draw should retain the data written by the first draw command. // Uses color attachment 1. -TEST_P(MultisampledRenderToTextureES3Test, ColorAttachment1) +TEST_P(MSRTTES3Test, ColorAttachment1) { colorAttachment1Common(false); } @@ -3052,12 +3133,12 @@ TEST_P(MultisampledRenderToTextureES3Test, ColorAttachment1) // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the // following draw should retain the data written by the first draw command. // Uses color attachment 1. Uses renderbuffer. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferColorAttachment1) +TEST_P(MSRTTES3Test, RenderbufferColorAttachment1) { colorAttachment1Common(true); } -void MultisampledRenderToTextureES3Test::colorAttachments0And3Common(bool useRenderbuffer) +void MSRTTES3Test::colorAttachments0And3Common(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!useRenderbuffer && @@ -3164,7 +3245,7 @@ void MultisampledRenderToTextureES3Test::colorAttachments0And3Common(bool useRen // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the // following draw should retain the data written by the first draw command. // Uses color attachments 0 and 3. -TEST_P(MultisampledRenderToTextureES3Test, ColorAttachments0And3) +TEST_P(MSRTTES3Test, ColorAttachments0And3) { colorAttachments0And3Common(false); } @@ -3172,7 +3253,7 @@ TEST_P(MultisampledRenderToTextureES3Test, ColorAttachments0And3) // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the // following draw should retain the data written by the first draw command. // Uses color attachments 0 and 3. Uses renderbuffer. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferColorAttachments0And3) +TEST_P(MSRTTES3Test, RenderbufferColorAttachments0And3) { colorAttachments0And3Common(true); } @@ -3182,7 +3263,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferColorAttachments0And3) // different between top and bottom. The second draw call will enable depth test and draw with the // average of the two depths. Only half of the samples will take the new color. Once resolved, the // expected color would be the average of the two draw colors. -TEST_P(MultisampledRenderToTextureES3Test, DepthStencilAttachment) +TEST_P(MSRTTES3Test, DepthStencilAttachment) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); @@ -3254,7 +3335,7 @@ TEST_P(MultisampledRenderToTextureES3Test, DepthStencilAttachment) // pass. On desktop Windows AMD drivers, this would previously cause a crash // because of a NULL pDepthStencilResolveAttachment pointer when ending the // render pass. Other vendors don't seem to mind the NULL pointer. -TEST_P(MultisampledRenderToTextureES3Test, DepthStencilInvalidate) +TEST_P(MSRTTES3Test, DepthStencilInvalidate) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -3345,11 +3426,11 @@ TEST_P(MultisampledRenderToTextureES3Test, DepthStencilInvalidate) glBindBuffer(GL_ARRAY_BUFFER, 0); } -// Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the -// following draw should retain the data written by the first draw command. -// Uses color attachments 0 and 1. Attachment 0 is a normal multisampled texture, while attachment -// 1 is a multisampled-render-to-texture texture. -TEST_P(MultisampledRenderToTextureES31Test, MixedMultisampledAndMultisampledRenderToTexture) +// Draw, copy, then blend. The copy triggers an implicit resolve from the multisampled +// render-to-texture attachment. This test verifies that blending after a copy preserves the +// previously written data. Uses color attachments 0 and 1, both configured as multisampled +// render-to-texture (MSRTT) attachments. +TEST_P(MSRTTES31Test, DrawCopyThenBlendWithMultipleMSRTTAttachments) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); @@ -3359,22 +3440,21 @@ TEST_P(MultisampledRenderToTextureES31Test, MixedMultisampledAndMultisampledRend setupCopyTexProgram(); - // Create multisampled framebuffer to draw into, use color attachment 1 + // Create multisampled framebuffer to draw into, both attachments use MSRTT + GLFramebuffer fboMS; + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + GLTexture colorMS0; - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, colorMS0); - glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true); + GLRenderbuffer renderbufferMS0; + createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT0, nullptr, 4, &colorMS0, + &renderbufferMS0); GLTexture colorMS1; - glBindTexture(GL_TEXTURE_2D, colorMS1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + GLRenderbuffer renderbufferMS1; + createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT1, nullptr, 4, &colorMS1, + &renderbufferMS1); - GLFramebuffer fboMS; - glBindFramebuffer(GL_FRAMEBUFFER, fboMS); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, - colorMS0, 0); - glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, - colorMS1, 0, 4); - ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Setup program to render into attachments 0 and 1. constexpr bool kBuffersEnabled[8] = {true, true}; @@ -3426,7 +3506,104 @@ TEST_P(MultisampledRenderToTextureES31Test, MixedMultisampledAndMultisampledRend glDeleteProgram(drawColor); } -void MultisampledRenderToTextureES31Test::blitFramebufferAttachment1Common(bool useRenderbuffer) +// Checking for framebuffer completeness mixing regular/MSRTT multisampled renderbuffers. +TEST_P(MSRTTES3Test, FramebufferCompletenessMixedMultisamplingMode) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); + + typedef struct AttachmentCombination + { + uint32_t attach1; // MultisamplingMode of the first surface: + // 0 == Regular; 1 == MultisampledRenderToTexture + uint32_t attach2; // MultisamplingMode of the second surface: + // 0 == Regular; 1 == MultisampledRenderToTexture + GLenum attach1Point; // The attachment point of the first surface + GLenum attach2Point; // The attachment point of the second surface + } AttachmentCombination; + + AttachmentCombination attachmentCombinations[] = { + // INVALID combinations + {0, 1, GL_COLOR_ATTACHMENT0, + GL_DEPTH_ATTACHMENT}, // first = Regular; second = MultisampledRenderToTexture + {0, 1, GL_COLOR_ATTACHMENT0, + GL_STENCIL_ATTACHMENT}, // first = Regular; second = MultisampledRenderToTexture + {1, 0, GL_COLOR_ATTACHMENT0, + GL_DEPTH_ATTACHMENT}, // first = MultisampledRenderToTexture; second = Regular + {1, 0, GL_COLOR_ATTACHMENT0, + GL_STENCIL_ATTACHMENT}, // first = MultisampledRenderToTexture; second = Regular + }; + + for (uint32_t i = 0; i < sizeof(attachmentCombinations) / sizeof((attachmentCombinations)[0]); + i++) + { + GLsizei samples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &samples); + + // Texture attachment for color attachment 0. Framebuffer should be complete. + GLFramebuffer FBO; + glBindFramebuffer(GL_FRAMEBUFFER, FBO); + + GLRenderbuffer colorRenderbuffer; + glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); + if (attachmentCombinations[i].attach1 == 0) + { + // Regular multisampling + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA4, 64, 64); + } + else + { + // Multisampled render to texture + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA4, 64, 64); + } + ASSERT_GL_NO_ERROR(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentCombinations[i].attach1Point, + GL_RENDERBUFFER, colorRenderbuffer); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Depth/stencil renderbuffer, potentially with a different sample count. + GLRenderbuffer dsRenderbuffer; + glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbuffer); + if (attachmentCombinations[i].attach2 == 0) + { + // Regular multisampling mode + if (attachmentCombinations[i].attach2Point == GL_DEPTH_ATTACHMENT) + { + // GL_DEPTH_ATTACHMENT + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT16, 64, + 64); + } + else + { + // GL_STENCIL_ATTACHMENT + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, 64, + 64); + } + } + else + { + // Multisampled render to texture mode + if (attachmentCombinations[i].attach2Point == GL_DEPTH_ATTACHMENT) + { + // GL_DEPTH_ATTACHMENT + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT16, + 64, 64); + } + else + { + // GL_STENCIL_ATTACHMENT + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, + 64, 64); + } + } + ASSERT_GL_NO_ERROR(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentCombinations[i].attach2Point, + GL_RENDERBUFFER, dsRenderbuffer); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } +} + +void MSRTTES31Test::blitFramebufferAttachment1Common(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!useRenderbuffer && @@ -3438,17 +3615,17 @@ void MultisampledRenderToTextureES31Test::blitFramebufferAttachment1Common(bool GLFramebuffer fboMS; glBindFramebuffer(GL_FRAMEBUFFER, fboMS); - // Create multisampled framebuffer to draw into, use color attachment 1 - GLTexture colorMS0; - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, colorMS0); - glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, - colorMS0, 0); + // Create multisampled framebuffer to draw into, use MSRTT for both attachments + GLTexture textureMS0; + GLRenderbuffer renderbufferMS0; + createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr, + mTestSampleCount, &textureMS0, &renderbufferMS0); GLTexture textureMS1; GLRenderbuffer renderbufferMS1; createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT1, nullptr, mTestSampleCount, &textureMS1, &renderbufferMS1); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Setup program to render into attachments 0 and 1. @@ -3497,26 +3674,23 @@ void MultisampledRenderToTextureES31Test::blitFramebufferAttachment1Common(bool ASSERT_GL_NO_ERROR(); } -// BlitFramebuffer functionality test with mixed color attachments where multisampled render to -// texture as attachment 1 and is the read buffer. This test makes sure the fact that attachment 0 -// is a true multisampled texture doesn't cause issues. +// BlitFramebuffer functionality test with two MSRTT texture attachments. +// Verifies that blitting from attachment 1 works correctly and implicit resolve is triggered. // Uses EXT_multisampled_render_to_texture2. -TEST_P(MultisampledRenderToTextureES31Test, BlitFramebufferAttachment1) +TEST_P(MSRTTES31Test, BlitFramebufferAttachment1) { blitFramebufferAttachment1Common(false); } -// BlitFramebuffer functionality test with mixed color attachments where multisampled render to -// texture as attachment 1 and is the read buffer. This test makes sure the fact that attachment 0 -// is a true multisampled texture doesn't cause issues. +// BlitFramebuffer functionality test with two MSRTT renderbuffer attachments. +// Verifies that blitting from attachment 1 works correctly and implicit resolve is triggered. // Uses renderbuffer. -TEST_P(MultisampledRenderToTextureES31Test, RenderbufferBlitFramebufferAttachment1) +TEST_P(MSRTTES31Test, RenderbufferBlitFramebufferAttachment1) { blitFramebufferAttachment1Common(true); } -void MultisampledRenderToTextureES3Test::blitFramebufferMixedColorAndDepthCommon( - bool useRenderbuffer) +void MSRTTES3Test::blitFramebufferMixedColorAndDepthCommon(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -3596,7 +3770,7 @@ void MultisampledRenderToTextureES3Test::blitFramebufferMixedColorAndDepthCommon // BlitFramebuffer functionality test with mixed multisampled-render-to-texture color attachment and // multisampled depth buffer. This test makes sure that the color attachment is blitted, while // the depth/stencil attachment is resolved. -TEST_P(MultisampledRenderToTextureES3Test, BlitFramebufferMixedColorAndDepth) +TEST_P(MSRTTES3Test, BlitFramebufferMixedColorAndDepth) { blitFramebufferMixedColorAndDepthCommon(false); } @@ -3604,21 +3778,18 @@ TEST_P(MultisampledRenderToTextureES3Test, BlitFramebufferMixedColorAndDepth) // BlitFramebuffer functionality test with mixed multisampled-render-to-texture color attachment and // multisampled depth buffer. This test makes sure that the color attachment is blitted, while // the depth/stencil attachment is resolved. Uses renderbuffer. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferBlitFramebufferMixedColorAndDepth) +TEST_P(MSRTTES3Test, RenderbufferBlitFramebufferMixedColorAndDepth) { blitFramebufferMixedColorAndDepthCommon(true); } // Draw non-multisampled, draw multisampled, repeat. This tests the same texture being bound // differently to two FBOs. -TEST_P(MultisampledRenderToTextureTest, DrawNonMultisampledThenMultisampled) +TEST_P(MSRTTTest, DrawNonMultisampledThenMultisampled) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; - // http://anglebug.com/42263509 - ANGLE_SKIP_TEST_IF(IsD3D11()); - // Texture attachment to the two framebuffers. GLTexture color; glBindTexture(GL_TEXTURE_2D, color); @@ -3685,9 +3856,72 @@ TEST_P(MultisampledRenderToTextureTest, DrawNonMultisampledThenMultisampled) ASSERT_GL_NO_ERROR(); } +// Draw multisampled triangle with different sample counts on one single FBO. This test makes use of +// different sample results for different sample location to distinguish whether sample count truly +// changed or not. +TEST_P(MSRTTTest, DrawMultisampledDifferentSamplesOneFBO) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); + constexpr GLsizei kSize = 64; + + GLsizei maxSamples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + ANGLE_SKIP_TEST_IF(maxSamples <= 4); + + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + + GLFramebuffer fboMS; + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + + std::array attribPosData = {1, 1, 0.5, 1, -1, 1, 0.5, 1, + 1, -1, 0.5, 1, -1, -1, 0.5, 1}; + const uint16_t indices[] = {0, 1, 2}; + + // Refer to Vulkan spec Standard Sample Locations + const GLColor kExpected4(128, 0, 0, 255); + const GLColor kExpected8(159, 0, 0, 255); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + ANGLE_GL_PROGRAM(drawColorTriangle, essl1_shaders::vs::Simple(), + essl1_shaders::fs::UniformColor()); + glUseProgram(drawColorTriangle); + + GLint colorUniformLocation = + glGetUniformLocation(drawColorTriangle, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorUniformLocation, -1); + glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f); + + GLint positionUniformLocation = + glGetAttribLocation(drawColorTriangle, angle::essl1_shaders::PositionAttrib()); + ASSERT_NE(positionUniformLocation, -1); + glEnableVertexAttribArray(positionUniformLocation); + glVertexAttribPointer(positionUniformLocation, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data()); + + // First set sample count to 4. + glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, + 0, 4); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices); + EXPECT_PIXEL_COLOR_NEAR(kSize / 2 - 1, kSize / 2, kExpected4, 1); + + // Then set sample count to 8 without changing FBO. + glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, + 0, 8); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices); + EXPECT_PIXEL_COLOR_NEAR(kSize / 2 - 1, kSize / 2, kExpected8, 1); + + ASSERT_GL_NO_ERROR(); +} + // Draw multisampled, draw multisampled with another sample count, repeat. This tests the same // texture being bound as multisampled-render-to-texture with different sample counts to two FBOs. -TEST_P(MultisampledRenderToTextureTest, DrawMultisampledDifferentSamples) +TEST_P(MSRTTTest, DrawMultisampledDifferentSamples) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); constexpr GLsizei kSize = 64; @@ -3764,7 +3998,7 @@ TEST_P(MultisampledRenderToTextureTest, DrawMultisampledDifferentSamples) ASSERT_GL_NO_ERROR(); } -void MultisampledRenderToTextureES31Test::drawCopyThenBlendAllAttachmentsMixed(bool useRenderbuffer) +void MSRTTES31Test::drawCopyThenBlendAllAttachmentsMixed(bool useRenderbuffer) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); @@ -3927,13 +4161,13 @@ precision highp float; // Draw, copy, then blend with 8 mixed format attachments. The copy will make sure an implicit // resolve happens. Regardless, the following draw should retain the data written by the first draw // command. -TEST_P(MultisampledRenderToTextureES31Test, DrawCopyThenBlendAllAttachmentsMixed) +TEST_P(MSRTTES31Test, DrawCopyThenBlendAllAttachmentsMixed) { drawCopyThenBlendAllAttachmentsMixed(false); } // Same as DrawCopyThenBlendAllAttachmentsMixed but with renderbuffers. -TEST_P(MultisampledRenderToTextureES31Test, RenderbufferDrawCopyThenBlendAllAttachmentsMixed) +TEST_P(MSRTTES31Test, RenderbufferDrawCopyThenBlendAllAttachmentsMixed) { // Linux Intel Vulkan returns 0 for GL_MAX_INTEGER_SAMPLES http://anglebug.com/42264519 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan()); @@ -3941,9 +4175,8 @@ TEST_P(MultisampledRenderToTextureES31Test, RenderbufferDrawCopyThenBlendAllAtta drawCopyThenBlendAllAttachmentsMixed(true); } -void MultisampledRenderToTextureES3Test::renderbufferUnresolveColorAndDepthStencilThenTwoColors( - bool withDepth, - bool withStencil) +void MSRTTES3Test::renderbufferUnresolveColorAndDepthStencilThenTwoColors(bool withDepth, + bool withStencil) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); @@ -4118,26 +4351,26 @@ void MultisampledRenderToTextureES3Test::renderbufferUnresolveColorAndDepthStenc // color attachments. Tests that unresolve is done correctly on two framebuffers with the same // number of attachments, but differing in depth being there. Note that this test doesn't apply to // depth/stencil textures as they are explicitly autoinvalidated between render passes. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndDepthThenTwoColors) +TEST_P(MSRTTES3Test, RenderbufferUnresolveColorAndDepthThenTwoColors) { renderbufferUnresolveColorAndDepthStencilThenTwoColors(true, false); } // Similar to RenderbufferUnresolveColorAndDepthThenTwoColors, but with stencil. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndStencilThenTwoColors) +TEST_P(MSRTTES3Test, RenderbufferUnresolveColorAndStencilThenTwoColors) { renderbufferUnresolveColorAndDepthStencilThenTwoColors(false, true); } // Similar to RenderbufferUnresolveColorAndDepthThenTwoColors, but with depth and stencil. -TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndDepthStencilThenTwoColors) +TEST_P(MSRTTES3Test, RenderbufferUnresolveColorAndDepthStencilThenTwoColors) { renderbufferUnresolveColorAndDepthStencilThenTwoColors(true, true); } // Make sure deferred clears are flushed correctly when the framebuffer switches between // needing unresolve and not needing it. -TEST_P(MultisampledRenderToTextureES3Test, ClearThenMaskedClearFramebufferTest) +TEST_P(MSRTTES3Test, ClearThenMaskedClearFramebufferTest) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -4196,7 +4429,7 @@ TEST_P(MultisampledRenderToTextureES3Test, ClearThenMaskedClearFramebufferTest) } // Make sure mid render pass clear works correctly. -TEST_P(MultisampledRenderToTextureES3Test, RenderToTextureMidRenderPassDepthClear) +TEST_P(MSRTTES3Test, RenderToTextureMidRenderPassDepthClear) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); @@ -4265,7 +4498,7 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderToTextureMidRenderPassDepthClea ASSERT_GL_NO_ERROR(); } -class MultisampledRenderToTextureWithAdvancedBlendTest : public MultisampledRenderToTextureES3Test +class MultisampledRenderToTextureWithAdvancedBlendTest : public MSRTTES3Test { protected: enum class InitMethod @@ -4378,7 +4611,7 @@ TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest, RenderbufferClearThenDr } ANGLE_INSTANTIATE_TEST_COMBINE_1( - MultisampledRenderToTextureTest, + MSRTTTest, PrintToStringParamName, testing::Bool(), ANGLE_ALL_TEST_PLATFORMS_ES2, @@ -4395,9 +4628,9 @@ ANGLE_INSTANTIATE_TEST_COMBINE_1( ES3_VULKAN().disable(Feature::SupportsSPIRV14), ES3_VULKAN_SWIFTSHADER().enable(Feature::EnableMultisampledRenderToTexture)); -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampledRenderToTextureES3Test); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MSRTTES3Test); ANGLE_INSTANTIATE_TEST_COMBINE_1( - MultisampledRenderToTextureES3Test, + MSRTTES3Test, PrintToStringParamName, testing::Bool(), ANGLE_ALL_TEST_PLATFORMS_ES3, @@ -4412,9 +4645,9 @@ ANGLE_INSTANTIATE_TEST_COMBINE_1( ES3_VULKAN().disable(Feature::SupportsSPIRV14), ES3_VULKAN_SWIFTSHADER().enable(Feature::EnableMultisampledRenderToTexture)); -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampledRenderToTextureES31Test); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MSRTTES31Test); ANGLE_INSTANTIATE_TEST_COMBINE_1( - MultisampledRenderToTextureES31Test, + MSRTTES31Test, PrintToStringParamName, testing::Bool(), ANGLE_ALL_TEST_PLATFORMS_ES31, diff --git a/src/tests/gl_tests/MultithreadingTest.cpp b/src/tests/gl_tests/MultithreadingTest.cpp index be998864c7b..7d28662bf69 100644 --- a/src/tests/gl_tests/MultithreadingTest.cpp +++ b/src/tests/gl_tests/MultithreadingTest.cpp @@ -4,6 +4,11 @@ // found in the LICENSE file. // // MulithreadingTest.cpp : Tests of multithreaded rendering +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "test_utils/ANGLETest.h" #include "test_utils/MultiThreadSteps.h" @@ -281,6 +286,9 @@ TEST_P(MultithreadingTest, MultiContextDeleteDraw) EXPECT_EGL_TRUE(eglDestroyContext(dpy, ctx2)); EXPECT_EGL_TRUE(eglDestroyContext(dpy, ctx1)); + + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); } }); @@ -324,6 +332,9 @@ TEST_P(MultithreadingTest, MultiContextDeleteDraw) glDrawArrays(GL_TRIANGLES, 0, 6); } } + + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); }); t1.join(); @@ -483,6 +494,55 @@ TEST_P(MultithreadingTest, MultiContextCreateAndDeleteResources) runMultithreadedGLTest(testBody, 32); } +// Test that changing sampler parameters of textures in unrelated share groups is thread-safe. +// Regression test for a bug in the Vulkan backend where the VkSampler cache was not thread-safe. +TEST_P(MultithreadingTestES3, MultiContextTextureSampleParameters) +{ + ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading()); + + constexpr size_t kThreadCount = 16; + std::atomic barrier(0); + + auto testBody = [this, &barrier](EGLSurface surface, size_t thread) { + constexpr size_t kIterationsPerThread = 32; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + glUseProgram(program); + glUseProgram(program); + GLint textureUniformLocation = + glGetUniformLocation(program, angle::essl1_shaders::Texture2DUniform()); + ASSERT_NE(textureUniformLocation, -1); + glUniform1i(textureUniformLocation, 0); + glActiveTexture(GL_TEXTURE0); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); + + barrier++; + while (barrier < kThreadCount) + { + } + + for (size_t iteration = 0; iteration < kIterationsPerThread; iteration++) + { + // Change the sampling parameters of the texture. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + iteration % 2 == 0 ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + iteration % 3 == 0 ? GL_LINEAR : GL_NEAREST); + + // Make sure the texture is synced. + drawQuad(program, essl1_shaders::PositionAttrib(), 0); + EXPECT_GL_NO_ERROR(); + } + glFinish(); + }; + + runMultithreadedGLTest(testBody, 16); +} + +// Test that multiple threads can create contexts at the same time. TEST_P(MultithreadingTest, MultiCreateContext) { // Supported by CGL, GLX, and WGL (https://anglebug.com/42263324) @@ -774,6 +834,9 @@ TEST_P(MultithreadingTest, EGLImageProduceConsume) } eglDestroyContext(dpy, ctx); + + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); }); std::thread consumerThread([&]() { @@ -842,6 +905,9 @@ TEST_P(MultithreadingTest, EGLImageProduceConsume) } } eglDestroyContext(dpy, ctx); + + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); }); producerThread.join(); @@ -1174,6 +1240,9 @@ TEST_P(MultithreadingTest, CreateFenceThreadAClientWaitSyncThreadBDelayedFlush) threadSynchronization.nextStep(Step::Thread0ClientWaitSync); ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR, eglClientWaitSyncKHR(dpy, sync, 0, kTimeout)); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); }; @@ -3002,6 +3071,9 @@ TEST_P(MultithreadingTestES3, MultithreadedTextureUploadAndDraw) glFlush(); ASSERT_NE(sync, nullptr); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Thread0UploadFinish); ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); }; @@ -3033,6 +3105,9 @@ TEST_P(MultithreadingTestES3, MultithreadedTextureUploadAndDraw) ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_RECT_EQ(0, 0, kTexSize, kTexSize, GLColor::green); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Finish); }; @@ -3162,6 +3237,9 @@ TEST_P(MultithreadingTestES3, CreateNewContextAfterTextureUploadOnMainThread) // Destroy the context. EXPECT_EGL_TRUE(eglDestroyContext(dpy, ctx1)); + + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); }); thread.join(); @@ -3319,6 +3397,9 @@ void main() ASSERT_NE(sync, nullptr); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Thread0UploadFinish); ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); }; @@ -3438,6 +3519,9 @@ void main() EXPECT_PIXEL_NE(x * w / 8, h / 4, 0, 0, 0, 0); } ASSERT_GL_NO_ERROR(); + + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); }; std::array threadFuncs = { @@ -3541,6 +3625,9 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Finish); }; @@ -3590,6 +3677,9 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + // Tell the other thread to finish up. threadSynchronization.nextStep(Step::Thread1FinishedDrawing); ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); @@ -3670,6 +3760,9 @@ TEST_P(MultithreadingTestES3, SharedFoveatedTexture) glTextureFoveationParametersQCOM(texture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f); EXPECT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Thread0ConfiguredTextureFoveation); ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); }; @@ -3716,6 +3809,9 @@ TEST_P(MultithreadingTestES3, SharedFoveatedTexture) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Finish); }; @@ -3915,6 +4011,9 @@ TEST_P(MultithreadingTest, ProgramLinkAndBind) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Finish); }; @@ -3950,6 +4049,9 @@ TEST_P(MultithreadingTest, ProgramLinkAndBind) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + // Tell the other thread to finish up. threadSynchronization.nextStep(Step::Thread1FinishedDrawing); ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); @@ -4069,6 +4171,9 @@ void main() verify(kSurfaceWidth / 2, kSurfaceHeight / 2); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + if (index == 0) { threadSynchronization.nextStep(Step::Finish); @@ -4170,6 +4275,9 @@ void main() } ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + threadSynchronization.nextStep(Step::Finish); }; auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) { @@ -4200,6 +4308,9 @@ void main() EXPECT_PIXEL_RECT_EQ(0, 0, kSurfaceWidth, kSurfaceHeight, expect); ASSERT_GL_NO_ERROR(); + // Clean up + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); }; @@ -4213,6 +4324,7 @@ void main() ASSERT_NE(currentStep, Step::Abort); } + ANGLE_INSTANTIATE_TEST( MultithreadingTest, ES2_METAL(), @@ -4222,7 +4334,6 @@ ANGLE_INSTANTIATE_TEST( ES2_OPENGLES(), ES3_OPENGLES(), ES3_VULKAN(), - ES3_VULKAN_SWIFTSHADER().disable(Feature::PreferMonolithicPipelinesOverLibraries), ES3_VULKAN_SWIFTSHADER().enable(Feature::PreferMonolithicPipelinesOverLibraries), ES3_VULKAN_SWIFTSHADER() .enable(Feature::PreferMonolithicPipelinesOverLibraries) @@ -4247,7 +4358,6 @@ ANGLE_INSTANTIATE_TEST( ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), - ES3_VULKAN_SWIFTSHADER().disable(Feature::PreferMonolithicPipelinesOverLibraries), ES3_VULKAN_SWIFTSHADER().enable(Feature::PreferMonolithicPipelinesOverLibraries), ES3_VULKAN_SWIFTSHADER() .enable(Feature::PreferMonolithicPipelinesOverLibraries) diff --git a/src/tests/gl_tests/MultiviewDrawTest.cpp b/src/tests/gl_tests/MultiviewDrawTest.cpp index b74e4d53d7a..5461b0269be 100644 --- a/src/tests/gl_tests/MultiviewDrawTest.cpp +++ b/src/tests/gl_tests/MultiviewDrawTest.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Multiview draw tests: -// Test issuing multiview Draw* commands. +// MultiviewDrawTest.cpp: +// Test issuing multiview Draw* commands. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "platform/autogen/FeaturesD3D_autogen.h" #include "test_utils/MultiviewTest.h" #include "test_utils/gl_raii.h" @@ -34,6 +38,12 @@ std::vector ConvertPixelCoordinatesToClipSpace(const std::vector +{ + protected: + MultiviewDependencyTest() { setExtensionsEnabled(false); } +}; + struct MultiviewRenderTestParams final : public MultiviewImplementationParams { MultiviewRenderTestParams(int samples, @@ -58,7 +68,7 @@ std::ostream &operator<<(std::ostream &os, const MultiviewRenderTestParams ¶ } class MultiviewFramebufferTestBase : public MultiviewTestBase, - public ::testing::TestWithParam + public ::testing::WithParamInterface { protected: MultiviewFramebufferTestBase(const PlatformParameters ¶ms, int samples) @@ -292,6 +302,12 @@ class MultiviewRenderTest : public MultiviewFramebufferTestBase void SetUp() override { MultiviewFramebufferTestBase::FramebufferTestSetUp(); + // SetUp() may have determined the test should be skipped and returned before completing. + if (Test::IsSkipped()) + { + return; + } + testSetUp(); } void TearDown() override @@ -530,6 +546,68 @@ class MultiviewLayeredRenderTest : public MultiviewFramebufferTestBase void TearDown() final { MultiviewFramebufferTestBase::FramebufferTestTearDown(); } }; +// Tests that GL_OVR_multiview requires ES 3.0+ and does not enable GL_OVR_multiview2. +TEST_P(MultiviewDependencyTest, MV1) +{ + ASSERT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview")); + ASSERT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview2")); + + GLint maxViews = -1; + glGetIntegerv(GL_MAX_VIEWS_OVR, &maxViews); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + EXPECT_EQ(maxViews, -1); + + EnsureGLExtensionEnabled("GL_OVR_multiview"); + + // GL_OVR_multiview never enables GL_OVR_multiview2 + EXPECT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview2")); + + if (getClientMajorVersion() < 3) + { + EXPECT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview")); + } + else + { + glGetIntegerv(GL_MAX_VIEWS_OVR, &maxViews); + if (IsGLExtensionEnabled("GL_OVR_multiview")) + { + EXPECT_GL_NO_ERROR(); + EXPECT_GE(maxViews, 2); + } + else + { + EXPECT_GL_ERROR(GL_INVALID_ENUM); + EXPECT_EQ(maxViews, -1); + } + } +} + +// Tests that GL_OVR_multiview2 requires ES 3.0+ and does enable GL_OVR_multiview. +TEST_P(MultiviewDependencyTest, MV2) +{ + ASSERT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview")); + ASSERT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview2")); + + EnsureGLExtensionEnabled("GL_OVR_multiview2"); + + if (getClientMajorVersion() < 3) + { + EXPECT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview")); + EXPECT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview2")); + } + else + { + if (IsGLExtensionEnabled("GL_OVR_multiview2")) + { + EXPECT_TRUE(IsGLExtensionEnabled("GL_OVR_multiview")); + } + else + { + EXPECT_FALSE(IsGLExtensionEnabled("GL_OVR_multiview")); + } + } +} + // The test verifies that glDraw*Indirect works for any number of views. TEST_P(MultiviewDrawValidationTest, IndirectDraw) { @@ -610,6 +688,68 @@ TEST_P(MultiviewDrawValidationTest, IndirectDraw) } } +// Test separable programs with OVR multiview. +TEST_P(MultiviewDrawValidationTest, SSOProgramMultiview) +{ + // Only the Vulkan backend supports PPOs. + ANGLE_SKIP_TEST_IF(!IsVulkan()); + ANGLE_SKIP_TEST_IF(!requestMultiviewExtension()); + + const std::string VS = + "#version 300 es\n" + "#extension " + + extensionName() + + ": require\n" + "layout(num_views = 2) in;\n" + "void main()\n" + "{}\n"; + const std::string FS = + "#version 300 es\n" + "#extension " + + extensionName() + + ": require\n" + "precision mediump float;\n" + "out vec4 color;\n" + "void main()\n" + "{color = vec4(1);}\n"; + + const char *vsSource = VS.c_str(), *fsSource = FS.c_str(); + GLuint programVS, programFS, pipeline; + programVS = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vsSource); + ASSERT_NE(programVS, 0u); + glProgramParameteri(programVS, GL_PROGRAM_SEPARABLE, GL_TRUE); + programFS = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fsSource); + ASSERT_NE(programFS, 0u); + glProgramParameteri(programFS, GL_PROGRAM_SEPARABLE, GL_TRUE); + glGenProgramPipelines(1, &pipeline); + glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVS); + EXPECT_GL_NO_ERROR(); + glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFS); + EXPECT_GL_NO_ERROR(); + glBindProgramPipeline(pipeline); + + GLVertexArray vao; + GLBuffer vertexBuffer; + GLBuffer indexBuffer; + initVAO(vao, vertexBuffer, indexBuffer); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + { + GLTexture tex2DArray; + initOnePixelColorTexture2DMultiLayered(tex2DArray); + + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray, 0, 0, 2); + + glDrawArrays(GL_TRIANGLES, 0, 3); + EXPECT_GL_NO_ERROR(); + + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); + EXPECT_GL_NO_ERROR(); + } +} + // The test verifies that glDraw*: // 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and // program differs. @@ -2450,18 +2590,15 @@ MultiviewRenderTestParams MultisampledVertexShaderVulkan(ExtensionName multiview return MultiviewRenderTestParams(2, VertexShaderVulkan(3, 1, multiviewExtension)); } -MultiviewRenderTestParams MultisampledVertexShaderD3D11(ExtensionName multiviewExtension) -{ - return MultiviewRenderTestParams(2, VertexShaderD3D11(3, 1, multiviewExtension)); -} - -#define ALL_VERTEX_SHADER_CONFIGS(minor) \ +#define ES31_CAPABLE_VERTEX_SHADER_CONFIGS(minor) \ VertexShaderOpenGL(3, minor, ExtensionName::multiview), \ VertexShaderVulkan(3, minor, ExtensionName::multiview), \ - VertexShaderD3D11(3, minor, ExtensionName::multiview), \ VertexShaderOpenGL(3, minor, ExtensionName::multiview2), \ - VertexShaderVulkan(3, minor, ExtensionName::multiview2), \ - VertexShaderD3D11(3, minor, ExtensionName::multiview2) + VertexShaderVulkan(3, minor, ExtensionName::multiview2) + +#define ES3_ONLY_VERTEX_SHADER_CONFIGS \ + ES31_CAPABLE_VERTEX_SHADER_CONFIGS(0), VertexShaderD3D11(3, 0, ExtensionName::multiview), \ + VertexShaderD3D11(3, 0, ExtensionName::multiview2) #define ALL_SINGLESAMPLE_CONFIGS() \ VertexShaderOpenGL(ExtensionName::multiview), VertexShaderVulkan(ExtensionName::multiview), \ @@ -2473,13 +2610,13 @@ MultiviewRenderTestParams MultisampledVertexShaderD3D11(ExtensionName multiviewE #define ALL_MULTISAMPLE_CONFIGS() \ MultisampledVertexShaderOpenGL(ExtensionName::multiview), \ MultisampledVertexShaderVulkan(ExtensionName::multiview), \ - MultisampledVertexShaderD3D11(ExtensionName::multiview), \ MultisampledVertexShaderOpenGL(ExtensionName::multiview2), \ - MultisampledVertexShaderVulkan(ExtensionName::multiview2), \ - MultisampledVertexShaderD3D11(ExtensionName::multiview2) + MultisampledVertexShaderVulkan(ExtensionName::multiview2) + +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MultiviewDependencyTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewDrawValidationTest); -ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest, ALL_VERTEX_SHADER_CONFIGS(1)); +ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest, ES31_CAPABLE_VERTEX_SHADER_CONFIGS(1)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewRenderDualViewTest); ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest, @@ -2499,7 +2636,7 @@ ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest, ALL_SINGLESAMPLE_CONFIGS()); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewProgramGenerationTest); ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest, - ALL_VERTEX_SHADER_CONFIGS(0), + ES3_ONLY_VERTEX_SHADER_CONFIGS, GeomShaderD3D11(3, 0, ExtensionName::multiview), GeomShaderD3D11(3, 0, ExtensionName::multiview2)); diff --git a/src/tests/gl_tests/MultiviewMultisampledRenderToTextureTest.cpp b/src/tests/gl_tests/MultiviewMultisampledRenderToTextureTest.cpp new file mode 100644 index 00000000000..2ef858d5a75 --- /dev/null +++ b/src/tests/gl_tests/MultiviewMultisampledRenderToTextureTest.cpp @@ -0,0 +1,1295 @@ +// +// Copyright 2019 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. +// + +// MultiviewMultisampledRenderToTextureTest: +// Tests of OVR_multiview_multisampled_render_to_texture extension + +#include +#include "test_utils/ANGLETest.h" +#include "test_utils/gl_raii.h" + +using namespace angle; + +namespace +{ +constexpr int kWindowSize = 6; +class MultiviewMSRTTTest : public ANGLETest<> +{ + protected: + MultiviewMSRTTTest() + { + setWindowWidth(kWindowSize); + setWindowHeight(kWindowSize); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } + + void testSetUp() override + { + if (getClientMajorVersion() >= 3) + { + glGetIntegerv(GL_MAX_SAMPLES, &mMaxIntegerSamples); + glGetIntegerv(GL_MAX_VIEWS_OVR, &mMaxViewsOVR); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &mMaxArrayTextureLayers); + } + } + + GLint mMaxIntegerSamples = 0; + GLint mMaxViewsOVR = 0; + GLint mMaxArrayTextureLayers = 0; +}; + +class MultiviewMSRTTES3Test : public MultiviewMSRTTTest +{}; + +// Test that INVALID_FRAMEBUFFER_OPERATION is generated by glReadPixels() command if the number +// of views in the current read framebuffer is greater than 1 +TEST_P(MultiviewMSRTTES3Test, ReadPixelsFromMultiviewFramebufferShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 2); + ASSERT_GL_NO_ERROR(); + std::vector pixels(kWindowSize * kWindowSize * numLayers); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); +} + +// Test that INVALID_FRAMEBUFFER_OPERATION is generated by glCopyTexImage2D() command if the number +// of views in the current read framebuffer is greater than 1 +TEST_P(MultiviewMSRTTES3Test, CopyTexImageFromMultiviewFramebufferShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 2); + ASSERT_GL_NO_ERROR(); + GLTexture copyImageTargetTexture; + glBindTexture(GL_TEXTURE_2D, copyImageTargetTexture); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, kWindowSize, kWindowSize, 0); + EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); +} + +// Test that INVALID_FRAMEBUFFER_OPERATION is generated by glCopyTexSubImage() command if the number +// of views in the current read framebuffer is greater than 1 +TEST_P(MultiviewMSRTTES3Test, CopyTexSubImageFromMultiviewFramebufferShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 2); + ASSERT_GL_NO_ERROR(); + GLTexture copySubImageTargetTexture; + glBindTexture(GL_TEXTURE_2D, copySubImageTargetTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWindowSize, kWindowSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kWindowSize, kWindowSize); + EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); +} + +// Test that INVALID_FRAMEBUFFER_OPERATION is generated by glCopyTexSubImage3D() command if the +// number of views in the current read framebuffer is greater than 1 +TEST_P(MultiviewMSRTTES3Test, CopyTexSubImage3DFromMultiviewFramebufferShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 2); + ASSERT_GL_NO_ERROR(); + GLTexture copySubImage3DTargetTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, copySubImage3DTargetTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, kWindowSize, kWindowSize); + EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); +} + +// Test that INVALID_VALUE is generated by FramebufferTextureMultisampleMultiviewOVR if numViews is +// less than 1 +TEST_P(MultiviewMSRTTES3Test, NumViewsLessThanOneShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 0); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that INVALID_VALUE is generated by FramebufferTextureMultisampleMultiviewOVR if numViews is +// more than MAX_VIEWS_OVR +TEST_P(MultiviewMSRTTES3Test, NumViewsGreaterThanMaxShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, + mMaxViewsOVR + 1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that INVALID_VALUE is generated by FramebufferTextureMultisampleMultiviewOVR if +// (baseViewIndex + numViews) exceeds GL_MAX_ARRAY_TEXTURE_LAYERS +TEST_P(MultiviewMSRTTES3Test, BaseViewIndexPlusNumViewsExceedsMaxArrayTextureLayersShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, + mMaxArrayTextureLayers, 1); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that INVALID_VALUE is generated by FramebufferTextureMultisampleMultiviewOVR if samples is +// greater than MAX_SAMPLES +TEST_P(MultiviewMSRTTES3Test, SamplesGreaterThanMaxSamplesShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + mMaxIntegerSamples + 1, 0, 2); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that INVALID_OPERATION is generated if a rendering command is issued and the number +// of views in the current draw framebuffer is not equal to the number of views declared in +// the currently bound program. +TEST_P(MultiviewMSRTTES3Test, ProgramViewMismatchFramebufferViewShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + // Create a program with 2 views + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } + )"; + const std::string fsSource = R"(#version 300 es + precision mediump float; + out vec4 FragColor; + void main() + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + )"; + + ANGLE_GL_PROGRAM(program, vsSource.c_str(), fsSource.c_str()); + glUseProgram(program); + + // Create a framebuffer with 1 view + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 1; // 1 view in framebuffer + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 1); + ASSERT_GL_NO_ERROR(); + + // Draw with program (2 views) and framebuffer (1 view) mismatch + drawQuad(program, "a_position", 0.5f, 0.5f, true); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Test that INVALID_OPERATION is generated if the target type of specified in +// FramebufferTextureMultisampleMultiviewOVR is not TEXTURE_2D_ARRAY +TEST_P(MultiviewMSRTTES3Test, InvalidTextureTargetShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); // Bind to GL_TEXTURE_2D instead of GL_TEXTURE_2D_ARRAY + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWindowSize, kWindowSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 2); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Test that calling glFramebufferTextureMultisampleMultiviewOVR() on both GL_COLOR_ATTACHMENT0 +// and GL_DEPTH_ATTACHMENT works, and that drawing to it works. +TEST_P(MultiviewMSRTTES3Test, ColorAndDepthAttachment) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } +)"; + const std::string fsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + precision mediump float; + out vec4 FragColor; + void main() + { + if (gl_ViewID_OVR == 0u) + { + FragColor = vec4(0.0, 1.0, 0.0, 1.0); + gl_FragDepth = 0.25; + } + else + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragDepth = 0.75; + } + } +)"; + ANGLE_GL_PROGRAM(program, vsSource.c_str(), fsSource.c_str()); + glUseProgram(program); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + // Color attachment + GLTexture colorTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, + 0, multisampleRenderToTextureSampleSize, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + + // Depth attachment + GLTexture depthTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, depthTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, kWindowSize, kWindowSize, numViews, + 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, + 0, multisampleRenderToTextureSampleSize, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glEnable(GL_DEPTH_TEST); + glClearDepthf(1.0f); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + drawQuad(program, "a_position", 0.5f, 0.5f, true); + ASSERT_GL_NO_ERROR(); + + // Verification + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + + // Verify view 0 + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, + baseViewIndex + 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::green); + + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, + baseViewIndex + 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + float depth0 = 0.0f; + glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth0); + EXPECT_NEAR(1.0f, depth0, 1e-6); + glReadPixels(kWindowSize / 2, kWindowSize / 2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth0); + EXPECT_NEAR(0.25, depth0, 1e-6); + + // Verify view 1 + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::red); + + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + float depth1 = 0.0f; + glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth1); + EXPECT_NEAR(1.0f, depth1, 1e-6); + glReadPixels(kWindowSize / 2, kWindowSize / 2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth1); + EXPECT_NEAR(0.75, depth1, 1e-6); + + ASSERT_GL_NO_ERROR(); +} + +// Test that an INVALID_OPERATION error is generated if samples is greater than the maximum number +// of samples supported for target and its internalformat. +TEST_P(MultiviewMSRTTES3Test, SamplesGreaterThanMaxSamplesForTextureFormatShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + GLint maxSamplesForFormat = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_RGBA8, GL_SAMPLES, 1, + &maxSamplesForFormat); + INFO() << "maxSamplesForFormat: " << maxSamplesForFormat; + ASSERT_GL_NO_ERROR(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 2; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + maxSamplesForFormat + 1, 0, 2); + + if (maxSamplesForFormat < mMaxIntegerSamples) + { + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } + else + { + // GL_INVALID_VALUE error code is generated if samples > mMaxIntegerSamples + EXPECT_GL_ERROR(GL_INVALID_VALUE); + } +} + +// Test that passing samples 0 to glFramebufferTextureMultisampleMultiviewOVR() works and +// produces the same result as glFramebufferTextureMultiviewOVR. +TEST_P(MultiviewMSRTTES3Test, SamplesZeroWorks) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } +)"; + const std::string fsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + precision mediump float; + out vec4 FragColor; + void main() + { + if (gl_ViewID_OVR == 0u) + { + FragColor = vec4(0.0, 1.0, 0.0, 1.0); + } + else + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + } +)"; + ANGLE_GL_PROGRAM(program, vsSource.c_str(), fsSource.c_str()); + glUseProgram(program); + + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + + // FBO 0: Use glFramebufferTextureMultisampleMultiviewOVR with 0 samples + GLFramebuffer fbo0; + glBindFramebuffer(GL_FRAMEBUFFER, fbo0); + GLTexture colorTexture0; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture0); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, + 0, 0, baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "a_position", 0.5f, 0.5f, true); + ASSERT_GL_NO_ERROR(); + + // FBO 1: Use glFramebufferTextureMultiviewOVR + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + GLTexture colorTexture1; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture1); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture1, 0, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "a_position", 0.5f, 0.5f, true); + ASSERT_GL_NO_ERROR(); + + // Verification: Compare colorTexture0 and colorTexture1 + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + + std::vector pixels0(kWindowSize * kWindowSize); + std::vector pixels1(kWindowSize * kWindowSize); + + for (int i = 0; i < numViews; ++i) + { + // Read from colorTexture0 + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, 0, + baseViewIndex + i); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, pixels0.data()); + ASSERT_GL_NO_ERROR(); + + // Read from colorTexture1 + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture1, 0, + baseViewIndex + i); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, pixels1.data()); + ASSERT_GL_NO_ERROR(); + + // Compare + EXPECT_EQ(pixels0, pixels1); + } + + ASSERT_GL_NO_ERROR(); +} + +// Test that after calling glFramebufferTextureMultisampleMultiviewOVR, the resulting value for +// TEXTURE_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more than the +// next larger sample count supported by the implementation. +TEST_P(MultiviewMSRTTES3Test, FrameBufferTextureSamplesExtValue) +{ + + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + constexpr GLsizei requestedSamples = 2; // Request 2 samples + GLTexture colorTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, + 0, requestedSamples, baseViewIndex, numViews); + + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Query TEXTURE_SAMPLES_EXT from the framebuffer attachment + GLint actualSamples = 0; + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT, + &actualSamples); + ASSERT_GL_NO_ERROR(); + + // Get supported sample counts for GL_RGBA8 + GLint numSampleCounts = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, + &numSampleCounts); + ASSERT_GL_NO_ERROR(); + std::vector supportedSampleCounts(numSampleCounts); + glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, numSampleCounts, + supportedSampleCounts.data()); + ASSERT_GL_NO_ERROR(); + + // Sort supported sample counts in ascending order + std::sort(supportedSampleCounts.begin(), supportedSampleCounts.end()); + // Find the smallest supported sample count that is >= requestedSamples + GLint expectedMaxSamples = 0; + if (requestedSamples == 0) + { + expectedMaxSamples = 0; + } + else + { + auto it = std::lower_bound(supportedSampleCounts.begin(), supportedSampleCounts.end(), + requestedSamples); + ASSERT(it != supportedSampleCounts.end()); + expectedMaxSamples = *it; + } + // Verify the conditions + EXPECT_GE(actualSamples, requestedSamples); + EXPECT_LE(actualSamples, expectedMaxSamples); +} + +// Test that glReadPixels() does not return an error if the GL_SAMPLE_BUFFERS of read framebuffer is +// 1, when the read framebuffer attachment is attached with +// glFramebufferTextureMultisampleMultiviewOVR() +TEST_P(MultiviewMSRTTES3Test, ReadPixelsFromSingleViewFramebufferShouldSucceed) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numLayers = 1; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + std::vector textureData; + textureData.resize(kWindowSize * kWindowSize * numLayers * 4, 0u); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, textureData.data()); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, + multisampleRenderToTextureSampleSize, 0, 1); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + GLint sampleBuffers = 0; + glGetIntegerv(GL_SAMPLE_BUFFERS, &sampleBuffers); + if (sampleBuffers == 1) + { + std::vector pixels(kWindowSize * kWindowSize * numLayers); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + EXPECT_GL_NO_ERROR(); + } +} + +// Test that framebuffer succeed with draw operations if the attachments are created with +// glFramebufferTextureMultisampleMultiviewOVR() and have the same render-to-texture sample counts +TEST_P(MultiviewMSRTTES3Test, FBOAttachmentsWithSameSampleCountShouldSucceed) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + constexpr GLsizei multisampleRenderToTextureSampleSize4 = 4; + ANGLE_SKIP_TEST_IF(mMaxIntegerSamples <= multisampleRenderToTextureSampleSize4); + + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Attach msrtt-multiview (4 samples) texture to COLOR_ATTACHMENT0 + GLTexture colorTexture0; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture0); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, + 0, multisampleRenderToTextureSampleSize4, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + + // Attach msrtt-multiview (4 samples) texture to COLOR_ATTACHMENT1 + GLTexture colorTexture1; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture1); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorTexture1, + 0, multisampleRenderToTextureSampleSize4, + baseViewIndex, numViews); + + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } + )"; + const std::string fsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + precision mediump float; + layout(location = 0)out vec4 FragColor0; + layout(location = 1)out vec4 FragColor1; + void main() + { + if (gl_ViewID_OVR == 0u) { + FragColor0 = vec4(1.0, 0.0, 0.0, 1.0); // Red for view 0 GL_COLOR_ATTACHMENT0 + FragColor1 = vec4(1.0, 1.0, 0.0, 1.0); // Yellow for view 0 GL_COLOR_ATTACHMENT1 + } else { + FragColor0 = vec4(0.0, 1.0, 0.0, 1.0); // Green for view 1 GL_COLOR_ATTACHMENT0 + FragColor1 = vec4(0.0, 0.0, 1.0, 1.0); // Blue for view 1 GL_COLOR_ATTACHMENT1 + } + } + )"; + + ANGLE_GL_PROGRAM(program, vsSource.c_str(), fsSource.c_str()); + glUseProgram(program); + + GLenum buffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; + glDrawBuffers(2, buffers); + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw a quad + drawQuad(program, "a_position", 0.5f, 0.5f, true); + ASSERT_GL_NO_ERROR(); + + // Verify draw result + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, 0, + baseViewIndex); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::green); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture1, 0, + baseViewIndex); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::yellow); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture1, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::blue); + + // Now attach with a different render-to-texture sample count + // Attach msrtt-multiview (mMaxIntegerSamples samples) texture to COLOR_ATTACHMENT0 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + GLTexture colorTexture3; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture3); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture3, + 0, mMaxIntegerSamples, baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + + // Attach msrtt-multiview (mMaxIntegerSamples samples) texture to COLOR_ATTACHMENT1 + GLTexture colorTexture4; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture4); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorTexture4, + 0, mMaxIntegerSamples, baseViewIndex, numViews); + // Draw a quad + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "a_position", 0.5f, 0.5f, true); + ASSERT_GL_NO_ERROR(); + + // Verify draw result + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture3, 0, + baseViewIndex); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture3, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::green); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture4, 0, + baseViewIndex); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::yellow); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture4, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, GLColor::blue); +} + +// Test that framebuffer fails completeness check if the attachments created with +// glFramebufferTextureMultisampleMultiviewOVR() have different render-to-texture sample counts +TEST_P(MultiviewMSRTTES3Test, FBOAttachmentsWithDifferentSampleCountShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + constexpr GLsizei multisampleRenderToTextureSampleSize4 = 4; + ANGLE_SKIP_TEST_IF(mMaxIntegerSamples <= multisampleRenderToTextureSampleSize4); + + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Attach msrtt-multiview (4 samples) texture to COLOR_ATTACHMENT0 + GLTexture colorTexture0; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture0); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, + 0, multisampleRenderToTextureSampleSize4, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + + // Attach msrtt-multiview (2 samples) texture to COLOR_ATTACHMENT1 + GLTexture colorTexture1; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture1); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorTexture1, + 0, mMaxIntegerSamples, baseViewIndex, numViews); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); +} + +// Test that framebuffer fails completeness check if the attachments created with +// glFramebufferTextureMultisampleMultiviewOVR() have different numViews +TEST_P(MultiviewMSRTTES3Test, FBOAttachmentsWithDifferentNumViewsShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + constexpr int multisampleRenderToTextureNumViews1 = 1; + ANGLE_SKIP_TEST_IF(mMaxViewsOVR <= multisampleRenderToTextureNumViews1); + + constexpr GLsizei samples = 2; + constexpr int baseViewIndex = 0; + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Attach a texture with numViews as 1 to COLOR_ATTACHMENT0 + GLTexture colorTexture0; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture0); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, + multisampleRenderToTextureNumViews1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture0, + 0, samples, baseViewIndex, + multisampleRenderToTextureNumViews1); + ASSERT_GL_NO_ERROR(); + + // Attach a texture with numViews as max to COLOR_ATTACHMENT1 + GLTexture colorTexture1; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture1); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, mMaxViewsOVR, 0, + GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorTexture1, + 0, samples, baseViewIndex, mMaxViewsOVR); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); +} + +// Test that if the layout qualifier num_views is declared more than once in the same shader, +// all those declarations must set num_views to the same value; otherwise a compile-time error +// results. +TEST_P(MultiviewMSRTTES3Test, ConflictingNumViewsDeclarationsShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + layout(num_views = 3) in; // Conflicting declaration + in vec4 a_position; + void main() + { + gl_Position = a_position; + } + )"; + const std::string fsSource = R"(#version 300 es + precision mediump float; + out vec4 FragColor; + void main() + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + )"; + + // Expect program compilation/linking to fail due to conflicting num_views + GLuint program = CompileProgram(vsSource.c_str(), fsSource.c_str()); + EXPECT_EQ(0u, program); +} + +// Test that it is a compile-time error to declare num_views to be less than or equal to zero. +TEST_P(MultiviewMSRTTES3Test, NumViewsLessThanOrEqualToZeroShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + // Test with num_views = 0 + const std::string vsSourceZero = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 0) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } + )"; + + GLuint vs1 = CompileShader(GL_VERTEX_SHADER, vsSourceZero.c_str()); + ASSERT(vs1 == 0); + + // Test with num_views = -1 + const std::string vsSourceNegative = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = -1) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } + )"; + GLuint vs2 = CompileShader(GL_VERTEX_SHADER, vsSourceNegative.c_str()); + ASSERT(vs2 == 0); + glDeleteShader(vs1); + glDeleteShader(vs2); +} + +// Test that it is a compile-time error to declare num_views to be greater than MAX_VIEWS_OVR. +TEST_P(MultiviewMSRTTES3Test, NumViewsGreaterThanMaxViewsOVRShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + // Use mMaxViewsOVR + 1 for the num_views declaration + std::string vsSource = "#version 300 es\n"; + vsSource += " #extension GL_OVR_multiview : require\n"; + vsSource += " layout(num_views = " + std::to_string(mMaxViewsOVR + 1) + ") in;\n"; + vsSource += " in vec4 a_position;\n"; + vsSource += " void main()\n"; + vsSource += " {\n"; + vsSource += " gl_Position = a_position;\n"; + vsSource += " }\n"; + + GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource.c_str()); + ASSERT(vs == 0); + glDeleteShader(vs); +} + +// Test that when attaching 2D array texture to FBO with +// glFramebufferTextureMultisampleMultiviewOVR(), glClear() will apply clear color to all views. +TEST_P(MultiviewMSRTTES3Test, ClearAppliesToAllViewsInMultiviewFramebuffer) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + + GLTexture colorTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, + 0, multisampleRenderToTextureSampleSize, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Set a clear color (e.g., red) + GLColor clearColor(255, 0, 0, 255); + glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f, + clearColor.A / 255.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + // Verify that all views are cleared to the specified color + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + + for (int i = 0; i < numViews; ++i) + { + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, + baseViewIndex + i); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 2, clearColor); + } + ASSERT_GL_NO_ERROR(); +} + +// Test that INVALID_OPERATION is generated for a draw operation when the draw framebuffer is +// multiview and transform feedback is active. +TEST_P(MultiviewMSRTTES3Test, MultiviewDrawFramebufferWithTransformFeedbackShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + // Create a multiview draw framebuffer + GLFramebuffer drawFbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); + + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + + GLTexture drawColorTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, drawColorTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR( + GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, drawColorTexture, 0, + multisampleRenderToTextureSampleSize, baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + + // Create a program with transform feedback varyings + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + out vec4 xfb_position; + void main() + { + gl_Position = a_position; + xfb_position = a_position; + } + )"; + const std::string fsSource = R"(#version 300 es + precision mediump float; + out vec4 FragColor; + void main() + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + )"; + + std::vector varyings = {"xfb_position"}; + ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, vsSource.c_str(), fsSource.c_str(), varyings, + GL_INTERLEAVED_ATTRIBS); + glUseProgram(program); + + // Create transform feedback buffer + GLBuffer transformFeedbackBuffer; + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(GLfloat) * 4 * 3, nullptr, GL_STREAM_READ); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer); + + // Begin transform feedback + glBeginTransformFeedback(GL_TRIANGLES); + ASSERT_GL_NO_ERROR(); + + // Attempt a draw operation with transform feedback active and multiview framebuffer + drawQuad(program, "a_position", 0.5f, 0.5f, true); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glEndTransformFeedback(); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); +} + +// Test that instanced drawing commands work with multiview. +TEST_P(MultiviewMSRTTES3Test, InstancedDrawingWithMultiview) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + if (gl_InstanceID == 1) { + gl_Position.y = gl_Position.y * 0.5 + 0.5; + } else { + gl_Position.y = gl_Position.y * 0.5 - 0.5; + } + } + )"; + const std::string fsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + precision mediump float; + out vec4 FragColor; + void main() + { + if (gl_ViewID_OVR == 0u) + { + FragColor = vec4(0.0, 1.0, 0.0, 1.0); // Green for view 0 + } + else + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red for view 1 + } + } + + )"; + ANGLE_GL_PROGRAM(program, vsSource.c_str(), fsSource.c_str()); + glUseProgram(program); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + + GLTexture colorTexture; + glBindTexture(GL_TEXTURE_2D_ARRAY, colorTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numViews, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, + 0, multisampleRenderToTextureSampleSize, + baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw 2 instance + drawQuadInstanced(program, "a_position", 0.5f, 0.5f, true, 2); + + ASSERT_GL_NO_ERROR(); + + // Verification + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + + // Verify view 0 (should be green) + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, + baseViewIndex + 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + // verify first instance + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 4, GLColor::green); + // verify second instance + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize * 3 / 4, GLColor::green); + + // Verify view 1 (should be red) + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, + baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + // verify first instance + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize / 4, GLColor::red); + // verify second instance + EXPECT_PIXEL_COLOR_EQ(kWindowSize / 2, kWindowSize * 3 / 4, GLColor::red); + + ASSERT_GL_NO_ERROR(); +} + +// Test that rendering to a mipmap level of a 2D array texture works. +TEST_P(MultiviewMSRTTES3Test, RenderToMipmapLevel1) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + const std::string vsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + layout(num_views = 2) in; + in vec4 a_position; + void main() + { + gl_Position = a_position; + } + )"; + const std::string fsSource = R"(#version 300 es + #extension GL_OVR_multiview : require + precision mediump float; + out vec4 FragColor; + void main() + { + if (gl_ViewID_OVR == 0u) { + FragColor = vec4(0.0, 1.0, 0.0, 1.0); // Green for view 0 + } else { + FragColor = vec4(1.0, 1.0, 0.0, 1.0); // Yellow for view 1 + } + } + )"; + + ANGLE_GL_PROGRAM(program, vsSource.c_str(), fsSource.c_str()); + glUseProgram(program); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + constexpr int numViews = 2; + constexpr int baseViewIndex = 0; + constexpr GLsizei samples = 4; + constexpr int mipmapLevels = 2; + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipmapLevels, GL_RGBA8, kWindowSize, kWindowSize, 2); + + // Initialize mipmap level 0 with red + std::vector level0Data(kWindowSize * kWindowSize * numViews, GLColor::red); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWindowSize, kWindowSize, numViews, GL_RGBA, + GL_UNSIGNED_BYTE, level0Data.data()); + + // Initialize mipmap level 1 with blue + constexpr int mipLevel1Size = kWindowSize >> 1; + std::vector level1Data(mipLevel1Size * mipLevel1Size * numViews, GLColor::blue); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, mipLevel1Size, mipLevel1Size, numViews, + GL_RGBA, GL_UNSIGNED_BYTE, level1Data.data()); + + // Attachm mipLevel 1 of the texture array to the FBO + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 1, + samples, baseViewIndex, numViews); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Draw a quad + glViewport(0, 0, mipLevel1Size, mipLevel1Size); + drawQuad(program, "a_position", 0.5f, 0.5f, true); + ASSERT_GL_NO_ERROR(); + + // Verification + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + + // Verify mipmap level 0 is unchanged (should be red) + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, baseViewIndex); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(mipLevel1Size / 2, mipLevel1Size / 2, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(mipLevel1Size / 2, mipLevel1Size / 2, GLColor::red); + + // Verify mipmap level 1 is changed (outer edge is blue, inner quad on layer 0 is green, inner + // quad on layer 1 is yellow) + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 1, baseViewIndex); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(mipLevel1Size / 2, mipLevel1Size / 2, GLColor::green); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 1, baseViewIndex + 1); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + EXPECT_PIXEL_COLOR_EQ(mipLevel1Size / 2, mipLevel1Size / 2, GLColor::yellow); + ASSERT_GL_NO_ERROR(); +} + +class MultiviewMSRTTES31Test : public MultiviewMSRTTTest +{}; + +// Test that it is invalid to attach a 2d array texture to the framebuffer with +// glFramebufferTextureMultisampleMultiviewOVR and then attach a multisampled texture that is +// created with glTexStorage2DMultisample() to the same framebuffer. +TEST_P(MultiviewMSRTTES31Test, + FramebufferTextureMultisampleMultiviewOVRInvalidAttachmentsShouldFail) +{ + ANGLE_SKIP_TEST_IF( + !EnsureGLExtensionEnabled("GL_OVR_multiview_multisampled_render_to_texture")); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + constexpr int numLayers = 2; + constexpr GLsizei multisampleRenderToTextureSampleSize = 4; + + // Attach a 2D array texture with glFramebufferTextureMultisampleMultiviewOVR + GLTexture textureArray; + glBindTexture(GL_TEXTURE_2D_ARRAY, textureArray); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWindowSize, kWindowSize, numLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureArray, + 0, multisampleRenderToTextureSampleSize, 0, + numLayers); + ASSERT_GL_NO_ERROR(); + + // Attempt to attach a multisample texture created with glTexStorage2DMultisample to the same + // Framebuffer should fail + GLTexture textureMultisample; + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureMultisample); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, multisampleRenderToTextureSampleSize, + GL_RGBA8, kWindowSize, kWindowSize, GL_TRUE); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, + textureMultisample, 0, + multisampleRenderToTextureSampleSize, 0, numLayers); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewMSRTTES3Test); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewMSRTTES31Test); + +ANGLE_INSTANTIATE_TEST_ES3(MultiviewMSRTTES3Test); +ANGLE_INSTANTIATE_TEST_ES31(MultiviewMSRTTES31Test); + +} // namespace diff --git a/src/tests/gl_tests/OcclusionQueriesTest.cpp b/src/tests/gl_tests/OcclusionQueriesTest.cpp index e70093db335..b4f32d11a54 100644 --- a/src/tests/gl_tests/OcclusionQueriesTest.cpp +++ b/src/tests/gl_tests/OcclusionQueriesTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" @@ -749,8 +753,7 @@ TEST_P(OcclusionQueriesTest, MultiContext) // Test skipped because the D3D backends cannot support simultaneous queries on multiple // contexts yet. - ANGLE_SKIP_TEST_IF(GetParam() == ES2_D3D9() || GetParam() == ES2_D3D11() || - GetParam() == ES3_D3D11()); + ANGLE_SKIP_TEST_IF(IsD3D()); glDepthMask(GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -767,9 +770,9 @@ TEST_P(OcclusionQueriesTest, MultiContext) EGLint contextAttributes[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, - GetParam().majorVersion, + getClientMajorVersion(), EGL_CONTEXT_MINOR_VERSION_KHR, - GetParam().minorVersion, + getClientMinorVersion(), EGL_NONE, }; @@ -999,12 +1002,10 @@ TEST_P(OcclusionQueriesTest, WrongSkippedQuery) EXPECT_EQ(expectation, results[1]); } -class OcclusionQueriesNoSurfaceTestES3 : public ANGLETestBase, - public ::testing::TestWithParam +class OcclusionQueriesNoSurfaceTestES3 : public ANGLETest<> { protected: - OcclusionQueriesNoSurfaceTestES3() - : ANGLETestBase(GetParam()), mUnusedConfig(0), mUnusedDisplay(nullptr) + OcclusionQueriesNoSurfaceTestES3() : mUnusedConfig(0), mUnusedDisplay(nullptr) { setWindowWidth(kWidth); setWindowHeight(kHeight); @@ -1018,9 +1019,6 @@ class OcclusionQueriesNoSurfaceTestES3 : public ANGLETestBase, static constexpr int kWidth = 300; static constexpr int kHeight = 300; - void SetUp() override { ANGLETestBase::ANGLETestSetUp(); } - void TearDown() override { ANGLETestBase::ANGLETestTearDown(); } - void swapBuffers() override {} EGLConfig mUnusedConfig; @@ -1040,9 +1038,9 @@ TEST_P(OcclusionQueriesNoSurfaceTestES3, SwitchingContextsWithQuery) EGLint contextAttributes[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, - GetParam().majorVersion, + getClientMajorVersion(), EGL_CONTEXT_MINOR_VERSION_KHR, - GetParam().minorVersion, + getClientMinorVersion(), EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_TRUE, EGL_NONE, diff --git a/src/tests/gl_tests/PBOExtensionTest.cpp b/src/tests/gl_tests/PBOExtensionTest.cpp index 522feaf221a..4b8ca7cc2cf 100644 --- a/src/tests/gl_tests/PBOExtensionTest.cpp +++ b/src/tests/gl_tests/PBOExtensionTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" using namespace angle; diff --git a/src/tests/gl_tests/PackUnpackTest.cpp b/src/tests/gl_tests/PackUnpackTest.cpp index ceebdcb8207..b34816ba724 100644 --- a/src/tests/gl_tests/PackUnpackTest.cpp +++ b/src/tests/gl_tests/PackUnpackTest.cpp @@ -8,6 +8,7 @@ // #include "test_utils/ANGLETest.h" +#include "test_utils/gl_raii.h" using namespace angle; @@ -223,7 +224,8 @@ TEST_P(PackUnpackTest, PackUnpackHalfZero) TEST_P(PackUnpackTest, PackUnpackUnormOverflow) { // Expect the shader to clamp the input to [0, 1] - compareBeforeAfter(mUNormProgram, 67000.0f, -67000.0f, 1.0f, 0.0f); + // mediump float data range is [2^-14, 2^14] + compareBeforeAfter(mUNormProgram, 16384.0f, -16384.0f, 1.0f, 0.0f); } // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating overflow floating @@ -231,7 +233,34 @@ TEST_P(PackUnpackTest, PackUnpackUnormOverflow) TEST_P(PackUnpackTest, PackUnpackSnormOverflow) { // Expect the shader to clamp the input to [-1, 1] - compareBeforeAfter(mSNormProgram, 67000.0f, -67000.0f, 1.0f, -1.0f); + // mediump float data range is [2^-14, 2^14] + compareBeforeAfter(mSNormProgram, 16384.0f, -16384.0f, 1.0f, -1.0f); +} + +// Test that the SaturateDepth pass in Metal uses the correct buffer size when the unpack image +// height is smaller than the image height. +TEST_P(PackUnpackTest, D32FSaturateDepth) +{ + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 128); + ASSERT_GL_NO_ERROR(); + + std::vector kInitData(1024, 0); + + GLBuffer unpackBuffer; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(float) * kInitData.size(), kInitData.data(), + GL_STATIC_DRAW); + + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 512, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PackUnpackTest); diff --git a/src/tests/gl_tests/gles1/PalettedTextureTest.cpp b/src/tests/gl_tests/PalettedTextureTest.cpp similarity index 53% rename from src/tests/gl_tests/gles1/PalettedTextureTest.cpp rename to src/tests/gl_tests/PalettedTextureTest.cpp index c75a518aca3..991d212fe2a 100644 --- a/src/tests/gl_tests/gles1/PalettedTextureTest.cpp +++ b/src/tests/gl_tests/PalettedTextureTest.cpp @@ -34,10 +34,35 @@ class PalettedTextureTest : public ANGLETest<> } }; +class PalettedTextureTestES2 : public PalettedTextureTest +{}; + +class PalettedTextureTestES3 : public PalettedTextureTest +{}; + +struct TestImage +{ + GLColor palette[16]; + uint8_t texels[2]; // 2x2, each texel is 4-bit +}; + +const TestImage testImage = { + { + GLColor::cyan, + GLColor::yellow, + GLColor::magenta, + GLColor::red, + }, + { + 0x01, + 0x23, + }, +}; + // Check that paletted formats are reported as supported. TEST_P(PalettedTextureTest, PalettedFormatsAreSupported) { - ANGLE_SKIP_TEST_IF(!IsVulkan()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_paletted_texture")); std::vector mustSupportFormats{ GL_PALETTE4_RGB8_OES, GL_PALETTE4_RGBA8_OES, GL_PALETTE4_R5_G6_B5_OES, @@ -62,7 +87,7 @@ TEST_P(PalettedTextureTest, PalettedFormatsAreSupported) // Check that sampling a paletted texture works. TEST_P(PalettedTextureTest, PalettedTextureSampling) { - ANGLE_SKIP_TEST_IF(!IsVulkan()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_paletted_texture")); struct Vertex { @@ -79,24 +104,6 @@ TEST_P(PalettedTextureTest, PalettedTextureSampling) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - struct TestImage - { - GLColor palette[16]; - uint8_t texels[2]; // 2x2, each texel is 4-bit - }; - - TestImage testImage = { - { - GLColor::cyan, - GLColor::yellow, - GLColor::magenta, - GLColor::red, - }, - { - 0x01, - 0x23, - }, - }; glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_PALETTE4_RGBA8_OES, 2, 2, 0, sizeof testImage, &testImage); EXPECT_GL_NO_ERROR(); @@ -138,4 +145,84 @@ TEST_P(PalettedTextureTest, PalettedTextureSampling) } } +// Check that validation for paletted formats is correct. +TEST_P(PalettedTextureTestES2, PalettedFormatsValidation) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_paletted_texture")); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_PALETTE4_RGBA8_OES, 2, 2, 0, sizeof testImage, + &testImage); + EXPECT_GL_NO_ERROR(); + + // Generate GL_INVALID_OPERATION, paletted formats cannot be used for glCompressedTexSubImage2D + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_PALETTE4_RGBA8_OES, 0, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Check that rendering using paletted texture works in GLES2 context. +TEST_P(PalettedTextureTestES2, PalettedTextureDraw) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_paletted_texture")); + + constexpr char kVS[] = R"(precision highp float; + attribute vec4 position; + varying vec2 texcoord; + + void main() + { + gl_Position = position; + texcoord = (position.xy * 0.5) + 0.5; + })"; + + constexpr char kFS[] = R"(precision highp float; + uniform sampler2D tex; + varying vec2 texcoord; + + void main() + { + gl_FragColor = texture2D(tex, texcoord); + })"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_PALETTE4_RGBA8_OES, 2, 2, 0, sizeof testImage, + &testImage); + EXPECT_GL_NO_ERROR(); + + GLint textureUniformLocation = glGetUniformLocation(program, "tex"); + ASSERT_NE(-1, textureUniformLocation); + glUniform1i(textureUniformLocation, 0); + + drawQuad(program, "position", 0.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); + EXPECT_PIXEL_COLOR_EQ(31, 0, GLColor::yellow); + EXPECT_PIXEL_COLOR_EQ(0, 31, GLColor::magenta); + EXPECT_PIXEL_COLOR_EQ(31, 31, GLColor::red); +} + +// glTexStorage2D with paletted formats should fail. +TEST_P(PalettedTextureTestES3, TexStorage2DShouldFail) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_paletted_texture")); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + + glTexStorage2D(GL_TEXTURE_2D, 1, GL_PALETTE4_RGBA8_OES, 2, 2); + EXPECT_GL_ERROR(GL_INVALID_ENUM); +} + ANGLE_INSTANTIATE_TEST_ES1(PalettedTextureTest); + +ANGLE_INSTANTIATE_TEST_ES2(PalettedTextureTestES2); + +ANGLE_INSTANTIATE_TEST_ES3(PalettedTextureTestES3); diff --git a/src/tests/gl_tests/PbufferTest.cpp b/src/tests/gl_tests/PbufferTest.cpp index 9cdce6ef433..e16d5e0caef 100644 --- a/src/tests/gl_tests/PbufferTest.cpp +++ b/src/tests/gl_tests/PbufferTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" @@ -894,6 +898,82 @@ TEST_P(PbufferTest, BindTexImageAndRedefineTexture) glDeleteTextures(1, &texture); } +// Bind a Pbuffer, generate mipmap for it, and verify it renders correctly +TEST_P(PbufferTest, BindTexImageAndGenerateMipmap) +{ + // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA + // textures. + ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage); + // Crash in drawQuad. http://anglebug.com/412867392 + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); + + EGLWindow *window = getEGLWindow(); + + EGLSurface pbuffer; + GLuint texture = 0; + + static EGLint pbufferAttributes[] = { + EGL_WIDTH, 2, + EGL_HEIGHT, 1, + EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_MIPMAP_TEXTURE, GL_TRUE, + EGL_NONE, + }; + + pbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pbufferAttributes); + ASSERT_EGL_SUCCESS(); + + ASSERT_NE(EGL_NO_SURFACE, pbuffer); + + // create texture + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + EXPECT_GL_NO_ERROR(); + + // bind pbuffer as texture storage + eglBindTexImage(window->getDisplay(), pbuffer, EGL_BACK_BUFFER); + ASSERT_EGL_SUCCESS(); + EXPECT_GL_NO_ERROR(); + + unsigned int pixelValue = 0xFFFF00FF; + std::vector pixelData(2, pixelValue); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]); + glGenerateMipmap(GL_TEXTURE_2D); + + glViewport(0, 0, 1, 1); + // Draw a quad and verify that it is magenta + glUseProgram(mTextureProgram); + glUniform1i(mTextureUniformLocation, 0); + + drawQuad(mTextureProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + + // Verify that magenta was drawn + EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255); + + EXPECT_TRUE(eglMakeCurrent(window->getDisplay(), pbuffer, pbuffer, window->getContext())); + ASSERT_EGL_SUCCESS(); + glClearColor(1.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + // Verify that yellow was drawn to pbuffer + EXPECT_PIXEL_EQ(0, 0, 255, 255, 0, 255); + + drawQuad(mTextureProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + + // Verify that the texture color is still magenta (texture is disconnected from pbuffer) + EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255); + + glDeleteTextures(1, &texture); + window->makeCurrent(); + eglDestroySurface(window->getDisplay(), pbuffer); +} + // Bind the Pbuffer to a texture, use that texture as Framebuffer color attachment and then // destroy framebuffer, texture and Pbuffer. TEST_P(PbufferTest, UseAsFramebufferColorThenDestroy) @@ -1070,6 +1150,105 @@ TEST_P(PbufferColorspaceTest, CreateSurfaceWithColorspace) } } +// Test the implementation for EGL_LARGEST_PBUFFER +TEST_P(PbufferTest, LargestPbuffer) +{ + ANGLE_SKIP_TEST_IF(!mSupportsPbuffers); + ANGLE_SKIP_TEST_IF(!IsARM()); + EGLWindow *window = getEGLWindow(); + EGLDisplay display = window->getDisplay(); + EGLSurface pbufferSurface; + + EGLint maxPbufferWidth; + EGLint maxPbufferHeight; + EGLint value; + EGLint pBufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, + EGL_LARGEST_PBUFFER, EGL_FALSE, EGL_NONE}; + + // Check that eglCreatePbufferSurface can succeed when EGL_LARGEST_PBUFFER is set to EGL_FALSE + pbufferSurface = eglCreatePbufferSurface(display, window->getConfig(), pBufferAttributes); + ASSERT_NE(pbufferSurface, EGL_NO_SURFACE); + ASSERT_EGL_SUCCESS(); + + // Cleanup + eglDestroySurface(display, pbufferSurface); + + EXPECT_EGL_TRUE( + eglGetConfigAttrib(display, window->getConfig(), EGL_MAX_PBUFFER_WIDTH, &maxPbufferWidth)); + pBufferAttributes[1] = maxPbufferWidth + 1; + pBufferAttributes[5] = EGL_TRUE; + + // Check that eglCreatePbufferSurface clamps an EGL_WIDTH that is too large with + // EGL_LARGEST_PBUFFER set + pbufferSurface = eglCreatePbufferSurface(display, window->getConfig(), pBufferAttributes); + ASSERT_NE(pbufferSurface, EGL_NO_SURFACE); + ASSERT_EGL_SUCCESS(); + + EXPECT_EGL_TRUE(eglQuerySurface(display, pbufferSurface, EGL_WIDTH, &value)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(value, maxPbufferWidth); + + // Cleanup + eglDestroySurface(display, pbufferSurface); + + pBufferAttributes[1] = 1; + + EXPECT_EGL_TRUE(eglGetConfigAttrib(display, window->getConfig(), EGL_MAX_PBUFFER_HEIGHT, + &maxPbufferHeight)); + pBufferAttributes[3] = maxPbufferHeight + 1; + + // Check that eglCreatePbufferSurface clamps an EGL_HEIGHT that is too large with + // EGL_LARGEST_PBUFFER set + pbufferSurface = eglCreatePbufferSurface(display, window->getConfig(), pBufferAttributes); + ASSERT_NE(pbufferSurface, EGL_NO_SURFACE); + ASSERT_EGL_SUCCESS(); + + EXPECT_EGL_TRUE(eglQuerySurface(display, pbufferSurface, EGL_HEIGHT, &value)); + ASSERT_EGL_SUCCESS(); + ASSERT_EQ(value, maxPbufferHeight); + + // Cleanup + eglDestroySurface(display, pbufferSurface); +} + +// Test the implementation for query format sizes from zero sized pbuffer surface +TEST_P(PbufferTest, ZeroSizedSurfaceFormatQuery) +{ + ANGLE_SKIP_TEST_IF(!mSupportsPbuffers); + EGLWindow *window = getEGLWindow(); + EGLDisplay display = window->getDisplay(); + EGLSurface pbufferSurface; + + EGLint pBufferAttributes[] = {EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_NONE}; + + pbufferSurface = eglCreatePbufferSurface(display, window->getConfig(), pBufferAttributes); + ASSERT_NE(pbufferSurface, EGL_NO_SURFACE); + ASSERT_EGL_SUCCESS(); + + EGLint width, height; + EXPECT_EGL_TRUE(eglQuerySurface(display, pbufferSurface, EGL_WIDTH, &width)); + EXPECT_EGL_TRUE(eglQuerySurface(display, pbufferSurface, EGL_HEIGHT, &height)); + EXPECT_EQ(width, 0); + EXPECT_EQ(height, 0); + + window->makeCurrent(pbufferSurface, pbufferSurface, window->getContext()); + + GLint redBits, greenBits, blueBits, alphaBits; + glGetIntegerv(GL_RED_BITS, &redBits); + glGetIntegerv(GL_GREEN_BITS, &greenBits); + glGetIntegerv(GL_BLUE_BITS, &blueBits); + glGetIntegerv(GL_ALPHA_BITS, &alphaBits); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(redBits, 8); + EXPECT_EQ(greenBits, 8); + EXPECT_EQ(blueBits, 8); + EXPECT_EQ(alphaBits, 8); + + // Cleanup + window->makeCurrent(); + eglDestroySurface(display, pbufferSurface); +} + ANGLE_INSTANTIATE_TEST_ES2(PbufferTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PbufferColorspaceTest); diff --git a/src/tests/gl_tests/PixelLocalStorageTest.cpp b/src/tests/gl_tests/PixelLocalStorageTest.cpp index 0825f2e4169..f9339634e37 100644 --- a/src/tests/gl_tests/PixelLocalStorageTest.cpp +++ b/src/tests/gl_tests/PixelLocalStorageTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include "test_utils/ANGLETest.h" @@ -42,15 +46,15 @@ using namespace angle; EXPECT_EQ(nextError, GLenum(GL_NO_ERROR)); \ } -#define EXPECT_GL_SINGLE_ERROR_MSG(msg) \ - if (mHasDebugKHR) \ - { \ - EXPECT_EQ(mErrorMessages.size(), size_t(1)); \ - if (mErrorMessages.size() == 1) \ - { \ - EXPECT_EQ(std::string(msg), mErrorMessages.back()); \ - } \ - mErrorMessages.clear(); \ +#define EXPECT_GL_SINGLE_ERROR_MSG(msg) \ + if (mHasDebugKHR) \ + { \ + EXPECT_EQ(mErrorMessages.size(), size_t(1)); \ + if (mErrorMessages.size() == 1) \ + { \ + EXPECT_NE(mErrorMessages.back().find(std::string(msg)), std::string::npos); \ + } \ + mErrorMessages.clear(); \ } #define EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(plane, rgba) \ @@ -112,14 +116,38 @@ using namespace angle; EXPECT_EQ(value, static_cast(expectedValue)); \ } +#define EXPECT_FRAMEBUFFER_ATTACHMENT_TYPE(framebuffer, attachment, value) \ + { \ + GLint attachmentType = 1234567890; \ + glGetFramebufferAttachmentParameteriv( \ + framebuffer, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType); \ + EXPECT_EQ(attachmentType, static_cast(value)); \ + } + #define EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(framebuffer, attachment, value) \ { \ - GLint attachmentName = 0xbaadc0de; \ + GLint attachmentName = 1234567890; \ glGetFramebufferAttachmentParameteriv( \ framebuffer, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attachmentName); \ EXPECT_EQ(attachmentName, static_cast(value)); \ } +#define EXPECT_FRAMEBUFFER_ATTACHMENT_LEVEL(framebuffer, attachment, value) \ + { \ + GLint attachmentLevel = 1234567890; \ + glGetFramebufferAttachmentParameteriv( \ + framebuffer, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &attachmentLevel); \ + EXPECT_EQ(attachmentLevel, static_cast(value)); \ + } + +#define EXPECT_FRAMEBUFFER_ATTACHMENT_LAYER(framebuffer, attachment, value) \ + { \ + GLint attachmentLayer = 1234567890; \ + glGetFramebufferAttachmentParameteriv( \ + framebuffer, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, &attachmentLayer); \ + EXPECT_EQ(attachmentLayer, static_cast(value)); \ + } + #define EXPECT_GL_COLOR_MASK(r, g, b, a) \ { \ std::array mask; \ @@ -177,20 +205,24 @@ class PLSTestTexture { public: PLSTestTexture(GLenum internalformat) { reset(internalformat); } - PLSTestTexture(GLenum internalformat, int w, int h) { reset(internalformat, w, h); } + PLSTestTexture(GLenum internalformat, int w, int h) { reset(internalformat, w, h, 1); } + PLSTestTexture(GLenum internalformat, int w, int h, int mipLevels) + { + reset(internalformat, w, h, mipLevels); + } PLSTestTexture(PLSTestTexture &&that) : mID(std::exchange(that.mID, 0)) {} void reset() { glDeleteTextures(1, &mID); mID = 0; } - void reset(GLenum internalformat) { reset(internalformat, W, H); } - void reset(GLenum internalformat, int w, int h) + void reset(GLenum internalformat) { reset(internalformat, W, H, 1); } + void reset(GLenum internalformat, int w, int h, int mipLevels) { GLuint id; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); - glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, w, h); + glTexStorage2D(GL_TEXTURE_2D, mipLevels, internalformat, w, h); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (mID) @@ -207,6 +239,7 @@ class PLSTestTexture } } operator GLuint() const { return mID; } + GLuint id() const { return mID; } private: PLSTestTexture &operator=(const PLSTestTexture &) = delete; @@ -231,10 +264,11 @@ struct Box float4 aux2; }; -enum class UseBarriers : bool +enum class UseBarriers { - No = false, - IfNotCoherent + Never, + IfNotCoherent, + Always, }; class PLSProgram @@ -386,8 +420,9 @@ class PLSProgram glBufferData(GL_ARRAY_BUFFER, boxes.size() * sizeof(Box), boxes.data(), GL_STATIC_DRAW); base = 0; } - if (useBarriers == UseBarriers::IfNotCoherent && - !IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")) + if ((useBarriers == UseBarriers::IfNotCoherent && + !IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")) || + useBarriers == UseBarriers::Always) { for (size_t i = 0; i < boxes.size(); ++i) { @@ -504,8 +539,6 @@ class PixelLocalStorageTest : public ANGLETest<> if (EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")) { glGetIntegerv(GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE, &MAX_PIXEL_LOCAL_STORAGE_PLANES); - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE, - &MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE); glGetIntegerv(GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE, &MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES); glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &MAX_COLOR_ATTACHMENTS); @@ -535,6 +568,17 @@ class PixelLocalStorageTest : public ANGLETest<> ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); } + void attachTextureCubeFaceToScratchFBO(GLuint tex, GLenum target, GLint level = 0) + { + if (!mScratchFBO) + { + glGenFramebuffers(1, &mScratchFBO); + } + glBindFramebuffer(GL_FRAMEBUFFER, mScratchFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex, level); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + } + void attachTextureLayerToScratchFBO(GLuint tex, int level, int layer) { if (!mScratchFBO) @@ -592,15 +636,20 @@ class PixelLocalStorageTest : public ANGLETest<> glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } + // Tests that run with and without the "noncoherent" qualifier. + void doRGBA8Test(bool noncoherent); + void doR32Test(bool noncoherent); + void doCoherencyTest(bool noncoherent); + // Implemented as a class members so we can run the test on ES3 and ES31 both. void doStateRestorationTest(); void doDrawStateTest(); void doImplicitDisablesTest_Framebuffer(); void doImplicitDisablesTest_TextureAttachments(); void doImplicitDisablesTest_RenderbufferAttachments(); + void doImplicitDisablesTest_Invalidate(); GLint MAX_PIXEL_LOCAL_STORAGE_PLANES = 0; - GLint MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE = 0; GLint MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES = 0; GLint MAX_COLOR_ATTACHMENTS = 0; GLint MAX_DRAW_BUFFERS = 0; @@ -618,14 +667,12 @@ TEST_P(PixelLocalStorageTest, ImplementationDependentLimits) // Table 6.X: Impementation Dependent Pixel Local Storage Limits. EXPECT_TRUE(MAX_PIXEL_LOCAL_STORAGE_PLANES >= 4); - EXPECT_TRUE(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE >= 0); EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= 4); // Logical deductions based on 6.X. EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= MAX_PIXEL_LOCAL_STORAGE_PLANES); - EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE); + EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= MAX_DRAW_BUFFERS); EXPECT_TRUE(MAX_COLOR_ATTACHMENTS + MAX_PIXEL_LOCAL_STORAGE_PLANES >= MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES); EXPECT_TRUE(MAX_DRAW_BUFFERS + MAX_PIXEL_LOCAL_STORAGE_PLANES >= @@ -633,20 +680,31 @@ TEST_P(PixelLocalStorageTest, ImplementationDependentLimits) } // Verify that rgba8, rgba8i, and rgba8ui pixel local storage behaves as specified. -TEST_P(PixelLocalStorageTest, RGBA8) +void PixelLocalStorageTest::doRGBA8Test(bool noncoherent) { - ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); - - mProgram.compile(R"( + std::ostringstream shader; + if (noncoherent) + { + shader << R"( + layout(binding=0, rgba8, noncoherent) uniform lowp pixelLocalANGLE plane1; + layout(rgba8i, noncoherent, binding=1) uniform lowp ipixelLocalANGLE plane2; + layout(noncoherent, binding=2, rgba8ui) uniform lowp upixelLocalANGLE plane3;)"; + } + else + { + shader << R"( layout(binding=0, rgba8) uniform lowp pixelLocalANGLE plane1; layout(rgba8i, binding=1) uniform lowp ipixelLocalANGLE plane2; - layout(binding=2, rgba8ui) uniform lowp upixelLocalANGLE plane3; - void main() - { - pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1)); - pixelLocalStoreANGLE(plane2, ivec4(aux1) + pixelLocalLoadANGLE(plane2)); - pixelLocalStoreANGLE(plane3, uvec4(aux2) + pixelLocalLoadANGLE(plane3)); - })"); + layout(binding=2, rgba8ui) uniform lowp upixelLocalANGLE plane3;)"; + } + shader << R"( + void main() + { + pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1)); + pixelLocalStoreANGLE(plane2, ivec4(aux1) + pixelLocalLoadANGLE(plane2)); + pixelLocalStoreANGLE(plane3, uvec4(aux2) + pixelLocalLoadANGLE(plane3)); + })"; + mProgram.compile(shader.str().c_str()); PLSTestTexture tex1(GL_RGBA8); PLSTestTexture tex2(GL_RGBA8I); @@ -668,7 +726,8 @@ TEST_P(PixelLocalStorageTest, RGBA8) mProgram.drawBoxes({{FULLSCREEN, {2, -1, -2, -3}, {-500, 0, 0, 0}, {1, 0, 0, 0}}, {FULLSCREEN, {0, 1, 0, 100}, {0, -129, 0, 0}, {0, 50, 0, 0}}, {FULLSCREEN, {0, 0, 1, 0}, {0, 0, -70, 0}, {0, 0, 100, 0}}, - {FULLSCREEN, {0, 0, 0, -1}, {128, 0, 0, 500}, {0, 0, 0, 300}}}); + {FULLSCREEN, {0, 0, 0, -1}, {128, 0, 0, 500}, {0, 0, 0, 300}}}, + noncoherent ? UseBarriers::Always : UseBarriers::IfNotCoherent); glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); @@ -685,43 +744,78 @@ TEST_P(PixelLocalStorageTest, RGBA8) ASSERT_GL_NO_ERROR(); } -// Verify that r32f and r32ui pixel local storage behaves as specified. -TEST_P(PixelLocalStorageTest, R32) +// Verify that rgba8, rgba8i, and rgba8ui pixel local storage behaves as specified. +TEST_P(PixelLocalStorageTest, RGBA8) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + doRGBA8Test(/*noncoherent=*/false); +} - mProgram.compile(R"( +// Verify that rgba8, rgba8i, and rgba8ui pixel local storage behaves as specified when using the +// "noncoherent" qualifier. +TEST_P(PixelLocalStorageTest, RGBA8_noncoherent) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + doRGBA8Test(/*noncoherent=*/true); +} + +// Verify that r32f, r32i, and r32ui pixel local storage behaves as specified. +void PixelLocalStorageTest::doR32Test(bool noncoherent) +{ + std::ostringstream shader; + if (noncoherent) + { + shader << R"( + layout(noncoherent, r32f, binding=0) uniform highp pixelLocalANGLE plane1; + layout(binding=1, noncoherent, r32i) uniform highp ipixelLocalANGLE plane2; + layout(r32ui, binding=2, noncoherent) uniform highp upixelLocalANGLE plane3;)"; + } + else + { + shader << R"( layout(r32f, binding=0) uniform highp pixelLocalANGLE plane1; - layout(binding=1, r32ui) uniform highp upixelLocalANGLE plane2; - void main() - { - pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1)); - pixelLocalStoreANGLE(plane2, uvec4(aux1) + pixelLocalLoadANGLE(plane2)); - })"); + layout(binding=1, r32i) uniform highp ipixelLocalANGLE plane2; + layout(r32ui, binding=2) uniform highp upixelLocalANGLE plane3;)"; + } + shader << R"( + void main() + { + pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1)); + pixelLocalStoreANGLE(plane2, ivec4(aux1) + pixelLocalLoadANGLE(plane2)); + pixelLocalStoreANGLE(plane3, uvec4(aux2) + pixelLocalLoadANGLE(plane3)); + })"; + mProgram.compile(shader.str().c_str()); PLSTestTexture tex1(GL_R32F); - PLSTestTexture tex2(GL_R32UI); + PLSTestTexture tex2(GL_R32I); + PLSTestTexture tex3(GL_R32UI); GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexturePixelLocalStorageANGLE(0, tex1, 0, 0); glFramebufferTexturePixelLocalStorageANGLE(1, tex2, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(2, tex3, 0, 0); glViewport(0, 0, W, H); glDrawBuffers(0, nullptr); - glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); // Accumulate R in 4 separate passes. - mProgram.drawBoxes({{FULLSCREEN, {-1.5, 0, 0, 0}, {0x000000ff, 0, 0, 0}}, - {FULLSCREEN, {-10.25, 0, 0, 0}, {0x0000ff00, 0, 0, 0}}, - {FULLSCREEN, {-100, 0, 0, 0}, {0x00ff0000, 0, 0, 0}}, - {FULLSCREEN, {.25, 0, 0, 0}, {0xff000000, 0, 0, 22}}}); + mProgram.drawBoxes( + {{FULLSCREEN, {-1.5, 0, 0, 0}, {0x000000ff, 0, 0, 0}, {0x000000ff, 0, 0, 0}}, + {FULLSCREEN, {-10.25, 0, 0, 0}, {0x0000ff00, 0, 0, 0}, {0x0000ff00, 0, 0, 0}}, + {FULLSCREEN, {-100, 0, 0, 0}, {0x00ff0000, 0, 0, 0}, {0x00ff0000, 0, 0, 0}}, + {FULLSCREEN, {.25, 0, 0, 0}, {-0x1000000, 0, 0, 0}, {0xff000000, 0, 0, 22}}}, + noncoherent ? UseBarriers::Always : UseBarriers::IfNotCoherent); - glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, + GL_STORE_OP_STORE_ANGLE})); // These values should be exact matches. // - // GL_R32F is spec'd as a 32-bit IEEE float, and GL_R32UI is a 32-bit unsigned integer. + // GL_R32F is spec'd as a 32-bit IEEE float, GL_R32I is a 32-bit signed integer, + // and GL_R32UI is a 32-bit unsigned integer. // There is some affordance for fp32 fused operations, but "a + b" is required to be // correctly rounded. // @@ -740,11 +834,31 @@ TEST_P(PixelLocalStorageTest, R32) EXPECT_PIXEL_RECT32F_EQ(0, 0, W, H, GLColor32F(-111.5, 0, 0, 1)); attachTexture2DToScratchFBO(tex2); + EXPECT_PIXEL_RECT32I_EQ(0, 0, W, H, GLColor32I(-1, 0, 0, 1)); + + attachTexture2DToScratchFBO(tex3); EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(0xffffffff, 0, 0, 1)); ASSERT_GL_NO_ERROR(); } +// Verify that r32f, r32i, and r32ui pixel local storage behaves as specified. +TEST_P(PixelLocalStorageTest, R32) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); + doR32Test(/*noncoherent=*/false); +} + +// Verify that r32f, r32i, and r32ui pixel local storage behaves as specified +// when using the "noncoherent" qualifier. +TEST_P(PixelLocalStorageTest, R32_noncoherent) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); + doR32Test(/*noncoherent=*/true); +} + // Check proper functioning of the clear value state. TEST_P(PixelLocalStorageTest, ClearValues_rgba8) { @@ -914,31 +1028,108 @@ TEST_P(PixelLocalStorageTest, ClearValues_rgba8) EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0)); } -// Check clear values for r32f and r32ui PLS format. +// Check clear values for r32f, r32i, and r32ui PLS format. TEST_P(PixelLocalStorageTest, ClearValues_r32) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); // Test custom R32 clear values. PLSTestTexture tex32f(GL_R32F); + PLSTestTexture tex32i(GL_R32I); PLSTestTexture tex32ui(GL_R32UI); glFramebufferTexturePixelLocalStorageANGLE(0, tex32f, 0, 0); - glFramebufferTexturePixelLocalStorageANGLE(1, tex32ui, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, tex32i, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(2, tex32ui, 0, 0); glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(100.5, 0, 0, 0)); - glFramebufferPixelLocalClearValueuivANGLE(1, ClearUI(0xbaadbeef, 1, 1, 0)); - glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE})); + glFramebufferPixelLocalClearValueivANGLE(1, ClearI(-2, 1, 0, 0)); + glFramebufferPixelLocalClearValueuivANGLE(2, ClearUI(0xbaadbeef, 1, 1, 0)); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({100.5f, 0, 0, 0})); - EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(1, ({0xbaadbeef, 1, 1, 0})); - glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({-2, 1, 0, 0})); + EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({0xbaadbeef, 1, 1, 0})); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, + GL_STORE_OP_STORE_ANGLE})); attachTexture2DToScratchFBO(tex32f); EXPECT_PIXEL_RECT32F_EQ(0, 0, 1, 1, GLColor32F(100.5f, 0, 0, 1)); + attachTexture2DToScratchFBO(tex32i); + EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(-2, 0, 0, 1)); attachTexture2DToScratchFBO(tex32ui); EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0xbaadbeef, 0, 0, 1)); } +// Check type conversions of PLS state queries. +TEST_P(PixelLocalStorageTest, ClearValueConversions) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1.0f, 2.0f, 3.0f, 4.0f)); + glFramebufferPixelLocalClearValueivANGLE(0, ClearI(-5, -6, -7, -8)); + glFramebufferPixelLocalClearValueuivANGLE( + 0, ClearUI(2147483648, 2147483649, 2147483650, 2147483651)); + ASSERT_GL_NO_ERROR(); + + { + GLfloat value[4]{}; + glGetFramebufferPixelLocalStorageParameterfvANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, + value); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(value[0], 1.0f); + EXPECT_EQ(value[1], 2.0f); + EXPECT_EQ(value[2], 3.0f); + EXPECT_EQ(value[3], 4.0f); + + glGetFramebufferPixelLocalStorageParameterfvANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, + value); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(value[0], -5.0f); + EXPECT_EQ(value[1], -6.0f); + EXPECT_EQ(value[2], -7.0f); + EXPECT_EQ(value[3], -8.0f); + + glGetFramebufferPixelLocalStorageParameterfvANGLE( + 0, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, value); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(value[0], 2147483648.0f); + EXPECT_EQ(value[1], 2147483648.0f); // closest f32 to 2147483649 + EXPECT_EQ(value[2], 2147483648.0f); // closest f32 to 2147483650 + EXPECT_EQ(value[3], 2147483648.0f); // closest f32 to 2147483651 + } + { + GLint value[4]{}; + glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, + value); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(value[0], 1); + EXPECT_EQ(value[1], 2); + EXPECT_EQ(value[2], 3); + EXPECT_EQ(value[3], 4); + + glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, + value); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(value[0], -5); + EXPECT_EQ(value[1], -6); + EXPECT_EQ(value[2], -7); + EXPECT_EQ(value[3], -8); + + glGetFramebufferPixelLocalStorageParameterivANGLE( + 0, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, value); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(static_cast(value[0]), 2147483648); + EXPECT_EQ(static_cast(value[1]), 2147483649); + EXPECT_EQ(static_cast(value[2]), 2147483650); + EXPECT_EQ(static_cast(value[3]), 2147483651); + } +} + // Check proper support of GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_LOAD_ANGLE, and GL_LOAD_OP_CLEAR_ANGLE // loadOps. Also verify that it works do draw with GL_MAX_LOCAL_STORAGE_PLANES_ANGLE planes. TEST_P(PixelLocalStorageTest, LoadOps) @@ -957,7 +1148,7 @@ TEST_P(PixelLocalStorageTest, LoadOps) << "));\n"; } fs << "}"; - mProgram.compile(fs.str().c_str()); + mProgram.compile(fs.str()); // Create pls textures and clear them to red. glClearColor(1, 0, 0, 1); @@ -1218,6 +1409,7 @@ TEST_P(PixelLocalStorageTest, FragmentReject_viewport) TEST_P(PixelLocalStorageTest, ForgetBarrier) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); mProgram.compile(R"( layout(binding=0, r32f) uniform highp pixelLocalANGLE framebuffer; @@ -1266,9 +1458,9 @@ TEST_P(PixelLocalStorageTest, ForgetBarrier) // First make sure it works properly with a barrier. glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); - mProgram.drawBoxes(boxesA_100, UseBarriers::No); + mProgram.drawBoxes(boxesA_100, UseBarriers::Never); glPixelLocalStorageBarrierANGLE(); - mProgram.drawBoxes(boxesB_7, UseBarriers::No); + mProgram.drawBoxes(boxesB_7, UseBarriers::Never); glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); attachTexture2DToScratchFBO(tex); @@ -1285,9 +1477,9 @@ TEST_P(PixelLocalStorageTest, ForgetBarrier) // constraints. glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); - mProgram.drawBoxes(boxesA_100, UseBarriers::No); + mProgram.drawBoxes(boxesA_100, UseBarriers::Never); // OOPS! We forgot to insert a barrier! - mProgram.drawBoxes(boxesB_7, UseBarriers::No); + mProgram.drawBoxes(boxesB_7, UseBarriers::Never); glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); float pixels[H * W * 4]; @@ -1343,6 +1535,10 @@ TEST_P(PixelLocalStorageTest, MemorylessStorage) glViewport(0, 0, W, H); glDrawBuffers(0, nullptr); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + + // Draw into memoryless storage. + // (Also validates that compiling works while PLS is active.) PLSProgram drawMemorylessProgram; drawMemorylessProgram.compile(R"( layout(binding=0, rgba8) uniform highp pixelLocalANGLE framebuffer; @@ -1352,6 +1548,14 @@ TEST_P(PixelLocalStorageTest, MemorylessStorage) pixelLocalStoreANGLE(memoryless, color + pixelLocalLoadANGLE(memoryless)); })"); + drawMemorylessProgram.drawBoxes({{{0, 20, W, H}, {1, 0, 0, 0}}, + {{0, 40, W, H}, {0, 1, 0, 0}}, + {{0, 60, W, H}, {0, 0, 1, 0}}}); + + ASSERT_GL_NO_ERROR(); + + // Transfer to a texture. + // (Also validates that compiling works while PLS is active.) PLSProgram transferToTextureProgram; transferToTextureProgram.compile(R"( layout(binding=0, rgba8) uniform highp pixelLocalANGLE framebuffer; @@ -1360,19 +1564,6 @@ TEST_P(PixelLocalStorageTest, MemorylessStorage) { pixelLocalStoreANGLE(framebuffer, vec4(1) - pixelLocalLoadANGLE(memoryless)); })"); - - glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); - - // Draw into memoryless storage. - drawMemorylessProgram.bind(); - drawMemorylessProgram.drawBoxes({{{0, 20, W, H}, {1, 0, 0, 0}}, - {{0, 40, W, H}, {0, 1, 0, 0}}, - {{0, 60, W, H}, {0, 0, 1, 0}}}); - - ASSERT_GL_NO_ERROR(); - - // Transfer to a texture. - transferToTextureProgram.bind(); transferToTextureProgram.drawBoxes({{FULLSCREEN}}); glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE})); @@ -1401,8 +1592,7 @@ TEST_P(PixelLocalStorageTest, MaxCombinedDrawBuffersAndPLSPlanes) for (int numDrawBuffers : {0, 1, MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1}) { - numDrawBuffers = - std::min(numDrawBuffers, MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE); + numDrawBuffers = std::min(numDrawBuffers, MAX_DRAW_BUFFERS); int numPLSPlanes = MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numDrawBuffers; numPLSPlanes = std::min(numPLSPlanes, MAX_PIXEL_LOCAL_STORAGE_PLANES); @@ -1440,7 +1630,7 @@ TEST_P(PixelLocalStorageTest, MaxCombinedDrawBuffersAndPLSPlanes) fs << "out" << i << " = uvec4(aux1) + uvec4(" << i << ");\n"; } fs << "}"; - mProgram.compile(fs.str().c_str()); + mProgram.compile(fs.str()); glViewport(0, 0, W, H); @@ -1558,6 +1748,7 @@ TEST_P(PixelLocalStorageTest, ProgramCache) TEST_P(PixelLocalStorageTest, LoadOnly) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); PLSTestTexture tex(GL_RGBA8); @@ -1631,13 +1822,11 @@ TEST_P(PixelLocalStorageTest, LoadOnly) glBindFramebuffer(GL_FRAMEBUFFER, fbo); PLSTestTexture tex2(GL_RGBA8); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) - { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0); - glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0})); - glClear(GL_COLOR_BUFFER_BIT); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0); + glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0})); + glClear(GL_COLOR_BUFFER_BIT); - mProgram.compile(R"( + mProgram.compile(R"( layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless; layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex; out vec4 fragcolor; @@ -1646,24 +1835,7 @@ TEST_P(PixelLocalStorageTest, LoadOnly) fragcolor = 1.0 - pixelLocalLoadANGLE(tex); })"); - glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE})); - } - else - { - glFramebufferTexturePixelLocalStorageANGLE(2, tex2, 0, 0); - - mProgram.compile(R"( - layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless; - layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex; - layout(binding=2, rgba8) uniform highp pixelLocalANGLE fragcolor; - void main() - { - pixelLocalStoreANGLE(fragcolor, 1.0 - pixelLocalLoadANGLE(tex)); - })"); - - glBeginPixelLocalStorageANGLE( - 3, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); - } + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE})); mProgram.drawBoxes({{FULLSCREEN}}); @@ -1673,10 +1845,6 @@ TEST_P(PixelLocalStorageTest, LoadOnly) n, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); // Ensure "tex" was properly read in the shader. - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0) - { - attachTexture2DToScratchFBO(tex2); - } EXPECT_PIXEL_RECT_EQ(0, 0, 64, 64, GLColor(0, 0, 0, 0)); EXPECT_PIXEL_RECT_EQ(64, 0, W - 64, 64, GLColor(255, 0, 0, 0)); EXPECT_PIXEL_RECT_EQ(0, 64, 64, H - 64, GLColor(0, 0, 255, 0)); @@ -1696,6 +1864,7 @@ TEST_P(PixelLocalStorageTest, LoadOnly) TEST_P(PixelLocalStorageTest, LoadAfterStore) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); // Run a fibonacci loop that stores and loads the same PLS multiple times. mProgram.compile(R"( @@ -1733,71 +1902,43 @@ TEST_P(PixelLocalStorageTest, LoadAfterStore) ASSERT_GL_NO_ERROR(); - // Now verify that r32f and r32ui still reload as (r, 0, 0, 1), even after an in-shader store. - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) - { - mProgram.compile(R"( + // Now verify that r32f, r32i, and r32ui still reload as (r, 0, 0, 1), even after an in-shader + // store. + mProgram.compile(R"( layout(binding=0, r32f) uniform highp pixelLocalANGLE pls32f; - layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls32ui; + layout(binding=1, r32i) uniform highp ipixelLocalANGLE pls32i; + layout(binding=2, r32ui) uniform highp upixelLocalANGLE pls32ui; out vec4 fragcolor; void main() { pixelLocalStoreANGLE(pls32f, vec4(1, .5, .5, .5)); + pixelLocalStoreANGLE(pls32i, ivec4(1, -1, -1, 0)); pixelLocalStoreANGLE(pls32ui, uvec4(1, 1, 1, 0)); - if ((int(floor(gl_FragCoord.x)) & 1) == 0) + lowp int index = int(floor(gl_FragCoord.x)) % 3; + if (index == 0) fragcolor = pixelLocalLoadANGLE(pls32f); + else if (index == 1) + fragcolor = vec4(pixelLocalLoadANGLE(pls32i)); else fragcolor = vec4(pixelLocalLoadANGLE(pls32ui)); })"); - tex.reset(GL_RGBA8); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F); - glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_R32UI); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); - glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0})); - - glBeginPixelLocalStorageANGLE(2, - GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); - } - else - { - mProgram.compile(R"( - layout(binding=0, r32f) uniform highp pixelLocalANGLE pls32f; - layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls32ui; - layout(binding=2, rgba8) uniform highp pixelLocalANGLE fragcolor; - void main() - { - pixelLocalStoreANGLE(pls32f, vec4(1, .5, .5, .5)); - pixelLocalStoreANGLE(pls32ui, uvec4(1, 1, 1, 0)); - if ((int(floor(gl_FragCoord.x)) & 1) == 0) - pixelLocalStoreANGLE(fragcolor, pixelLocalLoadANGLE(pls32f)); - else - pixelLocalStoreANGLE(fragcolor, vec4(pixelLocalLoadANGLE(pls32ui))); - })"); - - tex.reset(GL_RGBA8); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F); - glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_R32UI); - glFramebufferTexturePixelLocalStorageANGLE(2, tex, 0, 0); + tex.reset(GL_RGBA8); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F); + glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_R32I); + glFramebufferMemorylessPixelLocalStorageANGLE(2, GL_R32UI); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0})); - glBeginPixelLocalStorageANGLE( - 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_DONT_CARE})); - } + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); mProgram.drawBoxes({{FULLSCREEN}}); - int n; - glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n); - glEndPixelLocalStorageANGLE(n, - GLenumArray({GL_DONT_CARE, GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE})); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE})); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0) - { - attachTexture2DToScratchFBO(tex); - } EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(255, 0, 0, 255)); ASSERT_GL_NO_ERROR(); } @@ -1806,6 +1947,7 @@ TEST_P(PixelLocalStorageTest, LoadAfterStore) TEST_P(PixelLocalStorageTest, FunctionArguments) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); mProgram.compile(R"( layout(binding=0, rgba8) uniform lowp pixelLocalANGLE dst; @@ -1856,14 +1998,26 @@ TEST_P(PixelLocalStorageTest, FunctionArguments) ASSERT_GL_NO_ERROR(); } -// Check that if the "_coherent" extension is advertised, PLS operations are ordered and coherent. -TEST_P(PixelLocalStorageTest, Coherency) +// Check that large amounts of overlapping draws are ordered and coherent, either implicitly via the +// "_coherent" extension, or explicitly via app-suppied barrier commands. +void PixelLocalStorageTest::doCoherencyTest(bool noncoherent) { - ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); - - mProgram.compile(R"( - layout(binding=0, rgba8ui) uniform lowp upixelLocalANGLE framebuffer; - layout(binding=1, rgba8) uniform lowp pixelLocalANGLE tmp; + std::ostringstream shader; + if (noncoherent) + { + shader << R"( + layout(binding=0, rgba8ui, noncoherent) uniform lowp upixelLocalANGLE framebuffer; + layout(binding=1, rgba8, noncoherent) uniform lowp pixelLocalANGLE tmp;)"; + } + else + { + shader << R"( + layout(binding=0, rgba8ui) uniform lowp upixelLocalANGLE framebuffer; + layout(binding=1, rgba8) uniform lowp pixelLocalANGLE tmp;)"; + } + shader << R"( + // Defining a noncoherent plane shouldn't make the others noncoherent. + layout(binding=2, rgba8ui, noncoherent) uniform lowp upixelLocalANGLE framebufferNoncoherent; // The application shouldn't be able to override internal synchronization functions used by // the compiler. // @@ -1881,16 +2035,28 @@ TEST_P(PixelLocalStorageTest, Coherency) { highp uvec4 d = pixelLocalLoadANGLE(framebuffer) >> 1; pixelLocalStoreANGLE(framebuffer, uvec4(color) + d); + + // NOTE: This isn't valid without barriers since the plane is noncoherent. We do this to + // verify that if 'd' above is coherent, accessing this noncoherent plane doesn't + // disable the interlock and make 'd' noncoherent as well. + highp uvec4 dNoncoherent = pixelLocalLoadANGLE(framebufferNoncoherent) >> 1; + pixelLocalStoreANGLE(framebufferNoncoherent, uvec4(color) + dNoncoherent); + + // Make sure the compiler doesn't call our overloads of GLSL functions it might be using + // for synchronization. beginInvocationInterlockNV(); endInvocationInterlockARB(); - })"); + })"; + mProgram.compile(shader.str().c_str()); PLSTestTexture tex(GL_RGBA8UI); + PLSTestTexture texNoncoherent(GL_RGBA8UI); GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0); glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_RGBA8); + glFramebufferTexturePixelLocalStorageANGLE(2, texNoncoherent, 0, 0); glViewport(0, 0, W, H); glDrawBuffers(0, nullptr); @@ -1900,6 +2066,7 @@ TEST_P(PixelLocalStorageTest, Coherency) // This test times out on Swiftshader and noncoherent backends if we draw anywhere near the // same number of boxes as we do on coherent, hardware backends. int boxesPerList = !IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent") || + noncoherent || strstr((const char *)glGetString(GL_RENDERER), "SwiftShader") ? 200 : H * W * 3; @@ -1939,22 +2106,28 @@ TEST_P(PixelLocalStorageTest, Coherency) float x1 = x + w; float y0 = y; float y1 = y + h; - // Allow boxes to have negative widths and heights. This adds randomness by making the - // diagonals go in different directions. + // Allow boxes to have negative widths and heights. This adds randomness by making + // the diagonals go in different directions. if (rand() & 1) + { std::swap(x0, x1); + } if (rand() & 1) + { std::swap(y0, y1); + } boxes.push_back({{x0, y0, x1, y1}, {(float)r, (float)g, (float)b, (float)a}}); } } - glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); for (const std::vector &boxes : boxesList) { - mProgram.drawBoxes(boxes); + mProgram.drawBoxes(boxes, noncoherent ? UseBarriers::Always : UseBarriers::IfNotCoherent); } - glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE})); + glEndPixelLocalStorageANGLE( + 3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE})); attachTexture2DToScratchFBO(tex); std::vector actual(H * W * 4); @@ -1964,6 +2137,22 @@ TEST_P(PixelLocalStorageTest, Coherency) ASSERT_GL_NO_ERROR(); } +// Check that large amounts of overlapping draws are ordered and coherent, either implicitly via the +// "_coherent" extension, or explicitly via app-suppied barrier commands. +TEST_P(PixelLocalStorageTest, Coherency) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + doCoherencyTest(/*noncoherent=*/false); +} + +// Check that large amounts of overlapping draws that use the "noncoherent" qualifier are still +// ordered and coherent as long as we call glPixelLocalStorageBarrierANGLE(). +TEST_P(PixelLocalStorageTest, Coherency_noncoherent) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + doCoherencyTest(/*noncoherent=*/true); +} + // Check that binding mipmap levels to PLS is supported. TEST_P(PixelLocalStorageTest, MipMapLevels) { @@ -2086,34 +2275,284 @@ TEST_P(PixelLocalStorageTest, TextureLevelsAndLayers) } } -void PixelLocalStorageTest::doStateRestorationTest() +// Check that PLS works on multiple layers of the same array texture. +TEST_P(PixelLocalStorageTest, Texture2DArrayMultipleLayers) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); - // Setup state. - PLSTestTexture plsTex(GL_RGBA8UI, 32, 33); + PLSTestTexture tex(GL_RGBA8); + ASSERT_GL_NO_ERROR(); + + GLTexture texArray; + glBindTexture(GL_TEXTURE_2D_ARRAY, texArray); + ASSERT_GL_NO_ERROR(); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, W * 2, H * 2, 2); + ASSERT_GL_NO_ERROR(); + GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, texArray, 1, 0); + glFramebufferTexturePixelLocalStorageANGLE(2, texArray, 1, 1); + glViewport(0, 0, W, H); + glDrawBuffers(0, nullptr); - glViewport(1, 1, 5, 5); - glScissor(2, 2, 4, 4); - glEnable(GL_SCISSOR_TEST); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + ASSERT_GL_NO_ERROR(); - bool hasDrawBuffersIndexedOES = IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"); - if (hasDrawBuffersIndexedOES) - { - for (int i = 0; i < MAX_DRAW_BUFFERS; ++i) - { - if (i % 2 == 1) - { - glEnableiOES(GL_BLEND, i); - } - glColorMaskiOES(i, i % 3 == 0, i % 3 == 1, i % 3 == 2, i % 2 == 0); - } - } - else + // Pass 1: seed the texArray. + mProgram.compile(R"( + layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls0; + layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls1; + layout(binding=2, r32ui) uniform highp upixelLocalANGLE pls2; + void main() { - glEnable(GL_BLEND); + pixelLocalStoreANGLE(pls1, uvec4(floatBitsToUint(1.))); + pixelLocalStoreANGLE(pls2, uvec4(floatBitsToUint(2.))); + })"); + mProgram.drawBoxes({{FULLSCREEN}}); + + // Pass 2: read the texArray. + mProgram.compile(R"( + layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls0; + layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls1; + layout(binding=2, r32ui) uniform highp upixelLocalANGLE pls2; + void main() + { + float r = uintBitsToFloat(pixelLocalLoadANGLE(pls1).r); + float g = uintBitsToFloat(pixelLocalLoadANGLE(pls2).r) - 2.; + pixelLocalStoreANGLE(pls0, vec4(r, g, 0, 1)); + })"); + mProgram.drawBoxes({{FULLSCREEN}}); + ASSERT_GL_NO_ERROR(); + + glEndPixelLocalStorageANGLE(3, + GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, GL_DONT_CARE})); + + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); +} + +// Check that PLS works on multiple faces of the same cube texture. +TEST_P(PixelLocalStorageTest, TextureCubeMultipleFaces) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + PLSTestTexture tex(GL_RGBA8); + ASSERT_GL_NO_ERROR(); + + GLTexture texCube; + glBindTexture(GL_TEXTURE_CUBE_MAP, texCube); + ASSERT_GL_NO_ERROR(); + glTexStorage2D(GL_TEXTURE_CUBE_MAP, 2, GL_R32UI, W * 2, H * 2); + ASSERT_GL_NO_ERROR(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, texCube, 1, 0); + glFramebufferTexturePixelLocalStorageANGLE(2, texCube, 1, 5); + glViewport(0, 0, W, H); + glDrawBuffers(0, nullptr); + + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + ASSERT_GL_NO_ERROR(); + + // Pass 1: seed the texCube. + mProgram.compile(R"( + layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls0; + layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls1; + layout(binding=2, r32ui) uniform highp upixelLocalANGLE pls2; + void main() + { + pixelLocalStoreANGLE(pls1, uvec4(floatBitsToUint(1.))); + pixelLocalStoreANGLE(pls2, uvec4(floatBitsToUint(2.))); + })"); + mProgram.drawBoxes({{FULLSCREEN}}); + + // Pass 2: read the texCube. + mProgram.compile(R"( + layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls0; + layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls1; + layout(binding=2, r32ui) uniform highp upixelLocalANGLE pls2; + void main() + { + float r = uintBitsToFloat(pixelLocalLoadANGLE(pls1).r); + float g = uintBitsToFloat(pixelLocalLoadANGLE(pls2).r) - 2.; + pixelLocalStoreANGLE(pls0, vec4(r, g, 0, 1)); + })"); + mProgram.drawBoxes({{FULLSCREEN}}); + ASSERT_GL_NO_ERROR(); + + glEndPixelLocalStorageANGLE(3, + GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, GL_DONT_CARE})); + + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); +} + +// Check that cube map faces work as PLS planes. +TEST_P(PixelLocalStorageTest, TextureCubeFaces) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + // Invert the color of PLS plane 0 assuming opaque alpha, e.g., red <-> cyan + mProgram.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls; + void main() + { + pixelLocalStoreANGLE(pls, vec4(1, 1, 1, 2) - pixelLocalLoadANGLE(pls)); + })"); + + std::vector redImg(H * W, GLColor::red); + std::vector greenImg(H * W, GLColor::green); + std::vector blueImg(H * W, GLColor::blue); + std::vector cyanImg(H * W, GLColor::cyan); + std::vector magentaImg(H * W, GLColor::magenta); + std::vector yellowImg(H * W, GLColor::yellow); + + { + // Level 2. + GLTexture tex; + glBindTexture(GL_TEXTURE_CUBE_MAP, tex); + glTexStorage2D(GL_TEXTURE_CUBE_MAP, 3, GL_RGBA8, W * 4, H * 4); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + redImg.data()); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + cyanImg.data()); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + greenImg.data()); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + magentaImg.data()); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + blueImg.data()); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + yellowImg.data()); + ASSERT_GL_NO_ERROR(); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + for (size_t i = 0; i < 6; ++i) + { + // Sequentially attach each cube map face as PLS plane 0 and invert it + glFramebufferTexturePixelLocalStorageANGLE(0, tex, 2, i); + ASSERT_GL_NO_ERROR(); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE})); + mProgram.drawBoxes({{FULLSCREEN}}); + ASSERT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); + } + + // Check that all faces have inverted colors now + attachTextureCubeFaceToScratchFBO(tex, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::cyan); + attachTextureCubeFaceToScratchFBO(tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); + attachTextureCubeFaceToScratchFBO(tex, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::magenta); + attachTextureCubeFaceToScratchFBO(tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + attachTextureCubeFaceToScratchFBO(tex, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::yellow); + attachTextureCubeFaceToScratchFBO(tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::blue); + ASSERT_GL_NO_ERROR(); + } +} + +// Check that glFlush, glFinish, and glClientWaitSync don't invalidate PLS. +TEST_P(PixelLocalStorageTest, FlushFinishSync) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + mProgram.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE plane1; + layout(rgba8i, binding=1) uniform lowp ipixelLocalANGLE plane2; + layout(binding=2, rgba8ui) uniform lowp upixelLocalANGLE plane3; + void main() + { + pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1)); + pixelLocalStoreANGLE(plane2, ivec4(aux1) + pixelLocalLoadANGLE(plane2)); + pixelLocalStoreANGLE(plane3, uvec4(aux2) + pixelLocalLoadANGLE(plane3)); + })"); + + PLSTestTexture tex1(GL_RGBA8); + PLSTestTexture tex2(GL_RGBA8I); + PLSTestTexture tex3(GL_RGBA8UI); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, tex1, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, tex2, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(2, tex3, 0, 0); + glViewport(0, 0, W, H); + glDrawBuffers(0, nullptr); + + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + + // Accumulate R, G, B, A in 4 separate passes. + // Store out-of-range values to ensure they are properly clamped upon storage. + mProgram.drawBoxes({{FULLSCREEN, {2, -1, -2, -3}, {-500, 0, 0, 0}, {1, 0, 0, 0}}}); + glFlush(); + + mProgram.drawBoxes({{FULLSCREEN, {0, 1, 0, 100}, {0, -129, 0, 0}, {0, 50, 0, 0}}}); + glFinish(); + + mProgram.drawBoxes({{FULLSCREEN, {0, 0, 1, 0}, {0, 0, -70, 0}, {0, 0, 100, 0}}}); + GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glFlush(); + glClientWaitSync(sync, 0, std::numeric_limits::max()); + + mProgram.drawBoxes({{FULLSCREEN, {0, 0, 0, -1}, {128, 0, 0, 500}, {0, 0, 0, 300}}}); + glFlush(); + glFinish(); + + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, + GL_STORE_OP_STORE_ANGLE})); + + attachTexture2DToScratchFBO(tex1); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(255, 255, 255, 0)); + + attachTexture2DToScratchFBO(tex2); + EXPECT_PIXEL_RECT32I_EQ(0, 0, W, H, GLColor32I(0, -128, -70, 127)); + + attachTexture2DToScratchFBO(tex3); + EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(1, 50, 100, 255)); + + ASSERT_GL_NO_ERROR(); +} + +void PixelLocalStorageTest::doStateRestorationTest() +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + // Setup state. + PLSTestTexture plsTex(GL_RGBA8UI, 32, 33); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glViewport(1, 1, 5, 5); + glScissor(2, 2, 4, 4); + glEnable(GL_SCISSOR_TEST); + + bool hasDrawBuffersIndexedOES = IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"); + if (hasDrawBuffersIndexedOES) + { + for (int i = 0; i < MAX_DRAW_BUFFERS; ++i) + { + if (i % 2 == 1) + { + glEnableiOES(GL_BLEND, i); + } + glColorMaskiOES(i, i % 3 == 0, i % 3 == 1, i % 3 == 2, i % 2 == 0); + } + } + else + { + glEnable(GL_BLEND); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); } @@ -2157,9 +2596,6 @@ void PixelLocalStorageTest::doStateRestorationTest() glPixelLocalStorageBarrierANGLE(); glEndPixelLocalStorageANGLE( 4, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, GL_DONT_CARE})); - int firstOverriddenDrawBuffer = - std::min(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE, - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 4); // Check state. GLint textureBinding2D; @@ -2220,21 +2656,17 @@ void PixelLocalStorageTest::doStateRestorationTest() if (hasDrawBuffersIndexedOES) { - for (int i = 0; i < firstOverriddenDrawBuffer; ++i) + for (int i = 0; i < MAX_DRAW_BUFFERS; ++i) { EXPECT_EQ(glIsEnablediOES(GL_BLEND, i), i % 2 == 1); EXPECT_GL_COLOR_MASK_INDEXED(i, i % 3 == 0, i % 3 == 1, i % 3 == 2, i % 2 == 0); } - for (int i = firstOverriddenDrawBuffer; i < MAX_DRAW_BUFFERS; ++i) - { - EXPECT_FALSE(glIsEnablediOES(GL_BLEND, i)); - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } } else { - EXPECT_FALSE(glIsEnabled(GL_BLEND)); - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) + EXPECT_TRUE(glIsEnabled(GL_BLEND)); + EXPECT_GL_INTEGER(GL_BLEND, GL_TRUE); + EXPECT_GL_COLOR_MASK(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE) } EXPECT_TRUE(glIsEnabled(GL_SCISSOR_TEST)); @@ -2337,25 +2769,23 @@ void PixelLocalStorageTest::doDrawStateTest() ASSERT_GL_NO_ERROR(); } -#define SETUP_IMPLICIT_DISABLES_TEST(framebufferTarget) \ - GLFramebuffer fbo, readFBO; \ - glBindFramebuffer(framebufferTarget, fbo); \ - \ - PLSTestTexture tex0(GL_RGBA8); \ - PLSTestTexture tex1(GL_RGBA8); \ - PLSTestTexture tex2(GL_RGBA8); \ - PLSTestTexture tex3(GL_RGBA8); \ - glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); \ - glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0); \ - glFramebufferTexturePixelLocalStorageANGLE(2, tex2, 0, 0); \ - glFramebufferTexturePixelLocalStorageANGLE(3, tex3, 0, 0); \ - GLenum loadOps[4] = {GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, \ - GL_LOAD_OP_ZERO_ANGLE}; \ - GLenum storeOps[4] = {GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, \ - GL_DONT_CARE}; \ - \ - glDrawBuffers(0, nullptr); \ - \ +#define SETUP_IMPLICIT_DISABLES_TEST(framebufferTarget) \ + GLFramebuffer fbo, readFBO; \ + glBindFramebuffer(framebufferTarget, fbo); \ + \ + PLSTestTexture tex0(GL_RGBA8); \ + PLSTestTexture tex1(GL_RGBA8); \ + PLSTestTexture tex2(GL_RGBA8); \ + PLSTestTexture tex3(GL_RGBA8); \ + glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); \ + glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0); \ + glFramebufferTexturePixelLocalStorageANGLE(2, tex2, 0, 0); \ + glFramebufferTexturePixelLocalStorageANGLE(3, tex3, 0, 0); \ + GLenum loadOps[4] = {GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, \ + GL_LOAD_OP_ZERO_ANGLE}; \ + \ + glDrawBuffers(0, nullptr); \ + \ EXPECT_GL_NO_ERROR() #define CHECK_PLS_ENABLED() \ @@ -2375,29 +2805,27 @@ void PixelLocalStorageTest::doDrawStateTest() cmd; \ CHECK_PLS_DISABLED() -#define CHECK_DOES_NOT_END_PLS(cmd) \ - BEGIN_PLS(); \ - cmd; \ - CHECK_PLS_ENABLED(); \ - glEndPixelLocalStorageANGLE(4, storeOps); \ - CHECK_PLS_DISABLED() - -#define CHECK_DOES_NOT_END_PLS_WITH_READ_FBO(cmd) \ - BEGIN_PLS(); \ +#define CHECK_ENDS_PLS_WITH_READ_FBO(cmd) \ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); \ - cmd; \ - CHECK_PLS_ENABLED(); \ - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); \ + BEGIN_PLS(); \ CHECK_PLS_ENABLED(); \ - glEndPixelLocalStorageANGLE(4, storeOps); \ + cmd; \ + CHECK_PLS_DISABLED(); + +#define CHECK_DOES_NOT_END_PLS(cmd) \ + BEGIN_PLS(); \ + cmd; \ + CHECK_PLS_ENABLED(); \ + glEndPixelLocalStorageANGLE(4, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, \ + GL_DONT_CARE, GL_DONT_CARE})); \ CHECK_PLS_DISABLED() void PixelLocalStorageTest::doImplicitDisablesTest_Framebuffer() { SETUP_IMPLICIT_DISABLES_TEST(GL_DRAW_FRAMEBUFFER); - // Binding a READ_FRAMEBUFFER does not end PLS. - CHECK_DOES_NOT_END_PLS(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); + // Binding a READ_FRAMEBUFFER still ends PLS. + CHECK_ENDS_PLS(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); EXPECT_GL_INTEGER(GL_READ_FRAMEBUFFER_BINDING, 0); EXPECT_GL_INTEGER(GL_DRAW_FRAMEBUFFER_BINDING, fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -2443,7 +2871,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_Framebuffer() EXPECT_FRAMEBUFFER_PARAMETER_INT_MESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, GL_TRUE); glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, GL_FALSE); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO( + CHECK_ENDS_PLS_WITH_READ_FBO( glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, GL_TRUE)); } @@ -2460,7 +2888,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_Framebuffer() glFramebufferParameteri(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 25)); EXPECT_FRAMEBUFFER_PARAMETER_INT(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 25); glFramebufferParameteri(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO( + CHECK_ENDS_PLS_WITH_READ_FBO( glFramebufferParameteri(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 23)); } @@ -2496,7 +2924,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_TextureAttachments() glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO( + CHECK_ENDS_PLS_WITH_READ_FBO( glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0)); GLTexture tex2DArray; @@ -2514,7 +2942,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_TextureAttachments() glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray, 0, 0)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO( + CHECK_ENDS_PLS_WITH_READ_FBO( glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray, 0, 0)); GLTexture tex3d; @@ -2531,7 +2959,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_TextureAttachments() glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex3d, 0, 0)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex3d); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO( + CHECK_ENDS_PLS_WITH_READ_FBO( glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex3d, 0, 0)); if (EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")) @@ -2549,7 +2977,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_TextureAttachments() GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texMSAA, 0, 4)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texMSAA); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO(glFramebufferTexture2DMultisampleEXT( + CHECK_ENDS_PLS_WITH_READ_FBO(glFramebufferTexture2DMultisampleEXT( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texMSAA, 0, 4)); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); ASSERT_GL_NO_ERROR(); @@ -2569,7 +2997,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_TextureAttachments() tex2DArray, 0, 0, 1)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO(glFramebufferTextureMultiviewOVR( + CHECK_ENDS_PLS_WITH_READ_FBO(glFramebufferTextureMultiviewOVR( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray, 0, 0, 1)); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); } @@ -2588,7 +3016,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_TextureAttachments() GL_TEXTURE_3D, tex3d, 0, 0)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex3d); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO(glFramebufferTexture3DOES( + CHECK_ENDS_PLS_WITH_READ_FBO(glFramebufferTexture3DOES( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, tex3d, 0, 0)); } } @@ -2613,7 +3041,7 @@ void PixelLocalStorageTest::doImplicitDisablesTest_RenderbufferAttachments() GL_RENDERBUFFER, colorBuffer)); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorBuffer); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO(glFramebufferRenderbuffer( + CHECK_ENDS_PLS_WITH_READ_FBO(glFramebufferRenderbuffer( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer)); GLuint depthStencilBuffer; @@ -2635,11 +3063,27 @@ void PixelLocalStorageTest::doImplicitDisablesTest_RenderbufferAttachments() EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); - CHECK_DOES_NOT_END_PLS_WITH_READ_FBO(glFramebufferRenderbuffer( + CHECK_ENDS_PLS_WITH_READ_FBO(glFramebufferRenderbuffer( GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilBuffer)); } -#undef CHECK_DOES_NOT_END_PLS_WITH_READ_FBO +void PixelLocalStorageTest::doImplicitDisablesTest_Invalidate() +{ + SETUP_IMPLICIT_DISABLES_TEST(GL_FRAMEBUFFER); + + // "... Commands that flush or invalidate tiled memory. + // + // "e.g., DiscardFramebufferEXT, InvalidateFramebuffer, + // InvalidateSubFramebuffer, etc." + if (EnsureGLExtensionEnabled("GL_EXT_discard_framebuffer")) + { + CHECK_ENDS_PLS(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 0, nullptr)); + } + CHECK_ENDS_PLS(glInvalidateFramebuffer(GL_FRAMEBUFFER, 0, nullptr)); + CHECK_ENDS_PLS(glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 0, nullptr, 0, 0, 1, 1)); +} + +#undef CHECK_ENDS_PLS_WITH_READ_FBO #undef CHECK_DOES_NOT_END_PLS #undef BEGIN_PLS #undef CHECK_PLS_DISABLED @@ -2671,16 +3115,14 @@ TEST_P(PixelLocalStorageTest, BlendColorMaskAndClear) glBindFramebuffer(GL_FRAMEBUFFER, fbo); glViewport(0, 0, W, H); - const bool drawBuffersIndexed = IsGLExtensionEnabled("GL_OES_draw_buffers_indexed") && - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE >= 2; - GLint firstClearBuffer = 0; - GLint firstPLSOverriddenDrawBuffer = 0; + const bool drawBuffersIndexed = IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"); + GLint firstClearBuffer = 0; if (!drawBuffersIndexed) { // Blend should not affect pixel local storage. glBlendFunc(GL_ZERO, GL_ZERO); // Color mask should not affect pixel local storage. - glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); mProgram.compile(R"( layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls1; @@ -2706,22 +3148,26 @@ TEST_P(PixelLocalStorageTest, BlendColorMaskAndClear) // Blend should not affect pixel local storage. EXPECT_FALSE(glIsEnabled(GL_BLEND)); + EXPECT_GL_INTEGER(GL_BLEND, GL_FALSE); glEnable(GL_BLEND); - // Enabling GL_BLEND is ignored while PLS is active. - EXPECT_FALSE(glIsEnabled(GL_BLEND)); + // Enabling GL_BLEND works from the client perspective even though PLS is overriding it. + EXPECT_TRUE(glIsEnabled(GL_BLEND)); + EXPECT_GL_INTEGER(GL_BLEND, GL_TRUE); // BlendFunc has no effect as long as GL_BLEND stays disabled on our PLS draw buffers. glBlendFunc(GL_ZERO, GL_ONE); + EXPECT_GL_INTEGER(GL_BLEND_SRC_RGB, GL_ZERO); + EXPECT_GL_INTEGER(GL_BLEND_SRC_ALPHA, GL_ZERO); + EXPECT_GL_INTEGER(GL_BLEND_DST_RGB, GL_ONE); + EXPECT_GL_INTEGER(GL_BLEND_DST_ALPHA, GL_ONE); EXPECT_GL_NO_ERROR(); - // Color is ignored when PLS is active. - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - EXPECT_GL_NO_ERROR(); + // Color mask should not affect PLS. + EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + EXPECT_GL_COLOR_MASK(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); EXPECT_GL_NO_ERROR(); } @@ -2745,9 +3191,10 @@ TEST_P(PixelLocalStorageTest, BlendColorMaskAndClear) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, whiteData.data()); // Blend should not affect pixel local storage. - glEnablei(GL_BLEND, 0); - glBlendEquationi(0, GL_FUNC_REVERSE_SUBTRACT); - glBlendFunci(0, GL_ONE, GL_ONE); + glEnableiOES(GL_BLEND, 0); + glBlendEquationiOES(0, GL_FUNC_REVERSE_SUBTRACT); + glBlendFunciOES(0, GL_ONE, GL_ONE); + glEnableiOES(GL_BLEND, 2); std::vector blackData(H * W, GLColor::black); glBindTexture(GL_TEXTURE_2D, tex2); @@ -2759,53 +3206,47 @@ TEST_P(PixelLocalStorageTest, BlendColorMaskAndClear) glFramebufferTexturePixelLocalStorageANGLE(1, tex4, 0, 0); glDrawBuffers(2, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1})); firstClearBuffer = 2; - firstPLSOverriddenDrawBuffer = - std::min(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE, - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 2); glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); // Color mask should not affect pixel local storage. glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); + glColorMaskiOES(2, GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE); EXPECT_GL_COLOR_MASK_INDEXED(0, GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); EXPECT_GL_COLOR_MASK_INDEXED(1, GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); + EXPECT_GL_COLOR_MASK_INDEXED(2, GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - EXPECT_FALSE(glIsEnabledi(GL_BLEND, 1)); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, 0)); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, 1)); for (int i = 2; i < MAX_DRAW_BUFFERS; ++i) { - // Blend cannot be enabled on an overridden PLS plane. - EXPECT_FALSE(glIsEnabledi(GL_BLEND, i)); - glEnablei(GL_BLEND, i); - glBlendFunci(i, GL_ZERO, GL_ONE); - if (i >= firstPLSOverriddenDrawBuffer) + // Enabling blend with PLS active still works from the client perspective, even though + // it's overridden by PLS. + if (i == 2) { - EXPECT_FALSE(glIsEnabledi(GL_BLEND, i)); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, i)); } else { - EXPECT_TRUE(glIsEnabledi(GL_BLEND, i)); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, i)); } + glEnableiOES(GL_BLEND, i); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, i)); + glBlendFunciOES(i, GL_ZERO, GL_ONE); - // Color mask cannot be enabled on an overridden PLS plane. - if (i >= firstPLSOverriddenDrawBuffer) + // Changing the color mask with PLS active still works from the client perspective, even + // though it's overridden by PLS. + if (i == 2) { - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE); } else { EXPECT_GL_COLOR_MASK_INDEXED(i, GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); } - glColorMaski(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - if (i >= firstPLSOverriddenDrawBuffer) - { - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - else - { - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - } + glColorMaskiOES(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + EXPECT_GL_COLOR_MASK_INDEXED(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } ASSERT_GL_NO_ERROR(); @@ -2842,37 +3283,24 @@ TEST_P(PixelLocalStorageTest, BlendColorMaskAndClear) attachTexture2DToScratchFBO(tex4); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::black); - // Blend state attempted to be set on overridden draw buffers during PLS should not have taken - // effect afterward. + // Blend state that was set on overridden draw buffers during PLS should still be in effect + // after PLS ends. if (!drawBuffersIndexed) { - EXPECT_FALSE(glIsEnabled(GL_BLEND)); - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + EXPECT_TRUE(glIsEnabled(GL_BLEND)); + EXPECT_GL_INTEGER(GL_BLEND, GL_TRUE); + EXPECT_GL_COLOR_MASK(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); } else { - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - EXPECT_FALSE(glIsEnabledi(GL_BLEND, 1)); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, 0)); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, 1)); EXPECT_GL_COLOR_MASK_INDEXED(0, GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); EXPECT_GL_COLOR_MASK_INDEXED(1, GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); for (GLint i = 2; i < MAX_DRAW_BUFFERS; ++i) { - if (i >= firstPLSOverriddenDrawBuffer) - { - EXPECT_FALSE(glIsEnabledi(GL_BLEND, i)); - } - else - { - EXPECT_TRUE(glIsEnabledi(GL_BLEND, i)); - } - if (i >= firstPLSOverriddenDrawBuffer) - { - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - else - { - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - } + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, i)); + // EXPECT_GL_COLOR_MASK_INDEXED(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } } @@ -2885,10 +3313,10 @@ TEST_P(PixelLocalStorageTest, BlendColorMaskAndClear) GL_LOAD_OP_LOAD_ANGLE})); constexpr static GLfloat one[4] = {1, 1, 1, 1}; - glColorMaski(0, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + glColorMaskiOES(0, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); glClearBufferfv(GL_COLOR, 0, one); - glColorMaski(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + glColorMaskiOES(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); glClearBufferfv(GL_COLOR, 1, one); ASSERT_GL_NO_ERROR(); @@ -2933,48 +3361,472 @@ TEST_P(PixelLocalStorageTest, ImplicitDisables_RenderbufferAttachments) doImplicitDisablesTest_RenderbufferAttachments(); } -// Check that PLS and EXT_shader_framebuffer_fetch can be used together. -TEST_P(PixelLocalStorageTest, ParallelFramebufferFetch) +// Check that invalidation commands implicitly disable pixel local storage. +TEST_P(PixelLocalStorageTest, ImplicitDisables_Invalidate) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); - ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); - ANGLE_SKIP_TEST_IF(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0); - mProgram.compile("#extension GL_EXT_shader_framebuffer_fetch : require", R"( - layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls; - inout highp vec4 fbfetch; - void main() - { - // Swap pls and fbfetch. - vec4 tmp = pixelLocalLoadANGLE(pls); - pixelLocalStoreANGLE(pls, fbfetch); - fbfetch = tmp; - })"); + doImplicitDisablesTest_Invalidate(); +} - PLSTestTexture pls(GL_RGBA8), fbfetch(GL_RGBA8); +// Check that gl(Copy)TexSubImage{2,3}D end PLS before running. +TEST_P(PixelLocalStorageTest, CopyTexSubImage) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + PLSTestTexture tex0(GL_RGBA8); GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexturePixelLocalStorageANGLE(0, pls, 0, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbfetch, 0); - + glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 1, 0, 1)); - glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); - - GLfloat red[] = {1, 0, 0, 1}; - glClearBufferfv(GL_COLOR, 0, red); - // Swap pls and fbfetch. - mProgram.drawBoxes({{FULLSCREEN}}); + PLSTestTexture color0(GL_RGBA8); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color0, 0); + glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0})); + glClearBufferfv(GL_COLOR, 0, MakeArray({0, 0, 0, 0})); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::transparentBlack); - glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + mProgram.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE tex0; + layout(location=0) out lowp vec4 color0; + void main() + { + lowp vec4 plsOut = color + pixelLocalLoadANGLE(tex0); + pixelLocalStoreANGLE(tex0, plsOut); + color0 = vec4(0, 1, 1, 0); + })"); - EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + GLTexture tex3D; + glBindTexture(GL_TEXTURE_3D, tex3D); + glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, W, H, 5); - attachTexture2DToScratchFBO(pls); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + glClearBufferfv(GL_COLOR, 0, MakeArray({1, 0, 0, 1})); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); -} - + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE})); + + glBindTexture(GL_TEXTURE_2D, tex0); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, W, H / 2); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE})); + + // glTexStorage2D on a PLS plane generates an error since the texture must be immutable. + glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, W / 2, H / 2); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_NO_ERROR(); + mProgram.drawBoxes({{{FULLSCREEN}, {0, 0, 1, 0}}}); + EXPECT_GL_NO_ERROR(); + + glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE})); + + GLTexture texNonImmutable; + glBindTexture(GL_TEXTURE_2D, texNonImmutable); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, W, H, 0); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + attachTexture2DToScratchFBO(tex0); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H / 2, GLColor::magenta); + EXPECT_PIXEL_RECT_EQ(0, H / 2, W, H - H / 2, GLColor::cyan); + + attachTextureLayerToScratchFBO(tex3D, 0, 2); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::yellow); + + attachTexture2DToScratchFBO(texNonImmutable); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::yellow); + + ASSERT_GL_NO_ERROR(); +} + +// Check that glBlitFramebuffer ends PLS, while also working as expected. +TEST_P(PixelLocalStorageTest, BlitFramebuffer) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + PLSTestTexture tex0(GL_RGBA8); + PLSTestTexture tex1(GL_R32UI); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0); + constexpr static int NUM_PLANES = 2; + + PLSTestTexture colorAttachment(GL_RGBA8); + bool canHaveColorAttachment = + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES > NUM_PLANES; + if (canHaveColorAttachment) + { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colorAttachment, 0); + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + } + + // Set the to-be current PLS plane as the read framebuffer. + GLFramebuffer readFBO; + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0); + EXPECT_GL_NO_ERROR(); + + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 1, 0, 1)); + glFramebufferPixelLocalClearValueuivANGLE(1, ClearUI(123, 0, 0, 0)); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE})); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, NUM_PLANES); + + // glBlitFramebuffer will implicitly end PLS and store the PLS plane before + // executing. + glBlitFramebuffer(0, 0, W / 2, H, 0, 0, W / 2, H, GL_COLOR_BUFFER_BIT, GL_NEAREST); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + if (canHaveColorAttachment) + { + attachTexture2DToScratchFBO(colorAttachment); + EXPECT_PIXEL_RECT_EQ(0, 0, W / 2, H, GLColor::green); + EXPECT_PIXEL_RECT_EQ(W / 2, 0, W - W / 2, H, GLColor::red); + } + + attachTexture2DToScratchFBO(tex0); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + + attachTexture2DToScratchFBO(tex1); + EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(123, 0, 0, 1)); +} + +// Check that GL_RASTERIZER_DISCARD disables renders to PLS, but not PLS clear operations. +TEST_P(PixelLocalStorageTest, RasterizerDiscard) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + PLSTestTexture tex(GL_RGBA8); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0); + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1, 0, 0, 1)); + + mProgram.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE tex; + void main() + { + pixelLocalStoreANGLE(tex, vec4(0, 1, 0, 1)); + })"); + + // PLS clears still pass when RASTERIZER_DISCARD is disabled. + glDisable(GL_RASTERIZER_DISCARD); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 0, 1, 1)); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::blue); + ASSERT_GL_NO_ERROR(); + + // PLS clears still pass when RASTERIZER_DISCARD is enabled. + glEnable(GL_RASTERIZER_DISCARD); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE})); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::transparentBlack); + ASSERT_GL_NO_ERROR(); + + // Rasterization passes when RASTERIZER_DISCARD is disabled. + glDisable(GL_RASTERIZER_DISCARD); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1, 0, 0, 1)); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + mProgram.drawBoxes({{{FULLSCREEN}}}); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + ASSERT_GL_NO_ERROR(); + + // Rasterization fails when RASTERIZER_DISCARD is enabled (but PLS still clears). + glEnable(GL_RASTERIZER_DISCARD); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + mProgram.drawBoxes({{{FULLSCREEN}}}); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); + ASSERT_GL_NO_ERROR(); + + // RASTERIZER_DISCARD can be disabled while PLS is active. + glEnable(GL_RASTERIZER_DISCARD); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + glDisable(GL_RASTERIZER_DISCARD); + mProgram.drawBoxes({{{FULLSCREEN}}}); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + ASSERT_GL_NO_ERROR(); + + // RASTERIZER_DISCARD can be enabled while PLS is active. + glDisable(GL_RASTERIZER_DISCARD); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + glEnable(GL_RASTERIZER_DISCARD); + mProgram.drawBoxes({{{FULLSCREEN}}}); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + attachTexture2DToScratchFBO(tex); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); +} + +// Check that glClear does not clear PLS planes. +TEST_P(PixelLocalStorageTest, ClearWithActivePLS) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + PLSTestTexture pls0(GL_RGBA8); + PLSTestTexture pls1(GL_RGBA8); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0); + + constexpr static int NUM_PLANES = 2; + int maxColorAttachmentsWith2PLSPlanes = + std::min(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 2, MAX_DRAW_BUFFERS); + int numColorAttachments = std::min(maxColorAttachmentsWith2PLSPlanes, 2); + + PLSTestTexture colorAttachment0(GL_RGBA8); + PLSTestTexture colorAttachment1(GL_RGBA8); + + for (int colorAttachmentMask = 0; colorAttachmentMask < (1 << numColorAttachments); + ++colorAttachmentMask) + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + if (numColorAttachments >= 2) + { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, + colorAttachment1, 0); + } + if (numColorAttachments >= 1) + { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colorAttachment0, 0); + } + + // Clear color attachments. + glDrawBuffers(2, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1})); + if (numColorAttachments >= 2) + { + float green[4] = {0, 1, 0, 1}; + glClearBufferfv(GL_COLOR, 1, green); + glReadBuffer(GL_COLOR_ATTACHMENT1); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + } + if (numColorAttachments >= 1) + { + float red[4] = {1, 0, 0, 1}; + glClearBufferfv(GL_COLOR, 0, red); + glReadBuffer(GL_COLOR_ATTACHMENT0); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); + } + + // Only enable draw buffers that are in colorAttachmentMask. + GLenum drawBuffers[2]; + for (int i = 0; i < 2; ++i) + { + drawBuffers[i] = (colorAttachmentMask & (1 << i)) ? GL_COLOR_ATTACHMENT0 + i : GL_NONE; + } + glDrawBuffers(2, drawBuffers); + + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 0, 1, 1)); + glFramebufferPixelLocalClearValuefvANGLE(1, ClearF(0, 1, 1, 1)); + glBeginPixelLocalStorageANGLE( + NUM_PLANES, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE})); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, NUM_PLANES); + + glClearColor(1, 1, 1, 1); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 10, H); + if (numColorAttachments != 0) + { + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + } + glDisable(GL_SCISSOR_TEST); + EXPECT_GL_NO_ERROR(); + + glEndPixelLocalStorageANGLE( + NUM_PLANES, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + + // Make sure glClear worked on the enabled color attachments, and did not clear the disabled + // ones. + if (numColorAttachments >= 2) + { + glReadBuffer(GL_COLOR_ATTACHMENT1); + EXPECT_PIXEL_RECT_EQ(0, 0, 10, H, + (colorAttachmentMask & 2) ? GLColor::white : GLColor::green); + EXPECT_PIXEL_RECT_EQ(10, 0, W - 10, H, GLColor::green); + } + if (numColorAttachments >= 1) + { + glReadBuffer(GL_COLOR_ATTACHMENT0); + EXPECT_PIXEL_RECT_EQ(0, 0, 10, H, + (colorAttachmentMask & 1) ? GLColor::white : GLColor::red); + EXPECT_PIXEL_RECT_EQ(10, 0, W - 10, H, GLColor::red); + } + + // Make sure glClear did not touch the PLS planes. + attachTexture2DToScratchFBO(pls0); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::blue); + + attachTexture2DToScratchFBO(pls1); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::cyan); + + // Clear to check that the draw buffers were properly restored after we cleared with PLS + // active. + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glClearColor(0, 0, 0, 1); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 10, H); + if (numColorAttachments >= 1) + { + glClear(GL_COLOR_BUFFER_BIT); + } + glDisable(GL_SCISSOR_TEST); + EXPECT_GL_NO_ERROR(); + + // Make sure glClear worked on the enabled color attachments, and did not clear the disabled + // ones. + if (numColorAttachments >= 2) + { + glReadBuffer(GL_COLOR_ATTACHMENT1); + EXPECT_PIXEL_RECT_EQ(0, 0, 10, H, + (colorAttachmentMask & 2) ? GLColor::black : GLColor::green); + EXPECT_PIXEL_RECT_EQ(10, 0, W - 10, H, GLColor::green); + } + if (numColorAttachments >= 1) + { + glReadBuffer(GL_COLOR_ATTACHMENT0); + EXPECT_PIXEL_RECT_EQ(0, 0, 10, H, + (colorAttachmentMask & 1) ? GLColor::black : GLColor::red); + EXPECT_PIXEL_RECT_EQ(10, 0, W - 10, H, GLColor::red); + } + + // Make sure glClear still did not touch the PLS planes. + attachTexture2DToScratchFBO(pls0); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::blue); + + attachTexture2DToScratchFBO(pls1); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::cyan); + EXPECT_GL_NO_ERROR(); + } + + ASSERT_GL_NO_ERROR(); +} + +// Check the Intel-Mac workaround for GL_COLOR_ATTACHMENT0. On this platform, it has been necessary +// in the past to attach a texture on GL_COLOR_ATTACHMENT0 when rendering PLS only to storage +// textures. +// +// Check that: +// 1) Needed workarounds are applied and PLS draws correctly. +// 2) The workarounds do not affect GL state after PLS ends. +// +TEST_P(PixelLocalStorageTest, ColorAttachment0Workaround) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES < 3); + + mProgram.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE tex; + void main() + { + pixelLocalStoreANGLE(tex, pixelLocalLoadANGLE(tex) + vec4(0, 1, 0, 1)); + })"); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + PLSTestTexture pls(GL_RGBA8); + glFramebufferTexturePixelLocalStorageANGLE(0, pls, 0, 0); + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1, 0, 0, 1)); + + GLTexture attachment0; + glBindTexture(GL_TEXTURE_2D_ARRAY, attachment0); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, W * 2, H * 2, 3); + + // Use PLS with: + // 1) GL_COLOR_ATTACHMENT0 attached. + // 2) drawbuffer 0 disabled. + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, attachment0, 1, 2); + glDrawBuffers(1, GLenumArray({GL_NONE})); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + mProgram.drawBoxes({{{FULLSCREEN}}}); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + EXPECT_GL_NO_ERROR(); + + // Ensure our workaround didn't change the COLOR_ATTACHMENT0 binding. + EXPECT_FRAMEBUFFER_ATTACHMENT_TYPE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, attachment0); + EXPECT_FRAMEBUFFER_ATTACHMENT_LEVEL(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1); + EXPECT_FRAMEBUFFER_ATTACHMENT_LAYER(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 2); + EXPECT_GL_NO_ERROR(); + + attachTexture2DToScratchFBO(pls); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::yellow); + + ASSERT_GL_NO_ERROR(); +} + +// Check that PLS and EXT_shader_framebuffer_fetch can be used together. +TEST_P(PixelLocalStorageTest, ParallelFramebufferFetch) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + mProgram.compile("#extension GL_EXT_shader_framebuffer_fetch : require", R"( + layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls; + inout highp vec4 fbfetch; + void main() + { + // Swap pls and fbfetch. + vec4 tmp = pixelLocalLoadANGLE(pls); + pixelLocalStoreANGLE(pls, fbfetch); + fbfetch = tmp; + })"); + + PLSTestTexture pls(GL_RGBA8), fbfetch(GL_RGBA8); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, pls, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbfetch, 0); + + glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 1, 0, 1)); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE})); + + GLfloat red[] = {1, 0, 0, 1}; + glClearBufferfv(GL_COLOR, 0, red); + + // Swap pls and fbfetch. + mProgram.drawBoxes({{FULLSCREEN}}); + + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + + attachTexture2DToScratchFBO(pls); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); +} + // Check that PLS gets properly cleaned up when its framebuffer and textures are never deleted. TEST_P(PixelLocalStorageTest, LeakFramebufferAndTexture) { @@ -2990,7 +3842,7 @@ TEST_P(PixelLocalStorageTest, LeakFramebufferAndTexture) glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 10, 10); glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); - PLSTestTexture tex1(GL_R32F); + PLSTestTexture tex1(GL_R32UI); glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0); glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8I); @@ -3020,7 +3872,7 @@ TEST_P(PixelLocalStorageTest, PLSWithSamplers) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, blueData.data()); PLSTestTexture pls0(GL_RGBA8); - std::vector greenData(H * H, GLColor::green); + std::vector greenData(H * W, GLColor::green); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, greenData.data()); PLSTestTexture pls1(GL_RGBA8); @@ -3206,22 +4058,16 @@ TEST_P(PixelLocalStorageTest, DeleteAttachments_draw_framebuffer) EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthStencil); PLSTestTexture colorTex(GL_RGBA8); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) - { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTex); - } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTex); GLuint colorRenderbuffer; - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1) - { - glGenRenderbuffers(1, &colorRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, W, H); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, - colorRenderbuffer); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorRenderbuffer); - } + glGenRenderbuffers(1, &colorRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, W, H); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, + colorRenderbuffer); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorRenderbuffer); PLSTestTexture pls0(GL_RGBA8); glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); @@ -3242,25 +4088,19 @@ TEST_P(PixelLocalStorageTest, DeleteAttachments_draw_framebuffer) EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 0); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) - { - // Deleting the color texture will implicitly end pixel local storage. - glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); - colorTex.reset(); - EXPECT_GL_NO_ERROR(); - EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0); - } + // Deleting the color texture will implicitly end pixel local storage. + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); + colorTex.reset(); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1) - { - // Deleting the color renderbuffer will implicitly end pixel local storage. - glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); - glDeleteRenderbuffers(1, &colorRenderbuffer); - EXPECT_GL_NO_ERROR(); - EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0); - } + // Deleting the color renderbuffer will implicitly end pixel local storage. + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); + glDeleteRenderbuffers(1, &colorRenderbuffer); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0); // Pixel local storage can't be ended because it's already deactivated. glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); @@ -3306,25 +4146,18 @@ TEST_P(PixelLocalStorageTest, DeleteAttachments_read_framebuffer) EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthStencil); PLSTestTexture colorTex(GL_RGBA8); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) - { - colorTex.reset(GL_RGBA8); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, - 0); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTex); - } + colorTex.reset(GL_RGBA8); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTex); GLuint colorRenderbuffer; - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1) - { - glGenRenderbuffers(1, &colorRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, W, H); - glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, - colorRenderbuffer); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, - colorRenderbuffer); - } + glGenRenderbuffers(1, &colorRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, W, H); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, + colorRenderbuffer); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, + colorRenderbuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, readFBO); @@ -3348,17 +4181,11 @@ TEST_P(PixelLocalStorageTest, DeleteAttachments_read_framebuffer) glDeleteRenderbuffers(1, &depthStencil); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0); EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 0); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) - { - colorTex.reset(); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0); - } + colorTex.reset(); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0); - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1) - { - glDeleteRenderbuffers(1, &colorRenderbuffer); - EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0); - } + glDeleteRenderbuffers(1, &colorRenderbuffer); + EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0); inactivePLS0.reset(); inactivePLS1.reset(); @@ -3373,6 +4200,47 @@ TEST_P(PixelLocalStorageTest, DeleteAttachments_read_framebuffer) EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0); } +// Check that glBeginPixelLocalStorageANGLE() is banned while tiled rendering is +// active, and that glStartTilingQCOM() implicitly disables PLS. +TEST_P(PixelLocalStorageTest, TiledRenderingInteractions) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_QCOM_tiled_rendering")); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + PLSTestTexture pls0(GL_RGBA8, 100, 100); + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); + + PLSTestTexture color0(GL_RGBA8, 100, 100); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color0, 0); + + glStartTilingQCOM(8, 8, 8, 8, GL_COLOR_BUFFER_BIT0_QCOM); + ASSERT_GL_NO_ERROR(); + + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); + ASSERT_GL_NO_ERROR(); + + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1); + + // glStartTilingQCOM implicitly disables PLS. + glStartTilingQCOM(8, 8, 8, 8, GL_COLOR_BUFFER_BIT0_QCOM); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + + glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); +} + // Checks that draw commands validate current PLS state against the shader's PLS uniforms. class DrawCommandValidationTest { @@ -3572,11 +4440,6 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTest); #define PLS_INSTANTIATE_RENDERING_TEST_AND(TEST, API, ...) \ ANGLE_INSTANTIATE_TEST( \ TEST, \ - PLATFORM(API, D3D11) /* D3D coherent. */ \ - .enable(Feature::EmulatePixelLocalStorage), \ - PLATFORM(API, D3D11) /* D3D noncoherent. */ \ - .enable(Feature::DisableRasterizerOrderViews) \ - .enable(Feature::EmulatePixelLocalStorage), \ PLATFORM(API, OPENGL) /* OpenGL coherent. */ \ .enable(Feature::EmulatePixelLocalStorage), \ PLATFORM(API, OPENGL) /* OpenGL noncoherent. */ \ @@ -3586,6 +4449,10 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTest); .disable(Feature::SupportsFragmentShaderInterlockARB), \ PLATFORM(API, OPENGLES) /* OpenGL ES coherent */ \ .enable(Feature::EmulatePixelLocalStorage), \ + PLATFORM(API, OPENGLES) /* Test PLS not having access to \ + glEnablei/glDisablei/glColorMaski. */ \ + .enable(Feature::EmulatePixelLocalStorage) \ + .enable(Feature::DisableDrawBuffersIndexed), \ PLATFORM(API, OPENGLES) /* OpenGL ES noncoherent \ (EXT_shader_framebuffer_fetch_non_coherent). */ \ .enable(Feature::EmulatePixelLocalStorage) \ @@ -3606,18 +4473,21 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTest); .disable(Feature::SupportsShaderFramebufferFetch) \ .disable(Feature::SupportsFragmentShaderPixelInterlock) \ .enable(Feature::EmulatePixelLocalStorage), \ - PLATFORM(API, VULKAN_SWIFTSHADER) /* Test PLS not having access to \ - glEnablei/glDisablei/glColorMaski. */ \ - .enable(Feature::EmulatePixelLocalStorage) \ - .enable(Feature::DisableDrawBuffersIndexed), \ __VA_ARGS__) #define PLS_INSTANTIATE_RENDERING_TEST_ES3(TEST) \ PLS_INSTANTIATE_RENDERING_TEST_AND( \ - TEST, ES3, /* Metal, coherent (in tiled memory on Apple Silicon).*/ \ - ES3_METAL().enable(Feature::EmulatePixelLocalStorage), /* Metal, coherent via raster order \ - groups + read_write textures.*/ \ - ES3_METAL() \ + TEST, ES3, \ + \ + ES3_D3D11().enable(Feature::EmulatePixelLocalStorage), /* D3D coherent. */ \ + \ + ES3_D3D11() /* D3D noncoherent. */ \ + .enable(Feature::DisableRasterizerOrderViews) \ + .enable(Feature::EmulatePixelLocalStorage), \ + \ + ES3_METAL().enable(Feature::EmulatePixelLocalStorage), /* Metal, coherent (in tiled memory \ + on Apple Silicon).*/ \ + ES3_METAL() /* Metal, coherent via raster order groups + read_write textures.*/ \ .enable(Feature::EmulatePixelLocalStorage) \ .enable(Feature::DisableProgrammableBlending), /* Metal, coherent, r32 packed \ read_write texture formats.*/ \ @@ -3636,8 +4506,79 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTest); PLS_INSTANTIATE_RENDERING_TEST_ES3(PixelLocalStorageTest); -class PixelLocalStorageTestES31 : public PixelLocalStorageTest -{}; +class PixelLocalStorageTestES31 : public PixelLocalStorageTest +{}; + +// Check that cube map array faces work as PLS planes. +TEST_P(PixelLocalStorageTestES31, TextureCubeArrayFaces) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_texture_cube_map_array") && + !EnsureGLExtensionEnabled("GL_OES_texture_cube_map_array")); + + // Invert the color of PLS plane 0 assuming opaque alpha, e.g., red <-> cyan + mProgram.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls; + void main() + { + pixelLocalStoreANGLE(pls, vec4(1, 1, 1, 2) - pixelLocalLoadANGLE(pls)); + })"); + + std::vector redImg(H * W, GLColor::red); + std::vector greenImg(H * W, GLColor::green); + std::vector blueImg(H * W, GLColor::blue); + std::vector cyanImg(H * W, GLColor::cyan); + std::vector magentaImg(H * W, GLColor::magenta); + std::vector yellowImg(H * W, GLColor::yellow); + + { + // Level 2, layer 1 (layer-faces 6-11) + GLTexture tex; + glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex); + glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 3, GL_RGBA8, W * 4, H * 4, 12); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 6, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, + redImg.data()); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 7, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, + cyanImg.data()); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 8, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, + greenImg.data()); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 9, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, + magentaImg.data()); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 10, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, + blueImg.data()); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 11, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, + yellowImg.data()); + ASSERT_GL_NO_ERROR(); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + for (size_t i = 6; i < 12; ++i) + { + // Sequentially attach cube map layer-faces 6-11 as PLS plane 0 and invert them + glFramebufferTexturePixelLocalStorageANGLE(0, tex, 2, i); + ASSERT_GL_NO_ERROR(); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE})); + mProgram.drawBoxes({{FULLSCREEN}}); + ASSERT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); + } + + // Check that layer-faces 6-11 have inverted colors now + attachTextureLayerToScratchFBO(tex, 2, 6); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::cyan); + attachTextureLayerToScratchFBO(tex, 2, 7); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); + attachTextureLayerToScratchFBO(tex, 2, 8); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::magenta); + attachTextureLayerToScratchFBO(tex, 2, 9); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); + attachTextureLayerToScratchFBO(tex, 2, 10); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::yellow); + attachTextureLayerToScratchFBO(tex, 2, 11); + EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::blue); + ASSERT_GL_NO_ERROR(); + } +} // Check that early_fragment_tests are not triggered when PLS uniforms are not declared. TEST_P(PixelLocalStorageTestES31, EarlyFragmentTests) @@ -3775,6 +4716,14 @@ TEST_P(PixelLocalStorageTestES31, ImplicitDisables_RenderbufferAttachments) doImplicitDisablesTest_RenderbufferAttachments(); } +// Check that invalidation commands implicitly disable pixel local storage. +TEST_P(PixelLocalStorageTestES31, ImplicitDisables_Invalidate) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + doImplicitDisablesTest_Invalidate(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTestES31); PLS_INSTANTIATE_RENDERING_TEST_ES31(PixelLocalStorageTestES31); @@ -3788,14 +4737,10 @@ static void do_implicitly_enabled_extensions_test(const char *plsExtensionToRequ { bool hasDrawBuffersIndexedOES = IsGLExtensionRequestable("GL_OES_draw_buffers_indexed"); bool hasDrawBuffersIndexedEXT = IsGLExtensionRequestable("GL_EXT_draw_buffers_indexed"); - bool hasColorBufferFloat = IsGLExtensionRequestable("GL_EXT_color_buffer_float"); - bool hasColorBufferHalfFloat = IsGLExtensionRequestable("GL_EXT_color_buffer_half_float"); bool hasCoherent = IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage_coherent"); EXPECT_TRUE(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed")); - EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_float")); - EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); @@ -3810,14 +4755,6 @@ static void do_implicitly_enabled_extensions_test(const char *plsExtensionToRequ { EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed")); } - if (hasColorBufferFloat) - { - EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_float")); - } - if (hasColorBufferHalfFloat) - { - EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_half_float")); - } if (hasCoherent) { EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")); @@ -3844,26 +4781,6 @@ static void do_implicitly_enabled_extensions_test(const char *plsExtensionToRequ EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed")); } - if (hasColorBufferFloat) - { - // If EXT_color_buffer_float ever becomes disablable, it will have to implicitly disable - // ANGLE_shader_pixel_local_storage. - glDisableExtensionANGLE("GL_EXT_color_buffer_float"); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); - EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); - EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_float")); - } - - if (hasColorBufferHalfFloat) - { - // If EXT_color_buffer_half_float ever becomes disablable, it will have to implicitly - // disable ANGLE_shader_pixel_local_storage. - glDisableExtensionANGLE("GL_EXT_color_buffer_half_float"); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); - EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); - EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_half_float")); - } - if (hasCoherent) { // ANGLE_shader_pixel_local_storage_coherent is not disablable. @@ -3886,14 +4803,6 @@ static void do_implicitly_enabled_extensions_test(const char *plsExtensionToRequ { EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed")); } - if (hasColorBufferFloat) - { - EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_float")); - } - if (hasColorBufferHalfFloat) - { - EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_half_float")); - } if (hasCoherent) { EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")); @@ -3925,8 +4834,6 @@ TEST_P(PixelLocalStorageRequestableExtensionTest, ImplicitlyEnabledExtensionsCoh EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_TRUE(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed")); - EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_float")); - EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); } @@ -3945,8 +4852,6 @@ TEST_P(PixelLocalStorageRequestableExtensionTest, ANGLEShaderPixelLocalStorageNo EnsureGLExtensionEnabled("GL_OES_draw_buffers_indexed"); EnsureGLExtensionEnabled("GL_EXT_draw_buffers_indexed"); - EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"); - EnsureGLExtensionEnabled("GL_EXT_color_buffer_half_float"); EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent")); EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); @@ -3975,10 +4880,8 @@ class PixelLocalStorageValidationTest : public ANGLETest<> protected: void testSetUp() override { - ASSERT(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ASSERT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); glGetIntegerv(GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE, &MAX_PIXEL_LOCAL_STORAGE_PLANES); - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE, - &MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE); glGetIntegerv(GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE, &MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES); glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &MAX_COLOR_ATTACHMENTS); @@ -4020,7 +4923,6 @@ class PixelLocalStorageValidationTest : public ANGLETest<> } GLint MAX_PIXEL_LOCAL_STORAGE_PLANES = 0; - GLint MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE = 0; GLint MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES = 0; GLint MAX_COLOR_ATTACHMENTS = 0; GLint MAX_DRAW_BUFFERS = 0; @@ -4029,6 +4931,15 @@ class PixelLocalStorageValidationTest : public ANGLETest<> std::vector mErrorMessages; }; +class PixelLocalStorageWebGLValidationTest : public PixelLocalStorageValidationTest +{ + public: + PixelLocalStorageWebGLValidationTest() { setWebGLCompatibilityEnabled(true); } + + protected: + void testSetUp() override { PixelLocalStorageValidationTest::testSetUp(); } +}; + class ScopedEnable { public: @@ -4066,9 +4977,9 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferMemorylessPixelLocalStorageAN GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F); + glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32UI); EXPECT_GL_NO_ERROR(); - EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_R32F); + EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_R32UI); EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_NONE); EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, GL_NONE); EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, GL_NONE); @@ -4134,6 +5045,20 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferMemorylessPixelLocalStorageAN EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, GL_NONE); EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, GL_NONE); + // INVALID_OPERATION is generated if is not color-renderable. + glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Internal format is not renderable."); + EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I); + + // Repeat after enabling the extension + if (EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")) + { + glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F); + EXPECT_GL_NO_ERROR(); + EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_R32F); + } + ASSERT_GL_NO_ERROR(); } @@ -4272,19 +5197,7 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferTexturePixelLocalStorageANGLE EXPECT_GL_SINGLE_ERROR_MSG("Texture is not immutable."); // INVALID_OPERATION is generated if is nonzero - // and not of type TEXTURE_2D or TEXTURE_2D_ARRAY. - GLTexture texCube; - glBindTexture(GL_TEXTURE_CUBE_MAP, texCube); - glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 10, 10); - EXPECT_GL_NO_ERROR(); - glFramebufferTexturePixelLocalStorageANGLE(0, texCube, 0, 1); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage texture type."); - EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE); - EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0); - EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0); - EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0); - + // and of type TEXTURE_2D_MULTISAMPLE or TEXTURE_3D. GLTexture tex2DMultisample; glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex2DMultisample); glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 10, 10, 1); @@ -4367,6 +5280,23 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferTexturePixelLocalStorageANGLE EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0); } + GLTexture texCubeMap; + glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeMap); + glTexStorage2D(GL_TEXTURE_CUBE_MAP, 2, GL_RGBA8I, 10, 10); + EXPECT_GL_NO_ERROR(); + glFramebufferTexturePixelLocalStorageANGLE(2, texCubeMap, 1, 6); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); + EXPECT_GL_SINGLE_ERROR_MSG("Layer is larger than texture depth."); + glFramebufferTexturePixelLocalStorageANGLE(2, texCubeMap, 2, 5); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); + EXPECT_GL_SINGLE_ERROR_MSG("Level is larger than texture level count."); + glFramebufferTexturePixelLocalStorageANGLE(2, texCubeMap, 1, 5); + EXPECT_GL_NO_ERROR(); + EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I); + EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, texCubeMap); + EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 1); + EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 5); + // INVALID_ENUM is generated if is nonzero and its internalformat is not // one of the acceptable values in Table X.2. tex.reset(); @@ -4377,6 +5307,25 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferTexturePixelLocalStorageANGLE EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage internal format."); + // INVALID_OPERATION is generated if is nonzero and its internalformat is not + // color-renderable. + tex.reset(); + glBindTexture(GL_TEXTURE_2D, tex); + glTexStorage2D(GL_TEXTURE_2D, 3, GL_R32F, 10, 10); + EXPECT_GL_NO_ERROR(); + glFramebufferTexturePixelLocalStorageANGLE(2, tex, 1, 0); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Internal format is not renderable."); + EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I); + + // Repeat after enabling the extension + if (EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")) + { + glFramebufferTexturePixelLocalStorageANGLE(2, tex, 1, 0); + EXPECT_GL_NO_ERROR(); + EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_R32F); + } + ASSERT_GL_NO_ERROR(); } @@ -4517,12 +5466,12 @@ static std::vector FormatBannedCapMsg(GLenum cap) EXPECT_GL_NO_ERROR(); \ } -#define EXPECT_BANNED_CAP_INDEXED(cap) \ - { \ - std::vector msg = FormatBannedCapMsg(cap); \ - EXPECT_BANNED(glEnablei(cap, 0), msg.data()); \ - EXPECT_BANNED(glDisablei(cap, 0), msg.data()); \ - EXPECT_GL_NO_ERROR(); \ +#define EXPECT_BANNED_CAP_INDEXED(cap) \ + { \ + std::vector msg = FormatBannedCapMsg(cap); \ + EXPECT_BANNED(glEnableiOES(cap, 0), msg.data()); \ + EXPECT_BANNED(glDisableiOES(cap, 0), msg.data()); \ + EXPECT_GL_NO_ERROR(); \ } // Check that glBeginPixelLocalStorageANGLE validates non-PLS context state as specified. @@ -4589,20 +5538,11 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_context_stat "Attempted to begin pixel local storage with GL_DITHER enabled."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } - - // INVALID_OPERATION is generated if RASTERIZER_DISCARD is enabled. - { - ScopedEnable scopedEnable(GL_RASTERIZER_DISCARD); - glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE})); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG( - "Attempted to begin pixel local storage with GL_RASTERIZER_DISCARD enabled."); - ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - } } -// Check that transform feedback is banned when PLS is active. -TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_transform_feedback) +// Check that glBeginPixelLocalStorageANGLE() is banned while transform feedback +// is active, and that glBeginTransformFeedback() implicitly disables PLS. +TEST_P(PixelLocalStorageValidationTest, TransformFeedbackInteractions) { GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -4643,14 +5583,20 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_transform_feedback) EXPECT_GL_NO_ERROR(); EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1); - // glBeginTransformFeedback is not on the PLS allow list. - EXPECT_BANNED_DEFAULT_MSG(glBeginTransformFeedback(GL_TRIANGLES)) - ASSERT_GL_INTEGER(GL_TRANSFORM_FEEDBACK_ACTIVE, 0); - - glUseProgram(0); + // glBeginTransformFeedback implicitly disables PLS. + glBeginTransformFeedback(GL_TRIANGLES); EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_TRANSFORM_FEEDBACK_ACTIVE, 1); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); + + glEndTransformFeedback(); + EXPECT_GL_NO_ERROR(); + + glUseProgram(0); EXPECT_GL_NO_ERROR(); } @@ -4684,7 +5630,7 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_func_extended) if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - glBlendFunci(MAX_DRAW_BUFFERS - 1, GL_ZERO, blendFunc); + glBlendFunciOES(MAX_DRAW_BUFFERS - 1, GL_ZERO, blendFunc); ASSERT_GL_NO_ERROR(); glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); @@ -4707,7 +5653,7 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_func_extended) if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - glBlendFuncSeparatei(MAX_DRAW_BUFFERS - 1, blendFunc, GL_ONE, GL_ONE, GL_ONE); + glBlendFuncSeparateiOES(MAX_DRAW_BUFFERS - 1, blendFunc, GL_ONE, GL_ONE, GL_ONE); ASSERT_GL_NO_ERROR(); glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); @@ -4740,15 +5686,14 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_func_extended) if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - for (GLint i : {0, MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE - 1, - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1, + for (GLint i : {0, MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1, MAX_DRAW_BUFFERS - 1}) { - glBlendFunci(i, blendFunc, GL_ZERO); + glBlendFunciOES(i, blendFunc, GL_ZERO); EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG(kErrMsg); - glBlendFuncSeparatei(i, GL_ONE, GL_ONE, GL_ONE, blendFunc); + glBlendFuncSeparateiOES(i, GL_ONE, GL_ONE, GL_ONE, blendFunc); EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG(kErrMsg); } @@ -4771,8 +5716,8 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_func_extended) { for (GLint i = 0; i < MAX_DRAW_BUFFERS; ++i) { - glBlendFuncSeparatei(i, GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT, - GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT); + glBlendFuncSeparateiOES(i, GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT, + GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT); EXPECT_GL_NO_ERROR(); } } @@ -4823,7 +5768,7 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_equation_advanced) glBlendEquation(GL_FUNC_ADD); if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - glBlendEquationi(0, blendEquation); + glBlendEquationiOES(0, blendEquation); } else { @@ -4837,7 +5782,7 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_equation_advanced) if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - glBlendEquationi(0, GL_FUNC_ADD); + glBlendEquationiOES(0, GL_FUNC_ADD); } else { @@ -4859,12 +5804,12 @@ TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_equation_advanced) if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - for (GLint i : {0, MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE - 1, + for (GLint i : {0, MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1, MAX_DRAW_BUFFERS - 1}) { - glBlendEquationi(i, blendEquation); + glBlendEquationiOES(i, blendEquation); EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG( "Advanced blend equations are not supported when pixel local storage is " @@ -4903,29 +5848,6 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_framebuffer_ "Planes must be less than or equal to GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to - // any color attachment point on or after: - // - // COLOR_ATTACHMENT0 + - // MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE - // - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE < MAX_COLOR_ATTACHMENTS) - { - for (int reservedAttachment : - {MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE, MAX_COLOR_ATTACHMENTS - 1}) - { - PLSTestTexture tmp(GL_RGBA8, 100, 100); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + reservedAttachment, - GL_TEXTURE_2D, tmp, 0); - glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG( - "Framebuffer cannot have images attached to color attachment points on or after " - "COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE."); - ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - } - } - // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to // any color attachment point on or after: // @@ -4933,24 +5855,20 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_framebuffer_ // int maxColorAttachmentsWithMaxPLSPlanes = MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - MAX_PIXEL_LOCAL_STORAGE_PLANES; - if (maxColorAttachmentsWithMaxPLSPlanes < MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE) + for (int reservedAttachment : {maxColorAttachmentsWithMaxPLSPlanes, MAX_DRAW_BUFFERS - 1}) { - for (int reservedAttachment : {maxColorAttachmentsWithMaxPLSPlanes, - MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE - 1}) - { - PLSTestTexture tmp(GL_RGBA8, 100, 100); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + reservedAttachment, - GL_TEXTURE_2D, tmp, 0); - glBeginPixelLocalStorageANGLE( - MAX_PIXEL_LOCAL_STORAGE_PLANES, - std::vector(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DONT_CARE).data()); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG( - "Framebuffer cannot have images attached to color attachment points on or after " - "COLOR_ATTACHMENT0 + " - "MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."); - ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - } + PLSTestTexture tmp(GL_RGBA8, 100, 100); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + reservedAttachment, + GL_TEXTURE_2D, tmp, 0); + glBeginPixelLocalStorageANGLE( + MAX_PIXEL_LOCAL_STORAGE_PLANES, + std::vector(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DONT_CARE).data()); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "Framebuffer cannot have images attached to color attachment points on or after " + "COLOR_ATTACHMENT0 + " + "MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } } @@ -5112,7 +6030,6 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) // INVALID_OPERATION is generated if the draw framebuffer has other attachments, and its // enabled, texture-backed pixel local storage planes do not have identical dimensions with the // rendering area. - if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0) { PLSTestTexture rt0(GL_RGBA8, 200, 100); PLSTestTexture rt1(GL_RGBA8, 100, 200); @@ -5142,47 +6059,368 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) EXPECT_GL_NO_ERROR(); glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE})); - ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - } + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + } + + // INVALID_OPERATION is generated if the draw framebuffer has no attachments and no enabled, + // texture-backed pixel local storage planes. + { + for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i) + { + glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8); + } + glBeginPixelLocalStorageANGLE( + MAX_PIXEL_LOCAL_STORAGE_PLANES, + std::vector(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_LOAD_OP_ZERO_ANGLE).data()); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "Draw framebuffer has no attachments and no enabled, texture-backed pixel local " + "storage planes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8); + glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "Draw framebuffer has no attachments and no enabled, texture-backed pixel local " + "storage planes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + } +} + +// Check that glBeginPixelLocalStorageANGLE validates GL_TEXTURE_BASE_LEVEL and +// GL_TEXTURE_MAX_LEVEL. +// +// INVALID_OPERATION is generated if, for any active backing texture, the mipmap level bound to +// pixel local storage is outside the effective base/max range of that texture. +TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_base_max_level) +{ + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + ASSERT_GL_NO_ERROR(); + + PLSTestTexture pls0(GL_RGBA8, 256, 256, 9); + PLSTestTexture pls1(GL_RGBA8, 256, 256, 9); + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 2, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 2, 0); + + GLenum dontCare[2] = {GL_DONT_CARE, GL_DONT_CARE}; + glBeginPixelLocalStorageANGLE(2, dontCare); + glEndPixelLocalStorageANGLE(2, dontCare); + ASSERT_GL_NO_ERROR(); + + // GL_TEXTURE_BASE_LEVEL == GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: pass. + glBindTexture(GL_TEXTURE_2D, pls0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); + glBeginPixelLocalStorageANGLE(2, dontCare); + glEndPixelLocalStorageANGLE(2, dontCare); + ASSERT_GL_NO_ERROR(); + + // GL_TEXTURE_BASE_LEVEL > GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: fail. + glBindTexture(GL_TEXTURE_2D, pls1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3); + glBeginPixelLocalStorageANGLE(2, dontCare); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "Mipmap level for PLS backing texture outside the effective base/max range."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // GL_TEXTURE_BASE_LEVEL > GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, but plane not enabled: pass. + glBindTexture(GL_TEXTURE_2D, pls1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3); + glBeginPixelLocalStorageANGLE(1, dontCare); + glEndPixelLocalStorageANGLE(1, dontCare); + ASSERT_GL_NO_ERROR(); + + // GL_TEXTURE_BASE_LEVEL == GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: pass again. + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 3, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 3, 0); + glBeginPixelLocalStorageANGLE(2, dontCare); + glEndPixelLocalStorageANGLE(2, dontCare); + ASSERT_GL_NO_ERROR(); + + // GL_TEXTURE_MAX_LEVEL == GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: pass. + glBindTexture(GL_TEXTURE_2D, pls1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); + glBeginPixelLocalStorageANGLE(2, dontCare); + glEndPixelLocalStorageANGLE(2, dontCare); + ASSERT_GL_NO_ERROR(); + + // GL_TEXTURE_MAX_LEVEL < GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: fail. + glBindTexture(GL_TEXTURE_2D, pls0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); + glBeginPixelLocalStorageANGLE(2, dontCare); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "Mipmap level for PLS backing texture outside the effective base/max range."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); +} + +// Check that glBeginPixelLocalStorageANGLE validates feedback loops with GL_TEXTURE_2D as +// specified: +// +// INVALID_OPERATION is generated if a single texture slice is bound to more than one pixel local +// storage plane. +// +// INVALID_OPERATION is generated if a single texture slice is simultaneously bound to an active +// pixel local storage plane and attached to an enabled drawbuffer. +TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_collisions_tex2d) +{ + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffers(4, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3})); + ASSERT_GL_NO_ERROR(); + + // Check for simple tex2D collisions. + PLSTestTexture pls0(GL_RGBA8, W, H); + PLSTestTexture pls1(GL_RGBA8, W, H); + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + EXPECT_GL_NO_ERROR(); + glFramebufferTexturePixelLocalStorageANGLE(2, pls0, 0, 0); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is bound to multiple active pixel local storage planes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Now attach it to the framebuffer and check for a collision there. + PLSTestTexture color(GL_RGBA8, W, H); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, pls0, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is simultaneously bound to an active pixel local storage plane and " + "attached to an enabled drawbuffer."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Turning off the draw buffer removes the collision. + glDrawBuffers(4, GLenumArray({GL_COLOR_ATTACHMENT0, GL_NONE, GL_COLOR_ATTACHMENT2, GL_NONE})); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); + glDrawBuffers(4, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3})); + + // Double-binding the other plane also causes a collision. + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, pls1, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is simultaneously bound to an active pixel local storage plane and " + "attached to an enabled drawbuffer."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // A PLS collision is fine as long as only one of the planes is active. + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); +} + +// Check that glBeginPixelLocalStorageANGLE validates feedback loops with GL_TEXTURE_2D_ARRAY as +// specified: +// +// INVALID_OPERATION is generated if a single texture slice is bound to more than one active pixel +// local storage plane. +// +// INVALID_OPERATION is generated if a single texture slice is simultaneously bound to an active +// pixel local storage plane and attached to an enabled drawbuffer. +TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_collisions_tex2darray) +{ + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffers(4, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3})); + ASSERT_GL_NO_ERROR(); + + // Attach different array indices of the same texture to PLS. + GLTexture pls2darray; + glBindTexture(GL_TEXTURE_2D_ARRAY, pls2darray); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, W, H, 4); + glFramebufferTexturePixelLocalStorageANGLE(0, pls2darray, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls2darray, 0, 1); + glFramebufferTexturePixelLocalStorageANGLE(2, pls2darray, 0, 2); + glFramebufferTexturePixelLocalStorageANGLE(3, pls2darray, 0, 3); + glBeginPixelLocalStorageANGLE(4, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, + GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(4, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, + GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + EXPECT_GL_NO_ERROR(); + + // Now attach the same array index twice. + glFramebufferTexturePixelLocalStorageANGLE(2, pls2darray, 0, 3); + glBeginPixelLocalStorageANGLE(4, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, + GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is bound to multiple active pixel local storage planes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Now attach the same array index to the framebuffer and PLS. + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pls2darray, 0, 3); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is simultaneously bound to an active pixel local storage plane and " + "attached to an enabled drawbuffer."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Attach the sidelined layer to the framebuffer and use fewer PLS planes so there is no + // longer a collision. + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, pls2darray, 0, 2); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); +} + +// Check that glBeginPixelLocalStorageANGLE validates feedback loops with GL_TEXTURE_CUBE_MAP as +// specified: +// +// INVALID_OPERATION is generated if a single texture slice is bound to more than one active pixel +// local storage plane. +// +// INVALID_OPERATION is generated if a single texture slice is simultaneously bound to an active +// pixel local storage plane and attached to an enabled drawbuffer. +TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_collisions_texcubemap) +{ + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffers(4, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3})); + ASSERT_GL_NO_ERROR(); + + // Attach different faces of the same cube map texture to PLS. + GLTexture plscubemap; + glBindTexture(GL_TEXTURE_CUBE_MAP, plscubemap); + glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, W, H); + ASSERT_GL_NO_ERROR(); + glFramebufferTexturePixelLocalStorageANGLE(0, plscubemap, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, plscubemap, 0, 1); + glFramebufferTexturePixelLocalStorageANGLE(2, plscubemap, 0, 2); + glFramebufferTexturePixelLocalStorageANGLE(3, plscubemap, 0, 3); + glBeginPixelLocalStorageANGLE(4, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, + GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(4, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, + GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + EXPECT_GL_NO_ERROR(); - // INVALID_OPERATION is generated if the draw framebuffer has no attachments and no enabled, - // texture-backed pixel local storage planes. - { - for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i) - { - glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8); - } - glBeginPixelLocalStorageANGLE( - MAX_PIXEL_LOCAL_STORAGE_PLANES, - std::vector(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_LOAD_OP_ZERO_ANGLE).data()); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG( - "Draw framebuffer has no attachments and no enabled, texture-backed pixel local " - "storage planes."); - ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + // Now attach the same face index twice. + glFramebufferTexturePixelLocalStorageANGLE(2, plscubemap, 0, 3); + glBeginPixelLocalStorageANGLE(4, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, + GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is bound to multiple active pixel local storage planes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8); - glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG( - "Draw framebuffer has no attachments and no enabled, texture-backed pixel local " - "storage planes."); - ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - } + // Now attach the same face index to the framebuffer and PLS (-Y face has index 3). + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + plscubemap, 0); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is simultaneously bound to an active pixel local storage plane and " + "attached to an enabled drawbuffer."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Attach the sidelined face to the framebuffer and use fewer PLS planes so there is no + // longer a collision (+Y face has index 2). + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + plscubemap, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); } -// TODO(anglebug.com/40096838): Block feedback loops -// Check glBeginPixelLocalStorageANGLE validates feedback loops as specified. -// TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_feedback_loops) -// { -// // INVALID_OPERATION is generated if a single texture image is bound to more than one pixel -// // local storage plane. +// Check that glBeginPixelLocalStorageANGLE validates feedback loops with mipmap levels as +// specified: // -// // INVALID_OPERATION is generated if a single texture image is simultaneously bound to a -// // pixel local storage plane and attached to the draw framebuffer. +// INVALID_OPERATION is generated if a single texture slice is bound to more than one active pixel +// local storage plane. // -// ASSERT_GL_NO_ERROR(); -// } +// INVALID_OPERATION is generated if a single texture slice is simultaneously bound to an active +// pixel local storage plane and attached to an enabled drawbuffer. +TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_collisions_mipmap) +{ + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffers(4, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3})); + ASSERT_GL_NO_ERROR(); + + // Check collisions with mipmaps. + GLTexture pls8; + glBindTexture(GL_TEXTURE_2D, pls8); + glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 8, 8); + GLTexture pls16; + glBindTexture(GL_TEXTURE_2D, pls16); + glTexStorage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 16, 16); + ASSERT_GL_NO_ERROR(); + glFramebufferTexturePixelLocalStorageANGLE(0, pls8, 2, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls16, 3, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + EXPECT_GL_NO_ERROR(); + + // Can't have the same mipmap level attached to different PLS planes. + glFramebufferTexturePixelLocalStorageANGLE(2, pls16, 3, 0); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is bound to multiple active pixel local storage planes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Can't attach different levels to PLS because they're different sizes. + glFramebufferTexturePixelLocalStorageANGLE(2, pls16, 2, 0); + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Mismatched pixel local storage backing texture sizes."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Can't have the same mipmap level attached to PLS and the framebuffer. + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, pls16, 3); + glBeginPixelLocalStorageANGLE( + 2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "A single texture slice is simultaneously bound to an active pixel local storage plane and " + "attached to an enabled drawbuffer."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Can't attach different levels to the framebuffer because they're different sizes. + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, pls16, 2); + glBeginPixelLocalStorageANGLE( + 2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG( + "Pixel local storage backing texture dimensions not equal to the rendering area."); + ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + + // Removing the attachment causes PLS to pass again. + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0); + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + ASSERT_GL_NO_ERROR(); +} // Check that glEndPixelLocalStorageANGLE and glPixelLocalStorageBarrierANGLE validate as specified. TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) @@ -5291,17 +6529,17 @@ TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) glEndPixelLocalStorageANGLE( 3, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E5."); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E4."); glEndPixelLocalStorageANGLE( 3, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE, GL_STORE_OP_STORE_ANGLE})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E6."); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E5."); glEndPixelLocalStorageANGLE( 3, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E4."); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E3."); glEndPixelLocalStorageANGLE( 3, GLenumArray({GL_DONT_CARE, GL_SCISSOR_BOX, GL_STORE_OP_STORE_ANGLE})); @@ -5416,24 +6654,20 @@ TEST_P(PixelLocalStorageValidationTest, GetFramebufferPixelLocalStorageParameter GLFramebuffer fbo; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is + // No error is generated if pixel local storage on the draw framebuffer is // in an interrupted state. glFramebufferPixelLocalStorageInterruptANGLE(); glGetFramebufferPixelLocalStorageParameterfvRobustANGLE( 0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted."); + EXPECT_GL_NO_ERROR(); glGetFramebufferPixelLocalStorageParameterfvANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted."); + EXPECT_GL_NO_ERROR(); glGetFramebufferPixelLocalStorageParameterivRobustANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, 4, &length, ints); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted."); + EXPECT_GL_NO_ERROR(); glGetFramebufferPixelLocalStorageParameterivANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, ints); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted."); + EXPECT_GL_NO_ERROR(); glFramebufferPixelLocalStorageRestoreANGLE(); ASSERT_GL_NO_ERROR(); @@ -5473,70 +6707,29 @@ TEST_P(PixelLocalStorageValidationTest, GetFramebufferPixelLocalStorageParameter EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE."); - // INVALID_ENUM is generated if the command issued is not the associated "Get Command" for - // in Table 6.Y. - glGetFramebufferPixelLocalStorageParameterivRobustANGLE( - 0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, ints); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EC is currently not supported."); - glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, - ints); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EC is currently not supported."); - glGetFramebufferPixelLocalStorageParameterivRobustANGLE( - 0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, 4, &length, ints); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD0 is currently not supported."); - glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, - ints); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD0 is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, 4, - &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E8 is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E8 is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 1, - &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E9 is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E9 is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, - 1, &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EA is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, - floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EA is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, - 1, &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EB is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, - floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EB is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, - 1, &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96ED is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, - floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96ED is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvRobustANGLE( - 1, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, 1, &length, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EE is currently not supported."); - glGetFramebufferPixelLocalStorageParameterfvANGLE( - 1, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, floats); - EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EE is currently not supported."); + // No error for known enums + const GLenum params[] = { + GL_PIXEL_LOCAL_FORMAT_ANGLE, + GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, + GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, + GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, + GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, + GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, + GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, + }; + for (GLenum param : params) + { + glGetFramebufferPixelLocalStorageParameterfvANGLE(0, param, floats); + EXPECT_GL_NO_ERROR(); + glGetFramebufferPixelLocalStorageParameterivANGLE(0, param, ints); + EXPECT_GL_NO_ERROR(); + glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(0, param, 4, &length, floats); + EXPECT_GL_NO_ERROR(); + glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, param, 4, &length, ints); + EXPECT_GL_NO_ERROR(); + } + + // INVALID_ENUM is generated if is not in Table 6.Y. glGetFramebufferPixelLocalStorageParameterfvRobustANGLE( 1, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 1, &length, floats); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); @@ -5545,6 +6738,14 @@ TEST_P(PixelLocalStorageValidationTest, GetFramebufferPixelLocalStorageParameter 1, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, floats); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD3 is currently not supported."); + glGetFramebufferPixelLocalStorageParameterivRobustANGLE( + 1, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 1, &length, ints); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); + EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD3 is currently not supported."); + glGetFramebufferPixelLocalStorageParameterivANGLE( + 1, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, ints); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); + EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD3 is currently not supported."); // INVALID_OPERATION is generated if is not large enough to receive the requested // parameter. @@ -5716,15 +6917,6 @@ TEST_P(PixelLocalStorageValidationTest, BannedCommands) ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, numActivePlanes); ASSERT_GL_NO_ERROR(); - // Check commands called out by EXT_shader_pixel_local_storage for flushing tiled memory. - EXPECT_BANNED_DEFAULT_MSG(glFlush()); - EXPECT_BANNED_DEFAULT_MSG(glFinish()); - EXPECT_BANNED_DEFAULT_MSG(glClientWaitSync(nullptr, 0, 0)); - EXPECT_BANNED_DEFAULT_MSG( - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); - EXPECT_BANNED_DEFAULT_MSG(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)); - EXPECT_BANNED_DEFAULT_MSG(glBlitFramebuffer(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - // INVALID_OPERATION is generated by Enable(), Disable() if is not one of: CULL_FACE, // DEPTH_CLAMP_EXT, DEPTH_TEST, POLYGON_OFFSET_POINT_NV, POLYGON_OFFSET_LINE_NV, // POLYGON_OFFSET_LINE_ANGLE, POLYGON_OFFSET_FILL, PRIMITIVE_RESTART_FIXED_INDEX, @@ -5763,6 +6955,7 @@ TEST_P(PixelLocalStorageValidationTest, BannedCommands) } EXPECT_ALLOWED_CAP(GL_POLYGON_OFFSET_FILL); EXPECT_ALLOWED_CAP(GL_PRIMITIVE_RESTART_FIXED_INDEX); + EXPECT_ALLOWED_CAP(GL_RASTERIZER_DISCARD); EXPECT_ALLOWED_CAP(GL_SCISSOR_TEST); EXPECT_ALLOWED_CAP(GL_STENCIL_TEST); if (EnsureGLExtensionEnabled("GL_EXT_clip_cull_distance")) @@ -5775,7 +6968,6 @@ TEST_P(PixelLocalStorageValidationTest, BannedCommands) EXPECT_BANNED_CAP(GL_SAMPLE_ALPHA_TO_COVERAGE); EXPECT_BANNED_CAP(GL_SAMPLE_COVERAGE); EXPECT_BANNED_CAP(GL_DITHER); - EXPECT_BANNED_CAP(GL_RASTERIZER_DISCARD); if (isContextVersionAtLeast(3, 1)) { EXPECT_BANNED_CAP(GL_SAMPLE_MASK); @@ -5804,33 +6996,26 @@ TEST_P(PixelLocalStorageValidationTest, BannedCommands) // The validation tests are expected to run in a configuration where the draw buffers are // restricted by PLS (e.g., not shader images). - int bannedColorAttachment = MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE; - ASSERT(bannedColorAttachment < MAX_DRAW_BUFFERS); - int bannedCombinedAttachment = MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numActivePlanes; + ASSERT(bannedCombinedAttachment < MAX_DRAW_BUFFERS); // glClearBuffer{f,i,ui}v are ignored for all attachments at or beyond - // MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE when PLS is active. + // MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numActivePlanes. GLfloat clearf[4]{}; GLint cleari[4]{}; GLuint clearui[4]{}; - { - glClearBufferfv(GL_COLOR, bannedColorAttachment, clearf); - glClearBufferiv(GL_COLOR, bannedColorAttachment, cleari); - glClearBufferuiv(GL_COLOR, bannedColorAttachment, clearui); - glClearBufferfv(GL_COLOR, MAX_DRAW_BUFFERS - 1, clearf); - glClearBufferiv(GL_COLOR, MAX_DRAW_BUFFERS - 1, cleari); - glClearBufferuiv(GL_COLOR, MAX_DRAW_BUFFERS - 1, clearui); - EXPECT_GL_NO_ERROR(); - } - if (bannedCombinedAttachment < bannedColorAttachment) - { - glClearBufferfv(GL_COLOR, bannedCombinedAttachment, clearf); - glClearBufferiv(GL_COLOR, bannedCombinedAttachment, cleari); - glClearBufferuiv(GL_COLOR, bannedCombinedAttachment, clearui); - EXPECT_GL_NO_ERROR(); - } + + glClearBufferfv(GL_COLOR, MAX_DRAW_BUFFERS - 1, clearf); + glClearBufferiv(GL_COLOR, MAX_DRAW_BUFFERS - 1, cleari); + glClearBufferuiv(GL_COLOR, MAX_DRAW_BUFFERS - 1, clearui); + EXPECT_GL_NO_ERROR(); + + glClearBufferfv(GL_COLOR, bannedCombinedAttachment, clearf); + glClearBufferiv(GL_COLOR, bannedCombinedAttachment, cleari); + glClearBufferuiv(GL_COLOR, bannedCombinedAttachment, clearui); + EXPECT_GL_NO_ERROR(); + glClearBufferfv(GL_DEPTH, 0, clearf); EXPECT_GL_NO_ERROR(); glClearBufferiv(GL_STENCIL, 0, cleari); @@ -5839,25 +7024,14 @@ TEST_P(PixelLocalStorageValidationTest, BannedCommands) if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { // Enabling and disabling GL_BLEND is valid while PLS is active. - { - glEnableiOES(GL_BLEND, bannedColorAttachment); - glDisableiOES(GL_BLEND, bannedColorAttachment); - glEnableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1); - glDisableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1); - EXPECT_GL_NO_ERROR(); - } - if (bannedCombinedAttachment < bannedColorAttachment) - { - glEnableiOES(GL_BLEND, bannedCombinedAttachment); - glDisableiOES(GL_BLEND, bannedCombinedAttachment); - EXPECT_GL_NO_ERROR(); - } - } + glEnableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1); + glDisableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1); + EXPECT_GL_NO_ERROR(); - // INVALID_OPERATION is generated if a draw is issued with a fragment shader that accesses a - // texture bound to pixel local storage. - // - // TODO(anglebug.com/40096838). + glEnableiOES(GL_BLEND, bannedCombinedAttachment); + glDisableiOES(GL_BLEND, bannedCombinedAttachment); + EXPECT_GL_NO_ERROR(); + } ASSERT_GL_NO_ERROR(); } @@ -5979,26 +7153,196 @@ TEST_P(PixelLocalStorageValidationTest, BlendFuncDuringPLS) EXPECT_EQ(blendEquationRGB, GL_FUNC_REVERSE_SUBTRACT); EXPECT_EQ(blendEquationAlpha, GL_FUNC_ADD); - GLint blendSrcRGB, blendDstRGB, blendSrcAlpha, blendDstAlpha; - if (drawBufferIndexCount > 1) - { - glGetIntegeri_v(GL_BLEND_SRC_RGB, i, &blendSrcRGB); - glGetIntegeri_v(GL_BLEND_SRC_ALPHA, i, &blendSrcAlpha); - glGetIntegeri_v(GL_BLEND_DST_RGB, i, &blendDstRGB); - glGetIntegeri_v(GL_BLEND_DST_ALPHA, i, &blendDstAlpha); - } - else - { - glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); - glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); - glGetIntegerv(GL_BLEND_DST_RGB, &blendDstRGB); - glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDstAlpha); - } - EXPECT_EQ(blendSrcRGB, GL_ZERO); - EXPECT_EQ(blendDstRGB, GL_DST_COLOR); - EXPECT_EQ(blendSrcAlpha, GL_DST_ALPHA); - EXPECT_EQ(blendDstAlpha, GL_SRC_COLOR); - } + GLint blendSrcRGB, blendDstRGB, blendSrcAlpha, blendDstAlpha; + if (drawBufferIndexCount > 1) + { + glGetIntegeri_v(GL_BLEND_SRC_RGB, i, &blendSrcRGB); + glGetIntegeri_v(GL_BLEND_SRC_ALPHA, i, &blendSrcAlpha); + glGetIntegeri_v(GL_BLEND_DST_RGB, i, &blendDstRGB); + glGetIntegeri_v(GL_BLEND_DST_ALPHA, i, &blendDstAlpha); + } + else + { + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDstRGB); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDstAlpha); + } + EXPECT_EQ(blendSrcRGB, GL_ZERO); + EXPECT_EQ(blendDstRGB, GL_DST_COLOR); + EXPECT_EQ(blendSrcAlpha, GL_DST_ALPHA); + EXPECT_EQ(blendDstAlpha, GL_SRC_COLOR); + } +} + +// Check that glGetFramebufferAttachmentParameteriv() generates errors when +// querying overridden PLS attachments. +TEST_P(PixelLocalStorageValidationTest, FramebufferQueries) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + PLSTestTexture pls0(GL_RGBA8); + PLSTestTexture pls1(GL_RGBA8); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0); + + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE})); + EXPECT_GL_NO_ERROR(); + + int firstOverriddenDrawBuffer = MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 2; + // The validation tests are expected to run in a configuration where the draw buffers are + // restricted by PLS (e.g., not shader images). + ASSERT(firstOverriddenDrawBuffer < MAX_DRAW_BUFFERS); + + GLint intValue; + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + firstOverriddenDrawBuffer, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Color attachment is actively reserved for pixel local storage."); + + glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 2, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Color attachment is actively reserved for pixel local storage."); + + glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Color attachment is actively reserved for pixel local storage."); + + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS - 1, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Color attachment is actively reserved for pixel local storage."); + + if (firstOverriddenDrawBuffer != 0) + { + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_NO_ERROR(); + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + firstOverriddenDrawBuffer - 1, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_NO_ERROR(); + } + + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE})); + EXPECT_GL_NO_ERROR(); + + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + firstOverriddenDrawBuffer, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_NO_ERROR(); + + glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 2, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_NO_ERROR(); + + glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_NO_ERROR(); + + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS - 1, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &intValue); + EXPECT_GL_NO_ERROR(); +} + +// Test that binding overlapping regions of a texture to a sampler and a PLS plane is an error. +TEST_P(PixelLocalStorageWebGLValidationTest, FeedbackLoopValidation) +{ + PLSProgram program; + program.compile(R"( + layout(binding=0, rgba8) uniform lowp pixelLocalANGLE plane1; + layout(rgba8i, binding=1) uniform lowp ipixelLocalANGLE plane2; + layout(binding=2, rgba8ui) uniform lowp upixelLocalANGLE plane3; + uniform sampler2D tex2d; + uniform highp sampler2DArray tex2dArray; + void main() + { + vec3 texcoord = vec3(0, 0, 0); + vec4 sampledValue = texture(tex2d, texcoord.xy) + texture(tex2dArray, texcoord.xyz); + pixelLocalStoreANGLE(plane1, sampledValue + color + pixelLocalLoadANGLE(plane1)); + pixelLocalStoreANGLE(plane2, ivec4(aux1) + pixelLocalLoadANGLE(plane2)); + pixelLocalStoreANGLE(plane3, uvec4(aux2) + pixelLocalLoadANGLE(plane3)); + })"); + + GLuint sampler2dLocation = glGetUniformLocation(program, "tex2d"); + glUniform1i(sampler2dLocation, 0); + + GLuint sampler2dArrayLocation = glGetUniformLocation(program, "tex2dArray"); + glUniform1i(sampler2dArrayLocation, 1); + + PLSTestTexture tex1(GL_RGBA8); + PLSTestTexture tex2(GL_RGBA8I); + PLSTestTexture tex3(GL_RGBA8UI); + + // 2D_ARRAY texture for coverage of more texture types + GLTexture tex4; + glBindTexture(GL_TEXTURE_2D_ARRAY, tex4); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, W, H, 16); + + // Attached to plane 3 but unrefernced/inactive + PLSTestTexture tex5(GL_RGBA8); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(1, tex2, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(2, tex3, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(3, tex5, 0, 0); + glViewport(0, 0, W, H); + glDrawBuffers(0, nullptr); + + auto doSinglePLSDraw = [&]() { + glBeginPixelLocalStorageANGLE( + 3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE})); + program.drawBoxes({{FULLSCREEN, {-1.5, 0, 0, 0}, {0x000000ff, 0, 0, 0}}}); + glEndPixelLocalStorageANGLE( + 3, GLenumArray( + {GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + }; + + // Bind tex1 and tex4 for sampling + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex1); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D_ARRAY, tex4); + ASSERT_GL_NO_ERROR(); + + // Bind tex1 as a PLS plane, should generate a feedback loop error + glFramebufferTexturePixelLocalStorageANGLE(0, tex1, 0, 0); + ASSERT_GL_NO_ERROR(); + doSinglePLSDraw(); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Feedback loop formed between Framebuffer and active Texture."); + + // Bind tex5 for sampling. Should not generate feedback loop errors because it's bound to an + // inactive plane + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex5); + ASSERT_GL_NO_ERROR(); + doSinglePLSDraw(); + EXPECT_GL_NO_ERROR(); + + // Bind the 2D array texture as a PLS plane and expect that it generates a feedback loop because + // it's also bound for sampling. + glFramebufferTexturePixelLocalStorageANGLE(0, tex4, 0, 0); + ASSERT_GL_NO_ERROR(); + doSinglePLSDraw(); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + EXPECT_GL_SINGLE_ERROR_MSG("Feedback loop formed between Framebuffer and active Texture."); } // Check that glEnable(GL_BLEND) and glColorMask() do not generate errors, and are ignored for @@ -6006,7 +7350,7 @@ TEST_P(PixelLocalStorageValidationTest, BlendFuncDuringPLS) TEST_P(PixelLocalStorageValidationTest, BlendMaskDuringPLS) { // Make sure we're given a context where this test is relevant. - ASSERT(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE < MAX_DRAW_BUFFERS); + ASSERT(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES <= MAX_DRAW_BUFFERS); PLSTestTexture tex(GL_RGBA8); GLFramebuffer fbo; @@ -6025,63 +7369,40 @@ TEST_P(PixelLocalStorageValidationTest, BlendMaskDuringPLS) glEndPixelLocalStorageANGLE(numActivePlanes, std::vector(numActivePlanes, GL_DONT_CARE).data()); }; - int firstOverriddenDrawBuffer = - std::min(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE, - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numActivePlanes); -#define CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED() \ - for (int i = firstOverriddenDrawBuffer; i < MAX_DRAW_BUFFERS; ++i) \ - { \ - EXPECT_FALSE(glIsEnabledi(GL_BLEND, i)); \ - } - -#define EXPECT_NON_OVERRIDDEN_BLEND_MASK(ENABLED) \ - if (!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) \ - { \ - EXPECT_FALSE(glIsEnabled(GL_BLEND)); \ - } \ - else \ +#define EXPECT_UNIFORM_BLEND_MASK(ENABLED) \ + EXPECT_EQ(glIsEnabled(GL_BLEND), ENABLED); \ + EXPECT_GL_INTEGER(GL_BLEND, ENABLED); \ + if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) \ { \ - EXPECT_EQ(glIsEnabled(GL_BLEND), ENABLED); \ - for (int i = 0; i < firstOverriddenDrawBuffer; ++i) \ + for (int i = 0; i < MAX_DRAW_BUFFERS; ++i) \ { \ - EXPECT_EQ(glIsEnabledi(GL_BLEND, i), ENABLED); \ + EXPECT_EQ(glIsEnablediOES(GL_BLEND, i), ENABLED); \ } \ - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); \ } -#define CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED() \ - for (int i = firstOverriddenDrawBuffer; i < MAX_DRAW_BUFFERS; ++i) \ - { \ - EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \ - } - -#define EXPECT_NON_OVERRIDDEN_COLOR_MASK(R, G, B, A) \ - if (!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) \ - { \ - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \ - } \ - else \ - { \ - EXPECT_GL_COLOR_MASK(R, G, B, A); \ - for (int i = 0; i < firstOverriddenDrawBuffer; ++i) \ - { \ - EXPECT_GL_COLOR_MASK_INDEXED(i, R, G, B, A); \ - } \ - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); \ +#define EXPECT_UNIFORM_COLOR_MASK(R, G, B, A) \ + EXPECT_GL_COLOR_MASK(R, G, B, A); \ + if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) \ + { \ + for (int i = 0; i < MAX_DRAW_BUFFERS; ++i) \ + { \ + EXPECT_GL_COLOR_MASK_INDEXED(i, R, G, B, A); \ + } \ } // Set before. glEnable(GL_BLEND); - EXPECT_TRUE(glIsEnabled(GL_BLEND)); + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); beginPLS(); - EXPECT_NON_OVERRIDDEN_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE); EXPECT_GL_NO_ERROR(); - EXPECT_NON_OVERRIDDEN_COLOR_MASK(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE); + EXPECT_UNIFORM_COLOR_MASK(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE); endPLS(); // Blend & color mask shouldn't change after endPLS(). - EXPECT_NON_OVERRIDDEN_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_COLOR_MASK(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE); glDisable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -6089,163 +7410,543 @@ TEST_P(PixelLocalStorageValidationTest, BlendMaskDuringPLS) // Set during. beginPLS(); - EXPECT_NON_OVERRIDDEN_BLEND_MASK(GL_FALSE); - EXPECT_NON_OVERRIDDEN_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + EXPECT_UNIFORM_BLEND_MASK(GL_FALSE); + EXPECT_UNIFORM_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); EXPECT_GL_NO_ERROR(); - EXPECT_NON_OVERRIDDEN_BLEND_MASK(GL_TRUE); - EXPECT_NON_OVERRIDDEN_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); endPLS(); // Blend & color mask shouldn't change after endPLS(). - EXPECT_NON_OVERRIDDEN_BLEND_MASK(GL_TRUE); - EXPECT_NON_OVERRIDDEN_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glDisable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); EXPECT_GL_NO_ERROR(); if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")) { - ASSERT(firstOverriddenDrawBuffer > 0); - GLint highestPLSDrawBuffer = - std::min(MAX_DRAW_BUFFERS, MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES) - - 1; - // Indexed before, non-indexed during. - glEnablei(GL_BLEND, 0); - glEnablei(GL_BLEND, highestPLSDrawBuffer); - glColorMaski(0, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); - glColorMaski(highestPLSDrawBuffer, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + glEnableiOES(GL_BLEND, 0); + glEnableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1); + glColorMaskiOES(0, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + glColorMaskiOES(MAX_DRAW_BUFFERS - 1, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); beginPLS(); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - if (firstOverriddenDrawBuffer > 1) + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, 0)); + for (GLint i = 1; i < MAX_DRAW_BUFFERS - 1; ++i) { - EXPECT_TRUE(!glIsEnabledi(GL_BLEND, 1)); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, i)); } - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, MAX_DRAW_BUFFERS - 1)); EXPECT_GL_COLOR_MASK_INDEXED(0, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); - if (firstOverriddenDrawBuffer > 1) + for (GLint i = 1; i < MAX_DRAW_BUFFERS - 1; ++i) { - EXPECT_GL_COLOR_MASK_INDEXED(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); + EXPECT_GL_COLOR_MASK_INDEXED(MAX_DRAW_BUFFERS - 1, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + + glEnable(GL_BLEND); + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); + + glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_UNIFORM_COLOR_MASK(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + + endPLS(); + + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_COLOR_MASK(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + + glDisable(GL_BLEND); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + EXPECT_GL_NO_ERROR(); + // Non-indexed before, indexed during. + glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); glEnable(GL_BLEND); + + beginPLS(); + + EXPECT_UNIFORM_BLEND_MASK(GL_TRUE); + EXPECT_UNIFORM_COLOR_MASK(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + + glDisableiOES(GL_BLEND, 1); + glDisableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1); EXPECT_TRUE(glIsEnabled(GL_BLEND)); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - if (firstOverriddenDrawBuffer > 1) + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, 0)); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, 1)); + for (GLint i = 2; i < MAX_DRAW_BUFFERS - 1; ++i) { - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 1)); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, i)); } - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); - - glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); - EXPECT_GL_COLOR_MASK(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); - EXPECT_GL_COLOR_MASK_INDEXED(0, GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); - if (firstOverriddenDrawBuffer > 1) + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, MAX_DRAW_BUFFERS - 1)); + + glColorMaskiOES(2, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + glColorMaskiOES(MAX_DRAW_BUFFERS - 1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(0, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(2, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + for (GLint i = 3; i < MAX_DRAW_BUFFERS - 1; ++i) { - EXPECT_GL_COLOR_MASK_INDEXED(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); } - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); + EXPECT_GL_COLOR_MASK_INDEXED(MAX_DRAW_BUFFERS - 1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); endPLS(); EXPECT_TRUE(glIsEnabled(GL_BLEND)); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - if (firstOverriddenDrawBuffer > 1) + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, 0)); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, 1)); + for (GLint i = 2; i < MAX_DRAW_BUFFERS - 1; ++i) { - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 1)); + EXPECT_TRUE(glIsEnablediOES(GL_BLEND, i)); } - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); + EXPECT_FALSE(glIsEnablediOES(GL_BLEND, MAX_DRAW_BUFFERS - 1)); - EXPECT_GL_COLOR_MASK(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); - EXPECT_GL_COLOR_MASK_INDEXED(0, GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); - if (firstOverriddenDrawBuffer > 1) + EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(0, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(2, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + for (GLint i = 3; i < MAX_DRAW_BUFFERS - 1; ++i) { - EXPECT_GL_COLOR_MASK_INDEXED(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + EXPECT_GL_COLOR_MASK_INDEXED(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); } - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); + EXPECT_GL_COLOR_MASK_INDEXED(MAX_DRAW_BUFFERS - 1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDisable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); EXPECT_GL_NO_ERROR(); + } - // Non-indexed before, indexed during. - glColorMaski(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); - glEnable(GL_BLEND); + EXPECT_GL_NO_ERROR(); - beginPLS(); +#undef EXPECT_NON_OVERRIDDEN_COLOR_MASK +#undef EXPECT_UNIFORM_BLEND_MASK +} - EXPECT_TRUE(glIsEnabled(GL_BLEND)); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - if (firstOverriddenDrawBuffer > 1) +// Check that modifications to PLS textures bounce while it's active. +TEST_P(PixelLocalStorageValidationTest, ModifyTextureDuringPLS) +{ + GLTexture pls2d; + glBindTexture(GL_TEXTURE_2D, pls2d); + glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, W, H); + + GLTexture nonpls2d; + glBindTexture(GL_TEXTURE_2D, nonpls2d); + glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, W, H); + + GLTexture pls2darray; + glBindTexture(GL_TEXTURE_2D_ARRAY, pls2darray); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 3, GL_RGBA8, W, H, 5); + + GLTexture nonpls2darray; + glBindTexture(GL_TEXTURE_2D_ARRAY, nonpls2darray); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 3, GL_RGBA8, W, H, 5); + + GLFramebuffer fbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, pls2d, 1, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls2darray, 1, 4); + + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE})); + ASSERT_GL_NO_ERROR(); + +#define CHECK_TEXTURE_2D_MODIFICATION(FN) \ + glBindTexture(GL_TEXTURE_2D, pls2d); \ + FN; \ + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); \ + EXPECT_GL_SINGLE_ERROR_MSG( \ + "Operation not permitted on an active pixel local storage backing texture.") \ + glBindTexture(GL_TEXTURE_2D, nonpls2d); \ + FN; \ + EXPECT_GL_NO_ERROR(); + +#define CHECK_TEXTURE_2D_ARRAY_MODIFICATION(FN) \ + glBindTexture(GL_TEXTURE_2D_ARRAY, pls2darray); \ + FN; \ + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); \ + EXPECT_GL_SINGLE_ERROR_MSG( \ + "Operation not permitted on an active pixel local storage backing texture.") \ + glBindTexture(GL_TEXTURE_2D_ARRAY, nonpls2darray); \ + FN; \ + EXPECT_GL_NO_ERROR(); + + std::vector imageData(H * W * 4); + + CHECK_TEXTURE_2D_MODIFICATION( + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, imageData.data())); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION(glTexSubImage3D( + GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, imageData.data())); + + CHECK_TEXTURE_2D_MODIFICATION(glGenerateMipmap(GL_TEXTURE_2D)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION(glGenerateMipmap(GL_TEXTURE_2D_ARRAY)); + + if (EnsureGLExtensionEnabled("GL_ANGLE_robust_client_memory")) + { + CHECK_TEXTURE_2D_MODIFICATION( + glTexSubImage2DRobustANGLE(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, + imageData.size(), imageData.data())); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexSubImage3DRobustANGLE(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, W, H, 1, GL_RGBA, + GL_UNSIGNED_BYTE, imageData.size(), imageData.data())); + } + + if (EnsureGLExtensionEnabled("GL_OES_texture_3D")) + { + CHECK_TEXTURE_2D_ARRAY_MODIFICATION(glTexSubImage3DOES( + GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, W, H, 1, GL_RGBA, GL_UNSIGNED_BYTE, imageData.data())); + } + + if (EnsureGLExtensionEnabled("GL_ANGLE_texture_external_update")) + { + CHECK_TEXTURE_2D_MODIFICATION(glInvalidateTextureANGLE(GL_TEXTURE_2D)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION(glInvalidateTextureANGLE(GL_TEXTURE_2D_ARRAY)); + } + + GLfloat zerof[4] = {}; + GLint zeroi[4] = {}; + GLuint zeroui[4] = {}; + CHECK_TEXTURE_2D_MODIFICATION(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); + CHECK_TEXTURE_2D_MODIFICATION(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, zeroi)); + CHECK_TEXTURE_2D_MODIFICATION(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0.f)); + CHECK_TEXTURE_2D_MODIFICATION(glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, zerof)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameteriv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, zeroi)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LOD, 0.f)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LOD, zerof)); + + if (EnsureGLExtensionEnabled("GL_ANGLE_robust_client_memory")) + { + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterivRobustANGLE(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1, zeroi)); + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterfvRobustANGLE(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 1, zerof)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterfvRobustANGLE(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LOD, 1, zerof)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterivRobustANGLE(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1, zeroi)); + + // TODO: Re-enable these tests once glTexParameterI(u?)ivRobustANGLE are implemented. +#if 0 + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterIivRobustANGLE(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, 4, zeroi)); + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterIuivRobustANGLE(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, 4, zeroui)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterIivRobustANGLE(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, 4, zeroi)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterIuivRobustANGLE(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, 4, zeroui)); +#endif + } + + if (EnsureGLExtensionEnabled("GL_EXT_texture_border_clamp")) + { + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterIivEXT(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, zeroi)); + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterIuivEXT(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, zeroui)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterIivEXT(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, zeroi)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterIuivEXT(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, zeroui)); + } + + if (EnsureGLExtensionEnabled("GL_OES_texture_border_clamp")) + { + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, zeroi)); + CHECK_TEXTURE_2D_MODIFICATION( + glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, zeroui)); + + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterIivOES(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, zeroi)); + CHECK_TEXTURE_2D_ARRAY_MODIFICATION( + glTexParameterIuivOES(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, zeroui)); + } + +#undef CHECK_TEXTURE_2D_MODIFICATION +#undef CHECK_TEXTURE_2D_ARRAY_MODIFICATION + + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE})); + ASSERT_GL_NO_ERROR(); +} + +// Check that glClear with active PLS doesn't accidentally turn off draw buffers when there is no +// color attachment. +TEST_P(PixelLocalStorageValidationTest, ClearDuringPLSDoesntAffectDrawBuffers) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + + PLSTestTexture pls0(GL_RGBA8); + PLSTestTexture pls1(GL_RGBA8); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); + glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0); + + constexpr static int NUM_PLANES = 2; + int maxColorAttachmentsWith2PLSPlanes = + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - NUM_PLANES; + // The validation tests are expected to run in a configuration where the draw buffers are + // restricted by PLS (e.g., not shader images). + ASSERT(maxColorAttachmentsWith2PLSPlanes < MAX_DRAW_BUFFERS); + + int numColorAttachments = std::min(maxColorAttachmentsWith2PLSPlanes, 2); + + PLSTestTexture colorAttachment0(GL_RGBA8); + PLSTestTexture colorAttachment1(GL_RGBA8); + + for (int colorAttachmentMask = 0; colorAttachmentMask < (1 << numColorAttachments); + ++colorAttachmentMask) + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + if (numColorAttachments >= 2) { - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 1)); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, + colorAttachment1, 0); } - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); - - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - EXPECT_GL_COLOR_MASK_INDEXED(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - if (firstOverriddenDrawBuffer > 1) + if (numColorAttachments >= 1) { - EXPECT_GL_COLOR_MASK_INDEXED(1, GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colorAttachment0, 0); } - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); - glDisablei(GL_BLEND, 1); - glDisablei(GL_BLEND, highestPLSDrawBuffer); - EXPECT_TRUE(glIsEnabled(GL_BLEND)); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - if (firstOverriddenDrawBuffer > 1) + // Only enable draw buffers that are in colorAttachmentMask. + GLenum drawBuffers[2]; + for (int i = 0; i < 2; ++i) { - EXPECT_FALSE(glIsEnabledi(GL_BLEND, 1)); + drawBuffers[i] = (colorAttachmentMask & (1 << i)) ? GL_COLOR_ATTACHMENT0 + i : GL_NONE; } - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); + glDrawBuffers(2, drawBuffers); - glColorMaski(2, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); - glColorMaski(highestPLSDrawBuffer, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - EXPECT_GL_COLOR_MASK_INDEXED(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - if (firstOverriddenDrawBuffer > 2) + if (colorAttachmentMask != 0 && colorAttachmentMask != 3) { - EXPECT_GL_COLOR_MASK_INDEXED(2, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffers(2, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1})); + if (numColorAttachments >= 2) + { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + (colorAttachmentMask & 2) ? colorAttachment1.id() : 0, 0); + } + if (numColorAttachments >= 1) + { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, + (colorAttachmentMask & 1) ? colorAttachment0.id() : 0, 0); + } + + glBeginPixelLocalStorageANGLE( + NUM_PLANES, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE})); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, NUM_PLANES); + EXPECT_GL_INTEGER(GL_DRAW_BUFFER1, + numColorAttachments >= 2 ? GL_COLOR_ATTACHMENT1 : GL_NONE); + EXPECT_GL_INTEGER(GL_DRAW_BUFFER0, + numColorAttachments >= 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE); + + // Check that glClear doesn't turn off any draw buffers. We have to do this check now + // because glEndPixelLocalStorageANGLE restores them anyway. + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_INTEGER(GL_DRAW_BUFFER1, + numColorAttachments >= 2 ? GL_COLOR_ATTACHMENT1 : GL_NONE); + EXPECT_GL_INTEGER(GL_DRAW_BUFFER0, + numColorAttachments >= 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE); + + glEndPixelLocalStorageANGLE( + NUM_PLANES, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE})); + + // Make sure the draw buffers stuck after disabling PLS. + EXPECT_GL_INTEGER(GL_DRAW_BUFFER1, + numColorAttachments >= 2 ? GL_COLOR_ATTACHMENT1 : GL_NONE); + EXPECT_GL_INTEGER(GL_DRAW_BUFFER0, + numColorAttachments >= 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE); } - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); + } - endPLS(); + ASSERT_GL_NO_ERROR(); +} - EXPECT_TRUE(glIsEnabled(GL_BLEND)); - EXPECT_TRUE(glIsEnabledi(GL_BLEND, 0)); - if (firstOverriddenDrawBuffer > 1) +// Check that glReadPixels and glCopyTex*Image* end PLS before running. +TEST_P(PixelLocalStorageValidationTest, ReadPixels) +{ + PLSTestTexture tex(GL_RGBA8); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0); + int numActivePlanes = MAX_PIXEL_LOCAL_STORAGE_PLANES - 1; + for (int i = 1; i < numActivePlanes; ++i) + { + glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8); + } + + int firstOverriddenDrawBuffer = + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numActivePlanes; + // The validation tests are expected to run in a configuration where the draw buffers are + // restricted by PLS (e.g., not shader images). + ASSERT(firstOverriddenDrawBuffer < MAX_DRAW_BUFFERS); + + std::vector colorAttachments; + std::vector drawBuffers; + for (int i = 0; i < firstOverriddenDrawBuffer; ++i) + { + colorAttachments.emplace_back(GL_RGBA8); + drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i); + glFramebufferTexture2D(GL_FRAMEBUFFER, drawBuffers.back(), GL_TEXTURE_2D, + colorAttachments.back(), 0); + } + for (int i = firstOverriddenDrawBuffer; i < MAX_DRAW_BUFFERS; ++i) + { + colorAttachments.emplace_back(GL_RGBA8); + } + glDrawBuffers(firstOverriddenDrawBuffer, drawBuffers.data()); + + GLTexture tex2d; + glBindTexture(GL_TEXTURE_2D, tex2d); + + GLTexture tex3D; + glBindTexture(GL_TEXTURE_3D, tex3D); + glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, W, H, 5); + + auto beginPLS = [=]() { + glBeginPixelLocalStorageANGLE( + numActivePlanes, std::vector(numActivePlanes, GL_LOAD_OP_ZERO_ANGLE).data()); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, numActivePlanes); + }; + beginPLS(); + std::vector pixelData(H * W * 4); + + // glReadPixels can't access the overridden PLS draw buffers. + for (int i = 0; i < firstOverriddenDrawBuffer; ++i) + { + glReadBuffer(GL_COLOR_ATTACHMENT0 + i); + EXPECT_GL_NO_ERROR(); + glReadPixels(0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, W, H, 0); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, W, H); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + if (EnsureGLExtensionEnabled("GL_OES_texture_3D")) { - EXPECT_FALSE(glIsEnabledi(GL_BLEND, 1)); + beginPLS(); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } - CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED(); - - EXPECT_GL_COLOR_MASK(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - EXPECT_GL_COLOR_MASK_INDEXED(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - if (firstOverriddenDrawBuffer > 2) + beginPLS(); + } + for (int i = firstOverriddenDrawBuffer; i < MAX_DRAW_BUFFERS; ++i) + { +#define EXPECT_BLIT_FRAMEBUFFER_ERROR() \ + if (firstOverriddenDrawBuffer == 0) \ + { \ + EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); \ + EXPECT_GL_SINGLE_ERROR_MSG( \ + "Framebuffer is incomplete: No attachments and default size is zero."); \ + } \ + else \ + { \ + EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); \ + EXPECT_GL_SINGLE_ERROR_MSG("Missing read attachment."); \ + } + // PLS gets disabled even if there was an error. + glReadBuffer(GL_COLOR_ATTACHMENT0 + i); + EXPECT_GL_NO_ERROR(); + glReadPixels(0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); + EXPECT_BLIT_FRAMEBUFFER_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, W, H, 0); + EXPECT_BLIT_FRAMEBUFFER_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, W, H); + EXPECT_BLIT_FRAMEBUFFER_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_BLIT_FRAMEBUFFER_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + if (EnsureGLExtensionEnabled("GL_OES_texture_3D")) { - EXPECT_GL_COLOR_MASK_INDEXED(2, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); + beginPLS(); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_BLIT_FRAMEBUFFER_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } - CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED(); - - glDisable(GL_BLEND); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + beginPLS(); +#undef EXPECT_BLIT_FRAMEBUFFER_ERROR + } + // When a different READ_FRAMEBUFFER is bound, glReadPixels can access all the draw buffers. + GLFramebuffer readFBO; + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + for (int i = 0; i < MAX_DRAW_BUFFERS; ++i) + { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, + colorAttachments[i], 0); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glReadBuffer(GL_COLOR_ATTACHMENT0 + i); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, numActivePlanes); + glReadPixels(0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, W, H, 0); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, W, H); EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + beginPLS(); + glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + if (EnsureGLExtensionEnabled("GL_OES_texture_3D")) + { + beginPLS(); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 0, 0, 0, 2, 0, 0, W, H); + EXPECT_GL_NO_ERROR(); + EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); + } + beginPLS(); } - EXPECT_GL_NO_ERROR(); + glEndPixelLocalStorageANGLE(numActivePlanes, + std::vector(numActivePlanes, GL_DONT_CARE).data()); -#undef CHECK_OVERRIDDEN_COLOR_MASKS_INDEXED -#undef EXPECT_NON_OVERRIDDEN_COLOR_MASK -#undef CHECK_OVERRIDDEN_BLEND_MASKS_INDEXED -#undef EXPECT_NON_OVERRIDDEN_BLEND_MASK + ASSERT_GL_NO_ERROR(); } // Check that draw commands validate current PLS state against the shader's PLS uniforms. @@ -6267,7 +7968,7 @@ TEST_P(PixelLocalStorageValidationTest, LeakFramebufferAndTexture) glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 10, 10); glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); - PLSTestTexture tex1(GL_R32F); + PLSTestTexture tex1(GL_R32UI); glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0); glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8I); @@ -6295,7 +7996,7 @@ TEST_P(PixelLocalStorageValidationTest, LoseContext) glBindTexture(GL_TEXTURE_2D, tex0); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 10, 10); - PLSTestTexture tex1(GL_R32F); + PLSTestTexture tex1(GL_R32UI); glBindFramebuffer(GL_FRAMEBUFFER, fbo0); glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0); @@ -6321,11 +8022,11 @@ TEST_P(PixelLocalStorageValidationTest, LoseContext) } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageValidationTest); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageWebGLValidationTest); ANGLE_INSTANTIATE_TEST(PixelLocalStorageValidationTest, - WithRobustness(ES31_NULL()).enable(Feature::EmulatePixelLocalStorage), - WithRobustness(ES31_NULL()) - .enable(Feature::EmulatePixelLocalStorage) - .enable(Feature::DisableDrawBuffersIndexed)); + WithRobustness(ES31_NULL()).enable(Feature::EmulatePixelLocalStorage)); +ANGLE_INSTANTIATE_TEST(PixelLocalStorageWebGLValidationTest, + WithRobustness(ES31_NULL()).enable(Feature::EmulatePixelLocalStorage)); class PixelLocalStorageCompilerTest : public ANGLETest<> { @@ -6335,7 +8036,7 @@ class PixelLocalStorageCompilerTest : public ANGLETest<> protected: void testSetUp() override { - ASSERT(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); + ASSERT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage")); // INVALID_OPERATION is generated if DITHER is enabled. glDisable(GL_DITHER); @@ -6557,9 +8258,8 @@ TEST_P(PixelLocalStorageCompilerTest, LayoutQualifiers) layout(binding=4, rgba16ui) highp uniform upixelLocalANGLE pls4; layout(binding=5, rgba32i) highp uniform ipixelLocalANGLE pls5; layout(binding=6, rgba16i) highp uniform ipixelLocalANGLE pls6; - layout(binding=7, r32i) highp uniform ipixelLocalANGLE pls7; - layout(binding=999999999, rgba) highp uniform ipixelLocalANGLE pls8; - highp uniform pixelLocalANGLE pls9; + layout(binding=999999999, rgba) highp uniform ipixelLocalANGLE pls7; + highp uniform pixelLocalANGLE pls8; void main() { })"; @@ -6571,14 +8271,13 @@ TEST_P(PixelLocalStorageCompilerTest, LayoutQualifiers) EXPECT_TRUE(log.has("ERROR: 0:7: 'rgba16ui' : illegal pixel local storage format")); EXPECT_TRUE(log.has("ERROR: 0:8: 'rgba32i' : illegal pixel local storage format")); EXPECT_TRUE(log.has("ERROR: 0:9: 'rgba16i' : illegal pixel local storage format")); - EXPECT_TRUE(log.has("ERROR: 0:10: 'r32i' : illegal pixel local storage format")); - EXPECT_TRUE(log.has("ERROR: 0:11: 'rgba' : invalid layout qualifier")); + EXPECT_TRUE(log.has("ERROR: 0:10: 'rgba' : invalid layout qualifier")); EXPECT_TRUE(log.has( - "ERROR: 0:11: 'layout qualifier' : pixel local storage requires a format specifier")); + "ERROR: 0:10: 'layout qualifier' : pixel local storage requires a format specifier")); EXPECT_TRUE(log.has( - "ERROR: 0:12: 'layout qualifier' : pixel local storage requires a format specifier")); + "ERROR: 0:11: 'layout qualifier' : pixel local storage requires a format specifier")); EXPECT_TRUE( - log.has("ERROR: 0:12: 'layout qualifier' : pixel local storage requires a binding index")); + log.has("ERROR: 0:11: 'layout qualifier' : pixel local storage requires a binding index")); // PLS handles must be within MAX_PIXEL_LOCAL_STORAGE_PLANES. GLint MAX_PIXEL_LOCAL_STORAGE_PLANES; @@ -6609,6 +8308,8 @@ TEST_P(PixelLocalStorageCompilerTest, LayoutQualifiers) layout(binding=10, r32f) highp uniform upixelLocalANGLE pls10; layout(binding=11, r32ui) highp uniform pixelLocalANGLE pls11; layout(binding=12, r32ui) highp uniform ipixelLocalANGLE pls12; + layout(binding=13, r32i) highp uniform pixelLocalANGLE pls13; + layout(binding=14, r32i) highp uniform upixelLocalANGLE pls14; void main() { })"; @@ -6639,6 +8340,10 @@ TEST_P(PixelLocalStorageCompilerTest, LayoutQualifiers) log.has("ERROR: 0:14: 'r32ui' : pixel local storage format requires upixelLocalANGLE")); EXPECT_TRUE( log.has("ERROR: 0:15: 'r32ui' : pixel local storage format requires upixelLocalANGLE")); + EXPECT_TRUE( + log.has("ERROR: 0:16: 'r32i' : pixel local storage format requires ipixelLocalANGLE")); + EXPECT_TRUE( + log.has("ERROR: 0:17: 'r32i' : pixel local storage format requires ipixelLocalANGLE")); // PLS handles cannot have duplicate binding indices. constexpr char kPLSDuplicateBindings[] = R"(#version 310 es @@ -7070,12 +8775,12 @@ TEST_P(PixelLocalStorageCompilerTest, BlendFuncExtended_illegal_with_PLS) void main() {})"; EXPECT_FALSE(log.compileFragmentShader(kBlendFuncExtendedNoLocation)); - EXPECT_TRUE(log.has( - "ERROR: 0:5: 'out1' : must explicitly specify all locations when using multiple fragment " - "outputs and pixel local storage, even if EXT_blend_func_extended is enabled")); - EXPECT_TRUE(log.has( - "ERROR: 0:6: 'out0' : must explicitly specify all locations when using multiple fragment " - "outputs and pixel local storage, even if EXT_blend_func_extended is enabled")); + EXPECT_TRUE( + log.has("'out1' : must explicitly specify all locations when using multiple fragment " + "outputs and pixel local storage, even if EXT_blend_func_extended is enabled")); + EXPECT_TRUE( + log.has("'out0' : must explicitly specify all locations when using multiple fragment " + "outputs and pixel local storage, even if EXT_blend_func_extended is enabled")); // index=0 is ok. constexpr char kValidFragmentIndex0[] = R"(#version 300 es @@ -7203,10 +8908,7 @@ TEST_P(PixelLocalStorageCompilerTest, FunctionArguments) GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageCompilerTest); ANGLE_INSTANTIATE_TEST(PixelLocalStorageCompilerTest, - ES31_NULL().enable(Feature::EmulatePixelLocalStorage), - ES31_NULL() - .enable(Feature::EmulatePixelLocalStorage) - .enable(Feature::DisableDrawBuffersIndexed)); + ES31_NULL().enable(Feature::EmulatePixelLocalStorage)); class PixelLocalStorageTestPreES3 : public ANGLETest<> { @@ -7236,5 +8938,4 @@ TEST_P(PixelLocalStorageTestPreES3, UnsupportedClientVersion) GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTestPreES3); ANGLE_INSTANTIATE_TEST(PixelLocalStorageTestPreES3, - ES1_NULL().enable(Feature::EmulatePixelLocalStorage), ES2_NULL().enable(Feature::EmulatePixelLocalStorage)); diff --git a/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/tests/gl_tests/ProgramBinaryTest.cpp index b22f8d124c1..0dbb4b40117 100644 --- a/src/tests/gl_tests/ProgramBinaryTest.cpp +++ b/src/tests/gl_tests/ProgramBinaryTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include @@ -229,6 +233,82 @@ TEST_P(ProgramBinaryTest, SaveAndLoadBinaryTwice) EXPECT_GL_NO_ERROR(); } +// Test to verify that when saving a program binary twice consecutively, both the length and the +// binary match. Also verify that when loading each program binary, the quad rendered using the +// binary matches as expected. +TEST_P(ProgramBinaryTest, ReturnedBinaryTwiceShouldMatch) +{ + if (!supported()) + { + return; + } + + // Create a red program. + ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + + GLint programLength1 = 0; + GLint writtenLength1 = 0; + GLenum binaryFormat1 = GL_NONE; + + GLint programLength2 = 0; + GLint writtenLength2 = 0; + GLenum binaryFormat2 = GL_NONE; + + // Get the binary initially. + glGetProgramiv(redProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength1); + std::vector binary1(programLength1); + glGetProgramBinaryOES(redProgram, programLength1, &writtenLength1, &binaryFormat1, + binary1.data()); + EXPECT_GL_NO_ERROR(); + + // Ensure that the lengths from glGetProgramiv and glGetProgramBinaryOES match. + EXPECT_EQ(programLength1, writtenLength1); + + // Immediately get the binary again. + glGetProgramiv(redProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength2); + std::vector binary2(programLength2); + glGetProgramBinaryOES(redProgram, programLength2, &writtenLength2, &binaryFormat2, + binary2.data()); + EXPECT_GL_NO_ERROR(); + + // Ensure that the lengths from glGetProgramiv and glGetProgramBinaryOES match again. + EXPECT_EQ(programLength2, writtenLength2); + + // Verify length/binary 1 and 2 are the same. + EXPECT_EQ(programLength1, programLength2); + EXPECT_EQ(binary1, binary2); + + // Load the program binary 1. + GLuint loadedProgram = glCreateProgram(); + glProgramBinaryOES(loadedProgram, binaryFormat1, binary1.data(), writtenLength1); + EXPECT_GL_NO_ERROR(); + + // Load the program binary 2. + GLuint reloadedProgram = glCreateProgram(); + glProgramBinaryOES(reloadedProgram, binaryFormat2, binary2.data(), writtenLength2); + EXPECT_GL_NO_ERROR(); + + glUseProgram(loadedProgram); + + // Verify that the red program draws correctly for the program binary 1. + drawQuad(loadedProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_GL_NO_ERROR(); + + // Clear with black before the second iteration. + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); + EXPECT_GL_NO_ERROR(); + + glUseProgram(reloadedProgram); + + // Verify that the red program draws correctly for the program binary 2. + drawQuad(reloadedProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_GL_NO_ERROR(); +} + // Ensures that we init the compiler before calling ProgramBinary. TEST_P(ProgramBinaryTest, CallProgramBinaryBeforeLink) { @@ -1531,6 +1611,17 @@ class ProgramBinariesAcrossPlatforms : public testing::TestWithParaminitialize("ProgramBinariesAcrossRenderersTests", 100, 100); @@ -1604,8 +1695,11 @@ class ProgramBinariesAcrossPlatforms : public testing::TestWithParamdestroy(); - OSWindow::Delete(&mOSWindow); + if (mOSWindow != nullptr) + { + mOSWindow->destroy(); + OSWindow::Delete(&mOSWindow); + } } OSWindow *mOSWindow = nullptr; diff --git a/src/tests/gl_tests/ProgramInterfaceTest.cpp b/src/tests/gl_tests/ProgramInterfaceTest.cpp index 3188aac00e9..a9e9c3ce097 100644 --- a/src/tests/gl_tests/ProgramInterfaceTest.cpp +++ b/src/tests/gl_tests/ProgramInterfaceTest.cpp @@ -6,6 +6,10 @@ // ProgramInterfaceTest: Tests of program interfaces. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/string_utils.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -179,6 +183,121 @@ TEST_P(ProgramInterfaceTestES31, GetResourceName) EXPECT_EQ("oColor[", std::string(name)); } +// Tests queries for array of arrays in tessellation shader. +TEST_P(ProgramInterfaceTestES31, ArrayofArraysQueries) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader")); + + const GLchar *TCS = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout(vertices = 3) out; +in float vt[]; +out float tt[][2]; +void main() +{ + gl_TessLevelOuter[0] = 3.0; + gl_TessLevelOuter[1] = 3.0; + gl_TessLevelOuter[2] = 3.0; + gl_TessLevelInner[0] = 7.0; + gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; + tt[gl_InvocationID][1] = vt[gl_InvocationID]; +})"; + + const GLchar *TES = R"(#version 310 es +#extension GL_EXT_tessellation_shader : require +layout(triangles, fractional_even_spacing, ccw) in; +in float tt[][2]; +out float tg[2]; +void main() +{ + gl_Position.xyzw = gl_in[0].gl_Position.xyzw * gl_TessCoord.x + + gl_in[1].gl_Position.xyzw * gl_TessCoord.y + + gl_in[2].gl_Position.xyzw * gl_TessCoord.z; + tg[1] = tt[0][1]; +})"; + + // Create shader and init program. + GLuint programTCS, programTES; + programTCS = glCreateShaderProgramv(GL_TESS_CONTROL_SHADER, 1, &TCS); + ASSERT_NE(programTCS, 0u); + GLint linked = GL_FALSE; + glGetProgramiv(programTCS, GL_LINK_STATUS, &linked); + ASSERT_GL_TRUE(linked); + programTES = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &TES); + ASSERT_NE(programTES, 0u); + glGetProgramiv(programTES, GL_LINK_STATUS, &linked); + ASSERT_GL_TRUE(linked); + + // Program interfaces to query for resources. + constexpr uint32_t kInterfaceCount = 2; + struct InterfaceProperties + { + uint32_t programIndex; + GLenum iface; + const GLchar *resourceName; + }; + InterfaceProperties kInterfaceProps[kInterfaceCount] = { + {programTCS, GL_PROGRAM_OUTPUT, "tt[0][0]"}, {programTES, GL_PROGRAM_INPUT, "tt[0][0]"}}; + + // Table of queries to perform on resource. + constexpr GLsizei kPropCount = 3; + constexpr GLenum kResourceProps[kPropCount] = {GL_NAME_LENGTH, GL_TYPE, GL_ARRAY_SIZE}; + constexpr GLsizei kBufferSize = 150; + + // Buffer for results of resource queries. + GLint resourceResults[3] = {0}; + + // Test: Check each interface by querying for resources. + for (uint32_t i = 0; i < kPropCount; ++i) + { + GLint numActiveResources = 0; + GLchar name[64]; + GLuint program = kInterfaceProps[i].programIndex; + GLenum programInterface = kInterfaceProps[i].iface; + bool resourceFound = false; + + // Get the number of active resources for the given interface. Should be bigger than zero. + glGetProgramInterfaceiv(program, programInterface, GL_ACTIVE_RESOURCES, + &numActiveResources); + EXPECT_GL_NO_ERROR(); + ASSERT_NE(0, numActiveResources); + + for (GLuint resourceIndex = 0; resourceIndex < (GLuint)numActiveResources; ++resourceIndex) + { + GLsizei nameLength = 0; + GLint queryResourceIndex = 0; + + glGetProgramResourceName(program, programInterface, resourceIndex, sizeof(name), + &nameLength, name); + EXPECT_GL_NO_ERROR(); + ASSERT_NE(0, nameLength); + + // Cross-reference the name back to the resource index. + queryResourceIndex = (GLint)glGetProgramResourceIndex(program, programInterface, name); + EXPECT_GL_NO_ERROR(); + ASSERT_EQ((GLuint)queryResourceIndex, resourceIndex); + + if (strcmp(name, kInterfaceProps[i].resourceName) == 0) + { + GLsizei length = 0; + glGetProgramResourceiv(program, programInterface, resourceIndex, kPropCount, + kResourceProps, kBufferSize, &length, resourceResults); + EXPECT_GL_NO_ERROR(); + ASSERT_NE(0, length); + + // Validate queried resource properties. + ASSERT_EQ(strlen(kInterfaceProps[i].resourceName) + 1, (GLuint)resourceResults[0]); + ASSERT_EQ(GL_FLOAT, resourceResults[1]); + ASSERT_EQ(2, resourceResults[2]); + + resourceFound = true; + } + } + + ASSERT_TRUE(resourceFound); + } +} + // Tests glGetProgramResourceLocation. TEST_P(ProgramInterfaceTestES31, GetResourceLocation) { diff --git a/src/tests/gl_tests/ProgramParameterTest.cpp b/src/tests/gl_tests/ProgramParameterTest.cpp index 9a8f18df02d..2e3da315c0a 100644 --- a/src/tests/gl_tests/ProgramParameterTest.cpp +++ b/src/tests/gl_tests/ProgramParameterTest.cpp @@ -70,6 +70,38 @@ TEST_P(ProgramParameterTestES31, ValidateParameters) glDeleteProgram(program); } +// Get GL_PROGRAM_BINARY_RETRIEVABLE_HINT before glLinkProgram to +// make sure it gets the correct in effect value. +TEST_P(ProgramParameterTest, DelayRetrievableHint) +{ + GLuint program = glCreateProgram(); + ASSERT_NE(program, 0u); + + GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple()); + GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Red()); + ASSERT_NE(0u, vertexShader); + ASSERT_NE(0u, fragmentShader); + + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + + glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + glLinkProgram(program); + + GLint params; + glGetProgramiv(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, ¶ms); + ASSERT_EQ(1, params); + + // False is not in effect before glLinkProgram. + glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_FALSE); + glGetProgramiv(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, ¶ms); + ASSERT_EQ(1, params); + + glLinkProgram(program); + glGetProgramiv(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, ¶ms); + ASSERT_EQ(0, params); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProgramParameterTest); ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(ProgramParameterTest); diff --git a/src/tests/gl_tests/ProgramPipelineTest.cpp b/src/tests/gl_tests/ProgramPipelineTest.cpp index e75efa8675c..014e44eeccb 100644 --- a/src/tests/gl_tests/ProgramPipelineTest.cpp +++ b/src/tests/gl_tests/ProgramPipelineTest.cpp @@ -7,6 +7,10 @@ // Various tests related to Program Pipeline. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -2302,6 +2306,50 @@ void main() EXPECT_GL_NO_ERROR(); } +// Test that GetProgramPipelineivf works. +TEST_P(ProgramPipelineTest31, ProgramPipelineivTest) +{ + GLuint pipeline; + GLint log_length = -1; + glGenProgramPipelines(1, &pipeline); + glGetProgramPipelineiv(pipeline, GL_INFO_LOG_LENGTH, &log_length); + glGetProgramPipelineInfoLog(pipeline, 0, NULL, NULL); + EXPECT_GL_NO_ERROR(); + glDeleteProgramPipelines(1, &pipeline); + EXPECT_GL_NO_ERROR(); +} + +// Test that shader interface matching does not accidentally match by name +// when location is specified in separable programs. +TEST_P(ProgramPipelineTest31, ShaderInterfaceMatchingTest) +{ + ANGLE_SKIP_TEST_IF(!IsVulkan()); + + const GLchar *vertString = R"(#version 310 es +precision highp float; +in vec4 a_position; +layout(location = 0) flat out uvec3 u3; +layout(location = 1) out float f[2]; +void main() +{ + gl_Position = a_position; +})"; + + const GLchar *fragString = R"(#version 310 es +precision highp float; +layout(location = 0) flat in uvec3 f; +layout(location = 1) in float u3[2]; +out vec4 my_FragColor; +void main() +{ + my_FragColor = vec4(1.0, 1.0, 0.0, 1.0); +})"; + bindProgramPipeline(vertString, fragString); + + drawQuadWithPPO("a_position", 0.5f, 1.0f); + ASSERT_GL_NO_ERROR(); +} + class ProgramPipelineTest32 : public ProgramPipelineTest { protected: diff --git a/src/tests/gl_tests/ProvokingVertexTest.cpp b/src/tests/gl_tests/ProvokingVertexTest.cpp index 739499b04e2..59b9128d1bb 100644 --- a/src/tests/gl_tests/ProvokingVertexTest.cpp +++ b/src/tests/gl_tests/ProvokingVertexTest.cpp @@ -9,6 +9,10 @@ // in the ES 3 specs. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLES2/gl2.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -742,13 +746,9 @@ TEST_P(ProvokingVertexBufferUpdateTest, DrawFlatWithPartialBufferSubUpdatesBetwe } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProvokingVertexTest); -ANGLE_INSTANTIATE_TEST(ProvokingVertexTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_METAL()); +ANGLE_INSTANTIATE_TEST_ES3(ProvokingVertexTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProvokingVertexBufferUpdateTest); -ANGLE_INSTANTIATE_TEST(ProvokingVertexBufferUpdateTest, - ES3_D3D11(), - ES3_OPENGL(), - ES3_OPENGLES(), - ES3_METAL()); +ANGLE_INSTANTIATE_TEST_ES3(ProvokingVertexBufferUpdateTest); } // anonymous namespace diff --git a/src/tests/gl_tests/ReadPixelsTest.cpp b/src/tests/gl_tests/ReadPixelsTest.cpp index 77d536de925..3cf1179bd78 100644 --- a/src/tests/gl_tests/ReadPixelsTest.cpp +++ b/src/tests/gl_tests/ReadPixelsTest.cpp @@ -7,6 +7,10 @@ // Tests calls related to glReadPixels. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include @@ -1552,6 +1556,31 @@ TEST_P(ReadPixelsErrorTest, ColorBufferSnorm16) {GL_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT}); } +// The test verifies that glReadnPixels* generates a GL_INVALID_OPERATION error if +// the buffer size required to store the requested data is greater than bufSize if +// PBO is bound. +TEST_P(ReadPixelsErrorTest, PBOBufSizeTest) +{ + GLuint PBO; + glGenBuffers(1, &PBO); + glBindBuffer(GL_PIXEL_PACK_BUFFER, PBO); + glBufferData(GL_PIXEL_PACK_BUFFER, 4, nullptr, GL_STATIC_DRAW); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + + if (IsGLExtensionEnabled("GL_KHR_robustness")) + { + glReadnPixelsKHR(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 2, 0); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } + if (IsGLExtensionEnabled("GL_EXT_robustness")) + { + glReadnPixelsEXT(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 2, 0); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } + + glDeleteBuffers(1, &PBO); +} + // texture internal format is GL_RGBA32F class ReadPixelsFloat32TypePBOTest : public ReadPixelsPBOTest { diff --git a/src/tests/gl_tests/RenderbufferMultisampleTest.cpp b/src/tests/gl_tests/RenderbufferMultisampleTest.cpp index bbaa8fc81c3..fe41f292565 100644 --- a/src/tests/gl_tests/RenderbufferMultisampleTest.cpp +++ b/src/tests/gl_tests/RenderbufferMultisampleTest.cpp @@ -140,33 +140,27 @@ TEST_P(RenderbufferMultisampleTest, OddSampleCount) TEST_P(RenderbufferMultisampleTestES31, ColorBurnBlend) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); - // Create shader programs - std::stringstream vs; - vs << "#version 310 es\n" - "in highp vec4 a_position;\n" - "in mediump vec4 a_color;\n" - "out mediump vec4 v_color;\n" - "void main()\n" - "{\n" - "gl_Position = a_position;\n" - "v_color = a_color;\n" - "}\n"; - - std::stringstream fs; - - fs << "#version 310 es\n" - "#extension GL_KHR_blend_equation_advanced : require\n" - "in mediump vec4 v_color;\n" - "layout (blend_support_colorburn) out;\n" - "layout (location = 0) out mediump vec4 o_color;\n" - "void main()\n" - "{\n" - "o_color = v_color;\n" - "}\n"; - - GLuint program; - - program = CompileProgram(vs.str().c_str(), fs.str().c_str()); + constexpr char kVS[] = R"(#version 310 es +in highp vec4 a_position; +in mediump vec4 a_color; +out mediump vec4 v_color; +void main() +{ +gl_Position = a_position; +v_color = a_color; +})"; + + constexpr char kFS[] = R"(#version 310 es +#extension GL_KHR_blend_equation_advanced : require +in mediump vec4 v_color; +layout (blend_support_colorburn) out; +layout (location = 0) out mediump vec4 o_color; +void main() +{ +o_color = v_color; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); // Create vertex data and buffers // Create vertex position data @@ -203,23 +197,19 @@ TEST_P(RenderbufferMultisampleTestES31, ColorBurnBlend) glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0); // Create a multisampled render buffer and attach it to frame buffer color attachment - GLuint rbo; - glGenRenderbuffers(1, &rbo); + GLRenderbuffer rbo; glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, getWindowWidth(), getWindowHeight()); - GLuint fbo = 0; - glGenFramebuffers(1, &fbo); + GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); // Create a singlesampled render buffer and attach it to frame buffer color attachment - GLuint resolvedRbo; - glGenRenderbuffers(1, &resolvedRbo); + GLRenderbuffer resolvedRbo; glBindRenderbuffer(GL_RENDERBUFFER, resolvedRbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight()); - GLuint resolvedFbo = 0; - glGenFramebuffers(1, &resolvedFbo); + GLFramebuffer resolvedFbo; glBindFramebuffer(GL_FRAMEBUFFER, resolvedFbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, resolvedRbo); @@ -243,13 +233,6 @@ TEST_P(RenderbufferMultisampleTestES31, ColorBurnBlend) glBindFramebuffer(GL_READ_FRAMEBUFFER, resolvedFbo); EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::red); // Validation error - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glDeleteProgram(program); - glDeleteFramebuffers(1, &fbo); - glDeleteRenderbuffers(1, &rbo); - glDeleteFramebuffers(1, &resolvedFbo); - glDeleteRenderbuffers(1, &resolvedRbo); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RenderbufferMultisampleTest); diff --git a/src/tests/gl_tests/RendererTest.cpp b/src/tests/gl_tests/RendererTest.cpp index 9c97e4ed62c..ac741144524 100644 --- a/src/tests/gl_tests/RendererTest.cpp +++ b/src/tests/gl_tests/RendererTest.cpp @@ -9,6 +9,7 @@ // configured incorrectly. For example, they might be using the D3D11 renderer when the test is // meant to be using the D3D9 renderer. +#include #include "common/string_utils.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -130,8 +131,27 @@ TEST_P(RendererTest, RequestedRendererCreated) ASSERT_TRUE(IsVulkan()); } - EGLint glesMajorVersion = GetParam().majorVersion; - EGLint glesMinorVersion = GetParam().minorVersion; + // EGL_ANGLE_create_context_backwards_compatible is required to guarantee the expected context + // version. + EGLint glesMajorVersion; + EGLint glesMinorVersion; + EGLWindow *window = getEGLWindow(); + EGLDisplay display = window->getDisplay(); + if (IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_create_context_backwards_compatible")) + { + // If the extension is available, verify the requested version matches the returned version. + glesMajorVersion = GetParam().majorVersion; + glesMinorVersion = GetParam().minorVersion; + } + else + { + // Otherwise, get the created context's (maximally conformant) version. + glesMajorVersion = getClientMajorVersion(); + glesMinorVersion = getClientMinorVersion(); + // Verify that the returned version is >= the requested version. + ASSERT_GE(glesMajorVersion, GetParam().majorVersion); + ASSERT_GE(glesMinorVersion, GetParam().minorVersion); + } std::ostringstream expectedVersionString; expectedVersionString << "es " << glesMajorVersion << "." << glesMinorVersion; @@ -212,10 +232,49 @@ TEST_P(RendererTest, Draw) glDrawArrays(GL_TRIANGLES, 0, 3); } +// This test validates that the GL_RENDERER string reported by ANGLE adheres to the +// canonical format: "ANGLE (Vendor, Renderer, Version)". +// This format is a de-facto API contract relied upon by upstream clients like Skia +// to enable workarounds and optimizations. +TEST_P(RendererTest, ValidateCanonicalFormat) +{ + // Use the idiomatic IsNULL() check to skip this test on the Null backend. + if (IsNULL()) + { + std::cout << "Skipping canonical format validation for the Null backend." << std::endl; + return; + } + + // 1. Query the renderer string from the driver. + const char *rendererCStr = reinterpret_cast(glGetString(GL_RENDERER)); + ASSERT_NE(rendererCStr, nullptr); + std::string rendererStr(rendererCStr); + std::cout << "Renderer string: \"" << rendererStr << "\"" << std::endl; + + // 2. Validate the entire string structure using a single regular expression. + // This regex enforces the "ANGLE (...)" wrapper and the presence of three + // comma-space-separated components, while allowing components to be empty. + const std::regex kRendererFormat("^ANGLE \\((.*), (.*), (.*)\\)$"); + std::smatch match; + + bool matches = std::regex_match(rendererStr, match, kRendererFormat); + + // 3. Assert that the string matches the format and contains the correct number of groups. + // match[0] is the full string, match[1-3] are the captured components. + ASSERT_TRUE(matches && match.size() == 4) + << "Renderer string does not match the expected format 'ANGLE (Vendor, Renderer, Version)'." + << "\n Actual string: " << rendererStr; + + // 4. For clarity in test logs, print the parsed components. + std::cout << "Successfully parsed renderer string components:" << std::endl; + std::cout << " - Vendor: \"" << match[1].str() << "\"" << std::endl; + std::cout << " - Renderer: \"" << match[2].str() << "\"" << std::endl; + std::cout << " - Version: \"" << match[3].str() << "\"" << std::endl; + + EXPECT_GL_NO_ERROR(); +} + // Select configurations (e.g. which renderer, which GLES major version) these tests should be run // against. -// TODO(http://anglebug.com/42266907): move ES2_WEBGPU to the definition of -// ANGLE_ALL_TEST_PLATFORMS_ES2 once webgpu is developed enough to run more tests. -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL_AND(RendererTest, - ES2_WEBGPU()); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL(RendererTest); } // namespace angle diff --git a/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp b/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp index 2268444719f..fcae00f2b11 100644 --- a/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp +++ b/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp @@ -45,7 +45,13 @@ class RobustBufferAccessBehaviorTest : public ANGLETest<> } setWindowVisible(mOSWindow, true); - Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(GLESDriverType::AngleEGL); + Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(getDriverType()); + + if (!driverLib) + { + std::cout << "Error: Failed to load driver library!"; + return false; + } const PlatformParameters ¶ms = GetParam(); mEGLWindow = EGLWindow::New(params.majorVersion, params.minorVersion); @@ -236,14 +242,14 @@ TEST_P(RobustBufferAccessBehaviorTest, D3D11StateSynchronizationOrderBug) glBindBuffer(GL_ARRAY_BUFFER, vb); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW); - const std::array indicies{ + const std::array indices{ 0, 1, 2, 0, 2, 3, // quad0 4, 5, 6, 4, 6, 7, // quad1 }; GLBuffer ib; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies.data(), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW); constexpr char kVS[] = R"( precision highp float; @@ -294,6 +300,104 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Tests that the test draws correctly after a larger size has been copied to the array buffer from +// another location of the same source data. +TEST_P(RobustBufferAccessBehaviorTest, ChangeBufferDataSizeWithSameAttribPointer) +{ + ANGLE_SKIP_TEST_IF(!initExtension()); + constexpr size_t kWindowWidth = 128; + constexpr size_t kWindowHeight = 128; + glViewport(0, 0, kWindowWidth, kWindowHeight); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + constexpr char kVS[] = R"(#version 300 es +in highp vec2 a_position; +in mediump vec3 a_color; +out mediump vec3 v_color; +void main() +{ + gl_Position = vec4(a_position, 0.0, 1.0); + v_color = a_color; +})"; + constexpr char kFS[] = R"(#version 300 es +in mediump vec3 v_color; +layout(location = 0) out mediump vec4 o_color; +void main() +{ + o_color = vec4(v_color, 1.0); +})"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + + GLVertexArray vao; + glBindVertexArray(vao); + + const std::array vertices{ + angle::Vector2(-1.0f, 1.0f), angle::Vector2(-1.0f, -1.0f), angle::Vector2(1.0f, -1.0f), + angle::Vector2(1.0f, 1.0f), angle::Vector2(-0.5f, 0.5f), angle::Vector2(-0.5f, -0.5f), + angle::Vector2(0.5f, -0.5f), angle::Vector2(0.5f, 0.5f), + }; + + GLBuffer positionBuffer; + glBindBuffer(GL_ARRAY_BUFFER, positionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW); + + const std::array indices{ + 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, + }; + + GLint locPos = glGetAttribLocation(program, "a_position"); + glEnableVertexAttribArray(locPos); + glVertexAttribPointer(locPos, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + + GLBuffer indexBuffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW); + + const std::array colors{ + angle::Vector3(1.0f, 0.0f, 0.0f), angle::Vector3(1.0f, 0.0f, 0.0f), + angle::Vector3(1.0f, 0.0f, 0.0f), angle::Vector3(1.0f, 0.0f, 0.0f), + + angle::Vector3(1.0f, 0.0f, 0.0f), angle::Vector3(1.0f, 0.0f, 0.0f), + angle::Vector3(1.0f, 0.0f, 0.0f), angle::Vector3(1.0f, 0.0f, 0.0f), + + angle::Vector3(1.0f, 0.0f, 0.0f), angle::Vector3(1.0f, 0.0f, 0.0f), + angle::Vector3(1.0f, 0.0f, 0.0f), angle::Vector3(1.0f, 0.0f, 0.0f), + + angle::Vector3(0.0f, 1.0f, 0.0f), angle::Vector3(0.0f, 1.0f, 0.0f), + angle::Vector3(0.0f, 1.0f, 0.0f), angle::Vector3(0.0f, 1.0f, 0.0f), + }; + + GLBuffer colorBuffer; + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(angle::Vector3) * 4, &colors[0], GL_STREAM_DRAW); + + GLint locColor = glGetAttribLocation(program, "a_color"); + glEnableVertexAttribArray(locColor); + glVertexAttribPointer(locColor, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth, kWindowHeight, GLColor::red); + glBindVertexArray(0); + + // Copy a larger amount of data to the same buffer containing the colors from another location + // while using the same args for the vertex attribute pointer. The larger draw should be able to + // use the new data copied into the bound buffer. + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(angle::Vector3) * 8, &colors[8], GL_STREAM_DRAW); + glBindVertexArray(vao); + glEnableVertexAttribArray(locColor); + glVertexAttribPointer(locColor, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, nullptr); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth, kWindowHeight / 4, GLColor::red); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 4, kWindowHeight, GLColor::red); + EXPECT_PIXEL_RECT_EQ(0, 3 * kWindowHeight / 4, kWindowWidth, kWindowHeight / 4, GLColor::red); + EXPECT_PIXEL_RECT_EQ(3 * kWindowWidth / 4, 0, kWindowWidth / 4, kWindowHeight, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 4, kWindowHeight / 4, kWindowWidth / 2, kWindowHeight / 2, + GLColor::green); +} + // Covers drawing with a very large vertex range which overflows GLsizei. http://crbug.com/842028 TEST_P(RobustBufferAccessBehaviorTest, VeryLargeVertexCountWithDynamicVertexData) { @@ -1030,6 +1134,102 @@ TEST_P(RobustBufferAccessBehaviorTest, OutOfBoundsIndexBuffers) DrawAndVerifyOutOfBoundsIndex(/*StartIndex*/ numberOfQuads - 4); } +// DrawArray with both color and position attribute data interleaved in the same buffer. +TEST_P(RobustBufferAccessBehaviorTest, DrawArraysWithInterleavedAttributeData) +{ + ANGLE_SKIP_TEST_IF(!initExtension()); + + constexpr char vert[] = + "attribute vec2 v_position;\n" + "attribute vec4 a_color;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_Position = vec4(v_position, 0.0, 1.0);\n" + " v_color = a_color;\n" + "}\n"; + + constexpr char frag[] = + "precision mediump float;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_FragColor = v_color;\n" + "}\n"; + + ANGLE_GL_PROGRAM(prog, vert, frag); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw a red quad covering the whole screen. On Xclipse devices this is + // rendered as if the final vertex is transparent black rather than red. + std::array, 6> vertices = {{{{-1.0f, 1.0f}, kFloatRed}, + {{-1.0f, -1.0f}, kFloatRed}, + {{1.0f, -1.0f}, kFloatRed}, + {{-1.0f, 1.0f}, kFloatRed}, + {{1.0f, -1.0f}, kFloatRed}, + {{1.0f, 1.0f}, kFloatRed}}}; + + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(), + GL_STATIC_DRAW); + glUseProgram(prog); + const GLint positionLocation = glGetAttribLocation(prog, "v_position"); + ASSERT_NE(-1, positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), 0); + glEnableVertexAttribArray(positionLocation); + const GLint colorLocation = glGetAttribLocation(prog, "a_color"); + ASSERT_NE(-1, colorLocation); + glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), + reinterpret_cast(sizeof(Vector2))); + glEnableVertexAttribArray(colorLocation); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red); + EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red); + EXPECT_GL_NO_ERROR(); +} + +// Test dynamic buffer crash when context created with robust buffer access enabled +TEST_P(RobustBufferAccessBehaviorTest, DynamicBufferCrash) +{ + ANGLE_SKIP_TEST_IF(!initExtension()); + + constexpr char kVS[] = R"( +attribute vec4 position; +attribute vec2 texCoord; +varying vec2 v_texCoord; +void main(void) { + v_texCoord = texCoord; +})"; + + constexpr char kFS[] = R"(precision mediump float; +varying vec2 v_texCoord; +uniform vec4 colorMult; +uniform sampler2D colorMap; +void main(void) { + gl_FragColor = texture2D(colorMap, v_texCoord) * colorMult; +})"; + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glLinkProgram(program); + ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true)); + glUseProgram(program); + + GLBuffer buffer; + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0); + glVertexAttribDivisor(0, 65537); + glDrawArraysInstanced(GL_TRIANGLE_FAN, 0x4141, 65, 536870912); + // Either no error or invalid operation is okay, but test should not crash or hang. + GLenum glError = glGetError(); + ASSERT_EQ(true, glError == GL_NO_ERROR || glError == GL_OUT_OF_MEMORY); +} + ANGLE_INSTANTIATE_TEST(RobustBufferAccessBehaviorTest, WithNoFixture(ES3_VULKAN()), WithNoFixture(ES3_OPENGL()), diff --git a/src/tests/gl_tests/RobustClientMemoryTest.cpp b/src/tests/gl_tests/RobustClientMemoryTest.cpp index 988672459ca..740cf342403 100644 --- a/src/tests/gl_tests/RobustClientMemoryTest.cpp +++ b/src/tests/gl_tests/RobustClientMemoryTest.cpp @@ -27,26 +27,12 @@ class RobustClientMemoryTest : public ANGLETest<> setConfigBlueBits(8); setConfigAlphaBits(8); } - - bool extensionsPresent() const - { - if (!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")) - { - std::cout << "Test skipped because GL_ANGLE_robust_client_memory is not available."; - return false; - } - - return true; - } }; // Test basic usage and validation of glGetIntegervRobustANGLE TEST_P(RobustClientMemoryTest, GetInteger) { - if (!extensionsPresent()) - { - return; - } + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")); // Verify that the robust and regular entry points return the same values GLint resultRobust; @@ -100,13 +86,33 @@ TEST_P(RobustClientMemoryTest, GetInteger) EXPECT_GL_NO_ERROR(); } +// Test basic usage and validation of glGetInteger64vRobustANGLE +TEST_P(RobustClientMemoryTest, GetInteger64) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")); + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); + + constexpr GLint64 kMinRequiredMaxElementIndex = 16777215; + + // Verify that the regular and robust entry points return the same values + GLint64 resultRegular; + glGetInteger64v(GL_MAX_ELEMENT_INDEX, &resultRegular); + ASSERT_GL_NO_ERROR(); + ASSERT_GE(resultRegular, kMinRequiredMaxElementIndex); + + GLsizei length; + GLint64 resultRobust; + glGetInteger64vRobustANGLE(GL_MAX_ELEMENT_INDEX, 1, &length, &resultRobust); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(1, length); + EXPECT_EQ(resultRegular, resultRobust); +} + // Test basic usage and validation of glTexImage2DRobustANGLE and glTexSubImage2DRobustANGLE TEST_P(RobustClientMemoryTest, TexImage2D) { - if (!extensionsPresent()) - { - return; - } + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")); + GLTexture tex; glBindTexture(GL_TEXTURE_2D, tex); @@ -146,13 +152,68 @@ TEST_P(RobustClientMemoryTest, TexImage2D) } } -// Test basic usage and validation of glReadPixelsRobustANGLE -TEST_P(RobustClientMemoryTest, ReadPixels) +// Test basic usage and validation of glCompressedTexImage2DRobustANGLE +// and glCompressedTexSubImage2DRobustANGLE +TEST_P(RobustClientMemoryTest, CompressedTexImage2D) { - if (!extensionsPresent()) + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")); + + // Either ETC1 or BC1 should be supported everywhere + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1") && + !IsGLExtensionEnabled("GL_OES_compressed_ETC1_RGB8_texture")); + + const GLenum format = IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1") + ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + : GL_ETC1_RGB8_OES; + + // Both ETC1 and BC1 use 4x4 blocks of 8 bytes + constexpr GLint smallDimension = 4; + std::array smallData; + + constexpr GLint largeDimension = 1024; + constexpr GLint largeSize = 1024 * 1024 / 2; + + // Test the regular case + { + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glCompressedTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, format, smallDimension, smallDimension, + 0, smallData.size(), smallData.size(), smallData.data()); + EXPECT_GL_NO_ERROR(); + + glCompressedTexSubImage2DRobustANGLE(GL_TEXTURE_2D, 0, 0, 0, smallDimension, smallDimension, + format, smallData.size(), smallData.size(), + smallData.data()); + EXPECT_GL_NO_ERROR(); + } + + // Test creating a large texture with small data size + { + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glCompressedTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, format, largeDimension, largeDimension, + 0, largeSize, smallData.size(), smallData.data()); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } + + // Test updating a large texture with small data size { - return; + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, largeDimension, largeDimension, 0, + largeSize, nullptr); + ASSERT_GL_NO_ERROR(); + + glCompressedTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, format, largeDimension, largeDimension, + 0, largeSize, smallData.size(), smallData.data()); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); } +} + +// Test basic usage and validation of glReadPixelsRobustANGLE +TEST_P(RobustClientMemoryTest, ReadPixels) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory")); // TODO(ynovikov): Looks like a driver bug on Intel HD 530 http://anglebug.com/42260689 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsDesktopOpenGL()); @@ -198,8 +259,75 @@ TEST_P(RobustClientMemoryTest, ReadPixels) } } +class RobustClientMemoryNoExtensionsTest : public RobustClientMemoryTest +{ + protected: + RobustClientMemoryNoExtensionsTest() : RobustClientMemoryTest() { setExtensionsEnabled(false); } +}; + +// Test with empty result +TEST_P(RobustClientMemoryNoExtensionsTest, GetEmpty) +{ + GLint numFormats = 10; + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(numFormats, 0); // Must be zero on unextended OpenGL ES 2.0 + + GLsizei length = 1; + std::vector resultBuf(2, 3); + + // Test non-robust with empty response + { + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, resultBuf.data()); + EXPECT_GL_NO_ERROR(); + + // Must not touch the buffer + EXPECT_TRUE(std::all_of(resultBuf.begin(), resultBuf.end(), + [](GLint value) { return value == 3; })); + } + + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_robust_client_memory")); + + // Test robust with empty response + { + glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS, resultBuf.size(), &length, + resultBuf.data()); + EXPECT_GL_NO_ERROR(); + + // Must update length + EXPECT_EQ(length, 0); + + // Must not touch the buffer + EXPECT_TRUE(std::all_of(resultBuf.begin(), resultBuf.end(), + [](GLint value) { return value == 3; })); + } + + // Test robust with empty response and null length + { + glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS, resultBuf.size(), nullptr, + resultBuf.data()); + EXPECT_GL_NO_ERROR(); + + // Must not touch the buffer + EXPECT_TRUE(std::all_of(resultBuf.begin(), resultBuf.end(), + [](GLint value) { return value == 3; })); + } + + // Test robust with empty response, zero buffer size, and null length + { + glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS, 0, nullptr, resultBuf.data()); + EXPECT_GL_NO_ERROR(); + + // Must not touch the buffer + EXPECT_TRUE(std::all_of(resultBuf.begin(), resultBuf.end(), + [](GLint value) { return value == 3; })); + } +} + // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(RobustClientMemoryTest); +ANGLE_INSTANTIATE_TEST_ES2(RobustClientMemoryNoExtensionsTest); + } // namespace angle diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp index 7452b1e5657..5beb889e3d6 100644 --- a/src/tests/gl_tests/RobustResourceInitTest.cpp +++ b/src/tests/gl_tests/RobustResourceInitTest.cpp @@ -5,6 +5,10 @@ // // RobustResourceInitTest: Tests for GL_ANGLE_robust_resource_initialization. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -662,6 +666,36 @@ TEST_P(RobustResourceInitTest, ReadingUninitializedTexture) EXPECT_GL_NO_ERROR(); } +// Calling invalidate then draw should work. Regression test for a bug where the robust init's +// clear was applied after the draw call. +TEST_P(RobustResourceInitTestES3, InvalidateThenDraw) +{ + ANGLE_SKIP_TEST_IF(!hasGLExtension()); + + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Invalidate first + std::array attachments = {GL_COLOR_ATTACHMENT0}; + glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data()); + + // Draw over the entire image + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f); + + // Read back, ensure the draw call succeeded + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + EXPECT_GL_NO_ERROR(); +} + // Test that calling glTexImage2D multiple times with the same size and no data resets all texture // data TEST_P(RobustResourceInitTest, ReuploadingClearsTexture) @@ -751,7 +785,7 @@ TEST_P(RobustResourceInitTestES3, CopyTexSubImage3DTextureWronglyInitialized) GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2D, 0); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); GLTexture texture3D; glBindTexture(GL_TEXTURE_3D, texture3D); @@ -1055,7 +1089,7 @@ TEST_P(RobustResourceInitTestES3, MultisampledDepthInitializedCorrectly) glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); glClearColor(0, 1, 0, 1); glClearDepthf(0); @@ -1071,7 +1105,7 @@ TEST_P(RobustResourceInitTestES3, MultisampledDepthInitializedCorrectly) GLFramebuffer msFBO; glBindFramebuffer(GL_READ_FRAMEBUFFER, msFBO); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msDepth); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); // Multisample resolve. glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT, @@ -1464,7 +1498,7 @@ TEST_P(RobustResourceInitTestES3, BlitFramebufferOutOfBounds) glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_draw, 0); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); using Region = std::array; @@ -1549,7 +1583,7 @@ void RobustResourceInitTest::maskedDepthClear(ClearFunc clearFunc) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Disable depth writes and trigger a clear. glDepthMask(GL_FALSE); @@ -1631,7 +1665,7 @@ void RobustResourceInitTest::maskedStencilClear(ClearFunc clearFunc) stencilbuffer); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Disable stencil writes and trigger a clear. Use a tricky mask that does not overlap the // clear. @@ -1737,7 +1771,7 @@ TEST_P(RobustResourceInitTest, CopyTexSubImage2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexture, 0); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Create uninitialized destination texture. GLTexture destTexture; @@ -1857,7 +1891,7 @@ TEST_P(RobustResourceInitTestES3, CopyTexSubImage3D) glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 0); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Create uninitialized destination texture. glBindTexture(GL_TEXTURE_3D, destTexture); @@ -1885,7 +1919,7 @@ TEST_P(RobustResourceInitTestES3, CopyTexSubImage3D) glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 0); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Fill destination texture with red. glBindTexture(GL_TEXTURE_3D, destTexture); @@ -1961,7 +1995,7 @@ TEST_P(RobustResourceInitTestES3, CompressedSubImage) GLFramebuffer framebuffer; glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); glViewport(0, 0, width, height); @@ -2080,7 +2114,7 @@ TEST_P(RobustResourceInitTest, ClearWithScissor) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer); ASSERT_GL_NO_ERROR(); - ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); // Scissor to half the width. glEnable(GL_SCISSOR_TEST); diff --git a/src/tests/gl_tests/SRGBTextureTest.cpp b/src/tests/gl_tests/SRGBTextureTest.cpp index 203ea974134..4cb9ccf49ee 100644 --- a/src/tests/gl_tests/SRGBTextureTest.cpp +++ b/src/tests/gl_tests/SRGBTextureTest.cpp @@ -275,6 +275,39 @@ TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter) EXPECT_PIXEL_COLOR_NEAR(0, 0, decodedToLinearColor, 1.0); } +// Test that GL_SKIP_DECODE_EXT makes glGenerateMipmap skip sRGB conversion +TEST_P(SRGBTextureTestES3, SRGBSkipEncodeAndDecodeInGenerateMipmap) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_sRGB_decode")); + + constexpr angle::GLColor srgbColor(21, 30, 39, 24); + constexpr angle::GLColor linearColor(12, 16, 20, 24); + static const GLubyte input[4][4] = {{48, 64, 80, 96}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}; + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, input); + ASSERT_GL_NO_ERROR(); + + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + + glUseProgram(mProgram); + glUniform1i(mTextureLocation, 0); + + glViewport(0, 0, 1, 1); + + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0); + + glGenerateMipmap(GL_TEXTURE_2D); + + glViewport(1, 0, 1, 1); + + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(1, 0, linearColor, 1.0); +} + // Test interaction between SRGB decode and texelFetch TEST_P(SRGBTextureTestES3, SRGBDecodeTexelFetch) { @@ -325,6 +358,56 @@ void main() { EXPECT_PIXEL_COLOR_NEAR(0, 0, decodedToLinearColor, 1.0); } +// Test interaction between SRGB decode and texelFetch of an array of textures +TEST_P(SRGBTextureTestES3, SRGBDecodeTexelFetchArray) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_sRGB_decode")); + + constexpr angle::GLColor srgbColor(64, 127, 191, 255); + constexpr angle::GLColor decodedToLinearColor(13, 54, 133, 255); + + constexpr char kTexelFetchFS[] = R"(#version 300 es +precision highp float; +precision highp int; + +uniform highp sampler2D tex[1]; + +in vec4 v_position; +out vec4 my_FragColor; + +void main() { + ivec2 sampleCoords = ivec2(v_position.xy * 0.5 + 0.5); + my_FragColor = texelFetch(tex[0], sampleCoords, 0); +} +)"; + + GLTexture tex; + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0, + getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, srgbColor.data()); + ASSERT_GL_NO_ERROR(); + + glUseProgram(mProgram); + glUniform1i(mTextureLocation, 0); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, decodedToLinearColor, 1.0); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0); + + ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(), kTexelFetchFS); + glUseProgram(texelFetchProgram); + GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex"); + ASSERT_GE(texLocation, 0); + glUniform1i(texLocation, 0); + + drawQuad(texelFetchProgram, "a_position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, decodedToLinearColor, 1.0); +} + // Test basic functionality of SRGB override using the texture parameter TEST_P(SRGBTextureTest, SRGBOverrideTextureParameter) { @@ -619,6 +702,114 @@ TEST_P(SRGBTextureTestES3, SRGBDecodeOverridePriority) EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0); } +// GL_RGBA, GL_RGB and GL_SRGB_ALPHA_EXT, GL_SRGB_EXT should be compatible formats and valid +// combination. +TEST_P(SRGBTextureTestES3, SRGBFormatCombinationValidation) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB")); + + typedef struct formatCombination + { + GLint internalformat; + GLenum format; + GLenum subFormat; + } formatCombination; + + std::vector combinations = { + {GL_SRGB_EXT, GL_RGB, GL_RGB}, + {GL_SRGB_EXT, GL_SRGB_EXT, GL_RGB}, + {GL_SRGB_ALPHA_EXT, GL_RGBA, GL_SRGB_ALPHA_EXT}, + {GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT}, + {GL_SRGB8, GL_SRGB_EXT, GL_RGB}, + {GL_SRGB8_ALPHA8, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT}, + {GL_SRGB_EXT, GL_RGB, GL_SRGB_EXT}, + {GL_SRGB_EXT, GL_SRGB_EXT, GL_SRGB_EXT}, + {GL_SRGB_ALPHA_EXT, GL_RGBA, GL_RGBA}, + {GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_RGBA}, + {GL_SRGB8, GL_SRGB_EXT, GL_SRGB_EXT}, + {GL_SRGB8_ALPHA8, GL_SRGB_ALPHA_EXT, GL_RGBA}, + }; + + constexpr GLColor linearColor1(132, 55, 219, 255); + constexpr GLColor srgbColor1(190, 128, 238, 255); + constexpr GLColor linearColor2(13, 54, 133, 255); + constexpr GLColor srgbColor2(64, 127, 191, 255); + GLubyte srgbColor3D[] = {190, 128, 238, 255, 230, 159, 191, 255}; + + GLuint program3D = 0; + const char *vs3D = + "#version 300 es\n" + "out vec3 texcoord;\n" + "in vec4 position;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(position.xy, 0.0, 1.0);\n" + " texcoord = (position.xyz * 0.5) + 0.5;\n" + "}\n"; + const char *fs3D = + "#version 300 es\n" + "precision highp float;\n" + "uniform highp sampler3D tex3D;\n" + "in vec3 texcoord;\n" + "out vec4 fragColor;\n" + "void main()\n" + "{\n" + " fragColor = texture(tex3D, vec3(texcoord.x, texcoord.z, texcoord.y));\n" + "}\n"; + program3D = CompileProgram(vs3D, fs3D); + glUseProgram(program3D); + GLint texLocation3D = glGetUniformLocation(program3D, "tex3D"); + ASSERT_NE(-1, texLocation3D); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + for (auto comb : combinations) + { + GLTexture texSRGB; + glBindTexture(GL_TEXTURE_2D, texSRGB); + glTexImage2D(GL_TEXTURE_2D, 0, comb.internalformat, 1, 1, 0, comb.format, GL_UNSIGNED_BYTE, + srgbColor1.data()); + EXPECT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glUseProgram(mProgram); + glUniform1i(mTextureLocation, 0); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor1, 1.0); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, comb.subFormat, GL_UNSIGNED_BYTE, + srgbColor2.data()); + EXPECT_GL_NO_ERROR(); + glUseProgram(mProgram); + glUniform1i(mTextureLocation, 0); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor2, 1.0); + + GLTexture tex3DSRGB; + glBindTexture(GL_TEXTURE_3D, tex3DSRGB); + glTexImage3D(GL_TEXTURE_3D, 0, comb.internalformat, 1, 1, 2, 0, comb.format, + GL_UNSIGNED_BYTE, srgbColor3D); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + EXPECT_GL_NO_ERROR(); + glUseProgram(program3D); + glUniform1i(texLocation3D, 0); + drawQuad(program3D, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor1, 1.0); + + glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, comb.subFormat, GL_UNSIGNED_BYTE, + srgbColor2.data()); + EXPECT_GL_NO_ERROR(); + glUseProgram(program3D); + glUniform1i(texLocation3D, 0); + drawQuad(program3D, "position", 0.5f); + EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor2, 1.0); + } +} + // Test that mipmaps are generated correctly for sRGB textures TEST_P(SRGBTextureTestES3, GenerateMipmaps) { diff --git a/src/tests/gl_tests/SamplersTest.cpp b/src/tests/gl_tests/SamplersTest.cpp index 96107e78c51..c80df6c9342 100644 --- a/src/tests/gl_tests/SamplersTest.cpp +++ b/src/tests/gl_tests/SamplersTest.cpp @@ -6,13 +6,441 @@ // SamplerTest.cpp : Tests for samplers. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "gtest/gtest.h" #include "test_utils/ANGLETest.h" +#include "test_utils/angle_test_configs.h" #include "test_utils/gl_raii.h" +#include "util/gles_loader_autogen.h" +#include "util/shader_utils.h" namespace angle { +using BasicSamplersTest = ANGLETest<>; + +// Basic sampler test. +TEST_P(BasicSamplersTest, SampleATexture) +{ + constexpr int kWidth = 2; + constexpr int kHeight = 2; + + const GLchar *vertString = R"(precision highp float; +attribute vec2 a_position; +varying vec2 texCoord; +void main() +{ + gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); + texCoord = a_position * 0.5 + vec2(0.5); +})"; + + const GLchar *fragString = R"(precision highp float; +varying vec2 texCoord; +uniform sampler2D tex; +void main() +{ + gl_FragColor = texture2D(tex, texCoord); +})"; + + std::array redColor = { + {GLColor::red, GLColor::red, GLColor::red, GLColor::red}}; + std::array greenColor = { + {GLColor::green, GLColor::green, GLColor::green, GLColor::green}}; + + // Create a red texture and bind to texture unit 0 + GLTexture redTex; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, redTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + redColor.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + // Create a green texture and bind to texture unit 1 + GLTexture greenTex; + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, greenTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + greenColor.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glActiveTexture(GL_TEXTURE0); + ASSERT_GL_NO_ERROR(); + + GLProgram program; + program.makeRaster(vertString, fragString); + ASSERT_NE(0u, program); + glUseProgram(program); + + GLint location = glGetUniformLocation(program, "tex"); + ASSERT_NE(location, -1); + ASSERT_GL_NO_ERROR(); + + // Draw red + glUniform1i(location, 0); + ASSERT_GL_NO_ERROR(); + drawQuad(program, "a_position", 0.5f); + ASSERT_GL_NO_ERROR(); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + + // Draw green + glUniform1i(location, 1); + ASSERT_GL_NO_ERROR(); + drawQuad(program, "a_position", 0.5f); + ASSERT_GL_NO_ERROR(); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); +} + +class SampleFromRenderedTextureTest : public ANGLETest<> +{ + protected: + const GLchar *vertString = R"(precision highp float; +attribute vec2 a_position; +varying vec2 texCoord; +void main() +{ + gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); + texCoord = a_position * 0.5 + vec2(0.5); +})"; + const GLchar *vertString2 = R"(precision highp float; +attribute vec2 a_position; +varying vec2 texCoord; +void main() +{ + gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); + texCoord = a_position * 0.25 + vec2(0.5); +})"; + + const GLchar *fragString = R"(precision highp float; +varying vec2 texCoord; +uniform sampler2D tex; +void main() +{ + gl_FragColor = texture2D(tex, texCoord); +})"; + + virtual GLsizei getTextureWidth() = 0; + virtual GLsizei getTextureHeight() = 0; + virtual GLsizei getViewportOriginX() = 0; + virtual GLsizei getViewportOriginY() = 0; + + void testSetUp() override + { + glViewport(getViewportOriginX(), getViewportOriginY(), getTextureWidth(), + getTextureHeight()); + ANGLETest<>::testSetUp(); + } + + GLuint createGradientTexture() + { + GLuint gradientTex; + glGenTextures(1, &gradientTex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gradientTex); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + std::vector gradientPixels(getTextureWidth() * getTextureHeight() * 4); + for (GLubyte y = 0; y < getTextureHeight(); y++) + { + for (GLubyte x = 0; x < getTextureWidth(); x++) + { + GLubyte *pixel = &gradientPixels[0] + ((y * getTextureWidth() + x) * 4); + + // Draw a gradient, red in x direction, green in y direction + pixel[0] = x; + pixel[1] = y; + pixel[2] = 0u; + pixel[3] = 255u; + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getTextureWidth(), getTextureHeight(), 0, GL_RGBA, + GL_UNSIGNED_BYTE, gradientPixels.data()); + EXPECT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, 0); + + return gradientTex; + } + + void installProgram(bool halfScreen) + { + if (halfScreen) + { + mProgram.makeRaster(vertString2, fragString); + ASSERT_NE(0u, mProgram); + glUseProgram(mProgram); + } + else + { + mProgram.makeRaster(vertString, fragString); + ASSERT_NE(0u, mProgram); + glUseProgram(mProgram); + } + } + + void createBoundFramebufferWithColorAttachment(GLuint *fboId, GLuint *colorAttachment) + { + // Create a texture to use as the non-default FBO's color attachment. + glGenTextures(1, colorAttachment); + glBindTexture(GL_TEXTURE_2D, *colorAttachment); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + EXPECT_GL_NO_ERROR(); + + // Create the non-default fbo + if (fboId) + { + glGenFramebuffers(1, fboId); + glBindFramebuffer(GL_FRAMEBUFFER, *fboId); + EXPECT_GL_NO_ERROR(); + } + + // Attach the texture to the fbo + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + *colorAttachment, 0); + ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, 0); + } + + void bindActiveTextureToProgram(GLuint activeTextureUnit, GLuint tex) + { + GLint texLocation = glGetUniformLocation(mProgram, "tex"); + ASSERT_NE(texLocation, -1); + ASSERT_GL_NO_ERROR(); + + glActiveTexture(GL_TEXTURE0 + activeTextureUnit); + glBindTexture(GL_TEXTURE_2D, tex); + ASSERT_GL_NO_ERROR(); + glUniform1i(texLocation, activeTextureUnit); + ASSERT_GL_NO_ERROR(); + } + + void drawAndCheckGradient(bool strict) + { + drawQuad(mProgram, "a_position", 0.5f); + ASSERT_GL_NO_ERROR(); + + std::vector pixels(getTextureWidth() * getTextureHeight() * 4); + glReadPixels(getViewportOriginX(), getViewportOriginY(), getTextureWidth(), + getTextureHeight(), GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + ASSERT_GL_NO_ERROR(); + + // Check the pixels match the gradient. + size_t checkWidth = getTextureWidth(); + size_t checkHeight = getTextureHeight(); + if (!strict) + { + // Don't check the last row or column if not strict. + checkWidth--; + checkHeight--; + } + for (size_t y = 1; y < checkHeight; y++) + { + for (size_t x = 1; x < checkWidth; x++) + { + const GLubyte *prevPixel = + pixels.data() + (((y - 1) * getTextureWidth() + (x - 1)) * 4); + const GLubyte *curPixel = pixels.data() + ((y * getTextureWidth() + x) * 4); + + if (strict) + { + EXPECT_EQ(curPixel[0], prevPixel[0] + 1) + << " failed at (" << x << ", " << y << ")"; + EXPECT_EQ(curPixel[1], prevPixel[1] + 1) + << " failed at (" << x << ", " << y << ")"; + } + else + { + EXPECT_GE(curPixel[0], prevPixel[0]) << " failed at (" << x << ", " << y << ")"; + EXPECT_GE(curPixel[1], prevPixel[1]) << " failed at (" << x << ", " << y << ")"; + } + EXPECT_EQ(curPixel[2], prevPixel[2]); + EXPECT_EQ(curPixel[3], prevPixel[3]); + } + } + } + + GLProgram mProgram; +}; + +class SampleFromRenderedTextureTestHalfWindow : public SampleFromRenderedTextureTest +{ + protected: + static constexpr GLsizei kTextureWidth = 255; + static constexpr GLsizei kTextureHeight = 255; + + static constexpr GLsizei kViewportOriginX = kTextureWidth / 2; + static constexpr GLsizei kViewportOriginY = kTextureHeight / 2; + + static constexpr GLsizei kWindowWidth = kTextureWidth * 2; + static constexpr GLsizei kWindowHeight = kTextureHeight * 2; + + GLsizei getTextureWidth() override { return kTextureWidth; } + GLsizei getTextureHeight() override { return kTextureHeight; } + GLsizei getViewportOriginX() override { return kViewportOriginX; } + GLsizei getViewportOriginY() override { return kViewportOriginY; } + + SampleFromRenderedTextureTestHalfWindow() + { + setWindowWidth(kWindowWidth); + setWindowHeight(kWindowHeight); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +// Renders a gradient to a texture (twice the size) attached to an FBO, then samples from that +// texture in a second pass, effectively copying the gradient to the middle of the default +// framebuffer. Tests that the gradient remains intact. +TEST_P(SampleFromRenderedTextureTestHalfWindow, RenderToTextureAndSampleFromIt) +{ + // Create a gradient texture to use as the original source texture. + GLuint gradientTex = createGradientTexture(); + + installProgram(/*halfScreen=*/false); + + GLuint fboId; + GLuint fboTextureAttachment; + createBoundFramebufferWithColorAttachment(&fboId, &fboTextureAttachment); + + // The source texture used by the fragment shader should be the gradient texture. + bindActiveTextureToProgram(0, gradientTex); + + drawAndCheckGradient(/*strict=*/true); + + // Sample from the texture only in the current viewport (half the screen). + installProgram(/*halfScreen=*/true); + + // Now bind the default framebuffer. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + ASSERT_GL_NO_ERROR(); + + // Use the texture attached to the first framebuffer as the source texture for this draw call. + bindActiveTextureToProgram(0, fboTextureAttachment); + + // Draw and check the pixels, but in the default framebuffer + drawAndCheckGradient(/*strict=*/false); +} + +class SampleFromRenderedTextureTestFullWindow : public SampleFromRenderedTextureTest +{ + protected: + static constexpr GLsizei kTextureWidth = 255; + static constexpr GLsizei kTextureHeight = 255; + + static constexpr GLsizei kViewportOriginX = 0; + static constexpr GLsizei kViewportOriginY = 0; + + static constexpr GLsizei kWindowWidth = kTextureWidth; + static constexpr GLsizei kWindowHeight = kTextureHeight; + + GLsizei getTextureWidth() override { return kTextureWidth; } + GLsizei getTextureHeight() override { return kTextureHeight; } + GLsizei getViewportOriginX() override { return kViewportOriginX; } + GLsizei getViewportOriginY() override { return kViewportOriginY; } + + SampleFromRenderedTextureTestFullWindow() + { + setWindowWidth(kWindowWidth); + setWindowHeight(kWindowHeight); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +// Renders a gradient to a texture attached to an FBO, then samples from that texture in a second +// pass, effectively copying the gradient to the default framebuffer. Tests that the gradient +// remains intact. +TEST_P(SampleFromRenderedTextureTestFullWindow, RenderToTextureAndSampleFromIt) +{ + // Setup the program. + installProgram(/*halfScreen=*/false); + + // Create a gradient texture to use as the original source texture. + GLuint gradientTex = createGradientTexture(); + + // Create a texture to use as the non-default FBO's color attachment. + GLuint fboId; + GLuint fboTextureAttachment; + createBoundFramebufferWithColorAttachment(&fboId, &fboTextureAttachment); + + bindActiveTextureToProgram(0, gradientTex); + + drawAndCheckGradient(/*strict=*/true); + + // Now bind the default framebuffer. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + ASSERT_GL_NO_ERROR(); + + // Use the texture attached to the first framebuffer as the source texture for this draw call. + bindActiveTextureToProgram(0, fboTextureAttachment); + + drawAndCheckGradient(/*strict=*/true); +} + +// Renders a gradient to a texture attached to an FBO, then samples from that texture in a second +// pass rendering to another texture attached to the FBO. Finally that texture is rendered to the +// default framebuffer. Tests that the gradient remains intact. +TEST_P(SampleFromRenderedTextureTestFullWindow, RenderToTextureTwiceAndSampleFromIt) +{ + // Setup the program. + installProgram(/*halfScreen=*/false); + + // Create a gradient texture to use as the original source texture. + GLuint gradientTex = createGradientTexture(); + + // Create a texture to use as the non-default FBO's color attachment. + GLuint fboId; + GLuint fboTextureAttachment; + createBoundFramebufferWithColorAttachment(&fboId, &fboTextureAttachment); + + bindActiveTextureToProgram(0, gradientTex); + + drawAndCheckGradient(/*strict=*/true); + + // Create another texture to use as the non-default FBO's color attachment. + GLuint fboTextureAttachment2; + createBoundFramebufferWithColorAttachment(nullptr, &fboTextureAttachment2); + + // Use the texture attached to the first framebuffer as the source texture for this draw call. + bindActiveTextureToProgram(0, fboTextureAttachment); + + drawAndCheckGradient(/*strict=*/true); + + // Now bind the default framebuffer. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + ASSERT_GL_NO_ERROR(); + + // Use the second texture attached to the first framebuffer as the source texture for this draw + // call. + bindActiveTextureToProgram(0, fboTextureAttachment2); + + drawAndCheckGradient(/*strict=*/true); +} + class SamplersTest : public ANGLETest<> { protected: @@ -169,6 +597,14 @@ void main() EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BasicSamplersTest); +ANGLE_INSTANTIATE_TEST_ES2(BasicSamplersTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SampleFromRenderedTextureTestHalfWindow); +ANGLE_INSTANTIATE_TEST_ES2(SampleFromRenderedTextureTestHalfWindow); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SampleFromRenderedTextureTestFullWindow); +ANGLE_INSTANTIATE_TEST_ES2(SampleFromRenderedTextureTestFullWindow); + // Samplers are only supported on ES3. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SamplersTest); ANGLE_INSTANTIATE_TEST_ES3(SamplersTest); diff --git a/src/tests/gl_tests/SemaphoreTest.cpp b/src/tests/gl_tests/SemaphoreTest.cpp index f3b791207bf..610a373c485 100644 --- a/src/tests/gl_tests/SemaphoreTest.cpp +++ b/src/tests/gl_tests/SemaphoreTest.cpp @@ -6,6 +6,10 @@ // SemaphoreTest.cpp : Tests of the GL_EXT_semaphore extension. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/ShaderAlgorithmTest.cpp b/src/tests/gl_tests/ShaderAlgorithmTest.cpp index 4ec785c7cbc..595614363ce 100644 --- a/src/tests/gl_tests/ShaderAlgorithmTest.cpp +++ b/src/tests/gl_tests/ShaderAlgorithmTest.cpp @@ -27,35 +27,33 @@ class ShaderAlgorithmTest : public ANGLETest<> // Simplied version of dEQP test dEQP?GLES2.functional.shaders.algorithm.rgb_to_hsl_vertex TEST_P(ShaderAlgorithmTest, rgb_to_hsl_vertex_shader) { - const char kVS[] = - "attribute highp vec3 a_position;\n" - "attribute highp vec3 a_unitCoords;\n" - "varying mediump vec3 v_color;\n" - - "void main()\n" - "{\n" - " gl_Position =vec4(a_position.x, a_position.y, a_position.z, 1.0);\n" - " mediump vec3 coords = a_unitCoords;\n" - " mediump vec3 res = vec3(0.0);\n" - " mediump float r = coords.x, g = coords.y, b = coords.z;\n" - " mediump float minVal = min(min(r, g), b);\n" - " mediump float maxVal = max(max(r, g), b);\n" - " mediump float H = 0.0; \n" - " mediump float S = 0.0; \n" - " if (r == maxVal)\n" - " H = 1.0;\n" - " else\n" - " S = 1.0;\n" - " res = vec3(H, S, 0);\n" - " v_color = res;\n" - "}\n"; - - const char kFS[] = - "varying mediump vec3 v_color;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(v_color, 1.0);\n" - "}\n"; + const char kVS[] = R"(attribute highp vec3 a_position; +attribute highp vec3 a_unitCoords; +varying mediump vec3 v_color; + +void main() +{ + gl_Position =vec4(a_position.x, a_position.y, a_position.z, 1.0); + mediump vec3 coords = a_unitCoords; + mediump vec3 res = vec3(0.0); + mediump float r = coords.x, g = coords.y, b = coords.z; + mediump float minVal = min(min(r, g), b); + mediump float maxVal = max(max(r, g), b); + mediump float H = 0.0; + mediump float S = 0.0; + if (r == maxVal) + H = 1.0; + else + S = 1.0; + res = vec3(H, S, 0); + v_color = res; +})"; + + const char kFS[] = R"(varying mediump vec3 v_color; +void main() +{ + gl_FragColor = vec4(v_color, 1.0); +})"; ANGLE_GL_PROGRAM(program, kVS, kFS); diff --git a/src/tests/gl_tests/ShaderBinaryTest.cpp b/src/tests/gl_tests/ShaderBinaryTest.cpp index c4bec8d16f6..04282b11caf 100644 --- a/src/tests/gl_tests/ShaderBinaryTest.cpp +++ b/src/tests/gl_tests/ShaderBinaryTest.cpp @@ -92,6 +92,14 @@ class ShaderBinaryTest : public ANGLETest<> bool supported() const { + // The system driver compiler version is not expected to match the version compiled into + // this test, causing glShaderBinary() to return GL_INVALID_VALUE due to the incompatible + // binaries. + if (isDriverSystemEgl()) + { + return false; + } + GLint formatCount; glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &formatCount); if (formatCount == 0) diff --git a/src/tests/gl_tests/ShaderMultisampleInterpolation.cpp b/src/tests/gl_tests/ShaderMultisampleInterpolation.cpp index fe25654ff0d..d87dd3dc529 100644 --- a/src/tests/gl_tests/ShaderMultisampleInterpolation.cpp +++ b/src/tests/gl_tests/ShaderMultisampleInterpolation.cpp @@ -16,6 +16,11 @@ namespace class SampleMultisampleInterpolationTest : public ANGLETest<> { + public: + void basicPerSampleShading(std::vector samples, bool verify); + void simpleDraw(bool verify); + void dispatch(); + protected: SampleMultisampleInterpolationTest() { @@ -27,54 +32,11 @@ class SampleMultisampleInterpolationTest : public ANGLETest<> } }; -// Test state queries -TEST_P(SampleMultisampleInterpolationTest, StateQueries) +void SampleMultisampleInterpolationTest::basicPerSampleShading(std::vector samples, + bool verify) { - // New state queries fail without the extension - { - GLint bits = 0; - glGetIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES, &bits); - EXPECT_GL_ERROR(GL_INVALID_ENUM); - EXPECT_EQ(bits, 0); - - GLfloat minOffset = 0.0f; - glGetFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES, &minOffset); - EXPECT_GL_ERROR(GL_INVALID_ENUM); - EXPECT_EQ(minOffset, 0.0f); - - GLfloat maxOffset = 0.0f; - glGetFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES, &maxOffset); - EXPECT_GL_ERROR(GL_INVALID_ENUM); - EXPECT_EQ(maxOffset, 0.0f); - - ASSERT_GL_NO_ERROR(); - } - - ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); - - // Implementation-dependent values - { - GLint bits = 0; - glGetIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES, &bits); - EXPECT_GE(bits, 4); - - GLfloat minOffset = 0.0f; - glGetFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES, &minOffset); - EXPECT_LE(minOffset, -0.5f + std::pow(2, -bits)); - - GLfloat maxOffset = 0.0f; - glGetFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES, &maxOffset); - EXPECT_GE(maxOffset, 0.5f - std::pow(2, -bits)); - - ASSERT_GL_NO_ERROR(); - } -} - -// Test gl_SampleMaskIn values with per-sample shading -TEST_P(SampleMultisampleInterpolationTest, SampleMaskInPerSample) -{ - ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); - ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + ASSERT(IsGLExtensionEnabled("GL_OES_sample_variables")); + ASSERT(IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); const char kVS[] = R"(#version 300 es #extension GL_OES_shader_multisample_interpolation : require @@ -110,7 +72,7 @@ void main() ANGLE_GL_PROGRAM(program, kVS, kFS); glUseProgram(program); - for (GLint sampleCount : {0, 4}) + for (GLint sampleCount : samples) { GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -125,19 +87,112 @@ void main() drawQuad(program, "a_position", 0.0); ASSERT_GL_NO_ERROR(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (verify) + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + GLubyte pixel[4]; + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + ASSERT_GL_NO_ERROR(); + + EXPECT_EQ(pixel[0], 255) << "Samples: " << sampleCount; + } + } +} + +void SampleMultisampleInterpolationTest::simpleDraw(bool verify) +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + ANGLE_GL_PROGRAM(simpleDrawProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + glUseProgram(simpleDrawProgram); + drawQuad(simpleDrawProgram, "a_position", 0.0); + if (verify) + { + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + } +} + +void SampleMultisampleInterpolationTest::dispatch() +{ + constexpr char kCS[] = R"(#version 310 es +layout(local_size_x=4, local_size_y=3, local_size_z=2) in; +layout(rgba32ui) uniform highp writeonly uimage2D imageOut; +void main() +{ + uvec3 temp = gl_NumWorkGroups; + imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u)); +})"; + + ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kCS); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 4, 3); + EXPECT_GL_NO_ERROR(); + + glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + EXPECT_GL_NO_ERROR(); + + glUseProgram(computeProgram); + glDispatchCompute(8, 4, 2); + EXPECT_GL_NO_ERROR(); +} + +// Test state queries +TEST_P(SampleMultisampleInterpolationTest, StateQueries) +{ + // New state queries fail without the extension + { + GLint bits = 0; + glGetIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES, &bits); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + EXPECT_EQ(bits, 0); + + GLfloat minOffset = 0.0f; + glGetFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES, &minOffset); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + EXPECT_EQ(minOffset, 0.0f); + + GLfloat maxOffset = 0.0f; + glGetFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES, &maxOffset); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + EXPECT_EQ(maxOffset, 0.0f); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - GLubyte pixel[4]; - glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); ASSERT_GL_NO_ERROR(); + } - EXPECT_EQ(pixel[0], 255) << "Samples: " << sampleCount; + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Implementation-dependent values + { + GLint bits = 0; + glGetIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES, &bits); + EXPECT_GE(bits, 4); + + GLfloat minOffset = 0.0f; + glGetFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES, &minOffset); + EXPECT_LE(minOffset, -0.5f + std::pow(2, -bits)); + + GLfloat maxOffset = 0.0f; + glGetFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES, &maxOffset); + EXPECT_GE(maxOffset, 0.5f - std::pow(2, -bits)); + + ASSERT_GL_NO_ERROR(); } } +// Test gl_SampleMaskIn values with per-sample shading +TEST_P(SampleMultisampleInterpolationTest, SampleMaskInPerSample) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + basicPerSampleShading({0, 4}, true); +} + // Test gl_SampleMaskIn values with per-sample noperspective shading TEST_P(SampleMultisampleInterpolationTest, SampleMaskInPerSampleNoPerspective) { @@ -390,7 +445,103 @@ void main() ANGLE_GL_PROGRAM(program, kVS, kFS); } +class SampleMultisampleInterpolationTest31 : public SampleMultisampleInterpolationTest +{}; + +// Test per-sample shading draw -> simple draw -> per-sample shading draw +TEST_P(SampleMultisampleInterpolationTest31, SampleShadingThenSimpleDraw) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Draw with sample shading + basicPerSampleShading({4}, false); + + // Draw without sample shading + simpleDraw(false); + + // Draw with sample shading, again + basicPerSampleShading({4}, true); +} + +// Test per-sample shading draw -> dispatch +TEST_P(SampleMultisampleInterpolationTest31, SampleShadingThenCompute) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Draw with sample shading + basicPerSampleShading({4}, false); + + // Dispatch with compute shader + dispatch(); +} + +// Test dispatch -> per-sample shading draw +TEST_P(SampleMultisampleInterpolationTest31, ComputeThenSampleShading) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Dispatch with compute shader + dispatch(); + + // Draw with sample shading + basicPerSampleShading({4}, false); +} + +// Test per-sample shading draw -> dispatch -> simple draw +TEST_P(SampleMultisampleInterpolationTest31, SampleShadingThenComputeThenSimpleDraw) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Draw with sample shading + basicPerSampleShading({4}, false); + + // Dispatch with compute shader + dispatch(); + + // Draw without sample shading + simpleDraw(true); +} + +// Test per-sample shading draw -> dispatch -> per-sample shading draw +TEST_P(SampleMultisampleInterpolationTest31, SampleShadingThenComputeThenSampleShading) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Draw with sample shading + basicPerSampleShading({4}, false); + + // Dispatch with compute shader + dispatch(); + + // Draw with sample shading, again + basicPerSampleShading({4}, true); +} + +// Test simple draw -> dispatch -> per-sample shading draw +TEST_P(SampleMultisampleInterpolationTest31, SimpleDrawThenComputeThenSampleShading) +{ + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables")); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation")); + + // Draw without sample shading + simpleDraw(false); + + // Dispatch with compute shader + dispatch(); + + // Draw with sample shading + basicPerSampleShading({4}, true); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SampleMultisampleInterpolationTest); ANGLE_INSTANTIATE_TEST_ES3(SampleMultisampleInterpolationTest); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SampleMultisampleInterpolationTest31); +ANGLE_INSTANTIATE_TEST_ES31(SampleMultisampleInterpolationTest31); + } // anonymous namespace diff --git a/src/tests/gl_tests/ShaderStorageBufferTest.cpp b/src/tests/gl_tests/ShaderStorageBufferTest.cpp index 802a7243b15..7ad97bc31e1 100644 --- a/src/tests/gl_tests/ShaderStorageBufferTest.cpp +++ b/src/tests/gl_tests/ShaderStorageBufferTest.cpp @@ -7,6 +7,10 @@ // Various tests related for shader storage buffers. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -818,7 +822,7 @@ TEST_P(ShaderStorageBufferTest31, VectorSwizzleInColumnMajorMatrixTest) // Test that access/write to swizzle vector data in row_major matrix in shader storage block. TEST_P(ShaderStorageBufferTest31, VectorSwizzleInRowMajorMatrixTest) { - ANGLE_SKIP_TEST_IF(IsAndroid()); + ANGLE_SKIP_TEST_IF(IsAndroid() && IsQualcomm()); constexpr char kComputeShaderSource[] = R"(#version 310 es @@ -853,8 +857,8 @@ TEST_P(ShaderStorageBufferTest31, ScalarDataInMatrixInSSBOWithRowMajorQualifier) { // TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform. // http://anglebug.com/40644618 - ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux()); - ANGLE_SKIP_TEST_IF(IsAndroid()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); + ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL()); constexpr char kComputeShaderSource[] = R"(#version 310 es @@ -869,9 +873,9 @@ void main() { instanceOut.data[0][0] = instanceIn.data[0][0]; instanceOut.data[0][1] = instanceIn.data[0][1]; - instanceOut.data[0][2] = instanceIn.data[0][2]; - instanceOut.data[1][0] = instanceIn.data[1][0]; - instanceOut.data[1][1] = instanceIn.data[1][1]; + instanceOut.data[0].z = instanceIn.data[0].z; + instanceOut.data[1].x = instanceIn.data[1].x; + instanceOut.data[1].y = instanceIn.data[1].y; instanceOut.data[1][2] = instanceIn.data[1][2]; } )"; @@ -890,7 +894,7 @@ void main() TEST_P(ShaderStorageBufferTest31, VectorDataInMatrixInSSBOWithRowMajorQualifier) { - ANGLE_SKIP_TEST_IF(IsAndroid()); + ANGLE_SKIP_TEST_IF(IsAndroid() && IsQualcomm()); constexpr char kComputeShaderSource[] = R"(#version 310 es @@ -956,8 +960,8 @@ TEST_P(ShaderStorageBufferTest31, ScalarDataInMatrixInStructureInSSBOWithRowMajo { // TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform. // http://anglebug.com/40644618 - ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux()); - ANGLE_SKIP_TEST_IF(IsAndroid()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); + ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL()); constexpr char kComputeShaderSource[] = R"(#version 310 es @@ -976,9 +980,9 @@ void main() { instanceOut.s.data[0][0] = instanceIn.s.data[0][0]; instanceOut.s.data[0][1] = instanceIn.s.data[0][1]; - instanceOut.s.data[0][2] = instanceIn.s.data[0][2]; - instanceOut.s.data[1][0] = instanceIn.s.data[1][0]; - instanceOut.s.data[1][1] = instanceIn.s.data[1][1]; + instanceOut.s.data[0].z = instanceIn.s.data[0].z; + instanceOut.s.data[1].x = instanceIn.s.data[1].x; + instanceOut.s.data[1].y = instanceIn.s.data[1].y; instanceOut.s.data[1][2] = instanceIn.s.data[1][2]; } )"; @@ -1784,7 +1788,7 @@ TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanValue) { // TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform. // http://anglebug.com/40644618 - ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); constexpr char kComputeShaderSource[] = R"(#version 310 es layout (local_size_x=1) in; @@ -1857,7 +1861,7 @@ TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanVec3) { // TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform. // http://anglebug.com/40644618 - ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL()); @@ -1921,7 +1925,7 @@ TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanVarAndVec2) { // TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform. // http://anglebug.com/40644618 - ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL()); diff --git a/src/tests/gl_tests/ShadingRateEXTTest.cpp b/src/tests/gl_tests/ShadingRateEXTTest.cpp new file mode 100644 index 00000000000..fa035b6b19d --- /dev/null +++ b/src/tests/gl_tests/ShadingRateEXTTest.cpp @@ -0,0 +1,336 @@ +// +// Copyright 2022 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. +// + +// ShadingRateEXTTest.cpp : Tests of the GL_EXT_fragment_shading_rate extension. + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "test_utils/ANGLETest.h" + +#include "test_utils/gl_raii.h" + +namespace angle +{ + +class ShadingRateEXTTest : public ANGLETest<> +{ + protected: + ShadingRateEXTTest() + { + setWindowWidth(256); + setWindowHeight(256); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +constexpr char kSimpleShadingRateVS[] = R"(#version 310 es +in vec4 a_position; +void main() +{ + gl_Position = a_position; +})"; + +constexpr char kSimplePrimitiveShadingRateVS[] = R"(#version 310 es +#extension GL_EXT_fragment_shading_rate : require +in vec4 a_position; +void main() +{ + gl_Position = a_position; + gl_PrimitiveShadingRateEXT = gl_ShadingRateFlag2VerticalPixelsEXT | gl_ShadingRateFlag2HorizontalPixelsEXT; +})"; + +constexpr char kSimplePrimitiveShadingRateGS[] = R"(#version 310 es +#extension GL_EXT_geometry_shader : require +#extension GL_EXT_fragment_shading_rate : require +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +void main() +{ + for (int i = 0; i < 3; i++) + { + gl_PrimitiveShadingRateEXT = gl_ShadingRateFlag2VerticalPixelsEXT | gl_ShadingRateFlag2HorizontalPixelsEXT; + gl_Position = gl_in[i].gl_Position; + EmitVertex(); + } + EndPrimitive(); +})"; + +constexpr char kSimpleShadingRateFS[] = R"(#version 310 es +#extension GL_EXT_fragment_shading_rate : require +precision highp float; +layout(location = 0) out vec4 fragColor; +uniform mediump vec4 u_color; +void main() +{ + // Emit red color if ShadingRateEXT == gl_ShadingRateFlag2VerticalPixelsEXT | gl_ShadingRateFlag2HorizontalPixelsEXT + if (gl_ShadingRateEXT == 5) { + fragColor = vec4(1.0, 0.0, 0.0, 1.0); // red + } + // ShadingRateEXT == 0 indicates 1x1 shading rate + else if (gl_ShadingRateEXT == 0) { + fragColor = u_color; + } else { + fragColor = vec4(0.0, 1.0, 0.0, 1.0); // green + } +})"; + +constexpr char kSimpleShadingRateUniformColorFS[] = R"(#version 310 es +#extension GL_EXT_fragment_shading_rate : require +precision highp float; +uniform mediump vec4 u_color; +layout(location = 0) out vec4 fragColor; +void main() +{ + // Emit uniform color if ShadingRateEXT == gl_ShadingRateFlag2VerticalPixelsEXT | gl_ShadingRateFlag2HorizontalPixelsEXT + if (gl_ShadingRateEXT == 5) { + fragColor = u_color; + } else { + fragColor = vec4(0.0, 0.0, 0.0, 1.0); + } +})"; + +// Test basic functionality of EXT_fragment_shading_rate +TEST_P(ShadingRateEXTTest, FragmentShadingRate) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate")); + + // Verify validate shading rate. + GLsizei count = 0; + const int maxNum = 9; + GLenum shadingRates[maxNum]; + glGetFragmentShadingRatesEXT(1, maxNum, &count, shadingRates); + ASSERT_GL_NO_ERROR(); + + for (int i = 0; i < count; i++) + { + glShadingRateEXT(shadingRates[i]); + } + ASSERT_GL_NO_ERROR(); + + glShadingRateEXT(GL_SHADING_RATE_1X1_PIXELS_EXT); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + ANGLE_GL_PROGRAM(drawShadingRateProgram, kSimpleShadingRateVS, kSimpleShadingRateFS); + glUseProgram(drawShadingRateProgram); + + // Set and query shading rate. + glShadingRateEXT(GL_SHADING_RATE_2X2_PIXELS_EXT); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + GLint shadingRate = 0; + glGetIntegerv(GL_SHADING_RATE_EXT, &shadingRate); + ASSERT(shadingRate == GL_SHADING_RATE_2X2_PIXELS_EXT); + + // Verify draw call with 2x2 shading rate. + drawQuad(drawShadingRateProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); +} + +// Test EXT_fragment_shading_rate and EXT_fragment_shading_rate_primitive state change with Blend +TEST_P(ShadingRateEXTTest, FragmentShadingRateBlend) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate_primitive")); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + // Render red quad with 2x2 shading rate. + ANGLE_GL_PROGRAM(drawShadingRateProgram, kSimpleShadingRateVS, + kSimpleShadingRateUniformColorFS); + glUseProgram(drawShadingRateProgram); + GLint colorUniformLocation = glGetUniformLocation(drawShadingRateProgram, "u_color"); + ASSERT_NE(colorUniformLocation, -1); + glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f); + + glShadingRateEXT(GL_SHADING_RATE_2X2_PIXELS_EXT); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + drawQuad(drawShadingRateProgram, essl1_shaders::PositionAttrib(), 0.5f); + + // Enable blend + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + + // Render green quad with 2x2 shading rate. + ANGLE_GL_PROGRAM(primitiveShadingRateVSProgram, kSimplePrimitiveShadingRateVS, + kSimpleShadingRateUniformColorFS); + glUseProgram(primitiveShadingRateVSProgram); + colorUniformLocation = glGetUniformLocation(primitiveShadingRateVSProgram, "u_color"); + ASSERT_NE(colorUniformLocation, -1); + glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.0f); + + glShadingRateEXT(GL_SHADING_RATE_1X1_PIXELS_EXT); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + drawQuad(primitiveShadingRateVSProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + + // Verify if render a yellow quad. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255u, 255u, 0u, 255u)); +} + +// Test basic functionality of EXT_fragment_shading_rate_primitive +TEST_P(ShadingRateEXTTest, FragmentShadingRatePrimitive) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate_primitive")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader")); + + // Yellow + glClearColor(1.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + ANGLE_GL_PROGRAM(drawShadingRateProgram, kSimpleShadingRateVS, kSimpleShadingRateFS); + glUseProgram(drawShadingRateProgram); + GLint colorLoc = glGetUniformLocation(drawShadingRateProgram, "u_color"); + ASSERT_NE(colorLoc, -1); + glUniform4f(colorLoc, 0, 0, 1, 1); // blue + + // Set 1x1 shading rate and KEEP combinerOps. + glShadingRateEXT(GL_SHADING_RATE_1X1_PIXELS_EXT); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + // Verify draw call with 1x1 shading rate. + drawQuad(drawShadingRateProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + // GL_SHADING_RATE_1X1_PIXELS_EXT -> gl_ShadingRateEXT = 0 + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + // Compile PrimitiveShadingRateVS + FS and use this program + ANGLE_GL_PROGRAM(primitiveShadingRateVSProgram, kSimplePrimitiveShadingRateVS, + kSimpleShadingRateFS); + glUseProgram(primitiveShadingRateVSProgram); + colorLoc = glGetUniformLocation(primitiveShadingRateVSProgram, "u_color"); + ASSERT_NE(colorLoc, -1); + glUniform4f(colorLoc, 0, 0, 1, 1); // blue + + // Set 2x2 shading rate and REPLACE combinerOps. + glShadingRateEXT(GL_SHADING_RATE_2X2_PIXELS_EXT); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + // Verify draw call with 2x2 primitive shading rate. + drawQuad(primitiveShadingRateVSProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + glClear(GL_COLOR_BUFFER_BIT); + // Compile VS + PrimitiveShadingRateGS + FS and use this program + ANGLE_GL_PROGRAM_WITH_GS(primitiveShadingRateGSProgram, kSimpleShadingRateVS, + kSimplePrimitiveShadingRateGS, kSimpleShadingRateFS); + glUseProgram(primitiveShadingRateGSProgram); + colorLoc = glGetUniformLocation(primitiveShadingRateGSProgram, "u_color"); + ASSERT_NE(colorLoc, -1); + glUniform4f(colorLoc, 0, 0, 1, 1); // blue + + // Verify draw call with 2x2 primitive shading rate with GS. + drawQuad(primitiveShadingRateGSProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Recover 1x1 shading rate and KEEP combinerOps to verify. + glShadingRateEXT(GL_SHADING_RATE_1X1_PIXELS_EXT); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + drawQuad(drawShadingRateProgram, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); +} + +// The negative test of EXT_fragment_shading_rate +TEST_P(ShadingRateEXTTest, Error) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate")); + + glShadingRateEXT(GL_SAMPLE_SHADING); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + + glShadingRateCombinerOpsEXT(GL_SHADING_RATE_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + + GLboolean supportNonTrivialCombiner = false; + glGetBooleanv(GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT, + &supportNonTrivialCombiner); + + if (!supportNonTrivialCombiner) + { + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } + + if (!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate_primitive")) + { + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } + + if (!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate_attachment")) + { + glShadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT, + GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } +} + +// Test that when FETCH_PER_SAMPLE_ARM is enabled, the fragment shading rate +// is set to GL_SHADING_RATE_1X1_PIXELS_EXT. +TEST_P(ShadingRateEXTTest, ShadingRateFramebufferFetchPerSample) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_fragment_shading_rate")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARM_shader_framebuffer_fetch")); + + glShadingRateEXT(GL_SHADING_RATE_2X2_PIXELS_EXT); + ASSERT_GL_NO_ERROR(); + + ANGLE_GL_PROGRAM(program, kSimpleShadingRateVS, kSimpleShadingRateFS); + glUseProgram(program); + + GLint colorLoc = glGetUniformLocation(program, "u_color"); + ASSERT_NE(colorLoc, -1); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + glEnable(GL_FETCH_PER_SAMPLE_ARM); + glUniform4f(colorLoc, 0, 0, 1, 0); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + + glDisable(GL_FETCH_PER_SAMPLE_ARM); + glUniform4f(colorLoc, 0, 0, 0, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + + glEnable(GL_FETCH_PER_SAMPLE_ARM); + glUniform4f(colorLoc, 0, 0.5, 0, 0); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 128, 255, 255), 1); +} + +// Use this to select which configurations (e.g. which renderer, which GLES major version) these +// tests should be run against. +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadingRateEXTTest); +ANGLE_INSTANTIATE_TEST_ES31(ShadingRateEXTTest); + +} // namespace angle diff --git a/src/tests/gl_tests/ShadowSamplerFunctionsTest.cpp b/src/tests/gl_tests/ShadowSamplerFunctionsTest.cpp index 1cb19a17a89..594b472d9ec 100644 --- a/src/tests/gl_tests/ShadowSamplerFunctionsTest.cpp +++ b/src/tests/gl_tests/ShadowSamplerFunctionsTest.cpp @@ -66,6 +66,9 @@ const char *FunctionName(FunctionType function) return "textureProjGrad"; case FunctionType::TextureProjGradOffset: return "textureProjGradOffset"; + default: + UNREACHABLE(); + return ""; } } diff --git a/src/tests/gl_tests/SimpleOperationTest.cpp b/src/tests/gl_tests/SimpleOperationTest.cpp index 43e103ba9bb..056d8489e4e 100644 --- a/src/tests/gl_tests/SimpleOperationTest.cpp +++ b/src/tests/gl_tests/SimpleOperationTest.cpp @@ -5,6 +5,11 @@ // // SimpleOperationTest: // Basic GL commands such as linking a program, initializing a buffer, etc. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "test_utils/ANGLETest.h" @@ -214,6 +219,20 @@ TEST_P(SimpleOperationTest, ClearAndSwap) ASSERT_FALSE(getGLWindow()->hasError()); } +// Deleting shader zero is no-op. +TEST_P(SimpleOperationTest, DeleteShaderZero) +{ + glDeleteShader(0); + EXPECT_GL_NO_ERROR(); +} + +// Deleting program zero is no-op. +TEST_P(SimpleOperationTest, DeleteProgramZero) +{ + glDeleteProgram(0); + EXPECT_GL_NO_ERROR(); +} + // Simple case of setting a scissor, enabled or disabled. TEST_P(SimpleOperationTest, ScissorTest) { @@ -1571,6 +1590,102 @@ TEST_P(SimpleOperationTest, DrawSingleMultiSampleWithAlphaToCoverage) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); } +// Test glGetRenderbufferParameteriv returned value for different render buffer +TEST_P(SimpleOperationTest, GetRenderbufferParameter) +{ + GLint value = 0; + // call glGetRenderbufferParameteriv with renderbuffer bound to 0 + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &value); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // generate an empty renderbuffer, then get all parameters, they should equal to default values + GLRenderbuffer renderBuffer; + glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer); + + // Retrieve all values + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &value); + ASSERT_EQ(value, GL_RGBA4); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_GREEN_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_BLUE_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &value); + ASSERT_EQ(value, 0); + + // set buffer storage, then get all renderbuffer parameters + + // Allocate memory for renderbuffer + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 32, 32); + + /* Retrieve all values */ + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &value); + ASSERT_EQ(value, 32); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &value); + ASSERT_EQ(value, 32); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &value); + ASSERT_EQ(value, GL_DEPTH_COMPONENT16); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_GREEN_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_BLUE_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE, &value); + ASSERT_EQ(value, 0); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, &value); + ASSERT_GE(value, 16); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &value); + ASSERT_EQ(value, 0); + + // call glGetRenderbufferParameteriv with an invalid pname + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_INVALID_ENUM, &value); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + + // Call with invalid target with invalid target + glGetRenderbufferParameteriv(GL_INVALID_VALUE, GL_RENDERBUFFER_WIDTH, &value); + EXPECT_GL_ERROR(GL_INVALID_ENUM); +} + +// Test that passing NULL to the shader parameter in the glGetAttachedShaders function +// should return GL_INVALID_VALUE. +TEST_P(SimpleOperationTest, NullParameterInGetAttachedShaders) +{ + GLsizei length; + GLuint attachedShaders[2] = {0u}; + GLuint program = glCreateProgram(); + ASSERT_GL_NO_ERROR(); + + glGetAttachedShaders(program, 0, &length, NULL); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glGetAttachedShaders(program, 0, NULL, attachedShaders); + EXPECT_GL_ERROR(GL_NO_ERROR); +} + +// Test that passing NULL separately to the range and precision parameters +// in the glGetShaderPrecisionFormat function should return GL_INVALID_VALUE. +TEST_P(SimpleOperationTest, NullParameterInGetShaderPrecisionFormat) +{ + GLint range[2], precision; + + glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_LOW_FLOAT, range, NULL); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_LOW_FLOAT, NULL, &precision); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( diff --git a/src/tests/gl_tests/SixteenBppTextureTest.cpp b/src/tests/gl_tests/SixteenBppTextureTest.cpp index d2fec92d8a1..40490e9957a 100644 --- a/src/tests/gl_tests/SixteenBppTextureTest.cpp +++ b/src/tests/gl_tests/SixteenBppTextureTest.cpp @@ -6,6 +6,10 @@ // SixteenBppTextureTest: // Basic tests using 16bpp texture formats (e.g. GL_RGB565). +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp index 2dbb37bed83..dd91fd6db44 100644 --- a/src/tests/gl_tests/StateChangeTest.cpp +++ b/src/tests/gl_tests/StateChangeTest.cpp @@ -8,6 +8,10 @@ // ANGLE's dirty bits systems don't get confused by certain sequences of state changes. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/random_utils.h" @@ -4334,8 +4338,13 @@ void main() // Capture rendered pixel color w/ s1 linear std::vector s1LinearColors(kWindowSize * kWindowSize); glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data()); + // Results should be the same regardless of if s0 or s1 is linear - EXPECT_EQ(s0LinearColors, s1LinearColors); + ASSERT(s0LinearColors.size() == s1LinearColors.size()); + for (size_t index = 0; index < s0LinearColors.size(); index++) + { + EXPECT_COLOR_NEAR(s0LinearColors[index], s1LinearColors[index], 1u); + } } // Tests that rendering works as expected with multiple VAOs. @@ -5582,6 +5591,153 @@ TEST_P(ValidationStateChangeTest, MapBufferAndDraw) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); } +// Test mapBuffer while attribute disabled should succeed. If attribute is then enabled it should +// fail with GL_INVALID_OPERATION +TEST_P(ValidationStateChangeTest, MapBufferWithAttribDisabledThenEnableAndDraw) +{ + // Initialize program and set up state. + ANGLE_GL_PROGRAM(program, kColorVS, kColorFS); + + glUseProgram(program); + GLint positionLoc = glGetAttribLocation(program, "position"); + ASSERT_NE(-1, positionLoc); + GLint colorLoc = glGetAttribLocation(program, "color"); + ASSERT_NE(-1, colorLoc); + + const std::array &quadVertices = GetQuadVertices(); + const size_t posBufferSize = quadVertices.size() * sizeof(Vector3); + + // Start with position enabled and posBuffer unmapped. + GLBuffer posBuffer; + glBindBuffer(GL_ARRAY_BUFFER, posBuffer); + glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLoc); + + // Color disabled and color buffer mapped. + std::vector colorVertices(6, GLColor::blue); + const size_t colorBufferSize = sizeof(GLColor) * 6; + GLBuffer colorBuffer; + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW); + glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr); + glDisableVertexAttribArray(colorLoc); + glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + + // Draw with colorBuffer mapped but disabled. Should succeed. + glVertexAttrib4f(colorLoc, 0, 1, 0, 1); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Now enable color attribute and draw. Should produce GL_INVALID_OPERATION. + glEnableVertexAttribArray(colorLoc); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Unmap then draw. Should succeed. + glUnmapBuffer(GL_ARRAY_BUFFER); + glDrawArrays(GL_TRIANGLES, 0, 6); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); +} + +// Test glBindBuffer picks up buffer changes in another shared context. +TEST_P(ValidationStateChangeTest, RebindBufferShouldPickupBufferChange) +{ + EGLWindow *window = getEGLWindow(); + EGLDisplay display = window->getDisplay(); + EGLConfig config = window->getConfig(); + EGLContext context1 = window->getContext(); + EGLSurface surface1 = window->getSurface(); + + // Initialize program and set up state. + ANGLE_GL_PROGRAM(program, kColorVS, kColorFS); + + glUseProgram(program); + GLint positionLoc = glGetAttribLocation(program, "position"); + ASSERT_NE(-1, positionLoc); + GLint colorLoc = glGetAttribLocation(program, "color"); + ASSERT_NE(-1, colorLoc); + + const std::array &quadVertices = GetQuadVertices(); + const size_t posBufferSize = quadVertices.size() * sizeof(Vector3); + + // Start with context 1, with position and color enabled and unmapped. Draw should success. + GLBuffer posBuffer; + glBindBuffer(GL_ARRAY_BUFFER, posBuffer); + glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLoc); + std::vector colorVertices(6, GLColor::blue); + const size_t colorBufferSize = sizeof(GLColor) * 6; + GLBuffer colorBuffer; + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW); + glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr); + glEnableVertexAttribArray(colorLoc); + glVertexAttrib4f(colorLoc, 0, 1, 0, 1); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + // Created shared context2, and switch to context2 and draw. Should success. + EGLint pbufferAttributes[] = {EGL_WIDTH, getWindowWidth(), EGL_HEIGHT, + getWindowHeight(), EGL_NONE, EGL_NONE}; + EGLSurface surface2 = eglCreatePbufferSurface(display, config, pbufferAttributes); + EGLContext context2 = window->createContext(context1, nullptr); + EXPECT_EGL_SUCCESS(); + ASSERT_NE(context2, EGL_NO_CONTEXT); + eglMakeCurrent(display, surface2, surface2, context2); + EXPECT_EGL_SUCCESS(); + glUseProgram(program); + glBindBuffer(GL_ARRAY_BUFFER, posBuffer); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLoc); + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr); + glEnableVertexAttribArray(colorLoc); + glVertexAttrib4f(colorLoc, 0, 1, 0, 1); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + // In context2, map color buffer again and draw, should produce produce GL_INVALID_OPERATION + GLColor *bufferPtr = static_cast( + glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_WRITE_BIT)); + for (size_t i = 0; i < 6; i++) + { + bufferPtr[i] = GLColor::red; + } + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Now switch back to context1 and draw. Since buffer is modified (map) in context2, we need to + // rebind the buffer. Rebind should pick up the buffer change and produce GL_INVALID_OPERATION. + eglMakeCurrent(display, surface1, surface1, context1); + EXPECT_EGL_SUCCESS(); + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Back to context2 and unmap the color buffer without draw + eglMakeCurrent(display, surface2, surface2, context2); + EXPECT_EGL_SUCCESS(); + glUnmapBuffer(GL_ARRAY_BUFFER); + ASSERT_GL_NO_ERROR(); + + // Switch back to context1 and rebind and draw. Rebind should pick up the buffer change and draw + // should succeed. + eglMakeCurrent(display, surface1, surface1, context1); + EXPECT_EGL_SUCCESS(); + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glDrawArrays(GL_TRIANGLES, 0, 6); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Clean up and destroy context2 + eglMakeCurrent(display, surface1, surface1, context1); + eglDestroyContext(display, context2); +} + // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer() // allows rendering to succeed. TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw) @@ -5797,6 +5953,116 @@ TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test glBindVertexBuffer picks up buffer changes in another shared context. +TEST_P(ValidationStateChangeTestES31, RebindVertexBufferShouldPickupBufferChange) +{ + EGLWindow *window = getEGLWindow(); + EGLDisplay display = window->getDisplay(); + EGLConfig config = window->getConfig(); + EGLContext context1 = window->getContext(); + EGLSurface surface1 = window->getSurface(); + + // Initialize program and set up state. + ANGLE_GL_PROGRAM(program, kColorVS, kColorFS); + + glUseProgram(program); + GLint positionLoc = glGetAttribLocation(program, "position"); + ASSERT_NE(-1, positionLoc); + GLint colorLoc = glGetAttribLocation(program, "color"); + ASSERT_NE(-1, colorLoc); + + const std::array &quadVertices = GetQuadVertices(); + const size_t posBufferSize = quadVertices.size() * sizeof(Vector3); + + // Start with context 1, with position and color enabled and unmapped. Draw should success. + GLVertexArray vao1; + glBindVertexArray(vao1); + GLBuffer posBuffer; + glBindBuffer(GL_ARRAY_BUFFER, posBuffer); + glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLoc); + std::vector colorVertices(6, GLColor::blue); + const size_t colorBufferSize = sizeof(GLColor) * 6; + GLBuffer colorBuffer; + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW); + glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0); + constexpr GLint kBufferBinding1 = 3; + ASSERT_NE(colorLoc, kBufferBinding1); + ASSERT_NE(positionLoc, kBufferBinding1); + glVertexAttribBinding(colorLoc, kBufferBinding1); + glBindVertexBuffer(kBufferBinding1, colorBuffer, /*offset*/ 0, /*stride*/ sizeof(GLColor)); + glEnableVertexAttribArray(colorLoc); + glVertexAttrib4f(colorLoc, 0, 1, 0, 1); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + // Created shared context2, and switch to context2 and draw. Should success. + EGLint pbufferAttributes[] = {EGL_WIDTH, getWindowWidth(), EGL_HEIGHT, + getWindowHeight(), EGL_NONE, EGL_NONE}; + EGLSurface surface2 = eglCreatePbufferSurface(display, config, pbufferAttributes); + EGLContext context2 = window->createContext(context1, nullptr); + EXPECT_EGL_SUCCESS(); + ASSERT_NE(context2, EGL_NO_CONTEXT); + eglMakeCurrent(display, surface2, surface2, context2); + EXPECT_EGL_SUCCESS(); + glUseProgram(program); + GLVertexArray vao2; + glBindVertexArray(vao2); + glBindBuffer(GL_ARRAY_BUFFER, posBuffer); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLoc); + glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0); + constexpr GLint kBufferBinding2 = 4; + ASSERT_NE(colorLoc, kBufferBinding2); + ASSERT_NE(positionLoc, kBufferBinding2); + glVertexAttribBinding(colorLoc, kBufferBinding2); + glBindVertexBuffer(kBufferBinding2, colorBuffer, /*offset*/ 0, /*stride*/ sizeof(GLColor)); + glEnableVertexAttribArray(colorLoc); + glVertexAttrib4f(colorLoc, 0, 1, 0, 1); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + // In context2, map color buffer again and draw, should produce produce GL_INVALID_OPERATION + GLColor *bufferPtr = static_cast( + glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_WRITE_BIT)); + for (size_t i = 0; i < 6; i++) + { + bufferPtr[i] = GLColor::red; + } + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Now switch back to context1 and draw. Since buffer is modified (map) in context2, we need to + // rebind the buffer. Rebind should pick up the buffer change and produce GL_INVALID_OPERATION. + eglMakeCurrent(display, surface1, surface1, context1); + EXPECT_EGL_SUCCESS(); + glBindVertexBuffer(kBufferBinding1, colorBuffer, /*offset*/ 0, /*stride*/ sizeof(GLColor)); + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Back to context2 and unmap the color buffer without draw + eglMakeCurrent(display, surface2, surface2, context2); + EXPECT_EGL_SUCCESS(); + glUnmapBuffer(GL_ARRAY_BUFFER); + ASSERT_GL_NO_ERROR(); + + // Switch back to context1 and rebind and draw. Rebind should pick up the buffer change and draw + // should succeed. + eglMakeCurrent(display, surface1, surface1, context1); + EXPECT_EGL_SUCCESS(); + glBindVertexBuffer(kBufferBinding1, colorBuffer, /*offset*/ 0, /*stride*/ sizeof(GLColor)); + glDrawArrays(GL_TRIANGLES, 0, 6); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Clean up and destroy context2 + eglMakeCurrent(display, surface1, surface1, context1); + eglDestroyContext(display, context2); +} + // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check. TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor) { @@ -7642,7 +7908,7 @@ TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed) constexpr char kFS[] = R"(#version 300 es precision mediump float; uniform block { uint data; } ubo; -uniform uint expect; +uniform highp uint expect; uniform vec4 successColor; out vec4 colorOut; void main() @@ -7855,18 +8121,36 @@ void main() EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes); EGLContext ctx = window->createContext(EGL_NO_CONTEXT, nullptr); EXPECT_EGL_SUCCESS(); + EGLSurface mainSurface = window->getSurface(); + EGLContext mainContext = window->getContext(); + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + std::thread flushThread = std::thread([&]() { EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx)); EXPECT_EGL_SUCCESS(); + GLFramebuffer threadFbo; + GLTexture threadTexture; + glBindTexture(GL_TEXTURE_2D, threadTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindFramebuffer(GL_FRAMEBUFFER, threadFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + threadTexture, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glClearColor(1, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); EXPECT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); }); flushThread.join(); + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, mainSurface, mainSurface, mainContext)); eglDestroySurface(dpy, surface); eglDestroyContext(dpy, ctx); } @@ -8210,10 +8494,10 @@ TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedback) glEndTransformFeedback(); } -// Test a bug angleproject:6998 in TransformFeedback code path by allocating paddingBuffer first and -// then allocate another buffer and then deallocate paddingBuffer and then allocate buffer again. -// This new buffer will be allocated in the space where paddingBuffer was allocated which causing -// XFB generate VVL error. +// Test a bug http://anglebug.com/42265470 in TransformFeedback code path by allocating +// paddingBuffer first and then allocate another buffer and then deallocate paddingBuffer and then +// allocate buffer again. This new buffer will be allocated in the space where paddingBuffer was +// allocated which causing XFB generate VVL error. TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer) { std::vector tfVaryings = {"gl_Position"}; @@ -10714,6 +10998,66 @@ TEST_P(StateChangeTestES3, SampleCoverageFramebufferAttachmentSwitch) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test that GL_SAMPLE_COVERAGE value has proper effect after frame buffer switch. +TEST_P(StateChangeTestES3, SampleCoverageFramebufferSwitch) +{ + // Keep this state unchanged during the test + glEnable(GL_SAMPLE_COVERAGE); + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + GLRenderbuffer rboMS; + glBindRenderbuffer(GL_RENDERBUFFER, rboMS); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + GLFramebuffer fboResolve; + glBindFramebuffer(GL_FRAMEBUFFER, fboResolve); + + GLRenderbuffer rboResolve; + glBindRenderbuffer(GL_RENDERBUFFER, rboResolve); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboResolve); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClearColor(1, 0, 0, 1); + + // Set any non 1 coverage and draw the quad + glSampleCoverage(0.5, false); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5); + ASSERT_GL_NO_ERROR(); + + // Switch to single sampled FBO and draw with coverage 1. + glBindFramebuffer(GL_FRAMEBUFFER, fboResolve); + glSampleCoverage(1.0, false); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + + // Switch back to multisampled FBO and draw with coverage 1, verify that coverage was indeed 1. + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glSampleCoverage(1.0, false); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + + // Resolve + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve); + glClear(GL_COLOR_BUFFER_BIT); + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + + // Last draw happened with sample coverage 1, so we expect the results to be green. + glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + // Test that switching FBO attachments affects alpha-to-coverage TEST_P(StateChangeTestES3, AlphaToCoverageFramebufferAttachmentSwitch) { diff --git a/src/tests/gl_tests/SwizzleTest.cpp b/src/tests/gl_tests/SwizzleTest.cpp index 1429078b994..c1fc9f946c1 100644 --- a/src/tests/gl_tests/SwizzleTest.cpp +++ b/src/tests/gl_tests/SwizzleTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include diff --git a/src/tests/gl_tests/SyncQueriesTest.cpp b/src/tests/gl_tests/SyncQueriesTest.cpp deleted file mode 100644 index 66bd11413c6..00000000000 --- a/src/tests/gl_tests/SyncQueriesTest.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright 2016 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. -// - -// SyncQueriesTest.cpp: Tests of the GL_CHROMIUM_sync_query extension - -#include "test_utils/ANGLETest.h" - -namespace angle -{ - -class SyncQueriesTest : public ANGLETest<> -{ - protected: - SyncQueriesTest() - { - setWindowWidth(128); - setWindowHeight(128); - setConfigRedBits(8); - setConfigGreenBits(8); - setConfigBlueBits(8); - setConfigAlphaBits(8); - setConfigDepthBits(24); - } - - void testTearDown() override - { - if (mQuery != 0) - { - glDeleteQueriesEXT(1, &mQuery); - mQuery = 0; - } - } - - GLuint mQuery = 0; -}; - -// Test basic usage of sync queries -TEST_P(SyncQueriesTest, Basic) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_sync_query")); - - glGenQueriesEXT(1, &mQuery); - glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, mQuery); - EXPECT_GL_NO_ERROR(); - - glClearColor(0.0, 0.0, 1.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); - - glFlush(); - GLuint result = 0; - glGetQueryObjectuivEXT(mQuery, GL_QUERY_RESULT_EXT, &result); - EXPECT_GL_TRUE(result); - EXPECT_GL_NO_ERROR(); -} - -// Test that the sync query enums are not accepted unless the extension is available -TEST_P(SyncQueriesTest, Validation) -{ - // Need the GL_EXT_occlusion_query_boolean extension for the entry points - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean")); - - bool extensionAvailable = IsGLExtensionEnabled("GL_CHROMIUM_sync_query"); - - glGenQueriesEXT(1, &mQuery); - - glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, mQuery); - if (extensionAvailable) - { - EXPECT_GL_NO_ERROR(); - } - else - { - EXPECT_GL_ERROR(GL_INVALID_ENUM); - } - - glDeleteQueriesEXT(1, &mQuery); - - EXPECT_GL_NO_ERROR(); -} - -// Use this to select which configurations (e.g. which renderer, which GLES major version) these -// tests should be run against. -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SyncQueriesTest); - -} // namespace angle diff --git a/src/tests/gl_tests/TextureFixedRateCompressionTest.cpp b/src/tests/gl_tests/TextureFixedRateCompressionTest.cpp index d21a90cf226..72c3097b922 100644 --- a/src/tests/gl_tests/TextureFixedRateCompressionTest.cpp +++ b/src/tests/gl_tests/TextureFixedRateCompressionTest.cpp @@ -6,6 +6,10 @@ // TextureFixedRateCompressionTest: Tests for GL_EXT_texture_storage_compression +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -18,11 +22,39 @@ static constexpr GLint kDefaultAttribList[3][3] = { {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT, GL_NONE}, }; +// Return its name by value for easy printing +static const char *Name(int value) +{ +#define NAME(ERR) \ + case ERR: \ + return #ERR; + switch (value) + { + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_2BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_3BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_4BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_5BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_6BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_7BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_8BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_9BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_10BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_11BPC_EXT) + NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT) + } + return "UNKNOW"; +#undef NAME +} + class TextureFixedRateCompressionTest : public ANGLETest<> { protected: void invalidTestHelper(const GLint *attribs); void basicTestHelper(const GLint *attribs); + void RenderToTexture(const GLenum internalFormat, const GLint *attribs); }; void TextureFixedRateCompressionTest::invalidTestHelper(const GLint *attribs) @@ -127,6 +159,79 @@ TEST_P(TextureFixedRateCompressionTest, TexStorageAttribs2DEXT) } } +void TextureFixedRateCompressionTest::RenderToTexture(const GLenum internalFormat, + const GLint *attribs) +{ + GLint compressRate = 0; + ASSERT(attribs != nullptr); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ASSERT_GL_NO_ERROR(); + + glTexStorageAttribs2DEXT(GL_TEXTURE_2D, 1, internalFormat, 16, 16, attribs); + ASSERT_GL_NO_ERROR(); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + ASSERT_GL_NO_ERROR(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + ASSERT_GL_NO_ERROR(); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Query and check the compression rate + glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(compressRate, attribs[1]) + << "Compression rate of original texture: " << Name(compressRate); + + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0); + EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::red); + ASSERT_GL_NO_ERROR(); + + // Query and check the compression rate after render + glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate); + ASSERT_GL_NO_ERROR(); + ASSERT_EQ(compressRate, attribs[1]) + << "Compression rate of texture after render: " << Name(compressRate); +} + +// Test render to texture with fixed compression +TEST_P(TextureFixedRateCompressionTest, RenderToTexture) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage_compression")); + + static GLint attribList[] = {GL_SURFACE_COMPRESSION_EXT, + GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT, GL_NONE}; + GLint numRates = 0; + constexpr GLenum internalFormats[] = {GL_RGBA4, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8}; + + for (GLenum internalFormat : internalFormats) + { + // Test attrib list generated from internal format query. + glGetInternalformativ(GL_TEXTURE_2D, internalFormat, + GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT, 1, &numRates); + ASSERT_GL_NO_ERROR(); + if (numRates > 0) + { + std::vector rates(numRates); + glGetInternalformativ(GL_TEXTURE_2D, internalFormat, GL_SURFACE_COMPRESSION_EXT, + numRates, rates.data()); + ASSERT_GL_NO_ERROR(); + + for (int i = 0; i < numRates; ++i) + { + attribList[1] = rates[i]; + RenderToTexture(internalFormat, attribList); + } + } + } +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureFixedRateCompressionTest); // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES31_AND(TextureFixedRateCompressionTest); diff --git a/src/tests/gl_tests/TextureMultisampleTest.cpp b/src/tests/gl_tests/TextureMultisampleTest.cpp index 0a6aff02287..ef19e32b3ac 100644 --- a/src/tests/gl_tests/TextureMultisampleTest.cpp +++ b/src/tests/gl_tests/TextureMultisampleTest.cpp @@ -6,6 +6,10 @@ // TextureMultisampleTest: Tests of multisampled texture +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -471,6 +475,77 @@ TEST_P(TextureMultisampleTest, CheckSamplePositions) ASSERT_GL_NO_ERROR(); } +// Regression test for a bug in the Vulkan backend where a staged clear was not applied if +// glGetMultisamplefv is called. +TEST_P(TextureMultisampleTest, GetMultisamplefvAfterClear) +{ + ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported()); + + // OpenGL does not guarantee sample positions. + ANGLE_SKIP_TEST_IF(IsOpenGL()); + + GLint numSampleCounts = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, + &numSampleCounts); + ASSERT_GT(numSampleCounts, 0); + + GLint sampleCount = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 1, &sampleCount); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture); + texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture, + 0); + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + ASSERT_GL_NO_ERROR(); + + // Clear operation will be staged (Vulkan backend). + glClearColor(1.0f, 1.0f, 0.0, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + // Calling this API will perform draw framebuffer sync which will flush staged clear. + // If there is no bug, clear will not be deferred during the flush. + GLfloat samplePosition[2]; + getMultisamplefv(GL_SAMPLE_POSITION, 0, samplePosition); + ASSERT_GL_NO_ERROR(); + + ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(), + multisampleTextureFragmentShader()); + GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex"); + ASSERT_GE(texLocation, 0); + GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum"); + ASSERT_GE(sampleNumLocation, 0); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glViewport(0, 0, 1, 1); + + // Check that texture is cleared correctly. + glUseProgram(texelFetchProgram); + glUniform1i(texLocation, 0); + glUniform1i(sampleNumLocation, 0); + drawQuad(texelFetchProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer); + + // Modify the framebuffer. + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture2); + texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, + texture2, 0); + + // This call will perform draw framebuffer sync. + // In case of a bug, previously deferred clear will cause an ASSERT. + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); +} + // Test textureSize and texelFetch when using ANGLE_texture_multisample extension TEST_P(TextureMultisampleTest, SimpleTexelFetch) { diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp index 1675baa534e..6e51924b5f2 100644 --- a/src/tests/gl_tests/TextureTest.cpp +++ b/src/tests/gl_tests/TextureTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/mathutil.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -394,27 +398,45 @@ class Texture2DTestES3 : public Texture2DTest const char *getVertexShaderSource() override { - return "#version 300 es\n" - "out vec2 texcoord;\n" - "in vec4 position;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(position.xy, 0.0, 1.0);\n" - " texcoord = (position.xy * 0.5) + 0.5;\n" - "}\n"; + return R"(#version 300 es +out vec2 texcoord; +in vec4 position; +void main() +{ + gl_Position = vec4(position.xy, 0.0, 1.0); + texcoord = (position.xy * 0.5) + 0.5; +})"; } const char *getFragmentShaderSource() override { - return "#version 300 es\n" - "precision highp float;\n" - "uniform highp sampler2D tex;\n" - "in vec2 texcoord;\n" - "out vec4 fragColor;\n" - "void main()\n" - "{\n" - " fragColor = texture(tex, texcoord);\n" - "}\n"; + return R"(#version 300 es +precision highp float; +uniform highp sampler2D tex; +in vec2 texcoord; +out vec4 fragColor; +void main() +{ + fragColor = texture(tex, texcoord); +})"; + } + + const char *getExpensiveFragmentShaderSource() + { + return R"(#version 300 es +precision highp float; +uniform sampler2D tex; +in vec2 texcoord; +out vec4 fragColor; +void main() +{ + vec4 test = vec4(0.8, 0.8, 0.8, 0.8); + for (int i = 0; i < 500; i++) + { + test = sqrt(test); + } + fragColor = texture(tex, texcoord * test.xy); +})"; } void testSetUp() override @@ -935,7 +957,6 @@ class TextureCubeTest : public TexCoordDrawTest uniform samplerCube texCube; uniform int cubeFace; varying vec2 texcoord; - void main() { gl_FragColor = texture2D(tex2D, texcoord); @@ -995,10 +1016,39 @@ class TextureCubeTest : public TexCoordDrawTest GLint mTextureCubeFaceUniformLocation; }; +class TextureDefaultTextureTest : public TextureCubeTest +{ + protected: + TextureDefaultTextureTest() : TextureCubeTest() {} + + const char *getFragmentShaderSource() override + { + return + R"(precision highp float; + uniform samplerCube texCube; + uniform sampler2D tex2D; + uniform sampler2D white; + + void main() + { + vec4 whiteSamplerValue = texture2D(white, vec2(0)); + vec4 noValue = textureCube(texCube, vec3(0)); + vec4 noValue2 = texture2D(tex2D, vec2(0)); + gl_FragColor = whiteSamplerValue + noValue*0.000001 + noValue2*0.000001; + })"; + } + + void testSetUp() override { setUpProgram(); } + + void testTearDown() override { glDeleteProgram(mProgram); } +}; + class TextureCubeTestES3 : public TextureCubeTest { protected: TextureCubeTestES3() {} + + void incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain(GLint format); }; class TextureCubeTestES32 : public TextureCubeTest @@ -2336,6 +2386,53 @@ TEST_P(TextureCubeTest, CubeMapBug) EXPECT_GL_NO_ERROR(); } +// Duplicate of CubeMapBug test and change texture bind unit to trigger an ANGLE bug in validation +TEST_P(TextureCubeTest, CubeMapBug2) +{ + const char *vertexShaderSource = getVertexShaderSource(); + const char *fragmentShaderSource = R"(precision highp float; + uniform sampler2D tex2D; + uniform sampler2D tex2DUnused; + uniform samplerCube texCube; + uniform int cubeFace; + varying vec2 texcoord; + void main() + { + gl_FragColor = texture2D(tex2D, texcoord); + + vec2 scaled = vec2(1) - vec2(2) * texcoord.xy; + vec3 cubecoord = vec3(1, scaled.xy); + if (cubeFace == 1) + cubecoord = vec3(-1, scaled.xy); + else if (cubeFace == 2) + cubecoord = vec3(scaled.x, 1, scaled.y); + else if (cubeFace == 3) + cubecoord = vec3(scaled.x, -1, scaled.y); + else if (cubeFace == 4) + cubecoord = vec3(scaled.xy, 1); + else if (cubeFace == 5) + cubecoord = vec3(scaled.xy, -1); + + gl_FragColor += textureCube(texCube, cubecoord) + texture2D(tex2DUnused, texcoord); + })"; + ANGLE_GL_PROGRAM(cubeMapBug2Program, vertexShaderSource, fragmentShaderSource); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); + EXPECT_GL_ERROR(GL_NO_ERROR); + + glUseProgram(cubeMapBug2Program); + GLint tex2DUniformLocation = glGetUniformLocation(cubeMapBug2Program, "tex2D"); + ASSERT_NE(tex2DUniformLocation, -1); + GLint texCubeUniformLocation = glGetUniformLocation(cubeMapBug2Program, "texCube"); + ASSERT_NE(texCubeUniformLocation, -1); + glUniform1i(tex2DUniformLocation, 3); + glUniform1i(texCubeUniformLocation, 0); + drawQuad(cubeMapBug2Program, "position", 0.5f); + EXPECT_GL_NO_ERROR(); +} + // Test drawing with two texture types accessed from the same shader and check that the result of // drawing is correct. TEST_P(TextureCubeTest, CubeMapDraw) @@ -2813,8 +2910,9 @@ TEST_P(Texture2DTestES3, UnitTest_DMSAA_dst_read) // Create texture program ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); ASSERT_GL_NO_ERROR(); - GLint texLocation = glGetUniformLocation(drawTexture, "u_tex2D"); + GLint texLocation = glGetUniformLocation(drawTexture, essl1_shaders::Texture2DUniform()); ASSERT_NE(-1, texLocation); + glUseProgram(drawTexture); glUniform1i(texLocation, 0); glDisable(GL_BLEND); @@ -3741,434 +3839,932 @@ TEST_P(Texture2DTestES3, Texture1UploadThenTexture2UploadThenTexture1Delete) ASSERT_GL_NO_ERROR(); } -// Test that the driver performs a flush when there is a large amount of image updates. -TEST_P(Texture2DMemoryTestES3, TextureDataInLoopUntilFlush) +// Test uploading packed data to RGB565 images of various sizes and binding them to a framebuffer. +TEST_P(Texture2DTestES3, RGB565UploadPacked565Data) { - // Run this test for Vulkan only. - ANGLE_SKIP_TEST_IF(!IsVulkan()); + constexpr uint32_t kWidth1 = 4; + constexpr uint32_t kHeight1 = 4; + constexpr uint32_t kWidth2 = 3; + constexpr uint32_t kHeight2 = 6; + constexpr uint32_t kWidth3 = 19; + constexpr uint32_t kHeight3 = 13; - // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no - // submissions. - ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::SupportsHostImageCopy)); + // Since the upload data for the textures is continuous, the unpack alignment should be set to 1 + // (default is 4). + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLPerfMonitor monitor; - glBeginPerfMonitorAMD(monitor); + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + std::vector texColorYellow(kWidth1 * kHeight1, 0xFFE0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth1, kHeight1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColorYellow.data()); - uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth1, kHeight1, GLColor::yellow); - // Set up program - const char *kFS = R"(#version 300 es -precision highp float; -uniform uni { vec4 color; }; -out vec4 fragColor; -void main() -{ - fragColor = color; -})"; - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); - ASSERT_NE(program, 0u); + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColorCyan(kWidth2 * kHeight2, 0x7FF); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth2, kHeight2, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColorCyan.data()); - // Set up the uniform buffer and framebuffer - GLint uniformBufferIndex; - uniformBufferIndex = glGetUniformBlockIndex(program, "uni"); - ASSERT_NE(uniformBufferIndex, -1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth2, kHeight2, GLColor::cyan); - glClear(GL_COLOR_BUFFER_BIT); - constexpr size_t kBufferSize = 4 * 1024 * 1024; - std::vector floatData; - floatData.resize(kBufferSize / (sizeof(float)), 0.0f); - floatData[0] = 0.5f; - floatData[1] = 0.75f; - floatData[2] = 0.25f; - floatData[3] = 1.0f; + GLTexture texture3; + glBindTexture(GL_TEXTURE_2D, texture3); + std::vector texColorRed(kWidth3 * kHeight3, 0xF800); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth3, kHeight3, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth3, kHeight3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColorRed.data()); - GLBuffer uniformBuffer; - glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer); - glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer); - glUniformBlockBinding(program, uniformBufferIndex, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture3, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth3, kHeight3, GLColor::red); +} +// Test uploading byte data to RGB565 images of various sizes and binding them to a framebuffer. +TEST_P(Texture2DTestES3, RGB565UploadByteData) +{ + constexpr uint32_t kWidth1 = 4; + constexpr uint32_t kHeight1 = 4; + constexpr uint32_t kWidth2 = 6; + constexpr uint32_t kHeight2 = 3; + constexpr uint32_t kWidth3 = 13; + constexpr uint32_t kHeight3 = 19; + + // Since the upload data for the textures is continuous, the unpack alignment should be set to 1 + // (default is 4). GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // Create textures and draw - constexpr uint32_t kTextureWidth = 512; - constexpr uint32_t kTextureHeight = 512; - std::vector textureColor(kTextureWidth * kTextureHeight, GLColor::red); - constexpr uint32_t kIterationCount = 4096; - GLTexture textures[kIterationCount]; + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + std::vector texColorRed(kWidth1 * kHeight1, GLColorRGB::red); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth1, kHeight1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RGB, GL_UNSIGNED_BYTE, + texColorRed.data()); - for (auto &texture : textures) - { - glBindTexture(GL_TEXTURE_2D, texture); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureWidth, kTextureHeight); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RGBA, - GL_UNSIGNED_BYTE, textureColor.data()); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth1, kHeight1, GLColor::red); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColorBlue(kWidth2 * kHeight2, GLColorRGB::blue); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth2, kHeight2, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RGB, GL_UNSIGNED_BYTE, + texColorBlue.data()); - if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls) - { - break; - } - } - glEndPerfMonitorAMD(monitor); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth2, kHeight2, GLColor::blue); - EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1); + GLTexture texture3; + glBindTexture(GL_TEXTURE_2D, texture3); + std::vector texColorYellow(kWidth3 * kHeight3, GLColorRGB::yellow); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth3, kHeight3, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth3, kHeight3, GL_RGB, GL_UNSIGNED_BYTE, + texColorYellow.data()); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture3, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth3, kHeight3, GLColor::yellow); } -// Creating a texture and drawing with it in a loop without glFlush() should still work. Driver is -// supposedly to issue flush if needed. There should be no fallbacks to allocate outside the device -// memory. -TEST_P(Texture2DMemoryTestES3, TextureDataInLoopManyTimes) +// Test binding an RGB565 image to a framebuffer and rendering to it. +TEST_P(Texture2DTestES3, RGB565RenderToFBO) { - // Run this test for Vulkan only. - ANGLE_SKIP_TEST_IF(!IsVulkan()); + constexpr uint32_t kWidth = 5; + constexpr uint32_t kHeight = 9; - GLPerfMonitor monitor; - glBeginPerfMonitorAMD(monitor); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); - uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1; - uint64_t expectedDeviceMemoryFallbacks = getPerfCounters().deviceMemoryImageAllocationFallbacks; + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Set up program - const char *kFS = R"(#version 300 es -precision highp float; -uniform uni { vec4 color; }; -out vec4 fragColor; -void main() -{ - fragColor = color; -})"; - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); - ASSERT_NE(program, 0u); + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); - // Set up the uniform buffer and framebuffer - GLint uniformBufferIndex; - uniformBufferIndex = glGetUniformBlockIndex(program, "uni"); - ASSERT_NE(uniformBufferIndex, -1); + ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); +} - glClear(GL_COLOR_BUFFER_BIT); - constexpr size_t kBufferSize = 4 * 1024 * 1024; - std::vector floatData; - floatData.resize(kBufferSize / (sizeof(float)), 0.0f); - floatData[0] = 0.5f; - floatData[1] = 0.75f; - floatData[2] = 0.25f; - floatData[3] = 1.0f; +// Test binding an RGB565 image to a framebuffer, rendering to it, and sampling from it to render to +// an RGBA image. +TEST_P(Texture2DTestES3, RGB565RenderAndSampleToRenderToRGBA) +{ + constexpr uint32_t kWidth = 9; + constexpr uint32_t kHeight = 5; - GLBuffer uniformBuffer; - glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer); - glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer); - glUniformBlockBinding(program, uniformBufferIndex, 0); + // Render into the RGB565 texture. + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); GLFramebuffer fbo; glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Create textures and draw. We will use very small image updates to prevent flush before the - // device runs out of memory. - constexpr uint32_t kTextureWidth = 4096; - constexpr uint32_t kTextureHeight = 4096; - std::vector textureColor(kTextureWidth * kTextureHeight, GLColor::red); - constexpr uint32_t kIterationCount = 4096; + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); - uint32_t iteration = 0; - for (; iteration < kIterationCount; iteration++) - { - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - textureColor.data()); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + // Prepare the RGBA8 texture to be rendered into. + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColorBlue(kWidth * kHeight, GLColor::blue); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texColorBlue.data()); - if (getPerfCounters().commandQueueSubmitCallsTotal >= expectedSubmitCalls) - { - break; - } - } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); - glEndPerfMonitorAMD(monitor); - EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls) - << "iteration " << iteration; - EXPECT_EQ(getPerfCounters().deviceMemoryImageAllocationFallbacks, - expectedDeviceMemoryFallbacks); - ASSERT_GL_NO_ERROR(); + // Sample from the RGB565 to render into the RGBA8 texture. + glBindTexture(GL_TEXTURE_2D, texture1); + ANGLE_GL_PROGRAM(drawTex, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + drawQuad(drawTex, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); } -// Test functionality of GL_ANGLE_yuv_internal_format with min/mag filters -// set to nearest and linear modes. -TEST_P(Texture2DTestES3YUV, TexStorage2DYuvFilterModes) +// Test uploading data from a PBO to an RGB565 image and rendering with it. +TEST_P(Texture2DTestES3, RGB565UploadToPBOAndRender) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 16; - // Create YUV texture - GLTexture yuvTexture; - GLubyte yuvColor[] = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109}; - GLubyte expectedRgbColor[] = {0, 0, 255, 255}; - createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + GLTexture texture; + const std::vector texDataYellow(kWidth * kHeight, 0xFFE0); + const std::vector texDataBlue(kWidth * kHeight, 0x001F); - // Default is nearest filter mode - verifyResults2D(yuvTexture, expectedRgbColor); + glViewport(0, 0, kWidth, kHeight); + glBindTexture(GL_TEXTURE_2D, texture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB565, kWidth, kHeight); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texDataYellow.data()); ASSERT_GL_NO_ERROR(); - // Enable linear filter mode - glBindTexture(GL_TEXTURE_2D, yuvTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - verifyResults2D(yuvTexture, expectedRgbColor); + GLBuffer pbo; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * kWidth * kHeight, texDataBlue.data(), GL_STATIC_DRAW); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); ASSERT_GL_NO_ERROR(); - const int windowHeight = getWindowHeight(); - EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::blue, 1); - EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::blue, 1); - EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor::blue, 1); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); } -// Test functionality of GL_ANGLE_yuv_internal_format while cycling through RGB and YUV sources -TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvAndRgbSources) +// Test rendering to an RGB565 image and reading its content to a PBO in the packed RGB565 format. +TEST_P(Texture2DTestES3, RGB565RenderAndReadIntoRGB565PBO) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + constexpr uint32_t kWidth = 7; + constexpr uint32_t kHeight = 5; - // Create YUV texture - GLTexture yuvTexture; - GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109}; - GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; - createImmutableTexture2D(yuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); - // Create RGBA texture - GLTexture rgbaTexture; - GLubyte rgbaColor[4] = {0, 0, 255, 255}; - createImmutableTexture2D(rgbaTexture, 1, 1, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 1, rgbaColor); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Cycle through source textures - // RGBA source - verifyResults2D(rgbaTexture, rgbaColor); - ASSERT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); - // YUV source - verifyResults2D(yuvTexture, expectedRgbColor); - ASSERT_GL_NO_ERROR(); + // The pack alignment is set to 1 to avoid alignment gaps in the read data (default is 4). + GLBuffer pbo; + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); + glBufferData(GL_PIXEL_PACK_BUFFER, 2 * kWidth * kHeight, nullptr, GL_STREAM_READ); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr); + glFinish(); - // RGBA source - verifyResults2D(rgbaTexture, rgbaColor); - ASSERT_GL_NO_ERROR(); + auto pixels = reinterpret_cast( + glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 2 * kWidth * kHeight, GL_MAP_READ_BIT)); + for (uint32_t i = 0; i < kWidth * kHeight; i++) + { + EXPECT_EQ(pixels[i], 0xF800); + } } -// Test functionality of GL_ANGLE_yuv_internal_format with large number of YUV sources -TEST_P(Texture2DTestES3, TexStorage2DLargeYuvTextureCount) +// Test rendering to an RGB565 image and reading its content to a PBO in the RGBA8 format. +TEST_P(Texture2DTestES3, RGB565RenderAndReadIntoRGBA8PBO) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + constexpr uint32_t kWidth = 5; + constexpr uint32_t kHeight = 7; - constexpr uint32_t kTextureCount = 16; + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); - // Create YUV texture - GLTexture yuvTexture[kTextureCount]; - for (uint32_t i = 0; i < kTextureCount; i++) - { - // Create 2 plane YCbCr 420 texture - createImmutableTexture2D(yuvTexture[i], 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); - } + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Cycle through YUV source textures - glUseProgram(mProgram); - glUniform1i(mTexture2DUniformLocation, 0); + ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); - for (uint32_t i = 0; i < kTextureCount; i++) + // The pack alignment is set to 1 to avoid alignment gaps in the read data (default is 4). + GLBuffer pbo; + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); + glBufferData(GL_PIXEL_PACK_BUFFER, 4 * kWidth * kHeight, nullptr, GL_STREAM_READ); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glFinish(); + + auto pixels = reinterpret_cast( + glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 4 * kWidth * kHeight, GL_MAP_READ_BIT)); + for (uint32_t i = 0; i < 4 * kWidth * kHeight; i += 4) { - glBindTexture(GL_TEXTURE_2D, yuvTexture[i]); - drawQuad(mProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); + EXPECT_EQ(pixels[i + 0], 0); + EXPECT_EQ(pixels[i + 1], 0); + EXPECT_EQ(pixels[i + 2], 255); + EXPECT_EQ(pixels[i + 3], 255); } } -// Test functionality of GL_ANGLE_yuv_internal_format with simultaneous use of multiple YUV sources -TEST_P(Texture2DTestES3, TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData) +// Test rendering to an RGB565 image, and using glCopyTexSubImage2D() to copy the framebuffer to +// another RGB565 image. +TEST_P(Texture2DTestES3, RGB565RenderAndCopyTexSubImage) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + constexpr uint32_t kWidth = 11; + constexpr uint32_t kHeight = 6; - // Create YUV texture - // Create 2 plane YCbCr 420 texture - GLTexture twoPlaneYuvTexture; - createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); - // Create 3 plane YCbCr 420 texture - GLTexture threePlaneYuvTexture; - createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, - GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Cycle through YUV source textures - // Create program with 2 samplers - const char *vertexShaderSource = getVertexShaderSource(); - const char *fragmentShaderSource = R"(#version 300 es -precision highp float; -uniform sampler2D tex0; -uniform sampler2D tex1; -in vec2 texcoord; -out vec4 fragColor; + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); -void main() -{ - vec4 color0 = texture(tex0, texcoord); - vec4 color1 = texture(tex1, texcoord); - fragColor = color0 + color1; -})"; + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColor(kWidth * kHeight, 0x7FF); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColor.data()); - ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource); - glUseProgram(twoSamplersProgram); - GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0"); - ASSERT_NE(-1, tex0Location); - GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1"); - ASSERT_NE(-1, tex1Location); + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::cyan); - glUniform1i(tex0Location, 0); - glUniform1i(tex1Location, 1); + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kWidth, kHeight); - // Bind 2 plane YUV source - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - ASSERT_GL_NO_ERROR(); + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); +} - // Bind 3 plane YUV source - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); - ASSERT_GL_NO_ERROR(); +// Test rendering to an RGB565 image, and using glCopyTexImage2D() the framebuffer to another RGB565 +// image. +TEST_P(Texture2DTestES3, RGB565RenderAndCopyTexImage) +{ + constexpr uint32_t kWidth = 6; + constexpr uint32_t kHeight = 11; - drawQuad(twoSamplersProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + std::vector texColor1(kWidth * kHeight, 0xF800); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColor1.data()); - // Switch active texture index and draw again - // Bind 2 plane YUV source - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - ASSERT_GL_NO_ERROR(); + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); - // Bind 3 plane YUV source - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); - ASSERT_GL_NO_ERROR(); + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColor2(kWidth * kHeight, 0x7FF); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColor2.data()); - drawQuad(twoSamplersProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::cyan); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, 0, 0, kWidth, kHeight, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); } -// Test functional of GL_ANGLE_yuv_internal_format while cycling through YUV sources -TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvSourcesNoData) +// Test rendering to an RGBA8 image, and blitting the framebuffer to another framebuffer bound to an +// RGB565 image. +TEST_P(Texture2DTestES3, RenderRGBA8AndBlitToRGB565) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + constexpr uint32_t kWidth = 7; + constexpr uint32_t kHeight = 5; - // Create YUV texture - // Create 2 plane YCbCr 420 texture - GLTexture twoPlaneYuvTexture; - createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + // Render to the RGBA texture. + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); - // Create 3 plane YCbCr 420 texture - GLTexture threePlaneYuvTexture; - createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, - GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Cycle through YUV source textures - glUseProgram(mProgram); - glUniform1i(mTexture2DUniformLocation, 0); + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); - // 2 plane YUV source - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - drawQuad(mProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); + // Prepare the RGB565 texture. + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColor(kWidth * kHeight, 0x7FF); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColor.data()); - // 3 plane YUV source - glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); - drawQuad(mProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::cyan); - // 2 plane YUV source - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - drawQuad(mProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); + // Blit the RGBA framebuffer into the RGB565 one. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo2); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); } -// Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while -// switching sampler uniform values. -TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues) +// Test rendering to an RGB565 image, and blitting the framebuffer to another framebuffer bound to +// an RGBA8 image. +TEST_P(Texture2DTestES3, RenderRGB565AndBlitToRGBA8) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + constexpr uint32_t kWidth = 5; + constexpr uint32_t kHeight = 7; - // Create YUV texture - GLTexture yuvTexture; - GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109}; - GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; + // Render to the RGB565 texture. + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); - // Create YUV texture - // Create 2 plane YCbCr 420 texture - GLTexture twoPlaneYuvTexture; - createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); - // Create 3 plane YCbCr 420 texture - GLTexture threePlaneYuvTexture; - createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, - GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); - // Create program with 2 samplers - const char *vertexShaderSource = getVertexShaderSource(); - const char *fragmentShaderSource = R"(#version 300 es + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); + + // Prepare the RGB565 texture. + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColor(kWidth * kHeight, GLColor::yellow); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texColor.data()); + + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow); + + // Blit the RGB565 framebuffer into the RGBA one. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo2); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); +} + +// Test rendering to an RGB565 image, and blitting the framebuffer to another framebuffer bound to +// another RGB565 image. +TEST_P(Texture2DTestES3, RenderRGB565AndBlitToRGB565) +{ + constexpr uint32_t kWidth = 5; + constexpr uint32_t kHeight = 5; + + // Render to the first RGB565 texture. + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + nullptr); + + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + + // Prepare the second RGB565 texture. + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + std::vector texColor(kWidth * kHeight, 0x7FF); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, kWidth, kHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + texColor.data()); + + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::cyan); + + // Blit the first RGB565 framebuffer into the second one. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo2); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); +} + +// Test that the driver performs a flush when there is a large amount of image updates. +TEST_P(Texture2DMemoryTestES3, TextureDataInLoopUntilFlush) +{ + // Run this test for Vulkan only. + ANGLE_SKIP_TEST_IF(!IsVulkan()); + + // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no + // submissions. + ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::SupportsHostImageCopy)); + + GLPerfMonitor monitor; + glBeginPerfMonitorAMD(monitor); + + uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1; + + // Set up program + const char *kFS = R"(#version 300 es precision highp float; -uniform sampler2D tex0; -uniform sampler2D tex1; -uniform int texIndex; -in vec2 texcoord; +uniform uni { vec4 color; }; out vec4 fragColor; void main() { - vec4 color0 = texture(tex0, texcoord); - vec4 color1 = texture(tex1, texcoord); - if (texIndex == 0) + fragColor = color; +})"; + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + ASSERT_NE(program, 0u); + + // Set up the uniform buffer and framebuffer + GLint uniformBufferIndex; + uniformBufferIndex = glGetUniformBlockIndex(program, "uni"); + ASSERT_NE(uniformBufferIndex, -1); + + glClear(GL_COLOR_BUFFER_BIT); + constexpr size_t kBufferSize = 4 * 1024 * 1024; + std::vector floatData; + floatData.resize(kBufferSize / (sizeof(float)), 0.0f); + floatData[0] = 0.5f; + floatData[1] = 0.75f; + floatData[2] = 0.25f; + floatData[3] = 1.0f; + + GLBuffer uniformBuffer; + glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer); + glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer); + glUniformBlockBinding(program, uniformBufferIndex, 0); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Create textures and draw + constexpr uint32_t kTextureWidth = 512; + constexpr uint32_t kTextureHeight = 512; + std::vector textureColor(kTextureWidth * kTextureHeight, GLColor::red); + constexpr uint32_t kIterationCount = 4096; + GLTexture textures[kIterationCount]; + + for (auto &texture : textures) { - fragColor = color0; + glBindTexture(GL_TEXTURE_2D, texture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureWidth, kTextureHeight); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RGBA, + GL_UNSIGNED_BYTE, textureColor.data()); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + + if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls) + { + break; + } } - else + glEndPerfMonitorAMD(monitor); + + EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1); +} + +// Creating a texture and drawing with it in a loop without glFlush() should still work. Driver is +// supposedly to issue flush if needed. There should be no fallbacks to allocate outside the device +// memory. +TEST_P(Texture2DMemoryTestES3, TextureDataInLoopManyTimes) +{ + // Run this test for Vulkan only. + ANGLE_SKIP_TEST_IF(!IsVulkan()); + + GLPerfMonitor monitor; + glBeginPerfMonitorAMD(monitor); + + uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1; + uint64_t expectedDeviceMemoryFallbacks = getPerfCounters().deviceMemoryImageAllocationFallbacks; + + // Set up program + const char *kFS = R"(#version 300 es +precision highp float; +uniform uni { vec4 color; }; +out vec4 fragColor; +void main() +{ + fragColor = color; +})"; + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + ASSERT_NE(program, 0u); + + // Set up the uniform buffer and framebuffer + GLint uniformBufferIndex; + uniformBufferIndex = glGetUniformBlockIndex(program, "uni"); + ASSERT_NE(uniformBufferIndex, -1); + + glClear(GL_COLOR_BUFFER_BIT); + constexpr size_t kBufferSize = 4 * 1024 * 1024; + std::vector floatData; + floatData.resize(kBufferSize / (sizeof(float)), 0.0f); + floatData[0] = 0.5f; + floatData[1] = 0.75f; + floatData[2] = 0.25f; + floatData[3] = 1.0f; + + GLBuffer uniformBuffer; + glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer); + glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer); + glUniformBlockBinding(program, uniformBufferIndex, 0); + + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Create textures and draw. We will use very small image updates to prevent flush before the + // device runs out of memory. + constexpr uint32_t kTextureWidth = 4096; + constexpr uint32_t kTextureHeight = 4096; + std::vector textureColor(kTextureWidth * kTextureHeight, GLColor::red); + constexpr uint32_t kIterationCount = 4096; + + uint32_t iteration = 0; + for (; iteration < kIterationCount; iteration++) { - fragColor = color1; + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, + textureColor.data()); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + + if (getPerfCounters().commandQueueSubmitCallsTotal >= expectedSubmitCalls) + { + break; + } } -})"; - ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource); - glUseProgram(twoSamplersProgram); - GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0"); - ASSERT_NE(-1, tex0Location); - GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1"); - ASSERT_NE(-1, tex1Location); - GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex"); - ASSERT_NE(-1, texIndexLocation); - // Bind 2 plane YUV source - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - ASSERT_GL_NO_ERROR(); - // Bind 3 plane YUV source - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + + glEndPerfMonitorAMD(monitor); + EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls) + << "iteration " << iteration; + EXPECT_EQ(getPerfCounters().deviceMemoryImageAllocationFallbacks, + expectedDeviceMemoryFallbacks); ASSERT_GL_NO_ERROR(); +} - // Set sampler uniform values and draw - glUniform1i(tex0Location, 0); - glUniform1i(tex1Location, 1); - // Set texture index selector to the 2 plane texture unit - glUniform1i(texIndexLocation, 0); - drawQuad(twoSamplersProgram, "position", 0.5f); +// Test functionality of GL_ANGLE_yuv_internal_format with min/mag filters +// set to nearest and linear modes. +TEST_P(Texture2DTestES3YUV, TexStorage2DYuvFilterModes) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + // Create YUV texture + GLTexture yuvTexture; + GLubyte yuvColor[] = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109}; + GLubyte expectedRgbColor[] = {0, 0, 255, 255}; + createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + + // Default is nearest filter mode + verifyResults2D(yuvTexture, expectedRgbColor); ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2], - expectedRgbColor[3], 1); + + // Enable linear filter mode + glBindTexture(GL_TEXTURE_2D, yuvTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + verifyResults2D(yuvTexture, expectedRgbColor); + ASSERT_GL_NO_ERROR(); + + const int windowHeight = getWindowHeight(); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::blue, 1); + EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::blue, 1); + EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor::blue, 1); +} + +// Test functionality of GL_ANGLE_yuv_internal_format while cycling through RGB and YUV sources +TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvAndRgbSources) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + // Create YUV texture + GLTexture yuvTexture; + GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109}; + GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; + createImmutableTexture2D(yuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + + // Create RGBA texture + GLTexture rgbaTexture; + GLubyte rgbaColor[4] = {0, 0, 255, 255}; + createImmutableTexture2D(rgbaTexture, 1, 1, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 1, rgbaColor); + + // Cycle through source textures + // RGBA source + verifyResults2D(rgbaTexture, rgbaColor); + ASSERT_GL_NO_ERROR(); + + // YUV source + verifyResults2D(yuvTexture, expectedRgbColor); + ASSERT_GL_NO_ERROR(); + + // RGBA source + verifyResults2D(rgbaTexture, rgbaColor); + ASSERT_GL_NO_ERROR(); +} + +// Test functionality of GL_ANGLE_yuv_internal_format with large number of YUV sources +TEST_P(Texture2DTestES3, TexStorage2DLargeYuvTextureCount) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + constexpr uint32_t kTextureCount = 16; + + // Create YUV texture + GLTexture yuvTexture[kTextureCount]; + for (uint32_t i = 0; i < kTextureCount; i++) + { + // Create 2 plane YCbCr 420 texture + createImmutableTexture2D(yuvTexture[i], 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + } + + // Cycle through YUV source textures + glUseProgram(mProgram); + glUniform1i(mTexture2DUniformLocation, 0); + + for (uint32_t i = 0; i < kTextureCount; i++) + { + glBindTexture(GL_TEXTURE_2D, yuvTexture[i]); + drawQuad(mProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + } +} + +// Test functionality of GL_ANGLE_yuv_internal_format with simultaneous use of multiple YUV sources +TEST_P(Texture2DTestES3, TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + // Create YUV texture + // Create 2 plane YCbCr 420 texture + GLTexture twoPlaneYuvTexture; + createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + + // Create 3 plane YCbCr 420 texture + GLTexture threePlaneYuvTexture; + createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, + GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + + // Cycle through YUV source textures + // Create program with 2 samplers + const char *vertexShaderSource = getVertexShaderSource(); + const char *fragmentShaderSource = R"(#version 300 es +precision highp float; +uniform sampler2D tex0; +uniform sampler2D tex1; +in vec2 texcoord; +out vec4 fragColor; + +void main() +{ + vec4 color0 = texture(tex0, texcoord); + vec4 color1 = texture(tex1, texcoord); + fragColor = color0 + color1; +})"; + + ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource); + glUseProgram(twoSamplersProgram); + GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0"); + ASSERT_NE(-1, tex0Location); + GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1"); + ASSERT_NE(-1, tex1Location); + + glUniform1i(tex0Location, 0); + glUniform1i(tex1Location, 1); + + // Bind 2 plane YUV source + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + + // Bind 3 plane YUV source + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + + drawQuad(twoSamplersProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + + // Switch active texture index and draw again + // Bind 2 plane YUV source + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + + // Bind 3 plane YUV source + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + + drawQuad(twoSamplersProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); +} + +// Test functional of GL_ANGLE_yuv_internal_format while cycling through YUV sources +TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvSourcesNoData) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + // Create YUV texture + // Create 2 plane YCbCr 420 texture + GLTexture twoPlaneYuvTexture; + createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + + // Create 3 plane YCbCr 420 texture + GLTexture threePlaneYuvTexture; + createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, + GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + + // Cycle through YUV source textures + glUseProgram(mProgram); + glUniform1i(mTexture2DUniformLocation, 0); + + // 2 plane YUV source + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + drawQuad(mProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + + // 3 plane YUV source + glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + drawQuad(mProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + + // 2 plane YUV source + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + drawQuad(mProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); +} + +// Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while +// switching sampler uniform values. +TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + // Create YUV texture + GLTexture yuvTexture; + GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109}; + GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; + + // Create YUV texture + // Create 2 plane YCbCr 420 texture + GLTexture twoPlaneYuvTexture; + createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + // Create 3 plane YCbCr 420 texture + GLTexture threePlaneYuvTexture; + createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, + GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + // Create program with 2 samplers + const char *vertexShaderSource = getVertexShaderSource(); + const char *fragmentShaderSource = R"(#version 300 es +precision highp float; +uniform sampler2D tex0; +uniform sampler2D tex1; +uniform int texIndex; +in vec2 texcoord; +out vec4 fragColor; +void main() +{ + vec4 color0 = texture(tex0, texcoord); + vec4 color1 = texture(tex1, texcoord); + if (texIndex == 0) + { + fragColor = color0; + } + else + { + fragColor = color1; + } +})"; + ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource); + glUseProgram(twoSamplersProgram); + GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0"); + ASSERT_NE(-1, tex0Location); + GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1"); + ASSERT_NE(-1, tex1Location); + GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex"); + ASSERT_NE(-1, texIndexLocation); + // Bind 2 plane YUV source + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + // Bind 3 plane YUV source + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + + // Set sampler uniform values and draw + glUniform1i(tex0Location, 0); + glUniform1i(tex1Location, 1); + // Set texture index selector to the 2 plane texture unit + glUniform1i(texIndexLocation, 0); + drawQuad(twoSamplersProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2], + expectedRgbColor[3], 1); ASSERT_GL_NO_ERROR(); // Switch sampler uniform values and draw @@ -4194,1913 +4790,2800 @@ void main() ASSERT_GL_NO_ERROR(); } -// Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while -// switching bound textures. -TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchBoundTextures) +// Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while +// switching bound textures. +TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchBoundTextures) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + + // Create YUV texture + GLTexture yuvTexture; + GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109}; + GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; + + // Create YUV texture + // Create 2 plane YCbCr 420 texture + GLTexture twoPlaneYuvTexture; + createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + // Create 3 plane YCbCr 420 texture + GLTexture threePlaneYuvTexture; + createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, + GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); + // Create program with 2 samplers + const char *vertexShaderSource = getVertexShaderSource(); + const char *fragmentShaderSource = R"(#version 300 es +precision highp float; +uniform sampler2D tex0; +uniform sampler2D tex1; +uniform int texIndex; +in vec2 texcoord; +out vec4 fragColor; +void main() +{ + vec4 color0 = texture(tex0, texcoord); + vec4 color1 = texture(tex1, texcoord); + if (texIndex == 0) + { + fragColor = color0; + } + else + { + fragColor = color1; + } +})"; + ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource); + glUseProgram(twoSamplersProgram); + GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0"); + ASSERT_NE(-1, tex0Location); + GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1"); + ASSERT_NE(-1, tex1Location); + GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex"); + ASSERT_NE(-1, texIndexLocation); + // Set sampler uniform values + glUniform1i(tex0Location, 0); + glUniform1i(tex1Location, 1); + + // Bind 2 plane YUV source + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + // Bind 3 plane YUV source + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + // Set texture index selector to the 2 plane texture unit + glUniform1i(texIndexLocation, 0); + // Draw + drawQuad(twoSamplersProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2], + expectedRgbColor[3], 1); + ASSERT_GL_NO_ERROR(); + + // Bind 3 plane YUV source + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + // Bind 2 plane YUV source + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); + ASSERT_GL_NO_ERROR(); + // Set texture index selector to the 2 plane texture unit + glUniform1i(texIndexLocation, 1); + // Draw + drawQuad(twoSamplersProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2], + expectedRgbColor[3], 1); + ASSERT_GL_NO_ERROR(); +} + +// Test functionality of GL_ANGLE_yuv_internal_format glCopyTextureCHROMIUM +TEST_P(Texture2DTestES3YUV, CopyTextureChromium) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_copy_texture")); + + // Create YUV texture + GLTexture yuvTexture; + GLubyte yuvColor[] = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109}; + GLubyte expectedRgbColor[] = {0, 0, 255, 255}; + createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, + GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); + + verifyResults2D(yuvTexture, expectedRgbColor); + + // Create an RGBA texture to copy into + GLTexture rgbTexture; + glBindTexture(GL_TEXTURE_2D, rgbTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glCopyTextureCHROMIUM(yuvTexture, 0, GL_TEXTURE_2D, rgbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, + GL_FALSE, GL_FALSE, GL_FALSE); + verifyResults2D(rgbTexture, expectedRgbColor); + + ASSERT_GL_NO_ERROR(); +} +// Tests CopySubImage for float formats +TEST_P(Texture2DTest, CopySubImageFloat_R_R) +{ + testFloatCopySubImage(1, 1); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RG_R) +{ + testFloatCopySubImage(2, 1); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RG_RG) +{ + testFloatCopySubImage(2, 2); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGB_R) +{ + testFloatCopySubImage(3, 1); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG) +{ + testFloatCopySubImage(3, 2); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB) +{ + // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/40096350) + ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); + + testFloatCopySubImage(3, 3); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R) +{ + testFloatCopySubImage(4, 1); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG) +{ + testFloatCopySubImage(4, 2); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB) +{ + testFloatCopySubImage(4, 3); +} + +TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA) +{ + testFloatCopySubImage(4, 4); +} + +// Port of +// https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html +// Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly +// handles GL_ALPHA +TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE) +{ + const int npotTexSize = 5; + const int potTexSize = 4; // Should be less than npotTexSize + GLTexture tex2D; + + if (IsGLExtensionEnabled("GL_OES_texture_npot")) + { + // This test isn't applicable if texture_npot is enabled + return; + } + + setUpProgram(); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1. + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex2D); + + const std::vector pixels(1 * npotTexSize * npotTexSize, 64); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Check that an NPOT texture not on level 0 generates INVALID_VALUE + glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, + GL_UNSIGNED_BYTE, pixels.data()); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + // Check that an NPOT texture on level 0 succeeds + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, + GL_UNSIGNED_BYTE, pixels.data()); + EXPECT_GL_NO_ERROR(); + + // Check that generateMipmap fails on NPOT + glGenerateMipmap(GL_TEXTURE_2D); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + // Check that nothing is drawn if filtering is not correct for NPOT + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 1.0f); + EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255); + + // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 1.0f); + EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255); + + // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 1.0f); + EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64); + + // Check that glTexImage2D for POT texture succeeds + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, + pixels.data()); + EXPECT_GL_NO_ERROR(); + + // Check that generateMipmap for an POT texture succeeds + glGenerateMipmap(GL_TEXTURE_2D); + EXPECT_GL_NO_ERROR(); + + // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 1.0f); + EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64); + EXPECT_GL_NO_ERROR(); +} + +// Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions. +// ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect. +TEST_P(Texture2DTest, NPOTSubImageParameters) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + + // Create an 8x8 (i.e. power-of-two) texture. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D); + + // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture. + // This should always work, even if GL_OES_texture_npot isn't active. + std::array data; + glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, data.data()); + + EXPECT_GL_NO_ERROR(); +} + +// Regression test for https://crbug.com/1222516 to prevent integer overflow during validation. +TEST_P(Texture2DTest, SubImageValidationOverflow) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + EXPECT_GL_NO_ERROR(); + + glTexSubImage2D(GL_TEXTURE_2D, 0, -4, 0, 2147483647, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, -4, 1, 2147483647, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + EXPECT_GL_ERROR(GL_INVALID_VALUE); +} + +// Test that when a mutable texture is deleted, its corresponding pointer in the Vulkan backend, +// which is used for mutable texture flushing, is also deleted, and is not accessed by the new +// mutable texture after it. +TEST_P(Texture2DTest, MutableUploadThenDeleteThenMutableUpload) +{ + GLTexture texture1; + glBindTexture(GL_TEXTURE_2D, texture1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + GLColor::red.data()); + texture1.reset(); + EXPECT_GL_NO_ERROR(); + + GLTexture texture2; + glBindTexture(GL_TEXTURE_2D, texture2); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + GLColor::green.data()); + texture2.reset(); + EXPECT_GL_NO_ERROR(); +} + +// Test to ensure that glTexStorage3D accepts ASTC sliced 3D. https://crbug.com/1060012 +TEST_P(Texture3DTestES3, ImmutableASTCSliced3D) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d")); + + glBindTexture(GL_TEXTURE_3D, mTexture3D); + glTexStorage3D(GL_TEXTURE_3D, 1, GL_COMPRESSED_RGBA_ASTC_4x4, 4, 4, 1); + EXPECT_GL_NO_ERROR(); +} + +void FillLevel(GLint level, + GLuint width, + GLuint height, + const GLColor &color, + bool cubemap, + bool subTex) +{ + std::vector pixels(width * height, color); + std::vector targets; + if (cubemap) + { + targets = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}; + } + else + { + targets = {GL_TEXTURE_2D}; + } + + for (GLenum target : targets) + { + if (subTex) + { + glTexSubImage2D(target, level, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, + pixels.data()); + } + else + { + glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixels.data()); + } + } +} + +// This is part of tests that webgl_conformance_vulkan_passthrough_tests +// conformance/textures/misc/texture-size.html does +void Texture2DTest::testTextureSize(int testCaseIndex) +{ + std::array kNewMipColors = { + GLColor::green, GLColor::red, GLColor::blue, + GLColor::yellow, GLColor::magenta, GLColor::cyan, + }; + GLuint colorCount = 0; + + setUpProgram(); + + constexpr char kVS[] = + R"(precision highp float; +attribute vec4 position; +varying vec3 texcoord; +void main() +{ + gl_Position = position; + texcoord = (position.xyz * 0.5) + 0.5; +} +)"; + constexpr char kFS[] = + R"(precision mediump float; +uniform samplerCube tex; +varying vec3 texcoord; +void main() +{ + gl_FragColor = textureCube(tex, texcoord); +})"; + ANGLE_GL_PROGRAM(programCubeMap, kVS, kFS); + GLint textureCubeUniformLocation = glGetUniformLocation(programCubeMap, "tex"); + ASSERT_NE(-1, textureCubeUniformLocation); + ASSERT_GL_NO_ERROR(); + + GLint max2DSize = 0; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize); + GLint maxCubeMapSize = 0; + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapSize); + // Assuming 2048x2048xRGBA (22 mb with mips) will run on all WebGL platforms + GLint max2DSquareSize = std::min(max2DSize, 2048); + // I'd prefer this to be 2048 but that's 16 mb x 6 faces or 128 mb (with mips) + // 1024 is 33.5 mb (with mips) + maxCubeMapSize = std::min(maxCubeMapSize, 1024); + ASSERT_GL_NO_ERROR(); + + for (GLint size = 1; size <= max2DSize; size *= 2) + { + bool cubeMap = testCaseIndex == 3; + GLenum texTarget = cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + GLuint program = cubeMap ? programCubeMap : mProgram; + GLint texWidth = 0, texHeight = 0; + + switch (testCaseIndex) + { + case 0: + texWidth = size; + texHeight = 1; + break; + case 1: + texWidth = 1; + texHeight = size; + break; + case 2: + case 3: + texWidth = size; + texHeight = size; + break; + } + + if (texWidth == texHeight && size > max2DSquareSize) + { + return; + } + + if (cubeMap && size > maxCubeMapSize) + { + return; + } + + GLTexture texture; + glActiveTexture(GL_TEXTURE0); + glBindTexture(texTarget, texture); + FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false); + glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + ASSERT_GL_NO_ERROR(); + + glClear(GL_COLOR_BUFFER_BIT); + ASSERT_GL_NO_ERROR(); + + glUseProgram(program); + if (cubeMap) + { + glUniform1i(textureCubeUniformLocation, 0); + } + else + { + glUniform1i(mTexture2DUniformLocation, 0); + } + + drawQuad(program, "position", 1.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]); + + colorCount = (colorCount + 1) % kNewMipColors.size(); + FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false); + glGenerateMipmap(texTarget); + ASSERT_GL_NO_ERROR(); + + glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 1.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]); + + colorCount = (colorCount + 1) % kNewMipColors.size(); + FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, true); + glGenerateMipmap(texTarget); + + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, "position", 1.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]); + } +} + +void Texture2DTest::testTextureSizeError() +{ + GLint max2DSize = 0; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize); + glActiveTexture(GL_TEXTURE0); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + FillLevel(0, max2DSize, max2DSize, GLColor::red, false, false); + GLenum err = glGetError(); + bool passed = (err == GL_NO_ERROR || err == GL_OUT_OF_MEMORY); + ASSERT_TRUE(passed); +} + +// Permutation 0 of testTextureSize. +TEST_P(Texture2DTest, TextureSizeCase0) +{ + testTextureSize(0); +} + +// Permutation 1 of testTextureSize. +TEST_P(Texture2DTest, TextureSizeCase1) +{ + testTextureSize(1); +} + +// Permutation 2 of testTextureSize. +TEST_P(Texture2DTest, TextureSizeCase2) +{ + testTextureSize(2); +} + +// Permutation 3 of testTextureSize. +TEST_P(Texture2DTest, TextureSizeCase3) +{ + testTextureSize(3); +} + +// Test allocating a very large texture +TEST_P(Texture2DTest, TextureMaxSize) +{ + testTextureSizeError(); +} + +// Test that drawing works correctly RGBA 3D texture +TEST_P(Texture3DTestES2, RGBA) +{ + ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + + // http://anglebug.com/42264265 + ANGLE_SKIP_TEST_IF(IsOzone()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + std::vector texDataGreen(2u * 2u * 2u, GLColor::green); + std::vector texDataRed(1u * 1u * 1u, GLColor::red); + glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + EXPECT_GL_NO_ERROR(); + + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test that drawing works correctly Luminance 3D texture +TEST_P(Texture3DTestES2, Luminance) +{ + ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + + // http://anglebug.com/42264265 + ANGLE_SKIP_TEST_IF(IsOzone()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + std::vector texData(2u * 2u * 2u, 125); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + texData.data()); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + EXPECT_GL_NO_ERROR(); + + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(125, 125, 125, 255)); +} + +// Test that drawing works correctly with glCopyTexSubImage3D +TEST_P(Texture3DTestES2, CopySubImageRGBA) +{ + ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + + // http://anglebug.com/42264265 + ANGLE_SKIP_TEST_IF(IsOzone()); + + glClearColor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + std::vector texDataRed(4u * 4u * 4u, GLColor::red); + glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glTexImage3DOES(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + + EXPECT_GL_NO_ERROR(); + + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glUseProgram(mProgram); + glUniform1f(glGetUniformLocation(mProgram, "level"), 1); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); +} + +TEST_P(Texture3DTestES2, CopySubImageLuminance) +{ + ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + + // http://anglebug.com/42264265 + ANGLE_SKIP_TEST_IF(IsOzone()); + + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 4, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + nullptr); + glTexImage3DOES(GL_TEXTURE_3D, 1, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + nullptr); + glTexImage3DOES(GL_TEXTURE_3D, 2, GL_LUMINANCE, 1, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + nullptr); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + + EXPECT_GL_NO_ERROR(); + + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glUseProgram(mProgram); + glUniform1f(glGetUniformLocation(mProgram, "level"), 1); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); +} + +TEST_P(Texture3DTestES2, CopySubImageAlpha) +{ + ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + + // http://anglebug.com/42264265 + ANGLE_SKIP_TEST_IF(IsOzone()); + + glClearColor(1, 0, 0, 0.5); + glClear(GL_COLOR_BUFFER_BIT); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + glTexImage3DOES(GL_TEXTURE_3D, 0, GL_ALPHA, 4, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr); + glTexImage3DOES(GL_TEXTURE_3D, 1, GL_ALPHA, 2, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr); + glTexImage3DOES(GL_TEXTURE_3D, 2, GL_ALPHA, 1, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); + glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + + EXPECT_GL_NO_ERROR(); + + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glUseProgram(mProgram); + glUniform1f(glGetUniformLocation(mProgram, "level"), 1); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 128), 1.0); +} + +// Test that defining a 2D texture array fails with Texture3DOES on ES2. +TEST_P(Texture3DTestES2, DefineTexture2DArrayShouldFail) +{ + ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2); + + ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + + // http://anglebug.com/42264265 + ANGLE_SKIP_TEST_IF(IsOzone()); + + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + + glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + EXPECT_GL_ERROR(GL_INVALID_ENUM); +} + +// Verify shrinking a texture with glTexStorage2D works correctly +TEST_P(Texture2DTestES3, ChangeTexSizeWithTexStorage) +{ + // TODO: http://anglebug.com/42263810 + ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL()); + + constexpr uint32_t kSizeLarge = 128; + constexpr uint32_t kSizeSmall = 64; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // Create the texture with 'large' dimensions + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + ASSERT_GL_NO_ERROR(); + + GLFramebuffer destFbo; + glBindFramebuffer(GL_FRAMEBUFFER, destFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Draw with the new texture so it's created in the back end + ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + glUseProgram(blueProgram); + drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::blue); + + // Shrink the texture + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall); + ASSERT_GL_NO_ERROR(); + + // Create a source texture/FBO to blit from + GLTexture sourceTex; + glBindTexture(GL_TEXTURE_2D, sourceTex); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall); + ASSERT_GL_NO_ERROR(); + GLFramebuffer sourceFbo; + glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTex, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + // Fill the source texture with green + ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + glUseProgram(greenProgram); + drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::green); + + // Blit the source (green) to the destination + glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo); + glBlitFramebuffer(0, 0, kSizeSmall, kSizeSmall, 0, 0, kSizeSmall, kSizeSmall, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + + // Render to the default framebuffer sampling from the blited texture and verify it's green + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + glUseProgram(texProgram); + drawQuad(texProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green); +} + +// Regression test for http://crbug.com/949985 to make sure dirty bits are propagated up from +// TextureImpl and the texture is synced before being used in a draw call. +TEST_P(Texture2DTestES3, TextureImplPropagatesDirtyBits) +{ + ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL()); + // Flaky hangs on Win10 AMD RX 550 GL. http://anglebug.com/42262039 + ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL()); + // D3D Debug device reports an error. http://anglebug.com/40096590 + ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11()); + // Support copy from levels outside the image range. http://anglebug.com/42263331 + ANGLE_SKIP_TEST_IF(IsVulkan()); + + // The workaround in the GL backend required to trigger this bug generates driver warning + // messages. + ScopedIgnorePlatformMessages ignoreMessages; + + setUpProgram(); + glUseProgram(mProgram); + glActiveTexture(GL_TEXTURE0 + mTexture2DUniformLocation); + + GLTexture dest; + glBindTexture(GL_TEXTURE_2D, dest); + + GLTexture source; + glBindTexture(GL_TEXTURE_2D, source); + + // Put data in mip 0 and 1 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + GLColor::red.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + GLColor::green.data()); + + // Disable mipmapping so source is complete + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Force the dirty bits to be synchronized in source + drawQuad(mProgram, "position", 1.0f); + + // Copy from mip 1 of the source. In the GL backend this internally sets the base level to mip + // 1 and sets a dirty bit. + glCopyTextureCHROMIUM(source, 1, GL_TEXTURE_2D, dest, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE, + GL_FALSE, GL_FALSE); + + // Draw again, assertions are generated if the texture has internal dirty bits at draw time + drawQuad(mProgram, "position", 1.0f); +} + +// This test case changes the base level of a texture that's attached to a framebuffer, clears every +// level to green, and then samples the texture when rendering. Test is taken from +// https://www.khronos.org/registry/webgl/sdk/tests/conformance2/rendering/framebuffer-texture-changing-base-level.html +TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel) +{ + // TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/42262633 + ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD()); + + setUpProgram(); + + constexpr GLint width = 8; + constexpr GLint height = 4; + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level. + GLint level = 0; + GLint levelW = width; + GLint levelH = height; + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + while (levelW > 1 || levelH > 1) + { + ++level; + levelW = static_cast(std::max(1.0, std::floor(width / std::pow(2, level)))); + levelH = static_cast(std::max(1.0, std::floor(height / std::pow(2, level)))); + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + } + + // Clear each level of the texture using an FBO. Change the base level to match the level used + // for the FBO on each iteration. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + level = 0; + levelW = width; + levelH = height; + while (levelW > 1 || levelH > 1) + { + levelW = static_cast(std::floor(width / std::pow(2, level))); + levelH = static_cast(std::floor(height / std::pow(2, level))); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level); + + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + EXPECT_GL_NO_ERROR(); + + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + ++level; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, 16, 16); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + + drawQuad(mProgram, "position", 0.5f); + + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test that changing the base level of a texture after redefining a level outside the mip-chain +// preserves the other mips' data. +TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine) +{ + // http://anglebug.com/42263298 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); + + // http://anglebug.com/42263714 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsMac()); + + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + + std::array mipData; + fillMipData(mipData.data(), kMip0Size, kMipColors); + + for (size_t mip = 1; mip < kMipCount; ++mip) + { + glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA, + GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip)); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Mip 1 is green. Verify this. + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]); + + // http://anglebug.com/42263308 + ANGLE_SKIP_TEST_IF(IsOpenGL() && (IsIntel() || IsAMD()) && IsWindows()); + + // Add mip 0 and rebase the mip chain. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + mipData.data() + getMipDataOffset(kMip0Size, 0)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + + // Mip 1 should still be green. + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]); + + // Verify the other mips too. + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[2]); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[3]); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]); +} + +// Test that changing the base level of a texture multiple times preserves the data. +TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevel) +{ + testPingPongBaseLevel(false); +} +TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevelImmutable) +{ + testPingPongBaseLevel(true); +} +void Texture2DBaseMaxTestES3::testPingPongBaseLevel(bool immutable) +{ + // http://anglebug.com/42263310 + ANGLE_SKIP_TEST_IF(IsD3D()); + + // http://anglebug.com/42263311 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows()); + + // http://anglebug.com/42263301 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); + + initTest(immutable); + + // Ping pong a few times. + for (uint32_t tries = 0; tries < 2; ++tries) + { + // Rebase to different mips and verify mips. + for (uint32_t base = 0; base < kMipCount; ++base) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); + for (uint32_t lod = 0; lod < kMipCount - base; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]); + } + } + + // Rebase backwards and verify mips. + for (uint32_t base = kMipCount - 2; base > 0; --base) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); + for (uint32_t lod = 0; lod < kMipCount - base; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]); + } + } + } +} + +// Test that glTexSubImage2D after incompatibly redefining a mip level correctly applies the update +// after the redefine data. +TEST_P(Texture2DBaseMaxTestES3, SubImageAfterRedefine) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format")); - - // Create YUV texture - GLTexture yuvTexture; - GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109}; - GLubyte expectedRgbColor[4] = {0, 0, 255, 255}; + initTest(false); - // Create YUV texture - // Create 2 plane YCbCr 420 texture - GLTexture twoPlaneYuvTexture; - createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, - GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor); - // Create 3 plane YCbCr 420 texture - GLTexture threePlaneYuvTexture; - createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, - GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr); - // Create program with 2 samplers - const char *vertexShaderSource = getVertexShaderSource(); - const char *fragmentShaderSource = R"(#version 300 es -precision highp float; -uniform sampler2D tex0; -uniform sampler2D tex1; -uniform int texIndex; -in vec2 texcoord; -out vec4 fragColor; -void main() -{ - vec4 color0 = texture(tex0, texcoord); - vec4 color1 = texture(tex1, texcoord); - if (texIndex == 0) + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) { - fragColor = color0; + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); } - else + + // Redefine every level, followed by a glTexSubImage2D + const GLColor kNewMipColors[kMipCount] = { + GLColor::yellow, + GLColor::cyan, + GLColor(127, 0, 0, 255), + GLColor(0, 127, 0, 255), + }; + std::array newMipData; + fillMipData(newMipData.data(), kMip0Size * 2, kNewMipColors); + + const GLColor kSubImageMipColors[kMipCount] = { + GLColor(0, 0, 127, 255), + GLColor(127, 127, 0, 255), + GLColor(0, 127, 127, 255), + GLColor(127, 0, 127, 255), + }; + std::array subImageMipData; + fillMipData(subImageMipData.data(), kMip0Size, kSubImageMipColors); + + for (size_t mip = 0; mip < kMipCount; ++mip) { - fragColor = color1; - } -})"; - ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource); - glUseProgram(twoSamplersProgram); - GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0"); - ASSERT_NE(-1, tex0Location); - GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1"); - ASSERT_NE(-1, tex1Location); - GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex"); - ASSERT_NE(-1, texIndexLocation); - // Set sampler uniform values - glUniform1i(tex0Location, 0); - glUniform1i(tex1Location, 1); + // Redefine the level. + size_t newMipSize = (kMip0Size * 2) >> mip; + glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, newMipSize, newMipSize, 0, GL_RGBA, + GL_UNSIGNED_BYTE, newMipData.data() + getMipDataOffset(kMip0Size * 2, mip)); - // Bind 2 plane YUV source - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - ASSERT_GL_NO_ERROR(); - // Bind 3 plane YUV source - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); - ASSERT_GL_NO_ERROR(); - // Set texture index selector to the 2 plane texture unit - glUniform1i(texIndexLocation, 0); - // Draw - drawQuad(twoSamplersProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2], - expectedRgbColor[3], 1); - ASSERT_GL_NO_ERROR(); + // Immediately follow that with a subimage update. + glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA, + GL_UNSIGNED_BYTE, + subImageMipData.data() + getMipDataOffset(kMip0Size, mip)); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1); - // Bind 3 plane YUV source - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture); - ASSERT_GL_NO_ERROR(); - // Bind 2 plane YUV source - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture); - ASSERT_GL_NO_ERROR(); - // Set texture index selector to the 2 plane texture unit - glUniform1i(texIndexLocation, 1); - // Draw - drawQuad(twoSamplersProgram, "position", 0.5f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2], - expectedRgbColor[3], 1); - ASSERT_GL_NO_ERROR(); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kSubImageMipColors[lod]); + EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColors[lod]); + EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColors[lod]); + EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColors[lod]); + } } -// Tests CopySubImage for float formats -TEST_P(Texture2DTest, CopySubImageFloat_R_R) +// Test that incompatibly redefining a level then redefining it back to its original size works. +TEST_P(Texture2DBaseMaxTestES3, IncompatiblyRedefineLevelThenRevert) { - testFloatCopySubImage(1, 1); -} + initTest(false); -TEST_P(Texture2DTest, CopySubImageFloat_RG_R) -{ - testFloatCopySubImage(2, 1); -} + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + } -TEST_P(Texture2DTest, CopySubImageFloat_RG_RG) -{ - testFloatCopySubImage(2, 2); -} + // Redefine Mip 1 to be larger. + constexpr size_t kLargeMip1Size = getMipDataSize(kMip0Size * 2, 1); + std::array interimMipData; + std::fill(interimMipData.data(), interimMipData.data() + kLargeMip1Size, GLColor::yellow); -TEST_P(Texture2DTest, CopySubImageFloat_RGB_R) -{ - testFloatCopySubImage(3, 1); -} + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + interimMipData.data()); -TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG) -{ - testFloatCopySubImage(3, 2); -} + // Redefine Mip 1 back to its original size. + constexpr size_t kNormalMip1Size = getMipDataSize(kMip0Size, 1); + std::array newMipData; + std::fill(newMipData.data(), newMipData.data() + kNormalMip1Size, GLColor::cyan); -TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB) -{ - // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/40096350) - ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size / 2, kMip0Size / 2, 0, GL_RGBA, + GL_UNSIGNED_BYTE, newMipData.data()); - testFloatCopySubImage(3, 3); + // Verify texture colors. + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, lod == 1 ? GLColor::cyan : kMipColors[lod]); + } } -TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R) +// Test that redefining every level of a texture to another format works. The format uses more +// bits per component, to ensure alignment requirements for the new format are taken into account. +TEST_P(Texture2DBaseMaxTestES3, RedefineEveryLevelToAnotherFormat) { - testFloatCopySubImage(4, 1); -} + initTest(false); -TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG) -{ - testFloatCopySubImage(4, 2); + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + } + + const GLColor32F kNewMipColors[kMipCount] = { + GLColor32F(1.0, 1.0, 0.0, 1.0f), + GLColor32F(1.0, 0.0, 1.0, 1.0f), + GLColor32F(0.0, 1.0, 1.0, 1.0f), + GLColor32F(1.0, 1.0, 1.0, 1.0f), + }; + + std::array newMipData; + fillMipData(newMipData.data(), kMip0Size, kNewMipColors); + + // Redefine every level with the new format. + for (size_t mip = 0; mip < kMipCount; ++mip) + { + glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA32F, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA, + GL_FLOAT, newMipData.data() + getMipDataOffset(kMip0Size, mip)); + } + + // Verify texture colors. + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + + GLColor32F mipColor32F = kNewMipColors[lod]; + GLColor mipColor(static_cast(std::roundf(mipColor32F.R * 255)), + static_cast(std::roundf(mipColor32F.G * 255)), + static_cast(std::roundf(mipColor32F.B * 255)), + static_cast(std::roundf(mipColor32F.A * 255))); + + EXPECT_PIXEL_COLOR_EQ(0, 0, mipColor); + } } -TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB) +// Test that generating mipmaps after change base level. +TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebase) { - testFloatCopySubImage(4, 3); + // http://anglebug.com/42264421 + ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); + + testGenerateMipmapAfterRebase(false); } -TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA) +TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebaseImmutable) { - testFloatCopySubImage(4, 4); + // http://anglebug.com/42263310 + ANGLE_SKIP_TEST_IF(IsD3D()); + // http://anglebug.com/42264332 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA()); + // http://anglebug.com/42264421 + ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); + + testGenerateMipmapAfterRebase(true); } -// Port of -// https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html -// Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly -// handles GL_ALPHA -TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE) +void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable) { - const int npotTexSize = 5; - const int potTexSize = 4; // Should be less than npotTexSize - GLTexture tex2D; + initTest(immutable); - if (IsGLExtensionEnabled("GL_OES_texture_npot")) + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) { - // This test isn't applicable if texture_npot is enabled - return; + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); } - setUpProgram(); - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1. - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex2D); - - const std::vector pixels(1 * npotTexSize * npotTexSize, 64); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Check that an NPOT texture not on level 0 generates INVALID_VALUE - glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, - GL_UNSIGNED_BYTE, pixels.data()); - EXPECT_GL_ERROR(GL_INVALID_VALUE); + // Update level 1 (any level would do other than 0) with new data + const GLColor kNewMipColor = GLColor::yellow; + std::array> 1, 0)> newMipData; + std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); - // Check that an NPOT texture on level 0 succeeds - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, - GL_UNSIGNED_BYTE, pixels.data()); - EXPECT_GL_NO_ERROR(); + glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kMip0Size >> 1, kMip0Size >> 1, GL_RGBA, + GL_UNSIGNED_BYTE, newMipData.data()); - // Check that generateMipmap fails on NPOT + // Change base level and max level and then generate mipmaps. This should redefine level 1 and 2 + // with kNewMipColor and leave levels 0 and 3 unchanged. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 2); glGenerateMipmap(GL_TEXTURE_2D); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1); - // Check that nothing is drawn if filtering is not correct for NPOT - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(mProgram, "position", 1.0f); - EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + if (lod == 0) + { + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod; + } + else if (lod == kMipCount - 1) + { + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod; + } + else + { + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod; + EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod; + } + } +} - // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(mProgram, "position", 1.0f); - EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255); +// Test that generating mipmaps after incompatibly redefining a level works. +TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefine) +{ + initTest(false); - // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(mProgram, "position", 1.0f); - EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64); + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + } - // Check that glTexImage2D for POT texture succeeds - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, - pixels.data()); - EXPECT_GL_NO_ERROR(); + // Redefine level 1 (any level would do other than 0) to an incompatible size, say the same size + // as level 0. + const GLColor kNewMipColor = GLColor::yellow; + std::array newMipData; + std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); - // Check that generateMipmap for an POT texture succeeds + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + newMipData.data()); + + // Generate mipmaps. This should redefine level 1 back to being compatible with level 0. glGenerateMipmap(GL_TEXTURE_2D); - EXPECT_GL_NO_ERROR(); - // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(mProgram, "position", 1.0f); - EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64); - EXPECT_GL_NO_ERROR(); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]); + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]); + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]); + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]); + } } -// Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions. -// ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect. -TEST_P(Texture2DTest, NPOTSubImageParameters) +// Test that generating mipmaps after incompatibly redefining a level while simultaneously changing +// the base level works. +TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefineAndRebase) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); + ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL()); - // Create an 8x8 (i.e. power-of-two) texture. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glGenerateMipmap(GL_TEXTURE_2D); + // http://crbug.com/1100613 + ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); - // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture. - // This should always work, even if GL_OES_texture_npot isn't active. - std::array data; - glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, data.data()); + // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs. + ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); - EXPECT_GL_NO_ERROR(); -} + initTest(false); -// Regression test for https://crbug.com/1222516 to prevent integer overflow during validation. -TEST_P(Texture2DTest, SubImageValidationOverflow) -{ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << lod; + } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_NO_ERROR(); + // Redefine level 2 to an incompatible size, say the same size as level 0. + const GLColor kNewMipColor = GLColor::yellow; + std::array newMipData; + std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); - glTexSubImage2D(GL_TEXTURE_2D, 0, -4, 0, 2147483647, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_ERROR(GL_INVALID_VALUE); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + newMipData.data()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, -4, 1, 2147483647, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_ERROR(GL_INVALID_VALUE); -} + // Set base level of the texture to 1 then generate mipmaps. Level 2 that's redefined should + // go back to being compatibly defined. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glGenerateMipmap(GL_TEXTURE_2D); -// Test that when a mutable texture is deleted, its corresponding pointer in the Vulkan backend, -// which is used for mutable texture flushing, is also deleted, and is not accessed by the new -// mutable texture after it. -TEST_P(Texture2DTest, MutableUploadThenDeleteThenMutableUpload) -{ - GLTexture texture1; - glBindTexture(GL_TEXTURE_2D, texture1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - GLColor::red.data()); - texture1.reset(); - EXPECT_GL_NO_ERROR(); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]) << lod; + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[1]) << lod; + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[1]) << lod; + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[1]) << lod; + } - GLTexture texture2; - glBindTexture(GL_TEXTURE_2D, texture2); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - GLColor::green.data()); - texture2.reset(); - EXPECT_GL_NO_ERROR(); -} + // Redefine level 1 (current base level) to an incompatible size. + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + newMipData.data()); -// Test to ensure that glTexStorage3D accepts ASTC sliced 3D. https://crbug.com/1060012 -TEST_P(Texture3DTestES3, ImmutableASTCSliced3D) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d")); + // Set base level of the texture back to 0 then generate mipmaps. Level 1 should go back to + // being compatibly defined. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - glTexStorage3D(GL_TEXTURE_3D, 1, GL_COMPRESSED_RGBA_ASTC_4x4, 4, 4, 1); - EXPECT_GL_NO_ERROR(); + // Test that the texture looks as expected. + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]) << lod; + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]) << lod; + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]) << lod; + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]) << lod; + } } -void FillLevel(GLint level, - GLuint width, - GLuint height, - const GLColor &color, - bool cubemap, - bool subTex) +// Test that generating mipmaps after incompatibly redefining the base level of the texture works. +TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBase) { - std::vector pixels(width * height, color); - std::vector targets; - if (cubemap) - { - targets = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}; - } - else - { - targets = {GL_TEXTURE_2D}; - } + initTest(false); - for (GLenum target : targets) + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) { - if (subTex) - { - glTexSubImage2D(target, level, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, - pixels.data()); - } - else - { - glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixels.data()); - } + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); } -} -// This is part of tests that webgl_conformance_vulkan_passthrough_tests -// conformance/textures/misc/texture-size.html does -void Texture2DTest::testTextureSize(int testCaseIndex) -{ - std::array kNewMipColors = { - GLColor::green, GLColor::red, GLColor::blue, - GLColor::yellow, GLColor::magenta, GLColor::cyan, - }; - GLuint colorCount = 0; + // Redefine level 0 to an incompatible size. + const GLColor kNewMipColor = GLColor::yellow; + std::array newMipData; + std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); - setUpProgram(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA, + GL_UNSIGNED_BYTE, newMipData.data()); - constexpr char kVS[] = - R"(precision highp float; -attribute vec4 position; -varying vec3 texcoord; -void main() -{ - gl_Position = position; - texcoord = (position.xyz * 0.5) + 0.5; + // Generate mipmaps. + glGenerateMipmap(GL_TEXTURE_2D); + + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod < kMipCount + 1; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor); + EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor); + EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor); + EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor); + } } -)"; - constexpr char kFS[] = - R"(precision mediump float; -uniform samplerCube tex; -varying vec3 texcoord; -void main() -{ - gl_FragColor = textureCube(tex, texcoord); -})"; - ANGLE_GL_PROGRAM(programCubeMap, kVS, kFS); - GLint textureCubeUniformLocation = glGetUniformLocation(programCubeMap, "tex"); - ASSERT_NE(-1, textureCubeUniformLocation); - ASSERT_GL_NO_ERROR(); - GLint max2DSize = 0; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize); - GLint maxCubeMapSize = 0; - glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapSize); - // Assuming 2048x2048xRGBA (22 mb with mips) will run on all WebGL platforms - GLint max2DSquareSize = std::min(max2DSize, 2048); - // I'd prefer this to be 2048 but that's 16 mb x 6 faces or 128 mb (with mips) - // 1024 is 33.5 mb (with mips) - maxCubeMapSize = std::min(maxCubeMapSize, 1024); - ASSERT_GL_NO_ERROR(); +// Test that generating mipmaps after incompatibly redefining the base level while simultaneously +// changing MAX_LEVEL works. +TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBaseAndChangingMax) +{ + initTest(false); - for (GLint size = 1; size <= max2DSize; size *= 2) + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) { - bool cubeMap = testCaseIndex == 3; - GLenum texTarget = cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - GLuint program = cubeMap ? programCubeMap : mProgram; - GLint texWidth = 0, texHeight = 0; + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + } - switch (testCaseIndex) - { - case 0: - texWidth = size; - texHeight = 1; - break; - case 1: - texWidth = 1; - texHeight = size; - break; - case 2: - case 3: - texWidth = size; - texHeight = size; - break; - } + // Redefine level 0 to an incompatible size. + const GLColor kNewMipColor = GLColor::yellow; + std::array newMipData; + std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); - if (texWidth == texHeight && size > max2DSquareSize) - { - return; - } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA, + GL_UNSIGNED_BYTE, newMipData.data()); - if (cubeMap && size > maxCubeMapSize) - { - return; - } + // Set max level of the texture to 2 then generate mipmaps. + constexpr uint32_t kMaxLevel = 2; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMaxLevel); + glGenerateMipmap(GL_TEXTURE_2D); - GLTexture texture; - glActiveTexture(GL_TEXTURE0); - glBindTexture(texTarget, texture); - FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false); - glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - ASSERT_GL_NO_ERROR(); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod <= kMaxLevel; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor); + EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor); + EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor); + EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor); + } +} - glClear(GL_COLOR_BUFFER_BIT); - ASSERT_GL_NO_ERROR(); +// Test that stage invalid texture levels work. +TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels) +{ + constexpr uint32_t kMaxLevel = 2; + const GLColor kMipColor[kMaxLevel + 1] = {GLColor::red, GLColor::green, GLColor::blue}; - glUseProgram(program); - if (cubeMap) - { - glUniform1i(textureCubeUniformLocation, 0); - } - else - { - glUniform1i(mTexture2DUniformLocation, 0); - } + initTest(false); - drawQuad(program, "position", 1.0f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); - colorCount = (colorCount + 1) % kNewMipColors.size(); - FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false); - glGenerateMipmap(texTarget); - ASSERT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + std::vector texDataCyan(2u * 2u, GLColor::cyan); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataCyan.data()); + setLodUniform(0); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); - glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(program, "position", 1.0f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]); + std::vector texDataGreen(2u * 2u, GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); - colorCount = (colorCount + 1) % kNewMipColors.size(); - FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, true); - glGenerateMipmap(texTarget); + std::vector texDataRed(4u * 4u, GLColor::red); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(program, "position", 1.0f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod <= kMaxLevel; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColor[lod]); + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColor[lod]); + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColor[lod]); + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColor[lod]); } } -void Texture2DTest::testTextureSizeError() +// Test redefine a mutable texture into an immutable texture. +TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable) { - GLint max2DSize = 0; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize); - glActiveTexture(GL_TEXTURE0); - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - FillLevel(0, max2DSize, max2DSize, GLColor::red, false, false); - GLenum err = glGetError(); - bool passed = (err == GL_NO_ERROR || err == GL_OUT_OF_MEMORY); - ASSERT_TRUE(passed); -} + // http://anglebug.com/42263310 + ANGLE_SKIP_TEST_IF(IsD3D()); -// Permutation 0 of testTextureSize. -TEST_P(Texture2DTest, TextureSizeCase0) -{ - testTextureSize(0); -} + // http://anglebug.com/42263301 + ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); -// Permutation 1 of testTextureSize. -TEST_P(Texture2DTest, TextureSizeCase1) -{ - testTextureSize(1); -} + constexpr uint32_t kBaseLevel = 1; + const GLColor kNewMipColors[kMipCount] = { + GLColor::yellow, + GLColor::cyan, + GLColor::white, + GLColor(127u, 127u, 127u, 255u), + }; -// Permutation 2 of testTextureSize. -TEST_P(Texture2DTest, TextureSizeCase2) -{ - testTextureSize(2); -} + initTest(false); -// Permutation 3 of testTextureSize. -TEST_P(Texture2DTest, TextureSizeCase3) -{ - testTextureSize(3); -} + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel); -// Test allocating a very large texture -TEST_P(Texture2DTest, TextureMaxSize) -{ - testTextureSizeError(); + // Test that all mips have the expected data + for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod) + { + setLodUniform(lod - kBaseLevel); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + } + + glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size); + std::array mipData; + fillMipData(mipData.data(), kMip0Size, kNewMipColors); + for (size_t mip = 0; mip < kMipCount; ++mip) + { + glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA, + GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip)); + } + + // Test that all enabled mips have the expected data + for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod) + { + setLodUniform(lod - kBaseLevel); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + for (uint32_t lod = 0; lod < kBaseLevel; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]); + } } -// Test that drawing works correctly RGBA 3D texture -TEST_P(Texture3DTestES2, RGBA) +// Test that redefine a level with incompatible size beyond the max level. +TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel) { - ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + initTest(false); - // http://anglebug.com/42264265 - ANGLE_SKIP_TEST_IF(IsOzone()); + // Test that all mips have the expected data initially (this makes sure the texture image is + // created already). + for (uint32_t lod = 0; lod < kMipCount; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - std::vector texDataGreen(2u * 2u * 2u, GLColor::green); - std::vector texDataRed(1u * 1u * 1u, GLColor::red); - glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataRed.data()); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + uint32_t maxLevel = 1; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel); - EXPECT_GL_NO_ERROR(); + // Update level 0 + const GLColor kNewMipLevle0Color = GLColor::yellow; + std::array newMipData; + std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE, + newMipData.data()); - drawQuad(mProgram, "position", 0.5f); + // Update level 2 with incompatible data + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, + newMipData.data()); + EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + // Test that the texture looks as expected. + const int w = getWindowWidth() - 1; + const int h = getWindowHeight() - 1; + for (uint32_t lod = 0; lod < maxLevel; ++lod) + { + setLodUniform(lod); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + if (lod == 0) + { + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color); + EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color); + EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color); + EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color); + } + else + { + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]); + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]); + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]); + } + } } -// Test that drawing works correctly Luminance 3D texture -TEST_P(Texture3DTestES2, Luminance) +// Test that rendering to a framebuffer succeeds when base level > max level and the attachment +// level equals the base level. This verifies that the framebuffer is complete and can be rendered +// to without crashing. +TEST_P(Texture2DBaseMaxTestES3, BaseExceedsMaxFboAttachAtBase) { - ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + // Use simple shader that outputs green + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); - // http://anglebug.com/42264265 - ANGLE_SKIP_TEST_IF(IsOzone()); + // Set up mutable texture with mipmap filter + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - std::vector texData(2u * 2u * 2u, 125); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - texData.data()); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // Fill texture with red initially + std::vector redPixels0(4, GLColor::red); // 2x2 = 4 pixels for level 0 + std::vector redPixels1(1, GLColor::red); // 1x1 = 1 pixel for level 1 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels0.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels1.data()); - EXPECT_GL_NO_ERROR(); + // Base level > max level + const GLint baseLevel = 1; + const GLint maxLevel = 0; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel); - drawQuad(mProgram, "position", 0.5f); + // Set up framebuffer object and attach texture at same level as base + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + const GLint attachmentLevel = baseLevel; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, + attachmentLevel); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(125, 125, 125, 255)); + // Framebuffer is complete (attachment == base, even though base > max) + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + // Render green to the framebuffer + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true); + EXPECT_GL_NO_ERROR(); + + // Verify green was written + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that drawing works correctly with glCopyTexSubImage3D -TEST_P(Texture3DTestES2, CopySubImageRGBA) +// Test that the framebuffer is incomplete when base level > max level and the attachment level +// does not equal the base level. Drawing to an incomplete framebuffer should fail. +TEST_P(Texture2DBaseMaxTestES3, BaseExceedsMaxFboAttachNotAtBase) { - ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); - - // http://anglebug.com/42264265 - ANGLE_SKIP_TEST_IF(IsOzone()); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); - glClearColor(0, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT); + // Set up mutable texture with mipmap filter + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - std::vector texDataRed(4u * 4u * 4u, GLColor::red); - glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataRed.data()); - glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataRed.data()); - glTexImage3DOES(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataRed.data()); - glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); - glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + // Fill texture with red + std::vector redPixels0(4, GLColor::red); // 2x2 = 4 pixels for level 0 + std::vector redPixels1(1, GLColor::red); // 1x1 = 1 pixel for level 1 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels0.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels1.data()); - EXPECT_GL_NO_ERROR(); + // Base level > max level + const GLint baseLevel = 1; + const GLint maxLevel = 0; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel); - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + // Set up framebuffer object and attach texture at different level than base + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + const GLint attachmentLevel = 0; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, + attachmentLevel); - glUseProgram(mProgram); - glUniform1f(glGetUniformLocation(mProgram, "level"), 1); - drawQuad(mProgram, "position", 0.5f); + // Framebuffer is incomplete (attachment != base when base > max) + EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + // Drawing to an incomplete framebuffer should generate an error + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true); + EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); } -TEST_P(Texture3DTestES2, CopySubImageLuminance) +// Port test from web_gl/conformance2/textures/misc/fuzz-545-immutable-tex-render-feedback.html. +// What this tries to do is create a render feedback loop and ensure it is not crashing. +TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback) { - ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - // http://anglebug.com/42264265 - ANGLE_SKIP_TEST_IF(IsOzone()); + constexpr GLint MIPS = 3; + constexpr GLint SIZE = 10; - glClearColor(1, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); + GLTexture immutTex; + glBindTexture(GL_TEXTURE_2D, immutTex); + glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, SIZE, SIZE); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 4, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - nullptr); - glTexImage3DOES(GL_TEXTURE_3D, 1, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - nullptr); - glTexImage3DOES(GL_TEXTURE_3D, 2, GL_LUMINANCE, 1, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - nullptr); - glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); - glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + GLTexture mutTex; + glBindTexture(GL_TEXTURE_2D, mutTex); + for (GLint mip = 0; mip < MIPS; mip++) + { + const GLint size = SIZE >> mip; + glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + } + + constexpr GLenum MAG_FILTERS[] = {GL_LINEAR, GL_NEAREST}; + constexpr GLenum MIN_FILTERS[] = { + GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, + GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST}; - EXPECT_GL_NO_ERROR(); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + const GLuint texs[] = {immutTex, mutTex}; + for (const GLuint tex : texs) + { + glBindTexture(GL_TEXTURE_2D, tex); - glUseProgram(mProgram); - glUniform1f(glGetUniformLocation(mProgram, "level"), 1); - drawQuad(mProgram, "position", 0.5f); + for (GLint level_prime_base = 0; level_prime_base < (MIPS + 1); level_prime_base++) + { // `level_base` in GLES + // ES 3.0.6 p150 + GLint _level_base = level_prime_base; + if (tex == immutTex) + { + _level_base = std::min(_level_base, MIPS - 1); + } + const GLint level_base = _level_base; - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); -} + for (GLint _level_prime_max = (level_prime_base > 0 ? level_prime_base - 1 : 0); + _level_prime_max < (MIPS + 2); _level_prime_max++) + { // `q` in GLES + const GLint level_prime_max = (_level_prime_max == (MIPS + 1)) + ? 10000 // This is the default, after all! + : _level_prime_max; -TEST_P(Texture3DTestES2, CopySubImageAlpha) -{ - ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + // ES 3.0.6 p150 + GLint _level_max = level_prime_max; + if (tex == immutTex) + { + _level_max = std::min(std::max(level_base, level_prime_max), MIPS - 1); + } + const GLint level_max = _level_max; - // http://anglebug.com/42264265 - ANGLE_SKIP_TEST_IF(IsOzone()); + const GLint p = std::floor((float)std::log2(SIZE)) + level_base; + const GLint q = std::min(p, level_max); - glClearColor(1, 0, 0, 0.5); - glClear(GL_COLOR_BUFFER_BIT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level_prime_base); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level_prime_max); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - glTexImage3DOES(GL_TEXTURE_3D, 0, GL_ALPHA, 4, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr); - glTexImage3DOES(GL_TEXTURE_3D, 1, GL_ALPHA, 2, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr); - glTexImage3DOES(GL_TEXTURE_3D, 2, GL_ALPHA, 1, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr); - glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); - glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + const bool mipComplete = (q <= MIPS - 1); - EXPECT_GL_NO_ERROR(); + for (const GLenum minFilter : MIN_FILTERS) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + for (const GLenum magFilter : MAG_FILTERS) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); - glUseProgram(mProgram); - glUniform1f(glGetUniformLocation(mProgram, "level"), 1); - drawQuad(mProgram, "position", 0.5f); + for (GLint dstMip = 0; dstMip < (MIPS + 1); dstMip++) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tex, dstMip); - EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 128), 1.0); -} + // ES3.0 p213-214 + bool fbComplete = true; -// Test that defining a 2D texture array fails with Texture3DOES on ES2. -TEST_P(Texture3DTestES2, DefineTexture2DArrayShouldFail) -{ - ANGLE_SKIP_TEST_IF(!hasTexture3DExt()); + // * "The width and height of `image` are non-zero" + fbComplete &= (0 <= dstMip && dstMip <= MIPS - 1); - // http://anglebug.com/42264265 - ANGLE_SKIP_TEST_IF(IsOzone()); + if (tex != immutTex) + { // "...does not name an immutable-format texture..." + // * "...the value of [level] must be in the range `[level_base, + // q]`" + fbComplete &= + (level_base == dstMip || (level_base <= dstMip && dstMip <= q)); - glClearColor(1, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); + // * "...the value of [level] is not `level_base`, then the texture + // must be mipmap complete" + if (dstMip != level_base) + { + fbComplete &= mipComplete; + } + } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D); - EXPECT_GL_ERROR(GL_INVALID_ENUM); + // - + GLenum expectError = 0; + GLenum expectStatus = GL_FRAMEBUFFER_COMPLETE; + if (!fbComplete) + { + expectStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + expectError = GL_INVALID_FRAMEBUFFER_OPERATION; + } - glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - EXPECT_GL_ERROR(GL_INVALID_ENUM); + // - + EXPECT_GLENUM_EQ(expectStatus, + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true); + EXPECT_EQ(expectError, glGetError()); + } + } + } + } + } + } } -// Verify shrinking a texture with glTexStorage2D works correctly -TEST_P(Texture2DTestES3, ChangeTexSizeWithTexStorage) +// Test sampling from a texture of a (usually) not color-renderable +// base format with a color-renderable level beyond the max level. +TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableWithColorRenderableBeyondMaxLevel) { - // TODO: http://anglebug.com/42263810 - ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL()); - - constexpr uint32_t kSizeLarge = 128; - constexpr uint32_t kSizeSmall = 64; + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Create the texture with 'large' dimensions - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); + const GLuint data[4] = {0xC0040200, 0xC0040200, 0xC0040200, 0xC0040200}; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); ASSERT_GL_NO_ERROR(); - GLFramebuffer destFbo; - glBindFramebuffer(GL_FRAMEBUFFER, destFbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - - // Draw with the new texture so it's created in the back end - ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); - glUseProgram(blueProgram); - drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::blue); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); +} - // Shrink the texture - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall); - ASSERT_GL_NO_ERROR(); +// Test sampling from a texture of a depth-renderable base format +// with a color-renderable level beyond the max level. +TEST_P(Texture2DBaseMaxTestES3, DepthRenderableWithColorRenderableBeyondMaxLevel) +{ + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - // Create a source texture/FBO to blit from - GLTexture sourceTex; - glBindTexture(GL_TEXTURE_2D, sourceTex); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall); - ASSERT_GL_NO_ERROR(); - GLFramebuffer sourceFbo; - glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTex, 0); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Fill the source texture with green - ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); - glUseProgram(greenProgram); - drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); - ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::green); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Blit the source (green) to the destination - glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo); - glBlitFramebuffer(0, 0, kSizeSmall, kSizeSmall, 0, 0, kSizeSmall, kSizeSmall, - GL_COLOR_BUFFER_BIT, GL_NEAREST); + const GLfloat data[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + data); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); ASSERT_GL_NO_ERROR(); - // Render to the default framebuffer sampling from the blited texture and verify it's green - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - glUseProgram(texProgram); - drawQuad(texProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f); - EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); } -// Regression test for http://crbug.com/949985 to make sure dirty bits are propagated up from -// TextureImpl and the texture is synced before being used in a draw call. -TEST_P(Texture2DTestES3, TextureImplPropogatesDirtyBits) +// Test texture sampling while changing the base format from color-renderable +// to (usually) not color-renderable by manipulating base and max levels. +TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableAfterColorRenderableBelowBaseLevel) { - ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL()); - // Flaky hangs on Win10 AMD RX 550 GL. http://anglebug.com/42262039 - ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL()); - // D3D Debug device reports an error. http://anglebug.com/40096590 - ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11()); - // Support copy from levels outside the image range. http://anglebug.com/42263331 - ANGLE_SKIP_TEST_IF(IsVulkan()); - - // The workaround in the GL backend required to trigger this bug generates driver warning - // messages. - ScopedIgnorePlatformMessages ignoreMessages; - - setUpProgram(); - glUseProgram(mProgram); - glActiveTexture(GL_TEXTURE0 + mTexture2DUniformLocation); - - GLTexture dest; - glBindTexture(GL_TEXTURE_2D, dest); - - GLTexture source; - glBindTexture(GL_TEXTURE_2D, source); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - // Put data in mip 0 and 1 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - GLColor::red.data()); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - GLColor::green.data()); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Disable mipmapping so source is complete - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + std::array data0; + data0.fill(GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data()); - // Force the dirty bits to be synchronized in source - drawQuad(mProgram, "position", 1.0f); + const GLuint data1[1] = {0xC0040200}; + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data1); + ASSERT_GL_NO_ERROR(); - // Copy from mip 1 of the source. In the GL backend this internally sets the base level to mip - // 1 and sets a dirty bit. - glCopyTextureCHROMIUM(source, 1, GL_TEXTURE_2D, dest, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE, - GL_FALSE, GL_FALSE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - // Draw again, assertions are generated if the texture has internal dirty bits at draw time - drawQuad(mProgram, "position", 1.0f); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); } -// This test case changes the base level of a texture that's attached to a framebuffer, clears every -// level to green, and then samples the texture when rendering. Test is taken from -// https://www.khronos.org/registry/webgl/sdk/tests/conformance2/rendering/framebuffer-texture-changing-base-level.html -TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel) +// Test texture sampling while changing the base format from color-renderable +// to depth-renderable by manipulating base and max levels. +TEST_P(Texture2DBaseMaxTestES3, DepthRenderableAfterColorRenderableBelowBaseLevel) { - // TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/42262633 - ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD()); - - setUpProgram(); - - constexpr GLint width = 8; - constexpr GLint height = 4; + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); GLTexture texture; glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level. - GLint level = 0; - GLint levelW = width; - GLint levelH = height; - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - while (levelW > 1 || levelH > 1) - { - ++level; - levelW = static_cast(std::max(1.0, std::floor(width / std::pow(2, level)))); - levelH = static_cast(std::max(1.0, std::floor(height / std::pow(2, level)))); - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - } + std::array data0; + data0.fill(GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data()); - // Clear each level of the texture using an FBO. Change the base level to match the level used - // for the FBO on each iteration. - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - level = 0; - levelW = width; - levelH = height; - while (levelW > 1 || levelH > 1) - { - levelW = static_cast(std::floor(width / std::pow(2, level))); - levelH = static_cast(std::floor(height / std::pow(2, level))); + const GLfloat data1[1] = {1.0f}; + glTexImage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + data1); + ASSERT_GL_NO_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); - EXPECT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); +} - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); +// Test that the following scenario works: +// - change a texture's max level to 0. +// - clear the texture with glClear. +// - sample the texture and draw to another FBO. +// - draw to the texture again. +// - The texture's final color should be clear color in 1st pass + draw color. +TEST_P(Texture2DBaseMaxTestES3, SetMaxLevelToZeroThenClearThenSampleThenDraw) +{ + ANGLE_GL_PROGRAM(textureProgram, angle::essl3_shaders::vs::Texture2DLod(), + angle::essl3_shaders::fs::Texture2DLod()); + ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(), + angle::essl1_shaders::fs::Blue()); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - ++level; - } + // 1. Change the texture's max level to 0. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + EXPECT_GL_NO_ERROR(); + + // 2. Attach the texture to a FBO and clear it. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + EXPECT_GL_NO_ERROR(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 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 the bound texture to default FBO. glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, 16, 16); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(textureProgram); + drawQuad(textureProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); - drawQuad(mProgram, "position", 0.5f); + // 4. Draw to the texture again + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glUseProgram(blueProgram); + drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); + // Expect the final color to be accumulated color EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255)); } -// Test that changing the base level of a texture after redefining a level outside the mip-chain -// preserves the other mips' data. -TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine) +// Test that the following scenario works: +// - change a texture's max level to 1. +// - clear the texture with glClear. +// - change the texture's max level to 0. +// - sample the texture and draw to another FBO. +// - draw to the texture again. +// - The texture's final color should be clear color in 1st pass + draw color. +TEST_P(Texture2DBaseMaxTestES3, SetMaxLevelToOneThenClearThenSetMaxLevelToZeroThenSampleThenDraw) { - // http://anglebug.com/42263298 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); - - // http://anglebug.com/42263714 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsMac()); - - GLFramebuffer framebuffer; - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + ANGLE_GL_PROGRAM(textureProgram, angle::essl3_shaders::vs::Texture2DLod(), + angle::essl3_shaders::fs::Texture2DLod()); + ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(), + angle::essl1_shaders::fs::Blue()); GLTexture texture; glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - std::array mipData; - fillMipData(mipData.data(), kMip0Size, kMipColors); - - for (size_t mip = 1; mip < kMipCount; ++mip) - { - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA, - GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip)); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - - // Mip 1 is green. Verify this. - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]); - - // http://anglebug.com/42263308 - ANGLE_SKIP_TEST_IF(IsOpenGL() && (IsIntel() || IsAMD()) && IsWindows()); - - // Add mip 0 and rebase the mip chain. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - mipData.data() + getMipDataOffset(kMip0Size, 0)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + // 1. Change the texture's max level to 1. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + EXPECT_GL_NO_ERROR(); - // Mip 1 should still be green. - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]); + // 2. Attach the texture to a FBO and clear it. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + EXPECT_GL_NO_ERROR(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 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); - // Verify the other mips too. - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[2]); + // 3. Change the texture's max level to 0. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[3]); + // 4. Draw the bound texture to default FBO. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(textureProgram); + drawQuad(textureProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + // 5. Draw to the texture again + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glUseProgram(blueProgram); + drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]); + // Expect the final color to be accumulated color + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255)); } -// Test that changing the base level of a texture multiple times preserves the data. -TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevel) -{ - testPingPongBaseLevel(false); -} -TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevelImmutable) -{ - testPingPongBaseLevel(true); -} -void Texture2DBaseMaxTestES3::testPingPongBaseLevel(bool immutable) +// Test to check that texture completeness is determined correctly when the texture base level is +// greater than 0, and also that level 0 is not sampled when base level is greater than 0. +TEST_P(Texture2DTestES3, DrawWithBaseLevel1) { - // http://anglebug.com/42263310 - ANGLE_SKIP_TEST_IF(IsD3D()); - - // http://anglebug.com/42263311 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows()); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); - // http://anglebug.com/42263301 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); + std::vector texDataRed(4u * 4u, GLColor::red); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + std::vector texDataGreen(2u * 2u, GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - initTest(immutable); + EXPECT_GL_NO_ERROR(); - // Ping pong a few times. - for (uint32_t tries = 0; tries < 2; ++tries) - { - // Rebase to different mips and verify mips. - for (uint32_t base = 0; base < kMipCount; ++base) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); - for (uint32_t lod = 0; lod < kMipCount - base; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]); - } - } + drawQuad(mProgram, "position", 0.5f); - // Rebase backwards and verify mips. - for (uint32_t base = kMipCount - 2; base > 0; --base) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); - for (uint32_t lod = 0; lod < kMipCount - base; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]); - } - } - } + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that glTexSubImage2D after incompatibly redefining a mip level correctly applies the update -// after the redefine data. -TEST_P(Texture2DBaseMaxTestES3, SubImageAfterRedefine) +void Texture2DTestES3::testCopyImage(const APIExtensionVersion usedExtension) { - initTest(false); + ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - } + std::vector texDataRed(4u * 4u, GLColor::red); + GLTexture srcTexture; + GLTexture destTexture; - // Redefine every level, followed by a glTexSubImage2D - const GLColor kNewMipColors[kMipCount] = { - GLColor::yellow, - GLColor::cyan, - GLColor(127, 0, 0, 255), - GLColor(0, 127, 0, 255), - }; - std::array newMipData; - fillMipData(newMipData.data(), kMip0Size * 2, kNewMipColors); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, destTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - const GLColor kSubImageMipColors[kMipCount] = { - GLColor(0, 0, 127, 255), - GLColor(127, 127, 0, 255), - GLColor(0, 127, 127, 255), - GLColor(127, 0, 127, 255), - }; - std::array subImageMipData; - fillMipData(subImageMipData.data(), kMip0Size, kSubImageMipColors); + std::vector texDataGreen(4u * 4u, GLColor::green); + glBindTexture(GL_TEXTURE_2D, srcTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - for (size_t mip = 0; mip < kMipCount; ++mip) - { - // Redefine the level. - size_t newMipSize = (kMip0Size * 2) >> mip; - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, newMipSize, newMipSize, 0, GL_RGBA, - GL_UNSIGNED_BYTE, newMipData.data() + getMipDataOffset(kMip0Size * 2, mip)); + glBindTexture(GL_TEXTURE_2D, 0); - // Immediately follow that with a subimage update. - glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA, - GL_UNSIGNED_BYTE, - subImageMipData.data() + getMipDataOffset(kMip0Size, mip)); + // copy + if (usedExtension == APIExtensionVersion::OES) + { + glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0, + 2, 2, 0, 2, 2, 1); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1); - - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod < kMipCount; ++lod) + else { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kSubImageMipColors[lod]); - EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColors[lod]); - EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColors[lod]); - EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColors[lod]); + glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0, + 2, 2, 0, 2, 2, 1); } + glBindTexture(GL_TEXTURE_2D, destTexture); + EXPECT_GL_NO_ERROR(); + + glViewport(0, 0, 4, 4); + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red); } -// Test that incompatibly redefining a level then redefining it back to its original size works. -TEST_P(Texture2DBaseMaxTestES3, IncompatiblyRedefineLevelThenRevert) +void MultisampleTexture2DTestES31::testCopyMultisampleImage(const APIExtensionVersion usedExtension, + const GLenum internalFormat) { - initTest(false); - - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - } + ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); - // Redefine Mip 1 to be larger. - constexpr size_t kLargeMip1Size = getMipDataSize(kMip0Size * 2, 1); - std::array interimMipData; - std::fill(interimMipData.data(), interimMipData.data() + kLargeMip1Size, GLColor::yellow); + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - interimMipData.data()); + GLTexture srcTexture; + GLTexture destTexture; + const GLenum target = GL_TEXTURE_2D_MULTISAMPLE; - // Redefine Mip 1 back to its original size. - constexpr size_t kNormalMip1Size = getMipDataSize(kMip0Size, 1); - std::array newMipData; - std::fill(newMipData.data(), newMipData.data() + kNormalMip1Size, GLColor::cyan); + GLint maxSamples = 0; + glGetInternalformativ(target, internalFormat, GL_SAMPLES, 1, &maxSamples); + EXPECT_GL_NO_ERROR(); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size / 2, kMip0Size / 2, 0, GL_RGBA, - GL_UNSIGNED_BYTE, newMipData.data()); + glActiveTexture(GL_TEXTURE0); + glBindTexture(target, destTexture); + glTexStorage2DMultisample(target, maxSamples, internalFormat, 4, 4, false); + EXPECT_GL_NO_ERROR(); - // Verify texture colors. - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, lod == 1 ? GLColor::cyan : kMipColors[lod]); - } -} + glBindTexture(target, srcTexture); + glTexStorage2DMultisample(target, maxSamples, internalFormat, 4, 4, false); + EXPECT_GL_NO_ERROR(); -// Test that redefining every level of a texture to another format works. The format uses more -// bits per component, to ensure alignment requirements for the new format are taken into account. -TEST_P(Texture2DBaseMaxTestES3, RedefineEveryLevelToAnotherFormat) -{ - initTest(false); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, srcTexture, 0); + EXPECT_GL_NO_ERROR(); - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - } + // Draw red into the source texture + glViewport(0, 0, 4, 4); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - const GLColor32F kNewMipColors[kMipCount] = { - GLColor32F(1.0, 1.0, 0.0, 1.0f), - GLColor32F(1.0, 0.0, 1.0, 1.0f), - GLColor32F(0.0, 1.0, 1.0, 1.0f), - GLColor32F(1.0, 1.0, 1.0, 1.0f), - }; + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); - std::array newMipData; - fillMipData(newMipData.data(), kMip0Size, kNewMipColors); + glBindTexture(target, 0); - // Redefine every level with the new format. - for (size_t mip = 0; mip < kMipCount; ++mip) + // Copy + if (usedExtension == APIExtensionVersion::OES) { - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA32F, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA, - GL_FLOAT, newMipData.data() + getMipDataOffset(kMip0Size, mip)); + glCopyImageSubDataOES(srcTexture, target, 0, 0, 0, 0, destTexture, target, 0, 0, 0, 0, 4, 4, + 1); } - - // Verify texture colors. - for (uint32_t lod = 0; lod < kMipCount; ++lod) + else { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + glCopyImageSubDataEXT(srcTexture, target, 0, 0, 0, 0, destTexture, target, 0, 0, 0, 0, 4, 4, + 1); + } + EXPECT_GL_NO_ERROR(); - GLColor32F mipColor32F = kNewMipColors[lod]; - GLColor mipColor(static_cast(std::roundf(mipColor32F.R * 255)), - static_cast(std::roundf(mipColor32F.G * 255)), - static_cast(std::roundf(mipColor32F.B * 255)), - static_cast(std::roundf(mipColor32F.A * 255))); + // Resolve the target texture + GLTexture resolveTexture; + glBindTexture(GL_TEXTURE_2D, resolveTexture); + glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 4, 4); - EXPECT_PIXEL_COLOR_EQ(0, 0, mipColor); - } -} + GLFramebuffer resolveFbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, + 0); -// Test that generating mipmaps after change base level. -TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebase) -{ - // http://anglebug.com/42264421 - ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, destTexture, 0); + ASSERT_GL_NO_ERROR(); + glCheckFramebufferStatus(GL_FRAMEBUFFER); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - testGenerateMipmapAfterRebase(false); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, resolveFbo); + EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red); } -TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebaseImmutable) +void MultisampleTexture2DTestES31::testCopyMultisampleArrayImage( + const APIExtensionVersion usedExtension, + const GLenum internalFormat) { - // http://anglebug.com/42263310 - ANGLE_SKIP_TEST_IF(IsD3D()); - // http://anglebug.com/42264332 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA()); - // http://anglebug.com/42264421 - ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array")); + + ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); + + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + + GLTexture srcTexture; + GLTexture destTexture; + + GLint maxSamples = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalFormat, GL_SAMPLES, 1, &maxSamples); + EXPECT_GL_NO_ERROR(); - testGenerateMipmapAfterRebase(true); -} + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, destTexture); + glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamples, internalFormat, 4, + 4, 3, false); + EXPECT_GL_NO_ERROR(); -void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable) -{ - initTest(immutable); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, srcTexture); + glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamples, internalFormat, 4, + 4, 3, false); + EXPECT_GL_NO_ERROR(); - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - } + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 1); + EXPECT_GL_NO_ERROR(); - // Update level 1 (any level would do other than 0) with new data - const GLColor kNewMipColor = GLColor::yellow; - std::array> 1, 0)> newMipData; - std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); + // Draw red into the source texture layer 1 + glViewport(0, 0, 4, 4); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kMip0Size >> 1, kMip0Size >> 1, GL_RGBA, - GL_UNSIGNED_BYTE, newMipData.data()); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); - // Change base level and max level and then generate mipmaps. This should redefine level 1 and 2 - // with kNewMipColor and leave levels 0 and 3 unchanged. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 2); - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0); - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod < kMipCount; ++lod) + // Copy + if (usedExtension == APIExtensionVersion::OES) { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - if (lod == 0) - { - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod; - } - else if (lod == kMipCount - 1) - { - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod; - } - else - { - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod; - EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod; - } + glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 1, + destTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 2, 4, 4, + 1); } -} - -// Test that generating mipmaps after incompatibly redefining a level works. -TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefine) -{ - initTest(false); - - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) + else { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 1, + destTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 2, 4, 4, + 1); } + EXPECT_GL_NO_ERROR(); - // Redefine level 1 (any level would do other than 0) to an incompatible size, say the same size - // as level 0. - const GLColor kNewMipColor = GLColor::yellow; - std::array newMipData; - std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); + // Resolve the target texture + GLTexture resolveTexture; + glBindTexture(GL_TEXTURE_2D, resolveTexture); + glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 4, 4); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - newMipData.data()); + GLFramebuffer resolveFbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, + 0); - // Generate mipmaps. This should redefine level 1 back to being compatible with level 0. - glGenerateMipmap(GL_TEXTURE_2D); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTexture, 0, 2); + ASSERT_GL_NO_ERROR(); + glCheckFramebufferStatus(GL_FRAMEBUFFER); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]); - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]); - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]); - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]); - } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, resolveFbo); + EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red); } -// Test that generating mipmaps after incompatibly redefining a level while simultaneously changing -// the base level works. -TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefineAndRebase) +// Test basic GL_EXT_copy_image copy without any bound textures +TEST_P(Texture2DTestES3, CopyImageEXT) { - ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL()); - - // http://crbug.com/1100613 - ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + testCopyImage(APIExtensionVersion::EXT); +} - // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs. - ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); +// Test basic GL_OES_copy_image copy without any bound textures +TEST_P(Texture2DTestES3, CopyImageOES) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); + testCopyImage(APIExtensionVersion::OES); +} - initTest(false); +void Texture2DTestES3::testCopyImageDepthStencil(const APIExtensionVersion usedExtension) +{ + ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << lod; - } + std::vector texDataRed(4u * 4u, GLColor::red); + GLTexture srcTexture; + GLTexture destTexture; - // Redefine level 2 to an incompatible size, say the same size as level 0. - const GLColor kNewMipColor = GLColor::yellow; - std::array newMipData; - std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); + constexpr GLsizei kSize = 4; - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - newMipData.data()); + GLTexture src; + glBindTexture(GL_TEXTURE_2D, src); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize); - // Set base level of the texture to 1 then generate mipmaps. Level 2 that's redefined should - // go back to being compatibly defined. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glGenerateMipmap(GL_TEXTURE_2D); + GLTexture dst; + glBindTexture(GL_TEXTURE_2D, dst); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize); - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]) << lod; - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[1]) << lod; - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[1]) << lod; - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[1]) << lod; - } + // A color image for testing depth/stencil + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); - // Redefine level 1 (current base level) to an incompatible size. - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - newMipData.data()); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glUseProgram(program); + GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorLoc, -1); - // Set base level of the texture back to 0 then generate mipmaps. Level 1 should go back to - // being compatibly defined. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glGenerateMipmap(GL_TEXTURE_2D); + // Initialize the src depth image + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src, 0); + glClearDepthf(0.3f); + glClearStencil(0x57); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - // Test that the texture looks as expected. - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]) << lod; - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]) << lod; - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]) << lod; - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]) << lod; - } -} + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, 0x57, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilMask(0xFF); -// Test that generating mipmaps after incompatibly redefining the base level of the texture works. -TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBase) -{ - initTest(false); + glDepthFunc(GL_LESS); + glUniform4f(colorLoc, 1, 0, 0, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) + glDepthFunc(GL_GREATER); + glUniform4f(colorLoc, 0, 1, 0, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + ASSERT_GL_NO_ERROR(); + + // Now that the depth stencil image is definitely initialized, copy it into the destination + if (usedExtension == APIExtensionVersion::OES) { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + glCopyImageSubDataOES(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize, + kSize, 1); } + else + { + glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize, + kSize, 1); + } + ASSERT_GL_NO_ERROR(); - // Redefine level 0 to an incompatible size. - const GLColor kNewMipColor = GLColor::yellow; - std::array newMipData; - std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); + // Verify the dst texture has the right depth/stencil values + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA, - GL_UNSIGNED_BYTE, newMipData.data()); + glDepthFunc(GL_LESS); + glUniform4f(colorLoc, 0, 0, 1, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); - // Generate mipmaps. - glGenerateMipmap(GL_TEXTURE_2D); + glDepthFunc(GL_GREATER); + glUniform4f(colorLoc, 1, 1, 0, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); + ASSERT_GL_NO_ERROR(); +} - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod < kMipCount + 1; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor); - EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor); - EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor); - EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor); - } +// Test basic GL_EXT_copy_image copy with a depth/stencil texture +TEST_P(Texture2DTestES3, CopyImageEXTDepthStencil) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + testCopyImageDepthStencil(APIExtensionVersion::EXT); } -// Test that generating mipmaps after incompatibly redefining the base level while simultaneously -// changing MAX_LEVEL works. -TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBaseAndChangingMax) +// Test basic GL_OES_copy_image copy with a depth/stencil texture +TEST_P(Texture2DTestES3, CopyImageOESDepthStencil) { - initTest(false); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); + testCopyImageDepthStencil(APIExtensionVersion::OES); +} - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) +// Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size +TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + // TODO(http://anglebug.com/42264170): Fix calls to vkCmdCopyBufferToImage() with images smaller + // than the compressed format block size. + ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory)); + + constexpr uint32_t kSize = 4; + constexpr size_t kNumLevels = 3; + const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0}; + + GLTexture srcTexture; + glBindTexture(GL_TEXTURE_2D, srcTexture); + for (size_t level = 0; level < kNumLevels; ++level) { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); + glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level, + kSize >> level, 0, 8, CompressedImageETC1); + EXPECT_GL_NO_ERROR(); } - // Redefine level 0 to an incompatible size. - const GLColor kNewMipColor = GLColor::yellow; - std::array newMipData; - std::fill(newMipData.begin(), newMipData.end(), kNewMipColor); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA, - GL_UNSIGNED_BYTE, newMipData.data()); + GLTexture destTexture; + glBindTexture(GL_TEXTURE_2D, destTexture); + for (size_t level = 0; level < kNumLevels; ++level) + { + glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level, + kSize >> level, 0, 8, nullptr); + EXPECT_GL_NO_ERROR(); + } - // Set max level of the texture to 2 then generate mipmaps. - constexpr uint32_t kMaxLevel = 2; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMaxLevel); - glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod <= kMaxLevel; ++lod) + // copy + for (size_t level = 0; level < kNumLevels; ++level) { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor); - EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor); - EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor); - EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor); + glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D, + level, 0, 0, 0, kSize >> level, kSize >> level, 1); + EXPECT_GL_NO_ERROR(); } } -// Test that stage invalid texture levels work. -TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels) +// Test GL_EXT_copy_image copy with a non-zero base level +TEST_P(Texture2DTestES3, CopyImageBaseLevel1) { - constexpr uint32_t kMaxLevel = 2; - const GLColor kMipColor[kMaxLevel + 1] = {GLColor::red, GLColor::green, GLColor::blue}; + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - initTest(false); + std::vector texDataBlack(8u * 8u, GLColor::black); + std::vector texDataRed(4u * 4u, GLColor::red); + std::vector texDataGreen(4u * 4u, GLColor::green); + std::vector texDataBlue(4u * 4u, GLColor::blue); - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); + GLTexture srcTexture; + GLTexture destTexture; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - std::vector texDataCyan(2u * 2u, GLColor::cyan); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataCyan.data()); - setLodUniform(0); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_GL_NO_ERROR(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, destTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataBlack.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - std::vector texDataGreen(2u * 2u, GLColor::green); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + glBindTexture(GL_TEXTURE_2D, srcTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataBlack.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen.data()); - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data()); + glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + + glBindTexture(GL_TEXTURE_2D, 0); + + // copy + glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 1, 2, 2, 0, destTexture, GL_TEXTURE_2D, 1, 2, + 2, 0, 2, 2, 1); + + glBindTexture(GL_TEXTURE_2D, destTexture); + EXPECT_GL_NO_ERROR(); - std::vector texDataRed(4u * 4u, GLColor::red); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + glViewport(0, 0, 4, 4); + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod <= kMaxLevel; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColor[lod]); - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColor[lod]); - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColor[lod]); - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColor[lod]); - } + EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red); } -// Test redefine a mutable texture into an immutable texture. -TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable) +// Test basic GL_EXT_copy_image copy without any draw calls by attaching the texture +// to a framebuffer and reads from the framebuffer to validate the copy +TEST_P(Texture2DTestES3, CopyImageFB) { - // http://anglebug.com/42263310 - ANGLE_SKIP_TEST_IF(IsD3D()); - - // http://anglebug.com/42263301 - ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac()); - - constexpr uint32_t kBaseLevel = 1; - const GLColor kNewMipColors[kMipCount] = { - GLColor::yellow, - GLColor::cyan, - GLColor::white, - GLColor(127u, 127u, 127u, 255u), - }; + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - initTest(false); + glViewport(0, 0, 4, 4); + std::vector texDataRed(4u * 4u, GLColor::red); + GLTexture srcTexture; + GLTexture destTexture; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, destTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - // Test that all mips have the expected data - for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod) - { - setLodUniform(lod - kBaseLevel); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - } + std::vector texDataGreen(4u * 4u, GLColor::green); + glBindTexture(GL_TEXTURE_2D, srcTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glBindTexture(GL_TEXTURE_2D, 0); - glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size); - std::array mipData; - fillMipData(mipData.data(), kMip0Size, kNewMipColors); - for (size_t mip = 0; mip < kMipCount; ++mip) - { - glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA, - GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip)); - } + // copy + glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, destTexture, GL_TEXTURE_2D, 0, 0, + 1, 0, 3, 3, 1); - // Test that all enabled mips have the expected data - for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod) - { - setLodUniform(lod - kBaseLevel); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]); - } + EXPECT_GL_NO_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - for (uint32_t lod = 0; lod < kBaseLevel; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]); - } + GLFramebuffer fb; + glBindFramebuffer(GL_FRAMEBUFFER, fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + EXPECT_PIXEL_RECT_EQ(0, 1, 3, 3, GLColor::green); + EXPECT_PIXEL_RECT_EQ(3, 0, 1, 4, GLColor::red); + EXPECT_PIXEL_RECT_EQ(0, 0, 4, 1, GLColor::red); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } -// Test that redefine a level with incompatible size beyond the max level. -TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel) +// Test GL_EXT_copy_image copy to a framebuffer attachment after +// invalidation. Then draw with blending onto the framebuffer. +TEST_P(Texture2DTestES3, CopyImageFBInvalidateThenBlend) { - initTest(false); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - // Test that all mips have the expected data initially (this makes sure the texture image is - // created already). - for (uint32_t lod = 0; lod < kMipCount; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - } + ANGLE_GL_PROGRAM(drawBlueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + ANGLE_GL_PROGRAM(drawRedProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - uint32_t maxLevel = 1; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel); + glViewport(0, 0, 4, 4); + GLTexture srcTexture; + GLTexture textureAttachment; - // Update level 0 - const GLColor kNewMipLevle0Color = GLColor::yellow; - std::array newMipData; - std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE, - newMipData.data()); + std::vector texDataGreen(4u * 4u, GLColor::green); + glBindTexture(GL_TEXTURE_2D, srcTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glBindTexture(GL_TEXTURE_2D, 0); - // Update level 2 with incompatible data - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, - newMipData.data()); - EXPECT_GL_NO_ERROR(); + glBindTexture(GL_TEXTURE_2D, textureAttachment); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + glBindTexture(GL_TEXTURE_2D, 0); - // Test that the texture looks as expected. - const int w = getWindowWidth() - 1; - const int h = getWindowHeight() - 1; - for (uint32_t lod = 0; lod < maxLevel; ++lod) - { - setLodUniform(lod); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - if (lod == 0) - { - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color); - EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color); - EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color); - EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color); - } - else - { - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]); - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]); - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]); - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]); - } - } -} + GLFramebuffer fb; + glBindFramebuffer(GL_FRAMEBUFFER, fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment, + 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); -// Port test from web_gl/conformance2/textures/misc/fuzz-545-immutable-tex-render-feedback.html. -// What this tries to do is create a render feedback loop and ensure it is not crashing. -TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback) -{ - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + // Draw something in the texture to make sure it's image is defined. + drawQuad(drawRedProgram, essl1_shaders::PositionAttrib(), 0.0f); - constexpr uint32_t MIPS = 2; - constexpr uint32_t SIZE = 10; + // Invalidate the framebuffer. + const GLenum discards[] = {GL_COLOR_ATTACHMENT0}; + glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards); + ASSERT_GL_NO_ERROR(); - GLTexture immutTex; - glBindTexture(GL_TEXTURE_2D, immutTex); - glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, SIZE, SIZE); + // Copy into the framebuffer attachment. + glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, textureAttachment, GL_TEXTURE_2D, + 0, 0, 0, 0, 4, 4, 1); + EXPECT_GL_NO_ERROR(); - GLTexture mutTex; - glBindTexture(GL_TEXTURE_2D, mutTex); - for (uint32_t mip = 0; mip < MIPS; mip++) - { - const uint32_t size = SIZE >> mip; - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - } + // Draw and blend, making sure both the copy and draw happen correctly. + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + drawQuad(drawBlueProgram, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); - constexpr GLenum MAG_FILTERS[] = {GL_LINEAR, GL_NEAREST}; - constexpr GLenum MIN_FILTERS[] = { - GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, - GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST}; + EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::cyan); - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} - const GLuint texs[] = {immutTex, mutTex}; - for (const GLuint tex : texs) - { - glBindTexture(GL_TEXTURE_2D, tex); +// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not +// have images defined. +TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined) +{ + // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array. + ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL()); - for (GLuint level_prime_base = 0; level_prime_base < (MIPS + 1); level_prime_base++) - { // `level_base` in GLES - // ES 3.0.6 p150 - GLuint _level_base = level_prime_base; - if (tex == immutTex) - { - _level_base = std::min(_level_base, MIPS - 1); - } - const GLuint level_base = _level_base; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + std::vector texDataGreen(2u * 2u, GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - for (GLuint _level_prime_max = (level_prime_base - 1); _level_prime_max < (MIPS + 2); - _level_prime_max++) - { // `q` in GLES - if (_level_prime_max < 0) - continue; - if (_level_prime_max == (MIPS + 1)) - { - _level_prime_max = 10000; // This is the default, after all! - } - const GLuint level_prime_max = _level_prime_max; + EXPECT_GL_NO_ERROR(); - // ES 3.0.6 p150 - GLuint _level_max = level_prime_max; - if (tex == immutTex) - { - _level_max = std::min(std::max(level_base, level_prime_max), MIPS - 1); - } - const GLuint level_max = _level_max; + drawQuad(mProgram, "position", 0.5f); - const GLuint p = std::floor((float)std::log2(SIZE)) + level_base; - const GLuint q = std::min(p, level_max); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level_prime_base); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level_prime_max); +// Test that drawing works correctly when level 0 is undefined and base level is 1. +TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined) +{ + // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array. + ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL()); - const bool mipComplete = (q <= MIPS - 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + std::vector texDataGreen(2u * 2u, GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); - for (const GLenum minFilter : MIN_FILTERS) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); + EXPECT_GL_NO_ERROR(); - for (const GLenum magFilter : MAG_FILTERS) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); + // Texture is incomplete. + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); - for (GLuint dstMip = 0; dstMip < (MIPS + 1); dstMip++) - { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, tex, dstMip); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - // ES3.0 p213-214 - bool fbComplete = true; + // Texture is now complete. + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} - // * "The width and height of `image` are non-zero" - fbComplete &= (0 <= dstMip && dstMip <= MIPS - 1); +// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have +// dimensions that don't fit the images inside the range. +// GLES 3.0.4 section 3.8.13 Texture completeness +TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + std::vector texDataRed(8u * 8u, GLColor::red); + std::vector texDataGreen(2u * 2u, GLColor::green); + std::vector texDataCyan(2u * 2u, GLColor::cyan); - if (tex != immutTex) - { // "...does not name an immutable-format texture..." - // * "...the value of [level] must be in the range `[level_base, - // q]`" - fbComplete &= (level_base <= dstMip && dstMip <= q); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - // * "...the value of [level] is not `level_base`, then the texture - // must be mipmap complete" - if (dstMip != level_base) - { - fbComplete &= mipComplete; - } - } + // Two levels that are initially unused. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataCyan.data()); - // - - GLenum expectError = 0; - GLenum expectStatus = GL_FRAMEBUFFER_COMPLETE; - if (!fbComplete) - { - expectStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - expectError = GL_INVALID_FRAMEBUFFER_OPERATION; - } + // One level that is used - only this level should affect completeness. + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + + EXPECT_GL_NO_ERROR(); - // - - EXPECT_GLENUM_EQ(expectStatus, - glCheckFramebufferStatus(GL_FRAMEBUFFER)); + drawQuad(mProgram, "position", 0.5f); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true); - EXPECT_EQ(expectError, glGetError()); - } - } - } - } - } - } -} + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); -// Test sampling from a texture of a (usually) not color-renderable -// base format with a color-renderable level beyond the max level. -TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableWithColorRenderableBeyondMaxLevel) -{ - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL()); - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // Switch the level that is being used to the cyan level 2. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); - const GLuint data[4] = {0xC0040200, 0xC0040200, 0xC0040200, 0xC0040200}; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - ASSERT_GL_NO_ERROR(); + EXPECT_GL_NO_ERROR(); + + drawQuad(mProgram, "position", 0.5f); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); } -// Test sampling from a texture of a depth-renderable base format -// with a color-renderable level beyond the max level. -TEST_P(Texture2DBaseMaxTestES3, DepthRenderableWithColorRenderableBeyondMaxLevel) +// Test glCopyImageSubDataEXT with GL_TEXTURE_2D_MULTISAMPLE, +// RGBA8->RGBA8 copy +// RGB8->RGB8 copy +TEST_P(MultisampleTexture2DTestES31, CopyMultisampleImageEXT) { - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + testCopyMultisampleImage(APIExtensionVersion::EXT, GL_RGBA8); + testCopyMultisampleImage(APIExtensionVersion::EXT, GL_RGB8); +} - const GLfloat data[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, - data); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - ASSERT_GL_NO_ERROR(); +// Test glCopyImageSubDataOES with GL_TEXTURE_2D_MULTISAMPLE, +// RGBA8->RGBA8 copy +// RGB8->RGB8 copy +TEST_P(MultisampleTexture2DTestES31, CopyMultisampleImageOES) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); + testCopyMultisampleImage(APIExtensionVersion::OES, GL_RGBA8); + testCopyMultisampleImage(APIExtensionVersion::OES, GL_RGB8); +} - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); +// Test glCopyImageSubDataEXT with GL_TEXTURE_2D_MULTISAMPLE_ARRAY, +// RGBA8->RGBA8 copy +// RGB8->RGB8 copy +TEST_P(MultisampleTexture2DTestES31, CopyMultisampleArrayImageEXT) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + testCopyMultisampleArrayImage(APIExtensionVersion::EXT, GL_RGBA8); + testCopyMultisampleArrayImage(APIExtensionVersion::EXT, GL_RGB8); } -// Test texture sampling while changing the base format from color-renderable -// to (usually) not color-renderable by manipulating base and max levels. -TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableAfterColorRenderableBelowBaseLevel) +// Test glCopyImageSubDataOES with GL_TEXTURE_2D_MULTISAMPLE_ARRAY, +// RGBA8->RGBA8 copy +// RGB8->RGB8 copy +TEST_P(MultisampleTexture2DTestES31, CopyMultisampleArrayImageOES) { - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); + testCopyMultisampleArrayImage(APIExtensionVersion::OES, GL_RGBA8); + testCopyMultisampleArrayImage(APIExtensionVersion::OES, GL_RGB8); +} - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +// Depth/Stencil textures cannot be 3D. +TEST_P(Texture3DTestES3, DepthStencil3DDisallowed) +{ + const std::array, 6> testConfigs = { + std::make_tuple(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT), + std::make_tuple(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT), + std::make_tuple(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT), + std::make_tuple(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV), + std::make_tuple(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8), + std::make_tuple(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE)}; - std::array data0; - data0.fill(GLColor::green); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data()); + for (auto testConfig : testConfigs) + { + const GLenum internalformat = std::get<0>(testConfig); + const GLenum format = std::get<1>(testConfig); + const GLenum type = std::get<2>(testConfig); - const GLuint data1[1] = {0xC0040200}; - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data1); - ASSERT_GL_NO_ERROR(); + if (internalformat == GL_STENCIL_INDEX8 && !IsGLExtensionEnabled("GL_OES_texture_stencil8")) + { + continue; + } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + GLTexture depthTexture; + glBindTexture(GL_TEXTURE_3D, depthTexture); + glTexImage3D(GL_TEXTURE_3D, 0, internalformat, 16, 16, 16, 0, format, type, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); + glTexStorage3D(GL_TEXTURE_3D, 2, internalformat, 16, 16, 16); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + } } -// Test texture sampling while changing the base format from color-renderable -// to depth-renderable by manipulating base and max levels. -TEST_P(Texture2DBaseMaxTestES3, DepthRenderableAfterColorRenderableBelowBaseLevel) +// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not +// have images defined. +TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined) { - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + std::vector texDataGreen(2u * 2u * 2u, GLColor::green); + glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1); - std::array data0; - data0.fill(GLColor::green); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data()); + EXPECT_GL_NO_ERROR(); - const GLfloat data1[1] = {1.0f}; - glTexImage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT, - data1); - ASSERT_GL_NO_ERROR(); + drawQuad(mProgram, "position", 0.5f); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); } -// Test that the following scenario works: -// - change a texture's max level to 0. -// - clear the texture with glClear. -// - sample the texture and draw to another FBO. -// - draw to the texture again. -// - The texture's final color should be clear color in 1st pass + draw color. -TEST_P(Texture2DBaseMaxTestES3, SetMaxLevelToZeroThenClearThenSampleThenDraw) +// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have +// dimensions that don't fit the images inside the range. +// GLES 3.0.4 section 3.8.13 Texture completeness +TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) { - ANGLE_GL_PROGRAM(textureProgram, angle::essl3_shaders::vs::Texture2DLod(), - angle::essl3_shaders::fs::Texture2DLod()); - ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(), - angle::essl1_shaders::fs::Blue()); - - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - // 1. Change the texture's max level to 0. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - EXPECT_GL_NO_ERROR(); - - // 2. Attach the texture to a FBO and clear it. - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - EXPECT_GL_NO_ERROR(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 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 the bound texture to default FBO. - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - glUseProgram(textureProgram); - drawQuad(textureProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + std::vector texDataRed(8u * 8u * 8u, GLColor::red); + std::vector texDataGreen(2u * 2u * 2u, GLColor::green); + std::vector texDataCyan(2u * 2u * 2u, GLColor::cyan); - // 4. Draw to the texture again - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glUseProgram(blueProgram); - drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - // Expect the final color to be accumulated color - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255)); -} + // Two levels that are initially unused. + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataCyan.data()); -// Test that the following scenario works: -// - change a texture's max level to 1. -// - clear the texture with glClear. -// - change the texture's max level to 0. -// - sample the texture and draw to another FBO. -// - draw to the texture again. -// - The texture's final color should be clear color in 1st pass + draw color. -TEST_P(Texture2DBaseMaxTestES3, SetMaxLevelToOneThenClearThenSetMaxLevelToZeroThenSampleThenDraw) -{ - ANGLE_GL_PROGRAM(textureProgram, angle::essl3_shaders::vs::Texture2DLod(), - angle::essl3_shaders::fs::Texture2DLod()); - ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(), - angle::essl1_shaders::fs::Blue()); + // One level that is used - only this level should affect completeness. + glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1); - // 1. Change the texture's max level to 1. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); EXPECT_GL_NO_ERROR(); - // 2. Attach the texture to a FBO and clear it. - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - EXPECT_GL_NO_ERROR(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 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); + drawQuad(mProgram, "position", 0.5f); - // 3. Change the texture's max level to 0. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - // 4. Draw the bound texture to default FBO. - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - glUseProgram(textureProgram); - drawQuad(textureProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); + ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL()); - // 5. Draw to the texture again - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glUseProgram(blueProgram); - drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); + // Switch the level that is being used to the cyan level 2. + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2); - // Expect the final color to be accumulated color EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255)); + + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); } -// Test to check that texture completeness is determined correctly when the texture base level is -// greater than 0, and also that level 0 is not sampled when base level is greater than 0. -TEST_P(Texture2DTestES3, DrawWithBaseLevel1) +// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not +// have images defined. +TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - - std::vector texDataRed(4u * 4u, GLColor::red); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - std::vector texDataGreen(2u * 2u, GLColor::green); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); + std::vector texDataGreen(2u * 2u * 2u, GLColor::green); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1); EXPECT_GL_NO_ERROR(); @@ -6109,604 +7592,681 @@ TEST_P(Texture2DTestES3, DrawWithBaseLevel1) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -void Texture2DTestES3::testCopyImage(const APIExtensionVersion usedExtension) +// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have +// dimensions that don't fit the images inside the range. +// GLES 3.0.4 section 3.8.13 Texture completeness +TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) { - ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); - - std::vector texDataRed(4u * 4u, GLColor::red); - GLTexture srcTexture; - GLTexture destTexture; + // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV) + ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, destTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glBindTexture(GL_TEXTURE_3D, m2DArrayTexture); + std::vector texDataRed(8u * 8u * 8u, GLColor::red); + std::vector texDataGreen(2u * 2u * 2u, GLColor::green); + std::vector texDataCyan(2u * 2u * 2u, GLColor::cyan); - std::vector texDataGreen(4u * 4u, GLColor::green); - glBindTexture(GL_TEXTURE_2D, srcTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + + // Two levels that are initially unused. + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataCyan.data()); + + // One level that is used - only this level should affect completeness. + glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen.data()); - glBindTexture(GL_TEXTURE_2D, 0); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1); - // copy - if (usedExtension == APIExtensionVersion::OES) - { - glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0, - 2, 2, 0, 2, 2, 1); - } - else - { - glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0, - 2, 2, 0, 2, 2, 1); - } - glBindTexture(GL_TEXTURE_2D, destTexture); EXPECT_GL_NO_ERROR(); - glViewport(0, 0, 4, 4); drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL()); + + // Switch the level that is being used to the cyan level 2. + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2); + EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green); - EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red); - EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); } -void MultisampleTexture2DTestES31::testCopyMultisampleImage(const APIExtensionVersion usedExtension, - const GLenum internalFormat) +// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug +// in the Vulkan backend where the old higher-layer-count data upload was not removed. +TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse) { - ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); + int px = getWindowWidth() / 2; + int py = getWindowHeight() / 2; - ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); - GLTexture srcTexture; - GLTexture destTexture; - const GLenum target = GL_TEXTURE_2D_MULTISAMPLE; + // Fill the whole texture with red, then redefine it and fill with green + std::vector pixelsRed(2 * 2 * 4, GLColor::red); + std::vector pixelsGreen(2 * 2 * 2, GLColor::green); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsRed.data()); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsGreen.data()); - GLint maxSamples = 0; - glGetInternalformativ(target, internalFormat, GL_SAMPLES, 1, &maxSamples); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); EXPECT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, destTexture); - glTexStorage2DMultisample(target, maxSamples, internalFormat, 4, 4, false); + glUseProgram(mProgram); EXPECT_GL_NO_ERROR(); - glBindTexture(target, srcTexture); - glTexStorage2DMultisample(target, maxSamples, internalFormat, 4, 4, false); + // Draw the first slice + glUniform1i(mTextureArraySliceUniformLocation, 0); + drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, srcTexture, 0); + // Draw the second slice + glUniform1i(mTextureArraySliceUniformLocation, 1); + drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); +} - // Draw red into the source texture - glViewport(0, 0, 4, 4); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +// Create a 2D array texture and update layers with data and test that pruning +// of superseded updates works as expected. +TEST_P(Texture2DArrayTestES3, TextureArrayPruneSupersededUpdates) +{ + constexpr uint32_t kTexWidth = 256; + constexpr uint32_t kTexHeight = 256; + constexpr uint32_t kTexLayers = 3; - drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); - ASSERT_GL_NO_ERROR(); + glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_GL_NO_ERROR(); - glBindTexture(target, 0); + // Initialize entire texture. + constexpr GLColor kInitialExpectedColor = GLColor(201u, 201u, 201u, 201u); + std::vector initialData(kTexWidth * kTexHeight * kTexLayers, kInitialExpectedColor); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexWidth, kTexHeight, kTexLayers, 0, GL_RGBA, + GL_UNSIGNED_BYTE, initialData.data()); - // Copy - if (usedExtension == APIExtensionVersion::OES) - { - glCopyImageSubDataOES(srcTexture, target, 0, 0, 0, 0, destTexture, target, 0, 0, 0, 0, 4, 4, - 1); - } - else - { - glCopyImageSubDataEXT(srcTexture, target, 0, 0, 0, 0, destTexture, target, 0, 0, 0, 0, 4, 4, - 1); - } - EXPECT_GL_NO_ERROR(); + // Upate different layers with different colors, these together should supersed + // the entire init update + constexpr GLColor kExpectedColor[] = {GLColor(32u, 32u, 32u, 32u), GLColor(64u, 64u, 64u, 64u), + GLColor(128u, 128u, 128u, 128u)}; + std::vector supersedingData[] = { + std::vector(kTexWidth * kTexHeight, kExpectedColor[0]), + std::vector(kTexWidth * kTexHeight, kExpectedColor[1]), + std::vector(kTexWidth * kTexHeight, kExpectedColor[2])}; - // Resolve the target texture - GLTexture resolveTexture; - glBindTexture(GL_TEXTURE_2D, resolveTexture); - glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 4, 4); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, GL_RGBA, + GL_UNSIGNED_BYTE, supersedingData[0].data()); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, kTexWidth, kTexHeight, 1, GL_RGBA, + GL_UNSIGNED_BYTE, supersedingData[1].data()); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, kTexWidth, kTexHeight, 1, GL_RGBA, + GL_UNSIGNED_BYTE, supersedingData[2].data()); - GLFramebuffer resolveFbo; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, - 0); + glUseProgram(mProgram); + EXPECT_GL_NO_ERROR(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, destTexture, 0); - ASSERT_GL_NO_ERROR(); - glCheckFramebufferStatus(GL_FRAMEBUFFER); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + // Draw layer 0 + glUniform1i(mTextureArraySliceUniformLocation, 0); + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[0]); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ASSERT_GL_NO_ERROR(); + // Draw layer 1 + glUniform1i(mTextureArraySliceUniformLocation, 1); + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[1]); - glBindFramebuffer(GL_FRAMEBUFFER, resolveFbo); - EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red); + // Draw layer 2 + glUniform1i(mTextureArraySliceUniformLocation, 2); + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[2]); } -void MultisampleTexture2DTestES31::testCopyMultisampleArrayImage( - const APIExtensionVersion usedExtension, - const GLenum internalFormat) +// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in +// the Vulkan backend where the old higher-layer-count data upload was not removed. +TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array")); - - ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); + int px = getWindowWidth() / 2; + int py = getWindowHeight() / 2; - ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); - GLTexture srcTexture; - GLTexture destTexture; + // Fill the whole texture with red. + std::vector pixelsRed(2 * 2 * 4, GLColor::red); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsRed.data()); - GLint maxSamples = 0; - glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalFormat, GL_SAMPLES, 1, &maxSamples); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); EXPECT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, destTexture); - glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamples, internalFormat, 4, - 4, 3, false); + glUseProgram(mProgram); EXPECT_GL_NO_ERROR(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, srcTexture); - glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamples, internalFormat, 4, - 4, 3, false); + // Draw the first slice + glUniform1i(mTextureArraySliceUniformLocation, 0); + drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red); - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 1); + // Draw the fourth slice + glUniform1i(mTextureArraySliceUniformLocation, 3); + drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red); - // Draw red into the source texture layer 1 - glViewport(0, 0, 4, 4); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f); - ASSERT_GL_NO_ERROR(); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0); + // Redefine the image and fill with green + std::vector pixelsGreen(2 * 2 * 2, GLColor::green); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsGreen.data()); - // Copy - if (usedExtension == APIExtensionVersion::OES) - { - glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 1, - destTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 2, 4, 4, - 1); - } - else - { - glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 1, - destTexture, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, 0, 0, 2, 4, 4, - 1); - } + // Draw the first slice + glUniform1i(mTextureArraySliceUniformLocation, 0); + drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); - // Resolve the target texture - GLTexture resolveTexture; - glBindTexture(GL_TEXTURE_2D, resolveTexture); - glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 4, 4); + // Draw the second slice + glUniform1i(mTextureArraySliceUniformLocation, 1); + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); +} - GLFramebuffer resolveFbo; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, - 0); +// Create a 2D array texture, use it, then redefine one level without changing dimensions. +TEST_P(Texture2DArrayTestES3, RedefineLevelData) +{ + glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTexture, 0, 2); + // Fill both levels with red + std::vector pixelsRed(2 * 2 * 1, GLColor::red); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsRed.data()); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsRed.data()); ASSERT_GL_NO_ERROR(); - glCheckFramebufferStatus(GL_FRAMEBUFFER); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_LINEAR); + // Check that both levels are red + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Redefine level 1 with green + glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + &GLColor::green); ASSERT_GL_NO_ERROR(); - glBindFramebuffer(GL_FRAMEBUFFER, resolveFbo); - EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red); + // Check that level 0 is red and level 1 is green + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test basic GL_EXT_copy_image copy without any bound textures -TEST_P(Texture2DTestES3, CopyImageEXT) +// Create a 3D texture, use it, then redefine one level without changing dimensions. +TEST_P(Texture3DTestES3, RedefineLevelData) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - testCopyImage(APIExtensionVersion::EXT); -} + glBindTexture(GL_TEXTURE_3D, mTexture3D); -// Test basic GL_OES_copy_image copy without any bound textures -TEST_P(Texture2DTestES3, CopyImageOES) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); - testCopyImage(APIExtensionVersion::OES); -} + // Fill both levels with red + std::vector pixelsRed(2 * 2 * 1, GLColor::red); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsRed.data()); + glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixelsRed.data()); + ASSERT_GL_NO_ERROR(); -void Texture2DTestES3::testCopyImageDepthStencil(const APIExtensionVersion usedExtension) -{ - ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES); + // Check that both levels are red + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - std::vector texDataRed(4u * 4u, GLColor::red); - GLTexture srcTexture; - GLTexture destTexture; + // Redefine level 1 with green + glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + &GLColor::green); + ASSERT_GL_NO_ERROR(); - constexpr GLsizei kSize = 4; + // Check that level 0 is red and level 1 is green + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} - GLTexture src; - glBindTexture(GL_TEXTURE_2D, src); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize); +// Test that texture completeness is updated if texture max level changes. +// GLES 3.0.4 section 3.8.13 Texture completeness +TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + std::vector texDataGreen(8u * 8u, GLColor::green); - GLTexture dst; - glBindTexture(GL_TEXTURE_2D, dst); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - // A color image for testing depth/stencil - GLTexture color; - glBindTexture(GL_TEXTURE_2D, color); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); + // A level that is initially unused. + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); - glUseProgram(program); - GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform()); - ASSERT_NE(colorLoc, -1); + // One level that is initially used - only this level should affect completeness. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - // Initialize the src depth image - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src, 0); - glClearDepthf(0.3f); - glClearStencil(0x57); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_EQUAL, 0x57, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilMask(0xFF); + EXPECT_GL_NO_ERROR(); - glDepthFunc(GL_LESS); - glUniform4f(colorLoc, 1, 0, 0, 1); - drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + drawQuad(mProgram, "position", 0.5f); - glDepthFunc(GL_GREATER); - glUniform4f(colorLoc, 0, 1, 0, 1); - drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - ASSERT_GL_NO_ERROR(); - - // Now that the depth stencil image is definitely initialized, copy it into the destination - if (usedExtension == APIExtensionVersion::OES) - { - glCopyImageSubDataOES(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize, - kSize, 1); - } - else - { - glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize, - kSize, 1); - } - ASSERT_GL_NO_ERROR(); - - // Verify the dst texture has the right depth/stencil values - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst, 0); - - glDepthFunc(GL_LESS); - glUniform4f(colorLoc, 0, 0, 1, 1); - drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); - glDepthFunc(GL_GREATER); - glUniform4f(colorLoc, 1, 1, 0, 1); - drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); - ASSERT_GL_NO_ERROR(); -} - -// Test basic GL_EXT_copy_image copy with a depth/stencil texture -TEST_P(Texture2DTestES3, CopyImageEXTDepthStencil) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - testCopyImageDepthStencil(APIExtensionVersion::EXT); -} + // Switch the max level to level 1. The levels within the used range now have inconsistent + // dimensions and the texture should be incomplete. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); -// Test basic GL_OES_copy_image copy with a depth/stencil texture -TEST_P(Texture2DTestES3, CopyImageOESDepthStencil) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); - testCopyImageDepthStencil(APIExtensionVersion::OES); + EXPECT_GL_NO_ERROR(); + + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); } -// Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size -TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps) +// Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly +// keep the staged clear. http://anglebug.com/345532371 +TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenRead) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - // TODO(http://anglebug.com/42264170): Fix calls to vkCmdCopyBufferToImage() with images smaller - // than the compressed format block size. - ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory)); - - constexpr uint32_t kSize = 4; - constexpr size_t kNumLevels = 3; - const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0}; + constexpr GLsizei kTexWidth = 128; + constexpr GLsizei kTexHeight = 128; + constexpr GLsizei kTexDepth = 6; + // Create a single leveled texture with 6 layers + GLTexture tex; + glBindTexture(GL_TEXTURE_2D_ARRAY, tex); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth); - GLTexture srcTexture; - glBindTexture(GL_TEXTURE_2D, srcTexture); - for (size_t level = 0; level < kNumLevels; ++level) + // Stage clear to red on all layers + GLFramebuffer drawFBO; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + for (GLsizei layer = 0; layer < kTexDepth; layer++) { - glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level, - kSize >> level, 0, 8, CompressedImageETC1); - EXPECT_GL_NO_ERROR(); + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + glClear(GL_COLOR_BUFFER_BIT); } - GLTexture destTexture; - glBindTexture(GL_TEXTURE_2D, destTexture); - for (size_t level = 0; level < kNumLevels; ++level) + // TexSubImage with green color on half of the image of layer 2,3,4 + constexpr GLsizei kUpdateLayerStart = 2; + constexpr GLsizei kUpdateLayerCount = 3; + std::vector updateData((kTexWidth / 2) * kTexHeight * kUpdateLayerCount, + GLColor::green); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, kUpdateLayerStart, kTexWidth / 2, kTexHeight, + kUpdateLayerCount, GL_RGBA, GL_UNSIGNED_BYTE, updateData.data()); + + // Verify that layers 2, 3 and 4 have been correctly overwritten, and the other layers are + // cleared. + GLFramebuffer readFBO; + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); + for (GLsizei layer = 0; layer < kTexDepth; layer++) { - glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level, - kSize >> level, 0, 8, nullptr); - EXPECT_GL_NO_ERROR(); - } - - glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); - // copy - for (size_t level = 0; level < kNumLevels; ++level) - { - glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D, - level, 0, 0, 0, kSize >> level, kSize >> level, 1); - EXPECT_GL_NO_ERROR(); + static_assert(kUpdateLayerStart + kUpdateLayerCount <= kTexDepth); + if (layer >= kUpdateLayerStart && layer < kUpdateLayerStart + kUpdateLayerCount) + { + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth / 2, kTexHeight, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kTexWidth / 2, 0, kTexWidth - kTexWidth / 2, kTexHeight, + GLColor::red); + } + else + { + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth, kTexHeight, GLColor::red); + } } + ASSERT_GL_NO_ERROR(); } -// Test GL_EXT_copy_image copy with a non-zero base level -TEST_P(Texture2DTestES3, CopyImageBaseLevel1) +// Test for a bug when staged clear to a layer is entirely overwritten with glTexSubImage with +// multiple layers, but the clear for the layers that were not overwritten by glTexSubImage was +// incorrectly dropped. +TEST_P(Texture2DArrayTestES3, ClearThenOverwriteWithTexSubImageThenRead) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + constexpr GLsizei kTexWidth = 92; + constexpr GLsizei kTexHeight = 128; + constexpr GLsizei kTexDepth = 6; + // Create a single leveled texture with 6 layers + GLTexture tex; + glBindTexture(GL_TEXTURE_2D_ARRAY, tex); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth); - std::vector texDataBlack(8u * 8u, GLColor::black); - std::vector texDataRed(4u * 4u, GLColor::red); - std::vector texDataGreen(4u * 4u, GLColor::green); - std::vector texDataBlue(4u * 4u, GLColor::blue); + // Stage clear to red on all layers + GLFramebuffer drawFBO; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + for (GLsizei layer = 0; layer < kTexDepth; layer++) + { + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + glClear(GL_COLOR_BUFFER_BIT); + } - GLTexture srcTexture; - GLTexture destTexture; + // TexSubImage with green color in layers 1, 2 and 3 + constexpr GLsizei kUpdateLayerStart = 1; + constexpr GLsizei kUpdateLayerCount = 3; + std::vector updateData(kTexWidth * kTexHeight * kUpdateLayerCount, GLColor::green); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, kUpdateLayerStart, kTexWidth, kTexHeight, + kUpdateLayerCount, GL_RGBA, GL_UNSIGNED_BYTE, updateData.data()); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, destTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataBlack.data()); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + // Verify that layers 1, 2 and 3 have been correctly overwritten, and the other layers are + // cleared. + GLFramebuffer readFBO; + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); + for (GLsizei layer = 0; layer < kTexDepth; layer++) + { + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); - glBindTexture(GL_TEXTURE_2D, srcTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataBlack.data()); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data()); - glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + static_assert(kUpdateLayerStart + kUpdateLayerCount <= kTexDepth); + if (layer >= kUpdateLayerStart && layer < kUpdateLayerStart + kUpdateLayerCount) + { + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth, kTexHeight, GLColor::green); + } + else + { + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth, kTexHeight, GLColor::red); + } + } + ASSERT_GL_NO_ERROR(); +} - glBindTexture(GL_TEXTURE_2D, 0); +// Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly +// keep the staged clear. http://anglebug.com/345532371 +TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead) +{ + constexpr GLsizei kTexWidth = 128; + constexpr GLsizei kTexHeight = 128; + constexpr GLsizei kTexDepth = 6; + // Create a single leveled texture with 6 layers + GLTexture tex; + glBindTexture(GL_TEXTURE_2D_ARRAY, tex); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth); - // copy - glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 1, 2, 2, 0, destTexture, GL_TEXTURE_2D, 1, 2, - 2, 0, 2, 2, 1); + // Stage clear to red on all layers + GLFramebuffer drawFBO; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + for (GLsizei layer = 0; layer < kTexDepth; layer++) + { + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + glClear(GL_COLOR_BUFFER_BIT); + } - glBindTexture(GL_TEXTURE_2D, destTexture); + // TexSubImage with green color on half of the image of layer 2,3,4 + constexpr GLsizei kUpdateLayerStart = 2; + constexpr GLsizei kUpdateLayerCount = 3; + std::vector updateData((kTexWidth / 2) * kTexHeight * kUpdateLayerCount, + GLColor::green); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, kUpdateLayerStart, kTexWidth / 2, kTexHeight, + kUpdateLayerCount, GL_RGBA, GL_UNSIGNED_BYTE, updateData.data()); - EXPECT_GL_NO_ERROR(); + // Now Draw to fbo on layerStart with blue color + constexpr GLsizei kBlueQuadLayer = 2; + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, kBlueQuadLayer); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue()); + glUseProgram(blueProgram); + drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f); - glViewport(0, 0, 4, 4); - drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); + // Verify that layer 2 has the result of the draw call, layers 3 and 4 have been correctly + // overwritten by glTexSubImage3D, and the other layers are cleared. + GLFramebuffer readFBO; + glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); + for (GLsizei layer = 0; layer < kTexDepth; layer++) + { + glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); - EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green); - EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red); - EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red); + static_assert(kBlueQuadLayer < kTexDepth); + static_assert(kUpdateLayerStart + kUpdateLayerCount <= kTexDepth); + if (layer == kBlueQuadLayer) + { + // green + blue = cyan + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth / 2, kTexHeight, GLColor::cyan); + // red + blue = magenta + EXPECT_PIXEL_RECT_EQ(kTexWidth / 2, 0, kTexWidth - kTexWidth / 2, kTexHeight, + GLColor::magenta); + } + else if (layer >= kUpdateLayerStart && layer < kUpdateLayerStart + kUpdateLayerCount) + { + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth / 2, kTexHeight, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kTexWidth / 2, 0, kTexWidth - kTexWidth / 2, kTexHeight, + GLColor::red); + } + else + { + EXPECT_PIXEL_RECT_EQ(0, 0, kTexWidth, kTexHeight, GLColor::red); + } + } + ASSERT_GL_NO_ERROR(); } -// Test basic GL_EXT_copy_image copy without any draw calls by attaching the texture -// to a framebuffer and reads from the framebuffer to validate the copy -TEST_P(Texture2DTestES3, CopyImageFB) +// Test that compressed textures ignore the pixel unpack state. +// (https://crbug.org/1267496) +TEST_P(Texture3DTestES3, PixelUnpackStateTexImage) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && + !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); - glViewport(0, 0, 4, 4); - std::vector texDataRed(4u * 4u, GLColor::red); - GLTexture srcTexture; - GLTexture destTexture; + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5); + glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, destTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + uint8_t data[64] = {0}; + glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64, + data); + EXPECT_GL_NO_ERROR(); +} - std::vector texDataGreen(4u * 4u, GLColor::green); - glBindTexture(GL_TEXTURE_2D, srcTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glBindTexture(GL_TEXTURE_2D, 0); +// Test that compressed textures ignore the pixel unpack state. +// (https://crbug.org/1267496) +TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && + !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); - // copy - glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, destTexture, GL_TEXTURE_2D, 0, 0, - 1, 0, 3, 3, 1); + glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D); + uint8_t data[64] = {0}; + glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64, + data); EXPECT_GL_NO_ERROR(); - GLFramebuffer fb; - glBindFramebuffer(GL_FRAMEBUFFER, fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - - EXPECT_PIXEL_RECT_EQ(0, 1, 3, 3, GLColor::green); - EXPECT_PIXEL_RECT_EQ(3, 0, 1, 4, GLColor::red); - EXPECT_PIXEL_RECT_EQ(0, 0, 4, 1, GLColor::red); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data); + EXPECT_GL_NO_ERROR(); } -// Test GL_EXT_copy_image copy to a framebuffer attachment after -// invalidation. Then draw with blending onto the framebuffer. -TEST_P(Texture2DTestES3, CopyImageFBInvalidateThenBlend) +// Test that unpack buffer works in Texture 3D +TEST_P(Texture3DTestES3, PixelUnpackParamsChangeTexImage) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + // Contains three slices to pick out and one slice to skip. + static const unsigned char user_buffer_3d[6 * 16] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - ANGLE_GL_PROGRAM(drawBlueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); - ANGLE_GL_PROGRAM(drawRedProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0xFF, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - glViewport(0, 0, 4, 4); - GLTexture srcTexture; - GLTexture textureAttachment; + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - std::vector texDataGreen(4u * 4u, GLColor::green); - glBindTexture(GL_TEXTURE_2D, srcTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glBindTexture(GL_TEXTURE_2D, 0); + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - glBindTexture(GL_TEXTURE_2D, textureAttachment); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glBindTexture(GL_TEXTURE_2D, 0); + GLTexture tex; + glActiveTexture(GL_TEXTURE0); - GLFramebuffer fb; - glBindFramebuffer(GL_FRAMEBUFFER, fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment, - 0); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glBindTexture(GL_TEXTURE_3D, tex); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + EXPECT_GL_NO_ERROR(); - // Draw something in the texture to make sure it's image is defined. - drawQuad(drawRedProgram, essl1_shaders::PositionAttrib(), 0.0f); + GLBuffer buf; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 5); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 1); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 4); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // Invalidate the framebuffer. - const GLenum discards[] = {GL_COLOR_ATTACHMENT0}; - glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards); - ASSERT_GL_NO_ERROR(); + glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(user_buffer_3d), NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, sizeof(user_buffer_3d), user_buffer_3d); + EXPECT_GL_NO_ERROR(); - // Copy into the framebuffer attachment. - glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, textureAttachment, GL_TEXTURE_2D, - 0, 0, 0, 0, 4, 4, 1); + glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, 3, 2, 3, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); + glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 3, 2, 3, GL_RED, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_NO_ERROR(); - // Draw and blend, making sure both the copy and draw happen correctly. - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - drawQuad(drawBlueProgram, essl1_shaders::PositionAttrib(), 0.0f); - ASSERT_GL_NO_ERROR(); + glUseProgram(mProgram); + glUniform1i(mTexture3DUniformLocation, 0); + drawQuad(mProgram, "position", (1 + 0.5f) / 3.0f); + EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::cyan); + // Update using no skips and a row length of 1 to obtain a plain red block + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 1); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); + glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, 3, 2, 3, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); + glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 3, 2, 3, GL_RED, GL_UNSIGNED_BYTE, nullptr); + EXPECT_GL_NO_ERROR(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + drawQuad(mProgram, "position", (1 + 0.5f) / 3.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_RECT_EQ(0, 0, 3, 2, GLColor::red); + EXPECT_GL_NO_ERROR(); } -// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not -// have images defined. -TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined) +// Test that texture reload using unpack buffer and different type +TEST_P(Texture3DTestES3, PixelUnpackReloadTexImage) { - // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array. - ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL()); + constexpr GLsizei kTexWidth = 2; + constexpr GLsizei kTexHeight = 2; + constexpr GLsizei kTexDepth = 2; + float in_fp[kTexWidth * kTexHeight * kTexDepth * 3]; + std::fill(in_fp, in_fp + kTexWidth * kTexHeight * kTexDepth * 3, 0.2f); + + GLTexture tex; glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - std::vector texDataGreen(2u * 2u, GLColor::green); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + glBindTexture(GL_TEXTURE_3D, tex); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage3D(GL_TEXTURE_3D, 0, GL_R11F_G11F_B10F, kTexWidth, kTexHeight, kTexDepth, 0, GL_RGB, + GL_HALF_FLOAT, in_fp); EXPECT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); -} + GLRenderbuffer rbo; + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, kTexWidth, kTexHeight); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); + EXPECT_GL_NO_ERROR(); -// Test that drawing works correctly when level 0 is undefined and base level is 1. -TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined) -{ - // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array. - ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL()); + // Flush memory + glUseProgram(mProgram); + glUniform1i(mTexture3DUniformLocation, 0); + drawQuad(mProgram, "position", (1 + 0.5f) / 2.0f); + EXPECT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - std::vector texDataGreen(2u * 2u, GLColor::green); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); + // Use default unpacking parameters + GLBuffer buf; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); + glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(in_fp), in_fp, GL_DYNAMIC_DRAW); EXPECT_GL_NO_ERROR(); - // Texture is incomplete. - drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); + // Change the data type of the pixel data to GL_FLOAT + glTexImage3D(GL_TEXTURE_3D, 0, GL_R11F_G11F_B10F, kTexWidth, kTexHeight, kTexDepth, 0, GL_RGB, + GL_FLOAT, nullptr); + EXPECT_GL_NO_ERROR(); - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); + glUseProgram(mProgram); + glUniform1i(mTexture3DUniformLocation, 0); + drawQuad(mProgram, "position", (1 + 0.5f) / 2.0f); + EXPECT_GL_NO_ERROR(); - // Texture is now complete. - drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + for (int i = 0; i < kTexWidth; i++) + { + for (int j = 0; j < kTexHeight; j++) + { + EXPECT_PIXEL_32F_NEAR(i, j, 0.199219f, 0.199219f, 0.199219f, 1.0f, 0.00001f); + } + } + EXPECT_GL_NO_ERROR(); } -// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have -// dimensions that don't fit the images inside the range. +// Test that 3D texture completeness is updated if texture max level changes. // GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) +TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - std::vector texDataRed(8u * 8u, GLColor::red); - std::vector texDataGreen(2u * 2u, GLColor::green); - std::vector texDataCyan(2u * 2u, GLColor::cyan); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + std::vector texDataGreen(2u * 2u * 2u, GLColor::green); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - // Two levels that are initially unused. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataCyan.data()); + // A level that is initially unused. + glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - // One level that is used - only this level should affect completeness. - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + // One level that is initially used - only this level should affect completeness. + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); EXPECT_GL_NO_ERROR(); @@ -6714,1028 +8274,874 @@ TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL()); - - // Switch the level that is being used to the cyan level 2. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); + // Switch the max level to level 1. The levels within the used range now have inconsistent + // dimensions and the texture should be incomplete. + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); -} - -// Test glCopyImageSubDataEXT with GL_TEXTURE_2D_MULTISAMPLE, -// RGBA8->RGBA8 copy -// RGB8->RGB8 copy -TEST_P(MultisampleTexture2DTestES31, CopyMultisampleImageEXT) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - testCopyMultisampleImage(APIExtensionVersion::EXT, GL_RGBA8); - testCopyMultisampleImage(APIExtensionVersion::EXT, GL_RGB8); -} - -// Test glCopyImageSubDataOES with GL_TEXTURE_2D_MULTISAMPLE, -// RGBA8->RGBA8 copy -// RGB8->RGB8 copy -TEST_P(MultisampleTexture2DTestES31, CopyMultisampleImageOES) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); - testCopyMultisampleImage(APIExtensionVersion::OES, GL_RGBA8); - testCopyMultisampleImage(APIExtensionVersion::OES, GL_RGB8); -} - -// Test glCopyImageSubDataEXT with GL_TEXTURE_2D_MULTISAMPLE_ARRAY, -// RGBA8->RGBA8 copy -// RGB8->RGB8 copy -TEST_P(MultisampleTexture2DTestES31, CopyMultisampleArrayImageEXT) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - testCopyMultisampleArrayImage(APIExtensionVersion::EXT, GL_RGBA8); - testCopyMultisampleArrayImage(APIExtensionVersion::EXT, GL_RGB8); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); } -// Test glCopyImageSubDataOES with GL_TEXTURE_2D_MULTISAMPLE_ARRAY, -// RGBA8->RGBA8 copy -// RGB8->RGB8 copy -TEST_P(MultisampleTexture2DTestES31, CopyMultisampleArrayImageOES) +// Test that texture completeness is updated if texture base level changes. +// GLES 3.0.4 section 3.8.13 Texture completeness +TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image")); - testCopyMultisampleArrayImage(APIExtensionVersion::OES, GL_RGBA8); - testCopyMultisampleArrayImage(APIExtensionVersion::OES, GL_RGB8); -} + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + std::vector texDataGreen(8u * 8u, GLColor::green); -// Depth/Stencil textures cannot be 3D. -TEST_P(Texture3DTestES3, DepthStencil3DDisallowed) -{ - const std::array, 6> testConfigs = { - std::make_tuple(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT), - std::make_tuple(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT), - std::make_tuple(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT), - std::make_tuple(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV), - std::make_tuple(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8), - std::make_tuple(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE)}; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - for (auto testConfig : testConfigs) - { - const GLenum internalformat = std::get<0>(testConfig); - const GLenum format = std::get<1>(testConfig); - const GLenum type = std::get<2>(testConfig); + // Two levels that are initially unused. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - if (internalformat == GL_STENCIL_INDEX8 && !IsGLExtensionEnabled("GL_OES_texture_stencil8")) - { - continue; - } + // One level that is initially used - only this level should affect completeness. + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - GLTexture depthTexture; - glBindTexture(GL_TEXTURE_3D, depthTexture); - glTexImage3D(GL_TEXTURE_3D, 0, internalformat, 16, 16, 16, 0, format, type, nullptr); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); - glTexStorage3D(GL_TEXTURE_3D, 2, internalformat, 16, 16, 16); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); - } -} + EXPECT_GL_NO_ERROR(); -// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not -// have images defined. -TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined) -{ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - std::vector texDataGreen(2u * 2u * 2u, GLColor::green); - glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Switch the base level to level 1. The levels within the used range now have inconsistent + // dimensions and the texture should be incomplete. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); } -// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have -// dimensions that don't fit the images inside the range. +// Test that texture is not complete if base level is greater than max level. // GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) +TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - std::vector texDataRed(8u * 8u * 8u, GLColor::red); - std::vector texDataGreen(2u * 2u * 2u, GLColor::green); - std::vector texDataCyan(2u * 2u * 2u, GLColor::cyan); - - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glBindTexture(GL_TEXTURE_2D, mTexture2D); - // Two levels that are initially unused. - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataRed.data()); - glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataCyan.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - // One level that is used - only this level should affect completeness. - glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + // Texture should be incomplete. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); +} - ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL()); +// Test base level is greater than max level for 2-level textures. +TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMax2Levels) +{ + std::vector texDataRed(2u * 2u, GLColor::red); - // Switch the level that is being used to the cyan level 2. - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2); + GLTexture tex2D; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); EXPECT_GL_NO_ERROR(); + // Texture should be complete. + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Texture should be incomplete. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); + // Texture should be complete. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not -// have images defined. -TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined) +// Test base level is greater than max level for 3-level textures. +TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel3Levels) { + GLColor expectedColor[] = {GLColor::red, GLColor::green, GLColor::blue, GLColor::black}; + std::vector texDataRed(4u * 4u, GLColor::red); + std::vector texDataGreen(2u * 2u, GLColor::green); + + GLTexture tex2D; glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); - std::vector texDataGreen(2u * 2u * 2u, GLColor::green); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + glBindTexture(GL_TEXTURE_2D, tex2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data()); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen.data()); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1); + glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue); EXPECT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + for (int base = 0; base < 3; ++base) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); + for (int max = 0; max < 3; ++max) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor[base <= max ? base : 3]); + } + } - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + for (int max = 0; max < 3; ++max) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max); + for (int base = 0; base < 3; ++base) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor[base <= max ? base : 3]); + } + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + for (int base = 0; base < 3; ++base) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); + for (int max = 0; max < 3; ++max) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor[base]); + } + } + + for (int max = 0; max < 3; ++max) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max); + for (int base = 0; base < 3; ++base) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base); + drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor[base]); + } + } } -// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have -// dimensions that don't fit the images inside the range. -// GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions) +// Test that immutable texture base level and max level are clamped. +// GLES 3.0.4 section 3.8.10 subsection Mipmapping +TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange) { - // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV) - ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, m2DArrayTexture); - std::vector texDataRed(8u * 8u * 8u, GLColor::red); - std::vector texDataGreen(2u * 2u * 2u, GLColor::green); - std::vector texDataCyan(2u * 2u * 2u, GLColor::cyan); + glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - // Two levels that are initially unused. - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataRed.data()); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataCyan.data()); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); - // One level that is used - only this level should affect completeness. - glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1); + // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level + // should be clamped to [base_level, levels - 1]. + // GLES 3.0.4 section 3.8.10 subsection Mipmapping + // In the case of this test, those rules make the effective base level and max level 0. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); + // Texture should be complete. EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} - ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL()); - - // Switch the level that is being used to the cyan level 2. - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2); +// Test that changing base level works when it affects the format of the texture. +TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel) +{ + // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV) + ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); - EXPECT_GL_NO_ERROR(); + ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL()); - drawQuad(mProgram, "position", 0.5f); + // Observed incorrect rendering on AMD OpenGL. + ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL()); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); -} + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + std::vector texDataCyan(4u * 4u, GLColor::cyan); + std::vector texDataGreen(4u * 4u, GLColor::green); -// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug -// in the Vulkan backend where the old higher-layer-count data upload was not removed. -TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse) -{ - int px = getWindowWidth() / 2; - int py = getWindowHeight() / 2; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); + // RGBA8 level that's initially unused. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataCyan.data()); - // Fill the whole texture with red, then redefine it and fill with green - std::vector pixelsRed(2 * 2 * 4, GLColor::red); - std::vector pixelsGreen(2 * 2 * 2, GLColor::green); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsRed.data()); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsGreen.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - EXPECT_GL_NO_ERROR(); + // RG8 level that's initially used, with consistent dimensions with level 0 but a different + // format. It reads green channel data from the green and alpha channels of texDataGreen + // (this is a bit hacky but works). + glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data()); - glUseProgram(mProgram); EXPECT_GL_NO_ERROR(); - // Draw the first slice - glUniform1i(mTextureArraySliceUniformLocation, 0); drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); - // Draw the second slice - glUniform1i(mTextureArraySliceUniformLocation, 1); - drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); -} + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); -// Create a 2D array texture and update layers with data and test that pruning -// of superseded updates works as expected. -TEST_P(Texture2DArrayTestES3, TextureArrayPruneSupersededUpdates) -{ - constexpr uint32_t kTexWidth = 256; - constexpr uint32_t kTexHeight = 256; - constexpr uint32_t kTexLayers = 3; + // Switch the texture to use the cyan level 0 with the RGBA format. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); EXPECT_GL_NO_ERROR(); - // Initialize entire texture. - constexpr GLColor kInitialExpectedColor = GLColor(201u, 201u, 201u, 201u); - std::vector initialData(kTexWidth * kTexHeight * kTexLayers, kInitialExpectedColor); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexWidth, kTexHeight, kTexLayers, 0, GL_RGBA, - GL_UNSIGNED_BYTE, initialData.data()); + drawQuad(mProgram, "position", 0.5f); - // Upate different layers with different colors, these together should supersed - // the entire init update - constexpr GLColor kExpectedColor[] = {GLColor(32u, 32u, 32u, 32u), GLColor(64u, 64u, 64u, 64u), - GLColor(128u, 128u, 128u, 128u)}; - std::vector supersedingData[] = { - std::vector(kTexWidth * kTexHeight, kExpectedColor[0]), - std::vector(kTexWidth * kTexHeight, kExpectedColor[1]), - std::vector(kTexWidth * kTexHeight, kExpectedColor[2])}; + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); +} - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, GL_RGBA, - GL_UNSIGNED_BYTE, supersedingData[0].data()); - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, kTexWidth, kTexHeight, 1, GL_RGBA, - GL_UNSIGNED_BYTE, supersedingData[1].data()); - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, kTexWidth, kTexHeight, 1, GL_RGBA, - GL_UNSIGNED_BYTE, supersedingData[2].data()); +// Test that setting a texture image works when base level is out of range. +TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glUseProgram(mProgram); - EXPECT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000); - // Draw layer 0 - glUniform1i(mTextureArraySliceUniformLocation, 0); - drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); - // Draw layer 1 - glUniform1i(mTextureArraySliceUniformLocation, 1); - drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[1]); - // Draw layer 2 - glUniform1i(mTextureArraySliceUniformLocation, 2); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[2]); + + // Texture should be complete. + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in -// the Vulkan backend where the old higher-layer-count data upload was not removed. -TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse) +// In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG +// RBA->RGBA8, with 1.0 in the alpha channel. This test covers a bug where redefining array textures +// with these formats does not work as expected. +TEST_P(Texture2DArrayTestES3, RedefineInittableArray) { - int px = getWindowWidth() / 2; - int py = getWindowHeight() / 2; + std::vector pixelData; + for (size_t count = 0; count < 5000; count++) + { + pixelData.push_back(0u); + pixelData.push_back(255u); + pixelData.push_back(0u); + } glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); + glUseProgram(mProgram); + glUniform1i(mTextureArrayLocation, 0); - // Fill the whole texture with red. - std::vector pixelsRed(2 * 2 * 4, GLColor::red); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsRed.data()); + // The first draw worked correctly. + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, + &pixelData[0]); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - EXPECT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); + drawQuad(mProgram, "position", 1.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - glUseProgram(mProgram); - EXPECT_GL_NO_ERROR(); + // The dimension of the respecification must match the original exactly to trigger the bug. + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, + &pixelData[0]); + drawQuad(mProgram, "position", 1.0f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - // Draw the first slice - glUniform1i(mTextureArraySliceUniformLocation, 0); - drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red); + ASSERT_GL_NO_ERROR(); +} - // Draw the fourth slice - glUniform1i(mTextureArraySliceUniformLocation, 3); - drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red); +// Test shadow sampler and regular non-shadow sampler coexisting in the same shader. +// This test is needed especially to confirm that sampler registers get assigned correctly on +// the HLSL backend even when there's a mix of different HLSL sampler and texture types. +TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, mTexture3D); + GLubyte texData[4]; + texData[0] = 0; + texData[1] = 60; + texData[2] = 0; + texData[3] = 255; + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); - // Redefine the image and fill with green - std::vector pixelsGreen(2 * 2 * 2, GLColor::green); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsGreen.data()); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, mTextureShadow); + GLfloat depthTexData[1]; + depthTexData[0] = 0.5f; + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + depthTexData); - // Draw the first slice - glUniform1i(mTextureArraySliceUniformLocation, 0); + glUseProgram(mProgram); + glUniform1f(mDepthRefUniformLocation, 0.3f); + glUniform1i(mTexture3DUniformLocation, 0); + glUniform1i(mTextureShadowUniformLocation, 1); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); + // The shader writes 0.5 * + + EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2); - // Draw the second slice - glUniform1i(mTextureArraySliceUniformLocation, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER); drawQuad(mProgram, "position", 0.5f); EXPECT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green); + // The shader writes 0.5 * + + EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2); } -// Create a 2D array texture, use it, then redefine one level without changing dimensions. -TEST_P(Texture2DArrayTestES3, RedefineLevelData) +// Test multiple different sampler types in the same shader. +// This test makes sure that even if sampler / texture registers get grouped together based on type +// or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer +// still has the right register index information for each ESSL sampler. +// The tested ESSL samplers have the following types in D3D11 HLSL: +// sampler2D: Texture2D + SamplerState +// samplerCube: TextureCube + SamplerState +// sampler2DShadow: Texture2D + SamplerComparisonState +// samplerCubeShadow: TextureCube + SamplerComparisonState +TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw) { - glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + GLubyte texData[4]; + texData[0] = 0; + texData[1] = 0; + texData[2] = 120; + texData[3] = 255; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); - // Fill both levels with red - std::vector pixelsRed(2 * 2 * 1, GLColor::red); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsRed.data()); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsRed.data()); - ASSERT_GL_NO_ERROR(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); + texData[0] = 0; + texData[1] = 90; + texData[2] = 0; + texData[3] = 255; + glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, + texData); - // Check that both levels are red - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, mTexture2DShadow); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + GLfloat depthTexData[1]; + depthTexData[0] = 0.5f; + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + depthTexData); - // Redefine level 1 with green - glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - &GLColor::green); - ASSERT_GL_NO_ERROR(); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + depthTexData[0] = 0.2f; + glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, + depthTexData); - // Check that level 0 is red and level 1 is green - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + // http://anglebug.com/42262588: TODO: Add a DS texture case + + EXPECT_GL_NO_ERROR(); + + glUseProgram(mProgram); + glUniform1f(mDepthRefUniformLocation, 0.3f); + glUniform1i(mTexture2DUniformLocation, 0); + glUniform1i(mTextureCubeUniformLocation, 1); + glUniform1i(mTexture2DShadowUniformLocation, 2); + glUniform1i(mTextureCubeShadowUniformLocation, 3); + + drawQuad(mProgram, "position", 0.5f); + EXPECT_GL_NO_ERROR(); + // The shader writes: + // + + // + + // 0.25 * + + // 0.125 * + EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2); } -// Create a 3D texture, use it, then redefine one level without changing dimensions. -TEST_P(Texture3DTestES3, RedefineLevelData) +// Test different base levels on textures accessed through the same sampler array. +// Calling textureSize() on the samplers hits the D3D sampler metadata workaround. +TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray) { - glBindTexture(GL_TEXTURE_3D, mTexture3D); + ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11()); - // Fill both levels with red - std::vector pixelsRed(2 * 2 * 1, GLColor::red); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsRed.data()); - glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - pixelsRed.data()); - ASSERT_GL_NO_ERROR(); + // http://anglebug.com/42263017 + ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsWindows() && IsD3D11()); - // Check that both levels are red - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2DA); + GLsizei size = 64; + for (GLint level = 0; level < 7; ++level) + { + ASSERT_LT(0, size); + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + size = size / 2; + } + ASSERT_EQ(0, size); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - // Redefine level 1 with green - glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - &GLColor::green); - ASSERT_GL_NO_ERROR(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, mTexture2DB); + size = 128; + for (GLint level = 0; level < 8; ++level) + { + ASSERT_LT(0, size); + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + size = size / 2; + } + ASSERT_EQ(0, size); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3); + EXPECT_GL_NO_ERROR(); + + glUseProgram(mProgram); + glUniform1i(mTexture0Location, 0); + glUniform1i(mTexture1Location, 1); - // Check that level 0 is red and level 1 is green - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_GL_NO_ERROR(); + // Red channel: width of level 1 of texture A: 32. + // Green channel: width of level 3 of texture B: 16. + EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2); } -// Test that texture completeness is updated if texture max level changes. -// GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - std::vector texDataGreen(8u * 8u, GLColor::green); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - - // A level that is initially unused. - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - - // One level that is initially used - only this level should affect completeness. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} - // Switch the max level to level 1. The levels within the used range now have inconsistent - // dimensions and the texture should be incomplete. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); + GLTexture texture2D; + glBindTexture(GL_TEXTURE_2D, texture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBX8_ANGLE, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glActiveTexture(GL_TEXTURE0); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly -// keep the staged clear. http://anglebug.com/345532371 -TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenRead) +// Test that data upload to RGBX works. +TEST_P(Texture2DTestES3, TextureRGBXUpload) { - constexpr GLsizei kTexWidth = 128; - constexpr GLsizei kTexHeight = 128; - constexpr GLsizei kTexDepth = 6; - // Create a single leveled texture with 6 layers - GLTexture tex; - glBindTexture(GL_TEXTURE_2D_ARRAY, tex); - glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); - // Stage clear to red on all layers - GLFramebuffer drawFBO; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - for (GLsizei layer = 0; layer < kTexDepth; layer++) - { - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); - glClear(GL_COLOR_BUFFER_BIT); - } + const size_t kWidth = 32; + const size_t kHeight = 32; - // TexSubImage with green color on half of the image of layer 2,3,4 - std::vector updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green); - GLsizei layerStart = 2; - GLsizei layerCount = 3; - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount, - GL_RGBA, GL_UNSIGNED_BYTE, updateData.data()); + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight); - // Now read out layer 2/3/4 - GLFramebuffer readFBO; - glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); - for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++) - { - glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); - EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G, - GLColor::green.B, GLColor::green.A); - EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G, - GLColor::red.B, GLColor::red.A); - } + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); ASSERT_GL_NO_ERROR(); -} - -// Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly -// keep the staged clear. http://anglebug.com/345532371 -TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead) -{ - constexpr GLsizei kTexWidth = 128; - constexpr GLsizei kTexHeight = 128; - constexpr GLsizei kTexDepth = 6; - // Create a single leveled texture with 6 layers - GLTexture tex; - glBindTexture(GL_TEXTURE_2D_ARRAY, tex); - glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Stage clear to red on all layers - GLFramebuffer drawFBO; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - for (GLsizei layer = 0; layer < kTexDepth; layer++) - { - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); - glClear(GL_COLOR_BUFFER_BIT); - } + // Upload data to an RGBX texture + const GLColorRGB kColor(100, 200, 55); + std::vector data(kWidth * kHeight, kColor); - // TexSubImage with green color on half of the image of layer 2,3,4 - std::vector updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green); - GLsizei layerStart = 2; - GLsizei layerCount = 3; - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount, - GL_RGBA, GL_UNSIGNED_BYTE, updateData.data()); + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, data.data()); + ASSERT_GL_NO_ERROR(); - // Now Draw to fbo on layerStart with blue color - GLsizei blueQuadLayer = 2; - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, blueQuadLayer); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue()); - glUseProgram(blueProgram); - drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f); + // Sample from the texture + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5); - // Now read out layer 2/3/4 - GLFramebuffer readFBO; - glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); - for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++) - { - glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); - if (layer == blueQuadLayer) - { - // green + blue = cyan - EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::cyan.R, GLColor::cyan.G, - GLColor::cyan.B, GLColor::cyan.A); - // red + blue = magenta - EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::magenta.R, - GLColor::magenta.G, GLColor::magenta.B, GLColor::magenta.A); - } - else - { - EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G, - GLColor::green.B, GLColor::green.A); - EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G, - GLColor::red.B, GLColor::red.A); - } - } + const GLColor kExpect(kColor.R, kColor.G, kColor.B, 255); + EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1); + EXPECT_PIXEL_COLOR_NEAR(0, 1, kExpect, 1); + EXPECT_PIXEL_COLOR_NEAR(1, 0, kExpect, 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpect, 1); + EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpect, 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpect, 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, kHeight / 2, kExpect, 1); ASSERT_GL_NO_ERROR(); } -// Test that compressed textures ignore the pixel unpack state. -// (https://crbug.org/1267496) -TEST_P(Texture3DTestES3, PixelUnpackStateTexImage) +// Test that data download from RGBX works. +TEST_P(Texture2DTestES3, TextureRGBXDownload) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && - !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5); - glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D); + const size_t kWidth = 32; + const size_t kHeight = 32; - uint8_t data[64] = {0}; - glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64, - data); - EXPECT_GL_NO_ERROR(); -} + GLTexture color; + glBindTexture(GL_TEXTURE_2D, color); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight); -// Test that compressed textures ignore the pixel unpack state. -// (https://crbug.org/1267496) -TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && - !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + ASSERT_GL_NO_ERROR(); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D); + // Render to the RGBX texture + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glUseProgram(program); + GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorLoc, -1); - uint8_t data[64] = {0}; - glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64, - data); - EXPECT_GL_NO_ERROR(); + glUniform4f(colorLoc, 0.3f, 0.6f, 0.8f, 0.2f); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5); + // Readback as RGBX. + std::vector readback(kWidth * kHeight); + glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data()); + ASSERT_GL_NO_ERROR(); - glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4, - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data); - EXPECT_GL_NO_ERROR(); + const GLColor kExpect(76, // 0.3f * 255 + 153, // 0.6f * 255 + 204, // 0.8f * 255 + 255); + + for (size_t y = 0; y < kHeight; y++) + { + for (size_t x = 0; x < kWidth; x++) + { + const GLColor actualColor = readback[y * kWidth + x]; + + EXPECT_NEAR(actualColor.R, kExpect.R, 1) << x << "x" << y; + EXPECT_NEAR(actualColor.G, kExpect.G, 1) << x << "x" << y; + EXPECT_NEAR(actualColor.B, kExpect.B, 1) << x << "x" << y; + EXPECT_EQ(actualColor.A, kExpect.A) << x << "x" << y; + } + } + ASSERT_GL_NO_ERROR(); } -// Test that 3D texture completeness is updated if texture max level changes. -// GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTest, TextureLuminanceImplicitAlpha1) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - std::vector texDataGreen(2u * 2u * 2u, GLColor::green); + setUpProgram(); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr); + EXPECT_GL_NO_ERROR(); - // A level that is initially unused. - glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); + drawQuad(mProgram, "position", 0.5f); - // One level that is initially used - only this level should affect completeness. - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); +// Validate that every component of the pixel will be equal to the luminance value we've set +// and that the alpha channel will be 1 (or 255 to be exact). +TEST_P(Texture2DTest, TextureLuminanceRGBSame) +{ + setUpProgram(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + uint8_t pixel = 50; + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel, pixel, pixel, 255)); +} - // Switch the max level to level 1. The levels within the used range now have inconsistent - // dimensions and the texture should be incomplete. - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1); +// Validate that every component of the pixel will be equal to the luminance value we've set +// and that the alpha channel will be the second component. +TEST_P(Texture2DTest, TextureLuminanceAlphaRGBSame) +{ + setUpProgram(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + uint8_t pixel[] = {50, 25}; + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA, + GL_UNSIGNED_BYTE, pixel); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel[0], pixel[0], pixel[0], pixel[1])); } -// Test that texture completeness is updated if texture base level changes. -// GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTest, TextureLuminance32ImplicitAlpha1) { + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float")); + ANGLE_SKIP_TEST_IF(IsD3D9()); + ANGLE_SKIP_TEST_IF(IsVulkan()); + + setUpProgram(); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - std::vector texDataGreen(8u * 8u, GLColor::green); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr); + EXPECT_GL_NO_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + drawQuad(mProgram, "position", 0.5f); - // Two levels that are initially unused. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); - glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} - // One level that is initially used - only this level should affect completeness. - glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataGreen.data()); +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTest, TextureLuminance16ImplicitAlpha1) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float")); + ANGLE_SKIP_TEST_IF(IsD3D9()); + ANGLE_SKIP_TEST_IF(IsVulkan()); + // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260416 is fixed + ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); + setUpProgram(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, nullptr); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} - // Switch the base level to level 1. The levels within the used range now have inconsistent - // dimensions and the texture should be incomplete. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); +// Test that CopyTexImage2D does not trigger assertion after CompressedTexImage2D. +// https://crbug.com/1216276 +TEST_P(Texture2DTest, CopyAfterCompressed) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1")); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, nullptr); EXPECT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); - - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 0, 0, 4, 4, 0); + EXPECT_GL_NO_ERROR(); } -// Test that texture is not complete if base level is greater than max level. -// GLES 3.0.4 section 3.8.13 Texture completeness -TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1) { + ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - // Texture should be incomplete. - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test that immutable texture base level and max level are clamped. -// GLES 3.0.4 section 3.8.10 subsection Mipmapping -TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1) { + ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); - - // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level - // should be clamped to [base_level, levels - 1]. - // GLES 3.0.4 section 3.8.10 subsection Mipmapping - // In the case of this test, those rules make the effective base level and max level 0. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000); - EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - // Texture should be complete. - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test that changing base level works when it affects the format of the texture. -TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1) { - // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV) - ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); - - ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL()); - - // Observed incorrect rendering on AMD OpenGL. - ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL()); + ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - std::vector texDataCyan(4u * 4u, GLColor::cyan); - std::vector texDataGreen(4u * 4u, GLColor::green); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - - // RGBA8 level that's initially unused. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - texDataCyan.data()); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - - // RG8 level that's initially used, with consistent dimensions with level 0 but a different - // format. It reads green channel data from the green and alpha channels of texDataGreen - // (this is a bit hacky but works). - glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data()); - - EXPECT_GL_NO_ERROR(); - - drawQuad(mProgram, "position", 0.5f); - - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - - // Switch the texture to use the cyan level 0 with the RGBA format. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test that setting a texture image works when base level is out of range. -TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1) { + ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); - EXPECT_GL_NO_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - drawQuad(mProgram, "position", 0.5f); - // Texture should be complete. - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); -} - -// In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG -// RBA->RGBA8, with 1.0 in the alpha channel. This test covers a bug where redefining array textures -// with these formats does not work as expected. -TEST_P(Texture2DArrayTestES3, RedefineInittableArray) -{ - std::vector pixelData; - for (size_t count = 0; count < 5000; count++) - { - pixelData.push_back(0u); - pixelData.push_back(255u); - pixelData.push_back(0u); - } - - glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture); - glUseProgram(mProgram); - glUniform1i(mTextureArrayLocation, 0); - - // The first draw worked correctly. - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, - &pixelData[0]); - - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); - drawQuad(mProgram, "position", 1.0f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - - // The dimension of the respecification must match the original exactly to trigger the bug. - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, - &pixelData[0]); - drawQuad(mProgram, "position", 1.0f); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - - ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test shadow sampler and regular non-shadow sampler coexisting in the same shader. -// This test is needed especially to confirm that sampler registers get assigned correctly on -// the HLSL backend even when there's a mix of different HLSL sampler and texture types. -TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw) -{ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, mTexture3D); - GLubyte texData[4]; - texData[0] = 0; - texData[1] = 60; - texData[2] = 0; - texData[3] = 255; - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, mTextureShadow); - GLfloat depthTexData[1]; - depthTexData[0] = 0.5f; - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT, - depthTexData); - - glUseProgram(mProgram); - glUniform1f(mDepthRefUniformLocation, 0.3f); - glUniform1i(mTexture3DUniformLocation, 0); - glUniform1i(mTextureShadowUniformLocation, 1); +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1) +{ + ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - drawQuad(mProgram, "position", 0.5f); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); EXPECT_GL_NO_ERROR(); - // The shader writes 0.5 * + - EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER); drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - // The shader writes 0.5 * + - EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2); + + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test multiple different sampler types in the same shader. -// This test makes sure that even if sampler / texture registers get grouped together based on type -// or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer -// still has the right register index information for each ESSL sampler. -// The tested ESSL samplers have the following types in D3D11 HLSL: -// sampler2D: Texture2D + SamplerState -// samplerCube: TextureCube + SamplerState -// sampler2DShadow: Texture2D + SamplerComparisonState -// samplerCubeShadow: TextureCube + SamplerComparisonState -TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1) { + ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - GLubyte texData[4]; - texData[0] = 0; - texData[1] = 0; - texData[2] = 120; - texData[3] = 255; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + EXPECT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); - texData[0] = 0; - texData[1] = 90; - texData[2] = 0; - texData[3] = 255; - glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1); - glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - texData); + drawQuad(mProgram, "position", 0.5f); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, mTexture2DShadow); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - GLfloat depthTexData[1]; - depthTexData[0] = 0.5f; - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT, - depthTexData); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - depthTexData[0] = 0.2f; - glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1); - glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, - depthTexData); +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr); + EXPECT_GL_NO_ERROR(); - // http://anglebug.com/42262588: TODO: Add a DS texture case + drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} - glUseProgram(mProgram); - glUniform1f(mDepthRefUniformLocation, 0.3f); - glUniform1i(mTexture2DUniformLocation, 0); - glUniform1i(mTextureCubeUniformLocation, 1); - glUniform1i(mTexture2DShadowUniformLocation, 2); - glUniform1i(mTextureCubeShadowUniformLocation, 3); +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, + nullptr); + EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); - EXPECT_GL_NO_ERROR(); - // The shader writes: - // + - // + - // 0.25 * + - // 0.125 * - EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2); + + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test different base levels on textures accessed through the same sampler array. -// Calling textureSize() on the samplers hits the D3D sampler metadata workaround. -TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray) +// When sampling a texture without an alpha channel, "1" is returned as the alpha value. +// ES 3.0.4 table 3.24 +TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1) { - ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11()); - - // http://anglebug.com/42263017 - ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsWindows() && IsD3D11()); + // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497 + ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL()); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2DA); - GLsizei size = 64; - for (GLint level = 0; level < 7; ++level) - { - ASSERT_LT(0, size); - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - size = size / 2; - } - ASSERT_EQ(0, size); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, mTexture2DB); - size = 128; - for (GLint level = 0; level < 8; ++level) - { - ASSERT_LT(0, size); - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, - nullptr); - size = size / 2; - } - ASSERT_EQ(0, size); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr); EXPECT_GL_NO_ERROR(); - glUseProgram(mProgram); - glUniform1i(mTexture0Location, 0); - glUniform1i(mTexture1Location, 1); + drawQuad(mProgram, "position", 0.5f); - drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_GL_NO_ERROR(); - // Red channel: width of level 1 of texture A: 32. - // Green channel: width of level 3 of texture B: 16. - EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2); + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } // When sampling a texture without an alpha channel, "1" is returned as the alpha value. // ES 3.0.4 table 3.24 -TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1) +TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1) { + // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497 + ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL()); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); @@ -7743,16 +9149,29 @@ TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1) EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1) +// ETC2 punchthrough alpha formats must be initialized to opaque black when emulated +// http://anglebug.com/42265413 +TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDRGB8A1ETC2) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0, + 8, nullptr); + EXPECT_GL_NO_ERROR(); - GLTexture texture2D; - glBindTexture(GL_TEXTURE_2D, texture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBX8_ANGLE, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); +} + +// ETC2 punchthrough alpha formats must be initialized to opaque black when emulated +// http://anglebug.com/42265413 +TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDSRGB8A1ETC2) +{ glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0, + 8, nullptr); EXPECT_GL_NO_ERROR(); drawQuad(mProgram, "position", 0.5f); @@ -7760,476 +9179,695 @@ TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1) EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } -// Test that data upload to RGBX works. -TEST_P(Texture2DTestES3, TextureRGBXUpload) +// Test that compressed textures ignore the pixel unpack state. +// (https://crbug.org/1267496) +TEST_P(Texture2DTestES3, PixelUnpackStateTexImage) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && + !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); - const size_t kWidth = 32; - const size_t kHeight = 32; + glPixelStorei(GL_UNPACK_ROW_LENGTH, 9); + glBindTexture(GL_TEXTURE_2D, mTexture2D); - GLTexture color; - glBindTexture(GL_TEXTURE_2D, color); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight); + uint8_t data[64] = {0}; + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data); + EXPECT_GL_NO_ERROR(); +} - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); - ASSERT_GL_NO_ERROR(); - EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); +// Test that compressed textures ignore the pixel unpack state. +// (https://crbug.org/1267496) +TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && + !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); - // Upload data to an RGBX texture - const GLColorRGB kColor(100, 200, 55); - std::vector data(kWidth * kHeight, kColor); + glBindTexture(GL_TEXTURE_2D, mTexture2D); - GLTexture texture; - glBindTexture(GL_TEXTURE_2D, texture); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, data.data()); + uint8_t data[64] = {0}; + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data); + EXPECT_GL_NO_ERROR(); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 9); + + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, + data); + EXPECT_GL_NO_ERROR(); +} + +// Test for http://anglebug.com/42265405. +TEST_P(Texture2DTestES3, TextureRGBUpdateWithPBO) +{ + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + + glViewport(0, 0, 16, 16); + + GLTexture tex1; + const std::vector texDataRed(16u * 16u, GLColor::red); + const std::vector texDataGreen(16u * 16u, GLColor::green); + + glBindTexture(GL_TEXTURE_2D, tex1); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, texDataRed.data()); + ASSERT_GL_NO_ERROR(); + + GLBuffer pbo; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, texDataGreen.data(), GL_STATIC_DRAW); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, nullptr); ASSERT_GL_NO_ERROR(); - // Sample from the texture - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.5); - - const GLColor kExpect(kColor.R, kColor.G, kColor.B, 255); - EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1); - EXPECT_PIXEL_COLOR_NEAR(0, 1, kExpect, 1); - EXPECT_PIXEL_COLOR_NEAR(1, 0, kExpect, 1); - EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpect, 1); - EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpect, 1); - EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpect, 1); - EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, kHeight / 2, kExpect, 1); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); ASSERT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green); } -// Test that data download from RGBX works. -TEST_P(Texture2DTestES3, TextureRGBXDownload) +// Test drawing to a texture, then overwriting its base level fully and then calling +// glGenerateMipmap. +TEST_P(Texture2DTestES3, RenderToTextureThenFullUpdateAndGenerateMipmap) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - const size_t kWidth = 32; - const size_t kHeight = 32; + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - GLTexture color; - glBindTexture(GL_TEXTURE_2D, color); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight); + glViewport(0, 0, kWidth, kHeight); - GLFramebuffer fbo; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + GLSampler sampler; + GLTexture tex1; + GLTexture tex2; + const std::vector texDataBlue(kWidth * kHeight, GLColor::blue); + const std::vector texDataGreen(kWidth * kHeight, GLColor::green); + + glBindTexture(GL_TEXTURE_2D, tex1); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth, kHeight); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, tex2); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth, kHeight); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); + + GLFramebuffer fb; + glBindFramebuffer(GL_FRAMEBUFFER, fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 1); EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); - // Render to the RGBX texture - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); - glUseProgram(program); - GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform()); - ASSERT_NE(colorLoc, -1); + // Use an expensive draw call to sample from tex1 and render to tex2. Then sample from tex2 + // (into the window surface) again with an expensive draw call. + // + // While the draw call is busy on the GPU, completely overwrite the base level of the texture + // and issue glGenerateMipmap. - glUniform4f(colorLoc, 0.3f, 0.6f, 0.8f, 0.2f); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + glBindSampler(0, sampler); + glSamplerParameteri(sampler, GL_TEXTURE_MIN_LOD, 0); + glSamplerParameteri(sampler, GL_TEXTURE_MAX_LOD, 0); + glBindTexture(GL_TEXTURE_2D, tex1); + drawQuad(program, "position", 0.0f); ASSERT_GL_NO_ERROR(); - // Readback as RGBX. - std::vector readback(kWidth * kHeight); - glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data()); + glBindTexture(GL_TEXTURE_2D, tex2); + glSamplerParameteri(sampler, GL_TEXTURE_MIN_LOD, 1); + glSamplerParameteri(sampler, GL_TEXTURE_MAX_LOD, 1); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + drawQuad(program, "position", 0.0f); ASSERT_GL_NO_ERROR(); - const GLColor kExpect(76, // 0.3f * 255 - 153, // 0.6f * 255 - 204, // 0.8f * 255 - 255); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + texDataBlue.data()); + glGenerateMipmap(GL_TEXTURE_2D); + ASSERT_GL_NO_ERROR(); - for (size_t y = 0; y < kHeight; y++) - { - for (size_t x = 0; x < kWidth; x++) - { - const GLColor actualColor = readback[y * kWidth + x]; + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - EXPECT_NEAR(actualColor.R, kExpect.R, 1) << x << "x" << y; - EXPECT_NEAR(actualColor.G, kExpect.G, 1) << x << "x" << y; - EXPECT_NEAR(actualColor.B, kExpect.B, 1) << x << "x" << y; - EXPECT_EQ(actualColor.A, kExpect.A) << x << "x" << y; - } - } + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); ASSERT_GL_NO_ERROR(); + + glBindFramebuffer(GL_FRAMEBUFFER, fb); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kHeight / 2, GLColor::blue); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTest, TextureLuminanceImplicitAlpha1) +// Test sampling from a texture, then overwriting a level before its base level fully, calling +// glGenerateMipmap and then copying out the result out of its non-zero base level. +TEST_P(Texture2DTestES3, SampleThenFullUpdateAndGenerateMipmapThenCopyLevel1) { - setUpProgram(); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_NO_ERROR(); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); - drawQuad(mProgram, "position", 0.5f); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + glViewport(0, 0, kWidth, kHeight); -// Validate that every component of the pixel will be equal to the luminance value we've set -// and that the alpha channel will be 1 (or 255 to be exact). -TEST_P(Texture2DTest, TextureLuminanceRGBSame) -{ - setUpProgram(); + GLTexture tex1; + GLTexture tex2; + std::vector texDataRed(kWidth * kHeight * 3, 0); + std::vector texDataGreen(kWidth * kHeight * 3, 0); + for (size_t i = 0; i < texDataRed.size(); i += 3) + { + texDataRed[i + 0] = 255; + texDataGreen[i + 1] = 255; + } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - uint8_t pixel = 50; - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel); - EXPECT_GL_NO_ERROR(); + GLSampler sampler; + glBindSampler(0, sampler); + glSamplerParameteri(sampler, GL_TEXTURE_MIN_LOD, 1); + glSamplerParameteri(sampler, GL_TEXTURE_MAX_LOD, 1); + ASSERT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + // Use an expensive draw call to sample from tex1. Then overwrite its base level fully and call + // glGenerateMipmap while the draw call is busy on the GPU. Then copy level 1 of tex1 into tex2 + // and sample from tex2. This makes sure the values copied out of tex1 are the results of + // glGenerateMipmap. - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel, pixel, pixel, 255)); -} + glBindTexture(GL_TEXTURE_2D, tex1); + glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGB8, kWidth, kHeight); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth / 2, kHeight / 2, GL_RGB, GL_UNSIGNED_BYTE, + texDataGreen.data()); + ASSERT_GL_NO_ERROR(); -// Validate that every component of the pixel will be equal to the luminance value we've set -// and that the alpha channel will be the second component. -TEST_P(Texture2DTest, TextureLuminanceAlphaRGBSame) -{ - setUpProgram(); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - uint8_t pixel[] = {50, 25}; - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA, - GL_UNSIGNED_BYTE, pixel); - EXPECT_GL_NO_ERROR(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, + texDataRed.data()); + glGenerateMipmap(GL_TEXTURE_2D); + ASSERT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + glBindTexture(GL_TEXTURE_2D, tex2); + glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGB8, kWidth, kHeight); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glCopyImageSubDataEXT(tex1, GL_TEXTURE_2D, 1, 0, 0, 0, tex2, GL_TEXTURE_2D, 1, 0, 0, 0, + kWidth / 2, kHeight / 2, 1); + ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel[0], pixel[0], pixel[0], pixel[1])); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTest, TextureLuminance32ImplicitAlpha1) +// Sample from image, update base level and generate mipmap. This is to test the same scenario but +// if some tracking kicks in after that pattern is repeated a few times. +TEST_P(Texture2DTestES3, SampleThenUpdateBaseLevelAndGenerateMipmapInLoop) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float")); - ANGLE_SKIP_TEST_IF(IsD3D9()); - ANGLE_SKIP_TEST_IF(IsVulkan()); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - setUpProgram(); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr); - EXPECT_GL_NO_ERROR(); + glViewport(0, 0, kWidth, kHeight); - drawQuad(mProgram, "position", 0.5f); + GLTexture tex1; + GLTexture tex2; + const std::vector originalColor(kWidth * kHeight, GLColor::yellow); + const std::vector updateColor1(kWidth * kHeight, GLColor::red); + const std::vector updateColor2(kWidth * kHeight, GLColor::green); + const std::vector updateColor3(kWidth * kHeight, GLColor::blue); + const std::vector *updateColors[] = {&updateColor1, &updateColor2, &updateColor3}; - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + glBindTexture(GL_TEXTURE_2D, tex1); + glTexStorage2D(GL_TEXTURE_2D, 5, GL_RGBA8, kWidth, kHeight); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + originalColor.data()); + ASSERT_GL_NO_ERROR(); -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTest, TextureLuminance16ImplicitAlpha1) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float")); - ANGLE_SKIP_TEST_IF(IsD3D9()); - ANGLE_SKIP_TEST_IF(IsVulkan()); - // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260416 is fixed - ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES()); + // Use an expensive draw call to sample from tex1. Then overwrite its base level fully and call + // glGenerateMipmap while the draw call is busy on the GPU. + for (uint32_t i = 0; i < 13; ++i) + { + for (const auto *updateColor : updateColors) + { + drawQuad(program, "position", 0.0f); - setUpProgram(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + updateColor->data()); + glGenerateMipmap(GL_TEXTURE_2D); + } + } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, nullptr); - EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, updateColor2[0]); + ASSERT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + // For completeness, also sample from level 1 of the texture and make sure generate mipmap + // worked. + ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, updateColor3[0]); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, updateColor3[0]); } -// Test that CopyTexImage2D does not trigger assertion after CompressedTexImage2D. -// https://crbug.com/1216276 -TEST_P(Texture2DTest, CopyAfterCompressed) +// Test sampling from a texture with base level 1, then add level 0 with same size as level 1, and +// sample again. The contents of level 1 shouldn't be discarded. +TEST_P(Texture2DTestES3, SampleThenAddLevel0ThenSampleAgain) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1")); - - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, nullptr); - EXPECT_GL_NO_ERROR(); - - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 0, 0, 4, 4, 0); - EXPECT_GL_NO_ERROR(); -} + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1) -{ - ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_GL_NO_ERROR(); + glViewport(0, 0, kWidth, kHeight); - drawQuad(mProgram, "position", 0.5f); + GLTexture tex; + const std::vector texDataBlue(kWidth * kHeight, GLColor::blue); + const std::vector texDataGreen(kWidth * kHeight, GLColor::green); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + // Use an expensive draw call to sample from tex. Then add level 0 to it with the same size and + // sample again. In the Vulkan backend, the backing image of the texture may be changed on + // write. This test makes sure the backing image's level (0) is not mistaken with the GL level + // being written (also 0), in which case the contents of the image would be lost. -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1) -{ - ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataBlue.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + ASSERT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, kWidth / 2, kHeight); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_GL_NO_ERROR(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); - drawQuad(mProgram, "position", 0.5f); + glScissor(kWidth / 2, 0, kWidth - kWidth / 2, kHeight); + drawQuad(program, "position", 0.0f); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); + ASSERT_GL_NO_ERROR(); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1) +// Test glGenerateMipmap followed by sample (of a non-base level) in a draw call, then a full update +// of the base level of the image and sample the same level again. +TEST_P(Texture2DTestES3, GenerateMipmapThenSampleThenFullUpdateThenSampleAgain) { - ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); + + glViewport(0, 0, kWidth, kHeight); + + GLTexture tex; + const std::vector texDataRed(kWidth * kHeight, GLColor::red); + const std::vector texDataGreen(kWidth * kHeight, GLColor::green); + GLSampler sampler; + glBindSampler(0, sampler); + glSamplerParameteri(sampler, GL_TEXTURE_MIN_LOD, 1); + glSamplerParameteri(sampler, GL_TEXTURE_MAX_LOD, 1); + ASSERT_GL_NO_ERROR(); + + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glGenerateMipmap(GL_TEXTURE_2D); + ASSERT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + ASSERT_GL_NO_ERROR(); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1) +// Test completely overwriting a texture with a data upload while the texture is being sampled from +// by the GPU. +// Test uses a renderable format. +TEST_P(Texture2DTestES3, SampleThenFullUpdateThenSampleAgain) { - ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - drawQuad(mProgram, "position", 0.5f); + glViewport(0, 0, kWidth, kHeight); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + GLTexture tex; + const std::vector texDataRed(kWidth * kHeight, GLColor::red); + const std::vector texDataGreen(kWidth * kHeight, GLColor::green); + const std::vector texDataBlue(kWidth * kHeight, GLColor::blue); -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1) -{ - ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + // Include an unused level in the texture + glTexImage2D(GL_TEXTURE_2D, 7, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataBlue.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_GL_NO_ERROR(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + texDataGreen.data()); + drawQuad(program, "position", 0.0f); - drawQuad(mProgram, "position", 0.5f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + ASSERT_GL_NO_ERROR(); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + // Ensure the unused level is not lost. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 7); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7); + drawQuad(program, "position", 0.0f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue); + ASSERT_GL_NO_ERROR(); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1) +// Test completely overwriting a texture with a data upload while the texture is being sampled from +// by the GPU. +// Tests uses a LUMA format. +TEST_P(Texture2DTestES3, SampleThenFullUpdateThenSampleAgainLUMA) { - ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL()); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - drawQuad(mProgram, "position", 0.5f); + glViewport(0, 0, kWidth, kHeight); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + GLTexture tex; + // For simplicity, one GLColor is used for two LUMA pixel values. + const std::vector texData1(kWidth * kHeight / 2, GLColor(127, 63, 127, 63)); + const std::vector texData2(kWidth * kHeight / 2, GLColor(191, 31, 191, 31)); -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1) -{ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr); - EXPECT_GL_NO_ERROR(); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, kWidth, kHeight, 0, GL_LUMINANCE_ALPHA, + GL_UNSIGNED_BYTE, texData1.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + texData2.data()); + drawQuad(program, "position", 0.0f); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 191, 191, 31), 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, GLColor(191, 191, 191, 31), 1); + ASSERT_GL_NO_ERROR(); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1) +// Test completely overwriting a texture with a data upload while the texture is being sampled from +// by the GPU. +// Tests uses a compressed format. +TEST_P(Texture2DTestES3, SampleThenFullUpdateThenSampleAgainCompressed) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, - nullptr); - EXPECT_GL_NO_ERROR(); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_ldr")); - drawQuad(mProgram, "position", 0.5f); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1) -{ - // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497 - ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL()); + glViewport(0, 0, kWidth, kHeight); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr); - EXPECT_GL_NO_ERROR(); + // Based on https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#ASTC, a 4x4 + // block of constant format has the following pattern: + // 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, r, r, g, g, b, b, a, a + constexpr uint8_t block1[16] = {0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0x7F, 0x3F, 0x3F, 0xBF, 0xBF, 0xFF, 0xFF}; + constexpr uint8_t block2[16] = {0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x1F, 0x1F, 0x5F, 0x5F, 0xEF, 0xEF, 0xFF, 0xFF}; - drawQuad(mProgram, "position", 0.5f); + GLTexture tex; + std::vector texData1(kWidth * kHeight); + std::vector texData2(kWidth * kHeight); + for (uint32_t i = 0; i < kWidth * kHeight / 16; ++i) + { + memcpy(texData1.data() + i * 16, block1, 16); + memcpy(texData2.data() + i * 16, block2, 16); + } - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + glBindTexture(GL_TEXTURE_2D, tex); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, kWidth, kHeight, 0, + kWidth * kHeight, texData1.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); + + glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, + GL_COMPRESSED_RGBA_ASTC_4x4_KHR, kWidth * kHeight, texData2.data()); + drawQuad(program, "position", 0.0f); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0x1F, 0x5F, 0xEF, 0xFF), 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, GLColor(0x1F, 0x5F, 0xEF, 0xFF), 1); + ASSERT_GL_NO_ERROR(); } -// When sampling a texture without an alpha channel, "1" is returned as the alpha value. -// ES 3.0.4 table 3.24 -TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1) +// Test completely overwriting a texture with a data upload while the texture is being sampled from +// by the GPU. +// Tests uses a depth/stencil format. +TEST_P(Texture2DTestES3, SampleThenFullUpdateThenSampleAgainDepthStencil) { - // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497 - ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL()); + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr); - EXPECT_GL_NO_ERROR(); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getExpensiveFragmentShaderSource()); - drawQuad(mProgram, "position", 0.5f); + glViewport(0, 0, kWidth, kHeight); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + GLTexture tex; + const std::vector originalData(kWidth * kHeight, 0x800000'C0); + const std::vector updateData(kWidth * kHeight, 0x400000'0A); -// ETC2 punchthrough alpha formats must be initialized to opaque black when emulated -// http://anglebug.com/42265413 -TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDRGB8A1ETC2) -{ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0, - 8, nullptr); - EXPECT_GL_NO_ERROR(); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kWidth, kHeight, 0, GL_DEPTH_STENCIL, + GL_UNSIGNED_INT_24_8, originalData.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + drawQuad(program, "position", 0.0f); + ASSERT_GL_NO_ERROR(); - drawQuad(mProgram, "position", 0.5f); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, + updateData.data()); + drawQuad(program, "position", 0.0f); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); -} + // Verify that depth is correct after update. + EXPECT_NEAR(63, angle::ReadColor(0, 0).R, 1); + EXPECT_NEAR(63, angle::ReadColor(kWidth - 1, kHeight - 1).R, 1); + ASSERT_GL_NO_ERROR(); -// ETC2 punchthrough alpha formats must be initialized to opaque black when emulated -// http://anglebug.com/42265413 -TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDSRGB8A1ETC2) + // Verify that stencil is correct as well. + if (IsGLExtensionEnabled("GL_ANGLE_stencil_texturing")) + { + constexpr char kStencilFS[] = R"(#version 300 es +precision mediump float; +uniform highp usampler2D tex; +out vec4 color; +void main() { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture2D); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0, - 8, nullptr); - EXPECT_GL_NO_ERROR(); + color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0; +})"; - drawQuad(mProgram, "position", 0.5f); + ANGLE_GL_PROGRAM(stencilProgram, getVertexShaderSource(), kStencilFS); + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, GL_STENCIL_INDEX); + drawQuad(stencilProgram, "position", 0.0f); - EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); + EXPECT_NEAR(10, angle::ReadColor(0, 0).R, 1); + EXPECT_NEAR(10, angle::ReadColor(kWidth - 1, kHeight - 1).R, 1); + ASSERT_GL_NO_ERROR(); + } } -// Test that compressed textures ignore the pixel unpack state. -// (https://crbug.org/1267496) -TEST_P(Texture2DTestES3, PixelUnpackStateTexImage) +// Test for ASTC decode mode queries +TEST_P(Texture2DTestES3, ASTCDecodeModeQueries) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && - !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); + GLint value = 0, result = 0, defaultValue = GL_RGBA16F; + if (IsGLExtensionEnabled("GL_EXT_texture_compression_astc_decode_mode")) + { + // Set invalid ASTC decode mode + value = GL_RGBA32F; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_EQ(result, defaultValue); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 9); - glBindTexture(GL_TEXTURE_2D, mTexture2D); + // Set valid ASTC decode mode + value = GL_RGBA8; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_NO_ERROR(); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_EQ(result, value); - uint8_t data[64] = {0}; - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data); - EXPECT_GL_NO_ERROR(); + value = GL_RGBA16F; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_NO_ERROR(); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_EQ(result, value); + + if (IsGLExtensionEnabled("GL_EXT_texture_compression_astc_decode_mode_rgb9e5")) + { + value = GL_RGB9_E5; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_NO_ERROR(); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_EQ(result, value); + } + else + { + value = GL_RGB9_E5; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_GL_ERROR(GL_NO_ERROR); + EXPECT_EQ(result, GL_RGBA16F); + } + } + else + { + value = GL_RGBA8; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + + value = GL_RGBA16F; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &value); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, &result); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + } } -// Test that compressed textures ignore the pixel unpack state. -// (https://crbug.org/1267496) -TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage) +// Test that rendering with ASTC texture formats with different decode modes on GL_TEXTURE_2D works. +TEST_P(Texture2DTestES3, ASTCDecodeModeDrawTexture) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") && - !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_astc_decode_mode")); - glBindTexture(GL_TEXTURE_2D, mTexture2D); + GLTexture tex; + constexpr uint32_t kWidth = 4; + constexpr uint32_t kHeight = 4; + std::vector decodemodes = {GL_RGBA16F, GL_RGBA8, GL_RGB9_E5}; - uint8_t data[64] = {0}; - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getFragmentShaderSource()); EXPECT_GL_NO_ERROR(); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 9); - - glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, - data); + constexpr uint8_t block[16] = {0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0x7F, 0x3F, 0x3F, 0xBF, 0xBF, 0xFF, 0xFF}; + std::vector texData(kWidth * kHeight); + memcpy(texData.data(), block, 16); + glBindTexture(GL_TEXTURE_2D, tex); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, kWidth, kHeight, 0, + kWidth * kHeight, texData.data()); EXPECT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + for (GLenum mode : decodemodes) + { + if (mode == GL_RGB9_E5 && + !IsGLExtensionEnabled("GL_EXT_texture_compression_astc_decode_mode_rgb9e5")) + { + std::cout << "GL_RGB9_E5 subtest skipped: " + "GL_EXT_texture_compression_astc_decode_mode_rgb9e5 is not enabled.\n"; + continue; + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, mode); + EXPECT_GL_NO_ERROR(); + + drawQuad(program, "position", 0.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 63, 191, 255), 1); + EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, GLColor(127, 63, 191, 255), 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, GLColor(127, 63, 191, 255), 1); + EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, GLColor(127, 63, 191, 255), 1); + ASSERT_GL_NO_ERROR(); + } } -// Test for http://anglebug.com/42265405. -TEST_P(Texture2DTestES3, TextureRGBUpdateWithPBO) +// Test that the selected decode precision is actually used for texture decoding. +TEST_P(Texture2DTestES3, ASTCDecodeModeSwitch) { - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_astc_decode_mode")); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_hdr")); - glViewport(0, 0, 16, 16); + GLTexture tex, colorBuf; + constexpr uint32_t kWidth = 4; + constexpr uint32_t kHeight = 4; - GLTexture tex1; - std::vector texDataRed(16u * 16u, GLColor::red); - std::vector texDataGreen(16u * 16u, GLColor::green); + ANGLE_GL_PROGRAM(program, getVertexShaderSource(), getFragmentShaderSource()); + EXPECT_GL_NO_ERROR(); - glBindTexture(GL_TEXTURE_2D, tex1); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, texDataRed.data()); - ASSERT_GL_NO_ERROR(); + constexpr uint8_t block[16] = {0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xBC, 0x00, 0x40, 0x00, 0xC2, 0x00, 0x44}; + std::vector texData(kWidth * kHeight); + memcpy(texData.data(), block, 16); + // Load compressed texture data into tex. + glBindTexture(GL_TEXTURE_2D, tex); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, kWidth, kHeight, 0, + kWidth * kHeight, texData.data()); + EXPECT_GL_NO_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - GLBuffer pbo; - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); - glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, texDataGreen.data(), GL_STATIC_DRAW); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, nullptr); - ASSERT_GL_NO_ERROR(); + // Create an empty texture and bind it to the frame buffer. + glBindTexture(GL_TEXTURE_2D, colorBuf); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, kWidth, kHeight, 0, GL_RGBA, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuf, 0); + + glViewport(0, 0, kWidth, kHeight); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); - ASSERT_GL_NO_ERROR(); + // The default value of the decode precision is RGBA16F. + glBindTexture(GL_TEXTURE_2D, tex); + drawQuad(program, "position", 0.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT32F_EQ(0, 0, kWidth, kHeight, GLColor32F(-1.0f, 2.0f, -3.0f, 4.0f)); - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green); + // Switch the decode precision to RGB9_E5 and verify the results. + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_astc_decode_mode_rgb9e5")); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, GL_RGB9_E5); + EXPECT_GL_NO_ERROR(); + drawQuad(program, "position", 0.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT32F_EQ(0, 0, kWidth, kHeight, GLColor32F(0.0f, 2.0f, 0.0f, 1.0f)); + + // Switch the decode precision back to RGBA16F and verify the results. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, GL_RGBA16F); + EXPECT_GL_NO_ERROR(); + drawQuad(program, "position", 0.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT32F_EQ(0, 0, kWidth, kHeight, GLColor32F(-1.0f, 2.0f, -3.0f, 4.0f)); } // Copied from Texture2DTest::TexStorage @@ -8702,6 +10340,35 @@ TEST_P(TextureBorderClampTest, TextureBorderClampUnorm8) EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1); } +// Test GL_TEXTURE_BORDER_COLOR parameter with RGB565 with different colors. +TEST_P(TextureBorderClampTest, TextureBorderClampRGB565) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp")); + + GLColor32F kBorder1 = {1.0f, 0.0f, 0.0f, 1.0f}; + GLColor32F kBorder2 = {0.0f, 1.0f, 0.0f, 1.0f}; + GLColor32F kBorder3 = {0.0f, 0.0f, 1.0f, 1.0f}; + GLColor32F kBorder4 = {1.0f, 1.0f, 0.0f, 1.0f}; + GLColor32F kBorder5 = {0.0f, 1.0f, 1.0f, 1.0f}; + + setUpProgram(); + + testFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, kBorder1); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + testFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, kBorder2); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + testFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, kBorder3); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + + testFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, kBorder4); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); + + testFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, kBorder5); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); +} + // Test GL_TEXTURE_BORDER_COLOR parameter with sRGB formats. TEST_P(TextureBorderClampTest, TextureBorderClampSrgb) { @@ -9010,6 +10677,205 @@ TEST_P(TextureBorderClampTestES3, TextureBorderTypeMismatch) EXPECT_PIXEL_ALPHA_EQ(0, 0, 255); } +class TextureBorderClampTestES31 : public TextureBorderClampTest +{ + protected: + TextureBorderClampTestES31() : TextureBorderClampTest() {} + + void callTexParameterIuivAPI(const APIExtensionVersion usedExtension, + GLenum target, + GLenum pname, + const GLuint *params); + void testCustomBorderColorWithStencil(const APIExtensionVersion usedExtension); +}; + +void TextureBorderClampTestES31::callTexParameterIuivAPI(const APIExtensionVersion usedExtension, + GLenum target, + GLenum pname, + const GLuint *params) +{ + ASSERT(usedExtension == APIExtensionVersion::OES || usedExtension == APIExtensionVersion::EXT || + usedExtension == APIExtensionVersion::Core); + if (usedExtension == APIExtensionVersion::OES) + { + glTexParameterIuivOES(target, pname, params); + } + else if (usedExtension == APIExtensionVersion::EXT) + { + glTexParameterIuivEXT(target, pname, params); + } + else + { + glTexParameterIuiv(target, pname, params); + } +} + +// Based on dEQP test: +// dEQP-GLES31.functional.texture.border_clamp.unused_channels.depth24_stencil8_sample_stencil +void TextureBorderClampTestES31::testCustomBorderColorWithStencil( + const APIExtensionVersion usedExtension) +{ + ASSERT(usedExtension == APIExtensionVersion::OES || usedExtension == APIExtensionVersion::EXT || + usedExtension == APIExtensionVersion::Core); + + int width = getWindowWidth(); + int height = getWindowHeight(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClearColor(0.0, 0.0, 1.0, 1.0); + glClearDepthf(0.0); + glClearStencil(0xFF); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + // Shaders + std::string vs; + std::string fs; + + constexpr char kGLSLVersion31[] = R"(#version 310 es +)"; + constexpr char kGLSLVersion32[] = R"(#version 320 es +)"; + if (usedExtension == APIExtensionVersion::Core) + { + vs.append(kGLSLVersion32); + fs.append(kGLSLVersion32); + } + else + { + vs.append(kGLSLVersion31); + fs.append(kGLSLVersion31); + } + + constexpr char kVSBody[] = R"( +in highp vec2 a_position; +in highp vec2 a_texCoord; +out highp vec2 v_texCoord; + +void main (void) +{ + gl_Position = vec4(a_position, 0.0, 1.0); + v_texCoord = a_texCoord; +})"; + vs.append(kVSBody); + + constexpr char kFSBody[] = R"( +layout(location = 0) out mediump vec4 outColor; +in highp vec2 v_texCoord; +uniform highp usampler2D stencilSampler; + +void main (void) +{ + outColor = vec4(texture(stencilSampler, v_texCoord)) * vec4(1.0 / 255.0, 1.0, 1.0, 1.0); +})"; + fs.append(kFSBody); + + ANGLE_GL_PROGRAM(program, vs.c_str(), fs.c_str()); + EXPECT_GL_NO_ERROR(); + glUseProgram(program); + + // In case of using stencil for border clamp, the first component of the border color is used. + // If the texcoords are within the bounds, the texture's stencil value is used. + constexpr uint32_t kQuadStencil = 0xFF; + static_assert(kQuadStencil <= 0xFF); + std::vector textureData(16 * 16, 0xFFFFFF00 | kQuadStencil); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 16, 16, 0, GL_DEPTH_STENCIL, + GL_UNSIGNED_INT_24_8, textureData.data()); + + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + constexpr GLuint kUsedComponentForBorder = 145; + constexpr GLuint kBorderData[4] = {kUsedComponentForBorder, 100, 37, 111}; + callTexParameterIuivAPI(usedExtension, GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, kBorderData); + EXPECT_GL_NO_ERROR(); + + // The vertex and index data are set to draw a quad at the center of the screen, with the color + // sampled from the texture's stencil value, surrounded by the border color. + constexpr float kVertexData[] = { + // Position + -1.0f, + -1.0f, + -1.0f, + 1.0f, + 1.0f, + -1.0f, + 1.0f, + 1.0f, + // TexCoord + -0.5, + -0.5, + -0.5, + 1.5, + 1.5, + -0.5, + 1.5, + 1.5, + }; + constexpr uint16_t kIndices[] = {0, 1, 2, 2, 1, 3}; + + GLVertexArray vao; + glBindVertexArray(vao); + + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, 64, kVertexData, GL_STATIC_DRAW); + + GLBuffer indexBuffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 12, kIndices, GL_STATIC_DRAW); + + GLint posLoc = glGetAttribLocation(program, "a_position"); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(0)); + GLint texLoc = glGetAttribLocation(program, "a_texCoord"); + glEnableVertexAttribArray(texLoc); + glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(32)); + + // Draw + glUniform1i(glGetUniformLocation(program, "stencilSampler"), 0); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr); + + constexpr GLColor kExpectedBorderColor = GLColor(kUsedComponentForBorder, 0, 0, 255); + constexpr GLColor kExpectedQuadColor = GLColor(kQuadStencil, 0, 0, 255); + EXPECT_PIXEL_RECT_EQ(0, 0, width / 4, height, kExpectedBorderColor); + EXPECT_PIXEL_RECT_EQ(3 * width / 4, 0, width / 4, height, kExpectedBorderColor); + EXPECT_PIXEL_RECT_EQ(0, 0, width, height / 4, kExpectedBorderColor); + EXPECT_PIXEL_RECT_EQ(0, 3 * height / 4, width, height / 4, kExpectedBorderColor); + EXPECT_PIXEL_RECT_EQ(width / 4, height / 4, width / 2, height / 2, kExpectedQuadColor); +} + +// Tests texture border clamp in case of sampling from a texture with a stencil component. +TEST_P(TextureBorderClampTestES31, CustomBorderColorWithStencilOES) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp")); + testCustomBorderColorWithStencil(APIExtensionVersion::OES); +} + +// Tests texture border clamp in case of sampling from a texture with a stencil component. +TEST_P(TextureBorderClampTestES31, CustomBorderColorWithStencilEXT) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_border_clamp")); + testCustomBorderColorWithStencil(APIExtensionVersion::EXT); +} + +class TextureBorderClampTestES32 : public TextureBorderClampTestES31 +{ + protected: + TextureBorderClampTestES32() : TextureBorderClampTestES31() {} +}; + +// Tests texture border clamp in case of sampling from a texture with a stencil component. +TEST_P(TextureBorderClampTestES32, CustomBorderColorWithStencil) +{ + testCustomBorderColorWithStencil(APIExtensionVersion::Core); +} + class TextureBorderClampIntegerTestES3 : public Texture2DTest { protected: @@ -11778,6 +13644,47 @@ TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerAB) } } +// Test two samplers (one of type sampler2d and one of type samplerCube), +// link program successfully, don't set the samplers to anything (ie, keep +// default values as 0) and call function glValidateProgram on program id. +TEST_P(TextureDefaultTextureTest, SampleFromDefaultTexture) +{ + constexpr uint32_t whiteTextureData[] = {0xFFFFFFFF}; + GLTexture whiteTex; + + glUseProgram(mProgram); + EXPECT_GL_NO_ERROR(); + + glActiveTexture(GL_TEXTURE7); + glBindTexture(GL_TEXTURE_2D, whiteTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, whiteTextureData); + GLint loc = glGetUniformLocation(mProgram, "white"); + ASSERT_NE(-1, loc); + glUniform1i(loc, 7); + EXPECT_GL_NO_ERROR(); + + glActiveTexture(GL_TEXTURE0); + EXPECT_GL_NO_ERROR(); + + glValidateProgram(mProgram); + EXPECT_GL_NO_ERROR(); + + // Verify that the validate status is false + GLint validateStatus = 0; + glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validateStatus); + EXPECT_GL_FALSE(validateStatus); + EXPECT_GL_NO_ERROR(); + + // Check that the info log is non-empty + GLint programInfoLength = 0; + GLubyte errMessage[1000]; + glGetProgramInfoLog(mProgram, 1000, &programInfoLength, (char *)errMessage); + EXPECT_GT(programInfoLength, 0); + EXPECT_GL_NO_ERROR(); + + drawQuad(mProgram, "position", 0.5f); +} + // Similar to IncompatibleLayerABThenCompatibleLayerAB, but with a single-level texture TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerABSingleLevel) { @@ -11802,50 +13709,379 @@ TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerABSingleLevel) glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, data.data()); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, tex); + + glUseProgram(mProgram); + glUniform1i(mTexture2DUniformLocation, 0); + glUniform1i(mTextureCubeUniformLocation, 1); + + const int w = getWindowWidth(); + const int h = getWindowHeight(); + + for (uint32_t i = 0; i < 6; ++i) + { + glUniform1i(mTextureCubeFaceUniformLocation, i); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 0.5f); + + EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green); + EXPECT_GL_NO_ERROR(); + } + + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA, + GL_UNSIGNED_INT_2_10_10_10_REV, data.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA, + GL_UNSIGNED_INT_2_10_10_10_REV, data.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA, + GL_UNSIGNED_INT_2_10_10_10_REV, data2.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA, + GL_UNSIGNED_INT_2_10_10_10_REV, data2.data()); + + for (uint32_t i = 0; i < 6; ++i) + { + glUniform1i(mTextureCubeFaceUniformLocation, i); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 0.5f); + + const bool expectRed = i == 2 || i == 5; + const GLColor expect = expectRed ? GLColor::red : GLColor::green; + EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect); + EXPECT_GL_NO_ERROR(); + } +} + +// Test that after a cubemap is setup, if the faces are incompatibly redefined (with data), then a +// single face is redefined back to the original size (with data) and redefined again back to the +// incompatible size, that the (incompatible) updates to the other faces are not accidentally +// dropped. +void TextureCubeTestES3::incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain( + GLint internalformat) +{ + uint32_t kSize = 16; + + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + + switch (internalformat) + { + case GL_RGBA8: + break; + case GL_LUMINANCE: + format = GL_LUMINANCE; + break; + case GL_LUMINANCE_ALPHA: + format = GL_LUMINANCE_ALPHA; + break; + case GL_ALPHA: + format = GL_ALPHA; + break; + default: + // Unhandled format + ASSERT_TRUE(false); + } + + GLTexture tex; + glBindTexture(GL_TEXTURE_CUBE_MAP, tex); + + // Initial data to upload to the textures. + const std::vector initialData(kSize * kSize, GLColor(50, 100, 50, 100)); + + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, format, type, + initialData.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, format, type, + initialData.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, format, type, + initialData.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, format, type, + initialData.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, format, type, + initialData.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, format, type, + initialData.data()); + + // Sample from the cubemap and make sure all faces are correct + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Make sure the program's sample from tex2D doesn't interfere with the test. + GLTexture zero2D; + glBindTexture(GL_TEXTURE_2D, zero2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + &GLColor::transparentBlack); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, zero2D); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, tex); + + glUseProgram(mProgram); + glUniform1i(mTexture2DUniformLocation, 0); + glUniform1i(mTextureCubeUniformLocation, 1); + + const auto getExpectedColor = [internalformat](const GLColor &uploadColor, GLColor *expect0, + GLColor *expect1) { + *expect0 = uploadColor; + *expect1 = uploadColor; + switch (internalformat) + { + case GL_RGBA8: + break; + case GL_LUMINANCE: + *expect0 = GLColor(uploadColor.R, uploadColor.R, uploadColor.R, 255); + *expect1 = GLColor(uploadColor.G, uploadColor.G, uploadColor.G, 255); + break; + case GL_LUMINANCE_ALPHA: + *expect0 = *expect1 = + GLColor(uploadColor.R, uploadColor.R, uploadColor.R, uploadColor.G); + break; + case GL_ALPHA: + *expect0 = GLColor(0, 0, 0, uploadColor.R); + *expect1 = GLColor(0, 0, 0, uploadColor.G); + break; + default: + ASSERT_TRUE(false); + } + }; + + const int w = getWindowWidth(); + const int h = getWindowHeight(); + + for (uint32_t i = 0; i < 6; ++i) + { + glUniform1i(mTextureCubeFaceUniformLocation, i); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 0.5f); + + GLColor expect0, expect1; + getExpectedColor(initialData[0], &expect0, &expect1); + + // How the texture is projected depends on the face + if (i != 0 && i != 5) + { + std::swap(expect0, expect1); + } + EXPECT_PIXEL_COLOR_EQ(0, 0, expect0) << "At cubemap face " << i; + EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, expect1) << "At cubemap face " << i; + ASSERT_GL_NO_ERROR(); + } + + // Redefine the faces to something smaller. + const std::vector redefine0(kSize * kSize / 4, GLColor(20, 150, 20, 150)); + const std::vector redefine1(kSize * kSize / 4, GLColor(80, 200, 80, 200)); + const std::vector redefine2(kSize * kSize / 4, GLColor(120, 40, 120, 40)); + const std::vector redefine3(kSize * kSize / 4, GLColor(180, 10, 180, 10)); + const std::vector redefine4(kSize * kSize / 4, GLColor(220, 70, 220, 70)); + const std::vector redefine5(kSize * kSize / 4, GLColor(160, 240, 160, 240)); + + // Leave one face untouched so the image doesn't become complete. This way the staged updates + // have to stay pending. + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize / 2, kSize / 2, 0, format, + type, redefine1.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize / 2, kSize / 2, 0, format, + type, redefine2.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize / 2, kSize / 2, 0, format, + type, redefine3.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize / 2, kSize / 2, 0, format, + type, redefine4.data()); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize / 2, kSize / 2, 0, format, + type, redefine5.data()); + + // Upload data to the untouched face, overwriting it completely. + const std::vector throwAway(kSize * kSize, GLColor(12, 34, 56, 78)); + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, + throwAway.data()); + + // Redefine that face to the smaller size too to make the texture complete. + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize / 2, kSize / 2, 0, format, + type, redefine0.data()); + + // Verify that the previously staged updates are not lost. + const std::vector *redefines[] = { + &redefine0, &redefine1, &redefine2, &redefine3, &redefine4, &redefine5, + }; + for (uint32_t i = 0; i < 6; ++i) + { + glUniform1i(mTextureCubeFaceUniformLocation, i); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(mProgram, "position", 0.5f); + + GLColor expect0, expect1; + getExpectedColor((*redefines[i])[0], &expect0, &expect1); + + // How the texture is projected depends on the face + if (i != 0 && i != 5) + { + std::swap(expect0, expect1); + } + EXPECT_PIXEL_COLOR_EQ(0, 0, expect0) << "At cubemap face " << i; + EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, expect1) << "At cubemap face " << i; + ASSERT_GL_NO_ERROR(); + } +} + +// |incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain| with RGBA8 +TEST_P(TextureCubeTestES3, + IncompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgainRGBA8) +{ + incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain(GL_RGBA8); +} + +// |incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain| with LUMINANCE +TEST_P(TextureCubeTestES3, + IncompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgainLUMINANCE) +{ + incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain(GL_LUMINANCE); +} + +// |incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain| with LUMINANCE_ALPHA +TEST_P(TextureCubeTestES3, + IncompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgainLUMA) +{ + incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain(GL_LUMINANCE_ALPHA); +} - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, tex); +// |incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain| with ALPHA +TEST_P(TextureCubeTestES3, + IncompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgainALPHA) +{ + incompatibleCubeFacesThenSingleFaceCompatibleUploadAndIncompatibleAgain(GL_ALPHA); +} - glUseProgram(mProgram); - glUniform1i(mTexture2DUniformLocation, 0); - glUniform1i(mTextureCubeUniformLocation, 1); +// Test that glCopyImageSubData works with GL_TEXTURE_CUBE_MAP_ARRAY layers unique to array cubes +TEST_P(TextureCubeTestES32, CopyImageSubDataCubeMapArray) +{ + // The test harness uses an FBO to work around an issue, which is not needed here + glBindFramebuffer(GL_FRAMEBUFFER, 0); + constexpr char kVS[] = + R"(#version 320 es + precision mediump float; + in vec3 pos; + void main() { + gl_Position = vec4(pos, 1.0); + })"; - const int w = getWindowWidth(); - const int h = getWindowHeight(); + constexpr char kFS[] = + R"(#version 320 es + precision mediump float; + precision highp samplerCubeArray; - for (uint32_t i = 0; i < 6; ++i) + out vec4 color; + uniform samplerCubeArray uTex; + uniform int uTexCubeIndex; + uniform vec3 uDir; + void main(){ + color = texture(uTex, vec4(normalize(uDir), float(uTexCubeIndex))); + })"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + GLint textureLoc = glGetUniformLocation(program, "uTex"); + ASSERT_NE(-1, textureLoc); + glUniform1i(textureLoc, 0); + + GLint cubeIndex = glGetUniformLocation(program, "uTexCubeIndex"); + ASSERT_NE(-1, cubeIndex); + GLint dirLoc = glGetUniformLocation(program, "uDir"); + ASSERT_NE(-1, dirLoc); + // Use nearest filtering to avoid cross-face blending at seams during testing + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + // Test copying from GL_TEXTURE_CUBE_MAP_ARRAY to GL_TEXTURE_CUBE_MAP_ARRAY { - glUniform1i(mTextureCubeFaceUniformLocation, i); + // Create source CubeMapArray with 3 cubes (18 layers total) + GLTexture srcCubeArray; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, srcCubeArray); + glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 128, 128, 18); + + std::vector redData(128 * 128, GLColor::red); + std::vector greenData(128 * 128, GLColor::green); + std::vector blueData(128 * 128, GLColor::blue); + + // Fill layer 0 (first cube, first face) + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, 128, 128, 1, GL_RGBA, + GL_UNSIGNED_BYTE, redData.data()); + // Fill layer 7 (second cube, second face) + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 7, 128, 128, 1, GL_RGBA, + GL_UNSIGNED_BYTE, greenData.data()); + // Fill layer 15 (third cube, fourth face) + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 15, 128, 128, 1, GL_RGBA, + GL_UNSIGNED_BYTE, blueData.data()); + + // Create destination CubeMapArray with 3 cubes + GLTexture dstCubeArray; + glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, dstCubeArray); + glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 128, 128, 18); + + // Copy from the source to the destination + glCopyImageSubData(srcCubeArray, GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, dstCubeArray, + GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, 128, 128, 1); + glCopyImageSubData(srcCubeArray, GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 7, dstCubeArray, + GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 7, 128, 128, 1); + glCopyImageSubData(srcCubeArray, GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 15, dstCubeArray, + GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 15, 128, 128, 1); + ASSERT_GL_NO_ERROR(); + + glClearColor(1.0f, 0.0f, 1.0f, 1.0f); // Set clear color to magenta glClear(GL_COLOR_BUFFER_BIT); - drawQuad(mProgram, "position", 0.5f); - EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green); - EXPECT_GL_NO_ERROR(); - } + glUniform1i(cubeIndex, 0); + glUniform3f(dirLoc, 1.0f, 0.0f, 0.0f); // layer 0 is cube 0, face +X + drawQuad(program, "pos", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA, - GL_UNSIGNED_INT_2_10_10_10_REV, data.data()); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA, - GL_UNSIGNED_INT_2_10_10_10_REV, data.data()); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA, - GL_UNSIGNED_INT_2_10_10_10_REV, data2.data()); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA, - GL_UNSIGNED_INT_2_10_10_10_REV, data2.data()); + // Check layer 7 (green) + glUniform1i(cubeIndex, 1); + glUniform3f(dirLoc, -1.0f, 0.0f, 0.0f); // layer 7 is cube 1, face -X + drawQuad(program, "pos", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); - for (uint32_t i = 0; i < 6; ++i) + // Check layer 15 (blue) + glUniform1i(cubeIndex, 2); + glUniform3f(dirLoc, 0.0f, -1.0f, 0.0f); // layer 15 is cube 2, face -Y + drawQuad(program, "pos", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + } + + // Test copying from GL_RENDERBUFFER to GL_TEXTURE_CUBE_MAP_ARRAY { - glUniform1i(mTextureCubeFaceUniformLocation, i); + // Create a renderbuffer as source + GLRenderbuffer srcRenderbuffer; + glBindRenderbuffer(GL_RENDERBUFFER, srcRenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 128, 128); + + // Fill renderbuffer with color using FBO + GLFramebuffer srcFbo; + glBindFramebuffer(GL_FRAMEBUFFER, srcFbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + srcRenderbuffer); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glClearColor(1.0f, 0.0f, 1.0f, 1.0f); // Set clear color to magenta glClear(GL_COLOR_BUFFER_BIT); - drawQuad(mProgram, "position", 0.5f); - const bool expectRed = i == 2 || i == 5; - const GLColor expect = expectRed ? GLColor::red : GLColor::green; - EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect); - EXPECT_GL_NO_ERROR(); + // Create destination CubeMapArray + GLTexture dstCubeArrayFromRB; + glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, dstCubeArrayFromRB); + glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 128, 128, 12); // 2 cubes + + // Copy from renderbuffer to CubeMapArray layer 8 (second cube, third face) + glCopyImageSubData(srcRenderbuffer, GL_RENDERBUFFER, 0, 0, 0, 0, dstCubeArrayFromRB, + GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 8, 128, 128, 1); + ASSERT_GL_NO_ERROR(); + + // Verify the copied data + GLFramebuffer verifyFbo; + glBindFramebuffer(GL_FRAMEBUFFER, verifyFbo); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstCubeArrayFromRB, 0, 8); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta); } } @@ -11953,27 +14189,22 @@ TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexSubImageGreaterThanSizeLimit) GLTexture cubeMapArrayTexture; glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture); - GLint max3DTextureSize = -1; - glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize); - EXPECT_GT(max3DTextureSize, 0); - GLint maxCubeTextureSize = -1; glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeTextureSize); EXPECT_GT(maxCubeTextureSize, 0); - GLint maxSizeLimit = std::min(maxCubeTextureSize, max3DTextureSize); - glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, maxSizeLimit, maxSizeLimit, 6, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); + glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, maxCubeTextureSize, maxCubeTextureSize, 6, + 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); ASSERT_GL_NO_ERROR(); // TexSubImage3D can take unequal values for width and height for cube map arrays. However, they // should stay below the size limit. - glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, maxSizeLimit + 1, maxSizeLimit, 6, - GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, maxCubeTextureSize + 1, + maxCubeTextureSize, 6, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); EXPECT_GL_ERROR(GL_INVALID_VALUE); - glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, maxSizeLimit, maxSizeLimit + 1, 6, - GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, maxCubeTextureSize, + maxCubeTextureSize + 1, 6, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green); EXPECT_GL_ERROR(GL_INVALID_VALUE); } @@ -12036,25 +14267,15 @@ TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexImageInvalidInputs) maxCubeTextureSize / 4 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_VALUE); - // Width and height and depth should not exceed the maximum 3D texture size. - GLint max3DTextureSize = -1; - glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize); - EXPECT_GT(max3DTextureSize, 0); - - glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 256, max3DTextureSize + 1, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_ERROR(GL_INVALID_VALUE); - - glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, max3DTextureSize + 1, max3DTextureSize + 1, - 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_ERROR(GL_INVALID_VALUE); - - glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA, max3DTextureSize / 2 + 1, - max3DTextureSize / 2 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GL_ERROR(GL_INVALID_VALUE); + // Depth should not exceed the maximum array layer count. + GLint maxArrayTextureLayers = -1; + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers); + ASSERT_GE(maxArrayTextureLayers, 6); + // Max valid layer count + const GLint maxValidCubeArrayTextureLayers = maxArrayTextureLayers / 6 * 6; - glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, GL_RGBA, max3DTextureSize / 4 + 1, - max3DTextureSize / 4 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 256, + maxValidCubeArrayTextureLayers + 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_VALUE); } @@ -12094,16 +14315,15 @@ TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexStorageInvalidInputs) maxCubeTextureSize + 1, 6); EXPECT_GL_ERROR(GL_INVALID_VALUE); - // Width and height and depth should not exceed the maximum 3D texture size. - GLint max3DTextureSize = -1; - glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize); - EXPECT_GT(max3DTextureSize, 0); - - glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, max3DTextureSize + 1, - max3DTextureSize + 1, 6); - EXPECT_GL_ERROR(GL_INVALID_VALUE); + // Depth should not exceed the maximum array layer count. + GLint maxArrayTextureLayers = -1; + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers); + ASSERT_GE(maxArrayTextureLayers, 6); + // Max valid layer count + const GLint maxValidCubeArrayTextureLayers = maxArrayTextureLayers / 6 * 6; - glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 256, max3DTextureSize + 1); + glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 256, + maxValidCubeArrayTextureLayers + 6); EXPECT_GL_ERROR(GL_INVALID_VALUE); // Level count must not exceed log2(max(width, height)) + 1. @@ -13117,6 +15337,86 @@ TEST_P(Texture2DTestES3, RespecifyWithMoreMips) } } +// Test to verify that reinitializing an image with incompatible mipmap levels, and enabling mipmap +// filtering after it was disabled, does not cause a crash. +TEST_P(Texture2DTestES3, ReinitIncompatibleLevelsNoMipmapThenMipmap) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mTexture2D); + + constexpr const GLsizei kSize = 8; + const std::vector> kMipLevelData = { + std::vector(8 * 8, GLColor::red), std::vector(4 * 4, GLColor::green), + std::vector(2 * 2, GLColor::blue), std::vector(1 * 1, GLColor::yellow)}; + const std::vector kSingleLevelData(4 * 4, 0x001f); + + // Store an image with a level count of 4. + for (GLint mip = 0; mip < static_cast(kMipLevelData.size()); ++mip) + { + GLint size = kSize >> mip; + glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kMipLevelData[mip].data()); + } + + // Use mipmap filtering. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + EXPECT_GL_NO_ERROR(); + + // Set up the lod program. + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod()); + glUseProgram(program); + GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform()); + GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform()); + ASSERT_NE(-1, textureLoc); + ASSERT_NE(-1, lodLoc); + glUniform1i(textureLoc, 0); + + // Set lod = 0. + glUniform1f(lodLoc, 0); + + // Verify draw and the texture image will be stored. + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + EXPECT_GL_NO_ERROR(); + + // Use GL_LINEAR filtering so that mipmap is not used. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + EXPECT_GL_NO_ERROR(); + + // Reinit image with a different sized internal format with a single level. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, 4, 4, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + kSingleLevelData.data()); + EXPECT_GL_NO_ERROR(); + + // Verify draw with mip level 0 and expect that the color matches kSingleLevelData. + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + EXPECT_GL_NO_ERROR(); + + // Use mipmap filtering again. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + EXPECT_GL_NO_ERROR(); + + // Restore mip level 0 to the mipmap format and ensure all levels are included in the texture. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kMipLevelData[0].data()); + EXPECT_GL_NO_ERROR(); + + // Verify that all the mips are still correct. + for (GLint mip = 0; mip < static_cast(kMipLevelData.size()); ++mip) + { + glUniform1f(lodLoc, mip); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipLevelData[mip].data()[0]); + EXPECT_GL_NO_ERROR(); + ASSERT_GL_NO_ERROR(); + } +} + // Covers a bug in the D3D11 backend: http://anglebug.com/42261476 // When using a sampler the texture was created as if it has mipmaps, // regardless what you specified in GL_TEXTURE_MIN_FILTER via @@ -14392,10 +16692,6 @@ TEST_P(TextureBufferTestES31, TexBufferDrawTwice) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer")); - // TODO(http://anglebug.com/42264369): Claims to support GL_OES_texture_buffer, but fails - // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported". - ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES()); - const std::array kTexData = {GLColor::red}; GLBuffer buffer; @@ -14606,15 +16902,83 @@ TEST_P(TextureBufferTestES32, RGBANorm16) GLColor::magenta); } +// Verify that when two shaders are writing to the same texture buffer but using +// different buffer view formats will result in correct value. +TEST_P(TextureBufferTestES32, TexBufferViewFormatMismatch) +{ + // Requires ES 3.2 for testing texture buffer + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || + (getClientMajorVersion() == 3 && getClientMinorVersion() < 2)); + + // Pass 1: write a 16-byte sentinel at texel index 1 (offset 16 bytes) with RGBA32UI view. + constexpr char kCS_RGBA32UI[] = R"(#version 320 es +layout(local_size_x=1) in; +layout(rgba32ui, binding = 0) uniform writeonly highp uimageBuffer img; +void main() { + imageStore(img, 1, uvec4(1, 2, 3, 4)); +})"; + + // Pass 2: write a 4-byte marker at texel index 4 (offset 16 bytes if R32UI view is used). + constexpr char kCS_R32UI[] = R"(#version 320 es +layout(local_size_x=1) in; +layout(r32ui, binding = 0) uniform highp uimageBuffer img; +void main() { + imageStore(img, 4, uvec4(5)); +})"; + + // Create buffer large enough for the intended writes: + // - RGBA32UI write at index 1 (offset 16, size 16) + // - R32UI write at index 4 (offset 16, size 4) + // Use 80 bytes so either intended or buggy writes are in-bounds. + constexpr GLsizeiptr kBufferBytes = 80; + GLBuffer buffer; + glBindBuffer(GL_TEXTURE_BUFFER, buffer); + glBufferData(GL_TEXTURE_BUFFER, kBufferBytes, nullptr, GL_DYNAMIC_DRAW); + + // Create texture buffer and attach buffer with a base format + GLTexture tex; + glBindTexture(GL_TEXTURE_BUFFER, tex); + // Base internal format can be any integer format; use R32UI. + glTexBufferRange(GL_TEXTURE_BUFFER, GL_R32UI, buffer, 0, kBufferBytes); + + ANGLE_GL_COMPUTE_PROGRAM(progRGBA1, kCS_RGBA32UI); + ANGLE_GL_COMPUTE_PROGRAM(progR1, kCS_R32UI); + + // First dispatch: rgba32ui (creates/uses RGBA view). Writes at texel 1 (offset 16). + glUseProgram(progRGBA1); + glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); + glDispatchCompute(1, 1, 1); + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT); + + // Second dispatch: r32ui (should use an R32UI view). Writes at texel 4, which is offset 16 + // when texel size is 4 bytes (R32UI). + glUseProgram(progR1); + glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glDispatchCompute(1, 1, 1); + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT); + + // Read back buffer contents and validate marker at offset 16 bytes (index 4). + glBindBuffer(GL_TEXTURE_BUFFER, buffer); + void *ptr = glMapBufferRange(GL_TEXTURE_BUFFER, 0, kBufferBytes, GL_MAP_READ_BIT); + ASSERT_NE(nullptr, ptr); + const auto *bytes = static_cast(ptr); + + std::array values; + memcpy(values.data(), bytes, kBufferBytes); + glUnmapBuffer(GL_TEXTURE_BUFFER); + + EXPECT_EQ(values[4], 5u) << "values[16] is " << values[16]; + EXPECT_EQ(values[5], 2u); + EXPECT_EQ(values[6], 3u); + EXPECT_EQ(values[7], 4u); + EXPECT_GL_NO_ERROR(); +} + // Test that uploading data to buffer that's in use then using it as texture buffer works. TEST_P(TextureBufferTestES31, UseAsUBOThenUpdateThenAsTextureBuffer) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer")); - // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension - // 'GL_OES_texture_buffer' is not supported". http://anglebug.com/42264369 - ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES()); - const std::array kInitialData = {GLColor::red, GLColor::red, GLColor::red, GLColor::red}; const std::array kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue, @@ -14681,9 +17045,6 @@ TEST_P(TextureBufferTestES31, MapTextureBufferInvalidateThenWrite) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer")); - // TODO(http://anglebug.com/42264369): Claims to support GL_OES_texture_buffer, but fails - // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported". - ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES()); // TODO(http://anglebug.com/42264910): The OpenGL backend doesn't correctly handle texture // buffers being invalidated when mapped. ANGLE_SKIP_TEST_IF(IsOpenGL()); @@ -14782,6 +17143,84 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); } +// Test that drawing with a texture buffer after changing its content using transform feedback. +TEST_P(TextureBufferTestES31, UseAsXFBThenAsTextureBuffer) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer")); + + // Issue a draw call with xfb, set buffer to red + constexpr char kXFBVS[] = R"(#version 310 es + uniform vec4 colorIn; + flat out highp vec4 colorOut; + void main() + { + gl_Position = vec4(0, 0, 0, 1); + colorOut = colorIn; + })"; + + // Capture the varying "v". + const std::vector tfVaryings = {"colorOut"}; + ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(programXFB, kXFBVS, essl31_shaders::fs::Green(), tfVaryings, + GL_INTERLEAVED_ATTRIBS); + EXPECT_GL_NO_ERROR(); + glUseProgram(programXFB); + const GLint colorLoc = glGetUniformLocation(programXFB, "colorIn"); + ASSERT_NE(-1, colorLoc); + glUniform4f(colorLoc, 1, 0, 0, 1); + EXPECT_GL_NO_ERROR(); + + GLTransformFeedback tf; + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf); + // Initializing the buffer with 0. After the transform feedback writes to it, the data will + // change. + const std::array data = {0.0, 0.0, 0.0, 0.0}; + GLBuffer buffer; + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, data.size() * sizeof(data[0]), data.data(), + GL_DYNAMIC_DRAW); + // Fill the buffer using transform feedback. + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, 1); + glEndTransformFeedback(); + + // Issue a draw call with samplerBuffer, sample from buffer and write to color attachment + constexpr char kTextureBufferFS[] = R"(#version 310 es + #extension GL_EXT_texture_buffer : require + precision mediump float; + uniform highp samplerBuffer sampler_buffer; + out vec4 colorOut; + void main() + { + colorOut = texelFetch(sampler_buffer, 0); + })"; + ANGLE_GL_PROGRAM(programTextureBuffer, essl31_shaders::vs::Simple(), kTextureBufferFS); + glUseProgram(programTextureBuffer); + + glBindBuffer(GL_TEXTURE_BUFFER, buffer); + glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA32F, buffer); + + drawQuad(programTextureBuffer, essl31_shaders::PositionAttrib(), 0.5); + EXPECT_GL_NO_ERROR(); + + // Issue a draw call with xfb, set buffer to green + glUseProgram(programXFB); + glUniform4f(colorLoc, 0, 1, 0, 1); + EXPECT_GL_NO_ERROR(); + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, 1); + glEndTransformFeedback(); + + // Enable blend, with glBlendFunc(GL_ONE, GL_ONE) + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + // Issue a draw call with samplerBuffer + glUseProgram(programTextureBuffer); + drawQuad(programTextureBuffer, essl31_shaders::PositionAttrib(), 0.5); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255)); +} + // Test workaround in Vulkan backend for mismatched texture buffer and sampler formats TEST_P(TextureBufferTestES31, TexBufferFormatMismatch) { @@ -14960,6 +17399,56 @@ class CopyImageTestES31 : public ANGLETest<> } }; +// Test validation of target +TEST_P(CopyImageTestES31, InvalidTarget) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image")); + + // INVALID_ENUM is generated + // if either srcTarget or dstTarget + // - is not RENDERBUFFER or a valid non-proxy texture target + // - is TEXTURE_BUFFER, or + // - is one of the cubemap face selectors described in table 3.17, + // if the target does not match the type of the object. + GLenum invalidTargets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_BUFFER_EXT, GL_ARRAY_BUFFER, + }; + GLTexture texSrc; + GLTexture texDest; + const uint32_t invalidTargetsSize = sizeof(invalidTargets) / sizeof((invalidTargets)[0]); + for (uint32_t i = 0; i < invalidTargetsSize; ++i) + { + for (uint32_t j = 0; j < invalidTargetsSize; ++j) + { + glCopyImageSubDataEXT(texSrc, invalidTargets[i], 0, 0, 0, 0, texDest, invalidTargets[j], + 0, 0, 0, 0, 1, 1, 1); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + } + } + + // Target does not match the type of the object + glBindTexture(GL_TEXTURE_2D, texSrc); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glBindTexture(GL_TEXTURE_3D, texDest); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glCopyImageSubDataEXT(texSrc, GL_TEXTURE_2D, 0, 0, 0, 0, texDest, GL_TEXTURE_2D, 0, 0, 0, 0, 0, + 0, 1); + EXPECT_GL_ERROR(GL_INVALID_ENUM); + + glCopyImageSubDataEXT(texSrc, GL_TEXTURE_3D, 0, 0, 0, 0, texDest, GL_TEXTURE_3D, 0, 0, 0, 0, 0, + 0, 1); + EXPECT_GL_ERROR(GL_INVALID_ENUM); +} + // Test that copies between RGB formats doesn't affect the emulated alpha channel, if any. TEST_P(CopyImageTestES31, PreserveEmulatedAlpha) { @@ -15446,6 +17935,146 @@ TEST_P(CopyImageTestES31, MultisampleRenderbufferCopyImageSubData) EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); } +// Test glCopyImageSubDataEXT with GL_EXT_texture_norm16 +void CopyImageCompressedWithNorm16(bool isCompressedToNorm16) +{ + struct CompressedFormatDesc + { + GLenum format; + GLsizei blockX; + GLsizei blockY; + GLsizei size; + std::string extension; + }; + + const CompressedFormatDesc possibleCompressedFormats[] = { + {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8, "GL_EXT_texture_compression_dxt1"}, + {GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8, "GL_EXT_texture_compression_s3tc_srgb"}, + {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8, "GL_EXT_texture_compression_dxt1"}, + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8, "GL_EXT_texture_compression_s3tc_srgb"}, + {GL_COMPRESSED_RED_RGTC1_EXT, 4, 4, 8, "GL_EXT_texture_compression_rgtc"}, + {GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 8, "GL_EXT_texture_compression_rgtc"}, + {GL_COMPRESSED_RGB8_ETC2, 4, 4, 8, ""}, + {GL_COMPRESSED_SRGB8_ETC2, 4, 4, 8, ""}, + {GL_COMPRESSED_R11_EAC, 4, 4, 8, ""}, + {GL_COMPRESSED_SIGNED_R11_EAC, 4, 4, 8, ""}, + {GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 8, ""}, + {GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 8, ""}}; + struct Norm16FormatDesc + { + GLint internalformat; + GLenum format; + GLenum type; + }; + constexpr Norm16FormatDesc possibleNorm16Formats[] = { + {GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT}, {GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT}}; + + for (CompressedFormatDesc compressedFormat : possibleCompressedFormats) + { + if (!compressedFormat.extension.empty() && + !IsGLExtensionEnabled(compressedFormat.extension)) + { + std::cout << "subtest skipped due to missing " << compressedFormat.extension << "." + << std::endl; + continue; + } + for (Norm16FormatDesc norm16Format : possibleNorm16Formats) + { + // Compressed: each 4x4 block = 8 bytes + // 4x4 image => (4/4)*(4/4) = 1 blocks => 1 * 8 = 8 bytes + // Assume uncompressed target is just a raw memory buffer with same size + // To match the compressed size exactly, we simulate the destination as a 1x1 texture + // with RGBA16 + const int norm16Width = compressedFormat.blockX / 4; + const int norm16Height = compressedFormat.blockY / 4; + // RGBA16 = 4 channels * 2 bytes = 8 bytes per pixel + // 1x1 pixels = 8 bytes + const int norm16Size = norm16Width * norm16Height * 4 * sizeof(uint16_t); + // Expect exact match + ASSERT_EQ(compressedFormat.size, norm16Size); + + // Create compressed texture with 0x0 (1 block = 4x4 pixels, 8 bytes) + std::vector compressedInitColor(compressedFormat.size, 0x0); + + // Create Compressed Texture + GLTexture compressedTex; + glBindTexture(GL_TEXTURE_2D, compressedTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, compressedFormat.format, + compressedFormat.blockX, compressedFormat.blockY, 0, + compressedFormat.size, compressedInitColor.data()); + ASSERT_GL_NO_ERROR(); + + // Create a texture with 0x33 + std::vector norm16InitColor(norm16Size, 0x33); + + // Create Uncompressed Texture + GLTexture norm16Tex; + glBindTexture(GL_TEXTURE_2D, norm16Tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, norm16Format.internalformat, norm16Width, norm16Height, + 0, norm16Format.format, norm16Format.type, norm16InitColor.data()); + ASSERT_GL_NO_ERROR(); + + if (isCompressedToNorm16) + { + // Copy from compressed to uncompressed + glCopyImageSubDataEXT(compressedTex, GL_TEXTURE_2D, 0, 0, 0, 0, norm16Tex, + GL_TEXTURE_2D, 0, 0, 0, 0, compressedFormat.blockX, + compressedFormat.blockY, 1); + ASSERT_GL_NO_ERROR(); + + // Read back destination texture memory + std::vector readback(norm16Size); + glBindTexture(GL_TEXTURE_2D, norm16Tex); + glGetTexImageANGLE(GL_TEXTURE_2D, 0, norm16Format.format, norm16Format.type, + readback.data()); + ASSERT_GL_NO_ERROR(); + + // Raw memory comparison + EXPECT_EQ(memcmp(readback.data(), compressedInitColor.data(), norm16Size), 0); + } + else + { + // Copy from uncompressed to compressed + glCopyImageSubDataEXT(norm16Tex, GL_TEXTURE_2D, 0, 0, 0, 0, compressedTex, + GL_TEXTURE_2D, 0, 0, 0, 0, norm16Width, norm16Height, 1); + ASSERT_GL_NO_ERROR(); + + // Read back destination texture memory + std::vector readback(compressedFormat.size); + glBindTexture(GL_TEXTURE_2D, compressedTex); + glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 0, readback.data()); + ASSERT_GL_NO_ERROR(); + + // Raw memory comparison + EXPECT_EQ(memcmp(readback.data(), norm16InitColor.data(), compressedFormat.size), + 0); + } + } + } +} + +// Test glCopyImageSubDataEXT from a compressed 2D texture to RGBA16_EXT/RGBA16_SNORM_EXT +TEST_P(CopyImageTestES31, CompressedToNorm16) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image") || + !IsGLExtensionEnabled("GL_EXT_texture_norm16") || + !IsGLExtensionEnabled("GL_ANGLE_get_image")); + CopyImageCompressedWithNorm16(true); +} + +// Test glCopyImageSubDataEXT from RGBA16_EXT/RGBA16_SNORM_EXT to compressed 2D texture +TEST_P(CopyImageTestES31, Norm16ToCompressed) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image") || + !IsGLExtensionEnabled("GL_EXT_texture_norm16") || + !IsGLExtensionEnabled("GL_ANGLE_get_image")); + CopyImageCompressedWithNorm16(false); +} + class TextureChangeStorageUploadTest : public ANGLETest<> { protected: @@ -16110,11 +18739,10 @@ void main() #define ES3_EMULATE_COPY_TEX_IMAGE() \ ES3_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \ ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers) -ANGLE_INSTANTIATE_TEST(Texture2DTest, - ANGLE_ALL_TEST_PLATFORMS_ES2, - ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(), - ES2_EMULATE_COPY_TEX_IMAGE(), - ES2_WEBGPU()); +ANGLE_INSTANTIATE_TEST_ES2_AND(Texture2DTest, + ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(), + ES2_EMULATE_COPY_TEX_IMAGE(), + ES2_OPENGLES().enable(Feature::ForcePassthroughShaders)); ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest); ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale); ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest); @@ -16124,7 +18752,8 @@ ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3); ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3, ES3_VULKAN().enable(Feature::AllocateNonZeroMemory), - ES3_VULKAN().enable(Feature::ForceFallbackFormat)); + ES3_VULKAN().enable(Feature::ForceFallbackFormat), + ES3_VULKAN_SWIFTSHADER().enable(Feature::PreferBGR565ToRGB565)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DMemoryTestES3); ANGLE_INSTANTIATE_TEST_ES3(Texture2DMemoryTestES3); @@ -16182,11 +18811,17 @@ ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructArrayAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerInNestedStructAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAndOtherVariableTest); ANGLE_INSTANTIATE_TEST_ES2(TextureAnisotropyTest); -ANGLE_INSTANTIATE_TEST_ES2(TextureBorderClampTest); +ANGLE_INSTANTIATE_TEST_ES2_AND(TextureBorderClampTest, + ES2_VULKAN_SWIFTSHADER().enable(Feature::PreferBGR565ToRGB565)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES3); ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampTestES3); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES31); +ANGLE_INSTANTIATE_TEST_ES31(TextureBorderClampTestES31); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES32); +ANGLE_INSTANTIATE_TEST_ES32(TextureBorderClampTestES32); + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampIntegerTestES3); ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampIntegerTestES3); @@ -16203,13 +18838,11 @@ ANGLE_INSTANTIATE_TEST_ES2(TextureLimitsTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DNorm16TestES3); ANGLE_INSTANTIATE_TEST_ES3(Texture2DNorm16TestES3); -ANGLE_INSTANTIATE_TEST(Texture2DRGTest, - ANGLE_ALL_TEST_PLATFORMS_ES2, - ANGLE_ALL_TEST_PLATFORMS_ES3, - ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(), - ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB(), - ES2_EMULATE_COPY_TEX_IMAGE(), - ES3_EMULATE_COPY_TEX_IMAGE()); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(Texture2DRGTest, + ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(), + ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB(), + ES2_EMULATE_COPY_TEX_IMAGE(), + ES3_EMULATE_COPY_TEX_IMAGE()); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DFloatTestES3); ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3); @@ -16219,6 +18852,9 @@ ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES3); ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureDefaultTextureTest); +ANGLE_INSTANTIATE_TEST_ES3(TextureDefaultTextureTest); + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES32); ANGLE_INSTANTIATE_TEST_ES32(TextureCubeTestES32); diff --git a/src/tests/gl_tests/TextureUploadFormatTest.cpp b/src/tests/gl_tests/TextureUploadFormatTest.cpp index 4b73919f727..40131bf796f 100644 --- a/src/tests/gl_tests/TextureUploadFormatTest.cpp +++ b/src/tests/gl_tests/TextureUploadFormatTest.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Texture upload format tests: +// TextureUploadFormatTest.cpp: // Test all texture unpack/upload formats for sampling correctness. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/mathutil.h" #include "image_util/copyimage.h" #include "test_utils/ANGLETest.h" @@ -16,8 +20,19 @@ using namespace angle; namespace { +enum class UploadSource +{ + ClientMemory, + PBO, +}; class TextureUploadFormatTest : public ANGLETest<> +{ + protected: + void TestAll(UploadSource uploadSource); +}; + +class TextureUploadFormatTest_ES3 : public TextureUploadFormatTest {}; struct TexFormat final @@ -144,7 +159,7 @@ void EncodeThenZeroAndCopy(DestT &dest, const float srcVals[4]) // Upload (1,2,5,3) to integer formats, and (1,2,5,3)/8.0 to float formats. // Draw a point into a 1x1 renderbuffer and readback the result for comparison with expectations. // Test all internalFormat/unpackFormat/unpackType combinations from ES3.0. -TEST_P(TextureUploadFormatTest, All) +void TextureUploadFormatTest::TestAll(UploadSource uploadSource) { ANGLE_SKIP_TEST_IF(IsD3D9()); @@ -290,8 +305,25 @@ TEST_P(TextureUploadFormatTest, All) std::array srcBuffer; std::array subrectBuffer; + + GLBuffer pboBuffer; + const bool usePBO = uploadSource == UploadSource::PBO; + if (usePBO) + { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboBuffer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, subrectBuffer.size(), nullptr, GL_DYNAMIC_DRAW); + } + const auto fnTest = [&](const TexFormat &format, const GLColor &err) { - fnTestData(format, srcBuffer.data(), err, "simple"); + if (usePBO) + { + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, srcBuffer.size(), srcBuffer.data()); + fnTestData(format, nullptr, err, "simple"); + } + else + { + fnTestData(format, srcBuffer.data(), err, "simple"); + } if (!hasSubrectUploads) return; @@ -302,7 +334,15 @@ TEST_P(TextureUploadFormatTest, All) subrectBuffer.fill(0); memcpy(subrectBuffer.data() + bytesPerPixel, srcBuffer.data(), bytesPerPixel); - fnTestData(format, subrectBuffer.data(), err, "subrect"); + if (usePBO) + { + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, subrectBuffer.size(), subrectBuffer.data()); + fnTestData(format, nullptr, err, "simple"); + } + else + { + fnTestData(format, subrectBuffer.data(), err, "subrect"); + } glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); }; @@ -631,4 +671,19 @@ TEST_P(TextureUploadFormatTest, All) EXPECT_GL_NO_ERROR(); } +// Test uploadings without PBO +TEST_P(TextureUploadFormatTest, All) +{ + TestAll(UploadSource::ClientMemory); +} + +// Test uploadings with PBO +TEST_P(TextureUploadFormatTest_ES3, AllWithPBO) +{ + TestAll(UploadSource::PBO); +} + ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureUploadFormatTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureUploadFormatTest_ES3); +ANGLE_INSTANTIATE_TEST_ES3(TextureUploadFormatTest_ES3); diff --git a/src/tests/gl_tests/TimeoutDrawTest.cpp b/src/tests/gl_tests/TimeoutDrawTest.cpp new file mode 100644 index 00000000000..a53ba6fd09f --- /dev/null +++ b/src/tests/gl_tests/TimeoutDrawTest.cpp @@ -0,0 +1,201 @@ + +// +// Copyright 2025 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. +// +#include "test_utils/ANGLETest.h" +#include "test_utils/gl_raii.h" +#include "util/shader_utils.h" + +namespace +{ + +// To inspect current behavior, run the tests in following manner: +// clang-format off +// ANGLE_FEATURE_OVERRIDES_DISABLED=injectAsmStatementIntoLoopBodies GMD_STDOUT=1 ./out/Debug/angle_end2end_tests --gtest_also_run_disabled_tests --gtest_filter=TimeoutDrawTest.DISABLED_DynamicInfiniteLoop2VS/ES3_Metal +// GMD_STDOUT=1 ./out/Debug/angle_end2end_tests --gtest_also_run_disabled_tests --gtest_filter=TimeoutDrawTest.DISABLED_DynamicInfiniteLoop2VS/ES3_Metal_EnsureLoopForwardProgress +// clang-format on + +using namespace angle; +class TimeoutDrawTest : public ANGLETest<> +{ + protected: + TimeoutDrawTest() + { + setWindowWidth(128); + setWindowHeight(128); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + // Tests should skip if robustness not supported, but this can be done only after + // Metal supports robustness. + if (IsEGLClientExtensionEnabled("EGL_EXT_create_context_robustness")) + { + setContextResetStrategy(EGL_LOSE_CONTEXT_ON_RESET_EXT); + } + else + { + setContextResetStrategy(EGL_NO_RESET_NOTIFICATION_EXT); + } + } + void testSetUp() override + { + glClear(GL_COLOR_BUFFER_BIT); + glFinish(); + } +}; + +// Tests that trivial infinite loops in vertex shaders hang instead of progress. +TEST_P(TimeoutDrawTest, DISABLED_TrivialInfiniteLoopVS) +{ + constexpr char kVS[] = R"(precision highp float; +attribute vec4 a_position; +void main() +{ + for (;;) {} + gl_Position = a_position; +})"; + ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glFinish(); + if (glGetError() != GL_CONTEXT_LOST) + { + FAIL(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + } +} + +// Tests that trivial infinite loops in fragment shaders hang instead of progress. +TEST_P(TimeoutDrawTest, DISABLED_TrivialInfiniteLoopFS) +{ + constexpr char kFS[] = R"(precision mediump float; +void main() +{ + for (;;) {} + gl_FragColor = vec4(1, 0, 0, 1); +})"; + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glFinish(); + if (glGetError() != GL_CONTEXT_LOST) + { + FAIL(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + } +} +// Tests that infinite loops based on user-supplied values in vertex shaders hang instead of +// progress. Otherwise optimizer would be able to assume something about the domain of the +// user-supplied value. +TEST_P(TimeoutDrawTest, DISABLED_DynamicInfiniteLoopVS) +{ + constexpr char kVS[] = R"(precision highp float; +attribute vec4 a_position; +uniform int f; +void main() +{ + for (;f != 0;) {} + gl_Position = a_position; +})"; + ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); + glUseProgram(program); + GLint uniformLocation = glGetUniformLocation(program, "f"); + glUniform1i(uniformLocation, 77); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glFinish(); + if (glGetError() != GL_CONTEXT_LOST) + { + FAIL(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + } +} +// Tests that infinite loops based on user-supplied values in fragment shaders hang instead of +// progress. Otherwise optimizer would be able to assume something about the domain of the +// user-supplied value. +TEST_P(TimeoutDrawTest, DISABLED_DynamicInfiniteLoopFS) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform int f; +void main() +{ + for (;f != 0;) {} + gl_FragColor = vec4(1, 0, 0, 1); +})"; + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + glUseProgram(program); + GLint uniformLocation = glGetUniformLocation(program, "f"); + glUniform1i(uniformLocation, 88); + EXPECT_GL_NO_ERROR(); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glFinish(); + if (glGetError() != GL_CONTEXT_LOST) + { + FAIL(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + } +} +// Tests that infinite loops based on user-supplied values in vertex shaders hang instead of +// progress. Otherwise optimizer would be able to assume something about the domain of the +// user-supplied value. Explicit value break variant. +TEST_P(TimeoutDrawTest, DISABLED_DynamicInfiniteLoop2VS) +{ + constexpr char kVS[] = R"(precision highp float; +attribute vec4 a_position; +uniform int f; +void main() +{ + for (;;) { if (f <= 1) break; } + gl_Position = a_position; +})"; + ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); + glUseProgram(program); + GLint uniformLocation = glGetUniformLocation(program, "f"); + glUniform1i(uniformLocation, 66); + EXPECT_GL_NO_ERROR(); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glFinish(); + if (glGetError() != GL_CONTEXT_LOST) + { + FAIL(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + } +} + +// Tests that infinite loops based on user-supplied values in fragment shaders hang instead of +// progress. Otherwise optimizer would be able to assume something about the domain of the +// user-supplied value. Explicit value break variant. +TEST_P(TimeoutDrawTest, DISABLED_DynamicInfiniteLoop2FS) +{ + constexpr char kFS[] = R"(precision mediump float; +uniform float f; +void main() +{ + for (;;) { if (f < 0.1) break; } + gl_FragColor = vec4(1, 0, f, 1); +})"; + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); + glUseProgram(program); + GLint uniformLocation = glGetUniformLocation(program, "f"); + glUniform1f(uniformLocation, .5f); + EXPECT_GL_NO_ERROR(); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glFinish(); + if (glGetError() != GL_CONTEXT_LOST) + { + FAIL(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); + } +} +} // namespace + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TimeoutDrawTest); + +ANGLE_INSTANTIATE_TEST( + TimeoutDrawTest, + WithRobustness(ES2_METAL()), + WithRobustness(ES3_METAL()), + WithRobustness(ES2_METAL().enable(Feature::InjectAsmStatementIntoLoopBodies)), + WithRobustness(ES3_METAL().enable(Feature::InjectAsmStatementIntoLoopBodies)), + WithRobustness(ES2_METAL().enable(Feature::EnsureLoopForwardProgress)), + WithRobustness(ES3_METAL().enable(Feature::EnsureLoopForwardProgress))); diff --git a/src/tests/gl_tests/TimerQueriesTest.cpp b/src/tests/gl_tests/TimerQueriesTest.cpp index 99bf8b77afe..ef8b7935706 100644 --- a/src/tests/gl_tests/TimerQueriesTest.cpp +++ b/src/tests/gl_tests/TimerQueriesTest.cpp @@ -561,6 +561,52 @@ TEST_P(TimerQueriesTestES3, TimestampGetInteger64) EXPECT_LT(result1, result2); } +// Test glQueryCounterEXT with target GL_TIMESTAMP_EXT after query id has been used for +// GL_ANY_SAMPLES_PASSED +TEST_P(TimerQueriesTest, QueryCounterEXTWithTypeMismatch) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query")); + + GLuint query = 0; + GLint result = 0; + glGenQueriesEXT(1, &query); + glBeginQueryEXT(GL_ANY_SAMPLES_PASSED, query); + glEndQueryEXT(GL_ANY_SAMPLES_PASSED); + glGetQueryObjectivEXT(query, GL_QUERY_RESULT_EXT, &result); + ASSERT_GL_NO_ERROR(); + + glQueryCounterEXT(query, GL_TIMESTAMP_EXT); + ASSERT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Tests glGetQueryivEXT with GL_QUERY_COUNTER_BITS_EXT works for all targets. +TEST_P(TimerQueriesTest, QueryCounterBits) +{ + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query")); + GLint result; + + glGetQueryivEXT(GL_ANY_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS_EXT, &result); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(result, 1); + + glGetQueryivEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, GL_QUERY_COUNTER_BITS_EXT, &result); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(result, 1); + + glGetQueryivEXT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_QUERY_COUNTER_BITS_EXT, &result); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(result, 32); + + // Value is returned from Vulkan, so we do not need to check the value since it can vary on + // different platforms + glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &result); + ASSERT_GL_NO_ERROR(); + + glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &result); + ASSERT_GL_NO_ERROR(); +} + ANGLE_INSTANTIATE_TEST_ES2_AND(TimerstampQueriesTest, ES3_D3D11().disable(Feature::EnableTimestampQueries), ES3_D3D11().enable(Feature::EnableTimestampQueries)); diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp index 84a99299151..ed019b18b67 100644 --- a/src/tests/gl_tests/TransformFeedbackTest.cpp +++ b/src/tests/gl_tests/TransformFeedbackTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" @@ -1653,6 +1657,65 @@ TEST_P(TransformFeedbackTest, CaptureAndCopy) EXPECT_GL_NO_ERROR(); } +// Test that the captured xfb buffer can be used as uniform buffer. +TEST_P(TransformFeedbackTest, CaptureThenUseAsUBO) +{ + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // Set the program's transform feedback varyings (just gl_Position) + std::vector tfVaryings; + tfVaryings.push_back("gl_Position"); + compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS); + glUseProgram(mProgram); + GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib()); + + // First pass: draw 3 points to the XFB buffer + glEnable(GL_RASTERIZER_DISCARD); + const GLfloat vertices[] = {-0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f}; + glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); + glEnableVertexAttribArray(positionLocation); + + // Bind the buffer for transform feedback output and start transform feedback + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer); + glBeginTransformFeedback(GL_POINTS); + + glDrawArrays(GL_POINTS, 0, 3); + // End the transform feedback + glEndTransformFeedback(); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); + glDisable(GL_RASTERIZER_DISCARD); + + // Second pass: draw from the feedback buffer + { + glBindBuffer(GL_UNIFORM_BUFFER, mTransformFeedbackBuffer); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, mTransformFeedbackBuffer); + EXPECT_GL_NO_ERROR(); + + constexpr char kVerifyUBO[] = R"(#version 300 es + precision mediump float; + uniform block { + vec3 data[3]; + } ubo; + out vec4 colorOut; + void main() + { + bool data0Ok = all(equal(ubo.data[0], vec3(-0.5f, 0.5f, 0.5f))); + bool data1Ok = all(equal(ubo.data[1], vec3(-0.5f, -0.5f, 0.5f))); + bool data2Ok = all(equal(ubo.data[2], vec3(0.5f, -0.5f, 0.5f))); + if (data0Ok && data1Ok && data2Ok) + colorOut = vec4(0, 1.0, 0, 1.0); + else + colorOut = vec4(0, 0, 1.0, 1.0); + })"; + + ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO); + drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green); + } +} + class TransformFeedbackLifetimeTest : public TransformFeedbackTest { protected: @@ -2148,10 +2211,9 @@ TEST_P(TransformFeedbackTestES31, CaptureArray) float *mappedFloats = static_cast(mappedBuffer); for (int i = 0; i < 6; i++) { - std::array mappedData = {mappedFloats[i * 3], mappedFloats[i * 3 + 1], - mappedFloats[i * 3 + 2]}; - std::array data = {data1[i], data2[i], data3[i]}; - EXPECT_EQ(data, mappedData) << "iteration #" << i; + EXPECT_NEAR(data1[i], mappedFloats[i * 3], 0.001f); + EXPECT_NEAR(data2[i], mappedFloats[i * 3 + 1], 0.001f); + EXPECT_NEAR(data3[i], mappedFloats[i * 3 + 2], 0.001f); } glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); @@ -4434,6 +4496,246 @@ color = var; glFlush(); } +// Test that geometry or tessellation shader support allows transform feedback primitive to be +// different from the draw call. +TEST_P(TransformFeedbackTestES31, ModeMismatchButSameClass) +{ + // Geometry and tessellation shaders allow the transform feedback mode to match the draw call's + // primitive mode class but not necessarily identically. + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader") && + !IsGLExtensionEnabled("GL_OES_geometry_shader") && + !IsGLExtensionEnabled("GL_EXT_tessellation_shader") && + !IsGLExtensionEnabled("GL_OES_tessellation_shader")); + + std::vector tfVaryings; + tfVaryings.push_back("gl_Position"); + mProgram = CompileProgramWithTransformFeedback( + essl3_shaders::vs::Simple(), essl3_shaders::fs::Red(), tfVaryings, GL_INTERLEAVED_ATTRIBS); + + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer); + glUseProgram(mProgram); + glBeginTransformFeedback(GL_TRIANGLES); + + const GLint posLoc = glGetAttribLocation(mProgram, essl3_shaders::PositionAttrib()); + constexpr GLfloat kVertices[] = {-1, -1, 1, -1, -1, 1, 1, 1}; + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, kVertices, GL_STATIC_DRAW); + glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(posLoc); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glEndTransformFeedback(); + + const GLfloat *mapped = (const GLfloat *)glMapBufferRange( + GL_TRANSFORM_FEEDBACK_BUFFER, 0, 6 * 4 * sizeof(float), GL_MAP_READ_BIT); + + // First triangle + EXPECT_EQ(mapped[0], -1.0); + EXPECT_EQ(mapped[1], -1.0); + EXPECT_EQ(mapped[2], 0.0); + EXPECT_EQ(mapped[3], 1.0); + + EXPECT_EQ(mapped[4], 1.0); + EXPECT_EQ(mapped[5], -1.0); + EXPECT_EQ(mapped[6], 0.0); + EXPECT_EQ(mapped[7], 1.0); + + EXPECT_EQ(mapped[8], -1.0); + EXPECT_EQ(mapped[9], 1.0); + EXPECT_EQ(mapped[10], 0.0); + EXPECT_EQ(mapped[11], 1.0); + + // Second triangle. The ordering of the vertices is driver-dependent. + // Most drivers produce (-1, 1), (1, -1), (1, 1) (variant 1). But some drivers produce + // (1, -1), (1, 1), (-1, 1) (variant 2). + const bool isVariant2 = mapped[12] == 1; + + EXPECT_EQ(mapped[12], isVariant2 ? 1.0 : -1.0); + EXPECT_EQ(mapped[13], isVariant2 ? -1.0 : 1.0); + EXPECT_EQ(mapped[14], 0.0); + EXPECT_EQ(mapped[15], 1.0); + + EXPECT_EQ(mapped[16], 1.0); + EXPECT_EQ(mapped[17], isVariant2 ? 1.0 : -1.0); + EXPECT_EQ(mapped[18], 0.0); + EXPECT_EQ(mapped[19], 1.0); + + EXPECT_EQ(mapped[20], isVariant2 ? -1.0 : 1.0); + EXPECT_EQ(mapped[21], 1.0); + EXPECT_EQ(mapped[22], 0.0); + EXPECT_EQ(mapped[23], 1.0); + + glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); + ASSERT_GL_NO_ERROR(); +} + +// Test that while geometry or tessellation shader support allows transform feedback primitive to be +// different from the draw call, the classes should still match. +TEST_P(TransformFeedbackTestES31, ModeMismatchClassMismatch) +{ + // Geometry and tessellation shaders allow the transform feedback mode to match the draw call's + // primitive mode class but not necessarily identically. + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader") && + !IsGLExtensionEnabled("GL_OES_geometry_shader") && + !IsGLExtensionEnabled("GL_EXT_tessellation_shader") && + !IsGLExtensionEnabled("GL_OES_tessellation_shader")); + + std::vector tfVaryings; + tfVaryings.push_back("gl_Position"); + mProgram = CompileProgramWithTransformFeedback( + essl3_shaders::vs::Simple(), essl3_shaders::fs::Red(), tfVaryings, GL_INTERLEAVED_ATTRIBS); + + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer); + glUseProgram(mProgram); + glBeginTransformFeedback(GL_TRIANGLES); + + GLVertexArray vao; + glBindVertexArray(vao); + + const GLint posLoc = glGetAttribLocation(mProgram, essl3_shaders::PositionAttrib()); + constexpr GLfloat kVertices[] = {-1, -1, 1, -1, -1, 1, 1, 1}; + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + // Create a large buffer because while the data is set up for triangle strip, other modes are + // also tested. + glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * 8, kVertices); + glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(posLoc); + + GLBuffer indirectBuffer; + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer); + constexpr uint32_t kIndirectParams[] = {4, 1, 0, 0, 0}; + glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uint32_t) * 5, kIndirectParams, GL_STATIC_DRAW); + + // First, use an acceptable mode to make sure everything is set up correctly. + glDrawArraysIndirect(GL_TRIANGLE_STRIP, nullptr); + glEndTransformFeedback(); + + const GLfloat *mapped = (const GLfloat *)glMapBufferRange( + GL_TRANSFORM_FEEDBACK_BUFFER, 0, 6 * 4 * sizeof(float), GL_MAP_READ_BIT); + + // First triangle + EXPECT_EQ(mapped[0], -1.0); + EXPECT_EQ(mapped[1], -1.0); + EXPECT_EQ(mapped[2], 0.0); + EXPECT_EQ(mapped[3], 1.0); + + EXPECT_EQ(mapped[4], 1.0); + EXPECT_EQ(mapped[5], -1.0); + EXPECT_EQ(mapped[6], 0.0); + EXPECT_EQ(mapped[7], 1.0); + + EXPECT_EQ(mapped[8], -1.0); + EXPECT_EQ(mapped[9], 1.0); + EXPECT_EQ(mapped[10], 0.0); + EXPECT_EQ(mapped[11], 1.0); + + // Second triangle is not verified. The ordering of the vertices is driver-dependent, and the + // ModeMismatchButSameClass test above already verifies correctness for this case. + + glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); + ASSERT_GL_NO_ERROR(); + + // Then verify that the other modes are validated correctly. + glBeginTransformFeedback(GL_TRIANGLES); + glDrawArraysIndirect(GL_POINTS, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glDrawArraysIndirect(GL_LINES, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glDrawArraysIndirect(GL_LINE_STRIP, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glDrawArraysIndirect(GL_LINE_LOOP, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glDrawArraysIndirect(GL_TRIANGLES, nullptr); + EXPECT_GL_NO_ERROR(); + + glDrawArraysIndirect(GL_TRIANGLE_FAN, nullptr); + EXPECT_GL_NO_ERROR(); + + glDrawArraysIndirect(GL_PATCHES, nullptr); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glEndTransformFeedback(); +} + +class WebGLTransformFeedbackTest : public TransformFeedbackTest +{ + public: + WebGLTransformFeedbackTest() { setWebGLCompatibilityEnabled(true); } +}; + +// Test that XFB does not allow writing more vertices than fit in the bound buffers. +// This version exercises the extra restrictions specified by the WebGL specification. +TEST_P(WebGLTransformFeedbackTest, TooSmallBuffers) +{ + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + glEnable(GL_RASTERIZER_DISCARD); + + // Set the program's transform feedback varyings (just gl_Position) + std::vector tfVaryings; + tfVaryings.push_back("gl_Position"); + compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS); + GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib()); + + glUseProgram(mProgram); + + const GLfloat vertices[] = { + -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f, + -1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f, + }; + + GLBuffer buffer; + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLocation); + + const size_t verticesToDraw = 6; + const size_t stride = sizeof(float) * 4; + const size_t bytesNeeded = stride * verticesToDraw; + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer); + + // Set up the buffer to be the right size + uint8_t tfData[stride * verticesToDraw] = {0}; + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bytesNeeded, &tfData, GL_STATIC_DRAW); + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, verticesToDraw); + EXPECT_GL_NO_ERROR(); + glEndTransformFeedback(); + + // Set up the buffer to be too small + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bytesNeeded - 1, &tfData, GL_STATIC_DRAW); + + glBeginTransformFeedback(GL_POINTS); + EXPECT_GL_NO_ERROR(); + glDrawArrays(GL_POINTS, 0, verticesToDraw); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glEndTransformFeedback(); + + // Set up the buffer to be the right size but make it smaller after glBeginTransformFeedback + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bytesNeeded, &tfData, GL_STATIC_DRAW); + glBeginTransformFeedback(GL_POINTS); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bytesNeeded - 1, &tfData, GL_STATIC_DRAW); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glPauseTransformFeedback(); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bytesNeeded - 1, &tfData, GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + glResumeTransformFeedback(); + glDrawArrays(GL_POINTS, 0, verticesToDraw); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glEndTransformFeedback(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTest); ANGLE_INSTANTIATE_TEST_ES3_AND(TransformFeedbackTest, ES3_VULKAN().disable(Feature::SupportsTransformFeedbackExtension), @@ -4471,4 +4773,12 @@ ANGLE_INSTANTIATE_TEST_ES3_AND(TransformFeedbackWithDepthBufferTest, ES3_VULKAN() .disable(Feature::SupportsTransformFeedbackExtension) .disable(Feature::SupportsSPIRV14)); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLTransformFeedbackTest); +ANGLE_INSTANTIATE_TEST_ES3_AND(WebGLTransformFeedbackTest, + ES3_VULKAN().disable(Feature::SupportsTransformFeedbackExtension), + ES3_VULKAN() + .disable(Feature::SupportsTransformFeedbackExtension) + .disable(Feature::SupportsSPIRV14)); + } // anonymous namespace diff --git a/src/tests/gl_tests/UniformBufferTest.cpp b/src/tests/gl_tests/UniformBufferTest.cpp index 158dbe81706..6c44fa958b7 100644 --- a/src/tests/gl_tests/UniformBufferTest.cpp +++ b/src/tests/gl_tests/UniformBufferTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/random_utils.h" @@ -786,7 +790,7 @@ TEST_P(UniformBufferTest, VeryLargeReadback) // block before larger one. TEST_P(UniformBufferTest, MultipleSizesSmallBeforeBig) { - constexpr size_t kSizeOfVec4 = 4 * sizeof(float); + constexpr GLint kSizeOfVec4 = 4 * sizeof(float); constexpr char kUniformName[] = "uni"; constexpr char kFS1[] = R"(#version 300 es precision highp float; @@ -813,8 +817,9 @@ void main() { GLint offsetAlignmentInBytes; glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignmentInBytes); - ASSERT_EQ(offsetAlignmentInBytes % kSizeOfVec4, 0U); - GLint offsetAlignmentInVec4 = offsetAlignmentInBytes / kSizeOfVec4; + ASSERT_TRUE(offsetAlignmentInBytes < kSizeOfVec4 || offsetAlignmentInBytes % kSizeOfVec4 == 0); + GLint offsetAlignmentInVec4 = + offsetAlignmentInBytes < kSizeOfVec4 ? 1 : offsetAlignmentInBytes / kSizeOfVec4; // Insert padding required by implementation to have first unform block at a non-zero // offset. @@ -1185,6 +1190,911 @@ void main() { EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test that buffer updates between uniform buffer range change works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeAfterSubData) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni0; + +out vec4 fragColor; + +void main() +{ + fragColor = uni0.color; +})"; + + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to Half red color + colors[0] = 0.55; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 0.35; + + GLBuffer ubo; + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with uniform buffer range = [0, size / 2) + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Update last-half of the buffer with Greenish yellow + colors[alignment / 4 + 0] = 0.55; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 0.75; + glBufferSubData(GL_UNIFORM_BUFFER, alignment, alignment, &colors[alignment / 4]); + + // Draw with uniform buffer range = [size / 2, size) + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, alignment, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); +} + +// Test that buffer updates between uniform buffer range change with multiple UBOs works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithMultipleUBO) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni0; + +layout (binding = 1) uniform block1 { + vec4 color; +} uni1; + +out vec4 fragColor; + +void main() +{ + fragColor = uni0.color + uni1.color; +})"; + + // Setup UBOs + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to green color + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + + GLBuffer ubo0; + glBindBuffer(GL_UNIFORM_BUFFER, ubo0); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + std::vector colorA(alignment / 4, 0); + // Set color to green color + colorA[0] = 0.0; + colorA[1] = 1.0; + colorA[2] = 0.0; + colorA[3] = 1.0; + GLBuffer uboA; + glBindBuffer(GL_UNIFORM_BUFFER, uboA); + glBufferData(GL_UNIFORM_BUFFER, alignment, colorA.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + std::vector colorB(alignment / 4, 0); + // Set color to blue color + colorB[0] = 0.0; + colorB[1] = 0.0; + colorB[2] = 1.0; + colorB[3] = 1.0; + GLBuffer uboB; + glBindBuffer(GL_UNIFORM_BUFFER, uboB); + glBufferData(GL_UNIFORM_BUFFER, alignment, colorB.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with ubo0 with buffer range = [0, size / 2) and uboA + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, 0, kVec4Size); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, uboA, 0, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with ubo0 with buffer range = [size / 2, size) and uboB + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, alignment, kVec4Size); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, uboB, 0, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); +} + +// Test that buffer range changes to inactive UBOs works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeToInactiveUBO) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni0; + +layout (binding = 1) uniform block1 { + vec4 color; +} uni1; + +out vec4 fragColor; + +void main() +{ + fragColor = uni0.color + uni1.color; +})"; + + constexpr char kFSWithInactiveUBO[] = R"(#version 310 es +precision highp float; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni0; + +layout (binding = 1) uniform block1 { + vec4 color; +} uni1; + +out vec4 fragColor; + +void main() +{ + fragColor = uni0.color; +})"; + + // Setup UBOs + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to green color + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + + GLBuffer ubo0; + glBindBuffer(GL_UNIFORM_BUFFER, ubo0); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Switch color order for the other UBO + // Set first-half of buffer to green color + colors[0] = 0.0; + colors[1] = 1.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to red color + colors[alignment / 4 + 0] = 1.0; + colors[alignment / 4 + 1] = 0.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + GLBuffer ubo1; + glBindBuffer(GL_UNIFORM_BUFFER, ubo1); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup programs for draw + ANGLE_GL_PROGRAM(programA, essl31_shaders::vs::Simple(), kFS); + ANGLE_GL_PROGRAM(programB, essl31_shaders::vs::Simple(), kFSWithInactiveUBO); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with programA with ubo0 and ubo1 with buffer range = [0, size / 2) + glUseProgram(programA); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, 0, kVec4Size); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, ubo1, 0, kVec4Size); + drawQuad(programA, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); + + // Draw with programB with ubo0 with buffer range = [size / 2, size) + // ubo1 is an inactive UBO in programB + glUseProgram(programB); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, alignment, kVec4Size); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, ubo1, alignment, kVec4Size); + drawQuad(programB, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Draw with programA again but with no changes to ubo0 and ubo1 buffer range + glUseProgram(programA); + drawQuad(programA, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); +} + +// Test that buffer range changes to both SSBO and UBO buffers work. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithSSBO) +{ + constexpr char kFS[] = R"(#version 310 es +precision mediump float; + +layout(binding=0, std140) buffer Storage +{ + uint b; +} ssbo; + +uniform uni { vec4 color; }; +out vec4 fragColor; +void main() +{ + fragColor = color * float(ssbo.b); +} +)"; + + // Setup SSBO + constexpr GLsizei kBytesPerComponent = sizeof(unsigned int); + GLint ssboAlignment; + glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssboAlignment); + if (ssboAlignment < kBytesPerComponent) + { + ssboAlignment = kBytesPerComponent; + } + ASSERT_EQ(ssboAlignment % 4, 0); + + std::vector initialValue(ssboAlignment / 2, 0); + initialValue[0] = 1u; + initialValue[ssboAlignment / 4] = 2u; + GLBuffer ssbo; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); + glBufferData(GL_SHADER_STORAGE_BUFFER, ssboAlignment * 2, initialValue.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo); + + // Setup UBO + constexpr GLsizei kVec4Size = 4 * sizeof(float); + GLint uboAlignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uboAlignment); + if (uboAlignment < kVec4Size) + { + uboAlignment = kVec4Size; + } + ASSERT_EQ(uboAlignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(uboAlignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to half green color + colors[uboAlignment / 4 + 0] = 0.0; + colors[uboAlignment / 4 + 1] = 0.5; + colors[uboAlignment / 4 + 2] = 0.0; + colors[uboAlignment / 4 + 3] = 0.5; + + GLBuffer ubo; + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, uboAlignment * 2, colors.data(), GL_STATIC_DRAW); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with ssbo and ubo range = [0, size / 2) + glUseProgram(program); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, ssbo, 0, kBytesPerComponent); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with ssbo and ubo range = [size / 2, size) + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, ssbo, ssboAlignment, kBytesPerComponent); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, uboAlignment, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); +} + +// Test that buffer range changes to both ACB and UBO buffers work. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithACB) +{ + // Skip the test if atomic counters aren't supported + GLint maxCounters = -1; + glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &maxCounters); + ANGLE_SKIP_TEST_IF(maxCounters <= 0); + + constexpr char kFS[] = R"(#version 310 es +precision highp float; + +layout(binding = 0) uniform atomic_uint acb; +uniform uni { vec4 color; }; +out vec4 fragColor; +void main() +{ + fragColor = color * float(atomicCounter(acb)); +} +)"; + + // Setup ACB + constexpr unsigned int kBytesPerComponent = sizeof(unsigned int); + constexpr unsigned int kInitialValue[2] = {1u, 2u}; + GLBuffer acb; + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, acb); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, kBytesPerComponent * 2, &kInitialValue, GL_STATIC_DRAW); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, acb); + + // Setup UBO + constexpr GLsizei kVec4Size = 4 * sizeof(float); + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to half green color + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 0.5; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 0.5; + + GLBuffer ubo; + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with acb and ubo range = [0, size / 2) + glUseProgram(program); + glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, acb, 0, kBytesPerComponent); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with acb and ubo range = [size / 2, size) + glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, acb, kBytesPerComponent, kBytesPerComponent); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, alignment, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); +} + +// Test that buffer range changes to both UBO and storage image works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithStorageImage) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; +layout(rgba8, binding = 0) uniform highp writeonly image2D img; +uniform uni { vec4 color; }; +out vec4 colorOut; +void main() +{ + colorOut = color; + imageStore(img, ivec2(gl_FragCoord.xy), color); +})"; + + // Setup UBO + constexpr GLsizei kVec4Size = 4 * sizeof(float); + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to green color + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + + GLBuffer ubo; + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + + // Setup storage images + static constexpr int kTextureSize = 1; + GLTexture imageA; + glBindTexture(GL_TEXTURE_2D, imageA); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureSize, kTextureSize); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, + GLColor::transparentBlack.data()); + + GLTexture imageB; + glBindTexture(GL_TEXTURE_2D, imageB); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureSize, kTextureSize); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, + GLColor::transparentBlack.data()); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with imageA and ubo range = [0, size / 2) + glBindImageTexture(0, imageA, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with imageB and ubo range = [size / 2, size) + glBindImageTexture(0, imageB, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, alignment, kVec4Size); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + glFinish(); + + // Verify framebuffer content + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); + + // Verify storage image content + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glBindTexture(GL_TEXTURE_2D, imageA); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, imageA, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + glBindTexture(GL_TEXTURE_2D, imageB); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, imageB, 0); + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test that uniform buffer binding change when using multiple programs works. +TEST_P(UniformBufferTest31, UniformBufferBindingChangeWithMultiplePrograms) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni0; + +layout (binding = 1) uniform block1 { + vec4 color; +} uni1; + +out vec4 fragColor; + +void main() +{ + fragColor = uni0.color + uni1.color; +})"; + + // Setup UBOs + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + // Set color0 to red + std::vector color0 = {1.0, 0.0, 0.0, 1.0}; + + GLBuffer ubo0; + glBindBuffer(GL_UNIFORM_BUFFER, ubo0); + glBufferData(GL_UNIFORM_BUFFER, kVec4Size, color0.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Set colorA to green + std::vector colorA = {0.0, 1.0, 0.0, 1.0}; + GLBuffer uboA; + glBindBuffer(GL_UNIFORM_BUFFER, uboA); + glBufferData(GL_UNIFORM_BUFFER, kVec4Size, colorA.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Set colorB to blue + std::vector colorB = {0.0, 0.0, 1.0, 1.0}; + GLBuffer uboB; + glBindBuffer(GL_UNIFORM_BUFFER, uboB); + glBufferData(GL_UNIFORM_BUFFER, kVec4Size, colorB.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup programs for draw + ANGLE_GL_PROGRAM(program0, essl31_shaders::vs::Simple(), kFS); + ANGLE_GL_PROGRAM(program1, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red()); + + // Draw with program0 + glUseProgram(program0); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with ubo0 and uboA + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, 0, kVec4Size); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, uboA, 0, kVec4Size); + drawQuad(program0, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Change buffer binding of GL_UNIFORM_BUFFER index 1 to uboB + glBindBufferRange(GL_UNIFORM_BUFFER, 1, uboB, 0, kVec4Size); + + // Draw with program1 + glUseProgram(program1); + drawQuad(program1, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with program0, again + glUseProgram(program0); + drawQuad(program0, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta); +} + +// Test that uniform buffer range change when using multiple programs works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithMultiplePrograms) +{ + constexpr char kFS[] = R"(#version 310 es +precision highp float; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni0; + +layout (binding = 1) uniform block1 { + vec4 color; +} uni1; + +out vec4 fragColor; + +void main() +{ + fragColor = uni0.color + uni1.color; +})"; + + // Setup UBOs + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Put two colors in the uniform buffer, the sum of which is yellow. + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to green color + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + + GLBuffer ubo0; + glBindBuffer(GL_UNIFORM_BUFFER, ubo0); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + std::vector colorA(alignment / 4, 0); + // Set color to green color + colorA[0] = 0.0; + colorA[1] = 1.0; + colorA[2] = 0.0; + colorA[3] = 1.0; + GLBuffer uboA; + glBindBuffer(GL_UNIFORM_BUFFER, uboA); + glBufferData(GL_UNIFORM_BUFFER, alignment, colorA.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup programs for draw + ANGLE_GL_PROGRAM(program0, essl31_shaders::vs::Simple(), kFS); + ANGLE_GL_PROGRAM(program1, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red()); + + // Draw with program0 + glUseProgram(program0); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with ubo0 with buffer range = [0, size / 2) and uboA + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, 0, kVec4Size); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, uboA, 0, kVec4Size); + drawQuad(program0, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + // Update buffer range of ubo0 + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo0, alignment, kVec4Size); + + // Draw with program1 + glUseProgram(program1); + drawQuad(program1, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with program0, again + glUseProgram(program0); + drawQuad(program0, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + +// Test that uniform buffer range change with non-coherent framebuffer fetch works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithNonCoherentFBF) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent")); + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require +precision highp float; +layout(noncoherent, location = 0) inout highp vec4 o_color; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni; + +void main (void) +{ + o_color += uni.color; +})"; + + // Setup UBO with 2 colors + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to Green + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + + GLBuffer ubo; + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + // Setup framebuffer with texture attachment + constexpr GLsizei kTextureSize = 1; + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + GLTexture colorBufferTex; + glBindTexture(GL_TEXTURE_2D, colorBufferTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0); + ASSERT_GL_NO_ERROR(); + + // Clear to blue + glClearColor(0, 0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with uniform buffer range = [0, size / 2) + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, kVec4Size); + // Insert barrier to ensure previous framebuffer writes are visible to + // subsequent fragment shader invocations. + glFramebufferFetchBarrierEXT(); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with uniform buffer range = [size / 2, size) + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, alignment, kVec4Size); + // Insert barrier to ensure previous framebuffer writes are visible to + // subsequent fragment shader invocations. + glFramebufferFetchBarrierEXT(); + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +// Test that uniform buffer range change with coherent framebuffer fetch works. +TEST_P(UniformBufferTest31, UniformBufferBindingRangeChangeWithCoherentFBF) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch")); + + constexpr char kFS[] = R"(#version 310 es +#extension GL_EXT_shader_framebuffer_fetch : require +precision highp float; +layout(location = 0) inout highp vec4 o_color; + +layout (binding = 0) uniform block0 { + vec4 color; +} uni; + +void main (void) +{ + o_color += uni.color; +})"; + + // Setup UBO with 2 colors + constexpr GLsizei kVec4Size = 4 * sizeof(float); + + GLint alignment; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); + if (alignment < kVec4Size) + { + alignment = kVec4Size; + } + ASSERT_EQ(alignment % 4, 0); + + // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats. + std::vector colors(alignment / 2, 0); + // Set first-half of buffer to red color + colors[0] = 1.0; + colors[1] = 0.0; + colors[2] = 0.0; + colors[3] = 1.0; + // Set last-half of the buffer to Green + colors[alignment / 4 + 0] = 0.0; + colors[alignment / 4 + 1] = 1.0; + colors[alignment / 4 + 2] = 0.0; + colors[alignment / 4 + 3] = 1.0; + + GLBuffer ubo; + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + // Setup program for draw + ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); + glUseProgram(program); + + // Setup framebuffer with texture attachment + constexpr GLsizei kTextureSize = 1; + GLFramebuffer framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + GLTexture colorBufferTex; + glBindTexture(GL_TEXTURE_2D, colorBufferTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0); + ASSERT_GL_NO_ERROR(); + + // Clear to blue + glClearColor(0, 0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw with uniform buffer range = [0, size / 2) + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, kVec4Size); + // No barrier necessary + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + // Draw with uniform buffer range = [size / 2, size) + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, alignment, kVec4Size); + // No barrier necessary + drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f); + EXPECT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + // Test with a block containing an array of structs. TEST_P(UniformBufferTest, BlockContainingArrayOfStructs) { @@ -3703,9 +4613,9 @@ TEST_P(UniformBufferTest, BufferDataInLoop) { glClear(GL_COLOR_BUFFER_BIT); - // Use large buffer size to get around suballocation, so that we will gets a new buffer with + // Use large buffer size to get around suballocation, so that we will get a new buffer with // bufferData call. - static constexpr size_t kBufferSize = 4 * 1024 * 1024; + static constexpr size_t kBufferSize = 64 * 1024 * 1024; std::vector floatData; floatData.resize(kBufferSize / (sizeof(float)), 0.0f); floatData[0] = 0.5f; diff --git a/src/tests/gl_tests/UniformTest.cpp b/src/tests/gl_tests/UniformTest.cpp index 26469aa3a72..fc742ddb4b0 100644 --- a/src/tests/gl_tests/UniformTest.cpp +++ b/src/tests/gl_tests/UniformTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/angle_test_configs.h" @@ -20,6 +24,9 @@ using namespace angle; namespace { +// The relative precision factor of mediump float-point variables declared in shaders +// Reference: https://developer.arm.com/documentation/102502/0101/Shader-precision +const float kMediumpFloatRelativePrecisionFactor = std::pow(2.0, -10.0); class SimpleUniformTest : public ANGLETest<> { @@ -55,7 +62,7 @@ void main() { GLfloat f = 0.0f; glGetUniformfv(program, uniformLocation, &f); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(f, expected); + EXPECT_NEAR(f, expected, std::abs(expected) * kMediumpFloatRelativePrecisionFactor); } // Test that we can get and set an int uniform successfully. @@ -126,7 +133,11 @@ void main() { std::vector floats(3, 0); glGetUniformfv(program, uniformLocation, floats.data()); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(floats, expected); + for (size_t i = 0; i < 3; ++i) + { + EXPECT_NEAR(floats[i], expected[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); + } } // Test that we can get and set a vec4 uniform successfully. @@ -150,7 +161,59 @@ void main() { std::vector floats(4, 0); glGetUniformfv(program, uniformLocation, floats.data()); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(floats, expected); + for (size_t i = 0; i < 4; ++i) + { + EXPECT_NEAR(floats[i], expected[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); + } +} + +// Test that we can get and set mediump vec4 uniform arrays successfully. +TEST_P(SimpleUniformTest, FloatVec4UniformArrayStateQuery) +{ + constexpr char kFragShader[] = R"(precision mediump float; +uniform vec4 uniVec4[2]; +void main() { + // Use the uniforms to prevent them from being optimized out. + gl_FragColor = uniVec4[0] + uniVec4[1]; +})"; + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader); + glUseProgram(program); + + GLint uniformLocation = glGetUniformLocation(program, "uniVec4"); + ASSERT_NE(uniformLocation, -1); + + // Define data for an array of two vec4 uniforms + std::vector expected = { + 1.0f, 0.5f, 0.2f, -0.8f, // First vec4: uniVec4[0] + -0.1f, 0.3f, 0.7f, -0.9f // Second vec4: uniVec4[1] + }; + + // Set both uniforms in the array with a single API call + glUniform4fv(uniformLocation, 2, expected.data()); + ASSERT_GL_NO_ERROR(); + + // Query and verify the first uniform in the array + std::vector actual1(4, 0); + glGetUniformfv(program, uniformLocation, actual1.data()); + ASSERT_GL_NO_ERROR(); + for (size_t i = 0; i < 4; ++i) + { + EXPECT_NEAR(actual1[i], expected[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); + } + + // Query and verify the second uniform in the array. + // The location of subsequent array elements is found by incrementing the base location. + std::vector actual2(4, 0); + glGetUniformfv(program, uniformLocation + 1, actual2.data()); + ASSERT_GL_NO_ERROR(); + for (size_t i = 0; i < 4; ++i) + { + EXPECT_NEAR(actual2[i], expected[i + 4], + std::abs(expected[i + 4]) * kMediumpFloatRelativePrecisionFactor); + } } // Test that we can get and set a 2x2 float Matrix uniform successfully. @@ -174,7 +237,11 @@ void main() { std::vector floats(4, 0); glGetUniformfv(program, uniformLocation, floats.data()); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(floats, expected); + for (size_t i = 0; i < 4; ++i) + { + EXPECT_NEAR(expected[i], floats[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); + } } // Test that we can get and set a 3x3 float Matrix uniform successfully. @@ -198,7 +265,12 @@ void main() { std::vector floats(9, 0); glGetUniformfv(program, uniformLocation, floats.data()); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(floats, expected); + + for (size_t i = 0; i < 9; ++i) + { + EXPECT_NEAR(expected[i], floats[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); + } } // Test that we can get and set a 4x4 float Matrix uniform successfully. @@ -223,7 +295,11 @@ void main() { std::vector floats(16, 0); glGetUniformfv(program, uniformLocation, floats.data()); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(floats, expected); + for (size_t i = 0; i < 16; ++i) + { + EXPECT_NEAR(expected[i], floats[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); + } } // Test that we can get and set a float array of uniforms. @@ -252,7 +328,8 @@ void main() { GLfloat result = 0; glGetUniformfv(program, uniformLocation, &result); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(result, expected[i]); + EXPECT_NEAR(result, expected[i], + std::abs(expected[i]) * kMediumpFloatRelativePrecisionFactor); } } @@ -283,7 +360,12 @@ void main() { std::vector results(9, 0); glGetUniformfv(program, uniformLocation, results.data()); ASSERT_GL_NO_ERROR(); - ASSERT_EQ(results, expected[i]); + for (size_t matrixElementIndex = 0; matrixElementIndex < 9; ++matrixElementIndex) + { + EXPECT_NEAR( + results[matrixElementIndex], expected[i][matrixElementIndex], + std::abs(expected[i][matrixElementIndex]) * kMediumpFloatRelativePrecisionFactor); + } } } @@ -452,12 +534,61 @@ TEST_P(BasicUniformUsageTest, Vec4MultipleDraws) EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red); } -// Named differently to instantiate on different backends. -using SimpleUniformUsageTest = SimpleUniformTest; +// Test that we can index a uniform matrix correctly. +TEST_P(SimpleUniformTest, FloatMatrix2UniformIndexed) +{ + constexpr char kFragShader[] = R"(precision mediump float; +uniform mat2 umat2; +void main() { + gl_FragColor = vec4(umat2[0], umat2[1]); +})"; + + GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFragShader); + glUseProgram(program); + + GLint uniformLocation = glGetUniformLocation(program, "umat2"); + ASSERT_NE(uniformLocation, -1); + + std::vector expected = {{1.0f, 0.0f, 0.0f, 1.0f}}; + glUniformMatrix2fv(uniformLocation, 1, false, expected.data()); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); +} + +// Test that we can index a uniform matrix correctly, when that uniform matrix is an array element. +TEST_P(SimpleUniformTest, FloatMatrix2ArrayUniformDoubleIndexed) +{ + constexpr char kFragShader[] = R"(precision mediump float; +uniform mat2 umat2Array[2]; +void main() { + gl_FragColor = vec4(umat2Array[1][0], umat2Array[1][1]); +})"; + + GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFragShader); + glUseProgram(program); + + GLint uniformLocation = glGetUniformLocation(program, "umat2Array"); + ASSERT_NE(uniformLocation, -1); + + std::vector uniformData = {// Data for umat2Array[0] + 0.0f, 0.0f, 1.0f, 1.0f, + + // Data for umat2Array[1] + 0.0f, 1.0f, 0.0f, 1.0f}; + + glUniformMatrix2fv(uniformLocation, 2, false, uniformData.data()); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} // In std140, the member following a struct will need to be aligned to 16. This tests that backends // like WGSL which take std140 buffers correctly align this member. -TEST_P(SimpleUniformUsageTest, NestedStructAlignedCorrectly) +TEST_P(SimpleUniformTest, NestedStructAlignedCorrectly) { constexpr char kFragShader[] = R"(precision mediump float; struct NestedUniforms { @@ -515,7 +646,7 @@ void main() { // Similarly to the above, tests that structs as array elements are aligned correctly, and nested // structs that follow float members are aligned correctly. -TEST_P(SimpleUniformUsageTest, NestedStructAlignedCorrectly2) +TEST_P(SimpleUniformTest, NestedStructAlignedCorrectly2) { constexpr char kFragShader[] = R"(precision mediump float; struct NestedUniforms { @@ -620,7 +751,7 @@ void main() { // Tests that arrays in uniforms function corectly. In particular, WGSL requires arrays in uniforms // to have a stride a multiple of 16, but some arrays (e.g. vec2[N] or float[N]) will not // automatically have stride 16 and need special handling. -TEST_P(SimpleUniformUsageTest, ArraysInUniforms) +TEST_P(SimpleUniformTest, ArraysInUniforms) { constexpr char kFragShader[] = R"( precision mediump float; @@ -692,10 +823,48 @@ void main() { glDeleteProgram(program); } -using SimpleUniformUsageTestES3 = SimpleUniformUsageTest; +// Tests that inactive uniforms do not cause buffer offsets to be incorrectly calculated. +TEST_P(SimpleUniformTest, MiddleInactiveUniform) +{ + constexpr char kFragShader[] = R"( +precision mediump float; + +uniform vec4 one; +uniform vec4 two; +uniform vec4 three; + +void main() { + gl_FragColor = vec4(0.0); + gl_FragColor += one; + gl_FragColor += three; +})"; + + GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint uniformOneLocation = glGetUniformLocation(program, "one"); + ASSERT_NE(uniformOneLocation, -1); + GLint uniformTwoLocation = glGetUniformLocation(program, "two"); + ASSERT_EQ(uniformTwoLocation, -1); + GLint uniformThreeLocation = glGetUniformLocation(program, "three"); + ASSERT_NE(uniformThreeLocation, -1); + + // Set to magenta. + glUniform4f(uniformOneLocation, 1.0f, 0.0f, 0.0f, 1.0f); + glUniform4f(uniformThreeLocation, 0.0f, 0.0f, 1.0f, 1.0f); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta); + + glDeleteProgram(program); +} + +using SimpleUniformTestES3 = SimpleUniformTest; // Tests that making a copy of a struct of uniforms functions correctly. -TEST_P(SimpleUniformUsageTestES3, CopyOfUniformsWithArrays) +TEST_P(SimpleUniformTestES3, CopyOfUniformsWithArrays) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -770,7 +939,7 @@ void main() { } // Tests that making a copy of an array from a uniform functions correctly. -TEST_P(SimpleUniformUsageTestES3, CopyOfArrayInUniform) +TEST_P(SimpleUniformTestES3, CopyOfArrayInUniform) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -822,18 +991,10 @@ void main() { } // Tests that ternaries function correctly when retrieving an array element from a uniform. -TEST_P(SimpleUniformUsageTestES3, TernarySelectAnArrayElement) +TEST_P(SimpleUniformTestES3, TernarySelectAnArrayElement) { - - // TODO(anglebug.com/42267100): should eventually have a test (for WGSL) where the array is - // select by the ternary, and then the element is selected (`(unis.a > 0.5 ? unis.b : - // unis.c)[1]`). It doesn't work right now because ternaries are implemented incorrectly in the - // translator (translated as select()). constexpr char kFragShader[] = R"(#version 300 es precision mediump float; -struct NestedUniforms { - vec2 x[5]; -}; struct Uniforms { float a; float b[2]; @@ -891,11 +1052,74 @@ void main() { glDeleteProgram(program); } +// Tests that ternaries function correctly when retrieving an array a uniform and then indexing the +// result of the ternary. +TEST_P(SimpleUniformTestES3, TernarySelectAnArrayThenIndex) +{ + constexpr char kFragShader[] = R"(#version 300 es +precision mediump float; +struct Uniforms { + float a; + float b[2]; + float c[2]; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + fragColor = vec4((unis.a > 0.5 ? unis.b : unis.c)[1], + (unis.a > 0.5 ? unis.c : unis.b)[1], + 0.0, 1.0); +})"; + + GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint uniformALocation = glGetUniformLocation(program, "unis.a"); + ASSERT_NE(uniformALocation, -1); + GLint uniformBLocation = glGetUniformLocation(program, "unis.b[1]"); + ASSERT_NE(uniformBLocation, -1); + GLint uniformCLocation = glGetUniformLocation(program, "unis.c[1]"); + ASSERT_NE(uniformCLocation, -1); + + // Set to red + glUniform1f(uniformALocation, 1.0f); + glUniform1f(uniformBLocation, 1.0f); + glUniform1f(uniformCLocation, 0.0f); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Flip unis.a to set to green + glUniform1f(uniformALocation, 0.0f); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Set to red by flipping unis.b[1] and unis.c[1]. + glUniform1f(uniformBLocation, 0.0f); + glUniform1f(uniformCLocation, 1.0f); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + // Flip unis.a to set to green + glUniform1f(uniformALocation, 1.0f); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glDeleteProgram(program); +} // Tests that a struct used in the uniform address space can also be used outside of the uniform // address space. The WGSL translator changes the type signature of the struct which can cause // problems assigning to fields. -TEST_P(SimpleUniformUsageTestES3, UseUniformStructOutsideOfUniformAddressSpace) +TEST_P(SimpleUniformTestES3, UseUniformStructOutsideOfUniformAddressSpace) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -941,9 +1165,136 @@ void main() { glDeleteProgram(program); } +// Tests that bools function correctly in a uniform. WGSL does not allow booleans in the uniform +// address space. +TEST_P(SimpleUniformTestES3, Bool) +{ + constexpr char kFragShader[] = R"(#version 300 es +precision mediump float; +struct Uniforms { + bool a; + + bool[2] aArr; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + bool a = unis.a; + + fragColor = vec4(a, 0.0, 0.0, 1.0); +})"; + + GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint uniformALocation = glGetUniformLocation(program, "unis.a"); + ASSERT_NE(uniformALocation, -1); + + GLuint a = 1; + + glUniform1ui(uniformALocation, a); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + glDeleteProgram(program); +} + +// Tests that bool in an array in a uniform can be used in a shader. +TEST_P(SimpleUniformTestES3, BoolInArray) +{ + constexpr char kFragShader[] = R"(#version 300 es +precision mediump float; +struct Uniforms { + bool a; + + bool[2] aArr; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + bool[2] a = unis.aArr; + + fragColor = vec4(a[0], a[1], 0.0, 1.0); +})"; + + GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint uniformALocation = glGetUniformLocation(program, "unis.aArr"); + ASSERT_NE(uniformALocation, -1); + + GLuint aArr[] = {1, 0}; + + glUniform1uiv(uniformALocation, 2, aArr); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + GLuint aArrFlipped[] = {0, 1}; + + glUniform1uiv(uniformALocation, 2, aArrFlipped); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glDeleteProgram(program); +} + +// Tests that a uniform array containing bool can be indexed into correctly. +// The WGSL translator includes some optimizations around this case. +TEST_P(SimpleUniformTestES3, BoolInArrayWithOptimization) +{ + constexpr char kFragShader[] = R"(#version 300 es +precision mediump float; +struct Uniforms { + bool a; + + bool[2] aArr; +}; +uniform Uniforms unis; +out vec4 fragColor; +void main() { + bool a0 = unis.aArr[0]; + bool a1 = unis.aArr[1]; + + fragColor = vec4(a0, a1, 0.0, 1.0); +})"; + + GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint uniformALocation = glGetUniformLocation(program, "unis.aArr"); + ASSERT_NE(uniformALocation, -1); + + GLuint aArr[] = {1, 0}; + + glUniform1uiv(uniformALocation, 2, aArr); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); + + GLuint aArrFlipped[] = {0, 1}; + + glUniform1uiv(uniformALocation, 2, aArrFlipped); + + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + glDeleteProgram(program); +} + // Tests that matCx2 (matrix with C columns and 2 rows) functions correctly in a // uniform. WGSL's matCx2 does not match std140 layout. -TEST_P(SimpleUniformUsageTestES3, MatCx2) +TEST_P(SimpleUniformTestES3, MatCx2) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -1020,7 +1371,7 @@ void main() { } // Tests that matCx2 in an array in a uniform can be used in a shader. -TEST_P(SimpleUniformUsageTestES3, MatCx2InArray) +TEST_P(SimpleUniformTestES3, MatCx2InArray) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -1095,7 +1446,7 @@ void main() { // Tests that a uniform array containing matCx2 can be indexed into correctly. // The WGSL translator includes some optimizations around this case.. -TEST_P(SimpleUniformUsageTestES3, MatCx2InArrayWithOptimization) +TEST_P(SimpleUniformTestES3, MatCx2InArrayWithOptimization) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -1170,7 +1521,7 @@ void main() { // Tests that matCx2 can be used in a uniform at the same time an array of // matCx2s is used in a uniform. (The WGSL translator had trouble with this) -TEST_P(SimpleUniformUsageTestES3, MatCx2InArrayAndOutOfArray) +TEST_P(SimpleUniformTestES3, MatCx2InArrayAndOutOfArray) { constexpr char kFragShader[] = R"(#version 300 es precision mediump float; @@ -1276,29 +1627,33 @@ class UniformTest : public ANGLETest<> TEST_P(UniformTest, GetUniformNoCurrentProgram) { - glUseProgram(mProgram); glUniform1f(mUniformFLocation, 1.0f); glUniform1i(mUniformILocation, 1); glUseProgram(0); - GLfloat f; - glGetnUniformfvEXT(mProgram, mUniformFLocation, 4, &f); - ASSERT_GL_NO_ERROR(); - EXPECT_EQ(1.0f, f); - + GLfloat f = 0.0f; glGetUniformfv(mProgram, mUniformFLocation, &f); ASSERT_GL_NO_ERROR(); EXPECT_EQ(1.0f, f); - GLint i; - glGetnUniformivEXT(mProgram, mUniformILocation, 4, &i); - ASSERT_GL_NO_ERROR(); - EXPECT_EQ(1, i); - + GLint i = 0; glGetUniformiv(mProgram, mUniformILocation, &i); ASSERT_GL_NO_ERROR(); EXPECT_EQ(1, i); + + if (IsGLExtensionEnabled("GL_EXT_robustness")) + { + f = 0.0f; + glGetnUniformfvEXT(mProgram, mUniformFLocation, 4, &f); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(1.0f, f); + + i = 0; + glGetnUniformivEXT(mProgram, mUniformILocation, 4, &i); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(1, i); + } } TEST_P(UniformTest, UniformArrayLocations) @@ -1318,48 +1673,135 @@ void main(void) gl_FragColor = vec4(uColor[0], uColor[1], uColor[2], uColor[3]); })"; - ANGLE_GL_PROGRAM(program, kVS, kFS); + ANGLE_GL_PROGRAM(program, kVS, kFS); + + // Array index zero should be equivalent to the un-indexed uniform + EXPECT_NE(-1, glGetUniformLocation(program, "uPosition")); + EXPECT_EQ(glGetUniformLocation(program, "uPosition"), + glGetUniformLocation(program, "uPosition[0]")); + + EXPECT_NE(-1, glGetUniformLocation(program, "uColor")); + EXPECT_EQ(glGetUniformLocation(program, "uColor"), glGetUniformLocation(program, "uColor[0]")); + + // All array uniform locations should be unique + GLint positionLocations[4] = { + glGetUniformLocation(program, "uPosition[0]"), + glGetUniformLocation(program, "uPosition[1]"), + glGetUniformLocation(program, "uPosition[2]"), + glGetUniformLocation(program, "uPosition[3]"), + }; + + GLint colorLocations[4] = { + glGetUniformLocation(program, "uColor[0]"), + glGetUniformLocation(program, "uColor[1]"), + glGetUniformLocation(program, "uColor[2]"), + glGetUniformLocation(program, "uColor[3]"), + }; + + for (size_t i = 0; i < 4; i++) + { + EXPECT_NE(-1, positionLocations[i]); + EXPECT_NE(-1, colorLocations[i]); + + for (size_t j = i + 1; j < 4; j++) + { + EXPECT_NE(positionLocations[i], positionLocations[j]); + EXPECT_NE(colorLocations[i], colorLocations[j]); + } + } + + glDeleteProgram(program); +} + +// Test that float to integer GetUniform rounds values correctly for highp float uniforms +TEST_P(UniformTest, HighpFloatUniformStateQuery) +{ + + std::vector inValues; + std::vector expectedFValues; + std::vector expectedIValues; + + double intMaxD = static_cast(std::numeric_limits::max()); + double intMinD = static_cast(std::numeric_limits::min()); + + // TODO(jmadill): Investigate rounding of .5 + inValues.push_back(-1.0); + inValues.push_back(-0.6); + // inValues.push_back(-0.5); // undefined behaviour? + inValues.push_back(-0.4); + inValues.push_back(0.0); + inValues.push_back(0.4); + // inValues.push_back(0.5); // undefined behaviour? + inValues.push_back(0.6); + inValues.push_back(1.0); + inValues.push_back(999999.2); + inValues.push_back(intMaxD * 2.0); + inValues.push_back(intMaxD + 1.0); + inValues.push_back(intMinD * 2.0); + inValues.push_back(intMinD - 1.0); + + for (double value : inValues) + { + expectedFValues.push_back(static_cast(value)); + + double clampedValue = std::max(intMinD, std::min(intMaxD, value)); + double rounded = round(clampedValue); + expectedIValues.push_back(static_cast(rounded)); + } + + constexpr char kVS[] = "void main() { gl_Position = vec4(1); }"; + + constexpr char kFS[] = + "precision highp float;\n" + "uniform float uniF;\n" + "uniform int uniI;\n" + "uniform bool uniB;\n" + "uniform bool uniBArr[4];\n" + "void main() {\n" + " gl_FragColor = vec4(uniF + float(uniI));\n" + " gl_FragColor += vec4(uniB ? 1.0 : 0.0);\n" + " gl_FragColor += vec4(uniBArr[0] ? 1.0 : 0.0);\n" + " gl_FragColor += vec4(uniBArr[1] ? 1.0 : 0.0);\n" + " gl_FragColor += vec4(uniBArr[2] ? 1.0 : 0.0);\n" + " gl_FragColor += vec4(uniBArr[3] ? 1.0 : 0.0);\n" + "}"; + + mProgram = CompileProgram(kVS, kFS); + ASSERT_NE(mProgram, 0u); - // Array index zero should be equivalent to the un-indexed uniform - EXPECT_NE(-1, glGetUniformLocation(program, "uPosition")); - EXPECT_EQ(glGetUniformLocation(program, "uPosition"), - glGetUniformLocation(program, "uPosition[0]")); + glUseProgram(mProgram); + ASSERT_GL_NO_ERROR(); - EXPECT_NE(-1, glGetUniformLocation(program, "uColor")); - EXPECT_EQ(glGetUniformLocation(program, "uColor"), glGetUniformLocation(program, "uColor[0]")); + mUniformFLocation = glGetUniformLocation(mProgram, "uniF"); + ASSERT_NE(mUniformFLocation, -1); - // All array uniform locations should be unique - GLint positionLocations[4] = { - glGetUniformLocation(program, "uPosition[0]"), - glGetUniformLocation(program, "uPosition[1]"), - glGetUniformLocation(program, "uPosition[2]"), - glGetUniformLocation(program, "uPosition[3]"), - }; + for (size_t index = 0; index < inValues.size(); ++index) + { + GLfloat inValue = static_cast(inValues[index]); + GLfloat expectedValue = expectedFValues[index]; - GLint colorLocations[4] = { - glGetUniformLocation(program, "uColor[0]"), - glGetUniformLocation(program, "uColor[1]"), - glGetUniformLocation(program, "uColor[2]"), - glGetUniformLocation(program, "uColor[3]"), - }; + glUniform1f(mUniformFLocation, inValue); + GLfloat testValue; + glGetUniformfv(mProgram, mUniformFLocation, &testValue); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(expectedValue, testValue); + } - for (size_t i = 0; i < 4; i++) + for (size_t index = 0; index < inValues.size(); ++index) { - EXPECT_NE(-1, positionLocations[i]); - EXPECT_NE(-1, colorLocations[i]); + GLfloat inValue = static_cast(inValues[index]); + GLint expectedValue = expectedIValues[index]; - for (size_t j = i + 1; j < 4; j++) - { - EXPECT_NE(positionLocations[i], positionLocations[j]); - EXPECT_NE(colorLocations[i], colorLocations[j]); - } + glUniform1f(mUniformFLocation, inValue); + GLint testValue; + glGetUniformiv(mProgram, mUniformFLocation, &testValue); + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(expectedValue, testValue); } - - glDeleteProgram(program); } -// Test that float to integer GetUniform rounds values correctly. -TEST_P(UniformTest, FloatUniformStateQuery) +// Test that float to integer GetUniform rounds values correctly for mediump float uniforms +TEST_P(UniformTest, MediumpFloatUniformStateQuery) { std::vector inValues; @@ -1372,18 +1814,11 @@ TEST_P(UniformTest, FloatUniformStateQuery) // TODO(jmadill): Investigate rounding of .5 inValues.push_back(-1.0); inValues.push_back(-0.6); - // inValues.push_back(-0.5); // undefined behaviour? inValues.push_back(-0.4); inValues.push_back(0.0); inValues.push_back(0.4); - // inValues.push_back(0.5); // undefined behaviour? inValues.push_back(0.6); inValues.push_back(1.0); - inValues.push_back(999999.2); - inValues.push_back(intMaxD * 2.0); - inValues.push_back(intMaxD + 1.0); - inValues.push_back(intMinD * 2.0); - inValues.push_back(intMinD - 1.0); for (double value : inValues) { @@ -1406,7 +1841,8 @@ TEST_P(UniformTest, FloatUniformStateQuery) GLfloat testValue; glGetUniformfv(mProgram, mUniformFLocation, &testValue); ASSERT_GL_NO_ERROR(); - EXPECT_EQ(expectedValue, testValue); + EXPECT_NEAR(expectedValue, testValue, + std::abs(expectedValue) * kMediumpFloatRelativePrecisionFactor); } for (size_t index = 0; index < inValues.size(); ++index) @@ -1648,7 +2084,8 @@ TEST_P(UniformTestES3, MatrixArrayUniformStateQuery) for (size_t compIdx = 0; compIdx < kMatrixStride; compIdx++) { - EXPECT_EQ(results[compIdx], expected[i][compIdx]); + EXPECT_NEAR(results[compIdx], expected[i][compIdx], + std::abs(expected[i][compIdx]) * kMediumpFloatRelativePrecisionFactor); } } } @@ -2177,6 +2614,789 @@ TEST_P(UniformTestES31, UnusedUniformArraysConflictingLocation) EXPECT_EQ(0u, mProgram); } +// Test that having a combination of different float type uniforms with different precisions work +// properly with uniform sort +TEST_P(UniformTestES31, PackUniformFP16Test) +{ + setWindowWidth(1); + setWindowHeight(1); + constexpr char kFragShader[] = R"(#version 310 es +layout(std140, binding=0) buffer debugBlock { + uvec4 data[]; +}; +precision mediump float; +struct Structs{ + float floatInStructs; +}; +uniform float floatUniform; +uniform highp float highpFloatUniform; +uniform mat4 mat4Uniform; +uniform highp mat4 highpMat4Uniform; +uniform vec4 vec4Uniform; +uniform highp vec4 highpVec4Uniform; +uniform mat3x2 mat32Uniform; +uniform highp mat3x2 highpMat32Uniform; +uniform mat2x3 mat23Uniform; +uniform highp mat2x3 highpMat23Uniform; +uniform Structs structUniform; + +out vec4 fragColor; + +void main() { + data[0] = floatBitsToUint(vec4(floatUniform, highpFloatUniform, structUniform.floatInStructs, 1.0)); + + vec4 verifyMat4Uniform = vec4(1.0, 1.0, 1.0, 1.0) * mat4Uniform; + data[1] = floatBitsToUint(verifyMat4Uniform); + + highp vec4 verifyHighpMat4Uniform = vec4(1.0, 1.0, 1.0, 1.0) * highpMat4Uniform; + data[2] = floatBitsToUint(verifyHighpMat4Uniform); + + data[3] = floatBitsToUint(vec4Uniform); + + data[4] = floatBitsToUint(highpVec4Uniform); + + vec3 verifyMat3x2Uniform = vec2(1.0, 1.0) * mat32Uniform; + data[5] = floatBitsToUint(vec4(verifyMat3x2Uniform, 1.0)); + + highp vec3 verifyMat3x2HighpUniform = vec2(1.0, 1.0) * highpMat32Uniform; + data[6] = floatBitsToUint(vec4(verifyMat3x2HighpUniform, 1.0)); + + vec2 verifyMat2x3Uniform = vec3(1.0, 1.0, 1.0) * mat23Uniform; + highp vec2 verifyMat2x3HighpUniform = vec3(1.0, 1.0, 1.0) * highpMat23Uniform; + data[7] = floatBitsToUint(vec4(verifyMat2x3Uniform, verifyMat2x3HighpUniform)); + + fragColor = vec4(1.0, 0.0, 0.0, 1.0); +})"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint floatUniformLocation = glGetUniformLocation(program, "floatUniform"); + ASSERT_NE(floatUniformLocation, -1); + GLint highpFloatUniformLocation = glGetUniformLocation(program, "highpFloatUniform"); + ASSERT_NE(highpFloatUniformLocation, -1); + GLint mat4UniformLocation = glGetUniformLocation(program, "mat4Uniform"); + ASSERT_NE(mat4UniformLocation, -1); + GLint highpMat4UniformLocation = glGetUniformLocation(program, "highpMat4Uniform"); + ASSERT_NE(highpMat4UniformLocation, -1); + GLint vec4UniformLocation = glGetUniformLocation(program, "vec4Uniform"); + ASSERT_NE(vec4UniformLocation, -1); + GLint highpVec4UniformLocation = glGetUniformLocation(program, "highpVec4Uniform"); + ASSERT_NE(highpVec4UniformLocation, -1); + GLint mat32UniformLocation = glGetUniformLocation(program, "mat32Uniform"); + ASSERT_NE(mat32UniformLocation, -1); + GLint highpMat32UniformLocation = glGetUniformLocation(program, "highpMat32Uniform"); + ASSERT_NE(highpMat32UniformLocation, -1); + GLint mat23UniformLocation = glGetUniformLocation(program, "mat23Uniform"); + ASSERT_NE(mat23UniformLocation, -1); + GLint highpMat23UniformLocation = glGetUniformLocation(program, "highpMat23Uniform"); + ASSERT_NE(highpMat23UniformLocation, -1); + GLint structUniformLocation = glGetUniformLocation(program, "structUniform.floatInStructs"); + ASSERT_NE(structUniformLocation, -1); + + GLfloat floatUniformValue = 1.0; + GLfloat highpFloatUniformValue = 131072.0; + GLfloat mat4UniformValue[16] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0}; + GLfloat highpMat4UniformValue[16] = {131072.0, 131073.0, 131074.0, 131075.0, 131076.0, 131077.0, + 131078.0, 131079.0, 131080.0, 131081.0, 131082.0, 131083.0, + 131084.0, 131085.0, 131086.0, 131087.0}; + GLfloat vec4UniformValue[4] = {17.0, 18.0, 19.0, 20.0}; + GLfloat highpVec4UniformValue[4] = {131088.0, 131089.0, 131090.0, 131091.0}; + GLfloat mat32UniformValue[6] = {21.0, 22.0, 23.0, 24.0, 25.0, 26.0}; + GLfloat highpMat32UniformValue[6] = {131092.0, 131093.0, 131094.0, + 131095.0, 131096.0, 131097.0}; + GLfloat mat23UniformValue[6] = {27.0, 28.0, 29.0, 30.0, 31.0, 32.0}; + GLfloat highpMat23UniformValue[6] = {131098.0, 131099.0, 131100.0, + 131101.0, 131102.0, 131103.0}; + GLfloat structUniformValue = 33.0; + glUniform1f(floatUniformLocation, floatUniformValue); + glUniform1f(highpFloatUniformLocation, highpFloatUniformValue); + glUniformMatrix4fv(mat4UniformLocation, 1, GL_FALSE, mat4UniformValue); + glUniformMatrix4fv(highpMat4UniformLocation, 1, GL_FALSE, highpMat4UniformValue); + glUniform4fv(vec4UniformLocation, 1, vec4UniformValue); + glUniform4fv(highpVec4UniformLocation, 1, highpVec4UniformValue); + glUniformMatrix3x2fv(mat32UniformLocation, 1, GL_FALSE, mat32UniformValue); + glUniformMatrix3x2fv(highpMat32UniformLocation, 1, GL_FALSE, highpMat32UniformValue); + glUniformMatrix2x3fv(mat23UniformLocation, 1, GL_FALSE, mat23UniformValue); + glUniformMatrix2x3fv(highpMat23UniformLocation, 1, GL_FALSE, highpMat23UniformValue); + glUniform1f(structUniformLocation, structUniformValue); + constexpr GLint kBufferSize = 8 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + float *data = static_cast(ptr); + ASSERT_EQ(data[0], 1); + ASSERT_EQ(data[1], 131072); + ASSERT_EQ(data[2], 33); + ASSERT_EQ(data[3], 1); + ASSERT_EQ(data[4], 10); + ASSERT_EQ(data[5], 26); + ASSERT_EQ(data[6], 42); + ASSERT_EQ(data[7], 58); + ASSERT_EQ(data[8], 524294); + ASSERT_EQ(data[9], 524310); + ASSERT_EQ(data[10], 524326); + ASSERT_EQ(data[11], 524342); + ASSERT_EQ(data[12], 17); + ASSERT_EQ(data[13], 18); + ASSERT_EQ(data[14], 19); + ASSERT_EQ(data[15], 20); + ASSERT_EQ(data[16], 131088); + ASSERT_EQ(data[17], 131089); + ASSERT_EQ(data[18], 131090); + ASSERT_EQ(data[19], 131091); + ASSERT_EQ(data[20], 43); + ASSERT_EQ(data[21], 47); + ASSERT_EQ(data[22], 51); + ASSERT_EQ(data[23], 1); + ASSERT_EQ(data[24], 262185); + ASSERT_EQ(data[25], 262189); + ASSERT_EQ(data[26], 262193); + ASSERT_EQ(data[27], 1); + ASSERT_EQ(data[28], 84); + ASSERT_EQ(data[29], 93); + ASSERT_EQ(data[30], 393297); + ASSERT_EQ(data[31], 393306); + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glDeleteProgram(program); +} + +// Test that nested struct uniform with mediump float works properly with the float being +// transformed from 32-bit to 16-bit. Also check that highp float member and non-float members +// are unaffected. +TEST_P(UniformTestES31, PackUniformFP16TestNestedStruct) +{ + setWindowWidth(1); + setWindowHeight(1); + constexpr char kFragShader[] = R"(#version 310 es +layout(std140, binding=0) buffer debugBlock { + uvec4 data[]; +}; + precision mediump float; + struct InnerStruct { + highp float highpFloatInStructs; + float mediumpFloatInStructs; + uint integerInStructs; + }; + + struct OuterStruct { + InnerStruct structMember; + }; + uniform OuterStruct structUniform; + + + out vec4 fragColor; + + void main() { + data[0] = floatBitsToUint(vec4(structUniform.structMember.mediumpFloatInStructs, structUniform.structMember.highpFloatInStructs, 0.0, 1.0)); + data[0].z = structUniform.structMember.integerInStructs; + + fragColor = vec4(1.0, 0.0, 0.0, 1.0); +})"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + GLint mediumpFloatInStructsUniformLocation = + glGetUniformLocation(program, "structUniform.structMember.mediumpFloatInStructs"); + ASSERT_NE(mediumpFloatInStructsUniformLocation, -1); + GLint highpFloatInStructsUniformLocation = + glGetUniformLocation(program, "structUniform.structMember.highpFloatInStructs"); + ASSERT_NE(highpFloatInStructsUniformLocation, -1); + GLint integerInStructsUniformLocation = + glGetUniformLocation(program, "structUniform.structMember.integerInStructs"); + ASSERT_NE(integerInStructsUniformLocation, -1); + GLfloat mediumpFloatInStructUniformValue = 1.0; + glUniform1f(mediumpFloatInStructsUniformLocation, mediumpFloatInStructUniformValue); + GLfloat highpFloatInStructUniformValue = 131072.0; + glUniform1f(highpFloatInStructsUniformLocation, highpFloatInStructUniformValue); + GLuint integerInStructUniformValue = 10; + glUniform1ui(integerInStructsUniformLocation, integerInStructUniformValue); + constexpr GLint kBufferSize = 1 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + unsigned int *data = static_cast(ptr); + ASSERT_EQ(*reinterpret_cast(&data[0]), 1.0); + ASSERT_EQ(*reinterpret_cast(&data[1]), 131072.0); + ASSERT_EQ(data[2], 10u); + ASSERT_EQ(*reinterpret_cast(&data[3]), 1.0); + ASSERT_GL_NO_ERROR(); + + glDeleteProgram(program); +} + +// Test that TCompiler::sortUniforms() does not break the shader code when there are multiple +// uniforms of the same struct data type, and one of them is the struct specifier. +TEST_P(UniformTestES31, UniformReorderDoesNotBreakStructUniforms) +{ + constexpr char kFS[] = + "#version 310 es\n" + "precision mediump float;\n" + "out highp vec4 my_FragColor;\n" + "uniform struct{vec3 b;}G[1],S;\n" + "void main()\n" + "{}"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFS); + ASSERT_NE(program, 0u); +} + +// That that TCompiler::sortUniforms() does not break the shader code when there are multiple +// uniforms of the struct data type, and both of them are struct specifiers, and one struct +// references the other struct. +TEST_P(UniformTestES31, UniformReorderDoesNotBreakStructUniformsV2) +{ + constexpr char kFS[] = + "#version 310 es\n" + "precision mediump float;\n" + "uniform struct S1 { samplerCube ar; } a1;\n" + "uniform struct S2 { S1 s; } a2;\n" + "void main (void)\n" + "{}"; + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFS); + ASSERT_NE(program, 0u); +} + +// Test that with the PackedSPIRVBlockEncoder applies to "defaultUniform" ubo interface block, +// it does not incorrectly interfere with other structs that are also named "defaultUniforms" +TEST_P(UniformTestES31, PackedEncoderDoesNotApplyToStructNamedDefaultUniforms) +{ + setWindowWidth(1); + setWindowHeight(1); + constexpr char kFragShader[] = R"(#version 310 es + layout(std140, binding=0) buffer debugBlock { + uvec4 data[]; + }; + + precision mediump float; + uniform vec3 vec3Uniform1; + uniform vec3 vec3Uniform2; + struct defaultUniforms { + vec3 vec3Uniform1; + vec3 vec3Uniform2; + }; + + out highp vec4 my_color; + void main() { + defaultUniforms nonDefaultUniform = defaultUniforms(vec3(1.0, 2.0, 3.0), vec3(4.0, 5.0, 6.0)); + data[0] = floatBitsToUint(vec4(nonDefaultUniform.vec3Uniform1.x, nonDefaultUniform.vec3Uniform1.y, nonDefaultUniform.vec3Uniform1.z, 1.0)); + data[1] = floatBitsToUint(vec4(nonDefaultUniform.vec3Uniform2.x, nonDefaultUniform.vec3Uniform2.y, nonDefaultUniform.vec3Uniform2.z, 1.0)); + data[2] = floatBitsToUint(vec4(vec3Uniform1.x, vec3Uniform1.y, vec3Uniform1.z, 1.0)); + data[3] = floatBitsToUint(vec4(vec3Uniform2.x, vec3Uniform2.y, vec3Uniform2.z, 1.0)); + my_color = vec4(1.0, 0.0, 0.0, 1.0); + })"; + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint vec3Uniform1Location = glGetUniformLocation(program, "vec3Uniform1"); + ASSERT_NE(vec3Uniform1Location, -1); + GLfloat vec3Uniform1Value[3] = {11.0f, 12.0f, 13.0f}; + glUniform3fv(vec3Uniform1Location, 1, vec3Uniform1Value); + + GLint vec3Uniform2Location = glGetUniformLocation(program, "vec3Uniform2"); + ASSERT_NE(vec3Uniform2Location, -1); + GLfloat vec3Uniform2Value[3] = {14.0f, 15.0f, 16.0f}; + glUniform3fv(vec3Uniform2Location, 1, vec3Uniform2Value); + + constexpr GLint kBufferSize = 4 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + + ASSERT_GL_NO_ERROR(); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + float *data = static_cast(ptr); + + ASSERT_EQ(data[0], 1); + ASSERT_EQ(data[1], 2); + ASSERT_EQ(data[2], 3); + ASSERT_EQ(data[3], 1); + ASSERT_EQ(data[4], 4); + ASSERT_EQ(data[5], 5); + ASSERT_EQ(data[6], 6); + ASSERT_EQ(data[7], 1); + ASSERT_EQ(data[8], 11); + ASSERT_EQ(data[9], 12); + ASSERT_EQ(data[10], 13); + ASSERT_EQ(data[11], 1); + ASSERT_EQ(data[12], 14); + ASSERT_EQ(data[13], 15); + ASSERT_EQ(data[14], 16); + ASSERT_EQ(data[15], 1); + + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glDeleteProgram(program); +} + +// Test that with the PackedSPIRVBlockEncoder applies to "defaultUniform" ubo interface block, +// it does not incorrectly interfere with other ubo created that are also named "defaultUniforms" +TEST_P(UniformTestES31, PackedEncoderDoesNotApplyToCustomizedUBONamedDefaultUniforms) +{ + setWindowWidth(1); + setWindowHeight(1); + + constexpr char kFragShader[] = R"(#version 310 es + layout(std140, binding=0) buffer debugBlock { + uvec4 data[]; + }; + + precision mediump float; + uniform vec3 vec3Uniform1; + uniform vec3 vec3Uniform2; + layout(std140) uniform defaultUniforms { + vec3 vec3Uniform1; + vec3 vec3Uniform2; + } defaultUniformsBufferInstance; + + out highp vec4 my_color; + void main() { + data[0] = floatBitsToUint(vec4(defaultUniformsBufferInstance.vec3Uniform1.x, defaultUniformsBufferInstance.vec3Uniform1.y, defaultUniformsBufferInstance.vec3Uniform1.z, 1.0)); + data[1] = floatBitsToUint(vec4(defaultUniformsBufferInstance.vec3Uniform2.x, defaultUniformsBufferInstance.vec3Uniform2.y, defaultUniformsBufferInstance.vec3Uniform2.z, 1.0)); + data[2] = floatBitsToUint(vec4(vec3Uniform1.x, vec3Uniform1.y, vec3Uniform1.z, 1.0)); + data[3] = floatBitsToUint(vec4(vec3Uniform2.x, vec3Uniform2.y, vec3Uniform2.z, 1.0)); + my_color = vec4(1.0, 0.0, 0.0, 1.0); + })"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint vec3Uniform1Location = glGetUniformLocation(program, "vec3Uniform1"); + ASSERT_NE(vec3Uniform1Location, -1); + GLfloat vec3Uniform1Value[3] = {11.0f, 12.0f, 13.0f}; + glUniform3fv(vec3Uniform1Location, 1, vec3Uniform1Value); + + GLint vec3Uniform2Location = glGetUniformLocation(program, "vec3Uniform2"); + ASSERT_NE(vec3Uniform2Location, -1); + GLfloat vec3Uniform2Value[3] = {14.0f, 15.0f, 16.0f}; + glUniform3fv(vec3Uniform2Location, 1, vec3Uniform2Value); + + std::vector uboData; + uboData.insert(uboData.end(), {1.0f, 2.0f, 3.0f, 0.0f}); + uboData.insert(uboData.end(), {4.0f, 5.0f, 6.0f, 0.0f}); + GLBuffer ubo; + glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo); + glBufferData(GL_UNIFORM_BUFFER, uboData.size() * sizeof(float), uboData.data(), GL_STATIC_DRAW); + ASSERT_GL_NO_ERROR(); + + GLuint uboIndex = glGetUniformBlockIndex(program, "defaultUniforms"); + EXPECT_NE(GL_INVALID_INDEX, uboIndex); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, uboData.size() * sizeof(float)); + glUniformBlockBinding(program, uboIndex, 0); + + constexpr GLint kBufferSize = 4 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + + ASSERT_GL_NO_ERROR(); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + float *data = static_cast(ptr); + + ASSERT_EQ(data[0], 1); + ASSERT_EQ(data[1], 2); + ASSERT_EQ(data[2], 3); + ASSERT_EQ(data[3], 1); + ASSERT_EQ(data[4], 4); + ASSERT_EQ(data[5], 5); + ASSERT_EQ(data[6], 6); + ASSERT_EQ(data[7], 1); + ASSERT_EQ(data[8], 11); + ASSERT_EQ(data[9], 12); + ASSERT_EQ(data[10], 13); + ASSERT_EQ(data[11], 1); + ASSERT_EQ(data[12], 14); + ASSERT_EQ(data[13], 15); + ASSERT_EQ(data[14], 16); + ASSERT_EQ(data[15], 1); + + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glDeleteProgram(program); +} + +// Same as PackedEncoderDoesNotApplyToCustomizedUBONamedDefaultUniforms, except the SSBO +// data type is changed from uvec4 to vec4 to add more coverage +TEST_P(UniformTestES31, PackedEncoderDoesNotApplyToCustomizedUBONamedDefaultUniformsV2) +{ + setWindowWidth(1); + setWindowHeight(1); + + constexpr char kFragShader[] = R"(#version 310 es + precision mediump float; + layout(std140, binding=0) buffer debugBlock { + vec4 data[]; + }; + uniform vec3 vec3Uniform1; + uniform vec3 vec3Uniform2; + layout(std140) uniform defaultUniforms { + vec3 vec3Uniform1; + vec3 vec3Uniform2; + } defaultUniformsBufferInstance; + + out highp vec4 my_color; + void main() { + data[0] = vec4(defaultUniformsBufferInstance.vec3Uniform1.x, defaultUniformsBufferInstance.vec3Uniform1.y, defaultUniformsBufferInstance.vec3Uniform1.z, 1.0); + data[1] = vec4(defaultUniformsBufferInstance.vec3Uniform2.x, defaultUniformsBufferInstance.vec3Uniform2.y, defaultUniformsBufferInstance.vec3Uniform2.z, 1.0); + data[2] = vec4(vec3Uniform1.x, vec3Uniform1.y, vec3Uniform1.z, 1.0); + data[3] = vec4(vec3Uniform2.x, vec3Uniform2.y, vec3Uniform2.z, 1.0); + my_color = vec4(1.0, 0.0, 0.0, 1.0); + })"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLint vec3Uniform1Location = glGetUniformLocation(program, "vec3Uniform1"); + ASSERT_NE(vec3Uniform1Location, -1); + GLfloat vec3Uniform1Value[3] = {11.0f, 12.0f, 13.0f}; + glUniform3fv(vec3Uniform1Location, 1, vec3Uniform1Value); + + GLint vec3Uniform2Location = glGetUniformLocation(program, "vec3Uniform2"); + ASSERT_NE(vec3Uniform2Location, -1); + GLfloat vec3Uniform2Value[3] = {14.0f, 15.0f, 16.0f}; + glUniform3fv(vec3Uniform2Location, 1, vec3Uniform2Value); + + std::vector uboData; + uboData.insert(uboData.end(), {1.0f, 2.0f, 3.0f, 0.0f}); + uboData.insert(uboData.end(), {4.0f, 5.0f, 6.0f, 0.0f}); + GLBuffer ubo; + glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo); + glBufferData(GL_UNIFORM_BUFFER, uboData.size() * sizeof(float), uboData.data(), GL_STATIC_DRAW); + ASSERT_GL_NO_ERROR(); + + GLuint uboIndex = glGetUniformBlockIndex(program, "defaultUniforms"); + EXPECT_NE(GL_INVALID_INDEX, uboIndex); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, uboData.size() * sizeof(float)); + glUniformBlockBinding(program, uboIndex, 0); + + constexpr GLint kBufferSize = 4 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + + ASSERT_GL_NO_ERROR(); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + float *data = static_cast(ptr); + + ASSERT_EQ(data[0], 1); + ASSERT_EQ(data[1], 2); + ASSERT_EQ(data[2], 3); + ASSERT_EQ(data[3], 1); + ASSERT_EQ(data[4], 4); + ASSERT_EQ(data[5], 5); + ASSERT_EQ(data[6], 6); + ASSERT_EQ(data[7], 1); + ASSERT_EQ(data[8], 11); + ASSERT_EQ(data[9], 12); + ASSERT_EQ(data[10], 13); + ASSERT_EQ(data[11], 1); + ASSERT_EQ(data[12], 14); + ASSERT_EQ(data[13], 15); + ASSERT_EQ(data[14], 16); + ASSERT_EQ(data[15], 1); + + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glDeleteProgram(program); +} + +// Test PackedSPIRVBlockEncoder works properly for array of struct default uniforms +TEST_P(UniformTestES31, PackedEncoderWorksForArrayOfStructs) +{ + setWindowWidth(1); + setWindowHeight(1); + + constexpr char kFragShader[] = R"(#version 310 es + precision mediump float; + layout(std140, binding=0) buffer debugBlock { + vec4 data[]; + }; + + struct UniformStruct { + float floatMember; + vec2 vec2Member; + vec3 vec3Member; + vec4 vec4Member; + }; + + uniform UniformStruct uniformStructArray[3]; + + out highp vec4 my_color; + void main() { + for (int i = 0; i < 3; ++i) { + int offset = i * 3; + data[offset + 0] = vec4(uniformStructArray[i].floatMember, uniformStructArray[i].vec2Member, 0.0); + data[offset + 1] = vec4(uniformStructArray[i].vec3Member, 0.0); + data[offset + 2] = uniformStructArray[i].vec4Member; + } + my_color = vec4(1.0, 0.0, 0.0, 1.0); + })"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLfloat expectedData[36] = { + 0.0f, 1.0f, 2.0f, 0.0f, 3.0f, 4.0f, 5.0f, 0.0f, 6.0f, 7.0f, 8.0f, 9.0f, + + 10.0f, 11.0f, 12.0f, 0.0f, 13.0f, 14.0f, 15.0f, 0.0f, 16.0f, 17.0f, 18.0f, 19.0f, + + 20.0f, 21.0f, 22.0f, 0.0f, 23.0f, 24.0f, 25.0f, 0.0f, 26.0f, 27.0f, 28.0f, 29.0f, + }; + + for (int i = 0; i < 3; ++i) + { + std::string base = "uniformStructArray[" + std::to_string(i) + "]."; + int indexOffset = i * 12; + + GLfloat floatVal = expectedData[indexOffset]; + GLint floatMemberLocation = glGetUniformLocation(program, (base + "floatMember").c_str()); + ASSERT_NE(floatMemberLocation, -1); + glUniform1f(floatMemberLocation, floatVal); + + GLfloat vec2Val[2] = {expectedData[indexOffset + 1], expectedData[indexOffset + 2]}; + GLint vec2MemberLocation = glGetUniformLocation(program, (base + "vec2Member").c_str()); + ASSERT_NE(vec2MemberLocation, -1); + glUniform2fv(vec2MemberLocation, 1, vec2Val); + + GLfloat vec3Val[3] = {expectedData[indexOffset + 4], expectedData[indexOffset + 5], + expectedData[indexOffset + 6]}; + GLint vec3MemberLocation = glGetUniformLocation(program, (base + "vec3Member").c_str()); + ASSERT_NE(vec3MemberLocation, -1); + glUniform3fv(vec3MemberLocation, 1, vec3Val); + + GLfloat vec4Val[4] = {expectedData[indexOffset + 8], expectedData[indexOffset + 9], + expectedData[indexOffset + 10], expectedData[indexOffset + 11]}; + GLint vec4MemberLocation = glGetUniformLocation(program, (base + "vec4Member").c_str()); + glUniform4fv(vec4MemberLocation, 1, vec4Val); + } + + constexpr GLint kBufferSize = 9 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + + ASSERT_GL_NO_ERROR(); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + float *data = static_cast(ptr); + + for (int i = 0; i < 36; ++i) + { + ASSERT_EQ(data[i], expectedData[i]); + } + + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glDeleteProgram(program); +} + +// Test PackedSPIRVBlockEncoder works properly for array of nested struct default uniforms +TEST_P(UniformTestES31, PackedEncoderWorksForArrayOfNestedStructs) +{ + setWindowWidth(1); + setWindowHeight(1); + + constexpr char kFragShader[] = R"(#version 310 es + precision mediump float; + layout(std140, binding=0) buffer debugBlock { + vec4 data[]; + }; + + struct InnerStruct { + float innerFloatMember; + vec2 innerVec2Member; + vec3 innerVec3Member; + vec4 innerVec4Member; + }; + + struct OuterStruct { + InnerStruct innerStructMember; + float outerFloatMember; + vec2 outerVec2Member; + vec3 outerVec3Member; + vec4 outerVec4Member; + }; + + uniform OuterStruct uniformNestedStructArray[3]; + + out highp vec4 my_color; + void main() { + for (int i = 0; i < 3; ++i) { + int offset = i * 6; + data[offset + 0] = vec4(uniformNestedStructArray[i].innerStructMember.innerFloatMember, uniformNestedStructArray[i].innerStructMember.innerVec2Member, 0.0); + data[offset + 1] = vec4(uniformNestedStructArray[i].innerStructMember.innerVec3Member, 0.0); + data[offset + 2] = uniformNestedStructArray[i].innerStructMember.innerVec4Member; + data[offset + 3] = vec4(uniformNestedStructArray[i].outerFloatMember, uniformNestedStructArray[i].outerVec2Member, 0.0); + data[offset + 4] = vec4(uniformNestedStructArray[i].outerVec3Member, 0.0); + data[offset + 5] = uniformNestedStructArray[i].outerVec4Member; + } + my_color = vec4(1.0, 0.0, 0.0, 1.0); + })"; + + GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFragShader); + ASSERT_NE(program, 0u); + glUseProgram(program); + + GLfloat expectedData[72] = { + 0.0f, 1.0f, 2.0f, 0.0f, 3.0f, 4.0f, 5.0f, 0.0f, 6.0f, 7.0f, 8.0f, 9.0f, + + 10.0f, 11.0f, 12.0f, 0.0f, 13.0f, 14.0f, 15.0f, 0.0f, 16.0f, 17.0f, 18.0f, 19.0f, + + 20.0f, 21.0f, 22.0f, 0.0f, 23.0f, 24.0f, 25.0f, 0.0f, 26.0f, 27.0f, 28.0f, 29.0f, + + 30.0f, 31.0f, 32.0f, 0.0f, 33.0f, 34.0f, 35.0f, 0.0f, 36.0f, 37.0f, 38.0f, 39.0f, + + 40.0f, 41.0f, 42.0f, 0.0f, 43.0f, 44.0f, 45.0f, 0.0f, 46.0f, 47.0f, 48.0f, 49.0f, + + 50.0f, 51.0f, 52.0f, 0.0f, 53.0f, 54.0f, 55.0f, 0.0f, 56.0f, 57.0f, 58.0f, 59.0f, + }; + + for (int i = 0; i < 3; ++i) + { + std::string base = "uniformNestedStructArray[" + std::to_string(i) + "]."; + int indexOffset = i * 24; + + GLfloat innerStructFloatVal = expectedData[indexOffset]; + GLint innerStructFloatLocation = + glGetUniformLocation(program, (base + "innerStructMember.innerFloatMember").c_str()); + ASSERT_NE(innerStructFloatLocation, -1); + glUniform1f(innerStructFloatLocation, innerStructFloatVal); + + GLfloat innerStructVec2Val[2] = {expectedData[indexOffset + 1], + expectedData[indexOffset + 2]}; + GLint innerStructVec2Location = + glGetUniformLocation(program, (base + "innerStructMember.innerVec2Member").c_str()); + ASSERT_NE(innerStructVec2Location, -1); + glUniform2fv(innerStructVec2Location, 1, innerStructVec2Val); + + GLfloat innerStructVec3Val[3] = {expectedData[indexOffset + 4], + expectedData[indexOffset + 5], + expectedData[indexOffset + 6]}; + GLint innerStructVec3Location = + glGetUniformLocation(program, (base + "innerStructMember.innerVec3Member").c_str()); + ASSERT_NE(innerStructVec3Location, -1); + glUniform3fv(innerStructVec3Location, 1, innerStructVec3Val); + + GLfloat innerStructVec4Val[4] = { + expectedData[indexOffset + 8], expectedData[indexOffset + 9], + expectedData[indexOffset + 10], expectedData[indexOffset + 11]}; + GLint innerStructVec4Location = + glGetUniformLocation(program, (base + "innerStructMember.innerVec4Member").c_str()); + ASSERT_NE(innerStructVec4Location, -1); + glUniform4fv(innerStructVec4Location, 1, innerStructVec4Val); + + GLfloat floatVal = expectedData[indexOffset + 12]; + GLint floatMemberLocation = + glGetUniformLocation(program, (base + "outerFloatMember").c_str()); + ASSERT_NE(floatMemberLocation, -1); + glUniform1f(floatMemberLocation, floatVal); + + GLfloat vec2Val[2] = {expectedData[indexOffset + 13], expectedData[indexOffset + 14]}; + GLint vec2MemberLocation = + glGetUniformLocation(program, (base + "outerVec2Member").c_str()); + ASSERT_NE(vec2MemberLocation, -1); + glUniform2fv(vec2MemberLocation, 1, vec2Val); + + GLfloat vec3Val[3] = {expectedData[indexOffset + 16], expectedData[indexOffset + 17], + expectedData[indexOffset + 18]}; + GLint vec3MemberLocation = + glGetUniformLocation(program, (base + "outerVec3Member").c_str()); + ASSERT_NE(vec3MemberLocation, -1); + glUniform3fv(vec3MemberLocation, 1, vec3Val); + + GLfloat vec4Val[4] = {expectedData[indexOffset + 20], expectedData[indexOffset + 21], + expectedData[indexOffset + 22], expectedData[indexOffset + 23]}; + GLint vec4MemberLocation = + glGetUniformLocation(program, (base + "outerVec4Member").c_str()); + glUniform4fv(vec4MemberLocation, 1, vec4Val); + } + + constexpr GLint kBufferSize = 9 * 4 * sizeof(GLuint); + GLBuffer buffer; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f); + + ASSERT_GL_NO_ERROR(); + + void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT); + ASSERT_GL_NO_ERROR(); + ASSERT(ptr); + float *data = static_cast(ptr); + + for (int i = 0; i < 36; ++i) + { + ASSERT_EQ(data[i], expectedData[i]); + } + + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glDeleteProgram(program); +} + // Test a uniform struct containing a non-square matrix and a boolean. // Minimal test case for a bug revealed by dEQP tests. TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool) @@ -2445,8 +3665,8 @@ void main() EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Regression test for D3D11 packing of 3x3 matrices followed by a single float. The setting of the -// matrix would overwrite the float which is packed right after. http://anglebug.com/42266878, +// Regression test for D3D11 packing of 3x3 matrices followed by three floats. The setting of the +// matrix would overwrite the floats which is packed right after. http://anglebug.com/42266878, // http://crbug.com/345525082 TEST_P(UniformTestES3, ExpandedFloatMatrix3Packing) { @@ -2461,11 +3681,13 @@ void main() struct s { mat3 umat3; - float ufloat; + float ufloat1; + float ufloat2; + float ufloat3; }; uniform s u; void main() { - gl_FragColor = vec4(u.umat3[0][0], u.ufloat, 1.0, 1.0); + gl_FragColor = vec4(u.umat3[0][0], u.ufloat1, u.ufloat2, u.ufloat3); })"; ANGLE_GL_PROGRAM(program, vs, fs); @@ -2474,30 +3696,38 @@ void main() { GLint umat3Location = glGetUniformLocation(program, "u.umat3"); ASSERT_NE(umat3Location, -1); - GLint ufloatLocation = glGetUniformLocation(program, "u.ufloat"); - ASSERT_NE(ufloatLocation, -1); + GLint ufloat1Location = glGetUniformLocation(program, "u.ufloat1"); + ASSERT_NE(ufloat1Location, -1); + + GLint ufloat2Location = glGetUniformLocation(program, "u.ufloat2"); + ASSERT_NE(ufloat2Location, -1); + + GLint ufloat3Location = glGetUniformLocation(program, "u.ufloat3"); + ASSERT_NE(ufloat3Location, -1); constexpr GLfloat mat3[9] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }; - glUniform1f(ufloatLocation, 1.0f); + glUniform1f(ufloat1Location, 1.0f); + glUniform1f(ufloat2Location, 1.0f); + glUniform1f(ufloat3Location, 1.0f); glUniformMatrix3fv(umat3Location, 1, GL_FALSE, mat3); drawQuad(program, "position", 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 255, 255)); } // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SimpleUniformTest); -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(SimpleUniformUsageTest, ES2_WEBGPU()); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(UniformTest); -ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(BasicUniformUsageTest, ES2_WEBGPU()); +ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(BasicUniformUsageTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformTestES3); ANGLE_INSTANTIATE_TEST_ES3(UniformTestES3); -ANGLE_INSTANTIATE_TEST_ES3_AND(SimpleUniformUsageTestES3, ES3_WEBGPU()); +ANGLE_INSTANTIATE_TEST_ES3(SimpleUniformTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformTestES31); ANGLE_INSTANTIATE_TEST_ES31(UniformTestES31); diff --git a/src/tests/gl_tests/UnpackAlignmentTest.cpp b/src/tests/gl_tests/UnpackAlignmentTest.cpp index 13ecdefca53..5d615ac98b3 100644 --- a/src/tests/gl_tests/UnpackAlignmentTest.cpp +++ b/src/tests/gl_tests/UnpackAlignmentTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" using namespace angle; diff --git a/src/tests/gl_tests/VertexAttributeTest.cpp b/src/tests/gl_tests/VertexAttributeTest.cpp index fe83ec694b5..21fc8054473 100644 --- a/src/tests/gl_tests/VertexAttributeTest.cpp +++ b/src/tests/gl_tests/VertexAttributeTest.cpp @@ -3,6 +3,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "anglebase/numerics/safe_conversions.h" #include "common/mathutil.h" #include "test_utils/ANGLETest.h" @@ -350,7 +355,7 @@ class VertexAttributeTest : public ANGLETest<> "void main(void)\n" "{\n" " gl_Position = position;\n" - " vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n" + " vec4 threshold = max(abs(expected) * 0.01, vec4(1.0 / 64.0));\n" " color = vec4(lessThanEqual(abs(test - expected), threshold));\n" "}\n"; @@ -1838,7 +1843,7 @@ TEST_P(VertexAttributeTest, DrawArraysWithDisabledAttribute) "void main(void)\n" "{\n" " gl_Position = position;\n" - " vec4 threshold = max(abs(expected + disabled) * 0.005, 1.0 / 64.0);\n" + " vec4 threshold = max(abs(expected + disabled) * 0.005, vec4(1.0 / 64.0));\n" " color = vec4(lessThanEqual(abs(test - expected), threshold));\n" "}\n"; @@ -2569,7 +2574,7 @@ void main() { reinterpret_cast(0)); glBindBuffer(GL_ARRAY_BUFFER, 0); - glEnableVertexAttribArray(1); + glEnableVertexAttribArray(colorLocation); drawQuad(program, "a_position", 0.5f); @@ -2578,6 +2583,58 @@ void main() { ASSERT_GL_NO_ERROR(); } +// Validate that we can support GL_MAX_ATTRIBS attribs with built-in attribs +TEST_P(VertexAttributeTestES3, MaxAttribsWithBuiltInAttribs) +{ + GLint maxAttribs; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs); + ASSERT_GL_NO_ERROR(); + + std::stringstream shaderStream; + shaderStream << "#version 300 es" << std::endl << "precision highp float;" << std::endl; + for (GLint attribIndex = 1; attribIndex < maxAttribs; ++attribIndex) + { + shaderStream << "in float a" << attribIndex << ";" << std::endl; + } + shaderStream << "in vec4 position;" << std::endl; + shaderStream << "out float color;" << std::endl + << "void main() {" << std::endl + << " gl_Position = position;" << std::endl + << " color = 0.0;" << std::endl; + for (GLint attribIndex = 1; attribIndex < maxAttribs; ++attribIndex) + { + shaderStream << " color += a" << attribIndex << ";" << std::endl; + } + + // Built-In attributes + shaderStream << " color += (float(gl_VertexID) + float(gl_InstanceID))/2.0f;" << std::endl; + shaderStream << "}" << std::endl; + + constexpr char kFS[] = + "#version 300 es\n" + "precision highp float;\n" + "in float color;\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = vec4(color, 0.0, 0.0, 1.0);\n" + "}\n"; + + ANGLE_GL_PROGRAM(program, shaderStream.str().c_str(), kFS); + + GLint location = glGetAttribLocation(program, "gl_VertexID"); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(location, -1); + + location = 0; + location = glGetAttribLocation(program, "gl_InstanceID"); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(location, -1); + + drawQuad(program, "position", 0.5f); + EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1); +} + class VertexAttributeTestES31 : public VertexAttributeTestES3 { protected: @@ -3815,12 +3872,17 @@ void main() // include data via glVertexAttribPointer(), there is no crash. TEST_P(VertexAttributeTest, VertexAttribPointerCopyBufferFromInvalidAddress) { + // clang-format off const GLfloat vertices[] = { // position // color // texCoord -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Lower left corner 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // Bottom right corner 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 1.0f // Top + -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f, // Extra bottom left + 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, // Extra bottom right + 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f // Extra top }; + // clang-format on constexpr char kVS[] = R"( attribute highp vec2 position; @@ -3874,12 +3936,149 @@ TEST_P(VertexAttributeTest, VertexAttribPointerCopyBufferFromInvalidAddress) glDrawArrays(GL_TRIANGLES, 0, 3); EXPECT_GL_NO_ERROR(); + glDrawArrays(GL_TRIANGLES, 3, 3); + EXPECT_GL_NO_ERROR(); + glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); EXPECT_GL_NO_ERROR(); } +// Test that there is no crash when two vertex attribute indices are enabled and initialized via +// glVertexAttribPointer(), but then the corresponding array buffer is deleted and recreated, and +// for the next draws only one attribute among them is re-initialized via glVertexAttribPointer(). +TEST_P(VertexAttributeTest, VertexAttribPointerCopyBufferFromInvalidAddressAfterArrayBufferDeletion) +{ + // clang-format off + const GLfloat vertices[] = { + // position // color + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Lower left corner + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Bottom right corner + 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f // Top + -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // Extra bottom left + 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // Extra bottom right + 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f // Extra top + }; + // clang-format on + + constexpr char kVS[] = R"( + attribute highp vec2 position; + attribute mediump vec4 color; + varying mediump vec4 fragColor; + varying highp vec2 fragTexCoord; + void main() { + gl_Position = vec4(position, 0.0, 1.0); + fragColor = color; + fragTexCoord = 0.5 * (position + 1.0); + } + )"; + + constexpr char kFS[] = R"( + precision mediump float; + varying mediump vec4 fragColor; + varying highp vec2 fragTexCoord; + void main() { + if (fragTexCoord.x > 0.5) { + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); + } else { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + } + )"; + + mProgram = CompileProgram(kVS, kFS); + ASSERT_NE(0u, mProgram); + glBindAttribLocation(mProgram, 0, "position"); + glBindAttribLocation(mProgram, 1, "color"); + glUseProgram(mProgram); + EXPECT_GL_NO_ERROR(); + + glGenBuffers(1, &mBuffer); + glBindBuffer(GL_ARRAY_BUFFER, mBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + EXPECT_GL_NO_ERROR(); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *)0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), + (GLvoid *)(2 * sizeof(GLfloat))); + + glDrawArrays(GL_TRIANGLES, 0, 3); + EXPECT_GL_NO_ERROR(); + + glDrawArrays(GL_TRIANGLES, 3, 3); + EXPECT_GL_NO_ERROR(); + + // Here the original bound array buffer is deleted, but is recreated with the same data. Next, + // the vertex attribute pointer 0 is re-initialized, but vertex attribute pointer 1 is skipped. + glDeleteBuffers(1, &mBuffer); + glGenBuffers(1, &mBuffer); + glBindBuffer(GL_ARRAY_BUFFER, mBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *)0); + // Missing VertexAttribPointer at index 1 + + glDrawArrays(GL_TRIANGLES, 0, 3); + EXPECT_GL_NO_ERROR(); + + glDrawArrays(GL_TRIANGLES, 3, 3); + EXPECT_GL_NO_ERROR(); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + EXPECT_GL_NO_ERROR(); +} + +// Test that when the offset for the vertex attribute pointer is not aligned with the stride, the +// draw is successful without crashes due to out-of-bound access. +TEST_P(VertexAttributeTest, BufferOffsetNonAlignedWithStride) +{ + glClearColor(0.0f, 0.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + constexpr char kVS[] = R"( +attribute highp vec3 pos; +void main() { + gl_Position = vec4(pos, 1.0); +})"; + constexpr char kFS[] = R"( +precision highp float; +void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +})"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + glBindAttribLocation(program, 0, "pos"); + glUseProgram(program); + ASSERT_GL_NO_ERROR(); + + const std::vector kVertexData = {-1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f}; + constexpr size_t kOffset = 1; + constexpr size_t kStride = 12; + static_assert(kOffset % kStride != 0, "Offset must not be aligned with stride."); + + constexpr size_t kBufferSize = 1 * 1024 * 1024; + std::vector bufferData(kBufferSize, 0); + memcpy(bufferData.data() + kOffset, kVertexData.data(), kVertexData.size() * sizeof(float)); + + GLBuffer buffer; + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, kBufferSize, bufferData.data(), GL_DYNAMIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, kStride, + reinterpret_cast(kOffset)); + + glDrawArrays(GL_TRIANGLES, 0, 6); + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); +} + // Test that default unsigned integer attribute works correctly even if there is a gap in // attribute locations. TEST_P(VertexAttributeTestES3, DefaultUIntAttribWithGap) @@ -5566,6 +5765,8 @@ ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat), ES3_VULKAN().enable(Feature::ForceFallbackFormat), ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat), + ES3_VULKAN().disable(Feature::ForceSizePointerForBoundVertexBuffers), + ES3_VULKAN_SWIFTSHADER().disable(Feature::ForceSizePointerForBoundVertexBuffers), ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass), ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass), ES2_OPENGL().enable(Feature::ForceMinimumMaxVertexAttributes), @@ -5592,15 +5793,18 @@ ANGLE_INSTANTIATE_TEST_ES3_AND( ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass), ES3_VULKAN() .disable(Feature::UseVertexInputBindingStrideDynamicState) - .disable(Feature::SupportsGraphicsPipelineLibrary)); + .disable(Feature::SupportsGraphicsPipelineLibrary), + ES3_VULKAN().disable(Feature::ForceSizePointerForBoundVertexBuffers)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES31); -ANGLE_INSTANTIATE_TEST_ES31_AND(VertexAttributeTestES31, - ES31_VULKAN().enable(Feature::ForceFallbackFormat), - ES31_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat), - ES31_VULKAN() - .disable(Feature::UseVertexInputBindingStrideDynamicState) - .disable(Feature::SupportsGraphicsPipelineLibrary)); +ANGLE_INSTANTIATE_TEST_ES31_AND( + VertexAttributeTestES31, + ES31_VULKAN().enable(Feature::ForceFallbackFormat), + ES31_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat), + ES31_VULKAN() + .disable(Feature::UseVertexInputBindingStrideDynamicState) + .disable(Feature::SupportsGraphicsPipelineLibrary), + ES31_VULKAN().disable(Feature::ForceSizePointerForBoundVertexBuffers)); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( VertexAttributeCachingTest, diff --git a/src/tests/gl_tests/ViewportTest.cpp b/src/tests/gl_tests/ViewportTest.cpp index 9de83a80a62..e5942d5071f 100644 --- a/src/tests/gl_tests/ViewportTest.cpp +++ b/src/tests/gl_tests/ViewportTest.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" @@ -435,15 +439,7 @@ TEST_P(ViewportTest, ClampOnStore) // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. D3D11 Feature Level 9 and D3D9 emulate large and negative viewports // in the vertex shader. We should test both of these as well as D3D11 Feature Level 10_0+. -ANGLE_INSTANTIATE_TEST(ViewportTest, - ES2_D3D9(), - ES2_D3D11(), - ES2_D3D11_PRESENT_PATH_FAST(), - ES2_OPENGLES(), - ES3_OPENGLES(), - ES2_METAL(), - ES2_OPENGL(), - ES2_VULKAN()); +ANGLE_INSTANTIATE_TEST_ES2_AND(ViewportTest, ES2_D3D11_PRESENT_PATH_FAST()); // This test suite is not instantiated on some OSes. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ViewportTest); diff --git a/src/tests/gl_tests/VulkanDescriptorSetTest.cpp b/src/tests/gl_tests/VulkanDescriptorSetTest.cpp index b24afdc4f0e..72a57caa8a5 100644 --- a/src/tests/gl_tests/VulkanDescriptorSetTest.cpp +++ b/src/tests/gl_tests/VulkanDescriptorSetTest.cpp @@ -210,5 +210,6 @@ TEST_P(VulkanDescriptorSetLayoutDescTest, Basic) ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()); ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanDescriptorSetLayoutDescTest); } // namespace diff --git a/src/tests/gl_tests/VulkanFormatTablesTest.cpp b/src/tests/gl_tests/VulkanFormatTablesTest.cpp index 561b37517c2..3926fbac3ba 100644 --- a/src/tests/gl_tests/VulkanFormatTablesTest.cpp +++ b/src/tests/gl_tests/VulkanFormatTablesTest.cpp @@ -70,7 +70,7 @@ TEST_P(VulkanFormatTablesTest, TestFormatSupport) for (const ParametersToTest params : parametersToTest) { VkFormat actualImageVkFormat = rx::vk::GetVkFormatFromFormatID( - renderer, vkFormat.getActualImageFormatID(rx::vk::ImageAccess::SampleOnly)); + renderer, vkFormat.getActualImageFormatID(rx::vk::ImageFormatSupport::SampleOnly)); // Now let's verify that against vulkan. VkFormatProperties formatProperties; @@ -117,5 +117,6 @@ TEST_P(VulkanFormatTablesTest, TestFormatSupport) } ANGLE_INSTANTIATE_TEST(VulkanFormatTablesTest, ES2_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanFormatTablesTest); } // anonymous namespace diff --git a/src/tests/gl_tests/VulkanFramebufferTest.cpp b/src/tests/gl_tests/VulkanFramebufferTest.cpp index 9c3766ae3b6..6445b5f39f4 100644 --- a/src/tests/gl_tests/VulkanFramebufferTest.cpp +++ b/src/tests/gl_tests/VulkanFramebufferTest.cpp @@ -127,5 +127,6 @@ TEST_P(VulkanFramebufferTest, R4G4B4A4TextureSampleOnlyActuallyUses444Format) } ANGLE_INSTANTIATE_TEST(VulkanFramebufferTest, ES3_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanFramebufferTest); } // anonymous namespace diff --git a/src/tests/gl_tests/VulkanImageTest.cpp b/src/tests/gl_tests/VulkanImageTest.cpp index bd5f645e414..2f06e2d5d92 100644 --- a/src/tests/gl_tests/VulkanImageTest.cpp +++ b/src/tests/gl_tests/VulkanImageTest.cpp @@ -6,6 +6,10 @@ // VulkanImageTest.cpp : Tests of EGL_ANGLE_vulkan_image & GL_ANGLE_vulkan_image extensions. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "common/debug.h" @@ -25,6 +29,27 @@ class VulkanImageTest : public ANGLETest<> { protected: VulkanImageTest() { setRobustResourceInit(true); } + + GLenum expectedGLLayoutAfterTransfer(const VulkanHelper &helper) + { + return helper.useUnifiedImageLayouts() ? GL_LAYOUT_GENERAL_EXT : GL_LAYOUT_TRANSFER_DST_EXT; + } + VkImageLayout expectedVKLayoutAfterTransfer(const VulkanHelper &helper) + { + return helper.useUnifiedImageLayouts() ? VK_IMAGE_LAYOUT_GENERAL + : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + } + + GLenum expectedGLLayoutAfterColorWrite(const VulkanHelper &helper) + { + return helper.useUnifiedImageLayouts() ? GL_LAYOUT_GENERAL_EXT + : GL_LAYOUT_COLOR_ATTACHMENT_EXT; + } + VkImageLayout expectedVKLayoutAfterColorWrite(const VulkanHelper &helper) + { + return helper.useUnifiedImageLayouts() ? VK_IMAGE_LAYOUT_GENERAL + : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } }; class VulkanMemoryTest : public ANGLETest<> @@ -237,11 +262,11 @@ TEST_P(VulkanImageTest, PixelTestTexImage2D) GLuint textures[1] = {texture}; GLenum layouts[1] = {GL_NONE}; glReleaseTexturesANGLE(1, textures, layouts); - EXPECT_EQ(layouts[0], static_cast(GL_LAYOUT_TRANSFER_DST_EXT)); + EXPECT_EQ(layouts[0], expectedGLLayoutAfterTransfer(helper)); { std::vector pixels(kWidth * kHeight); - helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, info.format, {}, + helper.readPixels(vkImage, expectedVKLayoutAfterTransfer(helper), info.format, {}, info.extent, pixels.data(), pixels.size() * sizeof(GLuint)); EXPECT_EQ(pixels, std::vector(kWidth * kHeight, kColor)); } @@ -293,10 +318,10 @@ TEST_P(VulkanImageTest, PixelTestClear) GLuint textures[1] = {texture}; GLenum layouts[1] = {GL_NONE}; glReleaseTexturesANGLE(1, textures, layouts); - EXPECT_EQ(layouts[0], static_cast(GL_LAYOUT_TRANSFER_DST_EXT)); + EXPECT_EQ(layouts[0], expectedGLLayoutAfterTransfer(helper)); std::vector pixels(kWidth * kHeight); - helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, info.format, {}, info.extent, + helper.readPixels(vkImage, expectedVKLayoutAfterTransfer(helper), info.format, {}, info.extent, pixels.data(), pixels.size() * sizeof(GLuint)); EXPECT_EQ(pixels, std::vector(kWidth * kHeight, kWhite)); @@ -308,9 +333,9 @@ TEST_P(VulkanImageTest, PixelTestClear) glClear(GL_COLOR_BUFFER_BIT); glReleaseTexturesANGLE(1, textures, layouts); - EXPECT_EQ(layouts[0], static_cast(GL_LAYOUT_TRANSFER_DST_EXT)); + EXPECT_EQ(layouts[0], expectedGLLayoutAfterTransfer(helper)); - helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, info.format, {}, info.extent, + helper.readPixels(vkImage, expectedVKLayoutAfterTransfer(helper), info.format, {}, info.extent, pixels.data(), pixels.size() * sizeof(GLuint)); EXPECT_EQ(pixels, std::vector(kWidth * kHeight, kRed)); @@ -361,7 +386,7 @@ TEST_P(VulkanImageTest, PixelTestDrawQuad) GLuint textures[1] = {texture}; GLenum layouts[1] = {GL_NONE}; glReleaseTexturesANGLE(1, textures, layouts); - EXPECT_EQ(layouts[0], static_cast(GL_LAYOUT_COLOR_ATTACHMENT_EXT)); + EXPECT_EQ(layouts[0], expectedGLLayoutAfterColorWrite(helper)); VkImage vkImage = VK_NULL_HANDLE; VkImageCreateInfo info = {}; @@ -369,7 +394,7 @@ TEST_P(VulkanImageTest, PixelTestDrawQuad) EXPECT_NE(vkImage, static_cast(VK_NULL_HANDLE)); std::vector pixels(kWidth * kHeight); - helper.readPixels(vkImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, info.format, {}, + helper.readPixels(vkImage, expectedVKLayoutAfterColorWrite(helper), info.format, {}, info.extent, pixels.data(), pixels.size() * sizeof(GLuint)); EXPECT_EQ(pixels, std::vector(kWidth * kHeight, kRed)); @@ -442,10 +467,10 @@ TEST_P(VulkanImageTest, ClientBuffer) textures[0] = texture; layouts[0] = GL_NONE; glReleaseTexturesANGLE(1, textures, layouts); - EXPECT_EQ(layouts[0], static_cast(GL_LAYOUT_TRANSFER_DST_EXT)); + EXPECT_EQ(layouts[0], expectedGLLayoutAfterTransfer(helper)); std::vector pixels(kWidth * kHeight); - helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageCreateInfo.format, {}, + helper.readPixels(vkImage, expectedVKLayoutAfterTransfer(helper), imageCreateInfo.format, {}, imageCreateInfo.extent, pixels.data(), pixels.size() * sizeof(GLuint)); EXPECT_EQ(pixels, std::vector(kWidth * kHeight, kWhite)); @@ -457,9 +482,9 @@ TEST_P(VulkanImageTest, ClientBuffer) glClear(GL_COLOR_BUFFER_BIT); glReleaseTexturesANGLE(1, textures, layouts); - EXPECT_EQ(layouts[0], static_cast(GL_LAYOUT_TRANSFER_DST_EXT)); + EXPECT_EQ(layouts[0], expectedGLLayoutAfterTransfer(helper)); - helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageCreateInfo.format, {}, + helper.readPixels(vkImage, expectedVKLayoutAfterTransfer(helper), imageCreateInfo.format, {}, imageCreateInfo.extent, pixels.data(), pixels.size() * sizeof(GLuint)); EXPECT_EQ(pixels, std::vector(kWidth * kHeight, kRed)); diff --git a/src/tests/gl_tests/VulkanMultithreadingTest.cpp b/src/tests/gl_tests/VulkanMultithreadingTest.cpp index 145e05e8ca0..2839ae567c9 100644 --- a/src/tests/gl_tests/VulkanMultithreadingTest.cpp +++ b/src/tests/gl_tests/VulkanMultithreadingTest.cpp @@ -205,5 +205,6 @@ TEST_P(VulkanMultithreadingTest, MultiContextDrawSmallDescriptorPools) } ANGLE_INSTANTIATE_TEST(VulkanMultithreadingTest, ES2_VULKAN(), ES3_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanMultithreadingTest); } // namespace angle diff --git a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp index 70aa9f615cc..f5294d826ad 100644 --- a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp +++ b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp @@ -6,11 +6,18 @@ // VulkanPerformanceCounterTest: // Validates specific GL call patterns with ANGLE performance counters. // For example we can verify a certain call set doesn't break the render pass. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "include/platform/Feature.h" #include "test_utils/ANGLETest.h" #include "test_utils/angle_test_instantiate.h" #include "test_utils/gl_raii.h" +#include "util/EGLWindow.h" +#include "util/OSWindow.h" #include "util/random_utils.h" #include "util/shader_utils.h" #include "util/test_utils.h" @@ -148,8 +155,11 @@ class VulkanPerformanceCounterTest : public ANGLETest<> void testSetUp() override { - glGenPerfMonitorsAMD(1, &monitor); - glBeginPerfMonitorAMD(monitor); + // Using local variable so that ASAN can catch "stack-buffer-overflow" error. + GLuint localMonitor; + glGenPerfMonitorsAMD(1, &localMonitor); + glBeginPerfMonitorAMD(localMonitor); + monitor = localMonitor; } void testTearDown() override @@ -238,41 +248,6 @@ class VulkanPerformanceCounterTest : public ANGLETest<> ASSERT_GL_NO_ERROR(); } - void setExpectedCountersForDepthOps(const angle::VulkanPerfCounters &counters, - uint64_t incrementalRenderPasses, - uint64_t incrementalDepthLoadOpClears, - uint64_t incrementalDepthLoadOpLoads, - uint64_t incrementalDepthLoadOpNones, - uint64_t incrementalDepthStoreOpStores, - uint64_t incrementalDepthStoreOpNones, - angle::VulkanPerfCounters *expected) - { - expected->renderPasses = counters.renderPasses + incrementalRenderPasses; - expected->depthLoadOpClears = counters.depthLoadOpClears + incrementalDepthLoadOpClears; - expected->depthLoadOpLoads = counters.depthLoadOpLoads + incrementalDepthLoadOpLoads; - expected->depthLoadOpNones = counters.depthLoadOpNones + incrementalDepthLoadOpNones; - expected->depthStoreOpStores = counters.depthStoreOpStores + incrementalDepthStoreOpStores; - expected->depthStoreOpNones = counters.depthStoreOpNones + incrementalDepthStoreOpNones; - } - - void setExpectedCountersForStencilOps(const angle::VulkanPerfCounters &counters, - uint64_t incrementalStencilLoadOpClears, - uint64_t incrementalStencilLoadOpLoads, - uint64_t incrementalStencilLoadOpNones, - uint64_t incrementalStencilStoreOpStores, - uint64_t incrementalStencilStoreOpNones, - angle::VulkanPerfCounters *expected) - { - expected->stencilLoadOpClears = - counters.stencilLoadOpClears + incrementalStencilLoadOpClears; - expected->stencilLoadOpLoads = counters.stencilLoadOpLoads + incrementalStencilLoadOpLoads; - expected->stencilLoadOpNones = counters.stencilLoadOpNones + incrementalStencilLoadOpNones; - expected->stencilStoreOpStores = - counters.stencilStoreOpStores + incrementalStencilStoreOpStores; - expected->stencilStoreOpNones = - counters.stencilStoreOpNones + incrementalStencilStoreOpNones; - } - void setExpectedCountersForColorOps(const angle::VulkanPerfCounters &counters, uint64_t incrementalRenderPasses, uint64_t incrementalColorLoadOpClears, @@ -290,16 +265,6 @@ class VulkanPerformanceCounterTest : public ANGLETest<> expected->colorStoreOpNones = counters.colorStoreOpNones + incrementalColorStoreOpNones; } - void setAndIncrementDepthStencilLoadCountersForOpsTest( - const angle::VulkanPerfCounters &counters, - uint64_t incrementalDepthLoadOpLoads, - uint64_t incrementalStencilLoadOpLoads, - angle::VulkanPerfCounters *expected) - { - expected->depthLoadOpLoads = counters.depthLoadOpLoads + incrementalDepthLoadOpLoads; - expected->stencilLoadOpLoads = counters.stencilLoadOpLoads + incrementalStencilLoadOpLoads; - } - void setExpectedCountersForUnresolveResolveTest(const angle::VulkanPerfCounters &counters, uint64_t incrementalColorAttachmentUnresolves, uint64_t incrementalDepthAttachmentUnresolves, @@ -326,9 +291,6 @@ class VulkanPerformanceCounterTest : public ANGLETest<> void maskedFramebufferFetchDraw(const GLColor &clearColor, GLBuffer &buffer); void maskedFramebufferFetchDrawVerify(const GLColor &expectedColor, GLBuffer &buffer); - void saveAndReloadBinary(GLProgram *original, GLProgram *reloaded); - void testPipelineCacheIsWarm(GLProgram *program, GLColor color); - void updateBuffer(BufferUpdate update, GLenum target, GLintptr offset, @@ -398,9 +360,9 @@ class VulkanPerformanceCounterTest : public ANGLETest<> { return isFeatureEnabled(Feature::WarmUpPipelineCacheAtLink); } - bool hasEffectivePipelineCacheSerialization() const + bool skipPipelineCacheSerialization() const { - return isFeatureEnabled(Feature::HasEffectivePipelineCacheSerialization); + return isFeatureEnabled(Feature::SkipPipelineCacheSerialization); } bool hasPreferCPUForBufferSubData() const { @@ -427,18 +389,174 @@ class VulkanPerformanceCounterTest : public ANGLETest<> return isFeatureEnabled(Feature::SupportsDepthStencilResolve) && !isFeatureEnabled(Feature::DisableDepthStencilResolveThroughAttachment); } + bool hasSupportsTileMemoryOrSimulation() const + { + return isFeatureEnabled(Feature::SupportsTileMemoryHeap) || + isFeatureEnabled(Feature::SimulateTileMemoryForTesting); + } + + // Setup color texture and depth/stencil render buffer + void setupColorTextureAndDepthBuffer(GLuint colorTexture, + GLuint depthStencil, + GLenum depthStencilFormat, + GLsizei width, + GLsizei height) + { + glBindTexture(GL_TEXTURE_2D, colorTexture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height); + + glBindRenderbuffer(GL_RENDERBUFFER, depthStencil); + glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height); + } + + // Setup FBO with color/depth/stencil attachment + void setupFBO(GLuint colorTexture, + GLuint depthBuffer, + GLuint stencilBuffer, + GLuint fbo, + GLsizei width, + GLsizei height) + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + if (colorTexture != 0) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colorTexture, 0); + } + if (depthBuffer != 0) + { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + depthBuffer); + } + if (stencilBuffer != 0) + { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + stencilBuffer); + } + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glViewport(0, 0, width, height); + } + + // Draw a quad that would display green if depth buffer == depthValue, and display red + // otherwise. + void drawQuadToVerifyDepthValue(const GLProgram &drawGreen, + const GLProgram &drawRed, + GLfloat depthValue) + { + GLfloat kErrorTolerance = 0.01f; + glDisable(GL_STENCIL_TEST); + // Don't modify depth buffer + glDepthMask(GL_FALSE); + glEnable(GL_DEPTH_TEST); + // This should pass + glDepthFunc(GL_LESS); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), depthValue - kErrorTolerance); + // This should fail + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValue + kErrorTolerance); + glDepthFunc(GL_GREATER); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValue - kErrorTolerance); + } + + // Draw a quad that would display green if stencil buffer == stencilValue. + void drawQuadToVerifyStencilValue(const GLProgram &drawGreen, GLint stencilValue) + { + glDisable(GL_DEPTH_TEST); + glStencilMask(0x00); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, stencilValue, 0xFF); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f); + } + + void drawWithDepthValue(std::array &quadVertices, float depth) + { + for (Vector3 &vertice : quadVertices) + { + vertice[2] = depth; + } + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quadVertices[0]) * quadVertices.size(), + quadVertices.data()); + glDrawArrays(GL_TRIANGLES, 0, 6); + } GLuint monitor; CounterNameToIndexMap mIndexMap; }; +class VulkanPerformanceCounterTest_DepthStencilLoadStoreOps : public VulkanPerformanceCounterTest +{ + protected: + void setExpectedCountersForDepthOps(const angle::VulkanPerfCounters &counters, + uint64_t incrementalRenderPasses, + uint64_t incrementalDepthLoadOpClears, + uint64_t incrementalDepthLoadOpLoads, + uint64_t incrementalDepthLoadOpNones, + uint64_t incrementalDepthStoreOpStores, + uint64_t incrementalDepthStoreOpNones, + angle::VulkanPerfCounters *expected) + { + expected->renderPasses = counters.renderPasses + incrementalRenderPasses; + expected->depthLoadOpClears = counters.depthLoadOpClears + incrementalDepthLoadOpClears; + expected->depthLoadOpLoads = counters.depthLoadOpLoads + incrementalDepthLoadOpLoads; + expected->depthLoadOpNones = counters.depthLoadOpNones + incrementalDepthLoadOpNones; + expected->depthStoreOpStores = counters.depthStoreOpStores + incrementalDepthStoreOpStores; + expected->depthStoreOpNones = counters.depthStoreOpNones + incrementalDepthStoreOpNones; + } + + void setExpectedCountersForStencilOps(const angle::VulkanPerfCounters &counters, + uint64_t incrementalStencilLoadOpClears, + uint64_t incrementalStencilLoadOpLoads, + uint64_t incrementalStencilLoadOpNones, + uint64_t incrementalStencilStoreOpStores, + uint64_t incrementalStencilStoreOpNones, + angle::VulkanPerfCounters *expected) + { + expected->stencilLoadOpClears = + counters.stencilLoadOpClears + incrementalStencilLoadOpClears; + expected->stencilLoadOpLoads = counters.stencilLoadOpLoads + incrementalStencilLoadOpLoads; + expected->stencilLoadOpNones = counters.stencilLoadOpNones + incrementalStencilLoadOpNones; + expected->stencilStoreOpStores = + counters.stencilStoreOpStores + incrementalStencilStoreOpStores; + expected->stencilStoreOpNones = + counters.stencilStoreOpNones + incrementalStencilStoreOpNones; + } + + void setAndIncrementDepthStencilLoadCountersForOpsTest( + const angle::VulkanPerfCounters &counters, + uint64_t incrementalDepthLoadOpLoads, + uint64_t incrementalStencilLoadOpLoads, + angle::VulkanPerfCounters *expected) + { + expected->depthLoadOpLoads = counters.depthLoadOpLoads + incrementalDepthLoadOpLoads; + expected->stencilLoadOpLoads = counters.stencilLoadOpLoads + incrementalStencilLoadOpLoads; + } +}; + +class VulkanPerformanceCounterTest_RGBSurface : public VulkanPerformanceCounterTest +{ + protected: + VulkanPerformanceCounterTest_RGBSurface() : VulkanPerformanceCounterTest() + { + // Only set the Alpha bit to 0 on ARM platforms to avoid EGL configuration + // failures. + if (IsARM()) + { + setConfigAlphaBits(0); + } + } +}; + class VulkanPerformanceCounterTest_ES31 : public VulkanPerformanceCounterTest {}; -class VulkanPerformanceCounterTest_MSAA : public VulkanPerformanceCounterTest +class VulkanPerformanceCounterTest_DepthStencilLoadStoreOps_ES31 + : public VulkanPerformanceCounterTest_DepthStencilLoadStoreOps +{}; + +class VulkanPerformanceCounterTest_MSAA + : public VulkanPerformanceCounterTest_DepthStencilLoadStoreOps { protected: - VulkanPerformanceCounterTest_MSAA() : VulkanPerformanceCounterTest() + VulkanPerformanceCounterTest_MSAA() : VulkanPerformanceCounterTest_DepthStencilLoadStoreOps() { // Make sure the window is non-square to correctly test prerotation setWindowWidth(32); @@ -641,7 +759,7 @@ TEST_P(VulkanPerformanceCounterTest, SubmittingOutsideCommandBufferDoesNotBreakR constexpr size_t kMaxBufferToImageCopySize = 64 * 1024 * 1024; constexpr uint64_t kNumSubmits = 2; uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1; - uint64_t expectedSubmitCommandsCount = getPerfCounters().vkQueueSubmitCallsTotal + kNumSubmits; + uint64_t submitCommandsCountBefore = getPerfCounters().vkQueueSubmitCallsTotal; // Step 1: Set up a simple 2D texture. GLTexture texture; @@ -694,7 +812,16 @@ TEST_P(VulkanPerformanceCounterTest, SubmittingOutsideCommandBufferDoesNotBreakR // Verify render pass and submitted frame counts. EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount); - EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedSubmitCommandsCount); + if (hasSupportsTileMemoryOrSimulation()) + { + // When tile memory is used we may not submit if depthStencil has valid data. + EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal - submitCommandsCountBefore, 0ul); + } + else + { + EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal - submitCommandsCountBefore, + kNumSubmits); + } } // Tests that submitting the outside command buffer due to texture upload size does not result in @@ -1871,7 +1998,7 @@ void main() } // Test resolving the depth/stencil attachment -TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleDepthStencilResolve) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps_ES31, MultisampleDepthStencilResolve) { ANGLE_SKIP_TEST_IF(!hasDepthStencilResolveThroughAttachment()); @@ -2120,7 +2247,7 @@ TEST_P(VulkanPerformanceCounterTest, ClearColorBufferAndReadOnlyDepthStencilUses // Similar scenario as in ClearColorBufferAndReadOnlyDepthStencilUsesSingleRenderPass based on // Manhattan, but involving queries that end up marking a render pass for closure. This results in // the switch to read-only depth/stencil mode to flush the render pass twice. -TEST_P(VulkanPerformanceCounterTest, +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, QueryThenClearColorBufferAndReadOnlyDepthStencilUsesSingleRenderPass) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2193,7 +2320,8 @@ TEST_P(VulkanPerformanceCounterTest, // Make sure depth/stencil clears followed by a switch to read-only mode still lets the color clears // use loadOp=CLEAR optimally. -TEST_P(VulkanPerformanceCounterTest, SwitchToReadOnlyDepthStencilLeavesOtherAspectsOptimal) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + SwitchToReadOnlyDepthStencilLeavesOtherAspectsOptimal) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2713,7 +2841,7 @@ TEST_P(VulkanPerformanceCounterTest_ES31, FramebufferFetchRenderPassThenColorMas // Tests that clear after unused depth/stencil is optimized to use loadOp // // - Scenario: disable depth/stencil, draw, clear -TEST_P(VulkanPerformanceCounterTest, DepthStencilMaskedDrawThenClear) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilMaskedDrawThenClear) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2763,7 +2891,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilMaskedDrawThenClear) // - Scenario: depth test enabled, depth write mask = 0, // clear depth, draw red quad with compare function always, // and then draw green quad with compare function less equal -TEST_P(VulkanPerformanceCounterTest, DepthFunctionDynamicChangeLoadOp) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthFunctionDynamicChangeLoadOp) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2813,7 +2941,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthFunctionDynamicChangeLoadOp) // Tests that common PUBG MOBILE case does not break render pass, and that counts are correct: // // - Scenario: invalidate, disable, draw -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidateDisableDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2863,7 +2991,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDraw) // Tests that alternative PUBG MOBILE case does not break render pass, and that counts are correct: // // - Scenario: disable, invalidate, draw -TEST_P(VulkanPerformanceCounterTest, DisableInvalidateDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DisableInvalidateDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2913,7 +3041,7 @@ TEST_P(VulkanPerformanceCounterTest, DisableInvalidateDraw) // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: disable, draw, invalidate, enable -TEST_P(VulkanPerformanceCounterTest, DisableDrawInvalidateEnable) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DisableDrawInvalidateEnable) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -2974,7 +3102,7 @@ TEST_P(VulkanPerformanceCounterTest, DisableDrawInvalidateEnable) // Tests that common TRex case does not break render pass, and that counts are correct: // // - Scenario: invalidate -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidate) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidate) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3015,7 +3143,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidate) // Similar to Invalidate, but uses glInvalidateSubFramebuffer such that the given area covers the // whole framebuffer. -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateSub) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidateSub) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3057,7 +3185,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateSub) // Similar to InvalidateSub, but uses glInvalidateSubFramebuffer such that the given area does NOT // covers the whole framebuffer. -TEST_P(VulkanPerformanceCounterTest, DepthStencilPartialInvalidateSub) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilPartialInvalidateSub) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3131,7 +3259,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilPartialInvalidateSub) // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, draw -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidateDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3177,7 +3305,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDraw) // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, draw, disable -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisable) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidateDrawDisable) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3233,7 +3361,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisable) // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, disable, draw, enable -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDrawEnable) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDisableDrawEnable) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3289,7 +3418,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDrawEnable) // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, disable, draw, enable, draw -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDrawEnableDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDisableDrawEnableDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3348,7 +3478,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDrawEnableDraw // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, draw, disable, enable -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnable) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDrawDisableEnable) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3407,7 +3538,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnable) // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, draw, disable, enable, invalidate -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnableInvalidate) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDrawDisableEnableInvalidate) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3468,7 +3600,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnableInva // Tests that another case does not break render pass, and that counts are correct: // // - Scenario: invalidate, draw, disable, enable, invalidate, draw -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnableInvalidateDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDrawDisableEnableInvalidateDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3533,7 +3666,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnableInva // Tests that another common (dEQP) case does not break render pass, and that counts are correct: // // - Scenario: invalidate, disable, enable, draw -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableEnableDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDisableEnableDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3588,7 +3722,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableEnableDraw) } // Tests that an in renderpass clear after invalidate keeps content stored. -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateAndClear) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidateAndClear) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3648,7 +3782,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateAndClear) // Tests that the draw path for clear after invalidate and disabling depth/stencil test keeps // content stored. -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateAndMaskedClear) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthStencilInvalidateAndMaskedClear) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3713,7 +3847,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateAndMaskedClear) // Tests that the renderpass is using depthFunc(GL_ALWAYS) and depthMask(GL_FALSE), it should not // load or store depth value. -TEST_P(VulkanPerformanceCounterTest, DepthFuncALWAYSWithDepthMaskDisabledShouldNotLoadStore) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthFuncALWAYSWithDepthMaskDisabledShouldNotLoadStore) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3760,7 +3895,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthFuncALWAYSWithDepthMaskDisabledShouldN // Tests that the renderpass is using depthFunc(GL_ALWAYS) and depthMask(GL_FALSE) and draw. Then it // followed by glClear, it should not load or store depth value. -TEST_P(VulkanPerformanceCounterTest, +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthFuncALWAYSWithDepthMaskDisabledThenClearShouldNotLoadStore) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3818,7 +3953,8 @@ TEST_P(VulkanPerformanceCounterTest, // Tests that the renderpass is using depthFunc(GL_NEVER) and depthMask(GL_FALSE), it should not // load or store depth value. -TEST_P(VulkanPerformanceCounterTest, DepthFuncNEVERWithDepthMaskDisabledShouldNotLoadStore) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthFuncNEVERWithDepthMaskDisabledShouldNotLoadStore) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3853,7 +3989,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthFuncNEVERWithDepthMaskDisabledShouldNo // Tests whether depth-stencil ContentDefined will be correct when: // // - Scenario: invalidate, detach D/S texture and modify it, attach D/S texture, draw with blend -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDetachModifyTexAttachDrawWithBlend) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDetachModifyTexAttachDrawWithBlend) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -3951,7 +4088,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDetachModifyTexAttach // still works. // // - Scenario: invalidate -TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawAndDeleteRenderbuffer) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + DepthStencilInvalidateDrawAndDeleteRenderbuffer) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -4002,7 +4140,8 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawAndDeleteRenderbu // Test that disabling color buffer after clear continues to use loadOp for it. // // - Scenario: clear color and depth, disable color, draw, enable color, draw -TEST_P(VulkanPerformanceCounterTest_ES31, ColorDisableThenDrawThenEnableThenDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps_ES31, + ColorDisableThenDrawThenEnableThenDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -4465,9 +4604,7 @@ TEST_P(VulkanPerformanceCounterTest, ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - uint64_t expectedRenderPassCount = - getPerfCounters().renderPasses + - (isFeatureEnabled(Feature::PreferSubmitOnAnySamplesPassedQueryEnd) ? 2 : 1); + uint64_t renderPassCountBefore = getPerfCounters().renderPasses; GLQueryEXT query1, query2; // Draw inside query @@ -4486,8 +4623,17 @@ TEST_P(VulkanPerformanceCounterTest, glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_EXT, &results[1]); EXPECT_GL_NO_ERROR(); - uint64_t actualRenderPassCount = getPerfCounters().renderPasses; - EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount); + uint64_t actualRenderPassCount = getPerfCounters().renderPasses - renderPassCountBefore; + if (hasSupportsTileMemoryOrSimulation() || + !isFeatureEnabled(Feature::PreferSubmitOnAnySamplesPassedQueryEnd)) + { + // When tile memory is used we may not submit if depthStencil has valid data. + EXPECT_EQ(1ul, actualRenderPassCount); + } + else + { + EXPECT_EQ(2ul, actualRenderPassCount); + } } // Tests that depth/stencil texture clear/load works correctly. @@ -4723,7 +4869,8 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNot // Tests that multisampled-render-to-texture depth/stencil renderbuffers don't ever load // depth/stencil data. -TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShouldNotLoad) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + RenderToTextureDepthStencilRenderbufferShouldNotLoad) { // http://anglebug.com/42263651 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan()); @@ -4852,7 +4999,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou // Tests counters when multisampled-render-to-texture color/depth/stencil renderbuffers are // invalidated. -TEST_P(VulkanPerformanceCounterTest, RenderToTextureInvalidate) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, RenderToTextureInvalidate) { // http://anglebug.com/42263651 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan()); @@ -4983,7 +5130,8 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureInvalidate) // Tests counters when uninitialized multisampled-render-to-texture depth/stencil renderbuffers are // unused but not invalidated. -TEST_P(VulkanPerformanceCounterTest, RenderToTextureUninitializedAndUnusedDepthStencil) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + RenderToTextureUninitializedAndUnusedDepthStencil) { // http://anglebug.com/42263651 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan()); @@ -5055,80 +5203,211 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureUninitializedAndUnusedDepthS EXPECT_COUNTERS_FOR_UNRESOLVE_RESOLVE_TEST(getPerfCounters(), expected); } -// Ensures we use read-only depth layout when there is no write -TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout) +// Tests that multisampled-render-to-texture depth/stencil renderbuffers resolve to be updated +// respectively. +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + MultisampleDepthStencilResolveSeparately) { - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); - constexpr GLsizei kSize = 64; + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); angle::VulkanPerfCounters expected; - // Create depth only FBO and fill depth texture to leftHalf=0.0 and rightHalf=1.0. This should - // use writeable layout - expected.readOnlyDepthStencilRenderPasses = getPerfCounters().readOnlyDepthStencilRenderPasses; + // This test creates 4 render passes. In the first render pass, color, depth and stencil are + // cleared. In the following render passes, depth and stencil toggle between Load and Clear + // respectively. - // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0), - // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0) - setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected); - setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected); + constexpr GLsizei kSize = 6; - GLTexture depthTexture; - glBindTexture(GL_TEXTURE_2D, depthTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 0, GL_DEPTH_COMPONENT, - GL_UNSIGNED_INT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // Create multisampled framebuffer to draw into, with both color and depth attachments. + GLTexture colorMS; + glBindTexture(GL_TEXTURE_2D, colorMS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - GLFramebuffer depthOnlyFBO; - glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + GLRenderbuffer depthStencilMS; + glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glDepthMask(GL_TRUE); - ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glViewport(0, 0, kSize / 2, kSize); - drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0f); - glViewport(kSize / 2, 0, kSize / 2, kSize); - drawQuad(redProgram, essl1_shaders::PositionAttrib(), 1.0f); - glViewport(0, 0, kSize, kSize); + GLFramebuffer fboMS; + glBindFramebuffer(GL_FRAMEBUFFER, fboMS); + glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colorMS, 0, 4); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + depthStencilMS); ASSERT_GL_NO_ERROR(); - // Because the layout counter is updated at end of renderpass, we need to issue a finish call - // here to end the renderpass. - glFinish(); + // Set up texture for copy operation that breaks the render pass + GLTexture copyTex; + glBindTexture(GL_TEXTURE_2D, copyTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - uint64_t actualReadOnlyDepthStencilCount = getPerfCounters().readOnlyDepthStencilRenderPasses; - EXPECT_EQ(expected.readOnlyDepthStencilRenderPasses, actualReadOnlyDepthStencilCount); - EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected); + // Set viewport and clear color, depth and stencil + glViewport(0, 0, kSize, kSize); + glClearColor(0, 0, 0, 0.0f); + glClearDepthf(1.0); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - // Create a color+depth FBO and use depth as read only. This should use read only layout - ++expected.readOnlyDepthStencilRenderPasses; - // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1), - // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0) - setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 0, 1, &expected); - setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected); + // Output depth/stencil but disable testing so all draw calls succeed + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); - GLTexture colorTexture; - glBindTexture(GL_TEXTURE_2D, colorTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - GLFramebuffer depthAndColorFBO; - glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); - ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glEnable(GL_STENCIL_TEST); + glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 255); + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 255); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP); + glStencilMask(255); - // Clear color to blue and draw a green quad with depth=0.5 - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glDepthMask(GL_FALSE); + // Set up program + ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glUseProgram(drawColor); + GLint colorUniformLocation = + glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorUniformLocation, -1); - angle::Vector4 clearColor = GLColor::blue.toNormalizedVector(); - glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f); + // First render pass: The depthLoadOp and stencilLoadOp are Clear. + // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0), + // stencil(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0) + setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected); + setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 1, 0, &expected); + + glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.75f); + ASSERT_GL_NO_ERROR(); + + // Break the first render pass and verify the counters. + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize); + ASSERT_GL_NO_ERROR(); + EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected); + + // Second render pass: The depthLoadOp and stencilLoadOp are Load. + // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0), + // stencil(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0) + setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected); + setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 1, 0, &expected); + + glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f); + ASSERT_GL_NO_ERROR(); + + // Break the second render pass and verify the counters. + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize); + ASSERT_GL_NO_ERROR(); + EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected); + + // Clear depth, but not stencil buffer (loadOp D=CLEAR) + glClear(GL_DEPTH_BUFFER_BIT); + + // Third render pass: The depthLoadOp is Clear and stencilLoadOp is Load. + // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0), + // stencil(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0) + setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected); + setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 1, 0, &expected); + + glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f); + ASSERT_GL_NO_ERROR(); + + // Break the third render pass and verify the counters. + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize); + ASSERT_GL_NO_ERROR(); + EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected); + + // Clear stencil, but not depth buffer (loadOp S=CLEAR) + glClear(GL_STENCIL_BUFFER_BIT); + + // Fourth render pass: The depthLoadOp is Load and stencilLoadOp is Clear. + // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0), + // stencil(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0) + setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected); + setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 1, 0, &expected); + + glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f); + ASSERT_GL_NO_ERROR(); + + // Break the fourth render pass and verify the counters. + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize); + ASSERT_GL_NO_ERROR(); + EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected); +} + +// Ensures we use read-only depth layout when there is no write +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, ReadOnlyDepthBufferLayout) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + constexpr GLsizei kSize = 64; + + angle::VulkanPerfCounters expected; + + // Create depth only FBO and fill depth texture to leftHalf=0.0 and rightHalf=1.0. This should + // use writeable layout + expected.readOnlyDepthStencilRenderPasses = getPerfCounters().readOnlyDepthStencilRenderPasses; + + // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0), + // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0) + setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected); + setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected); + + GLTexture depthTexture; + glBindTexture(GL_TEXTURE_2D, depthTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 0, GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + GLFramebuffer depthOnlyFBO; + glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); + ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glViewport(0, 0, kSize / 2, kSize); + drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0f); + glViewport(kSize / 2, 0, kSize / 2, kSize); + drawQuad(redProgram, essl1_shaders::PositionAttrib(), 1.0f); + glViewport(0, 0, kSize, kSize); + ASSERT_GL_NO_ERROR(); + + // Because the layout counter is updated at end of renderpass, we need to issue a finish call + // here to end the renderpass. + glFinish(); + + uint64_t actualReadOnlyDepthStencilCount = getPerfCounters().readOnlyDepthStencilRenderPasses; + EXPECT_EQ(expected.readOnlyDepthStencilRenderPasses, actualReadOnlyDepthStencilCount); + EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected); + + // Create a color+depth FBO and use depth as read only. This should use read only layout + ++expected.readOnlyDepthStencilRenderPasses; + // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1), + // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0) + setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 0, 1, &expected); + setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected); + + GLTexture colorTexture; + glBindTexture(GL_TEXTURE_2D, colorTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + GLFramebuffer depthAndColorFBO; + glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + + // Clear color to blue and draw a green quad with depth=0.5 + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(GL_FALSE); + + angle::Vector4 clearColor = GLColor::blue.toNormalizedVector(); + glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f); ASSERT_GL_NO_ERROR(); // The pixel check will end renderpass. EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue); @@ -5140,7 +5419,8 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout) // Ensures depth/stencil is not loaded after storeOp=DONT_CARE due to optimization (as opposed to // invalidate) -TEST_P(VulkanPerformanceCounterTest, RenderPassAfterRenderPassWithoutDepthStencilWrite) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + RenderPassAfterRenderPassWithoutDepthStencilWrite) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -5676,7 +5956,7 @@ void main() GLsizei offset = 0; - uint64_t expectedShaderResourcesCacheMisses = 0; + uint64_t expectedUniformBuffersCacheMisses = 0; for (int iteration = 0; iteration < kIterations; ++iteration) { @@ -5696,15 +5976,15 @@ void main() // Capture the allocations counter after the first run. if (iteration == 0) { - expectedShaderResourcesCacheMisses = - getPerfCounters().shaderResourcesDescriptorSetCacheMisses; + expectedUniformBuffersCacheMisses = + getPerfCounters().uniformBuffersDescriptorSetCacheMisses; } } ASSERT_GL_NO_ERROR(); if (isFeatureEnabled(Feature::DescriptorSetCache)) { - EXPECT_GT(expectedShaderResourcesCacheMisses, 0u); + EXPECT_GT(expectedUniformBuffersCacheMisses, 0u); } // Verify correctness first. @@ -5722,9 +6002,9 @@ void main() if (isFeatureEnabled(Feature::DescriptorSetCache)) { // Check for unnecessary descriptor set allocations. - uint64_t actualShaderResourcesCacheMisses = - getPerfCounters().shaderResourcesDescriptorSetCacheMisses; - EXPECT_EQ(expectedShaderResourcesCacheMisses, actualShaderResourcesCacheMisses); + uint64_t actualUniformBuffersCacheMisses = + getPerfCounters().uniformBuffersDescriptorSetCacheMisses; + EXPECT_EQ(expectedUniformBuffersCacheMisses, actualUniformBuffersCacheMisses); } } @@ -5763,7 +6043,7 @@ precision mediump float; uniform block { uvec4 data; } ubo; -uniform uint expect; +uniform highp uint expect; uniform vec4 successOutput; out vec4 colorOut; void main() @@ -6008,7 +6288,7 @@ TEST_P(VulkanPerformanceCounterTest, BufferSubDataShouldNotTriggerSyncState_Copy } // Verifies that rendering to backbuffer discards depth/stencil. -TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthStencil) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, SwapShouldInvalidateDepthStencil) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -6892,7 +7172,7 @@ TEST_P(VulkanPerformanceCounterTest, DrawThenInceptionScissorClears) } // Test that color clears are respected after invalidate -TEST_P(VulkanPerformanceCounterTest, ColorClearAfterInvalidate) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, ColorClearAfterInvalidate) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -6955,7 +7235,7 @@ TEST_P(VulkanPerformanceCounterTest, ColorClearAfterInvalidate) } // Test that depth clears are picked up as loadOp even if a color blit is done in between. -TEST_P(VulkanPerformanceCounterTest, DepthClearThenColorBlitThenDraw) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, DepthClearThenColorBlitThenDraw) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -7276,9 +7556,10 @@ TEST_P(VulkanPerformanceCounterTest, VerifySubmitCounterForSwitchUserFBOToSystem expectedCommandQueueWaitSemaphoreCount); } -// Tests that PreferSubmitAtFBOBoundary feature works properly. Bind to different FBO and should -// trigger submit of previous FBO. In this specific test, we test bind to a new user FBO which we -// used to had a bug. +// Tests that PreferSubmitAtFBOBoundary feature works properly. Binding to a different FBO should +// trigger the submission of the previous FBO if enough workload has been accumulated. In this +// specific test, we test binding to a new user FBO after issuing the minimum amount of draw calls +// for submission. TEST_P(VulkanPerformanceCounterTest, VerifySubmitCounterForSwitchUserFBOToDirtyUserFBO) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -7287,18 +7568,25 @@ TEST_P(VulkanPerformanceCounterTest, VerifySubmitCounterForSwitchUserFBOToDirtyU uint64_t expectedCommandQueueWaitSemaphoreCount = getPerfCounters().commandQueueWaitSemaphoresTotal; - GLFramebuffer framebuffer; - GLTexture texture; - setupForColorOpsTest(&framebuffer, &texture); + GLFramebuffer framebuffer1; + GLTexture texture1; + setupForColorOpsTest(&framebuffer1, &texture1); - // Draw + // Issue the draws. In case of preference to submit at FBO boundary, there is a minimum render + // pass command count to submit. (Currently, the exception is if there is a clear or invalidate + // command at the boundary, or if there are no in-flight commands. In those cases, the minimum + // command count is ignored.) + constexpr uint32_t kMinCommandCountToSubmit = 32; ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + for (uint32_t i = 0; i < kMinCommandCountToSubmit; i++) + { + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + } ASSERT_GL_NO_ERROR(); if (hasPreferSubmitAtFBOBoundary()) { - // One submission coming from glBindFramebuffer and draw + // One submission coming from glBindFramebuffer and draw calls. ++expectedCommandQueueSubmitCount; // This submission should not wait for any semaphore. } @@ -7514,7 +7802,7 @@ void main() { ASSERT_GL_NO_ERROR(); - GLuint expectedCacheMisses = getPerfCounters().shaderResourcesDescriptorSetCacheMisses; + GLuint expectedCacheMisses = getPerfCounters().uniformBuffersDescriptorSetCacheMisses; GLuint totalAllocationsAtFirstProgram = getPerfCounters().descriptorSetAllocations; if (isFeatureEnabled(Feature::DescriptorSetCache)) { @@ -7532,7 +7820,7 @@ void main() { if (isFeatureEnabled(Feature::DescriptorSetCache)) { - GLuint actualCacheMisses = getPerfCounters().shaderResourcesDescriptorSetCacheMisses; + GLuint actualCacheMisses = getPerfCounters().uniformBuffersDescriptorSetCacheMisses; EXPECT_EQ(expectedCacheMisses, actualCacheMisses); } else @@ -7711,100 +7999,6 @@ TEST_P(VulkanPerformanceCounterTest, SetTextureSwizzleWithDifferentValueOnFBOAtt EXPECT_EQ(framebufferCacheSizeIncrease, expectedFramebufferCacheSizeIncrease); } -void VulkanPerformanceCounterTest::saveAndReloadBinary(GLProgram *original, GLProgram *reloaded) -{ - GLint programLength = 0; - GLint writtenLength = 0; - GLenum binaryFormat = 0; - - // Get the binary out of the program and delete it. - glGetProgramiv(*original, GL_PROGRAM_BINARY_LENGTH_OES, &programLength); - EXPECT_GL_NO_ERROR(); - - std::vector binary(programLength); - glGetProgramBinaryOES(*original, programLength, &writtenLength, &binaryFormat, binary.data()); - EXPECT_GL_NO_ERROR(); - - original->reset(); - - // Reload the binary into another program - reloaded->makeEmpty(); - glProgramBinaryOES(*reloaded, binaryFormat, binary.data(), writtenLength); - EXPECT_GL_NO_ERROR(); - - GLint linkStatus; - glGetProgramiv(*reloaded, GL_LINK_STATUS, &linkStatus); - EXPECT_NE(linkStatus, 0); -} - -void VulkanPerformanceCounterTest::testPipelineCacheIsWarm(GLProgram *program, GLColor color) -{ - glUseProgram(*program); - GLint colorUniformLocation = - glGetUniformLocation(*program, angle::essl1_shaders::ColorUniform()); - ASSERT_NE(-1, colorUniformLocation); - ASSERT_GL_NO_ERROR(); - - GLuint expectedCacheHits = getPerfCounters().pipelineCreationCacheHits + 1; - GLuint expectedCacheMisses = getPerfCounters().pipelineCreationCacheMisses; - - glUniform4fv(colorUniformLocation, 1, color.toNormalizedVector().data()); - drawQuad(*program, essl1_shaders::PositionAttrib(), 0.5f); - - EXPECT_EQ(getPerfCounters().pipelineCreationCacheHits, expectedCacheHits); - EXPECT_EQ(getPerfCounters().pipelineCreationCacheMisses, expectedCacheMisses); - - EXPECT_PIXEL_COLOR_EQ(0, 0, color); -} - -// Verifies that the pipeline cache is warmed up at link time with reasonable defaults. -TEST_P(VulkanPerformanceCounterTest, PipelineCacheIsWarmedUpAtLinkTime) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); - - // Test is only valid when pipeline creation feedback is available - ANGLE_SKIP_TEST_IF(!hasSupportsPipelineCreationFeedback() || !hasWarmUpPipelineCacheAtLink() || - !hasEffectivePipelineCacheSerialization()); - - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor()); - - testPipelineCacheIsWarm(&program, GLColor::red); -} - -// Verifies that the pipeline cache is reloaded correctly through glProgramBinary. -TEST_P(VulkanPerformanceCounterTest, PipelineCacheIsRestoredWithProgramBinary) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); - - // Test is only valid when pipeline creation feedback is available - ANGLE_SKIP_TEST_IF(!hasSupportsPipelineCreationFeedback() || !hasWarmUpPipelineCacheAtLink() || - !hasEffectivePipelineCacheSerialization()); - - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor()); - GLProgram reloadedProgram; - saveAndReloadBinary(&program, &reloadedProgram); - - testPipelineCacheIsWarm(&reloadedProgram, GLColor::green); -} - -// Verifies that the pipeline cache is reloaded correctly through glProgramBinary twice. -TEST_P(VulkanPerformanceCounterTest, PipelineCacheIsRestoredWithProgramBinaryTwice) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); - - // Test is only valid when pipeline creation feedback is available - ANGLE_SKIP_TEST_IF(!hasSupportsPipelineCreationFeedback() || !hasWarmUpPipelineCacheAtLink() || - !hasEffectivePipelineCacheSerialization()); - - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor()); - GLProgram reloadedProgram; - GLProgram twiceReloadedProgram; - saveAndReloadBinary(&program, &reloadedProgram); - saveAndReloadBinary(&reloadedProgram, &twiceReloadedProgram); - - testPipelineCacheIsWarm(&twiceReloadedProgram, GLColor::blue); -} - // Test calling glEGLImageTargetTexture2DOES repeatedly with same arguments will not leak // DescriptorSets. This is the same usage pattern surafceflinger is doing with notification shades // except with AHB. @@ -7976,73 +8170,6 @@ void main() EXPECT_EQ(0, shaderResourceDescriptorSetCacheTotalSizeIncrease); } -// Similar to CreateDestroyTextureDoesNotIncreaseDescriptporSetCache, but for uniform buffers. -TEST_P(VulkanPerformanceCounterTest, DestroyUniformBufferAlsoDestroyDescriptporSetCache) -{ - ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); - - const char *mkFS = R"(#version 300 es -precision highp float; -uniform uni { vec4 color; }; -out vec4 fragColor; -void main() -{ - fragColor = color; -})"; - ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), mkFS); - GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni"); - ASSERT_NE(uniformBufferIndex, -1); - - // Warm up. Make a draw to ensure other descriptorSets are created if needed. - GLBuffer intialBuffer; - glBindBuffer(GL_UNIFORM_BUFFER, intialBuffer); - std::vector initialData = {0.1, 0.2, 0.3, 0.4}; - glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * initialData.size(), initialData.data(), - GL_DYNAMIC_DRAW); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, intialBuffer); - glUniformBlockBinding(program, uniformBufferIndex, 0); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_NEAR(0, 0, initialData[0] * 255, initialData[1] * 255, initialData[2] * 255, - initialData[3] * 255, 1); - - // Use big buffer size to force it into individual bufferBlocks - constexpr GLsizei kBufferSize = 4 * 1024 * 1024; - GLint DescriptorSetCacheTotalSizeBefore = getPerfCounters().descriptorSetCacheTotalSize; - - // Create buffer and use it and then destroy it. Because buffers are big enough they should be - // in a different bufferBlock. DescriptorSet created due to these temporary buffer should be - // destroyed promptly. - constexpr int kBufferCount = 16; - for (int i = 0; i < kBufferCount; i++) - { - GLBuffer uniformBuffer; - glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer); - glBufferData(GL_UNIFORM_BUFFER, kBufferSize, nullptr, GL_DYNAMIC_DRAW); - float *ptr = reinterpret_cast( - glMapBufferRange(GL_UNIFORM_BUFFER, 0, kBufferSize, GL_MAP_WRITE_BIT)); - for (int j = 0; j < 4; j++) - { - ptr[j] = (float)(i * 4 + j) / 255.0f; - } - glUnmapBuffer(GL_UNIFORM_BUFFER); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer); - glUniformBlockBinding(program, uniformBufferIndex, 0); - glClear(GL_COLOR_BUFFER_BIT); - drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); - EXPECT_PIXEL_NEAR(0, 0, (i * 4), (i * 4 + 1), (i * 4 + 2), (i * 4 + 3), 1); - } - // Should trigger prune buffer call - swapBuffers(); - - GLint DescriptorSetCacheTotalSizeIncrease = - getPerfCounters().descriptorSetCacheTotalSize - DescriptorSetCacheTotalSizeBefore; - // We expect most of descriptorSet caches for temporary uniformBuffers gets destroyed. Give - // extra room in case a new descriptorSet is allocated due to a new driver uniform buffer gets - // allocated. - EXPECT_LT(DescriptorSetCacheTotalSizeIncrease, 2); -} - // Similar to CreateDestroyTextureDoesNotIncreaseDescriptporSetCache, but for atomic acounter // buffer. TEST_P(VulkanPerformanceCounterTest_ES31, DestroyAtomicCounterBufferAlsoDestroyDescriptporSetCache) @@ -8158,7 +8285,7 @@ outData = vec4(1.0, 1.0, 1.0, 1.0); // Test that post-render-pass-to-swapchain glFenceSync followed by eglSwapBuffers incurs only a // single submission. -TEST_P(VulkanPerformanceCounterTest, FenceThenSwapBuffers) +TEST_P(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, FenceThenSwapBuffers) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); @@ -8357,6 +8484,57 @@ TEST_P(VulkanPerformanceCounterTest, FBOChangeAndClearAndBackDoesNotBreakRenderP EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); } +// Test that just switching programs without breaking the renderpass +// doesn't cause updates to GraphicsDriverUniforms +TEST_P(VulkanPerformanceCounterTest, NoUpdatesToGraphicsDriverUniformsOnProgramChange) +{ + // Create 2 programs and switch between them + ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + + GLFramebuffer framebuffer; + GLTexture texture; + setupForColorOpsTest(&framebuffer, &texture); + + glUseProgram(program1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program1, essl1_shaders::PositionAttrib(), 0); + uint64_t program1Count = getPerfCounters().graphicsDriverUniformsUpdated; + + glUseProgram(program2); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program2, essl1_shaders::PositionAttrib(), 0); + uint64_t program2Count = getPerfCounters().graphicsDriverUniformsUpdated; + + // Verify vkCmdUpdatePushConstants perf counter + EXPECT_EQ(program1Count, program2Count); + + glUseProgram(program1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program1, essl1_shaders::PositionAttrib(), 0); + program1Count = getPerfCounters().graphicsDriverUniformsUpdated; + + // Verify vkCmdUpdatePushConstants perf counter + EXPECT_EQ(program1Count, program2Count); + + // Verify pixel color + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); + + // Now that we have broken the render pass expect a call to vkCmdUpdatePushConstants + // even if using the same program + glUseProgram(program1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + drawQuad(program1, essl1_shaders::PositionAttrib(), 0); + program1Count = getPerfCounters().graphicsDriverUniformsUpdated; + + // Verify vkCmdUpdatePushConstants perf counter + EXPECT_EQ(program1Count, program2Count + 1); +} + // This is test for optimization in vulkan backend. efootball_pes_2021 usage shows this usage // pattern and we expect implementation to reuse the storage for performance. TEST_P(VulkanPerformanceCounterTest, @@ -8435,49 +8613,1041 @@ TEST_P(VulkanPerformanceCounterTest, SubmittingOutsideCommandBufferAssertIsOpen) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } -// Verifies that clear followed by eglSwapBuffers() on multisampled FBO does not result -// extra resolve pass, if the surface is double-buffered and when the egl swap behavior -// is EGL_BUFFER_DESTROYED -TEST_P(VulkanPerformanceCounterTest_MSAA, SwapAfterClearOnMultisampledFBOShouldNotResolve) +// Demonstrate the WAW syncVal bug https://anglebug.com/400789178 +TEST_P(VulkanPerformanceCounterTest, DepthBufferWriteThenReadThenWriteInThreeRenderPasses) { - // Skip test if - // 1) the EGL Surface is single-buffered or - // 2) the EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED - EGLint renderBufferType; - eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(), EGL_RENDER_BUFFER, - &renderBufferType); - EGLint swapBehavior; - eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(), EGL_SWAP_BEHAVIOR, - &swapBehavior); - ANGLE_SKIP_TEST_IF( - !(renderBufferType == EGL_BACK_BUFFER && swapBehavior == EGL_BUFFER_DESTROYED)); + ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); - uint32_t expectedResolvesSubpass = getPerfCounters().swapchainResolveInSubpass; - uint32_t expectedResolvesOutside = getPerfCounters().swapchainResolveOutsideSubpass; - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - swapBuffers(); - EXPECT_EQ(getPerfCounters().swapchainResolveInSubpass, expectedResolvesSubpass); - EXPECT_EQ(getPerfCounters().swapchainResolveOutsideSubpass, expectedResolvesOutside); -} + constexpr GLsizei kWidth = 4; + constexpr GLsizei kHeight = 4; -// Test that swapchain does not get necessary recreation with 90 or 270 emulated pre-rotation -TEST_P(VulkanPerformanceCounterTest_Prerotation, swapchainCreateCounterTest) -{ - uint64_t expectedSwapchainCreateCounter = getPerfCounters().swapchainCreate; - for (uint32_t i = 0; i < 10; ++i) - { + GLTexture colorTexture1; + glBindTexture(GL_TEXTURE_2D, colorTexture1); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight); + + GLTexture colorTexture2; + glBindTexture(GL_TEXTURE_2D, colorTexture2); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight); + + GLRenderbuffer depthStencil; + glBindRenderbuffer(GL_RENDERBUFFER, depthStencil); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight); + + GLFramebuffer fbo1; + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture1, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencil); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencil); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glViewport(0, 0, kWidth, kHeight); + + GLFramebuffer fbo2; + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencil); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencil); + ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); + glViewport(0, 0, kWidth, kHeight); + + GLfloat depthValue = 0.0f; + // Draw to fbo1 with depth buffer write + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(depthValue * 0.5f + 0.5f); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), depthValue); + + // Draw to fbo2 with read only depth buffer + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glClear(GL_COLOR_BUFFER_BIT); + glDepthMask(GL_FALSE); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), depthValue); + + std::array attachments = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 2, attachments.data()); + + // Draw to fbo1 with depth buffer write + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glDepthMask(GL_TRUE); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), depthValue); + glFinish(); +} + +// Verifies that clear followed by eglSwapBuffers() on multisampled FBO does not result +// extra resolve pass, if the surface is double-buffered and when the egl swap behavior +// is EGL_BUFFER_DESTROYED +TEST_P(VulkanPerformanceCounterTest_MSAA, SwapAfterClearOnMultisampledFBOShouldNotResolve) +{ + // Skip test if + // 1) the EGL Surface is single-buffered or + // 2) the EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED + EGLint renderBufferType; + eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(), EGL_RENDER_BUFFER, + &renderBufferType); + EGLint swapBehavior; + eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(), EGL_SWAP_BEHAVIOR, + &swapBehavior); + ANGLE_SKIP_TEST_IF( + !(renderBufferType == EGL_BACK_BUFFER && swapBehavior == EGL_BUFFER_DESTROYED)); + + uint32_t expectedResolvesSubpass = getPerfCounters().swapchainResolveInSubpass; + uint32_t expectedResolvesOutside = getPerfCounters().swapchainResolveOutsideSubpass; + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + swapBuffers(); + EXPECT_EQ(getPerfCounters().swapchainResolveInSubpass, expectedResolvesSubpass); + EXPECT_EQ(getPerfCounters().swapchainResolveOutsideSubpass, expectedResolvesOutside); +} + +// MSAA draw and the blit that uses sub-pass resolve and then followed by masked clear +TEST_P(VulkanPerformanceCounterTest_MSAA, MultisampleDrawThenBlitThenMaskedClear) +{ + // http://anglebug.com/40096654 + ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES()); + + ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); + ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green()); + ANGLE_GL_PROGRAM(drawBlue, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue()); + + constexpr GLsizei kWidth = 256; + constexpr GLsizei kHeight = 256; + // Setup framebufferResolved and clear to black + GLRenderbuffer colorResolved; + glBindRenderbuffer(GL_RENDERBUFFER, colorResolved); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight); + GLFramebuffer framebufferResolved; + glBindFramebuffer(GL_FRAMEBUFFER, framebufferResolved); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorResolved); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_PIXEL_COLOR_EQ(255, 0, GLColor::black); + + uint64_t renderPassesBefore = getPerfCounters().renderPasses; + + // Setup framebufferMS, clear color/depth attachments, and draw quad + GLsizei kSamples = 2; + GLRenderbuffer depthMS; + glBindRenderbuffer(GL_RENDERBUFFER, depthMS); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, kSamples, GL_DEPTH_COMPONENT24, + kSamples * kWidth, kSamples * kHeight); + GLRenderbuffer colorMS; + glBindRenderbuffer(GL_RENDERBUFFER, colorMS); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, kSamples, GL_RGBA8, kSamples * kWidth, + kSamples * kHeight); + GLFramebuffer framebufferMS; + glBindFramebuffer(GL_FRAMEBUFFER, framebufferMS); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorMS); + // Clear depth buffer to 0.5 and color to blue. + glClearColor(0.0f, 0.0f, 1.0f, 1.0f); + GLfloat depthValue = 0.0f; + glClearDepthf(depthValue * 0.5f + 0.5f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValue); + + // Resolve the color buffer to make sure the above draw worked correctly, which in turn implies + // that the multi-sampled depth clear worked. + glBindFramebuffer(GL_FRAMEBUFFER, framebufferResolved); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferMS); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + // Blit should reuse the render pass of draw. + EXPECT_EQ(1u, getPerfCounters().renderPasses - renderPassesBefore); + + // Bind framebufferMS and do masked clear of blue channel + glBindFramebuffer(GL_FRAMEBUFFER, framebufferMS); + glClearColor(0.0f, 0.0f, 1.0f, 1.0f); + glColorMask(false, false, true, false); + glClear(GL_COLOR_BUFFER_BIT); + + // Masked clear should not reuse the previous render pass. + EXPECT_EQ(2u, getPerfCounters().renderPasses - renderPassesBefore); + + // Now verify the data + glBindFramebuffer(GL_FRAMEBUFFER, framebufferResolved); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferMS); + // This should use resolveColorWithCommand + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferResolved); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan); + EXPECT_PIXEL_COLOR_EQ(255, 255, GLColor::blue); + EXPECT_EQ(2u, getPerfCounters().renderPasses - renderPassesBefore); +} + +// Test that swapchain does not get necessary recreation with 90 or 270 emulated pre-rotation +TEST_P(VulkanPerformanceCounterTest_Prerotation, swapchainCreateCounterTest) +{ + uint64_t expectedSwapchainCreateCounter = getPerfCounters().swapchainCreate; + for (uint32_t i = 0; i < 10; ++i) + { swapBuffers(); } EXPECT_EQ(getPerfCounters().swapchainCreate, expectedSwapchainCreateCounter); } +// Test that fully overwriting a sampled texture does not close the render pass due to texture +// ghosting. +TEST_P(VulkanPerformanceCounterTest, TextureOverwriteDoesNotBreakRenderPass) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); + glUseProgram(program); + GLint textureLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform()); + ASSERT_NE(-1, textureLoc); + + constexpr uint32_t kWidth = 16; + constexpr uint32_t kHeight = 24; + + const std::vector texDataRed(kWidth * kHeight, GLColor::red); + const std::vector texDataGreen(kWidth * kHeight, GLColor::green); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + texDataRed.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + + uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1; + + // Draw multiple times, completely overwriting the texture each time. + for (uint32_t i = 0; i < 10; ++i) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + i % 2 == 0 ? texDataGreen.data() : texDataRed.data()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + } + + // There should be only one render pass. + uint64_t actualRenderPassCount = getPerfCounters().renderPasses; + EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount); + + // For completeness, verify rendering results. + EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); +} + +// Demonstrate usage pattern seeing in asphalt_9 and ensure we use one render pass for maximum +// performance +TEST_P(VulkanPerformanceCounterTest, ClearThenBlitThenDraw) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + GLProgram drawRed, drawGreen; + drawRed.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawGreen.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + + constexpr uint32_t kWidth = 4; + constexpr uint32_t kHeight = 4; + + // Initialize two FBOs with red color and depthValue + GLTexture colorTextures[2]; + GLRenderbuffer depthStencils[2]; + GLFramebuffer fbos[2]; + GLfloat depthValue = 0.0f; + GLuint stencilValue = 0x55; + for (size_t i = 0; i < 2; i++) + { + setupColorTextureAndDepthBuffer(colorTextures[i], depthStencils[i], GL_DEPTH24_STENCIL8, + kWidth, kHeight); + setupFBO(colorTextures[i], depthStencils[i], depthStencils[i], fbos[i], kWidth, kHeight); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glStencilMask(0xFF); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, stencilValue, 0xFF); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValue); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + } + + uint64_t renderPassesBefore = getPerfCounters().renderPasses; + + // Clear + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearDepthf(1.0f); + glClearStencil(0x00); + glDepthMask(GL_TRUE); + glStencilMask(0xFF); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + // Blit depth buffer from fbo1 to fbo0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT, + GL_NEAREST); + + // Verify depth value + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValue); + + // There should be only one render pass. + EXPECT_EQ(1u, getPerfCounters().renderPasses - renderPassesBefore); + + // verify stencil results. + glClear(GL_COLOR_BUFFER_BIT); + drawQuadToVerifyStencilValue(drawGreen, 0x00); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); +} + +// Similar to ClearThenBlitThenDraw, but with scissor changes +TEST_P(VulkanPerformanceCounterTest, ScissoredDrawThenBlitThenDraw) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + GLProgram drawRed, drawGreen, drawBlue; + drawRed.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawGreen.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawBlue.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + + constexpr uint32_t kWidth = 64; + constexpr uint32_t kHeight = 64; + + // Initialize two FBOs with red color and depth and stencil value + GLTexture colorTextures[2]; + GLRenderbuffer depthStencils[2]; + GLFramebuffer fbos[2]; + std::array depthValues = {0.0f, 0.5f}; + GLuint stencilValue = 0x55; + for (size_t i = 0; i < 2; i++) + { + setupColorTextureAndDepthBuffer(colorTextures[i], depthStencils[i], GL_DEPTH24_STENCIL8, + kWidth, kHeight); + setupFBO(colorTextures[i], depthStencils[i], depthStencils[i], fbos[i], kWidth, kHeight); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glStencilMask(0xFF); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, stencilValue, 0xFF); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValues[i]); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + } + + uint64_t renderPassesBefore = getPerfCounters().renderPasses; + + // Draw with viewport/scissor set to small rect. It should fail depth test. + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + glDepthFunc(GL_LESS); + glViewport(kWidth / 2, kHeight / 2, 1, 1); + glEnable(GL_SCISSOR_TEST); + glScissor(kWidth / 4, kHeight / 4, kWidth / 2, kHeight / 2); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), depthValues[0] + 0.1f); + + // Mid render pass blit depth/stencil buffer from fbo1 to fbo0 with scissor disabled. It should + // cover th whole framebuffer. + glDisable(GL_SCISSOR_TEST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT, + GL_NEAREST); + + // Draw again without modify any viewport/scissor state. It should still fail depth test. + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), depthValues[1] + 0.1f); + + // end render pass. + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + // There should be only one render pass. + EXPECT_EQ(1u, getPerfCounters().renderPasses - renderPassesBefore); + + // Verify depth value. It should contain fbos[1]'s depth value if blit successful. + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glViewport(0, 0, kWidth, kHeight); + glClear(GL_COLOR_BUFFER_BIT); + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValues[1]); + // verify stencil results. + glClear(GL_COLOR_BUFFER_BIT); + drawQuadToVerifyStencilValue(drawGreen, stencilValue); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); +} + +// Test interaction between transform feedback and mid render pass blit +TEST_P(VulkanPerformanceCounterTest, DrawThenBlitThenDrawWithXFB) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + GLProgram drawRed; + drawRed.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + + constexpr uint32_t kWidth = 4; + constexpr uint32_t kHeight = 4; + + // Initialize two FBOs with red color and depthValue + GLTexture colorTextures[2]; + GLRenderbuffer depthStencils[2]; + GLFramebuffer fbos[2]; + GLfloat depthValue = 0.0f; + GLuint stencilValue = 0x55; + for (size_t i = 0; i < 2; i++) + { + setupColorTextureAndDepthBuffer(colorTextures[i], depthStencils[i], GL_DEPTH24_STENCIL8, + kWidth, kHeight); + setupFBO(colorTextures[i], depthStencils[i], depthStencils[i], fbos[i], kWidth, kHeight); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glStencilMask(0xFF); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, stencilValue, 0xFF); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValue); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + } + + uint64_t renderPassesBefore = getPerfCounters().renderPasses; + + std::vector tfVaryings = {"gl_Position"}; + ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(xfbProgram, essl1_shaders::vs::Simple(), + essl1_shaders::fs::Red(), tfVaryings, + GL_INTERLEAVED_ATTRIBS); + glUseProgram(xfbProgram); + + GLBuffer xfbBuffer; + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STATIC_DRAW); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer); + glBeginTransformFeedback(GL_TRIANGLES); + + // Draw + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + drawQuad(xfbProgram, essl1_shaders::PositionAttrib(), depthValue); + + // Blit depth buffer from fbo1 to fbo0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + drawQuad(xfbProgram, essl1_shaders::PositionAttrib(), depthValue); + + glEndTransformFeedback(); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); + EXPECT_GL_NO_ERROR(); + + // XFB should prevent ANGLE to use mid render pass blit + EXPECT_LT(1u, getPerfCounters().renderPasses - renderPassesBefore); + + // Ensure that triangles were actually captured correctly. + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer); + // We have two quads + GLuint quadCount = 2; + // Each quad have two triangles, each triangle have 3 vertices, each vertex have 4 floats. + GLuint vertexCount = 2 * 3 * 4; + void *mappedBuffer = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, + quadCount * vertexCount * sizeof(float), GL_MAP_READ_BIT); + ASSERT_NE(nullptr, mappedBuffer); + + const GLfloat expect[] = { + // clang-format off + -1.0f, 1.0f, depthValue, 1.0f, + -1.0f, -1.0f, depthValue, 1.0f, + 1.0f, -1.0f, depthValue, 1.0f, + + -1.0f, 1.0f, depthValue, 1.0f, + 1.0f, -1.0f, depthValue, 1.0f, + 1.0f, 1.0f, depthValue, 1.0f, + // clang-format on + }; + + float *mappedFloats = static_cast(mappedBuffer); + for (uint32_t quadIndex = 0; quadIndex < quadCount; quadIndex++) + { + for (uint32_t i = 0; i < vertexCount; ++i) + { + EXPECT_EQ(*mappedFloats, expect[i]); + mappedFloats++; + } + } + glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); +} + +// Test interaction between occlusion query and mid render pass blit +TEST_P(VulkanPerformanceCounterTest, DrawThenBlitThenDrawWithQuery) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + GLProgram drawRed, drawGreen; + drawRed.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + drawGreen.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + + constexpr uint32_t kWidth = 4; + constexpr uint32_t kHeight = 4; + + // Initialize two FBOs + GLTexture colorTextures[2]; + GLRenderbuffer depthStencils[2]; + GLFramebuffer fbos[2]; + std::array depthValues = {0.0f, 0.5}; + for (size_t i = 0; i < 2; i++) + { + setupColorTextureAndDepthBuffer(colorTextures[i], depthStencils[i], GL_DEPTH24_STENCIL8, + kWidth, kHeight); + setupFBO(colorTextures[i], depthStencils[i], depthStencils[i], fbos[i], kWidth, kHeight); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), depthValues[i]); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + } + + uint64_t renderPassesBefore = getPerfCounters().renderPasses; + + GLQueryEXT query; + glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query); + + // Draw with depthValue+0.1f, this should fail depth test. + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + glDepthFunc(GL_LESS); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValues[0] + 0.1f); + + // Blit depth buffer from fbo1 to fbo0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT, + GL_NEAREST); + + // Draw with depthValue+0.2f, this should still fail depth test if blit successful. + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + glDepthFunc(GL_GREATER); + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValues[0] + 0.2f); + + glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); + EXPECT_GL_NO_ERROR(); + // Query should prevent ANGLE from using mid render pass blit + EXPECT_LT(1u, getPerfCounters().renderPasses - renderPassesBefore); + + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + + GLuint result = GL_TRUE; + glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result); + EXPECT_GL_FALSE(result); +} + +// Test draw with same GL state after mid render pass blit works properly +TEST_P(VulkanPerformanceCounterTest, DrawThenBlitThenDrawWithSameProgram) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + + auto quadVertices = GetQuadVertices(); + GLBuffer vertexBuffer; + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]), + quadVertices.data(), GL_STATIC_DRAW); + + GLProgram drawRed; + drawRed.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + const GLint positionLocation = glGetAttribLocation(drawRed, essl1_shaders::PositionAttrib()); + ASSERT_NE(-1, positionLocation); + glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(positionLocation); + + GLProgram drawGreen; + drawGreen.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + ASSERT(positionLocation == glGetAttribLocation(drawGreen, essl1_shaders::PositionAttrib())); + + constexpr uint32_t kWidth = 4; + constexpr uint32_t kHeight = 4; + + // Initialize two FBOs with red color and depthValue + GLTexture colorTextures[2]; + GLRenderbuffer depthStencils[2]; + GLFramebuffer fbos[2]; + std::array depthValues = {0.0f, 0.5}; + for (size_t i = 0; i < 2; i++) + { + setupColorTextureAndDepthBuffer(colorTextures[i], depthStencils[i], GL_DEPTH24_STENCIL8, + kWidth, kHeight); + setupFBO(colorTextures[i], depthStencils[i], depthStencils[i], fbos[i], kWidth, kHeight); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glUseProgram(drawRed); + drawWithDepthValue(quadVertices, 0.75f); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red); + } + + uint64_t renderPassesBefore = getPerfCounters().renderPasses; + + // Draw with depthValue+0.1f, this should fail depth test. + glUseProgram(drawGreen); + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + glDepthFunc(GL_LESS); + drawWithDepthValue(quadVertices, depthValues[0] + 0.1f); + + // Blit depth buffer from fbo1 to fbo0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT, + GL_NEAREST); + + // Draw with depthValues[1] - 0.1f, this should still pass depth test if blit successful, but + // fail if blit is unsuccessful. + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + drawWithDepthValue(quadVertices, depthValues[1] - 0.1f); + + // ANGLE should use mid render pass blit + EXPECT_EQ(1u, getPerfCounters().renderPasses - renderPassesBefore); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); +} + +// Verifies whether, when GL_RASTERIZER_DISCARD is enabled and no glClear is issued, +// the Vulkan color attachment uses VK_ATTACHMENT_LOAD_OP_NONE and VK_ATTACHMENT_STORE_OP_NONE, +// as no actual rendering or clearing is expected. +TEST_P(VulkanPerformanceCounterTest_RGBSurface, UnrenderedSurfaceShouldNotClear) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!hasLoadOpNoneSupport()); + + // Use default EGL window, display, surface, and context. + EGLWindow *window = getEGLWindow(); + EGLDisplay dpy = window->getDisplay(); + EGLSurface surface = window->getSurface(); + EGLContext context = window->getContext(); + + // Make the default context current. + EXPECT_TRUE(eglMakeCurrent(dpy, surface, surface, context)); + ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; + + angle::VulkanPerfCounters expected; + // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1) + setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected); + + glEnable(GL_RASTERIZER_DISCARD); + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); + glDisable(GL_RASTERIZER_DISCARD); + + // Validate no GL errors and check performance counters. + ASSERT_GL_NO_ERROR(); + EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses); + glFinish(); + EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected); + + // Restore original context (optional if already using default). + eglMakeCurrent(dpy, window->getSurface(), window->getSurface(), window->getContext()); +} + +class VulkanPerformanceCounterTest_TileMemory : public VulkanPerformanceCounterTest +{ + protected: + VulkanPerformanceCounterTest_TileMemory() : VulkanPerformanceCounterTest() + { + setWindowWidth(64); + setWindowHeight(64); + setConfigDepthBits(24); + } + + void setupPrograms() + { + drawRed.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + ASSERT_TRUE(drawRed.valid()); + drawGreen.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + ASSERT_TRUE(drawGreen.valid()); + drawBlue.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); + ASSERT_TRUE(drawBlue.valid()); + } + + void setupColorTexturesAndDepthBuffer(GLTexture &colorTexture1, + GLTexture &colorTexture2, + GLRenderbuffer &depthStencil, + GLenum depthStencilFormat, + GLsizei width, + GLsizei height) + { + glBindTexture(GL_TEXTURE_2D, colorTexture1); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height); + + glBindTexture(GL_TEXTURE_2D, colorTexture2); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height); + + glBindRenderbuffer(GL_RENDERBUFFER, depthStencil); + glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height); + } + + void drawQuadToVerifyDepthStencilValue(GLfloat depthValue, GLint stencilValue) + { + glStencilMask(0x0); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, stencilValue, 0xFF); + + GLfloat kErrorTolerance = 0.01f; + // Don't modify depth buffer + glDepthMask(GL_FALSE); + glEnable(GL_DEPTH_TEST); + // This should pass + glDepthFunc(GL_LESS); + drawQuad(drawGreen, essl1_shaders::PositionAttrib(), depthValue - kErrorTolerance); + // This should fail + drawQuad(drawRed, essl1_shaders::PositionAttrib(), depthValue + kErrorTolerance); + glDepthFunc(GL_GREATER); + drawQuad(drawBlue, essl1_shaders::PositionAttrib(), depthValue - kErrorTolerance); + } + + void oneDepthStencilBufferUsedInOneRenderPassAndThenInvalidate(GLenum depthStencilFormat) + { + setupPrograms(); + + constexpr GLsizei kWidth = 4; + constexpr GLsizei kHeight = 4; + bool hasStencil = depthStencilFormat == GL_DEPTH24_STENCIL8 ? true : false; + + uint64_t tileMemoryImageCountBefore = getPerfCounters().tileMemoryImages; + + GLTexture colorTexture; + GLRenderbuffer depthStencil; + setupColorTextureAndDepthBuffer(colorTexture, depthStencil, depthStencilFormat, kWidth, + kHeight); + GLFramebuffer fbo; + if (hasStencil) + { + setupFBO(colorTexture, depthStencil, depthStencil, fbo, kWidth, kHeight); + } + else + { + setupFBO(colorTexture, depthStencil, 0, fbo, kWidth, kHeight); + } + + uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1; + + GLfloat depthValue = 0.0f; + // Clear color/depth/stencil buffers + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(depthValue * 0.5f + 0.5f); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + if (hasStencil) + { + drawQuadToVerifyDepthStencilValue(depthValue, 0x55); + } + else + { + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValue); + } + + std::array attachments = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + glInvalidateFramebuffer(GL_FRAMEBUFFER, attachments.size(), attachments.data()); + EXPECT_GL_NO_ERROR(); + + // There should be only one render pass. + uint64_t actualRenderPassCount = getPerfCounters().renderPasses; + EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount); + // For completeness, verify rendering results. + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + + EXPECT_EQ(1u, getPerfCounters().tileMemoryImages - tileMemoryImageCountBefore); + EXPECT_EQ(0u, getPerfCounters().fallbackFromTileMemory); + } + + GLProgram drawRed; + GLProgram drawGreen; + GLProgram drawBlue; +}; + +// Test that depth buffer of window surface should use tile memory since EGL spec says data is +// invalid after swapBuffer. +TEST_P(VulkanPerformanceCounterTest_TileMemory, SurfaceDepthStencilBufferShouldUseTileMemory) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + glUseProgram(drawColor); + GLint colorUniformLocation = + glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform()); + ASSERT_NE(colorUniformLocation, -1); + + // Clear color to red and the depth/stencil buffer to 1.0 + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(0.5f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDepthRangef(-1, 1); + EXPECT_GL_NO_ERROR(); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f); + drawQuad(drawColor, essl1_shaders::PositionAttrib(), -1.0f); + + swapBuffers(); + + // depthStencil should be using tile memory + EXPECT_EQ(1u, getPerfCounters().tileMemoryImages); + EXPECT_EQ(0u, getPerfCounters().fallbackFromTileMemory); +} + +// Test that depth buffer of FBO should use tile memory if invalidateFramebuffer is called. +TEST_P(VulkanPerformanceCounterTest_TileMemory, OneDSBufferUsedInOneRenderPassThenInvalidate_D24S8) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + oneDepthStencilBufferUsedInOneRenderPassAndThenInvalidate(GL_DEPTH24_STENCIL8); +} + +// Test that depth buffer of FBO should use tile memory if invalidateFramebuffer is called. +TEST_P(VulkanPerformanceCounterTest_TileMemory, OneDSBufferUsedInOneRenderPassThenInvalidate_D24) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + oneDepthStencilBufferUsedInOneRenderPassAndThenInvalidate(GL_DEPTH_COMPONENT24); +} + +// Test that depth buffer of FBO should use tile memory if invalidateFramebuffer is called. +TEST_P(VulkanPerformanceCounterTest_TileMemory, OneDSBufferUsedInOneRenderPassThenInvalidate_D16) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + oneDepthStencilBufferUsedInOneRenderPassAndThenInvalidate(GL_DEPTH_COMPONENT16); +} + +// depth buffer of FBO should use tile memory if was valid in first render pass but invalidate in +// second render pass. +TEST_P(VulkanPerformanceCounterTest_TileMemory, OneDSBufferUsedInTwoRenderPassesThenInvalidate) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + setupPrograms(); + + // Surface's depth buffer should also using tile memory. + uint64_t expectedTileMemoryImageCount = getPerfCounters().tileMemoryImages + 1; + + constexpr GLsizei kWidth = 4; + constexpr GLsizei kHeight = 4; + + GLTexture colorTexture1, colorTexture2; + GLRenderbuffer depthStencil; + setupColorTexturesAndDepthBuffer(colorTexture1, colorTexture2, depthStencil, + GL_DEPTH24_STENCIL8, kWidth, kHeight); + + // Setup two fbos share the same depth stencil buffer + GLFramebuffer fbo1, fbo2; + setupFBO(colorTexture1, depthStencil, depthStencil, fbo1, kWidth, kHeight); + setupFBO(colorTexture2, depthStencil, depthStencil, fbo2, kWidth, kHeight); + + uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 2; + + GLfloat depthValue = 0.0f; + // draw to fbo1, keep depth buffer valid + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(depthValue * 0.5f + 0.5f); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + drawQuadToVerifyDepthStencilValue(depthValue, 0x55); + + // draw to fbo2 without modifying depth buffer, and invalidate depth buffer + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glClear(GL_COLOR_BUFFER_BIT); + drawQuadToVerifyDepthStencilValue(depthValue, 0x55); + std::array attachments = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 2, attachments.data()); + EXPECT_GL_NO_ERROR(); + + // There should be two render pass. + EXPECT_EQ(expectedRenderPassCount, getPerfCounters().renderPasses); + + // For completeness, verify rendering results. + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + + // depthStencil should also be using tile memory + EXPECT_EQ(expectedTileMemoryImageCount, getPerfCounters().tileMemoryImages); + EXPECT_EQ(0u, getPerfCounters().fallbackFromTileMemory); +} + +// Similar to OneDepthStencilRenderBufferUsedInTwoRenderPasses, but repeat. This will create many +// render passes that uses depthStencil buffers which could allocate in tile memory heap and exceed +// heap capacity and fail. They may fallback to regular memory but should still work. +TEST_P(VulkanPerformanceCounterTest_TileMemory, ManyDSBufferUsedInOneSubmit) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + setupPrograms(); + + constexpr GLsizei kWidth = 1024; + constexpr GLsizei kHeight = 1024; + constexpr size_t kRepeatCount = 10; + + std::array colorTextures1, colorTextures2; + std::array depthStencils; + std::array fbos1, fbos2; + + // Surface's depth buffer should also using tile memory. + uint64_t expectedMaxTileMemoryImageCount = getPerfCounters().tileMemoryImages + kRepeatCount; + uint64_t expectedMinTileMemoryImageCount = getPerfCounters().tileMemoryImages + 1; + uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 2 * kRepeatCount; + + std::array attachments = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + GLfloat depthValue = 0.0f; + for (size_t i = 0; i < kRepeatCount; i++) + { + setupColorTexturesAndDepthBuffer(colorTextures1[i], colorTextures2[i], depthStencils[i], + GL_DEPTH24_STENCIL8, kWidth, kHeight); + setupFBO(colorTextures1[i], depthStencils[i], depthStencils[i], fbos1[i], kWidth, kHeight); + setupFBO(colorTextures2[i], depthStencils[i], depthStencils[i], fbos2[i], kWidth, kHeight); + + // Clear color/depth/stencil buffer + glBindFramebuffer(GL_FRAMEBUFFER, fbos1[i]); + glDepthMask(GL_TRUE); + glStencilMask(0xFF); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(depthValue * 0.5f + 0.5f); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + drawQuadToVerifyDepthStencilValue(depthValue, 0x55); + + // draw to fbo2 without modifying depth buffer, and invalidate depth buffer + glBindFramebuffer(GL_FRAMEBUFFER, fbos2[i]); + glClear(GL_COLOR_BUFFER_BIT); + drawQuadToVerifyDepthStencilValue(depthValue, 0x55); + glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, attachments.size(), attachments.data()); + } + + // There should be two render pass for every kRepeatCount loop. + EXPECT_EQ(expectedRenderPassCount, getPerfCounters().renderPasses); + // depthStencil should also be using tile memory + EXPECT_LE(getPerfCounters().tileMemoryImages, expectedMaxTileMemoryImageCount); + EXPECT_GE(getPerfCounters().tileMemoryImages, expectedMinTileMemoryImageCount); + + // For completeness, verify rendering results. + for (size_t i = 0; i < kRepeatCount; i++) + { + glBindFramebuffer(GL_FRAMEBUFFER, fbos1[i]); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + glBindFramebuffer(GL_FRAMEBUFFER, fbos2[i]); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + } + EXPECT_EQ(0u, getPerfCounters().fallbackFromTileMemory); +} + +// Test that depth buffer of FBO that uses tile memory will switch back to regular memory if it has +// valid data across submissions +TEST_P(VulkanPerformanceCounterTest_TileMemory, OneDSBufferUsedInTwoRenderPassesWithTwoSubmission) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + setupPrograms(); + + uint64_t tileMemoryStartingImageCount = getPerfCounters().tileMemoryImages; + + constexpr GLsizei kWidth = 4; + constexpr GLsizei kHeight = 4; + + GLTexture colorTexture1, colorTexture2; + GLRenderbuffer depthStencil; + setupColorTexturesAndDepthBuffer(colorTexture1, colorTexture2, depthStencil, + GL_DEPTH24_STENCIL8, kWidth, kHeight); + + // Setup two fbos share the same depth stencil buffer + GLFramebuffer fbo1, fbo2; + setupFBO(colorTexture1, depthStencil, depthStencil, fbo1, kWidth, kHeight); + setupFBO(colorTexture2, depthStencil, depthStencil, fbo2, kWidth, kHeight); + + GLfloat depthValue = 0.0f; + // draw to fbo1, keep depth buffer valid + glBindFramebuffer(GL_FRAMEBUFFER, fbo1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(depthValue * 0.5f + 0.5f); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + drawQuadToVerifyDepthStencilValue(depthValue, 0x55); + EXPECT_GL_NO_ERROR(); + // depthStencil should also be using tile memory + EXPECT_EQ(tileMemoryStartingImageCount + 1, getPerfCounters().tileMemoryImages); + EXPECT_EQ(0u, getPerfCounters().fallbackFromTileMemory); + // Submit + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + // depthStencil should not be using tile memory + EXPECT_EQ(tileMemoryStartingImageCount, getPerfCounters().tileMemoryImages); + EXPECT_EQ(1u, getPerfCounters().fallbackFromTileMemory); + + // draw to fbo2 without modifying depth buffer + glBindFramebuffer(GL_FRAMEBUFFER, fbo2); + glClear(GL_COLOR_BUFFER_BIT); + // Verify depth has correct value + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValue); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + glClear(GL_COLOR_BUFFER_BIT); + // Verify stencil has correct value + drawQuadToVerifyStencilValue(drawGreen, 0x55); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); +} + +// Test that depth buffer of surface that uses tile memory will switch back to regular memory if it +// has valid data across submissions +TEST_P(VulkanPerformanceCounterTest_TileMemory, + SurfaceDepthBufferUsedInTwoRenderPassesWithTwoSubmission) +{ + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName)); + ANGLE_SKIP_TEST_IF(!isFeatureEnabled(Feature::SimulateTileMemoryForTesting) && + !isFeatureEnabled(Feature::SupportsTileMemoryHeap)); + + setupPrograms(); + + constexpr GLsizei kWidth = 4; + constexpr GLsizei kHeight = 4; + + GLfloat depthValue = 0.0f; + // draw to depth depth buffer and keep data valid + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearDepthf(depthValue * 0.5f + 0.5f); + glClearStencil(0x55); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValue); + EXPECT_GL_NO_ERROR(); + // depthStencil should also be using tile memory + EXPECT_EQ(1u, getPerfCounters().tileMemoryImages); + EXPECT_EQ(0u, getPerfCounters().fallbackFromTileMemory); + // Submit + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); + // depthStencil should not be using tile memory + EXPECT_EQ(0u, getPerfCounters().tileMemoryImages); + EXPECT_EQ(1u, getPerfCounters().fallbackFromTileMemory); + + // draw again without modifying depth buffer + glClear(GL_COLOR_BUFFER_BIT); + // Verify depth buffer has correct value + drawQuadToVerifyDepthValue(drawGreen, drawRed, depthValue); + EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest); ANGLE_INSTANTIATE_TEST( VulkanPerformanceCounterTest, ES3_VULKAN(), ES3_VULKAN().enable(Feature::PadBuffersToMaxVertexAttribStride), - ES3_VULKAN_SWIFTSHADER().disable(Feature::PreferMonolithicPipelinesOverLibraries), ES3_VULKAN_SWIFTSHADER().enable(Feature::PreferMonolithicPipelinesOverLibraries), ES3_VULKAN_SWIFTSHADER() .enable(Feature::PreferMonolithicPipelinesOverLibraries) @@ -8486,9 +9656,21 @@ ANGLE_INSTANTIATE_TEST( .enable(Feature::PreferMonolithicPipelinesOverLibraries) .disable(Feature::MergeProgramPipelineCachesToGlobalCache)); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + VulkanPerformanceCounterTest_DepthStencilLoadStoreOps); +ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps, + ES3_VULKAN(), + ES3_VULKAN_SWIFTSHADER()); + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_ES31); ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + VulkanPerformanceCounterTest_DepthStencilLoadStoreOps_ES31); +ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_DepthStencilLoadStoreOps_ES31, + ES31_VULKAN(), + ES31_VULKAN_SWIFTSHADER()); + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_MSAA); ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_MSAA, ES3_VULKAN(), @@ -8498,14 +9680,34 @@ ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_MSAA, ES3_VULKAN().enable(Feature::EmulatedPrerotation270)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_Prerotation); -ANGLE_INSTANTIATE_TEST( - VulkanPerformanceCounterTest_Prerotation, - ES3_VULKAN().enable(Feature::PerFrameWindowSizeQuery), - ES3_VULKAN().enable(Feature::EmulatedPrerotation90).enable(Feature::PerFrameWindowSizeQuery), - ES3_VULKAN().enable(Feature::EmulatedPrerotation180).enable(Feature::PerFrameWindowSizeQuery), - ES3_VULKAN().enable(Feature::EmulatedPrerotation270).enable(Feature::PerFrameWindowSizeQuery)); +ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_Prerotation, + ES3_VULKAN(), + ES3_VULKAN().enable(Feature::EmulatedPrerotation90), + ES3_VULKAN().enable(Feature::EmulatedPrerotation180), + ES3_VULKAN().enable(Feature::EmulatedPrerotation270)); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_SingleBuffer); ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_SingleBuffer, ES3_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_RGBSurface); +ANGLE_INSTANTIATE_TEST( + VulkanPerformanceCounterTest_RGBSurface, + ES3_VULKAN(), + ES3_VULKAN().enable(Feature::PadBuffersToMaxVertexAttribStride), + ES3_VULKAN_SWIFTSHADER().enable(Feature::PreferMonolithicPipelinesOverLibraries), + ES3_VULKAN_SWIFTSHADER() + .enable(Feature::PreferMonolithicPipelinesOverLibraries) + .enable(Feature::SlowDownMonolithicPipelineCreationForTesting), + ES3_VULKAN_SWIFTSHADER() + .enable(Feature::PreferMonolithicPipelinesOverLibraries) + .disable(Feature::MergeProgramPipelineCachesToGlobalCache)); + +// Enable SimulateTileMemoryForTesting feature to get some test coverage on bots. Note that if both +// SimulateTileMemoryForTesting and SupportsTileMemoryHeap are enabled, SupportsTileMemoryHeap will +// take precedence. +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_TileMemory); +ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_TileMemory, + ES3_VULKAN(), + ES3_VULKAN().enable(Feature::SimulateTileMemoryForTesting), + ES3_VULKAN_SWIFTSHADER().enable(Feature::SimulateTileMemoryForTesting)); } // anonymous namespace diff --git a/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp b/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp index 78cd14f361f..e5575b62f82 100644 --- a/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp +++ b/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp @@ -7,6 +7,10 @@ // Tests to validate our Vulkan dynamic uniform updates are working as expected. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "libANGLE/Context.h" #include "libANGLE/Display.h" #include "libANGLE/angletypes.h" @@ -619,6 +623,7 @@ TEST_P(VulkanUniformUpdatesTest, MultipleProgramsShareDescriptors) } ANGLE_INSTANTIATE_TEST(VulkanUniformUpdatesTest, ES2_VULKAN(), ES3_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanUniformUpdatesTest); // This test tries to test uniform data update while switching between PPO and monolithic program. // The uniform data update occurred on one should carry over to the other. Also buffers are hacked @@ -757,5 +762,6 @@ void main() } ANGLE_INSTANTIATE_TEST(PipelineProgramUniformUpdatesTest, ES31_VULKAN()); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PipelineProgramUniformUpdatesTest); } // anonymous namespace diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp index 1c41ba50aa2..cc1a12f2617 100644 --- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp +++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp @@ -6,6 +6,10 @@ // WebGLCompatibilityTest.cpp : Tests of the GL_ANGLE_webgl_compatibility extension. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "common/mathutil.h" @@ -65,6 +69,13 @@ class WebGLCompatibilityTest : public ANGLETest<> setConfigBlueBits(8); setConfigAlphaBits(8); setWebGLCompatibilityEnabled(true); + setExtensionsEnabled(false); + + mFloatTextureSamplingProgram = 0; + mFloatTextureSamplingProgram_texLocation = -1; + mFloatTextureSamplingProgram_subtractorLocation = -1; + mUniformColorRenderingProgram = 0; + mUniformColorRenderingProgram_colorUniformLocation = -1; } template @@ -109,8 +120,21 @@ void main() } })"; - ANGLE_GL_PROGRAM(samplingProgram, kVS, kFS); - glUseProgram(samplingProgram); + if (mFloatTextureSamplingProgram == 0) + { + mFloatTextureSamplingProgram = CompileProgram(kVS, kFS); + ASSERT(mFloatTextureSamplingProgram != 0); + ASSERT_GL_NO_ERROR(); + + mFloatTextureSamplingProgram_texLocation = + glGetUniformLocation(mFloatTextureSamplingProgram, "tex"); + ASSERT(mFloatTextureSamplingProgram_texLocation != -1); + mFloatTextureSamplingProgram_subtractorLocation = + glGetUniformLocation(mFloatTextureSamplingProgram, "subtractor"); + ASSERT(mFloatTextureSamplingProgram_subtractorLocation != -1); + ASSERT_GL_NO_ERROR(); + } + glUseProgram(mFloatTextureSamplingProgram); // Need RGBA8 renderbuffers for enough precision on the readback if (IsGLExtensionRequestable("GL_OES_rgb8_rgba8")) @@ -163,16 +187,16 @@ void main() } ASSERT_GL_NO_ERROR(); - glUniform1i(glGetUniformLocation(samplingProgram, "tex"), 0); - glUniform4fv(glGetUniformLocation(samplingProgram, "subtractor"), 1, floatData); + glUniform1i(mFloatTextureSamplingProgram_texLocation, 0); + glUniform4fv(mFloatTextureSamplingProgram_subtractorLocation, 1, floatData); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - drawQuad(samplingProgram, "position", 0.5f, 1.0f, true); + drawQuad(mFloatTextureSamplingProgram, "position", 0.5f, 1.0f, true); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - drawQuad(samplingProgram, "position", 0.5f, 1.0f, true); + drawQuad(mFloatTextureSamplingProgram, "position", 0.5f, 1.0f, true); if (linearSamplingEnabled) { @@ -201,14 +225,23 @@ void main() } ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, framebufferStatus); - ANGLE_GL_PROGRAM(renderingProgram, essl1_shaders::vs::Simple(), - essl1_shaders::fs::UniformColor()); - glUseProgram(renderingProgram); + if (mUniformColorRenderingProgram == 0) + { + mUniformColorRenderingProgram = + CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); + ASSERT(mUniformColorRenderingProgram != 0); + ASSERT_GL_NO_ERROR(); - glUniform4fv(glGetUniformLocation(renderingProgram, essl1_shaders::ColorUniform()), 1, - floatData); + mUniformColorRenderingProgram_colorUniformLocation = + glGetUniformLocation(mUniformColorRenderingProgram, essl1_shaders::ColorUniform()); + ASSERT(mUniformColorRenderingProgram_colorUniformLocation != -1); + ASSERT_GL_NO_ERROR(); + } + glUseProgram(mUniformColorRenderingProgram); - drawQuad(renderingProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); + glUniform4fv(mUniformColorRenderingProgram_colorUniformLocation, 1, floatData); + + drawQuad(mUniformColorRenderingProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); EXPECT_PIXEL_COLOR32F_NEAR( 0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f); @@ -311,11 +344,60 @@ void main() GLenum expectedError, const char *explanation); void testCompressedTexImage(GLenum format); + + private: + GLuint mFloatTextureSamplingProgram; + GLint mFloatTextureSamplingProgram_texLocation; + GLint mFloatTextureSamplingProgram_subtractorLocation; + + GLuint mUniformColorRenderingProgram; + GLint mUniformColorRenderingProgram_colorUniformLocation; }; class WebGL2CompatibilityTest : public WebGLCompatibilityTest {}; +class HardenedContextTest : public ANGLETest<> +{ + protected: + EGLContext setupHardenedContext() + { + EGLWindow *window = getEGLWindow(); + const EGLDisplay display = window->getDisplay(); + const EGLConfig config = window->getConfig(); + const EGLSurface surface = window->getSurface(); + const EGLint contextAttributes[] = { + EGL_CONTEXT_MAJOR_VERSION_KHR, + GetParam().majorVersion, + EGL_CONTEXT_MINOR_VERSION_KHR, + GetParam().minorVersion, + EGL_CONTEXT_HARDENED_ANGLE, + EGL_TRUE, + EGL_NONE, + }; + + mOriginalContext = eglGetCurrentContext(); + + EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes); + EXPECT_NE(context, EGL_NO_CONTEXT); + eglMakeCurrent(display, surface, surface, context); + return context; + } + + void destroyHardenedContext(EGLContext context) + { + EGLWindow *window = getEGLWindow(); + const EGLDisplay display = window->getDisplay(); + const EGLSurface surface = window->getSurface(); + + eglMakeCurrent(display, surface, surface, mOriginalContext); + eglDestroyContext(display, context); + } + + private: + EGLContext mOriginalContext = EGL_NO_CONTEXT; +}; + // Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so // the GL extension should always be present TEST_P(WebGLCompatibilityTest, ExtensionStringExposed) @@ -791,7 +873,6 @@ TEST_P(WebGLCompatibilityTest, EnableQueryExtensions) { EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean")); EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_disjoint_timer_query")); - EXPECT_FALSE(IsGLExtensionEnabled("GL_CHROMIUM_sync_query")); // This extensions become core in in ES3/WebGL2. ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); @@ -810,9 +891,6 @@ TEST_P(WebGLCompatibilityTest, EnableQueryExtensions) glQueryCounterEXT(GL_TIMESTAMP_EXT, badQuery); EXPECT_GL_ERROR(GL_INVALID_OPERATION); - glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, badQuery); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); - if (IsGLExtensionRequestable("GL_EXT_occlusion_query_boolean")) { glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean"); @@ -838,17 +916,6 @@ TEST_P(WebGLCompatibilityTest, EnableQueryExtensions) glQueryCounterEXT(query2, GL_TIMESTAMP_EXT); EXPECT_GL_NO_ERROR(); } - - if (IsGLExtensionRequestable("GL_CHROMIUM_sync_query")) - { - glRequestExtensionANGLE("GL_CHROMIUM_sync_query"); - EXPECT_GL_NO_ERROR(); - - GLQueryEXT query; - glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query); - glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); - EXPECT_GL_NO_ERROR(); - } } // Test enabling the GL_ANGLE_framebuffer_multisample extension @@ -1029,14 +1096,6 @@ TEST_P(WebGLCompatibilityTest, EnableTextureRectangle) glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_NO_ERROR(); - - glDisableExtensionANGLE("GL_ANGLE_texture_rectangle"); - EXPECT_GL_NO_ERROR(); - - EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")); - - glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture); - EXPECT_GL_ERROR(GL_INVALID_ENUM); } } @@ -2064,7 +2123,7 @@ TEST_P(WebGLCompatibilityTest, DrawBuffersIndexedGetIndexedParameter) ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_OES_draw_buffers_indexed")); GLint value; - GLboolean data[4]; + GLint data[4]; glGetIntegeri_v(GL_BLEND_EQUATION_RGB, 0, &value); EXPECT_GL_ERROR(GL_INVALID_ENUM); @@ -2078,8 +2137,8 @@ TEST_P(WebGLCompatibilityTest, DrawBuffersIndexedGetIndexedParameter) EXPECT_GL_ERROR(GL_INVALID_ENUM); glGetIntegeri_v(GL_BLEND_DST_ALPHA, 0, &value); EXPECT_GL_ERROR(GL_INVALID_ENUM); - glGetBooleani_v(GL_COLOR_WRITEMASK, 0, data); - EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glGetIntegeri_v(GL_COLOR_WRITEMASK, 0, data); + EXPECT_GL_ERROR(GL_INVALID_ENUM); glRequestExtensionANGLE("GL_OES_draw_buffers_indexed"); EXPECT_GL_NO_ERROR(); @@ -2112,7 +2171,7 @@ TEST_P(WebGLCompatibilityTest, DrawBuffersIndexedGetIndexedParameter) glGetIntegeri_v(GL_BLEND_DST_ALPHA, 0, &value); EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_ZERO, value); - glGetBooleani_v(GL_COLOR_WRITEMASK, 0, data); + glGetIntegeri_v(GL_COLOR_WRITEMASK, 0, data); EXPECT_GL_NO_ERROR(); EXPECT_EQ(true, data[0]); EXPECT_EQ(false, data[1]); @@ -2249,48 +2308,93 @@ oo = 1.0; EXPECT_EQ(0u, program); } -// Tests bindAttribLocations for reserved prefixes and length limits +// Tests bindAttribLocation for reserved prefixes and length limits TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation) { - constexpr int maxLocStringLength = 256; - const std::string tooLongString(maxLocStringLength + 1, '_'); + // A program must exist for binding attribute locations + ANGLE_GL_PROGRAM(p, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glBindAttribLocation(0, 0, "_webgl_var"); + glBindAttribLocation(p, 0, "gl_attr"); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + glBindAttribLocation(p, 0, "webgl_attr"); EXPECT_GL_ERROR(GL_INVALID_OPERATION); - glBindAttribLocation(0, 0, static_cast(tooLongString.c_str())); + glBindAttribLocation(p, 0, "_webgl_attr"); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + const int maxStringLength = getClientMajorVersion() < 3 ? 256 : 1024; + const std::string tooLongString(maxStringLength + 1, '_'); + glBindAttribLocation(p, 0, static_cast(tooLongString.c_str())); EXPECT_GL_ERROR(GL_INVALID_VALUE); } -// Tests getAttribLocation for reserved prefixes -TEST_P(WebGLCompatibilityTest, GetAttribLocationNameLimitation) +// Tests getAttribLocation for reserved prefixes and length limits +TEST_P(WebGLCompatibilityTest, GetAttribLocationLimitation) { - GLint attrLocation; + // A program must exist for querying attribute locations + ANGLE_GL_PROGRAM(p, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - attrLocation = glGetAttribLocation(0, "gl_attr"); + GLint location = -2; + + location = glGetAttribLocation(p, "gl_attr"); EXPECT_GL_NO_ERROR(); - EXPECT_EQ(-1, attrLocation); + EXPECT_EQ(-1, location); - attrLocation = glGetAttribLocation(0, "webgl_attr"); + location = glGetAttribLocation(p, "webgl_attr"); EXPECT_GL_NO_ERROR(); - EXPECT_EQ(-1, attrLocation); + EXPECT_EQ(-1, location); - attrLocation = glGetAttribLocation(0, "_webgl_attr"); + location = glGetAttribLocation(p, "_webgl_attr"); EXPECT_GL_NO_ERROR(); - EXPECT_EQ(-1, attrLocation); + EXPECT_EQ(-1, location); + + const int maxStringLength = getClientMajorVersion() < 3 ? 256 : 1024; + const std::string tooLongString(maxStringLength + 1, '_'); + + location = glGetAttribLocation(p, static_cast(tooLongString.c_str())); + EXPECT_GL_ERROR(GL_INVALID_VALUE); + EXPECT_EQ(-1, location); } -// Tests getAttribLocation for length limits -TEST_P(WebGLCompatibilityTest, GetAttribLocationLengthLimitation) +// Tests bindUniformLocation for reserved prefixes +TEST_P(WebGLCompatibilityTest, BindUniformLocationLimitation) { - constexpr int maxLocStringLength = 256; - const std::string tooLongString(maxLocStringLength + 1, '_'); + ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location")); - glGetAttribLocation(0, static_cast(tooLongString.c_str())); + // A program must exist for binding uniform locations + ANGLE_GL_PROGRAM(p, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - EXPECT_GL_ERROR(GL_INVALID_VALUE); + glBindUniformLocationCHROMIUM(p, 0, "gl_var"); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glBindUniformLocationCHROMIUM(p, 0, "webgl_var"); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + glBindUniformLocationCHROMIUM(p, 0, "_webgl_var"); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + +// Tests getUniformLocation for reserved prefixes +TEST_P(WebGLCompatibilityTest, GetUniformLocationLimitation) +{ + // A program must exist for querying uniform locations + ANGLE_GL_PROGRAM(p, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + + GLint location = -2; + + location = glGetUniformLocation(p, "gl_var"); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(-1, location); + + location = glGetUniformLocation(p, "webgl_var"); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(-1, location); + + location = glGetUniformLocation(p, "_webgl_var"); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(-1, location); } // Test that having no attributes with a zero divisor is valid in WebGL2 @@ -5280,10 +5384,9 @@ TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionLossyDecode) // This is an implementation-defined limit - crbug.com/1220237 . TEST_P(WebGLCompatibilityTest, ValidateArraySizes) { - // Note: on macOS with ANGLE's OpenGL backend, getting anywhere - // close to this limit causes pathologically slow shader - // compilation in the driver. For the "ok" case, therefore, use a - // fairly small array. + // Note: on macOS/Intel with ANGLE's OpenGL backend, loops are not used to initialize arrays, so + // getting anywhere close to this limit results in gigantic shaders that are too slow to + // compile. For the "ok" case, therefore, use a fairly small array. constexpr char kVSArrayOK[] = R"(varying vec4 color; const int array_size = 500; @@ -5344,10 +5447,9 @@ void main() // This is an implementation-defined limit - crbug.com/1220237 . TEST_P(WebGLCompatibilityTest, ValidateStructSizes) { - // Note: on macOS with ANGLE's OpenGL backend, getting anywhere - // close to this limit causes pathologically slow shader - // compilation in the driver. For this reason, only perform a - // negative test. + // Note: on macOS/Intel with ANGLE's OpenGL backend, loops are not used to initialize arrays, so + // getting anywhere close to this limit results in gigantic shaders that are too slow to + // compile. For this reason, only perform a negative test. constexpr char kFSStructTooLarge[] = R"(precision mediump float; struct Light { @@ -5737,6 +5839,33 @@ TEST_P(WebGL2CompatibilityTest, TransformFeedbackDoubleBinding) EXPECT_GL_ERROR(GL_INVALID_OPERATION); } +// Writing to the contents of a currently active transform feedback buffer is invalid +TEST_P(WebGL2CompatibilityTest, TransformFeedbackBufferModification) +{ + constexpr char kVS[] = R"(attribute float a; varying float b; void main() { b = a; })"; + constexpr char kFS[] = R"(void main(){})"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + static const char *varyings[] = {"b"}; + glTransformFeedbackVaryings(program, 1, varyings, GL_SEPARATE_ATTRIBS); + glLinkProgram(program); + glUseProgram(program); + ASSERT_GL_NO_ERROR(); + + // Bind the transform feedback varyings to non-overlapping regions of the same buffer. + GLBuffer buffer; + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 4); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 8, nullptr, GL_STATIC_DRAW); + glBeginTransformFeedback(GL_POINTS); + ASSERT_GL_NO_ERROR(); + + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 8, nullptr, GL_STATIC_DRAW); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); + + constexpr uint8_t data[8] = {0}; + glBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 8, data); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + // Check the return type of a given parameter upon getting the active uniforms. TEST_P(WebGL2CompatibilityTest, UniformVariablesReturnTypes) { @@ -5807,7 +5936,7 @@ TEST_P(WebGL2CompatibilityTest, RenderToLevelsOfSampledTexture) } // Reject attempts to allocate too-large variables in shaders. -// This is an implementation-defined limit - crbug.com/1220237 . +// This is an implementation-defined limit - http://crbug.com/40056230. TEST_P(WebGL2CompatibilityTest, ValidateTypeSizes) { constexpr char kFSArrayBlockTooLarge[] = R"(#version 300 es @@ -5832,8 +5961,38 @@ void main() EXPECT_EQ(0u, program); } +// Similar to WebGL2CompatibilityTest.ValidateTypeSizes, but ensure the same validation is done in +// non-webgl contexts with the EGL_CONTEXT_HARDENED_ANGLE flag. +TEST_P(HardenedContextTest, ValidateTypeSizes) +{ + constexpr char kFSArrayBlockTooLarge[] = R"(#version 300 es +precision mediump float; +// 1 + the maximum size this implementation allows. +uniform LargeArrayBlock { + vec4 large_array[134217729]; +}; + +out vec4 out_FragColor; + +void main() +{ + if (large_array[1].x == 2.0) + out_FragColor = vec4(0.0, 1.0, 0.0, 1.0); + else + out_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} +)"; + + EGLContext hardenedContext = setupHardenedContext(); + + GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFSArrayBlockTooLarge); + EXPECT_EQ(0u, program); + + destroyHardenedContext(hardenedContext); +} + // Ensure that new type size validation code added for -// crbug.com/1220237 does not crash. +// http://crbug.com/40056230 does not crash. TEST_P(WebGL2CompatibilityTest, ValidatingTypeSizesShouldNotCrash) { constexpr char kFS1[] = R"(#version 300 es @@ -6844,8 +7003,39 @@ void main() } } +// Tests that indexing with primitive restart index produces error, even +// if it's done after toggling GL_PRIMITIVE_RESTART_FIXED_INDEX. +// If there is MAX_ELEMENT_INDEX, it is smaller or equal than primitive +// restart index 2^32 - 1 for GLuint. +TEST_P(WebGL2CompatibilityTest, PrimitiveRestartIndexAfterToggleIsError) +{ + constexpr char kVS[] = "void main() { gl_Position = vec4(0); }"; + constexpr char kFS[] = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"; + ANGLE_GL_PROGRAM(program, kVS, kFS); + glUseProgram(program); + ASSERT_GL_NO_ERROR(); + std::vector indices(1); + indices[0] = 0xFFFFFFFFu; + GLBuffer indexBuffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), &indices[0], + GL_STATIC_DRAW); + EXPECT_GL_NO_ERROR(); + // Primitive restart works, no-op draw. + glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + glDrawElements(GL_POINTS, indices.size(), GL_UNSIGNED_INT, 0); + EXPECT_GL_NO_ERROR(); + // This is being tested: ensure that any cached state keys on PRIMITIVE_RESTART_FIXED_INDEX. + glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + glDrawElements(GL_POINTS, indices.size(), GL_UNSIGNED_INT, 0); + EXPECT_GL_ERROR(GL_INVALID_OPERATION); +} + ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WebGLCompatibilityTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2CompatibilityTest); ANGLE_INSTANTIATE_TEST_ES3(WebGL2CompatibilityTest); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HardenedContextTest); +ANGLE_INSTANTIATE_TEST_ES3(HardenedContextTest); } // namespace angle diff --git a/src/tests/gl_tests/WebGLCompressedTextureAvailabilityTest.cpp b/src/tests/gl_tests/WebGLCompressedTextureAvailabilityTest.cpp index 056ebe560b4..c6c3edd4cc4 100644 --- a/src/tests/gl_tests/WebGLCompressedTextureAvailabilityTest.cpp +++ b/src/tests/gl_tests/WebGLCompressedTextureAvailabilityTest.cpp @@ -18,7 +18,11 @@ namespace class WebGLCompressedTextureAvailabilityTest : public ANGLETest<> { public: - WebGLCompressedTextureAvailabilityTest() { setWebGLCompatibilityEnabled(true); } + WebGLCompressedTextureAvailabilityTest() + { + setWebGLCompatibilityEnabled(true); + setExtensionsEnabled(false); + } }; const char kDXT1[] = "GL_EXT_texture_compression_dxt1"; diff --git a/src/tests/gl_tests/gles1/DrawTextureTest.cpp b/src/tests/gl_tests/gles1/DrawTextureTest.cpp index bdb6ec57929..68721d087b9 100644 --- a/src/tests/gl_tests/gles1/DrawTextureTest.cpp +++ b/src/tests/gl_tests/gles1/DrawTextureTest.cpp @@ -339,4 +339,314 @@ TEST_P(DrawTextureTest, DrawWithTexCoordPtrThenDisableTexture2DAndDrawAnother) kColorCornerTR); } +// Tests that vertex and tex coord pointers are used correctly. +// Draw same non-zero texture twice with same vertex and tex coord pointers, but do not disable +// texture. +TEST_P(DrawTextureTest, DrawNonZeroSameTexWithSameVertexPtrWithoutDisabledTexture2D) +{ + // Set up texture with four colors; one color per corner to verify if the texture will be + // uploaded with appropriate vertex attributes. + std::vector textureColors = {GLColor::red, GLColor::yellow, GLColor::green, + GLColor::blue}; + GLTexture tex2D; + glBindTexture(GL_TEXTURE_2D, tex2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureColors.data()); + + // Set up vertex and texture coordinate pointers. + std::vector vertexPtrData = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f}; + std::vector texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData.data()); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data()); + + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // Bind tex2D and draw. + // ----------------------- + // | Green | Blue | + // | Red | Yellow | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex2D); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); + + // Bind tex2D and draw again. Expect the vertex attributes remain. + // ----------------------- + // | Green | Blue | + // | Red | Yellow | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex2D); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); +} + +// Tests that vertex and tex coord pointers are used correctly. +// Draw same non-zero texture twice with different vertex pointer, but do not disable texture. +TEST_P(DrawTextureTest, DrawNonZeroSameTexWithDifferentVertexPtrWithoutDisabledTexture2D) +{ + // Set up texture with four colors; one color per corner to verify if the texture will be + // uploaded with appropriate vertex attributes. + std::vector textureColors = {GLColor::red, GLColor::yellow, GLColor::green, + GLColor::blue}; + GLTexture tex2D; + glBindTexture(GL_TEXTURE_2D, tex2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureColors.data()); + + // Set up vertex and texture coordinate pointers. + std::vector vertexPtrData_1 = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f}; + std::vector texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData_1.data()); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data()); + + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // Bind tex2D and draw. + // ----------------------- + // | Green | Blue | + // | Red | Yellow | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex2D); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); + + // Change vertex data. + std::vector vertexPtrData_2 = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData_2.data()); + + // Bind tex2D and draw. + // ----------------------- + // | Yellow | Blue | + // | Red | Green | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex2D); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); +} + +// Test that vertex and tex coord pointers are used correctly. +// Draw two different non-zero textures with different vertex pointer, but do not disable texture. +TEST_P(DrawTextureTest, DrawNonZeroTwoTexWithDifferentVertexPtrWithoutDisableTexture2D) +{ + // Set up texture with four colors; one color per corner to verify if the texture will be + // uploaded with appropriate vertex attributes. + std::vector textureColors_1 = {GLColor::red, GLColor::yellow, GLColor::green, + GLColor::blue}; + GLTexture tex2D_1; + glBindTexture(GL_TEXTURE_2D, tex2D_1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureColors_1.data()); + + // Set up vertex and texture coordinate pointers. + std::vector vertexPtrData_1 = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f}; + std::vector texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData_1.data()); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data()); + + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // Bind tex2D and draw. + // ----------------------- + // | Green | Blue | + // | Red | Yellow | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); + + // Change texture to bind. + std::vector textureColors_2 = {GLColor::magenta, GLColor::transparentBlack, + GLColor::white, GLColor::cyan}; + GLTexture tex2D_2; + glBindTexture(GL_TEXTURE_2D, tex2D_2); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureColors_2.data()); + + // Change vertex data. + std::vector vertexPtrData_2 = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData_2.data()); + + // Bind tex2D and draw. + // ----------------------------------- + // | TransparentBlack | Cyan | + // | Magenta | White | + // ----------------------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::magenta); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::white); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::transparentBlack); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::cyan); +} + +// Tests that vertex and tex coord pointers are used correctly. +// Draw zero texture first then draw tex2D with same vertex and tex coord pointers, but do not +// disable texture. +TEST_P(DrawTextureTest, DrawZeroTexWithSameVertexPtrWithoutDisableTexture2D) +{ + // Set up texture with four colors; one color per corner to verify if the texture will be + // uploaded with appropriate vertex attributes. + std::vector textureColors = {GLColor::red, GLColor::yellow, GLColor::green, + GLColor::blue}; + GLTexture tex2D; + glBindTexture(GL_TEXTURE_2D, tex2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureColors.data()); + + // Set up vertex and texture coordinate pointers. + std::vector vertexPtrData = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f}; + std::vector texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData.data()); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data()); + + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // Bind zero texture and draw. + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, 0); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + + // Bind tex2D and draw. Expect the vertex attributes remain. + // ----------------------- + // | Green | Blue | + // | Red | Yellow | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex2D); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); +} + +// Tests that vertex and tex coord pointers are used correctly. +// Draw zero texture first then draw tex2D with different vertex pointers, but do not disable +// texture. +TEST_P(DrawTextureTest, DrawZeroTexWithDifferentVertexPtrWithoutDisableTexture2D) +{ + // Set up texture with four colors; one color per corner to verify if the texture will be + // uploaded with appropriate vertex attributes. + std::vector textureColors = {GLColor::red, GLColor::yellow, GLColor::green, + GLColor::blue}; + GLTexture tex2D; + glBindTexture(GL_TEXTURE_2D, tex2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + textureColors.data()); + + // Set up vertex and texture coordinate pointers. + std::vector vertexPtrData_1 = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f}; + std::vector texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData_1.data()); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data()); + + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // Bind zero texture and draw. + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, 0); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + + // Change vertex data. + std::vector vertexPtrData_2 = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; + glVertexPointer(2, GL_FLOAT, 0, vertexPtrData_2.data()); + + // Bind tex2D and draw. + // ----------------------- + // | Yellow | Blue | + // | Red | Green | + // ----------------------- + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex2D); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::red); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, GLColor::green); + EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::yellow); + EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, + GLColor::blue); +} + ANGLE_INSTANTIATE_TEST_ES1(DrawTextureTest); diff --git a/src/tests/gl_tests/gles1/FramebufferObjectTest.cpp b/src/tests/gl_tests/gles1/FramebufferObjectTest.cpp index e32464d6dce..27d163bee5c 100644 --- a/src/tests/gl_tests/gles1/FramebufferObjectTest.cpp +++ b/src/tests/gl_tests/gles1/FramebufferObjectTest.cpp @@ -40,6 +40,8 @@ class FramebufferObjectTest : public ANGLETest<> // Checks that framebuffer object can be used without GL errors. TEST_P(FramebufferObjectTest, FramebufferObject) { + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_framebuffer_object")); + GLuint fboId; GLint params; @@ -56,7 +58,7 @@ TEST_P(FramebufferObjectTest, FramebufferObject) GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, ¶ms); EXPECT_GL_NO_ERROR(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebufferOES(GL_FRAMEBUFFER, 0); glDeleteFramebuffersOES(1, &fboId); EXPECT_GL_NO_ERROR(); } @@ -64,21 +66,25 @@ TEST_P(FramebufferObjectTest, FramebufferObject) // Checks that texture object can be bound for framebuffer object. TEST_P(FramebufferObjectTest, TextureObject) { + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_framebuffer_object")); + GLuint fboId; - glGenFramebuffers(1, &fboId); - glBindFramebuffer(GL_FRAMEBUFFER, fboId); + glGenFramebuffersOES(1, &fboId); + glBindFramebufferOES(GL_FRAMEBUFFER, fboId); glFramebufferTexture2DOES(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture->get(), 0); EXPECT_GL_NO_ERROR(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fboId); + glBindFramebufferOES(GL_FRAMEBUFFER, 0); + glDeleteFramebuffersOES(1, &fboId); } // Checks different formats for a texture object bound to a framebuffer object. TEST_P(FramebufferObjectTest, TextureObjectDifferentFormats) { + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_framebuffer_object")); + // http://anglebug.com/42264178 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL()); @@ -120,8 +126,8 @@ TEST_P(FramebufferObjectTest, RenderbufferObject) GLuint rboId; GLint params; - glGenFramebuffers(1, &fboId); - glBindFramebuffer(GL_FRAMEBUFFER, fboId); + glGenFramebuffersOES(1, &fboId); + glBindFramebufferOES(GL_FRAMEBUFFER, fboId); glGenRenderbuffersOES(1, &rboId); EXPECT_GL_NO_ERROR(); @@ -143,8 +149,8 @@ TEST_P(FramebufferObjectTest, RenderbufferObject) glGetRenderbufferParameterivOES(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, ¶ms); EXPECT_GL_NO_ERROR(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fboId); + glBindFramebufferOES(GL_FRAMEBUFFER, 0); + glDeleteFramebuffersOES(1, &fboId); glDeleteRenderbuffersOES(1, &rboId); EXPECT_GL_NO_ERROR(); } @@ -158,8 +164,8 @@ TEST_P(FramebufferObjectTest, RGBA8Renderbuffer) GLuint fbo; GLuint rbo; - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glGenFramebuffersOES(1, &fbo); + glBindFramebufferOES(GL_FRAMEBUFFER, fbo); glGenRenderbuffersOES(1, &rbo); EXPECT_GL_NO_ERROR(); @@ -178,8 +184,8 @@ TEST_P(FramebufferObjectTest, RGBA8Renderbuffer) EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::white); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fbo); + glBindFramebufferOES(GL_FRAMEBUFFER, 0); + glDeleteFramebuffersOES(1, &fbo); glDeleteRenderbuffersOES(1, &rbo); EXPECT_GL_NO_ERROR(); } @@ -194,8 +200,8 @@ TEST_P(FramebufferObjectTest, RGB8AndRGBA8Renderbuffers) GLuint fbo; GLuint rbo[2]; - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glGenFramebuffersOES(1, &fbo); + glBindFramebufferOES(GL_FRAMEBUFFER, fbo); glGenRenderbuffersOES(2, rbo); EXPECT_GL_NO_ERROR(); @@ -222,8 +228,8 @@ TEST_P(FramebufferObjectTest, RGB8AndRGBA8Renderbuffers) glClear(GL_COLOR_BUFFER_BIT); EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::magenta); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fbo); + glBindFramebufferOES(GL_FRAMEBUFFER, 0); + glDeleteFramebuffersOES(1, &fbo); glDeleteRenderbuffersOES(2, rbo); EXPECT_GL_NO_ERROR(); } @@ -231,6 +237,8 @@ TEST_P(FramebufferObjectTest, RGB8AndRGBA8Renderbuffers) // Checks that generateMipmap can be called without GL errors. TEST_P(FramebufferObjectTest, GenerateMipmap) { + ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_framebuffer_object")); + constexpr uint32_t kSize = 32; std::vector pixelData(kSize * kSize * 4, 0); diff --git a/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp b/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp index b1ecbdfe39c..c575474bad9 100644 --- a/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp +++ b/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp @@ -6,6 +6,10 @@ // MatrixBuiltinsTest.cpp: Tests basic usage of builtin matrix operations. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/gles1/TextureParameterTest.cpp b/src/tests/gl_tests/gles1/TextureParameterTest.cpp index 4aa5b8a8d89..5a19d79374a 100644 --- a/src/tests/gl_tests/gles1/TextureParameterTest.cpp +++ b/src/tests/gl_tests/gles1/TextureParameterTest.cpp @@ -6,6 +6,10 @@ // TextureParameterTest.cpp: Tests GLES1-specific usage of glTexParameter. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gl_tests/gles1/VertexPointerTest.cpp b/src/tests/gl_tests/gles1/VertexPointerTest.cpp index 9ac1b8edb41..ee113ab840f 100644 --- a/src/tests/gl_tests/gles1/VertexPointerTest.cpp +++ b/src/tests/gl_tests/gles1/VertexPointerTest.cpp @@ -6,6 +6,10 @@ // VertexPointerTest.cpp: Tests basic usage of built-in vertex attributes of GLES1. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/gles1_conformance_tests/PrimtestTests.cpp b/src/tests/gles1_conformance_tests/PrimtestTests.cpp index 0a22bb97142..922a68a639d 100644 --- a/src/tests/gles1_conformance_tests/PrimtestTests.cpp +++ b/src/tests/gles1_conformance_tests/PrimtestTests.cpp @@ -7,6 +7,10 @@ // GLES1 conformance primtest tests. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GLES/gl.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/perf_tests/ANGLEComputeTestCL.cpp b/src/tests/perf_tests/ANGLEComputeTestCL.cpp index e7d1d20c3a3..df903f197c8 100644 --- a/src/tests/perf_tests/ANGLEComputeTestCL.cpp +++ b/src/tests/perf_tests/ANGLEComputeTestCL.cpp @@ -82,6 +82,8 @@ void ANGLEComputeTestCL::updatePerfCounters() { uint32_t counter = iter.first; std::vector &samples = iter.second.samples; + ASSERT(perfData[counter].group == 0); + ASSERT(perfData[counter].counter == counter); samples.push_back(perfData[counter].value); } } diff --git a/src/tests/perf_tests/ANGLEPerfTest.cpp b/src/tests/perf_tests/ANGLEPerfTest.cpp index e4d62a8c919..144cd6f0c27 100644 --- a/src/tests/perf_tests/ANGLEPerfTest.cpp +++ b/src/tests/perf_tests/ANGLEPerfTest.cpp @@ -7,6 +7,10 @@ // Base class for google test performance tests // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "ANGLEPerfTest.h" #if defined(ANGLE_PLATFORM_ANDROID) @@ -33,6 +37,7 @@ #include #include +#include #include #include #include @@ -85,7 +90,7 @@ TraceEventHandle AddPerfTraceEvent(PlatformMethods *platform, const unsigned char *categoryEnabledFlag, const char *name, unsigned long long id, - double timestamp, + double /*timestamp*/, int numArgs, const char **argNames, const unsigned char *argTypes, @@ -108,7 +113,8 @@ TraceEventHandle AddPerfTraceEvent(PlatformMethods *platform, uint32_t tid = renderTest->getCurrentThreadSerial(); std::vector &buffer = renderTest->getTraceEventBuffer(); - buffer.emplace_back(phase, category->name, name, timestamp, tid); + buffer.emplace_back(phase, category->name, name, + platform->monotonicallyIncreasingTime(platform), tid); return buffer.size(); } @@ -305,6 +311,8 @@ ANGLEPerfTest::ANGLEPerfTest(const std::string &name, mBackend(backend), mStory(story), mGPUTimeNs(0), + mFrameWallTimeSec(0.0), + mBusyWaitCpuTimeSec(0.0), mSkipTest(false), mStepsToRun(std::max(gStepsPerTrial, gMaxStepsPerformed)), mTrialNumStepsPerformed(0), @@ -323,6 +331,7 @@ ANGLEPerfTest::ANGLEPerfTest(const std::string &name, } mReporter = std::make_unique(mName + mBackend, mStory); mReporter->RegisterImportantMetric(".wall_time", units); + mReporter->RegisterImportantMetric(".frame_wall_time", units); mReporter->RegisterImportantMetric(".cpu_time", units); mReporter->RegisterImportantMetric(".gpu_time", units); mReporter->RegisterFyiMetric(".trial_steps", "count"); @@ -372,6 +381,14 @@ void ANGLEPerfTest::run() double secondsPerIteration = secondsPerStep / static_cast(mIterationsPerStep); mTestTrialResults.push_back(secondsPerIteration * 1000.0); } + if (gSleepBetweenTrialMs > 0 && trial + 1 < numTrials) + { + if (gVerboseLogging) + { + printf("Sleeping for %d milliseconds before next trial...\n", gSleepBetweenTrialMs); + } + std::this_thread::sleep_for(std::chrono::milliseconds(gSleepBetweenTrialMs)); + } } atraceCounter("TraceStage", 0); @@ -415,6 +432,8 @@ void ANGLEPerfTest::runTrial(double maxRunTime, int maxStepsToRun, RunTrialPolic mTrialNumStepsPerformed = 0; mRunning = true; mGPUTimeNs = 0; + mFrameWallTimeSec = 0.0; + mBusyWaitCpuTimeSec = 0.0; int stepAlignment = getStepAlignment(); mTrialTimer.start(); startTest(); @@ -423,15 +442,15 @@ void ANGLEPerfTest::runTrial(double maxRunTime, int maxStepsToRun, RunTrialPolic double lastLoopWallTime = 0; while (mRunning) { - // When ATrace enabled, track average frame time before the first frame of each trace loop. + // When ATrace enabled, track average wall time before the first frame of each trace loop. if (ATraceEnabled() && stepAlignment > 1 && runPolicy == RunTrialPolicy::RunContinuously && mTrialNumStepsPerformed % stepAlignment == 0) { double wallTime = mTrialTimer.getElapsedWallClockTime(); if (loopStepsPerformed > 0) // 0 at the first frame of the first loop { - int frameTimeAvgUs = int(1e6 * (wallTime - lastLoopWallTime) / loopStepsPerformed); - atraceCounter("TraceLoopFrameTimeAvgUs", frameTimeAvgUs); + int wallTimeAvgUs = int(1e6 * (wallTime - lastLoopWallTime) / loopStepsPerformed); + atraceCounter("TraceLoopWallTimeAvgUs", wallTimeAvgUs); loopStepsPerformed = 0; } lastLoopWallTime = wallTime; @@ -473,11 +492,28 @@ void ANGLEPerfTest::runTrial(double maxRunTime, int maxStepsToRun, RunTrialPolic if (gFpsLimit) { - double wantTime = mTrialNumStepsPerformed / double(gFpsLimit); - double currentTime = mTrialTimer.getElapsedWallClockTime(); - if (currentTime < wantTime) + double wantTime = mTrialNumStepsPerformed / double(gFpsLimit); + if (gFpsLimitUsesBusyWait) { - std::this_thread::sleep_for(std::chrono::duration(wantTime - currentTime)); + Timer busyWaitTimer; + busyWaitTimer.start(); + while (mTrialTimer.getElapsedWallClockTime() < wantTime) + { + } + busyWaitTimer.stop(); + // Estimate CPU time spend busy waiting by the current thread. + const double busyWaitCpuTime = std::min(busyWaitTimer.getElapsedWallClockTime(), + busyWaitTimer.getElapsedCpuTime()); + mBusyWaitCpuTimeSec += busyWaitCpuTime; + } + else + { + double currentTime = mTrialTimer.getElapsedWallClockTime(); + if (currentTime < wantTime) + { + std::this_thread::sleep_for( + std::chrono::duration(wantTime - currentTime)); + } } } step(); @@ -502,7 +538,7 @@ void ANGLEPerfTest::runTrial(double maxRunTime, int maxStepsToRun, RunTrialPolic if (runPolicy == RunTrialPolicy::RunContinuously) { - atraceCounter("TraceLoopFrameTimeAvgUs", 0); + atraceCounter("TraceLoopWallTimeAvgUs", 0); } finishTest(); mTrialTimer.stop(); @@ -581,7 +617,11 @@ void ANGLEPerfTest::addHistogramSample(const char *metric, double value, const s void ANGLEPerfTest::processResults() { - processClockResult(".cpu_time", mTrialTimer.getElapsedCpuTime()); + processClockResult(".cpu_time", mTrialTimer.getElapsedCpuTime() - mBusyWaitCpuTimeSec); + if (mFrameWallTimeSec > 0.0) + { + processClockResult(".frame_wall_time", mFrameWallTimeSec); + } processClockResult(".wall_time", mTrialTimer.getElapsedWallClockTime()); if (mGPUTimeNs > 0) @@ -773,6 +813,9 @@ std::string RenderTestParams::backend() const case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE: strstr << "_metal"; break; + case EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE: + strstr << "_webgpu"; + break; default: assert(0); return "_unk"; @@ -999,14 +1042,29 @@ void ANGLERenderTest::SetUp() return; } + constexpr const char *REQUESTED_EXTENSIONS_FILENAME = "angle_trace_requested_extensions"; + if (gRequestedExtensions != nullptr) { + std::filesystem::path tempDir = std::filesystem::temp_directory_path(); + std::filesystem::path extFilePath = tempDir / REQUESTED_EXTENSIONS_FILENAME; std::istringstream ss{gRequestedExtensions}; std::string ext; + + std::ofstream extFile(extFilePath); + if (!extFile.is_open()) + { + FATAL() << "Error: Couldn't open temporary extension file"; + } + while (std::getline(ss, ext, ' ')) { + // Set the extension for the trace's main context glRequestExtensionANGLE(ext.c_str()); + // Write extension to file for the trace's side-contexts + extFile << ext << std::endl; } + extFile.close(); } // Disable vsync (if not done by the window init). @@ -1022,6 +1080,18 @@ void ANGLERenderTest::SetUp() if (mTestParams.trackGpuTime) { mIsTimestampQueryAvailable = EnsureGLExtensionEnabled("GL_EXT_disjoint_timer_query"); + + if (IsAndroid() && mIsTimestampQueryAvailable && + mTestParams.driver == GLESDriverType::SystemEGL) + { + // It was observed that on Native GLES drivers (both Adreno and Mali) the query was + // inserted before previous draw commands if there is no flush right before the + // glQueryCounterEXT() call. Adreno is known to respect glFlush() call, while Mali + // ignores it and requires a glFenceSync() hack. + mEndQueryFlushPolicy = (mTestParams.majorVersion >= 3 && !IsAdreno()) + ? EndQueryFlushPolicy::FenceSync + : EndQueryFlushPolicy::Flush; + } } skipTestIfMissingExtensionPrerequisites(); @@ -1058,6 +1128,19 @@ void ANGLERenderTest::SetUp() { printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER)); printf("GL_VERSION: %s\n", glGetString(GL_VERSION)); + switch (mEndQueryFlushPolicy) + { + case EndQueryFlushPolicy::Flush: + printf("Native GLES driver - using flush before end GPU timestamp query\n"); + break; + case EndQueryFlushPolicy::FenceSync: + printf( + "Native GLES driver - using glFenceSync() hack before end GPU " + "timestamp query\n"); + break; + default: + break; + } } mTestTrialResults.reserve(gTestTrials); @@ -1188,6 +1271,8 @@ void ANGLERenderTest::updatePerfCounters() { uint32_t counter = iter.first; std::vector &samples = iter.second.samples; + ASSERT(perfData[counter].group == 0); + ASSERT(perfData[counter].counter == counter); samples.push_back(perfData[counter].value); } } @@ -1292,10 +1377,27 @@ void ANGLERenderTest::startGpuTimer() } } -void ANGLERenderTest::stopGpuTimer() +void ANGLERenderTest::stopGpuTimer(bool mayNeedFlush) { if (mTestParams.trackGpuTime && mIsTimestampQueryAvailable) { + if (mayNeedFlush) + { + switch (mEndQueryFlushPolicy) + { + case EndQueryFlushPolicy::Flush: + glFlush(); + break; + case EndQueryFlushPolicy::FenceSync: + { + GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glDeleteSync(sync); + break; + } + default: + break; + } + } GLuint endQuery = 0; glGenQueriesEXT(1, &endQuery); glQueryCounterEXT(endQuery, GL_TIMESTAMP_EXT); diff --git a/src/tests/perf_tests/ANGLEPerfTest.h b/src/tests/perf_tests/ANGLEPerfTest.h index e01c79b42dd..8609eaa3793 100644 --- a/src/tests/perf_tests/ANGLEPerfTest.h +++ b/src/tests/perf_tests/ANGLEPerfTest.h @@ -138,6 +138,8 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable std::string mStory; Timer mTrialTimer; uint64_t mGPUTimeNs; + double mFrameWallTimeSec; + double mBusyWaitCpuTimeSec; bool mSkipTest; std::string mSkipTestReason; std::unique_ptr mReporter; @@ -222,7 +224,7 @@ class ANGLERenderTest : public ANGLEPerfTest void setRobustResourceInit(bool enabled); void startGpuTimer(); - void stopGpuTimer(); + void stopGpuTimer(bool mayNeedFlush = true); void beginInternalTraceEvent(const char *name); void endInternalTraceEvent(const char *name); @@ -238,6 +240,10 @@ class ANGLERenderTest : public ANGLEPerfTest void startTest() override; void finishTest() override; + // non-const, so tests (e.g., TracePerfTest, + // ProgramPipelineObjectBenchmark) can set the values they need. + ConfigParameters &getConfigParams() { return mConfigParams; } + private: void SetUp() override; void TearDown() override; @@ -263,6 +269,13 @@ class ANGLERenderTest : public ANGLEPerfTest ConfigParameters mConfigParams; bool mSwapEnabled; + enum class EndQueryFlushPolicy + { + NoFlush, + Flush, + FenceSync + }; + struct TimestampSample { GLuint beginQuery; @@ -271,6 +284,7 @@ class ANGLERenderTest : public ANGLEPerfTest GLuint mCurrentTimestampBeginQuery = 0; std::queue mTimestampQueries; + EndQueryFlushPolicy mEndQueryFlushPolicy = EndQueryFlushPolicy::NoFlush; // Trace event record that can be output. std::vector mTraceEventBuffer; diff --git a/src/tests/perf_tests/ANGLEPerfTestArgs.cpp b/src/tests/perf_tests/ANGLEPerfTestArgs.cpp index a67a93a2346..73453f81fce 100644 --- a/src/tests/perf_tests/ANGLEPerfTestArgs.cpp +++ b/src/tests/perf_tests/ANGLEPerfTestArgs.cpp @@ -7,6 +7,10 @@ // Parse command line arguments for angle_perftests. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTestArgs.h" #include #include @@ -37,6 +41,7 @@ bool gVerboseLogging = false; bool gWarmup = false; int gTrialTimeSeconds = kDefaultTrialTimeSeconds; int gTestTrials = kDefaultTestTrials; +int gSleepBetweenTrialMs = 0; bool gNoFinish = false; bool gRetraceMode = false; bool gMinimizeGPUWork = false; @@ -47,6 +52,7 @@ const char *gUseGL = nullptr; bool gOffscreen = false; bool gVsync = false; int gFpsLimit = 0; +bool gFpsLimitUsesBusyWait = false; bool gRunToKeyFrame = false; int gFixedTestTime = 0; int gFixedTestTimeWithWarmup = 0; @@ -54,6 +60,9 @@ const char *gTraceInterpreter = nullptr; const char *gPrintExtensionsToFile = nullptr; const char *gRequestedExtensions = nullptr; bool gIncludeInactiveResources = false; +bool gTrackGPUTime = false; +bool gAddSwapIntoGPUTime = false; +bool gAddSwapIntoFrameWallTime = false; namespace { @@ -75,7 +84,8 @@ bool PerfTestArg(int *argc, char **argv, int argIndex) &gFixedTestTimeWithWarmup) || ParseIntArg("--trial-time", argc, argv, argIndex, &gTrialTimeSeconds) || ParseIntArg("--max-trial-time", argc, argv, argIndex, &gTrialTimeSeconds) || - ParseIntArg("--trials", argc, argv, argIndex, &gTestTrials); + ParseIntArg("--trials", argc, argv, argIndex, &gTestTrials) || + ParseIntArg("--sleep-between-trials", argc, argv, argIndex, &gSleepBetweenTrialMs); } bool TraceTestArg(int *argc, char **argv, int argIndex) @@ -89,6 +99,7 @@ bool TraceTestArg(int *argc, char **argv, int argIndex) ParseCStringArg("--trace-interpreter", argc, argv, argIndex, &gTraceInterpreter) || ParseIntArg("--screenshot-frame", argc, argv, argIndex, &gScreenshotFrame) || ParseIntArg("--fps-limit", argc, argv, argIndex, &gFpsLimit) || + ParseFlag("--fps-limit-uses-busy-wait", argc, argv, argIndex, &gFpsLimitUsesBusyWait) || ParseCStringArgWithHandling("--render-test-output-dir", argc, argv, argIndex, &gRenderTestOutputDir, ArgHandling::Preserve) || ParseCStringArg("--screenshot-dir", argc, argv, argIndex, &gScreenshotDir) || @@ -98,7 +109,11 @@ bool TraceTestArg(int *argc, char **argv, int argIndex) &gPrintExtensionsToFile) || ParseCStringArg("--request-extensions", argc, argv, argIndex, &gRequestedExtensions) || ParseFlag("--include-inactive-resources", argc, argv, argIndex, - &gIncludeInactiveResources); + &gIncludeInactiveResources) || + ParseFlag("--track-gpu-time", argc, argv, argIndex, &gTrackGPUTime) || + ParseFlag("--add-swap-into-gpu-time", argc, argv, argIndex, &gAddSwapIntoGPUTime) || + ParseFlag("--add-swap-into-frame-wall-time", argc, argv, argIndex, + &gAddSwapIntoFrameWallTime); } } // namespace } // namespace angle diff --git a/src/tests/perf_tests/ANGLEPerfTestArgs.h b/src/tests/perf_tests/ANGLEPerfTestArgs.h index 42672dc8fcb..260deda08f8 100644 --- a/src/tests/perf_tests/ANGLEPerfTestArgs.h +++ b/src/tests/perf_tests/ANGLEPerfTestArgs.h @@ -28,6 +28,7 @@ extern bool gVerboseLogging; extern bool gWarmup; extern int gTrialTimeSeconds; extern int gTestTrials; +extern int gSleepBetweenTrialMs; extern bool gNoFinish; extern bool gRetraceMode; extern bool gMinimizeGPUWork; @@ -39,9 +40,13 @@ extern const char *gUseGL; extern bool gOffscreen; extern bool gVsync; extern int gFpsLimit; +extern bool gFpsLimitUsesBusyWait; extern const char *gPrintExtensionsToFile; extern const char *gRequestedExtensions; extern bool gIncludeInactiveResources; +extern bool gTrackGPUTime; +extern bool gAddSwapIntoGPUTime; +extern bool gAddSwapIntoFrameWallTime; // Constant for when trace's frame count should be used constexpr int kAllFrames = -1; diff --git a/src/tests/perf_tests/AstcDecompressorPerf.cpp b/src/tests/perf_tests/AstcDecompressorPerf.cpp index 5a38501f431..7c1b0a69e24 100644 --- a/src/tests/perf_tests/AstcDecompressorPerf.cpp +++ b/src/tests/perf_tests/AstcDecompressorPerf.cpp @@ -57,8 +57,10 @@ AstcDecompressorPerfTest::AstcDecompressorPerfTest() mDecompressor(AstcDecompressor::get()), mInput(makeAstcCheckerboard(GetParam().width, GetParam().height)), mOutput(GetParam().width * GetParam().height * 4), - mSingleThreadPool(WorkerThreadPool::Create(1, ANGLEPlatformCurrent())), - mMultiThreadPool(WorkerThreadPool::Create(0, ANGLEPlatformCurrent())) + mSingleThreadPool( + WorkerThreadPool::Create(angle::ThreadPoolType::Synchronous, 0, ANGLEPlatformCurrent())), + mMultiThreadPool( + WorkerThreadPool::Create(angle::ThreadPoolType::Asynchronous, 0, ANGLEPlatformCurrent())) {} void AstcDecompressorPerfTest::step() diff --git a/src/tests/perf_tests/BindingPerf.cpp b/src/tests/perf_tests/BindingPerf.cpp index 061bb31d4e6..9007fc35b3b 100644 --- a/src/tests/perf_tests/BindingPerf.cpp +++ b/src/tests/perf_tests/BindingPerf.cpp @@ -7,6 +7,10 @@ // Performance test for binding objects // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include @@ -228,7 +232,7 @@ BindingsParams D3D11Params(AllocationStyle allocationStyle) BindingsParams OpenGLOrGLESParams(AllocationStyle allocationStyle) { BindingsParams params; - params.eglParameters = egl_platform::OPENGL_OR_GLES_NULL(); + params.eglParameters = egl_platform::OPENGL_OR_GLES(); params.allocationStyle = allocationStyle; return params; } diff --git a/src/tests/perf_tests/BitSetIteratorPerf.cpp b/src/tests/perf_tests/BitSetIteratorPerf.cpp index 2fcad28b6a4..2d85a8d9d4d 100644 --- a/src/tests/perf_tests/BitSetIteratorPerf.cpp +++ b/src/tests/perf_tests/BitSetIteratorPerf.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// IndexDataManagerPerfTest: -// Performance test for index buffer management. +// BitSetIteratorPerf.cpp: +// Performance test for bitset iterators. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include diff --git a/src/tests/perf_tests/BufferSubData.cpp b/src/tests/perf_tests/BufferSubData.cpp index 9417c69b646..c0bb32ddcd1 100644 --- a/src/tests/perf_tests/BufferSubData.cpp +++ b/src/tests/perf_tests/BufferSubData.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// BufferSubDataBenchmark: +// BufferSubData.cpp: // Performance test for ANGLE buffer updates. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "ANGLEPerfTest.h" diff --git a/src/tests/perf_tests/CompilerPerf.cpp b/src/tests/perf_tests/CompilerPerf.cpp index 31a5061a001..f5357269ff0 100644 --- a/src/tests/perf_tests/CompilerPerf.cpp +++ b/src/tests/perf_tests/CompilerPerf.cpp @@ -198,13 +198,11 @@ bool IsPlatformAvailable(const CompilerParameters ¶m) { angle::PoolAllocator allocator; InitializePoolIndex(); - allocator.push(); SetGlobalPoolAllocator(&allocator); ShHandle translator = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC, param.output); bool success = translator != nullptr; SetGlobalPoolAllocator(nullptr); - allocator.pop(); FreePoolIndex(); if (!success) { @@ -271,14 +269,12 @@ void CompilerPerfTest::SetUp() ANGLEPerfTest::SetUp(); InitializePoolIndex(); - mAllocator.push(); SetGlobalPoolAllocator(&mAllocator); const auto ¶ms = GetParam(); mTranslator = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC, params.output); sh::InitBuiltInResources(&mResources); - mResources.FragmentPrecisionHigh = true; if (!mTranslator->Init(mResources)) { SafeDelete(mTranslator); @@ -292,7 +288,7 @@ void CompilerPerfTest::TearDown() SafeDelete(mTranslator); SetGlobalPoolAllocator(nullptr); - mAllocator.pop(); + mAllocator.reset(); FreePoolIndex(); @@ -310,7 +306,7 @@ void CompilerPerfTest::step() #if !defined(NDEBUG) // Make sure that compilation succeeds and print the info log if it doesn't in debug mode. - if (!mTranslator->compile(shaderStrings, 1, compileOptions)) + if (!mTranslator->compile(shaderStrings, compileOptions)) { std::cout << "Compiling perf test shader failed with log:\n" << mTranslator->getInfoSink().info.c_str(); @@ -319,7 +315,7 @@ void CompilerPerfTest::step() for (unsigned int iteration = 0; iteration < kNumIterationsPerStep; ++iteration) { - mTranslator->compile(shaderStrings, 1, compileOptions); + mTranslator->compile(shaderStrings, compileOptions); } } diff --git a/src/tests/perf_tests/DispatchComputePerf.cpp b/src/tests/perf_tests/DispatchComputePerf.cpp index dc0c876c37a..3611be2d7e8 100644 --- a/src/tests/perf_tests/DispatchComputePerf.cpp +++ b/src/tests/perf_tests/DispatchComputePerf.cpp @@ -155,11 +155,10 @@ void DispatchComputePerfBenchmark::drawBenchmark() ASSERT_GL_NO_ERROR(); } -DispatchComputePerfParams DispatchComputePerfOpenGLOrGLESParams(bool useNullDevice) +DispatchComputePerfParams DispatchComputePerfOpenGLOrGLESParams() { DispatchComputePerfParams params; - params.eglParameters = useNullDevice ? angle::egl_platform::OPENGL_OR_GLES_NULL() - : angle::egl_platform::OPENGL_OR_GLES(); + params.eglParameters = angle::egl_platform::OPENGL_OR_GLES(); return params; } @@ -169,8 +168,6 @@ TEST_P(DispatchComputePerfBenchmark, Run) } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DispatchComputePerfBenchmark); -ANGLE_INSTANTIATE_TEST(DispatchComputePerfBenchmark, - DispatchComputePerfOpenGLOrGLESParams(true), - DispatchComputePerfOpenGLOrGLESParams(false)); +ANGLE_INSTANTIATE_TEST(DispatchComputePerfBenchmark, DispatchComputePerfOpenGLOrGLESParams()); } // namespace diff --git a/src/tests/perf_tests/DrawCallPerf.cpp b/src/tests/perf_tests/DrawCallPerf.cpp index 3eeb7018faf..19467b8b3ce 100644 --- a/src/tests/perf_tests/DrawCallPerf.cpp +++ b/src/tests/perf_tests/DrawCallPerf.cpp @@ -7,6 +7,10 @@ // Performance tests for ANGLE draw call overhead. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include "DrawCallPerfParams.h" #include "common/PackedEnums.h" diff --git a/src/tests/perf_tests/EGLInitializePerf.cpp b/src/tests/perf_tests/EGLInitializePerf.cpp index 80bfbe94f85..f10c4615e83 100644 --- a/src/tests/perf_tests/EGLInitializePerf.cpp +++ b/src/tests/perf_tests/EGLInitializePerf.cpp @@ -7,6 +7,10 @@ // Performance test for device creation. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "ANGLEPerfTest.h" #include "platform/PlatformMethods.h" #include "test_utils/angle_test_configs.h" @@ -79,7 +83,7 @@ EGLInitializePerfTest::EGLInitializePerfTest() { auto platform = GetParam().eglParameters; - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platform.renderer); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -98,17 +102,17 @@ EGLInitializePerfTest::EGLInitializePerfTest() mOSWindow = OSWindow::New(); mOSWindow->initialize("EGLInitialize Test", 64, 64); - auto eglGetPlatformDisplayEXT = reinterpret_cast( - eglGetProcAddress("eglGetPlatformDisplayEXT")); - if (eglGetPlatformDisplayEXT == nullptr) + auto eglGetPlatformDisplay = + reinterpret_cast(eglGetProcAddress("eglGetPlatformDisplay")); + if (eglGetPlatformDisplay == nullptr) { std::cerr << "Error getting platform display!" << std::endl; return; } - mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(mOSWindow->getNativeDisplay()), - &displayAttributes[0]); + mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + reinterpret_cast(mOSWindow->getNativeDisplay()), + &displayAttributes[0]); } void EGLInitializePerfTest::SetUp() diff --git a/src/tests/perf_tests/EGLMakeCurrentPerf.cpp b/src/tests/perf_tests/EGLMakeCurrentPerf.cpp index 3232c1dff9f..ca21ce2a041 100644 --- a/src/tests/perf_tests/EGLMakeCurrentPerf.cpp +++ b/src/tests/perf_tests/EGLMakeCurrentPerf.cpp @@ -49,7 +49,7 @@ EGLMakeCurrentPerfTest::EGLMakeCurrentPerfTest() { auto platform = GetParam().eglParameters; - std::vector displayAttributes; + std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platform.renderer); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); @@ -78,13 +78,13 @@ EGLMakeCurrentPerfTest::EGLMakeCurrentPerfTest() // Test harness warmup calls glFinish so we need GLES too. LoadUtilGLES(getProc); - if (!eglGetPlatformDisplayEXT) + if (!eglGetPlatformDisplay) { abortTest(); } else { - mDisplay = eglGetPlatformDisplayEXT( + mDisplay = eglGetPlatformDisplay( EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(mOSWindow->getNativeDisplay()), &displayAttributes[0]); } diff --git a/src/tests/perf_tests/FormatUploadDrawPerf.cpp b/src/tests/perf_tests/FormatUploadDrawPerf.cpp new file mode 100644 index 00000000000..9927c71e21a --- /dev/null +++ b/src/tests/perf_tests/FormatUploadDrawPerf.cpp @@ -0,0 +1,236 @@ +// +// Copyright 2025 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. +// +// FormatUploadDrawPerfBenchmark: +// Performance of texture upload and draw using various formats. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + +#include "ANGLEPerfTest.h" + +#include +#include +#include + +#include "test_utils/gl_raii.h" +#include "util/shader_utils.h" + +using namespace angle; + +enum class TestedFormat +{ + RGBA8, + RGB8, + RGB565, +}; + +constexpr const char *kTestedFormatString[] = { + "rgba8", + "rgb8", + "rgb565", +}; + +template +constexpr auto ToUnderlying(E e) noexcept +{ + return static_cast>(e); +} + +namespace +{ +struct FormatUploadDrawPerfParams final : public RenderTestParams +{ + FormatUploadDrawPerfParams() { iterationsPerStep = 1; } + + std::string story() const override; + + TestedFormat testedFormat; +}; + +std::ostream &operator<<(std::ostream &os, const FormatUploadDrawPerfParams ¶ms) +{ + return os << params.backendAndStory().substr(1); +} + +std::string FormatUploadDrawPerfParams::story() const +{ + std::stringstream strstr; + + strstr << RenderTestParams::story() << "_" << kTestedFormatString[ToUnderlying(testedFormat)]; + + return strstr.str(); +} + +class FormatUploadDrawPerfBenchmark + : public ANGLERenderTest, + public ::testing::WithParamInterface +{ + public: + FormatUploadDrawPerfBenchmark(); + + void initializeBenchmark() override; + void drawBenchmark() override; + void destroyBenchmark() override; + + protected: + std::vector mColors; + GLuint mTexture; + TestedFormat mTestedFormat; + uint32_t mTextureSize; + uint32_t mPixelSize; + GLuint mFormat; + GLuint mType; + GLuint mProgram; +}; + +FormatUploadDrawPerfBenchmark::FormatUploadDrawPerfBenchmark() + : ANGLERenderTest("FormatUploadDrawPerf", GetParam()) +{ + mTestedFormat = GetParam().testedFormat; + mTextureSize = 256; + switch (mTestedFormat) + { + case TestedFormat::RGBA8: + mFormat = GL_RGBA; + mType = GL_UNSIGNED_BYTE; + mPixelSize = 4; + break; + case TestedFormat::RGB8: + mFormat = GL_RGB; + mType = GL_UNSIGNED_BYTE; + mPixelSize = 3; + break; + case TestedFormat::RGB565: + mFormat = GL_RGB; + mType = GL_UNSIGNED_SHORT_5_6_5; + mPixelSize = 2; + break; + default: + UNREACHABLE(); + break; + } +} + +void FormatUploadDrawPerfBenchmark::initializeBenchmark() +{ + // Initialize texture. + ASSERT(gl::isPow2(mTextureSize)); + glGenTextures(1, &mTexture); + glBindTexture(GL_TEXTURE_2D, mTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mTextureSize, mTextureSize, 0, mFormat, mType, nullptr); + + // Initialize color data. + mColors.resize(mTextureSize * mTextureSize * mPixelSize); + memset(mColors.data(), 0, mTextureSize * mTextureSize * mPixelSize); + + // Set up program. + std::string vs = R"(#version 300 es +out highp vec2 texcoord; +void main() +{ + gl_Position = vec4(0, 0, 0, 0); + texcoord = vec2(0, 0); +} +)"; + std::string fs = R"(#version 300 es +uniform highp sampler2D tex; +out highp vec4 color; +in highp vec2 texcoord; +void main() +{ + color = texture(tex, texcoord); +})"; + + mProgram = CompileProgram(vs.c_str(), fs.c_str()); + ASSERT_NE(0u, mProgram); + glUseProgram(mProgram); +} + +void FormatUploadDrawPerfBenchmark::destroyBenchmark() +{ + glDeleteTextures(1, &mTexture); + glDeleteProgram(mProgram); +} + +void FormatUploadDrawPerfBenchmark::drawBenchmark() +{ + // Upload and draw many times. + for (uint32_t i = 0; i < 100; i++) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mTextureSize, mTextureSize, mFormat, mType, + mColors.data()); + glDrawArrays(GL_TRIANGLES, 0, 6); + } + ASSERT_GL_NO_ERROR(); +} + +FormatUploadDrawPerfParams VulkanParams(TestedFormat testedFormat) +{ + FormatUploadDrawPerfParams params; + params.eglParameters = egl_platform::VULKAN(); + params.majorVersion = 3; + params.minorVersion = 0; + params.testedFormat = testedFormat; + return params; +} + +FormatUploadDrawPerfParams OpenGLOrGLESParams(TestedFormat testedFormat) +{ + FormatUploadDrawPerfParams params; + params.eglParameters = egl_platform::OPENGL_OR_GLES(); + params.majorVersion = 3; + params.minorVersion = 0; + params.testedFormat = testedFormat; + return params; +} + +FormatUploadDrawPerfParams MetalParams(TestedFormat testedFormat) +{ + FormatUploadDrawPerfParams params; + params.eglParameters = egl_platform::METAL(); + params.majorVersion = 3; + params.minorVersion = 0; + params.testedFormat = testedFormat; + return params; +} + +FormatUploadDrawPerfParams D3D11Params(TestedFormat testedFormat) +{ + FormatUploadDrawPerfParams params; + params.eglParameters = egl_platform::D3D11(); + params.majorVersion = 3; + params.minorVersion = 0; + params.testedFormat = testedFormat; + return params; +} +} // anonymous namespace + +// Runs the test to measure the performance of various formats. +TEST_P(FormatUploadDrawPerfBenchmark, Run) +{ + run(); +} + +using namespace params; + +ANGLE_INSTANTIATE_TEST(FormatUploadDrawPerfBenchmark, + VulkanParams(TestedFormat::RGBA8), + VulkanParams(TestedFormat::RGB8), + VulkanParams(TestedFormat::RGB565), + OpenGLOrGLESParams(TestedFormat::RGBA8), + OpenGLOrGLESParams(TestedFormat::RGB8), + OpenGLOrGLESParams(TestedFormat::RGB565), + MetalParams(TestedFormat::RGBA8), + MetalParams(TestedFormat::RGB8), + MetalParams(TestedFormat::RGB565), + D3D11Params(TestedFormat::RGBA8), + D3D11Params(TestedFormat::RGB8), + D3D11Params(TestedFormat::RGB565)); diff --git a/src/tests/perf_tests/IndexDataManagerTest.cpp b/src/tests/perf_tests/IndexDataManagerTest.cpp index ef49729c50b..5d9856a518a 100644 --- a/src/tests/perf_tests/IndexDataManagerTest.cpp +++ b/src/tests/perf_tests/IndexDataManagerTest.cpp @@ -7,6 +7,10 @@ // Performance test for index buffer management. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include @@ -86,7 +90,8 @@ class MockBufferD3D : public rx::BufferD3D gl::BufferBinding target, const void *data, size_t size, - gl::BufferUsage) override + gl::BufferUsage, + rx::BufferFeedback *feedback) override { mData.resize(size); if (data && size > 0) @@ -96,17 +101,35 @@ class MockBufferD3D : public rx::BufferD3D return angle::Result::Continue; } - MOCK_METHOD5( - setSubData, - angle::Result(const gl::Context *, gl::BufferBinding, const void *, size_t, size_t)); - MOCK_METHOD5(copySubData, - angle::Result(const gl::Context *, BufferImpl *, GLintptr, GLintptr, GLsizeiptr)); - MOCK_METHOD3(map, angle::Result(const gl::Context *context, GLenum, void **)); - MOCK_METHOD5(mapRange, angle::Result(const gl::Context *, size_t, size_t, GLbitfield, void **)); - MOCK_METHOD2(unmap, angle::Result(const gl::Context *context, GLboolean *)); + MOCK_METHOD6(setSubData, + angle::Result(const gl::Context *, + gl::BufferBinding, + const void *, + size_t, + size_t, + rx::BufferFeedback *)); + MOCK_METHOD6(copySubData, + angle::Result(const gl::Context *, + BufferImpl *, + GLintptr, + GLintptr, + GLsizeiptr, + rx::BufferFeedback *)); + MOCK_METHOD4(map, + angle::Result(const gl::Context *context, GLenum, void **, rx::BufferFeedback *)); + MOCK_METHOD6(mapRange, + angle::Result(const gl::Context *, + size_t, + size_t, + GLbitfield, + void **, + rx::BufferFeedback *)); + MOCK_METHOD3(unmap, + angle::Result(const gl::Context *context, GLboolean *, rx::BufferFeedback *)); // BufferD3D - MOCK_METHOD1(markTransformFeedbackUsage, angle::Result(const gl::Context *)); + MOCK_METHOD2(markTransformFeedbackUsage, + angle::Result(const gl::Context *, rx::BufferFeedback *)); // inlined for speed bool supportsDirectBinding() const override { return false; } @@ -131,11 +154,12 @@ class MockGLFactoryD3D : public rx::MockGLFactory rx::BufferImpl *createBuffer(const gl::BufferState &state) override { MockBufferD3D *mockBufferD3D = new MockBufferD3D(mBufferFactory); + rx::BufferFeedback feedback; EXPECT_CALL(*mBufferFactory, createVertexBuffer()) .WillOnce(Return(nullptr)) .RetiresOnSaturation(); - mockBufferD3D->initializeStaticData(nullptr); + mockBufferD3D->initializeStaticData(nullptr, &feedback); return mockBufferD3D; } diff --git a/src/tests/perf_tests/InstancingPerf.cpp b/src/tests/perf_tests/InstancingPerf.cpp index 4b5f2768166..b9e9a656b2a 100644 --- a/src/tests/perf_tests/InstancingPerf.cpp +++ b/src/tests/perf_tests/InstancingPerf.cpp @@ -7,6 +7,10 @@ // Performance tests for ANGLE instanced draw calls. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include diff --git a/src/tests/perf_tests/InterleavedAttributeData.cpp b/src/tests/perf_tests/InterleavedAttributeData.cpp index 06ff8b6cb27..6e7cc99bc9f 100644 --- a/src/tests/perf_tests/InterleavedAttributeData.cpp +++ b/src/tests/perf_tests/InterleavedAttributeData.cpp @@ -7,6 +7,10 @@ // Performance test for draws using interleaved attribute data in vertex buffers. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "ANGLEPerfTest.h" diff --git a/src/tests/perf_tests/MapBufferRange.cpp b/src/tests/perf_tests/MapBufferRange.cpp index b02c660c162..ce160f256a6 100644 --- a/src/tests/perf_tests/MapBufferRange.cpp +++ b/src/tests/perf_tests/MapBufferRange.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// MapBufferRangeBenchmark:: +// MapBufferRangeBenchmark: // Performance test for ANGLE GLES mapped buffers. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include diff --git a/src/tests/perf_tests/MultisampleResolvePerf.cpp b/src/tests/perf_tests/MultisampleResolvePerf.cpp index 6717fa49bf4..cff3ea75a05 100644 --- a/src/tests/perf_tests/MultisampleResolvePerf.cpp +++ b/src/tests/perf_tests/MultisampleResolvePerf.cpp @@ -7,6 +7,10 @@ // Performance tests for glBlitFramebuffer and glInvalidateFramebuffer where the framebuffer is // multisampled. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include "util/shader_utils.h" diff --git a/src/tests/perf_tests/MultiviewPerf.cpp b/src/tests/perf_tests/MultiviewPerf.cpp index db6e25b9b85..686c0e3ed9c 100644 --- a/src/tests/perf_tests/MultiviewPerf.cpp +++ b/src/tests/perf_tests/MultiviewPerf.cpp @@ -3,13 +3,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// MultiviewPerfTest: +// MultiviewPerf.cpp: // Performance tests for multiview rendering. // - MultiviewCPUBoundBenchmark issues many draw calls and state changes to stress the CPU. // - MultiviewGPUBoundBenchmark draws half a million quads with multiple attributes per vertex in // order to stress the GPU's memory system. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "ANGLEPerfTest.h" #include "common/vector_utils.h" #include "platform/autogen/FeaturesD3D_autogen.h" @@ -66,6 +70,7 @@ enum class MultiviewOption NoAcceleration, InstancedMultiviewVertexShader, InstancedMultiviewGeometryShader, + InstancedMultiviewMultisampledVertexShader, Unspecified }; @@ -109,6 +114,9 @@ struct MultiviewPerfParams final : public RenderTestParams case MultiviewOption::InstancedMultiviewGeometryShader: name += "_instanced_multiview_geometry_shader"; break; + case MultiviewOption::InstancedMultiviewMultisampledVertexShader: + name += "_instanced_multiview_multisampled_vertex_shader"; + break; default: name += "_error"; break; @@ -128,6 +136,10 @@ struct MultiviewPerfParams final : public RenderTestParams } name += "_" + ext; name += "_" + ToString(numViews) + "_views"; + if (multiviewOption == MultiviewOption::InstancedMultiviewMultisampledVertexShader) + { + name += "_4_samples"; + } return name; } @@ -161,6 +173,12 @@ class MultiviewBenchmark : public ANGLERenderTest, // Unknown extension. break; } + + if (GetParam().multiviewOption == + MultiviewOption::InstancedMultiviewMultisampledVertexShader) + { + addExtensionPrerequisite("GL_OVR_multiview_multisampled_render_to_texture"); + } } virtual ~MultiviewBenchmark() @@ -212,7 +230,17 @@ class MultiviewCPUBoundBenchmark : public MultiviewBenchmark class MultiviewGPUBoundBenchmark : public MultiviewBenchmark { public: - MultiviewGPUBoundBenchmark() : MultiviewBenchmark("MultiviewGPUBoundBenchmark") {} + MultiviewGPUBoundBenchmark() : MultiviewBenchmark("MultiviewGPUBoundBenchmark") + { + if (IsPixel6() && + GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE && + GetParam().multiviewOption == MultiviewOption::NoAcceleration) + { + skipTest( + "http://anglebug.com/463416137 Fails on Pixel 6 Vulkan with no " + "acceleration."); + } + } void initializeBenchmark() override; @@ -261,6 +289,24 @@ void MultiviewBenchmark::initializeBenchmark() 0, params->numViews); break; } + case MultiviewOption::InstancedMultiviewMultisampledVertexShader: + { + // Multiview texture arrays + glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, params->windowWidth, + params->windowHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + + glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTexture); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, params->windowWidth, + params->windowHeight, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + + glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + mColorTexture, 0, 4, 0, params->numViews); + glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + mDepthTexture, 0, 4, 0, params->numViews); + break; + } case MultiviewOption::Unspecified: // implementation error. break; @@ -292,6 +338,7 @@ void MultiviewBenchmark::drawBenchmark() break; case MultiviewOption::InstancedMultiviewVertexShader: case MultiviewOption::InstancedMultiviewGeometryShader: + case MultiviewOption::InstancedMultiviewMultisampledVertexShader: glViewport(0, 0, viewWidth, viewHeight); glScissor(0, 0, viewWidth, viewHeight); renderScene(); @@ -561,6 +608,15 @@ MultiviewPerfParams SelectViewInVertexShader(const EGLPlatformParameters &eglPar MultiviewOption::InstancedMultiviewVertexShader, multiviewExtensionIn); } + +MultiviewPerfParams SelectMultisampledViewInVertexShader(const EGLPlatformParameters &eglParameters, + const MultiviewPerfWorkload &workload, + ExtensionName multiviewExtensionIn) +{ + return MultiviewPerfParams(eglParameters, workload, + MultiviewOption::InstancedMultiviewMultisampledVertexShader, + multiviewExtensionIn); +} } // namespace TEST_P(MultiviewCPUBoundBenchmark, Run) @@ -572,18 +628,28 @@ ANGLE_INSTANTIATE_TEST( MultiviewCPUBoundBenchmark, NoAcceleration(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview), NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview), + NoAcceleration(egl_platform::VULKAN(), SmallWorkload(), ExtensionName::multiview), SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview), SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview), SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview), + SelectViewInVertexShader(egl_platform::VULKAN(), SmallWorkload(), ExtensionName::multiview), + SelectMultisampledViewInVertexShader(egl_platform::VULKAN(), + SmallWorkload(), + ExtensionName::multiview), NoAcceleration(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview2), NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2), + NoAcceleration(egl_platform::VULKAN(), SmallWorkload(), ExtensionName::multiview2), SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview2), SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview2), - SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2)); + SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2), + SelectViewInVertexShader(egl_platform::VULKAN(), SmallWorkload(), ExtensionName::multiview2), + SelectMultisampledViewInVertexShader(egl_platform::VULKAN(), + SmallWorkload(), + ExtensionName::multiview2)); TEST_P(MultiviewGPUBoundBenchmark, Run) { @@ -594,17 +660,27 @@ ANGLE_INSTANTIATE_TEST( MultiviewGPUBoundBenchmark, NoAcceleration(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview), NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview), + NoAcceleration(egl_platform::VULKAN(), BigWorkload(), ExtensionName::multiview), SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview), SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview), SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview), + SelectViewInVertexShader(egl_platform::VULKAN(), BigWorkload(), ExtensionName::multiview), + SelectMultisampledViewInVertexShader(egl_platform::VULKAN(), + BigWorkload(), + ExtensionName::multiview), NoAcceleration(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview2), NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2), + NoAcceleration(egl_platform::VULKAN(), BigWorkload(), ExtensionName::multiview2), SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview2), SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview2), - SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2)); + SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2), + SelectViewInVertexShader(egl_platform::VULKAN(), BigWorkload(), ExtensionName::multiview2), + SelectMultisampledViewInVertexShader(egl_platform::VULKAN(), + BigWorkload(), + ExtensionName::multiview2)); } // anonymous namespace diff --git a/src/tests/perf_tests/README.md b/src/tests/perf_tests/README.md index 74f230aec4c..4d4e1840a38 100644 --- a/src/tests/perf_tests/README.md +++ b/src/tests/perf_tests/README.md @@ -38,8 +38,8 @@ sub-test and its name. ### Null/No-op Configurations -ANGLE implements a no-op driver for OpenGL, D3D11 and Vulkan. To run on these -configurations use the `gl_null`, `d3d11_null` or `vulkan_null` test +ANGLE implements a no-op driver for D3D11 and Vulkan. To run on these +configurations use the `d3d11_null` or `vulkan_null` test configurations. These null drivers will not do any GPU work. They will skip the driver entirely. These null configs are useful for diagnosing performance overhead in ANGLE code. @@ -62,6 +62,7 @@ Several command-line arguments control how the tests run: * `--warmup`: Run a warmup phase before the test. Defaults to off. * `--fixed-test-time-with-warmup x`: Start with a warmup, then run the tests until this much time has elapsed. * `--trials`: Number of times to repeat testing. Defaults to 3. +* `--sleep-between-trials`: Number of milliseconds to sleep between trials. May be useful to see trials boundaries in Perfetto `"gpu.renderstages"` traces. * `--no-finish`: Don't call glFinish after each test trial. * `--validation`: Enable serialization validation in the trace tests. Normally used with SwiftShader and retracing. * `--perf-counters`: Additional performance counters to include in the result output. Separate multiple entries with colons: ':'. @@ -105,13 +106,17 @@ Trace tests take command line arguments that pick the run configuration: * `--use-gl=native`: Runs the tests against the default system GLES implementation instad of your local ANGLE. * `--use-angle=backend`: Picks an ANGLE back-end. e.g. vulkan, d3d11, d3d9, gl, gles, metal, or swiftshader. Vulkan is the default. * `--offscreen`: Run with an offscreen surface instead of swapping every frame. -* `--vsync`: Run with vsync enabled, and measure CPU and GPU work insead of wall clock time. +* `--vsync`: Run with vsync enabled, and measure CPU and GPU work instead of wall clock time. * `--minimize-gpu-work`: Modify API calls so that GPU work is reduced to minimum. * `--screenshot-dir dir`: Directory to store test screenshots. Implies `--save-screenshots`. On Android this directory is on device, not local (see also `--render-test-output-dir`). Only implemented in `TracePerfTest`. * `--save-screenshots`: Save screenshots. Only implemented in `TracePerfTest`. * `--screenshot-frame `: Which frame to capture a screenshot of. Defaults to first frame (1). Using `-1` will capture every frame rendered, including those after Reset for multiple loops. Only implemented in `TracePerfTest`. * `--include-inactive-resources` : Include all resources captured at trace-time during replay. Only resources which are active during trace execution are replayed by default. -* `--fps-limit ` : Limit replay framerate to specified value. +* `--fps-limit ` : Limit replay framerate to specified value. Can be used to remove GPU waiting time from CPU for more accurate `frame_wall_time` measurements. +* `--fps-limit-uses-busy-wait` : Use busy wait instead of sleep to limit the framerate. This may be useful to move test process to the "BIG" core and active "high performance" mode on Android devices for more accurate `frame_wall_time` measurements. Note, that simply setting affinity of the test thread to "BIG" core may not give the same result (2X measured difference was observed on a real device between busy wait vs just setting thread CPU affinity). +* `--track-gpu-time` : Enables GPU frametime tracking if "GL_EXT_disjoint_timer_query" is available. +* `--add-swap-into-gpu-time` : Normally, GPU time is only tracked for the replay frame commands while excluding swap (or blit calls in case of the offscreen test). This option includes swap/blit time into the GPU frametime tracking. Warning: this will also include screenshot capture code when it is enabled. +* `--add-swap-into-frame-wall-time` : Similar to `--add-swap-into-gpu-time` but for the `frame_wall_time` (CPU time of the `replayFrame()` function). For example, for an endless run with no warmup on swiftshader, run: @@ -126,7 +131,8 @@ on all CPU threads for the test. * `wall_time`: Wall time taken to run a single iteration, calculated by dividing the total wall clock time by the number of test iterations. * For trace tests, each rendered frame is an iteration. +* `frame_wall_time`: Time of all GLES calls in the `replayFrame()` function. Optionally may include swap / offscreen blit calls by using the `--add-swap-into-frame-wall-time` argument. * `gpu_time`: Estimated GPU elapsed time per test iteration. We compute the estimate using GLES [timestamp queries](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_disjoint_timer_query.txt) at the beginning and ending of each test loop. - * For trace tests, this metric is only enabled in `vsync` mode. + * For trace tests, this metric is enabled by the `--track-gpu-time` argument. diff --git a/src/tests/perf_tests/RGBImageAllocation.cpp b/src/tests/perf_tests/RGBImageAllocation.cpp index 0779622ff42..068e6e490c2 100644 --- a/src/tests/perf_tests/RGBImageAllocation.cpp +++ b/src/tests/perf_tests/RGBImageAllocation.cpp @@ -7,6 +7,10 @@ // GL_RGB8 image allocation and loading using GL_UNSIGNED_BYTE. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include diff --git a/src/tests/perf_tests/TexturesPerf.cpp b/src/tests/perf_tests/TexturesPerf.cpp index 10bb00444c8..3a333ea857c 100644 --- a/src/tests/perf_tests/TexturesPerf.cpp +++ b/src/tests/perf_tests/TexturesPerf.cpp @@ -354,7 +354,7 @@ TexturesParams OpenGLOrGLESParams(bool webglCompat, Frequency stateUpdateFrequency) { TexturesParams params; - params.eglParameters = egl_platform::OPENGL_OR_GLES_NULL(); + params.eglParameters = egl_platform::OPENGL_OR_GLES(); params.webgl = webglCompat; return ApplyFrequencies(params, rebindFrequency, stateUpdateFrequency); } diff --git a/src/tests/perf_tests/TracePerfTest.cpp b/src/tests/perf_tests/TracePerfTest.cpp index 41694e36c37..db3fc783c6c 100644 --- a/src/tests/perf_tests/TracePerfTest.cpp +++ b/src/tests/perf_tests/TracePerfTest.cpp @@ -3,10 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// TracePerf: +// TracePerfTest.cpp: // Performance test for ANGLE replaying traces. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "tests/perf_tests/TracePerfTest.h" #include #include "common/PackedEnums.h" @@ -134,6 +138,10 @@ class TracePerfTest : public ANGLERenderTest return strncmp(name, mParams->traceInfo.name, kTraceInfoMaxNameLen) == 0; } + bool loadTestExpectationsFromFileWithConfig(const GPUTestConfig &config, + const std::string &fileName); + void initializeConfigParams(GPUTestConfig::API api); + private: struct QueryInfo { @@ -189,6 +197,7 @@ class TracePerfTest : public ANGLERenderTest bool mScreenshotSaved = false; int32_t mScreenshotFrame = gScreenshotFrame; std::unique_ptr mTraceReplay; + GPUTestExpectationsParser mTestExpectationsParser; }; TracePerfTest *gCurrentTracePerfTest = nullptr; @@ -365,6 +374,15 @@ void KHRONOS_APIENTRY DrawElementsInstancedMinimizedProc(GLenum mode, glDrawElementsInstanced(GL_POINTS, 1, type, indices, 1); } +void KHRONOS_APIENTRY DrawElementsInstancedEXTMinimizedProc(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instancecount) +{ + glDrawElementsInstancedEXT(GL_POINTS, 1, type, indices, 1); +} + void KHRONOS_APIENTRY DrawElementsBaseVertexMinimizedProc(GLenum mode, GLsizei count, GLenum type, @@ -374,6 +392,24 @@ void KHRONOS_APIENTRY DrawElementsBaseVertexMinimizedProc(GLenum mode, glDrawElementsBaseVertex(GL_POINTS, 1, type, indices, basevertex); } +void KHRONOS_APIENTRY DrawElementsBaseVertexEXTMinimizedProc(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLint basevertex) +{ + glDrawElementsBaseVertexEXT(GL_POINTS, 1, type, indices, basevertex); +} + +void KHRONOS_APIENTRY DrawElementsBaseVertexOESMinimizedProc(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLint basevertex) +{ + glDrawElementsBaseVertexOES(GL_POINTS, 1, type, indices, basevertex); +} + void KHRONOS_APIENTRY DrawElementsInstancedBaseVertexMinimizedProc(GLenum mode, GLsizei count, GLenum type, @@ -384,6 +420,26 @@ void KHRONOS_APIENTRY DrawElementsInstancedBaseVertexMinimizedProc(GLenum mode, glDrawElementsInstancedBaseVertex(GL_POINTS, 1, type, indices, 1, basevertex); } +void KHRONOS_APIENTRY DrawElementsInstancedBaseVertexEXTMinimizedProc(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instancecount, + GLint basevertex) +{ + glDrawElementsInstancedBaseVertexEXT(GL_POINTS, 1, type, indices, 1, basevertex); +} + +void KHRONOS_APIENTRY DrawElementsInstancedBaseVertexOESMinimizedProc(GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instancecount, + GLint basevertex) +{ + glDrawElementsInstancedBaseVertexOES(GL_POINTS, 1, type, indices, 1, basevertex); +} + void KHRONOS_APIENTRY DrawRangeElementsMinimizedProc(GLenum mode, GLuint start, GLuint end, @@ -407,6 +463,14 @@ void KHRONOS_APIENTRY DrawArraysInstancedMinimizedProc(GLenum mode, glDrawArraysInstanced(GL_POINTS, first, 1, 1); } +void KHRONOS_APIENTRY DrawArraysInstancedEXTMinimizedProc(GLenum mode, + GLint first, + GLsizei count, + GLsizei instancecount) +{ + glDrawArraysInstancedEXT(GL_POINTS, first, 1, 1); +} + void KHRONOS_APIENTRY DrawArraysIndirectMinimizedProc(GLenum mode, const void *indirect) { glDrawArraysInstanced(GL_POINTS, 0, 1, 1); @@ -452,6 +516,15 @@ void *KHRONOS_APIENTRY MapBufferRangeMinimizedProc(GLenum target, return glMapBufferRange(target, offset, length, access); } +void *KHRONOS_APIENTRY MapBufferRangeEXTMinimizedProc(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access) +{ + access |= GL_MAP_UNSYNCHRONIZED_BIT; + return glMapBufferRangeEXT(target, offset, length, access); +} + void KHRONOS_APIENTRY TexImage2DMinimizedProc(GLenum target, GLint level, GLint internalformat, @@ -539,6 +612,8 @@ void KHRONOS_APIENTRY GenerateMipmapMinimizedProc(GLenum target) // glTexImage2D call for each generated level. } +void KHRONOS_APIENTRY GenerateMipmapOESMinimizedProc(GLenum target) {} + void KHRONOS_APIENTRY BlitFramebufferMinimizedProc(GLint srcX0, GLint srcY0, GLint srcX1, @@ -662,116 +737,48 @@ angle::GenericProc KHRONOS_APIENTRY TraceLoadProc(const char *procName) if (gMinimizeGPUWork) { - if (strcmp(procName, "glViewport") == 0) - { - return reinterpret_cast(ViewportMinimizedProc); - } +#define MINIMIZED(EntryPoint) \ + if (strcmp(procName, "gl" #EntryPoint) == 0) \ + { \ + return reinterpret_cast(EntryPoint##MinimizedProc); \ + } - if (strcmp(procName, "glScissor") == 0) - { - return reinterpret_cast(ScissorMinimizedProc); - } + MINIMIZED(Viewport) + MINIMIZED(Scissor) // Interpose the calls that generate actual GPU work - if (strcmp(procName, "glDrawElements") == 0) - { - return reinterpret_cast(DrawElementsMinimizedProc); - } - if (strcmp(procName, "glDrawElementsIndirect") == 0) - { - return reinterpret_cast(DrawElementsIndirectMinimizedProc); - } - if (strcmp(procName, "glDrawElementsInstanced") == 0 || - strcmp(procName, "glDrawElementsInstancedEXT") == 0) - { - return reinterpret_cast(DrawElementsInstancedMinimizedProc); - } - if (strcmp(procName, "glDrawElementsBaseVertex") == 0 || - strcmp(procName, "glDrawElementsBaseVertexEXT") == 0 || - strcmp(procName, "glDrawElementsBaseVertexOES") == 0) - { - return reinterpret_cast(DrawElementsBaseVertexMinimizedProc); - } - if (strcmp(procName, "glDrawElementsInstancedBaseVertex") == 0 || - strcmp(procName, "glDrawElementsInstancedBaseVertexEXT") == 0 || - strcmp(procName, "glDrawElementsInstancedBaseVertexOES") == 0) - { - return reinterpret_cast( - DrawElementsInstancedBaseVertexMinimizedProc); - } - if (strcmp(procName, "glDrawRangeElements") == 0) - { - return reinterpret_cast(DrawRangeElementsMinimizedProc); - } - if (strcmp(procName, "glDrawArrays") == 0) - { - return reinterpret_cast(DrawArraysMinimizedProc); - } - if (strcmp(procName, "glDrawArraysInstanced") == 0 || - strcmp(procName, "glDrawArraysInstancedEXT") == 0) - { - return reinterpret_cast(DrawArraysInstancedMinimizedProc); - } - if (strcmp(procName, "glDrawArraysIndirect") == 0) - { - return reinterpret_cast(DrawArraysIndirectMinimizedProc); - } - if (strcmp(procName, "glDispatchCompute") == 0) - { - return reinterpret_cast(DispatchComputeMinimizedProc); - } - if (strcmp(procName, "glDispatchComputeIndirect") == 0) - { - return reinterpret_cast(DispatchComputeIndirectMinimizedProc); - } + MINIMIZED(DrawElements) + MINIMIZED(DrawElementsIndirect) + MINIMIZED(DrawElementsInstanced) + MINIMIZED(DrawElementsInstancedEXT) + MINIMIZED(DrawElementsBaseVertex) + MINIMIZED(DrawElementsBaseVertexEXT) + MINIMIZED(DrawElementsBaseVertexOES) + MINIMIZED(DrawElementsInstancedBaseVertex) + MINIMIZED(DrawElementsInstancedBaseVertexEXT) + MINIMIZED(DrawElementsInstancedBaseVertexOES) + MINIMIZED(DrawRangeElements) + MINIMIZED(DrawArrays) + MINIMIZED(DrawArraysInstanced) + MINIMIZED(DrawArraysInstancedEXT) + MINIMIZED(DrawArraysIndirect) + MINIMIZED(DispatchCompute) + MINIMIZED(DispatchComputeIndirect) // Interpose the calls that generate data copying work - if (strcmp(procName, "glBufferData") == 0) - { - return reinterpret_cast(BufferDataMinimizedProc); - } - if (strcmp(procName, "glBufferSubData") == 0) - { - return reinterpret_cast(BufferSubDataMinimizedProc); - } - if (strcmp(procName, "glMapBufferRange") == 0 || - strcmp(procName, "glMapBufferRangeEXT") == 0) - { - return reinterpret_cast(MapBufferRangeMinimizedProc); - } - if (strcmp(procName, "glTexImage2D") == 0) - { - return reinterpret_cast(TexImage2DMinimizedProc); - } - if (strcmp(procName, "glTexImage3D") == 0) - { - return reinterpret_cast(TexImage3DMinimizedProc); - } - if (strcmp(procName, "glTexSubImage2D") == 0) - { - return reinterpret_cast(TexSubImage2DMinimizedProc); - } - if (strcmp(procName, "glTexSubImage3D") == 0) - { - return reinterpret_cast(TexSubImage3DMinimizedProc); - } - if (strcmp(procName, "glGenerateMipmap") == 0 || - strcmp(procName, "glGenerateMipmapOES") == 0) - { - return reinterpret_cast(GenerateMipmapMinimizedProc); - } - if (strcmp(procName, "glBlitFramebuffer") == 0) - { - return reinterpret_cast(BlitFramebufferMinimizedProc); - } - if (strcmp(procName, "glReadPixels") == 0) - { - return reinterpret_cast(ReadPixelsMinimizedProc); - } - if (strcmp(procName, "glBeginTransformFeedback") == 0) - { - return reinterpret_cast(BeginTransformFeedbackMinimizedProc); - } + MINIMIZED(BufferData) + MINIMIZED(BufferSubData) + MINIMIZED(MapBufferRange) + MINIMIZED(MapBufferRangeEXT) + MINIMIZED(TexImage2D) + MINIMIZED(TexImage3D) + MINIMIZED(TexSubImage2D) + MINIMIZED(TexSubImage3D) + MINIMIZED(GenerateMipmap) + MINIMIZED(GenerateMipmapOES) + MINIMIZED(BlitFramebuffer) + MINIMIZED(ReadPixels) + MINIMIZED(BeginTransformFeedback) } return gCurrentTracePerfTest->getGLWindow()->getProcAddress(procName); @@ -795,35 +802,126 @@ bool FindRootTraceTestDataPath(char *testDataDirOut, size_t maxDataDirLen) return angle::FindTestDataPath(kTraceTestFolder, testDataDirOut, maxDataDirLen); } +GPUTestConfig::API getTestConfigAPIFromRenderer(angle::GLESDriverType driverType, + EGLenum renderer, + EGLenum deviceType) +{ + if (driverType == angle::GLESDriverType::SystemEGL || + driverType == angle::GLESDriverType::SystemWGL) + { + return GPUTestConfig::kAPINative; + } + + if (driverType != angle::GLESDriverType::AngleEGL && + driverType != angle::GLESDriverType::AngleVulkanSecondariesEGL) + { + return GPUTestConfig::kAPIUnknown; + } + + switch (renderer) + { + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: + return GPUTestConfig::kAPID3D11; + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + return GPUTestConfig::kAPID3D9; + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + return GPUTestConfig::kAPIGLDesktop; + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + return GPUTestConfig::kAPIGLES; + case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: + if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE) + { + return GPUTestConfig::kAPISwiftShader; + } + else + { + return GPUTestConfig::kAPIVulkan; + } + case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE: + return GPUTestConfig::kAPIMetal; + case EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE: + return GPUTestConfig::kAPIWgpu; + default: + std::cerr << "Unknown Renderer enum: 0x" << std::hex << renderer << "\n"; + return GPUTestConfig::kAPIUnknown; + } +} + +bool TracePerfTest::loadTestExpectationsFromFileWithConfig(const GPUTestConfig &config, + const std::string &fileName) +{ + if (!mTestExpectationsParser.loadTestExpectationsFromFile(config, fileName)) + { + std::stringstream errorMsgStream; + for (const auto &message : mTestExpectationsParser.getErrorMessages()) + { + errorMsgStream << std::endl << " " << message; + } + + std::cerr << "Failed to load test expectations." << errorMsgStream.str() << std::endl; + return false; + } + return true; +} + +void TracePerfTest::initializeConfigParams(GPUTestConfig::API api) +{ + // TODO (b/423678565): These config parameters will be overridden by ANGLERenderTest::SetUp(). + ConfigParameters &configParams = getConfigParams(); + configParams.redBits = mParams->traceInfo.configRedBits; + configParams.greenBits = mParams->traceInfo.configGreenBits; + configParams.blueBits = mParams->traceInfo.configBlueBits; + configParams.alphaBits = mParams->traceInfo.configAlphaBits; + configParams.depthBits = mParams->traceInfo.configDepthBits; + configParams.stencilBits = mParams->traceInfo.configStencilBits; + configParams.colorSpace = mParams->traceInfo.drawSurfaceColorSpace; + + // TODO (b/423680521): App traces shouldn't be relying on these extensions anyway, since they + // are not available when the real app is running on a real device, so these values should + // always match the defaults to begin with. + configParams.webGLCompatibility = mParams->traceInfo.isWebGLCompatibilityEnabled; + configParams.robustResourceInit = mParams->traceInfo.isRobustResourceInitEnabled; + configParams.bindGeneratesResource = mParams->traceInfo.isBindGeneratesResourcesEnabled; + configParams.clientArraysEnabled = mParams->traceInfo.areClientArraysEnabled; +} + TracePerfTest::TracePerfTest(std::unique_ptr params) : ANGLERenderTest("TracePerf", *params.get(), "ms"), mParams(std::move(params)), mStartFrame(0), mEndFrame(0) { - 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(); - // bool isAMDWinNative = isAMDWin && !mParams->isANGLE(); - - bool isIntel = IsIntel() && !mParams->isSwiftshader(); - bool isIntelLinux = isIntel && IsLinux(); - bool isIntelLinuxANGLE = isIntelLinux && mParams->isANGLE(); - bool isIntelLinuxNative = isIntelLinux && !mParams->isANGLE(); - bool isIntelWin = IsWindows() && isIntel; - bool isIntelWinANGLE = isIntelWin && mParams->isANGLE(); - bool isIntelWinNative = isIntelWin && !mParams->isANGLE(); - - bool isNVIDIA = IsNVIDIA() && !mParams->isSwiftshader(); - bool isNVIDIALinux = isNVIDIA && IsLinux(); - bool isNVIDIALinuxANGLE = isNVIDIALinux && mParams->isANGLE(); - bool isNVIDIALinuxNative = isNVIDIALinux && !mParams->isANGLE(); - bool isNVIDIAWin = isNVIDIA && IsWindows(); - bool isNVIDIAWinANGLE = isNVIDIAWin && mParams->isANGLE(); - bool isNVIDIAWinNative = isNVIDIAWin && !mParams->isANGLE(); + constexpr char kTestExpectationsPath[] = + "src/tests/perf_tests/angle_trace_tests_expectations.txt"; + constexpr size_t kMaxPath = 512; + std::array foundDataPath; + if (!angle::FindTestDataPath(kTestExpectationsPath, foundDataPath.data(), foundDataPath.size())) + { + failTest(std::string("Unable to find ANGLE trace tests expectations path: ") + + std::string(kTestExpectationsPath)); + return; + } + + angle::GPUTestConfig::API api = getTestConfigAPIFromRenderer( + mParams->driver, mParams->eglParameters.renderer, mParams->eglParameters.deviceType); + + GPUTestConfig testConfig = GPUTestConfig(api, 0); + if (!loadTestExpectationsFromFileWithConfig(testConfig, std::string(foundDataPath.data()))) + { + failTest(std::string("Unable to load ANGLE trace tests expectations file: ") + + std::string(foundDataPath.data())); + return; + } + else + { + int32_t testExpectation = + mTestExpectationsParser.getTestExpectation(mParams->traceInfo.name); + + if (testExpectation == GPUTestExpectationsParser::kGpuTestSkip) + { + skipTest("Test skipped on this config"); + } + } if (!mParams->traceInfo.initialized) { @@ -831,6 +929,8 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) return; } + initializeConfigParams(api); + for (std::string extension : mParams->traceInfo.requiredExtensions) { addExtensionPrerequisite(extension); @@ -863,60 +963,29 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) } } - if (isIntelWinANGLE && traceNameIs("manhattan_10")) - { - skipTest( - "TODO: http://anglebug.com/40096690 This fails after the upgrade to the 26.20.100.7870 " - "driver"); - } - - if (isIntelWinNative && traceNameIs("angry_birds_2_1500")) - { - skipTest( - "TODO: http://anglebug.com/40096702 Fails on older Intel drivers. Passes in newer"); - } + // Configuration-specific test exceptions. Only include exceptions that are outside the scope + // of the trace tests expectations file, "angle_trace_tests_expectations.txt". - if (traceNameIs("cod_mobile")) + if (traceNameIs("modern_combat_5")) { - if (isIntelWin) + if (IsPixel6() && !IsAndroid14OrNewer()) { - skipTest("http://anglebug.com/42265065 Flaky on Intel/windows"); + skipTest( + "https://issuetracker.google.com/42267261 Causing thermal failures on Pixel 6 with " + "Android 13"); } } - if (isIntelLinuxANGLE && traceNameIs("octopath_traveler")) - { - skipTest("TODO: http://anglebug.com/378666645 Non-deterministic image on Ubuntu 22.04"); - } - - if (isIntelLinuxANGLE && traceNameIs("dead_by_daylight")) - { - skipTest("TODO: http://anglebug.com/378666645 Non-deterministic image on Ubuntu 22.04"); - } - - if (isIntelWinANGLE && traceNameIs("black_desert_mobile")) - { - skipTest( - "TODO: http://anglebug.com/42266346 Non-deterministic image on 31.0.101.2111 driver"); - } - - if (isIntelWinANGLE && traceNameIs("the_gardens_between")) - { - skipTest( - "TODO: http://anglebug.com/42266346 Non-deterministic image on 31.0.101.2111 driver"); - } - - if (isIntelWinANGLE && traceNameIs("animal_crossing")) + if (traceNameIs("genshin_impact")) { - skipTest( - "TODO: http://anglebug.com/353690308 Non-deterministic image on UHD770 31.0.101.5333"); + if (!Is64Bit()) + { + skipTest("Genshin is too large to handle in 32-bit mode"); + } } - if (isIntelWinANGLE && traceNameIs("black_clover_m")) - { - skipTest( - "TODO: http://anglebug.com/353690308 Non-deterministic image on UHD770 31.0.101.5333"); - } + // Legacy trace-specific extension dependencies. For new traces this information will be + // included in the trace's json file. if (traceNameIs("brawl_stars")) { @@ -957,14 +1026,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) if (traceNameIs("saint_seiya_awakening")) { addExtensionPrerequisite("GL_EXT_shadow_samplers"); - - if (isIntelLinuxANGLE) - { - skipTest( - "TODO: https://anglebug.com/42264055 Linux+Intel generates 'Framebuffer is " - "incomplete' " - "errors"); - } } if (traceNameIs("magic_tiles_3")) @@ -980,12 +1041,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) // Intel doesn't support external images. addExtensionPrerequisite("GL_OES_EGL_image_external"); - - if (isIntelLinuxNative || isAMDLinuxNative) - { - skipTest( - "http://anglebug.com/42264358 Failing on Linux Intel and AMD due to invalid enum"); - } } if (traceNameIs("asphalt_8")) @@ -998,16 +1053,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("efootball_pes_2021")) - { - if (isIntelLinuxANGLE) - { - skipTest( - "TODO: https://anglebug.com/42264055 Linux+Intel generate 'Framebuffer is " - "incomplete' errors with the Vulkan backend"); - } - } - if (traceNameIs("shadow_fight_2")) { addExtensionPrerequisite("GL_OES_EGL_image_external"); @@ -1019,75 +1064,16 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_OES_EGL_image_external"); } - if (traceNameIs("happy_color")) - { - if (isAMDWinANGLE) - { - skipTest( - "http://anglebug.com/42264158 Generates incorrect results on AMD Windows Vulkan"); - } - } - - if (traceNameIs("bus_simulator_indonesia")) - { - if (isIntelLinuxNative || isAMDLinuxNative) - { - skipTest( - "TODO: https://anglebug.com/42264164 native GLES generates GL_INVALID_OPERATION"); - } - } - - if (traceNameIs("messenger_lite")) - { - if (isNVIDIAWinANGLE) - { - skipTest( - "https://anglebug.com/42264199 Incorrect pixels on NVIDIA Windows for first frame"); - } - } - if (traceNameIs("among_us")) { addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("car_parking_multiplayer")) - { - if (isNVIDIAWinNative || isNVIDIALinuxNative) - { - skipTest( - "TODO: https://anglebug.com/42264147 NVIDIA native driver spews undefined behavior " - "warnings"); - } - if (isIntelWinANGLE) - { - skipTest("https://anglebug.com/42264261 Device lost on Win Intel"); - } - } - - if (traceNameIs("fifa_mobile")) - { - if (isIntelWinANGLE) - { - skipTest( - "TODO: http://anglebug.com/42264415 Intel Windows Vulkan flakily renders entirely " - "black"); - } - } - if (traceNameIs("extreme_car_driving_simulator")) { addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("plants_vs_zombies_2")) - { - if (isAMDWinANGLE) - { - skipTest("TODO: http://crbug.com/1187752 Corrupted image"); - } - } - if (traceNameIs("junes_journey")) { addExtensionPrerequisite("GL_OES_EGL_image_external"); @@ -1103,47 +1089,16 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) { addExtensionPrerequisite("GL_OES_EGL_image_external"); addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - - if (isIntelLinuxANGLE) - { - skipTest("TODO: http://anglebug.com/42264351 Trace is crashing on Intel Linux"); - } } if (traceNameIs("aztec_ruins")) { - if (isIntelWinANGLE) - { - skipTest( - "TODO: http://anglebug.com/353690308 Non-deterministic image on UHD770 " - "31.0.101.5333"); - } - addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } if (traceNameIs("dragon_raja")) { addExtensionPrerequisite("GL_OES_EGL_image_external"); - - if (isIntelLinuxANGLE) - { - skipTest( - "TODO: http://anglebug.com/42264343 Intel Linux errors with 'Framebuffer is " - "incomplete' on Vulkan"); - } - } - - if (traceNameIs("hill_climb_racing") || traceNameIs("dead_trigger_2") || - traceNameIs("disney_mirrorverse") || traceNameIs("cut_the_rope") || - traceNameIs("geometry_dash") || traceNameIs("critical_ops")) - { - if (IsAndroid() && (IsPixel4() || IsPixel4XL()) && !mParams->isANGLE()) - { - skipTest( - "http://anglebug.com/42264359 Adreno gives a driver error with empty/small draw " - "calls"); - } } if (traceNameIs("avakin_life")) @@ -1151,190 +1106,45 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_OES_EGL_image_external"); } - if (traceNameIs("professional_baseball_spirits")) + if (traceNameIs("ludo_king")) { - if (isIntelLinuxANGLE || isAMDLinuxNative) - { - skipTest( - "TODO: https://anglebug.com/42264363 Linux+Mesa/RADV Vulkan generates " - "GL_INVALID_FRAMEBUFFER_OPERATION. Mesa versions below 20.3.5 produce the same " - "issue on Linux+Mesa/Intel Vulkan"); - } + addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("call_break_offline_card_game")) + if (traceNameIs("pokemon_go")) { - if (isIntelLinuxANGLE) - { - skipTest( - "TODO: http://anglebug.com/42264374 Intel Linux Vulkan errors with 'Framebuffer is " - "incomplete'"); - } + addExtensionPrerequisite("GL_EXT_texture_cube_map_array"); + addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("ludo_king")) + if (traceNameIs("cookie_run_kingdom")) { - addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); + addExtensionPrerequisite("GL_OES_EGL_image_external"); } - if (traceNameIs("summoners_war")) + if (traceNameIs("pubg_mobile_skydive") || traceNameIs("pubg_mobile_battle_royale")) { - if (isIntelWinANGLE) - { - skipTest("TODO: http://anglebug.com/42264477 GL_INVALID_ENUM on Windows/Intel"); - } - - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } + addExtensionPrerequisite("GL_EXT_texture_buffer"); } - if (traceNameIs("pokemon_go")) + if (traceNameIs("scrabble_go")) { - addExtensionPrerequisite("GL_EXT_texture_cube_map_array"); addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - - if (isIntelLinuxANGLE) - { - skipTest("TODO: http://anglebug.com/42264520 Intel Linux crashing on teardown"); - } - - if (isIntelLinuxNative) - { - skipTest("TODO: http://anglebug.com/392938092 flaky crash"); - } - - if (isIntelWinANGLE) - { - skipTest("TODO: http://anglebug.com/42264526 Intel Windows timing out periodically"); - } } - if (traceNameIs("cookie_run_kingdom")) + if (traceNameIs("world_of_kings")) { - addExtensionPrerequisite("GL_EXT_texture_cube_map_array"); addExtensionPrerequisite("GL_OES_EGL_image_external"); } - if (traceNameIs("genshin_impact")) + if (traceNameIs("nier_reincarnation")) { addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - - if (isNVIDIAWinANGLE || isNVIDIALinuxANGLE) - { - skipTest("http://anglebug.com/42265965 Nondeterministic noise between runs"); - } - - if (isIntelLinuxANGLE) - { - skipTest("TODO: http://anglebug.com/42264560 Crashes on Linux Intel Vulkan"); - } - - if (IsQualcomm() && mParams->isVulkan()) - { - skipTest("TODO: http://anglebug.com/378464990 Crashes on Qualcomm (Pixel 4)"); - } - - if (!Is64Bit()) - { - skipTest("Genshin is too large to handle in 32-bit mode"); - } - } - - if (traceNameIs("mario_kart_tour")) - { - if (isIntelLinuxNative) - { - skipTest("http://anglebug.com/42265205 Fails on native Mesa"); - } - } - - if (traceNameIs("pubg_mobile_skydive") || traceNameIs("pubg_mobile_battle_royale")) - { - addExtensionPrerequisite("GL_EXT_texture_buffer"); - - if (isIntelWinNative || isNVIDIALinuxNative || isNVIDIAWinNative) - { - skipTest( - "TODO: http://anglebug.com/42264759 Internal errors on Windows/Intel and NVIDIA"); - } - } - - if (traceNameIs("sakura_school_simulator")) - { - if (isIntelWin) - { - skipTest("http://anglebug.com/42264813 Flaky on Intel"); - } - } - - if (traceNameIs("scrabble_go")) - { - addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - } - - if (traceNameIs("world_of_kings")) - { - addExtensionPrerequisite("GL_OES_EGL_image_external"); - if (isIntelWin) - { - skipTest("http://anglebug.com/42264888 Flaky on Intel"); - } - } - - if (traceNameIs("nier_reincarnation")) - { - addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - } - - if (traceNameIs("mini_world")) - { - if ((IsPixel4() || IsPixel4XL()) && mParams->isVulkan()) - { - skipTest( - "TODO: http://anglebug.com/42264956 Vulkan Test failure on Pixel4XL due to vulkan " - "validation error VUID-vkDestroyBuffer-buffer-00922"); - } - if (isIntelWinNative) - { - skipTest("https://anglebug.com/42266865 Flaky on native Win Intel"); - } - } - - if (traceNameIs("pokemon_unite")) - { - addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - - if (IsIntel()) - { - skipTest( - "http://anglebug.com/42265045 nondeterministic on Intel+Windows. Crashes on Linux " - "Intel"); - } } if (traceNameIs("world_cricket_championship_2")) { addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - - if (isIntelLinuxNative) - { - skipTest("http://anglebug.com/42265152 Native test timing out on Intel Linux"); - } - } - - if (traceNameIs("zillow")) - { - if (isNVIDIAWinANGLE || isNVIDIALinuxANGLE) - { - skipTest("http://anglebug.com/42265153 Crashing in Vulkan backend"); - } - - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } } if (traceNameIs("township")) @@ -1347,22 +1157,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("pubg_mobile_launch")) - { - if (isNVIDIALinuxNative) - { - skipTest("http://anglebug.com/40644857 Crashing in Nvidia GLES driver"); - } - } - - if (traceNameIs("star_wars_kotor")) - { - if (IsLinux() && mParams->isSwiftshader()) - { - skipTest("TODO: http://anglebug.com/42266034 Flaky on Swiftshader"); - } - } - if (traceNameIs("dead_by_daylight")) { addExtensionPrerequisite("GL_EXT_shader_framebuffer_fetch"); @@ -1379,26 +1173,9 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_EXT_texture_storage"); } - if (traceNameIs("marvel_strike_force")) - { - if ((IsAndroid() && IsQualcomm()) && !mParams->isANGLE()) - { - skipTest( - "http://anglebug.com/42265489 Qualcomm native driver gets confused about the state " - "of " - "a buffer that was recreated during the trace"); - } - } - if (traceNameIs("real_racing3")) { addExtensionPrerequisite("GL_EXT_shader_framebuffer_fetch"); - if (isNVIDIAWinANGLE || isNVIDIALinuxANGLE) - { - skipTest( - "http://anglebug.com/377923479 SYNC-HAZARD-WRITE-AFTER-WRITE on Linux 535.183.01 " - "Windows 31.0.15.4601"); - } } if (traceNameIs("blade_and_soul_revolution")) @@ -1415,21 +1192,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) if (traceNameIs("car_chase")) { - if (isIntelWin) - { - skipTest("http://anglebug.com/42265648 Fails on Intel HD 630 Mobile"); - } - - if (isIntelLinux) - { - skipTest("http://anglebug.com/42265598#comment9 Flaky hang on UHD630 Mesa 20.0.8"); - } - - if (isNVIDIAWinANGLE || isNVIDIALinuxANGLE) - { - skipTest("http://anglebug.com/42265598 Renders incorrectly on NVIDIA"); - } - addExtensionPrerequisite("GL_EXT_geometry_shader"); addExtensionPrerequisite("GL_EXT_primitive_bounding_box"); addExtensionPrerequisite("GL_EXT_tessellation_shader"); @@ -1437,25 +1199,8 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_EXT_texture_cube_map_array"); } - if (traceNameIs("pokemon_masters_ex")) - { - if (isIntelLinux) - { - skipTest( - "https://issuetracker.google.com/u/2/issues/326199738#comment3 Renders incorrectly " - "on Intel Linux"); - } - } - if (traceNameIs("aztec_ruins_high")) { - if (isIntelWinANGLE) - { - skipTest( - "TODO: http://anglebug.com/353690308 Non-deterministic image on UHD770 " - "31.0.101.5333"); - } - addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } @@ -1466,11 +1211,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) if (traceNameIs("tessellation")) { - if (isNVIDIAWinANGLE || isNVIDIALinuxANGLE) - { - skipTest("http://anglebug.com/42265714 Tessellation driver bugs on Nvidia"); - } - addExtensionPrerequisite("GL_EXT_geometry_shader"); addExtensionPrerequisite("GL_EXT_primitive_bounding_box"); addExtensionPrerequisite("GL_EXT_tessellation_shader"); @@ -1501,16 +1241,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) if (traceNameIs("antutu_refinery")) { - if (isIntelLinuxANGLE || isAMDLinuxANGLE) - { - skipTest("https://anglebug.com/342545097 fails on Mesa 23.2.1"); - } - - if (isIntelWinANGLE) - { - skipTest("https://anglebug.com/379886383 times out on Windows Intel"); - } - addExtensionPrerequisite("GL_ANDROID_extension_pack_es31a"); } @@ -1519,64 +1249,20 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); } - if (traceNameIs("eve_echoes")) - { - if (IsQualcomm() && mParams->isVulkan()) - { - skipTest( - "TODO: http://anglebug.com/42266157 Test crashes in LLVM on Qualcomm (Pixel 4)"); - } - } - if (traceNameIs("life_is_strange")) { - if (isNVIDIAWinANGLE) - { - skipTest("http://anglebug.com/42266193 Renders incorrectly on Nvidia Windows"); - } - - if (isNVIDIALinuxANGLE) - { - skipTest("https://anglebug.com/362728695 Renders incorrectly on Linux/NVIDIA"); - } - addExtensionPrerequisite("GL_EXT_texture_buffer"); addExtensionPrerequisite("GL_EXT_texture_cube_map_array"); } - if (traceNameIs("survivor_io")) - { - if (isNVIDIAWinANGLE) - { - skipTest("http://anglebug.com/42266203 Renders incorrectly on Nvidia Windows"); - } - - if (isIntelWinNative) - { - skipTest( - "http://anglebug.com/42266207 Programs fail to link on Intel Windows native " - "driver, " - "citing MAX_UNIFORM_LOCATIONS exceeded"); - } - } - if (traceNameIs("minetest")) { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } addExtensionPrerequisite("GL_EXT_texture_format_BGRA8888"); addIntegerPrerequisite(GL_MAX_TEXTURE_UNITS, 4); } if (traceNameIs("diablo_immortal")) { - if (IsQualcomm() && mParams->isVulkan()) - { - skipTest("TODO: http://anglebug.com/378464990 Crashes on Qualcomm (Pixel 4)"); - } - addExtensionPrerequisite("GL_EXT_shader_framebuffer_fetch"); } @@ -1592,46 +1278,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_EXT_shader_framebuffer_fetch"); } - if (traceNameIs("five_nights_at_freddys")) - { - if (isIntelWinANGLE) - { - skipTest("http://anglebug.com/42266395 Too slow on Win Intel Vulkan"); - } - } - - if (traceNameIs("pubg_mobile_launch")) - { - if (isIntelWinNative || isIntelWinANGLE) - { - skipTest("http://anglebug.com/42266395 Too slow on Win Intel native and Vulkan"); - } - } - - if (traceNameIs("beach_buggy_racing")) - { - if (isIntelWinANGLE) - { - skipTest("http://anglebug.com/42266401 Flaky context lost on Win Intel Vulkan"); - } - } - - if (traceNameIs("aliexpress")) - { - if (isIntelWinNative) - { - skipTest("http://anglebug.com/42266401 Flaky failure on Win Intel native"); - } - } - - if (traceNameIs("final_fantasy")) - { - if (IsAndroid() && IsPixel6() && !mParams->isANGLE()) - { - skipTest("http://anglebug.com/42266403 Crashes on Pixel 6 native"); - } - } - if (traceNameIs("limbo")) { addExtensionPrerequisite("GL_EXT_shader_framebuffer_fetch"); @@ -1640,80 +1286,15 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addExtensionPrerequisite("GL_EXT_texture_storage"); } - if (traceNameIs("into_the_dead_2")) - { - if (isNVIDIAWinANGLE) - { - skipTest("http://anglebug.com/42266499 Non-deterministic trace"); - } - } - if (traceNameIs("arknights")) { // Intel doesn't support external images. addExtensionPrerequisite("GL_OES_EGL_image_external"); } - if (traceNameIs("street_fighter_duel")) - { - if (isNVIDIAWinANGLE) - { - skipTest("https://anglebug.com/42266525 NVIDIA Windows flaky diffs"); - } - } - if (traceNameIs("honkai_star_rail")) { addExtensionPrerequisite("GL_KHR_texture_compression_astc_ldr"); - if (isIntelWin) - { - skipTest("https://anglebug.com/42266613 Consistently stuck on Intel/windows"); - } - } - - if (traceNameIs("gangstar_vegas")) - { - if (mParams->isSwiftshader()) - { - skipTest("TODO: http://anglebug.com/42266611 Missing shadows on Swiftshader"); - } - } - - if (traceNameIs("respawnables")) - { - if (!mParams->isANGLE() && (IsWindows() || IsLinux())) - { - skipTest("TODO: https://anglebug.com/42266627 Undefined behavior on native"); - } - } - - if (traceNameIs("street_fighter_iv_ce")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - - if (mParams->isSwiftshader()) - { - skipTest("https://anglebug.com/42266679 Too slow on Swiftshader (large keyframe)"); - } - } - - if (traceNameIs("monster_hunter_stories")) - { - if (isIntelWinANGLE) - { - skipTest("http://anglebug.com/42266025 Flaky context lost on Win Intel Vulkan"); - } - } - - if (traceNameIs("injustice_2")) - { - if (isNVIDIAWinANGLE) - { - skipTest("https://anglebug.com/42266746 NVIDIA Windows flaky diffs"); - } } if (traceNameIs("toca_life_world")) @@ -1727,72 +1308,6 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) addIntegerPrerequisite(GL_MAX_TEXTURE_SIZE, 16383); } - if (traceNameIs("dr_driving")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("plague_inc")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("sonic_the_hedgehog")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("wayward_souls")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("wordscapes")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("zenonia_4")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("zombie_smasher")) - { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } - } - - if (traceNameIs("modern_combat_5")) - { - if (IsPixel6() && !IsAndroid14OrNewer()) - { - skipTest( - "https://issuetracker.google.com/42267261 Causing thermal failures on Pixel 6 with " - "Android 13"); - } - } - if (traceNameIs("grand_mountain_adventure")) { addIntegerPrerequisite(GL_MAX_TEXTURE_SIZE, 11016); @@ -1800,86 +1315,21 @@ TracePerfTest::TracePerfTest(std::unique_ptr params) if (traceNameIs("passmark_simple")) { - if (isIntelLinuxNative) - { - skipTest("https://anglebug.com/42267118 fails on newer OS/driver"); - } addExtensionPrerequisite("GL_OES_framebuffer_object"); } - if (traceNameIs("passmark_complex")) - { - if (isIntelLinuxNative) - { - skipTest("b/362801312 eglCreateContext fails on Mesa 23.2.1"); - } - } - - if (traceNameIs("critical_ops")) - { - if (isNVIDIALinuxANGLE || isNVIDIAWinANGLE) - { - skipTest("https://anglebug.com/365524876 Renders incorrectly on Nvidia"); - } - } - - if (traceNameIs("dota_underlords")) + if (traceNameIs("minecraft_vibrant_visuals")) { - if (isNVIDIALinuxANGLE || isNVIDIAWinANGLE) - { - skipTest( - "https://anglebug.com/369533074 Flaky on Nvidia Linux 535.183.1.0 Windows " - "31.0.15.4601"); - } + addIntegerPrerequisite(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, 1024); } - if (traceNameIs("going_balls")) + if (traceNameIs("love_and_deepspace")) { - if (isIntelWinANGLE) - { - skipTest("https://issuetracker.google.com/372513853 Nondeterministic on Windows Intel"); - } + addIntegerPrerequisite(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 6); } - if (traceNameIs("solar_smash")) - { - if (isIntelWinANGLE) - { - skipTest("https://issuetracker.google.com/378900717 Nondeterministic on Windows Intel"); - } - } - - if (traceNameIs("balatro")) - { - if (isNVIDIALinuxANGLE || isNVIDIAWinANGLE) - { - skipTest("https://anglebug.com/382960265 Renders incorrectly on Nvidia"); - } - } - - if (traceNameIs("monopoly_go")) - { - if (isNVIDIALinuxANGLE || isIntelWinANGLE || isIntelLinuxANGLE) - { - skipTest("https://anglebug.com/385226328 crashes in UpdateClientBufferData()"); - } - } - - if (IsGalaxyS22()) - { - if (traceNameIs("cod_mobile") || traceNameIs("dota_underlords") || - traceNameIs("marvel_snap") || traceNameIs("nier_reincarnation") || - traceNameIs("pokemon_unite") || traceNameIs("slingshot_test1") || - traceNameIs("slingshot_test2") || traceNameIs("supertuxkart") || - traceNameIs("the_witcher_monster_slayer") || traceNameIs("warcraft_rumble") || - traceNameIs("critical_ops")) - { - skipTest("https://issuetracker.google.com/267953710 Trace needs triage on Galaxy S22"); - } - } - - // glDebugMessageControlKHR and glDebugMessageCallbackKHR crash on ARM GLES1. - if (IsARM() && mParams->traceInfo.contextClientMajorVersion == 1) + // GL_KHR_debug does not work on Android for GLES1 + if (IsAndroid() && mParams->traceInfo.contextClientMajorVersion == 1) { mEnableDebugCallback = false; } @@ -2163,19 +1613,6 @@ void TracePerfTest::drawBenchmark() buffer = 0; // gles1: a single frame is rendered to buffer 0 } bindFramebuffer(GL_FRAMEBUFFER, buffer); - - GLsync sync = mOffscreenSyncs[offscreenBufferIndex]; - if (sync) - { - constexpr GLuint64 kTimeout = 2'000'000'000; // 2 seconds - GLenum result = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, kTimeout); - if (result != GL_CONDITION_SATISFIED && result != GL_ALREADY_SIGNALED) - { - failTest(std::string("glClientWaitSync unexpected result: ") + - std::to_string(result)); - } - glDeleteSync(sync); - } } char frameName[32]; @@ -2184,11 +1621,22 @@ void TracePerfTest::drawBenchmark() startGpuTimer(); atraceCounter("TraceFrameIndex", mCurrentFrame); + + const double beginReplayFrameTimeSec = mTrialTimer.getElapsedWallClockTime(); mTraceReplay->replayFrame(mCurrentFrame); - stopGpuTimer(); + mFrameWallTimeSec += mTrialTimer.getElapsedWallClockTime() - beginReplayFrameTimeSec; + + if (!gAddSwapIntoGPUTime) + { + stopGpuTimer(); + } updatePerfCounters(); + // Need to exclude potentially expensive calls above from the Frame Time. + const double beginSwapTimeSec = + gAddSwapIntoFrameWallTime ? mTrialTimer.getElapsedWallClockTime() : 0.0; + if (mParams->surfaceType == SurfaceType::Offscreen) { if (gMinimizeGPUWork) @@ -2259,7 +1707,6 @@ void TracePerfTest::drawBenchmark() saveScreenshotIfEnabled(ScreenshotType::kGrid); } getGLWindow()->swap(); - glClear(GL_COLOR_BUFFER_BIT); mOffscreenFrameCount = 0; } else @@ -2283,6 +1730,20 @@ void TracePerfTest::drawBenchmark() bindFramebuffer(GL_READ_FRAMEBUFFER, currentReadFBO); } + // Wait for the next frame here to simulate the behaviour of the swap buffers call + GLsync sync = mOffscreenSyncs[(offscreenBufferIndex + 1) % mMaxOffscreenBufferCount]; + if (sync) + { + constexpr GLuint64 kTimeout = 2'000'000'000; // 2 seconds + GLenum result = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, kTimeout); + if (result != GL_CONDITION_SATISFIED && result != GL_ALREADY_SIGNALED) + { + failTest(std::string("glClientWaitSync unexpected result: ") + + std::to_string(result)); + } + glDeleteSync(sync); + } + if (currentEglContext != mEglContext) { eglMakeCurrent(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW), @@ -2297,6 +1758,22 @@ void TracePerfTest::drawBenchmark() getGLWindow()->swap(); } + if (gAddSwapIntoFrameWallTime) + { + const double endSwapTimeSec = mTrialTimer.getElapsedWallClockTime(); + mFrameWallTimeSec += endSwapTimeSec - beginSwapTimeSec; + } + + if (gAddSwapIntoGPUTime) + { + // No need flush here since swap already performs it implicitly and we already call flush + // in case of the offscreen test. + stopGpuTimer(false); + // Need this flush to submit the timestamp query to the GPU right now, instead of delaying + // it until some time later in the next frame. + glFlush(); + } + endInternalTraceEvent(frameName); mTotalFrameCount++; @@ -2305,6 +1782,8 @@ void TracePerfTest::drawBenchmark() { mTraceReplay->resetReplay(); mCurrentFrame = mStartFrame; + // Flush to avoid gpu_time tracking issues on some platforms (Native GLES Qualcomm). + glFlush(); } else { diff --git a/src/tests/perf_tests/TracePerfTest.h b/src/tests/perf_tests/TracePerfTest.h index e4abecdc0af..e66490ae0b7 100644 --- a/src/tests/perf_tests/TracePerfTest.h +++ b/src/tests/perf_tests/TracePerfTest.h @@ -11,6 +11,7 @@ #include #include "tests/perf_tests/ANGLEPerfTest.h" #include "tests/perf_tests/ANGLEPerfTestArgs.h" +#include "tests/test_expectations/GPUTestExpectationsParser.h" #include "util/capture/frame_capture_test_utils.h" #include "util/test_utils.h" @@ -39,6 +40,8 @@ struct TracePerfParams final : public RenderTestParams // Display the frame after every drawBenchmark invocation iterationsPerStep = 1; + trackGpuTime = gTrackGPUTime; + driver = driverType; eglParameters.renderer = platformType; eglParameters.deviceType = deviceType; diff --git a/src/tests/perf_tests/TracePerfTestCL.cpp b/src/tests/perf_tests/TracePerfTestCL.cpp index 2cac3abc392..d3a4611244f 100644 --- a/src/tests/perf_tests/TracePerfTestCL.cpp +++ b/src/tests/perf_tests/TracePerfTestCL.cpp @@ -7,6 +7,10 @@ // Performance test for ANGLE CL replaying traces. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "tests/perf_tests/ANGLEComputeTestCL.h" #include "tests/perf_tests/TracePerfTest.h" diff --git a/src/tests/perf_tests/UniformsPerf.cpp b/src/tests/perf_tests/UniformsPerf.cpp index d4a4010352d..e8cb509fed3 100644 --- a/src/tests/perf_tests/UniformsPerf.cpp +++ b/src/tests/perf_tests/UniformsPerf.cpp @@ -7,6 +7,10 @@ // Performance test for setting uniform data. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include @@ -150,6 +154,7 @@ class UniformsBenchmark : public ANGLERenderTest, std::vector GenMatrixData(size_t count, int parity) { std::vector data; + data.reserve(count); // Very simple matrix data allocation scheme. for (size_t index = 0; index < count; ++index) @@ -516,7 +521,6 @@ ANGLE_INSTANTIATE_TEST( VectorUniforms(METAL(), DataMode::REPEAT), VectorUniforms(OPENGL_OR_GLES(), DataMode::UPDATE), VectorUniforms(OPENGL_OR_GLES(), DataMode::REPEAT), - VectorUniforms(OPENGL_OR_GLES_NULL(), DataMode::UPDATE), MatrixUniforms(D3D11(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE), MatrixUniforms(METAL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE), MatrixUniforms(OPENGL_OR_GLES(), diff --git a/src/tests/perf_tests/VertexArrayPerfTest.cpp b/src/tests/perf_tests/VertexArrayPerfTest.cpp index 98faca5d671..c0003f48f53 100644 --- a/src/tests/perf_tests/VertexArrayPerfTest.cpp +++ b/src/tests/perf_tests/VertexArrayPerfTest.cpp @@ -7,6 +7,10 @@ // Performance test for glBindVertexArray. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLEPerfTest.h" #include "DrawCallPerfParams.h" #include "test_utils/gl_raii.h" diff --git a/src/tests/perf_tests/VulkanBarriersPerf.cpp b/src/tests/perf_tests/VulkanBarriersPerf.cpp index 524a08645b8..a86c926b592 100644 --- a/src/tests/perf_tests/VulkanBarriersPerf.cpp +++ b/src/tests/perf_tests/VulkanBarriersPerf.cpp @@ -7,6 +7,10 @@ // Performance tests for ANGLE's Vulkan backend w.r.t barrier efficiency. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "ANGLEPerfTest.h" diff --git a/src/tests/perf_tests/VulkanCommandBufferPerf.cpp b/src/tests/perf_tests/VulkanCommandBufferPerf.cpp index 555f4efe7c0..edbe06f942e 100644 --- a/src/tests/perf_tests/VulkanCommandBufferPerf.cpp +++ b/src/tests/perf_tests/VulkanCommandBufferPerf.cpp @@ -7,6 +7,11 @@ // Can run just these tests by adding "--gtest_filter=VulkanCommandBufferPerfTest*" // option to angle_white_box_perftests. // When running on Android with run_angle_white_box_perftests, use "-v" option. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "ANGLEPerfTest.h" #include "common/platform.h" diff --git a/src/tests/perf_tests/VulkanPipelineCachePerf.cpp b/src/tests/perf_tests/VulkanPipelineCachePerf.cpp index 01af1330cc8..26068f41766 100644 --- a/src/tests/perf_tests/VulkanPipelineCachePerf.cpp +++ b/src/tests/perf_tests/VulkanPipelineCachePerf.cpp @@ -5,6 +5,11 @@ // // VulkanPipelineCachePerf: // Performance benchmark for the Vulkan Pipeline cache. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "ANGLEPerfTest.h" @@ -118,8 +123,9 @@ void VulkanPipelineCachePerfTest::step() { if (!mCache.getPipeline(hit, &desc, &result)) { - (void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, ssm, defaultSpecConsts, - PipelineSource::Draw, hit, &desc, &result); + (void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, + {&ssm, &defaultSpecConsts}, PipelineSource::Draw, hit, + &desc, &result); } } } @@ -130,7 +136,7 @@ void VulkanPipelineCachePerfTest::step() const auto &miss = mCacheMisses[mMissIndex]; if (!mCache.getPipeline(miss, &desc, &result)) { - (void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, ssm, defaultSpecConsts, + (void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, {&ssm, &defaultSpecConsts}, PipelineSource::Draw, miss, &desc, &result); } } diff --git a/src/tests/perf_tests/angle_trace_tests_expectations.txt b/src/tests/perf_tests/angle_trace_tests_expectations.txt new file mode 100644 index 00000000000..7090add7492 --- /dev/null +++ b/src/tests/perf_tests/angle_trace_tests_expectations.txt @@ -0,0 +1,253 @@ +// Copyright 2025 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. + +// See deqp_support/README.md for format. + +42266611 SWIFTSHADER : gangstar_vegas = SKIP +42266679 SWIFTSHADER : street_fighter_iv_ce = SKIP +42266627 WIN NATIVE : respawnables = SKIP +42266627 LINUX NATIVE : respawnables = SKIP +42266627 PIXEL4ORXL NATIVE : respawnables = SKIP +42266627 PIXEL6 NATIVE : respawnables = SKIP +42266034 LINUX SWIFTSHADER : star_wars_kotor = SKIP + +267953710 GALAXYS22 : cod_mobile = SKIP +267953710 GALAXYS22 : dota_underlords = SKIP +267953710 GALAXYS22 : marvel_snap = SKIP +267953710 GALAXYS22 : nier_reincarnation = SKIP +267953710 GALAXYS22 : pokemon_unite = SKIP +267953710 GALAXYS22 : slingshot_test1 = SKIP +267953710 GALAXYS22 : slingshot_test2 = SKIP +267953710 GALAXYS22 : supertuxkart = SKIP +267953710 GALAXYS22 : the_witcher_monster_slayer = SKIP +267953710 GALAXYS22 : warcraft_rumble = SKIP +267953710 GALAXYS22 : critical_ops = SKIP + +410630704 GALAXYS24EXYNOS : agent_a = SKIP +410630704 GALAXYS24EXYNOS : arena_of_valor = SKIP +415852525 GALAXYS24EXYNOS : cash_frenzy_casino_slots = SKIP +410630704 GALAXYS24EXYNOS : critical_ops = SKIP +410630704 GALAXYS24EXYNOS : cod_mobile = SKIP +410630704 GALAXYS24EXYNOS : dota_underlords = SKIP +415852525 GALAXYS24EXYNOS : genshin_impact = SKIP +410630704 GALAXYS24EXYNOS : magic_tiles_3 = SKIP +410630704 GALAXYS24EXYNOS : manhattan_10 = SKIP +410630704 GALAXYS24EXYNOS : manhattan_31 = SKIP +410630704 GALAXYS24EXYNOS : marvel_snap = SKIP +410630704 GALAXYS24EXYNOS : nier_reincarnation = SKIP +410630704 GALAXYS24EXYNOS : pokemon_unite = SKIP +410630704 GALAXYS24EXYNOS : sakura_school_simulator = SKIP +410630704 GALAXYS24EXYNOS : slingshot_test1 = SKIP +410630704 GALAXYS24EXYNOS : slingshot_test2 = SKIP +410630704 GALAXYS24EXYNOS : star_trek_fleet_command = SKIP +410630704 GALAXYS24EXYNOS : supertuxkart = SKIP +410630704 GALAXYS24EXYNOS : the_witcher_monster_slayer = SKIP +410630704 GALAXYS24EXYNOS : warcraft_rumble = SKIP +415852525 GALAXYS24EXYNOS : black_beacon = SKIP +410630704 GALAXYS24EXYNOS : minecraft_vibrant_visuals = SKIP + +42264359 ANDROID PIXEL4ORXL NATIVE : dead_trigger_2 = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : cut_the_rope = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : critical_ops = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : hill_climb_racing = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : disney_mirrorverse = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : geometry_dash = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : total_battle = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : block_craft_3d = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : cashman_casino = SKIP +42264359 ANDROID PIXEL4ORXL NATIVE : lightning_link = SKIP +450251026 ANDROID PIXEL6 VULKAN : black_beacon = SKIP +42266403 ANDROID PIXEL6 NATIVE : final_fantasy = SKIP + +42265489 ANDROID QUALCOMM NATIVE : marvel_strike_force = SKIP +42264956 PIXEL4ORXL VULKAN : mini_world = SKIP +378464990 PIXEL4ORXL VULKAN : diablo_immortal = SKIP +42266157 PIXEL4ORXL VULKAN : eve_echoes = SKIP +378464990 QUALCOMM VULKAN : genshin_impact = SKIP +404436749 PIXEL4ORXL VULKAN : aliexpress = SKIP + +42264164 LINUX AMD NATIVE : bus_simulator_indonesia = SKIP +42264363 LINUX AMD NATIVE : professional_baseball_spirits = SKIP +42264358 LINUX AMD NATIVE : real_gangster_crime = SKIP +342545097 LINUX AMD VULKAN : antutu_refinery = SKIP +42264158 WIN AMD VULKAN : happy_color = SKIP +1187752 WIN AMD VULKAN : plants_vs_zombies_2 = SKIP + +42265045 INTEL : pokemon_unite = SKIP +42265598 LINUX INTEL : car_chase = SKIP +326199738 LINUX INTEL : pokemon_masters_ex = SKIP +42264358 LINUX INTEL NATIVE : real_gangster_crime = SKIP +42264164 LINUX INTEL NATIVE : bus_simulator_indonesia = SKIP +42267118 LINUX INTEL NATIVE : summoners_war = SKIP +392938092 LINUX INTEL NATIVE : pokemon_go = SKIP +42265205 LINUX INTEL NATIVE : mario_kart_tour = SKIP +42265152 LINUX INTEL NATIVE : world_cricket_championship_2 = SKIP +42267118 LINUX INTEL NATIVE : zillow = SKIP +42267118 LINUX INTEL NATIVE : minetest = SKIP +42267118 LINUX INTEL NATIVE : street_fighter_iv_ce = SKIP +42267118 LINUX INTEL NATIVE : dr_driving = SKIP +42267118 LINUX INTEL NATIVE : plague_inc = SKIP +42267118 LINUX INTEL NATIVE : sonic_the_hedgehog = SKIP +42267118 LINUX INTEL NATIVE : wayward_souls = SKIP +42267118 LINUX INTEL NATIVE : wordscapes = SKIP +42267118 LINUX INTEL NATIVE : zenonia_4 = SKIP +42267118 LINUX INTEL NATIVE : zombie_smasher = SKIP +42267118 LINUX INTEL NATIVE : passmark_simple = SKIP +362801312 LINUX INTEL NATIVE : passmark_complex = SKIP +448110252 LINUX INTEL NATIVE : puzzle_and_dragons = SKIP +378666645 LINUX INTEL VULKAN : octopath_traveler = SKIP +378666645 LINUX INTEL VULKAN : dead_by_daylight = SKIP +42264055 LINUX INTEL VULKAN : saint_seiya_awakening = SKIP +42264055 LINUX INTEL VULKAN : efootball_pes_2021 = SKIP +42264351 LINUX INTEL VULKAN : league_of_legends_wild_rift = SKIP +42264343 LINUX INTEL VULKAN : dragon_raja = SKIP +42264363 LINUX INTEL VULKAN : professional_baseball_spirits = SKIP +42264374 LINUX INTEL VULKAN : call_break_offline_card_game = SKIP +42264520 LINUX INTEL VULKAN : pokemon_go = SKIP +42264560 LINUX INTEL VULKAN : genshin_impact = SKIP +342545097 LINUX INTEL VULKAN : antutu_refinery = SKIP +385226328 LINUX INTEL VULKAN : monopoly_go = SKIP +444333530 LINUX INTEL VULKAN : odin_valhalla_rising = SKIP +445419190 LINUX INTEL VULKAN : lineage_2m = SKIP +448468885 LINUX INTEL VULKAN : raising_a_goblin = SKIP + +42265065 WIN INTEL : cod_mobile = SKIP +42264813 WIN INTEL : sakura_school_simulator = SKIP +42264888 WIN INTEL : world_of_kings = SKIP +42265648 WIN INTEL : car_chase = SKIP +42266395 WIN INTEL : pubg_mobile_launch = SKIP +42266613 WIN INTEL : honkai_star_rail = SKIP +441288013 WIN INTEL : ace_racer = SKIP +40096702 WIN INTEL NATIVE : angry_birds_2_1500 = SKIP +42266865 WIN INTEL NATIVE : mini_world = SKIP +42266207 WIN INTEL NATIVE : survivor_io = SKIP +42266401 WIN INTEL NATIVE : aliexpress = SKIP +42264759 WIN INTEL NATIVE : pubg_mobile_battle_royale = SKIP +42264759 WIN INTEL NATIVE : pubg_mobile_skydive = SKIP +442286882 WIN INTEL NATIVE : minecraft_vibrant_visuals = SKIP +448110252 WIN INTEL NATIVE : puzzle_and_dragons = SKIP +459511105 WIN INTEL NATIVE : love_and_deepspace = SKIP +40096690 WIN INTEL VULKAN : manhattan_10 = SKIP +42266346 WIN INTEL VULKAN : black_desert_mobile = SKIP +42266346 WIN INTEL VULKAN : the_gardens_between = SKIP +353690308 WIN INTEL VULKAN : animal_crossing = SKIP +353690308 WIN INTEL VULKAN : black_clover_m = SKIP +42264261 WIN INTEL VULKAN : car_parking_multiplayer = SKIP +42264415 WIN INTEL VULKAN : fifa_mobile = SKIP +353690308 WIN INTEL VULKAN : aztec_ruins = SKIP +42264477 WIN INTEL VULKAN : summoners_war = SKIP +42264526 WIN INTEL VULKAN : pokemon_go = SKIP +353690308 WIN INTEL VULKAN : aztec_ruins_high = SKIP +379886383 WIN INTEL VULKAN : antutu_refinery = SKIP +42266395 WIN INTEL VULKAN : five_nights_at_freddys = SKIP +42266401 WIN INTEL VULKAN : beach_buggy_racing = SKIP +42266025 WIN INTEL VULKAN : monster_hunter_stories = SKIP +372513853 WIN INTEL VULKAN : going_balls = SKIP +378900717 WIN INTEL VULKAN : solar_smash = SKIP +385226328 WIN INTEL VULKAN : monopoly_go = SKIP +413358136 WIN INTEL VULKAN : black_beacon = SKIP +445419190 WIN INTEL VULKAN : lineage_2m = SKIP +474664078 WIN INTEL VULKAN : pokemon_go_combat = SKIP + +461532426 NVIDIA NATIVE : ace_racer = SKIP +42264147 NVIDIA NATIVE : car_parking_multiplayer = SKIP +442286938 NVIDIA NATIVE : minecraft_vibrant_visuals = SKIP +42264759 NVIDIA NATIVE : pubg_mobile_battle_royale = SKIP +40644857 NVIDIA NATIVE : pubg_mobile_launch = SKIP +42264759 NVIDIA NATIVE : pubg_mobile_skydive = SKIP +448110252 NVIDIA NATIVE : puzzle_and_dragons = SKIP +382960265 NVIDIA VULKAN : balatro = SKIP +42265598 NVIDIA VULKAN : car_chase = SKIP +365524876 NVIDIA VULKAN : critical_ops = SKIP +369533074 NVIDIA VULKAN : dota_underlords = SKIP +42265965 NVIDIA VULKAN : genshin_impact = SKIP +42266746 NVIDIA VULKAN : injustice_2 = SKIP +42266499 NVIDIA VULKAN : into_the_dead_2 = SKIP +362728695 NVIDIA VULKAN : life_is_strange = SKIP +42264199 NVIDIA VULKAN : messenger_lite = SKIP +385226328 NVIDIA VULKAN : monopoly_go = SKIP +474664078 NVIDIA VULKAN : pokemon_go_combat = SKIP +377923479 NVIDIA VULKAN : real_racing3 = SKIP +42266525 NVIDIA VULKAN : street_fighter_duel = SKIP +42266203 NVIDIA VULKAN : survivor_io = SKIP +42265714 NVIDIA VULKAN : tessellation = SKIP +42265153 NVIDIA VULKAN : zillow = SKIP + +// Translator IR failures. They are mostly due to slight changes in GOLD images, but one or two are real failures. +// Disabled until later, when we can enable the IR and accept the new GOLD images. +349994211 IR NVIDIA VULKAN : aztec_ruins = SKIP +349994211 IR NVIDIA VULKAN : aztec_ruins_high = SKIP +349994211 IR NVIDIA VULKAN : basemark_gpu = SKIP +349994211 IR NVIDIA VULKAN : bingo_blitz = SKIP +349994211 IR NVIDIA VULKAN : black_desert_mobile = SKIP +349994211 IR NVIDIA VULKAN : dc_dark_legion = SKIP +349994211 IR NVIDIA VULKAN : gangstar_vegas = SKIP +349994211 IR NVIDIA VULKAN : honkai_impact_3rd = SKIP +349994211 IR NVIDIA VULKAN : honkai_star_rail = SKIP +349994211 IR NVIDIA VULKAN : i9_inferno_nine = SKIP +349994211 IR NVIDIA VULKAN : last_war_survival_game = SKIP +349994211 IR NVIDIA VULKAN : marvel_snap = SKIP +349994211 IR NVIDIA VULKAN : off_the_road = SKIP +349994211 IR NVIDIA VULKAN : pokemon_unite = SKIP +349994211 IR NVIDIA VULKAN : ragnarok_m_eternal_love = SKIP +349994211 IR NVIDIA VULKAN : raising_a_goblin = SKIP +349994211 IR NVIDIA VULKAN : simcity_buildit = SKIP +349994211 IR NVIDIA VULKAN : subway_princess_runner = SKIP +349994211 IR NVIDIA VULKAN : war_planet_online = SKIP +349994211 IR NVIDIA VULKAN : wuthering_waves = SKIP + +349994211 IR WIN INTEL VULKAN : balatro = SKIP +349994211 IR WIN INTEL VULKAN : basemark_gpu = SKIP +349994211 IR WIN INTEL VULKAN : bullet_echo = SKIP +349994211 IR WIN INTEL VULKAN : gangstar_vegas = SKIP +349994211 IR WIN INTEL VULKAN : lego_legacy = SKIP +349994211 IR WIN INTEL VULKAN : marvel_snap = SKIP +349994211 IR WIN INTEL VULKAN : off_the_road = SKIP +349994211 IR WIN INTEL VULKAN : raising_a_goblin = SKIP +349994211 IR WIN INTEL VULKAN : simcity_buildit = SKIP +349994211 IR WIN INTEL VULKAN : warcraft_rumble = SKIP + +349994211 IR PIXEL6 VULKAN : command_and_conquer_rivals = SKIP +349994211 IR PIXEL6 VULKAN : genshin_impact = SKIP +349994211 IR PIXEL6 VULKAN : grand_mountain_adventure = SKIP +349994211 IR PIXEL6 VULKAN : identity_v = SKIP +349994211 IR PIXEL6 VULKAN : manhattan_31 = SKIP +349994211 IR PIXEL6 VULKAN : solar_smash = SKIP +349994211 IR PIXEL6 VULKAN : the_gardens_between = SKIP +349994211 IR PIXEL6 VULKAN : warcraft_rumble = SKIP +349994211 IR PIXEL6 VULKAN : agent_a = SKIP +349994211 IR PIXEL6 VULKAN : aztec_ruins = SKIP +349994211 IR PIXEL6 VULKAN : black_desert_mobile = SKIP +349994211 IR PIXEL6 VULKAN : lineage_2m = SKIP +349994211 IR PIXEL6 VULKAN : riptide_gp2 = SKIP +349994211 IR PIXEL6 VULKAN : simcity_buildit = SKIP +349994211 IR PIXEL6 VULKAN : streets_of_rage_4 = SKIP +349994211 IR PIXEL6 VULKAN : the_sims_mobile = SKIP +349994211 IR PIXEL6 VULKAN : asphalt_8 = SKIP +349994211 IR PIXEL6 VULKAN : aztec_ruins_high = SKIP +349994211 IR PIXEL6 VULKAN : beach_buggy_racing = SKIP +349994211 IR PIXEL6 VULKAN : dc_dark_legion = SKIP +349994211 IR PIXEL6 VULKAN : disney_mirrorverse = SKIP +349994211 IR PIXEL6 VULKAN : eve_echoes = SKIP +349994211 IR PIXEL6 VULKAN : honkai_star_rail = SKIP +349994211 IR PIXEL6 VULKAN : knives_out = SKIP +349994211 IR PIXEL6 VULKAN : lego_legacy = SKIP +349994211 IR PIXEL6 VULKAN : asphalt_9 = SKIP +349994211 IR PIXEL6 VULKAN : lands_of_jail = SKIP +349994211 IR PIXEL6 VULKAN : marvel_snap = SKIP +349994211 IR PIXEL6 VULKAN : real_racing3 = SKIP +349994211 IR PIXEL6 VULKAN : slam_dunk_from_tv_animation = SKIP +349994211 IR PIXEL6 VULKAN : asphalt_9_2024 = SKIP +349994211 IR PIXEL6 VULKAN : balatro = SKIP +349994211 IR PIXEL6 VULKAN : car_chase = SKIP +349994211 IR PIXEL6 VULKAN : gangstar_vegas = SKIP +349994211 IR PIXEL6 VULKAN : off_the_road = SKIP +349994211 IR PIXEL6 VULKAN : raid_shadow_legends = SKIP +349994211 IR PIXEL6 VULKAN : survivor_io = SKIP +349994211 IR PIXEL6 VULKAN : basemark_gpu = SKIP +349994211 IR PIXEL6 VULKAN : harry_potter_magic_awakened = SKIP +349994211 IR PIXEL6 VULKAN : into_the_dead_2 = SKIP +349994211 IR PIXEL6 VULKAN : portal_knights = SKIP +349994211 IR PIXEL6 VULKAN : raising_a_goblin = SKIP +349994211 IR PIXEL6 VULKAN : war_planet_online = SKIP diff --git a/src/tests/perf_tests/glmark2Benchmark.cpp b/src/tests/perf_tests/glmark2Benchmark.cpp index d65b5288530..c19b7e63f4a 100644 --- a/src/tests/perf_tests/glmark2Benchmark.cpp +++ b/src/tests/perf_tests/glmark2Benchmark.cpp @@ -7,6 +7,10 @@ // Runs the glmark2 benchmark. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include diff --git a/src/tests/perf_tests/third_party/perf/perf_test.cc b/src/tests/perf_tests/third_party/perf/perf_test.cc index 5c3de9e2ee1..745d841c75e 100644 --- a/src/tests/perf_tests/third_party/perf/perf_test.cc +++ b/src/tests/perf_tests/third_party/perf/perf_test.cc @@ -2,8 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "perf_test.h" +#include "common/angleutils.h" #include "common/base/anglebase/no_destructor.h" #include @@ -32,6 +37,7 @@ std::string FormatString(const char *fmt, va_list vararg) return std::string(buffer->data(), len); } +ANGLE_FORMAT_PRINTF(1, 2) std::string StringPrintf(const char *fmt, ...) { va_list vararg; @@ -43,7 +49,7 @@ std::string StringPrintf(const char *fmt, ...) std::string NumberToString(size_t value) { - return StringPrintf("%u", value); + return StringPrintf("%zu", value); } std::string NumberToString(double value) diff --git a/src/tests/preprocessor_tests/char_test.cpp b/src/tests/preprocessor_tests/char_test.cpp index 715d022f5e3..369b8c6ce59 100644 --- a/src/tests/preprocessor_tests/char_test.cpp +++ b/src/tests/preprocessor_tests/char_test.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include diff --git a/src/tests/preprocessor_tests/input_test.cpp b/src/tests/preprocessor_tests/input_test.cpp index 599fadd680d..d6e0d6f9189 100644 --- a/src/tests/preprocessor_tests/input_test.cpp +++ b/src/tests/preprocessor_tests/input_test.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "compiler/preprocessor/Input.h" #include "PreprocessorTest.h" #include "compiler/preprocessor/Token.h" diff --git a/src/tests/py_utils/android_helper.py b/src/tests/py_utils/android_helper.py index 19cbd908186..ad9da21db43 100644 --- a/src/tests/py_utils/android_helper.py +++ b/src/tests/py_utils/android_helper.py @@ -78,7 +78,7 @@ def _InitializeAndroid(apk_path): if _Global.IsMultiUser(): # TODO(b/361388557): Switch to a content provider for this, i.e. `content write` logging.warning( - 'Using app dir for external storage, may not work with chromium scripts, may require `setenforce 0`' + '\n\n!!!!! Using app dir for external storage, may not work with chromium scripts, may require `setenforce 0` !!!!!\n' ) _Global.external_storage = _Global.base_dir + 'chromium_tests_root/' else: @@ -163,6 +163,12 @@ def _AdbShell(cmd): return output +def _AdbShellWithRunAs(cmd): + if _Global.use_run_as: + cmd = "run-as com.android.angle.test sh -c '{cmd}'".format(cmd=cmd) + return _AdbShell(cmd) + + def _GetAdbRoot(shell_id, su_path): if int(shell_id) == 0: logging.info('adb already got root') @@ -232,7 +238,10 @@ def _AddRestrictedTracesJson(): '../../src/tests/restricted_traces/*/*.json', 'gen/trace_list.json', ]) - _AdbShell('r=' + _Global.external_storage + '; tar -xf $r/t.tar -C $r/ && rm $r/t.tar') + _AdbShell( + 'r=' + _Global.external_storage + + '; tar --no-same-permissions --no-same-owner -xf $r/t.tar -C $r/ && rm $r/t.tar && chmod -R o+r $r/' + ) def _AddDeqpFiles(suite_name): @@ -255,7 +264,10 @@ def _AddDeqpFiles(suite_name): patterns.append('gen/vk_gl_cts_data/data/gles2/data/brick.png') _MakeTar(_Global.external_storage + 'deqp.tar', patterns) - _AdbShell('r=' + _Global.external_storage + '; tar -xf $r/deqp.tar -C $r/ && rm $r/deqp.tar') + _AdbShell( + 'r=' + _Global.external_storage + + '; tar --no-same-permissions --no-same-owner -xf $r/deqp.tar -C $r/ && rm $r/deqp.tar && chmod -R o+r $r/' + ) def _GetDeviceApkPath(): @@ -341,6 +353,10 @@ def PrepareTestSuite(suite_name): if suite_name == ANGLE_TRACE_TEST_SUITE: _AddRestrictedTracesJson() + _AdbRun([ + 'push', '../../src/tests/perf_tests/angle_trace_tests_expectations.txt', + _Global.external_storage + 'src/tests/perf_tests/angle_trace_tests_expectations.txt' + ]) if '_deqp_' in suite_name: _AddDeqpFiles(suite_name) @@ -411,6 +427,9 @@ def _PushLibToAppDir(lib_name): logging.info('Syncing %s trace (%d/%d)', trace, idx + 1, len(traces)) path_from_root = 'src/tests/restricted_traces/' + trace + '/' + trace + '.angledata.gz' + # If compressed binary data file does not exist use correct uncompressed filename + if not os.path.exists('../../' + path_from_root): + path_from_root = 'src/tests/restricted_traces/' + trace + '/' + trace + '.angledata' _Push('../../' + path_from_root, path_from_root) if _Global.traces_outside_of_apk: @@ -468,7 +487,10 @@ def _SetCaptureProps(env, device_out_dir): 'ANGLE_CAPTURE_ENABLED': 'debug.angle.capture.enabled', 'ANGLE_CAPTURE_FRAME_START': 'debug.angle.capture.frame_start', 'ANGLE_CAPTURE_FRAME_END': 'debug.angle.capture.frame_end', + 'ANGLE_CAPTURE_MAX_RESIDENT_BINARY_SIZE': 'debug.angle.capture.max_resident_binary_size', + 'ANGLE_CAPTURE_BLOCK_SIZE': 'debug.angle.capture.block_size', 'ANGLE_CAPTURE_TRIGGER': 'debug.angle.capture.trigger', + 'ANGLE_CAPTURE_END_CAPTURE': 'debug.angle.capture.end_capture', 'ANGLE_CAPTURE_LABEL': 'debug.angle.capture.label', 'ANGLE_CAPTURE_COMPRESSION': 'debug.angle.capture.compression', 'ANGLE_CAPTURE_VALIDATION': 'debug.angle.capture.validation', @@ -605,9 +627,12 @@ def RunTests(test_suite, args, stdoutfile=None, log_output=True): if perf_output_path: _AdbRun(['pull', device_perf_path, perf_output_path]) - if log_output: + if log_output or result: logging.info(output.decode()) + if result: + logging.error('Tests failed, see stdout above') + if stdoutfile: with open(stdoutfile, 'wb') as f: f.write(output) diff --git a/src/tests/restricted_traces/README.md b/src/tests/restricted_traces/README.md index 45c1e7f7c06..7c1c20e2483 100644 --- a/src/tests/restricted_traces/README.md +++ b/src/tests/restricted_traces/README.md @@ -153,6 +153,16 @@ angle_enable_cl = true angle_extract_native_libs = true +## Capturing long traces + +The tracer will capture traces larger than the available physical memory on the +target device. However, for very long traces there may be noticeable hitching +during disk-writes once available memory is exhausted. If this becomes problematic a +release build can be used, or to minimize hitching completely, disable binary data +file compression. To do this ensure that the following property is set for capture: +``` +adb shell setprop debug.angle.capture.compression 0 +``` ## Determine the target app We first need to identify which application we want to trace. That can generally be done by @@ -234,6 +244,8 @@ adb shell setprop debug.angle.capture.frame_start 1 adb shell setprop debug.angle.capture.frame_end 100. ``` +But if you do want to capture OpenCL and the end frame isn't clear, use the end_capture feature. See [End the capture early](./README.md#end-the-capture-early) for more information. + ## Create output location We need to write out the trace file in a location accessible by the app. We use the app's data @@ -242,6 +254,28 @@ storage on sdcard, but create a subfolder to isolate ANGLE's files: adb shell mkdir -p /sdcard/Android/data/$PACKAGE_NAME/angle_capture ``` +If the [capture](#Trigger the capture) failed due +to these errors: + +``` +Output directory +'/sdcard/Android/data/$PACKAGE_NAME/angle_capture/' does not exist. +Create it over adb using mkdir. +``` + +``` +Could not open binary data file /sdcard/Android/data/$PACKAGE_NAME/angle_capture/$LABEL.angledata.gz +``` + +It means the app does not have access to /sdcard/. We will need to use the app's +own data storage, which requires enabling adb root first: + +``` +adb root +adb shell setprop debug.angle.capture.out_dir /data/data/$PACKAGE_NAME/angle_capture +adb shell mkdir -p /data/data/$PACKAGE_NAME/angle_capture +``` + ## Start the target app From here, you can start the application. You should see logcat entries like the following, @@ -326,6 +360,24 @@ Note that multiple captures are incompatible with applications using persistent If more than one capture is attempted in this situation the tracer will exit immediately. The initial capture will remain valid. +## End the capture early + +If the application doesn't have a clear known ending frame, use ```debug.angle.capture.end_capture```. + +Set frame_start. frame_end is irrelevant for ending the capture early. +``` +adb shell setprop debug.angle.capture.frame_start 1 +``` +Set end_capture to any number greater than 0. The value doesn't matter, as long as it's greater than 0. +``` +adb shell setprop debug.angle.capture.end_capture 1 +``` +Run the application. At the moment you want the capture to be done, set end_capture to 0 +``` +adb shell setprop debug.angle.capture.end_capture 0 +``` +This will capture everything up to the time you triggered the end of the capture. + ## Pull the trace files Next, we want to pull those files over to the host and run some scripts. @@ -432,7 +484,7 @@ cd screenshots And run the compare script: ``` -python3 ../src/tests/restricted_traces/compare_trace_screenshots.py versus_native --trace-list-path ../src/tests/restricted_traces/ +python3 ../src/tests/restricted_traces/compare_trace_screenshots.py versus_native --screenshot-dir . --trace-list-path ../src/tests/restricted_traces/ ``` The script will print out results comparing ANGLE vs. native screenshots at different fuzz factors. @@ -444,6 +496,30 @@ asphalt_8 angle_vulkan_asphalt_8.png angle_native_asphalt_8.png 641849 222157 11 asphalt_9 angle_vulkan_asphalt_9.png angle_native_asphalt_9.png 17919 420 305 293 232 3 ... ``` + +Script will also save difference PNG files for each fuzz factor into the `--screenshot-dir`. These +files will be saved even if there is no difference. To discard such files you may add +`--discard_zero_diff_png` (or `-d`) argument **before** the `versus_native` command. + +# Comparing screenshots in two directories at different fuzz factors + +In some cases it may be useful to compare screenshots in two directories. For example: to compare +different runs on the same device, different loops of the same replay run, runs on different +devices, and so on. + +After you have prepared screenshots for comparison, run the `fuzz_ab` command: + +``` +python3 compare_trace_screenshots.py -d fuzz_ab --a_dir /my/trace/a --b_dir /my/trace/b --out /my/trace/diff +``` + +It will compare screenshots in these directories at different fuzz factors (similar to the +`versus_native` command). In this example `-d` (`--discard_zero_diff_png`) argument was added to +only keep PNG files with the difference. + +Command also has `--relaxed_file_list_match` (`-r`) argument, allowing to compare directories with +at least single match, which may be handy in some situations. + # Upgrading existing traces With tracer updates sometimes we want to re-run tracing to upgrade the trace file format or to diff --git a/src/tests/restricted_traces/compare_trace_screenshots.py b/src/tests/restricted_traces/compare_trace_screenshots.py index 5e9ae48b5c7..25bb6cefee8 100644 --- a/src/tests/restricted_traces/compare_trace_screenshots.py +++ b/src/tests/restricted_traces/compare_trace_screenshots.py @@ -25,6 +25,12 @@ python3 compare_trace_screenshots.py versus_upgrade --before /my/trace/before --after /my/trace/after --out /my/trace/compare +* `fuzz_ab` + + Similar to `versus_upgrade` mode but uses "AE" metric with different fuzz factors like `versus_native` does + + python3 compare_trace_screenshots.py fuzz_ab --a_dir /my/trace/a --b_dir /my/trace/b --out /my/trace/diff + Prerequisites sudo apt-get install imagemagick ''' @@ -42,6 +48,60 @@ EXIT_FAILURE = 1 +def compare_with_fuzz_factors(outdir, discard_zero_diff_png, trace, a_image, b_image): + # Compare each of the images with different fuzz factors so we can see how each is doing + # `compare -metric AE -fuzz ${FUZZ} ${A_IMAGE} ${B_IMAGE} ${TRACE}_fuzz${FUZZ}_diff.png` + results = [] + for fuzz in {0, 1, 2, 5, 10, 20}: + diff_file = trace + "_fuzz" + str(fuzz) + "%_TEST_diff.png" + diff_file = os.path.join(outdir, diff_file) + command = "compare -metric AE -fuzz " + str( + fuzz) + "% " + a_image + " " + b_image + " " + diff_file + logging.debug("Running " + command) + diff = subprocess.run(command, shell=True, capture_output=True) + for line in diff.stderr.splitlines(): + if "unable to open image".encode('UTF-8') in line: + results.append("NA".encode('UTF-8')) + else: + results.append(diff.stderr) + if discard_zero_diff_png and line.split()[0] == b'0': + os.remove(diff_file) + logging.debug(" for " + trace + " " + str(fuzz) + "%") + return results + + +def get_common_files(relaxed_match, a_dir, b_dir): + # Get a list of all the files in a_dir + a_files = sorted(os.listdir(a_dir)) + + # Get a list of all the files in b_dir + b_files = sorted(os.listdir(b_dir)) + + # Can return either list if they are equal + if a_files == b_files: + return a_files + + extra_a_files = sorted(set(a_files) - set(b_files)) + extra_b_files = sorted(set(b_files) - set(a_files)) + + print("File lists don't match!") + if extra_a_files: + print("Extra '%s' files: %s" % (a_dir, extra_a_files)) + if extra_b_files: + print("Extra '%s' files: %s" % (b_dir, extra_b_files)) + + # If either list is missing files, this is a fail if relaxed_match is False + if not relaxed_match: + exit(1) + + common_files = sorted(set(a_files) & set(b_files)) + if not common_files: + print("No matches between file lists while using relaxed match!") + exit(2) + + return common_files + + def versus_native(args): # Get a list of all PNG files in the directory @@ -86,9 +146,9 @@ def get_trace_key_frame(restricted_traces_path, trace): get_traces_from_images() for trace in sorted(traces): + frame = "" if args.trace_list_path != None: keyframe = get_trace_key_frame(args.trace_list_path, trace) - frame = "" if keyframe != "": frame = "_frame" + str(keyframe) @@ -105,23 +165,8 @@ def get_trace_key_frame(restricted_traces_path, trace): if not os.path.isfile(vulkan_file): vulkan_file = "MISSING_EXT.png" - # Compare each of the images with different fuzz factors so we can see how each is doing - # `compare -metric AE -fuzz ${FUZZ} ${VULKAN} ${NATIVE} ${TRACE}_fuzz${FUZZ}_diff.png` - results = [] - for fuzz in {0, 1, 2, 5, 10, 20}: - diff_file = trace + "_fuzz" + str(fuzz) + "%_TEST_diff.png" - diff_file = os.path.join(args.screenshot_dir, diff_file) - command = "compare -metric AE -fuzz " + str( - fuzz) + "% " + vulkan_file + " " + native_file + " " + diff_file - logging.debug("Running " + command) - diff = subprocess.run(command, shell=True, capture_output=True) - for line in diff.stderr.splitlines(): - if "unable to open image".encode('UTF-8') in line: - results.append("NA".encode('UTF-8')) - else: - results.append(diff.stderr) - logging.debug(" for " + trace + " " + str(fuzz) + "%") - + results = compare_with_fuzz_factors(args.screenshot_dir, args.discard_zero_diff_png, trace, + vulkan_file, native_file) print(trace, os.path.basename(vulkan_file), os.path.basename(native_file), results[0].decode('UTF-8'), results[1].decode('UTF-8'), results[2].decode('UTF-8'), results[3].decode('UTF-8'), results[4].decode('UTF-8'), results[5].decode('UTF-8')) @@ -129,34 +174,19 @@ def get_trace_key_frame(restricted_traces_path, trace): def versus_upgrade(args): - # Get a list of all the files in before - before_files = sorted(os.listdir(args.before)) - - # Get a list of all the files in after - after_files = sorted(os.listdir(args.after)) - - # If either list is missing files, this is a fail! - if before_files != after_files: - before_minus_after = list(sorted(set(before_files) - set(after_files))) - after_minus_before = list(sorted(set(after_files) - set(before_files))) - print("File lists don't match!") - if before_minus_after is not []: - print("Extra before files: %s" % before_minus_after) - if after_minus_before is not []: - print("Extra after files: %s" % after_minus_before) - exit(1) + # Get a list of all the files in before and after (lists MUST match!) + files = get_common_files(False, args.before, args.after) - # Walk through the before list and compare it with after - for before_image, after_image in zip(sorted(before_files), sorted(after_files)): + # Walk through the list and compare files in two directories + for image in files: # Compare each of the images using root mean squared, no fuzz factor # `compare -metric RMSE ${BEFORE} ${AFTER} ${TRACE}_RMSE_diff.png;` results = [] - diff_file = args.outdir + "/" + before_image + "_TEST_diff.png" - command = "compare -metric RMSE " + os.path.join( - args.before, before_image) + " " + os.path.join(args.after, - after_image) + " " + diff_file + diff_file = args.outdir + "/" + image + "_TEST_diff.png" + command = "compare -metric RMSE " + os.path.join(args.before, image) + " " + os.path.join( + args.after, image) + " " + diff_file diff = subprocess.run(command, shell=True, capture_output=True) for line in diff.stderr.splitlines(): if "unable to open image".encode('UTF-8') in line: @@ -164,20 +194,43 @@ def versus_upgrade(args): else: # If the last element of the diff isn't zero, there was a pixel diff if line.split()[-1] != b'(0)': - print(before_image, diff.stderr.decode('UTF-8')) + print(image, diff.stderr.decode('UTF-8')) print("Pixel diff detected!") exit(1) else: results.append(diff.stderr) + if args.discard_zero_diff_png: + os.remove(diff_file) - print(before_image, results[0].decode('UTF-8')) + print(image, results[0].decode('UTF-8')) print("Test completed successfully, no diffs detected") +def fuzz_ab(args): + + # Get a list of common files in a_dir and b_dir + files = get_common_files(args.relaxed_file_list_match, args.a_dir, args.b_dir) + + # Walk through the list and compare files in two directories + for image in files: + results = compare_with_fuzz_factors(args.outdir, args.discard_zero_diff_png, image, + os.path.join(args.a_dir, image), + os.path.join(args.b_dir, image)) + print(image, results[0].decode('UTF-8'), results[1].decode('UTF-8'), + results[2].decode('UTF-8'), results[3].decode('UTF-8'), results[4].decode('UTF-8'), + results[5].decode('UTF-8')) + + def main(): parser = argparse.ArgumentParser() parser.add_argument('-l', '--log', help='Logging level.', default=DEFAULT_LOG_LEVEL) + parser.add_argument( + '-d', + '--discard_zero_diff_png', + help='Discard output PNGs with zero difference.', + action='store_true', + default=False) # Create commands for different modes of using this script subparsers = parser.add_subparsers(dest='command', required=True, help='Command to run.') @@ -199,13 +252,32 @@ def main(): '--after', help='Full path to dir containing *after* screenshots', required=True) versus_upgrade_parser.add_argument('--outdir', help='Where to write output files', default='.') + # This mode will compare images in two directories, and give you fuzzy comparison results + fuzz_ab_parser = subparsers.add_parser( + 'fuzz_ab', help='Compare images in two directories, and give you fuzzy comparison results') + fuzz_ab_parser.add_argument( + '-r', + '--relaxed_file_list_match', + help='Allow comparing file lists if there is at least single match', + action='store_true', + default=False) + fuzz_ab_parser.add_argument( + '--a_dir', help='Full path to dir containing *A* screenshots', required=True) + fuzz_ab_parser.add_argument( + '--b_dir', help='Full path to dir containing *B* screenshots', required=True) + fuzz_ab_parser.add_argument('--outdir', help='Where to write output files', default='.') + args = parser.parse_args() + logging.basicConfig(level=args.log.upper()) + try: if args.command == 'versus_native': return versus_native(args) elif args.command == 'versus_upgrade': return versus_upgrade(args) + elif args.command == 'fuzz_ab': + return fuzz_ab(args) else: logging.fatal('Unknown command: %s' % args.command) return EXIT_FAILURE diff --git a/src/tests/restricted_traces/restricted_trace_gold_tests.py b/src/tests/restricted_traces/restricted_trace_gold_tests.py index dd6d36b1ad3..413e5c887ce 100755 --- a/src/tests/restricted_traces/restricted_trace_gold_tests.py +++ b/src/tests/restricted_traces/restricted_trace_gold_tests.py @@ -343,6 +343,28 @@ def _get_gtest_filter_for_batch(args, batch): return '--gtest_filter=%s' % ':'.join(expanded) +def _get_filtered_batch(batches, args): + for batch in batches: + filtered_batch = [] + filtered_trace = False + for trace in batch: + + # Check for conditions where we want to skip golden image comparison on the trace + if args.key_frame_limit: + keyframe = get_trace_key_frame(trace) + if keyframe != '' and int(keyframe) > int(args.key_frame_limit): + filtered_trace = True + logging.info('Skipping %s since key frame (%s) is higher than the limit (%s).', + trace, keyframe, args.key_frame_limit) + + if not filtered_trace: + logging.debug('Adding %s to batch.', trace) + filtered_batch.append(trace) + + filtered_trace = False + + yield filtered_batch + def _run_tests(args, tests, extra_flags, env, screenshot_dir, results, test_results): keys = get_skia_gold_keys(args, env) @@ -367,7 +389,7 @@ def _run_tests(args, tests, extra_flags, env, screenshot_dir, results, test_resu batches = _get_batches(traces, batch_size) - for batch in batches: + for batch in _get_filtered_batch(batches, args): if angle_test_util.IsAndroid(): android_helper.PrepareRestrictedTraces(batch) @@ -390,6 +412,8 @@ def _run_tests(args, tests, extra_flags, env, screenshot_dir, results, test_resu if args.swiftshader: cmd_args += ['--use-angle=swiftshader'] + # break here to debug new options + logging.info('Running batch with args: %s' % cmd_args) result, _, json_results = angle_test_util.RunTestSuite( args.test_suite, cmd_args, env, use_xvfb=args.xvfb) @@ -484,6 +508,12 @@ def main(): 'that are likely to cause differences in many tests, e.g. SwiftShader ' 'or driver changes. Can be enabled on bots by adding a ' '"Use-Permissive-Angle-Pixel-Comparison: True" footer.') + parser.add_argument( + '--key-frame-limit', + type=str, + help='Traces that have a high key frame can take a long time to run ' + 'on software renderers. To keep test times low, use this option to ' + 'skip traces that have key frames over the specified limit') add_skia_gold_args(parser) diff --git a/src/tests/restricted_traces/restricted_trace_perf.py b/src/tests/restricted_traces/restricted_trace_perf.py index 6d5a7e45e95..2f3a91af533 100644 --- a/src/tests/restricted_traces/restricted_trace_perf.py +++ b/src/tests/restricted_traces/restricted_trace_perf.py @@ -7,7 +7,7 @@ ''' Pixel 6 (ARM based) specific script that measures the following for each restricted_trace: - Wall time per frame -- GPU time per frame (if run with --vsync) +- GPU time per frame (if run with --track-gpu-time) - CPU time per frame - GPU power per frame - CPU power per frame @@ -105,17 +105,21 @@ def run_adb_shell_command(cmd): return android_helper._AdbShell(cmd).decode() +def run_adb_shell_command_with_run_as(cmd): + return android_helper._AdbShellWithRunAs(cmd).decode() + + def run_async_adb_command(args): return run_async_command('adb ' + args) def cleanup(): - run_adb_shell_command('rm -f ' + _global.storage_dir + '/out.txt ' + _global.storage_dir + - '/gpumem.txt') + run_adb_shell_command_with_run_as('rm -f ' + _global.storage_dir + '/out.txt ' + + _global.storage_dir + '/gpumem.txt') def clear_blob_cache(): - run_adb_shell_command('run-as com.android.angle.test rm -rf ' + _global.cache_dir) + run_adb_shell_command_with_run_as('rm -rf ' + _global.cache_dir) def select_device(device_arg): @@ -192,12 +196,15 @@ def pull_screenshot(args, screenshot_device_dir, renderer): # There might not be a screenshot if the test was skipped files = list(filter(None, (f.strip() for f in files))) # Remove empty strings and whitespace - if files: - assert len(files) == 1, 'Multiple files(%s) in %s, expected 1: %s' % ( - len(files), screenshot_device_dir, files) + + # We should only look for png files as tmp dir might contain other files too + png_files = [f for f in files if f.lower().endswith('.png')] + if png_files: + assert len(png_files) == 1, 'Multiple PNG files(%s) in %s, expected 1: %s' % ( + len(png_files), screenshot_device_dir, png_files) # Grab the single screenshot - src_file = files[0] + src_file = png_files[0] # Rename the file to reflect renderer, since we force everything through the platform using "native" dst_file = src_file.replace("native", renderer) @@ -262,6 +269,14 @@ def run_trace(trace, args, screenshot_device_dir): flags += ['--screenshot-frame', args.screenshot_frame] if args.fps_limit != '': flags += ['--fps-limit', args.fps_limit] + if args.fps_limit_uses_busy_wait: + flags.append('--fps-limit-uses-busy-wait') + if args.track_gpu_time: + flags.append('--track-gpu-time') + if args.add_swap_into_gpu_time: + flags.append('--add-swap-into-gpu-time') + if args.add_swap_into_frame_wall_time: + flags.append('--add-swap-into-frame-wall-time') # Build a command that can be run directly over ADB, for example: r''' @@ -298,8 +313,8 @@ def run_trace(trace, args, screenshot_device_dir): def get_test_time(): # Pull the results from the device and parse - result = run_adb_shell_command('cat ' + _global.storage_dir + - '/out.txt | grep -v Error | grep -v Frame') + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + + '/out.txt | grep -v Error | grep -v Frame') measured_time = None @@ -320,7 +335,7 @@ def get_test_time(): break if measured_time is None: - if '[ PASSED ]' in result.stdout: + if '[ PASSED ]' in result: measured_time = 'missing' else: measured_time = 'crashed' @@ -330,7 +345,8 @@ def get_test_time(): def get_gpu_memory(trace_duration): # Pull the results from the device and parse - result = run_adb_shell_command('cat ' + _global.storage_dir + '/gpumem.txt | awk "NF"') + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + + '/gpumem.txt | awk "NF"') # The gpumem script grabs snapshots of memory per process # Output looks like this, repeated once per sleep_duration of the test: @@ -398,7 +414,7 @@ def get_gpu_memory(trace_duration): def get_proc_memory(): # Pull the results from the device and parse - result = run_adb_shell_command('cat ' + _global.storage_dir + '/out.txt') + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + '/out.txt') memory_median = '' memory_max = '' @@ -419,7 +435,7 @@ def get_proc_memory(): def get_gpu_time(): # Pull the results from the device and parse - result = run_adb_shell_command('cat ' + _global.storage_dir + '/out.txt') + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + '/out.txt') gpu_time = '0' for line in result.splitlines(): @@ -433,9 +449,25 @@ def get_gpu_time(): return gpu_time +def get_frame_wall_time(): + # Pull the results from the device and parse + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + '/out.txt') + frame_wall_time = '0' + + for line in result.splitlines(): + # Look for "frame_wall_time" in the line and grab the second to last entry: + logging.debug('Checking line: %s' % line) + + if "frame_wall_time" in line: + frame_wall_time = line.split()[-2] + break + + return frame_wall_time + + def get_cpu_time(): # Pull the results from the device and parse - result = run_adb_shell_command('cat ' + _global.storage_dir + '/out.txt') + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + '/out.txt') cpu_time = '0' for line in result.splitlines(): @@ -451,8 +483,8 @@ def get_cpu_time(): def get_frame_count(): # Pull the results from the device and parse - result = run_adb_shell_command('cat ' + _global.storage_dir + - '/out.txt | grep -v Error | grep -v Frame') + result = run_adb_shell_command_with_run_as('cat ' + _global.storage_dir + + '/out.txt | grep -v Error | grep -v Frame') frame_count = 0 @@ -556,6 +588,77 @@ def wait_for_test_warmup(done_event): return +def collect_cpu_inst(done_event, test_fixedtime, results): + try: + tmp_data_file = run_adb_shell_command('mktemp /data/local/tmp/tmp.XXXXXX').strip() + + # Starting point is post test warmup as there are spikes during warmup + wait_for_test_warmup(done_event) + + if done_event.is_set(): + logging.debug('Test finished earlier than expected by collect_cpu_inst') + return + + # Start simpleperf record right after warmup is done + logging.debug('Starting cpu instruction count') + + # Collect cpu instructions of "com.android.angle.test:test_process" + run_adb_shell_command(f'''simpleperf record \ + -o {tmp_data_file} \ + -e instructions \ + -f 4000 \ + -p $(pidof com.android.angle.test:test_process)''') + + # Get the start time of simple perf to filter simpleperf data file + start_ns = run_adb_shell_command(f'''simpleperf report-sample \ + -i {tmp_data_file} \ + | sed -n '/^[[:space:]]*time/p;' | sort -n | head -n 1 ''') + start_ns = safe_cast_int(start_ns.strip().split()[-1]) + + done_event.wait(timeout=10) + if not done_event.is_set(): + logging.debug('Test finished but progress is stuck') + return + + # Calculate actual test running time based on frame count and wall time + frame_count = get_frame_count() + wall_time = get_test_time() + # Compensate 0.5ms for the delay before starting test + execution_time_ms = safe_cast_float(frame_count) * safe_cast_float(wall_time) + 0.5 + end_ns = safe_cast_int(start_ns + execution_time_ms * 1e6) + + # Filter simpleperf record within actual test running time + temp_filter_file = run_adb_shell_command('mktemp /data/local/tmp/tmp.XXXXXX').strip() + run_adb_shell_command(f'echo "CLOCK monotonic\n\ + GLOBAL_BEGIN {start_ns}\n\ + GLOBAL_END {end_ns}" > {temp_filter_file}') + + perf_output = run_adb_shell_command(f'''simpleperf report \ + --sort dso \ + --print-event-count \ + --filter-file {temp_filter_file} \ + -i {tmp_data_file}''') + + perf_output = perf_output.split('\n') + + for line in perf_output: + if 'Event count:' in line: + results['Total'] = safe_cast_float(line.split()[-1].strip()) + + if re.search('libGLES.*_.*\.so', line): + if ('angle' in line): + results['angle_lib'] = safe_cast_float(line.split()[-2].strip()) + else: + results['gles_lib'] = safe_cast_float(line.split()[-2].strip()) + + if re.search('vulkan\..*\.so', line): + results['vulkan_lib'] = safe_cast_float(line.split()[-2].strip()) + + finally: + run_adb_shell_command(f'rm -f {tmp_data_file}') + run_adb_shell_command(f'rm -f {temp_filter_file}') + logging.debug('Ending cpu instruction count') + def collect_power(done_event, test_fixedtime, results): # Starting point is post test warmup as there are spikes during warmup wait_for_test_warmup(done_event) @@ -588,6 +691,7 @@ def get_thermal_info(): out = run_adb_shell_command('dumpsys android.hardware.thermal.IThermal/default') result = [] for line in out.splitlines(): + logging.debug('Checking line in get_thermal_info: %a', line) if 'ThrottlingStatus:' in line: name = re.search('Name: ([^ ]*)', line).group(1) if ('VIRTUAL-SKIN' in name and @@ -722,6 +826,11 @@ def main(): default=False) parser.add_argument( '--power', help='Include CPU/GPU power used per trace', action='store_true', default=False) + parser.add_argument( + '--cpu-inst', + help='Include cpu instruction count of gpu user mode driver per trace', + action='store_true', + default=False) parser.add_argument( '--memory', help='Include CPU/GPU memory used per trace', @@ -789,6 +898,23 @@ def main(): help='Whether to run the trace in offscreen mode', action='store_true', default=False) + parser.add_argument( + '--fps-limit-uses-busy-wait', + help='Use busy wait instead of sleep to limit the framerate.', + action='store_true', + default=False) + parser.add_argument( + '--track-gpu-time', help='Enables GPU time tracking', action='store_true', default=False) + parser.add_argument( + '--add-swap-into-gpu-time', + help='Adds swap/offscreen blit into the gpu_time tracking', + action='store_true', + default=False) + parser.add_argument( + '--add-swap-into-frame-wall-time', + help='Adds swap/offscreen blit into the frame_wall_time tracking', + action='store_true', + default=False) args = parser.parse_args() @@ -850,28 +976,63 @@ def run_traces(args): 'trace': trace_width, 'wall_time': 15, 'gpu_time': 15, + 'frame_wall_time': 15, 'cpu_time': 15, 'gpu_power': 10, 'cpu_power': 10, 'gpu_mem_sustained': 20, 'gpu_mem_peak': 15, 'proc_mem_median': 20, - 'proc_mem_peak': 15 + 'proc_mem_peak': 15, + 'process_cpuinst': 20, + 'gfxlib_cpuinst': 20, + 'angle_cpuinst': 20, + 'vulkan_cpuinst': 20, + 'gles_cpuinst': 20, } if args.walltimeonly: print('%-*s' % (trace_width, 'wall_time_per_frame')) else: - print('%-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s' % - (column_width['trace'], 'trace', column_width['wall_time'], 'wall_time', - column_width['gpu_time'], 'gpu_time', column_width['cpu_time'], 'cpu_time', - column_width['gpu_power'], 'gpu_power', column_width['cpu_power'], 'cpu_power', - column_width['gpu_mem_sustained'], 'gpu_mem_sustained', - column_width['gpu_mem_peak'], 'gpu_mem_peak', column_width['proc_mem_median'], - 'proc_mem_median', column_width['proc_mem_peak'], 'proc_mem_peak')) + print('%-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*s' % ( + column_width['trace'], + 'trace', + column_width['wall_time'], + 'wall_time', + column_width['gpu_time'], + 'gpu_time', + column_width['frame_wall_time'], + 'frame_wall_time', + column_width['cpu_time'], + 'cpu_time', + column_width['gpu_power'], + 'gpu_power', + column_width['cpu_power'], + 'cpu_power', + column_width['gpu_mem_sustained'], + 'gpu_mem_sustained', + column_width['gpu_mem_peak'], + 'gpu_mem_peak', + column_width['proc_mem_median'], + 'proc_mem_median', + column_width['proc_mem_peak'], + 'proc_mem_peak', + column_width['process_cpuinst'], + 'process_cpuinst', + column_width['gfxlib_cpuinst'], + 'gfxlib_cpuinst', + column_width['angle_cpuinst'], + 'angle_cpuinst', + column_width['vulkan_cpuinst'], + 'vulkan_cpuinst', + column_width['gles_cpuinst'], + 'gles_cpuinst', + )) output_writer.writerow([ - 'trace', 'wall_time(ms)', 'gpu_time(ms)', 'cpu_time(ms)', 'gpu_power(W)', - 'cpu_power(W)', 'gpu_mem_sustained', 'gpu_mem_peak', 'proc_mem_median', 'proc_mem_peak' + 'trace', 'wall_time(ms)', 'gpu_time(ms)', 'frame_wall_time(ms)', 'cpu_time(ms)', + 'gpu_power(W)', 'cpu_power(W)', 'gpu_mem_sustained', 'gpu_mem_peak', 'proc_mem_median', + 'proc_mem_peak', 'process_cpuinst', 'gfxlib_cpuinst', 'angle_cpuinst', + 'vulkan_cpuinst', 'gles_cpuinst' ]) if args.power: @@ -886,6 +1047,7 @@ def run_traces(args): wall_times = defaultdict(dict) gpu_times = defaultdict(dict) + frame_wall_times = defaultdict(dict) cpu_times = defaultdict(dict) gpu_powers = defaultdict(dict) cpu_powers = defaultdict(dict) @@ -893,6 +1055,11 @@ def run_traces(args): gpu_mem_peaks = defaultdict(dict) proc_mem_medians = defaultdict(dict) proc_mem_peaks = defaultdict(dict) + process_cpuinsts = defaultdict(dict) + gfxlib_cpuinsts = defaultdict(dict) + angle_cpuinsts = defaultdict(dict) + vulkan_cpuinsts = defaultdict(dict) + gles_cpuinsts = defaultdict(dict) # Organize the data for writing out rows = defaultdict(dict) @@ -938,33 +1105,92 @@ def populate_row(rows, name, results): f"\"{renderer_name}\nprocess\nmem\n(B)\"", f"\"{renderer_name}\nprocess\nmem\nvariance\"", f"\"{renderer_name}\npeak\nprocess\nmem\n(B)\"", - f"\"{renderer_name}\npeak\nprocess\nmem\nvariance\"" + f"\"{renderer_name}\npeak\nprocess\nmem\nvariance\"", + f"\"{renderer_name}\nprocess\ncpu\ninst\n\"", + f"\"{renderer_name}\nprocess\ncpu\ninst\nvariance\"", + f"\"{renderer_name}\ngfxlib\ncpu\ninst\n\"", + f"\"{renderer_name}\ngfxlib\ncpu\ninst\nvariance\"", + f"\"{renderer_name}\nangle\ncpu\ninst\n\"", + f"\"{renderer_name}\nangle\ncpu\ninst\nvariance\"", + f"\"{renderer_name}\nvulkan\ncpu\ninst\n\"", + f"\"{renderer_name}\nvulkan\ncpu\ninst\nvariance\"", + f"\"{renderer_name}\ngles\ncpu\ninst\n\"", + f"\"{renderer_name}\ngles\ncpu\ninst\nvariance\"" ]) else: summary_writer.writerow([ - "#", "\"Trace\"", "\"Native\nwall\ntime\nper\nframe\n(ms)\"", - "\"Native\nwall\ntime\nvariance\"", "\"ANGLE\nwall\ntime\nper\nframe\n(ms)\"", - "\"ANGLE\nwall\ntime\nvariance\"", "\"wall\ntime\ncompare\"", - "\"Native\nGPU\ntime\nper\nframe\n(ms)\"", "\"Native\nGPU\ntime\nvariance\"", - "\"ANGLE\nGPU\ntime\nper\nframe\n(ms)\"", "\"ANGLE\nGPU\ntime\nvariance\"", - "\"GPU\ntime\ncompare\"", "\"Native\nCPU\ntime\nper\nframe\n(ms)\"", - "\"Native\nCPU\ntime\nvariance\"", "\"ANGLE\nCPU\ntime\nper\nframe\n(ms)\"", - "\"ANGLE\nCPU\ntime\nvariance\"", "\"CPU\ntime\ncompare\"", - "\"Native\nGPU\npower\n(W)\"", "\"Native\nGPU\npower\nvariance\"", - "\"ANGLE\nGPU\npower\n(W)\"", "\"ANGLE\nGPU\npower\nvariance\"", - "\"GPU\npower\ncompare\"", "\"Native\nCPU\npower\n(W)\"", - "\"Native\nCPU\npower\nvariance\"", "\"ANGLE\nCPU\npower\n(W)\"", - "\"ANGLE\nCPU\npower\nvariance\"", "\"CPU\npower\ncompare\"", - "\"Native\nGPU\nmem\n(B)\"", "\"Native\nGPU\nmem\nvariance\"", - "\"ANGLE\nGPU\nmem\n(B)\"", "\"ANGLE\nGPU\nmem\nvariance\"", "\"GPU\nmem\ncompare\"", - "\"Native\npeak\nGPU\nmem\n(B)\"", "\"Native\npeak\nGPU\nmem\nvariance\"", - "\"ANGLE\npeak\nGPU\nmem\n(B)\"", "\"ANGLE\npeak\nGPU\nmem\nvariance\"", - "\"GPU\npeak\nmem\ncompare\"", "\"Native\nprocess\nmem\n(B)\"", - "\"Native\nprocess\nmem\nvariance\"", "\"ANGLE\nprocess\nmem\n(B)\"", - "\"ANGLE\nprocess\nmem\nvariance\"", "\"process\nmem\ncompare\"", - "\"Native\npeak\nprocess\nmem\n(B)\"", "\"Native\npeak\nprocess\nmem\nvariance\"", - "\"ANGLE\npeak\nprocess\nmem\n(B)\"", "\"ANGLE\npeak\nprocess\nmem\nvariance\"", - "\"process\npeak\nmem\ncompare\"" + "#", + "\"Trace\"", + "\"Native\nwall\ntime\nper\nframe\n(ms)\"", + "\"Native\nwall\ntime\nvariance\"", + "\"ANGLE\nwall\ntime\nper\nframe\n(ms)\"", + "\"ANGLE\nwall\ntime\nvariance\"", + "\"wall\ntime\ncompare\"", + "\"Native\nGPU\ntime\nper\nframe\n(ms)\"", + "\"Native\nGPU\ntime\nvariance\"", + "\"ANGLE\nGPU\ntime\nper\nframe\n(ms)\"", + "\"ANGLE\nGPU\ntime\nvariance\"", + "\"GPU\ntime\ncompare\"", + "\"Native\nCPU\ntime\nper\nframe\n(ms)\"", + "\"Native\nCPU\ntime\nvariance\"", + "\"ANGLE\nCPU\ntime\nper\nframe\n(ms)\"", + "\"ANGLE\nCPU\ntime\nvariance\"", + "\"CPU\ntime\ncompare\"", + "\"Native\nGPU\npower\n(W)\"", + "\"Native\nGPU\npower\nvariance\"", + "\"ANGLE\nGPU\npower\n(W)\"", + "\"ANGLE\nGPU\npower\nvariance\"", + "\"GPU\npower\ncompare\"", + "\"Native\nCPU\npower\n(W)\"", + "\"Native\nCPU\npower\nvariance\"", + "\"ANGLE\nCPU\npower\n(W)\"", + "\"ANGLE\nCPU\npower\nvariance\"", + "\"CPU\npower\ncompare\"", + "\"Native\nGPU\nmem\n(B)\"", + "\"Native\nGPU\nmem\nvariance\"", + "\"ANGLE\nGPU\nmem\n(B)\"", + "\"ANGLE\nGPU\nmem\nvariance\"", + "\"GPU\nmem\ncompare\"", + "\"Native\npeak\nGPU\nmem\n(B)\"", + "\"Native\npeak\nGPU\nmem\nvariance\"", + "\"ANGLE\npeak\nGPU\nmem\n(B)\"", + "\"ANGLE\npeak\nGPU\nmem\nvariance\"", + "\"GPU\npeak\nmem\ncompare\"", + "\"Native\nprocess\nmem\n(B)\"", + "\"Native\nprocess\nmem\nvariance\"", + "\"ANGLE\nprocess\nmem\n(B)\"", + "\"ANGLE\nprocess\nmem\nvariance\"", + "\"process\nmem\ncompare\"", + "\"Native\npeak\nprocess\nmem\n(B)\"", + "\"Native\npeak\nprocess\nmem\nvariance\"", + "\"ANGLE\npeak\nprocess\nmem\n(B)\"", + "\"ANGLE\npeak\nprocess\nmem\nvariance\"", + "\"process\npeak\nmem\ncompare\"", + "\"Native\nprocess\ncpu\ninst\"", + "\"Native\nprocess\ncpu\ninst\nvariance\"", + "\"ANGLE\nprocess\ncpu\ninst\"", + "\"ANGLE\nprocess\ncpu\ninst\nvariance\"", + "\"process\ncpu\ninst\ncompare\"", + "\"Native\ngfxlib\ncpu\ninst\"", + "\"Native\ngfxlib\ncpu\ninst\nvariance\"", + "\"ANGLE\ngfxlib\ncpu\ninst\"", + "\"ANGLE\ngfxlib\ncpu\ninst\nvariance\"", + "\"gfxlib\ncpu\ninst\ncompare\"", + "\"Native\nangle\ncpu\ninst\"", + "\"Native\nangle\ncpu\ninst\nvariance\"", + "\"ANGLE\nangle\ncpu\ninst\"", + "\"ANGLE\nangle\ncpu\ninst\nvariance\"", + "\"angle\ncpu\ninst\ncompare\"", + "\"Native\nvulkan\ncpu\ninst\"", + "\"Native\nvulkan\ncpu\ninst\nvariance\"", + "\"ANGLE\nvulkan\ncpu\ninst\"", + "\"ANGLE\nvulkan\ncpu\ninst\nvariance\"", + "\"vulkan\ncpu\ninst\ncompare\"", + "\"Native\ngles\ncpu\ninst\"", + "\"Native\ngles\ncpu\ninst\nvariance\"", + "\"ANGLE\ngles\ncpu\ninst\"", + "\"ANGLE\ngles\ncpu\ninst\nvariance\"", + "\"gles\ncpu\ninst\ncompare\"", ]) with run_from_dir(args.build_dir): @@ -983,6 +1209,7 @@ def populate_row(rows, name, results): rows.clear() wall_times.clear() gpu_times.clear() + frame_wall_times.clear() cpu_times.clear() gpu_powers.clear() cpu_powers.clear() @@ -990,6 +1217,11 @@ def populate_row(rows, name, results): gpu_mem_peaks.clear() proc_mem_medians.clear() proc_mem_peaks.clear() + process_cpuinsts.clear() + gfxlib_cpuinsts.clear() + angle_cpuinsts.clear() + vulkan_cpuinsts.clear() + gles_cpuinsts.clear() for i in range(int(args.loop_count)): @@ -1037,10 +1269,26 @@ def populate_row(rows, name, results): test = trace.split(' ')[0] + if args.cpu_inst or args.power: + run_adb_command(['logcat', '-c']) # needed for wait_for_test_warmup + done_event = threading.Event() + + if args.cpu_inst: + assert args.fixedtime, '--cpu_inst requires --fixedtime' + cpu_inst_results = { + "Total": 0, + "gles_lib": 0, + "angle_lib": 0, + "vulkan_lib": 0, + } # output arg + cpu_inst_thread = threading.Thread( + target=collect_cpu_inst, + args=(done_event, float(args.fixedtime), cpu_inst_results)) + cpu_inst_thread.daemon = True + cpu_inst_thread.start() + if args.power: assert args.fixedtime, '--power requires --fixedtime' - done_event = threading.Event() - run_adb_command(['logcat', '-c']) # needed for wait_for_test_warmup power_results = {} # output arg power_thread = threading.Thread( target=collect_power, @@ -1061,9 +1309,40 @@ def populate_row(rows, name, results): if screenshot_device_dir: pull_screenshot(args, screenshot_device_dir, renderer) + if args.cpu_inst or args.power: + done_event.set() + + process_cpuinst = 0 + gfxlib_cpuinst = 0 + angle_cpuinst = 0 + vulkan_cpuinst = 0 + gles_cpuinst = 0 + if args.cpu_inst: + cpu_inst_thread.join(timeout=10) + if cpu_inst_thread.is_alive(): + logging.warning('collect_cpu_inst thread did not terminate') + else: + # Calculate per frame cpu instruction count + frame_count = safe_cast_float(get_frame_count()) + process_cpuinst = cpu_inst_results["Total"] + process_cpuinst = safe_divide(process_cpuinst, frame_count) + + gfxlib_cpuinst = cpu_inst_results["gles_lib"] + gfxlib_cpuinst += cpu_inst_results["angle_lib"] + gfxlib_cpuinst += cpu_inst_results["vulkan_lib"] + gfxlib_cpuinst = safe_divide(gfxlib_cpuinst, frame_count) + + angle_cpuinst = cpu_inst_results["angle_lib"] + angle_cpuinst = safe_divide(angle_cpuinst, frame_count) + + vulkan_cpuinst = cpu_inst_results["vulkan_lib"] + vulkan_cpuinst = safe_divide(vulkan_cpuinst, frame_count) + + gles_cpuinst = cpu_inst_results["gles_lib"] + gles_cpuinst = safe_divide(gles_cpuinst, frame_count) + gpu_power, cpu_power = 0, 0 if args.power: - done_event.set() power_thread.join(timeout=2) if power_thread.is_alive(): logging.warning('collect_power thread did not terminate') @@ -1073,7 +1352,9 @@ def populate_row(rows, name, results): wall_time = get_test_time() - gpu_time = get_gpu_time() if args.vsync else '0' + gpu_time = get_gpu_time() if args.track_gpu_time else '0' + + frame_wall_time = get_frame_wall_time() cpu_time = get_cpu_time() @@ -1101,6 +1382,10 @@ def populate_row(rows, name, results): gpu_times[test] = defaultdict(list) gpu_times[test][renderer].append(safe_cast_float(gpu_time)) + if len(frame_wall_times[test]) == 0: + frame_wall_times[test] = defaultdict(list) + frame_wall_times[test][renderer].append(safe_cast_float(frame_wall_time)) + if len(cpu_times[test]) == 0: cpu_times[test] = defaultdict(list) cpu_times[test][renderer].append(safe_cast_float(cpu_time)) @@ -1129,21 +1414,70 @@ def populate_row(rows, name, results): proc_mem_peaks[test] = defaultdict(list) proc_mem_peaks[test][renderer].append(safe_cast_int(proc_mem_peak)) + if len(process_cpuinsts[test]) == 0: + process_cpuinsts[test] = defaultdict(list) + process_cpuinsts[test][renderer].append(safe_cast_float(process_cpuinst)) + + if len(gfxlib_cpuinsts[test]) == 0: + gfxlib_cpuinsts[test] = defaultdict(list) + gfxlib_cpuinsts[test][renderer].append(safe_cast_float(gfxlib_cpuinst)) + + if len(angle_cpuinsts[test]) == 0: + angle_cpuinsts[test] = defaultdict(list) + angle_cpuinsts[test][renderer].append(safe_cast_float(angle_cpuinst)) + + if len(vulkan_cpuinsts[test]) == 0: + vulkan_cpuinsts[test] = defaultdict(list) + vulkan_cpuinsts[test][renderer].append(safe_cast_float(vulkan_cpuinst)) + + if len(gles_cpuinsts[test]) == 0: + gles_cpuinsts[test] = defaultdict(list) + gles_cpuinsts[test][renderer].append(safe_cast_float(gles_cpuinst)) + if args.walltimeonly: print('%-*s' % (trace_width, wall_time)) else: print( - '%-*s %-*s %-*s %-*s %-*s %-*s %-*i %-*i %-*i %-*i' % - (column_width['trace'], trace_name, column_width['wall_time'], wall_time, - column_width['gpu_time'], gpu_time, column_width['cpu_time'], cpu_time, - column_width['gpu_power'], '%.3f' % gpu_power, column_width['cpu_power'], - '%.3f' % cpu_power, column_width['gpu_mem_sustained'], gpu_mem_sustained, - column_width['gpu_mem_peak'], gpu_mem_peak, - column_width['proc_mem_median'], proc_mem_median, - column_width['proc_mem_peak'], proc_mem_peak)) + '%-*s %-*s %-*s %-*s %-*s %-*s %-*s %-*i %-*i %-*i %-*i %-*s %-*s %-*s %-*s %-*s' + % ( + column_width['trace'], + trace_name, + column_width['wall_time'], + wall_time, + column_width['gpu_time'], + gpu_time, + column_width['frame_wall_time'], + frame_wall_time, + column_width['cpu_time'], + cpu_time, + column_width['gpu_power'], + '%.3f' % gpu_power, + column_width['cpu_power'], + '%.3f' % cpu_power, + column_width['gpu_mem_sustained'], + gpu_mem_sustained, + column_width['gpu_mem_peak'], + gpu_mem_peak, + column_width['proc_mem_median'], + proc_mem_median, + column_width['proc_mem_peak'], + proc_mem_peak, + column_width['process_cpuinst'], + process_cpuinst, + column_width['gfxlib_cpuinst'], + gfxlib_cpuinst, + column_width['angle_cpuinst'], + angle_cpuinst, + column_width['vulkan_cpuinst'], + vulkan_cpuinst, + column_width['gles_cpuinst'], + gles_cpuinst, + )) output_writer.writerow([ - mode + renderer + '_' + test, wall_time, gpu_time, cpu_time, gpu_power, - cpu_power, gpu_mem_sustained, gpu_mem_peak, proc_mem_median, proc_mem_peak + mode + renderer + '_' + test, wall_time, gpu_time, frame_wall_time, + cpu_time, gpu_power, cpu_power, gpu_mem_sustained, gpu_mem_peak, + proc_mem_median, proc_mem_peak, process_cpuinst, gfxlib_cpuinst, + angle_cpuinst, vulkan_cpuinst, gles_cpuinst ]) @@ -1172,6 +1506,9 @@ def populate_row(rows, name, results): for name, results in gpu_times.items(): populate_row(rows, name, results) + for name, results in frame_wall_times.items(): + populate_row(rows, name, results) + for name, results in cpu_times.items(): populate_row(rows, name, results) @@ -1193,6 +1530,21 @@ def populate_row(rows, name, results): for name, results in proc_mem_peaks.items(): populate_row(rows, name, results) + for name, results in process_cpuinsts.items(): + populate_row(rows, name, results) + + for name, results in gfxlib_cpuinsts.items(): + populate_row(rows, name, results) + + for name, results in angle_cpuinsts.items(): + populate_row(rows, name, results) + + for name, results in vulkan_cpuinsts.items(): + populate_row(rows, name, results) + + for name, results in gles_cpuinsts.items(): + populate_row(rows, name, results) + if (len(renderers) == 1) and (renderers[0] != "both"): renderer_name = renderers[0] for name, data in rows.items(): @@ -1227,6 +1579,21 @@ def populate_row(rows, name, results): # process peak mem int(data[renderer_name][16]), percent(data[renderer_name][17]), + # process cpuinst + "%.3f" % data[renderer_name][18], + percent(data[renderer_name][19]), + # gfxlib cpuinst + "%.3f" % data[renderer_name][20], + percent(data[renderer_name][21]), + # angle cpuinst + "%.3f" % data[renderer_name][22], + percent(data[renderer_name][23]), + # vulkan cpuinst + "%.3f" % data[renderer_name][24], + percent(data[renderer_name][25]), + # gles cpuinst + "%.3f" % data[renderer_name][26], + percent(data[renderer_name][27]), ]) else: for name, data in rows.items(): @@ -1287,7 +1654,37 @@ def populate_row(rows, name, results): percent(data["native"][17]), int(data["vulkan"][16]), percent(data["vulkan"][17]), - percent(safe_divide(data["native"][16], data["vulkan"][16])) + percent(safe_divide(data["native"][16], data["vulkan"][16])), + # process cpuinst + "%.3f" % data["native"][18], + percent(data["native"][19]), + "%.3f" % data["vulkan"][18], + percent(data["vulkan"][19]), + percent(safe_divide(data["native"][18], data["vulkan"][18])), + # gfxlib cpuinst + "%.3f" % data["native"][20], + percent(data["native"][21]), + "%.3f" % data["vulkan"][20], + percent(data["vulkan"][21]), + percent(safe_divide(data["native"][20], data["vulkan"][20])), + # angle cpuinst + "%.3f" % data["native"][22], + percent(data["native"][23]), + "%.3f" % data["vulkan"][22], + percent(data["vulkan"][23]), + percent(safe_divide(data["native"][22], data["vulkan"][22])), + # vulkan cpuinst + "%.3f" % data["native"][24], + percent(data["native"][25]), + "%.3f" % data["vulkan"][24], + percent(data["vulkan"][25]), + percent(safe_divide(data["native"][24], data["vulkan"][24])), + # vulkan cpuinst + "%.3f" % data["native"][26], + percent(data["native"][27]), + "%.3f" % data["vulkan"][26], + percent(data["vulkan"][27]), + percent(safe_divide(data["native"][26], data["vulkan"][26])), ]) diff --git a/src/tests/restricted_traces/restricted_traces.json b/src/tests/restricted_traces/restricted_traces.json index 2b5b23767d3..8a5160e175d 100644 --- a/src/tests/restricted_traces/restricted_traces.json +++ b/src/tests/restricted_traces/restricted_traces.json @@ -12,6 +12,7 @@ "20_minutes_till_dawn 1", "2_3_4_player_mini_games 1", "3d_pool_ball 1", + "ace_racer 1", "afk_arena 1", "age_of_origins_z 1", "agent_a 1", @@ -23,33 +24,43 @@ "animal_crossing 4", "antistress 1", "antutu_refinery 1", + "apex_girl 1", + "archero_2 1", "arena_of_valor 5", "arknights 1", "asphalt_8 5", "asphalt_9 5", "asphalt_9_2024 1", "avakin_life 5", + "avatar_world 1", "aztec_ruins 5", "aztec_ruins_high 1", "badland 5", - "balatro 1", + "balatro 2", "basemark_gpu 1", "batman_telltale 1", "battle_of_polytopia 1", "beach_buggy_racing 5", "billiards_city 1", + "bingo_blitz 1", + "black_beacon 1", "black_clover_m 1", "black_desert_mobile 1", "blade_and_soul_revolution 2", "block_blast 1", + "block_craft_3d 1", "blockman_go 5", + "blood_strike 1", "botworld_adventure 1", + "brain_test_tricky_puzzles 1", "brawl_stars 5", "brawlhalla 1", "bricks_breaker_quest 5", "bridge_constructor_portal 1", + "brotato 1", "bubble_shooter 5", "bubble_shooter_and_friends 1", + "bubble_shooter_relaxing 1", "bullet_echo 1", "bus_simulator_indonesia 5", "call_break_offline_card_game 5", @@ -59,26 +70,36 @@ "car_chase 1", "car_parking_multiplayer 5", "car_race_3d 1", + "carrom_pool_disc_game 1", + "cash_frenzy_casino_slots 1", + "cashman_casino 1", "castlevania_sotn 1", + "cat_runner 1", "catalyst_black 1", "chrono_trigger 1", "clash_of_clans 5", "clash_royale 5", "cod_mobile 6", "coin_master 5", + "color_block_combo_blast 1", "command_and_conquer_rivals 5", - "cookie_run_kingdom 5", + "cookie_run_kingdom 6", "cookie_run_oven_break 1", "critical_ops 1", "csr2_drag_racing 1", "cut_the_rope 1", + "dark_war_survival 1", "darkness_rises 1", + "dc_dark_legion 2", "dead_by_daylight 2", "dead_cells 1", "dead_trigger_2 1", "diablo_immortal 2", + "dice_dreams 1", "disney_mirrorverse 1", + "disney_solitaire 1", "disney_tsum_tsum 5", + "domino_dreams 1", "dont_starve 1", "dota_underlords 5", "downwell 1", @@ -99,56 +120,78 @@ "fallout_shelter_online 5", "family_island 1", "farm_heroes_saga 5", + "fashion_show 1", "fate_grand_order 5", "fifa_mobile 5", - "final_fantasy 5", + "final_fantasy 6", "final_fantasy_brave_exvius 1", "fire_emblem_heroes 1", "fishdom 1", "five_nights_at_freddys 1", + "football_league_2025 1", "free_fire 5", "free_fire_max 1", + "frost_and_flame 1", "gacha_club 1", "gacha_life 2", "gangstar_vegas 1", "gardenscapes 5", - "genshin_impact 5", + "genshin_impact 6", "geometry_dash 1", "goddess_of_victory_nikke 1", "going_balls 1", "google_maps 5", + "gossip_harbor 1", "grand_mountain_adventure 1", "grimvalor 1", "gwent_witcher_card_game 1", "happy_color 5", "harry_potter_hogwarts_mystery 1", + "harry_potter_magic_awakened 1", "hay_day 5", "hearthstone 5", + "hero_wars 1", "higgs_domino_island 5", "hill_climb_racing 5", + "hole_io 1", "homescapes 5", + "honkai_impact_3rd 2", "honkai_star_rail 1", "hungry_shark_evolution 1", + "hunter_assassin 1", + "i9_inferno_nine 1", + "identity_v 1", "idle_heroes 5", + "indian_bikes_driving_3d 1", "infinity_ops 1", "injustice_2 1", "into_the_dead_2 1", + "jackpot_party 1", "jackpot_world 1", "jetpack_joyride 1", "junes_journey 5", "kartrider_rush 5", "kentucky_route_zero 1", + "kingshot 1", "klondike_adventures 5", + "knives_out 1", + "lands_of_jail 1", "last_shelter_survival 1", + "last_war_survival_game 1", + "last_z_survival_shooter 1", "league_of_legends_wild_rift 5", "lego_legacy 5", "life_is_strange 1", + "lightning_link 1", "lilys_garden 1", "limbo 1", + "lineage_2m 1", "lineage_m 5", "loop_hero 1", "lords_mobile 1", + "lost_light 1", "lotsa_slots 1", + "love_and_deepspace 2", "ludo_king 5", "lumino_city 1", "magic_rush_heroes 1", @@ -158,14 +201,21 @@ "mario_kart_tour 5", "marvel_contest_of_champions 5", "marvel_snap 1", - "marvel_strike_force 1", + "marvel_strike_force 2", + "match_factory 1", + "match_masters 1", + "matching_story 1", "merge_dragons 1", + "merge_mansion 1", "messenger_lite 5", "minecraft 7", "minecraft_bedrock 1", + "minecraft_vibrant_visuals 1", "minetest 2", "mini_block_craft 1", + "mini_games_calm_and_relax 1", "mini_world 5", + "mob_control 1", "mobile_legends 5", "modern_combat_5 1", "monopoly_go 1", @@ -175,6 +225,9 @@ "mortal_kombat 2", "mu_origin_3 1", "my_friend_pedro 1", + "my_talking_angela 1", + "my_talking_angela_2 1", + "my_talking_tom 1", "my_talking_tom2 5", "my_talking_tom_friends 5", "nba2k20_800 5", @@ -183,10 +236,14 @@ "ni_no_kuni 1", "nier_reincarnation 5", "octopath_traveler 2", + "odin_valhalla_rising 1", "off_the_road 1", + "offline_games 1", "one_piece_treasure_cruise 1", "one_punch_man 5", + "onmyoji 1", "oxenfree 1", + "paper_io2 1", "passmark_complex 1", "passmark_simple 1", "passmark_unity 1", @@ -196,8 +253,9 @@ "plants_vs_zombies_2 5", "plants_vs_zombies_heroes 1", "pokemon_go 5", + "pokemon_go_combat 1", "pokemon_masters_ex 1", - "pokemon_unite 5", + "pokemon_unite 6", "poppy_playtime 1", "portal_knights 1", "professional_baseball_spirits 5", @@ -205,9 +263,13 @@ "pubg_mobile_launch 6", "pubg_mobile_lite 5", "pubg_mobile_skydive 5", + "puzzle_and_dragons 2", "puzzles_and_survival 1", + "qblock_wood_block_puzzle_game 1", + "race_master_3d 1", "ragnarok_m_eternal_love 5", "raid_shadow_legends 5", + "raising_a_goblin 1", "real_commando_secret_mission 5", "real_cricket_20 5", "real_gangster_crime 5", @@ -220,15 +282,18 @@ "rise_of_kingdoms 5", "romancing_saga 5", "rope_hero_vice_town 5", + "royal_kingdom 1", "royal_match 1", "rush_royale 1", "saint_seiya_awakening 5", "sakura_school_simulator 5", "scary_teacher_3d 1", + "school_party_craft 1", "scrabble_go 5", + "seaside_escape 1", "shadow_fight_2 5", "shadow_fight_3 1", - "shadowgun_legends 1", + "shadowgun_legends 2", "shovel_knight_pocket_dungeon 1", "simcity_buildit 1", "sky_force_reloaded 1", @@ -236,17 +301,22 @@ "slay_the_spire 1", "slingshot_test1 5", "slingshot_test2 5", + "slotomania 1", + "snake_io 1", + "snake_lite 1", "sniper_3d 5", - "solar_smash 2", + "soccer_superstar 1", + "solar_smash 3", "sonic_forces 1", "sonic_the_hedgehog 5", "special_forces_group_2 1", + "spider_fighter_3 1", "standoff_2 5", "star_trek_fleet_command 1", "star_wars_galaxy_of_heroes 1", "star_wars_kotor 1", "stardew_valley 1", - "state_of_survival 1", + "state_of_survival 2", "street_fighter_duel 1", "street_fighter_iv_ce 1", "streets_of_rage_4 1", @@ -254,10 +324,12 @@ "subway_princess_runner 5", "subway_surfers 5", "summoners_war 5", + "super_bear_adventure 1", "super_mario_run 1", "supertuxkart 1", "supreme_duelist 1", "survivor_io 1", + "talking_tom_gold_run 1", "talking_tom_hero_dash 5", "temple_run_2 5", "temple_run_300 5", @@ -269,22 +341,30 @@ "the_witcher_monster_slayer 1", "thief_puzzle 1", "thimbleweed_park 1", + "tile_club 1", "tmnt_shredders_revenge 1", - "toca_life_world 2", - "toon_blast 5", + "toca_life_world 3", + "toon_blast 6", + "top_heroes_kingdom_saga 1", "top_war 1", + "total_battle 1", "tower_of_fantasy 1", "township 5", "traffic_rider 1", + "travel_town 1", "trex_200 5", + "two_player_games 1", "uber 1", + "umamusume_pretty_derby 1", "vainglory 1", + "vita_mahjong 1", "walking_dead_survivors 1", "war_planet_online 1", "warcraft_rumble 1", "warhammer_40000_freeblade 1", "wayward_souls 1", "whatsapp 5", + "whiteout_survival 1", "woodoku 1", "words_crush 1", "words_of_wonders 1", @@ -295,6 +375,8 @@ "world_of_tanks_blitz 5", "world_war_doh 5", "worms_zone_io 5", + "wuthering_waves 1", + "yalla_ludo 1", "zenonia_4 1", "zillow 5", "zombie_smasher 1" diff --git a/src/tests/restricted_traces/retrace_restricted_traces.py b/src/tests/restricted_traces/retrace_restricted_traces.py index 81d8f858bcc..e170aa16eb4 100755 --- a/src/tests/restricted_traces/retrace_restricted_traces.py +++ b/src/tests/restricted_traces/retrace_restricted_traces.py @@ -524,6 +524,12 @@ def recurse_run(others, exts, depth=0): if extension[0] in recurse_reqs and extension[1] in recurse_reqs: recurse_reqs.remove(extension[1]) + # For replay portability, if GL_EXT_separate_shader_sources is required + # bump version to 3.1 where this functionality is core + if "GL_EXT_separate_shader_objects" in recurse_reqs and min_version < (3, 1): + set_gles_version(json_data, (3, 1)) + recurse_reqs.remove("GL_EXT_separate_shader_objects") + json_data['RequiredExtensions'] = recurse_reqs save_trace_json(trace, json_data) diff --git a/src/tests/test_expectations/GPUTestConfig.cpp b/src/tests/test_expectations/GPUTestConfig.cpp index a7a33d38d38..31d653d4b90 100644 --- a/src/tests/test_expectations/GPUTestConfig.cpp +++ b/src/tests/test_expectations/GPUTestConfig.cpp @@ -277,6 +277,24 @@ inline bool IsAppleGPU() return angle::IsAppleGPU(GetActiveGPUVendorID()); } +// Check whether the active GPU is Qualcomm. +inline bool IsQualcomm() +{ + return angle::IsQualcomm(GetActiveGPUVendorID()); +} + +// Check whether the active GPU is Samsung +inline bool IsSamsung() +{ + return angle::IsSamsung(GetActiveGPUVendorID()); +} + +// Check whether the active GPU is ARM. +inline bool IsARM() +{ + return angle::IsARM(GetActiveGPUVendorID()); +} + // Check whether this is a debug build. inline bool IsDebug() { @@ -384,7 +402,7 @@ inline bool IsGalaxyS23() inline bool IsGalaxyS24Exynos() { - return IsAndroidDevice("SM-S926B"); + return IsAndroidDevice("SM-S926B") || IsAndroidDevice("SM-S721U1"); } inline bool IsGalaxyS24Qualcomm() @@ -456,6 +474,12 @@ inline bool IsVulkan(const GPUTestConfig::API &api) return (api == GPUTestConfig::kAPIVulkan) || (api == GPUTestConfig::kAPISwiftShader); } +// Check whether the backend API has been set to ANGLE Native in the constructor +inline bool IsNative(const GPUTestConfig::API &api) +{ + return (api == GPUTestConfig::kAPINative); +} + inline bool IsSwiftShader(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPISwiftShader); @@ -506,6 +530,9 @@ GPUTestConfig::GPUTestConfig(bool isSwiftShader) mConditions[kConditionIntel] = !isSwiftShader && IsIntel(); mConditions[kConditionVMWare] = !isSwiftShader && IsVMWare(); mConditions[kConditionApple] = !isSwiftShader && IsAppleGPU(); + mConditions[kConditionQualcomm] = !isSwiftShader && IsQualcomm(); + mConditions[kConditionARM] = !isSwiftShader && IsARM(); + mConditions[kConditionSamsung] = !isSwiftShader && IsSamsung(); mConditions[kConditionSwiftShader] = isSwiftShader; mConditions[kConditionRelease] = IsRelease(); @@ -518,6 +545,7 @@ GPUTestConfig::GPUTestConfig(bool isSwiftShader) mConditions[kConditionVulkan] = true; mConditions[kConditionMetal] = true; mConditions[kConditionWgpu] = true; + mConditions[kConditionNative] = true; // Devices are irrelevant if we are running on SW mConditions[kConditionNexus5X] = !isSwiftShader && IsNexus5X(); @@ -548,6 +576,14 @@ GPUTestConfig::GPUTestConfig(bool isSwiftShader) mConditions[kConditionASan] = IsASan(); mConditions[kConditionTSan] = IsTSan(); mConditions[kConditionUBSan] = IsUBSan(); + +#ifdef ANGLE_IR + // The IR can be disabled at runtime, but we can't detect that. For the purposes of test + // expectations, especially for deqp, assume that if the IR is built, it's used. + mConditions[kConditionIR] = true; +#else + mConditions[kConditionIR] = false; +#endif } // If the constructor is passed an API, load those conditions as well @@ -561,6 +597,7 @@ GPUTestConfig::GPUTestConfig(const API &api, uint32_t preRotation) mConditions[kConditionVulkan] = IsVulkan(api); mConditions[kConditionMetal] = IsMetal(api); mConditions[kConditionWgpu] = IsWgpu(api); + mConditions[kConditionNative] = IsNative(api); switch (preRotation) { diff --git a/src/tests/test_expectations/GPUTestConfig.h b/src/tests/test_expectations/GPUTestConfig.h index e58c12b577b..baf9df2b922 100644 --- a/src/tests/test_expectations/GPUTestConfig.h +++ b/src/tests/test_expectations/GPUTestConfig.h @@ -26,6 +26,7 @@ struct GPUTestConfig kAPISwiftShader, kAPIMetal, kAPIWgpu, + kAPINative, }; enum Condition @@ -56,6 +57,9 @@ struct GPUTestConfig kConditionIntel, kConditionVMWare, kConditionApple, + kConditionQualcomm, + kConditionARM, + kConditionSamsung, kConditionRelease, kConditionDebug, kConditionD3D9, @@ -63,6 +67,7 @@ struct GPUTestConfig kConditionGLDesktop, kConditionGLES, kConditionVulkan, + kConditionNative, kConditionMetal, kConditionWgpu, kConditionNexus5X, @@ -92,6 +97,7 @@ struct GPUTestConfig kConditionASan, kConditionTSan, kConditionUBSan, + kConditionIR, kNumberOfConditions, }; diff --git a/src/tests/test_expectations/GPUTestExpectationsParser.cpp b/src/tests/test_expectations/GPUTestExpectationsParser.cpp index 80352ec2011..95fae6f2d9c 100644 --- a/src/tests/test_expectations/GPUTestExpectationsParser.cpp +++ b/src/tests/test_expectations/GPUTestExpectationsParser.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "GPUTestExpectationsParser.h" #include @@ -61,6 +65,9 @@ enum Token kConfigIntel, kConfigVMWare, kConfigApple, + kConfigQualcomm, + kConfigARM, + kConfigSamsung, // build type kConfigRelease, kConfigDebug, @@ -73,6 +80,7 @@ enum Token kConfigSwiftShader, kConfigMetal, kConfigWgpu, + kConfigNative, // Android devices kConfigNexus5X, kConfigPixel2, @@ -103,6 +111,8 @@ enum Token kConfigASan, kConfigTSan, kConfigUBSan, + // Translator + kConfigIR, // expectation kExpectationPass, kExpectationFail, @@ -185,6 +195,9 @@ constexpr TokenInfo kTokenData[kNumberOfTokens] = { {"intel", GPUTestConfig::kConditionIntel}, {"vmware", GPUTestConfig::kConditionVMWare}, {"apple", GPUTestConfig::kConditionApple}, + {"qualcomm", GPUTestConfig::kConditionQualcomm}, + {"arm", GPUTestConfig::kConditionARM}, + {"samsung", GPUTestConfig::kConditionSamsung}, {"release", GPUTestConfig::kConditionRelease}, {"debug", GPUTestConfig::kConditionDebug}, {"d3d9", GPUTestConfig::kConditionD3D9}, @@ -192,6 +205,7 @@ constexpr TokenInfo kTokenData[kNumberOfTokens] = { {"opengl", GPUTestConfig::kConditionGLDesktop}, {"gles", GPUTestConfig::kConditionGLES}, {"vulkan", GPUTestConfig::kConditionVulkan}, + {"native", GPUTestConfig::kConditionNative}, {"swiftshader", GPUTestConfig::kConditionSwiftShader}, {"metal", GPUTestConfig::kConditionMetal}, {"wgpu", GPUTestConfig::kConditionWgpu}, @@ -221,6 +235,7 @@ constexpr TokenInfo kTokenData[kNumberOfTokens] = { {"asan", GPUTestConfig::kConditionASan}, {"tsan", GPUTestConfig::kConditionTSan}, {"ubsan", GPUTestConfig::kConditionUBSan}, + {"ir", GPUTestConfig::kConditionIR}, {"pass", GPUTestConfig::kConditionNone, GPUTestExpectationsParser::kGpuTestPass}, {"fail", GPUTestConfig::kConditionNone, GPUTestExpectationsParser::kGpuTestFail}, {"flaky", GPUTestConfig::kConditionNone, GPUTestExpectationsParser::kGpuTestFlaky}, @@ -518,6 +533,9 @@ bool GPUTestExpectationsParser::parseLine(const GPUTestConfig *config, case kConfigIntel: case kConfigVMWare: case kConfigApple: + case kConfigQualcomm: + case kConfigARM: + case kConfigSamsung: case kConfigRelease: case kConfigDebug: case kConfigD3D9: @@ -528,6 +546,7 @@ bool GPUTestExpectationsParser::parseLine(const GPUTestConfig *config, case kConfigSwiftShader: case kConfigMetal: case kConfigWgpu: + case kConfigNative: case kConfigNexus5X: case kConfigPixel2: case kConfigPixel4: @@ -554,6 +573,7 @@ bool GPUTestExpectationsParser::parseLine(const GPUTestConfig *config, case kConfigASan: case kConfigTSan: case kConfigUBSan: + case kConfigIR: // MODIFIERS, check each condition and add accordingly. if (stage != kLineParserConfigs && stage != kLineParserBugID) { diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp index bb2d4c3d297..99cda0a18a3 100644 --- a/src/tests/test_utils/ANGLETest.cpp +++ b/src/tests/test_utils/ANGLETest.cpp @@ -7,6 +7,10 @@ // Implementation of common ANGLE testing fixture. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "ANGLETest.h" #include @@ -171,10 +175,8 @@ bool gReuseDisplays = false; bool ShouldAlwaysForceNewDisplay(const PlatformParameters ¶ms) { - // When running WebGPU tests on linux always force a new display. The underlying vulkan swap - // chain appears to fail to get a new image after swapping when rapidly creating new swap chains - // for an existing window. - if (params.isWebGPU() && IsLinux()) + // When running WebGPU tests always force a new display. + if (params.isWebGPU()) { return true; } @@ -188,6 +190,18 @@ bool ShouldAlwaysForceNewDisplay(const PlatformParameters ¶ms) SystemInfo *systemInfo = GetTestSystemInfo(); return (!systemInfo || !IsWindows() || systemInfo->hasAMDGPU()); } + +bool ShouldAlwaysForceNewWindow(const PlatformParameters ¶ms) +{ + // The WebGPU underlying vulkan and D3D swap chain appears to fail to get a new image after + // swapping when rapidly creating new swap chains for an existing window. + if (params.isWebGPU()) + { + return true; + } + + return false; +} } // anonymous namespace GPUTestConfig::API GetTestConfigAPIFromRenderer(angle::GLESDriverType driverType, @@ -195,6 +209,9 @@ GPUTestConfig::API GetTestConfigAPIFromRenderer(angle::GLESDriverType driverType EGLenum deviceType) { if (driverType != angle::GLESDriverType::AngleEGL && +#if defined(ANGLE_TEST_ENABLE_SYSTEM_EGL) + driverType != angle::GLESDriverType::SystemEGL && +#endif driverType != angle::GLESDriverType::AngleVulkanSecondariesEGL) { return GPUTestConfig::kAPIUnknown; @@ -368,6 +385,14 @@ GLColor32F ReadColor32F(GLint x, GLint y) void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driverType) { #if defined(ANGLE_USE_UTIL_LOADER) + Library *driverLibrary = ANGLETestEnvironment::GetDriverLibrary(driverType); + if (driverLibrary == nullptr) + { + WriteDebugMessage("Failed to load library! (driverType = %d)", + static_cast(driverType)); + return; + } + PFNEGLGETPROCADDRESSPROC getProcAddress; ANGLETestEnvironment::GetDriverLibrary(driverType)->getAs("eglGetProcAddress", &getProcAddress); ASSERT(nullptr != getProcAddress); @@ -386,6 +411,19 @@ bool IsFormatEmulated(GLenum target) return gl::IsEmulatedCompressedFormat(readFormat); } +EGLenum GetEglPlatform() +{ + EGLenum eglPlatform = EGL_PLATFORM_ANGLE_ANGLE; + +#if defined(ANGLE_TEST_ENABLE_SYSTEM_EGL) + if (angle::IsAndroid()) + { + eglPlatform = EGL_PLATFORM_ANDROID_KHR; + } +#endif + return eglPlatform; +} + } // namespace angle using namespace angle; @@ -559,7 +597,7 @@ void ANGLETestBase::initOSWindow() FATAL() << "Failed to create a new window"; } mFixture->osWindow->disableErrorMessageDialog(); - if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128)) + if (!mFixture->osWindow->initialize(windowName, 128, 128)) { std::cerr << "Failed to initialize OS Window.\n"; } @@ -701,12 +739,24 @@ void ANGLETestBase::ANGLETestSetUp() SetupEnvironmentVarsForCaptureReplay(); } + if (ShouldAlwaysForceNewWindow(*mCurrentParams)) + { + OSWindow::Delete(&mFixture->osWindow); + initOSWindow(); + } + if (!mFixture->osWindow->valid()) { mIsSetUp = true; return; } + // WGL tests are currently disabled. + if (mFixture->wglWindow) + { + FAIL() << "Unsupported driver."; + } + // Resize the window before creating the context so that the first make current // sets the viewport and scissor box to the right size. bool needSwap = false; @@ -736,60 +786,83 @@ void ANGLETestBase::ANGLETestSetUp() } needSwap = true; } - // WGL tests are currently disabled. - if (mFixture->wglWindow) - { - FAIL() << "Unsupported driver."; - } - else - { - Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(mCurrentParams->driver); - if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized()) + Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(mCurrentParams->driver); + + // Overriding ANGLE features requires the extension EGL_ANGLE_feature_control. + // Only allow skipping tests due to unsupported ANGLE extensions when testing the system EGL, + // since we want it to be obvious if ANGLE itself stops exposing them. + // Must be checked before initializing the Display, since + if (isDriverSystemEgl()) + { + if ((!mCurrentParams->eglParameters.enabledFeatureOverrides.empty() || + !mCurrentParams->eglParameters.disabledFeatureOverrides.empty()) && + !IsEGLClientExtensionEnabled("EGL_ANGLE_feature_control")) { - mFixture->eglWindow->destroyGL(); - if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, driverLib, - mCurrentParams->driver, - mCurrentParams->eglParameters)) - { - FAIL() << "EGL Display init failed."; - } + GTEST_SKIP() << "Test skipped because EGL_ANGLE_feature_control is not available."; } - else if (mCurrentParams->eglParameters != mFixture->eglWindow->getPlatform()) + } + + if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized()) + { + mFixture->eglWindow->destroyGL(); + if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, driverLib, + mCurrentParams->driver, + mCurrentParams->eglParameters)) { - FAIL() << "Internal parameter conflict error."; + FAIL() << "EGL Display init failed."; } + } + else if (mCurrentParams->eglParameters != mFixture->eglWindow->getPlatform()) + { + FAIL() << "Internal parameter conflict error."; + } + + // Skip tests that require unsupported ANGLE extensions. + checkUnsupportedExtensions(); + if (IsSkipped()) + { + return; + } - const GLWindowResult windowResult = mFixture->eglWindow->initializeSurface( - mFixture->osWindow, driverLib, mFixture->configParams); + const GLWindowResult windowResult = mFixture->eglWindow->initializeSurface( + mFixture->osWindow, driverLib, mFixture->configParams); - if (windowResult != GLWindowResult::NoError) + if (windowResult != GLWindowResult::NoError) + { + if (windowResult != GLWindowResult::Error) { - if (windowResult != GLWindowResult::Error) - { - // If the test requests an extension that isn't supported, automatically skip the - // test. - GTEST_SKIP() << "Test skipped due to missing extension"; - } - else if (mFixture->configParams.multisample) - { - // If the test requests a multisampled window that isn't supported, automatically - // skip the test. - GTEST_SKIP() << "Test skipped due to no multisampled configs available"; - } - else - { - // Otherwise fail the test. - FAIL() << "egl surface init failed."; - } + // If the test requests an extension that isn't supported, automatically skip the + // test. + GTEST_SKIP() << "Test skipped due to missing extension"; } - - if (!mDeferContextInit && !mFixture->eglWindow->initializeContext()) + else if (mFixture->configParams.multisample) + { + // If the test requests a multisampled window that isn't supported, automatically + // skip the test. + GTEST_SKIP() << "Test skipped due to no multisampled configs available"; + } + else { - FAIL() << "GL Context init failed."; + // Otherwise fail the test. + FAIL() << "egl surface init failed."; } } + if (!mDeferContextInit && !mFixture->eglWindow->initializeContext()) + { + FAIL() << "GL Context init failed."; + } + + if (mFixture->eglWindow->getClientMajorVersion() != mCurrentParams->majorVersion || + mFixture->eglWindow->getClientMinorVersion() != mCurrentParams->minorVersion) + { + WARN() << "Requested Context version does not match the version created. Requested: " + << mCurrentParams->majorVersion << "." << mCurrentParams->minorVersion + << ", Actual: " << mFixture->eglWindow->getClientMajorVersion() << "." + << mFixture->eglWindow->getClientMinorVersion(); + } + if (needSwap) { // Swap the buffers so that the default framebuffer picks up the resize @@ -808,6 +881,57 @@ void ANGLETestBase::ANGLETestSetUp() mRenderDoc.startFrame(); } +void ANGLETestBase::checkUnsupportedExtensions() +{ + // Only allow skipping tests due to unsupported ANGLE extensions when testing the system EGL, + // since we want it to be obvious if ANGLE itself stops exposing them. + if (mCurrentParams->driver != GLESDriverType::SystemEGL) + { + return; + } + + if (mFixture->configParams.webGLCompatibility && + !IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(), + "EGL_ANGLE_create_context_webgl_compatibility")) + { + GTEST_SKIP() + << "Test skipped due to EGL_ANGLE_create_context_webgl_compatibility not available"; + } + if (mFixture->configParams.robustResourceInit && + !IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(), + "EGL_ANGLE_robust_resource_initialization")) + { + GTEST_SKIP() + << "Test skipped due to EGL_ANGLE_robust_resource_initialization not available"; + } + if (!mFixture->configParams.extensionsEnabled && + !IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(), + "EGL_ANGLE_create_context_extensions_enabled")) + { + GTEST_SKIP() + << "Test skipped due to EGL_ANGLE_create_context_extensions_enabled not available"; + } + if (!mFixture->configParams.bindGeneratesResource && + !IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(), + "EGL_CHROMIUM_create_context_bind_generates_resource")) + { + GTEST_SKIP() << "Test skipped due to " + "EGL_CHROMIUM_create_context_bind_generates_resource not available"; + } + if (!mFixture->configParams.clientArraysEnabled && + !IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(), + "EGL_ANGLE_create_context_client_arrays")) + { + GTEST_SKIP() << "Test skipped due to EGL_ANGLE_create_context_client_arrays not available"; + } + if (!mFixture->configParams.contextProgramCacheEnabled && + !IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(), + "EGL_ANGLE_program_cache_control")) + { + GTEST_SKIP() << "Test skipped due to EGL_ANGLE_program_cache_control not available"; + } +} + void ANGLETestBase::ANGLETestPreTearDown() { // We swap an extra time before we call "tearDown" to capture resources before they're freed. @@ -828,7 +952,7 @@ void ANGLETestBase::ANGLETestTearDown() WriteDebugMessage("Exiting %s.%s\n", info->test_suite_name(), info->name()); } - if (mCurrentParams->noFixture || !mFixture->osWindow->valid()) + if (mCurrentParams->noFixture || !mFixture->osWindow || !mFixture->osWindow->valid()) { mRenderDoc.endFrame(); return; @@ -861,13 +985,18 @@ void ANGLETestBase::ANGLETestTearDown() } Event myEvent; - while (mFixture->osWindow->popEvent(&myEvent)) + while (mFixture->osWindow && mFixture->osWindow->popEvent(&myEvent)) { if (myEvent.Type == Event::EVENT_CLOSED) { exit(0); } } + + if (ShouldAlwaysForceNewWindow(*mCurrentParams)) + { + OSWindow::Delete(&mFixture->osWindow); + } } void ANGLETestBase::ReleaseFixtures() @@ -1132,8 +1261,7 @@ void ANGLETestBase::drawIndexedQuad(GLuint program, GLfloat positionAttribZ, GLfloat positionAttribXYScale) { - ASSERT(!mFixture || !mFixture->configParams.webGLCompatibility.valid() || - !mFixture->configParams.webGLCompatibility.value()); + ASSERT(!mFixture || !mFixture->configParams.webGLCompatibility); drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false); } diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h index ac103759f4a..2c7e0869654 100644 --- a/src/tests/test_utils/ANGLETest.h +++ b/src/tests/test_utils/ANGLETest.h @@ -10,6 +10,10 @@ #ifndef ANGLE_TESTS_ANGLE_TEST_H_ #define ANGLE_TESTS_ANGLE_TEST_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include #include @@ -18,6 +22,7 @@ #include "angle_test_configs.h" #include "angle_test_platform.h" #include "common/angleutils.h" +#include "common/platform_helpers.h" #include "common/system_utils.h" #include "common/vector_utils.h" #include "platform/PlatformMethods.h" @@ -236,6 +241,8 @@ bool IsFormatEmulated(GLenum target); GPUTestConfig::API GetTestConfigAPIFromRenderer(angle::GLESDriverType driverType, EGLenum renderer, EGLenum deviceType); + +EGLenum GetEglPlatform(); } // namespace angle #define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \ @@ -395,7 +402,7 @@ struct TestPlatformContext final : private angle::NonCopyable ANGLETestBase *currentTest = nullptr; }; -class ANGLETestBase +class ANGLETestBase : public ::testing::Test { protected: ANGLETestBase(const angle::PlatformParameters ¶ms); @@ -583,12 +590,20 @@ class ANGLETestBase mCurrentParams->isSwiftshader(); } + bool isDriverSystemEgl() const + { + return mCurrentParams->driver == angle::GLESDriverType::SystemEGL; + } + + angle::GLESDriverType getDriverType() const { return mCurrentParams->driver; } + bool platformSupportsMultithreading() const; bool mIsSetUp = false; private: void checkD3D11SDKLayersMessages(); + void checkUnsupportedExtensions(); void drawQuad(GLuint program, const std::string &positionAttribName, @@ -656,7 +671,7 @@ class ANGLETestBase }; template -class ANGLETest : public ANGLETestBase, public ::testing::TestWithParam +class ANGLETest : public ANGLETestBase, public ::testing::WithParamInterface { protected: ANGLETest(); diff --git a/src/tests/test_utils/CompilerTest.cpp b/src/tests/test_utils/CompilerTest.cpp new file mode 100644 index 00000000000..775eb1fd514 --- /dev/null +++ b/src/tests/test_utils/CompilerTest.cpp @@ -0,0 +1,203 @@ +// +// Copyright 2025 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. +// + +#include "tests/test_utils/CompilerTest.h" + +GLuint CompiledShader::compile(GLenum type, const char *source) +{ + mShader = glCreateShader(type); + + const char *sourceArray[1] = {source}; + glShaderSource(mShader, 1, sourceArray, nullptr); + glCompileShader(mShader); + + GLint compileResult; + glGetShaderiv(mShader, GL_COMPILE_STATUS, &compileResult); + + GLint infoLogLength; + glGetShaderiv(mShader, GL_INFO_LOG_LENGTH, &infoLogLength); + mInfoLog.clear(); + + if (infoLogLength > 0) + { + std::vector infoLog(infoLogLength); + glGetShaderInfoLog(mShader, infoLogLength, nullptr, infoLog.data()); + + // Note: the info log is nul-terminated. + mInfoLog = infoLog.data(); + } + + if (compileResult == 0) + { + std::cerr << "shader compilation failed: " + << (mInfoLog.empty() ? "" : mInfoLog.data()); + + destroy(); + } + else if (IsGLExtensionEnabled("GL_ANGLE_translated_shader_source")) + { + GLint translatedSourceLength; + glGetShaderiv(mShader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &translatedSourceLength); + + if (translatedSourceLength > 0) + { + std::vector translatedSource(translatedSourceLength); + glGetTranslatedShaderSourceANGLE(mShader, translatedSourceLength, nullptr, + translatedSource.data()); + + // Note: the translatedSource is nul-terminated. + mTranslatedSource = translatedSource.data(); + } + } + + return mShader; +} + +CompiledShader::~CompiledShader() +{ + if (mShader != 0) + { + destroy(); + } +} + +void CompiledShader::destroy() +{ + glDeleteShader(mShader); + ASSERT_GL_NO_ERROR(); + mShader = 0; + + mTranslatedSource.clear(); +} + +bool CompiledShader::hasInfoLog(const char *expect) const +{ + return mInfoLog.find(expect) != std::string::npos; +} + +bool CompiledShader::verifyInTranslatedSource(const char *expect) const +{ + return mTranslatedSource.empty() || mTranslatedSource.find(expect) != std::string::npos; +} + +bool CompiledShader::verifyNotInTranslatedSource(const char *expect) const +{ + return mTranslatedSource.empty() || mTranslatedSource.find(expect) == std::string::npos; +} + +bool CompiledShader::verifyCountInTranslatedSource(const char *expect, size_t expectCount) const +{ + if (mTranslatedSource.empty()) + { + return true; + } + + size_t count = 0; + std::string::size_type pos = 0; + while (true) + { + pos = mTranslatedSource.find(expect, pos); + if (pos == std::string::npos) + { + break; + } + ++count; + ++pos; + } + return count == expectCount; +} + +void CompilerTest::testSetUp() {} + +void CompilerTest::testTearDown() +{ + reset(); +} + +void CompilerTest::reset() +{ + mVertexShader.destroy(); + mTessellationControlShader.destroy(); + mTessellationEvaluationShader.destroy(); + mGeometryShader.destroy(); + mFragmentShader.destroy(); + mComputeShader.destroy(); + + glDeleteProgram(mProgram); + mProgram = 0; +} + +const CompiledShader &CompilerTest::compile(GLenum type, const char *source) +{ + CompiledShader &shader = getCompiledShader(type); + shader.compile(type, source); + return shader; +} + +CompiledShader &CompilerTest::getCompiledShader(GLenum type) +{ + switch (type) + { + case GL_VERTEX_SHADER: + return mVertexShader; + case GL_TESS_CONTROL_SHADER: + return mTessellationControlShader; + case GL_TESS_EVALUATION_SHADER: + return mTessellationEvaluationShader; + case GL_GEOMETRY_SHADER: + return mGeometryShader; + case GL_FRAGMENT_SHADER: + return mFragmentShader; + case GL_COMPUTE_SHADER: + return mComputeShader; + default: + // Unsupported type + ASSERT(false); + return mVertexShader; + } +} + +GLuint CompilerTest::link() +{ + mProgram = glCreateProgram(); + + if (mComputeShader.success()) + { + glAttachShader(mProgram, mComputeShader.getShader()); + } + else + { + if (mVertexShader.success()) + { + glAttachShader(mProgram, mVertexShader.getShader()); + } + if (mTessellationControlShader.success()) + { + glAttachShader(mProgram, mTessellationControlShader.getShader()); + } + if (mTessellationEvaluationShader.success()) + { + glAttachShader(mProgram, mTessellationEvaluationShader.getShader()); + } + if (mGeometryShader.success()) + { + glAttachShader(mProgram, mGeometryShader.getShader()); + } + if (mFragmentShader.success()) + { + glAttachShader(mProgram, mFragmentShader.getShader()); + } + } + + glLinkProgram(mProgram); + EXPECT_GL_NO_ERROR(); + + GLint linkStatus; + glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus); + EXPECT_NE(linkStatus, 0); + + return mProgram; +} diff --git a/src/tests/test_utils/CompilerTest.h b/src/tests/test_utils/CompilerTest.h new file mode 100644 index 00000000000..6120d7c5fd8 --- /dev/null +++ b/src/tests/test_utils/CompilerTest.h @@ -0,0 +1,91 @@ +// +// Copyright 2025 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. +// +// CompilerTest.h: +// Helpers to test shader validation and translated output. +// + +#ifndef TESTS_TEST_UTILS_COMPILER_TEST_H_ +#define TESTS_TEST_UTILS_COMPILER_TEST_H_ + +#include "test_utils/ANGLETest.h" + +class CompiledShader +{ + public: + ~CompiledShader(); + + // Compile the source and return the GL shader object. + // + // If compilation is successful, the return value will be non-zero and mTranslatedSource will + // contain the translated source if ANGLE_translated_shader_source is supported. Note that with + // SPIR-V, the translated source is mostly hex numbers, so the test pretends the extension is + // not supported in that case. If compilation fails, 0 is returned. + // + // In either case, the compiler's logs are placed in mInfoLog. + GLuint compile(GLenum type, const char *source); + void destroy(); + + bool success() const { return mShader != 0; } + GLuint getShader() const { return mShader; } + const std::string &getInfoLog() const { return mInfoLog; } + const std::string &getTranslatedSource() const { return mTranslatedSource; } + + // Returns true if the expected message is found in the info log. + bool hasInfoLog(const char *expect) const; + + // Returns true if either the translated source does not exist or it contains this substring. + bool verifyInTranslatedSource(const char *expect) const; + // Returns true if either the translated source does not exist or it does not contains this + // substring. + bool verifyNotInTranslatedSource(const char *expect) const; + // Returns true if either the translated source does not exist or it contains this substring + // exactly N times. + bool verifyCountInTranslatedSource(const char *expect, size_t expectCount) const; + + private: + std::string mInfoLog; + std::string mTranslatedSource; + GLuint mShader = 0; +}; + +class CompilerTest : public ANGLETest<> +{ + public: + CompilerTest() + { + setWindowWidth(128); + setWindowHeight(128); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } + + void reset(); + + const CompiledShader &compile(GLenum type, const char *source); + CompiledShader &getCompiledShader(GLenum type); + + // Link the compiled shaders into a program, and return it. The focus of this class is the + // shader compiler, so if asked to link, it assumes that link is going to succeed. + GLuint link(); + + protected: + void testSetUp() override; + void testTearDown() override; + + private: + CompiledShader mVertexShader; + CompiledShader mTessellationControlShader; + CompiledShader mTessellationEvaluationShader; + CompiledShader mGeometryShader; + CompiledShader mFragmentShader; + CompiledShader mComputeShader; + + GLuint mProgram = 0; +}; + +#endif // TESTS_TEST_UTILS_COMPILER_TEST_H_ diff --git a/src/tests/test_utils/ConstantFoldingTest.cpp b/src/tests/test_utils/ConstantFoldingTest.cpp deleted file mode 100644 index 9fe1d4a9760..00000000000 --- a/src/tests/test_utils/ConstantFoldingTest.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright 2016 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. -// -// ConstantFoldingTest.cpp: -// Utilities for constant folding tests. -// - -#include "tests/test_utils/ConstantFoldingTest.h" - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "compiler/translator/glsl/TranslatorESSL.h" - -using namespace sh; - -void ConstantFoldingExpressionTest::evaluate(const std::string &type, const std::string &expression) -{ - // We first assign the expression into a const variable so we can also verify that it gets - // qualified as a constant expression. We then assign that constant expression into my_FragColor - // to make sure that the value is not pruned. - std::stringstream shaderStream; - shaderStream << "#version 310 es\n" - "precision mediump float;\n" - << "out " << type << " my_FragColor;\n" - << "void main()\n" - "{\n" - << " const " << type << " v = " << expression << ";\n" - << " my_FragColor = v;\n" - "}\n"; - compileAssumeSuccess(shaderStream.str()); -} - -void ConstantFoldingExpressionTest::evaluateIvec4(const std::string &ivec4Expression) -{ - evaluate("ivec4", ivec4Expression); -} - -void ConstantFoldingExpressionTest::evaluateVec4(const std::string &ivec4Expression) -{ - evaluate("vec4", ivec4Expression); -} - -void ConstantFoldingExpressionTest::evaluateFloat(const std::string &floatExpression) -{ - evaluate("float", floatExpression); -} - -void ConstantFoldingExpressionTest::evaluateInt(const std::string &intExpression) -{ - evaluate("int", intExpression); -} - -void ConstantFoldingExpressionTest::evaluateUint(const std::string &uintExpression) -{ - evaluate("uint", uintExpression); -} diff --git a/src/tests/test_utils/ConstantFoldingTest.h b/src/tests/test_utils/ConstantFoldingTest.h deleted file mode 100644 index ab7eee908d8..00000000000 --- a/src/tests/test_utils/ConstantFoldingTest.h +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright 2016 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. -// -// ConstantFoldingTest.h: -// Utilities for constant folding tests. -// - -#ifndef TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_ -#define TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_ - -#include - -#include "common/mathutil.h" -#include "compiler/translator/tree_util/FindMain.h" -#include "compiler/translator/tree_util/FindSymbolNode.h" -#include "compiler/translator/tree_util/IntermTraverse.h" -#include "tests/test_utils/ShaderCompileTreeTest.h" - -namespace sh -{ - -class TranslatorESSL; - -template -class ConstantFinder : public TIntermTraverser -{ - public: - ConstantFinder(const std::vector &constantVector) - : TIntermTraverser(true, false, false), - mConstantVector(constantVector), - mFaultTolerance(T()), - mFound(false) - {} - - ConstantFinder(const std::vector &constantVector, const T &faultTolerance) - : TIntermTraverser(true, false, false), - mConstantVector(constantVector), - mFaultTolerance(faultTolerance), - mFound(false) - {} - - ConstantFinder(const T &value) - : TIntermTraverser(true, false, false), mFaultTolerance(T()), mFound(false) - { - mConstantVector.push_back(value); - } - - void visitConstantUnion(TIntermConstantUnion *node) - { - if (node->getType().getObjectSize() == mConstantVector.size()) - { - bool found = true; - for (size_t i = 0; i < mConstantVector.size(); i++) - { - if (!isEqual(node->getConstantValue()[i], mConstantVector[i])) - { - found = false; - break; - } - } - if (found) - { - mFound = found; - } - } - } - - bool found() const { return mFound; } - - private: - bool isEqual(const TConstantUnion &node, const float &value) const - { - if (node.getType() != EbtFloat) - { - return false; - } - if (value == std::numeric_limits::infinity()) - { - return gl::isInf(node.getFConst()) && node.getFConst() > 0; - } - else if (value == -std::numeric_limits::infinity()) - { - return gl::isInf(node.getFConst()) && node.getFConst() < 0; - } - else if (gl::isNaN(value)) - { - // All NaNs are treated as equal. - return gl::isNaN(node.getFConst()); - } - return mFaultTolerance >= fabsf(node.getFConst() - value); - } - - bool isEqual(const TConstantUnion &node, const int &value) const - { - if (node.getType() != EbtInt) - { - return false; - } - ASSERT(mFaultTolerance < std::numeric_limits::max()); - // abs() returns 0 at least on some platforms when the minimum int value is passed in (it - // doesn't have a positive counterpart). - return mFaultTolerance >= abs(node.getIConst() - value) && - (node.getIConst() - value) != std::numeric_limits::min(); - } - - bool isEqual(const TConstantUnion &node, const unsigned int &value) const - { - if (node.getType() != EbtUInt) - { - return false; - } - ASSERT(mFaultTolerance < static_cast(std::numeric_limits::max())); - return static_cast(mFaultTolerance) >= - abs(static_cast(node.getUConst() - value)) && - static_cast(node.getUConst() - value) != std::numeric_limits::min(); - } - - bool isEqual(const TConstantUnion &node, const bool &value) const - { - if (node.getType() != EbtBool) - { - return false; - } - return node.getBConst() == value; - } - - std::vector mConstantVector; - T mFaultTolerance; - bool mFound; -}; - -class ConstantFoldingTest : public ShaderCompileTreeTest -{ - public: - ConstantFoldingTest() {} - - protected: - ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } - ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } - - template - bool constantFoundInAST(T constant) - { - ConstantFinder finder(constant); - mASTRoot->traverse(&finder); - return finder.found(); - } - - template - bool constantVectorFoundInAST(const std::vector &constantVector) - { - ConstantFinder finder(constantVector); - mASTRoot->traverse(&finder); - return finder.found(); - } - - template - bool constantColumnMajorMatrixFoundInAST(const std::vector &constantMatrix) - { - return constantVectorFoundInAST(constantMatrix); - } - - template - bool constantVectorNearFoundInAST(const std::vector &constantVector, const T &faultTolerance) - { - ConstantFinder finder(constantVector, faultTolerance); - mASTRoot->traverse(&finder); - return finder.found(); - } - - bool symbolFoundInAST(const char *symbolName) - { - return FindSymbolNode(mASTRoot, ImmutableString(symbolName)) != nullptr; - } - - bool symbolFoundInMain(const char *symbolName) - { - return FindSymbolNode(FindMain(mASTRoot), ImmutableString(symbolName)) != nullptr; - } -}; - -class ConstantFoldingExpressionTest : public ConstantFoldingTest -{ - public: - ConstantFoldingExpressionTest() {} - - void evaluateIvec4(const std::string &ivec4Expression); - void evaluateVec4(const std::string &vec4Expression); - void evaluateFloat(const std::string &floatExpression); - void evaluateInt(const std::string &intExpression); - void evaluateUint(const std::string &uintExpression); - - private: - void evaluate(const std::string &type, const std::string &expression); -}; - -} // namespace sh - -#endif // TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_ diff --git a/src/tests/test_utils/MultiThreadSteps.cpp b/src/tests/test_utils/MultiThreadSteps.cpp index 0000e335a46..5b0358ee6f1 100644 --- a/src/tests/test_utils/MultiThreadSteps.cpp +++ b/src/tests/test_utils/MultiThreadSteps.cpp @@ -6,6 +6,10 @@ // MultiThreadSteps.cpp: // Synchronization help for tests that use multiple threads. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "MultiThreadSteps.h" #include "angle_test_platform.h" diff --git a/src/tests/test_utils/MultiviewTest.h b/src/tests/test_utils/MultiviewTest.h index f2dc8052f97..7e7c7bf9013 100644 --- a/src/tests/test_utils/MultiviewTest.h +++ b/src/tests/test_utils/MultiviewTest.h @@ -98,7 +98,6 @@ class MultiviewTestBase : public ANGLETestBase { setWindowWidth(128); setWindowHeight(128); - setWebGLCompatibilityEnabled(true); } virtual ~MultiviewTestBase() {} @@ -109,7 +108,7 @@ class MultiviewTestBase : public ANGLETestBase // Base class for multiview tests that don't need specific helper functions. class MultiviewTest : public MultiviewTestBase, - public ::testing::TestWithParam + public ::testing::WithParamInterface { protected: MultiviewTest() : MultiviewTestBase(GetParam()) {} diff --git a/src/tests/test_utils/ShaderCompileTreeTest.cpp b/src/tests/test_utils/ShaderCompileTreeTest.cpp index 7091bb9ff3a..008a7e63ad2 100644 --- a/src/tests/test_utils/ShaderCompileTreeTest.cpp +++ b/src/tests/test_utils/ShaderCompileTreeTest.cpp @@ -111,7 +111,6 @@ class OnlyContainsZeroConstantsTraverser final : public TIntermTraverser void ShaderCompileTreeTest::SetUp() { - mAllocator.push(); SetGlobalPoolAllocator(&mAllocator); ShBuiltInResources resources; @@ -128,13 +127,13 @@ void ShaderCompileTreeTest::TearDown() delete mTranslator; SetGlobalPoolAllocator(nullptr); - mAllocator.pop(); + mAllocator.reset(); } bool ShaderCompileTreeTest::compile(const std::string &shaderString) { const char *shaderStrings[] = {shaderString.c_str()}; - mASTRoot = mTranslator->compileTreeForTesting(shaderStrings, 1, mCompileOptions); + mASTRoot = mTranslator->compileTreeForTesting(shaderStrings, mCompileOptions); TInfoSink &infoSink = mTranslator->getInfoSink(); mInfoLog = infoSink.info.c_str(); return mASTRoot != nullptr; diff --git a/src/tests/test_utils/ShaderExtensionTest.h b/src/tests/test_utils/ShaderExtensionTest.h deleted file mode 100644 index 89702ca468e..00000000000 --- a/src/tests/test_utils/ShaderExtensionTest.h +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright 2018 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. -// -// ShaderExtensionTest.cpp: -// Utilities for testing that GLSL extension pragma and changing the extension flag in compiler -// resources has the correct effect. -// - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" -#include "gtest/gtest.h" - -using testing::Combine; -using testing::make_tuple; -using testing::Values; - -namespace sh -{ - -const char ESSLVersion100[] = "#version 100\n"; -const char ESSLVersion300[] = "#version 300 es\n"; -const char ESSLVersion310[] = "#version 310 es\n"; - -class ShaderExtensionTest - : public testing::TestWithParam> -{ - protected: - void SetUp() override - { - sh::InitBuiltInResources(&mResources); - mCompiler = nullptr; - mCompileOptions = {}; - mCompileOptions.objectCode = true; - } - - void TearDown() override { DestroyCompiler(); } - void DestroyCompiler() - { - if (mCompiler) - { - sh::Destruct(mCompiler); - mCompiler = nullptr; - } - } - - void InitializeCompiler() - { - DestroyCompiler(); - mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), - SH_GLSL_COMPATIBILITY_OUTPUT, &mResources); - ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; - } - - testing::AssertionResult TestShaderCompile(const char *pragma) - { - return TestShaderCompile(testing::get<1>(GetParam()), // Version. - pragma, - testing::get<2>(GetParam()) // Shader. - ); - } - - testing::AssertionResult TestShaderCompile(const char *version, - const char *pragma, - const char *shader) - { - const char *shaderStrings[] = {version, pragma, shader}; - bool success = sh::Compile(mCompiler, shaderStrings, 3, mCompileOptions); - if (success) - { - return ::testing::AssertionSuccess() << "Compilation success"; - } - return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); - } - - protected: - ShBuiltInResources mResources; - ShHandle mCompiler; - ShCompileOptions mCompileOptions; -}; - -} // namespace sh diff --git a/src/tests/test_utils/VulkanHelper.cpp b/src/tests/test_utils/VulkanHelper.cpp index 249e41730b5..5135cb2bb5c 100644 --- a/src/tests/test_utils/VulkanHelper.cpp +++ b/src/tests/test_utils/VulkanHelper.cpp @@ -6,6 +6,10 @@ // VulkanHelper.cpp : Helper for allocating & managing vulkan external objects. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/VulkanHelper.h" #include @@ -474,6 +478,22 @@ void VulkanHelper::initializeFromANGLE() vkGetSemaphoreZirconHandleFUCHSIA = reinterpret_cast( vkGetInstanceProcAddr(mInstance, "vkGetSemaphoreZirconHandleFUCHSIA")); ASSERT(!mHasExternalSemaphoreFuchsia || vkGetSemaphoreZirconHandleFUCHSIA); + + EGLAttrib featureCount = 0; + EXPECT_TRUE(eglQueryDisplayAttribANGLE(display, EGL_FEATURE_COUNT_ANGLE, &featureCount)); + for (EGLint index = 0; index < featureCount; ++index) + { + const char *name = eglQueryStringiANGLE(display, EGL_FEATURE_NAME_ANGLE, index); + const char *status = eglQueryStringiANGLE(display, EGL_FEATURE_STATUS_ANGLE, index); + ASSERT(name != nullptr); + ASSERT(status != nullptr); + + if (strcmp(name, "supportsUnifiedImageLayouts") == 0) + { + mHasUnifiedImageLayouts = strcmp(status, "enabled") == 0; + break; + } + } } VkResult VulkanHelper::createImage2D(VkFormat format, @@ -1147,35 +1167,35 @@ void VulkanHelper::readPixels(VkImage srcImage, }; constexpr uint32_t bufferImageCopyCount = std::extent(); - if (srcImageLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) - { - VkImageMemoryBarrier imageMemoryBarriers = { - /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - /* .pNext = */ nullptr, - /* .srcAccessMask = */ VK_ACCESS_TRANSFER_WRITE_BIT, - /* .dstAccessMask = */ VK_ACCESS_TRANSFER_READ_BIT, - /* .oldLayout = */ srcImageLayout, - /* .newLayout = */ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - /* .srcQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, - /* .dstQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, - /* .image = */ srcImage, - /* .subresourceRange = */ - { - /* .aspectMask = */ VK_IMAGE_ASPECT_COLOR_BIT, - /* .baseMipLevel = */ 0, - /* .levelCount = */ 1, - /* .baseArrayLayer = */ 0, - /* .layerCount = */ 1, - }, + const VkImageLayout dstImageLayout = + mHasUnifiedImageLayouts ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - }; - vkCmdPipelineBarrier(commandBuffers[0], VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &imageMemoryBarriers); - srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - } + // Assume the worst and issue a barrier, previous usage is unknown. + VkImageMemoryBarrier imageMemoryBarriers = { + /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + /* .pNext = */ nullptr, + /* .srcAccessMask = */ VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT, + /* .dstAccessMask = */ VK_ACCESS_TRANSFER_READ_BIT, + /* .oldLayout = */ srcImageLayout, + /* .newLayout = */ dstImageLayout, + /* .srcQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, + /* .dstQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, + /* .image = */ srcImage, + /* .subresourceRange = */ + { + /* .aspectMask = */ VK_IMAGE_ASPECT_COLOR_BIT, + /* .baseMipLevel = */ 0, + /* .levelCount = */ 1, + /* .baseArrayLayer = */ 0, + /* .layerCount = */ 1, + }, - vkCmdCopyImageToBuffer(commandBuffers[0], srcImage, srcImageLayout, stagingBuffer, + }; + vkCmdPipelineBarrier(commandBuffers[0], VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, + &imageMemoryBarriers); + + vkCmdCopyImageToBuffer(commandBuffers[0], srcImage, dstImageLayout, stagingBuffer, bufferImageCopyCount, bufferImageCopies); VkMemoryBarrier memoryBarriers[] = { @@ -1247,7 +1267,7 @@ void VulkanHelper::readPixels(VkImage srcImage, } void VulkanHelper::writePixels(VkImage dstImage, - VkImageLayout imageLayout, + VkImageLayout srcImageLayout, VkFormat imageFormat, VkOffset3D imageOffset, VkExtent3D imageExtent, @@ -1357,34 +1377,33 @@ void VulkanHelper::writePixels(VkImage dstImage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0 /* dependencyFlags */, memoryBarrierCount, memoryBarriers, 0, nullptr, 0, nullptr); - // Memory-barrier for image to Transfer-Write. - if (imageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) - { - VkImageMemoryBarrier imageMemoryBarriers = { - /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - /* .pNext = */ nullptr, - /* .srcAccessMask = */ VK_ACCESS_NONE, - /* .dstAccessMask = */ VK_ACCESS_TRANSFER_WRITE_BIT, - /* .oldLayout = */ imageLayout, - /* .newLayout = */ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - /* .srcQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, - /* .dstQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, - /* .image = */ dstImage, - /* .subresourceRange = */ - { - /* .aspectMask = */ VK_IMAGE_ASPECT_COLOR_BIT, - /* .baseMipLevel = */ 0, - /* .levelCount = */ 1, - /* .baseArrayLayer = */ 0, - /* .layerCount = */ 1, - }, + const VkImageLayout dstImageLayout = + mHasUnifiedImageLayouts ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - }; - vkCmdPipelineBarrier(commandBuffers[0], VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &imageMemoryBarriers); - imageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - } + // Assume the worst and issue a barrier, previous usage is unknown. + VkImageMemoryBarrier imageMemoryBarriers = { + /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + /* .pNext = */ nullptr, + /* .srcAccessMask = */ VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT, + /* .dstAccessMask = */ VK_ACCESS_TRANSFER_WRITE_BIT, + /* .oldLayout = */ srcImageLayout, + /* .newLayout = */ dstImageLayout, + /* .srcQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, + /* .dstQueueFamilyIndex = */ mGraphicsQueueFamilyIndex, + /* .image = */ dstImage, + /* .subresourceRange = */ + { + /* .aspectMask = */ VK_IMAGE_ASPECT_COLOR_BIT, + /* .baseMipLevel = */ 0, + /* .levelCount = */ 1, + /* .baseArrayLayer = */ 0, + /* .layerCount = */ 1, + }, + + }; + vkCmdPipelineBarrier(commandBuffers[0], VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, + &imageMemoryBarriers); // Issue the buffer to image copy. VkBufferImageCopy bufferImageCopies[] = { @@ -1406,7 +1425,7 @@ void VulkanHelper::writePixels(VkImage dstImage, constexpr uint32_t bufferImageCopyCount = std::extent(); - vkCmdCopyBufferToImage(commandBuffers[0], stagingBuffer, dstImage, imageLayout, + vkCmdCopyBufferToImage(commandBuffers[0], stagingBuffer, dstImage, dstImageLayout, bufferImageCopyCount, bufferImageCopies); result = vkEndCommandBuffer(commandBuffers[0]); diff --git a/src/tests/test_utils/VulkanHelper.h b/src/tests/test_utils/VulkanHelper.h index 65c46323cfd..bf288c75beb 100644 --- a/src/tests/test_utils/VulkanHelper.h +++ b/src/tests/test_utils/VulkanHelper.h @@ -140,7 +140,7 @@ class VulkanHelper // Writes pixels into an image. Currently only VK_FORMAT_R8G8B8A8_UNORM // and VK_FORMAT_B8G8R8A8_UNORM formats are supported. void writePixels(VkImage dstImage, - VkImageLayout imageLayout, + VkImageLayout srcImageLayout, VkFormat imageFormat, VkOffset3D imageOffset, VkExtent3D imageExtent, @@ -157,6 +157,8 @@ class VulkanHelper void *pixels, size_t pixelsSize); + bool useUnifiedImageLayouts() const { return mHasUnifiedImageLayouts; } + private: bool mInitializedFromANGLE = false; VkInstance mInstance = VK_NULL_HANDLE; @@ -174,6 +176,7 @@ class VulkanHelper bool mHasExternalMemoryFuchsia = false; bool mHasExternalSemaphoreFd = false; bool mHasExternalSemaphoreFuchsia = false; + bool mHasUnifiedImageLayouts = false; PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2 = nullptr; PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR = nullptr; diff --git a/src/tests/test_utils/angle_test_configs.cpp b/src/tests/test_utils/angle_test_configs.cpp index fe2247462ba..d312e572666 100644 --- a/src/tests/test_utils/angle_test_configs.cpp +++ b/src/tests/test_utils/angle_test_configs.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils/angle_test_configs.h" #include "common/debug.h" @@ -39,12 +43,12 @@ bool HasFeatureOverride(const std::vector &overrides, Feature feature) } } // namespace -PlatformParameters::PlatformParameters() : PlatformParameters(2, 0, GLESDriverType::AngleEGL) {} +PlatformParameters::PlatformParameters() : PlatformParameters(2, 0, kDefaultGLESDriver) {} PlatformParameters::PlatformParameters(EGLint majorVersion, EGLint minorVersion, const EGLPlatformParameters &eglPlatformParameters) - : driver(GLESDriverType::AngleEGL), + : driver(kDefaultGLESDriver), noFixture(false), eglParameters(eglPlatformParameters), majorVersion(majorVersion), @@ -175,7 +179,7 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp) stream << "WGL"; break; case GLESDriverType::SystemEGL: - stream << "EGL"; + stream << GetRendererName(pp.eglParameters.renderer); break; case GLESDriverType::ZinkEGL: stream << "Zink"; @@ -417,12 +421,6 @@ EGLPlatformParameters OPENGL(EGLint major, EGLint minor) return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, major, minor, EGL_DONT_CARE); } -EGLPlatformParameters OPENGL_NULL() -{ - return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, EGL_DONT_CARE, EGL_DONT_CARE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE); -} - EGLPlatformParameters OPENGLES() { return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE); @@ -434,12 +432,6 @@ EGLPlatformParameters OPENGLES(EGLint major, EGLint minor) EGL_DONT_CARE); } -EGLPlatformParameters OPENGLES_NULL() -{ - return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, EGL_DONT_CARE, - EGL_DONT_CARE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE); -} - EGLPlatformParameters OPENGL_OR_GLES() { #if defined(ANGLE_PLATFORM_ANDROID) @@ -458,15 +450,6 @@ EGLPlatformParameters OPENGL_OR_GLES(EGLint major, EGLint minor) #endif } -EGLPlatformParameters OPENGL_OR_GLES_NULL() -{ -#if defined(ANGLE_PLATFORM_ANDROID) - return OPENGLES_NULL(); -#else - return OPENGL_NULL(); -#endif -} - EGLPlatformParameters VULKAN() { return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE); @@ -596,21 +579,6 @@ PlatformParameters ES3_D3D11_FL10_1() return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1()); } -PlatformParameters ES31_D3D11() -{ - return PlatformParameters(3, 1, egl_platform::D3D11()); -} - -PlatformParameters ES31_D3D11_FL11_1() -{ - return PlatformParameters(3, 1, egl_platform::D3D11_FL11_1()); -} - -PlatformParameters ES31_D3D11_FL11_0() -{ - return PlatformParameters(3, 1, egl_platform::D3D11_FL11_0()); -} - PlatformParameters ES3_D3D11_WARP() { return PlatformParameters(3, 0, egl_platform::D3D11_WARP()); @@ -821,31 +789,6 @@ PlatformParameters ES3_WGL() return PlatformParameters(3, 0, GLESDriverType::SystemWGL); } -PlatformParameters ES1_EGL() -{ - return PlatformParameters(1, 0, GLESDriverType::SystemEGL); -} - -PlatformParameters ES2_EGL() -{ - return PlatformParameters(2, 0, GLESDriverType::SystemEGL); -} - -PlatformParameters ES3_EGL() -{ - return PlatformParameters(3, 0, GLESDriverType::SystemEGL); -} - -PlatformParameters ES31_EGL() -{ - return PlatformParameters(3, 1, GLESDriverType::SystemEGL); -} - -PlatformParameters ES32_EGL() -{ - return PlatformParameters(3, 2, GLESDriverType::SystemEGL); -} - PlatformParameters ES1_ANGLE_Vulkan_Secondaries() { return WithVulkanSecondaries(ES1_VULKAN()); diff --git a/src/tests/test_utils/angle_test_configs.h b/src/tests/test_utils/angle_test_configs.h index 74ce9aa4ce0..8ee753645df 100644 --- a/src/tests/test_utils/angle_test_configs.h +++ b/src/tests/test_utils/angle_test_configs.h @@ -110,15 +110,12 @@ EGLPlatformParameters METAL(); EGLPlatformParameters OPENGL(); EGLPlatformParameters OPENGL(EGLint major, EGLint minor); -EGLPlatformParameters OPENGL_NULL(); EGLPlatformParameters OPENGLES(); EGLPlatformParameters OPENGLES(EGLint major, EGLint minor); -EGLPlatformParameters OPENGLES_NULL(); EGLPlatformParameters OPENGL_OR_GLES(); EGLPlatformParameters OPENGL_OR_GLES(EGLint major, EGLint minor); -EGLPlatformParameters OPENGL_OR_GLES_NULL(); EGLPlatformParameters VULKAN(); EGLPlatformParameters VULKAN_NULL(); @@ -153,9 +150,6 @@ PlatformParameters ES3_D3D11(); PlatformParameters ES3_D3D11_FL11_1(); PlatformParameters ES3_D3D11_FL11_0(); PlatformParameters ES3_D3D11_FL10_1(); -PlatformParameters ES31_D3D11(); -PlatformParameters ES31_D3D11_FL11_1(); -PlatformParameters ES31_D3D11_FL11_0(); PlatformParameters ES3_D3D11_WARP(); PlatformParameters ES3_D3D11_FL11_1_WARP(); @@ -206,12 +200,6 @@ PlatformParameters ES3_METAL(); PlatformParameters ES2_WGL(); PlatformParameters ES3_WGL(); -PlatformParameters ES1_EGL(); -PlatformParameters ES2_EGL(); -PlatformParameters ES3_EGL(); -PlatformParameters ES31_EGL(); -PlatformParameters ES32_EGL(); - PlatformParameters ES1_ANGLE_Vulkan_Secondaries(); PlatformParameters ES2_ANGLE_Vulkan_Secondaries(); PlatformParameters ES3_ANGLE_Vulkan_Secondaries(); diff --git a/src/tests/test_utils/angle_test_instantiate.cpp b/src/tests/test_utils/angle_test_instantiate.cpp index 8038b3ce8ef..7c802b176a9 100644 --- a/src/tests/test_utils/angle_test_instantiate.cpp +++ b/src/tests/test_utils/angle_test_instantiate.cpp @@ -7,6 +7,10 @@ // angle_test_instantiate.cpp: Adds support for filtering parameterized // tests by platform, so we skip unsupported configs. +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "test_utils/angle_test_instantiate.h" #include @@ -342,6 +346,11 @@ bool IsAMD() return HasSystemVendorID(kVendorID_AMD); } +bool IsSamsung() +{ + return HasSystemVendorID(kVendorID_Samsung); +} + bool IsAppleGPU() { return HasSystemVendorID(kVendorID_Apple); @@ -357,6 +366,11 @@ bool IsSwiftshaderDevice() return HasSystemDeviceID(kVendorID_GOOGLE, kDeviceID_Swiftshader); } +bool IsLavapipeDevice() +{ + return HasSystemDeviceID(kVendorID_Mesa, kDeviceID_Lavapipe); +} + bool SwiftshaderTestsEnabled() { #if defined(ANGLE_ENABLE_SWIFTSHADER) @@ -564,11 +578,9 @@ bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters if (IsLinux() || IsAndroid()) { - // We do not support WGL bindings on Linux/Android. We do support system EGL. + // We do not support WGL bindings on Linux/Android. switch (param.driver) { - case GLESDriverType::SystemEGL: - return param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; case GLESDriverType::SystemWGL: return false; case GLESDriverType::ZinkEGL: @@ -580,11 +592,13 @@ bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters if (IsLinux()) { - ASSERT(param.driver == GLESDriverType::AngleEGL); + ASSERT(param.driver == GLESDriverType::AngleEGL || + param.driver == GLESDriverType::SystemEGL); // Currently we support the OpenGL, Vulkan and WebGPU back-ends on Linux. switch (param.getRenderer()) { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: case EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE: case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: @@ -596,7 +610,8 @@ bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters if (IsAndroid()) { - ASSERT(param.driver == GLESDriverType::AngleEGL); + ASSERT(param.driver == GLESDriverType::AngleEGL || + param.driver == GLESDriverType::SystemEGL); // Nexus Android devices don't support backing 3.2 contexts if (param.eglParameters.majorVersion == 3 && param.eglParameters.minorVersion == 2) @@ -610,6 +625,7 @@ bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters // Currently we support the GLES and Vulkan back-ends on Android. switch (param.getRenderer()) { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: return true; case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: diff --git a/src/tests/test_utils/angle_test_instantiate.h b/src/tests/test_utils/angle_test_instantiate.h index b02f64e68e1..acfe3291edb 100644 --- a/src/tests/test_utils/angle_test_instantiate.h +++ b/src/tests/test_utils/angle_test_instantiate.h @@ -10,6 +10,10 @@ #ifndef ANGLE_TEST_INSTANTIATE_H_ #define ANGLE_TEST_INSTANTIATE_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include #include "common/platform_helpers.h" @@ -43,6 +47,7 @@ bool IsAndroid14OrNewer(); // GPU vendors. bool IsIntel(); bool IsAMD(); +bool IsSamsung(); bool IsAppleGPU(); bool IsARM(); bool IsNVIDIA(); @@ -119,29 +124,13 @@ struct CombinedPrintToStringParamName INSTANTIATE_TEST_SUITE_P(, testName, testing::ValuesIn(::angle::FilterTestParams(valuesin)), \ testing::PrintToStringParamName()) -#if !defined(ANGLE_TEST_ENABLE_SYSTEM_EGL) -# define ANGLE_TEST_PLATFORMS_ES1_SYSTEM_EGL -# define ANGLE_TEST_PLATFORMS_ES2_SYSTEM_EGL -# define ANGLE_TEST_PLATFORMS_ES3_SYSTEM_EGL -# define ANGLE_TEST_PLATFORMS_ES31_SYSTEM_EGL -# define ANGLE_TEST_PLATFORMS_ES32_SYSTEM_EGL -#else -# define ANGLE_TEST_PLATFORMS_ES1_SYSTEM_EGL ES1_EGL(), -# define ANGLE_TEST_PLATFORMS_ES2_SYSTEM_EGL ES2_EGL(), -# define ANGLE_TEST_PLATFORMS_ES3_SYSTEM_EGL ES3_EGL(), -# define ANGLE_TEST_PLATFORMS_ES31_SYSTEM_EGL ES31_EGL(), -# define ANGLE_TEST_PLATFORMS_ES32_SYSTEM_EGL ES32_EGL(), -#endif - #define ANGLE_ALL_TEST_PLATFORMS_ES1 \ - ANGLE_TEST_PLATFORMS_ES1_SYSTEM_EGL \ ES1_D3D11(), ES1_METAL(), ES1_OPENGL(), ES1_OPENGLES(), ES1_VULKAN(), \ ES1_VULKAN_SWIFTSHADER(), ES1_VULKAN().enable(Feature::EnableParallelCompileAndLink) #define ANGLE_ALL_TEST_PLATFORMS_ES2 \ - ANGLE_TEST_PLATFORMS_ES2_SYSTEM_EGL \ ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(), ES2_VULKAN_SWIFTSHADER(), \ - ES2_METAL(), \ + ES2_METAL(), ES2_WEBGPU(), \ ES2_VULKAN() \ .enable(Feature::EnableParallelCompileAndLink) \ .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv), \ @@ -150,7 +139,6 @@ struct CombinedPrintToStringParamName .disable(Feature::SupportsGraphicsPipelineLibrary) #define ANGLE_ALL_TEST_PLATFORMS_ES3 \ - ANGLE_TEST_PLATFORMS_ES3_SYSTEM_EGL \ ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER(), \ ES3_METAL(), \ ES3_VULKAN() \ @@ -159,21 +147,20 @@ struct CombinedPrintToStringParamName ES3_VULKAN_SWIFTSHADER() \ .enable(Feature::EnableParallelCompileAndLink) \ .disable(Feature::SupportsGraphicsPipelineLibrary) \ - .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv) - -#define ANGLE_ALL_TEST_PLATFORMS_ES31 \ - ANGLE_TEST_PLATFORMS_ES31_SYSTEM_EGL \ - ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER(), \ - ES31_VULKAN() \ - .enable(Feature::EnableParallelCompileAndLink) \ - .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv), \ - ES31_VULKAN_SWIFTSHADER() \ - .enable(Feature::EnableParallelCompileAndLink) \ - .disable(Feature::SupportsGraphicsPipelineLibrary) \ + .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv) \ + .enable(Feature::SimulateTileMemoryForTesting) + +#define ANGLE_ALL_TEST_PLATFORMS_ES31 \ + ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER(), \ + ES31_VULKAN() \ + .enable(Feature::EnableParallelCompileAndLink) \ + .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv), \ + ES31_VULKAN_SWIFTSHADER() \ + .enable(Feature::EnableParallelCompileAndLink) \ + .disable(Feature::SupportsGraphicsPipelineLibrary) \ .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv) #define ANGLE_ALL_TEST_PLATFORMS_ES32 \ - ANGLE_TEST_PLATFORMS_ES32_SYSTEM_EGL \ ES32_VULKAN(), ES32_VULKAN() \ .enable(Feature::EnableParallelCompileAndLink) \ .enable(Feature::VaryingsRequireMatchingPrecisionInSpirv) @@ -290,6 +277,13 @@ struct CombinedPrintToStringParamName INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \ testing::PrintToStringParamName()) +#define ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND_ES32(testName, ...) \ + const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, \ + ANGLE_ALL_TEST_PLATFORMS_ES31, \ + ANGLE_ALL_TEST_PLATFORMS_ES32, __VA_ARGS__}; \ + INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \ + testing::PrintToStringParamName()) + // Instantiate the test for a combination of N parameters and the // enumeration of platforms in the extra args, similar to // ANGLE_INSTANTIATE_TEST. The macros are defined only for the Ns diff --git a/src/tests/test_utils/angle_test_platform.cpp b/src/tests/test_utils/angle_test_platform.cpp index df1e5d0ef95..71c34986f82 100644 --- a/src/tests/test_utils/angle_test_platform.cpp +++ b/src/tests/test_utils/angle_test_platform.cpp @@ -74,6 +74,13 @@ bool IsD3D() return IsD3D9() || IsD3D11(); } +bool IsWebGPU() +{ + const char *renderer = reinterpret_cast(glGetString(GL_RENDERER)); + std::string rendererString(renderer); + return (rendererString.find("WebGPU") != std::string::npos); +} + bool IsDebug() { #if !defined(NDEBUG) diff --git a/src/tests/test_utils/angle_test_platform.h b/src/tests/test_utils/angle_test_platform.h index 84312a20375..2eb65eaf845 100644 --- a/src/tests/test_utils/angle_test_platform.h +++ b/src/tests/test_utils/angle_test_platform.h @@ -25,6 +25,7 @@ bool IsNULL(); bool IsVulkan(); bool IsMetal(); bool IsD3D(); +bool IsWebGPU(); // Debug/Release bool IsDebug(); diff --git a/src/tests/test_utils/compiler_test.cpp b/src/tests/test_utils/compiler_test.cpp index 84c771bc033..1fbf9a1f5ac 100644 --- a/src/tests/test_utils/compiler_test.cpp +++ b/src/tests/test_utils/compiler_test.cpp @@ -80,7 +80,7 @@ bool compileTestShader(GLenum type, ShCompileOptions options = compileOptions; options.objectCode = true; - bool compilationSuccess = translator->compile(shaderStrings, 1, options); + bool compilationSuccess = translator->compile(shaderStrings, options); TInfoSink &infoSink = translator->getInfoSink(); if (translatedCode) { @@ -104,7 +104,6 @@ bool compileTestShader(GLenum type, { ShBuiltInResources resources; sh::InitBuiltInResources(&resources); - resources.FragmentPrecisionHigh = 1; return compileTestShader(type, spec, output, shaderString, &resources, compileOptions, translatedCode, infoLog); } @@ -113,7 +112,6 @@ MatchOutputCodeTest::MatchOutputCodeTest(GLenum shaderType, ShShaderOutput outpu : mShaderType(shaderType), mDefaultCompileOptions{} { sh::InitBuiltInResources(&mResources); - mResources.FragmentPrecisionHigh = 1; mOutputCode[outputType] = std::string(); } @@ -143,8 +141,15 @@ void MatchOutputCodeTest::compile(const std::string &shaderString, std::string infoLog; for (auto &code : mOutputCode) { + const ShShaderOutput output = code.first; + ShCompileOptions options = compileOptions; + if (output == SH_SPIRV_VULKAN_OUTPUT || output == SH_MSL_METAL_OUTPUT) + { + options.removeInactiveVariables = true; + } + bool compilationSuccess = - compileWithSettings(code.first, shaderString, compileOptions, &code.second, &infoLog); + compileWithSettings(output, shaderString, options, &code.second, &infoLog); if (!compilationSuccess) { FAIL() << "Shader compilation failed:\n" << infoLog; diff --git a/src/tests/test_utils/runner/TestSuite.cpp b/src/tests/test_utils/runner/TestSuite.cpp index 7c65744e250..25eedf7c5b4 100644 --- a/src/tests/test_utils/runner/TestSuite.cpp +++ b/src/tests/test_utils/runner/TestSuite.cpp @@ -5,6 +5,11 @@ // // TestSuite: // Basic implementation of a test harness in ANGLE. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include "TestSuite.h" @@ -15,6 +20,7 @@ #include "common/system_utils.h" #include "util/Timer.h" +#include #include #include @@ -73,6 +79,47 @@ constexpr double kIdleMessageTimeout = 15.0; constexpr int kDefaultMaxProcesses = 16; constexpr int kDefaultMaxFailures = 100; +#if defined(ANGLE_PLATFORM_ANDROID) +struct sigaction g_originalSigaction[NSIG]; +TestSuite *g_ThisTestSuite = nullptr; + +// This function runs in a compromised context. It should not allocate memory. +void SignalHandler(int sig, siginfo_t *info, void *reserved) +{ + const char crashedMarker[] = "[ CRASHED ]\n"; + + // Output the crash marker. + std::cerr << crashedMarker << std::endl; + if (g_ThisTestSuite != nullptr) + { + g_ThisTestSuite->onCrashOrTimeout(TestResultType::Crash); + } + else + { + std::cerr << "SignalHandler: TestSuite not initialized!" << std::endl; + } + + g_originalSigaction[sig].sa_sigaction(sig, info, reserved); +} + +void InstallExceptionHandlers() +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + + sa.sa_sigaction = SignalHandler; + sa.sa_flags = SA_SIGINFO; + + // The list of signals which are considered to be crashes. + const int exceptionSignals[] = {SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1}; + + for (unsigned int i = 0; exceptionSignals[i] != -1; ++i) + { + sigaction(exceptionSignals[i], &sa, &g_originalSigaction[exceptionSignals[i]]); + } +} +#endif // ANGLE_PLATFORM_ANDROID + const char *ResultTypeToString(TestResultType type) { switch (type) @@ -322,7 +369,12 @@ void UpdateCurrentTestResult(const testing::TestResult &resultIn, TestResults *r } else { - resultOut.type = TestResultType::Pass; + // With --gtest_repeat the same test is seen multiple times, so resultOut.type may have been + // previously set to e.g. ::Fail. Only set to ::Pass if there was no other result yet. + if (resultOut.type == TestResultType::NoResult) + { + resultOut.type = TestResultType::Pass; + } } resultOut.elapsedTimeSeconds.back() = resultsOut->currentTestTimer.getElapsedWallClockTime(); @@ -720,19 +772,28 @@ std::string GetConfigNameFromTestIdentifier(const TestIdentifier &id) TestQueue BatchTests(const std::vector &tests, int batchSize) { - // First sort tests by configuration. - angle::HashMap> testsSortedByConfig; + // First group tests by configuration. + angle::HashMap> testsGroupedByConfig; for (const TestIdentifier &id : tests) { std::string config = GetConfigNameFromTestIdentifier(id); - testsSortedByConfig[config].push_back(id); + testsGroupedByConfig[config].push_back(id); } + // Sort configs for consistent ordering. + std::vector configs; + configs.reserve(testsGroupedByConfig.size()); + for (const auto &configAndIds : testsGroupedByConfig) + { + configs.push_back(configAndIds.first); + } + std::sort(configs.begin(), configs.end()); + // Then group into batches by 'batchSize'. TestQueue testQueue; - for (const auto &configAndIds : testsSortedByConfig) + for (const auto &config : configs) { - const std::vector &configTests = configAndIds.second; + const std::vector &configTests = testsGroupedByConfig[config]; // Count the number of batches needed for this config. int batchesForConfig = static_cast(configTests.size() + batchSize - 1) / batchSize; @@ -1114,6 +1175,10 @@ TestSuite::TestSuite(int *argc, char **argv, std::function registerTests { SetEnvironmentVar(kPreferredDeviceEnvVar, "apple"); } + else if (conditions[GPUTestConfig::kConditionQualcomm]) + { + SetEnvironmentVar(kPreferredDeviceEnvVar, "qualcomm"); + } } // Special handling for TSAN and UBSAN to force crashes when run in automated testing. @@ -1419,6 +1484,11 @@ bool TestSuite::launchChildTestProcess(uint32_t batchId, // Launch child process and wait for completion. processInfo.process = LaunchProcess(args, ProcessOutputCapture::StdoutAndStderrInterleaved); + if (!processInfo.process) + { + std::cerr << "Error creating child process.\n"; + return false; + } if (!processInfo.process->started()) { @@ -1646,6 +1716,11 @@ int TestSuite::run() return EXIT_SUCCESS; } +#if defined(ANGLE_PLATFORM_ANDROID) + g_ThisTestSuite = this; + InstallExceptionHandlers(); +#endif // ANGLE_PLATFORM_ANDROID + if (mGTestListTests) { GTestListTests(mTestResults.results); @@ -1757,7 +1832,7 @@ int TestSuite::run() if (progress) { - messageTimer.start(); + messageTimer.restart(); } else if (messageTimer.getElapsedWallClockTime() > kIdleMessageTimeout) { @@ -1765,7 +1840,7 @@ int TestSuite::run() double processTime = processInfo.process->getElapsedTimeSeconds(); printf("Running %d tests in %d processes, longest for %d seconds.\n", totalTestCount, static_cast(mCurrentProcesses.size()), static_cast(processTime)); - messageTimer.start(); + messageTimer.restart(); } // Early exit if we passed the maximum failure threshold. Still wait for current tests. diff --git a/src/tests/test_utils/runner/TestSuite_unittest.cpp b/src/tests/test_utils/runner/TestSuite_unittest.cpp index d3c5e61f1cf..7070f998f1a 100644 --- a/src/tests/test_utils/runner/TestSuite_unittest.cpp +++ b/src/tests/test_utils/runner/TestSuite_unittest.cpp @@ -6,6 +6,10 @@ // TestSuite_unittest.cpp: Unit tests for ANGLE's test harness. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include "../angle_test_instantiate.h" diff --git a/src/tests/test_utils/runner/android/AngleNativeTest.cpp b/src/tests/test_utils/runner/android/AngleNativeTest.cpp index 3481c7570ca..eba0d454f57 100644 --- a/src/tests/test_utils/runner/android/AngleNativeTest.cpp +++ b/src/tests/test_utils/runner/android/AngleNativeTest.cpp @@ -2,8 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// angle_native_test: +// AngleNativeTest.cpp: // Contains native implementation for com.android.angle.test.AngleNativeTest. +// + +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif #include #include diff --git a/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java b/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java index 7799db010dd..ecdd92f24cb 100644 --- a/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java +++ b/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java @@ -28,7 +28,7 @@ public class AngleNativeTest private static final String TAG = "NativeTest"; private String mCommandLineFilePath; - private StringBuilder mCommandLineFlags = new StringBuilder(); + private final StringBuilder mCommandLineFlags = new StringBuilder(); private TestStatusReporter mReporter; private String mStdoutFilePath; @@ -36,8 +36,8 @@ private static class ReportingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { - private TestStatusReporter mReporter; - private Thread.UncaughtExceptionHandler mWrappedHandler; + private final TestStatusReporter mReporter; + private final Thread.UncaughtExceptionHandler mWrappedHandler; public ReportingUncaughtExceptionHandler( TestStatusReporter reporter, Thread.UncaughtExceptionHandler wrappedHandler) diff --git a/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleUnitTestActivity.java b/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleUnitTestActivity.java index e264324bd5a..78334585698 100644 --- a/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleUnitTestActivity.java +++ b/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleUnitTestActivity.java @@ -17,7 +17,7 @@ public class AngleUnitTestActivity extends NativeActivity { private static final String TAG = "NativeTest"; - private AngleNativeTest mTest = new AngleNativeTest(); + private final AngleNativeTest mTest = new AngleNativeTest(); @Override public void onCreate(Bundle savedInstanceState) diff --git a/src/tests/test_utils/third_party/README.chromium b/src/tests/test_utils/third_party/README.chromium index 0eeeb893064..9af93d8f4e2 100644 --- a/src/tests/test_utils/third_party/README.chromium +++ b/src/tests/test_utils/third_party/README.chromium @@ -1,9 +1,10 @@ -Name: vulkan_command_buffer_utils.h, vulkan_command_buffer_utils.cpp +Name: Vulkan Command Buffer Utils URL: https://github.com/LunarG/VulkanSamples/tree/master/API-Samples/utils Version: N/A Revision: 9cbde4db68a38f8e108560741a97d759f76a9eb3 -License: Apache License, Version 2.0 -License File: http://www.apache.org/licenses/LICENSE-2.0 +Update Mechanism: Manual +License: Apache-2.0 +License File: LICENSE Security Critical: no Shipped: no diff --git a/src/tests/test_utils/third_party/vulkan_command_buffer_utils.cpp b/src/tests/test_utils/third_party/vulkan_command_buffer_utils.cpp index 012b9ae810c..1c279492c86 100644 --- a/src/tests/test_utils/third_party/vulkan_command_buffer_utils.cpp +++ b/src/tests/test_utils/third_party/vulkan_command_buffer_utils.cpp @@ -23,6 +23,10 @@ VULKAN_SAMPLE_DESCRIPTION samples utility functions */ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "vulkan_command_buffer_utils.h" #include diff --git a/src/third_party/ceval/README.chromium b/src/third_party/ceval/README.chromium index 7e7454b9a32..a5253db07f5 100644 --- a/src/third_party/ceval/README.chromium +++ b/src/third_party/ceval/README.chromium @@ -1,7 +1,8 @@ Name: ceval URL: https://github.com/erstan/ceval-single-header -Version: 1ed80ae78ba7bef1744b1ccdffc6c6802eeec8fa +Version: N/A Revision: 1ed80ae78ba7bef1744b1ccdffc6c6802eeec8fa +Update Mechanism: Manual License: MIT License File: LICENSE Security Critical: no diff --git a/src/third_party/libXNVCtrl/README.chromium b/src/third_party/libXNVCtrl/README.chromium index 26e5b3f054c..8c451d2d304 100644 --- a/src/third_party/libXNVCtrl/README.chromium +++ b/src/third_party/libXNVCtrl/README.chromium @@ -4,6 +4,7 @@ URL: http://cgit.freedesktop.org/~aplattner/nvidia-settings/ Revision: ffa5183362ed4ace5b1cfd031a272f72e7d68c1b Version: N/A Date: 2012-05-19 +Update Mechanism: Manual License: MIT License File: LICENSE Security Critical: no diff --git a/src/third_party/volk/README.chromium b/src/third_party/volk/README.chromium index cb29594c660..f44ebfc684c 100644 --- a/src/third_party/volk/README.chromium +++ b/src/third_party/volk/README.chromium @@ -1,7 +1,8 @@ Name: Volk Meta loader for Vulkan API Short Name: volk URL: https://github.com/zeux/volk -Revision: 1ee0b6642ecb947a10f4f988930c02f54cb4b577 +Revision: 9767549a8bba5454555764ee0f3319bc5d205da9 +Update Mechanism: Manual Version: N/A License: MIT License File: LICENSE.md diff --git a/src/third_party/volk/volk.c b/src/third_party/volk/volk.c index efa40773847..64136ad7a60 100644 --- a/src/third_party/volk/volk.c +++ b/src/third_party/volk/volk.c @@ -21,14 +21,26 @@ # include #endif +#include + +#ifdef _WIN32 #ifdef __cplusplus extern "C" { #endif - -#ifdef _WIN32 __declspec(dllimport) HMODULE __stdcall LoadLibraryA(LPCSTR); __declspec(dllimport) FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); __declspec(dllimport) int __stdcall FreeLibrary(HMODULE); +#ifdef __cplusplus +} +#endif +#endif + +#ifdef __cplusplus +#ifdef VOLK_NAMESPACE +namespace volk { +#else +extern "C" { +#endif #endif #if defined(__GNUC__) @@ -81,6 +93,10 @@ VkResult volkInitialize(void) void* module = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); if (!module) module = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL); + // modern versions of macOS don't search /usr/local/lib automatically contrary to what man dlopen says + // Vulkan SDK uses this as the system-wide installation location, so we're going to fallback to this if all else fails + if (!module && getenv("DYLD_FALLBACK_LIBRARY_PATH") == NULL) + module = dlopen("/usr/local/lib/libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); if (!module) module = dlopen("libMoltenVK.dylib", RTLD_NOW | RTLD_LOCAL); // Add support for using Vulkan and MoltenVK in a Framework. App store rules for iOS @@ -89,10 +105,6 @@ VkResult volkInitialize(void) module = dlopen("vulkan.framework/vulkan", RTLD_NOW | RTLD_LOCAL); if (!module) module = dlopen("MoltenVK.framework/MoltenVK", RTLD_NOW | RTLD_LOCAL); - // modern versions of macOS don't search /usr/local/lib automatically contrary to what man dlopen says - // Vulkan SDK uses this as the system-wide installation location, so we're going to fallback to this if all else fails - if (!module && getenv("DYLD_FALLBACK_LIBRARY_PATH") == NULL) - module = dlopen("/usr/local/lib/libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); if (!module) return VK_ERROR_INITIALIZATION_FAILED; @@ -188,6 +200,7 @@ VkDevice volkGetLoadedDevice(void) void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device) { + memset(table, 0, sizeof(*table)); volkGenLoadDeviceTable(table, device, vkGetDeviceProcAddrStub); } @@ -239,6 +252,13 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_VERSION_1_3) vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties)load(context, "vkGetPhysicalDeviceToolProperties"); #endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_ARM_data_graph) + vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM"); + vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) + vkGetPhysicalDeviceExternalTensorPropertiesARM = (PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM)load(context, "vkGetPhysicalDeviceExternalTensorPropertiesARM"); +#endif /* defined(VK_ARM_tensors) */ #if defined(VK_EXT_acquire_drm_display) vkAcquireDrmDisplayEXT = (PFN_vkAcquireDrmDisplayEXT)load(context, "vkAcquireDrmDisplayEXT"); vkGetDrmDisplayEXT = (PFN_vkGetDrmDisplayEXT)load(context, "vkGetDrmDisplayEXT"); @@ -401,6 +421,12 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_NV_cooperative_matrix) vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV"); #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) + vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV"); +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) + vkGetPhysicalDeviceCooperativeVectorPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV"); +#endif /* defined(VK_NV_cooperative_vector) */ #if defined(VK_NV_coverage_reduction_mode) vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = (PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)load(context, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV"); #endif /* defined(VK_NV_coverage_reduction_mode) */ @@ -410,6 +436,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_NV_optical_flow) vkGetPhysicalDeviceOpticalFlowImageFormatsNV = (PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV)load(context, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV"); #endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_OHOS_surface) + vkCreateSurfaceOHOS = (PFN_vkCreateSurfaceOHOS)load(context, "vkCreateSurfaceOHOS"); +#endif /* defined(VK_OHOS_surface) */ #if defined(VK_QNX_screen_surface) vkCreateScreenSurfaceQNX = (PFN_vkCreateScreenSurfaceQNX)load(context, "vkCreateScreenSurfaceQNX"); vkGetPhysicalDeviceScreenPresentationSupportQNX = (PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)load(context, "vkGetPhysicalDeviceScreenPresentationSupportQNX"); @@ -616,6 +645,27 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2"); vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData"); #endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) + vkCmdBindDescriptorSets2 = (PFN_vkCmdBindDescriptorSets2)load(context, "vkCmdBindDescriptorSets2"); + vkCmdBindIndexBuffer2 = (PFN_vkCmdBindIndexBuffer2)load(context, "vkCmdBindIndexBuffer2"); + vkCmdPushConstants2 = (PFN_vkCmdPushConstants2)load(context, "vkCmdPushConstants2"); + vkCmdPushDescriptorSet = (PFN_vkCmdPushDescriptorSet)load(context, "vkCmdPushDescriptorSet"); + vkCmdPushDescriptorSet2 = (PFN_vkCmdPushDescriptorSet2)load(context, "vkCmdPushDescriptorSet2"); + vkCmdPushDescriptorSetWithTemplate = (PFN_vkCmdPushDescriptorSetWithTemplate)load(context, "vkCmdPushDescriptorSetWithTemplate"); + vkCmdPushDescriptorSetWithTemplate2 = (PFN_vkCmdPushDescriptorSetWithTemplate2)load(context, "vkCmdPushDescriptorSetWithTemplate2"); + vkCmdSetLineStipple = (PFN_vkCmdSetLineStipple)load(context, "vkCmdSetLineStipple"); + vkCmdSetRenderingAttachmentLocations = (PFN_vkCmdSetRenderingAttachmentLocations)load(context, "vkCmdSetRenderingAttachmentLocations"); + vkCmdSetRenderingInputAttachmentIndices = (PFN_vkCmdSetRenderingInputAttachmentIndices)load(context, "vkCmdSetRenderingInputAttachmentIndices"); + vkCopyImageToImage = (PFN_vkCopyImageToImage)load(context, "vkCopyImageToImage"); + vkCopyImageToMemory = (PFN_vkCopyImageToMemory)load(context, "vkCopyImageToMemory"); + vkCopyMemoryToImage = (PFN_vkCopyMemoryToImage)load(context, "vkCopyMemoryToImage"); + vkGetDeviceImageSubresourceLayout = (PFN_vkGetDeviceImageSubresourceLayout)load(context, "vkGetDeviceImageSubresourceLayout"); + vkGetImageSubresourceLayout2 = (PFN_vkGetImageSubresourceLayout2)load(context, "vkGetImageSubresourceLayout2"); + vkGetRenderingAreaGranularity = (PFN_vkGetRenderingAreaGranularity)load(context, "vkGetRenderingAreaGranularity"); + vkMapMemory2 = (PFN_vkMapMemory2)load(context, "vkMapMemory2"); + vkTransitionImageLayout = (PFN_vkTransitionImageLayout)load(context, "vkTransitionImageLayout"); + vkUnmapMemory2 = (PFN_vkUnmapMemory2)load(context, "vkUnmapMemory2"); +#endif /* defined(VK_VERSION_1_4) */ #if defined(VK_AMDX_shader_enqueue) vkCmdDispatchGraphAMDX = (PFN_vkCmdDispatchGraphAMDX)load(context, "vkCmdDispatchGraphAMDX"); vkCmdDispatchGraphIndirectAMDX = (PFN_vkCmdDispatchGraphIndirectAMDX)load(context, "vkCmdDispatchGraphIndirectAMDX"); @@ -625,9 +675,15 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetExecutionGraphPipelineNodeIndexAMDX = (PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)load(context, "vkGetExecutionGraphPipelineNodeIndexAMDX"); vkGetExecutionGraphPipelineScratchSizeAMDX = (PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)load(context, "vkGetExecutionGraphPipelineScratchSizeAMDX"); #endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) + vkAntiLagUpdateAMD = (PFN_vkAntiLagUpdateAMD)load(context, "vkAntiLagUpdateAMD"); +#endif /* defined(VK_AMD_anti_lag) */ #if defined(VK_AMD_buffer_marker) vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_AMD_display_native_hdr) vkSetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)load(context, "vkSetLocalDimmingAMD"); #endif /* defined(VK_AMD_display_native_hdr) */ @@ -642,6 +698,31 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)load(context, "vkGetAndroidHardwareBufferPropertiesANDROID"); vkGetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)load(context, "vkGetMemoryAndroidHardwareBufferANDROID"); #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) + vkBindDataGraphPipelineSessionMemoryARM = (PFN_vkBindDataGraphPipelineSessionMemoryARM)load(context, "vkBindDataGraphPipelineSessionMemoryARM"); + vkCmdDispatchDataGraphARM = (PFN_vkCmdDispatchDataGraphARM)load(context, "vkCmdDispatchDataGraphARM"); + vkCreateDataGraphPipelineSessionARM = (PFN_vkCreateDataGraphPipelineSessionARM)load(context, "vkCreateDataGraphPipelineSessionARM"); + vkCreateDataGraphPipelinesARM = (PFN_vkCreateDataGraphPipelinesARM)load(context, "vkCreateDataGraphPipelinesARM"); + vkDestroyDataGraphPipelineSessionARM = (PFN_vkDestroyDataGraphPipelineSessionARM)load(context, "vkDestroyDataGraphPipelineSessionARM"); + vkGetDataGraphPipelineAvailablePropertiesARM = (PFN_vkGetDataGraphPipelineAvailablePropertiesARM)load(context, "vkGetDataGraphPipelineAvailablePropertiesARM"); + vkGetDataGraphPipelinePropertiesARM = (PFN_vkGetDataGraphPipelinePropertiesARM)load(context, "vkGetDataGraphPipelinePropertiesARM"); + vkGetDataGraphPipelineSessionBindPointRequirementsARM = (PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM)load(context, "vkGetDataGraphPipelineSessionBindPointRequirementsARM"); + vkGetDataGraphPipelineSessionMemoryRequirementsARM = (PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM)load(context, "vkGetDataGraphPipelineSessionMemoryRequirementsARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) + vkBindTensorMemoryARM = (PFN_vkBindTensorMemoryARM)load(context, "vkBindTensorMemoryARM"); + vkCmdCopyTensorARM = (PFN_vkCmdCopyTensorARM)load(context, "vkCmdCopyTensorARM"); + vkCreateTensorARM = (PFN_vkCreateTensorARM)load(context, "vkCreateTensorARM"); + vkCreateTensorViewARM = (PFN_vkCreateTensorViewARM)load(context, "vkCreateTensorViewARM"); + vkDestroyTensorARM = (PFN_vkDestroyTensorARM)load(context, "vkDestroyTensorARM"); + vkDestroyTensorViewARM = (PFN_vkDestroyTensorViewARM)load(context, "vkDestroyTensorViewARM"); + vkGetDeviceTensorMemoryRequirementsARM = (PFN_vkGetDeviceTensorMemoryRequirementsARM)load(context, "vkGetDeviceTensorMemoryRequirementsARM"); + vkGetTensorMemoryRequirementsARM = (PFN_vkGetTensorMemoryRequirementsARM)load(context, "vkGetTensorMemoryRequirementsARM"); +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) + vkGetTensorOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorOpaqueCaptureDescriptorDataARM"); + vkGetTensorViewOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorViewOpaqueCaptureDescriptorDataARM"); +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ #if defined(VK_EXT_attachment_feedback_loop_dynamic_state) vkCmdSetAttachmentFeedbackLoopEnableEXT = (PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)load(context, "vkCmdSetAttachmentFeedbackLoopEnableEXT"); #endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ @@ -686,6 +767,17 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_EXT_device_fault) vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); #endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) + vkCmdExecuteGeneratedCommandsEXT = (PFN_vkCmdExecuteGeneratedCommandsEXT)load(context, "vkCmdExecuteGeneratedCommandsEXT"); + vkCmdPreprocessGeneratedCommandsEXT = (PFN_vkCmdPreprocessGeneratedCommandsEXT)load(context, "vkCmdPreprocessGeneratedCommandsEXT"); + vkCreateIndirectCommandsLayoutEXT = (PFN_vkCreateIndirectCommandsLayoutEXT)load(context, "vkCreateIndirectCommandsLayoutEXT"); + vkCreateIndirectExecutionSetEXT = (PFN_vkCreateIndirectExecutionSetEXT)load(context, "vkCreateIndirectExecutionSetEXT"); + vkDestroyIndirectCommandsLayoutEXT = (PFN_vkDestroyIndirectCommandsLayoutEXT)load(context, "vkDestroyIndirectCommandsLayoutEXT"); + vkDestroyIndirectExecutionSetEXT = (PFN_vkDestroyIndirectExecutionSetEXT)load(context, "vkDestroyIndirectExecutionSetEXT"); + vkGetGeneratedCommandsMemoryRequirementsEXT = (PFN_vkGetGeneratedCommandsMemoryRequirementsEXT)load(context, "vkGetGeneratedCommandsMemoryRequirementsEXT"); + vkUpdateIndirectExecutionSetPipelineEXT = (PFN_vkUpdateIndirectExecutionSetPipelineEXT)load(context, "vkUpdateIndirectExecutionSetPipelineEXT"); + vkUpdateIndirectExecutionSetShaderEXT = (PFN_vkUpdateIndirectExecutionSetShaderEXT)load(context, "vkUpdateIndirectExecutionSetShaderEXT"); +#endif /* defined(VK_EXT_device_generated_commands) */ #if defined(VK_EXT_discard_rectangles) vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ @@ -702,10 +794,20 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_EXT_external_memory_host) vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); #endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) + vkGetMemoryMetalHandleEXT = (PFN_vkGetMemoryMetalHandleEXT)load(context, "vkGetMemoryMetalHandleEXT"); + vkGetMemoryMetalHandlePropertiesEXT = (PFN_vkGetMemoryMetalHandlePropertiesEXT)load(context, "vkGetMemoryMetalHandlePropertiesEXT"); +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) + vkCmdEndRendering2EXT = (PFN_vkCmdEndRendering2EXT)load(context, "vkCmdEndRendering2EXT"); +#endif /* defined(VK_EXT_fragment_density_map_offset) */ #if defined(VK_EXT_full_screen_exclusive) vkAcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)load(context, "vkAcquireFullScreenExclusiveModeEXT"); vkReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)load(context, "vkReleaseFullScreenExclusiveModeEXT"); #endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) + vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ #if defined(VK_EXT_hdr_metadata) vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); #endif /* defined(VK_EXT_hdr_metadata) */ @@ -726,9 +828,11 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_mesh_shader) vkCmdDrawMeshTasksEXT = (PFN_vkCmdDrawMeshTasksEXT)load(context, "vkCmdDrawMeshTasksEXT"); - vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); vkCmdDrawMeshTasksIndirectEXT = (PFN_vkCmdDrawMeshTasksIndirectEXT)load(context, "vkCmdDrawMeshTasksIndirectEXT"); #endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_EXT_metal_objects) vkExportMetalObjectsEXT = (PFN_vkExportMetalObjectsEXT)load(context, "vkExportMetalObjectsEXT"); #endif /* defined(VK_EXT_metal_objects) */ @@ -820,9 +924,11 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_HUAWEI_invocation_mask) vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); #endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 + vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ #if defined(VK_HUAWEI_subpass_shading) vkCmdSubpassShadingHUAWEI = (PFN_vkCmdSubpassShadingHUAWEI)load(context, "vkCmdSubpassShadingHUAWEI"); - vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); #endif /* defined(VK_HUAWEI_subpass_shading) */ #if defined(VK_INTEL_performance_query) vkAcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)load(context, "vkAcquirePerformanceConfigurationINTEL"); @@ -873,6 +979,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdCopyImageToBuffer2KHR = (PFN_vkCmdCopyImageToBuffer2KHR)load(context, "vkCmdCopyImageToBuffer2KHR"); vkCmdResolveImage2KHR = (PFN_vkCmdResolveImage2KHR)load(context, "vkCmdResolveImage2KHR"); #endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) + vkCmdCopyMemoryIndirectKHR = (PFN_vkCmdCopyMemoryIndirectKHR)load(context, "vkCmdCopyMemoryIndirectKHR"); + vkCmdCopyMemoryToImageIndirectKHR = (PFN_vkCmdCopyMemoryToImageIndirectKHR)load(context, "vkCmdCopyMemoryToImageIndirectKHR"); +#endif /* defined(VK_KHR_copy_memory_indirect) */ #if defined(VK_KHR_create_renderpass2) vkCmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)load(context, "vkCmdBeginRenderPass2KHR"); vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)load(context, "vkCmdEndRenderPass2KHR"); @@ -983,6 +1093,13 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); #endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) + vkCreatePipelineBinariesKHR = (PFN_vkCreatePipelineBinariesKHR)load(context, "vkCreatePipelineBinariesKHR"); + vkDestroyPipelineBinaryKHR = (PFN_vkDestroyPipelineBinaryKHR)load(context, "vkDestroyPipelineBinaryKHR"); + vkGetPipelineBinaryDataKHR = (PFN_vkGetPipelineBinaryDataKHR)load(context, "vkGetPipelineBinaryDataKHR"); + vkGetPipelineKeyKHR = (PFN_vkGetPipelineKeyKHR)load(context, "vkGetPipelineKeyKHR"); + vkReleaseCapturedPipelineDataKHR = (PFN_vkReleaseCapturedPipelineDataKHR)load(context, "vkReleaseCapturedPipelineDataKHR"); +#endif /* defined(VK_KHR_pipeline_binary) */ #if defined(VK_KHR_pipeline_executable_properties) vkGetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)load(context, "vkGetPipelineExecutableInternalRepresentationsKHR"); vkGetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)load(context, "vkGetPipelineExecutablePropertiesKHR"); @@ -991,6 +1108,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_KHR_present_wait) vkWaitForPresentKHR = (PFN_vkWaitForPresentKHR)load(context, "vkWaitForPresentKHR"); #endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) + vkWaitForPresent2KHR = (PFN_vkWaitForPresent2KHR)load(context, "vkWaitForPresent2KHR"); +#endif /* defined(VK_KHR_present_wait2) */ #if defined(VK_KHR_push_descriptor) vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); #endif /* defined(VK_KHR_push_descriptor) */ @@ -1020,6 +1140,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)load(context, "vkGetSwapchainImagesKHR"); vkQueuePresentKHR = (PFN_vkQueuePresentKHR)load(context, "vkQueuePresentKHR"); #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) + vkReleaseSwapchainImagesKHR = (PFN_vkReleaseSwapchainImagesKHR)load(context, "vkReleaseSwapchainImagesKHR"); +#endif /* defined(VK_KHR_swapchain_maintenance1) */ #if defined(VK_KHR_synchronization2) vkCmdPipelineBarrier2KHR = (PFN_vkCmdPipelineBarrier2KHR)load(context, "vkCmdPipelineBarrier2KHR"); vkCmdResetEvent2KHR = (PFN_vkCmdResetEvent2KHR)load(context, "vkCmdResetEvent2KHR"); @@ -1028,12 +1151,6 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdWriteTimestamp2KHR = (PFN_vkCmdWriteTimestamp2KHR)load(context, "vkCmdWriteTimestamp2KHR"); vkQueueSubmit2KHR = (PFN_vkQueueSubmit2KHR)load(context, "vkQueueSubmit2KHR"); #endif /* defined(VK_KHR_synchronization2) */ -#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) - vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); -#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ -#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) - vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); -#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ #if defined(VK_KHR_timeline_semaphore) vkGetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)load(context, "vkGetSemaphoreCounterValueKHR"); vkSignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)load(context, "vkSignalSemaphoreKHR"); @@ -1066,12 +1183,25 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkDestroyCuModuleNVX = (PFN_vkDestroyCuModuleNVX)load(context, "vkDestroyCuModuleNVX"); #endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) - vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); vkGetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)load(context, "vkGetImageViewHandleNVX"); #endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 + vkGetImageViewHandle64NVX = (PFN_vkGetImageViewHandle64NVX)load(context, "vkGetImageViewHandle64NVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 + vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ #if defined(VK_NV_clip_space_w_scaling) vkCmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)load(context, "vkCmdSetViewportWScalingNV"); #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) + vkCmdBuildClusterAccelerationStructureIndirectNV = (PFN_vkCmdBuildClusterAccelerationStructureIndirectNV)load(context, "vkCmdBuildClusterAccelerationStructureIndirectNV"); + vkGetClusterAccelerationStructureBuildSizesNV = (PFN_vkGetClusterAccelerationStructureBuildSizesNV)load(context, "vkGetClusterAccelerationStructureBuildSizesNV"); +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_cooperative_vector) + vkCmdConvertCooperativeVectorMatrixNV = (PFN_vkCmdConvertCooperativeVectorMatrixNV)load(context, "vkCmdConvertCooperativeVectorMatrixNV"); + vkConvertCooperativeVectorMatrixNV = (PFN_vkConvertCooperativeVectorMatrixNV)load(context, "vkConvertCooperativeVectorMatrixNV"); +#endif /* defined(VK_NV_cooperative_vector) */ #if defined(VK_NV_copy_memory_indirect) vkCmdCopyMemoryIndirectNV = (PFN_vkCmdCopyMemoryIndirectNV)load(context, "vkCmdCopyMemoryIndirectNV"); vkCmdCopyMemoryToImageIndirectNV = (PFN_vkCmdCopyMemoryToImageIndirectNV)load(context, "vkCmdCopyMemoryToImageIndirectNV"); @@ -1088,6 +1218,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_NV_device_generated_commands) vkCmdBindPipelineShaderGroupNV = (PFN_vkCmdBindPipelineShaderGroupNV)load(context, "vkCmdBindPipelineShaderGroupNV"); vkCmdExecuteGeneratedCommandsNV = (PFN_vkCmdExecuteGeneratedCommandsNV)load(context, "vkCmdExecuteGeneratedCommandsNV"); @@ -1101,6 +1234,11 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetPipelineIndirectDeviceAddressNV = (PFN_vkGetPipelineIndirectDeviceAddressNV)load(context, "vkGetPipelineIndirectDeviceAddressNV"); vkGetPipelineIndirectMemoryRequirementsNV = (PFN_vkGetPipelineIndirectMemoryRequirementsNV)load(context, "vkGetPipelineIndirectMemoryRequirementsNV"); #endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) + vkCreateExternalComputeQueueNV = (PFN_vkCreateExternalComputeQueueNV)load(context, "vkCreateExternalComputeQueueNV"); + vkDestroyExternalComputeQueueNV = (PFN_vkDestroyExternalComputeQueueNV)load(context, "vkDestroyExternalComputeQueueNV"); + vkGetExternalComputeQueueDataNV = (PFN_vkGetExternalComputeQueueDataNV)load(context, "vkGetExternalComputeQueueDataNV"); +#endif /* defined(VK_NV_external_compute_queue) */ #if defined(VK_NV_external_memory_rdma) vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); #endif /* defined(VK_NV_external_memory_rdma) */ @@ -1122,16 +1260,22 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); #endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) - vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); vkCmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)load(context, "vkCmdDrawMeshTasksNV"); #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_NV_optical_flow) vkBindOpticalFlowSessionImageNV = (PFN_vkBindOpticalFlowSessionImageNV)load(context, "vkBindOpticalFlowSessionImageNV"); vkCmdOpticalFlowExecuteNV = (PFN_vkCmdOpticalFlowExecuteNV)load(context, "vkCmdOpticalFlowExecuteNV"); vkCreateOpticalFlowSessionNV = (PFN_vkCreateOpticalFlowSessionNV)load(context, "vkCreateOpticalFlowSessionNV"); vkDestroyOpticalFlowSessionNV = (PFN_vkDestroyOpticalFlowSessionNV)load(context, "vkDestroyOpticalFlowSessionNV"); #endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) + vkCmdBuildPartitionedAccelerationStructuresNV = (PFN_vkCmdBuildPartitionedAccelerationStructuresNV)load(context, "vkCmdBuildPartitionedAccelerationStructuresNV"); + vkGetPartitionedAccelerationStructuresBuildSizesNV = (PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV)load(context, "vkGetPartitionedAccelerationStructuresBuildSizesNV"); +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ #if defined(VK_NV_ray_tracing) vkBindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)load(context, "vkBindAccelerationStructureMemoryNV"); vkCmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)load(context, "vkCmdBuildAccelerationStructureNV"); @@ -1157,10 +1301,18 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)load(context, "vkCmdSetCoarseSampleOrderNV"); vkCmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)load(context, "vkCmdSetViewportShadingRatePaletteNV"); #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_memory_heap) + vkCmdBindTileMemoryQCOM = (PFN_vkCmdBindTileMemoryQCOM)load(context, "vkCmdBindTileMemoryQCOM"); +#endif /* defined(VK_QCOM_tile_memory_heap) */ #if defined(VK_QCOM_tile_properties) vkGetDynamicRenderingTilePropertiesQCOM = (PFN_vkGetDynamicRenderingTilePropertiesQCOM)load(context, "vkGetDynamicRenderingTilePropertiesQCOM"); vkGetFramebufferTilePropertiesQCOM = (PFN_vkGetFramebufferTilePropertiesQCOM)load(context, "vkGetFramebufferTilePropertiesQCOM"); #endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) + vkCmdBeginPerTileExecutionQCOM = (PFN_vkCmdBeginPerTileExecutionQCOM)load(context, "vkCmdBeginPerTileExecutionQCOM"); + vkCmdDispatchTileQCOM = (PFN_vkCmdDispatchTileQCOM)load(context, "vkCmdDispatchTileQCOM"); + vkCmdEndPerTileExecutionQCOM = (PFN_vkCmdEndPerTileExecutionQCOM)load(context, "vkCmdEndPerTileExecutionQCOM"); +#endif /* defined(VK_QCOM_tile_shading) */ #if defined(VK_QNX_external_memory_screen_buffer) vkGetScreenBufferPropertiesQNX = (PFN_vkGetScreenBufferPropertiesQNX)load(context, "vkGetScreenBufferPropertiesQNX"); #endif /* defined(VK_QNX_external_memory_screen_buffer) */ @@ -1168,6 +1320,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) + vkCmdSetDepthClampRangeEXT = (PFN_vkCmdSetDepthClampRangeEXT)load(context, "vkCmdSetDepthClampRangeEXT"); +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ #if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); @@ -1254,18 +1409,15 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ -#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) - vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); -#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ #if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) vkGetImageSubresourceLayout2EXT = (PFN_vkGetImageSubresourceLayout2EXT)load(context, "vkGetImageSubresourceLayout2EXT"); #endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ #if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); #endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); -#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)load(context, "vkGetDeviceGroupPresentCapabilitiesKHR"); vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)load(context, "vkGetDeviceGroupSurfacePresentModesKHR"); @@ -1472,6 +1624,27 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2"); table->vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData"); #endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) + table->vkCmdBindDescriptorSets2 = (PFN_vkCmdBindDescriptorSets2)load(context, "vkCmdBindDescriptorSets2"); + table->vkCmdBindIndexBuffer2 = (PFN_vkCmdBindIndexBuffer2)load(context, "vkCmdBindIndexBuffer2"); + table->vkCmdPushConstants2 = (PFN_vkCmdPushConstants2)load(context, "vkCmdPushConstants2"); + table->vkCmdPushDescriptorSet = (PFN_vkCmdPushDescriptorSet)load(context, "vkCmdPushDescriptorSet"); + table->vkCmdPushDescriptorSet2 = (PFN_vkCmdPushDescriptorSet2)load(context, "vkCmdPushDescriptorSet2"); + table->vkCmdPushDescriptorSetWithTemplate = (PFN_vkCmdPushDescriptorSetWithTemplate)load(context, "vkCmdPushDescriptorSetWithTemplate"); + table->vkCmdPushDescriptorSetWithTemplate2 = (PFN_vkCmdPushDescriptorSetWithTemplate2)load(context, "vkCmdPushDescriptorSetWithTemplate2"); + table->vkCmdSetLineStipple = (PFN_vkCmdSetLineStipple)load(context, "vkCmdSetLineStipple"); + table->vkCmdSetRenderingAttachmentLocations = (PFN_vkCmdSetRenderingAttachmentLocations)load(context, "vkCmdSetRenderingAttachmentLocations"); + table->vkCmdSetRenderingInputAttachmentIndices = (PFN_vkCmdSetRenderingInputAttachmentIndices)load(context, "vkCmdSetRenderingInputAttachmentIndices"); + table->vkCopyImageToImage = (PFN_vkCopyImageToImage)load(context, "vkCopyImageToImage"); + table->vkCopyImageToMemory = (PFN_vkCopyImageToMemory)load(context, "vkCopyImageToMemory"); + table->vkCopyMemoryToImage = (PFN_vkCopyMemoryToImage)load(context, "vkCopyMemoryToImage"); + table->vkGetDeviceImageSubresourceLayout = (PFN_vkGetDeviceImageSubresourceLayout)load(context, "vkGetDeviceImageSubresourceLayout"); + table->vkGetImageSubresourceLayout2 = (PFN_vkGetImageSubresourceLayout2)load(context, "vkGetImageSubresourceLayout2"); + table->vkGetRenderingAreaGranularity = (PFN_vkGetRenderingAreaGranularity)load(context, "vkGetRenderingAreaGranularity"); + table->vkMapMemory2 = (PFN_vkMapMemory2)load(context, "vkMapMemory2"); + table->vkTransitionImageLayout = (PFN_vkTransitionImageLayout)load(context, "vkTransitionImageLayout"); + table->vkUnmapMemory2 = (PFN_vkUnmapMemory2)load(context, "vkUnmapMemory2"); +#endif /* defined(VK_VERSION_1_4) */ #if defined(VK_AMDX_shader_enqueue) table->vkCmdDispatchGraphAMDX = (PFN_vkCmdDispatchGraphAMDX)load(context, "vkCmdDispatchGraphAMDX"); table->vkCmdDispatchGraphIndirectAMDX = (PFN_vkCmdDispatchGraphIndirectAMDX)load(context, "vkCmdDispatchGraphIndirectAMDX"); @@ -1481,9 +1654,15 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetExecutionGraphPipelineNodeIndexAMDX = (PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)load(context, "vkGetExecutionGraphPipelineNodeIndexAMDX"); table->vkGetExecutionGraphPipelineScratchSizeAMDX = (PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)load(context, "vkGetExecutionGraphPipelineScratchSizeAMDX"); #endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) + table->vkAntiLagUpdateAMD = (PFN_vkAntiLagUpdateAMD)load(context, "vkAntiLagUpdateAMD"); +#endif /* defined(VK_AMD_anti_lag) */ #if defined(VK_AMD_buffer_marker) table->vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + table->vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_AMD_display_native_hdr) table->vkSetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)load(context, "vkSetLocalDimmingAMD"); #endif /* defined(VK_AMD_display_native_hdr) */ @@ -1498,6 +1677,31 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)load(context, "vkGetAndroidHardwareBufferPropertiesANDROID"); table->vkGetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)load(context, "vkGetMemoryAndroidHardwareBufferANDROID"); #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) + table->vkBindDataGraphPipelineSessionMemoryARM = (PFN_vkBindDataGraphPipelineSessionMemoryARM)load(context, "vkBindDataGraphPipelineSessionMemoryARM"); + table->vkCmdDispatchDataGraphARM = (PFN_vkCmdDispatchDataGraphARM)load(context, "vkCmdDispatchDataGraphARM"); + table->vkCreateDataGraphPipelineSessionARM = (PFN_vkCreateDataGraphPipelineSessionARM)load(context, "vkCreateDataGraphPipelineSessionARM"); + table->vkCreateDataGraphPipelinesARM = (PFN_vkCreateDataGraphPipelinesARM)load(context, "vkCreateDataGraphPipelinesARM"); + table->vkDestroyDataGraphPipelineSessionARM = (PFN_vkDestroyDataGraphPipelineSessionARM)load(context, "vkDestroyDataGraphPipelineSessionARM"); + table->vkGetDataGraphPipelineAvailablePropertiesARM = (PFN_vkGetDataGraphPipelineAvailablePropertiesARM)load(context, "vkGetDataGraphPipelineAvailablePropertiesARM"); + table->vkGetDataGraphPipelinePropertiesARM = (PFN_vkGetDataGraphPipelinePropertiesARM)load(context, "vkGetDataGraphPipelinePropertiesARM"); + table->vkGetDataGraphPipelineSessionBindPointRequirementsARM = (PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM)load(context, "vkGetDataGraphPipelineSessionBindPointRequirementsARM"); + table->vkGetDataGraphPipelineSessionMemoryRequirementsARM = (PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM)load(context, "vkGetDataGraphPipelineSessionMemoryRequirementsARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) + table->vkBindTensorMemoryARM = (PFN_vkBindTensorMemoryARM)load(context, "vkBindTensorMemoryARM"); + table->vkCmdCopyTensorARM = (PFN_vkCmdCopyTensorARM)load(context, "vkCmdCopyTensorARM"); + table->vkCreateTensorARM = (PFN_vkCreateTensorARM)load(context, "vkCreateTensorARM"); + table->vkCreateTensorViewARM = (PFN_vkCreateTensorViewARM)load(context, "vkCreateTensorViewARM"); + table->vkDestroyTensorARM = (PFN_vkDestroyTensorARM)load(context, "vkDestroyTensorARM"); + table->vkDestroyTensorViewARM = (PFN_vkDestroyTensorViewARM)load(context, "vkDestroyTensorViewARM"); + table->vkGetDeviceTensorMemoryRequirementsARM = (PFN_vkGetDeviceTensorMemoryRequirementsARM)load(context, "vkGetDeviceTensorMemoryRequirementsARM"); + table->vkGetTensorMemoryRequirementsARM = (PFN_vkGetTensorMemoryRequirementsARM)load(context, "vkGetTensorMemoryRequirementsARM"); +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) + table->vkGetTensorOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorOpaqueCaptureDescriptorDataARM"); + table->vkGetTensorViewOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorViewOpaqueCaptureDescriptorDataARM"); +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ #if defined(VK_EXT_attachment_feedback_loop_dynamic_state) table->vkCmdSetAttachmentFeedbackLoopEnableEXT = (PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)load(context, "vkCmdSetAttachmentFeedbackLoopEnableEXT"); #endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ @@ -1542,6 +1746,17 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_EXT_device_fault) table->vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); #endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) + table->vkCmdExecuteGeneratedCommandsEXT = (PFN_vkCmdExecuteGeneratedCommandsEXT)load(context, "vkCmdExecuteGeneratedCommandsEXT"); + table->vkCmdPreprocessGeneratedCommandsEXT = (PFN_vkCmdPreprocessGeneratedCommandsEXT)load(context, "vkCmdPreprocessGeneratedCommandsEXT"); + table->vkCreateIndirectCommandsLayoutEXT = (PFN_vkCreateIndirectCommandsLayoutEXT)load(context, "vkCreateIndirectCommandsLayoutEXT"); + table->vkCreateIndirectExecutionSetEXT = (PFN_vkCreateIndirectExecutionSetEXT)load(context, "vkCreateIndirectExecutionSetEXT"); + table->vkDestroyIndirectCommandsLayoutEXT = (PFN_vkDestroyIndirectCommandsLayoutEXT)load(context, "vkDestroyIndirectCommandsLayoutEXT"); + table->vkDestroyIndirectExecutionSetEXT = (PFN_vkDestroyIndirectExecutionSetEXT)load(context, "vkDestroyIndirectExecutionSetEXT"); + table->vkGetGeneratedCommandsMemoryRequirementsEXT = (PFN_vkGetGeneratedCommandsMemoryRequirementsEXT)load(context, "vkGetGeneratedCommandsMemoryRequirementsEXT"); + table->vkUpdateIndirectExecutionSetPipelineEXT = (PFN_vkUpdateIndirectExecutionSetPipelineEXT)load(context, "vkUpdateIndirectExecutionSetPipelineEXT"); + table->vkUpdateIndirectExecutionSetShaderEXT = (PFN_vkUpdateIndirectExecutionSetShaderEXT)load(context, "vkUpdateIndirectExecutionSetShaderEXT"); +#endif /* defined(VK_EXT_device_generated_commands) */ #if defined(VK_EXT_discard_rectangles) table->vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ @@ -1558,10 +1773,20 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_EXT_external_memory_host) table->vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); #endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) + table->vkGetMemoryMetalHandleEXT = (PFN_vkGetMemoryMetalHandleEXT)load(context, "vkGetMemoryMetalHandleEXT"); + table->vkGetMemoryMetalHandlePropertiesEXT = (PFN_vkGetMemoryMetalHandlePropertiesEXT)load(context, "vkGetMemoryMetalHandlePropertiesEXT"); +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) + table->vkCmdEndRendering2EXT = (PFN_vkCmdEndRendering2EXT)load(context, "vkCmdEndRendering2EXT"); +#endif /* defined(VK_EXT_fragment_density_map_offset) */ #if defined(VK_EXT_full_screen_exclusive) table->vkAcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)load(context, "vkAcquireFullScreenExclusiveModeEXT"); table->vkReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)load(context, "vkReleaseFullScreenExclusiveModeEXT"); #endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) + table->vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ #if defined(VK_EXT_hdr_metadata) table->vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); #endif /* defined(VK_EXT_hdr_metadata) */ @@ -1582,9 +1807,11 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_mesh_shader) table->vkCmdDrawMeshTasksEXT = (PFN_vkCmdDrawMeshTasksEXT)load(context, "vkCmdDrawMeshTasksEXT"); - table->vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); table->vkCmdDrawMeshTasksIndirectEXT = (PFN_vkCmdDrawMeshTasksIndirectEXT)load(context, "vkCmdDrawMeshTasksIndirectEXT"); #endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + table->vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_EXT_metal_objects) table->vkExportMetalObjectsEXT = (PFN_vkExportMetalObjectsEXT)load(context, "vkExportMetalObjectsEXT"); #endif /* defined(VK_EXT_metal_objects) */ @@ -1676,9 +1903,11 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_HUAWEI_invocation_mask) table->vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); #endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 + table->vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ #if defined(VK_HUAWEI_subpass_shading) table->vkCmdSubpassShadingHUAWEI = (PFN_vkCmdSubpassShadingHUAWEI)load(context, "vkCmdSubpassShadingHUAWEI"); - table->vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); #endif /* defined(VK_HUAWEI_subpass_shading) */ #if defined(VK_INTEL_performance_query) table->vkAcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)load(context, "vkAcquirePerformanceConfigurationINTEL"); @@ -1729,6 +1958,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdCopyImageToBuffer2KHR = (PFN_vkCmdCopyImageToBuffer2KHR)load(context, "vkCmdCopyImageToBuffer2KHR"); table->vkCmdResolveImage2KHR = (PFN_vkCmdResolveImage2KHR)load(context, "vkCmdResolveImage2KHR"); #endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) + table->vkCmdCopyMemoryIndirectKHR = (PFN_vkCmdCopyMemoryIndirectKHR)load(context, "vkCmdCopyMemoryIndirectKHR"); + table->vkCmdCopyMemoryToImageIndirectKHR = (PFN_vkCmdCopyMemoryToImageIndirectKHR)load(context, "vkCmdCopyMemoryToImageIndirectKHR"); +#endif /* defined(VK_KHR_copy_memory_indirect) */ #if defined(VK_KHR_create_renderpass2) table->vkCmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)load(context, "vkCmdBeginRenderPass2KHR"); table->vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)load(context, "vkCmdEndRenderPass2KHR"); @@ -1839,6 +2072,13 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); table->vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); #endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) + table->vkCreatePipelineBinariesKHR = (PFN_vkCreatePipelineBinariesKHR)load(context, "vkCreatePipelineBinariesKHR"); + table->vkDestroyPipelineBinaryKHR = (PFN_vkDestroyPipelineBinaryKHR)load(context, "vkDestroyPipelineBinaryKHR"); + table->vkGetPipelineBinaryDataKHR = (PFN_vkGetPipelineBinaryDataKHR)load(context, "vkGetPipelineBinaryDataKHR"); + table->vkGetPipelineKeyKHR = (PFN_vkGetPipelineKeyKHR)load(context, "vkGetPipelineKeyKHR"); + table->vkReleaseCapturedPipelineDataKHR = (PFN_vkReleaseCapturedPipelineDataKHR)load(context, "vkReleaseCapturedPipelineDataKHR"); +#endif /* defined(VK_KHR_pipeline_binary) */ #if defined(VK_KHR_pipeline_executable_properties) table->vkGetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)load(context, "vkGetPipelineExecutableInternalRepresentationsKHR"); table->vkGetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)load(context, "vkGetPipelineExecutablePropertiesKHR"); @@ -1847,6 +2087,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_KHR_present_wait) table->vkWaitForPresentKHR = (PFN_vkWaitForPresentKHR)load(context, "vkWaitForPresentKHR"); #endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) + table->vkWaitForPresent2KHR = (PFN_vkWaitForPresent2KHR)load(context, "vkWaitForPresent2KHR"); +#endif /* defined(VK_KHR_present_wait2) */ #if defined(VK_KHR_push_descriptor) table->vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); #endif /* defined(VK_KHR_push_descriptor) */ @@ -1876,6 +2119,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)load(context, "vkGetSwapchainImagesKHR"); table->vkQueuePresentKHR = (PFN_vkQueuePresentKHR)load(context, "vkQueuePresentKHR"); #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) + table->vkReleaseSwapchainImagesKHR = (PFN_vkReleaseSwapchainImagesKHR)load(context, "vkReleaseSwapchainImagesKHR"); +#endif /* defined(VK_KHR_swapchain_maintenance1) */ #if defined(VK_KHR_synchronization2) table->vkCmdPipelineBarrier2KHR = (PFN_vkCmdPipelineBarrier2KHR)load(context, "vkCmdPipelineBarrier2KHR"); table->vkCmdResetEvent2KHR = (PFN_vkCmdResetEvent2KHR)load(context, "vkCmdResetEvent2KHR"); @@ -1884,12 +2130,6 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdWriteTimestamp2KHR = (PFN_vkCmdWriteTimestamp2KHR)load(context, "vkCmdWriteTimestamp2KHR"); table->vkQueueSubmit2KHR = (PFN_vkQueueSubmit2KHR)load(context, "vkQueueSubmit2KHR"); #endif /* defined(VK_KHR_synchronization2) */ -#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) - table->vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); -#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ -#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) - table->vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); -#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ #if defined(VK_KHR_timeline_semaphore) table->vkGetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)load(context, "vkGetSemaphoreCounterValueKHR"); table->vkSignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)load(context, "vkSignalSemaphoreKHR"); @@ -1922,12 +2162,25 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkDestroyCuModuleNVX = (PFN_vkDestroyCuModuleNVX)load(context, "vkDestroyCuModuleNVX"); #endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) - table->vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); table->vkGetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)load(context, "vkGetImageViewHandleNVX"); #endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 + table->vkGetImageViewHandle64NVX = (PFN_vkGetImageViewHandle64NVX)load(context, "vkGetImageViewHandle64NVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 + table->vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ #if defined(VK_NV_clip_space_w_scaling) table->vkCmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)load(context, "vkCmdSetViewportWScalingNV"); #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) + table->vkCmdBuildClusterAccelerationStructureIndirectNV = (PFN_vkCmdBuildClusterAccelerationStructureIndirectNV)load(context, "vkCmdBuildClusterAccelerationStructureIndirectNV"); + table->vkGetClusterAccelerationStructureBuildSizesNV = (PFN_vkGetClusterAccelerationStructureBuildSizesNV)load(context, "vkGetClusterAccelerationStructureBuildSizesNV"); +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_cooperative_vector) + table->vkCmdConvertCooperativeVectorMatrixNV = (PFN_vkCmdConvertCooperativeVectorMatrixNV)load(context, "vkCmdConvertCooperativeVectorMatrixNV"); + table->vkConvertCooperativeVectorMatrixNV = (PFN_vkConvertCooperativeVectorMatrixNV)load(context, "vkConvertCooperativeVectorMatrixNV"); +#endif /* defined(VK_NV_cooperative_vector) */ #if defined(VK_NV_copy_memory_indirect) table->vkCmdCopyMemoryIndirectNV = (PFN_vkCmdCopyMemoryIndirectNV)load(context, "vkCmdCopyMemoryIndirectNV"); table->vkCmdCopyMemoryToImageIndirectNV = (PFN_vkCmdCopyMemoryToImageIndirectNV)load(context, "vkCmdCopyMemoryToImageIndirectNV"); @@ -1944,6 +2197,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); table->vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + table->vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_NV_device_generated_commands) table->vkCmdBindPipelineShaderGroupNV = (PFN_vkCmdBindPipelineShaderGroupNV)load(context, "vkCmdBindPipelineShaderGroupNV"); table->vkCmdExecuteGeneratedCommandsNV = (PFN_vkCmdExecuteGeneratedCommandsNV)load(context, "vkCmdExecuteGeneratedCommandsNV"); @@ -1957,6 +2213,11 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetPipelineIndirectDeviceAddressNV = (PFN_vkGetPipelineIndirectDeviceAddressNV)load(context, "vkGetPipelineIndirectDeviceAddressNV"); table->vkGetPipelineIndirectMemoryRequirementsNV = (PFN_vkGetPipelineIndirectMemoryRequirementsNV)load(context, "vkGetPipelineIndirectMemoryRequirementsNV"); #endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) + table->vkCreateExternalComputeQueueNV = (PFN_vkCreateExternalComputeQueueNV)load(context, "vkCreateExternalComputeQueueNV"); + table->vkDestroyExternalComputeQueueNV = (PFN_vkDestroyExternalComputeQueueNV)load(context, "vkDestroyExternalComputeQueueNV"); + table->vkGetExternalComputeQueueDataNV = (PFN_vkGetExternalComputeQueueDataNV)load(context, "vkGetExternalComputeQueueDataNV"); +#endif /* defined(VK_NV_external_compute_queue) */ #if defined(VK_NV_external_memory_rdma) table->vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); #endif /* defined(VK_NV_external_memory_rdma) */ @@ -1978,16 +2239,22 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); #endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) - table->vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); table->vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); table->vkCmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)load(context, "vkCmdDrawMeshTasksNV"); #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + table->vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_NV_optical_flow) table->vkBindOpticalFlowSessionImageNV = (PFN_vkBindOpticalFlowSessionImageNV)load(context, "vkBindOpticalFlowSessionImageNV"); table->vkCmdOpticalFlowExecuteNV = (PFN_vkCmdOpticalFlowExecuteNV)load(context, "vkCmdOpticalFlowExecuteNV"); table->vkCreateOpticalFlowSessionNV = (PFN_vkCreateOpticalFlowSessionNV)load(context, "vkCreateOpticalFlowSessionNV"); table->vkDestroyOpticalFlowSessionNV = (PFN_vkDestroyOpticalFlowSessionNV)load(context, "vkDestroyOpticalFlowSessionNV"); #endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) + table->vkCmdBuildPartitionedAccelerationStructuresNV = (PFN_vkCmdBuildPartitionedAccelerationStructuresNV)load(context, "vkCmdBuildPartitionedAccelerationStructuresNV"); + table->vkGetPartitionedAccelerationStructuresBuildSizesNV = (PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV)load(context, "vkGetPartitionedAccelerationStructuresBuildSizesNV"); +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ #if defined(VK_NV_ray_tracing) table->vkBindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)load(context, "vkBindAccelerationStructureMemoryNV"); table->vkCmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)load(context, "vkCmdBuildAccelerationStructureNV"); @@ -2013,10 +2280,18 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)load(context, "vkCmdSetCoarseSampleOrderNV"); table->vkCmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)load(context, "vkCmdSetViewportShadingRatePaletteNV"); #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_memory_heap) + table->vkCmdBindTileMemoryQCOM = (PFN_vkCmdBindTileMemoryQCOM)load(context, "vkCmdBindTileMemoryQCOM"); +#endif /* defined(VK_QCOM_tile_memory_heap) */ #if defined(VK_QCOM_tile_properties) table->vkGetDynamicRenderingTilePropertiesQCOM = (PFN_vkGetDynamicRenderingTilePropertiesQCOM)load(context, "vkGetDynamicRenderingTilePropertiesQCOM"); table->vkGetFramebufferTilePropertiesQCOM = (PFN_vkGetFramebufferTilePropertiesQCOM)load(context, "vkGetFramebufferTilePropertiesQCOM"); #endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) + table->vkCmdBeginPerTileExecutionQCOM = (PFN_vkCmdBeginPerTileExecutionQCOM)load(context, "vkCmdBeginPerTileExecutionQCOM"); + table->vkCmdDispatchTileQCOM = (PFN_vkCmdDispatchTileQCOM)load(context, "vkCmdDispatchTileQCOM"); + table->vkCmdEndPerTileExecutionQCOM = (PFN_vkCmdEndPerTileExecutionQCOM)load(context, "vkCmdEndPerTileExecutionQCOM"); +#endif /* defined(VK_QCOM_tile_shading) */ #if defined(VK_QNX_external_memory_screen_buffer) table->vkGetScreenBufferPropertiesQNX = (PFN_vkGetScreenBufferPropertiesQNX)load(context, "vkGetScreenBufferPropertiesQNX"); #endif /* defined(VK_QNX_external_memory_screen_buffer) */ @@ -2024,6 +2299,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); table->vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) + table->vkCmdSetDepthClampRangeEXT = (PFN_vkCmdSetDepthClampRangeEXT)load(context, "vkCmdSetDepthClampRangeEXT"); +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ #if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) table->vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); table->vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); @@ -2110,18 +2388,15 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) table->vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ -#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) - table->vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); -#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ #if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) table->vkGetImageSubresourceLayout2EXT = (PFN_vkGetImageSubresourceLayout2EXT)load(context, "vkGetImageSubresourceLayout2EXT"); #endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ #if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); #endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) table->vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); -#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) table->vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)load(context, "vkGetDeviceGroupPresentCapabilitiesKHR"); table->vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)load(context, "vkGetDeviceGroupSurfacePresentModesKHR"); @@ -2364,6 +2639,27 @@ PFN_vkGetPrivateData vkGetPrivateData; PFN_vkQueueSubmit2 vkQueueSubmit2; PFN_vkSetPrivateData vkSetPrivateData; #endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) +PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2; +PFN_vkCmdBindIndexBuffer2 vkCmdBindIndexBuffer2; +PFN_vkCmdPushConstants2 vkCmdPushConstants2; +PFN_vkCmdPushDescriptorSet vkCmdPushDescriptorSet; +PFN_vkCmdPushDescriptorSet2 vkCmdPushDescriptorSet2; +PFN_vkCmdPushDescriptorSetWithTemplate vkCmdPushDescriptorSetWithTemplate; +PFN_vkCmdPushDescriptorSetWithTemplate2 vkCmdPushDescriptorSetWithTemplate2; +PFN_vkCmdSetLineStipple vkCmdSetLineStipple; +PFN_vkCmdSetRenderingAttachmentLocations vkCmdSetRenderingAttachmentLocations; +PFN_vkCmdSetRenderingInputAttachmentIndices vkCmdSetRenderingInputAttachmentIndices; +PFN_vkCopyImageToImage vkCopyImageToImage; +PFN_vkCopyImageToMemory vkCopyImageToMemory; +PFN_vkCopyMemoryToImage vkCopyMemoryToImage; +PFN_vkGetDeviceImageSubresourceLayout vkGetDeviceImageSubresourceLayout; +PFN_vkGetImageSubresourceLayout2 vkGetImageSubresourceLayout2; +PFN_vkGetRenderingAreaGranularity vkGetRenderingAreaGranularity; +PFN_vkMapMemory2 vkMapMemory2; +PFN_vkTransitionImageLayout vkTransitionImageLayout; +PFN_vkUnmapMemory2 vkUnmapMemory2; +#endif /* defined(VK_VERSION_1_4) */ #if defined(VK_AMDX_shader_enqueue) PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; @@ -2373,9 +2669,15 @@ PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; #endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) +PFN_vkAntiLagUpdateAMD vkAntiLagUpdateAMD; +#endif /* defined(VK_AMD_anti_lag) */ #if defined(VK_AMD_buffer_marker) PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_AMD_display_native_hdr) PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; #endif /* defined(VK_AMD_display_native_hdr) */ @@ -2390,6 +2692,34 @@ PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) +PFN_vkBindDataGraphPipelineSessionMemoryARM vkBindDataGraphPipelineSessionMemoryARM; +PFN_vkCmdDispatchDataGraphARM vkCmdDispatchDataGraphARM; +PFN_vkCreateDataGraphPipelineSessionARM vkCreateDataGraphPipelineSessionARM; +PFN_vkCreateDataGraphPipelinesARM vkCreateDataGraphPipelinesARM; +PFN_vkDestroyDataGraphPipelineSessionARM vkDestroyDataGraphPipelineSessionARM; +PFN_vkGetDataGraphPipelineAvailablePropertiesARM vkGetDataGraphPipelineAvailablePropertiesARM; +PFN_vkGetDataGraphPipelinePropertiesARM vkGetDataGraphPipelinePropertiesARM; +PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM vkGetDataGraphPipelineSessionBindPointRequirementsARM; +PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM vkGetDataGraphPipelineSessionMemoryRequirementsARM; +PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM; +PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) +PFN_vkBindTensorMemoryARM vkBindTensorMemoryARM; +PFN_vkCmdCopyTensorARM vkCmdCopyTensorARM; +PFN_vkCreateTensorARM vkCreateTensorARM; +PFN_vkCreateTensorViewARM vkCreateTensorViewARM; +PFN_vkDestroyTensorARM vkDestroyTensorARM; +PFN_vkDestroyTensorViewARM vkDestroyTensorViewARM; +PFN_vkGetDeviceTensorMemoryRequirementsARM vkGetDeviceTensorMemoryRequirementsARM; +PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM vkGetPhysicalDeviceExternalTensorPropertiesARM; +PFN_vkGetTensorMemoryRequirementsARM vkGetTensorMemoryRequirementsARM; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) +PFN_vkGetTensorOpaqueCaptureDescriptorDataARM vkGetTensorOpaqueCaptureDescriptorDataARM; +PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM vkGetTensorViewOpaqueCaptureDescriptorDataARM; +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ #if defined(VK_EXT_acquire_drm_display) PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; @@ -2461,6 +2791,17 @@ PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationSt #if defined(VK_EXT_device_fault) PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; #endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) +PFN_vkCmdExecuteGeneratedCommandsEXT vkCmdExecuteGeneratedCommandsEXT; +PFN_vkCmdPreprocessGeneratedCommandsEXT vkCmdPreprocessGeneratedCommandsEXT; +PFN_vkCreateIndirectCommandsLayoutEXT vkCreateIndirectCommandsLayoutEXT; +PFN_vkCreateIndirectExecutionSetEXT vkCreateIndirectExecutionSetEXT; +PFN_vkDestroyIndirectCommandsLayoutEXT vkDestroyIndirectCommandsLayoutEXT; +PFN_vkDestroyIndirectExecutionSetEXT vkDestroyIndirectExecutionSetEXT; +PFN_vkGetGeneratedCommandsMemoryRequirementsEXT vkGetGeneratedCommandsMemoryRequirementsEXT; +PFN_vkUpdateIndirectExecutionSetPipelineEXT vkUpdateIndirectExecutionSetPipelineEXT; +PFN_vkUpdateIndirectExecutionSetShaderEXT vkUpdateIndirectExecutionSetShaderEXT; +#endif /* defined(VK_EXT_device_generated_commands) */ #if defined(VK_EXT_direct_mode_display) PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; #endif /* defined(VK_EXT_direct_mode_display) */ @@ -2487,11 +2828,21 @@ PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabil #if defined(VK_EXT_external_memory_host) PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) +PFN_vkGetMemoryMetalHandleEXT vkGetMemoryMetalHandleEXT; +PFN_vkGetMemoryMetalHandlePropertiesEXT vkGetMemoryMetalHandlePropertiesEXT; +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) +PFN_vkCmdEndRendering2EXT vkCmdEndRendering2EXT; +#endif /* defined(VK_EXT_fragment_density_map_offset) */ #if defined(VK_EXT_full_screen_exclusive) PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; #endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) +PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ #if defined(VK_EXT_hdr_metadata) PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #endif /* defined(VK_EXT_hdr_metadata) */ @@ -2515,9 +2866,11 @@ PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; #endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_mesh_shader) PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; -PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; #endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_EXT_metal_objects) PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; #endif /* defined(VK_EXT_metal_objects) */ @@ -2622,9 +2975,11 @@ PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; #if defined(VK_HUAWEI_invocation_mask) PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 +PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ #if defined(VK_HUAWEI_subpass_shading) PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; -PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; #endif /* defined(VK_HUAWEI_subpass_shading) */ #if defined(VK_INTEL_performance_query) PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; @@ -2682,6 +3037,10 @@ PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; #endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) +PFN_vkCmdCopyMemoryIndirectKHR vkCmdCopyMemoryIndirectKHR; +PFN_vkCmdCopyMemoryToImageIndirectKHR vkCmdCopyMemoryToImageIndirectKHR; +#endif /* defined(VK_KHR_copy_memory_indirect) */ #if defined(VK_KHR_create_renderpass2) PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; @@ -2835,6 +3194,13 @@ PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumerateP PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; #endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) +PFN_vkCreatePipelineBinariesKHR vkCreatePipelineBinariesKHR; +PFN_vkDestroyPipelineBinaryKHR vkDestroyPipelineBinaryKHR; +PFN_vkGetPipelineBinaryDataKHR vkGetPipelineBinaryDataKHR; +PFN_vkGetPipelineKeyKHR vkGetPipelineKeyKHR; +PFN_vkReleaseCapturedPipelineDataKHR vkReleaseCapturedPipelineDataKHR; +#endif /* defined(VK_KHR_pipeline_binary) */ #if defined(VK_KHR_pipeline_executable_properties) PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; @@ -2843,6 +3209,9 @@ PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; #if defined(VK_KHR_present_wait) PFN_vkWaitForPresentKHR vkWaitForPresentKHR; #endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) +PFN_vkWaitForPresent2KHR vkWaitForPresent2KHR; +#endif /* defined(VK_KHR_present_wait2) */ #if defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ @@ -2879,6 +3248,9 @@ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; PFN_vkQueuePresentKHR vkQueuePresentKHR; #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) +PFN_vkReleaseSwapchainImagesKHR vkReleaseSwapchainImagesKHR; +#endif /* defined(VK_KHR_swapchain_maintenance1) */ #if defined(VK_KHR_synchronization2) PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; @@ -2887,12 +3259,6 @@ PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; #endif /* defined(VK_KHR_synchronization2) */ -#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) -PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; -#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ -#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) -PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; -#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ #if defined(VK_KHR_timeline_semaphore) PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; @@ -2953,9 +3319,14 @@ PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; #endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) -PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; #endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 +PFN_vkGetImageViewHandle64NVX vkGetImageViewHandle64NVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 +PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ #if defined(VK_NV_acquire_winrt_display) PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; @@ -2963,9 +3334,21 @@ PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; #if defined(VK_NV_clip_space_w_scaling) PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) +PFN_vkCmdBuildClusterAccelerationStructureIndirectNV vkCmdBuildClusterAccelerationStructureIndirectNV; +PFN_vkGetClusterAccelerationStructureBuildSizesNV vkGetClusterAccelerationStructureBuildSizesNV; +#endif /* defined(VK_NV_cluster_acceleration_structure) */ #if defined(VK_NV_cooperative_matrix) PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) +PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) +PFN_vkCmdConvertCooperativeVectorMatrixNV vkCmdConvertCooperativeVectorMatrixNV; +PFN_vkConvertCooperativeVectorMatrixNV vkConvertCooperativeVectorMatrixNV; +PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV vkGetPhysicalDeviceCooperativeVectorPropertiesNV; +#endif /* defined(VK_NV_cooperative_vector) */ #if defined(VK_NV_copy_memory_indirect) PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; @@ -2985,6 +3368,9 @@ PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_NV_device_generated_commands) PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; @@ -2998,6 +3384,11 @@ PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; #endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) +PFN_vkCreateExternalComputeQueueNV vkCreateExternalComputeQueueNV; +PFN_vkDestroyExternalComputeQueueNV vkDestroyExternalComputeQueueNV; +PFN_vkGetExternalComputeQueueDataNV vkGetExternalComputeQueueDataNV; +#endif /* defined(VK_NV_external_compute_queue) */ #if defined(VK_NV_external_memory_capabilities) PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; #endif /* defined(VK_NV_external_memory_capabilities) */ @@ -3022,10 +3413,12 @@ PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; #endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) -PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_NV_optical_flow) PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; @@ -3033,6 +3426,10 @@ PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; #endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) +PFN_vkCmdBuildPartitionedAccelerationStructuresNV vkCmdBuildPartitionedAccelerationStructuresNV; +PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV vkGetPartitionedAccelerationStructuresBuildSizesNV; +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ #if defined(VK_NV_ray_tracing) PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; @@ -3058,10 +3455,21 @@ PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_OHOS_surface) +PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS; +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QCOM_tile_memory_heap) +PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; +#endif /* defined(VK_QCOM_tile_memory_heap) */ #if defined(VK_QCOM_tile_properties) PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; #endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) +PFN_vkCmdBeginPerTileExecutionQCOM vkCmdBeginPerTileExecutionQCOM; +PFN_vkCmdDispatchTileQCOM vkCmdDispatchTileQCOM; +PFN_vkCmdEndPerTileExecutionQCOM vkCmdEndPerTileExecutionQCOM; +#endif /* defined(VK_QCOM_tile_shading) */ #if defined(VK_QNX_external_memory_screen_buffer) PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; #endif /* defined(VK_QNX_external_memory_screen_buffer) */ @@ -3073,6 +3481,9 @@ PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPre PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) +PFN_vkCmdSetDepthClampRangeEXT vkCmdSetDepthClampRangeEXT; +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ #if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; @@ -3159,18 +3570,15 @@ PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTes #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ -#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) -PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; -#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ #if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; #endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ #if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; #endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; -#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; @@ -3186,6 +3594,6 @@ PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; #endif #ifdef __cplusplus -} +} // extern "C" / namespace volk #endif /* clang-format on */ diff --git a/src/third_party/volk/volk.h b/src/third_party/volk/volk.h index b8055318b82..169126e6d35 100644 --- a/src/third_party/volk/volk.h +++ b/src/third_party/volk/volk.h @@ -1,7 +1,7 @@ /** * volk * - * Copyright (C) 2018-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2018-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://github.com/zeux/volk * * This library is distributed under the MIT License. See notice at the end of this file. @@ -10,12 +10,16 @@ #ifndef VOLK_H_ #define VOLK_H_ +#if defined(VOLK_NAMESPACE) && !defined(__cplusplus) +#error VOLK_NAMESPACE is only supported in C++ +#endif + #if defined(VULKAN_H_) && !defined(VK_NO_PROTOTYPES) # error To use volk, you need to define VK_NO_PROTOTYPES before including vulkan.h #endif /* VOLK_GENERATE_VERSION_DEFINE */ -#define VOLK_HEADER_VERSION 288 +#define VOLK_HEADER_VERSION 329 /* VOLK_GENERATE_VERSION_DEFINE */ #ifndef VK_NO_PROTOTYPES @@ -25,43 +29,19 @@ #ifndef VULKAN_H_ # ifdef VOLK_VULKAN_H_PATH # include VOLK_VULKAN_H_PATH -# elif defined(VK_USE_PLATFORM_WIN32_KHR) +# else /* Platform headers included below */ # include # include - - /* When VK_USE_PLATFORM_WIN32_KHR is defined, instead of including vulkan.h directly, we include individual parts of the SDK - * This is necessary to avoid including which is very heavy - it takes 200ms to parse without WIN32_LEAN_AND_MEAN - * and 100ms to parse with it. vulkan_win32.h only needs a few symbols that are easy to redefine ourselves. - */ - typedef unsigned long DWORD; - typedef const wchar_t* LPCWSTR; - typedef void* HANDLE; - typedef struct HINSTANCE__* HINSTANCE; - typedef struct HWND__* HWND; - typedef struct HMONITOR__* HMONITOR; - typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; - -# include - -# ifdef VK_ENABLE_BETA_EXTENSIONS -# include -# endif -# else -# include # endif #endif -/* Disable several extensions on earlier SDKs because later SDKs introduce a backwards incompatible change to function signatures */ -#if VK_HEADER_VERSION < 140 -# undef VK_NVX_image_view_handle -#endif -#if VK_HEADER_VERSION < 184 -# undef VK_HUAWEI_subpass_shading -#endif - #ifdef __cplusplus +#ifdef VOLK_NAMESPACE +namespace volk { +#else extern "C" { #endif +#endif struct VolkDeviceTable; @@ -132,6 +112,112 @@ VkDevice volkGetLoadedDevice(void); */ void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device); +#ifdef __cplusplus +} // extern "C" / namespace volk +#endif + +/* Instead of directly including vulkan.h, we include platform-specific parts of the SDK manually + * This is necessary to avoid including platform headers in some cases (which vulkan.h does unconditionally) + * and replace them with forward declarations, which makes build times faster and avoids macro conflicts. + * + * Note that we only replace platform-specific headers when the headers are known to be problematic: very large + * or slow to compile (Windows), or introducing unprefixed macros which can cause conflicts (Windows, Xlib). + */ +#if !defined(VULKAN_H_) && !defined(VOLK_VULKAN_H_PATH) + +#ifdef VK_USE_PLATFORM_ANDROID_KHR +#include +#endif + +#ifdef VK_USE_PLATFORM_FUCHSIA +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_IOS_MVK +#include +#endif + +#ifdef VK_USE_PLATFORM_MACOS_MVK +#include +#endif + +#ifdef VK_USE_PLATFORM_METAL_EXT +#include +#endif + +#ifdef VK_USE_PLATFORM_VI_NN +#include +#endif + +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +#include +#endif + +#ifdef VK_USE_PLATFORM_WIN32_KHR +typedef unsigned long DWORD; +typedef const wchar_t* LPCWSTR; +typedef void* HANDLE; +typedef struct HINSTANCE__* HINSTANCE; +typedef struct HWND__* HWND; +typedef struct HMONITOR__* HMONITOR; +typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; +#include +#endif + +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_XLIB_KHR +typedef struct _XDisplay Display; +typedef unsigned long Window; +typedef unsigned long VisualID; +#include +#endif + +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT +typedef struct _XDisplay Display; +typedef unsigned long RROutput; +#include +#endif + +#ifdef VK_USE_PLATFORM_GGP +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_SCREEN_QNX +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_SCI +#include +#include +#include +#endif + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include +#endif + +#endif + +#ifdef __cplusplus +#ifdef VOLK_NAMESPACE +namespace volk { +#else +extern "C" { +#endif +#endif + /** * Device-specific function pointer table */ @@ -259,6 +345,8 @@ struct VolkDeviceTable PFN_vkUnmapMemory vkUnmapMemory; PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; PFN_vkWaitForFences vkWaitForFences; +#else + PFN_vkVoidFunction padding_6ce80d51[120]; #endif /* defined(VK_VERSION_1_0) */ #if defined(VK_VERSION_1_1) PFN_vkBindBufferMemory2 vkBindBufferMemory2; @@ -277,6 +365,8 @@ struct VolkDeviceTable PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2; PFN_vkTrimCommandPool vkTrimCommandPool; PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; +#else + PFN_vkVoidFunction padding_1ec56847[16]; #endif /* defined(VK_VERSION_1_1) */ #if defined(VK_VERSION_1_2) PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; @@ -292,6 +382,8 @@ struct VolkDeviceTable PFN_vkResetQueryPool vkResetQueryPool; PFN_vkSignalSemaphore vkSignalSemaphore; PFN_vkWaitSemaphores vkWaitSemaphores; +#else + PFN_vkVoidFunction padding_a3e00662[13]; #endif /* defined(VK_VERSION_1_2) */ #if defined(VK_VERSION_1_3) PFN_vkCmdBeginRendering vkCmdBeginRendering; @@ -330,7 +422,32 @@ struct VolkDeviceTable PFN_vkGetPrivateData vkGetPrivateData; PFN_vkQueueSubmit2 vkQueueSubmit2; PFN_vkSetPrivateData vkSetPrivateData; +#else + PFN_vkVoidFunction padding_ee798a88[36]; #endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) + PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2; + PFN_vkCmdBindIndexBuffer2 vkCmdBindIndexBuffer2; + PFN_vkCmdPushConstants2 vkCmdPushConstants2; + PFN_vkCmdPushDescriptorSet vkCmdPushDescriptorSet; + PFN_vkCmdPushDescriptorSet2 vkCmdPushDescriptorSet2; + PFN_vkCmdPushDescriptorSetWithTemplate vkCmdPushDescriptorSetWithTemplate; + PFN_vkCmdPushDescriptorSetWithTemplate2 vkCmdPushDescriptorSetWithTemplate2; + PFN_vkCmdSetLineStipple vkCmdSetLineStipple; + PFN_vkCmdSetRenderingAttachmentLocations vkCmdSetRenderingAttachmentLocations; + PFN_vkCmdSetRenderingInputAttachmentIndices vkCmdSetRenderingInputAttachmentIndices; + PFN_vkCopyImageToImage vkCopyImageToImage; + PFN_vkCopyImageToMemory vkCopyImageToMemory; + PFN_vkCopyMemoryToImage vkCopyMemoryToImage; + PFN_vkGetDeviceImageSubresourceLayout vkGetDeviceImageSubresourceLayout; + PFN_vkGetImageSubresourceLayout2 vkGetImageSubresourceLayout2; + PFN_vkGetRenderingAreaGranularity vkGetRenderingAreaGranularity; + PFN_vkMapMemory2 vkMapMemory2; + PFN_vkTransitionImageLayout vkTransitionImageLayout; + PFN_vkUnmapMemory2 vkUnmapMemory2; +#else + PFN_vkVoidFunction padding_82585fa3[19]; +#endif /* defined(VK_VERSION_1_4) */ #if defined(VK_AMDX_shader_enqueue) PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; @@ -339,39 +456,102 @@ struct VolkDeviceTable PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#else + PFN_vkVoidFunction padding_9d3e2bba[7]; #endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) + PFN_vkAntiLagUpdateAMD vkAntiLagUpdateAMD; +#else + PFN_vkVoidFunction padding_cf792fb4[1]; +#endif /* defined(VK_AMD_anti_lag) */ #if defined(VK_AMD_buffer_marker) PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; +#else + PFN_vkVoidFunction padding_7836e92f[1]; #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#else + PFN_vkVoidFunction padding_bbf9b7bb[1]; +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_AMD_display_native_hdr) PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#else + PFN_vkVoidFunction padding_6b81b2fb[1]; #endif /* defined(VK_AMD_display_native_hdr) */ #if defined(VK_AMD_draw_indirect_count) PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; +#else + PFN_vkVoidFunction padding_fbfa9964[2]; #endif /* defined(VK_AMD_draw_indirect_count) */ #if defined(VK_AMD_shader_info) PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; +#else + PFN_vkVoidFunction padding_bfb754b[1]; #endif /* defined(VK_AMD_shader_info) */ #if defined(VK_ANDROID_external_memory_android_hardware_buffer) PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; +#else + PFN_vkVoidFunction padding_c67b1beb[2]; #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) + PFN_vkBindDataGraphPipelineSessionMemoryARM vkBindDataGraphPipelineSessionMemoryARM; + PFN_vkCmdDispatchDataGraphARM vkCmdDispatchDataGraphARM; + PFN_vkCreateDataGraphPipelineSessionARM vkCreateDataGraphPipelineSessionARM; + PFN_vkCreateDataGraphPipelinesARM vkCreateDataGraphPipelinesARM; + PFN_vkDestroyDataGraphPipelineSessionARM vkDestroyDataGraphPipelineSessionARM; + PFN_vkGetDataGraphPipelineAvailablePropertiesARM vkGetDataGraphPipelineAvailablePropertiesARM; + PFN_vkGetDataGraphPipelinePropertiesARM vkGetDataGraphPipelinePropertiesARM; + PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM vkGetDataGraphPipelineSessionBindPointRequirementsARM; + PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM vkGetDataGraphPipelineSessionMemoryRequirementsARM; +#else + PFN_vkVoidFunction padding_894d85d8[9]; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) + PFN_vkBindTensorMemoryARM vkBindTensorMemoryARM; + PFN_vkCmdCopyTensorARM vkCmdCopyTensorARM; + PFN_vkCreateTensorARM vkCreateTensorARM; + PFN_vkCreateTensorViewARM vkCreateTensorViewARM; + PFN_vkDestroyTensorARM vkDestroyTensorARM; + PFN_vkDestroyTensorViewARM vkDestroyTensorViewARM; + PFN_vkGetDeviceTensorMemoryRequirementsARM vkGetDeviceTensorMemoryRequirementsARM; + PFN_vkGetTensorMemoryRequirementsARM vkGetTensorMemoryRequirementsARM; +#else + PFN_vkVoidFunction padding_df67a729[8]; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) + PFN_vkGetTensorOpaqueCaptureDescriptorDataARM vkGetTensorOpaqueCaptureDescriptorDataARM; + PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM vkGetTensorViewOpaqueCaptureDescriptorDataARM; +#else + PFN_vkVoidFunction padding_9483bf7e[2]; +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ #if defined(VK_EXT_attachment_feedback_loop_dynamic_state) PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#else + PFN_vkVoidFunction padding_760a41f5[1]; #endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ #if defined(VK_EXT_buffer_device_address) PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; +#else + PFN_vkVoidFunction padding_3b69d885[1]; #endif /* defined(VK_EXT_buffer_device_address) */ #if defined(VK_EXT_calibrated_timestamps) PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; +#else + PFN_vkVoidFunction padding_d0981c89[1]; #endif /* defined(VK_EXT_calibrated_timestamps) */ #if defined(VK_EXT_color_write_enable) PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#else + PFN_vkVoidFunction padding_d301ecc3[1]; #endif /* defined(VK_EXT_color_write_enable) */ #if defined(VK_EXT_conditional_rendering) PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; +#else + PFN_vkVoidFunction padding_ab532c18[2]; #endif /* defined(VK_EXT_conditional_rendering) */ #if defined(VK_EXT_debug_marker) PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBeginEXT; @@ -379,9 +559,13 @@ struct VolkDeviceTable PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsertEXT; PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; +#else + PFN_vkVoidFunction padding_89986968[5]; #endif /* defined(VK_EXT_debug_marker) */ #if defined(VK_EXT_depth_bias_control) PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#else + PFN_vkVoidFunction padding_bcddab4d[1]; #endif /* defined(VK_EXT_depth_bias_control) */ #if defined(VK_EXT_descriptor_buffer) PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; @@ -394,62 +578,127 @@ struct VolkDeviceTable PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#else + PFN_vkVoidFunction padding_80aa973c[10]; #endif /* defined(VK_EXT_descriptor_buffer) */ #if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#else + PFN_vkVoidFunction padding_98d0fb33[1]; #endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ #if defined(VK_EXT_device_fault) PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#else + PFN_vkVoidFunction padding_55095419[1]; #endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) + PFN_vkCmdExecuteGeneratedCommandsEXT vkCmdExecuteGeneratedCommandsEXT; + PFN_vkCmdPreprocessGeneratedCommandsEXT vkCmdPreprocessGeneratedCommandsEXT; + PFN_vkCreateIndirectCommandsLayoutEXT vkCreateIndirectCommandsLayoutEXT; + PFN_vkCreateIndirectExecutionSetEXT vkCreateIndirectExecutionSetEXT; + PFN_vkDestroyIndirectCommandsLayoutEXT vkDestroyIndirectCommandsLayoutEXT; + PFN_vkDestroyIndirectExecutionSetEXT vkDestroyIndirectExecutionSetEXT; + PFN_vkGetGeneratedCommandsMemoryRequirementsEXT vkGetGeneratedCommandsMemoryRequirementsEXT; + PFN_vkUpdateIndirectExecutionSetPipelineEXT vkUpdateIndirectExecutionSetPipelineEXT; + PFN_vkUpdateIndirectExecutionSetShaderEXT vkUpdateIndirectExecutionSetShaderEXT; +#else + PFN_vkVoidFunction padding_7ba7ebaa[9]; +#endif /* defined(VK_EXT_device_generated_commands) */ #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; +#else + PFN_vkVoidFunction padding_d6355c2[1]; #endif /* defined(VK_EXT_discard_rectangles) */ #if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#else + PFN_vkVoidFunction padding_7bb44f77[2]; #endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; +#else + PFN_vkVoidFunction padding_d30dfaaf[4]; #endif /* defined(VK_EXT_display_control) */ #if defined(VK_EXT_external_memory_host) PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; +#else + PFN_vkVoidFunction padding_357656e9[1]; #endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) + PFN_vkGetMemoryMetalHandleEXT vkGetMemoryMetalHandleEXT; + PFN_vkGetMemoryMetalHandlePropertiesEXT vkGetMemoryMetalHandlePropertiesEXT; +#else + PFN_vkVoidFunction padding_37d43fb[2]; +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) + PFN_vkCmdEndRendering2EXT vkCmdEndRendering2EXT; +#else + PFN_vkVoidFunction padding_9c90cf11[1]; +#endif /* defined(VK_EXT_fragment_density_map_offset) */ #if defined(VK_EXT_full_screen_exclusive) PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#else + PFN_vkVoidFunction padding_3859df46[2]; #endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) + PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; +#else + PFN_vkVoidFunction padding_e5b48b5b[1]; +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ #if defined(VK_EXT_hdr_metadata) PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; +#else + PFN_vkVoidFunction padding_ca6d733c[1]; #endif /* defined(VK_EXT_hdr_metadata) */ #if defined(VK_EXT_host_image_copy) PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#else + PFN_vkVoidFunction padding_dd6d9b61[4]; #endif /* defined(VK_EXT_host_image_copy) */ #if defined(VK_EXT_host_query_reset) PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#else + PFN_vkVoidFunction padding_34e58bd3[1]; #endif /* defined(VK_EXT_host_query_reset) */ #if defined(VK_EXT_image_drm_format_modifier) PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; +#else + PFN_vkVoidFunction padding_eb50dc14[1]; #endif /* defined(VK_EXT_image_drm_format_modifier) */ #if defined(VK_EXT_line_rasterization) PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#else + PFN_vkVoidFunction padding_8a212c37[1]; #endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_mesh_shader) PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; - PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#else + PFN_vkVoidFunction padding_f65e838[2]; #endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +#else + PFN_vkVoidFunction padding_dcbaac2f[1]; +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_EXT_metal_objects) PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#else + PFN_vkVoidFunction padding_df21f735[1]; #endif /* defined(VK_EXT_metal_objects) */ #if defined(VK_EXT_multi_draw) PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#else + PFN_vkVoidFunction padding_ce8b93b6[2]; #endif /* defined(VK_EXT_multi_draw) */ #if defined(VK_EXT_opacity_micromap) PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; @@ -466,34 +715,50 @@ struct VolkDeviceTable PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#else + PFN_vkVoidFunction padding_fa41e53c[14]; #endif /* defined(VK_EXT_opacity_micromap) */ #if defined(VK_EXT_pageable_device_local_memory) PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#else + PFN_vkVoidFunction padding_b2d2c2d7[1]; #endif /* defined(VK_EXT_pageable_device_local_memory) */ #if defined(VK_EXT_pipeline_properties) PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#else + PFN_vkVoidFunction padding_11313020[1]; #endif /* defined(VK_EXT_pipeline_properties) */ #if defined(VK_EXT_private_data) PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#else + PFN_vkVoidFunction padding_108010f[4]; #endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; +#else + PFN_vkVoidFunction padding_26f9079f[1]; #endif /* defined(VK_EXT_sample_locations) */ #if defined(VK_EXT_shader_module_identifier) PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#else + PFN_vkVoidFunction padding_e10c8f86[2]; #endif /* defined(VK_EXT_shader_module_identifier) */ #if defined(VK_EXT_shader_object) PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; PFN_vkCreateShadersEXT vkCreateShadersEXT; PFN_vkDestroyShaderEXT vkDestroyShaderEXT; PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#else + PFN_vkVoidFunction padding_374f3e18[4]; #endif /* defined(VK_EXT_shader_object) */ #if defined(VK_EXT_swapchain_maintenance1) PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#else + PFN_vkVoidFunction padding_ea55bf74[1]; #endif /* defined(VK_EXT_swapchain_maintenance1) */ #if defined(VK_EXT_transform_feedback) PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; @@ -502,12 +767,16 @@ struct VolkDeviceTable PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT; PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT; PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT; +#else + PFN_vkVoidFunction padding_36980658[6]; #endif /* defined(VK_EXT_transform_feedback) */ #if defined(VK_EXT_validation_cache) PFN_vkCreateValidationCacheEXT vkCreateValidationCacheEXT; PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; +#else + PFN_vkVoidFunction padding_b4f2df29[4]; #endif /* defined(VK_EXT_validation_cache) */ #if defined(VK_FUCHSIA_buffer_collection) PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; @@ -515,29 +784,47 @@ struct VolkDeviceTable PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#else + PFN_vkVoidFunction padding_8eaa27bc[5]; #endif /* defined(VK_FUCHSIA_buffer_collection) */ #if defined(VK_FUCHSIA_external_memory) PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#else + PFN_vkVoidFunction padding_e3cb8a67[2]; #endif /* defined(VK_FUCHSIA_external_memory) */ #if defined(VK_FUCHSIA_external_semaphore) PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#else + PFN_vkVoidFunction padding_3df6f656[2]; #endif /* defined(VK_FUCHSIA_external_semaphore) */ #if defined(VK_GOOGLE_display_timing) PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; +#else + PFN_vkVoidFunction padding_2a6f50cd[2]; #endif /* defined(VK_GOOGLE_display_timing) */ #if defined(VK_HUAWEI_cluster_culling_shader) PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#else + PFN_vkVoidFunction padding_75b97be6[2]; #endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#else + PFN_vkVoidFunction padding_c3a4569f[1]; #endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 + PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#else + PFN_vkVoidFunction padding_2e923f32[1]; +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ #if defined(VK_HUAWEI_subpass_shading) PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; - PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#else + PFN_vkVoidFunction padding_f766fdf5[1]; #endif /* defined(VK_HUAWEI_subpass_shading) */ #if defined(VK_INTEL_performance_query) PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; @@ -549,6 +836,8 @@ struct VolkDeviceTable PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#else + PFN_vkVoidFunction padding_495a0a0b[9]; #endif /* defined(VK_INTEL_performance_query) */ #if defined(VK_KHR_acceleration_structure) PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; @@ -567,18 +856,26 @@ struct VolkDeviceTable PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#else + PFN_vkVoidFunction padding_5a999b78[16]; #endif /* defined(VK_KHR_acceleration_structure) */ #if defined(VK_KHR_bind_memory2) PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; +#else + PFN_vkVoidFunction padding_ed8481f5[2]; #endif /* defined(VK_KHR_bind_memory2) */ #if defined(VK_KHR_buffer_device_address) PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#else + PFN_vkVoidFunction padding_178fdf81[3]; #endif /* defined(VK_KHR_buffer_device_address) */ #if defined(VK_KHR_calibrated_timestamps) PFN_vkGetCalibratedTimestampsKHR vkGetCalibratedTimestampsKHR; +#else + PFN_vkVoidFunction padding_8fd6f40d[1]; #endif /* defined(VK_KHR_calibrated_timestamps) */ #if defined(VK_KHR_copy_commands2) PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; @@ -587,12 +884,22 @@ struct VolkDeviceTable PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#else + PFN_vkVoidFunction padding_4c841ff2[6]; #endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) + PFN_vkCmdCopyMemoryIndirectKHR vkCmdCopyMemoryIndirectKHR; + PFN_vkCmdCopyMemoryToImageIndirectKHR vkCmdCopyMemoryToImageIndirectKHR; +#else + PFN_vkVoidFunction padding_95995957[2]; +#endif /* defined(VK_KHR_copy_memory_indirect) */ #if defined(VK_KHR_create_renderpass2) PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; +#else + PFN_vkVoidFunction padding_2a0a8727[4]; #endif /* defined(VK_KHR_create_renderpass2) */ #if defined(VK_KHR_deferred_host_operations) PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; @@ -600,117 +907,189 @@ struct VolkDeviceTable PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#else + PFN_vkVoidFunction padding_346287bb[5]; #endif /* defined(VK_KHR_deferred_host_operations) */ #if defined(VK_KHR_descriptor_update_template) PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR; +#else + PFN_vkVoidFunction padding_3d63aec0[3]; #endif /* defined(VK_KHR_descriptor_update_template) */ #if defined(VK_KHR_device_group) PFN_vkCmdDispatchBaseKHR vkCmdDispatchBaseKHR; PFN_vkCmdSetDeviceMaskKHR vkCmdSetDeviceMaskKHR; PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR; +#else + PFN_vkVoidFunction padding_5ebe16bd[3]; #endif /* defined(VK_KHR_device_group) */ #if defined(VK_KHR_display_swapchain) PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; +#else + PFN_vkVoidFunction padding_12099367[1]; #endif /* defined(VK_KHR_display_swapchain) */ #if defined(VK_KHR_draw_indirect_count) PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; +#else + PFN_vkVoidFunction padding_7b5bc4c1[2]; #endif /* defined(VK_KHR_draw_indirect_count) */ #if defined(VK_KHR_dynamic_rendering) PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#else + PFN_vkVoidFunction padding_b80f75a5[2]; #endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_dynamic_rendering_local_read) PFN_vkCmdSetRenderingAttachmentLocationsKHR vkCmdSetRenderingAttachmentLocationsKHR; PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAttachmentIndicesKHR; +#else + PFN_vkVoidFunction padding_b1510532[2]; #endif /* defined(VK_KHR_dynamic_rendering_local_read) */ #if defined(VK_KHR_external_fence_fd) PFN_vkGetFenceFdKHR vkGetFenceFdKHR; PFN_vkImportFenceFdKHR vkImportFenceFdKHR; +#else + PFN_vkVoidFunction padding_a2c787d5[2]; #endif /* defined(VK_KHR_external_fence_fd) */ #if defined(VK_KHR_external_fence_win32) PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR; PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR; +#else + PFN_vkVoidFunction padding_55d8e6a9[2]; #endif /* defined(VK_KHR_external_fence_win32) */ #if defined(VK_KHR_external_memory_fd) PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; +#else + PFN_vkVoidFunction padding_982d9e19[2]; #endif /* defined(VK_KHR_external_memory_fd) */ #if defined(VK_KHR_external_memory_win32) PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR; PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR; +#else + PFN_vkVoidFunction padding_4af9e25a[2]; #endif /* defined(VK_KHR_external_memory_win32) */ #if defined(VK_KHR_external_semaphore_fd) PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; +#else + PFN_vkVoidFunction padding_2237b7cf[2]; #endif /* defined(VK_KHR_external_semaphore_fd) */ #if defined(VK_KHR_external_semaphore_win32) PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; +#else + PFN_vkVoidFunction padding_c18dea52[2]; #endif /* defined(VK_KHR_external_semaphore_win32) */ #if defined(VK_KHR_fragment_shading_rate) PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +#else + PFN_vkVoidFunction padding_f91b0a90[1]; #endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_memory_requirements2) PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR; +#else + PFN_vkVoidFunction padding_79d9c5c4[3]; #endif /* defined(VK_KHR_get_memory_requirements2) */ #if defined(VK_KHR_line_rasterization) PFN_vkCmdSetLineStippleKHR vkCmdSetLineStippleKHR; +#else + PFN_vkVoidFunction padding_83c2939[1]; #endif /* defined(VK_KHR_line_rasterization) */ #if defined(VK_KHR_maintenance1) PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; +#else + PFN_vkVoidFunction padding_4b372c56[1]; #endif /* defined(VK_KHR_maintenance1) */ #if defined(VK_KHR_maintenance3) PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; +#else + PFN_vkVoidFunction padding_5ea7858d[1]; #endif /* defined(VK_KHR_maintenance3) */ #if defined(VK_KHR_maintenance4) PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#else + PFN_vkVoidFunction padding_8e2d4198[3]; #endif /* defined(VK_KHR_maintenance4) */ #if defined(VK_KHR_maintenance5) PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#else + PFN_vkVoidFunction padding_37040339[4]; #endif /* defined(VK_KHR_maintenance5) */ #if defined(VK_KHR_maintenance6) PFN_vkCmdBindDescriptorSets2KHR vkCmdBindDescriptorSets2KHR; PFN_vkCmdPushConstants2KHR vkCmdPushConstants2KHR; +#else + PFN_vkVoidFunction padding_442955d8[2]; #endif /* defined(VK_KHR_maintenance6) */ #if defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSet2KHR vkCmdPushDescriptorSet2KHR; PFN_vkCmdPushDescriptorSetWithTemplate2KHR vkCmdPushDescriptorSetWithTemplate2KHR; +#else + PFN_vkVoidFunction padding_80e8513f[2]; #endif /* defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) */ #if defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT vkCmdBindDescriptorBufferEmbeddedSamplers2EXT; PFN_vkCmdSetDescriptorBufferOffsets2EXT vkCmdSetDescriptorBufferOffsets2EXT; +#else + PFN_vkVoidFunction padding_2816b9cd[2]; #endif /* defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) */ #if defined(VK_KHR_map_memory2) PFN_vkMapMemory2KHR vkMapMemory2KHR; PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#else + PFN_vkVoidFunction padding_5a6d8986[2]; #endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#else + PFN_vkVoidFunction padding_76f2673b[2]; #endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) + PFN_vkCreatePipelineBinariesKHR vkCreatePipelineBinariesKHR; + PFN_vkDestroyPipelineBinaryKHR vkDestroyPipelineBinaryKHR; + PFN_vkGetPipelineBinaryDataKHR vkGetPipelineBinaryDataKHR; + PFN_vkGetPipelineKeyKHR vkGetPipelineKeyKHR; + PFN_vkReleaseCapturedPipelineDataKHR vkReleaseCapturedPipelineDataKHR; +#else + PFN_vkVoidFunction padding_65232810[5]; +#endif /* defined(VK_KHR_pipeline_binary) */ #if defined(VK_KHR_pipeline_executable_properties) PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#else + PFN_vkVoidFunction padding_f7629b1e[3]; #endif /* defined(VK_KHR_pipeline_executable_properties) */ #if defined(VK_KHR_present_wait) PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#else + PFN_vkVoidFunction padding_b16cbe03[1]; #endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) + PFN_vkWaitForPresent2KHR vkWaitForPresent2KHR; +#else + PFN_vkVoidFunction padding_7401483a[1]; +#endif /* defined(VK_KHR_present_wait2) */ #if defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; +#else + PFN_vkVoidFunction padding_8f7712ad[1]; #endif /* defined(VK_KHR_push_descriptor) */ #if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#else + PFN_vkVoidFunction padding_dd5f9b4a[1]; #endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_ray_tracing_pipeline) PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; @@ -720,13 +1099,19 @@ struct VolkDeviceTable PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#else + PFN_vkVoidFunction padding_af99aedc[7]; #endif /* defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_sampler_ycbcr_conversion) PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; +#else + PFN_vkVoidFunction padding_88e61b30[2]; #endif /* defined(VK_KHR_sampler_ycbcr_conversion) */ #if defined(VK_KHR_shared_presentable_image) PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR; +#else + PFN_vkVoidFunction padding_1ff3379[1]; #endif /* defined(VK_KHR_shared_presentable_image) */ #if defined(VK_KHR_swapchain) PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; @@ -734,7 +1119,14 @@ struct VolkDeviceTable PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; PFN_vkQueuePresentKHR vkQueuePresentKHR; +#else + PFN_vkVoidFunction padding_a1de893b[5]; #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) + PFN_vkReleaseSwapchainImagesKHR vkReleaseSwapchainImagesKHR; +#else + PFN_vkVoidFunction padding_e032d5c4[1]; +#endif /* defined(VK_KHR_swapchain_maintenance1) */ #if defined(VK_KHR_synchronization2) PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; @@ -742,24 +1134,26 @@ struct VolkDeviceTable PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#else + PFN_vkVoidFunction padding_e85bf128[6]; #endif /* defined(VK_KHR_synchronization2) */ -#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) - PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; -#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ -#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) - PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; -#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ #if defined(VK_KHR_timeline_semaphore) PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#else + PFN_vkVoidFunction padding_c799d931[3]; #endif /* defined(VK_KHR_timeline_semaphore) */ #if defined(VK_KHR_video_decode_queue) PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#else + PFN_vkVoidFunction padding_7a7cc7ad[1]; #endif /* defined(VK_KHR_video_decode_queue) */ #if defined(VK_KHR_video_encode_queue) PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; +#else + PFN_vkVoidFunction padding_f2997fb4[2]; #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; @@ -772,6 +1166,8 @@ struct VolkDeviceTable PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#else + PFN_vkVoidFunction padding_98fb7016[10]; #endif /* defined(VK_KHR_video_queue) */ #if defined(VK_NVX_binary_import) PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; @@ -779,17 +1175,46 @@ struct VolkDeviceTable PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#else + PFN_vkVoidFunction padding_eb54309b[5]; #endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) - PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; +#else + PFN_vkVoidFunction padding_887f6736[1]; #endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 + PFN_vkGetImageViewHandle64NVX vkGetImageViewHandle64NVX; +#else + PFN_vkVoidFunction padding_64ad40e2[1]; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 + PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; +#else + PFN_vkVoidFunction padding_d290479a[1]; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ #if defined(VK_NV_clip_space_w_scaling) PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; +#else + PFN_vkVoidFunction padding_88d7eb2e[1]; #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) + PFN_vkCmdBuildClusterAccelerationStructureIndirectNV vkCmdBuildClusterAccelerationStructureIndirectNV; + PFN_vkGetClusterAccelerationStructureBuildSizesNV vkGetClusterAccelerationStructureBuildSizesNV; +#else + PFN_vkVoidFunction padding_60e35395[2]; +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_cooperative_vector) + PFN_vkCmdConvertCooperativeVectorMatrixNV vkCmdConvertCooperativeVectorMatrixNV; + PFN_vkConvertCooperativeVectorMatrixNV vkConvertCooperativeVectorMatrixNV; +#else + PFN_vkVoidFunction padding_f4a887d0[2]; +#endif /* defined(VK_NV_cooperative_vector) */ #if defined(VK_NV_copy_memory_indirect) PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#else + PFN_vkVoidFunction padding_9536230e[2]; #endif /* defined(VK_NV_copy_memory_indirect) */ #if defined(VK_NV_cuda_kernel_launch) PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; @@ -798,11 +1223,20 @@ struct VolkDeviceTable PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#else + PFN_vkVoidFunction padding_2eabdf3b[6]; #endif /* defined(VK_NV_cuda_kernel_launch) */ #if defined(VK_NV_device_diagnostic_checkpoints) PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; +#else + PFN_vkVoidFunction padding_adaa5a21[2]; #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#else + PFN_vkVoidFunction padding_c776633d[1]; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_NV_device_generated_commands) PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; @@ -810,20 +1244,37 @@ struct VolkDeviceTable PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#else + PFN_vkVoidFunction padding_4c7e4395[6]; #endif /* defined(VK_NV_device_generated_commands) */ #if defined(VK_NV_device_generated_commands_compute) PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#else + PFN_vkVoidFunction padding_5195094c[3]; #endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) + PFN_vkCreateExternalComputeQueueNV vkCreateExternalComputeQueueNV; + PFN_vkDestroyExternalComputeQueueNV vkDestroyExternalComputeQueueNV; + PFN_vkGetExternalComputeQueueDataNV vkGetExternalComputeQueueDataNV; +#else + PFN_vkVoidFunction padding_4f947e0b[3]; +#endif /* defined(VK_NV_external_compute_queue) */ #if defined(VK_NV_external_memory_rdma) PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#else + PFN_vkVoidFunction padding_920e405[1]; #endif /* defined(VK_NV_external_memory_rdma) */ #if defined(VK_NV_external_memory_win32) PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; +#else + PFN_vkVoidFunction padding_c13d6f3a[1]; #endif /* defined(VK_NV_external_memory_win32) */ #if defined(VK_NV_fragment_shading_rate_enums) PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#else + PFN_vkVoidFunction padding_4979ca14[1]; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ #if defined(VK_NV_low_latency2) PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; @@ -831,22 +1282,40 @@ struct VolkDeviceTable PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#else + PFN_vkVoidFunction padding_fabf8b19[5]; #endif /* defined(VK_NV_low_latency2) */ #if defined(VK_NV_memory_decompression) PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#else + PFN_vkVoidFunction padding_706009[2]; #endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) - PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; +#else + PFN_vkVoidFunction padding_ac232758[2]; #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; +#else + PFN_vkVoidFunction padding_53495be7[1]; +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_NV_optical_flow) PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +#else + PFN_vkVoidFunction padding_f67571eb[4]; #endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) + PFN_vkCmdBuildPartitionedAccelerationStructuresNV vkCmdBuildPartitionedAccelerationStructuresNV; + PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV vkGetPartitionedAccelerationStructuresBuildSizesNV; +#else + PFN_vkVoidFunction padding_d27c8c6d[2]; +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ #if defined(VK_NV_ray_tracing) PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; @@ -860,29 +1329,60 @@ struct VolkDeviceTable PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV; PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; +#else + PFN_vkVoidFunction padding_feefbeac[12]; #endif /* defined(VK_NV_ray_tracing) */ #if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#else + PFN_vkVoidFunction padding_e3c24f80[1]; #endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; +#else + PFN_vkVoidFunction padding_8e88d86c[1]; #endif /* defined(VK_NV_scissor_exclusive) */ #if defined(VK_NV_shading_rate_image) PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; +#else + PFN_vkVoidFunction padding_92a0767f[3]; #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_memory_heap) + PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; +#else + PFN_vkVoidFunction padding_e2d55d04[1]; +#endif /* defined(VK_QCOM_tile_memory_heap) */ #if defined(VK_QCOM_tile_properties) PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#else + PFN_vkVoidFunction padding_be12e32[2]; #endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) + PFN_vkCmdBeginPerTileExecutionQCOM vkCmdBeginPerTileExecutionQCOM; + PFN_vkCmdDispatchTileQCOM vkCmdDispatchTileQCOM; + PFN_vkCmdEndPerTileExecutionQCOM vkCmdEndPerTileExecutionQCOM; +#else + PFN_vkVoidFunction padding_fcd9e1df[3]; +#endif /* defined(VK_QCOM_tile_shading) */ #if defined(VK_QNX_external_memory_screen_buffer) PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#else + PFN_vkVoidFunction padding_1c27735d[1]; #endif /* defined(VK_QNX_external_memory_screen_buffer) */ #if defined(VK_VALVE_descriptor_set_host_mapping) PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#else + PFN_vkVoidFunction padding_fd71e4c6[2]; #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) + PFN_vkCmdSetDepthClampRangeEXT vkCmdSetDepthClampRangeEXT; +#else + PFN_vkVoidFunction padding_faa18a61[1]; +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ #if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; @@ -896,6 +1396,8 @@ struct VolkDeviceTable PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#else + PFN_vkVoidFunction padding_3e8c720f[12]; #endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; @@ -903,6 +1405,8 @@ struct VolkDeviceTable PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#else + PFN_vkVoidFunction padding_b93e02a6[5]; #endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; @@ -915,84 +1419,359 @@ struct VolkDeviceTable PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +#else + PFN_vkVoidFunction padding_ab566e7e[10]; #endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#else + PFN_vkVoidFunction padding_6730ed0c[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +#else + PFN_vkVoidFunction padding_d3ebb335[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +#else + PFN_vkVoidFunction padding_a21758f4[2]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +#else + PFN_vkVoidFunction padding_a498a838[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +#else + PFN_vkVoidFunction padding_67db38de[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +#else + PFN_vkVoidFunction padding_fbea7481[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +#else + PFN_vkVoidFunction padding_3a8ec90e[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +#else + PFN_vkVoidFunction padding_29cdb756[2]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +#else + PFN_vkVoidFunction padding_815a7240[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#else + PFN_vkVoidFunction padding_d1f00511[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#else + PFN_vkVoidFunction padding_7a73d553[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#else + PFN_vkVoidFunction padding_6045fb8c[2]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#else + PFN_vkVoidFunction padding_bdc35c80[3]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#else + PFN_vkVoidFunction padding_9a5cd6e8[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#else + PFN_vkVoidFunction padding_3ee17e96[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#else + PFN_vkVoidFunction padding_263d525a[1]; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ -#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) - PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; -#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ #if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#else + PFN_vkVoidFunction padding_ecddace1[1]; #endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ #if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#else + PFN_vkVoidFunction padding_d83e1de1[1]; #endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; -#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ +#else + PFN_vkVoidFunction padding_60f8358a[1]; +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; +#else + PFN_vkVoidFunction padding_460290c6[2]; #endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; +#else + PFN_vkVoidFunction padding_cffc198[1]; #endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ /* VOLK_GENERATE_DEVICE_TABLE */ }; /* VOLK_GENERATE_PROTOTYPES_H */ #if defined(VK_VERSION_1_0) +extern PFN_vkCreateDevice vkCreateDevice; +extern PFN_vkCreateInstance vkCreateInstance; +extern PFN_vkDestroyInstance vkDestroyInstance; +extern PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; +extern PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; +extern PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; +extern PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; +extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; +extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; +extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; +extern PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; +extern PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; +extern PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; +extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; +extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) +extern PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; +extern PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups; +extern PFN_vkGetPhysicalDeviceExternalBufferProperties vkGetPhysicalDeviceExternalBufferProperties; +extern PFN_vkGetPhysicalDeviceExternalFenceProperties vkGetPhysicalDeviceExternalFenceProperties; +extern PFN_vkGetPhysicalDeviceExternalSemaphoreProperties vkGetPhysicalDeviceExternalSemaphoreProperties; +extern PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; +extern PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2; +extern PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2; +extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; +extern PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2; +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseImageFormatProperties2; +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_3) +extern PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_ARM_data_graph) +extern PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM; +extern PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) +extern PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM vkGetPhysicalDeviceExternalTensorPropertiesARM; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_EXT_acquire_drm_display) +extern PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; +extern PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; +#endif /* defined(VK_EXT_acquire_drm_display) */ +#if defined(VK_EXT_acquire_xlib_display) +extern PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; +extern PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; +#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_calibrated_timestamps) +extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_debug_report) +extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; +extern PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT; +extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; +#endif /* defined(VK_EXT_debug_report) */ +#if defined(VK_EXT_debug_utils) +extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT; +extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT; +extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; +extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT; +extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT; +extern PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT; +extern PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT; +extern PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT; +extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; +extern PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; +extern PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; +#endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_direct_mode_display) +extern PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; +#endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) +extern PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; +extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; +#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_display_surface_counter) +extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; +#endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_full_screen_exclusive) +extern PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_headless_surface) +extern PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_metal_surface) +extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; +#endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_sample_locations) +extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) +extern PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; +#endif /* defined(VK_EXT_tooling_info) */ +#if defined(VK_FUCHSIA_imagepipe_surface) +extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; +#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) +extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; +#endif /* defined(VK_GGP_stream_descriptor_surface) */ +#if defined(VK_KHR_android_surface) +extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; +#endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_calibrated_timestamps) +extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR vkGetPhysicalDeviceCalibrateableTimeDomainsKHR; +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_cooperative_matrix) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; +#endif /* defined(VK_KHR_cooperative_matrix) */ +#if defined(VK_KHR_device_group_creation) +extern PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR; +#endif /* defined(VK_KHR_device_group_creation) */ +#if defined(VK_KHR_display) +extern PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; +extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; +extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; +extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; +extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; +extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; +#endif /* defined(VK_KHR_display) */ +#if defined(VK_KHR_external_fence_capabilities) +extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; +#endif /* defined(VK_KHR_external_fence_capabilities) */ +#if defined(VK_KHR_external_memory_capabilities) +extern PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; +#endif /* defined(VK_KHR_external_memory_capabilities) */ +#if defined(VK_KHR_external_semaphore_capabilities) +extern PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR; +#endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_fragment_shading_rate) +extern PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_display_properties2) +extern PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; +extern PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; +extern PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR vkGetPhysicalDeviceDisplayPlaneProperties2KHR; +extern PFN_vkGetPhysicalDeviceDisplayProperties2KHR vkGetPhysicalDeviceDisplayProperties2KHR; +#endif /* defined(VK_KHR_get_display_properties2) */ +#if defined(VK_KHR_get_physical_device_properties2) +extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; +extern PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; +extern PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR; +extern PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; +extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR; +#endif /* defined(VK_KHR_get_physical_device_properties2) */ +#if defined(VK_KHR_get_surface_capabilities2) +extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; +extern PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR; +#endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_performance_query) +extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; +extern PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_surface) +extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; +extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; +extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; +extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; +extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; +#endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_video_encode_queue) +extern PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) +extern PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; +extern PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_KHR_wayland_surface) +extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; +extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; +#endif /* defined(VK_KHR_wayland_surface) */ +#if defined(VK_KHR_win32_surface) +extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; +extern PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; +#endif /* defined(VK_KHR_win32_surface) */ +#if defined(VK_KHR_xcb_surface) +extern PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; +extern PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; +#endif /* defined(VK_KHR_xcb_surface) */ +#if defined(VK_KHR_xlib_surface) +extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; +extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; +#endif /* defined(VK_KHR_xlib_surface) */ +#if defined(VK_MVK_ios_surface) +extern PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK; +#endif /* defined(VK_MVK_ios_surface) */ +#if defined(VK_MVK_macos_surface) +extern PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; +#endif /* defined(VK_MVK_macos_surface) */ +#if defined(VK_NN_vi_surface) +extern PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; +#endif /* defined(VK_NN_vi_surface) */ +#if defined(VK_NV_acquire_winrt_display) +extern PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; +extern PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; +#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NV_cooperative_matrix) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) +extern PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV vkGetPhysicalDeviceCooperativeVectorPropertiesNV; +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_coverage_reduction_mode) +extern PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; +#endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_external_memory_capabilities) +extern PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; +#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_optical_flow) +extern PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_OHOS_surface) +extern PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS; +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QNX_screen_surface) +extern PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; +extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; +#endif /* defined(VK_QNX_screen_surface) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) +extern PFN_vkGetPhysicalDevicePresentRectanglesKHR vkGetPhysicalDevicePresentRectanglesKHR; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +/* VOLK_GENERATE_PROTOTYPES_H */ + +#ifndef VOLK_NO_DEVICE_PROTOTYPES +/* VOLK_GENERATE_PROTOTYPES_H_DEVICE */ +#if defined(VK_VERSION_1_0) extern PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; extern PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; extern PFN_vkAllocateMemory vkAllocateMemory; @@ -1049,14 +1828,12 @@ extern PFN_vkCreateCommandPool vkCreateCommandPool; extern PFN_vkCreateComputePipelines vkCreateComputePipelines; extern PFN_vkCreateDescriptorPool vkCreateDescriptorPool; extern PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; -extern PFN_vkCreateDevice vkCreateDevice; extern PFN_vkCreateEvent vkCreateEvent; extern PFN_vkCreateFence vkCreateFence; extern PFN_vkCreateFramebuffer vkCreateFramebuffer; extern PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; extern PFN_vkCreateImage vkCreateImage; extern PFN_vkCreateImageView vkCreateImageView; -extern PFN_vkCreateInstance vkCreateInstance; extern PFN_vkCreatePipelineCache vkCreatePipelineCache; extern PFN_vkCreatePipelineLayout vkCreatePipelineLayout; extern PFN_vkCreateQueryPool vkCreateQueryPool; @@ -1075,7 +1852,6 @@ extern PFN_vkDestroyFence vkDestroyFence; extern PFN_vkDestroyFramebuffer vkDestroyFramebuffer; extern PFN_vkDestroyImage vkDestroyImage; extern PFN_vkDestroyImageView vkDestroyImageView; -extern PFN_vkDestroyInstance vkDestroyInstance; extern PFN_vkDestroyPipeline vkDestroyPipeline; extern PFN_vkDestroyPipelineCache vkDestroyPipelineCache; extern PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; @@ -1086,32 +1862,18 @@ extern PFN_vkDestroySemaphore vkDestroySemaphore; extern PFN_vkDestroyShaderModule vkDestroyShaderModule; extern PFN_vkDeviceWaitIdle vkDeviceWaitIdle; extern PFN_vkEndCommandBuffer vkEndCommandBuffer; -extern PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; -extern PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; -extern PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; -extern PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; -extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; extern PFN_vkFreeCommandBuffers vkFreeCommandBuffers; extern PFN_vkFreeDescriptorSets vkFreeDescriptorSets; extern PFN_vkFreeMemory vkFreeMemory; extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; extern PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment; -extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; extern PFN_vkGetDeviceQueue vkGetDeviceQueue; extern PFN_vkGetEventStatus vkGetEventStatus; extern PFN_vkGetFenceStatus vkGetFenceStatus; extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; extern PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; extern PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; -extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; -extern PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; -extern PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; -extern PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; -extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; -extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; -extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; -extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; extern PFN_vkGetPipelineCacheData vkGetPipelineCacheData; extern PFN_vkGetQueryPoolResults vkGetQueryPoolResults; extern PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity; @@ -1140,24 +1902,12 @@ extern PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate; extern PFN_vkCreateSamplerYcbcrConversion vkCreateSamplerYcbcrConversion; extern PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate; extern PFN_vkDestroySamplerYcbcrConversion vkDestroySamplerYcbcrConversion; -extern PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; -extern PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups; extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; extern PFN_vkGetDescriptorSetLayoutSupport vkGetDescriptorSetLayoutSupport; extern PFN_vkGetDeviceGroupPeerMemoryFeatures vkGetDeviceGroupPeerMemoryFeatures; extern PFN_vkGetDeviceQueue2 vkGetDeviceQueue2; extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; extern PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2; -extern PFN_vkGetPhysicalDeviceExternalBufferProperties vkGetPhysicalDeviceExternalBufferProperties; -extern PFN_vkGetPhysicalDeviceExternalFenceProperties vkGetPhysicalDeviceExternalFenceProperties; -extern PFN_vkGetPhysicalDeviceExternalSemaphoreProperties vkGetPhysicalDeviceExternalSemaphoreProperties; -extern PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; -extern PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2; -extern PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2; -extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; -extern PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; -extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2; -extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseImageFormatProperties2; extern PFN_vkTrimCommandPool vkTrimCommandPool; extern PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; #endif /* defined(VK_VERSION_1_1) */ @@ -1210,11 +1960,31 @@ extern PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; extern PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; extern PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; extern PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; -extern PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; extern PFN_vkGetPrivateData vkGetPrivateData; extern PFN_vkQueueSubmit2 vkQueueSubmit2; extern PFN_vkSetPrivateData vkSetPrivateData; #endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) +extern PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2; +extern PFN_vkCmdBindIndexBuffer2 vkCmdBindIndexBuffer2; +extern PFN_vkCmdPushConstants2 vkCmdPushConstants2; +extern PFN_vkCmdPushDescriptorSet vkCmdPushDescriptorSet; +extern PFN_vkCmdPushDescriptorSet2 vkCmdPushDescriptorSet2; +extern PFN_vkCmdPushDescriptorSetWithTemplate vkCmdPushDescriptorSetWithTemplate; +extern PFN_vkCmdPushDescriptorSetWithTemplate2 vkCmdPushDescriptorSetWithTemplate2; +extern PFN_vkCmdSetLineStipple vkCmdSetLineStipple; +extern PFN_vkCmdSetRenderingAttachmentLocations vkCmdSetRenderingAttachmentLocations; +extern PFN_vkCmdSetRenderingInputAttachmentIndices vkCmdSetRenderingInputAttachmentIndices; +extern PFN_vkCopyImageToImage vkCopyImageToImage; +extern PFN_vkCopyImageToMemory vkCopyImageToMemory; +extern PFN_vkCopyMemoryToImage vkCopyMemoryToImage; +extern PFN_vkGetDeviceImageSubresourceLayout vkGetDeviceImageSubresourceLayout; +extern PFN_vkGetImageSubresourceLayout2 vkGetImageSubresourceLayout2; +extern PFN_vkGetRenderingAreaGranularity vkGetRenderingAreaGranularity; +extern PFN_vkMapMemory2 vkMapMemory2; +extern PFN_vkTransitionImageLayout vkTransitionImageLayout; +extern PFN_vkUnmapMemory2 vkUnmapMemory2; +#endif /* defined(VK_VERSION_1_4) */ #if defined(VK_AMDX_shader_enqueue) extern PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; extern PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; @@ -1224,9 +1994,15 @@ extern PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAM extern PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; extern PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; #endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) +extern PFN_vkAntiLagUpdateAMD vkAntiLagUpdateAMD; +#endif /* defined(VK_AMD_anti_lag) */ #if defined(VK_AMD_buffer_marker) extern PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +extern PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_AMD_display_native_hdr) extern PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; #endif /* defined(VK_AMD_display_native_hdr) */ @@ -1241,14 +2017,31 @@ extern PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ -#if defined(VK_EXT_acquire_drm_display) -extern PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; -extern PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; -#endif /* defined(VK_EXT_acquire_drm_display) */ -#if defined(VK_EXT_acquire_xlib_display) -extern PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; -extern PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; -#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_ARM_data_graph) +extern PFN_vkBindDataGraphPipelineSessionMemoryARM vkBindDataGraphPipelineSessionMemoryARM; +extern PFN_vkCmdDispatchDataGraphARM vkCmdDispatchDataGraphARM; +extern PFN_vkCreateDataGraphPipelineSessionARM vkCreateDataGraphPipelineSessionARM; +extern PFN_vkCreateDataGraphPipelinesARM vkCreateDataGraphPipelinesARM; +extern PFN_vkDestroyDataGraphPipelineSessionARM vkDestroyDataGraphPipelineSessionARM; +extern PFN_vkGetDataGraphPipelineAvailablePropertiesARM vkGetDataGraphPipelineAvailablePropertiesARM; +extern PFN_vkGetDataGraphPipelinePropertiesARM vkGetDataGraphPipelinePropertiesARM; +extern PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM vkGetDataGraphPipelineSessionBindPointRequirementsARM; +extern PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM vkGetDataGraphPipelineSessionMemoryRequirementsARM; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_tensors) +extern PFN_vkBindTensorMemoryARM vkBindTensorMemoryARM; +extern PFN_vkCmdCopyTensorARM vkCmdCopyTensorARM; +extern PFN_vkCreateTensorARM vkCreateTensorARM; +extern PFN_vkCreateTensorViewARM vkCreateTensorViewARM; +extern PFN_vkDestroyTensorARM vkDestroyTensorARM; +extern PFN_vkDestroyTensorViewARM vkDestroyTensorViewARM; +extern PFN_vkGetDeviceTensorMemoryRequirementsARM vkGetDeviceTensorMemoryRequirementsARM; +extern PFN_vkGetTensorMemoryRequirementsARM vkGetTensorMemoryRequirementsARM; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) +extern PFN_vkGetTensorOpaqueCaptureDescriptorDataARM vkGetTensorOpaqueCaptureDescriptorDataARM; +extern PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM vkGetTensorViewOpaqueCaptureDescriptorDataARM; +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ #if defined(VK_EXT_attachment_feedback_loop_dynamic_state) extern PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; #endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ @@ -1257,7 +2050,6 @@ extern PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; #endif /* defined(VK_EXT_buffer_device_address) */ #if defined(VK_EXT_calibrated_timestamps) extern PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; -extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; #endif /* defined(VK_EXT_calibrated_timestamps) */ #if defined(VK_EXT_color_write_enable) extern PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; @@ -1273,24 +2065,6 @@ extern PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsertEXT; extern PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; extern PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; #endif /* defined(VK_EXT_debug_marker) */ -#if defined(VK_EXT_debug_report) -extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; -extern PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT; -extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; -#endif /* defined(VK_EXT_debug_report) */ -#if defined(VK_EXT_debug_utils) -extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT; -extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT; -extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; -extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT; -extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT; -extern PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT; -extern PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT; -extern PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT; -extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; -extern PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; -extern PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; -#endif /* defined(VK_EXT_debug_utils) */ #if defined(VK_EXT_depth_bias_control) extern PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; #endif /* defined(VK_EXT_depth_bias_control) */ @@ -1312,13 +2086,17 @@ extern PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAcceler #if defined(VK_EXT_device_fault) extern PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; #endif /* defined(VK_EXT_device_fault) */ -#if defined(VK_EXT_direct_mode_display) -extern PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; -#endif /* defined(VK_EXT_direct_mode_display) */ -#if defined(VK_EXT_directfb_surface) -extern PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; -extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; -#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_device_generated_commands) +extern PFN_vkCmdExecuteGeneratedCommandsEXT vkCmdExecuteGeneratedCommandsEXT; +extern PFN_vkCmdPreprocessGeneratedCommandsEXT vkCmdPreprocessGeneratedCommandsEXT; +extern PFN_vkCreateIndirectCommandsLayoutEXT vkCreateIndirectCommandsLayoutEXT; +extern PFN_vkCreateIndirectExecutionSetEXT vkCreateIndirectExecutionSetEXT; +extern PFN_vkDestroyIndirectCommandsLayoutEXT vkDestroyIndirectCommandsLayoutEXT; +extern PFN_vkDestroyIndirectExecutionSetEXT vkDestroyIndirectExecutionSetEXT; +extern PFN_vkGetGeneratedCommandsMemoryRequirementsEXT vkGetGeneratedCommandsMemoryRequirementsEXT; +extern PFN_vkUpdateIndirectExecutionSetPipelineEXT vkUpdateIndirectExecutionSetPipelineEXT; +extern PFN_vkUpdateIndirectExecutionSetShaderEXT vkUpdateIndirectExecutionSetShaderEXT; +#endif /* defined(VK_EXT_device_generated_commands) */ #if defined(VK_EXT_discard_rectangles) extern PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ @@ -1332,23 +2110,26 @@ extern PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; extern PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; extern PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_display_surface_counter) -extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; -#endif /* defined(VK_EXT_display_surface_counter) */ #if defined(VK_EXT_external_memory_host) extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) +extern PFN_vkGetMemoryMetalHandleEXT vkGetMemoryMetalHandleEXT; +extern PFN_vkGetMemoryMetalHandlePropertiesEXT vkGetMemoryMetalHandlePropertiesEXT; +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) +extern PFN_vkCmdEndRendering2EXT vkCmdEndRendering2EXT; +#endif /* defined(VK_EXT_fragment_density_map_offset) */ #if defined(VK_EXT_full_screen_exclusive) extern PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; -extern PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; extern PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; #endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) +extern PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ #if defined(VK_EXT_hdr_metadata) extern PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #endif /* defined(VK_EXT_hdr_metadata) */ -#if defined(VK_EXT_headless_surface) -extern PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; -#endif /* defined(VK_EXT_headless_surface) */ #if defined(VK_EXT_host_image_copy) extern PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; extern PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; @@ -1366,15 +2147,14 @@ extern PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; #endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_mesh_shader) extern PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; -extern PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; extern PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; #endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +extern PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_EXT_metal_objects) extern PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; #endif /* defined(VK_EXT_metal_objects) */ -#if defined(VK_EXT_metal_surface) -extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; -#endif /* defined(VK_EXT_metal_surface) */ #if defined(VK_EXT_multi_draw) extern PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; extern PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; @@ -1409,7 +2189,6 @@ extern PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; #endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) extern PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; -extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; #endif /* defined(VK_EXT_sample_locations) */ #if defined(VK_EXT_shader_module_identifier) extern PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; @@ -1424,9 +2203,6 @@ extern PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; #if defined(VK_EXT_swapchain_maintenance1) extern PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; #endif /* defined(VK_EXT_swapchain_maintenance1) */ -#if defined(VK_EXT_tooling_info) -extern PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; -#endif /* defined(VK_EXT_tooling_info) */ #if defined(VK_EXT_transform_feedback) extern PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; extern PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; @@ -1456,12 +2232,6 @@ extern PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePrope extern PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; extern PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; #endif /* defined(VK_FUCHSIA_external_semaphore) */ -#if defined(VK_FUCHSIA_imagepipe_surface) -extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; -#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ -#if defined(VK_GGP_stream_descriptor_surface) -extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; -#endif /* defined(VK_GGP_stream_descriptor_surface) */ #if defined(VK_GOOGLE_display_timing) extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; @@ -1473,9 +2243,11 @@ extern PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; #if defined(VK_HUAWEI_invocation_mask) extern PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 +extern PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ #if defined(VK_HUAWEI_subpass_shading) extern PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; -extern PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; #endif /* defined(VK_HUAWEI_subpass_shading) */ #if defined(VK_INTEL_performance_query) extern PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; @@ -1506,9 +2278,6 @@ extern PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructure extern PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; extern PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; #endif /* defined(VK_KHR_acceleration_structure) */ -#if defined(VK_KHR_android_surface) -extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; -#endif /* defined(VK_KHR_android_surface) */ #if defined(VK_KHR_bind_memory2) extern PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; extern PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; @@ -1520,11 +2289,7 @@ extern PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptu #endif /* defined(VK_KHR_buffer_device_address) */ #if defined(VK_KHR_calibrated_timestamps) extern PFN_vkGetCalibratedTimestampsKHR vkGetCalibratedTimestampsKHR; -extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR vkGetPhysicalDeviceCalibrateableTimeDomainsKHR; #endif /* defined(VK_KHR_calibrated_timestamps) */ -#if defined(VK_KHR_cooperative_matrix) -extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; -#endif /* defined(VK_KHR_cooperative_matrix) */ #if defined(VK_KHR_copy_commands2) extern PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; extern PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; @@ -1533,6 +2298,10 @@ extern PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; extern PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; extern PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; #endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) +extern PFN_vkCmdCopyMemoryIndirectKHR vkCmdCopyMemoryIndirectKHR; +extern PFN_vkCmdCopyMemoryToImageIndirectKHR vkCmdCopyMemoryToImageIndirectKHR; +#endif /* defined(VK_KHR_copy_memory_indirect) */ #if defined(VK_KHR_create_renderpass2) extern PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; extern PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; @@ -1556,18 +2325,6 @@ extern PFN_vkCmdDispatchBaseKHR vkCmdDispatchBaseKHR; extern PFN_vkCmdSetDeviceMaskKHR vkCmdSetDeviceMaskKHR; extern PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR; #endif /* defined(VK_KHR_device_group) */ -#if defined(VK_KHR_device_group_creation) -extern PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR; -#endif /* defined(VK_KHR_device_group_creation) */ -#if defined(VK_KHR_display) -extern PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; -extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; -extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; -extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; -extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; -extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; -extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; -#endif /* defined(VK_KHR_display) */ #if defined(VK_KHR_display_swapchain) extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; #endif /* defined(VK_KHR_display_swapchain) */ @@ -1583,9 +2340,6 @@ extern PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; extern PFN_vkCmdSetRenderingAttachmentLocationsKHR vkCmdSetRenderingAttachmentLocationsKHR; extern PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAttachmentIndicesKHR; #endif /* defined(VK_KHR_dynamic_rendering_local_read) */ -#if defined(VK_KHR_external_fence_capabilities) -extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; -#endif /* defined(VK_KHR_external_fence_capabilities) */ #if defined(VK_KHR_external_fence_fd) extern PFN_vkGetFenceFdKHR vkGetFenceFdKHR; extern PFN_vkImportFenceFdKHR vkImportFenceFdKHR; @@ -1594,9 +2348,6 @@ extern PFN_vkImportFenceFdKHR vkImportFenceFdKHR; extern PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR; extern PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR; #endif /* defined(VK_KHR_external_fence_win32) */ -#if defined(VK_KHR_external_memory_capabilities) -extern PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; -#endif /* defined(VK_KHR_external_memory_capabilities) */ #if defined(VK_KHR_external_memory_fd) extern PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; extern PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; @@ -1605,9 +2356,6 @@ extern PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; extern PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR; extern PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR; #endif /* defined(VK_KHR_external_memory_win32) */ -#if defined(VK_KHR_external_semaphore_capabilities) -extern PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR; -#endif /* defined(VK_KHR_external_semaphore_capabilities) */ #if defined(VK_KHR_external_semaphore_fd) extern PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; @@ -1618,32 +2366,12 @@ extern PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; #endif /* defined(VK_KHR_external_semaphore_win32) */ #if defined(VK_KHR_fragment_shading_rate) extern PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; -extern PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; #endif /* defined(VK_KHR_fragment_shading_rate) */ -#if defined(VK_KHR_get_display_properties2) -extern PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; -extern PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; -extern PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR vkGetPhysicalDeviceDisplayPlaneProperties2KHR; -extern PFN_vkGetPhysicalDeviceDisplayProperties2KHR vkGetPhysicalDeviceDisplayProperties2KHR; -#endif /* defined(VK_KHR_get_display_properties2) */ #if defined(VK_KHR_get_memory_requirements2) extern PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; extern PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; extern PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR; #endif /* defined(VK_KHR_get_memory_requirements2) */ -#if defined(VK_KHR_get_physical_device_properties2) -extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; -extern PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; -extern PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR; -extern PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; -extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; -extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; -extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR; -#endif /* defined(VK_KHR_get_physical_device_properties2) */ -#if defined(VK_KHR_get_surface_capabilities2) -extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; -extern PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR; -#endif /* defined(VK_KHR_get_surface_capabilities2) */ #if defined(VK_KHR_line_rasterization) extern PFN_vkCmdSetLineStippleKHR vkCmdSetLineStippleKHR; #endif /* defined(VK_KHR_line_rasterization) */ @@ -1682,10 +2410,15 @@ extern PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; #endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; -extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; -extern PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; extern PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; #endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) +extern PFN_vkCreatePipelineBinariesKHR vkCreatePipelineBinariesKHR; +extern PFN_vkDestroyPipelineBinaryKHR vkDestroyPipelineBinaryKHR; +extern PFN_vkGetPipelineBinaryDataKHR vkGetPipelineBinaryDataKHR; +extern PFN_vkGetPipelineKeyKHR vkGetPipelineKeyKHR; +extern PFN_vkReleaseCapturedPipelineDataKHR vkReleaseCapturedPipelineDataKHR; +#endif /* defined(VK_KHR_pipeline_binary) */ #if defined(VK_KHR_pipeline_executable_properties) extern PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; extern PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; @@ -1694,6 +2427,9 @@ extern PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatistic #if defined(VK_KHR_present_wait) extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR; #endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) +extern PFN_vkWaitForPresent2KHR vkWaitForPresent2KHR; +#endif /* defined(VK_KHR_present_wait2) */ #if defined(VK_KHR_push_descriptor) extern PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ @@ -1716,13 +2452,6 @@ extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR #if defined(VK_KHR_shared_presentable_image) extern PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR; #endif /* defined(VK_KHR_shared_presentable_image) */ -#if defined(VK_KHR_surface) -extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; -extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; -extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; -extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; -extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; -#endif /* defined(VK_KHR_surface) */ #if defined(VK_KHR_swapchain) extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; extern PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; @@ -1730,6 +2459,9 @@ extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; extern PFN_vkQueuePresentKHR vkQueuePresentKHR; #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) +extern PFN_vkReleaseSwapchainImagesKHR vkReleaseSwapchainImagesKHR; +#endif /* defined(VK_KHR_swapchain_maintenance1) */ #if defined(VK_KHR_synchronization2) extern PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; extern PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; @@ -1738,12 +2470,6 @@ extern PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; extern PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; extern PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; #endif /* defined(VK_KHR_synchronization2) */ -#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) -extern PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; -#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ -#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) -extern PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; -#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ #if defined(VK_KHR_timeline_semaphore) extern PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; extern PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; @@ -1755,7 +2481,6 @@ extern PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; #if defined(VK_KHR_video_encode_queue) extern PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; extern PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; -extern PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) extern PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; @@ -1766,36 +2491,9 @@ extern PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; extern PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; extern PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; extern PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; -extern PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; -extern PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; extern PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; extern PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; #endif /* defined(VK_KHR_video_queue) */ -#if defined(VK_KHR_wayland_surface) -extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; -extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; -#endif /* defined(VK_KHR_wayland_surface) */ -#if defined(VK_KHR_win32_surface) -extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; -extern PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; -#endif /* defined(VK_KHR_win32_surface) */ -#if defined(VK_KHR_xcb_surface) -extern PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; -extern PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; -#endif /* defined(VK_KHR_xcb_surface) */ -#if defined(VK_KHR_xlib_surface) -extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; -extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; -#endif /* defined(VK_KHR_xlib_surface) */ -#if defined(VK_MVK_ios_surface) -extern PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK; -#endif /* defined(VK_MVK_ios_surface) */ -#if defined(VK_MVK_macos_surface) -extern PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; -#endif /* defined(VK_MVK_macos_surface) */ -#if defined(VK_NN_vi_surface) -extern PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; -#endif /* defined(VK_NN_vi_surface) */ #if defined(VK_NVX_binary_import) extern PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; extern PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; @@ -1804,26 +2502,29 @@ extern PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; extern PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; #endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) -extern PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; extern PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; #endif /* defined(VK_NVX_image_view_handle) */ -#if defined(VK_NV_acquire_winrt_display) -extern PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; -extern PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; -#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 +extern PFN_vkGetImageViewHandle64NVX vkGetImageViewHandle64NVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 +extern PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ #if defined(VK_NV_clip_space_w_scaling) extern PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #endif /* defined(VK_NV_clip_space_w_scaling) */ -#if defined(VK_NV_cooperative_matrix) -extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; -#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cluster_acceleration_structure) +extern PFN_vkCmdBuildClusterAccelerationStructureIndirectNV vkCmdBuildClusterAccelerationStructureIndirectNV; +extern PFN_vkGetClusterAccelerationStructureBuildSizesNV vkGetClusterAccelerationStructureBuildSizesNV; +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_cooperative_vector) +extern PFN_vkCmdConvertCooperativeVectorMatrixNV vkCmdConvertCooperativeVectorMatrixNV; +extern PFN_vkConvertCooperativeVectorMatrixNV vkConvertCooperativeVectorMatrixNV; +#endif /* defined(VK_NV_cooperative_vector) */ #if defined(VK_NV_copy_memory_indirect) extern PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; extern PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; #endif /* defined(VK_NV_copy_memory_indirect) */ -#if defined(VK_NV_coverage_reduction_mode) -extern PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; -#endif /* defined(VK_NV_coverage_reduction_mode) */ #if defined(VK_NV_cuda_kernel_launch) extern PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; extern PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; @@ -1836,6 +2537,9 @@ extern PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; extern PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; extern PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +extern PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ #if defined(VK_NV_device_generated_commands) extern PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; extern PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; @@ -1849,9 +2553,11 @@ extern PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBuffer extern PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; extern PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; #endif /* defined(VK_NV_device_generated_commands_compute) */ -#if defined(VK_NV_external_memory_capabilities) -extern PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; -#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_external_compute_queue) +extern PFN_vkCreateExternalComputeQueueNV vkCreateExternalComputeQueueNV; +extern PFN_vkDestroyExternalComputeQueueNV vkDestroyExternalComputeQueueNV; +extern PFN_vkGetExternalComputeQueueDataNV vkGetExternalComputeQueueDataNV; +#endif /* defined(VK_NV_external_compute_queue) */ #if defined(VK_NV_external_memory_rdma) extern PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; #endif /* defined(VK_NV_external_memory_rdma) */ @@ -1873,17 +2579,22 @@ extern PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCou extern PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; #endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) -extern PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; extern PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; extern PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +extern PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ #if defined(VK_NV_optical_flow) extern PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; extern PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; extern PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; extern PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; -extern PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; #endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) +extern PFN_vkCmdBuildPartitionedAccelerationStructuresNV vkCmdBuildPartitionedAccelerationStructuresNV; +extern PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV vkGetPartitionedAccelerationStructuresBuildSizesNV; +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ #if defined(VK_NV_ray_tracing) extern PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; extern PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; @@ -1909,21 +2620,28 @@ extern PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; extern PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; extern PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_memory_heap) +extern PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; +#endif /* defined(VK_QCOM_tile_memory_heap) */ #if defined(VK_QCOM_tile_properties) extern PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; extern PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; #endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) +extern PFN_vkCmdBeginPerTileExecutionQCOM vkCmdBeginPerTileExecutionQCOM; +extern PFN_vkCmdDispatchTileQCOM vkCmdDispatchTileQCOM; +extern PFN_vkCmdEndPerTileExecutionQCOM vkCmdEndPerTileExecutionQCOM; +#endif /* defined(VK_QCOM_tile_shading) */ #if defined(VK_QNX_external_memory_screen_buffer) extern PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; #endif /* defined(VK_QNX_external_memory_screen_buffer) */ -#if defined(VK_QNX_screen_surface) -extern PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; -extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; -#endif /* defined(VK_QNX_screen_surface) */ #if defined(VK_VALVE_descriptor_set_host_mapping) extern PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; extern PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) +extern PFN_vkCmdSetDepthClampRangeEXT vkCmdSetDepthClampRangeEXT; +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ #if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; @@ -2010,34 +2728,35 @@ extern PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFrag #if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) extern PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; #endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ -#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) -extern PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; -#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ #if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) extern PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; #endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ #if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; #endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) extern PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; -#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) extern PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; extern PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; -extern PFN_vkGetPhysicalDevicePresentRectanglesKHR vkGetPhysicalDevicePresentRectanglesKHR; #endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; #endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ -/* VOLK_GENERATE_PROTOTYPES_H */ +/* VOLK_GENERATE_PROTOTYPES_H_DEVICE */ +#endif #ifdef __cplusplus -} +} // extern "C" / namespace volk #endif +#ifdef VOLK_NAMESPACE +using namespace volk; #endif +#endif // VOLK_H + #ifdef VOLK_IMPLEMENTATION #undef VOLK_IMPLEMENTATION /* Prevent tools like dependency checkers from detecting a cyclic dependency */ @@ -2046,7 +2765,7 @@ extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; #endif /** - * Copyright (c) 2018-2024 Arseny Kapoulkine + * Copyright (c) 2018-2025 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/testing b/testing index 8a57c900f44..5c4e0257bbf 160000 --- a/testing +++ b/testing @@ -1 +1 @@ -Subproject commit 8a57c900f440d8296314771517e8a02f26b93e17 +Subproject commit 5c4e0257bbfadfdb0bb2d09d0f4a7e866aad1e2d diff --git a/third_party/EGL-Registry/README.chromium b/third_party/EGL-Registry/README.chromium index 67086d56460..90b80b61ed6 100644 --- a/third_party/EGL-Registry/README.chromium +++ b/third_party/EGL-Registry/README.chromium @@ -2,8 +2,8 @@ Name: Khronos EGL API and Extension Registry Short Name: EGL-Registry Version: N/A URL: https://github.com/KhronosGroup/EGL-Registry -SOURCE CODE: git clone -b EGL-Registry https://github.com/KhronosGroup/EGL-Registry Revision: DEPS +Update Mechanism: Manual Security Critical: no Shipped: yes License: Apache-2.0 diff --git a/third_party/OpenCL-CTS/gn/BUILD.gn b/third_party/OpenCL-CTS/gn/BUILD.gn index fa1c5bcf628..37563668457 100644 --- a/third_party/OpenCL-CTS/gn/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/BUILD.gn @@ -25,6 +25,14 @@ source_set("test_common") { ] defines = [ "CL_TARGET_OPENCL_VERSION=300" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_2_2_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_2_1_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_2_0_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_1_2_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_1_1_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_1_0_APIS=1" ] + defines += [ "CL_NO_EXTENSION_PROTOTYPES" ] + defines += [ "CL_ENABLE_BETA_EXTENSIONS" ] sources = [ "$angle_root/third_party/OpenCL-CTS/src/test_common/harness/ThreadPool.cpp", diff --git a/third_party/OpenCL-CTS/gn/angle_ocl_cts.gni b/third_party/OpenCL-CTS/gn/angle_ocl_cts.gni index 4184dec7874..f270d52381d 100644 --- a/third_party/OpenCL-CTS/gn/angle_ocl_cts.gni +++ b/third_party/OpenCL-CTS/gn/angle_ocl_cts.gni @@ -15,6 +15,14 @@ template("ocl_cts_source_set") { "-Wno-c++11-narrowing", ] defines = [ "CL_TARGET_OPENCL_VERSION=300" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_2_2_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_2_1_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_2_0_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_1_2_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_1_1_APIS=1" ] + defines += [ "CL_USE_DEPRECATED_OPENCL_1_0_APIS=1" ] + defines += [ "CL_NO_EXTENSION_PROTOTYPES" ] + defines += [ "CL_ENABLE_BETA_EXTENSIONS" ] # Rename main() to avoid conflict with the gtest-based main() defines += [ "main=ANGLE_oclcts_main" ] diff --git a/third_party/OpenCL-CTS/gn/api/BUILD.gn b/third_party/OpenCL-CTS/gn/api/BUILD.gn index e725fa64a7c..07eb3d8475b 100644 --- a/third_party/OpenCL-CTS/gn/api/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/api/BUILD.gn @@ -41,6 +41,7 @@ ocl_cts_source_set("api") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/api/test_retain.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/api/test_retain_program.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/api/test_sub_group_dispatch.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/api/test_wg_suggested_local_work_size.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/api/test_zero_sized_enqueue.cpp", ] } diff --git a/third_party/OpenCL-CTS/gn/basic/BUILD.gn b/third_party/OpenCL-CTS/gn/basic/BUILD.gn index ddd15cce981..fdc5d4f48cc 100644 --- a/third_party/OpenCL-CTS/gn/basic/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/basic/BUILD.gn @@ -38,7 +38,6 @@ ocl_cts_source_set("basic") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_image_param.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_image_r8.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_imagearraycopy.cpp", - "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_imagearraycopy3d.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_imagecopy.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_imagecopy3d.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/basic/test_imagedim.cpp", diff --git a/third_party/OpenCL-CTS/gn/images/clCopyImage/BUILD.gn b/third_party/OpenCL-CTS/gn/images/clCopyImage/BUILD.gn index c5fc4948338..34cbfc4242b 100644 --- a/third_party/OpenCL-CTS/gn/images/clCopyImage/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/images/clCopyImage/BUILD.gn @@ -14,6 +14,7 @@ ocl_cts_source_set("cl_copy_images") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/test_copy_1D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/test_copy_1D_array.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/test_copy_1D_buffer.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/test_copy_2D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/test_copy_2D_2D_array.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clCopyImage/test_copy_2D_3D.cpp", diff --git a/third_party/OpenCL-CTS/gn/images/clFillImage/BUILD.gn b/third_party/OpenCL-CTS/gn/images/clFillImage/BUILD.gn index f57a8e4cc63..1f8a357d615 100644 --- a/third_party/OpenCL-CTS/gn/images/clFillImage/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/images/clFillImage/BUILD.gn @@ -14,6 +14,7 @@ ocl_cts_source_set("cl_fill_images") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/test_fill_1D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/test_fill_1D_array.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/test_fill_1D_buffer.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/test_fill_2D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/test_fill_2D_array.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clFillImage/test_fill_3D.cpp", diff --git a/third_party/OpenCL-CTS/gn/images/clGetInfo/BUILD.gn b/third_party/OpenCL-CTS/gn/images/clGetInfo/BUILD.gn index 892f3fe5cce..a96f527b563 100644 --- a/third_party/OpenCL-CTS/gn/images/clGetInfo/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/images/clGetInfo/BUILD.gn @@ -14,6 +14,7 @@ ocl_cts_source_set("cl_get_info") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/test_1D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/test_1D_2D_array.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/test_1D_buffer.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/test_2D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/test_3D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clGetInfo/test_loops.cpp", diff --git a/third_party/OpenCL-CTS/gn/images/clReadWriteImage/BUILD.gn b/third_party/OpenCL-CTS/gn/images/clReadWriteImage/BUILD.gn index 5cfe4a5f777..60b6e7660a9 100644 --- a/third_party/OpenCL-CTS/gn/images/clReadWriteImage/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/images/clReadWriteImage/BUILD.gn @@ -15,6 +15,7 @@ ocl_cts_source_set("cl_read_write_images") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_loops.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_read_1D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_read_1D_array.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_read_1D_buffer.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_read_2D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_read_2D_array.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/clReadWriteImage/test_read_3D.cpp", diff --git a/third_party/OpenCL-CTS/gn/images/kernel_image_methods/BUILD.gn b/third_party/OpenCL-CTS/gn/images/kernel_image_methods/BUILD.gn index 89285d7cade..fba83b66083 100644 --- a/third_party/OpenCL-CTS/gn/images/kernel_image_methods/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/images/kernel_image_methods/BUILD.gn @@ -15,6 +15,7 @@ ocl_cts_source_set("kernel_image_methods") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/test_1D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/test_1D_array.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/test_1D_buffer.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/test_2D.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/test_2D_array.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_image_methods/test_3D.cpp", diff --git a/third_party/OpenCL-CTS/gn/images/kernel_read_write/BUILD.gn b/third_party/OpenCL-CTS/gn/images/kernel_read_write/BUILD.gn index cd9ee16f3ef..2445dcbcf2f 100644 --- a/third_party/OpenCL-CTS/gn/images/kernel_read_write/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/images/kernel_read_write/BUILD.gn @@ -14,6 +14,7 @@ ocl_cts_source_set("image_streams") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/common.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_read_write/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_read_write/test_cl_ext_image_from_buffer.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_read_write/test_cl_ext_image_raw10_raw12.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_read_write/test_cl_ext_image_requirements_info.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_read_write/test_common.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/images/kernel_read_write/test_iterations.cpp", diff --git a/third_party/OpenCL-CTS/gn/math_brute_force/BUILD.gn b/third_party/OpenCL-CTS/gn/math_brute_force/BUILD.gn index 358668592cf..eb8b3454c66 100644 --- a/third_party/OpenCL-CTS/gn/math_brute_force/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/math_brute_force/BUILD.gn @@ -11,35 +11,48 @@ ocl_cts_source_set("bruteforce") { sources = [ "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_i_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_i_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_i_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_operator_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_operator_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_operator_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_two_results_i_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_two_results_i_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/binary_two_results_i_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/common.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/function_list.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/i_unary_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/i_unary_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/i_unary_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/macro_binary_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/macro_binary_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/macro_binary_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/macro_unary_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/macro_unary_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/macro_unary_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/mad_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/mad_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/mad_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/reference_math.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/sleep.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/ternary_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/ternary_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/ternary_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_two_results_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_two_results_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_two_results_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_two_results_i_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_two_results_i_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_two_results_i_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_u_double.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_u_float.cpp", + "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/unary_u_half.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/utility.cpp", ] } diff --git a/third_party/OpenCL-CTS/gn/spirv_new/BUILD.gn b/third_party/OpenCL-CTS/gn/spirv_new/BUILD.gn index 74866aa5f5b..f9965d578f2 100644 --- a/third_party/OpenCL-CTS/gn/spirv_new/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/spirv_new/BUILD.gn @@ -12,7 +12,6 @@ ocl_cts_source_set("spirv_new") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/math_brute_force/utility.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/spirv_new/main.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/spirv_new/test_basic_versions.cpp", - "$angle_root/third_party/OpenCL-CTS/src/test_conformance/spirv_new/test_cl_khr_spirv_no_integer_wrap_decoration.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/spirv_new/test_decorate.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/spirv_new/test_get_program_il.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/spirv_new/test_linkage.cpp", diff --git a/third_party/OpenCL-CTS/gn/workgroups/BUILD.gn b/third_party/OpenCL-CTS/gn/workgroups/BUILD.gn index c36c4e653d8..b3bc37e6159 100644 --- a/third_party/OpenCL-CTS/gn/workgroups/BUILD.gn +++ b/third_party/OpenCL-CTS/gn/workgroups/BUILD.gn @@ -13,6 +13,5 @@ ocl_cts_source_set("workgroups") { "$angle_root/third_party/OpenCL-CTS/src/test_conformance/workgroups/test_wg_any.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/workgroups/test_wg_broadcast.cpp", "$angle_root/third_party/OpenCL-CTS/src/test_conformance/workgroups/test_wg_scan_reduce.cpp", - "$angle_root/third_party/OpenCL-CTS/src/test_conformance/workgroups/test_wg_suggested_local_work_size.cpp", ] } diff --git a/third_party/OpenCL-CTS/src b/third_party/OpenCL-CTS/src index e0a31a03fc8..9fc0d23b4cf 160000 --- a/third_party/OpenCL-CTS/src +++ b/third_party/OpenCL-CTS/src @@ -1 +1 @@ -Subproject commit e0a31a03fc8f816d59fd8b3051ac6a61d3fa50c6 +Subproject commit 9fc0d23b4cfccd84be8927363a77107dc554de30 diff --git a/third_party/OpenCL-Docs/README.chromium b/third_party/OpenCL-Docs/README.chromium index b424f108520..0e884f043ce 100644 --- a/third_party/OpenCL-Docs/README.chromium +++ b/third_party/OpenCL-Docs/README.chromium @@ -2,11 +2,11 @@ Name: Khronos OpenCL API, OpenCL C, Extensions, SPIR-V Environment Specs, Ref pa Short Name: OpenCL-Docs Version: N/A URL: https://github.com/KhronosGroup/OpenCL-Docs -SOURCE CODE: git clone -b OpenCL-Docs https://github.com/KhronosGroup/OpenCL-Docs Revision: DEPS +Update Mechanism: Manual Security Critical: no Shipped: yes -License: Apache 2.0 +License: Apache-2.0 License File: Not Included Description: diff --git a/third_party/OpenCL-Docs/src b/third_party/OpenCL-Docs/src index 774114e8761..5b4ca15f0e5 160000 --- a/third_party/OpenCL-Docs/src +++ b/third_party/OpenCL-Docs/src @@ -1 +1 @@ -Subproject commit 774114e8761920b976d538d47fad8178d05984ec +Subproject commit 5b4ca15f0e5a5be87b56b99f652f728e05cab587 diff --git a/third_party/OpenCL-ICD-Loader/BUILD.gn b/third_party/OpenCL-ICD-Loader/BUILD.gn index a04032369ed..07db50a06d7 100644 --- a/third_party/OpenCL-ICD-Loader/BUILD.gn +++ b/third_party/OpenCL-ICD-Loader/BUILD.gn @@ -6,6 +6,7 @@ import("//gni/angle.gni") config("opencl_icd_loader_config") { include_dirs = [ "src/loader" ] + include_dirs += [ "src/include" ] } source_set("opencl_icd_loader") { @@ -16,13 +17,16 @@ source_set("opencl_icd_loader") { ] defines = [ "CL_TARGET_OPENCL_VERSION=300", - "OPENCL_ICD_LOADER_DISABLE_OPENCLON12", + "CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES", + "OPENCL_ICD_LOADER_VERSION_MAJOR=3", + "OPENCL_ICD_LOADER_VERSION_MINOR=0", + "OPENCL_ICD_LOADER_VERSION_REV=7", ] if (is_win) { sources += [ "src/loader/windows/icd_windows.c", - "src/loader/windows/icd_windows_apppackage.cpp", + "src/loader/windows/icd_windows_apppackage.c", "src/loader/windows/icd_windows_dxgk.c", "src/loader/windows/icd_windows_envvars.c", "src/loader/windows/icd_windows_hkr.c", diff --git a/third_party/OpenCL-ICD-Loader/README.chromium b/third_party/OpenCL-ICD-Loader/README.chromium index 68692b22f31..c878015a74e 100644 --- a/third_party/OpenCL-ICD-Loader/README.chromium +++ b/third_party/OpenCL-ICD-Loader/README.chromium @@ -1,16 +1,17 @@ Name: Khronos OpenCL ICD Loader Short Name: OpenCL-ICD-Loader Version: v2021.04.29 -URL: https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenCL-ICD-Loader -SOURCE CODE: git clone -b OpenCL-ICD-Loader https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenCL-ICD-Loader +URL: https://github.com/KhronosGroup/OpenCL-ICD-Loader Date: 2021-04-29 Revision: 9b5e3849b49a1448996c8b96ba086cd774d987db +Update Mechanism: Manual Security Critical: no Shipped: yes -License: Apache 2.0 +License: Apache-2.0 License File: LICENSE Description: + OpenCL defines an Installable Client Driver (ICD) mechanism to allow developers to build applications against an Installable Client Driver loader (ICD loader) rather than linking their applications against a specific OpenCL implementation. diff --git a/third_party/OpenCL-ICD-Loader/src b/third_party/OpenCL-ICD-Loader/src index 9b5e3849b49..ddf6c70230a 160000 --- a/third_party/OpenCL-ICD-Loader/src +++ b/third_party/OpenCL-ICD-Loader/src @@ -1 +1 @@ -Subproject commit 9b5e3849b49a1448996c8b96ba086cd774d987db +Subproject commit ddf6c70230a79cdb8fcccfd3c775b09e6820f42e diff --git a/third_party/OpenGL-Registry/README.chromium b/third_party/OpenGL-Registry/README.chromium index 6690c453976..908bd99c68c 100644 --- a/third_party/OpenGL-Registry/README.chromium +++ b/third_party/OpenGL-Registry/README.chromium @@ -2,11 +2,11 @@ Name: Khronos OpenGL, OpenGL ES, and OpenGL ES-SC API and Extension Registry Short Name: OpenGL-Registry Version: N/A URL: https://github.com/KhronosGroup/OpenGL-Registry -SOURCE CODE: git clone -b OpenGL-Registry https://github.com/KhronosGroup/OpenGL-Registry Revision: DEPS +Update Mechanism: Manual Security Critical: no Shipped: yes -License: Apache 2.0 +License: Apache-2.0 License File: Not Included Description: diff --git a/third_party/OpenGL-Registry/src b/third_party/OpenGL-Registry/src index 5bae8738b23..d38ff693f3e 160000 --- a/third_party/OpenGL-Registry/src +++ b/third_party/OpenGL-Registry/src @@ -1 +1 @@ -Subproject commit 5bae8738b23d06968e7c3a41308568120943ae77 +Subproject commit d38ff693f3e99ac5a61e3858de76c6c02976fa67 diff --git a/third_party/SwiftShader b/third_party/SwiftShader index 720189cae84..374652a342e 160000 --- a/third_party/SwiftShader +++ b/third_party/SwiftShader @@ -1 +1 @@ -Subproject commit 720189cae8478484f51531a9eed9abc6d8635271 +Subproject commit 374652a342e0e8f5bc82df06e520ce6acb1c969d diff --git a/third_party/VK-GL-CTS/README.chromium b/third_party/VK-GL-CTS/README.chromium index b8124c7c2ee..a3c964a451a 100644 --- a/third_party/VK-GL-CTS/README.chromium +++ b/third_party/VK-GL-CTS/README.chromium @@ -1,16 +1,17 @@ Name: Khronos dEQP / CTS Short Name: VK-GL-CTS -Version: 1.0 -URL: https://chromium.googlesource.com/external/github.com/KhronosGroup/VK-GL-CTS -SOURCE CODE: git clone -b VK-GL-CTS https://chromium.googlesource.com/external/github.com/KhronosGroup/VK-GL-CTS +Version: N/A +URL: https://github.com/KhronosGroup/VK-GL-CTS Date: 2016-06-20 Revision: f4f3d8079e7a37d7675ab93583e6438d0bca0e58 +Update Mechanism: Autoroll Security Critical: no Shipped: no -License: Apache 2.0 +License: Apache-2.0 License File: LICENSE Description: + VK-GL-CTS (formally dEQP) is a set of tests and testing tools for GPUs and their drivers. It currently supports OpenGL ES 2.0 - 3.1 & AEP, EGL and Vulkan (though ANGLE only uses the GLES pieces). The dEQP has been part of the Android CTS since the L release. diff --git a/third_party/VK-GL-CTS/src b/third_party/VK-GL-CTS/src index 69ec1790cb7..9ef5ffd652c 160000 --- a/third_party/VK-GL-CTS/src +++ b/third_party/VK-GL-CTS/src @@ -1 +1 @@ -Subproject commit 69ec1790cb7c1b72a758a3562aa4e511caaef780 +Subproject commit 9ef5ffd652cb39797f17321899d3d100bcf4ce08 diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp index 9d07d51c6ee..6d5ac0f7d3f 160000 --- a/third_party/abseil-cpp +++ b/third_party/abseil-cpp @@ -1 +1 @@ -Subproject commit 9d07d51c6ee92333a9f86acef20acadf9f5d9a89 +Subproject commit 6d5ac0f7d3f0af5d13b78044fc31c793aa3549f8 diff --git a/third_party/android_build_tools b/third_party/android_build_tools index 3539c64cce0..6806b500844 160000 --- a/third_party/android_build_tools +++ b/third_party/android_build_tools @@ -1 +1 @@ -Subproject commit 3539c64cce01b0bad61eb21757d3f9822a242eef +Subproject commit 6806b5008448cdb1d9f10d5fc9737774dfc65867 diff --git a/third_party/android_deps b/third_party/android_deps index e531e949913..c2ef7a5a664 160000 --- a/third_party/android_deps +++ b/third_party/android_deps @@ -1 +1 @@ -Subproject commit e531e9499137b325a289bbd67b0e5c66d9ce3b5b +Subproject commit c2ef7a5a6647277a9c53c4b9e0c8403fe059723b diff --git a/third_party/android_platform b/third_party/android_platform index e96dafd97e0..e3919359f23 160000 --- a/third_party/android_platform +++ b/third_party/android_platform @@ -1 +1 @@ -Subproject commit e96dafd97e013cc44ee83d9d3d5d322a1356c6ca +Subproject commit e3919359f2387399042d31401817db4a02d756ec diff --git a/third_party/android_sdk b/third_party/android_sdk index 16e84167911..3af3898c673 160000 --- a/third_party/android_sdk +++ b/third_party/android_sdk @@ -1 +1 @@ -Subproject commit 16e8416791134998bf4e060ce9cbe7f94b66d432 +Subproject commit 3af3898c67301201301f834693ff44326174ecea diff --git a/third_party/android_system_sdk/README.chromium b/third_party/android_system_sdk/README.chromium index b5b8ff959f3..ea9755dcfb4 100644 --- a/third_party/android_system_sdk/README.chromium +++ b/third_party/android_system_sdk/README.chromium @@ -2,6 +2,7 @@ Name: Android System SDK URL: https://android.googlesource.com/platform/frameworks/base Short Name: Android System SDK Version: AP31.240517.022 +Update Mechanism: Manual License: GPL-2.0-with-classpath-exception License File: LICENSE Security Critical: No diff --git a/third_party/astc-encoder/BUILD.gn b/third_party/astc-encoder/BUILD.gn index a421acce7c7..6a9799e4b0c 100644 --- a/third_party/astc-encoder/BUILD.gn +++ b/third_party/astc-encoder/BUILD.gn @@ -22,13 +22,13 @@ source_set("astcenc") { "src/Source/astcenc_image.cpp", "src/Source/astcenc_integer_sequence.cpp", "src/Source/astcenc_internal.h", + "src/Source/astcenc_internal_entry.h", "src/Source/astcenc_mathlib.cpp", "src/Source/astcenc_mathlib.h", "src/Source/astcenc_mathlib_softfloat.cpp", "src/Source/astcenc_partition_tables.cpp", "src/Source/astcenc_percentile_tables.cpp", "src/Source/astcenc_pick_best_endpoint_format.cpp", - "src/Source/astcenc_platform_isa_detection.cpp", "src/Source/astcenc_quantization.cpp", "src/Source/astcenc_symbolic_physical.cpp", "src/Source/astcenc_vecmathlib.h", diff --git a/third_party/astc-encoder/README.chromium b/third_party/astc-encoder/README.chromium index e59ff2e1fdd..e084f639daf 100644 --- a/third_party/astc-encoder/README.chromium +++ b/third_party/astc-encoder/README.chromium @@ -1,7 +1,9 @@ Name: astc-encoder Short Name: astc-encoder URL: https://github.com/ARM-software/astc-encoder -Version: 573c475389bf51d16a5c3fc8348092e094e50e8f +Version: N/A +Revision: 2319d9c4d4af53a7fc7c52985e264ce6e8a02a9b +Update Mechanism: Manual Security Critical: no Shipped: yes License: Apache-2.0 diff --git a/third_party/astc-encoder/src b/third_party/astc-encoder/src index 573c475389b..2319d9c4d4a 160000 --- a/third_party/astc-encoder/src +++ b/third_party/astc-encoder/src @@ -1 +1 @@ -Subproject commit 573c475389bf51d16a5c3fc8348092e094e50e8f +Subproject commit 2319d9c4d4af53a7fc7c52985e264ce6e8a02a9b diff --git a/third_party/bazel/README.chromium b/third_party/bazel/README.chromium index dac8f542f01..6e1f9add016 100644 --- a/third_party/bazel/README.chromium +++ b/third_party/bazel/README.chromium @@ -5,6 +5,7 @@ License: Apache-2.0 License File: LICENSE Version: N/A Revision: DEPS +Update Mechanism: Manual Security Critical: no Shipped: no @@ -12,4 +13,3 @@ Description: This directory contains Bazel components used for building Android binaries. Chromium does not use Bazel itself as the build platform. Please refer to each sub-directory for information on each Bazel component. - diff --git a/third_party/bazel/desugar/README.chromium b/third_party/bazel/desugar/README.chromium index 4f00b271eed..14c24d6a19f 100644 --- a/third_party/bazel/desugar/README.chromium +++ b/third_party/bazel/desugar/README.chromium @@ -2,7 +2,8 @@ Name: Desugar, transforming Java 8 bytecode to be Java 7 compatible Short Name: desugar URL: https://github.com/bazelbuild/bazel Version: 1.1.0 -License: Apache 2.0 +Update Mechanism: Manual +License: Apache-2.0 Security Critical: no Shipped: yes diff --git a/third_party/catapult b/third_party/catapult index d5166861902..145e14f52fa 160000 --- a/third_party/catapult +++ b/third_party/catapult @@ -1 +1 @@ -Subproject commit d5166861902b565df446e15181eba270fe168275 +Subproject commit 145e14f52facfa0b5a34cca92b22dade15943a0c diff --git a/third_party/clang-format/script b/third_party/clang-format/script index 37f6e68a107..c2725e0622e 160000 --- a/third_party/clang-format/script +++ b/third_party/clang-format/script @@ -1 +1 @@ -Subproject commit 37f6e68a107df43b7d7e044fd36a13cbae3413f2 +Subproject commit c2725e0622e1a86d55f14514f2177a39efea4a0e diff --git a/third_party/clspv/BUILD.gn b/third_party/clspv/BUILD.gn index 8b266473d33..f639752e5ba 100644 --- a/third_party/clspv/BUILD.gn +++ b/third_party/clspv/BUILD.gn @@ -76,7 +76,13 @@ action("clspv-builtins") { # to the clspv README.md file for instructions. action("clspv_builtin_library") { script = "src/cmake/bake_file.py" - inputs = [ "src/cmake/clspv--.bc" ] + + # TODO(hoonee.cho): fix the GN script to build libclc libraries with clspv + # The recent CLSPV's commit changed a way to get clspv--.bc and clspv64--.bc when building CLSPV. + # https://github.com/google/clspv/commit/769daac0f9b7ace2d6fb9839f18ba82f9751aefd + # Before: use prebuilt clspv--.bc and clspv64--.bc + # After: build clang/libclc with target set to clspv--.bc and clspv64--.bc + inputs = [ "gn/clspv--.bc" ] outputs = [ "$target_gen_dir/clspv/clspv_builtin_library.h" ] args = [ @@ -89,7 +95,7 @@ action("clspv_builtin_library") { action("clspv64_builtin_library") { script = "src/cmake/bake_file.py" - inputs = [ "src/cmake/clspv64--.bc" ] + inputs = [ "gn/clspv64--.bc" ] outputs = [ "$target_gen_dir/clspv/clspv64_builtin_library.h" ] args = [ @@ -212,7 +218,6 @@ source_set("clspv_passes") { "src/lib/UndoSRetPass.cpp", "src/lib/UndoTranslateSamplerFoldPass.cpp", "src/lib/UndoTruncateToOddIntegerPass.cpp", - "src/lib/WrapKernelPass.cpp", "src/lib/ZeroInitializeAllocasPass.cpp", ] diff --git a/third_party/clspv/README.chromium b/third_party/clspv/README.chromium index 84c0e963576..3d9c9218510 100644 --- a/third_party/clspv/README.chromium +++ b/third_party/clspv/README.chromium @@ -1,8 +1,9 @@ Name: clspv Short Name: clspv URL: https://github.com/google/clspv -Version: a173c052455434a422bcfe5c12ffe44d574fd6e1 -Revision: a173c052455434a422bcfe5c12ffe44d574fd6e1 +Version: N/A +Revision: 8f35aa835ae973e1c802421ba5a873f5e967278c +Update Mechanism: Manual Security Critical: no Shipped: no License: Apache-2.0 diff --git a/third_party/clspv/gn/build/BUILD.gn b/third_party/clspv/gn/build/BUILD.gn index 637c0c3d9ea..fe9e8ae5abd 100644 --- a/third_party/clspv/gn/build/BUILD.gn +++ b/third_party/clspv/gn/build/BUILD.gn @@ -75,6 +75,8 @@ config("clang_code") { "-fno-strict-aliasing", "-Wno-deprecated-declarations", ] + } else { + defines = [ "CLANG_EXPORTS" ] } include_dirs = [ "//$clspv_llvm_dir/clang/include", diff --git a/third_party/clspv/gn/clspv--.bc b/third_party/clspv/gn/clspv--.bc new file mode 100644 index 00000000000..6a41f92f86a Binary files /dev/null and b/third_party/clspv/gn/clspv--.bc differ diff --git a/third_party/clspv/gn/clspv64--.bc b/third_party/clspv/gn/clspv64--.bc new file mode 100644 index 00000000000..a263312dc0e Binary files /dev/null and b/third_party/clspv/gn/clspv64--.bc differ diff --git a/third_party/clspv/gn/llvm/config/BUILD.gn b/third_party/clspv/gn/llvm/config/BUILD.gn index dad477dde6c..fc4f8529a23 100644 --- a/third_party/clspv/gn/llvm/config/BUILD.gn +++ b/third_party/clspv/gn/llvm/config/BUILD.gn @@ -72,18 +72,14 @@ write_cmake_config("config") { "HAVE_DECL_FE_ALL_EXCEPT=1", "HAVE_DECL_FE_INEXACT=1", "LLVM_ENABLE_CRASH_DUMPS=", - "HAVE_ERRNO_H=1", - "HAVE_FCNTL_H=1", - "HAVE_FENV_H=1", "HAVE_FFI_CALL=", "HAVE_FFI_FFI_H=", "HAVE_FFI_H=", "HAVE_LIBPFM=", "HAVE_LIBPSAPI=", "HAVE_MALLCTL=", - "HAVE_SIGNAL_H=1", - "HAVE_SYS_STAT_H=1", - "HAVE_SYS_TYPES_H=1", + "HAVE_PTHREAD_GET_NAME_NP=", + "HAVE_PTHREAD_SET_NAME_NP=", "HAVE_VALGRIND_VALGRIND_H=", "HAVE__ALLOCA=", "HAVE___ALLOCA=", @@ -106,6 +102,7 @@ write_cmake_config("config") { "HOST_LINK_VERSION=", "LIBPFM_HAS_FIELD_CYCLES=", "LLVM_TARGET_TRIPLE_ENV=", + "LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG=1", "LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO=1", "LLVM_WINDOWS_PREFER_FORWARD_SLASH=", "PACKAGE_BUGREPORT=https://github.com/llvm/llvm-project/issues/", @@ -115,6 +112,9 @@ write_cmake_config("config") { "PACKAGE_VENDOR=", "LLVM_GISEL_COV_ENABLED=", "LLVM_GISEL_COV_PREFIX=", + "HAVE_GETAUXVAL=", + "HAVE_ICU=", + "HAVE_ICONV=", # FIXME: Set to 1 on mac once the 10.14 SDK is in common use. "LLVM_SUPPORT_XCODE_SIGNPOSTS=", @@ -123,14 +123,12 @@ write_cmake_config("config") { if (current_os == "linux" || current_os == "android") { values += [ "HAVE_FUTIMENS=1", - "HAVE_LINK_H=1", "HAVE_MALLINFO=1", "HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=1", ] } else { values += [ "HAVE_FUTIMENS=", - "HAVE_LINK_H=", "HAVE_MALLINFO=", "HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=", ] @@ -140,7 +138,6 @@ write_cmake_config("config") { values += [ "HAVE_CRASHREPORTER_INFO=1", "HAVE_DECL_ARC4RANDOM=1", - "HAVE_DLADDR=1", "HAVE_MACH_MACH_H=1", "HAVE_MALLOC_MALLOC_H=1", "HAVE_MALLOC_ZONE_STATISTICS=1", @@ -152,7 +149,6 @@ write_cmake_config("config") { values += [ "HAVE_CRASHREPORTER_INFO=", "HAVE_DECL_ARC4RANDOM=", - "HAVE_DLADDR=", "HAVE_MACH_MACH_H=", "HAVE_MALLOC_MALLOC_H=", "HAVE_MALLOC_ZONE_STATISTICS=", @@ -191,11 +187,9 @@ write_cmake_config("config") { if (current_os == "win") { values += [ "HAVE_DECL_STRERROR_S=1", - "HAVE_DLFCN_H=", "HAVE_DLOPEN=", "HAVE_FUTIMES=", "HAVE_GETPAGESIZE=", - "HAVE_GETRLIMIT=", "HAVE_GETRUSAGE=", "HAVE_ISATTY=", "HAVE_LIBPTHREAD=", @@ -206,19 +200,14 @@ write_cmake_config("config") { "HAVE_PTHREAD_RWLOCK_INIT=", "HAVE_SBRK=", "HAVE_SETENV=", - "HAVE_SETRLIMIT=", "HAVE_SIGALTSTACK=", "HAVE_STRERROR_R=", "HAVE_SYSCONF=", - "HAVE_SYS_IOCTL_H=", "HAVE_SYS_MMAN_H=", - "HAVE_SYS_PARAM_H=", - "HAVE_SYS_RESOURCE_H=", - "HAVE_SYS_TIME_H=", - "HAVE_TERMIOS_H=", "HAVE_UNISTD_H=", "HAVE__CHSIZE_S=1", "HAVE__UNWIND_BACKTRACE=", + "HAVE_SYS_IOCTL_H=", "stricmp=_stricmp", "strdup=_strdup", ] @@ -226,11 +215,9 @@ write_cmake_config("config") { # POSIX-y system defaults. values += [ "HAVE_DECL_STRERROR_S=", - "HAVE_DLFCN_H=1", "HAVE_DLOPEN=1", "HAVE_FUTIMES=1", "HAVE_GETPAGESIZE=1", - "HAVE_GETRLIMIT=1", "HAVE_GETRUSAGE=1", "HAVE_ISATTY=1", "HAVE_LIBPTHREAD=1", @@ -241,19 +228,14 @@ write_cmake_config("config") { "HAVE_PTHREAD_RWLOCK_INIT=1", "HAVE_SBRK=1", "HAVE_SETENV=1", - "HAVE_SETRLIMIT=1", "HAVE_SIGALTSTACK=1", "HAVE_STRERROR_R=1", "HAVE_SYSCONF=1", - "HAVE_SYS_IOCTL_H=1", "HAVE_SYS_MMAN_H=1", - "HAVE_SYS_PARAM_H=1", - "HAVE_SYS_RESOURCE_H=1", - "HAVE_SYS_TIME_H=1", - "HAVE_TERMIOS_H=1", "HAVE_UNISTD_H=1", "HAVE__CHSIZE_S=", "HAVE__UNWIND_BACKTRACE=1", + "HAVE_SYS_IOCTL_H=1", "stricmp=", "strdup=", ] @@ -277,12 +259,6 @@ write_cmake_config("config") { values += [ "HAVE_LIBEDIT=" ] } - if (llvm_enable_terminfo) { - values += [ "LLVM_ENABLE_TERMINFO=1" ] - } else { - values += [ "LLVM_ENABLE_TERMINFO=" ] - } - if (llvm_enable_libxml2) { values += [ "LLVM_ENABLE_LIBXML2=1" ] } else { @@ -308,6 +284,7 @@ write_cmake_config("llvm-config") { "LLVM_ENABLE_ZSTD=", "LLVM_FORCE_USE_OLD_TOOLCHAIN=", "LLVM_HAS_ATOMICS=1", + "LLVM_HAS_LOGF128=0", "LLVM_HAVE_TFLITE=", "LLVM_HOST_TRIPLE=$llvm_current_triple", "LLVM_NATIVE_ARCH=$native_target", @@ -319,6 +296,13 @@ write_cmake_config("llvm-config") { "LLVM_VERSION_MINOR=$llvm_version_minor", "LLVM_VERSION_PATCH=$llvm_version_patch", "LLVM_WITH_Z3=", + "LLVM_ENABLE_TELEMETRY=", + "LLVM_ENABLE_PROFCHECK=", + "LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS=", + "LLVM_ENABLE_LLVM_C_EXPORT_ANNOTATIONS=", + "LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE=", + "LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN=", + "LLVM_ENABLE_ONDISK_CAS=", "PACKAGE_VERSION=${llvm_version}git", ] @@ -387,94 +371,6 @@ write_cmake_config("llvm-config") { } else { values += [ "LLVM_FORCE_ENABLE_STATS=" ] } - - if (llvm_build_AArch64) { - values += [ "LLVM_HAS_AARCH64_TARGET=1" ] - } else { - values += [ "LLVM_HAS_AARCH64_TARGET=" ] - } - - if (llvm_build_AMDGPU) { - values += [ "LLVM_HAS_AMDGPU_TARGET=1" ] - } else { - values += [ "LLVM_HAS_AMDGPU_TARGET=" ] - } - - values += [ "LLVM_HAS_ARC_TARGET=" ] - - if (llvm_build_ARM) { - values += [ "LLVM_HAS_ARM_TARGET=1" ] - } else { - values += [ "LLVM_HAS_ARM_TARGET=" ] - } - - values += [ "LLVM_HAS_AVR_TARGET=" ] - - if (llvm_build_BPF) { - values += [ "LLVM_HAS_BPF_TARGET=1" ] - } else { - values += [ "LLVM_HAS_BPF_TARGET=" ] - } - - values += [ "LLVM_HAS_CSKY_TARGET=" ] - values += [ "LLVM_HAS_DIRECTX_TARGET=" ] - values += [ "LLVM_HAS_HEXAGON_TARGET=" ] - values += [ "LLVM_HAS_LANAI_TARGET=" ] - - if (llvm_build_LoongArch) { - values += [ "LLVM_HAS_LOONGARCH_TARGET=1" ] - } else { - values += [ "LLVM_HAS_LOONGARCH_TARGET=" ] - } - - values += [ "LLVM_HAS_M68K_TARGET=" ] - - if (llvm_build_Mips) { - values += [ "LLVM_HAS_MIPS_TARGET=1" ] - } else { - values += [ "LLVM_HAS_MIPS_TARGET=" ] - } - - values += [ "LLVM_HAS_MSP430_TARGET=" ] - values += [ "LLVM_HAS_NVPTX_TARGET=" ] - - if (llvm_build_PowerPC) { - values += [ "LLVM_HAS_POWERPC_TARGET=1" ] - } else { - values += [ "LLVM_HAS_POWERPC_TARGET=" ] - } - - if (llvm_build_RISCV) { - values += [ "LLVM_HAS_RISCV_TARGET=1" ] - } else { - values += [ "LLVM_HAS_RISCV_TARGET=" ] - } - - values += [ "LLVM_HAS_SPARC_TARGET=" ] - values += [ "LLVM_HAS_SPIRV_TARGET=" ] - - if (llvm_build_SystemZ) { - values += [ "LLVM_HAS_SYSTEMZ_TARGET=1" ] - } else { - values += [ "LLVM_HAS_SYSTEMZ_TARGET=" ] - } - - values += [ "LLVM_HAS_VE_TARGET=" ] - - if (llvm_build_WebAssembly) { - values += [ "LLVM_HAS_WEBASSEMBLY_TARGET=1" ] - } else { - values += [ "LLVM_HAS_WEBASSEMBLY_TARGET=" ] - } - - if (llvm_build_X86) { - values += [ "LLVM_HAS_X86_TARGET=1" ] - } else { - values += [ "LLVM_HAS_X86_TARGET=" ] - } - - values += [ "LLVM_HAS_XCORE_TARGET=" ] - values += [ "LLVM_HAS_XTENSA_TARGET=" ] } ############################################################################## diff --git a/third_party/clspv/gn/llvm/config/clang/BUILD.gn b/third_party/clspv/gn/llvm/config/clang/BUILD.gn index 2f76d24adef..7287f77d1ed 100644 --- a/third_party/clspv/gn/llvm/config/clang/BUILD.gn +++ b/third_party/clspv/gn/llvm/config/clang/BUILD.gn @@ -7,8 +7,6 @@ import("//build_overrides/clspv.gni") # `clang/include/clang/Config/BUILD.gn` # `clang/include/clang/Basic/BUILD.gn` # `clang/lib/Basic/BUILD.gn` -import( - "//$clspv_llvm_dir/llvm/utils/gn/secondary/clang/lib/ARCMigrate/enable.gni") import( "//$clspv_llvm_dir/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Frontend/enable.gni") import("//$clspv_llvm_dir/llvm/utils/gn/secondary/llvm/version.gni") @@ -24,6 +22,7 @@ write_cmake_config("version") { "CLANG_VERSION_MAJOR=$llvm_version_major", "CLANG_VERSION_MINOR=$llvm_version_minor", "CLANG_VERSION_PATCHLEVEL=$llvm_version_patch", + "MAX_CLANG_ABI_COMPAT_VERSION=$llvm_version_major", ] } @@ -66,16 +65,11 @@ write_cmake_config("Config") { "ENABLE_LINKER_BUILD_ID=", "ENABLE_X86_RELAX_RELOCATIONS=1", "CLANG_ENABLE_OBJC_REWRITER=1", # FIXME: flag? + "CLANG_ENABLE_CIR=", "CLANG_SYSTEMZ_DEFAULT_ARCH=z10", "PPC_LINUX_DEFAULT_IEEELONGDOUBLE=", ] - if (clang_enable_arcmt) { - values += [ "CLANG_ENABLE_ARCMT=1" ] - } else { - values += [ "CLANG_ENABLE_ARCMT=" ] - } - if (clang_enable_static_analyzer) { values += [ "CLANG_ENABLE_STATIC_ANALYZER=1" ] } else { @@ -83,9 +77,17 @@ write_cmake_config("Config") { } if (host_os != "win") { - values += [ "CLANG_HAVE_RLIMITS=1" ] + values += [ + "CLANG_HAVE_DLADDR=1", + "CLANG_HAVE_DLFCN_H=1", + "CLANG_HAVE_RLIMITS=1", + ] } else { - values += [ "CLANG_HAVE_RLIMITS=" ] + values += [ + "CLANG_HAVE_DLADDR=", + "CLANG_HAVE_DLFCN_H=", + "CLANG_HAVE_RLIMITS=", + ] } if (llvm_enable_libxml2) { diff --git a/third_party/clspv/gn/llvm/sources/BUILD.gn b/third_party/clspv/gn/llvm/sources/BUILD.gn index 35181e0c578..9eedc08fbc6 100644 --- a/third_party/clspv/gn/llvm/sources/BUILD.gn +++ b/third_party/clspv/gn/llvm/sources/BUILD.gn @@ -62,8 +62,8 @@ template("clspv_llvm_static_lib") { # add the config header deps here as most need them deps = [ + "$clspv_gn_dir/llvm/config", "$clspv_gn_dir/llvm/config:abi-breaking", - "$clspv_gn_dir/llvm/config:config", "$clspv_gn_dir/llvm/config:llvm-config", ] @@ -150,7 +150,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen_types") { ":clspv_llvm_lib_support", "$clspv_gn_dir/llvm/tablegen:GenVT", ] - sources = [ "//$clspv_llvm_dir/llvm/lib/CodeGen/LowLevelType.cpp" ] + sources = [ "//$clspv_llvm_dir/llvm/lib/CodeGenTypes/LowLevelType.cpp" ] } clspv_llvm_static_lib("clspv_llvm_lib_frontend_driver") { @@ -168,7 +168,13 @@ clspv_llvm_static_lib("clspv_llvm_lib_frontend_hlsl") { ":clspv_llvm_lib_ir", ":clspv_llvm_lib_support", ] - sources = [ "//$clspv_llvm_dir/llvm/lib/Frontend/HLSL/HLSLResource.cpp" ] + sources = [ + "//$clspv_llvm_dir/llvm/lib/Frontend/HLSL/HLSLBinding.cpp", + "//$clspv_llvm_dir/llvm/lib/Frontend/HLSL/HLSLResource.cpp", + "//$clspv_llvm_dir/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp", + "//$clspv_llvm_dir/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp", + "//$clspv_llvm_dir/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp", + ] } clspv_llvm_static_lib("clspv_llvm_lib_frontend_offloading") { @@ -181,9 +187,27 @@ clspv_llvm_static_lib("clspv_llvm_lib_frontend_offloading") { sources = [ "//$clspv_llvm_dir/llvm/lib/Frontend/Offloading/Utility.cpp" ] } +clspv_llvm_static_lib("clspv_llvm_lib_frontend_atomic") { + deps = [ + ":clspv_llvm_lib_analysis", + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_targetparser", + ":clspv_llvm_lib_transforms_utils", + ] + sources = [ "//$clspv_llvm_dir/llvm/lib/Frontend/Atomic/Atomic.cpp" ] +} + +clspv_llvm_static_lib("clspv_llvm_lib_frontend_directive") { + deps = [ ":clspv_llvm_lib_support" ] + sources = [ "//$clspv_llvm_dir/llvm/lib/Frontend/Directive/Spelling.cpp" ] +} + clspv_llvm_static_lib("clspv_llvm_lib_frontend_openmp") { deps = [ ":clspv_llvm_lib_analysis", + ":clspv_llvm_lib_frontend_atomic", + ":clspv_llvm_lib_frontend_directive", ":clspv_llvm_lib_frontend_offloading", ":clspv_llvm_lib_ir", ":clspv_llvm_lib_mc", @@ -194,6 +218,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_frontend_openmp") { "$clspv_gn_dir/llvm/tablegen:public_tablegen", ] sources = [ + "//$clspv_llvm_dir/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp", "//$clspv_llvm_dir/llvm/lib/Frontend/OpenMP/OMP.cpp", "//$clspv_llvm_dir/llvm/lib/Frontend/OpenMP/OMPContext.cpp", "//$clspv_llvm_dir/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp", @@ -236,14 +261,13 @@ clspv_llvm_static_lib("clspv_llvm_lib_lto") { ":clspv_llvm_lib_transforms_scalar", ":clspv_llvm_lib_transforms_utils", ":write_vcsrevision", - "$clspv_gn_dir/llvm/config:config", + "$clspv_gn_dir/llvm/config", ] sources = [ "//$clspv_llvm_dir/llvm/lib/LTO/LTO.cpp", "//$clspv_llvm_dir/llvm/lib/LTO/LTOBackend.cpp", "//$clspv_llvm_dir/llvm/lib/LTO/LTOCodeGenerator.cpp", "//$clspv_llvm_dir/llvm/lib/LTO/LTOModule.cpp", - "//$clspv_llvm_dir/llvm/lib/LTO/SummaryBasedOptimizations.cpp", "//$clspv_llvm_dir/llvm/lib/LTO/ThinLTOCodeGenerator.cpp", "//$clspv_llvm_dir/llvm/lib/LTO/UpdateCompilerUsed.cpp", ] @@ -253,21 +277,42 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_vectorize") { deps = [ ":clspv_llvm_lib_analysis", ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_sandbox_ir", ":clspv_llvm_lib_support", ":clspv_llvm_lib_transforms_utils", "$clspv_gn_dir/llvm/tablegen:public_tablegen", ] sources = [ "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/LoopIdiomVectorize.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/InstrMaps.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Interval.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PackReuse.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionSave.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Scheduler.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SeedCollector.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/SandboxVectorizer/VecUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlan.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanSLP.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/VectorCombine.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Vectorize/Vectorize.cpp", @@ -300,10 +345,12 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_utils") { "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/CodeExtractor.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/CodeLayout.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/ControlFlowUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/CountVisits.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/CtorUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/DXILUpgrade.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/Debugify.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/EscapeEnumerator.cpp", @@ -315,9 +362,11 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_utils") { "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/GlobalStatus.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/GuardUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/HelloWorld.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/IRNormalizer.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/InjectTLIMappings.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/InlineFunction.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/InstructionNamer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/Instrumentation.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/IntegerDivision.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/LCSSA.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/LibCallsShrinkWrap.cpp", @@ -337,6 +386,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_utils") { "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/LowerInvoke.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/LowerMemIntrinsics.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/LowerSwitch.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/MatrixUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/Mem2Reg.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp", @@ -347,6 +397,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_utils") { "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/MoveAutoInit.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/NameAnonGlobals.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/PredicateInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/ProfileVerify.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Utils/SCCPSolver.cpp", @@ -394,6 +445,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_scalar") { "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/DivRemPairs.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/EarlyCSE.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/Float2Int.cpp", @@ -407,6 +459,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_scalar") { "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/InferAlignment.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/InstSimplifyPass.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/JumpThreading.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LICM.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopAccessAnalysisPrinter.cpp", @@ -422,11 +475,11 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_scalar") { "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopPassManager.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopPredication.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopRerollPass.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopRotation.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopSink.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopTermFold.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp", @@ -459,7 +512,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_scalar") { "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/TLSVariableHoist.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Scalar/WarnMissedTransforms.cpp", ] @@ -474,7 +526,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_objcarc") { sources = [ "//$clspv_llvm_dir/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp", @@ -493,10 +544,12 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_instrumentation") { ":clspv_llvm_lib_support", ":clspv_llvm_lib_targetparser", ":clspv_llvm_lib_transforms_utils", + "$clspv_gn_dir/llvm/tablegen:IntrinsicsAArch64", "$clspv_gn_dir/llvm/tablegen:IntrinsicsX86", ] sources = [ "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/AllocToken.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/BlockCoverageInference.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/CGProfile.cpp", @@ -505,18 +558,23 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_instrumentation") { "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/InstrOrderFile.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/KCFI.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/LowerAllowCheckPass.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/MemProfInstrumentation.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/MemProfUse.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/PGOForceFunctionAttrs.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Instrumentation/ValueProfileCollector.cpp", ] } @@ -587,7 +645,9 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_ipo") { "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/ElimAvailExtern.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/ExpandVariadics.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/ExtractGV.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/FatLTOCleanup.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/FunctionAttrs.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/FunctionImport.cpp", @@ -611,10 +671,10 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_ipo") { "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/SCCP.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/SampleContextTracker.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/SampleProfile.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/StripSymbols.cpp", - "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/SyntheticCountsPropagation.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp", ] @@ -633,6 +693,15 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_aggressiveinstcombine") { ] } +clspv_llvm_static_lib("clspv_llvm_lib_transforms_cfguard") { + deps = [ + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_targetparser", + ] + sources = [ "//$clspv_llvm_dir/llvm/lib/Transforms/CFGuard/CFGuard.cpp" ] +} + clspv_llvm_static_lib("clspv_llvm_lib_transforms_coroutines") { deps = [ ":clspv_llvm_lib_analysis", @@ -644,6 +713,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_coroutines") { ] sources = [ # llvm/lib/Transforms/* + "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/CoroConditionalWrapper.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/CoroEarly.cpp", @@ -651,6 +721,9 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_coroutines") { "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/CoroFrame.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/CoroSplit.cpp", "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/Coroutines.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/MaterializationUtils.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/SpillUtils.cpp", + "//$clspv_llvm_dir/llvm/lib/Transforms/Coroutines/SuspendCrossingInfo.cpp", ] } @@ -668,6 +741,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_transforms_hipstdpar") { clspv_llvm_static_lib("clspv_llvm_lib_analysis") { deps = [ ":clspv_llvm_lib_binaryformat", + ":clspv_llvm_lib_frontend_hlsl", ":clspv_llvm_lib_ir", ":clspv_llvm_lib_profiledata", ":clspv_llvm_lib_support", @@ -701,21 +775,29 @@ clspv_llvm_static_lib("clspv_llvm_lib_analysis") { "//$clspv_llvm_dir/llvm/lib/Analysis/ConstantFolding.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/ConstraintSystem.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/CostModel.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/CtxProfAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/CycleAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DDG.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DDGPrinter.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/DXILMetadataAnalysis.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/DXILResource.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/Delinearization.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DemandedBits.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DependenceAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DependenceGraphBuilder.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/DomConditionCache.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DomPrinter.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DomTreeUpdater.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/DominanceFrontier.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/EphemeralValuesCache.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/FloatingPointPredicateUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/GlobalsModRef.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/GuardUtils.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/HashRecognize.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/HeatUtils.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/IR2Vec.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/IRSimilarityIdentifier.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/IVDescriptors.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/IVUsers.cpp", @@ -729,8 +811,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_analysis") { "//$clspv_llvm_dir/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/InstructionSimplify.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/InteractiveModelRunner.cpp", - "//$clspv_llvm_dir/llvm/lib/Analysis/Interval.cpp", - "//$clspv_llvm_dir/llvm/lib/Analysis/IntervalPartition.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/KernelInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/LazyBlockFrequencyInfo.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/LazyBranchProbabilityInfo.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/LazyCallGraph.cpp", @@ -779,6 +861,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_analysis") { "//$clspv_llvm_dir/llvm/lib/Analysis/ScopedNoAliasAA.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/StackLifetime.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/StackSafetyAnalysis.cpp", + "//$clspv_llvm_dir/llvm/lib/Analysis/StaticDataProfileInfo.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/StructuralHash.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/SyntheticCountsUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/TFLiteUtils.cpp", @@ -790,7 +873,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_analysis") { "//$clspv_llvm_dir/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/TypeMetadataUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/UniformityAnalysis.cpp", - "//$clspv_llvm_dir/llvm/lib/Analysis/VFABIDemangling.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/ValueLattice.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/ValueLatticeUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Analysis/ValueTracking.cpp", @@ -813,7 +895,11 @@ clspv_llvm_static_lib("clspv_llvm_lib_asmparser") { clspv_llvm_static_lib("clspv_llvm_lib_targetparser") { deps = [ ":clspv_llvm_lib_support" ] - public_deps = [ "$clspv_gn_dir/llvm/tablegen:RISCVTargetParserDef" ] + public_deps = [ + "$clspv_gn_dir/llvm/tablegen:AArch64TargetParserDef", + "$clspv_gn_dir/llvm/tablegen:PPCGenTargetFeatures", + "$clspv_gn_dir/llvm/tablegen:RISCVTargetParserDef", + ] include_dirs = [ "Unix", "Windows", @@ -825,6 +911,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_targetparser") { "//$clspv_llvm_dir/llvm/lib/TargetParser/CSKYTargetParser.cpp", "//$clspv_llvm_dir/llvm/lib/TargetParser/Host.cpp", "//$clspv_llvm_dir/llvm/lib/TargetParser/LoongArchTargetParser.cpp", + "//$clspv_llvm_dir/llvm/lib/TargetParser/PPCTargetParser.cpp", + "//$clspv_llvm_dir/llvm/lib/TargetParser/RISCVISAInfo.cpp", "//$clspv_llvm_dir/llvm/lib/TargetParser/RISCVTargetParser.cpp", "//$clspv_llvm_dir/llvm/lib/TargetParser/SubtargetFeature.cpp", "//$clspv_llvm_dir/llvm/lib/TargetParser/TargetParser.cpp", @@ -874,6 +962,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { deps = [ ":clspv_llvm_lib_analysis", ":clspv_llvm_lib_bitcode_writer", + ":clspv_llvm_lib_cgdata", + ":clspv_llvm_lib_codegen_types", ":clspv_llvm_lib_ir", ":clspv_llvm_lib_mc", ":clspv_llvm_lib_profiledata", @@ -909,7 +999,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/CallingConvLower.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/CodeGen.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/CodeGenCommonISel.cpp", - "//$clspv_llvm_dir/llvm/lib/CodeGen/CodeGenPassBuilder.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/CodeGenPrepare.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/CommandFlags.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp", @@ -917,13 +1006,14 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/DFAPacketizer.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/DetectDeadLanes.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/DroppedVariableStatsMIR.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/DwarfEHPrepare.cpp", - "//$clspv_llvm_dir/llvm/lib/CodeGen/EHContGuardCatchret.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/EHContGuardTargets.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/EarlyIfConversion.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/EdgeBundles.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ExecutionDomainFix.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/ExpandFp.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ExpandLargeDivRem.cpp", - "//$clspv_llvm_dir/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ExpandMemCmp.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ExpandReductions.cpp", @@ -938,10 +1028,12 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/GCMetadataPrinter.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/GCRootLowering.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalMerge.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalMergeFunctions.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/HardwareLoops.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/IfConversion.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ImplicitNullChecks.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/IndirectBrExpandPass.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/InitUndef.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/InlineSpiller.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/InterferenceCache.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/InterleavedAccessPass.cpp", @@ -949,7 +1041,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/IntrinsicLowering.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/JMCInstrumenter.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/KCFI.cpp", - "//$clspv_llvm_dir/llvm/lib/CodeGen/LLVMTargetMachine.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LatencyPriorityQueue.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LazyMachineBlockFrequencyInfo.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LexicalScopes.cpp", @@ -971,10 +1062,10 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/LiveVariables.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LoopTraversal.cpp", - "//$clspv_llvm_dir/llvm/lib/CodeGen/LowLevelType.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LowLevelTypeUtils.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/LowerEmuTLS.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MBFIWrapper.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/MIR2Vec.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MIRCanonicalizerPass.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MIRFSDiscriminator.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MIRNamerPass.cpp", @@ -993,13 +1084,16 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineCSE.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineCheckDebugify.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineCombiner.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineConvergenceVerifier.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineCopyPropagation.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineCycleAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineDebugify.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineDominanceFrontier.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineDominators.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineFrameInfo.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineFunction.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineFunctionAnalysis.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineFunctionPass.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/MachineFunctionSplitter.cpp", @@ -1037,7 +1131,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/OptimizePHIs.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/PHIElimination.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/PHIEliminationUtils.cpp", - "//$clspv_llvm_dir/llvm/lib/CodeGen/ParallelCG.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/PatchableFunction.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/PeepholeOptimizer.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp", @@ -1068,6 +1161,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/RegisterPressure.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/RegisterScavenging.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/RegisterUsageInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/RemoveLoadsIntoFakeUses.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/RenameIndependentSubregs.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/ReplaceWithVeclib.cpp", @@ -1092,6 +1186,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/StackMaps.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/StackProtector.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/StackSlotColoring.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/StaticDataAnnotator.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/StaticDataSplitter.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/SwiftErrorValueTracking.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/SwitchLoweringUtils.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/TailDuplication.cpp", @@ -1113,10 +1209,182 @@ clspv_llvm_static_lib("clspv_llvm_lib_codegen") { "//$clspv_llvm_dir/llvm/lib/CodeGen/VirtRegMap.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/WasmEHPrepare.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/WinEHPrepare.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/WindowScheduler.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp", "//$clspv_llvm_dir/llvm/lib/CodeGen/XRayInstrumentation.cpp", ] } +clspv_llvm_static_lib("clspv_llvm_lib_codegen_asmprinter") { + deps = [ + ":clspv_llvm_lib_analysis", + ":clspv_llvm_lib_binaryformat", + ":clspv_llvm_lib_codegen", + ":clspv_llvm_lib_debuginfo_codeview", + ":clspv_llvm_lib_debuginfo_dwarf", + ":clspv_llvm_lib_debuginfo_gsym", + ":clspv_llvm_lib_debuginfo_msf", + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_mc", + ":clspv_llvm_lib_remarks", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_target", + ":clspv_llvm_lib_targetparser", + ":write_vcsrevision", + ] + sources = [ + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DIE.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/AsmPrinter/WinException.cpp", + ] +} + +clspv_llvm_static_lib("clspv_llvm_lib_codegen_globalisel") { + deps = [ + ":clspv_llvm_lib_analysis", + ":clspv_llvm_lib_codegen", + ":clspv_llvm_lib_codegen_selectiondag", + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_mc", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_target", + ":clspv_llvm_lib_transforms_utils", + "$clspv_gn_dir/llvm/tablegen:IntrinsicsAMDGPU", + "../config", + "../config:llvm-config", + ] + sources = [ + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/Combiner.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/GISelChangeObserver.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/Localizer.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/LostDebugLocObserver.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/GlobalISel/Utils.cpp", + ] +} + +clspv_llvm_static_lib("clspv_llvm_lib_codegen_mirparser") { + deps = [ + ":clspv_llvm_lib_asmparser", + ":clspv_llvm_lib_binaryformat", + ":clspv_llvm_lib_codegen", + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_mc", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_target", + ] + sources = [ + "//$clspv_llvm_dir/llvm/lib/CodeGen/MIRParser/MILexer.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/MIRParser/MIParser.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/MIRParser/MIRParser.cpp", + ] +} + +clspv_llvm_static_lib("clspv_llvm_lib_codegen_selectiondag") { + deps = [ + ":clspv_llvm_lib_analysis", + ":clspv_llvm_lib_codegen", + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_mc", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_target", + ":clspv_llvm_lib_targetparser", + ":clspv_llvm_lib_transforms_utils", + "$clspv_gn_dir/llvm/tablegen:IntrinsicsAArch64", + "$clspv_gn_dir/llvm/tablegen:IntrinsicsAMDGPU", + "$clspv_gn_dir/llvm/tablegen:IntrinsicsWebAssembly", + ] + sources = [ + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SDNodeInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGVLIW.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/SelectionDAGTargetInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp", + "//$clspv_llvm_dir/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp", + ] +} + +clspv_llvm_static_lib("clspv_llvm_lib_cgdata") { + deps = [ + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_support", + ] + sources = [ + # llvm/lib/CodeGen + "//$clspv_llvm_dir/llvm/lib/CGData/CodeGenData.cpp", + "//$clspv_llvm_dir/llvm/lib/CGData/CodeGenDataReader.cpp", + "//$clspv_llvm_dir/llvm/lib/CGData/CodeGenDataWriter.cpp", + "//$clspv_llvm_dir/llvm/lib/CGData/OutlinedHashTree.cpp", + "//$clspv_llvm_dir/llvm/lib/CGData/OutlinedHashTreeRecord.cpp", + "//$clspv_llvm_dir/llvm/lib/CGData/StableFunctionMap.cpp", + "//$clspv_llvm_dir/llvm/lib/CGData/StableFunctionMapRecord.cpp", + ] +} + clspv_llvm_static_lib("clspv_llvm_lib_debuginfo_btf") { deps = [ ":clspv_llvm_lib_support" ] sources = [ @@ -1186,9 +1454,9 @@ clspv_llvm_static_lib("clspv_llvm_lib_debuginfo_dwarf") { "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp", - "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp", @@ -1202,16 +1470,43 @@ clspv_llvm_static_lib("clspv_llvm_lib_debuginfo_dwarf") { "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp", - "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFLocationExpression.cpp", - "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFUnwindTablePrinter.cpp", "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFUnwindTable.cpp", + ] +} + +clspv_llvm_static_lib("clspv_llvm_lib_debuginfo_gsym") { + deps = [ + ":clspv_llvm_lib_mc", + ":clspv_llvm_lib_support", + ":clspv_llvm_lib_targetparser", + ] + sources = [ + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/CallSiteInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/ExtractRanges.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/FileWriter.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/GsymContext.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/GsymReader.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/Header.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/InlineInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/LineTable.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/LookupResult.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/MergedFunctionsInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp", ] } @@ -1374,6 +1669,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_debuginfo_symbolize") { deps = [ ":clspv_llvm_lib_debuginfo_btf", ":clspv_llvm_lib_debuginfo_dwarf", + ":clspv_llvm_lib_debuginfo_gsym", ":clspv_llvm_lib_debuginfo_pdb", ":clspv_llvm_lib_demangle", ":clspv_llvm_lib_object", @@ -1426,13 +1722,16 @@ clspv_llvm_static_lib("clspv_llvm_lib_ir") { "//$clspv_llvm_dir/llvm/lib/IR/BasicBlock.cpp", "//$clspv_llvm_dir/llvm/lib/IR/BuiltinGCs.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Comdat.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/ConstantFPRange.cpp", "//$clspv_llvm_dir/llvm/lib/IR/ConstantFold.cpp", "//$clspv_llvm_dir/llvm/lib/IR/ConstantRange.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/ConstantRangeList.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Constants.cpp", "//$clspv_llvm_dir/llvm/lib/IR/ConvergenceVerifier.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Core.cpp", "//$clspv_llvm_dir/llvm/lib/IR/CycleInfo.cpp", "//$clspv_llvm_dir/llvm/lib/IR/DIBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/DIExpressionOptimizer.cpp", "//$clspv_llvm_dir/llvm/lib/IR/DataLayout.cpp", "//$clspv_llvm_dir/llvm/lib/IR/DebugInfo.cpp", "//$clspv_llvm_dir/llvm/lib/IR/DebugInfoMetadata.cpp", @@ -1442,6 +1741,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_ir") { "//$clspv_llvm_dir/llvm/lib/IR/DiagnosticInfo.cpp", "//$clspv_llvm_dir/llvm/lib/IR/DiagnosticPrinter.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Dominators.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/DroppedVariableStats.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/DroppedVariableStatsIR.cpp", "//$clspv_llvm_dir/llvm/lib/IR/EHPersonalities.cpp", "//$clspv_llvm_dir/llvm/lib/IR/FPEnv.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Function.cpp", @@ -1454,12 +1755,14 @@ clspv_llvm_static_lib("clspv_llvm_lib_ir") { "//$clspv_llvm_dir/llvm/lib/IR/Instruction.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Instructions.cpp", "//$clspv_llvm_dir/llvm/lib/IR/IntrinsicInst.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/Intrinsics.cpp", "//$clspv_llvm_dir/llvm/lib/IR/LLVMContext.cpp", "//$clspv_llvm_dir/llvm/lib/IR/LLVMContextImpl.cpp", "//$clspv_llvm_dir/llvm/lib/IR/LLVMRemarkStreamer.cpp", "//$clspv_llvm_dir/llvm/lib/IR/LegacyPassManager.cpp", "//$clspv_llvm_dir/llvm/lib/IR/MDBuilder.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Mangler.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/MemoryModelRelaxationAnnotations.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Metadata.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Module.cpp", "//$clspv_llvm_dir/llvm/lib/IR/ModuleSummaryIndex.cpp", @@ -1475,6 +1778,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_ir") { "//$clspv_llvm_dir/llvm/lib/IR/ProfileSummary.cpp", "//$clspv_llvm_dir/llvm/lib/IR/PseudoProbe.cpp", "//$clspv_llvm_dir/llvm/lib/IR/ReplaceConstant.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/RuntimeLibcalls.cpp", "//$clspv_llvm_dir/llvm/lib/IR/SSAContext.cpp", "//$clspv_llvm_dir/llvm/lib/IR/SafepointIRVerifier.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Statepoint.cpp", @@ -1484,13 +1788,40 @@ clspv_llvm_static_lib("clspv_llvm_lib_ir") { "//$clspv_llvm_dir/llvm/lib/IR/TypedPointerType.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Use.cpp", "//$clspv_llvm_dir/llvm/lib/IR/User.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/VFABIDemangler.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Value.cpp", "//$clspv_llvm_dir/llvm/lib/IR/ValueSymbolTable.cpp", - "//$clspv_llvm_dir/llvm/lib/IR/VectorBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/IR/VectorTypeUtils.cpp", "//$clspv_llvm_dir/llvm/lib/IR/Verifier.cpp", ] } +clspv_llvm_static_lib("clspv_llvm_lib_sandbox_ir") { + deps = [ + ":clspv_llvm_lib_analysis", + ":clspv_llvm_lib_ir", + ":clspv_llvm_lib_support", + ] + sources = [ + # llvm/lib/SandboxIR + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Argument.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/BasicBlock.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Constant.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Context.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Function.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Instruction.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Module.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Pass.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/PassManager.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Region.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Tracker.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Type.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Use.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/User.cpp", + "//$clspv_llvm_dir/llvm/lib/SandboxIR/Value.cpp", + ] +} + clspv_llvm_static_lib("clspv_llvm_lib_irprinter") { deps = [ ":clspv_llvm_lib_ir", @@ -1524,7 +1855,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_target") { sources = [ # llvm/lib/Target "//$clspv_llvm_dir/llvm/lib/Target/Target.cpp", - "//$clspv_llvm_dir/llvm/lib/Target/TargetIntrinsicInfo.cpp", "//$clspv_llvm_dir/llvm/lib/Target/TargetLoweringObjectFile.cpp", "//$clspv_llvm_dir/llvm/lib/Target/TargetMachine.cpp", "//$clspv_llvm_dir/llvm/lib/Target/TargetMachineC.cpp", @@ -1580,15 +1910,11 @@ clspv_llvm_static_lib("clspv_llvm_lib_mc") { "//$clspv_llvm_dir/llvm/lib/MC/MCObjectWriter.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCPseudoProbe.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCRegisterInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/MC/MCSFrame.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCSPIRVStreamer.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCSchedule.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCSection.cpp", - "//$clspv_llvm_dir/llvm/lib/MC/MCSectionCOFF.cpp", - "//$clspv_llvm_dir/llvm/lib/MC/MCSectionDXContainer.cpp", - "//$clspv_llvm_dir/llvm/lib/MC/MCSectionELF.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCSectionMachO.cpp", - "//$clspv_llvm_dir/llvm/lib/MC/MCSectionWasm.cpp", - "//$clspv_llvm_dir/llvm/lib/MC/MCSectionXCOFF.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCStreamer.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCSubtargetInfo.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCSymbol.cpp", @@ -1629,7 +1955,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_mc_mcparser") { "//$clspv_llvm_dir/llvm/lib/MC/MCParser/DarwinAsmParser.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCParser/ELFAsmParser.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCParser/GOFFAsmParser.cpp", - "//$clspv_llvm_dir/llvm/lib/MC/MCParser/MCAsmLexer.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCParser/MCAsmParser.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp", "//$clspv_llvm_dir/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp", @@ -1688,6 +2013,11 @@ clspv_llvm_static_lib("clspv_llvm_lib_object") { "//$clspv_llvm_dir/llvm/lib/Object/WindowsMachineFlag.cpp", "//$clspv_llvm_dir/llvm/lib/Object/WindowsResource.cpp", "//$clspv_llvm_dir/llvm/lib/Object/XCOFFObjectFile.cpp", + "//$clspv_llvm_dir/llvm/lib/ObjectYAML/DWARFEmitter.cpp", + "//$clspv_llvm_dir/llvm/lib/ObjectYAML/DWARFYAML.cpp", + "//$clspv_llvm_dir/llvm/lib/ObjectYAML/ELFEmitter.cpp", + "//$clspv_llvm_dir/llvm/lib/ObjectYAML/ELFYAML.cpp", + "//$clspv_llvm_dir/llvm/lib/ObjectYAML/YAML.cpp", ] } @@ -1704,6 +2034,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_option") { clspv_llvm_static_lib("clspv_llvm_lib_profiledata") { deps = [ ":clspv_llvm_lib_debuginfo_dwarf", + ":clspv_llvm_lib_debuginfo_gsym", ":clspv_llvm_lib_debuginfo_symbolize", ":clspv_llvm_lib_ir", ":clspv_llvm_lib_object", @@ -1711,15 +2042,23 @@ clspv_llvm_static_lib("clspv_llvm_lib_profiledata") { ":clspv_llvm_lib_targetparser", ] sources = [ + "//$clspv_llvm_dir/llvm/lib/ProfileData/DataAccessProf.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/GCOV.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/IndexedMemProfData.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/InstrProf.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/InstrProfCorrelator.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/InstrProfReader.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/InstrProfWriter.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/ItaniumManglingCanonicalizer.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/MemProf.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/MemProfCommon.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/MemProfRadixTree.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/MemProfReader.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/MemProfSummary.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/MemProfSummaryBuilder.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/PGOCtxProfReader.cpp", + "//$clspv_llvm_dir/llvm/lib/ProfileData/PGOCtxProfWriter.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/ProfileSummaryBuilder.cpp", - "//$clspv_llvm_dir/llvm/lib/ProfileData/RawMemProfReader.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/SampleProf.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/SampleProfReader.cpp", "//$clspv_llvm_dir/llvm/lib/ProfileData/SampleProfWriter.cpp", @@ -1746,11 +2085,13 @@ clspv_llvm_static_lib("clspv_llvm_lib_passes") { deps = [ ":clspv_llvm_lib_analysis", ":clspv_llvm_lib_codegen", + ":clspv_llvm_lib_codegen_globalisel", ":clspv_llvm_lib_ir", ":clspv_llvm_lib_irprinter", ":clspv_llvm_lib_support", ":clspv_llvm_lib_target", ":clspv_llvm_lib_transforms_aggressiveinstcombine", + ":clspv_llvm_lib_transforms_cfguard", ":clspv_llvm_lib_transforms_coroutines", ":clspv_llvm_lib_transforms_hipstdpar", ":clspv_llvm_lib_transforms_instcombine", @@ -1766,6 +2107,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_passes") { #include_dirs = [ "$root_gen_dir/$clspv_llvm_dir" ] sources = [ + "//$clspv_llvm_dir/llvm/lib/Passes/CodeGenPassBuilder.cpp", "//$clspv_llvm_dir/llvm/lib/Passes/OptimizationLevel.cpp", "//$clspv_llvm_dir/llvm/lib/Passes/PassBuilder.cpp", "//$clspv_llvm_dir/llvm/lib/Passes/PassBuilderBindings.cpp", @@ -1807,8 +2149,10 @@ clspv_llvm_static_lib("clspv_llvm_lib_tblgen") { "//$clspv_llvm_dir/llvm/lib/TableGen/Record.cpp", "//$clspv_llvm_dir/llvm/lib/TableGen/SetTheory.cpp", "//$clspv_llvm_dir/llvm/lib/TableGen/StringMatcher.cpp", + "//$clspv_llvm_dir/llvm/lib/TableGen/StringToOffsetTable.cpp", "//$clspv_llvm_dir/llvm/lib/TableGen/TGLexer.cpp", "//$clspv_llvm_dir/llvm/lib/TableGen/TGParser.cpp", + "//$clspv_llvm_dir/llvm/lib/TableGen/TGTimer.cpp", "//$clspv_llvm_dir/llvm/lib/TableGen/TableGenBackend.cpp", "//$clspv_llvm_dir/llvm/lib/TableGen/TableGenBackendSkeleton.cpp", ] @@ -1820,6 +2164,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "$clspv_gn_dir/llvm/config:write_extension_def", "$clspv_gn_dir/llvm/config:write_target_def_files", ] + include_dirs = [ "//$clspv_llvm_dir/third-party/siphash/include" ] sources = [ "//$clspv_llvm_dir/llvm/lib/Support/ABIBreak.cpp", "//$clspv_llvm_dir/llvm/lib/Support/AMDGPUMetadata.cpp", @@ -1828,7 +2173,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/APInt.cpp", "//$clspv_llvm_dir/llvm/lib/Support/APSInt.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ARMAttributeParser.cpp", - "//$clspv_llvm_dir/llvm/lib/Support/ARMBuildAttrs.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/ARMBuildAttributes.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ARMWinEH.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Allocator.cpp", "//$clspv_llvm_dir/llvm/lib/Support/AutoConvert.cpp", @@ -1857,15 +2202,17 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/CrashRecoveryContext.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DAGDeltaAlgorithm.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DJB.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/DXILABI.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DataExtractor.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Debug.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DebugCounter.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DeltaAlgorithm.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DivisionByConstantInfo.cpp", - "//$clspv_llvm_dir/llvm/lib/Support/ELFAttributeParser.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/ELFAttrParserCompact.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ELFAttributes.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Error.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ErrorHandling.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/ExponentialBackoff.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ExtensibleRTTI.cpp", "//$clspv_llvm_dir/llvm/lib/Support/FileCollector.cpp", "//$clspv_llvm_dir/llvm/lib/Support/FileOutputBuffer.cpp", @@ -1876,13 +2223,15 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/FormattedStream.cpp", "//$clspv_llvm_dir/llvm/lib/Support/GlobPattern.cpp", "//$clspv_llvm_dir/llvm/lib/Support/GraphWriter.cpp", - "//$clspv_llvm_dir/llvm/lib/Support/Hashing.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/HexagonAttributeParser.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/HexagonAttributes.cpp", "//$clspv_llvm_dir/llvm/lib/Support/InitLLVM.cpp", "//$clspv_llvm_dir/llvm/lib/Support/InstructionCost.cpp", "//$clspv_llvm_dir/llvm/lib/Support/IntEqClasses.cpp", "//$clspv_llvm_dir/llvm/lib/Support/IntervalMap.cpp", "//$clspv_llvm_dir/llvm/lib/Support/JSON.cpp", "//$clspv_llvm_dir/llvm/lib/Support/KnownBits.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/KnownFPClass.cpp", "//$clspv_llvm_dir/llvm/lib/Support/LEB128.cpp", "//$clspv_llvm_dir/llvm/lib/Support/LineIterator.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Locale.cpp", @@ -1895,16 +2244,19 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/MemAlloc.cpp", "//$clspv_llvm_dir/llvm/lib/Support/MemoryBuffer.cpp", "//$clspv_llvm_dir/llvm/lib/Support/MemoryBufferRef.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/ModRef.cpp", "//$clspv_llvm_dir/llvm/lib/Support/NativeFormatting.cpp", "//$clspv_llvm_dir/llvm/lib/Support/OptimizedStructLayout.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/OptionStrCmp.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Optional.cpp", "//$clspv_llvm_dir/llvm/lib/Support/PGOOptions.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Parallel.cpp", "//$clspv_llvm_dir/llvm/lib/Support/PluginLoader.cpp", "//$clspv_llvm_dir/llvm/lib/Support/PrettyStackTrace.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/ProgramStack.cpp", "//$clspv_llvm_dir/llvm/lib/Support/RISCVAttributeParser.cpp", "//$clspv_llvm_dir/llvm/lib/Support/RISCVAttributes.cpp", - "//$clspv_llvm_dir/llvm/lib/Support/RISCVISAInfo.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/RISCVISAUtils.cpp", "//$clspv_llvm_dir/llvm/lib/Support/RWMutex.cpp", "//$clspv_llvm_dir/llvm/lib/Support/RandomNumberGenerator.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Regex.cpp", @@ -1913,6 +2265,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/ScaledNumber.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ScopedPrinter.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Signposts.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/SipHash.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/SlowDynamicAPInt.cpp", "//$clspv_llvm_dir/llvm/lib/Support/SmallPtrSet.cpp", "//$clspv_llvm_dir/llvm/lib/Support/SmallVector.cpp", "//$clspv_llvm_dir/llvm/lib/Support/SourceMgr.cpp", @@ -1931,7 +2285,6 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/Timer.cpp", "//$clspv_llvm_dir/llvm/lib/Support/ToolOutputFile.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Twine.cpp", - "//$clspv_llvm_dir/llvm/lib/Support/TypeSize.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Unicode.cpp", "//$clspv_llvm_dir/llvm/lib/Support/UnicodeCaseFold.cpp", "//$clspv_llvm_dir/llvm/lib/Support/UnicodeNameToCodepoint.cpp", @@ -1944,6 +2297,8 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/circular_raw_ostream.cpp", "//$clspv_llvm_dir/llvm/lib/Support/raw_os_ostream.cpp", "//$clspv_llvm_dir/llvm/lib/Support/raw_ostream.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/raw_ostream_proxy.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/raw_socket_stream.cpp", "//$clspv_llvm_dir/llvm/lib/Support/regcomp.c", "//$clspv_llvm_dir/llvm/lib/Support/regerror.c", "//$clspv_llvm_dir/llvm/lib/Support/regexec.c", @@ -1955,6 +2310,7 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/Atomic.cpp", "//$clspv_llvm_dir/llvm/lib/Support/DynamicLibrary.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Errno.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/Jobserver.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Memory.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Path.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Process.cpp", @@ -1963,6 +2319,11 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { "//$clspv_llvm_dir/llvm/lib/Support/Threading.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Valgrind.cpp", "//$clspv_llvm_dir/llvm/lib/Support/VirtualFileSystem.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/VirtualOutputBackend.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/VirtualOutputBackends.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/VirtualOutputConfig.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/VirtualOutputError.cpp", + "//$clspv_llvm_dir/llvm/lib/Support/VirtualOutputFile.cpp", "//$clspv_llvm_dir/llvm/lib/Support/Watchdog.cpp", ] libs = [] @@ -1974,7 +2335,10 @@ clspv_llvm_static_lib("clspv_llvm_lib_support") { libs += [ "dl" ] } else if (current_os == "win") { # Delay load shell32.dll if possible to speed up process startup. - libs += [ "delayimp.lib" ] + libs += [ + "delayimp.lib", + "ntdll.lib", + ] ldflags = [ "-delayload:ole32.dll", "-delayload:shell32.dll", @@ -2024,18 +2388,25 @@ clspv_llvm_static_lib("clspv_llvm_lib_windowsdriver") { clspv_llvm_source_set("clspv_llvm_tool_min_tblgen_sources") { deps = [ ":clspv_llvm_lib_support" ] sources = [ - "//$clspv_llvm_dir/llvm/utils/TableGen/Attributes.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenIntrinsics.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/DirectiveEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/IntrinsicEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/SDNodeProperties.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/TableGen.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/VTEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/Attributes.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/RISCVTargetDefEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/SDNodeProperties.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/TableGen.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Basic/VTEmitter.cpp", ] } clspv_llvm_source_set("clspv_llvm_tool_tblgen_sources") { + include_dirs = [ + "//$clspv_llvm_dir/llvm/utils/TableGen", + "//$clspv_llvm_dir/llvm/lib/Transforms/Utils", + ] deps = [ "$clspv_gn_dir/llvm/config:abi-breaking", "$clspv_gn_dir/llvm/config:llvm-config", @@ -2044,21 +2415,33 @@ clspv_llvm_source_set("clspv_llvm_tool_tblgen_sources") { sources = [ "//$clspv_llvm_dir/llvm/utils/TableGen/AsmMatcherEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/AsmWriterEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/AsmWriterInst.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/CTagsEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/CallingConvEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/CodeEmitterGen.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenDAGPatterns.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenHwModes.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenInstAlias.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenInstruction.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenMapTable.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenRegisters.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenSchedule.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/CodeGenTarget.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/AsmWriterInst.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenHwModes.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenInstruction.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenRegisters.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenSchedule.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/CodeGenTarget.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/DAGISelMatcher.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/InfoByHwMode.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/InstructionEncoding.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/OptEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/PredicateExpander.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/SubtargetFeatureInfo.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/Types.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/Utils.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/CompressInstEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DAGISelEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/DAGISelMatcher.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DAGISelMatcherGen.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DAGISelMatcherOpt.cpp", @@ -2066,32 +2449,27 @@ clspv_llvm_source_set("clspv_llvm_tool_tblgen_sources") { "//$clspv_llvm_dir/llvm/utils/TableGen/DFAPacketizerEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DXILEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DecoderEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/DecoderTableEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/DecoderTree.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/DisassemblerEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/ExegesisEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/FastISelEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISelEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISelMatchTable.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/InfoByHwMode.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/InstrDocsEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/InstrInfoEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/OptEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/OptParserEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/OptRSTEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/PredicateExpander.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/OptionParserEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/OptionRSTEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/PseudoLoweringEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/RegisterBankEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/RegisterInfoEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/SearchableTableEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/SubtargetEmitter.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/SubtargetFeatureInfo.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/Types.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/VarLenCodeEmitterGen.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/X86DisassemblerTables.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/X86FoldTablesEmitter.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/X86InstrMappingEmitter.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/X86MnemonicTables.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/X86ModRMFilters.cpp", "//$clspv_llvm_dir/llvm/utils/TableGen/X86RecognizableInstr.cpp", @@ -2099,16 +2477,17 @@ clspv_llvm_source_set("clspv_llvm_tool_tblgen_sources") { } clspv_llvm_static_lib("clspv_llvm_utils_lib_tablegen_globalisel") { + include_dirs = [ "//$clspv_llvm_dir/llvm/utils/TableGen" ] deps = [ ":clspv_llvm_lib_codegen_types", ":clspv_llvm_lib_support", "$clspv_gn_dir/llvm/tablegen:GenVT", ] sources = [ - "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISel/CXXPredicates.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISel/CodeExpander.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISel/MatchDataInfo.cpp", - "//$clspv_llvm_dir/llvm/utils/TableGen/GlobalISel/Patterns.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/CodeExpander.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp", + "//$clspv_llvm_dir/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp", ] } @@ -2156,8 +2535,18 @@ clspv_clang_static_lib("clspv_clang_lib_analysis") { "//$clspv_llvm_dir/clang/lib/Analysis/Consumed.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/Dominators.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/ExprMutationAnalyzer.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/FixitUtil.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/IntervalPartition.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/IssueHash.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/Checker.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/Facts.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/Loans.cpp", + "//$clspv_llvm_dir/clang/lib/Analysis/LifetimeSafety/Origins.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/LiveVariables.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/MacroExpansionContext.cpp", "//$clspv_llvm_dir/clang/lib/Analysis/ObjCNoReturn.cpp", @@ -2193,6 +2582,7 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { include_dirs = [ "$clspv_llvm_dir/clang/include", "$root_gen_dir/$clspv_llvm_dir/clang/AST", # for gen inc files + "$root_gen_dir/third_party/llvm/src/clang/include", ] deps = [ ":clspv_clang_lib_basic", @@ -2240,6 +2630,33 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { "//$clspv_llvm_dir/clang/lib/AST/ASTTypeTraits.cpp", "//$clspv_llvm_dir/clang/lib/AST/AttrDocTable.cpp", "//$clspv_llvm_dir/clang/lib/AST/AttrImpl.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/BitcastBuffer.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Compiler.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Context.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Descriptor.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Disasm.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/DynamicAllocator.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/EvalEmitter.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/EvaluationResult.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Floating.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Function.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/FunctionPointer.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Interp.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpBlock.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpBuiltin.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpFrame.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpShared.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpStack.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/InterpState.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/MemberPointer.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Pointer.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/PrimType.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Program.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Record.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Source.cpp", + "//$clspv_llvm_dir/clang/lib/AST/ByteCode/State.cpp", "//$clspv_llvm_dir/clang/lib/AST/CXXInheritance.cpp", "//$clspv_llvm_dir/clang/lib/AST/Comment.cpp", "//$clspv_llvm_dir/clang/lib/AST/CommentBriefParser.cpp", @@ -2256,10 +2673,12 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { "//$clspv_llvm_dir/clang/lib/AST/DeclFriend.cpp", "//$clspv_llvm_dir/clang/lib/AST/DeclGroup.cpp", "//$clspv_llvm_dir/clang/lib/AST/DeclObjC.cpp", + "//$clspv_llvm_dir/clang/lib/AST/DeclOpenACC.cpp", "//$clspv_llvm_dir/clang/lib/AST/DeclOpenMP.cpp", "//$clspv_llvm_dir/clang/lib/AST/DeclPrinter.cpp", "//$clspv_llvm_dir/clang/lib/AST/DeclTemplate.cpp", "//$clspv_llvm_dir/clang/lib/AST/DeclarationName.cpp", + "//$clspv_llvm_dir/clang/lib/AST/DynamicRecursiveASTVisitor.cpp", "//$clspv_llvm_dir/clang/lib/AST/Expr.cpp", "//$clspv_llvm_dir/clang/lib/AST/ExprCXX.cpp", "//$clspv_llvm_dir/clang/lib/AST/ExprClassification.cpp", @@ -2270,29 +2689,6 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { "//$clspv_llvm_dir/clang/lib/AST/ExternalASTSource.cpp", "//$clspv_llvm_dir/clang/lib/AST/FormatString.cpp", "//$clspv_llvm_dir/clang/lib/AST/InheritViz.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/ByteCodeEmitter.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/ByteCodeExprGen.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/ByteCodeGenError.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/ByteCodeStmtGen.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Context.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Descriptor.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Disasm.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/EvalEmitter.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Floating.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Frame.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Function.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Interp.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/InterpBlock.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/InterpBuiltin.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/InterpFrame.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/InterpStack.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/InterpState.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Pointer.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/PrimType.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Program.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Record.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/Source.cpp", - "//$clspv_llvm_dir/clang/lib/AST/Interp/State.cpp", "//$clspv_llvm_dir/clang/lib/AST/ItaniumCXXABI.cpp", "//$clspv_llvm_dir/clang/lib/AST/ItaniumMangle.cpp", "//$clspv_llvm_dir/clang/lib/AST/JSONNodeDumper.cpp", @@ -2304,6 +2700,7 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { "//$clspv_llvm_dir/clang/lib/AST/ODRDiagsEmitter.cpp", "//$clspv_llvm_dir/clang/lib/AST/ODRHash.cpp", "//$clspv_llvm_dir/clang/lib/AST/OSLog.cpp", + "//$clspv_llvm_dir/clang/lib/AST/OpenACCClause.cpp", "//$clspv_llvm_dir/clang/lib/AST/OpenMPClause.cpp", "//$clspv_llvm_dir/clang/lib/AST/ParentMap.cpp", "//$clspv_llvm_dir/clang/lib/AST/ParentMapContext.cpp", @@ -2319,6 +2716,7 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { "//$clspv_llvm_dir/clang/lib/AST/StmtCXX.cpp", "//$clspv_llvm_dir/clang/lib/AST/StmtIterator.cpp", "//$clspv_llvm_dir/clang/lib/AST/StmtObjC.cpp", + "//$clspv_llvm_dir/clang/lib/AST/StmtOpenACC.cpp", "//$clspv_llvm_dir/clang/lib/AST/StmtOpenMP.cpp", "//$clspv_llvm_dir/clang/lib/AST/StmtPrinter.cpp", "//$clspv_llvm_dir/clang/lib/AST/StmtProfile.cpp", @@ -2331,6 +2729,7 @@ clspv_clang_static_lib("clspv_clang_lib_ast") { "//$clspv_llvm_dir/clang/lib/AST/TypePrinter.cpp", "//$clspv_llvm_dir/clang/lib/AST/VTTBuilder.cpp", "//$clspv_llvm_dir/clang/lib/AST/VTableBuilder.cpp", + "//$clspv_llvm_dir/clang/lib/ASTMatchers/LowLevelHelpers.cpp", ] } @@ -2343,7 +2742,6 @@ clspv_clang_static_lib("clspv_clang_lib_astmatchers") { sources = [ "//$clspv_llvm_dir/clang/lib/ASTMatchers/ASTMatchFinder.cpp", "//$clspv_llvm_dir/clang/lib/ASTMatchers/ASTMatchersInternal.cpp", - "//$clspv_llvm_dir/clang/lib/ASTMatchers/GtestMatchers.cpp", ] } @@ -2351,13 +2749,26 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { public_deps = [ # public_dep because public header Version.h includes generated Version.inc. "$clspv_gn_dir/llvm/config/clang:version", - "$clspv_gn_dir/llvm/tablegen:AttrLeftSideCanPrintList", - "$clspv_gn_dir/llvm/tablegen:AttrLeftSideMustPrintList", + "$clspv_gn_dir/llvm/tablegen:AArch64TargetParserDef", "$clspv_gn_dir/llvm/tablegen:AttrList", "$clspv_gn_dir/llvm/tablegen:AttrSubMatchRulesList", - "$clspv_gn_dir/llvm/tablegen:AttrTokenKinds", + "$clspv_gn_dir/llvm/tablegen:Builtins", + "$clspv_gn_dir/llvm/tablegen:BuiltinsBPF", + "$clspv_gn_dir/llvm/tablegen:BuiltinsDirectX", + "$clspv_gn_dir/llvm/tablegen:BuiltinsHexagon", + "$clspv_gn_dir/llvm/tablegen:BuiltinsNVPTX", + "$clspv_gn_dir/llvm/tablegen:BuiltinsRISCV", + "$clspv_gn_dir/llvm/tablegen:BuiltinsSPIRV", + "$clspv_gn_dir/llvm/tablegen:BuiltinsSPIRVCL", + "$clspv_gn_dir/llvm/tablegen:BuiltinsSPIRVCommon", + "$clspv_gn_dir/llvm/tablegen:BuiltinsSPIRVVK", + "$clspv_gn_dir/llvm/tablegen:BuiltinsX86", + "$clspv_gn_dir/llvm/tablegen:BuiltinsX86_64", + "$clspv_gn_dir/llvm/tablegen:DiagnosticAllCompatIDs", "$clspv_gn_dir/llvm/tablegen:DiagnosticGroups", + "$clspv_gn_dir/llvm/tablegen:RegularKeywordAttrInfo", "$clspv_gn_dir/llvm/tablegen:arm_cde_builtins", + "$clspv_gn_dir/llvm/tablegen:arm_immcheck_types", "$clspv_gn_dir/llvm/tablegen:arm_mve_builtins", "$clspv_gn_dir/llvm/tablegen:arm_sme_builtins", "$clspv_gn_dir/llvm/tablegen:arm_sve_builtins", @@ -2369,6 +2780,8 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { # public_dep because public header AttributeCommonInfo.h includes generated # AttrParsedAttrList.inc. "$clspv_gn_dir/llvm/tablegen:AttrParsedAttrList", + "$clspv_gn_dir/llvm/tablegen:BuiltinTemplates", + "$clspv_gn_dir/llvm/tablegen:CXX11AttributeInfo", # public_dep because public header OpenMPKinds.h includes generated # OMP.h.inc. @@ -2383,11 +2796,19 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { "$clspv_gn_dir/llvm/tablegen:AttrHasAttributeImpl", "$clspv_gn_dir/llvm/tablegen:AttrParsedAttrKinds", "$clspv_gn_dir/llvm/tablegen:AttrSpellingListIndex", + "$clspv_gn_dir/llvm/tablegen:AttributeSpellingList", "$clspv_gn_dir/llvm/tablegen:arm_fp16", "$clspv_gn_dir/llvm/tablegen:arm_neon", + "$clspv_gn_dir/llvm/tablegen:riscv_andes_vector_builtin_cg", + "$clspv_gn_dir/llvm/tablegen:riscv_andes_vector_builtin_sema", + "$clspv_gn_dir/llvm/tablegen:riscv_andes_vector_builtins", + ] + include_dirs = [ + "$root_gen_dir/third_party/llvm/src/clang/include", + "//$clspv_llvm_dir/clang/lib/Basic", ] - include_dirs = [ "//$clspv_llvm_dir/clang/lib/Basic" ] sources = [ + "//$clspv_llvm_dir/clang/lib/Basic/ASTSourceDescriptor.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Attributes.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Builtins.cpp", "//$clspv_llvm_dir/clang/lib/Basic/CLWarnings.cpp", @@ -2409,6 +2830,7 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { "//$clspv_llvm_dir/clang/lib/Basic/Module.cpp", "//$clspv_llvm_dir/clang/lib/Basic/NoSanitizeList.cpp", "//$clspv_llvm_dir/clang/lib/Basic/ObjCRuntime.cpp", + "//$clspv_llvm_dir/clang/lib/Basic/OffloadArch.cpp", "//$clspv_llvm_dir/clang/lib/Basic/OpenCLOptions.cpp", "//$clspv_llvm_dir/clang/lib/Basic/OpenMPKinds.cpp", "//$clspv_llvm_dir/clang/lib/Basic/OperatorPrecedence.cpp", @@ -2417,10 +2839,12 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { "//$clspv_llvm_dir/clang/lib/Basic/SanitizerSpecialCaseList.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Sanitizers.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Sarif.cpp", + "//$clspv_llvm_dir/clang/lib/Basic/SimpleTypoCorrection.cpp", "//$clspv_llvm_dir/clang/lib/Basic/SourceLocation.cpp", "//$clspv_llvm_dir/clang/lib/Basic/SourceManager.cpp", "//$clspv_llvm_dir/clang/lib/Basic/SourceMgrAdapter.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Stack.cpp", + "//$clspv_llvm_dir/clang/lib/Basic/StackExhaustionHandler.cpp", "//$clspv_llvm_dir/clang/lib/Basic/TargetID.cpp", "//$clspv_llvm_dir/clang/lib/Basic/TargetInfo.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets.cpp", @@ -2434,14 +2858,12 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { "//$clspv_llvm_dir/clang/lib/Basic/Targets/DirectX.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/Hexagon.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/Lanai.cpp", - "//$clspv_llvm_dir/clang/lib/Basic/Targets/Le64.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/LoongArch.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/M68k.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/MSP430.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/Mips.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/NVPTX.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/OSTargets.cpp", - "//$clspv_llvm_dir/clang/lib/Basic/Targets/PNaCl.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/PPC.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/RISCV.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/SPIR.cpp", @@ -2452,6 +2874,7 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { "//$clspv_llvm_dir/clang/lib/Basic/Targets/WebAssembly.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/X86.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Targets/XCore.cpp", + "//$clspv_llvm_dir/clang/lib/Basic/Targets/Xtensa.cpp", "//$clspv_llvm_dir/clang/lib/Basic/TokenKinds.cpp", "//$clspv_llvm_dir/clang/lib/Basic/TypeTraits.cpp", "//$clspv_llvm_dir/clang/lib/Basic/Version.cpp", @@ -2461,21 +2884,69 @@ clspv_clang_static_lib("clspv_clang_lib_basic") { ] } +clspv_llvm_source_set("clspv_clang_lib_codegen_target_builtins") { + deps = [ + "$clspv_gn_dir/llvm/tablegen:arm_cde_builtin_cg", + "$clspv_gn_dir/llvm/tablegen:arm_mve_builtin_cg", + "$clspv_gn_dir/llvm/tablegen:arm_sme_builtin_cg", + "$clspv_gn_dir/llvm/tablegen:arm_sve_builtin_cg", + "$clspv_gn_dir/llvm/tablegen:public_tablegen", + "$clspv_gn_dir/llvm/tablegen:riscv_sifive_vector_builtin_cg", + "$clspv_gn_dir/llvm/tablegen:riscv_vector_builtin_cg", + "//third_party/clspv/gn/llvm/tablegen:AArch64TargetParserDef", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsAArch64", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsAMDGPU", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsARM", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsBPF", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsHexagon", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsNVPTX", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsPowerPC", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsR600", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsRISCV", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsS390", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsWebAssembly", + "//third_party/clspv/gn/llvm/tablegen:IntrinsicsX86", + ] + public_deps = [ + "$clspv_gn_dir/llvm/tablegen:TypeNodes", + "$clspv_gn_dir/llvm/tablegen:diags_tablegen", + ] + include_dirs = [ + "$clspv_llvm_dir/clang/include", + "//$clspv_llvm_dir/clang/lib/CodeGen", + "$root_gen_dir/third_party/llvm/src/clang/include", + ] + sources = [ + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/ARM.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/DirectX.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/Hexagon.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/PPC.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/SystemZ.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TargetBuiltins/X86.cpp", + ] +} + if (true) { clspv_clang_static_lib("clspv_clang_lib_codegen") { deps = [ ":clspv_clang_lib_analysis", ":clspv_clang_lib_ast", ":clspv_clang_lib_basic", + ":clspv_clang_lib_codegen_target_builtins", ":clspv_clang_lib_frontend", ":clspv_clang_lib_lex", ":clspv_llvm_lib_analysis", ":clspv_llvm_lib_bitcode_reader", ":clspv_llvm_lib_codegen", ":clspv_llvm_lib_demangle", + ":clspv_llvm_lib_frontend_atomic", ":clspv_llvm_lib_frontend_driver", ":clspv_llvm_lib_frontend_hlsl", - ":clspv_llvm_lib_frontend_offloading", ":clspv_llvm_lib_ir", ":clspv_llvm_lib_irprinter", ":clspv_llvm_lib_irreader", @@ -2496,6 +2967,7 @@ if (true) { ":clspv_llvm_lib_transforms_objcarc", ":clspv_llvm_lib_transforms_scalar", ":clspv_llvm_lib_transforms_utils", + "$clspv_gn_dir/llvm/config:llvm-config", "$clspv_gn_dir/llvm/config:write_extension_def", "$clspv_gn_dir/llvm/tablegen:arm_cde_builtin_cg", "$clspv_gn_dir/llvm/tablegen:arm_mve_builtin_cg", @@ -2504,7 +2976,10 @@ if (true) { "$clspv_gn_dir/llvm/tablegen:riscv_sifive_vector_builtin_cg", "$clspv_gn_dir/llvm/tablegen:riscv_vector_builtin_cg", ] - include_dirs = [ "//$clspv_llvm_dir/clang/lib/CodeGen" ] + include_dirs = [ + "//$clspv_llvm_dir/clang/lib/CodeGen", + "$root_gen_dir/third_party/llvm/src/clang/include", + ] sources = [ "//$clspv_llvm_dir/clang/lib/CodeGen/ABIInfo.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/ABIInfoImpl.cpp", @@ -2531,6 +3006,7 @@ if (true) { "//$clspv_llvm_dir/clang/lib/CodeGen/CGExprConstant.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGExprScalar.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGGPUBuiltin.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/CGHLSLBuiltins.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGHLSLRuntime.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGLoopInfo.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGNonTrivialStruct.cpp", @@ -2541,6 +3017,7 @@ if (true) { "//$clspv_llvm_dir/clang/lib/CodeGen/CGOpenCLRuntime.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGOpenMPRuntime.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/CGPointerAuth.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGStmt.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CGStmtOpenMP.cpp", @@ -2551,16 +3028,18 @@ if (true) { "//$clspv_llvm_dir/clang/lib/CodeGen/CodeGenFunction.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CodeGenModule.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CodeGenPGO.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/CodeGenSYCL.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CodeGenTBAA.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CodeGenTypes.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/ConstantInitBuilder.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/CoverageMappingGen.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/ItaniumCXXABI.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/LinkInModulesPass.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/MacroPPCallbacks.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/MicrosoftCXXABI.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/ModuleBuilder.cpp", - "//$clspv_llvm_dir/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/PatternInit.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/SanitizerMetadata.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/SwiftCallingConv.cpp", @@ -2572,6 +3051,7 @@ if (true) { "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/AVR.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/BPF.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/CSKY.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/DirectX.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/Hexagon.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/Lanai.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/LoongArch.cpp", @@ -2579,7 +3059,6 @@ if (true) { "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/MSP430.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/Mips.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/NVPTX.cpp", - "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/PNaCl.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/PPC.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/RISCV.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/SPIR.cpp", @@ -2590,6 +3069,7 @@ if (true) { "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/WebAssembly.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/X86.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/Targets/XCore.cpp", + "//$clspv_llvm_dir/clang/lib/CodeGen/TrapReasonBuilder.cpp", "//$clspv_llvm_dir/clang/lib/CodeGen/VarBypassDetector.cpp", ] } @@ -2617,6 +3097,7 @@ clspv_clang_static_lib("clspv_clang_lib_driver") { public_deps = [ # public_dep because public header Options.h includes generated Options.inc. "$clspv_gn_dir/llvm/tablegen:Options", + "$clspv_gn_dir/llvm/tablegen:diags_tablegen", ] if (false) { # FIXME if (host_os == "win") { @@ -2624,7 +3105,10 @@ clspv_clang_static_lib("clspv_clang_lib_driver") { libs = [ "version.lib" ] } } - include_dirs = [ "//$clspv_llvm_dir/clang/lib/Driver" ] + include_dirs = [ + "//$clspv_llvm_dir/clang/lib/Driver", + "$root_gen_dir/third_party/llvm/src/clang/include", + ] sources = [ "//$clspv_llvm_dir/clang/lib/Driver/Action.cpp", "//$clspv_llvm_dir/clang/lib/Driver/Compilation.cpp", @@ -2662,6 +3146,7 @@ clspv_clang_static_lib("clspv_clang_lib_driver") { "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/CommonArgs.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/CrossWindows.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Cuda.cpp", + "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Cygwin.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Darwin.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/DragonFly.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Flang.cpp", @@ -2679,19 +3164,21 @@ clspv_clang_static_lib("clspv_clang_lib_driver") { "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Linux.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/MSP430.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/MSVC.cpp", + "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Managarm.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/MinGW.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/MipsLinux.cpp", - "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/NaCl.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/NetBSD.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/OHOS.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/OpenBSD.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/PPCFreeBSD.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/PPCLinux.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/PS4CPU.cpp", - "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/RISCVToolchain.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/SPIRV.cpp", + "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp", + "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/SYCL.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/Solaris.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/TCE.cpp", + "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/UEFI.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/VEToolchain.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/WebAssembly.cpp", "//$clspv_llvm_dir/clang/lib/Driver/ToolChains/XCore.cpp", @@ -2777,16 +3264,20 @@ clspv_clang_static_lib("clspv_clang_lib_lex") { ":clspv_llvm_lib_targetparser", "$clspv_gn_dir/llvm/config/clang:Config", ] + public_deps = [ "$clspv_gn_dir/llvm/tablegen:diags_tablegen" ] + include_dirs = [ "$root_gen_dir/third_party/llvm/src/clang/include" ] sources = [ "//$clspv_llvm_dir/clang/lib/Lex/DependencyDirectivesScanner.cpp", "//$clspv_llvm_dir/clang/lib/Lex/HeaderMap.cpp", "//$clspv_llvm_dir/clang/lib/Lex/HeaderSearch.cpp", "//$clspv_llvm_dir/clang/lib/Lex/InitHeaderSearch.cpp", + "//$clspv_llvm_dir/clang/lib/Lex/LexHLSLRootSignature.cpp", "//$clspv_llvm_dir/clang/lib/Lex/Lexer.cpp", "//$clspv_llvm_dir/clang/lib/Lex/LiteralSupport.cpp", "//$clspv_llvm_dir/clang/lib/Lex/MacroArgs.cpp", "//$clspv_llvm_dir/clang/lib/Lex/MacroInfo.cpp", "//$clspv_llvm_dir/clang/lib/Lex/ModuleMap.cpp", + "//$clspv_llvm_dir/clang/lib/Lex/ModuleMapFile.cpp", "//$clspv_llvm_dir/clang/lib/Lex/PPCaching.cpp", "//$clspv_llvm_dir/clang/lib/Lex/PPCallbacks.cpp", "//$clspv_llvm_dir/clang/lib/Lex/PPConditionalDirectiveRecord.cpp", @@ -2818,6 +3309,8 @@ clspv_clang_static_lib("clspv_clang_lib_parse") { "$clspv_gn_dir/llvm/tablegen:AttrParserStringSwitches", "$clspv_gn_dir/llvm/tablegen:AttrSubMatchRulesParserStringSwitches", ] + public_deps = [ "$clspv_gn_dir/llvm/tablegen:diags_tablegen" ] + include_dirs = [ "$root_gen_dir/third_party/llvm/src/clang/include" ] sources = [ "//$clspv_llvm_dir/clang/lib/Parse/ParseAST.cpp", "//$clspv_llvm_dir/clang/lib/Parse/ParseCXXInlineMethods.cpp", @@ -2826,6 +3319,7 @@ clspv_clang_static_lib("clspv_clang_lib_parse") { "//$clspv_llvm_dir/clang/lib/Parse/ParseExpr.cpp", "//$clspv_llvm_dir/clang/lib/Parse/ParseExprCXX.cpp", "//$clspv_llvm_dir/clang/lib/Parse/ParseHLSL.cpp", + "//$clspv_llvm_dir/clang/lib/Parse/ParseHLSLRootSignature.cpp", "//$clspv_llvm_dir/clang/lib/Parse/ParseInit.cpp", "//$clspv_llvm_dir/clang/lib/Parse/ParseObjc.cpp", "//$clspv_llvm_dir/clang/lib/Parse/ParseOpenACC.cpp", @@ -2862,18 +3356,28 @@ clspv_clang_static_lib("clspv_clang_lib_sema") { "$clspv_gn_dir/llvm/tablegen:arm_cde_builtin_sema", "$clspv_gn_dir/llvm/tablegen:arm_mve_builtin_aliases", "$clspv_gn_dir/llvm/tablegen:arm_mve_builtin_sema", + "$clspv_gn_dir/llvm/tablegen:arm_sme_builtins_za_state", "$clspv_gn_dir/llvm/tablegen:arm_sme_sema_rangechecks", + "$clspv_gn_dir/llvm/tablegen:arm_sme_streaming_attrs", "$clspv_gn_dir/llvm/tablegen:arm_sve_sema_rangechecks", + "$clspv_gn_dir/llvm/tablegen:arm_sve_streaming_attrs", "$clspv_gn_dir/llvm/tablegen:riscv_sifive_vector_builtin_sema", "$clspv_gn_dir/llvm/tablegen:riscv_vector_builtin_sema", ] - include_dirs = [ "$root_gen_dir/$clspv_llvm_dir/clang/lib/Sema" ] + public_deps = [ "$clspv_gn_dir/llvm/tablegen:diags_tablegen" ] + include_dirs = [ + "$root_gen_dir/$clspv_llvm_dir/clang/lib/Sema", + "$root_gen_dir/third_party/llvm/src/clang/include", + ] sources = [ "//$clspv_llvm_dir/clang/lib/Sema/AnalysisBasedWarnings.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/CheckExprLifetime.cpp", "//$clspv_llvm_dir/clang/lib/Sema/CodeCompleteConsumer.cpp", "//$clspv_llvm_dir/clang/lib/Sema/DeclSpec.cpp", "//$clspv_llvm_dir/clang/lib/Sema/DelayedDiagnostic.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp", "//$clspv_llvm_dir/clang/lib/Sema/HLSLExternalSemaSource.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/HeuristicResolver.cpp", "//$clspv_llvm_dir/clang/lib/Sema/IdentifierResolver.cpp", "//$clspv_llvm_dir/clang/lib/Sema/JumpDiagnostics.cpp", "//$clspv_llvm_dir/clang/lib/Sema/MultiplexExternalSemaSource.cpp", @@ -2881,9 +3385,16 @@ clspv_clang_static_lib("clspv_clang_lib_sema") { "//$clspv_llvm_dir/clang/lib/Sema/Scope.cpp", "//$clspv_llvm_dir/clang/lib/Sema/ScopeInfo.cpp", "//$clspv_llvm_dir/clang/lib/Sema/Sema.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaAMDGPU.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaAPINotes.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaARM.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaAVR.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaAccess.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaAttr.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaAvailability.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaBPF.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaBase.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaBoundsSafety.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaCUDA.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaCXXScopeSpec.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaCast.cpp", @@ -2896,32 +3407,54 @@ clspv_clang_static_lib("clspv_clang_lib_sema") { "//$clspv_llvm_dir/clang/lib/Sema/SemaDeclAttr.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaDeclCXX.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaDeclObjC.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaDirectX.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaExceptionSpec.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaExpr.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaExprCXX.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaExprMember.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaExprObjC.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaFixItUtils.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaFunctionEffects.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaHLSL.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaHexagon.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaInit.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaLambda.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaLookup.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaLoongArch.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaM68k.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaMIPS.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaMSP430.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaModule.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaNVPTX.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaObjC.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaObjCProperty.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaOpenACC.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaOpenACCAtomic.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaOpenACCClause.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaOpenCL.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaOpenMP.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaOverload.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaPPC.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaPseudoObject.cpp", - "//$clspv_llvm_dir/clang/lib/Sema/SemaRISCVVectorLookup.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaRISCV.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaSPIRV.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaSYCL.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaStmt.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaStmtAsm.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaStmtAttr.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaSwift.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaSystemZ.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaTemplate.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaTemplateDeduction.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaTemplateDeductionGuide.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaTemplateInstantiate.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaTemplateVariadic.cpp", "//$clspv_llvm_dir/clang/lib/Sema/SemaType.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaTypeTraits.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaWasm.cpp", + "//$clspv_llvm_dir/clang/lib/Sema/SemaX86.cpp", "//$clspv_llvm_dir/clang/lib/Sema/TypeLocBuilder.cpp", ] } @@ -2938,6 +3471,8 @@ clspv_clang_static_lib("clspv_clang_lib_serialization") { "$clspv_gn_dir/llvm/tablegen:AttrPCHRead", "$clspv_gn_dir/llvm/tablegen:AttrPCHWrite", ] + public_deps = [ "$clspv_gn_dir/llvm/tablegen:diags_tablegen" ] + include_dirs = [ "$root_gen_dir/third_party/llvm/src/clang/include" ] sources = [ "//$clspv_llvm_dir/clang/lib/Serialization/ASTCommon.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/ASTCommon.h", @@ -2951,10 +3486,12 @@ clspv_clang_static_lib("clspv_clang_lib_serialization") { "//$clspv_llvm_dir/clang/lib/Serialization/GeneratePCH.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/GlobalModuleIndex.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/InMemoryModuleCache.cpp", + "//$clspv_llvm_dir/clang/lib/Serialization/ModuleCache.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/ModuleFile.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/ModuleFileExtension.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/ModuleManager.cpp", "//$clspv_llvm_dir/clang/lib/Serialization/PCHContainerOperations.cpp", + "//$clspv_llvm_dir/clang/lib/Serialization/TemplateArgumentHasher.cpp", ] } diff --git a/third_party/clspv/gn/llvm/tablegen/BUILD.gn b/third_party/clspv/gn/llvm/tablegen/BUILD.gn index 6bb2aa145fe..a18610c7c3c 100644 --- a/third_party/clspv/gn/llvm/tablegen/BUILD.gn +++ b/third_party/clspv/gn/llvm/tablegen/BUILD.gn @@ -20,6 +20,27 @@ tablegen("RISCVTargetParserDef") { output_name = "$clspv_llvm_dir/llvm/TargetParser/RISCVTargetParserDef.inc" } +tablegen("ARMTargetParserDef") { + args = [ "-gen-arm-target-def" ] + td_file = "//$clspv_llvm_dir/llvm/lib/Target/ARM/ARM.td" + tblgen_target = "../tools:clspv-tool-llvm-min-tblgen" + output_name = "$clspv_llvm_dir/llvm/TargetParser/ARMTargetParserDef.inc" +} + +tablegen("AArch64TargetParserDef") { + args = [ "-gen-arm-target-def" ] + td_file = "//$clspv_llvm_dir/llvm/lib/Target/AArch64/AArch64.td" + tblgen_target = "../tools:clspv-tool-llvm-min-tblgen" + output_name = "$clspv_llvm_dir/llvm/TargetParser/AArch64TargetParserDef.inc" +} + +tablegen("PPCGenTargetFeatures") { + args = [ "-gen-target-features" ] + td_file = "//$clspv_llvm_dir/llvm/lib/Target/PowerPC/PPC.td" + tblgen_target = "../tools:clspv-tool-llvm-min-tblgen" + output_name = "$clspv_llvm_dir/llvm/TargetParser/PPCGenTargetFeatures.inc" +} + # from llvm/include/llvm/Frontend/OpenMP tablegen("OMPh") { #visibility = [ ":public_tablegen" ] @@ -37,6 +58,14 @@ tablegen("OMP") { output_name = "$clspv_llvm_dir/llvm/Frontend/OpenMP/OMP.inc" } +tablegen("ACCcpp") { + #visibility = [ ":public_tablegen" ] + args = [ "-gen-directive-impl" ] + td_file = "//$clspv_llvm_dir/llvm/include/llvm/Frontend/OpenACC/ACC.td" + tblgen_target = "../tools:clspv-tool-llvm-min-tblgen" + output_name = "$clspv_llvm_dir/llvm/Frontend/OpenACC/ACC.inc" +} + # from llvm/include/llvm/IR tablegen("Attributes") { #visibility = [ ":public_tablegen" ] @@ -46,6 +75,14 @@ tablegen("Attributes") { output_name = "$clspv_llvm_dir/llvm/IR/Attributes.inc" } +tablegen("RuntimeLibcalls") { + #visibility = [ ":public_tablegen" ] + args = [ "-gen-runtime-libcalls" ] + td_file = "//$clspv_llvm_dir/llvm/include/llvm/IR/RuntimeLibcalls.td" + tblgen_target = "../tools:clspv-tool-llvm-min-tblgen" + output_name = "$clspv_llvm_dir/llvm/IR/RuntimeLibcalls.inc" +} + tablegen("IntrinsicImpl") { args = [ "-gen-intrinsic-impl" ] td_file = "//$clspv_llvm_dir/llvm/include/llvm/IR/Intrinsics.td" @@ -126,6 +163,10 @@ gen_arch_intrinsics("IntrinsicsS390") { intrinsic_prefix = "s390" } +gen_arch_intrinsics("IntrinsicsSPIRV") { + intrinsic_prefix = "spv" +} + gen_arch_intrinsics("IntrinsicsVE") { intrinsic_prefix = "ve" } @@ -151,6 +192,9 @@ group("public_tablegen") { # IR's public headers include Attributes.inc. ":Attributes", + # IR's public headers include RuntimeLibcalls.inc. + ":RuntimeLibcalls", + # IR's public headers include IntrinsicEnums.inc. ":IntrinsicEnums", ":IntrinsicImpl", @@ -170,6 +214,7 @@ group("public_tablegen") { ":IntrinsicsR600", ":IntrinsicsRISCV", ":IntrinsicsS390", + ":IntrinsicsSPIRV", ":IntrinsicsVE", ":IntrinsicsWebAssembly", ":IntrinsicsX86", @@ -178,6 +223,9 @@ group("public_tablegen") { # Frontend/OpenMP ":OMP", ":OMPh", + + # Frontend/OpenACC + ":ACCcpp", ] } @@ -303,7 +351,7 @@ clang_tablegen("StmtDataCollectors") { # from clang/lib/AST clang_tablegen("Opcodes") { args = [ "-gen-clang-opcodes" ] - td_file = "//$clspv_llvm_dir/clang/lib/AST/Interp/Opcodes.td" + td_file = "//$clspv_llvm_dir/clang/lib/AST/ByteCode/Opcodes.td" output_name = "$clspv_llvm_dir/clang/AST/Opcodes.inc" } @@ -329,6 +377,8 @@ diag_groups = [ "Refactoring", "Sema", "Serialization", + "InstallAPI", + "Trap", ] foreach(diag_group, diag_groups) { clang_tablegen("Diagnostic${diag_group}Kinds") { @@ -337,16 +387,50 @@ foreach(diag_group, diag_groups) { "-clang-component=${diag_group}", ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Diagnostic.td" - output_name = "$clspv_llvm_dir/clang/Basic/Diagnostic${diag_group}Kinds.inc" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" + } + + clang_tablegen("Diagnostic${diag_group}Enums") { + args = [ + "-gen-clang-diags-enums", + "-clang-component=${diag_group}", + ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Diagnostic.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" + } + + clang_tablegen("Diagnostic${diag_group}CompatIDs") { + args = [ + "-gen-clang-diags-compat-ids", + "-clang-component=${diag_group}", + ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Diagnostic.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" + } + + clang_tablegen("Diagnostic${diag_group}Interface") { + args = [ + "-gen-clang-diags-iface", + "-clang-component=${diag_group}", + ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Diagnostic.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } } group("diags_tablegen") { - # DiagnosticGroups and DiagnosticIndexName are intentionally not part of this - # group. Much of clang depends on the DiagKinds.inc files transitively, - # but almost nothing needs DiagnosticGroups.inc or DiagnosticIndexName.inc. + # DiagnosticGroups, DiagnosticIndexName, DiagnosticAllCompatIDs are + # intentionally not part of this group. Much of clang depends on the + # DiagKinds.inc files transitively, but almost nothing needs + # DiagnosticGroups.inc, DiagnosticIndexName.inc, or + # DiagnosticAllCompatIDs.inc. public_deps = [] foreach(diag_group, diag_groups) { - public_deps += [ ":Diagnostic${diag_group}Kinds" ] + public_deps += [ + ":Diagnostic${diag_group}CompatIDs", + ":Diagnostic${diag_group}Enums", + ":Diagnostic${diag_group}Interface", + ":Diagnostic${diag_group}Kinds", + ] } } @@ -362,6 +446,12 @@ clang_tablegen("DiagnosticIndexName") { output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } +clang_tablegen("DiagnosticAllCompatIDs") { + args = [ "-gen-clang-diags-compat-ids" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Diagnostic.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + # Attributes clang_tablegen("AttrList") { @@ -370,33 +460,99 @@ clang_tablegen("AttrList") { output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } -clang_tablegen("AttrLeftSideCanPrintList") { - args = [ "-gen-clang-attr-can-print-left-list" ] +clang_tablegen("AttrSubMatchRulesList") { + args = [ "-gen-clang-attr-subject-match-rule-list" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } -clang_tablegen("AttrLeftSideMustPrintList") { - args = [ "-gen-clang-attr-must-print-left-list" ] +clang_tablegen("RegularKeywordAttrInfo") { + args = [ "-gen-clang-regular-keyword-attr-info" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } -clang_tablegen("AttrSubMatchRulesList") { - args = [ "-gen-clang-attr-subject-match-rule-list" ] +clang_tablegen("AttrHasAttributeImpl") { + args = [ "-gen-clang-attr-has-attribute-impl" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } -clang_tablegen("AttrTokenKinds") { - args = [ "-gen-clang-attr-token-kinds" ] +clang_tablegen("AttributeSpellingList") { + args = [ "-gen-attribute-spelling-list" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } -clang_tablegen("AttrHasAttributeImpl") { - args = [ "-gen-clang-attr-has-attribute-impl" ] - td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" +clang_tablegen("Builtins") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Builtins.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsBPF") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsBPF.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsNVPTX") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsNVPTX.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsSPIRV") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsSPIRVBase.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsX86_64") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsX86_64.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsHexagon") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsHexagon.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsRISCV") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsRISCV.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsX86") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsX86.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsDirectX") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsDirectX.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsSPIRVCommon") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsSPIRVCommon.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsSPIRVVK") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsSPIRVVK.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("BuiltinsSPIRVCL") { + args = [ "-gen-clang-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinsSPIRVCL.td" output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } @@ -414,6 +570,12 @@ clang_tablegen("arm_fp16") { output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } +clang_tablegen("arm_immcheck_types") { + args = [ "-gen-arm-immcheck-types" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_sve.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + clang_tablegen("arm_mve_builtins") { args = [ "-gen-arm-mve-builtin-def" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_mve.td" @@ -462,6 +624,12 @@ clang_tablegen("arm_sve_sema_rangechecks") { output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } +clang_tablegen("arm_sve_streaming_attrs") { + args = [ "-gen-arm-sve-streaming-attrs" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_sve.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + clang_tablegen("arm_sme_builtins") { args = [ "-gen-arm-sme-builtins" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_sme.td" @@ -480,6 +648,18 @@ clang_tablegen("arm_sme_sema_rangechecks") { output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } +clang_tablegen("arm_sme_streaming_attrs") { + args = [ "-gen-arm-sme-streaming-attrs" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_sme.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("arm_sme_builtins_za_state") { + args = [ "-gen-arm-sme-builtin-za-state" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_sme.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + clang_tablegen("arm_cde_builtins") { args = [ "-gen-arm-cde-builtin-def" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/arm_cde.td" @@ -542,6 +722,24 @@ clang_tablegen("riscv_sifive_vector_builtin_sema") { output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } +clang_tablegen("riscv_andes_vector_builtins") { + args = [ "-gen-riscv-andes-vector-builtins" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/riscv_andes_vector.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("riscv_andes_vector_builtin_cg") { + args = [ "-gen-riscv-andes-vector-builtin-codegen" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/riscv_andes_vector.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + +clang_tablegen("riscv_andes_vector_builtin_sema") { + args = [ "-gen-riscv-andes-vector-builtin-sema" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/riscv_andes_vector.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} + # from clang/include/clang/Driver tablegen("Options") { args = [ "-gen-opt-parser-defs" ] @@ -559,7 +757,7 @@ clang_tablegen("AttrTemplateInstantiate") { clang_tablegen("AttrParsedAttrList") { args = [ "-gen-clang-attr-parsed-attr-list" ] td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" - output_path = "$clspv_llvm_dir/clang/include/clang/Sema" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" } clang_tablegen("AttrParsedAttrKinds") { @@ -621,3 +819,14 @@ clang_tablegen("Checkers") { td_file = "//$clspv_llvm_dir/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td" output_path = "$clspv_llvm_dir/clang/include/clang/StaticAnalyzer/Checkers" } + +clang_tablegen("BuiltinTemplates") { + args = [ "-gen-clang-builtin-templates" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/BuiltinTemplates.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} +clang_tablegen("CXX11AttributeInfo") { + args = [ "-gen-cxx11-attribute-info" ] + td_file = "//$clspv_llvm_dir/clang/include/clang/Basic/Attr.td" + output_path = "$clspv_llvm_dir/clang/include/clang/Basic" +} diff --git a/third_party/clspv/gn/llvm/tools/BUILD.gn b/third_party/clspv/gn/llvm/tools/BUILD.gn index 1bd5f9d0f6a..5b370a9ea29 100644 --- a/third_party/clspv/gn/llvm/tools/BUILD.gn +++ b/third_party/clspv/gn/llvm/tools/BUILD.gn @@ -10,6 +10,8 @@ executable("clspv-tool-llvm-min-tblgen") { "../sources:clspv_llvm_lib_tblgen", "../sources:clspv_llvm_tool_min_tblgen_sources", ] + + sources = [ "//$clspv_llvm_dir/llvm/utils/TableGen/llvm-min-tblgen.cpp" ] } executable("clspv-tool-llvm-tblgen") { @@ -29,6 +31,8 @@ executable("clspv-tool-llvm-tblgen") { "../sources:clspv_llvm_utils_lib_tablegen_globalisel", "../tablegen:GenVT", ] + + sources = [ "//$clspv_llvm_dir/llvm/utils/TableGen/llvm-tblgen.cpp" ] } executable("clspv-tool-clang-tblgen") { @@ -46,9 +50,12 @@ executable("clspv-tool-clang-tblgen") { ] sources = [ "//$clspv_llvm_dir/clang/utils/TableGen/ASTTableGen.cpp", + "//$clspv_llvm_dir/clang/utils/TableGen/CIRLoweringEmitter.cpp", "//$clspv_llvm_dir/clang/utils/TableGen/ClangASTNodesEmitter.cpp", "//$clspv_llvm_dir/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp", "//$clspv_llvm_dir/clang/utils/TableGen/ClangAttrEmitter.cpp", + "//$clspv_llvm_dir/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp", + "//$clspv_llvm_dir/clang/utils/TableGen/ClangBuiltinsEmitter.cpp", "//$clspv_llvm_dir/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp", "//$clspv_llvm_dir/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp", "//$clspv_llvm_dir/clang/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp", diff --git a/third_party/clspv/src b/third_party/clspv/src index a173c052455..8f35aa835ae 160000 --- a/third_party/clspv/src +++ b/third_party/clspv/src @@ -1 +1 @@ -Subproject commit a173c052455434a422bcfe5c12ffe44d574fd6e1 +Subproject commit 8f35aa835ae973e1c802421ba5a873f5e967278c diff --git a/third_party/colorama/README.chromium b/third_party/colorama/README.chromium index 296cac7d4f7..5caa671303d 100644 --- a/third_party/colorama/README.chromium +++ b/third_party/colorama/README.chromium @@ -2,6 +2,7 @@ Name: colorama Short Name: colorama URL: https://github.com/tartley/colorama.git Version: 799604a104 +Update Mechanism: Manual License: BSD-3-Clause License File: LICENSE Security Critical: no diff --git a/third_party/cpu_features/README.chromium b/third_party/cpu_features/README.chromium index 23378547e76..c204ad99780 100644 --- a/third_party/cpu_features/README.chromium +++ b/third_party/cpu_features/README.chromium @@ -2,8 +2,10 @@ Name: cpu_features Short Name: cpu_features URL: https://github.com/google/cpu_features Version: v0.8.0 +Revision: 936b9ab5515dead115606559502e3864958f7f6e +Update Mechanism: Autoroll Date: 2023-05-17 -License: Apache 2.0 +License: Apache-2.0 License File: src/LICENSE Security Critical: Yes Shipped: yes diff --git a/third_party/dawn b/third_party/dawn index 1eca38fa523..c1308bb3f17 160000 --- a/third_party/dawn +++ b/third_party/dawn @@ -1 +1 @@ -Subproject commit 1eca38fa52364bf66c0d288a0537a2813d72b39b +Subproject commit c1308bb3f17e9637f82be72f7ed0a75f3427dda4 diff --git a/third_party/depot_tools b/third_party/depot_tools index 0cc30c3bafb..ec7d8f539cb 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools @@ -1 +1 @@ -Subproject commit 0cc30c3bafbabf75bc9c79bff5457741e742beb1 +Subproject commit ec7d8f539cb439ce9ca7750ff0d8942e68325090 diff --git a/third_party/flatbuffers/README.chromium b/third_party/flatbuffers/README.chromium index 3862495e755..a3efaf025fa 100644 --- a/third_party/flatbuffers/README.chromium +++ b/third_party/flatbuffers/README.chromium @@ -1,7 +1,9 @@ Name: FlatBuffers Short Name: flatbuffers URL: https://github.com/google/flatbuffers -Version: fb9afbafc7dfe226b9db54d4923bfb8839635274 +Version: N/A +Revision: fb9afbafc7dfe226b9db54d4923bfb8839635274 +Update Mechanism: Autoroll Date: 2024-07-01 License: Apache-2.0 License File: LICENSE diff --git a/third_party/flatbuffers/src b/third_party/flatbuffers/src index 8db59321d9f..a86afae9399 160000 --- a/third_party/flatbuffers/src +++ b/third_party/flatbuffers/src @@ -1 +1 @@ -Subproject commit 8db59321d9f02cdffa30126654059c7d02f70c32 +Subproject commit a86afae9399bbe631d1ea0783f8816e780e236cc diff --git a/third_party/glmark2/README.chromium b/third_party/glmark2/README.chromium index 7e5ff54e273..27a84eb7350 100644 --- a/third_party/glmark2/README.chromium +++ b/third_party/glmark2/README.chromium @@ -1,10 +1,12 @@ Name: glmark2 Short Name: glmark2 URL: https://github.com/glmark2/glmark2 -Version: ca8de51fedb70bace5351c6b002eb952c747e889 +Version: N/A +Revision: ca8de51fedb70bace5351c6b002eb952c747e889 +Update Mechanism: Manual Security Critical: no Shipped: no -License: GPL v3 +License: GPL-3.0 Description: glmark2 is an OpenGL 2.0 and ES 2.0 benchmark. diff --git a/third_party/glmark2/src b/third_party/glmark2/src index cb550a25c75..6edcf02205f 160000 --- a/third_party/glmark2/src +++ b/third_party/glmark2/src @@ -1 +1 @@ -Subproject commit cb550a25c75a99ae0def91a02e16ae29d73e6d1e +Subproject commit 6edcf02205fd1e8979dc3f3964257a81959b80c8 diff --git a/third_party/glslang/README.chromium b/third_party/glslang/README.chromium index e2c9ed0a597..984637aa9f6 100644 --- a/third_party/glslang/README.chromium +++ b/third_party/glslang/README.chromium @@ -3,6 +3,7 @@ Short Name: glslang URL: https://github.com/KhronosGroup/glslang Version: N/A Revision: DEPS +Update Mechanism: Autoroll Security Critical: yes Shipped: no License: Khronos diff --git a/third_party/glslang/src b/third_party/glslang/src index ef5207f9f8c..f0bd0257c30 160000 --- a/third_party/glslang/src +++ b/third_party/glslang/src @@ -1 +1 @@ -Subproject commit ef5207f9f8cce5097568efb15d3297d8b5d13014 +Subproject commit f0bd0257c308b9a26562c1a30c4748a0219cc951 diff --git a/third_party/googletest b/third_party/googletest deleted file mode 160000 index 17bbed2084d..00000000000 --- a/third_party/googletest +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 17bbed2084d3127bd7bcd27283f18d7a5861bea8 diff --git a/third_party/googletest/.gitignore b/third_party/googletest/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/third_party/googletest/BUILD.gn b/third_party/googletest/BUILD.gn new file mode 100644 index 00000000000..7b2244f64e7 --- /dev/null +++ b/third_party/googletest/BUILD.gn @@ -0,0 +1,201 @@ +# Copyright 2014 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build_overrides/build.gni") + +config("gtest_config") { + # webrtc wants to push this config without a public_dep chain + # TODO(crbug.com/1249254): figure out what to do with this + visibility = [ + ":*", # gmock also shares this config. + "//test:*", # webrts standalone setup + "//third_party/webrtc/test:*", + ] + + defines = [ + # Chromium always links googletest statically, so no API qualifier is + # necessary. The definition in gtest-port.h at the time of this writing + # causes crashes in content_browsertests. + "GTEST_API_=", + + # In order to allow regex matches in gtest to be shared between Windows + # and other systems, we tell gtest to always use its internal engine. + "GTEST_HAS_POSIX_RE=0", + + # Use Abseil, but without flags support: Abseil flags uses the + # `FastTypeId()` pattern internally, which is known to be broken in + # subtle ways in the component build. + "GTEST_HAS_ABSL", + "GTEST_NO_ABSL_FLAGS", + ] + + # Gtest headers need to be able to find themselves. + include_dirs = [ + "custom", + "src/googletest/include", + ] + + if (is_win) { + cflags = [ "/wd4800" ] # Unused variable warning. + } + + configs = [ + "//third_party/abseil-cpp:absl_include_config", + "//third_party/re2:re2_config", + ] +} + +config("gmock_config") { + # Gmock headers need to be able to find themselves. + include_dirs = [ + "custom", + "src/googlemock/include", + ] + + if (is_clang) { + # TODO(crbug.com/40616204): remove this when we migrated to new MOCK_METHOD + # macro. + # ref: https://google.github.io/googletest/gmock_cook_book.html#old-style-mock_methodn-macros + cflags = [ "-Wno-inconsistent-missing-override" ] + } +} + +# Do NOT depend on this directly. Use //testing/gtest instead. +# See README.chromium for details. +source_set("gtest") { + testonly = true + sources = [ + "custom/gtest/internal/custom/gtest.h", + "custom/gtest/internal/custom/stack_trace_getter.cc", + "custom/gtest/internal/custom/stack_trace_getter.h", + + # TODO(crbug.com/1009553): Remove this wrapper and custom temp dir + # after plumbing a workable temporary path into googletest on Android. + "custom/gtest/internal/custom/chrome_custom_temp_dir.cc", + "custom/gtest/internal/custom/chrome_custom_temp_dir.h", + "custom/gtest/internal/custom/gtest_port_wrapper.cc", + "src/googletest/include/gtest/gtest-assertion-result.h", + "src/googletest/include/gtest/gtest-death-test.h", + "src/googletest/include/gtest/gtest-matchers.h", + "src/googletest/include/gtest/gtest-message.h", + "src/googletest/include/gtest/gtest-param-test.h", + "src/googletest/include/gtest/gtest-printers.h", + "src/googletest/include/gtest/gtest-spi.h", + "src/googletest/include/gtest/gtest-test-part.h", + "src/googletest/include/gtest/gtest-typed-test.h", + "src/googletest/include/gtest/gtest.h", + "src/googletest/include/gtest/gtest_pred_impl.h", + "src/googletest/include/gtest/gtest_prod.h", + + #"src/googletest/include/gtest/internal/custom/gtest.h", # Superseded. + "src/googletest/include/gtest/internal/custom/gtest-port.h", + "src/googletest/include/gtest/internal/custom/gtest-printers.h", + "src/googletest/include/gtest/internal/gtest-death-test-internal.h", + "src/googletest/include/gtest/internal/gtest-filepath.h", + "src/googletest/include/gtest/internal/gtest-internal.h", + "src/googletest/include/gtest/internal/gtest-param-util.h", + "src/googletest/include/gtest/internal/gtest-port-arch.h", + "src/googletest/include/gtest/internal/gtest-port.h", + "src/googletest/include/gtest/internal/gtest-string.h", + "src/googletest/include/gtest/internal/gtest-type-util.h", + + #"src/googletest/src/gtest-all.cc", # Not needed by our build. + "src/googletest/src/gtest-assertion-result.cc", + "src/googletest/src/gtest-death-test.cc", + "src/googletest/src/gtest-filepath.cc", + "src/googletest/src/gtest-internal-inl.h", + "src/googletest/src/gtest-matchers.cc", + + # gtest_port_wrapper.cc is used instead of gtest-port.cc. + # TODO(crbug.com/1009553): Re-enable this file after plumbing a workable + # temporary path into googletest on Android. + #"src/googletest/src/gtest-port.cc", + "src/googletest/src/gtest-printers.cc", + "src/googletest/src/gtest-test-part.cc", + "src/googletest/src/gtest-typed-test.cc", + "src/googletest/src/gtest.cc", + ] + + # Some files include "src/gtest-internal-inl.h". + include_dirs = [ "src/googletest" ] + + public_configs = [ ":gtest_config" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + defines = [] + + # googletest only needs `absl`, but this makes gn check happier. + deps = [ "//third_party/abseil-cpp:absl_full" ] + public_deps = [ "//third_party/re2" ] + if (!build_with_chromium) { + defines += [ "GTEST_DISABLE_PRINT_STACK_TRACE" ] + sources -= [ + "custom/gtest/internal/custom/stack_trace_getter.cc", + "custom/gtest/internal/custom/stack_trace_getter.h", + ] + } else { + deps += [ "//base" ] + } + + if (is_fuchsia) { + deps += [ + "//third_party/fuchsia-sdk/sdk/pkg/fdio", + "//third_party/fuchsia-sdk/sdk/pkg/zx", + ] + } +} + +# Do NOT depend on this directly. Use //testing/gtest:gtest_main instead. +# See README.chromium for details. +source_set("gtest_main") { + testonly = true + sources = [ "src/googletest/src/gtest_main.cc" ] + deps = [ ":gtest" ] +} + +# Do NOT depend on this directly. Use //testing/gmock instead. +# See README.chromium for details. +source_set("gmock") { + testonly = true + sources = [ + "src/googlemock/include/gmock/gmock-actions.h", + "src/googlemock/include/gmock/gmock-cardinalities.h", + "src/googlemock/include/gmock/gmock-function-mocker.h", + "src/googlemock/include/gmock/gmock-matchers.h", + "src/googlemock/include/gmock/gmock-more-matchers.h", + "src/googlemock/include/gmock/gmock-nice-strict.h", + "src/googlemock/include/gmock/gmock-spec-builders.h", + "src/googlemock/include/gmock/gmock.h", + + #"src/googlemock/include/gmock/internal/custom/gmock-port.h", # Superseded. + "src/googlemock/include/gmock/internal/custom/gmock-generated-actions.h", + "src/googlemock/include/gmock/internal/custom/gmock-matchers.h", + "src/googlemock/include/gmock/internal/gmock-internal-utils.h", + "src/googlemock/include/gmock/internal/gmock-port.h", + "src/googlemock/include/gmock/internal/gmock-pp.h", + + #"src/googlemock/src/gmock-all.cc", # Not needed by our build. + "src/googlemock/src/gmock-cardinalities.cc", + "src/googlemock/src/gmock-internal-utils.cc", + "src/googlemock/src/gmock-matchers.cc", + "src/googlemock/src/gmock-spec-builders.cc", + "src/googlemock/src/gmock.cc", + ] + + # googlemock only needs `absl`, but this makes gn check happier. + deps = [ "//third_party/abseil-cpp:absl_full" ] + + public_deps = [ ":gtest" ] + public_configs = [ ":gmock_config" ] +} + +# Do NOT depend on this directly. Use //testing/gmock:gmock_main instead. +# See README.chromium for details. +static_library("gmock_main") { + testonly = true + sources = [ "src/googlemock/src/gmock_main.cc" ] + deps = [ ":gmock" ] +} diff --git a/third_party/googletest/DEPS b/third_party/googletest/DEPS new file mode 100644 index 00000000000..f23dccc97b6 --- /dev/null +++ b/third_party/googletest/DEPS @@ -0,0 +1,18 @@ +# This file is a dummy used so that non-Chromium clients can specify +# recursive DEPS. Otherwise the clients would need to nest DEPS inside +# each other. Nested DEPS are not supported by gclient. +# +# Clients *must* specify googletest_revision when using this DEPS file. + +use_relative_paths = True + +vars = { + 'chromium_git': 'https://chromium.googlesource.com', + + # We must specify a dummy variable here for recursedeps to work. + 'googletest_revision': 'master', +} + +deps = { + 'src': '{chromium_git}/external/github.com/google/googletest.git@{googletest_revision}' +} diff --git a/third_party/googletest/DIR_METADATA b/third_party/googletest/DIR_METADATA new file mode 100644 index 00000000000..67e6af8d94a --- /dev/null +++ b/third_party/googletest/DIR_METADATA @@ -0,0 +1,6 @@ +monorail: { + component: "Test>gTest" +} +buganizer_public: { + component_id: 1457072 +} diff --git a/third_party/googletest/README.chromium b/third_party/googletest/README.chromium new file mode 100644 index 00000000000..44ea2170d6f --- /dev/null +++ b/third_party/googletest/README.chromium @@ -0,0 +1,157 @@ +Name: Google Test: Google's C++ Testing Framework +Short Name: googletest +URL: https://github.com/google/googletest.git +Version: N/A +Revision: DEPS +Update Mechanism: Autoroll +License: BSD-3-Clause +License File: src/LICENSE +Shipped: no +Security critical: no + +Google Test is imported as-is, to facilitate version bumping. However, the +file/directory layout of Google Test is not yet considered stable. Therefore, +until Google Test's layout stabilizes, Chromium code MUST NOT depend on it +directly. Instead, Chromium code MUST: + +* #include the headers in testing/gtest and testing/gmock +* use //testing/gtest(:gtest_main) and //testing/gmock(:gmock_main) in BUILD.gn + deps + +This will allow us to adapt to Google Test changes with minimal disruption. + + +## Resources for Rolling Googletest in Chrome + +### What is Googletest + +Googletest is an open source C++ testing framework developed by Google and used +by Chromium. See the [User Guide](https://google.github.io/googletest/). + +### Where is Googletest + +Googletest is developed in google3 and uses +[copybara](https://github.com/google/copybara) to sync with the public GitHub +repository. + +* Development (Googler only): [google3/third\_party/googletest](http://google3/third_party/googletest/) +* GitHub: https://github.com/google/googletest +* Chromium mirror: https://chromium.googlesource.com/external/github.com/google/googletest/ +* Locally, [third\_party/googletest/src/](https://source.chromium.org/chromium/chromium/src/+/master:third_party/googletest/src/) + is a copy of Googletest which is updated via `gclient sync` according to the + `googletest revision` commit hash in the + [DEPS file](https://source.chromium.org/chromium/chromium/src/+/master:DEPS;l=244?q=DEPS%20googletest) + +### Unblocking Googletest Rolls + +1. Roll Googletest to include the breaking change +* Find the hash (on GitHub) of the offending commit + * If the change came from google3, the CL number can be found in the + `PiperOrigin-RevId` footer of Copybara commits +* On a fresh checkout, pull in the relevant change. Either: + * Sync using the DEPS file +``` +roll-dep --roll-to=commitish src/third_party/googletest/src/ +gclient sync +``` + * Check out the commit directly +``` +cd third_party/googletest/src +git remote add up https://github.com/google/googletest.git +git checkout commitish +``` + +2. Observe errors +* Ideally, this can be done by building locally. + If the build is successful, this means the change does not affect your OS or + your compiler flags differ from the trybots +* Upload a CL with the added trybots from + [Testing Changes to Chromium in Chromium](#testing-changes-to-chromium-in-chromium) + +3. Make changes +* To Chromium: create a CL including both the roll and other changes +* To Googletest: + * Make changes to [third\_party/googletest/src/](https://source.chromium.org/chromium/chromium/src/+/master:third_party/googletest/src/) + and try building locally. If the fix is successful and you’re confident + this change will work across all the trybots, create a PR on GitHub or a + CL to google3 (Googler only) of the changes you made locally to + [third\_party/googletest/src/](https://source.chromium.org/chromium/chromium/src/+/master:third_party/googletest/src/). + See [Testing Changes to Googletest in Googletest](#testing-changes-to-googletest-in-googletest) + * What if I need to make a change to Googletest, but I’m not confident it + will work with Chromium? Maybe it has to do with a tricky compiler error + that only affects a specific OS. See + [Testing Changes to Googletest in Chromium](#testing-changes-to-googletest-in-chromium) + * Once your Googletest change lands, create a roll which includes both the + offending commit and your change + +### Testing Changes to Chromium in Chromium + +Most changes should only require testing via the trybots, +with the following added: + +`Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:linux_chromium_cfi_rel_ng;luci.chrome.try:win-chrome` + +### Testing Changes to Googletest in Googletest + +External: Upload a PR with your proposed changes to GitHub. +This will trigger automated testing. + +Googlers: See the [Googletest Developer’s Guide](http://go/gunitdev). + +### Testing Changes to Googletest in Chromium + +In most cases, testing locally with changes to +[third\_party/googletest/src/](https://source.chromium.org/chromium/chromium/src/+/master:third_party/googletest/src/) +should be enough. But how can you make sure the changes to Googletest actually +work in Chromium? Sometimes it’s not possible to test these changes locally +(different compiler flags, error that only affects a specific OS, etc). +Insert the pwnall repo: + +* Development: https://github.com/pwnall/googletest +* Chromium mirror: https://chromium.googlesource.com/external/github.com/pwnall/googletest/ + +The pwnall repo allows you to make speculative changes to Googletest and run +them against the Chromium trybots. The flow is as follows: + +* Create a local remote to the pwnall repo (alternatively, clone it elsewhere): +``` +cd third_party/googletest/src +git remote +git remote add up https://github.com/google/googletest.git +git remote add pwnall git@github.com:pwnall/googletest.git +``` +* Sync the pwnall repo: +``` +git checkout master +git pull up master +git push pwnall master +``` +* Make changes on a new branch +* `git push pwnall branch-name` +* Update the `googletest revision` in the + [DEPS file](https://source.chromium.org/chromium/chromium/src/+/master:DEPS) + with the commit hash and `/external/github.com/google/googletest.git` to + `/external/github.com/pwnall/googletest.git` +* Upload the CL to run the change against the Chromium trybots + +### Common Problems + +* Differences in C++ version and clang compiler flags between Chromium and Googletest + * Chromium is on C++14, though its dependencies, + which may use Googletest, may be further behind + * Look for NACL in build errors. You may need to update your GN args with + `enable_nacl=true` to reproduce these errors locally +* [A Googletest interface is changed](https://github.com/google/googletest/pull/2718/) + * Rolling past the commit will fail, since Chromium still uses the old interface + * Roll past the affecting commit and update uses in Chromium [in one CL](https://crrev.com/c/2709263) +* [A Googletest header is removed](https://github.com/google/googletest/commit/df6b75949b1efab7606ba60c0f0a0125ac95c5af) + * Rolling past the commit will fail, since Chromium still expects the header to exist + * Roll past the affecting commit and updates uses in Chromium [in one CL](https://crrev.com/c/2713029) +* [A new Googletest feature](https://github.com/google/googletest/commit/ec94d9f24c92a5090fda5567156d6dde99cdbf31) + requires [updating tests in Chromium](https://crbug.com/1163396#c8) + +### Other Resources + +* [AutoRoller](https://autoroll.skia.org/r/googletest-chromium-autoroll) and + accompanying [configuration file](https://skia.googlesource.com/skia-autoroll-internal-config.git/+/main/skia-public/googletest-chromium.cfg) +* [Bug tracking substantial roll](https://crbug.com/1163396) diff --git a/third_party/googletest/custom/gtest/internal/custom/DEPS b/third_party/googletest/custom/gtest/internal/custom/DEPS new file mode 100644 index 00000000000..943f2bb3b9e --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/DEPS @@ -0,0 +1,5 @@ +# This directory contains Google Test glue that depends on //base. +include_rules = [ + '+base', + '+build', +] diff --git a/third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.cc b/third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.cc new file mode 100644 index 00000000000..e7f0a9a1908 --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.cc @@ -0,0 +1,121 @@ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.h" +#include "third_party/googletest/src/googletest/include/gtest/internal/gtest-port.h" +#if GTEST_OS_WINDOWS +# include +#endif // GTEST_OS_WINDOWS + +namespace testing +{ + +namespace +{ + +// The temporary directory read from the OS canonical environment variable. +// +// Returns an empty string if the environment variable is not set. The returned +// string may or may not end with the OS-specific path separator. The path is +// not guaranteed to point to an existing directory. The directory it points to +// is not guaranteed to be writable by the application. +std::string ChromeGetEnvTempDir() +{ +#if GTEST_OS_WINDOWS_MOBILE + const char *env_result = internal::posix::GetEnv("TEMP"); +#elif GTEST_OS_WINDOWS + char temp_dir_path[_MAX_PATH + 1] = {'\0'}; // NOLINT + if (::GetTempPathA(sizeof(temp_dir_path), temp_dir_path) != 0) + { + return temp_dir_path; + } + const char *env_result = internal::posix::GetEnv("TEMP"); +#else + const char *env_result = internal::posix::GetEnv("TMPDIR"); +#endif // GETST_OS_WINDOWS + + if (env_result == nullptr) + { + return std::string(); + } + return env_result; +} + +} // namespace + +// returns temp directory for tests. +std::string ChromeCustomTempDir() +{ + std::string temp_dir = ChromeGetEnvTempDir(); + if (!temp_dir.empty()) + { + if (temp_dir.back() != GTEST_PATH_SEP_[0]) + { + temp_dir.push_back(GTEST_PATH_SEP_[0]); + } + return temp_dir; + } + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS + return "\\temp\\"; +#elif GTEST_OS_LINUX_ANDROID + // Android applications are expected to call the framework's + // Context.getExternalStorageDirectory() method through JNI to get the + // location of the world-writable SD Card directory. However, this requires a + // Context handle, which cannot be retrieved globally from native code. Doing + // so also precludes running the code as part of a regular standalone + // executable, which doesn't run in a Dalvik process (e.g. when running it + // through 'adb shell'). + // + // Starting from Android O, the recommended generic temporary directory is + // '/data/local/tmp'. The recommended fallback is the current directory, + // which is usually accessible in app context. + if (::access("/data/local/tmp", R_OK | W_OK | X_OK) == 0) + { + return "/data/local/tmp/"; + } + const char *current_dir = ::getcwd(nullptr, 0); + if (current_dir != nullptr && ::access(current_dir, R_OK | W_OK | X_OK) == 0) + { + temp_dir = current_dir; + temp_dir.push_back(GTEST_PATH_SEP_[0]); + return temp_dir; + } + // Before Android O, /sdcard is usually available. + if (::access("/sdcard", R_OK | W_OK | X_OK) == 0) + { + return "/sdcard/"; + } + // Generic POSIX fallback. + return "/tmp/"; +#elif GTEST_OS_IOS + char name_template[PATH_MAX + 1]; + + // Documented alternative to NSTemporaryDirectory() (for obtaining creating + // a temporary directory) at + // https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10 + // + // _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not + // documented in the confstr() man page at + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr + // but are still available, according to the WebKit patches at + // https://trac.webkit.org/changeset/262004/webkit + // https://trac.webkit.org/changeset/263705/webkit + // + // The confstr() implementation falls back to getenv("TMPDIR"). See + // https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html + ::confstr(_CS_DARWIN_USER_TEMP_DIR, name_template, sizeof(name_template)); + + temp_dir = name_template; + if (temp_dir.back() != GTEST_PATH_SEP_[0]) + { + temp_dir.push_back(GTEST_PATH_SEP_[0]); + } + return temp_dir; +#else + return "/tmp/"; +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS +} + +} // namespace testing diff --git a/third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.h b/third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.h new file mode 100644 index 00000000000..fb7d766cec9 --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.h @@ -0,0 +1,16 @@ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_CHROME_CUSTOM_TEMP_DIR_H_ +#define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_CHROME_CUSTOM_TEMP_DIR_H_ + +#include + +namespace testing +{ +// Returns alternate temp directory for gtest. +std::string ChromeCustomTempDir(); +} // namespace testing + +#endif // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_CHROME_CUSTOM_TEMP_DIR_H_ diff --git a/third_party/googletest/custom/gtest/internal/custom/gtest.h b/third_party/googletest/custom/gtest/internal/custom/gtest.h new file mode 100644 index 00000000000..9bb736a3f51 --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/gtest.h @@ -0,0 +1,23 @@ +// Copyright 2018 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_H_ + +#include "build/build_config.h" +#include "third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.h" + +#if !defined(GTEST_DISABLE_PRINT_STACK_TRACE) +# include "third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h" + +// Tell Google Test to use a stack trace getter based on Chromium's +// base::debug::StackTrace. +# define GTEST_OS_STACK_TRACE_GETTER_ StackTraceGetter +#endif // defined(GTEST_DISABLE_PRINT_STACK_TRACE) + +// TODO(crbug.com/1009553): Remove once googletest android temporary path is +// fixed. +#define GTEST_CUSTOM_TEMPDIR_FUNCTION_ ChromeCustomTempDir + +#endif // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_H_ diff --git a/third_party/googletest/custom/gtest/internal/custom/gtest_port_wrapper.cc b/third_party/googletest/custom/gtest/internal/custom/gtest_port_wrapper.cc new file mode 100644 index 00000000000..741f7bdcccf --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/gtest_port_wrapper.cc @@ -0,0 +1,172 @@ +// Copyright 2019 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO(crbug.com/1009553): Remove this wrapper after finding a way to plumb a +// workable temporary path into googletest on Android. + +// This wrapper lets us compile gtest-port.cc without its stream redirection +// code. We replace this code with a variant that works on all Chrome platforms. +// This is a temporary workaround until we get good code upstream. +// +// Stream redirection requires the ability to create files in a temporary +// directory. Traditionally, this directory has been /sdcard on Android. +// Commit bf0fe874a27bd6c9a4a35b98e662d2d02f8879a2 changed the Android +// directory to /data/local/tmp, which is not writable in Chrome's testing +// setup. We work around this problem by using the old code for now. +// +// It is tempting to consider disabling the stream redirection code altogether, +// by setting GTEST_HAS_STREAM_REDIRECTION to 0 in googletest's BUILD.gn. +// This breaks gtest-death-test.cc, which assumes the existence of +// testing::internal::{GetCapturedStderr,CaptureStderr} without any macro +// checking. + +#define GTEST_HAS_STREAM_REDIRECTION 0 +#include "third_party/googletest/src/googletest/src/gtest-port.cc" + +namespace testing +{ +namespace internal +{ + +// Verbatim copy from gtest-port.cc, since it only provides these constants when +// GTEST_HAS_STREAM_REDIRECTION is true. +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // defined(_MSC_VER) || defined(__BORLANDC__) + +// Object that captures an output stream (stdout/stderr). +class CapturedStream +{ + public: + // The ctor redirects the stream to a temporary file. + explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) + { + std::string temp_dir = ::testing::TempDir(); + + // testing::TempDir() should return a directory with a path separator. + // However, this rule was documented fairly recently, so we normalize across + // implementations with and without a trailing path separator. + if (temp_dir.back() != GTEST_PATH_SEP_[0]) + { + temp_dir.push_back(GTEST_PATH_SEP_[0]); + } + +#if GTEST_OS_WINDOWS + char temp_file_path[MAX_PATH + 1] = {'\0'}; // NOLINT + const UINT success = ::GetTempFileNameA(temp_dir.c_str(), "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) << "Unable to create a temporary file in " << temp_dir; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " << temp_file_path; + filename_ = temp_file_path; +#else + std::string name_template = temp_dir + "gtest_captured_stream.XXXXXX"; + + // mkstemp() modifies the string bytes in place, and does not go beyond the + // string's length. This results in well-defined behavior in C++17. + // + // The const_cast is needed below C++17. The constraints on std::string + // implementations in C++11 and above make assumption behind the const_cast + // fairly safe. + const int captured_fd = ::mkstemp(const_cast(name_template.data())); + GTEST_CHECK_(captured_fd != -1) + << "Failed to create tmp file " << name_template + << " for test; does the test have write access to the directory?"; + filename_ = std::move(name_template); +#endif // GTEST_OS_WINDOWS + fflush(nullptr); + dup2(captured_fd, fd_); + close(captured_fd); + } + + CapturedStream(const CapturedStream &) = delete; + CapturedStream &operator=(const CapturedStream &) = delete; + + ~CapturedStream() { remove(filename_.c_str()); } + + std::string GetCapturedString() + { + if (uncaptured_fd_ != -1) + { + // Restores the original stream. + fflush(nullptr); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE *const file = posix::FOpen(filename_.c_str(), "r"); + if (file == nullptr) + { + GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_ + << " for capturing stream."; + } + const std::string content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; +}; + +static CapturedStream *g_captured_stderr = nullptr; +static CapturedStream *g_captured_stdout = nullptr; + +// Starts capturing an output stream (stdout/stderr). +static void CaptureStream(int fd, const char *stream_name, CapturedStream **stream) +{ + if (*stream != nullptr) + { + GTEST_LOG_(FATAL) << "Only one " << stream_name << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +static std::string GetCapturedStream(CapturedStream **captured_stream) +{ + const std::string content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = nullptr; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() +{ + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() +{ + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +std::string GetCapturedStdout() +{ + return GetCapturedStream(&g_captured_stdout); +} + +// Stops capturing stderr and returns the captured string. +std::string GetCapturedStderr() +{ + return GetCapturedStream(&g_captured_stderr); +} + +} // namespace internal +} // namespace testing diff --git a/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc new file mode 100644 index 00000000000..1e954493a2b --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc @@ -0,0 +1,72 @@ +// Copyright 2018 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h" + +#include +#include + +#include "base/containers/adapters.h" +#include "base/containers/span.h" + +std::string StackTraceGetter::CurrentStackTrace(int max_depth, int skip_count) +{ + base::debug::StackTrace stack_trace; + + base::span departure; + if (stack_trace_upon_leaving_gtest_.has_value()) + { + departure = stack_trace_upon_leaving_gtest_->addresses(); + } + + base::span current = stack_trace.addresses(); + + // Ignore the frames at the root of the current trace that match those of the + // point of departure from GTest. These frames all relate to thread start and + // test setup, and are irrelevant for diagnosing a failure in a given test. + // Also ignore the very first mismatch, as this identifies two instructions + // within the GTest function that called UponLeavingGTest, and is irrelevant + // as well. + { + const auto r_current = base::Reversed(current); + const size_t remaining = + r_current.end() - std::ranges::mismatch(base::Reversed(departure), r_current).in2; + if (remaining) + { + current = current.first(remaining - 1); + } + } + + // Ignore the frames at the leaf of the current trace that match those of the + // point of departure from GTest. These frames are the call(s) into + // StackTrace's constructor, which are irrelevant. Also ignore the very first + // mismatch, as it identifies two instructions within current function. + { + const size_t remaining = current.end() - std::ranges::mismatch(departure, current).in2; + if (remaining) + { + current = current.last(remaining - 1); + } + } + + // Ignore frames that the caller wishes to skip. + if (skip_count >= 0 && static_cast(skip_count) < current.size()) + { + current = current.subspan(static_cast(skip_count)); + } + + // Only return as many as requested. + if (max_depth >= 0 && static_cast(max_depth) < current.size()) + { + current = current.first(static_cast(max_depth)); + } + + return base::debug::StackTrace(current).ToString(); +} + +void StackTraceGetter::UponLeavingGTest() +{ + // Remember the callstack as GTest is left. + stack_trace_upon_leaving_gtest_.emplace(); +} diff --git a/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h new file mode 100644 index 00000000000..279a089f95d --- /dev/null +++ b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h @@ -0,0 +1,31 @@ +// Copyright 2018 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_ +#define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_ + +#include + +#include "base/debug/stack_trace.h" +#include "third_party/googletest/src/googletest/src/gtest-internal-inl.h" + +// An implementation of Google Test's OsStackTraceGetterInterface that uses +// Chromium's base::debug::StackTrace to obtain stringified stack traces. +class StackTraceGetter : public ::testing::internal::OsStackTraceGetterInterface +{ + public: + StackTraceGetter() = default; + ~StackTraceGetter() override = default; + StackTraceGetter(const StackTraceGetter &) = delete; + StackTraceGetter &operator=(const StackTraceGetter &) = delete; + + // ::testing::internal::OsStackTraceGetterInterface: + std::string CurrentStackTrace(int max_depth, int skip_count) override; + void UponLeavingGTest() override; + + private: + std::optional stack_trace_upon_leaving_gtest_; +}; + +#endif // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_ diff --git a/third_party/googletest/src b/third_party/googletest/src new file mode 160000 index 00000000000..4fe3307fb2d --- /dev/null +++ b/third_party/googletest/src @@ -0,0 +1 @@ +Subproject commit 4fe3307fb2d9f86d19777c7eb0e4809e9694dde7 diff --git a/third_party/ijar b/third_party/ijar index 4b6f53ee626..94af60a05b3 160000 --- a/third_party/ijar +++ b/third_party/ijar @@ -1 +1 @@ -Subproject commit 4b6f53ee6268ff3b8ffe0279e334aa5110249b65 +Subproject commit 94af60a05b33f9acb33477a8d969e48eb1c3029f diff --git a/third_party/jdk/README.chromium b/third_party/jdk/README.chromium index a22cda30d1c..d97ab886d4f 100644 --- a/third_party/jdk/README.chromium +++ b/third_party/jdk/README.chromium @@ -2,7 +2,8 @@ Name: Java Development Kit Short Name: JDK URL: https://openjdk.java.net/ Version: 11.0.4 -License: GPL v2 +Update Mechanism: Manual +License: GPL-2.0 Security Critical: no Shipped: no diff --git a/third_party/jinja2 b/third_party/jinja2 index 5e1ee241ab0..c3027d88496 160000 --- a/third_party/jinja2 +++ b/third_party/jinja2 @@ -1 +1 @@ -Subproject commit 5e1ee241ab04b38889f8d517f2da8b3df7cfbd9a +Subproject commit c3027d884967773057bf74b957e3fea87e5df4d7 diff --git a/third_party/libc++/src b/third_party/libc++/src index 2e25154d49c..7ab65651aed 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src @@ -1 +1 @@ -Subproject commit 2e25154d49c29fa9aa42c30ad4a027bd30123434 +Subproject commit 7ab65651aed6802d2599dcb7a73b1f82d5179d05 diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src index 634228a732a..8f11bb1d443 160000 --- a/third_party/libc++abi/src +++ b/third_party/libc++abi/src @@ -1 +1 @@ -Subproject commit 634228a732a1d9ae1a6d459556e8fc58707cf961 +Subproject commit 8f11bb1d4438d0239d0dfc1bd9456a9f31629dda diff --git a/third_party/libdrm/README.chromium b/third_party/libdrm/README.chromium index e87b10ef761..ce4248284d3 100644 --- a/third_party/libdrm/README.chromium +++ b/third_party/libdrm/README.chromium @@ -2,6 +2,7 @@ Name: libdrm Short Name: libdrm URL: https://chromium.googlesource.com/chromiumos/third_party/libdrm Version: 2.4.122 +Update Mechanism: Autoroll License: MIT Security Critical: yes Shipped: no diff --git a/third_party/libdrm/src b/third_party/libdrm/src index ad78bb591d0..369990d9660 160000 --- a/third_party/libdrm/src +++ b/third_party/libdrm/src @@ -1 +1 @@ -Subproject commit ad78bb591d02162d3b90890aa4d0a238b2a37cde +Subproject commit 369990d9660a387f618d0eedc341eb285016243b diff --git a/third_party/libjpeg_turbo b/third_party/libjpeg_turbo index 927aabfcd26..6bb85251a83 160000 --- a/third_party/libjpeg_turbo +++ b/third_party/libjpeg_turbo @@ -1 +1 @@ -Subproject commit 927aabfcd26897abb9776ecf2a6c38ea5bb52ab6 +Subproject commit 6bb85251a8382b5e07f635a981ac685cc5ab5053 diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn index 69b50c12610..88309e0b622 100644 --- a/third_party/libpng/BUILD.gn +++ b/third_party/libpng/BUILD.gn @@ -8,11 +8,6 @@ config("libpng_config") { if (is_clang) { cflags += [ "-Wno-tautological-constant-out-of-range-compare" ] } - if (is_apple) { - # TODO(crbug.com/41492875): this can be removed once libpng is updated to include - # https://github.com/pnggroup/libpng/commit/893b8113f04d408cc6177c6de19c9889a48faa24 - cflags += [ "-fno-define-target-os-macros" ] - } } static_library("libpng") { diff --git a/third_party/libpng/README.chromium b/third_party/libpng/README.chromium index 173735e16b7..ce4147fa79d 100644 --- a/third_party/libpng/README.chromium +++ b/third_party/libpng/README.chromium @@ -1,7 +1,16 @@ Name: libpng -URL: http://libpng.org/ -Version: 1.6.22 +URL: https://android.googlesource.com/platform/external/libpng +Version: 1.6.44 +Revision: 8cc222cd3e79fa5190f3aa039a03a4cbea6cfbe7 +Update Mechanism: Manual Security Critical: yes Shipped: no -License: libpng license +License: Libpng-2.0, Libpng +License File: LICENSE License Android Compatible: yes + +Description: +Homepage is http://libpng.org/ + +Local Modifications: +None diff --git a/third_party/libpng/src b/third_party/libpng/src index d2ece84bd73..8cc222cd3e7 160000 --- a/third_party/libpng/src +++ b/third_party/libpng/src @@ -1 +1 @@ -Subproject commit d2ece84bd73af1cd5fae5e7574f79b40e5de4fba +Subproject commit 8cc222cd3e79fa5190f3aa039a03a4cbea6cfbe7 diff --git a/third_party/libunwind/src b/third_party/libunwind/src index e55d8cf51c6..ba19d93d6d4 160000 --- a/third_party/libunwind/src +++ b/third_party/libunwind/src @@ -1 +1 @@ -Subproject commit e55d8cf51c6db1fdd4bb56c158945ec59772c8ee +Subproject commit ba19d93d6d4f467fba11ff20fe2fc7c056f79345 diff --git a/third_party/llvm-libc/README.chromium b/third_party/llvm-libc/README.chromium index 2a4d33aafe7..3daf6dfb64c 100644 --- a/third_party/llvm-libc/README.chromium +++ b/third_party/llvm-libc/README.chromium @@ -2,6 +2,7 @@ Name: llvm-libc URL: https://libc.llvm.org/ Version: N/A Revision: DEPS +Update Mechanism: Autoroll License: MIT, NCSA License File: src/LICENSE.TXT Security Critical: yes diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src index 6d0c8ee02e2..2a32a53cd55 160000 --- a/third_party/llvm-libc/src +++ b/third_party/llvm-libc/src @@ -1 +1 @@ -Subproject commit 6d0c8ee02e2fd44e69ac30e721e13be463035ee5 +Subproject commit 2a32a53cd558b813f154f6e2d290920556e7c9bc diff --git a/third_party/llvm/README.chromium b/third_party/llvm/README.chromium index da4320086a3..886e9b5eab6 100644 --- a/third_party/llvm/README.chromium +++ b/third_party/llvm/README.chromium @@ -1,7 +1,9 @@ Name: The LLVM Project Short Name: llvm URL: https://github.com/llvm/llvm-project -Version: d222fa4521531cc4ac14b8e157d231c108c003be +Revision: fd9a1dcc01766c71932898e9643ce28bf2801bad +Version: N/A +Update Mechanism: Manual Security Critical: no Shipped: no License: Apache-2.0 diff --git a/third_party/llvm/src b/third_party/llvm/src index d222fa45215..67790d3fb06 160000 --- a/third_party/llvm/src +++ b/third_party/llvm/src @@ -1 +1 @@ -Subproject commit d222fa4521531cc4ac14b8e157d231c108c003be +Subproject commit 67790d3fb06b184b7be9c4d3e36ab01f0ac4198e diff --git a/third_party/logdog/README.chromium b/third_party/logdog/README.md similarity index 95% rename from third_party/logdog/README.chromium rename to third_party/logdog/README.md index 1d040caa5ce..d8881071375 100644 --- a/third_party/logdog/README.chromium +++ b/third_party/logdog/README.md @@ -3,7 +3,7 @@ Short Name: logdog URL: https://chromium.googlesource.com/infra/luci/luci-py/client/libs/logdog Version: 17ec234f823f7bff6ada6584fdbbee9d54b8fc58 Revision: 17ec234f823f7bff6ada6584fdbbee9d54b8fc58 -License: Apache 2.0 +License: Apache-2.0 Security Critical: no Shipped: no diff --git a/third_party/lunarg-vulkantools/README.chromium b/third_party/lunarg-vulkantools/README.chromium index 1868654f49f..5588189d4a4 100644 --- a/third_party/lunarg-vulkantools/README.chromium +++ b/third_party/lunarg-vulkantools/README.chromium @@ -2,11 +2,11 @@ Name: LunarG VulkanTools Short Name: VulkanTools Version: N/A URL: https://github.com/LunarG/VulkanTools -SOURCE CODE: git clone https://github.com/LunarG/VulkanTools.git Revision: DEPS +Update Mechanism: Autoroll Security Critical: no Shipped: no -License: Apache 2.0 +License: Apache-2.0 License File: src/LICENSE.txt Description: diff --git a/third_party/lunarg-vulkantools/src b/third_party/lunarg-vulkantools/src index 0ed717a810d..7e47ffa5e86 160000 --- a/third_party/lunarg-vulkantools/src +++ b/third_party/lunarg-vulkantools/src @@ -1 +1 @@ -Subproject commit 0ed717a810d28e7533d935a7c0017f6d267a8671 +Subproject commit 7e47ffa5e8647946a6ebc96f67cf974f6afaa8ba diff --git a/third_party/markupsafe b/third_party/markupsafe index 9f8efc8637f..4256084ae14 160000 --- a/third_party/markupsafe +++ b/third_party/markupsafe @@ -1 +1 @@ -Subproject commit 9f8efc8637f847ab1ba984212598e6fb9cf1b3d4 +Subproject commit 4256084ae14175d38a3ff7d739dca83ae49ccec6 diff --git a/third_party/nasm b/third_party/nasm index f477acb1049..af5eeeb054b 160000 --- a/third_party/nasm +++ b/third_party/nasm @@ -1 +1 @@ -Subproject commit f477acb1049f5e043904b87b825c5915084a9a29 +Subproject commit af5eeeb054bebadfbb79c7bcd100a95e2ad4525f diff --git a/third_party/perfetto b/third_party/perfetto index d06bef7807a..5c17fc6e089 160000 --- a/third_party/perfetto +++ b/third_party/perfetto @@ -1 +1 @@ -Subproject commit d06bef7807a8b90de9bce77132e188f68459a714 +Subproject commit 5c17fc6e089cecec6bd75073875f57c99dcd2f02 diff --git a/third_party/proguard/README.chromium b/third_party/proguard/README.chromium index 0638d5e2ab3..3f911cdfdad 100644 --- a/third_party/proguard/README.chromium +++ b/third_party/proguard/README.chromium @@ -2,6 +2,7 @@ Name: Proguard URL: http://proguard.sourceforge.net/ Version: 6.0.3 Date: 2016-06-22 +Update Mechanism: Manual License: GPL-2.0 License File: LICENSE Security Critical: no diff --git a/third_party/protobuf b/third_party/protobuf index d8e413be0cb..ddf513ccaee 160000 --- a/third_party/protobuf +++ b/third_party/protobuf @@ -1 +1 @@ -Subproject commit d8e413be0cb7645a3545a6efea1aab03f9a58e52 +Subproject commit ddf513ccaeed6b1316bc2029b10f4436ad297324 diff --git a/third_party/r8/README.chromium b/third_party/r8/README.chromium index 039d8b1ebbd..43622613fcd 100644 --- a/third_party/r8/README.chromium +++ b/third_party/r8/README.chromium @@ -1,6 +1,7 @@ Name: R8 URL: https://r8.googlesource.com/r8 Version: 3.0.33 +Update Mechanism: Manual License: BSD-3-Clause License File: LICENSE Security Critical: no diff --git a/third_party/rapidjson/README.chromium b/third_party/rapidjson/README.chromium index dd0a80bed50..b645ce8b83a 100644 --- a/third_party/rapidjson/README.chromium +++ b/third_party/rapidjson/README.chromium @@ -2,6 +2,7 @@ Name: RapidJSON URL: https://github.com/TenCent/rapidjson Version: N/A Revision: DEPS +Update Mechanism: Manual License: MIT, BSD-3-Clause, JSON License File: src/license.txt Shipped: no diff --git a/third_party/re2/BUILD.gn b/third_party/re2/BUILD.gn new file mode 100644 index 00000000000..da398564a23 --- /dev/null +++ b/third_party/re2/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright 2014 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//testing/libfuzzer/fuzzer_test.gni") + +config("re2_config") { + include_dirs = [ "src" ] +} + +static_library("re2") { + sources = [ + "src/re2/bitmap256.cc", + "src/re2/bitmap256.h", + "src/re2/bitstate.cc", + "src/re2/compile.cc", + "src/re2/dfa.cc", + "src/re2/filtered_re2.cc", + "src/re2/filtered_re2.h", + "src/re2/mimics_pcre.cc", + "src/re2/nfa.cc", + "src/re2/onepass.cc", + "src/re2/parse.cc", + "src/re2/perl_groups.cc", + "src/re2/prefilter.cc", + "src/re2/prefilter.h", + "src/re2/prefilter_tree.cc", + "src/re2/prefilter_tree.h", + "src/re2/prog.cc", + "src/re2/prog.h", + "src/re2/re2.cc", + "src/re2/re2.h", + "src/re2/regexp.cc", + "src/re2/regexp.h", + "src/re2/set.cc", + "src/re2/set.h", + "src/re2/simplify.cc", + "src/re2/sparse_array.h", + "src/re2/sparse_set.h", + "src/re2/stringpiece.h", + "src/re2/tostring.cc", + "src/re2/unicode_casefold.cc", + "src/re2/unicode_casefold.h", + "src/re2/unicode_groups.cc", + "src/re2/unicode_groups.h", + "src/re2/walker-inl.h", + "src/util/rune.cc", + "src/util/strutil.cc", + "src/util/strutil.h", + "src/util/utf.h", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + public_configs = [ ":re2_config" ] + public_deps = [ "//third_party/abseil-cpp:absl" ] +} + +fuzzer_test("third_party_re2_fuzzer") { + sources = [ "src/re2/fuzzing/re2_fuzzer.cc" ] + deps = [ ":re2" ] +} diff --git a/third_party/re2/DEPS b/third_party/re2/DEPS new file mode 100644 index 00000000000..82c266c5b62 --- /dev/null +++ b/third_party/re2/DEPS @@ -0,0 +1,7 @@ +include_rules = [ + '+base', + '+build', + '+re2', + '+utest', + '+util', +] diff --git a/third_party/re2/DIR_METADATA b/third_party/re2/DIR_METADATA new file mode 100644 index 00000000000..45f7798a686 --- /dev/null +++ b/third_party/re2/DIR_METADATA @@ -0,0 +1,6 @@ +monorail: { + component: "Internals" +} +buganizer_public: { + component_id: 1456292 +} diff --git a/third_party/re2/LICENSE b/third_party/re2/LICENSE new file mode 100644 index 00000000000..09e5ec1c74c --- /dev/null +++ b/third_party/re2/LICENSE @@ -0,0 +1,27 @@ +// Copyright (c) 2009 The RE2 Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/re2/OWNERS b/third_party/re2/OWNERS new file mode 100644 index 00000000000..e542f4adc50 --- /dev/null +++ b/third_party/re2/OWNERS @@ -0,0 +1,2 @@ +junyer@chromium.org +thakis@chromium.org diff --git a/third_party/re2/README.chromium b/third_party/re2/README.chromium new file mode 100644 index 00000000000..f8dbcdff287 --- /dev/null +++ b/third_party/re2/README.chromium @@ -0,0 +1,14 @@ +Name: re2 - an efficient, principled regular expression library +Short Name: re2 +URL: https://github.com/google/re2 +Version: 1e44e72d31ddc66b783a545e9d9fcaa876a146b7 +Update Mechanism: Autoroll +Date: 2023-05-31 +License: BSD-3-Clause +License File: LICENSE +Security Critical: yes +Shipped: yes + +Description: +RE2 is a fast, safe, thread-friendly alternative to backtracking regular +expression engines like those used in PCRE, Perl, and Python. diff --git a/third_party/re2/src b/third_party/re2/src new file mode 160000 index 00000000000..972a15cedd0 --- /dev/null +++ b/third_party/re2/src @@ -0,0 +1 @@ +Subproject commit 972a15cedd008d846f1a39b2e88ce48d7f166cbd diff --git a/third_party/renderdoc/README.chromium b/third_party/renderdoc/README.chromium index 2ee925d5752..d4968ecdb8a 100644 --- a/third_party/renderdoc/README.chromium +++ b/third_party/renderdoc/README.chromium @@ -3,6 +3,7 @@ URL: https://raw.githubusercontent.com/baldurk/renderdoc/v1.1/renderdoc/api/app/ Revision: 026da176bbcc1678c439984cbbea1c17953c3a0e License: MIT Version: N/A +Update Mechanism: Manual Security Critical: no Shipped: no diff --git a/third_party/rust b/third_party/rust index 588e69eab28..37133fcc2fb 160000 --- a/third_party/rust +++ b/third_party/rust @@ -1 +1 @@ -Subproject commit 588e69eab286e9f07b49d45ac9d483aac4c1c9cf +Subproject commit 37133fcc2fb93e454471cec6501e6547c74108c0 diff --git a/third_party/six b/third_party/six index 580980eb7d3..98dedb5909b 160000 --- a/third_party/six +++ b/third_party/six @@ -1 +1 @@ -Subproject commit 580980eb7d380150995b82cd18e1254ab5eff77f +Subproject commit 98dedb5909b3e39848c6de5122772f5a89abe61a diff --git a/third_party/spirv-cross/README.chromium b/third_party/spirv-cross/README.chromium index cd88c17008b..8f016290e51 100644 --- a/third_party/spirv-cross/README.chromium +++ b/third_party/spirv-cross/README.chromium @@ -3,9 +3,10 @@ Short Name: SPIRV-Cross URL: https://github.com/KhronosGroup/SPIRV-Cross Version: N/A Revision: DEPS +Update Mechanism: Manual Security Critical: yes Shipped: no -License: Apache 2.0 +License: Apache-2.0 License File: src/LICENSE Description: diff --git a/third_party/spirv-headers/README.chromium b/third_party/spirv-headers/README.chromium index 92929570f96..5e0ac974930 100644 --- a/third_party/spirv-headers/README.chromium +++ b/third_party/spirv-headers/README.chromium @@ -3,6 +3,7 @@ Short Name: spirv-headers URL: https://github.com/KhronosGroup/SPIRV-Headers.git Version: N/A Revision: DEPS +Update Mechanism: Autoroll Security Critical: yes Shipped: yes License: Apache-2.0 diff --git a/third_party/spirv-headers/src b/third_party/spirv-headers/src index 09913f088a1..04f10f650d5 160000 --- a/third_party/spirv-headers/src +++ b/third_party/spirv-headers/src @@ -1 +1 @@ -Subproject commit 09913f088a1197aba4aefd300a876b2ebbaa3391 +Subproject commit 04f10f650d514df88b76d25e83db360142c7b174 diff --git a/third_party/spirv-tools/README.chromium b/third_party/spirv-tools/README.chromium index 19c80f0435d..71f13db2c35 100644 --- a/third_party/spirv-tools/README.chromium +++ b/third_party/spirv-tools/README.chromium @@ -3,6 +3,7 @@ Short Name: SPIRV-Tools URL: https://github.com/KhronosGroup/SPIRV-Tools.git Version: N/A Revision: DEPS +Update Mechanism: Autoroll Security Critical: yes Shipped: yes License: Apache-2.0 diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src index dc1641d1683..d3f9ef117aa 160000 --- a/third_party/spirv-tools/src +++ b/third_party/spirv-tools/src @@ -1 +1 @@ -Subproject commit dc1641d168304d3ef97bba23d5fc45c9bead45f5 +Subproject commit d3f9ef117aab877b23a266b1e7542549ea70b817 diff --git a/third_party/turbine/README.chromium b/third_party/turbine/README.chromium index be45df15eb6..8181f8492f7 100644 --- a/third_party/turbine/README.chromium +++ b/third_party/turbine/README.chromium @@ -3,6 +3,7 @@ Short Name: turbine URL: https://github.com/google/turbine Version: N/A Revision: 3c31e67ae25b5e43713fd868e3a9b535ff6298af +Update Mechanism: Manual License: Apache-2.0 License File: LICENSE Security Critical: no diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index b62b2ca7025..54fcc5faac1 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps @@ -1 +1 @@ -Subproject commit b62b2ca7025e54c25a16f678dd6ce39adfaccc73 +Subproject commit 54fcc5faac160ea56b6205fa91a7bf94bea5528a diff --git a/third_party/vulkan-headers/README.chromium b/third_party/vulkan-headers/README.chromium index 6b66f8705f3..a3639ebef01 100644 --- a/third_party/vulkan-headers/README.chromium +++ b/third_party/vulkan-headers/README.chromium @@ -3,6 +3,7 @@ Short Name: Vulkan URL: https://github.com/KhronosGroup/Vulkan-Headers Version: 1.2.140 Revision: 9250d5ae8f50202005233dc0512a1d460c8b4833 +Update Mechanism: Autoroll Security Critical: yes Shipped: yes License: Apache-2.0 diff --git a/third_party/vulkan-headers/src b/third_party/vulkan-headers/src index 234c4b7370a..b5c8f996196 160000 --- a/third_party/vulkan-headers/src +++ b/third_party/vulkan-headers/src @@ -1 +1 @@ -Subproject commit 234c4b7370a8ea3239a214c9e871e4b17c89f4ab +Subproject commit b5c8f996196ba4aa6d8f97e52b5d3b6e70f7e4e2 diff --git a/third_party/vulkan-loader/README.chromium b/third_party/vulkan-loader/README.chromium index 04ae2723eec..9cb3ac0163d 100644 --- a/third_party/vulkan-loader/README.chromium +++ b/third_party/vulkan-loader/README.chromium @@ -2,15 +2,15 @@ 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: DEPS +Update Mechanism: Autoroll Security Critical: no Shipped: yes -License: Apache 2.0 +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 index fde0f9718bd..32fcb949e25 160000 --- a/third_party/vulkan-loader/src +++ b/third_party/vulkan-loader/src @@ -1 +1 @@ -Subproject commit fde0f9718bd60b49cf8efc80d3fb7a093c309ac0 +Subproject commit 32fcb949e253cbeb40cda7ea76122b492db579ae diff --git a/third_party/vulkan-tools/README.chromium b/third_party/vulkan-tools/README.chromium index da5043beb49..540279307e2 100644 --- a/third_party/vulkan-tools/README.chromium +++ b/third_party/vulkan-tools/README.chromium @@ -2,14 +2,14 @@ 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: DEPS +Update Mechanism: Autoroll Security Critical: no Shipped: no -License: Apache 2.0 +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 index a9f88a232a4..48a4bcbdf61 160000 --- a/third_party/vulkan-tools/src +++ b/third_party/vulkan-tools/src @@ -1 +1 @@ -Subproject commit a9f88a232a4cd6634e47f0f93c8fac5789387a7a +Subproject commit 48a4bcbdf619e57204783f8c1a04c76c160ddd5b diff --git a/third_party/vulkan-utility-libraries/README.chromium b/third_party/vulkan-utility-libraries/README.chromium index 3e85b5d94d9..5e319796d1c 100644 --- a/third_party/vulkan-utility-libraries/README.chromium +++ b/third_party/vulkan-utility-libraries/README.chromium @@ -2,11 +2,11 @@ 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: DEPS +Update Mechanism: Autoroll Security Critical: no Shipped: no -License: Apache 2.0 +License: Apache-2.0 License File: src/LICENSE.md Description: diff --git a/third_party/vulkan-utility-libraries/src b/third_party/vulkan-utility-libraries/src index fe7a09b1389..a663eca87ba 160000 --- a/third_party/vulkan-utility-libraries/src +++ b/third_party/vulkan-utility-libraries/src @@ -1 +1 @@ -Subproject commit fe7a09b13899c5c77d956fa310286f7a7eb2c4ed +Subproject commit a663eca87ba71294dd4b74ba9d3e64a72d725453 diff --git a/third_party/vulkan-validation-layers/README.chromium b/third_party/vulkan-validation-layers/README.chromium index 2b5db0b7f50..5d8c2cc996c 100644 --- a/third_party/vulkan-validation-layers/README.chromium +++ b/third_party/vulkan-validation-layers/README.chromium @@ -2,14 +2,15 @@ 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: DEPS +Update Mechanism: Autoroll Security Critical: no Shipped: no -License: Apache 2.0 +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 diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src index 266d5cd69a9..2d34d32c82f 160000 --- a/third_party/vulkan-validation-layers/src +++ b/third_party/vulkan-validation-layers/src @@ -1 +1 @@ -Subproject commit 266d5cd69a94c1262c44307f4c4209c97f5c6ec4 +Subproject commit 2d34d32c82f7f0a308f09973f8874f69f56a66ae diff --git a/third_party/vulkan_memory_allocator b/third_party/vulkan_memory_allocator index 56300b29fbf..cb0597213b0 160000 --- a/third_party/vulkan_memory_allocator +++ b/third_party/vulkan_memory_allocator @@ -1 +1 @@ -Subproject commit 56300b29fbfcc693ee6609ddad3fdd5b7a449a21 +Subproject commit cb0597213b0fcb999caa9ed08c2f88dc45eb7d50 diff --git a/third_party/zlib b/third_party/zlib index 5634698162b..980253c1cc8 160000 --- a/third_party/zlib +++ b/third_party/zlib @@ -1 +1 @@ -Subproject commit 5634698162b2182c350e4cb360a0f4dd7706afec +Subproject commit 980253c1cc835c893c57b5cfc10c5b942e10bc46 diff --git a/tools/android b/tools/android index d5b1dd58bd5..93a7974ca06 160000 --- a/tools/android +++ b/tools/android @@ -1 +1 @@ -Subproject commit d5b1dd58bd5e7a0460e203909cb9fba5b3085a17 +Subproject commit 93a7974ca06a3e375df655bd7e86ec4845fae60c diff --git a/tools/clang b/tools/clang index 1340d3ed8ba..8837640dd26 160000 --- a/tools/clang +++ b/tools/clang @@ -1 +1 @@ -Subproject commit 1340d3ed8bae85ab0e8410c4439289dde1d3fea6 +Subproject commit 8837640dd26df7735d6574781ec4e20fb0c1baab diff --git a/tools/flex-bison/third_party/m4sugar/README.chromium b/tools/flex-bison/third_party/m4sugar/README.chromium index 4f447e3d459..4abbab0288a 100644 --- a/tools/flex-bison/third_party/m4sugar/README.chromium +++ b/tools/flex-bison/third_party/m4sugar/README.chromium @@ -3,6 +3,7 @@ Short Name: m4sugar URL: https://git.savannah.gnu.org/r/autoconf.git/ Version: N/A Date: 2019-12-01 +Update Mechanism: Static.HardFork (https://crbug.com/422061086) License: GPL-2.0 License File: LICENSE Shipped: no diff --git a/tools/flex-bison/third_party/skeletons/README.chromium b/tools/flex-bison/third_party/skeletons/README.chromium index ffe6c7a365c..b527e84f51c 100644 --- a/tools/flex-bison/third_party/skeletons/README.chromium +++ b/tools/flex-bison/third_party/skeletons/README.chromium @@ -1,6 +1,8 @@ Name: Bison skeletons URL: https://git.savannah.gnu.org/r/bison.git/ -Version: 3.3.2 +Revision: 437f6250c5e8e49d1d3bf437246f1d034897728e +Version: v3.3.2 +Update Mechanism: Manual License: GPL-3.0 License File: LICENSE Shipped: no diff --git a/tools/mb b/tools/mb index 8e880be2d6e..1fc5adbbce8 160000 --- a/tools/mb +++ b/tools/mb @@ -1 +1 @@ -Subproject commit 8e880be2d6e35587fd372f204b9d6d4aed0bc194 +Subproject commit 1fc5adbbce8acd2a5fdccefde5af9865b982429d diff --git a/tools/md_browser b/tools/md_browser index 6cc8e58a834..b7cfebc8143 160000 --- a/tools/md_browser +++ b/tools/md_browser @@ -1 +1 @@ -Subproject commit 6cc8e58a83412dc31de6fb7614fadb0b51748d4b +Subproject commit b7cfebc8143108734248df4e855a1bff01173f77 diff --git a/tools/memory b/tools/memory index 8e9b58419b4..e028ac64985 160000 --- a/tools/memory +++ b/tools/memory @@ -1 +1 @@ -Subproject commit 8e9b58419b41fe0d9dfe2e870f3164f446a0d7ab +Subproject commit e028ac649856478983fdca599522f242de568826 diff --git a/tools/perf b/tools/perf index 2ed187cab21..b70509b2381 160000 --- a/tools/perf +++ b/tools/perf @@ -1 +1 @@ -Subproject commit 2ed187cab21cd990e4b58c381ac157382114bf57 +Subproject commit b70509b23814bdcb08547d72d3e8fe6cc7d5dbcc diff --git a/tools/protoc_wrapper b/tools/protoc_wrapper index dbcbea90c20..3438d4183bf 160000 --- a/tools/protoc_wrapper +++ b/tools/protoc_wrapper @@ -1 +1 @@ -Subproject commit dbcbea90c20ae1ece442d8ef64e61c7b10e2b013 +Subproject commit 3438d4183bfc7c0d6850e8b970204cc8189f0323 diff --git a/tools/rust b/tools/rust index 05dbbfdcec4..d2fadac996b 160000 --- a/tools/rust +++ b/tools/rust @@ -1 +1 @@ -Subproject commit 05dbbfdcec4a7cc6c7cbf735d5a67d331a2f40da +Subproject commit d2fadac996be252abe5077583a42970163e9f2e7 diff --git a/tools/valgrind b/tools/valgrind index aa44e7637ff..da34b95fdbf 160000 --- a/tools/valgrind +++ b/tools/valgrind @@ -1 +1 @@ -Subproject commit aa44e7637ff74c6d4733ed5552afb44f3cfddb37 +Subproject commit da34b95fdbf2032df6cda5f3828c2ba421592644 diff --git a/tools/win b/tools/win new file mode 160000 index 00000000000..baacfc6d598 --- /dev/null +++ b/tools/win @@ -0,0 +1 @@ +Subproject commit baacfc6d5986b07abe0503216b491e234b94ba79 diff --git a/unsafe_buffers_paths.txt b/unsafe_buffers_paths.txt new file mode 100644 index 00000000000..69ad3bcddaa --- /dev/null +++ b/unsafe_buffers_paths.txt @@ -0,0 +1,43 @@ +# Copyright 2025 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. + +# See https://source.chromium.org/chromium/chromium/src/+/main:docs/unsafe_buffers.md + +# Checks to enforce +.buffers,libc + +# These directories are excluded +-build/ +-samples/ +-src/third_party/ +-src/common/third_party/ +-src/tests/capture_tests/ +-src/tests/capture_replay_tests/ +-src/tests/restricted_traces/ +-testing/ +-third_party/ +-tools/ + +# These generated files are excluded until templates are updated. +-src/common/Float16ToFloat32.cpp +-src/common/gl_enum_utils_autogen.cpp +-src/common/spirv/spirv_instruction_builder_autogen.cpp +-src/common/spirv/spirv_instruction_parser_autogen.cpp +-src/compiler/preprocessor/preprocessor_lex_autogen.cpp +-src/compiler/preprocessor/preprocessor_tab_autogen.cpp +-src/compiler/translator/ImmutableString_autogen.cpp +-src/compiler/translator/SymbolTable_autogen.cpp +-src/compiler/translator/glslang_lex_autogen.cpp +-src/compiler/translator/glslang_tab_autogen.cpp +-src/compiler/translator/hlsl/emulated_builtin_functions_hlsl_autogen.cpp +-src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp +-src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp +-util/autogen/angle_features_autogen.cpp +-util/capture/frame_capture_replay_autogen.cpp +-util/capture/trace_egl_loader_autogen.cpp +-util/capture/trace_gles_loader_autogen.cpp +-util/capture/trace_interpreter_autogen.cpp +-util/egl_loader_autogen.cpp +-util/gles_loader_autogen.cpp +-util/windows/wgl_loader_autogen.cpp diff --git a/util/BUILD.gn b/util/BUILD.gn index 6cff850678a..6e2473c4ddb 100644 --- a/util/BUILD.gn +++ b/util/BUILD.gn @@ -224,6 +224,7 @@ angle_source_set("angle_trace_fixture") { ] public_deps = [ ":angle_trace_loader", + "$angle_root:angle_capture_common", "$angle_root:includes", ] if (is_ios) { @@ -244,6 +245,7 @@ if (angle_enable_cl) { ] public_deps = [ ":angle_trace_loader", + "$angle_root:angle_capture_common", "$angle_root:includes", ] if (is_ios) { diff --git a/util/EGLPlatformParameters.h b/util/EGLPlatformParameters.h index d350aed0bb7..9d66cf26d38 100644 --- a/util/EGLPlatformParameters.h +++ b/util/EGLPlatformParameters.h @@ -33,6 +33,15 @@ enum class GLESDriverType ZinkEGL, }; +// The ANGLE test suite with all the various front/backend combinations can be instantiated for +// only either the packaged ANGLE libraries (AngleEGL) or the system libraries (SystemEGL), but not +// both at the same time. +#if !defined(ANGLE_TEST_ENABLE_SYSTEM_EGL) +constexpr GLESDriverType kDefaultGLESDriver = GLESDriverType::AngleEGL; +#else +constexpr GLESDriverType kDefaultGLESDriver = GLESDriverType::SystemEGL; +#endif + inline bool IsANGLE(angle::GLESDriverType driverType) { return driverType == angle::GLESDriverType::AngleEGL || diff --git a/util/EGLWindow.cpp b/util/EGLWindow.cpp index c84e1f27e9e..ff1a2f28a84 100644 --- a/util/EGLWindow.cpp +++ b/util/EGLWindow.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/EGLWindow.h" #include @@ -31,15 +35,29 @@ ConfigParameters::ConfigParameters() alphaBits(-1), depthBits(-1), stencilBits(-1), + // The default value of EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE is EGL_FALSE. + webGLCompatibility(false), + // The default value of EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE is EGL_FALSE. + robustResourceInit(false), componentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT), multisample(false), + // The default value of EGL_CONTEXT_OPENGL_DEBUG is EGL_FALSE. debug(false), + // The default value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR is EGL_FALSE. noError(false), + // The default value of EGL_EXTENSIONS_ENABLED_ANGLE is EGL_TRUE. + extensionsEnabled(true), + // The default value of EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM is EGL_TRUE. bindGeneratesResource(true), + // The default value of CLIENT_ARRAYS_ANGLE is EGL_TRUE. clientArraysEnabled(true), + // The default value of EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT is EGL_FALSE. robustAccess(false), + // EGL_RENDER_BUFFER requires EGL 1.4+ or extension support. mutableRenderBuffer(false), samples(-1), + // The default value of EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE is EGL_TRUE. + contextProgramCacheEnabled(true), resetStrategy(EGL_NO_RESET_NOTIFICATION_EXT), colorSpace(EGL_COLORSPACE_LINEAR), swapInterval(kDefaultSwapInterval) @@ -381,11 +399,10 @@ GLWindowResult EGLWindow::initializeSurface(OSWindow *osWindow, bool hasRobustResourceInit = strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr; - if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid()) + if (hasRobustResourceInit) { surfaceAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE); - surfaceAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE - : EGL_FALSE); + surfaceAttributes.push_back(mConfigParams.robustResourceInit ? EGL_TRUE : EGL_FALSE); } bool hasGLColorSpace = strstr(displayExtensions, "EGL_KHR_gl_colorspace") != nullptr; @@ -415,9 +432,10 @@ GLWindowResult EGLWindow::initializeSurface(OSWindow *osWindow, mSurface = eglCreateWindowSurface(mDisplay, mConfig, osWindow->getNativeWindow(), &surfaceAttributes[0]); - if (eglGetError() != EGL_SUCCESS || (mSurface == EGL_NO_SURFACE)) + EGLint error = eglGetError(); + if (error != EGL_SUCCESS || (mSurface == EGL_NO_SURFACE)) { - fprintf(stderr, "eglCreateWindowSurface failed: 0x%X\n", eglGetError()); + fprintf(stderr, "eglCreateWindowSurface failed: 0x%X\n", error); destroyGL(); return GLWindowResult::Error; } @@ -463,7 +481,7 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) bool hasWebGLCompatibility = strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr; - if (mConfigParams.webGLCompatibility.valid() && !hasWebGLCompatibility) + if (mConfigParams.webGLCompatibility && !hasWebGLCompatibility) { fprintf(stderr, "EGL_ANGLE_create_context_webgl_compatibility missing.\n"); return EGL_NO_CONTEXT; @@ -471,7 +489,7 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) bool hasCreateContextExtensionsEnabled = strstr(displayExtensions, "EGL_ANGLE_create_context_extensions_enabled") != nullptr; - if (mConfigParams.extensionsEnabled.valid() && !hasCreateContextExtensionsEnabled) + if (!mConfigParams.extensionsEnabled && !hasCreateContextExtensionsEnabled) { fprintf(stderr, "EGL_ANGLE_create_context_extensions_enabled missing.\n"); return EGL_NO_CONTEXT; @@ -490,6 +508,7 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr; if (!mConfigParams.bindGeneratesResource && !hasBindGeneratesResource) { + // Non-default state requested without the extension present fprintf(stderr, "EGL_CHROMIUM_create_context_bind_generates_resource missing.\n"); return EGL_NO_CONTEXT; } @@ -505,8 +524,9 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) bool hasProgramCacheControlExtension = strstr(displayExtensions, "EGL_ANGLE_program_cache_control ") != nullptr; - if (mConfigParams.contextProgramCacheEnabled.valid() && !hasProgramCacheControlExtension) + if (!mConfigParams.contextProgramCacheEnabled && !hasProgramCacheControlExtension) { + // Non-default state requested without the extension present fprintf(stderr, "EGL_ANGLE_program_cache_control missing.\n"); return EGL_NO_CONTEXT; } @@ -519,6 +539,14 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) return EGL_NO_CONTEXT; } + bool hasRobustResourceInit = + strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr; + if (mConfigParams.robustResourceInit && !hasRobustResourceInit) + { + fprintf(stderr, "EGL_ANGLE_robust_resource_initialization missing.\n"); + return EGL_NO_CONTEXT; + } + eglBindAPI(EGL_OPENGL_ES_API); if (eglGetError() != EGL_SUCCESS) { @@ -558,18 +586,16 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) contextAttributes.push_back(mConfigParams.noError ? EGL_TRUE : EGL_FALSE); } - if (mConfigParams.webGLCompatibility.valid()) + if (hasWebGLCompatibility) { contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE); - contextAttributes.push_back(mConfigParams.webGLCompatibility.value() ? EGL_TRUE - : EGL_FALSE); + contextAttributes.push_back(mConfigParams.webGLCompatibility ? EGL_TRUE : EGL_FALSE); } - if (mConfigParams.extensionsEnabled.valid()) + if (hasCreateContextExtensionsEnabled) { contextAttributes.push_back(EGL_EXTENSIONS_ENABLED_ANGLE); - contextAttributes.push_back(mConfigParams.extensionsEnabled.value() ? EGL_TRUE - : EGL_FALSE); + contextAttributes.push_back(mConfigParams.extensionsEnabled ? EGL_TRUE : EGL_FALSE); } if (hasRobustness) @@ -593,11 +619,11 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) contextAttributes.push_back(mConfigParams.clientArraysEnabled ? EGL_TRUE : EGL_FALSE); } - if (mConfigParams.contextProgramCacheEnabled.valid()) + if (hasProgramCacheControlExtension) { contextAttributes.push_back(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE); - contextAttributes.push_back( - mConfigParams.contextProgramCacheEnabled.value() ? EGL_TRUE : EGL_FALSE); + contextAttributes.push_back(mConfigParams.contextProgramCacheEnabled ? EGL_TRUE + : EGL_FALSE); } bool hasBackwardsCompatibleContextExtension = @@ -609,13 +635,10 @@ EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes) contextAttributes.push_back(EGL_FALSE); } - bool hasRobustResourceInit = - strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr; - if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid()) + if (hasRobustResourceInit) { contextAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE); - contextAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE - : EGL_FALSE); + contextAttributes.push_back(mConfigParams.robustResourceInit ? EGL_TRUE : EGL_FALSE); } } contextAttributes.push_back(EGL_NONE); @@ -645,6 +668,31 @@ bool EGLWindow::initializeContext() return false; } + // Without EGL_ANGLE_create_context_backwards_compatible and specifying + // EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE = EGL_FALSE, ANGLE will create a context with + // the maximum conformant version the display supports. If the extension is not supported, we + // need to query the actual context version, so each test can behave accordingly. + // EGL 1.5 Spec + // 3.7.1.1 OpenGL and OpenGL ES Context Versions + // The context returned must be the specified version, or a later version which is + // backwards compatible with that version. + bool hasBackwardsCompatibleContextExtension = angle::CheckExtensionExists( + eglQueryString(mDisplay, EGL_EXTENSIONS), "EGL_ANGLE_create_context_backwards_compatible"); + if (!hasBackwardsCompatibleContextExtension) + { + std::pair version = angle::GetCurrentContextVersion(); + // There's no OpenGL ES version "0.x". There is "x.0", though, so we can only check the + // first. + if (version.first == 0) + { + fprintf(stderr, "Failed to query the current context version: 0x%X\n", eglGetError()); + return false; + } + + mClientMajorVersion = version.first; + mClientMinorVersion = version.second; + } + return true; } diff --git a/util/EGLWindow.h b/util/EGLWindow.h index 833165c99d7..c59bc2c1311 100644 --- a/util/EGLWindow.h +++ b/util/EGLWindow.h @@ -43,21 +43,21 @@ struct ANGLE_UTIL_EXPORT ConfigParameters int depthBits; int stencilBits; - Optional webGLCompatibility; - Optional robustResourceInit; + bool webGLCompatibility; + bool robustResourceInit; // EGLWindow-specific. EGLenum componentType; bool multisample; bool debug; bool noError; - Optional extensionsEnabled; + bool extensionsEnabled; bool bindGeneratesResource; bool clientArraysEnabled; bool robustAccess; bool mutableRenderBuffer; EGLint samples; - Optional contextProgramCacheEnabled; + bool contextProgramCacheEnabled; EGLenum resetStrategy; EGLenum colorSpace; EGLint swapInterval; diff --git a/util/Event.h b/util/Event.h index 6fc3aca6a74..424524663a3 100644 --- a/util/Event.h +++ b/util/Event.h @@ -27,7 +27,7 @@ class Event struct KeyEvent { - Key Code; + angle::KeyType Code; bool Alt; bool Control; bool Shift; @@ -42,7 +42,7 @@ class Event struct MouseButtonEvent { - MouseButton Button; + angle::MouseButtonType Button; int X; int Y; }; diff --git a/util/Matrix.cpp b/util/Matrix.cpp index b1ab85e38ed..9d0382b1101 100644 --- a/util/Matrix.cpp +++ b/util/Matrix.cpp @@ -7,6 +7,10 @@ // Helper class for doing matrix math. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "Matrix.h" #define _USE_MATH_DEFINES diff --git a/util/OSWindow.cpp b/util/OSWindow.cpp index 3aac0ac5e02..b57eea26ad7 100644 --- a/util/OSWindow.cpp +++ b/util/OSWindow.cpp @@ -4,6 +4,10 @@ // found in the LICENSE file. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "OSWindow.h" #include @@ -23,21 +27,21 @@ #endif #if DEBUG_EVENTS -static const char *MouseButtonName(MouseButton button) +static const char *MouseButtonName(angle::MouseButtonType button) { switch (button) { - case MOUSEBUTTON_UNKNOWN: + case angle::MouseButtonType::UNKNOWN: return "Unknown"; - case MOUSEBUTTON_LEFT: + case angle::MouseButtonType::LEFT: return "Left"; - case MOUSEBUTTON_RIGHT: + case angle::MouseButtonType::RIGHT: return "Right"; - case MOUSEBUTTON_MIDDLE: + case angle::MouseButtonType::MIDDLE: return "Middle"; - case MOUSEBUTTON_BUTTON4: + case angle::MouseButtonType::BUTTON4: return "Button4"; - case MOUSEBUTTON_BUTTON5: + case angle::MouseButtonType::BUTTON5: return "Button5"; default: UNREACHABLE(); @@ -45,213 +49,213 @@ static const char *MouseButtonName(MouseButton button) } } -static const char *KeyName(Key key) +static const char *KeyName(angle::KeyType key) { switch (key) { - case KEY_UNKNOWN: + case angle::KeyType::UNKNOWN: return "Unknown"; - case KEY_A: + case angle::KeyType::A: return "A"; - case KEY_B: + case angle::KeyType::B: return "B"; - case KEY_C: + case angle::KeyType::C: return "C"; - case KEY_D: + case angle::KeyType::D: return "D"; - case KEY_E: + case angle::KeyType::E: return "E"; - case KEY_F: + case angle::KeyType::F: return "F"; - case KEY_G: + case angle::KeyType::G: return "G"; - case KEY_H: + case angle::KeyType::H: return "H"; - case KEY_I: + case angle::KeyType::I: return "I"; - case KEY_J: + case angle::KeyType::J: return "J"; - case KEY_K: + case angle::KeyType::K: return "K"; - case KEY_L: + case angle::KeyType::L: return "L"; - case KEY_M: + case angle::KeyType::M: return "M"; - case KEY_N: + case angle::KeyType::N: return "N"; - case KEY_O: + case angle::KeyType::O: return "O"; - case KEY_P: + case angle::KeyType::P: return "P"; - case KEY_Q: + case angle::KeyType::Q: return "Q"; - case KEY_R: + case angle::KeyType::R: return "R"; - case KEY_S: + case angle::KeyType::S: return "S"; - case KEY_T: + case angle::KeyType::T: return "T"; - case KEY_U: + case angle::KeyType::U: return "U"; - case KEY_V: + case angle::KeyType::V: return "V"; - case KEY_W: + case angle::KeyType::W: return "W"; - case KEY_X: + case angle::KeyType::X: return "X"; - case KEY_Y: + case angle::KeyType::Y: return "Y"; - case KEY_Z: + case angle::KeyType::Z: return "Z"; - case KEY_NUM0: + case angle::KeyType::NUM0: return "Num0"; - case KEY_NUM1: + case angle::KeyType::NUM1: return "Num1"; - case KEY_NUM2: + case angle::KeyType::NUM2: return "Num2"; - case KEY_NUM3: + case angle::KeyType::NUM3: return "Num3"; - case KEY_NUM4: + case angle::KeyType::NUM4: return "Num4"; - case KEY_NUM5: + case angle::KeyType::NUM5: return "Num5"; - case KEY_NUM6: + case angle::KeyType::NUM6: return "Num6"; - case KEY_NUM7: + case angle::KeyType::NUM7: return "Num7"; - case KEY_NUM8: + case angle::KeyType::NUM8: return "Num8"; - case KEY_NUM9: + case angle::KeyType::NUM9: return "Num9"; - case KEY_ESCAPE: + case angle::KeyType::ESCAPE: return "Escape"; - case KEY_LCONTROL: + case angle::KeyType::LCONTROL: return "Left Control"; - case KEY_LSHIFT: + case angle::KeyType::LSHIFT: return "Left Shift"; - case KEY_LALT: + case angle::KeyType::LALT: return "Left Alt"; - case KEY_LSYSTEM: + case angle::KeyType::LSYSTEM: return "Left System"; - case KEY_RCONTROL: + case angle::KeyType::RCONTROL: return "Right Control"; - case KEY_RSHIFT: + case angle::KeyType::RSHIFT: return "Right Shift"; - case KEY_RALT: + case angle::KeyType::RALT: return "Right Alt"; - case KEY_RSYSTEM: + case angle::KeyType::RSYSTEM: return "Right System"; - case KEY_MENU: + case angle::KeyType::MENU: return "Menu"; - case KEY_LBRACKET: + case angle::KeyType::LBRACKET: return "Left Bracket"; - case KEY_RBRACKET: + case angle::KeyType::RBRACKET: return "Right Bracket"; - case KEY_SEMICOLON: + case angle::KeyType::SEMICOLON: return "Semicolon"; - case KEY_COMMA: + case angle::KeyType::COMMA: return "Comma"; - case KEY_PERIOD: + case angle::KeyType::PERIOD: return "Period"; - case KEY_QUOTE: + case angle::KeyType::QUOTE: return "Quote"; - case KEY_SLASH: + case angle::KeyType::SLASH: return "Slash"; - case KEY_BACKSLASH: + case angle::KeyType::BACKSLASH: return "Backslash"; - case KEY_TILDE: + case angle::KeyType::TILDE: return "Tilde"; - case KEY_EQUAL: + case angle::KeyType::EQUAL: return "Equal"; - case KEY_DASH: + case angle::KeyType::DASH: return "Dash"; - case KEY_SPACE: + case angle::KeyType::SPACE: return "Space"; - case KEY_RETURN: + case angle::KeyType::RETURN: return "Return"; - case KEY_BACK: + case angle::KeyType::BACK: return "Back"; - case KEY_TAB: + case angle::KeyType::TAB: return "Tab"; - case KEY_PAGEUP: + case angle::KeyType::PAGEUP: return "Page Up"; - case KEY_PAGEDOWN: + case angle::KeyType::PAGEDOWN: return "Page Down"; - case KEY_END: + case angle::KeyType::END: return "End"; - case KEY_HOME: + case angle::KeyType::HOME: return "Home"; - case KEY_INSERT: + case angle::KeyType::INSERT: return "Insert"; - case KEY_DELETE: + case angle::KeyType::DEL: return "Delete"; - case KEY_ADD: + case angle::KeyType::ADD: return "Add"; - case KEY_SUBTRACT: + case angle::KeyType::SUBTRACT: return "Substract"; - case KEY_MULTIPLY: + case angle::KeyType::MULTIPLY: return "Multiply"; - case KEY_DIVIDE: + case angle::KeyType::DIVIDE: return "Divide"; - case KEY_LEFT: + case angle::KeyType::LEFT: return "Left"; - case KEY_RIGHT: + case angle::KeyType::RIGHT: return "Right"; - case KEY_UP: + case angle::KeyType::UP: return "Up"; - case KEY_DOWN: + case angle::KeyType::DOWN: return "Down"; - case KEY_NUMPAD0: + case angle::KeyType::NUMPAD0: return "Numpad 0"; - case KEY_NUMPAD1: + case angle::KeyType::NUMPAD1: return "Numpad 1"; - case KEY_NUMPAD2: + case angle::KeyType::NUMPAD2: return "Numpad 2"; - case KEY_NUMPAD3: + case angle::KeyType::NUMPAD3: return "Numpad 3"; - case KEY_NUMPAD4: + case angle::KeyType::NUMPAD4: return "Numpad 4"; - case KEY_NUMPAD5: + case angle::KeyType::NUMPAD5: return "Numpad 5"; - case KEY_NUMPAD6: + case angle::KeyType::NUMPAD6: return "Numpad 6"; - case KEY_NUMPAD7: + case angle::KeyType::NUMPAD7: return "Numpad 7"; - case KEY_NUMPAD8: + case angle::KeyType::NUMPAD8: return "Numpad 8"; - case KEY_NUMPAD9: + case angle::KeyType::NUMPAD9: return "Numpad 9"; - case KEY_F1: + case angle::KeyType::F1: return "F1"; - case KEY_F2: + case angle::KeyType::F2: return "F2"; - case KEY_F3: + case angle::KeyType::F3: return "F3"; - case KEY_F4: + case angle::KeyType::F4: return "F4"; - case KEY_F5: + case angle::KeyType::F5: return "F5"; - case KEY_F6: + case angle::KeyType::F6: return "F6"; - case KEY_F7: + case angle::KeyType::F7: return "F7"; - case KEY_F8: + case angle::KeyType::F8: return "F8"; - case KEY_F9: + case angle::KeyType::F9: return "F9"; - case KEY_F10: + case angle::KeyType::F10: return "F10"; - case KEY_F11: + case angle::KeyType::F11: return "F11"; - case KEY_F12: + case angle::KeyType::F12: return "F12"; - case KEY_F13: + case angle::KeyType::F13: return "F13"; - case KEY_F14: + case angle::KeyType::F14: return "F14"; - case KEY_F15: + case angle::KeyType::F15: return "F15"; - case KEY_PAUSE: + case angle::KeyType::PAUSE: return "Pause"; default: return "Unknown Key"; diff --git a/util/Timer.cpp b/util/Timer.cpp index 5bd51f24872..448df66069f 100644 --- a/util/Timer.cpp +++ b/util/Timer.cpp @@ -8,11 +8,20 @@ #include "util/Timer.h" +#include "common/debug.h" #include "common/system_utils.h" -Timer::Timer() : mRunning(false), mStartTime(0), mStopTime(0) {} +Timer::Timer() + : mRunning(false), mStartTime(0.0), mStopTime(0.0), mStartCpuTime(0.0), mStopCpuTime(0.0) +{} void Timer::start() +{ + ASSERT(!mRunning); + restart(); +} + +void Timer::restart() { mStartTime = angle::GetCurrentSystemTime(); mStartCpuTime = angle::GetCurrentProcessCpuTime(); @@ -21,6 +30,7 @@ void Timer::start() void Timer::stop() { + ASSERT(mRunning); mStopTime = angle::GetCurrentSystemTime(); mStopCpuTime = angle::GetCurrentProcessCpuTime(); mRunning = false; diff --git a/util/Timer.h b/util/Timer.h index af5cefe4886..8acb52403cf 100644 --- a/util/Timer.h +++ b/util/Timer.h @@ -17,6 +17,7 @@ class Timer final // duration. If getElapsedWallClockTime() is called in between, it will report the elapsed time // since start(). void start(); + void restart(); void stop(); double getElapsedWallClockTime() const; double getElapsedCpuTime() const; diff --git a/util/android/AndroidWindow.cpp b/util/android/AndroidWindow.cpp index cb6554e92ca..494f9bfd55b 100644 --- a/util/android/AndroidWindow.cpp +++ b/util/android/AndroidWindow.cpp @@ -127,9 +127,19 @@ bool AndroidWindow::resize(int width, int height) FATAL() << "Window is NULL (is screen locked? e.g. SplashScreen in logcat)"; } - // TODO: figure out a way to set the format as well, - // which is available only after EGLWindow initialization - int32_t err = ANativeWindow_setBuffersGeometry(sApp->window, mWidth, mHeight, 0); + // On some devices acquiring next swapchain image after window format change (without resize) + // does not return VK_ERROR_OUT_OF_DATE_KHR. Further rendering into the acquired image and/or + // presenting that image may produce undefined results. Try to preserve current window format + // to avoid such problem. Note, window format is automatically set after swapchain create based + // on the create info imageFormat. + int32_t currentFormat = ANativeWindow_getFormat(sApp->window); + if (currentFormat < 0) + { + ERR() << "ANativeWindow_getFormat() failed: " << currentFormat; + currentFormat = 0; + } + + int32_t err = ANativeWindow_setBuffersGeometry(sApp->window, mWidth, mHeight, currentFormat); return err == 0; } @@ -199,6 +209,12 @@ void android_main(struct android_app *app) if (source != nullptr) { source->process(app, source); + + // Check if the app is being destroyed, so we don't block it forever. + if (sApp->destroyRequested) + { + break; + } } } } diff --git a/util/android/third_party/LICENSE b/util/android/third_party/LICENSE new file mode 100644 index 00000000000..7a4a3ea2424 --- /dev/null +++ b/util/android/third_party/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. \ No newline at end of file diff --git a/util/android/third_party/README.chromium b/util/android/third_party/README.chromium index 17beb8f2ba4..65c0244f249 100644 --- a/util/android/third_party/README.chromium +++ b/util/android/third_party/README.chromium @@ -1,9 +1,10 @@ Name: android_native_app_glue URL: https://android.googlesource.com/platform/ndk/+/5aac75cf5bea628f44bc8e09fe672573aeac0849/sources/android/native_app_glue +Version: N/A Revision: 5aac75cf5bea628f44bc8e09fe672573aeac0849 -Version: 5aac75cf5bea628f44bc8e09fe672573aeac0849 -License: Apache License, Version 2.0 -License File: http://www.apache.org/licenses/LICENSE-2.0 +Update Mechanism: Manual +License: Apache-2.0 +License File: LICENSE Security Critical: no Shipped: no diff --git a/util/autogen/angle_features_autogen.cpp b/util/autogen/angle_features_autogen.cpp index 335f1120ea6..f784631c546 100644 --- a/util/autogen/angle_features_autogen.cpp +++ b/util/autogen/angle_features_autogen.cpp @@ -29,10 +29,12 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::AllowETCFormats, "allowETCFormats"}, {Feature::AllowGenerateMipmapWithCompute, "allowGenerateMipmapWithCompute"}, {Feature::AllowGenMultipleMipsPerPass, "allowGenMultipleMipsPerPass"}, + {Feature::AllowHostImageCopyAfterInitialUpload, "allowHostImageCopyAfterInitialUpload"}, {Feature::AllowHostImageCopyDespiteNonIdenticalLayout, "allowHostImageCopyDespiteNonIdenticalLayout"}, {Feature::AllowInlineConstVertexData, "allowInlineConstVertexData"}, {Feature::AllowMultisampledRenderToTextureEmulation, "allowMultisampledRenderToTextureEmulation"}, {Feature::AllowMultisampleStoreAndResolve, "allowMultisampleStoreAndResolve"}, + {Feature::AllowPipelineStatisticsForPrimitivesGeneratedQuery, "allowPipelineStatisticsForPrimitivesGeneratedQuery"}, {Feature::AllowRenderpassWithoutAttachment, "allowRenderpassWithoutAttachment"}, {Feature::AllowRuntimeSamplerCompareMode, "allowRuntimeSamplerCompareMode"}, {Feature::AllowSamplerCompareGradient, "allowSamplerCompareGradient"}, @@ -47,11 +49,14 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::AlwaysUseSharedStorageModeForBuffers, "alwaysUseSharedStorageModeForBuffers"}, {Feature::AlwaysUseStagedBufferUpdates, "alwaysUseStagedBufferUpdates"}, {Feature::AppendAliasedMemoryDecorations, "appendAliasedMemoryDecorations"}, - {Feature::AsyncCommandBufferResetAndGarbageCleanup, "asyncCommandBufferResetAndGarbageCleanup"}, + {Feature::AsyncCommandBufferReset, "asyncCommandBufferReset"}, + {Feature::AsyncGarbageCleanup, "asyncGarbageCleanup"}, {Feature::Avoid1BitAlphaTextureFormats, "avoid1BitAlphaTextureFormats"}, {Feature::AvoidBindFragDataLocation, "avoidBindFragDataLocation"}, + {Feature::AvoidInvisibleWindowSwapchainRecreate, "avoidInvisibleWindowSwapchainRecreate"}, {Feature::AvoidOpSelectWithMismatchingRelaxedPrecision, "avoidOpSelectWithMismatchingRelaxedPrecision"}, {Feature::AvoidStencilTextureSwizzle, "avoidStencilTextureSwizzle"}, + {Feature::AvoidWaitAny, "avoidWaitAny"}, {Feature::BgraTexImageFormatsBroken, "bgraTexImageFormatsBroken"}, {Feature::BindCompleteFramebufferForTimerQueries, "bindCompleteFramebufferForTimerQueries"}, {Feature::BindTransformFeedbackBufferBeforeBindBufferRange, "bindTransformFeedbackBufferBeforeBindBufferRange"}, @@ -66,29 +71,33 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::ClampPointSize, "clampPointSize"}, {Feature::ClDumpVkSpirv, "clDumpVkSpirv"}, {Feature::ClearsWithGapsNeedFlush, "clearsWithGapsNeedFlush"}, - {Feature::ClearToZeroOrOneBroken, "clearToZeroOrOneBroken"}, + {Feature::ClipCullDistanceBrokenWithPassthroughShaders, "clipCullDistanceBrokenWithPassthroughShaders"}, {Feature::ClipSrcRegionForBlitFramebuffer, "clipSrcRegionForBlitFramebuffer"}, + {Feature::ClSerializedExecution, "clSerializedExecution"}, {Feature::CompileJobIsThreadSafe, "compileJobIsThreadSafe"}, - {Feature::CompressVertexData, "compressVertexData"}, + {Feature::ConvertLowpAndMediumpFloatUniformsTo16Bits, "convertLowpAndMediumpFloatUniformsTo16Bits"}, {Feature::CopyIOSurfaceToNonIOSurfaceForReadOptimization, "copyIOSurfaceToNonIOSurfaceForReadOptimization"}, {Feature::CopyTextureToBufferForReadOptimization, "copyTextureToBufferForReadOptimization"}, {Feature::CorruptProgramBinaryForTesting, "corruptProgramBinaryForTesting"}, + {Feature::DebugClDumpCommandStream, "debugClDumpCommandStream"}, {Feature::DecodeEncodeSRGBForGenerateMipmap, "decodeEncodeSRGBForGenerateMipmap"}, {Feature::DepthStencilBlitExtraCopy, "depthStencilBlitExtraCopy"}, {Feature::DescriptorSetCache, "descriptorSetCache"}, + {Feature::DestroyOldSwapchainInSharedPresentMode, "destroyOldSwapchainInSharedPresentMode"}, {Feature::DisableAnisotropicFiltering, "disableAnisotropicFiltering"}, {Feature::DisableB5G6R5Support, "disableB5G6R5Support"}, {Feature::DisableBaseInstanceVertex, "disableBaseInstanceVertex"}, {Feature::DisableBlendEquationAdvanced, "disableBlendEquationAdvanced"}, - {Feature::DisableBlendFuncExtended, "disableBlendFuncExtended"}, + {Feature::DisableClearTexImageForRobustInit, "disableClearTexImageForRobustInit"}, {Feature::DisableClipControl, "disableClipControl"}, {Feature::DisableDepthStencilResolveThroughAttachment, "disableDepthStencilResolveThroughAttachment"}, {Feature::DisableDrawBuffersIndexed, "disableDrawBuffersIndexed"}, - {Feature::DisableFlippingBlitWithCommand, "disableFlippingBlitWithCommand"}, {Feature::DisableGPUSwitchingSupport, "disableGPUSwitchingSupport"}, {Feature::DisableMetalOnNvidia, "disableMetalOnNvidia"}, + {Feature::DisableMSAASampleCount1, "disableMSAASampleCount1"}, {Feature::DisableMultisampledRenderToTexture, "disableMultisampledRenderToTexture"}, {Feature::DisableNativeParallelCompile, "disableNativeParallelCompile"}, + {Feature::DisablePassthroughShaders, "disablePassthroughShaders"}, {Feature::DisablePipelineCacheLoadForTesting, "disablePipelineCacheLoadForTesting"}, {Feature::DisableProgramBinary, "disableProgramBinary"}, {Feature::DisableProgramCaching, "disableProgramCaching"}, @@ -111,10 +120,11 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::DontInitializeUninitializedLocals, "dontInitializeUninitializedLocals"}, {Feature::DontUseLoopsToInitializeVariables, "dontUseLoopsToInitializeVariables"}, {Feature::DoubleDepthBiasConstantFactor, "doubleDepthBiasConstantFactor"}, - {Feature::DoWhileGLSLCausesGPUHang, "doWhileGLSLCausesGPUHang"}, + {Feature::DropDepthStencilClearOnInvalidate, "dropDepthStencilClearOnInvalidate"}, {Feature::DumpShaderSource, "dumpShaderSource"}, {Feature::DumpTranslatedShaders, "dumpTranslatedShaders"}, {Feature::EglColorspaceAttributePassthrough, "eglColorspaceAttributePassthrough"}, + {Feature::EmitMaxGlsl400ForTesting, "emitMaxGlsl400ForTesting"}, {Feature::EmulateAbsIntFunction, "emulateAbsIntFunction"}, {Feature::EmulateAdvancedBlendEquations, "emulateAdvancedBlendEquations"}, {Feature::EmulateAlphaToCoverage, "emulateAlphaToCoverage"}, @@ -141,6 +151,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::EnableAdditionalBlendFactorsForDithering, "enableAdditionalBlendFactorsForDithering"}, {Feature::EnableAsyncPipelineCacheCompression, "enableAsyncPipelineCacheCompression"}, {Feature::EnableCaptureLimits, "enableCaptureLimits"}, + {Feature::EnableExtraSubmitFence, "enableExtraSubmitFence"}, {Feature::EnableInMemoryMtlLibraryCache, "enableInMemoryMtlLibraryCache"}, {Feature::EnableMergeClientAttribBuffer, "enableMergeClientAttribBuffer"}, {Feature::EnableMultisampledRenderToTexture, "enableMultisampledRenderToTexture"}, @@ -150,11 +161,11 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::EnablePipelineCacheDataCompression, "enablePipelineCacheDataCompression"}, {Feature::EnablePortabilityEnumeration, "enablePortabilityEnumeration"}, {Feature::EnablePrecisionQualifiers, "enablePrecisionQualifiers"}, - {Feature::EnablePreRotateSurfaces, "enablePreRotateSurfaces"}, {Feature::EnableProgramBinaryForCapture, "enableProgramBinaryForCapture"}, {Feature::EnableShaderSubstitution, "enableShaderSubstitution"}, {Feature::EnableTimestampQueries, "enableTimestampQueries"}, {Feature::EnableTranslatedShaderSubstitution, "enableTranslatedShaderSubstitution"}, + {Feature::EnsureLoopForwardProgress, "ensureLoopForwardProgress"}, {Feature::EnsureNonEmptyBufferIsBoundForDraw, "ensureNonEmptyBufferIsBoundForDraw"}, {Feature::ExpandIntegerPowExpressions, "expandIntegerPowExpressions"}, {Feature::ExplicitFragmentLocations, "explicitFragmentLocations"}, @@ -162,6 +173,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::ExplicitlyEnablePerSampleShading, "explicitlyEnablePerSampleShading"}, {Feature::ExposeES32ForTesting, "exposeES32ForTesting"}, {Feature::ExposeNonConformantExtensionsAndVersions, "exposeNonConformantExtensionsAndVersions"}, + {Feature::ExternallySynchronizePipelineCacheAccess, "externallySynchronizePipelineCacheAccess"}, {Feature::FinishDoesNotCauseQueriesToBeAvailable, "finishDoesNotCauseQueriesToBeAvailable"}, {Feature::FlushAfterEndingTransformFeedback, "flushAfterEndingTransformFeedback"}, {Feature::FlushAfterStreamVertexData, "flushAfterStreamVertexData"}, @@ -172,20 +184,25 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::ForceContinuousRefreshOnSharedPresent, "forceContinuousRefreshOnSharedPresent"}, {Feature::ForceD16TexFilter, "forceD16TexFilter"}, {Feature::ForceD24S8AsUnsupported, "forceD24S8AsUnsupported"}, + {Feature::ForceDebugContexts, "forceDebugContexts"}, {Feature::ForceDepthAttachmentInitOnClear, "forceDepthAttachmentInitOnClear"}, {Feature::ForceDisableFullScreenExclusive, "forceDisableFullScreenExclusive"}, {Feature::ForceFallbackFormat, "forceFallbackFormat"}, {Feature::ForceFlushAfterDrawcallUsingShadowmap, "forceFlushAfterDrawcallUsingShadowmap"}, - {Feature::ForceFragmentShaderPrecisionHighpToMediump, "forceFragmentShaderPrecisionHighpToMediump"}, {Feature::ForceGlErrorChecking, "forceGlErrorChecking"}, + {Feature::ForceHostImageCopyForLuma, "forceHostImageCopyForLuma"}, {Feature::ForceInitShaderVariables, "forceInitShaderVariables"}, + {Feature::ForceMaxCombinedShaderOutputResources, "forceMaxCombinedShaderOutputResources"}, {Feature::ForceMaxUniformBufferSize16KB, "forceMaxUniformBufferSize16KB"}, {Feature::ForceMinimumMaxVertexAttributes, "forceMinimumMaxVertexAttributes"}, {Feature::ForceNearestFiltering, "forceNearestFiltering"}, {Feature::ForceNearestMipFiltering, "forceNearestMipFiltering"}, {Feature::ForceNonCSBaseMipmapGeneration, "forceNonCSBaseMipmapGeneration"}, + {Feature::ForcePassthroughShaders, "forcePassthroughShaders"}, {Feature::ForceRobustResourceInit, "forceRobustResourceInit"}, {Feature::ForceSampleUsageForAhbBackedImages, "forceSampleUsageForAhbBackedImages"}, + {Feature::ForceSizePointerForBoundVertexBuffers, "forceSizePointerForBoundVertexBuffers"}, + {Feature::ForceSubmitExceptionsAtFBOBoundary, "forceSubmitExceptionsAtFBOBoundary"}, {Feature::ForceSubmitImmutableTextureUpdates, "forceSubmitImmutableTextureUpdates"}, {Feature::ForceTextureLodOffset1, "forceTextureLodOffset1"}, {Feature::ForceTextureLodOffset2, "forceTextureLodOffset2"}, @@ -199,7 +216,6 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::HasBlobCacheThatEvictsOldItemsFirst, "hasBlobCacheThatEvictsOldItemsFirst"}, {Feature::HasCheapRenderPass, "hasCheapRenderPass"}, {Feature::HasDepthAutoResolve, "hasDepthAutoResolve"}, - {Feature::HasEffectivePipelineCacheSerialization, "hasEffectivePipelineCacheSerialization"}, {Feature::HasEvents, "hasEvents"}, {Feature::HasExplicitMemBarrier, "hasExplicitMemBarrier"}, {Feature::HasNonUniformDispatch, "hasNonUniformDispatch"}, @@ -209,8 +225,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::InitFragmentOutputVariables, "initFragmentOutputVariables"}, {Feature::InitializeCurrentVertexAttributes, "initializeCurrentVertexAttributes"}, {Feature::InjectAsmStatementIntoLoopBodies, "injectAsmStatementIntoLoopBodies"}, - {Feature::IntelDisableFastMath, "intelDisableFastMath"}, - {Feature::IntelExplicitBoolCastWorkaround, "intelExplicitBoolCastWorkaround"}, + {Feature::IsVertexSyncDeferred, "isVertexSyncDeferred"}, {Feature::KeepBufferShadowCopy, "keepBufferShadowCopy"}, {Feature::LimitMax3dArrayTextureSizeTo1024, "limitMax3dArrayTextureSizeTo1024"}, {Feature::LimitMaxColorTargetBitsForTesting, "limitMaxColorTargetBitsForTesting"}, @@ -229,25 +244,26 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::MrtPerfWorkaround, "mrtPerfWorkaround"}, {Feature::MultisampleColorFormatShaderReadWorkaround, "multisampleColorFormatShaderReadWorkaround"}, {Feature::MutableMipmapTextureUpload, "mutableMipmapTextureUpload"}, + {Feature::NoperspectiveInterpolationBrokenWithPassthroughShaders, "noperspectiveInterpolationBrokenWithPassthroughShaders"}, {Feature::OverrideSurfaceFormatRGB8ToRGBA8, "overrideSurfaceFormatRGB8ToRGBA8"}, {Feature::PackLastRowSeparatelyForPaddingInclusion, "packLastRowSeparatelyForPaddingInclusion"}, {Feature::PackOverlappingRowsSeparatelyPackBuffer, "packOverlappingRowsSeparatelyPackBuffer"}, {Feature::PadBuffersToMaxVertexAttribStride, "padBuffersToMaxVertexAttribStride"}, {Feature::PassHighpToPackUnormSnormBuiltins, "passHighpToPackUnormSnormBuiltins"}, - {Feature::PerFrameWindowSizeQuery, "perFrameWindowSizeQuery"}, {Feature::PermanentlySwitchToFramebufferFetchMode, "permanentlySwitchToFramebufferFetchMode"}, {Feature::PersistentlyMappedBuffers, "persistentlyMappedBuffers"}, {Feature::PreAddTexelFetchOffsets, "preAddTexelFetchOffsets"}, {Feature::PreemptivelyStartProvokingVertexCommandBuffer, "preemptivelyStartProvokingVertexCommandBuffer"}, {Feature::PreferAggregateBarrierCalls, "preferAggregateBarrierCalls"}, + {Feature::PreferBGR565ToRGB565, "preferBGR565ToRGB565"}, {Feature::PreferCachedNoncoherentForDynamicStreamBufferUsage, "preferCachedNoncoherentForDynamicStreamBufferUsage"}, {Feature::PreferCpuForBuffersubdata, "preferCpuForBuffersubdata"}, {Feature::PreferCPUForBufferSubData, "preferCPUForBufferSubData"}, {Feature::PreferDeviceLocalMemoryHostVisible, "preferDeviceLocalMemoryHostVisible"}, {Feature::PreferDoubleBufferSwapchainOnFifoMode, "preferDoubleBufferSwapchainOnFifoMode"}, {Feature::PreferDrawClearOverVkCmdClearAttachments, "preferDrawClearOverVkCmdClearAttachments"}, - {Feature::PreferDriverUniformOverSpecConst, "preferDriverUniformOverSpecConst"}, {Feature::PreferDynamicRendering, "preferDynamicRendering"}, + {Feature::PreferGlobalPipelineCache, "preferGlobalPipelineCache"}, {Feature::PreferHostCachedForNonStaticBufferUsage, "preferHostCachedForNonStaticBufferUsage"}, {Feature::PreferLinearFilterForYUV, "preferLinearFilterForYUV"}, {Feature::PreferMonolithicPipelinesOverLibraries, "preferMonolithicPipelinesOverLibraries"}, @@ -261,16 +277,16 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::QueryCounterBitsGeneratesErrors, "queryCounterBitsGeneratesErrors"}, {Feature::ReadPixelsUsingImplementationColorReadFormatForNorm16, "readPixelsUsingImplementationColorReadFormatForNorm16"}, {Feature::ReapplyUBOBindingsAfterUsingBinaryProgram, "reapplyUBOBindingsAfterUsingBinaryProgram"}, + {Feature::RecycleVkEvent, "recycleVkEvent"}, {Feature::RegenerateStructNames, "regenerateStructNames"}, - {Feature::RejectWebglShadersWithUndefinedBehavior, "rejectWebglShadersWithUndefinedBehavior"}, {Feature::RemoveDynamicIndexingOfSwizzledVector, "removeDynamicIndexingOfSwizzledVector"}, {Feature::RemoveInvariantAndCentroidForESSL3, "removeInvariantAndCentroidForESSL3"}, {Feature::RequireGpuFamily2, "requireGpuFamily2"}, {Feature::RescopeGlobalVariables, "rescopeGlobalVariables"}, + {Feature::ResetSampleCoverageOnFBOChange, "resetSampleCoverageOnFBOChange"}, {Feature::ResetTexImage2DBaseLevel, "resetTexImage2DBaseLevel"}, {Feature::ResyncDepthRangeOnClipControl, "resyncDepthRangeOnClipControl"}, {Feature::RetainSPIRVDebugInfo, "retainSPIRVDebugInfo"}, - {Feature::RewriteFloatUnaryMinusOperator, "rewriteFloatUnaryMinusOperator"}, {Feature::RewriteRepeatedAssignToSwizzled, "rewriteRepeatedAssignToSwizzled"}, {Feature::RewriteRowMajorMatrices, "rewriteRowMajorMatrices"}, {Feature::RewriteUnaryMinusOperator, "rewriteUnaryMinusOperator"}, @@ -284,10 +300,13 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SetPrimitiveRestartFixedIndexForDrawArrays, "setPrimitiveRestartFixedIndexForDrawArrays"}, {Feature::SetZeroLevelBeforeGenerateMipmap, "setZeroLevelBeforeGenerateMipmap"}, {Feature::ShiftInstancedArrayDataWithOffset, "shiftInstancedArrayDataWithOffset"}, + {Feature::SimulateTileMemoryForTesting, "simulateTileMemoryForTesting"}, {Feature::SingleThreadedTextureDecompression, "singleThreadedTextureDecompression"}, + {Feature::SkipPipelineCacheSerialization, "skipPipelineCacheSerialization"}, {Feature::SkipVSConstantRegisterZero, "skipVSConstantRegisterZero"}, {Feature::SlowDownMonolithicPipelineCreationForTesting, "slowDownMonolithicPipelineCreationForTesting"}, {Feature::SrgbBlendingBroken, "srgbBlendingBroken"}, + {Feature::SupportFragmentShadingRateExtExtensions, "supportFragmentShadingRateExtExtensions"}, {Feature::Supports16BitInputOutput, "supports16BitInputOutput"}, {Feature::Supports16BitPushConstant, "supports16BitPushConstant"}, {Feature::Supports16BitStorageBuffer, "supports16BitStorageBuffer"}, @@ -299,10 +318,17 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsAndroidNativeFenceSync, "supportsAndroidNativeFenceSync"}, {Feature::SupportsAngleRgbxInternalFormat, "supportsAngleRgbxInternalFormat"}, {Feature::SupportsAppleClipDistance, "supportsAppleClipDistance"}, + {Feature::SupportsAstc3d, "supportsAstc3d"}, + {Feature::SupportsAstcDecodeMode, "supportsAstcDecodeMode"}, + {Feature::SupportsAstcDecodeModeRgb9e5, "supportsAstcDecodeModeRgb9e5"}, + {Feature::SupportsAstcHdr3dTextures, "supportsAstcHdr3dTextures"}, {Feature::SupportsAstcSliced3d, "supportsAstcSliced3d"}, {Feature::SupportsBindMemory2, "supportsBindMemory2"}, + {Feature::SupportsBindVertexBuffers2, "supportsBindVertexBuffers2"}, {Feature::SupportsBlendOperationAdvanced, "supportsBlendOperationAdvanced"}, {Feature::SupportsBlendOperationAdvancedCoherent, "supportsBlendOperationAdvancedCoherent"}, + {Feature::SupportsBufferDeviceAddress, "supportsBufferDeviceAddress"}, + {Feature::SupportsClipCullDistanceInGSAndTS, "supportsClipCullDistanceInGSAndTS"}, {Feature::SupportsColorWriteEnable, "supportsColorWriteEnable"}, {Feature::SupportsComputeTranscodeEtcToBc, "supportsComputeTranscodeEtcToBc"}, {Feature::SupportsCustomBorderColor, "supportsCustomBorderColor"}, @@ -316,6 +342,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsDepthClipControl, "supportsDepthClipControl"}, {Feature::SupportsDepthStencilIndependentResolveNone, "supportsDepthStencilIndependentResolveNone"}, {Feature::SupportsDepthStencilResolve, "supportsDepthStencilResolve"}, + {Feature::SupportsDeviceFault, "supportsDeviceFault"}, {Feature::SupportsDynamicRendering, "supportsDynamicRendering"}, {Feature::SupportsDynamicRenderingLocalRead, "supportsDynamicRenderingLocalRead"}, {Feature::SupportsExtendedDynamicState, "supportsExtendedDynamicState"}, @@ -323,7 +350,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsExternalFenceCapabilities, "supportsExternalFenceCapabilities"}, {Feature::SupportsExternalFenceFd, "supportsExternalFenceFd"}, {Feature::SupportsExternalFormatResolve, "supportsExternalFormatResolve"}, - {Feature::SupportsExternalMemoryDmaBufAndModifiers, "supportsExternalMemoryDmaBufAndModifiers"}, + {Feature::SupportsExternalMemoryDmaBuf, "supportsExternalMemoryDmaBuf"}, {Feature::SupportsExternalMemoryFd, "supportsExternalMemoryFd"}, {Feature::SupportsExternalMemoryFuchsia, "supportsExternalMemoryFuchsia"}, {Feature::SupportsExternalMemoryHost, "supportsExternalMemoryHost"}, @@ -340,14 +367,17 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsFullScreenExclusive, "supportsFullScreenExclusive"}, {Feature::SupportsGeometryStreamsCapability, "supportsGeometryStreamsCapability"}, {Feature::SupportsGetMemoryRequirements2, "supportsGetMemoryRequirements2"}, - {Feature::SupportsGGPFrameToken, "supportsGGPFrameToken"}, + {Feature::SupportsGlobalPriority, "supportsGlobalPriority"}, + {Feature::SupportsGlobalPriorityQuery, "supportsGlobalPriorityQuery"}, {Feature::SupportsGraphicsPipelineLibrary, "supportsGraphicsPipelineLibrary"}, + {Feature::SupportShaderPixelLocalStorageAngle, "supportShaderPixelLocalStorageAngle"}, {Feature::SupportsHostImageCopy, "supportsHostImageCopy"}, {Feature::SupportsHostQueryReset, "supportsHostQueryReset"}, {Feature::SupportsImage2dViewOf3d, "supportsImage2dViewOf3d"}, {Feature::SupportsImageCompressionControl, "supportsImageCompressionControl"}, {Feature::SupportsImageCompressionControlSwapchain, "supportsImageCompressionControlSwapchain"}, {Feature::SupportsImageCubeArray, "supportsImageCubeArray"}, + {Feature::SupportsImageDrmFormatModifier, "supportsImageDrmFormatModifier"}, {Feature::SupportsImageFormatList, "supportsImageFormatList"}, {Feature::SupportsImagelessFramebuffer, "supportsImagelessFramebuffer"}, {Feature::SupportsIncrementalPresent, "supportsIncrementalPresent"}, @@ -356,11 +386,12 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsLockSurfaceExtension, "supportsLockSurfaceExtension"}, {Feature::SupportsLogicOpDynamicState, "supportsLogicOpDynamicState"}, {Feature::SupportsMaintenance5, "supportsMaintenance5"}, + {Feature::SupportsMaintenance9, "supportsMaintenance9"}, {Feature::SupportsMemoryBudget, "supportsMemoryBudget"}, - {Feature::SupportsMixedReadWriteDepthStencilLayouts, "supportsMixedReadWriteDepthStencilLayouts"}, {Feature::SupportsMultiDrawIndirect, "supportsMultiDrawIndirect"}, {Feature::SupportsMultisampledRenderToSingleSampled, "supportsMultisampledRenderToSingleSampled"}, {Feature::SupportsMultiview, "supportsMultiview"}, + {Feature::SupportsMultiviewMultisampleRenderToTexture, "supportsMultiviewMultisampleRenderToTexture"}, {Feature::SupportsNonConstantLoopIndexing, "supportsNonConstantLoopIndexing"}, {Feature::SupportsPipelineCreationFeedback, "supportsPipelineCreationFeedback"}, {Feature::SupportsPipelineProtectedAccess, "supportsPipelineProtectedAccess"}, @@ -368,6 +399,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsPipelineStatisticsQuery, "supportsPipelineStatisticsQuery"}, {Feature::SupportsPortabilityEnumeration, "supportsPortabilityEnumeration"}, {Feature::SupportsPresentation, "supportsPresentation"}, + {Feature::SupportsPrimitiveFragmentShadingRate, "supportsPrimitiveFragmentShadingRate"}, {Feature::SupportsPrimitivesGeneratedQuery, "supportsPrimitivesGeneratedQuery"}, {Feature::SupportsPrimitiveTopologyListRestart, "supportsPrimitiveTopologyListRestart"}, {Feature::SupportsProtectedMemory, "supportsProtectedMemory"}, @@ -383,6 +415,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsRoundingModeRtzFp64, "supportsRoundingModeRtzFp64"}, {Feature::SupportsSampler2dViewOf3d, "supportsSampler2dViewOf3d"}, {Feature::SupportsSamplerMirrorClampToEdge, "supportsSamplerMirrorClampToEdge"}, + {Feature::SupportsShaderAtomicInt64, "supportsShaderAtomicInt64"}, {Feature::SupportsShaderFloat16, "supportsShaderFloat16"}, {Feature::SupportsShaderFloat64, "supportsShaderFloat64"}, {Feature::SupportsShaderFramebufferFetch, "supportsShaderFramebufferFetch"}, @@ -391,6 +424,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsShaderFramebufferFetchNonCoherent, "supportsShaderFramebufferFetchNonCoherent"}, {Feature::SupportsShaderFramebufferFetchNonCoherentEXT, "supportsShaderFramebufferFetchNonCoherentEXT"}, {Feature::SupportsShaderInt8, "supportsShaderInt8"}, + {Feature::SupportsShaderIntegerDotProduct, "supportsShaderIntegerDotProduct"}, {Feature::SupportsShaderNonSemanticInfo, "supportsShaderNonSemanticInfo"}, {Feature::SupportsShaderStencilExport, "supportsShaderStencilExport"}, {Feature::SupportsSharedPresentableImageExtension, "supportsSharedPresentableImageExtension"}, @@ -404,11 +438,14 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SupportsSurfaceProtectedCapabilitiesExtension, "supportsSurfaceProtectedCapabilitiesExtension"}, {Feature::SupportsSurfaceProtectedSwapchains, "supportsSurfaceProtectedSwapchains"}, {Feature::SupportsSwapchainMaintenance1, "supportsSwapchainMaintenance1"}, + {Feature::SupportsSwapchainMutableFormat, "supportsSwapchainMutableFormat"}, {Feature::SupportsSynchronization2, "supportsSynchronization2"}, {Feature::SupportsTextureCompressionAstcHdr, "supportsTextureCompressionAstcHdr"}, + {Feature::SupportsTileMemoryHeap, "supportsTileMemoryHeap"}, {Feature::SupportsTimelineSemaphore, "supportsTimelineSemaphore"}, {Feature::SupportsTimestampSurfaceAttribute, "supportsTimestampSurfaceAttribute"}, {Feature::SupportsTransformFeedbackExtension, "supportsTransformFeedbackExtension"}, + {Feature::SupportsUnifiedImageLayouts, "supportsUnifiedImageLayouts"}, {Feature::SupportsUniformBufferStandardLayout, "supportsUniformBufferStandardLayout"}, {Feature::SupportsVertexInputDynamicState, "supportsVertexInputDynamicState"}, {Feature::SupportsYUVSamplerConversion, "supportsYUVSamplerConversion"}, @@ -417,6 +454,7 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::SyncAllVertexArraysToDefault, "syncAllVertexArraysToDefault"}, {Feature::SyncDefaultVertexArraysToDefault, "syncDefaultVertexArraysToDefault"}, {Feature::SyncMonolithicPipelinesToBlobCache, "syncMonolithicPipelinesToBlobCache"}, + {Feature::SyncPipelineCacheToBlobCacheEveryFrame, "syncPipelineCacheToBlobCacheEveryFrame"}, {Feature::UnbindFBOBeforeSwitchingContext, "unbindFBOBeforeSwitchingContext"}, {Feature::UncurrentEglSurfaceUponSurfaceDestroy, "uncurrentEglSurfaceUponSurfaceDestroy"}, {Feature::UnfoldShortCircuits, "unfoldShortCircuits"}, @@ -434,13 +472,16 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::UseEmptyBlobsToEraseOldPipelineCacheFromBlobCache, "useEmptyBlobsToEraseOldPipelineCacheFromBlobCache"}, {Feature::UseFrontFaceDynamicState, "useFrontFaceDynamicState"}, {Feature::UseIntermediateTextureForGenerateMipmap, "useIntermediateTextureForGenerateMipmap"}, + {Feature::UseIr, "useIr"}, {Feature::UseMultipleDescriptorsForExternalFormats, "useMultipleDescriptorsForExternalFormats"}, {Feature::UseNonZeroStencilWriteMaskStaticState, "useNonZeroStencilWriteMaskStaticState"}, {Feature::UsePrimitiveRestartEnableDynamicState, "usePrimitiveRestartEnableDynamicState"}, + {Feature::UsePrimitiveTopologyDynamicState, "usePrimitiveTopologyDynamicState"}, {Feature::UseRasterizerDiscardEnableDynamicState, "useRasterizerDiscardEnableDynamicState"}, {Feature::UseResetCommandBufferBitForSecondaryPools, "useResetCommandBufferBitForSecondaryPools"}, {Feature::UseShadowBuffersWhenAppropriate, "useShadowBuffersWhenAppropriate"}, {Feature::UsesNativeBuiltinClKernel, "usesNativeBuiltinClKernel"}, + {Feature::UsesSecondComponentForStencilBorderColor, "usesSecondComponentForStencilBorderColor"}, {Feature::UseStencilOpDynamicState, "useStencilOpDynamicState"}, {Feature::UseStencilTestEnableDynamicState, "useStencilTestEnableDynamicState"}, {Feature::UseSystemMemoryForConstantBuffers, "useSystemMemoryForConstantBuffers"}, @@ -452,7 +493,6 @@ constexpr PackedEnumMap kFeatureNames = {{ {Feature::VaryingsRequireMatchingPrecisionInSpirv, "varyingsRequireMatchingPrecisionInSpirv"}, {Feature::VerifyPipelineCacheInBlobCache, "verifyPipelineCacheInBlobCache"}, {Feature::VertexIDDoesNotIncludeBaseVertex, "vertexIDDoesNotIncludeBaseVertex"}, - {Feature::WaitIdleBeforeSwapchainRecreation, "waitIdleBeforeSwapchainRecreation"}, {Feature::WarmUpPipelineCacheAtLink, "warmUpPipelineCacheAtLink"}, {Feature::WrapSwitchInIfTrue, "wrapSwitchInIfTrue"}, {Feature::WriteHelperSampleMask, "writeHelperSampleMask"}, diff --git a/util/autogen/angle_features_autogen.h b/util/autogen/angle_features_autogen.h index bdf3c642bf1..56e3c1469b3 100644 --- a/util/autogen/angle_features_autogen.h +++ b/util/autogen/angle_features_autogen.h @@ -29,10 +29,12 @@ enum class Feature AllowETCFormats, AllowGenerateMipmapWithCompute, AllowGenMultipleMipsPerPass, + AllowHostImageCopyAfterInitialUpload, AllowHostImageCopyDespiteNonIdenticalLayout, AllowInlineConstVertexData, AllowMultisampledRenderToTextureEmulation, AllowMultisampleStoreAndResolve, + AllowPipelineStatisticsForPrimitivesGeneratedQuery, AllowRenderpassWithoutAttachment, AllowRuntimeSamplerCompareMode, AllowSamplerCompareGradient, @@ -47,11 +49,14 @@ enum class Feature AlwaysUseSharedStorageModeForBuffers, AlwaysUseStagedBufferUpdates, AppendAliasedMemoryDecorations, - AsyncCommandBufferResetAndGarbageCleanup, + AsyncCommandBufferReset, + AsyncGarbageCleanup, Avoid1BitAlphaTextureFormats, AvoidBindFragDataLocation, + AvoidInvisibleWindowSwapchainRecreate, AvoidOpSelectWithMismatchingRelaxedPrecision, AvoidStencilTextureSwizzle, + AvoidWaitAny, BgraTexImageFormatsBroken, BindCompleteFramebufferForTimerQueries, BindTransformFeedbackBufferBeforeBindBufferRange, @@ -66,29 +71,33 @@ enum class Feature ClampPointSize, ClDumpVkSpirv, ClearsWithGapsNeedFlush, - ClearToZeroOrOneBroken, + ClipCullDistanceBrokenWithPassthroughShaders, ClipSrcRegionForBlitFramebuffer, + ClSerializedExecution, CompileJobIsThreadSafe, - CompressVertexData, + ConvertLowpAndMediumpFloatUniformsTo16Bits, CopyIOSurfaceToNonIOSurfaceForReadOptimization, CopyTextureToBufferForReadOptimization, CorruptProgramBinaryForTesting, + DebugClDumpCommandStream, DecodeEncodeSRGBForGenerateMipmap, DepthStencilBlitExtraCopy, DescriptorSetCache, + DestroyOldSwapchainInSharedPresentMode, DisableAnisotropicFiltering, DisableB5G6R5Support, DisableBaseInstanceVertex, DisableBlendEquationAdvanced, - DisableBlendFuncExtended, + DisableClearTexImageForRobustInit, DisableClipControl, DisableDepthStencilResolveThroughAttachment, DisableDrawBuffersIndexed, - DisableFlippingBlitWithCommand, DisableGPUSwitchingSupport, DisableMetalOnNvidia, + DisableMSAASampleCount1, DisableMultisampledRenderToTexture, DisableNativeParallelCompile, + DisablePassthroughShaders, DisablePipelineCacheLoadForTesting, DisableProgramBinary, DisableProgramCaching, @@ -111,10 +120,11 @@ enum class Feature DontInitializeUninitializedLocals, DontUseLoopsToInitializeVariables, DoubleDepthBiasConstantFactor, - DoWhileGLSLCausesGPUHang, + DropDepthStencilClearOnInvalidate, DumpShaderSource, DumpTranslatedShaders, EglColorspaceAttributePassthrough, + EmitMaxGlsl400ForTesting, EmulateAbsIntFunction, EmulateAdvancedBlendEquations, EmulateAlphaToCoverage, @@ -141,6 +151,7 @@ enum class Feature EnableAdditionalBlendFactorsForDithering, EnableAsyncPipelineCacheCompression, EnableCaptureLimits, + EnableExtraSubmitFence, EnableInMemoryMtlLibraryCache, EnableMergeClientAttribBuffer, EnableMultisampledRenderToTexture, @@ -150,11 +161,11 @@ enum class Feature EnablePipelineCacheDataCompression, EnablePortabilityEnumeration, EnablePrecisionQualifiers, - EnablePreRotateSurfaces, EnableProgramBinaryForCapture, EnableShaderSubstitution, EnableTimestampQueries, EnableTranslatedShaderSubstitution, + EnsureLoopForwardProgress, EnsureNonEmptyBufferIsBoundForDraw, ExpandIntegerPowExpressions, ExplicitFragmentLocations, @@ -162,6 +173,7 @@ enum class Feature ExplicitlyEnablePerSampleShading, ExposeES32ForTesting, ExposeNonConformantExtensionsAndVersions, + ExternallySynchronizePipelineCacheAccess, FinishDoesNotCauseQueriesToBeAvailable, FlushAfterEndingTransformFeedback, FlushAfterStreamVertexData, @@ -172,20 +184,25 @@ enum class Feature ForceContinuousRefreshOnSharedPresent, ForceD16TexFilter, ForceD24S8AsUnsupported, + ForceDebugContexts, ForceDepthAttachmentInitOnClear, ForceDisableFullScreenExclusive, ForceFallbackFormat, ForceFlushAfterDrawcallUsingShadowmap, - ForceFragmentShaderPrecisionHighpToMediump, ForceGlErrorChecking, + ForceHostImageCopyForLuma, ForceInitShaderVariables, + ForceMaxCombinedShaderOutputResources, ForceMaxUniformBufferSize16KB, ForceMinimumMaxVertexAttributes, ForceNearestFiltering, ForceNearestMipFiltering, ForceNonCSBaseMipmapGeneration, + ForcePassthroughShaders, ForceRobustResourceInit, ForceSampleUsageForAhbBackedImages, + ForceSizePointerForBoundVertexBuffers, + ForceSubmitExceptionsAtFBOBoundary, ForceSubmitImmutableTextureUpdates, ForceTextureLodOffset1, ForceTextureLodOffset2, @@ -199,7 +216,6 @@ enum class Feature HasBlobCacheThatEvictsOldItemsFirst, HasCheapRenderPass, HasDepthAutoResolve, - HasEffectivePipelineCacheSerialization, HasEvents, HasExplicitMemBarrier, HasNonUniformDispatch, @@ -209,8 +225,7 @@ enum class Feature InitFragmentOutputVariables, InitializeCurrentVertexAttributes, InjectAsmStatementIntoLoopBodies, - IntelDisableFastMath, - IntelExplicitBoolCastWorkaround, + IsVertexSyncDeferred, KeepBufferShadowCopy, LimitMax3dArrayTextureSizeTo1024, LimitMaxColorTargetBitsForTesting, @@ -229,25 +244,26 @@ enum class Feature MrtPerfWorkaround, MultisampleColorFormatShaderReadWorkaround, MutableMipmapTextureUpload, + NoperspectiveInterpolationBrokenWithPassthroughShaders, OverrideSurfaceFormatRGB8ToRGBA8, PackLastRowSeparatelyForPaddingInclusion, PackOverlappingRowsSeparatelyPackBuffer, PadBuffersToMaxVertexAttribStride, PassHighpToPackUnormSnormBuiltins, - PerFrameWindowSizeQuery, PermanentlySwitchToFramebufferFetchMode, PersistentlyMappedBuffers, PreAddTexelFetchOffsets, PreemptivelyStartProvokingVertexCommandBuffer, PreferAggregateBarrierCalls, + PreferBGR565ToRGB565, PreferCachedNoncoherentForDynamicStreamBufferUsage, PreferCpuForBuffersubdata, PreferCPUForBufferSubData, PreferDeviceLocalMemoryHostVisible, PreferDoubleBufferSwapchainOnFifoMode, PreferDrawClearOverVkCmdClearAttachments, - PreferDriverUniformOverSpecConst, PreferDynamicRendering, + PreferGlobalPipelineCache, PreferHostCachedForNonStaticBufferUsage, PreferLinearFilterForYUV, PreferMonolithicPipelinesOverLibraries, @@ -261,16 +277,16 @@ enum class Feature QueryCounterBitsGeneratesErrors, ReadPixelsUsingImplementationColorReadFormatForNorm16, ReapplyUBOBindingsAfterUsingBinaryProgram, + RecycleVkEvent, RegenerateStructNames, - RejectWebglShadersWithUndefinedBehavior, RemoveDynamicIndexingOfSwizzledVector, RemoveInvariantAndCentroidForESSL3, RequireGpuFamily2, RescopeGlobalVariables, + ResetSampleCoverageOnFBOChange, ResetTexImage2DBaseLevel, ResyncDepthRangeOnClipControl, RetainSPIRVDebugInfo, - RewriteFloatUnaryMinusOperator, RewriteRepeatedAssignToSwizzled, RewriteRowMajorMatrices, RewriteUnaryMinusOperator, @@ -284,10 +300,13 @@ enum class Feature SetPrimitiveRestartFixedIndexForDrawArrays, SetZeroLevelBeforeGenerateMipmap, ShiftInstancedArrayDataWithOffset, + SimulateTileMemoryForTesting, SingleThreadedTextureDecompression, + SkipPipelineCacheSerialization, SkipVSConstantRegisterZero, SlowDownMonolithicPipelineCreationForTesting, SrgbBlendingBroken, + SupportFragmentShadingRateExtExtensions, Supports16BitInputOutput, Supports16BitPushConstant, Supports16BitStorageBuffer, @@ -299,10 +318,17 @@ enum class Feature SupportsAndroidNativeFenceSync, SupportsAngleRgbxInternalFormat, SupportsAppleClipDistance, + SupportsAstc3d, + SupportsAstcDecodeMode, + SupportsAstcDecodeModeRgb9e5, + SupportsAstcHdr3dTextures, SupportsAstcSliced3d, SupportsBindMemory2, + SupportsBindVertexBuffers2, SupportsBlendOperationAdvanced, SupportsBlendOperationAdvancedCoherent, + SupportsBufferDeviceAddress, + SupportsClipCullDistanceInGSAndTS, SupportsColorWriteEnable, SupportsComputeTranscodeEtcToBc, SupportsCustomBorderColor, @@ -316,6 +342,7 @@ enum class Feature SupportsDepthClipControl, SupportsDepthStencilIndependentResolveNone, SupportsDepthStencilResolve, + SupportsDeviceFault, SupportsDynamicRendering, SupportsDynamicRenderingLocalRead, SupportsExtendedDynamicState, @@ -323,7 +350,7 @@ enum class Feature SupportsExternalFenceCapabilities, SupportsExternalFenceFd, SupportsExternalFormatResolve, - SupportsExternalMemoryDmaBufAndModifiers, + SupportsExternalMemoryDmaBuf, SupportsExternalMemoryFd, SupportsExternalMemoryFuchsia, SupportsExternalMemoryHost, @@ -340,14 +367,17 @@ enum class Feature SupportsFullScreenExclusive, SupportsGeometryStreamsCapability, SupportsGetMemoryRequirements2, - SupportsGGPFrameToken, + SupportsGlobalPriority, + SupportsGlobalPriorityQuery, SupportsGraphicsPipelineLibrary, + SupportShaderPixelLocalStorageAngle, SupportsHostImageCopy, SupportsHostQueryReset, SupportsImage2dViewOf3d, SupportsImageCompressionControl, SupportsImageCompressionControlSwapchain, SupportsImageCubeArray, + SupportsImageDrmFormatModifier, SupportsImageFormatList, SupportsImagelessFramebuffer, SupportsIncrementalPresent, @@ -356,11 +386,12 @@ enum class Feature SupportsLockSurfaceExtension, SupportsLogicOpDynamicState, SupportsMaintenance5, + SupportsMaintenance9, SupportsMemoryBudget, - SupportsMixedReadWriteDepthStencilLayouts, SupportsMultiDrawIndirect, SupportsMultisampledRenderToSingleSampled, SupportsMultiview, + SupportsMultiviewMultisampleRenderToTexture, SupportsNonConstantLoopIndexing, SupportsPipelineCreationFeedback, SupportsPipelineProtectedAccess, @@ -368,6 +399,7 @@ enum class Feature SupportsPipelineStatisticsQuery, SupportsPortabilityEnumeration, SupportsPresentation, + SupportsPrimitiveFragmentShadingRate, SupportsPrimitivesGeneratedQuery, SupportsPrimitiveTopologyListRestart, SupportsProtectedMemory, @@ -383,6 +415,7 @@ enum class Feature SupportsRoundingModeRtzFp64, SupportsSampler2dViewOf3d, SupportsSamplerMirrorClampToEdge, + SupportsShaderAtomicInt64, SupportsShaderFloat16, SupportsShaderFloat64, SupportsShaderFramebufferFetch, @@ -391,6 +424,7 @@ enum class Feature SupportsShaderFramebufferFetchNonCoherent, SupportsShaderFramebufferFetchNonCoherentEXT, SupportsShaderInt8, + SupportsShaderIntegerDotProduct, SupportsShaderNonSemanticInfo, SupportsShaderStencilExport, SupportsSharedPresentableImageExtension, @@ -404,11 +438,14 @@ enum class Feature SupportsSurfaceProtectedCapabilitiesExtension, SupportsSurfaceProtectedSwapchains, SupportsSwapchainMaintenance1, + SupportsSwapchainMutableFormat, SupportsSynchronization2, SupportsTextureCompressionAstcHdr, + SupportsTileMemoryHeap, SupportsTimelineSemaphore, SupportsTimestampSurfaceAttribute, SupportsTransformFeedbackExtension, + SupportsUnifiedImageLayouts, SupportsUniformBufferStandardLayout, SupportsVertexInputDynamicState, SupportsYUVSamplerConversion, @@ -417,6 +454,7 @@ enum class Feature SyncAllVertexArraysToDefault, SyncDefaultVertexArraysToDefault, SyncMonolithicPipelinesToBlobCache, + SyncPipelineCacheToBlobCacheEveryFrame, UnbindFBOBeforeSwitchingContext, UncurrentEglSurfaceUponSurfaceDestroy, UnfoldShortCircuits, @@ -434,13 +472,16 @@ enum class Feature UseEmptyBlobsToEraseOldPipelineCacheFromBlobCache, UseFrontFaceDynamicState, UseIntermediateTextureForGenerateMipmap, + UseIr, UseMultipleDescriptorsForExternalFormats, UseNonZeroStencilWriteMaskStaticState, UsePrimitiveRestartEnableDynamicState, + UsePrimitiveTopologyDynamicState, UseRasterizerDiscardEnableDynamicState, UseResetCommandBufferBitForSecondaryPools, UseShadowBuffersWhenAppropriate, UsesNativeBuiltinClKernel, + UsesSecondComponentForStencilBorderColor, UseStencilOpDynamicState, UseStencilTestEnableDynamicState, UseSystemMemoryForConstantBuffers, @@ -452,7 +493,6 @@ enum class Feature VaryingsRequireMatchingPrecisionInSpirv, VerifyPipelineCacheInBlobCache, VertexIDDoesNotIncludeBaseVertex, - WaitIdleBeforeSwapchainRecreation, WarmUpPipelineCacheAtLink, WrapSwitchInIfTrue, WriteHelperSampleMask, diff --git a/util/capture/frame_capture_replay_autogen.cpp b/util/capture/frame_capture_replay_autogen.cpp index c0dcff29487..60bd0d4ad1e 100644 --- a/util/capture/frame_capture_replay_autogen.cpp +++ b/util/capture/frame_capture_replay_autogen.cpp @@ -132,7 +132,8 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu case angle::EntryPoint::GLBindUniformLocationCHROMIUM: glBindUniformLocationCHROMIUM( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLcharConstPointerVal); break; case angle::EntryPoint::GLBindVertexArray: @@ -574,9 +575,8 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[2].value.GLcharConstPointerPointerVal); break; case angle::EntryPoint::GLCreateShaderProgramvEXT: - glCreateShaderProgramvEXT( - captures[0].value.GLenumVal, captures[1].value.GLsizeiVal, - const_cast(captures[2].value.GLcharConstPointerPointerVal)); + glCreateShaderProgramvEXT(captures[0].value.GLenumVal, captures[1].value.GLsizeiVal, + captures[2].value.GLcharConstPointerPointerVal); break; case angle::EntryPoint::GLCullFace: glCullFace(captures[0].value.GLenumVal); @@ -931,11 +931,6 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu glEGLImageTargetTexture2DOES(captures[0].value.GLenumVal, gEGLImageMap2[captures[1].value.GLuintVal]); break; - case angle::EntryPoint::GLEGLImageTargetTextureStorageEXT: - glEGLImageTargetTextureStorageEXT(captures[0].value.GLuintVal, - gEGLImageMap2[captures[1].value.GLuintVal], - captures[2].value.GLintConstPointerVal); - break; case angle::EntryPoint::GLEnable: glEnable(captures[0].value.GLenumVal); break; @@ -1061,6 +1056,12 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[2].value.GLenumVal, gRenderbufferMap[captures[3].value.GLuintVal]); break; + case angle::EntryPoint::GLFramebufferShadingRateEXT: + glFramebufferShadingRateEXT(captures[0].value.GLenumVal, captures[1].value.GLenumVal, + captures[2].value.GLuintVal, captures[3].value.GLintVal, + captures[4].value.GLsizeiVal, captures[5].value.GLsizeiVal, + captures[6].value.GLsizeiVal); + break; case angle::EntryPoint::GLFramebufferTexture: glFramebufferTexture(captures[0].value.GLenumVal, captures[1].value.GLenumVal, gTextureMap[captures[2].value.GLuintVal], @@ -1100,6 +1101,13 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu gTextureMap[captures[2].value.GLuintVal], captures[3].value.GLintVal, captures[4].value.GLintVal); break; + case angle::EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR: + glFramebufferTextureMultisampleMultiviewOVR( + captures[0].value.GLenumVal, captures[1].value.GLenumVal, + gTextureMap[captures[2].value.GLuintVal], captures[3].value.GLintVal, + captures[4].value.GLsizeiVal, captures[5].value.GLintVal, + captures[6].value.GLsizeiVal); + break; case angle::EntryPoint::GLFramebufferTextureMultiviewOVR: glFramebufferTextureMultiviewOVR( captures[0].value.GLenumVal, captures[1].value.GLenumVal, @@ -1336,6 +1344,11 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu glGetFragDataLocation(gShaderProgramMap[captures[0].value.GLuintVal], captures[1].value.GLcharConstPointerVal); break; + case angle::EntryPoint::GLGetFragmentShadingRatesEXT: + glGetFragmentShadingRatesEXT(captures[0].value.GLsizeiVal, captures[1].value.GLsizeiVal, + captures[2].value.GLsizeiPointerVal, + captures[3].value.GLenumPointerVal); + break; case angle::EntryPoint::GLGetFramebufferAttachmentParameteriv: glGetFramebufferAttachmentParameteriv( captures[0].value.GLenumVal, captures[1].value.GLenumVal, @@ -1973,39 +1986,45 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu break; case angle::EntryPoint::GLGetUniformfv: glGetUniformfv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatPointerVal); break; case angle::EntryPoint::GLGetUniformfvRobustANGLE: - glGetUniformfvRobustANGLE( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLsizeiPointerVal, - captures[4].value.GLfloatPointerVal); + glGetUniformfvRobustANGLE(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, + captures[3].value.GLsizeiPointerVal, + captures[4].value.GLfloatPointerVal); break; case angle::EntryPoint::GLGetUniformiv: glGetUniformiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintPointerVal); break; case angle::EntryPoint::GLGetUniformivRobustANGLE: - glGetUniformivRobustANGLE( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLsizeiPointerVal, - captures[4].value.GLintPointerVal); + glGetUniformivRobustANGLE(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, + captures[3].value.GLsizeiPointerVal, + captures[4].value.GLintPointerVal); break; case angle::EntryPoint::GLGetUniformuiv: glGetUniformuiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintPointerVal); break; case angle::EntryPoint::GLGetUniformuivRobustANGLE: - glGetUniformuivRobustANGLE( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLsizeiPointerVal, - captures[4].value.GLuintPointerVal); + glGetUniformuivRobustANGLE(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, + captures[3].value.GLsizeiPointerVal, + captures[4].value.GLuintPointerVal); break; case angle::EntryPoint::GLGetUnsignedBytei_vEXT: glGetUnsignedBytei_vEXT(captures[0].value.GLenumVal, captures[1].value.GLuintVal, @@ -2066,62 +2085,73 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu break; case angle::EntryPoint::GLGetnUniformfv: glGetnUniformfv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatPointerVal); break; case angle::EntryPoint::GLGetnUniformfvEXT: glGetnUniformfvEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatPointerVal); break; case angle::EntryPoint::GLGetnUniformfvKHR: glGetnUniformfvKHR(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatPointerVal); break; case angle::EntryPoint::GLGetnUniformfvRobustANGLE: - glGetnUniformfvRobustANGLE( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLsizeiPointerVal, - captures[4].value.GLfloatPointerVal); + glGetnUniformfvRobustANGLE(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, + captures[3].value.GLsizeiPointerVal, + captures[4].value.GLfloatPointerVal); break; case angle::EntryPoint::GLGetnUniformiv: glGetnUniformiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintPointerVal); break; case angle::EntryPoint::GLGetnUniformivEXT: glGetnUniformivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintPointerVal); break; case angle::EntryPoint::GLGetnUniformivKHR: glGetnUniformivKHR(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintPointerVal); break; case angle::EntryPoint::GLGetnUniformivRobustANGLE: - glGetnUniformivRobustANGLE( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLsizeiPointerVal, - captures[4].value.GLintPointerVal); + glGetnUniformivRobustANGLE(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, + captures[3].value.GLsizeiPointerVal, + captures[4].value.GLintPointerVal); break; case angle::EntryPoint::GLGetnUniformuiv: glGetnUniformuiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintPointerVal); break; case angle::EntryPoint::GLGetnUniformuivKHR: glGetnUniformuivKHR(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintPointerVal); break; case angle::EntryPoint::GLGetnUniformuivRobustANGLE: glGetnUniformuivRobustANGLE( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLsizeiPointerVal, captures[4].value.GLuintPointerVal); break; @@ -2364,6 +2394,11 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[0].value.GLenumVal, captures[1].value.GLintConstPointerVal, captures[2].value.GLsizeiConstPointerVal, captures[3].value.GLsizeiVal); break; + case angle::EntryPoint::GLMultiDrawArraysEXT: + glMultiDrawArraysEXT( + captures[0].value.GLenumVal, captures[1].value.GLintConstPointerVal, + captures[2].value.GLsizeiConstPointerVal, captures[3].value.GLsizeiVal); + break; case angle::EntryPoint::GLMultiDrawArraysIndirectEXT: glMultiDrawArraysIndirectEXT( captures[0].value.GLenumVal, captures[1].value.voidConstPointerVal, @@ -2393,6 +2428,12 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[2].value.GLenumVal, captures[3].value.voidConstPointerPointerVal, captures[4].value.GLsizeiVal, captures[5].value.GLintConstPointerVal); break; + case angle::EntryPoint::GLMultiDrawElementsEXT: + glMultiDrawElementsEXT( + captures[0].value.GLenumVal, captures[1].value.GLsizeiConstPointerVal, + captures[2].value.GLenumVal, captures[3].value.voidConstPointerPointerVal, + captures[4].value.GLsizeiVal); + break; case angle::EntryPoint::GLMultiDrawElementsIndirectEXT: glMultiDrawElementsIndirectEXT(captures[0].value.GLenumVal, captures[1].value.GLenumVal, captures[2].value.voidConstPointerVal, @@ -2422,12 +2463,6 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[2].value.GLfixedVal, captures[3].value.GLfixedVal, captures[4].value.GLfixedVal); break; - case angle::EntryPoint::GLNamedBufferStorageExternalEXT: - glNamedBufferStorageExternalEXT( - captures[0].value.GLuintVal, captures[1].value.GLintptrVal, - captures[2].value.GLsizeiptrVal, captures[3].value.GLeglClientBufferEXTVal, - captures[4].value.GLbitfieldVal); - break; case angle::EntryPoint::GLNormal3f: glNormal3f(captures[0].value.GLfloatVal, captures[1].value.GLfloatVal, captures[2].value.GLfloatVal); @@ -2574,403 +2609,466 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu break; case angle::EntryPoint::GLProgramUniform1f: glProgramUniform1f(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform1fEXT: glProgramUniform1fEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform1fv: glProgramUniform1fv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform1fvEXT: glProgramUniform1fvEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform1i: glProgramUniform1i(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform1iEXT: glProgramUniform1iEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform1iv: glProgramUniform1iv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform1ivEXT: glProgramUniform1ivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform1ui: glProgramUniform1ui(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform1uiEXT: glProgramUniform1uiEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform1uiv: glProgramUniform1uiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform1uivEXT: glProgramUniform1uivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform2f: glProgramUniform2f(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal, captures[3].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform2fEXT: glProgramUniform2fEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal, captures[3].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform2fv: glProgramUniform2fv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform2fvEXT: glProgramUniform2fvEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform2i: glProgramUniform2i(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal, captures[3].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform2iEXT: glProgramUniform2iEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal, captures[3].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform2iv: glProgramUniform2iv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform2ivEXT: glProgramUniform2ivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform2ui: glProgramUniform2ui(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal, captures[3].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform2uiEXT: glProgramUniform2uiEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal, captures[3].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform2uiv: glProgramUniform2uiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform2uivEXT: glProgramUniform2uivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform3f: glProgramUniform3f(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal, captures[3].value.GLfloatVal, captures[4].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform3fEXT: glProgramUniform3fEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal, captures[3].value.GLfloatVal, captures[4].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform3fv: glProgramUniform3fv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform3fvEXT: glProgramUniform3fvEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform3i: glProgramUniform3i(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal, captures[3].value.GLintVal, captures[4].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform3iEXT: glProgramUniform3iEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal, captures[3].value.GLintVal, captures[4].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform3iv: glProgramUniform3iv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform3ivEXT: glProgramUniform3ivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform3ui: glProgramUniform3ui(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal, captures[3].value.GLuintVal, captures[4].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform3uiEXT: glProgramUniform3uiEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal, captures[3].value.GLuintVal, captures[4].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform3uiv: glProgramUniform3uiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform3uivEXT: glProgramUniform3uivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform4f: glProgramUniform4f(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal, captures[3].value.GLfloatVal, captures[4].value.GLfloatVal, captures[5].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform4fEXT: glProgramUniform4fEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLfloatVal, captures[3].value.GLfloatVal, captures[4].value.GLfloatVal, captures[5].value.GLfloatVal); break; case angle::EntryPoint::GLProgramUniform4fv: glProgramUniform4fv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform4fvEXT: glProgramUniform4fvEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniform4i: glProgramUniform4i(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal, captures[3].value.GLintVal, captures[4].value.GLintVal, captures[5].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform4iEXT: glProgramUniform4iEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLintVal, captures[3].value.GLintVal, captures[4].value.GLintVal, captures[5].value.GLintVal); break; case angle::EntryPoint::GLProgramUniform4iv: glProgramUniform4iv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform4ivEXT: glProgramUniform4ivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform4ui: glProgramUniform4ui(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal, captures[3].value.GLuintVal, captures[4].value.GLuintVal, captures[5].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform4uiEXT: glProgramUniform4uiEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLuintVal, captures[3].value.GLuintVal, captures[4].value.GLuintVal, captures[5].value.GLuintVal); break; case angle::EntryPoint::GLProgramUniform4uiv: glProgramUniform4uiv(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniform4uivEXT: glProgramUniform4uivEXT(gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix2fv: - glProgramUniformMatrix2fv( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, - captures[4].value.GLfloatConstPointerVal); + glProgramUniformMatrix2fv(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, + captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix2fvEXT: glProgramUniformMatrix2fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix2x3fv: glProgramUniformMatrix2x3fv( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix2x3fvEXT: glProgramUniformMatrix2x3fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix2x4fv: glProgramUniformMatrix2x4fv( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix2x4fvEXT: glProgramUniformMatrix2x4fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix3fv: - glProgramUniformMatrix3fv( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, - captures[4].value.GLfloatConstPointerVal); + glProgramUniformMatrix3fv(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, + captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix3fvEXT: glProgramUniformMatrix3fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix3x2fv: glProgramUniformMatrix3x2fv( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix3x2fvEXT: glProgramUniformMatrix3x2fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix3x4fv: glProgramUniformMatrix3x4fv( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix3x4fvEXT: glProgramUniformMatrix3x4fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix4fv: - glProgramUniformMatrix4fv( - gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], - captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, - captures[4].value.GLfloatConstPointerVal); + glProgramUniformMatrix4fv(gShaderProgramMap[captures[0].value.GLuintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], + captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, + captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix4fvEXT: glProgramUniformMatrix4fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix4x2fv: glProgramUniformMatrix4x2fv( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix4x2fvEXT: glProgramUniformMatrix4x2fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix4x3fv: glProgramUniformMatrix4x3fv( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLProgramUniformMatrix4x3fvEXT: glProgramUniformMatrix4x3fvEXT( gShaderProgramMap[captures[0].value.GLuintVal], - gUniformLocations[gCurrentProgram][captures[1].value.GLintVal], + gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[1].value.GLintVal], captures[2].value.GLsizeiVal, captures[3].value.GLbooleanVal, captures[4].value.GLfloatConstPointerVal); break; @@ -3213,6 +3311,12 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[2].value.GLcharConstPointerPointerVal, captures[3].value.GLintConstPointerVal); break; + case angle::EntryPoint::GLShadingRateCombinerOpsEXT: + glShadingRateCombinerOpsEXT(captures[0].value.GLenumVal, captures[1].value.GLenumVal); + break; + case angle::EntryPoint::GLShadingRateEXT: + glShadingRateEXT(captures[0].value.GLenumVal); + break; case angle::EntryPoint::GLShadingRateQCOM: glShadingRateQCOM(captures[0].value.GLenumVal); break; @@ -3442,10 +3546,6 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu glTexParameterxv(captures[0].value.GLenumVal, captures[1].value.GLenumVal, captures[2].value.GLfixedConstPointerVal); break; - case angle::EntryPoint::GLTexStorage1DEXT: - glTexStorage1DEXT(captures[0].value.GLenumVal, captures[1].value.GLsizeiVal, - captures[2].value.GLenumVal, captures[3].value.GLsizeiVal); - break; case angle::EntryPoint::GLTexStorage2D: glTexStorage2D(captures[0].value.GLenumVal, captures[1].value.GLsizeiVal, captures[2].value.GLenumVal, captures[3].value.GLsizeiVal, @@ -3626,105 +3726,129 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[2].value.GLfixedVal); break; case angle::EntryPoint::GLUniform1f: - glUniform1f(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform1f(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLfloatVal); break; case angle::EntryPoint::GLUniform1fv: - glUniform1fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform1fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniform1i: - glUniform1i(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform1i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLintVal); break; case angle::EntryPoint::GLUniform1iv: - glUniform1iv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform1iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLintConstPointerVal); break; case angle::EntryPoint::GLUniform1ui: - glUniform1ui(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform1ui(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLuintVal); break; case angle::EntryPoint::GLUniform1uiv: - glUniform1uiv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform1uiv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLUniform2f: - glUniform2f(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform2f(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLfloatVal, captures[2].value.GLfloatVal); break; case angle::EntryPoint::GLUniform2fv: - glUniform2fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform2fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniform2i: - glUniform2i(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform2i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLintVal, captures[2].value.GLintVal); break; case angle::EntryPoint::GLUniform2iv: - glUniform2iv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform2iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLintConstPointerVal); break; case angle::EntryPoint::GLUniform2ui: - glUniform2ui(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform2ui(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLuintVal, captures[2].value.GLuintVal); break; case angle::EntryPoint::GLUniform2uiv: - glUniform2uiv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform2uiv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLUniform3f: - glUniform3f(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform3f(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLfloatVal, captures[2].value.GLfloatVal, captures[3].value.GLfloatVal); break; case angle::EntryPoint::GLUniform3fv: - glUniform3fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform3fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniform3i: - glUniform3i(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform3i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLintVal, captures[2].value.GLintVal, captures[3].value.GLintVal); break; case angle::EntryPoint::GLUniform3iv: - glUniform3iv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform3iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLintConstPointerVal); break; case angle::EntryPoint::GLUniform3ui: - glUniform3ui(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform3ui(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLuintVal, captures[2].value.GLuintVal, captures[3].value.GLuintVal); break; case angle::EntryPoint::GLUniform3uiv: - glUniform3uiv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform3uiv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLUniform4f: - glUniform4f(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform4f(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLfloatVal, captures[2].value.GLfloatVal, captures[3].value.GLfloatVal, captures[4].value.GLfloatVal); break; case angle::EntryPoint::GLUniform4fv: - glUniform4fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform4fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniform4i: - glUniform4i(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform4i(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLintVal, captures[2].value.GLintVal, captures[3].value.GLintVal, captures[4].value.GLintVal); break; case angle::EntryPoint::GLUniform4iv: - glUniform4iv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform4iv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLintConstPointerVal); break; case angle::EntryPoint::GLUniform4ui: - glUniform4ui(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform4ui(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLuintVal, captures[2].value.GLuintVal, captures[3].value.GLuintVal, captures[4].value.GLuintVal); break; case angle::EntryPoint::GLUniform4uiv: - glUniform4uiv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniform4uiv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLuintConstPointerVal); break; case angle::EntryPoint::GLUniformBlockBinding: @@ -3732,47 +3856,56 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu captures[1].value.GLuintVal, captures[2].value.GLuintVal); break; case angle::EntryPoint::GLUniformMatrix2fv: - glUniformMatrix2fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix2fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix2x3fv: - glUniformMatrix2x3fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix2x3fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix2x4fv: - glUniformMatrix2x4fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix2x4fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix3fv: - glUniformMatrix3fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix3fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix3x2fv: - glUniformMatrix3x2fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix3x2fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix3x4fv: - glUniformMatrix3x4fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix3x4fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix4fv: - glUniformMatrix4fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix4fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix4x2fv: - glUniformMatrix4x2fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix4x2fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; case angle::EntryPoint::GLUniformMatrix4x3fv: - glUniformMatrix4x3fv(gUniformLocations[gCurrentProgram][captures[0].value.GLintVal], + glUniformMatrix4x3fv(gUniformLocations[gCurrentProgramPerContext[gCurrentContext]] + [captures[0].value.GLintVal], captures[1].value.GLsizeiVal, captures[2].value.GLbooleanVal, captures[3].value.GLfloatConstPointerVal); break; diff --git a/util/capture/frame_capture_test_utils.cpp b/util/capture/frame_capture_test_utils.cpp index 13dc463dc68..6736d8ec4f4 100644 --- a/util/capture/frame_capture_test_utils.cpp +++ b/util/capture/frame_capture_test_utils.cpp @@ -7,6 +7,10 @@ // Helper functions for capture and replay of traces. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "frame_capture_test_utils.h" #include "common/frame_capture_utils.h" @@ -245,6 +249,68 @@ bool LoadTraceInfoFromJSON(const std::string &traceName, } } + if (doc.HasMember("BinaryMetadata")) + { + const rapidjson::Document::Object &binaryData = doc["BinaryMetadata"].GetObj(); + if (binaryData.HasMember("Version")) + { + traceInfoOut->binaryVersion = binaryData["Version"].GetInt(); + } + else + { + traceInfoOut->binaryVersion = 0; + } + + if (binaryData.HasMember("BlockCount")) + { + traceInfoOut->binaryBlockCount = binaryData["BlockCount"].GetInt(); + } + else + { + traceInfoOut->binaryBlockCount = 0; + } + + // The following three entries must be handled as strings as possible values may + // overflow internal rapidjson thresholds + if (binaryData.HasMember("BlockSize")) + { + std::string sizeString = std::string(binaryData["BlockSize"].GetString()); + traceInfoOut->binaryBlockSize = std::stoull(sizeString); + } + else + { + traceInfoOut->binaryBlockSize = 0; + } + + if (binaryData.HasMember("ResidentSize")) + { + std::string sizeString = std::string(binaryData["ResidentSize"].GetString()); + traceInfoOut->binaryResidentSize = std::stoull(sizeString); + } + else + { + traceInfoOut->binaryResidentSize = kDefaultBinaryDataSize; + } + + if (binaryData.HasMember("IndexOffset")) + { + std::string offsetString = std::string(binaryData["IndexOffset"].GetString()); + traceInfoOut->binaryIndexOffset = std::stoull(offsetString); + } + else + { + traceInfoOut->binaryIndexOffset = 0; + } + } + else + { + traceInfoOut->binaryVersion = 0; + traceInfoOut->binaryBlockCount = 0; + traceInfoOut->binaryBlockSize = 0; + traceInfoOut->binaryResidentSize = 0; + traceInfoOut->binaryIndexOffset = 0; + } + const rapidjson::Document::Array &traceFiles = doc["TraceFiles"].GetArray(); for (const rapidjson::Value &value : traceFiles) { @@ -291,6 +357,7 @@ uint8_t *TraceLibrary::LoadBinaryData(const char *fileName) { std::ostringstream pathBuffer; pathBuffer << mBinaryDataDir << "/" << fileName; + FILE *fp = fopen(pathBuffer.str().c_str(), "rb"); if (fp == 0) { @@ -300,6 +367,7 @@ uint8_t *TraceLibrary::LoadBinaryData(const char *fileName) fseek(fp, 0, SEEK_END); long size = ftell(fp); fseek(fp, 0, SEEK_SET); + if (mTraceInfo.isBinaryDataCompressed) { if (!strstr(fileName, ".gz")) @@ -348,4 +416,19 @@ uint8_t *TraceLibrary::LoadBinaryData(const char *fileName) return mBinaryData.data(); } +FrameCaptureBinaryData *TraceLibrary::ConfigureBinaryDataLoader(const char *fileName) +{ + std::ostringstream pathBuffer; + pathBuffer << mBinaryDataDir << "/" << fileName; + + FrameCaptureBinaryData *binaryData = new FrameCaptureBinaryData; + + binaryData->configureBinaryDataLoader( + mTraceInfo.isBinaryDataCompressed, mTraceInfo.binaryBlockCount, + static_cast(mTraceInfo.binaryBlockSize), + static_cast(mTraceInfo.binaryResidentSize), + static_cast(mTraceInfo.binaryIndexOffset), pathBuffer.str()); + + return binaryData; +} } // namespace angle diff --git a/util/capture/frame_capture_test_utils.h b/util/capture/frame_capture_test_utils.h index 053c709eb14..43a6aac20a8 100644 --- a/util/capture/frame_capture_test_utils.h +++ b/util/capture/frame_capture_test_utils.h @@ -10,6 +10,10 @@ #ifndef UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_ #define UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include #include #include @@ -19,6 +23,7 @@ #include "common/angleutils.h" #include "common/debug.h" +#include "common/frame_capture_binary_data.h" #include "common/frame_capture_utils.h" #include "common/system_utils.h" #include "trace_interface.h" @@ -110,6 +115,7 @@ class TraceLibrary : angle::NonCopyable, angle::TraceCallbacks return typedFunc(args...); } + FrameCaptureBinaryData *ConfigureBinaryDataLoader(const char *fileName) override; uint8_t *LoadBinaryData(const char *fileName) override; std::unique_ptr mTraceLibrary; diff --git a/util/capture/trace_egl_loader_autogen.cpp b/util/capture/trace_egl_loader_autogen.cpp index c8e212fc545..4aa268946ff 100644 --- a/util/capture/trace_egl_loader_autogen.cpp +++ b/util/capture/trace_egl_loader_autogen.cpp @@ -92,8 +92,6 @@ ANGLE_TRACE_LOADER_EXPORT PFNEGLQUERYSURFACEPOINTERANGLEPROC t_eglQuerySurfacePo ANGLE_TRACE_LOADER_EXPORT PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC t_eglCreateStreamProducerD3DTextureANGLE; ANGLE_TRACE_LOADER_EXPORT PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC t_eglStreamPostD3DTextureANGLE; -ANGLE_TRACE_LOADER_EXPORT PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC - t_eglSwapBuffersWithFrameTokenANGLE; ANGLE_TRACE_LOADER_EXPORT PFNEGLGETMSCRATEANGLEPROC t_eglGetMscRateANGLE; ANGLE_TRACE_LOADER_EXPORT PFNEGLEXPORTVKIMAGEANGLEPROC t_eglExportVkImageANGLE; ANGLE_TRACE_LOADER_EXPORT PFNEGLWAITUNTILWORKSCHEDULEDANGLEPROC t_eglWaitUntilWorkScheduledANGLE; @@ -265,9 +263,6 @@ void LoadTraceEGL(LoadProc loadProc) loadProc("eglCreateStreamProducerD3DTextureANGLE")); t_eglStreamPostD3DTextureANGLE = reinterpret_cast( loadProc("eglStreamPostD3DTextureANGLE")); - t_eglSwapBuffersWithFrameTokenANGLE = - reinterpret_cast( - loadProc("eglSwapBuffersWithFrameTokenANGLE")); t_eglGetMscRateANGLE = reinterpret_cast(loadProc("eglGetMscRateANGLE")); t_eglExportVkImageANGLE = diff --git a/util/capture/trace_egl_loader_autogen.h b/util/capture/trace_egl_loader_autogen.h index 0f517bb1523..0a01dc313b7 100644 --- a/util/capture/trace_egl_loader_autogen.h +++ b/util/capture/trace_egl_loader_autogen.h @@ -92,7 +92,6 @@ #define eglQuerySurfacePointerANGLE t_eglQuerySurfacePointerANGLE #define eglCreateStreamProducerD3DTextureANGLE t_eglCreateStreamProducerD3DTextureANGLE #define eglStreamPostD3DTextureANGLE t_eglStreamPostD3DTextureANGLE -#define eglSwapBuffersWithFrameTokenANGLE t_eglSwapBuffersWithFrameTokenANGLE #define eglGetMscRateANGLE t_eglGetMscRateANGLE #define eglExportVkImageANGLE t_eglExportVkImageANGLE #define eglWaitUntilWorkScheduledANGLE t_eglWaitUntilWorkScheduledANGLE @@ -225,8 +224,6 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNEGLQUERYSURFACEPOINTERANGLEPROC t_eglQuerySu ANGLE_TRACE_LOADER_EXPORT extern PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC t_eglCreateStreamProducerD3DTextureANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC t_eglStreamPostD3DTextureANGLE; -ANGLE_TRACE_LOADER_EXPORT extern PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC - t_eglSwapBuffersWithFrameTokenANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNEGLGETMSCRATEANGLEPROC t_eglGetMscRateANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNEGLEXPORTVKIMAGEANGLEPROC t_eglExportVkImageANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNEGLWAITUNTILWORKSCHEDULEDANGLEPROC @@ -278,7 +275,7 @@ typedef GenericProc(KHRONOS_APIENTRY *LoadProc)(const char *); ANGLE_TRACE_LOADER_EXPORT void LoadTraceEGL(LoadProc loadProc); #if defined(__cplusplus) -} // extern "C" +} // extern "C" #endif // defined(__cplusplus) #endif // ANGLE_TRACES_UTIL_EGL_LOADER_AUTOGEN_H_ diff --git a/util/capture/trace_fixture.cpp b/util/capture/trace_fixture.cpp index e58845c387a..c1f748eac56 100644 --- a/util/capture/trace_fixture.cpp +++ b/util/capture/trace_fixture.cpp @@ -7,10 +7,15 @@ // Common code for the ANGLE trace replays. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "trace_fixture.h" #include "angle_trace_gl.h" +#include #include namespace @@ -32,8 +37,9 @@ void UpdateResourceMapPerContext(GLuint **resourceArray, resourceArray[contextId][id] = returnedID; } -uint32_t gMaxContexts = 0; +uint32_t gMaxContexts = 1; angle::TraceCallbacks *gTraceCallbacks = nullptr; +std::vector *gRequestedExtensions = nullptr; EGLClientBuffer GetClientBuffer(EGLenum target, uintptr_t key) { @@ -68,10 +74,37 @@ ValidateSerializedStateCallback gValidateSerializedStateCallback; std::unordered_map> gInternalUniformLocationsMap; constexpr size_t kMaxClientArrays = 16; + +std::vector *LoadRequestedExtensions() +{ + // Read in requested extensions if the file exists + constexpr const char *REQUESTED_EXTENSIONS_FILENAME = "angle_trace_requested_extensions"; + + std::filesystem::path tempDir = std::filesystem::temp_directory_path(); + std::filesystem::path extFilePath = tempDir / REQUESTED_EXTENSIONS_FILENAME; + std::ifstream extFile(extFilePath); + std::vector *requestedExtensions = nullptr; + + if (extFile.is_open()) + { + requestedExtensions = new std::vector(); + std::string ext; + while (std::getline(extFile, ext)) + { + requestedExtensions->push_back(ext); + } + extFile.close(); + // Delete the file to prevent unexpected results in future runs + std::filesystem::remove(extFilePath); + } + return requestedExtensions; +} } // namespace GLint **gUniformLocations; GLuint gCurrentProgram = 0; +GLuint gCurrentContext = 0; +GLuint *gCurrentProgramPerContext; // TODO(jmadill): Hide from the traces. http://anglebug.com/42266223 BlockIndexesMap gUniformBlockIndexes; @@ -112,9 +145,22 @@ void UniformBlockBinding(GLuint program, GLuint uniformblockIndex, GLuint bindin void UpdateCurrentProgram(GLuint program) { gCurrentProgram = program; + // gCurrentContext will be zero for legacy traces + gCurrentProgramPerContext[0] = program; +} + +void UpdateCurrentContext(GLuint context) +{ + gCurrentContext = context; +} + +void UpdateCurrentProgramPerContext(GLuint program) +{ + gCurrentProgramPerContext[gCurrentContext] = program; } uint8_t *gBinaryData; +angle::FrameCaptureBinaryData *gFrameCaptureBinaryData; uint8_t *gReadBuffer; uint8_t *gClientArrays[kMaxClientArrays]; GLuint *gResourceIDBuffer; @@ -166,6 +212,39 @@ GLuint *AllocateZeroedUints(size_t count) return AllocateZeroedValues(count); } +void InitializeReplay5(const char *binaryDataFileName, + size_t maxClientArraySize, + size_t readBufferSize, + size_t resourceIDBufferSize, + GLuint contextId, + uint32_t maxBuffer, + uint32_t maxContext, + uint32_t maxFenceNV, + uint32_t maxFramebuffer, + uint32_t maxImage, + uint32_t maxMemoryObject, + uint32_t maxProgramPipeline, + uint32_t maxQuery, + uint32_t maxRenderbuffer, + uint32_t maxSampler, + uint32_t maxSemaphore, + uint32_t maxShaderProgram, + uint32_t maxSurface, + uint32_t maxSync, + uint32_t maxTexture, + uint32_t maxTransformFeedback, + uint32_t maxVertexArray, + GLuint maxEGLSyncID) +{ + gFrameCaptureBinaryData = gTraceCallbacks->ConfigureBinaryDataLoader(binaryDataFileName); + + InitializeReplay4(binaryDataFileName, maxClientArraySize, readBufferSize, resourceIDBufferSize, + contextId, maxBuffer, maxContext, maxFenceNV, maxFramebuffer, maxImage, + maxMemoryObject, maxProgramPipeline, maxQuery, maxRenderbuffer, maxSampler, + maxSemaphore, maxShaderProgram, maxSurface, maxSync, maxTexture, + maxTransformFeedback, maxVertexArray, maxEGLSyncID); +} + void InitializeReplay4(const char *binaryDataFileName, size_t maxClientArraySize, size_t readBufferSize, @@ -197,14 +276,6 @@ void InitializeReplay4(const char *binaryDataFileName, maxTransformFeedback, maxVertexArray); gEGLSyncMap = AllocateZeroedValues(maxEGLSyncID); gEGLDisplay = eglGetCurrentDisplay(); - - gMaxContexts = maxContext + 1; - gFramebufferMapPerContext = new GLuint *[gMaxContexts]; - memset(gFramebufferMapPerContext, 0, sizeof(GLuint *) * (gMaxContexts)); - for (uint8_t i = 0; i < gMaxContexts; i++) - { - gFramebufferMapPerContext[i] = AllocateZeroedValues(maxFramebuffer); - } } void InitializeReplay3(const char *binaryDataFileName, @@ -261,6 +332,7 @@ void InitializeReplay2(const char *binaryDataFileName, uint32_t maxTransformFeedback, uint32_t maxVertexArray) { + gMaxContexts = maxContext + 1; InitializeReplay(binaryDataFileName, maxClientArraySize, readBufferSize, maxBuffer, maxFenceNV, maxFramebuffer, maxMemoryObject, maxProgramPipeline, maxQuery, maxRenderbuffer, maxSampler, maxSemaphore, maxShaderProgram, maxTexture, maxTransformFeedback, @@ -293,7 +365,10 @@ void InitializeReplay(const char *binaryDataFileName, uint32_t maxTransformFeedback, uint32_t maxVertexArray) { - gBinaryData = gTraceCallbacks->LoadBinaryData(binaryDataFileName); + if (!gFrameCaptureBinaryData) + { + gBinaryData = gTraceCallbacks->LoadBinaryData(binaryDataFileName); + } for (uint8_t *&clientArray : gClientArrays) { @@ -320,6 +395,17 @@ void InitializeReplay(const char *binaryDataFileName, memset(gUniformLocations, 0, sizeof(GLint *) * (maxShaderProgram + 1)); gContextMap[0] = EGL_NO_CONTEXT; + + gCurrentProgramPerContext = new GLuint[gMaxContexts]; + gFramebufferMapPerContext = new GLuint *[gMaxContexts]; + memset(gFramebufferMapPerContext, 0, sizeof(GLuint *) * (gMaxContexts)); + for (uint8_t i = 0; i < gMaxContexts; i++) + { + gFramebufferMapPerContext[i] = AllocateZeroedValues(maxFramebuffer); + } + + // Pull in requested extension list from file created by ANGLEPerfTest + gRequestedExtensions = LoadRequestedExtensions(); } void FinishReplay() @@ -349,11 +435,21 @@ void FinishReplay() delete[] gTransformFeedbackMap; delete[] gVertexArrayMap; + delete gRequestedExtensions; + for (uint8_t i = 0; i < gMaxContexts; i++) { delete[] gFramebufferMapPerContext[i]; } delete[] gFramebufferMapPerContext; + delete[] gCurrentProgramPerContext; + + if (gFrameCaptureBinaryData) + { + gFrameCaptureBinaryData->closeBinaryDataLoader(); + delete gFrameCaptureBinaryData; + gFrameCaptureBinaryData = nullptr; + } } void SetValidateSerializedStateCallback(ValidateSerializedStateCallback callback) @@ -698,11 +794,34 @@ void CreateNativeClientBufferANDROID(const EGLint *attrib_list, uintptr_t client gClientBufferMap[clientBuffer] = eglCreateNativeClientBufferANDROID(attrib_list); } +// The test harness can set specific extensions, but only for the main context +// so enable the same set of extensions for each side-context. +void EnableSideContextExtensions(GLuint contextID) +{ + if (gRequestedExtensions) + { + // Change to newly-created side-context + eglMakeCurrent(NULL, NULL, NULL, gContextMap2[contextID]); + for (auto &ext : *gRequestedExtensions) + { + glRequestExtensionANGLE(ext.c_str()); + } + // Switch back to main context + eglMakeCurrent(NULL, NULL, NULL, gContextMap2[gShareContextId]); + } +} + void CreateContext(GLuint contextID) { EGLContext shareContext = gContextMap2[gShareContextId]; EGLContext context = eglCreateContext(nullptr, nullptr, shareContext, nullptr); gContextMap2[contextID] = context; + + // Extensions set using --request-extensions must be propagated to side-contexts + if (gRequestedExtensions) + { + EnableSideContextExtensions(contextID); + } } void SetCurrentContextID(GLuint id) @@ -710,6 +829,16 @@ void SetCurrentContextID(GLuint id) gContextMap2[id] = eglGetCurrentContext(); } +const uint8_t *GetBinaryData(const size_t offset) +{ + return gFrameCaptureBinaryData->getData(offset); +} + +void InitializeBinaryDataLoader() +{ + gFrameCaptureBinaryData->initializeBinaryDataLoader(); +} + ANGLE_REPLAY_EXPORT PFNEGLCREATEIMAGEPROC r_eglCreateImage; ANGLE_REPLAY_EXPORT PFNEGLCREATEIMAGEKHRPROC r_eglCreateImageKHR; ANGLE_REPLAY_EXPORT PFNEGLDESTROYIMAGEPROC r_eglDestroyImage; diff --git a/util/capture/trace_fixture.h b/util/capture/trace_fixture.h index e042c750c11..1744d669b72 100644 --- a/util/capture/trace_fixture.h +++ b/util/capture/trace_fixture.h @@ -17,6 +17,7 @@ #include #include "angle_gl.h" +#include "common/frame_capture_binary_data.h" #include "trace_interface.h" #include "traces_export.h" @@ -71,13 +72,17 @@ ANGLE_REPLAY_EXPORT void SetupEntryPoints(angle::TraceCallbacks *traceCallbacks, // Maps from to run-time location. extern GLint **gUniformLocations; +extern GLuint gCurrentContext; extern GLuint gCurrentProgram; +extern GLuint *gCurrentProgramPerContext; void UpdateUniformLocation(GLuint program, const char *name, GLint location, GLint count); void DeleteUniformLocations(GLuint program); void UpdateUniformBlockIndex(GLuint program, const char *name, GLuint index); void UniformBlockBinding(GLuint program, GLuint uniformblockIndex, GLuint binding); void UpdateCurrentProgram(GLuint program); +void UpdateCurrentContext(GLuint context); +void UpdateCurrentProgramPerContext(GLuint program); // Global state @@ -110,6 +115,30 @@ extern EGLSync *gEGLSyncMap; extern EGLDisplay gEGLDisplay; extern angle::ReplayResourceMode gReplayResourceMode; +void InitializeReplay5(const char *binaryDataFileName, + size_t maxClientArraySize, + size_t readBufferSize, + size_t resourceIDBufferSize, + GLuint contextId, + uint32_t maxBuffer, + uint32_t maxContext, + uint32_t maxFenceNV, + uint32_t maxFramebuffer, + uint32_t maxImage, + uint32_t maxMemoryObject, + uint32_t maxProgramPipeline, + uint32_t maxQuery, + uint32_t maxRenderbuffer, + uint32_t maxSampler, + uint32_t maxSemaphore, + uint32_t maxShaderProgram, + uint32_t maxSurface, + uint32_t maxSync, + uint32_t maxTexture, + uint32_t maxTransformFeedback, + uint32_t maxVertexArray, + uint32_t maxEGLSyncID); + void InitializeReplay4(const char *binaryDataFileName, size_t maxClientArraySize, size_t readBufferSize, @@ -195,6 +224,9 @@ void InitializeReplay(const char *binaryDataFileName, uint32_t maxTransformFeedback, uint32_t maxVertexArray); +const uint8_t *GetBinaryData(const size_t offset); +void InitializeBinaryDataLoader(); + void UpdateClientArrayPointer(int arrayIndex, const void *data, uint64_t size); void UpdateClientBufferData(GLuint bufferID, const void *source, GLsizei size); void UpdateClientBufferDataWithOffset(GLuint bufferID, diff --git a/util/capture/trace_fixture_cl.cpp b/util/capture/trace_fixture_cl.cpp index 9f507a9c61f..99a743d1e13 100644 --- a/util/capture/trace_fixture_cl.cpp +++ b/util/capture/trace_fixture_cl.cpp @@ -7,6 +7,10 @@ // OpenCL-specific code for the ANGLE trace replays. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "trace_fixture_cl.h" #include @@ -45,6 +49,7 @@ angle::ReplayResourceMode gReplayResourceMode = angle::ReplayResourceMode::Activ uint8_t *gBinaryData; uint8_t *gReadBuffer; +angle::FrameCaptureBinaryData *gFrameCaptureBinaryData; std::string gBinaryDataDir = "."; template @@ -60,6 +65,23 @@ GLuint *AllocateZeroedUints(size_t count) return AllocateZeroedValues(count); } +void InitializeReplayCL2(const char *binaryDataFileName, + size_t maxClientArraySize, + size_t readBufferSize, + uint32_t maxCLPlatform, + uint32_t maxCLDevices, + uint32_t maxCLContexts, + uint32_t maxCLCommandQueues, + uint32_t maxCLMem, + uint32_t maxCLEvents, + uint32_t maxCLPrograms, + uint32_t maxCLKernels, + uint32_t maxCLSamplers, + uint32_t maxCLVoidPointer) +{ + gFrameCaptureBinaryData = gTraceCallbacks->ConfigureBinaryDataLoader(binaryDataFileName); +} + void InitializeReplayCL(const char *binaryDataFileName, size_t maxClientArraySize, size_t readBufferSize, @@ -74,7 +96,11 @@ void InitializeReplayCL(const char *binaryDataFileName, uint32_t maxCLSamplers, uint32_t maxCLVoidPointer) { - gBinaryData = gTraceCallbacks->LoadBinaryData(binaryDataFileName); + if (!gFrameCaptureBinaryData) + { + gBinaryData = gTraceCallbacks->LoadBinaryData(binaryDataFileName); + } + gReadBuffer = new uint8_t[readBufferSize]; clPlatformsMap = AllocateZeroedValues(maxCLPlatform); @@ -103,6 +129,13 @@ void FinishReplay() delete[] clKernelsMap; delete[] clSamplerMap; delete[] clVoidMap; + + if (gFrameCaptureBinaryData) + { + gFrameCaptureBinaryData->closeBinaryDataLoader(); + delete gFrameCaptureBinaryData; + gFrameCaptureBinaryData = nullptr; + } } angle::TraceInfo gTraceInfo; @@ -155,3 +188,13 @@ void UpdateCLContextPropertiesWithPlatform(size_t propSize, std::memcpy(&temporaryContextProps.data()[platformIdxInProps], &clPlatformsMap[platformIdxInMap], sizeof(cl_platform_id)); } + +const uint8_t *GetBinaryData(const size_t offset) +{ + return gFrameCaptureBinaryData->getData(offset); +} + +void InitializeBinaryDataLoader() +{ + gFrameCaptureBinaryData->initializeBinaryDataLoader(); +} diff --git a/util/capture/trace_fixture_cl.h b/util/capture/trace_fixture_cl.h index 935596673d5..9e6c05d67de 100644 --- a/util/capture/trace_fixture_cl.h +++ b/util/capture/trace_fixture_cl.h @@ -72,6 +72,20 @@ extern std::vector temporaryVoidPtrList; extern std::vector temporaryUnsignedCharPointerList; extern void *temporaryVoidPtr; +void InitializeReplayCL2(const char *binaryDataFileName, + size_t maxClientArraySize, + size_t readBufferSize, + uint32_t maxCLPlatform, + uint32_t maxCLDevices, + uint32_t maxCLContexts, + uint32_t maxCLCommandQueues, + uint32_t maxCLMem, + uint32_t maxCLEvents, + uint32_t maxCLPrograms, + uint32_t maxCLKernels, + uint32_t maxCLSamplers, + uint32_t maxCLVoidPointer); + void InitializeReplayCL(const char *binaryDataFileName, size_t maxClientArraySize, size_t readBufferSize, @@ -86,6 +100,9 @@ void InitializeReplayCL(const char *binaryDataFileName, uint32_t maxCLSamplers, uint32_t maxCLVoidPointer); +const uint8_t *GetBinaryData(const size_t offset); +void InitializeBinaryDataLoader(); + void UpdateCLContextPropertiesNoPlatform(size_t propSize, const cl_context_properties *propData); void UpdateCLContextPropertiesWithPlatform(size_t propSize, const cl_context_properties *propData, diff --git a/util/capture/trace_gles_loader_autogen.cpp b/util/capture/trace_gles_loader_autogen.cpp index 3d7ab38014a..87d90c0da93 100644 --- a/util/capture/trace_gles_loader_autogen.cpp +++ b/util/capture/trace_gles_loader_autogen.cpp @@ -531,6 +531,10 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLEPRO t_glGetFramebufferAttachmentParameterivRobustANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLEPROC t_glGetFramebufferParameterivRobustANGLE; +ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC + t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; +ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC + t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLGETINTEGER64I_VROBUSTANGLEPROC t_glGetInteger64i_vRobustANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLGETINTEGER64VROBUSTANGLEPROC t_glGetInteger64vRobustANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLGETINTEGERI_VROBUSTANGLEPROC t_glGetIntegeri_vRobustANGLE; @@ -618,12 +622,8 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERTEXTUREPIXELLOCALSTORAGEANGLEPROC t_glFramebufferTexturePixelLocalStorageANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVANGLEPROC t_glGetFramebufferPixelLocalStorageParameterfvANGLE; -ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC - t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVANGLEPROC t_glGetFramebufferPixelLocalStorageParameterivANGLE; -ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC - t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLPIXELLOCALSTORAGEBARRIERANGLEPROC t_glPixelLocalStorageBarrierANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLINVALIDATETEXTUREANGLEPROC t_glInvalidateTextureANGLE; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXIMAGE2DEXTERNALANGLEPROC t_glTexImage2DExternalANGLE; @@ -641,8 +641,6 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLCOPYTEXTURECHROMIUMPROC t_glCopyTextureCHROMIUM; ANGLE_TRACE_LOADER_EXPORT PFNGLCOVERAGEMODULATIONCHROMIUMPROC t_glCoverageModulationCHROMIUM; ANGLE_TRACE_LOADER_EXPORT PFNGLLOSECONTEXTCHROMIUMPROC t_glLoseContextCHROMIUM; ANGLE_TRACE_LOADER_EXPORT PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC t_glEGLImageTargetTexStorageEXT; -ANGLE_TRACE_LOADER_EXPORT PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC - t_glEGLImageTargetTextureStorageEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC t_glDrawArraysInstancedBaseInstanceEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC @@ -694,11 +692,14 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC t_glDrawRangeElementsBaseVertexEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC t_glMultiDrawElementsBaseVertexEXT; -ANGLE_TRACE_LOADER_EXPORT PFNGLBUFFERSTORAGEEXTERNALEXTPROC t_glBufferStorageExternalEXT; -ANGLE_TRACE_LOADER_EXPORT PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC t_glNamedBufferStorageExternalEXT; -ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC t_glFramebufferTextureEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC t_glDrawArraysInstancedEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC t_glDrawElementsInstancedEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLBUFFERSTORAGEEXTERNALEXTPROC t_glBufferStorageExternalEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERSHADINGRATEEXTPROC t_glFramebufferShadingRateEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLGETFRAGMENTSHADINGRATESEXTPROC t_glGetFragmentShadingRatesEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLSHADINGRATECOMBINEROPSEXTPROC t_glShadingRateCombinerOpsEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLSHADINGRATEEXTPROC t_glShadingRateEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC t_glFramebufferTextureEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLVERTEXATTRIBDIVISOREXTPROC t_glVertexAttribDivisorEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC t_glFlushMappedBufferRangeEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLMAPBUFFERRANGEEXTPROC t_glMapBufferRangeEXT; @@ -715,6 +716,8 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC t_glTexStorageM ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGEMEM3DEXTPROC t_glTexStorageMem3DEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC t_glTexStorageMem3DMultisampleEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLIMPORTMEMORYFDEXTPROC t_glImportMemoryFdEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC t_glMultiDrawArraysEXT; +ANGLE_TRACE_LOADER_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC t_glMultiDrawElementsEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC t_glMultiDrawArraysIndirectEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC t_glMultiDrawElementsIndirectEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC @@ -791,7 +794,6 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLTEXPARAMETERIIVEXTPROC t_glTexParameterIivEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC t_glTexParameterIuivEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXBUFFEREXTPROC t_glTexBufferEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXBUFFERRANGEEXTPROC t_glTexBufferRangeEXT; -ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGE1DEXTPROC t_glTexStorage1DEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGE2DEXTPROC t_glTexStorage2DEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGE3DEXTPROC t_glTexStorage3DEXT; ANGLE_TRACE_LOADER_EXPORT PFNGLTEXSTORAGEATTRIBS2DEXTPROC t_glTexStorageAttribs2DEXT; @@ -874,6 +876,8 @@ ANGLE_TRACE_LOADER_EXPORT PFNGLGENVERTEXARRAYSOESPROC t_glGenVertexArraysOES; ANGLE_TRACE_LOADER_EXPORT PFNGLISVERTEXARRAYOESPROC t_glIsVertexArrayOES; ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC t_glFramebufferTextureMultiviewOVR; +ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC + t_glFramebufferTextureMultisampleMultiviewOVR; ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERFOVEATIONCONFIGQCOMPROC t_glFramebufferFoveationConfigQCOM; ANGLE_TRACE_LOADER_EXPORT PFNGLFRAMEBUFFERFOVEATIONPARAMETERSQCOMPROC @@ -1687,6 +1691,12 @@ void LoadTraceGLES(LoadProc loadProc) t_glGetFramebufferParameterivRobustANGLE = reinterpret_cast( loadProc("glGetFramebufferParameterivRobustANGLE")); + t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE = + reinterpret_cast( + loadProc("glGetFramebufferPixelLocalStorageParameterfvRobustANGLE")); + t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE = + reinterpret_cast( + loadProc("glGetFramebufferPixelLocalStorageParameterivRobustANGLE")); t_glGetInteger64i_vRobustANGLE = reinterpret_cast( loadProc("glGetInteger64i_vRobustANGLE")); t_glGetInteger64vRobustANGLE = @@ -1831,15 +1841,9 @@ void LoadTraceGLES(LoadProc loadProc) t_glGetFramebufferPixelLocalStorageParameterfvANGLE = reinterpret_cast( loadProc("glGetFramebufferPixelLocalStorageParameterfvANGLE")); - t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE = - reinterpret_cast( - loadProc("glGetFramebufferPixelLocalStorageParameterfvRobustANGLE")); t_glGetFramebufferPixelLocalStorageParameterivANGLE = reinterpret_cast( loadProc("glGetFramebufferPixelLocalStorageParameterivANGLE")); - t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE = - reinterpret_cast( - loadProc("glGetFramebufferPixelLocalStorageParameterivRobustANGLE")); t_glPixelLocalStorageBarrierANGLE = reinterpret_cast( loadProc("glPixelLocalStorageBarrierANGLE")); t_glInvalidateTextureANGLE = @@ -1872,9 +1876,6 @@ void LoadTraceGLES(LoadProc loadProc) reinterpret_cast(loadProc("glLoseContextCHROMIUM")); t_glEGLImageTargetTexStorageEXT = reinterpret_cast( loadProc("glEGLImageTargetTexStorageEXT")); - t_glEGLImageTargetTextureStorageEXT = - reinterpret_cast( - loadProc("glEGLImageTargetTextureStorageEXT")); t_glDrawArraysInstancedBaseInstanceEXT = reinterpret_cast( loadProc("glDrawArraysInstancedBaseInstanceEXT")); @@ -1952,16 +1953,21 @@ void LoadTraceGLES(LoadProc loadProc) loadProc("glDrawRangeElementsBaseVertexEXT")); t_glMultiDrawElementsBaseVertexEXT = reinterpret_cast( loadProc("glMultiDrawElementsBaseVertexEXT")); - t_glBufferStorageExternalEXT = - reinterpret_cast(loadProc("glBufferStorageExternalEXT")); - t_glNamedBufferStorageExternalEXT = reinterpret_cast( - loadProc("glNamedBufferStorageExternalEXT")); - t_glFramebufferTextureEXT = - reinterpret_cast(loadProc("glFramebufferTextureEXT")); t_glDrawArraysInstancedEXT = reinterpret_cast(loadProc("glDrawArraysInstancedEXT")); t_glDrawElementsInstancedEXT = reinterpret_cast(loadProc("glDrawElementsInstancedEXT")); + t_glBufferStorageExternalEXT = + reinterpret_cast(loadProc("glBufferStorageExternalEXT")); + t_glFramebufferShadingRateEXT = reinterpret_cast( + loadProc("glFramebufferShadingRateEXT")); + t_glGetFragmentShadingRatesEXT = reinterpret_cast( + loadProc("glGetFragmentShadingRatesEXT")); + t_glShadingRateCombinerOpsEXT = reinterpret_cast( + loadProc("glShadingRateCombinerOpsEXT")); + t_glShadingRateEXT = reinterpret_cast(loadProc("glShadingRateEXT")); + t_glFramebufferTextureEXT = + reinterpret_cast(loadProc("glFramebufferTextureEXT")); t_glVertexAttribDivisorEXT = reinterpret_cast(loadProc("glVertexAttribDivisorEXT")); t_glFlushMappedBufferRangeEXT = reinterpret_cast( @@ -1994,6 +2000,10 @@ void LoadTraceGLES(LoadProc loadProc) loadProc("glTexStorageMem3DMultisampleEXT")); t_glImportMemoryFdEXT = reinterpret_cast(loadProc("glImportMemoryFdEXT")); + t_glMultiDrawArraysEXT = + reinterpret_cast(loadProc("glMultiDrawArraysEXT")); + t_glMultiDrawElementsEXT = + reinterpret_cast(loadProc("glMultiDrawElementsEXT")); t_glMultiDrawArraysIndirectEXT = reinterpret_cast( loadProc("glMultiDrawArraysIndirectEXT")); t_glMultiDrawElementsIndirectEXT = reinterpret_cast( @@ -2141,7 +2151,6 @@ void LoadTraceGLES(LoadProc loadProc) t_glTexBufferEXT = reinterpret_cast(loadProc("glTexBufferEXT")); t_glTexBufferRangeEXT = reinterpret_cast(loadProc("glTexBufferRangeEXT")); - t_glTexStorage1DEXT = reinterpret_cast(loadProc("glTexStorage1DEXT")); t_glTexStorage2DEXT = reinterpret_cast(loadProc("glTexStorage2DEXT")); t_glTexStorage3DEXT = reinterpret_cast(loadProc("glTexStorage3DEXT")); t_glTexStorageAttribs2DEXT = @@ -2277,6 +2286,9 @@ void LoadTraceGLES(LoadProc loadProc) reinterpret_cast(loadProc("glIsVertexArrayOES")); t_glFramebufferTextureMultiviewOVR = reinterpret_cast( loadProc("glFramebufferTextureMultiviewOVR")); + t_glFramebufferTextureMultisampleMultiviewOVR = + reinterpret_cast( + loadProc("glFramebufferTextureMultisampleMultiviewOVR")); t_glFramebufferFoveationConfigQCOM = reinterpret_cast( loadProc("glFramebufferFoveationConfigQCOM")); t_glFramebufferFoveationParametersQCOM = diff --git a/util/capture/trace_gles_loader_autogen.h b/util/capture/trace_gles_loader_autogen.h index 92835c6a5d5..c0164a12831 100644 --- a/util/capture/trace_gles_loader_autogen.h +++ b/util/capture/trace_gles_loader_autogen.h @@ -520,6 +520,10 @@ #define glGetFramebufferAttachmentParameterivRobustANGLE \ t_glGetFramebufferAttachmentParameterivRobustANGLE #define glGetFramebufferParameterivRobustANGLE t_glGetFramebufferParameterivRobustANGLE +#define glGetFramebufferPixelLocalStorageParameterfvRobustANGLE \ + t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE +#define glGetFramebufferPixelLocalStorageParameterivRobustANGLE \ + t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE #define glGetInteger64i_vRobustANGLE t_glGetInteger64i_vRobustANGLE #define glGetInteger64vRobustANGLE t_glGetInteger64vRobustANGLE #define glGetIntegeri_vRobustANGLE t_glGetIntegeri_vRobustANGLE @@ -584,12 +588,8 @@ #define glFramebufferTexturePixelLocalStorageANGLE t_glFramebufferTexturePixelLocalStorageANGLE #define glGetFramebufferPixelLocalStorageParameterfvANGLE \ t_glGetFramebufferPixelLocalStorageParameterfvANGLE -#define glGetFramebufferPixelLocalStorageParameterfvRobustANGLE \ - t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE #define glGetFramebufferPixelLocalStorageParameterivANGLE \ t_glGetFramebufferPixelLocalStorageParameterivANGLE -#define glGetFramebufferPixelLocalStorageParameterivRobustANGLE \ - t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE #define glPixelLocalStorageBarrierANGLE t_glPixelLocalStorageBarrierANGLE #define glInvalidateTextureANGLE t_glInvalidateTextureANGLE #define glTexImage2DExternalANGLE t_glTexImage2DExternalANGLE @@ -606,7 +606,6 @@ #define glCoverageModulationCHROMIUM t_glCoverageModulationCHROMIUM #define glLoseContextCHROMIUM t_glLoseContextCHROMIUM #define glEGLImageTargetTexStorageEXT t_glEGLImageTargetTexStorageEXT -#define glEGLImageTargetTextureStorageEXT t_glEGLImageTargetTextureStorageEXT #define glDrawArraysInstancedBaseInstanceEXT t_glDrawArraysInstancedBaseInstanceEXT #define glDrawElementsInstancedBaseInstanceEXT t_glDrawElementsInstancedBaseInstanceEXT #define glDrawElementsInstancedBaseVertexBaseInstanceEXT \ @@ -651,11 +650,14 @@ #define glDrawElementsInstancedBaseVertexEXT t_glDrawElementsInstancedBaseVertexEXT #define glDrawRangeElementsBaseVertexEXT t_glDrawRangeElementsBaseVertexEXT #define glMultiDrawElementsBaseVertexEXT t_glMultiDrawElementsBaseVertexEXT -#define glBufferStorageExternalEXT t_glBufferStorageExternalEXT -#define glNamedBufferStorageExternalEXT t_glNamedBufferStorageExternalEXT -#define glFramebufferTextureEXT t_glFramebufferTextureEXT #define glDrawArraysInstancedEXT t_glDrawArraysInstancedEXT #define glDrawElementsInstancedEXT t_glDrawElementsInstancedEXT +#define glBufferStorageExternalEXT t_glBufferStorageExternalEXT +#define glFramebufferShadingRateEXT t_glFramebufferShadingRateEXT +#define glGetFragmentShadingRatesEXT t_glGetFragmentShadingRatesEXT +#define glShadingRateCombinerOpsEXT t_glShadingRateCombinerOpsEXT +#define glShadingRateEXT t_glShadingRateEXT +#define glFramebufferTextureEXT t_glFramebufferTextureEXT #define glVertexAttribDivisorEXT t_glVertexAttribDivisorEXT #define glFlushMappedBufferRangeEXT t_glFlushMappedBufferRangeEXT #define glMapBufferRangeEXT t_glMapBufferRangeEXT @@ -672,6 +674,8 @@ #define glTexStorageMem3DEXT t_glTexStorageMem3DEXT #define glTexStorageMem3DMultisampleEXT t_glTexStorageMem3DMultisampleEXT #define glImportMemoryFdEXT t_glImportMemoryFdEXT +#define glMultiDrawArraysEXT t_glMultiDrawArraysEXT +#define glMultiDrawElementsEXT t_glMultiDrawElementsEXT #define glMultiDrawArraysIndirectEXT t_glMultiDrawArraysIndirectEXT #define glMultiDrawElementsIndirectEXT t_glMultiDrawElementsIndirectEXT #define glFramebufferTexture2DMultisampleEXT t_glFramebufferTexture2DMultisampleEXT @@ -746,7 +750,6 @@ #define glTexParameterIuivEXT t_glTexParameterIuivEXT #define glTexBufferEXT t_glTexBufferEXT #define glTexBufferRangeEXT t_glTexBufferRangeEXT -#define glTexStorage1DEXT t_glTexStorage1DEXT #define glTexStorage2DEXT t_glTexStorage2DEXT #define glTexStorage3DEXT t_glTexStorage3DEXT #define glTexStorageAttribs2DEXT t_glTexStorageAttribs2DEXT @@ -825,6 +828,7 @@ #define glGenVertexArraysOES t_glGenVertexArraysOES #define glIsVertexArrayOES t_glIsVertexArrayOES #define glFramebufferTextureMultiviewOVR t_glFramebufferTextureMultiviewOVR +#define glFramebufferTextureMultisampleMultiviewOVR t_glFramebufferTextureMultisampleMultiviewOVR #define glFramebufferFoveationConfigQCOM t_glFramebufferFoveationConfigQCOM #define glFramebufferFoveationParametersQCOM t_glFramebufferFoveationParametersQCOM #define glShadingRateQCOM t_glShadingRateQCOM @@ -1405,6 +1409,10 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTA t_glGetFramebufferAttachmentParameterivRobustANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLEPROC t_glGetFramebufferParameterivRobustANGLE; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC + t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC + t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETINTEGER64I_VROBUSTANGLEPROC t_glGetInteger64i_vRobustANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETINTEGER64VROBUSTANGLEPROC t_glGetInteger64vRobustANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETINTEGERI_VROBUSTANGLEPROC t_glGetIntegeri_vRobustANGLE; @@ -1506,12 +1514,8 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERTEXTUREPIXELLOCALSTORAGEANGLEPR t_glFramebufferTexturePixelLocalStorageANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVANGLEPROC t_glGetFramebufferPixelLocalStorageParameterfvANGLE; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC - t_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVANGLEPROC t_glGetFramebufferPixelLocalStorageParameterivANGLE; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC - t_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLPIXELLOCALSTORAGEBARRIERANGLEPROC t_glPixelLocalStorageBarrierANGLE; ANGLE_TRACE_LOADER_EXPORT extern PFNGLINVALIDATETEXTUREANGLEPROC t_glInvalidateTextureANGLE; @@ -1534,8 +1538,6 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLCOVERAGEMODULATIONCHROMIUMPROC t_glCoverag ANGLE_TRACE_LOADER_EXPORT extern PFNGLLOSECONTEXTCHROMIUMPROC t_glLoseContextCHROMIUM; ANGLE_TRACE_LOADER_EXPORT extern PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC t_glEGLImageTargetTexStorageEXT; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC - t_glEGLImageTargetTextureStorageEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC t_glDrawArraysInstancedBaseInstanceEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC @@ -1587,12 +1589,14 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC t_glDrawRangeElementsBaseVertexEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC t_glMultiDrawElementsBaseVertexEXT; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLBUFFERSTORAGEEXTERNALEXTPROC t_glBufferStorageExternalEXT; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC - t_glNamedBufferStorageExternalEXT; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERTEXTUREEXTPROC t_glFramebufferTextureEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLDRAWARRAYSINSTANCEDEXTPROC t_glDrawArraysInstancedEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLDRAWELEMENTSINSTANCEDEXTPROC t_glDrawElementsInstancedEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLBUFFERSTORAGEEXTERNALEXTPROC t_glBufferStorageExternalEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERSHADINGRATEEXTPROC t_glFramebufferShadingRateEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLGETFRAGMENTSHADINGRATESEXTPROC t_glGetFragmentShadingRatesEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLSHADINGRATECOMBINEROPSEXTPROC t_glShadingRateCombinerOpsEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLSHADINGRATEEXTPROC t_glShadingRateEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERTEXTUREEXTPROC t_glFramebufferTextureEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLVERTEXATTRIBDIVISOREXTPROC t_glVertexAttribDivisorEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC t_glFlushMappedBufferRangeEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLMAPBUFFERRANGEEXTPROC t_glMapBufferRangeEXT; @@ -1612,6 +1616,8 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXSTORAGEMEM3DEXTPROC t_glTexStorageMem3D ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC t_glTexStorageMem3DMultisampleEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLIMPORTMEMORYFDEXTPROC t_glImportMemoryFdEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLMULTIDRAWARRAYSEXTPROC t_glMultiDrawArraysEXT; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLMULTIDRAWELEMENTSEXTPROC t_glMultiDrawElementsEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC t_glMultiDrawArraysIndirectEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC t_glMultiDrawElementsIndirectEXT; @@ -1697,7 +1703,6 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXPARAMETERIIVEXTPROC t_glTexParameterIiv ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXPARAMETERIUIVEXTPROC t_glTexParameterIuivEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXBUFFEREXTPROC t_glTexBufferEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXBUFFERRANGEEXTPROC t_glTexBufferRangeEXT; -ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXSTORAGE1DEXTPROC t_glTexStorage1DEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXSTORAGE2DEXTPROC t_glTexStorage2DEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXSTORAGE3DEXTPROC t_glTexStorage3DEXT; ANGLE_TRACE_LOADER_EXPORT extern PFNGLTEXSTORAGEATTRIBS2DEXTPROC t_glTexStorageAttribs2DEXT; @@ -1782,6 +1787,8 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNGLGENVERTEXARRAYSOESPROC t_glGenVertexArrays ANGLE_TRACE_LOADER_EXPORT extern PFNGLISVERTEXARRAYOESPROC t_glIsVertexArrayOES; ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC t_glFramebufferTextureMultiviewOVR; +ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC + t_glFramebufferTextureMultisampleMultiviewOVR; ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERFOVEATIONCONFIGQCOMPROC t_glFramebufferFoveationConfigQCOM; ANGLE_TRACE_LOADER_EXPORT extern PFNGLFRAMEBUFFERFOVEATIONPARAMETERSQCOMPROC @@ -1839,7 +1846,7 @@ typedef GenericProc(KHRONOS_APIENTRY *LoadProc)(const char *); ANGLE_TRACE_LOADER_EXPORT void LoadTraceGLES(LoadProc loadProc); #if defined(__cplusplus) -} // extern "C" +} // extern "C" #endif // defined(__cplusplus) #endif // ANGLE_TRACES_UTIL_GLES_LOADER_AUTOGEN_H_ diff --git a/util/capture/trace_interface.h b/util/capture/trace_interface.h index c99a6c9dc5f..4461a639d89 100644 --- a/util/capture/trace_interface.h +++ b/util/capture/trace_interface.h @@ -13,6 +13,8 @@ #include #include +#include "common/frame_capture_binary_data.h" + namespace angle { @@ -44,6 +46,11 @@ struct TraceInfo int configDepthBits; int configStencilBits; bool isBinaryDataCompressed; + uint32_t binaryVersion; + uint32_t binaryBlockCount; + uint64_t binaryBlockSize; + uint64_t binaryResidentSize; + uint64_t binaryIndexOffset; bool areClientArraysEnabled; bool isBindGeneratesResourcesEnabled; bool isWebGLCompatibilityEnabled; @@ -76,7 +83,7 @@ struct TraceFunctions struct TraceCallbacks { virtual uint8_t *LoadBinaryData(const char *fileName) = 0; - + virtual FrameCaptureBinaryData *ConfigureBinaryDataLoader(const char *fileName) = 0; virtual ~TraceCallbacks() {} }; diff --git a/util/capture/trace_interpreter.cpp b/util/capture/trace_interpreter.cpp index c2af3075cea..2f114cf7e8a 100644 --- a/util/capture/trace_interpreter.cpp +++ b/util/capture/trace_interpreter.cpp @@ -7,6 +7,10 @@ // Parser and interpreter for the C-based replays. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "trace_interpreter.h" #include "anglebase/no_destructor.h" diff --git a/util/capture/trace_interpreter.h b/util/capture/trace_interpreter.h index e9c8b298c9b..38c2222eceb 100644 --- a/util/capture/trace_interpreter.h +++ b/util/capture/trace_interpreter.h @@ -10,6 +10,10 @@ #ifndef ANGLE_TRACE_INTERPRETER_H_ #define ANGLE_TRACE_INTERPRETER_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/frame_capture_utils.h" #include "frame_capture_test_utils.h" #include "traces_export.h" diff --git a/util/capture/trace_interpreter_autogen.cpp b/util/capture/trace_interpreter_autogen.cpp index 826307ea7e5..0b1b6d13254 100644 --- a/util/capture/trace_interpreter_autogen.cpp +++ b/util/capture/trace_interpreter_autogen.cpp @@ -712,13 +712,6 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::EGLSwapBuffersWithDamageKHR, std::move(params)); } - if (strcmp(nameToken, "eglSwapBuffersWithFrameTokenANGLE") == 0) - { - ParamBuffer params = - ParseParameters::type>( - paramTokens, strings); - return CallCapture(EntryPoint::EGLSwapBuffersWithFrameTokenANGLE, std::move(params)); - } if (strcmp(nameToken, "eglSwapInterval") == 0) { ParamBuffer params = ParseParameters::type>( @@ -2085,13 +2078,6 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::GLEGLImageTargetTexture2DOES, std::move(params)); } - if (strcmp(nameToken, "glEGLImageTargetTextureStorageEXT") == 0) - { - ParamBuffer params = - ParseParameters::type>( - paramTokens, strings); - return CallCapture(EntryPoint::GLEGLImageTargetTextureStorageEXT, std::move(params)); - } if (strcmp(nameToken, "glEnable") == 0) { ParamBuffer params = @@ -2324,6 +2310,13 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::GLFramebufferRenderbufferOES, std::move(params)); } + if (strcmp(nameToken, "glFramebufferShadingRateEXT") == 0) + { + ParamBuffer params = + ParseParameters::type>( + paramTokens, strings); + return CallCapture(EntryPoint::GLFramebufferShadingRateEXT, std::move(params)); + } if (strcmp(nameToken, "glFramebufferTexture") == 0) { ParamBuffer params = @@ -2373,6 +2366,14 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::GLFramebufferTextureLayer, std::move(params)); } + if (strcmp(nameToken, "glFramebufferTextureMultisampleMultiviewOVR") == 0) + { + ParamBuffer params = ParseParameters< + std::remove_pointer::type>( + paramTokens, strings); + return CallCapture(EntryPoint::GLFramebufferTextureMultisampleMultiviewOVR, + std::move(params)); + } if (strcmp(nameToken, "glFramebufferTextureMultiviewOVR") == 0) { ParamBuffer params = @@ -2739,6 +2740,13 @@ CallCapture ParseCallCapture(const Token &nameToken, strings); return CallCapture(EntryPoint::GLGetFragDataLocation, std::move(params)); } + if (strcmp(nameToken, "glGetFragmentShadingRatesEXT") == 0) + { + ParamBuffer params = + ParseParameters::type>( + paramTokens, strings); + return CallCapture(EntryPoint::GLGetFragmentShadingRatesEXT, std::move(params)); + } if (strcmp(nameToken, "glGetFramebufferAttachmentParameteriv") == 0) { ParamBuffer params = ParseParameters< @@ -4248,6 +4256,13 @@ CallCapture ParseCallCapture(const Token &nameToken, strings); return CallCapture(EntryPoint::GLMultiDrawArraysANGLE, std::move(params)); } + if (strcmp(nameToken, "glMultiDrawArraysEXT") == 0) + { + ParamBuffer params = + ParseParameters::type>(paramTokens, + strings); + return CallCapture(EntryPoint::GLMultiDrawArraysEXT, std::move(params)); + } if (strcmp(nameToken, "glMultiDrawArraysIndirectEXT") == 0) { ParamBuffer params = @@ -4284,6 +4299,13 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::GLMultiDrawElementsBaseVertexEXT, std::move(params)); } + if (strcmp(nameToken, "glMultiDrawElementsEXT") == 0) + { + ParamBuffer params = + ParseParameters::type>(paramTokens, + strings); + return CallCapture(EntryPoint::GLMultiDrawElementsEXT, std::move(params)); + } if (strcmp(nameToken, "glMultiDrawElementsIndirectEXT") == 0) { ParamBuffer params = @@ -4318,13 +4340,6 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::GLMultiTexCoord4x, std::move(params)); } - if (strcmp(nameToken, "glNamedBufferStorageExternalEXT") == 0) - { - ParamBuffer params = - ParseParameters::type>( - paramTokens, strings); - return CallCapture(EntryPoint::GLNamedBufferStorageExternalEXT, std::move(params)); - } if (strcmp(nameToken, "glNormal3f") == 0) { ParamBuffer params = @@ -5344,6 +5359,19 @@ CallCapture ParseCallCapture(const Token &nameToken, ParseParameters::type>(paramTokens, strings); return CallCapture(EntryPoint::GLShaderSource, std::move(params)); } + if (strcmp(nameToken, "glShadingRateCombinerOpsEXT") == 0) + { + ParamBuffer params = + ParseParameters::type>( + paramTokens, strings); + return CallCapture(EntryPoint::GLShadingRateCombinerOpsEXT, std::move(params)); + } + if (strcmp(nameToken, "glShadingRateEXT") == 0) + { + ParamBuffer params = ParseParameters::type>( + paramTokens, strings); + return CallCapture(EntryPoint::GLShadingRateEXT, std::move(params)); + } if (strcmp(nameToken, "glShadingRateQCOM") == 0) { ParamBuffer params = ParseParameters::type>( @@ -5664,12 +5692,6 @@ CallCapture ParseCallCapture(const Token &nameToken, paramTokens, strings); return CallCapture(EntryPoint::GLTexParameterxv, std::move(params)); } - if (strcmp(nameToken, "glTexStorage1DEXT") == 0) - { - ParamBuffer params = ParseParameters::type>( - paramTokens, strings); - return CallCapture(EntryPoint::GLTexStorage1DEXT, std::move(params)); - } if (strcmp(nameToken, "glTexStorage2D") == 0) { ParamBuffer params = @@ -6354,6 +6376,12 @@ CallCapture ParseCallCapture(const Token &nameToken, ParamBuffer params = ParseParameters(paramTokens, strings); return CallCapture("FenceSync2", std::move(params)); } + if (strcmp(nameToken, "InitializeBinaryDataLoader") == 0) + { + ParamBuffer params = + ParseParameters(paramTokens, strings); + return CallCapture("InitializeBinaryDataLoader", std::move(params)); + } if (strcmp(nameToken, "InitializeReplay") == 0) { ParamBuffer params = ParseParameters(paramTokens, strings); @@ -6374,6 +6402,11 @@ CallCapture ParseCallCapture(const Token &nameToken, ParamBuffer params = ParseParameters(paramTokens, strings); return CallCapture("InitializeReplay4", std::move(params)); } + if (strcmp(nameToken, "InitializeReplay5") == 0) + { + ParamBuffer params = ParseParameters(paramTokens, strings); + return CallCapture("InitializeReplay5", std::move(params)); + } if (strcmp(nameToken, "MapBufferOES") == 0) { ParamBuffer params = ParseParameters(paramTokens, strings); @@ -6447,11 +6480,22 @@ CallCapture ParseCallCapture(const Token &nameToken, ParseParameters(paramTokens, strings); return CallCapture("UpdateClientBufferDataWithOffset", std::move(params)); } + if (strcmp(nameToken, "UpdateCurrentContext") == 0) + { + ParamBuffer params = ParseParameters(paramTokens, strings); + return CallCapture("UpdateCurrentContext", std::move(params)); + } if (strcmp(nameToken, "UpdateCurrentProgram") == 0) { ParamBuffer params = ParseParameters(paramTokens, strings); return CallCapture("UpdateCurrentProgram", std::move(params)); } + if (strcmp(nameToken, "UpdateCurrentProgramPerContext") == 0) + { + ParamBuffer params = + ParseParameters(paramTokens, strings); + return CallCapture("UpdateCurrentProgramPerContext", std::move(params)); + } if (strcmp(nameToken, "UpdateFenceNVID") == 0) { ParamBuffer params = ParseParameters(paramTokens, strings); @@ -6551,6 +6595,12 @@ CallCapture ParseCallCapture(const Token &nameToken, return CallCapture(nameToken, ParamBuffer()); } +template = 0> +void DispatchCallCapture(Fn *fn, const Captures &cap) +{ + (*fn)(); +} + template = 0> void DispatchCallCapture(Fn *fn, const Captures &cap) { @@ -6706,6 +6756,11 @@ void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &c DispatchCallCapture(FenceSync2, captures); return; } + if (call.customFunctionName == "InitializeBinaryDataLoader") + { + DispatchCallCapture(InitializeBinaryDataLoader, captures); + return; + } if (call.customFunctionName == "InitializeReplay") { DispatchCallCapture(InitializeReplay, captures); @@ -6726,6 +6781,11 @@ void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &c DispatchCallCapture(InitializeReplay4, captures); return; } + if (call.customFunctionName == "InitializeReplay5") + { + DispatchCallCapture(InitializeReplay5, captures); + return; + } if (call.customFunctionName == "MapBufferOES") { DispatchCallCapture(MapBufferOES, captures); @@ -6796,11 +6856,21 @@ void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &c DispatchCallCapture(UpdateClientBufferDataWithOffset, captures); return; } + if (call.customFunctionName == "UpdateCurrentContext") + { + DispatchCallCapture(UpdateCurrentContext, captures); + return; + } if (call.customFunctionName == "UpdateCurrentProgram") { DispatchCallCapture(UpdateCurrentProgram, captures); return; } + if (call.customFunctionName == "UpdateCurrentProgramPerContext") + { + DispatchCallCapture(UpdateCurrentProgramPerContext, captures); + return; + } if (call.customFunctionName == "UpdateFenceNVID") { DispatchCallCapture(UpdateFenceNVID, captures); diff --git a/util/egl_loader_autogen.cpp b/util/egl_loader_autogen.cpp index 97b2e7697a0..5395745b25e 100644 --- a/util/egl_loader_autogen.cpp +++ b/util/egl_loader_autogen.cpp @@ -90,7 +90,6 @@ ANGLE_UTIL_EXPORT PFNEGLQUERYSURFACEPOINTERANGLEPROC l_eglQuerySurfacePointerANG ANGLE_UTIL_EXPORT PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC l_eglCreateStreamProducerD3DTextureANGLE; ANGLE_UTIL_EXPORT PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC l_eglStreamPostD3DTextureANGLE; -ANGLE_UTIL_EXPORT PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC l_eglSwapBuffersWithFrameTokenANGLE; ANGLE_UTIL_EXPORT PFNEGLGETMSCRATEANGLEPROC l_eglGetMscRateANGLE; ANGLE_UTIL_EXPORT PFNEGLEXPORTVKIMAGEANGLEPROC l_eglExportVkImageANGLE; ANGLE_UTIL_EXPORT PFNEGLWAITUNTILWORKSCHEDULEDANGLEPROC l_eglWaitUntilWorkScheduledANGLE; @@ -260,9 +259,6 @@ void LoadUtilEGL(LoadProc loadProc) loadProc("eglCreateStreamProducerD3DTextureANGLE")); l_eglStreamPostD3DTextureANGLE = reinterpret_cast( loadProc("eglStreamPostD3DTextureANGLE")); - l_eglSwapBuffersWithFrameTokenANGLE = - reinterpret_cast( - loadProc("eglSwapBuffersWithFrameTokenANGLE")); l_eglGetMscRateANGLE = reinterpret_cast(loadProc("eglGetMscRateANGLE")); l_eglExportVkImageANGLE = diff --git a/util/egl_loader_autogen.h b/util/egl_loader_autogen.h index 1cb039bc005..adc728b1e40 100644 --- a/util/egl_loader_autogen.h +++ b/util/egl_loader_autogen.h @@ -92,7 +92,6 @@ #define eglQuerySurfacePointerANGLE l_eglQuerySurfacePointerANGLE #define eglCreateStreamProducerD3DTextureANGLE l_eglCreateStreamProducerD3DTextureANGLE #define eglStreamPostD3DTextureANGLE l_eglStreamPostD3DTextureANGLE -#define eglSwapBuffersWithFrameTokenANGLE l_eglSwapBuffersWithFrameTokenANGLE #define eglGetMscRateANGLE l_eglGetMscRateANGLE #define eglExportVkImageANGLE l_eglExportVkImageANGLE #define eglWaitUntilWorkScheduledANGLE l_eglWaitUntilWorkScheduledANGLE @@ -216,8 +215,6 @@ ANGLE_UTIL_EXPORT extern PFNEGLQUERYSURFACEPOINTERANGLEPROC l_eglQuerySurfacePoi ANGLE_UTIL_EXPORT extern PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC l_eglCreateStreamProducerD3DTextureANGLE; ANGLE_UTIL_EXPORT extern PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC l_eglStreamPostD3DTextureANGLE; -ANGLE_UTIL_EXPORT extern PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC - l_eglSwapBuffersWithFrameTokenANGLE; ANGLE_UTIL_EXPORT extern PFNEGLGETMSCRATEANGLEPROC l_eglGetMscRateANGLE; ANGLE_UTIL_EXPORT extern PFNEGLEXPORTVKIMAGEANGLEPROC l_eglExportVkImageANGLE; ANGLE_UTIL_EXPORT extern PFNEGLWAITUNTILWORKSCHEDULEDANGLEPROC l_eglWaitUntilWorkScheduledANGLE; @@ -268,7 +265,7 @@ typedef GenericProc(KHRONOS_APIENTRY *LoadProc)(const char *); ANGLE_UTIL_EXPORT void LoadUtilEGL(LoadProc loadProc); #if defined(__cplusplus) -} // extern "C" +} // extern "C" #endif // defined(__cplusplus) #endif // UTIL_EGL_LOADER_AUTOGEN_H_ diff --git a/util/fuchsia/ScenicWindow.cpp b/util/fuchsia/ScenicWindow.cpp index 101ebf0c1aa..ed5c46b8c0e 100644 --- a/util/fuchsia/ScenicWindow.cpp +++ b/util/fuchsia/ScenicWindow.cpp @@ -27,30 +27,13 @@ async::Loop *GetDefaultLoop() return defaultLoop; } -zx::channel ConnectToServiceRoot() -{ - zx::channel clientChannel; - zx::channel serverChannel; - zx_status_t result = zx::channel::create(0, &clientChannel, &serverChannel); - ASSERT(result == ZX_OK); - result = fdio_service_connect("/svc/.", serverChannel.release()); - ASSERT(result == ZX_OK); - return clientChannel; -} - template -zx_status_t ConnectToService(zx_handle_t serviceRoot, fidl::InterfaceRequest request) -{ - ASSERT(request.is_valid()); - return fdio_service_connect_at(serviceRoot, Interface::Name_, request.TakeChannel().release()); -} - -template -fidl::InterfacePtr ConnectToService(zx_handle_t serviceRoot, - async_dispatcher_t *dispatcher) +fidl::InterfacePtr ConnectToService(async_dispatcher_t *dispatcher) { fidl::InterfacePtr result; - ConnectToService(serviceRoot, result.NewRequest(dispatcher)); + fidl::InterfaceRequest request = result.NewRequest(dispatcher); + ASSERT(request.is_valid()); + fdio_service_connect_by_name(Interface::Name_, request.TakeChannel().release()); return result; } @@ -60,9 +43,7 @@ fidl::InterfacePtr ConnectToService(zx_handle_t serviceRoot, // ViewCreationToken to Fuchsia Flatland. ScenicWindow::ScenicWindow() : mLoop(GetDefaultLoop()), - mServiceRoot(ConnectToServiceRoot()), - mPresenter(ConnectToService(mServiceRoot.get(), - mLoop->dispatcher())) + mPresenter(ConnectToService(mLoop->dispatcher())) {} ScenicWindow::~ScenicWindow() diff --git a/util/fuchsia/ScenicWindow.h b/util/fuchsia/ScenicWindow.h index 62ec562e379..62d1737bdcf 100644 --- a/util/fuchsia/ScenicWindow.h +++ b/util/fuchsia/ScenicWindow.h @@ -66,7 +66,6 @@ class ANGLE_UTIL_EXPORT ScenicWindow : public OSWindow async::Loop *const mLoop; // System services. - zx::channel mServiceRoot; fuchsia::element::GraphicalPresenterPtr mPresenter; // EGL native window. diff --git a/util/gles_loader_autogen.cpp b/util/gles_loader_autogen.cpp index 50bf87098fe..6e87aaa47f1 100644 --- a/util/gles_loader_autogen.cpp +++ b/util/gles_loader_autogen.cpp @@ -523,6 +523,10 @@ ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLEPROC l_glGetFramebufferAttachmentParameterivRobustANGLE; ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLEPROC l_glGetFramebufferParameterivRobustANGLE; +ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC + l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; +ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC + l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_UTIL_EXPORT PFNGLGETINTEGER64I_VROBUSTANGLEPROC l_glGetInteger64i_vRobustANGLE; ANGLE_UTIL_EXPORT PFNGLGETINTEGER64VROBUSTANGLEPROC l_glGetInteger64vRobustANGLE; ANGLE_UTIL_EXPORT PFNGLGETINTEGERI_VROBUSTANGLEPROC l_glGetIntegeri_vRobustANGLE; @@ -596,12 +600,8 @@ ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERTEXTUREPIXELLOCALSTORAGEANGLEPROC l_glFramebufferTexturePixelLocalStorageANGLE; ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVANGLEPROC l_glGetFramebufferPixelLocalStorageParameterfvANGLE; -ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC - l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVANGLEPROC l_glGetFramebufferPixelLocalStorageParameterivANGLE; -ANGLE_UTIL_EXPORT PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC - l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_UTIL_EXPORT PFNGLPIXELLOCALSTORAGEBARRIERANGLEPROC l_glPixelLocalStorageBarrierANGLE; ANGLE_UTIL_EXPORT PFNGLINVALIDATETEXTUREANGLEPROC l_glInvalidateTextureANGLE; ANGLE_UTIL_EXPORT PFNGLTEXIMAGE2DEXTERNALANGLEPROC l_glTexImage2DExternalANGLE; @@ -618,7 +618,6 @@ ANGLE_UTIL_EXPORT PFNGLCOPYTEXTURECHROMIUMPROC l_glCopyTextureCHROMIUM; ANGLE_UTIL_EXPORT PFNGLCOVERAGEMODULATIONCHROMIUMPROC l_glCoverageModulationCHROMIUM; ANGLE_UTIL_EXPORT PFNGLLOSECONTEXTCHROMIUMPROC l_glLoseContextCHROMIUM; ANGLE_UTIL_EXPORT PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC l_glEGLImageTargetTexStorageEXT; -ANGLE_UTIL_EXPORT PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC l_glEGLImageTargetTextureStorageEXT; ANGLE_UTIL_EXPORT PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC l_glDrawArraysInstancedBaseInstanceEXT; ANGLE_UTIL_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC @@ -667,11 +666,14 @@ ANGLE_UTIL_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC l_glDrawElementsInstancedBaseVertexEXT; ANGLE_UTIL_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC l_glDrawRangeElementsBaseVertexEXT; ANGLE_UTIL_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC l_glMultiDrawElementsBaseVertexEXT; -ANGLE_UTIL_EXPORT PFNGLBUFFERSTORAGEEXTERNALEXTPROC l_glBufferStorageExternalEXT; -ANGLE_UTIL_EXPORT PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC l_glNamedBufferStorageExternalEXT; -ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC l_glFramebufferTextureEXT; ANGLE_UTIL_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC l_glDrawArraysInstancedEXT; ANGLE_UTIL_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC l_glDrawElementsInstancedEXT; +ANGLE_UTIL_EXPORT PFNGLBUFFERSTORAGEEXTERNALEXTPROC l_glBufferStorageExternalEXT; +ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERSHADINGRATEEXTPROC l_glFramebufferShadingRateEXT; +ANGLE_UTIL_EXPORT PFNGLGETFRAGMENTSHADINGRATESEXTPROC l_glGetFragmentShadingRatesEXT; +ANGLE_UTIL_EXPORT PFNGLSHADINGRATECOMBINEROPSEXTPROC l_glShadingRateCombinerOpsEXT; +ANGLE_UTIL_EXPORT PFNGLSHADINGRATEEXTPROC l_glShadingRateEXT; +ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC l_glFramebufferTextureEXT; ANGLE_UTIL_EXPORT PFNGLVERTEXATTRIBDIVISOREXTPROC l_glVertexAttribDivisorEXT; ANGLE_UTIL_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC l_glFlushMappedBufferRangeEXT; ANGLE_UTIL_EXPORT PFNGLMAPBUFFERRANGEEXTPROC l_glMapBufferRangeEXT; @@ -688,6 +690,8 @@ ANGLE_UTIL_EXPORT PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC l_glTexStorageMem2DMult ANGLE_UTIL_EXPORT PFNGLTEXSTORAGEMEM3DEXTPROC l_glTexStorageMem3DEXT; ANGLE_UTIL_EXPORT PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC l_glTexStorageMem3DMultisampleEXT; ANGLE_UTIL_EXPORT PFNGLIMPORTMEMORYFDEXTPROC l_glImportMemoryFdEXT; +ANGLE_UTIL_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC l_glMultiDrawArraysEXT; +ANGLE_UTIL_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC l_glMultiDrawElementsEXT; ANGLE_UTIL_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC l_glMultiDrawArraysIndirectEXT; ANGLE_UTIL_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC l_glMultiDrawElementsIndirectEXT; ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC @@ -763,7 +767,6 @@ ANGLE_UTIL_EXPORT PFNGLTEXPARAMETERIIVEXTPROC l_glTexParameterIivEXT; ANGLE_UTIL_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC l_glTexParameterIuivEXT; ANGLE_UTIL_EXPORT PFNGLTEXBUFFEREXTPROC l_glTexBufferEXT; ANGLE_UTIL_EXPORT PFNGLTEXBUFFERRANGEEXTPROC l_glTexBufferRangeEXT; -ANGLE_UTIL_EXPORT PFNGLTEXSTORAGE1DEXTPROC l_glTexStorage1DEXT; ANGLE_UTIL_EXPORT PFNGLTEXSTORAGE2DEXTPROC l_glTexStorage2DEXT; ANGLE_UTIL_EXPORT PFNGLTEXSTORAGE3DEXTPROC l_glTexStorage3DEXT; ANGLE_UTIL_EXPORT PFNGLTEXSTORAGEATTRIBS2DEXTPROC l_glTexStorageAttribs2DEXT; @@ -844,6 +847,8 @@ ANGLE_UTIL_EXPORT PFNGLDELETEVERTEXARRAYSOESPROC l_glDeleteVertexArraysOES; ANGLE_UTIL_EXPORT PFNGLGENVERTEXARRAYSOESPROC l_glGenVertexArraysOES; ANGLE_UTIL_EXPORT PFNGLISVERTEXARRAYOESPROC l_glIsVertexArrayOES; ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC l_glFramebufferTextureMultiviewOVR; +ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC + l_glFramebufferTextureMultisampleMultiviewOVR; ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERFOVEATIONCONFIGQCOMPROC l_glFramebufferFoveationConfigQCOM; ANGLE_UTIL_EXPORT PFNGLFRAMEBUFFERFOVEATIONPARAMETERSQCOMPROC l_glFramebufferFoveationParametersQCOM; @@ -1654,6 +1659,12 @@ void LoadUtilGLES(LoadProc loadProc) l_glGetFramebufferParameterivRobustANGLE = reinterpret_cast( loadProc("glGetFramebufferParameterivRobustANGLE")); + l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE = + reinterpret_cast( + loadProc("glGetFramebufferPixelLocalStorageParameterfvRobustANGLE")); + l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE = + reinterpret_cast( + loadProc("glGetFramebufferPixelLocalStorageParameterivRobustANGLE")); l_glGetInteger64i_vRobustANGLE = reinterpret_cast( loadProc("glGetInteger64i_vRobustANGLE")); l_glGetInteger64vRobustANGLE = @@ -1798,15 +1809,9 @@ void LoadUtilGLES(LoadProc loadProc) l_glGetFramebufferPixelLocalStorageParameterfvANGLE = reinterpret_cast( loadProc("glGetFramebufferPixelLocalStorageParameterfvANGLE")); - l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE = - reinterpret_cast( - loadProc("glGetFramebufferPixelLocalStorageParameterfvRobustANGLE")); l_glGetFramebufferPixelLocalStorageParameterivANGLE = reinterpret_cast( loadProc("glGetFramebufferPixelLocalStorageParameterivANGLE")); - l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE = - reinterpret_cast( - loadProc("glGetFramebufferPixelLocalStorageParameterivRobustANGLE")); l_glPixelLocalStorageBarrierANGLE = reinterpret_cast( loadProc("glPixelLocalStorageBarrierANGLE")); l_glInvalidateTextureANGLE = @@ -1839,9 +1844,6 @@ void LoadUtilGLES(LoadProc loadProc) reinterpret_cast(loadProc("glLoseContextCHROMIUM")); l_glEGLImageTargetTexStorageEXT = reinterpret_cast( loadProc("glEGLImageTargetTexStorageEXT")); - l_glEGLImageTargetTextureStorageEXT = - reinterpret_cast( - loadProc("glEGLImageTargetTextureStorageEXT")); l_glDrawArraysInstancedBaseInstanceEXT = reinterpret_cast( loadProc("glDrawArraysInstancedBaseInstanceEXT")); @@ -1919,16 +1921,21 @@ void LoadUtilGLES(LoadProc loadProc) loadProc("glDrawRangeElementsBaseVertexEXT")); l_glMultiDrawElementsBaseVertexEXT = reinterpret_cast( loadProc("glMultiDrawElementsBaseVertexEXT")); - l_glBufferStorageExternalEXT = - reinterpret_cast(loadProc("glBufferStorageExternalEXT")); - l_glNamedBufferStorageExternalEXT = reinterpret_cast( - loadProc("glNamedBufferStorageExternalEXT")); - l_glFramebufferTextureEXT = - reinterpret_cast(loadProc("glFramebufferTextureEXT")); l_glDrawArraysInstancedEXT = reinterpret_cast(loadProc("glDrawArraysInstancedEXT")); l_glDrawElementsInstancedEXT = reinterpret_cast(loadProc("glDrawElementsInstancedEXT")); + l_glBufferStorageExternalEXT = + reinterpret_cast(loadProc("glBufferStorageExternalEXT")); + l_glFramebufferShadingRateEXT = reinterpret_cast( + loadProc("glFramebufferShadingRateEXT")); + l_glGetFragmentShadingRatesEXT = reinterpret_cast( + loadProc("glGetFragmentShadingRatesEXT")); + l_glShadingRateCombinerOpsEXT = reinterpret_cast( + loadProc("glShadingRateCombinerOpsEXT")); + l_glShadingRateEXT = reinterpret_cast(loadProc("glShadingRateEXT")); + l_glFramebufferTextureEXT = + reinterpret_cast(loadProc("glFramebufferTextureEXT")); l_glVertexAttribDivisorEXT = reinterpret_cast(loadProc("glVertexAttribDivisorEXT")); l_glFlushMappedBufferRangeEXT = reinterpret_cast( @@ -1961,6 +1968,10 @@ void LoadUtilGLES(LoadProc loadProc) loadProc("glTexStorageMem3DMultisampleEXT")); l_glImportMemoryFdEXT = reinterpret_cast(loadProc("glImportMemoryFdEXT")); + l_glMultiDrawArraysEXT = + reinterpret_cast(loadProc("glMultiDrawArraysEXT")); + l_glMultiDrawElementsEXT = + reinterpret_cast(loadProc("glMultiDrawElementsEXT")); l_glMultiDrawArraysIndirectEXT = reinterpret_cast( loadProc("glMultiDrawArraysIndirectEXT")); l_glMultiDrawElementsIndirectEXT = reinterpret_cast( @@ -2108,7 +2119,6 @@ void LoadUtilGLES(LoadProc loadProc) l_glTexBufferEXT = reinterpret_cast(loadProc("glTexBufferEXT")); l_glTexBufferRangeEXT = reinterpret_cast(loadProc("glTexBufferRangeEXT")); - l_glTexStorage1DEXT = reinterpret_cast(loadProc("glTexStorage1DEXT")); l_glTexStorage2DEXT = reinterpret_cast(loadProc("glTexStorage2DEXT")); l_glTexStorage3DEXT = reinterpret_cast(loadProc("glTexStorage3DEXT")); l_glTexStorageAttribs2DEXT = @@ -2244,6 +2254,9 @@ void LoadUtilGLES(LoadProc loadProc) reinterpret_cast(loadProc("glIsVertexArrayOES")); l_glFramebufferTextureMultiviewOVR = reinterpret_cast( loadProc("glFramebufferTextureMultiviewOVR")); + l_glFramebufferTextureMultisampleMultiviewOVR = + reinterpret_cast( + loadProc("glFramebufferTextureMultisampleMultiviewOVR")); l_glFramebufferFoveationConfigQCOM = reinterpret_cast( loadProc("glFramebufferFoveationConfigQCOM")); l_glFramebufferFoveationParametersQCOM = diff --git a/util/gles_loader_autogen.h b/util/gles_loader_autogen.h index 24b2133c9f1..9b727db81eb 100644 --- a/util/gles_loader_autogen.h +++ b/util/gles_loader_autogen.h @@ -520,6 +520,10 @@ #define glGetFramebufferAttachmentParameterivRobustANGLE \ l_glGetFramebufferAttachmentParameterivRobustANGLE #define glGetFramebufferParameterivRobustANGLE l_glGetFramebufferParameterivRobustANGLE +#define glGetFramebufferPixelLocalStorageParameterfvRobustANGLE \ + l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE +#define glGetFramebufferPixelLocalStorageParameterivRobustANGLE \ + l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE #define glGetInteger64i_vRobustANGLE l_glGetInteger64i_vRobustANGLE #define glGetInteger64vRobustANGLE l_glGetInteger64vRobustANGLE #define glGetIntegeri_vRobustANGLE l_glGetIntegeri_vRobustANGLE @@ -584,12 +588,8 @@ #define glFramebufferTexturePixelLocalStorageANGLE l_glFramebufferTexturePixelLocalStorageANGLE #define glGetFramebufferPixelLocalStorageParameterfvANGLE \ l_glGetFramebufferPixelLocalStorageParameterfvANGLE -#define glGetFramebufferPixelLocalStorageParameterfvRobustANGLE \ - l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE #define glGetFramebufferPixelLocalStorageParameterivANGLE \ l_glGetFramebufferPixelLocalStorageParameterivANGLE -#define glGetFramebufferPixelLocalStorageParameterivRobustANGLE \ - l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE #define glPixelLocalStorageBarrierANGLE l_glPixelLocalStorageBarrierANGLE #define glInvalidateTextureANGLE l_glInvalidateTextureANGLE #define glTexImage2DExternalANGLE l_glTexImage2DExternalANGLE @@ -606,7 +606,6 @@ #define glCoverageModulationCHROMIUM l_glCoverageModulationCHROMIUM #define glLoseContextCHROMIUM l_glLoseContextCHROMIUM #define glEGLImageTargetTexStorageEXT l_glEGLImageTargetTexStorageEXT -#define glEGLImageTargetTextureStorageEXT l_glEGLImageTargetTextureStorageEXT #define glDrawArraysInstancedBaseInstanceEXT l_glDrawArraysInstancedBaseInstanceEXT #define glDrawElementsInstancedBaseInstanceEXT l_glDrawElementsInstancedBaseInstanceEXT #define glDrawElementsInstancedBaseVertexBaseInstanceEXT \ @@ -651,11 +650,14 @@ #define glDrawElementsInstancedBaseVertexEXT l_glDrawElementsInstancedBaseVertexEXT #define glDrawRangeElementsBaseVertexEXT l_glDrawRangeElementsBaseVertexEXT #define glMultiDrawElementsBaseVertexEXT l_glMultiDrawElementsBaseVertexEXT -#define glBufferStorageExternalEXT l_glBufferStorageExternalEXT -#define glNamedBufferStorageExternalEXT l_glNamedBufferStorageExternalEXT -#define glFramebufferTextureEXT l_glFramebufferTextureEXT #define glDrawArraysInstancedEXT l_glDrawArraysInstancedEXT #define glDrawElementsInstancedEXT l_glDrawElementsInstancedEXT +#define glBufferStorageExternalEXT l_glBufferStorageExternalEXT +#define glFramebufferShadingRateEXT l_glFramebufferShadingRateEXT +#define glGetFragmentShadingRatesEXT l_glGetFragmentShadingRatesEXT +#define glShadingRateCombinerOpsEXT l_glShadingRateCombinerOpsEXT +#define glShadingRateEXT l_glShadingRateEXT +#define glFramebufferTextureEXT l_glFramebufferTextureEXT #define glVertexAttribDivisorEXT l_glVertexAttribDivisorEXT #define glFlushMappedBufferRangeEXT l_glFlushMappedBufferRangeEXT #define glMapBufferRangeEXT l_glMapBufferRangeEXT @@ -672,6 +674,8 @@ #define glTexStorageMem3DEXT l_glTexStorageMem3DEXT #define glTexStorageMem3DMultisampleEXT l_glTexStorageMem3DMultisampleEXT #define glImportMemoryFdEXT l_glImportMemoryFdEXT +#define glMultiDrawArraysEXT l_glMultiDrawArraysEXT +#define glMultiDrawElementsEXT l_glMultiDrawElementsEXT #define glMultiDrawArraysIndirectEXT l_glMultiDrawArraysIndirectEXT #define glMultiDrawElementsIndirectEXT l_glMultiDrawElementsIndirectEXT #define glFramebufferTexture2DMultisampleEXT l_glFramebufferTexture2DMultisampleEXT @@ -746,7 +750,6 @@ #define glTexParameterIuivEXT l_glTexParameterIuivEXT #define glTexBufferEXT l_glTexBufferEXT #define glTexBufferRangeEXT l_glTexBufferRangeEXT -#define glTexStorage1DEXT l_glTexStorage1DEXT #define glTexStorage2DEXT l_glTexStorage2DEXT #define glTexStorage3DEXT l_glTexStorage3DEXT #define glTexStorageAttribs2DEXT l_glTexStorageAttribs2DEXT @@ -825,6 +828,7 @@ #define glGenVertexArraysOES l_glGenVertexArraysOES #define glIsVertexArrayOES l_glIsVertexArrayOES #define glFramebufferTextureMultiviewOVR l_glFramebufferTextureMultiviewOVR +#define glFramebufferTextureMultisampleMultiviewOVR l_glFramebufferTextureMultisampleMultiviewOVR #define glFramebufferFoveationConfigQCOM l_glFramebufferFoveationConfigQCOM #define glFramebufferFoveationParametersQCOM l_glFramebufferFoveationParametersQCOM #define glShadingRateQCOM l_glShadingRateQCOM @@ -1392,6 +1396,10 @@ ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLEPROC l_glGetFramebufferAttachmentParameterivRobustANGLE; ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLEPROC l_glGetFramebufferParameterivRobustANGLE; +ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC + l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; +ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC + l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_UTIL_EXPORT extern PFNGLGETINTEGER64I_VROBUSTANGLEPROC l_glGetInteger64i_vRobustANGLE; ANGLE_UTIL_EXPORT extern PFNGLGETINTEGER64VROBUSTANGLEPROC l_glGetInteger64vRobustANGLE; ANGLE_UTIL_EXPORT extern PFNGLGETINTEGERI_VROBUSTANGLEPROC l_glGetIntegeri_vRobustANGLE; @@ -1474,12 +1482,8 @@ ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERTEXTUREPIXELLOCALSTORAGEANGLEPROC l_glFramebufferTexturePixelLocalStorageANGLE; ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVANGLEPROC l_glGetFramebufferPixelLocalStorageParameterfvANGLE; -ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVROBUSTANGLEPROC - l_glGetFramebufferPixelLocalStorageParameterfvRobustANGLE; ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVANGLEPROC l_glGetFramebufferPixelLocalStorageParameterivANGLE; -ANGLE_UTIL_EXPORT extern PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVROBUSTANGLEPROC - l_glGetFramebufferPixelLocalStorageParameterivRobustANGLE; ANGLE_UTIL_EXPORT extern PFNGLPIXELLOCALSTORAGEBARRIERANGLEPROC l_glPixelLocalStorageBarrierANGLE; ANGLE_UTIL_EXPORT extern PFNGLINVALIDATETEXTUREANGLEPROC l_glInvalidateTextureANGLE; ANGLE_UTIL_EXPORT extern PFNGLTEXIMAGE2DEXTERNALANGLEPROC l_glTexImage2DExternalANGLE; @@ -1496,8 +1500,6 @@ ANGLE_UTIL_EXPORT extern PFNGLCOPYTEXTURECHROMIUMPROC l_glCopyTextureCHROMIUM; ANGLE_UTIL_EXPORT extern PFNGLCOVERAGEMODULATIONCHROMIUMPROC l_glCoverageModulationCHROMIUM; ANGLE_UTIL_EXPORT extern PFNGLLOSECONTEXTCHROMIUMPROC l_glLoseContextCHROMIUM; ANGLE_UTIL_EXPORT extern PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC l_glEGLImageTargetTexStorageEXT; -ANGLE_UTIL_EXPORT extern PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC - l_glEGLImageTargetTextureStorageEXT; ANGLE_UTIL_EXPORT extern PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC l_glDrawArraysInstancedBaseInstanceEXT; ANGLE_UTIL_EXPORT extern PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC @@ -1546,11 +1548,14 @@ ANGLE_UTIL_EXPORT extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC l_glDrawElementsInstancedBaseVertexEXT; ANGLE_UTIL_EXPORT extern PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC l_glDrawRangeElementsBaseVertexEXT; ANGLE_UTIL_EXPORT extern PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC l_glMultiDrawElementsBaseVertexEXT; -ANGLE_UTIL_EXPORT extern PFNGLBUFFERSTORAGEEXTERNALEXTPROC l_glBufferStorageExternalEXT; -ANGLE_UTIL_EXPORT extern PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC l_glNamedBufferStorageExternalEXT; -ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERTEXTUREEXTPROC l_glFramebufferTextureEXT; ANGLE_UTIL_EXPORT extern PFNGLDRAWARRAYSINSTANCEDEXTPROC l_glDrawArraysInstancedEXT; ANGLE_UTIL_EXPORT extern PFNGLDRAWELEMENTSINSTANCEDEXTPROC l_glDrawElementsInstancedEXT; +ANGLE_UTIL_EXPORT extern PFNGLBUFFERSTORAGEEXTERNALEXTPROC l_glBufferStorageExternalEXT; +ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERSHADINGRATEEXTPROC l_glFramebufferShadingRateEXT; +ANGLE_UTIL_EXPORT extern PFNGLGETFRAGMENTSHADINGRATESEXTPROC l_glGetFragmentShadingRatesEXT; +ANGLE_UTIL_EXPORT extern PFNGLSHADINGRATECOMBINEROPSEXTPROC l_glShadingRateCombinerOpsEXT; +ANGLE_UTIL_EXPORT extern PFNGLSHADINGRATEEXTPROC l_glShadingRateEXT; +ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERTEXTUREEXTPROC l_glFramebufferTextureEXT; ANGLE_UTIL_EXPORT extern PFNGLVERTEXATTRIBDIVISOREXTPROC l_glVertexAttribDivisorEXT; ANGLE_UTIL_EXPORT extern PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC l_glFlushMappedBufferRangeEXT; ANGLE_UTIL_EXPORT extern PFNGLMAPBUFFERRANGEEXTPROC l_glMapBufferRangeEXT; @@ -1567,6 +1572,8 @@ ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC l_glTexStorageMe ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGEMEM3DEXTPROC l_glTexStorageMem3DEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC l_glTexStorageMem3DMultisampleEXT; ANGLE_UTIL_EXPORT extern PFNGLIMPORTMEMORYFDEXTPROC l_glImportMemoryFdEXT; +ANGLE_UTIL_EXPORT extern PFNGLMULTIDRAWARRAYSEXTPROC l_glMultiDrawArraysEXT; +ANGLE_UTIL_EXPORT extern PFNGLMULTIDRAWELEMENTSEXTPROC l_glMultiDrawElementsEXT; ANGLE_UTIL_EXPORT extern PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC l_glMultiDrawArraysIndirectEXT; ANGLE_UTIL_EXPORT extern PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC l_glMultiDrawElementsIndirectEXT; ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC @@ -1643,7 +1650,6 @@ ANGLE_UTIL_EXPORT extern PFNGLTEXPARAMETERIIVEXTPROC l_glTexParameterIivEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXPARAMETERIUIVEXTPROC l_glTexParameterIuivEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXBUFFEREXTPROC l_glTexBufferEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXBUFFERRANGEEXTPROC l_glTexBufferRangeEXT; -ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGE1DEXTPROC l_glTexStorage1DEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGE2DEXTPROC l_glTexStorage2DEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGE3DEXTPROC l_glTexStorage3DEXT; ANGLE_UTIL_EXPORT extern PFNGLTEXSTORAGEATTRIBS2DEXTPROC l_glTexStorageAttribs2DEXT; @@ -1724,6 +1730,8 @@ ANGLE_UTIL_EXPORT extern PFNGLDELETEVERTEXARRAYSOESPROC l_glDeleteVertexArraysOE ANGLE_UTIL_EXPORT extern PFNGLGENVERTEXARRAYSOESPROC l_glGenVertexArraysOES; ANGLE_UTIL_EXPORT extern PFNGLISVERTEXARRAYOESPROC l_glIsVertexArrayOES; ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC l_glFramebufferTextureMultiviewOVR; +ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC + l_glFramebufferTextureMultisampleMultiviewOVR; ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERFOVEATIONCONFIGQCOMPROC l_glFramebufferFoveationConfigQCOM; ANGLE_UTIL_EXPORT extern PFNGLFRAMEBUFFERFOVEATIONPARAMETERSQCOMPROC l_glFramebufferFoveationParametersQCOM; @@ -1778,7 +1786,7 @@ typedef GenericProc(KHRONOS_APIENTRY *LoadProc)(const char *); ANGLE_UTIL_EXPORT void LoadUtilGLES(LoadProc loadProc); #if defined(__cplusplus) -} // extern "C" +} // extern "C" #endif // defined(__cplusplus) #endif // UTIL_GLES_LOADER_AUTOGEN_H_ diff --git a/util/keyboard.h b/util/keyboard.h index 50bcafd8b7c..e77d242eebd 100644 --- a/util/keyboard.h +++ b/util/keyboard.h @@ -7,111 +7,114 @@ #ifndef SAMPLE_UTIL_KEYBOARD_H #define SAMPLE_UTIL_KEYBOARD_H -enum Key +namespace angle { - KEY_UNKNOWN, - KEY_A, // The A key - KEY_B, // The B key - KEY_C, // The C key - KEY_D, // The D key - KEY_E, // The E key - KEY_F, // The F key - KEY_G, // The G key - KEY_H, // The H key - KEY_I, // The I key - KEY_J, // The J key - KEY_K, // The K key - KEY_L, // The L key - KEY_M, // The M key - KEY_N, // The N key - KEY_O, // The O key - KEY_P, // The P key - KEY_Q, // The Q key - KEY_R, // The R key - KEY_S, // The S key - KEY_T, // The T key - KEY_U, // The U key - KEY_V, // The V key - KEY_W, // The W key - KEY_X, // The X key - KEY_Y, // The Y key - KEY_Z, // The Z key - KEY_NUM0, // The 0 key - KEY_NUM1, // The 1 key - KEY_NUM2, // The 2 key - KEY_NUM3, // The 3 key - KEY_NUM4, // The 4 key - KEY_NUM5, // The 5 key - KEY_NUM6, // The 6 key - KEY_NUM7, // The 7 key - KEY_NUM8, // The 8 key - KEY_NUM9, // The 9 key - KEY_ESCAPE, // The escape key - KEY_LCONTROL, // The left control key - KEY_LSHIFT, // The left shift key - KEY_LALT, // The left alt key - KEY_LSYSTEM, // The left OS specific key: Window (Windows and Linux), Apple (MacOS X), ... - KEY_RCONTROL, // The right control key - KEY_RSHIFT, // The right shift key - KEY_RALT, // The right alt key - KEY_RSYSTEM, // The right OS specific key: Window (Windows and Linux), Apple (MacOS X), ... - KEY_MENU, // The menu key - KEY_LBRACKET, // The [ key - KEY_RBRACKET, // The ] key - KEY_SEMICOLON, // The ; key - KEY_COMMA, // The , key - KEY_PERIOD, // The . key - KEY_QUOTE, // The ' key - KEY_SLASH, // The / key - KEY_BACKSLASH, // The \ key - KEY_TILDE, // The ~ key - KEY_EQUAL, // The = key - KEY_DASH, // The - key - KEY_SPACE, // The space key - KEY_RETURN, // The return key - KEY_BACK, // The backspace key - KEY_TAB, // The tabulation key - KEY_PAGEUP, // The page up key - KEY_PAGEDOWN, // The page down key - KEY_END, // The end key - KEY_HOME, // The home key - KEY_INSERT, // The insert key - KEY_DELETE, // The delete key - KEY_ADD, // + - KEY_SUBTRACT, // - - KEY_MULTIPLY, // * - KEY_DIVIDE, // / - KEY_LEFT, // Left arrow - KEY_RIGHT, // Right arrow - KEY_UP, // Up arrow - KEY_DOWN, // Down arrow - KEY_NUMPAD0, // The numpad 0 key - KEY_NUMPAD1, // The numpad 1 key - KEY_NUMPAD2, // The numpad 2 key - KEY_NUMPAD3, // The numpad 3 key - KEY_NUMPAD4, // The numpad 4 key - KEY_NUMPAD5, // The numpad 5 key - KEY_NUMPAD6, // The numpad 6 key - KEY_NUMPAD7, // The numpad 7 key - KEY_NUMPAD8, // The numpad 8 key - KEY_NUMPAD9, // The numpad 9 key - KEY_F1, // The F1 key - KEY_F2, // The F2 key - KEY_F3, // The F3 key - KEY_F4, // The F4 key - KEY_F5, // The F5 key - KEY_F6, // The F6 key - KEY_F7, // The F7 key - KEY_F8, // The F8 key - KEY_F9, // The F8 key - KEY_F10, // The F10 key - KEY_F11, // The F11 key - KEY_F12, // The F12 key - KEY_F13, // The F13 key - KEY_F14, // The F14 key - KEY_F15, // The F15 key - KEY_PAUSE, // The pause key - KEY_COUNT, +enum class KeyType +{ + UNKNOWN, + A, // The A key + B, // The B key + C, // The C key + D, // The D key + E, // The E key + F, // The F key + G, // The G key + H, // The H key + I, // The I key + J, // The J key + K, // The K key + L, // The L key + M, // The M key + N, // The N key + O, // The O key + P, // The P key + Q, // The Q key + R, // The R key + S, // The S key + T, // The T key + U, // The U key + V, // The V key + W, // The W key + X, // The X key + Y, // The Y key + Z, // The Z key + NUM0, // The 0 key + NUM1, // The 1 key + NUM2, // The 2 key + NUM3, // The 3 key + NUM4, // The 4 key + NUM5, // The 5 key + NUM6, // The 6 key + NUM7, // The 7 key + NUM8, // The 8 key + NUM9, // The 9 key + ESCAPE, // The escape key + LCONTROL, // The left control key + LSHIFT, // The left shift key + LALT, // The left alt key + LSYSTEM, // The left OS specific key: Window (Windows and Linux), Apple (MacOS X), ... + RCONTROL, // The right control key + RSHIFT, // The right shift key + RALT, // The right alt key + RSYSTEM, // The right OS specific key: Window (Windows and Linux), Apple (MacOS X), ... + MENU, // The menu key + LBRACKET, // The [ key + RBRACKET, // The ] key + SEMICOLON, // The ; key + COMMA, // The , key + PERIOD, // The . key + QUOTE, // The ' key + SLASH, // The / key + BACKSLASH, // The \ key + TILDE, // The ~ key + EQUAL, // The = key + DASH, // The - key + SPACE, // The space key + RETURN, // The return key + BACK, // The backspace key + TAB, // The tabulation key + PAGEUP, // The page up key + PAGEDOWN, // The page down key + END, // The end key + HOME, // The home key + INSERT, // The insert key + DEL, // The delete key, Avoid Windows DELETE macro (#defined in ) + ADD, // + + SUBTRACT, // - + MULTIPLY, // * + DIVIDE, // / + LEFT, // Left arrow + RIGHT, // Right arrow + UP, // Up arrow + DOWN, // Down arrow + NUMPAD0, // The numpad 0 key + NUMPAD1, // The numpad 1 key + NUMPAD2, // The numpad 2 key + NUMPAD3, // The numpad 3 key + NUMPAD4, // The numpad 4 key + NUMPAD5, // The numpad 5 key + NUMPAD6, // The numpad 6 key + NUMPAD7, // The numpad 7 key + NUMPAD8, // The numpad 8 key + NUMPAD9, // The numpad 9 key + F1, // The F1 key + F2, // The F2 key + F3, // The F3 key + F4, // The F4 key + F5, // The F5 key + F6, // The F6 key + F7, // The F7 key + F8, // The F8 key + F9, // The F8 key + F10, // The F10 key + F11, // The F11 key + F12, // The F12 key + F13, // The F13 key + F14, // The F14 key + F15, // The F15 key + PAUSE, // The pause key + COUNT, }; +} // namespace angle #endif // SAMPLE_UTIL_KEYBOARD_H diff --git a/util/linux/wayland/WaylandWindow.cpp b/util/linux/wayland/WaylandWindow.cpp index 8a701eb2a7d..19f1e79eb34 100644 --- a/util/linux/wayland/WaylandWindow.cpp +++ b/util/linux/wayland/WaylandWindow.cpp @@ -6,6 +6,10 @@ // WaylandWindow.cpp: Implementation of OSWindow for Wayland +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/linux/wayland/WaylandWindow.h" #include #include diff --git a/util/linux/x11/X11Pixmap.cpp b/util/linux/x11/X11Pixmap.cpp index 612bc748331..253dcc85c1b 100644 --- a/util/linux/x11/X11Pixmap.cpp +++ b/util/linux/x11/X11Pixmap.cpp @@ -6,6 +6,10 @@ // X11Pixmap.cpp: Implementation of OSPixmap for X11 +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/linux/x11/X11Pixmap.h" X11Pixmap::X11Pixmap() : mPixmap(0), mDisplay(nullptr) {} diff --git a/util/linux/x11/X11Window.cpp b/util/linux/x11/X11Window.cpp index 8aef19eafa8..5f66f2ccc73 100644 --- a/util/linux/x11/X11Window.cpp +++ b/util/linux/x11/X11Window.cpp @@ -6,6 +6,10 @@ // X11Window.cpp: Implementation of OSWindow for X11 +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/linux/x11/X11Window.h" #include "common/debug.h" @@ -24,7 +28,7 @@ Bool WaitForMapNotify(Display *dpy, XEvent *event, XPointer window) return event->type == MapNotify && event->xmap.window == reinterpret_cast(window); } -static Key X11CodeToKey(Display *display, unsigned int scancode) +static angle::KeyType X11CodeToKey(Display *display, unsigned int scancode) { int temp; KeySym *keySymbols; @@ -36,214 +40,214 @@ static Key X11CodeToKey(Display *display, unsigned int scancode) switch (keySymbol) { case XK_Shift_L: - return KEY_LSHIFT; + return angle::KeyType::LSHIFT; case XK_Shift_R: - return KEY_RSHIFT; + return angle::KeyType::RSHIFT; case XK_Alt_L: - return KEY_LALT; + return angle::KeyType::LALT; case XK_Alt_R: - return KEY_RALT; + return angle::KeyType::RALT; case XK_Control_L: - return KEY_LCONTROL; + return angle::KeyType::LCONTROL; case XK_Control_R: - return KEY_RCONTROL; + return angle::KeyType::RCONTROL; case XK_Super_L: - return KEY_LSYSTEM; + return angle::KeyType::LSYSTEM; case XK_Super_R: - return KEY_RSYSTEM; + return angle::KeyType::RSYSTEM; case XK_Menu: - return KEY_MENU; + return angle::KeyType::MENU; case XK_semicolon: - return KEY_SEMICOLON; + return angle::KeyType::SEMICOLON; case XK_slash: - return KEY_SLASH; + return angle::KeyType::SLASH; case XK_equal: - return KEY_EQUAL; + return angle::KeyType::EQUAL; case XK_minus: - return KEY_DASH; + return angle::KeyType::DASH; case XK_bracketleft: - return KEY_LBRACKET; + return angle::KeyType::LBRACKET; case XK_bracketright: - return KEY_RBRACKET; + return angle::KeyType::RBRACKET; case XK_comma: - return KEY_COMMA; + return angle::KeyType::COMMA; case XK_period: - return KEY_PERIOD; + return angle::KeyType::PERIOD; case XK_backslash: - return KEY_BACKSLASH; + return angle::KeyType::BACKSLASH; case XK_asciitilde: - return KEY_TILDE; + return angle::KeyType::TILDE; case XK_Escape: - return KEY_ESCAPE; + return angle::KeyType::ESCAPE; case XK_space: - return KEY_SPACE; + return angle::KeyType::SPACE; case XK_Return: - return KEY_RETURN; + return angle::KeyType::RETURN; case XK_BackSpace: - return KEY_BACK; + return angle::KeyType::BACK; case XK_Tab: - return KEY_TAB; + return angle::KeyType::TAB; case XK_Page_Up: - return KEY_PAGEUP; + return angle::KeyType::PAGEUP; case XK_Page_Down: - return KEY_PAGEDOWN; + return angle::KeyType::PAGEDOWN; case XK_End: - return KEY_END; + return angle::KeyType::END; case XK_Home: - return KEY_HOME; + return angle::KeyType::HOME; case XK_Insert: - return KEY_INSERT; + return angle::KeyType::INSERT; case XK_Delete: - return KEY_DELETE; + return angle::KeyType::DEL; case XK_KP_Add: - return KEY_ADD; + return angle::KeyType::ADD; case XK_KP_Subtract: - return KEY_SUBTRACT; + return angle::KeyType::SUBTRACT; case XK_KP_Multiply: - return KEY_MULTIPLY; + return angle::KeyType::MULTIPLY; case XK_KP_Divide: - return KEY_DIVIDE; + return angle::KeyType::DIVIDE; case XK_Pause: - return KEY_PAUSE; + return angle::KeyType::PAUSE; case XK_F1: - return KEY_F1; + return angle::KeyType::F1; case XK_F2: - return KEY_F2; + return angle::KeyType::F2; case XK_F3: - return KEY_F3; + return angle::KeyType::F3; case XK_F4: - return KEY_F4; + return angle::KeyType::F4; case XK_F5: - return KEY_F5; + return angle::KeyType::F5; case XK_F6: - return KEY_F6; + return angle::KeyType::F6; case XK_F7: - return KEY_F7; + return angle::KeyType::F7; case XK_F8: - return KEY_F8; + return angle::KeyType::F8; case XK_F9: - return KEY_F9; + return angle::KeyType::F9; case XK_F10: - return KEY_F10; + return angle::KeyType::F10; case XK_F11: - return KEY_F11; + return angle::KeyType::F11; case XK_F12: - return KEY_F12; + return angle::KeyType::F12; case XK_F13: - return KEY_F13; + return angle::KeyType::F13; case XK_F14: - return KEY_F14; + return angle::KeyType::F14; case XK_F15: - return KEY_F15; + return angle::KeyType::F15; case XK_Left: - return KEY_LEFT; + return angle::KeyType::LEFT; case XK_Right: - return KEY_RIGHT; + return angle::KeyType::RIGHT; case XK_Down: - return KEY_DOWN; + return angle::KeyType::DOWN; case XK_Up: - return KEY_UP; + return angle::KeyType::UP; case XK_KP_Insert: - return KEY_NUMPAD0; + return angle::KeyType::NUMPAD0; case XK_KP_End: - return KEY_NUMPAD1; + return angle::KeyType::NUMPAD1; case XK_KP_Down: - return KEY_NUMPAD2; + return angle::KeyType::NUMPAD2; case XK_KP_Page_Down: - return KEY_NUMPAD3; + return angle::KeyType::NUMPAD3; case XK_KP_Left: - return KEY_NUMPAD4; + return angle::KeyType::NUMPAD4; case XK_KP_5: - return KEY_NUMPAD5; + return angle::KeyType::NUMPAD5; case XK_KP_Right: - return KEY_NUMPAD6; + return angle::KeyType::NUMPAD6; case XK_KP_Home: - return KEY_NUMPAD7; + return angle::KeyType::NUMPAD7; case XK_KP_Up: - return KEY_NUMPAD8; + return angle::KeyType::NUMPAD8; case XK_KP_Page_Up: - return KEY_NUMPAD9; + return angle::KeyType::NUMPAD9; case XK_a: - return KEY_A; + return angle::KeyType::A; case XK_b: - return KEY_B; + return angle::KeyType::B; case XK_c: - return KEY_C; + return angle::KeyType::C; case XK_d: - return KEY_D; + return angle::KeyType::D; case XK_e: - return KEY_E; + return angle::KeyType::E; case XK_f: - return KEY_F; + return angle::KeyType::F; case XK_g: - return KEY_G; + return angle::KeyType::G; case XK_h: - return KEY_H; + return angle::KeyType::H; case XK_i: - return KEY_I; + return angle::KeyType::I; case XK_j: - return KEY_J; + return angle::KeyType::J; case XK_k: - return KEY_K; + return angle::KeyType::K; case XK_l: - return KEY_L; + return angle::KeyType::L; case XK_m: - return KEY_M; + return angle::KeyType::M; case XK_n: - return KEY_N; + return angle::KeyType::N; case XK_o: - return KEY_O; + return angle::KeyType::O; case XK_p: - return KEY_P; + return angle::KeyType::P; case XK_q: - return KEY_Q; + return angle::KeyType::Q; case XK_r: - return KEY_R; + return angle::KeyType::R; case XK_s: - return KEY_S; + return angle::KeyType::S; case XK_t: - return KEY_T; + return angle::KeyType::T; case XK_u: - return KEY_U; + return angle::KeyType::U; case XK_v: - return KEY_V; + return angle::KeyType::V; case XK_w: - return KEY_W; + return angle::KeyType::W; case XK_x: - return KEY_X; + return angle::KeyType::X; case XK_y: - return KEY_Y; + return angle::KeyType::Y; case XK_z: - return KEY_Z; + return angle::KeyType::Z; case XK_1: - return KEY_NUM1; + return angle::KeyType::NUM1; case XK_2: - return KEY_NUM2; + return angle::KeyType::NUM2; case XK_3: - return KEY_NUM3; + return angle::KeyType::NUM3; case XK_4: - return KEY_NUM4; + return angle::KeyType::NUM4; case XK_5: - return KEY_NUM5; + return angle::KeyType::NUM5; case XK_6: - return KEY_NUM6; + return angle::KeyType::NUM6; case XK_7: - return KEY_NUM7; + return angle::KeyType::NUM7; case XK_8: - return KEY_NUM8; + return angle::KeyType::NUM8; case XK_9: - return KEY_NUM9; + return angle::KeyType::NUM9; case XK_0: - return KEY_NUM0; + return angle::KeyType::NUM0; } - return Key(0); + return angle::KeyType(0); } static void AddX11KeyStateToEvent(Event *event, unsigned int state) @@ -549,6 +553,14 @@ void X11Window::setVisible(bool isVisible) XEvent placeholderEvent; XIfEvent(mDisplay, &placeholderEvent, WaitForMapNotify, reinterpret_cast(mWindow)); + + // Block until we get ConfigureNotify to set up fully before returning. + mConfigured = false; + while (!mConfigured) + { + messageLoop(); + angle::Sleep(10); + } } else { @@ -556,14 +568,6 @@ void X11Window::setVisible(bool isVisible) XFlush(mDisplay); } - // Block until we get ConfigureNotify to set up fully before returning. - mConfigured = false; - while (!mConfigured) - { - messageLoop(); - angle::Sleep(10); - } - mVisible = isVisible; } @@ -591,8 +595,8 @@ void X11Window::processEvent(const XEvent &xEvent) case ButtonPress: { Event event; - MouseButton button = MOUSEBUTTON_UNKNOWN; - int wheelY = 0; + angle::MouseButtonType button = angle::MouseButtonType::UNKNOWN; + int wheelY = 0; // The mouse wheel updates are sent via button events. switch (xEvent.xbutton.button) @@ -609,19 +613,19 @@ void X11Window::processEvent(const XEvent &xEvent) break; case Button1: - button = MOUSEBUTTON_LEFT; + button = angle::MouseButtonType::LEFT; break; case Button2: - button = MOUSEBUTTON_MIDDLE; + button = angle::MouseButtonType::MIDDLE; break; case Button3: - button = MOUSEBUTTON_RIGHT; + button = angle::MouseButtonType::RIGHT; break; case 8: - button = MOUSEBUTTON_BUTTON4; + button = angle::MouseButtonType::BUTTON4; break; case 9: - button = MOUSEBUTTON_BUTTON5; + button = angle::MouseButtonType::BUTTON5; break; default: @@ -635,7 +639,7 @@ void X11Window::processEvent(const XEvent &xEvent) pushEvent(event); } - if (button != MOUSEBUTTON_UNKNOWN) + if (button != angle::MouseButtonType::UNKNOWN) { event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; event.MouseButton.Button = button; @@ -649,31 +653,31 @@ void X11Window::processEvent(const XEvent &xEvent) case ButtonRelease: { Event event; - MouseButton button = MOUSEBUTTON_UNKNOWN; + angle::MouseButtonType button = angle::MouseButtonType::UNKNOWN; switch (xEvent.xbutton.button) { case Button1: - button = MOUSEBUTTON_LEFT; + button = angle::MouseButtonType::LEFT; break; case Button2: - button = MOUSEBUTTON_MIDDLE; + button = angle::MouseButtonType::MIDDLE; break; case Button3: - button = MOUSEBUTTON_RIGHT; + button = angle::MouseButtonType::RIGHT; break; case 8: - button = MOUSEBUTTON_BUTTON4; + button = angle::MouseButtonType::BUTTON4; break; case 9: - button = MOUSEBUTTON_BUTTON5; + button = angle::MouseButtonType::BUTTON5; break; default: break; } - if (button != MOUSEBUTTON_UNKNOWN) + if (button != angle::MouseButtonType::UNKNOWN) { event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; event.MouseButton.Button = button; diff --git a/util/mouse.h b/util/mouse.h index 444fd1a5133..1d519136bcd 100644 --- a/util/mouse.h +++ b/util/mouse.h @@ -7,15 +7,18 @@ #ifndef SAMPLE_UTIL_MOUSE_H #define SAMPLE_UTIL_MOUSE_H -enum MouseButton +namespace angle { - MOUSEBUTTON_UNKNOWN, - MOUSEBUTTON_LEFT, - MOUSEBUTTON_RIGHT, - MOUSEBUTTON_MIDDLE, - MOUSEBUTTON_BUTTON4, - MOUSEBUTTON_BUTTON5, - MOUSEBUTTON_COUNT, +enum class MouseButtonType +{ + UNKNOWN, + LEFT, + RIGHT, + MIDDLE, + BUTTON4, + BUTTON5, + COUNT, }; +} // namespace angle #endif // SAMPLE_UTIL_MOUSE_H diff --git a/util/osx/OSXWindow.mm b/util/osx/OSXWindow.mm index bc8fa77361d..c710c19828f 100644 --- a/util/osx/OSXWindow.mm +++ b/util/osx/OSXWindow.mm @@ -181,219 +181,219 @@ - (void)windowDidResignKey:(NSNotification *)notification } @end -static Key NSCodeToKey(int keyCode) +static angle::KeyType NSCodeToKey(int keyCode) { // Missing KEY_PAUSE switch (keyCode) { case kVK_Shift: - return KEY_LSHIFT; + return angle::KeyType::LSHIFT; case kVK_RightShift: - return KEY_RSHIFT; + return angle::KeyType::RSHIFT; case kVK_Option: - return KEY_LALT; + return angle::KeyType::LALT; case kVK_RightOption: - return KEY_RALT; + return angle::KeyType::RALT; case kVK_Control: - return KEY_LCONTROL; + return angle::KeyType::LCONTROL; case kVK_RightControl: - return KEY_RCONTROL; + return angle::KeyType::RCONTROL; case kVK_Command: - return KEY_LSYSTEM; + return angle::KeyType::LSYSTEM; // Right System doesn't have a name, but shows up as 0x36. case 0x36: - return KEY_RSYSTEM; + return angle::KeyType::RSYSTEM; case kVK_Function: - return KEY_MENU; + return angle::KeyType::MENU; case kVK_ANSI_Semicolon: - return KEY_SEMICOLON; + return angle::KeyType::SEMICOLON; case kVK_ANSI_Slash: - return KEY_SLASH; + return angle::KeyType::SLASH; case kVK_ANSI_Equal: - return KEY_EQUAL; + return angle::KeyType::EQUAL; case kVK_ANSI_Minus: - return KEY_DASH; + return angle::KeyType::DASH; case kVK_ANSI_LeftBracket: - return KEY_LBRACKET; + return angle::KeyType::LBRACKET; case kVK_ANSI_RightBracket: - return KEY_RBRACKET; + return angle::KeyType::RBRACKET; case kVK_ANSI_Comma: - return KEY_COMMA; + return angle::KeyType::COMMA; case kVK_ANSI_Period: - return KEY_PERIOD; + return angle::KeyType::PERIOD; case kVK_ANSI_Backslash: - return KEY_BACKSLASH; + return angle::KeyType::BACKSLASH; case kVK_ANSI_Grave: - return KEY_TILDE; + return angle::KeyType::TILDE; case kVK_Escape: - return KEY_ESCAPE; + return angle::KeyType::ESCAPE; case kVK_Space: - return KEY_SPACE; + return angle::KeyType::SPACE; case kVK_Return: - return KEY_RETURN; + return angle::KeyType::RETURN; case kVK_Delete: - return KEY_BACK; + return angle::KeyType::BACK; case kVK_Tab: - return KEY_TAB; + return angle::KeyType::TAB; case kVK_PageUp: - return KEY_PAGEUP; + return angle::KeyType::PAGEUP; case kVK_PageDown: - return KEY_PAGEDOWN; + return angle::KeyType::PAGEDOWN; case kVK_End: - return KEY_END; + return angle::KeyType::END; case kVK_Home: - return KEY_HOME; + return angle::KeyType::HOME; case kVK_Help: - return KEY_INSERT; + return angle::KeyType::INSERT; case kVK_ForwardDelete: - return KEY_DELETE; + return angle::KeyType::DEL; case kVK_ANSI_KeypadPlus: - return KEY_ADD; + return angle::KeyType::ADD; case kVK_ANSI_KeypadMinus: - return KEY_SUBTRACT; + return angle::KeyType::SUBTRACT; case kVK_ANSI_KeypadMultiply: - return KEY_MULTIPLY; + return angle::KeyType::MULTIPLY; case kVK_ANSI_KeypadDivide: - return KEY_DIVIDE; + return angle::KeyType::DIVIDE; case kVK_F1: - return KEY_F1; + return angle::KeyType::F1; case kVK_F2: - return KEY_F2; + return angle::KeyType::F2; case kVK_F3: - return KEY_F3; + return angle::KeyType::F3; case kVK_F4: - return KEY_F4; + return angle::KeyType::F4; case kVK_F5: - return KEY_F5; + return angle::KeyType::F5; case kVK_F6: - return KEY_F6; + return angle::KeyType::F6; case kVK_F7: - return KEY_F7; + return angle::KeyType::F7; case kVK_F8: - return KEY_F8; + return angle::KeyType::F8; case kVK_F9: - return KEY_F9; + return angle::KeyType::F9; case kVK_F10: - return KEY_F10; + return angle::KeyType::F10; case kVK_F11: - return KEY_F11; + return angle::KeyType::F11; case kVK_F12: - return KEY_F12; + return angle::KeyType::F12; case kVK_F13: - return KEY_F13; + return angle::KeyType::F13; case kVK_F14: - return KEY_F14; + return angle::KeyType::F14; case kVK_F15: - return KEY_F15; + return angle::KeyType::F15; case kVK_LeftArrow: - return KEY_LEFT; + return angle::KeyType::LEFT; case kVK_RightArrow: - return KEY_RIGHT; + return angle::KeyType::RIGHT; case kVK_DownArrow: - return KEY_DOWN; + return angle::KeyType::DOWN; case kVK_UpArrow: - return KEY_UP; + return angle::KeyType::UP; case kVK_ANSI_Keypad0: - return KEY_NUMPAD0; + return angle::KeyType::NUMPAD0; case kVK_ANSI_Keypad1: - return KEY_NUMPAD1; + return angle::KeyType::NUMPAD1; case kVK_ANSI_Keypad2: - return KEY_NUMPAD2; + return angle::KeyType::NUMPAD2; case kVK_ANSI_Keypad3: - return KEY_NUMPAD3; + return angle::KeyType::NUMPAD3; case kVK_ANSI_Keypad4: - return KEY_NUMPAD4; + return angle::KeyType::NUMPAD4; case kVK_ANSI_Keypad5: - return KEY_NUMPAD5; + return angle::KeyType::NUMPAD5; case kVK_ANSI_Keypad6: - return KEY_NUMPAD6; + return angle::KeyType::NUMPAD6; case kVK_ANSI_Keypad7: - return KEY_NUMPAD7; + return angle::KeyType::NUMPAD7; case kVK_ANSI_Keypad8: - return KEY_NUMPAD8; + return angle::KeyType::NUMPAD8; case kVK_ANSI_Keypad9: - return KEY_NUMPAD9; + return angle::KeyType::NUMPAD9; case kVK_ANSI_A: - return KEY_A; + return angle::KeyType::A; case kVK_ANSI_B: - return KEY_B; + return angle::KeyType::B; case kVK_ANSI_C: - return KEY_C; + return angle::KeyType::C; case kVK_ANSI_D: - return KEY_D; + return angle::KeyType::D; case kVK_ANSI_E: - return KEY_E; + return angle::KeyType::E; case kVK_ANSI_F: - return KEY_F; + return angle::KeyType::F; case kVK_ANSI_G: - return KEY_G; + return angle::KeyType::G; case kVK_ANSI_H: - return KEY_H; + return angle::KeyType::H; case kVK_ANSI_I: - return KEY_I; + return angle::KeyType::I; case kVK_ANSI_J: - return KEY_J; + return angle::KeyType::J; case kVK_ANSI_K: - return KEY_K; + return angle::KeyType::K; case kVK_ANSI_L: - return KEY_L; + return angle::KeyType::L; case kVK_ANSI_M: - return KEY_M; + return angle::KeyType::M; case kVK_ANSI_N: - return KEY_N; + return angle::KeyType::N; case kVK_ANSI_O: - return KEY_O; + return angle::KeyType::O; case kVK_ANSI_P: - return KEY_P; + return angle::KeyType::P; case kVK_ANSI_Q: - return KEY_Q; + return angle::KeyType::Q; case kVK_ANSI_R: - return KEY_R; + return angle::KeyType::R; case kVK_ANSI_S: - return KEY_S; + return angle::KeyType::S; case kVK_ANSI_T: - return KEY_T; + return angle::KeyType::T; case kVK_ANSI_U: - return KEY_U; + return angle::KeyType::U; case kVK_ANSI_V: - return KEY_V; + return angle::KeyType::V; case kVK_ANSI_W: - return KEY_W; + return angle::KeyType::W; case kVK_ANSI_X: - return KEY_X; + return angle::KeyType::X; case kVK_ANSI_Y: - return KEY_Y; + return angle::KeyType::Y; case kVK_ANSI_Z: - return KEY_Z; + return angle::KeyType::Z; case kVK_ANSI_1: - return KEY_NUM1; + return angle::KeyType::NUM1; case kVK_ANSI_2: - return KEY_NUM2; + return angle::KeyType::NUM2; case kVK_ANSI_3: - return KEY_NUM3; + return angle::KeyType::NUM3; case kVK_ANSI_4: - return KEY_NUM4; + return angle::KeyType::NUM4; case kVK_ANSI_5: - return KEY_NUM5; + return angle::KeyType::NUM5; case kVK_ANSI_6: - return KEY_NUM6; + return angle::KeyType::NUM6; case kVK_ANSI_7: - return KEY_NUM7; + return angle::KeyType::NUM7; case kVK_ANSI_8: - return KEY_NUM8; + return angle::KeyType::NUM8; case kVK_ANSI_9: - return KEY_NUM9; + return angle::KeyType::NUM9; case kVK_ANSI_0: - return KEY_NUM0; + return angle::KeyType::NUM0; } - return Key(0); + return angle::KeyType(0); } static void AddNSKeyStateToEvent(Event *event, NSEventModifierFlags state) @@ -404,18 +404,18 @@ static void AddNSKeyStateToEvent(Event *event, NSEventModifierFlags state) event->Key.System = state & NSCommandKeyMask; } -static MouseButton TranslateMouseButton(NSInteger button) +static angle::MouseButtonType TranslateMouseButton(NSInteger button) { switch (button) { case 2: - return MOUSEBUTTON_MIDDLE; + return angle::MouseButtonType::MIDDLE; case 3: - return MOUSEBUTTON_BUTTON4; + return angle::MouseButtonType::BUTTON4; case 4: - return MOUSEBUTTON_BUTTON5; + return angle::MouseButtonType::BUTTON5; default: - return MOUSEBUTTON_UNKNOWN; + return angle::MouseButtonType::UNKNOWN; } } @@ -486,7 +486,7 @@ - (float)translateMouseY:(float)y - (void)addButtonEvent:(NSEvent *)nsEvent type:(Event::EventType)eventType - button:(MouseButton)button + button:(angle::MouseButtonType)button { Event event; event.Type = eventType; @@ -498,7 +498,9 @@ - (void)addButtonEvent:(NSEvent *)nsEvent - (void)mouseDown:(NSEvent *)event { - [self addButtonEvent:event type:Event::EVENT_MOUSE_BUTTON_PRESSED button:MOUSEBUTTON_LEFT]; + [self addButtonEvent:event + type:Event::EVENT_MOUSE_BUTTON_PRESSED + button:angle::MouseButtonType::LEFT]; } - (void)mouseDragged:(NSEvent *)event @@ -508,7 +510,9 @@ - (void)mouseDragged:(NSEvent *)event - (void)mouseUp:(NSEvent *)event { - [self addButtonEvent:event type:Event::EVENT_MOUSE_BUTTON_RELEASED button:MOUSEBUTTON_LEFT]; + [self addButtonEvent:event + type:Event::EVENT_MOUSE_BUTTON_RELEASED + button:angle::MouseButtonType::LEFT]; } - (void)mouseMoved:(NSEvent *)nsEvent @@ -536,7 +540,9 @@ - (void)mouseExited:(NSEvent *)nsEvent - (void)rightMouseDown:(NSEvent *)event { - [self addButtonEvent:event type:Event::EVENT_MOUSE_BUTTON_PRESSED button:MOUSEBUTTON_RIGHT]; + [self addButtonEvent:event + type:Event::EVENT_MOUSE_BUTTON_PRESSED + button:angle::MouseButtonType::RIGHT]; } - (void)rightMouseDragged:(NSEvent *)event @@ -546,7 +552,9 @@ - (void)rightMouseDragged:(NSEvent *)event - (void)rightMouseUp:(NSEvent *)event { - [self addButtonEvent:event type:Event::EVENT_MOUSE_BUTTON_RELEASED button:MOUSEBUTTON_RIGHT]; + [self addButtonEvent:event + type:Event::EVENT_MOUSE_BUTTON_RELEASED + button:angle::MouseButtonType::RIGHT]; } - (void)otherMouseDown:(NSEvent *)event diff --git a/util/png_utils.cpp b/util/png_utils.cpp index 7ca1acc065a..608067c1940 100644 --- a/util/png_utils.cpp +++ b/util/png_utils.cpp @@ -6,6 +6,10 @@ // png_utils: Wrapper around libpng. // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "util/png_utils.h" #include diff --git a/util/posix/crash_handler_posix.cpp b/util/posix/crash_handler_posix.cpp index 440b049576c..3ac44d041c7 100644 --- a/util/posix/crash_handler_posix.cpp +++ b/util/posix/crash_handler_posix.cpp @@ -8,6 +8,10 @@ // https://github.com/google/skia/blob/master/tools/CrashHandler.cpp // +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/test_utils.h" #include "common/FixedVector.h" diff --git a/util/posix/test_utils_posix.cpp b/util/posix/test_utils_posix.cpp index 27c4440ed7e..92dfa30ef88 100644 --- a/util/posix/test_utils_posix.cpp +++ b/util/posix/test_utils_posix.cpp @@ -6,6 +6,10 @@ // test_utils_posix.cpp: Implementation of OS-specific functions for Posix systems +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/test_utils.h" #include @@ -75,6 +79,7 @@ enum class ReadResult GotData, }; +#if !defined(ANGLE_PLATFORM_APPLETV) ReadResult ReadFromFile(int fd, std::string *out) { constexpr size_t kBufSize = 2048; @@ -321,6 +326,7 @@ class PosixProcess : public Process int mExitCode = 0; pid_t mPID = -1; }; +#endif } // anonymous namespace void Sleep(unsigned int milliseconds) @@ -400,7 +406,11 @@ bool DeleteSystemFile(const char *path) Process *LaunchProcess(const std::vector &args, ProcessOutputCapture captureOutput) { +#if !defined(ANGLE_PLATFORM_APPLETV) return new PosixProcess(args, captureOutput); +#else + return nullptr; +#endif } int NumberOfProcessors() diff --git a/util/shader_utils.cpp b/util/shader_utils.cpp index aa4c557ea37..275e261a5cd 100644 --- a/util/shader_utils.cpp +++ b/util/shader_utils.cpp @@ -6,11 +6,13 @@ #include "util/shader_utils.h" +#include #include #include #include #include +#include "common/span.h" #include "common/utilities.h" #include "util/test_utils.h" @@ -246,17 +248,17 @@ GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages) GLuint GetProgramShader(GLuint program, GLint requestedType) { - static constexpr GLsizei kMaxShaderCount = 16; - GLuint attachedShaders[kMaxShaderCount] = {0u}; - GLsizei count = 0; - glGetAttachedShaders(program, kMaxShaderCount, &count, attachedShaders); - for (int i = 0; i < count; ++i) + GLsizei count = 0; + std::array attachedShaders = {}; + glGetAttachedShaders(program, attachedShaders.size(), &count, attachedShaders.data()); + + for (GLuint shader : angle::Span(attachedShaders).first(count)) { GLint type = 0; - glGetShaderiv(attachedShaders[i], GL_SHADER_TYPE, &type); + glGetShaderiv(shader, GL_SHADER_TYPE, &type); if (type == requestedType) { - return attachedShaders[i]; + return shader; } } diff --git a/util/test_utils.cpp b/util/test_utils.cpp index a2a20cca8bb..1f1bfce5a8e 100644 --- a/util/test_utils.cpp +++ b/util/test_utils.cpp @@ -6,6 +6,10 @@ // system_utils: Defines common utility functions +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/test_utils.h" #include @@ -14,6 +18,7 @@ #include #include #include +#include namespace angle { diff --git a/util/test_utils_unittest.cpp b/util/test_utils_unittest.cpp index 9b916ecabe4..995c9ad1646 100644 --- a/util/test_utils_unittest.cpp +++ b/util/test_utils_unittest.cpp @@ -125,6 +125,7 @@ TEST(TestUtils, MAYBE_RunApp) EXPECT_TRUE(setEnvDone); ProcessHandle process(LaunchProcess(args, ProcessOutputCapture::StdoutAndStderrSeparately)); + EXPECT_TRUE(process); EXPECT_TRUE(process->started()); EXPECT_TRUE(process->finish()); diff --git a/util/test_utils_unittest_helper.cpp b/util/test_utils_unittest_helper.cpp index fc859032c9b..7213779a3a1 100644 --- a/util/test_utils_unittest_helper.cpp +++ b/util/test_utils_unittest_helper.cpp @@ -5,6 +5,10 @@ // system_utils_unittest_helper.cpp: Helper to the SystemUtils.RunApp unittest +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "test_utils_unittest_helper.h" #include "../src/tests/test_utils/runner/TestSuite.h" diff --git a/util/util_gl.h b/util/util_gl.h index 09ead2f84c9..40cb654dd02 100644 --- a/util/util_gl.h +++ b/util/util_gl.h @@ -8,6 +8,10 @@ #ifndef UTIL_GL_H_ #define UTIL_GL_H_ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "common/platform.h" #if defined(ANGLE_USE_UTIL_LOADER) @@ -27,7 +31,9 @@ # include "angle_gl.h" #endif // defined(ANGLE_USE_UTIL_LOADER) +#include #include +#include namespace angle { @@ -37,5 +43,16 @@ inline bool CheckExtensionExists(const char *allExtensions, const std::string &e return paddedExtensions.find(std::string(" ") + extName + std::string(" ")) != std::string::npos; } + +inline std::pair GetCurrentContextVersion() +{ + const char *versionString = reinterpret_cast(glGetString(GL_VERSION)); + if ((versionString == nullptr) || std::strstr(versionString, "OpenGL ES") == nullptr) + { + return {0, 0}; + } + + return {versionString[10] - '0', versionString[12] - '0'}; +} } // namespace angle #endif // UTIL_GL_H_ diff --git a/util/windows/WGLWindow.cpp b/util/windows/WGLWindow.cpp index d9b76b2b4d0..62945ba88a4 100644 --- a/util/windows/WGLWindow.cpp +++ b/util/windows/WGLWindow.cpp @@ -260,7 +260,7 @@ HGLRC WGLWindow::createContext(const ConfigParameters &configParams, HGLRC share return context; } - if (mConfigParams.webGLCompatibility.valid() || mConfigParams.robustResourceInit.valid()) + if (mConfigParams.webGLCompatibility || mConfigParams.robustResourceInit) { std::cerr << "WGLWindow does not support the requested feature set." << std::endl; return context; diff --git a/util/windows/test_utils_win.cpp b/util/windows/test_utils_win.cpp index eae2c92a441..6fcb3a33309 100644 --- a/util/windows/test_utils_win.cpp +++ b/util/windows/test_utils_win.cpp @@ -6,6 +6,10 @@ // test_utils_win.cpp: Implementation of OS-specific functions for Windows +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/test_utils.h" #include @@ -278,6 +282,16 @@ class WindowsProcess : public Process bool finish() override { + if (!mStarted) + { + return false; + } + + if (mFinished) + { + return true; + } + if (mStdoutPipe.valid()) { ReadFromFile(true, mStdoutPipe.readHandle, &mStdout); @@ -289,14 +303,24 @@ class WindowsProcess : public Process } DWORD result = ::WaitForSingleObject(mProcessInfo.hProcess, INFINITE); + + mFinished = true; mTimer.stop(); + return result == WAIT_OBJECT_0; } bool finished() override { if (!mStarted) + { return false; + } + + if (mFinished) + { + return true; + } // Pipe stdin and stdout. if (mStdoutPipe.valid()) @@ -312,12 +336,14 @@ class WindowsProcess : public Process DWORD result = ::WaitForSingleObject(mProcessInfo.hProcess, 0); if (result == WAIT_OBJECT_0) { + mFinished = true; mTimer.stop(); return true; } if (result == WAIT_TIMEOUT) return false; + mFinished = true; mTimer.stop(); std::cerr << "Unexpected result from WaitForSingleObject: " << result << ". Last error: " << ::GetLastError() << "\n"; @@ -342,7 +368,14 @@ class WindowsProcess : public Process bool kill() override { if (!mStarted) + { + return false; + } + + if (mFinished) + { return true; + } HANDLE newHandle; if (::DuplicateHandle(::GetCurrentProcess(), mProcessInfo.hProcess, ::GetCurrentProcess(), @@ -369,13 +402,14 @@ class WindowsProcess : public Process return false; } - mStarted = false; + mFinished = true; mTimer.stop(); return true; } private: - bool mStarted = false; + bool mStarted = false; + bool mFinished = false; ScopedPipe mStdoutPipe; ScopedPipe mStderrPipe; PROCESS_INFORMATION mProcessInfo = {}; diff --git a/util/windows/third_party/StackWalker/README.chromium b/util/windows/third_party/StackWalker/README.chromium index 0ede764d515..1d7371554f1 100644 --- a/util/windows/third_party/StackWalker/README.chromium +++ b/util/windows/third_party/StackWalker/README.chromium @@ -2,6 +2,7 @@ Name: StackWalker URL: https://github.com/JochenKalmbach/StackWalker Version: N/A Revision: 42e7a6e056a9e7aca911a7e9e54e2e4f90bc2652 +Update Mechanism: Static (https://crbug.com/422917292) License: BSD-3-Clause License File: LICENSE Security Critical: no diff --git a/util/windows/third_party/StackWalker/src/StackWalker.cpp b/util/windows/third_party/StackWalker/src/StackWalker.cpp index cfa0d0e04fc..679a7f45d98 100644 --- a/util/windows/third_party/StackWalker/src/StackWalker.cpp +++ b/util/windows/third_party/StackWalker/src/StackWalker.cpp @@ -82,6 +82,10 @@ * **********************************************************************/ +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "StackWalker.h" #include diff --git a/util/windows/wgl_loader_autogen.h b/util/windows/wgl_loader_autogen.h index 211562bb4f6..f399fb81c70 100644 --- a/util/windows/wgl_loader_autogen.h +++ b/util/windows/wgl_loader_autogen.h @@ -94,7 +94,7 @@ typedef GenericProc(KHRONOS_APIENTRY *LoadProc)(const char *); void LoadWGL(LoadProc loadProc); #if defined(__cplusplus) -} // extern "C" +} // extern "C" #endif // defined(__cplusplus) #endif // UTIL_WINDOWS_WGL_LOADER_AUTOGEN_H_ diff --git a/util/windows/win32/Win32Pixmap.cpp b/util/windows/win32/Win32Pixmap.cpp index ccfec113213..60a613e3f04 100644 --- a/util/windows/win32/Win32Pixmap.cpp +++ b/util/windows/win32/Win32Pixmap.cpp @@ -6,6 +6,10 @@ // Win32Pixmap.cpp: Implementation of OSPixmap for Win32 (Windows) +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_libc_calls +#endif + #include "util/windows/win32/Win32Pixmap.h" Win32Pixmap::Win32Pixmap() : mBitmap(nullptr) {} diff --git a/util/windows/win32/Win32Window.cpp b/util/windows/win32/Win32Window.cpp index 677602a7289..85465c4310b 100644 --- a/util/windows/win32/Win32Window.cpp +++ b/util/windows/win32/Win32Window.cpp @@ -13,7 +13,7 @@ #include "common/debug.h" -Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags) +angle::KeyType VirtualKeyCodeToKey(WPARAM key, LPARAM flags) { switch (key) { @@ -22,211 +22,212 @@ Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags) { static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC); unsigned int scancode = static_cast((flags & (0xFF << 16)) >> 16); - return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT; + return scancode == lShift ? angle::KeyType::LSHIFT : angle::KeyType::RSHIFT; } // Check the "extended" flag to distinguish between left and right alt case VK_MENU: - return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT; + return (HIWORD(flags) & KF_EXTENDED) ? angle::KeyType::RALT : angle::KeyType::LALT; // Check the "extended" flag to distinguish between left and right control case VK_CONTROL: - return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL; + return (HIWORD(flags) & KF_EXTENDED) ? angle::KeyType::RCONTROL + : angle::KeyType::LCONTROL; // Other keys are reported properly case VK_LWIN: - return KEY_LSYSTEM; + return angle::KeyType::LSYSTEM; case VK_RWIN: - return KEY_RSYSTEM; + return angle::KeyType::RSYSTEM; case VK_APPS: - return KEY_MENU; + return angle::KeyType::MENU; case VK_OEM_1: - return KEY_SEMICOLON; + return angle::KeyType::SEMICOLON; case VK_OEM_2: - return KEY_SLASH; + return angle::KeyType::SLASH; case VK_OEM_PLUS: - return KEY_EQUAL; + return angle::KeyType::EQUAL; case VK_OEM_MINUS: - return KEY_DASH; + return angle::KeyType::DASH; case VK_OEM_4: - return KEY_LBRACKET; + return angle::KeyType::LBRACKET; case VK_OEM_6: - return KEY_RBRACKET; + return angle::KeyType::RBRACKET; case VK_OEM_COMMA: - return KEY_COMMA; + return angle::KeyType::COMMA; case VK_OEM_PERIOD: - return KEY_PERIOD; + return angle::KeyType::PERIOD; case VK_OEM_7: - return KEY_QUOTE; + return angle::KeyType::QUOTE; case VK_OEM_5: - return KEY_BACKSLASH; + return angle::KeyType::BACKSLASH; case VK_OEM_3: - return KEY_TILDE; + return angle::KeyType::TILDE; case VK_ESCAPE: - return KEY_ESCAPE; + return angle::KeyType::ESCAPE; case VK_SPACE: - return KEY_SPACE; + return angle::KeyType::SPACE; case VK_RETURN: - return KEY_RETURN; + return angle::KeyType::RETURN; case VK_BACK: - return KEY_BACK; + return angle::KeyType::BACK; case VK_TAB: - return KEY_TAB; + return angle::KeyType::TAB; case VK_PRIOR: - return KEY_PAGEUP; + return angle::KeyType::PAGEUP; case VK_NEXT: - return KEY_PAGEDOWN; + return angle::KeyType::PAGEDOWN; case VK_END: - return KEY_END; + return angle::KeyType::END; case VK_HOME: - return KEY_HOME; + return angle::KeyType::HOME; case VK_INSERT: - return KEY_INSERT; + return angle::KeyType::INSERT; case VK_DELETE: - return KEY_DELETE; + return angle::KeyType::DEL; case VK_ADD: - return KEY_ADD; + return angle::KeyType::ADD; case VK_SUBTRACT: - return KEY_SUBTRACT; + return angle::KeyType::SUBTRACT; case VK_MULTIPLY: - return KEY_MULTIPLY; + return angle::KeyType::MULTIPLY; case VK_DIVIDE: - return KEY_DIVIDE; + return angle::KeyType::DIVIDE; case VK_PAUSE: - return KEY_PAUSE; + return angle::KeyType::PAUSE; case VK_F1: - return KEY_F1; + return angle::KeyType::F1; case VK_F2: - return KEY_F2; + return angle::KeyType::F2; case VK_F3: - return KEY_F3; + return angle::KeyType::F3; case VK_F4: - return KEY_F4; + return angle::KeyType::F4; case VK_F5: - return KEY_F5; + return angle::KeyType::F5; case VK_F6: - return KEY_F6; + return angle::KeyType::F6; case VK_F7: - return KEY_F7; + return angle::KeyType::F7; case VK_F8: - return KEY_F8; + return angle::KeyType::F8; case VK_F9: - return KEY_F9; + return angle::KeyType::F9; case VK_F10: - return KEY_F10; + return angle::KeyType::F10; case VK_F11: - return KEY_F11; + return angle::KeyType::F11; case VK_F12: - return KEY_F12; + return angle::KeyType::F12; case VK_F13: - return KEY_F13; + return angle::KeyType::F13; case VK_F14: - return KEY_F14; + return angle::KeyType::F14; case VK_F15: - return KEY_F15; + return angle::KeyType::F15; case VK_LEFT: - return KEY_LEFT; + return angle::KeyType::LEFT; case VK_RIGHT: - return KEY_RIGHT; + return angle::KeyType::RIGHT; case VK_UP: - return KEY_UP; + return angle::KeyType::UP; case VK_DOWN: - return KEY_DOWN; + return angle::KeyType::DOWN; case VK_NUMPAD0: - return KEY_NUMPAD0; + return angle::KeyType::NUMPAD0; case VK_NUMPAD1: - return KEY_NUMPAD1; + return angle::KeyType::NUMPAD1; case VK_NUMPAD2: - return KEY_NUMPAD2; + return angle::KeyType::NUMPAD2; case VK_NUMPAD3: - return KEY_NUMPAD3; + return angle::KeyType::NUMPAD3; case VK_NUMPAD4: - return KEY_NUMPAD4; + return angle::KeyType::NUMPAD4; case VK_NUMPAD5: - return KEY_NUMPAD5; + return angle::KeyType::NUMPAD5; case VK_NUMPAD6: - return KEY_NUMPAD6; + return angle::KeyType::NUMPAD6; case VK_NUMPAD7: - return KEY_NUMPAD7; + return angle::KeyType::NUMPAD7; case VK_NUMPAD8: - return KEY_NUMPAD8; + return angle::KeyType::NUMPAD8; case VK_NUMPAD9: - return KEY_NUMPAD9; + return angle::KeyType::NUMPAD9; case 'A': - return KEY_A; + return angle::KeyType::A; case 'Z': - return KEY_Z; + return angle::KeyType::Z; case 'E': - return KEY_E; + return angle::KeyType::E; case 'R': - return KEY_R; + return angle::KeyType::R; case 'T': - return KEY_T; + return angle::KeyType::T; case 'Y': - return KEY_Y; + return angle::KeyType::Y; case 'U': - return KEY_U; + return angle::KeyType::U; case 'I': - return KEY_I; + return angle::KeyType::I; case 'O': - return KEY_O; + return angle::KeyType::O; case 'P': - return KEY_P; + return angle::KeyType::P; case 'Q': - return KEY_Q; + return angle::KeyType::Q; case 'S': - return KEY_S; + return angle::KeyType::S; case 'D': - return KEY_D; + return angle::KeyType::D; case 'F': - return KEY_F; + return angle::KeyType::F; case 'G': - return KEY_G; + return angle::KeyType::G; case 'H': - return KEY_H; + return angle::KeyType::H; case 'J': - return KEY_J; + return angle::KeyType::J; case 'K': - return KEY_K; + return angle::KeyType::K; case 'L': - return KEY_L; + return angle::KeyType::L; case 'M': - return KEY_M; + return angle::KeyType::M; case 'W': - return KEY_W; + return angle::KeyType::W; case 'X': - return KEY_X; + return angle::KeyType::X; case 'C': - return KEY_C; + return angle::KeyType::C; case 'V': - return KEY_V; + return angle::KeyType::V; case 'B': - return KEY_B; + return angle::KeyType::B; case 'N': - return KEY_N; + return angle::KeyType::N; case '0': - return KEY_NUM0; + return angle::KeyType::NUM0; case '1': - return KEY_NUM1; + return angle::KeyType::NUM1; case '2': - return KEY_NUM2; + return angle::KeyType::NUM2; case '3': - return KEY_NUM3; + return angle::KeyType::NUM3; case '4': - return KEY_NUM4; + return angle::KeyType::NUM4; case '5': - return KEY_NUM5; + return angle::KeyType::NUM5; case '6': - return KEY_NUM6; + return angle::KeyType::NUM6; case '7': - return KEY_NUM7; + return angle::KeyType::NUM7; case '8': - return KEY_NUM8; + return angle::KeyType::NUM8; case '9': - return KEY_NUM9; + return angle::KeyType::NUM9; } - return Key(0); + return angle::KeyType(0); } LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -352,7 +353,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP { Event event; event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; - event.MouseButton.Button = MOUSEBUTTON_LEFT; + event.MouseButton.Button = angle::MouseButtonType::LEFT; event.MouseButton.X = static_cast(LOWORD(lParam)); event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); @@ -363,7 +364,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP { Event event; event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; - event.MouseButton.Button = MOUSEBUTTON_LEFT; + event.MouseButton.Button = angle::MouseButtonType::LEFT; event.MouseButton.X = static_cast(LOWORD(lParam)); event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); @@ -375,7 +376,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP { Event event; event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; - event.MouseButton.Button = MOUSEBUTTON_RIGHT; + event.MouseButton.Button = angle::MouseButtonType::RIGHT; event.MouseButton.X = static_cast(LOWORD(lParam)); event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); @@ -387,7 +388,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP { Event event; event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; - event.MouseButton.Button = MOUSEBUTTON_RIGHT; + event.MouseButton.Button = angle::MouseButtonType::RIGHT; event.MouseButton.X = static_cast(LOWORD(lParam)); event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); @@ -400,7 +401,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP { Event event; event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; - event.MouseButton.Button = MOUSEBUTTON_MIDDLE; + event.MouseButton.Button = angle::MouseButtonType::MIDDLE; event.MouseButton.X = static_cast(LOWORD(lParam)); event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); @@ -412,7 +413,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP { Event event; event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; - event.MouseButton.Button = MOUSEBUTTON_MIDDLE; + event.MouseButton.Button = angle::MouseButtonType::MIDDLE; event.MouseButton.X = static_cast(LOWORD(lParam)); event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); @@ -424,11 +425,12 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP case WM_XBUTTONDBLCLK: { Event event; - event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; - event.MouseButton.Button = - (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5; - event.MouseButton.X = static_cast(LOWORD(lParam)); - event.MouseButton.Y = static_cast(HIWORD(lParam)); + event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; + event.MouseButton.Button = (HIWORD(wParam) == XBUTTON1) + ? angle::MouseButtonType::BUTTON4 + : angle::MouseButtonType::BUTTON5; + event.MouseButton.X = static_cast(LOWORD(lParam)); + event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); break; } @@ -437,11 +439,12 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP case WM_XBUTTONUP: { Event event; - event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; - event.MouseButton.Button = - (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5; - event.MouseButton.X = static_cast(LOWORD(lParam)); - event.MouseButton.Y = static_cast(HIWORD(lParam)); + event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; + event.MouseButton.Button = (HIWORD(wParam) == XBUTTON1) + ? angle::MouseButtonType::BUTTON4 + : angle::MouseButtonType::BUTTON5; + event.MouseButton.X = static_cast(LOWORD(lParam)); + event.MouseButton.Y = static_cast(HIWORD(lParam)); window->pushEvent(event); break; } @@ -818,8 +821,7 @@ void Win32Window::setVisible(bool isVisible) if (isVisible) { - mSetVisibleTimer.stop(); - mSetVisibleTimer.start(); + mSetVisibleTimer.restart(); } } diff --git a/util/windows/win32/test_utils_win32.cpp b/util/windows/win32/test_utils_win32.cpp index fc1003efc19..9df48efb1d0 100644 --- a/util/windows/win32/test_utils_win32.cpp +++ b/util/windows/win32/test_utils_win32.cpp @@ -6,6 +6,10 @@ // test_utils_win32.cpp: Implementation of OS-specific functions for Win32 (Windows) +#ifdef UNSAFE_BUFFERS_BUILD +# pragma allow_unsafe_buffers +#endif + #include "util/test_utils.h" #include